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