| /* | |
| * Dump a typelib (tlb) file | |
| * | |
| * Copyright 2006 Jacek Caban | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | |
| */ | |
| #include "config.h" | |
| #include "wine/port.h" | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <assert.h> | |
| #include "windef.h" | |
| #include "winedump.h" | |
| #define MSFT_MAGIC 0x5446534d | |
| #define HELPDLLFLAG 0x0100 | |
| enum TYPEKIND { | |
| TKIND_ENUM = 0, | |
| TKIND_RECORD, | |
| TKIND_MODULE, | |
| TKIND_INTERFACE, | |
| TKIND_DISPATCH, | |
| TKIND_COCLASS, | |
| TKIND_ALIAS, | |
| TKIND_UNION, | |
| TKIND_MAX | |
| }; | |
| enum VARENUM { | |
| VT_EMPTY = 0, | |
| VT_NULL = 1, | |
| VT_I2 = 2, | |
| VT_I4 = 3, | |
| VT_R4 = 4, | |
| VT_R8 = 5, | |
| VT_CY = 6, | |
| VT_DATE = 7, | |
| VT_BSTR = 8, | |
| VT_DISPATCH = 9, | |
| VT_ERROR = 10, | |
| VT_BOOL = 11, | |
| VT_VARIANT = 12, | |
| VT_UNKNOWN = 13, | |
| VT_DECIMAL = 14, | |
| VT_I1 = 16, | |
| VT_UI1 = 17, | |
| VT_UI2 = 18, | |
| VT_UI4 = 19, | |
| VT_I8 = 20, | |
| VT_UI8 = 21, | |
| VT_INT = 22, | |
| VT_UINT = 23, | |
| VT_VOID = 24, | |
| VT_HRESULT = 25, | |
| VT_PTR = 26, | |
| VT_SAFEARRAY = 27, | |
| VT_CARRAY = 28, | |
| VT_USERDEFINED = 29, | |
| VT_LPSTR = 30, | |
| VT_LPWSTR = 31, | |
| VT_RECORD = 36, | |
| VT_INT_PTR = 37, | |
| VT_UINT_PTR = 38, | |
| VT_FILETIME = 64, | |
| VT_BLOB = 65, | |
| VT_STREAM = 66, | |
| VT_STORAGE = 67, | |
| VT_STREAMED_OBJECT = 68, | |
| VT_STORED_OBJECT = 69, | |
| VT_BLOB_OBJECT = 70, | |
| VT_CF = 71, | |
| VT_CLSID = 72, | |
| VT_VERSIONED_STREAM = 73, | |
| VT_BSTR_BLOB = 0xfff, | |
| VT_VECTOR = 0x1000, | |
| VT_ARRAY = 0x2000, | |
| VT_BYREF = 0x4000, | |
| VT_RESERVED = 0x8000, | |
| VT_ILLEGAL = 0xffff, | |
| VT_ILLEGALMASKED = 0xfff, | |
| VT_TYPEMASK = 0xfff | |
| }; | |
| struct seg_t; | |
| typedef BOOL (*dump_seg_t)(struct seg_t*); | |
| typedef struct seg_t { | |
| const char *name; | |
| dump_seg_t func; | |
| int offset; | |
| int length; | |
| } seg_t; | |
| static seg_t segdir[]; | |
| enum SEGDIRTYPE { | |
| SEGDIR_TYPEINFO, | |
| SEGDIR_IMPINFO, | |
| SEGDIR_IMPFILES, | |
| SEGDIR_REF, | |
| SEGDIR_GUIDHASH, | |
| SEGDIR_GUID, | |
| SEGDIR_NAMEHASH, | |
| SEGDIR_NAME, | |
| SEGDIR_STRING, | |
| SEGDIR_TYPEDESC, | |
| SEGDIR_ARRAYDESC, | |
| SEGDIR_CUSTDATA, | |
| SEGDIR_CDGUID, | |
| SEGDIR_res0e, | |
| SEGDIR_res0f | |
| }; | |
| static int offset=0; | |
| static int indent; | |
| static int typeinfo_cnt; | |
| static int header_flags = 0; | |
| static BOOL msft_eof = FALSE; | |
| static int msft_typeinfo_offs[1000]; | |
| static int msft_typeinfo_kind[1000]; | |
| static int msft_typeinfo_impltypes[1000]; | |
| static int msft_typeinfo_elemcnt[1000]; | |
| static int msft_typeinfo_cnt = 0; | |
| static const void *tlb_read(int size) { | |
| const void *ret = PRD(offset, size); | |
| if(ret) | |
| offset += size; | |
| else | |
| msft_eof = TRUE; | |
| return ret; | |
| } | |
| static int tlb_read_int(void) | |
| { | |
| const int *ret = tlb_read(sizeof(int)); | |
| return ret ? *ret : -1; | |
| } | |
| static int tlb_read_short(void) | |
| { | |
| const short *ret = tlb_read(sizeof(short)); | |
| return ret ? *ret : -1; | |
| } | |
| static int tlb_read_byte(void) | |
| { | |
| const unsigned char *ret = tlb_read(sizeof(char)); | |
| return ret ? *ret : -1; | |
| } | |
| static void print_offset(void) | |
| { | |
| int i; | |
| printf("%04x: ", offset); | |
| for(i=0; i<indent; i++) | |
| printf(" "); | |
| } | |
| static void print_begin_block(const char *name) | |
| { | |
| print_offset(); | |
| printf("%s {\n", name); | |
| indent++; | |
| } | |
| static void print_begin_block_id(const char *name, int id) | |
| { | |
| char buf[64]; | |
| sprintf(buf, "%s %d", name, id); | |
| print_begin_block(buf); | |
| } | |
| static void print_end_block(void) | |
| { | |
| indent--; | |
| print_offset(); | |
| printf("}\n"); | |
| print_offset(); | |
| printf("\n"); | |
| } | |
| static int print_hex(const char *name) | |
| { | |
| int ret; | |
| print_offset(); | |
| printf("%s = %08x\n", name, ret=tlb_read_int()); | |
| return ret; | |
| } | |
| static int print_hex_id(const char *name, int id) | |
| { | |
| char buf[64]; | |
| sprintf(buf, name, id); | |
| return print_hex(buf); | |
| } | |
| static int print_short_hex(const char *name) | |
| { | |
| int ret; | |
| print_offset(); | |
| printf("%s = %xh\n", name, ret=tlb_read_short()); | |
| return ret; | |
| } | |
| static int print_dec(const char *name) | |
| { | |
| int ret; | |
| print_offset(); | |
| printf("%s = %d\n", name, ret=tlb_read_int()); | |
| return ret; | |
| } | |
| static void print_guid(const char *name) | |
| { | |
| GUID guid = *(const GUID*)tlb_read(sizeof(guid)); | |
| print_offset(); | |
| printf("%s = {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n", name, | |
| guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], | |
| guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], | |
| guid.Data4[5], guid.Data4[6], guid.Data4[7]); | |
| } | |
| static void print_vartype(int vartype) | |
| { | |
| static const char *vartypes[VT_LPWSTR+1] = { | |
| "VT_EMPTY", "VT_NULL", "VT_I2", "VT_I4", "VT_R4", | |
| "VT_R8", "VT_CY", "VT_DATE", "VT_BSTR", "VT_DISPATCH", | |
| "VT_ERROR", "VT_BOOL", "VT_VARIANT", "VT_UNKNOWN","VT_DECIMAL", | |
| "unk 15", "VT_I1", "VT_UI1", "VT_UI2", "VT_UI4", | |
| "VT_I8", "VT_UI8", "VT_INT", "VT_UINT", "VT_VOID", | |
| "VT_HRESULT", "VT_PTR", "VT_SAFEARRAY","VT_CARRAY", "VT_USERDEFINED", | |
| "VT_LPSTR", "VT_LPWSTR" | |
| }; | |
| vartype &= VT_TYPEMASK; | |
| if (vartype >= VT_EMPTY && vartype <= VT_LPWSTR) | |
| printf("%s\n", vartypes[vartype]); | |
| else | |
| printf("unk %d\n", vartype); | |
| } | |
| static void print_ctl2(const char *name) | |
| { | |
| int len; | |
| const char *buf; | |
| print_offset(); | |
| len = tlb_read_short(); | |
| printf("%s = %d \"", name, len); | |
| len >>= 2; | |
| buf = tlb_read(len); | |
| fwrite(buf, len, 1, stdout); | |
| printf("\""); | |
| len += 2; | |
| while(len++ & 3) | |
| printf("\\%02x", tlb_read_byte()); | |
| printf("\n"); | |
| } | |
| static void dump_binary(int n) | |
| { | |
| int i; | |
| for(i = 1; i <= n; i++) { | |
| switch(i & 0x0f) { | |
| case 0: | |
| printf("%02x\n", tlb_read_byte()); | |
| break; | |
| case 1: | |
| print_offset(); | |
| /* fall through */ | |
| default: | |
| printf("%02x ", tlb_read_byte()); | |
| } | |
| } | |
| if(n&0x0f) | |
| printf("\n"); | |
| } | |
| static int dump_msft_varflags(void) | |
| { | |
| static const char *syskind[] = { | |
| "SYS_WIN16", "SYS_WIN32", "SYS_MAC", "SYS_WIN64", "unknown" | |
| }; | |
| int kind, flags; | |
| print_offset(); | |
| flags = tlb_read_int(); | |
| kind = flags & 0xf; | |
| if (kind > 3) kind = 4; | |
| printf("varflags = %08x, syskind = %s\n", flags, syskind[kind]); | |
| return flags; | |
| } | |
| static void dump_msft_version(void) | |
| { | |
| int version; | |
| print_offset(); | |
| version = tlb_read_int(); | |
| printf("version = %d.%d\n", version & 0xff, version >> 16); | |
| } | |
| static void dump_msft_header(void) | |
| { | |
| print_begin_block("Header"); | |
| print_hex("magic1"); | |
| print_hex("magic2"); | |
| print_hex("posguid"); | |
| print_hex("lcid"); | |
| print_hex("lcid2"); | |
| header_flags = dump_msft_varflags(); | |
| dump_msft_version(); | |
| print_hex("flags"); | |
| typeinfo_cnt = print_dec("ntypeinfos"); | |
| print_dec("helpstring"); | |
| print_dec("helpstringcontext"); | |
| print_dec("helpcontext"); | |
| print_dec("nametablecount"); | |
| print_dec("nametablechars"); | |
| print_hex("NameOffset"); | |
| print_hex("helpfile"); | |
| print_hex("CustomDataOffset"); | |
| print_hex("res44"); | |
| print_hex("res48"); | |
| print_hex("dispatchpos"); | |
| print_hex("res50"); | |
| print_end_block(); | |
| } | |
| static int dump_msft_typekind(void) | |
| { | |
| static const char *tkind[TKIND_MAX] = { | |
| "TKIND_ENUM", "TKIND_RECORD", "TKIND_MODULE", | |
| "TKIND_INTERFACE", "TKIND_DISPATCH", "TKIND_COCLASS", | |
| "TKIND_ALIAS", "TKIND_UNION" | |
| }; | |
| int ret, typekind; | |
| print_offset(); | |
| ret = tlb_read_int(); | |
| typekind = ret & 0xf; | |
| printf("typekind = %s, align = %d\n", typekind < TKIND_MAX ? tkind[typekind] : "unknown", (ret >> 11) & 0x1f); | |
| return ret; | |
| } | |
| static void dump_msft_typeinfobase(void) | |
| { | |
| print_begin_block_id("TypeInfoBase", msft_typeinfo_cnt); | |
| msft_typeinfo_kind[msft_typeinfo_cnt] = dump_msft_typekind(); | |
| msft_typeinfo_offs[msft_typeinfo_cnt] = print_hex("memoffset"); | |
| print_hex("res2"); | |
| print_hex("res3"); | |
| print_hex("res4"); | |
| print_hex("res5"); | |
| msft_typeinfo_elemcnt[msft_typeinfo_cnt] = print_hex("cElement"); | |
| print_hex("res7"); | |
| print_hex("res8"); | |
| print_hex("res9"); | |
| print_hex("resA"); | |
| print_hex("posguid"); | |
| print_hex("flags"); | |
| print_hex("NameOffset"); | |
| print_hex("version"); | |
| print_hex("docstringoffs"); | |
| print_hex("docstringcontext"); | |
| print_hex("helpcontext"); | |
| print_hex("oCustData"); | |
| msft_typeinfo_impltypes[msft_typeinfo_cnt++] = print_short_hex("cImplTypes"); | |
| print_short_hex("bSizeVftt"); | |
| print_dec("size"); | |
| print_hex("datatype1"); | |
| print_hex("datatype2"); | |
| print_hex("res18"); | |
| print_hex("res19"); | |
| print_end_block(); | |
| } | |
| static BOOL dump_msft_typeinfobases(seg_t *seg) | |
| { | |
| int i; | |
| for(i = 0; offset < seg->offset+seg->length; i++) | |
| dump_msft_typeinfobase(); | |
| assert(offset == seg->offset+seg->length); | |
| return TRUE; | |
| } | |
| static void dump_msft_impinfo(int n) | |
| { | |
| print_begin_block_id("ImpInfo", n); | |
| print_hex("flags"); | |
| print_hex("oImpInfo"); | |
| print_hex("oGuid"); | |
| print_end_block(); | |
| } | |
| static BOOL dump_msft_impinfos(seg_t *seg) | |
| { | |
| int i; | |
| for(i = 0; offset < seg->offset+seg->length; i++) | |
| dump_msft_impinfo(i); | |
| assert(offset == seg->offset+seg->length); | |
| return TRUE; | |
| } | |
| static void dump_msft_impfile(int n) | |
| { | |
| print_begin_block_id("ImpFile", n); | |
| print_hex("guid"); | |
| print_hex("lcid"); | |
| print_hex("version"); | |
| print_ctl2("impfile"); | |
| print_end_block(); | |
| } | |
| static BOOL dump_msft_impfiles(seg_t *seg) | |
| { | |
| int i; | |
| for(i = 0; offset < seg->offset+seg->length; i++) | |
| dump_msft_impfile(i); | |
| assert(offset == seg->offset+seg->length); | |
| return TRUE; | |
| } | |
| static BOOL dump_msft_reftabs(seg_t *seg) | |
| { | |
| print_begin_block("RefTab"); | |
| dump_binary(seg->length); /* FIXME */ | |
| print_end_block(); | |
| return TRUE; | |
| } | |
| static BOOL dump_msft_guidhashtab(seg_t *seg) | |
| { | |
| print_begin_block("GuidHashTab"); | |
| dump_binary(seg->length); /* FIXME */ | |
| print_end_block(); | |
| assert(offset == seg->offset+seg->length); | |
| return TRUE; | |
| } | |
| static void dump_msft_guidentry(int n) | |
| { | |
| print_begin_block_id("GuidEntry", n); | |
| print_guid("guid"); | |
| print_hex("hreftype"); | |
| print_hex("next_hash"); | |
| print_end_block(); | |
| } | |
| static BOOL dump_msft_guidtab(seg_t *seg) | |
| { | |
| int i; | |
| for(i = 0; offset < seg->offset+seg->length; i++) | |
| dump_msft_guidentry(i); | |
| assert(offset == seg->offset+seg->length); | |
| return TRUE; | |
| } | |
| static BOOL dump_msft_namehashtab(seg_t *seg) | |
| { | |
| print_begin_block("NameHashTab"); | |
| dump_binary(seg->length); /* FIXME */ | |
| print_end_block(); | |
| return TRUE; | |
| } | |
| static void dump_string(int len, int align_off) | |
| { | |
| printf("\""); | |
| fwrite(tlb_read(len), len, 1, stdout); | |
| printf("\" "); | |
| while((len++ + align_off) & 3) | |
| printf("\\%2.2x", tlb_read_byte()); | |
| } | |
| static void dump_msft_name(int base, int n) | |
| { | |
| int len; | |
| print_begin_block_id("Name", n); | |
| print_hex("hreftype"); | |
| print_hex("next_hash"); | |
| len = print_hex("namelen")&0xff; | |
| print_offset(); | |
| printf("name = "); | |
| dump_string(len, 0); | |
| printf("\n"); | |
| print_end_block(); | |
| } | |
| static BOOL dump_msft_nametab(seg_t *seg) | |
| { | |
| int i, base = offset; | |
| for(i = 0; offset < seg->offset+seg->length; i++) | |
| dump_msft_name(base, i); | |
| assert(offset == seg->offset+seg->length); | |
| return TRUE; | |
| } | |
| static void dump_msft_string(int n) | |
| { | |
| int len; | |
| print_begin_block_id("String", n); | |
| len = print_short_hex("stringlen"); | |
| print_offset(); | |
| printf("string = "); | |
| dump_string(len, 2); | |
| if(len < 3) { | |
| for(len = 0; len < 4; len++) | |
| printf("\\%2.2x", tlb_read_byte()); | |
| } | |
| printf("\n"); | |
| print_end_block(); | |
| } | |
| static BOOL dump_msft_stringtab(seg_t *seg) | |
| { | |
| int i; | |
| for(i = 0; offset < seg->offset+seg->length; i++) | |
| dump_msft_string(i); | |
| assert(offset == seg->offset+seg->length); | |
| return TRUE; | |
| } | |
| static void dump_msft_typedesc(int n) | |
| { | |
| print_begin_block_id("TYPEDESC", n); | |
| print_hex("hreftype"); | |
| print_hex("vt"); | |
| print_end_block(); | |
| } | |
| static BOOL dump_msft_typedesctab(seg_t *seg) | |
| { | |
| int i; | |
| print_begin_block("TypedescTab"); | |
| for(i = 0; offset < seg->offset+seg->length; i++) | |
| dump_msft_typedesc(i); | |
| print_end_block(); | |
| assert(offset == seg->offset+seg->length); | |
| return TRUE; | |
| } | |
| static BOOL dump_msft_arraydescs(seg_t *seg) | |
| { | |
| print_begin_block("ArrayDescriptions"); | |
| dump_binary(seg->length); /* FIXME */ | |
| print_end_block(); | |
| return TRUE; | |
| } | |
| static BOOL dump_msft_custdata(seg_t *seg) | |
| { | |
| unsigned short vt; | |
| unsigned i, n; | |
| print_begin_block("CustData"); | |
| for(i=0; offset < seg->offset+seg->length; i++) { | |
| print_offset(); | |
| vt = tlb_read_short(); | |
| printf("vt %d", vt); | |
| n = tlb_read_int(); | |
| switch(vt) { | |
| case VT_BSTR: | |
| printf(" len %d: ", n); | |
| dump_string(n, 2); | |
| printf("\n"); | |
| break; | |
| default: | |
| printf(": %x ", n); | |
| printf("\\%2.2x ", tlb_read_byte()); | |
| printf("\\%2.2x\n", tlb_read_byte()); | |
| } | |
| } | |
| print_end_block(); | |
| return TRUE; | |
| } | |
| static void dump_msft_cdguid(int n) | |
| { | |
| print_begin_block_id("CGUid", n); | |
| print_hex("GuidOffset"); | |
| print_hex("DataOffset"); | |
| print_hex("next"); | |
| print_end_block(); | |
| } | |
| static BOOL dump_msft_cdguids(seg_t *seg) | |
| { | |
| int i; | |
| for(i = 0; offset < seg->offset+seg->length; i++) | |
| dump_msft_cdguid(i); | |
| assert(offset == seg->offset+seg->length); | |
| return TRUE; | |
| } | |
| static BOOL dump_msft_res0e(seg_t *seg) | |
| { | |
| print_begin_block("res0e"); | |
| dump_binary(seg->length); | |
| print_end_block(); | |
| return TRUE; | |
| } | |
| static BOOL dump_msft_res0f(seg_t *seg) | |
| { | |
| print_begin_block("res0f"); | |
| dump_binary(seg->length); | |
| print_end_block(); | |
| return TRUE; | |
| } | |
| /* Used for function return value and arguments type */ | |
| static void dump_msft_datatype(const char *name) | |
| { | |
| int datatype; | |
| print_offset(); | |
| datatype = tlb_read_int(); | |
| printf("%s = %08x", name, datatype); | |
| if (datatype < 0) { | |
| printf(", "); | |
| print_vartype(datatype); | |
| } | |
| else { | |
| const short *vt; | |
| if (datatype > segdir[SEGDIR_TYPEDESC].length) { | |
| printf(", invalid offset\n"); | |
| return; | |
| } | |
| /* FIXME: in case of VT_USERDEFINED use hreftype */ | |
| vt = PRD(segdir[SEGDIR_TYPEDESC].offset + datatype, 4*sizeof(short)); | |
| datatype = vt[0] & VT_TYPEMASK; | |
| if (datatype == VT_PTR) { | |
| printf(", VT_PTR -> "); | |
| if (vt[3] < 0) | |
| datatype = vt[2]; | |
| else { | |
| vt = PRD(segdir[SEGDIR_TYPEDESC].offset + vt[2], 4*sizeof(short)); | |
| datatype = *vt; | |
| } | |
| } | |
| else { | |
| printf(", "); | |
| datatype = *vt; | |
| } | |
| print_vartype(datatype); | |
| } | |
| } | |
| static void dump_defaultvalue(int id) | |
| { | |
| int offset; | |
| print_offset(); | |
| offset = tlb_read_int(); | |
| printf("default value[%d] = %08x", id, offset); | |
| if (offset == -1) | |
| printf("\n"); | |
| else if (offset < 0) { | |
| printf(", "); | |
| print_vartype((offset & 0x7c000000) >> 26); | |
| } | |
| else { | |
| const unsigned short *vt; | |
| if (offset > segdir[SEGDIR_CUSTDATA].length) { | |
| printf(", invalid offset\n"); | |
| return; | |
| } | |
| vt = PRD(segdir[SEGDIR_CUSTDATA].offset + offset, sizeof(*vt)); | |
| printf(", "); | |
| print_vartype(*vt); | |
| } | |
| } | |
| static void dump_msft_func(int n) | |
| { | |
| int size, args_cnt, i, extra_attr, fkccic; | |
| print_begin_block_id("FuncRecord", n); | |
| size = print_short_hex("size"); | |
| print_short_hex("index"); | |
| dump_msft_datatype("retval type"); | |
| print_hex("flags"); | |
| print_short_hex("VtableOffset"); | |
| print_short_hex("funcdescsize"); | |
| fkccic = print_hex("FKCCIC"); | |
| args_cnt = print_short_hex("nrargs"); | |
| print_short_hex("noptargs"); | |
| extra_attr = size/sizeof(INT) - 6 - args_cnt*(fkccic&0x1000 ? 4 : 3); | |
| if(extra_attr) | |
| print_hex("helpcontext"); | |
| if(extra_attr >= 2) | |
| print_hex("oHelpString"); | |
| if(extra_attr >= 3) | |
| print_hex("toEntry"); | |
| if(extra_attr >= 4) | |
| print_hex("res9"); | |
| if(extra_attr >= 5) | |
| print_hex("resA"); | |
| if(extra_attr >= 6) | |
| print_hex("HelpStringContext"); | |
| if(extra_attr >= 7) | |
| print_hex("oCustData"); | |
| for(i = 0; i < extra_attr-7; i++) | |
| print_hex_id("oArgCustData", i); | |
| if(fkccic & 0x1000) { | |
| for(i=0; i < args_cnt; i++) | |
| dump_defaultvalue(i); | |
| } | |
| for(i=0; i < args_cnt; i++) { | |
| print_begin_block_id("param", i); | |
| /* FIXME: Handle default values */ | |
| dump_msft_datatype("datatype"); | |
| print_hex("name"); | |
| print_hex("paramflags"); | |
| print_end_block(); | |
| } | |
| print_end_block(); | |
| } | |
| static void dump_msft_var(int n) | |
| { | |
| INT size; | |
| print_begin_block_id("VarRecord", n); | |
| size = print_hex("recsize")&0x1ff; | |
| print_hex("DataType"); | |
| print_hex("flags"); | |
| print_short_hex("VarKind"); | |
| print_short_hex("vardescsize"); | |
| print_hex("OffsValue"); | |
| if(size > 5*sizeof(INT)) | |
| dump_binary(size - 5*sizeof(INT)); | |
| print_end_block(); | |
| } | |
| static void dump_msft_ref(int n) | |
| { | |
| print_begin_block_id("RefRecord", n); | |
| print_hex("reftype"); | |
| print_hex("flags"); | |
| print_hex("oCustData"); | |
| print_hex("onext"); | |
| print_end_block(); | |
| } | |
| static void dump_msft_coclass(int n) | |
| { | |
| int i; | |
| print_dec("size"); | |
| for(i=0; i < msft_typeinfo_impltypes[n]; i++) | |
| dump_msft_ref(i); | |
| } | |
| static BOOL dump_msft_typeinfo(int n) | |
| { | |
| int i; | |
| print_begin_block_id("TypeInfo", n); | |
| if((msft_typeinfo_kind[n] & 0xf) == TKIND_COCLASS) { | |
| dump_msft_coclass(n); | |
| print_end_block(); | |
| return TRUE; | |
| } | |
| print_dec("size"); | |
| for(i = 0; i < LOWORD(msft_typeinfo_elemcnt[n]); i++) | |
| dump_msft_func(i); | |
| for(i = 0; i < HIWORD(msft_typeinfo_elemcnt[n]); i++) | |
| dump_msft_var(i); | |
| for(i = 0; i < LOWORD(msft_typeinfo_elemcnt[n]); i++) | |
| print_hex_id("func %d id", i); | |
| for(i = 0; i < HIWORD(msft_typeinfo_elemcnt[n]); i++) | |
| print_hex_id("var %d id", i); | |
| for(i = 0; i < LOWORD(msft_typeinfo_elemcnt[n]); i++) | |
| print_hex_id("func %d name", i); | |
| for(i = 0; i < HIWORD(msft_typeinfo_elemcnt[n]); i++) | |
| print_hex_id("var %d name", i); | |
| for(i = 0; i < LOWORD(msft_typeinfo_elemcnt[n]); i++) | |
| print_hex_id("func %d offset", i); | |
| for(i = 0; i < HIWORD(msft_typeinfo_elemcnt[n]); i++) | |
| print_hex_id("var %d offset", i); | |
| print_end_block(); | |
| return TRUE; | |
| } | |
| static seg_t segdir[] = { | |
| {"TypeInfoTab", dump_msft_typeinfobases, -1, -1}, | |
| {"ImpInfo", dump_msft_impinfos, -1, -1}, | |
| {"ImpFiles", dump_msft_impfiles, -1, -1}, | |
| {"RefTab", dump_msft_reftabs, -1, -1}, | |
| {"GuidHashTab", dump_msft_guidhashtab, -1, -1}, | |
| {"GuidTab", dump_msft_guidtab, -1, -1}, | |
| {"NameHashTab", dump_msft_namehashtab, -1, -1}, | |
| {"pNameTab", dump_msft_nametab, -1, -1}, | |
| {"pStringTab", dump_msft_stringtab, -1, -1}, | |
| {"TypedescTab", dump_msft_typedesctab, -1, -1}, | |
| {"ArrayDescriptions", dump_msft_arraydescs, -1, -1}, | |
| {"CustData", dump_msft_custdata, -1, -1}, | |
| {"CDGuid", dump_msft_cdguids, -1, -1}, | |
| {"res0e", dump_msft_res0e, -1, -1}, | |
| {"res0f", dump_msft_res0f, -1, -1} | |
| }; | |
| static void dump_msft_seg(seg_t *seg) | |
| { | |
| print_begin_block(seg->name); | |
| seg->offset = print_hex("offset"); | |
| seg->length = print_dec("length"); | |
| print_hex("res08"); | |
| print_hex("res0c"); | |
| print_end_block(); | |
| } | |
| static void dump_msft_segdir(void) | |
| { | |
| int i; | |
| print_begin_block("SegDir"); | |
| for(i=0; i < sizeof(segdir)/sizeof(segdir[0]); i++) | |
| dump_msft_seg(segdir+i); | |
| print_end_block(); | |
| } | |
| static BOOL dump_offset(void) | |
| { | |
| int i; | |
| for(i=0; i < sizeof(segdir)/sizeof(segdir[0]); i++) | |
| if(segdir[i].offset == offset) | |
| return segdir[i].func(segdir+i); | |
| for(i=0; i < msft_typeinfo_cnt; i++) | |
| if(msft_typeinfo_offs[i] == offset) | |
| return dump_msft_typeinfo(i); | |
| return FALSE; | |
| } | |
| enum FileSig get_kind_msft(void) | |
| { | |
| const DWORD *sig = PRD(0, sizeof(DWORD)); | |
| return sig && *sig == MSFT_MAGIC ? SIG_MSFT : SIG_UNKNOWN; | |
| } | |
| void msft_dump(void) | |
| { | |
| int i; | |
| dump_msft_header(); | |
| for(i=0; i < typeinfo_cnt; i++) | |
| print_hex_id("typeinfo %d offset", i); | |
| if(header_flags & HELPDLLFLAG) | |
| print_hex("help dll offset"); | |
| print_offset(); | |
| printf("\n"); | |
| dump_msft_segdir(); | |
| while(!msft_eof) { | |
| if(!dump_offset()) | |
| print_hex("unknown"); | |
| } | |
| } |