Release 1.5.29.
[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
23 #define WINVER 0x0501 /* request latest DEVMODE */
24 #define NONAMELESSSTRUCT
25 #define NONAMELESSUNION
26
27 #include <assert.h>
28 #include <stdio.h>
29
30 #include "wine/test.h"
31 #include "winbase.h"
32 #include "wingdi.h"
33 #include "winuser.h"
34 #include "winspool.h"
35 #include "winerror.h"
36
37 #ifndef LAYOUT_LTR
38 #define LAYOUT_LTR 0
39 #endif
40
41 static DWORD (WINAPI *pSetLayout)(HDC hdc, DWORD layout);
42
43 static void dump_region(HRGN hrgn)
44 {
45     DWORD i, size;
46     RGNDATA *data = NULL;
47     RECT *rect;
48
49     if (!hrgn)
50     {
51         printf( "(null) region\n" );
52         return;
53     }
54     if (!(size = GetRegionData( hrgn, 0, NULL ))) return;
55     if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return;
56     GetRegionData( hrgn, size, data );
57     printf( "%d rects:", data->rdh.nCount );
58     for (i = 0, rect = (RECT *)data->Buffer; i < data->rdh.nCount; i++, rect++)
59         printf( " (%d,%d)-(%d,%d)", rect->left, rect->top, rect->right, rect->bottom );
60     printf( "\n" );
61     HeapFree( GetProcessHeap(), 0, data );
62 }
63
64 static void test_dc_values(void)
65 {
66     HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
67     COLORREF color;
68     int extra;
69
70     ok( hdc != NULL, "CreateDC failed\n" );
71     color = SetBkColor( hdc, 0x12345678 );
72     ok( color == 0xffffff, "initial color %08x\n", color );
73     color = GetBkColor( hdc );
74     ok( color == 0x12345678, "wrong color %08x\n", color );
75     color = SetBkColor( hdc, 0xffffffff );
76     ok( color == 0x12345678, "wrong color %08x\n", color );
77     color = GetBkColor( hdc );
78     ok( color == 0xffffffff, "wrong color %08x\n", color );
79     color = SetBkColor( hdc, 0 );
80     ok( color == 0xffffffff, "wrong color %08x\n", color );
81     color = GetBkColor( hdc );
82     ok( color == 0, "wrong color %08x\n", color );
83
84     color = SetTextColor( hdc, 0xffeeddcc );
85     ok( color == 0, "initial color %08x\n", color );
86     color = GetTextColor( hdc );
87     ok( color == 0xffeeddcc, "wrong color %08x\n", color );
88     color = SetTextColor( hdc, 0xffffffff );
89     ok( color == 0xffeeddcc, "wrong color %08x\n", color );
90     color = GetTextColor( hdc );
91     ok( color == 0xffffffff, "wrong color %08x\n", color );
92     color = SetTextColor( hdc, 0 );
93     ok( color == 0xffffffff, "wrong color %08x\n", color );
94     color = GetTextColor( hdc );
95     ok( color == 0, "wrong color %08x\n", color );
96
97     extra = GetTextCharacterExtra( hdc );
98     ok( extra == 0, "initial extra %d\n", extra );
99     SetTextCharacterExtra( hdc, 123 );
100     extra = GetTextCharacterExtra( hdc );
101     ok( extra == 123, "initial extra %d\n", extra );
102     SetMapMode( hdc, MM_LOMETRIC );
103     extra = GetTextCharacterExtra( hdc );
104     ok( extra == 123, "initial extra %d\n", extra );
105     SetMapMode( hdc, MM_TEXT );
106     extra = GetTextCharacterExtra( hdc );
107     ok( extra == 123, "initial extra %d\n", extra );
108
109     DeleteDC( hdc );
110 }
111
112 static void test_savedc_2(void)
113 {
114     HWND hwnd;
115     HDC hdc;
116     HRGN hrgn;
117     RECT rc, rc_clip;
118     int ret;
119
120     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,
121                            0, 0, 0, NULL);
122     assert(hwnd != 0);
123     ShowWindow(hwnd, SW_SHOW);
124     UpdateWindow(hwnd);
125
126     hrgn = CreateRectRgn(0, 0, 0, 0);
127     assert(hrgn != 0);
128
129     hdc = GetDC(hwnd);
130     ok(hdc != NULL, "GetDC failed\n");
131
132     ret = GetClipBox(hdc, &rc_clip);
133     ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION), "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
134     ret = GetClipRgn(hdc, hrgn);
135     ok(ret == 0, "GetClipRgn returned %d instead of 0\n", ret);
136     ret = GetRgnBox(hrgn, &rc);
137     ok(ret == NULLREGION, "GetRgnBox returned %d (%d,%d-%d,%d) instead of NULLREGION\n",
138        ret, rc.left, rc.top, rc.right, rc.bottom);
139     /*dump_region(hrgn);*/
140     SetRect(&rc, 0, 0, 100, 100);
141     ok(EqualRect(&rc, &rc_clip),
142        "rects are not equal: (%d,%d-%d,%d) - (%d,%d-%d,%d)\n",
143        rc.left, rc.top, rc.right, rc.bottom,
144        rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
145
146     ret = SaveDC(hdc);
147     ok(ret == 1, "ret = %d\n", ret);
148
149     ret = IntersectClipRect(hdc, 0, 0, 50, 50);
150     if (ret == COMPLEXREGION)
151     {
152         /* XP returns COMPLEXREGION although dump_region reports only 1 rect */
153         trace("Windows BUG: IntersectClipRect returned %d instead of SIMPLEREGION\n", ret);
154         /* let's make sure that it's a simple region */
155         ret = GetClipRgn(hdc, hrgn);
156         ok(ret == 1, "GetClipRgn returned %d instead of 1\n", ret);
157         dump_region(hrgn);
158     }
159     else
160         ok(ret == SIMPLEREGION, "IntersectClipRect returned %d instead of SIMPLEREGION\n", ret);
161
162     ret = GetClipBox(hdc, &rc_clip);
163     ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION), "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
164     SetRect(&rc, 0, 0, 50, 50);
165     ok(EqualRect(&rc, &rc_clip),
166        "rects are not equal: (%d,%d-%d,%d) - (%d,%d-%d,%d)\n",
167        rc.left, rc.top, rc.right, rc.bottom,
168        rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
169
170     ret = RestoreDC(hdc, 1);
171     ok(ret, "ret = %d\n", ret);
172
173     ret = GetClipBox(hdc, &rc_clip);
174     ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION), "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
175     SetRect(&rc, 0, 0, 100, 100);
176     ok(EqualRect(&rc, &rc_clip),
177        "rects are not equal: (%d,%d-%d,%d) - (%d,%d-%d,%d)\n",
178        rc.left, rc.top, rc.right, rc.bottom,
179        rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
180
181     DeleteObject(hrgn);
182     ReleaseDC(hwnd, hdc);
183     DestroyWindow(hwnd);
184 }
185
186 static void test_savedc(void)
187 {
188     HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
189     int ret;
190
191     ok(hdc != NULL, "CreateDC rets %p\n", hdc);
192
193     ret = SaveDC(hdc);
194     ok(ret == 1, "ret = %d\n", ret);
195     ret = SaveDC(hdc);
196     ok(ret == 2, "ret = %d\n", ret);
197     ret = SaveDC(hdc);
198     ok(ret == 3, "ret = %d\n", ret);
199     ret = RestoreDC(hdc, -1);
200     ok(ret, "ret = %d\n", ret);
201     ret = SaveDC(hdc);
202     ok(ret == 3, "ret = %d\n", ret);
203     ret = RestoreDC(hdc, 1);
204     ok(ret, "ret = %d\n", ret);
205     ret = SaveDC(hdc);
206     ok(ret == 1, "ret = %d\n", ret);
207     ret = SaveDC(hdc);
208     ok(ret == 2, "ret = %d\n", ret);
209     ret = SaveDC(hdc);
210     ok(ret == 3, "ret = %d\n", ret);
211     ret = RestoreDC(hdc, -2);
212     ok(ret, "ret = %d\n", ret);
213     ret = SaveDC(hdc);
214     ok(ret == 2, "ret = %d\n", ret);
215     ret = RestoreDC(hdc, -2);
216     ok(ret, "ret = %d\n", ret);
217     ret = SaveDC(hdc);
218     ok(ret == 1, "ret = %d\n", ret);
219     ret = SaveDC(hdc);
220     ok(ret == 2, "ret = %d\n", ret); 
221     ret = RestoreDC(hdc, -4);
222     ok(!ret, "ret = %d\n", ret);
223     ret = RestoreDC(hdc, 3);
224     ok(!ret, "ret = %d\n", ret);
225
226     /* Under Win9x the following RestoreDC call succeeds and clears the save stack. */
227     ret = RestoreDC(hdc, -3);
228     ok(!ret ||
229        broken(ret), /* Win9x */
230        "ret = %d\n", ret);
231
232     /* Trying to clear an empty save stack fails. */
233     ret = RestoreDC(hdc, -3);
234     ok(!ret, "ret = %d\n", ret);
235
236     ret = SaveDC(hdc);
237     ok(ret == 3 ||
238        broken(ret == 1), /* Win9x */
239        "ret = %d\n", ret);
240
241     /* Under Win9x the following RestoreDC call succeeds and clears the save stack. */
242     ret = RestoreDC(hdc, 0);
243     ok(!ret ||
244        broken(ret), /* Win9x */
245        "ret = %d\n", ret);
246
247     /* Trying to clear an empty save stack fails. */
248     ret = RestoreDC(hdc, 0);
249     ok(!ret, "ret = %d\n", ret);
250
251     ret = RestoreDC(hdc, 1);
252     ok(ret ||
253        broken(!ret), /* Win9x */
254        "ret = %d\n", ret);
255
256     DeleteDC(hdc);
257 }
258
259 static void test_GdiConvertToDevmodeW(void)
260 {
261     DEVMODEW * (WINAPI *pGdiConvertToDevmodeW)(const DEVMODEA *);
262     DEVMODEA dmA;
263     DEVMODEW *dmW;
264     BOOL ret;
265
266     pGdiConvertToDevmodeW = (void *)GetProcAddress(GetModuleHandleA("gdi32.dll"), "GdiConvertToDevmodeW");
267     if (!pGdiConvertToDevmodeW)
268     {
269         win_skip("GdiConvertToDevmodeW is not available on this platform\n");
270         return;
271     }
272
273     ret = EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &dmA);
274     ok(ret, "EnumDisplaySettingsExA error %u\n", GetLastError());
275     ok(dmA.dmSize >= FIELD_OFFSET(DEVMODEA, dmICMMethod), "dmSize is too small: %04x\n", dmA.dmSize);
276     ok(dmA.dmSize <= sizeof(DEVMODEA), "dmSize is too large: %04x\n", dmA.dmSize);
277
278     dmW = pGdiConvertToDevmodeW(&dmA);
279     ok(dmW->dmSize >= FIELD_OFFSET(DEVMODEW, dmICMMethod), "dmSize is too small: %04x\n", dmW->dmSize);
280     ok(dmW->dmSize <= sizeof(DEVMODEW), "dmSize is too large: %04x\n", dmW->dmSize);
281     HeapFree(GetProcessHeap(), 0, dmW);
282
283     dmA.dmSize = FIELD_OFFSET(DEVMODEA, dmFields) + sizeof(dmA.dmFields);
284     dmW = pGdiConvertToDevmodeW(&dmA);
285     ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmFields) + sizeof(dmW->dmFields),
286        "wrong size %u\n", dmW->dmSize);
287     HeapFree(GetProcessHeap(), 0, dmW);
288
289     dmA.dmICMMethod = DMICMMETHOD_NONE;
290     dmA.dmSize = FIELD_OFFSET(DEVMODEA, dmICMMethod) + sizeof(dmA.dmICMMethod);
291     dmW = pGdiConvertToDevmodeW(&dmA);
292     ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmICMMethod) + sizeof(dmW->dmICMMethod),
293        "wrong size %u\n", dmW->dmSize);
294     ok(dmW->dmICMMethod == DMICMMETHOD_NONE,
295        "expected DMICMMETHOD_NONE, got %u\n", dmW->dmICMMethod);
296     HeapFree(GetProcessHeap(), 0, dmW);
297
298     dmA.dmSize = 1024;
299     dmW = pGdiConvertToDevmodeW(&dmA);
300     ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmPanningHeight) + sizeof(dmW->dmPanningHeight),
301        "wrong size %u\n", dmW->dmSize);
302     HeapFree(GetProcessHeap(), 0, dmW);
303
304     SetLastError(0xdeadbeef);
305     dmA.dmSize = 0;
306     dmW = pGdiConvertToDevmodeW(&dmA);
307     ok(!dmW, "GdiConvertToDevmodeW should fail\n");
308     ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
309
310     /* this is the minimal dmSize that XP accepts */
311     dmA.dmSize = FIELD_OFFSET(DEVMODEA, dmFields);
312     dmW = pGdiConvertToDevmodeW(&dmA);
313     ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmFields),
314        "expected %04x, got %04x\n", FIELD_OFFSET(DEVMODEW, dmFields), dmW->dmSize);
315     HeapFree(GetProcessHeap(), 0, dmW);
316 }
317
318 static void test_device_caps( HDC hdc, HDC ref_dc, const char *descr, int scale )
319 {
320     static const int caps[] =
321     {
322         DRIVERVERSION,
323         TECHNOLOGY,
324         HORZSIZE,
325         VERTSIZE,
326         HORZRES,
327         VERTRES,
328         BITSPIXEL,
329         PLANES,
330         NUMBRUSHES,
331         NUMPENS,
332         NUMMARKERS,
333         NUMFONTS,
334         NUMCOLORS,
335         PDEVICESIZE,
336         CURVECAPS,
337         LINECAPS,
338         POLYGONALCAPS,
339         /* TEXTCAPS broken on printer DC on winxp */
340         CLIPCAPS,
341         RASTERCAPS,
342         ASPECTX,
343         ASPECTY,
344         ASPECTXY,
345         LOGPIXELSX,
346         LOGPIXELSY,
347         SIZEPALETTE,
348         NUMRESERVED,
349         COLORRES,
350         PHYSICALWIDTH,
351         PHYSICALHEIGHT,
352         PHYSICALOFFSETX,
353         PHYSICALOFFSETY,
354         SCALINGFACTORX,
355         SCALINGFACTORY,
356         VREFRESH,
357         DESKTOPVERTRES,
358         DESKTOPHORZRES,
359         BLTALIGNMENT,
360         SHADEBLENDCAPS
361     };
362     unsigned int i;
363     WORD ramp[3][256];
364     BOOL ret;
365     RECT rect;
366     UINT type;
367
368     if (GetObjectType( hdc ) == OBJ_METADC)
369     {
370         for (i = 0; i < sizeof(caps)/sizeof(caps[0]); i++)
371             ok( GetDeviceCaps( hdc, caps[i] ) == (caps[i] == TECHNOLOGY ? DT_METAFILE : 0),
372                 "wrong caps on %s for %u: %u\n", descr, caps[i],
373                 GetDeviceCaps( hdc, caps[i] ) );
374
375         SetLastError( 0xdeadbeef );
376         ret = GetDeviceGammaRamp( hdc, &ramp );
377         ok( !ret, "GetDeviceGammaRamp succeeded on %s\n", descr );
378         ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef), /* nt4 */
379             "wrong error %u on %s\n", GetLastError(), descr );
380         type = GetClipBox( hdc, &rect );
381         ok( type == ERROR, "GetClipBox returned %d on %s\n", type, descr );
382
383         SetBoundsRect( hdc, NULL, DCB_RESET | DCB_ENABLE );
384         SetMapMode( hdc, MM_TEXT );
385         Rectangle( hdc, 2, 2, 5, 5 );
386         type = GetBoundsRect( hdc, &rect, DCB_RESET );
387         ok( !type, "GetBoundsRect succeeded on %s\n", descr );
388         type = SetBoundsRect( hdc, &rect, DCB_RESET | DCB_ENABLE );
389         ok( !type, "SetBoundsRect succeeded on %s\n", descr );
390     }
391     else
392     {
393         for (i = 0; i < sizeof(caps)/sizeof(caps[0]); i++)
394         {
395             INT precision = 0;
396             INT hdc_caps = GetDeviceCaps( hdc, caps[i] );
397
398             switch (caps[i])
399             {
400             case HORZSIZE:
401             case VERTSIZE:
402                 hdc_caps /= scale;
403                 precision = 1;
404                 break;
405             case LOGPIXELSX:
406             case LOGPIXELSY:
407                 hdc_caps *= scale;
408                 break;
409             }
410
411             ok( abs(hdc_caps - GetDeviceCaps( ref_dc, caps[i] )) <= precision,
412                 "mismatched caps on %s for %u: %u/%u (scale %d)\n", descr, caps[i],
413                 hdc_caps, GetDeviceCaps( ref_dc, caps[i] ), scale );
414         }
415
416         SetLastError( 0xdeadbeef );
417         ret = GetDeviceGammaRamp( hdc, &ramp );
418         if (GetObjectType( hdc ) != OBJ_DC || GetDeviceCaps( hdc, TECHNOLOGY ) == DT_RASPRINTER)
419         {
420             ok( !ret, "GetDeviceGammaRamp succeeded on %s (type %d)\n", descr, GetObjectType( hdc ) );
421             ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef), /* nt4 */
422                 "wrong error %u on %s\n", GetLastError(), descr );
423         }
424         else
425             ok( ret || broken(!ret) /* NT4 */, "GetDeviceGammaRamp failed on %s (type %d), error %u\n", descr, GetObjectType( hdc ), GetLastError() );
426         type = GetClipBox( hdc, &rect );
427         if (GetObjectType( hdc ) == OBJ_ENHMETADC)
428             todo_wine ok( type == SIMPLEREGION, "GetClipBox returned %d on memdc for %s\n", type, descr );
429         else
430             ok( type == SIMPLEREGION, "GetClipBox returned %d on memdc for %s\n", type, descr );
431
432         type = GetBoundsRect( hdc, &rect, 0 );
433         ok( type == DCB_RESET || broken(type == DCB_SET) /* XP */,
434             "GetBoundsRect returned type %x for %s\n", type, descr );
435         if (type == DCB_RESET)
436             ok( rect.left == 0 && rect.top == 0 && rect.right == 0 && rect.bottom == 0,
437                 "GetBoundsRect returned %d,%d,%d,%d type %x for %s\n",
438                 rect.left, rect.top, rect.right, rect.bottom, type, descr );
439         type = SetBoundsRect( hdc, NULL, DCB_RESET | DCB_ENABLE );
440         ok( type == (DCB_RESET | DCB_DISABLE) || broken(type == (DCB_SET | DCB_ENABLE)) /* XP */,
441             "SetBoundsRect returned %x for %s (hdc type %d)\n", type, descr, GetObjectType( hdc ) );
442
443         SetMapMode( hdc, MM_TEXT );
444         Rectangle( hdc, 2, 2, 4, 4 );
445         type = GetBoundsRect( hdc, &rect, DCB_RESET );
446         if (GetObjectType( hdc ) == OBJ_ENHMETADC || (GetObjectType( hdc ) == OBJ_DC && GetDeviceCaps( hdc, TECHNOLOGY ) == DT_RASPRINTER))
447             todo_wine
448             ok( rect.left == 2 && rect.top == 2 && rect.right == 4 && rect.bottom == 4 && type == DCB_SET,
449                 "GetBoundsRect returned %d,%d,%d,%d type %x for %s\n",
450                 rect.left, rect.top, rect.right, rect.bottom, type, descr );
451         else
452             ok( rect.left == 2 && rect.top == 2 && rect.right == 4 && rect.bottom == 4 && type == DCB_SET,
453                 "GetBoundsRect returned %d,%d,%d,%d type %x for %s\n",
454                 rect.left, rect.top, rect.right, rect.bottom, type, descr );
455     }
456
457     type = GetClipBox( ref_dc, &rect );
458     if (type != COMPLEXREGION && type != ERROR)  /* region can be complex on multi-monitor setups */
459     {
460         ok( type == SIMPLEREGION, "GetClipBox returned %d on %s\n", type, descr );
461         ok( rect.left == 0 && rect.top == 0 &&
462             rect.right == GetDeviceCaps( ref_dc, DESKTOPHORZRES ) &&
463             rect.bottom == GetDeviceCaps( ref_dc, DESKTOPVERTRES ),
464             "GetClipBox returned %d,%d,%d,%d on %s\n",
465             rect.left, rect.top, rect.right, rect.bottom, descr );
466     }
467
468     SetBoundsRect( ref_dc, NULL, DCB_RESET | DCB_ACCUMULATE );
469     SetMapMode( ref_dc, MM_TEXT );
470     Rectangle( ref_dc, 3, 3, 5, 5 );
471     type = GetBoundsRect( ref_dc, &rect, DCB_RESET );
472     /* it may or may not work on non-memory DCs */
473     ok( (rect.left == 0 && rect.top == 0 && rect.right == 0 && rect.bottom == 0 && type == DCB_RESET) ||
474         (rect.left == 3 && rect.top == 3 && rect.right == 5 && rect.bottom == 5 && type == DCB_SET),
475         "GetBoundsRect returned %d,%d,%d,%d type %x on %s\n",
476         rect.left, rect.top, rect.right, rect.bottom, type, descr );
477
478     if (GetObjectType( hdc ) == OBJ_MEMDC)
479     {
480         char buffer[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
481         BITMAPINFO *info = (BITMAPINFO *)buffer;
482         HBITMAP dib, old;
483
484         memset( buffer, 0, sizeof(buffer) );
485         info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
486         info->bmiHeader.biWidth = 16;
487         info->bmiHeader.biHeight = 16;
488         info->bmiHeader.biPlanes = 1;
489         info->bmiHeader.biBitCount = 8;
490         info->bmiHeader.biCompression = BI_RGB;
491         dib = CreateDIBSection( ref_dc, info, DIB_RGB_COLORS, NULL, NULL, 0 );
492         old = SelectObject( hdc, dib );
493
494         for (i = 0; i < sizeof(caps)/sizeof(caps[0]); i++)
495             ok( GetDeviceCaps( hdc, caps[i] ) == GetDeviceCaps( ref_dc, caps[i] ),
496                 "mismatched caps on %s and DIB for %u: %u/%u\n", descr, caps[i],
497                 GetDeviceCaps( hdc, caps[i] ), GetDeviceCaps( ref_dc, caps[i] ) );
498
499         SetLastError( 0xdeadbeef );
500         ret = GetDeviceGammaRamp( hdc, &ramp );
501         ok( !ret, "GetDeviceGammaRamp succeeded on %s\n", descr );
502         ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef), /* nt4 */
503             "wrong error %u on %s\n", GetLastError(), descr );
504
505         type = GetClipBox( hdc, &rect );
506         ok( type == SIMPLEREGION, "GetClipBox returned %d on memdc for %s\n", type, descr );
507         ok( rect.left == 0 && rect.top == 0 && rect.right == 16 && rect.bottom == 16,
508             "GetClipBox returned %d,%d,%d,%d on memdc for %s\n",
509             rect.left, rect.top, rect.right, rect.bottom, descr );
510
511         SetBoundsRect( hdc, NULL, DCB_RESET | DCB_ENABLE );
512         SetMapMode( hdc, MM_TEXT );
513         Rectangle( hdc, 5, 5, 12, 14 );
514         type = GetBoundsRect( hdc, &rect, DCB_RESET );
515         ok( rect.left == 5 && rect.top == 5 && rect.right == 12 && rect.bottom == 14 && type == DCB_SET,
516             "GetBoundsRect returned %d,%d,%d,%d type %x on memdc for %s\n",
517             rect.left, rect.top, rect.right, rect.bottom, type, descr );
518
519         SelectObject( hdc, old );
520         DeleteObject( dib );
521     }
522
523     /* restore hdc state */
524     SetBoundsRect( hdc, NULL, DCB_RESET | DCB_DISABLE );
525     SetBoundsRect( ref_dc, NULL, DCB_RESET | DCB_DISABLE );
526 }
527
528 static void test_CreateCompatibleDC(void)
529 {
530     BOOL bRet;
531     HDC hdc, hNewDC, hdcMetafile, screen_dc;
532     HBITMAP bitmap;
533     INT caps;
534     DEVMODE dm;
535
536     bitmap = CreateBitmap( 10, 10, 1, 1, NULL );
537
538     bRet = EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm);
539     ok(bRet, "EnumDisplaySettingsEx failed\n");
540     dm.u1.s1.dmScale = 200;
541     dm.dmFields |= DM_SCALE;
542     hdc = CreateDC( "DISPLAY", NULL, NULL, &dm );
543
544     screen_dc = CreateDC( "DISPLAY", NULL, NULL, NULL );
545     test_device_caps( hdc, screen_dc, "display dc", 1 );
546     ResetDC( hdc, &dm );
547     test_device_caps( hdc, screen_dc, "display dc", 1 );
548     DeleteDC( hdc );
549
550     /* Create a DC compatible with the screen */
551     hdc = CreateCompatibleDC(NULL);
552     ok(hdc != NULL, "CreateCompatibleDC returned %p\n", hdc);
553     ok( SelectObject( hdc, bitmap ) != 0, "SelectObject failed\n" );
554     caps = GetDeviceCaps( hdc, TECHNOLOGY );
555     ok( caps == DT_RASDISPLAY, "wrong caps %u\n", caps );
556
557     test_device_caps( hdc, screen_dc, "display dc", 1 );
558
559     /* Delete this DC, this should succeed */
560     bRet = DeleteDC(hdc);
561     ok(bRet == TRUE, "DeleteDC returned %u\n", bRet);
562
563     /* Try to create a DC compatible to the deleted DC. This has to fail */
564     hNewDC = CreateCompatibleDC(hdc);
565     ok(hNewDC == NULL, "CreateCompatibleDC returned %p\n", hNewDC);
566
567     hdc = GetDC( 0 );
568     hdcMetafile = CreateEnhMetaFileA(hdc, NULL, NULL, NULL);
569     ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
570     hNewDC = CreateCompatibleDC( hdcMetafile );
571     ok(hNewDC != NULL, "CreateCompatibleDC failed\n");
572     ok( SelectObject( hNewDC, bitmap ) != 0, "SelectObject failed\n" );
573     caps = GetDeviceCaps( hdcMetafile, TECHNOLOGY );
574     ok( caps == DT_RASDISPLAY, "wrong caps %u\n", caps );
575     test_device_caps( hdcMetafile, hdc, "enhmetafile dc", 1 );
576     ResetDC( hdcMetafile, &dm );
577     test_device_caps( hdcMetafile, hdc, "enhmetafile dc", 1 );
578     DeleteDC( hNewDC );
579     DeleteEnhMetaFile( CloseEnhMetaFile( hdcMetafile ));
580     ReleaseDC( 0, hdc );
581
582     hdcMetafile = CreateMetaFileA(NULL);
583     ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
584     hNewDC = CreateCompatibleDC( hdcMetafile );
585     ok(hNewDC == NULL, "CreateCompatibleDC succeeded\n");
586     caps = GetDeviceCaps( hdcMetafile, TECHNOLOGY );
587     ok( caps == DT_METAFILE, "wrong caps %u\n", caps );
588     test_device_caps( hdcMetafile, screen_dc, "metafile dc", 1 );
589     ResetDC( hdcMetafile, &dm );
590     test_device_caps( hdcMetafile, screen_dc, "metafile dc", 1 );
591     DeleteMetaFile( CloseMetaFile( hdcMetafile ));
592
593     DeleteObject( bitmap );
594     DeleteDC( screen_dc );
595 }
596
597 static void test_DC_bitmap(void)
598 {
599     HDC hdc, hdcmem;
600     DWORD bits[64];
601     HBITMAP hbmp, oldhbmp;
602     COLORREF col;
603     int i, bitspixel;
604
605     /* fill bitmap data with b&w pattern */
606     for( i = 0; i < 64; i++) bits[i] = i & 1 ? 0 : 0xffffff;
607
608     hdc = GetDC(0);
609     ok( hdc != NULL, "CreateDC rets %p\n", hdc);
610     bitspixel = GetDeviceCaps( hdc, BITSPIXEL);
611     /* create a memory dc */
612     hdcmem = CreateCompatibleDC( hdc);
613     ok( hdcmem != NULL, "CreateCompatibleDC rets %p\n", hdcmem);
614     /* tests */
615     /* test monochrome bitmap: should always work */
616     hbmp = CreateBitmap(32, 32, 1, 1, bits);
617     ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
618     oldhbmp = SelectObject( hdcmem, hbmp);
619     ok( oldhbmp != NULL, "SelectObject returned NULL\n" ); /* a memdc always has a bitmap selected */
620     col = GetPixel( hdcmem, 0, 0);
621     ok( col == 0xffffff, "GetPixel returned %08x, expected 00ffffff\n", col);
622     col = GetPixel( hdcmem, 1, 1);
623     ok( col == 0x000000, "GetPixel returned %08x, expected 00000000\n", col);
624     col = GetPixel( hdcmem, 100, 1);
625     ok( col == CLR_INVALID, "GetPixel returned %08x, expected ffffffff\n", col);
626     SelectObject( hdcmem, oldhbmp);
627     DeleteObject( hbmp);
628
629     /* test with 2 bits color depth, not likely to succeed */
630     hbmp = CreateBitmap(16, 16, 1, 2, bits);
631     ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
632     oldhbmp = SelectObject( hdcmem, hbmp);
633     if( bitspixel != 2)
634         ok( !oldhbmp, "SelectObject of a bitmap with 2 bits/pixel should return  NULL\n");
635     if( oldhbmp) SelectObject( hdcmem, oldhbmp);
636     DeleteObject( hbmp);
637
638     /* test with 16 bits color depth, might succeed */
639     hbmp = CreateBitmap(6, 6, 1, 16, bits);
640     ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
641     oldhbmp = SelectObject( hdcmem, hbmp);
642     if( bitspixel == 16) {
643         ok( oldhbmp != NULL, "SelectObject returned NULL\n" );
644         col = GetPixel( hdcmem, 0, 0);
645         ok( col == 0xffffff,
646             "GetPixel of a bitmap with 16 bits/pixel returned %08x, expected 00ffffff\n", col);
647         col = GetPixel( hdcmem, 1, 1);
648         ok( col == 0x000000,
649             "GetPixel of a bitmap with 16 bits/pixel returned returned %08x, expected 00000000\n", col);
650     }
651     if( oldhbmp) SelectObject( hdcmem, oldhbmp);
652     DeleteObject( hbmp);
653
654     /* test with 32 bits color depth, probably succeed */
655     hbmp = CreateBitmap(4, 4, 1, 32, bits);
656     ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
657     oldhbmp = SelectObject( hdcmem, hbmp);
658     if( bitspixel == 32) {
659         ok( oldhbmp != NULL, "SelectObject returned NULL\n" );
660         col = GetPixel( hdcmem, 0, 0);
661         ok( col == 0xffffff,
662             "GetPixel of a bitmap with 32 bits/pixel returned %08x, expected 00ffffff\n", col);
663         col = GetPixel( hdcmem, 1, 1);
664         ok( col == 0x000000,
665             "GetPixel of a bitmap with 32 bits/pixel returned returned %08x, expected 00000000\n", col);
666     }
667     if( oldhbmp) SelectObject( hdcmem, oldhbmp);
668     DeleteObject( hbmp);
669     ReleaseDC( 0, hdc );
670 }
671
672 static void test_DeleteDC(void)
673 {
674     HWND hwnd;
675     HDC hdc, hdc_test;
676     WNDCLASSEX cls;
677     int ret;
678
679     /* window DC */
680     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
681                            0, 0, 0, NULL);
682     ok(hwnd != 0, "CreateWindowExA failed\n");
683
684     hdc = GetDC(hwnd);
685     ok(hdc != 0, "GetDC failed\n");
686     ret = GetObjectType(hdc);
687     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
688     ret = DeleteDC(hdc);
689     ok(ret, "DeleteDC failed\n");
690     ret = GetObjectType(hdc);
691     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
692
693     hdc = GetWindowDC(hwnd);
694     ok(hdc != 0, "GetDC failed\n");
695     ret = GetObjectType(hdc);
696     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
697     ret = DeleteDC(hdc);
698     ok(ret, "DeleteDC failed\n");
699     ret = GetObjectType(hdc);
700     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
701
702     DestroyWindow(hwnd);
703
704     /* desktop window DC */
705     hwnd = GetDesktopWindow();
706     ok(hwnd != 0, "GetDesktopWindow failed\n");
707
708     hdc = GetDC(hwnd);
709     ok(hdc != 0, "GetDC failed\n");
710     ret = GetObjectType(hdc);
711     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
712     ret = DeleteDC(hdc);
713     ok(ret, "DeleteDC failed\n");
714     ret = GetObjectType(hdc);
715     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
716
717     hdc = GetWindowDC(hwnd);
718     ok(hdc != 0, "GetDC failed\n");
719     ret = GetObjectType(hdc);
720     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
721     ret = DeleteDC(hdc);
722     ok(ret, "DeleteDC failed\n");
723     ret = GetObjectType(hdc);
724     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
725
726     /* CS_CLASSDC */
727     memset(&cls, 0, sizeof(cls));
728     cls.cbSize = sizeof(cls);
729     cls.style = CS_CLASSDC;
730     cls.hInstance = GetModuleHandle(0);
731     cls.lpszClassName = "Wine class DC";
732     cls.lpfnWndProc = DefWindowProcA;
733     ret = RegisterClassExA(&cls);
734     ok(ret, "RegisterClassExA failed\n");
735
736     hwnd = CreateWindowExA(0, "Wine class DC", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
737                            0, 0, 0, NULL);
738     ok(hwnd != 0, "CreateWindowExA failed\n");
739
740     hdc = GetDC(hwnd);
741     ok(hdc != 0, "GetDC failed\n");
742     ret = GetObjectType(hdc);
743     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
744     ret = DeleteDC(hdc);
745     ok(ret, "DeleteDC failed\n");
746     ret = GetObjectType(hdc);
747     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
748     ret = ReleaseDC(hwnd, hdc);
749     ok(ret, "ReleaseDC failed\n");
750     ret = GetObjectType(hdc);
751     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
752
753     hdc_test = hdc;
754
755     hdc = GetWindowDC(hwnd);
756     ok(hdc != 0, "GetDC failed\n");
757     ret = GetObjectType(hdc);
758     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
759     ret = DeleteDC(hdc);
760     ok(ret, "DeleteDC failed\n");
761     ret = GetObjectType(hdc);
762     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
763
764     DestroyWindow(hwnd);
765
766     ret = GetObjectType(hdc_test);
767     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
768
769     ret = UnregisterClassA("Wine class DC", GetModuleHandle(NULL));
770     ok(ret, "UnregisterClassA failed\n");
771
772     ret = GetObjectType(hdc_test);
773 todo_wine
774     ok(!ret, "GetObjectType should fail for a deleted DC\n");
775
776     /* CS_OWNDC */
777     memset(&cls, 0, sizeof(cls));
778     cls.cbSize = sizeof(cls);
779     cls.style = CS_OWNDC;
780     cls.hInstance = GetModuleHandle(0);
781     cls.lpszClassName = "Wine own DC";
782     cls.lpfnWndProc = DefWindowProcA;
783     ret = RegisterClassExA(&cls);
784     ok(ret, "RegisterClassExA failed\n");
785
786     hwnd = CreateWindowExA(0, "Wine own DC", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
787                            0, 0, 0, NULL);
788     ok(hwnd != 0, "CreateWindowExA failed\n");
789
790     hdc = GetDC(hwnd);
791     ok(hdc != 0, "GetDC failed\n");
792     ret = GetObjectType(hdc);
793     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
794     ret = DeleteDC(hdc);
795     ok(ret, "DeleteDC failed\n");
796     ret = GetObjectType(hdc);
797     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
798     ret = ReleaseDC(hwnd, hdc);
799     ok(ret, "ReleaseDC failed\n");
800     ret = GetObjectType(hdc);
801     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
802
803     hdc = GetWindowDC(hwnd);
804     ok(hdc != 0, "GetDC failed\n");
805     ret = GetObjectType(hdc);
806     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
807     ret = DeleteDC(hdc);
808     ok(ret, "DeleteDC failed\n");
809     ret = GetObjectType(hdc);
810     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
811
812     DestroyWindow(hwnd);
813
814     ret = UnregisterClassA("Wine own DC", GetModuleHandle(NULL));
815     ok(ret, "UnregisterClassA failed\n");
816 }
817
818 static void test_boundsrect(void)
819 {
820     char buffer[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
821     BITMAPINFO *info = (BITMAPINFO *)buffer;
822     HDC hdc;
823     HBITMAP bitmap, dib, old;
824     RECT rect, expect, set_rect;
825     UINT ret;
826     int i, level;
827
828     hdc = CreateCompatibleDC(0);
829     ok(hdc != NULL, "CreateCompatibleDC failed\n");
830     bitmap = CreateCompatibleBitmap( hdc, 200, 200 );
831     old = SelectObject( hdc, bitmap );
832
833     ret = GetBoundsRect(hdc, NULL, 0);
834     ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
835
836     ret = GetBoundsRect(hdc, NULL, ~0U);
837     ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
838
839     /* Test parameter handling order. */
840     SetRect(&set_rect, 10, 20, 40, 50);
841     ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
842     ok(ret & DCB_RESET,
843        "Expected return flag DCB_RESET to be set, got %u\n", ret);
844
845     ret = GetBoundsRect(hdc, NULL, DCB_RESET);
846     ok(ret == 0,
847        "Expected GetBoundsRect to return 0, got %u\n", ret);
848
849     ret = GetBoundsRect(hdc, &rect, 0);
850     ok(ret == DCB_RESET,
851        "Expected GetBoundsRect to return DCB_RESET, got %u\n", ret);
852     SetRect(&expect, 0, 0, 0, 0);
853     ok(EqualRect(&rect, &expect) ||
854        broken(EqualRect(&rect, &set_rect)), /* nt4 sp1-5 */
855        "Expected output rectangle (0,0)-(0,0), got (%d,%d)-(%d,%d)\n",
856        rect.left, rect.top, rect.right, rect.bottom);
857
858     ret = GetBoundsRect(NULL, NULL, 0);
859     ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
860
861     ret = GetBoundsRect(NULL, NULL, ~0U);
862     ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
863
864     ret = SetBoundsRect(NULL, NULL, 0);
865     ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret);
866
867     ret = SetBoundsRect(NULL, NULL, ~0U);
868     ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret);
869
870     SetRect(&set_rect, 10, 20, 40, 50);
871     ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
872     ok(ret == (DCB_RESET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
873
874     ret = GetBoundsRect(hdc, &rect, 0);
875     ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
876     SetRect(&expect, 10, 20, 40, 50);
877     ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
878        rect.left, rect.top, rect.right, rect.bottom);
879
880     SetMapMode( hdc, MM_ANISOTROPIC );
881     SetViewportExtEx( hdc, 2, 2, NULL );
882     ret = GetBoundsRect(hdc, &rect, 0);
883     ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
884     SetRect(&expect, 5, 10, 20, 25);
885     ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
886        rect.left, rect.top, rect.right, rect.bottom);
887
888     SetViewportOrgEx( hdc, 20, 30, NULL );
889     ret = GetBoundsRect(hdc, &rect, 0);
890     ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
891     SetRect(&expect, -5, -5, 10, 10);
892     ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
893        rect.left, rect.top, rect.right, rect.bottom);
894
895     SetRect(&set_rect, 10, 20, 40, 50);
896     ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
897     ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
898
899     ret = GetBoundsRect(hdc, &rect, 0);
900     ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
901     SetRect(&expect, 10, 20, 40, 50);
902     ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
903        rect.left, rect.top, rect.right, rect.bottom);
904
905     SetMapMode( hdc, MM_TEXT );
906     SetViewportOrgEx( hdc, 0, 0, NULL );
907     ret = GetBoundsRect(hdc, &rect, 0);
908     ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
909     SetRect(&expect, 40, 70, 100, 130);
910     ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
911        rect.left, rect.top, rect.right, rect.bottom);
912
913     if (pSetLayout)
914     {
915         pSetLayout( hdc, LAYOUT_RTL );
916         ret = GetBoundsRect(hdc, &rect, 0);
917         ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
918         SetRect(&expect, 159, 70, 99, 130);
919         ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
920            rect.left, rect.top, rect.right, rect.bottom);
921         SetRect(&set_rect, 50, 25, 30, 35);
922         ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
923         ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
924         ret = GetBoundsRect(hdc, &rect, 0);
925         ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
926         SetRect(&expect, 50, 25, 30, 35);
927         ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
928            rect.left, rect.top, rect.right, rect.bottom);
929
930         pSetLayout( hdc, LAYOUT_LTR );
931         ret = GetBoundsRect(hdc, &rect, 0);
932         ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
933         SetRect(&expect, 149, 25, 169, 35);
934         ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
935            rect.left, rect.top, rect.right, rect.bottom);
936     }
937
938     /* empty rect resets, except on nt4 */
939     SetRect(&expect, 20, 20, 10, 10);
940     ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
941     ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
942     ret = GetBoundsRect(hdc, &rect, 0);
943     ok(ret == DCB_RESET || broken(ret == DCB_SET)  /* nt4 */,
944        "GetBoundsRect returned %x\n", ret);
945     if (ret == DCB_RESET)
946     {
947         SetRect(&expect, 0, 0, 0, 0);
948         ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
949            rect.left, rect.top, rect.right, rect.bottom);
950
951         SetRect(&expect, 20, 20, 20, 20);
952         ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
953         ok(ret == (DCB_RESET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
954         ret = GetBoundsRect(hdc, &rect, 0);
955         ok(ret == DCB_RESET, "GetBoundsRect returned %x\n", ret);
956         SetRect(&expect, 0, 0, 0, 0);
957         ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
958            rect.left, rect.top, rect.right, rect.bottom);
959     }
960
961     SetBoundsRect( hdc, NULL, DCB_RESET | DCB_ENABLE );
962     MoveToEx( hdc, 10, 10, NULL );
963     LineTo( hdc, 20, 20 );
964     ret = GetBoundsRect( hdc, &rect, 0 );
965     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
966     SetRect( &expect, 10, 10, 21, 21 );
967     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
968     SetRect( &rect, 8, 8, 23, 23 );
969     expect = rect;
970     SetBoundsRect( hdc, &rect, DCB_ACCUMULATE );
971     ret = GetBoundsRect( hdc, &rect, 0 );
972     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
973     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
974
975     level = SaveDC( hdc );
976     LineTo( hdc, 30, 25 );
977     ret = GetBoundsRect( hdc, &rect, 0 );
978     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
979     SetRect( &expect, 8, 8, 31, 26 );
980     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
981     SetBoundsRect( hdc, NULL, DCB_DISABLE );
982     LineTo( hdc, 40, 40 );
983     ret = GetBoundsRect( hdc, &rect, 0 );
984     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
985     SetRect( &expect, 8, 8, 31, 26 );
986     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
987     SetRect( &rect, 6, 6, 30, 30 );
988     SetBoundsRect( hdc, &rect, DCB_ACCUMULATE );
989     ret = GetBoundsRect( hdc, &rect, 0 );
990     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
991     SetRect( &expect, 6, 6, 31, 30 );
992     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
993
994     RestoreDC( hdc, level );
995     ret = GetBoundsRect( hdc, &rect, 0 );
996     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
997     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
998     LineTo( hdc, 40, 40 );
999     ret = GetBoundsRect( hdc, &rect, 0 );
1000     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1001     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
1002
1003     SelectObject( hdc, old );
1004     ret = GetBoundsRect( hdc, &rect, 0 );
1005     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1006     SetRect( &expect, 6, 6, 1, 1 );
1007     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
1008     SetBoundsRect( hdc, NULL, DCB_ENABLE );
1009     LineTo( hdc, 50, 40 );
1010
1011     SelectObject( hdc, bitmap );
1012     ret = GetBoundsRect( hdc, &rect, 0 );
1013     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1014     SetRect( &expect, 6, 6, 51, 41 );
1015     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
1016     SelectObject( hdc, GetStockObject( NULL_PEN ));
1017     LineTo( hdc, 50, 50 );
1018     ret = GetBoundsRect( hdc, &rect, 0 );
1019     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1020     SetRect( &expect, 6, 6, 51, 51 );
1021     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
1022
1023     memset( buffer, 0, sizeof(buffer) );
1024     info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1025     info->bmiHeader.biWidth = 256;
1026     info->bmiHeader.biHeight = 256;
1027     info->bmiHeader.biPlanes = 1;
1028     info->bmiHeader.biBitCount = 8;
1029     info->bmiHeader.biCompression = BI_RGB;
1030     dib = CreateDIBSection( 0, info, DIB_RGB_COLORS, NULL, NULL, 0 );
1031     ok( dib != 0, "failed to create DIB\n" );
1032     SelectObject( hdc, dib );
1033     ret = GetBoundsRect( hdc, &rect, 0 );
1034     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1035     SetRect( &expect, 6, 6, 51, 51 );
1036     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
1037     LineTo( hdc, 55, 30 );
1038     ret = GetBoundsRect( hdc, &rect, 0 );
1039     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1040     SetRect( &expect, 6, 6, 56, 51 );
1041     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
1042     LineTo( hdc, 300, 30 );
1043     ret = GetBoundsRect( hdc, &rect, 0 );
1044     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1045     SetRect( &expect, 6, 6, 256, 51 );
1046     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
1047     LineTo( hdc, -300, -300 );
1048     ret = GetBoundsRect( hdc, &rect, 0 );
1049     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1050     SetRect( &expect, 0, 0, 256, 51 );
1051     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
1052
1053     /* test the wide pen heuristics */
1054     SetBoundsRect( hdc, NULL, DCB_ENABLE | DCB_RESET );
1055     for (i = 0; i < 1000; i++)
1056     {
1057         static const UINT endcaps[3] = { PS_ENDCAP_ROUND, PS_ENDCAP_SQUARE, PS_ENDCAP_FLAT };
1058         static const UINT joins[3] = { PS_JOIN_ROUND, PS_JOIN_BEVEL, PS_JOIN_MITER };
1059         LOGBRUSH brush = { BS_SOLID, RGB(0,0,0), 0 };
1060         UINT join = joins[i % 3];
1061         UINT endcap = endcaps[(i / 3) % 3];
1062         INT inflate, width = 1 + i / 9;
1063         HPEN pen = ExtCreatePen( PS_GEOMETRIC | join | endcap | PS_SOLID, width, &brush, 0, NULL );
1064         HPEN old = SelectObject( hdc, pen );
1065         MoveToEx( hdc, 100, 100, NULL );
1066         LineTo( hdc, 160, 100 );
1067         LineTo( hdc, 100, 160 );
1068         LineTo( hdc, 160, 160 );
1069         GetBoundsRect( hdc, &rect, DCB_RESET );
1070         SetRect( &expect, 100, 100, 161, 161 );
1071
1072         inflate = width + 2;
1073         if (join == PS_JOIN_MITER)
1074         {
1075             inflate *= 5;
1076             if (endcap == PS_ENDCAP_SQUARE)
1077                 InflateRect( &expect, (inflate * 3 + 1) / 2, (inflate * 3 + 1) / 2 );
1078             else
1079                 InflateRect( &expect, inflate, inflate );
1080         }
1081         else
1082         {
1083             if (endcap == PS_ENDCAP_SQUARE)
1084                 InflateRect( &expect, inflate - inflate / 4, inflate - inflate / 4 );
1085             else
1086                 InflateRect( &expect, (inflate + 1) / 2, (inflate + 1) / 2 );
1087         }
1088         expect.left   = max( expect.left, 0 );
1089         expect.top    = max( expect.top, 0 );
1090         expect.right  = min( expect.right, 256 );
1091         expect.bottom = min( expect.bottom, 256 );
1092         ok( EqualRect(&rect, &expect),
1093             "Got %d,%d,%d,%d expected %d,%d,%d,%d %u/%x/%x\n",
1094             rect.left, rect.top, rect.right, rect.bottom,
1095             expect.left, expect.top, expect.right, expect.bottom, width, endcap, join );
1096         DeleteObject( SelectObject( hdc, old ));
1097     }
1098
1099     DeleteDC( hdc );
1100     DeleteObject( bitmap );
1101     DeleteObject( dib );
1102 }
1103
1104 static void test_desktop_colorres(void)
1105 {
1106     HDC hdc = GetDC(NULL);
1107     int bitspixel, colorres;
1108
1109     bitspixel = GetDeviceCaps(hdc, BITSPIXEL);
1110     ok(bitspixel != 0, "Expected to get valid BITSPIXEL capability value\n");
1111
1112     colorres = GetDeviceCaps(hdc, COLORRES);
1113     ok(colorres != 0 ||
1114        broken(colorres == 0), /* Win9x */
1115        "Expected to get valid COLORRES capability value\n");
1116
1117     if (colorres)
1118     {
1119         switch (bitspixel)
1120         {
1121         case 8:
1122             ok(colorres == 18,
1123                "Expected COLORRES to be 18, got %d\n", colorres);
1124             break;
1125         case 16:
1126             ok(colorres == 16,
1127                "Expected COLORRES to be 16, got %d\n", colorres);
1128             break;
1129         case 24:
1130         case 32:
1131             ok(colorres == 24,
1132                "Expected COLORRES to be 24, got %d\n", bitspixel);
1133             break;
1134         default:
1135             ok(0, "Got unknown BITSPIXEL %d with COLORRES %d\n", bitspixel, colorres);
1136             break;
1137         }
1138     }
1139
1140     ReleaseDC(NULL, hdc);
1141 }
1142
1143 static void test_gamma(void)
1144 {
1145     BOOL ret;
1146     HDC hdc = GetDC(NULL);
1147     WORD oldramp[3][256], ramp[3][256];
1148     INT i;
1149
1150     ret = GetDeviceGammaRamp(hdc, &oldramp);
1151     if (!ret)
1152     {
1153         win_skip("GetDeviceGammaRamp failed, skipping tests\n");
1154         goto done;
1155     }
1156
1157     /* try to set back old ramp */
1158     ret = SetDeviceGammaRamp(hdc, &oldramp);
1159     if (!ret)
1160     {
1161         win_skip("SetDeviceGammaRamp failed, skipping tests\n");
1162         goto done;
1163     }
1164
1165     memcpy(ramp, oldramp, sizeof(ramp));
1166
1167     /* set one color ramp to zeros */
1168     memset(ramp[0], 0, sizeof(ramp[0]));
1169     ret = SetDeviceGammaRamp(hdc, &ramp);
1170     ok(!ret, "SetDeviceGammaRamp succeeded\n");
1171
1172     /* set one color ramp to a flat straight rising line */
1173     for (i = 0; i < 256; i++) ramp[0][i] = i;
1174     ret = SetDeviceGammaRamp(hdc, &ramp);
1175     todo_wine ok(!ret, "SetDeviceGammaRamp succeeded\n");
1176
1177     /* set one color ramp to a steep straight rising line */
1178     for (i = 0; i < 256; i++) ramp[0][i] = i * 256;
1179     ret = SetDeviceGammaRamp(hdc, &ramp);
1180     ok(ret, "SetDeviceGammaRamp failed\n");
1181
1182     /* try a bright gamma ramp */
1183     ramp[0][0] = 0;
1184     ramp[0][1] = 0x7FFF;
1185     for (i = 2; i < 256; i++) ramp[0][i] = 0xFFFF;
1186     ret = SetDeviceGammaRamp(hdc, &ramp);
1187     ok(!ret, "SetDeviceGammaRamp succeeded\n");
1188
1189     /* try ramps which are not uniform */
1190     ramp[0][0] = 0;
1191     for (i = 1; i < 256; i++) ramp[0][i] = ramp[0][i - 1] + 512;
1192     ret = SetDeviceGammaRamp(hdc, &ramp);
1193     ok(ret, "SetDeviceGammaRamp failed\n");
1194     ramp[0][0] = 0;
1195     for (i = 2; i < 256; i+=2)
1196     {
1197         ramp[0][i - 1] = ramp[0][i - 2];
1198         ramp[0][i] = ramp[0][i - 2] + 512;
1199     }
1200     ret = SetDeviceGammaRamp(hdc, &ramp);
1201     ok(ret, "SetDeviceGammaRamp failed\n");
1202
1203     /* cleanup: set old ramp again */
1204     ret = SetDeviceGammaRamp(hdc, &oldramp);
1205     ok(ret, "SetDeviceGammaRamp failed\n");
1206
1207 done:
1208     ReleaseDC(NULL, hdc);
1209 }
1210
1211 static BOOL is_postscript_printer(HDC hdc)
1212 {
1213     char tech[256];
1214
1215     if (ExtEscape(hdc, GETTECHNOLOGY, 0, NULL, sizeof(tech), tech) > 0)
1216         return strcmp(tech, "PostScript") == 0;
1217
1218     return FALSE;
1219 }
1220
1221 static HDC create_printer_dc(int scale, BOOL reset)
1222 {
1223     char buffer[260];
1224     DWORD len;
1225     PRINTER_INFO_2A *pbuf = NULL;
1226     DRIVER_INFO_3A *dbuf = NULL;
1227     HANDLE hprn = 0;
1228     HDC hdc = 0;
1229     HMODULE winspool = LoadLibraryA( "winspool.drv" );
1230     BOOL (WINAPI *pOpenPrinterA)(LPSTR, HANDLE *, LPPRINTER_DEFAULTSA);
1231     BOOL (WINAPI *pGetDefaultPrinterA)(LPSTR, LPDWORD);
1232     BOOL (WINAPI *pGetPrinterA)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD);
1233     BOOL (WINAPI *pGetPrinterDriverA)(HANDLE, LPSTR, DWORD, LPBYTE, DWORD, LPDWORD);
1234     BOOL (WINAPI *pClosePrinter)(HANDLE);
1235
1236     pGetDefaultPrinterA = (void *)GetProcAddress( winspool, "GetDefaultPrinterA" );
1237     pOpenPrinterA = (void *)GetProcAddress( winspool, "OpenPrinterA" );
1238     pGetPrinterA = (void *)GetProcAddress( winspool, "GetPrinterA" );
1239     pGetPrinterDriverA = (void *)GetProcAddress( winspool, "GetPrinterDriverA" );
1240     pClosePrinter = (void *)GetProcAddress( winspool, "ClosePrinter" );
1241
1242     if (!pGetDefaultPrinterA || !pOpenPrinterA || !pGetPrinterA || !pGetPrinterDriverA || !pClosePrinter)
1243         goto done;
1244
1245     len = sizeof(buffer);
1246     if (!pGetDefaultPrinterA( buffer, &len )) goto done;
1247     if (!pOpenPrinterA( buffer, &hprn, NULL )) goto done;
1248
1249     pGetPrinterA( hprn, 2, NULL, 0, &len );
1250     pbuf = HeapAlloc( GetProcessHeap(), 0, len );
1251     if (!pGetPrinterA( hprn, 2, (LPBYTE)pbuf, len, &len )) goto done;
1252
1253     pGetPrinterDriverA( hprn, NULL, 3, NULL, 0, &len );
1254     dbuf = HeapAlloc( GetProcessHeap(), 0, len );
1255     if (!pGetPrinterDriverA( hprn, NULL, 3, (LPBYTE)dbuf, len, &len )) goto done;
1256
1257     pbuf->pDevMode->u1.s1.dmScale = scale;
1258     pbuf->pDevMode->dmFields |= DM_SCALE;
1259
1260     hdc = CreateDCA( dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, pbuf->pDevMode );
1261     trace( "hdc %p for driver '%s' printer '%s' port '%s' is %sPostScript\n", hdc,
1262            dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName,
1263            is_postscript_printer(hdc) ? "" : "NOT " );
1264
1265     if (reset) ResetDC( hdc, pbuf->pDevMode );
1266 done:
1267     HeapFree( GetProcessHeap(), 0, dbuf );
1268     HeapFree( GetProcessHeap(), 0, pbuf );
1269     if (hprn) pClosePrinter( hprn );
1270     if (winspool) FreeLibrary( winspool );
1271     if (!hdc) skip( "could not create a DC for the default printer\n" );
1272     return hdc;
1273 }
1274
1275 static void test_printer_dc(void)
1276 {
1277     HDC memdc, display_memdc, enhmf_dc;
1278     HBITMAP orig, bmp;
1279     DWORD ret;
1280     HDC hdc, hdc_200;
1281
1282     hdc = create_printer_dc(100, FALSE);
1283     hdc_200 = create_printer_dc(200, FALSE);
1284
1285     if (!hdc || !hdc_200) return;
1286
1287     test_device_caps( hdc, hdc_200, "printer dc", is_postscript_printer(hdc) ? 2 : 1 );
1288     DeleteDC( hdc_200 );
1289
1290     hdc_200 = create_printer_dc(200, TRUE);
1291     test_device_caps( hdc, hdc_200, "printer dc", is_postscript_printer(hdc) ? 2 : 1 );
1292     DeleteDC( hdc_200 );
1293
1294     memdc = CreateCompatibleDC( hdc );
1295     display_memdc = CreateCompatibleDC( 0 );
1296
1297     ok( memdc != NULL, "CreateCompatibleDC failed for printer\n" );
1298     ok( display_memdc != NULL, "CreateCompatibleDC failed for screen\n" );
1299
1300     ret = GetDeviceCaps( hdc, TECHNOLOGY );
1301     ok( ret == DT_RASPRINTER, "wrong type %u\n", ret );
1302
1303     ret = GetDeviceCaps( memdc, TECHNOLOGY );
1304     ok( ret == DT_RASPRINTER, "wrong type %u\n", ret );
1305
1306     ret = GetDeviceCaps( display_memdc, TECHNOLOGY );
1307     ok( ret == DT_RASDISPLAY, "wrong type %u\n", ret );
1308
1309     bmp = CreateBitmap( 100, 100, 1, GetDeviceCaps( hdc, BITSPIXEL ), NULL );
1310     orig = SelectObject( memdc, bmp );
1311     ok( orig != NULL, "SelectObject failed\n" );
1312     ok( BitBlt( hdc, 10, 10, 20, 20, memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
1313
1314     test_device_caps( memdc, hdc, "printer dc", 1 );
1315
1316     ok( !SelectObject( display_memdc, bmp ), "SelectObject succeeded\n" );
1317     SelectObject( memdc, orig );
1318     DeleteObject( bmp );
1319
1320     bmp = CreateBitmap( 100, 100, 1, 1, NULL );
1321     orig = SelectObject( display_memdc, bmp );
1322     ok( orig != NULL, "SelectObject failed\n" );
1323     ok( !SelectObject( memdc, bmp ), "SelectObject succeeded\n" );
1324     ok( BitBlt( hdc, 10, 10, 20, 20, display_memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
1325     ok( BitBlt( memdc, 10, 10, 20, 20, display_memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
1326     ok( BitBlt( display_memdc, 10, 10, 20, 20, memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
1327
1328     ret = GetPixel( hdc, 0, 0 );
1329     ok( ret == CLR_INVALID, "wrong pixel value %x\n", ret );
1330
1331     enhmf_dc = CreateEnhMetaFileA( hdc, NULL, NULL, NULL );
1332     ok(enhmf_dc != 0, "CreateEnhMetaFileA failed\n");
1333     test_device_caps( enhmf_dc, hdc, "enhmetafile printer dc", 1 );
1334     DeleteEnhMetaFile( CloseEnhMetaFile( enhmf_dc ));
1335
1336     enhmf_dc = CreateEnhMetaFileA( hdc, NULL, NULL, NULL );
1337     ok(enhmf_dc != 0, "CreateEnhMetaFileA failed\n");
1338     test_device_caps( enhmf_dc, hdc, "enhmetafile printer dc", 1 );
1339     DeleteEnhMetaFile( CloseEnhMetaFile( enhmf_dc ));
1340
1341     DeleteDC( memdc );
1342     DeleteDC( display_memdc );
1343     DeleteDC( hdc );
1344     DeleteObject( bmp );
1345 }
1346
1347 START_TEST(dc)
1348 {
1349     pSetLayout = (void *)GetProcAddress( GetModuleHandle("gdi32.dll"), "SetLayout");
1350     test_dc_values();
1351     test_savedc();
1352     test_savedc_2();
1353     test_GdiConvertToDevmodeW();
1354     test_CreateCompatibleDC();
1355     test_DC_bitmap();
1356     test_DeleteDC();
1357     test_boundsrect();
1358     test_desktop_colorres();
1359     test_gamma();
1360     test_printer_dc();
1361 }