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
);
33 static int thread_from_line
;
36 static BOOL
open_clipboard(HWND hwnd
)
38 DWORD start
= GetTickCount();
41 BOOL ret
= OpenClipboard(hwnd
);
42 if (ret
|| GetLastError() != ERROR_ACCESS_DENIED
)
44 if (GetTickCount() - start
> 100)
47 DWORD le
= GetLastError();
48 HWND clipwnd
= GetOpenClipboardWindow();
49 /* Provide a hint as to the source of interference:
50 * - The class name would typically be CLIPBRDWNDCLASS if the
51 * clipboard was opened by a Windows application using the
53 * - And it would be __wine_clipboard_manager if it was opened in
54 * response to a native application.
56 GetClassNameA(clipwnd
, classname
, ARRAY_SIZE(classname
));
57 trace("%p (%s) opened the clipboard\n", clipwnd
, classname
);
65 static DWORD WINAPI
open_clipboard_thread(LPVOID arg
)
68 ok(open_clipboard(hWnd
), "%u: OpenClipboard failed\n", thread_from_line
);
72 static DWORD WINAPI
empty_clipboard_thread(LPVOID arg
)
74 SetLastError( 0xdeadbeef );
75 ok(!EmptyClipboard(), "%u: EmptyClipboard succeeded\n", thread_from_line
);
76 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "%u: wrong error %u\n",
77 thread_from_line
, GetLastError());
81 static DWORD WINAPI
open_and_empty_clipboard_thread(LPVOID arg
)
84 ok(open_clipboard(hWnd
), "%u: OpenClipboard failed\n", thread_from_line
);
85 ok(EmptyClipboard(), "%u: EmptyClipboard failed\n", thread_from_line
);
89 static DWORD WINAPI
open_and_empty_clipboard_win_thread(LPVOID arg
)
91 HWND hwnd
= CreateWindowA( "static", NULL
, WS_POPUP
, 0, 0, 10, 10, 0, 0, 0, NULL
);
92 ok(open_clipboard(hwnd
), "%u: OpenClipboard failed\n", thread_from_line
);
93 ok(EmptyClipboard(), "%u: EmptyClipboard failed\n", thread_from_line
);
97 static DWORD WINAPI
set_clipboard_data_thread(LPVOID arg
)
102 SetLastError( 0xdeadbeef );
103 if (GetClipboardOwner() == hwnd
)
105 SetClipboardData( CF_WAVE
, 0 );
106 ok( IsClipboardFormatAvailable( CF_WAVE
), "%u: SetClipboardData failed\n", thread_from_line
);
107 ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
108 ok( ret
!= 0, "%u: SetClipboardData failed err %u\n", thread_from_line
, GetLastError() );
109 SetLastError( 0xdeadbeef );
110 ret
= GetClipboardData( CF_WAVE
);
111 ok( !ret
, "%u: GetClipboardData succeeded\n", thread_from_line
);
112 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "%u: wrong error %u\n",
113 thread_from_line
, GetLastError());
117 SetClipboardData( CF_WAVE
, 0 );
118 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "%u: wrong error %u\n",
119 thread_from_line
, GetLastError());
120 ok( !IsClipboardFormatAvailable( CF_WAVE
), "%u: SetClipboardData succeeded\n", thread_from_line
);
121 ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
122 ok( !ret
, "%u: SetClipboardData succeeded\n", thread_from_line
);
123 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "%u: wrong error %u\n",
124 thread_from_line
, GetLastError());
129 static void set_clipboard_data_process( int arg
)
133 SetLastError( 0xdeadbeef );
136 ok( IsClipboardFormatAvailable( CF_WAVE
), "process %u: CF_WAVE not available\n", arg
);
137 ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
138 ok( ret
!= 0, "process %u: SetClipboardData failed err %u\n", arg
, GetLastError() );
142 SetClipboardData( CF_WAVE
, 0 );
143 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "process %u: wrong error %u\n",
144 arg
, GetLastError());
145 ok( !IsClipboardFormatAvailable( CF_WAVE
), "process %u: SetClipboardData succeeded\n", arg
);
146 ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
147 ok( !ret
, "process %u: SetClipboardData succeeded\n", arg
);
148 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "process %u: wrong error %u\n",
149 arg
, GetLastError());
153 static void grab_clipboard_process( int arg
)
157 SetLastError( 0xdeadbeef );
158 ret
= open_clipboard( 0 );
159 ok( ret
, "OpenClipboard failed\n" );
160 ret
= EmptyClipboard();
161 ok( ret
, "EmptyClipboard failed\n" );
164 HANDLE ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
165 ok( ret
!= 0, "process %u: SetClipboardData failed err %u\n", arg
, GetLastError() );
169 static void run_thread( LPTHREAD_START_ROUTINE func
, void *arg
, int line
)
174 thread_from_line
= line
;
175 thread
= CreateThread(NULL
, 0, func
, arg
, 0, NULL
);
176 ok(thread
!= NULL
, "%u: CreateThread failed with error %d\n", line
, GetLastError());
179 ret
= MsgWaitForMultipleObjectsEx( 1, &thread
, 1000, QS_ALLINPUT
, 0 );
180 if (ret
== WAIT_OBJECT_0
+ 1)
183 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
187 ok(ret
== WAIT_OBJECT_0
, "%u: expected WAIT_OBJECT_0, got %u\n", line
, ret
);
191 static void run_process( const char *args
)
194 PROCESS_INFORMATION info
;
195 STARTUPINFOA startup
;
197 sprintf( cmd
, "%s clipboard %s", argv0
, args
);
198 memset( &startup
, 0, sizeof(startup
) );
199 startup
.cb
= sizeof(startup
);
200 ok( CreateProcessA( NULL
, cmd
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &startup
, &info
),
201 "CreateProcess %s failed\n", cmd
);
203 wait_child_process( info
.hProcess
);
204 CloseHandle( info
.hProcess
);
205 CloseHandle( info
.hThread
);
208 static WNDPROC old_proc
;
209 static LRESULT CALLBACK
winproc_wrapper( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
211 static int wm_renderallformats
;
212 static int wm_drawclipboard
;
214 DWORD msg_flags
= InSendMessageEx( NULL
);
216 if (!seqno
) seqno
= GetClipboardSequenceNumber();
218 trace( "%p msg %04x\n", hwnd
, msg
);
219 if (!wm_renderallformats
)
221 ok( GetClipboardOwner() == hwnd
, "%04x: wrong owner %p/%p\n", msg
, GetClipboardOwner(), hwnd
);
222 ok( seqno
== GetClipboardSequenceNumber(), "%04x: seqno changed\n", msg
);
226 ok( !GetClipboardOwner(), "%04x: wrong owner %p\n", msg
, GetClipboardOwner() );
227 ok( seqno
+ 1 == GetClipboardSequenceNumber(), "%04x: seqno unchanged\n", msg
);
229 ok( GetClipboardViewer() == hwnd
, "%04x: wrong viewer %p/%p\n", msg
, GetClipboardViewer(), hwnd
);
230 ok( GetOpenClipboardWindow() == hwnd
, "%04x: wrong open win %p/%p\n",
231 msg
, GetOpenClipboardWindow(), hwnd
);
236 ok( wm_renderallformats
, "didn't receive WM_RENDERALLFORMATS before WM_DESTROY\n" );
237 ok( wm_drawclipboard
, "didn't receive WM_DRAWCLIPBOARD before WM_DESTROY\n" );
239 case WM_DRAWCLIPBOARD
:
240 ok( msg_flags
== ISMEX_NOSEND
, "WM_DRAWCLIPBOARD wrong flags %x\n", msg_flags
);
243 case WM_RENDERALLFORMATS
:
244 ok( msg_flags
== ISMEX_NOSEND
, "WM_RENDERALLFORMATS wrong flags %x\n", msg_flags
);
245 wm_renderallformats
++;
248 return old_proc( hwnd
, msg
, wp
, lp
);
251 static void test_ClipboardOwner(void)
256 SetLastError(0xdeadbeef);
257 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef,
258 "could not perform clipboard test: clipboard already owned\n");
260 hWnd1
= CreateWindowExA(0, "static", NULL
, WS_POPUP
,
261 0, 0, 10, 10, 0, 0, 0, NULL
);
262 ok(hWnd1
!= 0, "CreateWindowExA error %d\n", GetLastError());
263 trace("hWnd1 = %p\n", hWnd1
);
265 hWnd2
= CreateWindowExA(0, "static", NULL
, WS_POPUP
,
266 0, 0, 10, 10, 0, 0, 0, NULL
);
267 ok(hWnd2
!= 0, "CreateWindowExA error %d\n", GetLastError());
268 trace("hWnd2 = %p\n", hWnd2
);
270 SetLastError(0xdeadbeef);
271 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
272 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
|| broken(GetLastError() == 0xdeadbeef), /* wow64 */
273 "wrong error %u\n", GetLastError());
275 ok(open_clipboard(0), "OpenClipboard failed\n");
276 ok(!GetClipboardOwner(), "clipboard should still be not owned\n");
277 ok(!OpenClipboard(hWnd1
), "OpenClipboard should fail since clipboard already opened\n");
278 ok(open_clipboard(0), "OpenClipboard again failed\n");
279 ret
= CloseClipboard();
280 ok( ret
, "CloseClipboard error %d\n", GetLastError());
282 ok(open_clipboard(hWnd1
), "OpenClipboard failed\n");
283 run_thread( open_clipboard_thread
, hWnd1
, __LINE__
);
284 run_thread( empty_clipboard_thread
, 0, __LINE__
);
285 run_thread( set_clipboard_data_thread
, hWnd1
, __LINE__
);
286 ok( !IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE available\n" );
287 ok( !GetClipboardData( CF_WAVE
), "CF_WAVE data available\n" );
288 run_process( "set_clipboard_data 0" );
289 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
290 ok(open_clipboard(hWnd1
), "OpenClipboard failed\n");
292 SetLastError(0xdeadbeef);
293 ret
= OpenClipboard(hWnd2
);
294 ok(!ret
&& (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED
),
295 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
297 SetLastError(0xdeadbeef);
298 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should still be not owned\n");
299 ret
= EmptyClipboard();
300 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
301 ok(GetClipboardOwner() == hWnd1
, "clipboard should be owned by %p, not by %p\n", hWnd1
, GetClipboardOwner());
302 run_thread( empty_clipboard_thread
, 0, __LINE__
);
303 run_thread( set_clipboard_data_thread
, hWnd1
, __LINE__
);
304 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
305 ok( GetClipboardData( CF_WAVE
) != 0, "CF_WAVE data not available\n" );
306 run_process( "set_clipboard_data 1" );
308 SetLastError(0xdeadbeef);
309 ret
= OpenClipboard(hWnd2
);
310 ok(!ret
&& (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED
),
311 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
313 ret
= CloseClipboard();
314 ok( ret
, "CloseClipboard error %d\n", GetLastError());
315 ok(GetClipboardOwner() == hWnd1
, "clipboard should still be owned\n");
317 /* any window will do, even from a different process */
318 ret
= open_clipboard( GetDesktopWindow() );
319 ok( ret
, "OpenClipboard error %d\n", GetLastError());
320 ret
= EmptyClipboard();
321 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
322 ok( GetClipboardOwner() == GetDesktopWindow(), "wrong owner %p/%p\n",
323 GetClipboardOwner(), GetDesktopWindow() );
324 run_thread( set_clipboard_data_thread
, GetDesktopWindow(), __LINE__
);
325 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
326 ok( GetClipboardData( CF_WAVE
) != 0, "CF_WAVE data not available\n" );
327 run_process( "set_clipboard_data 2" );
328 ret
= CloseClipboard();
329 ok( ret
, "CloseClipboard error %d\n", GetLastError());
331 ret
= open_clipboard( hWnd1
);
332 ok( ret
, "OpenClipboard error %d\n", GetLastError());
333 ret
= EmptyClipboard();
334 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
335 SetClipboardData( CF_WAVE
, 0 );
336 SetClipboardViewer( hWnd1
);
337 ok( GetClipboardOwner() == hWnd1
, "wrong owner %p/%p\n", GetClipboardOwner(), hWnd1
);
338 ok( GetClipboardViewer() == hWnd1
, "wrong viewer %p/%p\n", GetClipboardViewer(), hWnd1
);
339 ok( GetOpenClipboardWindow() == hWnd1
, "wrong open win %p/%p\n", GetOpenClipboardWindow(), hWnd1
);
340 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
342 old_proc
= (WNDPROC
)SetWindowLongPtrA( hWnd1
, GWLP_WNDPROC
, (LONG_PTR
)winproc_wrapper
);
343 ret
= DestroyWindow(hWnd1
);
344 ok( ret
, "DestroyWindow error %d\n", GetLastError());
345 ret
= DestroyWindow(hWnd2
);
346 ok( ret
, "DestroyWindow error %d\n", GetLastError());
347 SetLastError(0xdeadbeef);
348 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should not be owned\n");
349 ok(!GetClipboardViewer() && GetLastError() == 0xdeadbeef, "viewer still exists\n");
350 ok(!GetOpenClipboardWindow() && GetLastError() == 0xdeadbeef, "clipboard should not be open\n");
351 ok( !IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE available\n" );
353 SetLastError( 0xdeadbeef );
354 ret
= CloseClipboard();
355 ok( !ret
, "CloseClipboard succeeded\n" );
356 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "wrong error %u\n", GetLastError() );
358 ret
= open_clipboard( 0 );
359 ok( ret
, "OpenClipboard error %d\n", GetLastError());
360 run_thread( set_clipboard_data_thread
, 0, __LINE__
);
361 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
362 ok( GetClipboardData( CF_WAVE
) != 0, "CF_WAVE data not available\n" );
363 run_process( "set_clipboard_data 3" );
364 ret
= CloseClipboard();
365 ok( ret
, "CloseClipboard error %d\n", GetLastError());
367 run_thread( open_and_empty_clipboard_thread
, 0, __LINE__
);
368 ok( !GetOpenClipboardWindow(), "wrong open window %p\n", GetOpenClipboardWindow() );
369 ok( !GetClipboardOwner(), "wrong owner window %p\n", GetClipboardOwner() );
371 ret
= open_clipboard( 0 );
372 ok( ret
, "OpenClipboard error %d\n", GetLastError());
373 run_thread( set_clipboard_data_thread
, 0, __LINE__
);
374 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
375 ok( GetClipboardData( CF_WAVE
) != 0, "CF_WAVE data not available\n" );
376 run_process( "set_clipboard_data 4" );
377 ret
= EmptyClipboard();
378 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
379 ret
= CloseClipboard();
380 ok( ret
, "CloseClipboard error %d\n", GetLastError());
382 SetLastError( 0xdeadbeef );
383 ok( !SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 )),
384 "SetClipboardData succeeded\n" );
385 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "wrong error %u\n", GetLastError() );
386 ok( !IsClipboardFormatAvailable( CF_WAVE
), "SetClipboardData succeeded\n" );
388 run_thread( open_and_empty_clipboard_thread
, GetDesktopWindow(), __LINE__
);
389 ok( !GetOpenClipboardWindow(), "wrong open window %p\n", GetOpenClipboardWindow() );
390 ok( GetClipboardOwner() == GetDesktopWindow(), "wrong owner window %p / %p\n",
391 GetClipboardOwner(), GetDesktopWindow() );
393 run_thread( open_and_empty_clipboard_win_thread
, 0, __LINE__
);
394 ok( !GetOpenClipboardWindow(), "wrong open window %p\n", GetOpenClipboardWindow() );
395 ok( !GetClipboardOwner(), "wrong owner window %p\n", GetClipboardOwner() );
398 static void test_RegisterClipboardFormatA(void)
401 UINT format_id
, format_id2
;
407 format_id
= RegisterClipboardFormatA("my_cool_clipboard_format");
408 ok(format_id
> 0xc000 && format_id
< 0xffff, "invalid clipboard format id %04x\n", format_id
);
410 format_id2
= RegisterClipboardFormatA("MY_COOL_CLIPBOARD_FORMAT");
411 ok(format_id2
== format_id
, "invalid clipboard format id %04x\n", format_id2
);
413 len
= GetClipboardFormatNameA(format_id
, buf
, ARRAY_SIZE(buf
));
414 ok(len
== lstrlenA("my_cool_clipboard_format"), "wrong format name length %d\n", len
);
415 ok(!lstrcmpA(buf
, "my_cool_clipboard_format"), "wrong format name \"%s\"\n", buf
);
417 len
= GetClipboardFormatNameA(format_id
, NULL
, 0);
418 ok(len
== 0, "wrong format name length %d\n", len
);
420 lstrcpyA(buf
, "foo");
421 SetLastError(0xdeadbeef);
422 len
= GetAtomNameA((ATOM
)format_id
, buf
, ARRAY_SIZE(buf
));
423 ok(len
== 0 || lstrcmpA(buf
, "my_cool_clipboard_format") != 0,
424 "format_id should not be a valid local atom\n");
425 ok(len
!= 0 || GetLastError() == ERROR_INVALID_HANDLE
,
426 "err %d\n", GetLastError());
428 lstrcpyA(buf
, "foo");
429 SetLastError(0xdeadbeef);
430 len
= GlobalGetAtomNameA((ATOM
)format_id
, buf
, ARRAY_SIZE(buf
));
431 todo_wine
ok(len
== 0 || lstrcmpA(buf
, "my_cool_clipboard_format") != 0,
432 "format_id should not be a valid global atom\n");
433 ok(len
!= 0 || GetLastError() == ERROR_INVALID_HANDLE
,
434 "err %d\n", GetLastError());
436 SetLastError(0xdeadbeef);
437 atom_id
= FindAtomA("my_cool_clipboard_format");
438 ok(atom_id
== 0, "FindAtomA should fail, but it returned %x (format_id=%x)\n", atom_id
, format_id
);
439 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "err %d\n", GetLastError());
443 /* this relies on the clipboard and global atom table being different */
444 SetLastError(0xdeadbeef);
445 atom_id
= GlobalFindAtomA("my_cool_clipboard_format");
446 ok(atom_id
== 0, "GlobalFindAtomA should fail, but it returned %x (format_id=%x)\n", atom_id
, format_id
);
447 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "err %d\n", GetLastError());
450 for (format_id
= 0; format_id
< 0x10fff; format_id
++)
452 SetLastError(0xdeadbeef);
453 len
= GetClipboardFormatNameA(format_id
, buf
, ARRAY_SIZE(buf
));
455 if (format_id
< 0xc000 || format_id
> 0xffff)
456 ok(!len
, "GetClipboardFormatNameA should fail, but it returned %d (%s)\n", len
, buf
);
457 else if (len
&& winetest_debug
> 1)
458 trace("%04x: %s\n", format_id
, len
? buf
: "");
461 ret
= open_clipboard(0);
462 ok( ret
, "OpenClipboard error %d\n", GetLastError());
464 /* try some invalid/unregistered formats */
465 SetLastError( 0xdeadbeef );
466 handle
= SetClipboardData( 0, GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, 1 ));
467 ok( !handle
, "SetClipboardData succeeded\n" );
468 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "wrong error %u\n", GetLastError());
469 handle
= SetClipboardData( 0x1234, GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, 1 ));
470 ok( handle
!= 0, "SetClipboardData failed err %d\n", GetLastError());
471 handle
= SetClipboardData( 0x123456, GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, 1 ));
472 ok( handle
!= 0, "SetClipboardData failed err %d\n", GetLastError());
473 handle
= SetClipboardData( 0xffff8765, GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, 1 ));
474 ok( handle
!= 0, "SetClipboardData failed err %d\n", GetLastError());
476 ok( IsClipboardFormatAvailable( 0x1234 ), "format missing\n" );
477 ok( IsClipboardFormatAvailable( 0x123456 ), "format missing\n" );
478 ok( IsClipboardFormatAvailable( 0xffff8765 ), "format missing\n" );
479 ok( !IsClipboardFormatAvailable( 0 ), "format available\n" );
480 ok( !IsClipboardFormatAvailable( 0x3456 ), "format available\n" );
481 ok( !IsClipboardFormatAvailable( 0x8765 ), "format available\n" );
483 trace("# of formats available: %d\n", CountClipboardFormats());
486 while ((format_id
= EnumClipboardFormats(format_id
)))
488 ok(IsClipboardFormatAvailable(format_id
), "format %04x was listed as available\n", format_id
);
489 len
= GetClipboardFormatNameA(format_id
, buf
, ARRAY_SIZE(buf
));
490 trace("%04x: %s\n", format_id
, len
? buf
: "");
493 ret
= EmptyClipboard();
494 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
495 ret
=CloseClipboard();
496 ok( ret
, "CloseClipboard error %d\n", GetLastError());
498 if (CountClipboardFormats())
500 SetLastError(0xdeadbeef);
501 ok(!EnumClipboardFormats(0), "EnumClipboardFormats should fail if clipboard wasn't open\n");
502 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
,
503 "Last error should be set to ERROR_CLIPBOARD_NOT_OPEN, not %d\n", GetLastError());
506 SetLastError(0xdeadbeef);
507 ok(!EmptyClipboard(), "EmptyClipboard should fail if clipboard wasn't open\n");
508 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
|| broken(GetLastError() == 0xdeadbeef), /* wow64 */
509 "Wrong error %u\n", GetLastError());
511 format_id
= RegisterClipboardFormatA("#1234");
512 ok(format_id
== 1234, "invalid clipboard format id %04x\n", format_id
);
515 static HGLOBAL
create_textA(void)
517 HGLOBAL h
= GlobalAlloc(GMEM_DDESHARE
|GMEM_MOVEABLE
, 10);
518 char *p
= GlobalLock(h
);
519 memcpy(p
, "test\0\0\0\0\0", 10);
524 static HGLOBAL
create_textW(void)
526 static const WCHAR testW
[] = {'t','e','s','t',0,0,0,0,0,0};
527 HGLOBAL h
= GlobalAlloc(GMEM_DDESHARE
|GMEM_MOVEABLE
, sizeof(testW
));
528 WCHAR
*p
= GlobalLock(h
);
529 memcpy(p
, testW
, sizeof(testW
));
534 static HANDLE
create_metafile(void)
536 const RECT rect
= {0, 0, 100, 100};
540 HDC hdc
= CreateMetaFileA( NULL
);
541 ExtTextOutA( hdc
, 0, 0, ETO_OPAQUE
, &rect
, "Test String", strlen("Test String"), NULL
);
542 mf
= CloseMetaFile( hdc
);
543 ret
= GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, sizeof(*pict
) );
544 pict
= GlobalLock( ret
);
546 pict
->xExt
= pict
->yExt
= 100;
552 static HENHMETAFILE
create_emf(void)
554 const RECT rect
= {0, 0, 100, 100};
555 HDC hdc
= CreateEnhMetaFileA(NULL
, NULL
, &rect
, "HENHMETAFILE Ole Clipboard Test\0Test\0\0");
556 ExtTextOutA(hdc
, 0, 0, ETO_OPAQUE
, &rect
, "Test String", strlen("Test String"), NULL
);
557 return CloseEnhMetaFile(hdc
);
560 static HBITMAP
create_bitmap(void)
562 HDC hdc
= GetDC( 0 );
563 UINT bpp
= GetDeviceCaps( hdc
, BITSPIXEL
);
565 return CreateBitmap( 10, 10, 1, bpp
, NULL
);
568 static HBITMAP
create_dib( BOOL v5
)
571 BITMAPINFOHEADER
*hdr
;
573 ret
= GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
| GMEM_ZEROINIT
,
574 sizeof(BITMAPV5HEADER
) + 256 * sizeof(RGBQUAD
) + 16 * 16 * 4 );
575 hdr
= GlobalLock( ret
);
576 hdr
->biSize
= v5
? sizeof(BITMAPV5HEADER
) : sizeof(*hdr
);
580 hdr
->biBitCount
= 32;
581 hdr
->biCompression
= BI_RGB
;
584 BITMAPV5HEADER
*hdr5
= (BITMAPV5HEADER
*)hdr
;
585 hdr5
->bV5RedMask
= 0x0000ff;
586 hdr5
->bV5GreenMask
= 0x00ff00;
587 hdr5
->bV5BlueMask
= 0xff0000;
588 hdr5
->bV5AlphaMask
= 0xff000000;
594 static LRESULT CALLBACK
renderer_winproc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
596 static UINT rendered
;
601 case WM_RENDERFORMAT
:
602 if (wp
< 32) rendered
|= (1 << wp
);
609 return DefWindowProcA( hwnd
, msg
, wp
, lp
);
612 static void test_synthesized(void)
614 static const struct test
620 /* 0 */ { CF_TEXT
, { CF_TEXT
, CF_LOCALE
, CF_OEMTEXT
, CF_UNICODETEXT
}},
621 { CF_OEMTEXT
, { CF_OEMTEXT
, CF_LOCALE
, CF_TEXT
, CF_UNICODETEXT
}},
622 { CF_UNICODETEXT
, { CF_UNICODETEXT
, CF_LOCALE
, CF_TEXT
, CF_OEMTEXT
}},
623 { CF_ENHMETAFILE
, { CF_ENHMETAFILE
, CF_METAFILEPICT
}},
624 { CF_METAFILEPICT
, { CF_METAFILEPICT
, CF_ENHMETAFILE
}},
625 /* 5 */ { CF_BITMAP
, { CF_BITMAP
, CF_DIB
, CF_DIBV5
}},
626 { CF_DIB
, { CF_DIB
, CF_BITMAP
, CF_DIBV5
}},
627 { CF_DIBV5
, { CF_DIBV5
, CF_BITMAP
, CF_DIB
}},
633 UINT cf
, i
, j
, count
, rendered
, seq
, old_seq
;
637 hwnd
= CreateWindowA( "static", NULL
, WS_POPUP
, 0, 0, 10, 10, 0, 0, 0, NULL
);
638 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)renderer_winproc
);
640 htext
= create_textA();
643 r
= open_clipboard(NULL
);
644 ok(r
, "gle %d\n", GetLastError());
645 r
= EmptyClipboard();
646 ok(r
, "gle %d\n", GetLastError());
647 h
= SetClipboardData(CF_TEXT
, htext
);
648 ok(h
== htext
, "got %p\n", h
);
649 h
= SetClipboardData(CF_ENHMETAFILE
, emf
);
650 ok(h
== emf
, "got %p\n", h
);
651 r
= CloseClipboard();
652 ok(r
, "gle %d\n", GetLastError());
654 count
= CountClipboardFormats();
655 ok( count
== 6, "count %u\n", count
);
656 r
= IsClipboardFormatAvailable( CF_TEXT
);
657 ok( r
, "CF_TEXT not available err %d\n", GetLastError());
658 r
= IsClipboardFormatAvailable( CF_LOCALE
);
659 ok( r
, "CF_LOCALE not available err %d\n", GetLastError());
660 r
= IsClipboardFormatAvailable( CF_OEMTEXT
);
661 ok( r
, "CF_OEMTEXT not available err %d\n", GetLastError());
662 r
= IsClipboardFormatAvailable( CF_UNICODETEXT
);
663 ok( r
, "CF_UNICODETEXT not available err %d\n", GetLastError());
664 r
= IsClipboardFormatAvailable( CF_ENHMETAFILE
);
665 ok( r
, "CF_ENHMETAFILE not available err %d\n", GetLastError());
666 r
= IsClipboardFormatAvailable( CF_METAFILEPICT
);
667 ok( r
, "CF_METAFILEPICT not available err %d\n", GetLastError());
669 r
= open_clipboard(NULL
);
670 ok(r
, "gle %d\n", GetLastError());
671 cf
= EnumClipboardFormats(0);
672 ok(cf
== CF_TEXT
, "cf %08x\n", cf
);
673 data
= GetClipboardData(cf
);
674 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
676 cf
= EnumClipboardFormats(cf
);
677 ok(cf
== CF_ENHMETAFILE
, "cf %08x\n", cf
);
678 data
= GetClipboardData(cf
);
679 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
681 cf
= EnumClipboardFormats(cf
);
682 ok(cf
== CF_LOCALE
, "cf %08x\n", cf
);
683 data
= GetClipboardData(cf
);
684 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
686 cf
= EnumClipboardFormats(cf
);
687 ok(cf
== CF_OEMTEXT
, "cf %08x\n", cf
);
688 data
= GetClipboardData(cf
);
689 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
691 cf
= EnumClipboardFormats(cf
);
692 ok(cf
== CF_UNICODETEXT
, "cf %08x\n", cf
);
694 cf
= EnumClipboardFormats(cf
);
695 ok(cf
== CF_METAFILEPICT
, "cf %08x\n", cf
);
696 data
= GetClipboardData(cf
);
697 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
699 cf
= EnumClipboardFormats(cf
);
700 ok(cf
== 0, "cf %08x\n", cf
);
702 r
= EmptyClipboard();
703 ok(r
, "gle %d\n", GetLastError());
705 SetClipboardData( CF_UNICODETEXT
, create_textW() );
706 SetClipboardData( CF_TEXT
, create_textA() );
707 SetClipboardData( CF_OEMTEXT
, create_textA() );
708 r
= CloseClipboard();
709 ok(r
, "gle %d\n", GetLastError());
711 r
= open_clipboard( NULL
);
712 ok(r
, "gle %d\n", GetLastError());
713 SetLastError( 0xdeadbeef );
714 cf
= EnumClipboardFormats(0);
715 ok( cf
== CF_UNICODETEXT
, "cf %08x\n", cf
);
716 ok( GetLastError() == ERROR_SUCCESS
, "wrong error %u\n", GetLastError() );
717 SetLastError( 0xdeadbeef );
718 cf
= EnumClipboardFormats(cf
);
719 ok( cf
== CF_TEXT
, "cf %08x\n", cf
);
720 ok( GetLastError() == ERROR_SUCCESS
, "wrong error %u\n", GetLastError() );
721 SetLastError( 0xdeadbeef );
722 cf
= EnumClipboardFormats(cf
);
723 ok( cf
== CF_OEMTEXT
, "cf %08x\n", cf
);
724 ok( GetLastError() == ERROR_SUCCESS
, "wrong error %u\n", GetLastError() );
725 SetLastError( 0xdeadbeef );
726 cf
= EnumClipboardFormats(cf
);
727 ok( cf
== CF_LOCALE
, "cf %08x\n", cf
);
728 ok( GetLastError() == ERROR_SUCCESS
, "wrong error %u\n", GetLastError() );
729 SetLastError( 0xdeadbeef );
730 cf
= EnumClipboardFormats( cf
);
731 ok( cf
== 0, "cf %08x\n", cf
);
732 ok( GetLastError() == ERROR_SUCCESS
, "wrong error %u\n", GetLastError() );
733 SetLastError( 0xdeadbeef );
734 cf
= EnumClipboardFormats( 0xdead );
735 ok( cf
== 0, "cf %08x\n", cf
);
736 ok( GetLastError() == ERROR_SUCCESS
, "wrong error %u\n", GetLastError() );
738 r
= EmptyClipboard();
739 ok(r
, "gle %d\n", GetLastError());
741 r
= CloseClipboard();
742 ok(r
, "gle %d\n", GetLastError());
744 for (i
= 0; i
< ARRAY_SIZE(tests
); i
++)
746 winetest_push_context("%d", i
);
747 r
= open_clipboard(NULL
);
748 ok(r
, "gle %d\n", GetLastError());
749 r
= EmptyClipboard();
750 ok(r
, "gle %d\n", GetLastError());
752 switch (tests
[i
].format
)
756 SetClipboardData( tests
[i
].format
, create_textA() );
759 SetClipboardData( CF_UNICODETEXT
, create_textW() );
762 SetClipboardData( CF_ENHMETAFILE
, create_emf() );
764 case CF_METAFILEPICT
:
765 SetClipboardData( CF_METAFILEPICT
, create_metafile() );
768 SetClipboardData( CF_BITMAP
, create_bitmap() );
772 SetClipboardData( tests
[i
].format
, create_dib( tests
[i
].format
== CF_DIBV5
));
776 count
= CountClipboardFormats();
777 ok( count
== 1, "count %u\n", count
);
779 r
= CloseClipboard();
780 ok(r
, "gle %d\n", GetLastError());
782 count
= CountClipboardFormats();
783 for (j
= 0; tests
[i
].expected
[j
]; j
++)
785 r
= IsClipboardFormatAvailable( tests
[i
].expected
[j
] );
786 ok( r
, "%04x not available\n", tests
[i
].expected
[j
] );
788 ok( count
== j
, "count %u instead of %u\n", count
, j
);
790 r
= open_clipboard( hwnd
);
791 ok(r
, "gle %d\n", GetLastError());
793 for (j
= 0; tests
[i
].expected
[j
]; j
++)
795 winetest_push_context("%d", j
);
796 cf
= EnumClipboardFormats( cf
);
797 ok(cf
== tests
[i
].expected
[j
], "got %04x instead of %04x\n",
798 cf
, tests
[i
].expected
[j
] );
799 if (cf
!= tests
[i
].expected
[j
])
801 winetest_pop_context();
804 old_seq
= GetClipboardSequenceNumber();
805 data
= GetClipboardData( cf
);
807 broken( tests
[i
].format
== CF_DIBV5
&& cf
== CF_DIB
), /* >= Vista */
808 "couldn't get data, cf %04x err %d\n", cf
, GetLastError());
809 seq
= GetClipboardSequenceNumber();
810 ok(seq
== old_seq
, "sequence changed (test %d)\n", cf
);
815 UINT
*ptr
= GlobalLock( data
);
816 DWORD layout
= LOWORD( GetKeyboardLayout(0) );
817 ok( GlobalSize( data
) == sizeof(*ptr
), "size %lu\n", GlobalSize( data
));
818 ok( *ptr
== layout
||
819 broken( *ptr
== MAKELANGID( LANG_ENGLISH
, SUBLANG_DEFAULT
)),
820 "CF_LOCALE %04x/%04x\n", *ptr
, layout
);
821 GlobalUnlock( data
);
826 ok( GlobalSize( data
) == 10, "wrong len %ld\n", GlobalSize( data
));
829 ok( GlobalSize( data
) == 10 * sizeof(WCHAR
), "wrong len %ld\n", GlobalSize( data
));
832 winetest_pop_context();
834 if (!tests
[i
].expected
[j
])
836 cf
= EnumClipboardFormats( cf
);
837 ok(cf
== 0, "cf %04x\n", cf
);
840 /* now with delayed rendering */
842 r
= EmptyClipboard();
843 ok(r
, "gle %d\n", GetLastError());
845 rendered
= SendMessageA( hwnd
, WM_USER
, 0, 0 );
846 ok( !rendered
, "formats %08x have been rendered\n", rendered
);
848 SetClipboardData( tests
[i
].format
, 0 );
849 rendered
= SendMessageA( hwnd
, WM_USER
, 0, 0 );
850 ok( !rendered
, "formats %08x have been rendered\n", rendered
);
852 count
= CountClipboardFormats();
853 ok( count
== 1, "count %u\n", count
);
855 r
= CloseClipboard();
856 ok(r
, "gle %d\n", GetLastError());
857 rendered
= SendMessageA( hwnd
, WM_USER
, 0, 0 );
858 ok( !rendered
, "formats %08x have been rendered\n", rendered
);
860 count
= CountClipboardFormats();
861 for (j
= 0; tests
[i
].expected
[j
]; j
++)
863 r
= IsClipboardFormatAvailable( tests
[i
].expected
[j
] );
864 ok( r
, "%04x not available\n", tests
[i
].expected
[j
] );
866 ok( count
== j
, "count %u instead of %u\n", count
, j
);
867 rendered
= SendMessageA( hwnd
, WM_USER
, 0, 0 );
868 ok( !rendered
, "formats %08x have been rendered\n", rendered
);
870 r
= open_clipboard(NULL
);
871 ok(r
, "gle %d\n", GetLastError());
873 for (j
= 0; tests
[i
].expected
[j
]; j
++)
875 winetest_push_context("%d", j
);
876 cf
= EnumClipboardFormats( cf
);
877 ok(cf
== tests
[i
].expected
[j
], "got %04x instead of %04x\n",
878 cf
, tests
[i
].expected
[j
] );
879 if (cf
!= tests
[i
].expected
[j
])
881 winetest_pop_context();
884 rendered
= SendMessageA( hwnd
, WM_USER
, 0, 0 );
885 ok( !rendered
, "formats %08x have been rendered\n", rendered
);
886 data
= GetClipboardData( cf
);
887 rendered
= SendMessageA( hwnd
, WM_USER
, 0, 0 );
890 ok(data
!= NULL
, "CF_LOCALE no data\n");
891 ok( !rendered
, "formats %08x have been rendered\n", rendered
);
895 ok(!data
, "format %04x got data %p\n", cf
, data
);
896 ok( rendered
== (1 << tests
[i
].format
),
897 "formats %08x have been rendered\n", rendered
);
898 /* try to render a second time */
899 data
= GetClipboardData( cf
);
900 rendered
= SendMessageA( hwnd
, WM_USER
, 0, 0 );
901 ok( rendered
== (1 << tests
[i
].format
),
902 "formats %08x have been rendered\n", rendered
);
904 winetest_pop_context();
906 if (!tests
[i
].expected
[j
])
908 cf
= EnumClipboardFormats( cf
);
909 ok(cf
== 0, "cf %04x\n", cf
);
911 r
= CloseClipboard();
912 ok(r
, "gle %d\n", GetLastError());
913 rendered
= SendMessageA( hwnd
, WM_USER
, 0, 0 );
914 ok( !rendered
, "formats %08x have been rendered\n", rendered
);
915 winetest_pop_context();
918 r
= open_clipboard(NULL
);
919 ok(r
, "gle %d\n", GetLastError());
920 r
= EmptyClipboard();
921 ok(r
, "gle %d\n", GetLastError());
922 r
= CloseClipboard();
923 ok(r
, "gle %d\n", GetLastError());
924 DestroyWindow( hwnd
);
927 static DWORD WINAPI
clipboard_render_data_thread(void *param
)
929 HANDLE handle
= SetClipboardData( CF_UNICODETEXT
, create_textW() );
930 ok( handle
!= 0, "SetClipboardData failed: %d\n", GetLastError() );
934 static CRITICAL_SECTION clipboard_cs
;
935 static HWND next_wnd
;
936 static UINT wm_drawclipboard
;
937 static UINT wm_clipboardupdate
;
938 static UINT wm_destroyclipboard
;
939 static UINT wm_renderformat
;
940 static UINT nb_formats
;
941 static BOOL cross_thread
;
942 static BOOL do_render_format
;
943 static HANDLE update_event
;
945 static LRESULT CALLBACK
clipboard_wnd_proc(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
948 DWORD msg_flags
= InSendMessageEx( NULL
);
951 case WM_DRAWCLIPBOARD
:
952 ok( msg_flags
== (cross_thread
? ISMEX_NOTIFY
: ISMEX_NOSEND
),
953 "WM_DRAWCLIPBOARD wrong flags %x\n", msg_flags
);
954 EnterCriticalSection(&clipboard_cs
);
956 LeaveCriticalSection(&clipboard_cs
);
958 case WM_CHANGECBCHAIN
:
959 ok( msg_flags
== (cross_thread
? ISMEX_SEND
: ISMEX_NOSEND
),
960 "WM_CHANGECBCHAIN wrong flags %x\n", msg_flags
);
961 if (next_wnd
== (HWND
)wp
)
964 SendMessageA(next_wnd
, msg
, wp
, lp
);
966 case WM_DESTROYCLIPBOARD
:
967 ok( msg_flags
== (cross_thread
? ISMEX_SEND
: ISMEX_NOSEND
),
968 "WM_DESTROYCLIPBOARD wrong flags %x\n", msg_flags
);
969 wm_destroyclipboard
++;
970 ok( GetClipboardOwner() == hwnd
, "WM_DESTROYCLIPBOARD owner %p\n", GetClipboardOwner() );
971 nb_formats
= CountClipboardFormats();
973 case WM_RENDERFORMAT
:
974 ok( !wm_renderformat
, "multiple WM_RENDERFORMAT %04x / %04lx\n", wm_renderformat
, wp
);
975 wm_renderformat
= wp
;
977 if (do_render_format
)
982 old_seq
= GetClipboardSequenceNumber();
983 handle
= SetClipboardData( CF_TEXT
, create_textA() );
984 ok( handle
!= 0, "SetClipboardData failed: %d\n", GetLastError() );
985 seq
= GetClipboardSequenceNumber();
986 ok( seq
== old_seq
, "sequence changed\n" );
989 handle
= CreateThread( NULL
, 0, clipboard_render_data_thread
, NULL
, 0, NULL
);
990 ok( handle
!= NULL
, "CreateThread failed: %d\n", GetLastError() );
991 ok( WaitForSingleObject(handle
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n" );
992 CloseHandle( handle
);
993 seq
= GetClipboardSequenceNumber();
994 ok( seq
== old_seq
, "sequence changed\n" );
998 case WM_CLIPBOARDUPDATE
:
999 ok( msg_flags
== ISMEX_NOSEND
, "WM_CLIPBOARDUPDATE wrong flags %x\n", msg_flags
);
1000 EnterCriticalSection(&clipboard_cs
);
1001 wm_clipboardupdate
++;
1002 SetEvent(update_event
);
1003 LeaveCriticalSection(&clipboard_cs
);
1006 ChangeClipboardChain(hwnd
, next_wnd
);
1010 ret
= wm_drawclipboard
;
1011 wm_drawclipboard
= 0;
1014 ret
= wm_clipboardupdate
;
1015 wm_clipboardupdate
= 0;
1018 ret
= wm_destroyclipboard
;
1019 wm_destroyclipboard
= 0;
1022 ret
= wm_renderformat
;
1023 wm_renderformat
= 0;
1029 return DefWindowProcA(hwnd
, msg
, wp
, lp
);
1032 static void get_clipboard_data_process(void)
1037 r
= open_clipboard(0);
1038 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
1039 data
= GetClipboardData( CF_UNICODETEXT
);
1040 ok( data
!= NULL
, "GetClipboardData failed: %d\n", GetLastError());
1041 r
= CloseClipboard();
1042 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
1045 static UINT old_seq
;
1047 static void check_messages_(int line
, HWND win
, UINT seq_diff
, UINT draw
, UINT update
, UINT destroy
, UINT render
)
1050 UINT count
, fmt
, seq
;
1052 seq
= GetClipboardSequenceNumber();
1053 ok_(__FILE__
, line
)(seq
- old_seq
== seq_diff
, "sequence diff %d\n", seq
- old_seq
);
1058 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
1061 if (update
&& !broken(!pAddClipboardFormatListener
))
1062 ok(WaitForSingleObject(update_event
, 1000) == WAIT_OBJECT_0
, "wait failed\n");
1064 count
= SendMessageA( win
, WM_USER
+ 1, 0, 0 );
1065 ok_(__FILE__
, line
)(count
== draw
, "WM_DRAWCLIPBOARD %sreceived\n", draw
? "not " : "");
1066 count
= SendMessageA( win
, WM_USER
+ 2, 0, 0 );
1067 ok_(__FILE__
, line
)(count
== update
|| broken(!pAddClipboardFormatListener
),
1068 "WM_CLIPBOARDUPDATE %sreceived\n", update
? "not " : "");
1069 count
= SendMessageA( win
, WM_USER
+ 3, 0, 0 );
1070 ok_(__FILE__
, line
)(count
== destroy
, "WM_DESTROYCLIPBOARD %sreceived\n", destroy
? "not " : "");
1071 fmt
= SendMessageA( win
, WM_USER
+ 4, 0, 0 );
1072 ok_(__FILE__
, line
)(fmt
== render
, "WM_RENDERFORMAT received %04x, expected %04x\n", fmt
, render
);
1074 #define check_messages(a,b,c,d,e,f) check_messages_(__LINE__,a,b,c,d,e,f)
1076 static DWORD WINAPI
clipboard_thread(void *param
)
1078 HWND ret
, win
= param
;
1082 UINT count
, fmt
, formats
;
1084 cross_thread
= (GetWindowThreadProcessId( win
, NULL
) != GetCurrentThreadId());
1085 trace( "%s-threaded test\n", cross_thread
? "multi" : "single" );
1087 old_seq
= GetClipboardSequenceNumber();
1089 EnterCriticalSection(&clipboard_cs
);
1090 SetLastError(0xdeadbeef);
1091 next_wnd
= SetClipboardViewer(win
);
1092 ok(GetLastError() == 0xdeadbeef, "GetLastError = %d\n", GetLastError());
1093 LeaveCriticalSection(&clipboard_cs
);
1095 SetLastError( 0xdeadbeef );
1096 ret
= SetClipboardViewer( (HWND
)0xdead );
1097 ok( !ret
, "SetClipboardViewer succeeded\n" );
1098 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %u\n", GetLastError() );
1099 SetLastError( 0xdeadbeef );
1100 r
= ChangeClipboardChain( win
, (HWND
)0xdead );
1101 ok( !r
, "ChangeClipboardChain succeeded\n" );
1102 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %u\n", GetLastError() );
1103 SetLastError( 0xdeadbeef );
1104 r
= ChangeClipboardChain( (HWND
)0xdead, next_wnd
);
1105 ok( !r
, "ChangeClipboardChain succeeded\n" );
1106 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %u\n", GetLastError() );
1108 if (pAddClipboardFormatListener
)
1110 r
= pAddClipboardFormatListener(win
);
1111 ok( r
, "AddClipboardFormatListener failed err %d\n", GetLastError());
1112 SetLastError( 0xdeadbeef );
1113 r
= pAddClipboardFormatListener( win
);
1114 ok( !r
, "AddClipboardFormatListener succeeded\n" );
1115 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1116 SetLastError( 0xdeadbeef );
1117 r
= pAddClipboardFormatListener( (HWND
)0xdead );
1118 ok( !r
, "AddClipboardFormatListener succeeded\n" );
1119 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %u\n", GetLastError() );
1120 r
= pAddClipboardFormatListener( GetDesktopWindow() );
1121 ok( r
, "AddClipboardFormatListener failed err %d\n", GetLastError());
1122 r
= pRemoveClipboardFormatListener( GetDesktopWindow() );
1123 ok( r
, "RemoveClipboardFormatListener failed err %d\n", GetLastError());
1126 check_messages(win
, 0, 1, 0, 0, 0);
1128 SetLastError( 0xdeadbeef );
1129 r
= OpenClipboard( (HWND
)0xdead );
1130 ok( !r
, "OpenClipboard succeeded\n" );
1131 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %u\n", GetLastError() );
1133 r
= open_clipboard(win
);
1134 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
1136 check_messages(win
, 0, 0, 0, 0, 0);
1138 r
= EmptyClipboard();
1139 ok(r
, "EmptyClipboard failed: %d\n", GetLastError());
1141 check_messages(win
, 1, 0, 0, 0, 0);
1143 r
= EmptyClipboard();
1144 ok(r
, "EmptyClipboard failed: %d\n", GetLastError());
1145 /* sequence changes again, even though it was already empty */
1146 check_messages(win
, 1, 0, 0, 1, 0);
1147 count
= SendMessageA( win
, WM_USER
+5, 0, 0 );
1148 ok( !count
, "wrong format count %u on WM_DESTROYCLIPBOARD\n", count
);
1150 handle
= SetClipboardData( CF_TEXT
, create_textA() );
1151 ok(handle
!= 0, "SetClipboardData failed: %d\n", GetLastError());
1153 check_messages(win
, 1, 0, 0, 0, 0);
1155 SetClipboardData( CF_UNICODETEXT
, 0 );
1157 check_messages(win
, 1, 0, 0, 0, 0);
1159 SetClipboardData( CF_UNICODETEXT
, 0 ); /* same data again */
1161 check_messages(win
, 1, 0, 0, 0, 0);
1163 ok( IsClipboardFormatAvailable( CF_TEXT
), "CF_TEXT available\n" );
1164 ok( IsClipboardFormatAvailable( CF_UNICODETEXT
), "CF_UNICODETEXT available\n" );
1165 ok( !IsClipboardFormatAvailable( CF_OEMTEXT
), "CF_OEMTEXT available\n" );
1167 EnterCriticalSection(&clipboard_cs
);
1168 r
= CloseClipboard();
1169 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
1170 LeaveCriticalSection(&clipboard_cs
);
1172 check_messages(win
, 2, 1, 1, 0, 0);
1174 r
= open_clipboard(win
);
1175 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
1177 check_messages(win
, 0, 0, 0, 0, 0);
1179 ok( IsClipboardFormatAvailable( CF_TEXT
), "CF_TEXT available\n" );
1180 ok( IsClipboardFormatAvailable( CF_UNICODETEXT
), "CF_UNICODETEXT available\n" );
1181 ok( IsClipboardFormatAvailable( CF_OEMTEXT
), "CF_OEMTEXT available\n" );
1183 ok( GetClipboardOwner() == win
, "wrong owner %p\n", GetClipboardOwner());
1184 handle
= GetClipboardData( CF_UNICODETEXT
);
1185 ok( !handle
, "got data for CF_UNICODETEXT\n" );
1186 fmt
= SendMessageA( win
, WM_USER
+4, 0, 0 );
1187 ok( fmt
== CF_UNICODETEXT
, "WM_RENDERFORMAT received %04x\n", fmt
);
1189 do_render_format
= TRUE
;
1190 handle
= GetClipboardData( CF_OEMTEXT
);
1191 ok( handle
!= NULL
, "didn't get data for CF_OEMTEXT\n" );
1192 fmt
= SendMessageA( win
, WM_USER
+4, 0, 0 );
1193 ok( fmt
== CF_UNICODETEXT
, "WM_RENDERFORMAT received %04x\n", fmt
);
1194 do_render_format
= FALSE
;
1196 SetClipboardData( CF_WAVE
, 0 );
1197 check_messages(win
, 1, 0, 0, 0, 0);
1199 r
= CloseClipboard();
1200 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
1201 /* no synthesized format, so CloseClipboard doesn't change the sequence */
1202 check_messages(win
, 0, 1, 1, 0, 0);
1204 r
= open_clipboard(win
);
1205 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
1206 r
= CloseClipboard();
1207 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
1208 /* nothing changed */
1209 check_messages(win
, 0, 0, 0, 0, 0);
1211 formats
= CountClipboardFormats();
1212 r
= open_clipboard(0);
1213 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
1214 r
= EmptyClipboard();
1215 ok(r
, "EmptyClipboard failed: %d\n", GetLastError());
1216 r
= CloseClipboard();
1217 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
1219 check_messages(win
, 1, 1, 1, 1, 0);
1220 count
= SendMessageA( win
, WM_USER
+5, 0, 0 );
1221 ok( count
== formats
, "wrong format count %u on WM_DESTROYCLIPBOARD\n", count
);
1223 r
= open_clipboard(win
);
1224 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
1225 SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_FIXED
, 1 ));
1226 check_messages(win
, 1, 0, 0, 0, 0);
1228 EnterCriticalSection(&clipboard_cs
);
1229 r
= CloseClipboard();
1230 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
1231 LeaveCriticalSection(&clipboard_cs
);
1233 check_messages(win
, 0, 1, 1, 0, 0);
1235 run_process( "grab_clipboard 0" );
1239 /* in this case we get a cross-thread WM_DRAWCLIPBOARD */
1240 cross_thread
= TRUE
;
1241 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
1242 cross_thread
= FALSE
;
1244 check_messages(win
, 1, 1, 1, 0, 0);
1246 r
= open_clipboard(0);
1247 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
1248 SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_FIXED
, 1 ));
1249 check_messages(win
, 1, 0, 0, 0, 0);
1251 EnterCriticalSection(&clipboard_cs
);
1252 r
= CloseClipboard();
1253 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
1254 LeaveCriticalSection(&clipboard_cs
);
1256 check_messages(win
, 0, 1, 1, 0, 0);
1258 run_process( "grab_clipboard 1" );
1262 /* in this case we get a cross-thread WM_DRAWCLIPBOARD */
1263 cross_thread
= TRUE
;
1264 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
1265 cross_thread
= FALSE
;
1267 check_messages(win
, 2, 1, 1, 0, 0);
1269 r
= open_clipboard(0);
1270 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
1271 SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_FIXED
, 1 ));
1272 check_messages(win
, 1, 0, 0, 0, 0);
1274 EnterCriticalSection(&clipboard_cs
);
1275 r
= CloseClipboard();
1276 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
1277 LeaveCriticalSection(&clipboard_cs
);
1279 check_messages(win
, 0, 1, 1, 0, 0);
1283 r
= open_clipboard( win
);
1284 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
1285 r
= EmptyClipboard();
1286 ok(r
, "EmptyClipboard failed: %d\n", GetLastError());
1287 SetClipboardData( CF_TEXT
, 0 );
1288 r
= CloseClipboard();
1289 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
1291 do_render_format
= TRUE
;
1292 old_seq
= GetClipboardSequenceNumber();
1293 run_process( "get_clipboard_data" );
1294 do_render_format
= FALSE
;
1296 check_messages(win
, 0, 1, 1, 0, CF_TEXT
);
1299 r
= PostMessageA(win
, WM_USER
, 0, 0);
1300 ok(r
, "PostMessage failed: %d\n", GetLastError());
1302 if (pRemoveClipboardFormatListener
)
1304 r
= pRemoveClipboardFormatListener(win
);
1305 ok( r
, "RemoveClipboardFormatListener failed err %d\n", GetLastError());
1306 SetLastError( 0xdeadbeef );
1307 r
= pRemoveClipboardFormatListener(win
);
1308 ok( !r
, "RemoveClipboardFormatListener succeeded\n" );
1309 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1310 SetLastError( 0xdeadbeef );
1311 r
= pRemoveClipboardFormatListener( (HWND
)0xdead );
1312 ok( !r
, "RemoveClipboardFormatListener succeeded\n" );
1313 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %u\n", GetLastError() );
1318 static void test_messages(void)
1326 InitializeCriticalSection(&clipboard_cs
);
1327 update_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1329 memset(&cls
, 0, sizeof(cls
));
1330 cls
.lpfnWndProc
= clipboard_wnd_proc
;
1331 cls
.hInstance
= GetModuleHandleA(NULL
);
1332 cls
.lpszClassName
= "clipboard_test";
1333 RegisterClassA(&cls
);
1335 win
= CreateWindowA("clipboard_test", NULL
, 0, 0, 0, 0, 0, NULL
, 0, NULL
, 0);
1336 ok(win
!= NULL
, "CreateWindow failed: %d\n", GetLastError());
1338 thread
= CreateThread(NULL
, 0, clipboard_thread
, (void*)win
, 0, &tid
);
1339 ok(thread
!= NULL
, "CreateThread failed: %d\n", GetLastError());
1341 while(GetMessageA(&msg
, NULL
, 0, 0))
1343 ok( msg
.message
!= WM_DRAWCLIPBOARD
, "WM_DRAWCLIPBOARD was posted\n" );
1344 TranslateMessage(&msg
);
1345 DispatchMessageA(&msg
);
1348 ok(WaitForSingleObject(thread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
1349 CloseHandle(thread
);
1351 DestroyWindow( win
);
1353 /* same tests again but inside a single thread */
1355 win
= CreateWindowA( "clipboard_test", NULL
, 0, 0, 0, 0, 0, NULL
, 0, NULL
, 0 );
1356 ok( win
!= NULL
, "CreateWindow failed: %d\n", GetLastError() );
1358 clipboard_thread( win
);
1359 DestroyWindow( win
);
1361 UnregisterClassA("clipboard_test", GetModuleHandleA(NULL
));
1362 DeleteCriticalSection(&clipboard_cs
);
1365 static BOOL
is_moveable( HANDLE handle
)
1367 void *ptr
= GlobalLock( handle
);
1368 if (ptr
) GlobalUnlock( handle
);
1369 return ptr
&& ptr
!= handle
;
1372 static BOOL
is_fixed( HANDLE handle
)
1374 void *ptr
= GlobalLock( handle
);
1375 if (ptr
) GlobalUnlock( handle
);
1376 return ptr
&& ptr
== handle
;
1379 static BOOL
is_freed( HANDLE handle
)
1381 return !GlobalSize( handle
);
1384 static UINT format_id
;
1385 static HBITMAP bitmap
, bitmap2
;
1386 static HPALETTE palette
;
1387 static const LOGPALETTE logpalette
= { 0x300, 1, {{ 0x12, 0x34, 0x56, 0x78 }}};
1389 static void test_handles( HWND hwnd
)
1391 HGLOBAL h
, htext
, htext2
, htext3
, htext4
, htext5
;
1392 HGLOBAL hfixed
, hfixed2
, hmoveable
, empty_fixed
, empty_moveable
;
1394 UINT format_id2
= RegisterClipboardFormatA( "another format" );
1397 HBITMAP bitmap_temp
;
1399 BOOL is_owner
= (GetWindowThreadProcessId( hwnd
, &process
) && process
== GetCurrentProcessId());
1401 trace( "hwnd %p\n", hwnd
);
1402 htext
= create_textA();
1403 htext2
= create_textA();
1404 htext3
= create_textA();
1405 htext4
= create_textA();
1406 htext5
= create_textA();
1407 bitmap
= CreateBitmap( 10, 10, 1, 1, NULL
);
1408 bitmap2
= CreateBitmap( 10, 10, 1, 1, NULL
);
1409 palette
= CreatePalette( &logpalette
);
1411 hfixed
= GlobalAlloc( GMEM_FIXED
, 17 );
1412 hfixed2
= GlobalAlloc( GMEM_FIXED
, 17 );
1413 ok( is_fixed( hfixed
), "expected fixed mem %p\n", hfixed
);
1414 ok( GlobalSize( hfixed
) == 17, "wrong size %lu\n", GlobalSize( hfixed
));
1416 hmoveable
= GlobalAlloc( GMEM_MOVEABLE
, 23 );
1417 ok( is_moveable( hmoveable
), "expected moveable mem %p\n", hmoveable
);
1418 ok( GlobalSize( hmoveable
) == 23, "wrong size %lu\n", GlobalSize( hmoveable
));
1420 empty_fixed
= GlobalAlloc( GMEM_FIXED
, 0 );
1421 ok( is_fixed( empty_fixed
), "expected fixed mem %p\n", empty_fixed
);
1423 empty_moveable
= GlobalAlloc( GMEM_MOVEABLE
, 0 );
1424 /* discarded handles can't be GlobalLock'ed */
1425 ok( is_freed( empty_moveable
), "expected free mem %p\n", empty_moveable
);
1427 r
= open_clipboard( hwnd
);
1428 ok( r
, "gle %d\n", GetLastError() );
1429 r
= EmptyClipboard();
1430 ok( r
, "gle %d\n", GetLastError() );
1432 h
= SetClipboardData( CF_TEXT
, htext
);
1433 ok( h
== htext
, "got %p\n", h
);
1434 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1435 h
= SetClipboardData( format_id
, htext2
);
1436 ok( h
== htext2
, "got %p\n", h
);
1437 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1438 bitmap_temp
= CreateBitmap( 10, 10, 1, 1, NULL
);
1439 h
= SetClipboardData( CF_BITMAP
, bitmap_temp
);
1440 ok( h
== bitmap_temp
, "got %p\n", h
);
1441 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1442 h
= SetClipboardData( CF_BITMAP
, bitmap
);
1443 ok( h
== bitmap
, "got %p\n", h
);
1444 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1445 h
= SetClipboardData( CF_DSPBITMAP
, bitmap2
);
1446 ok( h
== bitmap2
, "got %p\n", h
);
1447 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1448 h
= SetClipboardData( CF_PALETTE
, palette
);
1449 ok( h
== palette
, "got %p\n", h
);
1450 ok( GetObjectType( h
) == OBJ_PAL
, "expected palette %p\n", h
);
1451 h
= SetClipboardData( CF_GDIOBJFIRST
+ 3, htext3
);
1452 ok( h
== htext3
, "got %p\n", h
);
1453 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1454 h
= SetClipboardData( CF_PRIVATEFIRST
+ 7, htext5
);
1455 ok( h
== htext5
, "got %p\n", h
);
1456 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1457 h
= SetClipboardData( format_id2
, empty_moveable
);
1458 ok( !h
, "got %p\n", h
);
1459 GlobalFree( empty_moveable
);
1461 if (0) /* crashes on vista64 */
1463 ptr
= HeapAlloc( GetProcessHeap(), 0, 0 );
1464 h
= SetClipboardData( format_id2
, ptr
);
1465 ok( !h
, "got %p\n", h
);
1466 HeapFree( GetProcessHeap(), 0, ptr
);
1469 h
= SetClipboardData( format_id2
, empty_fixed
);
1470 ok( h
== empty_fixed
, "got %p\n", h
);
1471 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1472 h
= SetClipboardData( 0xdeadbeef, hfixed2
);
1473 ok( h
== hfixed2
, "got %p\n", h
);
1474 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1475 h
= SetClipboardData( 0xdeadbabe, hmoveable
);
1476 ok( h
== hmoveable
, "got %p\n", h
);
1477 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1479 ptr
= HeapAlloc( GetProcessHeap(), 0, 37 );
1480 h
= SetClipboardData( 0xdeadfade, ptr
);
1481 ok( h
== ptr
|| !h
, "got %p\n", h
);
1482 if (!h
) /* heap blocks are rejected on >= win8 */
1484 HeapFree( GetProcessHeap(), 0, ptr
);
1488 data
= GetClipboardData( CF_TEXT
);
1489 ok( data
== htext
, "wrong data %p\n", data
);
1490 ok( is_moveable( data
), "expected moveable mem %p\n", data
);
1492 data
= GetClipboardData( format_id
);
1493 ok( data
== htext2
, "wrong data %p, cf %08x\n", data
, format_id
);
1494 ok( is_moveable( data
), "expected moveable mem %p\n", data
);
1496 data
= GetClipboardData( CF_GDIOBJFIRST
+ 3 );
1497 ok( data
== htext3
, "wrong data %p\n", data
);
1498 ok( is_moveable( data
), "expected moveable mem %p\n", data
);
1500 data
= GetClipboardData( CF_PRIVATEFIRST
+ 7 );
1501 ok( data
== htext5
, "wrong data %p\n", data
);
1502 ok( is_moveable( data
), "expected moveable mem %p\n", data
);
1504 data
= GetClipboardData( format_id2
);
1505 ok( data
== empty_fixed
, "wrong data %p\n", data
);
1506 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1508 data
= GetClipboardData( 0xdeadbeef );
1509 ok( data
== hfixed2
, "wrong data %p\n", data
);
1510 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1512 data
= GetClipboardData( 0xdeadbabe );
1513 ok( data
== hmoveable
, "wrong data %p\n", data
);
1514 ok( is_moveable( data
), "expected moveable mem %p\n", data
);
1516 data
= GetClipboardData( 0xdeadfade );
1517 ok( data
== ptr
, "wrong data %p\n", data
);
1519 h
= SetClipboardData( CF_PRIVATEFIRST
+ 7, htext4
);
1520 ok( h
== htext4
, "got %p\n", h
);
1521 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1522 ok( is_freed( htext5
), "expected freed mem %p\n", htext5
);
1524 h
= SetClipboardData( 0xdeadbeef, hfixed
);
1525 ok( h
== hfixed
, "got %p\n", h
);
1526 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1527 if (0) /* this test is unreliable / crashes */
1528 ok( is_freed( hfixed2
), "expected freed mem %p\n", hfixed2
);
1530 r
= CloseClipboard();
1531 ok( r
, "gle %d\n", GetLastError() );
1533 /* data handles are still valid */
1534 ok( is_moveable( htext
), "expected moveable mem %p\n", htext
);
1535 ok( is_moveable( htext2
), "expected moveable mem %p\n", htext2
);
1536 ok( is_moveable( htext3
), "expected moveable mem %p\n", htext3
);
1537 ok( is_moveable( htext4
), "expected moveable mem %p\n", htext4
);
1538 ok( GetObjectType( bitmap
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap
);
1539 ok( GetObjectType( bitmap2
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap2
);
1540 ok( GetObjectType( palette
) == OBJ_PAL
, "expected palette %p\n", palette
);
1541 ok( is_fixed( hfixed
), "expected fixed mem %p\n", hfixed
);
1542 ok( is_moveable( hmoveable
), "expected moveable mem %p\n", hmoveable
);
1543 ok( is_fixed( empty_fixed
), "expected fixed mem %p\n", empty_fixed
);
1545 r
= open_clipboard( hwnd
);
1546 ok( r
, "gle %d\n", GetLastError() );
1548 /* and now they are freed, unless we are the owner */
1551 ok( is_freed( htext
), "expected freed mem %p\n", htext
);
1552 ok( is_freed( htext2
), "expected freed mem %p\n", htext2
);
1553 ok( is_freed( htext3
), "expected freed mem %p\n", htext3
);
1554 ok( is_freed( htext4
), "expected freed mem %p\n", htext4
);
1555 ok( is_freed( hmoveable
), "expected freed mem %p\n", hmoveable
);
1557 data
= GetClipboardData( CF_TEXT
);
1558 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1560 data
= GetClipboardData( format_id
);
1561 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1563 data
= GetClipboardData( CF_GDIOBJFIRST
+ 3 );
1564 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1566 data
= GetClipboardData( CF_PRIVATEFIRST
+ 7 );
1567 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1569 data
= GetClipboardData( format_id2
);
1570 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1571 ok( GlobalSize( data
) == 1, "wrong size %lu\n", GlobalSize( data
));
1573 data
= GetClipboardData( 0xdeadbeef );
1574 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1575 ok( GlobalSize( data
) == 17, "wrong size %lu\n", GlobalSize( data
));
1577 data
= GetClipboardData( 0xdeadbabe );
1578 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1579 ok( GlobalSize( data
) == 23, "wrong size %lu\n", GlobalSize( data
));
1581 data
= GetClipboardData( 0xdeadfade );
1582 ok( is_fixed( data
) || !ptr
, "expected fixed mem %p\n", data
);
1583 if (ptr
) ok( GlobalSize( data
) == 37, "wrong size %lu\n", GlobalSize( data
));
1587 ok( is_moveable( htext
), "expected moveable mem %p\n", htext
);
1588 ok( is_moveable( htext2
), "expected moveable mem %p\n", htext2
);
1589 ok( is_moveable( htext3
), "expected moveable mem %p\n", htext3
);
1590 ok( is_moveable( htext4
), "expected moveable mem %p\n", htext4
);
1591 ok( is_moveable( hmoveable
), "expected moveable mem %p\n", hmoveable
);
1593 data
= GetClipboardData( CF_TEXT
);
1594 ok( data
== htext
, "wrong data %p\n", data
);
1596 data
= GetClipboardData( format_id
);
1597 ok( data
== htext2
, "wrong data %p, cf %08x\n", data
, format_id
);
1599 data
= GetClipboardData( CF_GDIOBJFIRST
+ 3 );
1600 ok( data
== htext3
, "wrong data %p\n", data
);
1602 data
= GetClipboardData( CF_PRIVATEFIRST
+ 7 );
1603 ok( data
== htext4
, "wrong data %p\n", data
);
1605 data
= GetClipboardData( format_id2
);
1606 ok( data
== empty_fixed
, "wrong data %p\n", data
);
1608 data
= GetClipboardData( 0xdeadbeef );
1609 ok( data
== hfixed
, "wrong data %p\n", data
);
1611 data
= GetClipboardData( 0xdeadbabe );
1612 ok( data
== hmoveable
, "wrong data %p\n", data
);
1614 data
= GetClipboardData( 0xdeadfade );
1615 ok( data
== ptr
, "wrong data %p\n", data
);
1618 data
= GetClipboardData( CF_OEMTEXT
);
1619 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1620 data
= GetClipboardData( CF_UNICODETEXT
);
1621 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1622 data
= GetClipboardData( CF_LOCALE
);
1623 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1624 data
= GetClipboardData( CF_BITMAP
);
1625 ok( data
== bitmap
, "expected bitmap %p\n", data
);
1626 data
= GetClipboardData( CF_DSPBITMAP
);
1627 ok( data
== bitmap2
, "expected bitmap %p\n", data
);
1628 data
= GetClipboardData( CF_PALETTE
);
1629 ok( data
== palette
, "expected palette %p\n", data
);
1630 data
= GetClipboardData( CF_DIB
);
1631 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1632 data
= GetClipboardData( CF_DIBV5
);
1633 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1635 ok( GetObjectType( bitmap
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap
);
1636 ok( GetObjectType( bitmap2
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap2
);
1637 ok( GetObjectType( palette
) == OBJ_PAL
, "expected palette %p\n", palette
);
1638 ok( is_fixed( hfixed
), "expected fixed mem %p\n", hfixed
);
1639 ok( is_fixed( empty_fixed
), "expected fixed mem %p\n", empty_fixed
);
1641 r
= EmptyClipboard();
1642 ok( r
, "gle %d\n", GetLastError() );
1644 /* w2003, w2008 don't seem to free the data here */
1645 ok( is_freed( htext
) || broken( !is_freed( htext
)), "expected freed mem %p\n", htext
);
1646 ok( is_freed( htext2
) || broken( !is_freed( htext2
)), "expected freed mem %p\n", htext2
);
1647 ok( is_freed( htext3
) || broken( !is_freed( htext3
)), "expected freed mem %p\n", htext3
);
1648 ok( is_freed( htext4
) || broken( !is_freed( htext4
)), "expected freed mem %p\n", htext4
);
1649 ok( is_freed( hmoveable
) || broken( !is_freed( hmoveable
)), "expected freed mem %p\n", hmoveable
);
1650 ok( is_fixed( empty_fixed
), "expected fixed mem %p\n", empty_fixed
);
1651 ok( is_fixed( hfixed
), "expected fixed mem %p\n", hfixed
);
1653 r
= CloseClipboard();
1654 ok( r
, "gle %d\n", GetLastError() );
1657 static DWORD WINAPI
test_handles_thread( void *arg
)
1659 trace( "running from different thread\n" );
1660 test_handles( (HWND
)arg
);
1664 static DWORD WINAPI
test_handles_thread2( void *arg
)
1670 r
= open_clipboard( 0 );
1671 ok( r
, "gle %d\n", GetLastError() );
1672 h
= GetClipboardData( CF_TEXT
);
1673 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1674 ptr
= GlobalLock( h
);
1675 if (ptr
) ok( !strcmp( "test", ptr
), "wrong data '%.5s'\n", ptr
);
1677 h
= GetClipboardData( format_id
);
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( CF_GDIOBJFIRST
+ 3 );
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 trace( "gdiobj %p\n", h
);
1688 h
= GetClipboardData( CF_PRIVATEFIRST
+ 7 );
1689 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1690 ptr
= GlobalLock( h
);
1691 if (ptr
) ok( !strcmp( "test", ptr
), "wrong data '%.5s'\n", ptr
);
1693 trace( "private %p\n", h
);
1694 h
= GetClipboardData( CF_BITMAP
);
1695 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1696 ok( h
== bitmap
, "different bitmap %p / %p\n", h
, bitmap
);
1697 trace( "bitmap %p\n", h
);
1698 h
= GetClipboardData( CF_DSPBITMAP
);
1699 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1700 ok( h
== bitmap2
, "different bitmap %p / %p\n", h
, bitmap2
);
1701 trace( "bitmap2 %p\n", h
);
1702 h
= GetClipboardData( CF_PALETTE
);
1703 ok( GetObjectType( h
) == OBJ_PAL
, "expected palette %p\n", h
);
1704 ok( h
== palette
, "different palette %p / %p\n", h
, palette
);
1705 trace( "palette %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 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
)
1724 format_id
= RegisterClipboardFormatA( "my_cool_clipboard_format" );
1725 r
= open_clipboard( 0 );
1726 ok( r
, "gle %d\n", GetLastError() );
1727 h
= GetClipboardData( CF_TEXT
);
1728 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1729 ptr
= GlobalLock( h
);
1730 ok( !strcmp( str
, ptr
), "wrong data '%.5s'\n", ptr
);
1732 h
= GetClipboardData( format_id
);
1733 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1734 ptr
= GlobalLock( h
);
1735 if (ptr
) ok( !strcmp( str
, ptr
), "wrong data '%.5s'\n", ptr
);
1737 h
= GetClipboardData( CF_GDIOBJFIRST
+ 3 );
1738 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1739 ptr
= GlobalLock( h
);
1740 ok( !strcmp( str
, ptr
), "wrong data '%.5s'\n", ptr
);
1742 trace( "gdiobj %p\n", h
);
1743 h
= GetClipboardData( CF_PRIVATEFIRST
+ 7 );
1744 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1745 ptr
= GlobalLock( h
);
1746 ok( !strcmp( str
, ptr
), "wrong data '%.5s'\n", ptr
);
1748 trace( "private %p\n", h
);
1749 h
= GetClipboardData( CF_BITMAP
);
1750 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1751 ok( GetObjectW( h
, sizeof(bm
), &bm
) == sizeof(bm
), "GetObject %p failed\n", h
);
1752 ok( bm
.bmWidth
== 13 && bm
.bmHeight
== 17, "wrong bitmap %ux%u\n", bm
.bmWidth
, bm
.bmHeight
);
1753 trace( "bitmap %p\n", h
);
1754 h
= GetClipboardData( CF_DSPBITMAP
);
1755 ok( !GetObjectType( h
), "expected invalid object %p\n", h
);
1756 trace( "bitmap2 %p\n", h
);
1757 h
= GetClipboardData( CF_PALETTE
);
1758 ok( GetObjectType( h
) == OBJ_PAL
, "expected palette %p\n", h
);
1759 ok( GetPaletteEntries( h
, 0, 1, &entry
) == 1, "GetPaletteEntries %p failed\n", h
);
1760 ok( entry
.peRed
== 0x12 && entry
.peGreen
== 0x34 && entry
.peBlue
== 0x56,
1761 "wrong color %02x,%02x,%02x\n", entry
.peRed
, entry
.peGreen
, entry
.peBlue
);
1762 trace( "palette %p\n", h
);
1763 h
= GetClipboardData( CF_METAFILEPICT
);
1764 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1765 ok( GetObjectType( ((METAFILEPICT
*)h
)->hMF
) == OBJ_METAFILE
,
1766 "wrong object %p\n", ((METAFILEPICT
*)h
)->hMF
);
1767 trace( "metafile %p\n", h
);
1768 h
= GetClipboardData( CF_DSPMETAFILEPICT
);
1769 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1770 ok( GetObjectType( ((METAFILEPICT
*)h
)->hMF
) == OBJ_METAFILE
,
1771 "wrong object %p\n", ((METAFILEPICT
*)h
)->hMF
);
1772 trace( "metafile2 %p\n", h
);
1773 h
= GetClipboardData( CF_ENHMETAFILE
);
1774 ok( GetObjectType( h
) == OBJ_ENHMETAFILE
, "expected enhmetafile %p\n", h
);
1775 ok( GetEnhMetaFileBits( h
, sizeof(buffer
), buffer
) > sizeof(ENHMETAHEADER
),
1776 "GetEnhMetaFileBits failed on %p\n", h
);
1777 ok( ((ENHMETAHEADER
*)buffer
)->nRecords
== 3,
1778 "wrong records %u\n", ((ENHMETAHEADER
*)buffer
)->nRecords
);
1779 trace( "enhmetafile %p\n", h
);
1780 h
= GetClipboardData( CF_DSPENHMETAFILE
);
1781 ok( GetObjectType( h
) == OBJ_ENHMETAFILE
, "expected enhmetafile %p\n", h
);
1782 ok( GetEnhMetaFileBits( h
, sizeof(buffer
), buffer
) > sizeof(ENHMETAHEADER
),
1783 "GetEnhMetaFileBits failed on %p\n", h
);
1784 ok( ((ENHMETAHEADER
*)buffer
)->nRecords
== 3,
1785 "wrong records %u\n", ((ENHMETAHEADER
*)buffer
)->nRecords
);
1786 trace( "enhmetafile2 %p\n", h
);
1787 h
= GetClipboardData( CF_DIB
);
1788 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1789 h
= GetClipboardData( CF_DIBV5
);
1790 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1791 r
= CloseClipboard();
1792 ok( r
, "gle %d\n", GetLastError() );
1795 static void test_handles_process_open( const char *str
)
1797 HANDLE h
, text
= GlobalAlloc( GMEM_DDESHARE
|GMEM_MOVEABLE
, strlen(str
) + 1 );
1798 char *ptr
= GlobalLock( text
);
1801 GlobalUnlock( text
);
1803 /* clipboard already open by parent process */
1804 h
= SetClipboardData( CF_TEXT
, text
);
1805 ok( h
== text
, "wrong mem %p / %p\n", h
, text
);
1806 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1809 static void test_handles_process_dib( const char *str
)
1814 r
= open_clipboard( 0 );
1815 ok( r
, "gle %d\n", GetLastError() );
1816 h
= GetClipboardData( CF_BITMAP
);
1817 ok( !GetObjectType( h
), "expected invalid object %p\n", h
);
1818 trace( "dibsection %p\n", h
);
1819 r
= CloseClipboard();
1820 ok( r
, "gle %d\n", GetLastError() );
1823 static void test_data_handles(void)
1828 HWND hwnd
= CreateWindowA( "static", NULL
, WS_POPUP
, 0, 0, 10, 10, 0, 0, 0, NULL
);
1832 ok( hwnd
!= 0, "window creation failed\n" );
1833 format_id
= RegisterClipboardFormatA( "my_cool_clipboard_format" );
1835 test_handles( GetDesktopWindow() );
1836 test_handles( hwnd
);
1837 run_thread( test_handles_thread
, hwnd
, __LINE__
);
1839 bitmap
= CreateBitmap( 13, 17, 1, 1, NULL
);
1840 bitmap2
= CreateBitmap( 10, 10, 1, 1, NULL
);
1841 palette
= CreatePalette( &logpalette
);
1843 r
= open_clipboard( hwnd
);
1844 ok( r
, "gle %d\n", GetLastError() );
1845 r
= EmptyClipboard();
1846 ok( r
, "gle %d\n", GetLastError() );
1847 h
= SetClipboardData( CF_TEXT
, create_textA() );
1848 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1849 h
= SetClipboardData( format_id
, create_textA() );
1850 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1851 h
= SetClipboardData( CF_BITMAP
, bitmap
);
1852 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1853 h
= SetClipboardData( CF_DSPBITMAP
, bitmap2
);
1854 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1855 h
= SetClipboardData( CF_PALETTE
, palette
);
1856 ok( GetObjectType( h
) == OBJ_PAL
, "expected palette %p\n", h
);
1857 h
= SetClipboardData( CF_METAFILEPICT
, create_metafile() );
1858 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1859 trace( "metafile %p\n", h
);
1860 h
= SetClipboardData( CF_DSPMETAFILEPICT
, create_metafile() );
1861 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1862 trace( "metafile2 %p\n", h
);
1863 h
= SetClipboardData( CF_ENHMETAFILE
, create_emf() );
1864 ok( GetObjectType( h
) == OBJ_ENHMETAFILE
, "expected enhmetafile %p\n", h
);
1865 trace( "enhmetafile %p\n", h
);
1866 h
= SetClipboardData( CF_DSPENHMETAFILE
, create_emf() );
1867 ok( GetObjectType( h
) == OBJ_ENHMETAFILE
, "expected enhmetafile %p\n", h
);
1868 trace( "enhmetafile2 %p\n", h
);
1869 h
= SetClipboardData( CF_GDIOBJFIRST
+ 3, create_textA() );
1870 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1871 h
= SetClipboardData( CF_PRIVATEFIRST
+ 7, create_textA() );
1872 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1873 r
= CloseClipboard();
1874 ok( r
, "gle %d\n", GetLastError() );
1876 run_thread( test_handles_thread2
, 0, __LINE__
);
1877 run_process( "handles test" );
1879 r
= open_clipboard( hwnd
);
1880 ok( r
, "gle %d\n", GetLastError() );
1881 h
= GetClipboardData( CF_TEXT
);
1882 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1883 h
= GetClipboardData( format_id
);
1884 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1885 h
= GetClipboardData( CF_GDIOBJFIRST
+ 3 );
1886 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1887 h
= GetClipboardData( CF_PRIVATEFIRST
+ 7 );
1888 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1890 r
= EmptyClipboard();
1891 ok( r
, "gle %d\n", GetLastError() );
1892 text
= create_textA();
1893 h
= SetClipboardData( CF_TEXT
, text
);
1894 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1896 run_process( "handles_open foobar" );
1898 ok( is_moveable( text
), "expected moveable mem %p\n", text
);
1899 h
= GetClipboardData( CF_TEXT
);
1900 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1901 ok( is_moveable( text
), "expected moveable mem %p\n", text
);
1902 ptr
= GlobalLock( h
);
1903 ok( !strcmp( ptr
, "foobar" ), "wrong data '%.8s'\n", ptr
);
1906 r
= EmptyClipboard();
1907 ok( r
, "gle %d\n", GetLastError() );
1908 ok( is_fixed( h
), "expected free mem %p\n", h
);
1909 ok( is_freed( text
) || broken( is_moveable(text
) ), /* w2003, w2008 */
1910 "expected free mem %p\n", text
);
1911 r
= CloseClipboard();
1912 ok( r
, "gle %d\n", GetLastError() );
1914 /* test CF_BITMAP with a DIB section */
1915 memset( &bmi
, 0, sizeof(bmi
) );
1916 bmi
.bmiHeader
.biSize
= sizeof( bmi
.bmiHeader
);
1917 bmi
.bmiHeader
.biWidth
= 29;
1918 bmi
.bmiHeader
.biHeight
= 13;
1919 bmi
.bmiHeader
.biPlanes
= 1;
1920 bmi
.bmiHeader
.biBitCount
= 32;
1921 bitmap
= CreateDIBSection( 0, &bmi
, DIB_RGB_COLORS
, &bits
, 0, 0 );
1923 r
= open_clipboard( hwnd
);
1924 ok( r
, "gle %d\n", GetLastError() );
1925 r
= EmptyClipboard();
1926 ok( r
, "gle %d\n", GetLastError() );
1927 h
= SetClipboardData( CF_BITMAP
, bitmap
);
1928 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1929 trace( "dibsection %p\n", h
);
1930 r
= CloseClipboard();
1931 ok( r
, "gle %d\n", GetLastError() );
1933 run_process( "handles_dib dummy" );
1935 r
= open_clipboard( hwnd
);
1936 ok( r
, "gle %d\n", GetLastError() );
1937 ok( GetObjectType( bitmap
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap
);
1938 r
= EmptyClipboard();
1939 ok( r
, "gle %d\n", GetLastError() );
1940 r
= CloseClipboard();
1941 ok( r
, "gle %d\n", GetLastError() );
1943 DestroyWindow( hwnd
);
1946 static void test_GetUpdatedClipboardFormats(void)
1949 UINT count
, formats
[256];
1951 if (!pGetUpdatedClipboardFormats
)
1953 win_skip( "GetUpdatedClipboardFormats not supported\n" );
1958 r
= pGetUpdatedClipboardFormats( NULL
, 0, &count
);
1959 ok( r
, "gle %d\n", GetLastError() );
1960 ok( !count
, "wrong count %u\n", count
);
1963 r
= pGetUpdatedClipboardFormats( NULL
, 256, &count
);
1964 ok( r
, "gle %d\n", GetLastError() );
1965 ok( !count
, "wrong count %u\n", count
);
1967 SetLastError( 0xdeadbeef );
1968 r
= pGetUpdatedClipboardFormats( formats
, ARRAY_SIZE(formats
), NULL
);
1969 ok( !r
, "succeeded\n" );
1970 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
1973 r
= pGetUpdatedClipboardFormats( formats
, ARRAY_SIZE(formats
), &count
);
1974 ok( r
, "gle %d\n", GetLastError() );
1975 ok( !count
, "wrong count %u\n", count
);
1977 r
= open_clipboard( 0 );
1978 ok( r
, "gle %d\n", GetLastError() );
1979 r
= EmptyClipboard();
1980 ok( r
, "gle %d\n", GetLastError() );
1983 r
= pGetUpdatedClipboardFormats( formats
, ARRAY_SIZE(formats
), &count
);
1984 ok( r
, "gle %d\n", GetLastError() );
1985 ok( !count
, "wrong count %u\n", count
);
1987 SetClipboardData( CF_UNICODETEXT
, 0 );
1990 memset( formats
, 0xcc, sizeof(formats
) );
1991 r
= pGetUpdatedClipboardFormats( formats
, ARRAY_SIZE(formats
), &count
);
1992 ok( r
, "gle %d\n", GetLastError() );
1993 ok( count
== 1, "wrong count %u\n", count
);
1994 ok( formats
[0] == CF_UNICODETEXT
, "wrong format %u\n", formats
[0] );
1995 ok( formats
[1] == 0xcccccccc, "wrong format %u\n", formats
[1] );
1997 SetClipboardData( CF_TEXT
, 0 );
1999 memset( formats
, 0xcc, sizeof(formats
) );
2000 r
= pGetUpdatedClipboardFormats( formats
, ARRAY_SIZE(formats
), &count
);
2001 ok( r
, "gle %d\n", GetLastError() );
2002 ok( count
== 2, "wrong count %u\n", count
);
2003 ok( formats
[0] == CF_UNICODETEXT
, "wrong format %u\n", formats
[0] );
2004 ok( formats
[1] == CF_TEXT
, "wrong format %u\n", formats
[1] );
2005 ok( formats
[2] == 0xcccccccc, "wrong format %u\n", formats
[2] );
2007 SetLastError( 0xdeadbeef );
2009 r
= pGetUpdatedClipboardFormats( formats
, 0, &count
);
2010 ok( !r
, "succeeded\n" );
2011 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "wrong error %u\n", GetLastError() );
2012 ok( count
== 2, "wrong count %u\n", count
);
2014 SetLastError( 0xdeadbeef );
2016 r
= pGetUpdatedClipboardFormats( formats
, 1, &count
);
2017 ok( !r
, "succeeded\n" );
2018 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "wrong error %u\n", GetLastError() );
2019 ok( count
== 2, "wrong count %u\n", count
);
2021 r
= CloseClipboard();
2022 ok( r
, "gle %d\n", GetLastError() );
2025 memset( formats
, 0xcc, sizeof(formats
) );
2026 r
= pGetUpdatedClipboardFormats( formats
, ARRAY_SIZE(formats
), &count
);
2027 ok( r
, "gle %d\n", GetLastError() );
2028 ok( count
== 4, "wrong count %u\n", count
);
2029 ok( formats
[0] == CF_UNICODETEXT
, "wrong format %u\n", formats
[0] );
2030 ok( formats
[1] == CF_TEXT
, "wrong format %u\n", formats
[1] );
2031 ok( formats
[2] == CF_LOCALE
, "wrong format %u\n", formats
[2] );
2032 ok( formats
[3] == CF_OEMTEXT
, "wrong format %u\n", formats
[3] );
2033 ok( formats
[4] == 0xcccccccc, "wrong format %u\n", formats
[4] );
2036 memset( formats
, 0xcc, sizeof(formats
) );
2037 r
= pGetUpdatedClipboardFormats( formats
, 2, &count
);
2038 ok( !r
, "gle %d\n", GetLastError() );
2039 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "wrong error %u\n", GetLastError() );
2040 ok( count
== 4, "wrong count %u\n", count
);
2041 ok( formats
[0] == 0xcccccccc, "wrong format %u\n", formats
[0] );
2044 r
= pGetUpdatedClipboardFormats( NULL
, 256, &count
);
2045 ok( !r
, "gle %d\n", GetLastError() );
2046 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
2047 ok( count
== 4, "wrong count %u\n", count
);
2050 r
= pGetUpdatedClipboardFormats( NULL
, 256, &count
);
2051 ok( !r
, "gle %d\n", GetLastError() );
2052 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
2053 ok( count
== 4, "wrong count %u\n", count
);
2063 { "foo", {}, 3 }, /* 0 */
2065 { "foo\0bar", {}, 7 },
2066 { "foo\0bar", {}, 8 },
2067 { "", {'f','o','o'}, 3 * sizeof(WCHAR
) },
2068 { "", {'f','o','o',0}, 4 * sizeof(WCHAR
) }, /* 5 */
2069 { "", {'f','o','o',0,'b','a','r'}, 7 * sizeof(WCHAR
) },
2070 { "", {'f','o','o',0,'b','a','r',0}, 8 * sizeof(WCHAR
) },
2071 { "", {'f','o','o'}, 1 },
2072 { "", {'f','o','o'}, 2 },
2073 { "", {'f','o','o'}, 5 }, /* 10 */
2074 { "", {'f','o','o',0}, 7 },
2075 { "", {'f','o','o',0}, 9 },
2078 static void test_string_data(void)
2087 for (i
= 0; i
< ARRAY_SIZE(test_data
); i
++)
2089 /* 1-byte Unicode strings crash on Win64 */
2091 if (!test_data
[i
].strA
[0] && test_data
[i
].len
< sizeof(WCHAR
)) continue;
2093 winetest_push_context("%d", i
);
2094 r
= open_clipboard( 0 );
2095 ok( r
, "gle %d\n", GetLastError() );
2096 r
= EmptyClipboard();
2097 ok( r
, "gle %d\n", GetLastError() );
2098 data
= GlobalAlloc( GMEM_FIXED
, test_data
[i
].len
);
2099 if (test_data
[i
].strA
[0])
2101 memcpy( data
, test_data
[i
].strA
, test_data
[i
].len
);
2102 SetClipboardData( CF_TEXT
, data
);
2103 memcpy( bufferA
, test_data
[i
].strA
, test_data
[i
].len
);
2104 bufferA
[test_data
[i
].len
- 1] = 0;
2105 ok( !memcmp( data
, bufferA
, test_data
[i
].len
),
2106 "wrong data %.*s\n", test_data
[i
].len
, (char *)data
);
2110 memcpy( data
, test_data
[i
].strW
, test_data
[i
].len
);
2111 SetClipboardData( CF_UNICODETEXT
, data
);
2112 memcpy( bufferW
, test_data
[i
].strW
, test_data
[i
].len
);
2113 bufferW
[(test_data
[i
].len
+ 1) / sizeof(WCHAR
) - 1] = 0;
2114 ok( !memcmp( data
, bufferW
, test_data
[i
].len
),
2115 "wrong data %s\n", wine_dbgstr_wn( data
, (test_data
[i
].len
+ 1) / sizeof(WCHAR
) ));
2117 r
= CloseClipboard();
2118 ok( r
, "gle %d\n", GetLastError() );
2119 sprintf( cmd
, "string_data %u", i
);
2121 winetest_pop_context();
2125 static void test_string_data_process( int i
)
2133 winetest_push_context("%d", i
);
2134 r
= open_clipboard( 0 );
2135 ok( r
, "gle %d\n", GetLastError() );
2136 if (test_data
[i
].strA
[0])
2138 data
= GetClipboardData( CF_TEXT
);
2139 ok( data
!= 0, "could not get data\n" );
2140 len
= GlobalSize( data
);
2141 ok( len
== test_data
[i
].len
, "wrong size %u / %u\n", len
, test_data
[i
].len
);
2142 memcpy( bufferA
, test_data
[i
].strA
, test_data
[i
].len
);
2143 bufferA
[test_data
[i
].len
- 1] = 0;
2144 ok( !memcmp( data
, bufferA
, len
), "wrong data %.*s\n", len
, (char *)data
);
2145 data
= GetClipboardData( CF_UNICODETEXT
);
2146 ok( data
!= 0, "could not get data\n" );
2147 len
= GlobalSize( data
);
2148 len2
= MultiByteToWideChar( CP_ACP
, 0, bufferA
, test_data
[i
].len
, bufferW
, ARRAY_SIZE(bufferW
) );
2149 ok( len
== len2
* sizeof(WCHAR
), "wrong size %u / %u\n", len
, len2
);
2150 ok( !memcmp( data
, bufferW
, len
), "wrong data %s\n", wine_dbgstr_wn( data
, len2
));
2154 data
= GetClipboardData( CF_UNICODETEXT
);
2155 ok( data
!= 0, "could not get data\n" );
2156 len
= GlobalSize( data
);
2157 ok( len
== test_data
[i
].len
, "wrong size %u / %u\n", len
, test_data
[i
].len
);
2158 memcpy( bufferW
, test_data
[i
].strW
, test_data
[i
].len
);
2159 bufferW
[(test_data
[i
].len
+ 1) / sizeof(WCHAR
) - 1] = 0;
2160 ok( !memcmp( data
, bufferW
, len
),
2161 "wrong data %s\n", wine_dbgstr_wn( data
, (len
+ 1) / sizeof(WCHAR
) ));
2162 data
= GetClipboardData( CF_TEXT
);
2163 if (test_data
[i
].len
>= sizeof(WCHAR
))
2165 ok( data
!= 0, "could not get data\n" );
2166 len
= GlobalSize( data
);
2167 len2
= WideCharToMultiByte( CP_ACP
, 0, bufferW
, test_data
[i
].len
/ sizeof(WCHAR
),
2168 bufferA
, ARRAY_SIZE(bufferA
), NULL
, NULL
);
2169 bufferA
[len2
- 1] = 0;
2170 ok( len
== len2
, "wrong size %u / %u\n", len
, len2
);
2171 ok( !memcmp( data
, bufferA
, len
), "wrong data %.*s\n", len
, (char *)data
);
2175 ok( !data
, "got data for empty string\n" );
2176 ok( IsClipboardFormatAvailable( CF_TEXT
), "text not available\n" );
2179 r
= CloseClipboard();
2180 ok( r
, "gle %d\n", GetLastError() );
2181 winetest_pop_context();
2184 START_TEST(clipboard
)
2187 int argc
= winetest_get_mainargs( &argv
);
2188 HMODULE mod
= GetModuleHandleA( "user32" );
2191 pAddClipboardFormatListener
= (void *)GetProcAddress( mod
, "AddClipboardFormatListener" );
2192 pRemoveClipboardFormatListener
= (void *)GetProcAddress( mod
, "RemoveClipboardFormatListener" );
2193 pGetUpdatedClipboardFormats
= (void *)GetProcAddress( mod
, "GetUpdatedClipboardFormats" );
2195 if (argc
== 4 && !strcmp( argv
[2], "set_clipboard_data" ))
2197 set_clipboard_data_process( atoi( argv
[3] ));
2200 if (argc
== 4 && !strcmp( argv
[2], "grab_clipboard" ))
2202 grab_clipboard_process( atoi( argv
[3] ));
2205 if (argc
== 4 && !strcmp( argv
[2], "handles" ))
2207 test_handles_process( argv
[3] );
2210 if (argc
== 4 && !strcmp( argv
[2], "handles_open" ))
2212 test_handles_process_open( argv
[3] );
2215 if (argc
== 4 && !strcmp( argv
[2], "handles_dib" ))
2217 test_handles_process_dib( argv
[3] );
2220 if (argc
== 4 && !strcmp( argv
[2], "string_data" ))
2222 test_string_data_process( atoi( argv
[3] ));
2225 if (argc
== 3 && !strcmp( argv
[2], "get_clipboard_data" ))
2227 get_clipboard_data_process( );
2231 test_RegisterClipboardFormatA();
2232 test_ClipboardOwner();
2235 test_data_handles();
2236 test_GetUpdatedClipboardFormats();