winedump: Print the network share name in .lnk files.
[wine] / tools / winedump / emf.c
1 /*
2  *  Dump an Enhanced Meta File
3  *
4  *  Copyright 2005 Mike McCormack
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23 #include "winedump.h"
24
25 #include <stdio.h>
26 #ifdef HAVE_UNISTD_H
27 # include <unistd.h>
28 #endif
29 #ifdef HAVE_SYS_TYPES_H
30 # include <sys/types.h>
31 #endif
32 #include <fcntl.h>
33 #include <stdarg.h>
34
35 #include "windef.h"
36 #include "winbase.h"
37 #include "wingdi.h"
38
39 static const char *debugstr_wn(const WCHAR *wstr, unsigned int n)
40 {
41     static char buf[80];
42     char *p;
43     unsigned int i;
44
45     if (!wstr) return "(null)";
46
47     i = 0;
48     p = buf;
49     *p++ = '\"';
50     while (i < n && i < sizeof(buf) - 2 && wstr[i])
51     {
52         if (wstr[i] < 127) *p++ = wstr[i];
53         else *p++ = '.';
54         i++;
55     }
56     *p++ = '\"';
57     *p = 0;
58     return buf;
59 }
60
61 static unsigned int read_int(const unsigned char *buffer)
62 {
63     return buffer[0]
64      + (buffer[1]<<8)
65      + (buffer[2]<<16)
66      + (buffer[3]<<24);
67 }
68
69 #define EMRCASE(x) case x: printf("%-20s %08x\n", #x, length); break
70
71 static unsigned offset = 0;
72
73 static int dump_emfrecord(void)
74 {
75     const unsigned char*        ptr;
76     unsigned int type, length, i;
77
78     ptr = PRD(offset, 8);
79     if (!ptr) return -1;
80
81     type = read_int(ptr);
82     length = read_int(ptr + 4);
83
84     switch(type)
85     {
86     EMRCASE(EMR_HEADER);
87     EMRCASE(EMR_POLYBEZIER);
88     EMRCASE(EMR_POLYGON);
89     EMRCASE(EMR_POLYLINE);
90     EMRCASE(EMR_POLYBEZIERTO);
91     EMRCASE(EMR_POLYLINETO);
92     EMRCASE(EMR_POLYPOLYLINE);
93     EMRCASE(EMR_POLYPOLYGON);
94     EMRCASE(EMR_SETWINDOWEXTEX);
95     EMRCASE(EMR_SETWINDOWORGEX);
96     EMRCASE(EMR_SETVIEWPORTEXTEX);
97     EMRCASE(EMR_SETVIEWPORTORGEX);
98     EMRCASE(EMR_SETBRUSHORGEX);
99     EMRCASE(EMR_EOF);
100     EMRCASE(EMR_SETPIXELV);
101     EMRCASE(EMR_SETMAPPERFLAGS);
102     EMRCASE(EMR_SETMAPMODE);
103     EMRCASE(EMR_SETBKMODE);
104     EMRCASE(EMR_SETPOLYFILLMODE);
105     EMRCASE(EMR_SETROP2);
106     EMRCASE(EMR_SETSTRETCHBLTMODE);
107     EMRCASE(EMR_SETTEXTALIGN);
108     EMRCASE(EMR_SETCOLORADJUSTMENT);
109     EMRCASE(EMR_SETTEXTCOLOR);
110     EMRCASE(EMR_SETBKCOLOR);
111     EMRCASE(EMR_OFFSETCLIPRGN);
112     EMRCASE(EMR_MOVETOEX);
113     EMRCASE(EMR_SETMETARGN);
114     EMRCASE(EMR_EXCLUDECLIPRECT);
115
116     case EMR_INTERSECTCLIPRECT:
117     {
118         const EMRINTERSECTCLIPRECT *clip = PRD(offset, sizeof(*clip));
119
120         printf("%-20s %08x\n", "EMR_INTERSECTCLIPRECT", length);
121         printf("rect %d,%d - %d, %d\n",
122                clip->rclClip.left, clip->rclClip.top,
123                clip->rclClip.right, clip->rclClip.bottom);
124         break;
125     }
126
127     EMRCASE(EMR_SCALEVIEWPORTEXTEX);
128     EMRCASE(EMR_SCALEWINDOWEXTEX);
129     EMRCASE(EMR_SAVEDC);
130     EMRCASE(EMR_RESTOREDC);
131     EMRCASE(EMR_SETWORLDTRANSFORM);
132     EMRCASE(EMR_MODIFYWORLDTRANSFORM);
133     EMRCASE(EMR_SELECTOBJECT);
134     EMRCASE(EMR_CREATEPEN);
135     EMRCASE(EMR_CREATEBRUSHINDIRECT);
136     EMRCASE(EMR_DELETEOBJECT);
137     EMRCASE(EMR_ANGLEARC);
138     EMRCASE(EMR_ELLIPSE);
139     EMRCASE(EMR_RECTANGLE);
140     EMRCASE(EMR_ROUNDRECT);
141     EMRCASE(EMR_ARC);
142     EMRCASE(EMR_CHORD);
143     EMRCASE(EMR_PIE);
144     EMRCASE(EMR_SELECTPALETTE);
145     EMRCASE(EMR_CREATEPALETTE);
146     EMRCASE(EMR_SETPALETTEENTRIES);
147     EMRCASE(EMR_RESIZEPALETTE);
148     EMRCASE(EMR_REALIZEPALETTE);
149     EMRCASE(EMR_EXTFLOODFILL);
150     EMRCASE(EMR_LINETO);
151     EMRCASE(EMR_ARCTO);
152     EMRCASE(EMR_POLYDRAW);
153     EMRCASE(EMR_SETARCDIRECTION);
154     EMRCASE(EMR_SETMITERLIMIT);
155     EMRCASE(EMR_BEGINPATH);
156     EMRCASE(EMR_ENDPATH);
157     EMRCASE(EMR_CLOSEFIGURE);
158     EMRCASE(EMR_FILLPATH);
159     EMRCASE(EMR_STROKEANDFILLPATH);
160     EMRCASE(EMR_STROKEPATH);
161     EMRCASE(EMR_FLATTENPATH);
162     EMRCASE(EMR_WIDENPATH);
163     EMRCASE(EMR_SELECTCLIPPATH);
164     EMRCASE(EMR_ABORTPATH);
165     EMRCASE(EMR_GDICOMMENT);
166     EMRCASE(EMR_FILLRGN);
167     EMRCASE(EMR_FRAMERGN);
168     EMRCASE(EMR_INVERTRGN);
169     EMRCASE(EMR_PAINTRGN);
170
171     case EMR_EXTSELECTCLIPRGN:
172     {
173         const EMREXTSELECTCLIPRGN *clip = PRD(offset, sizeof(*clip));
174         const RGNDATA *data = (const RGNDATA *)clip->RgnData;
175         DWORD i, rc_count = 0;
176         const RECT *rc;
177
178         if (length >= sizeof(*clip) + sizeof(*data))
179             rc_count = data->rdh.nCount;
180
181         printf("%-20s %08x\n", "EMREXTSELECTCLIPRGN", length);
182         printf("mode %d, rects %d\n", clip->iMode, rc_count);
183         for (i = 0, rc = (const RECT *)data->Buffer; i < rc_count; i++, rc++)
184             printf(" (%d,%d)-(%d,%d)", rc->left, rc->top, rc->right, rc->bottom);
185         if (rc_count != 0) printf("\n");
186         break;
187     }
188
189     EMRCASE(EMR_BITBLT);
190     EMRCASE(EMR_STRETCHBLT);
191     EMRCASE(EMR_MASKBLT);
192     EMRCASE(EMR_PLGBLT);
193     EMRCASE(EMR_SETDIBITSTODEVICE);
194     EMRCASE(EMR_STRETCHDIBITS);
195
196     case EMR_EXTCREATEFONTINDIRECTW:
197     {
198         const EMREXTCREATEFONTINDIRECTW *pf = PRD(offset, sizeof(*pf));
199         const LOGFONTW *plf = &pf->elfw.elfLogFont;
200
201         printf("%-20s %08x\n", "EMR_EXTCREATEFONTINDIRECTW", length);
202         printf("(%d %d %d %d %x out %d clip %x quality %d charset %d) %s %s %s %s\n",
203                plf->lfHeight, plf->lfWidth,
204                plf->lfEscapement, plf->lfOrientation,
205                plf->lfPitchAndFamily,
206                plf->lfOutPrecision, plf->lfClipPrecision,
207                plf->lfQuality, plf->lfCharSet,
208                debugstr_wn(plf->lfFaceName, LF_FACESIZE),
209                plf->lfWeight > 400 ? "Bold" : "",
210                plf->lfItalic ? "Italic" : "",
211                plf->lfUnderline ? "Underline" : "");
212         break;
213     }
214
215     EMRCASE(EMR_EXTTEXTOUTA);
216
217     case EMR_EXTTEXTOUTW:
218     {
219         const EMREXTTEXTOUTW *etoW = PRD(offset, sizeof(*etoW));
220
221         printf("%-20s %08x\n", "EMR_EXTTEXTOUTW", length);
222         printf("pt (%d,%d) rect (%d,%d - %d,%d) flags %#x, %s\n",
223                etoW->emrtext.ptlReference.x, etoW->emrtext.ptlReference.y,
224                etoW->emrtext.rcl.left, etoW->emrtext.rcl.top,
225                etoW->emrtext.rcl.right, etoW->emrtext.rcl.bottom,
226                etoW->emrtext.fOptions,
227                debugstr_wn((LPCWSTR)((const BYTE *)etoW + etoW->emrtext.offString), etoW->emrtext.nChars));
228         break;
229     }
230
231     EMRCASE(EMR_POLYBEZIER16);
232     EMRCASE(EMR_POLYGON16);
233     EMRCASE(EMR_POLYLINE16);
234     EMRCASE(EMR_POLYBEZIERTO16);
235     EMRCASE(EMR_POLYLINETO16);
236     EMRCASE(EMR_POLYPOLYLINE16);
237     EMRCASE(EMR_POLYPOLYGON16);
238     EMRCASE(EMR_POLYDRAW16);
239     EMRCASE(EMR_CREATEMONOBRUSH);
240     EMRCASE(EMR_CREATEDIBPATTERNBRUSHPT);
241     EMRCASE(EMR_EXTCREATEPEN);
242     EMRCASE(EMR_POLYTEXTOUTA);
243     EMRCASE(EMR_POLYTEXTOUTW);
244     EMRCASE(EMR_SETICMMODE);
245     EMRCASE(EMR_CREATECOLORSPACE);
246     EMRCASE(EMR_SETCOLORSPACE);
247     EMRCASE(EMR_DELETECOLORSPACE);
248     EMRCASE(EMR_GLSRECORD);
249     EMRCASE(EMR_GLSBOUNDEDRECORD);
250     EMRCASE(EMR_PIXELFORMAT);
251     EMRCASE(EMR_DRAWESCAPE);
252     EMRCASE(EMR_EXTESCAPE);
253     EMRCASE(EMR_STARTDOC);
254     EMRCASE(EMR_SMALLTEXTOUT);
255     EMRCASE(EMR_FORCEUFIMAPPING);
256     EMRCASE(EMR_NAMEDESCAPE);
257     EMRCASE(EMR_COLORCORRECTPALETTE);
258     EMRCASE(EMR_SETICMPROFILEA);
259     EMRCASE(EMR_SETICMPROFILEW);
260     EMRCASE(EMR_ALPHABLEND);
261     EMRCASE(EMR_SETLAYOUT);
262     EMRCASE(EMR_TRANSPARENTBLT);
263     EMRCASE(EMR_RESERVED_117);
264     EMRCASE(EMR_GRADIENTFILL);
265     EMRCASE(EMR_SETLINKEDUFI);
266     EMRCASE(EMR_SETTEXTJUSTIFICATION);
267     EMRCASE(EMR_COLORMATCHTOTARGETW);
268     EMRCASE(EMR_CREATECOLORSPACEW);
269
270     default:
271         printf("%u %08x\n", type, length);
272         break;
273     }
274
275     if ( (length < 8) || (length % 4) )
276         return -1;
277
278     length -= 8;
279
280     offset += 8;
281
282     for(i=0; i<length; i+=4)
283     {
284          if (i%16 == 0)
285              printf("   ");
286          if (!(ptr = PRD(offset, 4))) return -1;
287          offset += 4;
288          printf("%08x ", read_int(ptr));
289          if ( (i % 16 == 12) || (i + 4 == length))
290              printf("\n");
291     }
292
293     return 0;
294 }
295
296 enum FileSig get_kind_emf(void)
297 {
298     const ENHMETAHEADER*        hdr;
299
300     hdr = PRD(0, sizeof(*hdr));
301     if (hdr && hdr->iType == EMR_HEADER && hdr->dSignature == ENHMETA_SIGNATURE)
302         return SIG_EMF;
303     return SIG_UNKNOWN;
304 }
305
306 void emf_dump(void)
307 {
308     offset = 0;
309     while (!dump_emfrecord());
310 }