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
22 #include "wine/port.h"
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
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 #define EXP_SZ_LINK_SIG 0xa0000001
67 #define EXP_SPECIAL_FOLDER_SIG 0xa0000005
68 #define EXP_DARWIN_ID_SIG 0xa0000006
69 #define EXP_SZ_ICON_SIG 0xa0000007
71 typedef struct tagDATABLOCKHEADER
77 typedef struct _LINK_HEADER
79 DWORD dwSize; /* 0x00 size of the header - 0x4c */
80 GUID MagicGuid; /* 0x04 is CLSID_ShellLink */
81 DWORD dwFlags; /* 0x14 describes elements following */
82 DWORD dwFileAttr; /* 0x18 attributes of the target file */
83 FILETIME Time1; /* 0x1c */
84 FILETIME Time2; /* 0x24 */
85 FILETIME Time3; /* 0x2c */
86 DWORD dwFileLength; /* 0x34 File length */
87 DWORD nIcon; /* 0x38 icon number */
88 DWORD fStartup; /* 0x3c startup type */
89 DWORD wHotKey; /* 0x40 hotkey */
90 DWORD Unknown5; /* 0x44 */
91 DWORD Unknown6; /* 0x48 */
92 } LINK_HEADER, * PLINK_HEADER;
94 typedef struct tagLINK_SZ_BLOCK
102 typedef struct _LOCATION_INFO
108 DWORD dwLocalPathOfs;
109 DWORD dwNetworkVolTableOfs;
110 DWORD dwFinalPathOfs;
113 typedef struct _LOCAL_VOLUME_INFO
121 typedef struct _NETWORK_VOLUME_INFO
125 DWORD dwShareNameOfs;
128 } NETWORK_VOLUME_INFO;
134 DWORD idSpecialFolder;
136 } EXP_SPECIAL_FOLDER;
138 typedef struct lnk_string_tag
149 static unsigned offset;
151 static const void* fetch_block(void)
156 if (!(u = PRD(offset, sizeof(*u)))) return 0;
157 if ((ret = PRD(offset, *u))) offset += *u;
161 static const lnk_string* fetch_string(int unicode)
163 const unsigned short* s;
167 if (!(s = PRD(offset, sizeof(*s)))) return 0;
168 len = *s * (unicode ? sizeof(WCHAR) : sizeof(char));
169 if ((ret = PRD(offset, sizeof(*s) + len))) offset += sizeof(*s) + len;
174 static int dump_pidl(void)
176 const lnk_string *pidl;
177 int i, n = 0, sz = 0;
179 pidl = fetch_string(FALSE);
188 const lnk_string *segment = (const lnk_string*) &pidl->str.a[sz];
195 printf("bad pidl\n");
199 printf("segment %d (%2d bytes) : ",n,segment->size);
200 for(i=0; i<segment->size; i++)
201 printf("%02x ",segment->str.a[i]);
209 static int dump_string(const char *what, int unicode)
211 const lnk_string *data;
214 data = fetch_string(unicode);
217 printf("%s : ", what);
220 while (sz) printf("%c", data->str.w[data->size - sz--]);
222 while (sz) printf("%c", data->str.a[data->size - sz--]);
228 static int dump_location(void)
230 const LOCATION_INFO *loc;
236 p = (const char*)loc;
238 printf("Location\n");
239 printf("--------\n\n");
240 printf("Total size = %d\n", loc->dwTotalSize);
241 printf("Header size = %d\n", loc->dwHeaderSize);
242 printf("Flags = %08x\n", loc->dwFlags);
244 /* dump information about the local volume the link points to */
245 printf("Local volume ofs = %08x ", loc->dwVolTableOfs);
246 if (loc->dwVolTableOfs &&
247 loc->dwVolTableOfs + sizeof(LOCAL_VOLUME_INFO) < loc->dwTotalSize)
249 const LOCAL_VOLUME_INFO *vol = (const LOCAL_VOLUME_INFO *)&p[loc->dwVolTableOfs];
251 printf("size %d type %d serial %08x label %d ",
252 vol->dwSize, vol->dwType, vol->dwVolSerial, vol->dwVolLabelOfs);
253 if(vol->dwVolLabelOfs)
254 printf("(\"%s\")", &p[loc->dwVolTableOfs + vol->dwVolLabelOfs]);
258 /* dump information about the network volume the link points to */
259 printf("Network volume ofs = %08x ", loc->dwNetworkVolTableOfs);
260 if (loc->dwNetworkVolTableOfs &&
261 loc->dwNetworkVolTableOfs + sizeof(NETWORK_VOLUME_INFO) < loc->dwTotalSize)
263 const NETWORK_VOLUME_INFO *vol = (const NETWORK_VOLUME_INFO *)&p[loc->dwNetworkVolTableOfs];
265 printf("size %d name %d ", vol->dwSize, vol->dwShareNameOfs);
266 if(vol->dwShareNameOfs)
267 printf("(\"%s\")", &p[loc->dwNetworkVolTableOfs + vol->dwShareNameOfs]);
271 /* dump out the path the link points to */
272 printf("LocalPath ofs = %08x ", loc->dwLocalPathOfs);
273 if( loc->dwLocalPathOfs && (loc->dwLocalPathOfs < loc->dwTotalSize) )
274 printf("(\"%s\")", &p[loc->dwLocalPathOfs]);
277 printf("Net Path ofs = %08x\n", loc->dwNetworkVolTableOfs);
278 printf("Final Path = %08x ", loc->dwFinalPathOfs);
279 if( loc->dwFinalPathOfs && (loc->dwFinalPathOfs < loc->dwTotalSize) )
280 printf("(\"%s\")", &p[loc->dwFinalPathOfs]);
287 static const unsigned char table_dec85[0x80] = {
288 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
289 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
290 0xff,0x00,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff,
291 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0xff,0xff,0xff,0x16,0xff,0x17,
292 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
293 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0xff,0x34,0x35,0x36,
294 0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,
295 0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0xff,0x53,0x54,0xff,
298 static int base85_to_guid( const char *str, LPGUID guid )
300 DWORD i, val = 0, base = 1, *p;
304 for( i=0; i<20; i++ )
314 val += table_dec85[ch] * base;
315 if( table_dec85[ch] == 0xff )
324 static int dump_special_folder_block(const DATABLOCK_HEADER* bhdr)
326 const EXP_SPECIAL_FOLDER *sfb = (const EXP_SPECIAL_FOLDER*)bhdr;
327 printf("Special folder block\n");
328 printf("--------------------\n\n");
329 printf("folder = 0x%04x\n", sfb->idSpecialFolder);
330 printf("offset = %d\n", sfb->cbOffset);
335 static int dump_sz_block(const DATABLOCK_HEADER* bhdr, const char* label)
337 const LINK_SZ_BLOCK *szp = (const LINK_SZ_BLOCK*)bhdr;
338 printf("String block\n");
339 printf("-----------\n\n");
340 printf("magic = %x\n", szp->magic);
341 printf("%s = %s\n", label, szp->bufA);
346 static int dump_darwin_id(const DATABLOCK_HEADER* bhdr)
348 const LINK_SZ_BLOCK *szp = (const LINK_SZ_BLOCK*)bhdr;
350 const char *feat, *comp, *prod_str, *feat_str;
353 printf("Advertise Info\n");
354 printf("--------------\n\n");
355 printf("msi string = %s\n", szp->bufA);
357 if (base85_to_guid(szp->bufA, &guid))
358 prod_str = get_guid_str(&guid);
362 comp = &szp->bufA[20];
363 feat = strchr(comp, '>');
365 feat = strchr(comp, '<');
368 memcpy(comp_str, comp, feat - comp);
369 comp_str[feat-comp] = 0;
373 strcpy(comp_str, "?");
376 if (feat && feat[0] == '>' && base85_to_guid( &feat[1], &guid ))
377 feat_str = get_guid_str( &guid );
381 printf(" product: %s\n", prod_str);
382 printf(" component: %s\n", comp_str );
383 printf(" feature: %s\n", feat_str);
389 static int dump_raw_block(const DATABLOCK_HEADER* bhdr)
393 printf("Raw Block\n");
394 printf("---------\n\n");
395 printf("size = %d\n", bhdr->cbSize);
396 printf("magic = %x\n", bhdr->dwSignature);
398 data_size=bhdr->cbSize-sizeof(*bhdr);
402 const unsigned char *data;
405 data=(const unsigned char*)bhdr+sizeof(*bhdr);
406 while (data_size > 0)
408 for (i=0; i < 16; i++)
411 printf("%02x ", data[i]);
415 for (i=0; i < data_size && i < 16; i++)
416 printf("%c", (data[i] >= 32 && data[i] < 128 ? data[i] : '.'));
430 static const GUID CLSID_ShellLink = {0x00021401L, 0, 0, {0xC0,0,0,0,0,0,0,0x46}};
432 enum FileSig get_kind_lnk(void)
434 const LINK_HEADER* hdr;
436 hdr = PRD(0, sizeof(*hdr));
437 if (hdr && hdr->dwSize == sizeof(LINK_HEADER) &&
438 !memcmp(&hdr->MagicGuid, &CLSID_ShellLink, sizeof(GUID)))
445 const LINK_HEADER* hdr;
446 const DATABLOCK_HEADER* bhdr;
455 printf("------\n\n");
456 printf("Size: %04x\n", hdr->dwSize);
457 printf("GUID: %s\n", get_guid_str(&hdr->MagicGuid));
459 printf("FileAttr: %08x\n", hdr->dwFileAttr);
460 printf("FileLength: %08x\n", hdr->dwFileLength);
461 printf("nIcon: %d\n", hdr->nIcon);
462 printf("Startup: %d\n", hdr->fStartup);
463 printf("HotKey: %08x\n", hdr->wHotKey);
464 printf("Unknown5: %08x\n", hdr->Unknown5);
465 printf("Unknown6: %08x\n", hdr->Unknown6);
467 /* dump out all the flags */
468 printf("Flags: %04x ( ", hdr->dwFlags);
469 dwFlags=hdr->dwFlags;
472 if (dwFlags & SLDF_##x) \
475 dwFlags&=~SLDF_##x; \
482 FLAG(HAS_WORKINGDIR);
484 FLAG(HAS_ICONLOCATION);
486 FLAG(FORCE_NO_LINKINFO);
488 FLAG(RUN_IN_SEPARATE);
492 FLAG(HAS_EXP_ICON_SZ);
495 FLAG(RUN_WITH_SHIMLAYER);
496 FLAG(FORCE_NO_LINKTRACK);
497 FLAG(ENABLE_TARGET_METADATA);
498 FLAG(DISABLE_KNOWNFOLDER_RELATIVE_TRACKING);
502 printf("+%04x", dwFlags);
505 printf("Length: %04x\n", hdr->dwFileLength);
508 if (hdr->dwFlags & SLDF_HAS_ID_LIST)
510 if (hdr->dwFlags & SLDF_HAS_LINK_INFO)
512 if (hdr->dwFlags & SLDF_HAS_NAME)
513 dump_string("Description", hdr->dwFlags & SLDF_UNICODE);
514 if (hdr->dwFlags & SLDF_HAS_RELPATH)
515 dump_string("Relative path", hdr->dwFlags & SLDF_UNICODE);
516 if (hdr->dwFlags & SLDF_HAS_WORKINGDIR)
517 dump_string("Working directory", hdr->dwFlags & SLDF_UNICODE);
518 if (hdr->dwFlags & SLDF_HAS_ARGS)
519 dump_string("Arguments", hdr->dwFlags & SLDF_UNICODE);
520 if (hdr->dwFlags & SLDF_HAS_ICONLOCATION)
521 dump_string("Icon path", hdr->dwFlags & SLDF_UNICODE);
528 switch (bhdr->dwSignature)
530 case EXP_SZ_LINK_SIG:
531 dump_sz_block(bhdr, "exp.link");
533 case EXP_SPECIAL_FOLDER_SIG:
534 dump_special_folder_block(bhdr);
536 case EXP_SZ_ICON_SIG:
537 dump_sz_block(bhdr, "icon");
539 case EXP_DARWIN_ID_SIG:
540 dump_darwin_id(bhdr);
543 dump_raw_block(bhdr);