winex11: Reject too bright gamma ramps.
[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 || broken(ret == COMPLEXREGION), "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 || broken(ret == COMPLEXREGION), "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
109     SetRect(&rc, 0, 0, 50, 50);
110     ok(EqualRect(&rc, &rc_clip),
111        "rects are not equal: (%d,%d-%d,%d) - (%d,%d-%d,%d)\n",
112        rc.left, rc.top, rc.right, rc.bottom,
113        rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
114
115     ret = RestoreDC(hdc, 1);
116     ok(ret, "ret = %d\n", ret);
117
118     ret = GetClipBox(hdc, &rc_clip);
119     ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION), "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
120     SetRect(&rc, 0, 0, 100, 100);
121     ok(EqualRect(&rc, &rc_clip),
122        "rects are not equal: (%d,%d-%d,%d) - (%d,%d-%d,%d)\n",
123        rc.left, rc.top, rc.right, rc.bottom,
124        rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
125
126     DeleteObject(hrgn);
127     ReleaseDC(hwnd, hdc);
128     DestroyWindow(hwnd);
129 }
130
131 static void test_savedc(void)
132 {
133     HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
134     int ret;
135
136     ok(hdc != NULL, "CreateDC rets %p\n", hdc);
137
138     ret = SaveDC(hdc);
139     ok(ret == 1, "ret = %d\n", ret);
140     ret = SaveDC(hdc);
141     ok(ret == 2, "ret = %d\n", ret);
142     ret = SaveDC(hdc);
143     ok(ret == 3, "ret = %d\n", ret);
144     ret = RestoreDC(hdc, -1);
145     ok(ret, "ret = %d\n", ret);
146     ret = SaveDC(hdc);
147     ok(ret == 3, "ret = %d\n", ret);
148     ret = RestoreDC(hdc, 1);
149     ok(ret, "ret = %d\n", ret);
150     ret = SaveDC(hdc);
151     ok(ret == 1, "ret = %d\n", ret);
152     ret = SaveDC(hdc);
153     ok(ret == 2, "ret = %d\n", ret);
154     ret = SaveDC(hdc);
155     ok(ret == 3, "ret = %d\n", ret);
156     ret = RestoreDC(hdc, -2);
157     ok(ret, "ret = %d\n", ret);
158     ret = SaveDC(hdc);
159     ok(ret == 2, "ret = %d\n", ret);
160     ret = RestoreDC(hdc, -2);
161     ok(ret, "ret = %d\n", ret);
162     ret = SaveDC(hdc);
163     ok(ret == 1, "ret = %d\n", ret);
164     ret = SaveDC(hdc);
165     ok(ret == 2, "ret = %d\n", ret); 
166     ret = RestoreDC(hdc, -4);
167     ok(!ret, "ret = %d\n", ret);
168     ret = RestoreDC(hdc, 3);
169     ok(!ret, "ret = %d\n", ret);
170
171     /* Under Win9x the following RestoreDC call succeeds and clears the save stack. */
172     ret = RestoreDC(hdc, -3);
173     ok(!ret ||
174        broken(ret), /* Win9x */
175        "ret = %d\n", ret);
176
177     /* Trying to clear an empty save stack fails. */
178     ret = RestoreDC(hdc, -3);
179     ok(!ret, "ret = %d\n", ret);
180
181     ret = SaveDC(hdc);
182     ok(ret == 3 ||
183        broken(ret == 1), /* Win9x */
184        "ret = %d\n", ret);
185
186     /* Under Win9x the following RestoreDC call succeeds and clears the save stack. */
187     ret = RestoreDC(hdc, 0);
188     ok(!ret ||
189        broken(ret), /* Win9x */
190        "ret = %d\n", ret);
191
192     /* Trying to clear an empty save stack fails. */
193     ret = RestoreDC(hdc, 0);
194     ok(!ret, "ret = %d\n", ret);
195
196     ret = RestoreDC(hdc, 1);
197     ok(ret ||
198        broken(!ret), /* Win9x */
199        "ret = %d\n", ret);
200
201     DeleteDC(hdc);
202 }
203
204 static void test_GdiConvertToDevmodeW(void)
205 {
206     DEVMODEW * (WINAPI *pGdiConvertToDevmodeW)(const DEVMODEA *);
207     DEVMODEA dmA;
208     DEVMODEW *dmW;
209     BOOL ret;
210
211     pGdiConvertToDevmodeW = (void *)GetProcAddress(GetModuleHandleA("gdi32.dll"), "GdiConvertToDevmodeW");
212     if (!pGdiConvertToDevmodeW)
213     {
214         win_skip("GdiConvertToDevmodeW is not available on this platform\n");
215         return;
216     }
217
218     ret = EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &dmA);
219     ok(ret, "EnumDisplaySettingsExA error %u\n", GetLastError());
220     ok(dmA.dmSize >= FIELD_OFFSET(DEVMODEA, dmICMMethod), "dmSize is too small: %04x\n", dmA.dmSize);
221     ok(dmA.dmSize <= sizeof(DEVMODEA), "dmSize is too large: %04x\n", dmA.dmSize);
222
223     dmW = pGdiConvertToDevmodeW(&dmA);
224     ok(dmW->dmSize >= FIELD_OFFSET(DEVMODEW, dmICMMethod), "dmSize is too small: %04x\n", dmW->dmSize);
225     ok(dmW->dmSize <= sizeof(DEVMODEW), "dmSize is too large: %04x\n", dmW->dmSize);
226     HeapFree(GetProcessHeap(), 0, dmW);
227
228     dmA.dmSize = FIELD_OFFSET(DEVMODEA, dmFields) + sizeof(dmA.dmFields);
229     dmW = pGdiConvertToDevmodeW(&dmA);
230     ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmFields) + sizeof(dmW->dmFields),
231        "wrong size %u\n", dmW->dmSize);
232     HeapFree(GetProcessHeap(), 0, dmW);
233
234     dmA.dmICMMethod = DMICMMETHOD_NONE;
235     dmA.dmSize = FIELD_OFFSET(DEVMODEA, dmICMMethod) + sizeof(dmA.dmICMMethod);
236     dmW = pGdiConvertToDevmodeW(&dmA);
237     ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmICMMethod) + sizeof(dmW->dmICMMethod),
238        "wrong size %u\n", dmW->dmSize);
239     ok(dmW->dmICMMethod == DMICMMETHOD_NONE,
240        "expected DMICMMETHOD_NONE, got %u\n", dmW->dmICMMethod);
241     HeapFree(GetProcessHeap(), 0, dmW);
242
243     dmA.dmSize = 1024;
244     dmW = pGdiConvertToDevmodeW(&dmA);
245     ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmPanningHeight) + sizeof(dmW->dmPanningHeight),
246        "wrong size %u\n", dmW->dmSize);
247     HeapFree(GetProcessHeap(), 0, dmW);
248
249     SetLastError(0xdeadbeef);
250     dmA.dmSize = 0;
251     dmW = pGdiConvertToDevmodeW(&dmA);
252     ok(!dmW, "GdiConvertToDevmodeW should fail\n");
253     ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
254
255     /* this is the minimal dmSize that XP accepts */
256     dmA.dmSize = FIELD_OFFSET(DEVMODEA, dmFields);
257     dmW = pGdiConvertToDevmodeW(&dmA);
258     ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmFields),
259        "expected %04x, got %04x\n", FIELD_OFFSET(DEVMODEW, dmFields), dmW->dmSize);
260     HeapFree(GetProcessHeap(), 0, dmW);
261 }
262
263 static void test_CreateCompatibleDC(void)
264 {
265     BOOL bRet;
266     HDC hDC;
267     HDC hNewDC;
268
269     /* Create a DC compatible with the screen */
270     hDC = CreateCompatibleDC(NULL);
271     ok(hDC != NULL, "CreateCompatibleDC returned %p\n", hDC);
272
273     /* Delete this DC, this should succeed */
274     bRet = DeleteDC(hDC);
275     ok(bRet == TRUE, "DeleteDC returned %u\n", bRet);
276
277     /* Try to create a DC compatible to the deleted DC. This has to fail */
278     hNewDC = CreateCompatibleDC(hDC);
279     ok(hNewDC == NULL, "CreateCompatibleDC returned %p\n", hNewDC);
280 }
281
282 static void test_DC_bitmap(void)
283 {
284     HDC hdc, hdcmem;
285     DWORD bits[64];
286     HBITMAP hbmp, oldhbmp;
287     COLORREF col;
288     int i, bitspixel;
289
290     /* fill bitmap data with b&w pattern */
291     for( i = 0; i < 64; i++) bits[i] = i & 1 ? 0 : 0xffffff;
292
293     hdc = GetDC(0);
294     ok( hdc != NULL, "CreateDC rets %p\n", hdc);
295     bitspixel = GetDeviceCaps( hdc, BITSPIXEL);
296     /* create a memory dc */
297     hdcmem = CreateCompatibleDC( hdc);
298     ok( hdcmem != NULL, "CreateCompatibleDC rets %p\n", hdcmem);
299     /* tests */
300     /* test monochrome bitmap: should always work */
301     hbmp = CreateBitmap(32, 32, 1, 1, bits);
302     ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
303     oldhbmp = SelectObject( hdcmem, hbmp);
304     ok( oldhbmp != NULL, "SelectObject returned NULL\n" ); /* a memdc always has a bitmap selected */
305     col = GetPixel( hdcmem, 0, 0);
306     ok( col == 0xffffff, "GetPixel returned %08x, expected 00ffffff\n", col);
307     col = GetPixel( hdcmem, 1, 1);
308     ok( col == 0x000000, "GetPixel returned %08x, expected 00000000\n", col);
309     col = GetPixel( hdcmem, 100, 1);
310     ok( col == CLR_INVALID, "GetPixel returned %08x, expected ffffffff\n", col);
311     SelectObject( hdcmem, oldhbmp);
312     DeleteObject( hbmp);
313
314     /* test with 2 bits color depth, not likely to succeed */
315     hbmp = CreateBitmap(16, 16, 1, 2, bits);
316     ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
317     oldhbmp = SelectObject( hdcmem, hbmp);
318     if( bitspixel != 2)
319         ok( !oldhbmp, "SelectObject of a bitmap with 2 bits/pixel should return  NULL\n");
320     if( oldhbmp) SelectObject( hdcmem, oldhbmp);
321     DeleteObject( hbmp);
322
323     /* test with 16 bits color depth, might succeed */
324     hbmp = CreateBitmap(6, 6, 1, 16, bits);
325     ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
326     oldhbmp = SelectObject( hdcmem, hbmp);
327     if( bitspixel == 16) {
328         ok( oldhbmp != NULL, "SelectObject returned NULL\n" );
329         col = GetPixel( hdcmem, 0, 0);
330         ok( col == 0xffffff,
331             "GetPixel of a bitmap with 16 bits/pixel returned %08x, expected 00ffffff\n", col);
332         col = GetPixel( hdcmem, 1, 1);
333         ok( col == 0x000000,
334             "GetPixel of a bitmap with 16 bits/pixel returned returned %08x, expected 00000000\n", col);
335     }
336     if( oldhbmp) SelectObject( hdcmem, oldhbmp);
337     DeleteObject( hbmp);
338
339     /* test with 32 bits color depth, probably succeed */
340     hbmp = CreateBitmap(4, 4, 1, 32, bits);
341     ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
342     oldhbmp = SelectObject( hdcmem, hbmp);
343     if( bitspixel == 32) {
344         ok( oldhbmp != NULL, "SelectObject returned NULL\n" );
345         col = GetPixel( hdcmem, 0, 0);
346         ok( col == 0xffffff,
347             "GetPixel of a bitmap with 32 bits/pixel returned %08x, expected 00ffffff\n", col);
348         col = GetPixel( hdcmem, 1, 1);
349         ok( col == 0x000000,
350             "GetPixel of a bitmap with 32 bits/pixel returned returned %08x, expected 00000000\n", col);
351     }
352     if( oldhbmp) SelectObject( hdcmem, oldhbmp);
353     DeleteObject( hbmp);
354     ReleaseDC( 0, hdc );
355 }
356
357 static void test_DeleteDC(void)
358 {
359     HWND hwnd;
360     HDC hdc, hdc_test;
361     WNDCLASSEX cls;
362     int ret;
363
364     /* window DC */
365     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
366                            0, 0, 0, NULL);
367     ok(hwnd != 0, "CreateWindowExA failed\n");
368
369     hdc = GetDC(hwnd);
370     ok(hdc != 0, "GetDC failed\n");
371     ret = GetObjectType(hdc);
372     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
373     ret = DeleteDC(hdc);
374     ok(ret, "DeleteDC failed\n");
375     ret = GetObjectType(hdc);
376     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
377
378     hdc = GetWindowDC(hwnd);
379     ok(hdc != 0, "GetDC failed\n");
380     ret = GetObjectType(hdc);
381     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
382     ret = DeleteDC(hdc);
383     ok(ret, "DeleteDC failed\n");
384     ret = GetObjectType(hdc);
385     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
386
387     DestroyWindow(hwnd);
388
389     /* desktop window DC */
390     hwnd = GetDesktopWindow();
391     ok(hwnd != 0, "GetDesktopWindow failed\n");
392
393     hdc = GetDC(hwnd);
394     ok(hdc != 0, "GetDC failed\n");
395     ret = GetObjectType(hdc);
396     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
397     ret = DeleteDC(hdc);
398     ok(ret, "DeleteDC failed\n");
399     ret = GetObjectType(hdc);
400     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
401
402     hdc = GetWindowDC(hwnd);
403     ok(hdc != 0, "GetDC failed\n");
404     ret = GetObjectType(hdc);
405     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
406     ret = DeleteDC(hdc);
407     ok(ret, "DeleteDC failed\n");
408     ret = GetObjectType(hdc);
409     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
410
411     /* CS_CLASSDC */
412     memset(&cls, 0, sizeof(cls));
413     cls.cbSize = sizeof(cls);
414     cls.style = CS_CLASSDC;
415     cls.hInstance = GetModuleHandle(0);
416     cls.lpszClassName = "Wine class DC";
417     cls.lpfnWndProc = DefWindowProcA;
418     ret = RegisterClassExA(&cls);
419     ok(ret, "RegisterClassExA failed\n");
420
421     hwnd = CreateWindowExA(0, "Wine class DC", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
422                            0, 0, 0, NULL);
423     ok(hwnd != 0, "CreateWindowExA failed\n");
424
425     hdc = GetDC(hwnd);
426     ok(hdc != 0, "GetDC failed\n");
427     ret = GetObjectType(hdc);
428     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
429     ret = DeleteDC(hdc);
430     ok(ret, "DeleteDC failed\n");
431     ret = GetObjectType(hdc);
432     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
433     ret = ReleaseDC(hwnd, hdc);
434     ok(ret, "ReleaseDC failed\n");
435     ret = GetObjectType(hdc);
436     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
437
438     hdc_test = hdc;
439
440     hdc = GetWindowDC(hwnd);
441     ok(hdc != 0, "GetDC failed\n");
442     ret = GetObjectType(hdc);
443     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
444     ret = DeleteDC(hdc);
445     ok(ret, "DeleteDC failed\n");
446     ret = GetObjectType(hdc);
447     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
448
449     DestroyWindow(hwnd);
450
451     ret = GetObjectType(hdc_test);
452     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
453
454     ret = UnregisterClassA("Wine class DC", GetModuleHandle(NULL));
455     ok(ret, "UnregisterClassA failed\n");
456
457     ret = GetObjectType(hdc_test);
458 todo_wine
459     ok(!ret, "GetObjectType should fail for a deleted DC\n");
460
461     /* CS_OWNDC */
462     memset(&cls, 0, sizeof(cls));
463     cls.cbSize = sizeof(cls);
464     cls.style = CS_OWNDC;
465     cls.hInstance = GetModuleHandle(0);
466     cls.lpszClassName = "Wine own DC";
467     cls.lpfnWndProc = DefWindowProcA;
468     ret = RegisterClassExA(&cls);
469     ok(ret, "RegisterClassExA failed\n");
470
471     hwnd = CreateWindowExA(0, "Wine own DC", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
472                            0, 0, 0, NULL);
473     ok(hwnd != 0, "CreateWindowExA failed\n");
474
475     hdc = GetDC(hwnd);
476     ok(hdc != 0, "GetDC failed\n");
477     ret = GetObjectType(hdc);
478     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
479     ret = DeleteDC(hdc);
480     ok(ret, "DeleteDC failed\n");
481     ret = GetObjectType(hdc);
482     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
483     ret = ReleaseDC(hwnd, hdc);
484     ok(ret, "ReleaseDC failed\n");
485     ret = GetObjectType(hdc);
486     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
487
488     hdc = GetWindowDC(hwnd);
489     ok(hdc != 0, "GetDC failed\n");
490     ret = GetObjectType(hdc);
491     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
492     ret = DeleteDC(hdc);
493     ok(ret, "DeleteDC failed\n");
494     ret = GetObjectType(hdc);
495     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
496
497     DestroyWindow(hwnd);
498
499     ret = UnregisterClassA("Wine own DC", GetModuleHandle(NULL));
500     ok(ret, "UnregisterClassA failed\n");
501 }
502
503 static void test_boundsrect_invalid(void)
504 {
505     HDC hdc;
506     RECT rect, expect, set_rect;
507     UINT ret;
508
509     hdc = GetDC(NULL);
510     ok(hdc != NULL, "GetDC failed\n");
511
512     ret = GetBoundsRect(hdc, NULL, 0);
513     ok(ret == 0 ||
514        broken(ret == DCB_RESET), /* Win9x */
515        "Expected GetBoundsRect to return 0, got %u\n", ret);
516
517     ret = GetBoundsRect(hdc, NULL, ~0U);
518     ok(ret == 0 ||
519        broken(ret == DCB_RESET), /* Win9x */
520        "Expected GetBoundsRect to return 0, got %u\n", ret);
521
522     if (GetBoundsRect(hdc, NULL, 0) == DCB_RESET)
523         win_skip("Win9x fails catastrophically with first GetBoundsRect call\n");
524     else
525     {
526         /* Test parameter handling order. */
527         SetRect(&set_rect, 10, 20, 40, 50);
528         ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
529         ok(ret & DCB_RESET,
530            "Expected return flag DCB_RESET to be set, got %u\n", ret);
531
532         ret = GetBoundsRect(hdc, NULL, DCB_RESET);
533         ok(ret == 0,
534            "Expected GetBoundsRect to return 0, got %u\n", ret);
535
536         ret = GetBoundsRect(hdc, &rect, 0);
537         if (ret != DCB_SET) /* WinME */
538         {
539             ok(ret == DCB_RESET,
540                "Expected GetBoundsRect to return DCB_RESET, got %u\n", ret);
541             SetRect(&expect, 0, 0, 0, 0);
542             ok(EqualRect(&rect, &expect) ||
543                broken(EqualRect(&rect, &set_rect)), /* nt4 sp1-5 */
544                "Expected output rectangle (0,0)-(0,0), got (%d,%d)-(%d,%d)\n",
545                rect.left, rect.top, rect.right, rect.bottom);
546        }
547     }
548
549     if (GetBoundsRect(hdc, NULL, 0) == DCB_RESET)
550         win_skip("Win9x fails catastrophically with NULL device context parameter\n");
551     else
552     {
553         ret = GetBoundsRect(NULL, NULL, 0);
554         ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
555
556         ret = GetBoundsRect(NULL, NULL, ~0U);
557         ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
558
559         ret = SetBoundsRect(NULL, NULL, 0);
560         ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret);
561
562         ret = SetBoundsRect(NULL, NULL, ~0U);
563         ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret);
564     }
565
566     ReleaseDC(NULL, hdc);
567 }
568
569 static void test_desktop_colorres(void)
570 {
571     HDC hdc = GetDC(NULL);
572     int bitspixel, colorres;
573
574     bitspixel = GetDeviceCaps(hdc, BITSPIXEL);
575     ok(bitspixel != 0, "Expected to get valid BITSPIXEL capability value\n");
576
577     colorres = GetDeviceCaps(hdc, COLORRES);
578     ok(colorres != 0 ||
579        broken(colorres == 0), /* Win9x */
580        "Expected to get valid COLORRES capability value\n");
581
582     if (colorres)
583     {
584         switch (bitspixel)
585         {
586         case 8:
587             ok(colorres == 18,
588                "Expected COLORRES to be 18, got %d\n", colorres);
589             break;
590         case 16:
591             ok(colorres == 16,
592                "Expected COLORRES to be 16, got %d\n", colorres);
593             break;
594         case 24:
595         case 32:
596             ok(colorres == 24,
597                "Expected COLORRES to be 24, got %d\n", bitspixel);
598             break;
599         default:
600             ok(0, "Got unknown BITSPIXEL %d with COLORRES %d\n", bitspixel, colorres);
601             break;
602         }
603     }
604
605     ReleaseDC(NULL, hdc);
606 }
607
608 static void test_gamma(void)
609 {
610     BOOL ret;
611     HDC hdc = GetDC(NULL);
612     WORD oldramp[3][256], ramp[3][256];
613     INT i;
614
615     ret = GetDeviceGammaRamp(hdc, &oldramp);
616     if (!ret)
617     {
618         win_skip("GetDeviceGammaRamp failed, skipping tests\n");
619         goto done;
620     }
621
622     /* try to set back old ramp */
623     ret = SetDeviceGammaRamp(hdc, &oldramp);
624     if (!ret)
625     {
626         win_skip("SetDeviceGammaRamp failed, skipping tests\n");
627         goto done;
628     }
629
630     memcpy(ramp, oldramp, sizeof(ramp));
631
632     /* set one color ramp to zeros */
633     memset(ramp[0], 0, sizeof(ramp[0]));
634     ret = SetDeviceGammaRamp(hdc, &ramp);
635     ok(!ret, "SetDeviceGammaRamp succeeded\n");
636
637     /* set one color ramp to a flat straight rising line */
638     for (i = 0; i < 256; i++) ramp[0][i] = i;
639     ret = SetDeviceGammaRamp(hdc, &ramp);
640     todo_wine ok(!ret, "SetDeviceGammaRamp succeeded\n");
641
642     /* set one color ramp to a steep straight rising line */
643     for (i = 0; i < 256; i++) ramp[0][i] = i * 256;
644     ret = SetDeviceGammaRamp(hdc, &ramp);
645     ok(ret, "SetDeviceGammaRamp failed\n");
646
647     /* try a bright gamma ramp */
648     ramp[0][0] = 0;
649     ramp[0][1] = 0x7FFF;
650     for (i = 2; i < 256; i++) ramp[0][i] = 0xFFFF;
651     ret = SetDeviceGammaRamp(hdc, &ramp);
652     ok(!ret, "SetDeviceGammaRamp succeeded\n");
653
654     /* cleanup: set old ramp again */
655     ret = SetDeviceGammaRamp(hdc, &oldramp);
656     ok(ret, "SetDeviceGammaRamp failed\n");
657
658 done:
659     ReleaseDC(NULL, hdc);
660 }
661
662 START_TEST(dc)
663 {
664     test_savedc();
665     test_savedc_2();
666     test_GdiConvertToDevmodeW();
667     test_CreateCompatibleDC();
668     test_DC_bitmap();
669     test_DeleteDC();
670     test_boundsrect_invalid();
671     test_desktop_colorres();
672     test_gamma();
673 }