user32: Disallow format 0 in SetClipboardData.
[wine.git] / dlls / user32 / tests / clipboard.c
blob25da45b99c4610258bad91ac3bd73663311d82fd
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 void test_ClipboardOwner(void)
39 HANDLE thread;
40 HWND hWnd1, hWnd2;
41 DWORD dwret;
42 BOOL ret;
44 SetLastError(0xdeadbeef);
45 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef,
46 "could not perform clipboard test: clipboard already owned\n");
48 hWnd1 = CreateWindowExA(0, "static", NULL, WS_POPUP,
49 0, 0, 10, 10, 0, 0, 0, NULL);
50 ok(hWnd1 != 0, "CreateWindowExA error %d\n", GetLastError());
51 trace("hWnd1 = %p\n", hWnd1);
53 hWnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP,
54 0, 0, 10, 10, 0, 0, 0, NULL);
55 ok(hWnd2 != 0, "CreateWindowExA error %d\n", GetLastError());
56 trace("hWnd2 = %p\n", hWnd2);
58 SetLastError(0xdeadbeef);
59 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
60 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */
61 "wrong error %u\n", GetLastError());
63 ok(OpenClipboard(0), "OpenClipboard failed\n");
64 ok(!GetClipboardOwner(), "clipboard should still be not owned\n");
65 ok(!OpenClipboard(hWnd1), "OpenClipboard should fail since clipboard already opened\n");
66 ok(OpenClipboard(0), "OpenClipboard again failed\n");
67 ret = CloseClipboard();
68 ok( ret, "CloseClipboard error %d\n", GetLastError());
70 ok(OpenClipboard(hWnd1), "OpenClipboard failed\n");
71 thread = CreateThread(NULL, 0, open_clipboard_thread, hWnd1, 0, NULL);
72 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
73 dwret = WaitForSingleObject(thread, 1000);
74 ok(dwret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", dwret);
75 CloseHandle(thread);
76 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
77 ok(OpenClipboard(hWnd1), "OpenClipboard failed\n");
79 SetLastError(0xdeadbeef);
80 ret = OpenClipboard(hWnd2);
81 ok(!ret && (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED),
82 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
84 SetLastError(0xdeadbeef);
85 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should still be not owned\n");
86 ret = EmptyClipboard();
87 ok( ret, "EmptyClipboard error %d\n", GetLastError());
88 ok(GetClipboardOwner() == hWnd1, "clipboard should be owned by %p, not by %p\n", hWnd1, GetClipboardOwner());
90 SetLastError(0xdeadbeef);
91 ret = OpenClipboard(hWnd2);
92 ok(!ret && (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED),
93 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
95 ret = CloseClipboard();
96 ok( ret, "CloseClipboard error %d\n", GetLastError());
97 ok(GetClipboardOwner() == hWnd1, "clipboard should still be owned\n");
99 ret = DestroyWindow(hWnd1);
100 ok( ret, "DestroyWindow error %d\n", GetLastError());
101 ret = DestroyWindow(hWnd2);
102 ok( ret, "DestroyWindow error %d\n", GetLastError());
103 SetLastError(0xdeadbeef);
104 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should not be owned\n");
107 static void test_RegisterClipboardFormatA(void)
109 ATOM atom_id;
110 UINT format_id, format_id2;
111 char buf[256];
112 int len;
113 BOOL ret;
114 HANDLE handle;
116 format_id = RegisterClipboardFormatA("my_cool_clipboard_format");
117 ok(format_id > 0xc000 && format_id < 0xffff, "invalid clipboard format id %04x\n", format_id);
119 format_id2 = RegisterClipboardFormatA("MY_COOL_CLIPBOARD_FORMAT");
120 ok(format_id2 == format_id, "invalid clipboard format id %04x\n", format_id2);
122 len = GetClipboardFormatNameA(format_id, buf, 256);
123 ok(len == lstrlenA("my_cool_clipboard_format"), "wrong format name length %d\n", len);
124 ok(!lstrcmpA(buf, "my_cool_clipboard_format"), "wrong format name \"%s\"\n", buf);
126 lstrcpyA(buf, "foo");
127 SetLastError(0xdeadbeef);
128 len = GetAtomNameA((ATOM)format_id, buf, 256);
129 ok(len == 0, "GetAtomNameA should fail\n");
130 ok(GetLastError() == ERROR_INVALID_HANDLE, "err %d\n", GetLastError());
132 todo_wine
134 lstrcpyA(buf, "foo");
135 SetLastError(0xdeadbeef);
136 len = GlobalGetAtomNameA((ATOM)format_id, buf, 256);
137 ok(len == 0, "GlobalGetAtomNameA should fail\n");
138 ok(GetLastError() == ERROR_INVALID_HANDLE, "err %d\n", GetLastError());
141 SetLastError(0xdeadbeef);
142 atom_id = FindAtomA("my_cool_clipboard_format");
143 ok(atom_id == 0, "FindAtomA should fail\n");
144 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError());
146 if (0)
148 /* this relies on the clipboard and global atom table being different */
149 SetLastError(0xdeadbeef);
150 atom_id = GlobalFindAtomA("my_cool_clipboard_format");
151 ok(atom_id == 0, "GlobalFindAtomA should fail\n");
152 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError());
155 for (format_id = 0; format_id < 0xffff; format_id++)
157 SetLastError(0xdeadbeef);
158 len = GetClipboardFormatNameA(format_id, buf, 256);
160 if (format_id < 0xc000)
161 ok(!len, "GetClipboardFormatNameA should fail, but it returned %d (%s)\n", len, buf);
162 else if (len && winetest_debug > 1)
163 trace("%04x: %s\n", format_id, len ? buf : "");
166 ret = OpenClipboard(0);
167 ok( ret, "OpenClipboard error %d\n", GetLastError());
169 /* try some invalid/unregistered formats */
170 SetLastError( 0xdeadbeef );
171 handle = SetClipboardData( 0, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
172 ok( !handle, "SetClipboardData succeeded\n" );
173 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError());
174 handle = SetClipboardData( 0x1234, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
175 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
176 handle = SetClipboardData( 0x123456, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
177 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
178 handle = SetClipboardData( 0xffff8765, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
179 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
181 ok( IsClipboardFormatAvailable( 0x1234 ), "format missing\n" );
182 ok( IsClipboardFormatAvailable( 0x123456 ), "format missing\n" );
183 ok( IsClipboardFormatAvailable( 0xffff8765 ), "format missing\n" );
184 ok( !IsClipboardFormatAvailable( 0 ), "format available\n" );
185 ok( !IsClipboardFormatAvailable( 0x3456 ), "format available\n" );
186 ok( !IsClipboardFormatAvailable( 0x8765 ), "format available\n" );
188 trace("# of formats available: %d\n", CountClipboardFormats());
190 format_id = 0;
191 while ((format_id = EnumClipboardFormats(format_id)))
193 ok(IsClipboardFormatAvailable(format_id), "format %04x was listed as available\n", format_id);
194 len = GetClipboardFormatNameA(format_id, buf, 256);
195 trace("%04x: %s\n", format_id, len ? buf : "");
198 ret = EmptyClipboard();
199 ok( ret, "EmptyClipboard error %d\n", GetLastError());
200 ret =CloseClipboard();
201 ok( ret, "CloseClipboard error %d\n", GetLastError());
203 if (CountClipboardFormats())
205 SetLastError(0xdeadbeef);
206 ok(!EnumClipboardFormats(0), "EnumClipboardFormats should fail if clipboard wasn't open\n");
207 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN,
208 "Last error should be set to ERROR_CLIPBOARD_NOT_OPEN, not %d\n", GetLastError());
211 SetLastError(0xdeadbeef);
212 ok(!EmptyClipboard(), "EmptyClipboard should fail if clipboard wasn't open\n");
213 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */
214 "Wrong error %u\n", GetLastError());
216 format_id = RegisterClipboardFormatA("#1234");
217 ok(format_id == 1234, "invalid clipboard format id %04x\n", format_id);
220 static HGLOBAL create_text(void)
222 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 5);
223 char *p = GlobalLock(h);
224 strcpy(p, "test");
225 GlobalUnlock(h);
226 return h;
229 static HENHMETAFILE create_emf(void)
231 const RECT rect = {0, 0, 100, 100};
232 HDC hdc = CreateEnhMetaFileA(NULL, NULL, &rect, "HENHMETAFILE Ole Clipboard Test\0Test\0\0");
233 ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
234 return CloseEnhMetaFile(hdc);
237 static void test_synthesized(void)
239 HGLOBAL h, htext;
240 HENHMETAFILE emf;
241 BOOL r;
242 UINT cf;
243 HANDLE data;
245 htext = create_text();
246 emf = create_emf();
248 r = OpenClipboard(NULL);
249 ok(r, "gle %d\n", GetLastError());
250 r = EmptyClipboard();
251 ok(r, "gle %d\n", GetLastError());
252 h = SetClipboardData(CF_TEXT, htext);
253 ok(h == htext, "got %p\n", h);
254 h = SetClipboardData(CF_ENHMETAFILE, emf);
255 ok(h == emf, "got %p\n", h);
256 r = CloseClipboard();
257 ok(r, "gle %d\n", GetLastError());
259 r = OpenClipboard(NULL);
260 ok(r, "gle %d\n", GetLastError());
261 cf = EnumClipboardFormats(0);
262 ok(cf == CF_TEXT, "cf %08x\n", cf);
263 data = GetClipboardData(cf);
264 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
266 cf = EnumClipboardFormats(cf);
267 ok(cf == CF_ENHMETAFILE, "cf %08x\n", cf);
268 data = GetClipboardData(cf);
269 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
271 cf = EnumClipboardFormats(cf);
272 todo_wine ok(cf == CF_LOCALE, "cf %08x\n", cf);
273 if(cf == CF_LOCALE)
274 cf = EnumClipboardFormats(cf);
275 ok(cf == CF_OEMTEXT, "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_UNICODETEXT ||
281 broken(cf == CF_METAFILEPICT), /* win9x and winME has no CF_UNICODETEXT */
282 "cf %08x\n", cf);
284 if(cf == CF_UNICODETEXT)
285 cf = EnumClipboardFormats(cf);
286 ok(cf == CF_METAFILEPICT, "cf %08x\n", cf);
287 data = GetClipboardData(cf);
288 todo_wine ok(data != NULL, "couldn't get data, cf %08x\n", cf);
290 cf = EnumClipboardFormats(cf);
291 ok(cf == 0, "cf %08x\n", cf);
293 r = EmptyClipboard();
294 ok(r, "gle %d\n", GetLastError());
296 r = CloseClipboard();
297 ok(r, "gle %d\n", GetLastError());
300 static CRITICAL_SECTION clipboard_cs;
301 static HWND next_wnd;
302 static LRESULT CALLBACK clipboard_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
304 static UINT wm_drawclipboard;
305 static UINT wm_clipboardupdate;
306 LRESULT ret;
308 switch(msg) {
309 case WM_DRAWCLIPBOARD:
310 EnterCriticalSection(&clipboard_cs);
311 wm_drawclipboard++;
312 LeaveCriticalSection(&clipboard_cs);
313 break;
314 case WM_CHANGECBCHAIN:
315 if (next_wnd == (HWND)wp)
316 next_wnd = (HWND)lp;
317 else if (next_wnd)
318 SendMessageA(next_wnd, msg, wp, lp);
319 break;
320 case WM_CLIPBOARDUPDATE:
321 wm_clipboardupdate++;
322 break;
323 case WM_USER:
324 ChangeClipboardChain(hwnd, next_wnd);
325 PostQuitMessage(0);
326 break;
327 case WM_USER+1:
328 ret = wm_drawclipboard;
329 wm_drawclipboard = 0;
330 return ret;
331 case WM_USER+2:
332 ret = wm_clipboardupdate;
333 wm_clipboardupdate = 0;
334 return ret;
337 return DefWindowProcA(hwnd, msg, wp, lp);
340 static DWORD WINAPI clipboard_thread(void *param)
342 HWND win = param;
343 BOOL r;
344 HANDLE handle;
345 UINT count, old_seq = 0, seq;
347 if (pGetClipboardSequenceNumber) old_seq = pGetClipboardSequenceNumber();
349 EnterCriticalSection(&clipboard_cs);
350 SetLastError(0xdeadbeef);
351 next_wnd = SetClipboardViewer(win);
352 ok(GetLastError() == 0xdeadbeef, "GetLastError = %d\n", GetLastError());
353 LeaveCriticalSection(&clipboard_cs);
354 if (pAddClipboardFormatListener)
356 r = pAddClipboardFormatListener(win);
357 ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError());
360 if (pGetClipboardSequenceNumber)
362 seq = pGetClipboardSequenceNumber();
363 ok( seq == old_seq, "sequence changed\n" );
365 count = SendMessageA( win, WM_USER + 1, 0, 0 );
366 ok( count, "WM_DRAWCLIPBOARD received\n" );
367 count = SendMessageA( win, WM_USER+2, 0, 0 );
368 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
370 r = OpenClipboard(win);
371 ok(r, "OpenClipboard failed: %d\n", GetLastError());
373 if (pGetClipboardSequenceNumber)
375 seq = pGetClipboardSequenceNumber();
376 ok( seq == old_seq, "sequence changed\n" );
378 count = SendMessageA( win, WM_USER+1, 0, 0 );
379 ok( !count, "WM_DRAWCLIPBOARD received\n" );
380 count = SendMessageA( win, WM_USER+2, 0, 0 );
381 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
383 r = EmptyClipboard();
384 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
386 if (pGetClipboardSequenceNumber)
388 seq = pGetClipboardSequenceNumber();
389 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
390 old_seq = seq;
392 count = SendMessageA( win, WM_USER+1, 0, 0 );
393 ok( !count, "WM_DRAWCLIPBOARD received\n" );
394 count = SendMessageA( win, WM_USER+2, 0, 0 );
395 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
397 r = EmptyClipboard();
398 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
399 /* sequence changes again, even though it was already empty */
400 if (pGetClipboardSequenceNumber)
402 seq = pGetClipboardSequenceNumber();
403 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
404 old_seq = seq;
406 count = SendMessageA( win, WM_USER+1, 0, 0 );
407 ok( !count, "WM_DRAWCLIPBOARD received\n" );
408 count = SendMessageA( win, WM_USER+2, 0, 0 );
409 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
411 handle = SetClipboardData( CF_TEXT, create_text() );
412 ok(handle != 0, "SetClipboardData failed: %d\n", GetLastError());
414 if (pGetClipboardSequenceNumber)
416 seq = pGetClipboardSequenceNumber();
417 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
418 old_seq = seq;
420 count = SendMessageA( win, WM_USER+1, 0, 0 );
421 ok( !count, "WM_DRAWCLIPBOARD received\n" );
422 count = SendMessageA( win, WM_USER+2, 0, 0 );
423 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
425 SetClipboardData( CF_UNICODETEXT, 0 );
427 if (pGetClipboardSequenceNumber)
429 seq = pGetClipboardSequenceNumber();
430 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
431 old_seq = seq;
433 count = SendMessageA( win, WM_USER+1, 0, 0 );
434 ok( !count, "WM_DRAWCLIPBOARD received\n" );
435 count = SendMessageA( win, WM_USER+2, 0, 0 );
436 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
438 SetClipboardData( CF_UNICODETEXT, 0 ); /* same data again */
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 EnterCriticalSection(&clipboard_cs);
452 r = CloseClipboard();
453 ok(r, "CloseClipboard failed: %d\n", GetLastError());
454 LeaveCriticalSection(&clipboard_cs);
456 if (pGetClipboardSequenceNumber)
458 seq = pGetClipboardSequenceNumber();
459 ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
460 old_seq = seq;
462 count = SendMessageA( win, WM_USER+1, 0, 0 );
463 ok( count, "WM_DRAWCLIPBOARD not received\n" );
464 count = SendMessageA( win, WM_USER+2, 0, 0 );
465 todo_wine ok( count || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
467 r = OpenClipboard(win);
468 ok(r, "OpenClipboard failed: %d\n", GetLastError());
470 if (pGetClipboardSequenceNumber)
472 seq = pGetClipboardSequenceNumber();
473 ok( seq == old_seq, "sequence changed\n" );
475 count = SendMessageA( win, WM_USER+1, 0, 0 );
476 ok( !count, "WM_DRAWCLIPBOARD received\n" );
477 count = SendMessageA( win, WM_USER+2, 0, 0 );
478 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
480 SetClipboardData( CF_WAVE, 0 );
481 if (pGetClipboardSequenceNumber)
483 seq = pGetClipboardSequenceNumber();
484 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
485 old_seq = seq;
487 count = SendMessageA( win, WM_USER+1, 0, 0 );
488 ok( !count, "WM_DRAWCLIPBOARD received\n" );
489 count = SendMessageA( win, WM_USER+2, 0, 0 );
490 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
492 r = CloseClipboard();
493 ok(r, "CloseClipboard failed: %d\n", GetLastError());
494 if (pGetClipboardSequenceNumber)
496 /* no synthesized format, so CloseClipboard doesn't change the sequence */
497 seq = pGetClipboardSequenceNumber();
498 todo_wine ok( seq == old_seq, "sequence changed\n" );
499 old_seq = seq;
501 count = SendMessageA( win, WM_USER+1, 0, 0 );
502 ok( count, "WM_DRAWCLIPBOARD not received\n" );
503 count = SendMessageA( win, WM_USER+2, 0, 0 );
504 todo_wine ok( count || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
506 r = OpenClipboard(win);
507 ok(r, "OpenClipboard failed: %d\n", GetLastError());
508 r = CloseClipboard();
509 ok(r, "CloseClipboard failed: %d\n", GetLastError());
510 /* nothing changed */
511 if (pGetClipboardSequenceNumber)
513 seq = pGetClipboardSequenceNumber();
514 ok( seq == old_seq, "sequence changed\n" );
516 count = SendMessageA( win, WM_USER+1, 0, 0 );
517 ok( !count, "WM_DRAWCLIPBOARD received\n" );
518 count = SendMessageA( win, WM_USER+2, 0, 0 );
519 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
521 r = PostMessageA(win, WM_USER, 0, 0);
522 ok(r, "PostMessage failed: %d\n", GetLastError());
523 return 0;
526 static void test_messages(void)
528 WNDCLASSA cls;
529 HWND win;
530 MSG msg;
531 HANDLE thread;
532 DWORD tid;
534 InitializeCriticalSection(&clipboard_cs);
536 memset(&cls, 0, sizeof(cls));
537 cls.lpfnWndProc = clipboard_wnd_proc;
538 cls.hInstance = GetModuleHandleA(NULL);
539 cls.lpszClassName = "clipboard_test";
540 RegisterClassA(&cls);
542 win = CreateWindowA("clipboard_test", NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0);
543 ok(win != NULL, "CreateWindow failed: %d\n", GetLastError());
545 thread = CreateThread(NULL, 0, clipboard_thread, (void*)win, 0, &tid);
546 ok(thread != NULL, "CreateThread failed: %d\n", GetLastError());
548 while(GetMessageA(&msg, NULL, 0, 0)) {
549 TranslateMessage(&msg);
550 DispatchMessageA(&msg);
553 ok(WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
554 CloseHandle(thread);
556 UnregisterClassA("clipboard_test", GetModuleHandleA(NULL));
557 DeleteCriticalSection(&clipboard_cs);
560 START_TEST(clipboard)
562 HMODULE mod = GetModuleHandleA( "user32" );
564 pAddClipboardFormatListener = (void *)GetProcAddress( mod, "AddClipboardFormatListener" );
565 pGetClipboardSequenceNumber = (void *)GetProcAddress( mod, "GetClipboardSequenceNumber" );
567 test_RegisterClipboardFormatA();
568 test_ClipboardOwner();
569 test_synthesized();
570 test_messages();