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 DWORD (WINAPI
*pGetClipboardSequenceNumber
)(void);
31 static int thread_from_line
;
34 static DWORD WINAPI
open_clipboard_thread(LPVOID arg
)
37 ok(OpenClipboard(hWnd
), "%u: OpenClipboard failed\n", thread_from_line
);
41 static DWORD WINAPI
empty_clipboard_thread(LPVOID arg
)
43 SetLastError( 0xdeadbeef );
44 ok(!EmptyClipboard(), "%u: EmptyClipboard succeeded\n", thread_from_line
);
45 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "%u: wrong error %u\n",
46 thread_from_line
, GetLastError());
50 static DWORD WINAPI
open_and_empty_clipboard_thread(LPVOID arg
)
53 ok(OpenClipboard(hWnd
), "%u: OpenClipboard failed\n", thread_from_line
);
54 ok(EmptyClipboard(), "%u: EmptyClipboard failed\n", thread_from_line
);
58 static DWORD WINAPI
set_clipboard_data_thread(LPVOID arg
)
63 SetLastError( 0xdeadbeef );
64 if (GetClipboardOwner() == hwnd
)
66 SetClipboardData( CF_WAVE
, 0 );
67 todo_wine
ok( IsClipboardFormatAvailable( CF_WAVE
), "%u: SetClipboardData failed\n", thread_from_line
);
68 ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
69 ok( ret
!= 0, "%u: SetClipboardData failed err %u\n", thread_from_line
, GetLastError() );
73 SetClipboardData( CF_WAVE
, 0 );
74 todo_wine
ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "%u: wrong error %u\n",
75 thread_from_line
, GetLastError());
76 ok( !IsClipboardFormatAvailable( CF_WAVE
), "%u: SetClipboardData succeeded\n", thread_from_line
);
77 ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
78 todo_wine
ok( !ret
, "%u: SetClipboardData succeeded\n", thread_from_line
);
79 todo_wine
ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "%u: wrong error %u\n",
80 thread_from_line
, GetLastError());
85 static void set_clipboard_data_process( int arg
)
89 SetLastError( 0xdeadbeef );
92 todo_wine_if( arg
== 1 || arg
== 3 )
93 ok( IsClipboardFormatAvailable( CF_WAVE
), "process %u: CF_WAVE not available\n", arg
);
94 ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
95 todo_wine_if( arg
== 2 || arg
== 4 )
96 ok( ret
!= 0, "process %u: SetClipboardData failed err %u\n", arg
, GetLastError() );
100 SetClipboardData( CF_WAVE
, 0 );
101 todo_wine
ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "process %u: wrong error %u\n",
102 arg
, GetLastError());
103 todo_wine
ok( !IsClipboardFormatAvailable( CF_WAVE
), "process %u: SetClipboardData succeeded\n", arg
);
104 ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
105 ok( !ret
, "process %u: SetClipboardData succeeded\n", arg
);
106 todo_wine
ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "process %u: wrong error %u\n",
107 arg
, GetLastError());
111 static void run_thread( LPTHREAD_START_ROUTINE func
, void *arg
, int line
)
116 thread_from_line
= line
;
117 thread
= CreateThread(NULL
, 0, func
, arg
, 0, NULL
);
118 ok(thread
!= NULL
, "%u: CreateThread failed with error %d\n", line
, GetLastError());
121 ret
= MsgWaitForMultipleObjectsEx( 1, &thread
, 1000, QS_ALLINPUT
, 0 );
122 if (ret
== WAIT_OBJECT_0
+ 1)
125 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
129 ok(ret
== WAIT_OBJECT_0
, "%u: expected WAIT_OBJECT_0, got %u\n", line
, ret
);
133 static void run_process( const char *args
)
136 PROCESS_INFORMATION info
;
137 STARTUPINFOA startup
;
139 sprintf( cmd
, "%s clipboard %s", argv0
, args
);
140 memset( &startup
, 0, sizeof(startup
) );
141 startup
.cb
= sizeof(startup
);
142 ok( CreateProcessA( NULL
, cmd
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &startup
, &info
),
143 "CreateProcess %s failed\n", cmd
);
145 winetest_wait_child_process( info
.hProcess
);
146 CloseHandle( info
.hProcess
);
147 CloseHandle( info
.hThread
);
150 static void test_ClipboardOwner(void)
155 SetLastError(0xdeadbeef);
156 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef,
157 "could not perform clipboard test: clipboard already owned\n");
159 hWnd1
= CreateWindowExA(0, "static", NULL
, WS_POPUP
,
160 0, 0, 10, 10, 0, 0, 0, NULL
);
161 ok(hWnd1
!= 0, "CreateWindowExA error %d\n", GetLastError());
162 trace("hWnd1 = %p\n", hWnd1
);
164 hWnd2
= CreateWindowExA(0, "static", NULL
, WS_POPUP
,
165 0, 0, 10, 10, 0, 0, 0, NULL
);
166 ok(hWnd2
!= 0, "CreateWindowExA error %d\n", GetLastError());
167 trace("hWnd2 = %p\n", hWnd2
);
169 SetLastError(0xdeadbeef);
170 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
171 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
|| broken(GetLastError() == 0xdeadbeef), /* wow64 */
172 "wrong error %u\n", GetLastError());
174 ok(OpenClipboard(0), "OpenClipboard failed\n");
175 ok(!GetClipboardOwner(), "clipboard should still be not owned\n");
176 ok(!OpenClipboard(hWnd1
), "OpenClipboard should fail since clipboard already opened\n");
177 ok(OpenClipboard(0), "OpenClipboard again failed\n");
178 ret
= CloseClipboard();
179 ok( ret
, "CloseClipboard error %d\n", GetLastError());
181 ok(OpenClipboard(hWnd1
), "OpenClipboard failed\n");
182 run_thread( open_clipboard_thread
, hWnd1
, __LINE__
);
183 run_thread( empty_clipboard_thread
, 0, __LINE__
);
184 run_thread( set_clipboard_data_thread
, hWnd1
, __LINE__
);
185 run_process( "set_clipboard_data 0" );
186 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
187 ok(OpenClipboard(hWnd1
), "OpenClipboard failed\n");
189 SetLastError(0xdeadbeef);
190 ret
= OpenClipboard(hWnd2
);
191 ok(!ret
&& (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED
),
192 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
194 SetLastError(0xdeadbeef);
195 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should still be not owned\n");
196 ret
= EmptyClipboard();
197 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
198 ok(GetClipboardOwner() == hWnd1
, "clipboard should be owned by %p, not by %p\n", hWnd1
, GetClipboardOwner());
199 run_thread( empty_clipboard_thread
, 0, __LINE__
);
200 run_thread( set_clipboard_data_thread
, hWnd1
, __LINE__
);
201 run_process( "set_clipboard_data 1" );
203 SetLastError(0xdeadbeef);
204 ret
= OpenClipboard(hWnd2
);
205 ok(!ret
&& (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED
),
206 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
208 ret
= CloseClipboard();
209 ok( ret
, "CloseClipboard error %d\n", GetLastError());
210 ok(GetClipboardOwner() == hWnd1
, "clipboard should still be owned\n");
212 /* any window will do, even from a different process */
213 ret
= OpenClipboard( GetDesktopWindow() );
214 ok( ret
, "OpenClipboard error %d\n", GetLastError());
215 ret
= EmptyClipboard();
216 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
217 ok( GetClipboardOwner() == GetDesktopWindow(), "wrong owner %p/%p\n",
218 GetClipboardOwner(), GetDesktopWindow() );
219 run_thread( set_clipboard_data_thread
, GetDesktopWindow(), __LINE__
);
220 run_process( "set_clipboard_data 2" );
221 ret
= CloseClipboard();
222 ok( ret
, "CloseClipboard error %d\n", GetLastError());
224 ret
= OpenClipboard( hWnd1
);
225 ok( ret
, "OpenClipboard error %d\n", GetLastError());
226 ret
= EmptyClipboard();
227 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
228 ok( GetClipboardOwner() == hWnd1
, "wrong owner %p/%p\n", GetClipboardOwner(), hWnd1
);
229 ret
= CloseClipboard();
230 ok( ret
, "CloseClipboard error %d\n", GetLastError());
232 ret
= DestroyWindow(hWnd1
);
233 ok( ret
, "DestroyWindow error %d\n", GetLastError());
234 ret
= DestroyWindow(hWnd2
);
235 ok( ret
, "DestroyWindow error %d\n", GetLastError());
236 SetLastError(0xdeadbeef);
237 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should not be owned\n");
239 ret
= OpenClipboard( 0 );
240 ok( ret
, "OpenClipboard error %d\n", GetLastError());
241 run_thread( set_clipboard_data_thread
, 0, __LINE__
);
242 run_process( "set_clipboard_data 3" );
243 ret
= CloseClipboard();
244 ok( ret
, "CloseClipboard error %d\n", GetLastError());
246 run_thread( open_and_empty_clipboard_thread
, 0, __LINE__
);
248 ret
= OpenClipboard( 0 );
249 ok( ret
, "OpenClipboard error %d\n", GetLastError());
250 run_thread( set_clipboard_data_thread
, 0, __LINE__
);
251 run_process( "set_clipboard_data 4" );
252 ret
= EmptyClipboard();
253 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
254 ret
= CloseClipboard();
255 ok( ret
, "CloseClipboard error %d\n", GetLastError());
257 SetLastError( 0xdeadbeef );
258 todo_wine
ok( !SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 )),
259 "SetClipboardData succeeded\n" );
260 todo_wine
ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "wrong error %u\n", GetLastError() );
261 todo_wine
ok( !IsClipboardFormatAvailable( CF_WAVE
), "SetClipboardData succeeded\n" );
265 static void test_RegisterClipboardFormatA(void)
268 UINT format_id
, format_id2
;
274 format_id
= RegisterClipboardFormatA("my_cool_clipboard_format");
275 ok(format_id
> 0xc000 && format_id
< 0xffff, "invalid clipboard format id %04x\n", format_id
);
277 format_id2
= RegisterClipboardFormatA("MY_COOL_CLIPBOARD_FORMAT");
278 ok(format_id2
== format_id
, "invalid clipboard format id %04x\n", format_id2
);
280 len
= GetClipboardFormatNameA(format_id
, buf
, 256);
281 ok(len
== lstrlenA("my_cool_clipboard_format"), "wrong format name length %d\n", len
);
282 ok(!lstrcmpA(buf
, "my_cool_clipboard_format"), "wrong format name \"%s\"\n", buf
);
284 lstrcpyA(buf
, "foo");
285 SetLastError(0xdeadbeef);
286 len
= GetAtomNameA((ATOM
)format_id
, buf
, 256);
287 ok(len
== 0, "GetAtomNameA should fail\n");
288 ok(GetLastError() == ERROR_INVALID_HANDLE
, "err %d\n", GetLastError());
292 lstrcpyA(buf
, "foo");
293 SetLastError(0xdeadbeef);
294 len
= GlobalGetAtomNameA((ATOM
)format_id
, buf
, 256);
295 ok(len
== 0, "GlobalGetAtomNameA should fail\n");
296 ok(GetLastError() == ERROR_INVALID_HANDLE
, "err %d\n", GetLastError());
299 SetLastError(0xdeadbeef);
300 atom_id
= FindAtomA("my_cool_clipboard_format");
301 ok(atom_id
== 0, "FindAtomA should fail\n");
302 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "err %d\n", GetLastError());
306 /* this relies on the clipboard and global atom table being different */
307 SetLastError(0xdeadbeef);
308 atom_id
= GlobalFindAtomA("my_cool_clipboard_format");
309 ok(atom_id
== 0, "GlobalFindAtomA should fail\n");
310 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "err %d\n", GetLastError());
313 for (format_id
= 0; format_id
< 0xffff; format_id
++)
315 SetLastError(0xdeadbeef);
316 len
= GetClipboardFormatNameA(format_id
, buf
, 256);
318 if (format_id
< 0xc000)
319 ok(!len
, "GetClipboardFormatNameA should fail, but it returned %d (%s)\n", len
, buf
);
320 else if (len
&& winetest_debug
> 1)
321 trace("%04x: %s\n", format_id
, len
? buf
: "");
324 ret
= OpenClipboard(0);
325 ok( ret
, "OpenClipboard error %d\n", GetLastError());
327 /* try some invalid/unregistered formats */
328 SetLastError( 0xdeadbeef );
329 handle
= SetClipboardData( 0, GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, 1 ));
330 ok( !handle
, "SetClipboardData succeeded\n" );
331 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "wrong error %u\n", GetLastError());
332 handle
= SetClipboardData( 0x1234, GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, 1 ));
333 ok( handle
!= 0, "SetClipboardData failed err %d\n", GetLastError());
334 handle
= SetClipboardData( 0x123456, GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, 1 ));
335 ok( handle
!= 0, "SetClipboardData failed err %d\n", GetLastError());
336 handle
= SetClipboardData( 0xffff8765, GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, 1 ));
337 ok( handle
!= 0, "SetClipboardData failed err %d\n", GetLastError());
339 ok( IsClipboardFormatAvailable( 0x1234 ), "format missing\n" );
340 ok( IsClipboardFormatAvailable( 0x123456 ), "format missing\n" );
341 ok( IsClipboardFormatAvailable( 0xffff8765 ), "format missing\n" );
342 ok( !IsClipboardFormatAvailable( 0 ), "format available\n" );
343 ok( !IsClipboardFormatAvailable( 0x3456 ), "format available\n" );
344 ok( !IsClipboardFormatAvailable( 0x8765 ), "format available\n" );
346 trace("# of formats available: %d\n", CountClipboardFormats());
349 while ((format_id
= EnumClipboardFormats(format_id
)))
351 ok(IsClipboardFormatAvailable(format_id
), "format %04x was listed as available\n", format_id
);
352 len
= GetClipboardFormatNameA(format_id
, buf
, 256);
353 trace("%04x: %s\n", format_id
, len
? buf
: "");
356 ret
= EmptyClipboard();
357 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
358 ret
=CloseClipboard();
359 ok( ret
, "CloseClipboard error %d\n", GetLastError());
361 if (CountClipboardFormats())
363 SetLastError(0xdeadbeef);
364 ok(!EnumClipboardFormats(0), "EnumClipboardFormats should fail if clipboard wasn't open\n");
365 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
,
366 "Last error should be set to ERROR_CLIPBOARD_NOT_OPEN, not %d\n", GetLastError());
369 SetLastError(0xdeadbeef);
370 ok(!EmptyClipboard(), "EmptyClipboard should fail if clipboard wasn't open\n");
371 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
|| broken(GetLastError() == 0xdeadbeef), /* wow64 */
372 "Wrong error %u\n", GetLastError());
374 format_id
= RegisterClipboardFormatA("#1234");
375 ok(format_id
== 1234, "invalid clipboard format id %04x\n", format_id
);
378 static HGLOBAL
create_text(void)
380 HGLOBAL h
= GlobalAlloc(GMEM_DDESHARE
|GMEM_MOVEABLE
, 5);
381 char *p
= GlobalLock(h
);
387 static HENHMETAFILE
create_emf(void)
389 const RECT rect
= {0, 0, 100, 100};
390 HDC hdc
= CreateEnhMetaFileA(NULL
, NULL
, &rect
, "HENHMETAFILE Ole Clipboard Test\0Test\0\0");
391 ExtTextOutA(hdc
, 0, 0, ETO_OPAQUE
, &rect
, "Test String", strlen("Test String"), NULL
);
392 return CloseEnhMetaFile(hdc
);
395 static void test_synthesized(void)
403 htext
= create_text();
406 r
= OpenClipboard(NULL
);
407 ok(r
, "gle %d\n", GetLastError());
408 r
= EmptyClipboard();
409 ok(r
, "gle %d\n", GetLastError());
410 h
= SetClipboardData(CF_TEXT
, htext
);
411 ok(h
== htext
, "got %p\n", h
);
412 h
= SetClipboardData(CF_ENHMETAFILE
, emf
);
413 ok(h
== emf
, "got %p\n", h
);
414 r
= CloseClipboard();
415 ok(r
, "gle %d\n", GetLastError());
417 r
= OpenClipboard(NULL
);
418 ok(r
, "gle %d\n", GetLastError());
419 cf
= EnumClipboardFormats(0);
420 ok(cf
== CF_TEXT
, "cf %08x\n", cf
);
421 data
= GetClipboardData(cf
);
422 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
424 cf
= EnumClipboardFormats(cf
);
425 ok(cf
== CF_ENHMETAFILE
, "cf %08x\n", cf
);
426 data
= GetClipboardData(cf
);
427 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
429 cf
= EnumClipboardFormats(cf
);
430 todo_wine
ok(cf
== CF_LOCALE
, "cf %08x\n", cf
);
432 cf
= EnumClipboardFormats(cf
);
433 ok(cf
== CF_OEMTEXT
, "cf %08x\n", cf
);
434 data
= GetClipboardData(cf
);
435 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
437 cf
= EnumClipboardFormats(cf
);
438 ok(cf
== CF_UNICODETEXT
, "cf %08x\n", cf
);
440 cf
= EnumClipboardFormats(cf
);
441 ok(cf
== CF_METAFILEPICT
, "cf %08x\n", cf
);
442 data
= GetClipboardData(cf
);
443 todo_wine
ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
445 cf
= EnumClipboardFormats(cf
);
446 ok(cf
== 0, "cf %08x\n", cf
);
448 r
= EmptyClipboard();
449 ok(r
, "gle %d\n", GetLastError());
451 r
= CloseClipboard();
452 ok(r
, "gle %d\n", GetLastError());
455 static CRITICAL_SECTION clipboard_cs
;
456 static HWND next_wnd
;
457 static LRESULT CALLBACK
clipboard_wnd_proc(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
459 static UINT wm_drawclipboard
;
460 static UINT wm_clipboardupdate
;
461 static UINT wm_destroyclipboard
;
465 case WM_DRAWCLIPBOARD
:
466 EnterCriticalSection(&clipboard_cs
);
468 LeaveCriticalSection(&clipboard_cs
);
470 case WM_CHANGECBCHAIN
:
471 if (next_wnd
== (HWND
)wp
)
474 SendMessageA(next_wnd
, msg
, wp
, lp
);
476 case WM_DESTROYCLIPBOARD
:
477 wm_destroyclipboard
++;
478 ok( GetClipboardOwner() == hwnd
, "WM_DESTROYCLIPBOARD owner %p\n", GetClipboardOwner() );
480 case WM_CLIPBOARDUPDATE
:
481 wm_clipboardupdate
++;
484 ChangeClipboardChain(hwnd
, next_wnd
);
488 ret
= wm_drawclipboard
;
489 wm_drawclipboard
= 0;
492 ret
= wm_clipboardupdate
;
493 wm_clipboardupdate
= 0;
496 ret
= wm_destroyclipboard
;
497 wm_destroyclipboard
= 0;
501 return DefWindowProcA(hwnd
, msg
, wp
, lp
);
504 static DWORD WINAPI
clipboard_thread(void *param
)
509 UINT count
, old_seq
= 0, seq
;
511 if (pGetClipboardSequenceNumber
) old_seq
= pGetClipboardSequenceNumber();
513 EnterCriticalSection(&clipboard_cs
);
514 SetLastError(0xdeadbeef);
515 next_wnd
= SetClipboardViewer(win
);
516 ok(GetLastError() == 0xdeadbeef, "GetLastError = %d\n", GetLastError());
517 LeaveCriticalSection(&clipboard_cs
);
518 if (pAddClipboardFormatListener
)
520 r
= pAddClipboardFormatListener(win
);
521 ok( r
, "AddClipboardFormatListener failed err %d\n", GetLastError());
524 if (pGetClipboardSequenceNumber
)
526 seq
= pGetClipboardSequenceNumber();
527 ok( seq
== old_seq
, "sequence changed\n" );
529 count
= SendMessageA( win
, WM_USER
+ 1, 0, 0 );
530 ok( count
, "WM_DRAWCLIPBOARD received\n" );
531 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
532 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
534 r
= OpenClipboard(win
);
535 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
537 if (pGetClipboardSequenceNumber
)
539 seq
= pGetClipboardSequenceNumber();
540 ok( seq
== old_seq
, "sequence changed\n" );
542 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
543 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
544 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
545 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
547 r
= EmptyClipboard();
548 ok(r
, "EmptyClipboard failed: %d\n", GetLastError());
550 if (pGetClipboardSequenceNumber
)
552 seq
= pGetClipboardSequenceNumber();
553 ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
556 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
557 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
558 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
559 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
560 count
= SendMessageA( win
, WM_USER
+3, 0, 0 );
561 ok( !count
, "WM_DESTROYCLIPBOARD received\n" );
563 r
= EmptyClipboard();
564 ok(r
, "EmptyClipboard failed: %d\n", GetLastError());
565 /* sequence changes again, even though it was already empty */
566 if (pGetClipboardSequenceNumber
)
568 seq
= pGetClipboardSequenceNumber();
569 ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
572 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
573 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
574 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
575 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
576 count
= SendMessageA( win
, WM_USER
+3, 0, 0 );
577 ok( count
, "WM_DESTROYCLIPBOARD not received\n" );
579 handle
= SetClipboardData( CF_TEXT
, create_text() );
580 ok(handle
!= 0, "SetClipboardData failed: %d\n", GetLastError());
582 if (pGetClipboardSequenceNumber
)
584 seq
= pGetClipboardSequenceNumber();
585 todo_wine
ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
588 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
589 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
590 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
591 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
593 SetClipboardData( CF_UNICODETEXT
, 0 );
595 if (pGetClipboardSequenceNumber
)
597 seq
= pGetClipboardSequenceNumber();
598 todo_wine
ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
601 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
602 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
603 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
604 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
606 SetClipboardData( CF_UNICODETEXT
, 0 ); /* same data again */
608 if (pGetClipboardSequenceNumber
)
610 seq
= pGetClipboardSequenceNumber();
611 todo_wine
ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
614 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
615 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
616 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
617 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
619 EnterCriticalSection(&clipboard_cs
);
620 r
= CloseClipboard();
621 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
622 LeaveCriticalSection(&clipboard_cs
);
624 if (pGetClipboardSequenceNumber
)
626 seq
= pGetClipboardSequenceNumber();
627 ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
630 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
631 ok( count
, "WM_DRAWCLIPBOARD not received\n" );
632 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
633 todo_wine
ok( count
|| broken(!pAddClipboardFormatListener
), "WM_CLIPBOARDUPDATE not received\n" );
635 r
= OpenClipboard(win
);
636 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
638 if (pGetClipboardSequenceNumber
)
640 seq
= pGetClipboardSequenceNumber();
641 ok( seq
== old_seq
, "sequence changed\n" );
643 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
644 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
645 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
646 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
648 SetClipboardData( CF_WAVE
, 0 );
649 if (pGetClipboardSequenceNumber
)
651 seq
= pGetClipboardSequenceNumber();
652 todo_wine
ok( (int)(seq
- old_seq
) > 0, "sequence unchanged\n" );
655 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
656 ok( !count
, "WM_DRAWCLIPBOARD received\n" );
657 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
658 ok( !count
, "WM_CLIPBOARDUPDATE received\n" );
660 r
= CloseClipboard();
661 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
662 if (pGetClipboardSequenceNumber
)
664 /* no synthesized format, so CloseClipboard doesn't change the sequence */
665 seq
= pGetClipboardSequenceNumber();
666 todo_wine
ok( seq
== old_seq
, "sequence changed\n" );
669 count
= SendMessageA( win
, WM_USER
+1, 0, 0 );
670 ok( count
, "WM_DRAWCLIPBOARD not received\n" );
671 count
= SendMessageA( win
, WM_USER
+2, 0, 0 );
672 todo_wine
ok( count
|| broken(!pAddClipboardFormatListener
), "WM_CLIPBOARDUPDATE not received\n" );
674 r
= OpenClipboard(win
);
675 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
676 r
= CloseClipboard();
677 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
678 /* nothing changed */
679 if (pGetClipboardSequenceNumber
)
681 seq
= pGetClipboardSequenceNumber();
682 ok( seq
== old_seq
, "sequence changed\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 r
= OpenClipboard(0);
690 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
691 r
= EmptyClipboard();
692 ok(r
, "EmptyClipboard failed: %d\n", GetLastError());
693 r
= CloseClipboard();
694 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
696 r
= PostMessageA(win
, WM_USER
, 0, 0);
697 ok(r
, "PostMessage failed: %d\n", GetLastError());
701 static void test_messages(void)
709 InitializeCriticalSection(&clipboard_cs
);
711 memset(&cls
, 0, sizeof(cls
));
712 cls
.lpfnWndProc
= clipboard_wnd_proc
;
713 cls
.hInstance
= GetModuleHandleA(NULL
);
714 cls
.lpszClassName
= "clipboard_test";
715 RegisterClassA(&cls
);
717 win
= CreateWindowA("clipboard_test", NULL
, 0, 0, 0, 0, 0, NULL
, 0, NULL
, 0);
718 ok(win
!= NULL
, "CreateWindow failed: %d\n", GetLastError());
720 thread
= CreateThread(NULL
, 0, clipboard_thread
, (void*)win
, 0, &tid
);
721 ok(thread
!= NULL
, "CreateThread failed: %d\n", GetLastError());
723 while(GetMessageA(&msg
, NULL
, 0, 0)) {
724 TranslateMessage(&msg
);
725 DispatchMessageA(&msg
);
728 ok(WaitForSingleObject(thread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
731 UnregisterClassA("clipboard_test", GetModuleHandleA(NULL
));
732 DeleteCriticalSection(&clipboard_cs
);
735 static BOOL
is_moveable( HANDLE handle
)
737 void *ptr
= GlobalLock( handle
);
738 if (ptr
) GlobalUnlock( handle
);
739 return ptr
&& ptr
!= handle
;
742 static BOOL
is_fixed( HANDLE handle
)
744 void *ptr
= GlobalLock( handle
);
745 if (ptr
) GlobalUnlock( handle
);
746 return ptr
&& ptr
== handle
;
749 static BOOL
is_freed( HANDLE handle
)
751 void *ptr
= GlobalLock( handle
);
752 if (ptr
) GlobalUnlock( handle
);
756 static UINT format_id
;
757 static HBITMAP bitmap
, bitmap2
;
758 static HPALETTE palette
;
760 static const LOGPALETTE logpalette
= { 0x300, 1 };
762 static void test_handles( HWND hwnd
)
764 HGLOBAL h
, htext
, htext2
;
768 BOOL is_owner
= (GetWindowThreadProcessId( hwnd
, &process
) && process
== GetCurrentProcessId());
770 trace( "hwnd %p\n", hwnd
);
771 htext
= create_text();
772 htext2
= create_text();
773 bitmap
= CreateBitmap( 10, 10, 1, 1, NULL
);
774 bitmap2
= CreateBitmap( 10, 10, 1, 1, NULL
);
775 palette
= CreatePalette( &logpalette
);
776 pen
= CreatePen( PS_SOLID
, 1, 0 );
778 r
= OpenClipboard( hwnd
);
779 ok( r
, "gle %d\n", GetLastError() );
780 r
= EmptyClipboard();
781 ok( r
, "gle %d\n", GetLastError() );
783 h
= SetClipboardData( CF_TEXT
, htext
);
784 ok( h
== htext
, "got %p\n", h
);
785 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
786 h
= SetClipboardData( format_id
, htext2
);
787 ok( h
== htext2
, "got %p\n", h
);
788 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
789 h
= SetClipboardData( CF_BITMAP
, bitmap
);
790 ok( h
== bitmap
, "got %p\n", h
);
791 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
792 h
= SetClipboardData( CF_PALETTE
, palette
);
793 ok( h
== palette
, "got %p\n", h
);
794 ok( GetObjectType( h
) == OBJ_PAL
, "expected palette %p\n", h
);
795 h
= SetClipboardData( CF_GDIOBJFIRST
+ 1, bitmap2
);
796 ok( h
== bitmap2
, "got %p\n", h
);
797 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
798 h
= SetClipboardData( CF_GDIOBJFIRST
+ 2, pen
);
799 ok( h
== pen
, "got %p\n", h
);
800 ok( GetObjectType( h
) == OBJ_PEN
, "expected pen %p\n", h
);
802 data
= GetClipboardData( CF_TEXT
);
803 ok( data
== htext
, "wrong data %p\n", data
);
804 ok( is_moveable( data
), "expected moveable mem %p\n", data
);
806 data
= GetClipboardData( format_id
);
807 ok( data
== htext2
, "wrong data %p, cf %08x\n", data
, format_id
);
808 ok( is_moveable( data
), "expected moveable mem %p\n", data
);
810 r
= CloseClipboard();
811 ok( r
, "gle %d\n", GetLastError() );
813 /* data handles are still valid */
814 ok( is_moveable( htext
), "expected moveable mem %p\n", htext
);
815 ok( is_moveable( htext2
), "expected moveable mem %p\n", htext
);
816 ok( GetObjectType( bitmap
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap
);
817 ok( GetObjectType( bitmap2
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap2
);
818 ok( GetObjectType( palette
) == OBJ_PAL
, "expected palette %p\n", palette
);
819 ok( GetObjectType( pen
) == OBJ_PEN
, "expected pen %p\n", pen
);
821 r
= OpenClipboard( hwnd
);
822 ok( r
, "gle %d\n", GetLastError() );
824 /* and now they are freed, unless we are the owner */
827 todo_wine
ok( is_freed( htext
), "expected freed mem %p\n", htext
);
828 todo_wine
ok( is_freed( htext2
), "expected freed mem %p\n", htext
);
830 data
= GetClipboardData( CF_TEXT
);
831 todo_wine
ok( is_fixed( data
), "expected fixed mem %p\n", data
);
833 data
= GetClipboardData( format_id
);
834 todo_wine
ok( is_fixed( data
), "expected fixed mem %p\n", data
);
838 ok( is_moveable( htext
), "expected moveable mem %p\n", htext
);
839 ok( is_moveable( htext2
), "expected moveable mem %p\n", htext
);
841 data
= GetClipboardData( CF_TEXT
);
842 ok( data
== htext
, "wrong data %p\n", data
);
844 data
= GetClipboardData( format_id
);
845 ok( data
== htext2
, "wrong data %p, cf %08x\n", data
, format_id
);
848 data
= GetClipboardData( CF_OEMTEXT
);
849 todo_wine
ok( is_fixed( data
), "expected fixed mem %p\n", data
);
850 data
= GetClipboardData( CF_UNICODETEXT
);
851 todo_wine
ok( is_fixed( data
), "expected fixed mem %p\n", data
);
852 data
= GetClipboardData( CF_BITMAP
);
853 ok( data
== bitmap
, "expected bitmap %p\n", data
);
854 data
= GetClipboardData( CF_PALETTE
);
855 ok( data
== palette
, "expected palette %p\n", data
);
856 data
= GetClipboardData( CF_GDIOBJFIRST
+ 1 );
857 ok( data
== bitmap2
, "expected bitmap2 %p\n", data
);
858 data
= GetClipboardData( CF_GDIOBJFIRST
+ 2 );
859 ok( data
== pen
, "expected pen %p\n", data
);
860 data
= GetClipboardData( CF_DIB
);
861 todo_wine
ok( is_fixed( data
), "expected fixed mem %p\n", data
);
862 data
= GetClipboardData( CF_DIBV5
);
863 todo_wine
ok( is_fixed( data
), "expected fixed mem %p\n", data
);
865 ok( GetObjectType( bitmap
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap
);
866 ok( GetObjectType( bitmap2
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap2
);
867 ok( GetObjectType( palette
) == OBJ_PAL
, "expected palette %p\n", palette
);
868 ok( GetObjectType( pen
) == OBJ_PEN
, "expected pen %p\n", pen
);
870 r
= EmptyClipboard();
871 ok( r
, "gle %d\n", GetLastError() );
873 /* w2003, w2008 don't seem to free the data here */
874 ok( is_freed( htext
) || broken( !is_freed( htext
)), "expected freed mem %p\n", htext
);
875 ok( is_freed( htext2
) || broken( !is_freed( htext2
)), "expected freed mem %p\n", htext
);
876 ok( !GetObjectType( bitmap
), "expected freed handle %p\n", bitmap
);
877 ok( !GetObjectType( palette
), "expected freed handle %p\n", palette
);
878 ok( GetObjectType( bitmap2
) == OBJ_BITMAP
, "expected bitmap2 %p\n", bitmap2
);
879 ok( GetObjectType( pen
) == OBJ_PEN
, "expected pen %p\n", pen
);
881 r
= CloseClipboard();
882 ok( r
, "gle %d\n", GetLastError() );
885 static DWORD WINAPI
test_handles_thread( void *arg
)
887 trace( "running from different thread\n" );
888 test_handles( (HWND
)arg
);
892 static DWORD WINAPI
test_handles_thread2( void *arg
)
898 r
= OpenClipboard( 0 );
899 ok( r
, "gle %d\n", GetLastError() );
900 h
= GetClipboardData( CF_TEXT
);
901 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
902 ptr
= GlobalLock( h
);
903 if (ptr
) ok( !strcmp( "test", ptr
), "wrong data '%.5s'\n", ptr
);
905 h
= GetClipboardData( format_id
);
906 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
907 ptr
= GlobalLock( h
);
908 if (ptr
) ok( !strcmp( "test", ptr
), "wrong data '%.5s'\n", ptr
);
910 h
= GetClipboardData( CF_BITMAP
);
911 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
912 ok( h
== bitmap
, "different bitmap %p / %p\n", h
, bitmap
);
913 trace( "bitmap %p\n", h
);
914 h
= GetClipboardData( CF_PALETTE
);
915 ok( GetObjectType( h
) == OBJ_PAL
, "expected palette %p\n", h
);
916 ok( h
== palette
, "different palette %p / %p\n", h
, palette
);
917 trace( "palette %p\n", h
);
918 h
= GetClipboardData( CF_GDIOBJFIRST
+ 1 );
919 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
920 ok( h
== bitmap2
, "different bitmap %p / %p\n", h
, bitmap2
);
921 trace( "bitmap2 %p\n", h
);
922 h
= GetClipboardData( CF_GDIOBJFIRST
+ 2 );
923 ok( GetObjectType( h
) == OBJ_PEN
, "expected pen %p\n", h
);
924 ok( h
== pen
, "different pen %p / %p\n", h
, pen
);
925 trace( "pen %p\n", h
);
926 h
= GetClipboardData( CF_DIB
);
927 todo_wine
ok( is_fixed( h
), "expected fixed mem %p\n", h
);
928 h
= GetClipboardData( CF_DIBV5
);
929 todo_wine
ok( is_fixed( h
), "expected fixed mem %p\n", h
);
930 r
= CloseClipboard();
931 ok( r
, "gle %d\n", GetLastError() );
935 static void test_handles_process( const char *str
)
941 format_id
= RegisterClipboardFormatA( "my_cool_clipboard_format" );
942 r
= OpenClipboard( 0 );
943 ok( r
, "gle %d\n", GetLastError() );
944 h
= GetClipboardData( CF_TEXT
);
945 todo_wine
ok( is_fixed( h
), "expected fixed mem %p\n", h
);
946 ptr
= GlobalLock( h
);
947 if (ptr
) todo_wine
ok( !strcmp( str
, ptr
), "wrong data '%.5s'\n", ptr
);
949 h
= GetClipboardData( format_id
);
950 todo_wine
ok( is_fixed( h
), "expected fixed mem %p\n", h
);
951 ptr
= GlobalLock( h
);
952 if (ptr
) ok( !strcmp( str
, ptr
), "wrong data '%.5s'\n", ptr
);
954 h
= GetClipboardData( CF_BITMAP
);
955 todo_wine
ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
956 trace( "bitmap %p\n", h
);
957 h
= GetClipboardData( CF_PALETTE
);
958 todo_wine
ok( GetObjectType( h
) == OBJ_PAL
, "expected palette %p\n", h
);
959 trace( "palette %p\n", h
);
960 h
= GetClipboardData( CF_GDIOBJFIRST
+ 1 );
961 ok( !GetObjectType( h
), "expected invalid %p\n", h
);
962 trace( "bitmap2 %p\n", h
);
963 h
= GetClipboardData( CF_GDIOBJFIRST
+ 2 );
964 ok( !GetObjectType( h
), "expected invalid %p\n", h
);
965 trace( "pen %p\n", h
);
966 h
= GetClipboardData( CF_DIB
);
967 todo_wine
ok( is_fixed( h
), "expected fixed mem %p\n", h
);
968 h
= GetClipboardData( CF_DIBV5
);
969 todo_wine
ok( is_fixed( h
), "expected fixed mem %p\n", h
);
970 r
= CloseClipboard();
971 ok( r
, "gle %d\n", GetLastError() );
974 static void test_data_handles(void)
978 HWND hwnd
= CreateWindowA( "static", NULL
, WS_POPUP
, 0, 0, 10, 10, 0, 0, 0, NULL
);
980 ok( hwnd
!= 0, "window creation failed\n" );
981 format_id
= RegisterClipboardFormatA( "my_cool_clipboard_format" );
983 test_handles( GetDesktopWindow() );
984 test_handles( hwnd
);
985 run_thread( test_handles_thread
, hwnd
, __LINE__
);
987 bitmap
= CreateBitmap( 10, 10, 1, 1, NULL
);
988 bitmap2
= CreateBitmap( 10, 10, 1, 1, NULL
);
989 palette
= CreatePalette( &logpalette
);
990 pen
= CreatePen( PS_SOLID
, 1, 0 );
992 r
= OpenClipboard( hwnd
);
993 ok( r
, "gle %d\n", GetLastError() );
994 r
= EmptyClipboard();
995 ok( r
, "gle %d\n", GetLastError() );
996 h
= SetClipboardData( CF_TEXT
, create_text() );
997 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
998 h
= SetClipboardData( format_id
, create_text() );
999 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1000 h
= SetClipboardData( CF_BITMAP
, bitmap
);
1001 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1002 h
= SetClipboardData( CF_PALETTE
, palette
);
1003 ok( GetObjectType( h
) == OBJ_PAL
, "expected palette %p\n", h
);
1004 h
= SetClipboardData( CF_GDIOBJFIRST
+ 1, bitmap2
);
1005 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1006 h
= SetClipboardData( CF_GDIOBJFIRST
+ 2, pen
);
1007 ok( GetObjectType( h
) == OBJ_PEN
, "expected pen %p\n", h
);
1008 r
= CloseClipboard();
1009 ok( r
, "gle %d\n", GetLastError() );
1011 run_thread( test_handles_thread2
, 0, __LINE__
);
1012 run_process( "handles test" );
1014 r
= OpenClipboard( hwnd
);
1015 ok( r
, "gle %d\n", GetLastError() );
1016 h
= GetClipboardData( CF_TEXT
);
1017 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1018 h
= GetClipboardData( format_id
);
1019 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1020 r
= EmptyClipboard();
1021 ok( r
, "gle %d\n", GetLastError() );
1022 r
= CloseClipboard();
1023 ok( r
, "gle %d\n", GetLastError() );
1025 DestroyWindow( hwnd
);
1028 START_TEST(clipboard
)
1031 int argc
= winetest_get_mainargs( &argv
);
1032 HMODULE mod
= GetModuleHandleA( "user32" );
1035 pAddClipboardFormatListener
= (void *)GetProcAddress( mod
, "AddClipboardFormatListener" );
1036 pGetClipboardSequenceNumber
= (void *)GetProcAddress( mod
, "GetClipboardSequenceNumber" );
1038 if (argc
== 4 && !strcmp( argv
[2], "set_clipboard_data" ))
1040 set_clipboard_data_process( atoi( argv
[3] ));
1043 if (argc
== 4 && !strcmp( argv
[2], "handles" ))
1045 test_handles_process( argv
[3] );
1049 test_RegisterClipboardFormatA();
1050 test_ClipboardOwner();
1053 test_data_handles();