user32/tests: Add tests for calling EmptyClipboard from a different thread.
[wine.git] / dlls / user32 / tests / clipboard.c
blob05deed649648b71cb1b165a902f740bafc9b0a9b
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 DWORD WINAPI open_clipboard_thread(LPVOID arg)
32 HWND hWnd = arg;
33 ok(OpenClipboard(hWnd), "OpenClipboard failed\n");
34 return 0;
37 static DWORD WINAPI empty_clipboard_thread(LPVOID arg)
39 SetLastError( 0xdeadbeef );
40 ok(!EmptyClipboard(), "EmptyClipboard succeeded\n" );
41 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError());
42 return 0;
45 static void test_ClipboardOwner(void)
47 HANDLE thread;
48 HWND hWnd1, hWnd2;
49 DWORD dwret;
50 BOOL ret;
52 SetLastError(0xdeadbeef);
53 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef,
54 "could not perform clipboard test: clipboard already owned\n");
56 hWnd1 = CreateWindowExA(0, "static", NULL, WS_POPUP,
57 0, 0, 10, 10, 0, 0, 0, NULL);
58 ok(hWnd1 != 0, "CreateWindowExA error %d\n", GetLastError());
59 trace("hWnd1 = %p\n", hWnd1);
61 hWnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP,
62 0, 0, 10, 10, 0, 0, 0, NULL);
63 ok(hWnd2 != 0, "CreateWindowExA error %d\n", GetLastError());
64 trace("hWnd2 = %p\n", hWnd2);
66 SetLastError(0xdeadbeef);
67 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
68 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */
69 "wrong error %u\n", GetLastError());
71 ok(OpenClipboard(0), "OpenClipboard failed\n");
72 ok(!GetClipboardOwner(), "clipboard should still be not owned\n");
73 ok(!OpenClipboard(hWnd1), "OpenClipboard should fail since clipboard already opened\n");
74 ok(OpenClipboard(0), "OpenClipboard again failed\n");
75 ret = CloseClipboard();
76 ok( ret, "CloseClipboard error %d\n", GetLastError());
78 ok(OpenClipboard(hWnd1), "OpenClipboard failed\n");
79 thread = CreateThread(NULL, 0, open_clipboard_thread, hWnd1, 0, NULL);
80 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
81 dwret = WaitForSingleObject(thread, 1000);
82 ok(dwret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", dwret);
83 CloseHandle(thread);
84 thread = CreateThread(NULL, 0, empty_clipboard_thread, 0, 0, NULL);
85 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
86 dwret = WaitForSingleObject(thread, 1000);
87 ok(dwret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", dwret);
88 CloseHandle(thread);
89 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
90 ok(OpenClipboard(hWnd1), "OpenClipboard failed\n");
92 SetLastError(0xdeadbeef);
93 ret = OpenClipboard(hWnd2);
94 ok(!ret && (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED),
95 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
97 SetLastError(0xdeadbeef);
98 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should still be not owned\n");
99 ret = EmptyClipboard();
100 ok( ret, "EmptyClipboard error %d\n", GetLastError());
101 ok(GetClipboardOwner() == hWnd1, "clipboard should be owned by %p, not by %p\n", hWnd1, GetClipboardOwner());
103 SetLastError(0xdeadbeef);
104 ret = OpenClipboard(hWnd2);
105 ok(!ret && (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED),
106 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
108 ret = CloseClipboard();
109 ok( ret, "CloseClipboard error %d\n", GetLastError());
110 ok(GetClipboardOwner() == hWnd1, "clipboard should still be owned\n");
112 ret = DestroyWindow(hWnd1);
113 ok( ret, "DestroyWindow error %d\n", GetLastError());
114 ret = DestroyWindow(hWnd2);
115 ok( ret, "DestroyWindow error %d\n", GetLastError());
116 SetLastError(0xdeadbeef);
117 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should not be owned\n");
120 static void test_RegisterClipboardFormatA(void)
122 ATOM atom_id;
123 UINT format_id, format_id2;
124 char buf[256];
125 int len;
126 BOOL ret;
127 HANDLE handle;
129 format_id = RegisterClipboardFormatA("my_cool_clipboard_format");
130 ok(format_id > 0xc000 && format_id < 0xffff, "invalid clipboard format id %04x\n", format_id);
132 format_id2 = RegisterClipboardFormatA("MY_COOL_CLIPBOARD_FORMAT");
133 ok(format_id2 == format_id, "invalid clipboard format id %04x\n", format_id2);
135 len = GetClipboardFormatNameA(format_id, buf, 256);
136 ok(len == lstrlenA("my_cool_clipboard_format"), "wrong format name length %d\n", len);
137 ok(!lstrcmpA(buf, "my_cool_clipboard_format"), "wrong format name \"%s\"\n", buf);
139 lstrcpyA(buf, "foo");
140 SetLastError(0xdeadbeef);
141 len = GetAtomNameA((ATOM)format_id, buf, 256);
142 ok(len == 0, "GetAtomNameA should fail\n");
143 ok(GetLastError() == ERROR_INVALID_HANDLE, "err %d\n", GetLastError());
145 todo_wine
147 lstrcpyA(buf, "foo");
148 SetLastError(0xdeadbeef);
149 len = GlobalGetAtomNameA((ATOM)format_id, buf, 256);
150 ok(len == 0, "GlobalGetAtomNameA should fail\n");
151 ok(GetLastError() == ERROR_INVALID_HANDLE, "err %d\n", GetLastError());
154 SetLastError(0xdeadbeef);
155 atom_id = FindAtomA("my_cool_clipboard_format");
156 ok(atom_id == 0, "FindAtomA should fail\n");
157 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError());
159 if (0)
161 /* this relies on the clipboard and global atom table being different */
162 SetLastError(0xdeadbeef);
163 atom_id = GlobalFindAtomA("my_cool_clipboard_format");
164 ok(atom_id == 0, "GlobalFindAtomA should fail\n");
165 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError());
168 for (format_id = 0; format_id < 0xffff; format_id++)
170 SetLastError(0xdeadbeef);
171 len = GetClipboardFormatNameA(format_id, buf, 256);
173 if (format_id < 0xc000)
174 ok(!len, "GetClipboardFormatNameA should fail, but it returned %d (%s)\n", len, buf);
175 else if (len && winetest_debug > 1)
176 trace("%04x: %s\n", format_id, len ? buf : "");
179 ret = OpenClipboard(0);
180 ok( ret, "OpenClipboard error %d\n", GetLastError());
182 /* try some invalid/unregistered formats */
183 SetLastError( 0xdeadbeef );
184 handle = SetClipboardData( 0, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
185 ok( !handle, "SetClipboardData succeeded\n" );
186 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError());
187 handle = SetClipboardData( 0x1234, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
188 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
189 handle = SetClipboardData( 0x123456, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
190 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
191 handle = SetClipboardData( 0xffff8765, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
192 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
194 ok( IsClipboardFormatAvailable( 0x1234 ), "format missing\n" );
195 ok( IsClipboardFormatAvailable( 0x123456 ), "format missing\n" );
196 ok( IsClipboardFormatAvailable( 0xffff8765 ), "format missing\n" );
197 ok( !IsClipboardFormatAvailable( 0 ), "format available\n" );
198 ok( !IsClipboardFormatAvailable( 0x3456 ), "format available\n" );
199 ok( !IsClipboardFormatAvailable( 0x8765 ), "format available\n" );
201 trace("# of formats available: %d\n", CountClipboardFormats());
203 format_id = 0;
204 while ((format_id = EnumClipboardFormats(format_id)))
206 ok(IsClipboardFormatAvailable(format_id), "format %04x was listed as available\n", format_id);
207 len = GetClipboardFormatNameA(format_id, buf, 256);
208 trace("%04x: %s\n", format_id, len ? buf : "");
211 ret = EmptyClipboard();
212 ok( ret, "EmptyClipboard error %d\n", GetLastError());
213 ret =CloseClipboard();
214 ok( ret, "CloseClipboard error %d\n", GetLastError());
216 if (CountClipboardFormats())
218 SetLastError(0xdeadbeef);
219 ok(!EnumClipboardFormats(0), "EnumClipboardFormats should fail if clipboard wasn't open\n");
220 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN,
221 "Last error should be set to ERROR_CLIPBOARD_NOT_OPEN, not %d\n", GetLastError());
224 SetLastError(0xdeadbeef);
225 ok(!EmptyClipboard(), "EmptyClipboard should fail if clipboard wasn't open\n");
226 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */
227 "Wrong error %u\n", GetLastError());
229 format_id = RegisterClipboardFormatA("#1234");
230 ok(format_id == 1234, "invalid clipboard format id %04x\n", format_id);
233 static HGLOBAL create_text(void)
235 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 5);
236 char *p = GlobalLock(h);
237 strcpy(p, "test");
238 GlobalUnlock(h);
239 return h;
242 static HENHMETAFILE create_emf(void)
244 const RECT rect = {0, 0, 100, 100};
245 HDC hdc = CreateEnhMetaFileA(NULL, NULL, &rect, "HENHMETAFILE Ole Clipboard Test\0Test\0\0");
246 ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
247 return CloseEnhMetaFile(hdc);
250 static void test_synthesized(void)
252 HGLOBAL h, htext;
253 HENHMETAFILE emf;
254 BOOL r;
255 UINT cf;
256 HANDLE data;
258 htext = create_text();
259 emf = create_emf();
261 r = OpenClipboard(NULL);
262 ok(r, "gle %d\n", GetLastError());
263 r = EmptyClipboard();
264 ok(r, "gle %d\n", GetLastError());
265 h = SetClipboardData(CF_TEXT, htext);
266 ok(h == htext, "got %p\n", h);
267 h = SetClipboardData(CF_ENHMETAFILE, emf);
268 ok(h == emf, "got %p\n", h);
269 r = CloseClipboard();
270 ok(r, "gle %d\n", GetLastError());
272 r = OpenClipboard(NULL);
273 ok(r, "gle %d\n", GetLastError());
274 cf = EnumClipboardFormats(0);
275 ok(cf == CF_TEXT, "cf %08x\n", cf);
276 data = GetClipboardData(cf);
277 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
279 cf = EnumClipboardFormats(cf);
280 ok(cf == CF_ENHMETAFILE, "cf %08x\n", cf);
281 data = GetClipboardData(cf);
282 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
284 cf = EnumClipboardFormats(cf);
285 todo_wine ok(cf == CF_LOCALE, "cf %08x\n", cf);
286 if(cf == CF_LOCALE)
287 cf = EnumClipboardFormats(cf);
288 ok(cf == CF_OEMTEXT, "cf %08x\n", cf);
289 data = GetClipboardData(cf);
290 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
292 cf = EnumClipboardFormats(cf);
293 ok(cf == CF_UNICODETEXT ||
294 broken(cf == CF_METAFILEPICT), /* win9x and winME has no CF_UNICODETEXT */
295 "cf %08x\n", cf);
297 if(cf == CF_UNICODETEXT)
298 cf = EnumClipboardFormats(cf);
299 ok(cf == CF_METAFILEPICT, "cf %08x\n", cf);
300 data = GetClipboardData(cf);
301 todo_wine ok(data != NULL, "couldn't get data, cf %08x\n", cf);
303 cf = EnumClipboardFormats(cf);
304 ok(cf == 0, "cf %08x\n", cf);
306 r = EmptyClipboard();
307 ok(r, "gle %d\n", GetLastError());
309 r = CloseClipboard();
310 ok(r, "gle %d\n", GetLastError());
313 static CRITICAL_SECTION clipboard_cs;
314 static HWND next_wnd;
315 static LRESULT CALLBACK clipboard_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
317 static UINT wm_drawclipboard;
318 static UINT wm_clipboardupdate;
319 static UINT wm_destroyclipboard;
320 LRESULT ret;
322 switch(msg) {
323 case WM_DRAWCLIPBOARD:
324 EnterCriticalSection(&clipboard_cs);
325 wm_drawclipboard++;
326 LeaveCriticalSection(&clipboard_cs);
327 break;
328 case WM_CHANGECBCHAIN:
329 if (next_wnd == (HWND)wp)
330 next_wnd = (HWND)lp;
331 else if (next_wnd)
332 SendMessageA(next_wnd, msg, wp, lp);
333 break;
334 case WM_DESTROYCLIPBOARD:
335 wm_destroyclipboard++;
336 ok( GetClipboardOwner() == hwnd, "WM_DESTROYCLIPBOARD owner %p\n", GetClipboardOwner() );
337 break;
338 case WM_CLIPBOARDUPDATE:
339 wm_clipboardupdate++;
340 break;
341 case WM_USER:
342 ChangeClipboardChain(hwnd, next_wnd);
343 PostQuitMessage(0);
344 break;
345 case WM_USER+1:
346 ret = wm_drawclipboard;
347 wm_drawclipboard = 0;
348 return ret;
349 case WM_USER+2:
350 ret = wm_clipboardupdate;
351 wm_clipboardupdate = 0;
352 return ret;
353 case WM_USER+3:
354 ret = wm_destroyclipboard;
355 wm_destroyclipboard = 0;
356 return ret;
359 return DefWindowProcA(hwnd, msg, wp, lp);
362 static DWORD WINAPI clipboard_thread(void *param)
364 HWND win = param;
365 BOOL r;
366 HANDLE handle;
367 UINT count, old_seq = 0, seq;
369 if (pGetClipboardSequenceNumber) old_seq = pGetClipboardSequenceNumber();
371 EnterCriticalSection(&clipboard_cs);
372 SetLastError(0xdeadbeef);
373 next_wnd = SetClipboardViewer(win);
374 ok(GetLastError() == 0xdeadbeef, "GetLastError = %d\n", GetLastError());
375 LeaveCriticalSection(&clipboard_cs);
376 if (pAddClipboardFormatListener)
378 r = pAddClipboardFormatListener(win);
379 ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError());
382 if (pGetClipboardSequenceNumber)
384 seq = pGetClipboardSequenceNumber();
385 ok( seq == old_seq, "sequence changed\n" );
387 count = SendMessageA( win, WM_USER + 1, 0, 0 );
388 ok( count, "WM_DRAWCLIPBOARD received\n" );
389 count = SendMessageA( win, WM_USER+2, 0, 0 );
390 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
392 r = OpenClipboard(win);
393 ok(r, "OpenClipboard failed: %d\n", GetLastError());
395 if (pGetClipboardSequenceNumber)
397 seq = pGetClipboardSequenceNumber();
398 ok( seq == old_seq, "sequence changed\n" );
400 count = SendMessageA( win, WM_USER+1, 0, 0 );
401 ok( !count, "WM_DRAWCLIPBOARD received\n" );
402 count = SendMessageA( win, WM_USER+2, 0, 0 );
403 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
405 r = EmptyClipboard();
406 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
408 if (pGetClipboardSequenceNumber)
410 seq = pGetClipboardSequenceNumber();
411 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
412 old_seq = seq;
414 count = SendMessageA( win, WM_USER+1, 0, 0 );
415 ok( !count, "WM_DRAWCLIPBOARD received\n" );
416 count = SendMessageA( win, WM_USER+2, 0, 0 );
417 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
418 count = SendMessageA( win, WM_USER+3, 0, 0 );
419 ok( !count, "WM_DESTROYCLIPBOARD received\n" );
421 r = EmptyClipboard();
422 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
423 /* sequence changes again, even though it was already empty */
424 if (pGetClipboardSequenceNumber)
426 seq = pGetClipboardSequenceNumber();
427 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
428 old_seq = seq;
430 count = SendMessageA( win, WM_USER+1, 0, 0 );
431 ok( !count, "WM_DRAWCLIPBOARD received\n" );
432 count = SendMessageA( win, WM_USER+2, 0, 0 );
433 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
434 count = SendMessageA( win, WM_USER+3, 0, 0 );
435 ok( count, "WM_DESTROYCLIPBOARD not received\n" );
437 handle = SetClipboardData( CF_TEXT, create_text() );
438 ok(handle != 0, "SetClipboardData failed: %d\n", GetLastError());
440 if (pGetClipboardSequenceNumber)
442 seq = pGetClipboardSequenceNumber();
443 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
444 old_seq = seq;
446 count = SendMessageA( win, WM_USER+1, 0, 0 );
447 ok( !count, "WM_DRAWCLIPBOARD received\n" );
448 count = SendMessageA( win, WM_USER+2, 0, 0 );
449 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
451 SetClipboardData( CF_UNICODETEXT, 0 );
453 if (pGetClipboardSequenceNumber)
455 seq = pGetClipboardSequenceNumber();
456 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
457 old_seq = seq;
459 count = SendMessageA( win, WM_USER+1, 0, 0 );
460 ok( !count, "WM_DRAWCLIPBOARD received\n" );
461 count = SendMessageA( win, WM_USER+2, 0, 0 );
462 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
464 SetClipboardData( CF_UNICODETEXT, 0 ); /* same data again */
466 if (pGetClipboardSequenceNumber)
468 seq = pGetClipboardSequenceNumber();
469 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
470 old_seq = seq;
472 count = SendMessageA( win, WM_USER+1, 0, 0 );
473 ok( !count, "WM_DRAWCLIPBOARD received\n" );
474 count = SendMessageA( win, WM_USER+2, 0, 0 );
475 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
477 EnterCriticalSection(&clipboard_cs);
478 r = CloseClipboard();
479 ok(r, "CloseClipboard failed: %d\n", GetLastError());
480 LeaveCriticalSection(&clipboard_cs);
482 if (pGetClipboardSequenceNumber)
484 seq = pGetClipboardSequenceNumber();
485 ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
486 old_seq = seq;
488 count = SendMessageA( win, WM_USER+1, 0, 0 );
489 ok( count, "WM_DRAWCLIPBOARD not received\n" );
490 count = SendMessageA( win, WM_USER+2, 0, 0 );
491 todo_wine ok( count || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
493 r = OpenClipboard(win);
494 ok(r, "OpenClipboard failed: %d\n", GetLastError());
496 if (pGetClipboardSequenceNumber)
498 seq = pGetClipboardSequenceNumber();
499 ok( seq == old_seq, "sequence changed\n" );
501 count = SendMessageA( win, WM_USER+1, 0, 0 );
502 ok( !count, "WM_DRAWCLIPBOARD received\n" );
503 count = SendMessageA( win, WM_USER+2, 0, 0 );
504 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
506 SetClipboardData( CF_WAVE, 0 );
507 if (pGetClipboardSequenceNumber)
509 seq = pGetClipboardSequenceNumber();
510 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
511 old_seq = seq;
513 count = SendMessageA( win, WM_USER+1, 0, 0 );
514 ok( !count, "WM_DRAWCLIPBOARD received\n" );
515 count = SendMessageA( win, WM_USER+2, 0, 0 );
516 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
518 r = CloseClipboard();
519 ok(r, "CloseClipboard failed: %d\n", GetLastError());
520 if (pGetClipboardSequenceNumber)
522 /* no synthesized format, so CloseClipboard doesn't change the sequence */
523 seq = pGetClipboardSequenceNumber();
524 todo_wine ok( seq == old_seq, "sequence changed\n" );
525 old_seq = seq;
527 count = SendMessageA( win, WM_USER+1, 0, 0 );
528 ok( count, "WM_DRAWCLIPBOARD not received\n" );
529 count = SendMessageA( win, WM_USER+2, 0, 0 );
530 todo_wine ok( count || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
532 r = OpenClipboard(win);
533 ok(r, "OpenClipboard failed: %d\n", GetLastError());
534 r = CloseClipboard();
535 ok(r, "CloseClipboard failed: %d\n", GetLastError());
536 /* nothing changed */
537 if (pGetClipboardSequenceNumber)
539 seq = pGetClipboardSequenceNumber();
540 ok( seq == old_seq, "sequence changed\n" );
542 count = SendMessageA( win, WM_USER+1, 0, 0 );
543 ok( !count, "WM_DRAWCLIPBOARD received\n" );
544 count = SendMessageA( win, WM_USER+2, 0, 0 );
545 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
547 r = OpenClipboard(0);
548 ok(r, "OpenClipboard failed: %d\n", GetLastError());
549 r = EmptyClipboard();
550 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
551 r = CloseClipboard();
552 ok(r, "CloseClipboard failed: %d\n", GetLastError());
554 r = PostMessageA(win, WM_USER, 0, 0);
555 ok(r, "PostMessage failed: %d\n", GetLastError());
556 return 0;
559 static void test_messages(void)
561 WNDCLASSA cls;
562 HWND win;
563 MSG msg;
564 HANDLE thread;
565 DWORD tid;
567 InitializeCriticalSection(&clipboard_cs);
569 memset(&cls, 0, sizeof(cls));
570 cls.lpfnWndProc = clipboard_wnd_proc;
571 cls.hInstance = GetModuleHandleA(NULL);
572 cls.lpszClassName = "clipboard_test";
573 RegisterClassA(&cls);
575 win = CreateWindowA("clipboard_test", NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0);
576 ok(win != NULL, "CreateWindow failed: %d\n", GetLastError());
578 thread = CreateThread(NULL, 0, clipboard_thread, (void*)win, 0, &tid);
579 ok(thread != NULL, "CreateThread failed: %d\n", GetLastError());
581 while(GetMessageA(&msg, NULL, 0, 0)) {
582 TranslateMessage(&msg);
583 DispatchMessageA(&msg);
586 ok(WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
587 CloseHandle(thread);
589 UnregisterClassA("clipboard_test", GetModuleHandleA(NULL));
590 DeleteCriticalSection(&clipboard_cs);
593 START_TEST(clipboard)
595 HMODULE mod = GetModuleHandleA( "user32" );
597 pAddClipboardFormatListener = (void *)GetProcAddress( mod, "AddClipboardFormatListener" );
598 pGetClipboardSequenceNumber = (void *)GetProcAddress( mod, "GetClipboardSequenceNumber" );
600 test_RegisterClipboardFormatA();
601 test_ClipboardOwner();
602 test_synthesized();
603 test_messages();