[USER32_WINETEST] Enable the skipped part of clipboard.c as the issue documented...
[reactos.git] / rostests / winetests / user32 / clipboard.c
1 /*
2 * Unit test suite for clipboard functions.
3 *
4 * Copyright 2002 Dmitry Timoshkov
5 *
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.
10 *
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.
15 *
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
19 */
20
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"
28
29 #define WM_CLIPBOARDUPDATE 0x031D
30
31 static BOOL (WINAPI *pAddClipboardFormatListener)(HWND hwnd);
32 static BOOL (WINAPI *pRemoveClipboardFormatListener)(HWND hwnd);
33 static DWORD (WINAPI *pGetClipboardSequenceNumber)(void);
34
35 static const BOOL is_win64 = sizeof(void *) > sizeof(int);
36 static int thread_from_line;
37 static char *argv0;
38
39 static DWORD WINAPI open_clipboard_thread(LPVOID arg)
40 {
41 HWND hWnd = arg;
42 ok(OpenClipboard(hWnd), "%u: OpenClipboard failed\n", thread_from_line);
43 return 0;
44 }
45
46 static DWORD WINAPI empty_clipboard_thread(LPVOID arg)
47 {
48 SetLastError( 0xdeadbeef );
49 ok(!EmptyClipboard(), "%u: EmptyClipboard succeeded\n", thread_from_line );
50 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
51 thread_from_line, GetLastError());
52 return 0;
53 }
54
55 static DWORD WINAPI open_and_empty_clipboard_thread(LPVOID arg)
56 {
57 HWND hWnd = arg;
58 ok(OpenClipboard(hWnd), "%u: OpenClipboard failed\n", thread_from_line);
59 ok(EmptyClipboard(), "%u: EmptyClipboard failed\n", thread_from_line );
60 return 0;
61 }
62
63 static DWORD WINAPI open_and_empty_clipboard_win_thread(LPVOID arg)
64 {
65 HWND hwnd = CreateWindowA( "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL );
66 ok(OpenClipboard(hwnd), "%u: OpenClipboard failed\n", thread_from_line);
67 ok(EmptyClipboard(), "%u: EmptyClipboard failed\n", thread_from_line );
68 return 0;
69 }
70
71 static DWORD WINAPI set_clipboard_data_thread(LPVOID arg)
72 {
73 HWND hwnd = arg;
74 HANDLE ret;
75
76 SetLastError( 0xdeadbeef );
77 if (GetClipboardOwner() == hwnd)
78 {
79 SetClipboardData( CF_WAVE, 0 );
80 ok( IsClipboardFormatAvailable( CF_WAVE ), "%u: SetClipboardData failed\n", thread_from_line );
81 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
82 ok( ret != 0, "%u: SetClipboardData failed err %u\n", thread_from_line, GetLastError() );
83 SetLastError( 0xdeadbeef );
84 ret = GetClipboardData( CF_WAVE );
85 ok( !ret, "%u: GetClipboardData succeeded\n", thread_from_line );
86 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
87 thread_from_line, GetLastError());
88 }
89 else
90 {
91 SetClipboardData( CF_WAVE, 0 );
92 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
93 thread_from_line, GetLastError());
94 ok( !IsClipboardFormatAvailable( CF_WAVE ), "%u: SetClipboardData succeeded\n", thread_from_line );
95 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
96 ok( !ret, "%u: SetClipboardData succeeded\n", thread_from_line );
97 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
98 thread_from_line, GetLastError());
99 }
100 return 0;
101 }
102
103 static void set_clipboard_data_process( int arg )
104 {
105 HANDLE ret;
106
107 SetLastError( 0xdeadbeef );
108 if (arg)
109 {
110 todo_wine_if( arg == 1 || arg == 3 )
111 ok( IsClipboardFormatAvailable( CF_WAVE ), "process %u: CF_WAVE not available\n", arg );
112 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
113 ok( ret != 0, "process %u: SetClipboardData failed err %u\n", arg, GetLastError() );
114 }
115 else
116 {
117 SetClipboardData( CF_WAVE, 0 );
118 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "process %u: wrong error %u\n",
119 arg, GetLastError());
120 ok( !IsClipboardFormatAvailable( CF_WAVE ), "process %u: SetClipboardData succeeded\n", arg );
121 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
122 ok( !ret, "process %u: SetClipboardData succeeded\n", arg );
123 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "process %u: wrong error %u\n",
124 arg, GetLastError());
125 }
126 }
127
128 static void grab_clipboard_process( int arg )
129 {
130 BOOL ret;
131
132 SetLastError( 0xdeadbeef );
133 ret = OpenClipboard( 0 );
134 ok( ret, "OpenClipboard failed\n" );
135 ret = EmptyClipboard();
136 ok( ret, "EmptyClipboard failed\n" );
137 if (arg)
138 {
139 HANDLE ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
140 ok( ret != 0, "process %u: SetClipboardData failed err %u\n", arg, GetLastError() );
141 }
142 }
143
144 static void run_thread( LPTHREAD_START_ROUTINE func, void *arg, int line )
145 {
146 DWORD ret;
147 HANDLE thread;
148
149 thread_from_line = line;
150 thread = CreateThread(NULL, 0, func, arg, 0, NULL);
151 ok(thread != NULL, "%u: CreateThread failed with error %d\n", line, GetLastError());
152 for (;;)
153 {
154 ret = MsgWaitForMultipleObjectsEx( 1, &thread, 1000, QS_ALLINPUT, 0 );
155 if (ret == WAIT_OBJECT_0 + 1)
156 {
157 MSG msg;
158 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
159 }
160 else break;
161 }
162 ok(ret == WAIT_OBJECT_0, "%u: expected WAIT_OBJECT_0, got %u\n", line, ret);
163 CloseHandle(thread);
164 }
165
166 static void run_process( const char *args )
167 {
168 char cmd[MAX_PATH];
169 PROCESS_INFORMATION info;
170 STARTUPINFOA startup;
171
172 sprintf( cmd, "%s clipboard %s", argv0, args );
173 memset( &startup, 0, sizeof(startup) );
174 startup.cb = sizeof(startup);
175 ok( CreateProcessA( NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info ),
176 "CreateProcess %s failed\n", cmd );
177
178 winetest_wait_child_process( info.hProcess );
179 CloseHandle( info.hProcess );
180 CloseHandle( info.hThread );
181 }
182
183 static WNDPROC old_proc;
184 static LRESULT CALLBACK winproc_wrapper( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
185 {
186 static int wm_renderallformats;
187 static int wm_drawclipboard;
188 static int seqno;
189 DWORD msg_flags = InSendMessageEx( NULL );
190
191 if (!seqno) seqno = GetClipboardSequenceNumber();
192
193 trace( "%p msg %04x\n", hwnd, msg );
194 if (!wm_renderallformats)
195 {
196 ok( GetClipboardOwner() == hwnd, "%04x: wrong owner %p/%p\n", msg, GetClipboardOwner(), hwnd );
197 ok( seqno == GetClipboardSequenceNumber(), "%04x: seqno changed\n", msg );
198 }
199 else
200 {
201 ok( !GetClipboardOwner(), "%04x: wrong owner %p\n", msg, GetClipboardOwner() );
202 ok( seqno + 1 == GetClipboardSequenceNumber(), "%04x: seqno unchanged\n", msg );
203 }
204 ok( GetClipboardViewer() == hwnd, "%04x: wrong viewer %p/%p\n", msg, GetClipboardViewer(), hwnd );
205 ok( GetOpenClipboardWindow() == hwnd, "%04x: wrong open win %p/%p\n",
206 msg, GetOpenClipboardWindow(), hwnd );
207
208 switch (msg)
209 {
210 case WM_DESTROY:
211 ok( wm_renderallformats, "didn't receive WM_RENDERALLFORMATS before WM_DESTROY\n" );
212 todo_wine ok( wm_drawclipboard, "didn't receive WM_DRAWCLIPBOARD before WM_DESTROY\n" );
213 break;
214 case WM_DRAWCLIPBOARD:
215 ok( msg_flags == ISMEX_NOSEND, "WM_DRAWCLIPBOARD wrong flags %x\n", msg_flags );
216 wm_drawclipboard++;
217 break;
218 case WM_RENDERALLFORMATS:
219 ok( msg_flags == ISMEX_NOSEND, "WM_RENDERALLFORMATS wrong flags %x\n", msg_flags );
220 wm_renderallformats++;
221 break;
222 }
223 return old_proc( hwnd, msg, wp, lp );
224 }
225
226 static void test_ClipboardOwner(void)
227 {
228 HWND hWnd1, hWnd2;
229 BOOL ret;
230
231 SetLastError(0xdeadbeef);
232 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef,
233 "could not perform clipboard test: clipboard already owned\n");
234
235 hWnd1 = CreateWindowExA(0, "static", NULL, WS_POPUP,
236 0, 0, 10, 10, 0, 0, 0, NULL);
237 ok(hWnd1 != 0, "CreateWindowExA error %d\n", GetLastError());
238 trace("hWnd1 = %p\n", hWnd1);
239
240 hWnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP,
241 0, 0, 10, 10, 0, 0, 0, NULL);
242 ok(hWnd2 != 0, "CreateWindowExA error %d\n", GetLastError());
243 trace("hWnd2 = %p\n", hWnd2);
244
245 SetLastError(0xdeadbeef);
246 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
247 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */
248 "wrong error %u\n", GetLastError());
249
250 ok(OpenClipboard(0), "OpenClipboard failed\n");
251 ok(!GetClipboardOwner(), "clipboard should still be not owned\n");
252 ok(!OpenClipboard(hWnd1), "OpenClipboard should fail since clipboard already opened\n");
253 ok(OpenClipboard(0), "OpenClipboard again failed\n");
254 ret = CloseClipboard();
255 ok( ret, "CloseClipboard error %d\n", GetLastError());
256
257 ok(OpenClipboard(hWnd1), "OpenClipboard failed\n");
258 run_thread( open_clipboard_thread, hWnd1, __LINE__ );
259 run_thread( empty_clipboard_thread, 0, __LINE__ );
260 run_thread( set_clipboard_data_thread, hWnd1, __LINE__ );
261 ok( !IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE available\n" );
262 ok( !GetClipboardData( CF_WAVE ), "CF_WAVE data available\n" );
263 run_process( "set_clipboard_data 0" );
264 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
265 ok(OpenClipboard(hWnd1), "OpenClipboard failed\n");
266
267 SetLastError(0xdeadbeef);
268 ret = OpenClipboard(hWnd2);
269 ok(!ret && (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED),
270 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
271
272 SetLastError(0xdeadbeef);
273 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should still be not owned\n");
274 ret = EmptyClipboard();
275 ok( ret, "EmptyClipboard error %d\n", GetLastError());
276 ok(GetClipboardOwner() == hWnd1, "clipboard should be owned by %p, not by %p\n", hWnd1, GetClipboardOwner());
277 run_thread( empty_clipboard_thread, 0, __LINE__ );
278 run_thread( set_clipboard_data_thread, hWnd1, __LINE__ );
279 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
280 ok( GetClipboardData( CF_WAVE ) != 0, "CF_WAVE data not available\n" );
281 run_process( "set_clipboard_data 1" );
282
283 SetLastError(0xdeadbeef);
284 ret = OpenClipboard(hWnd2);
285 ok(!ret && (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED),
286 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
287
288 ret = CloseClipboard();
289 ok( ret, "CloseClipboard error %d\n", GetLastError());
290 ok(GetClipboardOwner() == hWnd1, "clipboard should still be owned\n");
291
292 /* any window will do, even from a different process */
293 ret = OpenClipboard( GetDesktopWindow() );
294 ok( ret, "OpenClipboard error %d\n", GetLastError());
295 ret = EmptyClipboard();
296 ok( ret, "EmptyClipboard error %d\n", GetLastError());
297 ok( GetClipboardOwner() == GetDesktopWindow(), "wrong owner %p/%p\n",
298 GetClipboardOwner(), GetDesktopWindow() );
299 run_thread( set_clipboard_data_thread, GetDesktopWindow(), __LINE__ );
300 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
301 ok( GetClipboardData( CF_WAVE ) != 0, "CF_WAVE data not available\n" );
302 run_process( "set_clipboard_data 2" );
303 ret = CloseClipboard();
304 ok( ret, "CloseClipboard error %d\n", GetLastError());
305
306 ret = OpenClipboard( hWnd1 );
307 ok( ret, "OpenClipboard error %d\n", GetLastError());
308 ret = EmptyClipboard();
309 ok( ret, "EmptyClipboard error %d\n", GetLastError());
310 SetClipboardData( CF_WAVE, 0 );
311 SetClipboardViewer( hWnd1 );
312 ok( GetClipboardOwner() == hWnd1, "wrong owner %p/%p\n", GetClipboardOwner(), hWnd1 );
313 ok( GetClipboardViewer() == hWnd1, "wrong viewer %p/%p\n", GetClipboardViewer(), hWnd1 );
314 ok( GetOpenClipboardWindow() == hWnd1, "wrong open win %p/%p\n", GetOpenClipboardWindow(), hWnd1 );
315 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
316
317 old_proc = (WNDPROC)SetWindowLongPtrA( hWnd1, GWLP_WNDPROC, (LONG_PTR)winproc_wrapper );
318 ret = DestroyWindow(hWnd1);
319 ok( ret, "DestroyWindow error %d\n", GetLastError());
320 ret = DestroyWindow(hWnd2);
321 ok( ret, "DestroyWindow error %d\n", GetLastError());
322 SetLastError(0xdeadbeef);
323 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should not be owned\n");
324 ok(!GetClipboardViewer() && GetLastError() == 0xdeadbeef, "viewer still exists\n");
325 ok(!GetOpenClipboardWindow() && GetLastError() == 0xdeadbeef, "clipboard should not be open\n");
326 todo_wine ok( !IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE available\n" );
327
328 SetLastError( 0xdeadbeef );
329 ret = CloseClipboard();
330 ok( !ret, "CloseClipboard succeeded\n" );
331 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError() );
332
333 ret = OpenClipboard( 0 );
334 ok( ret, "OpenClipboard error %d\n", GetLastError());
335 run_thread( set_clipboard_data_thread, 0, __LINE__ );
336 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
337 ok( GetClipboardData( CF_WAVE ) != 0, "CF_WAVE data not available\n" );
338 run_process( "set_clipboard_data 3" );
339 ret = CloseClipboard();
340 ok( ret, "CloseClipboard error %d\n", GetLastError());
341
342 run_thread( open_and_empty_clipboard_thread, 0, __LINE__ );
343 ok( !GetOpenClipboardWindow(), "wrong open window %p\n", GetOpenClipboardWindow() );
344 ok( !GetClipboardOwner(), "wrong owner window %p\n", GetClipboardOwner() );
345
346 ret = OpenClipboard( 0 );
347 ok( ret, "OpenClipboard error %d\n", GetLastError());
348 run_thread( set_clipboard_data_thread, 0, __LINE__ );
349 ok( IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE not available\n" );
350 ok( GetClipboardData( CF_WAVE ) != 0, "CF_WAVE data not available\n" );
351 run_process( "set_clipboard_data 4" );
352 ret = EmptyClipboard();
353 ok( ret, "EmptyClipboard error %d\n", GetLastError());
354 ret = CloseClipboard();
355 ok( ret, "CloseClipboard error %d\n", GetLastError());
356
357 SetLastError( 0xdeadbeef );
358 ok( !SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 )),
359 "SetClipboardData succeeded\n" );
360 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError() );
361 ok( !IsClipboardFormatAvailable( CF_WAVE ), "SetClipboardData succeeded\n" );
362
363 run_thread( open_and_empty_clipboard_thread, GetDesktopWindow(), __LINE__ );
364 ok( !GetOpenClipboardWindow(), "wrong open window %p\n", GetOpenClipboardWindow() );
365 ok( GetClipboardOwner() == GetDesktopWindow(), "wrong owner window %p / %p\n",
366 GetClipboardOwner(), GetDesktopWindow() );
367
368 run_thread( open_and_empty_clipboard_win_thread, 0, __LINE__ );
369 ok( !GetOpenClipboardWindow(), "wrong open window %p\n", GetOpenClipboardWindow() );
370 ok( !GetClipboardOwner(), "wrong owner window %p\n", GetClipboardOwner() );
371 }
372
373 static void test_RegisterClipboardFormatA(void)
374 {
375 ATOM atom_id;
376 UINT format_id, format_id2;
377 char buf[256];
378 int len;
379 BOOL ret;
380 HANDLE handle;
381
382 format_id = RegisterClipboardFormatA("my_cool_clipboard_format");
383 ok(format_id > 0xc000 && format_id < 0xffff, "invalid clipboard format id %04x\n", format_id);
384
385 format_id2 = RegisterClipboardFormatA("MY_COOL_CLIPBOARD_FORMAT");
386 ok(format_id2 == format_id, "invalid clipboard format id %04x\n", format_id2);
387
388 len = GetClipboardFormatNameA(format_id, buf, 256);
389 ok(len == lstrlenA("my_cool_clipboard_format"), "wrong format name length %d\n", len);
390 ok(!lstrcmpA(buf, "my_cool_clipboard_format"), "wrong format name \"%s\"\n", buf);
391
392 lstrcpyA(buf, "foo");
393 SetLastError(0xdeadbeef);
394 len = GetAtomNameA((ATOM)format_id, buf, 256);
395 ok(len == 0, "GetAtomNameA should fail\n");
396 ok(GetLastError() == ERROR_INVALID_HANDLE, "err %d\n", GetLastError());
397
398 todo_wine
399 {
400 lstrcpyA(buf, "foo");
401 SetLastError(0xdeadbeef);
402 len = GlobalGetAtomNameA((ATOM)format_id, buf, 256);
403 ok(len == 0, "GlobalGetAtomNameA should fail\n");
404 ok(GetLastError() == ERROR_INVALID_HANDLE, "err %d\n", GetLastError());
405 }
406
407 SetLastError(0xdeadbeef);
408 atom_id = FindAtomA("my_cool_clipboard_format");
409 ok(atom_id == 0, "FindAtomA should fail\n");
410 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError());
411
412 if (0)
413 {
414 /* this relies on the clipboard and global atom table being different */
415 SetLastError(0xdeadbeef);
416 atom_id = GlobalFindAtomA("my_cool_clipboard_format");
417 ok(atom_id == 0, "GlobalFindAtomA should fail\n");
418 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError());
419 }
420
421 for (format_id = 0; format_id < 0xffff; format_id++)
422 {
423 SetLastError(0xdeadbeef);
424 len = GetClipboardFormatNameA(format_id, buf, 256);
425
426 if (format_id < 0xc000)
427 ok(!len, "GetClipboardFormatNameA should fail, but it returned %d (%s)\n", len, buf);
428 else if (len && winetest_debug > 1)
429 trace("%04x: %s\n", format_id, len ? buf : "");
430 }
431
432 ret = OpenClipboard(0);
433 ok( ret, "OpenClipboard error %d\n", GetLastError());
434
435 /* try some invalid/unregistered formats */
436 SetLastError( 0xdeadbeef );
437 handle = SetClipboardData( 0, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
438 ok( !handle, "SetClipboardData succeeded\n" );
439 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError());
440 handle = SetClipboardData( 0x1234, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
441 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
442 handle = SetClipboardData( 0x123456, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
443 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
444 handle = SetClipboardData( 0xffff8765, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
445 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
446
447 ok( IsClipboardFormatAvailable( 0x1234 ), "format missing\n" );
448 ok( IsClipboardFormatAvailable( 0x123456 ), "format missing\n" );
449 ok( IsClipboardFormatAvailable( 0xffff8765 ), "format missing\n" );
450 ok( !IsClipboardFormatAvailable( 0 ), "format available\n" );
451 ok( !IsClipboardFormatAvailable( 0x3456 ), "format available\n" );
452 ok( !IsClipboardFormatAvailable( 0x8765 ), "format available\n" );
453
454 trace("# of formats available: %d\n", CountClipboardFormats());
455
456 format_id = 0;
457 while ((format_id = EnumClipboardFormats(format_id)))
458 {
459 ok(IsClipboardFormatAvailable(format_id), "format %04x was listed as available\n", format_id);
460 len = GetClipboardFormatNameA(format_id, buf, 256);
461 trace("%04x: %s\n", format_id, len ? buf : "");
462 }
463
464 ret = EmptyClipboard();
465 ok( ret, "EmptyClipboard error %d\n", GetLastError());
466 ret =CloseClipboard();
467 ok( ret, "CloseClipboard error %d\n", GetLastError());
468
469 if (CountClipboardFormats())
470 {
471 SetLastError(0xdeadbeef);
472 ok(!EnumClipboardFormats(0), "EnumClipboardFormats should fail if clipboard wasn't open\n");
473 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN,
474 "Last error should be set to ERROR_CLIPBOARD_NOT_OPEN, not %d\n", GetLastError());
475 }
476
477 SetLastError(0xdeadbeef);
478 ok(!EmptyClipboard(), "EmptyClipboard should fail if clipboard wasn't open\n");
479 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */
480 "Wrong error %u\n", GetLastError());
481
482 format_id = RegisterClipboardFormatA("#1234");
483 ok(format_id == 1234, "invalid clipboard format id %04x\n", format_id);
484 }
485
486 static HGLOBAL create_textA(void)
487 {
488 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 5);
489 char *p = GlobalLock(h);
490 strcpy(p, "test");
491 GlobalUnlock(h);
492 return h;
493 }
494
495 static HGLOBAL create_textW(void)
496 {
497 static const WCHAR testW[] = {'t','e','s','t',0};
498 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 5 * sizeof(WCHAR));
499 WCHAR *p = GlobalLock(h);
500 lstrcpyW(p, testW);
501 GlobalUnlock(h);
502 return h;
503 }
504
505 static HANDLE create_metafile(void)
506 {
507 const RECT rect = {0, 0, 100, 100};
508 METAFILEPICT *pict;
509 HANDLE ret;
510 HMETAFILE mf;
511 HDC hdc = CreateMetaFileA( NULL );
512 ExtTextOutA( hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL );
513 mf = CloseMetaFile( hdc );
514 ret = GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(*pict) );
515 pict = GlobalLock( ret );
516 pict->mm = MM_TEXT;
517 pict->xExt = pict->yExt = 100;
518 pict->hMF = mf;
519 GlobalUnlock( ret );
520 return ret;
521 }
522
523 static HENHMETAFILE create_emf(void)
524 {
525 const RECT rect = {0, 0, 100, 100};
526 HDC hdc = CreateEnhMetaFileA(NULL, NULL, &rect, "HENHMETAFILE Ole Clipboard Test\0Test\0\0");
527 ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
528 return CloseEnhMetaFile(hdc);
529 }
530
531 static HBITMAP create_bitmap(void)
532 {
533 HDC hdc = GetDC( 0 );
534 UINT bpp = GetDeviceCaps( hdc, BITSPIXEL );
535 ReleaseDC( 0, hdc );
536 return CreateBitmap( 10, 10, 1, bpp, NULL );
537 }
538
539 static HBITMAP create_dib( BOOL v5 )
540 {
541 HANDLE ret;
542 BITMAPINFOHEADER *hdr;
543
544 ret = GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT,
545 sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD) + 16 * 16 * 4 );
546 hdr = GlobalLock( ret );
547 hdr->biSize = v5 ? sizeof(BITMAPV5HEADER) : sizeof(*hdr);
548 hdr->biWidth = 16;
549 hdr->biHeight = 16;
550 hdr->biPlanes = 1;
551 hdr->biBitCount = 32;
552 hdr->biCompression = BI_RGB;
553 if (v5)
554 {
555 BITMAPV5HEADER *hdr5 = (BITMAPV5HEADER *)hdr;
556 hdr5->bV5RedMask = 0x0000ff;
557 hdr5->bV5GreenMask = 0x00ff00;
558 hdr5->bV5BlueMask = 0xff0000;
559 hdr5->bV5AlphaMask = 0xff000000;
560 }
561 GlobalUnlock( ret );
562 return ret;
563 }
564
565 static void test_synthesized(void)
566 {
567 static const struct test
568 {
569 UINT format;
570 UINT expected[8];
571 UINT todo;
572 } tests[] =
573 {
574 /* 0 */ { CF_TEXT, { CF_TEXT, CF_LOCALE, CF_OEMTEXT, CF_UNICODETEXT }, 1 << 1 },
575 { CF_OEMTEXT, { CF_OEMTEXT, CF_LOCALE, CF_TEXT, CF_UNICODETEXT }, 1 << 1 },
576 { CF_UNICODETEXT, { CF_UNICODETEXT, CF_LOCALE, CF_TEXT, CF_OEMTEXT }, 1 << 1 },
577 { CF_ENHMETAFILE, { CF_ENHMETAFILE, CF_METAFILEPICT }},
578 { CF_METAFILEPICT, { CF_METAFILEPICT, CF_ENHMETAFILE }},
579 /* 5 */ { CF_BITMAP, { CF_BITMAP, CF_DIB, CF_DIBV5 }, 1 << 2 },
580 { CF_DIB, { CF_DIB, CF_BITMAP, CF_DIBV5 }, 1 << 2 },
581 { CF_DIBV5, { CF_DIBV5, CF_BITMAP, CF_DIB }, (1 << 1) | (1 << 2) },
582 };
583
584 HGLOBAL h, htext;
585 HENHMETAFILE emf;
586 BOOL r;
587 UINT cf, i, j, count;
588 HANDLE data;
589
590 htext = create_textA();
591 emf = create_emf();
592
593 r = OpenClipboard(NULL);
594 ok(r, "gle %d\n", GetLastError());
595 r = EmptyClipboard();
596 ok(r, "gle %d\n", GetLastError());
597 h = SetClipboardData(CF_TEXT, htext);
598 ok(h == htext, "got %p\n", h);
599 h = SetClipboardData(CF_ENHMETAFILE, emf);
600 ok(h == emf, "got %p\n", h);
601 r = CloseClipboard();
602 ok(r, "gle %d\n", GetLastError());
603
604 count = CountClipboardFormats();
605 todo_wine ok( count == 6, "count %u\n", count );
606 r = IsClipboardFormatAvailable( CF_TEXT );
607 ok( r, "CF_TEXT not available err %d\n", GetLastError());
608 r = IsClipboardFormatAvailable( CF_LOCALE );
609 todo_wine ok( r, "CF_LOCALE not available err %d\n", GetLastError());
610 r = IsClipboardFormatAvailable( CF_OEMTEXT );
611 ok( r, "CF_OEMTEXT not available err %d\n", GetLastError());
612 r = IsClipboardFormatAvailable( CF_UNICODETEXT );
613 ok( r, "CF_UNICODETEXT not available err %d\n", GetLastError());
614 r = IsClipboardFormatAvailable( CF_ENHMETAFILE );
615 ok( r, "CF_ENHMETAFILE not available err %d\n", GetLastError());
616 r = IsClipboardFormatAvailable( CF_METAFILEPICT );
617 ok( r, "CF_METAFILEPICT not available err %d\n", GetLastError());
618
619 r = OpenClipboard(NULL);
620 ok(r, "gle %d\n", GetLastError());
621 cf = EnumClipboardFormats(0);
622 ok(cf == CF_TEXT, "cf %08x\n", cf);
623 data = GetClipboardData(cf);
624 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
625
626 cf = EnumClipboardFormats(cf);
627 ok(cf == CF_ENHMETAFILE, "cf %08x\n", cf);
628 data = GetClipboardData(cf);
629 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
630
631 cf = EnumClipboardFormats(cf);
632 todo_wine ok(cf == CF_LOCALE, "cf %08x\n", cf);
633 if(cf == CF_LOCALE)
634 {
635 data = GetClipboardData(cf);
636 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
637 cf = EnumClipboardFormats(cf);
638 }
639 ok(cf == CF_OEMTEXT, "cf %08x\n", cf);
640 data = GetClipboardData(cf);
641 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
642
643 cf = EnumClipboardFormats(cf);
644 ok(cf == CF_UNICODETEXT, "cf %08x\n", cf);
645
646 cf = EnumClipboardFormats(cf);
647 ok(cf == CF_METAFILEPICT, "cf %08x\n", cf);
648 data = GetClipboardData(cf);
649 todo_wine ok(data != NULL, "couldn't get data, cf %08x\n", cf);
650
651 cf = EnumClipboardFormats(cf);
652 ok(cf == 0, "cf %08x\n", cf);
653
654 r = EmptyClipboard();
655 ok(r, "gle %d\n", GetLastError());
656
657 r = CloseClipboard();
658 ok(r, "gle %d\n", GetLastError());
659
660 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
661 {
662 r = OpenClipboard(NULL);
663 ok(r, "%u: gle %d\n", i, GetLastError());
664 r = EmptyClipboard();
665 ok(r, "%u: gle %d\n", i, GetLastError());
666
667 switch (tests[i].format)
668 {
669 case CF_TEXT:
670 case CF_OEMTEXT:
671 SetClipboardData( tests[i].format, create_textA() );
672 break;
673 case CF_UNICODETEXT:
674 SetClipboardData( CF_UNICODETEXT, create_textW() );
675 break;
676 case CF_ENHMETAFILE:
677 SetClipboardData( CF_ENHMETAFILE, create_emf() );
678 break;
679 case CF_METAFILEPICT:
680 SetClipboardData( CF_METAFILEPICT, create_metafile() );
681 break;
682 case CF_BITMAP:
683 SetClipboardData( CF_BITMAP, create_bitmap() );
684 break;
685 case CF_DIB:
686 case CF_DIBV5:
687 SetClipboardData( tests[i].format, create_dib( tests[i].format == CF_DIBV5 ));
688 break;
689 }
690
691 count = CountClipboardFormats();
692 ok( count == 1, "%u: count %u\n", i, count );
693
694 r = CloseClipboard();
695 ok(r, "%u: gle %d\n", i, GetLastError());
696
697 count = CountClipboardFormats();
698 for (j = 0; tests[i].expected[j]; j++)
699 {
700 r = IsClipboardFormatAvailable( tests[i].expected[j] );
701 todo_wine_if (tests[i].todo & (1 << j))
702 ok( r, "%u: %04x not available\n", i, tests[i].expected[j] );
703 }
704 todo_wine_if (tests[i].todo)
705 ok( count == j, "%u: count %u instead of %u\n", i, count, j );
706
707 r = OpenClipboard(NULL);
708 ok(r, "%u: gle %d\n", i, GetLastError());
709 cf = 0;
710 for (j = 0; tests[i].expected[j]; j++)
711 {
712 cf = EnumClipboardFormats( cf );
713 todo_wine_if (tests[i].todo & (1 << j))
714 ok(cf == tests[i].expected[j], "%u.%u: got %04x instead of %04x\n",
715 i, j, cf, tests[i].expected[j] );
716 if (cf != tests[i].expected[j]) break;
717 data = GetClipboardData( cf );
718 todo_wine_if (j && cf == CF_METAFILEPICT)
719 ok(data != NULL ||
720 broken( tests[i].format == CF_DIBV5 && cf == CF_DIB ), /* >= Vista */
721 "%u: couldn't get data, cf %04x err %d\n", i, cf, GetLastError());
722 if (cf == CF_LOCALE)
723 {
724 UINT *ptr = GlobalLock( data );
725 ok( GlobalSize( data ) == sizeof(*ptr), "%u: size %lu\n", i, GlobalSize( data ));
726 ok( *ptr == GetUserDefaultLCID() ||
727 broken( *ptr == MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT )),
728 "%u: CF_LOCALE %08x/%08x\n", i, *ptr, GetUserDefaultLCID() );
729 GlobalUnlock( data );
730 }
731 }
732 if (!tests[i].expected[j])
733 {
734 cf = EnumClipboardFormats( cf );
735 ok(cf == 0, "%u: cf %04x\n", i, cf);
736 }
737
738 /* now with delayed rendering */
739
740 r = EmptyClipboard();
741 ok(r, "%u: gle %d\n", i, GetLastError());
742
743 SetClipboardData( tests[i].format, 0 );
744
745 count = CountClipboardFormats();
746 ok( count == 1, "%u: count %u\n", i, count );
747
748 r = CloseClipboard();
749 ok(r, "%u: gle %d\n", i, GetLastError());
750
751 count = CountClipboardFormats();
752 for (j = 0; tests[i].expected[j]; j++)
753 {
754 r = IsClipboardFormatAvailable( tests[i].expected[j] );
755 todo_wine_if (tests[i].todo & (1 << j))
756 ok( r, "%u: %04x not available\n", i, tests[i].expected[j] );
757 }
758 todo_wine_if (tests[i].todo)
759 ok( count == j, "%u: count %u instead of %u\n", i, count, j );
760
761 r = OpenClipboard(NULL);
762 ok(r, "%u: gle %d\n", i, GetLastError());
763 cf = 0;
764 for (j = 0; tests[i].expected[j]; j++)
765 {
766 cf = EnumClipboardFormats( cf );
767 todo_wine_if (tests[i].todo & (1 << j))
768 ok(cf == tests[i].expected[j], "%u.%u: got %04x instead of %04x\n",
769 i, j, cf, tests[i].expected[j] );
770 if (cf != tests[i].expected[j]) break;
771 data = GetClipboardData( cf );
772 if (cf == CF_LOCALE)
773 ok(data != NULL, "%u: CF_LOCALE no data\n", i);
774 else
775 ok(!data, "%u: format %04x got data %p\n", i, cf, data);
776 }
777 if (!tests[i].expected[j])
778 {
779 cf = EnumClipboardFormats( cf );
780 ok(cf == 0, "%u: cf %04x\n", i, cf);
781 }
782 r = CloseClipboard();
783 ok(r, "%u: gle %d\n", i, GetLastError());
784 }
785
786 r = OpenClipboard(NULL);
787 ok(r, "gle %d\n", GetLastError());
788 r = EmptyClipboard();
789 ok(r, "gle %d\n", GetLastError());
790 r = CloseClipboard();
791 ok(r, "gle %d\n", GetLastError());
792 }
793
794 static CRITICAL_SECTION clipboard_cs;
795 static HWND next_wnd;
796 static UINT wm_drawclipboard;
797 static UINT wm_clipboardupdate;
798 static UINT wm_destroyclipboard;
799 static UINT wm_renderformat;
800 static UINT nb_formats;
801 static BOOL cross_thread;
802
803 static LRESULT CALLBACK clipboard_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
804 {
805 LRESULT ret;
806 DWORD msg_flags = InSendMessageEx( NULL );
807
808 switch(msg) {
809 case WM_DRAWCLIPBOARD:
810 ok( msg_flags == (cross_thread ? ISMEX_NOTIFY : ISMEX_NOSEND),
811 "WM_DRAWCLIPBOARD wrong flags %x\n", msg_flags );
812 EnterCriticalSection(&clipboard_cs);
813 wm_drawclipboard++;
814 LeaveCriticalSection(&clipboard_cs);
815 break;
816 case WM_CHANGECBCHAIN:
817 ok( msg_flags == (cross_thread ? ISMEX_SEND : ISMEX_NOSEND),
818 "WM_CHANGECBCHAIN wrong flags %x\n", msg_flags );
819 if (next_wnd == (HWND)wp)
820 next_wnd = (HWND)lp;
821 else if (next_wnd)
822 SendMessageA(next_wnd, msg, wp, lp);
823 break;
824 case WM_DESTROYCLIPBOARD:
825 ok( msg_flags == (cross_thread ? ISMEX_SEND : ISMEX_NOSEND),
826 "WM_DESTROYCLIPBOARD wrong flags %x\n", msg_flags );
827 wm_destroyclipboard++;
828 ok( GetClipboardOwner() == hwnd, "WM_DESTROYCLIPBOARD owner %p\n", GetClipboardOwner() );
829 nb_formats = CountClipboardFormats();
830 break;
831 case WM_RENDERFORMAT:
832 ok( !wm_renderformat, "multiple WM_RENDERFORMAT %04x / %04lx\n", wm_renderformat, wp );
833 wm_renderformat = wp;
834 break;
835 case WM_CLIPBOARDUPDATE:
836 ok( msg_flags == ISMEX_NOSEND, "WM_CLIPBOARDUPDATE wrong flags %x\n", msg_flags );
837 EnterCriticalSection(&clipboard_cs);
838 wm_clipboardupdate++;
839 LeaveCriticalSection(&clipboard_cs);
840 break;
841 case WM_USER:
842 ChangeClipboardChain(hwnd, next_wnd);
843 PostQuitMessage(0);
844 break;
845 case WM_USER+1:
846 ret = wm_drawclipboard;
847 wm_drawclipboard = 0;
848 return ret;
849 case WM_USER+2:
850 ret = wm_clipboardupdate;
851 wm_clipboardupdate = 0;
852 return ret;
853 case WM_USER+3:
854 ret = wm_destroyclipboard;
855 wm_destroyclipboard = 0;
856 return ret;
857 case WM_USER+4:
858 ret = wm_renderformat;
859 wm_renderformat = 0;
860 return ret;
861 case WM_USER+5:
862 return nb_formats;
863 }
864
865 return DefWindowProcA(hwnd, msg, wp, lp);
866 }
867
868 static DWORD WINAPI clipboard_thread(void *param)
869 {
870 HWND ret, win = param;
871 BOOL r;
872 MSG msg;
873 HANDLE handle;
874 UINT count, fmt, formats, old_seq = 0, seq;
875
876 cross_thread = (GetWindowThreadProcessId( win, NULL ) != GetCurrentThreadId());
877 trace( "%s-threaded test\n", cross_thread ? "multi" : "single" );
878
879 if (pGetClipboardSequenceNumber) old_seq = pGetClipboardSequenceNumber();
880
881 EnterCriticalSection(&clipboard_cs);
882 SetLastError(0xdeadbeef);
883 next_wnd = SetClipboardViewer(win);
884 ok(GetLastError() == 0xdeadbeef, "GetLastError = %d\n", GetLastError());
885 LeaveCriticalSection(&clipboard_cs);
886
887 SetLastError( 0xdeadbeef );
888 ret = SetClipboardViewer( (HWND)0xdead );
889 ok( !ret, "SetClipboardViewer succeeded\n" );
890 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
891 SetLastError( 0xdeadbeef );
892 r = ChangeClipboardChain( win, (HWND)0xdead );
893 ok( !r, "ChangeClipboardChain succeeded\n" );
894 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
895 SetLastError( 0xdeadbeef );
896 r = ChangeClipboardChain( (HWND)0xdead, next_wnd );
897 ok( !r, "ChangeClipboardChain succeeded\n" );
898 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
899
900 if (pAddClipboardFormatListener)
901 {
902 r = pAddClipboardFormatListener(win);
903 ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError());
904 SetLastError( 0xdeadbeef );
905 r = pAddClipboardFormatListener( win );
906 ok( !r, "AddClipboardFormatListener succeeded\n" );
907 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
908 SetLastError( 0xdeadbeef );
909 r = pAddClipboardFormatListener( (HWND)0xdead );
910 ok( !r, "AddClipboardFormatListener succeeded\n" );
911 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
912 r = pAddClipboardFormatListener( GetDesktopWindow() );
913 ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError());
914 r = pRemoveClipboardFormatListener( GetDesktopWindow() );
915 ok( r, "RemoveClipboardFormatListener failed err %d\n", GetLastError());
916 }
917
918 if (pGetClipboardSequenceNumber)
919 {
920 seq = pGetClipboardSequenceNumber();
921 ok( seq == old_seq, "sequence changed\n" );
922 }
923 if (!cross_thread)
924 {
925 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
926 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
927 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
928 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
929 }
930 count = SendMessageA( win, WM_USER + 1, 0, 0 );
931 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
932 count = SendMessageA( win, WM_USER+2, 0, 0 );
933 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
934 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
935 ok( !fmt, "WM_RENDERFORMAT received\n" );
936
937 SetLastError( 0xdeadbeef );
938 r = OpenClipboard( (HWND)0xdead );
939 ok( !r, "OpenClipboard succeeded\n" );
940 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
941
942 r = OpenClipboard(win);
943 ok(r, "OpenClipboard failed: %d\n", GetLastError());
944
945 if (pGetClipboardSequenceNumber)
946 {
947 seq = pGetClipboardSequenceNumber();
948 ok( seq == old_seq, "sequence changed\n" );
949 }
950 if (!cross_thread)
951 {
952 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
953 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
954 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
955 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
956 }
957 count = SendMessageA( win, WM_USER+1, 0, 0 );
958 ok( !count, "WM_DRAWCLIPBOARD received\n" );
959 count = SendMessageA( win, WM_USER+2, 0, 0 );
960 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
961 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
962 ok( !fmt, "WM_RENDERFORMAT received\n" );
963
964 r = EmptyClipboard();
965 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
966
967 if (pGetClipboardSequenceNumber)
968 {
969 seq = pGetClipboardSequenceNumber();
970 ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
971 old_seq = seq;
972 }
973 if (!cross_thread)
974 {
975 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
976 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
977 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
978 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
979 }
980 count = SendMessageA( win, WM_USER+1, 0, 0 );
981 ok( !count, "WM_DRAWCLIPBOARD received\n" );
982 count = SendMessageA( win, WM_USER+2, 0, 0 );
983 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
984 count = SendMessageA( win, WM_USER+3, 0, 0 );
985 ok( !count, "WM_DESTROYCLIPBOARD received\n" );
986 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
987 ok( !fmt, "WM_RENDERFORMAT received\n" );
988
989 r = EmptyClipboard();
990 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
991 /* sequence changes again, even though it was already empty */
992 if (pGetClipboardSequenceNumber)
993 {
994 seq = pGetClipboardSequenceNumber();
995 ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
996 old_seq = seq;
997 }
998 if (!cross_thread)
999 {
1000 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1001 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1002 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1003 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1004 }
1005 count = SendMessageA( win, WM_USER+1, 0, 0 );
1006 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1007 count = SendMessageA( win, WM_USER+2, 0, 0 );
1008 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1009 count = SendMessageA( win, WM_USER+3, 0, 0 );
1010 ok( count, "WM_DESTROYCLIPBOARD not received\n" );
1011 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1012 ok( !fmt, "WM_RENDERFORMAT received\n" );
1013 count = SendMessageA( win, WM_USER+5, 0, 0 );
1014 ok( !count, "wrong format count %u on WM_DESTROYCLIPBOARD\n", count );
1015
1016 handle = SetClipboardData( CF_TEXT, create_textA() );
1017 ok(handle != 0, "SetClipboardData failed: %d\n", GetLastError());
1018
1019 if (pGetClipboardSequenceNumber)
1020 {
1021 seq = pGetClipboardSequenceNumber();
1022 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
1023 old_seq = seq;
1024 }
1025 if (!cross_thread)
1026 {
1027 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1028 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1029 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1030 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1031 }
1032 count = SendMessageA( win, WM_USER+1, 0, 0 );
1033 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1034 count = SendMessageA( win, WM_USER+2, 0, 0 );
1035 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1036 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1037 ok( !fmt, "WM_RENDERFORMAT received\n" );
1038
1039 SetClipboardData( CF_UNICODETEXT, 0 );
1040
1041 if (pGetClipboardSequenceNumber)
1042 {
1043 seq = pGetClipboardSequenceNumber();
1044 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
1045 old_seq = seq;
1046 }
1047 if (!cross_thread)
1048 {
1049 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1050 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1051 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1052 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1053 }
1054 count = SendMessageA( win, WM_USER+1, 0, 0 );
1055 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1056 count = SendMessageA( win, WM_USER+2, 0, 0 );
1057 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1058 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1059 ok( !fmt, "WM_RENDERFORMAT received\n" );
1060
1061 SetClipboardData( CF_UNICODETEXT, 0 ); /* same data again */
1062
1063 if (pGetClipboardSequenceNumber)
1064 {
1065 seq = pGetClipboardSequenceNumber();
1066 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
1067 old_seq = seq;
1068 }
1069 if (!cross_thread)
1070 {
1071 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1072 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1073 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1074 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1075 }
1076 count = SendMessageA( win, WM_USER+1, 0, 0 );
1077 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1078 count = SendMessageA( win, WM_USER+2, 0, 0 );
1079 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1080 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1081 ok( !fmt, "WM_RENDERFORMAT received\n" );
1082
1083 ok( IsClipboardFormatAvailable( CF_TEXT ), "CF_TEXT available\n" );
1084 ok( IsClipboardFormatAvailable( CF_UNICODETEXT ), "CF_UNICODETEXT available\n" );
1085 ok( !IsClipboardFormatAvailable( CF_OEMTEXT ), "CF_OEMTEXT available\n" );
1086
1087 EnterCriticalSection(&clipboard_cs);
1088 r = CloseClipboard();
1089 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1090 LeaveCriticalSection(&clipboard_cs);
1091
1092 if (pGetClipboardSequenceNumber)
1093 {
1094 seq = pGetClipboardSequenceNumber();
1095 ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
1096 old_seq = seq;
1097 }
1098 if (!cross_thread)
1099 {
1100 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1101 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1102 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1103 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1104 }
1105 count = SendMessageA( win, WM_USER+1, 0, 0 );
1106 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1107 count = SendMessageA( win, WM_USER+2, 0, 0 );
1108 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1109 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1110 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1111
1112 r = OpenClipboard(win);
1113 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1114
1115 if (pGetClipboardSequenceNumber)
1116 {
1117 seq = pGetClipboardSequenceNumber();
1118 ok( seq == old_seq, "sequence changed\n" );
1119 }
1120 if (!cross_thread)
1121 {
1122 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1123 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1124 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1125 }
1126 count = SendMessageA( win, WM_USER+1, 0, 0 );
1127 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1128 count = SendMessageA( win, WM_USER+2, 0, 0 );
1129 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1130 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1131 ok( !fmt, "WM_RENDERFORMAT received\n" );
1132
1133 ok( IsClipboardFormatAvailable( CF_TEXT ), "CF_TEXT available\n" );
1134 ok( IsClipboardFormatAvailable( CF_UNICODETEXT ), "CF_UNICODETEXT available\n" );
1135 ok( IsClipboardFormatAvailable( CF_OEMTEXT ), "CF_OEMTEXT available\n" );
1136
1137 ok( GetClipboardOwner() == win, "wrong owner %p\n", GetClipboardOwner());
1138 handle = GetClipboardData( CF_UNICODETEXT );
1139 ok( !handle, "got data for CF_UNICODETEXT\n" );
1140 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1141 ok( fmt == CF_UNICODETEXT, "WM_RENDERFORMAT received %04x\n", fmt );
1142
1143 handle = GetClipboardData( CF_OEMTEXT );
1144 ok( !handle, "got data for CF_OEMTEXT\n" );
1145 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1146 ok( fmt == CF_UNICODETEXT, "WM_RENDERFORMAT received %04x\n", fmt );
1147
1148 SetClipboardData( CF_WAVE, 0 );
1149 if (pGetClipboardSequenceNumber)
1150 {
1151 seq = pGetClipboardSequenceNumber();
1152 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
1153 old_seq = seq;
1154 }
1155 if (!cross_thread)
1156 {
1157 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1158 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1159 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1160 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1161 }
1162 count = SendMessageA( win, WM_USER+1, 0, 0 );
1163 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1164 count = SendMessageA( win, WM_USER+2, 0, 0 );
1165 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1166 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1167 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1168
1169 r = CloseClipboard();
1170 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1171 if (pGetClipboardSequenceNumber)
1172 {
1173 /* no synthesized format, so CloseClipboard doesn't change the sequence */
1174 seq = pGetClipboardSequenceNumber();
1175 todo_wine ok( seq == old_seq, "sequence changed\n" );
1176 old_seq = seq;
1177 }
1178 if (!cross_thread)
1179 {
1180 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1181 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1182 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1183 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1184 }
1185 count = SendMessageA( win, WM_USER+1, 0, 0 );
1186 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1187 count = SendMessageA( win, WM_USER+2, 0, 0 );
1188 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1189 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1190 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1191
1192 r = OpenClipboard(win);
1193 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1194 r = CloseClipboard();
1195 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1196 /* nothing changed */
1197 if (pGetClipboardSequenceNumber)
1198 {
1199 seq = pGetClipboardSequenceNumber();
1200 ok( seq == old_seq, "sequence changed\n" );
1201 }
1202 if (!cross_thread)
1203 {
1204 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1205 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1206 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1207 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1208 }
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 count = SendMessageA( win, WM_USER+3, 0, 0 );
1214 ok( !count, "WM_DESTROYCLIPBOARD received\n" );
1215 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1216 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1217
1218 formats = CountClipboardFormats();
1219 r = OpenClipboard(0);
1220 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1221 r = EmptyClipboard();
1222 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
1223 r = CloseClipboard();
1224 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1225
1226 if (!cross_thread)
1227 {
1228 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1229 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1230 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1231 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1232 }
1233 count = SendMessageA( win, WM_USER+1, 0, 0 );
1234 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1235 count = SendMessageA( win, WM_USER+2, 0, 0 );
1236 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1237 count = SendMessageA( win, WM_USER+3, 0, 0 );
1238 ok( count == 1, "WM_DESTROYCLIPBOARD not received\n" );
1239 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1240 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1241 count = SendMessageA( win, WM_USER+5, 0, 0 );
1242 ok( count == formats, "wrong format count %u on WM_DESTROYCLIPBOARD\n", count );
1243
1244 r = OpenClipboard(win);
1245 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1246 SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_FIXED, 1 ));
1247 if (pGetClipboardSequenceNumber)
1248 {
1249 seq = pGetClipboardSequenceNumber();
1250 ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
1251 old_seq = seq;
1252 }
1253 if (!cross_thread)
1254 {
1255 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1256 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1257 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1258 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1259 }
1260 count = SendMessageA( win, WM_USER+1, 0, 0 );
1261 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1262 count = SendMessageA( win, WM_USER+2, 0, 0 );
1263 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1264 count = SendMessageA( win, WM_USER+3, 0, 0 );
1265 ok( !count, "WM_DESTROYCLIPBOARD received\n" );
1266 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1267 ok( !fmt, "WM_RENDERFORMAT received %04x\n", fmt );
1268
1269 EnterCriticalSection(&clipboard_cs);
1270 r = CloseClipboard();
1271 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1272 LeaveCriticalSection(&clipboard_cs);
1273
1274 if (pGetClipboardSequenceNumber)
1275 {
1276 seq = pGetClipboardSequenceNumber();
1277 todo_wine ok( seq == old_seq, "sequence changed\n" );
1278 old_seq = seq;
1279 }
1280 if (!cross_thread)
1281 {
1282 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1283 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1284 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1285 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1286 }
1287 count = SendMessageA( win, WM_USER+1, 0, 0 );
1288 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1289 count = SendMessageA( win, WM_USER+2, 0, 0 );
1290 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1291 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1292 ok( !fmt, "WM_RENDERFORMAT received\n" );
1293
1294 run_process( "grab_clipboard 0" );
1295
1296 if (pGetClipboardSequenceNumber)
1297 {
1298 seq = pGetClipboardSequenceNumber();
1299 ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
1300 old_seq = seq;
1301 }
1302 if (!cross_thread)
1303 {
1304 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1305 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1306 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1307 /* in this case we get a cross-thread WM_DRAWCLIPBOARD */
1308 cross_thread = TRUE;
1309 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1310 cross_thread = FALSE;
1311 }
1312 count = SendMessageA( win, WM_USER+1, 0, 0 );
1313 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1314 count = SendMessageA( win, WM_USER+2, 0, 0 );
1315 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1316 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1317 ok( !fmt, "WM_RENDERFORMAT received\n" );
1318
1319 r = OpenClipboard(0);
1320 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1321 SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_FIXED, 1 ));
1322 if (pGetClipboardSequenceNumber)
1323 {
1324 seq = pGetClipboardSequenceNumber();
1325 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
1326 old_seq = seq;
1327 }
1328 if (!cross_thread)
1329 {
1330 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1331 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1332 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1333 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1334 }
1335 count = SendMessageA( win, WM_USER+1, 0, 0 );
1336 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1337 count = SendMessageA( win, WM_USER+2, 0, 0 );
1338 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1339 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1340 ok( !fmt, "WM_RENDERFORMAT received\n" );
1341
1342 EnterCriticalSection(&clipboard_cs);
1343 r = CloseClipboard();
1344 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1345 LeaveCriticalSection(&clipboard_cs);
1346
1347 if (pGetClipboardSequenceNumber)
1348 {
1349 seq = pGetClipboardSequenceNumber();
1350 todo_wine ok( seq == old_seq, "sequence changed\n" );
1351 old_seq = seq;
1352 }
1353 if (!cross_thread)
1354 {
1355 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD received\n" );
1356 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1357 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1358 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1359 }
1360 count = SendMessageA( win, WM_USER+1, 0, 0 );
1361 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1362 count = SendMessageA( win, WM_USER+2, 0, 0 );
1363 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1364 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1365 ok( !fmt, "WM_RENDERFORMAT received\n" );
1366
1367 run_process( "grab_clipboard 1" );
1368
1369 if (pGetClipboardSequenceNumber)
1370 {
1371 seq = pGetClipboardSequenceNumber();
1372 ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
1373 old_seq = seq;
1374 }
1375 if (!cross_thread)
1376 {
1377 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1378 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1379 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1380 /* in this case we get a cross-thread WM_DRAWCLIPBOARD */
1381 cross_thread = TRUE;
1382 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1383 cross_thread = FALSE;
1384 }
1385 count = SendMessageA( win, WM_USER+1, 0, 0 );
1386 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1387 count = SendMessageA( win, WM_USER+2, 0, 0 );
1388 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1389 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1390 ok( !fmt, "WM_RENDERFORMAT received\n" );
1391
1392 r = OpenClipboard(0);
1393 ok(r, "OpenClipboard failed: %d\n", GetLastError());
1394 SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_FIXED, 1 ));
1395 if (pGetClipboardSequenceNumber)
1396 {
1397 seq = pGetClipboardSequenceNumber();
1398 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
1399 old_seq = seq;
1400 }
1401 if (!cross_thread)
1402 {
1403 ok( !wm_drawclipboard, "WM_DRAWCLIPBOARD received\n" );
1404 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1405 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1406 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1407 }
1408 count = SendMessageA( win, WM_USER+1, 0, 0 );
1409 ok( !count, "WM_DRAWCLIPBOARD received\n" );
1410 count = SendMessageA( win, WM_USER+2, 0, 0 );
1411 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
1412 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1413 ok( !fmt, "WM_RENDERFORMAT received\n" );
1414
1415 EnterCriticalSection(&clipboard_cs);
1416 r = CloseClipboard();
1417 ok(r, "CloseClipboard failed: %d\n", GetLastError());
1418 LeaveCriticalSection(&clipboard_cs);
1419
1420 if (pGetClipboardSequenceNumber)
1421 {
1422 seq = pGetClipboardSequenceNumber();
1423 todo_wine ok( seq == old_seq, "sequence changed\n" );
1424 old_seq = seq;
1425 }
1426 if (!cross_thread)
1427 {
1428 ok( wm_drawclipboard == 1, "WM_DRAWCLIPBOARD not received\n" );
1429 ok( !wm_clipboardupdate, "WM_CLIPBOARDUPDATE received\n" );
1430 ok( !wm_renderformat, "WM_RENDERFORMAT received\n" );
1431 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
1432 }
1433 count = SendMessageA( win, WM_USER+1, 0, 0 );
1434 ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
1435 count = SendMessageA( win, WM_USER+2, 0, 0 );
1436 ok( count == 1 || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
1437 fmt = SendMessageA( win, WM_USER+4, 0, 0 );
1438 ok( !fmt, "WM_RENDERFORMAT received\n" );
1439
1440 r = PostMessageA(win, WM_USER, 0, 0);
1441 ok(r, "PostMessage failed: %d\n", GetLastError());
1442
1443 if (pRemoveClipboardFormatListener)
1444 {
1445 r = pRemoveClipboardFormatListener(win);
1446 ok( r, "RemoveClipboardFormatListener failed err %d\n", GetLastError());
1447 SetLastError( 0xdeadbeef );
1448 r = pRemoveClipboardFormatListener(win);
1449 ok( !r, "RemoveClipboardFormatListener succeeded\n" );
1450 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
1451 SetLastError( 0xdeadbeef );
1452 r = pRemoveClipboardFormatListener( (HWND)0xdead );
1453 ok( !r, "RemoveClipboardFormatListener succeeded\n" );
1454 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
1455 }
1456 return 0;
1457 }
1458
1459 static void test_messages(void)
1460 {
1461 WNDCLASSA cls;
1462 HWND win;
1463 MSG msg;
1464 HANDLE thread;
1465 DWORD tid;
1466
1467 InitializeCriticalSection(&clipboard_cs);
1468
1469 memset(&cls, 0, sizeof(cls));
1470 cls.lpfnWndProc = clipboard_wnd_proc;
1471 cls.hInstance = GetModuleHandleA(NULL);
1472 cls.lpszClassName = "clipboard_test";
1473 RegisterClassA(&cls);
1474
1475 win = CreateWindowA("clipboard_test", NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0);
1476 ok(win != NULL, "CreateWindow failed: %d\n", GetLastError());
1477
1478 thread = CreateThread(NULL, 0, clipboard_thread, (void*)win, 0, &tid);
1479 ok(thread != NULL, "CreateThread failed: %d\n", GetLastError());
1480
1481 while(GetMessageA(&msg, NULL, 0, 0))
1482 {
1483 ok( msg.message != WM_DRAWCLIPBOARD, "WM_DRAWCLIPBOARD was posted\n" );
1484 TranslateMessage(&msg);
1485 DispatchMessageA(&msg);
1486 }
1487
1488 ok(WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1489 CloseHandle(thread);
1490
1491 DestroyWindow( win );
1492
1493 /* same tests again but inside a single thread */
1494
1495 win = CreateWindowA( "clipboard_test", NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0 );
1496 ok( win != NULL, "CreateWindow failed: %d\n", GetLastError() );
1497
1498 clipboard_thread( win );
1499 DestroyWindow( win );
1500
1501 UnregisterClassA("clipboard_test", GetModuleHandleA(NULL));
1502 DeleteCriticalSection(&clipboard_cs);
1503 }
1504
1505 static BOOL is_moveable( HANDLE handle )
1506 {
1507 void *ptr = GlobalLock( handle );
1508 if (ptr) GlobalUnlock( handle );
1509 return ptr && ptr != handle;
1510 }
1511
1512 static BOOL is_fixed( HANDLE handle )
1513 {
1514 void *ptr = GlobalLock( handle );
1515 if (ptr) GlobalUnlock( handle );
1516 return ptr && ptr == handle;
1517 }
1518
1519 static BOOL is_freed( HANDLE handle )
1520 {
1521 void *ptr = GlobalLock( handle );
1522 if (ptr) GlobalUnlock( handle );
1523 return !ptr;
1524 }
1525
1526 static UINT format_id;
1527 static HBITMAP bitmap, bitmap2;
1528 static HPALETTE palette;
1529 static HPEN pen;
1530 static const LOGPALETTE logpalette = { 0x300, 1 };
1531
1532 static void test_handles( HWND hwnd )
1533 {
1534 HGLOBAL h, htext, htext2;
1535 BOOL r;
1536 HANDLE data;
1537 DWORD process;
1538 BOOL is_owner = (GetWindowThreadProcessId( hwnd, &process ) && process == GetCurrentProcessId());
1539
1540 trace( "hwnd %p\n", hwnd );
1541 htext = create_textA();
1542 htext2 = create_textA();
1543 bitmap = CreateBitmap( 10, 10, 1, 1, NULL );
1544 bitmap2 = CreateBitmap( 10, 10, 1, 1, NULL );
1545 palette = CreatePalette( &logpalette );
1546 pen = CreatePen( PS_SOLID, 1, 0 );
1547
1548 r = OpenClipboard( hwnd );
1549 ok( r, "gle %d\n", GetLastError() );
1550 r = EmptyClipboard();
1551 ok( r, "gle %d\n", GetLastError() );
1552
1553 h = SetClipboardData( CF_TEXT, htext );
1554 ok( h == htext, "got %p\n", h );
1555 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1556 h = SetClipboardData( format_id, htext2 );
1557 ok( h == htext2, "got %p\n", h );
1558 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1559 h = SetClipboardData( CF_BITMAP, bitmap );
1560 ok( h == bitmap, "got %p\n", h );
1561 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1562 h = SetClipboardData( CF_PALETTE, palette );
1563 ok( h == palette, "got %p\n", h );
1564 ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
1565 /* setting custom GDI formats crashes on 64-bit Windows */
1566 if (!is_win64)
1567 {
1568 h = SetClipboardData( CF_GDIOBJFIRST + 1, bitmap2 );
1569 ok( h == bitmap2, "got %p\n", h );
1570 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1571 h = SetClipboardData( CF_GDIOBJFIRST + 2, pen );
1572 ok( h == pen, "got %p\n", h );
1573 ok( GetObjectType( h ) == OBJ_PEN, "expected pen %p\n", h );
1574 }
1575
1576 data = GetClipboardData( CF_TEXT );
1577 ok( data == htext, "wrong data %p\n", data );
1578 ok( is_moveable( data ), "expected moveable mem %p\n", data );
1579
1580 data = GetClipboardData( format_id );
1581 ok( data == htext2, "wrong data %p, cf %08x\n", data, format_id );
1582 ok( is_moveable( data ), "expected moveable mem %p\n", data );
1583
1584 r = CloseClipboard();
1585 ok( r, "gle %d\n", GetLastError() );
1586
1587 /* data handles are still valid */
1588 ok( is_moveable( htext ), "expected moveable mem %p\n", htext );
1589 ok( is_moveable( htext2 ), "expected moveable mem %p\n", htext );
1590 ok( GetObjectType( bitmap ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap );
1591 ok( GetObjectType( bitmap2 ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap2 );
1592 ok( GetObjectType( palette ) == OBJ_PAL, "expected palette %p\n", palette );
1593 ok( GetObjectType( pen ) == OBJ_PEN, "expected pen %p\n", pen );
1594
1595 r = OpenClipboard( hwnd );
1596 ok( r, "gle %d\n", GetLastError() );
1597
1598 /* and now they are freed, unless we are the owner */
1599 if (!is_owner)
1600 {
1601 todo_wine ok( is_freed( htext ), "expected freed mem %p\n", htext );
1602 todo_wine ok( is_freed( htext2 ), "expected freed mem %p\n", htext );
1603
1604 data = GetClipboardData( CF_TEXT );
1605 todo_wine ok( is_fixed( data ), "expected fixed mem %p\n", data );
1606
1607 data = GetClipboardData( format_id );
1608 todo_wine ok( is_fixed( data ), "expected fixed mem %p\n", data );
1609 }
1610 else
1611 {
1612 ok( is_moveable( htext ), "expected moveable mem %p\n", htext );
1613 ok( is_moveable( htext2 ), "expected moveable mem %p\n", htext );
1614
1615 data = GetClipboardData( CF_TEXT );
1616 ok( data == htext, "wrong data %p\n", data );
1617
1618 data = GetClipboardData( format_id );
1619 ok( data == htext2, "wrong data %p, cf %08x\n", data, format_id );
1620 }
1621
1622 data = GetClipboardData( CF_OEMTEXT );
1623 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1624 data = GetClipboardData( CF_UNICODETEXT );
1625 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1626 data = GetClipboardData( CF_BITMAP );
1627 ok( data == bitmap, "expected bitmap %p\n", data );
1628 data = GetClipboardData( CF_PALETTE );
1629 ok( data == palette, "expected palette %p\n", data );
1630 if (!is_win64)
1631 {
1632 data = GetClipboardData( CF_GDIOBJFIRST + 1 );
1633 ok( data == bitmap2, "expected bitmap2 %p\n", data );
1634 data = GetClipboardData( CF_GDIOBJFIRST + 2 );
1635 ok( data == pen, "expected pen %p\n", data );
1636 }
1637 data = GetClipboardData( CF_DIB );
1638 ok( is_fixed( data ), "expected fixed mem %p\n", data );
1639 data = GetClipboardData( CF_DIBV5 );
1640 todo_wine ok( is_fixed( data ), "expected fixed mem %p\n", data );
1641
1642 ok( GetObjectType( bitmap ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap );
1643 ok( GetObjectType( bitmap2 ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap2 );
1644 ok( GetObjectType( palette ) == OBJ_PAL, "expected palette %p\n", palette );
1645 ok( GetObjectType( pen ) == OBJ_PEN, "expected pen %p\n", pen );
1646
1647 r = EmptyClipboard();
1648 ok( r, "gle %d\n", GetLastError() );
1649
1650 /* w2003, w2008 don't seem to free the data here */
1651 ok( is_freed( htext ) || broken( !is_freed( htext )), "expected freed mem %p\n", htext );
1652 ok( is_freed( htext2 ) || broken( !is_freed( htext2 )), "expected freed mem %p\n", htext );
1653 ok( !GetObjectType( bitmap ), "expected freed handle %p\n", bitmap );
1654 ok( !GetObjectType( palette ), "expected freed handle %p\n", palette );
1655 ok( GetObjectType( bitmap2 ) == OBJ_BITMAP, "expected bitmap2 %p\n", bitmap2 );
1656 ok( GetObjectType( pen ) == OBJ_PEN, "expected pen %p\n", pen );
1657
1658 r = CloseClipboard();
1659 ok( r, "gle %d\n", GetLastError() );
1660 }
1661
1662 static DWORD WINAPI test_handles_thread( void *arg )
1663 {
1664 trace( "running from different thread\n" );
1665 test_handles( (HWND)arg );
1666 return 0;
1667 }
1668
1669 static DWORD WINAPI test_handles_thread2( void *arg )
1670 {
1671 BOOL r;
1672 HANDLE h;
1673 char *ptr;
1674
1675 r = OpenClipboard( 0 );
1676 ok( r, "gle %d\n", GetLastError() );
1677 h = GetClipboardData( CF_TEXT );
1678 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1679 ptr = GlobalLock( h );
1680 if (ptr) ok( !strcmp( "test", ptr ), "wrong data '%.5s'\n", ptr );
1681 GlobalUnlock( h );
1682 h = GetClipboardData( format_id );
1683 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1684 ptr = GlobalLock( h );
1685 if (ptr) ok( !strcmp( "test", ptr ), "wrong data '%.5s'\n", ptr );
1686 GlobalUnlock( h );
1687 h = GetClipboardData( CF_BITMAP );
1688 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1689 ok( h == bitmap, "different bitmap %p / %p\n", h, bitmap );
1690 trace( "bitmap %p\n", h );
1691 h = GetClipboardData( CF_PALETTE );
1692 ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
1693 ok( h == palette, "different palette %p / %p\n", h, palette );
1694 trace( "palette %p\n", h );
1695 if (!is_win64)
1696 {
1697 h = GetClipboardData( CF_GDIOBJFIRST + 1 );
1698 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1699 ok( h == bitmap2, "different bitmap %p / %p\n", h, bitmap2 );
1700 trace( "bitmap2 %p\n", h );
1701 h = GetClipboardData( CF_GDIOBJFIRST + 2 );
1702 ok( GetObjectType( h ) == OBJ_PEN, "expected pen %p\n", h );
1703 ok( h == pen, "different pen %p / %p\n", h, pen );
1704 trace( "pen %p\n", h );
1705 }
1706 h = GetClipboardData( CF_DIB );
1707 ok( is_fixed( h ), "expected fixed mem %p\n", h );
1708 h = GetClipboardData( CF_DIBV5 );
1709 todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h );
1710 r = CloseClipboard();
1711 ok( r, "gle %d\n", GetLastError() );
1712 return 0;
1713 }
1714
1715 static void test_handles_process( const char *str )
1716 {
1717 BOOL r;
1718 HANDLE h;
1719 char *ptr;
1720
1721 format_id = RegisterClipboardFormatA( "my_cool_clipboard_format" );
1722 r = OpenClipboard( 0 );
1723 ok( r, "gle %d\n", GetLastError() );
1724 h = GetClipboardData( CF_TEXT );
1725 todo_wine_if( !h ) ok( is_fixed( h ), "expected fixed mem %p\n", h );
1726 ptr = GlobalLock( h );
1727 if (ptr) todo_wine ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr );
1728 GlobalUnlock( h );
1729 h = GetClipboardData( format_id );
1730 todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h );
1731 ptr = GlobalLock( h );
1732 if (ptr) ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr );
1733 GlobalUnlock( h );
1734 h = GetClipboardData( CF_BITMAP );
1735 todo_wine ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1736 trace( "bitmap %p\n", h );
1737 h = GetClipboardData( CF_PALETTE );
1738 todo_wine ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
1739 trace( "palette %p\n", h );
1740 h = GetClipboardData( CF_GDIOBJFIRST + 1 );
1741 ok( !GetObjectType( h ), "expected invalid %p\n", h );
1742 trace( "bitmap2 %p\n", h );
1743 h = GetClipboardData( CF_GDIOBJFIRST + 2 );
1744 ok( !GetObjectType( h ), "expected invalid %p\n", h );
1745 trace( "pen %p\n", h );
1746 h = GetClipboardData( CF_DIB );
1747 todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h );
1748 h = GetClipboardData( CF_DIBV5 );
1749 todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h );
1750 r = CloseClipboard();
1751 ok( r, "gle %d\n", GetLastError() );
1752 }
1753
1754 static void test_data_handles(void)
1755 {
1756 BOOL r;
1757 HANDLE h;
1758 HWND hwnd = CreateWindowA( "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL );
1759
1760 ok( hwnd != 0, "window creation failed\n" );
1761 format_id = RegisterClipboardFormatA( "my_cool_clipboard_format" );
1762 test_handles( 0 );
1763 test_handles( GetDesktopWindow() );
1764 test_handles( hwnd );
1765 run_thread( test_handles_thread, hwnd, __LINE__ );
1766
1767 bitmap = CreateBitmap( 10, 10, 1, 1, NULL );
1768 bitmap2 = CreateBitmap( 10, 10, 1, 1, NULL );
1769 palette = CreatePalette( &logpalette );
1770 pen = CreatePen( PS_SOLID, 1, 0 );
1771
1772 r = OpenClipboard( hwnd );
1773 ok( r, "gle %d\n", GetLastError() );
1774 r = EmptyClipboard();
1775 ok( r, "gle %d\n", GetLastError() );
1776 h = SetClipboardData( CF_TEXT, create_textA() );
1777 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1778 h = SetClipboardData( format_id, create_textA() );
1779 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1780 h = SetClipboardData( CF_BITMAP, bitmap );
1781 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1782 h = SetClipboardData( CF_PALETTE, palette );
1783 ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
1784 if (!is_win64)
1785 {
1786 h = SetClipboardData( CF_GDIOBJFIRST + 1, bitmap2 );
1787 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1788 h = SetClipboardData( CF_GDIOBJFIRST + 2, pen );
1789 ok( GetObjectType( h ) == OBJ_PEN, "expected pen %p\n", h );
1790 }
1791 r = CloseClipboard();
1792 ok( r, "gle %d\n", GetLastError() );
1793
1794 run_thread( test_handles_thread2, 0, __LINE__ );
1795 run_process( "handles test" );
1796
1797 r = OpenClipboard( hwnd );
1798 ok( r, "gle %d\n", GetLastError() );
1799 h = GetClipboardData( CF_TEXT );
1800 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1801 h = GetClipboardData( format_id );
1802 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1803 r = EmptyClipboard();
1804 ok( r, "gle %d\n", GetLastError() );
1805 r = CloseClipboard();
1806 ok( r, "gle %d\n", GetLastError() );
1807
1808 DestroyWindow( hwnd );
1809 }
1810
1811 START_TEST(clipboard)
1812 {
1813 char **argv;
1814 int argc = winetest_get_mainargs( &argv );
1815 HMODULE mod = GetModuleHandleA( "user32" );
1816
1817 argv0 = argv[0];
1818 pAddClipboardFormatListener = (void *)GetProcAddress( mod, "AddClipboardFormatListener" );
1819 pRemoveClipboardFormatListener = (void *)GetProcAddress( mod, "RemoveClipboardFormatListener" );
1820 pGetClipboardSequenceNumber = (void *)GetProcAddress( mod, "GetClipboardSequenceNumber" );
1821
1822 if (argc == 4 && !strcmp( argv[2], "set_clipboard_data" ))
1823 {
1824 set_clipboard_data_process( atoi( argv[3] ));
1825 return;
1826 }
1827 if (argc == 4 && !strcmp( argv[2], "grab_clipboard" ))
1828 {
1829 grab_clipboard_process( atoi( argv[3] ));
1830 return;
1831 }
1832 if (argc == 4 && !strcmp( argv[2], "handles" ))
1833 {
1834 test_handles_process( argv[3] );
1835 return;
1836 }
1837
1838 test_RegisterClipboardFormatA();
1839 test_ClipboardOwner();
1840 test_synthesized();
1841 test_messages();
1842 test_data_handles();
1843 }