gdi32: Avoid making a DBCS character in range.
[wine] / dlls / gdi32 / tests / metafile.c
1 /*
2  * Unit tests for metafile functions
3  *
4  * Copyright (c) 2002 Dmitry Timoshkov
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <assert.h>
22 #include <stdio.h>
23 #include <math.h>
24
25 #include "wine/test.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winerror.h"
30
31 static LOGFONTA orig_lf;
32 static BOOL emr_processed = FALSE;
33
34 /* Arbitrarily chosen values for the second co-ordinate of a metafile line */
35 #define LINE_X 55.0f
36 #define LINE_Y 15.0f
37
38 static INT (WINAPI * pGetRelAbs)(HDC, DWORD);
39 static INT (WINAPI * pSetRelAbs)(HDC, INT);
40 static COLORREF (WINAPI *pSetDCBrushColor)(HDC,COLORREF);
41 static COLORREF (WINAPI *pSetDCPenColor)(HDC,COLORREF);
42
43 #define GDI_GET_PROC(func)                                     \
44     p ## func = (void *)GetProcAddress(hGDI, #func);           \
45     if(!p ## func)                                             \
46         trace("GetProcAddress(hGDI, \"%s\") failed\n", #func); \
47
48 static void init_function_pointers(void)
49 {
50     HMODULE hGDI;
51
52     pGetRelAbs = NULL;
53     pSetRelAbs = NULL;
54
55     hGDI = GetModuleHandleA("gdi32.dll");
56     assert(hGDI);
57     GDI_GET_PROC(GetRelAbs);
58     GDI_GET_PROC(SetRelAbs);
59     GDI_GET_PROC(SetDCBrushColor);
60     GDI_GET_PROC(SetDCPenColor);
61 }
62
63 static int CALLBACK eto_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
64     const ENHMETARECORD *emr, int n_objs, LPARAM param)
65 {
66     static int n_record;
67     DWORD i;
68     const INT *dx;
69     INT *orig_dx = (INT *)param;
70     LOGFONTA device_lf;
71     INT ret;
72
73     trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
74            hdc, emr->iType, emr->nSize, (void *)param);
75
76     if(!hdc) return 1;
77
78     PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
79
80     switch (emr->iType)
81     {
82     case EMR_HEADER:
83         ok(GetTextAlign(hdc) == 0, "text align %08x\n", GetTextAlign(hdc));
84         ok(GetBkColor(hdc) == RGB(0xff, 0xff, 0xff), "bk color %08x\n", GetBkColor(hdc));
85         ok(GetTextColor(hdc) == RGB(0x0, 0x0, 0x0), "text color %08x\n", GetTextColor(hdc));
86         ok(GetROP2(hdc) == R2_COPYPEN, "rop %d\n", GetROP2(hdc));
87         ok(GetArcDirection(hdc) == AD_COUNTERCLOCKWISE, "arc dir %d\n", GetArcDirection(hdc));
88         ok(GetPolyFillMode(hdc) == ALTERNATE, "poly fill %d\n", GetPolyFillMode(hdc));
89         ok(GetStretchBltMode(hdc) == BLACKONWHITE, "stretchblt mode %d\n", GetStretchBltMode(hdc));
90
91         /* GetBkMode, GetRelAbs do not get reset to the default value */
92         ok(GetBkMode(hdc) == OPAQUE, "bk mode %d\n", GetBkMode(hdc));
93         if(pSetRelAbs && pGetRelAbs)
94             ok(pGetRelAbs(hdc, 0) == RELATIVE, "relabs %d\n", pGetRelAbs(hdc, 0));
95
96         n_record = 0;
97         break;
98
99     case EMR_EXTTEXTOUTA:
100     {
101         const EMREXTTEXTOUTA *emr_ExtTextOutA = (const EMREXTTEXTOUTA *)emr;
102         dx = (const INT *)((const char *)emr + emr_ExtTextOutA->emrtext.offDx);
103
104         ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
105         ok( ret == sizeof(device_lf), "GetObjectA error %d\n", GetLastError());
106
107         /* compare up to lfOutPrecision, other values are not interesting,
108          * and in fact sometimes arbitrary adapted by Win9x.
109          */
110         ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
111         ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
112
113         for(i = 0; i < emr_ExtTextOutA->emrtext.nChars; i++)
114         {
115             ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
116                                      n_record, i, dx[i], orig_dx[i]);
117         }
118         n_record++;
119         emr_processed = TRUE;
120         break;
121     }
122
123     case EMR_EXTTEXTOUTW:
124     {
125         const EMREXTTEXTOUTW *emr_ExtTextOutW = (const EMREXTTEXTOUTW *)emr;
126         dx = (const INT *)((const char *)emr + emr_ExtTextOutW->emrtext.offDx);
127
128         SetLastError(0xdeadbeef);
129         ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
130         ok( ret == sizeof(device_lf) ||
131             broken(ret == (sizeof(device_lf) - LF_FACESIZE + strlen(device_lf.lfFaceName) + 1)), /* NT4 */
132             "GetObjectA error %d\n", GetLastError());
133
134         /* compare up to lfOutPrecision, other values are not interesting,
135          * and in fact sometimes arbitrary adapted by Win9x.
136          */
137         ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
138         ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
139
140         for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++)
141         {
142             ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
143                                      n_record, i, dx[i], orig_dx[i]);
144         }
145         n_record++;
146         emr_processed = TRUE;
147         break;
148     }
149
150     default:
151         break;
152     }
153
154     return 1;
155 }
156
157 static void test_ExtTextOut(void)
158 {
159     HWND hwnd;
160     HDC hdcDisplay, hdcMetafile;
161     HENHMETAFILE hMetafile;
162     HFONT hFont;
163     static const char text[] = "Simple text to test ExtTextOut on metafiles";
164     INT i, len, dx[256];
165     static const RECT rc = { 0, 0, 100, 100 };
166     BOOL ret;
167
168     assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text));
169
170     /* Win9x doesn't play EMFs on invisible windows */
171     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
172                            0, 0, 200, 200, 0, 0, 0, NULL);
173     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
174
175     hdcDisplay = GetDC(hwnd);
176     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
177
178     trace("hdcDisplay %p\n", hdcDisplay);
179
180     SetMapMode(hdcDisplay, MM_TEXT);
181
182     memset(&orig_lf, 0, sizeof(orig_lf));
183
184     orig_lf.lfCharSet = ANSI_CHARSET;
185     orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
186     orig_lf.lfWeight = FW_DONTCARE;
187     orig_lf.lfHeight = 7;
188     orig_lf.lfQuality = DEFAULT_QUALITY;
189     lstrcpyA(orig_lf.lfFaceName, "Arial");
190     hFont = CreateFontIndirectA(&orig_lf);
191     ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
192
193     hFont = SelectObject(hdcDisplay, hFont);
194
195     len = lstrlenA(text);
196     for (i = 0; i < len; i++)
197     {
198         ret = GetCharWidthA(hdcDisplay, text[i], text[i], &dx[i]);
199         ok( ret, "GetCharWidthA error %d\n", GetLastError());
200     }
201     hFont = SelectObject(hdcDisplay, hFont);
202
203     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
204     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
205
206     trace("hdcMetafile %p\n", hdcMetafile);
207
208     ok(GetDeviceCaps(hdcMetafile, TECHNOLOGY) == DT_RASDISPLAY,
209        "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
210
211     hFont = SelectObject(hdcMetafile, hFont);
212
213     /* 1. pass NULL lpDx */
214     ret = ExtTextOutA(hdcMetafile, 0, 0, 0, &rc, text, lstrlenA(text), NULL);
215     ok( ret, "ExtTextOutA error %d\n", GetLastError());
216
217     /* 2. pass custom lpDx */
218     ret = ExtTextOutA(hdcMetafile, 0, 20, 0, &rc, text, lstrlenA(text), dx);
219     ok( ret, "ExtTextOutA error %d\n", GetLastError());
220
221     hFont = SelectObject(hdcMetafile, hFont);
222     ret = DeleteObject(hFont);
223     ok( ret, "DeleteObject error %d\n", GetLastError());
224
225     hMetafile = CloseEnhMetaFile(hdcMetafile);
226     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
227
228     ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
229
230     ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
231     ok( ret, "PlayEnhMetaFile error %d\n", GetLastError());
232
233     SetTextAlign(hdcDisplay, TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING );
234     SetBkColor(hdcDisplay, RGB(0xff, 0, 0));
235     SetTextColor(hdcDisplay, RGB(0, 0xff, 0));
236     SetROP2(hdcDisplay, R2_NOT);
237     SetArcDirection(hdcDisplay, AD_CLOCKWISE);
238     SetPolyFillMode(hdcDisplay, WINDING);
239     SetStretchBltMode(hdcDisplay, HALFTONE);
240
241     if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE);
242     SetBkMode(hdcDisplay, OPAQUE);
243
244     ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc);
245     ok( ret, "EnumEnhMetaFile error %d\n", GetLastError());
246
247     ok( GetTextAlign(hdcDisplay) == (TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING),
248         "text align %08x\n", GetTextAlign(hdcDisplay));
249     ok( GetBkColor(hdcDisplay) == RGB(0xff, 0, 0), "bk color %08x\n", GetBkColor(hdcDisplay));
250     ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08x\n", GetTextColor(hdcDisplay));
251     ok( GetROP2(hdcDisplay) == R2_NOT, "rop2 %d\n", GetROP2(hdcDisplay));
252     ok( GetArcDirection(hdcDisplay) == AD_CLOCKWISE, "arc dir  %d\n", GetArcDirection(hdcDisplay));
253     ok( GetPolyFillMode(hdcDisplay) == WINDING, "poly fill %d\n", GetPolyFillMode(hdcDisplay));
254     ok( GetStretchBltMode(hdcDisplay) == HALFTONE, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay));
255
256     ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
257
258     ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL),
259        "A valid hdc has to require a valid rc\n");
260
261     ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL),
262        "A null hdc does not require a valid rc\n");
263
264     ret = DeleteEnhMetaFile(hMetafile);
265     ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
266     ret = ReleaseDC(hwnd, hdcDisplay);
267     ok( ret, "ReleaseDC error %d\n", GetLastError());
268     DestroyWindow(hwnd);
269 }
270
271 struct eto_scale_test_record
272 {
273     INT graphics_mode;
274     INT map_mode;
275     double ex_scale;
276     double ey_scale;
277     BOOL processed;
278 };
279
280 static int CALLBACK eto_scale_enum_proc(HDC hdc, HANDLETABLE *handle_table,
281     const ENHMETARECORD *emr, int n_objs, LPARAM param)
282 {
283     struct eto_scale_test_record *test = (struct eto_scale_test_record*)param;
284
285     if (emr->iType == EMR_EXTTEXTOUTW)
286     {
287         const EMREXTTEXTOUTW *pExtTextOutW = (const EMREXTTEXTOUTW *)emr;
288         trace("gm %d, mm %d, scale %f, %f, expected %f, %f\n",
289               test->graphics_mode, test->map_mode,
290               pExtTextOutW->exScale, pExtTextOutW->eyScale,
291               test->ex_scale, test->ey_scale);
292         ok(fabs(test->ex_scale - pExtTextOutW->exScale) < 0.001,
293            "Got exScale %f, expected %f\n", pExtTextOutW->exScale, test->ex_scale);
294         ok(fabs(test->ey_scale - pExtTextOutW->eyScale) < 0.001,
295            "Got eyScale %f, expected %f\n", pExtTextOutW->eyScale, test->ey_scale);
296         test->processed = TRUE;
297     }
298
299     return 1;
300 }
301
302 static void test_ExtTextOutScale(void)
303 {
304     const RECT rc = { 0, 0, 100, 100 };
305     const WCHAR str[] = {'a',0 };
306     struct eto_scale_test_record test;
307     HDC hdcDisplay, hdcMetafile;
308     HENHMETAFILE hMetafile;
309     HWND hwnd;
310     SIZE wndext, vportext;
311     int horzSize, vertSize, horzRes, vertRes;
312     int ret;
313     int i;
314
315     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
316                            0, 0, 200, 200, 0, 0, 0, NULL);
317     ok(hwnd != 0, "CreateWindowExA failed\n");
318
319     hdcDisplay = GetDC(hwnd);
320     ok(hdcDisplay != 0, "GetDC failed\n");
321
322     horzSize = GetDeviceCaps(hdcDisplay, HORZSIZE);
323     horzRes  = GetDeviceCaps(hdcDisplay, HORZRES);
324     vertSize = GetDeviceCaps(hdcDisplay, VERTSIZE);
325     vertRes  = GetDeviceCaps(hdcDisplay, VERTRES);
326     ok(horzSize && horzRes && vertSize && vertRes, "GetDeviceCaps failed\n");
327
328     for (i = 0; i < 16; i++)
329     {
330         test.graphics_mode = i / 8 + 1;
331         test.map_mode      = i % 8 + 1;
332
333         ret = SetGraphicsMode(hdcDisplay, test.graphics_mode);
334         ok(ret, "SetGraphicsMode failed\n");
335         ret = SetMapMode(hdcDisplay, test.map_mode);
336         ok(ret, "SetMapMode failed\n");
337
338         if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
339         {
340             ret = SetWindowExtEx(hdcDisplay, 1, 1, NULL);
341             ok(ret, "SetWindowExtEx failed\n");
342             ret = SetViewportExtEx(hdcDisplay, -20, -10, NULL);
343             ok(ret, "SetViewportExtEx failed\n");
344         }
345
346         ret = GetViewportExtEx(hdcDisplay, &vportext);
347         ok(ret, "GetViewportExtEx failed\n");
348         ret = GetWindowExtEx(hdcDisplay, &wndext);
349         ok(ret, "GetWindowExtEx failed\n");
350
351         trace("gm %d, mm %d, wnd %d,%d, vp %d,%d horz %d,%d vert %d,%d\n",
352                test.graphics_mode, test.map_mode,
353                wndext.cx, wndext.cy, vportext.cx, vportext.cy,
354                horzSize, horzRes, vertSize, vertRes);
355
356         if (test.graphics_mode == GM_COMPATIBLE)
357         {
358             test.ex_scale = 100.0 * ((FLOAT)horzSize  / (FLOAT)horzRes) /
359                                     ((FLOAT)wndext.cx / (FLOAT)vportext.cx);
360             test.ey_scale = 100.0 * ((FLOAT)vertSize  / (FLOAT)vertRes) /
361                                     ((FLOAT)wndext.cy / (FLOAT)vportext.cy);
362         }
363         else
364         {
365             test.ex_scale = 0.0;
366             test.ey_scale = 0.0;
367         }
368
369         hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
370         ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
371
372         ret = SetGraphicsMode(hdcMetafile, test.graphics_mode);
373         ok(ret, "SetGraphicsMode failed\n");
374         ret = SetMapMode(hdcMetafile, test.map_mode);
375         ok(ret, "SetMapMode failed\n");
376
377         if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
378         {
379             ret = SetWindowExtEx(hdcMetafile, 1, 1, NULL);
380             ok(ret, "SetWindowExtEx failed\n");
381             ret = SetViewportExtEx(hdcMetafile, -20, -10, NULL);
382             ok(ret, "SetViewportExtEx failed\n");
383         }
384
385         ret = ExtTextOutW(hdcMetafile, 0, 0, 0, 0, str, 1, NULL);
386         ok(ret, "ExtTextOutW failed\n");
387
388         hMetafile = CloseEnhMetaFile(hdcMetafile);
389         ok(hMetafile != 0, "CloseEnhMetaFile failed\n");
390
391         test.processed = 0;
392         ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_scale_enum_proc, &test, &rc);
393         ok(ret, "EnumEnhMetaFile failed\n");
394         ok(test.processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTW record\n");
395
396         ret = DeleteEnhMetaFile(hMetafile);
397         ok(ret, "DeleteEnhMetaFile failed\n");
398     }
399
400     ret = ReleaseDC(hwnd, hdcDisplay);
401     ok(ret, "ReleaseDC failed\n");
402     DestroyWindow(hwnd);
403 }
404
405
406 static void check_dc_state(HDC hdc, int restore_no,
407                            int wnd_org_x, int wnd_org_y, int wnd_ext_x, int wnd_ext_y,
408                            int vp_org_x, int vp_org_y, int vp_ext_x, int vp_ext_y)
409 {
410     BOOL ret;
411     XFORM xform;
412     POINT vp_org, win_org;
413     SIZE vp_size, win_size;
414     FLOAT xscale, yscale, edx, edy;
415
416     SetLastError(0xdeadbeef);
417     ret = GetWorldTransform(hdc, &xform);
418     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) goto win9x_here;
419     ok(ret, "GetWorldTransform error %u\n", GetLastError());
420
421     trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no, xform.eM11, xform.eM22, xform.eDx, xform.eDy);
422
423     ok(xform.eM12 == 0.0, "%d: expected eM12 0.0, got %f\n", restore_no, xform.eM12);
424     ok(xform.eM21 == 0.0, "%d: expected eM21 0.0, got %f\n", restore_no, xform.eM21);
425
426     xscale = (FLOAT)vp_ext_x / (FLOAT)wnd_ext_x;
427     trace("x scale %f\n", xscale);
428     ok(fabs(xscale - xform.eM11) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
429        restore_no, vp_ext_x, wnd_ext_x, xform.eM11);
430
431     yscale = (FLOAT)vp_ext_y / (FLOAT)wnd_ext_y;
432     trace("y scale %f\n", yscale);
433     ok(fabs(yscale - xform.eM22) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
434        restore_no, vp_ext_y, wnd_ext_y, xform.eM22);
435
436     edx = (FLOAT)vp_org_x - xform.eM11 * (FLOAT)wnd_org_x;
437     ok(fabs(edx - xform.eDx) < 0.01, "%d: edx %f != eDx %f\n", restore_no, edx, xform.eDx);
438     edy = (FLOAT)vp_org_y - xform.eM22 * (FLOAT)wnd_org_y;
439     ok(fabs(edy - xform.eDy) < 0.01, "%d: edy %f != eDy %f\n", restore_no, edy, xform.eDy);
440
441     return;
442
443 win9x_here:
444
445     GetWindowOrgEx(hdc, &win_org);
446     GetViewportOrgEx(hdc, &vp_org);
447     GetWindowExtEx(hdc, &win_size);
448     GetViewportExtEx(hdc, &vp_size);
449
450     ok(wnd_org_x == win_org.x, "%d: wnd_org_x: %d != %d\n", restore_no, wnd_org_x, win_org.x);
451     ok(wnd_org_y == win_org.y, "%d: wnd_org_y: %d != %d\n", restore_no, wnd_org_y, win_org.y);
452
453     ok(vp_org_x == vp_org.x, "%d: vport_org_x: %d != %d\n", restore_no, vp_org_x, vp_org.x);
454     ok(vp_org_y == vp_org.y, "%d: vport_org_y: %d != %d\n", restore_no, vp_org_y, vp_org.y);
455
456     ok(wnd_ext_x == win_size.cx, "%d: wnd_ext_x: %d != %d\n", restore_no, wnd_ext_x, win_size.cx);
457     ok(wnd_ext_y == win_size.cy, "%d: wnd_ext_y: %d != %d\n", restore_no, wnd_ext_y, win_size.cy);
458
459     ok(vp_ext_x == vp_size.cx, "%d: vport_ext_x: %d != %d\n", restore_no, vp_ext_x, vp_size.cx);
460     ok(vp_ext_y == vp_size.cy, "%d: vport_ext_y: %d != %d\n", restore_no, vp_ext_y, vp_size.cy);
461 }
462
463 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
464                                          const ENHMETARECORD *emr, int n_objs, LPARAM param)
465 {
466     BOOL ret;
467     XFORM xform;
468     POINT pt;
469     SIZE size;
470     static int save_state;
471     static int restore_no;
472     static int select_no;
473
474     trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
475            hdc, emr->iType, emr->nSize, (void *)param);
476
477     trace("BEFORE:\n");
478     SetLastError(0xdeadbeef);
479     ret = GetWorldTransform(hdc, &xform);
480     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
481     {
482         ret = GetWindowOrgEx(hdc, &pt);
483         ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
484         trace("window org (%d,%d)\n", pt.x, pt.y);
485         ret = GetViewportOrgEx(hdc, &pt);
486         ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
487         trace("vport org (%d,%d)\n", pt.x, pt.y);
488         ret = GetWindowExtEx(hdc, &size);
489         ok(ret, "GetWindowExtEx error %u\n", GetLastError());
490         trace("window ext (%d,%d)\n", size.cx, size.cy);
491         ret = GetViewportExtEx(hdc, &size);
492         ok(ret, "GetViewportExtEx error %u\n", GetLastError());
493         trace("vport ext (%d,%d)\n", size.cx, size.cy);
494     }
495     else
496     {
497         ok(ret, "GetWorldTransform error %u\n", GetLastError());
498         trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
499     }
500
501     PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
502
503     switch (emr->iType)
504     {
505     case EMR_HEADER:
506     {
507         static RECT exp_bounds = { 0, 0, 150, 150 };
508         RECT bounds;
509         const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr;
510
511         trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
512                emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom,
513                emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom);
514         trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy,
515                emf->szlDevice.cx, emf->szlDevice.cy);
516
517         SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom);
518         ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n");
519
520         save_state = 0;
521         restore_no = 0;
522         select_no = 0;
523         check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1);
524         break;
525     }
526
527     case EMR_LINETO:
528         {
529             const EMRLINETO *line = (const EMRLINETO *)emr;
530             trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x);
531             break;
532         }
533     case EMR_SETWINDOWORGEX:
534         {
535             const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr;
536             trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
537             break;
538         }
539     case EMR_SETWINDOWEXTEX:
540         {
541             const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr;
542             trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
543             break;
544         }
545     case EMR_SETVIEWPORTORGEX:
546         {
547             const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
548             trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
549             break;
550         }
551     case EMR_SETVIEWPORTEXTEX:
552         {
553             const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr;
554             trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
555             break;
556         }
557     case EMR_SAVEDC:
558         save_state++;
559         trace("EMR_SAVEDC\n");
560         break;
561
562     case EMR_RESTOREDC:
563         {
564             const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
565             trace("EMR_RESTOREDC: %d\n", restoredc->iRelative);
566
567             switch(++restore_no)
568             {
569             case 1:
570                 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
571                 check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
572                 break;
573             case 2:
574                 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
575                 check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
576                 break;
577             case 3:
578                 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
579                 check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
580                 break;
581             }
582             ok(restore_no <= 3, "restore_no %d\n", restore_no);
583             save_state += restoredc->iRelative;
584             break;
585         }
586     case EMR_SELECTOBJECT:
587         {
588             const EMRSELECTOBJECT *selectobj = (const EMRSELECTOBJECT*)emr;
589             trace("EMR_SELECTOBJECT: %x\n",selectobj->ihObject);
590             select_no ++;
591             break;
592         }
593     case EMR_EOF:
594         ok(save_state == 0, "EOF save_state %d\n", save_state);
595         ok(select_no == 3, "Too many/few selects  %i\n",select_no);
596         break;
597     }
598
599     trace("AFTER:\n");
600     SetLastError(0xdeadbeef);
601     ret = GetWorldTransform(hdc, &xform);
602     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
603     {
604         ret = GetWindowOrgEx(hdc, &pt);
605         ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
606         trace("window org (%d,%d)\n", pt.x, pt.y);
607         ret = GetViewportOrgEx(hdc, &pt);
608         ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
609         trace("vport org (%d,%d)\n", pt.x, pt.y);
610         ret = GetWindowExtEx(hdc, &size);
611         ok(ret, "GetWindowExtEx error %u\n", GetLastError());
612         trace("window ext (%d,%d)\n", size.cx, size.cy);
613         ret = GetViewportExtEx(hdc, &size);
614         ok(ret, "GetViewportExtEx error %u\n", GetLastError());
615         trace("vport ext (%d,%d)\n", size.cx, size.cy);
616     }
617     else
618     {
619         ok(ret, "GetWorldTransform error %u\n", GetLastError());
620         trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
621     }
622
623     return 1;
624 }
625
626 static void test_SaveDC(void)
627 {
628     HDC hdcMetafile, hdcDisplay;
629     HENHMETAFILE hMetafile;
630     HWND hwnd;
631     int ret;
632     POINT pt;
633     SIZE size;
634     HFONT hFont,hFont2,hFontOld,hFontCheck;
635     static const RECT rc = { 0, 0, 150, 150 };
636
637     /* Win9x doesn't play EMFs on invisible windows */
638     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
639                            0, 0, 200, 200, 0, 0, 0, NULL);
640     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
641
642     hdcDisplay = GetDC(hwnd);
643     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
644
645     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
646     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
647
648     SetMapMode(hdcMetafile, MM_ANISOTROPIC);
649
650     /* Need to write something to the emf, otherwise Windows won't play it back */
651     LineTo(hdcMetafile, 150, 150);
652
653     SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
654     SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
655     SetWindowExtEx(hdcMetafile, 110, 110, NULL );
656     SetViewportExtEx(hdcMetafile, 120, 120, NULL );
657
658     /* Force Win9x to update DC state */
659     SetPixelV(hdcMetafile, 50, 50, 0);
660
661     ret = GetViewportOrgEx(hdcMetafile, &pt);
662     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
663     ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
664     ret = GetViewportExtEx(hdcMetafile, &size);
665     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
666     ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
667     ret = SaveDC(hdcMetafile);
668     ok(ret == 1, "ret = %d\n", ret);
669
670     SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
671     SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
672     SetWindowExtEx(hdcMetafile, 150, 150, NULL );
673     SetViewportExtEx(hdcMetafile, 200, 200, NULL );
674
675     /* Force Win9x to update DC state */
676     SetPixelV(hdcMetafile, 50, 50, 0);
677
678     ret = GetViewportOrgEx(hdcMetafile, &pt);
679     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
680     ok(pt.x == 10,"Expecting ViewportOrg x of 10, got %i\n",pt.x);
681     ret = GetViewportExtEx(hdcMetafile, &size);
682     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
683     ok(size.cx == 200,"Expecting ViewportExt cx of 200, got %i\n",size.cx);
684     ret = SaveDC(hdcMetafile);
685     ok(ret == 2, "ret = %d\n", ret);
686
687     SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
688     SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
689     SetWindowExtEx(hdcMetafile, 120, 120, NULL );
690     SetViewportExtEx(hdcMetafile, 300, 300, NULL );
691     SetPolyFillMode( hdcMetafile, ALTERNATE );
692     SetBkColor( hdcMetafile, 0 );
693
694     /* Force Win9x to update DC state */
695     SetPixelV(hdcMetafile, 50, 50, 0);
696
697     ret = GetViewportOrgEx(hdcMetafile, &pt);
698     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
699     ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
700     ret = GetViewportExtEx(hdcMetafile, &size);
701     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
702     ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
703     ret = SaveDC(hdcMetafile);
704     ok(ret == 3, "ret = %d\n", ret);
705
706     SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
707     SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
708     SetWindowExtEx(hdcMetafile, 200, 200, NULL );
709     SetViewportExtEx(hdcMetafile, 400, 400, NULL );
710
711     SetPolyFillMode( hdcMetafile, WINDING );
712     SetBkColor( hdcMetafile, 0x123456 );
713     ok( GetPolyFillMode( hdcMetafile ) == WINDING, "PolyFillMode not restored\n" );
714     ok( GetBkColor( hdcMetafile ) == 0x123456, "Background color not restored\n" );
715
716     /* Force Win9x to update DC state */
717     SetPixelV(hdcMetafile, 50, 50, 0);
718
719     ret = GetViewportOrgEx(hdcMetafile, &pt);
720     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
721     ok(pt.x == 30,"Expecting ViewportOrg x of 30, got %i\n",pt.x);
722     ret = GetViewportExtEx(hdcMetafile, &size);
723     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
724     ok(size.cx == 400,"Expecting ViewportExt cx of 400, got %i\n",size.cx);
725     ret = RestoreDC(hdcMetafile, -1);
726     ok(ret, "ret = %d\n", ret);
727
728     ret = GetViewportOrgEx(hdcMetafile, &pt);
729     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
730     ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
731     ret = GetViewportExtEx(hdcMetafile, &size);
732     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
733     ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
734     ok( GetPolyFillMode( hdcMetafile ) == ALTERNATE, "PolyFillMode not restored\n" );
735     ok( GetBkColor( hdcMetafile ) == 0, "Background color not restored\n" );
736     ret = SaveDC(hdcMetafile);
737     ok(ret == 3, "ret = %d\n", ret);
738
739     ret = GetViewportOrgEx(hdcMetafile, &pt);
740     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
741     ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
742     ret = GetViewportExtEx(hdcMetafile, &size);
743     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
744     ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
745     ret = RestoreDC(hdcMetafile, 1);
746     ok(ret, "ret = %d\n", ret);
747     ret = GetViewportOrgEx(hdcMetafile, &pt);
748     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
749     ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
750     ret = GetViewportExtEx(hdcMetafile, &size);
751     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
752     ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
753
754     SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
755     SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
756     SetWindowExtEx(hdcMetafile, 500, 500, NULL );
757     SetViewportExtEx(hdcMetafile, 50, 50, NULL );
758
759     /* Force Win9x to update DC state */
760     SetPixelV(hdcMetafile, 50, 50, 0);
761
762     ret = GetViewportOrgEx(hdcMetafile, &pt);
763     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
764     ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
765     ret = GetViewportExtEx(hdcMetafile, &size);
766     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
767     ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
768     ret = SaveDC(hdcMetafile);
769     ok(ret == 1, "ret = %d\n", ret);
770
771     ret = GetViewportOrgEx(hdcMetafile, &pt);
772     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
773     ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
774     ret = GetViewportExtEx(hdcMetafile, &size);
775     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
776     ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
777     ret = SaveDC(hdcMetafile);
778     ok(ret == 2, "ret = %d\n", ret);
779
780     memset(&orig_lf, 0, sizeof(orig_lf));
781     orig_lf.lfCharSet = ANSI_CHARSET;
782     orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
783     orig_lf.lfWeight = FW_DONTCARE;
784     orig_lf.lfHeight = 7;
785     orig_lf.lfQuality = DEFAULT_QUALITY;
786     lstrcpyA(orig_lf.lfFaceName, "Arial");
787     hFont = CreateFontIndirectA(&orig_lf);
788     ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
789
790     hFontOld = SelectObject(hdcMetafile, hFont);
791
792     hFont2 = CreateFontIndirectA(&orig_lf);
793     ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
794     hFontCheck = SelectObject(hdcMetafile, hFont2);
795     ok(hFontCheck == hFont, "Font not selected\n");
796
797     /* Force Win9x to update DC state */
798     SetPixelV(hdcMetafile, 50, 50, 0);
799
800     ret = RestoreDC(hdcMetafile, 1);
801     ok(ret, "ret = %d\n", ret);
802     ret = GetViewportOrgEx(hdcMetafile, &pt);
803     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
804     ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
805     ret = GetViewportExtEx(hdcMetafile, &size);
806     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
807     ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
808
809     hFontCheck = SelectObject(hdcMetafile, hFontOld);
810     ok(hFontOld == hFontCheck && hFontCheck != hFont && hFontCheck != hFont2,
811        "Font not reverted with DC Restore\n");
812
813     ret = RestoreDC(hdcMetafile, -20);
814     ok(!ret, "ret = %d\n", ret);
815     ret = RestoreDC(hdcMetafile, 20);
816     ok(!ret, "ret = %d\n", ret);
817
818     hMetafile = CloseEnhMetaFile(hdcMetafile);
819     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
820
821     ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
822     ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
823
824     ret = DeleteObject(hFont);
825     ok( ret, "DeleteObject error %d\n", GetLastError());
826     ret = DeleteObject(hFont2);
827     ok( ret, "DeleteObject error %d\n", GetLastError());
828     ret = DeleteEnhMetaFile(hMetafile);
829     ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
830     ret = ReleaseDC(hwnd, hdcDisplay);
831     ok( ret, "ReleaseDC error %d\n", GetLastError());
832     DestroyWindow(hwnd);
833 }
834
835 static void test_mf_SaveDC(void)
836 {
837     HDC hdcMetafile;
838     HMETAFILE hMetafile;
839     int ret;
840     POINT pt;
841     SIZE size;
842     HFONT hFont,hFont2,hFontOld,hFontCheck;
843
844     hdcMetafile = CreateMetaFileA(NULL);
845     ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
846
847     ret = SetMapMode(hdcMetafile, MM_ANISOTROPIC);
848     ok (ret, "SetMapMode should not fail\n");
849
850     /* Need to write something to the emf, otherwise Windows won't play it back */
851     LineTo(hdcMetafile, 150, 150);
852
853     pt.x = pt.y = 5555;
854     SetWindowOrgEx(hdcMetafile, 0, 0, &pt);
855     ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y);
856     pt.x = pt.y = 5555;
857     SetViewportOrgEx(hdcMetafile, 0, 0, &pt);
858     ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y);
859     size.cx = size.cy = 5555;
860     SetWindowExtEx(hdcMetafile, 110, 110, &size );
861     ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy );
862     size.cx = size.cy = 5555;
863     SetViewportExtEx(hdcMetafile, 120, 120, &size );
864     ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy );
865
866     /* Force Win9x to update DC state */
867     SetPixelV(hdcMetafile, 50, 50, 0);
868
869     ret = GetViewportOrgEx(hdcMetafile, &pt);
870     todo_wine ok (!ret, "GetViewportOrgEx should fail\n");
871     ret = GetViewportExtEx(hdcMetafile, &size);
872     todo_wine ok (!ret, "GetViewportExtEx should fail\n");
873     ret = SaveDC(hdcMetafile);
874     ok(ret == 1, "ret = %d\n", ret);
875
876     SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
877     SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
878     SetWindowExtEx(hdcMetafile, 150, 150, NULL );
879     SetViewportExtEx(hdcMetafile, 200, 200, NULL );
880
881     /* Force Win9x to update DC state */
882     SetPixelV(hdcMetafile, 50, 50, 0);
883
884     ret = SaveDC(hdcMetafile);
885     ok(ret == 1, "ret = %d\n", ret);
886
887     SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
888     SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
889     SetWindowExtEx(hdcMetafile, 120, 120, NULL );
890     SetViewportExtEx(hdcMetafile, 300, 300, NULL );
891
892     /* Force Win9x to update DC state */
893     SetPixelV(hdcMetafile, 50, 50, 0);
894     SetPolyFillMode( hdcMetafile, ALTERNATE );
895     SetBkColor( hdcMetafile, 0 );
896
897     ret = SaveDC(hdcMetafile);
898     ok(ret == 1, "ret = %d\n", ret);
899
900     SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
901     SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
902     SetWindowExtEx(hdcMetafile, 200, 200, NULL );
903     SetViewportExtEx(hdcMetafile, 400, 400, NULL );
904
905     SetPolyFillMode( hdcMetafile, WINDING );
906     SetBkColor( hdcMetafile, 0x123456 );
907     todo_wine ok( !GetPolyFillMode( hdcMetafile ), "GetPolyFillMode succeeded\n" );
908     todo_wine ok( GetBkColor( hdcMetafile ) == CLR_INVALID, "GetBkColor succeeded\n" );
909
910     /* Force Win9x to update DC state */
911     SetPixelV(hdcMetafile, 50, 50, 0);
912
913     ret = RestoreDC(hdcMetafile, -1);
914     ok(ret, "ret = %d\n", ret);
915
916     ret = SaveDC(hdcMetafile);
917     ok(ret == 1, "ret = %d\n", ret);
918
919     ret = RestoreDC(hdcMetafile, 1);
920     ok(ret, "ret = %d\n", ret);
921
922     SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
923     SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
924     SetWindowExtEx(hdcMetafile, 500, 500, NULL );
925     SetViewportExtEx(hdcMetafile, 50, 50, NULL );
926
927     /* Force Win9x to update DC state */
928     SetPixelV(hdcMetafile, 50, 50, 0);
929
930     ret = SaveDC(hdcMetafile);
931     ok(ret == 1, "ret = %d\n", ret);
932
933     ret = SaveDC(hdcMetafile);
934     ok(ret == 1, "ret = %d\n", ret);
935
936     memset(&orig_lf, 0, sizeof(orig_lf));
937     orig_lf.lfCharSet = ANSI_CHARSET;
938     orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
939     orig_lf.lfWeight = FW_DONTCARE;
940     orig_lf.lfHeight = 7;
941     orig_lf.lfQuality = DEFAULT_QUALITY;
942     lstrcpyA(orig_lf.lfFaceName, "Arial");
943     hFont = CreateFontIndirectA(&orig_lf);
944     ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
945
946     hFontOld = SelectObject(hdcMetafile, hFont);
947
948     hFont2 = CreateFontIndirectA(&orig_lf);
949     ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
950     hFontCheck = SelectObject(hdcMetafile, hFont2);
951     ok(hFontCheck == hFont, "Font not selected\n");
952
953     /* Force Win9x to update DC state */
954     SetPixelV(hdcMetafile, 50, 50, 0);
955
956     ret = RestoreDC(hdcMetafile, 1);
957     ok(ret, "ret = %d\n", ret);
958
959     hFontCheck = SelectObject(hdcMetafile, hFontOld);
960     ok(hFontOld != hFontCheck && hFontCheck == hFont2, "Font incorrectly reverted with DC Restore\n");
961
962     /* restore level is ignored */
963     ret = RestoreDC(hdcMetafile, -20);
964     ok(ret, "ret = %d\n", ret);
965     ret = RestoreDC(hdcMetafile, 20);
966     ok(ret, "ret = %d\n", ret);
967     ret = RestoreDC(hdcMetafile, 0);
968     ok(ret, "ret = %d\n", ret);
969
970     hMetafile = CloseMetaFile(hdcMetafile);
971     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
972
973     ret = DeleteMetaFile(hMetafile);
974     ok( ret, "DeleteMetaFile error %d\n", GetLastError());
975     ret = DeleteObject(hFont);
976     ok( ret, "DeleteObject error %d\n", GetLastError());
977     ret = DeleteObject(hFont2);
978     ok( ret, "DeleteObject error %d\n", GetLastError());
979 }
980
981
982 /* Win-format metafile (mfdrv) tests */
983 /* These tests compare the generated metafiles byte-by-byte */
984 /* with the nominal results. */
985
986 /* Maximum size of sample metafiles in bytes. */
987 #define MF_BUFSIZE 512
988
989 /* 8x8 bitmap data for a pattern brush */
990 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
991     0x01, 0x00, 0x02, 0x00,
992     0x03, 0x00, 0x04, 0x00,
993     0x05, 0x00, 0x06, 0x00,
994     0x07, 0x00, 0x08, 0x00
995 };
996
997 /* Sample metafiles to be compared to the outputs of the
998  * test functions.
999  */
1000
1001 static const unsigned char MF_BLANK_BITS[] = {
1002     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
1003     0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1004     0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
1005 };
1006
1007 static const unsigned char MF_GRAPHICS_BITS[] = {
1008     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
1009     0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1010     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
1011     0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
1012     0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
1013     0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
1014     0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
1015     0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
1016     0x00, 0x00, 0x00, 0x00
1017 };
1018
1019 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
1020     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
1021     0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
1022     0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
1023     0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1024     0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1025     0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1026     0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1027     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1028     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1029     0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
1030     0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1031     0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1032     0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1033     0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1034     0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1035     0x00, 0x00
1036 };
1037
1038 static const unsigned char MF_DCBRUSH_BITS[] =
1039 {
1040     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2a, 0x00,
1041     0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00,
1042     0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xfc, 0x02,
1043     0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
1044     0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00,
1045     0x08, 0x00, 0x00, 0x00, 0xfa, 0x02, 0x00, 0x00,
1046     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1047     0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x01, 0x00,
1048     0x07, 0x00, 0x00, 0x00, 0x1b, 0x04, 0x14, 0x00,
1049     0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x03, 0x00,
1050     0x00, 0x00, 0x00, 0x00
1051 };
1052
1053 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
1054 {
1055     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
1056     0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1057     0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
1058     0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
1059     0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
1060     0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
1061     0x00, 0x00
1062 };
1063
1064 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
1065 {
1066     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1067     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1068     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1069     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1070     0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
1071     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1072     0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1073     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1074     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1075     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1076     0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1077     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1078     0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1079     0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
1080     0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
1081     0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1082     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1083     0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
1084     0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
1085     0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1086     0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
1087     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1088     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1089     0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
1090     0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
1091     0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1092     0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1093     0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1094     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1095     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1096     0x14, 0x00, 0x00, 0x00
1097 };
1098
1099 static const unsigned char MF_LINETO_BITS[] = {
1100     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1101     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1102     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1103     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1104     0x00, 0x00
1105 };
1106
1107 static const unsigned char EMF_LINETO_BITS[] = {
1108     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1109     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1110     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1111     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1112     0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1113     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1114     0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1115     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1116     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1117     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1118     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1119     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1120     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1121     0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1122     0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1123     0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1124     0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
1125     0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1126     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1127     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1128     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1129     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1130     0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1131     0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1132     0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1133     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1134     0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1135     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1136     0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1137     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1138     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1139     0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1140     0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1141     0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1142     0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1143     0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1144     0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1145     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1146     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1147 };
1148
1149 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
1150     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1151     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1152     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1153     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1154     0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1155     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1156     0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1157     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1158     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1159     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1160     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1161     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1162     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1163     0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1164     0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1165     0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1166     0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
1167     0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1168     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1169     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1170     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1171     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1172     0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1173     0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1174     0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1175     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1176     0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1177     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1178     0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1179     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1180     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1181     0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1182     0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1183     0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1184     0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1185     0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1186     0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1187     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1188     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1189 };
1190
1191 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
1192     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1193     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1194     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1195     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1196     0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1197     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1198     0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1199     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1200     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1201     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1202     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1203     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1204     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1205     0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
1206     0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1207     0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1208     0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1209     0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1210     0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
1211     0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1212     0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
1213     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1214     0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
1215     0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
1216     0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1217     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1218     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1219     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1220     0x14, 0x00, 0x00, 0x00
1221 };
1222
1223 static const unsigned char EMF_BITBLT[] =
1224 {
1225     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1226     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1227     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1228     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1229     0x6a, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00,
1230     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1231     0xa0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1232     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1233     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1234     0x23, 0x04, 0x00, 0x00, 0x3b, 0x02, 0x00, 0x00,
1235     0x75, 0x01, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00,
1236     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1237     0x00, 0x00, 0x00, 0x00, 0x08, 0xb1, 0x05, 0x00,
1238     0x28, 0x11, 0x03, 0x00, 0x4c, 0x00, 0x00, 0x00,
1239     0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1240     0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1241     0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1242     0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1243     0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1244     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1245     0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1246     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1247     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1248     0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1249     0x64, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1250     0x8c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1251     0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1252     0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1253     0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1254     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1255     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1256     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1257     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1258     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1259     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1260     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1261     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1262     0x4c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1263     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1264     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1265     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1266     0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1267     0x62, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1268     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1269     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1270     0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1271     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1272     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1273     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1274     0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1275     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1276     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1277 };
1278
1279 static const unsigned char EMF_DCBRUSH_BITS[] =
1280 {
1281     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1282     0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1283     0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1284     0x39, 0x01, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00,
1285     0x52, 0x02, 0x00, 0x00, 0x52, 0x02, 0x00, 0x00,
1286     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1287     0x44, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1288     0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1289     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1290     0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
1291     0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1292     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1293     0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1294     0x80, 0xa9, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00,
1295     0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x80,
1296     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1297     0x13, 0x00, 0x00, 0x80, 0x27, 0x00, 0x00, 0x00,
1298     0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1299     0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x00,
1300     0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1301     0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1302     0x26, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
1303     0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1304     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1305     0x33, 0x44, 0x55, 0x00, 0x25, 0x00, 0x00, 0x00,
1306     0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1307     0x2b, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
1308     0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1309     0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1310     0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1311     0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1312     0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1313     0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x00,
1314     0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1315     0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1316     0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1317     0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1318     0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1319     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1320     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1321     0x14, 0x00, 0x00, 0x00
1322 };
1323
1324 /* For debugging or dumping the raw metafiles produced by
1325  * new test functions.
1326  */
1327 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
1328                                  INT nobj, LPARAM param)
1329 {
1330     trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1331            hdc, mr->rdFunction, mr->rdSize, (void *)param);
1332     return TRUE;
1333 }
1334
1335 /* For debugging or dumping the raw metafiles produced by
1336  * new test functions.
1337  */
1338
1339 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
1340 {
1341     BYTE buf[MF_BUFSIZE];
1342     UINT mfsize, i;
1343
1344     if (!winetest_debug) return;
1345
1346     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1347     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1348
1349     printf ("MetaFile %s has bits:\n{\n    ", desc);
1350     for (i=0; i<mfsize; i++)
1351     {
1352         printf ("0x%02x", buf[i]);
1353         if (i == mfsize-1)
1354             printf ("\n");
1355         else if (i % 8 == 7)
1356             printf (",\n    ");
1357         else
1358             printf (", ");
1359     }
1360     printf ("};\n");
1361 }
1362
1363 /* Compare the metafile produced by a test function with the
1364  * expected raw metafile data in "bits".
1365  * Return value is 0 for a perfect match,
1366  * -1 if lengths aren't equal,
1367  * otherwise returns the number of non-matching bytes.
1368  */
1369
1370 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
1371     const char *desc)
1372 {
1373     unsigned char buf[MF_BUFSIZE];
1374     UINT mfsize, i;
1375     int diff;
1376
1377     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1378     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1379     if (mfsize < MF_BUFSIZE)
1380         ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
1381             desc, mfsize, bsize);
1382     else
1383         ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1384             desc, mfsize, bsize);
1385     if (mfsize != bsize)
1386         return -1;
1387
1388     diff = 0;
1389     for (i=0; i<bsize; i++)
1390     {
1391        if (buf[i] !=  bits[i])
1392            diff++;
1393     }
1394     ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1395         desc, mfsize, bsize, diff);
1396
1397     return diff; 
1398 }
1399
1400 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
1401 {
1402     unsigned char buf[MF_BUFSIZE];
1403     DWORD mfsize, rd_size, i;
1404     int diff;
1405     HANDLE hfile;
1406     BOOL ret;
1407
1408     hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1409     assert(hfile != INVALID_HANDLE_VALUE);
1410
1411     mfsize = GetFileSize(hfile, NULL);
1412     assert(mfsize <= MF_BUFSIZE);
1413
1414     ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
1415     ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
1416
1417     CloseHandle(hfile);
1418
1419     ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
1420
1421     if (mfsize != bsize)
1422         return -1;
1423
1424     diff = 0;
1425     for (i=0; i<bsize; i++)
1426     {
1427         if (buf[i] != bits[i])
1428             diff++;
1429     }
1430     ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1431         desc, mfsize, bsize, diff);
1432
1433     return diff; 
1434 }
1435
1436 /* For debugging or dumping the raw EMFs produced by
1437  * new test functions.
1438  */
1439 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
1440 {
1441     BYTE buf[MF_BUFSIZE];
1442     UINT mfsize, i;
1443
1444     if (!winetest_debug) return;
1445
1446     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1447     ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
1448
1449     printf("EMF %s has bits:\n{\n    ", desc);
1450     for (i = 0; i < mfsize; i++)
1451     {
1452         printf ("0x%02x", buf[i]);
1453         if (i == mfsize-1)
1454             printf ("\n");
1455         else if (i % 8 == 7)
1456             printf (",\n    ");
1457         else
1458             printf (", ");
1459     }
1460     printf ("};\n");
1461 }
1462
1463 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
1464 {
1465     BYTE *emf;
1466     BYTE buf[MF_BUFSIZE];
1467     UINT mfsize, offset;
1468
1469     if (!winetest_debug) return;
1470
1471     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1472     ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1473
1474     printf("EMF %s has records:\n", desc);
1475
1476     emf = buf;
1477     offset = 0;
1478     while(offset < mfsize)
1479     {
1480         EMR *emr = (EMR *)(emf + offset);
1481         printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
1482         /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1483         offset += emr->nSize;
1484     }
1485 }
1486
1487 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
1488 {
1489     const BYTE *buf;
1490     DWORD i;
1491
1492     if (!winetest_debug) return;
1493
1494     printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
1495     buf = (const BYTE *)emr;
1496     for (i = 0; i < emr->nSize; i++)
1497     {
1498         printf ("0x%02x", buf[i]);
1499         if (i == emr->nSize - 1)
1500             printf ("\n");
1501         else if (i % 8 == 7)
1502             printf (",\n");
1503         else
1504             printf (", ");
1505     }
1506     printf ("};\n");
1507 }
1508
1509 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
1510 {
1511     trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
1512           eto->rclBounds.right, eto->rclBounds.bottom);
1513     trace("iGraphicsMode %u\n", eto->iGraphicsMode);
1514     trace("exScale: %f\n", eto->exScale);
1515     trace("eyScale: %f\n", eto->eyScale);
1516     trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
1517     trace("emrtext.nChars %u\n", eto->emrtext.nChars);
1518     trace("emrtext.offString %#x\n", eto->emrtext.offString);
1519     trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
1520     trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
1521           eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
1522     trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
1523 }
1524
1525 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
1526                              const char *desc, BOOL ignore_scaling)
1527 {
1528     int diff;
1529
1530     ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1531        desc, emr1->iType, emr2->iType);
1532
1533     ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1534        desc, emr1->nSize, emr2->nSize);
1535
1536     /* iType and nSize mismatches are fatal */
1537     if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1538
1539     /* contents of EMR_GDICOMMENT are not interesting */
1540     if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1541
1542     /* different Windows versions setup DC scaling differently when
1543      * converting an old style metafile to an EMF.
1544      */
1545     if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1546                            emr1->iType == EMR_SETVIEWPORTEXTEX))
1547         return TRUE;
1548
1549     if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1550     {
1551         EMREXTTEXTOUTW *eto1, *eto2;
1552
1553         eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1554         memcpy(eto1, emr1, emr1->nSize);
1555         eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1556         memcpy(eto2, emr2, emr2->nSize);
1557
1558         /* different Windows versions setup DC scaling differently */
1559         eto1->exScale = eto1->eyScale = 0.0;
1560         eto2->exScale = eto2->eyScale = 0.0;
1561
1562         diff = memcmp(eto1, eto2, emr1->nSize);
1563         if (diff)
1564         {
1565             dump_EMREXTTEXTOUT(eto1);
1566             dump_EMREXTTEXTOUT(eto2);
1567         }
1568         HeapFree(GetProcessHeap(), 0, eto1);
1569         HeapFree(GetProcessHeap(), 0, eto2);
1570     }
1571     else if (emr1->iType == EMR_EXTSELECTCLIPRGN && !lstrcmpA(desc, "emf_clipping"))
1572     {
1573         /* We have to take care of NT4 differences here */
1574         diff = memcmp(emr1, emr2, emr1->nSize);
1575         if (diff)
1576         {
1577             ENHMETARECORD *emr_nt4;
1578
1579             emr_nt4 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1580             memcpy(emr_nt4, emr2, emr2->nSize);
1581             /* Correct the nRgnSize field */
1582             emr_nt4->dParm[5] = sizeof(RECT);
1583
1584             diff = memcmp(emr1, emr_nt4, emr1->nSize);
1585             if (!diff)
1586                 win_skip("Catered for NT4 differences\n");
1587
1588             HeapFree(GetProcessHeap(), 0, emr_nt4);
1589         }
1590     }
1591     else
1592         diff = memcmp(emr1, emr2, emr1->nSize);
1593
1594     ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1595
1596     if (diff)
1597     {
1598         dump_emf_record(emr1, "expected bits");
1599         dump_emf_record(emr2, "actual bits");
1600     }
1601
1602     return diff == 0; /* report all non-fatal record mismatches */
1603 }
1604
1605 /* Compare the EMF produced by a test function with the
1606  * expected raw EMF data in "bits".
1607  * Return value is 0 for a perfect match,
1608  * -1 if lengths aren't equal,
1609  * otherwise returns the number of non-matching bytes.
1610  */
1611 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1612                             UINT bsize, const char *desc,
1613                             BOOL ignore_scaling)
1614 {
1615     unsigned char buf[MF_BUFSIZE];
1616     UINT mfsize, offset1, offset2, diff_nt4, diff_9x;
1617     const ENHMETAHEADER *emh1, *emh2;
1618
1619     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1620     ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1621
1622     /* ENHMETAHEADER size could differ, depending on platform */
1623     diff_nt4 = sizeof(SIZEL);
1624     diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD);
1625
1626     if (mfsize < MF_BUFSIZE)
1627     {
1628         ok(mfsize == bsize ||
1629            broken(mfsize == bsize - diff_nt4) ||  /* NT4 */
1630            broken(mfsize == bsize - diff_9x), /* Win9x/WinME */
1631            "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1632     }
1633     else
1634         ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1635            desc, mfsize, bsize);
1636
1637     /* basic things must match */
1638     emh1 = (const ENHMETAHEADER *)bits;
1639     emh2 = (const ENHMETAHEADER *)buf;
1640     ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1641     ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1642     ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1643     ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1644
1645     ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1646     ok(emh1->nSize == emh2->nSize ||
1647        broken(emh1->nSize - diff_nt4 == emh2->nSize) ||
1648        broken(emh1->nSize - diff_9x == emh2->nSize),
1649        "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1650     ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1651     ok(emh1->nBytes == emh2->nBytes ||
1652        broken(emh1->nBytes - diff_nt4 == emh2->nBytes) ||
1653        broken(emh1->nBytes - diff_9x == emh2->nBytes),
1654        "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1655     ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords);
1656
1657     offset1 = emh1->nSize;
1658     offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */
1659     while (offset1 < emh1->nBytes)
1660     {
1661         const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1);
1662         const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2);
1663
1664         trace("%s: EMF record %u, size %u/record %u, size %u\n",
1665               desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1666
1667         if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1668
1669         /* We have already bailed out if iType or nSize don't match */
1670         offset1 += emr1->nSize;
1671         offset2 += emr2->nSize;
1672     }
1673     return 0;
1674 }
1675
1676
1677 /* tests blitting to an EMF */
1678 static void test_emf_BitBlt(void)
1679 {
1680     HDC hdcDisplay, hdcMetafile, hdcBitmap;
1681     HBITMAP hBitmap, hOldBitmap;
1682     HENHMETAFILE hMetafile;
1683 #define BMP_DIM 4
1684     BITMAPINFOHEADER bmih =
1685     {
1686         sizeof(BITMAPINFOHEADER),
1687         BMP_DIM,/* biWidth */
1688         BMP_DIM,/* biHeight */
1689         1,      /* biPlanes */
1690         24,     /* biBitCount */
1691         BI_RGB, /* biCompression */
1692         0,      /* biXPelsPerMeter */
1693         0,      /* biYPelsPerMeter */
1694         0,      /* biClrUsed */
1695         0,      /* biClrImportant */
1696     };
1697     void *bits;
1698     BOOL ret;
1699
1700     hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL);
1701     ok( hdcDisplay != 0, "CreateDCA error %d\n", GetLastError() );
1702
1703     hdcBitmap = CreateCompatibleDC(hdcDisplay);
1704     ok( hdcBitmap != 0, "CreateCompatibleDC failed\n" );
1705     bmih.biXPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSX), 100, 3937);
1706     bmih.biYPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSY), 100, 3937);
1707     hBitmap = CreateDIBSection(hdcDisplay, (const BITMAPINFO *)&bmih,
1708                                DIB_RGB_COLORS, &bits, NULL, 0);
1709     hOldBitmap = SelectObject(hdcBitmap, hBitmap);
1710
1711     hdcMetafile = CreateEnhMetaFileA(hdcBitmap, NULL, NULL, NULL);
1712     ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1713
1714     /* First fill the bitmap DC with something recognizable, like BLACKNESS */
1715     ret = BitBlt(hdcBitmap, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, BLACKNESS);
1716     ok( ret, "BitBlt(BLACKNESS) failed\n" );
1717
1718     ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, SRCCOPY);
1719     ok( ret, "BitBlt(SRCCOPY) failed\n" );
1720     ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, WHITENESS);
1721     ok( ret, "BitBlt(WHITENESS) failed\n" );
1722
1723     hMetafile = CloseEnhMetaFile(hdcMetafile);
1724     ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1725
1726     if(compare_emf_bits(hMetafile, EMF_BITBLT, sizeof(EMF_BITBLT),
1727         "emf_BitBlt", FALSE) != 0)
1728     {
1729         dump_emf_bits(hMetafile, "emf_BitBlt");
1730         dump_emf_records(hMetafile, "emf_BitBlt");
1731     }
1732
1733     SelectObject(hdcBitmap, hOldBitmap);
1734     DeleteObject(hBitmap);
1735     DeleteDC(hdcBitmap);
1736     DeleteDC(hdcDisplay);
1737 #undef BMP_DIM
1738 }
1739
1740 static void test_emf_DCBrush(void)
1741 {
1742     HDC hdcMetafile;
1743     HENHMETAFILE hMetafile;
1744     HBRUSH hBrush;
1745     HPEN hPen;
1746     BOOL ret;
1747     COLORREF color;
1748
1749     if (!pSetDCBrushColor || !pSetDCPenColor)
1750     {
1751         win_skip( "SetDCBrush/PenColor not supported\n" );
1752         return;
1753     }
1754
1755     hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
1756     ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1757
1758     hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
1759     ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1760
1761     hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
1762     ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
1763
1764     color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
1765     ok( color == 0xffffff, "SetDCBrushColor returned %x\n", color );
1766
1767     color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
1768     ok( color == 0, "SetDCPenColor returned %x\n", color );
1769
1770     Rectangle( hdcMetafile, 10, 10, 20, 20 );
1771
1772     color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
1773     ok( color == 0x555555, "SetDCBrushColor returned %x\n", color );
1774
1775     hMetafile = CloseEnhMetaFile(hdcMetafile);
1776     ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1777
1778     if (compare_emf_bits (hMetafile, EMF_DCBRUSH_BITS, sizeof(EMF_DCBRUSH_BITS),
1779                           "emf_DC_Brush", FALSE ) != 0)
1780     {
1781         dump_emf_bits(hMetafile, "emf_DC_Brush");
1782         dump_emf_records(hMetafile, "emf_DC_Brush");
1783     }
1784     ret = DeleteEnhMetaFile(hMetafile);
1785     ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1786     ret = DeleteObject(hBrush);
1787     ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1788     ret = DeleteObject(hPen);
1789     ok( ret, "DeleteObject(HPEN) error %d\n", GetLastError());
1790 }
1791
1792 /* Test a blank metafile.  May be used as a template for new tests. */
1793
1794 static void test_mf_Blank(void)
1795 {
1796     HDC hdcMetafile;
1797     HMETAFILE hMetafile;
1798     INT caps;
1799     BOOL ret;
1800     INT type;
1801
1802     hdcMetafile = CreateMetaFileA(NULL);
1803     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1804     trace("hdcMetafile %p\n", hdcMetafile);
1805
1806 /* Tests on metafile initialization */
1807     caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
1808     ok (caps == DT_METAFILE,
1809         "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
1810
1811     hMetafile = CloseMetaFile(hdcMetafile);
1812     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1813     type = GetObjectType(hMetafile);
1814     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1815     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1816
1817     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1818         "mf_blank") != 0)
1819     {
1820         dump_mf_bits(hMetafile, "mf_Blank");
1821         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1822     }
1823
1824     ret = DeleteMetaFile(hMetafile);
1825     ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1826 }
1827
1828 static void test_CopyMetaFile(void)
1829 {
1830     HDC hdcMetafile;
1831     HMETAFILE hMetafile, hmf_copy;
1832     BOOL ret;
1833     char temp_path[MAX_PATH];
1834     char mf_name[MAX_PATH];
1835     INT type;
1836
1837     hdcMetafile = CreateMetaFileA(NULL);
1838     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1839     trace("hdcMetafile %p\n", hdcMetafile);
1840
1841     hMetafile = CloseMetaFile(hdcMetafile);
1842     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1843     type = GetObjectType(hMetafile);
1844     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1845
1846     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1847         "mf_blank") != 0)
1848     {
1849         dump_mf_bits(hMetafile, "mf_Blank");
1850         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1851     }
1852
1853     GetTempPathA(MAX_PATH, temp_path);
1854     GetTempFileNameA(temp_path, "wmf", 0, mf_name);
1855
1856     hmf_copy = CopyMetaFileA(hMetafile, mf_name);
1857     ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
1858
1859     type = GetObjectType(hmf_copy);
1860     ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
1861
1862     ret = DeleteMetaFile(hMetafile);
1863     ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1864
1865     if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
1866     {
1867         dump_mf_bits(hmf_copy, "mf_Blank");
1868         EnumMetaFile(0, hmf_copy, mf_enum_proc, 0);
1869     }
1870
1871     ret = DeleteMetaFile(hmf_copy);
1872     ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
1873
1874     DeleteFileA(mf_name);
1875 }
1876
1877 static void test_SetMetaFileBits(void)
1878 {
1879     HMETAFILE hmf;
1880     INT type;
1881     BOOL ret;
1882     BYTE buf[256];
1883     METAHEADER *mh;
1884
1885     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
1886     trace("hmf %p\n", hmf);
1887     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1888     type = GetObjectType(hmf);
1889     ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
1890
1891     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1892     {
1893         dump_mf_bits(hmf, "mf_Graphics");
1894         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1895     }
1896
1897     ret = DeleteMetaFile(hmf);
1898     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1899
1900     /* NULL data crashes XP SP1 */
1901     /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1902
1903     /* Now with zero size */
1904     SetLastError(0xdeadbeef);
1905     hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
1906     trace("hmf %p\n", hmf);
1907     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1908     ok(GetLastError() == ERROR_INVALID_DATA ||
1909        broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1910        "wrong error %d\n", GetLastError());
1911
1912     /* Now with odd size */
1913     SetLastError(0xdeadbeef);
1914     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
1915     trace("hmf %p\n", hmf);
1916     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1917     ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
1918
1919     /* Now with zeroed out header fields */
1920     assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
1921     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1922     mh = (METAHEADER *)buf;
1923     /* corruption of any of the below fields leads to a failure */
1924     mh->mtType = 0;
1925     mh->mtVersion = 0;
1926     mh->mtHeaderSize = 0;
1927     SetLastError(0xdeadbeef);
1928     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1929     trace("hmf %p\n", hmf);
1930     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1931     ok(GetLastError() == ERROR_INVALID_DATA ||
1932        broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1933        "wrong error %d\n", GetLastError());
1934
1935     /* Now with corrupted mtSize field */
1936     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1937     mh = (METAHEADER *)buf;
1938     /* corruption of mtSize doesn't lead to a failure */
1939     mh->mtSize *= 2;
1940     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1941     trace("hmf %p\n", hmf);
1942     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1943
1944     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1945     {
1946         dump_mf_bits(hmf, "mf_Graphics");
1947         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1948     }
1949
1950     ret = DeleteMetaFile(hmf);
1951     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1952
1953 #ifndef _WIN64 /* Generates access violation on XP x64 and Win2003 x64 */
1954     /* Now with zeroed out mtSize field */
1955     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1956     mh = (METAHEADER *)buf;
1957     /* zeroing mtSize doesn't lead to a failure */
1958     mh->mtSize = 0;
1959     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1960     trace("hmf %p\n", hmf);
1961     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1962
1963     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1964     {
1965         dump_mf_bits(hmf, "mf_Graphics");
1966         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1967     }
1968
1969     ret = DeleteMetaFile(hmf);
1970     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1971 #endif
1972 }
1973
1974 /* Simple APIs from mfdrv/graphics.c
1975  */
1976
1977 static void test_mf_Graphics(void)
1978 {
1979     HDC hdcMetafile;
1980     HMETAFILE hMetafile;
1981     POINT oldpoint;
1982     BOOL ret;
1983
1984     hdcMetafile = CreateMetaFileA(NULL);
1985     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1986     trace("hdcMetafile %p\n", hdcMetafile);
1987
1988     ret = MoveToEx(hdcMetafile, 1, 1, NULL);
1989     ok( ret, "MoveToEx error %d.\n", GetLastError());
1990     ret = LineTo(hdcMetafile, 2, 2);
1991     ok( ret, "LineTo error %d.\n", GetLastError());
1992     ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
1993     ok( ret, "MoveToEx error %d.\n", GetLastError());
1994
1995 /* oldpoint gets garbage under Win XP, so the following test would
1996  * work under Wine but fails under Windows:
1997  *
1998  *   ok((oldpoint.x == 2) && (oldpoint.y == 2),
1999  *       "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
2000  *       oldpoint.x, oldpoint.y);
2001  */
2002
2003     ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
2004     ok( ret, "Ellipse error %d.\n", GetLastError());
2005
2006     hMetafile = CloseMetaFile(hdcMetafile);
2007     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2008     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2009
2010     if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
2011         "mf_Graphics") != 0)
2012     {
2013         dump_mf_bits(hMetafile, "mf_Graphics");
2014         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2015     }
2016
2017     ret = DeleteMetaFile(hMetafile);
2018     ok( ret, "DeleteMetaFile(%p) error %d\n",
2019         hMetafile, GetLastError());
2020 }
2021
2022 static void test_mf_PatternBrush(void)
2023 {
2024     HDC hdcMetafile;
2025     HMETAFILE hMetafile;
2026     LOGBRUSH *orig_lb;
2027     HBRUSH hBrush;
2028     BOOL ret;
2029
2030     orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
2031
2032     orig_lb->lbStyle = BS_PATTERN;
2033     orig_lb->lbColor = RGB(0, 0, 0);
2034     orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
2035     ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
2036
2037     hBrush = CreateBrushIndirect (orig_lb);
2038     ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
2039
2040     hdcMetafile = CreateMetaFileA(NULL);
2041     ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
2042     trace("hdcMetafile %p\n", hdcMetafile);
2043
2044     hBrush = SelectObject(hdcMetafile, hBrush);
2045     ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2046
2047     hMetafile = CloseMetaFile(hdcMetafile);
2048     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2049     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2050
2051     if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
2052         "mf_Pattern_Brush") != 0)
2053     {
2054         dump_mf_bits(hMetafile, "mf_Pattern_Brush");
2055         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2056     }
2057
2058     ret = DeleteMetaFile(hMetafile);
2059     ok( ret, "DeleteMetaFile error %d\n", GetLastError());
2060     ret = DeleteObject(hBrush);
2061     ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2062     ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
2063     ok( ret, "DeleteObject(HBITMAP) error %d\n",
2064         GetLastError());
2065     HeapFree (GetProcessHeap(), 0, orig_lb);
2066 }
2067
2068 static void test_mf_DCBrush(void)
2069 {
2070     HDC hdcMetafile;
2071     HMETAFILE hMetafile;
2072     HBRUSH hBrush;
2073     HPEN hPen;
2074     BOOL ret;
2075     COLORREF color;
2076
2077     if (!pSetDCBrushColor || !pSetDCPenColor)
2078     {
2079         win_skip( "SetDCBrush/PenColor not supported\n" );
2080         return;
2081     }
2082
2083     hdcMetafile = CreateMetaFileA(NULL);
2084     ok( hdcMetafile != 0, "CreateMetaFileA failed\n" );
2085
2086     hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
2087     ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2088
2089     hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
2090     ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
2091
2092     color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
2093     ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2094
2095     color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
2096     ok( color == CLR_INVALID, "SetDCPenColor returned %x\n", color );
2097
2098     Rectangle( hdcMetafile, 10, 10, 20, 20 );
2099
2100     color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
2101     ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2102
2103     hMetafile = CloseMetaFile(hdcMetafile);
2104     ok( hMetafile != 0, "CloseMetaFile failed\n" );
2105
2106     if (compare_mf_bits(hMetafile, MF_DCBRUSH_BITS, sizeof(MF_DCBRUSH_BITS), "mf_DCBrush") != 0)
2107     {
2108         dump_mf_bits(hMetafile, "mf_DCBrush");
2109         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2110     }
2111     ret = DeleteMetaFile(hMetafile);
2112     ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2113 }
2114
2115 static void test_mf_ExtTextOut_on_path(void)
2116 {
2117     HDC hdcMetafile;
2118     HMETAFILE hMetafile;
2119     BOOL ret;
2120     static const INT dx[4] = { 3, 5, 8, 12 };
2121
2122     hdcMetafile = CreateMetaFileA(NULL);
2123     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2124     trace("hdcMetafile %p\n", hdcMetafile);
2125
2126     ret = BeginPath(hdcMetafile);
2127     ok(!ret, "BeginPath on metafile DC should fail\n");
2128
2129     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2130     ok(ret, "ExtTextOut error %d\n", GetLastError());
2131
2132     ret = EndPath(hdcMetafile);
2133     ok(!ret, "EndPath on metafile DC should fail\n");
2134
2135     hMetafile = CloseMetaFile(hdcMetafile);
2136     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2137
2138     if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
2139         "mf_TextOut_on_path") != 0)
2140     {
2141         dump_mf_bits(hMetafile, "mf_TextOut_on_path");
2142         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2143     }
2144
2145     ret = DeleteMetaFile(hMetafile);
2146     ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2147 }
2148
2149 static void test_emf_ExtTextOut_on_path(void)
2150 {
2151     HWND hwnd;
2152     HDC hdcDisplay, hdcMetafile;
2153     HENHMETAFILE hMetafile;
2154     BOOL ret;
2155     static const INT dx[4] = { 3, 5, 8, 12 };
2156
2157     /* Win9x doesn't play EMFs on invisible windows */
2158     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2159                            0, 0, 200, 200, 0, 0, 0, NULL);
2160     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2161
2162     hdcDisplay = GetDC(hwnd);
2163     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
2164
2165     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
2166     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2167
2168     ret = BeginPath(hdcMetafile);
2169     ok(ret, "BeginPath error %d\n", GetLastError());
2170
2171     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2172     ok(ret, "ExtTextOut error %d\n", GetLastError());
2173
2174     ret = EndPath(hdcMetafile);
2175     ok(ret, "EndPath error %d\n", GetLastError());
2176
2177     hMetafile = CloseEnhMetaFile(hdcMetafile);
2178     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2179
2180     /* this doesn't succeed yet: EMF has correct size, all EMF records
2181      * are there, but their contents don't match for different reasons.
2182      */
2183     if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
2184         "emf_TextOut_on_path", FALSE) != 0)
2185     {
2186         dump_emf_bits(hMetafile, "emf_TextOut_on_path");
2187         dump_emf_records(hMetafile, "emf_TextOut_on_path");
2188     }
2189
2190     ret = DeleteEnhMetaFile(hMetafile);
2191     ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
2192     ret = ReleaseDC(hwnd, hdcDisplay);
2193     ok(ret, "ReleaseDC error %d\n", GetLastError());
2194     DestroyWindow(hwnd);
2195 }
2196
2197 static const unsigned char EMF_CLIPPING[] =
2198 {
2199     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
2200     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2201     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2202     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2203     0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2204     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
2205     0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
2206     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2207     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2208     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2209     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
2210     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2211     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
2212     0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
2213     0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2214     0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
2215     0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
2216     0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
2217     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2218     0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2219     0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2220     0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2221     0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2222     0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2223     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2224     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
2225 };
2226
2227 static void translate( POINT *pt, UINT count, const XFORM *xform )
2228 {
2229     while (count--)
2230     {
2231         FLOAT x = (FLOAT)pt->x;
2232         FLOAT y = (FLOAT)pt->y;
2233         pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
2234         pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
2235         pt++;
2236     }
2237 }
2238
2239 /* Compare rectangles allowing rounding errors */
2240 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
2241 {
2242     return abs(rc1->left - rc2->left) <= 1 &&
2243            abs(rc1->top - rc2->top) <= 1 &&
2244            abs(rc1->right - rc2->right) <= 1 &&
2245            abs(rc1->bottom - rc2->bottom) <= 1;
2246 }
2247
2248 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2249                                        const ENHMETARECORD *emr, int n_objs, LPARAM param)
2250 {
2251     if (emr->iType == EMR_EXTSELECTCLIPRGN)
2252     {
2253         const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
2254         union _rgn
2255         {
2256             RGNDATA data;
2257             char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
2258         };
2259         const union _rgn *rgn1;
2260         union _rgn rgn2;
2261         RECT rect, rc_transformed;
2262         const RECT *rc = (const RECT *)param;
2263         HRGN hrgn;
2264         XFORM xform;
2265         INT ret;
2266         BOOL is_win9x;
2267
2268         trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
2269                clip->cbRgnData, clip->iMode);
2270
2271         ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
2272         ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
2273            "too small data block: %u bytes\n", clip->cbRgnData);
2274         if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
2275             return 0;
2276
2277         rgn1 = (const union _rgn *)clip->RgnData;
2278
2279         trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2280               rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
2281               rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
2282               rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
2283               rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
2284
2285         ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
2286
2287         rect = *(const RECT *)rgn1->data.Buffer;
2288         trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2289         ok(EqualRect(&rect, rc), "rects don't match\n");
2290
2291         ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
2292         ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
2293         ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
2294         ok(rgn1->data.rdh.nRgnSize == sizeof(RECT) ||
2295            broken(rgn1->data.rdh.nRgnSize == 168), /* NT4 */
2296            "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
2297
2298         hrgn = CreateRectRgn(0, 0, 0, 0);
2299
2300         memset(&xform, 0, sizeof(xform));
2301         SetLastError(0xdeadbeef);
2302         ret = GetWorldTransform(hdc, &xform);
2303         is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
2304         if (!is_win9x)
2305             ok(ret, "GetWorldTransform error %u\n", GetLastError());
2306
2307         trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
2308
2309         ret = GetClipRgn(hdc, hrgn);
2310         ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
2311
2312         PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
2313
2314         ret = GetClipRgn(hdc, hrgn);
2315         ok(ret == 1, "GetClipRgn returned %d, expected 1\n", ret);
2316
2317         /* Win9x returns empty clipping region */
2318         if (is_win9x) return 1;
2319
2320         ret = GetRegionData(hrgn, 0, NULL);
2321         ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
2322
2323         ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
2324         ok(ret == sizeof(rgn2), "expected sizeof(rgn2), got %u\n", ret);
2325
2326         trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2327               rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
2328               rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
2329               rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
2330               rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
2331
2332         rect = rgn2.data.rdh.rcBound;
2333         rc_transformed = *rc;
2334         translate((POINT *)&rc_transformed, 2, &xform);
2335         trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2336               rc_transformed.right, rc_transformed.bottom);
2337         ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2338
2339         rect = *(const RECT *)rgn2.data.Buffer;
2340         trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2341         rc_transformed = *rc;
2342         translate((POINT *)&rc_transformed, 2, &xform);
2343         trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2344               rc_transformed.right, rc_transformed.bottom);
2345         ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2346
2347         ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
2348         ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
2349         ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
2350         ok(rgn2.data.rdh.nRgnSize == sizeof(RECT) ||
2351            broken(rgn2.data.rdh.nRgnSize == 168), /* NT4 */
2352            "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
2353
2354         DeleteObject(hrgn);
2355     }
2356     return 1;
2357 }
2358
2359 static void test_emf_clipping(void)
2360 {
2361     static const RECT rc = { 0, 0, 100, 100 };
2362     RECT rc_clip = { 100, 100, 1024, 1024 };
2363     HWND hwnd;
2364     HDC hdc;
2365     HENHMETAFILE hemf;
2366     HRGN hrgn;
2367     INT ret;
2368     RECT rc_res, rc_sclip;
2369
2370     SetLastError(0xdeadbeef);
2371     hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2372     ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2373
2374     /* Need to write something to the emf, otherwise Windows won't play it back */
2375     LineTo(hdc, 1, 1);
2376
2377     hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2378     ret = SelectClipRgn(hdc, hrgn);
2379     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
2380
2381     SetLastError(0xdeadbeef);
2382     hemf = CloseEnhMetaFile(hdc);
2383     ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2384
2385     if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
2386         "emf_clipping", FALSE) != 0)
2387     {
2388         dump_emf_bits(hemf, "emf_clipping");
2389         dump_emf_records(hemf, "emf_clipping");
2390     }
2391
2392     DeleteObject(hrgn);
2393
2394     /* Win9x doesn't play EMFs on invisible windows */
2395     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2396                            0, 0, 200, 200, 0, 0, 0, NULL);
2397     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2398
2399     hdc = GetDC(hwnd);
2400
2401     ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
2402     ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
2403
2404     DeleteEnhMetaFile(hemf);
2405     ReleaseDC(hwnd, hdc);
2406     DestroyWindow(hwnd);
2407
2408     hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2409
2410     SetRect(&rc_sclip, 100, 100, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2411     hrgn = CreateRectRgn(rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom);
2412     SelectClipRgn(hdc, hrgn);
2413     ret = GetClipBox(hdc, &rc_res);
2414 todo_wine
2415     ok(ret == SIMPLEREGION, "got %d\n", ret);
2416     if(ret == SIMPLEREGION)
2417         ok(EqualRect(&rc_res, &rc_sclip),
2418                  "expected rc_res (%d, %d) - (%d, %d), got (%d, %d) - (%d, %d)\n",
2419                  rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2420                  rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2421
2422     hemf = CloseEnhMetaFile(hdc);
2423     DeleteEnhMetaFile(hemf);
2424     DeleteObject(hrgn);
2425     DeleteDC(hdc);
2426 }
2427
2428 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
2429 {
2430     LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
2431     POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
2432     /* When using MM_TEXT Win9x does not update the mapping mode 
2433      * until a record is played which actually outputs something */
2434     PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
2435     LPtoDP(hdc, mapping, 2);
2436     trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
2437            lpEMFR->iType, lpEMFR->nSize,
2438            mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
2439
2440     if (lpEMFR->iType == EMR_LINETO)
2441     {
2442         INT x0, y0, x1, y1;
2443         if (!lpMFP || lpMFP->mm == MM_TEXT)
2444         {
2445             x0 = 0;
2446             y0 = 0;
2447             x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
2448             y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
2449         }
2450         else
2451         {
2452             ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
2453             
2454             x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2455             y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2456             x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2457             y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2458         }
2459         ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
2460             "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
2461             mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
2462             x0, y0, x1, y1);
2463     }
2464     return TRUE;
2465 }
2466
2467 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
2468 {
2469     HDC hdcMf;
2470     HMETAFILE hmf;
2471     HENHMETAFILE hemf;
2472     BOOL ret;
2473     UINT size;
2474     LPBYTE pBits;
2475
2476     hdcMf = CreateMetaFile(NULL);
2477     ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
2478     ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
2479     ok(ret, "LineTo failed with error %d\n", GetLastError());
2480     hmf = CloseMetaFile(hdcMf);
2481     ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
2482
2483     if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
2484     {
2485         dump_mf_bits(hmf, "mf_LineTo");
2486         EnumMetaFile(0, hmf, mf_enum_proc, 0);
2487     }
2488
2489     size = GetMetaFileBitsEx(hmf, 0, NULL);
2490     ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
2491     pBits = HeapAlloc(GetProcessHeap(), 0, size);
2492     GetMetaFileBitsEx(hmf, size, pBits);
2493     DeleteMetaFile(hmf);
2494     hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
2495     HeapFree(GetProcessHeap(), 0, pBits);
2496     return hemf;
2497 }
2498
2499 static void test_mf_conversions(void)
2500 {
2501     trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
2502     {
2503         HDC hdcOffscreen = CreateCompatibleDC(NULL);
2504         HENHMETAFILE hemf;
2505         METAFILEPICT mfp;
2506         RECT rect = { 0, 0, 100, 100 };
2507         mfp.mm = MM_ANISOTROPIC;
2508         mfp.xExt = 100;
2509         mfp.yExt = 100;
2510         mfp.hMF = NULL;
2511         hemf = create_converted_emf(&mfp);
2512
2513         if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
2514                              "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
2515         {
2516             dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
2517             dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
2518         }
2519
2520         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2521
2522         DeleteEnhMetaFile(hemf);
2523         DeleteDC(hdcOffscreen);
2524     }
2525
2526     trace("Testing MF->EMF conversion (MM_TEXT)\n");
2527     {
2528         HDC hdcOffscreen = CreateCompatibleDC(NULL);
2529         HENHMETAFILE hemf;
2530         METAFILEPICT mfp;
2531         RECT rect = { 0, 0, 100, 100 };
2532         mfp.mm = MM_TEXT;
2533         mfp.xExt = 0;
2534         mfp.yExt = 0;
2535         mfp.hMF = NULL;
2536         hemf = create_converted_emf(&mfp);
2537
2538         if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
2539                              "emf_LineTo MM_TEXT", TRUE) != 0)
2540         {
2541             dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
2542             dump_emf_records(hemf, "emf_LineTo MM_TEXT");
2543         }
2544
2545         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2546
2547         DeleteEnhMetaFile(hemf);
2548         DeleteDC(hdcOffscreen);
2549     }
2550
2551     trace("Testing MF->EMF conversion (NULL mfp)\n");
2552     {
2553         HDC hdcOffscreen = CreateCompatibleDC(NULL);
2554         HENHMETAFILE hemf;
2555         RECT rect = { 0, 0, 100, 100 };
2556         hemf = create_converted_emf(NULL);
2557
2558         if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
2559                              "emf_LineTo NULL", TRUE) != 0)
2560         {
2561             dump_emf_bits(hemf, "emf_LineTo NULL");
2562             dump_emf_records(hemf, "emf_LineTo NULL");
2563         }
2564
2565         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
2566
2567         DeleteEnhMetaFile(hemf);
2568         DeleteDC(hdcOffscreen);
2569     }
2570 }
2571
2572 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2573                                        LONG mm, LONG xExt, LONG yExt,
2574                                        RECTL * rclBounds, RECTL * rclFrame)
2575 {
2576   METAFILEPICT mfp;
2577   METAFILEPICT * mfpPtr = NULL;
2578   HENHMETAFILE emf;
2579   ENHMETAHEADER header;
2580   UINT res;
2581
2582   if (!mfpIsNull)
2583   {
2584     mfp.mm = mm;
2585     mfp.xExt = xExt;
2586     mfp.yExt = yExt;
2587     mfpPtr = &mfp;
2588   }
2589
2590   emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
2591   ok(emf != NULL, "SetWinMetaFileBits failed\n");
2592   if (!emf) return FALSE;
2593   res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
2594   ok(res != 0, "GetEnhMetaHeader failed\n");
2595   DeleteEnhMetaFile(emf);
2596   if (!res) return FALSE;
2597
2598   *rclBounds = header.rclBounds;
2599   *rclFrame = header.rclFrame;
2600   return TRUE;
2601 }
2602
2603 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2604                                          LONG mm, LONG xExt, LONG yExt,
2605                                          RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
2606 {
2607   RECTL rclBounds, rclFrame;
2608
2609   if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
2610   {
2611     const char * msg;
2612     char buf[64];
2613
2614     if (mfpIsNull)
2615     {
2616        msg = "mfp == NULL";
2617     }
2618     else
2619     {
2620       const char * mm_str;
2621       switch (mm)
2622       {
2623          case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
2624          case MM_ISOTROPIC:   mm_str = "MM_ISOTROPIC"; break;
2625          default:             mm_str = "Unexpected";
2626       }
2627       sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
2628       msg = buf;
2629     }
2630
2631     ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
2632     ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
2633     ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
2634     ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
2635     ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
2636     ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
2637     ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
2638     ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
2639   }
2640 }
2641
2642 static void test_SetWinMetaFileBits(void)
2643 {
2644   HMETAFILE wmf;
2645   HDC wmfDC;
2646   BYTE * buffer;
2647   UINT buffer_size;
2648   RECT rect;
2649   UINT res;
2650   RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
2651   RECTL rclBoundsIsotropic, rclFrameIsotropic;
2652   RECTL rclBounds, rclFrame;
2653   HDC dc;
2654   LONG diffx, diffy;
2655
2656   wmfDC = CreateMetaFile(NULL);
2657   ok(wmfDC != NULL, "CreateMetaFile failed\n");
2658   if (!wmfDC) return;
2659
2660   SetWindowExtEx(wmfDC, 100, 100, NULL);
2661   rect.left = rect.top = 0;
2662   rect.right = rect.bottom = 50;
2663   FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
2664   wmf = CloseMetaFile(wmfDC);
2665   ok(wmf != NULL, "Metafile creation failed\n");
2666   if (!wmf) return;
2667
2668   buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
2669   ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
2670   if (buffer_size == 0)
2671   {
2672     DeleteMetaFile(wmf);
2673     return;
2674   }
2675
2676   buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
2677   ok(buffer != NULL, "HeapAlloc failed\n");
2678   if (!buffer)
2679   {
2680     DeleteMetaFile(wmf);
2681     return;
2682   }
2683
2684   res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
2685   ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
2686   DeleteMetaFile(wmf);
2687   if (res != buffer_size)
2688   {
2689      HeapFree(GetProcessHeap(), 0, buffer);
2690      return;
2691   }
2692
2693   /* Get the reference bounds and frame */
2694   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2695   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0,  &rclBoundsIsotropic, &rclFrameIsotropic);
2696
2697   ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
2698      rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
2699      "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
2700
2701   ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
2702   ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
2703   diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
2704   if (diffx < 0) diffx = -diffx;
2705   ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
2706
2707   dc = CreateCompatibleDC(NULL);
2708
2709   /* Allow 1 mm difference (rounding errors) */
2710   diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
2711   diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
2712   if (diffx < 0) diffx = -diffx;
2713   if (diffy < 0) diffy = -diffy;
2714   todo_wine
2715   {
2716   ok(diffx <= 1 && diffy <= 1,
2717      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2718      GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
2719   }
2720
2721   /* Allow 1 mm difference (rounding errors) */
2722   diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
2723   diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
2724   if (diffx < 0) diffx = -diffx;
2725   if (diffy < 0) diffy = -diffy;
2726   todo_wine
2727   {
2728   ok(diffx <= 1 && diffy <= 1,
2729      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2730      GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
2731   }
2732   DeleteDC(dc);
2733
2734   /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
2735   checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2736
2737   /* If xExt or yExt is zero or negative, the whole device surface is used */
2738   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2739   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2740   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2741   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2742   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2743   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2744   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2745   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2746   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2747   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2748   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2749   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2750
2751   /* MSDN says that negative xExt and yExt values specify a ratio.
2752      Check that this is wrong and the whole device surface is used */
2753   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2754   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
2755
2756   /* Ordinary conversions */
2757
2758   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2759   {
2760     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2761        "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
2762     ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
2763        "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
2764   }
2765
2766   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2767   {
2768     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2769        "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
2770     ok(rclBounds.left == 0 && rclBounds.top == 0,
2771        "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
2772
2773     /* Wine has a rounding error */
2774     diffx = rclBounds.right - rclBounds.bottom;
2775     if (diffx < 0) diffx = -diffx;
2776     ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
2777   }
2778
2779   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
2780   {
2781     ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
2782        "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
2783   }
2784
2785   HeapFree(GetProcessHeap(), 0, buffer);
2786 }
2787
2788 static BOOL near_match(int x, int y)
2789 {
2790     int epsilon = min(abs(x), abs(y));
2791
2792     epsilon = max(epsilon/100, 2);
2793
2794     if(x < y - epsilon || x > y + epsilon) return FALSE;
2795     return TRUE;
2796 }
2797
2798 static void getwinmetafilebits(UINT mode, int scale, RECT *rc)
2799 {
2800     HENHMETAFILE emf;
2801     HDC display_dc, emf_dc;
2802     ENHMETAHEADER *enh_header;
2803     UINT size, emf_size, i;
2804     WORD check = 0;
2805     DWORD rec_num = 0;
2806     METAHEADER *mh = NULL;
2807     METARECORD *rec;
2808     INT horz_res, vert_res, horz_size, vert_size;
2809     INT curve_caps, line_caps, poly_caps;
2810
2811     display_dc = GetDC(NULL);
2812     ok(display_dc != NULL, "display_dc is NULL\n");
2813
2814     horz_res = GetDeviceCaps(display_dc, HORZRES);
2815     vert_res = GetDeviceCaps(display_dc, VERTRES);
2816     horz_size = GetDeviceCaps(display_dc, HORZSIZE);
2817     vert_size = GetDeviceCaps(display_dc, VERTSIZE);
2818
2819     emf_dc = CreateEnhMetaFileA(display_dc, NULL, rc, NULL);
2820     ok(emf_dc != NULL, "emf_dc is NULL\n");
2821
2822     curve_caps = GetDeviceCaps(emf_dc, CURVECAPS);
2823     ok(curve_caps == 511, "expect 511 got %d\n", curve_caps);
2824
2825     line_caps = GetDeviceCaps(emf_dc, LINECAPS);
2826     ok(line_caps == 254, "expect 254 got %d\n", line_caps);
2827
2828     poly_caps = GetDeviceCaps(emf_dc, POLYGONALCAPS);
2829     ok(poly_caps == 255, "expect 511 got %d\n", poly_caps);
2830
2831     for(i = 0; i < 3000; i++) /* This is enough to take emf_size > 0xffff */
2832         Rectangle(emf_dc, 0, 0, 1000, 20);
2833     emf = CloseEnhMetaFile(emf_dc);
2834     ok(emf != NULL, "emf is NULL\n");
2835
2836     emf_size = GetEnhMetaFileBits(emf, 0, NULL);
2837     enh_header = HeapAlloc(GetProcessHeap(), 0, emf_size);
2838     emf_size = GetEnhMetaFileBits(emf, emf_size, (BYTE*)enh_header);
2839     DeleteEnhMetaFile(emf);
2840     /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs
2841        have different resolutions */
2842     enh_header->szlDevice.cx *= scale;
2843     emf = SetEnhMetaFileBits(emf_size, (BYTE*)enh_header);
2844     ok(emf != NULL, "emf is NULL\n");
2845     ok(EqualRect((RECT*)&enh_header->rclFrame, rc), "Frame rectangles differ\n");
2846
2847     size = GetWinMetaFileBits(emf, 0, NULL, mode, display_dc);
2848     ok(size ||
2849        broken(size == 0), /* some versions of winxp fail for some reason */
2850        "GetWinMetaFileBits returns 0\n");
2851     if(!size) goto end;
2852     mh = HeapAlloc(GetProcessHeap(), 0, size);
2853     GetWinMetaFileBits(emf, size, (BYTE*)mh, mode, display_dc);
2854
2855     for(i = 0; i < size / 2; i++) check += ((WORD*)mh)[i];
2856     ok(check == 0, "check %04x\n", check);
2857
2858     rec = (METARECORD*)(mh + 1);
2859
2860     while(rec->rdSize && rec->rdFunction)
2861     {
2862         const DWORD chunk_size = 0x2000;
2863         DWORD mfcomment_chunks = (emf_size + chunk_size - 1) / chunk_size;
2864
2865         if(rec_num < mfcomment_chunks)
2866         {
2867             DWORD this_chunk_size = chunk_size;
2868
2869             if(rec_num == mfcomment_chunks - 1)
2870                 this_chunk_size = emf_size - rec_num * chunk_size;
2871
2872             ok(rec->rdSize == (this_chunk_size + 44) / 2, "%04x: got %04x expected %04x\n", rec_num, rec->rdSize, (this_chunk_size + 44) / 2);
2873             ok(rec->rdFunction == META_ESCAPE, "%04x: got %04x\n", rec_num, rec->rdFunction);
2874             if(rec->rdSize < (this_chunk_size + 44) / 2) break;
2875             ok(rec->rdParm[0] == MFCOMMENT, "got %04x\n", rec->rdParm[0]);
2876             ok(rec->rdParm[1] == this_chunk_size + 34, "got %04x %x\n", rec->rdParm[1], emf_size + 34);
2877             ok(rec->rdParm[2] == 0x4d57, "got %04x\n", rec->rdParm[2]); /* WMFC */
2878             ok(rec->rdParm[3] == 0x4346, "got %04x\n", rec->rdParm[3]); /*  "   */
2879             ok(rec->rdParm[4] == 1, "got %04x\n", rec->rdParm[4]);
2880             ok(rec->rdParm[5] == 0, "got %04x\n", rec->rdParm[5]);
2881             ok(rec->rdParm[6] == 0, "got %04x\n", rec->rdParm[6]);
2882             ok(rec->rdParm[7] == 1, "got %04x\n", rec->rdParm[7]);
2883             /* parm[8] is the checksum, tested above */
2884             if(rec_num > 0) ok(rec->rdParm[8] == 0, "got %04x\n", rec->rdParm[8]);
2885             ok(rec->rdParm[9] == 0, "got %04x\n", rec->rdParm[9]);
2886             ok(rec->rdParm[10] == 0, "got %04x\n", rec->rdParm[10]);
2887             ok(rec->rdParm[11] == mfcomment_chunks, "got %04x\n", rec->rdParm[11]); /* num chunks */
2888             ok(rec->rdParm[12] == 0, "got %04x\n", rec->rdParm[12]);
2889             ok(rec->rdParm[13] == this_chunk_size, "got %04x expected %04x\n", rec->rdParm[13], this_chunk_size);
2890             ok(rec->rdParm[14] == 0, "got %04x\n", rec->rdParm[14]);
2891             ok(*(DWORD*)(rec->rdParm + 15) == emf_size - this_chunk_size - rec_num * chunk_size, "got %08x\n", *(DWORD*)(rec->rdParm + 15));  /* DWORD size remaining after current chunk */
2892             ok(*(DWORD*)(rec->rdParm + 17) == emf_size, "got %08x emf_size %08x\n", *(DWORD*)(rec->rdParm + 17), emf_size);
2893             ok(!memcmp(rec->rdParm + 19, (char*)enh_header + rec_num * chunk_size, this_chunk_size), "bits mismatch\n");
2894         }
2895
2896         else if(rec_num == mfcomment_chunks)
2897         {
2898             ok(rec->rdFunction == META_SETMAPMODE, "got %04x\n", rec->rdFunction);
2899             ok(rec->rdParm[0] == mode, "got %04x\n", rec->rdParm[0]);
2900         }
2901         else if(rec_num == mfcomment_chunks + 1)
2902         {
2903             POINT pt;
2904             ok(rec->rdFunction == META_SETWINDOWORG, "got %04x\n", rec->rdFunction);
2905             switch(mode)
2906             {
2907             case MM_TEXT:
2908             case MM_ISOTROPIC:
2909             case MM_ANISOTROPIC:
2910                 pt.y = MulDiv(rc->top, vert_res, vert_size * 100) + 1;
2911                 pt.x = MulDiv(rc->left, horz_res, horz_size * 100);
2912                 break;
2913             case MM_LOMETRIC:
2914                 pt.y = MulDiv(-rc->top, 1, 10) + 1;
2915                 pt.x = MulDiv( rc->left, 1, 10);
2916                 break;
2917             case MM_HIMETRIC:
2918                 pt.y = -rc->top + 1;
2919                 pt.x = (rc->left >= 0) ? rc->left : rc->left + 1; /* strange but true */
2920                 break;
2921             case MM_LOENGLISH:
2922                 pt.y = MulDiv(-rc->top, 10, 254) + 1;
2923                 pt.x = MulDiv( rc->left, 10, 254);
2924                 break;
2925             case MM_HIENGLISH:
2926                 pt.y = MulDiv(-rc->top, 100, 254) + 1;
2927                 pt.x = MulDiv( rc->left, 100, 254);
2928                 break;
2929             case MM_TWIPS:
2930                 pt.y = MulDiv(-rc->top, 72 * 20, 2540) + 1;
2931                 pt.x = MulDiv( rc->left, 72 * 20, 2540);
2932                 break;
2933             default:
2934                 pt.x = pt.y = 0;
2935             }
2936             ok(near_match((short)rec->rdParm[0], pt.y), "got %d expect %d\n", (short)rec->rdParm[0], pt.y);
2937             ok(near_match((short)rec->rdParm[1], pt.x), "got %d expect %d\n", (short)rec->rdParm[1], pt.x);
2938         }
2939         if(rec_num == mfcomment_chunks + 2)
2940         {
2941             ok(rec->rdFunction == META_SETWINDOWEXT, "got %04x\n", rec->rdFunction);
2942             ok(near_match((short)rec->rdParm[0], MulDiv(rc->bottom - rc->top, vert_res, vert_size * 100)),
2943                "got %d\n", (short)rec->rdParm[0]);
2944             ok(near_match((short)rec->rdParm[1], MulDiv(rc->right - rc->left, horz_res, horz_size * 100)),
2945                "got %d\n", (short)rec->rdParm[1]);
2946         }
2947
2948         rec_num++;
2949         rec = (METARECORD*)((WORD*)rec + rec->rdSize);
2950     }
2951
2952 end:
2953     HeapFree(GetProcessHeap(), 0, mh);
2954     HeapFree(GetProcessHeap(), 0, enh_header);
2955     DeleteEnhMetaFile(emf);
2956
2957     ReleaseDC(NULL, display_dc);
2958 }
2959
2960 static void test_GetWinMetaFileBits(void)
2961 {
2962     UINT mode;
2963     RECT frames[] =
2964     {
2965         { 1000,  2000, 3000, 6000},
2966         {-1000,  2000, 3000, 6000},
2967         { 1000, -2000, 3000, 6000},
2968         { 1005,  2005, 3000, 6000},
2969         {-1005, -2005, 3000, 6000},
2970         {-1005, -2010, 3000, 6000},
2971         {-1005,  2010, 3000, 6000},
2972         {    0,     0,    1,    1},
2973         {   -1,    -1,    1,    1},
2974         {    0,     0,    0,    0}
2975     };
2976
2977     for(mode = MM_MIN; mode <= MM_MAX; mode++)
2978     {
2979         RECT *rc;
2980         trace("mode %d\n", mode);
2981
2982         for(rc = frames; rc->right - rc->left > 0; rc++)
2983         {
2984             trace("frame %d,%d - %d,%d\n", rc->left, rc->top, rc->right, rc->bottom);
2985             getwinmetafilebits(mode, 1, rc);
2986             getwinmetafilebits(mode, 2, rc);
2987         }
2988     }
2989 }
2990
2991 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
2992 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
2993 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
2994
2995 static void test_gdiis(void)
2996 {
2997     RECT rect = {0,0,100,100};
2998     HDC hdc, hemfDC, hmfDC;
2999     HENHMETAFILE hemf;
3000     HMODULE hgdi32;
3001
3002     /* resolve all the functions */
3003     hgdi32 = GetModuleHandle("gdi32");
3004     pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
3005     pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
3006     pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
3007
3008     if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
3009     {
3010         win_skip("Needed GdiIs* functions are not available\n");
3011         return;
3012     }
3013
3014     /* try with nothing */
3015     ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
3016     ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
3017     ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
3018
3019     /* try with a metafile */
3020     hmfDC = CreateMetaFile(NULL);
3021     ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
3022     ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
3023     ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
3024     DeleteMetaFile(CloseMetaFile(hmfDC));
3025
3026     /* try with an enhanced metafile */
3027     hdc = GetDC(NULL);
3028     hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
3029     ok(hemfDC != NULL, "failed to create emf\n");
3030
3031     ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
3032     ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
3033     ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
3034
3035     hemf = CloseEnhMetaFile(hemfDC);
3036     ok(hemf != NULL, "failed to close EMF\n");
3037     DeleteEnhMetaFile(hemf);
3038     ReleaseDC(NULL,hdc);
3039 }
3040
3041 static void test_SetEnhMetaFileBits(void)
3042 {
3043     BYTE data[256];
3044     HENHMETAFILE hemf;
3045     ENHMETAHEADER *emh;
3046
3047     memset(data, 0xAA, sizeof(data));
3048     SetLastError(0xdeadbeef);
3049     hemf = SetEnhMetaFileBits(sizeof(data), data);
3050     ok(!hemf, "SetEnhMetaFileBits should fail\n");
3051     ok(GetLastError() == ERROR_INVALID_DATA ||
3052        GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
3053        "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
3054
3055     emh = (ENHMETAHEADER *)data;
3056     memset(emh, 0, sizeof(*emh));
3057
3058     emh->iType = EMR_HEADER;
3059     emh->nSize = sizeof(*emh);
3060     emh->dSignature = ENHMETA_SIGNATURE;
3061     /* emh->nVersion  = 0x10000; XP doesn't care about version */
3062     emh->nBytes = sizeof(*emh);
3063     /* emh->nRecords = 1; XP doesn't care about records */
3064     emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
3065
3066     SetLastError(0xdeadbeef);
3067     hemf = SetEnhMetaFileBits(emh->nBytes, data);
3068     ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
3069     DeleteEnhMetaFile(hemf);
3070
3071     /* XP refuses to load unaligned EMF */
3072     emh->nBytes++;
3073     SetLastError(0xdeadbeef);
3074     hemf = SetEnhMetaFileBits(emh->nBytes, data);
3075     ok(!hemf ||
3076        broken(hemf != NULL), /* Win9x, WinMe */
3077        "SetEnhMetaFileBits should fail\n");
3078     ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3079     DeleteEnhMetaFile(hemf);
3080
3081     emh->dSignature = 0;
3082     emh->nBytes--;
3083     SetLastError(0xdeadbeef);
3084     hemf = SetEnhMetaFileBits(emh->nBytes, data);
3085     ok(!hemf ||
3086        broken(hemf != NULL), /* Win9x, WinMe */
3087        "SetEnhMetaFileBits should fail\n");
3088     ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3089     DeleteEnhMetaFile(hemf);
3090 }
3091
3092 START_TEST(metafile)
3093 {
3094     init_function_pointers();
3095
3096     /* For enhanced metafiles (enhmfdrv) */
3097     test_ExtTextOut();
3098     test_ExtTextOutScale();
3099     test_SaveDC();
3100     test_emf_BitBlt();
3101     test_emf_DCBrush();
3102
3103     /* For win-format metafiles (mfdrv) */
3104     test_mf_SaveDC();
3105     test_mf_Blank();
3106     test_mf_Graphics();
3107     test_mf_PatternBrush();
3108     test_mf_DCBrush();
3109     test_CopyMetaFile();
3110     test_SetMetaFileBits();
3111     test_mf_ExtTextOut_on_path();
3112     test_emf_ExtTextOut_on_path();
3113     test_emf_clipping();
3114
3115     /* For metafile conversions */
3116     test_mf_conversions();
3117     test_SetWinMetaFileBits();
3118     test_GetWinMetaFileBits();
3119
3120     test_gdiis();
3121     test_SetEnhMetaFileBits();
3122 }