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