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