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; 2438 } 2439 if (argc == 4 && !strcmp( argv[2], "grab_clipboard" )) 2440 { 2441 grab_clipboard_process( atoi( argv[3] )); 2442 return; 2443 } 2444 if (argc == 4 && !strcmp( argv[2], "handles" )) 2445 { 2446 test_handles_process( argv[3] ); 2447 return; 2448 } 2449 if (argc == 4 && !strcmp( argv[2], "handles_open" )) 2450 { 2451 test_handles_process_open( argv[3] ); 2452 return; 2453 } 2454 if (argc == 4 && !strcmp( argv[2], "handles_dib" )) 2455 { 2456 test_handles_process_dib( argv[3] ); 2457 return; 2458 } 2459 if (argc == 4 && !strcmp( argv[2], "string_data" )) 2460 { 2461 test_string_data_process( atoi( argv[3] )); 2462 return; 2463 } 2464 if (argc == 3 && !strcmp( argv[2], "get_clipboard_data" )) 2465 { 2466 get_clipboard_data_process( ); 2467 return; 2468 } 2469 2470 test_RegisterClipboardFormatA(); 2471 test_ClipboardOwner(); 2472 test_synthesized(); 2473 test_messages(); 2474 test_data_handles(); 2475 test_GetUpdatedClipboardFormats(); 2476 test_string_data(); 2477 } 2478