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
22 #include "wine/test.h"
29 #define WM_CLIPBOARDUPDATE 0x031D
31 static BOOL (WINAPI
*pAddClipboardFormatListener
)(HWND hwnd
);
32 static BOOL (WINAPI
*pRemoveClipboardFormatListener
)(HWND hwnd
);
33 static DWORD (WINAPI
*pGetClipboardSequenceNumber
)(void);
35 static const BOOL is_win64
= sizeof(void *) > sizeof(int);
36 static int thread_from_line
;
39 static DWORD WINAPI
open_clipboard_thread(LPVOID arg
)
42 ok(OpenClipboard(hWnd
), "%u: OpenClipboard failed\n", thread_from_line
);
46 static DWORD WINAPI
empty_clipboard_thread(LPVOID arg
)
48 SetLastError( 0xdeadbeef );
49 ok(!EmptyClipboard(), "%u: EmptyClipboard succeeded\n", thread_from_line
);
50 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "%u: wrong error %u\n",
51 thread_from_line
, GetLastError());
55 static DWORD WINAPI
open_and_empty_clipboard_thread(LPVOID arg
)
58 ok(OpenClipboard(hWnd
), "%u: OpenClipboard failed\n", thread_from_line
);
59 ok(EmptyClipboard(), "%u: EmptyClipboard failed\n", thread_from_line
);
63 static DWORD WINAPI
open_and_empty_clipboard_win_thread(LPVOID arg
)
65 HWND hwnd
= CreateWindowA( "static", NULL
, WS_POPUP
, 0, 0, 10, 10, 0, 0, 0, NULL
);
66 ok(OpenClipboard(hwnd
), "%u: OpenClipboard failed\n", thread_from_line
);
67 ok(EmptyClipboard(), "%u: EmptyClipboard failed\n", thread_from_line
);
71 static DWORD WINAPI
set_clipboard_data_thread(LPVOID arg
)
76 SetLastError( 0xdeadbeef );
77 if (GetClipboardOwner() == hwnd
)
79 SetClipboardData( CF_WAVE
, 0 );
80 ok( IsClipboardFormatAvailable( CF_WAVE
), "%u: SetClipboardData failed\n", thread_from_line
);
81 ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
82 ok( ret
!= 0, "%u: SetClipboardData failed err %u\n", thread_from_line
, GetLastError() );
83 SetLastError( 0xdeadbeef );
84 ret
= GetClipboardData( CF_WAVE
);
85 ok( !ret
, "%u: GetClipboardData succeeded\n", thread_from_line
);
86 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "%u: wrong error %u\n",
87 thread_from_line
, GetLastError());
91 SetClipboardData( CF_WAVE
, 0 );
92 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "%u: wrong error %u\n",
93 thread_from_line
, GetLastError());
94 ok( !IsClipboardFormatAvailable( CF_WAVE
), "%u: SetClipboardData succeeded\n", thread_from_line
);
95 ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
96 ok( !ret
, "%u: SetClipboardData succeeded\n", thread_from_line
);
97 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "%u: wrong error %u\n",
98 thread_from_line
, GetLastError());
103 static void set_clipboard_data_process( int arg
)
107 SetLastError( 0xdeadbeef );
110 todo_wine_if( arg
== 1 || arg
== 3 )
111 ok( IsClipboardFormatAvailable( CF_WAVE
), "process %u: CF_WAVE not available\n", arg
);
112 ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
113 ok( ret
!= 0, "process %u: SetClipboardData failed err %u\n", arg
, GetLastError() );
117 SetClipboardData( CF_WAVE
, 0 );
118 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "process %u: wrong error %u\n",
119 arg
, GetLastError());
120 ok( !IsClipboardFormatAvailable( CF_WAVE
), "process %u: SetClipboardData succeeded\n", arg
);
121 ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
122 ok( !ret
, "process %u: SetClipboardData succeeded\n", arg
);
123 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "process %u: wrong error %u\n",
124 arg
, GetLastError());
128 static void grab_clipboard_process( int arg
)
132 SetLastError( 0xdeadbeef );
133 ret
= OpenClipboard( 0 );
134 ok( ret
, "OpenClipboard failed\n" );
135 ret
= EmptyClipboard();
136 ok( ret
, "EmptyClipboard failed\n" );
139 HANDLE ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
140 ok( ret
!= 0, "process %u: SetClipboardData failed err %u\n", arg
, GetLastError() );
144 static void run_thread( LPTHREAD_START_ROUTINE func
, void *arg
, int line
)
149 thread_from_line
= line
;
150 thread
= CreateThread(NULL
, 0, func
, arg
, 0, NULL
);
151 ok(thread
!= NULL
, "%u: CreateThread failed with error %d\n", line
, GetLastError());
154 ret
= MsgWaitForMultipleObjectsEx( 1, &thread
, 1000, QS_ALLINPUT
, 0 );
155 if (ret
== WAIT_OBJECT_0
+ 1)
158 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
162 ok(ret
== WAIT_OBJECT_0
, "%u: expected WAIT_OBJECT_0, got %u\n", line
, ret
);
166 static void run_process( const char *args
)
169 PROCESS_INFORMATION info
;
170 STARTUPINFOA startup
;
172 sprintf( cmd
, "%s clipboard %s", argv0
, args
);
173 memset( &startup
, 0, sizeof(startup
) );
174 startup
.cb
= sizeof(startup
);
175 ok( CreateProcessA( NULL
, cmd
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &startup
, &info
),
176 "CreateProcess %s failed\n", cmd
);
178 winetest_wait_child_process( info
.hProcess
);
179 CloseHandle( info
.hProcess
);
180 CloseHandle( info
.hThread
);
183 static WNDPROC old_proc
;
184 static LRESULT CALLBACK
winproc_wrapper( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
186 static int wm_renderallformats
;
187 static int wm_drawclipboard
;
189 DWORD msg_flags
= InSendMessageEx( NULL
);
191 if (!seqno
) seqno
= GetClipboardSequenceNumber();
193 trace( "%p msg %04x\n", hwnd
, msg
);
194 if (!wm_renderallformats
)
196 ok( GetClipboardOwner() == hwnd
, "%04x: wrong owner %p/%p\n", msg
, GetClipboardOwner(), hwnd
);
197 ok( seqno
== GetClipboardSequenceNumber(), "%04x: seqno changed\n", msg
);
201 ok( !GetClipboardOwner(), "%04x: wrong owner %p\n", msg
, GetClipboardOwner() );
202 ok( seqno
+ 1 == GetClipboardSequenceNumber(), "%04x: seqno unchanged\n", msg
);
204 ok( GetClipboardViewer() == hwnd
, "%04x: wrong viewer %p/%p\n", msg
, GetClipboardViewer(), hwnd
);
205 ok( GetOpenClipboardWindow() == hwnd
, "%04x: wrong open win %p/%p\n",
206 msg
, GetOpenClipboardWindow(), hwnd
);
211 ok( wm_renderallformats
, "didn't receive WM_RENDERALLFORMATS before WM_DESTROY\n" );
212 todo_wine
ok( wm_drawclipboard
, "didn't receive WM_DRAWCLIPBOARD before WM_DESTROY\n" );
214 case WM_DRAWCLIPBOARD
:
215 ok( msg_flags
== ISMEX_NOSEND
, "WM_DRAWCLIPBOARD wrong flags %x\n", msg_flags
);
218 case WM_RENDERALLFORMATS
:
219 ok( msg_flags
== ISMEX_NOSEND
, "WM_RENDERALLFORMATS wrong flags %x\n", msg_flags
);
220 wm_renderallformats
++;
223 return old_proc( hwnd
, msg
, wp
, lp
);
226 static void test_ClipboardOwner(void)
231 SetLastError(0xdeadbeef);
232 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef,
233 "could not perform clipboard test: clipboard already owned\n");
235 hWnd1
= CreateWindowExA(0, "static", NULL
, WS_POPUP
,
236 0, 0, 10, 10, 0, 0, 0, NULL
);
237 ok(hWnd1
!= 0, "CreateWindowExA error %d\n", GetLastError());
238 trace("hWnd1 = %p\n", hWnd1
);
240 hWnd2
= CreateWindowExA(0, "static", NULL
, WS_POPUP
,
241 0, 0, 10, 10, 0, 0, 0, NULL
);
242 ok(hWnd2
!= 0, "CreateWindowExA error %d\n", GetLastError());
243 trace("hWnd2 = %p\n", hWnd2
);
245 SetLastError(0xdeadbeef);
246 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
247 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
|| broken(GetLastError() == 0xdeadbeef), /* wow64 */
248 "wrong error %u\n", GetLastError());
250 ok(OpenClipboard(0), "OpenClipboard failed\n");
251 ok(!GetClipboardOwner(), "clipboard should still be not owned\n");
252 ok(!OpenClipboard(hWnd1
), "OpenClipboard should fail since clipboard already opened\n");
253 ok(OpenClipboard(0), "OpenClipboard again failed\n");
254 ret
= CloseClipboard();
255 ok( ret
, "CloseClipboard error %d\n", GetLastError());
257 ok(OpenClipboard(hWnd1
), "OpenClipboard failed\n");
258 run_thread( open_clipboard_thread
, hWnd1
, __LINE__
);
259 run_thread( empty_clipboard_thread
, 0, __LINE__
);
260 run_thread( set_clipboard_data_thread
, hWnd1
, __LINE__
);
261 ok( !IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE available\n" );
262 ok( !GetClipboardData( CF_WAVE
), "CF_WAVE data available\n" );
263 run_process( "set_clipboard_data 0" );
264 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
265 ok(OpenClipboard(hWnd1
), "OpenClipboard failed\n");
267 SetLastError(0xdeadbeef);
268 ret
= OpenClipboard(hWnd2
);
269 ok(!ret
&& (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED
),
270 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
272 SetLastError(0xdeadbeef);
273 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should still be not owned\n");
274 ret
= EmptyClipboard();
275 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
276 ok(GetClipboardOwner() == hWnd1
, "clipboard should be owned by %p, not by %p\n", hWnd1
, GetClipboardOwner());
277 run_thread( empty_clipboard_thread
, 0, __LINE__
);
278 run_thread( set_clipboard_data_thread
, hWnd1
, __LINE__
);
279 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
280 ok( GetClipboardData( CF_WAVE
) != 0, "CF_WAVE data not available\n" );
281 run_process( "set_clipboard_data 1" );
283 SetLastError(0xdeadbeef);
284 ret
= OpenClipboard(hWnd2
);
285 ok(!ret
&& (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED
),
286 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
288 ret
= CloseClipboard();
289 ok( ret
, "CloseClipboard error %d\n", GetLastError());
290 ok(GetClipboardOwner() == hWnd1
, "clipboard should still be owned\n");
292 /* any window will do, even from a different process */
293 ret
= OpenClipboard( GetDesktopWindow() );
294 ok( ret
, "OpenClipboard error %d\n", GetLastError());
295 ret
= EmptyClipboard();
296 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
297 ok( GetClipboardOwner() == GetDesktopWindow(), "wrong owner %p/%p\n",
298 GetClipboardOwner(), GetDesktopWindow() );
299 run_thread( set_clipboard_data_thread
, GetDesktopWindow(), __LINE__
);
300 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
301 ok( GetClipboardData( CF_WAVE
) != 0, "CF_WAVE data not available\n" );
302 run_process( "set_clipboard_data 2" );
303 ret
= CloseClipboard();
304 ok( ret
, "CloseClipboard error %d\n", GetLastError());
306 ret
= OpenClipboard( hWnd1
);
307 ok( ret
, "OpenClipboard error %d\n", GetLastError());
308 ret
= EmptyClipboard();
309 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
310 SetClipboardData( CF_WAVE
, 0 );
311 SetClipboardViewer( hWnd1
);
312 ok( GetClipboardOwner() == hWnd1
, "wrong owner %p/%p\n", GetClipboardOwner(), hWnd1
);
313 ok( GetClipboardViewer() == hWnd1
, "wrong viewer %p/%p\n", GetClipboardViewer(), hWnd1
);
314 ok( GetOpenClipboardWindow() == hWnd1
, "wrong open win %p/%p\n", GetOpenClipboardWindow(), hWnd1
);
315 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
317 old_proc
= (WNDPROC
)SetWindowLongPtrA( hWnd1
, GWLP_WNDPROC
, (LONG_PTR
)winproc_wrapper
);
318 ret
= DestroyWindow(hWnd1
);
319 ok( ret
, "DestroyWindow error %d\n", GetLastError());
320 ret
= DestroyWindow(hWnd2
);
321 ok( ret
, "DestroyWindow error %d\n", GetLastError());
322 SetLastError(0xdeadbeef);
323 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should not be owned\n");
324 ok(!GetClipboardViewer() && GetLastError() == 0xdeadbeef, "viewer still exists\n");
325 ok(!GetOpenClipboardWindow() && GetLastError() == 0xdeadbeef, "clipboard should not be open\n");
326 todo_wine
ok( !IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE available\n" );
328 SetLastError( 0xdeadbeef );
329 ret
= CloseClipboard();
330 ok( !ret
, "CloseClipboard succeeded\n" );
331 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "wrong error %u\n", GetLastError() );
333 ret
= OpenClipboard( 0 );
334 ok( ret
, "OpenClipboard error %d\n", GetLastError());
335 run_thread( set_clipboard_data_thread
, 0, __LINE__
);
336 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
337 ok( GetClipboardData( CF_WAVE
) != 0, "CF_WAVE data not available\n" );
338 run_process( "set_clipboard_data 3" );
339 ret
= CloseClipboard();
340 ok( ret
, "CloseClipboard error %d\n", GetLastError());
342 run_thread( open_and_empty_clipboard_thread
, 0, __LINE__
);
343 ok( !GetOpenClipboardWindow(), "wrong open window %p\n", GetOpenClipboardWindow() );
344 ok( !GetClipboardOwner(), "wrong owner window %p\n", GetClipboardOwner() );
346 ret
= OpenClipboard( 0 );
347 ok( ret
, "OpenClipboard error %d\n", GetLastError());
348 run_thread( set_clipboard_data_thread
, 0, __LINE__
);
349 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
350 ok( GetClipboardData( CF_WAVE
) != 0, "CF_WAVE data not available\n" );
351 run_process( "set_clipboard_data 4" );
352 ret
= EmptyClipboard();
353 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
354 ret
= CloseClipboard();
355 ok( ret
, "CloseClipboard error %d\n", GetLastError());
357 SetLastError( 0xdeadbeef );
358 ok( !SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 )),
359 "SetClipboardData succeeded\n" );
360 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "wrong error %u\n", GetLastError() );
361 ok( !IsClipboardFormatAvailable( CF_WAVE
), "SetClipboardData succeeded\n" );
363 run_thread( open_and_empty_clipboard_thread
, GetDesktopWindow(), __LINE__
);
364 ok( !GetOpenClipboardWindow(), "wrong open window %p\n", GetOpenClipboardWindow() );
365 ok( GetClipboardOwner() == GetDesktopWindow(), "wrong owner window %p / %p\n",
366 GetClipboardOwner(), GetDesktopWindow() );
368 run_thread( open_and_empty_clipboard_win_thread
, 0, __LINE__
);
369 ok( !GetOpenClipboardWindow(), "wrong open window %p\n", GetOpenClipboardWindow() );
370 ok( !GetClipboardOwner(), "wrong owner window %p\n", GetClipboardOwner() );
373 static void test_RegisterClipboardFormatA(void)
376 UINT format_id
, format_id2
;
382 format_id
= RegisterClipboardFormatA("my_cool_clipboard_format");
383 ok(format_id
> 0xc000 && format_id
< 0xffff, "invalid clipboard format id %04x\n", format_id
);
385 format_id2
= RegisterClipboardFormatA("MY_COOL_CLIPBOARD_FORMAT");
386 ok(format_id2
== format_id
, "invalid clipboard format id %04x\n", format_id2
);
388 len
= GetClipboardFormatNameA(format_id
, buf
, 256);
389 ok(len
== lstrlenA("my_cool_clipboard_format"), "wrong format name length %d\n", len
);
390 ok(!lstrcmpA(buf
, "my_cool_clipboard_format"), "wrong format name \"%s\"\n", buf
);
392 lstrcpyA(buf
, "foo");
393 SetLastError(0xdeadbeef);
394 len
= GetAtomNameA((ATOM
)format_id
, buf
, 256);
395 ok(len
== 0, "GetAtomNameA should fail\n");
396 ok(GetLastError() == ERROR_INVALID_HANDLE
, "err %d\n", GetLastError());
400 lstrcpyA(buf
, "foo");
401 SetLastError(0xdeadbeef);
402 len
= GlobalGetAtomNameA((ATOM
)format_id
, buf
, 256);
403 ok(len
== 0, "GlobalGetAtomNameA should fail\n");
404 ok(GetLastError() == ERROR_INVALID_HANDLE
, "err %d\n", GetLastError());
407 SetLastError(0xdeadbeef);
408 atom_id
= FindAtomA("my_cool_clipboard_format");
409 ok(atom_id
== 0, "FindAtomA should fail\n");
410 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "err %d\n", GetLastError());
414 /* this relies on the clipboard and global atom table being different */
415 SetLastError(0xdeadbeef);
416 atom_id
= GlobalFindAtomA("my_cool_clipboard_format");
417 ok(atom_id
== 0, "GlobalFindAtomA should fail\n");
418 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "err %d\n", GetLastError());
421 for (format_id
= 0; format_id
< 0xffff; format_id
++)
423 SetLastError(0xdeadbeef);
424 len
= GetClipboardFormatNameA(format_id
, buf
, 256);
426 if (format_id
< 0xc000)
427 ok(!len
, "GetClipboardFormatNameA should fail, but it returned %d (%s)\n", len
, buf
);
428 else if (len
&& winetest_debug
> 1)
429 trace("%04x: %s\n", format_id
, len
? buf
: "");
432 ret
= OpenClipboard(0);
433 ok( ret
, "OpenClipboard error %d\n", GetLastError());
435 /* try some invalid/unregistered formats */
436 SetLastError( 0xdeadbeef );
437 handle
= SetClipboardData( 0, GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, 1 ));
438 ok( !handle
, "SetClipboardData succeeded\n" );
439 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "wrong error %u\n", GetLastError());
440 handle
= SetClipboardData( 0x1234, GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, 1 ));
441 ok( handle
!= 0, "SetClipboardData failed err %d\n", GetLastError());
442 handle
= SetClipboardData( 0x123456, GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, 1 ));
443 ok( handle
!= 0, "SetClipboardData failed err %d\n", GetLastError());
444 handle
= SetClipboardData( 0xffff8765, GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, 1 ));
445 ok( handle
!= 0, "SetClipboardData failed err %d\n", GetLastError());
447 ok( IsClipboardFormatAvailable( 0x1234 ), "format missing\n" );
448 ok( IsClipboardFormatAvailable( 0x123456 ), "format missing\n" );
449 ok( IsClipboardFormatAvailable( 0xffff8765 ), "format missing\n" );
450 ok( !IsClipboardFormatAvailable( 0 ), "format available\n" );
451 ok( !IsClipboardFormatAvailable( 0x3456 ), "format available\n" );
452 ok( !IsClipboardFormatAvailable( 0x8765 ), "format available\n" );
454 trace("# of formats available: %d\n", CountClipboardFormats());
457 while ((format_id
= EnumClipboardFormats(format_id
)))
459 ok(IsClipboardFormatAvailable(format_id
), "format %04x was listed as available\n", format_id
);
460 len
= GetClipboardFormatNameA(format_id
, buf
, 256);
461 trace("%04x: %s\n", format_id
, len
? buf
: "");
464 ret
= EmptyClipboard();
465 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
466 ret
=CloseClipboard();
467 ok( ret
, "CloseClipboard error %d\n", GetLastError());
469 if (CountClipboardFormats())
471 SetLastError(0xdeadbeef);
472 ok(!EnumClipboardFormats(0), "EnumClipboardFormats should fail if clipboard wasn't open\n");
473 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
,
474 "Last error should be set to ERROR_CLIPBOARD_NOT_OPEN, not %d\n", GetLastError());
477 SetLastError(0xdeadbeef);
478 ok(!EmptyClipboard(), "EmptyClipboard should fail if clipboard wasn't open\n");
479 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
|| broken(GetLastError() == 0xdeadbeef), /* wow64 */
480 "Wrong error %u\n", GetLastError());
482 format_id
= RegisterClipboardFormatA("#1234");
483 ok(format_id
== 1234, "invalid clipboard format id %04x\n", format_id
);
486 static HGLOBAL
create_textA(void)
488 HGLOBAL h
= GlobalAlloc(GMEM_DDESHARE
|GMEM_MOVEABLE
, 5);
489 char *p
= GlobalLock(h
);
495 static HGLOBAL
create_textW(void)
497 static const WCHAR testW
[] = {'t','e','s','t',0};
498 HGLOBAL h
= GlobalAlloc(GMEM_DDESHARE
|GMEM_MOVEABLE
, 5 * sizeof(WCHAR
));
499 WCHAR
*p
= GlobalLock(h
);
505 static HANDLE
create_metafile(void)
507 const RECT rect
= {0, 0, 100, 100};
511 HDC hdc
= CreateMetaFileA( NULL
);
512 ExtTextOutA( hdc
, 0, 0, ETO_OPAQUE
, &rect
, "Test String", strlen("Test String"), NULL
);
513 mf
= CloseMetaFile( hdc
);
514 ret
= GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, sizeof(*pict
) );
515 pict
= GlobalLock( ret
);
517 pict
->xExt
= pict
->yExt
= 100;
523 static HENHMETAFILE
create_emf(void)
525 const RECT rect
= {0, 0, 100, 100};
526 HDC hdc
= CreateEnhMetaFileA(NULL
, NULL
, &rect
, "HENHMETAFILE Ole Clipboard Test\0Test\0\0");
527 ExtTextOutA(hdc
, 0, 0, ETO_OPAQUE
, &rect
, "Test String", strlen("Test String"), NULL
);
528 return CloseEnhMetaFile(hdc
);
531 static HBITMAP
create_bitmap(void)
533 HDC hdc
= GetDC( 0 );
534 UINT bpp
= GetDeviceCaps( hdc
, BITSPIXEL
);
536 return CreateBitmap( 10, 10, 1, bpp
, NULL
);
539 static HBITMAP
create_dib( BOOL v5
)
542 BITMAPINFOHEADER
*hdr
;
544 ret
= GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
| GMEM_ZEROINIT
,
545 sizeof(BITMAPV5HEADER
) + 256 * sizeof(RGBQUAD
) + 16 * 16 * 4 );
546 hdr
= GlobalLock( ret
);
547 hdr
->biSize
= v5
? sizeof(BITMAPV5HEADER
) : sizeof(*hdr
);
551 hdr
->biBitCount
= 32;
552 hdr
->biCompression
= BI_RGB
;
555 BITMAPV5HEADER
*hdr5
= (BITMAPV5HEADER
*)hdr
;
556 hdr5
->bV5RedMask
= 0x0000ff;
557 hdr5
->bV5GreenMask
= 0x00ff00;
558 hdr5
->bV5BlueMask
= 0xff0000;
559 hdr5
->bV5AlphaMask
= 0xff000000;
565 static void test_synthesized(void)
567 static const struct test
574 /* 0 */ { CF_TEXT
, { CF_TEXT
, CF_LOCALE
, CF_OEMTEXT
, CF_UNICODETEXT
}, 1 << 1 },
575 { CF_OEMTEXT
, { CF_OEMTEXT
, CF_LOCALE
, CF_TEXT
, CF_UNICODETEXT
}, 1 << 1 },
576 { CF_UNICODETEXT
, { CF_UNICODETEXT
, CF_LOCALE
, CF_TEXT
, CF_OEMTEXT
}, 1 << 1 },
577 { CF_ENHMETAFILE
, { CF_ENHMETAFILE
, CF_METAFILEPICT
}},
578 { CF_METAFILEPICT
, { CF_METAFILEPICT
, CF_ENHMETAFILE
}},
579 /* 5 */ { CF_BITMAP
, { CF_BITMAP
, CF_DIB
, CF_DIBV5
}, 1 << 2 },
580 { CF_DIB
, { CF_DIB
, CF_BITMAP
, CF_DIBV5
}, 1 << 2 },
581 { CF_DIBV5
, { CF_DIBV5
, CF_BITMAP
, CF_DIB
}, (1 << 1) | (1 << 2) },
587 UINT cf
, i
, j
, count
;
590 htext
= create_textA();
593 r
= OpenClipboard(NULL
);
594 ok(r
, "gle %d\n", GetLastError());
595 r
= EmptyClipboard();
596 ok(r
, "gle %d\n", GetLastError());
597 h
= SetClipboardData(CF_TEXT
, htext
);
598 ok(h
== htext
, "got %p\n", h
);
599 h
= SetClipboardData(CF_ENHMETAFILE
, emf
);
600 ok(h
== emf
, "got %p\n", h
);
601 r
= CloseClipboard();
602 ok(r
, "gle %d\n", GetLastError());
604 count
= CountClipboardFormats();
605 todo_wine
ok( count
== 6, "count %u\n", count
);
606 r
= IsClipboardFormatAvailable( CF_TEXT
);
607 ok( r
, "CF_TEXT not available err %d\n", GetLastError());
608 r
= IsClipboardFormatAvailable( CF_LOCALE
);
609 todo_wine
ok( r
, "CF_LOCALE not available err %d\n", GetLastError());
610 r
= IsClipboardFormatAvailable( CF_OEMTEXT
);
611 ok( r
, "CF_OEMTEXT not available err %d\n", GetLastError());
612 r
= IsClipboardFormatAvailable( CF_UNICODETEXT
);
613 ok( r
, "CF_UNICODETEXT not available err %d\n", GetLastError());
614 r
= IsClipboardFormatAvailable( CF_ENHMETAFILE
);
615 ok( r
, "CF_ENHMETAFILE not available err %d\n", GetLastError());
616 r
= IsClipboardFormatAvailable( CF_METAFILEPICT
);
617 ok( r
, "CF_METAFILEPICT not available err %d\n", GetLastError());
619 r
= OpenClipboard(NULL
);
620 ok(r
, "gle %d\n", GetLastError());
621 cf
= EnumClipboardFormats(0);
622 ok(cf
== CF_TEXT
, "cf %08x\n", cf
);
623 data
= GetClipboardData(cf
);
624 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
626 cf
= EnumClipboardFormats(cf
);
627 ok(cf
== CF_ENHMETAFILE
, "cf %08x\n", cf
);
628 data
= GetClipboardData(cf
);
629 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
631 cf
= EnumClipboardFormats(cf
);
632 todo_wine
ok(cf
== CF_LOCALE
, "cf %08x\n", cf
);
635 data
= GetClipboardData(cf
);
636 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
637 cf
= EnumClipboardFormats(cf
);
639 ok(cf
== CF_OEMTEXT
, "cf %08x\n", cf
);
640 data
= GetClipboardData(cf
);
641 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
643 cf
= EnumClipboardFormats(cf
);
644 ok(cf
== CF_UNICODETEXT
, "cf %08x\n", cf
);
646 cf
= EnumClipboardFormats(cf
);
647 ok(cf
== CF_METAFILEPICT
, "cf %08x\n", cf
);
648 data
= GetClipboardData(cf
);
649 todo_wine
ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
651 cf
= EnumClipboardFormats(cf
);
652 ok(cf
== 0, "cf %08x\n", cf
);
654 r
= EmptyClipboard();
655 ok(r
, "gle %d\n", GetLastError());
657 r
= CloseClipboard();
658 ok(r
, "gle %d\n", GetLastError());
660 for (i
= 0; i
< sizeof(tests
) / sizeof(tests
[0]); i
++)
662 r
= OpenClipboard(NULL
);
663 ok(r
, "%u: gle %d\n", i
, GetLastError());
664 r
= EmptyClipboard();
665 ok(r
, "%u: gle %d\n", i
, GetLastError());
667 switch (tests
[i
].format
)
671 SetClipboardData( tests
[i
].format
, create_textA() );
674 SetClipboardData( CF_UNICODETEXT
, create_textW() );
677 SetClipboardData( CF_ENHMETAFILE
, create_emf() );
679 case CF_METAFILEPICT
:
680 SetClipboardData( CF_METAFILEPICT
, create_metafile() );
683 SetClipboardData( CF_BITMAP
, create_bitmap() );
687 SetClipboardData( tests
[i
].format
, create_dib( tests
[i
].format
== CF_DIBV5
));
691 count
= CountClipboardFormats();
692 ok( count
== 1, "%u: count %u\n", i
, count
);
694 r
= CloseClipboard();
695 ok(r
, "%u: gle %d\n", i
, GetLastError());
697 count
= CountClipboardFormats();
698 for (j
= 0; tests
[i
].expected
[j
]; j
++)
700 r
= IsClipboardFormatAvailable( tests
[i
].expected
[j
] );
701 todo_wine_if (tests
[i
].todo
& (1 << j
))
702 ok( r
, "%u: %04x not available\n", i
, tests
[i
].expected
[j
] );
704 todo_wine_if (tests
[i
].todo
)
705 ok( count
== j
, "%u: count %u instead of %u\n", i
, count
, j
);
707 r
= OpenClipboard(NULL
);
708 ok(r
, "%u: gle %d\n", i
, GetLastError());
710 for (j
= 0; tests
[i
].expected
[j
]; j
++)
712 cf
= EnumClipboardFormats( cf
);
713 todo_wine_if (tests
[i
].todo
& (1 << j
))
714 ok(cf
== tests
[i
].expected
[j
], "%u.%u: got %04x instead of %04x\n",
715 i
, j
, cf
, tests
[i
].expected
[j
] );
716 if (cf
!= tests
[i
].expected
[j
]) break;
717 data
= GetClipboardData( cf
);
718 todo_wine_if (j
&& cf
== CF_METAFILEPICT
)
720 broken( tests
[i
].format
== CF_DIBV5
&& cf
== CF_DIB
), /* >= Vista */
721 "%u: couldn't get data, cf %04x err %d\n", i
, cf
, GetLastError());
724 UINT
*ptr
= GlobalLock( data
);
725 ok( GlobalSize( data
) == sizeof(*ptr
), "%u: size %lu\n", i
, GlobalSize( data
));
726 ok( *ptr
== GetUserDefaultLCID() ||
727 broken( *ptr
== MAKELANGID( LANG_ENGLISH
, SUBLANG_DEFAULT
)),
728 "%u: CF_LOCALE %08x/%08x\n", i
, *ptr
, GetUserDefaultLCID() );
729 GlobalUnlock( data
);
732 if (!tests
[i
].expected
[j
])
734 cf
= EnumClipboardFormats( cf
);
735 ok(cf
== 0, "%u: cf %04x\n", i
, cf
);
738 /* now with delayed rendering */
740 r
= EmptyClipboard();
741 ok(r
, "%u: gle %d\n", i
, GetLastError());
743 SetClipboardData( tests
[i
].format
, 0 );
745 count
= CountClipboardFormats();
746 ok( count
== 1, "%u: count %u\n", i
, count
);
748 r
= CloseClipboard();
749 ok(r
, "%u: gle %d\n", i
, GetLastError());
751 count
= CountClipboardFormats();
752 for (j
= 0; tests
[i
].expected
[j
]; j
++)
754 r
= IsClipboardFormatAvailable( tests
[i
].expected
[j
] );
755 todo_wine_if (tests
[i
].todo
& (1 << j
))
756 ok( r
, "%u: %04x not available\n", i
, tests
[i
].expected
[j
] );
758 todo_wine_if (tests
[i
].todo
)
759 ok( count
== j
, "%u: count %u instead of %u\n", i
, count
, j
);
761 r
= OpenClipboard(NULL
);
762 ok(r
, "%u: gle %d\n", i
, GetLastError());
764 for (j
= 0; tests
[i
].expected
[j
]; j
++)
766 cf
= EnumClipboardFormats( cf
);
767 todo_wine_if (tests
[i
].todo
& (1 << j
))
768 ok(cf
== tests
[i
].expected
[j
], "%u.%u: got %04x instead of %04x\n",
769 i
, j
, cf
, tests
[i
].expected
[j
] );
770 if (cf
!= tests
[i
].expected
[j
]) break;
771 data
= GetClipboardData( cf
);
773 ok(data
!= NULL
, "%u: CF_LOCALE no data\n", i
);
775 ok(!data
, "%u: format %04x got data %p\n", i
, cf
, data
);
777 if (!tests
[i
].expected
[j
])
779 cf
= EnumClipboardFormats( cf
);
780 ok(cf
== 0, "%u: cf %04x\n", i
, cf
);
782 r
= CloseClipboard();
783 ok(r
, "%u: gle %d\n", i
, GetLastError());
786 r
= OpenClipboard(NULL
);
787 ok(r
, "gle %d\n", GetLastError());
788 r
= EmptyClipboard();
789 ok(r
, "gle %d\n", GetLastError());
790 r
= CloseClipboard();
791 ok(r
, "gle %d\n", GetLastError());
794 static CRITICAL_SECTION clipboard_cs
;
795 static HWND next_wnd
;
796 static UINT wm_drawclipboard
;
797 static UINT wm_clipboardupdate
;
798 static UINT wm_destroyclipboard
;
799 static UINT wm_renderformat
;
800 static UINT nb_formats
;
801 static BOOL cross_thread
;
803 static LRESULT CALLBACK
clipboard_wnd_proc(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
806 DWORD msg_flags
= InSendMessageEx( NULL
);
809 case WM_DRAWCLIPBOARD
:
810 ok( msg_flags
== (cross_thread
? ISMEX_NOTIFY
: ISMEX_NOSEND
),
811 "WM_DRAWCLIPBOARD wrong flags %x\n", msg_flags
);
812 EnterCriticalSection(&clipboard_cs
);
814 LeaveCriticalSection(&clipboard_cs
);
816 case WM_CHANGECBCHAIN
:
817 ok( msg_flags
== (cross_thread
? ISMEX_SEND
: ISMEX_NOSEND
),
818 "WM_CHANGECBCHAIN wrong flags %x\n", msg_flags
);
819 if (next_wnd
== (HWND
)wp
)
822 SendMessageA(next_wnd
, msg
, wp
, lp
);
824 case WM_DESTROYCLIPBOARD
:
825 ok( msg_flags
== (cross_thread
? ISMEX_SEND
: ISMEX_NOSEND
),
826 "WM_DESTROYCLIPBOARD wrong flags %x\n", msg_flags
);
827 wm_destroyclipboard
++;
828 ok( GetClipboardOwner() == hwnd
, "WM_DESTROYCLIPBOARD owner %p\n", GetClipboardOwner() );
829 nb_formats
= CountClipboardFormats();
831 case WM_RENDERFORMAT
:
832 ok( !wm_renderformat
, "multiple WM_RENDERFORMAT %04x / %04lx\n", wm_renderformat
, wp
);
833 wm_renderformat
= wp
;
835 case WM_CLIPBOARDUPDATE
:
836 ok( msg_flags
== ISMEX_NOSEND
, "WM_CLIPBOARDUPDATE wrong flags %x\n", msg_flags
);
837 EnterCriticalSection(&clipboard_cs
);
838 wm_clipboardupdate
++;
839 LeaveCriticalSection(&clipboard_cs
);
842 ChangeClipboardChain(hwnd
, next_wnd
);
846 ret
= wm_drawclipboard
;
847 wm_drawclipboard
= 0;
850 ret
= wm_clipboardupdate
;
851 wm_clipboardupdate
= 0;
854 ret
= wm_destroyclipboard
;
855 wm_destroyclipboard
= 0;
858 ret
= wm_renderformat
;
865 return DefWindowProcA(hwnd
, msg
, wp
, lp
);
868 static DWORD WINAPI
clipboard_thread(void *param
)
870 HWND ret
, win
= param
;
874 UINT count
, fmt
, formats
, old_seq
= 0, seq
;
876 cross_thread
= (GetWindowThreadProcessId( win
, NULL
) != GetCurrentThreadId());
877 trace( "%s-threaded test\n", cross_thread
? "multi" : "single" );
879 if (pGetClipboardSequenceNumber
) old_seq
= pGetClipboardSequenceNumber();
881 EnterCriticalSection(&clipboard_cs
);
882 SetLastError(0xdeadbeef);
883 next_wnd
= SetClipboardViewer(win
);
884 ok(GetLastError() == 0xdeadbeef, "GetLastError = %d\n", GetLastError());
885 LeaveCriticalSection(&clipboard_cs
);
887 SetLastError( 0xdeadbeef );
888 ret
= SetClipboardViewer( (HWND
)0xdead );
889 ok( !ret
, "SetClipboardViewer succeeded\n" );
890 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %u\n", GetLastError() );
891 SetLastError( 0xdeadbeef );
892 r
= ChangeClipboardChain( win
, (HWND
)0xdead );
893 ok( !r
, "ChangeClipboardChain succeeded\n" );
894 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %u\n", GetLastError() );
895 SetLastError( 0xdeadbeef );
896 r
= ChangeClipboardChain( (HWND
)0xdead, next_wnd
);
897 ok( !r
, "ChangeClipboardChain succeeded\n" );
898 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %u\n", GetLastError() );
900 if (pAddClipboardFormatListener
)
902 r
= pAddClipboardFormatListener(win
);
903 ok( r
, "AddClipboardFormatListener failed err %d\n", GetLastError());
904 SetLastError( 0xdeadbeef );
905 r
= pAddClipboardFormatListener( win
);
906 ok( !r
, "AddClipboardFormatListener succeeded\n" );
907 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
908 SetLastError( 0xdeadbeef );
909 r
= pAddClipboardFormatListener( (HWND
)0xdead );
910 ok( !r
, "AddClipboardFormatListener succeeded\n" );
911 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %u\n", GetLastError() );
912 r
= pAddClipboardFormatListener( GetDesktopWindow() );
913 ok( r
, "AddClipboardFormatListener failed err %d\n", GetLastError());
914 r
= pRemoveClipboardFormatListener( GetDesktopWindow() );
915 ok( r
, "RemoveClipboardFormatListener failed err %d\n", GetLastError());
918 if (pGetClipboardSequenceNumber
)
920 seq
= pGetClipboardSequenceNumber();
921 ok( seq
== old_seq
, "sequence changed\n" );
925 ok( wm_drawclipboard
== 1, "WM_DRAWCLIPBOARD not received\n" );
926 ok( !wm_clipboardupdate
, "WM_CLIPBOARDUPDATE received\n" );
927 ok( !wm_renderformat
, "WM_RENDERFORMAT received\n" );
928 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
930 count
= SendMessageA( win
, WM_USER
+ 1, 0, 0 );
931 ok( count
== 1, "WM_DRAWCLIPBOARD not received\n" );
932 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
933 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
934 fmt
= SendMessageA( win
, WM_USER
+4, 0, 0 );
935 ok( !fmt
, "WM_RENDERFORMAT received\n" );
937 SetLastError( 0xdeadbeef );
938 r
= OpenClipboard( (HWND
)0xdead );
939 ok( !r
, "OpenClipboard succeeded\n" );
940 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %u\n", GetLastError() );
942 r
= OpenClipboard(win
);
943 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
945 if (pGetClipboardSequenceNumber
)
947 seq
= pGetClipboardSequenceNumber();
948 ok( seq
== old_seq
, "sequence changed\n" );
952 ok( !wm_drawclipboard
, "WM_DRAWCLIPBOARD received\n" );
953 ok( !wm_clipboardupdate
, "WM_CLIPBOARDUPDATE received\n" );
954 ok( !wm_renderformat
, "WM_RENDERFORMAT received\n" );
955 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
957 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
958 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
959 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
960 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
961 fmt
= SendMessageA( win
, WM_USER
+4, 0, 0 );
962 ok( !fmt
, "WM_RENDERFORMAT received\n" );
964 r
= EmptyClipboard();
965 ok(r
, "EmptyClipboard failed: %d\n", GetLastError());
967 if (pGetClipboardSequenceNumber
)
969 seq
= pGetClipboardSequenceNumber();
970 ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
975 ok( !wm_drawclipboard
, "WM_DRAWCLIPBOARD received\n" );
976 ok( !wm_clipboardupdate
, "WM_CLIPBOARDUPDATE received\n" );
977 ok( !wm_renderformat
, "WM_RENDERFORMAT received\n" );
978 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
980 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
981 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
982 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
983 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
984 count
= SendMessageA( win
, WM_USER
+3, 0, 0 );
985 ok( !count
, "WM_DESTROYCLIPBOARD received\n" );
986 fmt
= SendMessageA( win
, WM_USER
+4, 0, 0 );
987 ok( !fmt
, "WM_RENDERFORMAT received\n" );
989 r
= EmptyClipboard();
990 ok(r
, "EmptyClipboard failed: %d\n", GetLastError());
991 /* sequence changes again, even though it was already empty */
992 if (pGetClipboardSequenceNumber
)
994 seq
= pGetClipboardSequenceNumber();
995 ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
1000 ok( !wm_drawclipboard
, "WM_DRAWCLIPBOARD received\n" );
1001 ok( !wm_clipboardupdate
, "WM_CLIPBOARDUPDATE received\n" );
1002 ok( !wm_renderformat
, "WM_RENDERFORMAT received\n" );
1003 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
1005 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
1006 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
1007 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
1008 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
1009 count
= SendMessageA( win
, WM_USER
+3, 0, 0 );
1010 ok( count
, "WM_DESTROYCLIPBOARD not received\n" );
1011 fmt
= SendMessageA( win
, WM_USER
+4, 0, 0 );
1012 ok( !fmt
, "WM_RENDERFORMAT received\n" );
1013 count
= SendMessageA( win
, WM_USER
+5, 0, 0 );
1014 ok( !count
, "wrong format count %u on WM_DESTROYCLIPBOARD\n", count
);
1016 handle
= SetClipboardData( CF_TEXT
, create_textA() );
1017 ok(handle
!= 0, "SetClipboardData failed: %d\n", GetLastError());
1019 if (pGetClipboardSequenceNumber
)
1021 seq
= pGetClipboardSequenceNumber();
1022 todo_wine
ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
1027 ok( !wm_drawclipboard
, "WM_DRAWCLIPBOARD received\n" );
1028 ok( !wm_clipboardupdate
, "WM_CLIPBOARDUPDATE received\n" );
1029 ok( !wm_renderformat
, "WM_RENDERFORMAT received\n" );
1030 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
1032 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
1033 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
1034 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
1035 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
1036 fmt
= SendMessageA( win
, WM_USER
+4, 0, 0 );
1037 ok( !fmt
, "WM_RENDERFORMAT received\n" );
1039 SetClipboardData( CF_UNICODETEXT
, 0 );
1041 if (pGetClipboardSequenceNumber
)
1043 seq
= pGetClipboardSequenceNumber();
1044 todo_wine
ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
1049 ok( !wm_drawclipboard
, "WM_DRAWCLIPBOARD received\n" );
1050 ok( !wm_clipboardupdate
, "WM_CLIPBOARDUPDATE received\n" );
1051 ok( !wm_renderformat
, "WM_RENDERFORMAT received\n" );
1052 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
1054 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
1055 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
1056 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
1057 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
1058 fmt
= SendMessageA( win
, WM_USER
+4, 0, 0 );
1059 ok( !fmt
, "WM_RENDERFORMAT received\n" );
1061 SetClipboardData( CF_UNICODETEXT
, 0 ); /* same data again */
1063 if (pGetClipboardSequenceNumber
)
1065 seq
= pGetClipboardSequenceNumber();
1066 todo_wine
ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
1071 ok( !wm_drawclipboard
, "WM_DRAWCLIPBOARD received\n" );
1072 ok( !wm_clipboardupdate
, "WM_CLIPBOARDUPDATE received\n" );
1073 ok( !wm_renderformat
, "WM_RENDERFORMAT received\n" );
1074 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
1076 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
1077 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
1078 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
1079 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
1080 fmt
= SendMessageA( win
, WM_USER
+4, 0, 0 );
1081 ok( !fmt
, "WM_RENDERFORMAT received\n" );
1083 ok( IsClipboardFormatAvailable( CF_TEXT
), "CF_TEXT available\n" );
1084 ok( IsClipboardFormatAvailable( CF_UNICODETEXT
), "CF_UNICODETEXT available\n" );
1085 ok( !IsClipboardFormatAvailable( CF_OEMTEXT
), "CF_OEMTEXT available\n" );
1087 EnterCriticalSection(&clipboard_cs
);
1088 r
= CloseClipboard();
1089 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
1090 LeaveCriticalSection(&clipboard_cs
);
1092 if (pGetClipboardSequenceNumber
)
1094 seq
= pGetClipboardSequenceNumber();
1095 ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
1100 ok( wm_drawclipboard
== 1, "WM_DRAWCLIPBOARD not 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
== 1, "WM_DRAWCLIPBOARD not received\n" );
1107 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
1108 ok( count
== 1 || broken(!pAddClipboardFormatListener
), "WM_CLIPBOARDUPDATE not received\n" );
1109 fmt
= SendMessageA( win
, WM_USER
+4, 0, 0 );
1110 ok( !fmt
, "WM_RENDERFORMAT received %04x\n", fmt
);
1112 r
= OpenClipboard(win
);
1113 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
1115 if (pGetClipboardSequenceNumber
)
1117 seq
= pGetClipboardSequenceNumber();
1118 ok( seq
== old_seq
, "sequence changed\n" );
1122 ok( !wm_drawclipboard
, "WM_DRAWCLIPBOARD received\n" );
1123 ok( !wm_clipboardupdate
, "WM_CLIPBOARDUPDATE received\n" );
1124 ok( !wm_renderformat
, "WM_RENDERFORMAT received\n" );
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 ok( IsClipboardFormatAvailable( CF_TEXT
), "CF_TEXT available\n" );
1134 ok( IsClipboardFormatAvailable( CF_UNICODETEXT
), "CF_UNICODETEXT available\n" );
1135 ok( IsClipboardFormatAvailable( CF_OEMTEXT
), "CF_OEMTEXT available\n" );
1137 ok( GetClipboardOwner() == win
, "wrong owner %p\n", GetClipboardOwner());
1138 handle
= GetClipboardData( CF_UNICODETEXT
);
1139 ok( !handle
, "got data for CF_UNICODETEXT\n" );
1140 fmt
= SendMessageA( win
, WM_USER
+4, 0, 0 );
1141 ok( fmt
== CF_UNICODETEXT
, "WM_RENDERFORMAT received %04x\n", fmt
);
1143 handle
= GetClipboardData( CF_OEMTEXT
);
1144 ok( !handle
, "got data for CF_OEMTEXT\n" );
1145 fmt
= SendMessageA( win
, WM_USER
+4, 0, 0 );
1146 ok( fmt
== CF_UNICODETEXT
, "WM_RENDERFORMAT received %04x\n", fmt
);
1148 SetClipboardData( CF_WAVE
, 0 );
1149 if (pGetClipboardSequenceNumber
)
1151 seq
= pGetClipboardSequenceNumber();
1152 todo_wine
ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
1157 ok( !wm_drawclipboard
, "WM_DRAWCLIPBOARD received\n" );
1158 ok( !wm_clipboardupdate
, "WM_CLIPBOARDUPDATE received\n" );
1159 ok( !wm_renderformat
, "WM_RENDERFORMAT received\n" );
1160 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
1162 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
1163 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
1164 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
1165 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
1166 fmt
= SendMessageA( win
, WM_USER
+4, 0, 0 );
1167 ok( !fmt
, "WM_RENDERFORMAT received %04x\n", fmt
);
1169 r
= CloseClipboard();
1170 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
1171 if (pGetClipboardSequenceNumber
)
1173 /* no synthesized format, so CloseClipboard doesn't change the sequence */
1174 seq
= pGetClipboardSequenceNumber();
1175 todo_wine
ok( seq
== old_seq
, "sequence changed\n" );
1180 ok( wm_drawclipboard
== 1, "WM_DRAWCLIPBOARD not received\n" );
1181 ok( !wm_clipboardupdate
, "WM_CLIPBOARDUPDATE received\n" );
1182 ok( !wm_renderformat
, "WM_RENDERFORMAT received\n" );
1183 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
1185 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
1186 ok( count
== 1, "WM_DRAWCLIPBOARD not received\n" );
1187 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
1188 ok( count
== 1 || broken(!pAddClipboardFormatListener
), "WM_CLIPBOARDUPDATE not received\n" );
1189 fmt
= SendMessageA( win
, WM_USER
+4, 0, 0 );
1190 ok( !fmt
, "WM_RENDERFORMAT received %04x\n", fmt
);
1192 r
= OpenClipboard(win
);
1193 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
1194 r
= CloseClipboard();
1195 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
1196 /* nothing changed */
1197 if (pGetClipboardSequenceNumber
)
1199 seq
= pGetClipboardSequenceNumber();
1200 ok( seq
== old_seq
, "sequence changed\n" );
1204 ok( !wm_drawclipboard
, "WM_DRAWCLIPBOARD received\n" );
1205 ok( !wm_clipboardupdate
, "WM_CLIPBOARDUPDATE received\n" );
1206 ok( !wm_renderformat
, "WM_RENDERFORMAT received\n" );
1207 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
1209 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
1210 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
1211 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
1212 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
1213 count
= SendMessageA( win
, WM_USER
+3, 0, 0 );
1214 ok( !count
, "WM_DESTROYCLIPBOARD received\n" );
1215 fmt
= SendMessageA( win
, WM_USER
+4, 0, 0 );
1216 ok( !fmt
, "WM_RENDERFORMAT received %04x\n", fmt
);
1218 formats
= CountClipboardFormats();
1219 r
= OpenClipboard(0);
1220 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
1221 r
= EmptyClipboard();
1222 ok(r
, "EmptyClipboard failed: %d\n", GetLastError());
1223 r
= CloseClipboard();
1224 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
1228 ok( wm_drawclipboard
== 1, "WM_DRAWCLIPBOARD not received\n" );
1229 ok( !wm_clipboardupdate
, "WM_CLIPBOARDUPDATE received\n" );
1230 ok( !wm_renderformat
, "WM_RENDERFORMAT received\n" );
1231 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
1233 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
1234 ok( count
== 1, "WM_DRAWCLIPBOARD not received\n" );
1235 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
1236 ok( count
== 1 || broken(!pAddClipboardFormatListener
), "WM_CLIPBOARDUPDATE not received\n" );
1237 count
= SendMessageA( win
, WM_USER
+3, 0, 0 );
1238 ok( count
== 1, "WM_DESTROYCLIPBOARD not received\n" );
1239 fmt
= SendMessageA( win
, WM_USER
+4, 0, 0 );
1240 ok( !fmt
, "WM_RENDERFORMAT received %04x\n", fmt
);
1241 count
= SendMessageA( win
, WM_USER
+5, 0, 0 );
1242 ok( count
== formats
, "wrong format count %u on WM_DESTROYCLIPBOARD\n", count
);
1244 r
= OpenClipboard(win
);
1245 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
1246 SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_FIXED
, 1 ));
1247 if (pGetClipboardSequenceNumber
)
1249 seq
= pGetClipboardSequenceNumber();
1250 ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
1255 ok( !wm_drawclipboard
, "WM_DRAWCLIPBOARD received\n" );
1256 ok( !wm_clipboardupdate
, "WM_CLIPBOARDUPDATE received\n" );
1257 ok( !wm_renderformat
, "WM_RENDERFORMAT received\n" );
1258 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
1260 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
1261 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
1262 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
1263 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
1264 count
= SendMessageA( win
, WM_USER
+3, 0, 0 );
1265 ok( !count
, "WM_DESTROYCLIPBOARD received\n" );
1266 fmt
= SendMessageA( win
, WM_USER
+4, 0, 0 );
1267 ok( !fmt
, "WM_RENDERFORMAT received %04x\n", fmt
);
1269 EnterCriticalSection(&clipboard_cs
);
1270 r
= CloseClipboard();
1271 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
1272 LeaveCriticalSection(&clipboard_cs
);
1274 if (pGetClipboardSequenceNumber
)
1276 seq
= pGetClipboardSequenceNumber();
1277 todo_wine
ok( seq
== old_seq
, "sequence changed\n" );
1282 ok( wm_drawclipboard
== 1, "WM_DRAWCLIPBOARD not received\n" );
1283 ok( !wm_clipboardupdate
, "WM_CLIPBOARDUPDATE received\n" );
1284 ok( !wm_renderformat
, "WM_RENDERFORMAT received\n" );
1285 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
1287 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
1288 ok( count
== 1, "WM_DRAWCLIPBOARD not received\n" );
1289 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
1290 ok( count
== 1 || broken(!pAddClipboardFormatListener
), "WM_CLIPBOARDUPDATE not received\n" );
1291 fmt
= SendMessageA( win
, WM_USER
+4, 0, 0 );
1292 ok( !fmt
, "WM_RENDERFORMAT received\n" );
1294 run_process( "grab_clipboard 0" );
1296 if (pGetClipboardSequenceNumber
)
1298 seq
= pGetClipboardSequenceNumber();
1299 ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
1304 ok( !wm_drawclipboard
, "WM_DRAWCLIPBOARD received\n" );
1305 ok( !wm_clipboardupdate
, "WM_CLIPBOARDUPDATE received\n" );
1306 ok( !wm_renderformat
, "WM_RENDERFORMAT received\n" );
1307 /* in this case we get a cross-thread WM_DRAWCLIPBOARD */
1308 cross_thread
= TRUE
;
1309 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
1310 cross_thread
= FALSE
;
1312 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
1313 ok( count
== 1, "WM_DRAWCLIPBOARD not received\n" );
1314 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
1315 ok( count
== 1 || broken(!pAddClipboardFormatListener
), "WM_CLIPBOARDUPDATE not received\n" );
1316 fmt
= SendMessageA( win
, WM_USER
+4, 0, 0 );
1317 ok( !fmt
, "WM_RENDERFORMAT received\n" );
1319 r
= OpenClipboard(0);
1320 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
1321 SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_FIXED
, 1 ));
1322 if (pGetClipboardSequenceNumber
)
1324 seq
= pGetClipboardSequenceNumber();
1325 todo_wine
ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
1330 ok( !wm_drawclipboard
, "WM_DRAWCLIPBOARD received\n" );
1331 ok( !wm_clipboardupdate
, "WM_CLIPBOARDUPDATE received\n" );
1332 ok( !wm_renderformat
, "WM_RENDERFORMAT received\n" );
1333 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
1335 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
1336 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
1337 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
1338 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
1339 fmt
= SendMessageA( win
, WM_USER
+4, 0, 0 );
1340 ok( !fmt
, "WM_RENDERFORMAT received\n" );
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" );
1355 ok( wm_drawclipboard
== 1, "WM_DRAWCLIPBOARD 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 1" );
1369 if (pGetClipboardSequenceNumber
)
1371 seq
= pGetClipboardSequenceNumber();
1372 ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
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
) > 0, "sequence unchanged\n" );
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" );
1428 ok( wm_drawclipboard
== 1, "WM_DRAWCLIPBOARD not 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 r
= PostMessageA(win
, WM_USER
, 0, 0);
1441 ok(r
, "PostMessage failed: %d\n", GetLastError());
1443 if (pRemoveClipboardFormatListener
)
1445 r
= pRemoveClipboardFormatListener(win
);
1446 ok( r
, "RemoveClipboardFormatListener failed err %d\n", GetLastError());
1447 SetLastError( 0xdeadbeef );
1448 r
= pRemoveClipboardFormatListener(win
);
1449 ok( !r
, "RemoveClipboardFormatListener succeeded\n" );
1450 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1451 SetLastError( 0xdeadbeef );
1452 r
= pRemoveClipboardFormatListener( (HWND
)0xdead );
1453 ok( !r
, "RemoveClipboardFormatListener succeeded\n" );
1454 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %u\n", GetLastError() );
1459 static void test_messages(void)
1467 InitializeCriticalSection(&clipboard_cs
);
1469 memset(&cls
, 0, sizeof(cls
));
1470 cls
.lpfnWndProc
= clipboard_wnd_proc
;
1471 cls
.hInstance
= GetModuleHandleA(NULL
);
1472 cls
.lpszClassName
= "clipboard_test";
1473 RegisterClassA(&cls
);
1475 win
= CreateWindowA("clipboard_test", NULL
, 0, 0, 0, 0, 0, NULL
, 0, NULL
, 0);
1476 ok(win
!= NULL
, "CreateWindow failed: %d\n", GetLastError());
1478 thread
= CreateThread(NULL
, 0, clipboard_thread
, (void*)win
, 0, &tid
);
1479 ok(thread
!= NULL
, "CreateThread failed: %d\n", GetLastError());
1481 while(GetMessageA(&msg
, NULL
, 0, 0))
1483 ok( msg
.message
!= WM_DRAWCLIPBOARD
, "WM_DRAWCLIPBOARD was posted\n" );
1484 TranslateMessage(&msg
);
1485 DispatchMessageA(&msg
);
1488 ok(WaitForSingleObject(thread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
1489 CloseHandle(thread
);
1491 DestroyWindow( win
);
1493 /* same tests again but inside a single thread */
1495 win
= CreateWindowA( "clipboard_test", NULL
, 0, 0, 0, 0, 0, NULL
, 0, NULL
, 0 );
1496 ok( win
!= NULL
, "CreateWindow failed: %d\n", GetLastError() );
1498 clipboard_thread( win
);
1499 DestroyWindow( win
);
1501 UnregisterClassA("clipboard_test", GetModuleHandleA(NULL
));
1502 DeleteCriticalSection(&clipboard_cs
);
1505 static BOOL
is_moveable( HANDLE handle
)
1507 void *ptr
= GlobalLock( handle
);
1508 if (ptr
) GlobalUnlock( handle
);
1509 return ptr
&& ptr
!= handle
;
1512 static BOOL
is_fixed( HANDLE handle
)
1514 void *ptr
= GlobalLock( handle
);
1515 if (ptr
) GlobalUnlock( handle
);
1516 return ptr
&& ptr
== handle
;
1519 static BOOL
is_freed( HANDLE handle
)
1521 void *ptr
= GlobalLock( handle
);
1522 if (ptr
) GlobalUnlock( handle
);
1526 static UINT format_id
;
1527 static HBITMAP bitmap
, bitmap2
;
1528 static HPALETTE palette
;
1530 static const LOGPALETTE logpalette
= { 0x300, 1 };
1532 static void test_handles( HWND hwnd
)
1534 HGLOBAL h
, htext
, htext2
;
1538 BOOL is_owner
= (GetWindowThreadProcessId( hwnd
, &process
) && process
== GetCurrentProcessId());
1540 trace( "hwnd %p\n", hwnd
);
1541 htext
= create_textA();
1542 htext2
= create_textA();
1543 bitmap
= CreateBitmap( 10, 10, 1, 1, NULL
);
1544 bitmap2
= CreateBitmap( 10, 10, 1, 1, NULL
);
1545 palette
= CreatePalette( &logpalette
);
1546 pen
= CreatePen( PS_SOLID
, 1, 0 );
1548 r
= OpenClipboard( hwnd
);
1549 ok( r
, "gle %d\n", GetLastError() );
1550 r
= EmptyClipboard();
1551 ok( r
, "gle %d\n", GetLastError() );
1553 h
= SetClipboardData( CF_TEXT
, htext
);
1554 ok( h
== htext
, "got %p\n", h
);
1555 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1556 h
= SetClipboardData( format_id
, htext2
);
1557 ok( h
== htext2
, "got %p\n", h
);
1558 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1559 h
= SetClipboardData( CF_BITMAP
, bitmap
);
1560 ok( h
== bitmap
, "got %p\n", h
);
1561 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1562 h
= SetClipboardData( CF_PALETTE
, palette
);
1563 ok( h
== palette
, "got %p\n", h
);
1564 ok( GetObjectType( h
) == OBJ_PAL
, "expected palette %p\n", h
);
1565 /* setting custom GDI formats crashes on 64-bit Windows */
1568 h
= SetClipboardData( CF_GDIOBJFIRST
+ 1, bitmap2
);
1569 ok( h
== bitmap2
, "got %p\n", h
);
1570 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1571 h
= SetClipboardData( CF_GDIOBJFIRST
+ 2, pen
);
1572 ok( h
== pen
, "got %p\n", h
);
1573 ok( GetObjectType( h
) == OBJ_PEN
, "expected pen %p\n", h
);
1576 data
= GetClipboardData( CF_TEXT
);
1577 ok( data
== htext
, "wrong data %p\n", data
);
1578 ok( is_moveable( data
), "expected moveable mem %p\n", data
);
1580 data
= GetClipboardData( format_id
);
1581 ok( data
== htext2
, "wrong data %p, cf %08x\n", data
, format_id
);
1582 ok( is_moveable( data
), "expected moveable mem %p\n", data
);
1584 r
= CloseClipboard();
1585 ok( r
, "gle %d\n", GetLastError() );
1587 /* data handles are still valid */
1588 ok( is_moveable( htext
), "expected moveable mem %p\n", htext
);
1589 ok( is_moveable( htext2
), "expected moveable mem %p\n", htext
);
1590 ok( GetObjectType( bitmap
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap
);
1591 ok( GetObjectType( bitmap2
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap2
);
1592 ok( GetObjectType( palette
) == OBJ_PAL
, "expected palette %p\n", palette
);
1593 ok( GetObjectType( pen
) == OBJ_PEN
, "expected pen %p\n", pen
);
1595 r
= OpenClipboard( hwnd
);
1596 ok( r
, "gle %d\n", GetLastError() );
1598 /* and now they are freed, unless we are the owner */
1601 todo_wine
ok( is_freed( htext
), "expected freed mem %p\n", htext
);
1602 todo_wine
ok( is_freed( htext2
), "expected freed mem %p\n", htext
);
1604 data
= GetClipboardData( CF_TEXT
);
1605 todo_wine
ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1607 data
= GetClipboardData( format_id
);
1608 todo_wine
ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1612 ok( is_moveable( htext
), "expected moveable mem %p\n", htext
);
1613 ok( is_moveable( htext2
), "expected moveable mem %p\n", htext
);
1615 data
= GetClipboardData( CF_TEXT
);
1616 ok( data
== htext
, "wrong data %p\n", data
);
1618 data
= GetClipboardData( format_id
);
1619 ok( data
== htext2
, "wrong data %p, cf %08x\n", data
, format_id
);
1622 data
= GetClipboardData( CF_OEMTEXT
);
1623 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1624 data
= GetClipboardData( CF_UNICODETEXT
);
1625 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1626 data
= GetClipboardData( CF_BITMAP
);
1627 ok( data
== bitmap
, "expected bitmap %p\n", data
);
1628 data
= GetClipboardData( CF_PALETTE
);
1629 ok( data
== palette
, "expected palette %p\n", data
);
1632 data
= GetClipboardData( CF_GDIOBJFIRST
+ 1 );
1633 ok( data
== bitmap2
, "expected bitmap2 %p\n", data
);
1634 data
= GetClipboardData( CF_GDIOBJFIRST
+ 2 );
1635 ok( data
== pen
, "expected pen %p\n", data
);
1637 data
= GetClipboardData( CF_DIB
);
1638 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1639 data
= GetClipboardData( CF_DIBV5
);
1640 todo_wine
ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1642 ok( GetObjectType( bitmap
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap
);
1643 ok( GetObjectType( bitmap2
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap2
);
1644 ok( GetObjectType( palette
) == OBJ_PAL
, "expected palette %p\n", palette
);
1645 ok( GetObjectType( pen
) == OBJ_PEN
, "expected pen %p\n", pen
);
1647 r
= EmptyClipboard();
1648 ok( r
, "gle %d\n", GetLastError() );
1650 /* w2003, w2008 don't seem to free the data here */
1651 ok( is_freed( htext
) || broken( !is_freed( htext
)), "expected freed mem %p\n", htext
);
1652 ok( is_freed( htext2
) || broken( !is_freed( htext2
)), "expected freed mem %p\n", htext
);
1653 ok( !GetObjectType( bitmap
), "expected freed handle %p\n", bitmap
);
1654 ok( !GetObjectType( palette
), "expected freed handle %p\n", palette
);
1655 ok( GetObjectType( bitmap2
) == OBJ_BITMAP
, "expected bitmap2 %p\n", bitmap2
);
1656 ok( GetObjectType( pen
) == OBJ_PEN
, "expected pen %p\n", pen
);
1658 r
= CloseClipboard();
1659 ok( r
, "gle %d\n", GetLastError() );
1662 static DWORD WINAPI
test_handles_thread( void *arg
)
1664 trace( "running from different thread\n" );
1665 test_handles( (HWND
)arg
);
1669 static DWORD WINAPI
test_handles_thread2( void *arg
)
1675 r
= OpenClipboard( 0 );
1676 ok( r
, "gle %d\n", GetLastError() );
1677 h
= GetClipboardData( CF_TEXT
);
1678 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1679 ptr
= GlobalLock( h
);
1680 if (ptr
) ok( !strcmp( "test", ptr
), "wrong data '%.5s'\n", ptr
);
1682 h
= GetClipboardData( format_id
);
1683 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1684 ptr
= GlobalLock( h
);
1685 if (ptr
) ok( !strcmp( "test", ptr
), "wrong data '%.5s'\n", ptr
);
1687 h
= GetClipboardData( CF_BITMAP
);
1688 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1689 ok( h
== bitmap
, "different bitmap %p / %p\n", h
, bitmap
);
1690 trace( "bitmap %p\n", h
);
1691 h
= GetClipboardData( CF_PALETTE
);
1692 ok( GetObjectType( h
) == OBJ_PAL
, "expected palette %p\n", h
);
1693 ok( h
== palette
, "different palette %p / %p\n", h
, palette
);
1694 trace( "palette %p\n", h
);
1697 h
= GetClipboardData( CF_GDIOBJFIRST
+ 1 );
1698 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1699 ok( h
== bitmap2
, "different bitmap %p / %p\n", h
, bitmap2
);
1700 trace( "bitmap2 %p\n", h
);
1701 h
= GetClipboardData( CF_GDIOBJFIRST
+ 2 );
1702 ok( GetObjectType( h
) == OBJ_PEN
, "expected pen %p\n", h
);
1703 ok( h
== pen
, "different pen %p / %p\n", h
, pen
);
1704 trace( "pen %p\n", h
);
1706 h
= GetClipboardData( CF_DIB
);
1707 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1708 h
= GetClipboardData( CF_DIBV5
);
1709 todo_wine
ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1710 r
= CloseClipboard();
1711 ok( r
, "gle %d\n", GetLastError() );
1715 static void test_handles_process( const char *str
)
1721 format_id
= RegisterClipboardFormatA( "my_cool_clipboard_format" );
1722 r
= OpenClipboard( 0 );
1723 ok( r
, "gle %d\n", GetLastError() );
1724 h
= GetClipboardData( CF_TEXT
);
1725 todo_wine_if( !h
) ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1726 ptr
= GlobalLock( h
);
1727 if (ptr
) todo_wine
ok( !strcmp( str
, ptr
), "wrong data '%.5s'\n", ptr
);
1729 h
= GetClipboardData( format_id
);
1730 todo_wine
ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1731 ptr
= GlobalLock( h
);
1732 if (ptr
) ok( !strcmp( str
, ptr
), "wrong data '%.5s'\n", ptr
);
1734 h
= GetClipboardData( CF_BITMAP
);
1735 todo_wine
ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1736 trace( "bitmap %p\n", h
);
1737 h
= GetClipboardData( CF_PALETTE
);
1738 todo_wine
ok( GetObjectType( h
) == OBJ_PAL
, "expected palette %p\n", h
);
1739 trace( "palette %p\n", h
);
1740 h
= GetClipboardData( CF_GDIOBJFIRST
+ 1 );
1741 ok( !GetObjectType( h
), "expected invalid %p\n", h
);
1742 trace( "bitmap2 %p\n", h
);
1743 h
= GetClipboardData( CF_GDIOBJFIRST
+ 2 );
1744 ok( !GetObjectType( h
), "expected invalid %p\n", h
);
1745 trace( "pen %p\n", h
);
1746 h
= GetClipboardData( CF_DIB
);
1747 todo_wine
ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1748 h
= GetClipboardData( CF_DIBV5
);
1749 todo_wine
ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1750 r
= CloseClipboard();
1751 ok( r
, "gle %d\n", GetLastError() );
1754 static void test_data_handles(void)
1758 HWND hwnd
= CreateWindowA( "static", NULL
, WS_POPUP
, 0, 0, 10, 10, 0, 0, 0, NULL
);
1760 ok( hwnd
!= 0, "window creation failed\n" );
1761 format_id
= RegisterClipboardFormatA( "my_cool_clipboard_format" );
1763 test_handles( GetDesktopWindow() );
1764 test_handles( hwnd
);
1765 run_thread( test_handles_thread
, hwnd
, __LINE__
);
1767 bitmap
= CreateBitmap( 10, 10, 1, 1, NULL
);
1768 bitmap2
= CreateBitmap( 10, 10, 1, 1, NULL
);
1769 palette
= CreatePalette( &logpalette
);
1770 pen
= CreatePen( PS_SOLID
, 1, 0 );
1772 r
= OpenClipboard( hwnd
);
1773 ok( r
, "gle %d\n", GetLastError() );
1774 r
= EmptyClipboard();
1775 ok( r
, "gle %d\n", GetLastError() );
1776 h
= SetClipboardData( CF_TEXT
, create_textA() );
1777 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1778 h
= SetClipboardData( format_id
, create_textA() );
1779 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1780 h
= SetClipboardData( CF_BITMAP
, bitmap
);
1781 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1782 h
= SetClipboardData( CF_PALETTE
, palette
);
1783 ok( GetObjectType( h
) == OBJ_PAL
, "expected palette %p\n", h
);
1786 h
= SetClipboardData( CF_GDIOBJFIRST
+ 1, bitmap2
);
1787 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1788 h
= SetClipboardData( CF_GDIOBJFIRST
+ 2, pen
);
1789 ok( GetObjectType( h
) == OBJ_PEN
, "expected pen %p\n", h
);
1791 r
= CloseClipboard();
1792 ok( r
, "gle %d\n", GetLastError() );
1794 run_thread( test_handles_thread2
, 0, __LINE__
);
1795 run_process( "handles test" );
1797 r
= OpenClipboard( hwnd
);
1798 ok( r
, "gle %d\n", GetLastError() );
1799 h
= GetClipboardData( CF_TEXT
);
1800 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1801 h
= GetClipboardData( format_id
);
1802 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1803 r
= EmptyClipboard();
1804 ok( r
, "gle %d\n", GetLastError() );
1805 r
= CloseClipboard();
1806 ok( r
, "gle %d\n", GetLastError() );
1808 DestroyWindow( hwnd
);
1811 START_TEST(clipboard
)
1814 int argc
= winetest_get_mainargs( &argv
);
1815 HMODULE mod
= GetModuleHandleA( "user32" );
1818 pAddClipboardFormatListener
= (void *)GetProcAddress( mod
, "AddClipboardFormatListener" );
1819 pRemoveClipboardFormatListener
= (void *)GetProcAddress( mod
, "RemoveClipboardFormatListener" );
1820 pGetClipboardSequenceNumber
= (void *)GetProcAddress( mod
, "GetClipboardSequenceNumber" );
1822 if (argc
== 4 && !strcmp( argv
[2], "set_clipboard_data" ))
1824 set_clipboard_data_process( atoi( argv
[3] ));
1827 if (argc
== 4 && !strcmp( argv
[2], "grab_clipboard" ))
1829 grab_clipboard_process( atoi( argv
[3] ));
1832 if (argc
== 4 && !strcmp( argv
[2], "handles" ))
1834 test_handles_process( argv
[3] );
1838 test_RegisterClipboardFormatA();
1839 test_ClipboardOwner();
1842 test_data_handles();