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