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
[15];
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 unsigned 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)
176 for(i
=0; i
<indent
; i
++)
180 static void print_begin_block(const char *name
)
183 printf("%s {\n", name
);
187 static void print_begin_block_id(const char *name
, int id
)
190 sprintf(buf
, "%s %d", name
, id
);
191 print_begin_block(buf
);
194 static void print_end_block(void)
203 static int print_hex(const char *name
)
207 printf("%s = %08xh\n", name
, ret
=tlb_read_int());
211 static int print_hex_id(const char *name
, int id
)
214 sprintf(buf
, name
, id
);
215 return print_hex(buf
);
218 static int print_short_hex(const char *name
)
222 printf("%s = %04xh\n", name
, ret
=tlb_read_short());
226 static int print_dec(const char *name
)
230 printf("%s = %d\n", name
, ret
=tlb_read_int());
234 static void print_guid(const char *name
)
236 GUID guid
= *(const GUID
*)tlb_read(sizeof(guid
));
240 printf("%s = {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n", name
,
241 guid
.Data1
, guid
.Data2
, guid
.Data3
, guid
.Data4
[0],
242 guid
.Data4
[1], guid
.Data4
[2], guid
.Data4
[3], guid
.Data4
[4],
243 guid
.Data4
[5], guid
.Data4
[6], guid
.Data4
[7]);
246 static void print_vartype(int vartype
)
248 static const char *vartypes
[VT_LPWSTR
+1] = {
249 "VT_EMPTY", "VT_NULL", "VT_I2", "VT_I4", "VT_R4",
250 "VT_R8", "VT_CY", "VT_DATE", "VT_BSTR", "VT_DISPATCH",
251 "VT_ERROR", "VT_BOOL", "VT_VARIANT", "VT_UNKNOWN","VT_DECIMAL",
252 "unk 15", "VT_I1", "VT_UI1", "VT_UI2", "VT_UI4",
253 "VT_I8", "VT_UI8", "VT_INT", "VT_UINT", "VT_VOID",
254 "VT_HRESULT", "VT_PTR", "VT_SAFEARRAY","VT_CARRAY", "VT_USERDEFINED",
255 "VT_LPSTR", "VT_LPWSTR"
258 vartype
&= VT_TYPEMASK
;
259 if (vartype
>= VT_EMPTY
&& vartype
<= VT_LPWSTR
)
260 printf("%s\n", vartypes
[vartype
]);
262 printf("unk %d\n", vartype
);
265 static void print_ctl2(const char *name
)
272 len
= tlb_read_short();
274 printf("%s = %d \"", name
, len
);
277 fwrite(buf
, len
, 1, stdout
);
282 printf("\\%02x", tlb_read_byte());
286 static void dump_binary(int n
)
290 for(i
= 1; i
<= n
; i
++) {
293 printf("%02x\n", tlb_read_byte());
299 printf("%02x ", tlb_read_byte());
307 static int dump_msft_varflags(void)
309 static const char *syskind
[] = {
310 "SYS_WIN16", "SYS_WIN32", "SYS_MAC", "SYS_WIN64", "unknown"
315 flags
= tlb_read_int();
317 if (kind
> 3) kind
= 4;
318 printf("varflags = %08x, syskind = %s\n", flags
, syskind
[kind
]);
322 static void dump_msft_version(void)
326 version
= tlb_read_int();
327 printf("version = %u.%u\n", version
& 0xffff, version
>> 16);
330 static void dump_msft_header(void)
332 print_begin_block("Header");
336 print_hex("posguid");
339 header_flags
= dump_msft_varflags();
342 typeinfo_cnt
= print_dec("ntypeinfos");
343 print_dec("helpstring");
344 print_dec("helpstringcontext");
345 print_dec("helpcontext");
346 print_dec("nametablecount");
347 print_dec("nametablechars");
348 print_hex("NameOffset");
349 print_hex("helpfile");
350 print_hex("CustomDataOffset");
353 print_hex("dispatchpos");
359 static int dump_msft_typekind(void)
361 static const char *tkind
[TKIND_MAX
] = {
362 "TKIND_ENUM", "TKIND_RECORD", "TKIND_MODULE",
363 "TKIND_INTERFACE", "TKIND_DISPATCH", "TKIND_COCLASS",
364 "TKIND_ALIAS", "TKIND_UNION"
369 ret
= tlb_read_int();
370 typekind
= ret
& 0xf;
371 printf("typekind = %s, align = %d\n", typekind
< TKIND_MAX
? tkind
[typekind
] : "unknown", (ret
>> 11) & 0x1f);
375 static void dump_msft_typeinfobase(void)
377 print_begin_block_id("TypeInfoBase", msft_typeinfo_cnt
);
379 msft_typeinfo_kind
[msft_typeinfo_cnt
] = dump_msft_typekind();
380 msft_typeinfo_offs
[msft_typeinfo_cnt
] = print_hex("memoffset");
385 msft_typeinfo_elemcnt
[msft_typeinfo_cnt
] = print_hex("cElement");
390 print_hex("posguid");
392 print_hex("NameOffset");
393 print_hex("version");
394 print_hex("docstringoffs");
395 print_hex("docstringcontext");
396 print_hex("helpcontext");
397 print_hex("oCustData");
398 msft_typeinfo_impltypes
[msft_typeinfo_cnt
++] = print_short_hex("cImplTypes");
399 print_short_hex("bSizeVftt");
401 print_hex("datatype1");
402 print_hex("datatype2");
409 static BOOL
dump_msft_typeinfobases(seg_t
*seg
)
413 for(i
= 0; offset
< seg
->offset
+seg
->length
; i
++)
414 dump_msft_typeinfobase();
416 assert(offset
== seg
->offset
+seg
->length
);
420 static void dump_msft_impinfo(int n
)
422 print_begin_block_id("ImpInfo", n
);
425 print_hex("oImpInfo");
431 static BOOL
dump_msft_impinfos(seg_t
*seg
)
435 for(i
= 0; offset
< seg
->offset
+seg
->length
; i
++)
436 dump_msft_impinfo(i
);
438 assert(offset
== seg
->offset
+seg
->length
);
442 static void dump_msft_impfile(int n
)
444 print_begin_block_id("ImpFile", n
);
448 print_hex("version");
449 print_ctl2("impfile");
454 static BOOL
dump_msft_impfiles(seg_t
*seg
)
458 for(i
= 0; offset
< seg
->offset
+seg
->length
; i
++)
459 dump_msft_impfile(i
);
461 assert(offset
== seg
->offset
+seg
->length
);
465 static BOOL
dump_msft_reftabs(seg_t
*seg
)
467 print_begin_block("RefTab");
469 dump_binary(seg
->length
); /* FIXME */
476 static BOOL
dump_msft_guidhashtab(seg_t
*seg
)
478 print_begin_block("GuidHashTab");
480 dump_binary(seg
->length
); /* FIXME */
484 assert(offset
== seg
->offset
+seg
->length
);
488 static void dump_msft_guidentry(int n
)
490 print_begin_block_id("GuidEntry", n
);
493 print_hex("hreftype");
494 print_hex("next_hash");
499 static BOOL
dump_msft_guidtab(seg_t
*seg
)
503 for(i
= 0; offset
< seg
->offset
+seg
->length
; i
++)
504 dump_msft_guidentry(i
);
506 assert(offset
== seg
->offset
+seg
->length
);
510 static BOOL
dump_msft_namehashtab(seg_t
*seg
)
512 print_begin_block("NameHashTab");
514 dump_binary(seg
->length
); /* FIXME */
520 static void print_string(int len
)
523 fwrite(tlb_read(len
), len
, 1, stdout
);
527 static void dump_string(int len
, int align_off
)
531 while((len
++ + align_off
) & 3)
532 printf("\\%2.2x", tlb_read_byte());
535 static void dump_msft_name(int base
, int n
)
539 print_begin_block_id("Name", n
);
541 print_hex("hreftype");
542 print_hex("next_hash");
543 len
= print_hex("namelen")&0xff;
553 static BOOL
dump_msft_nametab(seg_t
*seg
)
555 int i
, base
= offset
;
557 for(i
= 0; offset
< seg
->offset
+seg
->length
; i
++)
558 dump_msft_name(base
, i
);
560 assert(offset
== seg
->offset
+seg
->length
);
564 static void dump_msft_string(int n
)
568 print_begin_block_id("String", n
);
570 len
= print_short_hex("stringlen");
577 for(len
= 0; len
< 4; len
++)
578 printf("\\%2.2x", tlb_read_byte());
585 static BOOL
dump_msft_stringtab(seg_t
*seg
)
589 for(i
= 0; offset
< seg
->offset
+seg
->length
; i
++)
592 assert(offset
== seg
->offset
+seg
->length
);
596 static void dump_msft_typedesc(int n
)
598 print_begin_block_id("TYPEDESC", n
);
600 print_hex("hreftype");
606 static BOOL
dump_msft_typedesctab(seg_t
*seg
)
610 print_begin_block("TypedescTab");
612 for(i
= 0; offset
< seg
->offset
+seg
->length
; i
++)
613 dump_msft_typedesc(i
);
617 assert(offset
== seg
->offset
+seg
->length
);
621 static BOOL
dump_msft_arraydescs(seg_t
*seg
)
623 print_begin_block("ArrayDescriptions");
625 dump_binary(seg
->length
); /* FIXME */
631 static BOOL
dump_msft_custdata(seg_t
*seg
)
636 print_begin_block("CustData");
638 for(i
=0; offset
< seg
->offset
+seg
->length
; i
++) {
641 vt
= tlb_read_short();
647 printf(" len %d: ", n
);
653 printf("\\%2.2x ", tlb_read_byte());
654 printf("\\%2.2x\n", tlb_read_byte());
662 static void dump_msft_cdguid(int n
)
664 print_begin_block_id("CGUid", n
);
666 print_hex("GuidOffset");
667 print_hex("DataOffset");
673 static BOOL
dump_msft_cdguids(seg_t
*seg
)
677 for(i
= 0; offset
< seg
->offset
+seg
->length
; i
++)
680 assert(offset
== seg
->offset
+seg
->length
);
684 static BOOL
dump_msft_res0e(seg_t
*seg
)
686 print_begin_block("res0e");
687 dump_binary(seg
->length
);
693 static BOOL
dump_msft_res0f(seg_t
*seg
)
695 print_begin_block("res0f");
696 dump_binary(seg
->length
);
702 /* Used for function return value and arguments type */
703 static void dump_msft_datatype(const char *name
)
708 datatype
= tlb_read_int();
709 printf("%s = %08x", name
, datatype
);
712 print_vartype(datatype
);
717 if (datatype
> segdir
[SEGDIR_TYPEDESC
].length
) {
718 printf(", invalid offset\n");
722 /* FIXME: in case of VT_USERDEFINED use hreftype */
723 vt
= PRD(segdir
[SEGDIR_TYPEDESC
].offset
+ datatype
, 4*sizeof(short));
724 datatype
= vt
[0] & VT_TYPEMASK
;
725 if (datatype
== VT_PTR
) {
726 printf(", VT_PTR -> ");
730 vt
= PRD(segdir
[SEGDIR_TYPEDESC
].offset
+ vt
[2], 4*sizeof(short));
739 print_vartype(datatype
);
743 static void dump_defaultvalue(int id
)
748 offset
= tlb_read_int();
750 printf("default value[%d] = %08x", id
, offset
);
753 else if (offset
< 0) {
755 print_vartype((offset
& 0x7c000000) >> 26);
758 const unsigned short *vt
;
760 if (offset
> segdir
[SEGDIR_CUSTDATA
].length
) {
761 printf(", invalid offset\n");
765 vt
= PRD(segdir
[SEGDIR_CUSTDATA
].offset
+ offset
, sizeof(*vt
));
771 static void dump_msft_func(int n
)
773 int size
, args_cnt
, i
, extra_attr
, fkccic
;
775 print_begin_block_id("FuncRecord", n
);
777 size
= print_short_hex("size");
778 print_short_hex("index");
779 dump_msft_datatype("retval type");
781 print_short_hex("VtableOffset");
782 print_short_hex("funcdescsize");
783 fkccic
= print_hex("FKCCIC");
784 args_cnt
= print_short_hex("nrargs");
785 print_short_hex("noptargs");
787 extra_attr
= size
/sizeof(INT
) - 6 - args_cnt
*(fkccic
&0x1000 ? 4 : 3);
790 print_hex("helpcontext");
792 print_hex("oHelpString");
794 print_hex("toEntry");
800 print_hex("HelpStringContext");
802 print_hex("oCustData");
803 for(i
= 0; i
< extra_attr
-7; i
++)
804 print_hex_id("oArgCustData", i
);
806 if(fkccic
& 0x1000) {
807 for(i
=0; i
< args_cnt
; i
++)
808 dump_defaultvalue(i
);
811 for(i
=0; i
< args_cnt
; i
++) {
812 print_begin_block_id("param", i
);
814 /* FIXME: Handle default values */
815 dump_msft_datatype("datatype");
817 print_hex("paramflags");
825 static void dump_msft_var(int n
)
829 print_begin_block_id("VarRecord", n
);
831 size
= print_hex("recsize")&0x1ff;
832 print_hex("DataType");
834 print_short_hex("VarKind");
835 print_short_hex("vardescsize");
836 print_hex("OffsValue");
838 if(size
> 5*sizeof(INT
))
839 dump_binary(size
- 5*sizeof(INT
));
844 static void dump_msft_ref(int n
)
846 print_begin_block_id("RefRecord", n
);
848 print_hex("reftype");
850 print_hex("oCustData");
856 static void dump_msft_coclass(int n
)
862 for(i
=0; i
< msft_typeinfo_impltypes
[n
]; i
++)
866 static BOOL
dump_msft_typeinfo(int n
)
870 print_begin_block_id("TypeInfo", n
);
872 if((msft_typeinfo_kind
[n
] & 0xf) == TKIND_COCLASS
) {
873 dump_msft_coclass(n
);
880 for(i
= 0; i
< LOWORD(msft_typeinfo_elemcnt
[n
]); i
++)
883 for(i
= 0; i
< HIWORD(msft_typeinfo_elemcnt
[n
]); i
++)
886 for(i
= 0; i
< LOWORD(msft_typeinfo_elemcnt
[n
]); i
++)
887 print_hex_id("func %d id", i
);
889 for(i
= 0; i
< HIWORD(msft_typeinfo_elemcnt
[n
]); i
++)
890 print_hex_id("var %d id", i
);
892 for(i
= 0; i
< LOWORD(msft_typeinfo_elemcnt
[n
]); i
++)
893 print_hex_id("func %d name", i
);
895 for(i
= 0; i
< HIWORD(msft_typeinfo_elemcnt
[n
]); i
++)
896 print_hex_id("var %d name", i
);
898 for(i
= 0; i
< LOWORD(msft_typeinfo_elemcnt
[n
]); i
++)
899 print_hex_id("func %d offset", i
);
901 for(i
= 0; i
< HIWORD(msft_typeinfo_elemcnt
[n
]); i
++)
902 print_hex_id("var %d offset", i
);
909 static seg_t segdir
[] = {
910 {"TypeInfoTab", dump_msft_typeinfobases
, -1, -1},
911 {"ImpInfo", dump_msft_impinfos
, -1, -1},
912 {"ImpFiles", dump_msft_impfiles
, -1, -1},
913 {"RefTab", dump_msft_reftabs
, -1, -1},
914 {"GuidHashTab", dump_msft_guidhashtab
, -1, -1},
915 {"GuidTab", dump_msft_guidtab
, -1, -1},
916 {"NameHashTab", dump_msft_namehashtab
, -1, -1},
917 {"pNameTab", dump_msft_nametab
, -1, -1},
918 {"pStringTab", dump_msft_stringtab
, -1, -1},
919 {"TypedescTab", dump_msft_typedesctab
, -1, -1},
920 {"ArrayDescriptions", dump_msft_arraydescs
, -1, -1},
921 {"CustData", dump_msft_custdata
, -1, -1},
922 {"CDGuid", dump_msft_cdguids
, -1, -1},
923 {"res0e", dump_msft_res0e
, -1, -1},
924 {"res0f", dump_msft_res0f
, -1, -1}
927 static void dump_msft_seg(seg_t
*seg
)
929 print_begin_block(seg
->name
);
931 seg
->offset
= print_hex("offset");
932 seg
->length
= print_dec("length");
939 static void dump_msft_segdir(void)
943 print_begin_block("SegDir");
945 for(i
=0; i
< sizeof(segdir
)/sizeof(segdir
[0]); i
++)
946 dump_msft_seg(segdir
+i
);
951 static BOOL
dump_offset(void)
955 for(i
=0; i
< sizeof(segdir
)/sizeof(segdir
[0]); i
++)
956 if(segdir
[i
].offset
== offset
)
957 return segdir
[i
].func(segdir
+i
);
959 for(i
=0; i
< msft_typeinfo_cnt
; i
++)
960 if(msft_typeinfo_offs
[i
] == offset
)
961 return dump_msft_typeinfo(i
);
966 enum FileSig
get_kind_msft(void)
968 const DWORD
*sig
= PRD(0, sizeof(DWORD
));
969 return sig
&& *sig
== MSFT_MAGIC
? SIG_MSFT
: SIG_UNKNOWN
;
978 for(i
=0; i
< typeinfo_cnt
; i
++)
979 print_hex_id("typeinfo %d offset", i
);
981 if(header_flags
& HELPDLLFLAG
)
982 print_hex("help dll offset");
990 print_hex("unknown");