~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/gdi32/metafile.c

Version: ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  1 /*
  2  * Metafile functions
  3  *
  4  * Copyright  David W. Metcalfe, 1994
  5  * Copyright  Niels de Carpentier, 1996
  6  * Copyright  Albrecht Kleine, 1996
  7  * Copyright  Huw Davies, 1996
  8  *
  9  * This library is free software; you can redistribute it and/or
 10  * modify it under the terms of the GNU Lesser General Public
 11  * License as published by the Free Software Foundation; either
 12  * version 2.1 of the License, or (at your option) any later version.
 13  *
 14  * This library is distributed in the hope that it will be useful,
 15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17  * Lesser General Public License for more details.
 18  *
 19  * You should have received a copy of the GNU Lesser General Public
 20  * License along with this library; if not, write to the Free Software
 21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 22  *
 23  * NOTES
 24  *
 25  * These functions are primarily involved with metafile playback or anything
 26  * that touches a HMETAFILE.
 27  * For recording of metafiles look in graphics/metafiledrv/
 28  *
 29  * Note that (32 bit) HMETAFILEs are GDI objects, while HMETAFILE16s are
 30  * global memory handles so these cannot be interchanged.
 31  *
 32  * Memory-based metafiles are just stored as a continuous block of memory with
 33  * a METAHEADER at the head with METARECORDs appended to it.  mtType is
 34  * METAFILE_MEMORY (1).  Note this is identical to the disk image of a
 35  * disk-based metafile - even mtType is METAFILE_MEMORY.
 36  * 16bit HMETAFILE16s are global handles to this block
 37  * 32bit HMETAFILEs are GDI handles METAFILEOBJs, which contains a ptr to
 38  * the memory.
 39  * Disk-based metafiles are rather different. HMETAFILE16s point to a
 40  * METAHEADER which has mtType equal to METAFILE_DISK (2).  Following the 9
 41  * WORDs of the METAHEADER there are a further 3 WORDs of 0, 1 of 0x117, 1
 42  * more 0, then 2 which may be a time stamp of the file and then the path of
 43  * the file (METAHEADERDISK). I've copied this for 16bit compatibility.
 44  *
 45  * HDMD - 14/4/1999
 46  */
 47 
 48 #include "config.h"
 49 
 50 #include <stdarg.h>
 51 #include <string.h>
 52 #include <fcntl.h>
 53 
 54 #include "windef.h"
 55 #include "winbase.h"
 56 #include "wingdi.h"
 57 #include "winreg.h"
 58 #include "winternl.h"
 59 #include "gdi_private.h"
 60 #include "wine/debug.h"
 61 
 62 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
 63 
 64 #include "pshpack1.h"
 65 typedef struct
 66 {
 67     DWORD dw1, dw2, dw3;
 68     WORD w4;
 69     CHAR filename[0x100];
 70 } METAHEADERDISK;
 71 #include "poppack.h"
 72 
 73 typedef struct
 74 {
 75     GDIOBJHDR   header;
 76     METAHEADER  *mh;
 77 } METAFILEOBJ;
 78 
 79 
 80 /******************************************************************
 81  *         MF_AddHandle
 82  *
 83  *    Add a handle to an external handle table and return the index
 84  */
 85 static int MF_AddHandle(HANDLETABLE *ht, UINT htlen, HGDIOBJ hobj)
 86 {
 87     int i;
 88 
 89     for (i = 0; i < htlen; i++)
 90     {
 91         if (*(ht->objectHandle + i) == 0)
 92         {
 93             *(ht->objectHandle + i) = hobj;
 94             return i;
 95         }
 96     }
 97     return -1;
 98 }
 99 
