msxml3: Skip leading space characters when loading from BSTR.
[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_savedc_2(void)
58 {
59     HWND hwnd;
60     HDC hdc;
61     HRGN hrgn;
62     RECT rc, rc_clip;
63     int ret;
64
65     hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,
66                            0, 0, 0, NULL);
67     assert(hwnd != 0);
68     ShowWindow(hwnd, SW_SHOW);
69     UpdateWindow(hwnd);
70
71     hrgn = CreateRectRgn(0, 0, 0, 0);
72     assert(hrgn != 0);
73
74     hdc = GetDC(hwnd);
75     ok(hdc != NULL, "GetDC failed\n");
76
77     ret = GetClipBox(hdc, &rc_clip);
78     ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION), "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
79     ret = GetClipRgn(hdc, hrgn);
80     ok(ret == 0, "GetClipRgn returned %d instead of 0\n", ret);
81     ret = GetRgnBox(hrgn, &rc);
82     ok(ret == NULLREGION, "GetRgnBox returned %d (%d,%d-%d,%d) instead of NULLREGION\n",
83        ret, rc.left, rc.top, rc.right, rc.bottom);
84     /*dump_region(hrgn);*/
85     SetRect(&rc, 0, 0, 100, 100);
86     ok(EqualRect(&rc, &rc_clip),
87        "rects are not equal: (%d,%d-%d,%d) - (%d,%d-%d,%d)\n",
88        rc.left, rc.top, rc.right, rc.bottom,
89        rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
90
91     ret = SaveDC(hdc);
92 todo_wine
93 {
94     ok(ret == 1, "ret = %d\n", ret);
95 }
96
97     ret = IntersectClipRect(hdc, 0, 0, 50, 50);
98     if (ret == COMPLEXREGION)
99     {
100         /* XP returns COMPLEXREGION although dump_region reports only 1 rect */
101         trace("Windows BUG: IntersectClipRect returned %d instead of SIMPLEREGION\n", ret);
102         /* let's make sure that it's a simple region */
103         ret = GetClipRgn(hdc, hrgn);
104         ok(ret == 1, "GetClipRgn returned %d instead of 1\n", ret);
105         dump_region(hrgn);
106     }
107     else
108         ok(ret == SIMPLEREGION, "IntersectClipRect returned %d instead of SIMPLEREGION\n", ret);
109
110     ret = GetClipBox(hdc, &rc_clip);
111     ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION), "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
112     SetRect(&rc, 0, 0, 50, 50);
113     ok(EqualRect(&rc, &rc_clip),
114        "rects are not equal: (%d,%d-%d,%d) - (%d,%d-%d,%d)\n",
115        rc.left, rc.top, rc.right, rc.bottom,
116        rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
117
118     ret = RestoreDC(hdc, 1);
119     ok(ret, "ret = %d\n", ret);
120
121     ret = GetClipBox(hdc, &rc_clip);
122     ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION), "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
123     SetRect(&rc, 0, 0, 100, 100);
124     ok(EqualRect(&rc, &rc_clip),
125        "rects are not equal: (%d,%d-%d,%d) - (%d,%d-%d,%d)\n",
126        rc.left, rc.top, rc.right, rc.bottom,
127        rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
128
129     DeleteObject(hrgn);
130     ReleaseDC(hwnd, hdc);
131     DestroyWindow(hwnd);
132 }
133
134 static void test_savedc(void)
135 {
136     HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
137     int ret;
138
139     ok(hdc != NULL, "CreateDC rets %p\n", hdc);
140
141     ret = SaveDC(hdc);
142     ok(ret == 1, "ret = %d\n", ret);
143     ret = SaveDC(hdc);
144     ok(ret == 2, "ret = %d\n", ret);
145     ret = SaveDC(hdc);
146     ok(ret == 3, "ret = %d\n", ret);
147     ret = RestoreDC(hdc, -1);
148     ok(ret, "ret = %d\n", ret);
149     ret = SaveDC(hdc);
150     ok(ret == 3, "ret = %d\n", ret);
151     ret = RestoreDC(hdc, 1);
152     ok(ret, "ret = %d\n", ret);
153     ret = SaveDC(hdc);
154     ok(ret == 1, "ret = %d\n", ret);
155     ret = SaveDC(hdc);
156     ok(ret == 2, "ret = %d\n", ret);
157     ret = SaveDC(hdc);
158     ok(ret == 3, "ret = %d\n", ret);
159     ret = RestoreDC(hdc, -2);
160     ok(ret, "ret = %d\n", ret);
161     ret = SaveDC(hdc);
162     ok(ret == 2, "ret = %d\n", ret);
163     ret = RestoreDC(hdc, -2);
164     ok(ret, "ret = %d\n", ret);
165     ret = SaveDC(hdc);
166     ok(ret == 1, "ret = %d\n", ret);
167     ret = SaveDC(hdc);
168     ok(ret == 2, "ret = %d\n", ret); 
169     ret = RestoreDC(hdc, -4);
170     ok(!ret, "ret = %d\n", ret);
171     ret = RestoreDC(hdc, 3);
172     ok(!ret, "ret = %d\n", ret);
173
174     /* Under Win9x the following RestoreDC call succeeds and clears the save stack. */
175     ret = RestoreDC(hdc, -3);
176     ok(!ret ||
177        broken(ret), /* Win9x */
178        "ret = %d\n", ret);
179
180     /* Trying to clear an empty save stack fails. */
181     ret = RestoreDC(hdc, -3);
182     ok(!ret, "ret = %d\n", ret);
183
184     ret = SaveDC(hdc);
185     ok(ret == 3 ||
186        broken(ret == 1), /* Win9x */
187        "ret = %d\n", ret);
188
189     /* Under Win9x the following RestoreDC call succeeds and clears the save stack. */
190     ret = RestoreDC(hdc, 0);
191     ok(!ret ||
192        broken(ret), /* Win9x */
193        "ret = %d\n", ret);
194
195     /* Trying to clear an empty save stack fails. */
196     ret = RestoreDC(hdc, 0);
197     ok(!ret, "ret = %d\n", ret);
198
199     ret = RestoreDC(hdc, 1);
200     ok(ret ||
201        broken(!ret), /* Win9x */
202        "ret = %d\n", ret);
203
204     DeleteDC(hdc);
205 }
206
207 static void test_GdiConvertToDevmodeW(void)
208 {
209     DEVMODEW * (WINAPI *pGdiConvertToDevmodeW)(const DEVMODEA *);
210     DEVMODEA dmA;
211     DEVMODEW *dmW;
212     BOOL ret;
213
214     pGdiConvertToDevmodeW = (void *)GetProcAddress(GetModuleHandleA("gdi32.dll"), "GdiConvertToDevmodeW");
215     if (!pGdiConvertToDevmodeW)
216     {
217         win_skip("GdiConvertToDevmodeW is not available on this platform\n");
218         return;
219     }
220
221     ret = EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &dmA);
222     ok(ret, "EnumDisplaySettingsExA error %u\n", GetLastError());
223     ok(dmA.dmSize >= FIELD_OFFSET(DEVMODEA, dmICMMethod), "dmSize is too small: %04x\n", dmA.dmSize);
224     ok(dmA.dmSize <= sizeof(DEVMODEA), "dmSize is too large: %04x\n", dmA.dmSize);
225
226     dmW = pGdiConvertToDevmodeW(&dmA);
227     ok(dmW->dmSize >= FIELD_OFFSET(DEVMODEW, dmICMMethod), "dmSize is too small: %04x\n", dmW->dmSize);
228     ok(dmW->dmSize <= sizeof(DEVMODEW), "dmSize is too large: %04x\n", dmW->dmSize);
229     HeapFree(GetProcessHeap(), 0, dmW);
230
231     dmA.dmSize = FIELD_OFFSET(DEVMODEA, dmFields) + sizeof(dmA.dmFields);
232     dmW = pGdiConvertToDevmodeW(&dmA);
233     ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmFields) + sizeof(dmW->dmFields),
234        "wrong size %u\n", dmW->dmSize);
235     HeapFree(GetProcessHeap(), 0, dmW);
236
237     dmA.dmICMMethod = DMICMMETHOD_NONE;
238     dmA.dmSize = FIELD_OFFSET(DEVMODEA, dmICMMethod) + sizeof(dmA.dmICMMethod);
239     dmW = pGdiConvertToDevmodeW(&dmA);
240     ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmICMMethod) + sizeof(dmW->dmICMMethod),
241        "wrong size %u\n", dmW->dmSize);
242     ok(dmW->dmICMMethod == DMICMMETHOD_NONE,
243        "expected DMICMMETHOD_NONE, got %u\n", dmW->dmICMMethod);
244     HeapFree(GetProcessHeap(), 0, dmW);
245
246     dmA.dmSize = 1024;
247     dmW = pGdiConvertToDevmodeW(&dmA);
248     ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmPanningHeight) + sizeof(dmW->dmPanningHeight),
249        "wrong size %u\n", dmW->dmSize);
250     HeapFree(GetProcessHeap(), 0, dmW);
251
252     SetLastError(0xdeadbeef);
253     dmA.dmSize = 0;
254     dmW = pGdiConvertToDevmodeW(&dmA);
255     ok(!dmW, "GdiConvertToDevmodeW should fail\n");
256     ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
257
258     /* this is the minimal dmSize that XP accepts */
259     dmA.dmSize = FIELD_OFFSET(DEVMODEA, dmFields);
260     dmW = pGdiConvertToDevmodeW(&dmA);
261     ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmFields),
262        "expected %04x, got %04x\n", FIELD_OFFSET(DEVMODEW, dmFields), dmW->dmSize);
263     HeapFree(GetProcessHeap(), 0, dmW);
264 }
265
266 static void test_device_caps( HDC hdc, HDC ref_dc, const char *descr )
267 {
268     static const int caps[] =
269     {
270         DRIVERVERSION,
271         TECHNOLOGY,
272         HORZSIZE,
273         VERTSIZE,
274         HORZRES,
275         VERTRES,
276         BITSPIXEL,
277         PLANES,
278         NUMBRUSHES,
279         NUMPENS,
280         NUMMARKERS,
281         NUMFONTS,
282         NUMCOLORS,
283         PDEVICESIZE,
284         CURVECAPS,
285         LINECAPS,
286         POLYGONALCAPS,
287         TEXTCAPS,
288         CLIPCAPS,
289         RASTERCAPS,
290         ASPECTX,
291         ASPECTY,
292         ASPECTXY,
293         LOGPIXELSX,
294         LOGPIXELSY,
295         SIZEPALETTE,
296         NUMRESERVED,
297         COLORRES,
298         PHYSICALWIDTH,
299         PHYSICALHEIGHT,
300         PHYSICALOFFSETX,
301         PHYSICALOFFSETY,
302         SCALINGFACTORX,
303         SCALINGFACTORY,
304         VREFRESH,
305         DESKTOPVERTRES,
306         DESKTOPHORZRES,
307         BLTALIGNMENT,
308         SHADEBLENDCAPS,
309         COLORMGMTCAPS
310     };
311     unsigned int i;
312
313     if (GetObjectType( hdc ) == OBJ_METADC)
314         for (i = 0; i < sizeof(caps)/sizeof(caps[0]); i++)
315             ok( GetDeviceCaps( hdc, caps[i] ) == (caps[i] == TECHNOLOGY ? DT_METAFILE : 0),
316                 "wrong caps on %s for %u: %u\n", descr, caps[i],
317                 GetDeviceCaps( hdc, caps[i] ) );
318     else
319         for (i = 0; i < sizeof(caps)/sizeof(caps[0]); i++)
320             ok( GetDeviceCaps( hdc, caps[i] ) == GetDeviceCaps( ref_dc, caps[i] ),
321                 "mismatched caps on %s for %u: %u/%u\n", descr, caps[i],
322                 GetDeviceCaps( hdc, caps[i] ), GetDeviceCaps( ref_dc, caps[i] ) );
323
324     if (GetObjectType( hdc ) == OBJ_MEMDC)
325     {
326         char buffer[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
327         BITMAPINFO *info = (BITMAPINFO *)buffer;
328         HBITMAP dib, old;
329
330         memset( buffer, 0, sizeof(buffer) );
331         info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
332         info->bmiHeader.biWidth = 16;
333         info->bmiHeader.biHeight = 16;
334         info->bmiHeader.biPlanes = 1;
335         info->bmiHeader.biBitCount = 8;
336         info->bmiHeader.biCompression = BI_RGB;
337         dib = CreateDIBSection( ref_dc, info, DIB_RGB_COLORS, NULL, NULL, 0 );
338         old = SelectObject( hdc, dib );
339
340         for (i = 0; i < sizeof(caps)/sizeof(caps[0]); i++)
341             ok( GetDeviceCaps( hdc, caps[i] ) == GetDeviceCaps( ref_dc, caps[i] ),
342                 "mismatched caps on %s and DIB for %u: %u/%u\n", descr, caps[i],
343                 GetDeviceCaps( hdc, caps[i] ), GetDeviceCaps( ref_dc, caps[i] ) );
344
345         SelectObject( hdc, old );
346         DeleteObject( dib );
347     }
348 }
349
350 static void test_CreateCompatibleDC(void)
351 {
352     BOOL bRet;
353     HDC hdc, hNewDC, hdcMetafile, screen_dc;
354     HBITMAP bitmap;
355     INT caps;
356
357     screen_dc = GetDC( 0 );
358     bitmap = CreateBitmap( 10, 10, 1, 1, NULL );
359
360     /* Create a DC compatible with the screen */
361     hdc = CreateCompatibleDC(NULL);
362     ok(hdc != NULL, "CreateCompatibleDC returned %p\n", hdc);
363     ok( SelectObject( hdc, bitmap ) != 0, "SelectObject failed\n" );
364     caps = GetDeviceCaps( hdc, TECHNOLOGY );
365     ok( caps == DT_RASDISPLAY, "wrong caps %u\n", caps );
366
367     test_device_caps( hdc, screen_dc, "display dc" );
368
369     /* Delete this DC, this should succeed */
370     bRet = DeleteDC(hdc);
371     ok(bRet == TRUE, "DeleteDC returned %u\n", bRet);
372
373     /* Try to create a DC compatible to the deleted DC. This has to fail */
374     hNewDC = CreateCompatibleDC(hdc);
375     ok(hNewDC == NULL, "CreateCompatibleDC returned %p\n", hNewDC);
376
377     hdc = GetDC( 0 );
378     hdcMetafile = CreateEnhMetaFileA(hdc, NULL, NULL, NULL);
379     ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
380     hNewDC = CreateCompatibleDC( hdcMetafile );
381     ok(hNewDC != NULL, "CreateCompatibleDC failed\n");
382     ok( SelectObject( hNewDC, bitmap ) != 0, "SelectObject failed\n" );
383     caps = GetDeviceCaps( hdcMetafile, TECHNOLOGY );
384     ok( caps == DT_RASDISPLAY, "wrong caps %u\n", caps );
385     caps = GetDeviceCaps( hNewDC, TECHNOLOGY );
386     ok( caps == DT_RASDISPLAY, "wrong caps %u\n", caps );
387     DeleteDC( hNewDC );
388     DeleteEnhMetaFile( CloseEnhMetaFile( hdcMetafile ));
389     ReleaseDC( 0, hdc );
390
391     hdcMetafile = CreateMetaFileA(NULL);
392     ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
393     hNewDC = CreateCompatibleDC( hdcMetafile );
394     ok(hNewDC == NULL, "CreateCompatibleDC succeeded\n");
395     caps = GetDeviceCaps( hdcMetafile, TECHNOLOGY );
396     ok( caps == DT_METAFILE, "wrong caps %u\n", caps );
397     test_device_caps( hdcMetafile, screen_dc, "metafile dc" );
398     DeleteMetaFile( CloseMetaFile( hdcMetafile ));
399
400     DeleteObject( bitmap );
401     ReleaseDC( 0, screen_dc );
402 }
403
404 static void test_DC_bitmap(void)
405 {
406     HDC hdc, hdcmem;
407     DWORD bits[64];
408     HBITMAP hbmp, oldhbmp;
409     COLORREF col;
410     int i, bitspixel;
411
412     /* fill bitmap data with b&w pattern */
413     for( i = 0; i < 64; i++) bits[i] = i & 1 ? 0 : 0xffffff;
414
415     hdc = GetDC(0);
416     ok( hdc != NULL, "CreateDC rets %p\n", hdc);
417     bitspixel = GetDeviceCaps( hdc, BITSPIXEL);
418     /* create a memory dc */
419     hdcmem = CreateCompatibleDC( hdc);
420     ok( hdcmem != NULL, "CreateCompatibleDC rets %p\n", hdcmem);
421     /* tests */
422     /* test monochrome bitmap: should always work */
423     hbmp = CreateBitmap(32, 32, 1, 1, bits);
424     ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
425     oldhbmp = SelectObject( hdcmem, hbmp);
426     ok( oldhbmp != NULL, "SelectObject returned NULL\n" ); /* a memdc always has a bitmap selected */
427     col = GetPixel( hdcmem, 0, 0);
428     ok( col == 0xffffff, "GetPixel returned %08x, expected 00ffffff\n", col);
429     col = GetPixel( hdcmem, 1, 1);
430     ok( col == 0x000000, "GetPixel returned %08x, expected 00000000\n", col);
431     col = GetPixel( hdcmem, 100, 1);
432     ok( col == CLR_INVALID, "GetPixel returned %08x, expected ffffffff\n", col);
433     SelectObject( hdcmem, oldhbmp);
434     DeleteObject( hbmp);
435
436     /* test with 2 bits color depth, not likely to succeed */
437     hbmp = CreateBitmap(16, 16, 1, 2, bits);
438     ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
439     oldhbmp = SelectObject( hdcmem, hbmp);
440     if( bitspixel != 2)
441         ok( !oldhbmp, "SelectObject of a bitmap with 2 bits/pixel should return  NULL\n");
442     if( oldhbmp) SelectObject( hdcmem, oldhbmp);
443     DeleteObject( hbmp);
444
445     /* test with 16 bits color depth, might succeed */
446     hbmp = CreateBitmap(6, 6, 1, 16, bits);
447     ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
448     oldhbmp = SelectObject( hdcmem, hbmp);
449     if( bitspixel == 16) {
450         ok( oldhbmp != NULL, "SelectObject returned NULL\n" );
451         col = GetPixel( hdcmem, 0, 0);
452         ok( col == 0xffffff,
453             "GetPixel of a bitmap with 16 bits/pixel returned %08x, expected 00ffffff\n", col);
454         col = GetPixel( hdcmem, 1, 1);
455         ok( col == 0x000000,
456             "GetPixel of a bitmap with 16 bits/pixel returned returned %08x, expected 00000000\n", col);
457     }
458     if( oldhbmp) SelectObject( hdcmem, oldhbmp);
459     DeleteObject( hbmp);
460
461     /* test with 32 bits color depth, probably succeed */
462     hbmp = CreateBitmap(4, 4, 1, 32, bits);
463     ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
464     oldhbmp = SelectObject( hdcmem, hbmp);
465     if( bitspixel == 32) {
466         ok( oldhbmp != NULL, "SelectObject returned NULL\n" );
467         col = GetPixel( hdcmem, 0, 0);
468         ok( col == 0xffffff,
469             "GetPixel of a bitmap with 32 bits/pixel returned %08x, expected 00ffffff\n", col);
470         col = GetPixel( hdcmem, 1, 1);
471         ok( col == 0x000000,
472             "GetPixel of a bitmap with 32 bits/pixel returned returned %08x, expected 00000000\n", col);
473     }
474     if( oldhbmp) SelectObject( hdcmem, oldhbmp);
475     DeleteObject( hbmp);
476     ReleaseDC( 0, hdc );
477 }
478
479 static void test_DeleteDC(void)
480 {
481     HWND hwnd;
482     HDC hdc, hdc_test;
483     WNDCLASSEX cls;
484     int ret;
485
486     /* window DC */
487     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
488                            0, 0, 0, NULL);
489     ok(hwnd != 0, "CreateWindowExA failed\n");
490
491     hdc = GetDC(hwnd);
492     ok(hdc != 0, "GetDC failed\n");
493     ret = GetObjectType(hdc);
494     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
495     ret = DeleteDC(hdc);
496     ok(ret, "DeleteDC failed\n");
497     ret = GetObjectType(hdc);
498     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
499
500     hdc = GetWindowDC(hwnd);
501     ok(hdc != 0, "GetDC failed\n");
502     ret = GetObjectType(hdc);
503     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
504     ret = DeleteDC(hdc);
505     ok(ret, "DeleteDC failed\n");
506     ret = GetObjectType(hdc);
507     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
508
509     DestroyWindow(hwnd);
510
511     /* desktop window DC */
512     hwnd = GetDesktopWindow();
513     ok(hwnd != 0, "GetDesktopWindow failed\n");
514
515     hdc = GetDC(hwnd);
516     ok(hdc != 0, "GetDC failed\n");
517     ret = GetObjectType(hdc);
518     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
519     ret = DeleteDC(hdc);
520     ok(ret, "DeleteDC failed\n");
521     ret = GetObjectType(hdc);
522     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
523
524     hdc = GetWindowDC(hwnd);
525     ok(hdc != 0, "GetDC failed\n");
526     ret = GetObjectType(hdc);
527     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
528     ret = DeleteDC(hdc);
529     ok(ret, "DeleteDC failed\n");
530     ret = GetObjectType(hdc);
531     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
532
533     /* CS_CLASSDC */
534     memset(&cls, 0, sizeof(cls));
535     cls.cbSize = sizeof(cls);
536     cls.style = CS_CLASSDC;
537     cls.hInstance = GetModuleHandle(0);
538     cls.lpszClassName = "Wine class DC";
539     cls.lpfnWndProc = DefWindowProcA;
540     ret = RegisterClassExA(&cls);
541     ok(ret, "RegisterClassExA failed\n");
542
543     hwnd = CreateWindowExA(0, "Wine class DC", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
544                            0, 0, 0, NULL);
545     ok(hwnd != 0, "CreateWindowExA failed\n");
546
547     hdc = GetDC(hwnd);
548     ok(hdc != 0, "GetDC failed\n");
549     ret = GetObjectType(hdc);
550     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
551     ret = DeleteDC(hdc);
552     ok(ret, "DeleteDC failed\n");
553     ret = GetObjectType(hdc);
554     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
555     ret = ReleaseDC(hwnd, hdc);
556     ok(ret, "ReleaseDC failed\n");
557     ret = GetObjectType(hdc);
558     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
559
560     hdc_test = hdc;
561
562     hdc = GetWindowDC(hwnd);
563     ok(hdc != 0, "GetDC failed\n");
564     ret = GetObjectType(hdc);
565     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
566     ret = DeleteDC(hdc);
567     ok(ret, "DeleteDC failed\n");
568     ret = GetObjectType(hdc);
569     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
570
571     DestroyWindow(hwnd);
572
573     ret = GetObjectType(hdc_test);
574     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
575
576     ret = UnregisterClassA("Wine class DC", GetModuleHandle(NULL));
577     ok(ret, "UnregisterClassA failed\n");
578
579     ret = GetObjectType(hdc_test);
580 todo_wine
581     ok(!ret, "GetObjectType should fail for a deleted DC\n");
582
583     /* CS_OWNDC */
584     memset(&cls, 0, sizeof(cls));
585     cls.cbSize = sizeof(cls);
586     cls.style = CS_OWNDC;
587     cls.hInstance = GetModuleHandle(0);
588     cls.lpszClassName = "Wine own DC";
589     cls.lpfnWndProc = DefWindowProcA;
590     ret = RegisterClassExA(&cls);
591     ok(ret, "RegisterClassExA failed\n");
592
593     hwnd = CreateWindowExA(0, "Wine own DC", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
594                            0, 0, 0, NULL);
595     ok(hwnd != 0, "CreateWindowExA failed\n");
596
597     hdc = GetDC(hwnd);
598     ok(hdc != 0, "GetDC failed\n");
599     ret = GetObjectType(hdc);
600     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
601     ret = DeleteDC(hdc);
602     ok(ret, "DeleteDC failed\n");
603     ret = GetObjectType(hdc);
604     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
605     ret = ReleaseDC(hwnd, hdc);
606     ok(ret, "ReleaseDC failed\n");
607     ret = GetObjectType(hdc);
608     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
609
610     hdc = GetWindowDC(hwnd);
611     ok(hdc != 0, "GetDC failed\n");
612     ret = GetObjectType(hdc);
613     ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
614     ret = DeleteDC(hdc);
615     ok(ret, "DeleteDC failed\n");
616     ret = GetObjectType(hdc);
617     ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
618
619     DestroyWindow(hwnd);
620
621     ret = UnregisterClassA("Wine own DC", GetModuleHandle(NULL));
622     ok(ret, "UnregisterClassA failed\n");
623 }
624
625 static void test_boundsrect(void)
626 {
627     HDC hdc;
628     HBITMAP bitmap;
629     RECT rect, expect, set_rect;
630     UINT ret;
631
632     hdc = CreateCompatibleDC(0);
633     ok(hdc != NULL, "CreateCompatibleDC failed\n");
634     bitmap = CreateCompatibleBitmap( hdc, 200, 200 );
635     SelectObject( hdc, bitmap );
636
637     ret = GetBoundsRect(hdc, NULL, 0);
638     ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
639
640     ret = GetBoundsRect(hdc, NULL, ~0U);
641     ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
642
643     /* Test parameter handling order. */
644     SetRect(&set_rect, 10, 20, 40, 50);
645     ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
646     ok(ret & DCB_RESET,
647        "Expected return flag DCB_RESET to be set, got %u\n", ret);
648
649     ret = GetBoundsRect(hdc, NULL, DCB_RESET);
650     ok(ret == 0,
651        "Expected GetBoundsRect to return 0, got %u\n", ret);
652
653     ret = GetBoundsRect(hdc, &rect, 0);
654     ok(ret == DCB_RESET,
655        "Expected GetBoundsRect to return DCB_RESET, got %u\n", ret);
656     SetRect(&expect, 0, 0, 0, 0);
657     ok(EqualRect(&rect, &expect) ||
658        broken(EqualRect(&rect, &set_rect)), /* nt4 sp1-5 */
659        "Expected output rectangle (0,0)-(0,0), got (%d,%d)-(%d,%d)\n",
660        rect.left, rect.top, rect.right, rect.bottom);
661
662     ret = GetBoundsRect(NULL, NULL, 0);
663     ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
664
665     ret = GetBoundsRect(NULL, NULL, ~0U);
666     ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
667
668     ret = SetBoundsRect(NULL, NULL, 0);
669     ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret);
670
671     ret = SetBoundsRect(NULL, NULL, ~0U);
672     ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret);
673
674     SetRect(&set_rect, 10, 20, 40, 50);
675     ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
676     ok(ret == (DCB_RESET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
677
678     ret = GetBoundsRect(hdc, &rect, 0);
679     ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
680     SetRect(&expect, 10, 20, 40, 50);
681     ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
682        rect.left, rect.top, rect.right, rect.bottom);
683
684     SetMapMode( hdc, MM_ANISOTROPIC );
685     SetViewportExtEx( hdc, 2, 2, NULL );
686     ret = GetBoundsRect(hdc, &rect, 0);
687     ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
688     SetRect(&expect, 5, 10, 20, 25);
689     ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
690        rect.left, rect.top, rect.right, rect.bottom);
691
692     SetViewportOrgEx( hdc, 20, 30, NULL );
693     ret = GetBoundsRect(hdc, &rect, 0);
694     ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
695     SetRect(&expect, -5, -5, 10, 10);
696     ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
697        rect.left, rect.top, rect.right, rect.bottom);
698
699     SetRect(&set_rect, 10, 20, 40, 50);
700     ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
701     ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
702
703     ret = GetBoundsRect(hdc, &rect, 0);
704     ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
705     SetRect(&expect, 10, 20, 40, 50);
706     ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
707        rect.left, rect.top, rect.right, rect.bottom);
708
709     SetMapMode( hdc, MM_TEXT );
710     SetViewportOrgEx( hdc, 0, 0, NULL );
711     ret = GetBoundsRect(hdc, &rect, 0);
712     ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
713     SetRect(&expect, 40, 70, 100, 130);
714     ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
715        rect.left, rect.top, rect.right, rect.bottom);
716
717     if (pSetLayout)
718     {
719         pSetLayout( hdc, LAYOUT_RTL );
720         ret = GetBoundsRect(hdc, &rect, 0);
721         ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
722         SetRect(&expect, 159, 70, 99, 130);
723         ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
724            rect.left, rect.top, rect.right, rect.bottom);
725         SetRect(&set_rect, 50, 25, 30, 35);
726         ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
727         ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
728         ret = GetBoundsRect(hdc, &rect, 0);
729         ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
730         SetRect(&expect, 50, 25, 30, 35);
731         ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
732            rect.left, rect.top, rect.right, rect.bottom);
733
734         pSetLayout( hdc, LAYOUT_LTR );
735         ret = GetBoundsRect(hdc, &rect, 0);
736         ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
737         SetRect(&expect, 149, 25, 169, 35);
738         ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
739            rect.left, rect.top, rect.right, rect.bottom);
740     }
741
742     /* empty rect resets, except on nt4 */
743     SetRect(&expect, 20, 20, 10, 10);
744     ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
745     ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
746     ret = GetBoundsRect(hdc, &rect, 0);
747     ok(ret == DCB_RESET || broken(ret == DCB_SET)  /* nt4 */,
748        "GetBoundsRect returned %x\n", ret);
749     if (ret == DCB_RESET)
750     {
751         SetRect(&expect, 0, 0, 0, 0);
752         ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
753            rect.left, rect.top, rect.right, rect.bottom);
754
755         SetRect(&expect, 20, 20, 20, 20);
756         ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
757         ok(ret == (DCB_RESET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
758         ret = GetBoundsRect(hdc, &rect, 0);
759         ok(ret == DCB_RESET, "GetBoundsRect returned %x\n", ret);
760         SetRect(&expect, 0, 0, 0, 0);
761         ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
762            rect.left, rect.top, rect.right, rect.bottom);
763     }
764
765     DeleteDC( hdc );
766     DeleteObject( bitmap );
767 }
768
769 static void test_desktop_colorres(void)
770 {
771     HDC hdc = GetDC(NULL);
772     int bitspixel, colorres;
773
774     bitspixel = GetDeviceCaps(hdc, BITSPIXEL);
775     ok(bitspixel != 0, "Expected to get valid BITSPIXEL capability value\n");
776
777     colorres = GetDeviceCaps(hdc, COLORRES);
778     ok(colorres != 0 ||
779        broken(colorres == 0), /* Win9x */
780        "Expected to get valid COLORRES capability value\n");
781
782     if (colorres)
783     {
784         switch (bitspixel)
785         {
786         case 8:
787             ok(colorres == 18,
788                "Expected COLORRES to be 18, got %d\n", colorres);
789             break;
790         case 16:
791             ok(colorres == 16,
792                "Expected COLORRES to be 16, got %d\n", colorres);
793             break;
794         case 24:
795         case 32:
796             ok(colorres == 24,
797                "Expected COLORRES to be 24, got %d\n", bitspixel);
798             break;
799         default:
800             ok(0, "Got unknown BITSPIXEL %d with COLORRES %d\n", bitspixel, colorres);
801             break;
802         }
803     }
804
805     ReleaseDC(NULL, hdc);
806 }
807
808 static void test_gamma(void)
809 {
810     BOOL ret;
811     HDC hdc = GetDC(NULL);
812     WORD oldramp[3][256], ramp[3][256];
813     INT i;
814
815     ret = GetDeviceGammaRamp(hdc, &oldramp);
816     if (!ret)
817     {
818         win_skip("GetDeviceGammaRamp failed, skipping tests\n");
819         goto done;
820     }
821
822     /* try to set back old ramp */
823     ret = SetDeviceGammaRamp(hdc, &oldramp);
824     if (!ret)
825     {
826         win_skip("SetDeviceGammaRamp failed, skipping tests\n");
827         goto done;
828     }
829
830     memcpy(ramp, oldramp, sizeof(ramp));
831
832     /* set one color ramp to zeros */
833     memset(ramp[0], 0, sizeof(ramp[0]));
834     ret = SetDeviceGammaRamp(hdc, &ramp);
835     ok(!ret, "SetDeviceGammaRamp succeeded\n");
836
837     /* set one color ramp to a flat straight rising line */
838     for (i = 0; i < 256; i++) ramp[0][i] = i;
839     ret = SetDeviceGammaRamp(hdc, &ramp);
840     todo_wine ok(!ret, "SetDeviceGammaRamp succeeded\n");
841
842     /* set one color ramp to a steep straight rising line */
843     for (i = 0; i < 256; i++) ramp[0][i] = i * 256;
844     ret = SetDeviceGammaRamp(hdc, &ramp);
845     ok(ret, "SetDeviceGammaRamp failed\n");
846
847     /* try a bright gamma ramp */
848     ramp[0][0] = 0;
849     ramp[0][1] = 0x7FFF;
850     for (i = 2; i < 256; i++) ramp[0][i] = 0xFFFF;
851     ret = SetDeviceGammaRamp(hdc, &ramp);
852     ok(!ret, "SetDeviceGammaRamp succeeded\n");
853
854     /* try ramps which are not uniform */
855     ramp[0][0] = 0;
856     for (i = 1; i < 256; i++) ramp[0][i] = ramp[0][i - 1] + 512;
857     ret = SetDeviceGammaRamp(hdc, &ramp);
858     ok(ret, "SetDeviceGammaRamp failed\n");
859     ramp[0][0] = 0;
860     for (i = 2; i < 256; i+=2)
861     {
862         ramp[0][i - 1] = ramp[0][i - 2];
863         ramp[0][i] = ramp[0][i - 2] + 512;
864     }
865     ret = SetDeviceGammaRamp(hdc, &ramp);
866     ok(ret, "SetDeviceGammaRamp failed\n");
867
868     /* cleanup: set old ramp again */
869     ret = SetDeviceGammaRamp(hdc, &oldramp);
870     ok(ret, "SetDeviceGammaRamp failed\n");
871
872 done:
873     ReleaseDC(NULL, hdc);
874 }
875
876 static HDC create_printer_dc(void)
877 {
878     char buffer[260];
879     DWORD len;
880     PRINTER_INFO_2A *pbuf = NULL;
881     DRIVER_INFO_3A *dbuf = NULL;
882     HANDLE hprn = 0;
883     HDC hdc = 0;
884     HMODULE winspool = LoadLibraryA( "winspool.drv" );
885     BOOL (WINAPI *pOpenPrinterA)(LPSTR, HANDLE *, LPPRINTER_DEFAULTSA);
886     BOOL (WINAPI *pGetDefaultPrinterA)(LPSTR, LPDWORD);
887     BOOL (WINAPI *pGetPrinterA)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD);
888     BOOL (WINAPI *pGetPrinterDriverA)(HANDLE, LPSTR, DWORD, LPBYTE, DWORD, LPDWORD);
889     BOOL (WINAPI *pClosePrinter)(HANDLE);
890
891     pGetDefaultPrinterA = (void *)GetProcAddress( winspool, "GetDefaultPrinterA" );
892     pOpenPrinterA = (void *)GetProcAddress( winspool, "OpenPrinterA" );
893     pGetPrinterA = (void *)GetProcAddress( winspool, "GetPrinterA" );
894     pGetPrinterDriverA = (void *)GetProcAddress( winspool, "GetPrinterDriverA" );
895     pClosePrinter = (void *)GetProcAddress( winspool, "ClosePrinter" );
896
897     if (!pGetDefaultPrinterA || !pOpenPrinterA || !pGetPrinterA || !pGetPrinterDriverA || !pClosePrinter)
898         goto done;
899
900     len = sizeof(buffer);
901     if (!pGetDefaultPrinterA( buffer, &len )) goto done;
902     if (!pOpenPrinterA( buffer, &hprn, NULL )) goto done;
903
904     pGetPrinterA( hprn, 2, NULL, 0, &len );
905     pbuf = HeapAlloc( GetProcessHeap(), 0, len );
906     if (!pGetPrinterA( hprn, 2, (LPBYTE)pbuf, len, &len )) goto done;
907
908     pGetPrinterDriverA( hprn, NULL, 3, NULL, 0, &len );
909     dbuf = HeapAlloc( GetProcessHeap(), 0, len );
910     if (!pGetPrinterDriverA( hprn, NULL, 3, (LPBYTE)dbuf, len, &len )) goto done;
911
912     hdc = CreateDCA( dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, pbuf->pDevMode );
913     trace( "hdc %p for driver '%s' printer '%s' port '%s'\n", hdc,
914            dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName );
915 done:
916     HeapFree( GetProcessHeap(), 0, dbuf );
917     HeapFree( GetProcessHeap(), 0, pbuf );
918     if (hprn) pClosePrinter( hprn );
919     if (winspool) FreeLibrary( winspool );
920     if (!hdc) skip( "could not create a DC for the default printer\n" );
921     return hdc;
922 }
923
924 static void test_printer_dc(void)
925 {
926     HDC memdc, display_memdc;
927     HBITMAP orig, bmp;
928     DWORD ret;
929     HDC hdc = create_printer_dc();
930
931     if (!hdc) return;
932
933     memdc = CreateCompatibleDC( hdc );
934     display_memdc = CreateCompatibleDC( 0 );
935
936     ok( memdc != NULL, "CreateCompatibleDC failed for printer\n" );
937     ok( display_memdc != NULL, "CreateCompatibleDC failed for screen\n" );
938
939     ret = GetDeviceCaps( hdc, TECHNOLOGY );
940     ok( ret == DT_RASPRINTER, "wrong type %u\n", ret );
941
942     ret = GetDeviceCaps( memdc, TECHNOLOGY );
943     ok( ret == DT_RASPRINTER, "wrong type %u\n", ret );
944
945     ret = GetDeviceCaps( display_memdc, TECHNOLOGY );
946     ok( ret == DT_RASDISPLAY, "wrong type %u\n", ret );
947
948     test_device_caps( memdc, hdc, "printer dc" );
949
950     bmp = CreateBitmap( 100, 100, 1, GetDeviceCaps( hdc, BITSPIXEL ), NULL );
951     orig = SelectObject( memdc, bmp );
952     ok( orig != NULL, "SelectObject failed\n" );
953     ok( BitBlt( hdc, 10, 10, 20, 20, memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
954
955     ok( !SelectObject( display_memdc, bmp ), "SelectObject succeeded\n" );
956     SelectObject( memdc, orig );
957     DeleteObject( bmp );
958
959     bmp = CreateBitmap( 100, 100, 1, 1, NULL );
960     orig = SelectObject( display_memdc, bmp );
961     ok( orig != NULL, "SelectObject failed\n" );
962     ok( !SelectObject( memdc, bmp ), "SelectObject succeeded\n" );
963     ok( BitBlt( hdc, 10, 10, 20, 20, display_memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
964     ok( BitBlt( memdc, 10, 10, 20, 20, display_memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
965     ok( BitBlt( display_memdc, 10, 10, 20, 20, memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
966
967     ret = GetPixel( hdc, 0, 0 );
968     ok( ret == CLR_INVALID, "wrong pixel value %x\n", ret );
969
970     DeleteDC( memdc );
971     DeleteDC( display_memdc );
972     DeleteDC( hdc );
973     DeleteObject( bmp );
974 }
975
976 START_TEST(dc)
977 {
978     pSetLayout = (void *)GetProcAddress( GetModuleHandle("gdi32.dll"), "SetLayout");
979     test_savedc();
980     test_savedc_2();
981     test_GdiConvertToDevmodeW();
982     test_CreateCompatibleDC();
983     test_DC_bitmap();
984     test_DeleteDC();
985     test_boundsrect();
986     test_desktop_colorres();
987     test_gamma();
988     test_printer_dc();
989 }