ReactOS  0.4.14-dev-98-gb0d4763
pen.c
Go to the documentation of this file.
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 
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "winuser.h"
27 
28 #include "wine/test.h"
29 
30 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
31 #define expect2(expected, alt, got) ok(got == expected || got == alt, \
32  "Expected %.8x or %.8x, got %.8x\n", expected, alt, got)
33 
34 static void test_logpen(void)
35 {
36  static const struct
37  {
38  UINT style;
39  INT width;
41  UINT ret_style;
42  INT ret_width;
43  COLORREF ret_color;
44  } pen[] = {
45  { PS_SOLID, -123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
46  { PS_SOLID, 0, RGB(0x12,0x34,0x56), PS_SOLID, 0, RGB(0x12,0x34,0x56) },
47  { PS_SOLID, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
48  { PS_DASH, 123, RGB(0x12,0x34,0x56), PS_DASH, 123, RGB(0x12,0x34,0x56) },
49  { PS_DOT, 123, RGB(0x12,0x34,0x56), PS_DOT, 123, RGB(0x12,0x34,0x56) },
50  { PS_DASHDOT, 123, RGB(0x12,0x34,0x56), PS_DASHDOT, 123, RGB(0x12,0x34,0x56) },
51  { PS_DASHDOTDOT, 123, RGB(0x12,0x34,0x56), PS_DASHDOTDOT, 123, RGB(0x12,0x34,0x56) },
52  { PS_NULL, -123, RGB(0x12,0x34,0x56), PS_NULL, 1, 0 },
53  { PS_NULL, 123, RGB(0x12,0x34,0x56), PS_NULL, 1, 0 },
54  { PS_INSIDEFRAME, 123, RGB(0x12,0x34,0x56), PS_INSIDEFRAME, 123, RGB(0x12,0x34,0x56) },
55  { PS_USERSTYLE, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
56  { PS_ALTERNATE, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
57  { 9, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
58  { 10, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
59  { 11, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
60  { 13, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
61  { 14, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
62  { 15, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
63  };
64  INT i, size;
65  HPEN hpen;
66  LOGPEN lp;
67  EXTLOGPEN elp;
68  LOGBRUSH lb;
69  DWORD_PTR unset_hatch;
70  DWORD obj_type, user_style[2] = { 0xabc, 0xdef };
71  char elp_buffer[128];
72  EXTLOGPEN *ext_pen = (EXTLOGPEN *)elp_buffer;
73  DWORD *ext_style = ext_pen->elpStyleEntry;
74 
75  for (i = 0; i < sizeof(pen)/sizeof(pen[0]); i++)
76  {
77  trace("%d: testing style %u\n", i, pen[i].style);
78 
79  /********************** cosmetic pens **********************/
80  /* CreatePenIndirect behaviour */
81  lp.lopnStyle = pen[i].style,
82  lp.lopnWidth.x = pen[i].width;
83  lp.lopnWidth.y = 11; /* just in case */
84  lp.lopnColor = pen[i].color;
85  SetLastError(0xdeadbeef);
86  hpen = CreatePenIndirect(&lp);
88  {
89  win_skip("No support for pen style %u (%d)\n", pen[i].style, i);
90  continue;
91  }
92 
93  obj_type = GetObjectType(hpen);
94  ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type);
95 
96  memset(&lp, 0xb0, sizeof(lp));
97  SetLastError(0xdeadbeef);
98  size = GetObjectW(hpen, sizeof(lp), &lp);
99  ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError());
100 
101  ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
102  ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
103  ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
104  ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
105 
107 
108  /* CreatePen behaviour */
109  SetLastError(0xdeadbeef);
110  hpen = CreatePen(pen[i].style, pen[i].width, pen[i].color);
111  ok(hpen != 0, "CreatePen error %d\n", GetLastError());
112 
113  obj_type = GetObjectType(hpen);
114  ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type);
115 
116  /* check what's the real size of the object */
117  size = GetObjectW(hpen, 0, NULL);
118  ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError());
119 
120  /* ask for truncated data */
121  memset(&lp, 0xb0, sizeof(lp));
122  SetLastError(0xdeadbeef);
123  size = GetObjectW(hpen, sizeof(lp.lopnStyle), &lp);
124  ok(!size, "GetObject should fail: size %d, error %d\n", size, GetLastError());
125 
126  /* see how larger buffer sizes are handled */
127  memset(&lp, 0xb0, sizeof(lp));
128  SetLastError(0xdeadbeef);
129  size = GetObjectW(hpen, sizeof(lp) * 4, &lp);
130  ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError());
131 
132  /* see how larger buffer sizes are handled */
133  memset(&elp, 0xb0, sizeof(elp));
134  SetLastError(0xdeadbeef);
135  size = GetObjectW(hpen, sizeof(elp) * 2, &elp);
136  ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError());
137 
138  memset(&lp, 0xb0, sizeof(lp));
139  SetLastError(0xdeadbeef);
140  size = GetObjectW(hpen, sizeof(lp), &lp);
141  ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError());
142 
143  ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
144  ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
145  ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
146  ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
147 
148  memset(&elp, 0xb0, sizeof(elp));
149  SetLastError(0xdeadbeef);
150  size = GetObjectW(hpen, sizeof(elp), &elp);
151 
152  /* for some reason XP differentiates PS_NULL here */
153  if (pen[i].style == PS_NULL)
154  {
155  ok(hpen == GetStockObject(NULL_PEN), "hpen should be a stock NULL_PEN\n");
156  ok(size == offsetof(EXTLOGPEN, elpStyleEntry[1]), "GetObject returned %d, error %d\n",
157  size, GetLastError());
158  ok(elp.elpPenStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, elp.elpPenStyle);
159  ok(elp.elpWidth == 0, "expected 0, got %u\n", elp.elpWidth);
160  ok(elp.elpColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, elp.elpColor);
161  ok(elp.elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %u\n", elp.elpBrushStyle);
162  ok(elp.elpHatch == 0, "expected 0, got %p\n", (void *)elp.elpHatch);
163  ok(elp.elpNumEntries == 0, "expected 0, got %x\n", elp.elpNumEntries);
164  }
165  else
166  {
167  ok(size == sizeof(LOGPEN), "GetObject returned %d, error %d\n", size, GetLastError());
168  memcpy(&lp, &elp, sizeof(lp));
169  ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
170  ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
171  ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
172  ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
173  }
174 
176 
177  /********** cosmetic pens created by ExtCreatePen ***********/
178  lb.lbStyle = BS_SOLID;
179  lb.lbColor = pen[i].color;
180  lb.lbHatch = HS_CROSS; /* just in case */
181  SetLastError(0xdeadbeef);
182  hpen = ExtCreatePen(pen[i].style, pen[i].width, &lb, 2, user_style);
183  if (pen[i].style != PS_USERSTYLE)
184  {
185  ok(hpen == 0, "ExtCreatePen should fail\n");
187  "wrong last error value %d\n", GetLastError());
188  SetLastError(0xdeadbeef);
189  hpen = ExtCreatePen(pen[i].style, pen[i].width, &lb, 0, NULL);
190  if (pen[i].style != PS_NULL)
191  {
192  ok(hpen == 0, "ExtCreatePen with width != 1 should fail\n");
194  "wrong last error value %d\n", GetLastError());
195 
196  SetLastError(0xdeadbeef);
197  hpen = ExtCreatePen(pen[i].style, 1, &lb, 0, NULL);
198  }
199  }
200  else
201  {
202  ok(hpen == 0, "ExtCreatePen with width != 1 should fail\n");
204  "wrong last error value %d\n", GetLastError());
205  SetLastError(0xdeadbeef);
206  hpen = ExtCreatePen(pen[i].style, 1, &lb, 2, user_style);
207  }
208  if (pen[i].style == PS_INSIDEFRAME)
209  {
210  /* This style is applicable only for geometric pens */
211  ok(hpen == 0, "ExtCreatePen should fail\n");
212  goto test_geometric_pens;
213  }
214  if (pen[i].style > PS_ALTERNATE)
215  {
216  ok(hpen == 0, "ExtCreatePen should fail\n");
217  ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong last error value %d\n", GetLastError());
218  goto test_geometric_pens;
219  }
220  ok(hpen != 0, "ExtCreatePen error %d\n", GetLastError());
221 
222  obj_type = GetObjectType(hpen);
223  /* for some reason XP differentiates PS_NULL here */
224  if (pen[i].style == PS_NULL)
225  {
226  ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type);
227  ok(hpen == GetStockObject(NULL_PEN), "hpen should be a stock NULL_PEN\n");
228  }
229  else
230  ok(obj_type == OBJ_EXTPEN, "wrong object type %u\n", obj_type);
231 
232  /* check what's the real size of the object */
233  SetLastError(0xdeadbeef);
234  size = GetObjectW(hpen, 0, NULL);
235  switch (pen[i].style)
236  {
237  case PS_NULL:
238  ok(size == sizeof(LOGPEN),
239  "GetObject returned %d, error %d\n", size, GetLastError());
240  break;
241 
242  case PS_USERSTYLE:
243  ok(size == offsetof( EXTLOGPEN, elpStyleEntry[2] ),
244  "GetObject returned %d, error %d\n", size, GetLastError());
245  break;
246 
247  default:
248  ok(size == offsetof( EXTLOGPEN, elpStyleEntry ),
249  "GetObject returned %d, error %d\n", size, GetLastError());
250  break;
251  }
252 
253  /* ask for truncated data */
254  memset(&elp, 0xb0, sizeof(elp));
255  SetLastError(0xdeadbeef);
256  size = GetObjectW(hpen, sizeof(elp.elpPenStyle), &elp);
257  ok(!size, "GetObject should fail: size %d, error %d\n", size, GetLastError());
258 
259  /* see how larger buffer sizes are handled */
260  memset(elp_buffer, 0xb0, sizeof(elp_buffer));
261  SetLastError(0xdeadbeef);
262  size = GetObjectW(hpen, sizeof(elp_buffer), elp_buffer);
263  switch (pen[i].style)
264  {
265  case PS_NULL:
266  ok(size == sizeof(LOGPEN),
267  "GetObject returned %d, error %d\n", size, GetLastError());
268  memcpy(&lp, ext_pen, sizeof(lp));
269  ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
270  ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
271  ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
272  ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
273 
274  /* for PS_NULL it also works this way */
275  memset(&elp, 0xb0, sizeof(elp));
276  memset(&unset_hatch, 0xb0, sizeof(unset_hatch));
277  SetLastError(0xdeadbeef);
278  size = GetObjectW(hpen, sizeof(elp), &elp);
279  ok(size == offsetof(EXTLOGPEN, elpStyleEntry[1]),
280  "GetObject returned %d, error %d\n", size, GetLastError());
281  ok(ext_pen->elpHatch == unset_hatch, "expected 0xb0b0b0b0, got %p\n", (void *)ext_pen->elpHatch);
282  ok(ext_pen->elpNumEntries == 0xb0b0b0b0, "expected 0xb0b0b0b0, got %x\n", ext_pen->elpNumEntries);
283  break;
284 
285  case PS_USERSTYLE:
286  ok(size == offsetof( EXTLOGPEN, elpStyleEntry[2] ),
287  "GetObject returned %d, error %d\n", size, GetLastError());
288  ok(ext_pen->elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen->elpHatch);
289  ok(ext_pen->elpNumEntries == 2, "expected 0, got %x\n", ext_pen->elpNumEntries);
290  ok(ext_style[0] == 0xabc, "expected 0xabc, got %x\n", ext_style[0]);
291  ok(ext_style[1] == 0xdef, "expected 0xdef, got %x\n", ext_style[1]);
292  break;
293 
294  default:
295  ok(size == offsetof( EXTLOGPEN, elpStyleEntry ),
296  "GetObject returned %d, error %d\n", size, GetLastError());
297  ok(ext_pen->elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen->elpHatch);
298  ok(ext_pen->elpNumEntries == 0, "expected 0, got %x\n", ext_pen->elpNumEntries);
299  break;
300  }
301 
302  ok(ext_pen->elpPenStyle == pen[i].style, "expected %x, got %x\n", pen[i].style, ext_pen->elpPenStyle);
303  ok(ext_pen->elpWidth == 1, "expected 1, got %x\n", ext_pen->elpWidth);
304  ok(ext_pen->elpColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, ext_pen->elpColor);
305  ok(ext_pen->elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %x\n", ext_pen->elpBrushStyle);
306 
308 
309 test_geometric_pens:
310  /********************** geometric pens **********************/
311  lb.lbStyle = BS_SOLID;
312  lb.lbColor = pen[i].color;
313  lb.lbHatch = HS_CROSS; /* just in case */
314  SetLastError(0xdeadbeef);
315  hpen = ExtCreatePen(PS_GEOMETRIC | pen[i].style, pen[i].width, &lb, 2, user_style);
316  if (pen[i].style != PS_USERSTYLE)
317  {
318  ok(hpen == 0, "ExtCreatePen should fail\n");
319  SetLastError(0xdeadbeef);
320  hpen = ExtCreatePen(PS_GEOMETRIC | pen[i].style, pen[i].width, &lb, 0, NULL);
321  }
322  if (pen[i].style == PS_ALTERNATE)
323  {
324  /* This style is applicable only for cosmetic pens */
325  ok(hpen == 0, "ExtCreatePen should fail\n");
326  continue;
327  }
328  if (pen[i].style > PS_ALTERNATE)
329  {
330  ok(hpen == 0, "ExtCreatePen should fail\n");
331  ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong last error value %d\n", GetLastError());
332  continue;
333  }
334  ok(hpen != 0, "ExtCreatePen error %d\n", GetLastError());
335 
336  obj_type = GetObjectType(hpen);
337  /* for some reason XP differentiates PS_NULL here */
338  if (pen[i].style == PS_NULL)
339  ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type);
340  else
341  ok(obj_type == OBJ_EXTPEN, "wrong object type %u\n", obj_type);
342 
343  /* check what's the real size of the object */
344  size = GetObjectW(hpen, 0, NULL);
345  switch (pen[i].style)
346  {
347  case PS_NULL:
348  ok(size == sizeof(LOGPEN),
349  "GetObject returned %d, error %d\n", size, GetLastError());
350  break;
351 
352  case PS_USERSTYLE:
353  ok(size == offsetof( EXTLOGPEN, elpStyleEntry[2] ),
354  "GetObject returned %d, error %d\n", size, GetLastError());
355  break;
356 
357  default:
358  ok(size == offsetof( EXTLOGPEN, elpStyleEntry ),
359  "GetObject returned %d, error %d\n", size, GetLastError());
360  break;
361  }
362 
363  /* ask for truncated data */
364  memset(&lp, 0xb0, sizeof(lp));
365  SetLastError(0xdeadbeef);
366  size = GetObjectW(hpen, sizeof(lp.lopnStyle), &lp);
367  ok(!size, "GetObject should fail: size %d, error %d\n", size, GetLastError());
368 
369  memset(&lp, 0xb0, sizeof(lp));
370  SetLastError(0xdeadbeef);
371  size = GetObjectW(hpen, sizeof(lp), &lp);
372  /* for some reason XP differentiates PS_NULL here */
373  if (pen[i].style == PS_NULL)
374  {
375  ok(size == sizeof(LOGPEN), "GetObject returned %d, error %d\n", size, GetLastError());
376  ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
377  ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
378  ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
379  ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
380  }
381  else
382  /* XP doesn't set last error here */
383  ok(!size /*&& GetLastError() == ERROR_INVALID_PARAMETER*/,
384  "GetObject should fail: size %d, error %d\n", size, GetLastError());
385 
386  memset(elp_buffer, 0xb0, sizeof(elp_buffer));
387  SetLastError(0xdeadbeef);
388  /* buffer is too small for user styles */
389  size = GetObjectW(hpen, offsetof(EXTLOGPEN, elpStyleEntry[1]), elp_buffer);
390  switch (pen[i].style)
391  {
392  case PS_NULL:
393  ok(size == offsetof(EXTLOGPEN, elpStyleEntry[1]),
394  "GetObject returned %d, error %d\n", size, GetLastError());
395  ok(ext_pen->elpHatch == 0, "expected 0, got %p\n", (void *)ext_pen->elpHatch);
396  ok(ext_pen->elpNumEntries == 0, "expected 0, got %x\n", ext_pen->elpNumEntries);
397 
398  /* for PS_NULL it also works this way */
399  SetLastError(0xdeadbeef);
400  size = GetObjectW(hpen, sizeof(elp_buffer), &lp);
401  ok(size == sizeof(LOGPEN),
402  "GetObject returned %d, error %d\n", size, GetLastError());
403  ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
404  ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
405  ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
406  ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
407  break;
408 
409  case PS_USERSTYLE:
410  ok(!size /*&& GetLastError() == ERROR_INVALID_PARAMETER*/,
411  "GetObject should fail: size %d, error %d\n", size, GetLastError());
412  size = GetObjectW(hpen, sizeof(elp_buffer), elp_buffer);
413  ok(size == offsetof( EXTLOGPEN, elpStyleEntry[2] ),
414  "GetObject returned %d, error %d\n", size, GetLastError());
415  ok(ext_pen->elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen->elpHatch);
416  ok(ext_pen->elpNumEntries == 2, "expected 0, got %x\n", ext_pen->elpNumEntries);
417  ok(ext_style[0] == 0xabc, "expected 0xabc, got %x\n", ext_style[0]);
418  ok(ext_style[1] == 0xdef, "expected 0xdef, got %x\n", ext_style[1]);
419  break;
420 
421  default:
422  ok(size == offsetof( EXTLOGPEN, elpStyleEntry ),
423  "GetObject returned %d, error %d\n", size, GetLastError());
424  ok(ext_pen->elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen->elpHatch);
425  ok(ext_pen->elpNumEntries == 0, "expected 0, got %x\n", ext_pen->elpNumEntries);
426  break;
427  }
428 
429  /* for some reason XP differentiates PS_NULL here */
430  if (pen[i].style == PS_NULL)
431  ok(ext_pen->elpPenStyle == pen[i].ret_style, "expected %x, got %x\n", pen[i].ret_style, ext_pen->elpPenStyle);
432  else
433  {
434  ok(ext_pen->elpPenStyle == (PS_GEOMETRIC | pen[i].style), "expected %x, got %x\n", PS_GEOMETRIC | pen[i].style, ext_pen->elpPenStyle);
435  }
436 
437  if (pen[i].style == PS_NULL)
438  ok(ext_pen->elpWidth == 0, "expected 0, got %x\n", ext_pen->elpWidth);
439  else
440  ok(ext_pen->elpWidth == pen[i].ret_width, "expected %u, got %x\n", pen[i].ret_width, ext_pen->elpWidth);
441  ok(ext_pen->elpColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, ext_pen->elpColor);
442  ok(ext_pen->elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %x\n", ext_pen->elpBrushStyle);
443 
445  }
446 }
447 
448 static unsigned int atoi2(const char *s)
449 {
450  unsigned int ret = 0;
451  while(*s) ret = (ret << 1) | (*s++ == '1');
452  return ret;
453 }
454 
455 #define TEST_LINE(x1, x2, z) \
456  { int buf = 0; \
457  SetBitmapBits(bmp, sizeof(buf), &buf); \
458  MoveToEx(hdc, x1, 0, NULL); \
459  LineTo(hdc, x2, 0); \
460  GetBitmapBits(bmp, sizeof(buf), &buf); \
461  expect(atoi2(z), buf); }
462 
463 static void test_ps_alternate(void)
464 {
465  HDC hdc;
466  HBITMAP bmp;
467  HPEN pen;
468  LOGBRUSH lb;
469  INT iRet;
470  HGDIOBJ hRet;
471 
472  lb.lbStyle = BS_SOLID;
473  lb.lbColor = RGB(0xff,0xff,0xff);
474 
475  SetLastError(0xdeadbeef);
476  pen = ExtCreatePen(PS_COSMETIC|PS_ALTERNATE, 1, &lb, 0, NULL);
477  if(pen == NULL && GetLastError() == 0xdeadbeef) {
478  skip("looks like 9x, skipping PS_ALTERNATE tests\n");
479  return;
480  }
481  ok(pen != NULL, "gle=%d\n", GetLastError());
483  ok(hdc != NULL, "gle=%d\n", GetLastError());
484  bmp = CreateBitmap(8, 1, 1, 1, NULL);
485  ok(bmp != NULL, "gle=%d\n", GetLastError());
486  hRet = SelectObject(hdc, bmp);
487  ok(hRet != NULL, "gle=%d\n", GetLastError());
488  hRet = SelectObject(hdc, pen);
489  ok(hRet != NULL, "gle=%d\n", GetLastError());
490  iRet = SetBkMode(hdc, TRANSPARENT);
491  ok(iRet, "gle=%d\n", GetLastError());
492 
493  TEST_LINE(0, 1, "10000000")
494  TEST_LINE(0, 2, "10000000")
495  TEST_LINE(0, 3, "10100000")
496  TEST_LINE(0, 4, "10100000")
497  TEST_LINE(1, 4, "01010000")
498  TEST_LINE(1, 5, "01010000")
499  TEST_LINE(4, 8, "00001010")
500 
501  DeleteObject(pen);
502  DeleteObject(bmp);
503  DeleteDC(hdc);
504 }
505 
506 static void test_ps_userstyle(void)
507 {
508  static DWORD style[17] = {0, 2, 0, 4, 5, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 17};
509  static DWORD bad_style[5] = {0, 0, 0, 0, 0};
510  static DWORD bad_style2[5] = {4, 7, 8, 3, -1};
511 
512  LOGBRUSH lb;
513  HPEN pen;
514  INT size, i;
515  char buffer[offsetof(EXTLOGPEN, elpStyleEntry) + 16 * sizeof(DWORD)];
516  EXTLOGPEN *ext_pen = (EXTLOGPEN *)buffer;
517 
518  lb.lbColor = 0x00ff0000;
519  lb.lbStyle = BS_SOLID;
520  lb.lbHatch = 0;
521 
522  pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 3, NULL);
523  ok(pen == 0, "ExtCreatePen should fail\n");
525  DeleteObject(pen);
526  SetLastError(0xdeadbeef);
527 
528  pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 0, style);
529  ok(pen == 0, "ExtCreatePen should fail\n");
531  DeleteObject(pen);
532  SetLastError(0xdeadbeef);
533 
534  pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 17, style);
535  ok(pen == 0, "ExtCreatePen should fail\n");
537  DeleteObject(pen);
538  SetLastError(0xdeadbeef);
539 
540  pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, -1, style);
541  ok(pen == 0, "ExtCreatePen should fail\n");
542  expect(0xdeadbeef, GetLastError());
543  DeleteObject(pen);
544  SetLastError(0xdeadbeef);
545 
546  pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 5, bad_style);
547  ok(pen == 0, "ExtCreatePen should fail\n");
549  DeleteObject(pen);
550  SetLastError(0xdeadbeef);
551 
552  pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 5, bad_style2);
553  ok(pen == 0, "ExtCreatePen should fail\n");
555  DeleteObject(pen);
556  SetLastError(0xdeadbeef);
557 
558  pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 16, style);
559  ok(pen != 0, "ExtCreatePen should not fail\n");
560 
561  size = GetObjectW(pen, sizeof(buffer), ext_pen);
562  ok(size == offsetof(EXTLOGPEN, elpStyleEntry[16]), "wrong size %d\n", size);
563 
564  for(i = 0; i < 16; i++)
565  expect(style[i], ext_pen->elpStyleEntry[i]);
566 
567  DeleteObject(pen);
568 }
569 
570 static void test_brush_pens(void)
571 {
572  char buffer[offsetof(EXTLOGPEN, elpStyleEntry) + 16 * sizeof(DWORD)];
573  EXTLOGPEN *elp = (EXTLOGPEN *)buffer;
574  LOGBRUSH lb;
575  HPEN pen = 0;
576  DWORD size;
577  HBITMAP bmp = CreateBitmap( 8, 8, 1, 1, NULL );
578  BITMAPINFO *info;
579  HGLOBAL hmem;
580 
581  hmem = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(*info) + 16 * 16 * 4 );
582  info = GlobalLock( hmem );
583  info->bmiHeader.biSize = sizeof(info->bmiHeader);
584  info->bmiHeader.biWidth = 16;
585  info->bmiHeader.biHeight = 16;
586  info->bmiHeader.biPlanes = 1;
587  info->bmiHeader.biBitCount = 32;
588  info->bmiHeader.biCompression = BI_RGB;
589 
590  for (lb.lbStyle = BS_SOLID; lb.lbStyle <= BS_MONOPATTERN + 1; lb.lbStyle++)
591  {
592  SetLastError( 0xdeadbeef );
593  memset( buffer, 0xcc, sizeof(buffer) );
594  trace( "testing brush style %u\n", lb.lbStyle );
595 
596  switch (lb.lbStyle)
597  {
598  case BS_SOLID:
599  case BS_HATCHED:
600  lb.lbColor = RGB(12,34,56);
601  lb.lbHatch = HS_CROSS;
602  pen = ExtCreatePen( PS_DOT | PS_GEOMETRIC, 3, &lb, 0, NULL );
603  ok( pen != 0, "ExtCreatePen failed err %u\n", GetLastError() );
604  size = GetObjectW( pen, sizeof(buffer), elp );
605  ok( size == offsetof( EXTLOGPEN, elpStyleEntry ), "wrong size %u\n", size );
606  ok( elp->elpPenStyle == (PS_DOT | PS_GEOMETRIC), "wrong pen style %x\n", elp->elpPenStyle );
607  ok( elp->elpBrushStyle == lb.lbStyle, "wrong brush style %x\n", elp->elpBrushStyle );
608  ok( elp->elpColor == RGB(12,34,56), "wrong color %x\n", elp->elpColor );
609  ok( elp->elpHatch == HS_CROSS, "wrong hatch %lx\n", elp->elpHatch );
610  ok( elp->elpNumEntries == 0, "wrong entries %x\n", elp->elpNumEntries );
611  break;
612 
613  case BS_NULL:
614  pen = ExtCreatePen( PS_SOLID | PS_GEOMETRIC, 3, &lb, 0, NULL );
615  ok( pen != 0, "ExtCreatePen failed err %u\n", GetLastError() );
616  size = GetObjectW( pen, sizeof(buffer), elp );
617  ok( size == sizeof(LOGPEN), "wrong size %u\n", size );
618  ok( ((LOGPEN *)elp)->lopnStyle == PS_NULL,
619  "wrong pen style %x\n", ((LOGPEN *)elp)->lopnStyle );
620  ok( ((LOGPEN *)elp)->lopnColor == 0,
621  "wrong color %x\n", ((LOGPEN *)elp)->lopnColor );
622  break;
623 
624  case BS_PATTERN:
625  lb.lbColor = RGB(12,34,56);
626  lb.lbHatch = (ULONG_PTR)bmp;
627  pen = ExtCreatePen( PS_DOT | PS_GEOMETRIC, 3, &lb, 0, NULL );
628  ok( pen != 0, "ExtCreatePen failed err %u\n", GetLastError() );
629  size = GetObjectW( pen, sizeof(buffer), elp );
630  ok( size == offsetof( EXTLOGPEN, elpStyleEntry ), "wrong size %u\n", size );
631  ok( elp->elpPenStyle == (PS_DOT | PS_GEOMETRIC), "wrong pen style %x\n", elp->elpPenStyle );
632  ok( elp->elpBrushStyle == BS_PATTERN, "wrong brush style %x\n", elp->elpBrushStyle );
633  ok( elp->elpColor == 0, "wrong color %x\n", elp->elpColor );
634  ok( elp->elpHatch == (ULONG_PTR)bmp, "wrong hatch %lx/%p\n", elp->elpHatch, bmp );
635  ok( elp->elpNumEntries == 0, "wrong entries %x\n", elp->elpNumEntries );
636  break;
637 
638  case BS_DIBPATTERN:
639  case BS_DIBPATTERNPT:
640  lb.lbColor = DIB_PAL_COLORS;
641  lb.lbHatch = lb.lbStyle == BS_DIBPATTERN ? (ULONG_PTR)hmem : (ULONG_PTR)info;
642  pen = ExtCreatePen( PS_DOT | PS_GEOMETRIC, 3, &lb, 0, NULL );
643  ok( pen != 0, "ExtCreatePen failed err %u\n", GetLastError() );
644  size = GetObjectW( pen, sizeof(buffer), elp );
645  ok( size == offsetof( EXTLOGPEN, elpStyleEntry ), "wrong size %u\n", size );
646  ok( elp->elpPenStyle == (PS_DOT | PS_GEOMETRIC), "wrong pen style %x\n", elp->elpPenStyle );
647  ok( elp->elpBrushStyle == BS_DIBPATTERNPT, "wrong brush style %x\n", elp->elpBrushStyle );
648  ok( elp->elpColor == 0, "wrong color %x\n", elp->elpColor );
649  ok( elp->elpHatch == lb.lbHatch || broken(elp->elpHatch != lb.lbHatch), /* <= w2k */
650  "wrong hatch %lx/%lx\n", elp->elpHatch, lb.lbHatch );
651  ok( elp->elpNumEntries == 0, "wrong entries %x\n", elp->elpNumEntries );
652  break;
653 
654  default:
655  pen = ExtCreatePen( PS_DOT | PS_GEOMETRIC, 3, &lb, 0, NULL );
656  ok( !pen, "ExtCreatePen succeeded\n" );
657  ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
658  break;
659  }
660 
661  if (pen) DeleteObject( pen );
662  else continue;
663 
664  /* cosmetic pens require BS_SOLID */
665  SetLastError( 0xdeadbeef );
666  pen = ExtCreatePen( PS_DOT, 1, &lb, 0, NULL );
667  if (lb.lbStyle == BS_SOLID)
668  {
669  ok( pen != 0, "ExtCreatePen failed err %u\n", GetLastError() );
670  size = GetObjectW( pen, sizeof(buffer), elp );
671  ok( size == offsetof( EXTLOGPEN, elpStyleEntry ), "wrong size %u\n", size );
672  ok( elp->elpPenStyle == PS_DOT, "wrong pen style %x\n", elp->elpPenStyle );
673  ok( elp->elpBrushStyle == BS_SOLID, "wrong brush style %x\n", elp->elpBrushStyle );
674  ok( elp->elpColor == RGB(12,34,56), "wrong color %x\n", elp->elpColor );
675  ok( elp->elpHatch == HS_CROSS, "wrong hatch %lx\n", elp->elpHatch );
676  DeleteObject( pen );
677  }
678  else
679  {
680  ok( !pen, "ExtCreatePen succeeded\n" );
681  ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
682  }
683  }
684 
685  GlobalUnlock( hmem );
686  GlobalFree( hmem );
687  DeleteObject( bmp );
688 }
689 
691 {
692  test_logpen();
693  test_brush_pens();
696 }
HGDIOBJ WINAPI GetStockObject(_In_ int)
static void test_brush_pens(void)
Definition: pen.c:570
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
COLORREF elpColor
Definition: wingdi.h:1940
GLint GLint GLsizei width
Definition: gl.h:1546
#define BS_DIBPATTERN
Definition: wingdi.h:1091
static void test_logpen(void)
Definition: pen.c:34
HGLOBAL NTAPI GlobalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:368
long y
Definition: polytest.cpp:48
DWORD elpWidth
Definition: wingdi.h:1938
long x
Definition: polytest.cpp:48
#define DIB_PAL_COLORS
Definition: wingdi.h:365
UINT lbStyle
Definition: wingdi.h:1742
ULONG_PTR lbHatch
Definition: wingdi.h:1744
static HDC
Definition: imagelist.c:92
static void test_ps_userstyle(void)
Definition: pen.c:506
#define expect2(expected, alt, got)
Definition: pen.c:31
POINT lopnWidth
Definition: wingdi.h:1841
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1497
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
BOOL WINAPI DeleteObject(_In_ HGDIOBJ)
GLuint buffer
Definition: glext.h:5915
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
static HPEN hpen
static void test_ps_alternate(void)
Definition: pen.c:463
#define PS_GEOMETRIC
Definition: wingdi.h:582
ULONG_PTR elpHatch
Definition: wingdi.h:1941
START_TEST(pen)
Definition: pen.c:690
#define DWORD
Definition: nt_native.h:44
int32_t INT
Definition: typedefs.h:56
#define TEST_LINE(x1, x2, z)
Definition: pen.c:455
#define BS_NULL
Definition: wingdi.h:1086
DWORD elpNumEntries
Definition: wingdi.h:1942
struct _test_info info[]
Definition: SetCursorPos.c:19
#define OBJ_PEN
Definition: objidl.idl:1409
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define PS_SOLID
Definition: wingdi.h:585
int WINAPI SetBkMode(_In_ HDC, _In_ int)
Definition: dc.c:1032
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
DWORD elpStyleEntry[1]
Definition: wingdi.h:1943
GLuint color
Definition: glext.h:6243
#define TRANSPARENT
Definition: wingdi.h:949
DWORD elpPenStyle
Definition: wingdi.h:1937
UINT lopnStyle
Definition: wingdi.h:1840
#define NULL_PEN
Definition: wingdi.h:903
COLORREF lopnColor
Definition: wingdi.h:1842
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
#define PS_COSMETIC
Definition: wingdi.h:583
#define PS_ALTERNATE
Definition: wingdi.h:584
GLsizeiptr size
Definition: glext.h:5919
#define trace
Definition: atltest.h:70
DWORD COLORREF
Definition: windef.h:285
#define RGB(r, g, b)
Definition: wingdi.h:2935
COLORREF lbColor
Definition: wingdi.h:1743
unsigned long DWORD
Definition: ntddk_ex.h:95
HGLOBAL NTAPI GlobalFree(HGLOBAL hMem)
Definition: heapmem.c:611
#define BS_MONOPATTERN
Definition: wingdi.h:1095
#define SetLastError(x)
Definition: compat.h:409
BITMAP bmp
Definition: alphablend.c:62
int ret
HPEN WINAPI CreatePen(int nPenStyle, int nWidth, COLORREF crColor)
Definition: pen.c:21
LPVOID NTAPI GlobalLock(HGLOBAL hMem)
Definition: heapmem.c:755
HDC hdc
Definition: main.c:9
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLdouble s
Definition: gl.h:2039
#define expect(expected, got)
Definition: pen.c:30
uint32_t DWORD_PTR
Definition: typedefs.h:63
#define PS_DASH
Definition: wingdi.h:586
#define OBJ_EXTPEN
Definition: objidl.idl:1419
#define broken(x)
Definition: _sntprintf.h:21
#define PS_INSIDEFRAME
Definition: wingdi.h:592
int WINAPI GetObjectW(_In_ HANDLE h, _In_ int c, _Out_writes_bytes_opt_(c) LPVOID pv)
UINT elpBrushStyle
Definition: wingdi.h:1939
BOOL WINAPI DeleteDC(_In_ HDC)
#define ok(value,...)
Definition: atltest.h:57
#define HS_CROSS
Definition: wingdi.h:576
unsigned int UINT
Definition: ndis.h:50
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
#define PS_NULL
Definition: wingdi.h:590
#define PS_DASHDOTDOT
Definition: wingdi.h:589
static POBJECT_TYPE GetObjectType(IN PCWSTR TypeName)
Definition: ObTypes.c:15
#define PS_DASHDOT
Definition: wingdi.h:588
#define BS_PATTERN
Definition: wingdi.h:1089
HPEN WINAPI CreatePenIndirect(const LOGPEN *lplgpn)
Definition: pen.c:10
#define PS_DOT
Definition: wingdi.h:587
#define skip(...)
Definition: atltest.h:64
#define ULONG_PTR
Definition: config.h:101
HPEN WINAPI ExtCreatePen(_In_ DWORD iPenStyle, _In_ DWORD cWidth, _In_ const LOGBRUSH *plbrush, _In_ DWORD cStyle, _In_reads_opt_(cStyle) const DWORD *pstyle)
static unsigned int atoi2(const char *s)
Definition: pen.c:448
#define BS_HATCHED
Definition: wingdi.h:1088
static HBITMAP
Definition: button.c:44
#define BS_SOLID
Definition: wingdi.h:1085
Arabic default style
Definition: afstyles.h:93
#define memset(x, y, z)
Definition: compat.h:39
#define BS_DIBPATTERNPT
Definition: wingdi.h:1092
#define PS_USERSTYLE
Definition: wingdi.h:591
#define win_skip
Definition: test.h:141
#define BI_RGB
Definition: precomp.h:34
#define GMEM_MOVEABLE
Definition: winbase.h:291
#define GMEM_ZEROINIT
Definition: winbase.h:303
HBITMAP WINAPI CreateBitmap(_In_ INT cx, _In_ INT cy, _In_ UINT cPlanes, _In_ UINT cBitsPerPel, _In_opt_ const VOID *pvBits)