Resync with the latest DLLs that were added and/or moved.
[wine.git] / tools / winedump / lnk.c
blob056354f982f742cf71eef8ee0d86b3da6f9a08cd
1 /*
2 * Dump a shortcut (lnk) file
4 * Copyright 2005 Mike McCormack
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.
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.
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
21 #include "config.h"
22 #include "wine/port.h"
23 #include "winedump.h"
25 #include <stdio.h>
26 #include <stdlib.h>
27 #ifdef HAVE_UNISTD_H
28 # include <unistd.h>
29 #endif
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
32 #endif
33 #include <fcntl.h>
34 #include <stdarg.h>
36 #include "windef.h"
37 #include "winbase.h"
39 #include "pshpack1.h"
41 #define SCF_PIDL 1
42 #define SCF_LOCATION 2
43 #define SCF_DESCRIPTION 4
44 #define SCF_RELATIVE 8
45 #define SCF_WORKDIR 0x10
46 #define SCF_ARGS 0x20
47 #define SCF_CUSTOMICON 0x40
48 #define SCF_UNICODE 0x80
49 #define SCF_PRODUCT 0x800
50 #define SCF_COMPONENT 0x1000
52 typedef struct _LINK_HEADER
54 DWORD dwSize; /* 0x00 size of the header - 0x4c */
55 GUID MagicGuid; /* 0x04 is CLSID_ShellLink */
56 DWORD dwFlags; /* 0x14 describes elements following */
57 DWORD dwFileAttr; /* 0x18 attributes of the target file */
58 FILETIME Time1; /* 0x1c */
59 FILETIME Time2; /* 0x24 */
60 FILETIME Time3; /* 0x2c */
61 DWORD dwFileLength; /* 0x34 File length */
62 DWORD nIcon; /* 0x38 icon number */
63 DWORD fStartup; /* 0x3c startup type */
64 DWORD wHotKey; /* 0x40 hotkey */
65 DWORD Unknown5; /* 0x44 */
66 DWORD Unknown6; /* 0x48 */
67 } LINK_HEADER, * PLINK_HEADER;
69 typedef struct tagLINK_ADVERTISEINFO
71 DWORD size;
72 DWORD magic;
73 CHAR bufA[MAX_PATH];
74 WCHAR bufW[MAX_PATH];
75 } LINK_ADVERTISEINFO;
77 typedef struct _LOCATION_INFO
79 DWORD dwTotalSize;
80 DWORD dwHeaderSize;
81 DWORD dwFlags;
82 DWORD dwVolTableOfs;
83 DWORD dwLocalPathOfs;
84 DWORD dwNetworkVolTableOfs;
85 DWORD dwFinalPathOfs;
86 } LOCATION_INFO;
88 typedef struct _LOCAL_VOLUME_INFO
90 DWORD dwSize;
91 DWORD dwType;
92 DWORD dwVolSerial;
93 DWORD dwVolLabelOfs;
94 } LOCAL_VOLUME_INFO;
96 typedef struct lnk_string_tag {
97 unsigned short size;
98 union {
99 unsigned short w[1];
100 unsigned char a[1];
101 } str;
102 } lnk_string;
104 #include "poppack.h"
106 static void guid_to_string(LPGUID guid, char *str)
108 sprintf(str, "{%08lx-%04x-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X}",
109 guid->Data1, guid->Data2, guid->Data3,
110 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
111 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
114 /* the size is a short integer */
115 static void* load_pidl(int fd)
117 int r;
118 unsigned char *data;
119 unsigned short size = 0;
121 r = read( fd, &size, sizeof size );
122 if (r != sizeof size)
123 return NULL;
124 if (size<sizeof size)
125 return NULL;
127 data = malloc(size + sizeof size);
128 memcpy(data, &size, sizeof size);
129 r = read( fd, data + sizeof size, size );
130 if (r != size)
132 free(data);
133 return NULL;
135 return (void*)data;
138 /* size is an integer */
139 static void* load_long_section(int fd)
141 int r, size = 0;
142 unsigned char *data;
144 r = read( fd, &size, sizeof size );
145 if (r != sizeof size)
146 return NULL;
147 if (size<sizeof size)
148 return NULL;
150 data = malloc(size);
151 memcpy(data, &size, sizeof size);
152 r = read( fd, data + sizeof size, size - sizeof size);
153 if (r != (size - sizeof size))
155 free(data);
156 return NULL;
158 return (void*)data;
161 /* the size is a character count in a short integer */
162 static lnk_string* load_string(int fd, int unicode)
164 int r;
165 lnk_string *data;
166 unsigned short size = 0, bytesize;
168 r = read( fd, &size, sizeof size );
169 if (r != sizeof size)
170 return NULL;
171 if (size < sizeof size)
172 return NULL;
174 bytesize = size;
175 if (unicode)
176 bytesize *= sizeof(WCHAR);
177 data = malloc(sizeof *data + bytesize);
178 data->size = size;
179 if (unicode)
180 data->str.w[size] = 0;
181 else
182 data->str.a[size] = 0;
183 r = read(fd, &data->str, bytesize);
184 if (r != bytesize)
186 free(data);
187 return NULL;
189 return data;
193 static int dump_pidl(int fd)
195 lnk_string *pidl;
196 int i, n = 0, sz = 0;
198 pidl = load_pidl(fd);
199 if (!pidl)
200 return -1;
202 printf("PIDL\n");
203 printf("----\n\n");
205 while(sz<pidl->size)
207 lnk_string *segment = (lnk_string*) &pidl->str.a[sz];
209 if(!segment->size)
210 break;
211 sz+=segment->size;
212 if(sz>pidl->size)
214 printf("bad pidl\n");
215 break;
217 n++;
218 printf("segment %d (%2d bytes) : ",n,segment->size);
219 for(i=0; i<segment->size; i++)
220 printf("%02x ",segment->str.a[i]);
221 printf("\n");
223 printf("\n");
225 free(pidl);
227 return 0;
230 static void print_unicode_string(const unsigned short *str)
232 while(*str)
234 printf("%c", *str);
235 str++;
237 printf("\n");
240 static int dump_string(int fd, const char *what, int unicode)
242 lnk_string *data;
244 data = load_string(fd, unicode);
245 if (!data)
246 return -1;
247 printf("%s : ", what);
248 if (unicode)
249 print_unicode_string(data->str.w);
250 else
251 printf("%s",data->str.a);
252 printf("\n");
253 free(data);
254 return 0;
257 static int dump_location(int fd)
259 LOCATION_INFO *loc;
260 char *p;
262 loc = load_long_section(fd);
263 if (!loc)
264 return -1;
265 p = (char*)loc;
267 printf("Location\n");
268 printf("--------\n\n");
269 printf("Total size = %ld\n", loc->dwTotalSize);
270 printf("Header size = %ld\n", loc->dwHeaderSize);
271 printf("Flags = %08lx\n", loc->dwFlags);
273 /* dump out information about the volume the link points to */
274 printf("Volume ofs = %08lx ", loc->dwVolTableOfs);
275 if (loc->dwVolTableOfs && (loc->dwVolTableOfs<loc->dwTotalSize))
277 LOCAL_VOLUME_INFO *vol = (LOCAL_VOLUME_INFO *) &p[loc->dwVolTableOfs];
279 printf("size %ld type %ld serial %08lx label %ld ",
280 vol->dwSize, vol->dwType, vol->dwVolSerial, vol->dwVolLabelOfs);
281 if(vol->dwVolLabelOfs)
282 printf("(\"%s\")", &p[loc->dwVolTableOfs + vol->dwVolLabelOfs]);
284 printf("\n");
286 /* dump out the path the link points to */
287 printf("LocalPath ofs = %08lx ", loc->dwLocalPathOfs);
288 if( loc->dwLocalPathOfs && (loc->dwLocalPathOfs < loc->dwTotalSize) )
289 printf("(\"%s\")", &p[loc->dwLocalPathOfs]);
290 printf("\n");
292 printf("Net Path ofs = %08lx\n", loc->dwNetworkVolTableOfs);
293 printf("Final Path = %08lx ", loc->dwFinalPathOfs);
294 if( loc->dwFinalPathOfs && (loc->dwFinalPathOfs < loc->dwTotalSize) )
295 printf("(\"%s\")", &p[loc->dwFinalPathOfs]);
296 printf("\n");
297 printf("\n");
299 free(loc);
301 return 0;
304 static const unsigned char table_dec85[0x80] = {
305 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
306 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
307 0xff,0x00,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff,
308 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0xff,0xff,0xff,0x16,0xff,0x17,
309 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
310 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0xff,0x34,0x35,0x36,
311 0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,
312 0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0xff,0x53,0x54,0xff,
315 static int base85_to_guid( const char *str, LPGUID guid )
317 DWORD i, val = 0, base = 1, *p;
318 unsigned char ch;
320 p = (DWORD*) guid;
321 for( i=0; i<20; i++ )
323 if( (i%5) == 0 )
325 val = 0;
326 base = 1;
328 ch = str[i];
329 if( ch >= 0x80 )
330 return 0;
331 val += table_dec85[ch] * base;
332 if( table_dec85[ch] == 0xff )
333 return 0;
334 if( (i%5) == 4 )
335 p[i/5] = val;
336 base *= 85;
338 return 1;
341 static int dump_advertise_info(int fd, const char *type)
343 LINK_ADVERTISEINFO *avt;
345 avt = load_long_section(fd);
346 if (!avt)
347 return -1;
349 printf("Advertise Info\n");
350 printf("--------------\n\n");
351 printf("magic = %lx\n", avt->magic);
352 printf("%s = %s\n", type, avt->bufA);
353 if (avt->magic == 0xa0000006)
355 char prod_str[40], comp_str[40], feat_str[40];
356 char *feat, *comp;
357 GUID guid;
359 if (base85_to_guid(avt->bufA, &guid))
360 guid_to_string( &guid, prod_str );
361 else
362 strcpy( prod_str, "?" );
364 comp = &avt->bufA[20];
365 feat = strchr(comp,'>');
366 if (feat)
367 memcpy( comp_str, comp, feat - comp );
368 else
369 strcpy( prod_str, "?" );
371 if (feat && base85_to_guid( &feat[1], &guid ))
372 guid_to_string( &guid, feat_str );
373 else
374 strcpy( prod_str, "?" );
376 printf(" product: %s\n", prod_str);
377 printf(" component: %s\n", comp_str );
378 printf(" feature: %s\n", feat_str);
380 printf("\n");
382 return 0;
385 static int dump_lnk_fd(int fd)
387 LINK_HEADER *hdr;
388 char guid[40];
390 hdr = load_long_section( fd );
391 if (!hdr)
392 return -1;
394 guid_to_string(&hdr->MagicGuid, guid);
396 printf("Header\n");
397 printf("------\n\n");
398 printf("Size: %04lx\n", hdr->dwSize);
399 printf("GUID: %s\n", guid);
401 /* dump out all the flags */
402 printf("Flags: %04lx ( ", hdr->dwFlags);
403 #define FLAG(x) if(hdr->dwFlags & SCF_##x) printf("%s ",#x);
404 FLAG(PIDL)
405 FLAG(LOCATION)
406 FLAG(DESCRIPTION)
407 FLAG(RELATIVE)
408 FLAG(WORKDIR)
409 FLAG(ARGS)
410 FLAG(CUSTOMICON)
411 FLAG(UNICODE)
412 FLAG(PRODUCT)
413 FLAG(COMPONENT)
414 #undef FLAG
415 printf(")\n");
417 printf("Length: %04lx\n", hdr->dwFileLength);
418 printf("\n");
420 if (hdr->dwFlags & SCF_PIDL)
421 dump_pidl(fd);
422 if (hdr->dwFlags & SCF_LOCATION)
423 dump_location(fd);
424 if (hdr->dwFlags & SCF_DESCRIPTION)
425 dump_string(fd, "Description", hdr->dwFlags & SCF_UNICODE);
426 if (hdr->dwFlags & SCF_RELATIVE)
427 dump_string(fd, "Relative path", hdr->dwFlags & SCF_UNICODE);
428 if (hdr->dwFlags & SCF_WORKDIR)
429 dump_string(fd, "Working directory", hdr->dwFlags & SCF_UNICODE);
430 if (hdr->dwFlags & SCF_ARGS)
431 dump_string(fd, "Arguments", hdr->dwFlags & SCF_UNICODE);
432 if (hdr->dwFlags & SCF_CUSTOMICON)
433 dump_string(fd, "Icon path", hdr->dwFlags & SCF_UNICODE);
434 if (hdr->dwFlags & SCF_PRODUCT)
435 dump_advertise_info(fd, "product");
436 if (hdr->dwFlags & SCF_COMPONENT)
437 dump_advertise_info(fd, "msi string");
439 return 0;
442 int dump_lnk(const char *emf)
444 int fd;
446 fd = open(emf,O_RDONLY);
447 if (fd<0)
448 return -1;
449 dump_lnk_fd(fd);
450 close(fd);
451 return 0;