user32/tests: Test resulting size of strings with trailing nulls.
[wine.git] / dlls / user32 / tests / clipboard.c
blob5527a6e8dc7552222740818279bd5117860bce5b
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 DWORD (WINAPI *pGetClipboardSequenceNumber)(void);
32 static BOOL (WINAPI *pGetUpdatedClipboardFormats)( UINT *formats, UINT count, UINT *out_count );
34 static int thread_from_line;
35 static char *argv0;
37 static DWORD WINAPI open_clipboard_thread(LPVOID arg)
39 HWND hWnd = arg;
40 ok(OpenClipboard(hWnd), "%u: OpenClipboard failed\n", thread_from_line);
41 return 0;
44 static DWORD WINAPI empty_clipboard_thread(LPVOID arg)
46 SetLastError( 0xdeadbeef );
47 ok(!EmptyClipboard(), "%u: EmptyClipboard succeeded\n", thread_from_line );
48 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
49 thread_from_line, GetLastError());
50 return 0;
53 static DWORD WINAPI open_and_empty_clipboard_thread(LPVOID arg)
55 HWND hWnd = arg;
56 ok(OpenClipboard(hWnd), "%u: OpenClipboard failed\n", thread_from_line);
57 ok(EmptyClipboard(), "%u: EmptyClipboard failed\n", thread_from_line );
58 return 0;
61 static DWORD WINAPI open_and_empty_clipboard_win_thread(LPVOID arg)
63 HWND hwnd = CreateWindowA( "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL );
64 ok(OpenClipboard(hwnd), "%u: OpenClipboard failed\n", thread_from_line);
65 ok(EmptyClipboard(), "%u: EmptyClipboard failed\n", thread_from_line );
66 return 0;
69 static DWORD WINAPI set_clipboard_data_thread(LPVOID arg)
71 HWND hwnd = arg;
72 HANDLE ret;
74 SetLastError( 0xdeadbeef );
75 if (GetClipboardOwner() == hwnd)
77 SetClipboardData( CF_WAVE, 0 );
78 ok( IsClipboardFormatAvailable( CF_WAVE ), "%u: SetClipboardData failed\n", thread_from_line );
79 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
80 ok( ret != 0, "%u: SetClipboardData failed err %u\n", thread_from_line, GetLastError() );
81 SetLastError( 0xdeadbeef );
82 ret = GetClipboardData( CF_WAVE );
83 ok( !ret, "%u: GetClipboardData succeeded\n", thread_from_line );
84 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
85 thread_from_line, GetLastError());
87 else
89 SetClipboardData( CF_WAVE, 0 );
90 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
91 thread_from_line, GetLastError());
92 ok( !IsClipboardFormatAvailable( CF_WAVE ), "%u: SetClipboardData succeeded\n", thread_from_line );
93 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
94 ok( !ret, "%u: SetClipboardData succeeded\n", thread_from_line );
95 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
96 thread_from_line, GetLastError());
98 return 0;
101 static void set_clipboard_data_process( int arg )
103 HANDLE ret;
105 SetLastError( 0xdeadbeef );
106 if (arg)
108 ok( IsClipboardFormatAvailable( CF_WAVE ), "process %u: CF_WAVE not available\n", arg );
109 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
110 ok( ret != 0, "process %u: SetClipboardData failed err %u\n", arg, GetLastError() );
112 else
114 SetClipboardData( CF_WAVE, 0 );
115 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "process %u: wrong error %u\n",
116 arg, GetLastError());
117 ok( !IsClipboardFormatAvailable( CF_WAVE ), "process %u: SetClipboardData succeeded\n", arg );
118 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
119 ok( !ret, "process %u: SetClipboardData succeeded\n", arg );
120 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "process %u: wrong error %u\n",
121 arg, GetLastError());
125 static void grab_clipboard_process( int arg )
127 BOOL ret;
129 SetLastError( 0xdeadbeef );
130 ret = OpenClipboard( 0 );
131 ok( ret, "OpenClipboard failed\n" );
132 ret = EmptyClipboard();
133 ok( ret, "EmptyClipboard failed\n" );
134 if (arg)
136 HANDLE ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
137 ok( ret != 0, "process %u: SetClipboardData failed err %u\n", arg, GetLastError() );
141 static void run_thread( LPTHREAD_START_ROUTINE func, void *arg, int line )
143 DWORD ret;
144 HANDLE thread;
146 thread_from_line = line;
147 thread = CreateThread(NULL, 0, func, arg, 0, NULL);
148 ok(thread != NULL, "%u: CreateThread failed with error %d\n", line, GetLastError());
149 for (;;)
151 ret = MsgWaitForMultipleObjectsEx( 1, &thread, 1000, QS_ALLINPUT, 0 );
152 if (ret == WAIT_OBJECT_0 + 1)
154 MSG msg;
155 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
157 else break;
159 ok(ret == WAIT_OBJECT_0, "%u: expected WAIT_OBJECT_0, got %u\n", line, ret);
160 CloseHandle(thread);
163 static void run_process( const char *args )
165 char cmd[MAX_PATH];
166 PROCESS_INFORMATION info;
167 STARTUPINFOA startup;
169 sprintf( cmd, "%s clipboard %s", argv0, args );
170 memset( &startup, 0, sizeof(startup) );
171 startup.cb = sizeof(startup);
172 ok( CreateProcessA( NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info ),
173 "CreateProcess %s failed\n", cmd );
175 winetest_wait_child_process( info.hProcess );
176 CloseHandle( info.hProcess );
177 CloseHandle( info.hThread );
180 static WNDPROC old_proc;
181 static LRESULT CALLBACK winproc_wrapper( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
183 static int wm_renderallformats;
184 static int wm_drawclipboard;
185 static int seqno;
186 DWORD msg_flags = InSendMessageEx( NULL );
188 if (!seqno) seqno = GetClipboardSequenceNumber();
190 trace( "%p msg %04x\n", hwnd, msg );
191 if (!wm_renderallformats)
193 ok( GetClipboardOwner() == hwnd, "%04x: wrong owner %p/%p\n", msg, GetClipboardOwner(), hwnd );
194 ok( seqno == GetClipboardSequenceNumber(), "%04x: seqno changed\n", msg );
196 else
198 ok( !GetClipboardOwner(), "%04x: wrong owner %p\n", msg, GetClipboardOwner() );
199 ok( seqno + 1 == GetClipboardSequenceNumber(), "%04x: seqno unchanged\n", msg );
201 ok( GetClipboardViewer() == hwnd, "%04x: wrong viewer %p/%p\n", msg, GetClipboardViewer(), hwnd );
202 ok( GetOpenClipboardWindow() == hwnd, "%04x: wrong open win %p/%p\n",
203 msg, GetOpenClipboardWindow(), hwnd );
205 switch (msg)
207 case WM_DESTROY:
208 ok( wm_renderallformats, "didn't receive WM_RENDERALLFORMATS before WM_DESTROY\n" );
209 ok( wm_drawclipboard, "didn't receive WM_DRAWCLIPBOARD before WM_DESTROY\n" );
210 break;
211 case WM_DRAWCLIPBOARD:
212 ok( msg_flags == ISMEX_NOSEND, "WM_DRAWCLIPBOARD wrong flags %x\n", msg_flags );
213 wm_drawclipboard++;
214 break;
215 case WM_RENDERALLFORMATS:
216 ok( msg_flags == ISMEX_NOSEND, "WM_RENDERALLFORMATS wrong flags %x\n", msg_flags );
217 wm_renderallformats++;
218 break;
220 return old_proc( hwnd, msg, wp, lp );
223 static void test_ClipboardOwner(void)
225 HWND hWnd1, hWnd2;
226 BOOL ret;
228 SetLastError(0xdeadbeef);
229 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef,
230 "could not perform clipboard test: clipboard already owned\n");
232 hWnd1 = CreateWindowExA(0, "static", NULL, WS_POPUP,
233 0, 0, 10, 10, 0, 0, 0, NULL);
234 ok(hWnd1 != 0, "CreateWindowExA error %d\n", GetLastError());
235 trace("hWnd1 = %p\n", hWnd1);
237 hWnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP,
238 0, 0, 10, 10, 0, 0, 0, NULL);
239 ok(hWnd2 != 0, "CreateWindowExA error %d\n", GetLastError());
240 trace("hWnd2 = %p\n", hWnd2);
242 SetLastError(0xdeadbeef);
243 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
244 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */
245 "wrong error %u\n", GetLastError());
247 ok(OpenClipboard(0), "OpenClipboard failed\n");
248 ok(!GetClipboardOwner(), "clipboard should still be not owned\n");
249 ok(!OpenClipboard(hWnd1), "OpenClipboard should fail since clipboard already opened\n");
250 ok(OpenClipboard(0), "OpenClipboard again failed\n");
251 ret = CloseClipboard();
252 ok( ret, "CloseClipboard error %d\n", GetLastError());
254 ok(OpenClipboard(hWnd1), "OpenClipboard failed\n");
255 run_thread( open_clipboard_thread, hWnd1, __LINE__ );
256 run_thread( empty_clipboard_thread, 0, __LINE__ );
257 run_thread( set_clipboard_data_thread, hWnd1, __LINE__ );
258 ok( !IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE available\n" );
259 ok( !GetClipboardData( CF_WAVE ), "CF_WAVE data available\n" );
260 run_process( "set_clipboard_data 0" );
261 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
262 ok(OpenClipboard(hWnd1), "OpenClipboard failed\n");
264 SetLastError(0xdeadbeef);
265 ret = OpenClipboard(hWnd2);
266 ok(!ret && (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED),
267 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
269 SetLastError(0xdeadbeef);
270 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should still be not owned\n");
271 ret = EmptyClipboard();
272 ok( ret, "EmptyClipboard error %d\n", GetLastError());
273 ok(GetClipboardOwner() == hWnd1, "clipboard should be owned by %p, not by %p\n", hWnd1, GetClipboardOwner());
274 run_thread( empty_clipboard_thread, 0, __LINE__ );
275 run_thread( set_clipboard_data_thread, hWnd1, __LINE__ );
276 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
277 ok( GetClipboardData( CF_WAVE ) != 0, "CF_WAVE data not available\n" );
278 run_process( "set_clipboard_data 1" );
280 SetLastError(0xdeadbeef);
281 ret = OpenClipboard(hWnd2);
282 ok(!ret && (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED),
283 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
285 ret = CloseClipboard();
286 ok( ret, "CloseClipboard error %d\n", GetLastError());
287 ok(GetClipboardOwner() == hWnd1, "clipboard should still be owned\n");
289 /* any window will do, even from a different process */
290 ret = OpenClipboard( GetDesktopWindow() );
291 ok( ret, "OpenClipboard error %d\n", GetLastError());
292 ret = EmptyClipboard();
293 ok( ret, "EmptyClipboard error %d\n", GetLastError());
294 ok( GetClipboardOwner() == GetDesktopWindow(), "wrong owner %p/%p\n",
295 GetClipboardOwner(), GetDesktopWindow() );
296 run_thread( set_clipboard_data_thread, GetDesktopWindow(), __LINE__ );
297 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
298 ok( GetClipboardData( CF_WAVE ) != 0, "CF_WAVE data not available\n" );
299 run_process( "set_clipboard_data 2" );
300 ret = CloseClipboard();
301 ok( ret, "CloseClipboard error %d\n", GetLastError());
303 ret = OpenClipboard( hWnd1 );
304 ok( ret, "OpenClipboard error %d\n", GetLastError());
305 ret = EmptyClipboard();
306 ok( ret, "EmptyClipboard error %d\n", GetLastError());
307 SetClipboardData( CF_WAVE, 0 );
308 SetClipboardViewer( hWnd1 );
309 ok( GetClipboardOwner() == hWnd1, "wrong owner %p/%p\n", GetClipboardOwner(), hWnd1 );
310 ok( GetClipboardViewer() == hWnd1, "wrong viewer %p/%p\n", GetClipboardViewer(), hWnd1 );
311 ok( GetOpenClipboardWindow() == hWnd1, "wrong open win %p/%p\n", GetOpenClipboardWindow(), hWnd1 );
312 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
314 old_proc = (WNDPROC)SetWindowLongPtrA( hWnd1, GWLP_WNDPROC, (LONG_PTR)winproc_wrapper );
315 ret = DestroyWindow(hWnd1);
316 ok( ret, "DestroyWindow error %d\n", GetLastError());
317 ret = DestroyWindow(hWnd2);
318 ok( ret, "DestroyWindow error %d\n", GetLastError());
319 SetLastError(0xdeadbeef);
320 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should not be owned\n");
321 ok(!GetClipboardViewer() && GetLastError() == 0xdeadbeef, "viewer still exists\n");
322 ok(!GetOpenClipboardWindow() && GetLastError() == 0xdeadbeef, "clipboard should not be open\n");
323 ok( !IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE available\n" );
325 SetLastError( 0xdeadbeef );
326 ret = CloseClipboard();
327 ok( !ret, "CloseClipboard succeeded\n" );
328 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError() );
330 ret = OpenClipboard( 0 );
331 ok( ret, "OpenClipboard error %d\n", GetLastError());
332 run_thread( set_clipboard_data_thread, 0, __LINE__ );
333 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
334 ok( GetClipboardData( CF_WAVE ) != 0, "CF_WAVE data not available\n" );
335 run_process( "set_clipboard_data 3" );
336 ret = CloseClipboard();
337 ok( ret, "CloseClipboard error %d\n", GetLastError());
339 run_thread( open_and_empty_clipboard_thread, 0, __LINE__ );
340 ok( !GetOpenClipboardWindow(), "wrong open window %p\n", GetOpenClipboardWindow() );
341 ok( !GetClipboardOwner(), "wrong owner window %p\n", GetClipboardOwner() );
343 ret = OpenClipboard( 0 );
344 ok( ret, "OpenClipboard error %d\n", GetLastError());
345 run_thread( set_clipboard_data_thread, 0, __LINE__ );
346 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
347 ok( GetClipboardData( CF_WAVE ) != 0, "CF_WAVE data not available\n" );
348 run_process( "set_clipboard_data 4" );
349 ret = EmptyClipboard();
350 ok( ret, "EmptyClipboard error %d\n", GetLastError());
351 ret = CloseClipboard();
352 ok( ret, "CloseClipboard error %d\n", GetLastError());
354 SetLastError( 0xdeadbeef );
355 ok( !SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 )),
356 "SetClipboardData succeeded\n" );
357 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError() );
358 ok( !IsClipboardFormatAvailable( CF_WAVE ), "SetClipboardData succeeded\n" );
360 run_thread( open_and_empty_clipboard_thread, GetDesktopWindow(), __LINE__ );
361 ok( !GetOpenClipboardWindow(), "wrong open window %p\n", GetOpenClipboardWindow() );
362 ok( GetClipboardOwner() == GetDesktopWindow(), "wrong owner window %p / %p\n",
363 GetClipboardOwner(), GetDesktopWindow() );
365 run_thread( open_and_empty_clipboard_win_thread, 0, __LINE__ );
366 ok( !GetOpenClipboardWindow(), "wrong open window %p\n", GetOpenClipboardWindow() );
367 ok( !GetClipboardOwner(), "wrong owner window %p\n", GetClipboardOwner() );
370 static void test_RegisterClipboardFormatA(void)
372 ATOM atom_id;
373 UINT format_id, format_id2;
374 char buf[256];
375 int len;
376 BOOL ret;
377 HANDLE handle;
379 format_id = RegisterClipboardFormatA("my_cool_clipboard_format");
380 ok(format_id > 0xc000 && format_id < 0xffff, "invalid clipboard format id %04x\n", format_id);
382 format_id2 = RegisterClipboardFormatA("MY_COOL_CLIPBOARD_FORMAT");
383 ok(format_id2 == format_id, "invalid clipboard format id %04x\n", format_id2);
385 len = GetClipboardFormatNameA(format_id, buf, 256);
386 ok(len == lstrlenA("my_cool_clipboard_format"), "wrong format name length %d\n", len);
387 ok(!lstrcmpA(buf, "my_cool_clipboard_format"), "wrong format name \"%s\"\n", buf);
389 lstrcpyA(buf, "foo");
390 SetLastError(0xdeadbeef);
391 len = GetAtomNameA((ATOM)format_id, buf, 256);
392 ok(len == 0, "GetAtomNameA should fail\n");
393 ok(GetLastError() == ERROR_INVALID_HANDLE, "err %d\n", GetLastError());
395 todo_wine
397 lstrcpyA(buf, "foo");
398 SetLastError(0xdeadbeef);
399 len = GlobalGetAtomNameA((ATOM)format_id, buf, 256);
400 ok(len == 0, "GlobalGetAtomNameA should fail\n");
401 ok(GetLastError() == ERROR_INVALID_HANDLE, "err %d\n", GetLastError());
404 SetLastError(0xdeadbeef);
405 atom_id = FindAtomA("my_cool_clipboard_format");
406 ok(atom_id == 0, "FindAtomA should fail\n");
407 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError());
409 if (0)
411 /* this relies on the clipboard and global atom table being different */
412 SetLastError(0xdeadbeef);
413 atom_id = GlobalFindAtomA("my_cool_clipboard_format");
414 ok(atom_id == 0, "GlobalFindAtomA should fail\n");
415 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError());
418 for (format_id = 0; format_id < 0x10fff; format_id++)
420 SetLastError(0xdeadbeef);
421 len = GetClipboardFormatNameA(format_id, buf, 256);
423 if (format_id < 0xc000 || format_id > 0xffff)
424 ok(!len, "GetClipboardFormatNameA should fail, but it returned %d (%s)\n", len, buf);
425 else if (len && winetest_debug > 1)
426 trace("%04x: %s\n", format_id, len ? buf : "");
429 ret = OpenClipboard(0);
430 ok( ret, "OpenClipboard error %d\n", GetLastError());
432 /* try some invalid/unregistered formats */
433 SetLastError( 0xdeadbeef );
434 handle = SetClipboardData( 0, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
435 ok( !handle, "SetClipboardData succeeded\n" );
436 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError());
437 handle = SetClipboardData( 0x1234, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
438 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
439 handle = SetClipboardData( 0x123456, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
440 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
441 handle = SetClipboardData( 0xffff8765, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
442 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
444 ok( IsClipboardFormatAvailable( 0x1234 ), "format missing\n" );
445 ok( IsClipboardFormatAvailable( 0x123456 ), "format missing\n" );
446 ok( IsClipboardFormatAvailable( 0xffff8765 ), "format missing\n" );
447 ok( !IsClipboardFormatAvailable( 0 ), "format available\n" );
448 ok( !IsClipboardFormatAvailable( 0x3456 ), "format available\n" );
449 ok( !IsClipboardFormatAvailable( 0x8765 ), "format available\n" );
451 trace("# of formats available: %d\n", CountClipboardFormats());
453 format_id = 0;
454 while ((format_id = EnumClipboardFormats(format_id)))
456 ok(IsClipboardFormatAvailable(format_id), "format %04x was listed as available\n", format_id);
457 len = GetClipboardFormatNameA(format_id, buf, 256);
458 trace("%04x: %s\n", format_id, len ? buf : "");
461 ret = EmptyClipboard();
462 ok( ret, "EmptyClipboard error %d\n", GetLastError());
463 ret =CloseClipboard();
464 ok( ret, "CloseClipboard error %d\n", GetLastError());
466 if (CountClipboardFormats())
468 SetLastError(0xdeadbeef);
469 ok(!EnumClipboardFormats(0), "EnumClipboardFormats should fail if clipboard wasn't open\n");
470 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN,
471 "Last error should be set to ERROR_CLIPBOARD_NOT_OPEN, not %d\n", GetLastError());
474 SetLastError(0xdeadbeef);
475 ok(!EmptyClipboard(), "EmptyClipboard should fail if clipboard wasn't open\n");
476 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */
477 "Wrong error %u\n", GetLastError());
479 format_id = RegisterClipboardFormatA("#1234");
480 ok(format_id == 1234, "invalid clipboard format id %04x\n", format_id);
483 static HGLOBAL create_textA(void)
485 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 10);
486 char *p = GlobalLock(h);
487 memcpy(p, "test\0\0\0\0\0", 10);
488 GlobalUnlock(h);
489 return h;
492 static HGLOBAL create_textW(void)
494 static const WCHAR testW[] = {'t','e','s','t',0,0,0,0,0,0};
495 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, sizeof(testW));
496 WCHAR *p = GlobalLock(h);
497 memcpy(p, testW, sizeof(testW));
498 GlobalUnlock(h);
499 return h;
502 static HANDLE create_metafile(void)
504 const RECT rect = {0, 0, 100, 100};
505 METAFILEPICT *pict;
506 HANDLE ret;
507 HMETAFILE mf;
508 HDC hdc = CreateMetaFileA( NULL );
509 ExtTextOutA( hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL );
510 mf = CloseMetaFile( hdc );
511 ret = GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(*pict) );
512 pict = GlobalLock( ret );
513 pict->mm = MM_TEXT;
514 pict->xExt = pict->yExt = 100;
515 pict->hMF = mf;
516 GlobalUnlock( ret );
517 return ret;
520 static HENHMETAFILE create_emf(void)
522 const RECT rect = {0, 0, 100, 100};
523 HDC hdc = CreateEnhMetaFileA(NULL, NULL, &rect, "HENHMETAFILE Ole Clipboard Test\0Test\0\0");
524 ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
525 return CloseEnhMetaFile(hdc);
528 static HBITMAP create_bitmap(void)
530 HDC hdc = GetDC( 0 );
531 UINT bpp = GetDeviceCaps( hdc, BITSPIXEL );
532 ReleaseDC( 0, hdc );
533 return CreateBitmap( 10, 10, 1, bpp, NULL );
536 static HBITMAP create_dib( BOOL v5 )
538 HANDLE ret;
539 BITMAPINFOHEADER *hdr;
541 ret = GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT,
542 sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD) + 16 * 16 * 4 );
543 hdr = GlobalLock( ret );
544 hdr->biSize = v5 ? sizeof(BITMAPV5HEADER) : sizeof(*hdr);
545 hdr->biWidth = 16;
546 hdr->biHeight = 16;
547 hdr->biPlanes = 1;
548 hdr->biBitCount = 32;
549 hdr->biCompression = BI_RGB;
550 if (v5)
552 BITMAPV5HEADER *hdr5 = (BITMAPV5HEADER *)hdr;
553 hdr5->bV5RedMask = 0x0000ff;
554 hdr5->bV5GreenMask = 0x00ff00;
555 hdr5->bV5BlueMask = 0xff0000;
556 hdr5->bV5AlphaMask = 0xff000000;
558 GlobalUnlock( ret );
559 return ret;
562 static LRESULT CALLBACK renderer_winproc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
564 static UINT rendered;
565 UINT ret;
567 switch (msg)
569 case WM_RENDERFORMAT:
570 if (wp < 32) rendered |= (1 << wp);
571 break;
572 case WM_USER:
573 ret = rendered;
574 rendered = 0;
575 return ret;
577 return DefWindowProcA( hwnd, msg, wp, lp );
580 static void test_synthesized(void)
582 static const struct test
584 UINT format;
585 UINT expected[8];
586 } tests[] =
588 /* 0 */ { CF_TEXT, { CF_TEXT, CF_LOCALE, CF_OEMTEXT, CF_UNICODETEXT }},
589 { CF_OEMTEXT, { CF_OEMTEXT, CF_LOCALE, CF_TEXT, CF_UNICODETEXT }},
590 { CF_UNICODETEXT, { CF_UNICODETEXT, CF_LOCALE, CF_TEXT, CF_OEMTEXT }},
591 { CF_ENHMETAFILE, { CF_ENHMETAFILE, CF_METAFILEPICT }},
592 { CF_METAFILEPICT, { CF_METAFILEPICT, CF_ENHMETAFILE }},
593 /* 5 */ { CF_BITMAP, { CF_BITMAP, CF_DIB, CF_DIBV5 }},
594 { CF_DIB, { CF_DIB, CF_BITMAP, CF_DIBV5 }},
595 { CF_DIBV5, { CF_DIBV5, CF_BITMAP, CF_DIB }},
598 HGLOBAL h, htext;
599 HENHMETAFILE emf;
600 BOOL r;
601 UINT cf, i, j, count, rendered;
602 HANDLE data;
603 HWND hwnd;
605 hwnd = CreateWindowA( "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL );
606 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)renderer_winproc );
608 htext = create_textA();
609 emf = create_emf();
611 r = OpenClipboard(NULL);
612 ok(r, "gle %d\n", GetLastError());
613 r = EmptyClipboard();
614 ok(r, "gle %d\n", GetLastError());
615 h = SetClipboardData(CF_TEXT, htext);
616 ok(h == htext, "got %p\n", h);
617 h = SetClipboardData(CF_ENHMETAFILE, emf);
618 ok(h == emf, "got %p\n", h);
619 r = CloseClipboard();
620 ok(r, "gle %d\n", GetLastError());
622 count = CountClipboardFormats();
623 ok( count == 6, "count %u\n", count );
624 r = IsClipboardFormatAvailable( CF_TEXT );
625 ok( r, "CF_TEXT not available err %d\n", GetLastError());
626 r = IsClipboardFormatAvailable( CF_LOCALE );
627 ok( r, "CF_LOCALE not available err %d\n", GetLastError());
628 r = IsClipboardFormatAvailable( CF_OEMTEXT );
629 ok( r, "CF_OEMTEXT not available err %d\n", GetLastError());
630 r = IsClipboardFormatAvailable( CF_UNICODETEXT );
631 ok( r, "CF_UNICODETEXT not available err %d\n", GetLastError());
632 r = IsClipboardFormatAvailable( CF_ENHMETAFILE );
633 ok( r, "CF_ENHMETAFILE not available err %d\n", GetLastError());
634 r = IsClipboardFormatAvailable( CF_METAFILEPICT );
635 ok( r, "CF_METAFILEPICT not available err %d\n", GetLastError());
637 r = OpenClipboard(NULL);
638 ok(r, "gle %d\n", GetLastError());
639 cf = EnumClipboardFormats(0);
640 ok(cf == CF_TEXT, "cf %08x\n", cf);
641 data = GetClipboardData(cf);
642 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
644 cf = EnumClipboardFormats(cf);
645 ok(cf == CF_ENHMETAFILE, "cf %08x\n", cf);
646 data = GetClipboardData(cf);
647 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
649 cf = EnumClipboardFormats(cf);
650 ok(cf == CF_LOCALE, "cf %08x\n", cf);
651 data = GetClipboardData(cf);
652 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
654 cf = EnumClipboardFormats(cf);
655 ok(cf == CF_OEMTEXT, "cf %08x\n", cf);
656 data = GetClipboardData(cf);
657 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
659 cf = EnumClipboardFormats(cf);
660 ok(cf == CF_UNICODETEXT, "cf %08x\n", cf);
662 cf = EnumClipboardFormats(cf);
663 ok(cf == CF_METAFILEPICT, "cf %08x\n", cf);
664 data = GetClipboardData(cf);
665 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
667 cf = EnumClipboardFormats(cf);
668 ok(cf == 0, "cf %08x\n", cf);
670 r = EmptyClipboard();
671 ok(r, "gle %d\n", GetLastError());
673 SetClipboardData( CF_UNICODETEXT, create_textW() );
674 SetClipboardData( CF_TEXT, create_textA() );
675 SetClipboardData( CF_OEMTEXT, create_textA() );
676 r = CloseClipboard();
677 ok(r, "gle %d\n", GetLastError());
679 r = OpenClipboard( NULL );
680 ok(r, "gle %d\n", GetLastError());
681 SetLastError( 0xdeadbeef );
682 cf = EnumClipboardFormats(0);
683 ok( cf == CF_UNICODETEXT, "cf %08x\n", cf );
684 ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() );
685 SetLastError( 0xdeadbeef );
686 cf = EnumClipboardFormats(cf);
687 ok( cf == CF_TEXT, "cf %08x\n", cf );
688 ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() );
689 SetLastError( 0xdeadbeef );
690 cf = EnumClipboardFormats(cf);
691 ok( cf == CF_OEMTEXT, "cf %08x\n", cf );
692 ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() );
693 SetLastError( 0xdeadbeef );
694 cf = EnumClipboardFormats(cf);
695 ok( cf == CF_LOCALE, "cf %08x\n", cf );
696 ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() );
697 SetLastError( 0xdeadbeef );
698 cf = EnumClipboardFormats( cf );
699 ok( cf == 0, "cf %08x\n", cf );
700 ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() );
701 SetLastError( 0xdeadbeef );
702 cf = EnumClipboardFormats( 0xdead );
703 ok( cf == 0, "cf %08x\n", cf );
704 ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() );
706 r = EmptyClipboard();
707 ok(r, "gle %d\n", GetLastError());
709 r = CloseClipboard();
710 ok(r, "gle %d\n", GetLastError());
712 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
714 r = OpenClipboard(NULL);
715 ok(r, "%u: gle %d\n", i, GetLastError());
716 r = EmptyClipboard();
717 ok(r, "%u: gle %d\n", i, GetLastError());
719 switch (tests[i].format)
721 case CF_TEXT:
722 case CF_OEMTEXT:
723 SetClipboardData( tests[i].format, create_textA() );
724 break;
725 case CF_UNICODETEXT:
726 SetClipboardData( CF_UNICODETEXT, create_textW() );
727 break;
728 case CF_ENHMETAFILE:
729 SetClipboardData( CF_ENHMETAFILE, create_emf() );
730 break;
731 case CF_METAFILEPICT:
732 SetClipboardData( CF_METAFILEPICT, create_metafile() );
733 break;
734 case CF_BITMAP:
735 SetClipboardData( CF_BITMAP, create_bitmap() );
736 break;
737 case CF_DIB:
738 case CF_DIBV5:
739 SetClipboardData( tests[i].format, create_dib( tests[i].format == CF_DIBV5 ));
740 break;
743 count = CountClipboardFormats();
744 ok( count == 1, "%u: count %u\n", i, count );
746 r = CloseClipboard();
747 ok(r, "%u: gle %d\n", i, GetLastError());
749 count = CountClipboardFormats();
750 for (j = 0; tests[i].expected[j]; j++)
752 r = IsClipboardFormatAvailable( tests[i].expected[j] );
753 ok( r, "%u: %04x not available\n", i, tests[i].expected[j] );
755 ok( count == j, "%u: count %u instead of %u\n", i, count, j );
757 r = OpenClipboard( hwnd );
758 ok(r, "%u: gle %d\n", i, GetLastError());
759 cf = 0;
760 for (j = 0; tests[i].expected[j]; j++)
762 cf = EnumClipboardFormats( cf );
763 ok(cf == tests[i].expected[j], "%u.%u: got %04x instead of %04x\n",
764 i, j, cf, tests[i].expected[j] );
765 if (cf != tests[i].expected[j]) break;
766 data = GetClipboardData( cf );
767 ok(data != NULL ||
768 broken( tests[i].format == CF_DIBV5 && cf == CF_DIB ), /* >= Vista */
769 "%u: couldn't get data, cf %04x err %d\n", i, cf, GetLastError());
770 switch (cf)
772 case CF_LOCALE:
774 UINT *ptr = GlobalLock( data );
775 ok( GlobalSize( data ) == sizeof(*ptr), "%u: size %lu\n", i, GlobalSize( data ));
776 ok( *ptr == GetUserDefaultLCID() ||
777 broken( *ptr == MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT )),
778 "%u: CF_LOCALE %08x/%08x\n", i, *ptr, GetUserDefaultLCID() );
779 GlobalUnlock( data );
780 break;
782 case CF_TEXT:
783 case CF_OEMTEXT:
784 ok( GlobalSize( data ) == 10, "wrong len %ld\n", GlobalSize( data ));
785 break;
786 case CF_UNICODETEXT:
787 ok( GlobalSize( data ) == 10 * sizeof(WCHAR), "wrong len %ld\n", GlobalSize( data ));
788 break;
791 if (!tests[i].expected[j])
793 cf = EnumClipboardFormats( cf );
794 ok(cf == 0, "%u: cf %04x\n", i, cf);
797 /* now with delayed rendering */
799 r = EmptyClipboard();
800 ok(r, "%u: gle %d\n", i, GetLastError());
802 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
803 ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered );
805 SetClipboardData( tests[i].format, 0 );
806 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
807 ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered );
809 count = CountClipboardFormats();
810 ok( count == 1, "%u: count %u\n", i, count );
812 r = CloseClipboard();
813 ok(r, "%u: gle %d\n", i, GetLastError());
814 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
815 ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered );
817 count = CountClipboardFormats();
818 for (j = 0; tests[i].expected[j]; j++)
820 r = IsClipboardFormatAvailable( tests[i].expected[j] );
821 ok( r, "%u: %04x not available\n", i, tests[i].expected[j] );
823 ok( count == j, "%u: count %u instead of %u\n", i, count, j );
824 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
825 ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered );
827 r = OpenClipboard(NULL);
828 ok(r, "%u: gle %d\n", i, GetLastError());
829 cf = 0;
830 for (j = 0; tests[i].expected[j]; j++)
832 cf = EnumClipboardFormats( cf );
833 ok(cf == tests[i].expected[j], "%u.%u: got %04x instead of %04x\n",
834 i, j, cf, tests[i].expected[j] );
835 if (cf != tests[i].expected[j]) break;
836 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
837 ok( !rendered, "%u.%u: formats %08x have been rendered\n", i, j, rendered );
838 data = GetClipboardData( cf );
839 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
840 if (cf == CF_LOCALE)
842 ok(data != NULL, "%u: CF_LOCALE no data\n", i);
843 ok( !rendered, "%u.%u: formats %08x have been rendered\n", i, j, rendered );
845 else
847 ok(!data, "%u: format %04x got data %p\n", i, cf, data);
848 ok( rendered == (1 << tests[i].format),
849 "%u.%u: formats %08x have been rendered\n", i, j, rendered );
850 /* try to render a second time */
851 data = GetClipboardData( cf );
852 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
853 ok( rendered == (1 << tests[i].format),
854 "%u.%u: formats %08x have been rendered\n", i, j, rendered );
857 if (!tests[i].expected[j])
859 cf = EnumClipboardFormats( cf );
860 ok(cf == 0, "%u: cf %04x\n", i, cf);
862 r = CloseClipboard();
863 ok(r, "%u: gle %d\n", i, GetLastError());
864 rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
865 ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered );
868 r = OpenClipboard(NULL);
869 ok(r, "gle %d\n", GetLastError());
870 r = EmptyClipboard();
871 ok(r, "gle %d\n", GetLastError());
872 r = CloseClipboard();
873 ok(r, "gle %d\n", GetLastError());
874 DestroyWindow( hwnd );
877 static CRITICAL_SECTION clipboard_cs;
878 static HWND next_wnd;
879 static UINT wm_drawclipboard;
880 static UINT wm_clipboardupdate;
881 static UINT wm_destroyclipboard;
882 static UINT wm_renderformat;
883 static UINT nb_formats;
884 static BOOL cross_thread;
886 static LRESULT CALLBACK clipboard_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
888 LRESULT ret;
889 DWORD msg_flags = InSendMessageEx( NULL );
891 switch(msg) {
892 case WM_DRAWCLIPBOARD:
893 ok( msg_flags == (cross_thread ? ISMEX_NOTIFY : ISMEX_NOSEND),
894 "WM_DRAWCLIPBOARD wrong flags %x\n", msg_flags );
895 EnterCriticalSection(&clipboard_cs);
896 wm_drawclipboard++;
897 LeaveCriticalSection(&clipboard_cs);
898 break;
899 case WM_CHANGECBCHAIN:
900 ok( msg_flags == (cross_thread ? ISMEX_SEND : ISMEX_NOSEND),
901 "WM_CHANGECBCHAIN wrong flags %x\n", msg_flags );
902 if (next_wnd == (HWND)wp)
903 next_wnd = (HWND)lp;
904 else if (next_wnd)
905 SendMessageA(next_wnd, msg, wp, lp);
906 break;
907 case WM_DESTROYCLIPBOARD:
908 ok( msg_flags == (cross_thread ? ISMEX_SEND : ISMEX_NOSEND),
909 "WM_DESTROYCLIPBOARD wrong flags %x\n", msg_flags );
910 wm_destroyclipboard++;
911 ok( GetClipboardOwner() == hwnd, "WM_DESTROYCLIPBOARD owner %p\n", GetClipboardOwner() );
912 nb_formats = CountClipboardFormats();
913 break;
914 case WM_RENDERFORMAT:
915 ok( !wm_renderformat, "multiple WM_RENDERFORMAT %04x / %04lx\n", wm_renderformat, wp );
916 wm_renderformat = wp;
917 break;
918 case WM_CLIPBOARDUPDATE:
919 ok( msg_flags == ISMEX_NOSEND, "WM_CLIPBOARDUPDATE wrong flags %x\n", msg_flags );
920 EnterCriticalSection(&clipboard_cs);
921 wm_clipboardupdate++;
922 LeaveCriticalSection(&clipboard_cs);
923 break;
924 case WM_USER:
925 ChangeClipboardChain(hwnd, next_wnd);
926 PostQuitMessage(0);
927 break;
928 case WM_USER+1:
929 ret = wm_drawclipboard;
930 wm_drawclipboard = 0;
931 return ret;
932 case WM_USER+2:
933 ret = wm_clipboardupdate;
934 wm_clipboardupdate = 0;
935 return ret;
936 case WM_USER+3:
937 ret = wm_destroyclipboard;
938 wm_destroyclipboard = 0;
939 return ret;
940 case WM_USER+4:
941 ret = wm_renderformat;
942 wm_renderformat = 0;
943 return ret;
944 case WM_USER+5:
945 return nb_formats;
948 return DefWindowProcA(hwnd, msg, wp, lp);
951 static DWORD WINAPI clipboard_thread(void *param)
953 HWND ret, win = param;
954 BOOL r;
955 MSG msg;
956 HANDLE handle;
957 UINT count, fmt, formats, old_seq = 0, seq;
959 cross_thread = (GetWindowThreadProcessId( win, NULL ) != GetCurrentThreadId());
960 trace( "%s-threaded test\n", cross_thread ? "multi" : "single" );
962 if (pGetClipboardSequenceNumber) old_seq = pGetClipboardSequenceNumber();
964 EnterCriticalSection(&clipboard_cs);
965 SetLastError(0xdeadbeef);
966 next_wnd = SetClipboardViewer(win);
967 ok(GetLastError() == 0xdeadbeef, "GetLastError = %d\n", GetLastError());
968 LeaveCriticalSection(&clipboard_cs);
970 SetLastError( 0xdeadbeef );
971 ret = SetClipboardViewer( (HWND)0xdead );
972 ok( !ret, "SetClipboardViewer succeeded\n" );
973 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
974 SetLastError( 0xdeadbeef );
975 r = ChangeClipboardChain( win, (HWND)0xdead );
976 ok( !r, "ChangeClipboardChain succeeded\n" );
977 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
978 SetLastError( 0xdeadbeef );
979 r = ChangeClipboardChain( (HWND)0xdead, next_wnd );
980 ok( !r, "ChangeClipboardChain succeeded\n" );
981 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
983 if (pAddClipboardFormatListener)
985 r = pAddClipboardFormatListener(win);
986 ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError());
987 SetLastError( 0xdeadbeef );
988 r = pAddClipboardFormatListener( win );
989 ok( !r, "AddClipboardFormatListener succeeded\n" );
990 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
991 SetLastError( 0xdeadbeef );
992 r = pAddClipboardFormatListener( (HWND)0xdead );
993 ok( !r, "AddClipboardFormatListener succeeded\n" );
994 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
995 r = pAddClipboardFormatListener( GetDesktopWindow() );
996 ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError());
997 r = pRemoveClipboardFormatListener( GetDesktopWindow() );
998 ok( r, "RemoveClipboardFormatListener failed err %d\n", GetLastError());
1001 if (pGetClipboardSequenceNumber)
1003 seq = pGetClipboardSequenceNumber();
1004 ok( seq == old_seq, "sequence changed\n" );
1006 if (!cross_thread)
1008 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1009 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1010 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1011 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1013 count = SendMessageA( win, WM_USER + 1, 0, 0 );
1014 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1015 count = SendMessageA( win, WM_USER+2, 0, 0 );
1016 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1017 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1018 ok( !fmt, "WM_RENDERFORMAT received\n" );
1020 SetLastError( 0xdeadbeef );
1021 r = OpenClipboard( (HWND)0xdead );
1022 ok( !r, "OpenClipboard succeeded\n" );
1023 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
1025 r = OpenClipboard(win);
1026 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1028 if (pGetClipboardSequenceNumber)
1030 seq = pGetClipboardSequenceNumber();
1031 ok( seq == old_seq, "sequence changed\n" );
1033 if (!cross_thread)
1035 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1036 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1037 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1038 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1040 count = SendMessageA( win, WM_USER+1, 0, 0 );
1041 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1042 count = SendMessageA( win, WM_USER+2, 0, 0 );
1043 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1044 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1045 ok( !fmt, "WM_RENDERFORMAT received\n" );
1047 r = EmptyClipboard();
1048 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
1050 if (pGetClipboardSequenceNumber)
1052 seq = pGetClipboardSequenceNumber();
1053 ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1054 old_seq = seq;
1056 if (!cross_thread)
1058 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1059 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1060 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1061 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1063 count = SendMessageA( win, WM_USER+1, 0, 0 );
1064 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1065 count = SendMessageA( win, WM_USER+2, 0, 0 );
1066 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1067 count = SendMessageA( win, WM_USER+3, 0, 0 );
1068 ok( !count, "WM_DESTROYCLIPBOARD received\n" );
1069 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1070 ok( !fmt, "WM_RENDERFORMAT received\n" );
1072 r = EmptyClipboard();
1073 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
1074 /* sequence changes again, even though it was already empty */
1075 if (pGetClipboardSequenceNumber)
1077 seq = pGetClipboardSequenceNumber();
1078 ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1079 old_seq = seq;
1081 if (!cross_thread)
1083 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1084 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1085 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1086 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1088 count = SendMessageA( win, WM_USER+1, 0, 0 );
1089 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1090 count = SendMessageA( win, WM_USER+2, 0, 0 );
1091 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1092 count = SendMessageA( win, WM_USER+3, 0, 0 );
1093 ok( count, "WM_DESTROYCLIPBOARD not received\n" );
1094 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1095 ok( !fmt, "WM_RENDERFORMAT received\n" );
1096 count = SendMessageA( win, WM_USER+5, 0, 0 );
1097 ok( !count, "wrong format count %u on WM_DESTROYCLIPBOARD\n", count );
1099 handle = SetClipboardData( CF_TEXT, create_textA() );
1100 ok(handle != 0, "SetClipboardData failed: %d\n", GetLastError());
1102 if (pGetClipboardSequenceNumber)
1104 seq = pGetClipboardSequenceNumber();
1105 ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1106 old_seq = seq;
1108 if (!cross_thread)
1110 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1111 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1112 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1113 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1115 count = SendMessageA( win, WM_USER+1, 0, 0 );
1116 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1117 count = SendMessageA( win, WM_USER+2, 0, 0 );
1118 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1119 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1120 ok( !fmt, "WM_RENDERFORMAT received\n" );
1122 SetClipboardData( CF_UNICODETEXT, 0 );
1124 if (pGetClipboardSequenceNumber)
1126 seq = pGetClipboardSequenceNumber();
1127 ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1128 old_seq = seq;
1130 if (!cross_thread)
1132 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1133 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1134 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1135 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1137 count = SendMessageA( win, WM_USER+1, 0, 0 );
1138 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1139 count = SendMessageA( win, WM_USER+2, 0, 0 );
1140 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1141 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1142 ok( !fmt, "WM_RENDERFORMAT received\n" );
1144 SetClipboardData( CF_UNICODETEXT, 0 ); /* same data again */
1146 if (pGetClipboardSequenceNumber)
1148 seq = pGetClipboardSequenceNumber();
1149 ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1150 old_seq = seq;
1152 if (!cross_thread)
1154 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1155 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1156 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1157 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1159 count = SendMessageA( win, WM_USER+1, 0, 0 );
1160 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1161 count = SendMessageA( win, WM_USER+2, 0, 0 );
1162 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1163 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1164 ok( !fmt, "WM_RENDERFORMAT received\n" );
1166 ok( IsClipboardFormatAvailable( CF_TEXT ), "CF_TEXT available\n" );
1167 ok( IsClipboardFormatAvailable( CF_UNICODETEXT ), "CF_UNICODETEXT available\n" );
1168 ok( !IsClipboardFormatAvailable( CF_OEMTEXT ), "CF_OEMTEXT available\n" );
1170 EnterCriticalSection(&clipboard_cs);
1171 r = CloseClipboard();
1172 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1173 LeaveCriticalSection(&clipboard_cs);
1175 if (pGetClipboardSequenceNumber)
1177 seq = pGetClipboardSequenceNumber();
1178 ok( (int)(seq - old_seq) == 2, "sequence diff %d\n", seq - old_seq );
1179 old_seq = seq;
1181 if (!cross_thread)
1183 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1184 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1185 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1186 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1188 count = SendMessageA( win, WM_USER+1, 0, 0 );
1189 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1190 count = SendMessageA( win, WM_USER+2, 0, 0 );
1191 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1192 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1193 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1195 r = OpenClipboard(win);
1196 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1198 if (pGetClipboardSequenceNumber)
1200 seq = pGetClipboardSequenceNumber();
1201 ok( seq == old_seq, "sequence changed\n" );
1203 if (!cross_thread)
1205 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1206 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1207 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1209 count = SendMessageA( win, WM_USER+1, 0, 0 );
1210 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1211 count = SendMessageA( win, WM_USER+2, 0, 0 );
1212 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1213 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1214 ok( !fmt, "WM_RENDERFORMAT received\n" );
1216 ok( IsClipboardFormatAvailable( CF_TEXT ), "CF_TEXT available\n" );
1217 ok( IsClipboardFormatAvailable( CF_UNICODETEXT ), "CF_UNICODETEXT available\n" );
1218 ok( IsClipboardFormatAvailable( CF_OEMTEXT ), "CF_OEMTEXT available\n" );
1220 ok( GetClipboardOwner() == win, "wrong owner %p\n", GetClipboardOwner());
1221 handle = GetClipboardData( CF_UNICODETEXT );
1222 ok( !handle, "got data for CF_UNICODETEXT\n" );
1223 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1224 ok( fmt == CF_UNICODETEXT, "WM_RENDERFORMAT received %04x\n", fmt );
1226 handle = GetClipboardData( CF_OEMTEXT );
1227 ok( !handle, "got data for CF_OEMTEXT\n" );
1228 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1229 ok( fmt == CF_UNICODETEXT, "WM_RENDERFORMAT received %04x\n", fmt );
1231 SetClipboardData( CF_WAVE, 0 );
1232 if (pGetClipboardSequenceNumber)
1234 seq = pGetClipboardSequenceNumber();
1235 ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1236 old_seq = seq;
1238 if (!cross_thread)
1240 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1241 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1242 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1243 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1245 count = SendMessageA( win, WM_USER+1, 0, 0 );
1246 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1247 count = SendMessageA( win, WM_USER+2, 0, 0 );
1248 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1249 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1250 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1252 r = CloseClipboard();
1253 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1254 if (pGetClipboardSequenceNumber)
1256 /* no synthesized format, so CloseClipboard doesn't change the sequence */
1257 seq = pGetClipboardSequenceNumber();
1258 ok( seq == old_seq, "sequence changed\n" );
1259 old_seq = seq;
1261 if (!cross_thread)
1263 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1264 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1265 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1266 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1268 count = SendMessageA( win, WM_USER+1, 0, 0 );
1269 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1270 count = SendMessageA( win, WM_USER+2, 0, 0 );
1271 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1272 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1273 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1275 r = OpenClipboard(win);
1276 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1277 r = CloseClipboard();
1278 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1279 /* nothing changed */
1280 if (pGetClipboardSequenceNumber)
1282 seq = pGetClipboardSequenceNumber();
1283 ok( seq == old_seq, "sequence changed\n" );
1285 if (!cross_thread)
1287 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1288 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1289 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1290 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1292 count = SendMessageA( win, WM_USER+1, 0, 0 );
1293 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1294 count = SendMessageA( win, WM_USER+2, 0, 0 );
1295 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1296 count = SendMessageA( win, WM_USER+3, 0, 0 );
1297 ok( !count, "WM_DESTROYCLIPBOARD received\n" );
1298 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1299 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1301 formats = CountClipboardFormats();
1302 r = OpenClipboard(0);
1303 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1304 r = EmptyClipboard();
1305 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
1306 r = CloseClipboard();
1307 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1309 if (!cross_thread)
1311 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1312 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1313 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1314 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1316 count = SendMessageA( win, WM_USER+1, 0, 0 );
1317 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1318 count = SendMessageA( win, WM_USER+2, 0, 0 );
1319 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1320 count = SendMessageA( win, WM_USER+3, 0, 0 );
1321 ok( count == 1, "WM_DESTROYCLIPBOARD not received\n" );
1322 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1323 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1324 count = SendMessageA( win, WM_USER+5, 0, 0 );
1325 ok( count == formats, "wrong format count %u on WM_DESTROYCLIPBOARD\n", count );
1327 r = OpenClipboard(win);
1328 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1329 SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_FIXED, 1 ));
1330 if (pGetClipboardSequenceNumber)
1332 seq = pGetClipboardSequenceNumber();
1333 ok( (int)(seq - old_seq) == 2, "sequence diff %d\n", seq - old_seq );
1334 old_seq = seq;
1336 if (!cross_thread)
1338 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1339 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1340 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1341 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1343 count = SendMessageA( win, WM_USER+1, 0, 0 );
1344 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1345 count = SendMessageA( win, WM_USER+2, 0, 0 );
1346 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1347 count = SendMessageA( win, WM_USER+3, 0, 0 );
1348 ok( !count, "WM_DESTROYCLIPBOARD received\n" );
1349 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1350 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1352 EnterCriticalSection(&clipboard_cs);
1353 r = CloseClipboard();
1354 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1355 LeaveCriticalSection(&clipboard_cs);
1357 if (pGetClipboardSequenceNumber)
1359 seq = pGetClipboardSequenceNumber();
1360 ok( seq == old_seq, "sequence changed\n" );
1361 old_seq = seq;
1363 if (!cross_thread)
1365 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1366 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1367 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1368 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1370 count = SendMessageA( win, WM_USER+1, 0, 0 );
1371 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1372 count = SendMessageA( win, WM_USER+2, 0, 0 );
1373 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1374 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1375 ok( !fmt, "WM_RENDERFORMAT received\n" );
1377 run_process( "grab_clipboard 0" );
1379 if (pGetClipboardSequenceNumber)
1381 seq = pGetClipboardSequenceNumber();
1382 ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1383 old_seq = seq;
1385 if (!cross_thread)
1387 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1388 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1389 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1390 /* in this case we get a cross-thread WM_DRAWCLIPBOARD */
1391 cross_thread = TRUE;
1392 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1393 cross_thread = FALSE;
1395 count = SendMessageA( win, WM_USER+1, 0, 0 );
1396 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1397 count = SendMessageA( win, WM_USER+2, 0, 0 );
1398 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1399 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1400 ok( !fmt, "WM_RENDERFORMAT received\n" );
1402 r = OpenClipboard(0);
1403 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1404 SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_FIXED, 1 ));
1405 if (pGetClipboardSequenceNumber)
1407 seq = pGetClipboardSequenceNumber();
1408 ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1409 old_seq = seq;
1411 if (!cross_thread)
1413 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1414 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1415 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1416 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1418 count = SendMessageA( win, WM_USER+1, 0, 0 );
1419 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1420 count = SendMessageA( win, WM_USER+2, 0, 0 );
1421 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1422 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1423 ok( !fmt, "WM_RENDERFORMAT received\n" );
1425 EnterCriticalSection(&clipboard_cs);
1426 r = CloseClipboard();
1427 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1428 LeaveCriticalSection(&clipboard_cs);
1430 if (pGetClipboardSequenceNumber)
1432 seq = pGetClipboardSequenceNumber();
1433 ok( seq == old_seq, "sequence changed\n" );
1434 old_seq = seq;
1436 if (!cross_thread)
1438 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD received\n" );
1439 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1440 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1441 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1443 count = SendMessageA( win, WM_USER+1, 0, 0 );
1444 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1445 count = SendMessageA( win, WM_USER+2, 0, 0 );
1446 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1447 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1448 ok( !fmt, "WM_RENDERFORMAT received\n" );
1450 run_process( "grab_clipboard 1" );
1452 if (pGetClipboardSequenceNumber)
1454 seq = pGetClipboardSequenceNumber();
1455 ok( (int)(seq - old_seq) == 2, "sequence diff %d\n", seq - old_seq );
1456 old_seq = seq;
1458 if (!cross_thread)
1460 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1461 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1462 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1463 /* in this case we get a cross-thread WM_DRAWCLIPBOARD */
1464 cross_thread = TRUE;
1465 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1466 cross_thread = FALSE;
1468 count = SendMessageA( win, WM_USER+1, 0, 0 );
1469 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1470 count = SendMessageA( win, WM_USER+2, 0, 0 );
1471 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1472 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1473 ok( !fmt, "WM_RENDERFORMAT received\n" );
1475 r = OpenClipboard(0);
1476 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1477 SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_FIXED, 1 ));
1478 if (pGetClipboardSequenceNumber)
1480 seq = pGetClipboardSequenceNumber();
1481 ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
1482 old_seq = seq;
1484 if (!cross_thread)
1486 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1487 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1488 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1489 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1491 count = SendMessageA( win, WM_USER+1, 0, 0 );
1492 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1493 count = SendMessageA( win, WM_USER+2, 0, 0 );
1494 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1495 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1496 ok( !fmt, "WM_RENDERFORMAT received\n" );
1498 EnterCriticalSection(&clipboard_cs);
1499 r = CloseClipboard();
1500 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1501 LeaveCriticalSection(&clipboard_cs);
1503 if (pGetClipboardSequenceNumber)
1505 seq = pGetClipboardSequenceNumber();
1506 ok( seq == old_seq, "sequence changed\n" );
1507 old_seq = seq;
1509 if (!cross_thread)
1511 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1512 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1513 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1514 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1516 count = SendMessageA( win, WM_USER+1, 0, 0 );
1517 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1518 count = SendMessageA( win, WM_USER+2, 0, 0 );
1519 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1520 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1521 ok( !fmt, "WM_RENDERFORMAT received\n" );
1523 r = PostMessageA(win, WM_USER, 0, 0);
1524 ok(r, "PostMessage failed: %d\n", GetLastError());
1526 if (pRemoveClipboardFormatListener)
1528 r = pRemoveClipboardFormatListener(win);
1529 ok( r, "RemoveClipboardFormatListener failed err %d\n", GetLastError());
1530 SetLastError( 0xdeadbeef );
1531 r = pRemoveClipboardFormatListener(win);
1532 ok( !r, "RemoveClipboardFormatListener succeeded\n" );
1533 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1534 SetLastError( 0xdeadbeef );
1535 r = pRemoveClipboardFormatListener( (HWND)0xdead );
1536 ok( !r, "RemoveClipboardFormatListener succeeded\n" );
1537 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
1539 return 0;
1542 static void test_messages(void)
1544 WNDCLASSA cls;
1545 HWND win;
1546 MSG msg;
1547 HANDLE thread;
1548 DWORD tid;
1550 InitializeCriticalSection(&clipboard_cs);
1552 memset(&cls, 0, sizeof(cls));
1553 cls.lpfnWndProc = clipboard_wnd_proc;
1554 cls.hInstance = GetModuleHandleA(NULL);
1555 cls.lpszClassName = "clipboard_test";
1556 RegisterClassA(&cls);
1558 win = CreateWindowA("clipboard_test", NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0);
1559 ok(win != NULL, "CreateWindow failed: %d\n", GetLastError());
1561 thread = CreateThread(NULL, 0, clipboard_thread, (void*)win, 0, &tid);
1562 ok(thread != NULL, "CreateThread failed: %d\n", GetLastError());
1564 while(GetMessageA(&msg, NULL, 0, 0))
1566 ok( msg.message != WM_DRAWCLIPBOARD, "WM_DRAWCLIPBOARD was posted\n" );
1567 TranslateMessage(&msg);
1568 DispatchMessageA(&msg);
1571 ok(WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1572 CloseHandle(thread);
1574 DestroyWindow( win );
1576 /* same tests again but inside a single thread */
1578 win = CreateWindowA( "clipboard_test", NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0 );
1579 ok( win != NULL, "CreateWindow failed: %d\n", GetLastError() );
1581 clipboard_thread( win );
1582 DestroyWindow( win );
1584 UnregisterClassA("clipboard_test", GetModuleHandleA(NULL));
1585 DeleteCriticalSection(&clipboard_cs);
1588 static BOOL is_moveable( HANDLE handle )
1590 void *ptr = GlobalLock( handle );
1591 if (ptr) GlobalUnlock( handle );
1592 return ptr && ptr != handle;
1595 static BOOL is_fixed( HANDLE handle )
1597 void *ptr = GlobalLock( handle );
1598 if (ptr) GlobalUnlock( handle );
1599 return ptr && ptr == handle;
1602 static BOOL is_freed( HANDLE handle )
1604 return !GlobalSize( handle );
1607 static UINT format_id;
1608 static HBITMAP bitmap, bitmap2;
1609 static HPALETTE palette;
1610 static const LOGPALETTE logpalette = { 0x300, 1, {{ 0x12, 0x34, 0x56, 0x78 }}};
1612 static void test_handles( HWND hwnd )
1614 HGLOBAL h, htext, htext2, htext3, htext4, htext5;
1615 HGLOBAL hfixed, hfixed2, hmoveable, empty_fixed, empty_moveable;
1616 void *ptr;
1617 UINT format_id2 = RegisterClipboardFormatA( "another format" );
1618 BOOL r;
1619 HANDLE data;
1620 HBITMAP bitmap_temp;
1621 DWORD process;
1622 BOOL is_owner = (GetWindowThreadProcessId( hwnd, &process ) && process == GetCurrentProcessId());
1624 trace( "hwnd %p\n", hwnd );
1625 htext = create_textA();
1626 htext2 = create_textA();
1627 htext3 = create_textA();
1628 htext4 = create_textA();
1629 htext5 = create_textA();
1630 bitmap = CreateBitmap( 10, 10, 1, 1, NULL );
1631 bitmap2 = CreateBitmap( 10, 10, 1, 1, NULL );
1632 palette = CreatePalette( &logpalette );
1634 hfixed = GlobalAlloc( GMEM_FIXED, 17 );
1635 hfixed2 = GlobalAlloc( GMEM_FIXED, 17 );
1636 ok( is_fixed( hfixed ), "expected fixed mem %p\n", hfixed );
1637 ok( GlobalSize( hfixed ) == 17, "wrong size %lu\n", GlobalSize( hfixed ));
1639 hmoveable = GlobalAlloc( GMEM_MOVEABLE, 23 );
1640 ok( is_moveable( hmoveable ), "expected moveable mem %p\n", hmoveable );
1641 ok( GlobalSize( hmoveable ) == 23, "wrong size %lu\n", GlobalSize( hmoveable ));
1643 empty_fixed = GlobalAlloc( GMEM_FIXED, 0 );
1644 ok( is_fixed( empty_fixed ), "expected fixed mem %p\n", empty_fixed );
1646 empty_moveable = GlobalAlloc( GMEM_MOVEABLE, 0 );
1647 /* discarded handles can't be GlobalLock'ed */
1648 ok( is_freed( empty_moveable ), "expected free mem %p\n", empty_moveable );
1650 r = OpenClipboard( hwnd );
1651 ok( r, "gle %d\n", GetLastError() );
1652 r = EmptyClipboard();
1653 ok( r, "gle %d\n", GetLastError() );
1655 h = SetClipboardData( CF_TEXT, htext );
1656 ok( h == htext, "got %p\n", h );
1657 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1658 h = SetClipboardData( format_id, htext2 );
1659 ok( h == htext2, "got %p\n", h );
1660 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1661 bitmap_temp = CreateBitmap( 10, 10, 1, 1, NULL );
1662 h = SetClipboardData( CF_BITMAP, bitmap_temp );
1663 ok( h == bitmap_temp, "got %p\n", h );
1664 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1665 h = SetClipboardData( CF_BITMAP, bitmap );
1666 ok( h == bitmap, "got %p\n", h );
1667 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1668 ok( !GetObjectType( bitmap_temp ), "expected free object %p\n", bitmap_temp );
1669 h = SetClipboardData( CF_DSPBITMAP, bitmap2 );
1670 ok( h == bitmap2, "got %p\n", h );
1671 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1672 h = SetClipboardData( CF_PALETTE, palette );
1673 ok( h == palette, "got %p\n", h );
1674 ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
1675 h = SetClipboardData( CF_GDIOBJFIRST + 3, htext3 );
1676 ok( h == htext3, "got %p\n", h );
1677 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1678 h = SetClipboardData( CF_PRIVATEFIRST + 7, htext5 );
1679 ok( h == htext5, "got %p\n", h );
1680 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1681 h = SetClipboardData( format_id2, empty_moveable );
1682 ok( !h, "got %p\n", h );
1683 GlobalFree( empty_moveable );
1685 if (0) /* crashes on vista64 */
1687 ptr = HeapAlloc( GetProcessHeap(), 0, 0 );
1688 h = SetClipboardData( format_id2, ptr );
1689 ok( !h, "got %p\n", h );
1690 HeapFree( GetProcessHeap(), 0, ptr );
1693 h = SetClipboardData( format_id2, empty_fixed );
1694 ok( h == empty_fixed, "got %p\n", h );
1695 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1696 h = SetClipboardData( 0xdeadbeef, hfixed2 );
1697 ok( h == hfixed2, "got %p\n", h );
1698 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1699 h = SetClipboardData( 0xdeadbabe, hmoveable );
1700 ok( h == hmoveable, "got %p\n", h );
1701 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1703 ptr = HeapAlloc( GetProcessHeap(), 0, 37 );
1704 h = SetClipboardData( 0xdeadfade, ptr );
1705 ok( h == ptr || !h, "got %p\n", h );
1706 if (!h) /* heap blocks are rejected on >= win8 */
1708 HeapFree( GetProcessHeap(), 0, ptr );
1709 ptr = NULL;
1712 data = GetClipboardData( CF_TEXT );
1713 ok( data == htext, "wrong data %p\n", data );
1714 ok( is_moveable( data ), "expected moveable mem %p\n", data );
1716 data = GetClipboardData( format_id );
1717 ok( data == htext2, "wrong data %p, cf %08x\n", data, format_id );
1718 ok( is_moveable( data ), "expected moveable mem %p\n", data );
1720 data = GetClipboardData( CF_GDIOBJFIRST + 3 );
1721 ok( data == htext3, "wrong data %p\n", data );
1722 ok( is_moveable( data ), "expected moveable mem %p\n", data );
1724 data = GetClipboardData( CF_PRIVATEFIRST + 7 );
1725 ok( data == htext5, "wrong data %p\n", data );
1726 ok( is_moveable( data ), "expected moveable mem %p\n", data );
1728 data = GetClipboardData( format_id2 );
1729 ok( data == empty_fixed, "wrong data %p\n", data );
1730 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1732 data = GetClipboardData( 0xdeadbeef );
1733 ok( data == hfixed2, "wrong data %p\n", data );
1734 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1736 data = GetClipboardData( 0xdeadbabe );
1737 ok( data == hmoveable, "wrong data %p\n", data );
1738 ok( is_moveable( data ), "expected moveable mem %p\n", data );
1740 data = GetClipboardData( 0xdeadfade );
1741 ok( data == ptr, "wrong data %p\n", data );
1743 h = SetClipboardData( CF_PRIVATEFIRST + 7, htext4 );
1744 ok( h == htext4, "got %p\n", h );
1745 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1746 ok( is_freed( htext5 ), "expected freed mem %p\n", htext5 );
1748 h = SetClipboardData( 0xdeadbeef, hfixed );
1749 ok( h == hfixed, "got %p\n", h );
1750 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1751 #ifndef _WIN64
1752 /* testing if hfixed2 is freed triggers an exception on Win64 */
1753 ok( is_freed( hfixed2 ) || broken( !is_freed( hfixed2 )) /* < Vista */, "expected freed mem %p\n", hfixed2 );
1754 #endif
1756 r = CloseClipboard();
1757 ok( r, "gle %d\n", GetLastError() );
1759 /* data handles are still valid */
1760 ok( is_moveable( htext ), "expected moveable mem %p\n", htext );
1761 ok( is_moveable( htext2 ), "expected moveable mem %p\n", htext2 );
1762 ok( is_moveable( htext3 ), "expected moveable mem %p\n", htext3 );
1763 ok( is_moveable( htext4 ), "expected moveable mem %p\n", htext4 );
1764 ok( GetObjectType( bitmap ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap );
1765 ok( GetObjectType( bitmap2 ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap2 );
1766 ok( GetObjectType( palette ) == OBJ_PAL, "expected palette %p\n", palette );
1767 ok( is_fixed( hfixed ), "expected fixed mem %p\n", hfixed );
1768 ok( is_moveable( hmoveable ), "expected moveable mem %p\n", hmoveable );
1769 ok( is_fixed( empty_fixed ), "expected fixed mem %p\n", empty_fixed );
1771 r = OpenClipboard( hwnd );
1772 ok( r, "gle %d\n", GetLastError() );
1774 /* and now they are freed, unless we are the owner */
1775 if (!is_owner)
1777 ok( is_freed( htext ), "expected freed mem %p\n", htext );
1778 ok( is_freed( htext2 ), "expected freed mem %p\n", htext2 );
1779 ok( is_freed( htext3 ), "expected freed mem %p\n", htext3 );
1780 ok( is_freed( htext4 ), "expected freed mem %p\n", htext4 );
1781 ok( is_freed( hmoveable ), "expected freed mem %p\n", hmoveable );
1783 data = GetClipboardData( CF_TEXT );
1784 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1786 data = GetClipboardData( format_id );
1787 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1789 data = GetClipboardData( CF_GDIOBJFIRST + 3 );
1790 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1792 data = GetClipboardData( CF_PRIVATEFIRST + 7 );
1793 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1795 data = GetClipboardData( format_id2 );
1796 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1797 ok( GlobalSize( data ) == 1, "wrong size %lu\n", GlobalSize( data ));
1799 data = GetClipboardData( 0xdeadbeef );
1800 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1801 ok( GlobalSize( data ) == 17, "wrong size %lu\n", GlobalSize( data ));
1803 data = GetClipboardData( 0xdeadbabe );
1804 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1805 ok( GlobalSize( data ) == 23, "wrong size %lu\n", GlobalSize( data ));
1807 data = GetClipboardData( 0xdeadfade );
1808 ok( is_fixed( data ) || !ptr, "expected fixed mem %p\n", data );
1809 if (ptr) ok( GlobalSize( data ) == 37, "wrong size %lu\n", GlobalSize( data ));
1811 else
1813 ok( is_moveable( htext ), "expected moveable mem %p\n", htext );
1814 ok( is_moveable( htext2 ), "expected moveable mem %p\n", htext2 );
1815 ok( is_moveable( htext3 ), "expected moveable mem %p\n", htext3 );
1816 ok( is_moveable( htext4 ), "expected moveable mem %p\n", htext4 );
1817 ok( is_moveable( hmoveable ), "expected moveable mem %p\n", hmoveable );
1819 data = GetClipboardData( CF_TEXT );
1820 ok( data == htext, "wrong data %p\n", data );
1822 data = GetClipboardData( format_id );
1823 ok( data == htext2, "wrong data %p, cf %08x\n", data, format_id );
1825 data = GetClipboardData( CF_GDIOBJFIRST + 3 );
1826 ok( data == htext3, "wrong data %p\n", data );
1828 data = GetClipboardData( CF_PRIVATEFIRST + 7 );
1829 ok( data == htext4, "wrong data %p\n", data );
1831 data = GetClipboardData( format_id2 );
1832 ok( data == empty_fixed, "wrong data %p\n", data );
1834 data = GetClipboardData( 0xdeadbeef );
1835 ok( data == hfixed, "wrong data %p\n", data );
1837 data = GetClipboardData( 0xdeadbabe );
1838 ok( data == hmoveable, "wrong data %p\n", data );
1840 data = GetClipboardData( 0xdeadfade );
1841 ok( data == ptr, "wrong data %p\n", data );
1844 data = GetClipboardData( CF_OEMTEXT );
1845 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1846 data = GetClipboardData( CF_UNICODETEXT );
1847 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1848 data = GetClipboardData( CF_LOCALE );
1849 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1850 data = GetClipboardData( CF_BITMAP );
1851 ok( data == bitmap, "expected bitmap %p\n", data );
1852 data = GetClipboardData( CF_DSPBITMAP );
1853 ok( data == bitmap2, "expected bitmap %p\n", data );
1854 data = GetClipboardData( CF_PALETTE );
1855 ok( data == palette, "expected palette %p\n", data );
1856 data = GetClipboardData( CF_DIB );
1857 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1858 data = GetClipboardData( CF_DIBV5 );
1859 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1861 ok( GetObjectType( bitmap ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap );
1862 ok( GetObjectType( bitmap2 ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap2 );
1863 ok( GetObjectType( palette ) == OBJ_PAL, "expected palette %p\n", palette );
1864 ok( is_fixed( hfixed ), "expected fixed mem %p\n", hfixed );
1865 ok( is_fixed( empty_fixed ), "expected fixed mem %p\n", empty_fixed );
1867 r = EmptyClipboard();
1868 ok( r, "gle %d\n", GetLastError() );
1870 /* w2003, w2008 don't seem to free the data here */
1871 ok( is_freed( htext ) || broken( !is_freed( htext )), "expected freed mem %p\n", htext );
1872 ok( is_freed( htext2 ) || broken( !is_freed( htext2 )), "expected freed mem %p\n", htext2 );
1873 ok( is_freed( htext3 ) || broken( !is_freed( htext3 )), "expected freed mem %p\n", htext3 );
1874 ok( is_freed( htext4 ) || broken( !is_freed( htext4 )), "expected freed mem %p\n", htext4 );
1875 ok( is_freed( hmoveable ) || broken( !is_freed( hmoveable )), "expected freed mem %p\n", hmoveable );
1876 ok( is_fixed( empty_fixed ), "expected fixed mem %p\n", empty_fixed );
1877 ok( is_fixed( hfixed ), "expected fixed mem %p\n", hfixed );
1878 ok( !GetObjectType( bitmap ), "expected freed handle %p\n", bitmap );
1879 ok( !GetObjectType( bitmap2 ), "expected freed handle %p\n", bitmap2 );
1880 ok( !GetObjectType( palette ), "expected freed handle %p\n", palette );
1882 r = CloseClipboard();
1883 ok( r, "gle %d\n", GetLastError() );
1886 static DWORD WINAPI test_handles_thread( void *arg )
1888 trace( "running from different thread\n" );
1889 test_handles( (HWND)arg );
1890 return 0;
1893 static DWORD WINAPI test_handles_thread2( void *arg )
1895 BOOL r;
1896 HANDLE h;
1897 char *ptr;
1899 r = OpenClipboard( 0 );
1900 ok( r, "gle %d\n", GetLastError() );
1901 h = GetClipboardData( CF_TEXT );
1902 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1903 ptr = GlobalLock( h );
1904 if (ptr) ok( !strcmp( "test", ptr ), "wrong data '%.5s'\n", ptr );
1905 GlobalUnlock( h );
1906 h = GetClipboardData( format_id );
1907 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1908 ptr = GlobalLock( h );
1909 if (ptr) ok( !strcmp( "test", ptr ), "wrong data '%.5s'\n", ptr );
1910 GlobalUnlock( h );
1911 h = GetClipboardData( CF_GDIOBJFIRST + 3 );
1912 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1913 ptr = GlobalLock( h );
1914 if (ptr) ok( !strcmp( "test", ptr ), "wrong data '%.5s'\n", ptr );
1915 GlobalUnlock( h );
1916 trace( "gdiobj %p\n", h );
1917 h = GetClipboardData( CF_PRIVATEFIRST + 7 );
1918 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1919 ptr = GlobalLock( h );
1920 if (ptr) ok( !strcmp( "test", ptr ), "wrong data '%.5s'\n", ptr );
1921 GlobalUnlock( h );
1922 trace( "private %p\n", h );
1923 h = GetClipboardData( CF_BITMAP );
1924 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1925 ok( h == bitmap, "different bitmap %p / %p\n", h, bitmap );
1926 trace( "bitmap %p\n", h );
1927 h = GetClipboardData( CF_DSPBITMAP );
1928 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1929 ok( h == bitmap2, "different bitmap %p / %p\n", h, bitmap2 );
1930 trace( "bitmap2 %p\n", h );
1931 h = GetClipboardData( CF_PALETTE );
1932 ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
1933 ok( h == palette, "different palette %p / %p\n", h, palette );
1934 trace( "palette %p\n", h );
1935 h = GetClipboardData( CF_DIB );
1936 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1937 h = GetClipboardData( CF_DIBV5 );
1938 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1939 r = CloseClipboard();
1940 ok( r, "gle %d\n", GetLastError() );
1941 return 0;
1944 static void test_handles_process( const char *str )
1946 BOOL r;
1947 HANDLE h;
1948 char *ptr;
1949 BITMAP bm;
1950 PALETTEENTRY entry;
1951 BYTE buffer[1024];
1953 format_id = RegisterClipboardFormatA( "my_cool_clipboard_format" );
1954 r = OpenClipboard( 0 );
1955 ok( r, "gle %d\n", GetLastError() );
1956 h = GetClipboardData( CF_TEXT );
1957 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1958 ptr = GlobalLock( h );
1959 ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr );
1960 GlobalUnlock( h );
1961 h = GetClipboardData( format_id );
1962 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1963 ptr = GlobalLock( h );
1964 if (ptr) ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr );
1965 GlobalUnlock( h );
1966 h = GetClipboardData( CF_GDIOBJFIRST + 3 );
1967 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1968 ptr = GlobalLock( h );
1969 ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr );
1970 GlobalUnlock( h );
1971 trace( "gdiobj %p\n", h );
1972 h = GetClipboardData( CF_PRIVATEFIRST + 7 );
1973 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1974 ptr = GlobalLock( h );
1975 ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr );
1976 GlobalUnlock( h );
1977 trace( "private %p\n", h );
1978 h = GetClipboardData( CF_BITMAP );
1979 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1980 ok( GetObjectW( h, sizeof(bm), &bm ) == sizeof(bm), "GetObject %p failed\n", h );
1981 ok( bm.bmWidth == 13 && bm.bmHeight == 17, "wrong bitmap %ux%u\n", bm.bmWidth, bm.bmHeight );
1982 trace( "bitmap %p\n", h );
1983 h = GetClipboardData( CF_DSPBITMAP );
1984 ok( !GetObjectType( h ), "expected invalid object %p\n", h );
1985 trace( "bitmap2 %p\n", h );
1986 h = GetClipboardData( CF_PALETTE );
1987 ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
1988 ok( GetPaletteEntries( h, 0, 1, &entry ) == 1, "GetPaletteEntries %p failed\n", h );
1989 ok( entry.peRed == 0x12 && entry.peGreen == 0x34 && entry.peBlue == 0x56,
1990 "wrong color %02x,%02x,%02x\n", entry.peRed, entry.peGreen, entry.peBlue );
1991 trace( "palette %p\n", h );
1992 h = GetClipboardData( CF_METAFILEPICT );
1993 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1994 ok( GetObjectType( ((METAFILEPICT *)h)->hMF ) == OBJ_METAFILE,
1995 "wrong object %p\n", ((METAFILEPICT *)h)->hMF );
1996 trace( "metafile %p\n", h );
1997 h = GetClipboardData( CF_DSPMETAFILEPICT );
1998 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1999 ok( GetObjectType( ((METAFILEPICT *)h)->hMF ) == OBJ_METAFILE,
2000 "wrong object %p\n", ((METAFILEPICT *)h)->hMF );
2001 trace( "metafile2 %p\n", h );
2002 h = GetClipboardData( CF_ENHMETAFILE );
2003 ok( GetObjectType( h ) == OBJ_ENHMETAFILE, "expected enhmetafile %p\n", h );
2004 ok( GetEnhMetaFileBits( h, sizeof(buffer), buffer ) > sizeof(ENHMETAHEADER),
2005 "GetEnhMetaFileBits failed on %p\n", h );
2006 ok( ((ENHMETAHEADER *)buffer)->nRecords == 3,
2007 "wrong records %u\n", ((ENHMETAHEADER *)buffer)->nRecords );
2008 trace( "enhmetafile %p\n", h );
2009 h = GetClipboardData( CF_DSPENHMETAFILE );
2010 ok( GetObjectType( h ) == OBJ_ENHMETAFILE, "expected enhmetafile %p\n", h );
2011 ok( GetEnhMetaFileBits( h, sizeof(buffer), buffer ) > sizeof(ENHMETAHEADER),
2012 "GetEnhMetaFileBits failed on %p\n", h );
2013 ok( ((ENHMETAHEADER *)buffer)->nRecords == 3,
2014 "wrong records %u\n", ((ENHMETAHEADER *)buffer)->nRecords );
2015 trace( "enhmetafile2 %p\n", h );
2016 h = GetClipboardData( CF_DIB );
2017 ok( is_fixed( h ), "expected fixed mem %p\n", h );
2018 h = GetClipboardData( CF_DIBV5 );
2019 ok( is_fixed( h ), "expected fixed mem %p\n", h );
2020 r = CloseClipboard();
2021 ok( r, "gle %d\n", GetLastError() );
2024 static void test_handles_process_open( const char *str )
2026 HANDLE h, text = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE, strlen(str) + 1 );
2027 char *ptr = GlobalLock( text );
2029 strcpy( ptr, str );
2030 GlobalUnlock( text );
2032 /* clipboard already open by parent process */
2033 h = SetClipboardData( CF_TEXT, text );
2034 ok( h == text, "wrong mem %p / %p\n", h, text );
2035 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2038 static void test_handles_process_dib( const char *str )
2040 BOOL r;
2041 HANDLE h;
2043 r = OpenClipboard( 0 );
2044 ok( r, "gle %d\n", GetLastError() );
2045 h = GetClipboardData( CF_BITMAP );
2046 ok( !GetObjectType( h ), "expected invalid object %p\n", h );
2047 trace( "dibsection %p\n", h );
2048 r = CloseClipboard();
2049 ok( r, "gle %d\n", GetLastError() );
2052 static void test_data_handles(void)
2054 BOOL r;
2055 char *ptr;
2056 HANDLE h, text;
2057 HWND hwnd = CreateWindowA( "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL );
2058 BITMAPINFO bmi;
2059 void *bits;
2061 ok( hwnd != 0, "window creation failed\n" );
2062 format_id = RegisterClipboardFormatA( "my_cool_clipboard_format" );
2063 test_handles( 0 );
2064 test_handles( GetDesktopWindow() );
2065 test_handles( hwnd );
2066 run_thread( test_handles_thread, hwnd, __LINE__ );
2068 bitmap = CreateBitmap( 13, 17, 1, 1, NULL );
2069 bitmap2 = CreateBitmap( 10, 10, 1, 1, NULL );
2070 palette = CreatePalette( &logpalette );
2072 r = OpenClipboard( hwnd );
2073 ok( r, "gle %d\n", GetLastError() );
2074 r = EmptyClipboard();
2075 ok( r, "gle %d\n", GetLastError() );
2076 h = SetClipboardData( CF_TEXT, create_textA() );
2077 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2078 h = SetClipboardData( format_id, create_textA() );
2079 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2080 h = SetClipboardData( CF_BITMAP, bitmap );
2081 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
2082 h = SetClipboardData( CF_DSPBITMAP, bitmap2 );
2083 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
2084 h = SetClipboardData( CF_PALETTE, palette );
2085 ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
2086 h = SetClipboardData( CF_METAFILEPICT, create_metafile() );
2087 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2088 trace( "metafile %p\n", h );
2089 h = SetClipboardData( CF_DSPMETAFILEPICT, create_metafile() );
2090 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2091 trace( "metafile2 %p\n", h );
2092 h = SetClipboardData( CF_ENHMETAFILE, create_emf() );
2093 ok( GetObjectType( h ) == OBJ_ENHMETAFILE, "expected enhmetafile %p\n", h );
2094 trace( "enhmetafile %p\n", h );
2095 h = SetClipboardData( CF_DSPENHMETAFILE, create_emf() );
2096 ok( GetObjectType( h ) == OBJ_ENHMETAFILE, "expected enhmetafile %p\n", h );
2097 trace( "enhmetafile2 %p\n", h );
2098 h = SetClipboardData( CF_GDIOBJFIRST + 3, create_textA() );
2099 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2100 h = SetClipboardData( CF_PRIVATEFIRST + 7, create_textA() );
2101 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2102 r = CloseClipboard();
2103 ok( r, "gle %d\n", GetLastError() );
2105 run_thread( test_handles_thread2, 0, __LINE__ );
2106 run_process( "handles test" );
2108 r = OpenClipboard( hwnd );
2109 ok( r, "gle %d\n", GetLastError() );
2110 h = GetClipboardData( CF_TEXT );
2111 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2112 h = GetClipboardData( format_id );
2113 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2114 h = GetClipboardData( CF_GDIOBJFIRST + 3 );
2115 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2116 h = GetClipboardData( CF_PRIVATEFIRST + 7 );
2117 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2119 r = EmptyClipboard();
2120 ok( r, "gle %d\n", GetLastError() );
2121 text = create_textA();
2122 h = SetClipboardData( CF_TEXT, text );
2123 ok( is_moveable( h ), "expected moveable mem %p\n", h );
2125 run_process( "handles_open foobar" );
2127 ok( is_moveable( text ), "expected moveable mem %p\n", text );
2128 h = GetClipboardData( CF_TEXT );
2129 ok( is_fixed( h ), "expected fixed mem %p\n", h );
2130 ok( is_moveable( text ), "expected moveable mem %p\n", text );
2131 ptr = GlobalLock( h );
2132 ok( !strcmp( ptr, "foobar" ), "wrong data '%.8s'\n", ptr );
2133 GlobalUnlock( h );
2135 r = EmptyClipboard();
2136 ok( r, "gle %d\n", GetLastError() );
2137 ok( is_fixed( h ), "expected free mem %p\n", h );
2138 ok( is_freed( text ) || broken( is_moveable(text) ), /* w2003, w2008 */
2139 "expected free mem %p\n", text );
2140 r = CloseClipboard();
2141 ok( r, "gle %d\n", GetLastError() );
2143 /* test CF_BITMAP with a DIB section */
2144 memset( &bmi, 0, sizeof(bmi) );
2145 bmi.bmiHeader.biSize = sizeof( bmi.bmiHeader );
2146 bmi.bmiHeader.biWidth = 29;
2147 bmi.bmiHeader.biHeight = 13;
2148 bmi.bmiHeader.biPlanes = 1;
2149 bmi.bmiHeader.biBitCount = 32;
2150 bitmap = CreateDIBSection( 0, &bmi, DIB_RGB_COLORS, &bits, 0, 0 );
2152 r = OpenClipboard( hwnd );
2153 ok( r, "gle %d\n", GetLastError() );
2154 r = EmptyClipboard();
2155 ok( r, "gle %d\n", GetLastError() );
2156 h = SetClipboardData( CF_BITMAP, bitmap );
2157 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
2158 trace( "dibsection %p\n", h );
2159 r = CloseClipboard();
2160 ok( r, "gle %d\n", GetLastError() );
2162 run_process( "handles_dib dummy" );
2164 r = OpenClipboard( hwnd );
2165 ok( r, "gle %d\n", GetLastError() );
2166 ok( GetObjectType( bitmap ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap );
2167 r = EmptyClipboard();
2168 ok( r, "gle %d\n", GetLastError() );
2169 ok( !GetObjectType( bitmap ), "expected deleted %p\n", bitmap );
2170 r = CloseClipboard();
2171 ok( r, "gle %d\n", GetLastError() );
2173 DestroyWindow( hwnd );
2176 static void test_GetUpdatedClipboardFormats(void)
2178 BOOL r;
2179 UINT count, formats[256];
2181 if (!pGetUpdatedClipboardFormats)
2183 win_skip( "GetUpdatedClipboardFormats not supported\n" );
2184 return;
2187 count = 0xdeadbeef;
2188 r = pGetUpdatedClipboardFormats( NULL, 0, &count );
2189 ok( r, "gle %d\n", GetLastError() );
2190 ok( !count, "wrong count %u\n", count );
2192 count = 0xdeadbeef;
2193 r = pGetUpdatedClipboardFormats( NULL, 256, &count );
2194 ok( r, "gle %d\n", GetLastError() );
2195 ok( !count, "wrong count %u\n", count );
2197 SetLastError( 0xdeadbeef );
2198 r = pGetUpdatedClipboardFormats( formats, 256, NULL );
2199 ok( !r, "succeeded\n" );
2200 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
2202 count = 0xdeadbeef;
2203 r = pGetUpdatedClipboardFormats( formats, 256, &count );
2204 ok( r, "gle %d\n", GetLastError() );
2205 ok( !count, "wrong count %u\n", count );
2207 r = OpenClipboard( 0 );
2208 ok( r, "gle %d\n", GetLastError() );
2209 r = EmptyClipboard();
2210 ok( r, "gle %d\n", GetLastError() );
2212 count = 0xdeadbeef;
2213 r = pGetUpdatedClipboardFormats( formats, 256, &count );
2214 ok( r, "gle %d\n", GetLastError() );
2215 ok( !count, "wrong count %u\n", count );
2217 SetClipboardData( CF_UNICODETEXT, 0 );
2219 count = 0xdeadbeef;
2220 memset( formats, 0xcc, sizeof(formats) );
2221 r = pGetUpdatedClipboardFormats( formats, 256, &count );
2222 ok( r, "gle %d\n", GetLastError() );
2223 ok( count == 1, "wrong count %u\n", count );
2224 ok( formats[0] == CF_UNICODETEXT, "wrong format %u\n", formats[0] );
2225 ok( formats[1] == 0xcccccccc, "wrong format %u\n", formats[1] );
2227 SetClipboardData( CF_TEXT, 0 );
2228 count = 0xdeadbeef;
2229 memset( formats, 0xcc, sizeof(formats) );
2230 r = pGetUpdatedClipboardFormats( formats, 256, &count );
2231 ok( r, "gle %d\n", GetLastError() );
2232 ok( count == 2, "wrong count %u\n", count );
2233 ok( formats[0] == CF_UNICODETEXT, "wrong format %u\n", formats[0] );
2234 ok( formats[1] == CF_TEXT, "wrong format %u\n", formats[1] );
2235 ok( formats[2] == 0xcccccccc, "wrong format %u\n", formats[2] );
2237 SetLastError( 0xdeadbeef );
2238 count = 0xdeadbeef;
2239 r = pGetUpdatedClipboardFormats( formats, 0, &count );
2240 ok( !r, "succeeded\n" );
2241 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %u\n", GetLastError() );
2242 ok( count == 2, "wrong count %u\n", count );
2244 SetLastError( 0xdeadbeef );
2245 count = 0xdeadbeef;
2246 r = pGetUpdatedClipboardFormats( formats, 1, &count );
2247 ok( !r, "succeeded\n" );
2248 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %u\n", GetLastError() );
2249 ok( count == 2, "wrong count %u\n", count );
2251 r = CloseClipboard();
2252 ok( r, "gle %d\n", GetLastError() );
2254 count = 0xdeadbeef;
2255 memset( formats, 0xcc, sizeof(formats) );
2256 r = pGetUpdatedClipboardFormats( formats, 256, &count );
2257 ok( r, "gle %d\n", GetLastError() );
2258 ok( count == 4, "wrong count %u\n", count );
2259 ok( formats[0] == CF_UNICODETEXT, "wrong format %u\n", formats[0] );
2260 ok( formats[1] == CF_TEXT, "wrong format %u\n", formats[1] );
2261 ok( formats[2] == CF_LOCALE, "wrong format %u\n", formats[2] );
2262 ok( formats[3] == CF_OEMTEXT, "wrong format %u\n", formats[3] );
2263 ok( formats[4] == 0xcccccccc, "wrong format %u\n", formats[4] );
2265 count = 0xdeadbeef;
2266 memset( formats, 0xcc, sizeof(formats) );
2267 r = pGetUpdatedClipboardFormats( formats, 2, &count );
2268 ok( !r, "gle %d\n", GetLastError() );
2269 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %u\n", GetLastError() );
2270 ok( count == 4, "wrong count %u\n", count );
2271 ok( formats[0] == 0xcccccccc, "wrong format %u\n", formats[0] );
2273 count = 0xdeadbeef;
2274 r = pGetUpdatedClipboardFormats( NULL, 256, &count );
2275 ok( !r, "gle %d\n", GetLastError() );
2276 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
2277 ok( count == 4, "wrong count %u\n", count );
2279 count = 0xdeadbeef;
2280 r = pGetUpdatedClipboardFormats( NULL, 256, &count );
2281 ok( !r, "gle %d\n", GetLastError() );
2282 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
2283 ok( count == 4, "wrong count %u\n", count );
2286 static const struct
2288 char strA[12];
2289 WCHAR strW[12];
2290 UINT len;
2291 } test_data[] =
2293 { "foo", {}, 3 }, /* 0 */
2294 { "foo", {}, 4 },
2295 { "foo\0bar", {}, 7 },
2296 { "foo\0bar", {}, 8 },
2297 { "", {'f','o','o'}, 3 * sizeof(WCHAR) },
2298 { "", {'f','o','o',0}, 4 * sizeof(WCHAR) }, /* 5 */
2299 { "", {'f','o','o',0,'b','a','r'}, 7 * sizeof(WCHAR) },
2300 { "", {'f','o','o',0,'b','a','r',0}, 8 * sizeof(WCHAR) },
2301 { "", {'f','o','o'}, 1 },
2302 { "", {'f','o','o'}, 2 },
2303 { "", {'f','o','o'}, 5 }, /* 10 */
2304 { "", {'f','o','o',0}, 7 },
2305 { "", {'f','o','o',0}, 9 },
2308 static void test_string_data(void)
2310 UINT i;
2311 BOOL r;
2312 HANDLE data;
2313 char cmd[16];
2314 char bufferA[12];
2315 WCHAR bufferW[12];
2317 for (i = 0; i < sizeof(test_data) / sizeof(test_data[0]); i++)
2319 /* 1-byte Unicode strings crash on Win64 */
2320 #ifdef _WIN64
2321 if (!test_data[i].strA[0] && test_data[i].len < sizeof(WCHAR)) continue;
2322 #endif
2323 r = OpenClipboard( 0 );
2324 ok( r, "gle %d\n", GetLastError() );
2325 r = EmptyClipboard();
2326 ok( r, "gle %d\n", GetLastError() );
2327 data = GlobalAlloc( GMEM_FIXED, test_data[i].len );
2328 if (test_data[i].strA[0])
2330 memcpy( data, test_data[i].strA, test_data[i].len );
2331 SetClipboardData( CF_TEXT, data );
2332 memcpy( bufferA, test_data[i].strA, test_data[i].len );
2333 bufferA[test_data[i].len - 1] = 0;
2334 ok( !memcmp( data, bufferA, test_data[i].len ),
2335 "%u: wrong data %.*s\n", i, test_data[i].len, (char *)data );
2337 else
2339 memcpy( data, test_data[i].strW, test_data[i].len );
2340 SetClipboardData( CF_UNICODETEXT, data );
2341 memcpy( bufferW, test_data[i].strW, test_data[i].len );
2342 bufferW[(test_data[i].len + 1) / sizeof(WCHAR) - 1] = 0;
2343 ok( !memcmp( data, bufferW, test_data[i].len ),
2344 "%u: wrong data %s\n", i, wine_dbgstr_wn( data, (test_data[i].len + 1) / sizeof(WCHAR) ));
2346 r = CloseClipboard();
2347 ok( r, "gle %d\n", GetLastError() );
2348 sprintf( cmd, "string_data %u", i );
2349 run_process( cmd );
2353 static void test_string_data_process( int i )
2355 BOOL r;
2356 HANDLE data;
2357 UINT len, len2;
2358 char bufferA[12];
2359 WCHAR bufferW[12];
2361 r = OpenClipboard( 0 );
2362 ok( r, "gle %d\n", GetLastError() );
2363 if (test_data[i].strA[0])
2365 data = GetClipboardData( CF_TEXT );
2366 ok( data != 0, "%u: could not get data\n", i );
2367 len = GlobalSize( data );
2368 ok( len == test_data[i].len, "%u: wrong size %u / %u\n", i, len, test_data[i].len );
2369 memcpy( bufferA, test_data[i].strA, test_data[i].len );
2370 bufferA[test_data[i].len - 1] = 0;
2371 ok( !memcmp( data, bufferA, len ), "%u: wrong data %.*s\n", i, len, (char *)data );
2372 data = GetClipboardData( CF_UNICODETEXT );
2373 ok( data != 0, "%u: could not get data\n", i );
2374 len = GlobalSize( data );
2375 len2 = MultiByteToWideChar( CP_ACP, 0, bufferA, test_data[i].len, bufferW, 12 );
2376 ok( len == len2 * sizeof(WCHAR), "%u: wrong size %u / %u\n", i, len, len2 );
2377 ok( !memcmp( data, bufferW, len ), "%u: wrong data %s\n", i, wine_dbgstr_wn( data, len2 ));
2379 else
2381 data = GetClipboardData( CF_UNICODETEXT );
2382 ok( data != 0, "%u: could not get data\n", i );
2383 len = GlobalSize( data );
2384 ok( len == test_data[i].len, "%u: wrong size %u / %u\n", i, len, test_data[i].len );
2385 memcpy( bufferW, test_data[i].strW, test_data[i].len );
2386 bufferW[(test_data[i].len + 1) / sizeof(WCHAR) - 1] = 0;
2387 ok( !memcmp( data, bufferW, len ),
2388 "%u: wrong data %s\n", i, wine_dbgstr_wn( data, (len + 1) / sizeof(WCHAR) ));
2389 data = GetClipboardData( CF_TEXT );
2390 if (test_data[i].len >= sizeof(WCHAR))
2392 ok( data != 0, "%u: could not get data\n", i );
2393 len = GlobalSize( data );
2394 len2 = WideCharToMultiByte( CP_ACP, 0, bufferW, test_data[i].len / sizeof(WCHAR),
2395 bufferA, 12, NULL, NULL );
2396 bufferA[len2 - 1] = 0;
2397 ok( len == len2, "%u: wrong size %u / %u\n", i, len, len2 );
2398 ok( !memcmp( data, bufferA, len ), "%u: wrong data %.*s\n", i, len, (char *)data );
2400 else
2402 ok( !data, "%u: got data for empty string\n", i );
2403 ok( IsClipboardFormatAvailable( CF_TEXT ), "%u: text not available\n", i );
2406 r = CloseClipboard();
2407 ok( r, "gle %d\n", GetLastError() );
2410 START_TEST(clipboard)
2412 char **argv;
2413 int argc = winetest_get_mainargs( &argv );
2414 HMODULE mod = GetModuleHandleA( "user32" );
2416 argv0 = argv[0];
2417 pAddClipboardFormatListener = (void *)GetProcAddress( mod, "AddClipboardFormatListener" );
2418 pRemoveClipboardFormatListener = (void *)GetProcAddress( mod, "RemoveClipboardFormatListener" );
2419 pGetClipboardSequenceNumber = (void *)GetProcAddress( mod, "GetClipboardSequenceNumber" );
2420 pGetUpdatedClipboardFormats = (void *)GetProcAddress( mod, "GetUpdatedClipboardFormats" );
2422 if (argc == 4 && !strcmp( argv[2], "set_clipboard_data" ))
2424 set_clipboard_data_process( atoi( argv[3] ));
2425 return;
2427 if (argc == 4 && !strcmp( argv[2], "grab_clipboard" ))
2429 grab_clipboard_process( atoi( argv[3] ));
2430 return;
2432 if (argc == 4 && !strcmp( argv[2], "handles" ))
2434 test_handles_process( argv[3] );
2435 return;
2437 if (argc == 4 && !strcmp( argv[2], "handles_open" ))
2439 test_handles_process_open( argv[3] );
2440 return;
2442 if (argc == 4 && !strcmp( argv[2], "handles_dib" ))
2444 test_handles_process_dib( argv[3] );
2445 return;
2447 if (argc == 4 && !strcmp( argv[2], "string_data" ))
2449 test_string_data_process( atoi( argv[3] ));
2450 return;
2453 test_RegisterClipboardFormatA();
2454 test_ClipboardOwner();
2455 test_synthesized();
2456 test_messages();
2457 test_data_handles();
2458 test_GetUpdatedClipboardFormats();
2459 test_string_data();