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