/* * Unit test suite for pens * * Copyright 2006 Dmitry Timoshkov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include "windef.h" #include "winbase.h" #include "wingdi.h" #include "winuser.h" #include "wine/test.h" #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got) #define expect2(expected, alt, got) ok(got == expected || got == alt, \ "Expected %.8x or %.8x, got %.8x\n", expected, alt, got) static void test_logpen(void) { static const struct { UINT style; INT width; COLORREF color; UINT ret_style; INT ret_width; COLORREF ret_color; } pen[] = { { PS_SOLID, -123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) }, { PS_SOLID, 0, RGB(0x12,0x34,0x56), PS_SOLID, 0, RGB(0x12,0x34,0x56) }, { PS_SOLID, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) }, { PS_DASH, 123, RGB(0x12,0x34,0x56), PS_DASH, 123, RGB(0x12,0x34,0x56) }, { PS_DOT, 123, RGB(0x12,0x34,0x56), PS_DOT, 123, RGB(0x12,0x34,0x56) }, { PS_DASHDOT, 123, RGB(0x12,0x34,0x56), PS_DASHDOT, 123, RGB(0x12,0x34,0x56) }, { PS_DASHDOTDOT, 123, RGB(0x12,0x34,0x56), PS_DASHDOTDOT, 123, RGB(0x12,0x34,0x56) }, { PS_NULL, -123, RGB(0x12,0x34,0x56), PS_NULL, 1, 0 }, { PS_NULL, 123, RGB(0x12,0x34,0x56), PS_NULL, 1, 0 }, { PS_INSIDEFRAME, 123, RGB(0x12,0x34,0x56), PS_INSIDEFRAME, 123, RGB(0x12,0x34,0x56) }, { PS_USERSTYLE, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) }, { PS_ALTERNATE, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) } }; INT i, size; HPEN hpen; LOGPEN lp; EXTLOGPEN elp; LOGBRUSH lb; DWORD_PTR unset_hatch; DWORD obj_type, user_style[2] = { 0xabc, 0xdef }; char elp_buffer[128]; EXTLOGPEN *ext_pen = (EXTLOGPEN *)elp_buffer; DWORD *ext_style = ext_pen->elpStyleEntry; for (i = 0; i < sizeof(pen)/sizeof(pen[0]); i++) { trace("%d: testing style %u\n", i, pen[i].style); /********************** cosmetic pens **********************/ /* CreatePenIndirect behaviour */ lp.lopnStyle = pen[i].style, lp.lopnWidth.x = pen[i].width; lp.lopnWidth.y = 11; /* just in case */ lp.lopnColor = pen[i].color; SetLastError(0xdeadbeef); hpen = CreatePenIndirect(&lp); if(hpen == 0 && GetLastError() == ERROR_INVALID_PARAMETER) { win_skip("No support for pen style %u (%d)\n", pen[i].style, i); continue; } obj_type = GetObjectType(hpen); ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type); memset(&lp, 0xb0, sizeof(lp)); SetLastError(0xdeadbeef); size = GetObject(hpen, sizeof(lp), &lp); ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError()); if (pen[i].style == PS_USERSTYLE || pen[i].style == PS_ALTERNATE) { if (lp.lopnStyle == pen[i].style) { win_skip("Skipping PS_USERSTYLE and PS_ALTERNATE tests on Win9x\n"); continue; } } ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle); ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x); ok(lp.lopnWidth.y == 0 || broken(lp.lopnWidth.y == 0xb), /* Win9x */ "expected 0, got %d\n", lp.lopnWidth.y); ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor); DeleteObject(hpen); /* CreatePen behaviour */ SetLastError(0xdeadbeef); hpen = CreatePen(pen[i].style, pen[i].width, pen[i].color); ok(hpen != 0, "CreatePen error %d\n", GetLastError()); obj_type = GetObjectType(hpen); ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type); /* check what's the real size of the object */ size = GetObject(hpen, 0, NULL); ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError()); /* ask for truncated data */ memset(&lp, 0xb0, sizeof(lp)); SetLastError(0xdeadbeef); size = GetObject(hpen, sizeof(lp.lopnStyle), &lp); ok(!size || broken(size == sizeof(lp.lopnStyle)), /* Win9x */ "GetObject should fail: size %d, error %d\n", size, GetLastError()); /* see how larger buffer sizes are handled */ memset(&lp, 0xb0, sizeof(lp)); SetLastError(0xdeadbeef); size = GetObject(hpen, sizeof(lp) * 4, &lp); ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError()); /* see how larger buffer sizes are handled */ memset(&elp, 0xb0, sizeof(elp)); SetLastError(0xdeadbeef); size = GetObject(hpen, sizeof(elp) * 2, &elp); ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError()); memset(&lp, 0xb0, sizeof(lp)); SetLastError(0xdeadbeef); size = GetObject(hpen, sizeof(lp), &lp); ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError()); ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle); ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x); ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y); ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor); memset(&elp, 0xb0, sizeof(elp)); SetLastError(0xdeadbeef); size = GetObject(hpen, sizeof(elp), &elp); /* for some reason XP differentiates PS_NULL here */ if (pen[i].style == PS_NULL) { ok(hpen == GetStockObject(NULL_PEN), "hpen should be a stock NULL_PEN\n"); ok(size == sizeof(EXTLOGPEN), "GetObject returned %d, error %d\n", size, GetLastError()); ok(elp.elpPenStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, elp.elpPenStyle); ok(elp.elpWidth == 0, "expected 0, got %u\n", elp.elpWidth); ok(elp.elpColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, elp.elpColor); ok(elp.elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %u\n", elp.elpBrushStyle); ok(elp.elpHatch == 0, "expected 0, got %p\n", (void *)elp.elpHatch); ok(elp.elpNumEntries == 0, "expected 0, got %x\n", elp.elpNumEntries); } else { ok(size == sizeof(LOGPEN), "GetObject returned %d, error %d\n", size, GetLastError()); memcpy(&lp, &elp, sizeof(lp)); ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle); ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x); ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y); ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor); } DeleteObject(hpen); /********** cosmetic pens created by ExtCreatePen ***********/ lb.lbStyle = BS_SOLID; lb.lbColor = pen[i].color; lb.lbHatch = HS_CROSS; /* just in case */ SetLastError(0xdeadbeef); hpen = ExtCreatePen(pen[i].style, pen[i].width, &lb, 2, user_style); if (pen[i].style != PS_USERSTYLE) { ok(hpen == 0, "ExtCreatePen should fail\n"); ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong last error value %d\n", GetLastError()); SetLastError(0xdeadbeef); hpen = ExtCreatePen(pen[i].style, pen[i].width, &lb, 0, NULL); if (pen[i].style != PS_NULL) { ok(hpen == 0, "ExtCreatePen with width != 1 should fail\n"); ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong last error value %d\n", GetLastError()); SetLastError(0xdeadbeef); hpen = ExtCreatePen(pen[i].style, 1, &lb, 0, NULL); } } else { ok(hpen == 0, "ExtCreatePen with width != 1 should fail\n"); ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong last error value %d\n", GetLastError()); SetLastError(0xdeadbeef); hpen = ExtCreatePen(pen[i].style, 1, &lb, 2, user_style); } if (pen[i].style == PS_INSIDEFRAME) { /* This style is applicable only for geometric pens */ ok(hpen == 0, "ExtCreatePen should fail\n"); goto test_geometric_pens; } ok(hpen != 0, "ExtCreatePen error %d\n", GetLastError()); obj_type = GetObjectType(hpen); /* for some reason XP differentiates PS_NULL here */ if (pen[i].style == PS_NULL) { ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type); ok(hpen == GetStockObject(NULL_PEN), "hpen should be a stock NULL_PEN\n"); } else ok(obj_type == OBJ_EXTPEN, "wrong object type %u\n", obj_type); /* check what's the real size of the object */ SetLastError(0xdeadbeef); size = GetObject(hpen, 0, NULL); switch (pen[i].style) { case PS_NULL: ok(size == sizeof(LOGPEN), "GetObject returned %d, error %d\n", size, GetLastError()); break; case PS_USERSTYLE: ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry) + sizeof(user_style) || broken(size == 0 && GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */ "GetObject returned %d, error %d\n", size, GetLastError()); break; default: ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry) || broken(size == sizeof(LOGPEN)) || /* Win9x */ broken(pen[i].style == PS_ALTERNATE && size == 0 && GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */ "GetObject returned %d, error %d\n", size, GetLastError()); break; } /* ask for truncated data */ memset(&elp, 0xb0, sizeof(elp)); SetLastError(0xdeadbeef); size = GetObject(hpen, sizeof(elp.elpPenStyle), &elp); ok(!size || broken(size == sizeof(elp.elpPenStyle)), /* Win9x */ "GetObject should fail: size %d, error %d\n", size, GetLastError()); /* see how larger buffer sizes are handled */ memset(elp_buffer, 0xb0, sizeof(elp_buffer)); SetLastError(0xdeadbeef); size = GetObject(hpen, sizeof(elp_buffer), elp_buffer); switch (pen[i].style) { case PS_NULL: ok(size == sizeof(LOGPEN), "GetObject returned %d, error %d\n", size, GetLastError()); memcpy(&lp, ext_pen, sizeof(lp)); ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle); ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x); ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y); ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor); /* for PS_NULL it also works this way */ memset(&elp, 0xb0, sizeof(elp)); memset(&unset_hatch, 0xb0, sizeof(unset_hatch)); SetLastError(0xdeadbeef); size = GetObject(hpen, sizeof(elp), &elp); ok(size == sizeof(EXTLOGPEN), "GetObject returned %d, error %d\n", size, GetLastError()); ok(ext_pen->elpHatch == unset_hatch, "expected 0xb0b0b0b0, got %p\n", (void *)ext_pen->elpHatch); ok(ext_pen->elpNumEntries == 0xb0b0b0b0, "expected 0xb0b0b0b0, got %x\n", ext_pen->elpNumEntries); break; case PS_USERSTYLE: ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry) + sizeof(user_style), "GetObject returned %d, error %d\n", size, GetLastError()); ok(ext_pen->elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen->elpHatch); ok(ext_pen->elpNumEntries == 2, "expected 0, got %x\n", ext_pen->elpNumEntries); ok(ext_style[0] == 0xabc, "expected 0xabc, got %x\n", ext_style[0]); ok(ext_style[1] == 0xdef, "expected 0xdef, got %x\n", ext_style[1]); break; default: ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry) || broken(size == sizeof(LOGPEN)) || /* Win9x */ broken(pen[i].style == PS_ALTERNATE && size == 0 && GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */ "GetObject returned %d, error %d\n", size, GetLastError()); ok(ext_pen->elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen->elpHatch); ok(ext_pen->elpNumEntries == 0, "expected 0, got %x\n", ext_pen->elpNumEntries); break; } ok(ext_pen->elpPenStyle == pen[i].style, "expected %x, got %x\n", pen[i].style, ext_pen->elpPenStyle); ok(ext_pen->elpWidth == 1, "expected 1, got %x\n", ext_pen->elpWidth); ok(ext_pen->elpColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, ext_pen->elpColor); ok(ext_pen->elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %x\n", ext_pen->elpBrushStyle); DeleteObject(hpen); test_geometric_pens: /********************** geometric pens **********************/ lb.lbStyle = BS_SOLID; lb.lbColor = pen[i].color; lb.lbHatch = HS_CROSS; /* just in case */ SetLastError(0xdeadbeef); hpen = ExtCreatePen(PS_GEOMETRIC | pen[i].style, pen[i].width, &lb, 2, user_style); if (pen[i].style != PS_USERSTYLE) { ok(hpen == 0, "ExtCreatePen should fail\n"); SetLastError(0xdeadbeef); hpen = ExtCreatePen(PS_GEOMETRIC | pen[i].style, pen[i].width, &lb, 0, NULL); } if (pen[i].style == PS_ALTERNATE) { /* This style is applicable only for cosmetic pens */ ok(hpen == 0, "ExtCreatePen should fail\n"); continue; } ok(hpen != 0, "ExtCreatePen error %d\n", GetLastError()); obj_type = GetObjectType(hpen); /* for some reason XP differentiates PS_NULL here */ if (pen[i].style == PS_NULL) ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type); else ok(obj_type == OBJ_EXTPEN, "wrong object type %u\n", obj_type); /* check what's the real size of the object */ size = GetObject(hpen, 0, NULL); switch (pen[i].style) { case PS_NULL: ok(size == sizeof(LOGPEN), "GetObject returned %d, error %d\n", size, GetLastError()); break; case PS_USERSTYLE: ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry) + sizeof(user_style), "GetObject returned %d, error %d\n", size, GetLastError()); break; default: ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry), "GetObject returned %d, error %d\n", size, GetLastError()); break; } /* ask for truncated data */ memset(&lp, 0xb0, sizeof(lp)); SetLastError(0xdeadbeef); size = GetObject(hpen, sizeof(lp.lopnStyle), &lp); ok(!size, "GetObject should fail: size %d, error %d\n", size, GetLastError()); memset(&lp, 0xb0, sizeof(lp)); SetLastError(0xdeadbeef); size = GetObject(hpen, sizeof(lp), &lp); /* for some reason XP differentiates PS_NULL here */ if (pen[i].style == PS_NULL) { ok(size == sizeof(LOGPEN), "GetObject returned %d, error %d\n", size, GetLastError()); ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle); ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x); ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y); ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor); } else /* XP doesn't set last error here */ ok(!size /*&& GetLastError() == ERROR_INVALID_PARAMETER*/, "GetObject should fail: size %d, error %d\n", size, GetLastError()); memset(elp_buffer, 0xb0, sizeof(elp_buffer)); SetLastError(0xdeadbeef); /* buffer is too small for user styles */ size = GetObject(hpen, sizeof(EXTLOGPEN), elp_buffer); switch (pen[i].style) { case PS_NULL: ok(size == sizeof(EXTLOGPEN), "GetObject returned %d, error %d\n", size, GetLastError()); ok(ext_pen->elpHatch == 0, "expected 0, got %p\n", (void *)ext_pen->elpHatch); ok(ext_pen->elpNumEntries == 0, "expected 0, got %x\n", ext_pen->elpNumEntries); /* for PS_NULL it also works this way */ SetLastError(0xdeadbeef); size = GetObject(hpen, sizeof(elp_buffer), &lp); ok(size == sizeof(LOGPEN), "GetObject returned %d, error %d\n", size, GetLastError()); ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle); ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x); ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y); ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor); break; case PS_USERSTYLE: ok(!size /*&& GetLastError() == ERROR_INVALID_PARAMETER*/, "GetObject should fail: size %d, error %d\n", size, GetLastError()); size = GetObject(hpen, sizeof(elp_buffer), elp_buffer); ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry) + sizeof(user_style), "GetObject returned %d, error %d\n", size, GetLastError()); ok(ext_pen->elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen->elpHatch); ok(ext_pen->elpNumEntries == 2, "expected 0, got %x\n", ext_pen->elpNumEntries); ok(ext_style[0] == 0xabc, "expected 0xabc, got %x\n", ext_style[0]); ok(ext_style[1] == 0xdef, "expected 0xdef, got %x\n", ext_style[1]); break; default: ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry), "GetObject returned %d, error %d\n", size, GetLastError()); ok(ext_pen->elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen->elpHatch); ok(ext_pen->elpNumEntries == 0, "expected 0, got %x\n", ext_pen->elpNumEntries); break; } /* for some reason XP differentiates PS_NULL here */ if (pen[i].style == PS_NULL) ok(ext_pen->elpPenStyle == pen[i].ret_style, "expected %x, got %x\n", pen[i].ret_style, ext_pen->elpPenStyle); else { ok(ext_pen->elpPenStyle == (PS_GEOMETRIC | pen[i].style), "expected %x, got %x\n", PS_GEOMETRIC | pen[i].style, ext_pen->elpPenStyle); } if (pen[i].style == PS_NULL) ok(ext_pen->elpWidth == 0, "expected 0, got %x\n", ext_pen->elpWidth); else ok(ext_pen->elpWidth == pen[i].ret_width, "expected %u, got %x\n", pen[i].ret_width, ext_pen->elpWidth); ok(ext_pen->elpColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, ext_pen->elpColor); ok(ext_pen->elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %x\n", ext_pen->elpBrushStyle); DeleteObject(hpen); } } static unsigned int atoi2(const char *s) { unsigned int ret = 0; while(*s) ret = (ret << 1) | (*s++ == '1'); return ret; } #define TEST_LINE(x1, x2, z) \ { int buf = 0; \ SetBitmapBits(bmp, sizeof(buf), &buf); \ MoveToEx(hdc, x1, 0, NULL); \ LineTo(hdc, x2, 0); \ GetBitmapBits(bmp, sizeof(buf), &buf); \ expect(atoi2(z), buf); } static void test_ps_alternate(void) { HDC hdc; HBITMAP bmp; HPEN pen; LOGBRUSH lb; INT iRet; HGDIOBJ hRet; lb.lbStyle = BS_SOLID; lb.lbColor = RGB(0xff,0xff,0xff); SetLastError(0xdeadbeef); pen = ExtCreatePen(PS_COSMETIC|PS_ALTERNATE, 1, &lb, 0, NULL); if(pen == NULL && GetLastError() == 0xdeadbeef) { skip("looks like 9x, skipping PS_ALTERNATE tests\n"); return; } ok(pen != NULL, "gle=%d\n", GetLastError()); hdc = CreateCompatibleDC(NULL); ok(hdc != NULL, "gle=%d\n", GetLastError()); bmp = CreateBitmap(8, 1, 1, 1, NULL); ok(bmp != NULL, "gle=%d\n", GetLastError()); hRet = SelectObject(hdc, bmp); ok(hRet != NULL, "gle=%d\n", GetLastError()); hRet = SelectObject(hdc, pen); ok(hRet != NULL, "gle=%d\n", GetLastError()); iRet = SetBkMode(hdc, TRANSPARENT); ok(iRet, "gle=%d\n", GetLastError()); TEST_LINE(0, 1, "10000000") TEST_LINE(0, 2, "10000000") TEST_LINE(0, 3, "10100000") TEST_LINE(0, 4, "10100000") TEST_LINE(1, 4, "01010000") TEST_LINE(1, 5, "01010000") TEST_LINE(4, 8, "00001010") DeleteObject(pen); DeleteObject(bmp); DeleteDC(hdc); } static void test_ps_userstyle(void) { static DWORD style[17] = {0, 2, 0, 4, 5, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 17}; static DWORD bad_style[5] = {0, 0, 0, 0, 0}; static DWORD bad_style2[5] = {4, 7, 8, 3, -1}; LOGBRUSH lb; HPEN pen; INT size, i; struct { EXTLOGPEN elp; DWORD style_data[15]; } ext_pen; lb.lbColor = 0x00ff0000; lb.lbStyle = BS_SOLID; lb.lbHatch = 0; pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 3, NULL); ok(pen == 0, "ExtCreatePen should fail\n"); if (pen == 0 && GetLastError() == 0xdeadbeef) { win_skip("Looks like 9x, skipping PS_USERSTYLE tests\n"); return; } expect(ERROR_INVALID_PARAMETER, GetLastError()); DeleteObject(pen); SetLastError(0xdeadbeef); pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 0, style); ok(pen == 0, "ExtCreatePen should fail\n"); expect2(0xdeadbeef, ERROR_INVALID_PARAMETER, GetLastError()); DeleteObject(pen); SetLastError(0xdeadbeef); pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 17, style); ok(pen == 0, "ExtCreatePen should fail\n"); expect(ERROR_INVALID_PARAMETER, GetLastError()); DeleteObject(pen); SetLastError(0xdeadbeef); pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, -1, style); ok(pen == 0, "ExtCreatePen should fail\n"); expect(0xdeadbeef, GetLastError()); DeleteObject(pen); SetLastError(0xdeadbeef); pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 5, bad_style); ok(pen == 0, "ExtCreatePen should fail\n"); expect(ERROR_INVALID_PARAMETER, GetLastError()); DeleteObject(pen); SetLastError(0xdeadbeef); pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 5, bad_style2); ok(pen == 0, "ExtCreatePen should fail\n"); expect(ERROR_INVALID_PARAMETER, GetLastError()); DeleteObject(pen); SetLastError(0xdeadbeef); pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 16, style); ok(pen != 0, "ExtCreatePen should not fail\n"); size = GetObject(pen, sizeof(ext_pen), &ext_pen); expect(FIELD_OFFSET(EXTLOGPEN,elpStyleEntry[16]), size); for(i = 0; i < 16; i++) expect(style[i], ext_pen.elp.elpStyleEntry[i]); DeleteObject(pen); } START_TEST(pen) { test_logpen(); test_ps_alternate(); test_ps_userstyle(); }