gdi32/tests: Skip GetGlyphIndices tests for non-ANSI codepages.
[wine] / dlls / gdi32 / tests / dc.c
1 /*
2  * Unit tests for dc functions
3  *
4  * Copyright (c) 2005 Huw Davies
5  * Copyright (c) 2005 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #define WINVER 0x0501 /* request latest DEVMODE */
23
24 #include <assert.h>
25 #include <stdio.h>
26
27 #include "wine/test.h"
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "winuser.h"
31 #include "winerror.h"
32
33 static void dump_region(HRGN hrgn)
34 {
35     DWORD i, size;
36     RGNDATA *data = NULL;
37     RECT *rect;
38
39     if (!hrgn)
40     {
41         printf( "(null) region\n" );
42         return;
43     }
44     if (!(size = GetRegionData( hrgn, 0, NULL ))) return;
45     if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return;
46     GetRegionData( hrgn, size, data );
47     printf( "%d rects:", data->rdh.nCount );
48     for (i = 0, rect = (RECT *)data->Buffer; i < data->rdh.nCount; i++, rect++)
49         printf( " (%d,%d)-(%d,%d)", rect->left, rect->top, rect->right, rect->bottom );
50     printf( "\n" );
51     HeapFree( GetProcessHeap(), 0, data );
52 }
53
54 static void test_savedc_2(void)
55 {
56     HWND hwnd;
57     HDC hdc;
58     HRGN hrgn;
59     RECT rc, rc_clip;
60     int ret;
61
62     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,
63                            0, 0, 0, NULL);
64     assert(hwnd != 0);
65     ShowWindow(hwnd, SW_SHOW);
66     UpdateWindow(hwnd);
67
68     hrgn = CreateRectRgn(0, 0, 0, 0);
69     assert(hrgn != 0);
70
71     hdc = GetDC(hwnd);
72     ok(hdc != NULL, "GetDC failed\n");
73
74     ret = GetClipBox(hdc, &rc_clip);
75     ok(ret == SIMPLEREGION, "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
76     ret = GetClipRgn(hdc, hrgn);
77     ok(ret == 0, "GetClipRgn returned %d instead of 0\n", ret);
78     ret = GetRgnBox(hrgn, &rc);
79     ok(ret == NULLREGION, "GetRgnBox returned %d (%d,%d-%d,%d) instead of NULLREGION\n",
80        ret, rc.left, rc.top, rc.right, rc.bottom);
81     /*dump_region(hrgn);*/
82     SetRect(&rc, 0, 0, 100, 100);
83     ok(EqualRect(&rc, &rc_clip),
84        "rects are not equal: (%d,%d-%d,%d) - (%d,%d-%d,%d)\n",
85        rc.left, rc.top, rc.right, rc.bottom,
86        rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
87
88     ret = SaveDC(hdc);
89 todo_wine
90 {
91     ok(ret == 1, "ret = %d\n", ret);
92 }
93
94     ret = IntersectClipRect(hdc, 0, 0, 50, 50);
95     if (ret == COMPLEXREGION)
96     {
97         /* XP returns COMPLEXREGION although dump_region reports only 1 rect */
98         trace("Windows BUG: IntersectClipRect returned %d instead of SIMPLEREGION\n", ret);
99         /* let's make sure that it's a simple region */
100         ret = GetClipRgn(hdc, hrgn);
101         ok(ret == 1, "GetClipRgn returned %d instead of 1\n", ret);
102         dump_region(hrgn);
103     }
104     else
105         ok(ret == SIMPLEREGION, "IntersectClipRect returned %d instead of SIMPLEREGION\n", ret);
106
107     ret = GetClipBox(hdc, &rc_clip);
108     ok(ret == SIMPLEREGION, "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
109     SetRect(&rc, 0, 0, 50, 50);
110     ok(EqualRect(&rc, &rc_clip), "rects are not equal\n");
111
112     ret = RestoreDC(hdc, 1);
113     ok(ret, "ret = %d\n", ret);
114
115     ret = GetClipBox(hdc, &rc_clip);
116     ok(ret == SIMPLEREGION, "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
117     SetRect(&rc, 0, 0, 100, 100);
118     ok(EqualRect(&rc, &rc_clip), "rects are not equal\n");
119
120     DeleteObject(hrgn);
121     ReleaseDC(hwnd, hdc);
122     DestroyWindow(hwnd);
123 }
124
125 static void test_savedc(void)
126 {
127     HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
128     int ret;
129
130     ok(hdc != NULL, "CreateDC rets %p\n", hdc);
131
132     ret = SaveDC(hdc);
133     ok(ret == 1, "ret = %d\n", ret);
134     ret = SaveDC(hdc);
135     ok(ret == 2, "ret = %d\n", ret);
136     ret = SaveDC(hdc);
137     ok(ret == 3, "ret = %d\n", ret);
138     ret = RestoreDC(hdc, -1);
139     ok(ret, "ret = %d\n", ret);
140     ret = SaveDC(hdc);
141     ok(ret == 3, "ret = %d\n", ret);
142     ret = RestoreDC(hdc, 1);
143     ok(ret, "ret = %d\n", ret);
144     ret = SaveDC(hdc);
145     ok(ret == 1, "ret = %d\n", ret);
146     ret = SaveDC(hdc);
147     ok(ret == 2, "ret = %d\n", ret);
148     ret = SaveDC(hdc);
149     ok(ret == 3, "ret = %d\n", ret);
150     ret = RestoreDC(hdc, -2);
151     ok(ret, "ret = %d\n", ret);
152     ret = SaveDC(hdc);
153     ok(ret == 2, "ret = %d\n", ret);
154     ret = RestoreDC(hdc, -2);
155     ok(ret, "ret = %d\n", ret);
156     ret = SaveDC(hdc);
157     ok(ret == 1, "ret = %d\n", ret);
158     ret = SaveDC(hdc);
159     ok(ret == 2, "ret = %d\n", ret); 
160     ret = RestoreDC(hdc, -4);
161     ok(!ret, "ret = %d\n", ret);
162     ret = RestoreDC(hdc, 3);
163     ok(!ret, "ret = %d\n", ret);
164
165     /* Under Win9x the following RestoreDC call succeeds and clears the save stack. */
166     ret = RestoreDC(hdc, -3);
167     ok(!ret ||
168        broken(ret), /* Win9x */
169        "ret = %d\n", ret);
170
171     /* Trying to clear an empty save stack fails. */
172     ret = RestoreDC(hdc, -3);
173     ok(!ret, "ret = %d\n", ret);
174
175     ret = SaveDC(hdc);
176     ok(ret == 3 ||
177        broken(ret == 1), /* Win9x */
178        "ret = %d\n", ret);
179
180     /* Under Win9x the following RestoreDC call succeeds and clears the save stack. */
181     ret = RestoreDC(hdc, 0);
182     ok(!ret ||
183        broken(ret), /* Win9x */
184        "ret = %d\n", ret);
185
186     /* Trying to clear an empty save stack fails. */
187     ret = RestoreDC(hdc, 0);
188     ok(!ret, "ret = %d\n", ret);
189
190     ret = RestoreDC(hdc, 1);
191     ok(ret ||
192        broken(!ret), /* Win9x */
193        "ret = %d\n", ret);
194
195     DeleteDC(hdc);
196 }
197
198 static void test_GdiConvertToDevmodeW(void)
199 {
200     DEVMODEW * (WINAPI *pGdiConvertToDevmodeW)(const DEVMODEA *);
201     DEVMODEA dmA;
202     DEVMODEW *dmW;
203     BOOL ret;
204
205     pGdiConvertToDevmodeW = (void *)GetProcAddress(GetModuleHandleA("gdi32.dll"), "GdiConvertToDevmodeW");
206     if (!pGdiConvertToDevmodeW)
207     {
208         win_skip("GdiConvertToDevmodeW is not available on this platform\n");
209         return;
210     }
211
212     ret = EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &dmA);
213     ok(ret, "EnumDisplaySettingsExA error %u\n", GetLastError());
214     ok(dmA.dmSize >= FIELD_OFFSET(DEVMODEA, dmICMMethod), "dmSize is too small: %04x\n", dmA.dmSize);
215     ok(dmA.dmSize <= sizeof(DEVMODEA), "dmSize is too large: %04x\n", dmA.dmSize);
216
217     dmW = pGdiConvertToDevmodeW(&dmA);
218     ok(dmW->dmSize >= FIELD_OFFSET(DEVMODEW, dmICMMethod), "dmSize is too small: %04x\n", dmW->dmSize);
219     ok(dmW->dmSize <= sizeof(DEVMODEW), "dmSize is too large: %04x\n", dmW->dmSize);
220     HeapFree(GetProcessHeap(), 0, dmW);
221
222     dmA.dmSize = FIELD_OFFSET(DEVMODEA, dmFields) + sizeof(dmA.dmFields);
223     dmW = pGdiConvertToDevmodeW(&dmA);
224     ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmFields) + sizeof(dmW->dmFields),
225        "wrong size %u\n", dmW->dmSize);
226     HeapFree(GetProcessHeap(), 0, dmW);
227
228     dmA.dmICMMethod = DMICMMETHOD_NONE;
229     dmA.dmSize = FIELD_OFFSET(DEVMODEA, dmICMMethod) + sizeof(dmA.dmICMMethod);
230     dmW = pGdiConvertToDevmodeW(&dmA);
231     ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmICMMethod) + sizeof(dmW->dmICMMethod),
232        "wrong size %u\n", dmW->dmSize);
233     ok(dmW->dmICMMethod == DMICMMETHOD_NONE,
234        "expected DMICMMETHOD_NONE, got %u\n", dmW->dmICMMethod);
235     HeapFree(GetProcessHeap(), 0, dmW);
236
237     dmA.dmSize = 1024;
238     dmW = pGdiConvertToDevmodeW(&dmA);
239     ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmPanningHeight) + sizeof(dmW->dmPanningHeight),
240        "wrong size %u\n", dmW->dmSize);
241     HeapFree(GetProcessHeap(), 0, dmW);
242
243     SetLastError(0xdeadbeef);
244     dmA.dmSize = 0;
245     dmW = pGdiConvertToDevmodeW(&dmA);
246     ok(!dmW, "GdiConvertToDevmodeW should fail\n");
247     ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
248
249     /* this is the minimal dmSize that XP accepts */
250     dmA.dmSize = FIELD_OFFSET(DEVMODEA, dmFields);
251     dmW = pGdiConvertToDevmodeW(&dmA);
252     ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmFields),
253        "expected %04x, got %04x\n", FIELD_OFFSET(DEVMODEW, dmFields), dmW->dmSize);
254     HeapFree(GetProcessHeap(), 0, dmW);
255 }
256
257 static void test_CreateCompatibleDC(void)
258 {
259     BOOL bRet;
260     HDC hDC;
261     HDC hNewDC;
262
263     /* Create a DC compatible with the screen */
264     hDC = CreateCompatibleDC(NULL);
265     ok(hDC != NULL, "CreateCompatibleDC returned %p\n", hDC);
266
267     /* Delete this DC, this should succeed */
268     bRet = DeleteDC(hDC);
269     ok(bRet == TRUE, "DeleteDC returned %u\n", bRet);
270
271     /* Try to create a DC compatible to the deleted DC. This has to fail */
272     hNewDC = CreateCompatibleDC(hDC);
273     ok(hNewDC == NULL, "CreateCompatibleDC returned %p\n", hNewDC);
274 }
275
276 static void test_DC_bitmap(void)
277 {
278     HDC hdc, hdcmem;
279     DWORD bits[64];
280     HBITMAP hbmp, oldhbmp;
281     COLORREF col;
282     int i, bitspixel;
283
284     /* fill bitmap data with b&w pattern */
285     for( i = 0; i < 64; i++) bits[i] = i & 1 ? 0 : 0xffffff;
286
287     hdc = GetDC(0);
288     ok( hdc != NULL, "CreateDC rets %p\n", hdc);
289     bitspixel = GetDeviceCaps( hdc, BITSPIXEL);
290     /* create a memory dc */
291     hdcmem = CreateCompatibleDC( hdc);
292     ok( hdcmem != NULL, "CreateCompatibleDC rets %p\n", hdcmem);
293     /* tests */
294     /* test monochrome bitmap: should always work */
295     hbmp = CreateBitmap(32, 32, 1, 1, bits);
296     ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
297     oldhbmp = SelectObject( hdcmem, hbmp);
298     ok( oldhbmp != NULL, "SelectObject returned NULL\n" ); /* a memdc always has a bitmap selected */
299     col = GetPixel( hdcmem, 0, 0);
300     ok( col == 0xffffff, "GetPixel returned %08x, expected 00ffffff\n", col);
301     col = GetPixel( hdcmem, 1, 1);
302     ok( col == 0x000000, "GetPixel returned %08x, expected 00000000\n", col);
303     col = GetPixel( hdcmem, 100, 1);
304     ok( col == CLR_INVALID, "GetPixel returned %08x, expected ffffffff\n", col);
305     SelectObject( hdcmem, oldhbmp);
306     DeleteObject( hbmp);
307
308     /* test with 2 bits color depth, not likely to succeed */
309     hbmp = CreateBitmap(16, 16, 1, 2, bits);
310     ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
311     oldhbmp = SelectObject( hdcmem, hbmp);
312     if( bitspixel != 2)
313         ok( !oldhbmp, "SelectObject of a bitmap with 2 bits/pixel should return  NULL\n");
314     if( oldhbmp) SelectObject( hdcmem, oldhbmp);
315     DeleteObject( hbmp);
316
317     /* test with 16 bits color depth, might succeed */
318     hbmp = CreateBitmap(6, 6, 1, 16, bits);
319     ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
320     oldhbmp = SelectObject( hdcmem, hbmp);
321     if( bitspixel == 16) {
322         ok( oldhbmp != NULL, "SelectObject returned NULL\n" );
323         col = GetPixel( hdcmem, 0, 0);
324         ok( col == 0xffffff,
325             "GetPixel of a bitmap with 16 bits/pixel returned %08x, expected 00ffffff\n", col);
326         col = GetPixel( hdcmem, 1, 1);
327         ok( col == 0x000000,
328             "GetPixel of a bitmap with 16 bits/pixel returned returned %08x, expected 00000000\n", col);
329     }
330     if( oldhbmp) SelectObject( hdcmem, oldhbmp);
331     DeleteObject( hbmp);
332
333     /* test with 32 bits color depth, probably succeed */
334     hbmp = CreateBitmap(4, 4, 1, 32, bits);
335     ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
336     oldhbmp = SelectObject( hdcmem, hbmp);
337     if( bitspixel == 32) {
338         ok( oldhbmp != NULL, "SelectObject returned NULL\n" );
339         col = GetPixel( hdcmem, 0, 0);
340         ok( col == 0xffffff,
341             "GetPixel of a bitmap with 32 bits/pixel returned %08x, expected 00ffffff\n", col);
342         col = GetPixel( hdcmem, 1, 1);
343         ok( col == 0x000000,
344             "GetPixel of a bitmap with 32 bits/pixel returned returned %08x, expected 00000000\n", col);
345     }
346     if( oldhbmp) SelectObject( hdcmem, oldhbmp);
347     DeleteObject( hbmp);
348     ReleaseDC( 0, hdc );
349 }
350
351 static void test_DeleteDC(void)
352 {
353     HWND hwnd;
354     HDC hdc, hdc_test;
355     WNDCLASSEX cls;
356     int ret;
357
358     /* window DC */
359     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
360                            0, 0, 0, NULL);
361     ok(hwnd != 0, "CreateWindowExA failed\n");
362
363     hdc = GetDC(hwnd);
364     ok(hdc != 0, "GetDC failed\n");
365     ret = GetObjectType(hdc);
366     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
367     ret = DeleteDC(hdc);
368     ok(ret, "DeleteDC failed\n");
369     ret = GetObjectType(hdc);
370     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
371
372     hdc = GetWindowDC(hwnd);
373     ok(hdc != 0, "GetDC failed\n");
374     ret = GetObjectType(hdc);
375     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
376     ret = DeleteDC(hdc);
377     ok(ret, "DeleteDC failed\n");
378     ret = GetObjectType(hdc);
379     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
380
381     DestroyWindow(hwnd);
382
383     /* desktop window DC */
384     hwnd = GetDesktopWindow();
385     ok(hwnd != 0, "GetDesktopWindow failed\n");
386
387     hdc = GetDC(hwnd);
388     ok(hdc != 0, "GetDC failed\n");
389     ret = GetObjectType(hdc);
390     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
391     ret = DeleteDC(hdc);
392     ok(ret, "DeleteDC failed\n");
393     ret = GetObjectType(hdc);
394     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
395
396     hdc = GetWindowDC(hwnd);
397     ok(hdc != 0, "GetDC failed\n");
398     ret = GetObjectType(hdc);
399     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
400     ret = DeleteDC(hdc);
401     ok(ret, "DeleteDC failed\n");
402     ret = GetObjectType(hdc);
403     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
404
405     /* CS_CLASSDC */
406     memset(&cls, 0, sizeof(cls));
407     cls.cbSize = sizeof(cls);
408     cls.style = CS_CLASSDC;
409     cls.hInstance = GetModuleHandle(0);
410     cls.lpszClassName = "Wine class DC";
411     cls.lpfnWndProc = DefWindowProcA;
412     ret = RegisterClassExA(&cls);
413     ok(ret, "RegisterClassExA failed\n");
414
415     hwnd = CreateWindowExA(0, "Wine class DC", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
416                            0, 0, 0, NULL);
417     ok(hwnd != 0, "CreateWindowExA failed\n");
418
419     hdc = GetDC(hwnd);
420     ok(hdc != 0, "GetDC failed\n");
421     ret = GetObjectType(hdc);
422     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
423     ret = DeleteDC(hdc);
424     ok(ret, "DeleteDC failed\n");
425     ret = GetObjectType(hdc);
426     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
427     ret = ReleaseDC(hwnd, hdc);
428     ok(ret, "ReleaseDC failed\n");
429     ret = GetObjectType(hdc);
430     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
431
432     hdc_test = hdc;
433
434     hdc = GetWindowDC(hwnd);
435     ok(hdc != 0, "GetDC failed\n");
436     ret = GetObjectType(hdc);
437     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
438     ret = DeleteDC(hdc);
439     ok(ret, "DeleteDC failed\n");
440     ret = GetObjectType(hdc);
441     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
442
443     DestroyWindow(hwnd);
444
445     ret = GetObjectType(hdc_test);
446     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
447
448     ret = UnregisterClassA("Wine class DC", GetModuleHandle(NULL));
449     ok(ret, "UnregisterClassA failed\n");
450
451     ret = GetObjectType(hdc_test);
452 todo_wine
453     ok(!ret, "GetObjectType should fail for a deleted DC\n");
454
455     /* CS_OWNDC */
456     memset(&cls, 0, sizeof(cls));
457     cls.cbSize = sizeof(cls);
458     cls.style = CS_OWNDC;
459     cls.hInstance = GetModuleHandle(0);
460     cls.lpszClassName = "Wine own DC";
461     cls.lpfnWndProc = DefWindowProcA;
462     ret = RegisterClassExA(&cls);
463     ok(ret, "RegisterClassExA failed\n");
464
465     hwnd = CreateWindowExA(0, "Wine own DC", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
466                            0, 0, 0, NULL);
467     ok(hwnd != 0, "CreateWindowExA failed\n");
468
469     hdc = GetDC(hwnd);
470     ok(hdc != 0, "GetDC failed\n");
471     ret = GetObjectType(hdc);
472     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
473     ret = DeleteDC(hdc);
474     ok(ret, "DeleteDC failed\n");
475     ret = GetObjectType(hdc);
476     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
477     ret = ReleaseDC(hwnd, hdc);
478     ok(ret, "ReleaseDC failed\n");
479     ret = GetObjectType(hdc);
480     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
481
482     hdc = GetWindowDC(hwnd);
483     ok(hdc != 0, "GetDC failed\n");
484     ret = GetObjectType(hdc);
485     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
486     ret = DeleteDC(hdc);
487     ok(ret, "DeleteDC failed\n");
488     ret = GetObjectType(hdc);
489     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
490
491     DestroyWindow(hwnd);
492
493     ret = UnregisterClassA("Wine own DC", GetModuleHandle(NULL));
494     ok(ret, "UnregisterClassA failed\n");
495 }
496
497 static void test_boundsrect_invalid(void)
498 {
499     HDC hdc;
500     RECT rect, expect;
501     UINT ret;
502
503     hdc = GetDC(NULL);
504     ok(hdc != NULL, "GetDC failed\n");
505
506     ret = GetBoundsRect(hdc, NULL, 0);
507     ok(ret == 0 ||
508        broken(ret == DCB_RESET), /* Win9x */
509        "Expected GetBoundsRect to return 0, got %u\n", ret);
510
511     ret = GetBoundsRect(hdc, NULL, ~0U);
512     ok(ret == 0 ||
513        broken(ret == DCB_RESET), /* Win9x */
514        "Expected GetBoundsRect to return 0, got %u\n", ret);
515
516     if (GetBoundsRect(hdc, NULL, 0) == DCB_RESET)
517         win_skip("Win9x fails catastrophically with first GetBoundsRect call\n");
518     else
519     {
520         /* Test parameter handling order. */
521         SetRect(&rect, 0, 0, 50, 50);
522         ret = SetBoundsRect(hdc, &rect, DCB_SET);
523         ok(ret & DCB_RESET,
524            "Expected return flag DCB_RESET to be set, got %u\n", ret);
525
526         ret = GetBoundsRect(hdc, NULL, DCB_RESET);
527         ok(ret == 0,
528            "Expected GetBoundsRect to return 0, got %u\n", ret);
529
530         ret = GetBoundsRect(hdc, &rect, 0);
531         ok(ret == DCB_RESET,
532            "Expected GetBoundsRect to return DCB_RESET, got %u\n", ret);
533         SetRect(&expect, 0, 0, 0, 0);
534         ok(EqualRect(&rect, &expect),
535            "Expected output rectangle (0,0)-(0,0), got (%d,%d)-(%d,%d)\n",
536            rect.left, rect.top, rect.right, rect.bottom);
537     }
538
539     if (GetBoundsRect(hdc, NULL, 0) == DCB_RESET)
540         win_skip("Win9x fails catastrophically with NULL device context parameter\n");
541     else
542     {
543         ret = GetBoundsRect(NULL, NULL, 0);
544         ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
545
546         ret = GetBoundsRect(NULL, NULL, ~0U);
547         ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
548
549         ret = SetBoundsRect(NULL, NULL, 0);
550         ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret);
551
552         ret = SetBoundsRect(NULL, NULL, ~0U);
553         ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret);
554     }
555
556     DeleteDC(hdc);
557 }
558
559 static void test_desktop_colorres(void)
560 {
561     HDC hdc = GetDC(NULL);
562     int bitspixel, colorres;
563
564     bitspixel = GetDeviceCaps(hdc, BITSPIXEL);
565     ok(bitspixel != 0, "Expected to get valid BITSPIXEL capability value\n");
566
567     colorres = GetDeviceCaps(hdc, COLORRES);
568     ok(colorres != 0 ||
569        broken(colorres == 0), /* Win9x */
570        "Expected to get valid COLORRES capability value\n");
571
572     if (colorres)
573     {
574         switch (bitspixel)
575         {
576         case 8:
577             ok(colorres == 18,
578                "Expected COLORRES to be 18, got %d\n", colorres);
579             break;
580         case 16:
581             ok(colorres == 16,
582                "Expected COLORRES to be 16, got %d\n", colorres);
583             break;
584         case 24:
585         case 32:
586             ok(colorres == 24,
587                "Expected COLORRES to be 24, got %d\n", bitspixel);
588             break;
589         default:
590             ok(0, "Got unknown BITSPIXEL %d with COLORRES %d\n", bitspixel, colorres);
591             break;
592         }
593     }
594
595     DeleteDC(hdc);
596 }
597
598 START_TEST(dc)
599 {
600     test_savedc();
601     test_savedc_2();
602     test_GdiConvertToDevmodeW();
603     test_CreateCompatibleDC();
604     test_DC_bitmap();
605     test_DeleteDC();
606     test_boundsrect_invalid();
607     test_desktop_colorres();
608 }