wintrust: Use helper function for setting confidence in SoftpubCheckCert.
[wine] / dlls / gdi32 / tests / pen.c
1 /*
2  * Unit test suite for pens
3  *
4  * Copyright 2006 Dmitry Timoshkov
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <stdarg.h>
22 #include <assert.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28
29 #include "wine/test.h"
30
31 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
32 #define expect2(expected, alt, got) ok(got == expected || got == alt, \
33                                        "Expected %.8x or %.8x, got %.8x\n", expected, alt, got)
34
35 static void test_logpen(void)
36 {
37     static const struct
38     {
39         UINT style;
40         INT width;
41         COLORREF color;
42         UINT ret_style;
43         INT ret_width;
44         COLORREF ret_color;
45     } pen[] = {
46         { PS_SOLID, -123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
47         { PS_SOLID, 0, RGB(0x12,0x34,0x56), PS_SOLID, 0, RGB(0x12,0x34,0x56) },
48         { PS_SOLID, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
49         { PS_DASH, 123, RGB(0x12,0x34,0x56), PS_DASH, 123, RGB(0x12,0x34,0x56) },
50         { PS_DOT, 123, RGB(0x12,0x34,0x56), PS_DOT, 123, RGB(0x12,0x34,0x56) },
51         { PS_DASHDOT, 123, RGB(0x12,0x34,0x56), PS_DASHDOT, 123, RGB(0x12,0x34,0x56) },
52         { PS_DASHDOTDOT, 123, RGB(0x12,0x34,0x56), PS_DASHDOTDOT, 123, RGB(0x12,0x34,0x56) },
53         { PS_NULL, -123, RGB(0x12,0x34,0x56), PS_NULL, 1, 0 },
54         { PS_NULL, 123, RGB(0x12,0x34,0x56), PS_NULL, 1, 0 },
55         { PS_INSIDEFRAME, 123, RGB(0x12,0x34,0x56), PS_INSIDEFRAME, 123, RGB(0x12,0x34,0x56) },
56         { PS_USERSTYLE, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
57         { PS_ALTERNATE, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) }
58     };
59     INT i, size;
60     HPEN hpen;
61     LOGPEN lp;
62     EXTLOGPEN elp;
63     LOGBRUSH lb;
64     DWORD obj_type, user_style[2] = { 0xabc, 0xdef };
65     struct
66     {
67         EXTLOGPEN elp;
68         DWORD style_data[10];
69     } ext_pen;
70
71     for (i = 0; i < sizeof(pen)/sizeof(pen[0]); i++)
72     {
73         trace("testing style %u\n", pen[i].style);
74
75         /********************** cosmetic pens **********************/
76         /* CreatePenIndirect behaviour */
77         lp.lopnStyle = pen[i].style,
78         lp.lopnWidth.x = pen[i].width;
79         lp.lopnWidth.y = 11; /* just in case */
80         lp.lopnColor = pen[i].color;
81         SetLastError(0xdeadbeef);
82         hpen = CreatePenIndirect(&lp);
83         ok(hpen != 0, "CreatePen error %d\n", GetLastError());
84
85         obj_type = GetObjectType(hpen);
86         ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type);
87
88         memset(&lp, 0xb0, sizeof(lp));
89         SetLastError(0xdeadbeef);
90         size = GetObject(hpen, sizeof(lp), &lp);
91         ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError());
92
93         ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
94         ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
95         ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
96         ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
97
98         DeleteObject(hpen);
99
100         /* CreatePen behaviour */
101         SetLastError(0xdeadbeef);
102         hpen = CreatePen(pen[i].style, pen[i].width, pen[i].color);
103         ok(hpen != 0, "CreatePen error %d\n", GetLastError());
104
105         obj_type = GetObjectType(hpen);
106         ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type);
107
108         /* check what's the real size of the object */
109         size = GetObject(hpen, 0, NULL);
110         ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError());
111
112         /* ask for truncated data */
113         memset(&lp, 0xb0, sizeof(lp));
114         SetLastError(0xdeadbeef);
115         size = GetObject(hpen, sizeof(lp.lopnStyle), &lp);
116         ok(!size, "GetObject should fail: size %d, error %d\n", size, GetLastError());
117
118         /* see how larger buffer sizes are handled */
119         memset(&lp, 0xb0, sizeof(lp));
120         SetLastError(0xdeadbeef);
121         size = GetObject(hpen, sizeof(lp) * 2, &lp);
122         ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError());
123
124         /* see how larger buffer sizes are handled */
125         memset(&elp, 0xb0, sizeof(elp));
126         SetLastError(0xdeadbeef);
127         size = GetObject(hpen, sizeof(elp) * 2, &elp);
128         ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError());
129
130         memset(&lp, 0xb0, sizeof(lp));
131         SetLastError(0xdeadbeef);
132         size = GetObject(hpen, sizeof(lp), &lp);
133         ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError());
134
135         ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
136         ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
137         ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
138         ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
139
140         memset(&elp, 0xb0, sizeof(elp));
141         SetLastError(0xdeadbeef);
142         size = GetObject(hpen, sizeof(elp), &elp);
143
144         /* for some reason XP differentiates PS_NULL here */
145         if (pen[i].style == PS_NULL)
146         {
147             ok(size == sizeof(EXTLOGPEN), "GetObject returned %d, error %d\n", size, GetLastError());
148             ok(elp.elpPenStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, elp.elpPenStyle);
149             ok(elp.elpWidth == 0, "expected 0, got %u\n", elp.elpWidth);
150             ok(elp.elpColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, elp.elpColor);
151             ok(elp.elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %u\n", elp.elpBrushStyle);
152             ok(elp.elpHatch == 0, "expected 0, got %p\n", (void *)elp.elpHatch);
153             ok(elp.elpNumEntries == 0, "expected 0, got %x\n", elp.elpNumEntries);
154         }
155         else
156         {
157             ok(size == sizeof(LOGPEN), "GetObject returned %d, error %d\n", size, GetLastError());
158             memcpy(&lp, &elp, sizeof(lp));
159             ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
160             ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
161             ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
162             ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
163         }
164
165         DeleteObject(hpen);
166
167         /********** cosmetic pens created by ExtCreatePen ***********/
168         lb.lbStyle = BS_SOLID;
169         lb.lbColor = pen[i].color;
170         lb.lbHatch = HS_CROSS; /* just in case */
171         SetLastError(0xdeadbeef);
172         hpen = ExtCreatePen(pen[i].style, pen[i].width, &lb, 2, user_style);
173         if (pen[i].style != PS_USERSTYLE)
174         {
175             ok(hpen == 0, "ExtCreatePen should fail\n");
176             ok(GetLastError() == ERROR_INVALID_PARAMETER,
177                "wrong last error value %d\n", GetLastError());
178             SetLastError(0xdeadbeef);
179             hpen = ExtCreatePen(pen[i].style, pen[i].width, &lb, 0, NULL);
180             if (pen[i].style != PS_NULL)
181             {
182                 ok(hpen == 0, "ExtCreatePen with width != 1 should fail\n");
183                 ok(GetLastError() == ERROR_INVALID_PARAMETER,
184                    "wrong last error value %d\n", GetLastError());
185
186                 SetLastError(0xdeadbeef);
187                 hpen = ExtCreatePen(pen[i].style, 1, &lb, 0, NULL);
188             }
189         }
190         else
191         {
192             ok(hpen == 0, "ExtCreatePen with width != 1 should fail\n");
193             ok(GetLastError() == ERROR_INVALID_PARAMETER,
194                "wrong last error value %d\n", GetLastError());
195             SetLastError(0xdeadbeef);
196             hpen = ExtCreatePen(pen[i].style, 1, &lb, 2, user_style);
197         }
198         if (pen[i].style == PS_INSIDEFRAME)
199         {
200             /* This style is applicable only for geometric pens */
201             ok(hpen == 0, "ExtCreatePen should fail\n");
202             goto test_geometric_pens;
203         }
204         ok(hpen != 0, "ExtCreatePen error %d\n", GetLastError());
205
206         obj_type = GetObjectType(hpen);
207         /* for some reason XP differentiates PS_NULL here */
208         if (pen[i].style == PS_NULL)
209             ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type);
210         else
211             ok(obj_type == OBJ_EXTPEN, "wrong object type %u\n", obj_type);
212
213         /* check what's the real size of the object */
214         SetLastError(0xdeadbeef);
215         size = GetObject(hpen, 0, NULL);
216         switch (pen[i].style)
217         {
218         case PS_NULL:
219             ok(size == sizeof(LOGPEN),
220                "GetObject returned %d, error %d\n", size, GetLastError());
221             break;
222
223         case PS_USERSTYLE:
224             ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry) + sizeof(user_style),
225                "GetObject returned %d, error %d\n", size, GetLastError());
226             break;
227
228         default:
229             ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry),
230                "GetObject returned %d, error %d\n", size, GetLastError());
231             break;
232         }
233
234         /* ask for truncated data */
235         memset(&elp, 0xb0, sizeof(elp));
236         SetLastError(0xdeadbeef);
237         size = GetObject(hpen, sizeof(elp.elpPenStyle), &elp);
238         ok(!size, "GetObject should fail: size %d, error %d\n", size, GetLastError());
239
240         /* see how larger buffer sizes are handled */
241         memset(&ext_pen, 0xb0, sizeof(ext_pen));
242         SetLastError(0xdeadbeef);
243         size = GetObject(hpen, sizeof(ext_pen), &ext_pen.elp);
244         switch (pen[i].style)
245         {
246         case PS_NULL:
247             ok(size == sizeof(LOGPEN),
248                "GetObject returned %d, error %d\n", size, GetLastError());
249             memcpy(&lp, &ext_pen.elp, sizeof(lp));
250             ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
251             ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
252             ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
253             ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
254
255             /* for PS_NULL it also works this way */
256             memset(&elp, 0xb0, sizeof(elp));
257             SetLastError(0xdeadbeef);
258             size = GetObject(hpen, sizeof(elp), &elp);
259             ok(size == sizeof(EXTLOGPEN),
260                 "GetObject returned %d, error %d\n", size, GetLastError());
261             ok(ext_pen.elp.elpHatch == 0xb0b0b0b0, "expected 0xb0b0b0b0, got %p\n", (void *)ext_pen.elp.elpHatch);
262             ok(ext_pen.elp.elpNumEntries == 0xb0b0b0b0, "expected 0xb0b0b0b0, got %x\n", ext_pen.elp.elpNumEntries);
263             break;
264
265         case PS_USERSTYLE:
266             ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry) + sizeof(user_style),
267                "GetObject returned %d, error %d\n", size, GetLastError());
268             ok(ext_pen.elp.elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen.elp.elpHatch);
269             ok(ext_pen.elp.elpNumEntries == 2, "expected 0, got %x\n", ext_pen.elp.elpNumEntries);
270             ok(ext_pen.elp.elpStyleEntry[0] == 0xabc, "expected 0xabc, got %x\n", ext_pen.elp.elpStyleEntry[0]);
271             ok(ext_pen.elp.elpStyleEntry[1] == 0xdef, "expected 0xabc, got %x\n", ext_pen.elp.elpStyleEntry[1]);
272             break;
273
274         default:
275             ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry),
276                "GetObject returned %d, error %d\n", size, GetLastError());
277             ok(ext_pen.elp.elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen.elp.elpHatch);
278             ok(ext_pen.elp.elpNumEntries == 0, "expected 0, got %x\n", ext_pen.elp.elpNumEntries);
279             break;
280         }
281
282 if (pen[i].style == PS_USERSTYLE)
283 {
284     todo_wine
285         ok(ext_pen.elp.elpPenStyle == pen[i].style, "expected %x, got %x\n", pen[i].style, ext_pen.elp.elpPenStyle);
286 }
287 else
288         ok(ext_pen.elp.elpPenStyle == pen[i].style, "expected %x, got %x\n", pen[i].style, ext_pen.elp.elpPenStyle);
289         ok(ext_pen.elp.elpWidth == 1, "expected 1, got %x\n", ext_pen.elp.elpWidth);
290         ok(ext_pen.elp.elpColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, ext_pen.elp.elpColor);
291         ok(ext_pen.elp.elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %x\n", ext_pen.elp.elpBrushStyle);
292
293         DeleteObject(hpen);
294
295 test_geometric_pens:
296         /********************** geometric pens **********************/
297         lb.lbStyle = BS_SOLID;
298         lb.lbColor = pen[i].color;
299         lb.lbHatch = HS_CROSS; /* just in case */
300         SetLastError(0xdeadbeef);
301         hpen = ExtCreatePen(PS_GEOMETRIC | pen[i].style, pen[i].width, &lb, 2, user_style);
302         if (pen[i].style != PS_USERSTYLE)
303         {
304             ok(hpen == 0, "ExtCreatePen should fail\n");
305             SetLastError(0xdeadbeef);
306             hpen = ExtCreatePen(PS_GEOMETRIC | pen[i].style, pen[i].width, &lb, 0, NULL);
307         }
308         if (pen[i].style == PS_ALTERNATE)
309         {
310             /* This style is applicable only for cosmetic pens */
311             ok(hpen == 0, "ExtCreatePen should fail\n");
312             continue;
313         }
314         ok(hpen != 0, "ExtCreatePen error %d\n", GetLastError());
315
316         obj_type = GetObjectType(hpen);
317         /* for some reason XP differentiates PS_NULL here */
318         if (pen[i].style == PS_NULL)
319             ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type);
320         else
321             ok(obj_type == OBJ_EXTPEN, "wrong object type %u\n", obj_type);
322
323         /* check what's the real size of the object */
324         size = GetObject(hpen, 0, NULL);
325         switch (pen[i].style)
326         {
327         case PS_NULL:
328             ok(size == sizeof(LOGPEN),
329                "GetObject returned %d, error %d\n", size, GetLastError());
330             break;
331
332         case PS_USERSTYLE:
333             ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry) + sizeof(user_style),
334                "GetObject returned %d, error %d\n", size, GetLastError());
335             break;
336
337         default:
338             ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry),
339                "GetObject returned %d, error %d\n", size, GetLastError());
340             break;
341         }
342
343         /* ask for truncated data */
344         memset(&lp, 0xb0, sizeof(lp));
345         SetLastError(0xdeadbeef);
346         size = GetObject(hpen, sizeof(lp.lopnStyle), &lp);
347         ok(!size, "GetObject should fail: size %d, error %d\n", size, GetLastError());
348
349         memset(&lp, 0xb0, sizeof(lp));
350         SetLastError(0xdeadbeef);
351         size = GetObject(hpen, sizeof(lp), &lp);
352         /* for some reason XP differentiates PS_NULL here */
353         if (pen[i].style == PS_NULL)
354         {
355             ok(size == sizeof(LOGPEN), "GetObject returned %d, error %d\n", size, GetLastError());
356             ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
357             ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
358             ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
359             ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
360         }
361         else
362             /* XP doesn't set last error here */
363             ok(!size /*&& GetLastError() == ERROR_INVALID_PARAMETER*/,
364                "GetObject should fail: size %d, error %d\n", size, GetLastError());
365
366         memset(&ext_pen, 0xb0, sizeof(ext_pen));
367         SetLastError(0xdeadbeef);
368         /* buffer is too small for user styles */
369         size = GetObject(hpen, sizeof(elp), &ext_pen.elp);
370         switch (pen[i].style)
371         {
372         case PS_NULL:
373             ok(size == sizeof(EXTLOGPEN),
374                 "GetObject returned %d, error %d\n", size, GetLastError());
375             ok(ext_pen.elp.elpHatch == 0, "expected 0, got %p\n", (void *)ext_pen.elp.elpHatch);
376             ok(ext_pen.elp.elpNumEntries == 0, "expected 0, got %x\n", ext_pen.elp.elpNumEntries);
377
378             /* for PS_NULL it also works this way */
379             SetLastError(0xdeadbeef);
380             size = GetObject(hpen, sizeof(ext_pen), &lp);
381             ok(size == sizeof(LOGPEN),
382                 "GetObject returned %d, error %d\n", size, GetLastError());
383             ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
384             ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
385             ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
386             ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
387             break;
388
389         case PS_USERSTYLE:
390             ok(!size /*&& GetLastError() == ERROR_INVALID_PARAMETER*/,
391                "GetObject should fail: size %d, error %d\n", size, GetLastError());
392             size = GetObject(hpen, sizeof(ext_pen), &ext_pen.elp);
393             ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry) + sizeof(user_style),
394                "GetObject returned %d, error %d\n", size, GetLastError());
395             ok(ext_pen.elp.elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen.elp.elpHatch);
396             ok(ext_pen.elp.elpNumEntries == 2, "expected 0, got %x\n", ext_pen.elp.elpNumEntries);
397             ok(ext_pen.elp.elpStyleEntry[0] == 0xabc, "expected 0xabc, got %x\n", ext_pen.elp.elpStyleEntry[0]);
398             ok(ext_pen.elp.elpStyleEntry[1] == 0xdef, "expected 0xabc, got %x\n", ext_pen.elp.elpStyleEntry[1]);
399             break;
400
401         default:
402             ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry),
403                "GetObject returned %d, error %d\n", size, GetLastError());
404             ok(ext_pen.elp.elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen.elp.elpHatch);
405             ok(ext_pen.elp.elpNumEntries == 0, "expected 0, got %x\n", ext_pen.elp.elpNumEntries);
406             break;
407         }
408
409         /* for some reason XP differentiates PS_NULL here */
410         if (pen[i].style == PS_NULL)
411             ok(ext_pen.elp.elpPenStyle == pen[i].ret_style, "expected %x, got %x\n", pen[i].ret_style, ext_pen.elp.elpPenStyle);
412         else
413         {
414             ok(ext_pen.elp.elpPenStyle == (PS_GEOMETRIC | pen[i].style), "expected %x, got %x\n", PS_GEOMETRIC | pen[i].style, ext_pen.elp.elpPenStyle);
415         }
416
417         if (pen[i].style == PS_NULL)
418             ok(ext_pen.elp.elpWidth == 0, "expected 0, got %x\n", ext_pen.elp.elpWidth);
419         else
420             ok(ext_pen.elp.elpWidth == pen[i].ret_width, "expected %u, got %x\n", pen[i].ret_width, ext_pen.elp.elpWidth);
421         ok(ext_pen.elp.elpColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, ext_pen.elp.elpColor);
422         ok(ext_pen.elp.elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %x\n", ext_pen.elp.elpBrushStyle);
423
424         DeleteObject(hpen);
425     }
426 }
427
428 static unsigned int atoi2(const char *s)
429 {
430     unsigned int ret = 0;
431     while(*s) ret = (ret << 1) | (*s++ == '1');
432     return ret;
433 }
434
435 #define TEST_LINE(x1, x2, z) \
436     { int buf = 0; \
437       SetBitmapBits(bmp, sizeof(buf), &buf); \
438       MoveToEx(hdc, x1, 0, NULL); \
439       LineTo(hdc, x2, 0); \
440       GetBitmapBits(bmp, sizeof(buf), &buf); \
441       expect(atoi2(z), buf); }
442
443 static void test_ps_alternate(void)
444 {
445     HDC hdc;
446     HBITMAP bmp;
447     HPEN pen;
448     LOGBRUSH lb;
449
450     lb.lbStyle = BS_SOLID;
451     lb.lbColor = RGB(0xff,0xff,0xff);
452
453     SetLastError(0xdeadbeef);
454     pen = ExtCreatePen(PS_COSMETIC|PS_ALTERNATE, 1, &lb, 0, NULL);
455     if(pen == NULL && GetLastError() == 0xdeadbeef) {
456         skip("looks like 9x, skipping PS_ALTERNATE tests\n");
457         return;
458     }
459     ok(pen != NULL, "gle=%d\n", GetLastError());
460     hdc = CreateCompatibleDC(NULL);
461     ok(hdc != NULL, "gle=%d\n", GetLastError());
462     bmp = CreateBitmap(8, 1, 1, 1, NULL);
463     ok(bmp != NULL, "gle=%d\n", GetLastError());
464     ok(SelectObject(hdc, bmp) != NULL, "gle=%d\n", GetLastError());
465     ok(SelectObject(hdc, pen) != NULL, "gle=%d\n", GetLastError());
466     ok(SetBkMode(hdc, TRANSPARENT), "gle=%d\n", GetLastError());
467
468     TEST_LINE(0, 1, "10000000")
469     TEST_LINE(0, 2, "10000000")
470     TEST_LINE(0, 3, "10100000")
471     TEST_LINE(0, 4, "10100000")
472     TEST_LINE(1, 4, "01010000")
473     TEST_LINE(1, 5, "01010000")
474     TEST_LINE(4, 8, "00001010")
475
476     DeleteObject(pen);
477     DeleteObject(bmp);
478     DeleteDC(hdc);
479 }
480
481 static void test_ps_userstyle(void)
482 {
483     static DWORD style[17] = {0, 2, 0, 4, 5, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 17};
484     static DWORD bad_style[5] = {0, 0, 0, 0, 0};
485     static DWORD bad_style2[5] = {4, 7, 8, 3, -1};
486
487     LOGBRUSH lb;
488     HPEN pen;
489     INT size, i;
490
491     struct
492     {
493         EXTLOGPEN elp;
494         DWORD style_data[15];
495     } ext_pen;
496
497     lb.lbColor = 0x00ff0000;
498     lb.lbStyle = BS_SOLID;
499     lb.lbHatch = 0;
500
501     pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 3, NULL);
502     ok(pen == 0, "ExtCreatePen should fail\n");
503     expect(ERROR_INVALID_PARAMETER, GetLastError());
504     DeleteObject(pen);
505     SetLastError(0xdeadbeef);
506
507     pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 0, style);
508     ok(pen == 0, "ExtCreatePen should fail\n");
509     expect2(0xdeadbeef, ERROR_INVALID_PARAMETER, GetLastError());
510     DeleteObject(pen);
511     SetLastError(0xdeadbeef);
512
513     pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 17, style);
514     ok(pen == 0, "ExtCreatePen should fail\n");
515     expect(ERROR_INVALID_PARAMETER, GetLastError());
516     DeleteObject(pen);
517     SetLastError(0xdeadbeef);
518
519     pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, -1, style);
520     ok(pen == 0, "ExtCreatePen should fail\n");
521     expect(0xdeadbeef, GetLastError());
522     DeleteObject(pen);
523     SetLastError(0xdeadbeef);
524
525     pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 5, bad_style);
526     ok(pen == 0, "ExtCreatePen should fail\n");
527     expect(ERROR_INVALID_PARAMETER, GetLastError());
528     DeleteObject(pen);
529     SetLastError(0xdeadbeef);
530
531     pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 5, bad_style2);
532     ok(pen == 0, "ExtCreatePen should fail\n");
533     expect(ERROR_INVALID_PARAMETER, GetLastError());
534     DeleteObject(pen);
535     SetLastError(0xdeadbeef);
536
537     pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 16, style);
538     ok(pen != 0, "ExtCreatePen should not fail\n");
539
540     size = GetObject(pen, sizeof(ext_pen), &ext_pen);
541     expect(88, size);
542
543     for(i = 0; i < 16; i++)
544         expect(style[i], ext_pen.elp.elpStyleEntry[i]);
545
546     DeleteObject(pen);
547 }
548
549 START_TEST(pen)
550 {
551     test_logpen();
552     test_ps_alternate();
553     test_ps_userstyle();
554 }