user32: Cache clipboard data on the client side.
[wine.git] / dlls / user32 / tests / clipboard.c
blob90e1aaad13a50ebe754bca475aa21f0ac957bca8
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 int thread_from_line;
35 static char *argv0;
37 static DWORD WINAPI open_clipboard_thread(LPVOID arg)
39 HWND hWnd = arg;
40 ok(OpenClipboard(hWnd), "%u: OpenClipboard failed\n", thread_from_line);
41 return 0;
44 static DWORD WINAPI empty_clipboard_thread(LPVOID arg)
46 SetLastError( 0xdeadbeef );
47 ok(!EmptyClipboard(), "%u: EmptyClipboard succeeded\n", thread_from_line );
48 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
49 thread_from_line, GetLastError());
50 return 0;
53 static DWORD WINAPI open_and_empty_clipboard_thread(LPVOID arg)
55 HWND hWnd = arg;
56 ok(OpenClipboard(hWnd), "%u: OpenClipboard failed\n", thread_from_line);
57 ok(EmptyClipboard(), "%u: EmptyClipboard failed\n", thread_from_line );
58 return 0;
61 static DWORD WINAPI open_and_empty_clipboard_win_thread(LPVOID arg)
63 HWND hwnd = CreateWindowA( "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL );
64 ok(OpenClipboard(hwnd), "%u: OpenClipboard failed\n", thread_from_line);
65 ok(EmptyClipboard(), "%u: EmptyClipboard failed\n", thread_from_line );
66 return 0;
69 static DWORD WINAPI set_clipboard_data_thread(LPVOID arg)
71 HWND hwnd = arg;
72 HANDLE ret;
74 SetLastError( 0xdeadbeef );
75 if (GetClipboardOwner() == hwnd)
77 SetClipboardData( CF_WAVE, 0 );
78 ok( IsClipboardFormatAvailable( CF_WAVE ), "%u: SetClipboardData failed\n", thread_from_line );
79 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
80 ok( ret != 0, "%u: SetClipboardData failed err %u\n", thread_from_line, GetLastError() );
81 SetLastError( 0xdeadbeef );
82 ret = GetClipboardData( CF_WAVE );
83 ok( !ret, "%u: GetClipboardData succeeded\n", thread_from_line );
84 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
85 thread_from_line, GetLastError());
87 else
89 SetClipboardData( CF_WAVE, 0 );
90 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
91 thread_from_line, GetLastError());
92 ok( !IsClipboardFormatAvailable( CF_WAVE ), "%u: SetClipboardData succeeded\n", thread_from_line );
93 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
94 ok( !ret, "%u: SetClipboardData succeeded\n", thread_from_line );
95 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
96 thread_from_line, GetLastError());
98 return 0;
101 static void set_clipboard_data_process( int arg )
103 HANDLE ret;
105 SetLastError( 0xdeadbeef );
106 if (arg)
108 ok( IsClipboardFormatAvailable( CF_WAVE ), "process %u: CF_WAVE not available\n", arg );
109 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
110 ok( ret != 0, "process %u: SetClipboardData failed err %u\n", arg, GetLastError() );
112 else
114 SetClipboardData( CF_WAVE, 0 );
115 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "process %u: wrong error %u\n",
116 arg, GetLastError());
117 ok( !IsClipboardFormatAvailable( CF_WAVE ), "process %u: SetClipboardData succeeded\n", arg );
118 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
119 ok( !ret, "process %u: SetClipboardData succeeded\n", arg );
120 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "process %u: wrong error %u\n",
121 arg, GetLastError());
125 static void grab_clipboard_process( int arg )
127 BOOL ret;
129 SetLastError( 0xdeadbeef );
130 ret = OpenClipboard( 0 );
131 ok( ret, "OpenClipboard failed\n" );
132 ret = EmptyClipboard();
133 ok( ret, "EmptyClipboard failed\n" );
134 if (arg)
136 HANDLE ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
137 ok( ret != 0, "process %u: SetClipboardData failed err %u\n", arg, GetLastError() );
141 static void run_thread( LPTHREAD_START_ROUTINE func, void *arg, int line )
143 DWORD ret;
144 HANDLE thread;
146 thread_from_line = line;
147 thread = CreateThread(NULL, 0, func, arg, 0, NULL);
148 ok(thread != NULL, "%u: CreateThread failed with error %d\n", line, GetLastError());
149 for (;;)
151 ret = MsgWaitForMultipleObjectsEx( 1, &thread, 1000, QS_ALLINPUT, 0 );
152 if (ret == WAIT_OBJECT_0 + 1)
154 MSG msg;
155 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
157 else break;
159 ok(ret == WAIT_OBJECT_0, "%u: expected WAIT_OBJECT_0, got %u\n", line, ret);
160 CloseHandle(thread);
163 static void run_process( const char *args )
165 char cmd[MAX_PATH];
166 PROCESS_INFORMATION info;
167 STARTUPINFOA startup;
169 sprintf( cmd, "%s clipboard %s", argv0, args );
170 memset( &startup, 0, sizeof(startup) );
171 startup.cb = sizeof(startup);
172 ok( CreateProcessA( NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info ),
173 "CreateProcess %s failed\n", cmd );
175 winetest_wait_child_process( info.hProcess );
176 CloseHandle( info.hProcess );
177 CloseHandle( info.hThread );
180 static WNDPROC old_proc;
181 static LRESULT CALLBACK winproc_wrapper( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
183 static int wm_renderallformats;
184 static int wm_drawclipboard;
185 static int seqno;
186 DWORD msg_flags = InSendMessageEx( NULL );
188 if (!seqno) seqno = GetClipboardSequenceNumber();
190 trace( "%p msg %04x\n", hwnd, msg );
191 if (!wm_renderallformats)
193 ok( GetClipboardOwner() == hwnd, "%04x: wrong owner %p/%p\n", msg, GetClipboardOwner(), hwnd );
194 ok( seqno == GetClipboardSequenceNumber(), "%04x: seqno changed\n", msg );
196 else
198 ok( !GetClipboardOwner(), "%04x: wrong owner %p\n", msg, GetClipboardOwner() );
199 ok( seqno + 1 == GetClipboardSequenceNumber(), "%04x: seqno unchanged\n", msg );
201 ok( GetClipboardViewer() == hwnd, "%04x: wrong viewer %p/%p\n", msg, GetClipboardViewer(), hwnd );
202 ok( GetOpenClipboardWindow() == hwnd, "%04x: wrong open win %p/%p\n",
203 msg, GetOpenClipboardWindow(), hwnd );
205 switch (msg)
207 case WM_DESTROY:
208 ok( wm_renderallformats, "didn't receive WM_RENDERALLFORMATS before WM_DESTROY\n" );
209 ok( wm_drawclipboard, "didn't receive WM_DRAWCLIPBOARD before WM_DESTROY\n" );
210 break;
211 case WM_DRAWCLIPBOARD:
212 ok( msg_flags == ISMEX_NOSEND, "WM_DRAWCLIPBOARD wrong flags %x\n", msg_flags );
213 wm_drawclipboard++;
214 break;
215 case WM_RENDERALLFORMATS:
216 ok( msg_flags == ISMEX_NOSEND, "WM_RENDERALLFORMATS wrong flags %x\n", msg_flags );
217 wm_renderallformats++;
218 break;
220 return old_proc( hwnd, msg, wp, lp );
223 static void test_ClipboardOwner(void)
225 HWND hWnd1, hWnd2;
226 BOOL ret;
228 SetLastError(0xdeadbeef);
229 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef,
230 "could not perform clipboard test: clipboard already owned\n");
232 hWnd1 = CreateWindowExA(0, "static", NULL, WS_POPUP,
233 0, 0, 10, 10, 0, 0, 0, NULL);
234 ok(hWnd1 != 0, "CreateWindowExA error %d\n", GetLastError());
235 trace("hWnd1 = %p\n", hWnd1);
237 hWnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP,
238 0, 0, 10, 10, 0, 0, 0, NULL);
239 ok(hWnd2 != 0, "CreateWindowExA error %d\n", GetLastError());
240 trace("hWnd2 = %p\n", hWnd2);
242 SetLastError(0xdeadbeef);
243 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
244 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */
245 "wrong error %u\n", GetLastError());
247 ok(OpenClipboard(0), "OpenClipboard failed\n");
248 ok(!GetClipboardOwner(), "clipboard should still be not owned\n");
249 ok(!OpenClipboard(hWnd1), "OpenClipboard should fail since clipboard already opened\n");
250 ok(OpenClipboard(0), "OpenClipboard again failed\n");
251 ret = CloseClipboard();
252 ok( ret, "CloseClipboard error %d\n", GetLastError());
254 ok(OpenClipboard(hWnd1), "OpenClipboard failed\n");
255 run_thread( open_clipboard_thread, hWnd1, __LINE__ );
256 run_thread( empty_clipboard_thread, 0, __LINE__ );
257 run_thread( set_clipboard_data_thread, hWnd1, __LINE__ );
258 ok( !IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE available\n" );
259 ok( !GetClipboardData( CF_WAVE ), "CF_WAVE data available\n" );
260 run_process( "set_clipboard_data 0" );
261 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
262 ok(OpenClipboard(hWnd1), "OpenClipboard failed\n");
264 SetLastError(0xdeadbeef);
265 ret = OpenClipboard(hWnd2);
266 ok(!ret && (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED),
267 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
269 SetLastError(0xdeadbeef);
270 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should still be not owned\n");
271 ret = EmptyClipboard();
272 ok( ret, "EmptyClipboard error %d\n", GetLastError());
273 ok(GetClipboardOwner() == hWnd1, "clipboard should be owned by %p, not by %p\n", hWnd1, GetClipboardOwner());
274 run_thread( empty_clipboard_thread, 0, __LINE__ );
275 run_thread( set_clipboard_data_thread, hWnd1, __LINE__ );
276 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
277 ok( GetClipboardData( CF_WAVE ) != 0, "CF_WAVE data not available\n" );
278 run_process( "set_clipboard_data 1" );
280 SetLastError(0xdeadbeef);
281 ret = OpenClipboard(hWnd2);
282 ok(!ret && (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED),
283 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
285 ret = CloseClipboard();
286 ok( ret, "CloseClipboard error %d\n", GetLastError());
287 ok(GetClipboardOwner() == hWnd1, "clipboard should still be owned\n");
289 /* any window will do, even from a different process */
290 ret = OpenClipboard( GetDesktopWindow() );
291 ok( ret, "OpenClipboard error %d\n", GetLastError());
292 ret = EmptyClipboard();
293 ok( ret, "EmptyClipboard error %d\n", GetLastError());
294 ok( GetClipboardOwner() == GetDesktopWindow(), "wrong owner %p/%p\n",
295 GetClipboardOwner(), GetDesktopWindow() );
296 run_thread( set_clipboard_data_thread, GetDesktopWindow(), __LINE__ );
297 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
298 ok( GetClipboardData( CF_WAVE ) != 0, "CF_WAVE data not available\n" );
299 run_process( "set_clipboard_data 2" );
300 ret = CloseClipboard();
301 ok( ret, "CloseClipboard error %d\n", GetLastError());
303 ret = OpenClipboard( hWnd1 );
304 ok( ret, "OpenClipboard error %d\n", GetLastError());
305 ret = EmptyClipboard();
306 ok( ret, "EmptyClipboard error %d\n", GetLastError());
307 SetClipboardData( CF_WAVE, 0 );
308 SetClipboardViewer( hWnd1 );
309 ok( GetClipboardOwner() == hWnd1, "wrong owner %p/%p\n", GetClipboardOwner(), hWnd1 );
310 ok( GetClipboardViewer() == hWnd1, "wrong viewer %p/%p\n", GetClipboardViewer(), hWnd1 );
311 ok( GetOpenClipboardWindow() == hWnd1, "wrong open win %p/%p\n", GetOpenClipboardWindow(), hWnd1 );
312 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
314 old_proc = (WNDPROC)SetWindowLongPtrA( hWnd1, GWLP_WNDPROC, (LONG_PTR)winproc_wrapper );
315 ret = DestroyWindow(hWnd1);
316 ok( ret, "DestroyWindow error %d\n", GetLastError());
317 ret = DestroyWindow(hWnd2);
318 ok( ret, "DestroyWindow error %d\n", GetLastError());
319 SetLastError(0xdeadbeef);
320 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should not be owned\n");
321 ok(!GetClipboardViewer() && GetLastError() == 0xdeadbeef, "viewer still exists\n");
322 ok(!GetOpenClipboardWindow() && GetLastError() == 0xdeadbeef, "clipboard should not be open\n");
323 ok( !IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE available\n" );
325 SetLastError( 0xdeadbeef );
326 ret = CloseClipboard();
327 ok( !ret, "CloseClipboard succeeded\n" );
328 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError() );
330 ret = OpenClipboard( 0 );
331 ok( ret, "OpenClipboard error %d\n", GetLastError());
332 run_thread( set_clipboard_data_thread, 0, __LINE__ );
333 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
334 ok( GetClipboardData( CF_WAVE ) != 0, "CF_WAVE data not available\n" );
335 run_process( "set_clipboard_data 3" );
336 ret = CloseClipboard();
337 ok( ret, "CloseClipboard error %d\n", GetLastError());
339 run_thread( open_and_empty_clipboard_thread, 0, __LINE__ );
340 ok( !GetOpenClipboardWindow(), "wrong open window %p\n", GetOpenClipboardWindow() );
341 ok( !GetClipboardOwner(), "wrong owner window %p\n", GetClipboardOwner() );
343 ret = OpenClipboard( 0 );
344 ok( ret, "OpenClipboard error %d\n", GetLastError());
345 run_thread( set_clipboard_data_thread, 0, __LINE__ );
346 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
347 ok( GetClipboardData( CF_WAVE ) != 0, "CF_WAVE data not available\n" );
348 run_process( "set_clipboard_data 4" );
349 ret = EmptyClipboard();
350 ok( ret, "EmptyClipboard error %d\n", GetLastError());
351 ret = CloseClipboard();
352 ok( ret, "CloseClipboard error %d\n", GetLastError());
354 SetLastError( 0xdeadbeef );
355 ok( !SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 )),
356 "SetClipboardData succeeded\n" );
357 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError() );
358 ok( !IsClipboardFormatAvailable( CF_WAVE ), "SetClipboardData succeeded\n" );
360 run_thread( open_and_empty_clipboard_thread, GetDesktopWindow(), __LINE__ );
361 ok( !GetOpenClipboardWindow(), "wrong open window %p\n", GetOpenClipboardWindow() );
362 ok( GetClipboardOwner() == GetDesktopWindow(), "wrong owner window %p / %p\n",
363 GetClipboardOwner(), GetDesktopWindow() );
365 run_thread( open_and_empty_clipboard_win_thread, 0, __LINE__ );
366 ok( !GetOpenClipboardWindow(), "wrong open window %p\n", GetOpenClipboardWindow() );
367 ok( !GetClipboardOwner(), "wrong owner window %p\n", GetClipboardOwner() );
370 static void test_RegisterClipboardFormatA(void)
372 ATOM atom_id;
373 UINT format_id, format_id2;
374 char buf[256];
375 int len;
376 BOOL ret;
377 HANDLE handle;
379 format_id = RegisterClipboardFormatA("my_cool_clipboard_format");
380 ok(format_id > 0xc000 && format_id < 0xffff, "invalid clipboard format id %04x\n", format_id);
382 format_id2 = RegisterClipboardFormatA("MY_COOL_CLIPBOARD_FORMAT");
383 ok(format_id2 == format_id, "invalid clipboard format id %04x\n", format_id2);
385 len = GetClipboardFormatNameA(format_id, buf, 256);
386 ok(len == lstrlenA("my_cool_clipboard_format"), "wrong format name length %d\n", len);
387 ok(!lstrcmpA(buf, "my_cool_clipboard_format"), "wrong format name \"%s\"\n", buf);
389 lstrcpyA(buf, "foo");
390 SetLastError(0xdeadbeef);
391 len = GetAtomNameA((ATOM)format_id, buf, 256);
392 ok(len == 0, "GetAtomNameA should fail\n");
393 ok(GetLastError() == ERROR_INVALID_HANDLE, "err %d\n", GetLastError());
395 todo_wine
397 lstrcpyA(buf, "foo");
398 SetLastError(0xdeadbeef);
399 len = GlobalGetAtomNameA((ATOM)format_id, buf, 256);
400 ok(len == 0, "GlobalGetAtomNameA should fail\n");
401 ok(GetLastError() == ERROR_INVALID_HANDLE, "err %d\n", GetLastError());
404 SetLastError(0xdeadbeef);
405 atom_id = FindAtomA("my_cool_clipboard_format");
406 ok(atom_id == 0, "FindAtomA should fail\n");
407 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError());
409 if (0)
411 /* this relies on the clipboard and global atom table being different */
412 SetLastError(0xdeadbeef);
413 atom_id = GlobalFindAtomA("my_cool_clipboard_format");
414 ok(atom_id == 0, "GlobalFindAtomA should fail\n");
415 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError());
418 for (format_id = 0; format_id < 0x10fff; format_id++)
420 SetLastError(0xdeadbeef);
421 len = GetClipboardFormatNameA(format_id, buf, 256);
423 if (format_id < 0xc000 || format_id > 0xffff)
424 ok(!len, "GetClipboardFormatNameA should fail, but it returned %d (%s)\n", len, buf);
425 else if (len && winetest_debug > 1)
426 trace("%04x: %s\n", format_id, len ? buf : "");
429 ret = OpenClipboard(0);
430 ok( ret, "OpenClipboard error %d\n", GetLastError());
432 /* try some invalid/unregistered formats */
433 SetLastError( 0xdeadbeef );
434 handle = SetClipboardData( 0, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
435 ok( !handle, "SetClipboardData succeeded\n" );
436 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError());
437 handle = SetClipboardData( 0x1234, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
438 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
439 handle = SetClipboardData( 0x123456, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
440 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
441 handle = SetClipboardData( 0xffff8765, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
442 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
444 ok( IsClipboardFormatAvailable( 0x1234 ), "format missing\n" );
445 ok( IsClipboardFormatAvailable( 0x123456 ), "format missing\n" );
446 ok( IsClipboardFormatAvailable( 0xffff8765 ), "format missing\n" );
447 ok( !IsClipboardFormatAvailable( 0 ), "format available\n" );
448 ok( !IsClipboardFormatAvailable( 0x3456 ), "format available\n" );
449 ok( !IsClipboardFormatAvailable( 0x8765 ), "format available\n" );
451 trace("# of formats available: %d\n", CountClipboardFormats());
453 format_id = 0;
454 while ((format_id = EnumClipboardFormats(format_id)))
456 ok(IsClipboardFormatAvailable(format_id), "format %04x was listed as available\n", format_id);
457 len = GetClipboardFormatNameA(format_id, buf, 256);
458 trace("%04x: %s\n", format_id, len ? buf : "");
461 ret = EmptyClipboard();
462 ok( ret, "EmptyClipboard error %d\n", GetLastError());
463 ret =CloseClipboard();
464 ok( ret, "CloseClipboard error %d\n", GetLastError());
466 if (CountClipboardFormats())
468 SetLastError(0xdeadbeef);
469 ok(!EnumClipboardFormats(0), "EnumClipboardFormats should fail if clipboard wasn't open\n");
470 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN,
471 "Last error should be set to ERROR_CLIPBOARD_NOT_OPEN, not %d\n", GetLastError());
474 SetLastError(0xdeadbeef);
475 ok(!EmptyClipboard(), "EmptyClipboard should fail if clipboard wasn't open\n");
476 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */
477 "Wrong error %u\n", GetLastError());
479 format_id = RegisterClipboardFormatA("#1234");
480 ok(format_id == 1234, "invalid clipboard format id %04x\n", format_id);
483 static HGLOBAL create_textA(void)
485 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 5);
486 char *p = GlobalLock(h);
487 strcpy(p, "test");
488 GlobalUnlock(h);
489 return h;
492 static HGLOBAL create_textW(void)
494 static const WCHAR testW[] = {'t','e','s','t',0};
495 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 5 * sizeof(WCHAR));
496 WCHAR *p = GlobalLock(h);
497 lstrcpyW(p, testW);
498 GlobalUnlock(h);
499 return h;
502 static HANDLE create_metafile(void)
504 const RECT rect = {0, 0, 100, 100};
505 METAFILEPICT *pict;
506 HANDLE ret;
507 HMETAFILE mf;
508 HDC hdc = CreateMetaFileA( NULL );
509 ExtTextOutA( hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL );
510 mf = CloseMetaFile( hdc );
511 ret = GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(*pict) );
512 pict = GlobalLock( ret );
513 pict->mm = MM_TEXT;
514 pict->xExt = pict->yExt = 100;
515 pict->hMF = mf;
516 GlobalUnlock( ret );
517 return ret;
520 static HENHMETAFILE create_emf(void)
522 const RECT rect = {0, 0, 100, 100};
523 HDC hdc = CreateEnhMetaFileA(NULL, NULL, &rect, "HENHMETAFILE Ole Clipboard Test\0Test\0\0");
524 ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
525 return CloseEnhMetaFile(hdc);
528 static HBITMAP create_bitmap(void)
530 HDC hdc = GetDC( 0 );
531 UINT bpp = GetDeviceCaps( hdc, BITSPIXEL );
532 ReleaseDC( 0, hdc );
533 return CreateBitmap( 10, 10, 1, bpp, NULL );
536 static HBITMAP create_dib( BOOL v5 )
538 HANDLE ret;
539 BITMAPINFOHEADER *hdr;
541 ret = GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT,
542 sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD) + 16 * 16 * 4 );
543 hdr = GlobalLock( ret );
544 hdr->biSize = v5 ? sizeof(BITMAPV5HEADER) : sizeof(*hdr);
545 hdr->biWidth = 16;
546 hdr->biHeight = 16;
547 hdr->biPlanes = 1;
548 hdr->biBitCount = 32;
549 hdr->biCompression = BI_RGB;
550 if (v5)
552 BITMAPV5HEADER *hdr5 = (BITMAPV5HEADER *)hdr;
553 hdr5->bV5RedMask = 0x0000ff;
554 hdr5->bV5GreenMask = 0x00ff00;
555 hdr5->bV5BlueMask = 0xff0000;
556 hdr5->bV5AlphaMask = 0xff000000;
558 GlobalUnlock( ret );
559 return ret;
562 static LRESULT CALLBACK renderer_winproc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
564 static UINT rendered;
565 UINT ret;
567 switch (msg)
569 case WM_RENDERFORMAT:
570 if (wp < 32) rendered |= (1 << wp);
571 break;
572 case WM_USER:
573 ret = rendered;
574 rendered = 0;
575 return ret;
577 return DefWindowProcA( hwnd, msg, wp, lp );
580 static void test_synthesized(void)
582 static const struct test
584 UINT format;
585 UINT expected[8];
586 } tests[] =
588 /* 0 */ { CF_TEXT, { CF_TEXT, CF_LOCALE, CF_OEMTEXT, CF_UNICODETEXT }},
589 { CF_OEMTEXT, { CF_OEMTEXT, CF_LOCALE, CF_TEXT, CF_UNICODETEXT }},
590 { CF_UNICODETEXT, { CF_UNICODETEXT, CF_LOCALE, CF_TEXT, CF_OEMTEXT }},
591 { CF_ENHMETAFILE, { CF_ENHMETAFILE, CF_METAFILEPICT }},
592 { CF_METAFILEPICT, { CF_METAFILEPICT, CF_ENHMETAFILE }},
593 /* 5 */ { CF_BITMAP, { CF_BITMAP, CF_DIB, CF_DIBV5 }},
594 { CF_DIB, { CF_DIB, CF_BITMAP, CF_DIBV5 }},
595 { CF_DIBV5, { CF_DIBV5, CF_BITMAP, CF_DIB }},
598 HGLOBAL h, htext;
599 HENHMETAFILE emf;
600 BOOL r;
601 UINT cf, i, j, count, rendered;
602 HANDLE data;
603 HWND hwnd;
605 hwnd = CreateWindowA( "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL );
606 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)renderer_winproc );
608 htext = create_textA();
609 emf = create_emf();
611 r = OpenClipboard(NULL);
612 ok(r, "gle %d\n", GetLastError());
613 r = EmptyClipboard();
614 ok(r, "gle %d\n", GetLastError());
615 h = SetClipboardData(CF_TEXT, htext);
616 ok(h == htext, "got %p\n", h);
617 h = SetClipboardData(CF_ENHMETAFILE, emf);
618 ok(h == emf, "got %p\n", h);
619 r = CloseClipboard();
620 ok(r, "gle %d\n", GetLastError());
622 count = CountClipboardFormats();
623 ok( count == 6, "count %u\n", count );
624 r = IsClipboardFormatAvailable( CF_TEXT );
625 ok( r, "CF_TEXT not available err %d\n", GetLastError());
626 r = IsClipboardFormatAvailable( CF_LOCALE );
627 ok( r, "CF_LOCALE not available err %d\n", GetLastError());
628 r = IsClipboardFormatAvailable( CF_OEMTEXT );
629 ok( r, "CF_OEMTEXT not available err %d\n", GetLastError());
630 r = IsClipboardFormatAvailable( CF_UNICODETEXT );
631 ok( r, "CF_UNICODETEXT not available err %d\n", GetLastError());
632 r = IsClipboardFormatAvailable( CF_ENHMETAFILE );
633 ok( r, "CF_ENHMETAFILE not available err %d\n", GetLastError());
634 r = IsClipboardFormatAvailable( CF_METAFILEPICT );
635 ok( r, "CF_METAFILEPICT not available err %d\n", GetLastError());
637 r = OpenClipboard(NULL);
638 ok(r, "gle %d\n", GetLastError());
639 cf = EnumClipboardFormats(0);
640 ok(cf == CF_TEXT, "cf %08x\n", cf);
641 data = GetClipboardData(cf);
642 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
644 cf = EnumClipboardFormats(cf);
645 ok(cf == CF_ENHMETAFILE, "cf %08x\n", cf);
646 data = GetClipboardData(cf);
647 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
649 cf = EnumClipboardFormats(cf);
650 ok(cf == CF_LOCALE, "cf %08x\n", cf);
651 data = GetClipboardData(cf);
652 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
654 cf = EnumClipboardFormats(cf);
655 ok(cf == CF_OEMTEXT, "cf %08x\n", cf);
656 data = GetClipboardData(cf);
657 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
659 cf = EnumClipboardFormats(cf);
660 ok(cf == CF_UNICODETEXT, "cf %08x\n", cf);
662 cf = EnumClipboardFormats(cf);
663 ok(cf == CF_METAFILEPICT, "cf %08x\n", cf);
664 data = GetClipboardData(cf);
665 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
667 cf = EnumClipboardFormats(cf);
668 ok(cf == 0, "cf %08x\n", cf);
670 r = EmptyClipboard();
671 ok(r, "gle %d\n", GetLastError());
673 SetClipboardData( CF_UNICODETEXT, create_textW() );
674 SetClipboardData( CF_TEXT, create_textA() );
675 SetClipboardData( CF_OEMTEXT, create_textA() );
676 r = CloseClipboard();
677 ok(r, "gle %d\n", GetLastError());
679 r = OpenClipboard( NULL );
680 ok(r, "gle %d\n", GetLastError());
681 SetLastError( 0xdeadbeef );
682 cf = EnumClipboardFormats(0);
683 ok( cf == CF_UNICODETEXT, "cf %08x\n", cf );
684 ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() );
685 SetLastError( 0xdeadbeef );
686 cf = EnumClipboardFormats(cf);
687 ok( cf == CF_TEXT, "cf %08x\n", cf );
688 ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() );
689 SetLastError( 0xdeadbeef );
690 cf = EnumClipboardFormats(cf);
691 ok( cf == CF_OEMTEXT, "cf %08x\n", cf );
692 ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() );
693 SetLastError( 0xdeadbeef );
694 cf = EnumClipboardFormats(cf);
695 ok( cf == CF_LOCALE, "cf %08x\n", cf );
696 ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() );
697 SetLastError( 0xdeadbeef );
698 cf = EnumClipboardFormats( cf );
699 ok( cf == 0, "cf %08x\n", cf );
700 ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() );
701 SetLastError( 0xdeadbeef );
702 cf = EnumClipboardFormats( 0xdead );
703 ok( cf == 0, "cf %08x\n", cf );
704 ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() );
706 r = EmptyClipboard();
707 ok(r, "gle %d\n", GetLastError());
709 r = CloseClipboard();
710 ok(r, "gle %d\n", GetLastError());
712 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
714 r = OpenClipboard(NULL);
715 ok(r, "%u: gle %d\n", i, GetLastError());
716 r = EmptyClipboard();
717 ok(r, "%u: gle %d\n", i, GetLastError());
719 switch (tests[i].format)
721 case CF_TEXT:
722 case CF_OEMTEXT:
723 SetClipboardData( tests[i].format, create_textA() );
724 break;
725 case CF_UNICODETEXT:
726 SetClipboardData( CF_UNICODETEXT, create_textW() );
727 break;
728 case CF_ENHMETAFILE:
729 SetClipboardData( CF_ENHMETAFILE, create_emf() );
730 break;
731 case CF_METAFILEPICT:
732 SetClipboardData( CF_METAFILEPICT, create_metafile() );
733 break;
734 case CF_BITMAP:
735 SetClipboardData( CF_BITMAP, create_bitmap() );
736 break;
737 case CF_DIB:
738 case CF_DIBV5:
739 SetClipboardData( tests[i].format, create_dib( tests[i].format == CF_DIBV5 ));
740 break;
743 count = CountClipboardFormats();
744 ok( count == 1, "%u: count %u\n", i, count );
746 r = CloseClipboard();
747 ok(r, "%u: gle %d\n", i, GetLastError());
749 count = CountClipboardFormats();
750 for (j = 0; tests[i].expected[j]; j++)
752 r = IsClipboardFormatAvailable( tests[i].expected[j] );
753 ok( r, "%u: %04x not available\n", i, tests[i].expected[j] );
755 ok( count == j, "%u: count %u instead of %u\n", i, count, j );
757 r = OpenClipboard( hwnd );
758 ok(r, "%u: gle %d\n", i, GetLastError());
759 cf = 0;
760 for (j = 0; tests[i].expected[j]; j++)
762 cf = EnumClipboardFormats( cf );
763 ok(cf == tests[i].expected[j], "%u.%u: got %04x instead of %04x\n",
764 i, j, cf, tests[i].expected[j] );
765 if (cf != tests[i].expected[j]) break;
766 data = GetClipboardData( cf );
767 ok(data != NULL ||
768 broken( tests[i].format == CF_DIBV5 && cf == CF_DIB ), /* >= Vista */
769 "%u: couldn't get data, cf %04x err %d\n", i, cf, GetLastError());
770 if (cf == CF_LOCALE)
772 UINT *ptr = GlobalLock( data );
773 ok( GlobalSize( data ) == sizeof(*ptr), "%u: size %lu\n", i, GlobalSize( data ));
774 ok( *ptr == GetUserDefaultLCID() ||
775 broken( *ptr == MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT )),
776 "%u: CF_LOCALE %08x/%08x\n", i, *ptr, GetUserDefaultLCID() );
777 GlobalUnlock( data );
780 if (!tests[i].expected[j])
782 cf = EnumClipboardFormats( cf );
783 ok(cf == 0, "%u: cf %04x\n", i, cf);
786 /* now with delayed rendering */
788 r = EmptyClipboard();
789 ok(r, "%u: gle %d\n", i, GetLastError());
791 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
792 ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered );
794 SetClipboardData( tests[i].format, 0 );
795 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
796 ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered );
798 count = CountClipboardFormats();
799 ok( count == 1, "%u: count %u\n", i, count );
801 r = CloseClipboard();
802 ok(r, "%u: gle %d\n", i, GetLastError());
803 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
804 ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered );
806 count = CountClipboardFormats();
807 for (j = 0; tests[i].expected[j]; j++)
809 r = IsClipboardFormatAvailable( tests[i].expected[j] );
810 ok( r, "%u: %04x not available\n", i, tests[i].expected[j] );
812 ok( count == j, "%u: count %u instead of %u\n", i, count, j );
813 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
814 ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered );
816 r = OpenClipboard(NULL);
817 ok(r, "%u: gle %d\n", i, GetLastError());
818 cf = 0;
819 for (j = 0; tests[i].expected[j]; j++)
821 cf = EnumClipboardFormats( cf );
822 ok(cf == tests[i].expected[j], "%u.%u: got %04x instead of %04x\n",
823 i, j, cf, tests[i].expected[j] );
824 if (cf != tests[i].expected[j]) break;
825 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
826 ok( !rendered, "%u.%u: formats %08x have been rendered\n", i, j, rendered );
827 data = GetClipboardData( cf );
828 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
829 if (cf == CF_LOCALE)
831 ok(data != NULL, "%u: CF_LOCALE no data\n", i);
832 ok( !rendered, "%u.%u: formats %08x have been rendered\n", i, j, rendered );
834 else
836 ok(!data, "%u: format %04x got data %p\n", i, cf, data);
837 ok( rendered == (1 << tests[i].format),
838 "%u.%u: formats %08x have been rendered\n", i, j, rendered );
839 /* try to render a second time */
840 data = GetClipboardData( cf );
841 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
842 ok( rendered == (1 << tests[i].format),
843 "%u.%u: formats %08x have been rendered\n", i, j, rendered );
846 if (!tests[i].expected[j])
848 cf = EnumClipboardFormats( cf );
849 ok(cf == 0, "%u: cf %04x\n", i, cf);
851 r = CloseClipboard();
852 ok(r, "%u: gle %d\n", i, GetLastError());
853 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
854 ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered );
857 r = OpenClipboard(NULL);
858 ok(r, "gle %d\n", GetLastError());
859 r = EmptyClipboard();
860 ok(r, "gle %d\n", GetLastError());
861 r = CloseClipboard();
862 ok(r, "gle %d\n", GetLastError());
863 DestroyWindow( hwnd );
866 static CRITICAL_SECTION clipboard_cs;
867 static HWND next_wnd;
868 static UINT wm_drawclipboard;
869 static UINT wm_clipboardupdate;
870 static UINT wm_destroyclipboard;
871 static UINT wm_renderformat;
872 static UINT nb_formats;
873 static BOOL cross_thread;
875 static LRESULT CALLBACK clipboard_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
877 LRESULT ret;
878 DWORD msg_flags = InSendMessageEx( NULL );
880 switch(msg) {
881 case WM_DRAWCLIPBOARD:
882 ok( msg_flags == (cross_thread ? ISMEX_NOTIFY : ISMEX_NOSEND),
883 "WM_DRAWCLIPBOARD wrong flags %x\n", msg_flags );
884 EnterCriticalSection(&clipboard_cs);
885 wm_drawclipboard++;
886 LeaveCriticalSection(&clipboard_cs);
887 break;
888 case WM_CHANGECBCHAIN:
889 ok( msg_flags == (cross_thread ? ISMEX_SEND : ISMEX_NOSEND),
890 "WM_CHANGECBCHAIN wrong flags %x\n", msg_flags );
891 if (next_wnd == (HWND)wp)
892 next_wnd = (HWND)lp;
893 else if (next_wnd)
894 SendMessageA(next_wnd, msg, wp, lp);
895 break;
896 case WM_DESTROYCLIPBOARD:
897 ok( msg_flags == (cross_thread ? ISMEX_SEND : ISMEX_NOSEND),
898 "WM_DESTROYCLIPBOARD wrong flags %x\n", msg_flags );
899 wm_destroyclipboard++;
900 ok( GetClipboardOwner() == hwnd, "WM_DESTROYCLIPBOARD owner %p\n", GetClipboardOwner() );
901 nb_formats = CountClipboardFormats();
902 break;
903 case WM_RENDERFORMAT:
904 ok( !wm_renderformat, "multiple WM_RENDERFORMAT %04x / %04lx\n", wm_renderformat, wp );
905 wm_renderformat = wp;
906 break;
907 case WM_CLIPBOARDUPDATE:
908 ok( msg_flags == ISMEX_NOSEND, "WM_CLIPBOARDUPDATE wrong flags %x\n", msg_flags );
909 EnterCriticalSection(&clipboard_cs);
910 wm_clipboardupdate++;
911 LeaveCriticalSection(&clipboard_cs);
912 break;
913 case WM_USER:
914 ChangeClipboardChain(hwnd, next_wnd);
915 PostQuitMessage(0);
916 break;
917 case WM_USER+1:
918 ret = wm_drawclipboard;
919 wm_drawclipboard = 0;
920 return ret;
921 case WM_USER+2:
922 ret = wm_clipboardupdate;
923 wm_clipboardupdate = 0;
924 return ret;
925 case WM_USER+3:
926 ret = wm_destroyclipboard;
927 wm_destroyclipboard = 0;
928 return ret;
929 case WM_USER+4:
930 ret = wm_renderformat;
931 wm_renderformat = 0;
932 return ret;
933 case WM_USER+5:
934 return nb_formats;
937 return DefWindowProcA(hwnd, msg, wp, lp);
940 static DWORD WINAPI clipboard_thread(void *param)
942 HWND ret, win = param;
943 BOOL r;
944 MSG msg;
945 HANDLE handle;
946 UINT count, fmt, formats, old_seq = 0, seq;
948 cross_thread = (GetWindowThreadProcessId( win, NULL ) != GetCurrentThreadId());
949 trace( "%s-threaded test\n", cross_thread ? "multi" : "single" );
951 if (pGetClipboardSequenceNumber) old_seq = pGetClipboardSequenceNumber();
953 EnterCriticalSection(&clipboard_cs);
954 SetLastError(0xdeadbeef);
955 next_wnd = SetClipboardViewer(win);
956 ok(GetLastError() == 0xdeadbeef, "GetLastError = %d\n", GetLastError());
957 LeaveCriticalSection(&clipboard_cs);
959 SetLastError( 0xdeadbeef );
960 ret = SetClipboardViewer( (HWND)0xdead );
961 ok( !ret, "SetClipboardViewer succeeded\n" );
962 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
963 SetLastError( 0xdeadbeef );
964 r = ChangeClipboardChain( win, (HWND)0xdead );
965 ok( !r, "ChangeClipboardChain succeeded\n" );
966 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
967 SetLastError( 0xdeadbeef );
968 r = ChangeClipboardChain( (HWND)0xdead, next_wnd );
969 ok( !r, "ChangeClipboardChain succeeded\n" );
970 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
972 if (pAddClipboardFormatListener)
974 r = pAddClipboardFormatListener(win);
975 ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError());
976 SetLastError( 0xdeadbeef );
977 r = pAddClipboardFormatListener( win );
978 ok( !r, "AddClipboardFormatListener succeeded\n" );
979 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
980 SetLastError( 0xdeadbeef );
981 r = pAddClipboardFormatListener( (HWND)0xdead );
982 ok( !r, "AddClipboardFormatListener succeeded\n" );
983 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
984 r = pAddClipboardFormatListener( GetDesktopWindow() );
985 ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError());
986 r = pRemoveClipboardFormatListener( GetDesktopWindow() );
987 ok( r, "RemoveClipboardFormatListener failed err %d\n", GetLastError());
990 if (pGetClipboardSequenceNumber)
992 seq = pGetClipboardSequenceNumber();
993 ok( seq == old_seq, "sequence changed\n" );
995 if (!cross_thread)
997 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
998 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
999 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1000 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1002 count = SendMessageA( win, WM_USER + 1, 0, 0 );
1003 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1004 count = SendMessageA( win, WM_USER+2, 0, 0 );
1005 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1006 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1007 ok( !fmt, "WM_RENDERFORMAT received\n" );
1009 SetLastError( 0xdeadbeef );
1010 r = OpenClipboard( (HWND)0xdead );
1011 ok( !r, "OpenClipboard succeeded\n" );
1012 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
1014 r = OpenClipboard(win);
1015 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1017 if (pGetClipboardSequenceNumber)
1019 seq = pGetClipboardSequenceNumber();
1020 ok( seq == old_seq, "sequence changed\n" );
1022 if (!cross_thread)
1024 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1025 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1026 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1027 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1029 count = SendMessageA( win, WM_USER+1, 0, 0 );
1030 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1031 count = SendMessageA( win, WM_USER+2, 0, 0 );
1032 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1033 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1034 ok( !fmt, "WM_RENDERFORMAT received\n" );
1036 r = EmptyClipboard();
1037 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
1039 if (pGetClipboardSequenceNumber)
1041 seq = pGetClipboardSequenceNumber();
1042 ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1043 old_seq = seq;
1045 if (!cross_thread)
1047 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1048 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1049 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1050 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1052 count = SendMessageA( win, WM_USER+1, 0, 0 );
1053 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1054 count = SendMessageA( win, WM_USER+2, 0, 0 );
1055 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1056 count = SendMessageA( win, WM_USER+3, 0, 0 );
1057 ok( !count, "WM_DESTROYCLIPBOARD received\n" );
1058 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1059 ok( !fmt, "WM_RENDERFORMAT received\n" );
1061 r = EmptyClipboard();
1062 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
1063 /* sequence changes again, even though it was already empty */
1064 if (pGetClipboardSequenceNumber)
1066 seq = pGetClipboardSequenceNumber();
1067 ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1068 old_seq = seq;
1070 if (!cross_thread)
1072 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1073 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1074 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1075 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1077 count = SendMessageA( win, WM_USER+1, 0, 0 );
1078 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1079 count = SendMessageA( win, WM_USER+2, 0, 0 );
1080 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1081 count = SendMessageA( win, WM_USER+3, 0, 0 );
1082 ok( count, "WM_DESTROYCLIPBOARD not received\n" );
1083 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1084 ok( !fmt, "WM_RENDERFORMAT received\n" );
1085 count = SendMessageA( win, WM_USER+5, 0, 0 );
1086 ok( !count, "wrong format count %u on WM_DESTROYCLIPBOARD\n", count );
1088 handle = SetClipboardData( CF_TEXT, create_textA() );
1089 ok(handle != 0, "SetClipboardData failed: %d\n", GetLastError());
1091 if (pGetClipboardSequenceNumber)
1093 seq = pGetClipboardSequenceNumber();
1094 ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1095 old_seq = seq;
1097 if (!cross_thread)
1099 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1100 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1101 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1102 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1104 count = SendMessageA( win, WM_USER+1, 0, 0 );
1105 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1106 count = SendMessageA( win, WM_USER+2, 0, 0 );
1107 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1108 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1109 ok( !fmt, "WM_RENDERFORMAT received\n" );
1111 SetClipboardData( CF_UNICODETEXT, 0 );
1113 if (pGetClipboardSequenceNumber)
1115 seq = pGetClipboardSequenceNumber();
1116 ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1117 old_seq = seq;
1119 if (!cross_thread)
1121 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1122 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1123 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1124 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1126 count = SendMessageA( win, WM_USER+1, 0, 0 );
1127 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1128 count = SendMessageA( win, WM_USER+2, 0, 0 );
1129 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1130 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1131 ok( !fmt, "WM_RENDERFORMAT received\n" );
1133 SetClipboardData( CF_UNICODETEXT, 0 ); /* same data again */
1135 if (pGetClipboardSequenceNumber)
1137 seq = pGetClipboardSequenceNumber();
1138 ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1139 old_seq = seq;
1141 if (!cross_thread)
1143 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1144 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1145 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1146 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1148 count = SendMessageA( win, WM_USER+1, 0, 0 );
1149 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1150 count = SendMessageA( win, WM_USER+2, 0, 0 );
1151 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1152 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1153 ok( !fmt, "WM_RENDERFORMAT received\n" );
1155 ok( IsClipboardFormatAvailable( CF_TEXT ), "CF_TEXT available\n" );
1156 ok( IsClipboardFormatAvailable( CF_UNICODETEXT ), "CF_UNICODETEXT available\n" );
1157 ok( !IsClipboardFormatAvailable( CF_OEMTEXT ), "CF_OEMTEXT available\n" );
1159 EnterCriticalSection(&clipboard_cs);
1160 r = CloseClipboard();
1161 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1162 LeaveCriticalSection(&clipboard_cs);
1164 if (pGetClipboardSequenceNumber)
1166 seq = pGetClipboardSequenceNumber();
1167 ok( (int)(seq - old_seq) == 2, "sequence diff %d\n", seq - old_seq );
1168 old_seq = seq;
1170 if (!cross_thread)
1172 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1173 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1174 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1175 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1177 count = SendMessageA( win, WM_USER+1, 0, 0 );
1178 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1179 count = SendMessageA( win, WM_USER+2, 0, 0 );
1180 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1181 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1182 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1184 r = OpenClipboard(win);
1185 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1187 if (pGetClipboardSequenceNumber)
1189 seq = pGetClipboardSequenceNumber();
1190 ok( seq == old_seq, "sequence changed\n" );
1192 if (!cross_thread)
1194 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1195 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1196 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1198 count = SendMessageA( win, WM_USER+1, 0, 0 );
1199 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1200 count = SendMessageA( win, WM_USER+2, 0, 0 );
1201 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1202 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1203 ok( !fmt, "WM_RENDERFORMAT received\n" );
1205 ok( IsClipboardFormatAvailable( CF_TEXT ), "CF_TEXT available\n" );
1206 ok( IsClipboardFormatAvailable( CF_UNICODETEXT ), "CF_UNICODETEXT available\n" );
1207 ok( IsClipboardFormatAvailable( CF_OEMTEXT ), "CF_OEMTEXT available\n" );
1209 ok( GetClipboardOwner() == win, "wrong owner %p\n", GetClipboardOwner());
1210 handle = GetClipboardData( CF_UNICODETEXT );
1211 ok( !handle, "got data for CF_UNICODETEXT\n" );
1212 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1213 ok( fmt == CF_UNICODETEXT, "WM_RENDERFORMAT received %04x\n", fmt );
1215 handle = GetClipboardData( CF_OEMTEXT );
1216 ok( !handle, "got data for CF_OEMTEXT\n" );
1217 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1218 ok( fmt == CF_UNICODETEXT, "WM_RENDERFORMAT received %04x\n", fmt );
1220 SetClipboardData( CF_WAVE, 0 );
1221 if (pGetClipboardSequenceNumber)
1223 seq = pGetClipboardSequenceNumber();
1224 ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1225 old_seq = seq;
1227 if (!cross_thread)
1229 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1230 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1231 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1232 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1234 count = SendMessageA( win, WM_USER+1, 0, 0 );
1235 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1236 count = SendMessageA( win, WM_USER+2, 0, 0 );
1237 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1238 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1239 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1241 r = CloseClipboard();
1242 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1243 if (pGetClipboardSequenceNumber)
1245 /* no synthesized format, so CloseClipboard doesn't change the sequence */
1246 seq = pGetClipboardSequenceNumber();
1247 ok( seq == old_seq, "sequence changed\n" );
1248 old_seq = seq;
1250 if (!cross_thread)
1252 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1253 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1254 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1255 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1257 count = SendMessageA( win, WM_USER+1, 0, 0 );
1258 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1259 count = SendMessageA( win, WM_USER+2, 0, 0 );
1260 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1261 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1262 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1264 r = OpenClipboard(win);
1265 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1266 r = CloseClipboard();
1267 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1268 /* nothing changed */
1269 if (pGetClipboardSequenceNumber)
1271 seq = pGetClipboardSequenceNumber();
1272 ok( seq == old_seq, "sequence changed\n" );
1274 if (!cross_thread)
1276 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1277 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1278 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1279 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1281 count = SendMessageA( win, WM_USER+1, 0, 0 );
1282 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1283 count = SendMessageA( win, WM_USER+2, 0, 0 );
1284 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1285 count = SendMessageA( win, WM_USER+3, 0, 0 );
1286 ok( !count, "WM_DESTROYCLIPBOARD received\n" );
1287 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1288 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1290 formats = CountClipboardFormats();
1291 r = OpenClipboard(0);
1292 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1293 r = EmptyClipboard();
1294 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
1295 r = CloseClipboard();
1296 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1298 if (!cross_thread)
1300 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1301 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1302 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1303 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1305 count = SendMessageA( win, WM_USER+1, 0, 0 );
1306 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1307 count = SendMessageA( win, WM_USER+2, 0, 0 );
1308 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1309 count = SendMessageA( win, WM_USER+3, 0, 0 );
1310 ok( count == 1, "WM_DESTROYCLIPBOARD not received\n" );
1311 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1312 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1313 count = SendMessageA( win, WM_USER+5, 0, 0 );
1314 ok( count == formats, "wrong format count %u on WM_DESTROYCLIPBOARD\n", count );
1316 r = OpenClipboard(win);
1317 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1318 SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_FIXED, 1 ));
1319 if (pGetClipboardSequenceNumber)
1321 seq = pGetClipboardSequenceNumber();
1322 ok( (int)(seq - old_seq) == 2, "sequence diff %d\n", seq - old_seq );
1323 old_seq = seq;
1325 if (!cross_thread)
1327 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1328 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1329 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1330 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1332 count = SendMessageA( win, WM_USER+1, 0, 0 );
1333 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1334 count = SendMessageA( win, WM_USER+2, 0, 0 );
1335 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1336 count = SendMessageA( win, WM_USER+3, 0, 0 );
1337 ok( !count, "WM_DESTROYCLIPBOARD received\n" );
1338 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1339 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1341 EnterCriticalSection(&clipboard_cs);
1342 r = CloseClipboard();
1343 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1344 LeaveCriticalSection(&clipboard_cs);
1346 if (pGetClipboardSequenceNumber)
1348 seq = pGetClipboardSequenceNumber();
1349 ok( seq == old_seq, "sequence changed\n" );
1350 old_seq = seq;
1352 if (!cross_thread)
1354 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1355 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1356 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1357 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1359 count = SendMessageA( win, WM_USER+1, 0, 0 );
1360 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1361 count = SendMessageA( win, WM_USER+2, 0, 0 );
1362 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1363 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1364 ok( !fmt, "WM_RENDERFORMAT received\n" );
1366 run_process( "grab_clipboard 0" );
1368 if (pGetClipboardSequenceNumber)
1370 seq = pGetClipboardSequenceNumber();
1371 ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1372 old_seq = seq;
1374 if (!cross_thread)
1376 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1377 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1378 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1379 /* in this case we get a cross-thread WM_DRAWCLIPBOARD */
1380 cross_thread = TRUE;
1381 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1382 cross_thread = FALSE;
1384 count = SendMessageA( win, WM_USER+1, 0, 0 );
1385 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1386 count = SendMessageA( win, WM_USER+2, 0, 0 );
1387 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1388 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1389 ok( !fmt, "WM_RENDERFORMAT received\n" );
1391 r = OpenClipboard(0);
1392 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1393 SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_FIXED, 1 ));
1394 if (pGetClipboardSequenceNumber)
1396 seq = pGetClipboardSequenceNumber();
1397 ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1398 old_seq = seq;
1400 if (!cross_thread)
1402 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1403 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1404 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1405 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1407 count = SendMessageA( win, WM_USER+1, 0, 0 );
1408 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1409 count = SendMessageA( win, WM_USER+2, 0, 0 );
1410 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1411 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1412 ok( !fmt, "WM_RENDERFORMAT received\n" );
1414 EnterCriticalSection(&clipboard_cs);
1415 r = CloseClipboard();
1416 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1417 LeaveCriticalSection(&clipboard_cs);
1419 if (pGetClipboardSequenceNumber)
1421 seq = pGetClipboardSequenceNumber();
1422 ok( seq == old_seq, "sequence changed\n" );
1423 old_seq = seq;
1425 if (!cross_thread)
1427 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD received\n" );
1428 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1429 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1430 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1432 count = SendMessageA( win, WM_USER+1, 0, 0 );
1433 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1434 count = SendMessageA( win, WM_USER+2, 0, 0 );
1435 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1436 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1437 ok( !fmt, "WM_RENDERFORMAT received\n" );
1439 run_process( "grab_clipboard 1" );
1441 if (pGetClipboardSequenceNumber)
1443 seq = pGetClipboardSequenceNumber();
1444 ok( (int)(seq - old_seq) == 2, "sequence diff %d\n", seq - old_seq );
1445 old_seq = seq;
1447 if (!cross_thread)
1449 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1450 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1451 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1452 /* in this case we get a cross-thread WM_DRAWCLIPBOARD */
1453 cross_thread = TRUE;
1454 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1455 cross_thread = FALSE;
1457 count = SendMessageA( win, WM_USER+1, 0, 0 );
1458 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1459 count = SendMessageA( win, WM_USER+2, 0, 0 );
1460 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1461 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1462 ok( !fmt, "WM_RENDERFORMAT received\n" );
1464 r = OpenClipboard(0);
1465 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1466 SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_FIXED, 1 ));
1467 if (pGetClipboardSequenceNumber)
1469 seq = pGetClipboardSequenceNumber();
1470 ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1471 old_seq = seq;
1473 if (!cross_thread)
1475 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1476 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1477 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1478 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1480 count = SendMessageA( win, WM_USER+1, 0, 0 );
1481 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1482 count = SendMessageA( win, WM_USER+2, 0, 0 );
1483 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1484 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1485 ok( !fmt, "WM_RENDERFORMAT received\n" );
1487 EnterCriticalSection(&clipboard_cs);
1488 r = CloseClipboard();
1489 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1490 LeaveCriticalSection(&clipboard_cs);
1492 if (pGetClipboardSequenceNumber)
1494 seq = pGetClipboardSequenceNumber();
1495 ok( seq == old_seq, "sequence changed\n" );
1496 old_seq = seq;
1498 if (!cross_thread)
1500 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1501 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1502 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1503 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1505 count = SendMessageA( win, WM_USER+1, 0, 0 );
1506 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1507 count = SendMessageA( win, WM_USER+2, 0, 0 );
1508 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1509 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1510 ok( !fmt, "WM_RENDERFORMAT received\n" );
1512 r = PostMessageA(win, WM_USER, 0, 0);
1513 ok(r, "PostMessage failed: %d\n", GetLastError());
1515 if (pRemoveClipboardFormatListener)
1517 r = pRemoveClipboardFormatListener(win);
1518 ok( r, "RemoveClipboardFormatListener failed err %d\n", GetLastError());
1519 SetLastError( 0xdeadbeef );
1520 r = pRemoveClipboardFormatListener(win);
1521 ok( !r, "RemoveClipboardFormatListener succeeded\n" );
1522 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1523 SetLastError( 0xdeadbeef );
1524 r = pRemoveClipboardFormatListener( (HWND)0xdead );
1525 ok( !r, "RemoveClipboardFormatListener succeeded\n" );
1526 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
1528 return 0;
1531 static void test_messages(void)
1533 WNDCLASSA cls;
1534 HWND win;
1535 MSG msg;
1536 HANDLE thread;
1537 DWORD tid;
1539 InitializeCriticalSection(&clipboard_cs);
1541 memset(&cls, 0, sizeof(cls));
1542 cls.lpfnWndProc = clipboard_wnd_proc;
1543 cls.hInstance = GetModuleHandleA(NULL);
1544 cls.lpszClassName = "clipboard_test";
1545 RegisterClassA(&cls);
1547 win = CreateWindowA("clipboard_test", NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0);
1548 ok(win != NULL, "CreateWindow failed: %d\n", GetLastError());
1550 thread = CreateThread(NULL, 0, clipboard_thread, (void*)win, 0, &tid);
1551 ok(thread != NULL, "CreateThread failed: %d\n", GetLastError());
1553 while(GetMessageA(&msg, NULL, 0, 0))
1555 ok( msg.message != WM_DRAWCLIPBOARD, "WM_DRAWCLIPBOARD was posted\n" );
1556 TranslateMessage(&msg);
1557 DispatchMessageA(&msg);
1560 ok(WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1561 CloseHandle(thread);
1563 DestroyWindow( win );
1565 /* same tests again but inside a single thread */
1567 win = CreateWindowA( "clipboard_test", NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0 );
1568 ok( win != NULL, "CreateWindow failed: %d\n", GetLastError() );
1570 clipboard_thread( win );
1571 DestroyWindow( win );
1573 UnregisterClassA("clipboard_test", GetModuleHandleA(NULL));
1574 DeleteCriticalSection(&clipboard_cs);
1577 static BOOL is_moveable( HANDLE handle )
1579 void *ptr = GlobalLock( handle );
1580 if (ptr) GlobalUnlock( handle );
1581 return ptr && ptr != handle;
1584 static BOOL is_fixed( HANDLE handle )
1586 void *ptr = GlobalLock( handle );
1587 if (ptr) GlobalUnlock( handle );
1588 return ptr && ptr == handle;
1591 static BOOL is_freed( HANDLE handle )
1593 void *ptr = GlobalLock( handle );
1594 if (ptr) GlobalUnlock( handle );
1595 return !ptr;
1598 static UINT format_id;
1599 static HBITMAP bitmap, bitmap2;
1600 static HPALETTE palette;
1601 static const LOGPALETTE logpalette = { 0x300, 1, {{ 0x12, 0x34, 0x56, 0x78 }}};
1603 static void test_handles( HWND hwnd )
1605 HGLOBAL h, htext, htext2, htext3, htext4, htext5, hfixed, hmoveable, empty_fixed, empty_moveable;
1606 void *ptr;
1607 UINT format_id2 = RegisterClipboardFormatA( "another format" );
1608 BOOL r;
1609 HANDLE data;
1610 HBITMAP bitmap_temp;
1611 DWORD process;
1612 BOOL is_owner = (GetWindowThreadProcessId( hwnd, &process ) && process == GetCurrentProcessId());
1614 trace( "hwnd %p\n", hwnd );
1615 htext = create_textA();
1616 htext2 = create_textA();
1617 htext3 = create_textA();
1618 htext4 = create_textA();
1619 htext5 = create_textA();
1620 bitmap = CreateBitmap( 10, 10, 1, 1, NULL );
1621 bitmap2 = CreateBitmap( 10, 10, 1, 1, NULL );
1622 palette = CreatePalette( &logpalette );
1624 hfixed = GlobalAlloc( GMEM_FIXED, 17 );
1625 ok( is_fixed( hfixed ), "expected fixed mem %p\n", hfixed );
1626 ok( GlobalSize( hfixed ) == 17, "wrong size %lu\n", GlobalSize( hfixed ));
1628 hmoveable = GlobalAlloc( GMEM_MOVEABLE, 23 );
1629 ok( is_moveable( hmoveable ), "expected moveable mem %p\n", hmoveable );
1630 ok( GlobalSize( hmoveable ) == 23, "wrong size %lu\n", GlobalSize( hmoveable ));
1632 empty_fixed = GlobalAlloc( GMEM_FIXED, 0 );
1633 ok( is_fixed( empty_fixed ), "expected fixed mem %p\n", empty_fixed );
1635 empty_moveable = GlobalAlloc( GMEM_MOVEABLE, 0 );
1636 /* discarded handles can't be GlobalLock'ed */
1637 ok( is_freed( empty_moveable ), "expected free mem %p\n", empty_moveable );
1639 r = OpenClipboard( hwnd );
1640 ok( r, "gle %d\n", GetLastError() );
1641 r = EmptyClipboard();
1642 ok( r, "gle %d\n", GetLastError() );
1644 h = SetClipboardData( CF_TEXT, htext );
1645 ok( h == htext, "got %p\n", h );
1646 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1647 h = SetClipboardData( format_id, htext2 );
1648 ok( h == htext2, "got %p\n", h );
1649 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1650 bitmap_temp = CreateBitmap( 10, 10, 1, 1, NULL );
1651 h = SetClipboardData( CF_BITMAP, bitmap_temp );
1652 ok( h == bitmap_temp, "got %p\n", h );
1653 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1654 h = SetClipboardData( CF_BITMAP, bitmap );
1655 ok( h == bitmap, "got %p\n", h );
1656 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1657 ok( !GetObjectType( bitmap_temp ), "expected free object %p\n", bitmap_temp );
1658 h = SetClipboardData( CF_DSPBITMAP, bitmap2 );
1659 ok( h == bitmap2, "got %p\n", h );
1660 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1661 h = SetClipboardData( CF_PALETTE, palette );
1662 ok( h == palette, "got %p\n", h );
1663 ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
1664 h = SetClipboardData( CF_GDIOBJFIRST + 3, htext3 );
1665 ok( h == htext3, "got %p\n", h );
1666 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1667 h = SetClipboardData( CF_PRIVATEFIRST + 7, htext5 );
1668 ok( h == htext5, "got %p\n", h );
1669 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1670 h = SetClipboardData( format_id2, empty_moveable );
1671 ok( !h, "got %p\n", h );
1672 GlobalFree( empty_moveable );
1674 if (0) /* crashes on vista64 */
1676 ptr = HeapAlloc( GetProcessHeap(), 0, 0 );
1677 h = SetClipboardData( format_id2, ptr );
1678 ok( !h, "got %p\n", h );
1679 HeapFree( GetProcessHeap(), 0, ptr );
1682 h = SetClipboardData( format_id2, empty_fixed );
1683 ok( h == empty_fixed, "got %p\n", h );
1684 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1685 h = SetClipboardData( 0xdeadbeef, hfixed );
1686 ok( h == hfixed, "got %p\n", h );
1687 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1688 h = SetClipboardData( 0xdeadbabe, hmoveable );
1689 ok( h == hmoveable, "got %p\n", h );
1690 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1692 ptr = HeapAlloc( GetProcessHeap(), 0, 37 );
1693 h = SetClipboardData( 0xdeadfade, ptr );
1694 ok( h == ptr || !h, "got %p\n", h );
1695 if (!h) /* heap blocks are rejected on >= win8 */
1697 HeapFree( GetProcessHeap(), 0, ptr );
1698 ptr = NULL;
1701 data = GetClipboardData( CF_TEXT );
1702 ok( data == htext, "wrong data %p\n", data );
1703 ok( is_moveable( data ), "expected moveable mem %p\n", data );
1705 data = GetClipboardData( format_id );
1706 ok( data == htext2, "wrong data %p, cf %08x\n", data, format_id );
1707 ok( is_moveable( data ), "expected moveable mem %p\n", data );
1709 data = GetClipboardData( CF_GDIOBJFIRST + 3 );
1710 ok( data == htext3, "wrong data %p\n", data );
1711 ok( is_moveable( data ), "expected moveable mem %p\n", data );
1713 data = GetClipboardData( CF_PRIVATEFIRST + 7 );
1714 ok( data == htext5, "wrong data %p\n", data );
1715 ok( is_moveable( data ), "expected moveable mem %p\n", data );
1717 data = GetClipboardData( format_id2 );
1718 ok( data == empty_fixed, "wrong data %p\n", data );
1719 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1721 data = GetClipboardData( 0xdeadbeef );
1722 ok( data == hfixed, "wrong data %p\n", data );
1723 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1725 data = GetClipboardData( 0xdeadbabe );
1726 ok( data == hmoveable, "wrong data %p\n", data );
1727 ok( is_moveable( data ), "expected moveable mem %p\n", data );
1729 data = GetClipboardData( 0xdeadfade );
1730 ok( data == ptr, "wrong data %p\n", data );
1732 h = SetClipboardData( CF_PRIVATEFIRST + 7, htext4 );
1733 ok( h == htext4, "got %p\n", h );
1734 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1735 ok( is_freed( htext5 ), "expected freed mem %p\n", htext5 );
1737 r = CloseClipboard();
1738 ok( r, "gle %d\n", GetLastError() );
1740 /* data handles are still valid */
1741 ok( is_moveable( htext ), "expected moveable mem %p\n", htext );
1742 ok( is_moveable( htext2 ), "expected moveable mem %p\n", htext2 );
1743 ok( is_moveable( htext3 ), "expected moveable mem %p\n", htext3 );
1744 ok( is_moveable( htext4 ), "expected moveable mem %p\n", htext4 );
1745 ok( GetObjectType( bitmap ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap );
1746 ok( GetObjectType( bitmap2 ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap2 );
1747 ok( GetObjectType( palette ) == OBJ_PAL, "expected palette %p\n", palette );
1748 ok( is_fixed( hfixed ), "expected fixed mem %p\n", hfixed );
1749 ok( is_moveable( hmoveable ), "expected moveable mem %p\n", hmoveable );
1750 ok( is_fixed( empty_fixed ), "expected fixed mem %p\n", empty_fixed );
1752 r = OpenClipboard( hwnd );
1753 ok( r, "gle %d\n", GetLastError() );
1755 /* and now they are freed, unless we are the owner */
1756 if (!is_owner)
1758 ok( is_freed( htext ), "expected freed mem %p\n", htext );
1759 ok( is_freed( htext2 ), "expected freed mem %p\n", htext2 );
1760 ok( is_freed( htext3 ), "expected freed mem %p\n", htext3 );
1761 ok( is_freed( htext4 ), "expected freed mem %p\n", htext4 );
1762 ok( is_freed( hmoveable ), "expected freed mem %p\n", hmoveable );
1764 data = GetClipboardData( CF_TEXT );
1765 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1767 data = GetClipboardData( format_id );
1768 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1770 data = GetClipboardData( CF_GDIOBJFIRST + 3 );
1771 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1773 data = GetClipboardData( CF_PRIVATEFIRST + 7 );
1774 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1776 data = GetClipboardData( format_id2 );
1777 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1778 ok( GlobalSize( data ) == 1, "wrong size %lu\n", GlobalSize( data ));
1780 data = GetClipboardData( 0xdeadbeef );
1781 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1782 ok( GlobalSize( data ) == 17, "wrong size %lu\n", GlobalSize( data ));
1784 data = GetClipboardData( 0xdeadbabe );
1785 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1786 ok( GlobalSize( data ) == 23, "wrong size %lu\n", GlobalSize( data ));
1788 data = GetClipboardData( 0xdeadfade );
1789 ok( is_fixed( data ) || !ptr, "expected fixed mem %p\n", data );
1790 if (ptr) ok( GlobalSize( data ) == 37, "wrong size %lu\n", GlobalSize( data ));
1792 else
1794 ok( is_moveable( htext ), "expected moveable mem %p\n", htext );
1795 ok( is_moveable( htext2 ), "expected moveable mem %p\n", htext2 );
1796 ok( is_moveable( htext3 ), "expected moveable mem %p\n", htext3 );
1797 ok( is_moveable( htext4 ), "expected moveable mem %p\n", htext4 );
1798 ok( is_moveable( hmoveable ), "expected moveable mem %p\n", hmoveable );
1800 data = GetClipboardData( CF_TEXT );
1801 ok( data == htext, "wrong data %p\n", data );
1803 data = GetClipboardData( format_id );
1804 ok( data == htext2, "wrong data %p, cf %08x\n", data, format_id );
1806 data = GetClipboardData( CF_GDIOBJFIRST + 3 );
1807 ok( data == htext3, "wrong data %p\n", data );
1809 data = GetClipboardData( CF_PRIVATEFIRST + 7 );
1810 ok( data == htext4, "wrong data %p\n", data );
1812 data = GetClipboardData( format_id2 );
1813 ok( data == empty_fixed, "wrong data %p\n", data );
1815 data = GetClipboardData( 0xdeadbeef );
1816 ok( data == hfixed, "wrong data %p\n", data );
1818 data = GetClipboardData( 0xdeadbabe );
1819 ok( data == hmoveable, "wrong data %p\n", data );
1821 data = GetClipboardData( 0xdeadfade );
1822 ok( data == ptr, "wrong data %p\n", data );
1825 data = GetClipboardData( CF_OEMTEXT );
1826 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1827 data = GetClipboardData( CF_UNICODETEXT );
1828 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1829 data = GetClipboardData( CF_LOCALE );
1830 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1831 data = GetClipboardData( CF_BITMAP );
1832 ok( data == bitmap, "expected bitmap %p\n", data );
1833 data = GetClipboardData( CF_DSPBITMAP );
1834 ok( data == bitmap2, "expected bitmap %p\n", data );
1835 data = GetClipboardData( CF_PALETTE );
1836 ok( data == palette, "expected palette %p\n", data );
1837 data = GetClipboardData( CF_DIB );
1838 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1839 data = GetClipboardData( CF_DIBV5 );
1840 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1842 ok( GetObjectType( bitmap ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap );
1843 ok( GetObjectType( bitmap2 ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap2 );
1844 ok( GetObjectType( palette ) == OBJ_PAL, "expected palette %p\n", palette );
1845 ok( is_fixed( hfixed ), "expected fixed mem %p\n", hfixed );
1846 ok( is_fixed( empty_fixed ), "expected fixed mem %p\n", empty_fixed );
1848 r = EmptyClipboard();
1849 ok( r, "gle %d\n", GetLastError() );
1851 /* w2003, w2008 don't seem to free the data here */
1852 ok( is_freed( htext ) || broken( !is_freed( htext )), "expected freed mem %p\n", htext );
1853 ok( is_freed( htext2 ) || broken( !is_freed( htext2 )), "expected freed mem %p\n", htext2 );
1854 ok( is_freed( htext3 ) || broken( !is_freed( htext3 )), "expected freed mem %p\n", htext3 );
1855 ok( is_freed( htext4 ) || broken( !is_freed( htext4 )), "expected freed mem %p\n", htext4 );
1856 ok( is_freed( hmoveable ) || broken( !is_freed( hmoveable )), "expected freed mem %p\n", hmoveable );
1857 ok( is_fixed( empty_fixed ), "expected fixed mem %p\n", empty_fixed );
1858 ok( is_fixed( hfixed ), "expected fixed mem %p\n", hfixed );
1859 ok( !GetObjectType( bitmap ), "expected freed handle %p\n", bitmap );
1860 ok( !GetObjectType( bitmap2 ), "expected freed handle %p\n", bitmap2 );
1861 ok( !GetObjectType( palette ), "expected freed handle %p\n", palette );
1863 r = CloseClipboard();
1864 ok( r, "gle %d\n", GetLastError() );
1867 static DWORD WINAPI test_handles_thread( void *arg )
1869 trace( "running from different thread\n" );
1870 test_handles( (HWND)arg );
1871 return 0;
1874 static DWORD WINAPI test_handles_thread2( void *arg )
1876 BOOL r;
1877 HANDLE h;
1878 char *ptr;
1880 r = OpenClipboard( 0 );
1881 ok( r, "gle %d\n", GetLastError() );
1882 h = GetClipboardData( CF_TEXT );
1883 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1884 ptr = GlobalLock( h );
1885 if (ptr) ok( !strcmp( "test", ptr ), "wrong data '%.5s'\n", ptr );
1886 GlobalUnlock( h );
1887 h = GetClipboardData( format_id );
1888 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1889 ptr = GlobalLock( h );
1890 if (ptr) ok( !strcmp( "test", ptr ), "wrong data '%.5s'\n", ptr );
1891 GlobalUnlock( h );
1892 h = GetClipboardData( CF_GDIOBJFIRST + 3 );
1893 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1894 ptr = GlobalLock( h );
1895 if (ptr) ok( !strcmp( "test", ptr ), "wrong data '%.5s'\n", ptr );
1896 GlobalUnlock( h );
1897 trace( "gdiobj %p\n", h );
1898 h = GetClipboardData( CF_PRIVATEFIRST + 7 );
1899 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1900 ptr = GlobalLock( h );
1901 if (ptr) ok( !strcmp( "test", ptr ), "wrong data '%.5s'\n", ptr );
1902 GlobalUnlock( h );
1903 trace( "private %p\n", h );
1904 h = GetClipboardData( CF_BITMAP );
1905 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1906 ok( h == bitmap, "different bitmap %p / %p\n", h, bitmap );
1907 trace( "bitmap %p\n", h );
1908 h = GetClipboardData( CF_DSPBITMAP );
1909 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1910 ok( h == bitmap2, "different bitmap %p / %p\n", h, bitmap2 );
1911 trace( "bitmap2 %p\n", h );
1912 h = GetClipboardData( CF_PALETTE );
1913 ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
1914 ok( h == palette, "different palette %p / %p\n", h, palette );
1915 trace( "palette %p\n", h );
1916 h = GetClipboardData( CF_DIB );
1917 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1918 h = GetClipboardData( CF_DIBV5 );
1919 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1920 r = CloseClipboard();
1921 ok( r, "gle %d\n", GetLastError() );
1922 return 0;
1925 static void test_handles_process( const char *str )
1927 BOOL r;
1928 HANDLE h;
1929 char *ptr;
1930 BITMAP bm;
1931 PALETTEENTRY entry;
1932 BYTE buffer[1024];
1934 format_id = RegisterClipboardFormatA( "my_cool_clipboard_format" );
1935 r = OpenClipboard( 0 );
1936 ok( r, "gle %d\n", GetLastError() );
1937 h = GetClipboardData( CF_TEXT );
1938 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1939 ptr = GlobalLock( h );
1940 ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr );
1941 GlobalUnlock( h );
1942 h = GetClipboardData( format_id );
1943 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1944 ptr = GlobalLock( h );
1945 if (ptr) ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr );
1946 GlobalUnlock( h );
1947 h = GetClipboardData( CF_GDIOBJFIRST + 3 );
1948 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1949 ptr = GlobalLock( h );
1950 ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr );
1951 GlobalUnlock( h );
1952 trace( "gdiobj %p\n", h );
1953 h = GetClipboardData( CF_PRIVATEFIRST + 7 );
1954 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1955 ptr = GlobalLock( h );
1956 ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr );
1957 GlobalUnlock( h );
1958 trace( "private %p\n", h );
1959 h = GetClipboardData( CF_BITMAP );
1960 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1961 ok( GetObjectW( h, sizeof(bm), &bm ) == sizeof(bm), "GetObject %p failed\n", h );
1962 ok( bm.bmWidth == 13 && bm.bmHeight == 17, "wrong bitmap %ux%u\n", bm.bmWidth, bm.bmHeight );
1963 trace( "bitmap %p\n", h );
1964 h = GetClipboardData( CF_DSPBITMAP );
1965 ok( !GetObjectType( h ), "expected invalid object %p\n", h );
1966 trace( "bitmap2 %p\n", h );
1967 h = GetClipboardData( CF_PALETTE );
1968 ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
1969 ok( GetPaletteEntries( h, 0, 1, &entry ) == 1, "GetPaletteEntries %p failed\n", h );
1970 ok( entry.peRed == 0x12 && entry.peGreen == 0x34 && entry.peBlue == 0x56,
1971 "wrong color %02x,%02x,%02x\n", entry.peRed, entry.peGreen, entry.peBlue );
1972 trace( "palette %p\n", h );
1973 h = GetClipboardData( CF_METAFILEPICT );
1974 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1975 ok( GetObjectType( ((METAFILEPICT *)h)->hMF ) == OBJ_METAFILE,
1976 "wrong object %p\n", ((METAFILEPICT *)h)->hMF );
1977 trace( "metafile %p\n", h );
1978 h = GetClipboardData( CF_DSPMETAFILEPICT );
1979 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1980 ok( GetObjectType( ((METAFILEPICT *)h)->hMF ) == OBJ_METAFILE,
1981 "wrong object %p\n", ((METAFILEPICT *)h)->hMF );
1982 trace( "metafile2 %p\n", h );
1983 h = GetClipboardData( CF_ENHMETAFILE );
1984 ok( GetObjectType( h ) == OBJ_ENHMETAFILE, "expected enhmetafile %p\n", h );
1985 ok( GetEnhMetaFileBits( h, sizeof(buffer), buffer ) > sizeof(ENHMETAHEADER),
1986 "GetEnhMetaFileBits failed on %p\n", h );
1987 ok( ((ENHMETAHEADER *)buffer)->nRecords == 3,
1988 "wrong records %u\n", ((ENHMETAHEADER *)buffer)->nRecords );
1989 trace( "enhmetafile %p\n", h );
1990 h = GetClipboardData( CF_DSPENHMETAFILE );
1991 ok( GetObjectType( h ) == OBJ_ENHMETAFILE, "expected enhmetafile %p\n", h );
1992 ok( GetEnhMetaFileBits( h, sizeof(buffer), buffer ) > sizeof(ENHMETAHEADER),
1993 "GetEnhMetaFileBits failed on %p\n", h );
1994 ok( ((ENHMETAHEADER *)buffer)->nRecords == 3,
1995 "wrong records %u\n", ((ENHMETAHEADER *)buffer)->nRecords );
1996 trace( "enhmetafile2 %p\n", h );
1997 h = GetClipboardData( CF_DIB );
1998 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1999 h = GetClipboardData( CF_DIBV5 );
2000 ok( is_fixed( h ), "expected fixed mem %p\n", h );
2001 r = CloseClipboard();
2002 ok( r, "gle %d\n", GetLastError() );
2005 static void test_handles_process_open( const char *str )
2007 HANDLE h, text = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE, strlen(str) + 1 );
2008 char *ptr = GlobalLock( text );
2010 strcpy( ptr, str );
2011 GlobalUnlock( text );
2013 /* clipboard already open by parent process */
2014 h = SetClipboardData( CF_TEXT, text );
2015 ok( h == text, "wrong mem %p / %p\n", h, text );
2016 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2019 static void test_handles_process_dib( const char *str )
2021 BOOL r;
2022 HANDLE h;
2024 r = OpenClipboard( 0 );
2025 ok( r, "gle %d\n", GetLastError() );
2026 h = GetClipboardData( CF_BITMAP );
2027 ok( !GetObjectType( h ), "expected invalid object %p\n", h );
2028 trace( "dibsection %p\n", h );
2029 r = CloseClipboard();
2030 ok( r, "gle %d\n", GetLastError() );
2033 static void test_data_handles(void)
2035 BOOL r;
2036 char *ptr;
2037 HANDLE h, text;
2038 HWND hwnd = CreateWindowA( "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL );
2039 BITMAPINFO bmi;
2040 void *bits;
2042 ok( hwnd != 0, "window creation failed\n" );
2043 format_id = RegisterClipboardFormatA( "my_cool_clipboard_format" );
2044 test_handles( 0 );
2045 test_handles( GetDesktopWindow() );
2046 test_handles( hwnd );
2047 run_thread( test_handles_thread, hwnd, __LINE__ );
2049 bitmap = CreateBitmap( 13, 17, 1, 1, NULL );
2050 bitmap2 = CreateBitmap( 10, 10, 1, 1, NULL );
2051 palette = CreatePalette( &logpalette );
2053 r = OpenClipboard( hwnd );
2054 ok( r, "gle %d\n", GetLastError() );
2055 r = EmptyClipboard();
2056 ok( r, "gle %d\n", GetLastError() );
2057 h = SetClipboardData( CF_TEXT, create_textA() );
2058 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2059 h = SetClipboardData( format_id, create_textA() );
2060 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2061 h = SetClipboardData( CF_BITMAP, bitmap );
2062 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
2063 h = SetClipboardData( CF_DSPBITMAP, bitmap2 );
2064 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
2065 h = SetClipboardData( CF_PALETTE, palette );
2066 ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
2067 h = SetClipboardData( CF_METAFILEPICT, create_metafile() );
2068 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2069 trace( "metafile %p\n", h );
2070 h = SetClipboardData( CF_DSPMETAFILEPICT, create_metafile() );
2071 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2072 trace( "metafile2 %p\n", h );
2073 h = SetClipboardData( CF_ENHMETAFILE, create_emf() );
2074 ok( GetObjectType( h ) == OBJ_ENHMETAFILE, "expected enhmetafile %p\n", h );
2075 trace( "enhmetafile %p\n", h );
2076 h = SetClipboardData( CF_DSPENHMETAFILE, create_emf() );
2077 ok( GetObjectType( h ) == OBJ_ENHMETAFILE, "expected enhmetafile %p\n", h );
2078 trace( "enhmetafile2 %p\n", h );
2079 h = SetClipboardData( CF_GDIOBJFIRST + 3, create_textA() );
2080 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2081 h = SetClipboardData( CF_PRIVATEFIRST + 7, create_textA() );
2082 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2083 r = CloseClipboard();
2084 ok( r, "gle %d\n", GetLastError() );
2086 run_thread( test_handles_thread2, 0, __LINE__ );
2087 run_process( "handles test" );
2089 r = OpenClipboard( hwnd );
2090 ok( r, "gle %d\n", GetLastError() );
2091 h = GetClipboardData( CF_TEXT );
2092 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2093 h = GetClipboardData( format_id );
2094 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2095 h = GetClipboardData( CF_GDIOBJFIRST + 3 );
2096 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2097 h = GetClipboardData( CF_PRIVATEFIRST + 7 );
2098 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2100 r = EmptyClipboard();
2101 ok( r, "gle %d\n", GetLastError() );
2102 text = create_textA();
2103 h = SetClipboardData( CF_TEXT, text );
2104 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2106 run_process( "handles_open foobar" );
2108 ok( is_moveable( text ), "expected moveable mem %p\n", text );
2109 h = GetClipboardData( CF_TEXT );
2110 ok( is_fixed( h ), "expected fixed mem %p\n", h );
2111 ok( is_moveable( text ), "expected moveable mem %p\n", text );
2112 ptr = GlobalLock( h );
2113 ok( !strcmp( ptr, "foobar" ), "wrong data '%.8s'\n", ptr );
2114 GlobalUnlock( h );
2116 r = EmptyClipboard();
2117 ok( r, "gle %d\n", GetLastError() );
2118 ok( is_fixed( h ), "expected free mem %p\n", h );
2119 ok( is_freed( text ) || broken( is_moveable(text) ), /* w2003, w2008 */
2120 "expected free mem %p\n", text );
2121 r = CloseClipboard();
2122 ok( r, "gle %d\n", GetLastError() );
2124 /* test CF_BITMAP with a DIB section */
2125 memset( &bmi, 0, sizeof(bmi) );
2126 bmi.bmiHeader.biSize = sizeof( bmi.bmiHeader );
2127 bmi.bmiHeader.biWidth = 29;
2128 bmi.bmiHeader.biHeight = 13;
2129 bmi.bmiHeader.biPlanes = 1;
2130 bmi.bmiHeader.biBitCount = 32;
2131 bitmap = CreateDIBSection( 0, &bmi, DIB_RGB_COLORS, &bits, 0, 0 );
2133 r = OpenClipboard( hwnd );
2134 ok( r, "gle %d\n", GetLastError() );
2135 r = EmptyClipboard();
2136 ok( r, "gle %d\n", GetLastError() );
2137 h = SetClipboardData( CF_BITMAP, bitmap );
2138 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
2139 trace( "dibsection %p\n", h );
2140 r = CloseClipboard();
2141 ok( r, "gle %d\n", GetLastError() );
2143 run_process( "handles_dib dummy" );
2145 r = OpenClipboard( hwnd );
2146 ok( r, "gle %d\n", GetLastError() );
2147 ok( GetObjectType( bitmap ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap );
2148 r = EmptyClipboard();
2149 ok( r, "gle %d\n", GetLastError() );
2150 ok( !GetObjectType( bitmap ), "expected deleted %p\n", bitmap );
2151 r = CloseClipboard();
2152 ok( r, "gle %d\n", GetLastError() );
2154 DestroyWindow( hwnd );
2157 static void test_GetUpdatedClipboardFormats(void)
2159 BOOL r;
2160 UINT count, formats[256];
2162 if (!pGetUpdatedClipboardFormats)
2164 win_skip( "GetUpdatedClipboardFormats not supported\n" );
2165 return;
2168 count = 0xdeadbeef;
2169 r = pGetUpdatedClipboardFormats( NULL, 0, &count );
2170 ok( r, "gle %d\n", GetLastError() );
2171 ok( !count, "wrong count %u\n", count );
2173 count = 0xdeadbeef;
2174 r = pGetUpdatedClipboardFormats( NULL, 256, &count );
2175 ok( r, "gle %d\n", GetLastError() );
2176 ok( !count, "wrong count %u\n", count );
2178 SetLastError( 0xdeadbeef );
2179 r = pGetUpdatedClipboardFormats( formats, 256, NULL );
2180 ok( !r, "succeeded\n" );
2181 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
2183 count = 0xdeadbeef;
2184 r = pGetUpdatedClipboardFormats( formats, 256, &count );
2185 ok( r, "gle %d\n", GetLastError() );
2186 ok( !count, "wrong count %u\n", count );
2188 r = OpenClipboard( 0 );
2189 ok( r, "gle %d\n", GetLastError() );
2190 r = EmptyClipboard();
2191 ok( r, "gle %d\n", GetLastError() );
2193 count = 0xdeadbeef;
2194 r = pGetUpdatedClipboardFormats( formats, 256, &count );
2195 ok( r, "gle %d\n", GetLastError() );
2196 ok( !count, "wrong count %u\n", count );
2198 SetClipboardData( CF_UNICODETEXT, 0 );
2200 count = 0xdeadbeef;
2201 memset( formats, 0xcc, sizeof(formats) );
2202 r = pGetUpdatedClipboardFormats( formats, 256, &count );
2203 ok( r, "gle %d\n", GetLastError() );
2204 ok( count == 1, "wrong count %u\n", count );
2205 ok( formats[0] == CF_UNICODETEXT, "wrong format %u\n", formats[0] );
2206 ok( formats[1] == 0xcccccccc, "wrong format %u\n", formats[1] );
2208 SetClipboardData( CF_TEXT, 0 );
2209 count = 0xdeadbeef;
2210 memset( formats, 0xcc, sizeof(formats) );
2211 r = pGetUpdatedClipboardFormats( formats, 256, &count );
2212 ok( r, "gle %d\n", GetLastError() );
2213 ok( count == 2, "wrong count %u\n", count );
2214 ok( formats[0] == CF_UNICODETEXT, "wrong format %u\n", formats[0] );
2215 ok( formats[1] == CF_TEXT, "wrong format %u\n", formats[1] );
2216 ok( formats[2] == 0xcccccccc, "wrong format %u\n", formats[2] );
2218 SetLastError( 0xdeadbeef );
2219 count = 0xdeadbeef;
2220 r = pGetUpdatedClipboardFormats( formats, 0, &count );
2221 ok( !r, "succeeded\n" );
2222 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %u\n", GetLastError() );
2223 ok( count == 2, "wrong count %u\n", count );
2225 SetLastError( 0xdeadbeef );
2226 count = 0xdeadbeef;
2227 r = pGetUpdatedClipboardFormats( formats, 1, &count );
2228 ok( !r, "succeeded\n" );
2229 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %u\n", GetLastError() );
2230 ok( count == 2, "wrong count %u\n", count );
2232 r = CloseClipboard();
2233 ok( r, "gle %d\n", GetLastError() );
2235 count = 0xdeadbeef;
2236 memset( formats, 0xcc, sizeof(formats) );
2237 r = pGetUpdatedClipboardFormats( formats, 256, &count );
2238 ok( r, "gle %d\n", GetLastError() );
2239 ok( count == 4, "wrong count %u\n", count );
2240 ok( formats[0] == CF_UNICODETEXT, "wrong format %u\n", formats[0] );
2241 ok( formats[1] == CF_TEXT, "wrong format %u\n", formats[1] );
2242 ok( formats[2] == CF_LOCALE, "wrong format %u\n", formats[2] );
2243 ok( formats[3] == CF_OEMTEXT, "wrong format %u\n", formats[3] );
2244 ok( formats[4] == 0xcccccccc, "wrong format %u\n", formats[4] );
2246 count = 0xdeadbeef;
2247 memset( formats, 0xcc, sizeof(formats) );
2248 r = pGetUpdatedClipboardFormats( formats, 2, &count );
2249 ok( !r, "gle %d\n", GetLastError() );
2250 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %u\n", GetLastError() );
2251 ok( count == 4, "wrong count %u\n", count );
2252 ok( formats[0] == 0xcccccccc, "wrong format %u\n", formats[0] );
2254 count = 0xdeadbeef;
2255 r = pGetUpdatedClipboardFormats( NULL, 256, &count );
2256 ok( !r, "gle %d\n", GetLastError() );
2257 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
2258 ok( count == 4, "wrong count %u\n", count );
2260 count = 0xdeadbeef;
2261 r = pGetUpdatedClipboardFormats( NULL, 256, &count );
2262 ok( !r, "gle %d\n", GetLastError() );
2263 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
2264 ok( count == 4, "wrong count %u\n", count );
2267 START_TEST(clipboard)
2269 char **argv;
2270 int argc = winetest_get_mainargs( &argv );
2271 HMODULE mod = GetModuleHandleA( "user32" );
2273 argv0 = argv[0];
2274 pAddClipboardFormatListener = (void *)GetProcAddress( mod, "AddClipboardFormatListener" );
2275 pRemoveClipboardFormatListener = (void *)GetProcAddress( mod, "RemoveClipboardFormatListener" );
2276 pGetClipboardSequenceNumber = (void *)GetProcAddress( mod, "GetClipboardSequenceNumber" );
2277 pGetUpdatedClipboardFormats = (void *)GetProcAddress( mod, "GetUpdatedClipboardFormats" );
2279 if (argc == 4 && !strcmp( argv[2], "set_clipboard_data" ))
2281 set_clipboard_data_process( atoi( argv[3] ));
2282 return;
2284 if (argc == 4 && !strcmp( argv[2], "grab_clipboard" ))
2286 grab_clipboard_process( atoi( argv[3] ));
2287 return;
2289 if (argc == 4 && !strcmp( argv[2], "handles" ))
2291 test_handles_process( argv[3] );
2292 return;
2294 if (argc == 4 && !strcmp( argv[2], "handles_open" ))
2296 test_handles_process_open( argv[3] );
2297 return;
2299 if (argc == 4 && !strcmp( argv[2], "handles_dib" ))
2301 test_handles_process_dib( argv[3] );
2302 return;
2305 test_RegisterClipboardFormatA();
2306 test_ClipboardOwner();
2307 test_synthesized();
2308 test_messages();
2309 test_data_handles();
2310 test_GetUpdatedClipboardFormats();