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