user32/tests: Make the clipboard sequence tests more strict.
[wine.git] / dlls / user32 / tests / clipboard.c
blobdd724d90af952aa90eadea576a6df72204a38227
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 <stdio.h>
22 #include "wine/test.h"
23 #include "winbase.h"
24 #include "winerror.h"
25 #include "wingdi.h"
26 #include "winuser.h"
27 #include "winnls.h"
29 static BOOL (WINAPI *pAddClipboardFormatListener)(HWND hwnd);
30 static BOOL (WINAPI *pRemoveClipboardFormatListener)(HWND hwnd);
31 static DWORD (WINAPI *pGetClipboardSequenceNumber)(void);
32 static BOOL (WINAPI *pGetUpdatedClipboardFormats)( UINT *formats, UINT count, UINT *out_count );
34 static const BOOL is_win64 = sizeof(void *) > sizeof(int);
35 static int thread_from_line;
36 static char *argv0;
38 static DWORD WINAPI open_clipboard_thread(LPVOID arg)
40 HWND hWnd = arg;
41 ok(OpenClipboard(hWnd), "%u: OpenClipboard failed\n", thread_from_line);
42 return 0;
45 static DWORD WINAPI empty_clipboard_thread(LPVOID arg)
47 SetLastError( 0xdeadbeef );
48 ok(!EmptyClipboard(), "%u: EmptyClipboard succeeded\n", thread_from_line );
49 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
50 thread_from_line, GetLastError());
51 return 0;
54 static DWORD WINAPI open_and_empty_clipboard_thread(LPVOID arg)
56 HWND hWnd = arg;
57 ok(OpenClipboard(hWnd), "%u: OpenClipboard failed\n", thread_from_line);
58 ok(EmptyClipboard(), "%u: EmptyClipboard failed\n", thread_from_line );
59 return 0;
62 static DWORD WINAPI open_and_empty_clipboard_win_thread(LPVOID arg)
64 HWND hwnd = CreateWindowA( "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL );
65 ok(OpenClipboard(hwnd), "%u: OpenClipboard failed\n", thread_from_line);
66 ok(EmptyClipboard(), "%u: EmptyClipboard failed\n", thread_from_line );
67 return 0;
70 static DWORD WINAPI set_clipboard_data_thread(LPVOID arg)
72 HWND hwnd = arg;
73 HANDLE ret;
75 SetLastError( 0xdeadbeef );
76 if (GetClipboardOwner() == hwnd)
78 SetClipboardData( CF_WAVE, 0 );
79 ok( IsClipboardFormatAvailable( CF_WAVE ), "%u: SetClipboardData failed\n", thread_from_line );
80 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
81 ok( ret != 0, "%u: SetClipboardData failed err %u\n", thread_from_line, GetLastError() );
82 SetLastError( 0xdeadbeef );
83 ret = GetClipboardData( CF_WAVE );
84 ok( !ret, "%u: GetClipboardData succeeded\n", thread_from_line );
85 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
86 thread_from_line, GetLastError());
88 else
90 SetClipboardData( CF_WAVE, 0 );
91 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
92 thread_from_line, GetLastError());
93 ok( !IsClipboardFormatAvailable( CF_WAVE ), "%u: SetClipboardData succeeded\n", thread_from_line );
94 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
95 ok( !ret, "%u: SetClipboardData succeeded\n", thread_from_line );
96 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
97 thread_from_line, GetLastError());
99 return 0;
102 static void set_clipboard_data_process( int arg )
104 HANDLE ret;
106 SetLastError( 0xdeadbeef );
107 if (arg)
109 todo_wine_if( arg == 1 || arg == 3 )
110 ok( IsClipboardFormatAvailable( CF_WAVE ), "process %u: CF_WAVE not available\n", arg );
111 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
112 ok( ret != 0, "process %u: SetClipboardData failed err %u\n", arg, GetLastError() );
114 else
116 SetClipboardData( CF_WAVE, 0 );
117 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "process %u: wrong error %u\n",
118 arg, GetLastError());
119 ok( !IsClipboardFormatAvailable( CF_WAVE ), "process %u: SetClipboardData succeeded\n", arg );
120 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
121 ok( !ret, "process %u: SetClipboardData succeeded\n", arg );
122 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "process %u: wrong error %u\n",
123 arg, GetLastError());
127 static void grab_clipboard_process( int arg )
129 BOOL ret;
131 SetLastError( 0xdeadbeef );
132 ret = OpenClipboard( 0 );
133 ok( ret, "OpenClipboard failed\n" );
134 ret = EmptyClipboard();
135 ok( ret, "EmptyClipboard failed\n" );
136 if (arg)
138 HANDLE ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
139 ok( ret != 0, "process %u: SetClipboardData failed err %u\n", arg, GetLastError() );
143 static void run_thread( LPTHREAD_START_ROUTINE func, void *arg, int line )
145 DWORD ret;
146 HANDLE thread;
148 thread_from_line = line;
149 thread = CreateThread(NULL, 0, func, arg, 0, NULL);
150 ok(thread != NULL, "%u: CreateThread failed with error %d\n", line, GetLastError());
151 for (;;)
153 ret = MsgWaitForMultipleObjectsEx( 1, &thread, 1000, QS_ALLINPUT, 0 );
154 if (ret == WAIT_OBJECT_0 + 1)
156 MSG msg;
157 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
159 else break;
161 ok(ret == WAIT_OBJECT_0, "%u: expected WAIT_OBJECT_0, got %u\n", line, ret);
162 CloseHandle(thread);
165 static void run_process( const char *args )
167 char cmd[MAX_PATH];
168 PROCESS_INFORMATION info;
169 STARTUPINFOA startup;
171 sprintf( cmd, "%s clipboard %s", argv0, args );
172 memset( &startup, 0, sizeof(startup) );
173 startup.cb = sizeof(startup);
174 ok( CreateProcessA( NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info ),
175 "CreateProcess %s failed\n", cmd );
177 winetest_wait_child_process( info.hProcess );
178 CloseHandle( info.hProcess );
179 CloseHandle( info.hThread );
182 static WNDPROC old_proc;
183 static LRESULT CALLBACK winproc_wrapper( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
185 static int wm_renderallformats;
186 static int wm_drawclipboard;
187 static int seqno;
188 DWORD msg_flags = InSendMessageEx( NULL );
190 if (!seqno) seqno = GetClipboardSequenceNumber();
192 trace( "%p msg %04x\n", hwnd, msg );
193 if (!wm_renderallformats)
195 ok( GetClipboardOwner() == hwnd, "%04x: wrong owner %p/%p\n", msg, GetClipboardOwner(), hwnd );
196 ok( seqno == GetClipboardSequenceNumber(), "%04x: seqno changed\n", msg );
198 else
200 ok( !GetClipboardOwner(), "%04x: wrong owner %p\n", msg, GetClipboardOwner() );
201 ok( seqno + 1 == GetClipboardSequenceNumber(), "%04x: seqno unchanged\n", msg );
203 ok( GetClipboardViewer() == hwnd, "%04x: wrong viewer %p/%p\n", msg, GetClipboardViewer(), hwnd );
204 ok( GetOpenClipboardWindow() == hwnd, "%04x: wrong open win %p/%p\n",
205 msg, GetOpenClipboardWindow(), hwnd );
207 switch (msg)
209 case WM_DESTROY:
210 ok( wm_renderallformats, "didn't receive WM_RENDERALLFORMATS before WM_DESTROY\n" );
211 todo_wine ok( wm_drawclipboard, "didn't receive WM_DRAWCLIPBOARD before WM_DESTROY\n" );
212 break;
213 case WM_DRAWCLIPBOARD:
214 ok( msg_flags == ISMEX_NOSEND, "WM_DRAWCLIPBOARD wrong flags %x\n", msg_flags );
215 wm_drawclipboard++;
216 break;
217 case WM_RENDERALLFORMATS:
218 ok( msg_flags == ISMEX_NOSEND, "WM_RENDERALLFORMATS wrong flags %x\n", msg_flags );
219 wm_renderallformats++;
220 break;
222 return old_proc( hwnd, msg, wp, lp );
225 static void test_ClipboardOwner(void)
227 HWND hWnd1, hWnd2;
228 BOOL ret;
230 SetLastError(0xdeadbeef);
231 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef,
232 "could not perform clipboard test: clipboard already owned\n");
234 hWnd1 = CreateWindowExA(0, "static", NULL, WS_POPUP,
235 0, 0, 10, 10, 0, 0, 0, NULL);
236 ok(hWnd1 != 0, "CreateWindowExA error %d\n", GetLastError());
237 trace("hWnd1 = %p\n", hWnd1);
239 hWnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP,
240 0, 0, 10, 10, 0, 0, 0, NULL);
241 ok(hWnd2 != 0, "CreateWindowExA error %d\n", GetLastError());
242 trace("hWnd2 = %p\n", hWnd2);
244 SetLastError(0xdeadbeef);
245 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
246 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */
247 "wrong error %u\n", GetLastError());
249 ok(OpenClipboard(0), "OpenClipboard failed\n");
250 ok(!GetClipboardOwner(), "clipboard should still be not owned\n");
251 ok(!OpenClipboard(hWnd1), "OpenClipboard should fail since clipboard already opened\n");
252 ok(OpenClipboard(0), "OpenClipboard again failed\n");
253 ret = CloseClipboard();
254 ok( ret, "CloseClipboard error %d\n", GetLastError());
256 ok(OpenClipboard(hWnd1), "OpenClipboard failed\n");
257 run_thread( open_clipboard_thread, hWnd1, __LINE__ );
258 run_thread( empty_clipboard_thread, 0, __LINE__ );
259 run_thread( set_clipboard_data_thread, hWnd1, __LINE__ );
260 ok( !IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE available\n" );
261 ok( !GetClipboardData( CF_WAVE ), "CF_WAVE data available\n" );
262 run_process( "set_clipboard_data 0" );
263 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
264 ok(OpenClipboard(hWnd1), "OpenClipboard failed\n");
266 SetLastError(0xdeadbeef);
267 ret = OpenClipboard(hWnd2);
268 ok(!ret && (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED),
269 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
271 SetLastError(0xdeadbeef);
272 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should still be not owned\n");
273 ret = EmptyClipboard();
274 ok( ret, "EmptyClipboard error %d\n", GetLastError());
275 ok(GetClipboardOwner() == hWnd1, "clipboard should be owned by %p, not by %p\n", hWnd1, GetClipboardOwner());
276 run_thread( empty_clipboard_thread, 0, __LINE__ );
277 run_thread( set_clipboard_data_thread, hWnd1, __LINE__ );
278 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
279 ok( GetClipboardData( CF_WAVE ) != 0, "CF_WAVE data not available\n" );
280 run_process( "set_clipboard_data 1" );
282 SetLastError(0xdeadbeef);
283 ret = OpenClipboard(hWnd2);
284 ok(!ret && (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED),
285 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
287 ret = CloseClipboard();
288 ok( ret, "CloseClipboard error %d\n", GetLastError());
289 ok(GetClipboardOwner() == hWnd1, "clipboard should still be owned\n");
291 /* any window will do, even from a different process */
292 ret = OpenClipboard( GetDesktopWindow() );
293 ok( ret, "OpenClipboard error %d\n", GetLastError());
294 ret = EmptyClipboard();
295 ok( ret, "EmptyClipboard error %d\n", GetLastError());
296 ok( GetClipboardOwner() == GetDesktopWindow(), "wrong owner %p/%p\n",
297 GetClipboardOwner(), GetDesktopWindow() );
298 run_thread( set_clipboard_data_thread, GetDesktopWindow(), __LINE__ );
299 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
300 ok( GetClipboardData( CF_WAVE ) != 0, "CF_WAVE data not available\n" );
301 run_process( "set_clipboard_data 2" );
302 ret = CloseClipboard();
303 ok( ret, "CloseClipboard error %d\n", GetLastError());
305 ret = OpenClipboard( hWnd1 );
306 ok( ret, "OpenClipboard error %d\n", GetLastError());
307 ret = EmptyClipboard();
308 ok( ret, "EmptyClipboard error %d\n", GetLastError());
309 SetClipboardData( CF_WAVE, 0 );
310 SetClipboardViewer( hWnd1 );
311 ok( GetClipboardOwner() == hWnd1, "wrong owner %p/%p\n", GetClipboardOwner(), hWnd1 );
312 ok( GetClipboardViewer() == hWnd1, "wrong viewer %p/%p\n", GetClipboardViewer(), hWnd1 );
313 ok( GetOpenClipboardWindow() == hWnd1, "wrong open win %p/%p\n", GetOpenClipboardWindow(), hWnd1 );
314 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
316 old_proc = (WNDPROC)SetWindowLongPtrA( hWnd1, GWLP_WNDPROC, (LONG_PTR)winproc_wrapper );
317 ret = DestroyWindow(hWnd1);
318 ok( ret, "DestroyWindow error %d\n", GetLastError());
319 ret = DestroyWindow(hWnd2);
320 ok( ret, "DestroyWindow error %d\n", GetLastError());
321 SetLastError(0xdeadbeef);
322 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should not be owned\n");
323 ok(!GetClipboardViewer() && GetLastError() == 0xdeadbeef, "viewer still exists\n");
324 ok(!GetOpenClipboardWindow() && GetLastError() == 0xdeadbeef, "clipboard should not be open\n");
325 todo_wine ok( !IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE available\n" );
327 SetLastError( 0xdeadbeef );
328 ret = CloseClipboard();
329 ok( !ret, "CloseClipboard succeeded\n" );
330 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError() );
332 ret = OpenClipboard( 0 );
333 ok( ret, "OpenClipboard error %d\n", GetLastError());
334 run_thread( set_clipboard_data_thread, 0, __LINE__ );
335 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
336 ok( GetClipboardData( CF_WAVE ) != 0, "CF_WAVE data not available\n" );
337 run_process( "set_clipboard_data 3" );
338 ret = CloseClipboard();
339 ok( ret, "CloseClipboard error %d\n", GetLastError());
341 run_thread( open_and_empty_clipboard_thread, 0, __LINE__ );
342 ok( !GetOpenClipboardWindow(), "wrong open window %p\n", GetOpenClipboardWindow() );
343 ok( !GetClipboardOwner(), "wrong owner window %p\n", GetClipboardOwner() );
345 ret = OpenClipboard( 0 );
346 ok( ret, "OpenClipboard error %d\n", GetLastError());
347 run_thread( set_clipboard_data_thread, 0, __LINE__ );
348 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
349 ok( GetClipboardData( CF_WAVE ) != 0, "CF_WAVE data not available\n" );
350 run_process( "set_clipboard_data 4" );
351 ret = EmptyClipboard();
352 ok( ret, "EmptyClipboard error %d\n", GetLastError());
353 ret = CloseClipboard();
354 ok( ret, "CloseClipboard error %d\n", GetLastError());
356 SetLastError( 0xdeadbeef );
357 ok( !SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 )),
358 "SetClipboardData succeeded\n" );
359 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError() );
360 ok( !IsClipboardFormatAvailable( CF_WAVE ), "SetClipboardData succeeded\n" );
362 run_thread( open_and_empty_clipboard_thread, GetDesktopWindow(), __LINE__ );
363 ok( !GetOpenClipboardWindow(), "wrong open window %p\n", GetOpenClipboardWindow() );
364 ok( GetClipboardOwner() == GetDesktopWindow(), "wrong owner window %p / %p\n",
365 GetClipboardOwner(), GetDesktopWindow() );
367 run_thread( open_and_empty_clipboard_win_thread, 0, __LINE__ );
368 ok( !GetOpenClipboardWindow(), "wrong open window %p\n", GetOpenClipboardWindow() );
369 ok( !GetClipboardOwner(), "wrong owner window %p\n", GetClipboardOwner() );
372 static void test_RegisterClipboardFormatA(void)
374 ATOM atom_id;
375 UINT format_id, format_id2;
376 char buf[256];
377 int len;
378 BOOL ret;
379 HANDLE handle;
381 format_id = RegisterClipboardFormatA("my_cool_clipboard_format");
382 ok(format_id > 0xc000 && format_id < 0xffff, "invalid clipboard format id %04x\n", format_id);
384 format_id2 = RegisterClipboardFormatA("MY_COOL_CLIPBOARD_FORMAT");
385 ok(format_id2 == format_id, "invalid clipboard format id %04x\n", format_id2);
387 len = GetClipboardFormatNameA(format_id, buf, 256);
388 ok(len == lstrlenA("my_cool_clipboard_format"), "wrong format name length %d\n", len);
389 ok(!lstrcmpA(buf, "my_cool_clipboard_format"), "wrong format name \"%s\"\n", buf);
391 lstrcpyA(buf, "foo");
392 SetLastError(0xdeadbeef);
393 len = GetAtomNameA((ATOM)format_id, buf, 256);
394 ok(len == 0, "GetAtomNameA should fail\n");
395 ok(GetLastError() == ERROR_INVALID_HANDLE, "err %d\n", GetLastError());
397 todo_wine
399 lstrcpyA(buf, "foo");
400 SetLastError(0xdeadbeef);
401 len = GlobalGetAtomNameA((ATOM)format_id, buf, 256);
402 ok(len == 0, "GlobalGetAtomNameA should fail\n");
403 ok(GetLastError() == ERROR_INVALID_HANDLE, "err %d\n", GetLastError());
406 SetLastError(0xdeadbeef);
407 atom_id = FindAtomA("my_cool_clipboard_format");
408 ok(atom_id == 0, "FindAtomA should fail\n");
409 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError());
411 if (0)
413 /* this relies on the clipboard and global atom table being different */
414 SetLastError(0xdeadbeef);
415 atom_id = GlobalFindAtomA("my_cool_clipboard_format");
416 ok(atom_id == 0, "GlobalFindAtomA should fail\n");
417 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError());
420 for (format_id = 0; format_id < 0xffff; format_id++)
422 SetLastError(0xdeadbeef);
423 len = GetClipboardFormatNameA(format_id, buf, 256);
425 if (format_id < 0xc000)
426 ok(!len, "GetClipboardFormatNameA should fail, but it returned %d (%s)\n", len, buf);
427 else if (len && winetest_debug > 1)
428 trace("%04x: %s\n", format_id, len ? buf : "");
431 ret = OpenClipboard(0);
432 ok( ret, "OpenClipboard error %d\n", GetLastError());
434 /* try some invalid/unregistered formats */
435 SetLastError( 0xdeadbeef );
436 handle = SetClipboardData( 0, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
437 ok( !handle, "SetClipboardData succeeded\n" );
438 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError());
439 handle = SetClipboardData( 0x1234, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
440 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
441 handle = SetClipboardData( 0x123456, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
442 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
443 handle = SetClipboardData( 0xffff8765, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
444 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
446 ok( IsClipboardFormatAvailable( 0x1234 ), "format missing\n" );
447 ok( IsClipboardFormatAvailable( 0x123456 ), "format missing\n" );
448 ok( IsClipboardFormatAvailable( 0xffff8765 ), "format missing\n" );
449 ok( !IsClipboardFormatAvailable( 0 ), "format available\n" );
450 ok( !IsClipboardFormatAvailable( 0x3456 ), "format available\n" );
451 ok( !IsClipboardFormatAvailable( 0x8765 ), "format available\n" );
453 trace("# of formats available: %d\n", CountClipboardFormats());
455 format_id = 0;
456 while ((format_id = EnumClipboardFormats(format_id)))
458 ok(IsClipboardFormatAvailable(format_id), "format %04x was listed as available\n", format_id);
459 len = GetClipboardFormatNameA(format_id, buf, 256);
460 trace("%04x: %s\n", format_id, len ? buf : "");
463 ret = EmptyClipboard();
464 ok( ret, "EmptyClipboard error %d\n", GetLastError());
465 ret =CloseClipboard();
466 ok( ret, "CloseClipboard error %d\n", GetLastError());
468 if (CountClipboardFormats())
470 SetLastError(0xdeadbeef);
471 ok(!EnumClipboardFormats(0), "EnumClipboardFormats should fail if clipboard wasn't open\n");
472 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN,
473 "Last error should be set to ERROR_CLIPBOARD_NOT_OPEN, not %d\n", GetLastError());
476 SetLastError(0xdeadbeef);
477 ok(!EmptyClipboard(), "EmptyClipboard should fail if clipboard wasn't open\n");
478 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */
479 "Wrong error %u\n", GetLastError());
481 format_id = RegisterClipboardFormatA("#1234");
482 ok(format_id == 1234, "invalid clipboard format id %04x\n", format_id);
485 static HGLOBAL create_textA(void)
487 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 5);
488 char *p = GlobalLock(h);
489 strcpy(p, "test");
490 GlobalUnlock(h);
491 return h;
494 static HGLOBAL create_textW(void)
496 static const WCHAR testW[] = {'t','e','s','t',0};
497 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 5 * sizeof(WCHAR));
498 WCHAR *p = GlobalLock(h);
499 lstrcpyW(p, testW);
500 GlobalUnlock(h);
501 return h;
504 static HANDLE create_metafile(void)
506 const RECT rect = {0, 0, 100, 100};
507 METAFILEPICT *pict;
508 HANDLE ret;
509 HMETAFILE mf;
510 HDC hdc = CreateMetaFileA( NULL );
511 ExtTextOutA( hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL );
512 mf = CloseMetaFile( hdc );
513 ret = GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(*pict) );
514 pict = GlobalLock( ret );
515 pict->mm = MM_TEXT;
516 pict->xExt = pict->yExt = 100;
517 pict->hMF = mf;
518 GlobalUnlock( ret );
519 return ret;
522 static HENHMETAFILE create_emf(void)
524 const RECT rect = {0, 0, 100, 100};
525 HDC hdc = CreateEnhMetaFileA(NULL, NULL, &rect, "HENHMETAFILE Ole Clipboard Test\0Test\0\0");
526 ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
527 return CloseEnhMetaFile(hdc);
530 static HBITMAP create_bitmap(void)
532 HDC hdc = GetDC( 0 );
533 UINT bpp = GetDeviceCaps( hdc, BITSPIXEL );
534 ReleaseDC( 0, hdc );
535 return CreateBitmap( 10, 10, 1, bpp, NULL );
538 static HBITMAP create_dib( BOOL v5 )
540 HANDLE ret;
541 BITMAPINFOHEADER *hdr;
543 ret = GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT,
544 sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD) + 16 * 16 * 4 );
545 hdr = GlobalLock( ret );
546 hdr->biSize = v5 ? sizeof(BITMAPV5HEADER) : sizeof(*hdr);
547 hdr->biWidth = 16;
548 hdr->biHeight = 16;
549 hdr->biPlanes = 1;
550 hdr->biBitCount = 32;
551 hdr->biCompression = BI_RGB;
552 if (v5)
554 BITMAPV5HEADER *hdr5 = (BITMAPV5HEADER *)hdr;
555 hdr5->bV5RedMask = 0x0000ff;
556 hdr5->bV5GreenMask = 0x00ff00;
557 hdr5->bV5BlueMask = 0xff0000;
558 hdr5->bV5AlphaMask = 0xff000000;
560 GlobalUnlock( ret );
561 return ret;
564 static LRESULT CALLBACK renderer_winproc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
566 static UINT rendered;
567 UINT ret;
569 switch (msg)
571 case WM_RENDERFORMAT:
572 if (wp < 32) rendered |= (1 << wp);
573 break;
574 case WM_USER:
575 ret = rendered;
576 rendered = 0;
577 return ret;
579 return DefWindowProcA( hwnd, msg, wp, lp );
582 static void test_synthesized(void)
584 static const struct test
586 UINT format;
587 UINT expected[8];
588 } tests[] =
590 /* 0 */ { CF_TEXT, { CF_TEXT, CF_LOCALE, CF_OEMTEXT, CF_UNICODETEXT }},
591 { CF_OEMTEXT, { CF_OEMTEXT, CF_LOCALE, CF_TEXT, CF_UNICODETEXT }},
592 { CF_UNICODETEXT, { CF_UNICODETEXT, CF_LOCALE, CF_TEXT, CF_OEMTEXT }},
593 { CF_ENHMETAFILE, { CF_ENHMETAFILE, CF_METAFILEPICT }},
594 { CF_METAFILEPICT, { CF_METAFILEPICT, CF_ENHMETAFILE }},
595 /* 5 */ { CF_BITMAP, { CF_BITMAP, CF_DIB, CF_DIBV5 }},
596 { CF_DIB, { CF_DIB, CF_BITMAP, CF_DIBV5 }},
597 { CF_DIBV5, { CF_DIBV5, CF_BITMAP, CF_DIB }},
600 HGLOBAL h, htext;
601 HENHMETAFILE emf;
602 BOOL r;
603 UINT cf, i, j, count, rendered;
604 HANDLE data;
605 HWND hwnd;
607 hwnd = CreateWindowA( "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL );
608 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)renderer_winproc );
610 htext = create_textA();
611 emf = create_emf();
613 r = OpenClipboard(NULL);
614 ok(r, "gle %d\n", GetLastError());
615 r = EmptyClipboard();
616 ok(r, "gle %d\n", GetLastError());
617 h = SetClipboardData(CF_TEXT, htext);
618 ok(h == htext, "got %p\n", h);
619 h = SetClipboardData(CF_ENHMETAFILE, emf);
620 ok(h == emf, "got %p\n", h);
621 r = CloseClipboard();
622 ok(r, "gle %d\n", GetLastError());
624 count = CountClipboardFormats();
625 ok( count == 6, "count %u\n", count );
626 r = IsClipboardFormatAvailable( CF_TEXT );
627 ok( r, "CF_TEXT not available err %d\n", GetLastError());
628 r = IsClipboardFormatAvailable( CF_LOCALE );
629 ok( r, "CF_LOCALE not available err %d\n", GetLastError());
630 r = IsClipboardFormatAvailable( CF_OEMTEXT );
631 ok( r, "CF_OEMTEXT not available err %d\n", GetLastError());
632 r = IsClipboardFormatAvailable( CF_UNICODETEXT );
633 ok( r, "CF_UNICODETEXT not available err %d\n", GetLastError());
634 r = IsClipboardFormatAvailable( CF_ENHMETAFILE );
635 ok( r, "CF_ENHMETAFILE not available err %d\n", GetLastError());
636 r = IsClipboardFormatAvailable( CF_METAFILEPICT );
637 ok( r, "CF_METAFILEPICT not available err %d\n", GetLastError());
639 r = OpenClipboard(NULL);
640 ok(r, "gle %d\n", GetLastError());
641 cf = EnumClipboardFormats(0);
642 ok(cf == CF_TEXT, "cf %08x\n", cf);
643 data = GetClipboardData(cf);
644 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
646 cf = EnumClipboardFormats(cf);
647 ok(cf == CF_ENHMETAFILE, "cf %08x\n", cf);
648 data = GetClipboardData(cf);
649 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
651 cf = EnumClipboardFormats(cf);
652 ok(cf == CF_LOCALE, "cf %08x\n", cf);
653 data = GetClipboardData(cf);
654 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
656 cf = EnumClipboardFormats(cf);
657 ok(cf == CF_OEMTEXT, "cf %08x\n", cf);
658 data = GetClipboardData(cf);
659 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
661 cf = EnumClipboardFormats(cf);
662 ok(cf == CF_UNICODETEXT, "cf %08x\n", cf);
664 cf = EnumClipboardFormats(cf);
665 ok(cf == CF_METAFILEPICT, "cf %08x\n", cf);
666 data = GetClipboardData(cf);
667 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
669 cf = EnumClipboardFormats(cf);
670 ok(cf == 0, "cf %08x\n", cf);
672 r = EmptyClipboard();
673 ok(r, "gle %d\n", GetLastError());
675 SetClipboardData( CF_UNICODETEXT, create_textW() );
676 SetClipboardData( CF_TEXT, create_textA() );
677 SetClipboardData( CF_OEMTEXT, create_textA() );
678 r = CloseClipboard();
679 ok(r, "gle %d\n", GetLastError());
681 r = OpenClipboard( NULL );
682 ok(r, "gle %d\n", GetLastError());
683 SetLastError( 0xdeadbeef );
684 cf = EnumClipboardFormats(0);
685 ok( cf == CF_UNICODETEXT, "cf %08x\n", cf );
686 ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() );
687 SetLastError( 0xdeadbeef );
688 cf = EnumClipboardFormats(cf);
689 ok( cf == CF_TEXT, "cf %08x\n", cf );
690 ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() );
691 SetLastError( 0xdeadbeef );
692 cf = EnumClipboardFormats(cf);
693 ok( cf == CF_OEMTEXT, "cf %08x\n", cf );
694 ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() );
695 SetLastError( 0xdeadbeef );
696 cf = EnumClipboardFormats(cf);
697 ok( cf == CF_LOCALE, "cf %08x\n", cf );
698 ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() );
699 SetLastError( 0xdeadbeef );
700 cf = EnumClipboardFormats( cf );
701 ok( cf == 0, "cf %08x\n", cf );
702 ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() );
703 SetLastError( 0xdeadbeef );
704 cf = EnumClipboardFormats( 0xdead );
705 ok( cf == 0, "cf %08x\n", cf );
706 ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() );
708 r = EmptyClipboard();
709 ok(r, "gle %d\n", GetLastError());
711 r = CloseClipboard();
712 ok(r, "gle %d\n", GetLastError());
714 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
716 r = OpenClipboard(NULL);
717 ok(r, "%u: gle %d\n", i, GetLastError());
718 r = EmptyClipboard();
719 ok(r, "%u: gle %d\n", i, GetLastError());
721 switch (tests[i].format)
723 case CF_TEXT:
724 case CF_OEMTEXT:
725 SetClipboardData( tests[i].format, create_textA() );
726 break;
727 case CF_UNICODETEXT:
728 SetClipboardData( CF_UNICODETEXT, create_textW() );
729 break;
730 case CF_ENHMETAFILE:
731 SetClipboardData( CF_ENHMETAFILE, create_emf() );
732 break;
733 case CF_METAFILEPICT:
734 SetClipboardData( CF_METAFILEPICT, create_metafile() );
735 break;
736 case CF_BITMAP:
737 SetClipboardData( CF_BITMAP, create_bitmap() );
738 break;
739 case CF_DIB:
740 case CF_DIBV5:
741 SetClipboardData( tests[i].format, create_dib( tests[i].format == CF_DIBV5 ));
742 break;
745 count = CountClipboardFormats();
746 ok( count == 1, "%u: count %u\n", i, count );
748 r = CloseClipboard();
749 ok(r, "%u: gle %d\n", i, GetLastError());
751 count = CountClipboardFormats();
752 for (j = 0; tests[i].expected[j]; j++)
754 r = IsClipboardFormatAvailable( tests[i].expected[j] );
755 ok( r, "%u: %04x not available\n", i, tests[i].expected[j] );
757 ok( count == j, "%u: count %u instead of %u\n", i, count, j );
759 r = OpenClipboard( hwnd );
760 ok(r, "%u: gle %d\n", i, GetLastError());
761 cf = 0;
762 for (j = 0; tests[i].expected[j]; j++)
764 cf = EnumClipboardFormats( cf );
765 ok(cf == tests[i].expected[j], "%u.%u: got %04x instead of %04x\n",
766 i, j, cf, tests[i].expected[j] );
767 if (cf != tests[i].expected[j]) break;
768 data = GetClipboardData( cf );
769 ok(data != NULL ||
770 broken( tests[i].format == CF_DIBV5 && cf == CF_DIB ), /* >= Vista */
771 "%u: couldn't get data, cf %04x err %d\n", i, cf, GetLastError());
772 if (cf == CF_LOCALE)
774 UINT *ptr = GlobalLock( data );
775 ok( GlobalSize( data ) == sizeof(*ptr), "%u: size %lu\n", i, GlobalSize( data ));
776 ok( *ptr == GetUserDefaultLCID() ||
777 broken( *ptr == MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT )),
778 "%u: CF_LOCALE %08x/%08x\n", i, *ptr, GetUserDefaultLCID() );
779 GlobalUnlock( data );
782 if (!tests[i].expected[j])
784 cf = EnumClipboardFormats( cf );
785 ok(cf == 0, "%u: cf %04x\n", i, cf);
788 /* now with delayed rendering */
790 r = EmptyClipboard();
791 ok(r, "%u: gle %d\n", i, GetLastError());
793 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
794 ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered );
796 SetClipboardData( tests[i].format, 0 );
797 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
798 ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered );
800 count = CountClipboardFormats();
801 ok( count == 1, "%u: count %u\n", i, count );
803 r = CloseClipboard();
804 ok(r, "%u: gle %d\n", i, GetLastError());
805 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
806 ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered );
808 count = CountClipboardFormats();
809 for (j = 0; tests[i].expected[j]; j++)
811 r = IsClipboardFormatAvailable( tests[i].expected[j] );
812 ok( r, "%u: %04x not available\n", i, tests[i].expected[j] );
814 ok( count == j, "%u: count %u instead of %u\n", i, count, j );
815 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
816 ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered );
818 r = OpenClipboard(NULL);
819 ok(r, "%u: gle %d\n", i, GetLastError());
820 cf = 0;
821 for (j = 0; tests[i].expected[j]; j++)
823 cf = EnumClipboardFormats( cf );
824 ok(cf == tests[i].expected[j], "%u.%u: got %04x instead of %04x\n",
825 i, j, cf, tests[i].expected[j] );
826 if (cf != tests[i].expected[j]) break;
827 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
828 ok( !rendered, "%u.%u: formats %08x have been rendered\n", i, j, rendered );
829 data = GetClipboardData( cf );
830 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
831 if (cf == CF_LOCALE)
833 ok(data != NULL, "%u: CF_LOCALE no data\n", i);
834 ok( !rendered, "%u.%u: formats %08x have been rendered\n", i, j, rendered );
836 else
838 ok(!data, "%u: format %04x got data %p\n", i, cf, data);
839 ok( rendered == (1 << tests[i].format),
840 "%u.%u: formats %08x have been rendered\n", i, j, rendered );
841 /* try to render a second time */
842 data = GetClipboardData( cf );
843 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
844 ok( rendered == (1 << tests[i].format),
845 "%u.%u: formats %08x have been rendered\n", i, j, rendered );
848 if (!tests[i].expected[j])
850 cf = EnumClipboardFormats( cf );
851 ok(cf == 0, "%u: cf %04x\n", i, cf);
853 r = CloseClipboard();
854 ok(r, "%u: gle %d\n", i, GetLastError());
855 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
856 ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered );
859 r = OpenClipboard(NULL);
860 ok(r, "gle %d\n", GetLastError());
861 r = EmptyClipboard();
862 ok(r, "gle %d\n", GetLastError());
863 r = CloseClipboard();
864 ok(r, "gle %d\n", GetLastError());
865 DestroyWindow( hwnd );
868 static CRITICAL_SECTION clipboard_cs;
869 static HWND next_wnd;
870 static UINT wm_drawclipboard;
871 static UINT wm_clipboardupdate;
872 static UINT wm_destroyclipboard;
873 static UINT wm_renderformat;
874 static UINT nb_formats;
875 static BOOL cross_thread;
877 static LRESULT CALLBACK clipboard_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
879 LRESULT ret;
880 DWORD msg_flags = InSendMessageEx( NULL );
882 switch(msg) {
883 case WM_DRAWCLIPBOARD:
884 ok( msg_flags == (cross_thread ? ISMEX_NOTIFY : ISMEX_NOSEND),
885 "WM_DRAWCLIPBOARD wrong flags %x\n", msg_flags );
886 EnterCriticalSection(&clipboard_cs);
887 wm_drawclipboard++;
888 LeaveCriticalSection(&clipboard_cs);
889 break;
890 case WM_CHANGECBCHAIN:
891 ok( msg_flags == (cross_thread ? ISMEX_SEND : ISMEX_NOSEND),
892 "WM_CHANGECBCHAIN wrong flags %x\n", msg_flags );
893 if (next_wnd == (HWND)wp)
894 next_wnd = (HWND)lp;
895 else if (next_wnd)
896 SendMessageA(next_wnd, msg, wp, lp);
897 break;
898 case WM_DESTROYCLIPBOARD:
899 ok( msg_flags == (cross_thread ? ISMEX_SEND : ISMEX_NOSEND),
900 "WM_DESTROYCLIPBOARD wrong flags %x\n", msg_flags );
901 wm_destroyclipboard++;
902 ok( GetClipboardOwner() == hwnd, "WM_DESTROYCLIPBOARD owner %p\n", GetClipboardOwner() );
903 nb_formats = CountClipboardFormats();
904 break;
905 case WM_RENDERFORMAT:
906 ok( !wm_renderformat, "multiple WM_RENDERFORMAT %04x / %04lx\n", wm_renderformat, wp );
907 wm_renderformat = wp;
908 break;
909 case WM_CLIPBOARDUPDATE:
910 ok( msg_flags == ISMEX_NOSEND, "WM_CLIPBOARDUPDATE wrong flags %x\n", msg_flags );
911 EnterCriticalSection(&clipboard_cs);
912 wm_clipboardupdate++;
913 LeaveCriticalSection(&clipboard_cs);
914 break;
915 case WM_USER:
916 ChangeClipboardChain(hwnd, next_wnd);
917 PostQuitMessage(0);
918 break;
919 case WM_USER+1:
920 ret = wm_drawclipboard;
921 wm_drawclipboard = 0;
922 return ret;
923 case WM_USER+2:
924 ret = wm_clipboardupdate;
925 wm_clipboardupdate = 0;
926 return ret;
927 case WM_USER+3:
928 ret = wm_destroyclipboard;
929 wm_destroyclipboard = 0;
930 return ret;
931 case WM_USER+4:
932 ret = wm_renderformat;
933 wm_renderformat = 0;
934 return ret;
935 case WM_USER+5:
936 return nb_formats;
939 return DefWindowProcA(hwnd, msg, wp, lp);
942 static DWORD WINAPI clipboard_thread(void *param)
944 HWND ret, win = param;
945 BOOL r;
946 MSG msg;
947 HANDLE handle;
948 UINT count, fmt, formats, old_seq = 0, seq;
950 cross_thread = (GetWindowThreadProcessId( win, NULL ) != GetCurrentThreadId());
951 trace( "%s-threaded test\n", cross_thread ? "multi" : "single" );
953 if (pGetClipboardSequenceNumber) old_seq = pGetClipboardSequenceNumber();
955 EnterCriticalSection(&clipboard_cs);
956 SetLastError(0xdeadbeef);
957 next_wnd = SetClipboardViewer(win);
958 ok(GetLastError() == 0xdeadbeef, "GetLastError = %d\n", GetLastError());
959 LeaveCriticalSection(&clipboard_cs);
961 SetLastError( 0xdeadbeef );
962 ret = SetClipboardViewer( (HWND)0xdead );
963 ok( !ret, "SetClipboardViewer succeeded\n" );
964 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
965 SetLastError( 0xdeadbeef );
966 r = ChangeClipboardChain( win, (HWND)0xdead );
967 ok( !r, "ChangeClipboardChain succeeded\n" );
968 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
969 SetLastError( 0xdeadbeef );
970 r = ChangeClipboardChain( (HWND)0xdead, next_wnd );
971 ok( !r, "ChangeClipboardChain succeeded\n" );
972 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
974 if (pAddClipboardFormatListener)
976 r = pAddClipboardFormatListener(win);
977 ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError());
978 SetLastError( 0xdeadbeef );
979 r = pAddClipboardFormatListener( win );
980 ok( !r, "AddClipboardFormatListener succeeded\n" );
981 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
982 SetLastError( 0xdeadbeef );
983 r = pAddClipboardFormatListener( (HWND)0xdead );
984 ok( !r, "AddClipboardFormatListener succeeded\n" );
985 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
986 r = pAddClipboardFormatListener( GetDesktopWindow() );
987 ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError());
988 r = pRemoveClipboardFormatListener( GetDesktopWindow() );
989 ok( r, "RemoveClipboardFormatListener failed err %d\n", GetLastError());
992 if (pGetClipboardSequenceNumber)
994 seq = pGetClipboardSequenceNumber();
995 ok( seq == old_seq, "sequence changed\n" );
997 if (!cross_thread)
999 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1000 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1001 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1002 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1004 count = SendMessageA( win, WM_USER + 1, 0, 0 );
1005 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1006 count = SendMessageA( win, WM_USER+2, 0, 0 );
1007 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1008 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1009 ok( !fmt, "WM_RENDERFORMAT received\n" );
1011 SetLastError( 0xdeadbeef );
1012 r = OpenClipboard( (HWND)0xdead );
1013 ok( !r, "OpenClipboard succeeded\n" );
1014 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
1016 r = OpenClipboard(win);
1017 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1019 if (pGetClipboardSequenceNumber)
1021 seq = pGetClipboardSequenceNumber();
1022 ok( seq == old_seq, "sequence changed\n" );
1024 if (!cross_thread)
1026 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1027 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1028 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1029 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1031 count = SendMessageA( win, WM_USER+1, 0, 0 );
1032 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1033 count = SendMessageA( win, WM_USER+2, 0, 0 );
1034 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1035 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1036 ok( !fmt, "WM_RENDERFORMAT received\n" );
1038 r = EmptyClipboard();
1039 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
1041 if (pGetClipboardSequenceNumber)
1043 seq = pGetClipboardSequenceNumber();
1044 ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1045 old_seq = seq;
1047 if (!cross_thread)
1049 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1050 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1051 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1052 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1054 count = SendMessageA( win, WM_USER+1, 0, 0 );
1055 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1056 count = SendMessageA( win, WM_USER+2, 0, 0 );
1057 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1058 count = SendMessageA( win, WM_USER+3, 0, 0 );
1059 ok( !count, "WM_DESTROYCLIPBOARD received\n" );
1060 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1061 ok( !fmt, "WM_RENDERFORMAT received\n" );
1063 r = EmptyClipboard();
1064 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
1065 /* sequence changes again, even though it was already empty */
1066 if (pGetClipboardSequenceNumber)
1068 seq = pGetClipboardSequenceNumber();
1069 ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1070 old_seq = seq;
1072 if (!cross_thread)
1074 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1075 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1076 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1077 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1079 count = SendMessageA( win, WM_USER+1, 0, 0 );
1080 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1081 count = SendMessageA( win, WM_USER+2, 0, 0 );
1082 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1083 count = SendMessageA( win, WM_USER+3, 0, 0 );
1084 ok( count, "WM_DESTROYCLIPBOARD not received\n" );
1085 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1086 ok( !fmt, "WM_RENDERFORMAT received\n" );
1087 count = SendMessageA( win, WM_USER+5, 0, 0 );
1088 ok( !count, "wrong format count %u on WM_DESTROYCLIPBOARD\n", count );
1090 handle = SetClipboardData( CF_TEXT, create_textA() );
1091 ok(handle != 0, "SetClipboardData failed: %d\n", GetLastError());
1093 if (pGetClipboardSequenceNumber)
1095 seq = pGetClipboardSequenceNumber();
1096 todo_wine ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1097 old_seq = seq;
1099 if (!cross_thread)
1101 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1102 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1103 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1104 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1106 count = SendMessageA( win, WM_USER+1, 0, 0 );
1107 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1108 count = SendMessageA( win, WM_USER+2, 0, 0 );
1109 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1110 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1111 ok( !fmt, "WM_RENDERFORMAT received\n" );
1113 SetClipboardData( CF_UNICODETEXT, 0 );
1115 if (pGetClipboardSequenceNumber)
1117 seq = pGetClipboardSequenceNumber();
1118 todo_wine ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1119 old_seq = seq;
1121 if (!cross_thread)
1123 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1124 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1125 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1126 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1128 count = SendMessageA( win, WM_USER+1, 0, 0 );
1129 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1130 count = SendMessageA( win, WM_USER+2, 0, 0 );
1131 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1132 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1133 ok( !fmt, "WM_RENDERFORMAT received\n" );
1135 SetClipboardData( CF_UNICODETEXT, 0 ); /* same data again */
1137 if (pGetClipboardSequenceNumber)
1139 seq = pGetClipboardSequenceNumber();
1140 todo_wine ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1141 old_seq = seq;
1143 if (!cross_thread)
1145 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1146 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1147 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1148 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1150 count = SendMessageA( win, WM_USER+1, 0, 0 );
1151 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1152 count = SendMessageA( win, WM_USER+2, 0, 0 );
1153 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1154 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1155 ok( !fmt, "WM_RENDERFORMAT received\n" );
1157 ok( IsClipboardFormatAvailable( CF_TEXT ), "CF_TEXT available\n" );
1158 ok( IsClipboardFormatAvailable( CF_UNICODETEXT ), "CF_UNICODETEXT available\n" );
1159 ok( !IsClipboardFormatAvailable( CF_OEMTEXT ), "CF_OEMTEXT available\n" );
1161 EnterCriticalSection(&clipboard_cs);
1162 r = CloseClipboard();
1163 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1164 LeaveCriticalSection(&clipboard_cs);
1166 if (pGetClipboardSequenceNumber)
1168 seq = pGetClipboardSequenceNumber();
1169 todo_wine ok( (int)(seq - old_seq) == 2, "sequence diff %d\n", seq - old_seq );
1170 old_seq = seq;
1172 if (!cross_thread)
1174 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1175 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1176 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1177 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1179 count = SendMessageA( win, WM_USER+1, 0, 0 );
1180 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1181 count = SendMessageA( win, WM_USER+2, 0, 0 );
1182 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1183 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1184 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1186 r = OpenClipboard(win);
1187 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1189 if (pGetClipboardSequenceNumber)
1191 seq = pGetClipboardSequenceNumber();
1192 ok( seq == old_seq, "sequence changed\n" );
1194 if (!cross_thread)
1196 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1197 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1198 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1200 count = SendMessageA( win, WM_USER+1, 0, 0 );
1201 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1202 count = SendMessageA( win, WM_USER+2, 0, 0 );
1203 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1204 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1205 ok( !fmt, "WM_RENDERFORMAT received\n" );
1207 ok( IsClipboardFormatAvailable( CF_TEXT ), "CF_TEXT available\n" );
1208 ok( IsClipboardFormatAvailable( CF_UNICODETEXT ), "CF_UNICODETEXT available\n" );
1209 ok( IsClipboardFormatAvailable( CF_OEMTEXT ), "CF_OEMTEXT available\n" );
1211 ok( GetClipboardOwner() == win, "wrong owner %p\n", GetClipboardOwner());
1212 handle = GetClipboardData( CF_UNICODETEXT );
1213 ok( !handle, "got data for CF_UNICODETEXT\n" );
1214 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1215 ok( fmt == CF_UNICODETEXT, "WM_RENDERFORMAT received %04x\n", fmt );
1217 handle = GetClipboardData( CF_OEMTEXT );
1218 ok( !handle, "got data for CF_OEMTEXT\n" );
1219 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1220 ok( fmt == CF_UNICODETEXT, "WM_RENDERFORMAT received %04x\n", fmt );
1222 SetClipboardData( CF_WAVE, 0 );
1223 if (pGetClipboardSequenceNumber)
1225 seq = pGetClipboardSequenceNumber();
1226 todo_wine ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1227 old_seq = seq;
1229 if (!cross_thread)
1231 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1232 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1233 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1234 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1236 count = SendMessageA( win, WM_USER+1, 0, 0 );
1237 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1238 count = SendMessageA( win, WM_USER+2, 0, 0 );
1239 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1240 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1241 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1243 r = CloseClipboard();
1244 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1245 if (pGetClipboardSequenceNumber)
1247 /* no synthesized format, so CloseClipboard doesn't change the sequence */
1248 seq = pGetClipboardSequenceNumber();
1249 todo_wine ok( seq == old_seq, "sequence changed\n" );
1250 old_seq = seq;
1252 if (!cross_thread)
1254 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1255 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1256 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1257 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1259 count = SendMessageA( win, WM_USER+1, 0, 0 );
1260 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1261 count = SendMessageA( win, WM_USER+2, 0, 0 );
1262 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1263 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1264 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1266 r = OpenClipboard(win);
1267 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1268 r = CloseClipboard();
1269 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1270 /* nothing changed */
1271 if (pGetClipboardSequenceNumber)
1273 seq = pGetClipboardSequenceNumber();
1274 ok( seq == old_seq, "sequence changed\n" );
1276 if (!cross_thread)
1278 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1279 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1280 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1281 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1283 count = SendMessageA( win, WM_USER+1, 0, 0 );
1284 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1285 count = SendMessageA( win, WM_USER+2, 0, 0 );
1286 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1287 count = SendMessageA( win, WM_USER+3, 0, 0 );
1288 ok( !count, "WM_DESTROYCLIPBOARD received\n" );
1289 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1290 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1292 formats = CountClipboardFormats();
1293 r = OpenClipboard(0);
1294 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1295 r = EmptyClipboard();
1296 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
1297 r = CloseClipboard();
1298 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1300 if (!cross_thread)
1302 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1303 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1304 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1305 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1307 count = SendMessageA( win, WM_USER+1, 0, 0 );
1308 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1309 count = SendMessageA( win, WM_USER+2, 0, 0 );
1310 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1311 count = SendMessageA( win, WM_USER+3, 0, 0 );
1312 ok( count == 1, "WM_DESTROYCLIPBOARD not received\n" );
1313 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1314 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1315 count = SendMessageA( win, WM_USER+5, 0, 0 );
1316 ok( count == formats, "wrong format count %u on WM_DESTROYCLIPBOARD\n", count );
1318 r = OpenClipboard(win);
1319 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1320 SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_FIXED, 1 ));
1321 if (pGetClipboardSequenceNumber)
1323 seq = pGetClipboardSequenceNumber();
1324 ok( (int)(seq - old_seq) == 2, "sequence diff %d\n", seq - old_seq );
1325 old_seq = seq;
1327 if (!cross_thread)
1329 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1330 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1331 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1332 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1334 count = SendMessageA( win, WM_USER+1, 0, 0 );
1335 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1336 count = SendMessageA( win, WM_USER+2, 0, 0 );
1337 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1338 count = SendMessageA( win, WM_USER+3, 0, 0 );
1339 ok( !count, "WM_DESTROYCLIPBOARD received\n" );
1340 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1341 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1343 EnterCriticalSection(&clipboard_cs);
1344 r = CloseClipboard();
1345 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1346 LeaveCriticalSection(&clipboard_cs);
1348 if (pGetClipboardSequenceNumber)
1350 seq = pGetClipboardSequenceNumber();
1351 todo_wine ok( seq == old_seq, "sequence changed\n" );
1352 old_seq = seq;
1354 if (!cross_thread)
1356 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1357 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1358 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1359 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1361 count = SendMessageA( win, WM_USER+1, 0, 0 );
1362 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1363 count = SendMessageA( win, WM_USER+2, 0, 0 );
1364 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1365 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1366 ok( !fmt, "WM_RENDERFORMAT received\n" );
1368 run_process( "grab_clipboard 0" );
1370 if (pGetClipboardSequenceNumber)
1372 seq = pGetClipboardSequenceNumber();
1373 ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1374 old_seq = seq;
1376 if (!cross_thread)
1378 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1379 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1380 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1381 /* in this case we get a cross-thread WM_DRAWCLIPBOARD */
1382 cross_thread = TRUE;
1383 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1384 cross_thread = FALSE;
1386 count = SendMessageA( win, WM_USER+1, 0, 0 );
1387 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1388 count = SendMessageA( win, WM_USER+2, 0, 0 );
1389 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1390 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1391 ok( !fmt, "WM_RENDERFORMAT received\n" );
1393 r = OpenClipboard(0);
1394 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1395 SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_FIXED, 1 ));
1396 if (pGetClipboardSequenceNumber)
1398 seq = pGetClipboardSequenceNumber();
1399 todo_wine ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1400 old_seq = seq;
1402 if (!cross_thread)
1404 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1405 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1406 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1407 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1409 count = SendMessageA( win, WM_USER+1, 0, 0 );
1410 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1411 count = SendMessageA( win, WM_USER+2, 0, 0 );
1412 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1413 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1414 ok( !fmt, "WM_RENDERFORMAT received\n" );
1416 EnterCriticalSection(&clipboard_cs);
1417 r = CloseClipboard();
1418 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1419 LeaveCriticalSection(&clipboard_cs);
1421 if (pGetClipboardSequenceNumber)
1423 seq = pGetClipboardSequenceNumber();
1424 todo_wine ok( seq == old_seq, "sequence changed\n" );
1425 old_seq = seq;
1427 if (!cross_thread)
1429 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD received\n" );
1430 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1431 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1432 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1434 count = SendMessageA( win, WM_USER+1, 0, 0 );
1435 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1436 count = SendMessageA( win, WM_USER+2, 0, 0 );
1437 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1438 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1439 ok( !fmt, "WM_RENDERFORMAT received\n" );
1441 run_process( "grab_clipboard 1" );
1443 if (pGetClipboardSequenceNumber)
1445 seq = pGetClipboardSequenceNumber();
1446 todo_wine_if (!cross_thread)
1447 ok( (int)(seq - old_seq) == 2, "sequence diff %d\n", seq - old_seq );
1448 old_seq = seq;
1450 if (!cross_thread)
1452 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1453 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1454 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1455 /* in this case we get a cross-thread WM_DRAWCLIPBOARD */
1456 cross_thread = TRUE;
1457 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1458 cross_thread = FALSE;
1460 count = SendMessageA( win, WM_USER+1, 0, 0 );
1461 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1462 count = SendMessageA( win, WM_USER+2, 0, 0 );
1463 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1464 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1465 ok( !fmt, "WM_RENDERFORMAT received\n" );
1467 r = OpenClipboard(0);
1468 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1469 SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_FIXED, 1 ));
1470 if (pGetClipboardSequenceNumber)
1472 seq = pGetClipboardSequenceNumber();
1473 todo_wine ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1474 old_seq = seq;
1476 if (!cross_thread)
1478 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1479 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1480 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1481 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1483 count = SendMessageA( win, WM_USER+1, 0, 0 );
1484 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1485 count = SendMessageA( win, WM_USER+2, 0, 0 );
1486 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1487 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1488 ok( !fmt, "WM_RENDERFORMAT received\n" );
1490 EnterCriticalSection(&clipboard_cs);
1491 r = CloseClipboard();
1492 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1493 LeaveCriticalSection(&clipboard_cs);
1495 if (pGetClipboardSequenceNumber)
1497 seq = pGetClipboardSequenceNumber();
1498 todo_wine ok( seq == old_seq, "sequence changed\n" );
1499 old_seq = seq;
1501 if (!cross_thread)
1503 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1504 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1505 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1506 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1508 count = SendMessageA( win, WM_USER+1, 0, 0 );
1509 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1510 count = SendMessageA( win, WM_USER+2, 0, 0 );
1511 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1512 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1513 ok( !fmt, "WM_RENDERFORMAT received\n" );
1515 r = PostMessageA(win, WM_USER, 0, 0);
1516 ok(r, "PostMessage failed: %d\n", GetLastError());
1518 if (pRemoveClipboardFormatListener)
1520 r = pRemoveClipboardFormatListener(win);
1521 ok( r, "RemoveClipboardFormatListener failed err %d\n", GetLastError());
1522 SetLastError( 0xdeadbeef );
1523 r = pRemoveClipboardFormatListener(win);
1524 ok( !r, "RemoveClipboardFormatListener succeeded\n" );
1525 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1526 SetLastError( 0xdeadbeef );
1527 r = pRemoveClipboardFormatListener( (HWND)0xdead );
1528 ok( !r, "RemoveClipboardFormatListener succeeded\n" );
1529 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
1531 return 0;
1534 static void test_messages(void)
1536 WNDCLASSA cls;
1537 HWND win;
1538 MSG msg;
1539 HANDLE thread;
1540 DWORD tid;
1542 InitializeCriticalSection(&clipboard_cs);
1544 memset(&cls, 0, sizeof(cls));
1545 cls.lpfnWndProc = clipboard_wnd_proc;
1546 cls.hInstance = GetModuleHandleA(NULL);
1547 cls.lpszClassName = "clipboard_test";
1548 RegisterClassA(&cls);
1550 win = CreateWindowA("clipboard_test", NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0);
1551 ok(win != NULL, "CreateWindow failed: %d\n", GetLastError());
1553 thread = CreateThread(NULL, 0, clipboard_thread, (void*)win, 0, &tid);
1554 ok(thread != NULL, "CreateThread failed: %d\n", GetLastError());
1556 while(GetMessageA(&msg, NULL, 0, 0))
1558 ok( msg.message != WM_DRAWCLIPBOARD, "WM_DRAWCLIPBOARD was posted\n" );
1559 TranslateMessage(&msg);
1560 DispatchMessageA(&msg);
1563 ok(WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1564 CloseHandle(thread);
1566 DestroyWindow( win );
1568 /* same tests again but inside a single thread */
1570 win = CreateWindowA( "clipboard_test", NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0 );
1571 ok( win != NULL, "CreateWindow failed: %d\n", GetLastError() );
1573 clipboard_thread( win );
1574 DestroyWindow( win );
1576 UnregisterClassA("clipboard_test", GetModuleHandleA(NULL));
1577 DeleteCriticalSection(&clipboard_cs);
1580 static BOOL is_moveable( HANDLE handle )
1582 void *ptr = GlobalLock( handle );
1583 if (ptr) GlobalUnlock( handle );
1584 return ptr && ptr != handle;
1587 static BOOL is_fixed( HANDLE handle )
1589 void *ptr = GlobalLock( handle );
1590 if (ptr) GlobalUnlock( handle );
1591 return ptr && ptr == handle;
1594 static BOOL is_freed( HANDLE handle )
1596 void *ptr = GlobalLock( handle );
1597 if (ptr) GlobalUnlock( handle );
1598 return !ptr;
1601 static UINT format_id;
1602 static HBITMAP bitmap, bitmap2;
1603 static HPALETTE palette;
1604 static HPEN pen;
1605 static const LOGPALETTE logpalette = { 0x300, 1 };
1607 static void test_handles( HWND hwnd )
1609 HGLOBAL h, htext, htext2;
1610 BOOL r;
1611 HANDLE data;
1612 DWORD process;
1613 BOOL is_owner = (GetWindowThreadProcessId( hwnd, &process ) && process == GetCurrentProcessId());
1615 trace( "hwnd %p\n", hwnd );
1616 htext = create_textA();
1617 htext2 = create_textA();
1618 bitmap = CreateBitmap( 10, 10, 1, 1, NULL );
1619 bitmap2 = CreateBitmap( 10, 10, 1, 1, NULL );
1620 palette = CreatePalette( &logpalette );
1621 pen = CreatePen( PS_SOLID, 1, 0 );
1623 r = OpenClipboard( hwnd );
1624 ok( r, "gle %d\n", GetLastError() );
1625 r = EmptyClipboard();
1626 ok( r, "gle %d\n", GetLastError() );
1628 h = SetClipboardData( CF_TEXT, htext );
1629 ok( h == htext, "got %p\n", h );
1630 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1631 h = SetClipboardData( format_id, htext2 );
1632 ok( h == htext2, "got %p\n", h );
1633 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1634 h = SetClipboardData( CF_BITMAP, bitmap );
1635 ok( h == bitmap, "got %p\n", h );
1636 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1637 h = SetClipboardData( CF_PALETTE, palette );
1638 ok( h == palette, "got %p\n", h );
1639 ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
1640 /* setting custom GDI formats crashes on 64-bit Windows */
1641 if (!is_win64)
1643 h = SetClipboardData( CF_GDIOBJFIRST + 1, bitmap2 );
1644 ok( h == bitmap2, "got %p\n", h );
1645 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1646 h = SetClipboardData( CF_GDIOBJFIRST + 2, pen );
1647 ok( h == pen, "got %p\n", h );
1648 ok( GetObjectType( h ) == OBJ_PEN, "expected pen %p\n", h );
1651 data = GetClipboardData( CF_TEXT );
1652 ok( data == htext, "wrong data %p\n", data );
1653 ok( is_moveable( data ), "expected moveable mem %p\n", data );
1655 data = GetClipboardData( format_id );
1656 ok( data == htext2, "wrong data %p, cf %08x\n", data, format_id );
1657 ok( is_moveable( data ), "expected moveable mem %p\n", data );
1659 r = CloseClipboard();
1660 ok( r, "gle %d\n", GetLastError() );
1662 /* data handles are still valid */
1663 ok( is_moveable( htext ), "expected moveable mem %p\n", htext );
1664 ok( is_moveable( htext2 ), "expected moveable mem %p\n", htext );
1665 ok( GetObjectType( bitmap ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap );
1666 ok( GetObjectType( bitmap2 ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap2 );
1667 ok( GetObjectType( palette ) == OBJ_PAL, "expected palette %p\n", palette );
1668 ok( GetObjectType( pen ) == OBJ_PEN, "expected pen %p\n", pen );
1670 r = OpenClipboard( hwnd );
1671 ok( r, "gle %d\n", GetLastError() );
1673 /* and now they are freed, unless we are the owner */
1674 if (!is_owner)
1676 todo_wine ok( is_freed( htext ), "expected freed mem %p\n", htext );
1677 todo_wine ok( is_freed( htext2 ), "expected freed mem %p\n", htext );
1679 data = GetClipboardData( CF_TEXT );
1680 todo_wine ok( is_fixed( data ), "expected fixed mem %p\n", data );
1682 data = GetClipboardData( format_id );
1683 todo_wine ok( is_fixed( data ), "expected fixed mem %p\n", data );
1685 else
1687 ok( is_moveable( htext ), "expected moveable mem %p\n", htext );
1688 ok( is_moveable( htext2 ), "expected moveable mem %p\n", htext );
1690 data = GetClipboardData( CF_TEXT );
1691 ok( data == htext, "wrong data %p\n", data );
1693 data = GetClipboardData( format_id );
1694 ok( data == htext2, "wrong data %p, cf %08x\n", data, format_id );
1697 data = GetClipboardData( CF_OEMTEXT );
1698 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1699 data = GetClipboardData( CF_UNICODETEXT );
1700 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1701 data = GetClipboardData( CF_LOCALE );
1702 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1703 data = GetClipboardData( CF_BITMAP );
1704 ok( data == bitmap, "expected bitmap %p\n", data );
1705 data = GetClipboardData( CF_PALETTE );
1706 ok( data == palette, "expected palette %p\n", data );
1707 if (!is_win64)
1709 data = GetClipboardData( CF_GDIOBJFIRST + 1 );
1710 ok( data == bitmap2, "expected bitmap2 %p\n", data );
1711 data = GetClipboardData( CF_GDIOBJFIRST + 2 );
1712 ok( data == pen, "expected pen %p\n", data );
1714 data = GetClipboardData( CF_DIB );
1715 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1716 data = GetClipboardData( CF_DIBV5 );
1717 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1719 ok( GetObjectType( bitmap ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap );
1720 ok( GetObjectType( bitmap2 ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap2 );
1721 ok( GetObjectType( palette ) == OBJ_PAL, "expected palette %p\n", palette );
1722 ok( GetObjectType( pen ) == OBJ_PEN, "expected pen %p\n", pen );
1724 r = EmptyClipboard();
1725 ok( r, "gle %d\n", GetLastError() );
1727 /* w2003, w2008 don't seem to free the data here */
1728 ok( is_freed( htext ) || broken( !is_freed( htext )), "expected freed mem %p\n", htext );
1729 ok( is_freed( htext2 ) || broken( !is_freed( htext2 )), "expected freed mem %p\n", htext );
1730 ok( !GetObjectType( bitmap ), "expected freed handle %p\n", bitmap );
1731 ok( !GetObjectType( palette ), "expected freed handle %p\n", palette );
1732 ok( GetObjectType( bitmap2 ) == OBJ_BITMAP, "expected bitmap2 %p\n", bitmap2 );
1733 ok( GetObjectType( pen ) == OBJ_PEN, "expected pen %p\n", pen );
1735 r = CloseClipboard();
1736 ok( r, "gle %d\n", GetLastError() );
1739 static DWORD WINAPI test_handles_thread( void *arg )
1741 trace( "running from different thread\n" );
1742 test_handles( (HWND)arg );
1743 return 0;
1746 static DWORD WINAPI test_handles_thread2( void *arg )
1748 BOOL r;
1749 HANDLE h;
1750 char *ptr;
1752 r = OpenClipboard( 0 );
1753 ok( r, "gle %d\n", GetLastError() );
1754 h = GetClipboardData( CF_TEXT );
1755 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1756 ptr = GlobalLock( h );
1757 if (ptr) ok( !strcmp( "test", ptr ), "wrong data '%.5s'\n", ptr );
1758 GlobalUnlock( h );
1759 h = GetClipboardData( format_id );
1760 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1761 ptr = GlobalLock( h );
1762 if (ptr) ok( !strcmp( "test", ptr ), "wrong data '%.5s'\n", ptr );
1763 GlobalUnlock( h );
1764 h = GetClipboardData( CF_BITMAP );
1765 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1766 ok( h == bitmap, "different bitmap %p / %p\n", h, bitmap );
1767 trace( "bitmap %p\n", h );
1768 h = GetClipboardData( CF_PALETTE );
1769 ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
1770 ok( h == palette, "different palette %p / %p\n", h, palette );
1771 trace( "palette %p\n", h );
1772 if (!is_win64)
1774 h = GetClipboardData( CF_GDIOBJFIRST + 1 );
1775 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1776 ok( h == bitmap2, "different bitmap %p / %p\n", h, bitmap2 );
1777 trace( "bitmap2 %p\n", h );
1778 h = GetClipboardData( CF_GDIOBJFIRST + 2 );
1779 ok( GetObjectType( h ) == OBJ_PEN, "expected pen %p\n", h );
1780 ok( h == pen, "different pen %p / %p\n", h, pen );
1781 trace( "pen %p\n", h );
1783 h = GetClipboardData( CF_DIB );
1784 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1785 h = GetClipboardData( CF_DIBV5 );
1786 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1787 r = CloseClipboard();
1788 ok( r, "gle %d\n", GetLastError() );
1789 return 0;
1792 static void test_handles_process( const char *str )
1794 BOOL r;
1795 HANDLE h;
1796 char *ptr;
1798 format_id = RegisterClipboardFormatA( "my_cool_clipboard_format" );
1799 r = OpenClipboard( 0 );
1800 ok( r, "gle %d\n", GetLastError() );
1801 h = GetClipboardData( CF_TEXT );
1802 todo_wine_if( !h ) ok( is_fixed( h ), "expected fixed mem %p\n", h );
1803 ptr = GlobalLock( h );
1804 if (ptr) todo_wine ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr );
1805 GlobalUnlock( h );
1806 h = GetClipboardData( format_id );
1807 todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h );
1808 ptr = GlobalLock( h );
1809 if (ptr) ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr );
1810 GlobalUnlock( h );
1811 h = GetClipboardData( CF_BITMAP );
1812 todo_wine ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1813 trace( "bitmap %p\n", h );
1814 h = GetClipboardData( CF_PALETTE );
1815 todo_wine ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
1816 trace( "palette %p\n", h );
1817 h = GetClipboardData( CF_GDIOBJFIRST + 1 );
1818 ok( !GetObjectType( h ), "expected invalid %p\n", h );
1819 trace( "bitmap2 %p\n", h );
1820 h = GetClipboardData( CF_GDIOBJFIRST + 2 );
1821 ok( !GetObjectType( h ), "expected invalid %p\n", h );
1822 trace( "pen %p\n", h );
1823 h = GetClipboardData( CF_DIB );
1824 todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h );
1825 h = GetClipboardData( CF_DIBV5 );
1826 todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h );
1827 r = CloseClipboard();
1828 ok( r, "gle %d\n", GetLastError() );
1831 static void test_data_handles(void)
1833 BOOL r;
1834 HANDLE h;
1835 HWND hwnd = CreateWindowA( "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL );
1837 ok( hwnd != 0, "window creation failed\n" );
1838 format_id = RegisterClipboardFormatA( "my_cool_clipboard_format" );
1839 test_handles( 0 );
1840 test_handles( GetDesktopWindow() );
1841 test_handles( hwnd );
1842 run_thread( test_handles_thread, hwnd, __LINE__ );
1844 bitmap = CreateBitmap( 10, 10, 1, 1, NULL );
1845 bitmap2 = CreateBitmap( 10, 10, 1, 1, NULL );
1846 palette = CreatePalette( &logpalette );
1847 pen = CreatePen( PS_SOLID, 1, 0 );
1849 r = OpenClipboard( hwnd );
1850 ok( r, "gle %d\n", GetLastError() );
1851 r = EmptyClipboard();
1852 ok( r, "gle %d\n", GetLastError() );
1853 h = SetClipboardData( CF_TEXT, create_textA() );
1854 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1855 h = SetClipboardData( format_id, create_textA() );
1856 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1857 h = SetClipboardData( CF_BITMAP, bitmap );
1858 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1859 h = SetClipboardData( CF_PALETTE, palette );
1860 ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
1861 if (!is_win64)
1863 h = SetClipboardData( CF_GDIOBJFIRST + 1, bitmap2 );
1864 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1865 h = SetClipboardData( CF_GDIOBJFIRST + 2, pen );
1866 ok( GetObjectType( h ) == OBJ_PEN, "expected pen %p\n", h );
1868 r = CloseClipboard();
1869 ok( r, "gle %d\n", GetLastError() );
1871 run_thread( test_handles_thread2, 0, __LINE__ );
1872 run_process( "handles test" );
1874 r = OpenClipboard( hwnd );
1875 ok( r, "gle %d\n", GetLastError() );
1876 h = GetClipboardData( CF_TEXT );
1877 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1878 h = GetClipboardData( format_id );
1879 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1880 r = EmptyClipboard();
1881 ok( r, "gle %d\n", GetLastError() );
1882 r = CloseClipboard();
1883 ok( r, "gle %d\n", GetLastError() );
1885 DestroyWindow( hwnd );
1888 static void test_GetUpdatedClipboardFormats(void)
1890 BOOL r;
1891 UINT count, formats[256];
1893 if (!pGetUpdatedClipboardFormats)
1895 win_skip( "GetUpdatedClipboardFormats not supported\n" );
1896 return;
1899 count = 0xdeadbeef;
1900 r = pGetUpdatedClipboardFormats( NULL, 0, &count );
1901 ok( r, "gle %d\n", GetLastError() );
1902 ok( !count, "wrong count %u\n", count );
1904 count = 0xdeadbeef;
1905 r = pGetUpdatedClipboardFormats( NULL, 256, &count );
1906 ok( r, "gle %d\n", GetLastError() );
1907 ok( !count, "wrong count %u\n", count );
1909 SetLastError( 0xdeadbeef );
1910 r = pGetUpdatedClipboardFormats( formats, 256, NULL );
1911 ok( !r, "succeeded\n" );
1912 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
1914 count = 0xdeadbeef;
1915 r = pGetUpdatedClipboardFormats( formats, 256, &count );
1916 ok( r, "gle %d\n", GetLastError() );
1917 ok( !count, "wrong count %u\n", count );
1919 r = OpenClipboard( 0 );
1920 ok( r, "gle %d\n", GetLastError() );
1921 r = EmptyClipboard();
1922 ok( r, "gle %d\n", GetLastError() );
1924 count = 0xdeadbeef;
1925 r = pGetUpdatedClipboardFormats( formats, 256, &count );
1926 ok( r, "gle %d\n", GetLastError() );
1927 ok( !count, "wrong count %u\n", count );
1929 SetClipboardData( CF_UNICODETEXT, 0 );
1931 count = 0xdeadbeef;
1932 memset( formats, 0xcc, sizeof(formats) );
1933 r = pGetUpdatedClipboardFormats( formats, 256, &count );
1934 ok( r, "gle %d\n", GetLastError() );
1935 ok( count == 1, "wrong count %u\n", count );
1936 ok( formats[0] == CF_UNICODETEXT, "wrong format %u\n", formats[0] );
1937 ok( formats[1] == 0xcccccccc, "wrong format %u\n", formats[1] );
1939 SetClipboardData( CF_TEXT, 0 );
1940 count = 0xdeadbeef;
1941 memset( formats, 0xcc, sizeof(formats) );
1942 r = pGetUpdatedClipboardFormats( formats, 256, &count );
1943 ok( r, "gle %d\n", GetLastError() );
1944 ok( count == 2, "wrong count %u\n", count );
1945 ok( formats[0] == CF_UNICODETEXT, "wrong format %u\n", formats[0] );
1946 ok( formats[1] == CF_TEXT, "wrong format %u\n", formats[1] );
1947 ok( formats[2] == 0xcccccccc, "wrong format %u\n", formats[2] );
1949 SetLastError( 0xdeadbeef );
1950 count = 0xdeadbeef;
1951 r = pGetUpdatedClipboardFormats( formats, 0, &count );
1952 ok( !r, "succeeded\n" );
1953 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %u\n", GetLastError() );
1954 ok( count == 2, "wrong count %u\n", count );
1956 SetLastError( 0xdeadbeef );
1957 count = 0xdeadbeef;
1958 r = pGetUpdatedClipboardFormats( formats, 1, &count );
1959 ok( !r, "succeeded\n" );
1960 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %u\n", GetLastError() );
1961 ok( count == 2, "wrong count %u\n", count );
1963 r = CloseClipboard();
1964 ok( r, "gle %d\n", GetLastError() );
1966 count = 0xdeadbeef;
1967 memset( formats, 0xcc, sizeof(formats) );
1968 r = pGetUpdatedClipboardFormats( formats, 256, &count );
1969 ok( r, "gle %d\n", GetLastError() );
1970 ok( count == 4, "wrong count %u\n", count );
1971 ok( formats[0] == CF_UNICODETEXT, "wrong format %u\n", formats[0] );
1972 ok( formats[1] == CF_TEXT, "wrong format %u\n", formats[1] );
1973 ok( formats[2] == CF_LOCALE, "wrong format %u\n", formats[2] );
1974 ok( formats[3] == CF_OEMTEXT, "wrong format %u\n", formats[3] );
1975 ok( formats[4] == 0xcccccccc, "wrong format %u\n", formats[4] );
1977 count = 0xdeadbeef;
1978 memset( formats, 0xcc, sizeof(formats) );
1979 r = pGetUpdatedClipboardFormats( formats, 2, &count );
1980 ok( !r, "gle %d\n", GetLastError() );
1981 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %u\n", GetLastError() );
1982 ok( count == 4, "wrong count %u\n", count );
1983 ok( formats[0] == 0xcccccccc, "wrong format %u\n", formats[0] );
1985 count = 0xdeadbeef;
1986 r = pGetUpdatedClipboardFormats( NULL, 256, &count );
1987 ok( !r, "gle %d\n", GetLastError() );
1988 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
1989 ok( count == 4, "wrong count %u\n", count );
1991 count = 0xdeadbeef;
1992 r = pGetUpdatedClipboardFormats( NULL, 256, &count );
1993 ok( !r, "gle %d\n", GetLastError() );
1994 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
1995 ok( count == 4, "wrong count %u\n", count );
1998 START_TEST(clipboard)
2000 char **argv;
2001 int argc = winetest_get_mainargs( &argv );
2002 HMODULE mod = GetModuleHandleA( "user32" );
2004 argv0 = argv[0];
2005 pAddClipboardFormatListener = (void *)GetProcAddress( mod, "AddClipboardFormatListener" );
2006 pRemoveClipboardFormatListener = (void *)GetProcAddress( mod, "RemoveClipboardFormatListener" );
2007 pGetClipboardSequenceNumber = (void *)GetProcAddress( mod, "GetClipboardSequenceNumber" );
2008 pGetUpdatedClipboardFormats = (void *)GetProcAddress( mod, "GetUpdatedClipboardFormats" );
2010 if (argc == 4 && !strcmp( argv[2], "set_clipboard_data" ))
2012 set_clipboard_data_process( atoi( argv[3] ));
2013 return;
2015 if (argc == 4 && !strcmp( argv[2], "grab_clipboard" ))
2017 grab_clipboard_process( atoi( argv[3] ));
2018 return;
2020 if (argc == 4 && !strcmp( argv[2], "handles" ))
2022 test_handles_process( argv[3] );
2023 return;
2026 test_RegisterClipboardFormatA();
2027 test_ClipboardOwner();
2028 test_synthesized();
2029 test_messages();
2030 test_data_handles();
2031 test_GetUpdatedClipboardFormats();