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