dinput: Don't trace DIEFFECT members if they don't contain valid data.
[wine] / tools / winedump / lnk.c
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
21 #include "config.h"
22 #include "wine/port.h"
23 #include "winedump.h"
24
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>
35
36 #include "windef.h"
37 #include "winbase.h"
38
39 #include "pshpack1.h"
40
41 typedef enum {
42     SLDF_HAS_ID_LIST = 0x00000001,
43     SLDF_HAS_LINK_INFO = 0x00000002,
44     SLDF_HAS_NAME = 0x00000004,
45     SLDF_HAS_RELPATH = 0x00000008,
46     SLDF_HAS_WORKINGDIR = 0x00000010,
47     SLDF_HAS_ARGS = 0x00000020,
48     SLDF_HAS_ICONLOCATION = 0x00000040,
49     SLDF_UNICODE = 0x00000080,
50     SLDF_FORCE_NO_LINKINFO = 0x00000100,
51     SLDF_HAS_EXP_SZ = 0x00000200,
52     SLDF_RUN_IN_SEPARATE = 0x00000400,
53     SLDF_HAS_LOGO3ID = 0x00000800,
54     SLDF_HAS_DARWINID = 0x00001000,
55     SLDF_RUNAS_USER = 0x00002000,
56     SLDF_HAS_EXP_ICON_SZ = 0x00004000,
57     SLDF_NO_PIDL_ALIAS = 0x00008000,
58     SLDF_FORCE_UNCNAME = 0x00010000,
59     SLDF_RUN_WITH_SHIMLAYER = 0x00020000,
60     SLDF_FORCE_NO_LINKTRACK = 0x00040000,
61     SLDF_ENABLE_TARGET_METADATA = 0x00080000,
62     SLDF_DISABLE_KNOWNFOLDER_RELATIVE_TRACKING = 0x00200000,
63     SLDF_RESERVED = 0x80000000,
64 } SHELL_LINK_DATA_FLAGS;
65
66 #define EXP_SZ_LINK_SIG         0xa0000001
67 #define EXP_SPECIAL_FOLDER_SIG  0xa0000005
68 #define EXP_DARWIN_ID_SIG       0xa0000006
69 #define EXP_SZ_ICON_SIG         0xa0000007
70 #define EXP_PROPERTYSTORAGE_SIG 0xa0000009
71
72 typedef struct tagDATABLOCKHEADER
73 {
74     DWORD cbSize;
75     DWORD dwSignature;
76 } DATABLOCK_HEADER;
77
78 typedef struct _LINK_HEADER
79 {
80     DWORD    dwSize;        /* 0x00 size of the header - 0x4c */
81     GUID     MagicGuid;     /* 0x04 is CLSID_ShellLink */
82     DWORD    dwFlags;       /* 0x14 describes elements following */
83     DWORD    dwFileAttr;    /* 0x18 attributes of the target file */
84     FILETIME Time1;         /* 0x1c */
85     FILETIME Time2;         /* 0x24 */
86     FILETIME Time3;         /* 0x2c */
87     DWORD    dwFileLength;  /* 0x34 File length */
88     DWORD    nIcon;         /* 0x38 icon number */
89     DWORD   fStartup;       /* 0x3c startup type */
90     DWORD   wHotKey;        /* 0x40 hotkey */
91     DWORD   Unknown5;       /* 0x44 */
92     DWORD   Unknown6;       /* 0x48 */
93 } LINK_HEADER, * PLINK_HEADER;
94
95 typedef struct tagLINK_SZ_BLOCK
96 {
97     DWORD size;
98     DWORD magic;
99     CHAR  bufA[MAX_PATH];
100     WCHAR bufW[MAX_PATH];
101 } LINK_SZ_BLOCK;
102
103 typedef struct tagLINK_PROPERTYSTORAGE_GUID
104 {
105     DWORD size;
106     DWORD magic;
107     GUID fmtid;
108 } LINK_PROPERTYSTORAGE_GUID;
109
110 typedef struct tagLINK_PROPERTYSTORAGE_VALUE
111 {
112     DWORD size;
113     DWORD pid;
114     BYTE unknown8;
115     DWORD vt;
116     DWORD unknown25;
117 } LINK_PROPERTYSTORAGE_VALUE;
118
119 typedef struct _LOCATION_INFO
120 {
121     DWORD  dwTotalSize;
122     DWORD  dwHeaderSize;
123     DWORD  dwFlags;
124     DWORD  dwVolTableOfs;
125     DWORD  dwLocalPathOfs;
126     DWORD  dwNetworkVolTableOfs;
127     DWORD  dwFinalPathOfs;
128 } LOCATION_INFO;
129
130 typedef struct _LOCAL_VOLUME_INFO
131 {
132     DWORD dwSize;
133     DWORD dwType;
134     DWORD dwVolSerial;
135     DWORD dwVolLabelOfs;
136 } LOCAL_VOLUME_INFO;
137
138 typedef struct _NETWORK_VOLUME_INFO
139 {
140     DWORD dwSize;
141     DWORD dwUnkown1;
142     DWORD dwShareNameOfs;
143     DWORD dwReserved;
144     DWORD dwUnknown2;
145 } NETWORK_VOLUME_INFO;
146
147 typedef struct
148 {
149     DWORD cbSize;
150     DWORD dwSignature;
151     DWORD idSpecialFolder;
152     DWORD cbOffset;
153 } EXP_SPECIAL_FOLDER;
154
155 typedef struct lnk_string_tag
156 {
157     unsigned short size;
158     union {
159         unsigned short w[1];
160         unsigned char a[1];
161     } str;
162 } lnk_string;
163
164 #include "poppack.h"
165
166 static unsigned offset;
167
168 static const void* fetch_block(void)
169 {
170     const unsigned*     u;
171     const void*         ret;
172
173     if (!(u = PRD(offset, sizeof(*u)))) return 0;
174     if ((ret = PRD(offset, *u)))   offset += *u;
175     return ret;
176 }
177
178 static const lnk_string* fetch_string(int unicode)
179 {
180     const unsigned short*       s;
181     unsigned short              len;
182     const void*                 ret;
183
184     if (!(s = PRD(offset, sizeof(*s)))) return 0;
185     len = *s * (unicode ? sizeof(WCHAR) : sizeof(char));
186     if ((ret = PRD(offset, sizeof(*s) + len)))  offset += sizeof(*s) + len;
187     return ret;
188 }
189
190
191 static int dump_pidl(void)
192 {
193     const lnk_string *pidl;
194     int i, n = 0, sz = 0;
195
196     pidl = fetch_string(FALSE);
197     if (!pidl)
198         return -1;
199
200     printf("PIDL\n");
201     printf("----\n\n");
202
203     while(sz<pidl->size)
204     {
205         const lnk_string *segment = (const lnk_string*) &pidl->str.a[sz];
206
207         if(!segment->size)
208             break;
209         sz+=segment->size;
210         if(sz>pidl->size)
211         {
212             printf("bad pidl\n");
213             break;
214         }
215         n++;
216         printf("segment %d (%2d bytes) : ",n,segment->size);
217         for(i=0; i<segment->size; i++)
218             printf("%02x ",segment->str.a[i]);
219         printf("\n");
220     }
221     printf("\n");
222
223     return 0;
224 }
225
226 static int dump_string(const char *what, int unicode)
227 {
228     const lnk_string *data;
229     unsigned sz;
230
231     data = fetch_string(unicode);
232     if (!data)
233         return -1;
234     printf("%s : ", what);
235     sz = data->size;
236     if (unicode)
237         while (sz) printf("%c", data->str.w[data->size - sz--]);
238     else
239         while (sz) printf("%c", data->str.a[data->size - sz--]);
240     printf("\n");
241
242     return 0;
243 }
244
245 static int dump_location(void)
246 {
247     const LOCATION_INFO *loc;
248     const char *p;
249
250     loc = fetch_block();
251     if (!loc)
252         return -1;
253     p = (const char*)loc;
254
255     printf("Location\n");
256     printf("--------\n\n");
257     printf("Total size    = %d\n", loc->dwTotalSize);
258     printf("Header size   = %d\n", loc->dwHeaderSize);
259     printf("Flags         = %08x\n", loc->dwFlags);
260
261     /* dump information about the local volume the link points to */
262     printf("Local volume ofs    = %08x ", loc->dwVolTableOfs);
263     if (loc->dwVolTableOfs &&
264         loc->dwVolTableOfs + sizeof(LOCAL_VOLUME_INFO) < loc->dwTotalSize)
265     {
266         const LOCAL_VOLUME_INFO *vol = (const LOCAL_VOLUME_INFO *)&p[loc->dwVolTableOfs];
267
268         printf("size %d  type %d  serial %08x  label %d ",
269                vol->dwSize, vol->dwType, vol->dwVolSerial, vol->dwVolLabelOfs);
270         if(vol->dwVolLabelOfs)
271             printf("(\"%s\")", &p[loc->dwVolTableOfs + vol->dwVolLabelOfs]);
272     }
273     printf("\n");
274
275     /* dump information about the network volume the link points to */
276     printf("Network volume ofs    = %08x ", loc->dwNetworkVolTableOfs);
277     if (loc->dwNetworkVolTableOfs &&
278         loc->dwNetworkVolTableOfs + sizeof(NETWORK_VOLUME_INFO) < loc->dwTotalSize)
279     {
280         const NETWORK_VOLUME_INFO *vol = (const NETWORK_VOLUME_INFO *)&p[loc->dwNetworkVolTableOfs];
281
282         printf("size %d name %d ", vol->dwSize, vol->dwShareNameOfs);
283         if(vol->dwShareNameOfs)
284             printf("(\"%s\")", &p[loc->dwNetworkVolTableOfs + vol->dwShareNameOfs]);
285     }
286     printf("\n");
287
288     /* dump out the path the link points to */
289     printf("LocalPath ofs = %08x ", loc->dwLocalPathOfs);
290     if( loc->dwLocalPathOfs && (loc->dwLocalPathOfs < loc->dwTotalSize) )
291         printf("(\"%s\")", &p[loc->dwLocalPathOfs]);
292     printf("\n");
293
294     printf("Net Path ofs  = %08x\n", loc->dwNetworkVolTableOfs);
295     printf("Final Path    = %08x ", loc->dwFinalPathOfs);
296     if( loc->dwFinalPathOfs && (loc->dwFinalPathOfs < loc->dwTotalSize) )
297         printf("(\"%s\")", &p[loc->dwFinalPathOfs]);
298     printf("\n");
299     printf("\n");
300
301     return 0;
302 }
303
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,
313 };
314
315 static int base85_to_guid( const char *str, LPGUID guid )
316 {
317     DWORD i, val = 0, base = 1, *p;
318     unsigned char ch;
319
320     p = (DWORD*) guid;
321     for( i=0; i<20; i++ )
322     {
323         if( (i%5) == 0 )
324         {
325             val = 0;
326             base = 1;
327         }
328         ch = str[i];
329         if( ch >= 0x80 )
330             return 0;
331         val += table_dec85[ch] * base;
332         if( table_dec85[ch] == 0xff )
333             return 0;
334         if( (i%5) == 4 )
335             p[i/5] = val;
336         base *= 85;
337     }
338     return 1;
339 }
340
341 static int dump_special_folder_block(const DATABLOCK_HEADER* bhdr)
342 {
343     const EXP_SPECIAL_FOLDER *sfb = (const EXP_SPECIAL_FOLDER*)bhdr;
344     printf("Special folder block\n");
345     printf("--------------------\n\n");
346     printf("folder  = 0x%04x\n", sfb->idSpecialFolder);
347     printf("offset  = %d\n", sfb->cbOffset);
348     printf("\n");
349     return 0;
350 }
351
352 static int dump_sz_block(const DATABLOCK_HEADER* bhdr, const char* label)
353 {
354     const LINK_SZ_BLOCK *szp = (const LINK_SZ_BLOCK*)bhdr;
355     printf("String block\n");
356     printf("-----------\n\n");
357     printf("magic   = %x\n", szp->magic);
358     printf("%s    = %s\n", label, szp->bufA);
359     printf("\n");
360     return 0;
361 }
362
363 static int dump_darwin_id(const DATABLOCK_HEADER* bhdr)
364 {
365     const LINK_SZ_BLOCK *szp = (const LINK_SZ_BLOCK*)bhdr;
366     char comp_str[40];
367     const char *feat, *comp, *prod_str, *feat_str;
368     GUID guid;
369
370     printf("Advertise Info\n");
371     printf("--------------\n\n");
372     printf("msi string = %s\n", szp->bufA);
373
374     if (base85_to_guid(szp->bufA, &guid))
375         prod_str = get_guid_str(&guid);
376     else
377         prod_str = "?";
378
379     comp = &szp->bufA[20];
380     feat = strchr(comp, '>');
381     if (!feat)
382         feat = strchr(comp, '<');
383     if (feat)
384     {
385         memcpy(comp_str, comp, feat - comp);
386         comp_str[feat-comp] = 0;
387     }
388     else
389     {
390         strcpy(comp_str, "?");
391     }
392
393     if (feat && feat[0] == '>' && base85_to_guid( &feat[1], &guid ))
394         feat_str = get_guid_str( &guid );
395     else
396         feat_str = "";
397
398     printf("  product:   %s\n", prod_str);
399     printf("  component: %s\n", comp_str );
400     printf("  feature:   %s\n", feat_str);
401     printf("\n");
402
403     return 0;
404 }
405
406 static void dump_property_storage_value(const LINK_PROPERTYSTORAGE_VALUE *lnk_value_hdr,
407     DWORD data_size)
408 {
409     int got_terminator = 0, i, value_size;
410     const unsigned char *value;
411
412     while (data_size >= sizeof(DWORD))
413     {
414         if (!lnk_value_hdr->size)
415         {
416             got_terminator = 1;
417             break;
418         }
419
420         if (lnk_value_hdr->size > data_size || lnk_value_hdr->size < sizeof(*lnk_value_hdr))
421         {
422             printf("  size: %d (invald)\n", lnk_value_hdr->size);
423             return;
424         }
425
426         printf("  pid: %d\n", lnk_value_hdr->pid);
427         printf("    unknown8: %d\n", lnk_value_hdr->unknown8);
428         printf("    vartype: %d\n", lnk_value_hdr->vt);
429         printf("    unknown25: %d\n", lnk_value_hdr->unknown25);
430
431         value_size = lnk_value_hdr->size - sizeof(*lnk_value_hdr);
432         value = (const unsigned char*)(lnk_value_hdr+1);
433
434         printf("    value (%2d bytes) : ",value_size);
435         for(i=0; i<value_size; i++)
436             printf("%02x ",value[i]);
437         printf("\n\n");
438
439         data_size -= lnk_value_hdr->size;
440         lnk_value_hdr = (void*)((char*)lnk_value_hdr + lnk_value_hdr->size);
441     }
442
443     if (!got_terminator)
444         printf("  missing terminator!\n");
445 }
446
447 static int dump_property_storage(const DATABLOCK_HEADER* bhdr)
448 {
449     int data_size;
450     const LINK_PROPERTYSTORAGE_GUID *lnk_guid_hdr;
451     int got_terminator = 0;
452
453     printf("Property Storage\n");
454     printf("--------------\n\n");
455
456     data_size=bhdr->cbSize-sizeof(*bhdr);
457
458     lnk_guid_hdr=(void*)((const char*)bhdr+sizeof(*bhdr));
459
460     while (data_size >= sizeof(DWORD))
461     {
462         if (!lnk_guid_hdr->size)
463         {
464             got_terminator = 1;
465             break;
466         }
467
468         if (lnk_guid_hdr->size > data_size || lnk_guid_hdr->size < sizeof(*lnk_guid_hdr))
469         {
470             printf("size: %d (invald)\n", lnk_guid_hdr->size);
471             return 1;
472         }
473
474         if (lnk_guid_hdr->magic != 0x53505331)
475             printf("magic: %x\n", lnk_guid_hdr->magic);
476
477         printf("fmtid: %s\n", get_guid_str(&lnk_guid_hdr->fmtid));
478
479         dump_property_storage_value((void*)(lnk_guid_hdr + 1), lnk_guid_hdr->size - sizeof(*lnk_guid_hdr));
480
481         data_size -= lnk_guid_hdr->size;
482
483         lnk_guid_hdr = (void*)((char*)lnk_guid_hdr + lnk_guid_hdr->size);
484     }
485
486     if (!got_terminator)
487         printf("missing terminator!\n");
488
489     printf("\n");
490
491     return 0;
492 }
493
494 static int dump_raw_block(const DATABLOCK_HEADER* bhdr)
495 {
496     int data_size;
497
498     printf("Raw Block\n");
499     printf("---------\n\n");
500     printf("size    = %d\n", bhdr->cbSize);
501     printf("magic   = %x\n", bhdr->dwSignature);
502
503     data_size=bhdr->cbSize-sizeof(*bhdr);
504     if (data_size > 0)
505     {
506         int i;
507         const unsigned char *data;
508
509         printf("data    = ");
510         data=(const unsigned char*)bhdr+sizeof(*bhdr);
511         while (data_size > 0)
512         {
513             for (i=0; i < 16; i++)
514             {
515                 if (i < data_size)
516                     printf("%02x ", data[i]);
517                 else
518                     printf("   ");
519             }
520             for (i=0; i < data_size && i < 16; i++)
521                 printf("%c", (data[i] >= 32 && data[i] < 128 ? data[i] : '.'));
522             printf("\n");
523             data_size-=16;
524             if (data_size <= 0)
525                 break;
526             data+=16;
527             printf("          ");
528         }
529     }
530     printf("\n");
531
532     return 1;
533 }
534
535 static const GUID CLSID_ShellLink = {0x00021401L, 0, 0, {0xC0,0,0,0,0,0,0,0x46}};
536
537 enum FileSig get_kind_lnk(void)
538 {
539     const LINK_HEADER*        hdr;
540
541     hdr = PRD(0, sizeof(*hdr));
542     if (hdr && hdr->dwSize == sizeof(LINK_HEADER) &&
543         !memcmp(&hdr->MagicGuid, &CLSID_ShellLink, sizeof(GUID)))
544         return SIG_LNK;
545     return SIG_UNKNOWN;
546 }
547
548 void lnk_dump(void)
549 {
550     const LINK_HEADER*        hdr;
551     const DATABLOCK_HEADER*   bhdr;
552     DWORD dwFlags;
553
554     offset = 0;
555     hdr = fetch_block();
556     if (!hdr)
557         return;
558
559     printf("Header\n");
560     printf("------\n\n");
561     printf("Size:    %04x\n", hdr->dwSize);
562     printf("GUID:    %s\n", get_guid_str(&hdr->MagicGuid));
563
564     printf("FileAttr: %08x\n", hdr->dwFileAttr);
565     printf("FileLength: %08x\n", hdr->dwFileLength);
566     printf("nIcon: %d\n", hdr->nIcon);
567     printf("Startup: %d\n", hdr->fStartup);
568     printf("HotKey: %08x\n", hdr->wHotKey);
569     printf("Unknown5: %08x\n", hdr->Unknown5);
570     printf("Unknown6: %08x\n", hdr->Unknown6);
571
572     /* dump out all the flags */
573     printf("Flags:   %04x ( ", hdr->dwFlags);
574     dwFlags=hdr->dwFlags;
575 #define FLAG(x) do \
576                 { \
577                     if (dwFlags & SLDF_##x) \
578                     { \
579                         printf("%s ", #x); \
580                         dwFlags&=~SLDF_##x; \
581                     } \
582                 } while (0)
583     FLAG(HAS_ID_LIST);
584     FLAG(HAS_LINK_INFO);
585     FLAG(HAS_NAME);
586     FLAG(HAS_RELPATH);
587     FLAG(HAS_WORKINGDIR);
588     FLAG(HAS_ARGS);
589     FLAG(HAS_ICONLOCATION);
590     FLAG(UNICODE);
591     FLAG(FORCE_NO_LINKINFO);
592     FLAG(HAS_EXP_SZ);
593     FLAG(RUN_IN_SEPARATE);
594     FLAG(HAS_LOGO3ID);
595     FLAG(HAS_DARWINID);
596     FLAG(RUNAS_USER);
597     FLAG(HAS_EXP_ICON_SZ);
598     FLAG(NO_PIDL_ALIAS);
599     FLAG(FORCE_UNCNAME);
600     FLAG(RUN_WITH_SHIMLAYER);
601     FLAG(FORCE_NO_LINKTRACK);
602     FLAG(ENABLE_TARGET_METADATA);
603     FLAG(DISABLE_KNOWNFOLDER_RELATIVE_TRACKING);
604     FLAG(RESERVED);
605 #undef FLAG
606     if (dwFlags)
607         printf("+%04x", dwFlags);
608     printf(")\n");
609
610     printf("Length:  %04x\n", hdr->dwFileLength);
611     printf("\n");
612
613     if (hdr->dwFlags & SLDF_HAS_ID_LIST)
614         dump_pidl();
615     if (hdr->dwFlags & SLDF_HAS_LINK_INFO)
616         dump_location();
617     if (hdr->dwFlags & SLDF_HAS_NAME)
618         dump_string("Description", hdr->dwFlags & SLDF_UNICODE);
619     if (hdr->dwFlags & SLDF_HAS_RELPATH)
620         dump_string("Relative path", hdr->dwFlags & SLDF_UNICODE);
621     if (hdr->dwFlags & SLDF_HAS_WORKINGDIR)
622         dump_string("Working directory", hdr->dwFlags & SLDF_UNICODE);
623     if (hdr->dwFlags & SLDF_HAS_ARGS)
624         dump_string("Arguments", hdr->dwFlags & SLDF_UNICODE);
625     if (hdr->dwFlags & SLDF_HAS_ICONLOCATION)
626         dump_string("Icon path", hdr->dwFlags & SLDF_UNICODE);
627
628     bhdr=fetch_block();
629     while (bhdr)
630     {
631         if (!bhdr->cbSize)
632             break;
633         switch (bhdr->dwSignature)
634         {
635         case EXP_SZ_LINK_SIG:
636             dump_sz_block(bhdr, "exp.link");
637             break;
638         case EXP_SPECIAL_FOLDER_SIG:
639             dump_special_folder_block(bhdr);
640             break;
641         case EXP_SZ_ICON_SIG:
642             dump_sz_block(bhdr, "icon");
643             break;
644         case EXP_DARWIN_ID_SIG:
645             dump_darwin_id(bhdr);
646             break;
647         case EXP_PROPERTYSTORAGE_SIG:
648             dump_property_storage(bhdr);
649             break;
650         default:
651             dump_raw_block(bhdr);
652         }
653         bhdr=fetch_block();
654     }
655 }