lnk.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. /*
  2. * Dump a shortcut (lnk) file
  3. *
  4. * Copyright 2005 Mike McCormack
  5. *
  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.
  10. *
  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.
  15. *
  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
  19. */
  20. #include "config.h"
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <stdarg.h>
  24. #include <fcntl.h>
  25. #include "windef.h"
  26. #include "winbase.h"
  27. #include "winedump.h"
  28. #include "pshpack1.h"
  29. typedef enum {
  30. SLDF_HAS_ID_LIST = 0x00000001,
  31. SLDF_HAS_LINK_INFO = 0x00000002,
  32. SLDF_HAS_NAME = 0x00000004,
  33. SLDF_HAS_RELPATH = 0x00000008,
  34. SLDF_HAS_WORKINGDIR = 0x00000010,
  35. SLDF_HAS_ARGS = 0x00000020,
  36. SLDF_HAS_ICONLOCATION = 0x00000040,
  37. SLDF_UNICODE = 0x00000080,
  38. SLDF_FORCE_NO_LINKINFO = 0x00000100,
  39. SLDF_HAS_EXP_SZ = 0x00000200,
  40. SLDF_RUN_IN_SEPARATE = 0x00000400,
  41. SLDF_HAS_LOGO3ID = 0x00000800,
  42. SLDF_HAS_DARWINID = 0x00001000,
  43. SLDF_RUNAS_USER = 0x00002000,
  44. SLDF_HAS_EXP_ICON_SZ = 0x00004000,
  45. SLDF_NO_PIDL_ALIAS = 0x00008000,
  46. SLDF_FORCE_UNCNAME = 0x00010000,
  47. SLDF_RUN_WITH_SHIMLAYER = 0x00020000,
  48. SLDF_FORCE_NO_LINKTRACK = 0x00040000,
  49. SLDF_ENABLE_TARGET_METADATA = 0x00080000,
  50. SLDF_DISABLE_KNOWNFOLDER_RELATIVE_TRACKING = 0x00200000,
  51. SLDF_RESERVED = 0x80000000,
  52. } SHELL_LINK_DATA_FLAGS;
  53. #define EXP_SZ_LINK_SIG 0xa0000001
  54. #define EXP_SPECIAL_FOLDER_SIG 0xa0000005
  55. #define EXP_DARWIN_ID_SIG 0xa0000006
  56. #define EXP_SZ_ICON_SIG 0xa0000007
  57. #define EXP_PROPERTYSTORAGE_SIG 0xa0000009
  58. typedef struct tagDATABLOCKHEADER
  59. {
  60. DWORD cbSize;
  61. DWORD dwSignature;
  62. } DATABLOCK_HEADER;
  63. typedef struct _LINK_HEADER
  64. {
  65. DWORD dwSize; /* 0x00 size of the header - 0x4c */
  66. GUID MagicGuid; /* 0x04 is CLSID_ShellLink */
  67. DWORD dwFlags; /* 0x14 describes elements following */
  68. DWORD dwFileAttr; /* 0x18 attributes of the target file */
  69. FILETIME Time1; /* 0x1c */
  70. FILETIME Time2; /* 0x24 */
  71. FILETIME Time3; /* 0x2c */
  72. DWORD dwFileLength; /* 0x34 File length */
  73. DWORD nIcon; /* 0x38 icon number */
  74. DWORD fStartup; /* 0x3c startup type */
  75. DWORD wHotKey; /* 0x40 hotkey */
  76. DWORD Unknown5; /* 0x44 */
  77. DWORD Unknown6; /* 0x48 */
  78. } LINK_HEADER, * PLINK_HEADER;
  79. typedef struct tagLINK_SZ_BLOCK
  80. {
  81. DWORD size;
  82. DWORD magic;
  83. CHAR bufA[MAX_PATH];
  84. WCHAR bufW[MAX_PATH];
  85. } LINK_SZ_BLOCK;
  86. typedef struct tagLINK_PROPERTYSTORAGE_GUID
  87. {
  88. DWORD size;
  89. DWORD magic;
  90. GUID fmtid;
  91. } LINK_PROPERTYSTORAGE_GUID;
  92. typedef struct tagLINK_PROPERTYSTORAGE_VALUE
  93. {
  94. DWORD size;
  95. DWORD pid;
  96. BYTE unknown8;
  97. DWORD vt;
  98. DWORD unknown25;
  99. } LINK_PROPERTYSTORAGE_VALUE;
  100. typedef struct _LOCATION_INFO
  101. {
  102. DWORD dwTotalSize;
  103. DWORD dwHeaderSize;
  104. DWORD dwFlags;
  105. DWORD dwVolTableOfs;
  106. DWORD dwLocalPathOfs;
  107. DWORD dwNetworkVolTableOfs;
  108. DWORD dwFinalPathOfs;
  109. } LOCATION_INFO;
  110. typedef struct _LOCAL_VOLUME_INFO
  111. {
  112. DWORD dwSize;
  113. DWORD dwType;
  114. DWORD dwVolSerial;
  115. DWORD dwVolLabelOfs;
  116. } LOCAL_VOLUME_INFO;
  117. typedef struct _NETWORK_VOLUME_INFO
  118. {
  119. DWORD dwSize;
  120. DWORD dwUnknown1;
  121. DWORD dwShareNameOfs;
  122. DWORD dwReserved;
  123. DWORD dwUnknown2;
  124. } NETWORK_VOLUME_INFO;
  125. typedef struct
  126. {
  127. DWORD cbSize;
  128. DWORD dwSignature;
  129. DWORD idSpecialFolder;
  130. DWORD cbOffset;
  131. } EXP_SPECIAL_FOLDER;
  132. typedef struct lnk_string_tag
  133. {
  134. unsigned short size;
  135. union {
  136. unsigned short w[1];
  137. unsigned char a[1];
  138. } str;
  139. } lnk_string;
  140. #include "poppack.h"
  141. static unsigned offset;
  142. static const void* fetch_block(void)
  143. {
  144. const unsigned* u;
  145. const void* ret;
  146. if (!(u = PRD(offset, sizeof(*u)))) return 0;
  147. if ((ret = PRD(offset, *u))) offset += *u;
  148. return ret;
  149. }
  150. static const lnk_string* fetch_string(int unicode)
  151. {
  152. const unsigned short* s;
  153. unsigned short len;
  154. const void* ret;
  155. if (!(s = PRD(offset, sizeof(*s)))) return 0;
  156. len = *s * (unicode ? sizeof(WCHAR) : sizeof(char));
  157. if ((ret = PRD(offset, sizeof(*s) + len))) offset += sizeof(*s) + len;
  158. return ret;
  159. }
  160. static void dump_pidl(void)
  161. {
  162. const lnk_string *pidl;
  163. int i, n = 0, sz = 0;
  164. pidl = fetch_string(FALSE);
  165. if (!pidl)
  166. return;
  167. printf("PIDL\n");
  168. printf("----\n\n");
  169. while(sz<pidl->size)
  170. {
  171. const lnk_string *segment = (const lnk_string*) &pidl->str.a[sz];
  172. if(!segment->size)
  173. break;
  174. sz+=segment->size;
  175. if(sz>pidl->size)
  176. {
  177. printf("bad pidl\n");
  178. break;
  179. }
  180. n++;
  181. printf("segment %d (%2d bytes) : ",n,segment->size);
  182. for(i=0; i<segment->size; i++)
  183. printf("%02x ",segment->str.a[i]);
  184. printf("\n");
  185. }
  186. printf("\n");
  187. }
  188. static void dump_string(const char *what, int unicode)
  189. {
  190. const lnk_string *data;
  191. unsigned sz;
  192. data = fetch_string(unicode);
  193. if (!data)
  194. return;
  195. printf("%s : ", what);
  196. sz = data->size;
  197. if (unicode)
  198. while (sz) printf("%c", data->str.w[data->size - sz--]);
  199. else
  200. while (sz) printf("%c", data->str.a[data->size - sz--]);
  201. printf("\n");
  202. }
  203. static void dump_location(void)
  204. {
  205. const LOCATION_INFO *loc;
  206. const char *p;
  207. loc = fetch_block();
  208. if (!loc)
  209. return;
  210. p = (const char*)loc;
  211. printf("Location\n");
  212. printf("--------\n\n");
  213. printf("Total size = %d\n", loc->dwTotalSize);
  214. printf("Header size = %d\n", loc->dwHeaderSize);
  215. printf("Flags = %08x\n", loc->dwFlags);
  216. /* dump information about the local volume the link points to */
  217. printf("Local volume ofs = %08x ", loc->dwVolTableOfs);
  218. if (loc->dwVolTableOfs &&
  219. loc->dwVolTableOfs + sizeof(LOCAL_VOLUME_INFO) < loc->dwTotalSize)
  220. {
  221. const LOCAL_VOLUME_INFO *vol = (const LOCAL_VOLUME_INFO *)&p[loc->dwVolTableOfs];
  222. printf("size %d type %d serial %08x label %d ",
  223. vol->dwSize, vol->dwType, vol->dwVolSerial, vol->dwVolLabelOfs);
  224. if(vol->dwVolLabelOfs)
  225. printf("(\"%s\")", &p[loc->dwVolTableOfs + vol->dwVolLabelOfs]);
  226. }
  227. printf("\n");
  228. /* dump information about the network volume the link points to */
  229. printf("Network volume ofs = %08x ", loc->dwNetworkVolTableOfs);
  230. if (loc->dwNetworkVolTableOfs &&
  231. loc->dwNetworkVolTableOfs + sizeof(NETWORK_VOLUME_INFO) < loc->dwTotalSize)
  232. {
  233. const NETWORK_VOLUME_INFO *vol = (const NETWORK_VOLUME_INFO *)&p[loc->dwNetworkVolTableOfs];
  234. printf("size %d name %d ", vol->dwSize, vol->dwShareNameOfs);
  235. if(vol->dwShareNameOfs)
  236. printf("(\"%s\")", &p[loc->dwNetworkVolTableOfs + vol->dwShareNameOfs]);
  237. }
  238. printf("\n");
  239. /* dump out the path the link points to */
  240. printf("LocalPath ofs = %08x ", loc->dwLocalPathOfs);
  241. if( loc->dwLocalPathOfs && (loc->dwLocalPathOfs < loc->dwTotalSize) )
  242. printf("(\"%s\")", &p[loc->dwLocalPathOfs]);
  243. printf("\n");
  244. printf("Net Path ofs = %08x\n", loc->dwNetworkVolTableOfs);
  245. printf("Final Path = %08x ", loc->dwFinalPathOfs);
  246. if( loc->dwFinalPathOfs && (loc->dwFinalPathOfs < loc->dwTotalSize) )
  247. printf("(\"%s\")", &p[loc->dwFinalPathOfs]);
  248. printf("\n");
  249. printf("\n");
  250. }
  251. static const unsigned char table_dec85[0x80] = {
  252. 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
  253. 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
  254. 0xff,0x00,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff,
  255. 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0xff,0xff,0xff,0x16,0xff,0x17,
  256. 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
  257. 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0xff,0x34,0x35,0x36,
  258. 0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,
  259. 0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0xff,0x53,0x54,0xff,
  260. };
  261. static BOOL base85_to_guid( const char *str, LPGUID guid )
  262. {
  263. DWORD i, val = 0, base = 1, *p;
  264. unsigned char ch;
  265. p = (DWORD*) guid;
  266. for( i=0; i<20; i++ )
  267. {
  268. if( (i%5) == 0 )
  269. {
  270. val = 0;
  271. base = 1;
  272. }
  273. ch = str[i];
  274. if( ch >= 0x80 )
  275. return FALSE;
  276. val += table_dec85[ch] * base;
  277. if( table_dec85[ch] == 0xff )
  278. return FALSE;
  279. if( (i%5) == 4 )
  280. p[i/5] = val;
  281. base *= 85;
  282. }
  283. return TRUE;
  284. }
  285. static void dump_special_folder_block(const DATABLOCK_HEADER* bhdr)
  286. {
  287. const EXP_SPECIAL_FOLDER *sfb = (const EXP_SPECIAL_FOLDER*)bhdr;
  288. printf("Special folder block\n");
  289. printf("--------------------\n\n");
  290. printf("folder = 0x%04x\n", sfb->idSpecialFolder);
  291. printf("offset = %d\n", sfb->cbOffset);
  292. printf("\n");
  293. }
  294. static void dump_sz_block(const DATABLOCK_HEADER* bhdr, const char* label)
  295. {
  296. const LINK_SZ_BLOCK *szp = (const LINK_SZ_BLOCK*)bhdr;
  297. printf("String block\n");
  298. printf("-----------\n\n");
  299. printf("magic = %x\n", szp->magic);
  300. printf("%s = %s\n", label, szp->bufA);
  301. printf("\n");
  302. }
  303. static void dump_darwin_id(const DATABLOCK_HEADER* bhdr)
  304. {
  305. const LINK_SZ_BLOCK *szp = (const LINK_SZ_BLOCK*)bhdr;
  306. char comp_str[40];
  307. const char *feat, *comp, *prod_str, *feat_str;
  308. GUID guid;
  309. printf("Advertise Info\n");
  310. printf("--------------\n\n");
  311. printf("msi string = %s\n", szp->bufA);
  312. if (base85_to_guid(szp->bufA, &guid))
  313. prod_str = get_guid_str(&guid);
  314. else
  315. prod_str = "?";
  316. comp = &szp->bufA[20];
  317. feat = strchr(comp, '>');
  318. if (!feat)
  319. feat = strchr(comp, '<');
  320. if (feat)
  321. {
  322. memcpy(comp_str, comp, feat - comp);
  323. comp_str[feat-comp] = 0;
  324. }
  325. else
  326. {
  327. strcpy(comp_str, "?");
  328. }
  329. if (feat && feat[0] == '>' && base85_to_guid( &feat[1], &guid ))
  330. feat_str = get_guid_str( &guid );
  331. else
  332. feat_str = "";
  333. printf(" product: %s\n", prod_str);
  334. printf(" component: %s\n", comp_str );
  335. printf(" feature: %s\n", feat_str);
  336. printf("\n");
  337. }
  338. static void dump_property_storage_value(const LINK_PROPERTYSTORAGE_VALUE *lnk_value_hdr,
  339. DWORD data_size)
  340. {
  341. BOOL got_terminator = FALSE;
  342. int i, value_size;
  343. const unsigned char *value;
  344. while (data_size >= sizeof(DWORD))
  345. {
  346. if (!lnk_value_hdr->size)
  347. {
  348. got_terminator = TRUE;
  349. break;
  350. }
  351. if (lnk_value_hdr->size > data_size || lnk_value_hdr->size < sizeof(*lnk_value_hdr))
  352. {
  353. printf(" size: %d (invalid)\n", lnk_value_hdr->size);
  354. return;
  355. }
  356. printf(" pid: %d\n", lnk_value_hdr->pid);
  357. printf(" unknown8: %d\n", lnk_value_hdr->unknown8);
  358. printf(" vartype: %d\n", lnk_value_hdr->vt);
  359. printf(" unknown25: %d\n", lnk_value_hdr->unknown25);
  360. value_size = lnk_value_hdr->size - sizeof(*lnk_value_hdr);
  361. value = (const unsigned char*)(lnk_value_hdr+1);
  362. printf(" value (%2d bytes) : ",value_size);
  363. for(i=0; i<value_size; i++)
  364. printf("%02x ",value[i]);
  365. printf("\n\n");
  366. data_size -= lnk_value_hdr->size;
  367. lnk_value_hdr = (void*)((char*)lnk_value_hdr + lnk_value_hdr->size);
  368. }
  369. if (!got_terminator)
  370. printf(" missing terminator!\n");
  371. }
  372. static void dump_property_storage(const DATABLOCK_HEADER* bhdr)
  373. {
  374. int data_size;
  375. const LINK_PROPERTYSTORAGE_GUID *lnk_guid_hdr;
  376. BOOL got_terminator = FALSE;
  377. printf("Property Storage\n");
  378. printf("--------------\n\n");
  379. data_size=bhdr->cbSize-sizeof(*bhdr);
  380. lnk_guid_hdr=(void*)((const char*)bhdr+sizeof(*bhdr));
  381. while (data_size >= sizeof(DWORD))
  382. {
  383. if (!lnk_guid_hdr->size)
  384. {
  385. got_terminator = TRUE;
  386. break;
  387. }
  388. if (lnk_guid_hdr->size > data_size || lnk_guid_hdr->size < sizeof(*lnk_guid_hdr))
  389. {
  390. printf("size: %d (invalid)\n", lnk_guid_hdr->size);
  391. return;
  392. }
  393. if (lnk_guid_hdr->magic != 0x53505331)
  394. printf("magic: %x\n", lnk_guid_hdr->magic);
  395. printf("fmtid: %s\n", get_guid_str(&lnk_guid_hdr->fmtid));
  396. dump_property_storage_value((void*)(lnk_guid_hdr + 1), lnk_guid_hdr->size - sizeof(*lnk_guid_hdr));
  397. data_size -= lnk_guid_hdr->size;
  398. lnk_guid_hdr = (void*)((char*)lnk_guid_hdr + lnk_guid_hdr->size);
  399. }
  400. if (!got_terminator)
  401. printf("missing terminator!\n");
  402. printf("\n");
  403. }
  404. static void dump_raw_block(const DATABLOCK_HEADER* bhdr)
  405. {
  406. int data_size;
  407. printf("Raw Block\n");
  408. printf("---------\n\n");
  409. printf("size = %d\n", bhdr->cbSize);
  410. printf("magic = %x\n", bhdr->dwSignature);
  411. data_size=bhdr->cbSize-sizeof(*bhdr);
  412. if (data_size > 0)
  413. {
  414. int i;
  415. const unsigned char *data;
  416. printf("data = ");
  417. data=(const unsigned char*)bhdr+sizeof(*bhdr);
  418. while (data_size > 0)
  419. {
  420. for (i=0; i < 16; i++)
  421. {
  422. if (i < data_size)
  423. printf("%02x ", data[i]);
  424. else
  425. printf(" ");
  426. }
  427. for (i=0; i < data_size && i < 16; i++)
  428. printf("%c", (data[i] >= 32 && data[i] < 128 ? data[i] : '.'));
  429. printf("\n");
  430. data_size-=16;
  431. if (data_size <= 0)
  432. break;
  433. data+=16;
  434. printf(" ");
  435. }
  436. }
  437. printf("\n");
  438. }
  439. static const GUID CLSID_ShellLink = {0x00021401L, 0, 0, {0xC0,0,0,0,0,0,0,0x46}};
  440. enum FileSig get_kind_lnk(void)
  441. {
  442. const LINK_HEADER* hdr;
  443. hdr = PRD(0, sizeof(*hdr));
  444. if (hdr && hdr->dwSize == sizeof(LINK_HEADER) &&
  445. !memcmp(&hdr->MagicGuid, &CLSID_ShellLink, sizeof(GUID)))
  446. return SIG_LNK;
  447. return SIG_UNKNOWN;
  448. }
  449. void lnk_dump(void)
  450. {
  451. const LINK_HEADER* hdr;
  452. const DATABLOCK_HEADER* bhdr;
  453. DWORD dwFlags;
  454. offset = 0;
  455. hdr = fetch_block();
  456. if (!hdr)
  457. return;
  458. printf("Header\n");
  459. printf("------\n\n");
  460. printf("Size: %04x\n", hdr->dwSize);
  461. printf("GUID: %s\n", get_guid_str(&hdr->MagicGuid));
  462. printf("FileAttr: %08x\n", hdr->dwFileAttr);
  463. printf("FileLength: %08x\n", hdr->dwFileLength);
  464. printf("nIcon: %d\n", hdr->nIcon);
  465. printf("Startup: %d\n", hdr->fStartup);
  466. printf("HotKey: %08x\n", hdr->wHotKey);
  467. printf("Unknown5: %08x\n", hdr->Unknown5);
  468. printf("Unknown6: %08x\n", hdr->Unknown6);
  469. /* dump out all the flags */
  470. printf("Flags: %04x ( ", hdr->dwFlags);
  471. dwFlags=hdr->dwFlags;
  472. #define FLAG(x) do \
  473. { \
  474. if (dwFlags & SLDF_##x) \
  475. { \
  476. printf("%s ", #x); \
  477. dwFlags&=~SLDF_##x; \
  478. } \
  479. } while (0)
  480. FLAG(HAS_ID_LIST);
  481. FLAG(HAS_LINK_INFO);
  482. FLAG(HAS_NAME);
  483. FLAG(HAS_RELPATH);
  484. FLAG(HAS_WORKINGDIR);
  485. FLAG(HAS_ARGS);
  486. FLAG(HAS_ICONLOCATION);
  487. FLAG(UNICODE);
  488. FLAG(FORCE_NO_LINKINFO);
  489. FLAG(HAS_EXP_SZ);
  490. FLAG(RUN_IN_SEPARATE);
  491. FLAG(HAS_LOGO3ID);
  492. FLAG(HAS_DARWINID);
  493. FLAG(RUNAS_USER);
  494. FLAG(HAS_EXP_ICON_SZ);
  495. FLAG(NO_PIDL_ALIAS);
  496. FLAG(FORCE_UNCNAME);
  497. FLAG(RUN_WITH_SHIMLAYER);
  498. FLAG(FORCE_NO_LINKTRACK);
  499. FLAG(ENABLE_TARGET_METADATA);
  500. FLAG(DISABLE_KNOWNFOLDER_RELATIVE_TRACKING);
  501. FLAG(RESERVED);
  502. #undef FLAG
  503. if (dwFlags)
  504. printf("+%04x", dwFlags);
  505. printf(")\n");
  506. printf("Length: %04x\n", hdr->dwFileLength);
  507. printf("\n");
  508. if (hdr->dwFlags & SLDF_HAS_ID_LIST)
  509. dump_pidl();
  510. if (hdr->dwFlags & SLDF_HAS_LINK_INFO)
  511. dump_location();
  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);
  522. bhdr=fetch_block();
  523. while (bhdr)
  524. {
  525. if (!bhdr->cbSize)
  526. break;
  527. switch (bhdr->dwSignature)
  528. {
  529. case EXP_SZ_LINK_SIG:
  530. dump_sz_block(bhdr, "exp.link");
  531. break;
  532. case EXP_SPECIAL_FOLDER_SIG:
  533. dump_special_folder_block(bhdr);
  534. break;
  535. case EXP_SZ_ICON_SIG:
  536. dump_sz_block(bhdr, "icon");
  537. break;
  538. case EXP_DARWIN_ID_SIG:
  539. dump_darwin_id(bhdr);
  540. break;
  541. case EXP_PROPERTYSTORAGE_SIG:
  542. dump_property_storage(bhdr);
  543. break;
  544. default:
  545. dump_raw_block(bhdr);
  546. }
  547. bhdr=fetch_block();
  548. }
  549. }