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 static BOOL (WINAPI
*pAddClipboardFormatListener
)(HWND hwnd
);
30 static BOOL (WINAPI
*pRemoveClipboardFormatListener
)(HWND hwnd
);
31 static BOOL (WINAPI
*pGetUpdatedClipboardFormats
)( UINT
*formats
, UINT count
, UINT
*out_count
);
32 static HGLOBAL (WINAPI
*pGlobalFree
)(HGLOBAL
);
34 static int thread_from_line
;
37 #define open_clipboard(hwnd) open_clipboard_(__LINE__, hwnd)
38 static BOOL
open_clipboard_(int line
, HWND hwnd
)
40 DWORD start
= GetTickCount();
43 BOOL ret
= OpenClipboard(hwnd
);
44 if (ret
|| GetLastError() != ERROR_ACCESS_DENIED
)
46 if (GetTickCount() - start
> 100)
49 DWORD le
= GetLastError();
50 HWND clipwnd
= GetOpenClipboardWindow();
51 /* Provide a hint as to the source of interference:
52 * - The class name would typically be CLIPBRDWNDCLASS if the
53 * clipboard was opened by a Windows application using the
55 * - And it would be __wine_clipboard_manager if it was opened in
56 * response to a native application.
58 GetClassNameA(clipwnd
, classname
, ARRAY_SIZE(classname
));
59 trace_(__FILE__
, line
)("%p (%s) opened the clipboard\n", clipwnd
, classname
);
67 #define has_no_open_wnd() has_no_open_wnd_(__LINE__)
68 static BOOL
has_no_open_wnd_(int line
)
70 DWORD start
= GetTickCount();
71 DWORD le
= GetLastError();
74 HWND clipwnd
= GetOpenClipboardWindow();
75 if (!clipwnd
) return TRUE
;
76 if (GetTickCount() - start
> 100)
80 /* See open_clipboard() */
81 GetClassNameA(clipwnd
, classname
, ARRAY_SIZE(classname
));
82 trace_(__FILE__
, line
)("%p (%s) opened the clipboard\n", clipwnd
, classname
);
91 static DWORD WINAPI
open_clipboard_thread(LPVOID arg
)
94 ok(open_clipboard(hWnd
), "%u: OpenClipboard failed\n", thread_from_line
);
98 static DWORD WINAPI
empty_clipboard_thread(LPVOID arg
)
100 SetLastError( 0xdeadbeef );
101 ok(!EmptyClipboard(), "%u: EmptyClipboard succeeded\n", thread_from_line
);
102 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "%u: wrong error %lu\n",
103 thread_from_line
, GetLastError());
107 static DWORD WINAPI
open_and_empty_clipboard_thread(LPVOID arg
)
110 ok(open_clipboard(hWnd
), "%u: OpenClipboard failed\n", thread_from_line
);
111 ok(EmptyClipboard(), "%u: EmptyClipboard failed\n", thread_from_line
);
115 static DWORD WINAPI
open_and_empty_clipboard_win_thread(LPVOID arg
)
117 HWND hwnd
= CreateWindowA( "static", NULL
, WS_POPUP
, 0, 0, 10, 10, 0, 0, 0, NULL
);
118 ok(open_clipboard(hwnd
), "%u: OpenClipboard failed\n", thread_from_line
);
119 ok(EmptyClipboard(), "%u: EmptyClipboard failed\n", thread_from_line
);
123 static DWORD WINAPI
set_clipboard_data_thread(LPVOID arg
)
128 SetLastError( 0xdeadbeef );
129 if (GetClipboardOwner() == hwnd
)
131 SetClipboardData( CF_WAVE
, 0 );
132 ok( IsClipboardFormatAvailable( CF_WAVE
), "%u: SetClipboardData failed\n", thread_from_line
);
133 ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
134 ok( ret
!= 0, "%u: SetClipboardData failed err %lu\n", thread_from_line
, GetLastError() );
135 SetLastError( 0xdeadbeef );
136 ret
= GetClipboardData( CF_WAVE
);
137 ok( !ret
, "%u: GetClipboardData succeeded\n", thread_from_line
);
138 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "%u: wrong error %lu\n",
139 thread_from_line
, GetLastError());
143 SetClipboardData( CF_WAVE
, 0 );
144 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "%u: wrong error %lu\n",
145 thread_from_line
, GetLastError());
146 ok( !IsClipboardFormatAvailable( CF_WAVE
), "%u: SetClipboardData succeeded\n", thread_from_line
);
147 ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
148 ok( !ret
, "%u: SetClipboardData succeeded\n", thread_from_line
);
149 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "%u: wrong error %lu\n",
150 thread_from_line
, GetLastError());
155 static void set_clipboard_data_process( int arg
)
159 winetest_push_context("process %u", arg
);
160 SetLastError( 0xdeadbeef );
163 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
164 ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
165 ok( ret
!= 0, "SetClipboardData failed err %lu\n", GetLastError() );
169 SetClipboardData( CF_WAVE
, 0 );
170 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "wrong error %lu\n",
172 ok( !IsClipboardFormatAvailable( CF_WAVE
), "SetClipboardData succeeded\n" );
173 ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
174 ok( !ret
, "SetClipboardData succeeded\n" );
175 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "wrong error %lu\n",
178 winetest_pop_context();
181 static void grab_clipboard_process( int arg
)
185 SetLastError( 0xdeadbeef );
186 ret
= open_clipboard( 0 );
187 ok( ret
, "OpenClipboard failed\n" );
188 ret
= EmptyClipboard();
189 ok( ret
, "EmptyClipboard failed\n" );
192 HANDLE ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
193 ok( ret
!= 0, "process %u: SetClipboardData failed err %lu\n", arg
, GetLastError() );
197 static void run_thread( LPTHREAD_START_ROUTINE func
, void *arg
, int line
)
202 thread_from_line
= line
;
203 thread
= CreateThread(NULL
, 0, func
, arg
, 0, NULL
);
204 ok(thread
!= NULL
, "%u: CreateThread failed with error %ld\n", line
, GetLastError());
207 ret
= MsgWaitForMultipleObjectsEx( 1, &thread
, 1000, QS_ALLINPUT
, 0 );
208 if (ret
== WAIT_OBJECT_0
+ 1)
211 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
215 ok(ret
== WAIT_OBJECT_0
, "%u: expected WAIT_OBJECT_0, got %lu\n", line
, ret
);
219 static void run_process( const char *args
)
222 PROCESS_INFORMATION info
;
223 STARTUPINFOA startup
;
225 sprintf( cmd
, "%s clipboard %s", argv0
, args
);
226 memset( &startup
, 0, sizeof(startup
) );
227 startup
.cb
= sizeof(startup
);
228 ok( CreateProcessA( NULL
, cmd
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &startup
, &info
),
229 "CreateProcess %s failed\n", cmd
);
231 wait_child_process( info
.hProcess
);
232 CloseHandle( info
.hProcess
);
233 CloseHandle( info
.hThread
);
236 static WNDPROC old_proc
;
237 static LRESULT CALLBACK
winproc_wrapper( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
239 static int wm_renderallformats
;
240 static int wm_drawclipboard
;
242 DWORD msg_flags
= InSendMessageEx( NULL
);
244 if (!seqno
) seqno
= GetClipboardSequenceNumber();
246 trace( "%p msg %04x\n", hwnd
, msg
);
247 if (!wm_renderallformats
)
249 ok( GetClipboardOwner() == hwnd
, "%04x: wrong owner %p/%p\n", msg
, GetClipboardOwner(), hwnd
);
250 ok( seqno
== GetClipboardSequenceNumber(), "%04x: seqno changed\n", msg
);
254 ok( !GetClipboardOwner(), "%04x: wrong owner %p\n", msg
, GetClipboardOwner() );
255 ok( seqno
+ 1 == GetClipboardSequenceNumber(), "%04x: seqno unchanged\n", msg
);
257 ok( GetClipboardViewer() == hwnd
, "%04x: wrong viewer %p/%p\n", msg
, GetClipboardViewer(), hwnd
);
258 ok( GetOpenClipboardWindow() == hwnd
, "%04x: wrong open win %p/%p\n",
259 msg
, GetOpenClipboardWindow(), hwnd
);
264 ok( wm_renderallformats
, "didn't receive WM_RENDERALLFORMATS before WM_DESTROY\n" );
265 ok( wm_drawclipboard
, "didn't receive WM_DRAWCLIPBOARD before WM_DESTROY\n" );
267 case WM_DRAWCLIPBOARD
:
268 ok( msg_flags
== ISMEX_NOSEND
, "WM_DRAWCLIPBOARD wrong flags %lx\n", msg_flags
);
271 case WM_RENDERALLFORMATS
:
272 ok( msg_flags
== ISMEX_NOSEND
, "WM_RENDERALLFORMATS wrong flags %lx\n", msg_flags
);
273 wm_renderallformats
++;
276 return old_proc( hwnd
, msg
, wp
, lp
);
279 static void test_ClipboardOwner(void)
284 SetLastError(0xdeadbeef);
285 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef,
286 "could not perform clipboard test: clipboard already owned\n");
288 hWnd1
= CreateWindowExA(0, "static", NULL
, WS_POPUP
,
289 0, 0, 10, 10, 0, 0, 0, NULL
);
290 ok(hWnd1
!= 0, "CreateWindowExA error %ld\n", GetLastError());
291 trace("hWnd1 = %p\n", hWnd1
);
293 hWnd2
= CreateWindowExA(0, "static", NULL
, WS_POPUP
,
294 0, 0, 10, 10, 0, 0, 0, NULL
);
295 ok(hWnd2
!= 0, "CreateWindowExA error %ld\n", GetLastError());
296 trace("hWnd2 = %p\n", hWnd2
);
298 SetLastError(0xdeadbeef);
299 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
300 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
|| broken(GetLastError() == 0xdeadbeef), /* wow64 */
301 "wrong error %lu\n", GetLastError());
303 ok(open_clipboard(0), "OpenClipboard failed\n");
304 ok(!GetClipboardOwner(), "clipboard should still be not owned\n");
305 ok(!OpenClipboard(hWnd1
), "OpenClipboard should fail since clipboard already opened\n");
306 ok(open_clipboard(0), "OpenClipboard again failed\n");
307 ret
= CloseClipboard();
308 ok( ret
, "CloseClipboard error %ld\n", GetLastError());
310 ok(open_clipboard(hWnd1
), "OpenClipboard failed\n");
311 run_thread( open_clipboard_thread
, hWnd1
, __LINE__
);
312 run_thread( empty_clipboard_thread
, 0, __LINE__
);
313 run_thread( set_clipboard_data_thread
, hWnd1
, __LINE__
);
314 ok( !IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE available\n" );
315 ok( !GetClipboardData( CF_WAVE
), "CF_WAVE data available\n" );
316 run_process( "set_clipboard_data 0" );
317 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
318 ok(open_clipboard(hWnd1
), "OpenClipboard failed\n");
320 SetLastError(0xdeadbeef);
321 ret
= OpenClipboard(hWnd2
);
322 ok(!ret
&& (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED
),
323 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %ld\n", GetLastError());
325 SetLastError(0xdeadbeef);
326 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should still be not owned\n");
327 ret
= EmptyClipboard();
328 ok( ret
, "EmptyClipboard error %ld\n", GetLastError());
329 ok(GetClipboardOwner() == hWnd1
, "clipboard should be owned by %p, not by %p\n", hWnd1
, GetClipboardOwner());
330 run_thread( empty_clipboard_thread
, 0, __LINE__
);
331 run_thread( set_clipboard_data_thread
, hWnd1
, __LINE__
);
332 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
333 ok( GetClipboardData( CF_WAVE
) != 0, "CF_WAVE data not available\n" );
334 run_process( "set_clipboard_data 1" );
336 SetLastError(0xdeadbeef);
337 ret
= OpenClipboard(hWnd2
);
338 ok(!ret
&& (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED
),
339 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %ld\n", GetLastError());
341 ret
= CloseClipboard();
342 ok( ret
, "CloseClipboard error %ld\n", GetLastError());
343 ok(GetClipboardOwner() == hWnd1
, "clipboard should still be owned\n");
345 /* any window will do, even from a different process */
346 ret
= open_clipboard( GetDesktopWindow() );
347 ok( ret
, "OpenClipboard error %ld\n", GetLastError());
348 ret
= EmptyClipboard();
349 ok( ret
, "EmptyClipboard error %ld\n", GetLastError());
350 ok( GetClipboardOwner() == GetDesktopWindow(), "wrong owner %p/%p\n",
351 GetClipboardOwner(), GetDesktopWindow() );
352 run_thread( set_clipboard_data_thread
, GetDesktopWindow(), __LINE__
);
353 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
354 ok( GetClipboardData( CF_WAVE
) != 0, "CF_WAVE data not available\n" );
355 run_process( "set_clipboard_data 2" );
356 ret
= CloseClipboard();
357 ok( ret
, "CloseClipboard error %ld\n", GetLastError());
359 ret
= open_clipboard( hWnd1
);
360 ok( ret
, "OpenClipboard error %ld\n", GetLastError());
361 ret
= EmptyClipboard();
362 ok( ret
, "EmptyClipboard error %ld\n", GetLastError());
363 SetClipboardData( CF_WAVE
, 0 );
364 SetClipboardViewer( hWnd1
);
365 ok( GetClipboardOwner() == hWnd1
, "wrong owner %p/%p\n", GetClipboardOwner(), hWnd1
);
366 ok( GetClipboardViewer() == hWnd1
, "wrong viewer %p/%p\n", GetClipboardViewer(), hWnd1
);
367 ok( GetOpenClipboardWindow() == hWnd1
, "wrong open win %p/%p\n", GetOpenClipboardWindow(), hWnd1
);
368 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
370 old_proc
= (WNDPROC
)SetWindowLongPtrA( hWnd1
, GWLP_WNDPROC
, (LONG_PTR
)winproc_wrapper
);
371 ret
= DestroyWindow(hWnd1
);
372 ok( ret
, "DestroyWindow error %ld\n", GetLastError());
373 ret
= DestroyWindow(hWnd2
);
374 ok( ret
, "DestroyWindow error %ld\n", GetLastError());
375 SetLastError(0xdeadbeef);
376 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should not be owned\n");
377 ok(!GetClipboardViewer() && GetLastError() == 0xdeadbeef, "viewer still exists\n");
378 ok( has_no_open_wnd() && GetLastError() == 0xdeadbeef, "clipboard should not be open\n");
379 ok( !IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE available\n" );
381 SetLastError( 0xdeadbeef );
382 ret
= CloseClipboard();
383 ok( !ret
, "CloseClipboard succeeded\n" );
384 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "wrong error %lu\n", GetLastError() );
386 ret
= open_clipboard( 0 );
387 ok( ret
, "OpenClipboard error %ld\n", GetLastError());
388 run_thread( set_clipboard_data_thread
, 0, __LINE__
);
389 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
390 ok( GetClipboardData( CF_WAVE
) != 0, "CF_WAVE data not available\n" );
391 run_process( "set_clipboard_data 3" );
392 ret
= CloseClipboard();
393 ok( ret
, "CloseClipboard error %ld\n", GetLastError());
395 run_thread( open_and_empty_clipboard_thread
, 0, __LINE__
);
396 ok( has_no_open_wnd(), "wrong open window\n" );
397 ok( !GetClipboardOwner(), "wrong owner window %p\n", GetClipboardOwner() );
399 ret
= open_clipboard( 0 );
400 ok( ret
, "OpenClipboard error %ld\n", GetLastError());
401 run_thread( set_clipboard_data_thread
, 0, __LINE__
);
402 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
403 ok( GetClipboardData( CF_WAVE
) != 0, "CF_WAVE data not available\n" );
404 run_process( "set_clipboard_data 4" );
405 ret
= EmptyClipboard();
406 ok( ret
, "EmptyClipboard error %ld\n", GetLastError());
407 ret
= CloseClipboard();
408 ok( ret
, "CloseClipboard error %ld\n", GetLastError());
410 SetLastError( 0xdeadbeef );
411 ok( !SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 )),
412 "SetClipboardData succeeded\n" );
413 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "wrong error %lu\n", GetLastError() );
414 ok( !IsClipboardFormatAvailable( CF_WAVE
), "SetClipboardData succeeded\n" );
416 run_thread( open_and_empty_clipboard_thread
, GetDesktopWindow(), __LINE__
);
417 ok( has_no_open_wnd(), "wrong open window\n" );
418 ok( GetClipboardOwner() == GetDesktopWindow(), "wrong owner window %p / %p\n",
419 GetClipboardOwner(), GetDesktopWindow() );
421 run_thread( open_and_empty_clipboard_win_thread
, 0, __LINE__
);
422 ok( has_no_open_wnd(), "wrong open window\n" );
423 ok( !GetClipboardOwner(), "wrong owner window %p\n", GetClipboardOwner() );
426 static void test_RegisterClipboardFormatA(void)
429 UINT format_id
, format_id2
;
435 format_id
= RegisterClipboardFormatA("my_cool_clipboard_format");
436 ok(format_id
> 0xc000 && format_id
< 0xffff, "invalid clipboard format id %04x\n", format_id
);
438 format_id2
= RegisterClipboardFormatA("MY_COOL_CLIPBOARD_FORMAT");
439 ok(format_id2
== format_id
, "invalid clipboard format id %04x\n", format_id2
);
441 len
= GetClipboardFormatNameA(format_id
, buf
, ARRAY_SIZE(buf
));
442 ok(len
== lstrlenA("my_cool_clipboard_format"), "wrong format name length %d\n", len
);
443 ok(!lstrcmpA(buf
, "my_cool_clipboard_format"), "wrong format name \"%s\"\n", buf
);
445 len
= GetClipboardFormatNameA(format_id
, NULL
, 0);
446 ok(len
== 0, "wrong format name length %d\n", len
);
448 lstrcpyA(buf
, "foo");
449 SetLastError(0xdeadbeef);
450 len
= GetAtomNameA((ATOM
)format_id
, buf
, ARRAY_SIZE(buf
));
451 ok(len
== 0 || lstrcmpA(buf
, "my_cool_clipboard_format") != 0,
452 "format_id should not be a valid local atom\n");
453 ok(len
!= 0 || GetLastError() == ERROR_INVALID_HANDLE
,
454 "err %ld\n", GetLastError());
456 lstrcpyA(buf
, "foo");
457 SetLastError(0xdeadbeef);
458 len
= GlobalGetAtomNameA((ATOM
)format_id
, buf
, ARRAY_SIZE(buf
));
459 todo_wine
ok(len
== 0 || lstrcmpA(buf
, "my_cool_clipboard_format") != 0,
460 "format_id should not be a valid global atom\n");
461 ok(len
!= 0 || GetLastError() == ERROR_INVALID_HANDLE
,
462 "err %ld\n", GetLastError());
464 SetLastError(0xdeadbeef);
465 atom_id
= FindAtomA("my_cool_clipboard_format");
466 ok(atom_id
== 0, "FindAtomA should fail, but it returned %x (format_id=%x)\n", atom_id
, format_id
);
467 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "err %ld\n", GetLastError());
471 /* this relies on the clipboard and global atom table being different */
472 SetLastError(0xdeadbeef);
473 atom_id
= GlobalFindAtomA("my_cool_clipboard_format");
474 ok(atom_id
== 0, "GlobalFindAtomA should fail, but it returned %x (format_id=%x)\n", atom_id
, format_id
);
475 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "err %ld\n", GetLastError());
478 for (format_id
= 0; format_id
< 0x10fff; format_id
++)
480 SetLastError(0xdeadbeef);
481 len
= GetClipboardFormatNameA(format_id
, buf
, ARRAY_SIZE(buf
));
483 if (format_id
< 0xc000 || format_id
> 0xffff)
484 ok(!len
, "GetClipboardFormatNameA should fail, but it returned %d (%s)\n", len
, buf
);
485 else if (len
&& winetest_debug
> 1)
486 trace("%04x: %s\n", format_id
, len
? buf
: "");
489 ret
= open_clipboard(0);
490 ok( ret
, "OpenClipboard error %ld\n", GetLastError());
492 /* try some invalid/unregistered formats */
493 SetLastError( 0xdeadbeef );
494 handle
= SetClipboardData( 0, GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, 1 ));
495 ok( !handle
, "SetClipboardData succeeded\n" );
496 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "wrong error %lu\n", GetLastError());
497 handle
= SetClipboardData( 0x1234, GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, 1 ));
498 ok( handle
!= 0, "SetClipboardData failed err %ld\n", GetLastError());
499 handle
= SetClipboardData( 0x123456, GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, 1 ));
500 ok( handle
!= 0, "SetClipboardData failed err %ld\n", GetLastError());
501 handle
= SetClipboardData( 0xffff8765, GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, 1 ));
502 ok( handle
!= 0, "SetClipboardData failed err %ld\n", GetLastError());
504 ok( IsClipboardFormatAvailable( 0x1234 ), "format missing\n" );
505 ok( IsClipboardFormatAvailable( 0x123456 ), "format missing\n" );
506 ok( IsClipboardFormatAvailable( 0xffff8765 ), "format missing\n" );
507 ok( !IsClipboardFormatAvailable( 0 ), "format available\n" );
508 ok( !IsClipboardFormatAvailable( 0x3456 ), "format available\n" );
509 ok( !IsClipboardFormatAvailable( 0x8765 ), "format available\n" );
511 trace("# of formats available: %d\n", CountClipboardFormats());
514 while ((format_id
= EnumClipboardFormats(format_id
)))
516 ok(IsClipboardFormatAvailable(format_id
), "format %04x was listed as available\n", format_id
);
517 len
= GetClipboardFormatNameA(format_id
, buf
, ARRAY_SIZE(buf
));
518 trace("%04x: %s\n", format_id
, len
? buf
: "");
521 ret
= EmptyClipboard();
522 ok( ret
, "EmptyClipboard error %ld\n", GetLastError());
523 ret
=CloseClipboard();
524 ok( ret
, "CloseClipboard error %ld\n", GetLastError());
526 if (CountClipboardFormats())
528 SetLastError(0xdeadbeef);
529 ok(!EnumClipboardFormats(0), "EnumClipboardFormats should fail if clipboard wasn't open\n");
530 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
,
531 "Last error should be set to ERROR_CLIPBOARD_NOT_OPEN, not %ld\n", GetLastError());
534 SetLastError(0xdeadbeef);
535 ok(!EmptyClipboard(), "EmptyClipboard should fail if clipboard wasn't open\n");
536 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
|| broken(GetLastError() == 0xdeadbeef), /* wow64 */
537 "Wrong error %lu\n", GetLastError());
539 format_id
= RegisterClipboardFormatA("#1234");
540 ok(format_id
== 1234, "invalid clipboard format id %04x\n", format_id
);
543 static HGLOBAL
create_textA(void)
545 HGLOBAL h
= GlobalAlloc(GMEM_DDESHARE
|GMEM_MOVEABLE
, 10);
546 char *p
= GlobalLock(h
);
547 memcpy(p
, "test\0\0\0\0\0", 10);
552 static HGLOBAL
create_textW(void)
554 static const WCHAR testW
[] = {'t','e','s','t',0,0,0,0,0,0};
555 HGLOBAL h
= GlobalAlloc(GMEM_DDESHARE
|GMEM_MOVEABLE
, sizeof(testW
));
556 WCHAR
*p
= GlobalLock(h
);
557 memcpy(p
, testW
, sizeof(testW
));
562 static HANDLE
create_metafile(void)
564 const RECT rect
= {0, 0, 100, 100};
568 HDC hdc
= CreateMetaFileA( NULL
);
569 ExtTextOutA( hdc
, 0, 0, ETO_OPAQUE
, &rect
, "Test String", strlen("Test String"), NULL
);
570 mf
= CloseMetaFile( hdc
);
571 ret
= GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, sizeof(*pict
) );
572 pict
= GlobalLock( ret
);
574 pict
->xExt
= pict
->yExt
= 100;
580 static HENHMETAFILE
create_emf(void)
582 const RECT rect
= {0, 0, 100, 100};
583 HDC hdc
= CreateEnhMetaFileA(NULL
, NULL
, &rect
, "HENHMETAFILE Ole Clipboard Test\0Test\0\0");
584 ExtTextOutA(hdc
, 0, 0, ETO_OPAQUE
, &rect
, "Test String", strlen("Test String"), NULL
);
585 return CloseEnhMetaFile(hdc
);
588 static HBITMAP
create_bitmap(void)
590 HDC hdc
= GetDC( 0 );
591 UINT bpp
= GetDeviceCaps( hdc
, BITSPIXEL
);
593 return CreateBitmap( 10, 10, 1, bpp
, NULL
);
596 static HBITMAP
create_dib( BOOL v5
)
599 BITMAPINFOHEADER
*hdr
;
601 ret
= GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
| GMEM_ZEROINIT
,
602 sizeof(BITMAPV5HEADER
) + 256 * sizeof(RGBQUAD
) + 16 * 16 * 4 );
603 hdr
= GlobalLock( ret
);
604 hdr
->biSize
= v5
? sizeof(BITMAPV5HEADER
) : sizeof(*hdr
);
608 hdr
->biBitCount
= 32;
609 hdr
->biCompression
= BI_RGB
;
612 BITMAPV5HEADER
*hdr5
= (BITMAPV5HEADER
*)hdr
;
613 hdr5
->bV5RedMask
= 0x0000ff;
614 hdr5
->bV5GreenMask
= 0x00ff00;
615 hdr5
->bV5BlueMask
= 0xff0000;
616 hdr5
->bV5AlphaMask
= 0xff000000;
622 static LRESULT CALLBACK
renderer_winproc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
624 static UINT rendered
;
629 case WM_RENDERFORMAT
:
630 if (wp
< 32) rendered
|= (1 << wp
);
637 return DefWindowProcA( hwnd
, msg
, wp
, lp
);
640 static void test_synthesized(void)
642 static const struct test
648 /* 0 */ { CF_TEXT
, { CF_TEXT
, CF_LOCALE
, CF_OEMTEXT
, CF_UNICODETEXT
}},
649 { CF_OEMTEXT
, { CF_OEMTEXT
, CF_LOCALE
, CF_TEXT
, CF_UNICODETEXT
}},
650 { CF_UNICODETEXT
, { CF_UNICODETEXT
, CF_LOCALE
, CF_TEXT
, CF_OEMTEXT
}},
651 { CF_ENHMETAFILE
, { CF_ENHMETAFILE
, CF_METAFILEPICT
}},
652 { CF_METAFILEPICT
, { CF_METAFILEPICT
, CF_ENHMETAFILE
}},
653 /* 5 */ { CF_BITMAP
, { CF_BITMAP
, CF_DIB
, CF_DIBV5
}},
654 { CF_DIB
, { CF_DIB
, CF_BITMAP
, CF_DIBV5
}},
655 { CF_DIBV5
, { CF_DIBV5
, CF_BITMAP
, CF_DIB
}},
661 UINT cf
, i
, j
, count
, rendered
, seq
, old_seq
;
665 hwnd
= CreateWindowA( "static", NULL
, WS_POPUP
, 0, 0, 10, 10, 0, 0, 0, NULL
);
666 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)renderer_winproc
);
668 htext
= create_textA();
671 r
= open_clipboard(NULL
);
672 ok(r
, "gle %ld\n", GetLastError());
673 r
= EmptyClipboard();
674 ok(r
, "gle %ld\n", GetLastError());
675 h
= SetClipboardData(CF_TEXT
, htext
);
676 ok(h
== htext
, "got %p\n", h
);
677 h
= SetClipboardData(CF_ENHMETAFILE
, emf
);
678 ok(h
== emf
, "got %p\n", h
);
679 r
= CloseClipboard();
680 ok(r
, "gle %ld\n", GetLastError());
682 count
= CountClipboardFormats();
683 ok( count
== 6, "count %u\n", count
);
684 r
= IsClipboardFormatAvailable( CF_TEXT
);
685 ok( r
, "CF_TEXT not available err %ld\n", GetLastError());
686 r
= IsClipboardFormatAvailable( CF_LOCALE
);
687 ok( r
, "CF_LOCALE not available err %ld\n", GetLastError());
688 r
= IsClipboardFormatAvailable( CF_OEMTEXT
);
689 ok( r
, "CF_OEMTEXT not available err %ld\n", GetLastError());
690 r
= IsClipboardFormatAvailable( CF_UNICODETEXT
);
691 ok( r
, "CF_UNICODETEXT not available err %ld\n", GetLastError());
692 r
= IsClipboardFormatAvailable( CF_ENHMETAFILE
);
693 ok( r
, "CF_ENHMETAFILE not available err %ld\n", GetLastError());
694 r
= IsClipboardFormatAvailable( CF_METAFILEPICT
);
695 ok( r
, "CF_METAFILEPICT not available err %ld\n", GetLastError());
697 r
= open_clipboard(NULL
);
698 ok(r
, "gle %ld\n", GetLastError());
699 cf
= EnumClipboardFormats(0);
700 ok(cf
== CF_TEXT
, "cf %08x\n", cf
);
701 data
= GetClipboardData(cf
);
702 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
704 cf
= EnumClipboardFormats(cf
);
705 ok(cf
== CF_ENHMETAFILE
, "cf %08x\n", cf
);
706 data
= GetClipboardData(cf
);
707 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
709 cf
= EnumClipboardFormats(cf
);
710 ok(cf
== CF_LOCALE
, "cf %08x\n", cf
);
711 data
= GetClipboardData(cf
);
712 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
714 cf
= EnumClipboardFormats(cf
);
715 ok(cf
== CF_OEMTEXT
, "cf %08x\n", cf
);
716 data
= GetClipboardData(cf
);
717 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
719 cf
= EnumClipboardFormats(cf
);
720 ok(cf
== CF_UNICODETEXT
, "cf %08x\n", cf
);
722 cf
= EnumClipboardFormats(cf
);
723 ok(cf
== CF_METAFILEPICT
, "cf %08x\n", cf
);
724 data
= GetClipboardData(cf
);
725 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
727 cf
= EnumClipboardFormats(cf
);
728 ok(cf
== 0, "cf %08x\n", cf
);
730 r
= EmptyClipboard();
731 ok(r
, "gle %ld\n", GetLastError());
733 SetClipboardData( CF_UNICODETEXT
, create_textW() );
734 SetClipboardData( CF_TEXT
, create_textA() );
735 SetClipboardData( CF_OEMTEXT
, create_textA() );
736 r
= CloseClipboard();
737 ok(r
, "gle %ld\n", GetLastError());
739 r
= open_clipboard( NULL
);
740 ok(r
, "gle %ld\n", GetLastError());
741 SetLastError( 0xdeadbeef );
742 cf
= EnumClipboardFormats(0);
743 ok( cf
== CF_UNICODETEXT
, "cf %08x\n", cf
);
744 ok( GetLastError() == ERROR_SUCCESS
, "wrong error %lu\n", GetLastError() );
745 SetLastError( 0xdeadbeef );
746 cf
= EnumClipboardFormats(cf
);
747 ok( cf
== CF_TEXT
, "cf %08x\n", cf
);
748 ok( GetLastError() == ERROR_SUCCESS
, "wrong error %lu\n", GetLastError() );
749 SetLastError( 0xdeadbeef );
750 cf
= EnumClipboardFormats(cf
);
751 ok( cf
== CF_OEMTEXT
, "cf %08x\n", cf
);
752 ok( GetLastError() == ERROR_SUCCESS
, "wrong error %lu\n", GetLastError() );
753 SetLastError( 0xdeadbeef );
754 cf
= EnumClipboardFormats(cf
);
755 ok( cf
== CF_LOCALE
, "cf %08x\n", cf
);
756 ok( GetLastError() == ERROR_SUCCESS
, "wrong error %lu\n", GetLastError() );
757 SetLastError( 0xdeadbeef );
758 cf
= EnumClipboardFormats( cf
);
759 ok( cf
== 0, "cf %08x\n", cf
);
760 ok( GetLastError() == ERROR_SUCCESS
, "wrong error %lu\n", GetLastError() );
761 SetLastError( 0xdeadbeef );
762 cf
= EnumClipboardFormats( 0xdead );
763 ok( cf
== 0, "cf %08x\n", cf
);
764 ok( GetLastError() == ERROR_SUCCESS
, "wrong error %lu\n", GetLastError() );
766 r
= EmptyClipboard();
767 ok(r
, "gle %ld\n", GetLastError());
769 r
= CloseClipboard();
770 ok(r
, "gle %ld\n", GetLastError());
772 for (i
= 0; i
< ARRAY_SIZE(tests
); i
++)
774 winetest_push_context("%d", i
);
775 r
= open_clipboard(NULL
);
776 ok(r
, "gle %ld\n", GetLastError());
777 r
= EmptyClipboard();
778 ok(r
, "gle %ld\n", GetLastError());
780 switch (tests
[i
].format
)
784 SetClipboardData( tests
[i
].format
, create_textA() );
787 SetClipboardData( CF_UNICODETEXT
, create_textW() );
790 SetClipboardData( CF_ENHMETAFILE
, create_emf() );
792 case CF_METAFILEPICT
:
793 SetClipboardData( CF_METAFILEPICT
, create_metafile() );
796 SetClipboardData( CF_BITMAP
, create_bitmap() );
800 SetClipboardData( tests
[i
].format
, create_dib( tests
[i
].format
== CF_DIBV5
));
804 count
= CountClipboardFormats();
805 ok( count
== 1, "count %u\n", count
);
807 r
= CloseClipboard();
808 ok(r
, "gle %ld\n", GetLastError());
810 count
= CountClipboardFormats();
811 for (j
= 0; tests
[i
].expected
[j
]; j
++)
813 r
= IsClipboardFormatAvailable( tests
[i
].expected
[j
] );
814 ok( r
, "%04x not available\n", tests
[i
].expected
[j
] );
816 ok( count
== j
, "count %u instead of %u\n", count
, j
);
818 r
= open_clipboard( hwnd
);
819 ok(r
, "gle %ld\n", GetLastError());
821 for (j
= 0; tests
[i
].expected
[j
]; j
++)
823 winetest_push_context("%d", j
);
824 cf
= EnumClipboardFormats( cf
);
825 ok(cf
== tests
[i
].expected
[j
], "got %04x instead of %04x\n",
826 cf
, tests
[i
].expected
[j
] );
827 if (cf
!= tests
[i
].expected
[j
])
829 winetest_pop_context();
832 old_seq
= GetClipboardSequenceNumber();
833 data
= GetClipboardData( cf
);
835 broken( tests
[i
].format
== CF_DIBV5
&& cf
== CF_DIB
), /* >= Vista */
836 "couldn't get data, cf %04x err %ld\n", cf
, GetLastError());
837 seq
= GetClipboardSequenceNumber();
838 ok(seq
== old_seq
, "sequence changed (test %d)\n", cf
);
843 UINT
*ptr
= GlobalLock( data
);
844 DWORD layout
= LOWORD( GetKeyboardLayout(0) );
845 ok( GlobalSize( data
) == sizeof(*ptr
), "size %Iu\n", GlobalSize( data
));
846 ok( *ptr
== layout
||
847 broken( *ptr
== MAKELANGID( LANG_ENGLISH
, SUBLANG_DEFAULT
)),
848 "CF_LOCALE %04x/%04lx\n", *ptr
, layout
);
849 GlobalUnlock( data
);
854 ok( GlobalSize( data
) == 10, "wrong len %Id\n", GlobalSize( data
));
857 ok( GlobalSize( data
) == 10 * sizeof(WCHAR
), "wrong len %Id\n", GlobalSize( data
));
860 winetest_pop_context();
862 if (!tests
[i
].expected
[j
])
864 cf
= EnumClipboardFormats( cf
);
865 ok(cf
== 0, "cf %04x\n", cf
);
868 /* now with delayed rendering */
870 r
= EmptyClipboard();
871 ok(r
, "gle %ld\n", GetLastError());
873 rendered
= SendMessageA( hwnd
, WM_USER
, 0, 0 );
874 ok( !rendered
, "formats %08x have been rendered\n", rendered
);
876 SetClipboardData( tests
[i
].format
, 0 );
877 rendered
= SendMessageA( hwnd
, WM_USER
, 0, 0 );
878 ok( !rendered
, "formats %08x have been rendered\n", rendered
);
880 count
= CountClipboardFormats();
881 ok( count
== 1, "count %u\n", count
);
883 r
= CloseClipboard();
884 ok(r
, "gle %ld\n", GetLastError());
885 rendered
= SendMessageA( hwnd
, WM_USER
, 0, 0 );
886 ok( !rendered
, "formats %08x have been rendered\n", rendered
);
888 count
= CountClipboardFormats();
889 for (j
= 0; tests
[i
].expected
[j
]; j
++)
891 r
= IsClipboardFormatAvailable( tests
[i
].expected
[j
] );
892 ok( r
, "%04x not available\n", tests
[i
].expected
[j
] );
894 ok( count
== j
, "count %u instead of %u\n", count
, j
);
895 rendered
= SendMessageA( hwnd
, WM_USER
, 0, 0 );
896 ok( !rendered
, "formats %08x have been rendered\n", rendered
);
898 r
= open_clipboard(NULL
);
899 ok(r
, "gle %ld\n", GetLastError());
901 for (j
= 0; tests
[i
].expected
[j
]; j
++)
903 winetest_push_context("%d", j
);
904 cf
= EnumClipboardFormats( cf
);
905 ok(cf
== tests
[i
].expected
[j
], "got %04x instead of %04x\n",
906 cf
, tests
[i
].expected
[j
] );
907 if (cf
!= tests
[i
].expected
[j
])
909 winetest_pop_context();
912 rendered
= SendMessageA( hwnd
, WM_USER
, 0, 0 );
913 ok( !rendered
, "formats %08x have been rendered\n", rendered
);
914 data
= GetClipboardData( cf
);
915 rendered
= SendMessageA( hwnd
, WM_USER
, 0, 0 );
918 ok(data
!= NULL
, "CF_LOCALE no data\n");
919 ok( !rendered
, "formats %08x have been rendered\n", rendered
);
923 ok(!data
, "format %04x got data %p\n", cf
, data
);
924 ok( rendered
== (1 << tests
[i
].format
),
925 "formats %08x have been rendered\n", rendered
);
926 /* try to render a second time */
927 data
= GetClipboardData( cf
);
928 rendered
= SendMessageA( hwnd
, WM_USER
, 0, 0 );
929 ok( rendered
== (1 << tests
[i
].format
),
930 "formats %08x have been rendered\n", rendered
);
932 winetest_pop_context();
934 if (!tests
[i
].expected
[j
])
936 cf
= EnumClipboardFormats( cf
);
937 ok(cf
== 0, "cf %04x\n", cf
);
939 r
= CloseClipboard();
940 ok(r
, "gle %ld\n", GetLastError());
941 rendered
= SendMessageA( hwnd
, WM_USER
, 0, 0 );
942 ok( !rendered
, "formats %08x have been rendered\n", rendered
);
943 winetest_pop_context();
946 r
= open_clipboard(NULL
);
947 ok(r
, "gle %ld\n", GetLastError());
948 r
= EmptyClipboard();
949 ok(r
, "gle %ld\n", GetLastError());
950 r
= CloseClipboard();
951 ok(r
, "gle %ld\n", GetLastError());
952 DestroyWindow( hwnd
);
954 /* Check what happens to the delayed rendering clipboard formats when the
955 * owner window is destroyed.
957 hwnd
= CreateWindowA( "static", NULL
, WS_POPUP
, 0, 0, 10, 10, 0, 0, 0, NULL
);
958 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)renderer_winproc
);
960 r
= open_clipboard(hwnd
);
961 ok(r
, "gle %ld\n", GetLastError());
962 r
= EmptyClipboard();
963 ok(r
, "gle %ld\n", GetLastError());
964 SetClipboardData( CF_UNICODETEXT
, NULL
);
965 r
= CloseClipboard();
966 ok(r
, "gle %ld\n", GetLastError());
968 r
= open_clipboard(NULL
);
969 ok(r
, "gle %ld\n", GetLastError());
970 count
= CountClipboardFormats();
971 ok(count
== 4, "count %u\n", count
);
973 DestroyWindow( hwnd
);
975 /* CF_UNICODETEXT and derivatives, CF_TEXT + CF_OEMTEXT, should be gone */
976 count
= CountClipboardFormats();
977 ok(count
== 1, "count %u\n", count
);
978 cf
= EnumClipboardFormats( 0 );
979 ok(cf
== CF_LOCALE
, "unexpected clipboard format %u\n", cf
);
981 r
= CloseClipboard();
982 ok(r
, "gle %ld\n", GetLastError());
984 r
= open_clipboard(NULL
);
985 ok(r
, "gle %ld\n", GetLastError());
987 SetLastError(0xdeadbeef);
988 data
= GetClipboardData( CF_TEXT
);
989 ok(GetLastError() == ERROR_NOT_FOUND
/* win11 */ ||
990 broken(GetLastError() == 0xdeadbeef),
991 "bad last error %ld\n", GetLastError());
992 ok(!data
, "GetClipboardData() should have returned NULL\n");
994 r
= CloseClipboard();
995 ok(r
, "gle %ld\n", GetLastError());
998 static DWORD WINAPI
clipboard_render_data_thread(void *param
)
1000 HANDLE handle
= SetClipboardData( CF_UNICODETEXT
, create_textW() );
1001 ok( handle
!= 0, "SetClipboardData failed: %ld\n", GetLastError() );
1005 static CRITICAL_SECTION clipboard_cs
;
1006 static HWND next_wnd
;
1007 static UINT wm_drawclipboard
;
1008 static UINT wm_clipboardupdate
;
1009 static UINT wm_destroyclipboard
;
1010 static UINT wm_renderformat
;
1011 static UINT nb_formats
;
1012 static BOOL cross_thread
;
1013 static BOOL do_render_format
;
1014 static HANDLE update_event
;
1016 static LRESULT CALLBACK
clipboard_wnd_proc(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
1019 DWORD msg_flags
= InSendMessageEx( NULL
);
1022 case WM_DRAWCLIPBOARD
:
1023 ok( msg_flags
== (cross_thread
? ISMEX_NOTIFY
: ISMEX_NOSEND
),
1024 "WM_DRAWCLIPBOARD wrong flags %lx\n", msg_flags
);
1025 EnterCriticalSection(&clipboard_cs
);
1027 LeaveCriticalSection(&clipboard_cs
);
1029 case WM_CHANGECBCHAIN
:
1030 ok( msg_flags
== (cross_thread
? ISMEX_SEND
: ISMEX_NOSEND
),
1031 "WM_CHANGECBCHAIN wrong flags %lx\n", msg_flags
);
1032 if (next_wnd
== (HWND
)wp
)
1033 next_wnd
= (HWND
)lp
;
1035 SendMessageA(next_wnd
, msg
, wp
, lp
);
1037 case WM_DESTROYCLIPBOARD
:
1038 ok( msg_flags
== (cross_thread
? ISMEX_SEND
: ISMEX_NOSEND
),
1039 "WM_DESTROYCLIPBOARD wrong flags %lx\n", msg_flags
);
1040 wm_destroyclipboard
++;
1041 ok( GetClipboardOwner() == hwnd
, "WM_DESTROYCLIPBOARD owner %p\n", GetClipboardOwner() );
1042 nb_formats
= CountClipboardFormats();
1044 case WM_RENDERFORMAT
:
1045 ok( !wm_renderformat
, "multiple WM_RENDERFORMAT %04x / %04Ix\n", wm_renderformat
, wp
);
1046 wm_renderformat
= wp
;
1048 if (do_render_format
)
1053 old_seq
= GetClipboardSequenceNumber();
1054 handle
= SetClipboardData( CF_TEXT
, create_textA() );
1055 ok( handle
!= 0, "SetClipboardData failed: %ld\n", GetLastError() );
1056 seq
= GetClipboardSequenceNumber();
1057 ok( seq
== old_seq
, "sequence changed\n" );
1060 handle
= CreateThread( NULL
, 0, clipboard_render_data_thread
, NULL
, 0, NULL
);
1061 ok( handle
!= NULL
, "CreateThread failed: %ld\n", GetLastError() );
1062 ok( WaitForSingleObject(handle
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n" );
1063 CloseHandle( handle
);
1064 seq
= GetClipboardSequenceNumber();
1065 ok( seq
== old_seq
, "sequence changed\n" );
1069 case WM_CLIPBOARDUPDATE
:
1070 ok( msg_flags
== ISMEX_NOSEND
, "WM_CLIPBOARDUPDATE wrong flags %lx\n", msg_flags
);
1071 EnterCriticalSection(&clipboard_cs
);
1072 wm_clipboardupdate
++;
1073 SetEvent(update_event
);
1074 LeaveCriticalSection(&clipboard_cs
);
1077 ChangeClipboardChain(hwnd
, next_wnd
);
1081 ret
= wm_drawclipboard
;
1082 wm_drawclipboard
= 0;
1085 ret
= wm_clipboardupdate
;
1086 wm_clipboardupdate
= 0;
1089 ret
= wm_destroyclipboard
;
1090 wm_destroyclipboard
= 0;
1093 ret
= wm_renderformat
;
1094 wm_renderformat
= 0;
1100 return DefWindowProcA(hwnd
, msg
, wp
, lp
);
1103 static void get_clipboard_data_process(void)
1108 r
= open_clipboard(0);
1109 ok(r
, "OpenClipboard failed: %ld\n", GetLastError());
1110 data
= GetClipboardData( CF_UNICODETEXT
);
1111 ok( data
!= NULL
, "GetClipboardData failed: %ld\n", GetLastError());
1112 r
= CloseClipboard();
1113 ok(r
, "CloseClipboard failed: %ld\n", GetLastError());
1116 static UINT old_seq
;
1118 static void check_messages_(int line
, HWND win
, UINT seq_diff
, UINT draw
, UINT update
, UINT destroy
, UINT render
)
1121 UINT count
, fmt
, seq
;
1123 seq
= GetClipboardSequenceNumber();
1124 ok_(__FILE__
, line
)(seq
- old_seq
== seq_diff
, "sequence diff %d\n", seq
- old_seq
);
1129 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
1132 if (update
&& !broken(!pAddClipboardFormatListener
))
1133 ok(WaitForSingleObject(update_event
, 1000) == WAIT_OBJECT_0
, "wait failed\n");
1135 count
= SendMessageA( win
, WM_USER
+ 1, 0, 0 );
1136 ok_(__FILE__
, line
)(count
== draw
, "WM_DRAWCLIPBOARD %sreceived\n", draw
? "not " : "");
1137 count
= SendMessageA( win
, WM_USER
+ 2, 0, 0 );
1138 ok_(__FILE__
, line
)(count
== update
|| broken(!pAddClipboardFormatListener
),
1139 "WM_CLIPBOARDUPDATE %sreceived\n", update
? "not " : "");
1140 count
= SendMessageA( win
, WM_USER
+ 3, 0, 0 );
1141 ok_(__FILE__
, line
)(count
== destroy
, "WM_DESTROYCLIPBOARD %sreceived\n", destroy
? "not " : "");
1142 fmt
= SendMessageA( win
, WM_USER
+ 4, 0, 0 );
1143 ok_(__FILE__
, line
)(fmt
== render
, "WM_RENDERFORMAT received %04x, expected %04x\n", fmt
, render
);
1145 #define check_messages(a,b,c,d,e,f) check_messages_(__LINE__,a,b,c,d,e,f)
1147 static DWORD WINAPI
clipboard_thread(void *param
)
1149 HWND ret
, win
= param
;
1153 UINT count
, fmt
, formats
;
1155 cross_thread
= (GetWindowThreadProcessId( win
, NULL
) != GetCurrentThreadId());
1156 trace( "%s-threaded test\n", cross_thread
? "multi" : "single" );
1158 old_seq
= GetClipboardSequenceNumber();
1160 EnterCriticalSection(&clipboard_cs
);
1161 SetLastError(0xdeadbeef);
1162 next_wnd
= SetClipboardViewer(win
);
1163 ok(GetLastError() == 0xdeadbeef, "GetLastError = %ld\n", GetLastError());
1164 LeaveCriticalSection(&clipboard_cs
);
1166 SetLastError( 0xdeadbeef );
1167 ret
= SetClipboardViewer( (HWND
)0xdead );
1168 ok( !ret
, "SetClipboardViewer succeeded\n" );
1169 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %lu\n", GetLastError() );
1170 SetLastError( 0xdeadbeef );
1171 r
= ChangeClipboardChain( win
, (HWND
)0xdead );
1172 ok( !r
, "ChangeClipboardChain succeeded\n" );
1173 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %lu\n", GetLastError() );
1174 SetLastError( 0xdeadbeef );
1175 r
= ChangeClipboardChain( (HWND
)0xdead, next_wnd
);
1176 ok( !r
, "ChangeClipboardChain succeeded\n" );
1177 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %lu\n", GetLastError() );
1179 if (pAddClipboardFormatListener
)
1181 r
= pAddClipboardFormatListener(win
);
1182 ok( r
, "AddClipboardFormatListener failed err %ld\n", GetLastError());
1183 SetLastError( 0xdeadbeef );
1184 r
= pAddClipboardFormatListener( win
);
1185 ok( !r
, "AddClipboardFormatListener succeeded\n" );
1186 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %lu\n", GetLastError() );
1187 SetLastError( 0xdeadbeef );
1188 r
= pAddClipboardFormatListener( (HWND
)0xdead );
1189 ok( !r
, "AddClipboardFormatListener succeeded\n" );
1190 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %lu\n", GetLastError() );
1191 r
= pAddClipboardFormatListener( GetDesktopWindow() );
1192 ok( r
, "AddClipboardFormatListener failed err %ld\n", GetLastError());
1193 r
= pRemoveClipboardFormatListener( GetDesktopWindow() );
1194 ok( r
, "RemoveClipboardFormatListener failed err %ld\n", GetLastError());
1197 check_messages(win
, 0, 1, 0, 0, 0);
1199 SetLastError( 0xdeadbeef );
1200 r
= OpenClipboard( (HWND
)0xdead );
1201 ok( !r
, "OpenClipboard succeeded\n" );
1202 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %lu\n", GetLastError() );
1204 r
= open_clipboard(win
);
1205 ok(r
, "OpenClipboard failed: %ld\n", GetLastError());
1207 check_messages(win
, 0, 0, 0, 0, 0);
1209 r
= EmptyClipboard();
1210 ok(r
, "EmptyClipboard failed: %ld\n", GetLastError());
1212 check_messages(win
, 1, 0, 0, 0, 0);
1214 r
= EmptyClipboard();
1215 ok(r
, "EmptyClipboard failed: %ld\n", GetLastError());
1216 /* sequence changes again, even though it was already empty */
1217 check_messages(win
, 1, 0, 0, 1, 0);
1218 count
= SendMessageA( win
, WM_USER
+5, 0, 0 );
1219 ok( !count
, "wrong format count %u on WM_DESTROYCLIPBOARD\n", count
);
1221 handle
= SetClipboardData( CF_TEXT
, create_textA() );
1222 ok(handle
!= 0, "SetClipboardData failed: %ld\n", GetLastError());
1224 check_messages(win
, 1, 0, 0, 0, 0);
1226 SetClipboardData( CF_UNICODETEXT
, 0 );
1228 check_messages(win
, 1, 0, 0, 0, 0);
1230 SetClipboardData( CF_UNICODETEXT
, 0 ); /* same data again */
1232 check_messages(win
, 1, 0, 0, 0, 0);
1234 ok( IsClipboardFormatAvailable( CF_TEXT
), "CF_TEXT available\n" );
1235 ok( IsClipboardFormatAvailable( CF_UNICODETEXT
), "CF_UNICODETEXT available\n" );
1236 ok( !IsClipboardFormatAvailable( CF_OEMTEXT
), "CF_OEMTEXT available\n" );
1238 EnterCriticalSection(&clipboard_cs
);
1239 r
= CloseClipboard();
1240 ok(r
, "CloseClipboard failed: %ld\n", GetLastError());
1241 LeaveCriticalSection(&clipboard_cs
);
1243 check_messages(win
, 2, 1, 1, 0, 0);
1245 r
= open_clipboard(win
);
1246 ok(r
, "OpenClipboard failed: %ld\n", GetLastError());
1248 check_messages(win
, 0, 0, 0, 0, 0);
1250 ok( IsClipboardFormatAvailable( CF_TEXT
), "CF_TEXT available\n" );
1251 ok( IsClipboardFormatAvailable( CF_UNICODETEXT
), "CF_UNICODETEXT available\n" );
1252 ok( IsClipboardFormatAvailable( CF_OEMTEXT
), "CF_OEMTEXT available\n" );
1254 ok( GetClipboardOwner() == win
, "wrong owner %p\n", GetClipboardOwner());
1255 handle
= GetClipboardData( CF_UNICODETEXT
);
1256 ok( !handle
, "got data for CF_UNICODETEXT\n" );
1257 fmt
= SendMessageA( win
, WM_USER
+4, 0, 0 );
1258 ok( fmt
== CF_UNICODETEXT
, "WM_RENDERFORMAT received %04x\n", fmt
);
1260 do_render_format
= TRUE
;
1261 handle
= GetClipboardData( CF_OEMTEXT
);
1262 ok( handle
!= NULL
, "didn't get data for CF_OEMTEXT\n" );
1263 fmt
= SendMessageA( win
, WM_USER
+4, 0, 0 );
1264 ok( fmt
== CF_UNICODETEXT
, "WM_RENDERFORMAT received %04x\n", fmt
);
1265 do_render_format
= FALSE
;
1267 SetClipboardData( CF_WAVE
, 0 );
1268 check_messages(win
, 1, 0, 0, 0, 0);
1270 r
= CloseClipboard();
1271 ok(r
, "CloseClipboard failed: %ld\n", GetLastError());
1272 /* no synthesized format, so CloseClipboard doesn't change the sequence */
1273 check_messages(win
, 0, 1, 1, 0, 0);
1275 r
= open_clipboard(win
);
1276 ok(r
, "OpenClipboard failed: %ld\n", GetLastError());
1277 r
= CloseClipboard();
1278 ok(r
, "CloseClipboard failed: %ld\n", GetLastError());
1279 /* nothing changed */
1280 check_messages(win
, 0, 0, 0, 0, 0);
1282 formats
= CountClipboardFormats();
1283 r
= open_clipboard(0);
1284 ok(r
, "OpenClipboard failed: %ld\n", GetLastError());
1285 r
= EmptyClipboard();
1286 ok(r
, "EmptyClipboard failed: %ld\n", GetLastError());
1287 r
= CloseClipboard();
1288 ok(r
, "CloseClipboard failed: %ld\n", GetLastError());
1290 check_messages(win
, 1, 1, 1, 1, 0);
1291 count
= SendMessageA( win
, WM_USER
+5, 0, 0 );
1292 ok( count
== formats
, "wrong format count %u on WM_DESTROYCLIPBOARD\n", count
);
1294 r
= open_clipboard(win
);
1295 ok(r
, "OpenClipboard failed: %ld\n", GetLastError());
1296 SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_FIXED
, 1 ));
1297 check_messages(win
, 1, 0, 0, 0, 0);
1299 EnterCriticalSection(&clipboard_cs
);
1300 r
= CloseClipboard();
1301 ok(r
, "CloseClipboard failed: %ld\n", GetLastError());
1302 LeaveCriticalSection(&clipboard_cs
);
1304 check_messages(win
, 0, 1, 1, 0, 0);
1306 run_process( "grab_clipboard 0" );
1310 /* in this case we get a cross-thread WM_DRAWCLIPBOARD */
1311 cross_thread
= TRUE
;
1312 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
1313 cross_thread
= FALSE
;
1315 check_messages(win
, 1, 1, 1, 0, 0);
1317 r
= open_clipboard(0);
1318 ok(r
, "OpenClipboard failed: %ld\n", GetLastError());
1319 SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_FIXED
, 1 ));
1320 check_messages(win
, 1, 0, 0, 0, 0);
1322 EnterCriticalSection(&clipboard_cs
);
1323 r
= CloseClipboard();
1324 ok(r
, "CloseClipboard failed: %ld\n", GetLastError());
1325 LeaveCriticalSection(&clipboard_cs
);
1327 check_messages(win
, 0, 1, 1, 0, 0);
1329 run_process( "grab_clipboard 1" );
1333 /* in this case we get a cross-thread WM_DRAWCLIPBOARD */
1334 cross_thread
= TRUE
;
1335 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
1336 cross_thread
= FALSE
;
1338 check_messages(win
, 2, 1, 1, 0, 0);
1340 r
= open_clipboard(0);
1341 ok(r
, "OpenClipboard failed: %ld\n", GetLastError());
1342 SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_FIXED
, 1 ));
1343 check_messages(win
, 1, 0, 0, 0, 0);
1345 EnterCriticalSection(&clipboard_cs
);
1346 r
= CloseClipboard();
1347 ok(r
, "CloseClipboard failed: %ld\n", GetLastError());
1348 LeaveCriticalSection(&clipboard_cs
);
1350 check_messages(win
, 0, 1, 1, 0, 0);
1354 r
= open_clipboard( win
);
1355 ok(r
, "OpenClipboard failed: %ld\n", GetLastError());
1356 r
= EmptyClipboard();
1357 ok(r
, "EmptyClipboard failed: %ld\n", GetLastError());
1358 SetClipboardData( CF_TEXT
, 0 );
1359 r
= CloseClipboard();
1360 ok(r
, "CloseClipboard failed: %ld\n", GetLastError());
1362 do_render_format
= TRUE
;
1363 old_seq
= GetClipboardSequenceNumber();
1364 run_process( "get_clipboard_data" );
1365 do_render_format
= FALSE
;
1367 check_messages(win
, 0, 1, 1, 0, CF_TEXT
);
1370 r
= PostMessageA(win
, WM_USER
, 0, 0);
1371 ok(r
, "PostMessage failed: %ld\n", GetLastError());
1373 if (pRemoveClipboardFormatListener
)
1375 r
= pRemoveClipboardFormatListener(win
);
1376 ok( r
, "RemoveClipboardFormatListener failed err %ld\n", GetLastError());
1377 SetLastError( 0xdeadbeef );
1378 r
= pRemoveClipboardFormatListener(win
);
1379 ok( !r
, "RemoveClipboardFormatListener succeeded\n" );
1380 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %lu\n", GetLastError() );
1381 SetLastError( 0xdeadbeef );
1382 r
= pRemoveClipboardFormatListener( (HWND
)0xdead );
1383 ok( !r
, "RemoveClipboardFormatListener succeeded\n" );
1384 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %lu\n", GetLastError() );
1389 static void test_messages(void)
1397 InitializeCriticalSection(&clipboard_cs
);
1398 update_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1400 memset(&cls
, 0, sizeof(cls
));
1401 cls
.lpfnWndProc
= clipboard_wnd_proc
;
1402 cls
.hInstance
= GetModuleHandleA(NULL
);
1403 cls
.lpszClassName
= "clipboard_test";
1404 RegisterClassA(&cls
);
1406 win
= CreateWindowA("clipboard_test", NULL
, 0, 0, 0, 0, 0, NULL
, 0, NULL
, 0);
1407 ok(win
!= NULL
, "CreateWindow failed: %ld\n", GetLastError());
1409 thread
= CreateThread(NULL
, 0, clipboard_thread
, (void*)win
, 0, &tid
);
1410 ok(thread
!= NULL
, "CreateThread failed: %ld\n", GetLastError());
1412 while(GetMessageA(&msg
, NULL
, 0, 0))
1414 ok( msg
.message
!= WM_DRAWCLIPBOARD
, "WM_DRAWCLIPBOARD was posted\n" );
1415 TranslateMessage(&msg
);
1416 DispatchMessageA(&msg
);
1419 ok(WaitForSingleObject(thread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
1420 CloseHandle(thread
);
1422 DestroyWindow( win
);
1424 /* same tests again but inside a single thread */
1426 win
= CreateWindowA( "clipboard_test", NULL
, 0, 0, 0, 0, 0, NULL
, 0, NULL
, 0 );
1427 ok( win
!= NULL
, "CreateWindow failed: %ld\n", GetLastError() );
1429 clipboard_thread( win
);
1430 DestroyWindow( win
);
1432 UnregisterClassA("clipboard_test", GetModuleHandleA(NULL
));
1433 DeleteCriticalSection(&clipboard_cs
);
1436 static BOOL
is_moveable( HANDLE handle
)
1438 void *ptr
= GlobalLock( handle
);
1439 if (ptr
) GlobalUnlock( handle
);
1440 return ptr
&& ptr
!= handle
;
1443 static BOOL
is_fixed( HANDLE handle
)
1445 void *ptr
= GlobalLock( handle
);
1446 if (ptr
) GlobalUnlock( handle
);
1447 return ptr
&& ptr
== handle
;
1450 static BOOL
is_freed( HANDLE handle
)
1452 return !GlobalSize( handle
);
1455 static UINT format_id
;
1456 static HBITMAP bitmap
, bitmap2
;
1457 static HPALETTE palette
;
1458 static const LOGPALETTE logpalette
= { 0x300, 1, {{ 0x12, 0x34, 0x56, 0x78 }}};
1460 static void test_handles( HWND hwnd
)
1462 HGLOBAL h
, htext
, htext2
, htext3
, htext4
, htext5
;
1463 HGLOBAL hfixed
, hfixed2
, hmoveable
, empty_fixed
, empty_moveable
;
1465 UINT format_id2
= RegisterClipboardFormatA( "another format" );
1468 HBITMAP bitmap_temp
;
1470 BOOL is_owner
= (GetWindowThreadProcessId( hwnd
, &process
) && process
== GetCurrentProcessId());
1472 trace( "hwnd %p\n", hwnd
);
1473 htext
= create_textA();
1474 htext2
= create_textA();
1475 htext3
= create_textA();
1476 htext4
= create_textA();
1477 htext5
= create_textA();
1478 bitmap
= CreateBitmap( 10, 10, 1, 1, NULL
);
1479 bitmap2
= CreateBitmap( 10, 10, 1, 1, NULL
);
1480 palette
= CreatePalette( &logpalette
);
1482 hfixed
= GlobalAlloc( GMEM_FIXED
, 17 );
1483 hfixed2
= GlobalAlloc( GMEM_FIXED
, 17 );
1484 ok( is_fixed( hfixed
), "expected fixed mem %p\n", hfixed
);
1485 ok( GlobalSize( hfixed
) == 17, "wrong size %Iu\n", GlobalSize( hfixed
));
1487 hmoveable
= GlobalAlloc( GMEM_MOVEABLE
, 23 );
1488 ok( is_moveable( hmoveable
), "expected moveable mem %p\n", hmoveable
);
1489 ok( GlobalSize( hmoveable
) == 23, "wrong size %Iu\n", GlobalSize( hmoveable
));
1491 empty_fixed
= GlobalAlloc( GMEM_FIXED
, 0 );
1492 ok( is_fixed( empty_fixed
), "expected fixed mem %p\n", empty_fixed
);
1494 empty_moveable
= GlobalAlloc( GMEM_MOVEABLE
, 0 );
1495 /* discarded handles can't be GlobalLock'ed */
1496 ok( is_freed( empty_moveable
), "expected free mem %p\n", empty_moveable
);
1498 r
= open_clipboard( hwnd
);
1499 ok( r
, "gle %ld\n", GetLastError() );
1500 r
= EmptyClipboard();
1501 ok( r
, "gle %ld\n", GetLastError() );
1503 h
= SetClipboardData( CF_TEXT
, htext
);
1504 ok( h
== htext
, "got %p\n", h
);
1505 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1506 h
= SetClipboardData( format_id
, htext2
);
1507 ok( h
== htext2
, "got %p\n", h
);
1508 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1509 bitmap_temp
= CreateBitmap( 10, 10, 1, 1, NULL
);
1510 h
= SetClipboardData( CF_BITMAP
, bitmap_temp
);
1511 ok( h
== bitmap_temp
, "got %p\n", h
);
1512 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1513 h
= SetClipboardData( CF_BITMAP
, bitmap
);
1514 ok( h
== bitmap
, "got %p\n", h
);
1515 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1516 h
= SetClipboardData( CF_DSPBITMAP
, bitmap2
);
1517 ok( h
== bitmap2
, "got %p\n", h
);
1518 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1519 h
= SetClipboardData( CF_PALETTE
, palette
);
1520 ok( h
== palette
, "got %p\n", h
);
1521 ok( GetObjectType( h
) == OBJ_PAL
, "expected palette %p\n", h
);
1522 h
= SetClipboardData( CF_GDIOBJFIRST
+ 3, htext3
);
1523 ok( h
== htext3
, "got %p\n", h
);
1524 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1525 h
= SetClipboardData( CF_PRIVATEFIRST
+ 7, htext5
);
1526 ok( h
== htext5
, "got %p\n", h
);
1527 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1528 h
= SetClipboardData( format_id2
, empty_moveable
);
1529 ok( !h
, "got %p\n", h
);
1530 GlobalFree( empty_moveable
);
1532 if (0) /* crashes on vista64 */
1534 ptr
= HeapAlloc( GetProcessHeap(), 0, 0 );
1535 h
= SetClipboardData( format_id2
, ptr
);
1536 ok( !h
, "got %p\n", h
);
1537 HeapFree( GetProcessHeap(), 0, ptr
);
1540 h
= SetClipboardData( format_id2
, empty_fixed
);
1541 ok( h
== empty_fixed
, "got %p\n", h
);
1542 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1543 h
= SetClipboardData( 0xdeadbeef, hfixed2
);
1544 ok( h
== hfixed2
, "got %p\n", h
);
1545 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1546 h
= SetClipboardData( 0xdeadbabe, hmoveable
);
1547 ok( h
== hmoveable
, "got %p\n", h
);
1548 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1550 ptr
= HeapAlloc( GetProcessHeap(), 0, 37 );
1551 h
= SetClipboardData( 0xdeadfade, ptr
);
1552 ok( h
== ptr
|| !h
, "got %p\n", h
);
1553 if (!h
) /* heap blocks are rejected on >= win8 */
1555 HeapFree( GetProcessHeap(), 0, ptr
);
1559 data
= GetClipboardData( CF_TEXT
);
1560 ok( data
== htext
, "wrong data %p\n", data
);
1561 ok( is_moveable( data
), "expected moveable mem %p\n", data
);
1563 data
= GetClipboardData( format_id
);
1564 ok( data
== htext2
, "wrong data %p, cf %08x\n", data
, format_id
);
1565 ok( is_moveable( data
), "expected moveable mem %p\n", data
);
1567 data
= GetClipboardData( CF_GDIOBJFIRST
+ 3 );
1568 ok( data
== htext3
, "wrong data %p\n", data
);
1569 ok( is_moveable( data
), "expected moveable mem %p\n", data
);
1571 data
= GetClipboardData( CF_PRIVATEFIRST
+ 7 );
1572 ok( data
== htext5
, "wrong data %p\n", data
);
1573 ok( is_moveable( data
), "expected moveable mem %p\n", data
);
1575 data
= GetClipboardData( format_id2
);
1576 ok( data
== empty_fixed
, "wrong data %p\n", data
);
1577 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1579 data
= GetClipboardData( 0xdeadbeef );
1580 ok( data
== hfixed2
, "wrong data %p\n", data
);
1581 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1583 data
= GetClipboardData( 0xdeadbabe );
1584 ok( data
== hmoveable
, "wrong data %p\n", data
);
1585 ok( is_moveable( data
), "expected moveable mem %p\n", data
);
1587 data
= GetClipboardData( 0xdeadfade );
1588 ok( data
== ptr
, "wrong data %p\n", data
);
1590 SetLastError( 0xdeadbeef );
1591 data
= GetClipboardData( CF_RIFF
);
1592 ok( GetLastError() == ERROR_NOT_FOUND
/* win11 */ ||
1593 broken(GetLastError() == 0xdeadbeef),
1594 "unexpected last error %ld\n", GetLastError() );
1595 ok( !data
, "wrong data %p\n", data
);
1597 h
= SetClipboardData( CF_PRIVATEFIRST
+ 7, htext4
);
1598 ok( h
== htext4
, "got %p\n", h
);
1599 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1600 ok( is_freed( htext5
), "expected freed mem %p\n", htext5
);
1602 h
= SetClipboardData( 0xdeadbeef, hfixed
);
1603 ok( h
== hfixed
, "got %p\n", h
);
1604 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1605 if (0) /* this test is unreliable / crashes */
1606 ok( is_freed( hfixed2
), "expected freed mem %p\n", hfixed2
);
1608 r
= CloseClipboard();
1609 ok( r
, "gle %ld\n", GetLastError() );
1611 /* data handles are still valid */
1612 ok( is_moveable( htext
), "expected moveable mem %p\n", htext
);
1613 ok( is_moveable( htext2
), "expected moveable mem %p\n", htext2
);
1614 ok( is_moveable( htext3
), "expected moveable mem %p\n", htext3
);
1615 ok( is_moveable( htext4
), "expected moveable mem %p\n", htext4
);
1616 ok( GetObjectType( bitmap
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap
);
1617 ok( GetObjectType( bitmap2
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap2
);
1618 ok( GetObjectType( palette
) == OBJ_PAL
, "expected palette %p\n", palette
);
1619 ok( is_fixed( hfixed
), "expected fixed mem %p\n", hfixed
);
1620 ok( is_moveable( hmoveable
), "expected moveable mem %p\n", hmoveable
);
1621 ok( is_fixed( empty_fixed
), "expected fixed mem %p\n", empty_fixed
);
1623 r
= open_clipboard( hwnd
);
1624 ok( r
, "gle %ld\n", GetLastError() );
1626 /* and now they are freed, unless we are the owner */
1629 ok( is_freed( htext
), "expected freed mem %p\n", htext
);
1630 ok( is_freed( htext2
), "expected freed mem %p\n", htext2
);
1631 ok( is_freed( htext3
), "expected freed mem %p\n", htext3
);
1632 ok( is_freed( htext4
), "expected freed mem %p\n", htext4
);
1633 ok( is_freed( hmoveable
), "expected freed mem %p\n", hmoveable
);
1635 data
= GetClipboardData( CF_TEXT
);
1636 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1638 data
= GetClipboardData( format_id
);
1639 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1641 data
= GetClipboardData( CF_GDIOBJFIRST
+ 3 );
1642 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1644 data
= GetClipboardData( CF_PRIVATEFIRST
+ 7 );
1645 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1647 data
= GetClipboardData( format_id2
);
1648 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1649 ok( GlobalSize( data
) == 1, "wrong size %Iu\n", GlobalSize( data
));
1651 data
= GetClipboardData( 0xdeadbeef );
1652 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1653 ok( GlobalSize( data
) == 17, "wrong size %Iu\n", GlobalSize( data
));
1655 data
= GetClipboardData( 0xdeadbabe );
1656 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1657 ok( GlobalSize( data
) == 23, "wrong size %Iu\n", GlobalSize( data
));
1659 data
= GetClipboardData( 0xdeadfade );
1660 ok( is_fixed( data
) || !ptr
, "expected fixed mem %p\n", data
);
1661 if (ptr
) ok( GlobalSize( data
) == 37, "wrong size %Iu\n", GlobalSize( data
));
1665 ok( is_moveable( htext
), "expected moveable mem %p\n", htext
);
1666 ok( is_moveable( htext2
), "expected moveable mem %p\n", htext2
);
1667 ok( is_moveable( htext3
), "expected moveable mem %p\n", htext3
);
1668 ok( is_moveable( htext4
), "expected moveable mem %p\n", htext4
);
1669 ok( is_moveable( hmoveable
), "expected moveable mem %p\n", hmoveable
);
1671 data
= GetClipboardData( CF_TEXT
);
1672 ok( data
== htext
, "wrong data %p\n", data
);
1674 data
= GetClipboardData( format_id
);
1675 ok( data
== htext2
, "wrong data %p, cf %08x\n", data
, format_id
);
1677 data
= GetClipboardData( CF_GDIOBJFIRST
+ 3 );
1678 ok( data
== htext3
, "wrong data %p\n", data
);
1680 data
= GetClipboardData( CF_PRIVATEFIRST
+ 7 );
1681 ok( data
== htext4
, "wrong data %p\n", data
);
1683 data
= GetClipboardData( format_id2
);
1684 ok( data
== empty_fixed
, "wrong data %p\n", data
);
1686 data
= GetClipboardData( 0xdeadbeef );
1687 ok( data
== hfixed
, "wrong data %p\n", data
);
1689 data
= GetClipboardData( 0xdeadbabe );
1690 ok( data
== hmoveable
, "wrong data %p\n", data
);
1692 data
= GetClipboardData( 0xdeadfade );
1693 ok( data
== ptr
, "wrong data %p\n", data
);
1696 data
= GetClipboardData( CF_OEMTEXT
);
1697 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1698 data
= GetClipboardData( CF_UNICODETEXT
);
1699 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1700 data
= GetClipboardData( CF_LOCALE
);
1701 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1702 data
= GetClipboardData( CF_BITMAP
);
1703 ok( data
== bitmap
, "expected bitmap %p\n", data
);
1704 data
= GetClipboardData( CF_DSPBITMAP
);
1705 ok( data
== bitmap2
, "expected bitmap %p\n", data
);
1706 data
= GetClipboardData( CF_PALETTE
);
1707 ok( data
== palette
, "expected palette %p\n", data
);
1708 data
= GetClipboardData( CF_DIB
);
1709 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1710 data
= GetClipboardData( CF_DIBV5
);
1711 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1713 ok( GetObjectType( bitmap
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap
);
1714 ok( GetObjectType( bitmap2
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap2
);
1715 ok( GetObjectType( palette
) == OBJ_PAL
, "expected palette %p\n", palette
);
1716 ok( is_fixed( hfixed
), "expected fixed mem %p\n", hfixed
);
1717 ok( is_fixed( empty_fixed
), "expected fixed mem %p\n", empty_fixed
);
1719 r
= EmptyClipboard();
1720 ok( r
, "gle %ld\n", GetLastError() );
1722 /* w2003, w2008 don't seem to free the data here */
1723 ok( is_freed( htext
) || broken( !is_freed( htext
)), "expected freed mem %p\n", htext
);
1724 ok( is_freed( htext2
) || broken( !is_freed( htext2
)), "expected freed mem %p\n", htext2
);
1725 ok( is_freed( htext3
) || broken( !is_freed( htext3
)), "expected freed mem %p\n", htext3
);
1726 ok( is_freed( htext4
) || broken( !is_freed( htext4
)), "expected freed mem %p\n", htext4
);
1727 ok( is_freed( hmoveable
) || broken( !is_freed( hmoveable
)), "expected freed mem %p\n", hmoveable
);
1728 ok( is_fixed( empty_fixed
), "expected fixed mem %p\n", empty_fixed
);
1729 ok( is_fixed( hfixed
), "expected fixed mem %p\n", hfixed
);
1731 r
= CloseClipboard();
1732 ok( r
, "gle %ld\n", GetLastError() );
1735 static DWORD WINAPI
test_handles_thread( void *arg
)
1737 trace( "running from different thread\n" );
1738 test_handles( (HWND
)arg
);
1742 static DWORD WINAPI
test_handles_thread2( void *arg
)
1748 r
= open_clipboard( 0 );
1749 ok( r
, "gle %ld\n", GetLastError() );
1750 h
= GetClipboardData( CF_TEXT
);
1751 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1752 ptr
= GlobalLock( h
);
1753 if (ptr
) ok( !strcmp( "test", ptr
), "wrong data '%.5s'\n", ptr
);
1755 h
= GetClipboardData( format_id
);
1756 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1757 ptr
= GlobalLock( h
);
1758 if (ptr
) ok( !strcmp( "test", ptr
), "wrong data '%.5s'\n", ptr
);
1760 h
= GetClipboardData( CF_GDIOBJFIRST
+ 3 );
1761 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1762 ptr
= GlobalLock( h
);
1763 if (ptr
) ok( !strcmp( "test", ptr
), "wrong data '%.5s'\n", ptr
);
1765 trace( "gdiobj %p\n", h
);
1766 h
= GetClipboardData( CF_PRIVATEFIRST
+ 7 );
1767 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1768 ptr
= GlobalLock( h
);
1769 if (ptr
) ok( !strcmp( "test", ptr
), "wrong data '%.5s'\n", ptr
);
1771 trace( "private %p\n", h
);
1772 h
= GetClipboardData( CF_BITMAP
);
1773 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1774 ok( h
== bitmap
, "different bitmap %p / %p\n", h
, bitmap
);
1775 trace( "bitmap %p\n", h
);
1776 h
= GetClipboardData( CF_DSPBITMAP
);
1777 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1778 ok( h
== bitmap2
, "different bitmap %p / %p\n", h
, bitmap2
);
1779 trace( "bitmap2 %p\n", h
);
1780 h
= GetClipboardData( CF_PALETTE
);
1781 ok( GetObjectType( h
) == OBJ_PAL
, "expected palette %p\n", h
);
1782 ok( h
== palette
, "different palette %p / %p\n", h
, palette
);
1783 trace( "palette %p\n", h
);
1784 h
= GetClipboardData( CF_DIB
);
1785 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1786 h
= GetClipboardData( CF_DIBV5
);
1787 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1788 r
= CloseClipboard();
1789 ok( r
, "gle %ld\n", GetLastError() );
1793 static void test_handles_process( const char *str
)
1802 format_id
= RegisterClipboardFormatA( "my_cool_clipboard_format" );
1803 r
= open_clipboard( 0 );
1804 ok( r
, "gle %ld\n", GetLastError() );
1805 h
= GetClipboardData( CF_TEXT
);
1806 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1807 ptr
= GlobalLock( h
);
1808 ok( !strcmp( str
, ptr
), "wrong data '%.5s'\n", ptr
);
1810 h
= GetClipboardData( format_id
);
1811 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1812 ptr
= GlobalLock( h
);
1813 if (ptr
) ok( !strcmp( str
, ptr
), "wrong data '%.5s'\n", ptr
);
1815 h
= GetClipboardData( CF_GDIOBJFIRST
+ 3 );
1816 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1817 ptr
= GlobalLock( h
);
1818 ok( !strcmp( str
, ptr
), "wrong data '%.5s'\n", ptr
);
1820 trace( "gdiobj %p\n", h
);
1821 h
= GetClipboardData( CF_PRIVATEFIRST
+ 7 );
1822 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1823 ptr
= GlobalLock( h
);
1824 ok( !strcmp( str
, ptr
), "wrong data '%.5s'\n", ptr
);
1826 trace( "private %p\n", h
);
1827 h
= GetClipboardData( CF_BITMAP
);
1828 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1829 ok( GetObjectW( h
, sizeof(bm
), &bm
) == sizeof(bm
), "GetObject %p failed\n", h
);
1830 ok( bm
.bmWidth
== 13 && bm
.bmHeight
== 17, "wrong bitmap %ux%u\n", bm
.bmWidth
, bm
.bmHeight
);
1831 trace( "bitmap %p\n", h
);
1832 h
= GetClipboardData( CF_DSPBITMAP
);
1833 ok( !GetObjectType( h
), "expected invalid object %p\n", h
);
1834 trace( "bitmap2 %p\n", h
);
1835 h
= GetClipboardData( CF_PALETTE
);
1836 ok( GetObjectType( h
) == OBJ_PAL
, "expected palette %p\n", h
);
1837 ok( GetPaletteEntries( h
, 0, 1, &entry
) == 1, "GetPaletteEntries %p failed\n", h
);
1838 ok( entry
.peRed
== 0x12 && entry
.peGreen
== 0x34 && entry
.peBlue
== 0x56,
1839 "wrong color %02x,%02x,%02x\n", entry
.peRed
, entry
.peGreen
, entry
.peBlue
);
1840 trace( "palette %p\n", h
);
1841 h
= GetClipboardData( CF_METAFILEPICT
);
1842 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1843 ok( GetObjectType( ((METAFILEPICT
*)h
)->hMF
) == OBJ_METAFILE
,
1844 "wrong object %p\n", ((METAFILEPICT
*)h
)->hMF
);
1845 trace( "metafile %p\n", h
);
1846 h
= GetClipboardData( CF_DSPMETAFILEPICT
);
1847 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1848 ok( GetObjectType( ((METAFILEPICT
*)h
)->hMF
) == OBJ_METAFILE
,
1849 "wrong object %p\n", ((METAFILEPICT
*)h
)->hMF
);
1850 trace( "metafile2 %p\n", h
);
1851 h
= GetClipboardData( CF_ENHMETAFILE
);
1852 ok( GetObjectType( h
) == OBJ_ENHMETAFILE
, "expected enhmetafile %p\n", h
);
1853 ok( GetEnhMetaFileBits( h
, sizeof(buffer
), buffer
) > sizeof(ENHMETAHEADER
),
1854 "GetEnhMetaFileBits failed on %p\n", h
);
1855 ok( ((ENHMETAHEADER
*)buffer
)->nRecords
== 3,
1856 "wrong records %lu\n", ((ENHMETAHEADER
*)buffer
)->nRecords
);
1857 trace( "enhmetafile %p\n", h
);
1858 h
= GetClipboardData( CF_DSPENHMETAFILE
);
1859 ok( GetObjectType( h
) == OBJ_ENHMETAFILE
, "expected enhmetafile %p\n", h
);
1860 ok( GetEnhMetaFileBits( h
, sizeof(buffer
), buffer
) > sizeof(ENHMETAHEADER
),
1861 "GetEnhMetaFileBits failed on %p\n", h
);
1862 ok( ((ENHMETAHEADER
*)buffer
)->nRecords
== 3,
1863 "wrong records %lu\n", ((ENHMETAHEADER
*)buffer
)->nRecords
);
1864 trace( "enhmetafile2 %p\n", h
);
1865 h
= GetClipboardData( CF_DIB
);
1866 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1867 h
= GetClipboardData( CF_DIBV5
);
1868 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1869 r
= CloseClipboard();
1870 ok( r
, "gle %ld\n", GetLastError() );
1873 static void test_handles_process_open( const char *str
)
1875 HANDLE h
, text
= GlobalAlloc( GMEM_DDESHARE
|GMEM_MOVEABLE
, strlen(str
) + 1 );
1876 char *ptr
= GlobalLock( text
);
1879 GlobalUnlock( text
);
1881 /* clipboard already open by parent process */
1882 h
= SetClipboardData( CF_TEXT
, text
);
1883 ok( h
== text
, "wrong mem %p / %p\n", h
, text
);
1884 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1887 static void test_handles_process_dib( const char *str
)
1892 r
= open_clipboard( 0 );
1893 ok( r
, "gle %ld\n", GetLastError() );
1894 h
= GetClipboardData( CF_BITMAP
);
1895 ok( !GetObjectType( h
), "expected invalid object %p\n", h
);
1896 trace( "dibsection %p\n", h
);
1897 r
= CloseClipboard();
1898 ok( r
, "gle %ld\n", GetLastError() );
1901 static void test_data_handles(void)
1905 HANDLE h
, text
, metafile
;
1906 HWND hwnd
= CreateWindowA( "static", NULL
, WS_POPUP
, 0, 0, 10, 10, 0, 0, 0, NULL
);
1913 HDC hdc
= GetDC( 0 );
1915 ok( hwnd
!= 0, "window creation failed\n" );
1916 format_id
= RegisterClipboardFormatA( "my_cool_clipboard_format" );
1918 test_handles( GetDesktopWindow() );
1919 test_handles( hwnd
);
1920 run_thread( test_handles_thread
, hwnd
, __LINE__
);
1922 bitmap
= CreateBitmap( 13, 17, 1, 1, NULL
);
1923 bitmap2
= CreateBitmap( 10, 10, 1, 1, NULL
);
1924 palette
= CreatePalette( &logpalette
);
1926 r
= open_clipboard( hwnd
);
1927 ok( r
, "gle %ld\n", GetLastError() );
1928 r
= EmptyClipboard();
1929 ok( r
, "gle %ld\n", GetLastError() );
1930 h
= SetClipboardData( CF_TEXT
, create_textA() );
1931 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1932 h
= SetClipboardData( format_id
, create_textA() );
1933 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1934 h
= SetClipboardData( CF_BITMAP
, bitmap
);
1935 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1936 h
= SetClipboardData( CF_DSPBITMAP
, bitmap2
);
1937 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1938 h
= SetClipboardData( CF_PALETTE
, palette
);
1939 ok( GetObjectType( h
) == OBJ_PAL
, "expected palette %p\n", h
);
1940 h
= SetClipboardData( CF_METAFILEPICT
, create_metafile() );
1941 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1942 trace( "metafile %p\n", h
);
1943 h
= SetClipboardData( CF_DSPMETAFILEPICT
, create_metafile() );
1944 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1945 trace( "metafile2 %p\n", h
);
1946 h
= SetClipboardData( CF_ENHMETAFILE
, create_emf() );
1947 ok( GetObjectType( h
) == OBJ_ENHMETAFILE
, "expected enhmetafile %p\n", h
);
1948 trace( "enhmetafile %p\n", h
);
1949 h
= SetClipboardData( CF_DSPENHMETAFILE
, create_emf() );
1950 ok( GetObjectType( h
) == OBJ_ENHMETAFILE
, "expected enhmetafile %p\n", h
);
1951 trace( "enhmetafile2 %p\n", h
);
1952 h
= SetClipboardData( CF_GDIOBJFIRST
+ 3, create_textA() );
1953 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1954 h
= SetClipboardData( CF_PRIVATEFIRST
+ 7, create_textA() );
1955 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1956 r
= CloseClipboard();
1957 ok( r
, "gle %ld\n", GetLastError() );
1959 run_thread( test_handles_thread2
, 0, __LINE__
);
1960 run_process( "handles test" );
1962 r
= open_clipboard( hwnd
);
1963 ok( r
, "gle %ld\n", GetLastError() );
1964 h
= GetClipboardData( CF_TEXT
);
1965 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1966 h
= GetClipboardData( format_id
);
1967 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1968 h
= GetClipboardData( CF_GDIOBJFIRST
+ 3 );
1969 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1970 h
= GetClipboardData( CF_PRIVATEFIRST
+ 7 );
1971 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1973 r
= EmptyClipboard();
1974 ok( r
, "gle %ld\n", GetLastError() );
1975 text
= create_textA();
1976 h
= SetClipboardData( CF_TEXT
, text
);
1977 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1979 run_process( "handles_open foobar" );
1981 ok( is_moveable( text
), "expected moveable mem %p\n", text
);
1982 h
= GetClipboardData( CF_TEXT
);
1983 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1984 ok( is_moveable( text
), "expected moveable mem %p\n", text
);
1985 ptr
= GlobalLock( h
);
1986 ok( ptr
&& !strcmp( ptr
, "foobar" ), "wrong data %s\n", wine_dbgstr_a(ptr
) );
1989 r
= EmptyClipboard();
1990 ok( r
, "gle %ld\n", GetLastError() );
1991 ok( is_fixed( h
), "expected free mem %p\n", h
);
1992 ok( is_freed( text
) || broken( is_moveable(text
) ), /* w2003, w2008 */
1993 "expected free mem %p\n", text
);
1994 r
= CloseClipboard();
1995 ok( r
, "gle %ld\n", GetLastError() );
1997 /* test CF_BITMAP with a DIB section */
1998 memset( &bmi
, 0, sizeof(bmi
) );
1999 bmi
.bmiHeader
.biSize
= sizeof( bmi
.bmiHeader
);
2000 bmi
.bmiHeader
.biWidth
= 29;
2001 bmi
.bmiHeader
.biHeight
= 13;
2002 bmi
.bmiHeader
.biPlanes
= 1;
2003 bmi
.bmiHeader
.biBitCount
= 32;
2004 bitmap
= CreateDIBSection( 0, &bmi
, DIB_RGB_COLORS
, &bits
, 0, 0 );
2006 r
= open_clipboard( hwnd
);
2007 ok( r
, "gle %ld\n", GetLastError() );
2008 r
= EmptyClipboard();
2009 ok( r
, "gle %ld\n", GetLastError() );
2010 h
= SetClipboardData( CF_BITMAP
, bitmap
);
2011 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
2012 trace( "dibsection %p\n", h
);
2013 r
= CloseClipboard();
2014 ok( r
, "gle %ld\n", GetLastError() );
2016 run_process( "handles_dib dummy" );
2018 r
= open_clipboard( hwnd
);
2019 ok( r
, "gle %ld\n", GetLastError() );
2020 ok( GetObjectType( bitmap
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap
);
2021 r
= EmptyClipboard();
2022 ok( r
, "gle %ld\n", GetLastError() );
2023 r
= CloseClipboard();
2024 ok( r
, "gle %ld\n", GetLastError() );
2026 r
= open_clipboard( hwnd
);
2027 ok( r
, "Open clipboard failed: %#lx.\n", GetLastError() );
2028 r
= EmptyClipboard();
2029 ok( r
, "EmptyClipboard failed: %#lx.\n", GetLastError() );
2031 bitmap
= CreateBitmap( 10, 10, 1, 1, NULL
);
2032 h
= SetClipboardData( CF_BITMAP
, bitmap
);
2033 ok( h
== bitmap
, "Expected bitmap %p, got %p.\n", bitmap
, h
);
2034 ok( !!DeleteObject( bitmap
), "DeleteObject failed.\n" );
2035 h
= GetClipboardData( CF_BITMAP
);
2036 ok( h
== bitmap
, "Expected bitmap %p, got %p.\n", bitmap
, h
);
2037 memset( &bmi
, 0, sizeof(bmi
) );
2038 bmi
.bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
2039 result
= GetDIBits( hdc
, h
, 0, 0, NULL
, &bmi
, 0 );
2040 ok( !!result
, "GetDIBits failed: %#lx.\n", GetLastError() );
2042 bitmap
= CreateBitmap( 10, 10, 1, 1, NULL
);
2043 h
= SetClipboardData( CF_DSPBITMAP
, bitmap
);
2044 ok( h
== bitmap
, "Expected bitmap %p, got %p.\n", bitmap
, h
);
2045 ok( !!DeleteObject( bitmap
), "DeleteObject failed.\n" );
2046 h
= GetClipboardData( CF_DSPBITMAP
);
2047 ok( h
== bitmap
, "Expected bitmap %p, got %p.\n", bitmap
, h
);
2048 memset( &bmi
, 0, sizeof(bmi
) );
2049 bmi
.bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
2050 ok( !GetDIBits( hdc
, h
, 0, 0, 0, &bmi
, 0 ), "GetDIBits returned unexpected value.\n" );
2052 palette
= CreatePalette( &logpalette
);
2053 h
= SetClipboardData( CF_PALETTE
, palette
);
2054 ok( h
== palette
, "Expected palette %p, got %p.\n", palette
, h
);
2055 ok( !!DeleteObject( palette
), "DeleteObject failed.\n" );
2056 h
= GetClipboardData( CF_PALETTE
);
2057 ok( h
== palette
, "Expected palette %p, got %p.\n", palette
, h
);
2058 ok( !!GetPaletteEntries( h
, 0, 1, &entry
), "GetPaletteEntries %p failed.\n", h
);
2059 ok( entry
.peRed
== 0x12 && entry
.peGreen
== 0x34 && entry
.peBlue
== 0x56,
2060 "Got wrong color (%02x, %02x, %02x).\n", entry
.peRed
, entry
.peGreen
, entry
.peBlue
);
2063 h
= SetClipboardData( CF_ENHMETAFILE
, emf
);
2064 ok( h
== emf
, "Expected enhmetafile %p, got %p.\n", palette
, h
);
2065 ok( !!DeleteEnhMetaFile( emf
), "DeleteEnhMetaFile failed.\n" );
2066 h
= GetClipboardData( CF_ENHMETAFILE
);
2067 ok( h
== emf
, "Expected enhmetafile %p, got %p.\n", palette
, h
);
2068 ok( !GetEnhMetaFileBits( h
, sizeof(buffer
), buffer
), "GetEnhMetaFileBits returned unexpected value.\n" );
2071 h
= SetClipboardData( CF_DSPENHMETAFILE
, emf
);
2072 ok( h
== emf
, "Expected enhmetafile %p, got %p.\n", emf
, h
);
2073 ok( !!DeleteEnhMetaFile( emf
), "DeleteEnhMetaFile failed.\n" );
2074 h
= GetClipboardData( CF_DSPENHMETAFILE
);
2075 ok( h
== emf
, "Expected enhmetafile %p, got %p.\n", emf
, h
);
2076 ok( !GetEnhMetaFileBits( h
, sizeof(buffer
), buffer
), "GetEnhMetaFileBits returned unexpected value.\n" );
2078 metafile
= create_metafile();
2079 h
= SetClipboardData( CF_METAFILEPICT
, metafile
);
2080 ok( h
== metafile
, "Expected metafilepict %p, got %p.\n", metafile
, h
);
2081 ok( !pGlobalFree( metafile
), "GlobalFree failed.\n" );
2082 h
= GetClipboardData( CF_METAFILEPICT
);
2083 ok( h
== metafile
, "Expected metafile %p, got %p.\n", metafile
, h
);
2084 ok( is_freed( h
), "Expected freed mem %p.\n", h
);
2086 metafile
= create_metafile();
2087 h
= SetClipboardData( CF_DSPMETAFILEPICT
, metafile
);
2088 ok( h
== metafile
, "Expected metafilepict %p, got %p.\n", metafile
, h
);
2089 ok( !pGlobalFree( metafile
), "GlobalFree failed.\n" );
2090 h
= GetClipboardData( CF_DSPMETAFILEPICT
);
2091 ok( h
== metafile
, "Expected metafile %p, got %p.\n", metafile
, h
);
2092 ok( is_freed( h
), "Expected freed mem %p.\n", h
);
2094 r
= EmptyClipboard();
2095 ok( r
, "EmptyClipboard failed: %#lx.\n", GetLastError() );
2096 r
= CloseClipboard();
2097 ok( r
, "CloseClipboard failed: %#lx.\n", GetLastError() );
2099 ReleaseDC( 0, hdc
);
2100 DestroyWindow( hwnd
);
2103 static void test_GetUpdatedClipboardFormats(void)
2106 UINT count
, formats
[256];
2108 if (!pGetUpdatedClipboardFormats
)
2110 win_skip( "GetUpdatedClipboardFormats not supported\n" );
2115 r
= pGetUpdatedClipboardFormats( NULL
, 0, &count
);
2116 ok( r
, "gle %ld\n", GetLastError() );
2117 ok( !count
, "wrong count %u\n", count
);
2120 r
= pGetUpdatedClipboardFormats( NULL
, 256, &count
);
2121 ok( r
, "gle %ld\n", GetLastError() );
2122 ok( !count
, "wrong count %u\n", count
);
2124 SetLastError( 0xdeadbeef );
2125 r
= pGetUpdatedClipboardFormats( formats
, ARRAY_SIZE(formats
), NULL
);
2126 ok( !r
, "succeeded\n" );
2127 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %lu\n", GetLastError() );
2130 r
= pGetUpdatedClipboardFormats( formats
, ARRAY_SIZE(formats
), &count
);
2131 ok( r
, "gle %ld\n", GetLastError() );
2132 ok( !count
, "wrong count %u\n", count
);
2134 r
= open_clipboard( 0 );
2135 ok( r
, "gle %ld\n", GetLastError() );
2136 r
= EmptyClipboard();
2137 ok( r
, "gle %ld\n", GetLastError() );
2140 r
= pGetUpdatedClipboardFormats( formats
, ARRAY_SIZE(formats
), &count
);
2141 ok( r
, "gle %ld\n", GetLastError() );
2142 ok( !count
, "wrong count %u\n", count
);
2144 SetClipboardData( CF_UNICODETEXT
, 0 );
2147 memset( formats
, 0xcc, sizeof(formats
) );
2148 r
= pGetUpdatedClipboardFormats( formats
, ARRAY_SIZE(formats
), &count
);
2149 ok( r
, "gle %ld\n", GetLastError() );
2150 ok( count
== 1, "wrong count %u\n", count
);
2151 ok( formats
[0] == CF_UNICODETEXT
, "wrong format %u\n", formats
[0] );
2152 ok( formats
[1] == 0xcccccccc, "wrong format %u\n", formats
[1] );
2154 SetClipboardData( CF_TEXT
, 0 );
2156 memset( formats
, 0xcc, sizeof(formats
) );
2157 r
= pGetUpdatedClipboardFormats( formats
, ARRAY_SIZE(formats
), &count
);
2158 ok( r
, "gle %ld\n", GetLastError() );
2159 ok( count
== 2, "wrong count %u\n", count
);
2160 ok( formats
[0] == CF_UNICODETEXT
, "wrong format %u\n", formats
[0] );
2161 ok( formats
[1] == CF_TEXT
, "wrong format %u\n", formats
[1] );
2162 ok( formats
[2] == 0xcccccccc, "wrong format %u\n", formats
[2] );
2164 SetLastError( 0xdeadbeef );
2166 r
= pGetUpdatedClipboardFormats( formats
, 0, &count
);
2167 ok( !r
, "succeeded\n" );
2168 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "wrong error %lu\n", GetLastError() );
2169 ok( count
== 2, "wrong count %u\n", count
);
2171 SetLastError( 0xdeadbeef );
2173 r
= pGetUpdatedClipboardFormats( formats
, 1, &count
);
2174 ok( !r
, "succeeded\n" );
2175 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "wrong error %lu\n", GetLastError() );
2176 ok( count
== 2, "wrong count %u\n", count
);
2178 r
= CloseClipboard();
2179 ok( r
, "gle %ld\n", GetLastError() );
2182 memset( formats
, 0xcc, sizeof(formats
) );
2183 r
= pGetUpdatedClipboardFormats( formats
, ARRAY_SIZE(formats
), &count
);
2184 ok( r
, "gle %ld\n", GetLastError() );
2185 ok( count
== 4, "wrong count %u\n", count
);
2186 ok( formats
[0] == CF_UNICODETEXT
, "wrong format %u\n", formats
[0] );
2187 ok( formats
[1] == CF_TEXT
, "wrong format %u\n", formats
[1] );
2188 ok( formats
[2] == CF_LOCALE
, "wrong format %u\n", formats
[2] );
2189 ok( formats
[3] == CF_OEMTEXT
, "wrong format %u\n", formats
[3] );
2190 ok( formats
[4] == 0xcccccccc, "wrong format %u\n", formats
[4] );
2193 memset( formats
, 0xcc, sizeof(formats
) );
2194 r
= pGetUpdatedClipboardFormats( formats
, 2, &count
);
2195 ok( !r
, "gle %ld\n", GetLastError() );
2196 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "wrong error %lu\n", GetLastError() );
2197 ok( count
== 4, "wrong count %u\n", count
);
2198 ok( formats
[0] == 0xcccccccc, "wrong format %u\n", formats
[0] );
2201 r
= pGetUpdatedClipboardFormats( NULL
, 256, &count
);
2202 ok( !r
, "gle %ld\n", GetLastError() );
2203 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %lu\n", GetLastError() );
2204 ok( count
== 4, "wrong count %u\n", count
);
2207 r
= pGetUpdatedClipboardFormats( NULL
, 256, &count
);
2208 ok( !r
, "gle %ld\n", GetLastError() );
2209 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %lu\n", GetLastError() );
2210 ok( count
== 4, "wrong count %u\n", count
);
2220 { "foo", {}, 3 }, /* 0 */
2222 { "foo\0bar", {}, 7 },
2223 { "foo\0bar", {}, 8 },
2225 { "", {'f'}, 1 }, /* 5 */
2227 { "", {0x3b1,0x3b2,0x3b3}, 5 }, /* Alpha, beta, ... */
2228 { "", {0x3b1,0x3b2,0x3b3}, 6 },
2229 { "", {0x3b1,0x3b2,0x3b3,0}, 7 }, /* 10 */
2230 { "", {0x3b1,0x3b2,0x3b3,0}, 8 },
2231 { "", {0x3b1,0x3b2,0x3b3,0,0x3b4}, 9 },
2232 { "", {'f','o','o',0,'b','a','r'}, 7 * sizeof(WCHAR
) },
2233 { "", {'f','o','o',0,'b','a','r',0}, 8 * sizeof(WCHAR
) },
2236 static void test_string_data(void)
2245 for (i
= 0; i
< ARRAY_SIZE(test_data
); i
++)
2248 /* Before Windows 11 1-byte Unicode strings crash on Win64
2249 * because it underflows when 'appending' a 2 bytes NUL character!
2251 if (!test_data
[i
].strA
[0] && test_data
[i
].len
< sizeof(WCHAR
) &&
2252 strcmp(winetest_platform
, "windows") == 0) continue;
2254 winetest_push_context("%d", i
);
2255 r
= open_clipboard( 0 );
2256 ok( r
, "gle %ld\n", GetLastError() );
2257 r
= EmptyClipboard();
2258 ok( r
, "gle %ld\n", GetLastError() );
2259 data
= GlobalAlloc( GMEM_FIXED
, test_data
[i
].len
);
2260 if (test_data
[i
].strA
[0])
2262 memcpy( data
, test_data
[i
].strA
, test_data
[i
].len
);
2263 SetClipboardData( CF_TEXT
, data
);
2264 memcpy( bufferA
, test_data
[i
].strA
, test_data
[i
].len
);
2265 bufferA
[test_data
[i
].len
- 1] = 0;
2266 ok( !memcmp( data
, bufferA
, test_data
[i
].len
),
2267 "wrong data %.*s\n", test_data
[i
].len
, (char *)data
);
2271 memcpy( data
, test_data
[i
].strW
, test_data
[i
].len
);
2272 clip
= SetClipboardData( CF_UNICODETEXT
, data
);
2273 if (test_data
[i
].len
>= sizeof(WCHAR
))
2275 ok( clip
== data
, "SetClipboardData() returned %p != %p\n", clip
, data
);
2276 memcpy( bufferW
, test_data
[i
].strW
, test_data
[i
].len
);
2277 *((WCHAR
*)((char *)bufferW
+ test_data
[i
].len
) - 1) = 0;
2278 ok( !memcmp( data
, bufferW
, test_data
[i
].len
),
2279 "wrong data %s\n", wine_dbgstr_an( data
, test_data
[i
].len
));
2282 ok( !clip
|| broken(clip
!= NULL
), "expected SetClipboardData() to fail\n" );
2284 r
= CloseClipboard();
2285 ok( r
, "gle %ld\n", GetLastError() );
2286 sprintf( cmd
, "string_data %u", i
);
2288 winetest_pop_context();
2292 static void test_string_data_process( int i
)
2300 winetest_push_context("%d", i
);
2301 r
= open_clipboard( 0 );
2302 ok( r
, "gle %ld\n", GetLastError() );
2303 if (test_data
[i
].strA
[0])
2305 data
= GetClipboardData( CF_TEXT
);
2306 ok( data
!= 0, "could not get data\n" );
2307 len
= GlobalSize( data
);
2308 ok( len
== test_data
[i
].len
, "wrong size %u / %u\n", len
, test_data
[i
].len
);
2309 memcpy( bufferA
, test_data
[i
].strA
, test_data
[i
].len
);
2310 bufferA
[test_data
[i
].len
- 1] = 0;
2311 ok( !memcmp( data
, bufferA
, len
), "wrong data %.*s\n", len
, (char *)data
);
2312 data
= GetClipboardData( CF_UNICODETEXT
);
2313 ok( data
!= 0, "could not get data\n" );
2314 len
= GlobalSize( data
);
2315 len2
= MultiByteToWideChar( CP_ACP
, 0, bufferA
, test_data
[i
].len
, bufferW
, ARRAY_SIZE(bufferW
) );
2316 ok( len
== len2
* sizeof(WCHAR
), "wrong size %u / %u\n", len
, len2
);
2317 ok( !memcmp( data
, bufferW
, len
), "wrong data %s\n", wine_dbgstr_wn( data
, len2
));
2321 data
= GetClipboardData( CF_UNICODETEXT
);
2324 ok( test_data
[i
].len
< sizeof(WCHAR
), "got no data for len=%d\n", test_data
[i
].len
);
2325 ok( !IsClipboardFormatAvailable( CF_UNICODETEXT
), "unicode available\n" );
2327 else if (test_data
[i
].len
== 0)
2329 /* 0-byte string handling is broken on Windows <= 10 */
2330 len
= GlobalSize( data
);
2331 ok( broken(len
== 1), "wrong size %u / 0\n", len
);
2332 ok( broken(*((char*)data
) == 0), "wrong data %s\n", wine_dbgstr_an( data
, len
));
2336 len
= GlobalSize( data
);
2337 ok( len
== test_data
[i
].len
, "wrong size %u / %u\n", len
, test_data
[i
].len
);
2338 memcpy( bufferW
, test_data
[i
].strW
, test_data
[i
].len
);
2339 *((WCHAR
*)((char *)bufferW
+ test_data
[i
].len
) - 1) = 0;
2340 ok( !memcmp( data
, bufferW
, len
), "wrong data %s\n", wine_dbgstr_an( data
, len
));
2343 data
= GetClipboardData( CF_TEXT
);
2344 if (test_data
[i
].len
>= sizeof(WCHAR
))
2346 ok( data
!= 0, "could not get data\n" );
2347 len
= GlobalSize( data
);
2348 len2
= WideCharToMultiByte( CP_ACP
, 0, bufferW
, test_data
[i
].len
/ sizeof(WCHAR
),
2349 bufferA
, ARRAY_SIZE(bufferA
), NULL
, NULL
);
2350 bufferA
[len2
- 1] = 0;
2351 ok( len
== len2
, "wrong size %u / %u\n", len
, len2
);
2352 ok( !memcmp( data
, bufferA
, len
), "wrong data %s, expected %s\n",
2353 wine_dbgstr_an( data
, len
), wine_dbgstr_an( bufferA
, len2
));
2357 BOOL available
= IsClipboardFormatAvailable( CF_TEXT
);
2358 ok( !available
|| broken(available
/* win10 */),
2359 "available text %d\n", available
);
2360 ok( !data
, "got data for empty string\n" );
2363 r
= CloseClipboard();
2364 ok( r
, "gle %ld\n", GetLastError() );
2365 winetest_pop_context();
2368 START_TEST(clipboard
)
2371 int argc
= winetest_get_mainargs( &argv
);
2372 HMODULE mod
= GetModuleHandleA( "user32" );
2375 pAddClipboardFormatListener
= (void *)GetProcAddress( mod
, "AddClipboardFormatListener" );
2376 pRemoveClipboardFormatListener
= (void *)GetProcAddress( mod
, "RemoveClipboardFormatListener" );
2377 pGetUpdatedClipboardFormats
= (void *)GetProcAddress( mod
, "GetUpdatedClipboardFormats" );
2378 pGlobalFree
= (void *)GetProcAddress( GetModuleHandleA( "kernel32" ), "GlobalFree" );
2380 if (argc
== 4 && !strcmp( argv
[2], "set_clipboard_data" ))
2382 set_clipboard_data_process( atoi( argv
[3] ));
2385 if (argc
== 4 && !strcmp( argv
[2], "grab_clipboard" ))
2387 grab_clipboard_process( atoi( argv
[3] ));
2390 if (argc
== 4 && !strcmp( argv
[2], "handles" ))
2392 test_handles_process( argv
[3] );
2395 if (argc
== 4 && !strcmp( argv
[2], "handles_open" ))
2397 test_handles_process_open( argv
[3] );
2400 if (argc
== 4 && !strcmp( argv
[2], "handles_dib" ))
2402 test_handles_process_dib( argv
[3] );
2405 if (argc
== 4 && !strcmp( argv
[2], "string_data" ))
2407 test_string_data_process( atoi( argv
[3] ));
2410 if (argc
== 3 && !strcmp( argv
[2], "get_clipboard_data" ))
2412 get_clipboard_data_process( );
2416 test_RegisterClipboardFormatA();
2417 test_ClipboardOwner();
2420 test_data_handles();
2421 test_GetUpdatedClipboardFormats();