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 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
open_and_empty_clipboard_win_thread(LPVOID arg
)
62 HWND hwnd
= CreateWindowA( "static", NULL
, WS_POPUP
, 0, 0, 10, 10, 0, 0, 0, NULL
);
63 ok(OpenClipboard(hwnd
), "%u: OpenClipboard failed\n", thread_from_line
);
64 ok(EmptyClipboard(), "%u: EmptyClipboard failed\n", thread_from_line
);
68 static DWORD WINAPI
set_clipboard_data_thread(LPVOID arg
)
73 SetLastError( 0xdeadbeef );
74 if (GetClipboardOwner() == hwnd
)
76 SetClipboardData( CF_WAVE
, 0 );
77 ok( IsClipboardFormatAvailable( CF_WAVE
), "%u: SetClipboardData failed\n", thread_from_line
);
78 ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
79 ok( ret
!= 0, "%u: SetClipboardData failed err %u\n", thread_from_line
, GetLastError() );
80 SetLastError( 0xdeadbeef );
81 ret
= GetClipboardData( CF_WAVE
);
82 ok( !ret
, "%u: GetClipboardData succeeded\n", thread_from_line
);
83 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "%u: wrong error %u\n",
84 thread_from_line
, GetLastError());
88 SetClipboardData( CF_WAVE
, 0 );
89 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "%u: wrong error %u\n",
90 thread_from_line
, GetLastError());
91 ok( !IsClipboardFormatAvailable( CF_WAVE
), "%u: SetClipboardData succeeded\n", thread_from_line
);
92 ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
93 ok( !ret
, "%u: SetClipboardData succeeded\n", thread_from_line
);
94 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "%u: wrong error %u\n",
95 thread_from_line
, GetLastError());
100 static void set_clipboard_data_process( int arg
)
104 SetLastError( 0xdeadbeef );
107 ok( IsClipboardFormatAvailable( CF_WAVE
), "process %u: CF_WAVE not available\n", arg
);
108 ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
109 ok( ret
!= 0, "process %u: SetClipboardData failed err %u\n", arg
, GetLastError() );
113 SetClipboardData( CF_WAVE
, 0 );
114 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "process %u: wrong error %u\n",
115 arg
, GetLastError());
116 ok( !IsClipboardFormatAvailable( CF_WAVE
), "process %u: SetClipboardData succeeded\n", arg
);
117 ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
118 ok( !ret
, "process %u: SetClipboardData succeeded\n", arg
);
119 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "process %u: wrong error %u\n",
120 arg
, GetLastError());
124 static void grab_clipboard_process( int arg
)
128 SetLastError( 0xdeadbeef );
129 ret
= OpenClipboard( 0 );
130 ok( ret
, "OpenClipboard failed\n" );
131 ret
= EmptyClipboard();
132 ok( ret
, "EmptyClipboard failed\n" );
135 HANDLE ret
= SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 ));
136 ok( ret
!= 0, "process %u: SetClipboardData failed err %u\n", arg
, GetLastError() );
140 static void run_thread( LPTHREAD_START_ROUTINE func
, void *arg
, int line
)
145 thread_from_line
= line
;
146 thread
= CreateThread(NULL
, 0, func
, arg
, 0, NULL
);
147 ok(thread
!= NULL
, "%u: CreateThread failed with error %d\n", line
, GetLastError());
150 ret
= MsgWaitForMultipleObjectsEx( 1, &thread
, 1000, QS_ALLINPUT
, 0 );
151 if (ret
== WAIT_OBJECT_0
+ 1)
154 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
158 ok(ret
== WAIT_OBJECT_0
, "%u: expected WAIT_OBJECT_0, got %u\n", line
, ret
);
162 static void run_process( const char *args
)
165 PROCESS_INFORMATION info
;
166 STARTUPINFOA startup
;
168 sprintf( cmd
, "%s clipboard %s", argv0
, args
);
169 memset( &startup
, 0, sizeof(startup
) );
170 startup
.cb
= sizeof(startup
);
171 ok( CreateProcessA( NULL
, cmd
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &startup
, &info
),
172 "CreateProcess %s failed\n", cmd
);
174 wait_child_process( info
.hProcess
);
175 CloseHandle( info
.hProcess
);
176 CloseHandle( info
.hThread
);
179 static WNDPROC old_proc
;
180 static LRESULT CALLBACK
winproc_wrapper( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
182 static int wm_renderallformats
;
183 static int wm_drawclipboard
;
185 DWORD msg_flags
= InSendMessageEx( NULL
);
187 if (!seqno
) seqno
= GetClipboardSequenceNumber();
189 trace( "%p msg %04x\n", hwnd
, msg
);
190 if (!wm_renderallformats
)
192 ok( GetClipboardOwner() == hwnd
, "%04x: wrong owner %p/%p\n", msg
, GetClipboardOwner(), hwnd
);
193 ok( seqno
== GetClipboardSequenceNumber(), "%04x: seqno changed\n", msg
);
197 ok( !GetClipboardOwner(), "%04x: wrong owner %p\n", msg
, GetClipboardOwner() );
198 ok( seqno
+ 1 == GetClipboardSequenceNumber(), "%04x: seqno unchanged\n", msg
);
200 ok( GetClipboardViewer() == hwnd
, "%04x: wrong viewer %p/%p\n", msg
, GetClipboardViewer(), hwnd
);
201 ok( GetOpenClipboardWindow() == hwnd
, "%04x: wrong open win %p/%p\n",
202 msg
, GetOpenClipboardWindow(), hwnd
);
207 ok( wm_renderallformats
, "didn't receive WM_RENDERALLFORMATS before WM_DESTROY\n" );
208 ok( wm_drawclipboard
, "didn't receive WM_DRAWCLIPBOARD before WM_DESTROY\n" );
210 case WM_DRAWCLIPBOARD
:
211 ok( msg_flags
== ISMEX_NOSEND
, "WM_DRAWCLIPBOARD wrong flags %x\n", msg_flags
);
214 case WM_RENDERALLFORMATS
:
215 ok( msg_flags
== ISMEX_NOSEND
, "WM_RENDERALLFORMATS wrong flags %x\n", msg_flags
);
216 wm_renderallformats
++;
219 return old_proc( hwnd
, msg
, wp
, lp
);
222 static void test_ClipboardOwner(void)
227 SetLastError(0xdeadbeef);
228 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef,
229 "could not perform clipboard test: clipboard already owned\n");
231 hWnd1
= CreateWindowExA(0, "static", NULL
, WS_POPUP
,
232 0, 0, 10, 10, 0, 0, 0, NULL
);
233 ok(hWnd1
!= 0, "CreateWindowExA error %d\n", GetLastError());
234 trace("hWnd1 = %p\n", hWnd1
);
236 hWnd2
= CreateWindowExA(0, "static", NULL
, WS_POPUP
,
237 0, 0, 10, 10, 0, 0, 0, NULL
);
238 ok(hWnd2
!= 0, "CreateWindowExA error %d\n", GetLastError());
239 trace("hWnd2 = %p\n", hWnd2
);
241 SetLastError(0xdeadbeef);
242 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
243 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
|| broken(GetLastError() == 0xdeadbeef), /* wow64 */
244 "wrong error %u\n", GetLastError());
246 ok(OpenClipboard(0), "OpenClipboard failed\n");
247 ok(!GetClipboardOwner(), "clipboard should still be not owned\n");
248 ok(!OpenClipboard(hWnd1
), "OpenClipboard should fail since clipboard already opened\n");
249 ok(OpenClipboard(0), "OpenClipboard again failed\n");
250 ret
= CloseClipboard();
251 ok( ret
, "CloseClipboard error %d\n", GetLastError());
253 ok(OpenClipboard(hWnd1
), "OpenClipboard failed\n");
254 run_thread( open_clipboard_thread
, hWnd1
, __LINE__
);
255 run_thread( empty_clipboard_thread
, 0, __LINE__
);
256 run_thread( set_clipboard_data_thread
, hWnd1
, __LINE__
);
257 ok( !IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE available\n" );
258 ok( !GetClipboardData( CF_WAVE
), "CF_WAVE data available\n" );
259 run_process( "set_clipboard_data 0" );
260 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
261 ok(OpenClipboard(hWnd1
), "OpenClipboard failed\n");
263 SetLastError(0xdeadbeef);
264 ret
= OpenClipboard(hWnd2
);
265 ok(!ret
&& (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED
),
266 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
268 SetLastError(0xdeadbeef);
269 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should still be not owned\n");
270 ret
= EmptyClipboard();
271 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
272 ok(GetClipboardOwner() == hWnd1
, "clipboard should be owned by %p, not by %p\n", hWnd1
, GetClipboardOwner());
273 run_thread( empty_clipboard_thread
, 0, __LINE__
);
274 run_thread( set_clipboard_data_thread
, hWnd1
, __LINE__
);
275 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
276 ok( GetClipboardData( CF_WAVE
) != 0, "CF_WAVE data not available\n" );
277 run_process( "set_clipboard_data 1" );
279 SetLastError(0xdeadbeef);
280 ret
= OpenClipboard(hWnd2
);
281 ok(!ret
&& (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED
),
282 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
284 ret
= CloseClipboard();
285 ok( ret
, "CloseClipboard error %d\n", GetLastError());
286 ok(GetClipboardOwner() == hWnd1
, "clipboard should still be owned\n");
288 /* any window will do, even from a different process */
289 ret
= OpenClipboard( GetDesktopWindow() );
290 ok( ret
, "OpenClipboard error %d\n", GetLastError());
291 ret
= EmptyClipboard();
292 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
293 ok( GetClipboardOwner() == GetDesktopWindow(), "wrong owner %p/%p\n",
294 GetClipboardOwner(), GetDesktopWindow() );
295 run_thread( set_clipboard_data_thread
, GetDesktopWindow(), __LINE__
);
296 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
297 ok( GetClipboardData( CF_WAVE
) != 0, "CF_WAVE data not available\n" );
298 run_process( "set_clipboard_data 2" );
299 ret
= CloseClipboard();
300 ok( ret
, "CloseClipboard error %d\n", GetLastError());
302 ret
= OpenClipboard( hWnd1
);
303 ok( ret
, "OpenClipboard error %d\n", GetLastError());
304 ret
= EmptyClipboard();
305 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
306 SetClipboardData( CF_WAVE
, 0 );
307 SetClipboardViewer( hWnd1
);
308 ok( GetClipboardOwner() == hWnd1
, "wrong owner %p/%p\n", GetClipboardOwner(), hWnd1
);
309 ok( GetClipboardViewer() == hWnd1
, "wrong viewer %p/%p\n", GetClipboardViewer(), hWnd1
);
310 ok( GetOpenClipboardWindow() == hWnd1
, "wrong open win %p/%p\n", GetOpenClipboardWindow(), hWnd1
);
311 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
313 old_proc
= (WNDPROC
)SetWindowLongPtrA( hWnd1
, GWLP_WNDPROC
, (LONG_PTR
)winproc_wrapper
);
314 ret
= DestroyWindow(hWnd1
);
315 ok( ret
, "DestroyWindow error %d\n", GetLastError());
316 ret
= DestroyWindow(hWnd2
);
317 ok( ret
, "DestroyWindow error %d\n", GetLastError());
318 SetLastError(0xdeadbeef);
319 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should not be owned\n");
320 ok(!GetClipboardViewer() && GetLastError() == 0xdeadbeef, "viewer still exists\n");
321 ok(!GetOpenClipboardWindow() && GetLastError() == 0xdeadbeef, "clipboard should not be open\n");
322 ok( !IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE available\n" );
324 SetLastError( 0xdeadbeef );
325 ret
= CloseClipboard();
326 ok( !ret
, "CloseClipboard succeeded\n" );
327 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "wrong error %u\n", GetLastError() );
329 ret
= OpenClipboard( 0 );
330 ok( ret
, "OpenClipboard error %d\n", GetLastError());
331 run_thread( set_clipboard_data_thread
, 0, __LINE__
);
332 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
333 ok( GetClipboardData( CF_WAVE
) != 0, "CF_WAVE data not available\n" );
334 run_process( "set_clipboard_data 3" );
335 ret
= CloseClipboard();
336 ok( ret
, "CloseClipboard error %d\n", GetLastError());
338 run_thread( open_and_empty_clipboard_thread
, 0, __LINE__
);
339 ok( !GetOpenClipboardWindow(), "wrong open window %p\n", GetOpenClipboardWindow() );
340 ok( !GetClipboardOwner(), "wrong owner window %p\n", GetClipboardOwner() );
342 ret
= OpenClipboard( 0 );
343 ok( ret
, "OpenClipboard error %d\n", GetLastError());
344 run_thread( set_clipboard_data_thread
, 0, __LINE__
);
345 ok( IsClipboardFormatAvailable( CF_WAVE
), "CF_WAVE not available\n" );
346 ok( GetClipboardData( CF_WAVE
) != 0, "CF_WAVE data not available\n" );
347 run_process( "set_clipboard_data 4" );
348 ret
= EmptyClipboard();
349 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
350 ret
= CloseClipboard();
351 ok( ret
, "CloseClipboard error %d\n", GetLastError());
353 SetLastError( 0xdeadbeef );
354 ok( !SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_DDESHARE
| GMEM_ZEROINIT
, 100 )),
355 "SetClipboardData succeeded\n" );
356 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "wrong error %u\n", GetLastError() );
357 ok( !IsClipboardFormatAvailable( CF_WAVE
), "SetClipboardData succeeded\n" );
359 run_thread( open_and_empty_clipboard_thread
, GetDesktopWindow(), __LINE__
);
360 ok( !GetOpenClipboardWindow(), "wrong open window %p\n", GetOpenClipboardWindow() );
361 ok( GetClipboardOwner() == GetDesktopWindow(), "wrong owner window %p / %p\n",
362 GetClipboardOwner(), GetDesktopWindow() );
364 run_thread( open_and_empty_clipboard_win_thread
, 0, __LINE__
);
365 ok( !GetOpenClipboardWindow(), "wrong open window %p\n", GetOpenClipboardWindow() );
366 ok( !GetClipboardOwner(), "wrong owner window %p\n", GetClipboardOwner() );
369 static void test_RegisterClipboardFormatA(void)
372 UINT format_id
, format_id2
;
378 format_id
= RegisterClipboardFormatA("my_cool_clipboard_format");
379 ok(format_id
> 0xc000 && format_id
< 0xffff, "invalid clipboard format id %04x\n", format_id
);
381 format_id2
= RegisterClipboardFormatA("MY_COOL_CLIPBOARD_FORMAT");
382 ok(format_id2
== format_id
, "invalid clipboard format id %04x\n", format_id2
);
384 len
= GetClipboardFormatNameA(format_id
, buf
, 256);
385 ok(len
== lstrlenA("my_cool_clipboard_format"), "wrong format name length %d\n", len
);
386 ok(!lstrcmpA(buf
, "my_cool_clipboard_format"), "wrong format name \"%s\"\n", buf
);
388 len
= GetClipboardFormatNameA(format_id
, NULL
, 0);
389 ok(len
== 0, "wrong format name length %d\n", len
);
391 lstrcpyA(buf
, "foo");
392 SetLastError(0xdeadbeef);
393 len
= GetAtomNameA((ATOM
)format_id
, buf
, 256);
394 ok(len
== 0, "GetAtomNameA should fail\n");
395 ok(GetLastError() == ERROR_INVALID_HANDLE
, "err %d\n", GetLastError());
399 lstrcpyA(buf
, "foo");
400 SetLastError(0xdeadbeef);
401 len
= GlobalGetAtomNameA((ATOM
)format_id
, buf
, 256);
402 ok(len
== 0, "GlobalGetAtomNameA should fail\n");
403 ok(GetLastError() == ERROR_INVALID_HANDLE
, "err %d\n", GetLastError());
406 SetLastError(0xdeadbeef);
407 atom_id
= FindAtomA("my_cool_clipboard_format");
408 ok(atom_id
== 0, "FindAtomA should fail\n");
409 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "err %d\n", GetLastError());
413 /* this relies on the clipboard and global atom table being different */
414 SetLastError(0xdeadbeef);
415 atom_id
= GlobalFindAtomA("my_cool_clipboard_format");
416 ok(atom_id
== 0, "GlobalFindAtomA should fail\n");
417 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "err %d\n", GetLastError());
420 for (format_id
= 0; format_id
< 0x10fff; format_id
++)
422 SetLastError(0xdeadbeef);
423 len
= GetClipboardFormatNameA(format_id
, buf
, 256);
425 if (format_id
< 0xc000 || format_id
> 0xffff)
426 ok(!len
, "GetClipboardFormatNameA should fail, but it returned %d (%s)\n", len
, buf
);
427 else if (len
&& winetest_debug
> 1)
428 trace("%04x: %s\n", format_id
, len
? buf
: "");
431 ret
= OpenClipboard(0);
432 ok( ret
, "OpenClipboard error %d\n", GetLastError());
434 /* try some invalid/unregistered formats */
435 SetLastError( 0xdeadbeef );
436 handle
= SetClipboardData( 0, GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, 1 ));
437 ok( !handle
, "SetClipboardData succeeded\n" );
438 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
, "wrong error %u\n", GetLastError());
439 handle
= SetClipboardData( 0x1234, GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, 1 ));
440 ok( handle
!= 0, "SetClipboardData failed err %d\n", GetLastError());
441 handle
= SetClipboardData( 0x123456, GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, 1 ));
442 ok( handle
!= 0, "SetClipboardData failed err %d\n", GetLastError());
443 handle
= SetClipboardData( 0xffff8765, GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, 1 ));
444 ok( handle
!= 0, "SetClipboardData failed err %d\n", GetLastError());
446 ok( IsClipboardFormatAvailable( 0x1234 ), "format missing\n" );
447 ok( IsClipboardFormatAvailable( 0x123456 ), "format missing\n" );
448 ok( IsClipboardFormatAvailable( 0xffff8765 ), "format missing\n" );
449 ok( !IsClipboardFormatAvailable( 0 ), "format available\n" );
450 ok( !IsClipboardFormatAvailable( 0x3456 ), "format available\n" );
451 ok( !IsClipboardFormatAvailable( 0x8765 ), "format available\n" );
453 trace("# of formats available: %d\n", CountClipboardFormats());
456 while ((format_id
= EnumClipboardFormats(format_id
)))
458 ok(IsClipboardFormatAvailable(format_id
), "format %04x was listed as available\n", format_id
);
459 len
= GetClipboardFormatNameA(format_id
, buf
, 256);
460 trace("%04x: %s\n", format_id
, len
? buf
: "");
463 ret
= EmptyClipboard();
464 ok( ret
, "EmptyClipboard error %d\n", GetLastError());
465 ret
=CloseClipboard();
466 ok( ret
, "CloseClipboard error %d\n", GetLastError());
468 if (CountClipboardFormats())
470 SetLastError(0xdeadbeef);
471 ok(!EnumClipboardFormats(0), "EnumClipboardFormats should fail if clipboard wasn't open\n");
472 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
,
473 "Last error should be set to ERROR_CLIPBOARD_NOT_OPEN, not %d\n", GetLastError());
476 SetLastError(0xdeadbeef);
477 ok(!EmptyClipboard(), "EmptyClipboard should fail if clipboard wasn't open\n");
478 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN
|| broken(GetLastError() == 0xdeadbeef), /* wow64 */
479 "Wrong error %u\n", GetLastError());
481 format_id
= RegisterClipboardFormatA("#1234");
482 ok(format_id
== 1234, "invalid clipboard format id %04x\n", format_id
);
485 static HGLOBAL
create_textA(void)
487 HGLOBAL h
= GlobalAlloc(GMEM_DDESHARE
|GMEM_MOVEABLE
, 10);
488 char *p
= GlobalLock(h
);
489 memcpy(p
, "test\0\0\0\0\0", 10);
494 static HGLOBAL
create_textW(void)
496 static const WCHAR testW
[] = {'t','e','s','t',0,0,0,0,0,0};
497 HGLOBAL h
= GlobalAlloc(GMEM_DDESHARE
|GMEM_MOVEABLE
, sizeof(testW
));
498 WCHAR
*p
= GlobalLock(h
);
499 memcpy(p
, testW
, sizeof(testW
));
504 static HANDLE
create_metafile(void)
506 const RECT rect
= {0, 0, 100, 100};
510 HDC hdc
= CreateMetaFileA( NULL
);
511 ExtTextOutA( hdc
, 0, 0, ETO_OPAQUE
, &rect
, "Test String", strlen("Test String"), NULL
);
512 mf
= CloseMetaFile( hdc
);
513 ret
= GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
, sizeof(*pict
) );
514 pict
= GlobalLock( ret
);
516 pict
->xExt
= pict
->yExt
= 100;
522 static HENHMETAFILE
create_emf(void)
524 const RECT rect
= {0, 0, 100, 100};
525 HDC hdc
= CreateEnhMetaFileA(NULL
, NULL
, &rect
, "HENHMETAFILE Ole Clipboard Test\0Test\0\0");
526 ExtTextOutA(hdc
, 0, 0, ETO_OPAQUE
, &rect
, "Test String", strlen("Test String"), NULL
);
527 return CloseEnhMetaFile(hdc
);
530 static HBITMAP
create_bitmap(void)
532 HDC hdc
= GetDC( 0 );
533 UINT bpp
= GetDeviceCaps( hdc
, BITSPIXEL
);
535 return CreateBitmap( 10, 10, 1, bpp
, NULL
);
538 static HBITMAP
create_dib( BOOL v5
)
541 BITMAPINFOHEADER
*hdr
;
543 ret
= GlobalAlloc( GMEM_DDESHARE
| GMEM_MOVEABLE
| GMEM_ZEROINIT
,
544 sizeof(BITMAPV5HEADER
) + 256 * sizeof(RGBQUAD
) + 16 * 16 * 4 );
545 hdr
= GlobalLock( ret
);
546 hdr
->biSize
= v5
? sizeof(BITMAPV5HEADER
) : sizeof(*hdr
);
550 hdr
->biBitCount
= 32;
551 hdr
->biCompression
= BI_RGB
;
554 BITMAPV5HEADER
*hdr5
= (BITMAPV5HEADER
*)hdr
;
555 hdr5
->bV5RedMask
= 0x0000ff;
556 hdr5
->bV5GreenMask
= 0x00ff00;
557 hdr5
->bV5BlueMask
= 0xff0000;
558 hdr5
->bV5AlphaMask
= 0xff000000;
564 static LRESULT CALLBACK
renderer_winproc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
566 static UINT rendered
;
571 case WM_RENDERFORMAT
:
572 if (wp
< 32) rendered
|= (1 << wp
);
579 return DefWindowProcA( hwnd
, msg
, wp
, lp
);
582 static void test_synthesized(void)
584 static const struct test
590 /* 0 */ { CF_TEXT
, { CF_TEXT
, CF_LOCALE
, CF_OEMTEXT
, CF_UNICODETEXT
}},
591 { CF_OEMTEXT
, { CF_OEMTEXT
, CF_LOCALE
, CF_TEXT
, CF_UNICODETEXT
}},
592 { CF_UNICODETEXT
, { CF_UNICODETEXT
, CF_LOCALE
, CF_TEXT
, CF_OEMTEXT
}},
593 { CF_ENHMETAFILE
, { CF_ENHMETAFILE
, CF_METAFILEPICT
}},
594 { CF_METAFILEPICT
, { CF_METAFILEPICT
, CF_ENHMETAFILE
}},
595 /* 5 */ { CF_BITMAP
, { CF_BITMAP
, CF_DIB
, CF_DIBV5
}},
596 { CF_DIB
, { CF_DIB
, CF_BITMAP
, CF_DIBV5
}},
597 { CF_DIBV5
, { CF_DIBV5
, CF_BITMAP
, CF_DIB
}},
603 UINT cf
, i
, j
, count
, rendered
, seq
, old_seq
;
607 hwnd
= CreateWindowA( "static", NULL
, WS_POPUP
, 0, 0, 10, 10, 0, 0, 0, NULL
);
608 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)renderer_winproc
);
610 htext
= create_textA();
613 r
= OpenClipboard(NULL
);
614 ok(r
, "gle %d\n", GetLastError());
615 r
= EmptyClipboard();
616 ok(r
, "gle %d\n", GetLastError());
617 h
= SetClipboardData(CF_TEXT
, htext
);
618 ok(h
== htext
, "got %p\n", h
);
619 h
= SetClipboardData(CF_ENHMETAFILE
, emf
);
620 ok(h
== emf
, "got %p\n", h
);
621 r
= CloseClipboard();
622 ok(r
, "gle %d\n", GetLastError());
624 count
= CountClipboardFormats();
625 ok( count
== 6, "count %u\n", count
);
626 r
= IsClipboardFormatAvailable( CF_TEXT
);
627 ok( r
, "CF_TEXT not available err %d\n", GetLastError());
628 r
= IsClipboardFormatAvailable( CF_LOCALE
);
629 ok( r
, "CF_LOCALE not available err %d\n", GetLastError());
630 r
= IsClipboardFormatAvailable( CF_OEMTEXT
);
631 ok( r
, "CF_OEMTEXT not available err %d\n", GetLastError());
632 r
= IsClipboardFormatAvailable( CF_UNICODETEXT
);
633 ok( r
, "CF_UNICODETEXT not available err %d\n", GetLastError());
634 r
= IsClipboardFormatAvailable( CF_ENHMETAFILE
);
635 ok( r
, "CF_ENHMETAFILE not available err %d\n", GetLastError());
636 r
= IsClipboardFormatAvailable( CF_METAFILEPICT
);
637 ok( r
, "CF_METAFILEPICT not available err %d\n", GetLastError());
639 r
= OpenClipboard(NULL
);
640 ok(r
, "gle %d\n", GetLastError());
641 cf
= EnumClipboardFormats(0);
642 ok(cf
== CF_TEXT
, "cf %08x\n", cf
);
643 data
= GetClipboardData(cf
);
644 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
646 cf
= EnumClipboardFormats(cf
);
647 ok(cf
== CF_ENHMETAFILE
, "cf %08x\n", cf
);
648 data
= GetClipboardData(cf
);
649 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
651 cf
= EnumClipboardFormats(cf
);
652 ok(cf
== CF_LOCALE
, "cf %08x\n", cf
);
653 data
= GetClipboardData(cf
);
654 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
656 cf
= EnumClipboardFormats(cf
);
657 ok(cf
== CF_OEMTEXT
, "cf %08x\n", cf
);
658 data
= GetClipboardData(cf
);
659 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
661 cf
= EnumClipboardFormats(cf
);
662 ok(cf
== CF_UNICODETEXT
, "cf %08x\n", cf
);
664 cf
= EnumClipboardFormats(cf
);
665 ok(cf
== CF_METAFILEPICT
, "cf %08x\n", cf
);
666 data
= GetClipboardData(cf
);
667 ok(data
!= NULL
, "couldn't get data, cf %08x\n", cf
);
669 cf
= EnumClipboardFormats(cf
);
670 ok(cf
== 0, "cf %08x\n", cf
);
672 r
= EmptyClipboard();
673 ok(r
, "gle %d\n", GetLastError());
675 SetClipboardData( CF_UNICODETEXT
, create_textW() );
676 SetClipboardData( CF_TEXT
, create_textA() );
677 SetClipboardData( CF_OEMTEXT
, create_textA() );
678 r
= CloseClipboard();
679 ok(r
, "gle %d\n", GetLastError());
681 r
= OpenClipboard( NULL
);
682 ok(r
, "gle %d\n", GetLastError());
683 SetLastError( 0xdeadbeef );
684 cf
= EnumClipboardFormats(0);
685 ok( cf
== CF_UNICODETEXT
, "cf %08x\n", cf
);
686 ok( GetLastError() == ERROR_SUCCESS
, "wrong error %u\n", GetLastError() );
687 SetLastError( 0xdeadbeef );
688 cf
= EnumClipboardFormats(cf
);
689 ok( cf
== CF_TEXT
, "cf %08x\n", cf
);
690 ok( GetLastError() == ERROR_SUCCESS
, "wrong error %u\n", GetLastError() );
691 SetLastError( 0xdeadbeef );
692 cf
= EnumClipboardFormats(cf
);
693 ok( cf
== CF_OEMTEXT
, "cf %08x\n", cf
);
694 ok( GetLastError() == ERROR_SUCCESS
, "wrong error %u\n", GetLastError() );
695 SetLastError( 0xdeadbeef );
696 cf
= EnumClipboardFormats(cf
);
697 ok( cf
== CF_LOCALE
, "cf %08x\n", cf
);
698 ok( GetLastError() == ERROR_SUCCESS
, "wrong error %u\n", GetLastError() );
699 SetLastError( 0xdeadbeef );
700 cf
= EnumClipboardFormats( cf
);
701 ok( cf
== 0, "cf %08x\n", cf
);
702 ok( GetLastError() == ERROR_SUCCESS
, "wrong error %u\n", GetLastError() );
703 SetLastError( 0xdeadbeef );
704 cf
= EnumClipboardFormats( 0xdead );
705 ok( cf
== 0, "cf %08x\n", cf
);
706 ok( GetLastError() == ERROR_SUCCESS
, "wrong error %u\n", GetLastError() );
708 r
= EmptyClipboard();
709 ok(r
, "gle %d\n", GetLastError());
711 r
= CloseClipboard();
712 ok(r
, "gle %d\n", GetLastError());
714 for (i
= 0; i
< ARRAY_SIZE(tests
); i
++)
716 r
= OpenClipboard(NULL
);
717 ok(r
, "%u: gle %d\n", i
, GetLastError());
718 r
= EmptyClipboard();
719 ok(r
, "%u: gle %d\n", i
, GetLastError());
721 switch (tests
[i
].format
)
725 SetClipboardData( tests
[i
].format
, create_textA() );
728 SetClipboardData( CF_UNICODETEXT
, create_textW() );
731 SetClipboardData( CF_ENHMETAFILE
, create_emf() );
733 case CF_METAFILEPICT
:
734 SetClipboardData( CF_METAFILEPICT
, create_metafile() );
737 SetClipboardData( CF_BITMAP
, create_bitmap() );
741 SetClipboardData( tests
[i
].format
, create_dib( tests
[i
].format
== CF_DIBV5
));
745 count
= CountClipboardFormats();
746 ok( count
== 1, "%u: count %u\n", i
, count
);
748 r
= CloseClipboard();
749 ok(r
, "%u: gle %d\n", i
, GetLastError());
751 count
= CountClipboardFormats();
752 for (j
= 0; tests
[i
].expected
[j
]; j
++)
754 r
= IsClipboardFormatAvailable( tests
[i
].expected
[j
] );
755 ok( r
, "%u: %04x not available\n", i
, tests
[i
].expected
[j
] );
757 ok( count
== j
, "%u: count %u instead of %u\n", i
, count
, j
);
759 r
= OpenClipboard( hwnd
);
760 ok(r
, "%u: gle %d\n", i
, GetLastError());
762 for (j
= 0; tests
[i
].expected
[j
]; j
++)
764 cf
= EnumClipboardFormats( cf
);
765 ok(cf
== tests
[i
].expected
[j
], "%u.%u: got %04x instead of %04x\n",
766 i
, j
, cf
, tests
[i
].expected
[j
] );
767 if (cf
!= tests
[i
].expected
[j
]) break;
768 old_seq
= GetClipboardSequenceNumber();
769 data
= GetClipboardData( cf
);
771 broken( tests
[i
].format
== CF_DIBV5
&& cf
== CF_DIB
), /* >= Vista */
772 "%u: couldn't get data, cf %04x err %d\n", i
, cf
, GetLastError());
773 seq
= GetClipboardSequenceNumber();
774 ok(seq
== old_seq
, "sequence changed (test %d %d)\n", i
, cf
);
779 UINT
*ptr
= GlobalLock( data
);
780 ok( GlobalSize( data
) == sizeof(*ptr
), "%u: size %lu\n", i
, GlobalSize( data
));
781 ok( *ptr
== GetUserDefaultLCID() ||
782 broken( *ptr
== MAKELANGID( LANG_ENGLISH
, SUBLANG_DEFAULT
)),
783 "%u: CF_LOCALE %08x/%08x\n", i
, *ptr
, GetUserDefaultLCID() );
784 GlobalUnlock( data
);
789 ok( GlobalSize( data
) == 10, "wrong len %ld\n", GlobalSize( data
));
792 ok( GlobalSize( data
) == 10 * sizeof(WCHAR
), "wrong len %ld\n", GlobalSize( data
));
796 if (!tests
[i
].expected
[j
])
798 cf
= EnumClipboardFormats( cf
);
799 ok(cf
== 0, "%u: cf %04x\n", i
, cf
);
802 /* now with delayed rendering */
804 r
= EmptyClipboard();
805 ok(r
, "%u: gle %d\n", i
, GetLastError());
807 rendered
= SendMessageA( hwnd
, WM_USER
, 0, 0 );
808 ok( !rendered
, "%u: formats %08x have been rendered\n", i
, rendered
);
810 SetClipboardData( tests
[i
].format
, 0 );
811 rendered
= SendMessageA( hwnd
, WM_USER
, 0, 0 );
812 ok( !rendered
, "%u: formats %08x have been rendered\n", i
, rendered
);
814 count
= CountClipboardFormats();
815 ok( count
== 1, "%u: count %u\n", i
, count
);
817 r
= CloseClipboard();
818 ok(r
, "%u: gle %d\n", i
, GetLastError());
819 rendered
= SendMessageA( hwnd
, WM_USER
, 0, 0 );
820 ok( !rendered
, "%u: formats %08x have been rendered\n", i
, rendered
);
822 count
= CountClipboardFormats();
823 for (j
= 0; tests
[i
].expected
[j
]; j
++)
825 r
= IsClipboardFormatAvailable( tests
[i
].expected
[j
] );
826 ok( r
, "%u: %04x not available\n", i
, tests
[i
].expected
[j
] );
828 ok( count
== j
, "%u: count %u instead of %u\n", i
, count
, j
);
829 rendered
= SendMessageA( hwnd
, WM_USER
, 0, 0 );
830 ok( !rendered
, "%u: formats %08x have been rendered\n", i
, rendered
);
832 r
= OpenClipboard(NULL
);
833 ok(r
, "%u: gle %d\n", i
, GetLastError());
835 for (j
= 0; tests
[i
].expected
[j
]; j
++)
837 cf
= EnumClipboardFormats( cf
);
838 ok(cf
== tests
[i
].expected
[j
], "%u.%u: got %04x instead of %04x\n",
839 i
, j
, cf
, tests
[i
].expected
[j
] );
840 if (cf
!= tests
[i
].expected
[j
]) break;
841 rendered
= SendMessageA( hwnd
, WM_USER
, 0, 0 );
842 ok( !rendered
, "%u.%u: formats %08x have been rendered\n", i
, j
, rendered
);
843 data
= GetClipboardData( cf
);
844 rendered
= SendMessageA( hwnd
, WM_USER
, 0, 0 );
847 ok(data
!= NULL
, "%u: CF_LOCALE no data\n", i
);
848 ok( !rendered
, "%u.%u: formats %08x have been rendered\n", i
, j
, rendered
);
852 ok(!data
, "%u: format %04x got data %p\n", i
, cf
, data
);
853 ok( rendered
== (1 << tests
[i
].format
),
854 "%u.%u: formats %08x have been rendered\n", i
, j
, rendered
);
855 /* try to render a second time */
856 data
= GetClipboardData( cf
);
857 rendered
= SendMessageA( hwnd
, WM_USER
, 0, 0 );
858 ok( rendered
== (1 << tests
[i
].format
),
859 "%u.%u: formats %08x have been rendered\n", i
, j
, rendered
);
862 if (!tests
[i
].expected
[j
])
864 cf
= EnumClipboardFormats( cf
);
865 ok(cf
== 0, "%u: cf %04x\n", i
, cf
);
867 r
= CloseClipboard();
868 ok(r
, "%u: gle %d\n", i
, GetLastError());
869 rendered
= SendMessageA( hwnd
, WM_USER
, 0, 0 );
870 ok( !rendered
, "%u: formats %08x have been rendered\n", i
, rendered
);
873 r
= OpenClipboard(NULL
);
874 ok(r
, "gle %d\n", GetLastError());
875 r
= EmptyClipboard();
876 ok(r
, "gle %d\n", GetLastError());
877 r
= CloseClipboard();
878 ok(r
, "gle %d\n", GetLastError());
879 DestroyWindow( hwnd
);
882 static DWORD WINAPI
clipboard_render_data_thread(void *param
)
884 HANDLE handle
= SetClipboardData( CF_UNICODETEXT
, create_textW() );
885 ok( handle
!= 0, "SetClipboardData failed: %d\n", GetLastError() );
889 static CRITICAL_SECTION clipboard_cs
;
890 static HWND next_wnd
;
891 static UINT wm_drawclipboard
;
892 static UINT wm_clipboardupdate
;
893 static UINT wm_destroyclipboard
;
894 static UINT wm_renderformat
;
895 static UINT nb_formats
;
896 static BOOL cross_thread
;
897 static BOOL do_render_format
;
898 static HANDLE update_event
;
900 static LRESULT CALLBACK
clipboard_wnd_proc(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
903 DWORD msg_flags
= InSendMessageEx( NULL
);
906 case WM_DRAWCLIPBOARD
:
907 ok( msg_flags
== (cross_thread
? ISMEX_NOTIFY
: ISMEX_NOSEND
),
908 "WM_DRAWCLIPBOARD wrong flags %x\n", msg_flags
);
909 EnterCriticalSection(&clipboard_cs
);
911 LeaveCriticalSection(&clipboard_cs
);
913 case WM_CHANGECBCHAIN
:
914 ok( msg_flags
== (cross_thread
? ISMEX_SEND
: ISMEX_NOSEND
),
915 "WM_CHANGECBCHAIN wrong flags %x\n", msg_flags
);
916 if (next_wnd
== (HWND
)wp
)
919 SendMessageA(next_wnd
, msg
, wp
, lp
);
921 case WM_DESTROYCLIPBOARD
:
922 ok( msg_flags
== (cross_thread
? ISMEX_SEND
: ISMEX_NOSEND
),
923 "WM_DESTROYCLIPBOARD wrong flags %x\n", msg_flags
);
924 wm_destroyclipboard
++;
925 ok( GetClipboardOwner() == hwnd
, "WM_DESTROYCLIPBOARD owner %p\n", GetClipboardOwner() );
926 nb_formats
= CountClipboardFormats();
928 case WM_RENDERFORMAT
:
929 ok( !wm_renderformat
, "multiple WM_RENDERFORMAT %04x / %04lx\n", wm_renderformat
, wp
);
930 wm_renderformat
= wp
;
932 if (do_render_format
)
937 old_seq
= GetClipboardSequenceNumber();
938 handle
= SetClipboardData( CF_TEXT
, create_textA() );
939 ok( handle
!= 0, "SetClipboardData failed: %d\n", GetLastError() );
940 seq
= GetClipboardSequenceNumber();
941 ok( seq
== old_seq
, "sequence changed\n" );
944 handle
= CreateThread( NULL
, 0, clipboard_render_data_thread
, NULL
, 0, NULL
);
945 ok( handle
!= NULL
, "CreateThread failed: %d\n", GetLastError() );
946 ok( WaitForSingleObject(handle
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n" );
947 CloseHandle( handle
);
948 seq
= GetClipboardSequenceNumber();
949 ok( seq
== old_seq
, "sequence changed\n" );
953 case WM_CLIPBOARDUPDATE
:
954 ok( msg_flags
== ISMEX_NOSEND
, "WM_CLIPBOARDUPDATE wrong flags %x\n", msg_flags
);
955 EnterCriticalSection(&clipboard_cs
);
956 wm_clipboardupdate
++;
957 SetEvent(update_event
);
958 LeaveCriticalSection(&clipboard_cs
);
961 ChangeClipboardChain(hwnd
, next_wnd
);
965 ret
= wm_drawclipboard
;
966 wm_drawclipboard
= 0;
969 ret
= wm_clipboardupdate
;
970 wm_clipboardupdate
= 0;
973 ret
= wm_destroyclipboard
;
974 wm_destroyclipboard
= 0;
977 ret
= wm_renderformat
;
984 return DefWindowProcA(hwnd
, msg
, wp
, lp
);
987 static void get_clipboard_data_process(void)
992 r
= OpenClipboard(0);
993 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
994 data
= GetClipboardData( CF_UNICODETEXT
);
995 ok( data
!= NULL
, "GetClipboardData failed: %d\n", GetLastError());
996 r
= CloseClipboard();
997 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
1000 static UINT old_seq
;
1002 static void check_messages_(int line
, HWND win
, UINT seq_diff
, UINT draw
, UINT update
, UINT destroy
, UINT render
)
1005 UINT count
, fmt
, seq
;
1007 seq
= GetClipboardSequenceNumber();
1008 ok_(__FILE__
, line
)(seq
- old_seq
== seq_diff
, "sequence diff %d\n", seq
- old_seq
);
1013 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
1016 if (update
&& !broken(!pAddClipboardFormatListener
))
1017 ok(WaitForSingleObject(update_event
, 1000) == WAIT_OBJECT_0
, "wait failed\n");
1019 count
= SendMessageA( win
, WM_USER
+ 1, 0, 0 );
1020 ok_(__FILE__
, line
)(count
== draw
, "WM_DRAWCLIPBOARD %sreceived\n", draw
? "not " : "");
1021 count
= SendMessageA( win
, WM_USER
+ 2, 0, 0 );
1022 ok_(__FILE__
, line
)(count
== update
|| broken(!pAddClipboardFormatListener
),
1023 "WM_CLIPBOARDUPDATE %sreceived\n", update
? "not " : "");
1024 count
= SendMessageA( win
, WM_USER
+ 3, 0, 0 );
1025 ok_(__FILE__
, line
)(count
== destroy
, "WM_DESTROYCLIPBOARD %sreceived\n", destroy
? "not " : "");
1026 fmt
= SendMessageA( win
, WM_USER
+ 4, 0, 0 );
1027 ok_(__FILE__
, line
)(fmt
== render
, "WM_RENDERFORMAT received %04x, expected %04x\n", fmt
, render
);
1029 #define check_messages(a,b,c,d,e,f) check_messages_(__LINE__,a,b,c,d,e,f)
1031 static DWORD WINAPI
clipboard_thread(void *param
)
1033 HWND ret
, win
= param
;
1037 UINT count
, fmt
, formats
;
1039 cross_thread
= (GetWindowThreadProcessId( win
, NULL
) != GetCurrentThreadId());
1040 trace( "%s-threaded test\n", cross_thread
? "multi" : "single" );
1042 old_seq
= GetClipboardSequenceNumber();
1044 EnterCriticalSection(&clipboard_cs
);
1045 SetLastError(0xdeadbeef);
1046 next_wnd
= SetClipboardViewer(win
);
1047 ok(GetLastError() == 0xdeadbeef, "GetLastError = %d\n", GetLastError());
1048 LeaveCriticalSection(&clipboard_cs
);
1050 SetLastError( 0xdeadbeef );
1051 ret
= SetClipboardViewer( (HWND
)0xdead );
1052 ok( !ret
, "SetClipboardViewer succeeded\n" );
1053 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %u\n", GetLastError() );
1054 SetLastError( 0xdeadbeef );
1055 r
= ChangeClipboardChain( win
, (HWND
)0xdead );
1056 ok( !r
, "ChangeClipboardChain succeeded\n" );
1057 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %u\n", GetLastError() );
1058 SetLastError( 0xdeadbeef );
1059 r
= ChangeClipboardChain( (HWND
)0xdead, next_wnd
);
1060 ok( !r
, "ChangeClipboardChain succeeded\n" );
1061 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %u\n", GetLastError() );
1063 if (pAddClipboardFormatListener
)
1065 r
= pAddClipboardFormatListener(win
);
1066 ok( r
, "AddClipboardFormatListener failed err %d\n", GetLastError());
1067 SetLastError( 0xdeadbeef );
1068 r
= pAddClipboardFormatListener( win
);
1069 ok( !r
, "AddClipboardFormatListener succeeded\n" );
1070 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1071 SetLastError( 0xdeadbeef );
1072 r
= pAddClipboardFormatListener( (HWND
)0xdead );
1073 ok( !r
, "AddClipboardFormatListener succeeded\n" );
1074 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %u\n", GetLastError() );
1075 r
= pAddClipboardFormatListener( GetDesktopWindow() );
1076 ok( r
, "AddClipboardFormatListener failed err %d\n", GetLastError());
1077 r
= pRemoveClipboardFormatListener( GetDesktopWindow() );
1078 ok( r
, "RemoveClipboardFormatListener failed err %d\n", GetLastError());
1081 check_messages(win
, 0, 1, 0, 0, 0);
1083 SetLastError( 0xdeadbeef );
1084 r
= OpenClipboard( (HWND
)0xdead );
1085 ok( !r
, "OpenClipboard succeeded\n" );
1086 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %u\n", GetLastError() );
1088 r
= OpenClipboard(win
);
1089 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
1091 check_messages(win
, 0, 0, 0, 0, 0);
1093 r
= EmptyClipboard();
1094 ok(r
, "EmptyClipboard failed: %d\n", GetLastError());
1096 check_messages(win
, 1, 0, 0, 0, 0);
1098 r
= EmptyClipboard();
1099 ok(r
, "EmptyClipboard failed: %d\n", GetLastError());
1100 /* sequence changes again, even though it was already empty */
1101 check_messages(win
, 1, 0, 0, 1, 0);
1102 count
= SendMessageA( win
, WM_USER
+5, 0, 0 );
1103 ok( !count
, "wrong format count %u on WM_DESTROYCLIPBOARD\n", count
);
1105 handle
= SetClipboardData( CF_TEXT
, create_textA() );
1106 ok(handle
!= 0, "SetClipboardData failed: %d\n", GetLastError());
1108 check_messages(win
, 1, 0, 0, 0, 0);
1110 SetClipboardData( CF_UNICODETEXT
, 0 );
1112 check_messages(win
, 1, 0, 0, 0, 0);
1114 SetClipboardData( CF_UNICODETEXT
, 0 ); /* same data again */
1116 check_messages(win
, 1, 0, 0, 0, 0);
1118 ok( IsClipboardFormatAvailable( CF_TEXT
), "CF_TEXT available\n" );
1119 ok( IsClipboardFormatAvailable( CF_UNICODETEXT
), "CF_UNICODETEXT available\n" );
1120 ok( !IsClipboardFormatAvailable( CF_OEMTEXT
), "CF_OEMTEXT available\n" );
1122 EnterCriticalSection(&clipboard_cs
);
1123 r
= CloseClipboard();
1124 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
1125 LeaveCriticalSection(&clipboard_cs
);
1127 check_messages(win
, 2, 1, 1, 0, 0);
1129 r
= OpenClipboard(win
);
1130 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
1132 check_messages(win
, 0, 0, 0, 0, 0);
1134 ok( IsClipboardFormatAvailable( CF_TEXT
), "CF_TEXT available\n" );
1135 ok( IsClipboardFormatAvailable( CF_UNICODETEXT
), "CF_UNICODETEXT available\n" );
1136 ok( IsClipboardFormatAvailable( CF_OEMTEXT
), "CF_OEMTEXT available\n" );
1138 ok( GetClipboardOwner() == win
, "wrong owner %p\n", GetClipboardOwner());
1139 handle
= GetClipboardData( CF_UNICODETEXT
);
1140 ok( !handle
, "got data for CF_UNICODETEXT\n" );
1141 fmt
= SendMessageA( win
, WM_USER
+4, 0, 0 );
1142 ok( fmt
== CF_UNICODETEXT
, "WM_RENDERFORMAT received %04x\n", fmt
);
1144 do_render_format
= TRUE
;
1145 handle
= GetClipboardData( CF_OEMTEXT
);
1146 ok( handle
!= NULL
, "didn't get data for CF_OEMTEXT\n" );
1147 fmt
= SendMessageA( win
, WM_USER
+4, 0, 0 );
1148 ok( fmt
== CF_UNICODETEXT
, "WM_RENDERFORMAT received %04x\n", fmt
);
1149 do_render_format
= FALSE
;
1151 SetClipboardData( CF_WAVE
, 0 );
1152 check_messages(win
, 1, 0, 0, 0, 0);
1154 r
= CloseClipboard();
1155 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
1156 /* no synthesized format, so CloseClipboard doesn't change the sequence */
1157 check_messages(win
, 0, 1, 1, 0, 0);
1159 r
= OpenClipboard(win
);
1160 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
1161 r
= CloseClipboard();
1162 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
1163 /* nothing changed */
1164 check_messages(win
, 0, 0, 0, 0, 0);
1166 formats
= CountClipboardFormats();
1167 r
= OpenClipboard(0);
1168 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
1169 r
= EmptyClipboard();
1170 ok(r
, "EmptyClipboard failed: %d\n", GetLastError());
1171 r
= CloseClipboard();
1172 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
1174 check_messages(win
, 1, 1, 1, 1, 0);
1175 count
= SendMessageA( win
, WM_USER
+5, 0, 0 );
1176 ok( count
== formats
, "wrong format count %u on WM_DESTROYCLIPBOARD\n", count
);
1178 r
= OpenClipboard(win
);
1179 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
1180 SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_FIXED
, 1 ));
1181 check_messages(win
, 1, 0, 0, 0, 0);
1183 EnterCriticalSection(&clipboard_cs
);
1184 r
= CloseClipboard();
1185 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
1186 LeaveCriticalSection(&clipboard_cs
);
1188 check_messages(win
, 0, 1, 1, 0, 0);
1190 run_process( "grab_clipboard 0" );
1194 /* in this case we get a cross-thread WM_DRAWCLIPBOARD */
1195 cross_thread
= TRUE
;
1196 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
1197 cross_thread
= FALSE
;
1199 check_messages(win
, 1, 1, 1, 0, 0);
1201 r
= OpenClipboard(0);
1202 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
1203 SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_FIXED
, 1 ));
1204 check_messages(win
, 1, 0, 0, 0, 0);
1206 EnterCriticalSection(&clipboard_cs
);
1207 r
= CloseClipboard();
1208 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
1209 LeaveCriticalSection(&clipboard_cs
);
1211 check_messages(win
, 0, 1, 1, 0, 0);
1213 run_process( "grab_clipboard 1" );
1217 /* in this case we get a cross-thread WM_DRAWCLIPBOARD */
1218 cross_thread
= TRUE
;
1219 while (PeekMessageW( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW( &msg
);
1220 cross_thread
= FALSE
;
1222 check_messages(win
, 2, 1, 1, 0, 0);
1224 r
= OpenClipboard(0);
1225 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
1226 SetClipboardData( CF_WAVE
, GlobalAlloc( GMEM_FIXED
, 1 ));
1227 check_messages(win
, 1, 0, 0, 0, 0);
1229 EnterCriticalSection(&clipboard_cs
);
1230 r
= CloseClipboard();
1231 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
1232 LeaveCriticalSection(&clipboard_cs
);
1234 check_messages(win
, 0, 1, 1, 0, 0);
1238 r
= OpenClipboard( win
);
1239 ok(r
, "OpenClipboard failed: %d\n", GetLastError());
1240 r
= EmptyClipboard();
1241 ok(r
, "EmptyClipboard failed: %d\n", GetLastError());
1242 SetClipboardData( CF_TEXT
, 0 );
1243 r
= CloseClipboard();
1244 ok(r
, "CloseClipboard failed: %d\n", GetLastError());
1246 do_render_format
= TRUE
;
1247 old_seq
= GetClipboardSequenceNumber();
1248 run_process( "get_clipboard_data" );
1249 do_render_format
= FALSE
;
1251 check_messages(win
, 0, 1, 1, 0, CF_TEXT
);
1254 r
= PostMessageA(win
, WM_USER
, 0, 0);
1255 ok(r
, "PostMessage failed: %d\n", GetLastError());
1257 if (pRemoveClipboardFormatListener
)
1259 r
= pRemoveClipboardFormatListener(win
);
1260 ok( r
, "RemoveClipboardFormatListener failed err %d\n", GetLastError());
1261 SetLastError( 0xdeadbeef );
1262 r
= pRemoveClipboardFormatListener(win
);
1263 ok( !r
, "RemoveClipboardFormatListener succeeded\n" );
1264 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
1265 SetLastError( 0xdeadbeef );
1266 r
= pRemoveClipboardFormatListener( (HWND
)0xdead );
1267 ok( !r
, "RemoveClipboardFormatListener succeeded\n" );
1268 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE
, "wrong error %u\n", GetLastError() );
1273 static void test_messages(void)
1281 InitializeCriticalSection(&clipboard_cs
);
1282 update_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1284 memset(&cls
, 0, sizeof(cls
));
1285 cls
.lpfnWndProc
= clipboard_wnd_proc
;
1286 cls
.hInstance
= GetModuleHandleA(NULL
);
1287 cls
.lpszClassName
= "clipboard_test";
1288 RegisterClassA(&cls
);
1290 win
= CreateWindowA("clipboard_test", NULL
, 0, 0, 0, 0, 0, NULL
, 0, NULL
, 0);
1291 ok(win
!= NULL
, "CreateWindow failed: %d\n", GetLastError());
1293 thread
= CreateThread(NULL
, 0, clipboard_thread
, (void*)win
, 0, &tid
);
1294 ok(thread
!= NULL
, "CreateThread failed: %d\n", GetLastError());
1296 while(GetMessageA(&msg
, NULL
, 0, 0))
1298 ok( msg
.message
!= WM_DRAWCLIPBOARD
, "WM_DRAWCLIPBOARD was posted\n" );
1299 TranslateMessage(&msg
);
1300 DispatchMessageA(&msg
);
1303 ok(WaitForSingleObject(thread
, INFINITE
) == WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
1304 CloseHandle(thread
);
1306 DestroyWindow( win
);
1308 /* same tests again but inside a single thread */
1310 win
= CreateWindowA( "clipboard_test", NULL
, 0, 0, 0, 0, 0, NULL
, 0, NULL
, 0 );
1311 ok( win
!= NULL
, "CreateWindow failed: %d\n", GetLastError() );
1313 clipboard_thread( win
);
1314 DestroyWindow( win
);
1316 UnregisterClassA("clipboard_test", GetModuleHandleA(NULL
));
1317 DeleteCriticalSection(&clipboard_cs
);
1320 static BOOL
is_moveable( HANDLE handle
)
1322 void *ptr
= GlobalLock( handle
);
1323 if (ptr
) GlobalUnlock( handle
);
1324 return ptr
&& ptr
!= handle
;
1327 static BOOL
is_fixed( HANDLE handle
)
1329 void *ptr
= GlobalLock( handle
);
1330 if (ptr
) GlobalUnlock( handle
);
1331 return ptr
&& ptr
== handle
;
1334 static BOOL
is_freed( HANDLE handle
)
1336 return !GlobalSize( handle
);
1339 static UINT format_id
;
1340 static HBITMAP bitmap
, bitmap2
;
1341 static HPALETTE palette
;
1342 static const LOGPALETTE logpalette
= { 0x300, 1, {{ 0x12, 0x34, 0x56, 0x78 }}};
1344 static void test_handles( HWND hwnd
)
1346 HGLOBAL h
, htext
, htext2
, htext3
, htext4
, htext5
;
1347 HGLOBAL hfixed
, hfixed2
, hmoveable
, empty_fixed
, empty_moveable
;
1349 UINT format_id2
= RegisterClipboardFormatA( "another format" );
1352 HBITMAP bitmap_temp
;
1354 BOOL is_owner
= (GetWindowThreadProcessId( hwnd
, &process
) && process
== GetCurrentProcessId());
1356 trace( "hwnd %p\n", hwnd
);
1357 htext
= create_textA();
1358 htext2
= create_textA();
1359 htext3
= create_textA();
1360 htext4
= create_textA();
1361 htext5
= create_textA();
1362 bitmap
= CreateBitmap( 10, 10, 1, 1, NULL
);
1363 bitmap2
= CreateBitmap( 10, 10, 1, 1, NULL
);
1364 palette
= CreatePalette( &logpalette
);
1366 hfixed
= GlobalAlloc( GMEM_FIXED
, 17 );
1367 hfixed2
= GlobalAlloc( GMEM_FIXED
, 17 );
1368 ok( is_fixed( hfixed
), "expected fixed mem %p\n", hfixed
);
1369 ok( GlobalSize( hfixed
) == 17, "wrong size %lu\n", GlobalSize( hfixed
));
1371 hmoveable
= GlobalAlloc( GMEM_MOVEABLE
, 23 );
1372 ok( is_moveable( hmoveable
), "expected moveable mem %p\n", hmoveable
);
1373 ok( GlobalSize( hmoveable
) == 23, "wrong size %lu\n", GlobalSize( hmoveable
));
1375 empty_fixed
= GlobalAlloc( GMEM_FIXED
, 0 );
1376 ok( is_fixed( empty_fixed
), "expected fixed mem %p\n", empty_fixed
);
1378 empty_moveable
= GlobalAlloc( GMEM_MOVEABLE
, 0 );
1379 /* discarded handles can't be GlobalLock'ed */
1380 ok( is_freed( empty_moveable
), "expected free mem %p\n", empty_moveable
);
1382 r
= OpenClipboard( hwnd
);
1383 ok( r
, "gle %d\n", GetLastError() );
1384 r
= EmptyClipboard();
1385 ok( r
, "gle %d\n", GetLastError() );
1387 h
= SetClipboardData( CF_TEXT
, htext
);
1388 ok( h
== htext
, "got %p\n", h
);
1389 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1390 h
= SetClipboardData( format_id
, htext2
);
1391 ok( h
== htext2
, "got %p\n", h
);
1392 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1393 bitmap_temp
= CreateBitmap( 10, 10, 1, 1, NULL
);
1394 h
= SetClipboardData( CF_BITMAP
, bitmap_temp
);
1395 ok( h
== bitmap_temp
, "got %p\n", h
);
1396 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1397 h
= SetClipboardData( CF_BITMAP
, bitmap
);
1398 ok( h
== bitmap
, "got %p\n", h
);
1399 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1400 h
= SetClipboardData( CF_DSPBITMAP
, bitmap2
);
1401 ok( h
== bitmap2
, "got %p\n", h
);
1402 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1403 h
= SetClipboardData( CF_PALETTE
, palette
);
1404 ok( h
== palette
, "got %p\n", h
);
1405 ok( GetObjectType( h
) == OBJ_PAL
, "expected palette %p\n", h
);
1406 h
= SetClipboardData( CF_GDIOBJFIRST
+ 3, htext3
);
1407 ok( h
== htext3
, "got %p\n", h
);
1408 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1409 h
= SetClipboardData( CF_PRIVATEFIRST
+ 7, htext5
);
1410 ok( h
== htext5
, "got %p\n", h
);
1411 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1412 h
= SetClipboardData( format_id2
, empty_moveable
);
1413 ok( !h
, "got %p\n", h
);
1414 GlobalFree( empty_moveable
);
1416 if (0) /* crashes on vista64 */
1418 ptr
= HeapAlloc( GetProcessHeap(), 0, 0 );
1419 h
= SetClipboardData( format_id2
, ptr
);
1420 ok( !h
, "got %p\n", h
);
1421 HeapFree( GetProcessHeap(), 0, ptr
);
1424 h
= SetClipboardData( format_id2
, empty_fixed
);
1425 ok( h
== empty_fixed
, "got %p\n", h
);
1426 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1427 h
= SetClipboardData( 0xdeadbeef, hfixed2
);
1428 ok( h
== hfixed2
, "got %p\n", h
);
1429 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1430 h
= SetClipboardData( 0xdeadbabe, hmoveable
);
1431 ok( h
== hmoveable
, "got %p\n", h
);
1432 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1434 ptr
= HeapAlloc( GetProcessHeap(), 0, 37 );
1435 h
= SetClipboardData( 0xdeadfade, ptr
);
1436 ok( h
== ptr
|| !h
, "got %p\n", h
);
1437 if (!h
) /* heap blocks are rejected on >= win8 */
1439 HeapFree( GetProcessHeap(), 0, ptr
);
1443 data
= GetClipboardData( CF_TEXT
);
1444 ok( data
== htext
, "wrong data %p\n", data
);
1445 ok( is_moveable( data
), "expected moveable mem %p\n", data
);
1447 data
= GetClipboardData( format_id
);
1448 ok( data
== htext2
, "wrong data %p, cf %08x\n", data
, format_id
);
1449 ok( is_moveable( data
), "expected moveable mem %p\n", data
);
1451 data
= GetClipboardData( CF_GDIOBJFIRST
+ 3 );
1452 ok( data
== htext3
, "wrong data %p\n", data
);
1453 ok( is_moveable( data
), "expected moveable mem %p\n", data
);
1455 data
= GetClipboardData( CF_PRIVATEFIRST
+ 7 );
1456 ok( data
== htext5
, "wrong data %p\n", data
);
1457 ok( is_moveable( data
), "expected moveable mem %p\n", data
);
1459 data
= GetClipboardData( format_id2
);
1460 ok( data
== empty_fixed
, "wrong data %p\n", data
);
1461 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1463 data
= GetClipboardData( 0xdeadbeef );
1464 ok( data
== hfixed2
, "wrong data %p\n", data
);
1465 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1467 data
= GetClipboardData( 0xdeadbabe );
1468 ok( data
== hmoveable
, "wrong data %p\n", data
);
1469 ok( is_moveable( data
), "expected moveable mem %p\n", data
);
1471 data
= GetClipboardData( 0xdeadfade );
1472 ok( data
== ptr
, "wrong data %p\n", data
);
1474 h
= SetClipboardData( CF_PRIVATEFIRST
+ 7, htext4
);
1475 ok( h
== htext4
, "got %p\n", h
);
1476 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1477 ok( is_freed( htext5
), "expected freed mem %p\n", htext5
);
1479 h
= SetClipboardData( 0xdeadbeef, hfixed
);
1480 ok( h
== hfixed
, "got %p\n", h
);
1481 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1482 if (0) /* this test is unreliable / crashes */
1483 ok( is_freed( hfixed2
), "expected freed mem %p\n", hfixed2
);
1485 r
= CloseClipboard();
1486 ok( r
, "gle %d\n", GetLastError() );
1488 /* data handles are still valid */
1489 ok( is_moveable( htext
), "expected moveable mem %p\n", htext
);
1490 ok( is_moveable( htext2
), "expected moveable mem %p\n", htext2
);
1491 ok( is_moveable( htext3
), "expected moveable mem %p\n", htext3
);
1492 ok( is_moveable( htext4
), "expected moveable mem %p\n", htext4
);
1493 ok( GetObjectType( bitmap
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap
);
1494 ok( GetObjectType( bitmap2
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap2
);
1495 ok( GetObjectType( palette
) == OBJ_PAL
, "expected palette %p\n", palette
);
1496 ok( is_fixed( hfixed
), "expected fixed mem %p\n", hfixed
);
1497 ok( is_moveable( hmoveable
), "expected moveable mem %p\n", hmoveable
);
1498 ok( is_fixed( empty_fixed
), "expected fixed mem %p\n", empty_fixed
);
1500 r
= OpenClipboard( hwnd
);
1501 ok( r
, "gle %d\n", GetLastError() );
1503 /* and now they are freed, unless we are the owner */
1506 ok( is_freed( htext
), "expected freed mem %p\n", htext
);
1507 ok( is_freed( htext2
), "expected freed mem %p\n", htext2
);
1508 ok( is_freed( htext3
), "expected freed mem %p\n", htext3
);
1509 ok( is_freed( htext4
), "expected freed mem %p\n", htext4
);
1510 ok( is_freed( hmoveable
), "expected freed mem %p\n", hmoveable
);
1512 data
= GetClipboardData( CF_TEXT
);
1513 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1515 data
= GetClipboardData( format_id
);
1516 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1518 data
= GetClipboardData( CF_GDIOBJFIRST
+ 3 );
1519 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1521 data
= GetClipboardData( CF_PRIVATEFIRST
+ 7 );
1522 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1524 data
= GetClipboardData( format_id2
);
1525 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1526 ok( GlobalSize( data
) == 1, "wrong size %lu\n", GlobalSize( data
));
1528 data
= GetClipboardData( 0xdeadbeef );
1529 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1530 ok( GlobalSize( data
) == 17, "wrong size %lu\n", GlobalSize( data
));
1532 data
= GetClipboardData( 0xdeadbabe );
1533 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1534 ok( GlobalSize( data
) == 23, "wrong size %lu\n", GlobalSize( data
));
1536 data
= GetClipboardData( 0xdeadfade );
1537 ok( is_fixed( data
) || !ptr
, "expected fixed mem %p\n", data
);
1538 if (ptr
) ok( GlobalSize( data
) == 37, "wrong size %lu\n", GlobalSize( data
));
1542 ok( is_moveable( htext
), "expected moveable mem %p\n", htext
);
1543 ok( is_moveable( htext2
), "expected moveable mem %p\n", htext2
);
1544 ok( is_moveable( htext3
), "expected moveable mem %p\n", htext3
);
1545 ok( is_moveable( htext4
), "expected moveable mem %p\n", htext4
);
1546 ok( is_moveable( hmoveable
), "expected moveable mem %p\n", hmoveable
);
1548 data
= GetClipboardData( CF_TEXT
);
1549 ok( data
== htext
, "wrong data %p\n", data
);
1551 data
= GetClipboardData( format_id
);
1552 ok( data
== htext2
, "wrong data %p, cf %08x\n", data
, format_id
);
1554 data
= GetClipboardData( CF_GDIOBJFIRST
+ 3 );
1555 ok( data
== htext3
, "wrong data %p\n", data
);
1557 data
= GetClipboardData( CF_PRIVATEFIRST
+ 7 );
1558 ok( data
== htext4
, "wrong data %p\n", data
);
1560 data
= GetClipboardData( format_id2
);
1561 ok( data
== empty_fixed
, "wrong data %p\n", data
);
1563 data
= GetClipboardData( 0xdeadbeef );
1564 ok( data
== hfixed
, "wrong data %p\n", data
);
1566 data
= GetClipboardData( 0xdeadbabe );
1567 ok( data
== hmoveable
, "wrong data %p\n", data
);
1569 data
= GetClipboardData( 0xdeadfade );
1570 ok( data
== ptr
, "wrong data %p\n", data
);
1573 data
= GetClipboardData( CF_OEMTEXT
);
1574 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1575 data
= GetClipboardData( CF_UNICODETEXT
);
1576 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1577 data
= GetClipboardData( CF_LOCALE
);
1578 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1579 data
= GetClipboardData( CF_BITMAP
);
1580 ok( data
== bitmap
, "expected bitmap %p\n", data
);
1581 data
= GetClipboardData( CF_DSPBITMAP
);
1582 ok( data
== bitmap2
, "expected bitmap %p\n", data
);
1583 data
= GetClipboardData( CF_PALETTE
);
1584 ok( data
== palette
, "expected palette %p\n", data
);
1585 data
= GetClipboardData( CF_DIB
);
1586 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1587 data
= GetClipboardData( CF_DIBV5
);
1588 ok( is_fixed( data
), "expected fixed mem %p\n", data
);
1590 ok( GetObjectType( bitmap
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap
);
1591 ok( GetObjectType( bitmap2
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap2
);
1592 ok( GetObjectType( palette
) == OBJ_PAL
, "expected palette %p\n", palette
);
1593 ok( is_fixed( hfixed
), "expected fixed mem %p\n", hfixed
);
1594 ok( is_fixed( empty_fixed
), "expected fixed mem %p\n", empty_fixed
);
1596 r
= EmptyClipboard();
1597 ok( r
, "gle %d\n", GetLastError() );
1599 /* w2003, w2008 don't seem to free the data here */
1600 ok( is_freed( htext
) || broken( !is_freed( htext
)), "expected freed mem %p\n", htext
);
1601 ok( is_freed( htext2
) || broken( !is_freed( htext2
)), "expected freed mem %p\n", htext2
);
1602 ok( is_freed( htext3
) || broken( !is_freed( htext3
)), "expected freed mem %p\n", htext3
);
1603 ok( is_freed( htext4
) || broken( !is_freed( htext4
)), "expected freed mem %p\n", htext4
);
1604 ok( is_freed( hmoveable
) || broken( !is_freed( hmoveable
)), "expected freed mem %p\n", hmoveable
);
1605 ok( is_fixed( empty_fixed
), "expected fixed mem %p\n", empty_fixed
);
1606 ok( is_fixed( hfixed
), "expected fixed mem %p\n", hfixed
);
1608 r
= CloseClipboard();
1609 ok( r
, "gle %d\n", GetLastError() );
1612 static DWORD WINAPI
test_handles_thread( void *arg
)
1614 trace( "running from different thread\n" );
1615 test_handles( (HWND
)arg
);
1619 static DWORD WINAPI
test_handles_thread2( void *arg
)
1625 r
= OpenClipboard( 0 );
1626 ok( r
, "gle %d\n", GetLastError() );
1627 h
= GetClipboardData( CF_TEXT
);
1628 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1629 ptr
= GlobalLock( h
);
1630 if (ptr
) ok( !strcmp( "test", ptr
), "wrong data '%.5s'\n", ptr
);
1632 h
= GetClipboardData( format_id
);
1633 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1634 ptr
= GlobalLock( h
);
1635 if (ptr
) ok( !strcmp( "test", ptr
), "wrong data '%.5s'\n", ptr
);
1637 h
= GetClipboardData( CF_GDIOBJFIRST
+ 3 );
1638 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1639 ptr
= GlobalLock( h
);
1640 if (ptr
) ok( !strcmp( "test", ptr
), "wrong data '%.5s'\n", ptr
);
1642 trace( "gdiobj %p\n", h
);
1643 h
= GetClipboardData( CF_PRIVATEFIRST
+ 7 );
1644 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1645 ptr
= GlobalLock( h
);
1646 if (ptr
) ok( !strcmp( "test", ptr
), "wrong data '%.5s'\n", ptr
);
1648 trace( "private %p\n", h
);
1649 h
= GetClipboardData( CF_BITMAP
);
1650 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1651 ok( h
== bitmap
, "different bitmap %p / %p\n", h
, bitmap
);
1652 trace( "bitmap %p\n", h
);
1653 h
= GetClipboardData( CF_DSPBITMAP
);
1654 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1655 ok( h
== bitmap2
, "different bitmap %p / %p\n", h
, bitmap2
);
1656 trace( "bitmap2 %p\n", h
);
1657 h
= GetClipboardData( CF_PALETTE
);
1658 ok( GetObjectType( h
) == OBJ_PAL
, "expected palette %p\n", h
);
1659 ok( h
== palette
, "different palette %p / %p\n", h
, palette
);
1660 trace( "palette %p\n", h
);
1661 h
= GetClipboardData( CF_DIB
);
1662 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1663 h
= GetClipboardData( CF_DIBV5
);
1664 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1665 r
= CloseClipboard();
1666 ok( r
, "gle %d\n", GetLastError() );
1670 static void test_handles_process( const char *str
)
1679 format_id
= RegisterClipboardFormatA( "my_cool_clipboard_format" );
1680 r
= OpenClipboard( 0 );
1681 ok( r
, "gle %d\n", GetLastError() );
1682 h
= GetClipboardData( CF_TEXT
);
1683 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1684 ptr
= GlobalLock( h
);
1685 ok( !strcmp( str
, ptr
), "wrong data '%.5s'\n", ptr
);
1687 h
= GetClipboardData( format_id
);
1688 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1689 ptr
= GlobalLock( h
);
1690 if (ptr
) ok( !strcmp( str
, ptr
), "wrong data '%.5s'\n", ptr
);
1692 h
= GetClipboardData( CF_GDIOBJFIRST
+ 3 );
1693 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1694 ptr
= GlobalLock( h
);
1695 ok( !strcmp( str
, ptr
), "wrong data '%.5s'\n", ptr
);
1697 trace( "gdiobj %p\n", h
);
1698 h
= GetClipboardData( CF_PRIVATEFIRST
+ 7 );
1699 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1700 ptr
= GlobalLock( h
);
1701 ok( !strcmp( str
, ptr
), "wrong data '%.5s'\n", ptr
);
1703 trace( "private %p\n", h
);
1704 h
= GetClipboardData( CF_BITMAP
);
1705 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1706 ok( GetObjectW( h
, sizeof(bm
), &bm
) == sizeof(bm
), "GetObject %p failed\n", h
);
1707 ok( bm
.bmWidth
== 13 && bm
.bmHeight
== 17, "wrong bitmap %ux%u\n", bm
.bmWidth
, bm
.bmHeight
);
1708 trace( "bitmap %p\n", h
);
1709 h
= GetClipboardData( CF_DSPBITMAP
);
1710 ok( !GetObjectType( h
), "expected invalid object %p\n", h
);
1711 trace( "bitmap2 %p\n", h
);
1712 h
= GetClipboardData( CF_PALETTE
);
1713 ok( GetObjectType( h
) == OBJ_PAL
, "expected palette %p\n", h
);
1714 ok( GetPaletteEntries( h
, 0, 1, &entry
) == 1, "GetPaletteEntries %p failed\n", h
);
1715 ok( entry
.peRed
== 0x12 && entry
.peGreen
== 0x34 && entry
.peBlue
== 0x56,
1716 "wrong color %02x,%02x,%02x\n", entry
.peRed
, entry
.peGreen
, entry
.peBlue
);
1717 trace( "palette %p\n", h
);
1718 h
= GetClipboardData( CF_METAFILEPICT
);
1719 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1720 ok( GetObjectType( ((METAFILEPICT
*)h
)->hMF
) == OBJ_METAFILE
,
1721 "wrong object %p\n", ((METAFILEPICT
*)h
)->hMF
);
1722 trace( "metafile %p\n", h
);
1723 h
= GetClipboardData( CF_DSPMETAFILEPICT
);
1724 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1725 ok( GetObjectType( ((METAFILEPICT
*)h
)->hMF
) == OBJ_METAFILE
,
1726 "wrong object %p\n", ((METAFILEPICT
*)h
)->hMF
);
1727 trace( "metafile2 %p\n", h
);
1728 h
= GetClipboardData( CF_ENHMETAFILE
);
1729 ok( GetObjectType( h
) == OBJ_ENHMETAFILE
, "expected enhmetafile %p\n", h
);
1730 ok( GetEnhMetaFileBits( h
, sizeof(buffer
), buffer
) > sizeof(ENHMETAHEADER
),
1731 "GetEnhMetaFileBits failed on %p\n", h
);
1732 ok( ((ENHMETAHEADER
*)buffer
)->nRecords
== 3,
1733 "wrong records %u\n", ((ENHMETAHEADER
*)buffer
)->nRecords
);
1734 trace( "enhmetafile %p\n", h
);
1735 h
= GetClipboardData( CF_DSPENHMETAFILE
);
1736 ok( GetObjectType( h
) == OBJ_ENHMETAFILE
, "expected enhmetafile %p\n", h
);
1737 ok( GetEnhMetaFileBits( h
, sizeof(buffer
), buffer
) > sizeof(ENHMETAHEADER
),
1738 "GetEnhMetaFileBits failed on %p\n", h
);
1739 ok( ((ENHMETAHEADER
*)buffer
)->nRecords
== 3,
1740 "wrong records %u\n", ((ENHMETAHEADER
*)buffer
)->nRecords
);
1741 trace( "enhmetafile2 %p\n", h
);
1742 h
= GetClipboardData( CF_DIB
);
1743 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1744 h
= GetClipboardData( CF_DIBV5
);
1745 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1746 r
= CloseClipboard();
1747 ok( r
, "gle %d\n", GetLastError() );
1750 static void test_handles_process_open( const char *str
)
1752 HANDLE h
, text
= GlobalAlloc( GMEM_DDESHARE
|GMEM_MOVEABLE
, strlen(str
) + 1 );
1753 char *ptr
= GlobalLock( text
);
1756 GlobalUnlock( text
);
1758 /* clipboard already open by parent process */
1759 h
= SetClipboardData( CF_TEXT
, text
);
1760 ok( h
== text
, "wrong mem %p / %p\n", h
, text
);
1761 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1764 static void test_handles_process_dib( const char *str
)
1769 r
= OpenClipboard( 0 );
1770 ok( r
, "gle %d\n", GetLastError() );
1771 h
= GetClipboardData( CF_BITMAP
);
1772 ok( !GetObjectType( h
), "expected invalid object %p\n", h
);
1773 trace( "dibsection %p\n", h
);
1774 r
= CloseClipboard();
1775 ok( r
, "gle %d\n", GetLastError() );
1778 static void test_data_handles(void)
1783 HWND hwnd
= CreateWindowA( "static", NULL
, WS_POPUP
, 0, 0, 10, 10, 0, 0, 0, NULL
);
1787 ok( hwnd
!= 0, "window creation failed\n" );
1788 format_id
= RegisterClipboardFormatA( "my_cool_clipboard_format" );
1790 test_handles( GetDesktopWindow() );
1791 test_handles( hwnd
);
1792 run_thread( test_handles_thread
, hwnd
, __LINE__
);
1794 bitmap
= CreateBitmap( 13, 17, 1, 1, NULL
);
1795 bitmap2
= CreateBitmap( 10, 10, 1, 1, NULL
);
1796 palette
= CreatePalette( &logpalette
);
1798 r
= OpenClipboard( hwnd
);
1799 ok( r
, "gle %d\n", GetLastError() );
1800 r
= EmptyClipboard();
1801 ok( r
, "gle %d\n", GetLastError() );
1802 h
= SetClipboardData( CF_TEXT
, create_textA() );
1803 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1804 h
= SetClipboardData( format_id
, create_textA() );
1805 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1806 h
= SetClipboardData( CF_BITMAP
, bitmap
);
1807 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1808 h
= SetClipboardData( CF_DSPBITMAP
, bitmap2
);
1809 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1810 h
= SetClipboardData( CF_PALETTE
, palette
);
1811 ok( GetObjectType( h
) == OBJ_PAL
, "expected palette %p\n", h
);
1812 h
= SetClipboardData( CF_METAFILEPICT
, create_metafile() );
1813 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1814 trace( "metafile %p\n", h
);
1815 h
= SetClipboardData( CF_DSPMETAFILEPICT
, create_metafile() );
1816 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1817 trace( "metafile2 %p\n", h
);
1818 h
= SetClipboardData( CF_ENHMETAFILE
, create_emf() );
1819 ok( GetObjectType( h
) == OBJ_ENHMETAFILE
, "expected enhmetafile %p\n", h
);
1820 trace( "enhmetafile %p\n", h
);
1821 h
= SetClipboardData( CF_DSPENHMETAFILE
, create_emf() );
1822 ok( GetObjectType( h
) == OBJ_ENHMETAFILE
, "expected enhmetafile %p\n", h
);
1823 trace( "enhmetafile2 %p\n", h
);
1824 h
= SetClipboardData( CF_GDIOBJFIRST
+ 3, create_textA() );
1825 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1826 h
= SetClipboardData( CF_PRIVATEFIRST
+ 7, create_textA() );
1827 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1828 r
= CloseClipboard();
1829 ok( r
, "gle %d\n", GetLastError() );
1831 run_thread( test_handles_thread2
, 0, __LINE__
);
1832 run_process( "handles test" );
1834 r
= OpenClipboard( hwnd
);
1835 ok( r
, "gle %d\n", GetLastError() );
1836 h
= GetClipboardData( CF_TEXT
);
1837 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1838 h
= GetClipboardData( format_id
);
1839 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1840 h
= GetClipboardData( CF_GDIOBJFIRST
+ 3 );
1841 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1842 h
= GetClipboardData( CF_PRIVATEFIRST
+ 7 );
1843 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1845 r
= EmptyClipboard();
1846 ok( r
, "gle %d\n", GetLastError() );
1847 text
= create_textA();
1848 h
= SetClipboardData( CF_TEXT
, text
);
1849 ok( is_moveable( h
), "expected moveable mem %p\n", h
);
1851 run_process( "handles_open foobar" );
1853 ok( is_moveable( text
), "expected moveable mem %p\n", text
);
1854 h
= GetClipboardData( CF_TEXT
);
1855 ok( is_fixed( h
), "expected fixed mem %p\n", h
);
1856 ok( is_moveable( text
), "expected moveable mem %p\n", text
);
1857 ptr
= GlobalLock( h
);
1858 ok( !strcmp( ptr
, "foobar" ), "wrong data '%.8s'\n", ptr
);
1861 r
= EmptyClipboard();
1862 ok( r
, "gle %d\n", GetLastError() );
1863 ok( is_fixed( h
), "expected free mem %p\n", h
);
1864 ok( is_freed( text
) || broken( is_moveable(text
) ), /* w2003, w2008 */
1865 "expected free mem %p\n", text
);
1866 r
= CloseClipboard();
1867 ok( r
, "gle %d\n", GetLastError() );
1869 /* test CF_BITMAP with a DIB section */
1870 memset( &bmi
, 0, sizeof(bmi
) );
1871 bmi
.bmiHeader
.biSize
= sizeof( bmi
.bmiHeader
);
1872 bmi
.bmiHeader
.biWidth
= 29;
1873 bmi
.bmiHeader
.biHeight
= 13;
1874 bmi
.bmiHeader
.biPlanes
= 1;
1875 bmi
.bmiHeader
.biBitCount
= 32;
1876 bitmap
= CreateDIBSection( 0, &bmi
, DIB_RGB_COLORS
, &bits
, 0, 0 );
1878 r
= OpenClipboard( hwnd
);
1879 ok( r
, "gle %d\n", GetLastError() );
1880 r
= EmptyClipboard();
1881 ok( r
, "gle %d\n", GetLastError() );
1882 h
= SetClipboardData( CF_BITMAP
, bitmap
);
1883 ok( GetObjectType( h
) == OBJ_BITMAP
, "expected bitmap %p\n", h
);
1884 trace( "dibsection %p\n", h
);
1885 r
= CloseClipboard();
1886 ok( r
, "gle %d\n", GetLastError() );
1888 run_process( "handles_dib dummy" );
1890 r
= OpenClipboard( hwnd
);
1891 ok( r
, "gle %d\n", GetLastError() );
1892 ok( GetObjectType( bitmap
) == OBJ_BITMAP
, "expected bitmap %p\n", bitmap
);
1893 r
= EmptyClipboard();
1894 ok( r
, "gle %d\n", GetLastError() );
1895 r
= CloseClipboard();
1896 ok( r
, "gle %d\n", GetLastError() );
1898 DestroyWindow( hwnd
);
1901 static void test_GetUpdatedClipboardFormats(void)
1904 UINT count
, formats
[256];
1906 if (!pGetUpdatedClipboardFormats
)
1908 win_skip( "GetUpdatedClipboardFormats not supported\n" );
1913 r
= pGetUpdatedClipboardFormats( NULL
, 0, &count
);
1914 ok( r
, "gle %d\n", GetLastError() );
1915 ok( !count
, "wrong count %u\n", count
);
1918 r
= pGetUpdatedClipboardFormats( NULL
, 256, &count
);
1919 ok( r
, "gle %d\n", GetLastError() );
1920 ok( !count
, "wrong count %u\n", count
);
1922 SetLastError( 0xdeadbeef );
1923 r
= pGetUpdatedClipboardFormats( formats
, 256, NULL
);
1924 ok( !r
, "succeeded\n" );
1925 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
1928 r
= pGetUpdatedClipboardFormats( formats
, 256, &count
);
1929 ok( r
, "gle %d\n", GetLastError() );
1930 ok( !count
, "wrong count %u\n", count
);
1932 r
= OpenClipboard( 0 );
1933 ok( r
, "gle %d\n", GetLastError() );
1934 r
= EmptyClipboard();
1935 ok( r
, "gle %d\n", GetLastError() );
1938 r
= pGetUpdatedClipboardFormats( formats
, 256, &count
);
1939 ok( r
, "gle %d\n", GetLastError() );
1940 ok( !count
, "wrong count %u\n", count
);
1942 SetClipboardData( CF_UNICODETEXT
, 0 );
1945 memset( formats
, 0xcc, sizeof(formats
) );
1946 r
= pGetUpdatedClipboardFormats( formats
, 256, &count
);
1947 ok( r
, "gle %d\n", GetLastError() );
1948 ok( count
== 1, "wrong count %u\n", count
);
1949 ok( formats
[0] == CF_UNICODETEXT
, "wrong format %u\n", formats
[0] );
1950 ok( formats
[1] == 0xcccccccc, "wrong format %u\n", formats
[1] );
1952 SetClipboardData( CF_TEXT
, 0 );
1954 memset( formats
, 0xcc, sizeof(formats
) );
1955 r
= pGetUpdatedClipboardFormats( formats
, 256, &count
);
1956 ok( r
, "gle %d\n", GetLastError() );
1957 ok( count
== 2, "wrong count %u\n", count
);
1958 ok( formats
[0] == CF_UNICODETEXT
, "wrong format %u\n", formats
[0] );
1959 ok( formats
[1] == CF_TEXT
, "wrong format %u\n", formats
[1] );
1960 ok( formats
[2] == 0xcccccccc, "wrong format %u\n", formats
[2] );
1962 SetLastError( 0xdeadbeef );
1964 r
= pGetUpdatedClipboardFormats( formats
, 0, &count
);
1965 ok( !r
, "succeeded\n" );
1966 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "wrong error %u\n", GetLastError() );
1967 ok( count
== 2, "wrong count %u\n", count
);
1969 SetLastError( 0xdeadbeef );
1971 r
= pGetUpdatedClipboardFormats( formats
, 1, &count
);
1972 ok( !r
, "succeeded\n" );
1973 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "wrong error %u\n", GetLastError() );
1974 ok( count
== 2, "wrong count %u\n", count
);
1976 r
= CloseClipboard();
1977 ok( r
, "gle %d\n", GetLastError() );
1980 memset( formats
, 0xcc, sizeof(formats
) );
1981 r
= pGetUpdatedClipboardFormats( formats
, 256, &count
);
1982 ok( r
, "gle %d\n", GetLastError() );
1983 ok( count
== 4, "wrong count %u\n", count
);
1984 ok( formats
[0] == CF_UNICODETEXT
, "wrong format %u\n", formats
[0] );
1985 ok( formats
[1] == CF_TEXT
, "wrong format %u\n", formats
[1] );
1986 ok( formats
[2] == CF_LOCALE
, "wrong format %u\n", formats
[2] );
1987 ok( formats
[3] == CF_OEMTEXT
, "wrong format %u\n", formats
[3] );
1988 ok( formats
[4] == 0xcccccccc, "wrong format %u\n", formats
[4] );
1991 memset( formats
, 0xcc, sizeof(formats
) );
1992 r
= pGetUpdatedClipboardFormats( formats
, 2, &count
);
1993 ok( !r
, "gle %d\n", GetLastError() );
1994 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "wrong error %u\n", GetLastError() );
1995 ok( count
== 4, "wrong count %u\n", count
);
1996 ok( formats
[0] == 0xcccccccc, "wrong format %u\n", formats
[0] );
1999 r
= pGetUpdatedClipboardFormats( NULL
, 256, &count
);
2000 ok( !r
, "gle %d\n", GetLastError() );
2001 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
2002 ok( count
== 4, "wrong count %u\n", count
);
2005 r
= pGetUpdatedClipboardFormats( NULL
, 256, &count
);
2006 ok( !r
, "gle %d\n", GetLastError() );
2007 ok( GetLastError() == ERROR_NOACCESS
, "wrong error %u\n", GetLastError() );
2008 ok( count
== 4, "wrong count %u\n", count
);
2018 { "foo", {}, 3 }, /* 0 */
2020 { "foo\0bar", {}, 7 },
2021 { "foo\0bar", {}, 8 },
2022 { "", {'f','o','o'}, 3 * sizeof(WCHAR
) },
2023 { "", {'f','o','o',0}, 4 * sizeof(WCHAR
) }, /* 5 */
2024 { "", {'f','o','o',0,'b','a','r'}, 7 * sizeof(WCHAR
) },
2025 { "", {'f','o','o',0,'b','a','r',0}, 8 * sizeof(WCHAR
) },
2026 { "", {'f','o','o'}, 1 },
2027 { "", {'f','o','o'}, 2 },
2028 { "", {'f','o','o'}, 5 }, /* 10 */
2029 { "", {'f','o','o',0}, 7 },
2030 { "", {'f','o','o',0}, 9 },
2033 static void test_string_data(void)
2042 for (i
= 0; i
< ARRAY_SIZE(test_data
); i
++)
2044 /* 1-byte Unicode strings crash on Win64 */
2046 if (!test_data
[i
].strA
[0] && test_data
[i
].len
< sizeof(WCHAR
)) continue;
2048 r
= OpenClipboard( 0 );
2049 ok( r
, "gle %d\n", GetLastError() );
2050 r
= EmptyClipboard();
2051 ok( r
, "gle %d\n", GetLastError() );
2052 data
= GlobalAlloc( GMEM_FIXED
, test_data
[i
].len
);
2053 if (test_data
[i
].strA
[0])
2055 memcpy( data
, test_data
[i
].strA
, test_data
[i
].len
);
2056 SetClipboardData( CF_TEXT
, data
);
2057 memcpy( bufferA
, test_data
[i
].strA
, test_data
[i
].len
);
2058 bufferA
[test_data
[i
].len
- 1] = 0;
2059 ok( !memcmp( data
, bufferA
, test_data
[i
].len
),
2060 "%u: wrong data %.*s\n", i
, test_data
[i
].len
, (char *)data
);
2064 memcpy( data
, test_data
[i
].strW
, test_data
[i
].len
);
2065 SetClipboardData( CF_UNICODETEXT
, data
);
2066 memcpy( bufferW
, test_data
[i
].strW
, test_data
[i
].len
);
2067 bufferW
[(test_data
[i
].len
+ 1) / sizeof(WCHAR
) - 1] = 0;
2068 ok( !memcmp( data
, bufferW
, test_data
[i
].len
),
2069 "%u: wrong data %s\n", i
, wine_dbgstr_wn( data
, (test_data
[i
].len
+ 1) / sizeof(WCHAR
) ));
2071 r
= CloseClipboard();
2072 ok( r
, "gle %d\n", GetLastError() );
2073 sprintf( cmd
, "string_data %u", i
);
2078 static void test_string_data_process( int i
)
2086 r
= OpenClipboard( 0 );
2087 ok( r
, "gle %d\n", GetLastError() );
2088 if (test_data
[i
].strA
[0])
2090 data
= GetClipboardData( CF_TEXT
);
2091 ok( data
!= 0, "%u: could not get data\n", i
);
2092 len
= GlobalSize( data
);
2093 ok( len
== test_data
[i
].len
, "%u: wrong size %u / %u\n", i
, len
, test_data
[i
].len
);
2094 memcpy( bufferA
, test_data
[i
].strA
, test_data
[i
].len
);
2095 bufferA
[test_data
[i
].len
- 1] = 0;
2096 ok( !memcmp( data
, bufferA
, len
), "%u: wrong data %.*s\n", i
, len
, (char *)data
);
2097 data
= GetClipboardData( CF_UNICODETEXT
);
2098 ok( data
!= 0, "%u: could not get data\n", i
);
2099 len
= GlobalSize( data
);
2100 len2
= MultiByteToWideChar( CP_ACP
, 0, bufferA
, test_data
[i
].len
, bufferW
, 12 );
2101 ok( len
== len2
* sizeof(WCHAR
), "%u: wrong size %u / %u\n", i
, len
, len2
);
2102 ok( !memcmp( data
, bufferW
, len
), "%u: wrong data %s\n", i
, wine_dbgstr_wn( data
, len2
));
2106 data
= GetClipboardData( CF_UNICODETEXT
);
2107 ok( data
!= 0, "%u: could not get data\n", i
);
2108 len
= GlobalSize( data
);
2109 ok( len
== test_data
[i
].len
, "%u: wrong size %u / %u\n", i
, len
, test_data
[i
].len
);
2110 memcpy( bufferW
, test_data
[i
].strW
, test_data
[i
].len
);
2111 bufferW
[(test_data
[i
].len
+ 1) / sizeof(WCHAR
) - 1] = 0;
2112 ok( !memcmp( data
, bufferW
, len
),
2113 "%u: wrong data %s\n", i
, wine_dbgstr_wn( data
, (len
+ 1) / sizeof(WCHAR
) ));
2114 data
= GetClipboardData( CF_TEXT
);
2115 if (test_data
[i
].len
>= sizeof(WCHAR
))
2117 ok( data
!= 0, "%u: could not get data\n", i
);
2118 len
= GlobalSize( data
);
2119 len2
= WideCharToMultiByte( CP_ACP
, 0, bufferW
, test_data
[i
].len
/ sizeof(WCHAR
),
2120 bufferA
, 12, NULL
, NULL
);
2121 bufferA
[len2
- 1] = 0;
2122 ok( len
== len2
, "%u: wrong size %u / %u\n", i
, len
, len2
);
2123 ok( !memcmp( data
, bufferA
, len
), "%u: wrong data %.*s\n", i
, len
, (char *)data
);
2127 ok( !data
, "%u: got data for empty string\n", i
);
2128 ok( IsClipboardFormatAvailable( CF_TEXT
), "%u: text not available\n", i
);
2131 r
= CloseClipboard();
2132 ok( r
, "gle %d\n", GetLastError() );
2135 START_TEST(clipboard
)
2138 int argc
= winetest_get_mainargs( &argv
);
2139 HMODULE mod
= GetModuleHandleA( "user32" );
2142 pAddClipboardFormatListener
= (void *)GetProcAddress( mod
, "AddClipboardFormatListener" );
2143 pRemoveClipboardFormatListener
= (void *)GetProcAddress( mod
, "RemoveClipboardFormatListener" );
2144 pGetUpdatedClipboardFormats
= (void *)GetProcAddress( mod
, "GetUpdatedClipboardFormats" );
2146 if (argc
== 4 && !strcmp( argv
[2], "set_clipboard_data" ))
2148 set_clipboard_data_process( atoi( argv
[3] ));
2151 if (argc
== 4 && !strcmp( argv
[2], "grab_clipboard" ))
2153 grab_clipboard_process( atoi( argv
[3] ));
2156 if (argc
== 4 && !strcmp( argv
[2], "handles" ))
2158 test_handles_process( argv
[3] );
2161 if (argc
== 4 && !strcmp( argv
[2], "handles_open" ))
2163 test_handles_process_open( argv
[3] );
2166 if (argc
== 4 && !strcmp( argv
[2], "handles_dib" ))
2168 test_handles_process_dib( argv
[3] );
2171 if (argc
== 4 && !strcmp( argv
[2], "string_data" ))
2173 test_string_data_process( atoi( argv
[3] ));
2176 if (argc
== 3 && !strcmp( argv
[2], "get_clipboard_data" ))
2178 get_clipboard_data_process( );
2182 test_RegisterClipboardFormatA();
2183 test_ClipboardOwner();
2186 test_data_handles();
2187 test_GetUpdatedClipboardFormats();