100 
101 /******************************************************************
102  *         MF_Create_HMETATFILE
103  *
104  * Creates a (32 bit) HMETAFILE object from a METAHEADER
105  *
106  * HMETAFILEs are GDI objects.
107  */
108 HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh)
109 {
110     HMETAFILE hmf = 0;
111     METAFILEOBJ *metaObj = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC,
112                                             (HGDIOBJ *)&hmf, NULL );
113     if (metaObj)
114     {
115         metaObj->mh = mh;
116         GDI_ReleaseObj( hmf );
117     }
118     return hmf;
119 }
120 
121 /******************************************************************
122  *         MF_GetMetaHeader
123  *
124  * Returns ptr to METAHEADER associated with HMETAFILE
125  */
126 static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf )
127 {
128     METAHEADER *ret = NULL;
129     METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
130     if (metaObj)
131     {
132         ret = metaObj->mh;
133         GDI_ReleaseObj( hmf );
134     }
135     return ret;
136 }
137 
138 /******************************************************************
139  *         convert_points
140  *
141  * Convert an array of POINT16 to an array of POINT.
142  * Result must be freed by caller.
143  */
144 static POINT *convert_points( UINT count, POINT16 *pt16 )
145 {
146     UINT i;
147     POINT *ret = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*ret) );
148     if (ret)
149     {
150         for (i = 0; i < count; i++)
151         {
152             ret[i].x = pt16[i].x;
153             ret[i].y = pt16[i].y;
154         }
155     }
156     return ret;
157 }
158 
159 /******************************************************************
160  *          DeleteMetaFile  (GDI32.@)
161  *
162  *  Delete a memory-based metafile.
163  */
164 
165 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
166 {
167     METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
168     if (!metaObj) return FALSE;
169     HeapFree( GetProcessHeap(), 0, metaObj->mh );
170     GDI_FreeObject( hmf, metaObj );
171     return TRUE;
172 }
173 
174 /******************************************************************
175  *         MF_ReadMetaFile
176  *
177  * Returns a pointer to a memory based METAHEADER read in from file HFILE
178  *
179  */
180 METAHEADER *MF_ReadMetaFile(HANDLE hfile)
181 {
182     METAHEADER *mh;
183     DWORD BytesRead, size;
184 
185     size = sizeof(METAHEADER);
186     mh = HeapAlloc( GetProcessHeap(), 0, size );
187     if(!mh) return NULL;
188     if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
189        BytesRead != size) {
190         HeapFree( GetProcessHeap(), 0, mh );
191         return NULL;
192     }
193     if (mh->mtType != METAFILE_MEMORY || mh->mtVersion != MFVERSION ||
194         mh->mtHeaderSize != size / 2)
195     {
196         HeapFree( GetProcessHeap(), 0, mh );
197         return NULL;
198     }
199     size = mh->mtSize * 2;
200     mh = HeapReAlloc( GetProcessHeap(), 0, mh, size );
201     if(!mh) return NULL;
202     size -= sizeof(METAHEADER);
203     if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
204                  NULL) == 0 ||
205        BytesRead != size) {
206         HeapFree( GetProcessHeap(), 0, mh );
207         return NULL;
208     }
209 
210     if (mh->mtType != METAFILE_MEMORY) {
211         WARN("Disk metafile had mtType = %04x\n", mh->mtType);
212         mh->mtType = METAFILE_MEMORY;
213     }
214     return mh;
215 }
216 
217 /******************************************************************
218  *         GetMetaFileA   (GDI32.@)
219  *
220  *  Read a metafile from a file. Returns handle to a memory-based metafile.
221  */
222 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
223 {
224     METAHEADER *mh;
225     HANDLE hFile;
226 
227     TRACE("%s\n", lpFilename);
228 
229     if(!lpFilename)
230         return 0;
231 
232     if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
233                             OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
234         return 0;
235 
236     mh = MF_ReadMetaFile(hFile);
237     CloseHandle(hFile);
238     if(!mh) return 0;
239     return MF_Create_HMETAFILE( mh );
240 }
241 
242 /******************************************************************
243  *         GetMetaFileW   (GDI32.@)
244  */
245 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
246 {
247     METAHEADER *mh;
248     HANDLE hFile;
249 
250     TRACE("%s\n", debugstr_w(lpFilename));
251 
252     if(!lpFilename)
253         return 0;
254 
255     if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
256                             OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
257         return 0;
258 
259     mh = MF_ReadMetaFile(hFile);
260     CloseHandle(hFile);
261     if(!mh) return 0;
262     return MF_Create_HMETAFILE( mh );
263 }
264 
265 
266 /******************************************************************
267  *         MF_LoadDiskBasedMetaFile
268  *
269  * Creates a new memory-based metafile from a disk-based one.
270  */
271 METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
272 {
273     METAHEADERDISK *mhd;
274     HANDLE hfile;
275     METAHEADER *mh2;
276 
277     if(mh->mtType != METAFILE_DISK) {
278         ERR("Not a disk based metafile\n");
279         return NULL;
280     }
281     mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
282 
283     if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
284                             OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
285         WARN("Can't open file of disk based metafile\n");
286         return NULL;
287     }
288     mh2 = MF_ReadMetaFile(hfile);
289     CloseHandle(hfile);
290     return mh2;
291 }
292 
293 /******************************************************************
294  *         MF_CreateMetaHeaderDisk
295  *
296  * Take a memory based METAHEADER and change it to a disk based METAHEADER
297  * associated with filename.  Note: Trashes contents of old one.
298  */
299 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCVOID filename, BOOL uni )
300 {
301     METAHEADERDISK *mhd;
302 
303     mh = HeapReAlloc( GetProcessHeap(), 0, mh,
304                       sizeof(METAHEADER) + sizeof(METAHEADERDISK));
305     mh->mtType = METAFILE_DISK;
306     mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
307 
308     if( uni )
309         WideCharToMultiByte(CP_ACP, 0, filename, -1, 
310                    mhd->filename, sizeof mhd->filename, NULL, NULL);
311     else
312         lstrcpynA( mhd->filename, filename, sizeof mhd->filename );
313     return mh;
314 }
315 
316 /******************************************************************
317  *         CopyMetaFileW   (GDI32.@)
318  *
319  *  Copies the metafile corresponding to hSrcMetaFile to either
320  *  a disk file, if a filename is given, or to a new memory based
321  *  metafile, if lpFileName is NULL.
322  *
323  * PARAMS
324  *  hSrcMetaFile [I] handle of metafile to copy
325  *  lpFilename   [I] filename if copying to a file
326  *
327  * RETURNS
328  *  Handle to metafile copy on success, NULL on failure.
329  *
330  * BUGS
331  *  Copying to disk returns NULL even if successful.
332  */
333 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile, LPCWSTR lpFilename )
334 {
335     METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
336     METAHEADER *mh2 = NULL;
337     HANDLE hFile;
338 
339     TRACE("(%p,%s)\n", hSrcMetaFile, debugstr_w(lpFilename));
340 
341     if(!mh) return 0;
342 
343     if(mh->mtType == METAFILE_DISK)
344         mh2 = MF_LoadDiskBasedMetaFile(mh);
345     else {
346         mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
347         memcpy( mh2, mh, mh->mtSize * 2 );
348     }
349 
350     if(lpFilename) {         /* disk based metafile */
351         DWORD w;
352         if((hFile = CreateFileW(lpFilename, GENERIC_WRITE, 0, NULL,
353                                 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
354             HeapFree( GetProcessHeap(), 0, mh2 );
355             return 0;
356         }
357         WriteFile(hFile, mh2, mh2->mtSize * 2, &w, NULL);
358         CloseHandle(hFile);
359     }
360 
361     return MF_Create_HMETAFILE( mh2 );
362 }
363 
364 
365 /******************************************************************
366  *         CopyMetaFileA   (GDI32.@)
367  *
368  * See CopyMetaFileW.
369  */
370 HMETAFILE WINAPI CopyMetaFileA( HMETAFILE hSrcMetaFile, LPCSTR lpFilename )
371 {
372     UNICODE_STRING lpFilenameW;
373     HMETAFILE ret = 0;
374 
375     if (lpFilename) RtlCreateUnicodeStringFromAsciiz(&lpFilenameW, lpFilename);
376     else lpFilenameW.Buffer = NULL;
377 
378     ret = CopyMetaFileW( hSrcMetaFile, lpFilenameW.Buffer );
379     if (lpFilenameW.Buffer)
380         RtlFreeUnicodeString(&lpFilenameW);
381     return ret;
382 }
383 
384 /*******************************************************************
385  *         MF_PlayMetaFile
386  *
387  * Helper for PlayMetaFile
388  */
389 BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
390 {
391 
392     METARECORD *mr;
393     HANDLETABLE *ht;
394     unsigned int offset = 0;
395     WORD i;
396     HPEN hPen;
397     HBRUSH hBrush;
398     HFONT hFont;
399     HPALETTE hPal;
400     HRGN hRgn;
401     BOOL loaded = FALSE;
402 
403     if (!mh) return FALSE;
404     if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
405         mh = MF_LoadDiskBasedMetaFile(mh);
406         if(!mh) return FALSE;
407         loaded = TRUE;
408     }
409 
410     /* save DC */
411     hPen = GetCurrentObject(hdc, OBJ_PEN);
412     hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
413     hFont = GetCurrentObject(hdc, OBJ_FONT);
414     hPal = GetCurrentObject(hdc, OBJ_PAL);
415 
416     hRgn = CreateRectRgn(0, 0, 0, 0);
417     if (!GetClipRgn(hdc, hRgn))
418     {
419         DeleteObject(hRgn);
420         hRgn = 0;
421     }
422 
423     /* create the handle table */
424     ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
425                     sizeof(HANDLETABLE) * mh->mtNoObjects);
426     if(!ht) return FALSE;
427 
428     /* loop through metafile playing records */
429     offset = mh->mtHeaderSize * 2;
430     while (offset < mh->mtSize * 2)
431     {
432         mr = (METARECORD *)((char *)mh + offset);
433         TRACE("offset=%04x,size=%08x\n",
434             offset, mr->rdSize);
435         if (mr->rdSize < 3) { /* catch illegal record sizes */
436             TRACE("Entry got size %d at offset %d, total mf length is %d\n",
437                   mr->rdSize,offset,mh->mtSize*2);
438             break;
439         }
440 
441         offset += mr->rdSize * 2;
442         if (mr->rdFunction == META_EOF) {
443             TRACE("Got META_EOF so stopping\n");
444             break;
445         }
446         PlayMetaFileRecord( hdc, ht, mr, mh->mtNoObjects );
447     }
448 
449     /* restore DC */
450     SelectObject(hdc, hPen);
451     SelectObject(hdc, hBrush);
452     SelectPalette(hdc, hPal, FALSE);
453     ExtSelectClipRgn(hdc, hRgn, RGN_COPY);
454     DeleteObject(hRgn);
455 
456     /* free objects in handle table */
457     for(i = 0; i < mh->mtNoObjects; i++)
458       if(*(ht->objectHandle + i) != 0)
459         DeleteObject(*(ht->objectHandle + i));
460 
461     /* free handle table */
462     HeapFree( GetProcessHeap(), 0, ht );
463     if(loaded)
464         HeapFree( GetProcessHeap(), 0, mh );
465     return TRUE;
466 }
467 
468 /******************************************************************
469  *         PlayMetaFile   (GDI32.@)
470  *
471  *  Renders the metafile specified by hmf in the DC specified by
472  *  hdc. Returns FALSE on failure, TRUE on success.
473  *
474  * PARAMS
475  *  hdc [I] handle of DC to render in
476  *  hmf [I] handle of metafile to render
477  *
478  * RETURNS
479  *  Success: TRUE
480  *  Failure: FALSE
481  */
482 BOOL WINAPI PlayMetaFile( HDC hdc, HMETAFILE hmf )
483 {
484     METAHEADER *mh = MF_GetMetaHeader( hmf );
485     return MF_PlayMetaFile( hdc, mh );
486 }
487 
488 /******************************************************************
489  *            EnumMetaFile   (GDI32.@)
490  *
491  *  Loop through the metafile records in hmf, calling the user-specified
492  *  function for each one, stopping when the user's function returns FALSE
493  *  (which is considered to be failure)
494  *  or when no records are left (which is considered to be success).
495  *
496  * RETURNS
497  *  TRUE on success, FALSE on failure.
498  */
499 BOOL WINAPI EnumMetaFile(HDC hdc, HMETAFILE hmf, MFENUMPROC lpEnumFunc, LPARAM lpData)
500 {
501     METAHEADER *mhTemp = NULL, *mh = MF_GetMetaHeader(hmf);
502     METARECORD *mr;
503     HANDLETABLE *ht;
504     BOOL result = TRUE;
505     int i;
506     unsigned int offset = 0;
507     HPEN hPen;
508     HBRUSH hBrush;
509     HFONT hFont;
510 
511     TRACE("(%p,%p,%p,%p)\n", hdc, hmf, lpEnumFunc, (void*)lpData);
512     if (!mh) return 0;
513     if(mh->mtType == METAFILE_DISK)
514     {
515         /* Create a memory-based copy */
516         if (!(mhTemp = MF_LoadDiskBasedMetaFile(mh))) return FALSE;
517         mh = mhTemp;
518     }
519 
520     /* save the current pen, brush and font */
521     hPen = GetCurrentObject(hdc, OBJ_PEN);
522     hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
523     hFont = GetCurrentObject(hdc, OBJ_FONT);
524 
525     ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
526                             sizeof(HANDLETABLE) * mh->mtNoObjects);
527 
528     /* loop through metafile records */
529     offset = mh->mtHeaderSize * 2;
530 
531     while (offset < (mh->mtSize * 2))
532     {
533         mr = (METARECORD *)((char *)mh + offset);
534         if(mr->rdFunction == META_EOF) {
535             TRACE("Got META_EOF so stopping\n");
536             break;
537         }
538         TRACE("Calling EnumFunc with record type %x\n",
539               mr->rdFunction);
540         if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
541         {
542             result = FALSE;
543             break;
544         }
545 
546         offset += (mr->rdSize * 2);
547     }
548 
549     /* restore pen, brush and font */
550     SelectObject(hdc, hBrush);
551     SelectObject(hdc, hPen);
552     SelectObject(hdc, hFont);
553 
554     /* free objects in handle table */
555     for(i = 0; i < mh->mtNoObjects; i++)
556       if(*(ht->objectHandle + i) != 0)
557         DeleteObject(*(ht->objectHandle + i));
558 
559     /* free handle table */
560     HeapFree( GetProcessHeap(), 0, ht);
561     /* free a copy of metafile */
562     HeapFree( GetProcessHeap(), 0, mhTemp );
563     return result;
564 }
565 
566 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
567 static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr);
568 /******************************************************************
569  *         PlayMetaFileRecord   (GDI32.@)
570  *
571  *   Render a single metafile record specified by *mr in the DC hdc, while
572  *   using the handle table *ht, of length handles,
573  *   to store metafile objects.
574  *
575  * BUGS
576  *  The following metafile records are unimplemented:
577  *
578  *  DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
579  *  RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
580  *  ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
581  */
582 BOOL WINAPI PlayMetaFileRecord( HDC hdc,  HANDLETABLE *ht, METARECORD *mr, UINT handles )
583 {
584     short s1;
585     POINT *pt;
586     BITMAPINFOHEADER *infohdr;
587 
588     TRACE("(%p %p %p %u) function %04x\n", hdc, ht, mr, handles, mr->rdFunction);
589 
590     switch (mr->rdFunction)
591     {
592     case META_EOF:
593         break;
594 
595     case META_DELETEOBJECT:
596         DeleteObject(*(ht->objectHandle + mr->rdParm[0]));
597         *(ht->objectHandle + mr->rdParm[0]) = 0;
598         break;
599 
600     case META_SETBKCOLOR:
601         SetBkColor(hdc, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
602         break;
603 
604     case META_SETBKMODE:
605         SetBkMode(hdc, mr->rdParm[0]);
606         break;
607 
608     case META_SETMAPMODE:
609         SetMapMode(hdc, mr->rdParm[0]);
610         break;
611 
612     case META_SETROP2:
613         SetROP2(hdc, mr->rdParm[0]);
614         break;
615 
616     case META_SETRELABS:
617         SetRelAbs(hdc, mr->rdParm[0]);
618         break;
619 
620     case META_SETPOLYFILLMODE:
621         SetPolyFillMode(hdc, mr->rdParm[0]);
622         break;
623 
624     case META_SETSTRETCHBLTMODE:
625         SetStretchBltMode(hdc, mr->rdParm[0]);
626         break;
627 
628     case META_SETTEXTCOLOR:
629         SetTextColor(hdc, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
630         break;
631 
632     case META_SETWINDOWORG:
633         SetWindowOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
634         break;
635 
636     case META_SETWINDOWEXT:
637         SetWindowExtEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
638         break;
639 
640     case META_SETVIEWPORTORG:
641         SetViewportOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
642         break;
643 
644     case META_SETVIEWPORTEXT:
645         SetViewportExtEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
646         break;
647 
648     case META_OFFSETWINDOWORG:
649         OffsetWindowOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
650         break;
651 
652     case META_SCALEWINDOWEXT:
653         ScaleWindowExtEx(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
654                               (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
655         break;
656 
657     case META_OFFSETVIEWPORTORG:
658         OffsetViewportOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
659         break;
660 
661     case META_SCALEVIEWPORTEXT:
662         ScaleViewportExtEx(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
663                                 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
664         break;
665 
666     case META_LINETO:
667         LineTo(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
668         break;
669 
670     case META_MOVETO:
671         MoveToEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
672         break;
673 
674     case META_EXCLUDECLIPRECT:
675         ExcludeClipRect( hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
676                               (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
677         break;
678 
679     case META_INTERSECTCLIPRECT:
680         IntersectClipRect( hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
681                                 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
682         break;
683 
684     case META_ARC:
685         Arc(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
686                  (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
687                  (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
688                  (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
689         break;
690 
691     case META_ELLIPSE:
692         Ellipse(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
693                      (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
694         break;
695 
696     case META_FLOODFILL:
697         FloodFill(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
698                     MAKELONG(mr->rdParm[0], mr->rdParm[1]));
699         break;
700 
701     case META_PIE:
702         Pie(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
703                  (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
704                  (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
705                  (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
706         break;
707 
708     case META_RECTANGLE:
709         Rectangle(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
710                        (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
711         break;
712 
713     case META_ROUNDRECT:
714         RoundRect(hdc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
715                        (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
716                        (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
717         break;
718 
719     case META_PATBLT:
720         PatBlt(hdc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
721                     (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
722                     MAKELONG(mr->rdParm[0], mr->rdParm[1]));
723         break;
724 
725     case META_SAVEDC:
726         SaveDC(hdc);
727         break;
728 
729     case META_SETPIXEL:
730         SetPixel(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
731                  MAKELONG(mr->rdParm[0], mr->rdParm[1]));
732         break;
733 
734     case META_OFFSETCLIPRGN:
735         OffsetClipRgn( hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
736         break;
737 
738     case META_TEXTOUT:
739         s1 = mr->rdParm[0];
740         TextOutA(hdc, (SHORT)mr->rdParm[((s1 + 1) >> 1) + 2],
741                  (SHORT)mr->rdParm[((s1 + 1) >> 1) + 1],
742                  (char *)(mr->rdParm + 1), s1);
743         break;
744 
745     case META_POLYGON:
746         if ((pt = convert_points( mr->rdParm[0], (LPPOINT16)(mr->rdParm + 1))))
747         {
748             Polygon(hdc, pt, mr->rdParm[0]);
749             HeapFree( GetProcessHeap(), 0, pt );
750         }
751         break;
752 
753     case META_POLYPOLYGON:
754         {
755             UINT i, total;
756             SHORT *counts = (SHORT *)(mr->rdParm + 1);
757 
758             for (i = total = 0; i < mr->rdParm[0]; i++) total += counts[i];
759             pt = convert_points( total, (LPPOINT16)(counts + mr->rdParm[0]) );
760             if (pt)
761             {
762                 INT *cnt32 = HeapAlloc( GetProcessHeap(), 0, mr->rdParm[0] * sizeof(*cnt32) );
763                 if (cnt32)
764                 {
765                     for (i = 0; i < mr->rdParm[0]; i++) cnt32[i] = counts[i];
766                     PolyPolygon( hdc, pt, cnt32, mr->rdParm[0]);
767                     HeapFree( GetProcessHeap(), 0, cnt32 );
768                 }
769             }
770             HeapFree( GetProcessHeap(), 0, pt );
771         }
772         break;
773 
774     case META_POLYLINE:
775         if ((pt = convert_points( mr->rdParm[0], (LPPOINT16)(mr->rdParm + 1))))
776         {
777             Polyline( hdc, pt, mr->rdParm[0] );
778             HeapFree( GetProcessHeap(), 0, pt );
779         }
780         break;
781 
782     case META_RESTOREDC:
783         RestoreDC(hdc, (SHORT)mr->rdParm[0]);
784         break;
785 
786     case META_SELECTOBJECT:
787         SelectObject(hdc, *(ht->objectHandle + mr->rdParm[0]));
788         break;
789 
790     case META_CHORD:
791         Chord(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
792                    (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
793                    (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
794                    (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
795         break;
796 
797     case META_CREATEPATTERNBRUSH:
798         switch (mr->rdParm[0])
799         {
800         case BS_PATTERN:
801             infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
802             MF_AddHandle(ht, handles,
803                          CreatePatternBrush(CreateBitmap(infohdr->biWidth,
804                                       infohdr->biHeight,
805                                       infohdr->biPlanes,
806                                       infohdr->biBitCount,
807                                       (LPSTR)(mr->rdParm +
808                                       (sizeof(BITMAPINFOHEADER) / 2) + 4))));
809             break;
810 
811         case BS_DIBPATTERN:
812             infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
813             MF_AddHandle(ht, handles, CreateDIBPatternBrushPt( infohdr, mr->rdParm[1] ));
814             break;
815 
816         default:
817             ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
818                 mr->rdParm[0]);
819             break;
820         }
821         break;
822 
823     case META_CREATEPENINDIRECT:
824         {
825             LOGPEN pen;
826             pen.lopnStyle = mr->rdParm[0];
827             pen.lopnWidth.x = (SHORT)mr->rdParm[1];
828             pen.lopnWidth.y = (SHORT)mr->rdParm[2];
829             pen.lopnColor = MAKELONG( mr->rdParm[3], mr->rdParm[4] );
830             MF_AddHandle(ht, handles, CreatePenIndirect( &pen ));
831         }
832         break;
833 
834     case META_CREATEFONTINDIRECT:
835         {
836             LOGFONTA font;
837             font.lfHeight         = (SHORT)mr->rdParm[0];
838             font.lfWidth          = (SHORT)mr->rdParm[1];
839             font.lfEscapement     = (SHORT)mr->rdParm[2];
840             font.lfOrientation    = (SHORT)mr->rdParm[3];
841             font.lfWeight         = (SHORT)mr->rdParm[4];
842             font.lfItalic         = LOBYTE(mr->rdParm[5]);
843             font.lfUnderline      = HIBYTE(mr->rdParm[5]);
844             font.lfStrikeOut      = LOBYTE(mr->rdParm[6]);
845             font.lfCharSet        = HIBYTE(mr->rdParm[6]);
846             font.lfOutPrecision   = LOBYTE(mr->rdParm[7]);
847             font.lfClipPrecision  = HIBYTE(mr->rdParm[7]);
848             font.lfQuality        = LOBYTE(mr->rdParm[8]);
849             font.lfPitchAndFamily = HIBYTE(mr->rdParm[8]);
850             memcpy( font.lfFaceName, mr->rdParm + 9, LF_FACESIZE );
851             MF_AddHandle(ht, handles, CreateFontIndirectA( &font ));
852         }
853         break;
854 
855     case META_CREATEBRUSHINDIRECT:
856         {
857             LOGBRUSH brush;
858             brush.lbStyle = mr->rdParm[0];
859             brush.lbColor = MAKELONG( mr->rdParm[1], mr->rdParm[2] );
860             brush.lbHatch = mr->rdParm[3];
861             MF_AddHandle(ht, handles, CreateBrushIndirect( &brush ));
862         }
863         break;
864 
865     case META_CREATEPALETTE:
866         MF_AddHandle(ht, handles, CreatePalette((LPLOGPALETTE)mr->rdParm));
867         break;
868 
869     case META_SETTEXTALIGN:
870         SetTextAlign(hdc, mr->rdParm[0]);
871         break;
872 
873     case META_SELECTPALETTE:
874         GDISelectPalette(hdc, *(ht->objectHandle + mr->rdParm[1]), mr->rdParm[0]);
875         break;
876 
877     case META_SETMAPPERFLAGS:
878         SetMapperFlags(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
879         break;
880 
881     case META_REALIZEPALETTE:
882         GDIRealizePalette(hdc);
883         break;
884 
885     case META_ESCAPE:
886         switch (mr->rdParm[0]) {
887         case GETSCALINGFACTOR: /* get function ... would just NULL dereference */
888         case GETPHYSPAGESIZE:
889         case GETPRINTINGOFFSET:
890              return FALSE;
891         case SETABORTPROC:
892              FIXME("Filtering Escape(SETABORTPROC), possible virus?\n");
893              return FALSE;
894         }
895         Escape(hdc, mr->rdParm[0], mr->rdParm[1], (LPCSTR)&mr->rdParm[2], NULL);
896         break;
897 
898     case META_EXTTEXTOUT:
899         MF_Play_MetaExtTextOut( hdc, mr );
900         break;
901 
902     case META_STRETCHDIB:
903       {
904         LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
905         LPSTR bits = (LPSTR)info + bitmap_info_size( info, mr->rdParm[2] );
906         StretchDIBits( hdc, (SHORT)mr->rdParm[10], (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8],
907                        (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
908                        (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], bits, info,
909                        mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
910       }
911       break;
912 
913     case META_DIBSTRETCHBLT:
914       {
915         LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
916         LPSTR bits = (LPSTR)info + bitmap_info_size( info, mr->rdParm[2] );
917         StretchDIBits( hdc, (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
918                        (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
919                        (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], bits, info,
920                        DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
921       }
922       break;
923 
924     case META_STRETCHBLT:
925       {
926         HDC hdcSrc = CreateCompatibleDC(hdc);
927         HBITMAP hbitmap = CreateBitmap(mr->rdParm[10], /*Width */
928                                        mr->rdParm[11], /*Height*/
929                                        mr->rdParm[13], /*Planes*/
930                                        mr->rdParm[14], /*BitsPixel*/
931                                        (LPSTR)&mr->rdParm[15]);  /*bits*/
932         SelectObject(hdcSrc,hbitmap);
933         StretchBlt(hdc, (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8],
934                    (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
935                    hdcSrc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
936                    (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
937                    MAKELONG(mr->rdParm[0],mr->rdParm[1]));
938         DeleteDC(hdcSrc);
939       }
940       break;
941 
942     case META_BITBLT:
943       {
944         HDC hdcSrc = CreateCompatibleDC(hdc);
945         HBITMAP hbitmap = CreateBitmap(mr->rdParm[7]/*Width */,
946                                         mr->rdParm[8]/*Height*/,
947                                         mr->rdParm[10]/*Planes*/,
948                                         mr->rdParm[11]/*BitsPixel*/,
949                                         (LPSTR)&mr->rdParm[12]/*bits*/);
950         SelectObject(hdcSrc,hbitmap);
951         BitBlt(hdc,(SHORT)mr->rdParm[6],(SHORT)mr->rdParm[5],
952                 (SHORT)mr->rdParm[4],(SHORT)mr->rdParm[3],
953                 hdcSrc, (SHORT)mr->rdParm[2],(SHORT)mr->rdParm[1],
954                 MAKELONG(0,mr->rdParm[0]));
955         DeleteDC(hdcSrc);
956       }
957       break;
958 
959     case META_CREATEREGION:
960       {
961         HRGN hrgn = CreateRectRgn(0,0,0,0);
962 
963         MF_Play_MetaCreateRegion(mr, hrgn);
964         MF_AddHandle(ht, handles, hrgn);
965       }
966       break;
967 
968     case META_FILLREGION:
969         FillRgn(hdc, *(ht->objectHandle + mr->rdParm[1]),
970                 *(ht->objectHandle + mr->rdParm[0]));