Release 1.5.29.
[wine] / tools / winedump / tlb.c
1 /*
2  *  Dump a typelib (tlb) file
3  *
4  *  Copyright 2006 Jacek Caban
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
24 #include <stdlib.h>
25 #include <string.h>
26 #include <assert.h>
27
28 #include "windef.h"
29
30 #include "winedump.h"
31
32 #define MSFT_MAGIC 0x5446534d
33 #define HELPDLLFLAG 0x0100
34
35 enum TYPEKIND {
36   TKIND_ENUM = 0,
37   TKIND_RECORD,
38   TKIND_MODULE,
39   TKIND_INTERFACE,
40   TKIND_DISPATCH,
41   TKIND_COCLASS,
42   TKIND_ALIAS,
43   TKIND_UNION,
44   TKIND_MAX
45 };
46
47 struct seg_t;
48
49 typedef int (*dump_seg_t)(struct seg_t*);
50
51 typedef struct seg_t {
52     const char *name;
53     dump_seg_t func;
54     int offset;
55     int length;
56 } seg_t;
57
58 extern seg_t segdir[];
59
60 static int offset=0;
61 static int indent;
62 static int typeinfo_cnt;
63 static int header_flags = 0;
64 static int msft_eof = 0;
65
66 static int msft_typeinfo_offs[1000];
67 static int msft_typeinfo_kind[1000];
68 static int msft_typeinfo_impltypes[1000];
69 static int msft_typeinfo_elemcnt[1000];
70 static int msft_typeinfo_cnt = 0;
71
72 static const void *tlb_read(int size) {
73     const void *ret = PRD(offset, size);
74
75     if(ret)
76         offset += size;
77     else
78         msft_eof = -1;
79
80     return ret;
81 }
82
83 static int tlb_read_int(void)
84 {
85     const int *ret = (const int*)tlb_read(sizeof(int));
86     return ret ? *ret : -1;
87 }
88
89 static int tlb_read_short(void)
90 {
91     const short *ret = (const short*)tlb_read(sizeof(short));
92     return ret ? *ret : -1;
93 }
94
95 static int tlb_read_byte(void)
96 {
97     const unsigned char *ret = (const unsigned char*)tlb_read(sizeof(char));
98     return ret ? *ret : -1;
99 }
100
101 static void print_offset(void)
102 {
103     int i;
104
105     printf("%04x:   ", offset);
106
107     for(i=0; i<indent; i++)
108         printf("    ");
109 }
110
111 static void print_begin_block(const char *name)
112 {
113     print_offset();
114     printf("%s {\n", name);
115     indent++;
116 }
117
118 static void print_begin_block_id(const char *name, int id)
119 {
120     char buf[64];
121     sprintf(buf, "%s %d", name, id);
122     print_begin_block(buf);
123 }
124
125 static void print_end_block(void)
126 {
127     indent--;
128     print_offset();
129     printf("}\n");
130     print_offset();
131     printf("\n");
132 }
133
134 static int print_hex(const char *name)
135 {
136     int ret;
137     print_offset();
138     printf("%s = %08x\n", name, ret=tlb_read_int());
139     return ret;
140 }
141
142 static int print_hex_id(const char *name, int id)
143 {
144     char buf[64];
145     sprintf(buf, name, id);
146     return print_hex(buf);
147 }
148
149 static int print_short_hex(const char *name)
150 {
151     int ret;
152     print_offset();
153     printf("%s = %xh\n", name, ret=tlb_read_short());
154     return ret;
155 }
156
157 static int print_dec(const char *name)
158 {
159     int ret;
160     print_offset();
161     printf("%s = %d\n", name, ret=tlb_read_int());
162     return ret;
163 }
164
165 static void print_guid(const char *name)
166 {
167     GUID guid = *(const GUID*)tlb_read(sizeof(guid));
168
169     print_offset();
170
171     printf("%s = {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n", name,
172            guid.Data1, guid.Data2, guid.Data3, guid.Data4[0],
173            guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4],
174            guid.Data4[5], guid.Data4[6], guid.Data4[7]);
175 }
176
177 static void print_ctl2(const char *name)
178 {
179     int len;
180     const char *buf;
181
182     print_offset();
183
184     len = tlb_read_short();
185
186     printf("%s = %d \"", name, len);
187     len >>= 2;
188     buf = tlb_read(len);
189     fwrite(buf, len, 1, stdout);
190     printf("\"");
191     len += 2;
192
193     while(len++ & 3)
194         printf("\\%02x", tlb_read_byte());
195     printf("\n");
196 }
197
198 static void dump_binary(int n)
199 {
200     int i;
201
202     for(i = 1; i <= n; i++) {
203         switch(i & 0x0f) {
204         case 0:
205             printf("%02x\n", tlb_read_byte());
206             break;
207         case 1:
208             print_offset();
209             /* fall through */
210         default:
211             printf("%02x ", tlb_read_byte());
212         }
213     }
214
215     if(n&0x0f)
216         printf("\n");
217 }
218
219 static void dump_msft_header(void)
220 {
221     print_begin_block("Header");
222
223     print_hex("magic1");
224     print_hex("magic2");
225     print_hex("posguid");
226     print_hex("lcid");
227     print_hex("lsid2");
228     header_flags = print_hex("varflags");
229     print_hex("version");
230     print_hex("flags");
231     typeinfo_cnt = print_dec("ntypeinfos");
232     print_hex("helpstring");
233     print_hex("helpstringcontext");
234     print_hex("helpcontext");
235     print_dec("nametablecont");
236     print_dec("nametablechars");
237     print_hex("NameOffset");
238     print_hex("helpfile");
239     print_hex("CustomDataOffset");
240     print_hex("res44");
241     print_hex("res48");
242     print_hex("dispatchpos");
243     print_hex("res50");
244
245     print_end_block();
246 }
247
248 static void dump_msft_typeinfobase(void)
249 {
250     print_begin_block_id("TypeInfoBase", msft_typeinfo_cnt);
251
252     msft_typeinfo_kind[msft_typeinfo_cnt] = print_hex("typekind");
253     msft_typeinfo_offs[msft_typeinfo_cnt] = print_hex("memoffset");
254     print_hex("res2");
255     print_hex("res3");
256     print_hex("res4");
257     print_hex("res5");
258     msft_typeinfo_elemcnt[msft_typeinfo_cnt] = print_hex("cElement");
259     print_hex("res7");
260     print_hex("res8");
261     print_hex("res9");
262     print_hex("resA");
263     print_hex("posguid");
264     print_hex("flags");
265     print_hex("NameOffset");
266     print_hex("version");
267     print_hex("docstringoffs");
268     print_hex("docstringcontext");
269     print_hex("helpcontext");
270     print_hex("oCustData");
271     msft_typeinfo_impltypes[msft_typeinfo_cnt++] = print_short_hex("cImplTypes");
272     print_short_hex("bSizeVftt");
273     print_dec("size");
274     print_hex("datatype1");
275     print_hex("datatype2");
276     print_hex("res18");
277     print_hex("res19");
278
279     print_end_block();
280 }
281
282 static int dump_msft_typeinfobases(seg_t *seg)
283 {
284     int i;
285
286     for(i = 0; offset < seg->offset+seg->length; i++)
287         dump_msft_typeinfobase();
288
289     assert(offset == seg->offset+seg->length);
290     return -1;
291 }
292
293 static void dump_msft_impinfo(int n)
294 {
295     print_begin_block_id("ImpInfo", n);
296
297     print_hex("flags");
298     print_hex("oImpInfo");
299     print_hex("oGuid");
300
301     print_end_block();
302 }
303
304 static int dump_msft_impinfos(seg_t *seg)
305 {
306     int i;
307
308     for(i = 0; offset < seg->offset+seg->length; i++)
309         dump_msft_impinfo(i);
310
311     assert(offset == seg->offset+seg->length);
312     return -1;
313 }
314
315 static void dump_msft_impfile(int n)
316 {
317     print_begin_block_id("ImpFile", n);
318
319     print_hex("guid");
320     print_hex("lcid");
321     print_hex("version");
322     print_ctl2("impfile");
323
324     print_end_block();
325 }
326
327 static int dump_msft_impfiles(seg_t *seg)
328 {
329     int i;
330
331     for(i = 0; offset < seg->offset+seg->length; i++)
332         dump_msft_impfile(i);
333
334     assert(offset == seg->offset+seg->length);
335     return -1;
336 }
337
338 static int dump_msft_reftabs(seg_t *seg)
339 {
340     print_begin_block("RefTab");
341
342     dump_binary(seg->length); /* FIXME */
343
344     print_end_block();
345
346     return -1;
347 }
348
349 static int dump_msft_libtab(seg_t *seg)
350 {
351     print_begin_block("LibTab");
352
353     dump_binary(seg->length); /* FIXME */
354
355     print_end_block();
356
357     assert(offset == seg->offset+seg->length);
358     return -1;
359 }
360
361 static void dump_msft_guidentry(int n)
362 {
363     print_begin_block_id("GuidEntry", n);
364
365     print_guid("guid");
366     print_hex("hreftype");
367     print_hex("next_hash");
368
369     print_end_block();
370 }
371
372 static int dump_msft_guidtab(seg_t *seg)
373 {
374     int i;
375
376     for(i = 0; offset < seg->offset+seg->length; i++)
377         dump_msft_guidentry(i);
378
379     assert(offset == seg->offset+seg->length);
380     return -1;
381 }
382
383 static int dump_msft_res07(seg_t *seg)
384 {
385     print_begin_block("res07");
386
387     dump_binary(seg->length); /* FIXME */
388
389     print_end_block();
390     return -1;
391 }
392
393 static void dump_msft_name(int base, int n)
394 {
395     int len;
396
397     print_begin_block_id("Name", n);
398
399     print_hex("hreftype");
400     print_hex("next_hash");
401     len = print_hex("namelen")&0xff;
402
403     print_offset();
404     printf("name = \"");
405     fwrite(tlb_read(len), len, 1, stdout);
406     printf("\" ");
407     while(len++ & 3)
408         printf("\\%2.2x", tlb_read_byte());
409     printf("\n");
410
411     print_end_block();
412 }
413
414 static int dump_msft_nametab(seg_t *seg)
415 {
416     int i, base = offset;
417
418     for(i = 0; offset < seg->offset+seg->length; i++)
419         dump_msft_name(base, i);
420
421     assert(offset == seg->offset+seg->length);
422     return -1;
423 }
424
425 static int dump_msft_stringtab(seg_t *seg)
426 {
427     print_begin_block("StringTab");
428
429     dump_binary(seg->length); /* FIXME */
430
431     print_end_block();
432
433     return -1;
434 }
435
436 static void dump_msft_typedesc(int n)
437 {
438     print_begin_block_id("TYPEDESC", n);
439
440     print_hex("hreftype");
441     print_hex("vt");
442
443     print_end_block();
444 }
445
446 static int dump_msft_typedesctab(seg_t *seg)
447 {
448     int i;
449
450     print_begin_block("TypedescTab");
451
452     for(i = 0; offset < seg->offset+seg->length; i++)
453         dump_msft_typedesc(i);
454
455     print_end_block();
456
457     assert(offset == seg->offset+seg->length);
458     return -1;
459 }
460
461 static int dump_msft_arraydescs(seg_t *seg)
462 {
463     print_begin_block("ArrayDescriptions");
464
465     dump_binary(seg->length); /* FIXME */
466
467     print_end_block();
468     return -1;
469 }
470
471 static int dump_msft_custdata(seg_t *seg)
472 {
473     print_begin_block("CustData");
474
475     dump_binary(seg->length); /* FIXME */
476
477     print_end_block();
478     return -1;
479 }
480
481 static void dump_msft_cdguid(int n)
482 {
483     print_begin_block_id("CGUid", n);
484
485     print_hex("GuidOffset");
486     print_hex("DataOffset");
487     print_hex("next");
488
489     print_end_block();
490 }
491
492 static int dump_msft_cdguids(seg_t *seg)
493 {
494     int i;
495
496     for(i = 0; offset < seg->offset+seg->length; i++)
497         dump_msft_cdguid(i);
498
499     assert(offset == seg->offset+seg->length);
500     return -1;
501 }
502
503 static int dump_msft_res0e(seg_t *seg)
504 {
505     print_begin_block("res0e");
506     dump_binary(seg->length);
507     print_end_block();
508
509     return -1;
510 }
511
512 static int dump_msft_res0f(seg_t *seg)
513 {
514     print_begin_block("res0f");
515     dump_binary(seg->length);
516     print_end_block();
517
518     return -1;
519 }
520
521 static void dump_msft_func(int n)
522 {
523     int size, args_cnt, i, extra_attr, fkccic;
524
525     print_begin_block_id("FuncRecord", n);
526
527     size = print_short_hex("size");
528     print_short_hex("index");
529     print_hex("DataType");
530     print_hex("flags");
531     print_short_hex("VtableOffset");
532     print_short_hex("funcdescsize");
533     fkccic = print_hex("FKCCIC");
534     args_cnt = print_short_hex("nrargs");
535     print_short_hex("noptargs");
536
537     extra_attr = size/sizeof(INT) - 6 - args_cnt*(fkccic&0x1000 ? 4 : 3);
538
539     if(extra_attr)
540         print_hex("helpcontext");
541     if(extra_attr >= 2)
542         print_hex("oHelpString");
543     if(extra_attr >= 3)
544         print_hex("toEntry");
545     if(extra_attr >= 4)
546         print_hex("res9");
547     if(extra_attr >= 5)
548         print_hex("resA");
549     if(extra_attr >= 6)
550         print_hex("HelpStringContext");
551     if(extra_attr >= 7)
552         print_hex("oCustData");
553
554     if(fkccic & 0x1000) {
555         for(i=0; i < args_cnt; i++)
556             print_hex_id("default value[%d]", i);
557     }
558
559     for(i=0; i < args_cnt; i++) {
560         print_begin_block_id("param", i);
561
562         /* FIXME: Handle default values */
563         print_hex("data[0]");
564         print_hex("paramflags");
565         print_hex("data[2]");
566
567         print_end_block();
568     }
569
570     print_end_block();
571 }
572
573 static void dump_msft_var(int n)
574 {
575     INT size;
576
577     print_begin_block_id("VarRecord", n);
578
579     size = print_hex("recsize")&0x1ff;
580     print_hex("DataType");
581     print_hex("flags");
582     print_short_hex("VarKind");
583     print_short_hex("vardescsize");
584     print_hex("OffsValue");
585
586     if(size > 5*sizeof(INT))
587         dump_binary(size - 5*sizeof(INT));
588
589     print_end_block();
590 }
591
592 static void dump_msft_ref(int n)
593 {
594     print_begin_block_id("RefRecord", n);
595
596     print_hex("reftype");
597     print_hex("flags");
598     print_hex("oCustData");
599     print_hex("onext");
600
601     print_end_block();
602 }
603
604 static void dump_msft_coclass(int n)
605 {
606     int i;
607
608     print_dec("size");
609
610     for(i=0; i < msft_typeinfo_impltypes[n]; i++)
611         dump_msft_ref(i);
612 }
613
614 static int dump_msft_typeinfo(int n)
615 {
616     int i;
617
618     print_begin_block_id("TypeInfo", n);
619
620     if((msft_typeinfo_kind[n] & 0xf) == TKIND_COCLASS) {
621         dump_msft_coclass(n);
622         print_end_block();
623         return -1;
624     }
625
626     print_dec("size");
627
628     for(i = 0; i < LOWORD(msft_typeinfo_elemcnt[n]); i++)
629         dump_msft_func(i);
630
631     for(i = 0; i < HIWORD(msft_typeinfo_elemcnt[n]); i++)
632         dump_msft_var(i);
633
634     for(i = 0; i < LOWORD(msft_typeinfo_elemcnt[n]); i++)
635         print_hex_id("func %d id", i);
636
637     for(i = 0; i < HIWORD(msft_typeinfo_elemcnt[n]); i++)
638         print_hex_id("var %d id", i);
639
640     for(i = 0; i < LOWORD(msft_typeinfo_elemcnt[n]); i++)
641         print_hex_id("func %d name", i);
642
643     for(i = 0; i < HIWORD(msft_typeinfo_elemcnt[n]); i++)
644         print_hex_id("var %d name", i);
645
646     for(i = 0; i < LOWORD(msft_typeinfo_elemcnt[n]); i++)
647         print_hex_id("func %d offset", i);
648
649     for(i = 0; i < HIWORD(msft_typeinfo_elemcnt[n]); i++)
650         print_hex_id("var %d offset", i);
651
652     print_end_block();
653
654     return -1;
655 }
656
657 seg_t segdir[] = {
658     {"TypeInfoTab",       dump_msft_typeinfobases, -1, -1},
659     {"ImpInfo",           dump_msft_impinfos, -1, -1},
660     {"ImpFiles",          dump_msft_impfiles, -1, -1},
661     {"RefTab",            dump_msft_reftabs, -1, -1},
662     {"LibTab",            dump_msft_libtab, -1, -1},
663     {"GuidTab",           dump_msft_guidtab, -1, -1},
664     {"res07",             dump_msft_res07, -1, -1},
665     {"pNameTab",          dump_msft_nametab, -1, -1},
666     {"pStringTab",        dump_msft_stringtab, -1, -1},
667     {"TypedescTab",       dump_msft_typedesctab, -1, -1},
668     {"ArrayDescriptions", dump_msft_arraydescs, -1, -1},
669     {"CustData",          dump_msft_custdata, -1, -1},
670     {"CDGuid",            dump_msft_cdguids, -1, -1},
671     {"res0e",             dump_msft_res0e, -1, -1},
672     {"res0f",             dump_msft_res0f, -1, -1}
673 };
674
675 static void dump_msft_seg(seg_t *seg)
676 {
677     print_begin_block(seg->name);
678
679     seg->offset = print_hex("offset");
680     seg->length = print_dec("length");
681     print_hex("res08");
682     print_hex("res0c");
683
684     print_end_block();
685 }
686
687 static void dump_msft_segdir(void)
688 {
689     int i;
690
691     print_begin_block("SegDir");
692
693     for(i=0; i < sizeof(segdir)/sizeof(segdir[0]); i++)
694         dump_msft_seg(segdir+i);
695
696     print_end_block();
697 }
698
699 static int dump_offset(void)
700 {
701     int i;
702
703     for(i=0; i < sizeof(segdir)/sizeof(segdir[0]); i++)
704         if(segdir[i].offset == offset)
705             return segdir[i].func(segdir+i);
706
707     for(i=0; i < msft_typeinfo_cnt; i++)
708         if(msft_typeinfo_offs[i] == offset)
709             return dump_msft_typeinfo(i);
710
711     return 0;
712 }
713
714 enum FileSig get_kind_msft(void)
715 {
716     const DWORD *sig = PRD(0, sizeof(DWORD));
717     return sig && *sig == MSFT_MAGIC ? SIG_MSFT : SIG_UNKNOWN;
718 }
719
720 void msft_dump(void)
721 {
722     int i;
723
724     dump_msft_header();
725
726     for(i=0; i < typeinfo_cnt; i++)
727         print_hex_id("typeinfo %d offset", i);
728
729     if(header_flags & HELPDLLFLAG)
730         print_hex("help dll offset");
731     print_offset();
732     printf("\n");
733
734     dump_msft_segdir();
735
736     while(!msft_eof) {
737         if(!dump_offset())
738             print_hex("unknown");
739     }
740 }