gdi32: Add a test for undocumented EnumFontFamiliesEx(NULL), make it pass under Wine.
[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
41 #define GDI_GET_PROC(func)                                     \
42     p ## func = (void *)GetProcAddress(hGDI, #func);           \
43     if(!p ## func)                                             \
44         trace("GetProcAddress(hGDI, \"%s\") failed\n", #func); \
45
46 static void init_function_pointers(void)
47 {
48     HMODULE hGDI;
49
50     pGetRelAbs = NULL;
51     pSetRelAbs = NULL;
52
53     hGDI = GetModuleHandleA("gdi32.dll");
54     assert(hGDI);
55     GDI_GET_PROC(GetRelAbs);
56     GDI_GET_PROC(SetRelAbs);
57 }
58
59 static int CALLBACK eto_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
60     const ENHMETARECORD *emr, int n_objs, LPARAM param)
61 {
62     static int n_record;
63     DWORD i;
64     const INT *dx;
65     INT *orig_dx = (INT *)param;
66     LOGFONTA device_lf;
67     INT ret;
68
69     trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
70            hdc, emr->iType, emr->nSize, (void *)param);
71
72     if(!hdc) return 1;
73
74     PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
75
76     switch (emr->iType)
77     {
78     case EMR_HEADER:
79         ok(GetTextAlign(hdc) == 0, "text align %08x\n", GetTextAlign(hdc));
80         ok(GetBkColor(hdc) == RGB(0xff, 0xff, 0xff), "bk color %08x\n", GetBkColor(hdc));
81         ok(GetTextColor(hdc) == RGB(0x0, 0x0, 0x0), "text color %08x\n", GetTextColor(hdc));
82         ok(GetROP2(hdc) == R2_COPYPEN, "rop %d\n", GetROP2(hdc));
83         ok(GetArcDirection(hdc) == AD_COUNTERCLOCKWISE, "arc dir %d\n", GetArcDirection(hdc));
84         ok(GetPolyFillMode(hdc) == ALTERNATE, "poly fill %d\n", GetPolyFillMode(hdc));
85         ok(GetStretchBltMode(hdc) == BLACKONWHITE, "stretchblt mode %d\n", GetStretchBltMode(hdc));
86
87         /* GetBkMode, GetRelAbs do not get reset to the default value */
88         ok(GetBkMode(hdc) == OPAQUE, "bk mode %d\n", GetBkMode(hdc));
89         if(pSetRelAbs && pGetRelAbs)
90             ok(pGetRelAbs(hdc, 0) == RELATIVE, "relabs %d\n", pGetRelAbs(hdc, 0));
91
92         n_record = 0;
93         break;
94
95     case EMR_EXTTEXTOUTA:
96     {
97         const EMREXTTEXTOUTA *emr_ExtTextOutA = (const EMREXTTEXTOUTA *)emr;
98         dx = (const INT *)((const char *)emr + emr_ExtTextOutA->emrtext.offDx);
99
100         ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
101         ok( ret == sizeof(device_lf), "GetObjectA error %d\n", GetLastError());
102
103         /* compare up to lfOutPrecision, other values are not interesting,
104          * and in fact sometimes arbitrary adapted by Win9x.
105          */
106         ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
107         ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
108
109         for(i = 0; i < emr_ExtTextOutA->emrtext.nChars; i++)
110         {
111             ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
112                                      n_record, i, dx[i], orig_dx[i]);
113         }
114         n_record++;
115         emr_processed = TRUE;
116         break;
117     }
118
119     case EMR_EXTTEXTOUTW:
120     {
121         const EMREXTTEXTOUTW *emr_ExtTextOutW = (const EMREXTTEXTOUTW *)emr;
122         dx = (const INT *)((const char *)emr + emr_ExtTextOutW->emrtext.offDx);
123
124         ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
125         ok( ret == sizeof(device_lf), "GetObjectA error %d\n", GetLastError());
126
127         /* compare up to lfOutPrecision, other values are not interesting,
128          * and in fact sometimes arbitrary adapted by Win9x.
129          */
130         ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
131         ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
132
133         for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++)
134         {
135             ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
136                                      n_record, i, dx[i], orig_dx[i]);
137         }
138         n_record++;
139         emr_processed = TRUE;
140         break;
141     }
142
143     default:
144         break;
145     }
146
147     return 1;
148 }
149
150 static void test_ExtTextOut(void)
151 {
152     HWND hwnd;
153     HDC hdcDisplay, hdcMetafile;
154     HENHMETAFILE hMetafile;
155     HFONT hFont;
156     static const char text[] = "Simple text to test ExtTextOut on metafiles";
157     INT i, len, dx[256];
158     static const RECT rc = { 0, 0, 100, 100 };
159     BOOL ret;
160
161     assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text));
162
163     /* Win9x doesn't play EMFs on invisible windows */
164     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
165                            0, 0, 200, 200, 0, 0, 0, NULL);
166     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
167
168     hdcDisplay = GetDC(hwnd);
169     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
170
171     trace("hdcDisplay %p\n", hdcDisplay);
172
173     SetMapMode(hdcDisplay, MM_TEXT);
174
175     memset(&orig_lf, 0, sizeof(orig_lf));
176
177     orig_lf.lfCharSet = ANSI_CHARSET;
178     orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
179     orig_lf.lfWeight = FW_DONTCARE;
180     orig_lf.lfHeight = 7;
181     orig_lf.lfQuality = DEFAULT_QUALITY;
182     lstrcpyA(orig_lf.lfFaceName, "Arial");
183     hFont = CreateFontIndirectA(&orig_lf);
184     ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
185
186     hFont = SelectObject(hdcDisplay, hFont);
187
188     len = lstrlenA(text);
189     for (i = 0; i < len; i++)
190     {
191         ret = GetCharWidthA(hdcDisplay, text[i], text[i], &dx[i]);
192         ok( ret, "GetCharWidthA error %d\n", GetLastError());
193     }
194     hFont = SelectObject(hdcDisplay, hFont);
195
196     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
197     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
198
199     trace("hdcMetafile %p\n", hdcMetafile);
200
201     ok(GetDeviceCaps(hdcMetafile, TECHNOLOGY) == DT_RASDISPLAY,
202        "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
203
204     hFont = SelectObject(hdcMetafile, hFont);
205
206     /* 1. pass NULL lpDx */
207     ret = ExtTextOutA(hdcMetafile, 0, 0, 0, &rc, text, lstrlenA(text), NULL);
208     ok( ret, "ExtTextOutA error %d\n", GetLastError());
209
210     /* 2. pass custom lpDx */
211     ret = ExtTextOutA(hdcMetafile, 0, 20, 0, &rc, text, lstrlenA(text), dx);
212     ok( ret, "ExtTextOutA error %d\n", GetLastError());
213
214     hFont = SelectObject(hdcMetafile, hFont);
215     ret = DeleteObject(hFont);
216     ok( ret, "DeleteObject error %d\n", GetLastError());
217
218     hMetafile = CloseEnhMetaFile(hdcMetafile);
219     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
220
221     ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
222
223     ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
224     ok( ret, "PlayEnhMetaFile error %d\n", GetLastError());
225
226     SetTextAlign(hdcDisplay, TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING );
227     SetBkColor(hdcDisplay, RGB(0xff, 0, 0));
228     SetTextColor(hdcDisplay, RGB(0, 0xff, 0));
229     SetROP2(hdcDisplay, R2_NOT);
230     SetArcDirection(hdcDisplay, AD_CLOCKWISE);
231     SetPolyFillMode(hdcDisplay, WINDING);
232     SetStretchBltMode(hdcDisplay, HALFTONE);
233
234     if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE);
235     SetBkMode(hdcDisplay, OPAQUE);
236
237     ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc);
238     ok( ret, "EnumEnhMetaFile error %d\n", GetLastError());
239
240     ok( GetTextAlign(hdcDisplay) == (TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING),
241         "text align %08x\n", GetTextAlign(hdcDisplay));
242     ok( GetBkColor(hdcDisplay) == RGB(0xff, 0, 0), "bk color %08x\n", GetBkColor(hdcDisplay));
243     ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08x\n", GetTextColor(hdcDisplay));
244     ok( GetROP2(hdcDisplay) == R2_NOT, "rop2 %d\n", GetROP2(hdcDisplay));
245     ok( GetArcDirection(hdcDisplay) == AD_CLOCKWISE, "arc dir  %d\n", GetArcDirection(hdcDisplay));
246     ok( GetPolyFillMode(hdcDisplay) == WINDING, "poly fill %d\n", GetPolyFillMode(hdcDisplay));
247     ok( GetStretchBltMode(hdcDisplay) == HALFTONE, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay));
248
249     ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
250
251     ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL),
252        "A valid hdc has to require a valid rc\n");
253
254     ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL),
255        "A null hdc does not require a valid rc\n");
256
257     ret = DeleteEnhMetaFile(hMetafile);
258     ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
259     ret = ReleaseDC(hwnd, hdcDisplay);
260     ok( ret, "ReleaseDC error %d\n", GetLastError());
261     DestroyWindow(hwnd);
262 }
263
264 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
265                                          const ENHMETARECORD *emr, int n_objs, LPARAM param)
266 {
267     static int save_state;
268     static int restore_no;
269
270     switch (emr->iType)
271     {
272     case EMR_HEADER:
273         save_state = 0;
274         restore_no = 0;
275         break;
276
277     case EMR_SAVEDC:
278         save_state++;
279         break;
280
281     case EMR_RESTOREDC:
282         {
283             const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
284             switch(++restore_no)
285             {
286             case 1:
287                 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
288                 break;
289
290             case 2:
291                 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
292                 break;
293             case 3:
294                 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
295                 break;
296             }
297             ok(restore_no <= 3, "restore_no %d\n", restore_no);
298             save_state += restoredc->iRelative;
299             break;
300         }
301     case EMR_EOF:
302         ok(save_state == 0, "EOF save_state %d\n", save_state);
303         break;
304     }
305
306
307     return 1;
308 }
309
310 static void test_SaveDC(void)
311 {
312     HDC hdcMetafile, hdcDisplay;
313     HENHMETAFILE hMetafile;
314     HWND hwnd;
315     int ret;
316     static const RECT rc = { 0, 0, 100, 100 };
317
318     /* Win9x doesn't play EMFs on invisible windows */
319     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
320                            0, 0, 200, 200, 0, 0, 0, NULL);
321     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
322
323     hdcDisplay = GetDC(hwnd);
324     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
325
326     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
327     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
328
329     /* Need to write something to the emf, otherwise Windows won't play it back */
330     LineTo(hdcMetafile, 100, 100);
331
332     ret = SaveDC(hdcMetafile);
333     ok(ret == 1, "ret = %d\n", ret);
334
335     ret = SaveDC(hdcMetafile);
336     ok(ret == 2, "ret = %d\n", ret);
337
338     ret = SaveDC(hdcMetafile);
339     ok(ret == 3, "ret = %d\n", ret);
340
341     ret = RestoreDC(hdcMetafile, -1);
342     ok(ret, "ret = %d\n", ret);
343
344     ret = SaveDC(hdcMetafile);
345     ok(ret == 3, "ret = %d\n", ret);
346
347     ret = RestoreDC(hdcMetafile, 1);
348     ok(ret, "ret = %d\n", ret);
349
350     ret = SaveDC(hdcMetafile);
351     ok(ret == 1, "ret = %d\n", ret);
352
353     ret = SaveDC(hdcMetafile);
354     ok(ret == 2, "ret = %d\n", ret);
355
356     hMetafile = CloseEnhMetaFile(hdcMetafile);
357     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
358
359     ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
360     ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
361
362     ret = DeleteEnhMetaFile(hMetafile);
363     ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
364     ret = ReleaseDC(hwnd, hdcDisplay);
365     ok( ret, "ReleaseDC error %d\n", GetLastError());
366     DestroyWindow(hwnd);
367 }
368
369 /* Win-format metafile (mfdrv) tests */
370 /* These tests compare the generated metafiles byte-by-byte */
371 /* with the nominal results. */
372
373 /* Maximum size of sample metafiles in bytes. */
374 #define MF_BUFSIZE 512
375
376 /* 8x8 bitmap data for a pattern brush */
377 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
378     0x01, 0x00, 0x02, 0x00,
379     0x03, 0x00, 0x04, 0x00,
380     0x05, 0x00, 0x06, 0x00,
381     0x07, 0x00, 0x08, 0x00
382 };
383
384 /* Sample metafiles to be compared to the outputs of the
385  * test functions.
386  */
387
388 static const unsigned char MF_BLANK_BITS[] = {
389     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
390     0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
391     0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
392 };
393
394 static const unsigned char MF_GRAPHICS_BITS[] = {
395     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
396     0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
397     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
398     0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
399     0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
400     0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
401     0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
402     0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
403     0x00, 0x00, 0x00, 0x00
404 };
405
406 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
407     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
408     0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
409     0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
410     0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
411     0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
412     0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
413     0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
414     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
415     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
416     0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
417     0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
418     0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
419     0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
420     0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
421     0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
422     0x00, 0x00
423 };
424
425 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
426 {
427     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
428     0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
429     0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
430     0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
431     0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
432     0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
433     0x00, 0x00
434 };
435
436 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
437 {
438     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
439     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
440     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
441     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
442     0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
443     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
444     0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
445     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
446     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
447     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
448     0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
449     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
450     0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
451     0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
452     0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
453     0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
454     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
455     0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
456     0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
457     0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
458     0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
459     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
460     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
461     0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
462     0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
463     0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
464     0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
465     0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
466     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
467     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
468     0x14, 0x00, 0x00, 0x00
469 };
470
471 static const unsigned char MF_LINETO_BITS[] = {
472     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
473     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
474     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
475     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
476     0x00, 0x00
477 };
478
479 static const unsigned char EMF_LINETO_BITS[] = {
480     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
481     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
482     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
483     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
484     0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
485     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
486     0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
487     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
488     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
489     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
490     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
491     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
492     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
493     0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
494     0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
495     0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
496     0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
497     0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
498     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
499     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
500     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
501     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
502     0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
503     0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
504     0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
505     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
506     0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
507     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
508     0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
509     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
510     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
511     0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
512     0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
513     0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
514     0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
515     0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
516     0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
517     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
518     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
519 };
520
521 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
522     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
523     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
524     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
525     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526     0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
527     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
528     0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
529     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
530     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
531     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
532     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
533     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
534     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
535     0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
536     0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
537     0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
538     0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
539     0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
540     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
541     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
542     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
543     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
544     0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
545     0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
546     0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
547     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
548     0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
549     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
550     0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
551     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
552     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
553     0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
554     0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
555     0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
556     0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
557     0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558     0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
559     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
560     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
561 };
562
563 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
564     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
565     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
567     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568     0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
569     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
570     0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
571     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
573     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
574     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
575     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
577     0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
578     0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
579     0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
580     0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
581     0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
582     0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
583     0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
584     0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
585     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
586     0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
587     0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
588     0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
589     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
590     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
591     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
592     0x14, 0x00, 0x00, 0x00
593 };
594
595 /* For debugging or dumping the raw metafiles produced by
596  * new test functions.
597  */
598 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
599                                  INT nobj, LPARAM param)
600 {
601     trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
602            hdc, mr->rdFunction, mr->rdSize, (void *)param);
603     return TRUE;
604 }
605
606 /* For debugging or dumping the raw metafiles produced by
607  * new test functions.
608  */
609
610 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
611 {
612     BYTE buf[MF_BUFSIZE];
613     UINT mfsize, i;
614
615     if (!winetest_debug) return;
616
617     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
618     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
619
620     printf ("MetaFile %s has bits:\n{\n    ", desc);
621     for (i=0; i<mfsize; i++)
622     {
623         printf ("0x%02x", buf[i]);
624         if (i == mfsize-1)
625             printf ("\n");
626         else if (i % 8 == 7)
627             printf (",\n    ");
628         else
629             printf (", ");
630     }
631     printf ("};\n");
632 }
633
634 /* Compare the metafile produced by a test function with the
635  * expected raw metafile data in "bits".
636  * Return value is 0 for a perfect match,
637  * -1 if lengths aren't equal,
638  * otherwise returns the number of non-matching bytes.
639  */
640
641 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
642     const char *desc)
643 {
644     unsigned char buf[MF_BUFSIZE];
645     UINT mfsize, i;
646     int diff;
647
648     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
649     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
650     if (mfsize < MF_BUFSIZE)
651         ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
652             desc, mfsize, bsize);
653     else
654         ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
655             desc, mfsize, bsize);
656     if (mfsize != bsize)
657         return -1;
658
659     diff = 0;
660     for (i=0; i<bsize; i++)
661     {
662        if (buf[i] !=  bits[i])
663            diff++;
664     }
665     ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
666         desc, mfsize, bsize, diff);
667
668     return diff; 
669 }
670
671 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
672 {
673     unsigned char buf[MF_BUFSIZE];
674     DWORD mfsize, rd_size, i;
675     int diff;
676     HANDLE hfile;
677     BOOL ret;
678
679     hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
680     assert(hfile != INVALID_HANDLE_VALUE);
681
682     mfsize = GetFileSize(hfile, NULL);
683     assert(mfsize <= MF_BUFSIZE);
684
685     ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
686     ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
687
688     CloseHandle(hfile);
689
690     ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
691
692     if (mfsize != bsize)
693         return -1;
694
695     diff = 0;
696     for (i=0; i<bsize; i++)
697     {
698         if (buf[i] != bits[i])
699             diff++;
700     }
701     ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
702         desc, mfsize, bsize, diff);
703
704     return diff; 
705 }
706
707 /* For debugging or dumping the raw EMFs produced by
708  * new test functions.
709  */
710 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
711 {
712     BYTE buf[MF_BUFSIZE];
713     UINT mfsize, i;
714
715     if (!winetest_debug) return;
716
717     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
718     ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
719
720     printf("EMF %s has bits:\n{\n    ", desc);
721     for (i = 0; i < mfsize; i++)
722     {
723         printf ("0x%02x", buf[i]);
724         if (i == mfsize-1)
725             printf ("\n");
726         else if (i % 8 == 7)
727             printf (",\n    ");
728         else
729             printf (", ");
730     }
731     printf ("};\n");
732 }
733
734 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
735 {
736     BYTE *emf;
737     BYTE buf[MF_BUFSIZE];
738     UINT mfsize, offset;
739
740     if (!winetest_debug) return;
741
742     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
743     ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
744
745     printf("EMF %s has records:\n", desc);
746
747     emf = buf;
748     offset = 0;
749     while(offset < mfsize)
750     {
751         EMR *emr = (EMR *)(emf + offset);
752         printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
753         /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
754         offset += emr->nSize;
755     }
756 }
757
758 /* Compare the EMF produced by a test function with the
759  * expected raw EMF data in "bits".
760  * Return value is 0 for a perfect match,
761  * -1 if lengths aren't equal,
762  * otherwise returns the number of non-matching bytes.
763  */
764 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
765                             UINT bsize, const char *desc, BOOL todo)
766 {
767     unsigned char buf[MF_BUFSIZE];
768     UINT mfsize, i;
769     int diff;
770
771     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
772     ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
773
774     if (mfsize < MF_BUFSIZE)
775     {
776         if (mfsize != bsize && todo)
777         {
778         todo_wine
779         ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
780         }
781         else
782         ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
783     }
784     else
785         ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
786            desc, mfsize, bsize);
787
788     if (mfsize != bsize)
789         return -1;
790
791     diff = 0;
792     for (i = 0; i < bsize; i++)
793     {
794        if (buf[i] != bits[i])
795            diff++;
796     }
797     if (diff != 0 && todo)
798     {
799         todo_wine
800         {
801             ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
802                desc, mfsize, bsize, diff);
803         }
804         return diff;
805     }
806     else
807     {
808         ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
809            desc, mfsize, bsize, diff);
810
811         return diff;
812     }
813 }
814
815 /* Test a blank metafile.  May be used as a template for new tests. */
816
817 static void test_mf_Blank(void)
818 {
819     HDC hdcMetafile;
820     HMETAFILE hMetafile;
821     INT caps;
822     BOOL ret;
823     INT type;
824
825     hdcMetafile = CreateMetaFileA(NULL);
826     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
827     trace("hdcMetafile %p\n", hdcMetafile);
828
829 /* Tests on metafile initialization */
830     caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
831     ok (caps == DT_METAFILE,
832         "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
833
834     hMetafile = CloseMetaFile(hdcMetafile);
835     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
836     type = GetObjectType(hMetafile);
837     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
838     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
839
840     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
841         "mf_blank") != 0)
842     {
843         dump_mf_bits(hMetafile, "mf_Blank");
844         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
845     }
846
847     ret = DeleteMetaFile(hMetafile);
848     ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
849 }
850
851 static void test_CopyMetaFile(void)
852 {
853     HDC hdcMetafile;
854     HMETAFILE hMetafile, hmf_copy;
855     BOOL ret;
856     char temp_path[MAX_PATH];
857     char mf_name[MAX_PATH];
858     INT type;
859
860     hdcMetafile = CreateMetaFileA(NULL);
861     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
862     trace("hdcMetafile %p\n", hdcMetafile);
863
864     hMetafile = CloseMetaFile(hdcMetafile);
865     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
866     type = GetObjectType(hMetafile);
867     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
868
869     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
870         "mf_blank") != 0)
871     {
872         dump_mf_bits(hMetafile, "mf_Blank");
873         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
874     }
875
876     GetTempPathA(MAX_PATH, temp_path);
877     GetTempFileNameA(temp_path, "wmf", 0, mf_name);
878
879     hmf_copy = CopyMetaFileA(hMetafile, mf_name);
880     ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
881
882     type = GetObjectType(hmf_copy);
883     ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
884
885     ret = DeleteMetaFile(hMetafile);
886     ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
887
888     if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
889     {
890         dump_mf_bits(hMetafile, "mf_Blank");
891         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
892     }
893
894     ret = DeleteMetaFile(hmf_copy);
895     ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
896
897     DeleteFileA(mf_name);
898 }
899
900 static void test_SetMetaFileBits(void)
901 {
902     HMETAFILE hmf;
903     INT type;
904     BOOL ret;
905     BYTE buf[256];
906     METAHEADER *mh;
907
908     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
909     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
910     type = GetObjectType(hmf);
911     ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
912
913     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
914     {
915         dump_mf_bits(hmf, "mf_Graphics");
916         EnumMetaFile(0, hmf, mf_enum_proc, 0);
917     }
918
919     ret = DeleteMetaFile(hmf);
920     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
921
922     /* NULL data crashes XP SP1 */
923     /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
924
925     /* Now with not zero size */
926     SetLastError(0xdeadbeef);
927     hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
928     ok(!hmf, "SetMetaFileBitsEx should fail\n");
929     ok(GetLastError() == ERROR_INVALID_DATA, "wrong error %d\n", GetLastError());
930
931     /* Now with not even size */
932     SetLastError(0xdeadbeef);
933     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
934     ok(!hmf, "SetMetaFileBitsEx should fail\n");
935     ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
936
937     /* Now with zeroed out or faked some header fields */
938     assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
939     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
940     mh = (METAHEADER *)buf;
941     /* corruption of any of the below fields leads to a failure */
942     mh->mtType = 0;
943     mh->mtVersion = 0;
944     mh->mtHeaderSize = 0;
945     SetLastError(0xdeadbeef);
946     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
947     ok(!hmf, "SetMetaFileBitsEx should fail\n");
948     ok(GetLastError() == ERROR_INVALID_DATA, "wrong error %d\n", GetLastError());
949
950     /* Now with corrupted mtSize field */
951     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
952     mh = (METAHEADER *)buf;
953     /* corruption of mtSize doesn't lead to a failure */
954     mh->mtSize *= 2;
955     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
956     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
957
958     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
959     {
960         dump_mf_bits(hmf, "mf_Graphics");
961         EnumMetaFile(0, hmf, mf_enum_proc, 0);
962     }
963
964     ret = DeleteMetaFile(hmf);
965     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
966
967     /* Now with zeroed out mtSize field */
968     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
969     mh = (METAHEADER *)buf;
970     /* zeroing mtSize doesn't lead to a failure */
971     mh->mtSize = 0;
972     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
973     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
974
975     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
976     {
977         dump_mf_bits(hmf, "mf_Graphics");
978         EnumMetaFile(0, hmf, mf_enum_proc, 0);
979     }
980
981     ret = DeleteMetaFile(hmf);
982     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
983 }
984
985 /* Simple APIs from mfdrv/graphics.c
986  */
987
988 static void test_mf_Graphics(void)
989 {
990     HDC hdcMetafile;
991     HMETAFILE hMetafile;
992     POINT oldpoint;
993     BOOL ret;
994
995     hdcMetafile = CreateMetaFileA(NULL);
996     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
997     trace("hdcMetafile %p\n", hdcMetafile);
998
999     ret = MoveToEx(hdcMetafile, 1, 1, NULL);
1000     ok( ret, "MoveToEx error %d.\n", GetLastError());
1001     ret = LineTo(hdcMetafile, 2, 2);
1002     ok( ret, "LineTo error %d.\n", GetLastError());
1003     ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
1004     ok( ret, "MoveToEx error %d.\n", GetLastError());
1005
1006 /* oldpoint gets garbage under Win XP, so the following test would
1007  * work under Wine but fails under Windows:
1008  *
1009  *   ok((oldpoint.x == 2) && (oldpoint.y == 2),
1010  *       "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
1011  *       oldpoint.x, oldpoint.y);
1012  */
1013
1014     ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
1015     ok( ret, "Ellipse error %d.\n", GetLastError());
1016
1017     hMetafile = CloseMetaFile(hdcMetafile);
1018     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1019     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1020
1021     if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
1022         "mf_Graphics") != 0)
1023     {
1024         dump_mf_bits(hMetafile, "mf_Graphics");
1025         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1026     }
1027
1028     ret = DeleteMetaFile(hMetafile);
1029     ok( ret, "DeleteMetaFile(%p) error %d\n",
1030         hMetafile, GetLastError());
1031 }
1032
1033 static void test_mf_PatternBrush(void)
1034 {
1035     HDC hdcMetafile;
1036     HMETAFILE hMetafile;
1037     LOGBRUSH *orig_lb;
1038     HBRUSH hBrush;
1039     BOOL ret;
1040
1041     orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
1042
1043     orig_lb->lbStyle = BS_PATTERN;
1044     orig_lb->lbColor = RGB(0, 0, 0);
1045     orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
1046     ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
1047
1048     hBrush = CreateBrushIndirect (orig_lb);
1049     ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
1050
1051     hdcMetafile = CreateMetaFileA(NULL);
1052     ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
1053     trace("hdcMetafile %p\n", hdcMetafile);
1054
1055     hBrush = SelectObject(hdcMetafile, hBrush);
1056     ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1057
1058     hMetafile = CloseMetaFile(hdcMetafile);
1059     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1060     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1061
1062     if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
1063         "mf_Pattern_Brush") != 0)
1064     {
1065         dump_mf_bits(hMetafile, "mf_Pattern_Brush");
1066         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1067     }
1068
1069     ret = DeleteMetaFile(hMetafile);
1070     ok( ret, "DeleteMetaFile error %d\n", GetLastError());
1071     ret = DeleteObject(hBrush);
1072     ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1073     ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
1074     ok( ret, "DeleteObject(HBITMAP) error %d\n",
1075         GetLastError());
1076     HeapFree (GetProcessHeap(), 0, orig_lb);
1077 }
1078
1079 static void test_mf_ExtTextOut_on_path(void)
1080 {
1081     HDC hdcMetafile;
1082     HMETAFILE hMetafile;
1083     BOOL ret;
1084     static const INT dx[4] = { 3, 5, 8, 12 };
1085
1086     hdcMetafile = CreateMetaFileA(NULL);
1087     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1088     trace("hdcMetafile %p\n", hdcMetafile);
1089
1090     ret = BeginPath(hdcMetafile);
1091     ok(!ret, "BeginPath on metafile DC should fail\n");
1092
1093     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1094     ok(ret, "ExtTextOut error %d\n", GetLastError());
1095
1096     ret = EndPath(hdcMetafile);
1097     ok(!ret, "EndPath on metafile DC should fail\n");
1098
1099     hMetafile = CloseMetaFile(hdcMetafile);
1100     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1101
1102     if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
1103         "mf_TextOut_on_path") != 0)
1104     {
1105         dump_mf_bits(hMetafile, "mf_TextOut_on_path");
1106         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1107     }
1108
1109     ret = DeleteMetaFile(hMetafile);
1110     ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1111 }
1112
1113 static void test_emf_ExtTextOut_on_path(void)
1114 {
1115     HWND hwnd;
1116     HDC hdcDisplay, hdcMetafile;
1117     HENHMETAFILE hMetafile;
1118     BOOL ret;
1119     static const INT dx[4] = { 3, 5, 8, 12 };
1120
1121     /* Win9x doesn't play EMFs on invisible windows */
1122     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1123                            0, 0, 200, 200, 0, 0, 0, NULL);
1124     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1125
1126     hdcDisplay = GetDC(hwnd);
1127     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
1128
1129     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
1130     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1131
1132     ret = BeginPath(hdcMetafile);
1133     ok(ret, "BeginPath error %d\n", GetLastError());
1134
1135     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1136     ok(ret, "ExtTextOut error %d\n", GetLastError());
1137
1138     ret = EndPath(hdcMetafile);
1139     ok(ret, "EndPath error %d\n", GetLastError());
1140
1141     hMetafile = CloseEnhMetaFile(hdcMetafile);
1142     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1143
1144     /* this doesn't succeed yet: EMF has correct size, all EMF records
1145      * are there, but their contents don't match for different reasons.
1146      */
1147     if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
1148         "emf_TextOut_on_path", TRUE) != 0)
1149     {
1150         dump_emf_bits(hMetafile, "emf_TextOut_on_path");
1151         dump_emf_records(hMetafile, "emf_TextOut_on_path");
1152     }
1153
1154     ret = DeleteEnhMetaFile(hMetafile);
1155     ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1156     ret = ReleaseDC(hwnd, hdcDisplay);
1157     ok(ret, "ReleaseDC error %d\n", GetLastError());
1158     DestroyWindow(hwnd);
1159 }
1160
1161 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
1162 {
1163     LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
1164     POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
1165     /* When using MM_TEXT Win9x does not update the mapping mode 
1166      * until a record is played which actually outputs something */
1167     PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
1168     LPtoDP(hdc, mapping, 2);
1169     trace("Meta record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
1170            lpEMFR->iType, lpEMFR->nSize,
1171            mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
1172
1173     if (lpEMFR->iType == EMR_LINETO)
1174     {
1175         INT x0, y0, x1, y1;
1176         if (!lpMFP || lpMFP->mm == MM_TEXT)
1177         {
1178             x0 = 0;
1179             y0 = 0;
1180             x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
1181             y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
1182         }
1183         else
1184         {
1185             ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
1186             
1187             x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1188             y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1189             x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1190             y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1191         }
1192         ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
1193             "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
1194             mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
1195             x0, y0, x1, y1);
1196     }
1197     return TRUE;
1198 }
1199
1200 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
1201 {
1202     HDC hdcMf;
1203     HMETAFILE hmf;
1204     BOOL ret;
1205     UINT size;
1206     LPBYTE pBits;
1207
1208     hdcMf = CreateMetaFile(NULL);
1209     ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
1210     ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
1211     ok(ret, "LineTo failed with error %d\n", GetLastError());
1212     hmf = CloseMetaFile(hdcMf);
1213     ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
1214
1215     if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
1216     {
1217         dump_mf_bits(hmf, "mf_LineTo");
1218         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1219     }
1220
1221     size = GetMetaFileBitsEx(hmf, 0, NULL);
1222     ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
1223     pBits = HeapAlloc(GetProcessHeap(), 0, size);
1224     GetMetaFileBitsEx(hmf, size, pBits);
1225     DeleteMetaFile(hmf);
1226     return SetWinMetaFileBits(size, pBits, NULL, mfp);
1227 }
1228
1229 static void test_mf_conversions(void)
1230 {
1231     trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
1232     {
1233         HDC hdcOffscreen = CreateCompatibleDC(NULL);
1234         HENHMETAFILE hemf;
1235         METAFILEPICT mfp;
1236         RECT rect = { 0, 0, 100, 100 };
1237         mfp.mm = MM_ANISOTROPIC;
1238         mfp.xExt = 100;
1239         mfp.yExt = 100;
1240         mfp.hMF = NULL;
1241         hemf = create_converted_emf(&mfp);
1242
1243         if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
1244                              "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
1245         {
1246             dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
1247             dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
1248         }
1249
1250         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
1251
1252         DeleteEnhMetaFile(hemf);
1253         DeleteDC(hdcOffscreen);
1254     }
1255
1256     trace("Testing MF->EMF conversion (MM_TEXT)\n");
1257     {
1258         HDC hdcOffscreen = CreateCompatibleDC(NULL);
1259         HENHMETAFILE hemf;
1260         METAFILEPICT mfp;
1261         RECT rect = { 0, 0, 100, 100 };
1262         mfp.mm = MM_TEXT;
1263         mfp.xExt = 0;
1264         mfp.yExt = 0;
1265         mfp.hMF = NULL;
1266         hemf = create_converted_emf(&mfp);
1267
1268         if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
1269                              "emf_LineTo MM_TEXT", TRUE) != 0)
1270         {
1271             dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
1272             dump_emf_records(hemf, "emf_LineTo MM_TEXT");
1273         }
1274
1275         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
1276
1277         DeleteEnhMetaFile(hemf);
1278         DeleteDC(hdcOffscreen);
1279     }
1280
1281     trace("Testing MF->EMF conversion (NULL mfp)\n");
1282     {
1283         HDC hdcOffscreen = CreateCompatibleDC(NULL);
1284         HENHMETAFILE hemf;
1285         RECT rect = { 0, 0, 100, 100 };
1286         hemf = create_converted_emf(NULL);
1287
1288         if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
1289                              "emf_LineTo NULL", TRUE) != 0)
1290         {
1291             dump_emf_bits(hemf, "emf_LineTo NULL");
1292             dump_emf_records(hemf, "emf_LineTo NULL");
1293         }
1294
1295         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
1296
1297         DeleteEnhMetaFile(hemf);
1298         DeleteDC(hdcOffscreen);
1299     }
1300 }
1301
1302 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
1303                                        LONG mm, LONG xExt, LONG yExt,
1304                                        RECTL * rclBounds, RECTL * rclFrame)
1305 {
1306   METAFILEPICT mfp;
1307   METAFILEPICT * mfpPtr = NULL;
1308   HENHMETAFILE emf;
1309   ENHMETAHEADER header;
1310   UINT res;
1311
1312   if (!mfpIsNull)
1313   {
1314     mfp.mm = mm;
1315     mfp.xExt = xExt;
1316     mfp.yExt = yExt;
1317     mfpPtr = &mfp;
1318   }
1319
1320   emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
1321   ok(emf != NULL, "SetWinMetaFileBits failed\n");
1322   if (!emf) return FALSE;
1323   res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
1324   ok(res != 0, "GetEnhMetaHeader failed\n");
1325   DeleteEnhMetaFile(emf);
1326   if (!res) return FALSE;
1327
1328   *rclBounds = header.rclBounds;
1329   *rclFrame = header.rclFrame;
1330   return TRUE;
1331 }
1332
1333 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
1334                                          LONG mm, LONG xExt, LONG yExt,
1335                                          RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
1336 {
1337   RECTL rclBounds, rclFrame;
1338
1339   if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
1340   {
1341     const char * msg;
1342     char buf[64];
1343
1344     if (mfpIsNull)
1345     {
1346        msg = "mfp == NULL";
1347     }
1348     else
1349     {
1350       const char * mm_str;
1351       switch (mm)
1352       {
1353          case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
1354          case MM_ISOTROPIC:   mm_str = "MM_ISOTROPIC"; break;
1355          default:             mm_str = "Unexpected";
1356       }
1357       sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
1358       msg = buf;
1359     }
1360
1361     ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
1362     ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
1363     ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
1364     ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
1365     ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
1366     ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
1367     ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
1368     ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
1369   }
1370 }
1371
1372 static void test_SetWinMetaFileBits(void)
1373 {
1374   HMETAFILE wmf;
1375   HDC wmfDC;
1376   BYTE * buffer;
1377   UINT buffer_size;
1378   RECT rect;
1379   UINT res;
1380   RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
1381   RECTL rclBoundsIsotropic, rclFrameIsotropic;
1382   RECTL rclBounds, rclFrame;
1383   HDC dc;
1384   LONG diffx, diffy;
1385
1386   wmfDC = CreateMetaFile(NULL);
1387   ok(wmfDC != NULL, "CreateMetaFile failed\n");
1388   if (!wmfDC) return;
1389
1390   SetWindowExtEx(wmfDC, 100, 100, NULL);
1391   rect.left = rect.top = 0;
1392   rect.right = rect.bottom = 50;
1393   FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
1394   wmf = CloseMetaFile(wmfDC);
1395   ok(wmf != NULL, "Metafile creation failed\n");
1396   if (!wmf) return;
1397
1398   buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
1399   ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
1400   if (buffer_size == 0)
1401   {
1402     DeleteMetaFile(wmf);
1403     return;
1404   }
1405
1406   buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
1407   ok(buffer != NULL, "HeapAlloc failed\n");
1408   if (!buffer)
1409   {
1410     DeleteMetaFile(wmf);
1411     return;
1412   }
1413
1414   res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
1415   ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
1416   DeleteMetaFile(wmf);
1417   if (res != buffer_size)
1418   {
1419      HeapFree(GetProcessHeap(), 0, buffer);
1420      return;
1421   }
1422
1423   /* Get the reference bounds and frame */
1424   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1425   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0,  &rclBoundsIsotropic, &rclFrameIsotropic);
1426
1427   ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
1428      rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
1429      "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
1430
1431   ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
1432   ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
1433   diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
1434   if (diffx < 0) diffx = -diffx;
1435   ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
1436
1437   dc = CreateCompatibleDC(NULL);
1438   todo_wine
1439   {
1440   ok(rclBoundsAnisotropic.right == GetDeviceCaps(dc, HORZRES) / 2 - 1 &&
1441      rclBoundsAnisotropic.bottom == GetDeviceCaps(dc, VERTRES) / 2 - 1,
1442      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
1443      GetDeviceCaps(dc, HORZRES) / 2 - 1, GetDeviceCaps(dc, VERTRES) / 2 - 1, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
1444   }
1445
1446   /* Allow 1 mm difference (rounding errors) */
1447   diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
1448   diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
1449   if (diffx < 0) diffx = -diffx;
1450   if (diffy < 0) diffy = -diffy;
1451   todo_wine
1452   {
1453   ok(diffx <= 1 && diffy <= 1,
1454      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
1455      GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
1456   }
1457   DeleteDC(dc);
1458
1459   /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
1460   checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1461
1462   /* If xExt or yExt is zero or negative, the whole device surface is used */
1463   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1464   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
1465   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1466   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1467   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1468   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
1469   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1470   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1471   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1472   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1473   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1474   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1475
1476   /* MSDN says that negative xExt and yExt values specify a ratio.
1477      Check that this is wrong and the whole device surface is used */
1478   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1479   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
1480
1481   /* Ordinary conversions */
1482
1483   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
1484   {
1485     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
1486        "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
1487     ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
1488        "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
1489   }
1490
1491   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
1492   {
1493     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
1494        "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
1495     ok(rclBounds.left == 0 && rclBounds.top == 0,
1496        "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
1497
1498     /* Wine has a rounding error */
1499     diffx = rclBounds.right - rclBounds.bottom;
1500     if (diffx < 0) diffx = -diffx;
1501     ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
1502   }
1503
1504   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
1505   {
1506     ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
1507        "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
1508   }
1509
1510   HeapFree(GetProcessHeap(), 0, buffer);
1511 }
1512
1513 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
1514 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
1515 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
1516
1517 static void test_gdiis(void)
1518 {
1519     RECT rect = {0,0,100,100};
1520     HDC hdc, hemfDC, hmfDC;
1521     HENHMETAFILE hemf;
1522     HMODULE hgdi32;
1523
1524     /* resolve all the functions */
1525     hgdi32 = GetModuleHandle("gdi32");
1526     pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
1527     pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
1528     pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
1529
1530     /* they should all exist or none should exist */
1531     if(!pGdiIsMetaPrintDC)
1532         return;
1533
1534     /* try with nothing */
1535     ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
1536     ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
1537     ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
1538
1539     /* try with a metafile */
1540     hmfDC = CreateMetaFile(NULL);
1541     ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
1542     ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
1543     ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
1544     DeleteMetaFile(CloseMetaFile(hmfDC));
1545
1546     /* try with an enhanced metafile */
1547     hdc = GetDC(NULL);
1548     hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
1549     ok(hemfDC != NULL, "failed to create emf\n");
1550
1551     ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
1552     ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
1553     ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
1554
1555     hemf = CloseEnhMetaFile(hemfDC);
1556     ok(hemf != NULL, "failed to close EMF\n");
1557     DeleteEnhMetaFile(hemf);
1558     ReleaseDC(NULL,hdc);
1559 }
1560
1561 static void test_SetEnhMetaFileBits(void)
1562 {
1563     BYTE data[256];
1564     HENHMETAFILE hemf;
1565     ENHMETAHEADER *emh;
1566
1567     memset(data, 0xAA, sizeof(data));
1568     SetLastError(0xdeadbeef);
1569     hemf = SetEnhMetaFileBits(sizeof(data), data);
1570     ok(!hemf, "SetEnhMetaFileBits should fail\n");
1571     ok(GetLastError() == ERROR_INVALID_DATA, "expected ERROR_INVALID_DATA, got %u\n", GetLastError());
1572
1573     emh = (ENHMETAHEADER *)data;
1574     memset(emh, 0, sizeof(*emh));
1575
1576     emh->iType = EMR_HEADER;
1577     emh->nSize = sizeof(*emh);
1578     emh->dSignature = ENHMETA_SIGNATURE;
1579     /* emh->nVersion  = 0x10000; XP doesn't care about version */
1580     emh->nBytes = sizeof(*emh);
1581     /* emh->nRecords = 1; XP doesn't care about records */
1582     emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
1583
1584     SetLastError(0xdeadbeef);
1585     hemf = SetEnhMetaFileBits(emh->nBytes, data);
1586     ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
1587     DeleteEnhMetaFile(hemf);
1588
1589     /* XP refuses to load unaligned EMF */
1590     emh->nBytes++;
1591     SetLastError(0xdeadbeef);
1592     hemf = SetEnhMetaFileBits(emh->nBytes, data);
1593     ok(!hemf, "SetEnhMetaFileBits should fail\n");
1594     /* XP doesn't set error in this case */
1595
1596     emh->dSignature = 0;
1597     emh->nBytes--;
1598     SetLastError(0xdeadbeef);
1599     hemf = SetEnhMetaFileBits(emh->nBytes, data);
1600     ok(!hemf, "SetEnhMetaFileBits should fail\n");
1601     /* XP doesn't set error in this case */
1602 }
1603
1604 START_TEST(metafile)
1605 {
1606     init_function_pointers();
1607
1608     /* For enhanced metafiles (enhmfdrv) */
1609     test_ExtTextOut();
1610     test_SaveDC();
1611
1612     /* For win-format metafiles (mfdrv) */
1613     test_mf_Blank();
1614     test_mf_Graphics();
1615     test_mf_PatternBrush();
1616     test_CopyMetaFile();
1617     test_SetMetaFileBits();
1618     test_mf_ExtTextOut_on_path();
1619     test_emf_ExtTextOut_on_path();
1620
1621     /* For metafile conversions */
1622     test_mf_conversions();
1623     test_SetWinMetaFileBits();
1624
1625     test_gdiis();
1626     test_SetEnhMetaFileBits();
1627 }