Use config.h & HAVE_ where needed, -W fixes.
[wine] / tools / winedump / lnk.c
1 /*
2  *  Dump a shortcut (lnk) 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <stdio.h>
25 #include <stdlib.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
38 #include "pshpack1.h"
39
40 #define SCF_PIDL 1
41 #define SCF_LOCATION 2
42 #define SCF_DESCRIPTION 4
43 #define SCF_RELATIVE 8
44 #define SCF_WORKDIR 0x10
45 #define SCF_ARGS 0x20
46 #define SCF_CUSTOMICON 0x40
47 #define SCF_UNICODE 0x80
48 #define SCF_PRODUCT 0x800
49 #define SCF_COMPONENT 0x1000
50
51 typedef struct _LINK_HEADER
52 {
53     DWORD    dwSize;        /* 0x00 size of the header - 0x4c */
54     GUID     MagicGuid;     /* 0x04 is CLSID_ShellLink */
55     DWORD    dwFlags;       /* 0x14 describes elements following */
56     DWORD    dwFileAttr;    /* 0x18 attributes of the target file */
57     FILETIME Time1;         /* 0x1c */
58     FILETIME Time2;         /* 0x24 */
59     FILETIME Time3;         /* 0x2c */
60     DWORD    dwFileLength;  /* 0x34 File length */
61     DWORD    nIcon;         /* 0x38 icon number */
62     DWORD   fStartup;       /* 0x3c startup type */
63     DWORD   wHotKey;        /* 0x40 hotkey */
64     DWORD   Unknown5;       /* 0x44 */
65     DWORD   Unknown6;       /* 0x48 */
66 } LINK_HEADER, * PLINK_HEADER;
67
68 typedef struct tagLINK_ADVERTISEINFO
69 {
70     DWORD size;
71     DWORD magic;
72     CHAR  bufA[MAX_PATH];
73     WCHAR bufW[MAX_PATH];
74 } LINK_ADVERTISEINFO;
75
76 typedef struct _LOCATION_INFO
77 {
78     DWORD  dwTotalSize;
79     DWORD  dwHeaderSize;
80     DWORD  dwFlags;
81     DWORD  dwVolTableOfs;
82     DWORD  dwLocalPathOfs;
83     DWORD  dwNetworkVolTableOfs;
84     DWORD  dwFinalPathOfs;
85 } LOCATION_INFO;
86
87 typedef struct _LOCAL_VOLUME_INFO
88 {
89     DWORD dwSize;
90     DWORD dwType;
91     DWORD dwVolSerial;
92     DWORD dwVolLabelOfs;
93 } LOCAL_VOLUME_INFO;
94
95 typedef struct lnk_string_tag {
96     unsigned short size;
97     union {
98         unsigned short w[1];
99         unsigned char a[1];
100     } str;
101 } lnk_string;
102
103 #include "poppack.h"
104
105 static void guid_to_string(LPGUID guid, char *str)
106 {
107     sprintf(str, "{%08lx-%04x-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X}",
108             guid->Data1, guid->Data2, guid->Data3,
109             guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
110             guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
111 }
112
113 /* the size is a short integer */
114 static void* load_pidl(int fd)
115 {
116     int r;
117     unsigned char *data;
118     unsigned short size = 0;
119
120     r = read( fd, &size, sizeof size );
121     if (r != sizeof size)
122         return NULL;
123     if (size<sizeof size)
124         return NULL;
125
126     data = malloc(size + sizeof size);
127     memcpy(data, &size, sizeof size);
128     r = read( fd, data + sizeof size, size );
129     if (r != size)
130     {
131         free(data);
132         return NULL;
133     }
134     return (void*)data;
135 }
136
137 /* size is an integer */
138 static void* load_long_section(int fd)
139 {
140     int r, size = 0;
141     unsigned char *data;
142
143     r = read( fd, &size, sizeof size );
144     if (r != sizeof size)
145         return NULL;
146     if (size<sizeof size)
147         return NULL;
148
149     data = malloc(size);
150     memcpy(data, &size, sizeof size);
151     r = read( fd, data + sizeof size, size - sizeof size);
152     if (r != (size - sizeof size))
153     {
154         free(data);
155         return NULL;
156     }
157     return (void*)data;
158 }
159
160 /* the size is a character count in a short integer */
161 static lnk_string* load_string(int fd, int unicode)
162 {
163     int r;
164     lnk_string *data;
165     unsigned short size = 0, bytesize;
166
167     r = read( fd, &size, sizeof size );
168     if (r != sizeof size)
169         return NULL;
170     if (size < sizeof size)
171         return NULL;
172
173     bytesize = size;
174     if (unicode)
175         bytesize *= sizeof(WCHAR);
176     data = malloc(sizeof *data + bytesize);
177     data->size = size;
178     if (unicode)
179         data->str.w[size] = 0;
180     else
181         data->str.a[size] = 0;
182     r = read(fd, &data->str, bytesize);
183     if (r != bytesize)
184     {
185         free(data);
186         return NULL;
187     }
188     return data;
189 }
190
191
192 static int dump_pidl(int fd)
193 {
194     void *pidl;
195
196     pidl = load_pidl(fd);
197     if (!pidl)
198         return -1;
199
200     printf("PIDL\n");
201     printf("----\n\n");
202
203     free(pidl);
204
205     return 0;
206 }
207
208 static void print_unicode_string(unsigned short *str)
209 {
210     while(*str)
211     {
212         printf("%c", *str);
213         str++;
214     }
215     printf("\n");
216 }
217
218 static int dump_string(int fd, char *what, int unicode)
219 {
220     lnk_string *data;
221
222     data = load_string(fd, unicode);
223     if (!data)
224         return -1;
225     printf("%s : ", what);
226     if (unicode)
227         print_unicode_string(data->str.w);
228     else
229         printf("%s",data->str.a);
230     printf("\n");
231     free(data);
232     return 0;
233 }
234
235 static int dump_location(int fd)
236 {
237     LOCATION_INFO *loc;
238     char *p;
239
240     loc = load_long_section(fd);
241     if (!loc)
242         return -1;
243     p = (char*)loc;
244
245     printf("Location\n");
246     printf("--------\n\n");
247     printf("Total size    = %ld\n", loc->dwTotalSize);
248     printf("Header size   = %ld\n", loc->dwHeaderSize);
249     printf("Flags         = %08lx\n", loc->dwFlags);
250
251     /* dump out information about the volume the link points to */
252     printf("Volume ofs    = %08lx ", loc->dwVolTableOfs);
253     if (loc->dwVolTableOfs && (loc->dwVolTableOfs<loc->dwTotalSize))
254     {
255         LOCAL_VOLUME_INFO *vol = (LOCAL_VOLUME_INFO *) &p[loc->dwVolTableOfs];
256
257         printf("size %ld  type %ld  serial %08lx  label %ld ",
258                vol->dwSize, vol->dwType, vol->dwVolSerial, vol->dwVolLabelOfs);
259         if(vol->dwVolLabelOfs)
260             printf("(\"%s\")", &p[vol->dwVolLabelOfs]);
261     }
262     printf("\n");
263
264     /* dump out the path the link points to */
265     printf("LocalPath ofs = %08lx ", loc->dwLocalPathOfs);
266     if( loc->dwLocalPathOfs && (loc->dwLocalPathOfs < loc->dwTotalSize) )
267         printf("(\"%s\")", &p[loc->dwLocalPathOfs]);
268     printf("\n");
269
270     printf("Net Path ofs  = %08lx\n", loc->dwNetworkVolTableOfs);
271     printf("Final Path    = %08lx ", loc->dwFinalPathOfs);
272     if( loc->dwFinalPathOfs && (loc->dwFinalPathOfs < loc->dwTotalSize) )
273         printf("(\"%s\")", &p[loc->dwFinalPathOfs]);
274     printf("\n");
275     printf("\n");
276
277     free(loc);
278
279     return 0;
280 }
281
282 static int dump_advertise_info(int fd, char *type)
283 {
284     LINK_ADVERTISEINFO *avt;
285
286     avt = load_long_section(fd);
287     if (!avt)
288         return -1;
289
290     printf("Advertise Info\n");
291     printf("--------------\n\n");
292     printf("magic   = %lx\n", avt->magic);
293     printf("%s = %s\n", type, avt->bufA);
294     printf("\n");
295
296     return 0;
297 }
298
299 static int dump_lnk_fd(int fd)
300 {
301     LINK_HEADER *hdr;
302     char guid[40];
303
304     hdr = load_long_section( fd );
305     if (!hdr)
306         return -1;
307
308     guid_to_string(&hdr->MagicGuid, guid);
309
310     printf("Header\n");
311     printf("------\n\n");
312     printf("Size:    %04lx\n", hdr->dwSize);
313     printf("GUID:    %s\n", guid);
314
315     /* dump out all the flags */
316     printf("Flags:   %04lx ( ", hdr->dwFlags);
317 #define FLAG(x) if(hdr->dwFlags & SCF_##x) printf("%s ",#x);
318     FLAG(PIDL)
319     FLAG(LOCATION)
320     FLAG(DESCRIPTION)
321     FLAG(RELATIVE)
322     FLAG(WORKDIR)
323     FLAG(ARGS)
324     FLAG(CUSTOMICON)
325     FLAG(UNICODE)
326     FLAG(PRODUCT)
327     FLAG(COMPONENT)
328 #undef FLAG
329     printf(")\n");
330
331     printf("Length:  %04lx\n", hdr->dwFileLength);
332     printf("\n");
333
334     if (hdr->dwFlags & SCF_PIDL)
335         dump_pidl(fd);
336     if (hdr->dwFlags & SCF_LOCATION)
337         dump_location(fd);
338     if (hdr->dwFlags & SCF_DESCRIPTION)
339         dump_string(fd, "Description", hdr->dwFlags & SCF_UNICODE);
340     if (hdr->dwFlags & SCF_RELATIVE)
341         dump_string(fd, "Relative path", hdr->dwFlags & SCF_UNICODE);
342     if (hdr->dwFlags & SCF_WORKDIR)
343         dump_string(fd, "Working directory", hdr->dwFlags & SCF_UNICODE);
344     if (hdr->dwFlags & SCF_ARGS)
345         dump_string(fd, "Arguments", hdr->dwFlags & SCF_UNICODE);
346     if (hdr->dwFlags & SCF_CUSTOMICON)
347         dump_string(fd, "Icon path", hdr->dwFlags & SCF_UNICODE);
348     if (hdr->dwFlags & SCF_PRODUCT)
349         dump_advertise_info(fd, "product");
350     if (hdr->dwFlags & SCF_COMPONENT)
351         dump_advertise_info(fd, "component");
352
353     return 0;
354 }
355
356 int dump_lnk(const char *emf)
357 {
358     int fd;
359
360     fd = open(emf,O_RDONLY);
361     if (fd<0)
362         return -1;
363     dump_lnk_fd(fd);
364     close(fd);
365     return 0;
366 }