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
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
{
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
)
119 unsigned short size
= 0;
121 r
= read( fd
, &size
, sizeof size
);
122 if (r
!= sizeof size
)
124 if (size
<sizeof size
)
127 data
= malloc(size
+ sizeof size
);
128 memcpy(data
, &size
, sizeof size
);
129 r
= read( fd
, data
+ sizeof size
, size
);
138 /* size is an integer */
139 static void* load_long_section(int fd
)
144 r
= read( fd
, &size
, sizeof size
);
145 if (r
!= sizeof size
)
147 if (size
<sizeof size
)
151 memcpy(data
, &size
, sizeof size
);
152 r
= read( fd
, data
+ sizeof size
, size
- sizeof size
);
153 if (r
!= (size
- sizeof size
))
161 /* the size is a character count in a short integer */
162 static lnk_string
* load_string(int fd
, int unicode
)
166 unsigned short size
= 0, bytesize
;
168 r
= read( fd
, &size
, sizeof size
);
169 if (r
!= sizeof size
)
176 bytesize
*= sizeof(WCHAR
);
177 data
= malloc(sizeof *data
+ bytesize
);
180 data
->str
.w
[size
] = 0;
182 data
->str
.a
[size
] = 0;
183 r
= read(fd
, &data
->str
, bytesize
);
193 static int dump_pidl(int fd
)
196 int i
, n
= 0, sz
= 0;
198 pidl
= load_pidl(fd
);
207 lnk_string
*segment
= (lnk_string
*) &pidl
->str
.a
[sz
];
214 printf("bad pidl\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
]);
230 static void print_unicode_string(const unsigned short *str
)
240 static int dump_string(int fd
, const char *what
, int unicode
)
244 data
= load_string(fd
, unicode
);
247 printf("%s : ", what
);
249 print_unicode_string(data
->str
.w
);
251 printf("%s",data
->str
.a
);
257 static int dump_location(int fd
)
262 loc
= load_long_section(fd
);
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
]);
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
]);
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
]);
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
;
321 for( i
=0; i
<20; i
++ )
331 val
+= table_dec85
[ch
] * base
;
332 if( table_dec85
[ch
] == 0xff )
341 static int dump_advertise_info(int fd
, const char *type
)
343 LINK_ADVERTISEINFO
*avt
;
345 avt
= load_long_section(fd
);
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];
359 if (base85_to_guid(avt
->bufA
, &guid
))
360 guid_to_string( &guid
, prod_str
);
362 strcpy( prod_str
, "?" );
364 comp
= &avt
->bufA
[20];
365 feat
= strchr(comp
,'>');
367 memcpy( comp_str
, comp
, feat
- comp
);
369 strcpy( prod_str
, "?" );
371 if (feat
&& base85_to_guid( &feat
[1], &guid
))
372 guid_to_string( &guid
, feat_str
);
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
);
385 static int dump_lnk_fd(int fd
)
390 hdr
= load_long_section( fd
);
394 guid_to_string(&hdr
->MagicGuid
, guid
);
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);
417 printf("Length: %04lx\n", hdr
->dwFileLength
);
420 if (hdr
->dwFlags
& SCF_PIDL
)
422 if (hdr
->dwFlags
& SCF_LOCATION
)
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");
442 int dump_lnk(const char *emf
)
446 fd
= open(emf
,O_RDONLY
);