Fixed error handling in DGA_IDirectDraw2Impl_GetCaps().
[wine] / graphics / metafiledrv / init.c
1 /*
2  * Metafile driver initialisation functions
3  *
4  * Copyright 1996 Alexandre Julliard
5  */
6
7 #include "windef.h"
8 #include "wine/winbase16.h"
9 #include "dc.h"
10 #include "heap.h"
11 #include "global.h"
12 #include "metafile.h"
13 #include "metafiledrv.h"
14 #include "debug.h"
15
16 DEFAULT_DEBUG_CHANNEL(metafile)
17
18 #include <string.h>
19
20 static const DC_FUNCTIONS MFDRV_Funcs =
21 {
22     NULL,                            /* pAbortDoc */
23     MFDRV_Arc,                       /* pArc */
24     MFDRV_BitBlt,                    /* pBitBlt */
25     NULL,                            /* pBitmapBits */  
26     MFDRV_Chord,                     /* pChord */
27     NULL,                            /* pCreateBitmap */
28     NULL, /* no implementation */    /* pCreateDC */
29     NULL,                            /* pCreateDIBSection */
30     NULL,                            /* pCreateDIBSection16 */
31     NULL, /* no implementation */    /* pDeleteDC */
32     NULL,                            /* pDeleteObject */
33     NULL,                            /* pDeviceCapabilities */
34     MFDRV_Ellipse,                   /* pEllipse */
35     NULL,                            /* pEndDoc */
36     NULL,                            /* pEndPage */
37     NULL,                            /* pEnumDeviceFonts */
38     NULL,                            /* pEscape */
39     MFDRV_ExcludeClipRect,           /* pExcludeClipRect */
40     NULL,                            /* pExtDeviceMode */
41     MFDRV_ExtFloodFill,              /* pExtFloodFill */
42     MFDRV_ExtTextOut,                /* pExtTextOut */
43     MFDRV_FillRgn,                   /* pFillRgn */
44     MFDRV_FrameRgn,                  /* pFrameRgn */
45     NULL,                            /* pGetCharWidth */
46     NULL, /* no implementation */    /* pGetPixel */
47     NULL,                            /* pGetTextExtentPoint */
48     NULL,                            /* pGetTextMetrics */
49     MFDRV_IntersectClipRect,         /* pIntersectClipRect */
50     MFDRV_InvertRgn,                 /* pInvertRgn */
51     MFDRV_LineTo,                    /* pLineTo */
52     NULL,                            /* pLoadOEMResource */
53     MFDRV_MoveToEx,                  /* pMoveToEx */
54     MFDRV_OffsetClipRgn,             /* pOffsetClipRgn */
55     MFDRV_OffsetViewportOrg,         /* pOffsetViewportOrg */
56     MFDRV_OffsetWindowOrg,           /* pOffsetWindowOrg */
57     MFDRV_PaintRgn,                  /* pPaintRgn */
58     MFDRV_PatBlt,                    /* pPatBlt */
59     MFDRV_Pie,                       /* pPie */
60     MFDRV_PolyPolygon,               /* pPolyPolygon */
61     NULL,                            /* pPolyPolyline */
62     MFDRV_Polygon,                   /* pPolygon */
63     MFDRV_Polyline,                  /* pPolyline */
64     NULL,                            /* pPolyBezier */
65     NULL,                            /* pRealizePalette */
66     MFDRV_Rectangle,                 /* pRectangle */
67     MFDRV_RestoreDC,                 /* pRestoreDC */
68     MFDRV_RoundRect,                 /* pRoundRect */
69     MFDRV_SaveDC,                    /* pSaveDC */
70     MFDRV_ScaleViewportExt,          /* pScaleViewportExt */
71     MFDRV_ScaleWindowExt,            /* pScaleWindowExt */
72     NULL,                            /* pSelectClipRgn */
73     MFDRV_SelectObject,              /* pSelectObject */
74     NULL,                            /* pSelectPalette */
75     MFDRV_SetBkColor,                /* pSetBkColor */
76     MFDRV_SetBkMode,                 /* pSetBkMode */
77     NULL,                            /* pSetDeviceClipping */
78     MFDRV_SetDIBitsToDevice,         /* pSetDIBitsToDevice */
79     MFDRV_SetMapMode,                /* pSetMapMode */
80     MFDRV_SetMapperFlags,            /* pSetMapperFlags */
81     MFDRV_SetPixel,                  /* pSetPixel */
82     MFDRV_SetPolyFillMode,           /* pSetPolyFillMode */
83     MFDRV_SetROP2,                   /* pSetROP2 */
84     MFDRV_SetRelAbs,                 /* pSetRelAbs */
85     MFDRV_SetStretchBltMode,         /* pSetStretchBltMode */
86     MFDRV_SetTextAlign,              /* pSetTextAlign */
87     MFDRV_SetTextCharacterExtra,     /* pSetTextCharacterExtra */
88     MFDRV_SetTextColor,              /* pSetTextColor */
89     MFDRV_SetTextJustification,      /* pSetTextJustification */
90     MFDRV_SetViewportExt,            /* pSetViewportExt */
91     MFDRV_SetViewportOrg,            /* pSetViewportOrg */
92     MFDRV_SetWindowExt,              /* pSetWindowExt */
93     MFDRV_SetWindowOrg,              /* pSetWindowOrg */
94     NULL,                            /* pStartDoc */
95     NULL,                            /* pStartPage */
96     MFDRV_StretchBlt,                /* pStretchBlt */
97     MFDRV_StretchDIBits              /* pStretchDIBits */
98 };
99
100
101
102 /**********************************************************************
103  *           MFDRV_AllocMetaFile
104  */
105 static DC *MFDRV_AllocMetaFile(void)
106 {
107     DC *dc;
108     METAFILEDRV_PDEVICE *physDev;
109     
110     if (!(dc = DC_AllocDC( &MFDRV_Funcs ))) return NULL;
111     dc->header.wMagic = METAFILE_DC_MAGIC;
112
113     physDev = (METAFILEDRV_PDEVICE *)HeapAlloc(SystemHeap,0,sizeof(*physDev));
114     if (!physDev)
115     {
116         GDI_HEAP_FREE( dc->hSelf );
117         return NULL;
118     }
119     dc->physDev = physDev;
120
121     if (!(physDev->mh = HeapAlloc( SystemHeap, 0, sizeof(*physDev->mh) )))
122     {
123         HeapFree( SystemHeap, 0, physDev );
124         GDI_HEAP_FREE( dc->hSelf );
125         return NULL;
126     }
127
128     physDev->nextHandle = 0;
129     physDev->hFile = 0;
130
131     physDev->mh->mtHeaderSize   = sizeof(METAHEADER) / sizeof(WORD);
132     physDev->mh->mtVersion      = 0x0300;
133     physDev->mh->mtSize         = physDev->mh->mtHeaderSize;
134     physDev->mh->mtNoObjects    = 0;
135     physDev->mh->mtMaxRecord    = 0;
136     physDev->mh->mtNoParameters = 0;
137
138     return dc;
139 }
140
141
142 /**********************************************************************
143  *           MFDRV_DeleteDC
144  */
145 static BOOL MFDRV_DeleteDC( DC *dc )
146 {
147     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
148     
149     if (physDev->mh) HeapFree( SystemHeap, 0, physDev->mh );
150     HeapFree( SystemHeap, 0, physDev );
151     dc->physDev = NULL;
152     GDI_FreeObject(dc->hSelf);
153     return TRUE;
154 }
155
156 /**********************************************************************
157  *           CreateMetaFile16   (GDI.125)
158  *
159  *  Create a new DC and associate it with a metafile. Pass a filename
160  *  to create a disk-based metafile, NULL to create a memory metafile.
161  *
162  * RETURNS
163  *  A handle to the metafile DC if successful, NULL on failure.
164  */
165 HDC16 WINAPI CreateMetaFile16( 
166                               LPCSTR filename /* Filename of disk metafile */
167 )
168 {
169     DC *dc;
170     METAFILEDRV_PDEVICE *physDev;
171     HFILE hFile;
172
173     TRACE(metafile, "'%s'\n", filename );
174
175     if (!(dc = MFDRV_AllocMetaFile())) return 0;
176     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
177     
178     if (filename)  /* disk based metafile */
179     {
180         physDev->mh->mtType = METAFILE_DISK;
181         if ((hFile = CreateFileA(filename, GENERIC_WRITE, 0, NULL,
182                                 CREATE_ALWAYS, 0, -1)) == HFILE_ERROR) {
183             MFDRV_DeleteDC( dc );
184             return 0;
185         }
186         if (!WriteFile( hFile, (LPSTR)physDev->mh, sizeof(*physDev->mh), NULL,
187                         NULL )) {
188             MFDRV_DeleteDC( dc );
189             return 0;
190         }
191         physDev->hFile = hFile;
192
193         /* Grow METAHEADER to include filename */
194         physDev->mh = MF_CreateMetaHeaderDisk(physDev->mh, filename);
195     }
196     else  /* memory based metafile */
197         physDev->mh->mtType = METAFILE_MEMORY;
198         
199     TRACE(metafile, "returning %04x\n", dc->hSelf);
200     return dc->hSelf;
201 }
202
203 /**********************************************************************
204  *           CreateMetaFileA   (GDI32.51)
205  */
206 HDC WINAPI CreateMetaFileA( 
207                               LPCSTR filename /* Filename of disk metafile */
208 )
209 {
210   return CreateMetaFile16( filename );
211 }
212
213 /**********************************************************************
214  *          CreateMetaFileW   (GDI32.52)
215  */
216 HDC WINAPI CreateMetaFileW(LPCWSTR filename)
217 {
218     LPSTR filenameA;
219     HDC hReturnDC;
220
221     filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
222
223     hReturnDC = CreateMetaFileA(filenameA);
224
225     HeapFree( GetProcessHeap(), 0, filenameA );
226
227     return hReturnDC;
228 }
229
230
231 /**********************************************************************
232  *          MFDRV_CloseMetaFile
233  */
234 static DC *MFDRV_CloseMetaFile( HDC hdc ) 
235 {
236     DC *dc;
237     METAFILEDRV_PDEVICE *physDev;
238     
239     TRACE(metafile, "(%04x)\n", hdc );
240
241     if (!(dc = (DC *) GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC ))) return 0;
242     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
243
244     /* Construct the end of metafile record - this is documented
245      * in SDK Knowledgebase Q99334.
246      */
247
248     if (!MFDRV_MetaParam0(dc, META_EOF))
249     {
250         MFDRV_DeleteDC( dc );
251         return 0;
252     }   
253
254     if (physDev->mh->mtType == METAFILE_DISK)  /* disk based metafile */
255     {
256         if (SetFilePointer(physDev->hFile, 0, NULL, FILE_BEGIN) != 0) {
257             MFDRV_DeleteDC( dc );
258             return 0;
259         }
260
261         physDev->mh->mtType = METAFILE_MEMORY; /* This is what windows does */
262         if (!WriteFile(physDev->hFile, (LPSTR)physDev->mh,
263                        sizeof(*physDev->mh), NULL, NULL)) {
264             MFDRV_DeleteDC( dc );
265             return 0;
266         }
267         CloseHandle(physDev->hFile);
268         physDev->mh->mtType = METAFILE_DISK;
269     }
270
271     return dc;
272 }
273
274 /******************************************************************
275  *           CloseMetaFile16   (GDI.126)
276  */
277 HMETAFILE16 WINAPI CloseMetaFile16( 
278                                    HDC16 hdc /* Metafile DC to close */
279 )
280 {
281     HMETAFILE16 hmf;
282     METAFILEDRV_PDEVICE *physDev;
283     DC *dc = MFDRV_CloseMetaFile(hdc);
284     if (!dc) return 0;
285     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
286
287     /* Now allocate a global handle for the metafile */
288
289     hmf = MF_Create_HMETAFILE16( physDev->mh );
290
291     physDev->mh = NULL;  /* So it won't be deleted */
292     MFDRV_DeleteDC( dc );
293     return hmf;
294 }
295
296 /******************************************************************
297  *           CloseMetaFile   (GDI32.17)
298  *
299  *  Stop recording graphics operations in metafile associated with
300  *  hdc and retrieve metafile.
301  *
302  * RETURNS
303  *  Handle of newly created metafile on success, NULL on failure.
304  */
305 HMETAFILE WINAPI CloseMetaFile( 
306                                    HDC hdc /* Metafile DC to close */
307 )
308 {
309     HMETAFILE hmf;
310     METAFILEDRV_PDEVICE *physDev;
311     DC *dc = MFDRV_CloseMetaFile(hdc);
312     if (!dc) return 0;
313     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
314
315     /* Now allocate a global handle for the metafile */
316
317     hmf = MF_Create_HMETAFILE( physDev->mh );
318
319     physDev->mh = NULL;  /* So it won't be deleted */
320     MFDRV_DeleteDC( dc );
321     return hmf;
322 }
323
324
325 /******************************************************************
326  *         MFDRV_WriteRecord
327  *
328  * Warning: this function can change the pointer to the metafile header.
329  */
330 BOOL MFDRV_WriteRecord( DC *dc, METARECORD *mr, DWORD rlen)
331 {
332     DWORD len;
333     METAHEADER *mh;
334     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
335
336     switch(physDev->mh->mtType)
337     {
338     case METAFILE_MEMORY:
339         len = physDev->mh->mtSize * 2 + rlen;
340         mh = HeapReAlloc( SystemHeap, 0, physDev->mh, len );
341         if (!mh) return FALSE;
342         physDev->mh = mh;
343         memcpy((WORD *)physDev->mh + physDev->mh->mtSize, mr, rlen);
344         break;
345     case METAFILE_DISK:
346         TRACE(metafile,"Writing record to disk\n");
347         if (!WriteFile(physDev->hFile, (char *)mr, rlen, NULL, NULL))
348             return FALSE;
349         break;
350     default:
351         ERR(metafile, "Unknown metafile type %d\n", physDev->mh->mtType );
352         return FALSE;
353     }
354
355     physDev->mh->mtSize += rlen / 2;
356     physDev->mh->mtMaxRecord = MAX(physDev->mh->mtMaxRecord, rlen / 2);
357     return TRUE;
358 }
359
360
361 /******************************************************************
362  *         MFDRV_MetaParam0
363  */
364
365 BOOL MFDRV_MetaParam0(DC *dc, short func)
366 {
367     char buffer[8];
368     METARECORD *mr = (METARECORD *)&buffer;
369     
370     mr->rdSize = 3;
371     mr->rdFunction = func;
372     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
373 }
374
375
376 /******************************************************************
377  *         MFDRV_MetaParam1
378  */
379 BOOL MFDRV_MetaParam1(DC *dc, short func, short param1)
380 {
381     char buffer[8];
382     METARECORD *mr = (METARECORD *)&buffer;
383     
384     mr->rdSize = 4;
385     mr->rdFunction = func;
386     *(mr->rdParm) = param1;
387     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
388 }
389
390
391 /******************************************************************
392  *         MFDRV_MetaParam2
393  */
394 BOOL MFDRV_MetaParam2(DC *dc, short func, short param1, short param2)
395 {
396     char buffer[10];
397     METARECORD *mr = (METARECORD *)&buffer;
398     
399     mr->rdSize = 5;
400     mr->rdFunction = func;
401     *(mr->rdParm) = param2;
402     *(mr->rdParm + 1) = param1;
403     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
404 }
405
406
407 /******************************************************************
408  *         MFDRV_MetaParam4
409  */
410
411 BOOL MFDRV_MetaParam4(DC *dc, short func, short param1, short param2, 
412                       short param3, short param4)
413 {
414     char buffer[14];
415     METARECORD *mr = (METARECORD *)&buffer;
416     
417     mr->rdSize = 7;
418     mr->rdFunction = func;
419     *(mr->rdParm) = param4;
420     *(mr->rdParm + 1) = param3;
421     *(mr->rdParm + 2) = param2;
422     *(mr->rdParm + 3) = param1;
423     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
424 }
425
426
427 /******************************************************************
428  *         MFDRV_MetaParam6
429  */
430
431 BOOL MFDRV_MetaParam6(DC *dc, short func, short param1, short param2, 
432                       short param3, short param4, short param5, short param6)
433 {
434     char buffer[18];
435     METARECORD *mr = (METARECORD *)&buffer;
436     
437     mr->rdSize = 9;
438     mr->rdFunction = func;
439     *(mr->rdParm) = param6;
440     *(mr->rdParm + 1) = param5;
441     *(mr->rdParm + 2) = param4;
442     *(mr->rdParm + 3) = param3;
443     *(mr->rdParm + 4) = param2;
444     *(mr->rdParm + 5) = param1;
445     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
446 }
447
448
449 /******************************************************************
450  *         MFDRV_MetaParam8
451  */
452 BOOL MFDRV_MetaParam8(DC *dc, short func, short param1, short param2, 
453                       short param3, short param4, short param5,
454                       short param6, short param7, short param8)
455 {
456     char buffer[22];
457     METARECORD *mr = (METARECORD *)&buffer;
458     
459     mr->rdSize = 11;
460     mr->rdFunction = func;
461     *(mr->rdParm) = param8;
462     *(mr->rdParm + 1) = param7;
463     *(mr->rdParm + 2) = param6;
464     *(mr->rdParm + 3) = param5;
465     *(mr->rdParm + 4) = param4;
466     *(mr->rdParm + 5) = param3;
467     *(mr->rdParm + 6) = param2;
468     *(mr->rdParm + 7) = param1;
469     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
470 }
471
472
473 /******************************************************************
474  *         MFDRV_AddHandleDC
475  *
476  * Note: this function assumes that we never delete objects.
477  * If we do someday, we'll need to maintain a table to re-use deleted
478  * handles.
479  */
480 int MFDRV_AddHandleDC( DC *dc )
481 {
482     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
483     physDev->mh->mtNoObjects++;
484     return physDev->nextHandle++;
485 }
486
487