Use INVALID_FILE_ATTRIBUTES to test for failure of
[wine] / dlls / gdi / mfdrv / init.c
1 /*
2  * Metafile driver initialisation functions
3  *
4  * Copyright 1996 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <stdarg.h>
22 #include <string.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wine/winbase16.h"
27 #include "gdi.h"
28 #include "wownt32.h"
29 #include "mfdrv/metafiledrv.h"
30 #include "wine/debug.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
33
34 static const DC_FUNCTIONS MFDRV_Funcs =
35 {
36     NULL,                            /* pAbortDoc */
37     MFDRV_AbortPath,                 /* pAbortPath */
38     NULL,                            /* pAngleArc */
39     MFDRV_Arc,                       /* pArc */
40     NULL,                            /* pArcTo */
41     MFDRV_BeginPath,                 /* pBeginPath */
42     MFDRV_BitBlt,                    /* pBitBlt */
43     NULL,                            /* pChoosePixelFormat */
44     MFDRV_Chord,                     /* pChord */
45     MFDRV_CloseFigure,               /* pCloseFigure */
46     NULL,                            /* pCreateBitmap */
47     NULL,                            /* pCreateDC */
48     NULL,                            /* pCreateDIBSection */
49     NULL,                            /* pDeleteBitmap */
50     NULL,                            /* pDeleteDC */
51     NULL,                            /* pDescribePixelFormat */
52     NULL,                            /* pDeviceCapabilities */
53     MFDRV_Ellipse,                   /* pEllipse */
54     NULL,                            /* pEndDoc */
55     NULL,                            /* pEndPage */
56     MFDRV_EndPath,                   /* pEndPath */
57     NULL,                            /* pEnumDeviceFonts */
58     MFDRV_ExcludeClipRect,           /* pExcludeClipRect */
59     NULL,                            /* pExtDeviceMode */
60     MFDRV_ExtEscape,                 /* pExtEscape */
61     MFDRV_ExtFloodFill,              /* pExtFloodFill */
62     MFDRV_ExtSelectClipRgn,          /* pExtSelectClipRgn */
63     MFDRV_ExtTextOut,                /* pExtTextOut */
64     MFDRV_FillPath,                  /* pFillPath */
65     MFDRV_FillRgn,                   /* pFillRgn */
66     MFDRV_FlattenPath,               /* pFlattenPath */
67     MFDRV_FrameRgn,                  /* pFrameRgn */
68     NULL,                            /* pGdiComment */
69     NULL,                            /* pGetBitmapBits */
70     NULL,                            /* pGetCharWidth */
71     NULL,                            /* pGetDCOrgEx */
72     NULL,                            /* pGetDIBColorTable */
73     NULL,                            /* pGetDIBits */
74     MFDRV_GetDeviceCaps,             /* pGetDeviceCaps */
75     NULL,                            /* pGetDeviceGammaRamp */
76     NULL,                            /* pGetNearestColor */
77     NULL,                            /* pGetPixel */
78     NULL,                            /* pGetPixelFormat */
79     NULL,                            /* pGetSystemPaletteEntries */
80     NULL,                            /* pGetTextExtentPoint */
81     NULL,                            /* pGetTextMetrics */
82     MFDRV_IntersectClipRect,         /* pIntersectClipRect */
83     MFDRV_InvertRgn,                 /* pInvertRgn */
84     MFDRV_LineTo,                    /* pLineTo */
85     NULL,                            /* pModifyWorldTransform */
86     MFDRV_MoveTo,                    /* pMoveTo */
87     MFDRV_OffsetClipRgn,             /* pOffsetClipRgn */
88     MFDRV_OffsetViewportOrg,         /* pOffsetViewportOrg */
89     MFDRV_OffsetWindowOrg,           /* pOffsetWindowOrg */
90     MFDRV_PaintRgn,                  /* pPaintRgn */
91     MFDRV_PatBlt,                    /* pPatBlt */
92     MFDRV_Pie,                       /* pPie */
93     MFDRV_PolyBezier,                /* pPolyBezier */
94     MFDRV_PolyBezierTo,              /* pPolyBezierTo */
95     NULL,                            /* pPolyDraw */
96     MFDRV_PolyPolygon,               /* pPolyPolygon */
97     NULL,                            /* pPolyPolyline */
98     MFDRV_Polygon,                   /* pPolygon */
99     MFDRV_Polyline,                  /* pPolyline */
100     NULL,                            /* pPolylineTo */
101     NULL,                            /* pRealizeDefaultPalette */
102     MFDRV_RealizePalette,            /* pRealizePalette */
103     MFDRV_Rectangle,                 /* pRectangle */
104     NULL,                            /* pResetDC */
105     MFDRV_RestoreDC,                 /* pRestoreDC */
106     MFDRV_RoundRect,                 /* pRoundRect */
107     MFDRV_SaveDC,                    /* pSaveDC */
108     MFDRV_ScaleViewportExt,          /* pScaleViewportExt */
109     MFDRV_ScaleWindowExt,            /* pScaleWindowExt */
110     MFDRV_SelectBitmap,              /* pSelectBitmap */
111     MFDRV_SelectBrush,               /* pSelectBrush */
112     MFDRV_SelectClipPath,            /* pSelectClipPath */
113     MFDRV_SelectFont,                /* pSelectFont */
114     MFDRV_SelectPalette,             /* pSelectPalette */
115     MFDRV_SelectPen,                 /* pSelectPen */
116     NULL,                            /* pSetArcDirection */
117     NULL,                            /* pSetBitmapBits */
118     MFDRV_SetBkColor,                /* pSetBkColor */
119     MFDRV_SetBkMode,                 /* pSetBkMode */
120     NULL,                            /* pSetDCOrg */
121     NULL,                            /* pSetDIBColorTable */
122     NULL,                            /* pSetDIBits */
123     MFDRV_SetDIBitsToDevice,         /* pSetDIBitsToDevice */
124     NULL,                            /* pSetDeviceClipping */
125     NULL,                            /* pSetDeviceGammaRamp */
126     MFDRV_SetMapMode,                /* pSetMapMode */
127     MFDRV_SetMapperFlags,            /* pSetMapperFlags */
128     MFDRV_SetPixel,                  /* pSetPixel */
129     NULL,                            /* pSetPixelFormat */
130     MFDRV_SetPolyFillMode,           /* pSetPolyFillMode */
131     MFDRV_SetROP2,                   /* pSetROP2 */
132     MFDRV_SetRelAbs,                 /* pSetRelAbs */
133     MFDRV_SetStretchBltMode,         /* pSetStretchBltMode */
134     MFDRV_SetTextAlign,              /* pSetTextAlign */
135     MFDRV_SetTextCharacterExtra,     /* pSetTextCharacterExtra */
136     MFDRV_SetTextColor,              /* pSetTextColor */
137     MFDRV_SetTextJustification,      /* pSetTextJustification */
138     MFDRV_SetViewportExt,            /* pSetViewportExt */
139     MFDRV_SetViewportOrg,            /* pSetViewportOrg */
140     MFDRV_SetWindowExt,              /* pSetWindowExt */
141     MFDRV_SetWindowOrg,              /* pSetWindowOrg */
142     NULL,                            /* pSetWorldTransform */
143     NULL,                            /* pStartDoc */
144     NULL,                            /* pStartPage */
145     MFDRV_StretchBlt,                /* pStretchBlt */
146     MFDRV_StretchDIBits,             /* pStretchDIBits */
147     MFDRV_StrokeAndFillPath,         /* pStrokeAndFillPath */
148     MFDRV_StrokePath,                /* pStrokePath */
149     NULL,                            /* pSwapBuffers */
150     MFDRV_WidenPath                  /* pWidenPath */
151 };
152
153
154
155 /**********************************************************************
156  *           MFDRV_AllocMetaFile
157  */
158 static DC *MFDRV_AllocMetaFile(void)
159 {
160     DC *dc;
161     METAFILEDRV_PDEVICE *physDev;
162
163     if (!(dc = DC_AllocDC( &MFDRV_Funcs, METAFILE_DC_MAGIC ))) return NULL;
164
165     physDev = (METAFILEDRV_PDEVICE *)HeapAlloc(GetProcessHeap(),0,sizeof(*physDev));
166     if (!physDev)
167     {
168         GDI_FreeObject( dc->hSelf, dc );
169         return NULL;
170     }
171     dc->physDev = (PHYSDEV)physDev;
172     physDev->hdc = dc->hSelf;
173     physDev->dc = dc;
174
175     if (!(physDev->mh = HeapAlloc( GetProcessHeap(), 0, sizeof(*physDev->mh) )))
176     {
177         HeapFree( GetProcessHeap(), 0, physDev );
178         GDI_FreeObject( dc->hSelf, dc );
179         return NULL;
180     }
181
182     physDev->nextHandle = 0;
183     physDev->hFile = 0;
184
185     physDev->mh->mtHeaderSize   = sizeof(METAHEADER) / sizeof(WORD);
186     physDev->mh->mtVersion      = 0x0300;
187     physDev->mh->mtSize         = physDev->mh->mtHeaderSize;
188     physDev->mh->mtNoObjects    = 0;
189     physDev->mh->mtMaxRecord    = 0;
190     physDev->mh->mtNoParameters = 0;
191
192     return dc;
193 }
194
195
196 /**********************************************************************
197  *           MFDRV_DeleteDC
198  */
199 static BOOL MFDRV_DeleteDC( PHYSDEV dev )
200 {
201     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
202     DC *dc = physDev->dc;
203
204     if (physDev->mh) HeapFree( GetProcessHeap(), 0, physDev->mh );
205     HeapFree( GetProcessHeap(), 0, physDev );
206     dc->physDev = NULL;
207     GDI_FreeObject( dc->hSelf, dc );
208     return TRUE;
209 }
210
211
212 /**********************************************************************
213  *           CreateMetaFileA   (GDI32.@)
214  *
215  *  Create a new DC and associate it with a metafile. Pass a filename
216  *  to create a disk-based metafile, NULL to create a memory metafile.
217  *
218  * RETURNS
219  *  A handle to the metafile DC if successful, NULL on failure.
220  */
221 HDC WINAPI CreateMetaFileA( LPCSTR filename ) /* [in] Filename of disk metafile */
222 {
223     HDC ret;
224     DC *dc;
225     METAFILEDRV_PDEVICE *physDev;
226     HANDLE hFile;
227
228     TRACE("'%s'\n", filename );
229
230     if (!(dc = MFDRV_AllocMetaFile())) return 0;
231     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
232
233     if (filename)  /* disk based metafile */
234     {
235         physDev->mh->mtType = METAFILE_DISK;
236         if ((hFile = CreateFileA(filename, GENERIC_WRITE, 0, NULL,
237                                 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
238             MFDRV_DeleteDC( dc->physDev );
239             return 0;
240         }
241         if (!WriteFile( hFile, (LPSTR)physDev->mh, sizeof(*physDev->mh), NULL,
242                         NULL )) {
243             MFDRV_DeleteDC( dc->physDev );
244             return 0;
245         }
246         physDev->hFile = hFile;
247
248         /* Grow METAHEADER to include filename */
249         physDev->mh = MF_CreateMetaHeaderDisk(physDev->mh, filename);
250     }
251     else  /* memory based metafile */
252         physDev->mh->mtType = METAFILE_MEMORY;
253
254     TRACE("returning %p\n", dc->hSelf);
255     ret = dc->hSelf;
256     GDI_ReleaseObj( dc->hSelf );
257     return ret;
258 }
259
260 /**********************************************************************
261  *          CreateMetaFileW   (GDI32.@)
262  */
263 HDC WINAPI CreateMetaFileW(LPCWSTR filename)
264 {
265     LPSTR filenameA;
266     DWORD len;
267     HDC hReturnDC;
268
269     if (!filename) return CreateMetaFileA(NULL);
270
271     len = WideCharToMultiByte( CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL );
272     filenameA = HeapAlloc( GetProcessHeap(), 0, len );
273     WideCharToMultiByte( CP_ACP, 0, filename, -1, filenameA, len, NULL, NULL );
274
275     hReturnDC = CreateMetaFileA(filenameA);
276
277     HeapFree( GetProcessHeap(), 0, filenameA );
278
279     return hReturnDC;
280 }
281
282
283 /**********************************************************************
284  *          MFDRV_CloseMetaFile
285  */
286 static DC *MFDRV_CloseMetaFile( HDC hdc )
287 {
288     DC *dc;
289     METAFILEDRV_PDEVICE *physDev;
290
291     TRACE("(%p)\n", hdc );
292
293     if (!(dc = (DC *) GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC ))) return 0;
294     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
295
296     /* Construct the end of metafile record - this is documented
297      * in SDK Knowledgebase Q99334.
298      */
299
300     if (!MFDRV_MetaParam0(dc->physDev, META_EOF))
301     {
302         MFDRV_DeleteDC( dc->physDev );
303         return 0;
304     }
305
306     if (physDev->mh->mtType == METAFILE_DISK)  /* disk based metafile */
307     {
308         if (SetFilePointer(physDev->hFile, 0, NULL, FILE_BEGIN) != 0) {
309             MFDRV_DeleteDC( dc->physDev );
310             return 0;
311         }
312
313         physDev->mh->mtType = METAFILE_MEMORY; /* This is what windows does */
314         if (!WriteFile(physDev->hFile, (LPSTR)physDev->mh,
315                        sizeof(*physDev->mh), NULL, NULL)) {
316             MFDRV_DeleteDC( dc->physDev );
317             return 0;
318         }
319         CloseHandle(physDev->hFile);
320         physDev->mh->mtType = METAFILE_DISK;
321     }
322
323     return dc;
324 }
325
326 /******************************************************************
327  *           CloseMetaFile     (GDI.126)
328  */
329 HMETAFILE16 WINAPI CloseMetaFile16(
330                                    HDC16 hdc /* [in] Metafile DC to close */
331 )
332 {
333     HMETAFILE16 hmf;
334     METAFILEDRV_PDEVICE *physDev;
335     DC *dc = MFDRV_CloseMetaFile(HDC_32(hdc));
336     if (!dc) return 0;
337     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
338
339     /* Now allocate a global handle for the metafile */
340
341     hmf = MF_Create_HMETAFILE16( physDev->mh );
342
343     physDev->mh = NULL;  /* So it won't be deleted */
344     MFDRV_DeleteDC( dc->physDev );
345     return hmf;
346 }
347
348 /******************************************************************
349  *           CloseMetaFile   (GDI32.@)
350  *
351  *  Stop recording graphics operations in metafile associated with
352  *  hdc and retrieve metafile.
353  *
354  * RETURNS
355  *  Handle of newly created metafile on success, NULL on failure.
356  */
357 HMETAFILE WINAPI CloseMetaFile(
358                                    HDC hdc /* [in] Metafile DC to close */
359 )
360 {
361     HMETAFILE hmf;
362     METAFILEDRV_PDEVICE *physDev;
363     DC *dc = MFDRV_CloseMetaFile(hdc);
364     if (!dc) return 0;
365     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
366
367     /* Now allocate a global handle for the metafile */
368
369     hmf = MF_Create_HMETAFILE( physDev->mh );
370
371     physDev->mh = NULL;  /* So it won't be deleted */
372     MFDRV_DeleteDC( dc->physDev );
373     return hmf;
374 }
375
376
377 /******************************************************************
378  *         MFDRV_WriteRecord
379  *
380  * Warning: this function can change the pointer to the metafile header.
381  */
382 BOOL MFDRV_WriteRecord( PHYSDEV dev, METARECORD *mr, DWORD rlen)
383 {
384     DWORD len, size;
385     METAHEADER *mh;
386     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
387
388     switch(physDev->mh->mtType)
389     {
390     case METAFILE_MEMORY:
391         len = physDev->mh->mtSize * 2 + rlen;
392         /* reallocate memory if needed */
393         size = HeapSize( GetProcessHeap(), 0, physDev->mh );
394         if (len > size)
395         {
396             /*expand size*/
397             size += size / 2 + rlen;
398             mh = HeapReAlloc( GetProcessHeap(), 0, physDev->mh, size);
399             if (!mh) return FALSE;
400             physDev->mh = mh;
401             TRACE("Reallocated metafile: new size is %ld\n",size);
402         }
403         memcpy((WORD *)physDev->mh + physDev->mh->mtSize, mr, rlen);
404         break;
405     case METAFILE_DISK:
406         TRACE("Writing record to disk\n");
407         if (!WriteFile(physDev->hFile, (char *)mr, rlen, NULL, NULL))
408             return FALSE;
409         break;
410     default:
411         ERR("Unknown metafile type %d\n", physDev->mh->mtType );
412         return FALSE;
413     }
414
415     physDev->mh->mtSize += rlen / 2;
416     physDev->mh->mtMaxRecord = max(physDev->mh->mtMaxRecord, rlen / 2);
417     return TRUE;
418 }
419
420
421 /******************************************************************
422  *         MFDRV_MetaParam0
423  */
424
425 BOOL MFDRV_MetaParam0(PHYSDEV dev, short func)
426 {
427     char buffer[8];
428     METARECORD *mr = (METARECORD *)&buffer;
429
430     mr->rdSize = 3;
431     mr->rdFunction = func;
432     return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
433 }
434
435
436 /******************************************************************
437  *         MFDRV_MetaParam1
438  */
439 BOOL MFDRV_MetaParam1(PHYSDEV dev, short func, short param1)
440 {
441     char buffer[8];
442     METARECORD *mr = (METARECORD *)&buffer;
443
444     mr->rdSize = 4;
445     mr->rdFunction = func;
446     *(mr->rdParm) = param1;
447     return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
448 }
449
450
451 /******************************************************************
452  *         MFDRV_MetaParam2
453  */
454 BOOL MFDRV_MetaParam2(PHYSDEV dev, short func, short param1, short param2)
455 {
456     char buffer[10];
457     METARECORD *mr = (METARECORD *)&buffer;
458
459     mr->rdSize = 5;
460     mr->rdFunction = func;
461     *(mr->rdParm) = param2;
462     *(mr->rdParm + 1) = param1;
463     return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
464 }
465
466
467 /******************************************************************
468  *         MFDRV_MetaParam4
469  */
470
471 BOOL MFDRV_MetaParam4(PHYSDEV dev, short func, short param1, short param2,
472                       short param3, short param4)
473 {
474     char buffer[14];
475     METARECORD *mr = (METARECORD *)&buffer;
476
477     mr->rdSize = 7;
478     mr->rdFunction = func;
479     *(mr->rdParm) = param4;
480     *(mr->rdParm + 1) = param3;
481     *(mr->rdParm + 2) = param2;
482     *(mr->rdParm + 3) = param1;
483     return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
484 }
485
486
487 /******************************************************************
488  *         MFDRV_MetaParam6
489  */
490
491 BOOL MFDRV_MetaParam6(PHYSDEV dev, short func, short param1, short param2,
492                       short param3, short param4, short param5, short param6)
493 {
494     char buffer[18];
495     METARECORD *mr = (METARECORD *)&buffer;
496
497     mr->rdSize = 9;
498     mr->rdFunction = func;
499     *(mr->rdParm) = param6;
500     *(mr->rdParm + 1) = param5;
501     *(mr->rdParm + 2) = param4;
502     *(mr->rdParm + 3) = param3;
503     *(mr->rdParm + 4) = param2;
504     *(mr->rdParm + 5) = param1;
505     return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
506 }
507
508
509 /******************************************************************
510  *         MFDRV_MetaParam8
511  */
512 BOOL MFDRV_MetaParam8(PHYSDEV dev, short func, short param1, short param2,
513                       short param3, short param4, short param5,
514                       short param6, short param7, short param8)
515 {
516     char buffer[22];
517     METARECORD *mr = (METARECORD *)&buffer;
518
519     mr->rdSize = 11;
520     mr->rdFunction = func;
521     *(mr->rdParm) = param8;
522     *(mr->rdParm + 1) = param7;
523     *(mr->rdParm + 2) = param6;
524     *(mr->rdParm + 3) = param5;
525     *(mr->rdParm + 4) = param4;
526     *(mr->rdParm + 5) = param3;
527     *(mr->rdParm + 6) = param2;
528     *(mr->rdParm + 7) = param1;
529     return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
530 }
531
532
533 /******************************************************************
534  *         MFDRV_AddHandleDC
535  *
536  * Note: this function assumes that we never delete objects.
537  * If we do someday, we'll need to maintain a table to re-use deleted
538  * handles.
539  */
540 int MFDRV_AddHandleDC( PHYSDEV dev )
541 {
542     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
543     physDev->mh->mtNoObjects++;
544     return physDev->nextHandle++;
545 }
546
547 /**********************************************************************
548  *           MFDRV_ExtEscape
549  */
550 INT MFDRV_ExtEscape( PHYSDEV dev, INT nEscape, INT cbInput, LPCVOID in_data,
551                      INT cbOutput, LPVOID out_data )
552 {
553     METARECORD *mr;
554     DWORD len;
555     INT ret;
556
557     len = sizeof(*mr) + sizeof(WORD) + ((cbInput + 1) & ~1);
558     mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
559     mr->rdSize = len / 2;
560     mr->rdFunction = META_ESCAPE;
561     mr->rdParm[0] = nEscape;
562     mr->rdParm[1] = cbInput;
563     memcpy(&(mr->rdParm[2]), in_data, cbInput);
564     ret = MFDRV_WriteRecord( dev, mr, len);
565     HeapFree(GetProcessHeap(), 0, mr);
566     return ret;
567 }
568
569
570 /******************************************************************
571  *         MFDRV_GetDeviceCaps
572  *
573  *A very simple implementation that returns DT_METAFILE
574  */
575 INT MFDRV_GetDeviceCaps(PHYSDEV dev, INT cap)
576 {
577     switch(cap)
578     {
579     case TECHNOLOGY:
580         return DT_METAFILE;
581     case TEXTCAPS:
582         return 0;
583     default:
584         TRACE(" unsupported capability %d, will return 0\n", cap );
585     }
586     return 0;
587 }