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