2 * Dump a typelib (tlb) file
4 * Copyright 2006 Jacek Caban
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
22 #include "wine/port.h"
32 #define MSFT_MAGIC 0x5446534d
33 #define HELPDLLFLAG 0x0100
86 VT_STREAMED_OBJECT
= 68,
87 VT_STORED_OBJECT
= 69,
91 VT_VERSIONED_STREAM
= 73,
98 VT_ILLEGALMASKED
= 0xfff,
104 typedef BOOL (*dump_seg_t
)(struct seg_t
*);
106 typedef struct seg_t
{
112 static seg_t segdir
[];
134 static int typeinfo_cnt
;
135 static int header_flags
= 0;
136 static BOOL msft_eof
= FALSE
;
138 static int msft_typeinfo_offs
[1000];
139 static int msft_typeinfo_kind
[1000];
140 static int msft_typeinfo_impltypes
[1000];
141 static int msft_typeinfo_elemcnt
[1000];
142 static int msft_typeinfo_cnt
= 0;
144 static const void *tlb_read(int size
) {
145 const void *ret
= PRD(offset
, size
);
155 static int tlb_read_int(void)
157 const int *ret
= tlb_read(sizeof(int));
158 return ret
? *ret
: -1;
161 static int tlb_read_short(void)
163 const short *ret
= tlb_read(sizeof(short));
164 return ret
? *ret
: -1;
167 static int tlb_read_byte(void)
169 const unsigned char *ret
= tlb_read(sizeof(char));
170 return ret
? *ret
: -1;
173 static void print_offset(void)
177 printf("%04x: ", offset
);
179 for(i
=0; i
<indent
; i
++)
183 static void print_begin_block(const char *name
)
186 printf("%s {\n", name
);
190 static void print_begin_block_id(const char *name
, int id
)
193 sprintf(buf
, "%s %d", name
, id
);
194 print_begin_block(buf
);
197 static void print_end_block(void)
206 static int print_hex(const char *name
)
210 printf("%s = %08x\n", name
, ret
=tlb_read_int());
214 static int print_hex_id(const char *name
, int id
)
217 sprintf(buf
, name
, id
);
218 return print_hex(buf
);
221 static int print_short_hex(const char *name
)
225 printf("%s = %xh\n", name
, ret
=tlb_read_short());
229 static int print_dec(const char *name
)
233 printf("%s = %d\n", name
, ret
=tlb_read_int());
237 static void print_guid(const char *name
)
239 GUID guid
= *(const GUID
*)tlb_read(sizeof(guid
));
243 printf("%s = {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n", name
,
244 guid
.Data1
, guid
.Data2
, guid
.Data3
, guid
.Data4
[0],
245 guid
.Data4
[1], guid
.Data4
[2], guid
.Data4
[3], guid
.Data4
[4],
246 guid
.Data4
[5], guid
.Data4
[6], guid
.Data4
[7]);
249 static void print_vartype(int vartype
)
251 static const char *vartypes
[VT_LPWSTR
+1] = {
252 "VT_EMPTY", "VT_NULL", "VT_I2", "VT_I4", "VT_R4",
253 "VT_R8", "VT_CY", "VT_DATE", "VT_BSTR", "VT_DISPATCH",
254 "VT_ERROR", "VT_BOOL", "VT_VARIANT", "VT_UNKNOWN","VT_DECIMAL",
255 "unk 15", "VT_I1", "VT_UI1", "VT_UI2", "VT_UI4",
256 "VT_I8", "VT_UI8", "VT_INT", "VT_UINT", "VT_VOID",
257 "VT_HRESULT", "VT_PTR", "VT_SAFEARRAY","VT_CARRAY", "VT_USERDEFINED",
258 "VT_LPSTR", "VT_LPWSTR"
261 vartype
&= VT_TYPEMASK
;
262 if (vartype
>= VT_EMPTY
&& vartype
<= VT_LPWSTR
)
263 printf("%s\n", vartypes
[vartype
]);
265 printf("unk %d\n", vartype
);
268 static void print_ctl2(const char *name
)
275 len
= tlb_read_short();
277 printf("%s = %d \"", name
, len
);
280 fwrite(buf
, len
, 1, stdout
);
285 printf("\\%02x", tlb_read_byte());
289 static void dump_binary(int n
)
293 for(i
= 1; i
<= n
; i
++) {
296 printf("%02x\n", tlb_read_byte());
302 printf("%02x ", tlb_read_byte());
310 static int dump_msft_varflags(void)
312 static const char *syskind
[] = {
313 "SYS_WIN16", "SYS_WIN32", "SYS_MAC", "SYS_WIN64", "unknown"
318 flags
= tlb_read_int();
320 if (kind
> 3) kind
= 4;
321 printf("varflags = %08x, syskind = %s\n", flags
, syskind
[kind
]);
325 static void dump_msft_version(void)
329 version
= tlb_read_int();
330 printf("version = %d.%d\n", version
& 0xff, version
>> 16);
333 static void dump_msft_header(void)
335 print_begin_block("Header");
339 print_hex("posguid");
342 header_flags
= dump_msft_varflags();
345 typeinfo_cnt
= print_dec("ntypeinfos");
346 print_dec("helpstring");
347 print_dec("helpstringcontext");
348 print_dec("helpcontext");
349 print_dec("nametablecount");
350 print_dec("nametablechars");
351 print_hex("NameOffset");
352 print_hex("helpfile");
353 print_hex("CustomDataOffset");
356 print_hex("dispatchpos");
362 static int dump_msft_typekind(void)
364 static const char *tkind
[TKIND_MAX
] = {
365 "TKIND_ENUM", "TKIND_RECORD", "TKIND_MODULE",
366 "TKIND_INTERFACE", "TKIND_DISPATCH", "TKIND_COCLASS",
367 "TKIND_ALIAS", "TKIND_UNION"
372 ret
= tlb_read_int();
373 typekind
= ret
& 0xf;
374 printf("typekind = %s, align = %d\n", typekind
< TKIND_MAX
? tkind
[typekind
] : "unknown", (ret
>> 11) & 0x1f);
378 static void dump_msft_typeinfobase(void)
380 print_begin_block_id("TypeInfoBase", msft_typeinfo_cnt
);
382 msft_typeinfo_kind
[msft_typeinfo_cnt
] = dump_msft_typekind();
383 msft_typeinfo_offs
[msft_typeinfo_cnt
] = print_hex("memoffset");
388 msft_typeinfo_elemcnt
[msft_typeinfo_cnt
] = print_hex("cElement");
393 print_hex("posguid");
395 print_hex("NameOffset");
396 print_hex("version");
397 print_hex("docstringoffs");
398 print_hex("docstringcontext");
399 print_hex("helpcontext");
400 print_hex("oCustData");
401 msft_typeinfo_impltypes
[msft_typeinfo_cnt
++] = print_short_hex("cImplTypes");
402 print_short_hex("bSizeVftt");
404 print_hex("datatype1");
405 print_hex("datatype2");
412 static BOOL
dump_msft_typeinfobases(seg_t
*seg
)
416 for(i
= 0; offset
< seg
->offset
+seg
->length
; i
++)
417 dump_msft_typeinfobase();
419 assert(offset
== seg
->offset
+seg
->length
);
423 static void dump_msft_impinfo(int n
)
425 print_begin_block_id("ImpInfo", n
);
428 print_hex("oImpInfo");
434 static BOOL
dump_msft_impinfos(seg_t
*seg
)
438 for(i
= 0; offset
< seg
->offset
+seg
->length
; i
++)
439 dump_msft_impinfo(i
);
441 assert(offset
== seg
->offset
+seg
->length
);
445 static void dump_msft_impfile(int n
)
447 print_begin_block_id("ImpFile", n
);
451 print_hex("version");
452 print_ctl2("impfile");
457 static BOOL
dump_msft_impfiles(seg_t
*seg
)
461 for(i
= 0; offset
< seg
->offset
+seg
->length
; i
++)
462 dump_msft_impfile(i
);
464 assert(offset
== seg
->offset
+seg
->length
);
468 static BOOL
dump_msft_reftabs(seg_t
*seg
)
470 print_begin_block("RefTab");
472 dump_binary(seg
->length
); /* FIXME */
479 static BOOL
dump_msft_guidhashtab(seg_t
*seg
)
481 print_begin_block("GuidHashTab");
483 dump_binary(seg
->length
); /* FIXME */
487 assert(offset
== seg
->offset
+seg
->length
);
491 static void dump_msft_guidentry(int n
)
493 print_begin_block_id("GuidEntry", n
);
496 print_hex("hreftype");
497 print_hex("next_hash");
502 static BOOL
dump_msft_guidtab(seg_t
*seg
)
506 for(i
= 0; offset
< seg
->offset
+seg
->length
; i
++)
507 dump_msft_guidentry(i
);
509 assert(offset
== seg
->offset
+seg
->length
);
513 static BOOL
dump_msft_namehashtab(seg_t
*seg
)
515 print_begin_block("NameHashTab");
517 dump_binary(seg
->length
); /* FIXME */
523 static void dump_string(int len
, int align_off
)
526 fwrite(tlb_read(len
), len
, 1, stdout
);
528 while((len
++ + align_off
) & 3)
529 printf("\\%2.2x", tlb_read_byte());
532 static void dump_msft_name(int base
, int n
)
536 print_begin_block_id("Name", n
);
538 print_hex("hreftype");
539 print_hex("next_hash");
540 len
= print_hex("namelen")&0xff;
550 static BOOL
dump_msft_nametab(seg_t
*seg
)
552 int i
, base
= offset
;
554 for(i
= 0; offset
< seg
->offset
+seg
->length
; i
++)
555 dump_msft_name(base
, i
);
557 assert(offset
== seg
->offset
+seg
->length
);
561 static void dump_msft_string(int n
)
565 print_begin_block_id("String", n
);
567 len
= print_short_hex("stringlen");
574 for(len
= 0; len
< 4; len
++)
575 printf("\\%2.2x", tlb_read_byte());
582 static BOOL
dump_msft_stringtab(seg_t
*seg
)
586 for(i
= 0; offset
< seg
->offset
+seg
->length
; i
++)
589 assert(offset
== seg
->offset
+seg
->length
);
593 static void dump_msft_typedesc(int n
)
595 print_begin_block_id("TYPEDESC", n
);
597 print_hex("hreftype");
603 static BOOL
dump_msft_typedesctab(seg_t
*seg
)
607 print_begin_block("TypedescTab");
609 for(i
= 0; offset
< seg
->offset
+seg
->length
; i
++)
610 dump_msft_typedesc(i
);
614 assert(offset
== seg
->offset
+seg
->length
);
618 static BOOL
dump_msft_arraydescs(seg_t
*seg
)
620 print_begin_block("ArrayDescriptions");
622 dump_binary(seg
->length
); /* FIXME */
628 static BOOL
dump_msft_custdata(seg_t
*seg
)
633 print_begin_block("CustData");
635 for(i
=0; offset
< seg
->offset
+seg
->length
; i
++) {
638 vt
= tlb_read_short();
644 printf(" len %d: ", n
);
650 printf("\\%2.2x ", tlb_read_byte());
651 printf("\\%2.2x\n", tlb_read_byte());
659 static void dump_msft_cdguid(int n
)
661 print_begin_block_id("CGUid", n
);
663 print_hex("GuidOffset");
664 print_hex("DataOffset");
670 static BOOL
dump_msft_cdguids(seg_t
*seg
)
674 for(i
= 0; offset
< seg
->offset
+seg
->length
; i
++)
677 assert(offset
== seg
->offset
+seg
->length
);
681 static BOOL
dump_msft_res0e(seg_t
*seg
)
683 print_begin_block("res0e");
684 dump_binary(seg
->length
);
690 static BOOL
dump_msft_res0f(seg_t
*seg
)
692 print_begin_block("res0f");
693 dump_binary(seg
->length
);
699 /* Used for function return value and arguments type */
700 static void dump_msft_datatype(const char *name
)
705 datatype
= tlb_read_int();
706 printf("%s = %08x", name
, datatype
);
709 print_vartype(datatype
);
714 if (datatype
> segdir
[SEGDIR_TYPEDESC
].length
) {
715 printf(", invalid offset\n");
719 /* FIXME: in case of VT_USERDEFINED use hreftype */
720 vt
= PRD(segdir
[SEGDIR_TYPEDESC
].offset
+ datatype
, 4*sizeof(short));
721 datatype
= vt
[0] & VT_TYPEMASK
;
722 if (datatype
== VT_PTR
) {
723 printf(", VT_PTR -> ");
727 vt
= PRD(segdir
[SEGDIR_TYPEDESC
].offset
+ vt
[2], 4*sizeof(short));
736 print_vartype(datatype
);
740 static void dump_defaultvalue(int id
)
745 offset
= tlb_read_int();
747 printf("default value[%d] = %08x", id
, offset
);
750 else if (offset
< 0) {
752 print_vartype((offset
& 0x7c000000) >> 26);
755 const unsigned short *vt
;
757 if (offset
> segdir
[SEGDIR_CUSTDATA
].length
) {
758 printf(", invalid offset\n");
762 vt
= PRD(segdir
[SEGDIR_CUSTDATA
].offset
+ offset
, sizeof(*vt
));
768 static void dump_msft_func(int n
)
770 int size
, args_cnt
, i
, extra_attr
, fkccic
;
772 print_begin_block_id("FuncRecord", n
);
774 size
= print_short_hex("size");
775 print_short_hex("index");
776 dump_msft_datatype("retval type");
778 print_short_hex("VtableOffset");
779 print_short_hex("funcdescsize");
780 fkccic
= print_hex("FKCCIC");
781 args_cnt
= print_short_hex("nrargs");
782 print_short_hex("noptargs");
784 extra_attr
= size
/sizeof(INT
) - 6 - args_cnt
*(fkccic
&0x1000 ? 4 : 3);
787 print_hex("helpcontext");
789 print_hex("oHelpString");
791 print_hex("toEntry");
797 print_hex("HelpStringContext");
799 print_hex("oCustData");
800 for(i
= 0; i
< extra_attr
-7; i
++)
801 print_hex_id("oArgCustData", i
);
803 if(fkccic
& 0x1000) {
804 for(i
=0; i
< args_cnt
; i
++)
805 dump_defaultvalue(i
);
808 for(i
=0; i
< args_cnt
; i
++) {
809 print_begin_block_id("param", i
);
811 /* FIXME: Handle default values */
812 dump_msft_datatype("datatype");
814 print_hex("paramflags");
822 static void dump_msft_var(int n
)
826 print_begin_block_id("VarRecord", n
);
828 size
= print_hex("recsize")&0x1ff;
829 print_hex("DataType");
831 print_short_hex("VarKind");
832 print_short_hex("vardescsize");
833 print_hex("OffsValue");
835 if(size
> 5*sizeof(INT
))
836 dump_binary(size
- 5*sizeof(INT
));
841 static void dump_msft_ref(int n
)
843 print_begin_block_id("RefRecord", n
);
845 print_hex("reftype");
847 print_hex("oCustData");
853 static void dump_msft_coclass(int n
)
859 for(i
=0; i
< msft_typeinfo_impltypes
[n
]; i
++)
863 static BOOL
dump_msft_typeinfo(int n
)
867 print_begin_block_id("TypeInfo", n
);
869 if((msft_typeinfo_kind
[n
] & 0xf) == TKIND_COCLASS
) {
870 dump_msft_coclass(n
);
877 for(i
= 0; i
< LOWORD(msft_typeinfo_elemcnt
[n
]); i
++)
880 for(i
= 0; i
< HIWORD(msft_typeinfo_elemcnt
[n
]); i
++)
883 for(i
= 0; i
< LOWORD(msft_typeinfo_elemcnt
[n
]); i
++)
884 print_hex_id("func %d id", i
);
886 for(i
= 0; i
< HIWORD(msft_typeinfo_elemcnt
[n
]); i
++)
887 print_hex_id("var %d id", i
);
889 for(i
= 0; i
< LOWORD(msft_typeinfo_elemcnt
[n
]); i
++)
890 print_hex_id("func %d name", i
);
892 for(i
= 0; i
< HIWORD(msft_typeinfo_elemcnt
[n
]); i
++)
893 print_hex_id("var %d name", i
);
895 for(i
= 0; i
< LOWORD(msft_typeinfo_elemcnt
[n
]); i
++)
896 print_hex_id("func %d offset", i
);
898 for(i
= 0; i
< HIWORD(msft_typeinfo_elemcnt
[n
]); i
++)
899 print_hex_id("var %d offset", i
);
906 static seg_t segdir
[] = {
907 {"TypeInfoTab", dump_msft_typeinfobases
, -1, -1},
908 {"ImpInfo", dump_msft_impinfos
, -1, -1},
909 {"ImpFiles", dump_msft_impfiles
, -1, -1},
910 {"RefTab", dump_msft_reftabs
, -1, -1},
911 {"GuidHashTab", dump_msft_guidhashtab
, -1, -1},
912 {"GuidTab", dump_msft_guidtab
, -1, -1},
913 {"NameHashTab", dump_msft_namehashtab
, -1, -1},
914 {"pNameTab", dump_msft_nametab
, -1, -1},
915 {"pStringTab", dump_msft_stringtab
, -1, -1},
916 {"TypedescTab", dump_msft_typedesctab
, -1, -1},
917 {"ArrayDescriptions", dump_msft_arraydescs
, -1, -1},
918 {"CustData", dump_msft_custdata
, -1, -1},
919 {"CDGuid", dump_msft_cdguids
, -1, -1},
920 {"res0e", dump_msft_res0e
, -1, -1},
921 {"res0f", dump_msft_res0f
, -1, -1}
924 static void dump_msft_seg(seg_t
*seg
)
926 print_begin_block(seg
->name
);
928 seg
->offset
= print_hex("offset");
929 seg
->length
= print_dec("length");
936 static void dump_msft_segdir(void)
940 print_begin_block("SegDir");
942 for(i
=0; i
< sizeof(segdir
)/sizeof(segdir
[0]); i
++)
943 dump_msft_seg(segdir
+i
);
948 static BOOL
dump_offset(void)
952 for(i
=0; i
< sizeof(segdir
)/sizeof(segdir
[0]); i
++)
953 if(segdir
[i
].offset
== offset
)
954 return segdir
[i
].func(segdir
+i
);
956 for(i
=0; i
< msft_typeinfo_cnt
; i
++)
957 if(msft_typeinfo_offs
[i
] == offset
)
958 return dump_msft_typeinfo(i
);
963 enum FileSig
get_kind_msft(void)
965 const DWORD
*sig
= PRD(0, sizeof(DWORD
));
966 return sig
&& *sig
== MSFT_MAGIC
? SIG_MSFT
: SIG_UNKNOWN
;
975 for(i
=0; i
< typeinfo_cnt
; i
++)
976 print_hex_id("typeinfo %d offset", i
);
978 if(header_flags
& HELPDLLFLAG
)
979 print_hex("help dll offset");
987 print_hex("unknown");