Various trace fixes.
[wine] / dlls / gdi / metafile16.c
1 /*
2  * Metafile functions
3  *
4  * Copyright  David W. Metcalfe, 1994
5  * Copyright  Niels de Carpentier, 1996
6  * Copyright  Albrecht Kleine, 1996
7  * Copyright  Huw Davies, 1996
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 #include "config.h"
25
26 #include <string.h>
27 #include <fcntl.h>
28
29 #include "wine/winbase16.h"
30 #include "wine/wingdi16.h"
31 #include "gdi.h"
32 #include "wownt32.h"
33 #include "winreg.h"
34 #include "winternl.h"
35 #include "gdi_private.h"
36 #include "wine/debug.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
39
40 /******************************************************************
41  *         MF_GetMetaHeader16
42  *
43  * Returns ptr to METAHEADER associated with HMETAFILE16
44  * Should be followed by call to MF_ReleaseMetaHeader16
45  */
46 static METAHEADER *MF_GetMetaHeader16( HMETAFILE16 hmf )
47 {
48     return GlobalLock16(hmf);
49 }
50
51 /******************************************************************
52  *         MF_ReleaseMetaHeader16
53  *
54  * Releases METAHEADER associated with HMETAFILE16
55  */
56 static BOOL16 MF_ReleaseMetaHeader16( HMETAFILE16 hmf )
57 {
58     return GlobalUnlock16( hmf );
59 }
60
61 /******************************************************************
62  *           DeleteMetaFile   (GDI.127)
63  */
64 BOOL16 WINAPI DeleteMetaFile16(  HMETAFILE16 hmf )
65 {
66     return !GlobalFree16( hmf );
67 }
68
69 /******************************************************************
70  *         GetMetaFile   (GDI.124)
71  */
72 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
73 {
74     METAHEADER *mh;
75     HANDLE hFile;
76
77     TRACE("%s\n", lpFilename);
78
79     if(!lpFilename)
80         return 0;
81
82     if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
83                             OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
84         return 0;
85
86     mh = MF_ReadMetaFile(hFile);
87     CloseHandle(hFile);
88     if(!mh) return 0;
89     return MF_Create_HMETAFILE16( mh );
90 }
91
92 /******************************************************************
93  *         CopyMetaFile   (GDI.151)
94  */
95 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
96 {
97     METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
98     METAHEADER *mh2 = NULL;
99     HANDLE hFile;
100
101     TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
102
103     if(!mh) return 0;
104
105     if(mh->mtType == METAFILE_DISK)
106         mh2 = MF_LoadDiskBasedMetaFile(mh);
107     else {
108         mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
109         memcpy( mh2, mh, mh->mtSize * 2 );
110     }
111     MF_ReleaseMetaHeader16( hSrcMetaFile );
112
113     if(lpFilename) {         /* disk based metafile */
114         DWORD w;
115         if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
116                                 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
117             HeapFree( GetProcessHeap(), 0, mh2 );
118             return 0;
119         }
120         WriteFile(hFile, mh2, mh2->mtSize * 2, &w, NULL);
121         CloseHandle(hFile);
122         mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename, FALSE);
123     }
124
125     return MF_Create_HMETAFILE16( mh2 );
126 }
127
128 /******************************************************************
129  *         IsValidMetaFile   (GDI.410)
130  *
131  *  Attempts to check if a given metafile is correctly formatted.
132  *  Currently, the only things verified are several properties of the
133  *  header.
134  *
135  * RETURNS
136  *  TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
137  *
138  * BUGS
139  *  This is not exactly what windows does, see _Undocumented_Windows_
140  *  for details.
141  */
142 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
143 {
144     BOOL16 res=FALSE;
145     METAHEADER *mh = MF_GetMetaHeader16(hmf);
146     if (mh) {
147         if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
148             if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
149                 if (mh->mtVersion == MFVERSION)
150                     res=TRUE;
151         MF_ReleaseMetaHeader16(hmf);
152     }
153     TRACE("IsValidMetaFile %x => %d\n",hmf,res);
154     return res;
155 }
156
157 /******************************************************************
158  *         PlayMetaFile   (GDI.123)
159  *
160  */
161 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
162 {
163     BOOL16 ret;
164     METAHEADER *mh = MF_GetMetaHeader16( hmf );
165     ret = MF_PlayMetaFile( HDC_32(hdc), mh );
166     MF_ReleaseMetaHeader16( hmf );
167     return ret;
168 }
169
170
171 /******************************************************************
172  *            EnumMetaFile   (GDI.175)
173  *
174  */
175 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc16, HMETAFILE16 hmf,
176                               MFENUMPROC16 lpEnumFunc, LPARAM lpData )
177 {
178     METAHEADER *mh = MF_GetMetaHeader16(hmf);
179     METARECORD *mr;
180     HANDLETABLE16 *ht;
181     HDC hdc = HDC_32(hdc16);
182     HGLOBAL16 hHT;
183     SEGPTR spht;
184     unsigned int offset = 0;
185     WORD i, seg;
186     HPEN hPen;
187     HBRUSH hBrush;
188     HFONT hFont;
189     WORD args[8];
190     BOOL16 result = TRUE, loaded = FALSE;
191
192     TRACE("(%p, %04x, %p, %08lx)\n", hdc, hmf, lpEnumFunc, lpData);
193
194     if(!mh) return FALSE;
195     if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
196         mh = MF_LoadDiskBasedMetaFile(mh);
197         if(!mh) return FALSE;
198         loaded = TRUE;
199     }
200
201     /* save the current pen, brush and font */
202     hPen = GetCurrentObject(hdc, OBJ_PEN);
203     hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
204     hFont = GetCurrentObject(hdc, OBJ_FONT);
205
206     /* create the handle table */
207
208     hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
209                      sizeof(HANDLETABLE16) * mh->mtNoObjects);
210     spht = WOWGlobalLock16(hHT);
211
212     seg = hmf | 7;
213     offset = mh->mtHeaderSize * 2;
214
215     /* loop through metafile records */
216
217     args[7] = hdc16;
218     args[6] = SELECTOROF(spht);
219     args[5] = OFFSETOF(spht);
220     args[4] = seg + (HIWORD(offset) << __AHSHIFT);
221     args[3] = LOWORD(offset);
222     args[2] = mh->mtNoObjects;
223     args[1] = HIWORD(lpData);
224     args[0] = LOWORD(lpData);
225
226     while (offset < (mh->mtSize * 2))
227     {
228         DWORD ret;
229
230         mr = (METARECORD *)((char *)mh + offset);
231
232         WOWCallback16Ex( (DWORD)lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &ret );
233         if (!LOWORD(ret))
234         {
235             result = FALSE;
236             break;
237         }
238
239         offset += (mr->rdSize * 2);
240         args[4] = seg + (HIWORD(offset) << __AHSHIFT);
241         args[3] = LOWORD(offset);
242     }
243
244     SelectObject(hdc, hBrush);
245     SelectObject(hdc, hPen);
246     SelectObject(hdc, hFont);
247
248     ht = (HANDLETABLE16 *)GlobalLock16(hHT);
249
250     /* free objects in handle table */
251     for(i = 0; i < mh->mtNoObjects; i++)
252       if(*(ht->objectHandle + i) != 0)
253         DeleteObject( (HGDIOBJ)(ULONG_PTR)(*(ht->objectHandle + i) ));
254
255     /* free handle table */
256     GlobalFree16(hHT);
257     if(loaded)
258         HeapFree( GetProcessHeap(), 0, mh );
259     MF_ReleaseMetaHeader16(hmf);
260     return result;
261 }
262
263 /******************************************************************
264  *         GetMetaFileBits   (GDI.159)
265  *
266  * Trade in a metafile object handle for a handle to the metafile memory.
267  *
268  * PARAMS
269  *  hmf [I] metafile handle
270  */
271
272 HGLOBAL16 WINAPI GetMetaFileBits16( HMETAFILE16 hmf )
273 {
274     TRACE("hMem out: %04x\n", hmf);
275     return hmf;
276 }
277
278 /******************************************************************
279  *         SetMetaFileBits   (GDI.160)
280  *
281  * Trade in a metafile memory handle for a handle to a metafile object.
282  * The memory region should hold a proper metafile, otherwise
283  * problems will occur when it is used. Validity of the memory is not
284  * checked. The function is essentially just the identity function.
285  *
286  * PARAMS
287  *  hMem [I] handle to a memory region holding a metafile
288  *
289  * RETURNS
290  *  Handle to a metafile on success, NULL on failure..
291  */
292 HMETAFILE16 WINAPI SetMetaFileBits16( HGLOBAL16 hMem )
293 {
294     TRACE("hmf out: %04x\n", hMem);
295
296     return hMem;
297 }
298
299 /******************************************************************
300  *         SetMetaFileBitsBetter   (GDI.196)
301  *
302  * Trade in a metafile memory handle for a handle to a metafile object,
303  * making a cursory check (using IsValidMetaFile()) that the memory
304  * handle points to a valid metafile.
305  *
306  * RETURNS
307  *  Handle to a metafile on success, NULL on failure..
308  */
309 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
310 {
311     if( IsValidMetaFile16( hMeta ) )
312         return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
313                            GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
314     return (HMETAFILE16)0;
315 }
316