wined3d: Validate (2D) texture dimensions in texture_init().
[wine.git] / dlls / user32 / tests / clipboard.c
blobbe6c9bfb326aa05353f7d17c5702438873ea50b3
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 BOOL (WINAPI *pAddClipboardFormatListener)(HWND hwnd);
28 static DWORD (WINAPI *pGetClipboardSequenceNumber)(void);
30 static int thread_from_line;
32 static DWORD WINAPI open_clipboard_thread(LPVOID arg)
34 HWND hWnd = arg;
35 ok(OpenClipboard(hWnd), "%u: OpenClipboard failed\n", thread_from_line);
36 return 0;
39 static DWORD WINAPI empty_clipboard_thread(LPVOID arg)
41 SetLastError( 0xdeadbeef );
42 ok(!EmptyClipboard(), "%u: EmptyClipboard succeeded\n", thread_from_line );
43 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
44 thread_from_line, GetLastError());
45 return 0;
48 static DWORD WINAPI open_and_empty_clipboard_thread(LPVOID arg)
50 HWND hWnd = arg;
51 ok(OpenClipboard(hWnd), "%u: OpenClipboard failed\n", thread_from_line);
52 ok(EmptyClipboard(), "%u: EmptyClipboard failed\n", thread_from_line );
53 return 0;
56 static DWORD WINAPI set_clipboard_data_thread(LPVOID arg)
58 HWND hwnd = arg;
59 HANDLE ret;
61 SetLastError( 0xdeadbeef );
62 if (GetClipboardOwner() == hwnd)
64 SetClipboardData( CF_WAVE, 0 );
65 todo_wine ok( IsClipboardFormatAvailable( CF_WAVE ), "%u: SetClipboardData failed\n", thread_from_line );
66 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
67 ok( ret != 0, "%u: SetClipboardData failed err %u\n", thread_from_line, GetLastError() );
69 else
71 SetClipboardData( CF_WAVE, 0 );
72 todo_wine ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
73 thread_from_line, GetLastError());
74 ok( !IsClipboardFormatAvailable( CF_WAVE ), "%u: SetClipboardData succeeded\n", thread_from_line );
75 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
76 todo_wine ok( !ret, "%u: SetClipboardData succeeded\n", thread_from_line );
77 todo_wine ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
78 thread_from_line, GetLastError());
80 return 0;
83 static void run_thread( LPTHREAD_START_ROUTINE func, void *arg, int line )
85 DWORD ret;
86 HANDLE thread;
88 thread_from_line = line;
89 thread = CreateThread(NULL, 0, func, arg, 0, NULL);
90 ok(thread != NULL, "%u: CreateThread failed with error %d\n", line, GetLastError());
91 for (;;)
93 ret = MsgWaitForMultipleObjectsEx( 1, &thread, 1000, QS_ALLINPUT, 0 );
94 if (ret == WAIT_OBJECT_0 + 1)
96 MSG msg;
97 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
99 else break;
101 ok(ret == WAIT_OBJECT_0, "%u: expected WAIT_OBJECT_0, got %u\n", line, ret);
102 CloseHandle(thread);
105 static void test_ClipboardOwner(void)
107 HWND hWnd1, hWnd2;
108 BOOL ret;
110 SetLastError(0xdeadbeef);
111 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef,
112 "could not perform clipboard test: clipboard already owned\n");
114 hWnd1 = CreateWindowExA(0, "static", NULL, WS_POPUP,
115 0, 0, 10, 10, 0, 0, 0, NULL);
116 ok(hWnd1 != 0, "CreateWindowExA error %d\n", GetLastError());
117 trace("hWnd1 = %p\n", hWnd1);
119 hWnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP,
120 0, 0, 10, 10, 0, 0, 0, NULL);
121 ok(hWnd2 != 0, "CreateWindowExA error %d\n", GetLastError());
122 trace("hWnd2 = %p\n", hWnd2);
124 SetLastError(0xdeadbeef);
125 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
126 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */
127 "wrong error %u\n", GetLastError());
129 ok(OpenClipboard(0), "OpenClipboard failed\n");
130 ok(!GetClipboardOwner(), "clipboard should still be not owned\n");
131 ok(!OpenClipboard(hWnd1), "OpenClipboard should fail since clipboard already opened\n");
132 ok(OpenClipboard(0), "OpenClipboard again failed\n");
133 ret = CloseClipboard();
134 ok( ret, "CloseClipboard error %d\n", GetLastError());
136 ok(OpenClipboard(hWnd1), "OpenClipboard failed\n");
137 run_thread( open_clipboard_thread, hWnd1, __LINE__ );
138 run_thread( empty_clipboard_thread, 0, __LINE__ );
139 run_thread( set_clipboard_data_thread, hWnd1, __LINE__ );
140 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
141 ok(OpenClipboard(hWnd1), "OpenClipboard failed\n");
143 SetLastError(0xdeadbeef);
144 ret = OpenClipboard(hWnd2);
145 ok(!ret && (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED),
146 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
148 SetLastError(0xdeadbeef);
149 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should still be not owned\n");
150 ret = EmptyClipboard();
151 ok( ret, "EmptyClipboard error %d\n", GetLastError());
152 ok(GetClipboardOwner() == hWnd1, "clipboard should be owned by %p, not by %p\n", hWnd1, GetClipboardOwner());
153 run_thread( empty_clipboard_thread, 0, __LINE__ );
154 run_thread( set_clipboard_data_thread, hWnd1, __LINE__ );
156 SetLastError(0xdeadbeef);
157 ret = OpenClipboard(hWnd2);
158 ok(!ret && (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED),
159 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
161 ret = CloseClipboard();
162 ok( ret, "CloseClipboard error %d\n", GetLastError());
163 ok(GetClipboardOwner() == hWnd1, "clipboard should still be owned\n");
165 /* any window will do, even from a different process */
166 ret = OpenClipboard( GetDesktopWindow() );
167 ok( ret, "OpenClipboard error %d\n", GetLastError());
168 ret = EmptyClipboard();
169 ok( ret, "EmptyClipboard error %d\n", GetLastError());
170 ok( GetClipboardOwner() == GetDesktopWindow(), "wrong owner %p/%p\n",
171 GetClipboardOwner(), GetDesktopWindow() );
172 run_thread( set_clipboard_data_thread, GetDesktopWindow(), __LINE__ );
173 ret = CloseClipboard();
174 ok( ret, "CloseClipboard error %d\n", GetLastError());
176 ret = OpenClipboard( hWnd1 );
177 ok( ret, "OpenClipboard error %d\n", GetLastError());
178 ret = EmptyClipboard();
179 ok( ret, "EmptyClipboard error %d\n", GetLastError());
180 ok( GetClipboardOwner() == hWnd1, "wrong owner %p/%p\n", GetClipboardOwner(), hWnd1 );
181 ret = CloseClipboard();
182 ok( ret, "CloseClipboard error %d\n", GetLastError());
184 ret = DestroyWindow(hWnd1);
185 ok( ret, "DestroyWindow error %d\n", GetLastError());
186 ret = DestroyWindow(hWnd2);
187 ok( ret, "DestroyWindow error %d\n", GetLastError());
188 SetLastError(0xdeadbeef);
189 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should not be owned\n");
191 ret = OpenClipboard( 0 );
192 ok( ret, "OpenClipboard error %d\n", GetLastError());
193 run_thread( set_clipboard_data_thread, 0, __LINE__ );
194 ret = CloseClipboard();
195 ok( ret, "CloseClipboard error %d\n", GetLastError());
197 run_thread( open_and_empty_clipboard_thread, 0, __LINE__ );
199 ret = OpenClipboard( 0 );
200 ok( ret, "OpenClipboard error %d\n", GetLastError());
201 run_thread( set_clipboard_data_thread, 0, __LINE__ );
202 ret = EmptyClipboard();
203 ok( ret, "EmptyClipboard error %d\n", GetLastError());
204 ret = CloseClipboard();
205 ok( ret, "CloseClipboard error %d\n", GetLastError());
207 SetLastError( 0xdeadbeef );
208 todo_wine ok( !SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 )),
209 "SetClipboardData succeeded\n" );
210 todo_wine ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError() );
211 todo_wine ok( !IsClipboardFormatAvailable( CF_WAVE ), "SetClipboardData succeeded\n" );
215 static void test_RegisterClipboardFormatA(void)
217 ATOM atom_id;
218 UINT format_id, format_id2;
219 char buf[256];
220 int len;
221 BOOL ret;
222 HANDLE handle;
224 format_id = RegisterClipboardFormatA("my_cool_clipboard_format");
225 ok(format_id > 0xc000 && format_id < 0xffff, "invalid clipboard format id %04x\n", format_id);
227 format_id2 = RegisterClipboardFormatA("MY_COOL_CLIPBOARD_FORMAT");
228 ok(format_id2 == format_id, "invalid clipboard format id %04x\n", format_id2);
230 len = GetClipboardFormatNameA(format_id, buf, 256);
231 ok(len == lstrlenA("my_cool_clipboard_format"), "wrong format name length %d\n", len);
232 ok(!lstrcmpA(buf, "my_cool_clipboard_format"), "wrong format name \"%s\"\n", buf);
234 lstrcpyA(buf, "foo");
235 SetLastError(0xdeadbeef);
236 len = GetAtomNameA((ATOM)format_id, buf, 256);
237 ok(len == 0, "GetAtomNameA should fail\n");
238 ok(GetLastError() == ERROR_INVALID_HANDLE, "err %d\n", GetLastError());
240 todo_wine
242 lstrcpyA(buf, "foo");
243 SetLastError(0xdeadbeef);
244 len = GlobalGetAtomNameA((ATOM)format_id, buf, 256);
245 ok(len == 0, "GlobalGetAtomNameA should fail\n");
246 ok(GetLastError() == ERROR_INVALID_HANDLE, "err %d\n", GetLastError());
249 SetLastError(0xdeadbeef);
250 atom_id = FindAtomA("my_cool_clipboard_format");
251 ok(atom_id == 0, "FindAtomA should fail\n");
252 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError());
254 if (0)
256 /* this relies on the clipboard and global atom table being different */
257 SetLastError(0xdeadbeef);
258 atom_id = GlobalFindAtomA("my_cool_clipboard_format");
259 ok(atom_id == 0, "GlobalFindAtomA should fail\n");
260 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError());
263 for (format_id = 0; format_id < 0xffff; format_id++)
265 SetLastError(0xdeadbeef);
266 len = GetClipboardFormatNameA(format_id, buf, 256);
268 if (format_id < 0xc000)
269 ok(!len, "GetClipboardFormatNameA should fail, but it returned %d (%s)\n", len, buf);
270 else if (len && winetest_debug > 1)
271 trace("%04x: %s\n", format_id, len ? buf : "");
274 ret = OpenClipboard(0);
275 ok( ret, "OpenClipboard error %d\n", GetLastError());
277 /* try some invalid/unregistered formats */
278 SetLastError( 0xdeadbeef );
279 handle = SetClipboardData( 0, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
280 ok( !handle, "SetClipboardData succeeded\n" );
281 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError());
282 handle = SetClipboardData( 0x1234, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
283 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
284 handle = SetClipboardData( 0x123456, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
285 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
286 handle = SetClipboardData( 0xffff8765, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
287 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
289 ok( IsClipboardFormatAvailable( 0x1234 ), "format missing\n" );
290 ok( IsClipboardFormatAvailable( 0x123456 ), "format missing\n" );
291 ok( IsClipboardFormatAvailable( 0xffff8765 ), "format missing\n" );
292 ok( !IsClipboardFormatAvailable( 0 ), "format available\n" );
293 ok( !IsClipboardFormatAvailable( 0x3456 ), "format available\n" );
294 ok( !IsClipboardFormatAvailable( 0x8765 ), "format available\n" );
296 trace("# of formats available: %d\n", CountClipboardFormats());
298 format_id = 0;
299 while ((format_id = EnumClipboardFormats(format_id)))
301 ok(IsClipboardFormatAvailable(format_id), "format %04x was listed as available\n", format_id);
302 len = GetClipboardFormatNameA(format_id, buf, 256);
303 trace("%04x: %s\n", format_id, len ? buf : "");
306 ret = EmptyClipboard();
307 ok( ret, "EmptyClipboard error %d\n", GetLastError());
308 ret =CloseClipboard();
309 ok( ret, "CloseClipboard error %d\n", GetLastError());
311 if (CountClipboardFormats())
313 SetLastError(0xdeadbeef);
314 ok(!EnumClipboardFormats(0), "EnumClipboardFormats should fail if clipboard wasn't open\n");
315 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN,
316 "Last error should be set to ERROR_CLIPBOARD_NOT_OPEN, not %d\n", GetLastError());
319 SetLastError(0xdeadbeef);
320 ok(!EmptyClipboard(), "EmptyClipboard should fail if clipboard wasn't open\n");
321 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */
322 "Wrong error %u\n", GetLastError());
324 format_id = RegisterClipboardFormatA("#1234");
325 ok(format_id == 1234, "invalid clipboard format id %04x\n", format_id);
328 static HGLOBAL create_text(void)
330 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 5);
331 char *p = GlobalLock(h);
332 strcpy(p, "test");
333 GlobalUnlock(h);
334 return h;
337 static HENHMETAFILE create_emf(void)
339 const RECT rect = {0, 0, 100, 100};
340 HDC hdc = CreateEnhMetaFileA(NULL, NULL, &rect, "HENHMETAFILE Ole Clipboard Test\0Test\0\0");
341 ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
342 return CloseEnhMetaFile(hdc);
345 static void test_synthesized(void)
347 HGLOBAL h, htext;
348 HENHMETAFILE emf;
349 BOOL r;
350 UINT cf;
351 HANDLE data;
353 htext = create_text();
354 emf = create_emf();
356 r = OpenClipboard(NULL);
357 ok(r, "gle %d\n", GetLastError());
358 r = EmptyClipboard();
359 ok(r, "gle %d\n", GetLastError());
360 h = SetClipboardData(CF_TEXT, htext);
361 ok(h == htext, "got %p\n", h);
362 h = SetClipboardData(CF_ENHMETAFILE, emf);
363 ok(h == emf, "got %p\n", h);
364 r = CloseClipboard();
365 ok(r, "gle %d\n", GetLastError());
367 r = OpenClipboard(NULL);
368 ok(r, "gle %d\n", GetLastError());
369 cf = EnumClipboardFormats(0);
370 ok(cf == CF_TEXT, "cf %08x\n", cf);
371 data = GetClipboardData(cf);
372 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
374 cf = EnumClipboardFormats(cf);
375 ok(cf == CF_ENHMETAFILE, "cf %08x\n", cf);
376 data = GetClipboardData(cf);
377 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
379 cf = EnumClipboardFormats(cf);
380 todo_wine ok(cf == CF_LOCALE, "cf %08x\n", cf);
381 if(cf == CF_LOCALE)
382 cf = EnumClipboardFormats(cf);
383 ok(cf == CF_OEMTEXT, "cf %08x\n", cf);
384 data = GetClipboardData(cf);
385 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
387 cf = EnumClipboardFormats(cf);
388 ok(cf == CF_UNICODETEXT, "cf %08x\n", cf);
390 cf = EnumClipboardFormats(cf);
391 ok(cf == CF_METAFILEPICT, "cf %08x\n", cf);
392 data = GetClipboardData(cf);
393 todo_wine ok(data != NULL, "couldn't get data, cf %08x\n", cf);
395 cf = EnumClipboardFormats(cf);
396 ok(cf == 0, "cf %08x\n", cf);
398 r = EmptyClipboard();
399 ok(r, "gle %d\n", GetLastError());
401 r = CloseClipboard();
402 ok(r, "gle %d\n", GetLastError());
405 static CRITICAL_SECTION clipboard_cs;
406 static HWND next_wnd;
407 static LRESULT CALLBACK clipboard_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
409 static UINT wm_drawclipboard;
410 static UINT wm_clipboardupdate;
411 static UINT wm_destroyclipboard;
412 LRESULT ret;
414 switch(msg) {
415 case WM_DRAWCLIPBOARD:
416 EnterCriticalSection(&clipboard_cs);
417 wm_drawclipboard++;
418 LeaveCriticalSection(&clipboard_cs);
419 break;
420 case WM_CHANGECBCHAIN:
421 if (next_wnd == (HWND)wp)
422 next_wnd = (HWND)lp;
423 else if (next_wnd)
424 SendMessageA(next_wnd, msg, wp, lp);
425 break;
426 case WM_DESTROYCLIPBOARD:
427 wm_destroyclipboard++;
428 ok( GetClipboardOwner() == hwnd, "WM_DESTROYCLIPBOARD owner %p\n", GetClipboardOwner() );
429 break;
430 case WM_CLIPBOARDUPDATE:
431 wm_clipboardupdate++;
432 break;
433 case WM_USER:
434 ChangeClipboardChain(hwnd, next_wnd);
435 PostQuitMessage(0);
436 break;
437 case WM_USER+1:
438 ret = wm_drawclipboard;
439 wm_drawclipboard = 0;
440 return ret;
441 case WM_USER+2:
442 ret = wm_clipboardupdate;
443 wm_clipboardupdate = 0;
444 return ret;
445 case WM_USER+3:
446 ret = wm_destroyclipboard;
447 wm_destroyclipboard = 0;
448 return ret;
451 return DefWindowProcA(hwnd, msg, wp, lp);
454 static DWORD WINAPI clipboard_thread(void *param)
456 HWND win = param;
457 BOOL r;
458 HANDLE handle;
459 UINT count, old_seq = 0, seq;
461 if (pGetClipboardSequenceNumber) old_seq = pGetClipboardSequenceNumber();
463 EnterCriticalSection(&clipboard_cs);
464 SetLastError(0xdeadbeef);
465 next_wnd = SetClipboardViewer(win);
466 ok(GetLastError() == 0xdeadbeef, "GetLastError = %d\n", GetLastError());
467 LeaveCriticalSection(&clipboard_cs);
468 if (pAddClipboardFormatListener)
470 r = pAddClipboardFormatListener(win);
471 ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError());
474 if (pGetClipboardSequenceNumber)
476 seq = pGetClipboardSequenceNumber();
477 ok( seq == old_seq, "sequence changed\n" );
479 count = SendMessageA( win, WM_USER + 1, 0, 0 );
480 ok( count, "WM_DRAWCLIPBOARD received\n" );
481 count = SendMessageA( win, WM_USER+2, 0, 0 );
482 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
484 r = OpenClipboard(win);
485 ok(r, "OpenClipboard failed: %d\n", GetLastError());
487 if (pGetClipboardSequenceNumber)
489 seq = pGetClipboardSequenceNumber();
490 ok( seq == old_seq, "sequence changed\n" );
492 count = SendMessageA( win, WM_USER+1, 0, 0 );
493 ok( !count, "WM_DRAWCLIPBOARD received\n" );
494 count = SendMessageA( win, WM_USER+2, 0, 0 );
495 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
497 r = EmptyClipboard();
498 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
500 if (pGetClipboardSequenceNumber)
502 seq = pGetClipboardSequenceNumber();
503 ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
504 old_seq = seq;
506 count = SendMessageA( win, WM_USER+1, 0, 0 );
507 ok( !count, "WM_DRAWCLIPBOARD received\n" );
508 count = SendMessageA( win, WM_USER+2, 0, 0 );
509 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
510 count = SendMessageA( win, WM_USER+3, 0, 0 );
511 ok( !count, "WM_DESTROYCLIPBOARD received\n" );
513 r = EmptyClipboard();
514 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
515 /* sequence changes again, even though it was already empty */
516 if (pGetClipboardSequenceNumber)
518 seq = pGetClipboardSequenceNumber();
519 ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
520 old_seq = seq;
522 count = SendMessageA( win, WM_USER+1, 0, 0 );
523 ok( !count, "WM_DRAWCLIPBOARD received\n" );
524 count = SendMessageA( win, WM_USER+2, 0, 0 );
525 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
526 count = SendMessageA( win, WM_USER+3, 0, 0 );
527 ok( count, "WM_DESTROYCLIPBOARD not received\n" );
529 handle = SetClipboardData( CF_TEXT, create_text() );
530 ok(handle != 0, "SetClipboardData failed: %d\n", GetLastError());
532 if (pGetClipboardSequenceNumber)
534 seq = pGetClipboardSequenceNumber();
535 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
536 old_seq = seq;
538 count = SendMessageA( win, WM_USER+1, 0, 0 );
539 ok( !count, "WM_DRAWCLIPBOARD received\n" );
540 count = SendMessageA( win, WM_USER+2, 0, 0 );
541 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
543 SetClipboardData( CF_UNICODETEXT, 0 );
545 if (pGetClipboardSequenceNumber)
547 seq = pGetClipboardSequenceNumber();
548 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
549 old_seq = seq;
551 count = SendMessageA( win, WM_USER+1, 0, 0 );
552 ok( !count, "WM_DRAWCLIPBOARD received\n" );
553 count = SendMessageA( win, WM_USER+2, 0, 0 );
554 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
556 SetClipboardData( CF_UNICODETEXT, 0 ); /* same data again */
558 if (pGetClipboardSequenceNumber)
560 seq = pGetClipboardSequenceNumber();
561 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
562 old_seq = seq;
564 count = SendMessageA( win, WM_USER+1, 0, 0 );
565 ok( !count, "WM_DRAWCLIPBOARD received\n" );
566 count = SendMessageA( win, WM_USER+2, 0, 0 );
567 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
569 EnterCriticalSection(&clipboard_cs);
570 r = CloseClipboard();
571 ok(r, "CloseClipboard failed: %d\n", GetLastError());
572 LeaveCriticalSection(&clipboard_cs);
574 if (pGetClipboardSequenceNumber)
576 seq = pGetClipboardSequenceNumber();
577 ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
578 old_seq = seq;
580 count = SendMessageA( win, WM_USER+1, 0, 0 );
581 ok( count, "WM_DRAWCLIPBOARD not received\n" );
582 count = SendMessageA( win, WM_USER+2, 0, 0 );
583 todo_wine ok( count || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
585 r = OpenClipboard(win);
586 ok(r, "OpenClipboard failed: %d\n", GetLastError());
588 if (pGetClipboardSequenceNumber)
590 seq = pGetClipboardSequenceNumber();
591 ok( seq == old_seq, "sequence changed\n" );
593 count = SendMessageA( win, WM_USER+1, 0, 0 );
594 ok( !count, "WM_DRAWCLIPBOARD received\n" );
595 count = SendMessageA( win, WM_USER+2, 0, 0 );
596 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
598 SetClipboardData( CF_WAVE, 0 );
599 if (pGetClipboardSequenceNumber)
601 seq = pGetClipboardSequenceNumber();
602 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
603 old_seq = seq;
605 count = SendMessageA( win, WM_USER+1, 0, 0 );
606 ok( !count, "WM_DRAWCLIPBOARD received\n" );
607 count = SendMessageA( win, WM_USER+2, 0, 0 );
608 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
610 r = CloseClipboard();
611 ok(r, "CloseClipboard failed: %d\n", GetLastError());
612 if (pGetClipboardSequenceNumber)
614 /* no synthesized format, so CloseClipboard doesn't change the sequence */
615 seq = pGetClipboardSequenceNumber();
616 todo_wine ok( seq == old_seq, "sequence changed\n" );
617 old_seq = seq;
619 count = SendMessageA( win, WM_USER+1, 0, 0 );
620 ok( count, "WM_DRAWCLIPBOARD not received\n" );
621 count = SendMessageA( win, WM_USER+2, 0, 0 );
622 todo_wine ok( count || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
624 r = OpenClipboard(win);
625 ok(r, "OpenClipboard failed: %d\n", GetLastError());
626 r = CloseClipboard();
627 ok(r, "CloseClipboard failed: %d\n", GetLastError());
628 /* nothing changed */
629 if (pGetClipboardSequenceNumber)
631 seq = pGetClipboardSequenceNumber();
632 ok( seq == old_seq, "sequence changed\n" );
634 count = SendMessageA( win, WM_USER+1, 0, 0 );
635 ok( !count, "WM_DRAWCLIPBOARD received\n" );
636 count = SendMessageA( win, WM_USER+2, 0, 0 );
637 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
639 r = OpenClipboard(0);
640 ok(r, "OpenClipboard failed: %d\n", GetLastError());
641 r = EmptyClipboard();
642 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
643 r = CloseClipboard();
644 ok(r, "CloseClipboard failed: %d\n", GetLastError());
646 r = PostMessageA(win, WM_USER, 0, 0);
647 ok(r, "PostMessage failed: %d\n", GetLastError());
648 return 0;
651 static void test_messages(void)
653 WNDCLASSA cls;
654 HWND win;
655 MSG msg;
656 HANDLE thread;
657 DWORD tid;
659 InitializeCriticalSection(&clipboard_cs);
661 memset(&cls, 0, sizeof(cls));
662 cls.lpfnWndProc = clipboard_wnd_proc;
663 cls.hInstance = GetModuleHandleA(NULL);
664 cls.lpszClassName = "clipboard_test";
665 RegisterClassA(&cls);
667 win = CreateWindowA("clipboard_test", NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0);
668 ok(win != NULL, "CreateWindow failed: %d\n", GetLastError());
670 thread = CreateThread(NULL, 0, clipboard_thread, (void*)win, 0, &tid);
671 ok(thread != NULL, "CreateThread failed: %d\n", GetLastError());
673 while(GetMessageA(&msg, NULL, 0, 0)) {
674 TranslateMessage(&msg);
675 DispatchMessageA(&msg);
678 ok(WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
679 CloseHandle(thread);
681 UnregisterClassA("clipboard_test", GetModuleHandleA(NULL));
682 DeleteCriticalSection(&clipboard_cs);
685 START_TEST(clipboard)
687 HMODULE mod = GetModuleHandleA( "user32" );
689 pAddClipboardFormatListener = (void *)GetProcAddress( mod, "AddClipboardFormatListener" );
690 pGetClipboardSequenceNumber = (void *)GetProcAddress( mod, "GetClipboardSequenceNumber" );
692 test_RegisterClipboardFormatA();
693 test_ClipboardOwner();
694 test_synthesized();
695 test_messages();