Fixed invalid window refcount handling in RDW_Paint().
[wine] / objects / enhmetafile.c
1 /*
2  * Enhanced metafile functions
3  * Copyright 1998 Douglas Ridgway
4  *           1999 Huw D M Davies 
5  */ 
6
7 #include <string.h>
8 #include <assert.h>
9 #include "winbase.h"
10 #include "wingdi.h"
11 #include "wine/winestring.h"
12 #include "winerror.h"
13 #include "enhmetafile.h"
14 #include "debug.h"
15 #include "heap.h"
16
17 DEFAULT_DEBUG_CHANNEL(enhmetafile)
18
19 /****************************************************************************
20  *          EMF_Create_HENHMETAFILE
21  */
22 HENHMETAFILE EMF_Create_HENHMETAFILE(ENHMETAHEADER *emh, HFILE hFile, HANDLE
23                                      hMapping )
24 {
25     HENHMETAFILE hmf = GDI_AllocObject( sizeof(ENHMETAFILEOBJ),
26                                         ENHMETAFILE_MAGIC );
27     ENHMETAFILEOBJ *metaObj = (ENHMETAFILEOBJ *)GDI_HEAP_LOCK( hmf );
28     metaObj->emh = emh;
29     metaObj->hFile = hFile;
30     metaObj->hMapping = hMapping;
31     GDI_HEAP_UNLOCK( hmf );
32     return hmf;
33 }
34
35 /****************************************************************************
36  *          EMF_Delete_HENHMETAFILE
37  */
38 static BOOL EMF_Delete_HENHMETAFILE( HENHMETAFILE hmf )
39 {
40     ENHMETAFILEOBJ *metaObj = (ENHMETAFILEOBJ *)GDI_GetObjPtr( hmf,
41                                                            ENHMETAFILE_MAGIC );
42     if(!metaObj) return FALSE;
43     if(metaObj->hMapping) {
44         UnmapViewOfFile( metaObj->emh );
45         CloseHandle( metaObj->hMapping );
46         CloseHandle( metaObj->hFile );
47     } else
48         HeapFree( SystemHeap, 0, metaObj->emh );
49     return GDI_FreeObject( hmf );
50 }
51
52 /******************************************************************
53  *         EMF_GetEnhMetaHeader
54  *
55  * Returns ptr to ENHMETAHEADER associated with HENHMETAFILE
56  * Should be followed by call to EMF_ReleaseEnhMetaHeader
57  */
58 static ENHMETAHEADER *EMF_GetEnhMetaHeader( HENHMETAFILE hmf )
59 {
60     ENHMETAFILEOBJ *metaObj = (ENHMETAFILEOBJ *)GDI_GetObjPtr( hmf,
61                                                            ENHMETAFILE_MAGIC );
62     TRACE(enhmetafile, "hmf %04x -> enhmetaObj %p\n", hmf, metaObj);
63     return metaObj->emh;
64 }
65
66 /******************************************************************
67  *         EMF_ReleaseEnhMetaHeader
68  *
69  * Releases ENHMETAHEADER associated with HENHMETAFILE
70  */
71 static BOOL EMF_ReleaseEnhMetaHeader( HENHMETAFILE hmf )
72 {
73     return GDI_HEAP_UNLOCK( hmf );
74 }
75
76 /*****************************************************************************
77  *         EMF_GetEnhMetaFile
78  *
79  */
80 static HENHMETAFILE EMF_GetEnhMetaFile( HFILE hFile )
81 {
82     ENHMETAHEADER *emh;
83     HANDLE hMapping;
84     
85     hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
86     emh = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 );
87
88     if (emh->iType != EMR_HEADER || emh->dSignature != ENHMETA_SIGNATURE) {
89         WARN(enhmetafile, "Invalid emf header type 0x%08lx sig 0x%08lx.\n",
90              emh->iType, emh->dSignature);
91         UnmapViewOfFile( emh );
92         CloseHandle( hMapping );
93         return 0;
94     }
95     return EMF_Create_HENHMETAFILE( emh, hFile, hMapping );
96 }
97
98
99 /*****************************************************************************
100  *          GetEnhMetaFileA (GDI32.174)
101  *
102  *
103  */
104 HENHMETAFILE WINAPI GetEnhMetaFileA( 
105              LPCSTR lpszMetaFile  /* filename of enhanced metafile */
106     )
107 {
108     HENHMETAFILE hmf;
109     HFILE hFile;
110
111     hFile = CreateFileA(lpszMetaFile, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
112     if (hFile == INVALID_HANDLE_VALUE) {
113         WARN(enhmetafile,"could not open %s\n", lpszMetaFile);
114         return 0;
115     }
116     hmf = EMF_GetEnhMetaFile( hFile );
117     if(!hmf)
118         CloseHandle( hFile );
119     return hmf;
120 }
121
122 /*****************************************************************************
123  *          GetEnhMetaFile32W  (GDI32.180)
124  */
125 HENHMETAFILE WINAPI GetEnhMetaFileW(
126              LPCWSTR lpszMetaFile)  /* filename of enhanced metafile */ 
127 {
128     HENHMETAFILE hmf;
129     HFILE hFile;
130
131     hFile = CreateFileW(lpszMetaFile, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
132     if (hFile == INVALID_HANDLE_VALUE) {
133         WARN(enhmetafile,"could not open %s\n", debugstr_w(lpszMetaFile));
134         return 0;
135     }
136     hmf = EMF_GetEnhMetaFile( hFile );
137     if(!hmf)
138         CloseHandle( hFile );
139     return hmf;
140 }
141
142 /*****************************************************************************
143  *        GetEnhMetaFileHeader  (GDI32.178)
144  *
145  *  If _buf_ is NULL, returns the size of buffer required.
146  *  Otherwise, copy up to _bufsize_ bytes of enhanced metafile header into 
147  *  _buf.
148  */
149 UINT WINAPI GetEnhMetaFileHeader( 
150        HENHMETAFILE hmf, /* enhanced metafile */
151        UINT bufsize,     /* size of buffer */
152        LPENHMETAHEADER buf /* buffer */ 
153     )
154 {
155     LPENHMETAHEADER emh;
156
157     if (!buf) return sizeof(ENHMETAHEADER);
158     emh = EMF_GetEnhMetaHeader(hmf);
159     memmove(buf, emh, MIN(sizeof(ENHMETAHEADER), bufsize));
160     EMF_ReleaseEnhMetaHeader(hmf);
161     return MIN(sizeof(ENHMETAHEADER), bufsize);
162 }
163
164
165 /*****************************************************************************
166  *          GetEnhMetaFileDescription32A  (GDI32.176)
167  */
168 UINT WINAPI GetEnhMetaFileDescriptionA( 
169        HENHMETAFILE hmf, /* enhanced metafile */
170        UINT size, /* size of buf */ 
171        LPSTR buf /* buffer to receive description */
172     )
173 {
174      LPENHMETAHEADER emh = EMF_GetEnhMetaHeader(hmf);
175      INT first;
176  
177      if(emh->nDescription == 0 || emh->offDescription == 0) {
178          EMF_ReleaseEnhMetaHeader(hmf);
179         return 0;
180      }
181      if (!buf || !size ) {
182          EMF_ReleaseEnhMetaHeader(hmf);
183         return emh->nDescription;
184      }
185  
186      first = lstrlenW( (WCHAR *) ((char *) emh + emh->offDescription));
187  
188      lstrcpynWtoA(buf, (WCHAR *) ((char *) emh + emh->offDescription), size);
189      buf += first + 1;
190      lstrcpynWtoA(buf, (WCHAR *) ((char *) emh + emh->offDescription+2*(first+1)),
191                  size - first - 1);
192  
193      EMF_ReleaseEnhMetaHeader(hmf);
194      return MIN(size, emh->nDescription);
195 }
196
197 /*****************************************************************************
198  *          GetEnhMetaFileDescription32W  (GDI32.177)
199  *
200  *  Copies the description string of an enhanced metafile into a buffer 
201  *  _buf_.
202  *
203  *  If _buf_ is NULL, returns size of _buf_ required. Otherwise, returns
204  *  number of characters copied.
205  */
206 UINT WINAPI GetEnhMetaFileDescriptionW( 
207        HENHMETAFILE hmf, /* enhanced metafile */
208        UINT size, /* size of buf */ 
209        LPWSTR buf /* buffer to receive description */
210     )
211 {
212      LPENHMETAHEADER emh = EMF_GetEnhMetaHeader(hmf);
213  
214      if(emh->nDescription == 0 || emh->offDescription == 0) {
215          EMF_ReleaseEnhMetaHeader(hmf);
216         return 0;
217      }
218      if (!buf || !size ) {
219          EMF_ReleaseEnhMetaHeader(hmf);
220         return emh->nDescription;
221      }
222  
223      memmove(buf, (char *) emh + emh->offDescription, 
224             MIN(size,emh->nDescription));
225      EMF_ReleaseEnhMetaHeader(hmf);
226      return MIN(size, emh->nDescription);
227 }
228
229 /****************************************************************************
230  *    SetEnhMetaFileBits (GDI32.315)
231  *
232  *  Creates an enhanced metafile by copying _bufsize_ bytes from _buf_.
233  */
234 HENHMETAFILE WINAPI SetEnhMetaFileBits(UINT bufsize, const BYTE *buf)
235 {
236     ENHMETAHEADER *emh = HeapAlloc( SystemHeap, 0, bufsize );
237     memmove(emh, buf, bufsize);
238     return EMF_Create_HENHMETAFILE( emh, 0, 0 );
239 }
240
241 /*****************************************************************************
242  *  GetEnhMetaFileBits (GDI32.175)
243  *
244  */
245 UINT WINAPI GetEnhMetaFileBits(
246     HENHMETAFILE hmf, 
247     UINT bufsize, 
248     LPBYTE buf  
249 ) {
250   return 0;
251 }
252
253 /*****************************************************************************
254  *           PlayEnhMetaFileRecord  (GDI32.264)
255  *
256  *  Render a single enhanced metafile record in the device context hdc.
257  *
258  *  RETURNS
259  *    TRUE on success, FALSE on error.
260  *  BUGS
261  *    Many unimplemented records.
262  */
263 BOOL WINAPI PlayEnhMetaFileRecord( 
264      HDC hdc, /* device context in which to render EMF record */
265      LPHANDLETABLE handletable, /* array of handles to be used in rendering record */
266      const ENHMETARECORD *mr, /* EMF record to render */
267      UINT handles  /* size of handle array */
268      ) 
269 {
270   int type;
271   TRACE(enhmetafile, 
272         "hdc = %08x, handletable = %p, record = %p, numHandles = %d\n", 
273           hdc, handletable, mr, handles);
274   if (!mr) return FALSE;
275
276   type = mr->iType;
277
278   TRACE(enhmetafile, " type=%d\n", type);
279   switch(type) 
280     {
281     case EMR_HEADER:
282       {
283         /* ENHMETAHEADER *h = (LPENHMETAHEADER) mr; */
284         break;
285       }
286     case EMR_EOF:
287       break;
288     case EMR_GDICOMMENT:
289       /* application defined and processed */
290       break;
291     case EMR_SETMAPMODE:
292       {
293         DWORD mode = mr->dParm[0];
294         SetMapMode(hdc, mode);
295         break;
296       }
297     case EMR_SETBKMODE:
298       {
299         DWORD mode = mr->dParm[0];
300         SetBkMode(hdc, mode);
301         break;
302       }
303     case EMR_SETBKCOLOR:
304       {
305         DWORD mode = mr->dParm[0];
306         SetBkColor(hdc, mode);
307         break;
308       }
309     case EMR_SETPOLYFILLMODE:
310       {
311         DWORD mode = mr->dParm[0];
312         SetPolyFillMode(hdc, mode);
313         break;
314       }
315     case EMR_SETROP2:
316       {
317         DWORD mode = mr->dParm[0];
318         SetROP2(hdc, mode);
319         break;
320       }
321     case EMR_SETSTRETCHBLTMODE:
322       {
323         DWORD mode = mr->dParm[0];
324         SetStretchBltMode(hdc, mode);
325         break;
326       }
327     case EMR_SETTEXTALIGN:
328       {
329         DWORD align = mr->dParm[0];
330         SetTextAlign(hdc, align);
331         break;
332       }
333     case EMR_SETTEXTCOLOR:
334       {
335         DWORD color = mr->dParm[0];
336         SetTextColor(hdc, color);
337         break;
338       }
339     case EMR_SAVEDC:
340       {
341         SaveDC(hdc);
342         break;
343       }
344     case EMR_RESTOREDC:
345       {
346         RestoreDC(hdc, mr->dParm[0]);
347         break;
348       }
349     case EMR_INTERSECTCLIPRECT:
350       {
351         INT left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
352               bottom = mr->dParm[3];
353         IntersectClipRect(hdc, left, top, right, bottom);
354         break;
355       }
356     case EMR_SELECTOBJECT:
357       {
358         DWORD obj = mr->dParm[0];
359         SelectObject(hdc, (handletable->objectHandle)[obj]);
360         break;
361       }
362     case EMR_DELETEOBJECT:
363       {
364         DWORD obj = mr->dParm[0];
365         DeleteObject( (handletable->objectHandle)[obj]);
366         (handletable->objectHandle)[obj] = 0;
367         break;
368       }
369     case EMR_SETWINDOWORGEX:
370       {
371         DWORD x = mr->dParm[0], y = mr->dParm[1];
372         SetWindowOrgEx(hdc, x, y, NULL);
373         break;
374       }
375     case EMR_SETWINDOWEXTEX:
376       {
377         DWORD x = mr->dParm[0], y = mr->dParm[1];
378         SetWindowExtEx(hdc, x, y, NULL);
379         break;
380       }
381     case EMR_SETVIEWPORTORGEX:
382       {
383         DWORD x = mr->dParm[0], y = mr->dParm[1];
384         SetViewportOrgEx(hdc, x, y, NULL);
385         break;
386       }
387     case EMR_SETVIEWPORTEXTEX:
388       {
389         DWORD x = mr->dParm[0], y = mr->dParm[1];
390         SetViewportExtEx(hdc, x, y, NULL);
391         break;
392       }
393     case EMR_CREATEPEN:
394       {
395         DWORD obj = mr->dParm[0];
396         (handletable->objectHandle)[obj] = 
397           CreatePenIndirect((LOGPEN *) &(mr->dParm[1]));
398         break;
399       }
400     case EMR_EXTCREATEPEN:
401       {
402         DWORD obj = mr->dParm[0];
403         DWORD style = mr->dParm[1], brush = mr->dParm[2];
404         LOGBRUSH *b = (LOGBRUSH *) &mr->dParm[3];
405         FIXME(enhmetafile, "Some ExtCreatePen args not handled\n");
406         (handletable->objectHandle)[obj] = 
407           ExtCreatePen(style, brush, b, 0, NULL);
408         break;
409       }
410     case EMR_CREATEBRUSHINDIRECT:
411       {
412         DWORD obj = mr->dParm[0];
413         (handletable->objectHandle)[obj] = 
414           CreateBrushIndirect((LOGBRUSH *) &(mr->dParm[1]));
415         break;
416       }
417     case EMR_EXTCREATEFONTINDIRECTW:
418         {
419         DWORD obj = mr->dParm[0];
420         (handletable->objectHandle)[obj] = 
421           CreateFontIndirectW((LOGFONTW *) &(mr->dParm[1]));
422         break;
423         }
424     case EMR_MOVETOEX:
425       {
426         DWORD x = mr->dParm[0], y = mr->dParm[1];
427         MoveToEx(hdc, x, y, NULL);
428         break;
429       }
430     case EMR_LINETO:
431       {
432         DWORD x = mr->dParm[0], y = mr->dParm[1];
433         LineTo(hdc, x, y);
434         break;
435       }
436     case EMR_RECTANGLE:
437       {
438         INT left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
439               bottom = mr->dParm[3];
440         Rectangle(hdc, left, top, right, bottom);
441         break;
442       }
443     case EMR_ELLIPSE:
444       {
445         INT left = mr->dParm[0], top = mr->dParm[1], right = mr->dParm[2],
446               bottom = mr->dParm[3];
447         Ellipse(hdc, left, top, right, bottom);
448         break;
449       }
450     case EMR_POLYGON16:
451       {
452         /* 0-3 : a bounding rectangle? */
453         INT count = mr->dParm[4];
454         FIXME(enhmetafile, "Some Polygon16 args not handled\n");
455         Polygon16(hdc, (POINT16 *)&mr->dParm[5], count);
456         break;
457       }
458     case EMR_POLYLINE16:
459       {
460         /* 0-3 : a bounding rectangle? */
461         INT count = mr->dParm[4];
462         FIXME(enhmetafile, "Some Polyline16 args not handled\n");
463         Polyline16(hdc, (POINT16 *)&mr->dParm[5], count);
464         break;
465       }
466
467 #if 0
468     case EMR_POLYPOLYGON16:
469       {
470         INT polygons = mr->dParm[z];
471         LPPOINT16 pts = (LPPOINT16) &mr->dParm[x];
472         LPINT16 counts = (LPINT16) &mr->dParm[y];
473         PolyPolygon16(hdc, pts, counts, polygons);
474         break;
475       }
476 #endif
477     case EMR_STRETCHDIBITS:
478       {
479         LONG xDest = mr->dParm[4];
480         LONG yDest = mr->dParm[5];
481         LONG xSrc = mr->dParm[6];
482         LONG ySrc = mr->dParm[7];
483         LONG cxSrc = mr->dParm[8];
484         LONG cySrc = mr->dParm[9];
485         DWORD offBmiSrc = mr->dParm[10];
486         DWORD offBitsSrc = mr->dParm[12];
487         DWORD iUsageSrc = mr->dParm[14];
488         DWORD dwRop = mr->dParm[15];
489         LONG cxDest = mr->dParm[16];
490         LONG cyDest = mr->dParm[17];
491
492         StretchDIBits(hdc,xDest,yDest,cxDest,cyDest,
493                             xSrc,ySrc,cxSrc,cySrc,
494                             ((char *)mr)+offBitsSrc,
495                             (const BITMAPINFO *)(((char *)mr)+offBmiSrc),
496                             iUsageSrc,dwRop);
497         break;
498     }
499     case EMR_EXTTEXTOUTW:
500       {
501         /* 0-3: ??? */
502         DWORD flags = mr->dParm[4];
503         /* 5, 6: ??? */
504         DWORD x = mr->dParm[7], y = mr->dParm[8];
505         DWORD count = mr->dParm[9];
506         /* 10-16: ??? */
507         LPWSTR str = (LPWSTR)& mr->dParm[17];
508         /* trailing info: dx array? */
509         FIXME(enhmetafile, "Many ExtTextOut args not handled\n");
510         ExtTextOutW(hdc, x, y, flags, /* lpRect */ NULL, 
511                       str, count, /* lpDx */ NULL); 
512         break;
513       }
514
515     default:
516       FIXME(enhmetafile, "type %d is unimplemented\n", type);
517       /*  SetLastError(E_NOTIMPL); */
518       break;
519     }
520   return TRUE;
521 }
522
523
524 /*****************************************************************************
525  *
526  *        EnumEnhMetaFile32  (GDI32.79)
527  *
528  *  Walk an enhanced metafile, calling a user-specified function _EnhMetaFunc_
529  *  for each
530  *  record. Returns when either every record has been used or 
531  *  when _EnhMetaFunc_ returns FALSE.
532  *
533  *
534  * RETURNS
535  *  TRUE if every record is used, FALSE if any invocation of _EnhMetaFunc_
536  *  returns FALSE.
537  *
538  * BUGS
539  *   Ignores rect.
540  */
541 BOOL WINAPI EnumEnhMetaFile( 
542      HDC hdc, /* device context to pass to _EnhMetaFunc_ */
543      HENHMETAFILE hmf, /* EMF to walk */
544      ENHMFENUMPROC callback, /* callback function */ 
545      LPVOID data, /* optional data for callback function */
546      const RECT *rect  /* bounding rectangle for rendered metafile */
547     )
548 {
549     BOOL ret = TRUE;
550     LPENHMETARECORD p = (LPENHMETARECORD) EMF_GetEnhMetaHeader(hmf);
551     INT count = ((LPENHMETAHEADER) p)->nHandles;
552     HANDLETABLE *ht = HeapAlloc( GetProcessHeap(), 0, 
553                                  sizeof(HANDLETABLE)*count);
554     ht->objectHandle[0] = hmf;
555     while (ret) {
556         ret = (*callback)(hdc, ht, p, count, data); 
557         if (p->iType == EMR_EOF) break;
558         p = (LPENHMETARECORD) ((char *) p + p->nSize);
559     }
560     HeapFree( GetProcessHeap(), 0, ht);
561     EMF_ReleaseEnhMetaHeader(hmf);
562     return ret;
563 }
564
565
566 /**************************************************************************
567  *    PlayEnhMetaFile  (GDI32.263)
568  *
569  *    Renders an enhanced metafile into a specified rectangle *lpRect
570  *    in device context hdc.
571  *
572  * BUGS
573  *    Almost entirely unimplemented
574  *
575  */
576 BOOL WINAPI PlayEnhMetaFile( 
577        HDC hdc, /* DC to render into */
578        HENHMETAFILE hmf, /* metafile to render */
579        const RECT *lpRect  /* rectangle to place metafile inside */
580       )
581 {
582     LPENHMETARECORD p = (LPENHMETARECORD) EMF_GetEnhMetaHeader(hmf);
583     INT count = ((LPENHMETAHEADER) p)->nHandles;
584     HANDLETABLE *ht = HeapAlloc( GetProcessHeap(), 0, 
585                                  sizeof(HANDLETABLE) * count);
586     BOOL ret = FALSE;
587     INT savedMode = 0;
588     if (lpRect) {
589         LPENHMETAHEADER h = (LPENHMETAHEADER) p;
590         FLOAT xscale = (h->rclBounds.right - h->rclBounds.left) /
591           (lpRect->right - lpRect->left);
592         FLOAT yscale = (h->rclBounds.bottom - h->rclBounds.top) /
593           (lpRect->bottom - lpRect->top);
594         XFORM xform;
595         xform.eM11 = xscale;
596         xform.eM12 = 0;
597         xform.eM21 = 0;
598         xform.eM22 = yscale;
599         xform.eDx = lpRect->left;
600         xform.eDy = lpRect->top; 
601         FIXME(enhmetafile, "play into rect doesn't work\n");
602         savedMode = SetGraphicsMode(hdc, GM_ADVANCED);
603         if (!SetWorldTransform(hdc, &xform)) {
604             WARN(enhmetafile, "World transform failed!\n");
605         }
606     }
607
608     ht->objectHandle[0] = hmf;
609     while (1) {
610         PlayEnhMetaFileRecord(hdc, ht, p, count);
611         if (p->iType == EMR_EOF) break;
612         p = (LPENHMETARECORD) ((char *) p + p->nSize); /* casted so that arithmetic is in bytes */
613     }
614     HeapFree( GetProcessHeap(), 0, ht );
615     EMF_ReleaseEnhMetaHeader(hmf);
616     if (savedMode) SetGraphicsMode(hdc, savedMode);
617     ret = TRUE; /* FIXME: calculate a more accurate return value */
618     return ret;
619 }
620
621 /*****************************************************************************
622  *  DeleteEnhMetaFile (GDI32.68)
623  *
624  *  Deletes an enhanced metafile and frees the associated storage.
625  */
626 BOOL WINAPI DeleteEnhMetaFile(HENHMETAFILE hmf)
627 {
628     return EMF_Delete_HENHMETAFILE( hmf );
629 }
630
631 /*****************************************************************************
632  *  CopyEnhMetaFileA (GDI32.21)  Duplicate an enhanced metafile
633  *
634  *   
635  */
636 HENHMETAFILE WINAPI CopyEnhMetaFileA(
637     HENHMETAFILE hmfSrc, 
638     LPCSTR file)
639 {
640     ENHMETAHEADER *emrSrc = EMF_GetEnhMetaHeader( hmfSrc ), *emrDst;
641     HENHMETAFILE hmfDst;
642
643     if (!file) {
644         emrDst = HeapAlloc( SystemHeap, 0, emrSrc->nBytes );
645         memcpy( emrDst, emrSrc, emrSrc->nBytes );
646         hmfDst = EMF_Create_HENHMETAFILE( emrDst, 0, 0 );
647     } else {
648         HFILE hFile;
649         hFile = CreateFileA( file, GENERIC_WRITE | GENERIC_READ, 0, NULL,
650                              CREATE_ALWAYS, 0, -1);
651         WriteFile( hFile, emrSrc, emrSrc->nBytes, 0, 0);
652         hmfDst = EMF_GetEnhMetaFile( hFile );
653     }
654     EMF_ReleaseEnhMetaHeader( hmfSrc );
655     return hmfDst;
656 }
657
658
659 /*****************************************************************************
660  *  GetEnhMetaFilePaletteEntries (GDI32.179)  
661  * 
662  *  Copy the palette and report size  
663  */
664
665 UINT WINAPI GetEnhMetaFilePaletteEntries(HENHMETAFILE hemf,
666                                              UINT cEntries,
667                                              LPPALETTEENTRY lppe)
668 {
669     return 0;
670 }
671
672
673 /******************************************************************
674  *         SetWinMetaFileBits   (GDI32.343)
675  *      
676  *         Translate from old style to new style.
677  */
678
679 HENHMETAFILE WINAPI SetWinMetaFileBits(UINT cbBuffer,
680                                            CONST BYTE *lpbBuffer,
681                                            HDC hdcRef,
682                                            CONST METAFILEPICT *lpmfp
683                                            ) 
684 {
685      FIXME(enhmetafile,"Stub\n");
686      return 0;
687 }
688
689
690
691