winedump: Use the standard SLDF_XXX flag names instead of inventing new ones. Add...
[wine.git] / tools / winedump / lnk.c
blob2754602e58f515b2d1a2fb9b3cfa9db8872582d8
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 typedef enum {
42 SLDF_HAS_ID_LIST = 0x00000001,
43 SLDF_HAS_LINK_INFO = 0x00000002,
44 SLDF_HAS_NAME = 0x00000004,
45 SLDF_HAS_RELPATH = 0x00000008,
46 SLDF_HAS_WORKINGDIR = 0x00000010,
47 SLDF_HAS_ARGS = 0x00000020,
48 SLDF_HAS_ICONLOCATION = 0x00000040,
49 SLDF_UNICODE = 0x00000080,
50 SLDF_FORCE_NO_LINKINFO = 0x00000100,
51 SLDF_HAS_EXP_SZ = 0x00000200,
52 SLDF_RUN_IN_SEPARATE = 0x00000400,
53 SLDF_HAS_LOGO3ID = 0x00000800,
54 SLDF_HAS_DARWINID = 0x00001000,
55 SLDF_RUNAS_USER = 0x00002000,
56 SLDF_HAS_EXP_ICON_SZ = 0x00004000,
57 SLDF_NO_PIDL_ALIAS = 0x00008000,
58 SLDF_FORCE_UNCNAME = 0x00010000,
59 SLDF_RUN_WITH_SHIMLAYER = 0x00020000,
60 SLDF_FORCE_NO_LINKTRACK = 0x00040000,
61 SLDF_ENABLE_TARGET_METADATA = 0x00080000,
62 SLDF_DISABLE_KNOWNFOLDER_RELATIVE_TRACKING = 0x00200000,
63 SLDF_RESERVED = 0x80000000,
64 } SHELL_LINK_DATA_FLAGS;
66 typedef struct tagDATABLOCKHEADER
68 DWORD cbSize;
69 DWORD dwSignature;
70 } DATABLOCK_HEADER;
72 typedef struct _LINK_HEADER
74 DWORD dwSize; /* 0x00 size of the header - 0x4c */
75 GUID MagicGuid; /* 0x04 is CLSID_ShellLink */
76 DWORD dwFlags; /* 0x14 describes elements following */
77 DWORD dwFileAttr; /* 0x18 attributes of the target file */
78 FILETIME Time1; /* 0x1c */
79 FILETIME Time2; /* 0x24 */
80 FILETIME Time3; /* 0x2c */
81 DWORD dwFileLength; /* 0x34 File length */
82 DWORD nIcon; /* 0x38 icon number */
83 DWORD fStartup; /* 0x3c startup type */
84 DWORD wHotKey; /* 0x40 hotkey */
85 DWORD Unknown5; /* 0x44 */
86 DWORD Unknown6; /* 0x48 */
87 } LINK_HEADER, * PLINK_HEADER;
89 typedef struct tagLINK_ADVERTISEINFO
91 DWORD size;
92 DWORD magic;
93 CHAR bufA[MAX_PATH];
94 WCHAR bufW[MAX_PATH];
95 } LINK_ADVERTISEINFO;
97 typedef struct _LOCATION_INFO
99 DWORD dwTotalSize;
100 DWORD dwHeaderSize;
101 DWORD dwFlags;
102 DWORD dwVolTableOfs;
103 DWORD dwLocalPathOfs;
104 DWORD dwNetworkVolTableOfs;
105 DWORD dwFinalPathOfs;
106 } LOCATION_INFO;
108 typedef struct _LOCAL_VOLUME_INFO
110 DWORD dwSize;
111 DWORD dwType;
112 DWORD dwVolSerial;
113 DWORD dwVolLabelOfs;
114 } LOCAL_VOLUME_INFO;
116 typedef struct lnk_string_tag
118 unsigned short size;
119 union {
120 unsigned short w[1];
121 unsigned char a[1];
122 } str;
123 } lnk_string;
125 #include "poppack.h"
127 static unsigned offset;
129 static const void* fetch_block(void)
131 const unsigned* u;
132 const void* ret;
134 if (!(u = PRD(offset, sizeof(*u)))) return 0;
135 if ((ret = PRD(offset, *u))) offset += *u;
136 return ret;
139 static const lnk_string* fetch_string(int unicode)
141 const unsigned short* s;
142 unsigned short len;
143 const void* ret;
145 if (!(s = PRD(offset, sizeof(*s)))) return 0;
146 len = *s * (unicode ? sizeof(WCHAR) : sizeof(char));
147 if ((ret = PRD(offset, sizeof(*s) + len))) offset += sizeof(*s) + len;
148 return ret;
152 static int dump_pidl(void)
154 const lnk_string *pidl;
155 int i, n = 0, sz = 0;
157 pidl = fetch_string(FALSE);
158 if (!pidl)
159 return -1;
161 printf("PIDL\n");
162 printf("----\n\n");
164 while(sz<pidl->size)
166 const lnk_string *segment = (const lnk_string*) &pidl->str.a[sz];
168 if(!segment->size)
169 break;
170 sz+=segment->size;
171 if(sz>pidl->size)
173 printf("bad pidl\n");
174 break;
176 n++;
177 printf("segment %d (%2d bytes) : ",n,segment->size);
178 for(i=0; i<segment->size; i++)
179 printf("%02x ",segment->str.a[i]);
180 printf("\n");
182 printf("\n");
184 return 0;
187 static int dump_string(const char *what, int unicode)
189 const lnk_string *data;
190 unsigned sz;
192 data = fetch_string(unicode);
193 if (!data)
194 return -1;
195 printf("%s : ", what);
196 sz = data->size;
197 if (unicode)
198 while (sz) printf("%c", data->str.w[data->size - sz--]);
199 else
200 while (sz) printf("%c", data->str.a[data->size - sz--]);
201 printf("\n");
203 return 0;
206 static int dump_location(void)
208 const LOCATION_INFO *loc;
209 const char *p;
211 loc = fetch_block();
212 if (!loc)
213 return -1;
214 p = (const char*)loc;
216 printf("Location\n");
217 printf("--------\n\n");
218 printf("Total size = %d\n", loc->dwTotalSize);
219 printf("Header size = %d\n", loc->dwHeaderSize);
220 printf("Flags = %08x\n", loc->dwFlags);
222 /* dump out information about the volume the link points to */
223 printf("Volume ofs = %08x ", loc->dwVolTableOfs);
224 if (loc->dwVolTableOfs && (loc->dwVolTableOfs<loc->dwTotalSize))
226 const LOCAL_VOLUME_INFO *vol = (const LOCAL_VOLUME_INFO *)&p[loc->dwVolTableOfs];
228 printf("size %d type %d serial %08x label %d ",
229 vol->dwSize, vol->dwType, vol->dwVolSerial, vol->dwVolLabelOfs);
230 if(vol->dwVolLabelOfs)
231 printf("(\"%s\")", &p[loc->dwVolTableOfs + vol->dwVolLabelOfs]);
233 printf("\n");
235 /* dump out the path the link points to */
236 printf("LocalPath ofs = %08x ", loc->dwLocalPathOfs);
237 if( loc->dwLocalPathOfs && (loc->dwLocalPathOfs < loc->dwTotalSize) )
238 printf("(\"%s\")", &p[loc->dwLocalPathOfs]);
239 printf("\n");
241 printf("Net Path ofs = %08x\n", loc->dwNetworkVolTableOfs);
242 printf("Final Path = %08x ", loc->dwFinalPathOfs);
243 if( loc->dwFinalPathOfs && (loc->dwFinalPathOfs < loc->dwTotalSize) )
244 printf("(\"%s\")", &p[loc->dwFinalPathOfs]);
245 printf("\n");
246 printf("\n");
248 return 0;
251 static const unsigned char table_dec85[0x80] = {
252 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
253 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
254 0xff,0x00,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff,
255 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0xff,0xff,0xff,0x16,0xff,0x17,
256 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
257 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0xff,0x34,0x35,0x36,
258 0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,
259 0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0xff,0x53,0x54,0xff,
262 static int base85_to_guid( const char *str, LPGUID guid )
264 DWORD i, val = 0, base = 1, *p;
265 unsigned char ch;
267 p = (DWORD*) guid;
268 for( i=0; i<20; i++ )
270 if( (i%5) == 0 )
272 val = 0;
273 base = 1;
275 ch = str[i];
276 if( ch >= 0x80 )
277 return 0;
278 val += table_dec85[ch] * base;
279 if( table_dec85[ch] == 0xff )
280 return 0;
281 if( (i%5) == 4 )
282 p[i/5] = val;
283 base *= 85;
285 return 1;
288 static int dump_advertise_info(const char *type)
290 const LINK_ADVERTISEINFO *avt;
292 avt = fetch_block();
293 if (!avt)
294 return -1;
296 printf("Advertise Info\n");
297 printf("--------------\n\n");
298 printf("magic = %x\n", avt->magic);
299 printf("%s = %s\n", type, avt->bufA);
300 if (avt->magic == 0xa0000006)
302 char comp_str[40];
303 const char *feat, *comp, *prod_str, *feat_str;
304 GUID guid;
306 if (base85_to_guid(avt->bufA, &guid))
307 prod_str = get_guid_str( &guid );
308 else
309 prod_str = "?";
311 comp = &avt->bufA[20];
312 feat = strchr(comp,'>');
313 if (!feat)
314 feat = strchr(comp,'<');
315 if (feat)
317 memcpy( comp_str, comp, feat - comp );
318 comp_str[feat-comp] = 0;
320 else
322 strcpy( comp_str, "?" );
325 if (feat && feat[0] == '>' && base85_to_guid( &feat[1], &guid ))
326 feat_str = get_guid_str( &guid );
327 else
328 feat_str = "";
330 printf(" product: %s\n", prod_str);
331 printf(" component: %s\n", comp_str );
332 printf(" feature: %s\n", feat_str);
334 printf("\n");
336 return 0;
339 static const GUID CLSID_ShellLink = {0x00021401L, 0, 0, {0xC0,0,0,0,0,0,0,0x46}};
341 enum FileSig get_kind_lnk(void)
343 const LINK_HEADER* hdr;
345 hdr = PRD(0, sizeof(*hdr));
346 if (hdr && hdr->dwSize == sizeof(LINK_HEADER) &&
347 !memcmp(&hdr->MagicGuid, &CLSID_ShellLink, sizeof(GUID)))
348 return SIG_LNK;
349 return SIG_UNKNOWN;
352 void lnk_dump(void)
354 const LINK_HEADER* hdr;
356 offset = 0;
357 hdr = fetch_block();
359 printf("Header\n");
360 printf("------\n\n");
361 printf("Size: %04x\n", hdr->dwSize);
362 printf("GUID: %s\n", get_guid_str(&hdr->MagicGuid));
364 printf("FileAttr: %08x\n", hdr->dwFileAttr);
365 printf("FileLength: %08x\n", hdr->dwFileLength);
366 printf("nIcon: %d\n", hdr->nIcon);
367 printf("Startup: %d\n", hdr->fStartup);
368 printf("HotKey: %08x\n", hdr->wHotKey);
369 printf("Unknown5: %08x\n", hdr->Unknown5);
370 printf("Unknown6: %08x\n", hdr->Unknown6);
372 /* dump out all the flags */
373 printf("Flags: %04x ( ", hdr->dwFlags);
374 #define FLAG(x) if(hdr->dwFlags & SLDF_##x) printf("%s ",#x)
375 FLAG(HAS_ID_LIST);
376 FLAG(HAS_LINK_INFO);
377 FLAG(HAS_NAME);
378 FLAG(HAS_RELPATH);
379 FLAG(HAS_WORKINGDIR);
380 FLAG(HAS_ARGS);
381 FLAG(HAS_ICONLOCATION);
382 FLAG(UNICODE);
383 FLAG(FORCE_NO_LINKINFO);
384 FLAG(HAS_EXP_SZ);
385 FLAG(RUN_IN_SEPARATE);
386 FLAG(HAS_LOGO3ID);
387 FLAG(HAS_DARWINID);
388 FLAG(RUNAS_USER);
389 FLAG(HAS_EXP_ICON_SZ);
390 FLAG(NO_PIDL_ALIAS);
391 FLAG(FORCE_UNCNAME);
392 FLAG(RUN_WITH_SHIMLAYER);
393 FLAG(FORCE_NO_LINKTRACK);
394 FLAG(ENABLE_TARGET_METADATA);
395 FLAG(DISABLE_KNOWNFOLDER_RELATIVE_TRACKING);
396 FLAG(RESERVED);
397 #undef FLAG
398 printf(")\n");
400 printf("Length: %04x\n", hdr->dwFileLength);
401 printf("\n");
403 if (hdr->dwFlags & SLDF_HAS_ID_LIST)
404 dump_pidl();
405 if (hdr->dwFlags & SLDF_HAS_LINK_INFO)
406 dump_location();
407 if (hdr->dwFlags & SLDF_HAS_NAME)
408 dump_string("Description", hdr->dwFlags & SLDF_UNICODE);
409 if (hdr->dwFlags & SLDF_HAS_RELPATH)
410 dump_string("Relative path", hdr->dwFlags & SLDF_UNICODE);
411 if (hdr->dwFlags & SLDF_HAS_WORKINGDIR)
412 dump_string("Working directory", hdr->dwFlags & SLDF_UNICODE);
413 if (hdr->dwFlags & SLDF_HAS_ARGS)
414 dump_string("Arguments", hdr->dwFlags & SLDF_UNICODE);
415 if (hdr->dwFlags & SLDF_HAS_ICONLOCATION)
416 dump_string("Icon path", hdr->dwFlags & SLDF_UNICODE);
417 if (hdr->dwFlags & SLDF_HAS_LOGO3ID)
418 dump_advertise_info("product");
419 if (hdr->dwFlags & SLDF_HAS_DARWINID)
420 dump_advertise_info("msi string");