d3d9: COM cleanup for the IDirect3DVertexDeclaration9 interface.
[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         todo_wine
371         ok( !type, "GetBoundsRect succeeded on %s\n", descr );
372     }
373     else
374     {
375         for (i = 0; i < sizeof(caps)/sizeof(caps[0]); i++)
376             ok( GetDeviceCaps( hdc, caps[i] ) == GetDeviceCaps( ref_dc, caps[i] ),
377                 "mismatched caps on %s for %u: %u/%u\n", descr, caps[i],
378                 GetDeviceCaps( hdc, caps[i] ), GetDeviceCaps( ref_dc, caps[i] ) );
379
380         SetLastError( 0xdeadbeef );
381         ret = GetDeviceGammaRamp( hdc, &ramp );
382         ok( !ret, "GetDeviceGammaRamp succeeded on %s\n", descr );
383         ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef), /* nt4 */
384             "wrong error %u on %s\n", GetLastError(), descr );
385         type = GetClipBox( hdc, &rect );
386         if (GetObjectType( hdc ) == OBJ_ENHMETADC)
387             todo_wine ok( type == SIMPLEREGION, "GetClipBox returned %d on memdc for %s\n", type, descr );
388         else
389             ok( type == SIMPLEREGION, "GetClipBox returned %d on memdc for %s\n", type, descr );
390
391         SetBoundsRect( hdc, NULL, DCB_RESET | DCB_ENABLE );
392         SetMapMode( hdc, MM_TEXT );
393         Rectangle( hdc, 2, 2, 4, 4 );
394         type = GetBoundsRect( hdc, &rect, DCB_RESET );
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 on memdc for %s\n",
398             rect.left, rect.top, rect.right, rect.bottom, type, descr );
399     }
400
401     type = GetClipBox( ref_dc, &rect );
402     ok( type == SIMPLEREGION, "GetClipBox returned %d on %s\n", type, descr );
403     ok( rect.left == 0 && rect.top == 0 &&
404         rect.right == GetDeviceCaps( ref_dc, DESKTOPHORZRES ) &&
405         rect.bottom == GetDeviceCaps( ref_dc, DESKTOPVERTRES ),
406         "GetClipBox returned %d,%d,%d,%d on %s\n", rect.left, rect.top, rect.right, rect.bottom, descr );
407
408     SetBoundsRect( ref_dc, NULL, DCB_RESET | DCB_ACCUMULATE );
409     SetMapMode( ref_dc, MM_TEXT );
410     Rectangle( ref_dc, 3, 3, 5, 5 );
411     type = GetBoundsRect( ref_dc, &rect, DCB_RESET );
412     /* it may or may not work on non-memory DCs */
413     ok( (rect.left == 0 && rect.top == 0 && rect.right == 0 && rect.bottom == 0 && type == DCB_RESET) ||
414         (rect.left == 3 && rect.top == 3 && rect.right == 5 && rect.bottom == 5 && type == DCB_SET),
415         "GetBoundsRect returned %d,%d,%d,%d type %x on %s\n",
416         rect.left, rect.top, rect.right, rect.bottom, type, descr );
417
418     if (GetObjectType( hdc ) == OBJ_MEMDC)
419     {
420         char buffer[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
421         BITMAPINFO *info = (BITMAPINFO *)buffer;
422         HBITMAP dib, old;
423
424         memset( buffer, 0, sizeof(buffer) );
425         info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
426         info->bmiHeader.biWidth = 16;
427         info->bmiHeader.biHeight = 16;
428         info->bmiHeader.biPlanes = 1;
429         info->bmiHeader.biBitCount = 8;
430         info->bmiHeader.biCompression = BI_RGB;
431         dib = CreateDIBSection( ref_dc, info, DIB_RGB_COLORS, NULL, NULL, 0 );
432         old = SelectObject( hdc, dib );
433
434         for (i = 0; i < sizeof(caps)/sizeof(caps[0]); i++)
435             ok( GetDeviceCaps( hdc, caps[i] ) == GetDeviceCaps( ref_dc, caps[i] ),
436                 "mismatched caps on %s and DIB for %u: %u/%u\n", descr, caps[i],
437                 GetDeviceCaps( hdc, caps[i] ), GetDeviceCaps( ref_dc, caps[i] ) );
438
439         SetLastError( 0xdeadbeef );
440         ret = GetDeviceGammaRamp( hdc, &ramp );
441         ok( !ret, "GetDeviceGammaRamp succeeded on %s\n", descr );
442         ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef), /* nt4 */
443             "wrong error %u on %s\n", GetLastError(), descr );
444
445         type = GetClipBox( hdc, &rect );
446         ok( type == SIMPLEREGION, "GetClipBox returned %d on memdc for %s\n", type, descr );
447         ok( rect.left == 0 && rect.top == 0 && rect.right == 16 && rect.bottom == 16,
448             "GetClipBox returned %d,%d,%d,%d on memdc for %s\n",
449             rect.left, rect.top, rect.right, rect.bottom, descr );
450
451         SetBoundsRect( hdc, NULL, DCB_RESET | DCB_ENABLE );
452         SetMapMode( hdc, MM_TEXT );
453         Rectangle( hdc, 5, 5, 12, 14 );
454         type = GetBoundsRect( hdc, &rect, DCB_RESET );
455         todo_wine
456         ok( rect.left == 5 && rect.top == 5 && rect.right == 12 && rect.bottom == 14 && type == DCB_SET,
457             "GetBoundsRect returned %d,%d,%d,%d type %x on memdc for %s\n",
458             rect.left, rect.top, rect.right, rect.bottom, type, descr );
459
460         SelectObject( hdc, old );
461         DeleteObject( dib );
462     }
463 }
464
465 static void test_CreateCompatibleDC(void)
466 {
467     BOOL bRet;
468     HDC hdc, hNewDC, hdcMetafile, screen_dc;
469     HBITMAP bitmap;
470     INT caps;
471
472     screen_dc = CreateDC( "DISPLAY", NULL, NULL, NULL );
473     bitmap = CreateBitmap( 10, 10, 1, 1, NULL );
474
475     /* Create a DC compatible with the screen */
476     hdc = CreateCompatibleDC(NULL);
477     ok(hdc != NULL, "CreateCompatibleDC returned %p\n", hdc);
478     ok( SelectObject( hdc, bitmap ) != 0, "SelectObject failed\n" );
479     caps = GetDeviceCaps( hdc, TECHNOLOGY );
480     ok( caps == DT_RASDISPLAY, "wrong caps %u\n", caps );
481
482     test_device_caps( hdc, screen_dc, "display dc" );
483
484     /* Delete this DC, this should succeed */
485     bRet = DeleteDC(hdc);
486     ok(bRet == TRUE, "DeleteDC returned %u\n", bRet);
487
488     /* Try to create a DC compatible to the deleted DC. This has to fail */
489     hNewDC = CreateCompatibleDC(hdc);
490     ok(hNewDC == NULL, "CreateCompatibleDC returned %p\n", hNewDC);
491
492     hdc = GetDC( 0 );
493     hdcMetafile = CreateEnhMetaFileA(hdc, NULL, NULL, NULL);
494     ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
495     hNewDC = CreateCompatibleDC( hdcMetafile );
496     ok(hNewDC != NULL, "CreateCompatibleDC failed\n");
497     ok( SelectObject( hNewDC, bitmap ) != 0, "SelectObject failed\n" );
498     caps = GetDeviceCaps( hdcMetafile, TECHNOLOGY );
499     ok( caps == DT_RASDISPLAY, "wrong caps %u\n", caps );
500     test_device_caps( hdcMetafile, hdc, "enhmetafile dc" );
501     DeleteDC( hNewDC );
502     DeleteEnhMetaFile( CloseEnhMetaFile( hdcMetafile ));
503     ReleaseDC( 0, hdc );
504
505     hdcMetafile = CreateMetaFileA(NULL);
506     ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
507     hNewDC = CreateCompatibleDC( hdcMetafile );
508     ok(hNewDC == NULL, "CreateCompatibleDC succeeded\n");
509     caps = GetDeviceCaps( hdcMetafile, TECHNOLOGY );
510     ok( caps == DT_METAFILE, "wrong caps %u\n", caps );
511     test_device_caps( hdcMetafile, screen_dc, "metafile dc" );
512     DeleteMetaFile( CloseMetaFile( hdcMetafile ));
513
514     DeleteObject( bitmap );
515     DeleteDC( screen_dc );
516 }
517
518 static void test_DC_bitmap(void)
519 {
520     HDC hdc, hdcmem;
521     DWORD bits[64];
522     HBITMAP hbmp, oldhbmp;
523     COLORREF col;
524     int i, bitspixel;
525
526     /* fill bitmap data with b&w pattern */
527     for( i = 0; i < 64; i++) bits[i] = i & 1 ? 0 : 0xffffff;
528
529     hdc = GetDC(0);
530     ok( hdc != NULL, "CreateDC rets %p\n", hdc);
531     bitspixel = GetDeviceCaps( hdc, BITSPIXEL);
532     /* create a memory dc */
533     hdcmem = CreateCompatibleDC( hdc);
534     ok( hdcmem != NULL, "CreateCompatibleDC rets %p\n", hdcmem);
535     /* tests */
536     /* test monochrome bitmap: should always work */
537     hbmp = CreateBitmap(32, 32, 1, 1, bits);
538     ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
539     oldhbmp = SelectObject( hdcmem, hbmp);
540     ok( oldhbmp != NULL, "SelectObject returned NULL\n" ); /* a memdc always has a bitmap selected */
541     col = GetPixel( hdcmem, 0, 0);
542     ok( col == 0xffffff, "GetPixel returned %08x, expected 00ffffff\n", col);
543     col = GetPixel( hdcmem, 1, 1);
544     ok( col == 0x000000, "GetPixel returned %08x, expected 00000000\n", col);
545     col = GetPixel( hdcmem, 100, 1);
546     ok( col == CLR_INVALID, "GetPixel returned %08x, expected ffffffff\n", col);
547     SelectObject( hdcmem, oldhbmp);
548     DeleteObject( hbmp);
549
550     /* test with 2 bits color depth, not likely to succeed */
551     hbmp = CreateBitmap(16, 16, 1, 2, bits);
552     ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
553     oldhbmp = SelectObject( hdcmem, hbmp);
554     if( bitspixel != 2)
555         ok( !oldhbmp, "SelectObject of a bitmap with 2 bits/pixel should return  NULL\n");
556     if( oldhbmp) SelectObject( hdcmem, oldhbmp);
557     DeleteObject( hbmp);
558
559     /* test with 16 bits color depth, might succeed */
560     hbmp = CreateBitmap(6, 6, 1, 16, bits);
561     ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
562     oldhbmp = SelectObject( hdcmem, hbmp);
563     if( bitspixel == 16) {
564         ok( oldhbmp != NULL, "SelectObject returned NULL\n" );
565         col = GetPixel( hdcmem, 0, 0);
566         ok( col == 0xffffff,
567             "GetPixel of a bitmap with 16 bits/pixel returned %08x, expected 00ffffff\n", col);
568         col = GetPixel( hdcmem, 1, 1);
569         ok( col == 0x000000,
570             "GetPixel of a bitmap with 16 bits/pixel returned returned %08x, expected 00000000\n", col);
571     }
572     if( oldhbmp) SelectObject( hdcmem, oldhbmp);
573     DeleteObject( hbmp);
574
575     /* test with 32 bits color depth, probably succeed */
576     hbmp = CreateBitmap(4, 4, 1, 32, bits);
577     ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
578     oldhbmp = SelectObject( hdcmem, hbmp);
579     if( bitspixel == 32) {
580         ok( oldhbmp != NULL, "SelectObject returned NULL\n" );
581         col = GetPixel( hdcmem, 0, 0);
582         ok( col == 0xffffff,
583             "GetPixel of a bitmap with 32 bits/pixel returned %08x, expected 00ffffff\n", col);
584         col = GetPixel( hdcmem, 1, 1);
585         ok( col == 0x000000,
586             "GetPixel of a bitmap with 32 bits/pixel returned returned %08x, expected 00000000\n", col);
587     }
588     if( oldhbmp) SelectObject( hdcmem, oldhbmp);
589     DeleteObject( hbmp);
590     ReleaseDC( 0, hdc );
591 }
592
593 static void test_DeleteDC(void)
594 {
595     HWND hwnd;
596     HDC hdc, hdc_test;
597     WNDCLASSEX cls;
598     int ret;
599
600     /* window DC */
601     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
602                            0, 0, 0, NULL);
603     ok(hwnd != 0, "CreateWindowExA failed\n");
604
605     hdc = GetDC(hwnd);
606     ok(hdc != 0, "GetDC failed\n");
607     ret = GetObjectType(hdc);
608     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
609     ret = DeleteDC(hdc);
610     ok(ret, "DeleteDC failed\n");
611     ret = GetObjectType(hdc);
612     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
613
614     hdc = GetWindowDC(hwnd);
615     ok(hdc != 0, "GetDC failed\n");
616     ret = GetObjectType(hdc);
617     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
618     ret = DeleteDC(hdc);
619     ok(ret, "DeleteDC failed\n");
620     ret = GetObjectType(hdc);
621     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
622
623     DestroyWindow(hwnd);
624
625     /* desktop window DC */
626     hwnd = GetDesktopWindow();
627     ok(hwnd != 0, "GetDesktopWindow failed\n");
628
629     hdc = GetDC(hwnd);
630     ok(hdc != 0, "GetDC failed\n");
631     ret = GetObjectType(hdc);
632     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
633     ret = DeleteDC(hdc);
634     ok(ret, "DeleteDC failed\n");
635     ret = GetObjectType(hdc);
636     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
637
638     hdc = GetWindowDC(hwnd);
639     ok(hdc != 0, "GetDC failed\n");
640     ret = GetObjectType(hdc);
641     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
642     ret = DeleteDC(hdc);
643     ok(ret, "DeleteDC failed\n");
644     ret = GetObjectType(hdc);
645     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
646
647     /* CS_CLASSDC */
648     memset(&cls, 0, sizeof(cls));
649     cls.cbSize = sizeof(cls);
650     cls.style = CS_CLASSDC;
651     cls.hInstance = GetModuleHandle(0);
652     cls.lpszClassName = "Wine class DC";
653     cls.lpfnWndProc = DefWindowProcA;
654     ret = RegisterClassExA(&cls);
655     ok(ret, "RegisterClassExA failed\n");
656
657     hwnd = CreateWindowExA(0, "Wine class DC", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
658                            0, 0, 0, NULL);
659     ok(hwnd != 0, "CreateWindowExA failed\n");
660
661     hdc = GetDC(hwnd);
662     ok(hdc != 0, "GetDC failed\n");
663     ret = GetObjectType(hdc);
664     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
665     ret = DeleteDC(hdc);
666     ok(ret, "DeleteDC failed\n");
667     ret = GetObjectType(hdc);
668     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
669     ret = ReleaseDC(hwnd, hdc);
670     ok(ret, "ReleaseDC failed\n");
671     ret = GetObjectType(hdc);
672     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
673
674     hdc_test = hdc;
675
676     hdc = GetWindowDC(hwnd);
677     ok(hdc != 0, "GetDC failed\n");
678     ret = GetObjectType(hdc);
679     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
680     ret = DeleteDC(hdc);
681     ok(ret, "DeleteDC failed\n");
682     ret = GetObjectType(hdc);
683     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
684
685     DestroyWindow(hwnd);
686
687     ret = GetObjectType(hdc_test);
688     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
689
690     ret = UnregisterClassA("Wine class DC", GetModuleHandle(NULL));
691     ok(ret, "UnregisterClassA failed\n");
692
693     ret = GetObjectType(hdc_test);
694 todo_wine
695     ok(!ret, "GetObjectType should fail for a deleted DC\n");
696
697     /* CS_OWNDC */
698     memset(&cls, 0, sizeof(cls));
699     cls.cbSize = sizeof(cls);
700     cls.style = CS_OWNDC;
701     cls.hInstance = GetModuleHandle(0);
702     cls.lpszClassName = "Wine own DC";
703     cls.lpfnWndProc = DefWindowProcA;
704     ret = RegisterClassExA(&cls);
705     ok(ret, "RegisterClassExA failed\n");
706
707     hwnd = CreateWindowExA(0, "Wine own DC", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
708                            0, 0, 0, NULL);
709     ok(hwnd != 0, "CreateWindowExA failed\n");
710
711     hdc = GetDC(hwnd);
712     ok(hdc != 0, "GetDC failed\n");
713     ret = GetObjectType(hdc);
714     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
715     ret = DeleteDC(hdc);
716     ok(ret, "DeleteDC failed\n");
717     ret = GetObjectType(hdc);
718     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
719     ret = ReleaseDC(hwnd, hdc);
720     ok(ret, "ReleaseDC failed\n");
721     ret = GetObjectType(hdc);
722     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
723
724     hdc = GetWindowDC(hwnd);
725     ok(hdc != 0, "GetDC failed\n");
726     ret = GetObjectType(hdc);
727     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
728     ret = DeleteDC(hdc);
729     ok(ret, "DeleteDC failed\n");
730     ret = GetObjectType(hdc);
731     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
732
733     DestroyWindow(hwnd);
734
735     ret = UnregisterClassA("Wine own DC", GetModuleHandle(NULL));
736     ok(ret, "UnregisterClassA failed\n");
737 }
738
739 static void test_boundsrect(void)
740 {
741     char buffer[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
742     BITMAPINFO *info = (BITMAPINFO *)buffer;
743     HDC hdc;
744     HBITMAP bitmap, dib, old;
745     RECT rect, expect, set_rect;
746     UINT ret;
747     int level;
748
749     hdc = CreateCompatibleDC(0);
750     ok(hdc != NULL, "CreateCompatibleDC failed\n");
751     bitmap = CreateCompatibleBitmap( hdc, 200, 200 );
752     old = SelectObject( hdc, bitmap );
753
754     ret = GetBoundsRect(hdc, NULL, 0);
755     ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
756
757     ret = GetBoundsRect(hdc, NULL, ~0U);
758     ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
759
760     /* Test parameter handling order. */
761     SetRect(&set_rect, 10, 20, 40, 50);
762     ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
763     ok(ret & DCB_RESET,
764        "Expected return flag DCB_RESET to be set, got %u\n", ret);
765
766     ret = GetBoundsRect(hdc, NULL, DCB_RESET);
767     ok(ret == 0,
768        "Expected GetBoundsRect to return 0, got %u\n", ret);
769
770     ret = GetBoundsRect(hdc, &rect, 0);
771     ok(ret == DCB_RESET,
772        "Expected GetBoundsRect to return DCB_RESET, got %u\n", ret);
773     SetRect(&expect, 0, 0, 0, 0);
774     ok(EqualRect(&rect, &expect) ||
775        broken(EqualRect(&rect, &set_rect)), /* nt4 sp1-5 */
776        "Expected output rectangle (0,0)-(0,0), got (%d,%d)-(%d,%d)\n",
777        rect.left, rect.top, rect.right, rect.bottom);
778
779     ret = GetBoundsRect(NULL, NULL, 0);
780     ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
781
782     ret = GetBoundsRect(NULL, NULL, ~0U);
783     ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
784
785     ret = SetBoundsRect(NULL, NULL, 0);
786     ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret);
787
788     ret = SetBoundsRect(NULL, NULL, ~0U);
789     ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret);
790
791     SetRect(&set_rect, 10, 20, 40, 50);
792     ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
793     ok(ret == (DCB_RESET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
794
795     ret = GetBoundsRect(hdc, &rect, 0);
796     ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
797     SetRect(&expect, 10, 20, 40, 50);
798     ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
799        rect.left, rect.top, rect.right, rect.bottom);
800
801     SetMapMode( hdc, MM_ANISOTROPIC );
802     SetViewportExtEx( hdc, 2, 2, NULL );
803     ret = GetBoundsRect(hdc, &rect, 0);
804     ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
805     SetRect(&expect, 5, 10, 20, 25);
806     ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
807        rect.left, rect.top, rect.right, rect.bottom);
808
809     SetViewportOrgEx( hdc, 20, 30, NULL );
810     ret = GetBoundsRect(hdc, &rect, 0);
811     ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
812     SetRect(&expect, -5, -5, 10, 10);
813     ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
814        rect.left, rect.top, rect.right, rect.bottom);
815
816     SetRect(&set_rect, 10, 20, 40, 50);
817     ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
818     ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
819
820     ret = GetBoundsRect(hdc, &rect, 0);
821     ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
822     SetRect(&expect, 10, 20, 40, 50);
823     ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
824        rect.left, rect.top, rect.right, rect.bottom);
825
826     SetMapMode( hdc, MM_TEXT );
827     SetViewportOrgEx( hdc, 0, 0, NULL );
828     ret = GetBoundsRect(hdc, &rect, 0);
829     ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
830     SetRect(&expect, 40, 70, 100, 130);
831     ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
832        rect.left, rect.top, rect.right, rect.bottom);
833
834     if (pSetLayout)
835     {
836         pSetLayout( hdc, LAYOUT_RTL );
837         ret = GetBoundsRect(hdc, &rect, 0);
838         ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
839         SetRect(&expect, 159, 70, 99, 130);
840         ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
841            rect.left, rect.top, rect.right, rect.bottom);
842         SetRect(&set_rect, 50, 25, 30, 35);
843         ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
844         ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
845         ret = GetBoundsRect(hdc, &rect, 0);
846         ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
847         SetRect(&expect, 50, 25, 30, 35);
848         ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
849            rect.left, rect.top, rect.right, rect.bottom);
850
851         pSetLayout( hdc, LAYOUT_LTR );
852         ret = GetBoundsRect(hdc, &rect, 0);
853         ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
854         SetRect(&expect, 149, 25, 169, 35);
855         ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
856            rect.left, rect.top, rect.right, rect.bottom);
857     }
858
859     /* empty rect resets, except on nt4 */
860     SetRect(&expect, 20, 20, 10, 10);
861     ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
862     ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
863     ret = GetBoundsRect(hdc, &rect, 0);
864     ok(ret == DCB_RESET || broken(ret == DCB_SET)  /* nt4 */,
865        "GetBoundsRect returned %x\n", ret);
866     if (ret == DCB_RESET)
867     {
868         SetRect(&expect, 0, 0, 0, 0);
869         ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
870            rect.left, rect.top, rect.right, rect.bottom);
871
872         SetRect(&expect, 20, 20, 20, 20);
873         ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
874         ok(ret == (DCB_RESET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
875         ret = GetBoundsRect(hdc, &rect, 0);
876         ok(ret == DCB_RESET, "GetBoundsRect returned %x\n", ret);
877         SetRect(&expect, 0, 0, 0, 0);
878         ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
879            rect.left, rect.top, rect.right, rect.bottom);
880     }
881
882     SetBoundsRect( hdc, NULL, DCB_RESET | DCB_ENABLE );
883     MoveToEx( hdc, 10, 10, NULL );
884     LineTo( hdc, 20, 20 );
885     ret = GetBoundsRect( hdc, &rect, 0 );
886     todo_wine
887     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
888     SetRect( &expect, 10, 10, 21, 21 );
889     todo_wine
890     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
891     SetRect( &rect, 8, 8, 23, 23 );
892     expect = rect;
893     SetBoundsRect( hdc, &rect, DCB_ACCUMULATE );
894     ret = GetBoundsRect( hdc, &rect, 0 );
895     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
896     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
897
898     level = SaveDC( hdc );
899     LineTo( hdc, 30, 25 );
900     ret = GetBoundsRect( hdc, &rect, 0 );
901     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
902     SetRect( &expect, 8, 8, 31, 26 );
903     todo_wine
904     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
905     SetBoundsRect( hdc, NULL, DCB_DISABLE );
906     LineTo( hdc, 40, 40 );
907     ret = GetBoundsRect( hdc, &rect, 0 );
908     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
909     SetRect( &expect, 8, 8, 31, 26 );
910     todo_wine
911     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
912     SetRect( &rect, 6, 6, 30, 30 );
913     SetBoundsRect( hdc, &rect, DCB_ACCUMULATE );
914     ret = GetBoundsRect( hdc, &rect, 0 );
915     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
916     SetRect( &expect, 6, 6, 31, 30 );
917     todo_wine
918     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
919
920     RestoreDC( hdc, level );
921     ret = GetBoundsRect( hdc, &rect, 0 );
922     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
923     todo_wine
924     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
925     LineTo( hdc, 40, 40 );
926     ret = GetBoundsRect( hdc, &rect, 0 );
927     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
928     todo_wine
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     todo_wine
944     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
945     SelectObject( hdc, GetStockObject( NULL_PEN ));
946     LineTo( hdc, 50, 50 );
947     ret = GetBoundsRect( hdc, &rect, 0 );
948     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
949     SetRect( &expect, 6, 6, 51, 51 );
950     todo_wine
951     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
952
953     memset( buffer, 0, sizeof(buffer) );
954     info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
955     info->bmiHeader.biWidth = 64;
956     info->bmiHeader.biHeight = 64;
957     info->bmiHeader.biPlanes = 1;
958     info->bmiHeader.biBitCount = 8;
959     info->bmiHeader.biCompression = BI_RGB;
960     dib = CreateDIBSection( 0, info, DIB_RGB_COLORS, NULL, NULL, 0 );
961     ok( dib != 0, "failed to create DIB\n" );
962     SelectObject( hdc, dib );
963     ret = GetBoundsRect( hdc, &rect, 0 );
964     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
965     SetRect( &expect, 6, 6, 51, 51 );
966     todo_wine
967     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
968     LineTo( hdc, 55, 30 );
969     ret = GetBoundsRect( hdc, &rect, 0 );
970     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
971     SetRect( &expect, 6, 6, 56, 51 );
972     todo_wine
973     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
974     LineTo( hdc, 100, 30 );
975     ret = GetBoundsRect( hdc, &rect, 0 );
976     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
977     SetRect( &expect, 6, 6, 64, 51 );
978     todo_wine
979     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
980     LineTo( hdc, -100, -100 );
981     ret = GetBoundsRect( hdc, &rect, 0 );
982     ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
983     SetRect( &expect, 0, 0, 64, 51 );
984     todo_wine
985     ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
986
987     DeleteDC( hdc );
988     DeleteObject( bitmap );
989     DeleteObject( dib );
990 }
991
992 static void test_desktop_colorres(void)
993 {
994     HDC hdc = GetDC(NULL);
995     int bitspixel, colorres;
996
997     bitspixel = GetDeviceCaps(hdc, BITSPIXEL);
998     ok(bitspixel != 0, "Expected to get valid BITSPIXEL capability value\n");
999
1000     colorres = GetDeviceCaps(hdc, COLORRES);
1001     ok(colorres != 0 ||
1002        broken(colorres == 0), /* Win9x */
1003        "Expected to get valid COLORRES capability value\n");
1004
1005     if (colorres)
1006     {
1007         switch (bitspixel)
1008         {
1009         case 8:
1010             ok(colorres == 18,
1011                "Expected COLORRES to be 18, got %d\n", colorres);
1012             break;
1013         case 16:
1014             ok(colorres == 16,
1015                "Expected COLORRES to be 16, got %d\n", colorres);
1016             break;
1017         case 24:
1018         case 32:
1019             ok(colorres == 24,
1020                "Expected COLORRES to be 24, got %d\n", bitspixel);
1021             break;
1022         default:
1023             ok(0, "Got unknown BITSPIXEL %d with COLORRES %d\n", bitspixel, colorres);
1024             break;
1025         }
1026     }
1027
1028     ReleaseDC(NULL, hdc);
1029 }
1030
1031 static void test_gamma(void)
1032 {
1033     BOOL ret;
1034     HDC hdc = GetDC(NULL);
1035     WORD oldramp[3][256], ramp[3][256];
1036     INT i;
1037
1038     ret = GetDeviceGammaRamp(hdc, &oldramp);
1039     if (!ret)
1040     {
1041         win_skip("GetDeviceGammaRamp failed, skipping tests\n");
1042         goto done;
1043     }
1044
1045     /* try to set back old ramp */
1046     ret = SetDeviceGammaRamp(hdc, &oldramp);
1047     if (!ret)
1048     {
1049         win_skip("SetDeviceGammaRamp failed, skipping tests\n");
1050         goto done;
1051     }
1052
1053     memcpy(ramp, oldramp, sizeof(ramp));
1054
1055     /* set one color ramp to zeros */
1056     memset(ramp[0], 0, sizeof(ramp[0]));
1057     ret = SetDeviceGammaRamp(hdc, &ramp);
1058     ok(!ret, "SetDeviceGammaRamp succeeded\n");
1059
1060     /* set one color ramp to a flat straight rising line */
1061     for (i = 0; i < 256; i++) ramp[0][i] = i;
1062     ret = SetDeviceGammaRamp(hdc, &ramp);
1063     todo_wine ok(!ret, "SetDeviceGammaRamp succeeded\n");
1064
1065     /* set one color ramp to a steep straight rising line */
1066     for (i = 0; i < 256; i++) ramp[0][i] = i * 256;
1067     ret = SetDeviceGammaRamp(hdc, &ramp);
1068     ok(ret, "SetDeviceGammaRamp failed\n");
1069
1070     /* try a bright gamma ramp */
1071     ramp[0][0] = 0;
1072     ramp[0][1] = 0x7FFF;
1073     for (i = 2; i < 256; i++) ramp[0][i] = 0xFFFF;
1074     ret = SetDeviceGammaRamp(hdc, &ramp);
1075     ok(!ret, "SetDeviceGammaRamp succeeded\n");
1076
1077     /* try ramps which are not uniform */
1078     ramp[0][0] = 0;
1079     for (i = 1; i < 256; i++) ramp[0][i] = ramp[0][i - 1] + 512;
1080     ret = SetDeviceGammaRamp(hdc, &ramp);
1081     ok(ret, "SetDeviceGammaRamp failed\n");
1082     ramp[0][0] = 0;
1083     for (i = 2; i < 256; i+=2)
1084     {
1085         ramp[0][i - 1] = ramp[0][i - 2];
1086         ramp[0][i] = ramp[0][i - 2] + 512;
1087     }
1088     ret = SetDeviceGammaRamp(hdc, &ramp);
1089     ok(ret, "SetDeviceGammaRamp failed\n");
1090
1091     /* cleanup: set old ramp again */
1092     ret = SetDeviceGammaRamp(hdc, &oldramp);
1093     ok(ret, "SetDeviceGammaRamp failed\n");
1094
1095 done:
1096     ReleaseDC(NULL, hdc);
1097 }
1098
1099 static HDC create_printer_dc(void)
1100 {
1101     char buffer[260];
1102     DWORD len;
1103     PRINTER_INFO_2A *pbuf = NULL;
1104     DRIVER_INFO_3A *dbuf = NULL;
1105     HANDLE hprn = 0;
1106     HDC hdc = 0;
1107     HMODULE winspool = LoadLibraryA( "winspool.drv" );
1108     BOOL (WINAPI *pOpenPrinterA)(LPSTR, HANDLE *, LPPRINTER_DEFAULTSA);
1109     BOOL (WINAPI *pGetDefaultPrinterA)(LPSTR, LPDWORD);
1110     BOOL (WINAPI *pGetPrinterA)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD);
1111     BOOL (WINAPI *pGetPrinterDriverA)(HANDLE, LPSTR, DWORD, LPBYTE, DWORD, LPDWORD);
1112     BOOL (WINAPI *pClosePrinter)(HANDLE);
1113
1114     pGetDefaultPrinterA = (void *)GetProcAddress( winspool, "GetDefaultPrinterA" );
1115     pOpenPrinterA = (void *)GetProcAddress( winspool, "OpenPrinterA" );
1116     pGetPrinterA = (void *)GetProcAddress( winspool, "GetPrinterA" );
1117     pGetPrinterDriverA = (void *)GetProcAddress( winspool, "GetPrinterDriverA" );
1118     pClosePrinter = (void *)GetProcAddress( winspool, "ClosePrinter" );
1119
1120     if (!pGetDefaultPrinterA || !pOpenPrinterA || !pGetPrinterA || !pGetPrinterDriverA || !pClosePrinter)
1121         goto done;
1122
1123     len = sizeof(buffer);
1124     if (!pGetDefaultPrinterA( buffer, &len )) goto done;
1125     if (!pOpenPrinterA( buffer, &hprn, NULL )) goto done;
1126
1127     pGetPrinterA( hprn, 2, NULL, 0, &len );
1128     pbuf = HeapAlloc( GetProcessHeap(), 0, len );
1129     if (!pGetPrinterA( hprn, 2, (LPBYTE)pbuf, len, &len )) goto done;
1130
1131     pGetPrinterDriverA( hprn, NULL, 3, NULL, 0, &len );
1132     dbuf = HeapAlloc( GetProcessHeap(), 0, len );
1133     if (!pGetPrinterDriverA( hprn, NULL, 3, (LPBYTE)dbuf, len, &len )) goto done;
1134
1135     hdc = CreateDCA( dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, pbuf->pDevMode );
1136     trace( "hdc %p for driver '%s' printer '%s' port '%s'\n", hdc,
1137            dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName );
1138 done:
1139     HeapFree( GetProcessHeap(), 0, dbuf );
1140     HeapFree( GetProcessHeap(), 0, pbuf );
1141     if (hprn) pClosePrinter( hprn );
1142     if (winspool) FreeLibrary( winspool );
1143     if (!hdc) skip( "could not create a DC for the default printer\n" );
1144     return hdc;
1145 }
1146
1147 static void test_printer_dc(void)
1148 {
1149     HDC memdc, display_memdc, enhmf_dc;
1150     HBITMAP orig, bmp;
1151     DWORD ret;
1152     HDC hdc = create_printer_dc();
1153
1154     if (!hdc) return;
1155
1156     memdc = CreateCompatibleDC( hdc );
1157     display_memdc = CreateCompatibleDC( 0 );
1158
1159     ok( memdc != NULL, "CreateCompatibleDC failed for printer\n" );
1160     ok( display_memdc != NULL, "CreateCompatibleDC failed for screen\n" );
1161
1162     ret = GetDeviceCaps( hdc, TECHNOLOGY );
1163     ok( ret == DT_RASPRINTER, "wrong type %u\n", ret );
1164
1165     ret = GetDeviceCaps( memdc, TECHNOLOGY );
1166     ok( ret == DT_RASPRINTER, "wrong type %u\n", ret );
1167
1168     ret = GetDeviceCaps( display_memdc, TECHNOLOGY );
1169     ok( ret == DT_RASDISPLAY, "wrong type %u\n", ret );
1170
1171     bmp = CreateBitmap( 100, 100, 1, GetDeviceCaps( hdc, BITSPIXEL ), NULL );
1172     orig = SelectObject( memdc, bmp );
1173     ok( orig != NULL, "SelectObject failed\n" );
1174     ok( BitBlt( hdc, 10, 10, 20, 20, memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
1175
1176     test_device_caps( memdc, hdc, "printer dc" );
1177
1178     ok( !SelectObject( display_memdc, bmp ), "SelectObject succeeded\n" );
1179     SelectObject( memdc, orig );
1180     DeleteObject( bmp );
1181
1182     bmp = CreateBitmap( 100, 100, 1, 1, NULL );
1183     orig = SelectObject( display_memdc, bmp );
1184     ok( orig != NULL, "SelectObject failed\n" );
1185     ok( !SelectObject( memdc, bmp ), "SelectObject succeeded\n" );
1186     ok( BitBlt( hdc, 10, 10, 20, 20, display_memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
1187     ok( BitBlt( memdc, 10, 10, 20, 20, display_memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
1188     ok( BitBlt( display_memdc, 10, 10, 20, 20, memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
1189
1190     ret = GetPixel( hdc, 0, 0 );
1191     ok( ret == CLR_INVALID, "wrong pixel value %x\n", ret );
1192
1193     enhmf_dc = CreateEnhMetaFileA( hdc, NULL, NULL, NULL );
1194     ok(enhmf_dc != 0, "CreateEnhMetaFileA failed\n");
1195     test_device_caps( enhmf_dc, hdc, "enhmetafile printer dc" );
1196     DeleteEnhMetaFile( CloseEnhMetaFile( enhmf_dc ));
1197
1198     DeleteDC( memdc );
1199     DeleteDC( display_memdc );
1200     DeleteDC( hdc );
1201     DeleteObject( bmp );
1202 }
1203
1204 START_TEST(dc)
1205 {
1206     pSetLayout = (void *)GetProcAddress( GetModuleHandle("gdi32.dll"), "SetLayout");
1207     test_dc_values();
1208     test_savedc();
1209     test_savedc_2();
1210     test_GdiConvertToDevmodeW();
1211     test_CreateCompatibleDC();
1212     test_DC_bitmap();
1213     test_DeleteDC();
1214     test_boundsrect();
1215     test_desktop_colorres();
1216     test_gamma();
1217     test_printer_dc();
1218 }