Index: modules/rostests/winetests/user32/clipboard.c =================================================================== --- modules/rostests/winetests/user32/clipboard.c (revision 73312) +++ modules/rostests/winetests/user32/clipboard.c (working copy) @@ -31,8 +31,8 @@ static BOOL (WINAPI *pAddClipboardFormatListener)(HWND hwnd); static BOOL (WINAPI *pRemoveClipboardFormatListener)(HWND hwnd); static DWORD (WINAPI *pGetClipboardSequenceNumber)(void); +static BOOL (WINAPI *pGetUpdatedClipboardFormats)( UINT *formats, UINT count, UINT *out_count ); -static const BOOL is_win64 = sizeof(void *) > sizeof(int); static int thread_from_line; static char *argv0; @@ -107,7 +107,6 @@ SetLastError( 0xdeadbeef ); if (arg) { - todo_wine_if( arg == 1 || arg == 3 ) ok( IsClipboardFormatAvailable( CF_WAVE ), "process %u: CF_WAVE not available\n", arg ); ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 )); ok( ret != 0, "process %u: SetClipboardData failed err %u\n", arg, GetLastError() ); @@ -209,7 +208,7 @@ { case WM_DESTROY: ok( wm_renderallformats, "didn't receive WM_RENDERALLFORMATS before WM_DESTROY\n" ); - todo_wine ok( wm_drawclipboard, "didn't receive WM_DRAWCLIPBOARD before WM_DESTROY\n" ); + ok( wm_drawclipboard, "didn't receive WM_DRAWCLIPBOARD before WM_DESTROY\n" ); break; case WM_DRAWCLIPBOARD: ok( msg_flags == ISMEX_NOSEND, "WM_DRAWCLIPBOARD wrong flags %x\n", msg_flags ); @@ -323,7 +322,7 @@ ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should not be owned\n"); ok(!GetClipboardViewer() && GetLastError() == 0xdeadbeef, "viewer still exists\n"); ok(!GetOpenClipboardWindow() && GetLastError() == 0xdeadbeef, "clipboard should not be open\n"); - todo_wine ok( !IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE available\n" ); + ok( !IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE available\n" ); SetLastError( 0xdeadbeef ); ret = CloseClipboard(); @@ -418,12 +417,12 @@ ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError()); } - for (format_id = 0; format_id < 0xffff; format_id++) + for (format_id = 0; format_id < 0x10fff; format_id++) { SetLastError(0xdeadbeef); len = GetClipboardFormatNameA(format_id, buf, 256); - if (format_id < 0xc000) + if (format_id < 0xc000 || format_id > 0xffff) ok(!len, "GetClipboardFormatNameA should fail, but it returned %d (%s)\n", len, buf); else if (len && winetest_debug > 1) trace("%04x: %s\n", format_id, len ? buf : ""); @@ -562,6 +561,24 @@ return ret; } +static LRESULT CALLBACK renderer_winproc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) +{ + static UINT rendered; + UINT ret; + + switch (msg) + { + case WM_RENDERFORMAT: + if (wp < 32) rendered |= (1 << wp); + break; + case WM_USER: + ret = rendered; + rendered = 0; + return ret; + } + return DefWindowProcA( hwnd, msg, wp, lp ); +} + static void test_synthesized(void) { static const struct test @@ -568,25 +585,28 @@ { UINT format; UINT expected[8]; - UINT todo; } tests[] = { -/* 0 */ { CF_TEXT, { CF_TEXT, CF_LOCALE, CF_OEMTEXT, CF_UNICODETEXT }, 1 << 1 }, - { CF_OEMTEXT, { CF_OEMTEXT, CF_LOCALE, CF_TEXT, CF_UNICODETEXT }, 1 << 1 }, - { CF_UNICODETEXT, { CF_UNICODETEXT, CF_LOCALE, CF_TEXT, CF_OEMTEXT }, 1 << 1 }, +/* 0 */ { CF_TEXT, { CF_TEXT, CF_LOCALE, CF_OEMTEXT, CF_UNICODETEXT }}, + { CF_OEMTEXT, { CF_OEMTEXT, CF_LOCALE, CF_TEXT, CF_UNICODETEXT }}, + { CF_UNICODETEXT, { CF_UNICODETEXT, CF_LOCALE, CF_TEXT, CF_OEMTEXT }}, { CF_ENHMETAFILE, { CF_ENHMETAFILE, CF_METAFILEPICT }}, { CF_METAFILEPICT, { CF_METAFILEPICT, CF_ENHMETAFILE }}, -/* 5 */ { CF_BITMAP, { CF_BITMAP, CF_DIB, CF_DIBV5 }, 1 << 2 }, - { CF_DIB, { CF_DIB, CF_BITMAP, CF_DIBV5 }, 1 << 2 }, - { CF_DIBV5, { CF_DIBV5, CF_BITMAP, CF_DIB }, (1 << 1) | (1 << 2) }, +/* 5 */ { CF_BITMAP, { CF_BITMAP, CF_DIB, CF_DIBV5 }}, + { CF_DIB, { CF_DIB, CF_BITMAP, CF_DIBV5 }}, + { CF_DIBV5, { CF_DIBV5, CF_BITMAP, CF_DIB }}, }; HGLOBAL h, htext; HENHMETAFILE emf; BOOL r; - UINT cf, i, j, count; + UINT cf, i, j, count, rendered; HANDLE data; + HWND hwnd; + hwnd = CreateWindowA( "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL ); + SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)renderer_winproc ); + htext = create_textA(); emf = create_emf(); @@ -602,11 +622,11 @@ ok(r, "gle %d\n", GetLastError()); count = CountClipboardFormats(); - todo_wine ok( count == 6, "count %u\n", count ); + ok( count == 6, "count %u\n", count ); r = IsClipboardFormatAvailable( CF_TEXT ); ok( r, "CF_TEXT not available err %d\n", GetLastError()); r = IsClipboardFormatAvailable( CF_LOCALE ); - todo_wine ok( r, "CF_LOCALE not available err %d\n", GetLastError()); + ok( r, "CF_LOCALE not available err %d\n", GetLastError()); r = IsClipboardFormatAvailable( CF_OEMTEXT ); ok( r, "CF_OEMTEXT not available err %d\n", GetLastError()); r = IsClipboardFormatAvailable( CF_UNICODETEXT ); @@ -629,13 +649,11 @@ ok(data != NULL, "couldn't get data, cf %08x\n", cf); cf = EnumClipboardFormats(cf); - todo_wine ok(cf == CF_LOCALE, "cf %08x\n", cf); - if(cf == CF_LOCALE) - { - data = GetClipboardData(cf); - ok(data != NULL, "couldn't get data, cf %08x\n", cf); - cf = EnumClipboardFormats(cf); - } + ok(cf == CF_LOCALE, "cf %08x\n", cf); + data = GetClipboardData(cf); + ok(data != NULL, "couldn't get data, cf %08x\n", cf); + + cf = EnumClipboardFormats(cf); ok(cf == CF_OEMTEXT, "cf %08x\n", cf); data = GetClipboardData(cf); ok(data != NULL, "couldn't get data, cf %08x\n", cf); @@ -646,7 +664,7 @@ cf = EnumClipboardFormats(cf); ok(cf == CF_METAFILEPICT, "cf %08x\n", cf); data = GetClipboardData(cf); - todo_wine ok(data != NULL, "couldn't get data, cf %08x\n", cf); + ok(data != NULL, "couldn't get data, cf %08x\n", cf); cf = EnumClipboardFormats(cf); ok(cf == 0, "cf %08x\n", cf); @@ -654,9 +672,45 @@ r = EmptyClipboard(); ok(r, "gle %d\n", GetLastError()); + SetClipboardData( CF_UNICODETEXT, create_textW() ); + SetClipboardData( CF_TEXT, create_textA() ); + SetClipboardData( CF_OEMTEXT, create_textA() ); r = CloseClipboard(); ok(r, "gle %d\n", GetLastError()); + r = OpenClipboard( NULL ); + ok(r, "gle %d\n", GetLastError()); + SetLastError( 0xdeadbeef ); + cf = EnumClipboardFormats(0); + ok( cf == CF_UNICODETEXT, "cf %08x\n", cf ); + ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + cf = EnumClipboardFormats(cf); + ok( cf == CF_TEXT, "cf %08x\n", cf ); + ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + cf = EnumClipboardFormats(cf); + ok( cf == CF_OEMTEXT, "cf %08x\n", cf ); + ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + cf = EnumClipboardFormats(cf); + ok( cf == CF_LOCALE, "cf %08x\n", cf ); + ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + cf = EnumClipboardFormats( cf ); + ok( cf == 0, "cf %08x\n", cf ); + ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + cf = EnumClipboardFormats( 0xdead ); + ok( cf == 0, "cf %08x\n", cf ); + ok( GetLastError() == ERROR_SUCCESS, "wrong error %u\n", GetLastError() ); + + r = EmptyClipboard(); + ok(r, "gle %d\n", GetLastError()); + + r = CloseClipboard(); + ok(r, "gle %d\n", GetLastError()); + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { r = OpenClipboard(NULL); @@ -698,24 +752,20 @@ for (j = 0; tests[i].expected[j]; j++) { r = IsClipboardFormatAvailable( tests[i].expected[j] ); - todo_wine_if (tests[i].todo & (1 << j)) ok( r, "%u: %04x not available\n", i, tests[i].expected[j] ); } - todo_wine_if (tests[i].todo) ok( count == j, "%u: count %u instead of %u\n", i, count, j ); - r = OpenClipboard(NULL); + r = OpenClipboard( hwnd ); ok(r, "%u: gle %d\n", i, GetLastError()); cf = 0; for (j = 0; tests[i].expected[j]; j++) { cf = EnumClipboardFormats( cf ); - todo_wine_if (tests[i].todo & (1 << j)) ok(cf == tests[i].expected[j], "%u.%u: got %04x instead of %04x\n", i, j, cf, tests[i].expected[j] ); if (cf != tests[i].expected[j]) break; data = GetClipboardData( cf ); - todo_wine_if (j && cf == CF_METAFILEPICT) ok(data != NULL || broken( tests[i].format == CF_DIBV5 && cf == CF_DIB ), /* >= Vista */ "%u: couldn't get data, cf %04x err %d\n", i, cf, GetLastError()); @@ -740,7 +790,12 @@ r = EmptyClipboard(); ok(r, "%u: gle %d\n", i, GetLastError()); + rendered = SendMessageA( hwnd, WM_USER, 0, 0 ); + ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered ); + SetClipboardData( tests[i].format, 0 ); + rendered = SendMessageA( hwnd, WM_USER, 0, 0 ); + ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered ); count = CountClipboardFormats(); ok( count == 1, "%u: count %u\n", i, count ); @@ -747,16 +802,18 @@ r = CloseClipboard(); ok(r, "%u: gle %d\n", i, GetLastError()); + rendered = SendMessageA( hwnd, WM_USER, 0, 0 ); + ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered ); count = CountClipboardFormats(); for (j = 0; tests[i].expected[j]; j++) { r = IsClipboardFormatAvailable( tests[i].expected[j] ); - todo_wine_if (tests[i].todo & (1 << j)) ok( r, "%u: %04x not available\n", i, tests[i].expected[j] ); } - todo_wine_if (tests[i].todo) ok( count == j, "%u: count %u instead of %u\n", i, count, j ); + rendered = SendMessageA( hwnd, WM_USER, 0, 0 ); + ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered ); r = OpenClipboard(NULL); ok(r, "%u: gle %d\n", i, GetLastError()); @@ -764,15 +821,29 @@ for (j = 0; tests[i].expected[j]; j++) { cf = EnumClipboardFormats( cf ); - todo_wine_if (tests[i].todo & (1 << j)) ok(cf == tests[i].expected[j], "%u.%u: got %04x instead of %04x\n", i, j, cf, tests[i].expected[j] ); if (cf != tests[i].expected[j]) break; + rendered = SendMessageA( hwnd, WM_USER, 0, 0 ); + ok( !rendered, "%u.%u: formats %08x have been rendered\n", i, j, rendered ); data = GetClipboardData( cf ); + rendered = SendMessageA( hwnd, WM_USER, 0, 0 ); if (cf == CF_LOCALE) + { ok(data != NULL, "%u: CF_LOCALE no data\n", i); + ok( !rendered, "%u.%u: formats %08x have been rendered\n", i, j, rendered ); + } else + { ok(!data, "%u: format %04x got data %p\n", i, cf, data); + ok( rendered == (1 << tests[i].format), + "%u.%u: formats %08x have been rendered\n", i, j, rendered ); + /* try to render a second time */ + data = GetClipboardData( cf ); + rendered = SendMessageA( hwnd, WM_USER, 0, 0 ); + ok( rendered == (1 << tests[i].format), + "%u.%u: formats %08x have been rendered\n", i, j, rendered ); + } } if (!tests[i].expected[j]) { @@ -781,6 +852,8 @@ } r = CloseClipboard(); ok(r, "%u: gle %d\n", i, GetLastError()); + rendered = SendMessageA( hwnd, WM_USER, 0, 0 ); + ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered ); } r = OpenClipboard(NULL); @@ -789,6 +862,7 @@ ok(r, "gle %d\n", GetLastError()); r = CloseClipboard(); ok(r, "gle %d\n", GetLastError()); + DestroyWindow( hwnd ); } static CRITICAL_SECTION clipboard_cs; @@ -967,7 +1041,7 @@ if (pGetClipboardSequenceNumber) { seq = pGetClipboardSequenceNumber(); - ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" ); + ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq ); old_seq = seq; } if (!cross_thread) @@ -992,7 +1066,7 @@ if (pGetClipboardSequenceNumber) { seq = pGetClipboardSequenceNumber(); - ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" ); + ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq ); old_seq = seq; } if (!cross_thread) @@ -1019,7 +1093,7 @@ if (pGetClipboardSequenceNumber) { seq = pGetClipboardSequenceNumber(); - todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" ); + ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq ); old_seq = seq; } if (!cross_thread) @@ -1041,7 +1115,7 @@ if (pGetClipboardSequenceNumber) { seq = pGetClipboardSequenceNumber(); - todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" ); + ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq ); old_seq = seq; } if (!cross_thread) @@ -1063,7 +1137,7 @@ if (pGetClipboardSequenceNumber) { seq = pGetClipboardSequenceNumber(); - todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" ); + ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq ); old_seq = seq; } if (!cross_thread) @@ -1092,7 +1166,7 @@ if (pGetClipboardSequenceNumber) { seq = pGetClipboardSequenceNumber(); - ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" ); + ok( (int)(seq - old_seq) == 2, "sequence diff %d\n", seq - old_seq ); old_seq = seq; } if (!cross_thread) @@ -1149,7 +1223,7 @@ if (pGetClipboardSequenceNumber) { seq = pGetClipboardSequenceNumber(); - todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" ); + ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq ); old_seq = seq; } if (!cross_thread) @@ -1172,7 +1246,7 @@ { /* no synthesized format, so CloseClipboard doesn't change the sequence */ seq = pGetClipboardSequenceNumber(); - todo_wine ok( seq == old_seq, "sequence changed\n" ); + ok( seq == old_seq, "sequence changed\n" ); old_seq = seq; } if (!cross_thread) @@ -1247,7 +1321,7 @@ if (pGetClipboardSequenceNumber) { seq = pGetClipboardSequenceNumber(); - ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" ); + ok( (int)(seq - old_seq) == 2, "sequence diff %d\n", seq - old_seq ); old_seq = seq; } if (!cross_thread) @@ -1274,7 +1348,7 @@ if (pGetClipboardSequenceNumber) { seq = pGetClipboardSequenceNumber(); - todo_wine ok( seq == old_seq, "sequence changed\n" ); + ok( seq == old_seq, "sequence changed\n" ); old_seq = seq; } if (!cross_thread) @@ -1296,7 +1370,7 @@ if (pGetClipboardSequenceNumber) { seq = pGetClipboardSequenceNumber(); - ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" ); + ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq ); old_seq = seq; } if (!cross_thread) @@ -1322,7 +1396,7 @@ if (pGetClipboardSequenceNumber) { seq = pGetClipboardSequenceNumber(); - todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" ); + ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq ); old_seq = seq; } if (!cross_thread) @@ -1347,7 +1421,7 @@ if (pGetClipboardSequenceNumber) { seq = pGetClipboardSequenceNumber(); - todo_wine ok( seq == old_seq, "sequence changed\n" ); + ok( seq == old_seq, "sequence changed\n" ); old_seq = seq; } if (!cross_thread) @@ -1369,7 +1443,7 @@ if (pGetClipboardSequenceNumber) { seq = pGetClipboardSequenceNumber(); - ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" ); + ok( (int)(seq - old_seq) == 2, "sequence diff %d\n", seq - old_seq ); old_seq = seq; } if (!cross_thread) @@ -1395,7 +1469,7 @@ if (pGetClipboardSequenceNumber) { seq = pGetClipboardSequenceNumber(); - todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" ); + ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq ); old_seq = seq; } if (!cross_thread) @@ -1420,7 +1494,7 @@ if (pGetClipboardSequenceNumber) { seq = pGetClipboardSequenceNumber(); - todo_wine ok( seq == old_seq, "sequence changed\n" ); + ok( seq == old_seq, "sequence changed\n" ); old_seq = seq; } if (!cross_thread) @@ -1518,22 +1592,23 @@ static BOOL is_freed( HANDLE handle ) { - void *ptr = GlobalLock( handle ); - if (ptr) GlobalUnlock( handle ); - return !ptr; + return !GlobalSize( handle ); } static UINT format_id; static HBITMAP bitmap, bitmap2; static HPALETTE palette; -static HPEN pen; -static const LOGPALETTE logpalette = { 0x300, 1 }; +static const LOGPALETTE logpalette = { 0x300, 1, {{ 0x12, 0x34, 0x56, 0x78 }}}; static void test_handles( HWND hwnd ) { - HGLOBAL h, htext, htext2; + HGLOBAL h, htext, htext2, htext3, htext4, htext5; + HGLOBAL hfixed, hfixed2, hmoveable, empty_fixed, empty_moveable; + void *ptr; + UINT format_id2 = RegisterClipboardFormatA( "another format" ); BOOL r; HANDLE data; + HBITMAP bitmap_temp; DWORD process; BOOL is_owner = (GetWindowThreadProcessId( hwnd, &process ) && process == GetCurrentProcessId()); @@ -1540,11 +1615,29 @@ trace( "hwnd %p\n", hwnd ); htext = create_textA(); htext2 = create_textA(); + htext3 = create_textA(); + htext4 = create_textA(); + htext5 = create_textA(); bitmap = CreateBitmap( 10, 10, 1, 1, NULL ); bitmap2 = CreateBitmap( 10, 10, 1, 1, NULL ); palette = CreatePalette( &logpalette ); - pen = CreatePen( PS_SOLID, 1, 0 ); + hfixed = GlobalAlloc( GMEM_FIXED, 17 ); + hfixed2 = GlobalAlloc( GMEM_FIXED, 17 ); + ok( is_fixed( hfixed ), "expected fixed mem %p\n", hfixed ); + ok( GlobalSize( hfixed ) == 17, "wrong size %lu\n", GlobalSize( hfixed )); + + hmoveable = GlobalAlloc( GMEM_MOVEABLE, 23 ); + ok( is_moveable( hmoveable ), "expected moveable mem %p\n", hmoveable ); + ok( GlobalSize( hmoveable ) == 23, "wrong size %lu\n", GlobalSize( hmoveable )); + + empty_fixed = GlobalAlloc( GMEM_FIXED, 0 ); + ok( is_fixed( empty_fixed ), "expected fixed mem %p\n", empty_fixed ); + + empty_moveable = GlobalAlloc( GMEM_MOVEABLE, 0 ); + /* discarded handles can't be GlobalLock'ed */ + ok( is_freed( empty_moveable ), "expected free mem %p\n", empty_moveable ); + r = OpenClipboard( hwnd ); ok( r, "gle %d\n", GetLastError() ); r = EmptyClipboard(); @@ -1556,23 +1649,57 @@ h = SetClipboardData( format_id, htext2 ); ok( h == htext2, "got %p\n", h ); ok( is_moveable( h ), "expected moveable mem %p\n", h ); + bitmap_temp = CreateBitmap( 10, 10, 1, 1, NULL ); + h = SetClipboardData( CF_BITMAP, bitmap_temp ); + ok( h == bitmap_temp, "got %p\n", h ); + ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h ); h = SetClipboardData( CF_BITMAP, bitmap ); ok( h == bitmap, "got %p\n", h ); ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h ); + ok( !GetObjectType( bitmap_temp ), "expected free object %p\n", bitmap_temp ); + h = SetClipboardData( CF_DSPBITMAP, bitmap2 ); + ok( h == bitmap2, "got %p\n", h ); + ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h ); h = SetClipboardData( CF_PALETTE, palette ); ok( h == palette, "got %p\n", h ); ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h ); - /* setting custom GDI formats crashes on 64-bit Windows */ - if (!is_win64) + h = SetClipboardData( CF_GDIOBJFIRST + 3, htext3 ); + ok( h == htext3, "got %p\n", h ); + ok( is_moveable( h ), "expected moveable mem %p\n", h ); + h = SetClipboardData( CF_PRIVATEFIRST + 7, htext5 ); + ok( h == htext5, "got %p\n", h ); + ok( is_moveable( h ), "expected moveable mem %p\n", h ); + h = SetClipboardData( format_id2, empty_moveable ); + ok( !h, "got %p\n", h ); + GlobalFree( empty_moveable ); + + if (0) /* crashes on vista64 */ { - h = SetClipboardData( CF_GDIOBJFIRST + 1, bitmap2 ); - ok( h == bitmap2, "got %p\n", h ); - ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h ); - h = SetClipboardData( CF_GDIOBJFIRST + 2, pen ); - ok( h == pen, "got %p\n", h ); - ok( GetObjectType( h ) == OBJ_PEN, "expected pen %p\n", h ); + ptr = HeapAlloc( GetProcessHeap(), 0, 0 ); + h = SetClipboardData( format_id2, ptr ); + ok( !h, "got %p\n", h ); + HeapFree( GetProcessHeap(), 0, ptr ); } + h = SetClipboardData( format_id2, empty_fixed ); + ok( h == empty_fixed, "got %p\n", h ); + ok( is_fixed( h ), "expected fixed mem %p\n", h ); + h = SetClipboardData( 0xdeadbeef, hfixed2 ); + ok( h == hfixed2, "got %p\n", h ); + ok( is_fixed( h ), "expected fixed mem %p\n", h ); + h = SetClipboardData( 0xdeadbabe, hmoveable ); + ok( h == hmoveable, "got %p\n", h ); + ok( is_moveable( h ), "expected moveable mem %p\n", h ); + + ptr = HeapAlloc( GetProcessHeap(), 0, 37 ); + h = SetClipboardData( 0xdeadfade, ptr ); + ok( h == ptr || !h, "got %p\n", h ); + if (!h) /* heap blocks are rejected on >= win8 */ + { + HeapFree( GetProcessHeap(), 0, ptr ); + ptr = NULL; + } + data = GetClipboardData( CF_TEXT ); ok( data == htext, "wrong data %p\n", data ); ok( is_moveable( data ), "expected moveable mem %p\n", data ); @@ -1581,16 +1708,56 @@ ok( data == htext2, "wrong data %p, cf %08x\n", data, format_id ); ok( is_moveable( data ), "expected moveable mem %p\n", data ); + data = GetClipboardData( CF_GDIOBJFIRST + 3 ); + ok( data == htext3, "wrong data %p\n", data ); + ok( is_moveable( data ), "expected moveable mem %p\n", data ); + + data = GetClipboardData( CF_PRIVATEFIRST + 7 ); + ok( data == htext5, "wrong data %p\n", data ); + ok( is_moveable( data ), "expected moveable mem %p\n", data ); + + data = GetClipboardData( format_id2 ); + ok( data == empty_fixed, "wrong data %p\n", data ); + ok( is_fixed( data ), "expected fixed mem %p\n", data ); + + data = GetClipboardData( 0xdeadbeef ); + ok( data == hfixed2, "wrong data %p\n", data ); + ok( is_fixed( data ), "expected fixed mem %p\n", data ); + + data = GetClipboardData( 0xdeadbabe ); + ok( data == hmoveable, "wrong data %p\n", data ); + ok( is_moveable( data ), "expected moveable mem %p\n", data ); + + data = GetClipboardData( 0xdeadfade ); + ok( data == ptr, "wrong data %p\n", data ); + + h = SetClipboardData( CF_PRIVATEFIRST + 7, htext4 ); + ok( h == htext4, "got %p\n", h ); + ok( is_moveable( h ), "expected moveable mem %p\n", h ); + ok( is_freed( htext5 ), "expected freed mem %p\n", htext5 ); + + h = SetClipboardData( 0xdeadbeef, hfixed ); + ok( h == hfixed, "got %p\n", h ); + ok( is_fixed( h ), "expected fixed mem %p\n", h ); +#ifndef _WIN64 + /* testing if hfixed2 is freed triggers an exception on Win64 */ + ok( is_freed( hfixed2 ) || broken( !is_freed( hfixed2 )) /* < Vista */, "expected freed mem %p\n", hfixed2 ); +#endif + r = CloseClipboard(); ok( r, "gle %d\n", GetLastError() ); /* data handles are still valid */ ok( is_moveable( htext ), "expected moveable mem %p\n", htext ); - ok( is_moveable( htext2 ), "expected moveable mem %p\n", htext ); + ok( is_moveable( htext2 ), "expected moveable mem %p\n", htext2 ); + ok( is_moveable( htext3 ), "expected moveable mem %p\n", htext3 ); + ok( is_moveable( htext4 ), "expected moveable mem %p\n", htext4 ); ok( GetObjectType( bitmap ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap ); ok( GetObjectType( bitmap2 ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap2 ); ok( GetObjectType( palette ) == OBJ_PAL, "expected palette %p\n", palette ); - ok( GetObjectType( pen ) == OBJ_PEN, "expected pen %p\n", pen ); + ok( is_fixed( hfixed ), "expected fixed mem %p\n", hfixed ); + ok( is_moveable( hmoveable ), "expected moveable mem %p\n", hmoveable ); + ok( is_fixed( empty_fixed ), "expected fixed mem %p\n", empty_fixed ); r = OpenClipboard( hwnd ); ok( r, "gle %d\n", GetLastError() ); @@ -1598,19 +1765,47 @@ /* and now they are freed, unless we are the owner */ if (!is_owner) { - todo_wine ok( is_freed( htext ), "expected freed mem %p\n", htext ); - todo_wine ok( is_freed( htext2 ), "expected freed mem %p\n", htext ); + ok( is_freed( htext ), "expected freed mem %p\n", htext ); + ok( is_freed( htext2 ), "expected freed mem %p\n", htext2 ); + ok( is_freed( htext3 ), "expected freed mem %p\n", htext3 ); + ok( is_freed( htext4 ), "expected freed mem %p\n", htext4 ); + ok( is_freed( hmoveable ), "expected freed mem %p\n", hmoveable ); data = GetClipboardData( CF_TEXT ); - todo_wine ok( is_fixed( data ), "expected fixed mem %p\n", data ); + ok( is_fixed( data ), "expected fixed mem %p\n", data ); data = GetClipboardData( format_id ); - todo_wine ok( is_fixed( data ), "expected fixed mem %p\n", data ); + ok( is_fixed( data ), "expected fixed mem %p\n", data ); + + data = GetClipboardData( CF_GDIOBJFIRST + 3 ); + ok( is_fixed( data ), "expected fixed mem %p\n", data ); + + data = GetClipboardData( CF_PRIVATEFIRST + 7 ); + ok( is_fixed( data ), "expected fixed mem %p\n", data ); + + data = GetClipboardData( format_id2 ); + ok( is_fixed( data ), "expected fixed mem %p\n", data ); + ok( GlobalSize( data ) == 1, "wrong size %lu\n", GlobalSize( data )); + + data = GetClipboardData( 0xdeadbeef ); + ok( is_fixed( data ), "expected fixed mem %p\n", data ); + ok( GlobalSize( data ) == 17, "wrong size %lu\n", GlobalSize( data )); + + data = GetClipboardData( 0xdeadbabe ); + ok( is_fixed( data ), "expected fixed mem %p\n", data ); + ok( GlobalSize( data ) == 23, "wrong size %lu\n", GlobalSize( data )); + + data = GetClipboardData( 0xdeadfade ); + ok( is_fixed( data ) || !ptr, "expected fixed mem %p\n", data ); + if (ptr) ok( GlobalSize( data ) == 37, "wrong size %lu\n", GlobalSize( data )); } else { ok( is_moveable( htext ), "expected moveable mem %p\n", htext ); - ok( is_moveable( htext2 ), "expected moveable mem %p\n", htext ); + ok( is_moveable( htext2 ), "expected moveable mem %p\n", htext2 ); + ok( is_moveable( htext3 ), "expected moveable mem %p\n", htext3 ); + ok( is_moveable( htext4 ), "expected moveable mem %p\n", htext4 ); + ok( is_moveable( hmoveable ), "expected moveable mem %p\n", hmoveable ); data = GetClipboardData( CF_TEXT ); ok( data == htext, "wrong data %p\n", data ); @@ -1617,6 +1812,24 @@ data = GetClipboardData( format_id ); ok( data == htext2, "wrong data %p, cf %08x\n", data, format_id ); + + data = GetClipboardData( CF_GDIOBJFIRST + 3 ); + ok( data == htext3, "wrong data %p\n", data ); + + data = GetClipboardData( CF_PRIVATEFIRST + 7 ); + ok( data == htext4, "wrong data %p\n", data ); + + data = GetClipboardData( format_id2 ); + ok( data == empty_fixed, "wrong data %p\n", data ); + + data = GetClipboardData( 0xdeadbeef ); + ok( data == hfixed, "wrong data %p\n", data ); + + data = GetClipboardData( 0xdeadbabe ); + ok( data == hmoveable, "wrong data %p\n", data ); + + data = GetClipboardData( 0xdeadfade ); + ok( data == ptr, "wrong data %p\n", data ); } data = GetClipboardData( CF_OEMTEXT ); @@ -1623,26 +1836,24 @@ ok( is_fixed( data ), "expected fixed mem %p\n", data ); data = GetClipboardData( CF_UNICODETEXT ); ok( is_fixed( data ), "expected fixed mem %p\n", data ); + data = GetClipboardData( CF_LOCALE ); + ok( is_fixed( data ), "expected fixed mem %p\n", data ); data = GetClipboardData( CF_BITMAP ); ok( data == bitmap, "expected bitmap %p\n", data ); + data = GetClipboardData( CF_DSPBITMAP ); + ok( data == bitmap2, "expected bitmap %p\n", data ); data = GetClipboardData( CF_PALETTE ); ok( data == palette, "expected palette %p\n", data ); - if (!is_win64) - { - data = GetClipboardData( CF_GDIOBJFIRST + 1 ); - ok( data == bitmap2, "expected bitmap2 %p\n", data ); - data = GetClipboardData( CF_GDIOBJFIRST + 2 ); - ok( data == pen, "expected pen %p\n", data ); - } data = GetClipboardData( CF_DIB ); ok( is_fixed( data ), "expected fixed mem %p\n", data ); data = GetClipboardData( CF_DIBV5 ); - todo_wine ok( is_fixed( data ), "expected fixed mem %p\n", data ); + ok( is_fixed( data ), "expected fixed mem %p\n", data ); ok( GetObjectType( bitmap ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap ); ok( GetObjectType( bitmap2 ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap2 ); ok( GetObjectType( palette ) == OBJ_PAL, "expected palette %p\n", palette ); - ok( GetObjectType( pen ) == OBJ_PEN, "expected pen %p\n", pen ); + ok( is_fixed( hfixed ), "expected fixed mem %p\n", hfixed ); + ok( is_fixed( empty_fixed ), "expected fixed mem %p\n", empty_fixed ); r = EmptyClipboard(); ok( r, "gle %d\n", GetLastError() ); @@ -1649,11 +1860,15 @@ /* w2003, w2008 don't seem to free the data here */ ok( is_freed( htext ) || broken( !is_freed( htext )), "expected freed mem %p\n", htext ); - ok( is_freed( htext2 ) || broken( !is_freed( htext2 )), "expected freed mem %p\n", htext ); + ok( is_freed( htext2 ) || broken( !is_freed( htext2 )), "expected freed mem %p\n", htext2 ); + ok( is_freed( htext3 ) || broken( !is_freed( htext3 )), "expected freed mem %p\n", htext3 ); + ok( is_freed( htext4 ) || broken( !is_freed( htext4 )), "expected freed mem %p\n", htext4 ); + ok( is_freed( hmoveable ) || broken( !is_freed( hmoveable )), "expected freed mem %p\n", hmoveable ); + ok( is_fixed( empty_fixed ), "expected fixed mem %p\n", empty_fixed ); + ok( is_fixed( hfixed ), "expected fixed mem %p\n", hfixed ); ok( !GetObjectType( bitmap ), "expected freed handle %p\n", bitmap ); + ok( !GetObjectType( bitmap2 ), "expected freed handle %p\n", bitmap2 ); ok( !GetObjectType( palette ), "expected freed handle %p\n", palette ); - ok( GetObjectType( bitmap2 ) == OBJ_BITMAP, "expected bitmap2 %p\n", bitmap2 ); - ok( GetObjectType( pen ) == OBJ_PEN, "expected pen %p\n", pen ); r = CloseClipboard(); ok( r, "gle %d\n", GetLastError() ); @@ -1684,29 +1899,34 @@ ptr = GlobalLock( h ); if (ptr) ok( !strcmp( "test", ptr ), "wrong data '%.5s'\n", ptr ); GlobalUnlock( h ); + h = GetClipboardData( CF_GDIOBJFIRST + 3 ); + ok( is_moveable( h ), "expected moveable mem %p\n", h ); + ptr = GlobalLock( h ); + if (ptr) ok( !strcmp( "test", ptr ), "wrong data '%.5s'\n", ptr ); + GlobalUnlock( h ); + trace( "gdiobj %p\n", h ); + h = GetClipboardData( CF_PRIVATEFIRST + 7 ); + ok( is_moveable( h ), "expected moveable mem %p\n", h ); + ptr = GlobalLock( h ); + if (ptr) ok( !strcmp( "test", ptr ), "wrong data '%.5s'\n", ptr ); + GlobalUnlock( h ); + trace( "private %p\n", h ); h = GetClipboardData( CF_BITMAP ); ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h ); ok( h == bitmap, "different bitmap %p / %p\n", h, bitmap ); trace( "bitmap %p\n", h ); + h = GetClipboardData( CF_DSPBITMAP ); + ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h ); + ok( h == bitmap2, "different bitmap %p / %p\n", h, bitmap2 ); + trace( "bitmap2 %p\n", h ); h = GetClipboardData( CF_PALETTE ); ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h ); ok( h == palette, "different palette %p / %p\n", h, palette ); trace( "palette %p\n", h ); - if (!is_win64) - { - h = GetClipboardData( CF_GDIOBJFIRST + 1 ); - ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h ); - ok( h == bitmap2, "different bitmap %p / %p\n", h, bitmap2 ); - trace( "bitmap2 %p\n", h ); - h = GetClipboardData( CF_GDIOBJFIRST + 2 ); - ok( GetObjectType( h ) == OBJ_PEN, "expected pen %p\n", h ); - ok( h == pen, "different pen %p / %p\n", h, pen ); - trace( "pen %p\n", h ); - } h = GetClipboardData( CF_DIB ); ok( is_fixed( h ), "expected fixed mem %p\n", h ); h = GetClipboardData( CF_DIBV5 ); - todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h ); + ok( is_fixed( h ), "expected fixed mem %p\n", h ); r = CloseClipboard(); ok( r, "gle %d\n", GetLastError() ); return 0; @@ -1717,45 +1937,117 @@ BOOL r; HANDLE h; char *ptr; + BITMAP bm; + PALETTEENTRY entry; + BYTE buffer[1024]; format_id = RegisterClipboardFormatA( "my_cool_clipboard_format" ); r = OpenClipboard( 0 ); ok( r, "gle %d\n", GetLastError() ); h = GetClipboardData( CF_TEXT ); - todo_wine_if( !h ) ok( is_fixed( h ), "expected fixed mem %p\n", h ); + ok( is_fixed( h ), "expected fixed mem %p\n", h ); ptr = GlobalLock( h ); - if (ptr) todo_wine ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr ); + ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr ); GlobalUnlock( h ); h = GetClipboardData( format_id ); - todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h ); + ok( is_fixed( h ), "expected fixed mem %p\n", h ); ptr = GlobalLock( h ); if (ptr) ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr ); GlobalUnlock( h ); + h = GetClipboardData( CF_GDIOBJFIRST + 3 ); + ok( is_fixed( h ), "expected fixed mem %p\n", h ); + ptr = GlobalLock( h ); + ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr ); + GlobalUnlock( h ); + trace( "gdiobj %p\n", h ); + h = GetClipboardData( CF_PRIVATEFIRST + 7 ); + ok( is_fixed( h ), "expected fixed mem %p\n", h ); + ptr = GlobalLock( h ); + ok( !strcmp( str, ptr ), "wrong data '%.5s'\n", ptr ); + GlobalUnlock( h ); + trace( "private %p\n", h ); h = GetClipboardData( CF_BITMAP ); - todo_wine ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h ); + ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h ); + ok( GetObjectW( h, sizeof(bm), &bm ) == sizeof(bm), "GetObject %p failed\n", h ); + ok( bm.bmWidth == 13 && bm.bmHeight == 17, "wrong bitmap %ux%u\n", bm.bmWidth, bm.bmHeight ); trace( "bitmap %p\n", h ); + h = GetClipboardData( CF_DSPBITMAP ); + ok( !GetObjectType( h ), "expected invalid object %p\n", h ); + trace( "bitmap2 %p\n", h ); h = GetClipboardData( CF_PALETTE ); - todo_wine ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h ); + ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h ); + ok( GetPaletteEntries( h, 0, 1, &entry ) == 1, "GetPaletteEntries %p failed\n", h ); + ok( entry.peRed == 0x12 && entry.peGreen == 0x34 && entry.peBlue == 0x56, + "wrong color %02x,%02x,%02x\n", entry.peRed, entry.peGreen, entry.peBlue ); trace( "palette %p\n", h ); - h = GetClipboardData( CF_GDIOBJFIRST + 1 ); - ok( !GetObjectType( h ), "expected invalid %p\n", h ); - trace( "bitmap2 %p\n", h ); - h = GetClipboardData( CF_GDIOBJFIRST + 2 ); - ok( !GetObjectType( h ), "expected invalid %p\n", h ); - trace( "pen %p\n", h ); + h = GetClipboardData( CF_METAFILEPICT ); + ok( is_fixed( h ), "expected fixed mem %p\n", h ); + ok( GetObjectType( ((METAFILEPICT *)h)->hMF ) == OBJ_METAFILE, + "wrong object %p\n", ((METAFILEPICT *)h)->hMF ); + trace( "metafile %p\n", h ); + h = GetClipboardData( CF_DSPMETAFILEPICT ); + ok( is_fixed( h ), "expected fixed mem %p\n", h ); + ok( GetObjectType( ((METAFILEPICT *)h)->hMF ) == OBJ_METAFILE, + "wrong object %p\n", ((METAFILEPICT *)h)->hMF ); + trace( "metafile2 %p\n", h ); + h = GetClipboardData( CF_ENHMETAFILE ); + ok( GetObjectType( h ) == OBJ_ENHMETAFILE, "expected enhmetafile %p\n", h ); + ok( GetEnhMetaFileBits( h, sizeof(buffer), buffer ) > sizeof(ENHMETAHEADER), + "GetEnhMetaFileBits failed on %p\n", h ); + ok( ((ENHMETAHEADER *)buffer)->nRecords == 3, + "wrong records %u\n", ((ENHMETAHEADER *)buffer)->nRecords ); + trace( "enhmetafile %p\n", h ); + h = GetClipboardData( CF_DSPENHMETAFILE ); + ok( GetObjectType( h ) == OBJ_ENHMETAFILE, "expected enhmetafile %p\n", h ); + ok( GetEnhMetaFileBits( h, sizeof(buffer), buffer ) > sizeof(ENHMETAHEADER), + "GetEnhMetaFileBits failed on %p\n", h ); + ok( ((ENHMETAHEADER *)buffer)->nRecords == 3, + "wrong records %u\n", ((ENHMETAHEADER *)buffer)->nRecords ); + trace( "enhmetafile2 %p\n", h ); h = GetClipboardData( CF_DIB ); - todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h ); + ok( is_fixed( h ), "expected fixed mem %p\n", h ); h = GetClipboardData( CF_DIBV5 ); - todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h ); + ok( is_fixed( h ), "expected fixed mem %p\n", h ); r = CloseClipboard(); ok( r, "gle %d\n", GetLastError() ); } +static void test_handles_process_open( const char *str ) +{ + HANDLE h, text = GlobalAlloc( GMEM_DDESHARE|GMEM_MOVEABLE, strlen(str) + 1 ); + char *ptr = GlobalLock( text ); + + strcpy( ptr, str ); + GlobalUnlock( text ); + + /* clipboard already open by parent process */ + h = SetClipboardData( CF_TEXT, text ); + ok( h == text, "wrong mem %p / %p\n", h, text ); + ok( is_moveable( h ), "expected moveable mem %p\n", h ); +} + +static void test_handles_process_dib( const char *str ) +{ + BOOL r; + HANDLE h; + + r = OpenClipboard( 0 ); + ok( r, "gle %d\n", GetLastError() ); + h = GetClipboardData( CF_BITMAP ); + ok( !GetObjectType( h ), "expected invalid object %p\n", h ); + trace( "dibsection %p\n", h ); + r = CloseClipboard(); + ok( r, "gle %d\n", GetLastError() ); +} + static void test_data_handles(void) { BOOL r; - HANDLE h; + char *ptr; + HANDLE h, text; HWND hwnd = CreateWindowA( "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL ); + BITMAPINFO bmi; + void *bits; ok( hwnd != 0, "window creation failed\n" ); format_id = RegisterClipboardFormatA( "my_cool_clipboard_format" ); @@ -1764,10 +2056,9 @@ test_handles( hwnd ); run_thread( test_handles_thread, hwnd, __LINE__ ); - bitmap = CreateBitmap( 10, 10, 1, 1, NULL ); + bitmap = CreateBitmap( 13, 17, 1, 1, NULL ); bitmap2 = CreateBitmap( 10, 10, 1, 1, NULL ); palette = CreatePalette( &logpalette ); - pen = CreatePen( PS_SOLID, 1, 0 ); r = OpenClipboard( hwnd ); ok( r, "gle %d\n", GetLastError() ); @@ -1779,15 +2070,26 @@ ok( is_moveable( h ), "expected moveable mem %p\n", h ); h = SetClipboardData( CF_BITMAP, bitmap ); ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h ); + h = SetClipboardData( CF_DSPBITMAP, bitmap2 ); + ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h ); h = SetClipboardData( CF_PALETTE, palette ); ok( GetObjectType( h ) == OBJ_PAL, "expected palette %p\n", h ); - if (!is_win64) - { - h = SetClipboardData( CF_GDIOBJFIRST + 1, bitmap2 ); - ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h ); - h = SetClipboardData( CF_GDIOBJFIRST + 2, pen ); - ok( GetObjectType( h ) == OBJ_PEN, "expected pen %p\n", h ); - } + h = SetClipboardData( CF_METAFILEPICT, create_metafile() ); + ok( is_moveable( h ), "expected moveable mem %p\n", h ); + trace( "metafile %p\n", h ); + h = SetClipboardData( CF_DSPMETAFILEPICT, create_metafile() ); + ok( is_moveable( h ), "expected moveable mem %p\n", h ); + trace( "metafile2 %p\n", h ); + h = SetClipboardData( CF_ENHMETAFILE, create_emf() ); + ok( GetObjectType( h ) == OBJ_ENHMETAFILE, "expected enhmetafile %p\n", h ); + trace( "enhmetafile %p\n", h ); + h = SetClipboardData( CF_DSPENHMETAFILE, create_emf() ); + ok( GetObjectType( h ) == OBJ_ENHMETAFILE, "expected enhmetafile %p\n", h ); + trace( "enhmetafile2 %p\n", h ); + h = SetClipboardData( CF_GDIOBJFIRST + 3, create_textA() ); + ok( is_moveable( h ), "expected moveable mem %p\n", h ); + h = SetClipboardData( CF_PRIVATEFIRST + 7, create_textA() ); + ok( is_moveable( h ), "expected moveable mem %p\n", h ); r = CloseClipboard(); ok( r, "gle %d\n", GetLastError() ); @@ -1800,14 +2102,302 @@ ok( is_moveable( h ), "expected moveable mem %p\n", h ); h = GetClipboardData( format_id ); ok( is_moveable( h ), "expected moveable mem %p\n", h ); + h = GetClipboardData( CF_GDIOBJFIRST + 3 ); + ok( is_moveable( h ), "expected moveable mem %p\n", h ); + h = GetClipboardData( CF_PRIVATEFIRST + 7 ); + ok( is_moveable( h ), "expected moveable mem %p\n", h ); + r = EmptyClipboard(); ok( r, "gle %d\n", GetLastError() ); + text = create_textA(); + h = SetClipboardData( CF_TEXT, text ); + ok( is_moveable( h ), "expected moveable mem %p\n", h ); + + run_process( "handles_open foobar" ); + + ok( is_moveable( text ), "expected moveable mem %p\n", text ); + h = GetClipboardData( CF_TEXT ); + ok( is_fixed( h ), "expected fixed mem %p\n", h ); + ok( is_moveable( text ), "expected moveable mem %p\n", text ); + ptr = GlobalLock( h ); + ok( !strcmp( ptr, "foobar" ), "wrong data '%.8s'\n", ptr ); + GlobalUnlock( h ); + + r = EmptyClipboard(); + ok( r, "gle %d\n", GetLastError() ); + ok( is_fixed( h ), "expected free mem %p\n", h ); + ok( is_freed( text ) || broken( is_moveable(text) ), /* w2003, w2008 */ + "expected free mem %p\n", text ); r = CloseClipboard(); ok( r, "gle %d\n", GetLastError() ); + /* test CF_BITMAP with a DIB section */ + memset( &bmi, 0, sizeof(bmi) ); + bmi.bmiHeader.biSize = sizeof( bmi.bmiHeader ); + bmi.bmiHeader.biWidth = 29; + bmi.bmiHeader.biHeight = 13; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; + bitmap = CreateDIBSection( 0, &bmi, DIB_RGB_COLORS, &bits, 0, 0 ); + + r = OpenClipboard( hwnd ); + ok( r, "gle %d\n", GetLastError() ); + r = EmptyClipboard(); + ok( r, "gle %d\n", GetLastError() ); + h = SetClipboardData( CF_BITMAP, bitmap ); + ok( GetObjectType( h ) == OBJ_BITMAP, "expected bitmap %p\n", h ); + trace( "dibsection %p\n", h ); + r = CloseClipboard(); + ok( r, "gle %d\n", GetLastError() ); + + run_process( "handles_dib dummy" ); + + r = OpenClipboard( hwnd ); + ok( r, "gle %d\n", GetLastError() ); + ok( GetObjectType( bitmap ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap ); + r = EmptyClipboard(); + ok( r, "gle %d\n", GetLastError() ); + ok( !GetObjectType( bitmap ), "expected deleted %p\n", bitmap ); + r = CloseClipboard(); + ok( r, "gle %d\n", GetLastError() ); + DestroyWindow( hwnd ); } +static void test_GetUpdatedClipboardFormats(void) +{ + BOOL r; + UINT count, formats[256]; + + if (!pGetUpdatedClipboardFormats) + { + win_skip( "GetUpdatedClipboardFormats not supported\n" ); + return; + } + + count = 0xdeadbeef; + r = pGetUpdatedClipboardFormats( NULL, 0, &count ); + ok( r, "gle %d\n", GetLastError() ); + ok( !count, "wrong count %u\n", count ); + + count = 0xdeadbeef; + r = pGetUpdatedClipboardFormats( NULL, 256, &count ); + ok( r, "gle %d\n", GetLastError() ); + ok( !count, "wrong count %u\n", count ); + + SetLastError( 0xdeadbeef ); + r = pGetUpdatedClipboardFormats( formats, 256, NULL ); + ok( !r, "succeeded\n" ); + ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() ); + + count = 0xdeadbeef; + r = pGetUpdatedClipboardFormats( formats, 256, &count ); + ok( r, "gle %d\n", GetLastError() ); + ok( !count, "wrong count %u\n", count ); + + r = OpenClipboard( 0 ); + ok( r, "gle %d\n", GetLastError() ); + r = EmptyClipboard(); + ok( r, "gle %d\n", GetLastError() ); + + count = 0xdeadbeef; + r = pGetUpdatedClipboardFormats( formats, 256, &count ); + ok( r, "gle %d\n", GetLastError() ); + ok( !count, "wrong count %u\n", count ); + + SetClipboardData( CF_UNICODETEXT, 0 ); + + count = 0xdeadbeef; + memset( formats, 0xcc, sizeof(formats) ); + r = pGetUpdatedClipboardFormats( formats, 256, &count ); + ok( r, "gle %d\n", GetLastError() ); + ok( count == 1, "wrong count %u\n", count ); + ok( formats[0] == CF_UNICODETEXT, "wrong format %u\n", formats[0] ); + ok( formats[1] == 0xcccccccc, "wrong format %u\n", formats[1] ); + + SetClipboardData( CF_TEXT, 0 ); + count = 0xdeadbeef; + memset( formats, 0xcc, sizeof(formats) ); + r = pGetUpdatedClipboardFormats( formats, 256, &count ); + ok( r, "gle %d\n", GetLastError() ); + ok( count == 2, "wrong count %u\n", count ); + ok( formats[0] == CF_UNICODETEXT, "wrong format %u\n", formats[0] ); + ok( formats[1] == CF_TEXT, "wrong format %u\n", formats[1] ); + ok( formats[2] == 0xcccccccc, "wrong format %u\n", formats[2] ); + + SetLastError( 0xdeadbeef ); + count = 0xdeadbeef; + r = pGetUpdatedClipboardFormats( formats, 0, &count ); + ok( !r, "succeeded\n" ); + ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %u\n", GetLastError() ); + ok( count == 2, "wrong count %u\n", count ); + + SetLastError( 0xdeadbeef ); + count = 0xdeadbeef; + r = pGetUpdatedClipboardFormats( formats, 1, &count ); + ok( !r, "succeeded\n" ); + ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %u\n", GetLastError() ); + ok( count == 2, "wrong count %u\n", count ); + + r = CloseClipboard(); + ok( r, "gle %d\n", GetLastError() ); + + count = 0xdeadbeef; + memset( formats, 0xcc, sizeof(formats) ); + r = pGetUpdatedClipboardFormats( formats, 256, &count ); + ok( r, "gle %d\n", GetLastError() ); + ok( count == 4, "wrong count %u\n", count ); + ok( formats[0] == CF_UNICODETEXT, "wrong format %u\n", formats[0] ); + ok( formats[1] == CF_TEXT, "wrong format %u\n", formats[1] ); + ok( formats[2] == CF_LOCALE, "wrong format %u\n", formats[2] ); + ok( formats[3] == CF_OEMTEXT, "wrong format %u\n", formats[3] ); + ok( formats[4] == 0xcccccccc, "wrong format %u\n", formats[4] ); + + count = 0xdeadbeef; + memset( formats, 0xcc, sizeof(formats) ); + r = pGetUpdatedClipboardFormats( formats, 2, &count ); + ok( !r, "gle %d\n", GetLastError() ); + ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %u\n", GetLastError() ); + ok( count == 4, "wrong count %u\n", count ); + ok( formats[0] == 0xcccccccc, "wrong format %u\n", formats[0] ); + + count = 0xdeadbeef; + r = pGetUpdatedClipboardFormats( NULL, 256, &count ); + ok( !r, "gle %d\n", GetLastError() ); + ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() ); + ok( count == 4, "wrong count %u\n", count ); + + count = 0xdeadbeef; + r = pGetUpdatedClipboardFormats( NULL, 256, &count ); + ok( !r, "gle %d\n", GetLastError() ); + ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() ); + ok( count == 4, "wrong count %u\n", count ); +} + +static const struct +{ + char strA[12]; + WCHAR strW[12]; + UINT len; +} test_data[] = +{ + { "foo", {0}, 3 }, /* 0 */ + { "foo", {0}, 4 }, + { "foo\0bar", {0}, 7 }, + { "foo\0bar", {0}, 8 }, + { "", {'f','o','o'}, 3 * sizeof(WCHAR) }, + { "", {'f','o','o',0}, 4 * sizeof(WCHAR) }, /* 5 */ + { "", {'f','o','o',0,'b','a','r'}, 7 * sizeof(WCHAR) }, + { "", {'f','o','o',0,'b','a','r',0}, 8 * sizeof(WCHAR) }, + { "", {'f','o','o'}, 1 }, + { "", {'f','o','o'}, 2 }, + { "", {'f','o','o'}, 5 }, /* 10 */ + { "", {'f','o','o',0}, 7 }, + { "", {'f','o','o',0}, 9 }, +}; + +static void test_string_data(void) +{ + UINT i; + BOOL r; + HANDLE data; + char cmd[16]; + char bufferA[12]; + WCHAR bufferW[12]; + + for (i = 0; i < sizeof(test_data) / sizeof(test_data[0]); i++) + { + /* 1-byte Unicode strings crash on Win64 */ +#ifdef _WIN64 + if (!test_data[i].strA[0] && test_data[i].len < sizeof(WCHAR)) continue; +#endif + r = OpenClipboard( 0 ); + ok( r, "gle %d\n", GetLastError() ); + r = EmptyClipboard(); + ok( r, "gle %d\n", GetLastError() ); + data = GlobalAlloc( GMEM_FIXED, test_data[i].len ); + if (test_data[i].strA[0]) + { + memcpy( data, test_data[i].strA, test_data[i].len ); + SetClipboardData( CF_TEXT, data ); + memcpy( bufferA, test_data[i].strA, test_data[i].len ); + bufferA[test_data[i].len - 1] = 0; + ok( !memcmp( data, bufferA, test_data[i].len ), + "%u: wrong data %.*s\n", i, test_data[i].len, (char *)data ); + } + else + { + memcpy( data, test_data[i].strW, test_data[i].len ); + SetClipboardData( CF_UNICODETEXT, data ); + memcpy( bufferW, test_data[i].strW, test_data[i].len ); + bufferW[(test_data[i].len + 1) / sizeof(WCHAR) - 1] = 0; + ok( !memcmp( data, bufferW, test_data[i].len ), + "%u: wrong data %s\n", i, wine_dbgstr_wn( data, (test_data[i].len + 1) / sizeof(WCHAR) )); + } + r = CloseClipboard(); + ok( r, "gle %d\n", GetLastError() ); + sprintf( cmd, "string_data %u", i ); + run_process( cmd ); + } +} + +static void test_string_data_process( int i ) +{ + BOOL r; + HANDLE data; + UINT len, len2; + char bufferA[12]; + WCHAR bufferW[12]; + + r = OpenClipboard( 0 ); + ok( r, "gle %d\n", GetLastError() ); + if (test_data[i].strA[0]) + { + data = GetClipboardData( CF_TEXT ); + ok( data != 0, "%u: could not get data\n", i ); + len = GlobalSize( data ); + ok( len == test_data[i].len, "%u: wrong size %u / %u\n", i, len, test_data[i].len ); + memcpy( bufferA, test_data[i].strA, test_data[i].len ); + bufferA[test_data[i].len - 1] = 0; + ok( !memcmp( data, bufferA, len ), "%u: wrong data %.*s\n", i, len, (char *)data ); + data = GetClipboardData( CF_UNICODETEXT ); + ok( data != 0, "%u: could not get data\n", i ); + len = GlobalSize( data ); + len2 = MultiByteToWideChar( CP_ACP, 0, bufferA, test_data[i].len, bufferW, 12 ); + ok( len == len2 * sizeof(WCHAR), "%u: wrong size %u / %u\n", i, len, len2 ); + ok( !memcmp( data, bufferW, len ), "%u: wrong data %s\n", i, wine_dbgstr_wn( data, len2 )); + } + else + { + data = GetClipboardData( CF_UNICODETEXT ); + ok( data != 0, "%u: could not get data\n", i ); + len = GlobalSize( data ); + ok( len == test_data[i].len, "%u: wrong size %u / %u\n", i, len, test_data[i].len ); + memcpy( bufferW, test_data[i].strW, test_data[i].len ); + bufferW[(test_data[i].len + 1) / sizeof(WCHAR) - 1] = 0; + ok( !memcmp( data, bufferW, len ), + "%u: wrong data %s\n", i, wine_dbgstr_wn( data, (len + 1) / sizeof(WCHAR) )); + data = GetClipboardData( CF_TEXT ); + if (test_data[i].len >= sizeof(WCHAR)) + { + ok( data != 0, "%u: could not get data\n", i ); + len = GlobalSize( data ); + len2 = WideCharToMultiByte( CP_ACP, 0, bufferW, test_data[i].len / sizeof(WCHAR), + bufferA, 12, NULL, NULL ); + bufferA[len2 - 1] = 0; + ok( len == len2, "%u: wrong size %u / %u\n", i, len, len2 ); + ok( !memcmp( data, bufferA, len ), "%u: wrong data %.*s\n", i, len, (char *)data ); + } + else + { + ok( !data, "%u: got data for empty string\n", i ); + ok( IsClipboardFormatAvailable( CF_TEXT ), "%u: text not available\n", i ); + } + } + r = CloseClipboard(); + ok( r, "gle %d\n", GetLastError() ); +} + START_TEST(clipboard) { char **argv; @@ -1818,6 +2408,7 @@ pAddClipboardFormatListener = (void *)GetProcAddress( mod, "AddClipboardFormatListener" ); pRemoveClipboardFormatListener = (void *)GetProcAddress( mod, "RemoveClipboardFormatListener" ); pGetClipboardSequenceNumber = (void *)GetProcAddress( mod, "GetClipboardSequenceNumber" ); + pGetUpdatedClipboardFormats = (void *)GetProcAddress( mod, "GetUpdatedClipboardFormats" ); if (argc == 4 && !strcmp( argv[2], "set_clipboard_data" )) { @@ -1834,6 +2425,21 @@ test_handles_process( argv[3] ); return; } + if (argc == 4 && !strcmp( argv[2], "handles_open" )) + { + test_handles_process_open( argv[3] ); + return; + } + if (argc == 4 && !strcmp( argv[2], "handles_dib" )) + { + test_handles_process_dib( argv[3] ); + return; + } + if (argc == 4 && !strcmp( argv[2], "string_data" )) + { + test_string_data_process( atoi( argv[3] )); + return; + } test_RegisterClipboardFormatA(); test_ClipboardOwner(); @@ -1840,4 +2446,6 @@ test_synthesized(); test_messages(); test_data_handles(); + test_GetUpdatedClipboardFormats(); + test_string_data(); } Index: modules/rostests/winetests/user32/combo.c =================================================================== --- modules/rostests/winetests/user32/combo.c (revision 73312) +++ modules/rostests/winetests/user32/combo.c (working copy) @@ -32,8 +32,8 @@ #define expect_eq(expr, value, type, fmt); { type val = expr; ok(val == (value), #expr " expected " #fmt " got " #fmt "\n", (value), val); } #define expect_rect(r, _left, _top, _right, _bottom) ok(r.left == _left && r.top == _top && \ - r.bottom == _bottom && r.right == _right, "Invalid rect (%d,%d) (%d,%d) vs (%d,%d) (%d,%d)\n", \ - r.left, r.top, r.right, r.bottom, _left, _top, _right, _bottom); + r.bottom == _bottom && r.right == _right, "Invalid rect %s vs (%d,%d)-(%d,%d)\n", \ + wine_dbgstr_rect(&r), _left, _top, _right, _bottom); static HWND build_combo(DWORD style) { Index: modules/rostests/winetests/user32/cursoricon.c =================================================================== --- modules/rostests/winetests/user32/cursoricon.c (revision 73312) +++ modules/rostests/winetests/user32/cursoricon.c (working copy) @@ -83,6 +83,7 @@ typedef struct { BYTE data[32*32*4]; + BYTE mask_data[32*32/8]; } ani_data32x32x32; typedef struct { @@ -2621,7 +2622,9 @@ CloseHandle(handle); handle = LoadImageA(NULL, "icon.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE); - ok(handle != NULL, "LoadImage() failed with %u.\n", GetLastError()); + ok(handle != NULL || + broken(use_core_info && handle == NULL), /* Win 8, 10 */ + "LoadImage() failed with %u.\n", GetLastError()); if (handle == NULL) { skip("Icon failed to load: %s, %s\n", Index: modules/rostests/winetests/user32/dce.c =================================================================== --- modules/rostests/winetests/user32/dce.c (revision 73312) +++ modules/rostests/winetests/user32/dce.c (working copy) @@ -335,10 +335,8 @@ GetClipBox( hdc, &parent_rect ); ReleaseDC( hwnd_parent, hdc ); - ok( rect.left == parent_rect.left, "rect.left = %d, expected %d\n", rect.left, parent_rect.left ); - ok( rect.top == parent_rect.top, "rect.top = %d, expected %d\n", rect.top, parent_rect.top ); - ok( rect.right == parent_rect.right, "rect.right = %d, expected %d\n", rect.right, parent_rect.right ); - ok( rect.bottom == parent_rect.bottom, "rect.bottom = %d, expected %d\n", rect.bottom, parent_rect.bottom ); + ok( EqualRect( &rect, &parent_rect ), "rect = %s, expected %s\n", wine_dbgstr_rect( &rect ), + wine_dbgstr_rect( &parent_rect )); } Index: modules/rostests/winetests/user32/input.c =================================================================== --- modules/rostests/winetests/user32/input.c (revision 73312) +++ modules/rostests/winetests/user32/input.c (working copy) @@ -2493,6 +2493,36 @@ CloseHandle(semaphores[1]); } +static void test_OemKeyScan(void) +{ + DWORD ret, expect, vkey, scan; + WCHAR oem, wchr; + char oem_char; + + for (oem = 0; oem < 0x200; oem++) + { + ret = OemKeyScan( oem ); + + oem_char = LOBYTE( oem ); + if (!OemToCharBuffW( &oem_char, &wchr, 1 )) + expect = -1; + else + { + vkey = VkKeyScanW( wchr ); + scan = MapVirtualKeyW( LOBYTE( vkey ), MAPVK_VK_TO_VSC ); + if (!scan) + expect = -1; + else + { + vkey &= 0xff00; + vkey <<= 8; + expect = vkey | scan; + } + } + ok( ret == expect, "%04x: got %08x expected %08x\n", oem, ret, expect ); + } +} + START_TEST(input) { init_function_pointers(); @@ -2516,6 +2546,7 @@ test_key_names(); test_attach_input(); test_GetKeyState(); + test_OemKeyScan(); if(pGetMouseMovePointsEx) test_GetMouseMovePointsEx(); Index: modules/rostests/winetests/user32/msg.c =================================================================== --- modules/rostests/winetests/user32/msg.c (revision 73312) +++ modules/rostests/winetests/user32/msg.c (working copy) @@ -6517,7 +6517,7 @@ GetRegionData( hrgn, size, data ); printf("%d rects:", data->rdh.nCount ); for (i = 0, rect = (RECT *)data->Buffer; i < data->rdh.nCount; i++, rect++) - printf( " (%d,%d)-(%d,%d)", rect->left, rect->top, rect->right, rect->bottom ); + printf( " %s", wine_dbgstr_rect( rect )); printf("\n"); HeapFree( GetProcessHeap(), 0, data ); } @@ -6698,7 +6698,7 @@ static void test_paint_messages(void) { BOOL ret; - RECT rect; + RECT rect, rect2; POINT pt; MSG msg; HWND hparent, hchild; @@ -6763,7 +6763,8 @@ */ trace("testing ValidateRect(0, NULL)\n"); SetRectEmpty( &rect ); - if (ValidateRect(0, &rect)) /* not supported on Win9x */ + if (ValidateRect(0, &rect) && /* not supported on Win9x */ + GetUpdateRect(hwnd, NULL, FALSE)) /* or >= Win 8 */ { check_update_rgn( hwnd, hrgn ); ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE ); @@ -7237,15 +7238,21 @@ SetRectRgn( hrgn, 10, 10, 40, 40 ); check_update_rgn( hchild, hrgn ); MoveWindow( hparent, -20, -20, 200, 200, FALSE ); - SetRectRgn( hrgn, 20, 20, 100, 100 ); + GetUpdateRect( hparent, &rect2, FALSE ); + if (!EqualRect( &rect2, &rect )) /* Win 8 and later don't crop update to screen */ + { + rect.left += 20; + rect.top += 20; + } + SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom ); check_update_rgn( hparent, hrgn ); - SetRectRgn( hrgn, 30, 30, 40, 40 ); + SetRectRgn( hrgn, rect.left + 10, rect.top + 10, 40, 40 ); check_update_rgn( hchild, hrgn ); /* invalidated region is cropped by the parent rects */ SetRect( &rect, 0, 0, 50, 50 ); RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_ERASE ); - SetRectRgn( hrgn, 30, 30, 50, 50 ); + SetRectRgn( hrgn, rect2.left + 10, rect2.top + 10, 50, 50 ); check_update_rgn( hchild, hrgn ); DestroyWindow( hparent ); @@ -12125,9 +12132,8 @@ SetLastError(0xdeadbeef); ret = pGetMonitorInfoA(hmon, &mi); ok(ret, "GetMonitorInfo error %u\n", GetLastError()); - trace("monitor (%d,%d-%d,%d), work (%d,%d-%d,%d)\n", - mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom, - mi.rcWork.left, mi.rcWork.top, mi.rcWork.right, mi.rcWork.bottom); + trace("monitor %s, work %s\n", wine_dbgstr_rect(&mi.rcMonitor), + wine_dbgstr_rect(&mi.rcWork)); work_rc = mi.rcWork; } @@ -12145,11 +12151,8 @@ ok(wp.ptMaxPosition.x == -1 && wp.ptMaxPosition.y == -1, "expected -1,-1 got %d,%d\n", wp.ptMaxPosition.x, wp.ptMaxPosition.y); todo_wine_if (work_rc.left || work_rc.top) /* FIXME: remove once Wine is fixed */ - ok(EqualRect(&win_rc, &wp.rcNormalPosition), - "expected %d,%d-%d,%d got %d,%d-%d,%d\n", - win_rc.left, win_rc.top, win_rc.right, win_rc.bottom, - wp.rcNormalPosition.left, wp.rcNormalPosition.top, - wp.rcNormalPosition.right, wp.rcNormalPosition.bottom); + ok(EqualRect(&win_rc, &wp.rcNormalPosition), "expected %s got %s\n", wine_dbgstr_rect(&win_rc), + wine_dbgstr_rect(&wp.rcNormalPosition)); for (i = 0; i < sizeof(sw)/sizeof(sw[0]); i++) { @@ -12201,11 +12204,8 @@ "expected %d,%d got %d,%d\n", sw[i].wp_max.x, sw[i].wp_max.y, wp.ptMaxPosition.x, wp.ptMaxPosition.y); if (0) /* FIXME: Wine behaves completely different here */ - ok(EqualRect(&win_rc, &wp.rcNormalPosition), - "expected %d,%d-%d,%d got %d,%d-%d,%d\n", - win_rc.left, win_rc.top, win_rc.right, win_rc.bottom, - wp.rcNormalPosition.left, wp.rcNormalPosition.top, - wp.rcNormalPosition.right, wp.rcNormalPosition.bottom); + ok(EqualRect(&win_rc, &wp.rcNormalPosition), "expected %s got %s\n", + wine_dbgstr_rect(&win_rc), wine_dbgstr_rect(&wp.rcNormalPosition)); } DestroyWindow(hwnd); flush_events(); @@ -13983,6 +13983,25 @@ { 0 } }; +struct rbuttonup_thread_data +{ + HWND hwnd; + HANDLE wndproc_finished; +}; + +static DWORD CALLBACK post_rbuttonup_msg( void *arg ) +{ + struct rbuttonup_thread_data *data = arg; + DWORD ret; + + ret = WaitForSingleObject( data->wndproc_finished, 500 ); + todo_wine ok( ret == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", ret ); + if( ret == WAIT_OBJECT_0 ) return 0; + + PostMessageA( data->hwnd, WM_RBUTTONUP, 0, 0 ); + return 0; +} + static void test_defwinproc(void) { HWND hwnd; @@ -13992,6 +14011,8 @@ RECT rect; INT x, y; LRESULT res; + struct rbuttonup_thread_data data; + HANDLE thread; hwnd = CreateWindowExA(0, "TestWindowClass", "test_defwndproc", WS_VISIBLE | WS_CAPTION | WS_OVERLAPPEDWINDOW, 0,0,500,100,0,0,0, NULL); @@ -14007,11 +14028,25 @@ res = DefWindowProcA( hwnd, WM_NCHITTEST, 0, MAKELPARAM(x, y)); ok(res == HTCAPTION, "WM_NCHITTEST returned %ld\n", res); + mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 ); + mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 ); + flush_events(); + flush_sequence(); - PostMessageA( hwnd, WM_RBUTTONUP, 0, 0); + mouse_event( MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0 ); + /* workaround for missing support for clicking on window frame */ + data.hwnd = hwnd; + data.wndproc_finished = CreateEventA( NULL, FALSE, FALSE, NULL ); + thread = CreateThread( NULL, 0, post_rbuttonup_msg, (void*)&data, 0, NULL ); + DefWindowProcA( hwnd, WM_NCRBUTTONDOWN, HTCAPTION, MAKELPARAM(x, y)); ok_sequence(NCRBUTTONDOWNSeq, "WM_NCRBUTTONDOWN on caption", FALSE); + SetEvent( data.wndproc_finished ); + WaitForSingleObject( thread, 1000 ); + CloseHandle( data.wndproc_finished ); + CloseHandle( thread ); + SetCursorPos(pos.x, pos.y); DefWindowProcA( hwnd, WM_ENDSESSION, 1, 0); @@ -15604,8 +15639,8 @@ size.cx = 0; ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); ok( !ret, "UpdateLayeredWindow should fail on non-layered window\n" ); - ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(ERROR_MR_MID_NOT_FOUND) /* win7 */, - "wrong error %u\n", GetLastError() ); + ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == ERROR_MR_MID_NOT_FOUND) || + broken(GetLastError() == ERROR_GEN_FAILURE) /* win7 */, "wrong error %u\n", GetLastError() ); size.cx = 1; size.cy = -1; ret = pUpdateLayeredWindow( hwnd, 0, &pos, &size, hdc, &src, 0, NULL, ULW_OPAQUE ); Index: modules/rostests/winetests/user32/text.c =================================================================== --- modules/rostests/winetests/user32/text.c (revision 73312) +++ modules/rostests/winetests/user32/text.c (working copy) @@ -26,6 +26,7 @@ #include "wingdi.h" #include "winuser.h" #include "winerror.h" +#include "winnls.h" #define MODIFIED(rect) (rect.left == 10 && rect.right != 100 && rect.top == 10 && rect.bottom != 100) #define EMPTY(rect) (rect.left == rect.right && rect.bottom == rect.top) @@ -746,6 +747,8 @@ }; BOOL ret; int i; + char oem; + WCHAR uni, expect; for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { @@ -807,6 +810,15 @@ ok(ret == tests[i].ret, "test %d: expected %d, got %d\n", i, tests[i].ret, ret); ok(!lstrcmpW(buf, expected), "test %d: got '%s'\n", i, wine_dbgstr_w(buf)); } + + for (i = 0; i < 0x100; i++) + { + oem = i; + ret = OemToCharBuffW( &oem, &uni, 1 ); + ok( ret, "%02x: returns FALSE\n", i ); + MultiByteToWideChar( CP_OEMCP, MB_PRECOMPOSED | MB_USEGLYPHCHARS, &oem, 1, &expect, 1 ); + ok( uni == expect, "%02x: got %04x expected %04x\n", i, uni, expect ); + } } START_TEST(text) Index: modules/rostests/winetests/user32/win.c =================================================================== --- modules/rostests/winetests/user32/win.c (revision 73312) +++ modules/rostests/winetests/user32/win.c (working copy) @@ -9550,7 +9550,6 @@ test_window_without_child_style(); test_smresult(); test_GetMessagePos(); - test_activateapp(hwndMain); test_winproc_handles(argv[0]); test_deferwindowpos(); Index: modules/rostests/winetests/user32/wsprintf.c =================================================================== --- modules/rostests/winetests/user32/wsprintf.c (revision 73312) +++ modules/rostests/winetests/user32/wsprintf.c (working copy) @@ -119,7 +119,6 @@ for (i=0;i<256;i++) { out = (INT_PTR)CharUpperA((LPSTR)i); - /* printf("%0x ",out); */ if ((out >> 16) != 0) { failed = TRUE; @@ -137,7 +136,6 @@ for (i=0;i<256;i++) { out = (INT_PTR)CharLowerA((LPSTR)i); - /* printf("%0x ",out); */ if ((out >> 16) != 0) { failed = TRUE;