gdi32/tests: Add tests for path open/closed states.
[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 DWORD (WINAPI *pSetLayout)(HDC hdc, DWORD layout);
34
35 static void dump_region(HRGN hrgn)
36 {
37     DWORD i, size;
38     RGNDATA *data = NULL;
39     RECT *rect;
40
41     if (!hrgn)
42     {
43         printf( "(null) region\n" );
44         return;
45     }
46     if (!(size = GetRegionData( hrgn, 0, NULL ))) return;
47     if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return;
48     GetRegionData( hrgn, size, data );
49     printf( "%d rects:", data->rdh.nCount );
50     for (i = 0, rect = (RECT *)data->Buffer; i < data->rdh.nCount; i++, rect++)
51         printf( " (%d,%d)-(%d,%d)", rect->left, rect->top, rect->right, rect->bottom );
52     printf( "\n" );
53     HeapFree( GetProcessHeap(), 0, data );
54 }
55
56 static void test_savedc_2(void)
57 {
58     HWND hwnd;
59     HDC hdc;
60     HRGN hrgn;
61     RECT rc, rc_clip;
62     int ret;
63
64     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,
65                            0, 0, 0, NULL);
66     assert(hwnd != 0);
67     ShowWindow(hwnd, SW_SHOW);
68     UpdateWindow(hwnd);
69
70     hrgn = CreateRectRgn(0, 0, 0, 0);
71     assert(hrgn != 0);
72
73     hdc = GetDC(hwnd);
74     ok(hdc != NULL, "GetDC failed\n");
75
76     ret = GetClipBox(hdc, &rc_clip);
77     ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION), "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
78     ret = GetClipRgn(hdc, hrgn);
79     ok(ret == 0, "GetClipRgn returned %d instead of 0\n", ret);
80     ret = GetRgnBox(hrgn, &rc);
81     ok(ret == NULLREGION, "GetRgnBox returned %d (%d,%d-%d,%d) instead of NULLREGION\n",
82        ret, rc.left, rc.top, rc.right, rc.bottom);
83     /*dump_region(hrgn);*/
84     SetRect(&rc, 0, 0, 100, 100);
85     ok(EqualRect(&rc, &rc_clip),
86        "rects are not equal: (%d,%d-%d,%d) - (%d,%d-%d,%d)\n",
87        rc.left, rc.top, rc.right, rc.bottom,
88        rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
89
90     ret = SaveDC(hdc);
91 todo_wine
92 {
93     ok(ret == 1, "ret = %d\n", ret);
94 }
95
96     ret = IntersectClipRect(hdc, 0, 0, 50, 50);
97     if (ret == COMPLEXREGION)
98     {
99         /* XP returns COMPLEXREGION although dump_region reports only 1 rect */
100         trace("Windows BUG: IntersectClipRect returned %d instead of SIMPLEREGION\n", ret);
101         /* let's make sure that it's a simple region */
102         ret = GetClipRgn(hdc, hrgn);
103         ok(ret == 1, "GetClipRgn returned %d instead of 1\n", ret);
104         dump_region(hrgn);
105     }
106     else
107         ok(ret == SIMPLEREGION, "IntersectClipRect returned %d instead of SIMPLEREGION\n", ret);
108
109     ret = GetClipBox(hdc, &rc_clip);
110     ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION), "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
111     SetRect(&rc, 0, 0, 50, 50);
112     ok(EqualRect(&rc, &rc_clip),
113        "rects are not equal: (%d,%d-%d,%d) - (%d,%d-%d,%d)\n",
114        rc.left, rc.top, rc.right, rc.bottom,
115        rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
116
117     ret = RestoreDC(hdc, 1);
118     ok(ret, "ret = %d\n", ret);
119
120     ret = GetClipBox(hdc, &rc_clip);
121     ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION), "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
122     SetRect(&rc, 0, 0, 100, 100);
123     ok(EqualRect(&rc, &rc_clip),
124        "rects are not equal: (%d,%d-%d,%d) - (%d,%d-%d,%d)\n",
125        rc.left, rc.top, rc.right, rc.bottom,
126        rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
127
128     DeleteObject(hrgn);
129     ReleaseDC(hwnd, hdc);
130     DestroyWindow(hwnd);
131 }
132
133 static void test_savedc(void)
134 {
135     HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
136     int ret;
137
138     ok(hdc != NULL, "CreateDC rets %p\n", hdc);
139
140     ret = SaveDC(hdc);
141     ok(ret == 1, "ret = %d\n", ret);
142     ret = SaveDC(hdc);
143     ok(ret == 2, "ret = %d\n", ret);
144     ret = SaveDC(hdc);
145     ok(ret == 3, "ret = %d\n", ret);
146     ret = RestoreDC(hdc, -1);
147     ok(ret, "ret = %d\n", ret);
148     ret = SaveDC(hdc);
149     ok(ret == 3, "ret = %d\n", ret);
150     ret = RestoreDC(hdc, 1);
151     ok(ret, "ret = %d\n", ret);
152     ret = SaveDC(hdc);
153     ok(ret == 1, "ret = %d\n", ret);
154     ret = SaveDC(hdc);
155     ok(ret == 2, "ret = %d\n", ret);
156     ret = SaveDC(hdc);
157     ok(ret == 3, "ret = %d\n", ret);
158     ret = RestoreDC(hdc, -2);
159     ok(ret, "ret = %d\n", ret);
160     ret = SaveDC(hdc);
161     ok(ret == 2, "ret = %d\n", ret);
162     ret = RestoreDC(hdc, -2);
163     ok(ret, "ret = %d\n", ret);
164     ret = SaveDC(hdc);
165     ok(ret == 1, "ret = %d\n", ret);
166     ret = SaveDC(hdc);
167     ok(ret == 2, "ret = %d\n", ret); 
168     ret = RestoreDC(hdc, -4);
169     ok(!ret, "ret = %d\n", ret);
170     ret = RestoreDC(hdc, 3);
171     ok(!ret, "ret = %d\n", ret);
172
173     /* Under Win9x the following RestoreDC call succeeds and clears the save stack. */
174     ret = RestoreDC(hdc, -3);
175     ok(!ret ||
176        broken(ret), /* Win9x */
177        "ret = %d\n", ret);
178
179     /* Trying to clear an empty save stack fails. */
180     ret = RestoreDC(hdc, -3);
181     ok(!ret, "ret = %d\n", ret);
182
183     ret = SaveDC(hdc);
184     ok(ret == 3 ||
185        broken(ret == 1), /* Win9x */
186        "ret = %d\n", ret);
187
188     /* Under Win9x the following RestoreDC call succeeds and clears the save stack. */
189     ret = RestoreDC(hdc, 0);
190     ok(!ret ||
191        broken(ret), /* Win9x */
192        "ret = %d\n", ret);
193
194     /* Trying to clear an empty save stack fails. */
195     ret = RestoreDC(hdc, 0);
196     ok(!ret, "ret = %d\n", ret);
197
198     ret = RestoreDC(hdc, 1);
199     ok(ret ||
200        broken(!ret), /* Win9x */
201        "ret = %d\n", ret);
202
203     DeleteDC(hdc);
204 }
205
206 static void test_GdiConvertToDevmodeW(void)
207 {
208     DEVMODEW * (WINAPI *pGdiConvertToDevmodeW)(const DEVMODEA *);
209     DEVMODEA dmA;
210     DEVMODEW *dmW;
211     BOOL ret;
212
213     pGdiConvertToDevmodeW = (void *)GetProcAddress(GetModuleHandleA("gdi32.dll"), "GdiConvertToDevmodeW");
214     if (!pGdiConvertToDevmodeW)
215     {
216         win_skip("GdiConvertToDevmodeW is not available on this platform\n");
217         return;
218     }
219
220     ret = EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &dmA);
221     ok(ret, "EnumDisplaySettingsExA error %u\n", GetLastError());
222     ok(dmA.dmSize >= FIELD_OFFSET(DEVMODEA, dmICMMethod), "dmSize is too small: %04x\n", dmA.dmSize);
223     ok(dmA.dmSize <= sizeof(DEVMODEA), "dmSize is too large: %04x\n", dmA.dmSize);
224
225     dmW = pGdiConvertToDevmodeW(&dmA);
226     ok(dmW->dmSize >= FIELD_OFFSET(DEVMODEW, dmICMMethod), "dmSize is too small: %04x\n", dmW->dmSize);
227     ok(dmW->dmSize <= sizeof(DEVMODEW), "dmSize is too large: %04x\n", dmW->dmSize);
228     HeapFree(GetProcessHeap(), 0, dmW);
229
230     dmA.dmSize = FIELD_OFFSET(DEVMODEA, dmFields) + sizeof(dmA.dmFields);
231     dmW = pGdiConvertToDevmodeW(&dmA);
232     ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmFields) + sizeof(dmW->dmFields),
233        "wrong size %u\n", dmW->dmSize);
234     HeapFree(GetProcessHeap(), 0, dmW);
235
236     dmA.dmICMMethod = DMICMMETHOD_NONE;
237     dmA.dmSize = FIELD_OFFSET(DEVMODEA, dmICMMethod) + sizeof(dmA.dmICMMethod);
238     dmW = pGdiConvertToDevmodeW(&dmA);
239     ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmICMMethod) + sizeof(dmW->dmICMMethod),
240        "wrong size %u\n", dmW->dmSize);
241     ok(dmW->dmICMMethod == DMICMMETHOD_NONE,
242        "expected DMICMMETHOD_NONE, got %u\n", dmW->dmICMMethod);
243     HeapFree(GetProcessHeap(), 0, dmW);
244
245     dmA.dmSize = 1024;
246     dmW = pGdiConvertToDevmodeW(&dmA);
247     ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmPanningHeight) + sizeof(dmW->dmPanningHeight),
248        "wrong size %u\n", dmW->dmSize);
249     HeapFree(GetProcessHeap(), 0, dmW);
250
251     SetLastError(0xdeadbeef);
252     dmA.dmSize = 0;
253     dmW = pGdiConvertToDevmodeW(&dmA);
254     ok(!dmW, "GdiConvertToDevmodeW should fail\n");
255     ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
256
257     /* this is the minimal dmSize that XP accepts */
258     dmA.dmSize = FIELD_OFFSET(DEVMODEA, dmFields);
259     dmW = pGdiConvertToDevmodeW(&dmA);
260     ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmFields),
261        "expected %04x, got %04x\n", FIELD_OFFSET(DEVMODEW, dmFields), dmW->dmSize);
262     HeapFree(GetProcessHeap(), 0, dmW);
263 }
264
265 static void test_CreateCompatibleDC(void)
266 {
267     BOOL bRet;
268     HDC hdc, hNewDC, hdcMetafile;
269     HBITMAP bitmap;
270     INT caps;
271
272     bitmap = CreateBitmap( 10, 10, 1, 1, NULL );
273
274     /* Create a DC compatible with the screen */
275     hdc = CreateCompatibleDC(NULL);
276     ok(hdc != NULL, "CreateCompatibleDC returned %p\n", hdc);
277     ok( SelectObject( hdc, bitmap ) != 0, "SelectObject failed\n" );
278     caps = GetDeviceCaps( hdc, TECHNOLOGY );
279     ok( caps == DT_RASDISPLAY, "wrong caps %u\n", caps );
280
281     /* Delete this DC, this should succeed */
282     bRet = DeleteDC(hdc);
283     ok(bRet == TRUE, "DeleteDC returned %u\n", bRet);
284
285     /* Try to create a DC compatible to the deleted DC. This has to fail */
286     hNewDC = CreateCompatibleDC(hdc);
287     ok(hNewDC == NULL, "CreateCompatibleDC returned %p\n", hNewDC);
288
289     hdc = GetDC( 0 );
290     hdcMetafile = CreateEnhMetaFileA(hdc, NULL, NULL, NULL);
291     ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
292     hNewDC = CreateCompatibleDC( hdcMetafile );
293     ok(hNewDC != NULL, "CreateCompatibleDC failed\n");
294     ok( SelectObject( hNewDC, bitmap ) != 0, "SelectObject failed\n" );
295     caps = GetDeviceCaps( hdcMetafile, TECHNOLOGY );
296     ok( caps == DT_RASDISPLAY, "wrong caps %u\n", caps );
297     caps = GetDeviceCaps( hNewDC, TECHNOLOGY );
298     ok( caps == DT_RASDISPLAY, "wrong caps %u\n", caps );
299     DeleteDC( hNewDC );
300     DeleteEnhMetaFile( CloseEnhMetaFile( hdcMetafile ));
301     ReleaseDC( 0, hdc );
302
303     hdcMetafile = CreateMetaFileA(NULL);
304     ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
305     hNewDC = CreateCompatibleDC( hdcMetafile );
306     ok(hNewDC == NULL, "CreateCompatibleDC succeeded\n");
307     caps = GetDeviceCaps( hdcMetafile, TECHNOLOGY );
308     ok( caps == DT_METAFILE, "wrong caps %u\n", caps );
309     DeleteMetaFile( CloseMetaFile( hdcMetafile ));
310
311     DeleteObject( bitmap );
312 }
313
314 static void test_DC_bitmap(void)
315 {
316     HDC hdc, hdcmem;
317     DWORD bits[64];
318     HBITMAP hbmp, oldhbmp;
319     COLORREF col;
320     int i, bitspixel;
321
322     /* fill bitmap data with b&w pattern */
323     for( i = 0; i < 64; i++) bits[i] = i & 1 ? 0 : 0xffffff;
324
325     hdc = GetDC(0);
326     ok( hdc != NULL, "CreateDC rets %p\n", hdc);
327     bitspixel = GetDeviceCaps( hdc, BITSPIXEL);
328     /* create a memory dc */
329     hdcmem = CreateCompatibleDC( hdc);
330     ok( hdcmem != NULL, "CreateCompatibleDC rets %p\n", hdcmem);
331     /* tests */
332     /* test monochrome bitmap: should always work */
333     hbmp = CreateBitmap(32, 32, 1, 1, bits);
334     ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
335     oldhbmp = SelectObject( hdcmem, hbmp);
336     ok( oldhbmp != NULL, "SelectObject returned NULL\n" ); /* a memdc always has a bitmap selected */
337     col = GetPixel( hdcmem, 0, 0);
338     ok( col == 0xffffff, "GetPixel returned %08x, expected 00ffffff\n", col);
339     col = GetPixel( hdcmem, 1, 1);
340     ok( col == 0x000000, "GetPixel returned %08x, expected 00000000\n", col);
341     col = GetPixel( hdcmem, 100, 1);
342     ok( col == CLR_INVALID, "GetPixel returned %08x, expected ffffffff\n", col);
343     SelectObject( hdcmem, oldhbmp);
344     DeleteObject( hbmp);
345
346     /* test with 2 bits color depth, not likely to succeed */
347     hbmp = CreateBitmap(16, 16, 1, 2, bits);
348     ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
349     oldhbmp = SelectObject( hdcmem, hbmp);
350     if( bitspixel != 2)
351         ok( !oldhbmp, "SelectObject of a bitmap with 2 bits/pixel should return  NULL\n");
352     if( oldhbmp) SelectObject( hdcmem, oldhbmp);
353     DeleteObject( hbmp);
354
355     /* test with 16 bits color depth, might succeed */
356     hbmp = CreateBitmap(6, 6, 1, 16, bits);
357     ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
358     oldhbmp = SelectObject( hdcmem, hbmp);
359     if( bitspixel == 16) {
360         ok( oldhbmp != NULL, "SelectObject returned NULL\n" );
361         col = GetPixel( hdcmem, 0, 0);
362         ok( col == 0xffffff,
363             "GetPixel of a bitmap with 16 bits/pixel returned %08x, expected 00ffffff\n", col);
364         col = GetPixel( hdcmem, 1, 1);
365         ok( col == 0x000000,
366             "GetPixel of a bitmap with 16 bits/pixel returned returned %08x, expected 00000000\n", col);
367     }
368     if( oldhbmp) SelectObject( hdcmem, oldhbmp);
369     DeleteObject( hbmp);
370
371     /* test with 32 bits color depth, probably succeed */
372     hbmp = CreateBitmap(4, 4, 1, 32, bits);
373     ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
374     oldhbmp = SelectObject( hdcmem, hbmp);
375     if( bitspixel == 32) {
376         ok( oldhbmp != NULL, "SelectObject returned NULL\n" );
377         col = GetPixel( hdcmem, 0, 0);
378         ok( col == 0xffffff,
379             "GetPixel of a bitmap with 32 bits/pixel returned %08x, expected 00ffffff\n", col);
380         col = GetPixel( hdcmem, 1, 1);
381         ok( col == 0x000000,
382             "GetPixel of a bitmap with 32 bits/pixel returned returned %08x, expected 00000000\n", col);
383     }
384     if( oldhbmp) SelectObject( hdcmem, oldhbmp);
385     DeleteObject( hbmp);
386     ReleaseDC( 0, hdc );
387 }
388
389 static void test_DeleteDC(void)
390 {
391     HWND hwnd;
392     HDC hdc, hdc_test;
393     WNDCLASSEX cls;
394     int ret;
395
396     /* window DC */
397     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
398                            0, 0, 0, NULL);
399     ok(hwnd != 0, "CreateWindowExA failed\n");
400
401     hdc = GetDC(hwnd);
402     ok(hdc != 0, "GetDC failed\n");
403     ret = GetObjectType(hdc);
404     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
405     ret = DeleteDC(hdc);
406     ok(ret, "DeleteDC failed\n");
407     ret = GetObjectType(hdc);
408     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
409
410     hdc = GetWindowDC(hwnd);
411     ok(hdc != 0, "GetDC failed\n");
412     ret = GetObjectType(hdc);
413     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
414     ret = DeleteDC(hdc);
415     ok(ret, "DeleteDC failed\n");
416     ret = GetObjectType(hdc);
417     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
418
419     DestroyWindow(hwnd);
420
421     /* desktop window DC */
422     hwnd = GetDesktopWindow();
423     ok(hwnd != 0, "GetDesktopWindow 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 || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
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     /* CS_CLASSDC */
444     memset(&cls, 0, sizeof(cls));
445     cls.cbSize = sizeof(cls);
446     cls.style = CS_CLASSDC;
447     cls.hInstance = GetModuleHandle(0);
448     cls.lpszClassName = "Wine class DC";
449     cls.lpfnWndProc = DefWindowProcA;
450     ret = RegisterClassExA(&cls);
451     ok(ret, "RegisterClassExA failed\n");
452
453     hwnd = CreateWindowExA(0, "Wine class DC", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
454                            0, 0, 0, NULL);
455     ok(hwnd != 0, "CreateWindowExA failed\n");
456
457     hdc = GetDC(hwnd);
458     ok(hdc != 0, "GetDC failed\n");
459     ret = GetObjectType(hdc);
460     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
461     ret = DeleteDC(hdc);
462     ok(ret, "DeleteDC failed\n");
463     ret = GetObjectType(hdc);
464     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
465     ret = ReleaseDC(hwnd, hdc);
466     ok(ret, "ReleaseDC failed\n");
467     ret = GetObjectType(hdc);
468     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
469
470     hdc_test = hdc;
471
472     hdc = GetWindowDC(hwnd);
473     ok(hdc != 0, "GetDC failed\n");
474     ret = GetObjectType(hdc);
475     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
476     ret = DeleteDC(hdc);
477     ok(ret, "DeleteDC failed\n");
478     ret = GetObjectType(hdc);
479     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
480
481     DestroyWindow(hwnd);
482
483     ret = GetObjectType(hdc_test);
484     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
485
486     ret = UnregisterClassA("Wine class DC", GetModuleHandle(NULL));
487     ok(ret, "UnregisterClassA failed\n");
488
489     ret = GetObjectType(hdc_test);
490 todo_wine
491     ok(!ret, "GetObjectType should fail for a deleted DC\n");
492
493     /* CS_OWNDC */
494     memset(&cls, 0, sizeof(cls));
495     cls.cbSize = sizeof(cls);
496     cls.style = CS_OWNDC;
497     cls.hInstance = GetModuleHandle(0);
498     cls.lpszClassName = "Wine own DC";
499     cls.lpfnWndProc = DefWindowProcA;
500     ret = RegisterClassExA(&cls);
501     ok(ret, "RegisterClassExA failed\n");
502
503     hwnd = CreateWindowExA(0, "Wine own DC", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
504                            0, 0, 0, NULL);
505     ok(hwnd != 0, "CreateWindowExA failed\n");
506
507     hdc = GetDC(hwnd);
508     ok(hdc != 0, "GetDC failed\n");
509     ret = GetObjectType(hdc);
510     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
511     ret = DeleteDC(hdc);
512     ok(ret, "DeleteDC failed\n");
513     ret = GetObjectType(hdc);
514     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
515     ret = ReleaseDC(hwnd, hdc);
516     ok(ret, "ReleaseDC failed\n");
517     ret = GetObjectType(hdc);
518     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
519
520     hdc = GetWindowDC(hwnd);
521     ok(hdc != 0, "GetDC failed\n");
522     ret = GetObjectType(hdc);
523     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
524     ret = DeleteDC(hdc);
525     ok(ret, "DeleteDC failed\n");
526     ret = GetObjectType(hdc);
527     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
528
529     DestroyWindow(hwnd);
530
531     ret = UnregisterClassA("Wine own DC", GetModuleHandle(NULL));
532     ok(ret, "UnregisterClassA failed\n");
533 }
534
535 static void test_boundsrect(void)
536 {
537     HDC hdc;
538     HBITMAP bitmap;
539     RECT rect, expect, set_rect;
540     UINT ret;
541
542     hdc = CreateCompatibleDC(0);
543     ok(hdc != NULL, "CreateCompatibleDC failed\n");
544     bitmap = CreateCompatibleBitmap( hdc, 200, 200 );
545     SelectObject( hdc, bitmap );
546
547     ret = GetBoundsRect(hdc, NULL, 0);
548     ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
549
550     ret = GetBoundsRect(hdc, NULL, ~0U);
551     ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
552
553     /* Test parameter handling order. */
554     SetRect(&set_rect, 10, 20, 40, 50);
555     ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
556     ok(ret & DCB_RESET,
557        "Expected return flag DCB_RESET to be set, got %u\n", ret);
558
559     ret = GetBoundsRect(hdc, NULL, DCB_RESET);
560     ok(ret == 0,
561        "Expected GetBoundsRect to return 0, got %u\n", ret);
562
563     ret = GetBoundsRect(hdc, &rect, 0);
564     ok(ret == DCB_RESET,
565        "Expected GetBoundsRect to return DCB_RESET, got %u\n", ret);
566     SetRect(&expect, 0, 0, 0, 0);
567     ok(EqualRect(&rect, &expect) ||
568        broken(EqualRect(&rect, &set_rect)), /* nt4 sp1-5 */
569        "Expected output rectangle (0,0)-(0,0), got (%d,%d)-(%d,%d)\n",
570        rect.left, rect.top, rect.right, rect.bottom);
571
572     ret = GetBoundsRect(NULL, NULL, 0);
573     ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
574
575     ret = GetBoundsRect(NULL, NULL, ~0U);
576     ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
577
578     ret = SetBoundsRect(NULL, NULL, 0);
579     ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret);
580
581     ret = SetBoundsRect(NULL, NULL, ~0U);
582     ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret);
583
584     SetRect(&set_rect, 10, 20, 40, 50);
585     ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
586     ok(ret == (DCB_RESET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
587
588     ret = GetBoundsRect(hdc, &rect, 0);
589     ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
590     SetRect(&expect, 10, 20, 40, 50);
591     ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
592        rect.left, rect.top, rect.right, rect.bottom);
593
594     SetMapMode( hdc, MM_ANISOTROPIC );
595     SetViewportExtEx( hdc, 2, 2, NULL );
596     ret = GetBoundsRect(hdc, &rect, 0);
597     ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
598     SetRect(&expect, 5, 10, 20, 25);
599     ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
600        rect.left, rect.top, rect.right, rect.bottom);
601
602     SetViewportOrgEx( hdc, 20, 30, NULL );
603     ret = GetBoundsRect(hdc, &rect, 0);
604     ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
605     SetRect(&expect, -5, -5, 10, 10);
606     ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
607        rect.left, rect.top, rect.right, rect.bottom);
608
609     SetRect(&set_rect, 10, 20, 40, 50);
610     ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
611     ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
612
613     ret = GetBoundsRect(hdc, &rect, 0);
614     ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
615     SetRect(&expect, 10, 20, 40, 50);
616     ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
617        rect.left, rect.top, rect.right, rect.bottom);
618
619     SetMapMode( hdc, MM_TEXT );
620     SetViewportOrgEx( hdc, 0, 0, NULL );
621     ret = GetBoundsRect(hdc, &rect, 0);
622     ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
623     SetRect(&expect, 40, 70, 100, 130);
624     ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
625        rect.left, rect.top, rect.right, rect.bottom);
626
627     if (pSetLayout)
628     {
629         pSetLayout( hdc, LAYOUT_RTL );
630         ret = GetBoundsRect(hdc, &rect, 0);
631         ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
632         SetRect(&expect, 159, 70, 99, 130);
633         ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
634            rect.left, rect.top, rect.right, rect.bottom);
635         SetRect(&set_rect, 50, 25, 30, 35);
636         ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
637         ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
638         ret = GetBoundsRect(hdc, &rect, 0);
639         ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
640         SetRect(&expect, 50, 25, 30, 35);
641         ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
642            rect.left, rect.top, rect.right, rect.bottom);
643
644         pSetLayout( hdc, LAYOUT_LTR );
645         ret = GetBoundsRect(hdc, &rect, 0);
646         ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
647         SetRect(&expect, 149, 25, 169, 35);
648         ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
649            rect.left, rect.top, rect.right, rect.bottom);
650     }
651
652     /* empty rect resets, except on nt4 */
653     SetRect(&expect, 20, 20, 10, 10);
654     ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
655     ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
656     ret = GetBoundsRect(hdc, &rect, 0);
657     ok(ret == DCB_RESET || broken(ret == DCB_SET)  /* nt4 */,
658        "GetBoundsRect returned %x\n", ret);
659     if (ret == DCB_RESET)
660     {
661         SetRect(&expect, 0, 0, 0, 0);
662         ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
663            rect.left, rect.top, rect.right, rect.bottom);
664
665         SetRect(&expect, 20, 20, 20, 20);
666         ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
667         ok(ret == (DCB_RESET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
668         ret = GetBoundsRect(hdc, &rect, 0);
669         ok(ret == DCB_RESET, "GetBoundsRect returned %x\n", ret);
670         SetRect(&expect, 0, 0, 0, 0);
671         ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
672            rect.left, rect.top, rect.right, rect.bottom);
673     }
674
675     DeleteDC( hdc );
676     DeleteObject( bitmap );
677 }
678
679 static void test_desktop_colorres(void)
680 {
681     HDC hdc = GetDC(NULL);
682     int bitspixel, colorres;
683
684     bitspixel = GetDeviceCaps(hdc, BITSPIXEL);
685     ok(bitspixel != 0, "Expected to get valid BITSPIXEL capability value\n");
686
687     colorres = GetDeviceCaps(hdc, COLORRES);
688     ok(colorres != 0 ||
689        broken(colorres == 0), /* Win9x */
690        "Expected to get valid COLORRES capability value\n");
691
692     if (colorres)
693     {
694         switch (bitspixel)
695         {
696         case 8:
697             ok(colorres == 18,
698                "Expected COLORRES to be 18, got %d\n", colorres);
699             break;
700         case 16:
701             ok(colorres == 16,
702                "Expected COLORRES to be 16, got %d\n", colorres);
703             break;
704         case 24:
705         case 32:
706             ok(colorres == 24,
707                "Expected COLORRES to be 24, got %d\n", bitspixel);
708             break;
709         default:
710             ok(0, "Got unknown BITSPIXEL %d with COLORRES %d\n", bitspixel, colorres);
711             break;
712         }
713     }
714
715     ReleaseDC(NULL, hdc);
716 }
717
718 static void test_gamma(void)
719 {
720     BOOL ret;
721     HDC hdc = GetDC(NULL);
722     WORD oldramp[3][256], ramp[3][256];
723     INT i;
724
725     ret = GetDeviceGammaRamp(hdc, &oldramp);
726     if (!ret)
727     {
728         win_skip("GetDeviceGammaRamp failed, skipping tests\n");
729         goto done;
730     }
731
732     /* try to set back old ramp */
733     ret = SetDeviceGammaRamp(hdc, &oldramp);
734     if (!ret)
735     {
736         win_skip("SetDeviceGammaRamp failed, skipping tests\n");
737         goto done;
738     }
739
740     memcpy(ramp, oldramp, sizeof(ramp));
741
742     /* set one color ramp to zeros */
743     memset(ramp[0], 0, sizeof(ramp[0]));
744     ret = SetDeviceGammaRamp(hdc, &ramp);
745     ok(!ret, "SetDeviceGammaRamp succeeded\n");
746
747     /* set one color ramp to a flat straight rising line */
748     for (i = 0; i < 256; i++) ramp[0][i] = i;
749     ret = SetDeviceGammaRamp(hdc, &ramp);
750     todo_wine ok(!ret, "SetDeviceGammaRamp succeeded\n");
751
752     /* set one color ramp to a steep straight rising line */
753     for (i = 0; i < 256; i++) ramp[0][i] = i * 256;
754     ret = SetDeviceGammaRamp(hdc, &ramp);
755     ok(ret, "SetDeviceGammaRamp failed\n");
756
757     /* try a bright gamma ramp */
758     ramp[0][0] = 0;
759     ramp[0][1] = 0x7FFF;
760     for (i = 2; i < 256; i++) ramp[0][i] = 0xFFFF;
761     ret = SetDeviceGammaRamp(hdc, &ramp);
762     ok(!ret, "SetDeviceGammaRamp succeeded\n");
763
764     /* try ramps which are not uniform */
765     ramp[0][0] = 0;
766     for (i = 1; i < 256; i++) ramp[0][i] = ramp[0][i - 1] + 512;
767     ret = SetDeviceGammaRamp(hdc, &ramp);
768     ok(ret, "SetDeviceGammaRamp failed\n");
769     ramp[0][0] = 0;
770     for (i = 2; i < 256; i+=2)
771     {
772         ramp[0][i - 1] = ramp[0][i - 2];
773         ramp[0][i] = ramp[0][i - 2] + 512;
774     }
775     ret = SetDeviceGammaRamp(hdc, &ramp);
776     ok(ret, "SetDeviceGammaRamp failed\n");
777
778     /* cleanup: set old ramp again */
779     ret = SetDeviceGammaRamp(hdc, &oldramp);
780     ok(ret, "SetDeviceGammaRamp failed\n");
781
782 done:
783     ReleaseDC(NULL, hdc);
784 }
785
786 START_TEST(dc)
787 {
788     pSetLayout = (void *)GetProcAddress( GetModuleHandle("gdi32.dll"), "SetLayout");
789     test_savedc();
790     test_savedc_2();
791     test_GdiConvertToDevmodeW();
792     test_CreateCompatibleDC();
793     test_DC_bitmap();
794     test_DeleteDC();
795     test_boundsrect();
796     test_desktop_colorres();
797     test_gamma();
798 }