comctl32: A couple fixes for tab icon offsets.
[wine] / dlls / gdi / tests / gdiobj.c
1 /*
2  * Unit test suite for GDI objects
3  *
4  * Copyright 2002 Mike McCormack
5  * Copyright 2004 Dmitry Timoshkov
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <stdarg.h>
23 #include <assert.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29
30 #include "wine/test.h"
31
32
33 static void check_font(const char* test, const LOGFONTA* lf, HFONT hfont)
34 {
35     LOGFONTA getobj_lf;
36     int ret, minlen = 0;
37
38     if (!hfont)
39         return;
40
41     ret = GetObject(hfont, sizeof(getobj_lf), &getobj_lf);
42     /* NT4 tries to be clever and only returns the minimum length */
43     while (lf->lfFaceName[minlen] && minlen < LF_FACESIZE-1)
44         minlen++;
45     minlen += FIELD_OFFSET(LOGFONTA, lfFaceName) + 1;
46     ok(ret == sizeof(LOGFONTA) || ret == minlen,
47        "%s: GetObject returned %d expected %d or %d\n", test, ret, sizeof(LOGFONTA), minlen);
48     ok(!memcmp(&lf, &lf, FIELD_OFFSET(LOGFONTA, lfFaceName)), "%s: fonts don't match\n", test);
49     ok(!lstrcmpA(lf->lfFaceName, getobj_lf.lfFaceName),
50        "%s: font names don't match: %s != %s\n", test, lf->lfFaceName, getobj_lf.lfFaceName);
51 }
52
53 static HFONT create_font(const char* test, const LOGFONTA* lf)
54 {
55     HFONT hfont = CreateFontIndirectA(lf);
56     ok(hfont != 0, "%s: CreateFontIndirect failed\n", test);
57     if (hfont)
58         check_font(test, lf, hfont);
59     return hfont;
60 }
61
62 static void test_logfont(void)
63 {
64     LOGFONTA lf;
65     HFONT hfont;
66
67     memset(&lf, 0, sizeof lf);
68
69     lf.lfCharSet = ANSI_CHARSET;
70     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
71     lf.lfWeight = FW_DONTCARE;
72     lf.lfHeight = 16;
73     lf.lfWidth = 16;
74     lf.lfQuality = DEFAULT_QUALITY;
75
76     lstrcpyA(lf.lfFaceName, "Arial");
77     hfont = create_font("Arial", &lf);
78     DeleteObject(hfont);
79
80     memset(&lf, 'A', sizeof(lf));
81     hfont = CreateFontIndirectA(&lf);
82     ok(hfont != 0, "CreateFontIndirectA with strange LOGFONT failed\n");
83     
84     lf.lfFaceName[LF_FACESIZE - 1] = 0;
85     check_font("AAA...", &lf, hfont);
86     DeleteObject(hfont);
87 }
88
89 static INT CALLBACK font_enum_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
90 {
91     if (type & RASTER_FONTTYPE)
92     {
93         LOGFONT *lf = (LOGFONT *)lParam;
94         *lf = *elf;
95         return 0; /* stop enumeration */
96     }
97
98     return 1; /* continue enumeration */
99 }
100
101 static void test_font_metrics(HDC hdc, HFONT hfont, const char *test_str,
102                               INT test_str_len, const TEXTMETRICA *tm_orig,
103                               const SIZE *size_orig, INT width_orig,
104                               INT scale_x, INT scale_y)
105 {
106     HFONT old_hfont;
107     TEXTMETRICA tm;
108     SIZE size;
109     INT width;
110
111     if (!hfont)
112         return;
113
114     old_hfont = SelectObject(hdc, hfont);
115
116     GetTextMetricsA(hdc, &tm);
117
118     ok(tm.tmHeight == tm_orig->tmHeight * scale_y, "%ld != %ld\n", tm.tmHeight, tm_orig->tmHeight * scale_y);
119     ok(tm.tmAscent == tm_orig->tmAscent * scale_y, "%ld != %ld\n", tm.tmAscent, tm_orig->tmAscent * scale_y);
120     ok(tm.tmDescent == tm_orig->tmDescent * scale_y, "%ld != %ld\n", tm.tmDescent, tm_orig->tmDescent * scale_y);
121     ok(tm.tmAveCharWidth == tm_orig->tmAveCharWidth * scale_x, "%ld != %ld\n", tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x);
122
123     GetTextExtentPoint32A(hdc, test_str, test_str_len, &size);
124
125     ok(size.cx == size_orig->cx * scale_x, "%ld != %ld\n", size.cx, size_orig->cx * scale_x);
126     ok(size.cy == size_orig->cy * scale_y, "%ld != %ld\n", size.cy, size_orig->cy * scale_y);
127
128     GetCharWidthA(hdc, 'A', 'A', &width);
129
130     ok(width == width_orig * scale_x, "%d != %d\n", width, width_orig * scale_x);
131
132     SelectObject(hdc, old_hfont);
133 }
134
135 /* see whether GDI scales bitmap font metrics */
136 static void test_bitmap_font(void)
137 {
138     static const char test_str[11] = "Test String";
139     HDC hdc;
140     LOGFONTA bitmap_lf;
141     HFONT hfont, old_hfont;
142     TEXTMETRICA tm_orig;
143     SIZE size_orig;
144     INT ret, i, width_orig, height_orig;
145
146     hdc = GetDC(0);
147
148     /* "System" has only 1 pixel size defined, otherwise the test breaks */
149     ret = EnumFontFamiliesA(hdc, "System", font_enum_proc, (LPARAM)&bitmap_lf);
150     if (ret)
151     {
152         ReleaseDC(0, hdc);
153         trace("no bitmap fonts were found, skipping the test\n");
154         return;
155     }
156
157     trace("found bitmap font %s, height %ld\n", bitmap_lf.lfFaceName, bitmap_lf.lfHeight);
158
159     height_orig = bitmap_lf.lfHeight;
160     hfont = create_font("bitmap", &bitmap_lf);
161
162     old_hfont = SelectObject(hdc, hfont);
163     ok(GetTextMetricsA(hdc, &tm_orig), "GetTextMetricsA failed\n");
164     ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
165     ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
166     SelectObject(hdc, old_hfont);
167     DeleteObject(hfont);
168
169     /* test fractional scaling */
170     for (i = 1; i < height_orig; i++)
171     {
172         hfont = create_font("fractional", &bitmap_lf);
173         test_font_metrics(hdc, hfont, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, 1);
174         DeleteObject(hfont);
175     }
176
177     /* test integer scaling 3x2 */
178     bitmap_lf.lfHeight = height_orig * 2;
179     bitmap_lf.lfWidth *= 3;
180     hfont = create_font("3x2", &bitmap_lf);
181 todo_wine
182 {
183     test_font_metrics(hdc, hfont, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 2);
184 }
185     DeleteObject(hfont);
186
187     /* test integer scaling 3x3 */
188     bitmap_lf.lfHeight = height_orig * 3;
189     bitmap_lf.lfWidth = 0;
190     hfont = create_font("3x3", &bitmap_lf);
191
192 todo_wine
193 {
194     test_font_metrics(hdc, hfont, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 3);
195 }
196     DeleteObject(hfont);
197
198     ReleaseDC(0, hdc);
199 }
200
201 static INT CALLBACK find_font_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
202 {
203     LOGFONT *lf = (LOGFONT *)lParam;
204
205     trace("found font %s, height %ld\n", elf->lfFaceName, elf->lfHeight);
206
207     if (elf->lfHeight == lf->lfHeight && !strcmp(elf->lfFaceName, lf->lfFaceName))
208     {
209         *lf = *elf;
210         return 0; /* stop enumeration */
211     }
212     return 1; /* continue enumeration */
213 }
214
215 static void test_bitmap_font_metrics(void)
216 {
217     static const struct font_data
218     {
219         const char face_name[LF_FACESIZE];
220         int weight, height, ascent, descent, int_leading, ext_leading;
221         int ave_char_width, max_char_width;
222     } fd[] =
223     {
224         { "MS Sans Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11 },
225         { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14 },
226         { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 16 },
227         { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 20 },
228         { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 25 },
229         { "MS Sans Serif", FW_NORMAL, 37, 29, 8, 5, 0, 16, 32 },
230         { "MS Serif", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8 },
231         { "MS Serif", FW_NORMAL, 11, 9, 2, 2, 0, 5, 9 },
232         { "MS Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 12 },
233         { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 16 },
234         { "MS Serif", FW_NORMAL, 19, 15, 4, 3, 0, 8, 19 },
235         { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 23 },
236         { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 27 },
237         { "MS Serif", FW_NORMAL, 35, 27, 8, 3, 0, 16, 34 },
238         { "Courier", FW_NORMAL, 13, 11, 2, 0, 0, 8, 8 },
239         { "Courier", FW_NORMAL, 16, 13, 3, 0, 0, 9, 9 },
240         { "Courier", FW_NORMAL, 20, 16, 4, 0, 0, 12, 12 },
241         { "System", FW_BOLD, 16, 13, 3, 3, 0, 7, 15 }
242         /* FIXME: add "Fixedsys", "Terminal", "Small Fonts" */
243     };
244     HDC hdc;
245     LOGFONT lf;
246     HFONT hfont, old_hfont;
247     TEXTMETRIC tm;
248     INT ret, i;
249
250     hdc = CreateCompatibleDC(0);
251     assert(hdc);
252
253     for (i = 0; i < sizeof(fd)/sizeof(fd[0]); i++)
254     {
255         memset(&lf, 0, sizeof(lf));
256
257         lf.lfHeight = fd[i].height;
258         strcpy(lf.lfFaceName, fd[i].face_name);
259         ret = EnumFontFamilies(hdc, fd[i].face_name, find_font_proc, (LPARAM)&lf);
260         if (ret)
261         {
262             trace("font %s height %d not found\n", fd[i].face_name, fd[i].height);
263             continue;
264         }
265
266         trace("found font %s, height %ld\n", lf.lfFaceName, lf.lfHeight);
267
268         hfont = create_font(lf.lfFaceName, &lf);
269         old_hfont = SelectObject(hdc, hfont);
270         ok(GetTextMetrics(hdc, &tm), "GetTextMetrics error %ld\n", GetLastError());
271
272         ok(tm.tmWeight == fd[i].weight, "%s(%d): tm.tmWeight %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmWeight, fd[i].weight);
273         ok(tm.tmHeight == fd[i].height, "%s(%d): tm.tmHeight %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmHeight, fd[i].height);
274         ok(tm.tmAscent == fd[i].ascent, "%s(%d): tm.tmAscent %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmAscent, fd[i].ascent);
275         ok(tm.tmDescent == fd[i].descent, "%s(%d): tm.tmDescent %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmDescent, fd[i].descent);
276         ok(tm.tmInternalLeading == fd[i].int_leading, "%s(%d): tm.tmInternalLeading %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmInternalLeading, fd[i].int_leading);
277         ok(tm.tmExternalLeading == fd[i].ext_leading, "%s(%d): tm.tmExternalLeading %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmExternalLeading, fd[i].ext_leading);
278         ok(tm.tmAveCharWidth == fd[i].ave_char_width, "%s(%d): tm.tmAveCharWidth %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmAveCharWidth, fd[i].ave_char_width);
279         ok(tm.tmMaxCharWidth == fd[i].max_char_width, "%s(%d): tm.tmMaxCharWidth %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmMaxCharWidth, fd[i].max_char_width);
280
281         SelectObject(hdc, old_hfont);
282         DeleteObject(hfont);
283     }
284
285     DeleteDC(hdc);
286 }
287
288 static void test_gdi_objects(void)
289 {
290     BYTE buff[256];
291     HDC hdc = GetDC(NULL);
292     HPEN hp;
293     int i;
294     BOOL ret;
295
296     /* SelectObject() with a NULL DC returns 0 and sets ERROR_INVALID_HANDLE.
297      * Note: Under XP at least invalid ptrs can also be passed, not just NULL;
298      *       Don't test that here in case it crashes earlier win versions.
299      */
300     SetLastError(0);
301     hp = SelectObject(NULL, GetStockObject(BLACK_PEN));
302     ok(!hp && GetLastError() == ERROR_INVALID_HANDLE,
303        "SelectObject(NULL DC) expected 0, ERROR_INVALID_HANDLE, got %p, 0x%08lx\n",
304        hp, GetLastError());
305
306     /* With a valid DC and a NULL object, the call returns 0 but does not SetLastError() */
307     SetLastError(0);
308     hp = SelectObject(hdc, NULL);
309     ok(!hp && !GetLastError(),
310        "SelectObject(NULL obj) expected 0, NO_ERROR, got %p, 0x%08lx\n",
311        hp, GetLastError());
312
313     /* The DC is unaffected by the NULL SelectObject */
314     SetLastError(0);
315     hp = SelectObject(hdc, GetStockObject(BLACK_PEN));
316     ok(hp && !GetLastError(),
317        "SelectObject(post NULL) expected non-null, NO_ERROR, got %p, 0x%08lx\n",
318        hp, GetLastError());
319
320     /* GetCurrentObject does not SetLastError() on a null object */
321     SetLastError(0);
322     hp = GetCurrentObject(NULL, OBJ_PEN);
323     ok(!hp && !GetLastError(),
324        "GetCurrentObject(NULL DC) expected 0, NO_ERROR, got %p, 0x%08lx\n",
325        hp, GetLastError());
326
327     /* DeleteObject does not SetLastError() on a null object */
328     ret = DeleteObject(NULL);
329     ok( !ret && !GetLastError(),
330        "DeleteObject(NULL obj), expected 0, NO_ERROR, got %d, 0x%08lx\n",
331        ret, GetLastError());
332
333     /* GetObject does not SetLastError() on a null object */
334     SetLastError(0);
335     i = GetObjectA(NULL, sizeof(buff), buff);
336     ok (!i && !GetLastError(),
337         "GetObject(NULL obj), expected 0, NO_ERROR, got %d, 0x%08lx\n",
338         i, GetLastError());
339
340     /* GetObjectType does SetLastError() on a null object */
341     SetLastError(0);
342     i = GetObjectType(NULL);
343     ok (!i && GetLastError() == ERROR_INVALID_HANDLE,
344         "GetObjectType(NULL obj), expected 0, ERROR_INVALID_HANDLE, got %d, 0x%08lx\n",
345         i, GetLastError());
346
347     /* UnrealizeObject does not SetLastError() on a null object */
348     SetLastError(0);
349     i = UnrealizeObject(NULL);
350     ok (!i && !GetLastError(),
351         "UnrealizeObject(NULL obj), expected 0, NO_ERROR, got %d, 0x%08lx\n",
352         i, GetLastError());
353
354     ReleaseDC(NULL, hdc);
355 }
356
357 static void test_GdiGetCharDimensions(void)
358 {
359     HDC hdc;
360     TEXTMETRICW tm;
361     LONG ret;
362     SIZE size;
363     LONG avgwidth, height;
364     static const char szAlphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
365     typedef LONG (WINAPI *fnGdiGetCharDimensions)(HDC hdc, LPTEXTMETRICW lptm, LONG *height);
366     fnGdiGetCharDimensions GdiGetCharDimensions = (fnGdiGetCharDimensions)GetProcAddress(LoadLibrary("gdi32"), "GdiGetCharDimensions");
367     if (!GdiGetCharDimensions) return;
368
369     hdc = CreateCompatibleDC(NULL);
370
371     GetTextExtentPoint(hdc, szAlphabet, strlen(szAlphabet), &size);
372     avgwidth = ((size.cx / 26) + 1) / 2;
373
374     ret = GdiGetCharDimensions(hdc, &tm, &height);
375     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret);
376     ok(height == tm.tmHeight, "GdiGetCharDimensions should have set height to %ld instead of %ld\n", tm.tmHeight, height);
377
378     ret = GdiGetCharDimensions(hdc, &tm, NULL);
379     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret);
380
381     ret = GdiGetCharDimensions(hdc, NULL, NULL);
382     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret);
383
384     height = 0;
385     ret = GdiGetCharDimensions(hdc, NULL, &height);
386     ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret);
387     ok(height == size.cy, "GdiGetCharDimensions should have set height to %ld instead of %ld\n", size.cy, height);
388
389     DeleteDC(hdc);
390 }
391
392 static void test_text_extents(void)
393 {
394     LOGFONTA lf;
395     TEXTMETRICA tm;
396     HDC hdc;
397     HFONT hfont;
398     SIZE sz;
399
400     memset(&lf, 0, sizeof(lf));
401     strcpy(lf.lfFaceName, "Arial");
402     lf.lfHeight = 20;
403
404     hfont = CreateFontIndirectA(&lf);
405     hdc = GetDC(0);
406     hfont = SelectObject(hdc, hfont);
407     GetTextMetricsA(hdc, &tm);
408     GetTextExtentPointA(hdc, "o", 1, &sz);
409     ok(sz.cy == tm.tmHeight, "cy %ld tmHeight %ld\n", sz.cy, tm.tmHeight);
410
411     SelectObject(hdc, hfont);
412     DeleteObject(hfont);
413     ReleaseDC(NULL, hdc);
414 }
415
416 struct hgdiobj_event
417 {
418     HDC hdc;
419     HGDIOBJ hgdiobj1;
420     HGDIOBJ hgdiobj2;
421     HANDLE stop_event;
422     HANDLE ready_event;
423 };
424
425 static DWORD WINAPI thread_proc(void *param)
426 {
427     LOGPEN lp;
428     struct hgdiobj_event *hgdiobj_event = (struct hgdiobj_event *)param;
429
430     hgdiobj_event->hdc = CreateDC("display", NULL, NULL, NULL);
431     ok(hgdiobj_event->hdc != NULL, "CreateDC error %ld\n", GetLastError());
432
433     hgdiobj_event->hgdiobj1 = CreatePen(PS_DASHDOTDOT, 17, RGB(1, 2, 3));
434     ok(hgdiobj_event->hgdiobj1 != 0, "Failed to create pen\n");
435
436     hgdiobj_event->hgdiobj2 = CreateRectRgn(0, 1, 12, 17);
437     ok(hgdiobj_event->hgdiobj2 != 0, "Failed to create pen\n");
438
439     SetEvent(hgdiobj_event->ready_event);
440     ok(WaitForSingleObject(hgdiobj_event->stop_event, INFINITE) == WAIT_OBJECT_0,
441        "WaitForSingleObject error %ld\n", GetLastError());
442
443     ok(!GetObject(hgdiobj_event->hgdiobj1, sizeof(lp), &lp), "GetObject should fail\n");
444
445     ok(!GetDeviceCaps(hgdiobj_event->hdc, TECHNOLOGY), "GetDeviceCaps(TECHNOLOGY) should fail\n");
446
447     return 0;
448 }
449
450 static void test_thread_objects(void)
451 {
452     LOGPEN lp;
453     DWORD tid, type;
454     HANDLE hthread;
455     struct hgdiobj_event hgdiobj_event;
456     INT ret;
457
458     hgdiobj_event.stop_event = CreateEvent(NULL, 0, 0, NULL);
459     ok(hgdiobj_event.stop_event != NULL, "CreateEvent error %ld\n", GetLastError());
460     hgdiobj_event.ready_event = CreateEvent(NULL, 0, 0, NULL);
461     ok(hgdiobj_event.ready_event != NULL, "CreateEvent error %ld\n", GetLastError());
462
463     hthread = CreateThread(NULL, 0, thread_proc, &hgdiobj_event, 0, &tid);
464     ok(hthread != NULL, "CreateThread error %ld\n", GetLastError());
465
466     ok(WaitForSingleObject(hgdiobj_event.ready_event, INFINITE) == WAIT_OBJECT_0,
467        "WaitForSingleObject error %ld\n", GetLastError());
468
469     ok(GetObject(hgdiobj_event.hgdiobj1, sizeof(lp), &lp) == sizeof(lp),
470        "GetObject error %ld\n", GetLastError());
471     ok(lp.lopnStyle == PS_DASHDOTDOT, "wrong pen style %d\n", lp.lopnStyle);
472     ok(lp.lopnWidth.x == 17, "wrong pen width.y %ld\n", lp.lopnWidth.x);
473     ok(lp.lopnWidth.y == 0, "wrong pen width.y %ld\n", lp.lopnWidth.y);
474     ok(lp.lopnColor == RGB(1, 2, 3), "wrong pen width.y %08lx\n", lp.lopnColor);
475
476     ret = GetDeviceCaps(hgdiobj_event.hdc, TECHNOLOGY);
477     ok(ret == DT_RASDISPLAY, "GetDeviceCaps(TECHNOLOGY) should return DT_RASDISPLAY not %d\n", ret);
478
479     ok(DeleteObject(hgdiobj_event.hgdiobj1), "DeleteObject error %ld\n", GetLastError());
480     ok(DeleteDC(hgdiobj_event.hdc), "DeleteDC error %ld\n", GetLastError());
481
482     type = GetObjectType(hgdiobj_event.hgdiobj2);
483     ok(type == OBJ_REGION, "GetObjectType returned %lu\n", type);
484
485     SetEvent(hgdiobj_event.stop_event);
486     ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0,
487        "WaitForSingleObject error %ld\n", GetLastError());
488     CloseHandle(hthread);
489
490     type = GetObjectType(hgdiobj_event.hgdiobj2);
491     ok(type == OBJ_REGION, "GetObjectType returned %lu\n", type);
492     ok(DeleteObject(hgdiobj_event.hgdiobj2), "DeleteObject error %ld\n", GetLastError());
493
494     CloseHandle(hgdiobj_event.stop_event);
495     CloseHandle(hgdiobj_event.ready_event);
496 }
497
498 static void test_GetCurrentObject(void)
499 {
500     DWORD type;
501     HPEN hpen;
502     HBRUSH hbrush;
503     HPALETTE hpal;
504     HFONT hfont;
505     HBITMAP hbmp;
506     HRGN hrgn;
507     HDC hdc;
508     HCOLORSPACE hcs;
509     HGDIOBJ hobj;
510     LOGBRUSH lb;
511     LOGCOLORSPACEA lcs;
512
513     hdc = CreateCompatibleDC(0);
514     assert(hdc != 0);
515
516     type = GetObjectType(hdc);
517     ok(type == OBJ_MEMDC, "GetObjectType returned %lu\n", type);
518
519     hpen = CreatePen(PS_SOLID, 10, RGB(10, 20, 30));
520     assert(hpen != 0);
521     SelectObject(hdc, hpen);
522     hobj = GetCurrentObject(hdc, OBJ_PEN);
523     ok(hobj == hpen, "OBJ_PEN is wrong: %p\n", hobj);
524     hobj = GetCurrentObject(hdc, OBJ_EXTPEN);
525     ok(hobj == hpen, "OBJ_EXTPEN is wrong: %p\n", hobj);
526
527     hbrush = CreateSolidBrush(RGB(10, 20, 30));
528     assert(hbrush != 0);
529     SelectObject(hdc, hbrush);
530     hobj = GetCurrentObject(hdc, OBJ_BRUSH);
531     ok(hobj == hbrush, "OBJ_BRUSH is wrong: %p\n", hobj);
532
533     hpal = CreateHalftonePalette(hdc);
534     assert(hpal != 0);
535     SelectPalette(hdc, hpal, FALSE);
536     hobj = GetCurrentObject(hdc, OBJ_PAL);
537     ok(hobj == hpal, "OBJ_PAL is wrong: %p\n", hobj);
538
539     hfont = CreateFontA(10, 5, 0, 0, FW_DONTCARE, 0, 0, 0, ANSI_CHARSET,
540                         OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
541                         DEFAULT_PITCH, "MS Sans Serif");
542     assert(hfont != 0);
543     SelectObject(hdc, hfont);
544     hobj = GetCurrentObject(hdc, OBJ_FONT);
545     ok(hobj == hfont, "OBJ_FONT is wrong: %p\n", hobj);
546
547     hbmp = CreateBitmap(100, 100, 1, 1, NULL);
548     assert(hbmp != 0);
549     SelectObject(hdc, hbmp);
550     hobj = GetCurrentObject(hdc, OBJ_BITMAP);
551     ok(hobj == hbmp, "OBJ_BITMAP is wrong: %p\n", hobj);
552
553     assert(GetObject(hbrush, sizeof(lb), &lb) == sizeof(lb));
554     hpen = ExtCreatePen(PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_SQUARE | PS_JOIN_BEVEL,
555                         10, &lb, 0, NULL);
556     assert(hpen != 0);
557     SelectObject(hdc, hpen);
558     hobj = GetCurrentObject(hdc, OBJ_PEN);
559     ok(hobj == hpen, "OBJ_PEN is wrong: %p\n", hobj);
560     hobj = GetCurrentObject(hdc, OBJ_EXTPEN);
561     ok(hobj == hpen, "OBJ_EXTPEN is wrong: %p\n", hobj);
562
563     hcs = GetColorSpace(hdc);
564     if (hcs)
565     {
566         trace("current color space is not NULL\n");
567         ok(GetLogColorSpaceA(hcs, &lcs, sizeof(lcs)), "GetLogColorSpace failed\n");
568         hcs = CreateColorSpaceA(&lcs);
569         ok(hcs != 0, "CreateColorSpace failed\n");
570         SelectObject(hdc, hcs);
571         hobj = GetCurrentObject(hdc, OBJ_COLORSPACE);
572         ok(hobj == hcs, "OBJ_COLORSPACE is wrong: %p\n", hobj);
573     }
574
575     hrgn = CreateRectRgn(1, 1, 100, 100);
576     assert(hrgn != 0);
577     SelectObject(hdc, hrgn);
578     hobj = GetCurrentObject(hdc, OBJ_REGION);
579     ok(!hobj, "OBJ_REGION is wrong: %p\n", hobj);
580
581     DeleteDC(hdc);
582 }
583
584 static void test_logpen(void)
585 {
586     static const struct
587     {
588         UINT style;
589         INT width;
590         COLORREF color;
591         UINT ret_style;
592         INT ret_width;
593         COLORREF ret_color;
594     } pen[] = {
595         { PS_SOLID, -123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
596         { PS_SOLID, 0, RGB(0x12,0x34,0x56), PS_SOLID, 0, RGB(0x12,0x34,0x56) },
597         { PS_SOLID, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
598         { PS_DASH, 123, RGB(0x12,0x34,0x56), PS_DASH, 123, RGB(0x12,0x34,0x56) },
599         { PS_DOT, 123, RGB(0x12,0x34,0x56), PS_DOT, 123, RGB(0x12,0x34,0x56) },
600         { PS_DASHDOT, 123, RGB(0x12,0x34,0x56), PS_DASHDOT, 123, RGB(0x12,0x34,0x56) },
601         { PS_DASHDOTDOT, 123, RGB(0x12,0x34,0x56), PS_DASHDOTDOT, 123, RGB(0x12,0x34,0x56) },
602         { PS_NULL, -123, RGB(0x12,0x34,0x56), PS_NULL, 1, 0 },
603         { PS_NULL, 123, RGB(0x12,0x34,0x56), PS_NULL, 1, 0 },
604         { PS_INSIDEFRAME, 123, RGB(0x12,0x34,0x56), PS_INSIDEFRAME, 123, RGB(0x12,0x34,0x56) },
605         { PS_USERSTYLE, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
606         { PS_ALTERNATE, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) }
607     };
608     INT i, size;
609     HPEN hpen;
610     LOGPEN lp;
611     EXTLOGPEN elp;
612     LOGBRUSH lb;
613     DWORD obj_type, user_style[2] = { 0xabc, 0xdef };
614     struct
615     {
616         EXTLOGPEN elp;
617         DWORD style_data[10];
618     } ext_pen;
619
620     for (i = 0; i < sizeof(pen)/sizeof(pen[0]); i++)
621     {
622         trace("testing style %u\n", pen[i].style);
623
624         /********************** cosmetic pens **********************/
625         /* CreatePenIndirect behaviour */
626         lp.lopnStyle = pen[i].style,
627         lp.lopnWidth.x = pen[i].width;
628         lp.lopnWidth.y = 11; /* just in case */
629         lp.lopnColor = pen[i].color;
630         SetLastError(0xdeadbeef);
631         hpen = CreatePenIndirect(&lp);
632         ok(hpen != 0, "CreatePen error %ld\n", GetLastError());
633
634         obj_type = GetObjectType(hpen);
635         ok(obj_type == OBJ_PEN, "wrong object type %lu\n", obj_type);
636
637         memset(&lp, 0xb0, sizeof(lp));
638         SetLastError(0xdeadbeef);
639         size = GetObject(hpen, sizeof(lp), &lp);
640         ok(size == sizeof(lp), "GetObject returned %d, error %ld\n", size, GetLastError());
641
642         ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
643         ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %ld\n", pen[i].ret_width, lp.lopnWidth.x);
644         ok(lp.lopnWidth.y == 0, "expected 0, got %ld\n", lp.lopnWidth.y);
645         ok(lp.lopnColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, lp.lopnColor);
646
647         DeleteObject(hpen);
648
649         /* CreatePen behaviour */
650         SetLastError(0xdeadbeef);
651         hpen = CreatePen(pen[i].style, pen[i].width, pen[i].color);
652         ok(hpen != 0, "CreatePen error %ld\n", GetLastError());
653
654         obj_type = GetObjectType(hpen);
655         ok(obj_type == OBJ_PEN, "wrong object type %lu\n", obj_type);
656
657         /* check what's the real size of the object */
658         size = GetObject(hpen, 0, NULL);
659         ok(size == sizeof(lp), "GetObject returned %d, error %ld\n", size, GetLastError());
660
661         /* ask for truncated data */
662         memset(&lp, 0xb0, sizeof(lp));
663         SetLastError(0xdeadbeef);
664         size = GetObject(hpen, sizeof(lp.lopnStyle), &lp);
665         ok(!size, "GetObject should fail: size %d, error %ld\n", size, GetLastError());
666
667         /* see how larger buffer sizes are handled */
668         memset(&lp, 0xb0, sizeof(lp));
669         SetLastError(0xdeadbeef);
670         size = GetObject(hpen, sizeof(lp) * 2, &lp);
671         ok(size == sizeof(lp), "GetObject returned %d, error %ld\n", size, GetLastError());
672
673         /* see how larger buffer sizes are handled */
674         memset(&elp, 0xb0, sizeof(elp));
675         SetLastError(0xdeadbeef);
676         size = GetObject(hpen, sizeof(elp) * 2, &elp);
677         ok(size == sizeof(lp), "GetObject returned %d, error %ld\n", size, GetLastError());
678
679         memset(&lp, 0xb0, sizeof(lp));
680         SetLastError(0xdeadbeef);
681         size = GetObject(hpen, sizeof(lp), &lp);
682         ok(size == sizeof(lp), "GetObject returned %d, error %ld\n", size, GetLastError());
683
684         ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
685         ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %ld\n", pen[i].ret_width, lp.lopnWidth.x);
686         ok(lp.lopnWidth.y == 0, "expected 0, got %ld\n", lp.lopnWidth.y);
687         ok(lp.lopnColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, lp.lopnColor);
688
689         memset(&elp, 0xb0, sizeof(elp));
690         SetLastError(0xdeadbeef);
691         size = GetObject(hpen, sizeof(elp), &elp);
692
693         /* for some reason XP differentiates PS_NULL here */
694         if (pen[i].style == PS_NULL)
695         {
696             ok(size == sizeof(EXTLOGPEN), "GetObject returned %d, error %ld\n", size, GetLastError());
697             ok(elp.elpPenStyle == pen[i].ret_style, "expected %u, got %lu\n", pen[i].ret_style, elp.elpPenStyle);
698             ok(elp.elpWidth == 0, "expected 0, got %lu\n", elp.elpWidth);
699             ok(elp.elpColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, elp.elpColor);
700             ok(elp.elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %u\n", elp.elpBrushStyle);
701             ok(elp.elpHatch == 0, "expected 0, got %p\n", (void *)elp.elpHatch);
702             ok(elp.elpNumEntries == 0, "expected 0, got %lx\n", elp.elpNumEntries);
703         }
704         else
705         {
706             ok(size == sizeof(LOGPEN), "GetObject returned %d, error %ld\n", size, GetLastError());
707             memcpy(&lp, &elp, sizeof(lp));
708             ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
709             ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %ld\n", pen[i].ret_width, lp.lopnWidth.x);
710             ok(lp.lopnWidth.y == 0, "expected 0, got %ld\n", lp.lopnWidth.y);
711             ok(lp.lopnColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, lp.lopnColor);
712         }
713
714         DeleteObject(hpen);
715
716         /********** cosmetic pens created by ExtCreatePen ***********/
717         lb.lbStyle = BS_SOLID;
718         lb.lbColor = pen[i].color;
719         lb.lbHatch = HS_CROSS; /* just in case */
720         SetLastError(0xdeadbeef);
721         hpen = ExtCreatePen(pen[i].style, pen[i].width, &lb, 2, user_style);
722         if (pen[i].style != PS_USERSTYLE)
723         {
724             ok(hpen == 0, "ExtCreatePen should fail\n");
725             ok(GetLastError() == ERROR_INVALID_PARAMETER,
726                "wrong last error value %ld\n", GetLastError());
727             SetLastError(0xdeadbeef);
728             hpen = ExtCreatePen(pen[i].style, pen[i].width, &lb, 0, NULL);
729             if (pen[i].style != PS_NULL)
730             {
731                 ok(hpen == 0, "ExtCreatePen with width != 1 should fail\n");
732                 ok(GetLastError() == ERROR_INVALID_PARAMETER,
733                    "wrong last error value %ld\n", GetLastError());
734
735                 SetLastError(0xdeadbeef);
736                 hpen = ExtCreatePen(pen[i].style, 1, &lb, 0, NULL);
737             }
738         }
739         else
740         {
741             ok(hpen == 0, "ExtCreatePen with width != 1 should fail\n");
742             ok(GetLastError() == ERROR_INVALID_PARAMETER,
743                "wrong last error value %ld\n", GetLastError());
744             SetLastError(0xdeadbeef);
745             hpen = ExtCreatePen(pen[i].style, 1, &lb, 2, user_style);
746         }
747         if (pen[i].style == PS_INSIDEFRAME)
748         {
749             /* This style is applicable only for gemetric pens */
750             ok(hpen == 0, "ExtCreatePen should fail\n");
751             goto test_geometric_pens;
752         }
753         ok(hpen != 0, "ExtCreatePen error %ld\n", GetLastError());
754
755         obj_type = GetObjectType(hpen);
756         /* for some reason XP differentiates PS_NULL here */
757         if (pen[i].style == PS_NULL)
758             ok(obj_type == OBJ_PEN, "wrong object type %lu\n", obj_type);
759         else
760             ok(obj_type == OBJ_EXTPEN, "wrong object type %lu\n", obj_type);
761
762         /* check what's the real size of the object */
763         SetLastError(0xdeadbeef);
764         size = GetObject(hpen, 0, NULL);
765         switch (pen[i].style)
766         {
767         case PS_NULL:
768             ok(size == sizeof(LOGPEN),
769                "GetObject returned %d, error %ld\n", size, GetLastError());
770             break;
771
772         case PS_USERSTYLE:
773             ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry) + sizeof(user_style),
774                "GetObject returned %d, error %ld\n", size, GetLastError());
775             break;
776
777         default:
778             ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry),
779                "GetObject returned %d, error %ld\n", size, GetLastError());
780             break;
781         }
782
783         /* ask for truncated data */
784         memset(&elp, 0xb0, sizeof(elp));
785         SetLastError(0xdeadbeef);
786         size = GetObject(hpen, sizeof(elp.elpPenStyle), &elp);
787         ok(!size, "GetObject should fail: size %d, error %ld\n", size, GetLastError());
788
789         /* see how larger buffer sizes are handled */
790         memset(&ext_pen, 0xb0, sizeof(ext_pen));
791         SetLastError(0xdeadbeef);
792         size = GetObject(hpen, sizeof(ext_pen), &ext_pen.elp);
793         switch (pen[i].style)
794         {
795         case PS_NULL:
796             ok(size == sizeof(LOGPEN),
797                "GetObject returned %d, error %ld\n", size, GetLastError());
798             memcpy(&lp, &ext_pen.elp, sizeof(lp));
799             ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
800             ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %ld\n", pen[i].ret_width, lp.lopnWidth.x);
801             ok(lp.lopnWidth.y == 0, "expected 0, got %ld\n", lp.lopnWidth.y);
802             ok(lp.lopnColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, lp.lopnColor);
803
804             /* for PS_NULL it also works this way */
805             memset(&elp, 0xb0, sizeof(elp));
806             SetLastError(0xdeadbeef);
807             size = GetObject(hpen, sizeof(elp), &elp);
808             ok(size == sizeof(EXTLOGPEN),
809                 "GetObject returned %d, error %ld\n", size, GetLastError());
810             ok(ext_pen.elp.elpHatch == 0xb0b0b0b0, "expected 0xb0b0b0b0, got %p\n", (void *)ext_pen.elp.elpHatch);
811             ok(ext_pen.elp.elpNumEntries == 0xb0b0b0b0, "expected 0xb0b0b0b0, got %lx\n", ext_pen.elp.elpNumEntries);
812             break;
813
814         case PS_USERSTYLE:
815             ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry) + sizeof(user_style),
816                "GetObject returned %d, error %ld\n", size, GetLastError());
817             ok(ext_pen.elp.elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen.elp.elpHatch);
818             ok(ext_pen.elp.elpNumEntries == 2, "expected 0, got %lx\n", ext_pen.elp.elpNumEntries);
819             ok(ext_pen.elp.elpStyleEntry[0] == 0xabc, "expected 0xabc, got %lx\n", ext_pen.elp.elpStyleEntry[0]);
820             ok(ext_pen.elp.elpStyleEntry[1] == 0xdef, "expected 0xabc, got %lx\n", ext_pen.elp.elpStyleEntry[1]);
821             break;
822
823         default:
824             ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry),
825                "GetObject returned %d, error %ld\n", size, GetLastError());
826             ok(ext_pen.elp.elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen.elp.elpHatch);
827             ok(ext_pen.elp.elpNumEntries == 0, "expected 0, got %lx\n", ext_pen.elp.elpNumEntries);
828             break;
829         }
830
831 if (pen[i].style == PS_USERSTYLE)
832 {
833     todo_wine
834         ok(ext_pen.elp.elpPenStyle == pen[i].style, "expected %x, got %lx\n", pen[i].style, ext_pen.elp.elpPenStyle);
835 }
836 else
837         ok(ext_pen.elp.elpPenStyle == pen[i].style, "expected %x, got %lx\n", pen[i].style, ext_pen.elp.elpPenStyle);
838         ok(ext_pen.elp.elpWidth == 1, "expected 1, got %lx\n", ext_pen.elp.elpWidth);
839         ok(ext_pen.elp.elpColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, ext_pen.elp.elpColor);
840         ok(ext_pen.elp.elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %x\n", ext_pen.elp.elpBrushStyle);
841
842         DeleteObject(hpen);
843
844 test_geometric_pens:
845         /********************** geometric pens **********************/
846         lb.lbStyle = BS_SOLID;
847         lb.lbColor = pen[i].color;
848         lb.lbHatch = HS_CROSS; /* just in case */
849         SetLastError(0xdeadbeef);
850         hpen = ExtCreatePen(PS_GEOMETRIC | pen[i].style, pen[i].width, &lb, 2, user_style);
851         if (pen[i].style != PS_USERSTYLE)
852         {
853             ok(hpen == 0, "ExtCreatePen should fail\n");
854             SetLastError(0xdeadbeef);
855             hpen = ExtCreatePen(PS_GEOMETRIC | pen[i].style, pen[i].width, &lb, 0, NULL);
856         }
857         if (pen[i].style == PS_ALTERNATE)
858         {
859             /* This style is applicable only for cosmetic pens */
860             ok(hpen == 0, "ExtCreatePen should fail\n");
861             continue;
862         }
863         ok(hpen != 0, "ExtCreatePen error %ld\n", GetLastError());
864
865         obj_type = GetObjectType(hpen);
866         /* for some reason XP differentiates PS_NULL here */
867         if (pen[i].style == PS_NULL)
868             ok(obj_type == OBJ_PEN, "wrong object type %lu\n", obj_type);
869         else
870             ok(obj_type == OBJ_EXTPEN, "wrong object type %lu\n", obj_type);
871
872         /* check what's the real size of the object */
873         size = GetObject(hpen, 0, NULL);
874         switch (pen[i].style)
875         {
876         case PS_NULL:
877             ok(size == sizeof(LOGPEN),
878                "GetObject returned %d, error %ld\n", size, GetLastError());
879             break;
880
881         case PS_USERSTYLE:
882             ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry) + sizeof(user_style),
883                "GetObject returned %d, error %ld\n", size, GetLastError());
884             break;
885
886         default:
887             ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry),
888                "GetObject returned %d, error %ld\n", size, GetLastError());
889             break;
890         }
891
892         /* ask for truncated data */
893         memset(&lp, 0xb0, sizeof(lp));
894         SetLastError(0xdeadbeef);
895         size = GetObject(hpen, sizeof(lp.lopnStyle), &lp);
896         ok(!size, "GetObject should fail: size %d, error %ld\n", size, GetLastError());
897
898         memset(&lp, 0xb0, sizeof(lp));
899         SetLastError(0xdeadbeef);
900         size = GetObject(hpen, sizeof(lp), &lp);
901         /* for some reason XP differenciates PS_NULL here */
902         if (pen[i].style == PS_NULL)
903         {
904             ok(size == sizeof(LOGPEN), "GetObject returned %d, error %ld\n", size, GetLastError());
905             ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
906             ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %ld\n", pen[i].ret_width, lp.lopnWidth.x);
907             ok(lp.lopnWidth.y == 0, "expected 0, got %ld\n", lp.lopnWidth.y);
908             ok(lp.lopnColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, lp.lopnColor);
909         }
910         else
911             /* XP doesn't set last error here */
912             ok(!size /*&& GetLastError() == ERROR_INVALID_PARAMETER*/,
913                "GetObject should fail: size %d, error %ld\n", size, GetLastError());
914
915         memset(&ext_pen, 0xb0, sizeof(ext_pen));
916         SetLastError(0xdeadbeef);
917         /* buffer is too small for user styles */
918         size = GetObject(hpen, sizeof(elp), &ext_pen.elp);
919         switch (pen[i].style)
920         {
921         case PS_NULL:
922             ok(size == sizeof(EXTLOGPEN),
923                 "GetObject returned %d, error %ld\n", size, GetLastError());
924             ok(ext_pen.elp.elpHatch == 0, "expected 0, got %p\n", (void *)ext_pen.elp.elpHatch);
925             ok(ext_pen.elp.elpNumEntries == 0, "expected 0, got %lx\n", ext_pen.elp.elpNumEntries);
926
927             /* for PS_NULL it also works this way */
928             SetLastError(0xdeadbeef);
929             size = GetObject(hpen, sizeof(ext_pen), &lp);
930             ok(size == sizeof(LOGPEN),
931                 "GetObject returned %d, error %ld\n", size, GetLastError());
932             ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
933             ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %ld\n", pen[i].ret_width, lp.lopnWidth.x);
934             ok(lp.lopnWidth.y == 0, "expected 0, got %ld\n", lp.lopnWidth.y);
935             ok(lp.lopnColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, lp.lopnColor);
936             break;
937
938         case PS_USERSTYLE:
939             ok(!size /*&& GetLastError() == ERROR_INVALID_PARAMETER*/,
940                "GetObject should fail: size %d, error %ld\n", size, GetLastError());
941             size = GetObject(hpen, sizeof(ext_pen), &ext_pen.elp);
942             ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry) + sizeof(user_style),
943                "GetObject returned %d, error %ld\n", size, GetLastError());
944             ok(ext_pen.elp.elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen.elp.elpHatch);
945             ok(ext_pen.elp.elpNumEntries == 2, "expected 0, got %lx\n", ext_pen.elp.elpNumEntries);
946             ok(ext_pen.elp.elpStyleEntry[0] == 0xabc, "expected 0xabc, got %lx\n", ext_pen.elp.elpStyleEntry[0]);
947             ok(ext_pen.elp.elpStyleEntry[1] == 0xdef, "expected 0xabc, got %lx\n", ext_pen.elp.elpStyleEntry[1]);
948             break;
949
950         default:
951             ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry),
952                "GetObject returned %d, error %ld\n", size, GetLastError());
953             ok(ext_pen.elp.elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen.elp.elpHatch);
954             ok(ext_pen.elp.elpNumEntries == 0, "expected 0, got %lx\n", ext_pen.elp.elpNumEntries);
955             break;
956         }
957
958         /* for some reason XP differenciates PS_NULL here */
959         if (pen[i].style == PS_NULL)
960             ok(ext_pen.elp.elpPenStyle == pen[i].ret_style, "expected %x, got %lx\n", pen[i].ret_style, ext_pen.elp.elpPenStyle);
961         else
962         {
963 if (pen[i].style == PS_USERSTYLE)
964 {
965     todo_wine
966             ok(ext_pen.elp.elpPenStyle == (PS_GEOMETRIC | pen[i].style), "expected %x, got %lx\n", PS_GEOMETRIC | pen[i].style, ext_pen.elp.elpPenStyle);
967 }
968 else
969             ok(ext_pen.elp.elpPenStyle == (PS_GEOMETRIC | pen[i].style), "expected %x, got %lx\n", PS_GEOMETRIC | pen[i].style, ext_pen.elp.elpPenStyle);
970         }
971
972         if (pen[i].style == PS_NULL)
973             ok(ext_pen.elp.elpWidth == 0, "expected 0, got %lx\n", ext_pen.elp.elpWidth);
974         else
975             ok(ext_pen.elp.elpWidth == pen[i].ret_width, "expected %u, got %lx\n", pen[i].ret_width, ext_pen.elp.elpWidth);
976         ok(ext_pen.elp.elpColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, ext_pen.elp.elpColor);
977         ok(ext_pen.elp.elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %x\n", ext_pen.elp.elpBrushStyle);
978
979         DeleteObject(hpen);
980     }
981 }
982
983 static void test_bitmap(void)
984 {
985     char buf[256], buf_cmp[256];
986     HBITMAP hbmp, hbmp_old;
987     HDC hdc;
988     BITMAP bm;
989     INT ret;
990
991     hdc = CreateCompatibleDC(0);
992     assert(hdc != 0);
993
994     hbmp = CreateBitmap(15, 15, 1, 1, NULL);
995     assert(hbmp != NULL);
996
997     ret = GetObject(hbmp, sizeof(bm), &bm);
998     ok(ret == sizeof(bm), "%d != %d\n", ret, sizeof(bm));
999
1000     ok(bm.bmType == 0, "wrong bm.bmType %d\n", bm.bmType);
1001     ok(bm.bmWidth == 15, "wrong bm.bmWidth %d\n", bm.bmWidth);
1002     ok(bm.bmHeight == 15, "wrong bm.bmHeight %d\n", bm.bmHeight);
1003     ok(bm.bmWidthBytes == 2, "wrong bm.bmWidthBytes %d\n", bm.bmWidthBytes);
1004     ok(bm.bmPlanes == 1, "wrong bm.bmPlanes %d\n", bm.bmPlanes);
1005     ok(bm.bmBitsPixel == 1, "wrong bm.bmBitsPixel %d\n", bm.bmBitsPixel);
1006     ok(bm.bmBits == NULL, "wrong bm.bmBits %p\n", bm.bmBits);
1007
1008     assert(sizeof(buf) >= bm.bmWidthBytes * bm.bmHeight);
1009     assert(sizeof(buf) == sizeof(buf_cmp));
1010
1011     memset(buf_cmp, 0xAA, sizeof(buf_cmp));
1012     memset(buf_cmp, 0, bm.bmWidthBytes * bm.bmHeight);
1013
1014     memset(buf, 0xAA, sizeof(buf));
1015     ret = GetBitmapBits(hbmp, sizeof(buf), buf);
1016     ok(ret == bm.bmWidthBytes * bm.bmHeight, "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight);
1017     ok(!memcmp(buf, buf_cmp, sizeof(buf)), "buffers do not match\n");
1018
1019     hbmp_old = SelectObject(hdc, hbmp);
1020
1021     ret = GetObject(hbmp, sizeof(bm), &bm);
1022     ok(ret == sizeof(bm), "%d != %d\n", ret, sizeof(bm));
1023
1024     ok(bm.bmType == 0, "wrong bm.bmType %d\n", bm.bmType);
1025     ok(bm.bmWidth == 15, "wrong bm.bmWidth %d\n", bm.bmWidth);
1026     ok(bm.bmHeight == 15, "wrong bm.bmHeight %d\n", bm.bmHeight);
1027     ok(bm.bmWidthBytes == 2, "wrong bm.bmWidthBytes %d\n", bm.bmWidthBytes);
1028     ok(bm.bmPlanes == 1, "wrong bm.bmPlanes %d\n", bm.bmPlanes);
1029     ok(bm.bmBitsPixel == 1, "wrong bm.bmBitsPixel %d\n", bm.bmBitsPixel);
1030     ok(bm.bmBits == NULL, "wrong bm.bmBits %p\n", bm.bmBits);
1031
1032     memset(buf, 0xAA, sizeof(buf));
1033     ret = GetBitmapBits(hbmp, sizeof(buf), buf);
1034     ok(ret == bm.bmWidthBytes * bm.bmHeight, "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight);
1035     ok(!memcmp(buf, buf_cmp, sizeof(buf)), "buffers do not match\n");
1036
1037     hbmp_old = SelectObject(hdc, hbmp_old);
1038     ok(hbmp_old == hbmp, "wrong old bitmap %p\n", hbmp_old);
1039
1040     /* test various buffer sizes for GetObject */
1041     ret = GetObject(hbmp, sizeof(bm) * 2, &bm);
1042     ok(ret == sizeof(bm), "%d != %d\n", ret, sizeof(bm));
1043
1044     ret = GetObject(hbmp, sizeof(bm) / 2, &bm);
1045     ok(ret == 0, "%d != 0\n", ret);
1046
1047     ret = GetObject(hbmp, 0, &bm);
1048     ok(ret == 0, "%d != 0\n", ret);
1049
1050     ret = GetObject(hbmp, 1, &bm);
1051     ok(ret == 0, "%d != 0\n", ret);
1052
1053     DeleteObject(hbmp);
1054     DeleteDC(hdc);
1055 }
1056
1057 START_TEST(gdiobj)
1058 {
1059     test_logfont();
1060     test_logpen();
1061     test_bitmap();
1062     test_bitmap_font();
1063     test_bitmap_font_metrics();
1064     test_gdi_objects();
1065     test_GdiGetCharDimensions();
1066     test_text_extents();
1067     test_thread_objects();
1068     test_GetCurrentObject();
1069 }