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"
28 static BOOL (WINAPI
*pAddClipboardFormatListener
)(HWND hwnd
);
29 static BOOL (WINAPI
*pRemoveClipboardFormatListener
)(HWND hwnd
);
30 static DWORD (WINAPI
*pGetClipboardSequenceNumber
)(void);
32 static const BOOL is_win64
= sizeof(void *) > sizeof(int);
33 static int thread_from_line
;
36 static DWORD WINAPI
open_clipboard_thread(LPVOID arg
)
39 ok(OpenClipboard(hWnd
), "%u: OpenClipboard failed\n", thread_from_line
);
43 static DWORD WINAPI
empty_clipboard_thread(LPVOID arg
)
45 SetLastError( 0xdeadbeef );
46 ok(!EmptyClipboard(), "%u: EmptyClipboard succeeded\n", thread_from_line
);
47 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "%u: wrong error %u\n",
48 thread_from_line
, GetLastError());
52 static DWORD WINAPI
open_and_empty_clipboard_thread(LPVOID arg
)
55 ok(OpenClipboard(hWnd
), "%u: OpenClipboard failed\n", thread_from_line
);
56 ok(EmptyClipboard(), "%u: EmptyClipboard failed\n", thread_from_line
);
60 static DWORD WINAPI
set_clipboard_data_thread(LPVOID arg
)
65 SetLastError( 0xdeadbeef );
66 if (GetClipboardOwner() == hwnd
)
68 SetClipboardData( CF_WAVE
, 0 );
69 ok( IsClipboardFormatAvailable( CF_WAVE
), "%u: SetClipboardData failed\n", thread_from_line
);
70 ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
71 ok( ret
!= 0, "%u: SetClipboardData failed err %u\n", thread_from_line
, GetLastError() );
72 SetLastError( 0xdeadbeef );
73 ret
= GetClipboardData( CF_WAVE
);
74 ok( !ret
, "%u: GetClipboardData succeeded\n", thread_from_line
);
75 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "%u: wrong error %u\n",
76 thread_from_line
, GetLastError());
80 SetClipboardData( CF_WAVE
, 0 );
81 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "%u: wrong error %u\n",
82 thread_from_line
, GetLastError());
83 ok( !IsClipboardFormatAvailable( CF_WAVE
), "%u: SetClipboardData succeeded\n", thread_from_line
);
84 ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
85 ok( !ret
, "%u: SetClipboardData succeeded\n", thread_from_line
);
86 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "%u: wrong error %u\n",
87 thread_from_line
, GetLastError());
92 static void set_clipboard_data_process( int arg
)
96 SetLastError( 0xdeadbeef );
99 todo_wine_if( arg
== 1 || arg
== 3 )
100 ok( IsClipboardFormatAvailable( CF_WAVE
), "process %u: CF_WAVE not available\n", arg
);
101 ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
102 ok( ret
!= 0, "process %u: SetClipboardData failed err %u\n", arg
, GetLastError() );
106 SetClipboardData( CF_WAVE
, 0 );
107 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "process %u: wrong error %u\n",
108 arg
, GetLastError());
109 ok( !IsClipboardFormatAvailable( CF_WAVE
), "process %u: SetClipboardData succeeded\n", arg
);
110 ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
111 ok( !ret
, "process %u: SetClipboardData succeeded\n", arg
);
112 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "process %u: wrong error %u\n",
113 arg
, GetLastError());
117 static void grab_clipboard_process( int arg
)
121 SetLastError( 0xdeadbeef );
122 ret
= OpenClipboard( 0 );
123 ok( ret
, "OpenClipboard failed\n" );
124 ret
= EmptyClipboard();
125 ok( ret
, "EmptyClipboard failed\n" );
128 HANDLE ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
129 ok( ret
!= 0, "process %u: SetClipboardData failed err %u\n", arg
, GetLastError() );
133 static void run_thread( LPTHREAD_START_ROUTINE func
, void *arg
, int line
)
138 thread_from_line
= line
;
139 thread
= CreateThread(NULL
, 0, func
, arg
, 0, NULL
);
140 ok(thread
!= NULL
, "%u: CreateThread failed with error %d\n", line
, GetLastError());
143 ret
= MsgWaitForMultipleObjectsEx( 1, &thread
, 1000, QS_ALLINPUT
, 0 );
144 if (ret
== WAIT_OBJECT_0
+ 1)
147 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
151 ok(ret
== WAIT_OBJECT_0
, "%u: expected WAIT_OBJECT_0, got %u\n", line
, ret
);
155 static void run_process( const char *args
)
158 PROCESS_INFORMATION info
;
159 STARTUPINFOA startup
;
161 sprintf( cmd
, "%s clipboard %s", argv0
, args
);
162 memset( &startup
, 0, sizeof(startup
) );
163 startup
.cb
= sizeof(startup
);
164 ok( CreateProcessA( NULL
, cmd
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &startup
, &info
),
165 "CreateProcess %s failed\n", cmd
);
167 winetest_wait_child_process( info
.hProcess
);
168 CloseHandle( info
.hProcess
);
169 CloseHandle( info
.hThread
);
172 static WNDPROC old_proc
;
173 static LRESULT CALLBACK
winproc_wrapper( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
175 static int destroyed
;
177 if (msg
== WM_DESTROY
) destroyed
= TRUE
;
179 trace( "%p msg %04x\n", hwnd
, msg
);
181 ok( GetClipboardOwner() == hwnd
, "%04x: wrong owner %p/%p\n", msg
, GetClipboardOwner(), hwnd
);
182 else todo_wine_if (msg
== WM_DESTROY
)
183 ok( !GetClipboardOwner(), "%04x: wrong owner %p\n", msg
, GetClipboardOwner() );
184 ok( GetClipboardViewer() == hwnd
, "%04x: wrong viewer %p/%p\n", msg
, GetClipboardViewer(), hwnd
);
185 ok( GetOpenClipboardWindow() == hwnd
, "%04x: wrong open win %p/%p\n",
186 msg
, GetOpenClipboardWindow(), hwnd
);
187 return old_proc( hwnd
, msg
, wp
, lp
);
190 static void test_ClipboardOwner(void)
195 SetLastError(0xdeadbeef);
196 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef,
197 "could not perform clipboard test: clipboard already owned\n");
199 hWnd1
= CreateWindowExA(0, "static", NULL
, WS_POPUP
,
200 0, 0, 10, 10, 0, 0, 0, NULL
);
201 ok(hWnd1
!= 0, "CreateWindowExA error %d\n", GetLastError());
202 trace("hWnd1 = %p\n", hWnd1
);
204 hWnd2
= CreateWindowExA(0, "static", NULL
, WS_POPUP
,
205 0, 0, 10, 10, 0, 0, 0, NULL
);
206 ok(hWnd2
!= 0, "CreateWindowExA error %d\n", GetLastError());
207 trace("hWnd2 = %p\n", hWnd2
);
209 SetLastError(0xdeadbeef);
210 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
211 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
|| broken(GetLastError() == 0xdeadbeef), /* wow64 */
212 "wrong error %u\n", GetLastError());
214 ok(OpenClipboard(0), "OpenClipboard failed\n");
215 ok(!GetClipboardOwner(), "clipboard should still be not owned\n");
216 ok(!OpenClipboard(hWnd1
), "OpenClipboard should fail since clipboard already opened\n");
217 ok(OpenClipboard(0), "OpenClipboard again failed\n");
218 ret
= CloseClipboard();
219 ok( ret
, "CloseClipboard error %d\n", GetLastError());
221 ok(OpenClipboard(hWnd1
), "OpenClipboard failed\n");
222 run_thread( open_clipboard_thread
, hWnd1
, __LINE__
);
223 run_thread( empty_clipboard_thread
, 0, __LINE__
);
224 run_thread( set_clipboard_data_thread
, hWnd1
, __LINE__
);
225 ok( !IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE available\n" );
226 ok( !GetClipboardData( CF_WAVE
), "CF_WAVE data available\n" );
227 run_process( "set_clipboard_data 0" );
228 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
229 ok(OpenClipboard(hWnd1
), "OpenClipboard failed\n");
231 SetLastError(0xdeadbeef);
232 ret
= OpenClipboard(hWnd2
);
233 ok(!ret
&& (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED
),
234 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
236 SetLastError(0xdeadbeef);
237 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should still be not owned\n");
238 ret
= EmptyClipboard();
239 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
240 ok(GetClipboardOwner() == hWnd1
, "clipboard should be owned by %p, not by %p\n", hWnd1
, GetClipboardOwner());
241 run_thread( empty_clipboard_thread
, 0, __LINE__
);
242 run_thread( set_clipboard_data_thread
, hWnd1
, __LINE__
);
243 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
244 ok( GetClipboardData( CF_WAVE
) != 0, "CF_WAVE data not available\n" );
245 run_process( "set_clipboard_data 1" );
247 SetLastError(0xdeadbeef);
248 ret
= OpenClipboard(hWnd2
);
249 ok(!ret
&& (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED
),
250 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
252 ret
= CloseClipboard();
253 ok( ret
, "CloseClipboard error %d\n", GetLastError());
254 ok(GetClipboardOwner() == hWnd1
, "clipboard should still be owned\n");
256 /* any window will do, even from a different process */
257 ret
= OpenClipboard( GetDesktopWindow() );
258 ok( ret
, "OpenClipboard error %d\n", GetLastError());
259 ret
= EmptyClipboard();
260 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
261 ok( GetClipboardOwner() == GetDesktopWindow(), "wrong owner %p/%p\n",
262 GetClipboardOwner(), GetDesktopWindow() );
263 run_thread( set_clipboard_data_thread
, GetDesktopWindow(), __LINE__
);
264 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
265 ok( GetClipboardData( CF_WAVE
) != 0, "CF_WAVE data not available\n" );
266 run_process( "set_clipboard_data 2" );
267 ret
= CloseClipboard();
268 ok( ret
, "CloseClipboard error %d\n", GetLastError());
270 ret
= OpenClipboard( hWnd1
);
271 ok( ret
, "OpenClipboard error %d\n", GetLastError());
272 ret
= EmptyClipboard();
273 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
274 SetClipboardViewer( hWnd1
);
275 ok( GetClipboardOwner() == hWnd1
, "wrong owner %p/%p\n", GetClipboardOwner(), hWnd1
);
276 ok( GetClipboardViewer() == hWnd1
, "wrong viewer %p/%p\n", GetClipboardViewer(), hWnd1
);
277 ok( GetOpenClipboardWindow() == hWnd1
, "wrong open win %p/%p\n", GetOpenClipboardWindow(), hWnd1
);
279 old_proc
= (WNDPROC
)SetWindowLongPtrA( hWnd1
, GWLP_WNDPROC
, (LONG_PTR
)winproc_wrapper
);
280 ret
= DestroyWindow(hWnd1
);
281 ok( ret
, "DestroyWindow error %d\n", GetLastError());
282 ret
= DestroyWindow(hWnd2
);
283 ok( ret
, "DestroyWindow error %d\n", GetLastError());
284 SetLastError(0xdeadbeef);
285 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should not be owned\n");
286 ok(!GetClipboardViewer() && GetLastError() == 0xdeadbeef, "viewer still exists\n");
287 ok(!GetOpenClipboardWindow() && GetLastError() == 0xdeadbeef, "clipboard should not be open\n");
289 SetLastError( 0xdeadbeef );
290 ret
= CloseClipboard();
291 ok( !ret
, "CloseClipboard succeeded\n" );
292 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "wrong error %u\n", GetLastError() );
294 ret
= OpenClipboard( 0 );
295 ok( ret
, "OpenClipboard error %d\n", GetLastError());
296 run_thread( set_clipboard_data_thread
, 0, __LINE__
);
297 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
298 ok( GetClipboardData( CF_WAVE
) != 0, "CF_WAVE data not available\n" );
299 run_process( "set_clipboard_data 3" );
300 ret
= CloseClipboard();
301 ok( ret
, "CloseClipboard error %d\n", GetLastError());
303 run_thread( open_and_empty_clipboard_thread
, 0, __LINE__
);
305 ret
= OpenClipboard( 0 );
306 ok( ret
, "OpenClipboard error %d\n", GetLastError());
307 run_thread( set_clipboard_data_thread
, 0, __LINE__
);
308 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
309 ok( GetClipboardData( CF_WAVE
) != 0, "CF_WAVE data not available\n" );
310 run_process( "set_clipboard_data 4" );
311 ret
= EmptyClipboard();
312 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
313 ret
= CloseClipboard();
314 ok( ret
, "CloseClipboard error %d\n", GetLastError());
316 SetLastError( 0xdeadbeef );
317 ok( !SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 )),
318 "SetClipboardData succeeded\n" );
319 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "wrong error %u\n", GetLastError() );
320 ok( !IsClipboardFormatAvailable( CF_WAVE
), "SetClipboardData succeeded\n" );
324 static void test_RegisterClipboardFormatA(void)
327 UINT format_id
, format_id2
;
333 format_id
= RegisterClipboardFormatA("my_cool_clipboard_format");
334 ok(format_id
> 0xc000 && format_id
< 0xffff, "invalid clipboard format id %04x\n", format_id
);
336 format_id2
= RegisterClipboardFormatA("MY_COOL_CLIPBOARD_FORMAT");
337 ok(format_id2
== format_id
, "invalid clipboard format id %04x\n", format_id2
);
339 len
= GetClipboardFormatNameA(format_id
, buf
, 256);
340 ok(len
== lstrlenA("my_cool_clipboard_format"), "wrong format name length %d\n", len
);
341 ok(!lstrcmpA(buf
, "my_cool_clipboard_format"), "wrong format name \"%s\"\n", buf
);
343 lstrcpyA(buf
, "foo");
344 SetLastError(0xdeadbeef);
345 len
= GetAtomNameA((ATOM
)format_id
, buf
, 256);
346 ok(len
== 0, "GetAtomNameA should fail\n");
347 ok(GetLastError() == ERROR_INVALID_HANDLE
, "err %d\n", GetLastError());
351 lstrcpyA(buf
, "foo");
352 SetLastError(0xdeadbeef);
353 len
= GlobalGetAtomNameA((ATOM
)format_id
, buf
, 256);
354 ok(len
== 0, "GlobalGetAtomNameA should fail\n");
355 ok(GetLastError() == ERROR_INVALID_HANDLE
, "err %d\n", GetLastError());
358 SetLastError(0xdeadbeef);
359 atom_id
= FindAtomA("my_cool_clipboard_format");
360 ok(atom_id
== 0, "FindAtomA should fail\n");
361 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "err %d\n", GetLastError());
365 /* this relies on the clipboard and global atom table being different */
366 SetLastError(0xdeadbeef);
367 atom_id
= GlobalFindAtomA("my_cool_clipboard_format");
368 ok(atom_id
== 0, "GlobalFindAtomA should fail\n");
369 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "err %d\n", GetLastError());
372 for (format_id
= 0; format_id
< 0xffff; format_id
++)
374 SetLastError(0xdeadbeef);
375 len
= GetClipboardFormatNameA(format_id
, buf
, 256);
377 if (format_id
< 0xc000)
378 ok(!len
, "GetClipboardFormatNameA should fail, but it returned %d (%s)\n", len
, buf
);
379 else if (len
&& winetest_debug
> 1)
380 trace("%04x: %s\n", format_id
, len
? buf
: "");
383 ret
= OpenClipboard(0);
384 ok( ret
, "OpenClipboard error %d\n", GetLastError());
386 /* try some invalid/unregistered formats */
387 SetLastError( 0xdeadbeef );
388 handle
= SetClipboardData( 0, GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, 1 ));
389 ok( !handle
, "SetClipboardData succeeded\n" );
390 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "wrong error %u\n", GetLastError());
391 handle
= SetClipboardData( 0x1234, GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, 1 ));
392 ok( handle
!= 0, "SetClipboardData failed err %d\n", GetLastError());
393 handle
= SetClipboardData( 0x123456, GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, 1 ));
394 ok( handle
!= 0, "SetClipboardData failed err %d\n", GetLastError());
395 handle
= SetClipboardData( 0xffff8765, GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, 1 ));
396 ok( handle
!= 0, "SetClipboardData failed err %d\n", GetLastError());
398 ok( IsClipboardFormatAvailable( 0x1234 ), "format missing\n" );
399 ok( IsClipboardFormatAvailable( 0x123456 ), "format missing\n" );
400 ok( IsClipboardFormatAvailable( 0xffff8765 ), "format missing\n" );
401 ok( !IsClipboardFormatAvailable( 0 ), "format available\n" );
402 ok( !IsClipboardFormatAvailable( 0x3456 ), "format available\n" );
403 ok( !IsClipboardFormatAvailable( 0x8765 ), "format available\n" );
405 trace("# of formats available: %d\n", CountClipboardFormats());
408 while ((format_id
= EnumClipboardFormats(format_id
)))
410 ok(IsClipboardFormatAvailable(format_id
), "format %04x was listed as available\n", format_id
);
411 len
= GetClipboardFormatNameA(format_id
, buf
, 256);
412 trace("%04x: %s\n", format_id
, len
? buf
: "");
415 ret
= EmptyClipboard();
416 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
417 ret
=CloseClipboard();
418 ok( ret
, "CloseClipboard error %d\n", GetLastError());
420 if (CountClipboardFormats())
422 SetLastError(0xdeadbeef);
423 ok(!EnumClipboardFormats(0), "EnumClipboardFormats should fail if clipboard wasn't open\n");
424 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
,
425 "Last error should be set to ERROR_CLIPBOARD_NOT_OPEN, not %d\n", GetLastError());
428 SetLastError(0xdeadbeef);
429 ok(!EmptyClipboard(), "EmptyClipboard should fail if clipboard wasn't open\n");
430 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
|| broken(GetLastError() == 0xdeadbeef), /* wow64 */
431 "Wrong error %u\n", GetLastError());
433 format_id
= RegisterClipboardFormatA("#1234");
434 ok(format_id
== 1234, "invalid clipboard format id %04x\n", format_id
);
437 static HGLOBAL
create_text(void)
439 HGLOBAL h
= GlobalAlloc(GMEM_DDESHARE
|GMEM_MOVEABLE
, 5);
440 char *p
= GlobalLock(h
);
446 static HENHMETAFILE
create_emf(void)
448 const RECT rect
= {0, 0, 100, 100};
449 HDC hdc
= CreateEnhMetaFileA(NULL
, NULL
, &rect
, "HENHMETAFILE Ole Clipboard Test\0Test\0\0");
450 ExtTextOutA(hdc
, 0, 0, ETO_OPAQUE
, &rect
, "Test String", strlen("Test String"), NULL
);
451 return CloseEnhMetaFile(hdc
);
454 static void test_synthesized(void)
462 htext
= create_text();
465 r
= OpenClipboard(NULL
);
466 ok(r
, "gle %d\n", GetLastError());
467 r
= EmptyClipboard();
468 ok(r
, "gle %d\n", GetLastError());
469 h
= SetClipboardData(CF_TEXT
, htext
);
470 ok(h
== htext
, "got %p\n", h
);
471 h
= SetClipboardData(CF_ENHMETAFILE
, emf
);
472 ok(h
== emf
, "got %p\n", h
);
473 r
= CloseClipboard();
474 ok(r
, "gle %d\n", GetLastError());
476 r
= OpenClipboard(NULL
);
477 ok(r
, "gle %d\n", GetLastError());
478 cf
= EnumClipboardFormats(0);
479 ok(cf
== CF_TEXT
, "cf %08x\n", cf
);
480 data
= GetClipboardData(cf
);
481 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
483 cf
= EnumClipboardFormats(cf
);
484 ok(cf
== CF_ENHMETAFILE
, "cf %08x\n", cf
);
485 data
= GetClipboardData(cf
);
486 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
488 cf
= EnumClipboardFormats(cf
);
489 todo_wine
ok(cf
== CF_LOCALE
, "cf %08x\n", cf
);
491 cf
= EnumClipboardFormats(cf
);
492 ok(cf
== CF_OEMTEXT
, "cf %08x\n", cf
);
493 data
= GetClipboardData(cf
);
494 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
496 cf
= EnumClipboardFormats(cf
);
497 ok(cf
== CF_UNICODETEXT
, "cf %08x\n", cf
);
499 cf
= EnumClipboardFormats(cf
);
500 ok(cf
== CF_METAFILEPICT
, "cf %08x\n", cf
);
501 data
= GetClipboardData(cf
);
502 todo_wine
ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
504 cf
= EnumClipboardFormats(cf
);
505 ok(cf
== 0, "cf %08x\n", cf
);
507 r
= EmptyClipboard();
508 ok(r
, "gle %d\n", GetLastError());
510 r
= CloseClipboard();
511 ok(r
, "gle %d\n", GetLastError());
514 static CRITICAL_SECTION clipboard_cs
;
515 static HWND next_wnd
;
516 static LRESULT CALLBACK
clipboard_wnd_proc(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
518 static UINT wm_drawclipboard
;
519 static UINT wm_clipboardupdate
;
520 static UINT wm_destroyclipboard
;
521 static UINT nb_formats
;
525 case WM_DRAWCLIPBOARD
:
526 EnterCriticalSection(&clipboard_cs
);
528 LeaveCriticalSection(&clipboard_cs
);
530 case WM_CHANGECBCHAIN
:
531 if (next_wnd
== (HWND
)wp
)
534 SendMessageA(next_wnd
, msg
, wp
, lp
);
536 case WM_DESTROYCLIPBOARD
:
537 wm_destroyclipboard
++;
538 ok( GetClipboardOwner() == hwnd
, "WM_DESTROYCLIPBOARD owner %p\n", GetClipboardOwner() );
539 nb_formats
= CountClipboardFormats();
541 case WM_CLIPBOARDUPDATE
:
542 wm_clipboardupdate
++;
545 ChangeClipboardChain(hwnd
, next_wnd
);
549 ret
= wm_drawclipboard
;
550 wm_drawclipboard
= 0;
553 ret
= wm_clipboardupdate
;
554 wm_clipboardupdate
= 0;
557 ret
= wm_destroyclipboard
;
558 wm_destroyclipboard
= 0;
564 return DefWindowProcA(hwnd
, msg
, wp
, lp
);
567 static DWORD WINAPI
clipboard_thread(void *param
)
569 HWND ret
, win
= param
;
572 UINT count
, formats
, old_seq
= 0, seq
;
574 if (pGetClipboardSequenceNumber
) old_seq
= pGetClipboardSequenceNumber();
576 EnterCriticalSection(&clipboard_cs
);
577 SetLastError(0xdeadbeef);
578 next_wnd
= SetClipboardViewer(win
);
579 ok(GetLastError() == 0xdeadbeef, "GetLastError = %d\n", GetLastError());
580 LeaveCriticalSection(&clipboard_cs
);
582 SetLastError( 0xdeadbeef );
583 ret
= SetClipboardViewer( (HWND
)0xdead );
584 ok( !ret
, "SetClipboardViewer succeeded\n" );
585 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %u\n", GetLastError() );
586 SetLastError( 0xdeadbeef );
587 r
= ChangeClipboardChain( win
, (HWND
)0xdead );
588 ok( !r
, "ChangeClipboardChain succeeded\n" );
589 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %u\n", GetLastError() );
590 SetLastError( 0xdeadbeef );
591 r
= ChangeClipboardChain( (HWND
)0xdead, next_wnd
);
592 ok( !r
, "ChangeClipboardChain succeeded\n" );
593 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %u\n", GetLastError() );
595 if (pAddClipboardFormatListener
)
597 r
= pAddClipboardFormatListener(win
);
598 ok( r
, "AddClipboardFormatListener failed err %d\n", GetLastError());
599 SetLastError( 0xdeadbeef );
600 r
= pAddClipboardFormatListener( win
);
601 todo_wine
ok( !r
, "AddClipboardFormatListener succeeded\n" );
602 todo_wine
ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
603 SetLastError( 0xdeadbeef );
604 r
= pAddClipboardFormatListener( (HWND
)0xdead );
605 todo_wine
ok( !r
, "AddClipboardFormatListener succeeded\n" );
606 todo_wine
ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %u\n", GetLastError() );
607 r
= pAddClipboardFormatListener( GetDesktopWindow() );
608 ok( r
, "AddClipboardFormatListener failed err %d\n", GetLastError());
609 r
= pRemoveClipboardFormatListener( GetDesktopWindow() );
610 ok( r
, "RemoveClipboardFormatListener failed err %d\n", GetLastError());
613 if (pGetClipboardSequenceNumber
)
615 seq
= pGetClipboardSequenceNumber();
616 ok( seq
== old_seq
, "sequence changed\n" );
618 count
= SendMessageA( win
, WM_USER
+ 1, 0, 0 );
619 ok( count
, "WM_DRAWCLIPBOARD received\n" );
620 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
621 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
623 SetLastError( 0xdeadbeef );
624 r
= OpenClipboard( (HWND
)0xdead );
625 ok( !r
, "OpenClipboard succeeded\n" );
626 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %u\n", GetLastError() );
628 r
= OpenClipboard(win
);
629 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
631 if (pGetClipboardSequenceNumber
)
633 seq
= pGetClipboardSequenceNumber();
634 ok( seq
== old_seq
, "sequence changed\n" );
636 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
637 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
638 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
639 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
641 r
= EmptyClipboard();
642 ok(r
, "EmptyClipboard failed: %d\n", GetLastError());
644 if (pGetClipboardSequenceNumber
)
646 seq
= pGetClipboardSequenceNumber();
647 ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
650 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
651 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
652 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
653 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
654 count
= SendMessageA( win
, WM_USER
+3, 0, 0 );
655 ok( !count
, "WM_DESTROYCLIPBOARD received\n" );
657 r
= EmptyClipboard();
658 ok(r
, "EmptyClipboard failed: %d\n", GetLastError());
659 /* sequence changes again, even though it was already empty */
660 if (pGetClipboardSequenceNumber
)
662 seq
= pGetClipboardSequenceNumber();
663 ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
666 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
667 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
668 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
669 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
670 count
= SendMessageA( win
, WM_USER
+3, 0, 0 );
671 ok( count
, "WM_DESTROYCLIPBOARD not received\n" );
672 count
= SendMessageA( win
, WM_USER
+4, 0, 0 );
673 ok( !count
, "wrong format count %u on WM_DESTROYCLIPBOARD\n", count
);
675 handle
= SetClipboardData( CF_TEXT
, create_text() );
676 ok(handle
!= 0, "SetClipboardData failed: %d\n", GetLastError());
678 if (pGetClipboardSequenceNumber
)
680 seq
= pGetClipboardSequenceNumber();
681 todo_wine
ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
684 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
685 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
686 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
687 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
689 SetClipboardData( CF_UNICODETEXT
, 0 );
691 if (pGetClipboardSequenceNumber
)
693 seq
= pGetClipboardSequenceNumber();
694 todo_wine
ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
697 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
698 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
699 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
700 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
702 SetClipboardData( CF_UNICODETEXT
, 0 ); /* same data again */
704 if (pGetClipboardSequenceNumber
)
706 seq
= pGetClipboardSequenceNumber();
707 todo_wine
ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
710 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
711 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
712 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
713 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
715 EnterCriticalSection(&clipboard_cs
);
716 r
= CloseClipboard();
717 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
718 LeaveCriticalSection(&clipboard_cs
);
720 if (pGetClipboardSequenceNumber
)
722 seq
= pGetClipboardSequenceNumber();
723 ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
726 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
727 ok( count
, "WM_DRAWCLIPBOARD not received\n" );
728 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
729 todo_wine
ok( count
|| broken(!pAddClipboardFormatListener
), "WM_CLIPBOARDUPDATE not received\n" );
731 r
= OpenClipboard(win
);
732 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
734 if (pGetClipboardSequenceNumber
)
736 seq
= pGetClipboardSequenceNumber();
737 ok( seq
== old_seq
, "sequence changed\n" );
739 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
740 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
741 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
742 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
744 SetClipboardData( CF_WAVE
, 0 );
745 if (pGetClipboardSequenceNumber
)
747 seq
= pGetClipboardSequenceNumber();
748 todo_wine
ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
751 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
752 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
753 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
754 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
756 r
= CloseClipboard();
757 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
758 if (pGetClipboardSequenceNumber
)
760 /* no synthesized format, so CloseClipboard doesn't change the sequence */
761 seq
= pGetClipboardSequenceNumber();
762 todo_wine
ok( seq
== old_seq
, "sequence changed\n" );
765 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
766 ok( count
, "WM_DRAWCLIPBOARD not received\n" );
767 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
768 todo_wine
ok( count
|| broken(!pAddClipboardFormatListener
), "WM_CLIPBOARDUPDATE not received\n" );
770 r
= OpenClipboard(win
);
771 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
772 r
= CloseClipboard();
773 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
774 /* nothing changed */
775 if (pGetClipboardSequenceNumber
)
777 seq
= pGetClipboardSequenceNumber();
778 ok( seq
== old_seq
, "sequence changed\n" );
780 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
781 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
782 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
783 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
784 count
= SendMessageA( win
, WM_USER
+3, 0, 0 );
785 ok( !count
, "WM_DESTROYCLIPBOARD received\n" );
787 formats
= CountClipboardFormats();
788 r
= OpenClipboard(0);
789 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
790 r
= EmptyClipboard();
791 ok(r
, "EmptyClipboard failed: %d\n", GetLastError());
792 r
= CloseClipboard();
793 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
795 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
796 ok( count
, "WM_DRAWCLIPBOARD not received\n" );
797 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
798 todo_wine
ok( count
|| broken(!pAddClipboardFormatListener
), "WM_CLIPBOARDUPDATE not received\n" );
799 count
= SendMessageA( win
, WM_USER
+3, 0, 0 );
800 ok( count
, "WM_DESTROYCLIPBOARD not received\n" );
801 count
= SendMessageA( win
, WM_USER
+4, 0, 0 );
802 ok( count
== formats
, "wrong format count %u on WM_DESTROYCLIPBOARD\n", count
);
804 r
= OpenClipboard(win
);
805 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
806 SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_FIXED
, 1 ));
807 if (pGetClipboardSequenceNumber
)
809 seq
= pGetClipboardSequenceNumber();
810 ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
813 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
814 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
815 count
= SendMessageA( win
, WM_USER
+3, 0, 0 );
816 ok( !count
, "WM_DESTROYCLIPBOARD received\n" );
818 EnterCriticalSection(&clipboard_cs
);
819 r
= CloseClipboard();
820 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
821 LeaveCriticalSection(&clipboard_cs
);
823 if (pGetClipboardSequenceNumber
)
825 seq
= pGetClipboardSequenceNumber();
826 todo_wine
ok( seq
== old_seq
, "sequence changed\n" );
829 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
830 ok( count
, "WM_DRAWCLIPBOARD not received\n" );
831 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
832 todo_wine
ok( count
|| broken(!pAddClipboardFormatListener
), "WM_CLIPBOARDUPDATE not received\n" );
834 run_process( "grab_clipboard 0" );
836 if (pGetClipboardSequenceNumber
)
838 seq
= pGetClipboardSequenceNumber();
839 ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
842 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
843 todo_wine
ok( count
, "WM_DRAWCLIPBOARD not received\n" );
844 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
845 todo_wine
ok( count
|| broken(!pAddClipboardFormatListener
), "WM_CLIPBOARDUPDATE not received\n" );
847 r
= OpenClipboard(0);
848 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
849 SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_FIXED
, 1 ));
850 if (pGetClipboardSequenceNumber
)
852 seq
= pGetClipboardSequenceNumber();
853 todo_wine
ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
856 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
857 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
858 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
859 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
861 EnterCriticalSection(&clipboard_cs
);
862 r
= CloseClipboard();
863 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
864 LeaveCriticalSection(&clipboard_cs
);
866 if (pGetClipboardSequenceNumber
)
868 seq
= pGetClipboardSequenceNumber();
869 todo_wine
ok( seq
== old_seq
, "sequence changed\n" );
872 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
873 ok( count
, "WM_DRAWCLIPBOARD not received\n" );
874 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
875 todo_wine
ok( count
|| broken(!pAddClipboardFormatListener
), "WM_CLIPBOARDUPDATE not received\n" );
877 run_process( "grab_clipboard 1" );
879 if (pGetClipboardSequenceNumber
)
881 seq
= pGetClipboardSequenceNumber();
882 ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
885 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
886 todo_wine
ok( count
, "WM_DRAWCLIPBOARD not received\n" );
887 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
888 todo_wine
ok( count
|| broken(!pAddClipboardFormatListener
), "WM_CLIPBOARDUPDATE not received\n" );
890 r
= OpenClipboard(0);
891 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
892 SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_FIXED
, 1 ));
893 if (pGetClipboardSequenceNumber
)
895 seq
= pGetClipboardSequenceNumber();
896 todo_wine
ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
899 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
900 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
901 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
902 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
904 EnterCriticalSection(&clipboard_cs
);
905 r
= CloseClipboard();
906 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
907 LeaveCriticalSection(&clipboard_cs
);
909 if (pGetClipboardSequenceNumber
)
911 seq
= pGetClipboardSequenceNumber();
912 todo_wine
ok( seq
== old_seq
, "sequence changed\n" );
915 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
916 ok( count
, "WM_DRAWCLIPBOARD not received\n" );
917 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
918 todo_wine
ok( count
|| broken(!pAddClipboardFormatListener
), "WM_CLIPBOARDUPDATE not received\n" );
920 r
= PostMessageA(win
, WM_USER
, 0, 0);
921 ok(r
, "PostMessage failed: %d\n", GetLastError());
923 if (pRemoveClipboardFormatListener
)
925 r
= pRemoveClipboardFormatListener(win
);
926 ok( r
, "RemoveClipboardFormatListener failed err %d\n", GetLastError());
927 SetLastError( 0xdeadbeef );
928 r
= pRemoveClipboardFormatListener(win
);
929 todo_wine
ok( !r
, "RemoveClipboardFormatListener succeeded\n" );
930 todo_wine
ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
931 SetLastError( 0xdeadbeef );
932 r
= pRemoveClipboardFormatListener( (HWND
)0xdead );
933 todo_wine
ok( !r
, "RemoveClipboardFormatListener succeeded\n" );
934 todo_wine
ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %u\n", GetLastError() );
939 static void test_messages(void)
947 InitializeCriticalSection(&clipboard_cs
);
949 memset(&cls
, 0, sizeof(cls
));
950 cls
.lpfnWndProc
= clipboard_wnd_proc
;
951 cls
.hInstance
= GetModuleHandleA(NULL
);
952 cls
.lpszClassName
= "clipboard_test";
953 RegisterClassA(&cls
);
955 win
= CreateWindowA("clipboard_test", NULL
, 0, 0, 0, 0, 0, NULL
, 0, NULL
, 0);
956 ok(win
!= NULL
, "CreateWindow failed: %d\n", GetLastError());
958 thread
= CreateThread(NULL
, 0, clipboard_thread
, (void*)win
, 0, &tid
);
959 ok(thread
!= NULL
, "CreateThread failed: %d\n", GetLastError());
961 while(GetMessageA(&msg
, NULL
, 0, 0)) {
962 TranslateMessage(&msg
);
963 DispatchMessageA(&msg
);
966 ok(WaitForSingleObject(thread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
969 UnregisterClassA("clipboard_test", GetModuleHandleA(NULL
));
970 DeleteCriticalSection(&clipboard_cs
);
973 static BOOL
is_moveable( HANDLE handle
)
975 void *ptr
= GlobalLock( handle
);
976 if (ptr
) GlobalUnlock( handle
);
977 return ptr
&& ptr
!= handle
;
980 static BOOL
is_fixed( HANDLE handle
)
982 void *ptr
= GlobalLock( handle
);
983 if (ptr
) GlobalUnlock( handle
);
984 return ptr
&& ptr
== handle
;
987 static BOOL
is_freed( HANDLE handle
)
989 void *ptr
= GlobalLock( handle
);
990 if (ptr
) GlobalUnlock( handle
);
994 static UINT format_id
;
995 static HBITMAP bitmap
, bitmap2
;
996 static HPALETTE palette
;
998 static const LOGPALETTE logpalette
= { 0x300, 1 };
1000 static void test_handles( HWND hwnd
)
1002 HGLOBAL h
, htext
, htext2
;
1006 BOOL is_owner
= (GetWindowThreadProcessId( hwnd
, &process
) && process
== GetCurrentProcessId());
1008 trace( "hwnd %p\n", hwnd
);
1009 htext
= create_text();
1010 htext2
= create_text();
1011 bitmap
= CreateBitmap( 10, 10, 1, 1, NULL
);
1012 bitmap2
= CreateBitmap( 10, 10, 1, 1, NULL
);
1013 palette
= CreatePalette( &logpalette
);
1014 pen
= CreatePen( PS_SOLID
, 1, 0 );
1016 r
= OpenClipboard( hwnd
);
1017 ok( r
, "gle %d\n", GetLastError() );
1018 r
= EmptyClipboard();
1019 ok( r
, "gle %d\n", GetLastError() );
1021 h
= SetClipboardData( CF_TEXT
, htext
);
1022 ok( h
== htext
, "got %p\n", h
);
1023 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1024 h
= SetClipboardData( format_id
, htext2
);
1025 ok( h
== htext2
, "got %p\n", h
);
1026 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1027 h
= SetClipboardData( CF_BITMAP
, bitmap
);
1028 ok( h
== bitmap
, "got %p\n", h
);
1029 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1030 h
= SetClipboardData( CF_PALETTE
, palette
);
1031 ok( h
== palette
, "got %p\n", h
);
1032 ok( GetObjectType( h
) == OBJ_PAL
, "expected palette %p\n", h
);
1033 /* setting custom GDI formats crashes on 64-bit Windows */
1036 h
= SetClipboardData( CF_GDIOBJFIRST
+ 1, bitmap2
);
1037 ok( h
== bitmap2
, "got %p\n", h
);
1038 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1039 h
= SetClipboardData( CF_GDIOBJFIRST
+ 2, pen
);
1040 ok( h
== pen
, "got %p\n", h
);
1041 ok( GetObjectType( h
) == OBJ_PEN
, "expected pen %p\n", h
);
1044 data
= GetClipboardData( CF_TEXT
);
1045 ok( data
== htext
, "wrong data %p\n", data
);
1046 ok( is_moveable( data
), "expected moveable mem %p\n", data
);
1048 data
= GetClipboardData( format_id
);
1049 ok( data
== htext2
, "wrong data %p, cf %08x\n", data
, format_id
);
1050 ok( is_moveable( data
), "expected moveable mem %p\n", data
);
1052 r
= CloseClipboard();
1053 ok( r
, "gle %d\n", GetLastError() );
1055 /* data handles are still valid */
1056 ok( is_moveable( htext
), "expected moveable mem %p\n", htext
);
1057 ok( is_moveable( htext2
), "expected moveable mem %p\n", htext
);
1058 ok( GetObjectType( bitmap
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap
);
1059 ok( GetObjectType( bitmap2
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap2
);
1060 ok( GetObjectType( palette
) == OBJ_PAL
, "expected palette %p\n", palette
);
1061 ok( GetObjectType( pen
) == OBJ_PEN
, "expected pen %p\n", pen
);
1063 r
= OpenClipboard( hwnd
);
1064 ok( r
, "gle %d\n", GetLastError() );
1066 /* and now they are freed, unless we are the owner */
1069 todo_wine
ok( is_freed( htext
), "expected freed mem %p\n", htext
);
1070 todo_wine
ok( is_freed( htext2
), "expected freed mem %p\n", htext
);
1072 data
= GetClipboardData( CF_TEXT
);
1073 todo_wine
ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1075 data
= GetClipboardData( format_id
);
1076 todo_wine
ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1080 ok( is_moveable( htext
), "expected moveable mem %p\n", htext
);
1081 ok( is_moveable( htext2
), "expected moveable mem %p\n", htext
);
1083 data
= GetClipboardData( CF_TEXT
);
1084 ok( data
== htext
, "wrong data %p\n", data
);
1086 data
= GetClipboardData( format_id
);
1087 ok( data
== htext2
, "wrong data %p, cf %08x\n", data
, format_id
);
1090 data
= GetClipboardData( CF_OEMTEXT
);
1091 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1092 data
= GetClipboardData( CF_UNICODETEXT
);
1093 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1094 data
= GetClipboardData( CF_BITMAP
);
1095 ok( data
== bitmap
, "expected bitmap %p\n", data
);
1096 data
= GetClipboardData( CF_PALETTE
);
1097 ok( data
== palette
, "expected palette %p\n", data
);
1100 data
= GetClipboardData( CF_GDIOBJFIRST
+ 1 );
1101 ok( data
== bitmap2
, "expected bitmap2 %p\n", data
);
1102 data
= GetClipboardData( CF_GDIOBJFIRST
+ 2 );
1103 ok( data
== pen
, "expected pen %p\n", data
);
1105 data
= GetClipboardData( CF_DIB
);
1106 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1107 data
= GetClipboardData( CF_DIBV5
);
1108 todo_wine
ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1110 ok( GetObjectType( bitmap
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap
);
1111 ok( GetObjectType( bitmap2
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap2
);
1112 ok( GetObjectType( palette
) == OBJ_PAL
, "expected palette %p\n", palette
);
1113 ok( GetObjectType( pen
) == OBJ_PEN
, "expected pen %p\n", pen
);
1115 r
= EmptyClipboard();
1116 ok( r
, "gle %d\n", GetLastError() );
1118 /* w2003, w2008 don't seem to free the data here */
1119 ok( is_freed( htext
) || broken( !is_freed( htext
)), "expected freed mem %p\n", htext
);
1120 ok( is_freed( htext2
) || broken( !is_freed( htext2
)), "expected freed mem %p\n", htext
);
1121 ok( !GetObjectType( bitmap
), "expected freed handle %p\n", bitmap
);
1122 ok( !GetObjectType( palette
), "expected freed handle %p\n", palette
);
1123 ok( GetObjectType( bitmap2
) == OBJ_BITMAP
, "expected bitmap2 %p\n", bitmap2
);
1124 ok( GetObjectType( pen
) == OBJ_PEN
, "expected pen %p\n", pen
);
1126 r
= CloseClipboard();
1127 ok( r
, "gle %d\n", GetLastError() );
1130 static DWORD WINAPI
test_handles_thread( void *arg
)
1132 trace( "running from different thread\n" );
1133 test_handles( (HWND
)arg
);
1137 static DWORD WINAPI
test_handles_thread2( void *arg
)
1143 r
= OpenClipboard( 0 );
1144 ok( r
, "gle %d\n", GetLastError() );
1145 h
= GetClipboardData( CF_TEXT
);
1146 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1147 ptr
= GlobalLock( h
);
1148 if (ptr
) ok( !strcmp( "test", ptr
), "wrong data '%.5s'\n", ptr
);
1150 h
= GetClipboardData( format_id
);
1151 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1152 ptr
= GlobalLock( h
);
1153 if (ptr
) ok( !strcmp( "test", ptr
), "wrong data '%.5s'\n", ptr
);
1155 h
= GetClipboardData( CF_BITMAP
);
1156 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1157 ok( h
== bitmap
, "different bitmap %p / %p\n", h
, bitmap
);
1158 trace( "bitmap %p\n", h
);
1159 h
= GetClipboardData( CF_PALETTE
);
1160 ok( GetObjectType( h
) == OBJ_PAL
, "expected palette %p\n", h
);
1161 ok( h
== palette
, "different palette %p / %p\n", h
, palette
);
1162 trace( "palette %p\n", h
);
1165 h
= GetClipboardData( CF_GDIOBJFIRST
+ 1 );
1166 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1167 ok( h
== bitmap2
, "different bitmap %p / %p\n", h
, bitmap2
);
1168 trace( "bitmap2 %p\n", h
);
1169 h
= GetClipboardData( CF_GDIOBJFIRST
+ 2 );
1170 ok( GetObjectType( h
) == OBJ_PEN
, "expected pen %p\n", h
);
1171 ok( h
== pen
, "different pen %p / %p\n", h
, pen
);
1172 trace( "pen %p\n", h
);
1174 h
= GetClipboardData( CF_DIB
);
1175 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1176 h
= GetClipboardData( CF_DIBV5
);
1177 todo_wine
ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1178 r
= CloseClipboard();
1179 ok( r
, "gle %d\n", GetLastError() );
1183 static void test_handles_process( const char *str
)
1189 format_id
= RegisterClipboardFormatA( "my_cool_clipboard_format" );
1190 r
= OpenClipboard( 0 );
1191 ok( r
, "gle %d\n", GetLastError() );
1192 h
= GetClipboardData( CF_TEXT
);
1193 todo_wine_if( !h
) ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1194 ptr
= GlobalLock( h
);
1195 if (ptr
) todo_wine
ok( !strcmp( str
, ptr
), "wrong data '%.5s'\n", ptr
);
1197 h
= GetClipboardData( format_id
);
1198 todo_wine
ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1199 ptr
= GlobalLock( h
);
1200 if (ptr
) ok( !strcmp( str
, ptr
), "wrong data '%.5s'\n", ptr
);
1202 h
= GetClipboardData( CF_BITMAP
);
1203 todo_wine
ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1204 trace( "bitmap %p\n", h
);
1205 h
= GetClipboardData( CF_PALETTE
);
1206 todo_wine
ok( GetObjectType( h
) == OBJ_PAL
, "expected palette %p\n", h
);
1207 trace( "palette %p\n", h
);
1208 h
= GetClipboardData( CF_GDIOBJFIRST
+ 1 );
1209 ok( !GetObjectType( h
), "expected invalid %p\n", h
);
1210 trace( "bitmap2 %p\n", h
);
1211 h
= GetClipboardData( CF_GDIOBJFIRST
+ 2 );
1212 ok( !GetObjectType( h
), "expected invalid %p\n", h
);
1213 trace( "pen %p\n", h
);
1214 h
= GetClipboardData( CF_DIB
);
1215 todo_wine
ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1216 h
= GetClipboardData( CF_DIBV5
);
1217 todo_wine
ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1218 r
= CloseClipboard();
1219 ok( r
, "gle %d\n", GetLastError() );
1222 static void test_data_handles(void)
1226 HWND hwnd
= CreateWindowA( "static", NULL
, WS_POPUP
, 0, 0, 10, 10, 0, 0, 0, NULL
);
1228 ok( hwnd
!= 0, "window creation failed\n" );
1229 format_id
= RegisterClipboardFormatA( "my_cool_clipboard_format" );
1231 test_handles( GetDesktopWindow() );
1232 test_handles( hwnd
);
1233 run_thread( test_handles_thread
, hwnd
, __LINE__
);
1235 bitmap
= CreateBitmap( 10, 10, 1, 1, NULL
);
1236 bitmap2
= CreateBitmap( 10, 10, 1, 1, NULL
);
1237 palette
= CreatePalette( &logpalette
);
1238 pen
= CreatePen( PS_SOLID
, 1, 0 );
1240 r
= OpenClipboard( hwnd
);
1241 ok( r
, "gle %d\n", GetLastError() );
1242 r
= EmptyClipboard();
1243 ok( r
, "gle %d\n", GetLastError() );
1244 h
= SetClipboardData( CF_TEXT
, create_text() );
1245 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1246 h
= SetClipboardData( format_id
, create_text() );
1247 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1248 h
= SetClipboardData( CF_BITMAP
, bitmap
);
1249 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1250 h
= SetClipboardData( CF_PALETTE
, palette
);
1251 ok( GetObjectType( h
) == OBJ_PAL
, "expected palette %p\n", h
);
1254 h
= SetClipboardData( CF_GDIOBJFIRST
+ 1, bitmap2
);
1255 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1256 h
= SetClipboardData( CF_GDIOBJFIRST
+ 2, pen
);
1257 ok( GetObjectType( h
) == OBJ_PEN
, "expected pen %p\n", h
);
1259 r
= CloseClipboard();
1260 ok( r
, "gle %d\n", GetLastError() );
1262 run_thread( test_handles_thread2
, 0, __LINE__
);
1263 run_process( "handles test" );
1265 r
= OpenClipboard( hwnd
);
1266 ok( r
, "gle %d\n", GetLastError() );
1267 h
= GetClipboardData( CF_TEXT
);
1268 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1269 h
= GetClipboardData( format_id
);
1270 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1271 r
= EmptyClipboard();
1272 ok( r
, "gle %d\n", GetLastError() );
1273 r
= CloseClipboard();
1274 ok( r
, "gle %d\n", GetLastError() );
1276 DestroyWindow( hwnd
);
1279 START_TEST(clipboard
)
1282 int argc
= winetest_get_mainargs( &argv
);
1283 HMODULE mod
= GetModuleHandleA( "user32" );
1286 pAddClipboardFormatListener
= (void *)GetProcAddress( mod
, "AddClipboardFormatListener" );
1287 pRemoveClipboardFormatListener
= (void *)GetProcAddress( mod
, "RemoveClipboardFormatListener" );
1288 pGetClipboardSequenceNumber
= (void *)GetProcAddress( mod
, "GetClipboardSequenceNumber" );
1290 if (argc
== 4 && !strcmp( argv
[2], "set_clipboard_data" ))
1292 set_clipboard_data_process( atoi( argv
[3] ));
1295 if (argc
== 4 && !strcmp( argv
[2], "grab_clipboard" ))
1297 grab_clipboard_process( atoi( argv
[3] ));
1300 if (argc
== 4 && !strcmp( argv
[2], "handles" ))
1302 test_handles_process( argv
[3] );
1306 test_RegisterClipboardFormatA();
1307 test_ClipboardOwner();
1310 test_data_handles();