version: Avoid size_t type in traces.
[wine/dibdrv.git] / tools / winedump / lnk.c
blob661e48dffffa31388efb44064daff2d8451538a7
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 const void* fetch_block(void)
111 const unsigned* u;
112 const void* ret;
114 if (!(u = PRD(offset, sizeof(*u)))) return 0;
115 if ((ret = PRD(offset, *u))) offset += *u;
116 return ret;
119 static const lnk_string* fetch_string(int unicode)
121 const unsigned short* s;
122 unsigned short len;
123 const void* ret;
125 if (!(s = PRD(offset, sizeof(*s)))) return 0;
126 len = *s * (unicode ? sizeof(WCHAR) : sizeof(char));
127 if ((ret = PRD(offset, sizeof(*s) + len))) offset += sizeof(*s) + len;
128 return ret;
132 static int dump_pidl(void)
134 const lnk_string *pidl;
135 int i, n = 0, sz = 0;
137 pidl = fetch_string(FALSE);
138 if (!pidl)
139 return -1;
141 printf("PIDL\n");
142 printf("----\n\n");
144 while(sz<pidl->size)
146 lnk_string *segment = (lnk_string*) &pidl->str.a[sz];
148 if(!segment->size)
149 break;
150 sz+=segment->size;
151 if(sz>pidl->size)
153 printf("bad pidl\n");
154 break;
156 n++;
157 printf("segment %d (%2d bytes) : ",n,segment->size);
158 for(i=0; i<segment->size; i++)
159 printf("%02x ",segment->str.a[i]);
160 printf("\n");
162 printf("\n");
164 return 0;
167 static int dump_string(const char *what, int unicode)
169 const lnk_string *data;
170 unsigned sz;
172 data = fetch_string(unicode);
173 if (!data)
174 return -1;
175 printf("%s : ", what);
176 sz = data->size;
177 if (unicode)
178 while (sz) printf("%c", data->str.w[data->size - sz--]);
179 else
180 while (sz) printf("%c", data->str.a[data->size - sz--]);
181 printf("\n");
183 return 0;
186 static int dump_location(void)
188 const LOCATION_INFO *loc;
189 const char *p;
191 loc = fetch_block();
192 if (!loc)
193 return -1;
194 p = (const char*)loc;
196 printf("Location\n");
197 printf("--------\n\n");
198 printf("Total size = %d\n", loc->dwTotalSize);
199 printf("Header size = %d\n", loc->dwHeaderSize);
200 printf("Flags = %08x\n", loc->dwFlags);
202 /* dump out information about the volume the link points to */
203 printf("Volume ofs = %08x ", loc->dwVolTableOfs);
204 if (loc->dwVolTableOfs && (loc->dwVolTableOfs<loc->dwTotalSize))
206 const LOCAL_VOLUME_INFO *vol = (const LOCAL_VOLUME_INFO *)&p[loc->dwVolTableOfs];
208 printf("size %d type %d serial %08x label %d ",
209 vol->dwSize, vol->dwType, vol->dwVolSerial, vol->dwVolLabelOfs);
210 if(vol->dwVolLabelOfs)
211 printf("(\"%s\")", &p[loc->dwVolTableOfs + vol->dwVolLabelOfs]);
213 printf("\n");
215 /* dump out the path the link points to */
216 printf("LocalPath ofs = %08x ", loc->dwLocalPathOfs);
217 if( loc->dwLocalPathOfs && (loc->dwLocalPathOfs < loc->dwTotalSize) )
218 printf("(\"%s\")", &p[loc->dwLocalPathOfs]);
219 printf("\n");
221 printf("Net Path ofs = %08x\n", loc->dwNetworkVolTableOfs);
222 printf("Final Path = %08x ", loc->dwFinalPathOfs);
223 if( loc->dwFinalPathOfs && (loc->dwFinalPathOfs < loc->dwTotalSize) )
224 printf("(\"%s\")", &p[loc->dwFinalPathOfs]);
225 printf("\n");
226 printf("\n");
228 return 0;
231 static const unsigned char table_dec85[0x80] = {
232 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
233 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
234 0xff,0x00,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff,
235 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0xff,0xff,0xff,0x16,0xff,0x17,
236 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
237 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0xff,0x34,0x35,0x36,
238 0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,
239 0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0xff,0x53,0x54,0xff,
242 static int base85_to_guid( const char *str, LPGUID guid )
244 DWORD i, val = 0, base = 1, *p;
245 unsigned char ch;
247 p = (DWORD*) guid;
248 for( i=0; i<20; i++ )
250 if( (i%5) == 0 )
252 val = 0;
253 base = 1;
255 ch = str[i];
256 if( ch >= 0x80 )
257 return 0;
258 val += table_dec85[ch] * base;
259 if( table_dec85[ch] == 0xff )
260 return 0;
261 if( (i%5) == 4 )
262 p[i/5] = val;
263 base *= 85;
265 return 1;
268 static int dump_advertise_info(const char *type)
270 const LINK_ADVERTISEINFO *avt;
272 avt = fetch_block();
273 if (!avt)
274 return -1;
276 printf("Advertise Info\n");
277 printf("--------------\n\n");
278 printf("magic = %x\n", avt->magic);
279 printf("%s = %s\n", type, avt->bufA);
280 if (avt->magic == 0xa0000006)
282 char comp_str[40];
283 const char *feat, *comp, *prod_str, *feat_str;
284 GUID guid;
286 if (base85_to_guid(avt->bufA, &guid))
287 prod_str = get_guid_str( &guid );
288 else
289 prod_str = "?";
291 comp = &avt->bufA[20];
292 feat = strchr(comp,'>');
293 if (!feat)
294 feat = strchr(comp,'<');
295 if (feat)
297 memcpy( comp_str, comp, feat - comp );
298 comp_str[feat-comp] = 0;
300 else
302 strcpy( comp_str, "?" );
305 if (feat && feat[0] == '>' && base85_to_guid( &feat[1], &guid ))
306 feat_str = get_guid_str( &guid );
307 else
308 feat_str = "";
310 printf(" product: %s\n", prod_str);
311 printf(" component: %s\n", comp_str );
312 printf(" feature: %s\n", feat_str);
314 printf("\n");
316 return 0;
319 static const GUID CLSID_ShellLink = {0x00021401L, 0, 0, {0xC0,0,0,0,0,0,0,0x46}};
321 enum FileSig get_kind_lnk(void)
323 const LINK_HEADER* hdr;
325 hdr = PRD(0, sizeof(*hdr));
326 if (hdr && hdr->dwSize == sizeof(LINK_HEADER) &&
327 !memcmp(&hdr->MagicGuid, &CLSID_ShellLink, sizeof(GUID)))
328 return SIG_LNK;
329 return SIG_UNKNOWN;
332 void lnk_dump(void)
334 const LINK_HEADER* hdr;
336 offset = 0;
337 hdr = fetch_block();
339 printf("Header\n");
340 printf("------\n\n");
341 printf("Size: %04x\n", hdr->dwSize);
342 printf("GUID: %s\n", get_guid_str(&hdr->MagicGuid));
344 printf("FileAttr: %08x\n", hdr->dwFileAttr);
345 printf("FileLength: %08x\n", hdr->dwFileLength);
346 printf("nIcon: %d\n", hdr->nIcon);
347 printf("Startup: %d\n", hdr->fStartup);
348 printf("HotKey: %08x\n", hdr->wHotKey);
349 printf("Unknown5: %08x\n", hdr->Unknown5);
350 printf("Unknown6: %08x\n", hdr->Unknown6);
352 /* dump out all the flags */
353 printf("Flags: %04x ( ", hdr->dwFlags);
354 #define FLAG(x) if(hdr->dwFlags & SCF_##x) printf("%s ",#x);
355 FLAG(PIDL)
356 FLAG(LOCATION)
357 FLAG(DESCRIPTION)
358 FLAG(RELATIVE)
359 FLAG(WORKDIR)
360 FLAG(ARGS)
361 FLAG(CUSTOMICON)
362 FLAG(UNICODE)
363 FLAG(PRODUCT)
364 FLAG(COMPONENT)
365 #undef FLAG
366 printf(")\n");
368 printf("Length: %04x\n", hdr->dwFileLength);
369 printf("\n");
371 if (hdr->dwFlags & SCF_PIDL)
372 dump_pidl();
373 if (hdr->dwFlags & SCF_LOCATION)
374 dump_location();
375 if (hdr->dwFlags & SCF_DESCRIPTION)
376 dump_string("Description", hdr->dwFlags & SCF_UNICODE);
377 if (hdr->dwFlags & SCF_RELATIVE)
378 dump_string("Relative path", hdr->dwFlags & SCF_UNICODE);
379 if (hdr->dwFlags & SCF_WORKDIR)
380 dump_string("Working directory", hdr->dwFlags & SCF_UNICODE);
381 if (hdr->dwFlags & SCF_ARGS)
382 dump_string("Arguments", hdr->dwFlags & SCF_UNICODE);
383 if (hdr->dwFlags & SCF_CUSTOMICON)
384 dump_string("Icon path", hdr->dwFlags & SCF_UNICODE);
385 if (hdr->dwFlags & SCF_PRODUCT)
386 dump_advertise_info("product");
387 if (hdr->dwFlags & SCF_COMPONENT)
388 dump_advertise_info("msi string");