user32/tests: Add more tests for clipboard data storage.
[wine.git] / dlls / user32 / tests / clipboard.c
blob2b030cabf931d64f295422912112515ebf28a3f1
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 todo_wine_if( arg == 1 || arg == 3 )
109 ok( IsClipboardFormatAvailable( CF_WAVE ), "process %u: CF_WAVE not available\n", arg );
110 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
111 ok( ret != 0, "process %u: SetClipboardData failed err %u\n", arg, GetLastError() );
113 else
115 SetClipboardData( CF_WAVE, 0 );
116 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "process %u: wrong error %u\n",
117 arg, GetLastError());
118 ok( !IsClipboardFormatAvailable( CF_WAVE ), "process %u: SetClipboardData succeeded\n", arg );
119 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
120 ok( !ret, "process %u: SetClipboardData succeeded\n", arg );
121 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "process %u: wrong error %u\n",
122 arg, GetLastError());
126 static void grab_clipboard_process( int arg )
128 BOOL ret;
130 SetLastError( 0xdeadbeef );
131 ret = OpenClipboard( 0 );
132 ok( ret, "OpenClipboard failed\n" );
133 ret = EmptyClipboard();
134 ok( ret, "EmptyClipboard failed\n" );
135 if (arg)
137 HANDLE ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
138 ok( ret != 0, "process %u: SetClipboardData failed err %u\n", arg, GetLastError() );
142 static void run_thread( LPTHREAD_START_ROUTINE func, void *arg, int line )
144 DWORD ret;
145 HANDLE thread;
147 thread_from_line = line;
148 thread = CreateThread(NULL, 0, func, arg, 0, NULL);
149 ok(thread != NULL, "%u: CreateThread failed with error %d\n", line, GetLastError());
150 for (;;)
152 ret = MsgWaitForMultipleObjectsEx( 1, &thread, 1000, QS_ALLINPUT, 0 );
153 if (ret == WAIT_OBJECT_0 + 1)
155 MSG msg;
156 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
158 else break;
160 ok(ret == WAIT_OBJECT_0, "%u: expected WAIT_OBJECT_0, got %u\n", line, ret);
161 CloseHandle(thread);
164 static void run_process( const char *args )
166 char cmd[MAX_PATH];
167 PROCESS_INFORMATION info;
168 STARTUPINFOA startup;
170 sprintf( cmd, "%s clipboard %s", argv0, args );
171 memset( &startup, 0, sizeof(startup) );
172 startup.cb = sizeof(startup);
173 ok( CreateProcessA( NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info ),
174 "CreateProcess %s failed\n", cmd );
176 winetest_wait_child_process( info.hProcess );
177 CloseHandle( info.hProcess );
178 CloseHandle( info.hThread );
181 static WNDPROC old_proc;
182 static LRESULT CALLBACK winproc_wrapper( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
184 static int wm_renderallformats;
185 static int wm_drawclipboard;
186 static int seqno;
187 DWORD msg_flags = InSendMessageEx( NULL );
189 if (!seqno) seqno = GetClipboardSequenceNumber();
191 trace( "%p msg %04x\n", hwnd, msg );
192 if (!wm_renderallformats)
194 ok( GetClipboardOwner() == hwnd, "%04x: wrong owner %p/%p\n", msg, GetClipboardOwner(), hwnd );
195 ok( seqno == GetClipboardSequenceNumber(), "%04x: seqno changed\n", msg );
197 else
199 ok( !GetClipboardOwner(), "%04x: wrong owner %p\n", msg, GetClipboardOwner() );
200 ok( seqno + 1 == GetClipboardSequenceNumber(), "%04x: seqno unchanged\n", msg );
202 ok( GetClipboardViewer() == hwnd, "%04x: wrong viewer %p/%p\n", msg, GetClipboardViewer(), hwnd );
203 ok( GetOpenClipboardWindow() == hwnd, "%04x: wrong open win %p/%p\n",
204 msg, GetOpenClipboardWindow(), hwnd );
206 switch (msg)
208 case WM_DESTROY:
209 ok( wm_renderallformats, "didn't receive WM_RENDERALLFORMATS before WM_DESTROY\n" );
210 todo_wine ok( wm_drawclipboard, "didn't receive WM_DRAWCLIPBOARD before WM_DESTROY\n" );
211 break;
212 case WM_DRAWCLIPBOARD:
213 ok( msg_flags == ISMEX_NOSEND, "WM_DRAWCLIPBOARD wrong flags %x\n", msg_flags );
214 wm_drawclipboard++;
215 break;
216 case WM_RENDERALLFORMATS:
217 ok( msg_flags == ISMEX_NOSEND, "WM_RENDERALLFORMATS wrong flags %x\n", msg_flags );
218 wm_renderallformats++;
219 break;
221 return old_proc( hwnd, msg, wp, lp );
224 static void test_ClipboardOwner(void)
226 HWND hWnd1, hWnd2;
227 BOOL ret;
229 SetLastError(0xdeadbeef);
230 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef,
231 "could not perform clipboard test: clipboard already owned\n");
233 hWnd1 = CreateWindowExA(0, "static", NULL, WS_POPUP,
234 0, 0, 10, 10, 0, 0, 0, NULL);
235 ok(hWnd1 != 0, "CreateWindowExA error %d\n", GetLastError());
236 trace("hWnd1 = %p\n", hWnd1);
238 hWnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP,
239 0, 0, 10, 10, 0, 0, 0, NULL);
240 ok(hWnd2 != 0, "CreateWindowExA error %d\n", GetLastError());
241 trace("hWnd2 = %p\n", hWnd2);
243 SetLastError(0xdeadbeef);
244 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
245 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */
246 "wrong error %u\n", GetLastError());
248 ok(OpenClipboard(0), "OpenClipboard failed\n");
249 ok(!GetClipboardOwner(), "clipboard should still be not owned\n");
250 ok(!OpenClipboard(hWnd1), "OpenClipboard should fail since clipboard already opened\n");
251 ok(OpenClipboard(0), "OpenClipboard again failed\n");
252 ret = CloseClipboard();
253 ok( ret, "CloseClipboard error %d\n", GetLastError());
255 ok(OpenClipboard(hWnd1), "OpenClipboard failed\n");
256 run_thread( open_clipboard_thread, hWnd1, __LINE__ );
257 run_thread( empty_clipboard_thread, 0, __LINE__ );
258 run_thread( set_clipboard_data_thread, hWnd1, __LINE__ );
259 ok( !IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE available\n" );
260 ok( !GetClipboardData( CF_WAVE ), "CF_WAVE data available\n" );
261 run_process( "set_clipboard_data 0" );
262 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
263 ok(OpenClipboard(hWnd1), "OpenClipboard failed\n");
265 SetLastError(0xdeadbeef);
266 ret = OpenClipboard(hWnd2);
267 ok(!ret && (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED),
268 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
270 SetLastError(0xdeadbeef);
271 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should still be not owned\n");
272 ret = EmptyClipboard();
273 ok( ret, "EmptyClipboard error %d\n", GetLastError());
274 ok(GetClipboardOwner() == hWnd1, "clipboard should be owned by %p, not by %p\n", hWnd1, GetClipboardOwner());
275 run_thread( empty_clipboard_thread, 0, __LINE__ );
276 run_thread( set_clipboard_data_thread, hWnd1, __LINE__ );
277 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
278 ok( GetClipboardData( CF_WAVE ) != 0, "CF_WAVE data not available\n" );
279 run_process( "set_clipboard_data 1" );
281 SetLastError(0xdeadbeef);
282 ret = OpenClipboard(hWnd2);
283 ok(!ret && (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED),
284 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
286 ret = CloseClipboard();
287 ok( ret, "CloseClipboard error %d\n", GetLastError());
288 ok(GetClipboardOwner() == hWnd1, "clipboard should still be owned\n");
290 /* any window will do, even from a different process */
291 ret = OpenClipboard( GetDesktopWindow() );
292 ok( ret, "OpenClipboard error %d\n", GetLastError());
293 ret = EmptyClipboard();
294 ok( ret, "EmptyClipboard error %d\n", GetLastError());
295 ok( GetClipboardOwner() == GetDesktopWindow(), "wrong owner %p/%p\n",
296 GetClipboardOwner(), GetDesktopWindow() );
297 run_thread( set_clipboard_data_thread, GetDesktopWindow(), __LINE__ );
298 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
299 ok( GetClipboardData( CF_WAVE ) != 0, "CF_WAVE data not available\n" );
300 run_process( "set_clipboard_data 2" );
301 ret = CloseClipboard();
302 ok( ret, "CloseClipboard error %d\n", GetLastError());
304 ret = OpenClipboard( hWnd1 );
305 ok( ret, "OpenClipboard error %d\n", GetLastError());
306 ret = EmptyClipboard();
307 ok( ret, "EmptyClipboard error %d\n", GetLastError());
308 SetClipboardData( CF_WAVE, 0 );
309 SetClipboardViewer( hWnd1 );
310 ok( GetClipboardOwner() == hWnd1, "wrong owner %p/%p\n", GetClipboardOwner(), hWnd1 );
311 ok( GetClipboardViewer() == hWnd1, "wrong viewer %p/%p\n", GetClipboardViewer(), hWnd1 );
312 ok( GetOpenClipboardWindow() == hWnd1, "wrong open win %p/%p\n", GetOpenClipboardWindow(), hWnd1 );
313 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
315 old_proc = (WNDPROC)SetWindowLongPtrA( hWnd1, GWLP_WNDPROC, (LONG_PTR)winproc_wrapper );
316 ret = DestroyWindow(hWnd1);
317 ok( ret, "DestroyWindow error %d\n", GetLastError());
318 ret = DestroyWindow(hWnd2);
319 ok( ret, "DestroyWindow error %d\n", GetLastError());
320 SetLastError(0xdeadbeef);
321 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should not be owned\n");
322 ok(!GetClipboardViewer() && GetLastError() == 0xdeadbeef, "viewer still exists\n");
323 ok(!GetOpenClipboardWindow() && GetLastError() == 0xdeadbeef, "clipboard should not be open\n");
324 todo_wine ok( !IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE available\n" );
326 SetLastError( 0xdeadbeef );
327 ret = CloseClipboard();
328 ok( !ret, "CloseClipboard succeeded\n" );
329 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError() );
331 ret = OpenClipboard( 0 );
332 ok( ret, "OpenClipboard error %d\n", GetLastError());
333 run_thread( set_clipboard_data_thread, 0, __LINE__ );
334 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
335 ok( GetClipboardData( CF_WAVE ) != 0, "CF_WAVE data not available\n" );
336 run_process( "set_clipboard_data 3" );
337 ret = CloseClipboard();
338 ok( ret, "CloseClipboard error %d\n", GetLastError());
340 run_thread( open_and_empty_clipboard_thread, 0, __LINE__ );
341 ok( !GetOpenClipboardWindow(), "wrong open window %p\n", GetOpenClipboardWindow() );
342 ok( !GetClipboardOwner(), "wrong owner window %p\n", GetClipboardOwner() );
344 ret = OpenClipboard( 0 );
345 ok( ret, "OpenClipboard error %d\n", GetLastError());
346 run_thread( set_clipboard_data_thread, 0, __LINE__ );
347 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
348 ok( GetClipboardData( CF_WAVE ) != 0, "CF_WAVE data not available\n" );
349 run_process( "set_clipboard_data 4" );
350 ret = EmptyClipboard();
351 ok( ret, "EmptyClipboard error %d\n", GetLastError());
352 ret = CloseClipboard();
353 ok( ret, "CloseClipboard error %d\n", GetLastError());
355 SetLastError( 0xdeadbeef );
356 ok( !SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 )),
357 "SetClipboardData succeeded\n" );
358 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError() );
359 ok( !IsClipboardFormatAvailable( CF_WAVE ), "SetClipboardData succeeded\n" );
361 run_thread( open_and_empty_clipboard_thread, GetDesktopWindow(), __LINE__ );
362 ok( !GetOpenClipboardWindow(), "wrong open window %p\n", GetOpenClipboardWindow() );
363 ok( GetClipboardOwner() == GetDesktopWindow(), "wrong owner window %p / %p\n",
364 GetClipboardOwner(), GetDesktopWindow() );
366 run_thread( open_and_empty_clipboard_win_thread, 0, __LINE__ );
367 ok( !GetOpenClipboardWindow(), "wrong open window %p\n", GetOpenClipboardWindow() );
368 ok( !GetClipboardOwner(), "wrong owner window %p\n", GetClipboardOwner() );
371 static void test_RegisterClipboardFormatA(void)
373 ATOM atom_id;
374 UINT format_id, format_id2;
375 char buf[256];
376 int len;
377 BOOL ret;
378 HANDLE handle;
380 format_id = RegisterClipboardFormatA("my_cool_clipboard_format");
381 ok(format_id > 0xc000 && format_id < 0xffff, "invalid clipboard format id %04x\n", format_id);
383 format_id2 = RegisterClipboardFormatA("MY_COOL_CLIPBOARD_FORMAT");
384 ok(format_id2 == format_id, "invalid clipboard format id %04x\n", format_id2);
386 len = GetClipboardFormatNameA(format_id, buf, 256);
387 ok(len == lstrlenA("my_cool_clipboard_format"), "wrong format name length %d\n", len);
388 ok(!lstrcmpA(buf, "my_cool_clipboard_format"), "wrong format name \"%s\"\n", buf);
390 lstrcpyA(buf, "foo");
391 SetLastError(0xdeadbeef);
392 len = GetAtomNameA((ATOM)format_id, buf, 256);
393 ok(len == 0, "GetAtomNameA should fail\n");
394 ok(GetLastError() == ERROR_INVALID_HANDLE, "err %d\n", GetLastError());
396 todo_wine
398 lstrcpyA(buf, "foo");
399 SetLastError(0xdeadbeef);
400 len = GlobalGetAtomNameA((ATOM)format_id, buf, 256);
401 ok(len == 0, "GlobalGetAtomNameA should fail\n");
402 ok(GetLastError() == ERROR_INVALID_HANDLE, "err %d\n", GetLastError());
405 SetLastError(0xdeadbeef);
406 atom_id = FindAtomA("my_cool_clipboard_format");
407 ok(atom_id == 0, "FindAtomA should fail\n");
408 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError());
410 if (0)
412 /* this relies on the clipboard and global atom table being different */
413 SetLastError(0xdeadbeef);
414 atom_id = GlobalFindAtomA("my_cool_clipboard_format");
415 ok(atom_id == 0, "GlobalFindAtomA should fail\n");
416 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError());
419 for (format_id = 0; format_id < 0xffff; format_id++)
421 SetLastError(0xdeadbeef);
422 len = GetClipboardFormatNameA(format_id, buf, 256);
424 if (format_id < 0xc000)
425 ok(!len, "GetClipboardFormatNameA should fail, but it returned %d (%s)\n", len, buf);
426 else if (len && winetest_debug > 1)
427 trace("%04x: %s\n", format_id, len ? buf : "");
430 ret = OpenClipboard(0);
431 ok( ret, "OpenClipboard error %d\n", GetLastError());
433 /* try some invalid/unregistered formats */
434 SetLastError( 0xdeadbeef );
435 handle = SetClipboardData( 0, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
436 ok( !handle, "SetClipboardData succeeded\n" );
437 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError());
438 handle = SetClipboardData( 0x1234, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
439 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
440 handle = SetClipboardData( 0x123456, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
441 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
442 handle = SetClipboardData( 0xffff8765, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
443 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
445 ok( IsClipboardFormatAvailable( 0x1234 ), "format missing\n" );
446 ok( IsClipboardFormatAvailable( 0x123456 ), "format missing\n" );
447 ok( IsClipboardFormatAvailable( 0xffff8765 ), "format missing\n" );
448 ok( !IsClipboardFormatAvailable( 0 ), "format available\n" );
449 ok( !IsClipboardFormatAvailable( 0x3456 ), "format available\n" );
450 ok( !IsClipboardFormatAvailable( 0x8765 ), "format available\n" );
452 trace("# of formats available: %d\n", CountClipboardFormats());
454 format_id = 0;
455 while ((format_id = EnumClipboardFormats(format_id)))
457 ok(IsClipboardFormatAvailable(format_id), "format %04x was listed as available\n", format_id);
458 len = GetClipboardFormatNameA(format_id, buf, 256);
459 trace("%04x: %s\n", format_id, len ? buf : "");
462 ret = EmptyClipboard();
463 ok( ret, "EmptyClipboard error %d\n", GetLastError());
464 ret =CloseClipboard();
465 ok( ret, "CloseClipboard error %d\n", GetLastError());
467 if (CountClipboardFormats())
469 SetLastError(0xdeadbeef);
470 ok(!EnumClipboardFormats(0), "EnumClipboardFormats should fail if clipboard wasn't open\n");
471 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN,
472 "Last error should be set to ERROR_CLIPBOARD_NOT_OPEN, not %d\n", GetLastError());
475 SetLastError(0xdeadbeef);
476 ok(!EmptyClipboard(), "EmptyClipboard should fail if clipboard wasn't open\n");
477 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */
478 "Wrong error %u\n", GetLastError());
480 format_id = RegisterClipboardFormatA("#1234");
481 ok(format_id == 1234, "invalid clipboard format id %04x\n", format_id);
484 static HGLOBAL create_textA(void)
486 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 5);
487 char *p = GlobalLock(h);
488 strcpy(p, "test");
489 GlobalUnlock(h);
490 return h;
493 static HGLOBAL create_textW(void)
495 static const WCHAR testW[] = {'t','e','s','t',0};
496 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 5 * sizeof(WCHAR));
497 WCHAR *p = GlobalLock(h);
498 lstrcpyW(p, testW);
499 GlobalUnlock(h);
500 return h;
503 static HANDLE create_metafile(void)
505 const RECT rect = {0, 0, 100, 100};
506 METAFILEPICT *pict;
507 HANDLE ret;
508 HMETAFILE mf;
509 HDC hdc = CreateMetaFileA( NULL );
510 ExtTextOutA( hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL );
511 mf = CloseMetaFile( hdc );
512 ret = GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(*pict) );
513 pict = GlobalLock( ret );
514 pict->mm = MM_TEXT;
515 pict->xExt = pict->yExt = 100;
516 pict->hMF = mf;
517 GlobalUnlock( ret );
518 return ret;
521 static HENHMETAFILE create_emf(void)
523 const RECT rect = {0, 0, 100, 100};
524 HDC hdc = CreateEnhMetaFileA(NULL, NULL, &rect, "HENHMETAFILE Ole Clipboard Test\0Test\0\0");
525 ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
526 return CloseEnhMetaFile(hdc);
529 static HBITMAP create_bitmap(void)
531 HDC hdc = GetDC( 0 );
532 UINT bpp = GetDeviceCaps( hdc, BITSPIXEL );
533 ReleaseDC( 0, hdc );
534 return CreateBitmap( 10, 10, 1, bpp, NULL );
537 static HBITMAP create_dib( BOOL v5 )
539 HANDLE ret;
540 BITMAPINFOHEADER *hdr;
542 ret = GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT,
543 sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD) + 16 * 16 * 4 );
544 hdr = GlobalLock( ret );
545 hdr->biSize = v5 ? sizeof(BITMAPV5HEADER) : sizeof(*hdr);
546 hdr->biWidth = 16;
547 hdr->biHeight = 16;
548 hdr->biPlanes = 1;
549 hdr->biBitCount = 32;
550 hdr->biCompression = BI_RGB;
551 if (v5)
553 BITMAPV5HEADER *hdr5 = (BITMAPV5HEADER *)hdr;
554 hdr5->bV5RedMask = 0x0000ff;
555 hdr5->bV5GreenMask = 0x00ff00;
556 hdr5->bV5BlueMask = 0xff0000;
557 hdr5->bV5AlphaMask = 0xff000000;
559 GlobalUnlock( ret );
560 return ret;
563 static LRESULT CALLBACK renderer_winproc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
565 static UINT rendered;
566 UINT ret;
568 switch (msg)
570 case WM_RENDERFORMAT:
571 if (wp < 32) rendered |= (1 << wp);
572 break;
573 case WM_USER:
574 ret = rendered;
575 rendered = 0;
576 return ret;
578 return DefWindowProcA( hwnd, msg, wp, lp );
581 static void test_synthesized(void)
583 static const struct test
585 UINT format;
586 UINT expected[8];
587 } tests[] =
589 /* 0 */ { CF_TEXT, { CF_TEXT, CF_LOCALE, CF_OEMTEXT, CF_UNICODETEXT }},
590 { CF_OEMTEXT, { CF_OEMTEXT, CF_LOCALE, CF_TEXT, CF_UNICODETEXT }},
591 { CF_UNICODETEXT, { CF_UNICODETEXT, CF_LOCALE, CF_TEXT, CF_OEMTEXT }},
592 { CF_ENHMETAFILE, { CF_ENHMETAFILE, CF_METAFILEPICT }},
593 { CF_METAFILEPICT, { CF_METAFILEPICT, CF_ENHMETAFILE }},
594 /* 5 */ { CF_BITMAP, { CF_BITMAP, CF_DIB, CF_DIBV5 }},
595 { CF_DIB, { CF_DIB, CF_BITMAP, CF_DIBV5 }},
596 { CF_DIBV5, { CF_DIBV5, CF_BITMAP, CF_DIB }},
599 HGLOBAL h, htext;
600 HENHMETAFILE emf;
601 BOOL r;
602 UINT cf, i, j, count, rendered;
603 HANDLE data;
604 HWND hwnd;
606 hwnd = CreateWindowA( "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL );
607 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)renderer_winproc );
609 htext = create_textA();
610 emf = create_emf();
612 r = OpenClipboard(NULL);
613 ok(r, "gle %d\n", GetLastError());
614 r = EmptyClipboard();
615 ok(r, "gle %d\n", GetLastError());
616 h = SetClipboardData(CF_TEXT, htext);
617 ok(h == htext, "got %p\n", h);
618 h = SetClipboardData(CF_ENHMETAFILE, emf);
619 ok(h == emf, "got %p\n", h);
620 r = CloseClipboard();
621 ok(r, "gle %d\n", GetLastError());
623 count = CountClipboardFormats();
624 ok( count == 6, "count %u\n", count );
625 r = IsClipboardFormatAvailable( CF_TEXT );
626 ok( r, "CF_TEXT not available err %d\n", GetLastError());
627 r = IsClipboardFormatAvailable( CF_LOCALE );
628 ok( r, "CF_LOCALE not available err %d\n", GetLastError());
629 r = IsClipboardFormatAvailable( CF_OEMTEXT );
630 ok( r, "CF_OEMTEXT not available err %d\n", GetLastError());
631 r = IsClipboardFormatAvailable( CF_UNICODETEXT );
632 ok( r, "CF_UNICODETEXT not available err %d\n", GetLastError());
633 r = IsClipboardFormatAvailable( CF_ENHMETAFILE );
634 ok( r, "CF_ENHMETAFILE not available err %d\n", GetLastError());
635 r = IsClipboardFormatAvailable( CF_METAFILEPICT );
636 ok( r, "CF_METAFILEPICT not available err %d\n", GetLastError());
638 r = OpenClipboard(NULL);
639 ok(r, "gle %d\n", GetLastError());
640 cf = EnumClipboardFormats(0);
641 ok(cf == CF_TEXT, "cf %08x\n", cf);
642 data = GetClipboardData(cf);
643 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
645 cf = EnumClipboardFormats(cf);
646 ok(cf == CF_ENHMETAFILE, "cf %08x\n", cf);
647 data = GetClipboardData(cf);
648 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
650 cf = EnumClipboardFormats(cf);
651 ok(cf == CF_LOCALE, "cf %08x\n", cf);
652 data = GetClipboardData(cf);
653 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
655 cf = EnumClipboardFormats(cf);
656 ok(cf == CF_OEMTEXT, "cf %08x\n", cf);
657 data = GetClipboardData(cf);
658 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
660 cf = EnumClipboardFormats(cf);
661 ok(cf == CF_UNICODETEXT, "cf %08x\n", cf);
663 cf = EnumClipboardFormats(cf);
664 ok(cf == CF_METAFILEPICT, "cf %08x\n", cf);
665 data = GetClipboardData(cf);
666 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
668 cf = EnumClipboardFormats(cf);
669 ok(cf == 0, "cf %08x\n", cf);
671 r = EmptyClipboard();
672 ok(r, "gle %d\n", GetLastError());
674 SetClipboardData( CF_UNICODETEXT, create_textW() );
675 SetClipboardData( CF_TEXT, create_textA() );
676 SetClipboardData( CF_OEMTEXT, create_textA() );
677 r = CloseClipboard();
678 ok(r, "gle %d\n", GetLastError());
680 r = OpenClipboard( NULL );
681 ok(r, "gle %d\n", GetLastError());
682 SetLastError( 0xdeadbeef );
683 cf = EnumClipboardFormats(0);
684 ok( cf == CF_UNICODETEXT, "cf %08x\n", cf );
685 ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() );
686 SetLastError( 0xdeadbeef );
687 cf = EnumClipboardFormats(cf);
688 ok( cf == CF_TEXT, "cf %08x\n", cf );
689 ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() );
690 SetLastError( 0xdeadbeef );
691 cf = EnumClipboardFormats(cf);
692 ok( cf == CF_OEMTEXT, "cf %08x\n", cf );
693 ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() );
694 SetLastError( 0xdeadbeef );
695 cf = EnumClipboardFormats(cf);
696 ok( cf == CF_LOCALE, "cf %08x\n", cf );
697 ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() );
698 SetLastError( 0xdeadbeef );
699 cf = EnumClipboardFormats( cf );
700 ok( cf == 0, "cf %08x\n", cf );
701 ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() );
702 SetLastError( 0xdeadbeef );
703 cf = EnumClipboardFormats( 0xdead );
704 ok( cf == 0, "cf %08x\n", cf );
705 ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() );
707 r = EmptyClipboard();
708 ok(r, "gle %d\n", GetLastError());
710 r = CloseClipboard();
711 ok(r, "gle %d\n", GetLastError());
713 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
715 r = OpenClipboard(NULL);
716 ok(r, "%u: gle %d\n", i, GetLastError());
717 r = EmptyClipboard();
718 ok(r, "%u: gle %d\n", i, GetLastError());
720 switch (tests[i].format)
722 case CF_TEXT:
723 case CF_OEMTEXT:
724 SetClipboardData( tests[i].format, create_textA() );
725 break;
726 case CF_UNICODETEXT:
727 SetClipboardData( CF_UNICODETEXT, create_textW() );
728 break;
729 case CF_ENHMETAFILE:
730 SetClipboardData( CF_ENHMETAFILE, create_emf() );
731 break;
732 case CF_METAFILEPICT:
733 SetClipboardData( CF_METAFILEPICT, create_metafile() );
734 break;
735 case CF_BITMAP:
736 SetClipboardData( CF_BITMAP, create_bitmap() );
737 break;
738 case CF_DIB:
739 case CF_DIBV5:
740 SetClipboardData( tests[i].format, create_dib( tests[i].format == CF_DIBV5 ));
741 break;
744 count = CountClipboardFormats();
745 ok( count == 1, "%u: count %u\n", i, count );
747 r = CloseClipboard();
748 ok(r, "%u: gle %d\n", i, GetLastError());
750 count = CountClipboardFormats();
751 for (j = 0; tests[i].expected[j]; j++)
753 r = IsClipboardFormatAvailable( tests[i].expected[j] );
754 ok( r, "%u: %04x not available\n", i, tests[i].expected[j] );
756 ok( count == j, "%u: count %u instead of %u\n", i, count, j );
758 r = OpenClipboard( hwnd );
759 ok(r, "%u: gle %d\n", i, GetLastError());
760 cf = 0;
761 for (j = 0; tests[i].expected[j]; j++)
763 cf = EnumClipboardFormats( cf );
764 ok(cf == tests[i].expected[j], "%u.%u: got %04x instead of %04x\n",
765 i, j, cf, tests[i].expected[j] );
766 if (cf != tests[i].expected[j]) break;
767 data = GetClipboardData( cf );
768 ok(data != NULL ||
769 broken( tests[i].format == CF_DIBV5 && cf == CF_DIB ), /* >= Vista */
770 "%u: couldn't get data, cf %04x err %d\n", i, cf, GetLastError());
771 if (cf == CF_LOCALE)
773 UINT *ptr = GlobalLock( data );
774 ok( GlobalSize( data ) == sizeof(*ptr), "%u: size %lu\n", i, GlobalSize( data ));
775 ok( *ptr == GetUserDefaultLCID() ||
776 broken( *ptr == MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT )),
777 "%u: CF_LOCALE %08x/%08x\n", i, *ptr, GetUserDefaultLCID() );
778 GlobalUnlock( data );
781 if (!tests[i].expected[j])
783 cf = EnumClipboardFormats( cf );
784 ok(cf == 0, "%u: cf %04x\n", i, cf);
787 /* now with delayed rendering */
789 r = EmptyClipboard();
790 ok(r, "%u: gle %d\n", i, GetLastError());
792 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
793 ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered );
795 SetClipboardData( tests[i].format, 0 );
796 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
797 ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered );
799 count = CountClipboardFormats();
800 ok( count == 1, "%u: count %u\n", i, count );
802 r = CloseClipboard();
803 ok(r, "%u: gle %d\n", i, GetLastError());
804 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
805 ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered );
807 count = CountClipboardFormats();
808 for (j = 0; tests[i].expected[j]; j++)
810 r = IsClipboardFormatAvailable( tests[i].expected[j] );
811 ok( r, "%u: %04x not available\n", i, tests[i].expected[j] );
813 ok( count == j, "%u: count %u instead of %u\n", i, count, j );
814 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
815 ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered );
817 r = OpenClipboard(NULL);
818 ok(r, "%u: gle %d\n", i, GetLastError());
819 cf = 0;
820 for (j = 0; tests[i].expected[j]; j++)
822 cf = EnumClipboardFormats( cf );
823 ok(cf == tests[i].expected[j], "%u.%u: got %04x instead of %04x\n",
824 i, j, cf, tests[i].expected[j] );
825 if (cf != tests[i].expected[j]) break;
826 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
827 ok( !rendered, "%u.%u: formats %08x have been rendered\n", i, j, rendered );
828 data = GetClipboardData( cf );
829 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
830 if (cf == CF_LOCALE)
832 ok(data != NULL, "%u: CF_LOCALE no data\n", i);
833 ok( !rendered, "%u.%u: formats %08x have been rendered\n", i, j, rendered );
835 else
837 ok(!data, "%u: format %04x got data %p\n", i, cf, data);
838 ok( rendered == (1 << tests[i].format),
839 "%u.%u: formats %08x have been rendered\n", i, j, rendered );
840 /* try to render a second time */
841 data = GetClipboardData( cf );
842 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
843 ok( rendered == (1 << tests[i].format),
844 "%u.%u: formats %08x have been rendered\n", i, j, rendered );
847 if (!tests[i].expected[j])
849 cf = EnumClipboardFormats( cf );
850 ok(cf == 0, "%u: cf %04x\n", i, cf);
852 r = CloseClipboard();
853 ok(r, "%u: gle %d\n", i, GetLastError());
854 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
855 ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered );
858 r = OpenClipboard(NULL);
859 ok(r, "gle %d\n", GetLastError());
860 r = EmptyClipboard();
861 ok(r, "gle %d\n", GetLastError());
862 r = CloseClipboard();
863 ok(r, "gle %d\n", GetLastError());
864 DestroyWindow( hwnd );
867 static CRITICAL_SECTION clipboard_cs;
868 static HWND next_wnd;
869 static UINT wm_drawclipboard;
870 static UINT wm_clipboardupdate;
871 static UINT wm_destroyclipboard;
872 static UINT wm_renderformat;
873 static UINT nb_formats;
874 static BOOL cross_thread;
876 static LRESULT CALLBACK clipboard_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
878 LRESULT ret;
879 DWORD msg_flags = InSendMessageEx( NULL );
881 switch(msg) {
882 case WM_DRAWCLIPBOARD:
883 ok( msg_flags == (cross_thread ? ISMEX_NOTIFY : ISMEX_NOSEND),
884 "WM_DRAWCLIPBOARD wrong flags %x\n", msg_flags );
885 EnterCriticalSection(&clipboard_cs);
886 wm_drawclipboard++;
887 LeaveCriticalSection(&clipboard_cs);
888 break;
889 case WM_CHANGECBCHAIN:
890 ok( msg_flags == (cross_thread ? ISMEX_SEND : ISMEX_NOSEND),
891 "WM_CHANGECBCHAIN wrong flags %x\n", msg_flags );
892 if (next_wnd == (HWND)wp)
893 next_wnd = (HWND)lp;
894 else if (next_wnd)
895 SendMessageA(next_wnd, msg, wp, lp);
896 break;
897 case WM_DESTROYCLIPBOARD:
898 ok( msg_flags == (cross_thread ? ISMEX_SEND : ISMEX_NOSEND),
899 "WM_DESTROYCLIPBOARD wrong flags %x\n", msg_flags );
900 wm_destroyclipboard++;
901 ok( GetClipboardOwner() == hwnd, "WM_DESTROYCLIPBOARD owner %p\n", GetClipboardOwner() );
902 nb_formats = CountClipboardFormats();
903 break;
904 case WM_RENDERFORMAT:
905 ok( !wm_renderformat, "multiple WM_RENDERFORMAT %04x / %04lx\n", wm_renderformat, wp );
906 wm_renderformat = wp;
907 break;
908 case WM_CLIPBOARDUPDATE:
909 ok( msg_flags == ISMEX_NOSEND, "WM_CLIPBOARDUPDATE wrong flags %x\n", msg_flags );
910 EnterCriticalSection(&clipboard_cs);
911 wm_clipboardupdate++;
912 LeaveCriticalSection(&clipboard_cs);
913 break;
914 case WM_USER:
915 ChangeClipboardChain(hwnd, next_wnd);
916 PostQuitMessage(0);
917 break;
918 case WM_USER+1:
919 ret = wm_drawclipboard;
920 wm_drawclipboard = 0;
921 return ret;
922 case WM_USER+2:
923 ret = wm_clipboardupdate;
924 wm_clipboardupdate = 0;
925 return ret;
926 case WM_USER+3:
927 ret = wm_destroyclipboard;
928 wm_destroyclipboard = 0;
929 return ret;
930 case WM_USER+4:
931 ret = wm_renderformat;
932 wm_renderformat = 0;
933 return ret;
934 case WM_USER+5:
935 return nb_formats;
938 return DefWindowProcA(hwnd, msg, wp, lp);
941 static DWORD WINAPI clipboard_thread(void *param)
943 HWND ret, win = param;
944 BOOL r;
945 MSG msg;
946 HANDLE handle;
947 UINT count, fmt, formats, old_seq = 0, seq;
949 cross_thread = (GetWindowThreadProcessId( win, NULL ) != GetCurrentThreadId());
950 trace( "%s-threaded test\n", cross_thread ? "multi" : "single" );
952 if (pGetClipboardSequenceNumber) old_seq = pGetClipboardSequenceNumber();
954 EnterCriticalSection(&clipboard_cs);
955 SetLastError(0xdeadbeef);
956 next_wnd = SetClipboardViewer(win);
957 ok(GetLastError() == 0xdeadbeef, "GetLastError = %d\n", GetLastError());
958 LeaveCriticalSection(&clipboard_cs);
960 SetLastError( 0xdeadbeef );
961 ret = SetClipboardViewer( (HWND)0xdead );
962 ok( !ret, "SetClipboardViewer succeeded\n" );
963 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
964 SetLastError( 0xdeadbeef );
965 r = ChangeClipboardChain( win, (HWND)0xdead );
966 ok( !r, "ChangeClipboardChain succeeded\n" );
967 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
968 SetLastError( 0xdeadbeef );
969 r = ChangeClipboardChain( (HWND)0xdead, next_wnd );
970 ok( !r, "ChangeClipboardChain succeeded\n" );
971 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
973 if (pAddClipboardFormatListener)
975 r = pAddClipboardFormatListener(win);
976 ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError());
977 SetLastError( 0xdeadbeef );
978 r = pAddClipboardFormatListener( win );
979 ok( !r, "AddClipboardFormatListener succeeded\n" );
980 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
981 SetLastError( 0xdeadbeef );
982 r = pAddClipboardFormatListener( (HWND)0xdead );
983 ok( !r, "AddClipboardFormatListener succeeded\n" );
984 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
985 r = pAddClipboardFormatListener( GetDesktopWindow() );
986 ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError());
987 r = pRemoveClipboardFormatListener( GetDesktopWindow() );
988 ok( r, "RemoveClipboardFormatListener failed err %d\n", GetLastError());
991 if (pGetClipboardSequenceNumber)
993 seq = pGetClipboardSequenceNumber();
994 ok( seq == old_seq, "sequence changed\n" );
996 if (!cross_thread)
998 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
999 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1000 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1001 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1003 count = SendMessageA( win, WM_USER + 1, 0, 0 );
1004 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1005 count = SendMessageA( win, WM_USER+2, 0, 0 );
1006 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1007 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1008 ok( !fmt, "WM_RENDERFORMAT received\n" );
1010 SetLastError( 0xdeadbeef );
1011 r = OpenClipboard( (HWND)0xdead );
1012 ok( !r, "OpenClipboard succeeded\n" );
1013 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
1015 r = OpenClipboard(win);
1016 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1018 if (pGetClipboardSequenceNumber)
1020 seq = pGetClipboardSequenceNumber();
1021 ok( seq == old_seq, "sequence changed\n" );
1023 if (!cross_thread)
1025 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1026 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1027 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1028 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1030 count = SendMessageA( win, WM_USER+1, 0, 0 );
1031 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1032 count = SendMessageA( win, WM_USER+2, 0, 0 );
1033 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1034 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1035 ok( !fmt, "WM_RENDERFORMAT received\n" );
1037 r = EmptyClipboard();
1038 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
1040 if (pGetClipboardSequenceNumber)
1042 seq = pGetClipboardSequenceNumber();
1043 ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1044 old_seq = seq;
1046 if (!cross_thread)
1048 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1049 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1050 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1051 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1053 count = SendMessageA( win, WM_USER+1, 0, 0 );
1054 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1055 count = SendMessageA( win, WM_USER+2, 0, 0 );
1056 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1057 count = SendMessageA( win, WM_USER+3, 0, 0 );
1058 ok( !count, "WM_DESTROYCLIPBOARD received\n" );
1059 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1060 ok( !fmt, "WM_RENDERFORMAT received\n" );
1062 r = EmptyClipboard();
1063 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
1064 /* sequence changes again, even though it was already empty */
1065 if (pGetClipboardSequenceNumber)
1067 seq = pGetClipboardSequenceNumber();
1068 ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1069 old_seq = seq;
1071 if (!cross_thread)
1073 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1074 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1075 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1076 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1078 count = SendMessageA( win, WM_USER+1, 0, 0 );
1079 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1080 count = SendMessageA( win, WM_USER+2, 0, 0 );
1081 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1082 count = SendMessageA( win, WM_USER+3, 0, 0 );
1083 ok( count, "WM_DESTROYCLIPBOARD not received\n" );
1084 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1085 ok( !fmt, "WM_RENDERFORMAT received\n" );
1086 count = SendMessageA( win, WM_USER+5, 0, 0 );
1087 ok( !count, "wrong format count %u on WM_DESTROYCLIPBOARD\n", count );
1089 handle = SetClipboardData( CF_TEXT, create_textA() );
1090 ok(handle != 0, "SetClipboardData failed: %d\n", GetLastError());
1092 if (pGetClipboardSequenceNumber)
1094 seq = pGetClipboardSequenceNumber();
1095 todo_wine ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1096 old_seq = seq;
1098 if (!cross_thread)
1100 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1101 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1102 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1103 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1105 count = SendMessageA( win, WM_USER+1, 0, 0 );
1106 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1107 count = SendMessageA( win, WM_USER+2, 0, 0 );
1108 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1109 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1110 ok( !fmt, "WM_RENDERFORMAT received\n" );
1112 SetClipboardData( CF_UNICODETEXT, 0 );
1114 if (pGetClipboardSequenceNumber)
1116 seq = pGetClipboardSequenceNumber();
1117 todo_wine ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1118 old_seq = seq;
1120 if (!cross_thread)
1122 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1123 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1124 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1125 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1127 count = SendMessageA( win, WM_USER+1, 0, 0 );
1128 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1129 count = SendMessageA( win, WM_USER+2, 0, 0 );
1130 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1131 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1132 ok( !fmt, "WM_RENDERFORMAT received\n" );
1134 SetClipboardData( CF_UNICODETEXT, 0 ); /* same data again */
1136 if (pGetClipboardSequenceNumber)
1138 seq = pGetClipboardSequenceNumber();
1139 todo_wine ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1140 old_seq = seq;
1142 if (!cross_thread)
1144 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1145 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1146 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1147 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1149 count = SendMessageA( win, WM_USER+1, 0, 0 );
1150 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1151 count = SendMessageA( win, WM_USER+2, 0, 0 );
1152 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1153 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1154 ok( !fmt, "WM_RENDERFORMAT received\n" );
1156 ok( IsClipboardFormatAvailable( CF_TEXT ), "CF_TEXT available\n" );
1157 ok( IsClipboardFormatAvailable( CF_UNICODETEXT ), "CF_UNICODETEXT available\n" );
1158 ok( !IsClipboardFormatAvailable( CF_OEMTEXT ), "CF_OEMTEXT available\n" );
1160 EnterCriticalSection(&clipboard_cs);
1161 r = CloseClipboard();
1162 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1163 LeaveCriticalSection(&clipboard_cs);
1165 if (pGetClipboardSequenceNumber)
1167 seq = pGetClipboardSequenceNumber();
1168 todo_wine ok( (int)(seq - old_seq) == 2, "sequence diff %d\n", seq - old_seq );
1169 old_seq = seq;
1171 if (!cross_thread)
1173 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1174 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1175 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1176 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1178 count = SendMessageA( win, WM_USER+1, 0, 0 );
1179 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1180 count = SendMessageA( win, WM_USER+2, 0, 0 );
1181 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1182 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1183 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1185 r = OpenClipboard(win);
1186 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1188 if (pGetClipboardSequenceNumber)
1190 seq = pGetClipboardSequenceNumber();
1191 ok( seq == old_seq, "sequence changed\n" );
1193 if (!cross_thread)
1195 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1196 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1197 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1199 count = SendMessageA( win, WM_USER+1, 0, 0 );
1200 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1201 count = SendMessageA( win, WM_USER+2, 0, 0 );
1202 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1203 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1204 ok( !fmt, "WM_RENDERFORMAT received\n" );
1206 ok( IsClipboardFormatAvailable( CF_TEXT ), "CF_TEXT available\n" );
1207 ok( IsClipboardFormatAvailable( CF_UNICODETEXT ), "CF_UNICODETEXT available\n" );
1208 ok( IsClipboardFormatAvailable( CF_OEMTEXT ), "CF_OEMTEXT available\n" );
1210 ok( GetClipboardOwner() == win, "wrong owner %p\n", GetClipboardOwner());
1211 handle = GetClipboardData( CF_UNICODETEXT );
1212 ok( !handle, "got data for CF_UNICODETEXT\n" );
1213 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1214 ok( fmt == CF_UNICODETEXT, "WM_RENDERFORMAT received %04x\n", fmt );
1216 handle = GetClipboardData( CF_OEMTEXT );
1217 ok( !handle, "got data for CF_OEMTEXT\n" );
1218 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1219 ok( fmt == CF_UNICODETEXT, "WM_RENDERFORMAT received %04x\n", fmt );
1221 SetClipboardData( CF_WAVE, 0 );
1222 if (pGetClipboardSequenceNumber)
1224 seq = pGetClipboardSequenceNumber();
1225 todo_wine ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1226 old_seq = seq;
1228 if (!cross_thread)
1230 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1231 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1232 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1233 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1235 count = SendMessageA( win, WM_USER+1, 0, 0 );
1236 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1237 count = SendMessageA( win, WM_USER+2, 0, 0 );
1238 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1239 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1240 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1242 r = CloseClipboard();
1243 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1244 if (pGetClipboardSequenceNumber)
1246 /* no synthesized format, so CloseClipboard doesn't change the sequence */
1247 seq = pGetClipboardSequenceNumber();
1248 todo_wine ok( seq == old_seq, "sequence changed\n" );
1249 old_seq = seq;
1251 if (!cross_thread)
1253 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1254 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1255 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1256 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1258 count = SendMessageA( win, WM_USER+1, 0, 0 );
1259 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1260 count = SendMessageA( win, WM_USER+2, 0, 0 );
1261 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1262 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1263 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1265 r = OpenClipboard(win);
1266 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1267 r = CloseClipboard();
1268 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1269 /* nothing changed */
1270 if (pGetClipboardSequenceNumber)
1272 seq = pGetClipboardSequenceNumber();
1273 ok( seq == old_seq, "sequence changed\n" );
1275 if (!cross_thread)
1277 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1278 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1279 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1280 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1282 count = SendMessageA( win, WM_USER+1, 0, 0 );
1283 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1284 count = SendMessageA( win, WM_USER+2, 0, 0 );
1285 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1286 count = SendMessageA( win, WM_USER+3, 0, 0 );
1287 ok( !count, "WM_DESTROYCLIPBOARD received\n" );
1288 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1289 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1291 formats = CountClipboardFormats();
1292 r = OpenClipboard(0);
1293 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1294 r = EmptyClipboard();
1295 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
1296 r = CloseClipboard();
1297 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1299 if (!cross_thread)
1301 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1302 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1303 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1304 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1306 count = SendMessageA( win, WM_USER+1, 0, 0 );
1307 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1308 count = SendMessageA( win, WM_USER+2, 0, 0 );
1309 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1310 count = SendMessageA( win, WM_USER+3, 0, 0 );
1311 ok( count == 1, "WM_DESTROYCLIPBOARD not received\n" );
1312 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1313 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1314 count = SendMessageA( win, WM_USER+5, 0, 0 );
1315 ok( count == formats, "wrong format count %u on WM_DESTROYCLIPBOARD\n", count );
1317 r = OpenClipboard(win);
1318 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1319 SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_FIXED, 1 ));
1320 if (pGetClipboardSequenceNumber)
1322 seq = pGetClipboardSequenceNumber();
1323 ok( (int)(seq - old_seq) == 2, "sequence diff %d\n", seq - old_seq );
1324 old_seq = seq;
1326 if (!cross_thread)
1328 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1329 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1330 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1331 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1333 count = SendMessageA( win, WM_USER+1, 0, 0 );
1334 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1335 count = SendMessageA( win, WM_USER+2, 0, 0 );
1336 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1337 count = SendMessageA( win, WM_USER+3, 0, 0 );
1338 ok( !count, "WM_DESTROYCLIPBOARD received\n" );
1339 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1340 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1342 EnterCriticalSection(&clipboard_cs);
1343 r = CloseClipboard();
1344 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1345 LeaveCriticalSection(&clipboard_cs);
1347 if (pGetClipboardSequenceNumber)
1349 seq = pGetClipboardSequenceNumber();
1350 todo_wine ok( seq == old_seq, "sequence changed\n" );
1351 old_seq = seq;
1353 if (!cross_thread)
1355 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1356 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1357 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1358 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1360 count = SendMessageA( win, WM_USER+1, 0, 0 );
1361 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1362 count = SendMessageA( win, WM_USER+2, 0, 0 );
1363 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1364 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1365 ok( !fmt, "WM_RENDERFORMAT received\n" );
1367 run_process( "grab_clipboard 0" );
1369 if (pGetClipboardSequenceNumber)
1371 seq = pGetClipboardSequenceNumber();
1372 ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1373 old_seq = seq;
1375 if (!cross_thread)
1377 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1378 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1379 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1380 /* in this case we get a cross-thread WM_DRAWCLIPBOARD */
1381 cross_thread = TRUE;
1382 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1383 cross_thread = FALSE;
1385 count = SendMessageA( win, WM_USER+1, 0, 0 );
1386 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1387 count = SendMessageA( win, WM_USER+2, 0, 0 );
1388 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1389 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1390 ok( !fmt, "WM_RENDERFORMAT received\n" );
1392 r = OpenClipboard(0);
1393 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1394 SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_FIXED, 1 ));
1395 if (pGetClipboardSequenceNumber)
1397 seq = pGetClipboardSequenceNumber();
1398 todo_wine ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1399 old_seq = seq;
1401 if (!cross_thread)
1403 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1404 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1405 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1406 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1408 count = SendMessageA( win, WM_USER+1, 0, 0 );
1409 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1410 count = SendMessageA( win, WM_USER+2, 0, 0 );
1411 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1412 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1413 ok( !fmt, "WM_RENDERFORMAT received\n" );
1415 EnterCriticalSection(&clipboard_cs);
1416 r = CloseClipboard();
1417 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1418 LeaveCriticalSection(&clipboard_cs);
1420 if (pGetClipboardSequenceNumber)
1422 seq = pGetClipboardSequenceNumber();
1423 todo_wine ok( seq == old_seq, "sequence changed\n" );
1424 old_seq = seq;
1426 if (!cross_thread)
1428 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD received\n" );
1429 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1430 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1431 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1433 count = SendMessageA( win, WM_USER+1, 0, 0 );
1434 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1435 count = SendMessageA( win, WM_USER+2, 0, 0 );
1436 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1437 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1438 ok( !fmt, "WM_RENDERFORMAT received\n" );
1440 run_process( "grab_clipboard 1" );
1442 if (pGetClipboardSequenceNumber)
1444 seq = pGetClipboardSequenceNumber();
1445 todo_wine_if (!cross_thread)
1446 ok( (int)(seq - old_seq) == 2, "sequence diff %d\n", seq - old_seq );
1447 old_seq = seq;
1449 if (!cross_thread)
1451 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1452 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1453 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1454 /* in this case we get a cross-thread WM_DRAWCLIPBOARD */
1455 cross_thread = TRUE;
1456 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1457 cross_thread = FALSE;
1459 count = SendMessageA( win, WM_USER+1, 0, 0 );
1460 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1461 count = SendMessageA( win, WM_USER+2, 0, 0 );
1462 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1463 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1464 ok( !fmt, "WM_RENDERFORMAT received\n" );
1466 r = OpenClipboard(0);
1467 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1468 SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_FIXED, 1 ));
1469 if (pGetClipboardSequenceNumber)
1471 seq = pGetClipboardSequenceNumber();
1472 todo_wine ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1473 old_seq = seq;
1475 if (!cross_thread)
1477 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1478 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1479 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1480 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1482 count = SendMessageA( win, WM_USER+1, 0, 0 );
1483 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1484 count = SendMessageA( win, WM_USER+2, 0, 0 );
1485 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1486 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1487 ok( !fmt, "WM_RENDERFORMAT received\n" );
1489 EnterCriticalSection(&clipboard_cs);
1490 r = CloseClipboard();
1491 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1492 LeaveCriticalSection(&clipboard_cs);
1494 if (pGetClipboardSequenceNumber)
1496 seq = pGetClipboardSequenceNumber();
1497 todo_wine ok( seq == old_seq, "sequence changed\n" );
1498 old_seq = seq;
1500 if (!cross_thread)
1502 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1503 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1504 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1505 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1507 count = SendMessageA( win, WM_USER+1, 0, 0 );
1508 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1509 count = SendMessageA( win, WM_USER+2, 0, 0 );
1510 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1511 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1512 ok( !fmt, "WM_RENDERFORMAT received\n" );
1514 r = PostMessageA(win, WM_USER, 0, 0);
1515 ok(r, "PostMessage failed: %d\n", GetLastError());
1517 if (pRemoveClipboardFormatListener)
1519 r = pRemoveClipboardFormatListener(win);
1520 ok( r, "RemoveClipboardFormatListener failed err %d\n", GetLastError());
1521 SetLastError( 0xdeadbeef );
1522 r = pRemoveClipboardFormatListener(win);
1523 ok( !r, "RemoveClipboardFormatListener succeeded\n" );
1524 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1525 SetLastError( 0xdeadbeef );
1526 r = pRemoveClipboardFormatListener( (HWND)0xdead );
1527 ok( !r, "RemoveClipboardFormatListener succeeded\n" );
1528 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
1530 return 0;
1533 static void test_messages(void)
1535 WNDCLASSA cls;
1536 HWND win;
1537 MSG msg;
1538 HANDLE thread;
1539 DWORD tid;
1541 InitializeCriticalSection(&clipboard_cs);
1543 memset(&cls, 0, sizeof(cls));
1544 cls.lpfnWndProc = clipboard_wnd_proc;
1545 cls.hInstance = GetModuleHandleA(NULL);
1546 cls.lpszClassName = "clipboard_test";
1547 RegisterClassA(&cls);
1549 win = CreateWindowA("clipboard_test", NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0);
1550 ok(win != NULL, "CreateWindow failed: %d\n", GetLastError());
1552 thread = CreateThread(NULL, 0, clipboard_thread, (void*)win, 0, &tid);
1553 ok(thread != NULL, "CreateThread failed: %d\n", GetLastError());
1555 while(GetMessageA(&msg, NULL, 0, 0))
1557 ok( msg.message != WM_DRAWCLIPBOARD, "WM_DRAWCLIPBOARD was posted\n" );
1558 TranslateMessage(&msg);
1559 DispatchMessageA(&msg);
1562 ok(WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1563 CloseHandle(thread);
1565 DestroyWindow( win );
1567 /* same tests again but inside a single thread */
1569 win = CreateWindowA( "clipboard_test", NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0 );
1570 ok( win != NULL, "CreateWindow failed: %d\n", GetLastError() );
1572 clipboard_thread( win );
1573 DestroyWindow( win );
1575 UnregisterClassA("clipboard_test", GetModuleHandleA(NULL));
1576 DeleteCriticalSection(&clipboard_cs);
1579 static BOOL is_moveable( HANDLE handle )
1581 void *ptr = GlobalLock( handle );
1582 if (ptr) GlobalUnlock( handle );
1583 return ptr && ptr != handle;
1586 static BOOL is_fixed( HANDLE handle )
1588 void *ptr = GlobalLock( handle );
1589 if (ptr) GlobalUnlock( handle );
1590 return ptr && ptr == handle;
1593 static BOOL is_freed( HANDLE handle )
1595 void *ptr = GlobalLock( handle );
1596 if (ptr) GlobalUnlock( handle );
1597 return !ptr;
1600 static UINT format_id;
1601 static HBITMAP bitmap, bitmap2;
1602 static HPALETTE palette;
1603 static const LOGPALETTE logpalette = { 0x300, 1 };
1605 static void test_handles( HWND hwnd )
1607 HGLOBAL h, htext, htext2, htext3, htext4, htext5, hfixed, hmoveable, empty_fixed, empty_moveable;
1608 void *ptr;
1609 UINT format_id2 = RegisterClipboardFormatA( "another format" );
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 htext3 = create_textA();
1619 htext4 = create_textA();
1620 htext5 = create_textA();
1621 bitmap = CreateBitmap( 10, 10, 1, 1, NULL );
1622 bitmap2 = CreateBitmap( 10, 10, 1, 1, NULL );
1623 palette = CreatePalette( &logpalette );
1625 hfixed = GlobalAlloc( GMEM_FIXED, 17 );
1626 ok( is_fixed( hfixed ), "expected fixed mem %p\n", hfixed );
1627 ok( GlobalSize( hfixed ) == 17, "wrong size %lu\n", GlobalSize( hfixed ));
1629 hmoveable = GlobalAlloc( GMEM_MOVEABLE, 23 );
1630 ok( is_moveable( hmoveable ), "expected moveable mem %p\n", hmoveable );
1631 ok( GlobalSize( hmoveable ) == 23, "wrong size %lu\n", GlobalSize( hmoveable ));
1633 empty_fixed = GlobalAlloc( GMEM_FIXED, 0 );
1634 ok( is_fixed( empty_fixed ), "expected fixed mem %p\n", empty_fixed );
1636 empty_moveable = GlobalAlloc( GMEM_MOVEABLE, 0 );
1637 /* discarded handles can't be GlobalLock'ed */
1638 ok( is_freed( empty_moveable ), "expected free mem %p\n", empty_moveable );
1640 r = OpenClipboard( hwnd );
1641 ok( r, "gle %d\n", GetLastError() );
1642 r = EmptyClipboard();
1643 ok( r, "gle %d\n", GetLastError() );
1645 h = SetClipboardData( CF_TEXT, htext );
1646 ok( h == htext, "got %p\n", h );
1647 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1648 h = SetClipboardData( format_id, htext2 );
1649 ok( h == htext2, "got %p\n", h );
1650 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1651 h = SetClipboardData( CF_BITMAP, bitmap );
1652 ok( h == bitmap, "got %p\n", h );
1653 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1654 h = SetClipboardData( CF_DSPBITMAP, bitmap2 );
1655 ok( h == bitmap2, "got %p\n", h );
1656 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1657 h = SetClipboardData( CF_PALETTE, palette );
1658 ok( h == palette, "got %p\n", h );
1659 ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
1660 h = SetClipboardData( CF_GDIOBJFIRST + 3, htext3 );
1661 ok( h == htext3, "got %p\n", h );
1662 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1663 h = SetClipboardData( CF_PRIVATEFIRST + 7, htext5 );
1664 ok( h == htext5, "got %p\n", h );
1665 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1666 h = SetClipboardData( format_id2, empty_moveable );
1667 todo_wine ok( !h, "got %p\n", h );
1668 GlobalFree( empty_moveable );
1670 ptr = HeapAlloc( GetProcessHeap(), 0, 0 );
1671 h = SetClipboardData( format_id2, ptr );
1672 /* some platforms don't allocate a 0-size block correctly */
1673 todo_wine ok( !h || broken( HeapSize( GetProcessHeap(), 0, ptr ) == 1), "got %p\n", h );
1674 HeapFree( GetProcessHeap(), 0, ptr );
1676 h = SetClipboardData( format_id2, empty_fixed );
1677 ok( h == empty_fixed, "got %p\n", h );
1678 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1679 h = SetClipboardData( 0xdeadbeef, hfixed );
1680 ok( h == hfixed, "got %p\n", h );
1681 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1682 h = SetClipboardData( 0xdeadbabe, hmoveable );
1683 ok( h == hmoveable, "got %p\n", h );
1684 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1686 ptr = HeapAlloc( GetProcessHeap(), 0, 37 );
1687 h = SetClipboardData( 0xdeadfade, ptr );
1688 ok( h == ptr || !h, "got %p\n", h );
1689 if (!h) /* heap blocks are rejected on >= win8 */
1691 HeapFree( GetProcessHeap(), 0, ptr );
1692 ptr = NULL;
1695 data = GetClipboardData( CF_TEXT );
1696 ok( data == htext, "wrong data %p\n", data );
1697 ok( is_moveable( data ), "expected moveable mem %p\n", data );
1699 data = GetClipboardData( format_id );
1700 ok( data == htext2, "wrong data %p, cf %08x\n", data, format_id );
1701 ok( is_moveable( data ), "expected moveable mem %p\n", data );
1703 data = GetClipboardData( CF_GDIOBJFIRST + 3 );
1704 ok( data == htext3, "wrong data %p\n", data );
1705 ok( is_moveable( data ), "expected moveable mem %p\n", data );
1707 data = GetClipboardData( CF_PRIVATEFIRST + 7 );
1708 ok( data == htext5, "wrong data %p\n", data );
1709 ok( is_moveable( data ), "expected moveable mem %p\n", data );
1711 data = GetClipboardData( format_id2 );
1712 ok( data == empty_fixed, "wrong data %p\n", data );
1713 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1715 data = GetClipboardData( 0xdeadbeef );
1716 ok( data == hfixed, "wrong data %p\n", data );
1717 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1719 data = GetClipboardData( 0xdeadbabe );
1720 ok( data == hmoveable, "wrong data %p\n", data );
1721 ok( is_moveable( data ), "expected moveable mem %p\n", data );
1723 data = GetClipboardData( 0xdeadfade );
1724 ok( data == ptr, "wrong data %p\n", data );
1726 h = SetClipboardData( CF_PRIVATEFIRST + 7, htext4 );
1727 ok( h == htext4, "got %p\n", h );
1728 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1729 ok( is_freed( htext5 ), "expected freed mem %p\n", htext5 );
1731 r = CloseClipboard();
1732 ok( r, "gle %d\n", GetLastError() );
1734 /* data handles are still valid */
1735 ok( is_moveable( htext ), "expected moveable mem %p\n", htext );
1736 ok( is_moveable( htext2 ), "expected moveable mem %p\n", htext2 );
1737 ok( is_moveable( htext3 ), "expected moveable mem %p\n", htext3 );
1738 ok( is_moveable( htext4 ), "expected moveable mem %p\n", htext4 );
1739 ok( GetObjectType( bitmap ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap );
1740 ok( GetObjectType( bitmap2 ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap2 );
1741 ok( GetObjectType( palette ) == OBJ_PAL, "expected palette %p\n", palette );
1742 ok( is_fixed( hfixed ), "expected fixed mem %p\n", hfixed );
1743 ok( is_moveable( hmoveable ), "expected moveable mem %p\n", hmoveable );
1744 ok( is_fixed( empty_fixed ), "expected fixed mem %p\n", empty_fixed );
1746 r = OpenClipboard( hwnd );
1747 ok( r, "gle %d\n", GetLastError() );
1749 /* and now they are freed, unless we are the owner */
1750 if (!is_owner)
1752 todo_wine ok( is_freed( htext ), "expected freed mem %p\n", htext );
1753 todo_wine ok( is_freed( htext2 ), "expected freed mem %p\n", htext2 );
1754 todo_wine ok( is_freed( htext3 ), "expected freed mem %p\n", htext3 );
1755 todo_wine ok( is_freed( htext4 ), "expected freed mem %p\n", htext4 );
1756 todo_wine ok( is_freed( hmoveable ), "expected freed mem %p\n", hmoveable );
1758 data = GetClipboardData( CF_TEXT );
1759 todo_wine ok( is_fixed( data ), "expected fixed mem %p\n", data );
1761 data = GetClipboardData( format_id );
1762 todo_wine ok( is_fixed( data ), "expected fixed mem %p\n", data );
1764 data = GetClipboardData( CF_GDIOBJFIRST + 3 );
1765 todo_wine ok( is_fixed( data ), "expected fixed mem %p\n", data );
1767 data = GetClipboardData( CF_PRIVATEFIRST + 7 );
1768 todo_wine ok( is_fixed( data ), "expected fixed mem %p\n", data );
1770 data = GetClipboardData( format_id2 );
1771 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1772 ok( GlobalSize( data ) == 1, "wrong size %lu\n", GlobalSize( data ));
1774 data = GetClipboardData( 0xdeadbeef );
1775 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1776 ok( GlobalSize( data ) == 17, "wrong size %lu\n", GlobalSize( data ));
1778 data = GetClipboardData( 0xdeadbabe );
1779 todo_wine ok( is_fixed( data ), "expected fixed mem %p\n", data );
1780 ok( GlobalSize( data ) == 23, "wrong size %lu\n", GlobalSize( data ));
1782 data = GetClipboardData( 0xdeadfade );
1783 ok( is_fixed( data ) || !ptr, "expected fixed mem %p\n", data );
1784 if (ptr) ok( GlobalSize( data ) == 37, "wrong size %lu\n", GlobalSize( data ));
1786 else
1788 ok( is_moveable( htext ), "expected moveable mem %p\n", htext );
1789 ok( is_moveable( htext2 ), "expected moveable mem %p\n", htext2 );
1790 ok( is_moveable( htext3 ), "expected moveable mem %p\n", htext3 );
1791 ok( is_moveable( htext4 ), "expected moveable mem %p\n", htext4 );
1792 ok( is_moveable( hmoveable ), "expected moveable mem %p\n", hmoveable );
1794 data = GetClipboardData( CF_TEXT );
1795 ok( data == htext, "wrong data %p\n", data );
1797 data = GetClipboardData( format_id );
1798 ok( data == htext2, "wrong data %p, cf %08x\n", data, format_id );
1800 data = GetClipboardData( CF_GDIOBJFIRST + 3 );
1801 ok( data == htext3, "wrong data %p\n", data );
1803 data = GetClipboardData( CF_PRIVATEFIRST + 7 );
1804 ok( data == htext4, "wrong data %p\n", data );
1806 data = GetClipboardData( format_id2 );
1807 ok( data == empty_fixed, "wrong data %p\n", data );
1809 data = GetClipboardData( 0xdeadbeef );
1810 ok( data == hfixed, "wrong data %p\n", data );
1812 data = GetClipboardData( 0xdeadbabe );
1813 ok( data == hmoveable, "wrong data %p\n", data );
1815 data = GetClipboardData( 0xdeadfade );
1816 ok( data == ptr, "wrong data %p\n", data );
1819 data = GetClipboardData( CF_OEMTEXT );
1820 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1821 data = GetClipboardData( CF_UNICODETEXT );
1822 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1823 data = GetClipboardData( CF_LOCALE );
1824 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1825 data = GetClipboardData( CF_BITMAP );
1826 ok( data == bitmap, "expected bitmap %p\n", data );
1827 data = GetClipboardData( CF_DSPBITMAP );
1828 ok( data == bitmap2, "expected bitmap %p\n", data );
1829 data = GetClipboardData( CF_PALETTE );
1830 ok( data == palette, "expected palette %p\n", data );
1831 data = GetClipboardData( CF_DIB );
1832 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1833 data = GetClipboardData( CF_DIBV5 );
1834 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1836 ok( GetObjectType( bitmap ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap );
1837 ok( GetObjectType( bitmap2 ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap2 );
1838 ok( GetObjectType( palette ) == OBJ_PAL, "expected palette %p\n", palette );
1839 ok( is_fixed( hfixed ), "expected fixed mem %p\n", hfixed );
1840 ok( is_fixed( empty_fixed ), "expected fixed mem %p\n", empty_fixed );
1842 r = EmptyClipboard();
1843 ok( r, "gle %d\n", GetLastError() );
1845 /* w2003, w2008 don't seem to free the data here */
1846 ok( is_freed( htext ) || broken( !is_freed( htext )), "expected freed mem %p\n", htext );
1847 ok( is_freed( htext2 ) || broken( !is_freed( htext2 )), "expected freed mem %p\n", htext2 );
1848 ok( is_freed( htext3 ) || broken( !is_freed( htext3 )), "expected freed mem %p\n", htext3 );
1849 ok( is_freed( htext4 ) || broken( !is_freed( htext4 )), "expected freed mem %p\n", htext4 );
1850 ok( is_freed( hmoveable ) || broken( !is_freed( hmoveable )), "expected freed mem %p\n", hmoveable );
1851 ok( is_fixed( empty_fixed ), "expected fixed mem %p\n", empty_fixed );
1852 ok( is_fixed( hfixed ), "expected fixed mem %p\n", hfixed );
1853 ok( !GetObjectType( bitmap ), "expected freed handle %p\n", bitmap );
1854 ok( !GetObjectType( bitmap2 ), "expected freed handle %p\n", bitmap2 );
1855 ok( !GetObjectType( palette ), "expected freed handle %p\n", palette );
1857 r = CloseClipboard();
1858 ok( r, "gle %d\n", GetLastError() );
1861 static DWORD WINAPI test_handles_thread( void *arg )
1863 trace( "running from different thread\n" );
1864 test_handles( (HWND)arg );
1865 return 0;
1868 static DWORD WINAPI test_handles_thread2( void *arg )
1870 BOOL r;
1871 HANDLE h;
1872 char *ptr;
1874 r = OpenClipboard( 0 );
1875 ok( r, "gle %d\n", GetLastError() );
1876 h = GetClipboardData( CF_TEXT );
1877 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1878 ptr = GlobalLock( h );
1879 if (ptr) ok( !strcmp( "test", ptr ), "wrong data '%.5s'\n", ptr );
1880 GlobalUnlock( h );
1881 h = GetClipboardData( format_id );
1882 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1883 ptr = GlobalLock( h );
1884 if (ptr) ok( !strcmp( "test", ptr ), "wrong data '%.5s'\n", ptr );
1885 GlobalUnlock( h );
1886 h = GetClipboardData( CF_GDIOBJFIRST + 3 );
1887 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1888 ptr = GlobalLock( h );
1889 if (ptr) ok( !strcmp( "test", ptr ), "wrong data '%.5s'\n", ptr );
1890 GlobalUnlock( h );
1891 trace( "gdiobj %p\n", h );
1892 h = GetClipboardData( CF_PRIVATEFIRST + 7 );
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( "private %p\n", h );
1898 h = GetClipboardData( CF_BITMAP );
1899 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1900 ok( h == bitmap, "different bitmap %p / %p\n", h, bitmap );
1901 trace( "bitmap %p\n", h );
1902 h = GetClipboardData( CF_DSPBITMAP );
1903 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1904 ok( h == bitmap2, "different bitmap %p / %p\n", h, bitmap2 );
1905 trace( "bitmap2 %p\n", h );
1906 h = GetClipboardData( CF_PALETTE );
1907 ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
1908 ok( h == palette, "different palette %p / %p\n", h, palette );
1909 trace( "palette %p\n", h );
1910 h = GetClipboardData( CF_DIB );
1911 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1912 h = GetClipboardData( CF_DIBV5 );
1913 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1914 r = CloseClipboard();
1915 ok( r, "gle %d\n", GetLastError() );
1916 return 0;
1919 static void test_handles_process( const char *str )
1921 BOOL r;
1922 HANDLE h;
1923 char *ptr;
1925 format_id = RegisterClipboardFormatA( "my_cool_clipboard_format" );
1926 r = OpenClipboard( 0 );
1927 ok( r, "gle %d\n", GetLastError() );
1928 h = GetClipboardData( CF_TEXT );
1929 todo_wine_if( !h ) ok( is_fixed( h ), "expected fixed mem %p\n", h );
1930 ptr = GlobalLock( h );
1931 if (ptr) todo_wine ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr );
1932 GlobalUnlock( h );
1933 h = GetClipboardData( format_id );
1934 todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h );
1935 ptr = GlobalLock( h );
1936 if (ptr) ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr );
1937 GlobalUnlock( h );
1938 h = GetClipboardData( CF_GDIOBJFIRST + 3 );
1939 todo_wine_if( !h ) ok( is_fixed( h ), "expected fixed mem %p\n", h );
1940 ptr = GlobalLock( h );
1941 if (ptr) todo_wine ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr );
1942 GlobalUnlock( h );
1943 trace( "gdiobj %p\n", h );
1944 h = GetClipboardData( CF_PRIVATEFIRST + 7 );
1945 todo_wine_if( !h ) ok( is_fixed( h ), "expected fixed mem %p\n", h );
1946 ptr = GlobalLock( h );
1947 if (ptr) todo_wine ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr );
1948 GlobalUnlock( h );
1949 trace( "private %p\n", h );
1950 h = GetClipboardData( CF_BITMAP );
1951 todo_wine ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1952 trace( "bitmap %p\n", h );
1953 h = GetClipboardData( CF_DSPBITMAP );
1954 ok( !GetObjectType( h ), "expected invalid object %p\n", h );
1955 trace( "bitmap2 %p\n", h );
1956 h = GetClipboardData( CF_PALETTE );
1957 todo_wine ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
1958 trace( "palette %p\n", h );
1959 h = GetClipboardData( CF_DIB );
1960 todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h );
1961 h = GetClipboardData( CF_DIBV5 );
1962 todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h );
1963 r = CloseClipboard();
1964 ok( r, "gle %d\n", GetLastError() );
1967 static void test_handles_process_open( const char *str )
1969 HANDLE h, text = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE, strlen(str) + 1 );
1970 char *ptr = GlobalLock( text );
1972 strcpy( ptr, str );
1973 GlobalUnlock( text );
1975 /* clipboard already open by parent process */
1976 h = SetClipboardData( CF_TEXT, text );
1977 ok( h == text, "wrong mem %p / %p\n", h, text );
1978 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1981 static void test_data_handles(void)
1983 BOOL r;
1984 char *ptr;
1985 HANDLE h, text;
1986 HWND hwnd = CreateWindowA( "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL );
1988 ok( hwnd != 0, "window creation failed\n" );
1989 format_id = RegisterClipboardFormatA( "my_cool_clipboard_format" );
1990 test_handles( 0 );
1991 test_handles( GetDesktopWindow() );
1992 test_handles( hwnd );
1993 run_thread( test_handles_thread, hwnd, __LINE__ );
1995 bitmap = CreateBitmap( 10, 10, 1, 1, NULL );
1996 bitmap2 = CreateBitmap( 10, 10, 1, 1, NULL );
1997 palette = CreatePalette( &logpalette );
1999 r = OpenClipboard( hwnd );
2000 ok( r, "gle %d\n", GetLastError() );
2001 r = EmptyClipboard();
2002 ok( r, "gle %d\n", GetLastError() );
2003 h = SetClipboardData( CF_TEXT, create_textA() );
2004 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2005 h = SetClipboardData( format_id, create_textA() );
2006 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2007 h = SetClipboardData( CF_BITMAP, bitmap );
2008 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
2009 h = SetClipboardData( CF_DSPBITMAP, bitmap2 );
2010 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
2011 h = SetClipboardData( CF_PALETTE, palette );
2012 ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
2013 h = SetClipboardData( CF_GDIOBJFIRST + 3, create_textA() );
2014 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2015 h = SetClipboardData( CF_PRIVATEFIRST + 7, create_textA() );
2016 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2017 r = CloseClipboard();
2018 ok( r, "gle %d\n", GetLastError() );
2020 run_thread( test_handles_thread2, 0, __LINE__ );
2021 run_process( "handles test" );
2023 r = OpenClipboard( hwnd );
2024 ok( r, "gle %d\n", GetLastError() );
2025 h = GetClipboardData( CF_TEXT );
2026 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2027 h = GetClipboardData( format_id );
2028 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2029 h = GetClipboardData( CF_GDIOBJFIRST + 3 );
2030 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2031 h = GetClipboardData( CF_PRIVATEFIRST + 7 );
2032 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2034 r = EmptyClipboard();
2035 ok( r, "gle %d\n", GetLastError() );
2036 text = create_textA();
2037 h = SetClipboardData( CF_TEXT, text );
2038 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2040 run_process( "handles_open foobar" );
2042 ok( is_moveable( text ), "expected moveable mem %p\n", text );
2043 h = GetClipboardData( CF_TEXT );
2044 todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h );
2045 ok( is_moveable( text ), "expected moveable mem %p\n", text );
2046 ptr = GlobalLock( h );
2047 if (ptr) todo_wine ok( !strcmp( ptr, "foobar" ), "wrong data '%.8s'\n", ptr );
2048 GlobalUnlock( h );
2050 r = EmptyClipboard();
2051 ok( r, "gle %d\n", GetLastError() );
2052 todo_wine ok( is_fixed( h ), "expected free mem %p\n", h );
2053 ok( is_freed( text ) || broken( is_moveable(text) ), /* w2003, w2008 */
2054 "expected free mem %p\n", text );
2055 r = CloseClipboard();
2056 ok( r, "gle %d\n", GetLastError() );
2058 DestroyWindow( hwnd );
2061 static void test_GetUpdatedClipboardFormats(void)
2063 BOOL r;
2064 UINT count, formats[256];
2066 if (!pGetUpdatedClipboardFormats)
2068 win_skip( "GetUpdatedClipboardFormats not supported\n" );
2069 return;
2072 count = 0xdeadbeef;
2073 r = pGetUpdatedClipboardFormats( NULL, 0, &count );
2074 ok( r, "gle %d\n", GetLastError() );
2075 ok( !count, "wrong count %u\n", count );
2077 count = 0xdeadbeef;
2078 r = pGetUpdatedClipboardFormats( NULL, 256, &count );
2079 ok( r, "gle %d\n", GetLastError() );
2080 ok( !count, "wrong count %u\n", count );
2082 SetLastError( 0xdeadbeef );
2083 r = pGetUpdatedClipboardFormats( formats, 256, NULL );
2084 ok( !r, "succeeded\n" );
2085 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
2087 count = 0xdeadbeef;
2088 r = pGetUpdatedClipboardFormats( formats, 256, &count );
2089 ok( r, "gle %d\n", GetLastError() );
2090 ok( !count, "wrong count %u\n", count );
2092 r = OpenClipboard( 0 );
2093 ok( r, "gle %d\n", GetLastError() );
2094 r = EmptyClipboard();
2095 ok( r, "gle %d\n", GetLastError() );
2097 count = 0xdeadbeef;
2098 r = pGetUpdatedClipboardFormats( formats, 256, &count );
2099 ok( r, "gle %d\n", GetLastError() );
2100 ok( !count, "wrong count %u\n", count );
2102 SetClipboardData( CF_UNICODETEXT, 0 );
2104 count = 0xdeadbeef;
2105 memset( formats, 0xcc, sizeof(formats) );
2106 r = pGetUpdatedClipboardFormats( formats, 256, &count );
2107 ok( r, "gle %d\n", GetLastError() );
2108 ok( count == 1, "wrong count %u\n", count );
2109 ok( formats[0] == CF_UNICODETEXT, "wrong format %u\n", formats[0] );
2110 ok( formats[1] == 0xcccccccc, "wrong format %u\n", formats[1] );
2112 SetClipboardData( CF_TEXT, 0 );
2113 count = 0xdeadbeef;
2114 memset( formats, 0xcc, sizeof(formats) );
2115 r = pGetUpdatedClipboardFormats( formats, 256, &count );
2116 ok( r, "gle %d\n", GetLastError() );
2117 ok( count == 2, "wrong count %u\n", count );
2118 ok( formats[0] == CF_UNICODETEXT, "wrong format %u\n", formats[0] );
2119 ok( formats[1] == CF_TEXT, "wrong format %u\n", formats[1] );
2120 ok( formats[2] == 0xcccccccc, "wrong format %u\n", formats[2] );
2122 SetLastError( 0xdeadbeef );
2123 count = 0xdeadbeef;
2124 r = pGetUpdatedClipboardFormats( formats, 0, &count );
2125 ok( !r, "succeeded\n" );
2126 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %u\n", GetLastError() );
2127 ok( count == 2, "wrong count %u\n", count );
2129 SetLastError( 0xdeadbeef );
2130 count = 0xdeadbeef;
2131 r = pGetUpdatedClipboardFormats( formats, 1, &count );
2132 ok( !r, "succeeded\n" );
2133 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %u\n", GetLastError() );
2134 ok( count == 2, "wrong count %u\n", count );
2136 r = CloseClipboard();
2137 ok( r, "gle %d\n", GetLastError() );
2139 count = 0xdeadbeef;
2140 memset( formats, 0xcc, sizeof(formats) );
2141 r = pGetUpdatedClipboardFormats( formats, 256, &count );
2142 ok( r, "gle %d\n", GetLastError() );
2143 ok( count == 4, "wrong count %u\n", count );
2144 ok( formats[0] == CF_UNICODETEXT, "wrong format %u\n", formats[0] );
2145 ok( formats[1] == CF_TEXT, "wrong format %u\n", formats[1] );
2146 ok( formats[2] == CF_LOCALE, "wrong format %u\n", formats[2] );
2147 ok( formats[3] == CF_OEMTEXT, "wrong format %u\n", formats[3] );
2148 ok( formats[4] == 0xcccccccc, "wrong format %u\n", formats[4] );
2150 count = 0xdeadbeef;
2151 memset( formats, 0xcc, sizeof(formats) );
2152 r = pGetUpdatedClipboardFormats( formats, 2, &count );
2153 ok( !r, "gle %d\n", GetLastError() );
2154 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %u\n", GetLastError() );
2155 ok( count == 4, "wrong count %u\n", count );
2156 ok( formats[0] == 0xcccccccc, "wrong format %u\n", formats[0] );
2158 count = 0xdeadbeef;
2159 r = pGetUpdatedClipboardFormats( NULL, 256, &count );
2160 ok( !r, "gle %d\n", GetLastError() );
2161 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
2162 ok( count == 4, "wrong count %u\n", count );
2164 count = 0xdeadbeef;
2165 r = pGetUpdatedClipboardFormats( NULL, 256, &count );
2166 ok( !r, "gle %d\n", GetLastError() );
2167 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
2168 ok( count == 4, "wrong count %u\n", count );
2171 START_TEST(clipboard)
2173 char **argv;
2174 int argc = winetest_get_mainargs( &argv );
2175 HMODULE mod = GetModuleHandleA( "user32" );
2177 argv0 = argv[0];
2178 pAddClipboardFormatListener = (void *)GetProcAddress( mod, "AddClipboardFormatListener" );
2179 pRemoveClipboardFormatListener = (void *)GetProcAddress( mod, "RemoveClipboardFormatListener" );
2180 pGetClipboardSequenceNumber = (void *)GetProcAddress( mod, "GetClipboardSequenceNumber" );
2181 pGetUpdatedClipboardFormats = (void *)GetProcAddress( mod, "GetUpdatedClipboardFormats" );
2183 if (argc == 4 && !strcmp( argv[2], "set_clipboard_data" ))
2185 set_clipboard_data_process( atoi( argv[3] ));
2186 return;
2188 if (argc == 4 && !strcmp( argv[2], "grab_clipboard" ))
2190 grab_clipboard_process( atoi( argv[3] ));
2191 return;
2193 if (argc == 4 && !strcmp( argv[2], "handles" ))
2195 test_handles_process( argv[3] );
2196 return;
2198 if (argc == 4 && !strcmp( argv[2], "handles_open" ))
2200 test_handles_process_open( argv[3] );
2201 return;
2204 test_RegisterClipboardFormatA();
2205 test_ClipboardOwner();
2206 test_synthesized();
2207 test_messages();
2208 test_data_handles();
2209 test_GetUpdatedClipboardFormats();