user32/tests: Add some tests for GDI clipboard formats.
[wine.git] / dlls / user32 / tests / clipboard.c
blob2e9cd24debb0b7ba1d5a1cb6e56992fc4054a8a6
1 /*
2 * Unit test suite for clipboard functions.
4 * Copyright 2002 Dmitry Timoshkov
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdio.h>
22 #include "wine/test.h"
23 #include "winbase.h"
24 #include "winerror.h"
25 #include "wingdi.h"
26 #include "winuser.h"
28 static BOOL (WINAPI *pAddClipboardFormatListener)(HWND hwnd);
29 static DWORD (WINAPI *pGetClipboardSequenceNumber)(void);
31 static int thread_from_line;
32 static char *argv0;
34 static DWORD WINAPI open_clipboard_thread(LPVOID arg)
36 HWND hWnd = arg;
37 ok(OpenClipboard(hWnd), "%u: OpenClipboard failed\n", thread_from_line);
38 return 0;
41 static DWORD WINAPI empty_clipboard_thread(LPVOID arg)
43 SetLastError( 0xdeadbeef );
44 ok(!EmptyClipboard(), "%u: EmptyClipboard succeeded\n", thread_from_line );
45 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
46 thread_from_line, GetLastError());
47 return 0;
50 static DWORD WINAPI open_and_empty_clipboard_thread(LPVOID arg)
52 HWND hWnd = arg;
53 ok(OpenClipboard(hWnd), "%u: OpenClipboard failed\n", thread_from_line);
54 ok(EmptyClipboard(), "%u: EmptyClipboard failed\n", thread_from_line );
55 return 0;
58 static DWORD WINAPI set_clipboard_data_thread(LPVOID arg)
60 HWND hwnd = arg;
61 HANDLE ret;
63 SetLastError( 0xdeadbeef );
64 if (GetClipboardOwner() == hwnd)
66 SetClipboardData( CF_WAVE, 0 );
67 todo_wine ok( IsClipboardFormatAvailable( CF_WAVE ), "%u: SetClipboardData failed\n", thread_from_line );
68 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
69 ok( ret != 0, "%u: SetClipboardData failed err %u\n", thread_from_line, GetLastError() );
71 else
73 SetClipboardData( CF_WAVE, 0 );
74 todo_wine ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
75 thread_from_line, GetLastError());
76 ok( !IsClipboardFormatAvailable( CF_WAVE ), "%u: SetClipboardData succeeded\n", thread_from_line );
77 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
78 todo_wine ok( !ret, "%u: SetClipboardData succeeded\n", thread_from_line );
79 todo_wine ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "%u: wrong error %u\n",
80 thread_from_line, GetLastError());
82 return 0;
85 static void set_clipboard_data_process( int arg )
87 HANDLE ret;
89 SetLastError( 0xdeadbeef );
90 if (arg)
92 todo_wine_if( arg == 1 || arg == 3 )
93 ok( IsClipboardFormatAvailable( CF_WAVE ), "process %u: CF_WAVE not available\n", arg );
94 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
95 todo_wine_if( arg == 2 || arg == 4 )
96 ok( ret != 0, "process %u: SetClipboardData failed err %u\n", arg, GetLastError() );
98 else
100 SetClipboardData( CF_WAVE, 0 );
101 todo_wine ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "process %u: wrong error %u\n",
102 arg, GetLastError());
103 todo_wine ok( !IsClipboardFormatAvailable( CF_WAVE ), "process %u: SetClipboardData succeeded\n", arg );
104 ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
105 ok( !ret, "process %u: SetClipboardData succeeded\n", arg );
106 todo_wine ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "process %u: wrong error %u\n",
107 arg, GetLastError());
111 static void run_thread( LPTHREAD_START_ROUTINE func, void *arg, int line )
113 DWORD ret;
114 HANDLE thread;
116 thread_from_line = line;
117 thread = CreateThread(NULL, 0, func, arg, 0, NULL);
118 ok(thread != NULL, "%u: CreateThread failed with error %d\n", line, GetLastError());
119 for (;;)
121 ret = MsgWaitForMultipleObjectsEx( 1, &thread, 1000, QS_ALLINPUT, 0 );
122 if (ret == WAIT_OBJECT_0 + 1)
124 MSG msg;
125 while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
127 else break;
129 ok(ret == WAIT_OBJECT_0, "%u: expected WAIT_OBJECT_0, got %u\n", line, ret);
130 CloseHandle(thread);
133 static void run_process( const char *args )
135 char cmd[MAX_PATH];
136 PROCESS_INFORMATION info;
137 STARTUPINFOA startup;
139 sprintf( cmd, "%s clipboard %s", argv0, args );
140 memset( &startup, 0, sizeof(startup) );
141 startup.cb = sizeof(startup);
142 ok( CreateProcessA( NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info ),
143 "CreateProcess %s failed\n", cmd );
145 winetest_wait_child_process( info.hProcess );
146 CloseHandle( info.hProcess );
147 CloseHandle( info.hThread );
150 static void test_ClipboardOwner(void)
152 HWND hWnd1, hWnd2;
153 BOOL ret;
155 SetLastError(0xdeadbeef);
156 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef,
157 "could not perform clipboard test: clipboard already owned\n");
159 hWnd1 = CreateWindowExA(0, "static", NULL, WS_POPUP,
160 0, 0, 10, 10, 0, 0, 0, NULL);
161 ok(hWnd1 != 0, "CreateWindowExA error %d\n", GetLastError());
162 trace("hWnd1 = %p\n", hWnd1);
164 hWnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP,
165 0, 0, 10, 10, 0, 0, 0, NULL);
166 ok(hWnd2 != 0, "CreateWindowExA error %d\n", GetLastError());
167 trace("hWnd2 = %p\n", hWnd2);
169 SetLastError(0xdeadbeef);
170 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
171 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */
172 "wrong error %u\n", GetLastError());
174 ok(OpenClipboard(0), "OpenClipboard failed\n");
175 ok(!GetClipboardOwner(), "clipboard should still be not owned\n");
176 ok(!OpenClipboard(hWnd1), "OpenClipboard should fail since clipboard already opened\n");
177 ok(OpenClipboard(0), "OpenClipboard again failed\n");
178 ret = CloseClipboard();
179 ok( ret, "CloseClipboard error %d\n", GetLastError());
181 ok(OpenClipboard(hWnd1), "OpenClipboard failed\n");
182 run_thread( open_clipboard_thread, hWnd1, __LINE__ );
183 run_thread( empty_clipboard_thread, 0, __LINE__ );
184 run_thread( set_clipboard_data_thread, hWnd1, __LINE__ );
185 run_process( "set_clipboard_data 0" );
186 ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
187 ok(OpenClipboard(hWnd1), "OpenClipboard failed\n");
189 SetLastError(0xdeadbeef);
190 ret = OpenClipboard(hWnd2);
191 ok(!ret && (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED),
192 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
194 SetLastError(0xdeadbeef);
195 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should still be not owned\n");
196 ret = EmptyClipboard();
197 ok( ret, "EmptyClipboard error %d\n", GetLastError());
198 ok(GetClipboardOwner() == hWnd1, "clipboard should be owned by %p, not by %p\n", hWnd1, GetClipboardOwner());
199 run_thread( empty_clipboard_thread, 0, __LINE__ );
200 run_thread( set_clipboard_data_thread, hWnd1, __LINE__ );
201 run_process( "set_clipboard_data 1" );
203 SetLastError(0xdeadbeef);
204 ret = OpenClipboard(hWnd2);
205 ok(!ret && (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED),
206 "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
208 ret = CloseClipboard();
209 ok( ret, "CloseClipboard error %d\n", GetLastError());
210 ok(GetClipboardOwner() == hWnd1, "clipboard should still be owned\n");
212 /* any window will do, even from a different process */
213 ret = OpenClipboard( GetDesktopWindow() );
214 ok( ret, "OpenClipboard error %d\n", GetLastError());
215 ret = EmptyClipboard();
216 ok( ret, "EmptyClipboard error %d\n", GetLastError());
217 ok( GetClipboardOwner() == GetDesktopWindow(), "wrong owner %p/%p\n",
218 GetClipboardOwner(), GetDesktopWindow() );
219 run_thread( set_clipboard_data_thread, GetDesktopWindow(), __LINE__ );
220 run_process( "set_clipboard_data 2" );
221 ret = CloseClipboard();
222 ok( ret, "CloseClipboard error %d\n", GetLastError());
224 ret = OpenClipboard( hWnd1 );
225 ok( ret, "OpenClipboard error %d\n", GetLastError());
226 ret = EmptyClipboard();
227 ok( ret, "EmptyClipboard error %d\n", GetLastError());
228 ok( GetClipboardOwner() == hWnd1, "wrong owner %p/%p\n", GetClipboardOwner(), hWnd1 );
229 ret = CloseClipboard();
230 ok( ret, "CloseClipboard error %d\n", GetLastError());
232 ret = DestroyWindow(hWnd1);
233 ok( ret, "DestroyWindow error %d\n", GetLastError());
234 ret = DestroyWindow(hWnd2);
235 ok( ret, "DestroyWindow error %d\n", GetLastError());
236 SetLastError(0xdeadbeef);
237 ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should not be owned\n");
239 ret = OpenClipboard( 0 );
240 ok( ret, "OpenClipboard error %d\n", GetLastError());
241 run_thread( set_clipboard_data_thread, 0, __LINE__ );
242 run_process( "set_clipboard_data 3" );
243 ret = CloseClipboard();
244 ok( ret, "CloseClipboard error %d\n", GetLastError());
246 run_thread( open_and_empty_clipboard_thread, 0, __LINE__ );
248 ret = OpenClipboard( 0 );
249 ok( ret, "OpenClipboard error %d\n", GetLastError());
250 run_thread( set_clipboard_data_thread, 0, __LINE__ );
251 run_process( "set_clipboard_data 4" );
252 ret = EmptyClipboard();
253 ok( ret, "EmptyClipboard error %d\n", GetLastError());
254 ret = CloseClipboard();
255 ok( ret, "CloseClipboard error %d\n", GetLastError());
257 SetLastError( 0xdeadbeef );
258 todo_wine ok( !SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 )),
259 "SetClipboardData succeeded\n" );
260 todo_wine ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError() );
261 todo_wine ok( !IsClipboardFormatAvailable( CF_WAVE ), "SetClipboardData succeeded\n" );
265 static void test_RegisterClipboardFormatA(void)
267 ATOM atom_id;
268 UINT format_id, format_id2;
269 char buf[256];
270 int len;
271 BOOL ret;
272 HANDLE handle;
274 format_id = RegisterClipboardFormatA("my_cool_clipboard_format");
275 ok(format_id > 0xc000 && format_id < 0xffff, "invalid clipboard format id %04x\n", format_id);
277 format_id2 = RegisterClipboardFormatA("MY_COOL_CLIPBOARD_FORMAT");
278 ok(format_id2 == format_id, "invalid clipboard format id %04x\n", format_id2);
280 len = GetClipboardFormatNameA(format_id, buf, 256);
281 ok(len == lstrlenA("my_cool_clipboard_format"), "wrong format name length %d\n", len);
282 ok(!lstrcmpA(buf, "my_cool_clipboard_format"), "wrong format name \"%s\"\n", buf);
284 lstrcpyA(buf, "foo");
285 SetLastError(0xdeadbeef);
286 len = GetAtomNameA((ATOM)format_id, buf, 256);
287 ok(len == 0, "GetAtomNameA should fail\n");
288 ok(GetLastError() == ERROR_INVALID_HANDLE, "err %d\n", GetLastError());
290 todo_wine
292 lstrcpyA(buf, "foo");
293 SetLastError(0xdeadbeef);
294 len = GlobalGetAtomNameA((ATOM)format_id, buf, 256);
295 ok(len == 0, "GlobalGetAtomNameA should fail\n");
296 ok(GetLastError() == ERROR_INVALID_HANDLE, "err %d\n", GetLastError());
299 SetLastError(0xdeadbeef);
300 atom_id = FindAtomA("my_cool_clipboard_format");
301 ok(atom_id == 0, "FindAtomA should fail\n");
302 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError());
304 if (0)
306 /* this relies on the clipboard and global atom table being different */
307 SetLastError(0xdeadbeef);
308 atom_id = GlobalFindAtomA("my_cool_clipboard_format");
309 ok(atom_id == 0, "GlobalFindAtomA should fail\n");
310 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError());
313 for (format_id = 0; format_id < 0xffff; format_id++)
315 SetLastError(0xdeadbeef);
316 len = GetClipboardFormatNameA(format_id, buf, 256);
318 if (format_id < 0xc000)
319 ok(!len, "GetClipboardFormatNameA should fail, but it returned %d (%s)\n", len, buf);
320 else if (len && winetest_debug > 1)
321 trace("%04x: %s\n", format_id, len ? buf : "");
324 ret = OpenClipboard(0);
325 ok( ret, "OpenClipboard error %d\n", GetLastError());
327 /* try some invalid/unregistered formats */
328 SetLastError( 0xdeadbeef );
329 handle = SetClipboardData( 0, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
330 ok( !handle, "SetClipboardData succeeded\n" );
331 ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError());
332 handle = SetClipboardData( 0x1234, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
333 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
334 handle = SetClipboardData( 0x123456, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
335 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
336 handle = SetClipboardData( 0xffff8765, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 ));
337 ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError());
339 ok( IsClipboardFormatAvailable( 0x1234 ), "format missing\n" );
340 ok( IsClipboardFormatAvailable( 0x123456 ), "format missing\n" );
341 ok( IsClipboardFormatAvailable( 0xffff8765 ), "format missing\n" );
342 ok( !IsClipboardFormatAvailable( 0 ), "format available\n" );
343 ok( !IsClipboardFormatAvailable( 0x3456 ), "format available\n" );
344 ok( !IsClipboardFormatAvailable( 0x8765 ), "format available\n" );
346 trace("# of formats available: %d\n", CountClipboardFormats());
348 format_id = 0;
349 while ((format_id = EnumClipboardFormats(format_id)))
351 ok(IsClipboardFormatAvailable(format_id), "format %04x was listed as available\n", format_id);
352 len = GetClipboardFormatNameA(format_id, buf, 256);
353 trace("%04x: %s\n", format_id, len ? buf : "");
356 ret = EmptyClipboard();
357 ok( ret, "EmptyClipboard error %d\n", GetLastError());
358 ret =CloseClipboard();
359 ok( ret, "CloseClipboard error %d\n", GetLastError());
361 if (CountClipboardFormats())
363 SetLastError(0xdeadbeef);
364 ok(!EnumClipboardFormats(0), "EnumClipboardFormats should fail if clipboard wasn't open\n");
365 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN,
366 "Last error should be set to ERROR_CLIPBOARD_NOT_OPEN, not %d\n", GetLastError());
369 SetLastError(0xdeadbeef);
370 ok(!EmptyClipboard(), "EmptyClipboard should fail if clipboard wasn't open\n");
371 ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */
372 "Wrong error %u\n", GetLastError());
374 format_id = RegisterClipboardFormatA("#1234");
375 ok(format_id == 1234, "invalid clipboard format id %04x\n", format_id);
378 static HGLOBAL create_text(void)
380 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 5);
381 char *p = GlobalLock(h);
382 strcpy(p, "test");
383 GlobalUnlock(h);
384 return h;
387 static HENHMETAFILE create_emf(void)
389 const RECT rect = {0, 0, 100, 100};
390 HDC hdc = CreateEnhMetaFileA(NULL, NULL, &rect, "HENHMETAFILE Ole Clipboard Test\0Test\0\0");
391 ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
392 return CloseEnhMetaFile(hdc);
395 static void test_synthesized(void)
397 HGLOBAL h, htext;
398 HENHMETAFILE emf;
399 BOOL r;
400 UINT cf;
401 HANDLE data;
403 htext = create_text();
404 emf = create_emf();
406 r = OpenClipboard(NULL);
407 ok(r, "gle %d\n", GetLastError());
408 r = EmptyClipboard();
409 ok(r, "gle %d\n", GetLastError());
410 h = SetClipboardData(CF_TEXT, htext);
411 ok(h == htext, "got %p\n", h);
412 h = SetClipboardData(CF_ENHMETAFILE, emf);
413 ok(h == emf, "got %p\n", h);
414 r = CloseClipboard();
415 ok(r, "gle %d\n", GetLastError());
417 r = OpenClipboard(NULL);
418 ok(r, "gle %d\n", GetLastError());
419 cf = EnumClipboardFormats(0);
420 ok(cf == CF_TEXT, "cf %08x\n", cf);
421 data = GetClipboardData(cf);
422 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
424 cf = EnumClipboardFormats(cf);
425 ok(cf == CF_ENHMETAFILE, "cf %08x\n", cf);
426 data = GetClipboardData(cf);
427 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
429 cf = EnumClipboardFormats(cf);
430 todo_wine ok(cf == CF_LOCALE, "cf %08x\n", cf);
431 if(cf == CF_LOCALE)
432 cf = EnumClipboardFormats(cf);
433 ok(cf == CF_OEMTEXT, "cf %08x\n", cf);
434 data = GetClipboardData(cf);
435 ok(data != NULL, "couldn't get data, cf %08x\n", cf);
437 cf = EnumClipboardFormats(cf);
438 ok(cf == CF_UNICODETEXT, "cf %08x\n", cf);
440 cf = EnumClipboardFormats(cf);
441 ok(cf == CF_METAFILEPICT, "cf %08x\n", cf);
442 data = GetClipboardData(cf);
443 todo_wine ok(data != NULL, "couldn't get data, cf %08x\n", cf);
445 cf = EnumClipboardFormats(cf);
446 ok(cf == 0, "cf %08x\n", cf);
448 r = EmptyClipboard();
449 ok(r, "gle %d\n", GetLastError());
451 r = CloseClipboard();
452 ok(r, "gle %d\n", GetLastError());
455 static CRITICAL_SECTION clipboard_cs;
456 static HWND next_wnd;
457 static LRESULT CALLBACK clipboard_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
459 static UINT wm_drawclipboard;
460 static UINT wm_clipboardupdate;
461 static UINT wm_destroyclipboard;
462 LRESULT ret;
464 switch(msg) {
465 case WM_DRAWCLIPBOARD:
466 EnterCriticalSection(&clipboard_cs);
467 wm_drawclipboard++;
468 LeaveCriticalSection(&clipboard_cs);
469 break;
470 case WM_CHANGECBCHAIN:
471 if (next_wnd == (HWND)wp)
472 next_wnd = (HWND)lp;
473 else if (next_wnd)
474 SendMessageA(next_wnd, msg, wp, lp);
475 break;
476 case WM_DESTROYCLIPBOARD:
477 wm_destroyclipboard++;
478 ok( GetClipboardOwner() == hwnd, "WM_DESTROYCLIPBOARD owner %p\n", GetClipboardOwner() );
479 break;
480 case WM_CLIPBOARDUPDATE:
481 wm_clipboardupdate++;
482 break;
483 case WM_USER:
484 ChangeClipboardChain(hwnd, next_wnd);
485 PostQuitMessage(0);
486 break;
487 case WM_USER+1:
488 ret = wm_drawclipboard;
489 wm_drawclipboard = 0;
490 return ret;
491 case WM_USER+2:
492 ret = wm_clipboardupdate;
493 wm_clipboardupdate = 0;
494 return ret;
495 case WM_USER+3:
496 ret = wm_destroyclipboard;
497 wm_destroyclipboard = 0;
498 return ret;
501 return DefWindowProcA(hwnd, msg, wp, lp);
504 static DWORD WINAPI clipboard_thread(void *param)
506 HWND win = param;
507 BOOL r;
508 HANDLE handle;
509 UINT count, old_seq = 0, seq;
511 if (pGetClipboardSequenceNumber) old_seq = pGetClipboardSequenceNumber();
513 EnterCriticalSection(&clipboard_cs);
514 SetLastError(0xdeadbeef);
515 next_wnd = SetClipboardViewer(win);
516 ok(GetLastError() == 0xdeadbeef, "GetLastError = %d\n", GetLastError());
517 LeaveCriticalSection(&clipboard_cs);
518 if (pAddClipboardFormatListener)
520 r = pAddClipboardFormatListener(win);
521 ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError());
524 if (pGetClipboardSequenceNumber)
526 seq = pGetClipboardSequenceNumber();
527 ok( seq == old_seq, "sequence changed\n" );
529 count = SendMessageA( win, WM_USER + 1, 0, 0 );
530 ok( count, "WM_DRAWCLIPBOARD received\n" );
531 count = SendMessageA( win, WM_USER+2, 0, 0 );
532 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
534 r = OpenClipboard(win);
535 ok(r, "OpenClipboard failed: %d\n", GetLastError());
537 if (pGetClipboardSequenceNumber)
539 seq = pGetClipboardSequenceNumber();
540 ok( seq == old_seq, "sequence changed\n" );
542 count = SendMessageA( win, WM_USER+1, 0, 0 );
543 ok( !count, "WM_DRAWCLIPBOARD received\n" );
544 count = SendMessageA( win, WM_USER+2, 0, 0 );
545 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
547 r = EmptyClipboard();
548 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
550 if (pGetClipboardSequenceNumber)
552 seq = pGetClipboardSequenceNumber();
553 ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
554 old_seq = seq;
556 count = SendMessageA( win, WM_USER+1, 0, 0 );
557 ok( !count, "WM_DRAWCLIPBOARD received\n" );
558 count = SendMessageA( win, WM_USER+2, 0, 0 );
559 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
560 count = SendMessageA( win, WM_USER+3, 0, 0 );
561 ok( !count, "WM_DESTROYCLIPBOARD received\n" );
563 r = EmptyClipboard();
564 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
565 /* sequence changes again, even though it was already empty */
566 if (pGetClipboardSequenceNumber)
568 seq = pGetClipboardSequenceNumber();
569 ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
570 old_seq = seq;
572 count = SendMessageA( win, WM_USER+1, 0, 0 );
573 ok( !count, "WM_DRAWCLIPBOARD received\n" );
574 count = SendMessageA( win, WM_USER+2, 0, 0 );
575 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
576 count = SendMessageA( win, WM_USER+3, 0, 0 );
577 ok( count, "WM_DESTROYCLIPBOARD not received\n" );
579 handle = SetClipboardData( CF_TEXT, create_text() );
580 ok(handle != 0, "SetClipboardData failed: %d\n", GetLastError());
582 if (pGetClipboardSequenceNumber)
584 seq = pGetClipboardSequenceNumber();
585 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
586 old_seq = seq;
588 count = SendMessageA( win, WM_USER+1, 0, 0 );
589 ok( !count, "WM_DRAWCLIPBOARD received\n" );
590 count = SendMessageA( win, WM_USER+2, 0, 0 );
591 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
593 SetClipboardData( CF_UNICODETEXT, 0 );
595 if (pGetClipboardSequenceNumber)
597 seq = pGetClipboardSequenceNumber();
598 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
599 old_seq = seq;
601 count = SendMessageA( win, WM_USER+1, 0, 0 );
602 ok( !count, "WM_DRAWCLIPBOARD received\n" );
603 count = SendMessageA( win, WM_USER+2, 0, 0 );
604 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
606 SetClipboardData( CF_UNICODETEXT, 0 ); /* same data again */
608 if (pGetClipboardSequenceNumber)
610 seq = pGetClipboardSequenceNumber();
611 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
612 old_seq = seq;
614 count = SendMessageA( win, WM_USER+1, 0, 0 );
615 ok( !count, "WM_DRAWCLIPBOARD received\n" );
616 count = SendMessageA( win, WM_USER+2, 0, 0 );
617 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
619 EnterCriticalSection(&clipboard_cs);
620 r = CloseClipboard();
621 ok(r, "CloseClipboard failed: %d\n", GetLastError());
622 LeaveCriticalSection(&clipboard_cs);
624 if (pGetClipboardSequenceNumber)
626 seq = pGetClipboardSequenceNumber();
627 ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
628 old_seq = seq;
630 count = SendMessageA( win, WM_USER+1, 0, 0 );
631 ok( count, "WM_DRAWCLIPBOARD not received\n" );
632 count = SendMessageA( win, WM_USER+2, 0, 0 );
633 todo_wine ok( count || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
635 r = OpenClipboard(win);
636 ok(r, "OpenClipboard failed: %d\n", GetLastError());
638 if (pGetClipboardSequenceNumber)
640 seq = pGetClipboardSequenceNumber();
641 ok( seq == old_seq, "sequence changed\n" );
643 count = SendMessageA( win, WM_USER+1, 0, 0 );
644 ok( !count, "WM_DRAWCLIPBOARD received\n" );
645 count = SendMessageA( win, WM_USER+2, 0, 0 );
646 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
648 SetClipboardData( CF_WAVE, 0 );
649 if (pGetClipboardSequenceNumber)
651 seq = pGetClipboardSequenceNumber();
652 todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
653 old_seq = seq;
655 count = SendMessageA( win, WM_USER+1, 0, 0 );
656 ok( !count, "WM_DRAWCLIPBOARD received\n" );
657 count = SendMessageA( win, WM_USER+2, 0, 0 );
658 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
660 r = CloseClipboard();
661 ok(r, "CloseClipboard failed: %d\n", GetLastError());
662 if (pGetClipboardSequenceNumber)
664 /* no synthesized format, so CloseClipboard doesn't change the sequence */
665 seq = pGetClipboardSequenceNumber();
666 todo_wine ok( seq == old_seq, "sequence changed\n" );
667 old_seq = seq;
669 count = SendMessageA( win, WM_USER+1, 0, 0 );
670 ok( count, "WM_DRAWCLIPBOARD not received\n" );
671 count = SendMessageA( win, WM_USER+2, 0, 0 );
672 todo_wine ok( count || broken(!pAddClipboardFormatListener), "WM_CLIPBOARDUPDATE not received\n" );
674 r = OpenClipboard(win);
675 ok(r, "OpenClipboard failed: %d\n", GetLastError());
676 r = CloseClipboard();
677 ok(r, "CloseClipboard failed: %d\n", GetLastError());
678 /* nothing changed */
679 if (pGetClipboardSequenceNumber)
681 seq = pGetClipboardSequenceNumber();
682 ok( seq == old_seq, "sequence changed\n" );
684 count = SendMessageA( win, WM_USER+1, 0, 0 );
685 ok( !count, "WM_DRAWCLIPBOARD received\n" );
686 count = SendMessageA( win, WM_USER+2, 0, 0 );
687 ok( !count, "WM_CLIPBOARDUPDATE received\n" );
689 r = OpenClipboard(0);
690 ok(r, "OpenClipboard failed: %d\n", GetLastError());
691 r = EmptyClipboard();
692 ok(r, "EmptyClipboard failed: %d\n", GetLastError());
693 r = CloseClipboard();
694 ok(r, "CloseClipboard failed: %d\n", GetLastError());
696 r = PostMessageA(win, WM_USER, 0, 0);
697 ok(r, "PostMessage failed: %d\n", GetLastError());
698 return 0;
701 static void test_messages(void)
703 WNDCLASSA cls;
704 HWND win;
705 MSG msg;
706 HANDLE thread;
707 DWORD tid;
709 InitializeCriticalSection(&clipboard_cs);
711 memset(&cls, 0, sizeof(cls));
712 cls.lpfnWndProc = clipboard_wnd_proc;
713 cls.hInstance = GetModuleHandleA(NULL);
714 cls.lpszClassName = "clipboard_test";
715 RegisterClassA(&cls);
717 win = CreateWindowA("clipboard_test", NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0);
718 ok(win != NULL, "CreateWindow failed: %d\n", GetLastError());
720 thread = CreateThread(NULL, 0, clipboard_thread, (void*)win, 0, &tid);
721 ok(thread != NULL, "CreateThread failed: %d\n", GetLastError());
723 while(GetMessageA(&msg, NULL, 0, 0)) {
724 TranslateMessage(&msg);
725 DispatchMessageA(&msg);
728 ok(WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
729 CloseHandle(thread);
731 UnregisterClassA("clipboard_test", GetModuleHandleA(NULL));
732 DeleteCriticalSection(&clipboard_cs);
735 static BOOL is_moveable( HANDLE handle )
737 void *ptr = GlobalLock( handle );
738 if (ptr) GlobalUnlock( handle );
739 return ptr && ptr != handle;
742 static BOOL is_fixed( HANDLE handle )
744 void *ptr = GlobalLock( handle );
745 if (ptr) GlobalUnlock( handle );
746 return ptr && ptr == handle;
749 static BOOL is_freed( HANDLE handle )
751 void *ptr = GlobalLock( handle );
752 if (ptr) GlobalUnlock( handle );
753 return !ptr;
756 static UINT format_id;
757 static HBITMAP bitmap, bitmap2;
758 static HPALETTE palette;
759 static HPEN pen;
760 static const LOGPALETTE logpalette = { 0x300, 1 };
762 static void test_handles( HWND hwnd )
764 HGLOBAL h, htext, htext2;
765 BOOL r;
766 HANDLE data;
767 DWORD process;
768 BOOL is_owner = (GetWindowThreadProcessId( hwnd, &process ) && process == GetCurrentProcessId());
770 trace( "hwnd %p\n", hwnd );
771 htext = create_text();
772 htext2 = create_text();
773 bitmap = CreateBitmap( 10, 10, 1, 1, NULL );
774 bitmap2 = CreateBitmap( 10, 10, 1, 1, NULL );
775 palette = CreatePalette( &logpalette );
776 pen = CreatePen( PS_SOLID, 1, 0 );
778 r = OpenClipboard( hwnd );
779 ok( r, "gle %d\n", GetLastError() );
780 r = EmptyClipboard();
781 ok( r, "gle %d\n", GetLastError() );
783 h = SetClipboardData( CF_TEXT, htext );
784 ok( h == htext, "got %p\n", h );
785 ok( is_moveable( h ), "expected moveable mem %p\n", h );
786 h = SetClipboardData( format_id, htext2 );
787 ok( h == htext2, "got %p\n", h );
788 ok( is_moveable( h ), "expected moveable mem %p\n", h );
789 h = SetClipboardData( CF_BITMAP, bitmap );
790 ok( h == bitmap, "got %p\n", h );
791 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
792 h = SetClipboardData( CF_PALETTE, palette );
793 ok( h == palette, "got %p\n", h );
794 ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
795 h = SetClipboardData( CF_GDIOBJFIRST + 1, bitmap2 );
796 ok( h == bitmap2, "got %p\n", h );
797 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
798 h = SetClipboardData( CF_GDIOBJFIRST + 2, pen );
799 ok( h == pen, "got %p\n", h );
800 ok( GetObjectType( h ) == OBJ_PEN, "expected pen %p\n", h );
802 data = GetClipboardData( CF_TEXT );
803 ok( data == htext, "wrong data %p\n", data );
804 ok( is_moveable( data ), "expected moveable mem %p\n", data );
806 data = GetClipboardData( format_id );
807 ok( data == htext2, "wrong data %p, cf %08x\n", data, format_id );
808 ok( is_moveable( data ), "expected moveable mem %p\n", data );
810 r = CloseClipboard();
811 ok( r, "gle %d\n", GetLastError() );
813 /* data handles are still valid */
814 ok( is_moveable( htext ), "expected moveable mem %p\n", htext );
815 ok( is_moveable( htext2 ), "expected moveable mem %p\n", htext );
816 ok( GetObjectType( bitmap ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap );
817 ok( GetObjectType( bitmap2 ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap2 );
818 ok( GetObjectType( palette ) == OBJ_PAL, "expected palette %p\n", palette );
819 ok( GetObjectType( pen ) == OBJ_PEN, "expected pen %p\n", pen );
821 r = OpenClipboard( hwnd );
822 ok( r, "gle %d\n", GetLastError() );
824 /* and now they are freed, unless we are the owner */
825 if (!is_owner)
827 todo_wine ok( is_freed( htext ), "expected freed mem %p\n", htext );
828 todo_wine ok( is_freed( htext2 ), "expected freed mem %p\n", htext );
830 data = GetClipboardData( CF_TEXT );
831 todo_wine ok( is_fixed( data ), "expected fixed mem %p\n", data );
833 data = GetClipboardData( format_id );
834 todo_wine ok( is_fixed( data ), "expected fixed mem %p\n", data );
836 else
838 ok( is_moveable( htext ), "expected moveable mem %p\n", htext );
839 ok( is_moveable( htext2 ), "expected moveable mem %p\n", htext );
841 data = GetClipboardData( CF_TEXT );
842 ok( data == htext, "wrong data %p\n", data );
844 data = GetClipboardData( format_id );
845 ok( data == htext2, "wrong data %p, cf %08x\n", data, format_id );
848 data = GetClipboardData( CF_OEMTEXT );
849 todo_wine ok( is_fixed( data ), "expected fixed mem %p\n", data );
850 data = GetClipboardData( CF_UNICODETEXT );
851 todo_wine ok( is_fixed( data ), "expected fixed mem %p\n", data );
852 data = GetClipboardData( CF_BITMAP );
853 ok( data == bitmap, "expected bitmap %p\n", data );
854 data = GetClipboardData( CF_PALETTE );
855 ok( data == palette, "expected palette %p\n", data );
856 data = GetClipboardData( CF_GDIOBJFIRST + 1 );
857 ok( data == bitmap2, "expected bitmap2 %p\n", data );
858 data = GetClipboardData( CF_GDIOBJFIRST + 2 );
859 ok( data == pen, "expected pen %p\n", data );
860 data = GetClipboardData( CF_DIB );
861 todo_wine ok( is_fixed( data ), "expected fixed mem %p\n", data );
862 data = GetClipboardData( CF_DIBV5 );
863 todo_wine ok( is_fixed( data ), "expected fixed mem %p\n", data );
865 ok( GetObjectType( bitmap ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap );
866 ok( GetObjectType( bitmap2 ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap2 );
867 ok( GetObjectType( palette ) == OBJ_PAL, "expected palette %p\n", palette );
868 ok( GetObjectType( pen ) == OBJ_PEN, "expected pen %p\n", pen );
870 r = EmptyClipboard();
871 ok( r, "gle %d\n", GetLastError() );
873 /* w2003, w2008 don't seem to free the data here */
874 ok( is_freed( htext ) || broken( !is_freed( htext )), "expected freed mem %p\n", htext );
875 ok( is_freed( htext2 ) || broken( !is_freed( htext2 )), "expected freed mem %p\n", htext );
876 ok( !GetObjectType( bitmap ), "expected freed handle %p\n", bitmap );
877 ok( !GetObjectType( palette ), "expected freed handle %p\n", palette );
878 ok( GetObjectType( bitmap2 ) == OBJ_BITMAP, "expected bitmap2 %p\n", bitmap2 );
879 ok( GetObjectType( pen ) == OBJ_PEN, "expected pen %p\n", pen );
881 r = CloseClipboard();
882 ok( r, "gle %d\n", GetLastError() );
885 static DWORD WINAPI test_handles_thread( void *arg )
887 trace( "running from different thread\n" );
888 test_handles( (HWND)arg );
889 return 0;
892 static DWORD WINAPI test_handles_thread2( void *arg )
894 BOOL r;
895 HANDLE h;
896 char *ptr;
898 r = OpenClipboard( 0 );
899 ok( r, "gle %d\n", GetLastError() );
900 h = GetClipboardData( CF_TEXT );
901 ok( is_moveable( h ), "expected moveable mem %p\n", h );
902 ptr = GlobalLock( h );
903 if (ptr) ok( !strcmp( "test", ptr ), "wrong data '%.5s'\n", ptr );
904 GlobalUnlock( h );
905 h = GetClipboardData( format_id );
906 ok( is_moveable( h ), "expected moveable mem %p\n", h );
907 ptr = GlobalLock( h );
908 if (ptr) ok( !strcmp( "test", ptr ), "wrong data '%.5s'\n", ptr );
909 GlobalUnlock( h );
910 h = GetClipboardData( CF_BITMAP );
911 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
912 ok( h == bitmap, "different bitmap %p / %p\n", h, bitmap );
913 trace( "bitmap %p\n", h );
914 h = GetClipboardData( CF_PALETTE );
915 ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
916 ok( h == palette, "different palette %p / %p\n", h, palette );
917 trace( "palette %p\n", h );
918 h = GetClipboardData( CF_GDIOBJFIRST + 1 );
919 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
920 ok( h == bitmap2, "different bitmap %p / %p\n", h, bitmap2 );
921 trace( "bitmap2 %p\n", h );
922 h = GetClipboardData( CF_GDIOBJFIRST + 2 );
923 ok( GetObjectType( h ) == OBJ_PEN, "expected pen %p\n", h );
924 ok( h == pen, "different pen %p / %p\n", h, pen );
925 trace( "pen %p\n", h );
926 h = GetClipboardData( CF_DIB );
927 todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h );
928 h = GetClipboardData( CF_DIBV5 );
929 todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h );
930 r = CloseClipboard();
931 ok( r, "gle %d\n", GetLastError() );
932 return 0;
935 static void test_handles_process( const char *str )
937 BOOL r;
938 HANDLE h;
939 char *ptr;
941 format_id = RegisterClipboardFormatA( "my_cool_clipboard_format" );
942 r = OpenClipboard( 0 );
943 ok( r, "gle %d\n", GetLastError() );
944 h = GetClipboardData( CF_TEXT );
945 todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h );
946 ptr = GlobalLock( h );
947 if (ptr) todo_wine ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr );
948 GlobalUnlock( h );
949 h = GetClipboardData( format_id );
950 todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h );
951 ptr = GlobalLock( h );
952 if (ptr) ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr );
953 GlobalUnlock( h );
954 h = GetClipboardData( CF_BITMAP );
955 todo_wine ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
956 trace( "bitmap %p\n", h );
957 h = GetClipboardData( CF_PALETTE );
958 todo_wine ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
959 trace( "palette %p\n", h );
960 h = GetClipboardData( CF_GDIOBJFIRST + 1 );
961 ok( !GetObjectType( h ), "expected invalid %p\n", h );
962 trace( "bitmap2 %p\n", h );
963 h = GetClipboardData( CF_GDIOBJFIRST + 2 );
964 ok( !GetObjectType( h ), "expected invalid %p\n", h );
965 trace( "pen %p\n", h );
966 h = GetClipboardData( CF_DIB );
967 todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h );
968 h = GetClipboardData( CF_DIBV5 );
969 todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h );
970 r = CloseClipboard();
971 ok( r, "gle %d\n", GetLastError() );
974 static void test_data_handles(void)
976 BOOL r;
977 HANDLE h;
978 HWND hwnd = CreateWindowA( "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL );
980 ok( hwnd != 0, "window creation failed\n" );
981 format_id = RegisterClipboardFormatA( "my_cool_clipboard_format" );
982 test_handles( 0 );
983 test_handles( GetDesktopWindow() );
984 test_handles( hwnd );
985 run_thread( test_handles_thread, hwnd, __LINE__ );
987 bitmap = CreateBitmap( 10, 10, 1, 1, NULL );
988 bitmap2 = CreateBitmap( 10, 10, 1, 1, NULL );
989 palette = CreatePalette( &logpalette );
990 pen = CreatePen( PS_SOLID, 1, 0 );
992 r = OpenClipboard( hwnd );
993 ok( r, "gle %d\n", GetLastError() );
994 r = EmptyClipboard();
995 ok( r, "gle %d\n", GetLastError() );
996 h = SetClipboardData( CF_TEXT, create_text() );
997 ok( is_moveable( h ), "expected moveable mem %p\n", h );
998 h = SetClipboardData( format_id, create_text() );
999 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1000 h = SetClipboardData( CF_BITMAP, bitmap );
1001 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1002 h = SetClipboardData( CF_PALETTE, palette );
1003 ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h );
1004 h = SetClipboardData( CF_GDIOBJFIRST + 1, bitmap2 );
1005 ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h );
1006 h = SetClipboardData( CF_GDIOBJFIRST + 2, pen );
1007 ok( GetObjectType( h ) == OBJ_PEN, "expected pen %p\n", h );
1008 r = CloseClipboard();
1009 ok( r, "gle %d\n", GetLastError() );
1011 run_thread( test_handles_thread2, 0, __LINE__ );
1012 run_process( "handles test" );
1014 r = OpenClipboard( hwnd );
1015 ok( r, "gle %d\n", GetLastError() );
1016 h = GetClipboardData( CF_TEXT );
1017 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1018 h = GetClipboardData( format_id );
1019 ok( is_moveable( h ), "expected moveable mem %p\n", h );
1020 r = EmptyClipboard();
1021 ok( r, "gle %d\n", GetLastError() );
1022 r = CloseClipboard();
1023 ok( r, "gle %d\n", GetLastError() );
1025 DestroyWindow( hwnd );
1028 START_TEST(clipboard)
1030 char **argv;
1031 int argc = winetest_get_mainargs( &argv );
1032 HMODULE mod = GetModuleHandleA( "user32" );
1034 argv0 = argv[0];
1035 pAddClipboardFormatListener = (void *)GetProcAddress( mod, "AddClipboardFormatListener" );
1036 pGetClipboardSequenceNumber = (void *)GetProcAddress( mod, "GetClipboardSequenceNumber" );
1038 if (argc == 4 && !strcmp( argv[2], "set_clipboard_data" ))
1040 set_clipboard_data_process( atoi( argv[3] ));
1041 return;
1043 if (argc == 4 && !strcmp( argv[2], "handles" ))
1045 test_handles_process( argv[3] );
1046 return;
1049 test_RegisterClipboardFormatA();
1050 test_ClipboardOwner();
1051 test_synthesized();
1052 test_messages();
1053 test_data_handles();