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