2 * Dump a typelib (tlb) file
4 * Copyright 2006 Jacek Caban
5 * Copyright 2015 Dmitry Timoshkov
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/port.h"
33 #define MSFT_MAGIC 0x5446534d
34 #define SLTG_MAGIC 0x47544c53
35 #define HELPDLLFLAG 0x0100
88 VT_STREAMED_OBJECT
= 68,
89 VT_STORED_OBJECT
= 69,
93 VT_VERSIONED_STREAM
= 73,
100 VT_ILLEGALMASKED
= 0xfff,
106 typedef BOOL (*dump_seg_t
)(struct seg_t
*);
108 typedef struct seg_t
{
114 static seg_t segdir
[15];
136 static int typeinfo_cnt
;
137 static int header_flags
= 0;
138 static BOOL msft_eof
= FALSE
;
140 static int msft_typeinfo_offs
[1000];
141 static int msft_typeinfo_kind
[1000];
142 static int msft_typeinfo_impltypes
[1000];
143 static int msft_typeinfo_elemcnt
[1000];
144 static int msft_typeinfo_cnt
= 0;
146 static const char * const tkind
[TKIND_MAX
] = {
147 "TKIND_ENUM", "TKIND_RECORD", "TKIND_MODULE",
148 "TKIND_INTERFACE", "TKIND_DISPATCH", "TKIND_COCLASS",
149 "TKIND_ALIAS", "TKIND_UNION"
152 static const void *tlb_read(int size
) {
153 const void *ret
= PRD(offset
, size
);
163 static int tlb_read_int(void)
165 const int *ret
= tlb_read(sizeof(int));
166 return ret
? *ret
: -1;
169 static int tlb_read_short(void)
171 const unsigned short *ret
= tlb_read(sizeof(short));
172 return ret
? *ret
: -1;
175 static int tlb_read_byte(void)
177 const unsigned char *ret
= tlb_read(sizeof(char));
178 return ret
? *ret
: -1;
181 static void print_offset(void)
184 for(i
=0; i
<indent
; i
++)
188 static void print_begin_block(const char *name
)
191 printf("%s {\n", name
);
195 static void print_begin_block_id(const char *name
, int id
)
198 sprintf(buf
, "%s %d", name
, id
);
199 print_begin_block(buf
);
202 static void print_end_block(void)
209 static int print_byte(const char *name
)
213 printf("%s = %02xh\n", name
, ret
=tlb_read_byte());
217 static int print_hex(const char *name
)
221 printf("%s = %08xh\n", name
, ret
=tlb_read_int());
225 static int print_hex_id(const char *name
, int id
)
228 sprintf(buf
, name
, id
);
229 return print_hex(buf
);
232 static int print_short_hex(const char *name
)
236 printf("%s = %04xh\n", name
, ret
=tlb_read_short());
240 static int print_short_dec(const char *name
)
244 printf("%s = %d\n", name
, ret
=tlb_read_short());
248 static int print_dec(const char *name
)
252 printf("%s = %d\n", name
, ret
=tlb_read_int());
256 static void print_guid(const char *name
)
258 GUID guid
= *(const GUID
*)tlb_read(sizeof(guid
));
262 printf("%s = {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n", name
,
263 guid
.Data1
, guid
.Data2
, guid
.Data3
, guid
.Data4
[0],
264 guid
.Data4
[1], guid
.Data4
[2], guid
.Data4
[3], guid
.Data4
[4],
265 guid
.Data4
[5], guid
.Data4
[6], guid
.Data4
[7]);
268 static void print_vartype(int vartype
)
270 static const char *vartypes
[VT_LPWSTR
+1] = {
271 "VT_EMPTY", "VT_NULL", "VT_I2", "VT_I4", "VT_R4",
272 "VT_R8", "VT_CY", "VT_DATE", "VT_BSTR", "VT_DISPATCH",
273 "VT_ERROR", "VT_BOOL", "VT_VARIANT", "VT_UNKNOWN","VT_DECIMAL",
274 "unk 15", "VT_I1", "VT_UI1", "VT_UI2", "VT_UI4",
275 "VT_I8", "VT_UI8", "VT_INT", "VT_UINT", "VT_VOID",
276 "VT_HRESULT", "VT_PTR", "VT_SAFEARRAY","VT_CARRAY", "VT_USERDEFINED",
277 "VT_LPSTR", "VT_LPWSTR"
280 vartype
&= VT_TYPEMASK
;
281 if (vartype
>= VT_EMPTY
&& vartype
<= VT_LPWSTR
)
282 printf("%s\n", vartypes
[vartype
]);
284 printf("unk %d\n", vartype
);
287 static void print_ctl2(const char *name
)
294 len
= tlb_read_short();
296 printf("%s = %d \"", name
, len
);
299 fwrite(buf
, len
, 1, stdout
);
304 printf("\\%02x", tlb_read_byte());
308 static int tlb_isprint(unsigned char c
)
313 static void dump_binary(int size
)
315 const unsigned char *ptr
;
320 ptr
= tlb_read(size
);
324 printf("%08x: ", offset
- size
);
326 for (i
= 0; i
< size
; i
++)
328 printf("%02x%c", ptr
[i
], (i
% 16 == 7) ? '-' : ' ');
332 for (j
= 0; j
< 16; j
++)
333 printf("%c", tlb_isprint(ptr
[i
-15+j
]) ? ptr
[i
-15+j
] : '.');
338 printf("%08x: ", offset
- size
+ i
+ 1);
344 printf("%*s ", 3 * (16-(i
%16)), "");
345 for (j
= 0; j
< i
% 16; j
++)
346 printf("%c", tlb_isprint(ptr
[i
-(i
%16)+j
]) ? ptr
[i
-(i
%16)+j
] : '.');
351 static int dump_msft_varflags(void)
353 static const char *syskind
[] = {
354 "SYS_WIN16", "SYS_WIN32", "SYS_MAC", "SYS_WIN64", "unknown"
359 flags
= tlb_read_int();
361 if (kind
> 3) kind
= 4;
362 printf("varflags = %08x, syskind = %s\n", flags
, syskind
[kind
]);
366 static void dump_msft_version(void)
370 version
= tlb_read_int();
371 printf("version = %u.%u\n", version
& 0xffff, version
>> 16);
374 static void dump_msft_header(void)
376 print_begin_block("Header");
380 print_hex("posguid");
383 header_flags
= dump_msft_varflags();
386 typeinfo_cnt
= print_dec("ntypeinfos");
387 print_dec("helpstring");
388 print_dec("helpstringcontext");
389 print_dec("helpcontext");
390 print_dec("nametablecount");
391 print_dec("nametablechars");
392 print_hex("NameOffset");
393 print_hex("helpfile");
394 print_hex("CustomDataOffset");
397 print_hex("dispatchpos");
403 static int dump_msft_typekind(void)
408 ret
= tlb_read_int();
409 typekind
= ret
& 0xf;
410 printf("typekind = %s, align = %d\n", typekind
< TKIND_MAX
? tkind
[typekind
] : "unknown", (ret
>> 11) & 0x1f);
414 static void dump_msft_typeinfobase(void)
416 print_begin_block_id("TypeInfoBase", msft_typeinfo_cnt
);
418 msft_typeinfo_kind
[msft_typeinfo_cnt
] = dump_msft_typekind();
419 msft_typeinfo_offs
[msft_typeinfo_cnt
] = print_hex("memoffset");
424 msft_typeinfo_elemcnt
[msft_typeinfo_cnt
] = print_hex("cElement");
429 print_hex("posguid");
431 print_hex("NameOffset");
432 print_hex("version");
433 print_hex("docstringoffs");
434 print_hex("docstringcontext");
435 print_hex("helpcontext");
436 print_hex("oCustData");
437 msft_typeinfo_impltypes
[msft_typeinfo_cnt
++] = print_short_hex("cImplTypes");
438 print_short_hex("bSizeVftt");
440 print_hex("datatype1");
441 print_hex("datatype2");
448 static BOOL
dump_msft_typeinfobases(seg_t
*seg
)
452 for(i
= 0; offset
< seg
->offset
+seg
->length
; i
++)
453 dump_msft_typeinfobase();
455 assert(offset
== seg
->offset
+seg
->length
);
459 static void dump_msft_impinfo(int n
)
461 print_begin_block_id("ImpInfo", n
);
464 print_hex("oImpInfo");
470 static BOOL
dump_msft_impinfos(seg_t
*seg
)
474 for(i
= 0; offset
< seg
->offset
+seg
->length
; i
++)
475 dump_msft_impinfo(i
);
477 assert(offset
== seg
->offset
+seg
->length
);
481 static void dump_msft_impfile(int n
)
483 print_begin_block_id("ImpFile", n
);
487 print_hex("version");
488 print_ctl2("impfile");
493 static BOOL
dump_msft_impfiles(seg_t
*seg
)
497 for(i
= 0; offset
< seg
->offset
+seg
->length
; i
++)
498 dump_msft_impfile(i
);
500 assert(offset
== seg
->offset
+seg
->length
);
504 static BOOL
dump_msft_reftabs(seg_t
*seg
)
506 print_begin_block("RefTab");
508 dump_binary(seg
->length
); /* FIXME */
515 static BOOL
dump_msft_guidhashtab(seg_t
*seg
)
517 print_begin_block("GuidHashTab");
519 dump_binary(seg
->length
); /* FIXME */
523 assert(offset
== seg
->offset
+seg
->length
);
527 static void dump_msft_guidentry(int n
)
529 print_begin_block_id("GuidEntry", n
);
532 print_hex("hreftype");
533 print_hex("next_hash");
538 static BOOL
dump_msft_guidtab(seg_t
*seg
)
542 for(i
= 0; offset
< seg
->offset
+seg
->length
; i
++)
543 dump_msft_guidentry(i
);
545 assert(offset
== seg
->offset
+seg
->length
);
549 static BOOL
dump_msft_namehashtab(seg_t
*seg
)
551 print_begin_block("NameHashTab");
553 dump_binary(seg
->length
); /* FIXME */
559 static void print_string0(void)
564 while ((c
= tlb_read_byte()) != 0)
567 fwrite(&c
, 1, 1, stdout
);
571 sprintf(buf
, "\\%u", c
);
572 fwrite(buf
, 1, strlen(buf
), stdout
);
578 static void print_string(int len
)
581 fwrite(tlb_read(len
), len
, 1, stdout
);
585 static void dump_string(int len
, int align_off
)
589 while((len
++ + align_off
) & 3)
590 printf("\\%2.2x", tlb_read_byte());
593 static void dump_msft_name(int base
, int n
)
597 print_begin_block_id("Name", n
);
599 print_hex("hreftype");
600 print_hex("next_hash");
601 len
= print_hex("namelen")&0xff;
611 static BOOL
dump_msft_nametab(seg_t
*seg
)
613 int i
, base
= offset
;
615 for(i
= 0; offset
< seg
->offset
+seg
->length
; i
++)
616 dump_msft_name(base
, i
);
618 assert(offset
== seg
->offset
+seg
->length
);
622 static void dump_msft_string(int n
)
626 print_begin_block_id("String", n
);
628 len
= print_short_hex("stringlen");
635 for(len
= 0; len
< 4; len
++)
636 printf("\\%2.2x", tlb_read_byte());
643 static BOOL
dump_msft_stringtab(seg_t
*seg
)
647 for(i
= 0; offset
< seg
->offset
+seg
->length
; i
++)
650 assert(offset
== seg
->offset
+seg
->length
);
654 static void dump_msft_typedesc(int n
)
656 print_begin_block_id("TYPEDESC", n
);
658 print_hex("hreftype");
664 static BOOL
dump_msft_typedesctab(seg_t
*seg
)
668 print_begin_block("TypedescTab");
670 for(i
= 0; offset
< seg
->offset
+seg
->length
; i
++)
671 dump_msft_typedesc(i
);
675 assert(offset
== seg
->offset
+seg
->length
);
679 static BOOL
dump_msft_arraydescs(seg_t
*seg
)
681 print_begin_block("ArrayDescriptions");
683 dump_binary(seg
->length
); /* FIXME */
689 static BOOL
dump_msft_custdata(seg_t
*seg
)
694 print_begin_block("CustData");
696 for(i
=0; offset
< seg
->offset
+seg
->length
; i
++) {
699 vt
= tlb_read_short();
705 printf(" len %d: ", n
);
711 printf("\\%2.2x ", tlb_read_byte());
712 printf("\\%2.2x\n", tlb_read_byte());
720 static void dump_msft_cdguid(int n
)
722 print_begin_block_id("CGUid", n
);
724 print_hex("GuidOffset");
725 print_hex("DataOffset");
731 static BOOL
dump_msft_cdguids(seg_t
*seg
)
735 for(i
= 0; offset
< seg
->offset
+seg
->length
; i
++)
738 assert(offset
== seg
->offset
+seg
->length
);
742 static BOOL
dump_msft_res0e(seg_t
*seg
)
744 print_begin_block("res0e");
745 dump_binary(seg
->length
);
751 static BOOL
dump_msft_res0f(seg_t
*seg
)
753 print_begin_block("res0f");
754 dump_binary(seg
->length
);
760 /* Used for function return value and arguments type */
761 static void dump_msft_datatype(const char *name
)
766 datatype
= tlb_read_int();
767 printf("%s = %08x", name
, datatype
);
770 print_vartype(datatype
);
775 if (datatype
> segdir
[SEGDIR_TYPEDESC
].length
) {
776 printf(", invalid offset\n");
780 /* FIXME: in case of VT_USERDEFINED use hreftype */
781 vt
= PRD(segdir
[SEGDIR_TYPEDESC
].offset
+ datatype
, 4*sizeof(short));
782 datatype
= vt
[0] & VT_TYPEMASK
;
783 if (datatype
== VT_PTR
) {
784 printf(", VT_PTR -> ");
788 vt
= PRD(segdir
[SEGDIR_TYPEDESC
].offset
+ vt
[2], 4*sizeof(short));
797 print_vartype(datatype
);
801 static void dump_defaultvalue(int id
)
806 offset
= tlb_read_int();
808 printf("default value[%d] = %08x", id
, offset
);
811 else if (offset
< 0) {
813 print_vartype((offset
& 0x7c000000) >> 26);
816 const unsigned short *vt
;
818 if (offset
> segdir
[SEGDIR_CUSTDATA
].length
) {
819 printf(", invalid offset\n");
823 vt
= PRD(segdir
[SEGDIR_CUSTDATA
].offset
+ offset
, sizeof(*vt
));
829 static void dump_msft_func(int n
)
831 int size
, args_cnt
, i
, extra_attr
, fkccic
;
833 print_begin_block_id("FuncRecord", n
);
835 size
= print_short_hex("size");
836 print_short_hex("index");
837 dump_msft_datatype("retval type");
839 print_short_hex("VtableOffset");
840 print_short_hex("funcdescsize");
841 fkccic
= print_hex("FKCCIC");
842 args_cnt
= print_short_hex("nrargs");
843 print_short_hex("noptargs");
845 extra_attr
= size
/sizeof(INT
) - 6 - args_cnt
*(fkccic
&0x1000 ? 4 : 3);
848 print_hex("helpcontext");
850 print_hex("oHelpString");
852 print_hex("toEntry");
858 print_hex("HelpStringContext");
860 print_hex("oCustData");
861 for(i
= 0; i
< extra_attr
-7; i
++)
862 print_hex_id("oArgCustData", i
);
864 if(fkccic
& 0x1000) {
865 for(i
=0; i
< args_cnt
; i
++)
866 dump_defaultvalue(i
);
869 for(i
=0; i
< args_cnt
; i
++) {
870 print_begin_block_id("param", i
);
872 /* FIXME: Handle default values */
873 dump_msft_datatype("datatype");
875 print_hex("paramflags");
883 static void dump_msft_var(int n
)
887 print_begin_block_id("VarRecord", n
);
889 size
= print_hex("recsize")&0x1ff;
890 print_hex("DataType");
892 print_short_hex("VarKind");
893 print_short_hex("vardescsize");
894 print_hex("OffsValue");
896 if(size
> 5*sizeof(INT
))
897 dump_binary(size
- 5*sizeof(INT
));
902 static void dump_msft_ref(int n
)
904 print_begin_block_id("RefRecord", n
);
906 print_hex("reftype");
908 print_hex("oCustData");
914 static void dump_msft_coclass(int n
)
920 for(i
=0; i
< msft_typeinfo_impltypes
[n
]; i
++)
924 static BOOL
dump_msft_typeinfo(int n
)
928 print_begin_block_id("TypeInfo", n
);
930 if((msft_typeinfo_kind
[n
] & 0xf) == TKIND_COCLASS
) {
931 dump_msft_coclass(n
);
938 for(i
= 0; i
< LOWORD(msft_typeinfo_elemcnt
[n
]); i
++)
941 for(i
= 0; i
< HIWORD(msft_typeinfo_elemcnt
[n
]); i
++)
944 for(i
= 0; i
< LOWORD(msft_typeinfo_elemcnt
[n
]); i
++)
945 print_hex_id("func %d id", i
);
947 for(i
= 0; i
< HIWORD(msft_typeinfo_elemcnt
[n
]); i
++)
948 print_hex_id("var %d id", i
);
950 for(i
= 0; i
< LOWORD(msft_typeinfo_elemcnt
[n
]); i
++)
951 print_hex_id("func %d name", i
);
953 for(i
= 0; i
< HIWORD(msft_typeinfo_elemcnt
[n
]); i
++)
954 print_hex_id("var %d name", i
);
956 for(i
= 0; i
< LOWORD(msft_typeinfo_elemcnt
[n
]); i
++)
957 print_hex_id("func %d offset", i
);
959 for(i
= 0; i
< HIWORD(msft_typeinfo_elemcnt
[n
]); i
++)
960 print_hex_id("var %d offset", i
);
967 static seg_t segdir
[] = {
968 {"TypeInfoTab", dump_msft_typeinfobases
, -1, -1},
969 {"ImpInfo", dump_msft_impinfos
, -1, -1},
970 {"ImpFiles", dump_msft_impfiles
, -1, -1},
971 {"RefTab", dump_msft_reftabs
, -1, -1},
972 {"GuidHashTab", dump_msft_guidhashtab
, -1, -1},
973 {"GuidTab", dump_msft_guidtab
, -1, -1},
974 {"NameHashTab", dump_msft_namehashtab
, -1, -1},
975 {"pNameTab", dump_msft_nametab
, -1, -1},
976 {"pStringTab", dump_msft_stringtab
, -1, -1},
977 {"TypedescTab", dump_msft_typedesctab
, -1, -1},
978 {"ArrayDescriptions", dump_msft_arraydescs
, -1, -1},
979 {"CustData", dump_msft_custdata
, -1, -1},
980 {"CDGuid", dump_msft_cdguids
, -1, -1},
981 {"res0e", dump_msft_res0e
, -1, -1},
982 {"res0f", dump_msft_res0f
, -1, -1}
985 static void dump_msft_seg(seg_t
*seg
)
987 print_begin_block(seg
->name
);
989 seg
->offset
= print_hex("offset");
990 seg
->length
= print_dec("length");
997 static void dump_msft_segdir(void)
1001 print_begin_block("SegDir");
1003 for(i
=0; i
< ARRAY_SIZE(segdir
); i
++)
1004 dump_msft_seg(segdir
+i
);
1009 static BOOL
dump_offset(void)
1013 for(i
=0; i
< ARRAY_SIZE(segdir
); i
++)
1014 if(segdir
[i
].offset
== offset
)
1015 return segdir
[i
].func(segdir
+i
);
1017 for(i
=0; i
< msft_typeinfo_cnt
; i
++)
1018 if(msft_typeinfo_offs
[i
] == offset
)
1019 return dump_msft_typeinfo(i
);
1024 static void msft_dump(void)
1030 for(i
=0; i
< typeinfo_cnt
; i
++)
1031 print_hex_id("typeinfo %d offset", i
);
1033 if(header_flags
& HELPDLLFLAG
)
1034 print_hex("help dll offset");
1042 print_hex("unknown");
1046 /****************************** SLTG Typelibs ******************************/
1062 #include "pshpack1.h"
1063 struct sltg_typeinfo_header
1074 unsigned unknown1
: 3;
1075 unsigned flags
: 16;
1076 unsigned unknown2
: 5;
1077 unsigned typekind
: 8;
1082 struct sltg_member_header
1092 unsigned short cFuncs
;
1093 unsigned short cVars
;
1094 unsigned short cImplTypes
;
1095 unsigned short res06
; /* always 0000 */
1096 unsigned short funcs_off
; /* offset to functions (starting from the member header) */
1097 unsigned short vars_off
; /* offset to vars (starting from the member header) */
1098 unsigned short impls_off
; /* offset to implemented types (starting from the member header) */
1099 unsigned short funcs_bytes
; /* bytes used by function data */
1100 unsigned short vars_bytes
; /* bytes used by var data */
1101 unsigned short impls_bytes
; /* bytes used by implemented type data */
1102 unsigned short tdescalias_vt
; /* for TKIND_ALIAS */
1103 unsigned short res16
; /* always ffff */
1104 unsigned short res18
; /* always 0000 */
1105 unsigned short res1a
; /* always 0000 */
1106 unsigned short simple_alias
; /* tdescalias_vt is a vt rather than an offset? */
1107 unsigned short res1e
; /* always 0000 */
1108 unsigned short cbSizeInstance
;
1109 unsigned short cbAlignment
;
1110 unsigned short res24
;
1111 unsigned short res26
;
1112 unsigned short cbSizeVft
;
1113 unsigned short res2a
; /* always ffff */
1114 unsigned short res2c
; /* always ffff */
1115 unsigned short res2e
; /* always ffff */
1116 unsigned short res30
; /* always ffff */
1117 unsigned short res32
;
1118 unsigned short res34
;
1121 struct sltg_variable
1123 char magic
; /* 0x0a */
1127 short byte_offs
; /* pos in struct, or offset to const type or const data (if flags & 0x08) */
1128 short type
; /* if flags & 0x02 this is the type, else offset to type */
1130 short helpcontext
; /* ?? */
1131 short helpstring
; /* ?? */
1133 short varflags
; /* only present if magic & 0x20 */
1136 #include "poppack.h"
1138 static const char *lookup_code(const BYTE
*table
, DWORD table_size
, struct bitstream
*bits
)
1140 const BYTE
*p
= table
;
1142 while (p
< table
+ table_size
&& *p
== 0x80)
1144 if (p
+ 2 >= table
+ table_size
) return NULL
;
1146 if (!(bits
->current
& 0xff))
1148 if (!bits
->length
) return NULL
;
1149 bits
->current
= (*bits
->buffer
<< 8) | 1;
1154 if (bits
->current
& 0x8000)
1160 p
= table
+ (*(p
+ 2) | (*(p
+ 1) << 8));
1163 bits
->current
<<= 1;
1166 if (p
+ 1 < table
+ table_size
&& *(p
+ 1))
1168 /* FIXME: What is the meaning of *p? */
1169 const BYTE
*q
= p
+ 1;
1170 while (q
< table
+ table_size
&& *q
) q
++;
1171 return (q
< table
+ table_size
) ? (const char *)(p
+ 1) : NULL
;
1177 static const char *decode_string(const BYTE
*table
, const char *stream
, DWORD stream_length
, DWORD
*read_bytes
)
1180 DWORD buf_size
, table_size
;
1182 struct bitstream bits
;
1184 bits
.buffer
= (const BYTE
*)stream
;
1185 bits
.length
= stream_length
;
1188 buf_size
= *(const WORD
*)table
;
1189 table
+= sizeof(WORD
);
1190 table_size
= *(const DWORD
*)table
;
1191 table
+= sizeof(DWORD
);
1193 buf
= malloc(buf_size
);
1196 while ((p
= lookup_code(table
, table_size
, &bits
)))
1198 if (buf
[0]) strcat(buf
, " ");
1199 assert(strlen(buf
) + strlen(p
) + 1 <= buf_size
);
1203 if (read_bytes
) *read_bytes
= stream_length
- bits
.length
;
1208 static void print_sltg_name(const char *name
)
1210 unsigned short len
= tlb_read_short();
1212 printf("%s = %#x (", name
, len
);
1213 if (len
!= 0xffff) print_string(len
);
1217 static int dump_sltg_header(int *sltg_first_blk
, int *size_of_index
, int *size_of_pad
)
1221 print_begin_block("Header");
1224 n_file_blocks
= print_short_dec("# file blocks");
1225 *size_of_pad
= print_short_hex("pad");
1226 *size_of_index
= print_short_hex("size of index");
1227 *sltg_first_blk
= print_short_dec("first block");
1234 return n_file_blocks
;
1237 static void dump_sltg_index(int count
)
1248 for (i
= 0; i
< count
- 2; i
++)
1257 static void dump_sltg_pad(int size_of_pad
)
1260 dump_binary(size_of_pad
);
1264 static void dump_sltg_block_entry(int idx
, const char *index
)
1269 sprintf(name
, "Block entry %d", idx
);
1270 print_begin_block(name
);
1273 index_offset
= tlb_read_short();
1275 printf("index string = %xh \"%s\"\n", index_offset
, index
+ index_offset
);
1276 print_short_hex("next");
1281 static void dump_sltg_library_block(void)
1283 print_begin_block("Library block entry");
1285 print_short_hex("magic");
1286 print_short_hex("res02");
1287 print_sltg_name("name");
1288 print_short_hex("res06");
1289 print_sltg_name("helpstring");
1290 print_sltg_name("helpfile");
1291 print_hex("helpcontext");
1292 print_short_hex("syskind");
1293 print_short_hex("lcid");
1295 print_short_hex("libflags");
1296 dump_msft_version();
1302 static void skip_sltg_library_block(void)
1304 unsigned short skip
;
1308 skip
= tlb_read_short();
1309 if (skip
!= 0xffff) tlb_read(skip
);
1311 skip
= tlb_read_short();
1312 if (skip
!= 0xffff) tlb_read(skip
);
1313 skip
= tlb_read_short();
1314 if (skip
!= 0xffff) tlb_read(skip
);
1321 tlb_read(sizeof(GUID
));
1324 static void dump_sltg_other_typeinfo(int idx
, const char *hlp_strings
)
1326 int hlpstr_len
, saved_offset
;
1329 sprintf(name
, "Other typeinfo %d", idx
);
1330 print_begin_block(name
);
1332 print_sltg_name("index name");
1333 print_sltg_name("other name");
1334 print_short_hex("res1a");
1335 print_short_hex("name offset");
1338 hlpstr_len
= tlb_read_short();
1343 saved_offset
= offset
;
1344 str
= tlb_read(hlpstr_len
);
1345 str
= decode_string((const BYTE
*)hlp_strings
, str
, hlpstr_len
, NULL
);
1346 printf("helpstring: \"%s\"\n", str
);
1348 offset
= saved_offset
;
1350 printf("helpstring encoded bits: %d bytes\n", hlpstr_len
);
1351 dump_binary(hlpstr_len
);
1354 printf("helpstring: \"\"\n");
1356 print_short_hex("res20");
1357 print_hex("helpcontext");
1358 print_short_hex("res26");
1360 print_short_dec("typekind");
1365 static void skip_sltg_other_typeinfo(void)
1367 unsigned short skip
;
1369 skip
= tlb_read_short();
1370 if (skip
!= 0xffff) tlb_read(skip
);
1371 skip
= tlb_read_short();
1372 if (skip
!= 0xffff) tlb_read(skip
);
1375 skip
= tlb_read_short();
1376 if (skip
) tlb_read(skip
);
1380 tlb_read(sizeof(GUID
));
1384 static void sltg_print_simple_type(short type
)
1387 if ((type
& 0x0f00) == 0x0e00)
1389 printf("%04x | (%d)\n", type
& 0xff80, type
& 0x7f);
1392 static void dump_safe_array(int array_offset
)
1394 int i
, cDims
, saved_offset
= offset
;
1396 offset
= array_offset
;
1399 printf("safe array starts at %#x\n", offset
);
1401 cDims
= print_short_dec("cDims");
1402 print_short_hex("fFeatures");
1403 print_dec("cbElements");
1404 print_dec("cLocks");
1405 print_hex("pvData");
1407 for (i
= 0; i
< cDims
; i
++)
1408 dump_binary(8); /* sizeof(SAFEARRAYBOUND) */
1411 printf("safe array ends at %#x\n", offset
);
1412 offset
= saved_offset
;
1415 static int sltg_print_compound_type(int vars_start_offset
, int type_offset
)
1418 int type_bytes
, saved_offset
= offset
;
1420 offset
= vars_start_offset
+ type_offset
;
1422 printf("type description starts at %#x\n", offset
);
1428 type
= tlb_read_short();
1434 printf("%04x | VT_PTR\n", type
& 0xff80);
1436 } while (vt
== VT_PTR
);
1438 if (vt
== VT_USERDEFINED
)
1440 short href
= tlb_read_short();
1442 if ((type
& 0x0f00) == 0x0e00)
1444 printf("%04x | VT_USERDEFINED (href %d)\n", type
& 0xff80, href
);
1447 else if (vt
== VT_CARRAY
)
1451 off
= tlb_read_short();
1453 printf("VT_CARRAY: offset %#x (+%#x=%#x)\n",
1454 off
, vars_start_offset
, off
+ vars_start_offset
);
1455 dump_safe_array(vars_start_offset
+ off
);
1457 /* type description follows */
1459 printf("array element type:\n");
1462 else if (vt
== VT_SAFEARRAY
)
1466 off
= tlb_read_short();
1468 printf("VT_SAFEARRAY: offset %#x (+%#x=%#x)\n",
1469 off
, vars_start_offset
, off
+ vars_start_offset
);
1470 dump_safe_array(vars_start_offset
+ off
);
1475 sltg_print_simple_type(type
);
1481 printf("type description ends at %#x\n", offset
);
1482 type_bytes
= offset
- saved_offset
;
1483 offset
= saved_offset
;
1488 static void dump_type(int len
, const char *hlp_strings
)
1494 unsigned unknown1
: 3;
1495 unsigned flags
: 13;
1496 unsigned unknown2
: 8;
1497 unsigned typekind
: 8;
1501 int typeinfo_start_offset
, extra
, member_offset
, href_offset
, i
;
1502 int vars_header_bytes
= 0, vars_bytes
= 0, saved_offset
;
1504 const struct sltg_typeinfo_header
*ti
;
1505 const struct sltg_member_header
*mem
;
1506 const struct sltg_tail
*tail
;
1508 typeinfo_start_offset
= offset
;
1509 block
= tlb_read(len
);
1510 offset
= typeinfo_start_offset
;
1513 mem
= (const struct sltg_member_header
*)((char *)block
+ ti
->elem_table
);
1514 tail
= (const struct sltg_tail
*)((char *)(mem
+ 1) + mem
->extra
);
1516 typeinfo_start_offset
= offset
;
1518 print_short_hex("magic");
1519 href_offset
= tlb_read_int();
1521 if (href_offset
!= -1)
1522 printf("href offset = %#x (+%#x=%#x)\n",
1523 href_offset
, typeinfo_start_offset
, href_offset
+ typeinfo_start_offset
);
1525 printf("href offset = ffffffffh\n");
1527 member_offset
= tlb_read_int();
1529 printf("member offset = %#x (+%#x=%#x)\n",
1530 member_offset
, typeinfo_start_offset
, member_offset
+ typeinfo_start_offset
);
1532 print_hex("version");
1534 misc
.flags
= print_hex("misc");
1536 printf("misc: unknown1 %02x, flags %04x, unknown2 %02x, typekind %u (%s)\n",
1537 misc
.s
.unknown1
, misc
.s
.flags
, misc
.s
.unknown2
, misc
.s
.typekind
,
1538 misc
.s
.typekind
< TKIND_MAX
? tkind
[misc
.s
.typekind
] : "unknown");
1541 if (href_offset
!= -1)
1545 print_begin_block("href_table");
1547 print_short_hex("magic");
1564 print_short_hex("res42");
1565 number
= print_hex("number");
1567 for (i
= 0; i
< number
; i
+= 8)
1570 print_short_hex("res50");
1571 print_byte("res52");
1574 for (i
= 0; i
< number
/8; i
++)
1575 print_sltg_name("name");
1577 print_byte("resxx");
1583 printf("member_header starts at %#x, current offset = %#x\n", typeinfo_start_offset
+ member_offset
, offset
);
1584 member_offset
= offset
;
1585 print_short_hex("res00");
1586 print_short_hex("res02");
1587 print_byte("res04");
1588 extra
= print_hex("extra");
1590 if (misc
.s
.typekind
== TKIND_RECORD
|| misc
.s
.typekind
== TKIND_ENUM
)
1592 int vars_start_offset
= offset
;
1594 for (i
= 0; i
< tail
->cVars
; i
++)
1601 sprintf(name
, "variable %d", i
);
1602 print_begin_block(name
);
1605 dump_binary(sizeof(struct sltg_variable
));
1608 magic
= print_byte("magic");
1609 flags
= print_byte("flags");
1610 next
= tlb_read_short();
1613 printf("next offset = %#x (+%#x=%#x)\n",
1614 next
, vars_start_offset
, next
+ vars_start_offset
);
1616 printf("next offset = ffffh\n");
1617 print_short_hex("name");
1620 print_short_hex("dispatch");
1621 else if (flags
& 0x10)
1624 print_short_hex("const value");
1627 value
= tlb_read_short();
1629 printf("byte offset = %#x (+%#x=%#x)\n",
1630 value
, vars_start_offset
, value
+ vars_start_offset
);
1634 print_short_hex("oInst");
1636 value
= tlb_read_short();
1637 if (!(flags
& 0x02))
1640 printf("type offset = %#x (+%#x=%#x)\n",
1641 value
, vars_start_offset
, value
+ vars_start_offset
);
1644 vars_bytes
+= sltg_print_compound_type(vars_start_offset
, value
);
1650 sltg_print_simple_type(value
);
1654 print_short_hex("helpcontext");
1656 value
= tlb_read_short();
1661 DWORD hlpstr_maxlen
;
1663 printf("helpstring offset = %#x (+%#x=%#x)\n",
1664 value
, vars_start_offset
, value
+ vars_start_offset
);
1666 saved_offset
= offset
;
1668 offset
= value
+ vars_start_offset
;
1670 hlpstr_maxlen
= member_offset
+ sizeof(struct sltg_member_header
) + mem
->extra
- offset
;
1672 str
= tlb_read(hlpstr_maxlen
);
1673 str
= decode_string((const BYTE
*)hlp_strings
, str
, hlpstr_maxlen
, &hlpstr_maxlen
);
1675 printf("helpstring: \"%s\"\n", str
);
1677 offset
= value
+ vars_start_offset
;
1679 printf("helpstring encoded bits: %d bytes\n", hlpstr_maxlen
);
1680 dump_binary(hlpstr_maxlen
);
1682 offset
= saved_offset
;
1685 printf("helpstring offset = ffffh\n");
1689 print_short_hex("varflags");
1690 vars_header_bytes
+= 2;
1693 vars_header_bytes
+= sizeof(struct sltg_variable
);
1697 if (offset
!= vars_start_offset
+ next
)
1698 dump_binary(vars_start_offset
+ next
- offset
);
1704 else if (misc
.s
.typekind
== TKIND_INTERFACE
|| misc
.s
.typekind
== TKIND_COCLASS
)
1707 int funcs_start_offset
= offset
;
1709 for (i
= 0; i
< tail
->cImplTypes
; i
++)
1713 sprintf(name
, "impl.type %d (current offset %#x)", i
, offset
);
1714 print_begin_block(name
);
1716 print_short_hex("res00");
1717 next
= tlb_read_short();
1720 printf("next offset = %#x (+%#x=%#x)\n",
1721 next
, funcs_start_offset
, next
+ funcs_start_offset
);
1723 printf("next offset = ffffh\n");
1724 print_short_hex("res04");
1725 print_byte("impltypeflags");
1726 print_byte("res07");
1727 print_short_hex("res08");
1728 print_short_hex("ref");
1729 print_short_hex("res0c");
1730 print_short_hex("res0e");
1731 print_short_hex("res10");
1732 print_short_hex("res12");
1733 print_short_hex("pos in table");
1738 for (i
= 0; i
< tail
->cFuncs
; i
++)
1742 short args_off
, value
, n_params
, j
;
1744 sprintf(name
, "function %d (current offset %#x)", i
, offset
);
1745 print_begin_block(name
);
1747 magic
= print_byte("magic");
1748 flags
= tlb_read_byte();
1750 printf("invoke_kind = %u\n", flags
>> 4);
1751 next
= tlb_read_short();
1754 printf("next offset = %#x (+%#x=%#x)\n",
1755 next
, funcs_start_offset
, next
+ funcs_start_offset
);
1757 printf("next offset = ffffh\n");
1758 print_short_hex("name");
1759 print_hex("dispid");
1760 print_short_hex("helpcontext");
1762 value
= tlb_read_short();
1767 DWORD hlpstr_maxlen
;
1769 printf("helpstring offset = %#x (+%#x=%#x)\n",
1770 value
, funcs_start_offset
, value
+ funcs_start_offset
);
1772 saved_offset
= offset
;
1774 offset
= value
+ funcs_start_offset
;
1776 hlpstr_maxlen
= member_offset
+ sizeof(struct sltg_member_header
) + mem
->extra
- offset
;
1778 str
= tlb_read(hlpstr_maxlen
);
1779 str
= decode_string((const BYTE
*)hlp_strings
, str
, hlpstr_maxlen
, &hlpstr_maxlen
);
1781 printf("helpstring: \"%s\"\n", str
);
1783 offset
= value
+ funcs_start_offset
;
1785 printf("helpstring encoded bits: %d bytes\n", hlpstr_maxlen
);
1786 dump_binary(hlpstr_maxlen
);
1788 offset
= saved_offset
;
1791 printf("helpstring offset = ffffh\n");
1793 args_off
= tlb_read_short();
1796 printf("args off = %#x (+%#x=%#x)\n",
1797 args_off
, funcs_start_offset
, args_off
+ funcs_start_offset
);
1799 printf("args off = ffffh\n");
1800 flags
= tlb_read_byte();
1801 n_params
= flags
>> 3;
1803 printf("callconv %u, cParams %u\n", flags
& 0x7, n_params
);
1805 flags
= tlb_read_byte();
1807 printf("retnextop %02x, cParamsOpt %u\n", flags
, (flags
& 0x7e) >> 1);
1809 value
= print_short_hex("rettype");
1810 if (!(flags
& 0x80))
1813 printf("rettype offset = %#x (+%#x=%#x)\n",
1814 value
, funcs_start_offset
, value
+ funcs_start_offset
);
1816 printf("rettype:\n");
1817 sltg_print_compound_type(funcs_start_offset
, value
);
1822 printf("rettype:\n");
1823 sltg_print_simple_type(value
);
1826 print_short_hex("vtblpos");
1828 print_short_hex("funcflags");
1832 offset
= args_off
+ funcs_start_offset
;
1834 printf("arguments start at %#x\n", offset
);
1837 for (j
= 0; j
< n_params
; j
++)
1840 unsigned short name_offset
;
1842 sprintf(name
, "arg %d", j
);
1843 print_begin_block(name
);
1845 name_offset
= tlb_read_short();
1847 printf("name: %04xh\n", name_offset
);
1849 value
= tlb_read_short();
1851 printf("type/offset %04xh\n", value
);
1852 if (name_offset
& 1) /* type follows */
1855 printf("type follows, using current offset for type\n");
1857 value
= offset
- funcs_start_offset
;
1861 printf("arg[%d] off = %#x (+%#x=%#x)\n",
1862 j
, value
, funcs_start_offset
, value
+ funcs_start_offset
);
1865 value
= sltg_print_compound_type(funcs_start_offset
, value
);
1866 if (name_offset
& 1)
1875 printf("arguments end at %#x\n", offset
);
1880 if (offset
!= funcs_start_offset
+ next
)
1881 dump_binary(funcs_start_offset
+ next
- offset
);
1889 printf("skipping %#x bytes\n", extra
);
1893 if (offset
< member_offset
+ sizeof(struct sltg_member_header
) + mem
->extra
)
1896 printf("skipping %d bytes\n", member_offset
+ (int)sizeof(struct sltg_member_header
) + mem
->extra
- offset
);
1897 dump_binary(member_offset
+ sizeof(struct sltg_member_header
) + mem
->extra
- offset
);
1901 printf("dumped %d (%#x) bytes\n", offset
- typeinfo_start_offset
, offset
- typeinfo_start_offset
);
1902 len
-= offset
- typeinfo_start_offset
;
1904 printf("sltg_tail %d (%#x) bytes:\n", len
, len
);
1905 saved_offset
= offset
;
1907 offset
= saved_offset
;
1908 print_short_hex("cFuncs");
1909 print_short_hex("cVars");
1910 print_short_hex("cImplTypes");
1911 print_short_hex("res06");
1912 print_short_hex("funcs_off");
1913 print_short_hex("vars_off");
1914 print_short_hex("impls_off");
1915 print_short_hex("funcs_bytes");
1916 print_short_hex("vars_bytes");
1917 print_short_hex("impls_bytes");
1918 print_short_hex("tdescalias_vt");
1919 print_short_hex("res16");
1920 print_short_hex("res18");
1921 print_short_hex("res1a");
1922 print_short_hex("simple_alias");
1923 print_short_hex("res1e");
1924 print_short_hex("cbSizeInstance");
1925 print_short_hex("cbAlignment");
1926 print_short_hex("res24");
1927 print_short_hex("res26");
1928 print_short_hex("cbSizeVft");
1929 print_short_hex("res2a");
1930 print_short_hex("res2c");
1931 print_short_hex("res2e");
1932 print_short_hex("res30");
1933 print_short_hex("res32");
1934 print_short_hex("res34");
1935 offset
= saved_offset
+ len
;
1938 static void sltg_dump(void)
1940 int i
, n_file_blocks
, n_first_blk
, size_of_index
, size_of_pad
;
1941 int name_table_start
, name_table_size
, saved_offset
;
1942 int libblk_start
, libblk_len
, hlpstr_len
, len
;
1943 const char *index
, *hlp_strings
;
1944 const struct block_entry
*entry
;
1946 n_file_blocks
= dump_sltg_header(&n_first_blk
, &size_of_index
, &size_of_pad
);
1948 saved_offset
= offset
;
1949 entry
= tlb_read((n_file_blocks
- 1) * sizeof(*entry
));
1951 index
= tlb_read(size_of_index
);
1953 offset
= saved_offset
;
1955 for (i
= 0; i
< n_file_blocks
- 1; i
++)
1956 dump_sltg_block_entry(i
, index
);
1958 saved_offset
= offset
;
1959 dump_sltg_index(n_file_blocks
);
1960 assert(offset
- saved_offset
== size_of_index
);
1962 dump_sltg_pad(size_of_pad
);
1964 /* read the helpstrings for later decoding */
1965 saved_offset
= offset
;
1967 for (i
= n_first_blk
- 1; entry
[i
].next
!= 0; i
= entry
[i
].next
- 1)
1968 tlb_read(entry
[i
].len
);
1970 libblk_start
= offset
;
1971 skip_sltg_library_block();
1973 typeinfo_cnt
= tlb_read_short();
1975 for (i
= 0; i
< typeinfo_cnt
; i
++)
1976 skip_sltg_other_typeinfo();
1978 len
= tlb_read_int();
1979 hlpstr_len
= (libblk_start
+ len
) - offset
;
1980 hlp_strings
= tlb_read(hlpstr_len
);
1981 assert(hlp_strings
!= NULL
);
1982 /* check the helpstrings header values */
1983 len
= *(int *)(hlp_strings
+ 2);
1984 assert(hlpstr_len
== len
+ 6);
1986 offset
= saved_offset
;
1988 for (i
= n_first_blk
- 1; entry
[i
].next
!= 0; i
= entry
[i
].next
- 1)
1993 saved_offset
= offset
;
1995 sprintf(name
, "Block %d", i
);
1996 print_begin_block(name
);
1997 magic
= tlb_read_short();
1998 assert(magic
== 0x0501);
2000 dump_binary(entry
[i
].len
);
2003 offset
= saved_offset
;
2005 print_begin_block(name
);
2006 dump_type(entry
[i
].len
, hlp_strings
);
2009 offset
= saved_offset
+ entry
[i
].len
;
2012 libblk_len
= entry
[i
].len
;
2014 libblk_start
= offset
;
2015 dump_sltg_library_block();
2017 printf("skipping 0x40 bytes\n");
2020 typeinfo_cnt
= print_short_dec("typeinfo count");
2023 for (i
= 0; i
< typeinfo_cnt
; i
++)
2024 dump_sltg_other_typeinfo(i
, hlp_strings
);
2026 len
= print_hex("offset from start of library block to name table");
2027 printf("%#x + %#x = %#x\n", libblk_start
, len
, libblk_start
+ len
);
2028 len
= (libblk_start
+ len
) - offset
;
2029 printf("skipping %#x bytes (encoded/compressed helpstrings)\n", len
);
2030 printf("max string length: %#x, strings length %#x\n", *(short *)hlp_strings
, *(int *)(hlp_strings
+ 2));
2034 len
= print_short_hex("name table jump");
2037 printf("skipping 0x000a bytes\n");
2038 dump_binary(0x000a);
2041 else if (len
== 0x0200)
2043 printf("skipping 0x002a bytes\n");
2044 dump_binary(0x002a);
2049 printf("FIXME: please report! (%#x)\n", len
);
2053 printf("skipping 0x200 bytes\n");
2057 name_table_size
= print_hex("name table size");
2059 name_table_start
= offset
;
2060 printf("name table offset = %#x\n\n", offset
);
2062 while (offset
< name_table_start
+ name_table_size
)
2070 len
= offset
- name_table_start
;
2071 aligned_len
= (len
+ 0x1f) & ~0x1f;
2072 if (aligned_len
- len
< 4)
2073 dump_binary(aligned_len
- len
);
2075 dump_binary(len
& 1);
2079 print_hex("01ffff01");
2080 len
= print_hex("length");
2081 printf("skipping %#x bytes\n", len
);
2085 len
= (libblk_start
+ libblk_len
) - offset
;
2086 printf("skipping libblk remainder %#x bytes\n", len
);
2090 /* FIXME: msodumper/olestream.py parses this block differently
2091 print_short_hex("unknown");
2092 print_short_hex("byte order mark");
2093 i = tlb_read_short();
2094 printf("version = %u.%u\n", i & 0xff, i >> 8);
2095 print_short_hex("system identifier");
2096 print_hex("unknown");
2099 printf("skipping 12 bytes\n");
2106 /* 0x0008,"TYPELIB",0 */
2110 printf("skipping 12 bytes\n");
2114 printf("skipping remainder 0x10 bytes\n");
2121 const DWORD
*sig
= PRD(0, sizeof(DWORD
));
2122 if (*sig
== MSFT_MAGIC
)
2128 enum FileSig
get_kind_tlb(void)
2130 const DWORD
*sig
= PRD(0, sizeof(DWORD
));
2131 if (sig
&& (*sig
== MSFT_MAGIC
|| *sig
== SLTG_MAGIC
)) return SIG_TLB
;