Be less strict on parameter checking in the SetSurfaceDesc function.
[wine] / objects / enhmetafile.c
1 /*
2  * Enhanced metafile functions
3  * Copyright 1998 Douglas Ridgway
4  *           1999 Huw D M Davies
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  * NOTES:
21  *
22  * The enhanced format consists of the following elements:
23  *
24  *    A header
25  *    A table of handles to GDI objects
26  *    An array of metafile records
27  *    A private palette
28  *
29  *
30  *  The standard format consists of a header and an array of metafile records.
31  *
32  */
33
34 #include "config.h"
35 #include "wine/port.h"
36
37 #include <string.h>
38 #include <assert.h>
39 #include "winnls.h"
40 #include "winbase.h"
41 #include "wingdi.h"
42 #include "winerror.h"
43 #include "gdi.h"
44 #include "wine/debug.h"
45
46 WINE_DEFAULT_DEBUG_CHANNEL(enhmetafile);
47
48 typedef struct
49 {
50     GDIOBJHDR      header;
51     ENHMETAHEADER  *emh;
52     BOOL           on_disk;   /* true if metafile is on disk */
53 } ENHMETAFILEOBJ;
54
55
56 /****************************************************************************
57  *          EMF_Create_HENHMETAFILE
58  */
59 HENHMETAFILE EMF_Create_HENHMETAFILE(ENHMETAHEADER *emh, BOOL on_disk )
60 {
61     HENHMETAFILE hmf = 0;
62     ENHMETAFILEOBJ *metaObj = GDI_AllocObject( sizeof(ENHMETAFILEOBJ),
63                                                ENHMETAFILE_MAGIC, &hmf, NULL );
64     if (metaObj)
65     {
66         metaObj->emh = emh;
67         metaObj->on_disk = on_disk;
68         GDI_ReleaseObj( hmf );
69     }
70     return hmf;
71 }
72
73 /****************************************************************************
74  *          EMF_Delete_HENHMETAFILE
75  */
76 static BOOL EMF_Delete_HENHMETAFILE( HENHMETAFILE hmf )
77 {
78     ENHMETAFILEOBJ *metaObj = (ENHMETAFILEOBJ *)GDI_GetObjPtr( hmf,
79                                                            ENHMETAFILE_MAGIC );
80     if(!metaObj) return FALSE;
81
82     if(metaObj->on_disk)
83         UnmapViewOfFile( metaObj->emh );
84     else
85         HeapFree( GetProcessHeap(), 0, metaObj->emh );
86     return GDI_FreeObject( hmf, metaObj );
87 }
88
89 /******************************************************************
90  *         EMF_GetEnhMetaHeader
91  *
92  * Returns ptr to ENHMETAHEADER associated with HENHMETAFILE
93  */
94 static ENHMETAHEADER *EMF_GetEnhMetaHeader( HENHMETAFILE hmf )
95 {
96     ENHMETAHEADER *ret = NULL;
97     ENHMETAFILEOBJ *metaObj = (ENHMETAFILEOBJ *)GDI_GetObjPtr( hmf, ENHMETAFILE_MAGIC );
98     TRACE("hmf %04x -> enhmetaObj %p\n", hmf, metaObj);
99     if (metaObj)
100     {
101         ret = metaObj->emh;
102         GDI_ReleaseObj( hmf );
103     }
104     return ret;
105 }
106
107 /*****************************************************************************
108  *         EMF_GetEnhMetaFile
109  *
110  */
111 static HENHMETAFILE EMF_GetEnhMetaFile( HANDLE hFile )
112 {
113     ENHMETAHEADER *emh;
114     HANDLE hMapping;
115
116     hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
117     emh = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 );
118     CloseHandle( hMapping );
119
120     if (!emh) return 0;
121
122     if (emh->iType != EMR_HEADER || emh->dSignature != ENHMETA_SIGNATURE) {
123         WARN("Invalid emf header type 0x%08lx sig 0x%08lx.\n",
124              emh->iType, emh->dSignature);
125         UnmapViewOfFile( emh );
126         return 0;
127     }
128     return EMF_Create_HENHMETAFILE( emh, TRUE );
129 }
130
131
132 /*****************************************************************************
133  *          GetEnhMetaFileA (GDI32.@)
134  *
135  *
136  */
137 HENHMETAFILE WINAPI GetEnhMetaFileA(
138              LPCSTR lpszMetaFile  /* [in] filename of enhanced metafile */
139     )
140 {
141     HENHMETAFILE hmf;
142     HANDLE hFile;
143
144     hFile = CreateFileA(lpszMetaFile, GENERIC_READ, FILE_SHARE_READ, 0,
145                         OPEN_EXISTING, 0, 0);
146     if (hFile == INVALID_HANDLE_VALUE) {
147         WARN("could not open %s\n", lpszMetaFile);
148         return 0;
149     }
150     hmf = EMF_GetEnhMetaFile( hFile );
151     CloseHandle( hFile );
152     return hmf;
153 }
154
155 /*****************************************************************************
156  *          GetEnhMetaFileW  (GDI32.@)
157  */
158 HENHMETAFILE WINAPI GetEnhMetaFileW(
159              LPCWSTR lpszMetaFile)  /* [in] filename of enhanced metafile */
160 {
161     HENHMETAFILE hmf;
162     HANDLE hFile;
163
164     hFile = CreateFileW(lpszMetaFile, GENERIC_READ, FILE_SHARE_READ, 0,
165                         OPEN_EXISTING, 0, 0);
166     if (hFile == INVALID_HANDLE_VALUE) {
167         WARN("could not open %s\n", debugstr_w(lpszMetaFile));
168         return 0;
169     }
170     hmf = EMF_GetEnhMetaFile( hFile );
171     CloseHandle( hFile );
172     return hmf;
173 }
174
175 /*****************************************************************************
176  *        GetEnhMetaFileHeader  (GDI32.@)
177  *
178  *  If buf is NULL, returns the size of buffer required.
179  *  Otherwise, copy up to bufsize bytes of enhanced metafile header into
180  *  buf.
181  */
182 UINT WINAPI GetEnhMetaFileHeader(
183        HENHMETAFILE hmf,   /* [in] enhanced metafile */
184        UINT bufsize,       /* [in] size of buffer */
185        LPENHMETAHEADER buf /* [out] buffer */
186     )
187 {
188     LPENHMETAHEADER emh;
189     UINT size;
190
191     emh = EMF_GetEnhMetaHeader(hmf);
192     if(!emh) return FALSE;
193     size = emh->nSize;
194     if (!buf) return size;
195     size = min(size, bufsize);
196     memmove(buf, emh, size);
197     return size;
198 }
199
200
201 /*****************************************************************************
202  *          GetEnhMetaFileDescriptionA  (GDI32.@)
203  */
204 UINT WINAPI GetEnhMetaFileDescriptionA(
205        HENHMETAFILE hmf, /* [in] enhanced metafile */
206        UINT size,        /* [in] size of buf */
207        LPSTR buf         /* [out] buffer to receive description */
208     )
209 {
210      LPENHMETAHEADER emh = EMF_GetEnhMetaHeader(hmf);
211      DWORD len;
212      WCHAR *descrW;
213
214      if(!emh) return FALSE;
215      if(emh->nDescription == 0 || emh->offDescription == 0) return 0;
216      descrW = (WCHAR *) ((char *) emh + emh->offDescription);
217      len = WideCharToMultiByte( CP_ACP, 0, descrW, emh->nDescription, NULL, 0, NULL, NULL );
218
219      if (!buf || !size ) return len;
220
221      len = min( size, len );
222      WideCharToMultiByte( CP_ACP, 0, descrW, emh->nDescription, buf, len, NULL, NULL );
223      return len;
224 }
225
226 /*****************************************************************************
227  *          GetEnhMetaFileDescriptionW  (GDI32.@)
228  *
229  *  Copies the description string of an enhanced metafile into a buffer
230  *  _buf_.
231  *
232  *  If _buf_ is NULL, returns size of _buf_ required. Otherwise, returns
233  *  number of characters copied.
234  */
235 UINT WINAPI GetEnhMetaFileDescriptionW(
236        HENHMETAFILE hmf, /* [in] enhanced metafile */
237        UINT size,        /* [in] size of buf */
238        LPWSTR buf        /* [out] buffer to receive description */
239     )
240 {
241      LPENHMETAHEADER emh = EMF_GetEnhMetaHeader(hmf);
242
243      if(!emh) return FALSE;
244      if(emh->nDescription == 0 || emh->offDescription == 0) return 0;
245      if (!buf || !size ) return emh->nDescription;
246
247      memmove(buf, (char *) emh + emh->offDescription, min(size,emh->nDescription)*sizeof(WCHAR));
248      return min(size, emh->nDescription);
249 }
250
251 /****************************************************************************
252  *    SetEnhMetaFileBits (GDI32.@)
253  *
254  *  Creates an enhanced metafile by copying _bufsize_ bytes from _buf_.
255  */
256 HENHMETAFILE WINAPI SetEnhMetaFileBits(UINT bufsize, const BYTE *buf)
257 {
258     ENHMETAHEADER *emh = HeapAlloc( GetProcessHeap(), 0, bufsize );
259     memmove(emh, buf, bufsize);
260     return EMF_Create_HENHMETAFILE( emh, FALSE );
261 }
262
263 /*****************************************************************************
264  *  GetEnhMetaFileBits (GDI32.@)
265  *
266  */
267 UINT WINAPI GetEnhMetaFileBits(
268     HENHMETAFILE hmf,
269     UINT bufsize,
270     LPBYTE buf
271 )
272 {
273     LPENHMETAHEADER emh = EMF_GetEnhMetaHeader( hmf );
274     UINT size;
275
276     if(!emh) return 0;
277
278     size = emh->nBytes;
279     if( buf == NULL ) return size;
280
281     size = min( size, bufsize );
282     memmove(buf, emh, size);
283     return size;
284 }
285
286 /*****************************************************************************
287  *           PlayEnhMetaFileRecord  (GDI32.@)
288  *
289  *  Render a single enhanced metafile record in the device context hdc.
290  *
291  *  RETURNS
292  *    TRUE (non zero) on success, FALSE on error.
293  *  BUGS
294  *    Many unimplemented records.
295  *    No error handling on record play failures (ie checking return codes)
296  */
297 BOOL WINAPI PlayEnhMetaFileRecord(
298      HDC hdc,                   /* [in] device context in which to render EMF record */
299      LPHANDLETABLE handletable, /* [in] array of handles to be used in rendering record */
300      const ENHMETARECORD *mr,   /* [in] EMF record to render */
301      UINT handles               /* [in] size of handle array */
302      )
303 {
304   int type;
305   TRACE(
306         "hdc = %08x, handletable = %p, record = %p, numHandles = %d\n",
307           hdc, handletable, mr, handles);
308   if (!mr) return FALSE;
309
310   type = mr->iType;
311
312   TRACE(" type=%d\n", type);
313   switch(type)
314     {
315     case EMR_HEADER:
316       break;
317     case EMR_EOF:
318       break;
319     case EMR_GDICOMMENT:
320       {
321         PEMRGDICOMMENT lpGdiComment = (PEMRGDICOMMENT)mr;
322         /* In an enhanced metafile, there can be both public and private GDI comments */
323         GdiComment( hdc, lpGdiComment->cbData, lpGdiComment->Data );
324         break;
325       }
326     case EMR_SETMAPMODE:
327       {
328         PEMRSETMAPMODE pSetMapMode = (PEMRSETMAPMODE) mr;
329         SetMapMode(hdc, pSetMapMode->iMode);
330         break;
331       }
332     case EMR_SETBKMODE:
333       {
334         PEMRSETBKMODE pSetBkMode = (PEMRSETBKMODE) mr;
335         SetBkMode(hdc, pSetBkMode->iMode);
336         break;
337       }
338     case EMR_SETBKCOLOR:
339       {
340         PEMRSETBKCOLOR pSetBkColor = (PEMRSETBKCOLOR) mr;
341         SetBkColor(hdc, pSetBkColor->crColor);
342         break;
343       }
344     case EMR_SETPOLYFILLMODE:
345       {
346         PEMRSETPOLYFILLMODE pSetPolyFillMode = (PEMRSETPOLYFILLMODE) mr;
347         SetPolyFillMode(hdc, pSetPolyFillMode->iMode);
348         break;
349       }
350     case EMR_SETROP2:
351       {
352         PEMRSETROP2 pSetROP2 = (PEMRSETROP2) mr;
353         SetROP2(hdc, pSetROP2->iMode);
354         break;
355       }
356     case EMR_SETSTRETCHBLTMODE:
357       {
358         PEMRSETSTRETCHBLTMODE pSetStretchBltMode = (PEMRSETSTRETCHBLTMODE) mr;
359         SetStretchBltMode(hdc, pSetStretchBltMode->iMode);
360         break;
361       }
362     case EMR_SETTEXTALIGN:
363       {
364         PEMRSETTEXTALIGN pSetTextAlign = (PEMRSETTEXTALIGN) mr;
365         SetTextAlign(hdc, pSetTextAlign->iMode);
366         break;
367       }
368     case EMR_SETTEXTCOLOR:
369       {
370         PEMRSETTEXTCOLOR pSetTextColor = (PEMRSETTEXTCOLOR) mr;
371         SetTextColor(hdc, pSetTextColor->crColor);
372         break;
373       }
374     case EMR_SAVEDC:
375       {
376         SaveDC(hdc);
377         break;
378       }
379     case EMR_RESTOREDC:
380       {
381         PEMRRESTOREDC pRestoreDC = (PEMRRESTOREDC) mr;
382         RestoreDC(hdc, pRestoreDC->iRelative);
383         break;
384       }
385     case EMR_INTERSECTCLIPRECT:
386       {
387         PEMRINTERSECTCLIPRECT pClipRect = (PEMRINTERSECTCLIPRECT) mr;
388         IntersectClipRect(hdc, pClipRect->rclClip.left, pClipRect->rclClip.top,
389                           pClipRect->rclClip.right, pClipRect->rclClip.bottom);
390         break;
391       }
392     case EMR_SELECTOBJECT:
393       {
394         PEMRSELECTOBJECT pSelectObject = (PEMRSELECTOBJECT) mr;
395         if( pSelectObject->ihObject & 0x80000000 ) {
396           /* High order bit is set - it's a stock object
397            * Strip the high bit to get the index.
398            * See MSDN article Q142319
399            */
400           SelectObject( hdc, GetStockObject( pSelectObject->ihObject &
401                                              0x7fffffff ) );
402         } else {
403           /* High order bit wasn't set - not a stock object
404            */
405               SelectObject( hdc,
406                         (handletable->objectHandle)[pSelectObject->ihObject] );
407         }
408         break;
409       }
410     case EMR_DELETEOBJECT:
411       {
412         PEMRDELETEOBJECT pDeleteObject = (PEMRDELETEOBJECT) mr;
413         DeleteObject( (handletable->objectHandle)[pDeleteObject->ihObject]);
414         (handletable->objectHandle)[pDeleteObject->ihObject] = 0;
415         break;
416       }
417     case EMR_SETWINDOWORGEX:
418       {
419                 XFORM xform;
420                 PEMRSETWINDOWORGEX pSetWindowOrgEx = (PEMRSETWINDOWORGEX) mr;
421
422                 xform.eM11 = 1;
423                 xform.eM12 = 0;
424                 xform.eM21 = 0;
425                 xform.eM22 = 1;
426                 xform.eDx = -pSetWindowOrgEx->ptlOrigin.x;
427                 xform.eDy = -pSetWindowOrgEx->ptlOrigin.y;
428
429                 ModifyWorldTransform(hdc, &xform, MWT_LEFTMULTIPLY);
430                 break;
431       }
432     case EMR_SETWINDOWEXTEX:
433       {
434         PEMRSETWINDOWEXTEX pSetWindowExtEx = (PEMRSETWINDOWEXTEX) mr;
435         SetWindowExtEx(hdc, pSetWindowExtEx->szlExtent.cx,
436                        pSetWindowExtEx->szlExtent.cy, NULL);
437         break;
438       }
439     case EMR_SETVIEWPORTORGEX:
440       {
441         PEMRSETVIEWPORTORGEX pSetViewportOrgEx = (PEMRSETVIEWPORTORGEX) mr;
442         SetViewportOrgEx(hdc, pSetViewportOrgEx->ptlOrigin.x,
443                          pSetViewportOrgEx->ptlOrigin.y, NULL);
444         break;
445       }
446     case EMR_SETVIEWPORTEXTEX:
447       {
448         PEMRSETVIEWPORTEXTEX pSetViewportExtEx = (PEMRSETVIEWPORTEXTEX) mr;
449         SetViewportExtEx(hdc, pSetViewportExtEx->szlExtent.cx,
450                          pSetViewportExtEx->szlExtent.cy, NULL);
451         break;
452       }
453     case EMR_CREATEPEN:
454       {
455         PEMRCREATEPEN pCreatePen = (PEMRCREATEPEN) mr;
456         (handletable->objectHandle)[pCreatePen->ihPen] =
457           CreatePenIndirect(&pCreatePen->lopn);
458         break;
459       }
460     case EMR_EXTCREATEPEN:
461       {
462         PEMREXTCREATEPEN pPen = (PEMREXTCREATEPEN) mr;
463         LOGBRUSH lb;
464         lb.lbStyle = pPen->elp.elpBrushStyle;
465         lb.lbColor = pPen->elp.elpColor;
466         lb.lbHatch = pPen->elp.elpHatch;
467
468         if(pPen->offBmi || pPen->offBits)
469           FIXME("EMR_EXTCREATEPEN: Need to copy brush bitmap\n");
470
471         (handletable->objectHandle)[pPen->ihPen] =
472           ExtCreatePen(pPen->elp.elpPenStyle, pPen->elp.elpWidth, &lb,
473                        pPen->elp.elpNumEntries, pPen->elp.elpStyleEntry);
474         break;
475       }
476     case EMR_CREATEBRUSHINDIRECT:
477       {
478         PEMRCREATEBRUSHINDIRECT pBrush = (PEMRCREATEBRUSHINDIRECT) mr;
479         (handletable->objectHandle)[pBrush->ihBrush] =
480           CreateBrushIndirect(&pBrush->lb);
481         break;
482       }
483     case EMR_EXTCREATEFONTINDIRECTW:
484       {
485         PEMREXTCREATEFONTINDIRECTW pFont = (PEMREXTCREATEFONTINDIRECTW) mr;
486         (handletable->objectHandle)[pFont->ihFont] =
487           CreateFontIndirectW(&pFont->elfw.elfLogFont);
488         break;
489       }
490     case EMR_MOVETOEX:
491       {
492         PEMRMOVETOEX pMoveToEx = (PEMRMOVETOEX) mr;
493         MoveToEx(hdc, pMoveToEx->ptl.x, pMoveToEx->ptl.y, NULL);
494         break;
495       }
496     case EMR_LINETO:
497       {
498         PEMRLINETO pLineTo = (PEMRLINETO) mr;
499         LineTo(hdc, pLineTo->ptl.x, pLineTo->ptl.y);
500         break;
501       }
502     case EMR_RECTANGLE:
503       {
504         PEMRRECTANGLE pRect = (PEMRRECTANGLE) mr;
505         Rectangle(hdc, pRect->rclBox.left, pRect->rclBox.top,
506                   pRect->rclBox.right, pRect->rclBox.bottom);
507         break;
508       }
509     case EMR_ELLIPSE:
510       {
511         PEMRELLIPSE pEllipse = (PEMRELLIPSE) mr;
512         Ellipse(hdc, pEllipse->rclBox.left, pEllipse->rclBox.top,
513                 pEllipse->rclBox.right, pEllipse->rclBox.bottom);
514         break;
515       }
516     case EMR_POLYGON16:
517       {
518         PEMRPOLYGON16 pPoly = (PEMRPOLYGON16) mr;
519         /* Shouldn't use Polygon16 since pPoly->cpts is DWORD */
520         POINT *pts = HeapAlloc( GetProcessHeap(), 0,
521                                 pPoly->cpts * sizeof(POINT) );
522         DWORD i;
523         for(i = 0; i < pPoly->cpts; i++)
524           CONV_POINT16TO32(pPoly->apts + i, pts + i);
525         Polygon(hdc, pts, pPoly->cpts);
526         HeapFree( GetProcessHeap(), 0, pts );
527         break;
528       }
529     case EMR_POLYLINE16:
530       {
531         PEMRPOLYLINE16 pPoly = (PEMRPOLYLINE16) mr;
532         /* Shouldn't use Polyline16 since pPoly->cpts is DWORD */
533         POINT *pts = HeapAlloc( GetProcessHeap(), 0,
534                                 pPoly->cpts * sizeof(POINT) );
535         DWORD i;
536         for(i = 0; i < pPoly->cpts; i++)
537           CONV_POINT16TO32(pPoly->apts + i, pts + i);
538         Polyline(hdc, pts, pPoly->cpts);
539         HeapFree( GetProcessHeap(), 0, pts );
540         break;
541       }
542     case EMR_POLYLINETO16:
543       {
544         PEMRPOLYLINETO16 pPoly = (PEMRPOLYLINETO16) mr;
545         /* Shouldn't use PolylineTo16 since pPoly->cpts is DWORD */
546         POINT *pts = HeapAlloc( GetProcessHeap(), 0,
547                                 pPoly->cpts * sizeof(POINT) );
548         DWORD i;
549         for(i = 0; i < pPoly->cpts; i++)
550           CONV_POINT16TO32(pPoly->apts + i, pts + i);
551         PolylineTo(hdc, pts, pPoly->cpts);
552         HeapFree( GetProcessHeap(), 0, pts );
553         break;
554       }
555     case EMR_POLYBEZIER16:
556       {
557         PEMRPOLYBEZIER16 pPoly = (PEMRPOLYBEZIER16) mr;
558         /* Shouldn't use PolyBezier16 since pPoly->cpts is DWORD */
559         POINT *pts = HeapAlloc( GetProcessHeap(), 0,
560                                 pPoly->cpts * sizeof(POINT) );
561         DWORD i;
562         for(i = 0; i < pPoly->cpts; i++)
563           CONV_POINT16TO32(pPoly->apts + i, pts + i);
564         PolyBezier(hdc, pts, pPoly->cpts);
565         HeapFree( GetProcessHeap(), 0, pts );
566         break;
567       }
568     case EMR_POLYBEZIERTO16:
569       {
570         PEMRPOLYBEZIERTO16 pPoly = (PEMRPOLYBEZIERTO16) mr;
571         /* Shouldn't use PolyBezierTo16 since pPoly->cpts is DWORD */
572         POINT *pts = HeapAlloc( GetProcessHeap(), 0,
573                                 pPoly->cpts * sizeof(POINT) );
574         DWORD i;
575         for(i = 0; i < pPoly->cpts; i++)
576           CONV_POINT16TO32(pPoly->apts + i, pts + i);
577         PolyBezierTo(hdc, pts, pPoly->cpts);
578         HeapFree( GetProcessHeap(), 0, pts );
579         break;
580       }
581     case EMR_POLYPOLYGON16:
582       {
583         PEMRPOLYPOLYGON16 pPolyPoly = (PEMRPOLYPOLYGON16) mr;
584         /* NB POINTS array doesn't start at pPolyPoly->apts it's actually
585            pPolyPoly->aPolyCounts + pPolyPoly->nPolys */
586
587         POINT *pts = HeapAlloc( GetProcessHeap(), 0,
588                                 pPolyPoly->cpts * sizeof(POINT) );
589         DWORD i;
590         for(i = 0; i < pPolyPoly->cpts; i++)
591           CONV_POINT16TO32((POINT16*) (pPolyPoly->aPolyCounts +
592                                       pPolyPoly->nPolys) + i, pts + i);
593
594         PolyPolygon(hdc, pts, (INT*)pPolyPoly->aPolyCounts, pPolyPoly->nPolys);
595         HeapFree( GetProcessHeap(), 0, pts );
596         break;
597       }
598     case EMR_POLYPOLYLINE16:
599       {
600         PEMRPOLYPOLYLINE16 pPolyPoly = (PEMRPOLYPOLYLINE16) mr;
601         /* NB POINTS array doesn't start at pPolyPoly->apts it's actually
602            pPolyPoly->aPolyCounts + pPolyPoly->nPolys */
603
604         POINT *pts = HeapAlloc( GetProcessHeap(), 0,
605                                 pPolyPoly->cpts * sizeof(POINT) );
606         DWORD i;
607         for(i = 0; i < pPolyPoly->cpts; i++)
608           CONV_POINT16TO32((POINT16*) (pPolyPoly->aPolyCounts +
609                                       pPolyPoly->nPolys) + i, pts + i);
610
611         PolyPolyline(hdc, pts, pPolyPoly->aPolyCounts, pPolyPoly->nPolys);
612         HeapFree( GetProcessHeap(), 0, pts );
613         break;
614       }
615
616     case EMR_STRETCHDIBITS:
617       {
618         EMRSTRETCHDIBITS *pStretchDIBits = (EMRSTRETCHDIBITS *)mr;
619
620         StretchDIBits(hdc,
621                       pStretchDIBits->xDest,
622                       pStretchDIBits->yDest,
623                       pStretchDIBits->cxDest,
624                       pStretchDIBits->cyDest,
625                       pStretchDIBits->xSrc,
626                       pStretchDIBits->ySrc,
627                       pStretchDIBits->cxSrc,
628                       pStretchDIBits->cySrc,
629                       (BYTE *)mr + pStretchDIBits->offBitsSrc,
630                       (const BITMAPINFO *)((BYTE *)mr + pStretchDIBits->offBmiSrc),
631                       pStretchDIBits->iUsageSrc,
632                       pStretchDIBits->dwRop);
633         break;
634       }
635
636     case EMR_EXTTEXTOUTA:
637     {
638         PEMREXTTEXTOUTA pExtTextOutA = (PEMREXTTEXTOUTA)mr;
639         RECT rc;
640
641         rc.left = pExtTextOutA->emrtext.rcl.left;
642         rc.top = pExtTextOutA->emrtext.rcl.top;
643         rc.right = pExtTextOutA->emrtext.rcl.right;
644         rc.bottom = pExtTextOutA->emrtext.rcl.bottom;
645         ExtTextOutA(hdc, pExtTextOutA->emrtext.ptlReference.x, pExtTextOutA->emrtext.ptlReference.y,
646             pExtTextOutA->emrtext.fOptions, &rc,
647             (LPSTR)((BYTE *)mr + pExtTextOutA->emrtext.offString), pExtTextOutA->emrtext.nChars,
648             (INT *)((BYTE *)mr + pExtTextOutA->emrtext.offDx));
649         break;
650     }
651
652     case EMR_EXTTEXTOUTW:
653     {
654         PEMREXTTEXTOUTW pExtTextOutW = (PEMREXTTEXTOUTW)mr;
655         RECT rc;
656
657         rc.left = pExtTextOutW->emrtext.rcl.left;
658         rc.top = pExtTextOutW->emrtext.rcl.top;
659         rc.right = pExtTextOutW->emrtext.rcl.right;
660         rc.bottom = pExtTextOutW->emrtext.rcl.bottom;
661         ExtTextOutW(hdc, pExtTextOutW->emrtext.ptlReference.x, pExtTextOutW->emrtext.ptlReference.y,
662             pExtTextOutW->emrtext.fOptions, &rc,
663             (LPWSTR)((BYTE *)mr + pExtTextOutW->emrtext.offString), pExtTextOutW->emrtext.nChars,
664             (INT *)((BYTE *)mr + pExtTextOutW->emrtext.offDx));
665         break;
666     }
667
668     case EMR_CREATEPALETTE:
669       {
670         PEMRCREATEPALETTE lpCreatePal = (PEMRCREATEPALETTE)mr;
671
672         (handletable->objectHandle)[ lpCreatePal->ihPal ] =
673                 CreatePalette( &lpCreatePal->lgpl );
674
675         break;
676       }
677
678     case EMR_SELECTPALETTE:
679       {
680         PEMRSELECTPALETTE lpSelectPal = (PEMRSELECTPALETTE)mr;
681
682         if( lpSelectPal->ihPal & 0x80000000 ) {
683                 SelectPalette( hdc, GetStockObject(lpSelectPal->ihPal & 0x7fffffff), TRUE);
684         } else {
685         (handletable->objectHandle)[ lpSelectPal->ihPal ] =
686                 SelectPalette( hdc, (handletable->objectHandle)[lpSelectPal->ihPal], TRUE);
687         }
688         break;
689       }
690
691     case EMR_REALIZEPALETTE:
692       {
693         RealizePalette( hdc );
694         break;
695       }
696
697     case EMR_EXTSELECTCLIPRGN:
698       {
699         PEMREXTSELECTCLIPRGN lpRgn = (PEMREXTSELECTCLIPRGN)mr;
700         HRGN hRgn = ExtCreateRegion(NULL, lpRgn->cbRgnData, (RGNDATA *)lpRgn->RgnData);
701         ExtSelectClipRgn(hdc, hRgn, (INT)(lpRgn->iMode));
702         /* ExtSelectClipRgn created a copy of the region */
703         DeleteObject(hRgn);
704         break;
705       }
706
707     case EMR_SETMETARGN:
708       {
709         SetMetaRgn( hdc );
710         break;
711       }
712
713     case EMR_SETWORLDTRANSFORM:
714       {
715         PEMRSETWORLDTRANSFORM lpXfrm = (PEMRSETWORLDTRANSFORM)mr;
716         SetWorldTransform( hdc, &lpXfrm->xform );
717         break;
718       }
719
720     case EMR_POLYBEZIER:
721       {
722         PEMRPOLYBEZIER lpPolyBez = (PEMRPOLYBEZIER)mr;
723         PolyBezier(hdc, (const LPPOINT)lpPolyBez->aptl, (UINT)lpPolyBez->cptl);
724         break;
725       }
726
727     case EMR_POLYGON:
728       {
729         PEMRPOLYGON lpPoly = (PEMRPOLYGON)mr;
730         Polygon( hdc, (const LPPOINT)lpPoly->aptl, (UINT)lpPoly->cptl );
731         break;
732       }
733
734     case EMR_POLYLINE:
735       {
736         PEMRPOLYLINE lpPolyLine = (PEMRPOLYLINE)mr;
737         Polyline(hdc, (const LPPOINT)lpPolyLine->aptl, (UINT)lpPolyLine->cptl);
738         break;
739       }
740
741     case EMR_POLYBEZIERTO:
742       {
743         PEMRPOLYBEZIERTO lpPolyBezierTo = (PEMRPOLYBEZIERTO)mr;
744         PolyBezierTo( hdc, (const LPPOINT)lpPolyBezierTo->aptl,
745                       (UINT)lpPolyBezierTo->cptl );
746         break;
747       }
748
749     case EMR_POLYLINETO:
750       {
751         PEMRPOLYLINETO lpPolyLineTo = (PEMRPOLYLINETO)mr;
752         PolylineTo( hdc, (const LPPOINT)lpPolyLineTo->aptl,
753                     (UINT)lpPolyLineTo->cptl );
754         break;
755       }
756
757     case EMR_POLYPOLYLINE:
758       {
759         PEMRPOLYPOLYLINE pPolyPolyline = (PEMRPOLYPOLYLINE) mr;
760         /* NB Points at pPolyPolyline->aPolyCounts + pPolyPolyline->nPolys */
761
762         PolyPolyline(hdc, (LPPOINT)(pPolyPolyline->aPolyCounts +
763                                     pPolyPolyline->nPolys),
764                      pPolyPolyline->aPolyCounts,
765                      pPolyPolyline->nPolys );
766
767         break;
768       }
769
770     case EMR_POLYPOLYGON:
771       {
772         PEMRPOLYPOLYGON pPolyPolygon = (PEMRPOLYPOLYGON) mr;
773
774         /* NB Points at pPolyPolygon->aPolyCounts + pPolyPolygon->nPolys */
775
776         PolyPolygon(hdc, (LPPOINT)(pPolyPolygon->aPolyCounts +
777                                    pPolyPolygon->nPolys),
778                     (INT*)pPolyPolygon->aPolyCounts, pPolyPolygon->nPolys );
779         break;
780       }
781
782     case EMR_SETBRUSHORGEX:
783       {
784         PEMRSETBRUSHORGEX lpSetBrushOrgEx = (PEMRSETBRUSHORGEX)mr;
785
786         SetBrushOrgEx( hdc,
787                        (INT)lpSetBrushOrgEx->ptlOrigin.x,
788                        (INT)lpSetBrushOrgEx->ptlOrigin.y,
789                        NULL );
790
791         break;
792       }
793
794     case EMR_SETPIXELV:
795       {
796         PEMRSETPIXELV lpSetPixelV = (PEMRSETPIXELV)mr;
797
798         SetPixelV( hdc,
799                    (INT)lpSetPixelV->ptlPixel.x,
800                    (INT)lpSetPixelV->ptlPixel.y,
801                    lpSetPixelV->crColor );
802
803         break;
804       }
805
806     case EMR_SETMAPPERFLAGS:
807       {
808         PEMRSETMAPPERFLAGS lpSetMapperFlags = (PEMRSETMAPPERFLAGS)mr;
809
810         SetMapperFlags( hdc, lpSetMapperFlags->dwFlags );
811
812         break;
813       }
814
815     case EMR_SETCOLORADJUSTMENT:
816       {
817         PEMRSETCOLORADJUSTMENT lpSetColorAdjust = (PEMRSETCOLORADJUSTMENT)mr;
818
819         SetColorAdjustment( hdc, &lpSetColorAdjust->ColorAdjustment );
820
821         break;
822       }
823
824     case EMR_OFFSETCLIPRGN:
825       {
826         PEMROFFSETCLIPRGN lpOffsetClipRgn = (PEMROFFSETCLIPRGN)mr;
827
828         OffsetClipRgn( hdc,
829                        (INT)lpOffsetClipRgn->ptlOffset.x,
830                        (INT)lpOffsetClipRgn->ptlOffset.y );
831
832         break;
833       }
834
835     case EMR_EXCLUDECLIPRECT:
836       {
837         PEMREXCLUDECLIPRECT lpExcludeClipRect = (PEMREXCLUDECLIPRECT)mr;
838
839         ExcludeClipRect( hdc,
840                          lpExcludeClipRect->rclClip.left,
841                          lpExcludeClipRect->rclClip.top,
842                          lpExcludeClipRect->rclClip.right,
843                          lpExcludeClipRect->rclClip.bottom  );
844
845          break;
846       }
847
848     case EMR_SCALEVIEWPORTEXTEX:
849       {
850         PEMRSCALEVIEWPORTEXTEX lpScaleViewportExtEx = (PEMRSCALEVIEWPORTEXTEX)mr;
851
852         ScaleViewportExtEx( hdc,
853                             lpScaleViewportExtEx->xNum,
854                             lpScaleViewportExtEx->xDenom,
855                             lpScaleViewportExtEx->yNum,
856                             lpScaleViewportExtEx->yDenom,
857                             NULL );
858
859         break;
860       }
861
862     case EMR_SCALEWINDOWEXTEX:
863       {
864         PEMRSCALEWINDOWEXTEX lpScaleWindowExtEx = (PEMRSCALEWINDOWEXTEX)mr;
865
866         ScaleWindowExtEx( hdc,
867                           lpScaleWindowExtEx->xNum,
868                           lpScaleWindowExtEx->xDenom,
869                           lpScaleWindowExtEx->yNum,
870                           lpScaleWindowExtEx->yDenom,
871                           NULL );
872
873         break;
874       }
875
876     case EMR_MODIFYWORLDTRANSFORM:
877       {
878         PEMRMODIFYWORLDTRANSFORM lpModifyWorldTrans = (PEMRMODIFYWORLDTRANSFORM)mr;
879
880         ModifyWorldTransform( hdc, &lpModifyWorldTrans->xform,
881                               lpModifyWorldTrans->iMode );
882
883         break;
884       }
885
886     case EMR_ANGLEARC:
887       {
888         PEMRANGLEARC lpAngleArc = (PEMRANGLEARC)mr;
889
890         AngleArc( hdc,
891                  (INT)lpAngleArc->ptlCenter.x, (INT)lpAngleArc->ptlCenter.y,
892                  lpAngleArc->nRadius, lpAngleArc->eStartAngle,
893                  lpAngleArc->eSweepAngle );
894
895         break;
896       }
897
898     case EMR_ROUNDRECT:
899       {
900         PEMRROUNDRECT lpRoundRect = (PEMRROUNDRECT)mr;
901
902         RoundRect( hdc,
903                    lpRoundRect->rclBox.left,
904                    lpRoundRect->rclBox.top,
905                    lpRoundRect->rclBox.right,
906                    lpRoundRect->rclBox.bottom,
907                    lpRoundRect->szlCorner.cx,
908                    lpRoundRect->szlCorner.cy );
909
910         break;
911       }
912
913     case EMR_ARC:
914       {
915         PEMRARC lpArc = (PEMRARC)mr;
916
917         Arc( hdc,
918              (INT)lpArc->rclBox.left,
919              (INT)lpArc->rclBox.top,
920              (INT)lpArc->rclBox.right,
921              (INT)lpArc->rclBox.bottom,
922              (INT)lpArc->ptlStart.x,
923              (INT)lpArc->ptlStart.y,
924              (INT)lpArc->ptlEnd.x,
925              (INT)lpArc->ptlEnd.y );
926
927         break;
928       }
929
930     case EMR_CHORD:
931       {
932         PEMRCHORD lpChord = (PEMRCHORD)mr;
933
934         Chord( hdc,
935              (INT)lpChord->rclBox.left,
936              (INT)lpChord->rclBox.top,
937              (INT)lpChord->rclBox.right,
938              (INT)lpChord->rclBox.bottom,
939              (INT)lpChord->ptlStart.x,
940              (INT)lpChord->ptlStart.y,
941              (INT)lpChord->ptlEnd.x,
942              (INT)lpChord->ptlEnd.y );
943
944         break;
945       }
946
947     case EMR_PIE:
948       {
949         PEMRPIE lpPie = (PEMRPIE)mr;
950
951         Pie( hdc,
952              (INT)lpPie->rclBox.left,
953              (INT)lpPie->rclBox.top,
954              (INT)lpPie->rclBox.right,
955              (INT)lpPie->rclBox.bottom,
956              (INT)lpPie->ptlStart.x,
957              (INT)lpPie->ptlStart.y,
958              (INT)lpPie->ptlEnd.x,
959              (INT)lpPie->ptlEnd.y );
960
961        break;
962       }
963
964     case EMR_ARCTO:
965       {
966         PEMRARC lpArcTo = (PEMRARC)mr;
967
968         ArcTo( hdc,
969                (INT)lpArcTo->rclBox.left,
970                (INT)lpArcTo->rclBox.top,
971                (INT)lpArcTo->rclBox.right,
972                (INT)lpArcTo->rclBox.bottom,
973                (INT)lpArcTo->ptlStart.x,
974                (INT)lpArcTo->ptlStart.y,
975                (INT)lpArcTo->ptlEnd.x,
976                (INT)lpArcTo->ptlEnd.y );
977
978         break;
979       }
980
981     case EMR_EXTFLOODFILL:
982       {
983         PEMREXTFLOODFILL lpExtFloodFill = (PEMREXTFLOODFILL)mr;
984
985         ExtFloodFill( hdc,
986                       (INT)lpExtFloodFill->ptlStart.x,
987                       (INT)lpExtFloodFill->ptlStart.y,
988                       lpExtFloodFill->crColor,
989                       (UINT)lpExtFloodFill->iMode );
990
991         break;
992       }
993
994     case EMR_POLYDRAW:
995       {
996         PEMRPOLYDRAW lpPolyDraw = (PEMRPOLYDRAW)mr;
997         PolyDraw( hdc,
998                   (const LPPOINT)lpPolyDraw->aptl,
999                   lpPolyDraw->abTypes,
1000                   (INT)lpPolyDraw->cptl );
1001
1002         break;
1003       }
1004
1005     case EMR_SETARCDIRECTION:
1006       {
1007         PEMRSETARCDIRECTION lpSetArcDirection = (PEMRSETARCDIRECTION)mr;
1008         SetArcDirection( hdc, (INT)lpSetArcDirection->iArcDirection );
1009         break;
1010       }
1011
1012     case EMR_SETMITERLIMIT:
1013       {
1014         PEMRSETMITERLIMIT lpSetMiterLimit = (PEMRSETMITERLIMIT)mr;
1015         SetMiterLimit( hdc, lpSetMiterLimit->eMiterLimit, NULL );
1016         break;
1017       }
1018
1019     case EMR_BEGINPATH:
1020       {
1021         BeginPath( hdc );
1022         break;
1023       }
1024
1025     case EMR_ENDPATH:
1026       {
1027         EndPath( hdc );
1028         break;
1029       }
1030
1031     case EMR_CLOSEFIGURE:
1032       {
1033         CloseFigure( hdc );
1034         break;
1035       }
1036
1037     case EMR_FILLPATH:
1038       {
1039         /*PEMRFILLPATH lpFillPath = (PEMRFILLPATH)mr;*/
1040         FillPath( hdc );
1041         break;
1042       }
1043
1044     case EMR_STROKEANDFILLPATH:
1045       {
1046         /*PEMRSTROKEANDFILLPATH lpStrokeAndFillPath = (PEMRSTROKEANDFILLPATH)mr;*/
1047         StrokeAndFillPath( hdc );
1048         break;
1049       }
1050
1051     case EMR_STROKEPATH:
1052       {
1053         /*PEMRSTROKEPATH lpStrokePath = (PEMRSTROKEPATH)mr;*/
1054         StrokePath( hdc );
1055         break;
1056       }
1057
1058     case EMR_FLATTENPATH:
1059       {
1060         FlattenPath( hdc );
1061         break;
1062       }
1063
1064     case EMR_WIDENPATH:
1065       {
1066         WidenPath( hdc );
1067         break;
1068       }
1069
1070     case EMR_SELECTCLIPPATH:
1071       {
1072         PEMRSELECTCLIPPATH lpSelectClipPath = (PEMRSELECTCLIPPATH)mr;
1073         SelectClipPath( hdc, (INT)lpSelectClipPath->iMode );
1074         break;
1075       }
1076
1077     case EMR_ABORTPATH:
1078       {
1079         AbortPath( hdc );
1080         break;
1081       }
1082
1083     case EMR_CREATECOLORSPACE:
1084       {
1085         PEMRCREATECOLORSPACE lpCreateColorSpace = (PEMRCREATECOLORSPACE)mr;
1086         (handletable->objectHandle)[lpCreateColorSpace->ihCS] =
1087            CreateColorSpaceA( &lpCreateColorSpace->lcs );
1088         break;
1089       }
1090
1091     case EMR_SETCOLORSPACE:
1092       {
1093         PEMRSETCOLORSPACE lpSetColorSpace = (PEMRSETCOLORSPACE)mr;
1094         SetColorSpace( hdc,
1095                        (handletable->objectHandle)[lpSetColorSpace->ihCS] );
1096         break;
1097       }
1098
1099     case EMR_DELETECOLORSPACE:
1100       {
1101         PEMRDELETECOLORSPACE lpDeleteColorSpace = (PEMRDELETECOLORSPACE)mr;
1102         DeleteColorSpace( (handletable->objectHandle)[lpDeleteColorSpace->ihCS] );
1103         break;
1104       }
1105
1106     case EMR_SETICMMODE:
1107       {
1108         PERMSETICMMODE lpSetICMMode = (PERMSETICMMODE)mr;
1109         SetICMMode( hdc, (INT)lpSetICMMode->iMode );
1110         break;
1111       }
1112
1113     case EMR_PIXELFORMAT:
1114       {
1115         INT iPixelFormat;
1116         PEMRPIXELFORMAT lpPixelFormat = (PEMRPIXELFORMAT)mr;
1117
1118         iPixelFormat = ChoosePixelFormat( hdc, &lpPixelFormat->pfd );
1119         SetPixelFormat( hdc, iPixelFormat, &lpPixelFormat->pfd );
1120
1121         break;
1122       }
1123
1124     case EMR_SETPALETTEENTRIES:
1125       {
1126         PEMRSETPALETTEENTRIES lpSetPaletteEntries = (PEMRSETPALETTEENTRIES)mr;
1127
1128         SetPaletteEntries( (handletable->objectHandle)[lpSetPaletteEntries->ihPal],
1129                            (UINT)lpSetPaletteEntries->iStart,
1130                            (UINT)lpSetPaletteEntries->cEntries,
1131                            lpSetPaletteEntries->aPalEntries );
1132
1133         break;
1134       }
1135
1136     case EMR_RESIZEPALETTE:
1137       {
1138         PEMRRESIZEPALETTE lpResizePalette = (PEMRRESIZEPALETTE)mr;
1139
1140         ResizePalette( (handletable->objectHandle)[lpResizePalette->ihPal],
1141                        (UINT)lpResizePalette->cEntries );
1142
1143         break;
1144       }
1145
1146     case EMR_CREATEDIBPATTERNBRUSHPT:
1147       {
1148         PEMRCREATEDIBPATTERNBRUSHPT lpCreate = (PEMRCREATEDIBPATTERNBRUSHPT)mr;
1149
1150         /* This is a BITMAPINFO struct followed directly by bitmap bits */
1151         LPVOID lpPackedStruct = HeapAlloc( GetProcessHeap(),
1152                                            0,
1153                                            lpCreate->cbBmi + lpCreate->cbBits );
1154         /* Now pack this structure */
1155         memcpy( lpPackedStruct,
1156                 ((BYTE*)lpCreate) + lpCreate->offBmi,
1157                 lpCreate->cbBmi );
1158         memcpy( ((BYTE*)lpPackedStruct) + lpCreate->cbBmi,
1159                 ((BYTE*)lpCreate) + lpCreate->offBits,
1160                 lpCreate->cbBits );
1161
1162         (handletable->objectHandle)[lpCreate->ihBrush] =
1163            CreateDIBPatternBrushPt( lpPackedStruct,
1164                                     (UINT)lpCreate->iUsage );
1165
1166         break;
1167       }
1168
1169     case EMR_CREATEMONOBRUSH:
1170     {
1171         PEMRCREATEMONOBRUSH pCreateMonoBrush = (PEMRCREATEMONOBRUSH)mr;
1172         BITMAPINFO *pbi = (BITMAPINFO *)((BYTE *)mr + pCreateMonoBrush->offBmi);
1173         HBITMAP hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
1174                 (BYTE *)mr + pCreateMonoBrush->offBits, pbi, pCreateMonoBrush->iUsage);
1175         (handletable->objectHandle)[pCreateMonoBrush->ihBrush] = CreatePatternBrush(hBmp);
1176         /* CreatePatternBrush created a copy of the bitmap */
1177         DeleteObject(hBmp);
1178         break;
1179     }
1180
1181     case EMR_BITBLT:
1182     {
1183         PEMRBITBLT pBitBlt = (PEMRBITBLT)mr;
1184         HDC hdcSrc = CreateCompatibleDC(hdc);
1185         HBRUSH hBrush, hBrushOld;
1186         HBITMAP hBmp = 0, hBmpOld = 0;
1187         BITMAPINFO *pbi = (BITMAPINFO *)((BYTE *)mr + pBitBlt->offBmiSrc);
1188
1189         SetWorldTransform(hdcSrc, &pBitBlt->xformSrc);
1190
1191         hBrush = CreateSolidBrush(pBitBlt->crBkColorSrc);
1192         hBrushOld = SelectObject(hdcSrc, hBrush);
1193         PatBlt(hdcSrc, pBitBlt->rclBounds.left, pBitBlt->rclBounds.top,
1194                pBitBlt->rclBounds.right - pBitBlt->rclBounds.left,
1195                pBitBlt->rclBounds.bottom - pBitBlt->rclBounds.top, PATCOPY);
1196         SelectObject(hdcSrc, hBrushOld);
1197         DeleteObject(hBrush);
1198
1199         if (pBitBlt->offBmiSrc > 0)
1200         {
1201                 hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
1202                                           (BYTE *)mr + pBitBlt->offBitsSrc, pbi, pBitBlt->iUsageSrc);
1203                 hBmpOld = SelectObject(hdcSrc, hBmp);
1204         }
1205
1206         BitBlt(hdc,
1207                pBitBlt->xDest,
1208                pBitBlt->yDest,
1209                pBitBlt->cxDest,
1210                pBitBlt->cyDest,
1211                hdcSrc,
1212                pBitBlt->xSrc,
1213                pBitBlt->ySrc,
1214                pBitBlt->dwRop);
1215
1216         if (pBitBlt->offBmiSrc > 0)
1217         {
1218                 SelectObject(hdcSrc, hBmpOld);
1219                 DeleteObject(hBmp);
1220         }
1221         DeleteDC(hdcSrc);
1222         break;
1223     }
1224
1225     case EMR_STRETCHBLT:
1226     {
1227         PEMRSTRETCHBLT pStretchBlt= (PEMRSTRETCHBLT)mr;
1228         HDC hdcSrc = CreateCompatibleDC(hdc);
1229         HBRUSH hBrush, hBrushOld;
1230         HBITMAP hBmp = 0, hBmpOld = 0;
1231         BITMAPINFO *pbi = (BITMAPINFO *)((BYTE *)mr + pStretchBlt->offBmiSrc);
1232
1233         SetWorldTransform(hdcSrc, &pStretchBlt->xformSrc);
1234
1235         hBrush = CreateSolidBrush(pStretchBlt->crBkColorSrc);
1236         hBrushOld = SelectObject(hdcSrc, hBrush);
1237         PatBlt(hdcSrc, pStretchBlt->rclBounds.left, pStretchBlt->rclBounds.top,
1238                pStretchBlt->rclBounds.right - pStretchBlt->rclBounds.left,
1239                pStretchBlt->rclBounds.bottom - pStretchBlt->rclBounds.top, PATCOPY);
1240         SelectObject(hdcSrc, hBrushOld);
1241         DeleteObject(hBrush);
1242
1243         if (pStretchBlt->offBmiSrc)
1244         {
1245                 hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
1246                                           (BYTE *)mr + pStretchBlt->offBitsSrc, pbi, pStretchBlt->iUsageSrc);
1247                 hBmpOld = SelectObject(hdcSrc, hBmp);
1248         }
1249
1250         StretchBlt(hdc,
1251                pStretchBlt->xDest,
1252                pStretchBlt->yDest,
1253                pStretchBlt->cxDest,
1254                pStretchBlt->cyDest,
1255                hdcSrc,
1256                pStretchBlt->xSrc,
1257                pStretchBlt->ySrc,
1258                pStretchBlt->cxSrc,
1259                pStretchBlt->cySrc,
1260                pStretchBlt->dwRop);
1261
1262
1263         if (pStretchBlt->offBmiSrc)
1264         {
1265                 SelectObject(hdcSrc, hBmpOld);
1266                 DeleteObject(hBmp);
1267         }
1268
1269         DeleteDC(hdcSrc);
1270         break;
1271     }
1272
1273     case EMR_MASKBLT:
1274     {
1275         PEMRMASKBLT pMaskBlt= (PEMRMASKBLT)mr;
1276         HDC hdcSrc = CreateCompatibleDC(hdc);
1277         HBRUSH hBrush, hBrushOld;
1278         HBITMAP hBmp, hBmpOld, hBmpMask;
1279         BITMAPINFO *pbi;
1280
1281         SetWorldTransform(hdcSrc, &pMaskBlt->xformSrc);
1282
1283         hBrush = CreateSolidBrush(pMaskBlt->crBkColorSrc);
1284         hBrushOld = SelectObject(hdcSrc, hBrush);
1285         PatBlt(hdcSrc, pMaskBlt->rclBounds.left, pMaskBlt->rclBounds.top,
1286                pMaskBlt->rclBounds.right - pMaskBlt->rclBounds.left,
1287                pMaskBlt->rclBounds.bottom - pMaskBlt->rclBounds.top, PATCOPY);
1288         SelectObject(hdcSrc, hBrushOld);
1289         DeleteObject(hBrush);
1290
1291         pbi = (BITMAPINFO *)((BYTE *)mr + pMaskBlt->offBmiMask);
1292         hBmpMask = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
1293                               (BYTE *)mr + pMaskBlt->offBitsMask, pbi, pMaskBlt->iUsageMask);
1294
1295         pbi = (BITMAPINFO *)((BYTE *)mr + pMaskBlt->offBmiSrc);
1296         hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
1297                               (BYTE *)mr + pMaskBlt->offBitsSrc, pbi, pMaskBlt->iUsageSrc);
1298         hBmpOld = SelectObject(hdcSrc, hBmp);
1299         MaskBlt(hdc,
1300                 pMaskBlt->xDest,
1301                 pMaskBlt->yDest,
1302                 pMaskBlt->cxDest,
1303                 pMaskBlt->cyDest,
1304                 hdcSrc,
1305                 pMaskBlt->xSrc,
1306                 pMaskBlt->ySrc,
1307                 hBmpMask,
1308                 pMaskBlt->xMask,
1309                 pMaskBlt->yMask,
1310                 pMaskBlt->dwRop);
1311         SelectObject(hdcSrc, hBmpOld);
1312         DeleteObject(hBmp);
1313         DeleteObject(hBmpMask);
1314         DeleteDC(hdcSrc);
1315         break;
1316     }
1317
1318     case EMR_PLGBLT:
1319     {
1320         PEMRPLGBLT pPlgBlt= (PEMRPLGBLT)mr;
1321         HDC hdcSrc = CreateCompatibleDC(hdc);
1322         HBRUSH hBrush, hBrushOld;
1323         HBITMAP hBmp, hBmpOld, hBmpMask;
1324         BITMAPINFO *pbi;
1325         POINT pts[3];
1326
1327         SetWorldTransform(hdcSrc, &pPlgBlt->xformSrc);
1328
1329         pts[0].x = pPlgBlt->aptlDst[0].x; pts[0].y = pPlgBlt->aptlDst[0].y;
1330         pts[1].x = pPlgBlt->aptlDst[1].x; pts[1].y = pPlgBlt->aptlDst[1].y;
1331         pts[2].x = pPlgBlt->aptlDst[2].x; pts[2].y = pPlgBlt->aptlDst[2].y;
1332
1333         hBrush = CreateSolidBrush(pPlgBlt->crBkColorSrc);
1334         hBrushOld = SelectObject(hdcSrc, hBrush);
1335         PatBlt(hdcSrc, pPlgBlt->rclBounds.left, pPlgBlt->rclBounds.top,
1336                pPlgBlt->rclBounds.right - pPlgBlt->rclBounds.left,
1337                pPlgBlt->rclBounds.bottom - pPlgBlt->rclBounds.top, PATCOPY);
1338         SelectObject(hdcSrc, hBrushOld);
1339         DeleteObject(hBrush);
1340
1341         pbi = (BITMAPINFO *)((BYTE *)mr + pPlgBlt->offBmiMask);
1342         hBmpMask = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
1343                               (BYTE *)mr + pPlgBlt->offBitsMask, pbi, pPlgBlt->iUsageMask);
1344
1345         pbi = (BITMAPINFO *)((BYTE *)mr + pPlgBlt->offBmiSrc);
1346         hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
1347                               (BYTE *)mr + pPlgBlt->offBitsSrc, pbi, pPlgBlt->iUsageSrc);
1348         hBmpOld = SelectObject(hdcSrc, hBmp);
1349         PlgBlt(hdc,
1350                pts,
1351                hdcSrc,
1352                pPlgBlt->xSrc,
1353                pPlgBlt->ySrc,
1354                pPlgBlt->cxSrc,
1355                pPlgBlt->cySrc,
1356                hBmpMask,
1357                pPlgBlt->xMask,
1358                pPlgBlt->yMask);
1359         SelectObject(hdcSrc, hBmpOld);
1360         DeleteObject(hBmp);
1361         DeleteObject(hBmpMask);
1362         DeleteDC(hdcSrc);
1363         break;
1364     }
1365
1366     case EMR_SETDIBITSTODEVICE:
1367     {
1368         PEMRSETDIBITSTODEVICE pSetDIBitsToDevice = (PEMRSETDIBITSTODEVICE)mr;
1369
1370         SetDIBitsToDevice(hdc,
1371                           pSetDIBitsToDevice->xDest,
1372                           pSetDIBitsToDevice->yDest,
1373                           pSetDIBitsToDevice->cxSrc,
1374                           pSetDIBitsToDevice->cySrc,
1375                           pSetDIBitsToDevice->xSrc,
1376                           pSetDIBitsToDevice->ySrc,
1377                           pSetDIBitsToDevice->iStartScan,
1378                           pSetDIBitsToDevice->cScans,
1379                           (BYTE *)mr + pSetDIBitsToDevice->offBitsSrc,
1380                           (BITMAPINFO *)((BYTE *)mr + pSetDIBitsToDevice->offBmiSrc),
1381                           pSetDIBitsToDevice->iUsageSrc);
1382         break;
1383     }
1384
1385     case EMR_POLYTEXTOUTA:
1386     {
1387         PEMRPOLYTEXTOUTA pPolyTextOutA = (PEMRPOLYTEXTOUTA)mr;
1388         POLYTEXTA *polytextA = HeapAlloc(GetProcessHeap(), 0, pPolyTextOutA->cStrings * sizeof(POLYTEXTA));
1389         LONG i;
1390         XFORM xform, xformOld;
1391         int gModeOld;
1392
1393         gModeOld = SetGraphicsMode(hdc, pPolyTextOutA->iGraphicsMode);
1394         GetWorldTransform(hdc, &xformOld);
1395
1396         xform.eM11 = pPolyTextOutA->exScale;
1397         xform.eM12 = 0.0;
1398         xform.eM21 = 0.0;
1399         xform.eM22 = pPolyTextOutA->eyScale;
1400         xform.eDx = 0.0;
1401         xform.eDy = 0.0;
1402         SetWorldTransform(hdc, &xform);
1403
1404         /* Set up POLYTEXTA structures */
1405         for(i = 0; i < pPolyTextOutA->cStrings; i++)
1406         {
1407             polytextA[i].x = pPolyTextOutA->aemrtext[i].ptlReference.x;
1408             polytextA[i].y = pPolyTextOutA->aemrtext[i].ptlReference.y;
1409             polytextA[i].n = pPolyTextOutA->aemrtext[i].nChars;
1410             polytextA[i].lpstr = (LPSTR)((BYTE *)mr + pPolyTextOutA->aemrtext[i].offString);
1411             polytextA[i].uiFlags = pPolyTextOutA->aemrtext[i].fOptions;
1412             polytextA[i].rcl.left = pPolyTextOutA->aemrtext[i].rcl.left;
1413             polytextA[i].rcl.right = pPolyTextOutA->aemrtext[i].rcl.right;
1414             polytextA[i].rcl.top = pPolyTextOutA->aemrtext[i].rcl.top;
1415             polytextA[i].rcl.bottom = pPolyTextOutA->aemrtext[i].rcl.bottom;
1416             polytextA[i].pdx = (int *)((BYTE *)mr + pPolyTextOutA->aemrtext[i].offDx);
1417         }
1418         PolyTextOutA(hdc, polytextA, pPolyTextOutA->cStrings);
1419         HeapFree(GetProcessHeap(), 0, polytextA);
1420
1421         SetWorldTransform(hdc, &xformOld);
1422         SetGraphicsMode(hdc, gModeOld);
1423         break;
1424     }
1425
1426     case EMR_POLYTEXTOUTW:
1427     {
1428         PEMRPOLYTEXTOUTW pPolyTextOutW = (PEMRPOLYTEXTOUTW)mr;
1429         POLYTEXTW *polytextW = HeapAlloc(GetProcessHeap(), 0, pPolyTextOutW->cStrings * sizeof(POLYTEXTW));
1430         LONG i;
1431         XFORM xform, xformOld;
1432         int gModeOld;
1433
1434         gModeOld = SetGraphicsMode(hdc, pPolyTextOutW->iGraphicsMode);
1435         GetWorldTransform(hdc, &xformOld);
1436
1437         xform.eM11 = pPolyTextOutW->exScale;
1438         xform.eM12 = 0.0;
1439         xform.eM21 = 0.0;
1440         xform.eM22 = pPolyTextOutW->eyScale;
1441         xform.eDx = 0.0;
1442         xform.eDy = 0.0;
1443         SetWorldTransform(hdc, &xform);
1444
1445         /* Set up POLYTEXTW structures */
1446         for(i = 0; i < pPolyTextOutW->cStrings; i++)
1447         {
1448             polytextW[i].x = pPolyTextOutW->aemrtext[i].ptlReference.x;
1449             polytextW[i].y = pPolyTextOutW->aemrtext[i].ptlReference.y;
1450             polytextW[i].n = pPolyTextOutW->aemrtext[i].nChars;
1451             polytextW[i].lpstr = (LPWSTR)((BYTE *)mr + pPolyTextOutW->aemrtext[i].offString);
1452             polytextW[i].uiFlags = pPolyTextOutW->aemrtext[i].fOptions;
1453             polytextW[i].rcl.left = pPolyTextOutW->aemrtext[i].rcl.left;
1454             polytextW[i].rcl.right = pPolyTextOutW->aemrtext[i].rcl.right;
1455             polytextW[i].rcl.top = pPolyTextOutW->aemrtext[i].rcl.top;
1456             polytextW[i].rcl.bottom = pPolyTextOutW->aemrtext[i].rcl.bottom;
1457             polytextW[i].pdx = (int *)((BYTE *)mr + pPolyTextOutW->aemrtext[i].offDx);
1458         }
1459         PolyTextOutW(hdc, polytextW, pPolyTextOutW->cStrings);
1460         HeapFree(GetProcessHeap(), 0, polytextW);
1461
1462         SetWorldTransform(hdc, &xformOld);
1463         SetGraphicsMode(hdc, gModeOld);
1464         break;
1465     }
1466
1467     case EMR_FILLRGN:
1468     {
1469         PEMRFILLRGN pFillRgn = (PEMRFILLRGN)mr;
1470         HRGN hRgn = ExtCreateRegion(NULL, pFillRgn->cbRgnData, (RGNDATA *)pFillRgn->RgnData);
1471         FillRgn(hdc,
1472                 hRgn,
1473                 (handletable->objectHandle)[pFillRgn->ihBrush]);
1474         DeleteObject(hRgn);
1475         break;
1476     }
1477
1478     case EMR_FRAMERGN:
1479     {
1480         PEMRFRAMERGN pFrameRgn = (PEMRFRAMERGN)mr;
1481         HRGN hRgn = ExtCreateRegion(NULL, pFrameRgn->cbRgnData, (RGNDATA *)pFrameRgn->RgnData);
1482         FrameRgn(hdc,
1483                  hRgn,
1484                  (handletable->objectHandle)[pFrameRgn->ihBrush],
1485                  pFrameRgn->szlStroke.cx,
1486                  pFrameRgn->szlStroke.cy);
1487         DeleteObject(hRgn);
1488         break;
1489     }
1490
1491     case EMR_INVERTRGN:
1492     {
1493         PEMRINVERTRGN pInvertRgn = (PEMRINVERTRGN)mr;
1494         HRGN hRgn = ExtCreateRegion(NULL, pInvertRgn->cbRgnData, (RGNDATA *)pInvertRgn->RgnData);
1495         InvertRgn(hdc, hRgn);
1496         DeleteObject(hRgn);
1497         break;
1498     }
1499
1500     case EMR_PAINTRGN:
1501     {
1502         PEMRPAINTRGN pPaintRgn = (PEMRPAINTRGN)mr;
1503         HRGN hRgn = ExtCreateRegion(NULL, pPaintRgn->cbRgnData, (RGNDATA *)pPaintRgn->RgnData);
1504         PaintRgn(hdc, hRgn);
1505         DeleteObject(hRgn);
1506         break;
1507     }
1508
1509     case EMR_SETTEXTJUSTIFICATION:
1510     {
1511         PEMRSETTEXTJUSTIFICATION pSetTextJust = (PEMRSETTEXTJUSTIFICATION)mr;
1512         SetTextJustification(hdc, pSetTextJust->nBreakExtra, pSetTextJust->nBreakCount);
1513         break;
1514     }
1515
1516     case EMR_SETLAYOUT:
1517     {
1518         PEMRSETLAYOUT pSetLayout = (PEMRSETLAYOUT)mr;
1519         SetLayout(hdc, pSetLayout->iMode);
1520         break;
1521     }
1522
1523     case EMR_POLYDRAW16:
1524     case EMR_GLSRECORD:
1525     case EMR_GLSBOUNDEDRECORD:
1526         case EMR_DRAWESCAPE :
1527         case EMR_EXTESCAPE:
1528         case EMR_STARTDOC:
1529         case EMR_SMALLTEXTOUT:
1530         case EMR_FORCEUFIMAPPING:
1531         case EMR_NAMEDESCAPE:
1532         case EMR_COLORCORRECTPALETTE:
1533         case EMR_SETICMPROFILEA:
1534         case EMR_SETICMPROFILEW:
1535         case EMR_ALPHABLEND:
1536         case EMR_TRANSPARENTBLT:
1537         case EMR_GRADIENTFILL:
1538         case EMR_SETLINKEDUFI:
1539         case EMR_COLORMATCHTOTARGETW:
1540         case EMR_CREATECOLORSPACEW:
1541
1542     default:
1543       /* From docs: If PlayEnhMetaFileRecord doesn't recognize a
1544                     record then ignore and return TRUE. */
1545       FIXME("type %d is unimplemented\n", type);
1546       break;
1547     }
1548   return TRUE;
1549 }
1550
1551
1552 /*****************************************************************************
1553  *
1554  *        EnumEnhMetaFile  (GDI32.@)
1555  *
1556  *  Walk an enhanced metafile, calling a user-specified function _EnhMetaFunc_
1557  *  for each
1558  *  record. Returns when either every record has been used or
1559  *  when _EnhMetaFunc_ returns FALSE.
1560  *
1561  *
1562  * RETURNS
1563  *  TRUE if every record is used, FALSE if any invocation of _EnhMetaFunc_
1564  *  returns FALSE.
1565  *
1566  * BUGS
1567  *   Ignores rect.
1568  */
1569 BOOL WINAPI EnumEnhMetaFile(
1570      HDC hdc,                /* [in] device context to pass to _EnhMetaFunc_ */
1571      HENHMETAFILE hmf,       /* [in] EMF to walk */
1572      ENHMFENUMPROC callback, /* [in] callback function */
1573      LPVOID data,            /* [in] optional data for callback function */
1574      const RECT *lpRect      /* [in] bounding rectangle for rendered metafile */
1575     )
1576 {
1577     BOOL ret;
1578     ENHMETAHEADER *emh;
1579     ENHMETARECORD *emr;
1580     DWORD offset;
1581     UINT i;
1582     HANDLETABLE *ht;
1583     INT savedMode = 0;
1584     FLOAT xSrcPixSize, ySrcPixSize, xscale, yscale;
1585     XFORM savedXform, xform;
1586     HPEN hPen = (HPEN)NULL;
1587     HBRUSH hBrush = (HBRUSH)NULL;
1588     HFONT hFont = (HFONT)NULL;
1589
1590     if(!lpRect)
1591     {
1592         SetLastError(ERROR_INVALID_PARAMETER);
1593         return FALSE;
1594     }
1595
1596     emh = EMF_GetEnhMetaHeader(hmf);
1597     if(!emh) {
1598         SetLastError(ERROR_INVALID_HANDLE);
1599         return FALSE;
1600     }
1601
1602     ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1603                     sizeof(HANDLETABLE) * emh->nHandles );
1604     if(!ht)
1605     {
1606         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1607         return FALSE;
1608     }
1609     ht->objectHandle[0] = hmf;
1610
1611     if (hdc)
1612     {
1613         TRACE("rect: %d,%d - %d,%d. rclFrame: %ld,%ld - %ld,%ld\n",
1614               lpRect->left, lpRect->top, lpRect->right, lpRect->bottom,
1615               emh->rclFrame.left, emh->rclFrame.top, emh->rclFrame.right,
1616               emh->rclFrame.bottom);
1617
1618         xSrcPixSize = (FLOAT) emh->szlMillimeters.cx / emh->szlDevice.cx;
1619         ySrcPixSize = (FLOAT) emh->szlMillimeters.cy / emh->szlDevice.cy;
1620         xscale = (FLOAT)(lpRect->right - lpRect->left) * 100.0 /
1621           (emh->rclFrame.right - emh->rclFrame.left) * xSrcPixSize;
1622         yscale = (FLOAT)(lpRect->bottom - lpRect->top) * 100.0 /
1623           (emh->rclFrame.bottom - emh->rclFrame.top) * ySrcPixSize;
1624
1625         xform.eM11 = xscale;
1626         xform.eM12 = 0;
1627         xform.eM21 = 0;
1628         xform.eM22 = yscale;
1629         xform.eDx = (FLOAT) lpRect->left - (lpRect->right - lpRect->left) *
1630           emh->rclFrame.left / (emh->rclFrame.right - emh->rclFrame.left);
1631         xform.eDy = (FLOAT) lpRect->top - (lpRect->bottom - lpRect->top) *
1632           emh->rclFrame.top / (emh->rclFrame.bottom - emh->rclFrame.top);
1633
1634         savedMode = SetGraphicsMode(hdc, GM_ADVANCED);
1635         GetWorldTransform(hdc, &savedXform);
1636
1637         if (!ModifyWorldTransform(hdc, &xform, MWT_RIGHTMULTIPLY)) {
1638             ERR("World transform failed!\n");
1639         }
1640
1641         /* save the current pen, brush and font */
1642         hPen = GetCurrentObject(hdc, OBJ_PEN);
1643         hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
1644         hFont = GetCurrentObject(hdc, OBJ_FONT);
1645     }
1646
1647     TRACE("nSize = %ld, nBytes = %ld, nHandles = %d, nRecords = %ld, nPalEntries = %ld\n",
1648         emh->nSize, emh->nBytes, emh->nHandles, emh->nRecords, emh->nPalEntries);
1649
1650     ret = TRUE;
1651     offset = 0;
1652     while(ret && offset < emh->nBytes)
1653     {
1654         emr = (ENHMETARECORD *)((char *)emh + offset);
1655         TRACE("Calling EnumFunc with record type %ld, size %ld\n", emr->iType, emr->nSize);
1656         ret = (*callback)(hdc, ht, emr, emh->nHandles, data);
1657         offset += emr->nSize;
1658     }
1659
1660     if (hdc)
1661     {
1662         /* restore pen, brush and font */
1663         SelectObject(hdc, hBrush);
1664         SelectObject(hdc, hPen);
1665         SelectObject(hdc, hFont);
1666
1667         SetWorldTransform(hdc, &savedXform);
1668         if (savedMode)
1669             SetGraphicsMode(hdc, savedMode);
1670     }
1671
1672     for(i = 1; i < emh->nHandles; i++) /* Don't delete element 0 (hmf) */
1673         if( (ht->objectHandle)[i] )
1674             DeleteObject( (ht->objectHandle)[i] );
1675
1676     HeapFree( GetProcessHeap(), 0, ht );
1677     return ret;
1678 }
1679
1680 static INT CALLBACK EMF_PlayEnhMetaFileCallback(HDC hdc, HANDLETABLE *ht,
1681                                                 ENHMETARECORD *emr,
1682                                                 INT handles, LPVOID data)
1683 {
1684     return PlayEnhMetaFileRecord(hdc, ht, emr, handles);
1685 }
1686
1687 /**************************************************************************
1688  *    PlayEnhMetaFile  (GDI32.@)
1689  *
1690  *    Renders an enhanced metafile into a specified rectangle *lpRect
1691  *    in device context hdc.
1692  *
1693  */
1694 BOOL WINAPI PlayEnhMetaFile(
1695        HDC hdc,           /* [in] DC to render into */
1696        HENHMETAFILE hmf,  /* [in] metafile to render */
1697        const RECT *lpRect /* [in] rectangle to place metafile inside */
1698       )
1699 {
1700     return EnumEnhMetaFile(hdc, hmf, EMF_PlayEnhMetaFileCallback, NULL,
1701                            lpRect);
1702 }
1703
1704 /*****************************************************************************
1705  *  DeleteEnhMetaFile (GDI32.@)
1706  *
1707  *  Deletes an enhanced metafile and frees the associated storage.
1708  */
1709 BOOL WINAPI DeleteEnhMetaFile(HENHMETAFILE hmf)
1710 {
1711     return EMF_Delete_HENHMETAFILE( hmf );
1712 }
1713
1714 /*****************************************************************************
1715  *  CopyEnhMetaFileA (GDI32.@)  Duplicate an enhanced metafile
1716  *
1717  *
1718  */
1719 HENHMETAFILE WINAPI CopyEnhMetaFileA(
1720     HENHMETAFILE hmfSrc,
1721     LPCSTR file)
1722 {
1723     ENHMETAHEADER *emrSrc = EMF_GetEnhMetaHeader( hmfSrc ), *emrDst;
1724     HENHMETAFILE hmfDst;
1725
1726     if(!emrSrc) return FALSE;
1727     if (!file) {
1728         emrDst = HeapAlloc( GetProcessHeap(), 0, emrSrc->nBytes );
1729         memcpy( emrDst, emrSrc, emrSrc->nBytes );
1730         hmfDst = EMF_Create_HENHMETAFILE( emrDst, FALSE );
1731     } else {
1732         HANDLE hFile;
1733         hFile = CreateFileA( file, GENERIC_WRITE | GENERIC_READ, 0, NULL,
1734                              CREATE_ALWAYS, 0, 0);
1735         WriteFile( hFile, emrSrc, emrSrc->nBytes, 0, 0);
1736         hmfDst = EMF_GetEnhMetaFile( hFile );
1737         CloseHandle( hFile );
1738     }
1739     return hmfDst;
1740 }
1741
1742
1743 /* Struct to be used to be passed in the LPVOID parameter for cbEnhPaletteCopy */
1744 typedef struct tagEMF_PaletteCopy
1745 {
1746    UINT cEntries;
1747    LPPALETTEENTRY lpPe;
1748 } EMF_PaletteCopy;
1749
1750 /***************************************************************
1751  * Find the EMR_EOF record and then use it to find the
1752  * palette entries for this enhanced metafile.
1753  * The lpData is actually a pointer to a EMF_PaletteCopy struct
1754  * which contains the max number of elements to copy and where
1755  * to copy them to.
1756  *
1757  * NOTE: To be used by GetEnhMetaFilePaletteEntries only!
1758  */
1759 INT CALLBACK cbEnhPaletteCopy( HDC a,
1760                                LPHANDLETABLE b,
1761                                LPENHMETARECORD lpEMR,
1762                                INT c,
1763                                LPVOID lpData )
1764 {
1765
1766   if ( lpEMR->iType == EMR_EOF )
1767   {
1768     PEMREOF lpEof = (PEMREOF)lpEMR;
1769     EMF_PaletteCopy* info = (EMF_PaletteCopy*)lpData;
1770     DWORD dwNumPalToCopy = min( lpEof->nPalEntries, info->cEntries );
1771
1772     TRACE( "copying 0x%08lx palettes\n", dwNumPalToCopy );
1773
1774     memcpy( (LPVOID)info->lpPe,
1775             (LPVOID)(((LPSTR)lpEof) + lpEof->offPalEntries),
1776             sizeof( *(info->lpPe) ) * dwNumPalToCopy );
1777
1778     /* Update the passed data as a return code */
1779     info->lpPe     = NULL; /* Palettes were copied! */
1780     info->cEntries = (UINT)dwNumPalToCopy;
1781
1782     return FALSE; /* That's all we need */
1783   }
1784
1785   return TRUE;
1786 }
1787
1788 /*****************************************************************************
1789  *  GetEnhMetaFilePaletteEntries (GDI32.@)
1790  *
1791  *  Copy the palette and report size
1792  *
1793  *  BUGS: Error codes (SetLastError) are not set on failures
1794  */
1795 UINT WINAPI GetEnhMetaFilePaletteEntries( HENHMETAFILE hEmf,
1796                                           UINT cEntries,
1797                                           LPPALETTEENTRY lpPe )
1798 {
1799   ENHMETAHEADER* enhHeader = EMF_GetEnhMetaHeader( hEmf );
1800   EMF_PaletteCopy infoForCallBack;
1801
1802   TRACE( "(%04x,%d,%p)\n", hEmf, cEntries, lpPe );
1803
1804   /* First check if there are any palettes associated with
1805      this metafile. */
1806   if ( enhHeader->nPalEntries == 0 ) return 0;
1807
1808   /* Is the user requesting the number of palettes? */
1809   if ( lpPe == NULL ) return (UINT)enhHeader->nPalEntries;
1810
1811   /* Copy cEntries worth of PALETTEENTRY structs into the buffer */
1812   infoForCallBack.cEntries = cEntries;
1813   infoForCallBack.lpPe     = lpPe;
1814
1815   if ( !EnumEnhMetaFile( 0, hEmf, cbEnhPaletteCopy,
1816                          &infoForCallBack, NULL ) )
1817       return GDI_ERROR;
1818
1819   /* Verify that the callback executed correctly */
1820   if ( infoForCallBack.lpPe != NULL )
1821   {
1822      /* Callback proc had error! */
1823      ERR( "cbEnhPaletteCopy didn't execute correctly\n" );
1824      return GDI_ERROR;
1825   }
1826
1827   return infoForCallBack.cEntries;
1828 }
1829
1830 /******************************************************************
1831  *         SetWinMetaFileBits   (GDI32.@)
1832  *
1833  *         Translate from old style to new style.
1834  *
1835  * BUGS: - This doesn't take the DC and scaling into account
1836  *       - Most record conversions aren't implemented
1837  *       - Handle slot assignement is primative and most likely doesn't work
1838  */
1839 HENHMETAFILE WINAPI SetWinMetaFileBits(UINT cbBuffer,
1840                                            CONST BYTE *lpbBuffer,
1841                                            HDC hdcRef,
1842                                            CONST METAFILEPICT *lpmfp
1843                                            )
1844 {
1845      HENHMETAFILE    hMf;
1846      LPVOID          lpNewEnhMetaFileBuffer = NULL;
1847      UINT            uNewEnhMetaFileBufferSize = 0;
1848      BOOL            bFoundEOF = FALSE;
1849
1850      FIXME( "(%d,%p,%04x,%p):stub\n", cbBuffer, lpbBuffer, hdcRef, lpmfp );
1851
1852      /* 1. Get the header - skip over this and get straight to the records  */
1853
1854      uNewEnhMetaFileBufferSize = sizeof( ENHMETAHEADER );
1855      lpNewEnhMetaFileBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1856                                          uNewEnhMetaFileBufferSize );
1857
1858      if( lpNewEnhMetaFileBuffer == NULL )
1859      {
1860        goto error;
1861      }
1862
1863      /* Fill in the header record */
1864      {
1865        LPENHMETAHEADER lpNewEnhMetaFileHeader = (LPENHMETAHEADER)lpNewEnhMetaFileBuffer;
1866
1867        lpNewEnhMetaFileHeader->iType = EMR_HEADER;
1868        lpNewEnhMetaFileHeader->nSize = sizeof( ENHMETAHEADER );
1869
1870        /* FIXME: Not right. Must be able to get this from the DC */
1871        lpNewEnhMetaFileHeader->rclBounds.left   = 0;
1872        lpNewEnhMetaFileHeader->rclBounds.right  = 0;
1873        lpNewEnhMetaFileHeader->rclBounds.top    = 0;
1874        lpNewEnhMetaFileHeader->rclBounds.bottom = 0;
1875
1876        /* FIXME: Not right. Must be able to get this from the DC */
1877        lpNewEnhMetaFileHeader->rclFrame.left   = 0;
1878        lpNewEnhMetaFileHeader->rclFrame.right  = 0;
1879        lpNewEnhMetaFileHeader->rclFrame.top    = 0;
1880        lpNewEnhMetaFileHeader->rclFrame.bottom = 0;
1881
1882        lpNewEnhMetaFileHeader->dSignature=ENHMETA_SIGNATURE;
1883        lpNewEnhMetaFileHeader->nVersion=0x10000;
1884        lpNewEnhMetaFileHeader->nBytes = lpNewEnhMetaFileHeader->nSize;
1885        lpNewEnhMetaFileHeader->sReserved=0;
1886
1887         /* FIXME: if there is a description add it */
1888         lpNewEnhMetaFileHeader->nDescription=0;
1889         lpNewEnhMetaFileHeader->offDescription=0;
1890
1891         lpNewEnhMetaFileHeader->nHandles = 0; /* No handles yet */
1892         lpNewEnhMetaFileHeader->nRecords = 0;
1893
1894         /* I am pretty sure this starts at 0 and grows as entries are added */
1895         lpNewEnhMetaFileHeader->nPalEntries = 0;
1896
1897         /* Size in Pixels */
1898         lpNewEnhMetaFileHeader->szlDevice.cx = GetDeviceCaps(hdcRef,HORZRES);
1899         lpNewEnhMetaFileHeader->szlDevice.cy = GetDeviceCaps(hdcRef,VERTRES);
1900
1901         /* Size in mm */
1902         lpNewEnhMetaFileHeader->szlMillimeters.cx =
1903                                         GetDeviceCaps(hdcRef,HORZSIZE);
1904         lpNewEnhMetaFileHeader->szlMillimeters.cy =
1905                                         GetDeviceCaps(hdcRef,VERTSIZE);
1906
1907        /* FIXME: Add in the rest of the fields to the header */
1908        /* cbPixelFormat
1909           offPixelFormat,
1910           bOpenGL */
1911      }
1912
1913      (char*)lpbBuffer += ((METAHEADER*)lpbBuffer)->mtHeaderSize * 2; /* Point past the header - FIXME: metafile quirk? */
1914
1915      /* 2. Enum over individual records and convert them to the new type of records */
1916      while( !bFoundEOF )
1917      {
1918
1919         LPMETARECORD lpMetaRecord = (LPMETARECORD)lpbBuffer;
1920
1921 #define EMF_ReAllocAndAdjustPointers( a , b ) \
1922                                         { \
1923                                           LPVOID lpTmp; \
1924                                           lpTmp = HeapReAlloc( GetProcessHeap(), 0, \
1925                                                                lpNewEnhMetaFileBuffer, \
1926                                                                uNewEnhMetaFileBufferSize + (b) ); \
1927                                           if( lpTmp == NULL ) { ERR( "No memory!\n" ); goto error; } \
1928                                           lpNewEnhMetaFileBuffer = lpTmp; \
1929                                           lpRecord = (a)( (char*)lpNewEnhMetaFileBuffer + uNewEnhMetaFileBufferSize ); \
1930                                           uNewEnhMetaFileBufferSize += (b); \
1931                                         }
1932
1933         switch( lpMetaRecord->rdFunction )
1934         {
1935           case META_EOF:
1936           {
1937              PEMREOF lpRecord;
1938              size_t uRecord = sizeof(*lpRecord);
1939
1940              EMF_ReAllocAndAdjustPointers(PEMREOF,uRecord);
1941
1942              /* Fill the new record - FIXME: This is not right */
1943              lpRecord->emr.iType = EMR_EOF;
1944              lpRecord->emr.nSize = sizeof( *lpRecord );
1945              lpRecord->nPalEntries = 0;     /* FIXME */
1946              lpRecord->offPalEntries = 0;   /* FIXME */
1947              lpRecord->nSizeLast = 0;       /* FIXME */
1948
1949              /* No more records after this one */
1950              bFoundEOF = TRUE;
1951
1952              FIXME( "META_EOF conversion not correct\n" );
1953              break;
1954           }
1955
1956           case META_SETMAPMODE:
1957           {
1958              PEMRSETMAPMODE lpRecord;
1959              size_t uRecord = sizeof(*lpRecord);
1960
1961              EMF_ReAllocAndAdjustPointers(PEMRSETMAPMODE,uRecord);
1962
1963              lpRecord->emr.iType = EMR_SETMAPMODE;
1964              lpRecord->emr.nSize = sizeof( *lpRecord );
1965
1966              lpRecord->iMode = lpMetaRecord->rdParm[0];
1967
1968              break;
1969           }
1970
1971           case META_DELETEOBJECT: /* Select and Delete structures are the same */
1972           case META_SELECTOBJECT:
1973           {
1974             PEMRDELETEOBJECT lpRecord;
1975             size_t uRecord = sizeof(*lpRecord);
1976
1977             EMF_ReAllocAndAdjustPointers(PEMRDELETEOBJECT,uRecord);
1978
1979             if( lpMetaRecord->rdFunction == META_DELETEOBJECT )
1980             {
1981               lpRecord->emr.iType = EMR_DELETEOBJECT;
1982             }
1983             else
1984             {
1985               lpRecord->emr.iType = EMR_SELECTOBJECT;
1986             }
1987             lpRecord->emr.nSize = sizeof( *lpRecord );
1988
1989             lpRecord->ihObject = lpMetaRecord->rdParm[0]; /* FIXME: Handle */
1990
1991             break;
1992           }
1993
1994           case META_POLYGON: /* This is just plain busted. I don't know what I'm doing */
1995           {
1996              PEMRPOLYGON16 lpRecord; /* FIXME: Should it be a poly or poly16? */
1997              size_t uRecord = sizeof(*lpRecord);
1998
1999              EMF_ReAllocAndAdjustPointers(PEMRPOLYGON16,uRecord);
2000
2001              /* FIXME: This is mostly all wrong */
2002              lpRecord->emr.iType = EMR_POLYGON16;
2003              lpRecord->emr.nSize = sizeof( *lpRecord );
2004
2005              lpRecord->rclBounds.left   = 0;
2006              lpRecord->rclBounds.right  = 0;
2007              lpRecord->rclBounds.top    = 0;
2008              lpRecord->rclBounds.bottom = 0;
2009
2010              lpRecord->cpts = 0;
2011              lpRecord->apts[0].x = 0;
2012              lpRecord->apts[0].y = 0;
2013
2014              FIXME( "META_POLYGON conversion not correct\n" );
2015
2016              break;
2017           }
2018
2019           case META_SETPOLYFILLMODE:
2020           {
2021              PEMRSETPOLYFILLMODE lpRecord;
2022              size_t uRecord = sizeof(*lpRecord);
2023
2024              EMF_ReAllocAndAdjustPointers(PEMRSETPOLYFILLMODE,uRecord);
2025
2026              lpRecord->emr.iType = EMR_SETPOLYFILLMODE;
2027              lpRecord->emr.nSize = sizeof( *lpRecord );
2028
2029              lpRecord->iMode = lpMetaRecord->rdParm[0];
2030
2031              break;
2032           }
2033
2034           case META_SETWINDOWORG:
2035           {
2036              PEMRSETWINDOWORGEX lpRecord; /* Seems to be the closest thing */
2037              size_t uRecord = sizeof(*lpRecord);
2038
2039              EMF_ReAllocAndAdjustPointers(PEMRSETWINDOWORGEX,uRecord);
2040
2041              lpRecord->emr.iType = EMR_SETWINDOWORGEX;
2042              lpRecord->emr.nSize = sizeof( *lpRecord );
2043
2044              lpRecord->ptlOrigin.x = lpMetaRecord->rdParm[1];
2045              lpRecord->ptlOrigin.y = lpMetaRecord->rdParm[0];
2046
2047              break;
2048           }
2049
2050           case META_SETWINDOWEXT:  /* Structure is the same for SETWINDOWEXT & SETVIEWPORTEXT */
2051           case META_SETVIEWPORTEXT:
2052           {
2053              PEMRSETWINDOWEXTEX lpRecord;
2054              size_t uRecord = sizeof(*lpRecord);
2055
2056              EMF_ReAllocAndAdjustPointers(PEMRSETWINDOWEXTEX,uRecord);
2057
2058              if ( lpMetaRecord->rdFunction == META_SETWINDOWEXT )
2059              {
2060                lpRecord->emr.iType = EMR_SETWINDOWORGEX;
2061              }
2062              else
2063              {
2064                lpRecord->emr.iType = EMR_SETVIEWPORTEXTEX;
2065              }
2066              lpRecord->emr.nSize = sizeof( *lpRecord );
2067
2068              lpRecord->szlExtent.cx = lpMetaRecord->rdParm[1];
2069              lpRecord->szlExtent.cy = lpMetaRecord->rdParm[0];
2070
2071              break;
2072           }
2073
2074           case META_CREATEBRUSHINDIRECT:
2075           {
2076              PEMRCREATEBRUSHINDIRECT lpRecord;
2077              size_t uRecord = sizeof(*lpRecord);
2078
2079              EMF_ReAllocAndAdjustPointers(PEMRCREATEBRUSHINDIRECT,uRecord);
2080
2081              lpRecord->emr.iType = EMR_CREATEBRUSHINDIRECT;
2082              lpRecord->emr.nSize = sizeof( *lpRecord );
2083
2084              lpRecord->ihBrush    = ((LPENHMETAHEADER)lpNewEnhMetaFileBuffer)->nHandles;
2085              lpRecord->lb.lbStyle = ((LPLOGBRUSH16)lpMetaRecord->rdParm)->lbStyle;
2086              lpRecord->lb.lbColor = ((LPLOGBRUSH16)lpMetaRecord->rdParm)->lbColor;
2087              lpRecord->lb.lbHatch = ((LPLOGBRUSH16)lpMetaRecord->rdParm)->lbHatch;
2088
2089              ((LPENHMETAHEADER)lpNewEnhMetaFileBuffer)->nHandles += 1; /* New handle */
2090
2091              break;
2092           }
2093
2094           case META_LINETO:
2095           case META_MOVETO:
2096           {
2097              PEMRLINETO lpRecord;
2098              size_t uRecord = sizeof(*lpRecord);
2099
2100              EMF_ReAllocAndAdjustPointers(PEMRLINETO,uRecord);
2101
2102              if ( lpMetaRecord->rdFunction == META_LINETO )
2103              {
2104                lpRecord->emr.iType = EMR_LINETO;
2105              }
2106              else
2107              {
2108                lpRecord->emr.iType = EMR_MOVETOEX;
2109              }
2110              lpRecord->emr.nSize = sizeof( *lpRecord );
2111
2112              lpRecord->ptl.x = lpMetaRecord->rdParm[1];
2113              lpRecord->ptl.y = lpMetaRecord->rdParm[0];
2114
2115              break;
2116             }
2117
2118           case META_SETTEXTCOLOR:
2119           case META_SETBKCOLOR:
2120           {
2121              PEMRSETBKCOLOR lpRecord;
2122              size_t uRecord = sizeof(*lpRecord);
2123
2124              EMF_ReAllocAndAdjustPointers(PEMRSETBKCOLOR,uRecord);
2125
2126              if ( lpMetaRecord->rdFunction == META_SETTEXTCOLOR )
2127              {
2128                lpRecord->emr.iType = EMR_SETTEXTCOLOR;
2129              }
2130              else
2131              {
2132                lpRecord->emr.iType = EMR_SETBKCOLOR;
2133              }
2134              lpRecord->emr.nSize = sizeof( *lpRecord );
2135
2136              lpRecord->crColor = MAKELONG(lpMetaRecord->rdParm[0],
2137                                     lpMetaRecord->rdParm[1]);
2138
2139              break;
2140           }
2141
2142
2143
2144           /* These are all unimplemented and as such are intended to fall through to the default case */
2145           case META_SETBKMODE:
2146           case META_SETROP2:
2147           case META_SETRELABS:
2148           case META_SETSTRETCHBLTMODE:
2149           case META_SETVIEWPORTORG:
2150           case META_OFFSETWINDOWORG:
2151           case META_SCALEWINDOWEXT:
2152           case META_OFFSETVIEWPORTORG:
2153           case META_SCALEVIEWPORTEXT:
2154           case META_EXCLUDECLIPRECT:
2155           case META_INTERSECTCLIPRECT:
2156           case META_ARC:
2157           case META_ELLIPSE:
2158           case META_FLOODFILL:
2159           case META_PIE:
2160           case META_RECTANGLE:
2161           case META_ROUNDRECT:
2162           case META_PATBLT:
2163           case META_SAVEDC:
2164           case META_SETPIXEL:
2165           case META_OFFSETCLIPRGN:
2166           case META_TEXTOUT:
2167           case META_POLYPOLYGON:
2168           case META_POLYLINE:
2169           case META_RESTOREDC:
2170           case META_CHORD:
2171           case META_CREATEPATTERNBRUSH:
2172           case META_CREATEPENINDIRECT:
2173           case META_CREATEFONTINDIRECT:
2174           case META_CREATEPALETTE:
2175           case META_SETTEXTALIGN:
2176           case META_SELECTPALETTE:
2177           case META_SETMAPPERFLAGS:
2178           case META_REALIZEPALETTE:
2179           case META_ESCAPE:
2180           case META_EXTTEXTOUT:
2181           case META_STRETCHDIB:
2182           case META_DIBSTRETCHBLT:
2183           case META_STRETCHBLT:
2184           case META_BITBLT:
2185           case META_CREATEREGION:
2186           case META_FILLREGION:
2187           case META_FRAMEREGION:
2188           case META_INVERTREGION:
2189           case META_PAINTREGION:
2190           case META_SELECTCLIPREGION:
2191           case META_DIBCREATEPATTERNBRUSH:
2192           case META_DIBBITBLT:
2193           case META_SETTEXTCHAREXTRA:
2194           case META_SETTEXTJUSTIFICATION:
2195           case META_EXTFLOODFILL:
2196           case META_SETDIBTODEV:
2197           case META_DRAWTEXT:
2198           case META_ANIMATEPALETTE:
2199           case META_SETPALENTRIES:
2200           case META_RESIZEPALETTE:
2201           case META_RESETDC:
2202           case META_STARTDOC:
2203           case META_STARTPAGE:
2204           case META_ENDPAGE:
2205           case META_ABORTDOC:
2206           case META_ENDDOC:
2207           case META_CREATEBRUSH:
2208           case META_CREATEBITMAPINDIRECT:
2209           case META_CREATEBITMAP:
2210           /* Fall through to unimplemented */
2211           default:
2212           {
2213             /* Not implemented yet */
2214             FIXME( "Conversion of record type 0x%x not implemented.\n", lpMetaRecord->rdFunction );
2215             break;
2216           }
2217        }
2218
2219        /* Move to the next record */
2220        (char*)lpbBuffer += ((LPMETARECORD)lpbBuffer)->rdSize * 2; /* FIXME: Seem to be doing this in metafile.c */
2221
2222 #undef ReAllocAndAdjustPointers
2223      }
2224
2225      /* We know the last of the header information now */
2226      ((LPENHMETAHEADER)lpNewEnhMetaFileBuffer)->nBytes = uNewEnhMetaFileBufferSize;
2227
2228      /* Create the enhanced metafile */
2229      hMf = SetEnhMetaFileBits( uNewEnhMetaFileBufferSize, (const BYTE*)lpNewEnhMetaFileBuffer );
2230
2231      if( !hMf )
2232        ERR( "Problem creating metafile. Did the conversion fail somewhere?\n" );
2233
2234      return hMf;
2235
2236 error:
2237      /* Free the data associated with our copy since it's been copied */
2238      HeapFree( GetProcessHeap(), 0, lpNewEnhMetaFileBuffer );
2239
2240      return 0;
2241 }