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