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