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