winedump: Cast-qual warnings fix.
[wine/gsoc_dplay.git] / tools / winedump / lnk.c
blob13f3542847d27b5528b273d6870906f8efd255dc
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 #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
98 unsigned short size;
99 union {
100 unsigned short w[1];
101 unsigned char a[1];
102 } str;
103 } lnk_string;
105 #include "poppack.h"
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)
119 const unsigned* u;
120 const void* ret;
122 if (!(u = PRD(offset, sizeof(*u)))) return 0;
123 if ((ret = PRD(offset, *u))) offset += *u;
124 return ret;
127 static const lnk_string* fetch_string(int unicode)
129 const unsigned short* s;
130 unsigned short len;
131 const void* ret;
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;
136 return ret;
140 static int dump_pidl(void)
142 const lnk_string *pidl;
143 int i, n = 0, sz = 0;
145 pidl = fetch_string(FALSE);
146 if (!pidl)
147 return -1;
149 printf("PIDL\n");
150 printf("----\n\n");
152 while(sz<pidl->size)
154 lnk_string *segment = (lnk_string*) &pidl->str.a[sz];
156 if(!segment->size)
157 break;
158 sz+=segment->size;
159 if(sz>pidl->size)
161 printf("bad pidl\n");
162 break;
164 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]);
168 printf("\n");
170 printf("\n");
172 return 0;
175 static int dump_string(const char *what, int unicode)
177 const lnk_string *data;
178 unsigned sz;
180 data = fetch_string(unicode);
181 if (!data)
182 return -1;
183 printf("%s : ", what);
184 sz = data->size;
185 if (unicode)
186 while (sz) printf("%c", data->str.w[data->size - sz--]);
187 else
188 while (sz) printf("%c", data->str.a[data->size - sz--]);
189 printf("\n");
191 return 0;
194 static int dump_location(void)
196 const LOCATION_INFO *loc;
197 const char *p;
199 loc = fetch_block();
200 if (!loc)
201 return -1;
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]);
221 printf("\n");
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]);
227 printf("\n");
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]);
233 printf("\n");
234 printf("\n");
236 return 0;
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;
253 unsigned char ch;
255 p = (DWORD*) guid;
256 for( i=0; i<20; i++ )
258 if( (i%5) == 0 )
260 val = 0;
261 base = 1;
263 ch = str[i];
264 if( ch >= 0x80 )
265 return 0;
266 val += table_dec85[ch] * base;
267 if( table_dec85[ch] == 0xff )
268 return 0;
269 if( (i%5) == 4 )
270 p[i/5] = val;
271 base *= 85;
273 return 1;
276 static int dump_advertise_info(const char *type)
278 const LINK_ADVERTISEINFO *avt;
280 avt = fetch_block();
281 if (!avt)
282 return -1;
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;
292 GUID guid;
294 if (base85_to_guid(avt->bufA, &guid))
295 guid_to_string( &guid, prod_str );
296 else
297 strcpy( prod_str, "?" );
299 comp = &avt->bufA[20];
300 feat = strchr(comp,'>');
301 if (!feat)
302 feat = strchr(comp,'<');
303 if (feat)
305 memcpy( comp_str, comp, feat - comp );
306 comp_str[feat-comp] = 0;
308 else
310 strcpy( comp_str, "?" );
313 if (feat && feat[0] == '>' && base85_to_guid( &feat[1], &guid ))
314 guid_to_string( &guid, feat_str );
315 else
316 feat_str[0] = 0;
318 printf(" product: %s\n", prod_str);
319 printf(" component: %s\n", comp_str );
320 printf(" feature: %s\n", feat_str);
322 printf("\n");
324 return 0;
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)))
336 return SIG_LNK;
337 return SIG_UNKNOWN;
340 void lnk_dump(void)
342 const LINK_HEADER* hdr;
343 char guid[40];
345 offset = 0;
346 hdr = fetch_block();
348 guid_to_string(&hdr->MagicGuid, guid);
350 printf("Header\n");
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);
366 FLAG(PIDL)
367 FLAG(LOCATION)
368 FLAG(DESCRIPTION)
369 FLAG(RELATIVE)
370 FLAG(WORKDIR)
371 FLAG(ARGS)
372 FLAG(CUSTOMICON)
373 FLAG(UNICODE)
374 FLAG(PRODUCT)
375 FLAG(COMPONENT)
376 #undef FLAG
377 printf(")\n");
379 printf("Length: %04x\n", hdr->dwFileLength);
380 printf("\n");
382 if (hdr->dwFlags & SCF_PIDL)
383 dump_pidl();
384 if (hdr->dwFlags & SCF_LOCATION)
385 dump_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");