Stub implementation for MsiGetFileHashA/W.
[wine] / dlls / gdi / 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 %ld, emr->nSize %ld, 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 %08lx\n", GetBkColor(hdc));
81         ok(GetTextColor(hdc) == RGB(0x0, 0x0, 0x0), "text color %08lx\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 %ld\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[%ld] (%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 %ld\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[%ld] (%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 %ld\n", GetLastError());
167
168     hdcDisplay = GetDC(hwnd);
169     ok(hdcDisplay != 0, "GetDC error %ld\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 %ld\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 %ld\n", GetLastError());
193     }
194     hFont = SelectObject(hdcDisplay, hFont);
195
196     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
197     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %ld\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 %ld\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 %ld\n", GetLastError());
213
214     hFont = SelectObject(hdcMetafile, hFont);
215     ret = DeleteObject(hFont);
216     ok( ret, "DeleteObject error %ld\n", GetLastError());
217
218     hMetafile = CloseEnhMetaFile(hdcMetafile);
219     ok(hMetafile != 0, "CloseEnhMetaFile error %ld\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 %ld\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 %ld\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 %08lx\n", GetBkColor(hdcDisplay));
243     ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08lx\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 %ld\n", GetLastError());
259     ret = ReleaseDC(hwnd, hdcDisplay);
260     ok( ret, "ReleaseDC error %ld\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             EMRRESTOREDC *restoredc = (EMRRESTOREDC *)emr;
284             switch(++restore_no)
285             {
286             case 1:
287                 ok(restoredc->iRelative == -1, "first restore %ld\n", restoredc->iRelative);
288                 break;
289
290             case 2:
291                 ok(restoredc->iRelative == -3, "second restore %ld\n", restoredc->iRelative);
292                 break;
293             case 3:
294                 ok(restoredc->iRelative == -2, "third restore %ld\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 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 %ld\n", GetLastError());
322
323     hdcDisplay = GetDC(hwnd);
324     ok(hdcDisplay != 0, "GetDC error %ld\n", GetLastError());
325
326     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
327     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %ld\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 %ld\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 %ld\n", GetLastError());
364     ret = ReleaseDC(hwnd, hdcDisplay);
365     ok( ret, "ReleaseDC error %ld\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 256
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 /* For debugging or dumping the raw metafiles produced by
426  * new test functions.
427  */
428
429 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
430 {
431     char buf[MF_BUFSIZE];
432     UINT mfsize, i;
433
434     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
435     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
436
437     printf ("MetaFile %s has bits:\n{\n    ", desc);
438     for (i=0; i<mfsize; i++)
439     {
440         printf ("0x%.2hhx", buf[i]);
441         if (i == mfsize-1)
442             printf ("\n");
443         else if (i % 8 == 7)
444             printf (",\n    ");
445         else
446             printf (", ");
447     }
448     printf ("};\n");
449 }
450
451 /* Compare the metafile produced by a test function with the
452  * expected raw metafile data in "bits".
453  * Return value is 0 for a perfect match,
454  * -1 if lengths aren't equal,
455  * otherwise returns the number of non-matching bytes.
456  */
457
458 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
459     const char *desc)
460 {
461     unsigned char buf[MF_BUFSIZE];
462     UINT mfsize, i;
463     int diff;
464
465     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
466     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
467     if (mfsize < MF_BUFSIZE)
468         ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
469             desc, mfsize, bsize);
470     else
471         ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
472             desc, mfsize, bsize);
473     if (mfsize != bsize)
474         return -1;
475
476     diff = 0;
477     for (i=0; i<bsize; i++)
478     {
479        if (buf[i] !=  bits[i])
480            diff++;
481     }
482     ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
483         desc, mfsize, bsize, diff);
484
485     return diff; 
486 }
487
488 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
489 {
490     unsigned char buf[MF_BUFSIZE];
491     DWORD mfsize, rd_size, i;
492     int diff;
493     HANDLE hfile;
494     BOOL ret;
495
496     hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
497     assert(hfile != INVALID_HANDLE_VALUE);
498
499     mfsize = GetFileSize(hfile, NULL);
500     assert(mfsize <= MF_BUFSIZE);
501
502     ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
503     ok( ret && rd_size == mfsize, "ReadFile: error %ld\n", GetLastError());
504
505     CloseHandle(hfile);
506
507     ok(mfsize == bsize, "%s: mfsize=%ld, bsize=%d.\n", desc, mfsize, bsize);
508
509     if (mfsize != bsize)
510         return -1;
511
512     diff = 0;
513     for (i=0; i<bsize; i++)
514     {
515         if (buf[i] != bits[i])
516             diff++;
517     }
518     ok(diff == 0, "%s: mfsize=%ld, bsize=%d, diff=%d\n",
519         desc, mfsize, bsize, diff);
520
521     return diff; 
522 }
523
524 /* Test a blank metafile.  May be used as a template for new tests. */
525
526 static void test_mf_Blank(void)
527 {
528     HDC hdcMetafile;
529     HMETAFILE hMetafile;
530     INT caps;
531     BOOL ret;
532     INT type;
533
534     hdcMetafile = CreateMetaFileA(NULL);
535     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError());
536     trace("hdcMetafile %p\n", hdcMetafile);
537
538 /* Tests on metafile initialization */
539     caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
540     ok (caps == DT_METAFILE,
541         "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
542
543     hMetafile = CloseMetaFile(hdcMetafile);
544     ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
545     type = GetObjectType(hMetafile);
546     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
547     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
548
549     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
550         "mf_blank") != 0)
551             dump_mf_bits (hMetafile, "mf_Blank");
552
553     ret = DeleteMetaFile(hMetafile);
554     ok( ret, "DeleteMetaFile(%p) error %ld\n", hMetafile, GetLastError());
555 }
556
557 static void test_CopyMetaFile(void)
558 {
559     HDC hdcMetafile;
560     HMETAFILE hMetafile, hmf_copy;
561     BOOL ret;
562     char temp_path[MAX_PATH];
563     char mf_name[MAX_PATH];
564     INT type;
565
566     hdcMetafile = CreateMetaFileA(NULL);
567     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError());
568     trace("hdcMetafile %p\n", hdcMetafile);
569
570     hMetafile = CloseMetaFile(hdcMetafile);
571     ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
572     type = GetObjectType(hMetafile);
573     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
574
575     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
576         "mf_blank") != 0)
577             dump_mf_bits (hMetafile, "mf_Blank");
578
579     GetTempPathA(MAX_PATH, temp_path);
580     GetTempFileNameA(temp_path, "wmf", 0, mf_name);
581
582     hmf_copy = CopyMetaFileA(hMetafile, mf_name);
583     ok(hmf_copy != 0, "CopyMetaFile error %ld\n", GetLastError());
584
585     type = GetObjectType(hmf_copy);
586     ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
587
588     ret = DeleteMetaFile(hMetafile);
589     ok( ret, "DeleteMetaFile(%p) error %ld\n", hMetafile, GetLastError());
590
591     if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
592         dump_mf_bits(hmf_copy, "mf_Blank");
593
594     ret = DeleteMetaFile(hmf_copy);
595     ok( ret, "DeleteMetaFile(%p) error %ld\n", hmf_copy, GetLastError());
596
597     DeleteFileA(mf_name);
598 }
599
600 static void test_SetMetaFileBits(void)
601 {
602     HMETAFILE hmf;
603     INT type;
604     BOOL ret;
605     BYTE buf[256];
606     METAHEADER *mh;
607
608     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
609     ok(hmf != 0, "SetMetaFileBitsEx error %ld\n", GetLastError());
610     type = GetObjectType(hmf);
611     ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
612
613     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
614         dump_mf_bits(hmf, "mf_Graphics");
615
616     ret = DeleteMetaFile(hmf);
617     ok(ret, "DeleteMetaFile(%p) error %ld\n", hmf, GetLastError());
618
619     /* NULL data crashes XP SP1 */
620     /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
621
622     /* Now with not zero size */
623     SetLastError(0xdeadbeef);
624     hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
625     ok(!hmf, "SetMetaFileBitsEx should fail\n");
626     ok(GetLastError() == ERROR_INVALID_DATA, "wrong error %ld\n", GetLastError());
627
628     /* Now with not even size */
629     SetLastError(0xdeadbeef);
630     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
631     ok(!hmf, "SetMetaFileBitsEx should fail\n");
632     ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %ld\n", GetLastError());
633
634     /* Now with zeroed out or faked some header fields */
635     assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
636     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
637     mh = (METAHEADER *)buf;
638     /* corruption of any of the below fields leads to a failure */
639     mh->mtType = 0;
640     mh->mtVersion = 0;
641     mh->mtHeaderSize = 0;
642     SetLastError(0xdeadbeef);
643     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
644     ok(!hmf, "SetMetaFileBitsEx should fail\n");
645     ok(GetLastError() == ERROR_INVALID_DATA, "wrong error %ld\n", GetLastError());
646
647     /* Now with corrupted mtSize field */
648     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
649     mh = (METAHEADER *)buf;
650     /* corruption of mtSize doesn't lead to a failure */
651     mh->mtSize *= 2;
652     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
653     ok(hmf != 0, "SetMetaFileBitsEx error %ld\n", GetLastError());
654
655     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
656         dump_mf_bits(hmf, "mf_Graphics");
657
658     ret = DeleteMetaFile(hmf);
659     ok(ret, "DeleteMetaFile(%p) error %ld\n", hmf, GetLastError());
660
661     /* Now with zeroed out mtSize field */
662     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
663     mh = (METAHEADER *)buf;
664     /* zeroing mtSize doesn't lead to a failure */
665     mh->mtSize = 0;
666     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
667     ok(hmf != 0, "SetMetaFileBitsEx error %ld\n", GetLastError());
668
669     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
670         dump_mf_bits(hmf, "mf_Graphics");
671
672     ret = DeleteMetaFile(hmf);
673     ok(ret, "DeleteMetaFile(%p) error %ld\n", hmf, GetLastError());
674 }
675
676 /* Simple APIs from mfdrv/graphics.c
677  */
678
679 static void test_mf_Graphics(void)
680 {
681     HDC hdcMetafile;
682     HMETAFILE hMetafile;
683     POINT oldpoint;
684     BOOL ret;
685
686     hdcMetafile = CreateMetaFileA(NULL);
687     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError());
688     trace("hdcMetafile %p\n", hdcMetafile);
689
690     ret = MoveToEx(hdcMetafile, 1, 1, NULL);
691     ok( ret, "MoveToEx error %ld.\n", GetLastError());
692     ret = LineTo(hdcMetafile, 2, 2);
693     ok( ret, "LineTo error %ld.\n", GetLastError());
694     ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
695     ok( ret, "MoveToEx error %ld.\n", GetLastError());
696
697 /* oldpoint gets garbage under Win XP, so the following test would
698  * work under Wine but fails under Windows:
699  *
700  *   ok((oldpoint.x == 2) && (oldpoint.y == 2),
701  *       "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
702  *       oldpoint.x, oldpoint.y);
703  */
704
705     ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
706     ok( ret, "Ellipse error %ld.\n", GetLastError());
707
708     hMetafile = CloseMetaFile(hdcMetafile);
709     ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
710     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
711
712     if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
713         "mf_Graphics") != 0)
714             dump_mf_bits (hMetafile, "mf_Graphics");
715
716     ret = DeleteMetaFile(hMetafile);
717     ok( ret, "DeleteMetaFile(%p) error %ld\n",
718         hMetafile, GetLastError());
719 }
720
721 static void test_mf_PatternBrush(void)
722 {
723     HDC hdcMetafile;
724     HMETAFILE hMetafile;
725     LOGBRUSH *orig_lb;
726     HBRUSH hBrush;
727     BOOL ret;
728
729     orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
730
731     orig_lb->lbStyle = BS_PATTERN;
732     orig_lb->lbColor = RGB(0, 0, 0);
733     orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
734     ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %ld.\n", GetLastError());
735
736     hBrush = CreateBrushIndirect (orig_lb);
737     ok(hBrush != 0, "CreateBrushIndirect error %ld\n", GetLastError());
738
739     hdcMetafile = CreateMetaFileA(NULL);
740     ok(hdcMetafile != 0, "CreateMetaFileA error %ld\n", GetLastError());
741     trace("hdcMetafile %p\n", hdcMetafile);
742
743     hBrush = SelectObject(hdcMetafile, hBrush);
744     ok(hBrush != 0, "SelectObject error %ld.\n", GetLastError());
745
746     hMetafile = CloseMetaFile(hdcMetafile);
747     ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
748     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
749
750     if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
751         "mf_Pattern_Brush") != 0)
752             dump_mf_bits (hMetafile, "mf_Pattern_Brush");
753
754     ret = DeleteMetaFile(hMetafile);
755     ok( ret, "DeleteMetaFile error %ld\n", GetLastError());
756     ret = DeleteObject(hBrush);
757     ok( ret, "DeleteObject(HBRUSH) error %ld\n", GetLastError());
758     ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
759     ok( ret, "DeleteObject(HBITMAP) error %ld\n",
760         GetLastError());
761     HeapFree (GetProcessHeap(), 0, orig_lb);
762 }
763
764 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
765 {
766     LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
767     POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
768     /* When using MM_TEXT Win9x does not update the mapping mode 
769      * until a record is played which actually outputs something */
770     PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
771     LPtoDP(hdc, mapping, 2);
772     trace("Meta record: iType = %ld, (%ld,%ld)-(%ld,%ld)\n", lpEMFR->iType, mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
773     if (lpEMFR->iType == EMR_LINETO)
774     {
775         INT x0, y0, x1, y1;
776         if (!lpMFP || lpMFP->mm == MM_TEXT)
777         {
778             x0 = 0;
779             y0 = 0;
780             x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
781             y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
782         }
783         else
784         {
785             ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%ld\n", lpMFP->mm);
786             
787             x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
788             y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
789             x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
790             y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
791         }
792         ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
793             "(%ld,%ld)->(%ld,%ld), expected (%d,%d)->(%d,%d)\n",
794             mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
795             x0, y0, x1, y1);
796     }
797     return TRUE;
798 }
799
800 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
801 {
802     HDC hdcMf;
803     HMETAFILE hmf;
804     BOOL ret;
805     UINT size;
806     LPBYTE pBits;
807
808     hdcMf = CreateMetaFile(NULL);
809     ok(hdcMf != NULL, "CreateMetaFile failed with error %ld\n", GetLastError());
810     ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
811     ok(ret, "LineTo failed with error %ld\n", GetLastError());
812     hmf = CloseMetaFile(hdcMf);
813     ok(hmf != NULL, "CloseMetaFile failed with error %ld\n", GetLastError());
814     size = GetMetaFileBitsEx(hmf, 0, NULL);
815     ok(size, "GetMetaFileBitsEx failed with error %ld\n", GetLastError());
816     pBits = HeapAlloc(GetProcessHeap(), 0, size);
817     GetMetaFileBitsEx(hmf, size, pBits);
818     DeleteMetaFile(hmf);
819     return SetWinMetaFileBits(size, pBits, NULL, mfp);
820 }
821
822 static void test_mf_conversions(void)
823 {
824     trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
825     {
826         HDC hdcOffscreen = CreateCompatibleDC(NULL);
827         HENHMETAFILE hemf;
828         METAFILEPICT mfp;
829         RECT rect = { 0, 0, 100, 100 };
830         mfp.mm = MM_ANISOTROPIC;
831         mfp.xExt = 100;
832         mfp.yExt = 100;
833         mfp.hMF = NULL;
834         hemf = create_converted_emf(&mfp);
835         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
836         DeleteEnhMetaFile(hemf);
837         DeleteDC(hdcOffscreen);
838     }
839
840     trace("Testing MF->EMF conversion (MM_TEXT)\n");
841     {
842         HDC hdcOffscreen = CreateCompatibleDC(NULL);
843         HENHMETAFILE hemf;
844         METAFILEPICT mfp;
845         RECT rect = { 0, 0, 100, 100 };
846         mfp.mm = MM_TEXT;
847         mfp.xExt = 0;
848         mfp.yExt = 0;
849         mfp.hMF = NULL;
850         hemf = create_converted_emf(&mfp);
851         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
852         DeleteEnhMetaFile(hemf);
853         DeleteDC(hdcOffscreen);
854     }
855
856     trace("Testing MF->EMF conversion (NULL mfp)\n");
857     {
858         HDC hdcOffscreen = CreateCompatibleDC(NULL);
859         HENHMETAFILE hemf;
860         RECT rect = { 0, 0, 100, 100 };
861         hemf = create_converted_emf(NULL);
862         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
863         DeleteEnhMetaFile(hemf);
864         DeleteDC(hdcOffscreen);
865     }
866 }
867
868 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
869 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
870 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
871
872 static void test_gdiis(void)
873 {
874     RECT rect = {0,0,100,100};
875     HDC hdc, hemfDC, hmfDC;
876     HENHMETAFILE hemf;
877     HMODULE hgdi32;
878
879     /* resolve all the functions */
880     hgdi32 = GetModuleHandle("gdi32");
881     pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
882     pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
883     pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
884
885     /* they should all exist or none should exist */
886     if(!pGdiIsMetaPrintDC)
887         return;
888
889     /* try with nothing */
890     ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
891     ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
892     ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
893
894     /* try with a metafile */
895     hmfDC = CreateMetaFile(NULL);
896     ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
897     ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
898     ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
899     DeleteObject(CloseMetaFile(hmfDC));
900
901     /* try with an enhanced metafile */
902     hdc = GetDC(NULL);
903     hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
904     ok(hemfDC != NULL, "failed to create emf\n");
905
906     ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
907     ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
908     ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
909
910     hemf = CloseEnhMetaFile(hemfDC);
911     ok(hemf != NULL, "failed to close EMF\n");
912     DeleteObject(hemf);
913     ReleaseDC(NULL,hdc);
914 }
915
916 START_TEST(metafile)
917 {
918     init_function_pointers();
919
920     /* For enhanced metafiles (enhmfdrv) */
921     test_ExtTextOut();
922     test_SaveDC();
923
924     /* For win-format metafiles (mfdrv) */
925     test_mf_Blank();
926     test_mf_Graphics();
927     test_mf_PatternBrush();
928     test_CopyMetaFile();
929     test_SetMetaFileBits();
930
931     /* For metafile conversions */
932     test_mf_conversions();
933
934     test_gdiis();
935 }