server: Add some validation of clipboard window handles.
[wine.git] / dlls / user32 / tests / clipboard.c
blobb9b926d181ad9dd2ca563b1ceaacc95abfc399b8
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"
28 static BOOL (WINAPI *pAddClipboardFormatListener)(HWND hwnd);
29 static BOOL (WINAPI *pRemoveClipboardFormatListener)(HWND hwnd);
30 static DWORD (WINAPI *pGetClipboardSequenceNumber)(void);
32 static const BOOL is_win64 = sizeof(void *) > sizeof(int);
33 static int thread_from_line;
34 static char *argv0;
36 static DWORD WINAPI open_clipboard_thread(LPVOID arg)
38 HWND hWnd = arg;
39 ok(OpenClipboard(hWnd), "%u: OpenClipboard failed\n", thread_from_line);
40 return 0;
43 static DWORD WINAPI empty_clipboard_thread(LPVOID arg)
45 SetLastError( 0xdeadbeef );
46 ok(!EmptyClipboard(), "%u: EmptyClipboard succeeded\n", thread_from_line );
47 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
48 thread_from_line, GetLastError());
49 return 0;
52 static DWORD WINAPI open_and_empty_clipboard_thread(LPVOID arg)
54 HWND hWnd = arg;
55 ok(OpenClipboard(hWnd), "%u: OpenClipboard failed\n", thread_from_line);
56 ok(EmptyClipboard(), "%u: EmptyClipboard failed\n", thread_from_line );
57 return 0;
60 static DWORD WINAPI set_clipboard_data_thread(LPVOID arg)
62 HWND hwnd = arg;
63 HANDLE ret;
65 SetLastError( 0xdeadbeef );
66 if (GetClipboardOwner() == hwnd)
68 SetClipboardData( CF_WAVE, 0 );
69 ok( IsClipboardFormatAvailable( CF_WAVE ), "%u: SetClipboardData failed\n", thread_from_line );
70 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
71 ok( ret != 0, "%u: SetClipboardData failed err %u\n", thread_from_line, GetLastError() );
72 SetLastError( 0xdeadbeef );
73 ret = GetClipboardData( CF_WAVE );
74 ok( !ret, "%u: GetClipboardData succeeded\n", thread_from_line );
75 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
76 thread_from_line, GetLastError());
78 else
80 SetClipboardData( CF_WAVE, 0 );
81 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
82 thread_from_line, GetLastError());
83 ok( !IsClipboardFormatAvailable( CF_WAVE ), "%u: SetClipboardData succeeded\n", thread_from_line );
84 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
85 ok( !ret, "%u: SetClipboardData succeeded\n", thread_from_line );
86 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
87 thread_from_line, GetLastError());
89 return 0;
92 static void set_clipboard_data_process( int arg )
94 HANDLE ret;
96 SetLastError( 0xdeadbeef );
97 if (arg)
99 todo_wine_if( arg == 1 || arg == 3 )
100 ok( IsClipboardFormatAvailable( CF_WAVE ), "process %u: CF_WAVE not available\n", arg );
101 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
102 ok( ret != 0, "process %u: SetClipboardData failed err %u\n", arg, GetLastError() );
104 else
106 SetClipboardData( CF_WAVE, 0 );
107 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "process %u: wrong error %u\n",
108 arg, GetLastError());
109 ok( !IsClipboardFormatAvailable( CF_WAVE ), "process %u: SetClipboardData succeeded\n", arg );
110 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
111 ok( !ret, "process %u: SetClipboardData succeeded\n", arg );
112 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "process %u: wrong error %u\n",
113 arg, GetLastError());
117 static void grab_clipboard_process( int arg )
119 BOOL ret;
121 SetLastError( 0xdeadbeef );
122 ret = OpenClipboard( 0 );
123 ok( ret, "OpenClipboard failed\n" );
124 ret = EmptyClipboard();
125 ok( ret, "EmptyClipboard failed\n" );
126 if (arg)
128 HANDLE ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
129 ok( ret != 0, "process %u: SetClipboardData failed err %u\n", arg, GetLastError() );
133 static void run_thread( LPTHREAD_START_ROUTINE func, void *arg, int line )
135 DWORD ret;
136 HANDLE thread;
138 thread_from_line = line;
139 thread = CreateThread(NULL, 0, func, arg, 0, NULL);
140 ok(thread != NULL, "%u: CreateThread failed with error %d\n", line, GetLastError());
141 for (;;)
143 ret = MsgWaitForMultipleObjectsEx( 1, &thread, 1000, QS_ALLINPUT, 0 );
144 if (ret == WAIT_OBJECT_0 + 1)
146 MSG msg;
147 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
149 else break;
151 ok(ret == WAIT_OBJECT_0, "%u: expected WAIT_OBJECT_0, got %u\n", line, ret);
152 CloseHandle(thread);
155 static void run_process( const char *args )
157 char cmd[MAX_PATH];
158 PROCESS_INFORMATION info;
159 STARTUPINFOA startup;
161 sprintf( cmd, "%s clipboard %s", argv0, args );
162 memset( &startup, 0, sizeof(startup) );
163 startup.cb = sizeof(startup);
164 ok( CreateProcessA( NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info ),
165 "CreateProcess %s failed\n", cmd );
167 winetest_wait_child_process( info.hProcess );
168 CloseHandle( info.hProcess );
169 CloseHandle( info.hThread );
172 static WNDPROC old_proc;
173 static LRESULT CALLBACK winproc_wrapper( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
175 static int destroyed;
177 if (msg == WM_DESTROY) destroyed = TRUE;
179 trace( "%p msg %04x\n", hwnd, msg );
180 if (!destroyed)
181 ok( GetClipboardOwner() == hwnd, "%04x: wrong owner %p/%p\n", msg, GetClipboardOwner(), hwnd );
182 else todo_wine_if (msg == WM_DESTROY)
183 ok( !GetClipboardOwner(), "%04x: wrong owner %p\n", msg, GetClipboardOwner() );
184 ok( GetClipboardViewer() == hwnd, "%04x: wrong viewer %p/%p\n", msg, GetClipboardViewer(), hwnd );
185 ok( GetOpenClipboardWindow() == hwnd, "%04x: wrong open win %p/%p\n",
186 msg, GetOpenClipboardWindow(), hwnd );
187 return old_proc( hwnd, msg, wp, lp );
190 static void test_ClipboardOwner(void)
192 HWND hWnd1, hWnd2;
193 BOOL ret;
195 SetLastError(0xdeadbeef);
196 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef,
197 "could not perform clipboard test: clipboard already owned\n");
199 hWnd1 = CreateWindowExA(0, "static", NULL, WS_POPUP,
200 0, 0, 10, 10, 0, 0, 0, NULL);
201 ok(hWnd1 != 0, "CreateWindowExA error %d\n", GetLastError());
202 trace("hWnd1 = %p\n", hWnd1);
204 hWnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP,
205 0, 0, 10, 10, 0, 0, 0, NULL);
206 ok(hWnd2 != 0, "CreateWindowExA error %d\n", GetLastError());
207 trace("hWnd2 = %p\n", hWnd2);
209 SetLastError(0xdeadbeef);
210 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
211 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */
212 "wrong error %u\n", GetLastError());
214 ok(OpenClipboard(0), "OpenClipboard failed\n");
215 ok(!GetClipboardOwner(), "clipboard should still be not owned\n");
216 ok(!OpenClipboard(hWnd1), "OpenClipboard should fail since clipboard already opened\n");
217 ok(OpenClipboard(0), "OpenClipboard again failed\n");
218 ret = CloseClipboard();
219 ok( ret, "CloseClipboard error %d\n", GetLastError());
221 ok(OpenClipboard(hWnd1), "OpenClipboard failed\n");
222 run_thread( open_clipboard_thread, hWnd1, __LINE__ );
223 run_thread( empty_clipboard_thread, 0, __LINE__ );
224 run_thread( set_clipboard_data_thread, hWnd1, __LINE__ );
225 ok( !IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE available\n" );
226 ok( !GetClipboardData( CF_WAVE ), "CF_WAVE data available\n" );
227 run_process( "set_clipboard_data 0" );
228 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
229 ok(OpenClipboard(hWnd1), "OpenClipboard failed\n");
231 SetLastError(0xdeadbeef);
232 ret = OpenClipboard(hWnd2);
233 ok(!ret && (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED),
234 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
236 SetLastError(0xdeadbeef);
237 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should still be not owned\n");
238 ret = EmptyClipboard();
239 ok( ret, "EmptyClipboard error %d\n", GetLastError());
240 ok(GetClipboardOwner() == hWnd1, "clipboard should be owned by %p, not by %p\n", hWnd1, GetClipboardOwner());
241 run_thread( empty_clipboard_thread, 0, __LINE__ );
242 run_thread( set_clipboard_data_thread, hWnd1, __LINE__ );
243 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
244 ok( GetClipboardData( CF_WAVE ) != 0, "CF_WAVE data not available\n" );
245 run_process( "set_clipboard_data 1" );
247 SetLastError(0xdeadbeef);
248 ret = OpenClipboard(hWnd2);
249 ok(!ret && (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED),
250 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
252 ret = CloseClipboard();
253 ok( ret, "CloseClipboard error %d\n", GetLastError());
254 ok(GetClipboardOwner() == hWnd1, "clipboard should still be owned\n");
256 /* any window will do, even from a different process */
257 ret = OpenClipboard( GetDesktopWindow() );
258 ok( ret, "OpenClipboard error %d\n", GetLastError());
259 ret = EmptyClipboard();
260 ok( ret, "EmptyClipboard error %d\n", GetLastError());
261 ok( GetClipboardOwner() == GetDesktopWindow(), "wrong owner %p/%p\n",
262 GetClipboardOwner(), GetDesktopWindow() );
263 run_thread( set_clipboard_data_thread, GetDesktopWindow(), __LINE__ );
264 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
265 ok( GetClipboardData( CF_WAVE ) != 0, "CF_WAVE data not available\n" );
266 run_process( "set_clipboard_data 2" );
267 ret = CloseClipboard();
268 ok( ret, "CloseClipboard error %d\n", GetLastError());
270 ret = OpenClipboard( hWnd1 );
271 ok( ret, "OpenClipboard error %d\n", GetLastError());
272 ret = EmptyClipboard();
273 ok( ret, "EmptyClipboard error %d\n", GetLastError());
274 SetClipboardViewer( hWnd1 );
275 ok( GetClipboardOwner() == hWnd1, "wrong owner %p/%p\n", GetClipboardOwner(), hWnd1 );
276 ok( GetClipboardViewer() == hWnd1, "wrong viewer %p/%p\n", GetClipboardViewer(), hWnd1 );
277 ok( GetOpenClipboardWindow() == hWnd1, "wrong open win %p/%p\n", GetOpenClipboardWindow(), hWnd1 );
279 old_proc = (WNDPROC)SetWindowLongPtrA( hWnd1, GWLP_WNDPROC, (LONG_PTR)winproc_wrapper );
280 ret = DestroyWindow(hWnd1);
281 ok( ret, "DestroyWindow error %d\n", GetLastError());
282 ret = DestroyWindow(hWnd2);
283 ok( ret, "DestroyWindow error %d\n", GetLastError());
284 SetLastError(0xdeadbeef);
285 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should not be owned\n");
286 ok(!GetClipboardViewer() && GetLastError() == 0xdeadbeef, "viewer still exists\n");
287 ok(!GetOpenClipboardWindow() && GetLastError() == 0xdeadbeef, "clipboard should not be open\n");
289 SetLastError( 0xdeadbeef );
290 ret = CloseClipboard();
291 ok( !ret, "CloseClipboard succeeded\n" );
292 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError() );
294 ret = OpenClipboard( 0 );
295 ok( ret, "OpenClipboard error %d\n", GetLastError());
296 run_thread( set_clipboard_data_thread, 0, __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 3" );
300 ret = CloseClipboard();
301 ok( ret, "CloseClipboard error %d\n", GetLastError());
303 run_thread( open_and_empty_clipboard_thread, 0, __LINE__ );
305 ret = OpenClipboard( 0 );
306 ok( ret, "OpenClipboard error %d\n", GetLastError());
307 run_thread( set_clipboard_data_thread, 0, __LINE__ );
308 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
309 ok( GetClipboardData( CF_WAVE ) != 0, "CF_WAVE data not available\n" );
310 run_process( "set_clipboard_data 4" );
311 ret = EmptyClipboard();
312 ok( ret, "EmptyClipboard error %d\n", GetLastError());
313 ret = CloseClipboard();
314 ok( ret, "CloseClipboard error %d\n", GetLastError());
316 SetLastError( 0xdeadbeef );
317 ok( !SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 )),
318 "SetClipboardData succeeded\n" );
319 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError() );
320 ok( !IsClipboardFormatAvailable( CF_WAVE ), "SetClipboardData succeeded\n" );
324 static void test_RegisterClipboardFormatA(void)
326 ATOM atom_id;
327 UINT format_id, format_id2;
328 char buf[256];
329 int len;
330 BOOL ret;
331 HANDLE handle;
333 format_id = RegisterClipboardFormatA("my_cool_clipboard_format");
334 ok(format_id > 0xc000 && format_id < 0xffff, "invalid clipboard format id %04x\n", format_id);
336 format_id2 = RegisterClipboardFormatA("MY_COOL_CLIPBOARD_FORMAT");
337 ok(format_id2 == format_id, "invalid clipboard format id %04x\n", format_id2);
339 len = GetClipboardFormatNameA(format_id, buf, 256);
340 ok(len == lstrlenA("my_cool_clipboard_format"), "wrong format name length %d\n", len);
341 ok(!lstrcmpA(buf, "my_cool_clipboard_format"), "wrong format name \"%s\"\n", buf);
343 lstrcpyA(buf, "foo");
344 SetLastError(0xdeadbeef);
345 len = GetAtomNameA((ATOM)format_id, buf, 256);
346 ok(len == 0, "GetAtomNameA should fail\n");
347 ok(GetLastError() == ERROR_INVALID_HANDLE, "err %d\n", GetLastError());
349 todo_wine
351 lstrcpyA(buf, "foo");
352 SetLastError(0xdeadbeef);
353 len = GlobalGetAtomNameA((ATOM)format_id, buf, 256);
354 ok(len == 0, "GlobalGetAtomNameA should fail\n");
355 ok(GetLastError() == ERROR_INVALID_HANDLE, "err %d\n", GetLastError());
358 SetLastError(0xdeadbeef);
359 atom_id = FindAtomA("my_cool_clipboard_format");
360 ok(atom_id == 0, "FindAtomA should fail\n");
361 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError());
363 if (0)
365 /* this relies on the clipboard and global atom table being different */
366 SetLastError(0xdeadbeef);
367 atom_id = GlobalFindAtomA("my_cool_clipboard_format");
368 ok(atom_id == 0, "GlobalFindAtomA should fail\n");
369 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError());
372 for (format_id = 0; format_id < 0xffff; format_id++)
374 SetLastError(0xdeadbeef);
375 len = GetClipboardFormatNameA(format_id, buf, 256);
377 if (format_id < 0xc000)
378 ok(!len, "GetClipboardFormatNameA should fail, but it returned %d (%s)\n", len, buf);
379 else if (len && winetest_debug > 1)
380 trace("%04x: %s\n", format_id, len ? buf : "");
383 ret = OpenClipboard(0);
384 ok( ret, "OpenClipboard error %d\n", GetLastError());
386 /* try some invalid/unregistered formats */
387 SetLastError( 0xdeadbeef );
388 handle = SetClipboardData( 0, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
389 ok( !handle, "SetClipboardData succeeded\n" );
390 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError());
391 handle = SetClipboardData( 0x1234, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
392 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
393 handle = SetClipboardData( 0x123456, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
394 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
395 handle = SetClipboardData( 0xffff8765, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
396 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
398 ok( IsClipboardFormatAvailable( 0x1234 ), "format missing\n" );
399 ok( IsClipboardFormatAvailable( 0x123456 ), "format missing\n" );
400 ok( IsClipboardFormatAvailable( 0xffff8765 ), "format missing\n" );
401 ok( !IsClipboardFormatAvailable( 0 ), "format available\n" );
402 ok( !IsClipboardFormatAvailable( 0x3456 ), "format available\n" );
403 ok( !IsClipboardFormatAvailable( 0x8765 ), "format available\n" );
405 trace("# of formats available: %d\n", CountClipboardFormats());
407 format_id = 0;
408 while ((format_id = EnumClipboardFormats(format_id)))
410 ok(IsClipboardFormatAvailable(format_id), "format %04x was listed as available\n", format_id);
411 len = GetClipboardFormatNameA(format_id, buf, 256);
412 trace("%04x: %s\n", format_id, len ? buf : "");
415 ret = EmptyClipboard();
416 ok( ret, "EmptyClipboard error %d\n", GetLastError());
417 ret =CloseClipboard();
418 ok( ret, "CloseClipboard error %d\n", GetLastError());
420 if (CountClipboardFormats())
422 SetLastError(0xdeadbeef);
423 ok(!EnumClipboardFormats(0), "EnumClipboardFormats should fail if clipboard wasn't open\n");
424 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN,
425 "Last error should be set to ERROR_CLIPBOARD_NOT_OPEN, not %d\n", GetLastError());
428 SetLastError(0xdeadbeef);
429 ok(!EmptyClipboard(), "EmptyClipboard should fail if clipboard wasn't open\n");
430 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */
431 "Wrong error %u\n", GetLastError());
433 format_id = RegisterClipboardFormatA("#1234");
434 ok(format_id == 1234, "invalid clipboard format id %04x\n", format_id);
437 static HGLOBAL create_text(void)
439 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 5);
440 char *p = GlobalLock(h);
441 strcpy(p, "test");
442 GlobalUnlock(h);
443 return h;
446 static HENHMETAFILE create_emf(void)
448 const RECT rect = {0, 0, 100, 100};
449 HDC hdc = CreateEnhMetaFileA(NULL, NULL, &rect, "HENHMETAFILE Ole Clipboard Test\0Test\0\0");
450 ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
451 return CloseEnhMetaFile(hdc);
454 static void test_synthesized(void)
456 HGLOBAL h, htext;
457 HENHMETAFILE emf;
458 BOOL r;
459 UINT cf;
460 HANDLE data;
462 htext = create_text();
463 emf = create_emf();
465 r = OpenClipboard(NULL);
466 ok(r, "gle %d\n", GetLastError());
467 r = EmptyClipboard();
468 ok(r, "gle %d\n", GetLastError());
469 h = SetClipboardData(CF_TEXT, htext);
470 ok(h == htext, "got %p\n", h);
471 h = SetClipboardData(CF_ENHMETAFILE, emf);
472 ok(h == emf, "got %p\n", h);
473 r = CloseClipboard();
474 ok(r, "gle %d\n", GetLastError());
476 r = OpenClipboard(NULL);
477 ok(r, "gle %d\n", GetLastError());
478 cf = EnumClipboardFormats(0);
479 ok(cf == CF_TEXT, "cf %08x\n", cf);
480 data = GetClipboardData(cf);
481 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
483 cf = EnumClipboardFormats(cf);
484 ok(cf == CF_ENHMETAFILE, "cf %08x\n", cf);
485 data = GetClipboardData(cf);
486 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
488 cf = EnumClipboardFormats(cf);
489 todo_wine ok(cf == CF_LOCALE, "cf %08x\n", cf);
490 if(cf == CF_LOCALE)
491 cf = EnumClipboardFormats(cf);
492 ok(cf == CF_OEMTEXT, "cf %08x\n", cf);
493 data = GetClipboardData(cf);
494 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
496 cf = EnumClipboardFormats(cf);
497 ok(cf == CF_UNICODETEXT, "cf %08x\n", cf);
499 cf = EnumClipboardFormats(cf);
500 ok(cf == CF_METAFILEPICT, "cf %08x\n", cf);
501 data = GetClipboardData(cf);
502 todo_wine ok(data != NULL, "couldn't get data, cf %08x\n", cf);
504 cf = EnumClipboardFormats(cf);
505 ok(cf == 0, "cf %08x\n", cf);
507 r = EmptyClipboard();
508 ok(r, "gle %d\n", GetLastError());
510 r = CloseClipboard();
511 ok(r, "gle %d\n", GetLastError());
514 static CRITICAL_SECTION clipboard_cs;
515 static HWND next_wnd;
516 static LRESULT CALLBACK clipboard_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
518 static UINT wm_drawclipboard;
519 static UINT wm_clipboardupdate;
520 static UINT wm_destroyclipboard;
521 static UINT nb_formats;
522 LRESULT ret;
524 switch(msg) {
525 case WM_DRAWCLIPBOARD:
526 EnterCriticalSection(&clipboard_cs);
527 wm_drawclipboard++;
528 LeaveCriticalSection(&clipboard_cs);
529 break;
530 case WM_CHANGECBCHAIN:
531 if (next_wnd == (HWND)wp)
532 next_wnd = (HWND)lp;
533 else if (next_wnd)
534 SendMessageA(next_wnd, msg, wp, lp);
535 break;
536 case WM_DESTROYCLIPBOARD:
537 wm_destroyclipboard++;
538 ok( GetClipboardOwner() == hwnd, "WM_DESTROYCLIPBOARD owner %p\n", GetClipboardOwner() );
539 nb_formats = CountClipboardFormats();
540 break;
541 case WM_CLIPBOARDUPDATE:
542 wm_clipboardupdate++;
543 break;
544 case WM_USER:
545 ChangeClipboardChain(hwnd, next_wnd);
546 PostQuitMessage(0);
547 break;
548 case WM_USER+1:
549 ret = wm_drawclipboard;
550 wm_drawclipboard = 0;
551 return ret;
552 case WM_USER+2:
553 ret = wm_clipboardupdate;
554 wm_clipboardupdate = 0;
555 return ret;
556 case WM_USER+3:
557 ret = wm_destroyclipboard;
558 wm_destroyclipboard = 0;
559 return ret;
560 case WM_USER+4:
561 return nb_formats;
564 return DefWindowProcA(hwnd, msg, wp, lp);
567 static DWORD WINAPI clipboard_thread(void *param)
569 HWND ret, win = param;
570 BOOL r;
571 HANDLE handle;
572 UINT count, formats, old_seq = 0, seq;
574 if (pGetClipboardSequenceNumber) old_seq = pGetClipboardSequenceNumber();
576 EnterCriticalSection(&clipboard_cs);
577 SetLastError(0xdeadbeef);
578 next_wnd = SetClipboardViewer(win);
579 ok(GetLastError() == 0xdeadbeef, "GetLastError = %d\n", GetLastError());
580 LeaveCriticalSection(&clipboard_cs);
582 SetLastError( 0xdeadbeef );
583 ret = SetClipboardViewer( (HWND)0xdead );
584 ok( !ret, "SetClipboardViewer succeeded\n" );
585 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
586 SetLastError( 0xdeadbeef );
587 r = ChangeClipboardChain( win, (HWND)0xdead );
588 ok( !r, "ChangeClipboardChain succeeded\n" );
589 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
590 SetLastError( 0xdeadbeef );
591 r = ChangeClipboardChain( (HWND)0xdead, next_wnd );
592 ok( !r, "ChangeClipboardChain succeeded\n" );
593 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
595 if (pAddClipboardFormatListener)
597 r = pAddClipboardFormatListener(win);
598 ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError());
599 SetLastError( 0xdeadbeef );
600 r = pAddClipboardFormatListener( win );
601 todo_wine ok( !r, "AddClipboardFormatListener succeeded\n" );
602 todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
603 SetLastError( 0xdeadbeef );
604 r = pAddClipboardFormatListener( (HWND)0xdead );
605 todo_wine ok( !r, "AddClipboardFormatListener succeeded\n" );
606 todo_wine ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
607 r = pAddClipboardFormatListener( GetDesktopWindow() );
608 ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError());
609 r = pRemoveClipboardFormatListener( GetDesktopWindow() );
610 ok( r, "RemoveClipboardFormatListener failed err %d\n", GetLastError());
613 if (pGetClipboardSequenceNumber)
615 seq = pGetClipboardSequenceNumber();
616 ok( seq == old_seq, "sequence changed\n" );
618 count = SendMessageA( win, WM_USER + 1, 0, 0 );
619 ok( count, "WM_DRAWCLIPBOARD received\n" );
620 count = SendMessageA( win, WM_USER+2, 0, 0 );
621 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
623 SetLastError( 0xdeadbeef );
624 r = OpenClipboard( (HWND)0xdead );
625 ok( !r, "OpenClipboard succeeded\n" );
626 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
628 r = OpenClipboard(win);
629 ok(r, "OpenClipboard failed: %d\n", GetLastError());
631 if (pGetClipboardSequenceNumber)
633 seq = pGetClipboardSequenceNumber();
634 ok( seq == old_seq, "sequence changed\n" );
636 count = SendMessageA( win, WM_USER+1, 0, 0 );
637 ok( !count, "WM_DRAWCLIPBOARD received\n" );
638 count = SendMessageA( win, WM_USER+2, 0, 0 );
639 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
641 r = EmptyClipboard();
642 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
644 if (pGetClipboardSequenceNumber)
646 seq = pGetClipboardSequenceNumber();
647 ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
648 old_seq = seq;
650 count = SendMessageA( win, WM_USER+1, 0, 0 );
651 ok( !count, "WM_DRAWCLIPBOARD received\n" );
652 count = SendMessageA( win, WM_USER+2, 0, 0 );
653 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
654 count = SendMessageA( win, WM_USER+3, 0, 0 );
655 ok( !count, "WM_DESTROYCLIPBOARD received\n" );
657 r = EmptyClipboard();
658 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
659 /* sequence changes again, even though it was already empty */
660 if (pGetClipboardSequenceNumber)
662 seq = pGetClipboardSequenceNumber();
663 ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
664 old_seq = seq;
666 count = SendMessageA( win, WM_USER+1, 0, 0 );
667 ok( !count, "WM_DRAWCLIPBOARD received\n" );
668 count = SendMessageA( win, WM_USER+2, 0, 0 );
669 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
670 count = SendMessageA( win, WM_USER+3, 0, 0 );
671 ok( count, "WM_DESTROYCLIPBOARD not received\n" );
672 count = SendMessageA( win, WM_USER+4, 0, 0 );
673 ok( !count, "wrong format count %u on WM_DESTROYCLIPBOARD\n", count );
675 handle = SetClipboardData( CF_TEXT, create_text() );
676 ok(handle != 0, "SetClipboardData failed: %d\n", GetLastError());
678 if (pGetClipboardSequenceNumber)
680 seq = pGetClipboardSequenceNumber();
681 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
682 old_seq = seq;
684 count = SendMessageA( win, WM_USER+1, 0, 0 );
685 ok( !count, "WM_DRAWCLIPBOARD received\n" );
686 count = SendMessageA( win, WM_USER+2, 0, 0 );
687 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
689 SetClipboardData( CF_UNICODETEXT, 0 );
691 if (pGetClipboardSequenceNumber)
693 seq = pGetClipboardSequenceNumber();
694 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
695 old_seq = seq;
697 count = SendMessageA( win, WM_USER+1, 0, 0 );
698 ok( !count, "WM_DRAWCLIPBOARD received\n" );
699 count = SendMessageA( win, WM_USER+2, 0, 0 );
700 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
702 SetClipboardData( CF_UNICODETEXT, 0 ); /* same data again */
704 if (pGetClipboardSequenceNumber)
706 seq = pGetClipboardSequenceNumber();
707 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
708 old_seq = seq;
710 count = SendMessageA( win, WM_USER+1, 0, 0 );
711 ok( !count, "WM_DRAWCLIPBOARD received\n" );
712 count = SendMessageA( win, WM_USER+2, 0, 0 );
713 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
715 EnterCriticalSection(&clipboard_cs);
716 r = CloseClipboard();
717 ok(r, "CloseClipboard failed: %d\n", GetLastError());
718 LeaveCriticalSection(&clipboard_cs);
720 if (pGetClipboardSequenceNumber)
722 seq = pGetClipboardSequenceNumber();
723 ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
724 old_seq = seq;
726 count = SendMessageA( win, WM_USER+1, 0, 0 );
727 ok( count, "WM_DRAWCLIPBOARD not received\n" );
728 count = SendMessageA( win, WM_USER+2, 0, 0 );
729 todo_wine ok( count || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
731 r = OpenClipboard(win);
732 ok(r, "OpenClipboard failed: %d\n", GetLastError());
734 if (pGetClipboardSequenceNumber)
736 seq = pGetClipboardSequenceNumber();
737 ok( seq == old_seq, "sequence changed\n" );
739 count = SendMessageA( win, WM_USER+1, 0, 0 );
740 ok( !count, "WM_DRAWCLIPBOARD received\n" );
741 count = SendMessageA( win, WM_USER+2, 0, 0 );
742 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
744 SetClipboardData( CF_WAVE, 0 );
745 if (pGetClipboardSequenceNumber)
747 seq = pGetClipboardSequenceNumber();
748 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
749 old_seq = seq;
751 count = SendMessageA( win, WM_USER+1, 0, 0 );
752 ok( !count, "WM_DRAWCLIPBOARD received\n" );
753 count = SendMessageA( win, WM_USER+2, 0, 0 );
754 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
756 r = CloseClipboard();
757 ok(r, "CloseClipboard failed: %d\n", GetLastError());
758 if (pGetClipboardSequenceNumber)
760 /* no synthesized format, so CloseClipboard doesn't change the sequence */
761 seq = pGetClipboardSequenceNumber();
762 todo_wine ok( seq == old_seq, "sequence changed\n" );
763 old_seq = seq;
765 count = SendMessageA( win, WM_USER+1, 0, 0 );
766 ok( count, "WM_DRAWCLIPBOARD not received\n" );
767 count = SendMessageA( win, WM_USER+2, 0, 0 );
768 todo_wine ok( count || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
770 r = OpenClipboard(win);
771 ok(r, "OpenClipboard failed: %d\n", GetLastError());
772 r = CloseClipboard();
773 ok(r, "CloseClipboard failed: %d\n", GetLastError());
774 /* nothing changed */
775 if (pGetClipboardSequenceNumber)
777 seq = pGetClipboardSequenceNumber();
778 ok( seq == old_seq, "sequence changed\n" );
780 count = SendMessageA( win, WM_USER+1, 0, 0 );
781 ok( !count, "WM_DRAWCLIPBOARD received\n" );
782 count = SendMessageA( win, WM_USER+2, 0, 0 );
783 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
784 count = SendMessageA( win, WM_USER+3, 0, 0 );
785 ok( !count, "WM_DESTROYCLIPBOARD received\n" );
787 formats = CountClipboardFormats();
788 r = OpenClipboard(0);
789 ok(r, "OpenClipboard failed: %d\n", GetLastError());
790 r = EmptyClipboard();
791 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
792 r = CloseClipboard();
793 ok(r, "CloseClipboard failed: %d\n", GetLastError());
795 count = SendMessageA( win, WM_USER+1, 0, 0 );
796 ok( count, "WM_DRAWCLIPBOARD not received\n" );
797 count = SendMessageA( win, WM_USER+2, 0, 0 );
798 todo_wine ok( count || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
799 count = SendMessageA( win, WM_USER+3, 0, 0 );
800 ok( count, "WM_DESTROYCLIPBOARD not received\n" );
801 count = SendMessageA( win, WM_USER+4, 0, 0 );
802 ok( count == formats, "wrong format count %u on WM_DESTROYCLIPBOARD\n", count );
804 r = OpenClipboard(win);
805 ok(r, "OpenClipboard failed: %d\n", GetLastError());
806 SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_FIXED, 1 ));
807 if (pGetClipboardSequenceNumber)
809 seq = pGetClipboardSequenceNumber();
810 ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
811 old_seq = seq;
813 count = SendMessageA( win, WM_USER+2, 0, 0 );
814 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
815 count = SendMessageA( win, WM_USER+3, 0, 0 );
816 ok( !count, "WM_DESTROYCLIPBOARD received\n" );
818 EnterCriticalSection(&clipboard_cs);
819 r = CloseClipboard();
820 ok(r, "CloseClipboard failed: %d\n", GetLastError());
821 LeaveCriticalSection(&clipboard_cs);
823 if (pGetClipboardSequenceNumber)
825 seq = pGetClipboardSequenceNumber();
826 todo_wine ok( seq == old_seq, "sequence changed\n" );
827 old_seq = seq;
829 count = SendMessageA( win, WM_USER+1, 0, 0 );
830 ok( count, "WM_DRAWCLIPBOARD not received\n" );
831 count = SendMessageA( win, WM_USER+2, 0, 0 );
832 todo_wine ok( count || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
834 run_process( "grab_clipboard 0" );
836 if (pGetClipboardSequenceNumber)
838 seq = pGetClipboardSequenceNumber();
839 ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
840 old_seq = seq;
842 count = SendMessageA( win, WM_USER+1, 0, 0 );
843 todo_wine ok( count, "WM_DRAWCLIPBOARD not received\n" );
844 count = SendMessageA( win, WM_USER+2, 0, 0 );
845 todo_wine ok( count || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
847 r = OpenClipboard(0);
848 ok(r, "OpenClipboard failed: %d\n", GetLastError());
849 SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_FIXED, 1 ));
850 if (pGetClipboardSequenceNumber)
852 seq = pGetClipboardSequenceNumber();
853 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
854 old_seq = seq;
856 count = SendMessageA( win, WM_USER+1, 0, 0 );
857 ok( !count, "WM_DRAWCLIPBOARD received\n" );
858 count = SendMessageA( win, WM_USER+2, 0, 0 );
859 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
861 EnterCriticalSection(&clipboard_cs);
862 r = CloseClipboard();
863 ok(r, "CloseClipboard failed: %d\n", GetLastError());
864 LeaveCriticalSection(&clipboard_cs);
866 if (pGetClipboardSequenceNumber)
868 seq = pGetClipboardSequenceNumber();
869 todo_wine ok( seq == old_seq, "sequence changed\n" );
870 old_seq = seq;
872 count = SendMessageA( win, WM_USER+1, 0, 0 );
873 ok( count, "WM_DRAWCLIPBOARD not received\n" );
874 count = SendMessageA( win, WM_USER+2, 0, 0 );
875 todo_wine ok( count || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
877 run_process( "grab_clipboard 1" );
879 if (pGetClipboardSequenceNumber)
881 seq = pGetClipboardSequenceNumber();
882 ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
883 old_seq = seq;
885 count = SendMessageA( win, WM_USER+1, 0, 0 );
886 todo_wine ok( count, "WM_DRAWCLIPBOARD not received\n" );
887 count = SendMessageA( win, WM_USER+2, 0, 0 );
888 todo_wine ok( count || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
890 r = OpenClipboard(0);
891 ok(r, "OpenClipboard failed: %d\n", GetLastError());
892 SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_FIXED, 1 ));
893 if (pGetClipboardSequenceNumber)
895 seq = pGetClipboardSequenceNumber();
896 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
897 old_seq = seq;
899 count = SendMessageA( win, WM_USER+1, 0, 0 );
900 ok( !count, "WM_DRAWCLIPBOARD received\n" );
901 count = SendMessageA( win, WM_USER+2, 0, 0 );
902 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
904 EnterCriticalSection(&clipboard_cs);
905 r = CloseClipboard();
906 ok(r, "CloseClipboard failed: %d\n", GetLastError());
907 LeaveCriticalSection(&clipboard_cs);
909 if (pGetClipboardSequenceNumber)
911 seq = pGetClipboardSequenceNumber();
912 todo_wine ok( seq == old_seq, "sequence changed\n" );
913 old_seq = seq;
915 count = SendMessageA( win, WM_USER+1, 0, 0 );
916 ok( count, "WM_DRAWCLIPBOARD not received\n" );
917 count = SendMessageA( win, WM_USER+2, 0, 0 );
918 todo_wine ok( count || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
920 r = PostMessageA(win, WM_USER, 0, 0);
921 ok(r, "PostMessage failed: %d\n", GetLastError());
923 if (pRemoveClipboardFormatListener)
925 r = pRemoveClipboardFormatListener(win);
926 ok( r, "RemoveClipboardFormatListener failed err %d\n", GetLastError());
927 SetLastError( 0xdeadbeef );
928 r = pRemoveClipboardFormatListener(win);
929 todo_wine ok( !r, "RemoveClipboardFormatListener succeeded\n" );
930 todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
931 SetLastError( 0xdeadbeef );
932 r = pRemoveClipboardFormatListener( (HWND)0xdead );
933 todo_wine ok( !r, "RemoveClipboardFormatListener succeeded\n" );
934 todo_wine ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
936 return 0;
939 static void test_messages(void)
941 WNDCLASSA cls;
942 HWND win;
943 MSG msg;
944 HANDLE thread;
945 DWORD tid;
947 InitializeCriticalSection(&clipboard_cs);
949 memset(&cls, 0, sizeof(cls));
950 cls.lpfnWndProc = clipboard_wnd_proc;
951 cls.hInstance = GetModuleHandleA(NULL);
952 cls.lpszClassName = "clipboard_test";
953 RegisterClassA(&cls);
955 win = CreateWindowA("clipboard_test", NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0);
956 ok(win != NULL, "CreateWindow failed: %d\n", GetLastError());
958 thread = CreateThread(NULL, 0, clipboard_thread, (void*)win, 0, &tid);
959 ok(thread != NULL, "CreateThread failed: %d\n", GetLastError());
961 while(GetMessageA(&msg, NULL, 0, 0)) {
962 TranslateMessage(&msg);
963 DispatchMessageA(&msg);
966 ok(WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
967 CloseHandle(thread);
969 UnregisterClassA("clipboard_test", GetModuleHandleA(NULL));
970 DeleteCriticalSection(&clipboard_cs);
973 static BOOL is_moveable( HANDLE handle )
975 void *ptr = GlobalLock( handle );
976 if (ptr) GlobalUnlock( handle );
977 return ptr && ptr != handle;
980 static BOOL is_fixed( HANDLE handle )
982 void *ptr = GlobalLock( handle );
983 if (ptr) GlobalUnlock( handle );
984 return ptr && ptr == handle;
987 static BOOL is_freed( HANDLE handle )
989 void *ptr = GlobalLock( handle );
990 if (ptr) GlobalUnlock( handle );
991 return !ptr;
994 static UINT format_id;
995 static HBITMAP bitmap, bitmap2;
996 static HPALETTE palette;
997 static HPEN pen;
998 static const LOGPALETTE logpalette = { 0x300, 1 };
1000 static void test_handles( HWND hwnd )
1002 HGLOBAL h, htext, htext2;
1003 BOOL r;
1004 HANDLE data;
1005 DWORD process;
1006 BOOL is_owner = (GetWindowThreadProcessId( hwnd, &process ) && process == GetCurrentProcessId());
1008 trace( "hwnd %p\n", hwnd );
1009 htext = create_text();
1010 htext2 = create_text();
1011 bitmap = CreateBitmap( 10, 10, 1, 1, NULL );
1012 bitmap2 = CreateBitmap( 10, 10, 1, 1, NULL );
1013 palette = CreatePalette( &logpalette );
1014 pen = CreatePen( PS_SOLID, 1, 0 );
1016 r = OpenClipboard( hwnd );
1017 ok( r, "gle %d\n", GetLastError() );
1018 r = EmptyClipboard();
1019 ok( r, "gle %d\n", GetLastError() );
1021 h = SetClipboardData( CF_TEXT, htext );
1022 ok( h == htext, "got %p\n", h );
1023 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1024 h = SetClipboardData( format_id, htext2 );
1025 ok( h == htext2, "got %p\n", h );
1026 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1027 h = SetClipboardData( CF_BITMAP, bitmap );
1028 ok( h == bitmap, "got %p\n", h );
1029 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1030 h = SetClipboardData( CF_PALETTE, palette );
1031 ok( h == palette, "got %p\n", h );
1032 ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
1033 /* setting custom GDI formats crashes on 64-bit Windows */
1034 if (!is_win64)
1036 h = SetClipboardData( CF_GDIOBJFIRST + 1, bitmap2 );
1037 ok( h == bitmap2, "got %p\n", h );
1038 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1039 h = SetClipboardData( CF_GDIOBJFIRST + 2, pen );
1040 ok( h == pen, "got %p\n", h );
1041 ok( GetObjectType( h ) == OBJ_PEN, "expected pen %p\n", h );
1044 data = GetClipboardData( CF_TEXT );
1045 ok( data == htext, "wrong data %p\n", data );
1046 ok( is_moveable( data ), "expected moveable mem %p\n", data );
1048 data = GetClipboardData( format_id );
1049 ok( data == htext2, "wrong data %p, cf %08x\n", data, format_id );
1050 ok( is_moveable( data ), "expected moveable mem %p\n", data );
1052 r = CloseClipboard();
1053 ok( r, "gle %d\n", GetLastError() );
1055 /* data handles are still valid */
1056 ok( is_moveable( htext ), "expected moveable mem %p\n", htext );
1057 ok( is_moveable( htext2 ), "expected moveable mem %p\n", htext );
1058 ok( GetObjectType( bitmap ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap );
1059 ok( GetObjectType( bitmap2 ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap2 );
1060 ok( GetObjectType( palette ) == OBJ_PAL, "expected palette %p\n", palette );
1061 ok( GetObjectType( pen ) == OBJ_PEN, "expected pen %p\n", pen );
1063 r = OpenClipboard( hwnd );
1064 ok( r, "gle %d\n", GetLastError() );
1066 /* and now they are freed, unless we are the owner */
1067 if (!is_owner)
1069 todo_wine ok( is_freed( htext ), "expected freed mem %p\n", htext );
1070 todo_wine ok( is_freed( htext2 ), "expected freed mem %p\n", htext );
1072 data = GetClipboardData( CF_TEXT );
1073 todo_wine ok( is_fixed( data ), "expected fixed mem %p\n", data );
1075 data = GetClipboardData( format_id );
1076 todo_wine ok( is_fixed( data ), "expected fixed mem %p\n", data );
1078 else
1080 ok( is_moveable( htext ), "expected moveable mem %p\n", htext );
1081 ok( is_moveable( htext2 ), "expected moveable mem %p\n", htext );
1083 data = GetClipboardData( CF_TEXT );
1084 ok( data == htext, "wrong data %p\n", data );
1086 data = GetClipboardData( format_id );
1087 ok( data == htext2, "wrong data %p, cf %08x\n", data, format_id );
1090 data = GetClipboardData( CF_OEMTEXT );
1091 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1092 data = GetClipboardData( CF_UNICODETEXT );
1093 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1094 data = GetClipboardData( CF_BITMAP );
1095 ok( data == bitmap, "expected bitmap %p\n", data );
1096 data = GetClipboardData( CF_PALETTE );
1097 ok( data == palette, "expected palette %p\n", data );
1098 if (!is_win64)
1100 data = GetClipboardData( CF_GDIOBJFIRST + 1 );
1101 ok( data == bitmap2, "expected bitmap2 %p\n", data );
1102 data = GetClipboardData( CF_GDIOBJFIRST + 2 );
1103 ok( data == pen, "expected pen %p\n", data );
1105 data = GetClipboardData( CF_DIB );
1106 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1107 data = GetClipboardData( CF_DIBV5 );
1108 todo_wine ok( is_fixed( data ), "expected fixed mem %p\n", data );
1110 ok( GetObjectType( bitmap ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap );
1111 ok( GetObjectType( bitmap2 ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap2 );
1112 ok( GetObjectType( palette ) == OBJ_PAL, "expected palette %p\n", palette );
1113 ok( GetObjectType( pen ) == OBJ_PEN, "expected pen %p\n", pen );
1115 r = EmptyClipboard();
1116 ok( r, "gle %d\n", GetLastError() );
1118 /* w2003, w2008 don't seem to free the data here */
1119 ok( is_freed( htext ) || broken( !is_freed( htext )), "expected freed mem %p\n", htext );
1120 ok( is_freed( htext2 ) || broken( !is_freed( htext2 )), "expected freed mem %p\n", htext );
1121 ok( !GetObjectType( bitmap ), "expected freed handle %p\n", bitmap );
1122 ok( !GetObjectType( palette ), "expected freed handle %p\n", palette );
1123 ok( GetObjectType( bitmap2 ) == OBJ_BITMAP, "expected bitmap2 %p\n", bitmap2 );
1124 ok( GetObjectType( pen ) == OBJ_PEN, "expected pen %p\n", pen );
1126 r = CloseClipboard();
1127 ok( r, "gle %d\n", GetLastError() );
1130 static DWORD WINAPI test_handles_thread( void *arg )
1132 trace( "running from different thread\n" );
1133 test_handles( (HWND)arg );
1134 return 0;
1137 static DWORD WINAPI test_handles_thread2( void *arg )
1139 BOOL r;
1140 HANDLE h;
1141 char *ptr;
1143 r = OpenClipboard( 0 );
1144 ok( r, "gle %d\n", GetLastError() );
1145 h = GetClipboardData( CF_TEXT );
1146 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1147 ptr = GlobalLock( h );
1148 if (ptr) ok( !strcmp( "test", ptr ), "wrong data '%.5s'\n", ptr );
1149 GlobalUnlock( h );
1150 h = GetClipboardData( format_id );
1151 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1152 ptr = GlobalLock( h );
1153 if (ptr) ok( !strcmp( "test", ptr ), "wrong data '%.5s'\n", ptr );
1154 GlobalUnlock( h );
1155 h = GetClipboardData( CF_BITMAP );
1156 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1157 ok( h == bitmap, "different bitmap %p / %p\n", h, bitmap );
1158 trace( "bitmap %p\n", h );
1159 h = GetClipboardData( CF_PALETTE );
1160 ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
1161 ok( h == palette, "different palette %p / %p\n", h, palette );
1162 trace( "palette %p\n", h );
1163 if (!is_win64)
1165 h = GetClipboardData( CF_GDIOBJFIRST + 1 );
1166 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1167 ok( h == bitmap2, "different bitmap %p / %p\n", h, bitmap2 );
1168 trace( "bitmap2 %p\n", h );
1169 h = GetClipboardData( CF_GDIOBJFIRST + 2 );
1170 ok( GetObjectType( h ) == OBJ_PEN, "expected pen %p\n", h );
1171 ok( h == pen, "different pen %p / %p\n", h, pen );
1172 trace( "pen %p\n", h );
1174 h = GetClipboardData( CF_DIB );
1175 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1176 h = GetClipboardData( CF_DIBV5 );
1177 todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h );
1178 r = CloseClipboard();
1179 ok( r, "gle %d\n", GetLastError() );
1180 return 0;
1183 static void test_handles_process( const char *str )
1185 BOOL r;
1186 HANDLE h;
1187 char *ptr;
1189 format_id = RegisterClipboardFormatA( "my_cool_clipboard_format" );
1190 r = OpenClipboard( 0 );
1191 ok( r, "gle %d\n", GetLastError() );
1192 h = GetClipboardData( CF_TEXT );
1193 todo_wine_if( !h ) ok( is_fixed( h ), "expected fixed mem %p\n", h );
1194 ptr = GlobalLock( h );
1195 if (ptr) todo_wine ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr );
1196 GlobalUnlock( h );
1197 h = GetClipboardData( format_id );
1198 todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h );
1199 ptr = GlobalLock( h );
1200 if (ptr) ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr );
1201 GlobalUnlock( h );
1202 h = GetClipboardData( CF_BITMAP );
1203 todo_wine ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1204 trace( "bitmap %p\n", h );
1205 h = GetClipboardData( CF_PALETTE );
1206 todo_wine ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
1207 trace( "palette %p\n", h );
1208 h = GetClipboardData( CF_GDIOBJFIRST + 1 );
1209 ok( !GetObjectType( h ), "expected invalid %p\n", h );
1210 trace( "bitmap2 %p\n", h );
1211 h = GetClipboardData( CF_GDIOBJFIRST + 2 );
1212 ok( !GetObjectType( h ), "expected invalid %p\n", h );
1213 trace( "pen %p\n", h );
1214 h = GetClipboardData( CF_DIB );
1215 todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h );
1216 h = GetClipboardData( CF_DIBV5 );
1217 todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h );
1218 r = CloseClipboard();
1219 ok( r, "gle %d\n", GetLastError() );
1222 static void test_data_handles(void)
1224 BOOL r;
1225 HANDLE h;
1226 HWND hwnd = CreateWindowA( "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL );
1228 ok( hwnd != 0, "window creation failed\n" );
1229 format_id = RegisterClipboardFormatA( "my_cool_clipboard_format" );
1230 test_handles( 0 );
1231 test_handles( GetDesktopWindow() );
1232 test_handles( hwnd );
1233 run_thread( test_handles_thread, hwnd, __LINE__ );
1235 bitmap = CreateBitmap( 10, 10, 1, 1, NULL );
1236 bitmap2 = CreateBitmap( 10, 10, 1, 1, NULL );
1237 palette = CreatePalette( &logpalette );
1238 pen = CreatePen( PS_SOLID, 1, 0 );
1240 r = OpenClipboard( hwnd );
1241 ok( r, "gle %d\n", GetLastError() );
1242 r = EmptyClipboard();
1243 ok( r, "gle %d\n", GetLastError() );
1244 h = SetClipboardData( CF_TEXT, create_text() );
1245 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1246 h = SetClipboardData( format_id, create_text() );
1247 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1248 h = SetClipboardData( CF_BITMAP, bitmap );
1249 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1250 h = SetClipboardData( CF_PALETTE, palette );
1251 ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
1252 if (!is_win64)
1254 h = SetClipboardData( CF_GDIOBJFIRST + 1, bitmap2 );
1255 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1256 h = SetClipboardData( CF_GDIOBJFIRST + 2, pen );
1257 ok( GetObjectType( h ) == OBJ_PEN, "expected pen %p\n", h );
1259 r = CloseClipboard();
1260 ok( r, "gle %d\n", GetLastError() );
1262 run_thread( test_handles_thread2, 0, __LINE__ );
1263 run_process( "handles test" );
1265 r = OpenClipboard( hwnd );
1266 ok( r, "gle %d\n", GetLastError() );
1267 h = GetClipboardData( CF_TEXT );
1268 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1269 h = GetClipboardData( format_id );
1270 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1271 r = EmptyClipboard();
1272 ok( r, "gle %d\n", GetLastError() );
1273 r = CloseClipboard();
1274 ok( r, "gle %d\n", GetLastError() );
1276 DestroyWindow( hwnd );
1279 START_TEST(clipboard)
1281 char **argv;
1282 int argc = winetest_get_mainargs( &argv );
1283 HMODULE mod = GetModuleHandleA( "user32" );
1285 argv0 = argv[0];
1286 pAddClipboardFormatListener = (void *)GetProcAddress( mod, "AddClipboardFormatListener" );
1287 pRemoveClipboardFormatListener = (void *)GetProcAddress( mod, "RemoveClipboardFormatListener" );
1288 pGetClipboardSequenceNumber = (void *)GetProcAddress( mod, "GetClipboardSequenceNumber" );
1290 if (argc == 4 && !strcmp( argv[2], "set_clipboard_data" ))
1292 set_clipboard_data_process( atoi( argv[3] ));
1293 return;
1295 if (argc == 4 && !strcmp( argv[2], "grab_clipboard" ))
1297 grab_clipboard_process( atoi( argv[3] ));
1298 return;
1300 if (argc == 4 && !strcmp( argv[2], "handles" ))
1302 test_handles_process( argv[3] );
1303 return;
1306 test_RegisterClipboardFormatA();
1307 test_ClipboardOwner();
1308 test_synthesized();
1309 test_messages();
1310 test_data_handles();