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 #define SCF_LOCATION 2
43 #define SCF_DESCRIPTION 4
44 #define SCF_RELATIVE 8
45 #define SCF_WORKDIR 0x10
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
77 typedef struct _LOCATION_INFO
84 DWORD dwNetworkVolTableOfs
;
88 typedef struct _LOCAL_VOLUME_INFO
96 typedef struct lnk_string_tag
107 static unsigned offset
;
109 static void guid_to_string(const GUID
* guid
, char *str
)
111 sprintf(str
, "{%08x-%04x-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X}",
112 guid
->Data1
, guid
->Data2
, guid
->Data3
,
113 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
114 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
117 static const void* fetch_block(void)
122 if (!(u
= PRD(offset
, sizeof(*u
)))) return 0;
123 if ((ret
= PRD(offset
, *u
))) offset
+= *u
;
127 static const lnk_string
* fetch_string(int unicode
)
129 const unsigned short* s
;
133 if (!(s
= PRD(offset
, sizeof(*s
)))) return 0;
134 len
= *s
* (unicode
? sizeof(WCHAR
) : sizeof(char));
135 if ((ret
= PRD(offset
, sizeof(*s
) + len
))) offset
+= sizeof(*s
) + len
;
140 static int dump_pidl(void)
142 const lnk_string
*pidl
;
143 int i
, n
= 0, sz
= 0;
145 pidl
= fetch_string(FALSE
);
154 lnk_string
*segment
= (lnk_string
*) &pidl
->str
.a
[sz
];
161 printf("bad pidl\n");
165 printf("segment %d (%2d bytes) : ",n
,segment
->size
);
166 for(i
=0; i
<segment
->size
; i
++)
167 printf("%02x ",segment
->str
.a
[i
]);
175 static int dump_string(const char *what
, int unicode
)
177 const lnk_string
*data
;
180 data
= fetch_string(unicode
);
183 printf("%s : ", what
);
186 while (sz
) printf("%c", data
->str
.w
[data
->size
- sz
--]);
188 while (sz
) printf("%c", data
->str
.a
[data
->size
- sz
--]);
194 static int dump_location(void)
196 const LOCATION_INFO
*loc
;
202 p
= (const char*)loc
;
204 printf("Location\n");
205 printf("--------\n\n");
206 printf("Total size = %d\n", loc
->dwTotalSize
);
207 printf("Header size = %d\n", loc
->dwHeaderSize
);
208 printf("Flags = %08x\n", loc
->dwFlags
);
210 /* dump out information about the volume the link points to */
211 printf("Volume ofs = %08x ", loc
->dwVolTableOfs
);
212 if (loc
->dwVolTableOfs
&& (loc
->dwVolTableOfs
<loc
->dwTotalSize
))
214 const LOCAL_VOLUME_INFO
*vol
= (const LOCAL_VOLUME_INFO
*)&p
[loc
->dwVolTableOfs
];
216 printf("size %d type %d serial %08x label %d ",
217 vol
->dwSize
, vol
->dwType
, vol
->dwVolSerial
, vol
->dwVolLabelOfs
);
218 if(vol
->dwVolLabelOfs
)
219 printf("(\"%s\")", &p
[loc
->dwVolTableOfs
+ vol
->dwVolLabelOfs
]);
223 /* dump out the path the link points to */
224 printf("LocalPath ofs = %08x ", loc
->dwLocalPathOfs
);
225 if( loc
->dwLocalPathOfs
&& (loc
->dwLocalPathOfs
< loc
->dwTotalSize
) )
226 printf("(\"%s\")", &p
[loc
->dwLocalPathOfs
]);
229 printf("Net Path ofs = %08x\n", loc
->dwNetworkVolTableOfs
);
230 printf("Final Path = %08x ", loc
->dwFinalPathOfs
);
231 if( loc
->dwFinalPathOfs
&& (loc
->dwFinalPathOfs
< loc
->dwTotalSize
) )
232 printf("(\"%s\")", &p
[loc
->dwFinalPathOfs
]);
239 static const unsigned char table_dec85
[0x80] = {
240 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
241 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
242 0xff,0x00,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff,
243 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0xff,0xff,0xff,0x16,0xff,0x17,
244 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
245 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0xff,0x34,0x35,0x36,
246 0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,
247 0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0xff,0x53,0x54,0xff,
250 static int base85_to_guid( const char *str
, LPGUID guid
)
252 DWORD i
, val
= 0, base
= 1, *p
;
256 for( i
=0; i
<20; i
++ )
266 val
+= table_dec85
[ch
] * base
;
267 if( table_dec85
[ch
] == 0xff )
276 static int dump_advertise_info(const char *type
)
278 const LINK_ADVERTISEINFO
*avt
;
284 printf("Advertise Info\n");
285 printf("--------------\n\n");
286 printf("magic = %x\n", avt
->magic
);
287 printf("%s = %s\n", type
, avt
->bufA
);
288 if (avt
->magic
== 0xa0000006)
290 char prod_str
[40], comp_str
[40], feat_str
[40];
291 const char *feat
, *comp
;
294 if (base85_to_guid(avt
->bufA
, &guid
))
295 guid_to_string( &guid
, prod_str
);
297 strcpy( prod_str
, "?" );
299 comp
= &avt
->bufA
[20];
300 feat
= strchr(comp
,'>');
302 feat
= strchr(comp
,'<');
305 memcpy( comp_str
, comp
, feat
- comp
);
306 comp_str
[feat
-comp
] = 0;
310 strcpy( comp_str
, "?" );
313 if (feat
&& feat
[0] == '>' && base85_to_guid( &feat
[1], &guid
))
314 guid_to_string( &guid
, feat_str
);
318 printf(" product: %s\n", prod_str
);
319 printf(" component: %s\n", comp_str
);
320 printf(" feature: %s\n", feat_str
);
327 static const GUID CLSID_ShellLink
= {0x00021401L
, 0, 0, {0xC0,0,0,0,0,0,0,0x46}};
329 enum FileSig
get_kind_lnk(void)
331 const LINK_HEADER
* hdr
;
333 hdr
= PRD(0, sizeof(*hdr
));
334 if (hdr
&& hdr
->dwSize
== sizeof(LINK_HEADER
) &&
335 !memcmp(&hdr
->MagicGuid
, &CLSID_ShellLink
, sizeof(GUID
)))
342 const LINK_HEADER
* hdr
;
348 guid_to_string(&hdr
->MagicGuid
, guid
);
351 printf("------\n\n");
352 printf("Size: %04x\n", hdr
->dwSize
);
353 printf("GUID: %s\n", guid
);
355 printf("FileAttr: %08x\n", hdr
->dwFileAttr
);
356 printf("FileLength: %08x\n", hdr
->dwFileLength
);
357 printf("nIcon: %d\n", hdr
->nIcon
);
358 printf("Startup: %d\n", hdr
->fStartup
);
359 printf("HotKey: %08x\n", hdr
->wHotKey
);
360 printf("Unknown5: %08x\n", hdr
->Unknown5
);
361 printf("Unknown6: %08x\n", hdr
->Unknown6
);
363 /* dump out all the flags */
364 printf("Flags: %04x ( ", hdr
->dwFlags
);
365 #define FLAG(x) if(hdr->dwFlags & SCF_##x) printf("%s ",#x);
379 printf("Length: %04x\n", hdr
->dwFileLength
);
382 if (hdr
->dwFlags
& SCF_PIDL
)
384 if (hdr
->dwFlags
& SCF_LOCATION
)
386 if (hdr
->dwFlags
& SCF_DESCRIPTION
)
387 dump_string("Description", hdr
->dwFlags
& SCF_UNICODE
);
388 if (hdr
->dwFlags
& SCF_RELATIVE
)
389 dump_string("Relative path", hdr
->dwFlags
& SCF_UNICODE
);
390 if (hdr
->dwFlags
& SCF_WORKDIR
)
391 dump_string("Working directory", hdr
->dwFlags
& SCF_UNICODE
);
392 if (hdr
->dwFlags
& SCF_ARGS
)
393 dump_string("Arguments", hdr
->dwFlags
& SCF_UNICODE
);
394 if (hdr
->dwFlags
& SCF_CUSTOMICON
)
395 dump_string("Icon path", hdr
->dwFlags
& SCF_UNICODE
);
396 if (hdr
->dwFlags
& SCF_PRODUCT
)
397 dump_advertise_info("product");
398 if (hdr
->dwFlags
& SCF_COMPONENT
)
399 dump_advertise_info("msi string");