gdi32: Use NtGdiGetDeviceCaps for GetDeviceCaps implementation.
[wine.git] / dlls / gdi32 / tests / dc.c
blob2e005f23f3ca164f153aa37bd0f4dafdfc8b6376
1 /*
2 * Unit tests for dc functions
4 * Copyright (c) 2005 Huw Davies
5 * Copyright (c) 2005,2016 Dmitry Timoshkov
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.
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.
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
22 #define NONAMELESSSTRUCT
23 #define NONAMELESSUNION
25 #include <assert.h>
26 #include <stdio.h>
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"
35 #ifndef LAYOUT_LTR
36 #define LAYOUT_LTR 0
37 #endif
39 static void test_dc_values(void)
41 HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
42 COLORREF color;
43 int extra, attr;
45 ok( hdc != NULL, "CreateDC failed\n" );
46 color = SetBkColor( hdc, 0x12345678 );
47 ok( color == 0xffffff, "initial color %08x\n", color );
48 color = GetBkColor( hdc );
49 ok( color == 0x12345678, "wrong color %08x\n", color );
50 color = SetBkColor( hdc, 0xffffffff );
51 ok( color == 0x12345678, "wrong color %08x\n", color );
52 color = GetBkColor( hdc );
53 ok( color == 0xffffffff, "wrong color %08x\n", color );
54 color = SetBkColor( hdc, 0 );
55 ok( color == 0xffffffff, "wrong color %08x\n", color );
56 color = GetBkColor( hdc );
57 ok( color == 0, "wrong color %08x\n", color );
59 color = SetTextColor( hdc, 0xffeeddcc );
60 ok( color == 0, "initial color %08x\n", color );
61 color = GetTextColor( hdc );
62 ok( color == 0xffeeddcc, "wrong color %08x\n", color );
63 color = SetTextColor( hdc, 0xffffffff );
64 ok( color == 0xffeeddcc, "wrong color %08x\n", color );
65 color = GetTextColor( hdc );
66 ok( color == 0xffffffff, "wrong color %08x\n", color );
67 color = SetTextColor( hdc, 0 );
68 ok( color == 0xffffffff, "wrong color %08x\n", color );
69 color = GetTextColor( hdc );
70 ok( color == 0, "wrong color %08x\n", color );
72 extra = GetTextCharacterExtra( hdc );
73 ok( extra == 0, "initial extra %d\n", extra );
74 SetTextCharacterExtra( hdc, 123 );
75 extra = GetTextCharacterExtra( hdc );
76 ok( extra == 123, "initial extra %d\n", extra );
77 SetMapMode( hdc, MM_LOMETRIC );
78 extra = GetTextCharacterExtra( hdc );
79 ok( extra == 123, "initial extra %d\n", extra );
80 SetMapMode( hdc, MM_TEXT );
81 extra = GetTextCharacterExtra( hdc );
82 ok( extra == 123, "initial extra %d\n", extra );
84 SetLastError(0xdeadbeef);
85 attr = SetBkMode(ULongToHandle(0xdeadbeef), OPAQUE);
86 ok(!attr, "attr = %x\n", attr);
87 ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError() = %u\n", GetLastError());
89 attr = GetBkColor(ULongToHandle(0xdeadbeef));
90 ok(attr == CLR_INVALID, "attr = %x\n", attr);
92 SetLastError(0xdeadbeef);
93 attr = GetDeviceCaps(ULongToHandle(0xdeadbeef), TECHNOLOGY);
94 ok(!attr, "GetDeviceCaps rets %d\n", attr);
95 ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError() = %u\n", GetLastError());
97 DeleteDC( hdc );
100 static void test_savedc_2(void)
102 char buffer[100];
103 RGNDATA *rgndata = (RGNDATA *)buffer;
104 HWND hwnd;
105 HDC hdc;
106 HRGN hrgn;
107 RECT rc, rc_clip;
108 int ret;
110 hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,
111 0, 0, 0, NULL);
112 assert(hwnd != 0);
113 ShowWindow(hwnd, SW_SHOW);
114 UpdateWindow(hwnd);
116 hrgn = CreateRectRgn(0, 0, 0, 0);
117 assert(hrgn != 0);
119 hdc = GetDC(hwnd);
120 ok(hdc != NULL, "GetDC failed\n");
122 ret = GetClipBox(hdc, &rc_clip);
123 /* all versions of Windows return SIMPLEREGION despite returning an empty region */
124 todo_wine ok(ret == NULLREGION || broken(ret == SIMPLEREGION), "wrong region type %d\n", ret);
125 ret = GetClipRgn(hdc, hrgn);
126 ok(ret == 0, "GetClipRgn returned %d instead of 0\n", ret);
127 ret = GetRgnBox(hrgn, &rc);
128 ok(ret == NULLREGION, "GetRgnBox returned %d %s instead of NULLREGION\n",
129 ret, wine_dbgstr_rect(&rc));
130 ret = GetRegionData(hrgn, sizeof(buffer), rgndata);
131 ok(ret == sizeof(RGNDATAHEADER), "got %u\n", ret);
132 ok(!rgndata->rdh.nCount, "got %u rectangles\n", rgndata->rdh.nCount);
133 SetRect(&rc, 0, 0, 100, 100);
134 ok(EqualRect(&rc, &rc_clip), "rects are not equal: %s - %s\n", wine_dbgstr_rect(&rc),
135 wine_dbgstr_rect(&rc_clip));
137 ret = SaveDC(hdc);
138 ok(ret == 1, "ret = %d\n", ret);
140 ret = IntersectClipRect(hdc, 0, 0, 50, 50);
141 /* all versions of Windows return COMPLEXREGION despite the region comprising one rectangle */
142 ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION), "wrong region type %d\n", ret);
143 ret = GetClipRgn(hdc, hrgn);
144 ok(ret == 1, "GetClipRgn returned %d instead of 1\n", ret);
145 ret = GetRegionData(hrgn, sizeof(buffer), rgndata);
146 ok(ret == sizeof(RGNDATAHEADER) + sizeof(RECT), "got %u\n", ret);
147 ok(rgndata->rdh.nCount == 1, "got %u rectangles\n", rgndata->rdh.nCount);
148 SetRect(&rc, 0, 0, 50, 50);
149 ok(EqualRect((RECT *)rgndata->Buffer, &rc), "got rect %s\n", wine_dbgstr_rect((RECT *)rgndata->Buffer));
151 ret = GetClipBox(hdc, &rc_clip);
152 ok(ret == SIMPLEREGION, "wrong region type %d\n", ret);
153 SetRect(&rc, 0, 0, 50, 50);
154 ok(EqualRect(&rc, &rc_clip), "rects are not equal: %s - %s\n", wine_dbgstr_rect(&rc),
155 wine_dbgstr_rect(&rc_clip));
157 ret = RestoreDC(hdc, 1);
158 ok(ret, "ret = %d\n", ret);
160 ret = GetClipBox(hdc, &rc_clip);
161 ok(ret == SIMPLEREGION, "wrong region type %d\n", ret);
162 SetRect(&rc, 0, 0, 100, 100);
163 ok(EqualRect(&rc, &rc_clip), "rects are not equal: %s - %s\n", wine_dbgstr_rect(&rc),
164 wine_dbgstr_rect(&rc_clip));
166 DeleteObject(hrgn);
167 ReleaseDC(hwnd, hdc);
168 DestroyWindow(hwnd);
171 static void test_savedc(void)
173 HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
174 int ret;
176 ok(hdc != NULL, "CreateDC rets %p\n", hdc);
178 ret = SaveDC(hdc);
179 ok(ret == 1, "ret = %d\n", ret);
180 ret = SaveDC(hdc);
181 ok(ret == 2, "ret = %d\n", ret);
182 ret = SaveDC(hdc);
183 ok(ret == 3, "ret = %d\n", ret);
184 ret = RestoreDC(hdc, -1);
185 ok(ret, "ret = %d\n", ret);
186 ret = SaveDC(hdc);
187 ok(ret == 3, "ret = %d\n", ret);
188 ret = RestoreDC(hdc, 1);
189 ok(ret, "ret = %d\n", ret);
190 ret = SaveDC(hdc);
191 ok(ret == 1, "ret = %d\n", ret);
192 ret = SaveDC(hdc);
193 ok(ret == 2, "ret = %d\n", ret);
194 ret = SaveDC(hdc);
195 ok(ret == 3, "ret = %d\n", ret);
196 ret = RestoreDC(hdc, -2);
197 ok(ret, "ret = %d\n", ret);
198 ret = SaveDC(hdc);
199 ok(ret == 2, "ret = %d\n", ret);
200 ret = RestoreDC(hdc, -2);
201 ok(ret, "ret = %d\n", ret);
202 ret = SaveDC(hdc);
203 ok(ret == 1, "ret = %d\n", ret);
204 ret = SaveDC(hdc);
205 ok(ret == 2, "ret = %d\n", ret);
206 ret = RestoreDC(hdc, -4);
207 ok(!ret, "ret = %d\n", ret);
208 ret = RestoreDC(hdc, 3);
209 ok(!ret, "ret = %d\n", ret);
211 /* Under Win9x the following RestoreDC call succeeds and clears the save stack. */
212 ret = RestoreDC(hdc, -3);
213 ok(!ret ||
214 broken(ret), /* Win9x */
215 "ret = %d\n", ret);
217 /* Trying to clear an empty save stack fails. */
218 ret = RestoreDC(hdc, -3);
219 ok(!ret, "ret = %d\n", ret);
221 ret = SaveDC(hdc);
222 ok(ret == 3 ||
223 broken(ret == 1), /* Win9x */
224 "ret = %d\n", ret);
226 /* Under Win9x the following RestoreDC call succeeds and clears the save stack. */
227 ret = RestoreDC(hdc, 0);
228 ok(!ret ||
229 broken(ret), /* Win9x */
230 "ret = %d\n", ret);
232 /* Trying to clear an empty save stack fails. */
233 ret = RestoreDC(hdc, 0);
234 ok(!ret, "ret = %d\n", ret);
236 ret = RestoreDC(hdc, 1);
237 ok(ret ||
238 broken(!ret), /* Win9x */
239 "ret = %d\n", ret);
241 DeleteDC(hdc);
243 SetLastError(0xdeadbeef);
244 ret = SaveDC(ULongToHandle(0xdeadbeef));
245 ok(!ret, "SaveDC returned %u\n", ret);
246 ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError() = %u\n", GetLastError());
249 static void test_GdiConvertToDevmodeW(void)
251 DEVMODEW * (WINAPI *pGdiConvertToDevmodeW)(const DEVMODEA *);
252 DEVMODEA dmA;
253 DEVMODEW *dmW;
254 BOOL ret;
256 pGdiConvertToDevmodeW = (void *)GetProcAddress(GetModuleHandleA("gdi32.dll"), "GdiConvertToDevmodeW");
257 if (!pGdiConvertToDevmodeW)
259 win_skip("GdiConvertToDevmodeW is not available on this platform\n");
260 return;
263 memset(&dmA, 0, sizeof(dmA));
264 dmA.dmSize = sizeof(dmA);
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);
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);
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);
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);
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);
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());
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);
310 static void test_device_caps( HDC hdc, HDC ref_dc, const char *descr, int scale )
312 static const int caps[] =
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
354 unsigned int i;
355 WORD ramp[3][256];
356 BOOL ret;
357 RECT rect;
358 UINT type;
360 if (GetObjectType( hdc ) == OBJ_METADC)
362 for (i = 0; i < ARRAY_SIZE(caps); 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] ) );
367 type = GetClipBox( hdc, &rect );
368 ok( type == ERROR, "GetClipBox returned %d on %s\n", type, descr );
370 SetBoundsRect( hdc, NULL, DCB_RESET | DCB_ENABLE );
371 SetMapMode( hdc, MM_TEXT );
372 Rectangle( hdc, 2, 2, 5, 5 );
373 type = GetBoundsRect( hdc, &rect, DCB_RESET );
374 ok( !type, "GetBoundsRect succeeded on %s\n", descr );
375 type = SetBoundsRect( hdc, &rect, DCB_RESET | DCB_ENABLE );
376 ok( !type, "SetBoundsRect succeeded on %s\n", descr );
378 else
380 for (i = 0; i < ARRAY_SIZE(caps); i++)
382 INT precision = 0;
383 INT hdc_caps = GetDeviceCaps( hdc, caps[i] );
385 switch (caps[i])
387 case HORZSIZE:
388 case VERTSIZE:
389 hdc_caps /= scale;
390 precision = 1;
391 break;
392 case LOGPIXELSX:
393 case LOGPIXELSY:
394 hdc_caps *= scale;
395 break;
396 case VREFRESH:
397 if (GetDeviceCaps( hdc, TECHNOLOGY ) == DT_RASDISPLAY)
398 ok( hdc_caps > 0, "expected a positive value on %s, got %d\n", descr, hdc_caps );
399 else
400 ok( hdc_caps == 0, "expected 0 on %s, got %d\n", descr, hdc_caps );
401 break;
404 ok( abs(hdc_caps - GetDeviceCaps( ref_dc, caps[i] )) <= precision,
405 "mismatched caps on %s for %u: %u/%u (scale %d)\n", descr, caps[i],
406 hdc_caps, GetDeviceCaps( ref_dc, caps[i] ), scale );
409 type = GetBoundsRect( hdc, &rect, 0 );
410 ok( type == DCB_RESET || broken(type == DCB_SET) /* XP */,
411 "GetBoundsRect returned type %x for %s\n", type, descr );
412 if (type == DCB_RESET)
413 ok( rect.left == 0 && rect.top == 0 && rect.right == 0 && rect.bottom == 0,
414 "GetBoundsRect returned %s type %x for %s\n", wine_dbgstr_rect( &rect ),
415 type, descr );
416 type = SetBoundsRect( hdc, NULL, DCB_RESET | DCB_ENABLE );
417 ok( type == (DCB_RESET | DCB_DISABLE) || broken(type == (DCB_SET | DCB_ENABLE)) /* XP */,
418 "SetBoundsRect returned %x for %s (hdc type %d)\n", type, descr, GetObjectType( hdc ) );
420 SetMapMode( hdc, MM_TEXT );
421 Rectangle( hdc, 2, 2, 4, 4 );
422 type = GetBoundsRect( hdc, &rect, DCB_RESET );
423 todo_wine_if (GetObjectType( hdc ) == OBJ_ENHMETADC || (GetObjectType( hdc ) == OBJ_DC && GetDeviceCaps( hdc, TECHNOLOGY ) == DT_RASPRINTER))
424 ok( rect.left == 2 && rect.top == 2 && rect.right == 4 && rect.bottom == 4 && type == DCB_SET,
425 "GetBoundsRect returned %s type %x for %s\n", wine_dbgstr_rect( &rect ),
426 type, descr );
429 type = GetClipBox( ref_dc, &rect );
430 if (type != COMPLEXREGION && type != ERROR) /* region can be complex on multi-monitor setups */
432 RECT ref_rect;
434 ok( type == SIMPLEREGION, "GetClipBox returned %d on %s\n", type, descr );
435 if (GetDeviceCaps( ref_dc, TECHNOLOGY ) == DT_RASDISPLAY)
437 todo_wine_if (GetSystemMetrics( SM_CXSCREEN ) != GetSystemMetrics( SM_CXVIRTUALSCREEN ))
438 ok( GetDeviceCaps( ref_dc, DESKTOPHORZRES ) == GetSystemMetrics( SM_CXSCREEN ),
439 "Got DESKTOPHORZRES %d on %s, expected %d\n",
440 GetDeviceCaps( ref_dc, DESKTOPHORZRES ), descr, GetSystemMetrics( SM_CXSCREEN ) );
442 todo_wine_if (GetSystemMetrics( SM_CYSCREEN ) != GetSystemMetrics( SM_CYVIRTUALSCREEN ))
443 ok( GetDeviceCaps( ref_dc, DESKTOPVERTRES ) == GetSystemMetrics( SM_CYSCREEN ),
444 "Got DESKTOPVERTRES %d on %s, expected %d\n",
445 GetDeviceCaps( ref_dc, DESKTOPVERTRES ), descr, GetSystemMetrics( SM_CYSCREEN ) );
447 SetRect( &ref_rect, GetSystemMetrics( SM_XVIRTUALSCREEN ), GetSystemMetrics( SM_YVIRTUALSCREEN ),
448 GetSystemMetrics( SM_XVIRTUALSCREEN ) + GetSystemMetrics( SM_CXVIRTUALSCREEN ),
449 GetSystemMetrics( SM_YVIRTUALSCREEN ) + GetSystemMetrics( SM_CYVIRTUALSCREEN ) );
451 else
453 ok( GetDeviceCaps( ref_dc, DESKTOPHORZRES ) == GetDeviceCaps( ref_dc, HORZRES ),
454 "Got DESKTOPHORZRES %d on %s, expected %d\n",
455 GetDeviceCaps( ref_dc, DESKTOPHORZRES ), descr, GetDeviceCaps( ref_dc, HORZRES ));
456 ok( GetDeviceCaps( ref_dc, DESKTOPVERTRES ) == GetDeviceCaps( ref_dc, VERTRES ),
457 "Got DESKTOPVERTRES %d on %s, expected %d\n",
458 GetDeviceCaps( ref_dc, DESKTOPVERTRES ), descr, GetDeviceCaps( ref_dc, VERTRES ));
459 SetRect( &ref_rect, 0, 0, GetDeviceCaps( ref_dc, DESKTOPHORZRES ),
460 GetDeviceCaps( ref_dc, DESKTOPVERTRES ) );
463 todo_wine_if (GetDeviceCaps( ref_dc, TECHNOLOGY ) == DT_RASDISPLAY && GetObjectType( hdc ) != OBJ_ENHMETADC &&
464 (GetSystemMetrics( SM_XVIRTUALSCREEN ) || GetSystemMetrics( SM_YVIRTUALSCREEN )))
465 ok( EqualRect( &rect, &ref_rect ), "GetClipBox returned %s on %s\n",
466 wine_dbgstr_rect( &rect ), descr );
469 SetBoundsRect( ref_dc, NULL, DCB_RESET | DCB_ACCUMULATE );
470 SetMapMode( ref_dc, MM_TEXT );
471 Rectangle( ref_dc, 3, 3, 5, 5 );
472 type = GetBoundsRect( ref_dc, &rect, DCB_RESET );
473 /* it may or may not work on non-memory DCs */
474 ok( (rect.left == 0 && rect.top == 0 && rect.right == 0 && rect.bottom == 0 && type == DCB_RESET) ||
475 (rect.left == 3 && rect.top == 3 && rect.right == 5 && rect.bottom == 5 && type == DCB_SET),
476 "GetBoundsRect returned %s type %x on %s\n", wine_dbgstr_rect( &rect ), type, descr );
478 if (GetObjectType( hdc ) == OBJ_MEMDC)
480 char buffer[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
481 BITMAPINFO *info = (BITMAPINFO *)buffer;
482 HBITMAP dib, old;
484 memset( buffer, 0, sizeof(buffer) );
485 info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
486 info->bmiHeader.biWidth = 16;
487 info->bmiHeader.biHeight = 16;
488 info->bmiHeader.biPlanes = 1;
489 info->bmiHeader.biBitCount = 8;
490 info->bmiHeader.biCompression = BI_RGB;
491 dib = CreateDIBSection( ref_dc, info, DIB_RGB_COLORS, NULL, NULL, 0 );
492 old = SelectObject( hdc, dib );
494 for (i = 0; i < ARRAY_SIZE(caps); i++)
495 ok( GetDeviceCaps( hdc, caps[i] ) == GetDeviceCaps( ref_dc, caps[i] ),
496 "mismatched caps on %s and DIB for %u: %u/%u\n", descr, caps[i],
497 GetDeviceCaps( hdc, caps[i] ), GetDeviceCaps( ref_dc, caps[i] ) );
499 type = GetClipBox( hdc, &rect );
500 ok( type == SIMPLEREGION, "GetClipBox returned %d on memdc for %s\n", type, descr );
501 ok( rect.left == 0 && rect.top == 0 && rect.right == 16 && rect.bottom == 16,
502 "GetClipBox returned %s on memdc for %s\n", wine_dbgstr_rect( &rect ), descr );
504 SetBoundsRect( hdc, NULL, DCB_RESET | DCB_ENABLE );
505 SetMapMode( hdc, MM_TEXT );
506 Rectangle( hdc, 5, 5, 12, 14 );
507 type = GetBoundsRect( hdc, &rect, DCB_RESET );
508 ok( rect.left == 5 && rect.top == 5 && rect.right == 12 && rect.bottom == 14 && type == DCB_SET,
509 "GetBoundsRect returned %s type %x on memdc for %s\n", wine_dbgstr_rect( &rect ),
510 type, descr );
512 SelectObject( hdc, old );
513 DeleteObject( dib );
516 /* Memory DC, metafile DC and enhanced metafile DC support gamma ramp on Win10 1909+. Exclude
517 * these types from tests as they return different results depending on Windows versions */
518 if (GetObjectType( hdc ) != OBJ_MEMDC
519 && GetObjectType( hdc ) != OBJ_METADC
520 && GetObjectType( hdc ) != OBJ_ENHMETADC)
522 SetLastError( 0xdeadbeef );
523 ret = GetDeviceGammaRamp( hdc, &ramp );
524 if (GetObjectType( hdc ) != OBJ_DC || GetDeviceCaps( hdc, TECHNOLOGY ) == DT_RASPRINTER)
526 ok( !ret, "GetDeviceGammaRamp succeeded on %s (type %d)\n", descr, GetObjectType( hdc ) );
527 ok( GetLastError() == ERROR_INVALID_PARAMETER
528 || broken(GetLastError() == 0xdeadbeef) /* nt4 */
529 || broken(GetLastError() == NO_ERROR), /* Printer DC on Win10 1909+ */
530 "wrong error %u on %s\n", GetLastError(), descr );
532 else
534 ok( ret || broken(!ret) /* NT4 */, "GetDeviceGammaRamp failed on %s (type %d), error %u\n",
535 descr, GetObjectType( hdc ), GetLastError() );
539 /* restore hdc state */
540 SetBoundsRect( hdc, NULL, DCB_RESET | DCB_DISABLE );
541 SetBoundsRect( ref_dc, NULL, DCB_RESET | DCB_DISABLE );
544 static void test_CreateDC(void)
546 DISPLAY_DEVICEW display_device = {sizeof(display_device)};
547 WCHAR adapter_name[CCHDEVICENAME];
548 DWORD i, j;
549 HDC hdc;
551 hdc = CreateDCW( NULL, NULL, NULL, NULL );
552 ok( !hdc, "CreateDC succeeded\n" );
554 hdc = CreateDCW( NULL, L"display", NULL, NULL );
555 todo_wine ok( !hdc, "CreateDC succeeded\n" );
557 hdc = CreateDCW( L"display", NULL, NULL, NULL );
558 ok( hdc != NULL, "CreateDC failed\n" );
559 DeleteDC( hdc );
561 hdc = CreateDCW( L"display", L"deadbeef", NULL, NULL );
562 ok( hdc != NULL, "CreateDC failed\n" );
563 DeleteDC( hdc );
565 for (i = 0; EnumDisplayDevicesW( NULL, i, &display_device, 0 ); ++i)
567 if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
569 hdc = CreateDCW( display_device.DeviceName, NULL, NULL, NULL );
570 todo_wine ok( !hdc, "CreateDC succeeded\n" );
572 hdc = CreateDCW( NULL, display_device.DeviceName, NULL, NULL );
573 todo_wine ok( !hdc, "CreateDC succeeded\n" );
574 continue;
577 hdc = CreateDCW( display_device.DeviceName, NULL, NULL, NULL );
578 ok( hdc != NULL, "CreateDC failed %s\n", wine_dbgstr_w( display_device.DeviceName ) );
579 DeleteDC( hdc );
581 hdc = CreateDCW( NULL, display_device.DeviceName, NULL, NULL );
582 ok( hdc != NULL, "CreateDC failed\n" );
583 DeleteDC( hdc );
585 hdc = CreateDCW( display_device.DeviceName, display_device.DeviceName, NULL, NULL );
586 ok( hdc != NULL, "CreateDC failed\n" );
587 DeleteDC( hdc );
589 hdc = CreateDCW( display_device.DeviceName, L"deadbeef", NULL, NULL );
590 ok( hdc != NULL, "CreateDC failed\n" );
591 DeleteDC( hdc );
593 lstrcpyW( adapter_name, display_device.DeviceName );
594 for (j = 0; EnumDisplayDevicesW( adapter_name, j, &display_device, 0 ); ++j)
596 hdc = CreateDCW( display_device.DeviceName, NULL, NULL, NULL );
597 ok( !hdc, "CreateDC succeeded\n" );
599 hdc = CreateDCW( NULL, display_device.DeviceName, NULL, NULL );
600 ok( !hdc, "CreateDC succeeded\n" );
605 static void test_CreateCompatibleDC(void)
607 BOOL bRet;
608 HDC hdc, hNewDC, hdcMetafile, screen_dc;
609 HBITMAP bitmap;
610 INT caps;
611 DEVMODEA dm;
613 bitmap = CreateBitmap( 10, 10, 1, 1, NULL );
615 memset(&dm, 0, sizeof(dm));
616 dm.dmSize = sizeof(dm);
617 bRet = EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &dm);
618 ok(bRet, "EnumDisplaySettingsEx failed\n");
619 dm.u1.s1.dmScale = 200;
620 dm.dmFields |= DM_SCALE;
621 hdc = CreateDCA( "DISPLAY", NULL, NULL, &dm );
623 screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
624 test_device_caps( hdc, screen_dc, "display dc", 1 );
625 ResetDCA( hdc, &dm );
626 test_device_caps( hdc, screen_dc, "display dc", 1 );
627 DeleteDC( hdc );
629 /* Create a DC compatible with the screen */
630 hdc = CreateCompatibleDC(NULL);
631 ok(hdc != NULL, "CreateCompatibleDC returned %p\n", hdc);
632 ok( SelectObject( hdc, bitmap ) != 0, "SelectObject failed\n" );
633 caps = GetDeviceCaps( hdc, TECHNOLOGY );
634 ok( caps == DT_RASDISPLAY, "wrong caps %u\n", caps );
636 test_device_caps( hdc, screen_dc, "display dc", 1 );
638 /* Delete this DC, this should succeed */
639 bRet = DeleteDC(hdc);
640 ok(bRet == TRUE, "DeleteDC returned %u\n", bRet);
642 /* Try to create a DC compatible to the deleted DC. This has to fail */
643 hNewDC = CreateCompatibleDC(hdc);
644 ok(hNewDC == NULL, "CreateCompatibleDC returned %p\n", hNewDC);
646 hdc = GetDC( 0 );
647 hdcMetafile = CreateEnhMetaFileA(hdc, NULL, NULL, NULL);
648 ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
649 hNewDC = CreateCompatibleDC( hdcMetafile );
650 ok(hNewDC != NULL, "CreateCompatibleDC failed\n");
651 ok( SelectObject( hNewDC, bitmap ) != 0, "SelectObject failed\n" );
652 caps = GetDeviceCaps( hdcMetafile, TECHNOLOGY );
653 ok( caps == DT_RASDISPLAY, "wrong caps %u\n", caps );
654 test_device_caps( hdcMetafile, hdc, "enhmetafile dc", 1 );
655 ResetDCA( hdcMetafile, &dm );
656 test_device_caps( hdcMetafile, hdc, "enhmetafile dc", 1 );
657 DeleteDC( hNewDC );
658 DeleteEnhMetaFile( CloseEnhMetaFile( hdcMetafile ));
659 ReleaseDC( 0, hdc );
661 hdcMetafile = CreateMetaFileA(NULL);
662 ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
663 hNewDC = CreateCompatibleDC( hdcMetafile );
664 ok(hNewDC == NULL, "CreateCompatibleDC succeeded\n");
665 caps = GetDeviceCaps( hdcMetafile, TECHNOLOGY );
666 ok( caps == DT_METAFILE, "wrong caps %u\n", caps );
667 test_device_caps( hdcMetafile, screen_dc, "metafile dc", 1 );
668 ResetDCA( hdcMetafile, &dm );
669 test_device_caps( hdcMetafile, screen_dc, "metafile dc", 1 );
670 DeleteMetaFile( CloseMetaFile( hdcMetafile ));
672 DeleteObject( bitmap );
673 DeleteDC( screen_dc );
676 static void test_DC_bitmap(void)
678 PIXELFORMATDESCRIPTOR descr;
679 HDC hdc, hdcmem;
680 DWORD bits[64];
681 HBITMAP hbmp, oldhbmp;
682 COLORREF col;
683 int i, bitspixel;
684 int ret, ret2;
686 /* fill bitmap data with b&w pattern */
687 for( i = 0; i < 64; i++) bits[i] = i & 1 ? 0 : 0xffffff;
689 hdc = GetDC(0);
690 ok( hdc != NULL, "CreateDC rets %p\n", hdc);
691 bitspixel = GetDeviceCaps( hdc, BITSPIXEL);
692 /* create a memory dc */
693 hdcmem = CreateCompatibleDC( hdc);
694 ok( hdcmem != NULL, "CreateCompatibleDC rets %p\n", hdcmem);
696 /* test DescribePixelFormat with descr == NULL */
697 ret2 = DescribePixelFormat(hdcmem, 0, sizeof(descr), NULL);
698 ok(ret2 > 0, "expected ret2 > 0, got %d\n", ret2);
699 ret = DescribePixelFormat(hdcmem, 1, sizeof(descr), NULL);
700 ok(ret == ret2, "expected ret == %d, got %d\n", ret2, ret);
701 ret = DescribePixelFormat(hdcmem, 0x10000, sizeof(descr), NULL);
702 ok(ret == ret2, "expected ret == %d, got %d\n", ret2, ret);
704 /* test DescribePixelFormat with descr != NULL */
705 memset(&descr, 0, sizeof(descr));
706 ret = DescribePixelFormat(hdcmem, 0, sizeof(descr), &descr);
707 ok(ret == 0, "expected ret == 0, got %d\n", ret);
708 ok(descr.nSize == 0, "expected descr.nSize == 0, got %d\n", descr.nSize);
710 memset(&descr, 0, sizeof(descr));
711 ret = DescribePixelFormat(hdcmem, 1, sizeof(descr), &descr);
712 ok(ret == ret2, "expected ret == %d, got %d\n", ret2, ret);
713 ok(descr.nSize == sizeof(descr), "expected desc.nSize == sizeof(descr), got %d\n", descr.nSize);
715 memset(&descr, 0, sizeof(descr));
716 ret = DescribePixelFormat(hdcmem, 0x10000, sizeof(descr), &descr);
717 ok(ret == 0, "expected ret == 0, got %d\n", ret);
718 ok(descr.nSize == 0, "expected descr.nSize == 0, got %d\n", descr.nSize);
720 /* test monochrome bitmap: should always work */
721 hbmp = CreateBitmap(32, 32, 1, 1, bits);
722 ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
723 oldhbmp = SelectObject( hdcmem, hbmp);
724 ok( oldhbmp != NULL, "SelectObject returned NULL\n" ); /* a memdc always has a bitmap selected */
725 col = GetPixel( hdcmem, 0, 0);
726 ok( col == 0xffffff, "GetPixel returned %08x, expected 00ffffff\n", col);
727 col = GetPixel( hdcmem, 1, 1);
728 ok( col == 0x000000, "GetPixel returned %08x, expected 00000000\n", col);
729 col = GetPixel( hdcmem, 100, 1);
730 ok( col == CLR_INVALID, "GetPixel returned %08x, expected ffffffff\n", col);
731 SelectObject( hdcmem, oldhbmp);
732 DeleteObject( hbmp);
734 /* test with 2 bits color depth, not likely to succeed */
735 hbmp = CreateBitmap(16, 16, 1, 2, bits);
736 ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
737 oldhbmp = SelectObject( hdcmem, hbmp);
738 if( bitspixel != 2)
739 ok( !oldhbmp, "SelectObject of a bitmap with 2 bits/pixel should return NULL\n");
740 if( oldhbmp) SelectObject( hdcmem, oldhbmp);
741 DeleteObject( hbmp);
743 /* test with 16 bits color depth, might succeed */
744 hbmp = CreateBitmap(6, 6, 1, 16, bits);
745 ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
746 oldhbmp = SelectObject( hdcmem, hbmp);
747 if( bitspixel == 16) {
748 ok( oldhbmp != NULL, "SelectObject returned NULL\n" );
749 col = GetPixel( hdcmem, 0, 0);
750 ok( col == 0xffffff,
751 "GetPixel of a bitmap with 16 bits/pixel returned %08x, expected 00ffffff\n", col);
752 col = GetPixel( hdcmem, 1, 1);
753 ok( col == 0x000000,
754 "GetPixel of a bitmap with 16 bits/pixel returned returned %08x, expected 00000000\n", col);
756 if( oldhbmp) SelectObject( hdcmem, oldhbmp);
757 DeleteObject( hbmp);
759 /* test with 32 bits color depth, probably succeed */
760 hbmp = CreateBitmap(4, 4, 1, 32, bits);
761 ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
762 oldhbmp = SelectObject( hdcmem, hbmp);
763 if( bitspixel == 32) {
764 ok( oldhbmp != NULL, "SelectObject returned NULL\n" );
765 col = GetPixel( hdcmem, 0, 0);
766 ok( col == 0xffffff,
767 "GetPixel of a bitmap with 32 bits/pixel returned %08x, expected 00ffffff\n", col);
768 col = GetPixel( hdcmem, 1, 1);
769 ok( col == 0x000000,
770 "GetPixel of a bitmap with 32 bits/pixel returned returned %08x, expected 00000000\n", col);
772 if( oldhbmp) SelectObject( hdcmem, oldhbmp);
773 DeleteObject( hbmp);
774 ReleaseDC( 0, hdc );
777 static void test_DeleteDC(void)
779 HWND hwnd;
780 HDC hdc, hdc_test;
781 WNDCLASSEXA cls;
782 int ret;
784 /* window DC */
785 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
786 0, 0, 0, NULL);
787 ok(hwnd != 0, "CreateWindowExA failed\n");
789 hdc = GetDC(hwnd);
790 ok(hdc != 0, "GetDC failed\n");
791 ret = GetObjectType(hdc);
792 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
793 ret = GetDeviceCaps(hdc, TECHNOLOGY);
794 ok(ret == DT_RASDISPLAY, "GetDeviceCaps rets %d\n", ret);
795 ret = DeleteDC(hdc);
796 ok(ret, "DeleteDC failed\n");
797 ret = GetDeviceCaps(hdc, TECHNOLOGY);
798 ok(!ret, "GetDeviceCaps should fail for a deleted DC\n");
800 hdc = GetWindowDC(hwnd);
801 ok(hdc != 0, "GetDC failed\n");
802 ret = GetObjectType(hdc);
803 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
804 ret = GetDeviceCaps(hdc, TECHNOLOGY);
805 ok(ret == DT_RASDISPLAY, "GetDeviceCaps rets %d\n", ret);
806 ret = DeleteDC(hdc);
807 ok(ret, "DeleteDC failed\n");
808 ret = GetDeviceCaps(hdc, TECHNOLOGY);
809 ok(!ret, "GetDeviceCaps should fail for a deleted DC\n");
811 DestroyWindow(hwnd);
813 /* desktop window DC */
814 hwnd = GetDesktopWindow();
815 ok(hwnd != 0, "GetDesktopWindow failed\n");
817 hdc = GetDC(hwnd);
818 ok(hdc != 0, "GetDC failed\n");
819 ret = GetObjectType(hdc);
820 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
821 ret = GetDeviceCaps(hdc, TECHNOLOGY);
822 ok(ret == DT_RASDISPLAY, "GetDeviceCaps rets %d\n", ret);
823 ret = DeleteDC(hdc);
824 ok(ret, "DeleteDC failed\n");
825 ret = GetDeviceCaps(hdc, TECHNOLOGY);
826 ok(!ret, "GetDeviceCaps should fail for a deleted DC\n");
828 hdc = GetWindowDC(hwnd);
829 ok(hdc != 0, "GetDC failed\n");
830 ret = GetObjectType(hdc);
831 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
832 ret = GetDeviceCaps(hdc, TECHNOLOGY);
833 ok(ret == DT_RASDISPLAY, "GetDeviceCaps rets %d\n", ret);
834 ret = DeleteDC(hdc);
835 ok(ret, "DeleteDC failed\n");
836 ret = GetDeviceCaps(hdc, TECHNOLOGY);
837 ok(!ret, "GetDeviceCaps should fail for a deleted DC\n");
839 /* CS_CLASSDC */
840 memset(&cls, 0, sizeof(cls));
841 cls.cbSize = sizeof(cls);
842 cls.style = CS_CLASSDC;
843 cls.hInstance = GetModuleHandleA(NULL);
844 cls.lpszClassName = "Wine class DC";
845 cls.lpfnWndProc = DefWindowProcA;
846 ret = RegisterClassExA(&cls);
847 ok(ret, "RegisterClassExA failed\n");
849 hwnd = CreateWindowExA(0, "Wine class DC", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
850 0, 0, 0, NULL);
851 ok(hwnd != 0, "CreateWindowExA failed\n");
853 hdc = GetDC(hwnd);
854 ok(hdc != 0, "GetDC failed\n");
855 ret = GetObjectType(hdc);
856 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
857 ret = DeleteDC(hdc);
858 ok(ret, "DeleteDC failed\n");
859 ret = GetObjectType(hdc);
860 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
861 ret = ReleaseDC(hwnd, hdc);
862 ok(ret, "ReleaseDC failed\n");
863 ret = GetObjectType(hdc);
864 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
866 hdc_test = hdc;
868 hdc = GetWindowDC(hwnd);
869 ok(hdc != 0, "GetDC failed\n");
870 ret = GetObjectType(hdc);
871 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
872 ret = GetDeviceCaps(hdc, TECHNOLOGY);
873 ok(ret == DT_RASDISPLAY, "GetDeviceCaps rets %d\n", ret);
874 ret = DeleteDC(hdc);
875 ok(ret, "DeleteDC failed\n");
876 ret = GetDeviceCaps(hdc, TECHNOLOGY);
877 ok(!ret, "GetDeviceCaps should fail for a deleted DC\n");
879 DestroyWindow(hwnd);
881 ret = GetObjectType(hdc_test);
882 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
883 ret = GetDeviceCaps(hdc_test, TECHNOLOGY);
884 ok(ret == DT_RASDISPLAY, "GetDeviceCaps rets %d\n", ret);
886 ret = UnregisterClassA("Wine class DC", GetModuleHandleA(NULL));
887 ok(ret, "UnregisterClassA failed\n");
889 ret = GetDeviceCaps(hdc_test, TECHNOLOGY);
890 ok(!ret, "GetDeviceCaps should fail for a deleted DC\n");
892 /* CS_OWNDC */
893 memset(&cls, 0, sizeof(cls));
894 cls.cbSize = sizeof(cls);
895 cls.style = CS_OWNDC;
896 cls.hInstance = GetModuleHandleA(NULL);
897 cls.lpszClassName = "Wine own DC";
898 cls.lpfnWndProc = DefWindowProcA;
899 ret = RegisterClassExA(&cls);
900 ok(ret, "RegisterClassExA failed\n");
902 hwnd = CreateWindowExA(0, "Wine own DC", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
903 0, 0, 0, NULL);
904 ok(hwnd != 0, "CreateWindowExA failed\n");
906 hdc = GetDC(hwnd);
907 ok(hdc != 0, "GetDC failed\n");
908 ret = GetObjectType(hdc);
909 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
910 ret = DeleteDC(hdc);
911 ok(ret, "DeleteDC failed\n");
912 ret = GetObjectType(hdc);
913 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
914 ret = ReleaseDC(hwnd, hdc);
915 ok(ret, "ReleaseDC failed\n");
916 ret = GetObjectType(hdc);
917 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
919 hdc = GetWindowDC(hwnd);
920 ok(hdc != 0, "GetDC failed\n");
921 ret = GetObjectType(hdc);
922 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
923 ret = GetDeviceCaps(hdc, TECHNOLOGY);
924 ok(ret == DT_RASDISPLAY, "GetDeviceCaps rets %d\n", ret);
925 ret = DeleteDC(hdc);
926 ok(ret, "DeleteDC failed\n");
927 ret = GetDeviceCaps(hdc, TECHNOLOGY);
928 ok(!ret, "GetDeviceCaps should fail for a deleted DC\n");
930 DestroyWindow(hwnd);
932 ret = UnregisterClassA("Wine own DC", GetModuleHandleA(NULL));
933 ok(ret, "UnregisterClassA failed\n");
936 static void test_boundsrect(void)
938 char buffer[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
939 BITMAPINFO *info = (BITMAPINFO *)buffer;
940 HDC hdc;
941 HBITMAP bitmap, dib, old;
942 RECT rect, expect, set_rect;
943 UINT ret;
944 int i, level;
946 hdc = CreateCompatibleDC(0);
947 ok(hdc != NULL, "CreateCompatibleDC failed\n");
948 bitmap = CreateCompatibleBitmap( hdc, 200, 200 );
949 old = SelectObject( hdc, bitmap );
951 ret = GetBoundsRect(hdc, NULL, 0);
952 ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
954 ret = GetBoundsRect(hdc, NULL, ~0U);
955 ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
957 /* Test parameter handling order. */
958 SetRect(&set_rect, 10, 20, 40, 50);
959 ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
960 ok(ret & DCB_RESET,
961 "Expected return flag DCB_RESET to be set, got %u\n", ret);
963 ret = GetBoundsRect(hdc, NULL, DCB_RESET);
964 ok(ret == 0,
965 "Expected GetBoundsRect to return 0, got %u\n", ret);
967 ret = GetBoundsRect(hdc, &rect, 0);
968 ok(ret == DCB_RESET,
969 "Expected GetBoundsRect to return DCB_RESET, got %u\n", ret);
970 SetRectEmpty(&expect);
971 ok(EqualRect(&rect, &expect), "Expected output rectangle (0,0)-(0,0), got %s\n",
972 wine_dbgstr_rect(&rect));
974 ret = GetBoundsRect(NULL, NULL, 0);
975 ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
977 ret = GetBoundsRect(NULL, NULL, ~0U);
978 ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
980 ret = SetBoundsRect(NULL, NULL, 0);
981 ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret);
983 ret = SetBoundsRect(NULL, NULL, ~0U);
984 ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret);
986 SetRect(&set_rect, 10, 20, 40, 50);
987 ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
988 ok(ret == (DCB_RESET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
990 ret = GetBoundsRect(hdc, &rect, 0);
991 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
992 SetRect(&expect, 10, 20, 40, 50);
993 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
995 SetMapMode( hdc, MM_ANISOTROPIC );
996 SetViewportExtEx( hdc, 2, 2, NULL );
997 ret = GetBoundsRect(hdc, &rect, 0);
998 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
999 SetRect(&expect, 5, 10, 20, 25);
1000 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1002 SetViewportOrgEx( hdc, 20, 30, NULL );
1003 ret = GetBoundsRect(hdc, &rect, 0);
1004 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
1005 SetRect(&expect, -5, -5, 10, 10);
1006 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1008 SetRect(&set_rect, 10, 20, 40, 50);
1009 ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
1010 ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
1012 ret = GetBoundsRect(hdc, &rect, 0);
1013 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
1014 SetRect(&expect, 10, 20, 40, 50);
1015 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1017 SetMapMode( hdc, MM_TEXT );
1018 SetViewportOrgEx( hdc, 0, 0, NULL );
1019 ret = GetBoundsRect(hdc, &rect, 0);
1020 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
1021 SetRect(&expect, 40, 70, 100, 130);
1022 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1024 SetLayout( hdc, LAYOUT_RTL );
1025 ret = GetBoundsRect(hdc, &rect, 0);
1026 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
1027 SetRect(&expect, 159, 70, 99, 130);
1028 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1029 SetRect(&set_rect, 50, 25, 30, 35);
1030 ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
1031 ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
1032 ret = GetBoundsRect(hdc, &rect, 0);
1033 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
1034 SetRect(&expect, 50, 25, 30, 35);
1035 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1037 SetLayout( hdc, LAYOUT_LTR );
1038 ret = GetBoundsRect(hdc, &rect, 0);
1039 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
1040 SetRect(&expect, 149, 25, 169, 35);
1041 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1043 /* empty rect resets, except on nt4 */
1044 SetRect(&expect, 20, 20, 10, 10);
1045 ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
1046 ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
1047 ret = GetBoundsRect(hdc, &rect, 0);
1048 ok(ret == DCB_RESET || broken(ret == DCB_SET) /* nt4 */,
1049 "GetBoundsRect returned %x\n", ret);
1050 if (ret == DCB_RESET)
1052 SetRectEmpty(&expect);
1053 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1055 SetRect(&expect, 20, 20, 20, 20);
1056 ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
1057 ok(ret == (DCB_RESET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
1058 ret = GetBoundsRect(hdc, &rect, 0);
1059 ok(ret == DCB_RESET, "GetBoundsRect returned %x\n", ret);
1060 SetRectEmpty(&expect);
1061 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1064 SetBoundsRect( hdc, NULL, DCB_RESET | DCB_ENABLE );
1065 MoveToEx( hdc, 10, 10, NULL );
1066 LineTo( hdc, 20, 20 );
1067 ret = GetBoundsRect( hdc, &rect, 0 );
1068 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1069 SetRect( &expect, 10, 10, 21, 21 );
1070 ok( EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1071 SetRect( &rect, 8, 8, 23, 23 );
1072 expect = rect;
1073 SetBoundsRect( hdc, &rect, DCB_ACCUMULATE );
1074 ret = GetBoundsRect( hdc, &rect, 0 );
1075 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1076 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1078 level = SaveDC( hdc );
1079 LineTo( hdc, 30, 25 );
1080 ret = GetBoundsRect( hdc, &rect, 0 );
1081 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1082 SetRect( &expect, 8, 8, 31, 26 );
1083 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1084 SetBoundsRect( hdc, NULL, DCB_DISABLE );
1085 LineTo( hdc, 40, 40 );
1086 ret = GetBoundsRect( hdc, &rect, 0 );
1087 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1088 SetRect( &expect, 8, 8, 31, 26 );
1089 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1090 SetRect( &rect, 6, 6, 30, 30 );
1091 SetBoundsRect( hdc, &rect, DCB_ACCUMULATE );
1092 ret = GetBoundsRect( hdc, &rect, 0 );
1093 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1094 SetRect( &expect, 6, 6, 31, 30 );
1095 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1097 RestoreDC( hdc, level );
1098 ret = GetBoundsRect( hdc, &rect, 0 );
1099 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1100 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1101 LineTo( hdc, 40, 40 );
1102 ret = GetBoundsRect( hdc, &rect, 0 );
1103 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1104 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1106 SelectObject( hdc, old );
1107 ret = GetBoundsRect( hdc, &rect, 0 );
1108 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1109 SetRect( &expect, 6, 6, 1, 1 );
1110 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1111 SetBoundsRect( hdc, NULL, DCB_ENABLE );
1112 LineTo( hdc, 50, 40 );
1114 SelectObject( hdc, bitmap );
1115 ret = GetBoundsRect( hdc, &rect, 0 );
1116 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1117 SetRect( &expect, 6, 6, 51, 41 );
1118 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1119 SelectObject( hdc, GetStockObject( NULL_PEN ));
1120 LineTo( hdc, 50, 50 );
1121 ret = GetBoundsRect( hdc, &rect, 0 );
1122 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1123 SetRect( &expect, 6, 6, 51, 51 );
1124 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1126 memset( buffer, 0, sizeof(buffer) );
1127 info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1128 info->bmiHeader.biWidth = 256;
1129 info->bmiHeader.biHeight = 256;
1130 info->bmiHeader.biPlanes = 1;
1131 info->bmiHeader.biBitCount = 8;
1132 info->bmiHeader.biCompression = BI_RGB;
1133 dib = CreateDIBSection( 0, info, DIB_RGB_COLORS, NULL, NULL, 0 );
1134 ok( dib != 0, "failed to create DIB\n" );
1135 SelectObject( hdc, dib );
1136 ret = GetBoundsRect( hdc, &rect, 0 );
1137 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1138 SetRect( &expect, 6, 6, 51, 51 );
1139 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1140 LineTo( hdc, 55, 30 );
1141 ret = GetBoundsRect( hdc, &rect, 0 );
1142 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1143 SetRect( &expect, 6, 6, 56, 51 );
1144 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1145 LineTo( hdc, 300, 30 );
1146 ret = GetBoundsRect( hdc, &rect, 0 );
1147 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1148 SetRect( &expect, 6, 6, 256, 51 );
1149 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1150 LineTo( hdc, -300, -300 );
1151 ret = GetBoundsRect( hdc, &rect, 0 );
1152 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1153 SetRect( &expect, 0, 0, 256, 51 );
1154 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1156 /* test the wide pen heuristics */
1157 SetBoundsRect( hdc, NULL, DCB_ENABLE | DCB_RESET );
1158 for (i = 0; i < 1000; i++)
1160 static const UINT endcaps[3] = { PS_ENDCAP_ROUND, PS_ENDCAP_SQUARE, PS_ENDCAP_FLAT };
1161 static const UINT joins[3] = { PS_JOIN_ROUND, PS_JOIN_BEVEL, PS_JOIN_MITER };
1162 LOGBRUSH brush = { BS_SOLID, RGB(0,0,0), 0 };
1163 UINT join = joins[i % 3];
1164 UINT endcap = endcaps[(i / 3) % 3];
1165 INT inflate, width = 1 + i / 9;
1166 HPEN pen = ExtCreatePen( PS_GEOMETRIC | join | endcap | PS_SOLID, width, &brush, 0, NULL );
1167 HPEN old = SelectObject( hdc, pen );
1168 MoveToEx( hdc, 100, 100, NULL );
1169 LineTo( hdc, 160, 100 );
1170 LineTo( hdc, 100, 160 );
1171 LineTo( hdc, 160, 160 );
1172 GetBoundsRect( hdc, &rect, DCB_RESET );
1173 SetRect( &expect, 100, 100, 161, 161 );
1175 inflate = width + 2;
1176 if (join == PS_JOIN_MITER)
1178 inflate *= 5;
1179 if (endcap == PS_ENDCAP_SQUARE)
1180 InflateRect( &expect, (inflate * 3 + 1) / 2, (inflate * 3 + 1) / 2 );
1181 else
1182 InflateRect( &expect, inflate, inflate );
1184 else
1186 if (endcap == PS_ENDCAP_SQUARE)
1187 InflateRect( &expect, inflate - inflate / 4, inflate - inflate / 4 );
1188 else
1189 InflateRect( &expect, (inflate + 1) / 2, (inflate + 1) / 2 );
1191 expect.left = max( expect.left, 0 );
1192 expect.top = max( expect.top, 0 );
1193 expect.right = min( expect.right, 256 );
1194 expect.bottom = min( expect.bottom, 256 );
1195 ok(EqualRect(&rect, &expect), "Got %s expected %s %u/%x/%x\n", wine_dbgstr_rect(&rect),
1196 wine_dbgstr_rect(&expect), width, endcap, join);
1197 DeleteObject( SelectObject( hdc, old ));
1200 DeleteDC( hdc );
1201 DeleteObject( bitmap );
1202 DeleteObject( dib );
1205 static void test_desktop_colorres(void)
1207 HDC hdc = GetDC(NULL);
1208 int bitspixel, colorres;
1210 bitspixel = GetDeviceCaps(hdc, BITSPIXEL);
1211 ok(bitspixel != 0, "Expected to get valid BITSPIXEL capability value\n");
1213 colorres = GetDeviceCaps(hdc, COLORRES);
1214 ok(colorres != 0 ||
1215 broken(colorres == 0), /* Win9x */
1216 "Expected to get valid COLORRES capability value\n");
1218 if (colorres)
1220 switch (bitspixel)
1222 case 8:
1223 ok(colorres == 18,
1224 "Expected COLORRES to be 18, got %d\n", colorres);
1225 break;
1226 case 16:
1227 ok(colorres == 16,
1228 "Expected COLORRES to be 16, got %d\n", colorres);
1229 break;
1230 case 24:
1231 case 32:
1232 ok(colorres == 24,
1233 "Expected COLORRES to be 24, got %d\n", bitspixel);
1234 break;
1235 default:
1236 ok(0, "Got unknown BITSPIXEL %d with COLORRES %d\n", bitspixel, colorres);
1237 break;
1241 ReleaseDC(NULL, hdc);
1244 static void test_gamma(void)
1246 BOOL ret;
1247 HDC hdc = GetDC(NULL);
1248 WORD oldramp[3][256], ramp[3][256];
1249 INT i;
1251 ret = GetDeviceGammaRamp(hdc, &oldramp);
1252 if (!ret)
1254 win_skip("GetDeviceGammaRamp failed, skipping tests\n");
1255 goto done;
1258 /* try to set back old ramp */
1259 ret = SetDeviceGammaRamp(hdc, &oldramp);
1260 if (!ret)
1262 win_skip("SetDeviceGammaRamp failed, skipping tests\n");
1263 goto done;
1266 memcpy(ramp, oldramp, sizeof(ramp));
1268 /* set one color ramp to zeros */
1269 memset(ramp[0], 0, sizeof(ramp[0]));
1270 ret = SetDeviceGammaRamp(hdc, &ramp);
1271 ok(!ret, "SetDeviceGammaRamp succeeded\n");
1273 /* set one color ramp to a flat straight rising line */
1274 for (i = 0; i < 256; i++) ramp[0][i] = i;
1275 ret = SetDeviceGammaRamp(hdc, &ramp);
1276 todo_wine ok(!ret, "SetDeviceGammaRamp succeeded\n");
1278 /* set one color ramp to a steep straight rising line */
1279 for (i = 0; i < 256; i++) ramp[0][i] = i * 256;
1280 ret = SetDeviceGammaRamp(hdc, &ramp);
1281 ok(ret, "SetDeviceGammaRamp failed\n");
1283 /* try a bright gamma ramp */
1284 ramp[0][0] = 0;
1285 ramp[0][1] = 0x7FFF;
1286 for (i = 2; i < 256; i++) ramp[0][i] = 0xFFFF;
1287 ret = SetDeviceGammaRamp(hdc, &ramp);
1288 ok(!ret, "SetDeviceGammaRamp succeeded\n");
1290 /* try ramps which are not uniform */
1291 ramp[0][0] = 0;
1292 for (i = 1; i < 256; i++) ramp[0][i] = ramp[0][i - 1] + 512;
1293 ret = SetDeviceGammaRamp(hdc, &ramp);
1294 ok(ret, "SetDeviceGammaRamp failed\n");
1295 ramp[0][0] = 0;
1296 for (i = 2; i < 256; i+=2)
1298 ramp[0][i - 1] = ramp[0][i - 2];
1299 ramp[0][i] = ramp[0][i - 2] + 512;
1301 ret = SetDeviceGammaRamp(hdc, &ramp);
1302 ok(ret, "SetDeviceGammaRamp failed\n");
1304 /* cleanup: set old ramp again */
1305 ret = SetDeviceGammaRamp(hdc, &oldramp);
1306 ok(ret, "SetDeviceGammaRamp failed\n");
1308 done:
1309 ReleaseDC(NULL, hdc);
1312 static BOOL is_postscript_printer(HDC hdc)
1314 char tech[256];
1316 if (ExtEscape(hdc, GETTECHNOLOGY, 0, NULL, sizeof(tech), tech) > 0)
1317 return strcmp(tech, "PostScript") == 0;
1319 return FALSE;
1322 static HDC create_printer_dc(int scale, BOOL reset)
1324 char buffer[260];
1325 DWORD len;
1326 PRINTER_INFO_2A *pbuf = NULL;
1327 DRIVER_INFO_3A *dbuf = NULL;
1328 HANDLE hprn = 0;
1329 HDC hdc = 0;
1330 HMODULE winspool = LoadLibraryA( "winspool.drv" );
1331 BOOL (WINAPI *pOpenPrinterA)(LPSTR, HANDLE *, LPPRINTER_DEFAULTSA);
1332 BOOL (WINAPI *pGetDefaultPrinterA)(LPSTR, LPDWORD);
1333 BOOL (WINAPI *pGetPrinterA)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD);
1334 BOOL (WINAPI *pGetPrinterDriverA)(HANDLE, LPSTR, DWORD, LPBYTE, DWORD, LPDWORD);
1335 BOOL (WINAPI *pClosePrinter)(HANDLE);
1337 pGetDefaultPrinterA = (void *)GetProcAddress( winspool, "GetDefaultPrinterA" );
1338 pOpenPrinterA = (void *)GetProcAddress( winspool, "OpenPrinterA" );
1339 pGetPrinterA = (void *)GetProcAddress( winspool, "GetPrinterA" );
1340 pGetPrinterDriverA = (void *)GetProcAddress( winspool, "GetPrinterDriverA" );
1341 pClosePrinter = (void *)GetProcAddress( winspool, "ClosePrinter" );
1343 if (!pGetDefaultPrinterA || !pOpenPrinterA || !pGetPrinterA || !pGetPrinterDriverA || !pClosePrinter)
1344 goto done;
1346 len = sizeof(buffer);
1347 if (!pGetDefaultPrinterA( buffer, &len )) goto done;
1348 if (!pOpenPrinterA( buffer, &hprn, NULL )) goto done;
1350 pGetPrinterA( hprn, 2, NULL, 0, &len );
1351 pbuf = HeapAlloc( GetProcessHeap(), 0, len );
1352 if (!pGetPrinterA( hprn, 2, (LPBYTE)pbuf, len, &len )) goto done;
1354 pGetPrinterDriverA( hprn, NULL, 3, NULL, 0, &len );
1355 dbuf = HeapAlloc( GetProcessHeap(), 0, len );
1356 if (!pGetPrinterDriverA( hprn, NULL, 3, (LPBYTE)dbuf, len, &len )) goto done;
1358 pbuf->pDevMode->u1.s1.dmScale = scale;
1359 pbuf->pDevMode->dmFields |= DM_SCALE;
1361 hdc = CreateDCA( dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, pbuf->pDevMode );
1362 trace( "hdc %p for driver '%s' printer '%s' port '%s' is %sPostScript\n", hdc,
1363 dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName,
1364 is_postscript_printer(hdc) ? "" : "NOT " );
1366 if (reset) ResetDCA( hdc, pbuf->pDevMode );
1367 done:
1368 HeapFree( GetProcessHeap(), 0, dbuf );
1369 HeapFree( GetProcessHeap(), 0, pbuf );
1370 if (hprn) pClosePrinter( hprn );
1371 if (winspool) FreeLibrary( winspool );
1372 if (!hdc) skip( "could not create a DC for the default printer\n" );
1373 return hdc;
1376 static void test_printer_dc(void)
1378 HDC memdc, display_memdc, enhmf_dc;
1379 HBITMAP orig, bmp;
1380 DWORD ret;
1381 HDC hdc, hdc_200;
1383 hdc = create_printer_dc(100, FALSE);
1384 hdc_200 = create_printer_dc(200, FALSE);
1386 if (!hdc || !hdc_200) return;
1388 test_device_caps( hdc, hdc_200, "printer dc", is_postscript_printer(hdc) ? 2 : 1 );
1389 DeleteDC( hdc_200 );
1391 hdc_200 = create_printer_dc(200, TRUE);
1392 test_device_caps( hdc, hdc_200, "printer dc", is_postscript_printer(hdc) ? 2 : 1 );
1393 DeleteDC( hdc_200 );
1395 memdc = CreateCompatibleDC( hdc );
1396 display_memdc = CreateCompatibleDC( 0 );
1398 ok( memdc != NULL, "CreateCompatibleDC failed for printer\n" );
1399 ok( display_memdc != NULL, "CreateCompatibleDC failed for screen\n" );
1401 ret = GetDeviceCaps( hdc, TECHNOLOGY );
1402 ok( ret == DT_RASPRINTER, "wrong type %u\n", ret );
1404 ret = GetDeviceCaps( memdc, TECHNOLOGY );
1405 ok( ret == DT_RASPRINTER, "wrong type %u\n", ret );
1407 ret = GetDeviceCaps( display_memdc, TECHNOLOGY );
1408 ok( ret == DT_RASDISPLAY, "wrong type %u\n", ret );
1410 bmp = CreateBitmap( 100, 100, 1, GetDeviceCaps( hdc, BITSPIXEL ), NULL );
1411 orig = SelectObject( memdc, bmp );
1412 ok( orig != NULL, "SelectObject failed\n" );
1413 ok( BitBlt( hdc, 10, 10, 20, 20, memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
1415 test_device_caps( memdc, hdc, "printer dc", 1 );
1417 ok( !SelectObject( display_memdc, bmp ), "SelectObject succeeded\n" );
1418 SelectObject( memdc, orig );
1419 DeleteObject( bmp );
1421 bmp = CreateBitmap( 100, 100, 1, 1, NULL );
1422 orig = SelectObject( display_memdc, bmp );
1423 ok( orig != NULL, "SelectObject failed\n" );
1424 ok( !SelectObject( memdc, bmp ), "SelectObject succeeded\n" );
1425 ok( BitBlt( hdc, 10, 10, 20, 20, display_memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
1426 ok( BitBlt( memdc, 10, 10, 20, 20, display_memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
1427 ok( BitBlt( display_memdc, 10, 10, 20, 20, memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
1429 ret = GetPixel( hdc, 0, 0 );
1430 ok( ret == CLR_INVALID, "wrong pixel value %x\n", ret );
1432 enhmf_dc = CreateEnhMetaFileA( hdc, NULL, NULL, NULL );
1433 ok(enhmf_dc != 0, "CreateEnhMetaFileA failed\n");
1434 test_device_caps( enhmf_dc, hdc, "enhmetafile printer dc", 1 );
1435 DeleteEnhMetaFile( CloseEnhMetaFile( enhmf_dc ));
1437 enhmf_dc = CreateEnhMetaFileA( hdc, NULL, NULL, NULL );
1438 ok(enhmf_dc != 0, "CreateEnhMetaFileA failed\n");
1439 test_device_caps( enhmf_dc, hdc, "enhmetafile printer dc", 1 );
1440 DeleteEnhMetaFile( CloseEnhMetaFile( enhmf_dc ));
1442 DeleteDC( memdc );
1443 DeleteDC( display_memdc );
1444 DeleteDC( hdc );
1445 DeleteObject( bmp );
1448 static void print_something(HDC hdc)
1450 static const char psadobe[10] = "%!PS-Adobe";
1451 char buf[1024], *p;
1452 char temp_path[MAX_PATH], file_name[MAX_PATH];
1453 DOCINFOA di;
1454 DWORD ret;
1455 HANDLE hfile;
1457 GetTempPathA(sizeof(temp_path), temp_path);
1458 GetTempFileNameA(temp_path, "ps", 0, file_name);
1460 di.cbSize = sizeof(di);
1461 di.lpszDocName = "Let's dance";
1462 di.lpszOutput = file_name;
1463 di.lpszDatatype = NULL;
1464 di.fwType = 0;
1465 ret = StartDocA(hdc, &di);
1466 ok(ret > 0, "StartDoc failed: %d\n", ret);
1468 strcpy(buf + 2, "\n% ===> before DOWNLOADHEADER <===\n");
1469 *(WORD *)buf = strlen(buf + 2);
1470 ret = Escape(hdc, POSTSCRIPT_PASSTHROUGH, 0, buf, NULL);
1471 ok(ret == *(WORD *)buf, "POSTSCRIPT_PASSTHROUGH failed: %d\n", ret);
1473 strcpy(buf, "deadbeef");
1474 ret = ExtEscape(hdc, DOWNLOADHEADER, 0, NULL, sizeof(buf), buf );
1475 ok(ret == 1, "DOWNLOADHEADER failed\n");
1476 ok(strcmp(buf, "deadbeef") != 0, "DOWNLOADHEADER failed\n");
1478 strcpy(buf + 2, "\n% ===> after DOWNLOADHEADER <===\n");
1479 *(WORD *)buf = strlen(buf + 2);
1480 ret = Escape(hdc, POSTSCRIPT_PASSTHROUGH, 0, buf, NULL);
1481 ok(ret == *(WORD *)buf, "POSTSCRIPT_PASSTHROUGH failed: %d\n", ret);
1483 ret = EndDoc(hdc);
1484 ok(ret == 1, "EndDoc failed\n");
1486 hfile = CreateFileA(file_name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
1487 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed\n");
1488 memset(buf, 0, sizeof(buf));
1489 ret = ReadFile(hfile, buf, sizeof(buf), &ret, NULL);
1490 ok(ret, "ReadFile failed\n");
1491 CloseHandle(hfile);
1493 /* skip the HP PCL language selector */
1494 buf[sizeof(buf) - 1] = 0;
1495 p = buf;
1496 while (*p)
1498 if (!(p[0] == 0x1b && p[1] == '%') && memcmp(p, "@PJL", 4) != 0)
1499 break;
1501 p = strchr(p, '\n');
1502 if (!p) break;
1504 while (*p == '\r' || *p == '\n') p++;
1506 ok(p && !memcmp(p, psadobe, sizeof(psadobe)), "wrong signature: %.14s\n", p ? p : buf);
1508 DeleteFileA(file_name);
1511 static void test_pscript_printer_dc(void)
1513 HDC hdc;
1514 char buf[256];
1515 DWORD query, ret;
1517 hdc = create_printer_dc(100, FALSE);
1519 if (!hdc) return;
1521 if (!is_postscript_printer(hdc))
1523 skip("Default printer is not a PostScript device\n");
1524 DeleteDC( hdc );
1525 return;
1528 query = GETFACENAME;
1529 ret = Escape(hdc, QUERYESCSUPPORT, sizeof(query), (LPCSTR)&query, NULL);
1530 ok(!ret, "GETFACENAME is supported\n");
1532 query = DOWNLOADFACE;
1533 ret = Escape(hdc, QUERYESCSUPPORT, sizeof(query), (LPCSTR)&query, NULL);
1534 ok(ret == 1, "DOWNLOADFACE is not supported\n");
1536 query = OPENCHANNEL;
1537 ret = Escape(hdc, QUERYESCSUPPORT, sizeof(query), (LPCSTR)&query, NULL);
1538 ok(ret == 1, "OPENCHANNEL is not supported\n");
1540 query = DOWNLOADHEADER;
1541 ret = Escape(hdc, QUERYESCSUPPORT, sizeof(query), (LPCSTR)&query, NULL);
1542 ok(ret == 1, "DOWNLOADHEADER is not supported\n");
1544 query = CLOSECHANNEL;
1545 ret = Escape(hdc, QUERYESCSUPPORT, sizeof(query), (LPCSTR)&query, NULL);
1546 ok(ret == 1, "CLOSECHANNEL is not supported\n");
1548 query = POSTSCRIPT_PASSTHROUGH;
1549 ret = Escape(hdc, QUERYESCSUPPORT, sizeof(query), (LPCSTR)&query, NULL);
1550 ok(ret == 1, "POSTSCRIPT_PASSTHROUGH is not supported\n");
1552 ret = ExtEscape(hdc, GETFACENAME, 0, NULL, sizeof(buf), buf);
1553 ok(ret == 1, "GETFACENAME failed\n");
1554 trace("face name: %s\n", buf);
1556 print_something(hdc);
1558 DeleteDC(hdc);
1561 struct screen_region_info
1563 HRGN region;
1564 INT type;
1567 static BOOL CALLBACK enum_monitor_proc(HMONITOR monitor, HDC hdc, RECT *rect, LPARAM lparam)
1569 struct screen_region_info *info = (struct screen_region_info *)lparam;
1570 HRGN region;
1572 if (!info->region)
1574 info->region = CreateRectRgnIndirect(rect);
1575 info->type = SIMPLEREGION;
1577 else
1579 region = CreateRectRgnIndirect(rect);
1580 info->type = CombineRgn(info->region, info->region, region, RGN_OR);
1581 DeleteObject(region);
1583 return TRUE;
1586 static INT get_screen_region_type(void)
1588 struct screen_region_info info = {NULL, NULLREGION};
1590 EnumDisplayMonitors(NULL, NULL, enum_monitor_proc, (LPARAM)&info);
1591 DeleteObject(info.region);
1592 return info.type;
1595 static void test_clip_box(void)
1597 DEVMODEA scale_mode = {.dmSize = sizeof(DEVMODEA)};
1598 HBITMAP bitmap = CreateBitmap(10, 10, 1, 1, NULL);
1599 HDC dc, desktop_dc, printer_dc;
1600 RECT rect, expect, screen_rect;
1601 int type, screen_type;
1603 EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &scale_mode);
1604 scale_mode.dmFields |= DM_SCALE;
1605 scale_mode.u1.s1.dmScale = 200;
1607 SetRect(&screen_rect, GetSystemMetrics(SM_XVIRTUALSCREEN), GetSystemMetrics(SM_YVIRTUALSCREEN),
1608 GetSystemMetrics(SM_XVIRTUALSCREEN) + GetSystemMetrics(SM_CXVIRTUALSCREEN),
1609 GetSystemMetrics(SM_YVIRTUALSCREEN) + GetSystemMetrics(SM_CYVIRTUALSCREEN));
1610 screen_type = get_screen_region_type();
1612 dc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1613 type = GetClipBox(dc, &rect);
1614 todo_wine_if(screen_type == COMPLEXREGION)
1615 ok(type == screen_type, "wrong region type %d\n", type);
1616 ok(EqualRect(&rect, &screen_rect), "expected %s, got %s\n",
1617 wine_dbgstr_rect(&screen_rect), wine_dbgstr_rect(&rect));
1618 DeleteDC(dc);
1620 dc = CreateDCA("DISPLAY", NULL, NULL, &scale_mode);
1621 type = GetClipBox(dc, &rect);
1622 todo_wine_if(screen_type == COMPLEXREGION)
1623 ok(type == screen_type, "wrong region type %d\n", type);
1624 ok(EqualRect(&rect, &screen_rect), "expected %s, got %s\n",
1625 wine_dbgstr_rect(&screen_rect), wine_dbgstr_rect(&rect));
1626 ResetDCA(dc, &scale_mode);
1627 type = GetClipBox(dc, &rect);
1628 todo_wine_if(screen_type == COMPLEXREGION)
1629 ok(type == screen_type, "wrong region type %d\n", type);
1630 ok(EqualRect(&rect, &screen_rect), "expected %s, got %s\n",
1631 wine_dbgstr_rect(&screen_rect), wine_dbgstr_rect(&rect));
1632 DeleteDC(dc);
1634 dc = CreateCompatibleDC(NULL);
1635 type = GetClipBox(dc, &rect);
1636 ok(type == SIMPLEREGION, "wrong region type %d\n", type);
1637 SetRect(&expect, 0, 0, 1, 1);
1638 ok(EqualRect(&rect, &expect), "got %s\n", wine_dbgstr_rect(&rect));
1639 SelectObject(dc, bitmap);
1640 type = GetClipBox(dc, &rect);
1641 ok(type == SIMPLEREGION, "wrong region type %d\n", type);
1642 SetRect(&expect, 0, 0, 10, 10);
1643 ok(EqualRect(&rect, &expect), "got %s\n", wine_dbgstr_rect(&rect));
1644 DeleteDC(dc);
1646 desktop_dc = GetDC(0);
1647 type = GetClipBox(desktop_dc, &rect);
1648 todo_wine_if(screen_type == COMPLEXREGION)
1649 ok(type == screen_type, "wrong region type %d\n", type);
1650 ok(EqualRect(&rect, &screen_rect), "expected %s, got %s\n",
1651 wine_dbgstr_rect(&screen_rect), wine_dbgstr_rect(&rect));
1653 dc = CreateEnhMetaFileA(desktop_dc, NULL, NULL, NULL);
1654 ok(!!dc, "CreateEnhMetaFile() failed\n");
1655 type = GetClipBox(dc, &rect);
1656 todo_wine ok(type == SIMPLEREGION, "wrong region type %d\n", type);
1657 if (type != ERROR)
1658 ok(EqualRect(&rect, &screen_rect), "expected %s, got %s\n",
1659 wine_dbgstr_rect(&screen_rect), wine_dbgstr_rect(&rect));
1660 DeleteEnhMetaFile(CloseEnhMetaFile(dc));
1662 ReleaseDC(0, desktop_dc);
1664 dc = CreateMetaFileA(NULL);
1665 ok(!!dc, "CreateEnhMetaFile() failed\n");
1666 type = GetClipBox(dc, &rect);
1667 ok(type == ERROR, "wrong region type %d\n", type);
1668 DeleteMetaFile(CloseMetaFile(dc));
1670 if ((printer_dc = create_printer_dc(100, FALSE)))
1672 type = GetClipBox(printer_dc, &rect);
1673 ok(type == SIMPLEREGION, "wrong region type %d\n", type);
1675 dc = CreateCompatibleDC(printer_dc);
1676 type = GetClipBox(dc, &rect);
1677 ok(type == SIMPLEREGION, "wrong region type %d\n", type);
1678 SetRect(&expect, 0, 0, 1, 1);
1679 ok(EqualRect(&rect, &expect), "got %s\n", wine_dbgstr_rect(&rect));
1680 DeleteDC(dc);
1682 dc = CreateEnhMetaFileA(printer_dc, NULL, NULL, NULL);
1683 type = GetClipBox(dc, &rect);
1684 todo_wine ok(type == SIMPLEREGION, "wrong region type %d\n", type);
1685 DeleteEnhMetaFile(CloseEnhMetaFile(dc));
1687 DeleteDC(printer_dc);
1690 DeleteObject(bitmap);
1693 static void test_SetPixel(void)
1695 COLORREF c;
1697 c = SetPixel((HDC)0xdeadbeef, 0, 0, 0);
1698 ok(c == ~0, "SetPixel returned: %x\n", c);
1702 START_TEST(dc)
1704 test_dc_values();
1705 test_savedc();
1706 test_savedc_2();
1707 test_GdiConvertToDevmodeW();
1708 test_CreateDC();
1709 test_CreateCompatibleDC();
1710 test_DC_bitmap();
1711 test_DeleteDC();
1712 test_boundsrect();
1713 test_desktop_colorres();
1714 test_gamma();
1715 test_printer_dc();
1716 test_pscript_printer_dc();
1717 test_clip_box();
1718 test_SetPixel();