Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/tools/winedump/tlb.c
4388 views
1
/*
2
* Dump a typelib (tlb) file
3
*
4
* Copyright 2006 Jacek Caban
5
* Copyright 2015 Dmitry Timoshkov
6
*
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.
11
*
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.
16
*
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
20
*/
21
22
#include "config.h"
23
24
#include <stdlib.h>
25
#include <string.h>
26
#include <assert.h>
27
28
#include "winedump.h"
29
30
#define MSFT_MAGIC 0x5446534d
31
#define SLTG_MAGIC 0x47544c53
32
#define HELPDLLFLAG 0x0100
33
34
enum TYPEKIND {
35
TKIND_ENUM = 0,
36
TKIND_RECORD,
37
TKIND_MODULE,
38
TKIND_INTERFACE,
39
TKIND_DISPATCH,
40
TKIND_COCLASS,
41
TKIND_ALIAS,
42
TKIND_UNION,
43
TKIND_MAX
44
};
45
46
enum VARENUM {
47
VT_EMPTY = 0,
48
VT_NULL = 1,
49
VT_I2 = 2,
50
VT_I4 = 3,
51
VT_R4 = 4,
52
VT_R8 = 5,
53
VT_CY = 6,
54
VT_DATE = 7,
55
VT_BSTR = 8,
56
VT_DISPATCH = 9,
57
VT_ERROR = 10,
58
VT_BOOL = 11,
59
VT_VARIANT = 12,
60
VT_UNKNOWN = 13,
61
VT_DECIMAL = 14,
62
VT_I1 = 16,
63
VT_UI1 = 17,
64
VT_UI2 = 18,
65
VT_UI4 = 19,
66
VT_I8 = 20,
67
VT_UI8 = 21,
68
VT_INT = 22,
69
VT_UINT = 23,
70
VT_VOID = 24,
71
VT_HRESULT = 25,
72
VT_PTR = 26,
73
VT_SAFEARRAY = 27,
74
VT_CARRAY = 28,
75
VT_USERDEFINED = 29,
76
VT_LPSTR = 30,
77
VT_LPWSTR = 31,
78
VT_RECORD = 36,
79
VT_INT_PTR = 37,
80
VT_UINT_PTR = 38,
81
VT_FILETIME = 64,
82
VT_BLOB = 65,
83
VT_STREAM = 66,
84
VT_STORAGE = 67,
85
VT_STREAMED_OBJECT = 68,
86
VT_STORED_OBJECT = 69,
87
VT_BLOB_OBJECT = 70,
88
VT_CF = 71,
89
VT_CLSID = 72,
90
VT_VERSIONED_STREAM = 73,
91
VT_BSTR_BLOB = 0xfff,
92
VT_VECTOR = 0x1000,
93
VT_ARRAY = 0x2000,
94
VT_BYREF = 0x4000,
95
VT_RESERVED = 0x8000,
96
VT_ILLEGAL = 0xffff,
97
VT_ILLEGALMASKED = 0xfff,
98
VT_TYPEMASK = 0xfff
99
};
100
101
struct seg_t;
102
103
typedef BOOL (*dump_seg_t)(struct seg_t*);
104
105
typedef struct seg_t {
106
const char *name;
107
dump_seg_t func;
108
int offset;
109
int length;
110
} seg_t;
111
static seg_t segdir[15];
112
113
enum SEGDIRTYPE {
114
SEGDIR_TYPEINFO,
115
SEGDIR_IMPINFO,
116
SEGDIR_IMPFILES,
117
SEGDIR_REF,
118
SEGDIR_GUIDHASH,
119
SEGDIR_GUID,
120
SEGDIR_NAMEHASH,
121
SEGDIR_NAME,
122
SEGDIR_STRING,
123
SEGDIR_TYPEDESC,
124
SEGDIR_ARRAYDESC,
125
SEGDIR_CUSTDATA,
126
SEGDIR_CDGUID,
127
SEGDIR_res0e,
128
SEGDIR_res0f
129
};
130
131
static int offset=0;
132
static int indent;
133
static int typeinfo_cnt;
134
static int header_flags = 0;
135
static BOOL msft_eof = FALSE;
136
137
static int msft_typeinfo_offs[1000];
138
static int msft_typeinfo_kind[1000];
139
static int msft_typeinfo_impltypes[1000];
140
static int msft_typeinfo_elemcnt[1000];
141
static int msft_typeinfo_cnt = 0;
142
143
const char *dump_prefix = "";
144
145
static const char * const tkind[TKIND_MAX] = {
146
"TKIND_ENUM", "TKIND_RECORD", "TKIND_MODULE",
147
"TKIND_INTERFACE", "TKIND_DISPATCH", "TKIND_COCLASS",
148
"TKIND_ALIAS", "TKIND_UNION"
149
};
150
151
static const void *tlb_read(int size) {
152
const void *ret = PRD(offset, size);
153
154
if(ret)
155
offset += size;
156
else
157
msft_eof = TRUE;
158
159
return ret;
160
}
161
162
static int tlb_read_int(void)
163
{
164
const int *ret = tlb_read(sizeof(int));
165
return ret ? *ret : -1;
166
}
167
168
static int tlb_read_short(void)
169
{
170
const unsigned short *ret = tlb_read(sizeof(short));
171
return ret ? *ret : -1;
172
}
173
174
static int tlb_read_byte(void)
175
{
176
const unsigned char *ret = tlb_read(sizeof(char));
177
return ret ? *ret : -1;
178
}
179
180
static void print_offset(void)
181
{
182
int i;
183
printf("%s", dump_prefix);
184
for(i=0; i<indent; i++)
185
printf(" ");
186
}
187
188
static void print_begin_block(const char *name)
189
{
190
print_offset();
191
printf("%s {\n", name);
192
indent++;
193
}
194
195
static void print_begin_block_id(const char *name, int id)
196
{
197
char buf[64];
198
sprintf(buf, "%s %d", name, id);
199
print_begin_block(buf);
200
}
201
202
static void print_end_block(void)
203
{
204
indent--;
205
print_offset();
206
printf("}\n");
207
}
208
209
static int print_byte(const char *name)
210
{
211
unsigned char ret;
212
print_offset();
213
printf("%s = %02xh\n", name, ret=tlb_read_byte());
214
return ret;
215
}
216
217
static int print_hex(const char *name)
218
{
219
int ret;
220
print_offset();
221
printf("%s = %08xh\n", name, ret=tlb_read_int());
222
return ret;
223
}
224
225
static int print_hex_id(const char *name, int id)
226
{
227
char buf[64];
228
sprintf(buf, name, id);
229
return print_hex(buf);
230
}
231
232
static int print_short_hex(const char *name)
233
{
234
int ret;
235
print_offset();
236
printf("%s = %04xh\n", name, ret=tlb_read_short());
237
return ret;
238
}
239
240
static int print_short_dec(const char *name)
241
{
242
int ret;
243
print_offset();
244
printf("%s = %d\n", name, ret=tlb_read_short());
245
return ret;
246
}
247
248
static int print_dec(const char *name)
249
{
250
int ret;
251
print_offset();
252
printf("%s = %d\n", name, ret=tlb_read_int());
253
return ret;
254
}
255
256
static void print_guid(const char *name)
257
{
258
GUID guid = *(const GUID*)tlb_read(sizeof(guid));
259
260
print_offset();
261
262
printf("%s = {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n", name,
263
(unsigned int)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]);
266
}
267
268
static void print_vartype(int vartype)
269
{
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"
278
};
279
280
vartype &= VT_TYPEMASK;
281
if (vartype >= VT_EMPTY && vartype <= VT_LPWSTR)
282
printf("%s\n", vartypes[vartype]);
283
else
284
printf("unk %d\n", vartype);
285
}
286
287
static void print_ctl2(const char *name)
288
{
289
int len;
290
const char *buf;
291
292
print_offset();
293
294
len = tlb_read_short();
295
296
printf("%s = %d \"", name, len);
297
len >>= 2;
298
buf = tlb_read(len);
299
fwrite(buf, len, 1, stdout);
300
printf("\"");
301
len += 2;
302
303
while(len++ & 3)
304
printf("\\%02x", tlb_read_byte());
305
printf("\n");
306
}
307
308
static void dump_binary(int size)
309
{
310
const unsigned char *ptr;
311
char *prefix;
312
int i;
313
314
if (!size) return;
315
ptr = tlb_read(size);
316
if (!ptr) return;
317
318
prefix = malloc( strlen(dump_prefix) + 4 * indent + 1 );
319
strcpy( prefix, dump_prefix );
320
for (i = 0; i < indent; i++) strcat( prefix, " " );
321
dump_data_offset( ptr, size, offset, prefix );
322
free( prefix );
323
}
324
325
static int dump_msft_varflags(void)
326
{
327
static const char *syskind[] = {
328
"SYS_WIN16", "SYS_WIN32", "SYS_MAC", "SYS_WIN64", "unknown"
329
};
330
int kind, flags;
331
332
print_offset();
333
flags = tlb_read_int();
334
kind = flags & 0xf;
335
if (kind > 3) kind = 4;
336
printf("varflags = %08x, syskind = %s\n", flags, syskind[kind]);
337
return flags;
338
}
339
340
static void dump_msft_version(void)
341
{
342
unsigned version;
343
print_offset();
344
version = tlb_read_int();
345
printf("version = %u.%u\n", version & 0xffff, version >> 16);
346
}
347
348
static void dump_msft_header(void)
349
{
350
print_begin_block("Header");
351
352
print_hex("magic1");
353
print_hex("magic2");
354
print_hex("posguid");
355
print_hex("lcid");
356
print_hex("lcid2");
357
header_flags = dump_msft_varflags();
358
dump_msft_version();
359
print_hex("flags");
360
typeinfo_cnt = print_dec("ntypeinfos");
361
print_dec("helpstring");
362
print_dec("helpstringcontext");
363
print_dec("helpcontext");
364
print_dec("nametablecount");
365
print_dec("nametablechars");
366
print_hex("NameOffset");
367
print_hex("helpfile");
368
print_hex("CustomDataOffset");
369
print_hex("res44");
370
print_hex("res48");
371
print_hex("dispatchpos");
372
print_hex("res50");
373
374
print_end_block();
375
}
376
377
static int dump_msft_typekind(void)
378
{
379
int ret, typekind;
380
381
print_offset();
382
ret = tlb_read_int();
383
typekind = ret & 0xf;
384
printf("typekind = %s, align = %d\n", typekind < TKIND_MAX ? tkind[typekind] : "unknown", (ret >> 11) & 0x1f);
385
return ret;
386
}
387
388
static void dump_msft_typeinfobase(void)
389
{
390
print_begin_block_id("TypeInfoBase", msft_typeinfo_cnt);
391
392
msft_typeinfo_kind[msft_typeinfo_cnt] = dump_msft_typekind();
393
msft_typeinfo_offs[msft_typeinfo_cnt] = print_hex("memoffset");
394
print_hex("res2");
395
print_hex("res3");
396
print_hex("res4");
397
print_hex("res5");
398
msft_typeinfo_elemcnt[msft_typeinfo_cnt] = print_hex("cElement");
399
print_hex("res7");
400
print_hex("res8");
401
print_hex("res9");
402
print_hex("resA");
403
print_hex("posguid");
404
print_hex("flags");
405
print_hex("NameOffset");
406
print_hex("version");
407
print_hex("docstringoffs");
408
print_hex("docstringcontext");
409
print_hex("helpcontext");
410
print_hex("oCustData");
411
msft_typeinfo_impltypes[msft_typeinfo_cnt++] = print_short_hex("cImplTypes");
412
print_short_hex("bSizeVftt");
413
print_dec("size");
414
print_hex("datatype1");
415
print_hex("datatype2");
416
print_hex("res18");
417
print_hex("res19");
418
419
print_end_block();
420
}
421
422
static BOOL dump_msft_typeinfobases(seg_t *seg)
423
{
424
while (offset < seg->offset+seg->length)
425
dump_msft_typeinfobase();
426
427
assert(offset == seg->offset+seg->length);
428
return TRUE;
429
}
430
431
static void dump_msft_impinfo(int n)
432
{
433
print_begin_block_id("ImpInfo", n);
434
435
print_hex("flags");
436
print_hex("oImpInfo");
437
print_hex("oGuid");
438
439
print_end_block();
440
}
441
442
static BOOL dump_msft_impinfos(seg_t *seg)
443
{
444
int i;
445
446
for(i = 0; offset < seg->offset+seg->length; i++)
447
dump_msft_impinfo(i);
448
449
assert(offset == seg->offset+seg->length);
450
return TRUE;
451
}
452
453
static void dump_msft_impfile(int n)
454
{
455
print_begin_block_id("ImpFile", n);
456
457
print_hex("guid");
458
print_hex("lcid");
459
print_hex("version");
460
print_ctl2("impfile");
461
462
print_end_block();
463
}
464
465
static BOOL dump_msft_impfiles(seg_t *seg)
466
{
467
int i;
468
469
for(i = 0; offset < seg->offset+seg->length; i++)
470
dump_msft_impfile(i);
471
472
assert(offset == seg->offset+seg->length);
473
return TRUE;
474
}
475
476
static BOOL dump_msft_reftabs(seg_t *seg)
477
{
478
print_begin_block("RefTab");
479
480
dump_binary(seg->length); /* FIXME */
481
482
print_end_block();
483
484
return TRUE;
485
}
486
487
static BOOL dump_msft_guidhashtab(seg_t *seg)
488
{
489
print_begin_block("GuidHashTab");
490
491
dump_binary(seg->length); /* FIXME */
492
493
print_end_block();
494
495
assert(offset == seg->offset+seg->length);
496
return TRUE;
497
}
498
499
static void dump_msft_guidentry(int n)
500
{
501
print_begin_block_id("GuidEntry", n);
502
503
print_guid("guid");
504
print_hex("hreftype");
505
print_hex("next_hash");
506
507
print_end_block();
508
}
509
510
static BOOL dump_msft_guidtab(seg_t *seg)
511
{
512
int i;
513
514
for(i = 0; offset < seg->offset+seg->length; i++)
515
dump_msft_guidentry(i);
516
517
assert(offset == seg->offset+seg->length);
518
return TRUE;
519
}
520
521
static BOOL dump_msft_namehashtab(seg_t *seg)
522
{
523
print_begin_block("NameHashTab");
524
525
dump_binary(seg->length); /* FIXME */
526
527
print_end_block();
528
return TRUE;
529
}
530
531
static void print_string0(void)
532
{
533
unsigned char c;
534
535
printf("\"");
536
while ((c = tlb_read_byte()) != 0)
537
{
538
if (isprint(c))
539
fwrite(&c, 1, 1, stdout);
540
else
541
{
542
char buf[16];
543
sprintf(buf, "\\%u", c);
544
fwrite(buf, 1, strlen(buf), stdout);
545
}
546
}
547
printf("\"");
548
}
549
550
static void print_string(int len)
551
{
552
printf("\"");
553
fwrite(tlb_read(len), len, 1, stdout);
554
printf("\"");
555
}
556
557
static void dump_string(int len, int align_off)
558
{
559
print_string(len);
560
printf(" ");
561
while((len++ + align_off) & 3)
562
printf("\\%2.2x", tlb_read_byte());
563
}
564
565
static void dump_msft_name(int base, int n)
566
{
567
int len;
568
569
print_begin_block_id("Name", n);
570
571
print_hex("hreftype");
572
print_hex("next_hash");
573
len = print_hex("namelen")&0xff;
574
575
print_offset();
576
printf("name = ");
577
dump_string(len, 0);
578
printf("\n");
579
580
print_end_block();
581
}
582
583
static BOOL dump_msft_nametab(seg_t *seg)
584
{
585
int i, base = offset;
586
587
for(i = 0; offset < seg->offset+seg->length; i++)
588
dump_msft_name(base, i);
589
590
assert(offset == seg->offset+seg->length);
591
return TRUE;
592
}
593
594
static void dump_msft_string(int n)
595
{
596
int len;
597
598
print_begin_block_id("String", n);
599
600
len = print_short_hex("stringlen");
601
602
print_offset();
603
printf("string = ");
604
dump_string(len, 2);
605
606
if(len < 3) {
607
for(len = 0; len < 4; len++)
608
printf("\\%2.2x", tlb_read_byte());
609
}
610
printf("\n");
611
612
print_end_block();
613
}
614
615
static BOOL dump_msft_stringtab(seg_t *seg)
616
{
617
int i;
618
619
for(i = 0; offset < seg->offset+seg->length; i++)
620
dump_msft_string(i);
621
622
assert(offset == seg->offset+seg->length);
623
return TRUE;
624
}
625
626
static void dump_msft_typedesc(int n)
627
{
628
print_begin_block_id("TYPEDESC", n);
629
630
print_hex("hreftype");
631
print_hex("vt");
632
633
print_end_block();
634
}
635
636
static BOOL dump_msft_typedesctab(seg_t *seg)
637
{
638
int i;
639
640
print_begin_block("TypedescTab");
641
642
for(i = 0; offset < seg->offset+seg->length; i++)
643
dump_msft_typedesc(i);
644
645
print_end_block();
646
647
assert(offset == seg->offset+seg->length);
648
return TRUE;
649
}
650
651
static BOOL dump_msft_arraydescs(seg_t *seg)
652
{
653
print_begin_block("ArrayDescriptions");
654
655
dump_binary(seg->length); /* FIXME */
656
657
print_end_block();
658
return TRUE;
659
}
660
661
static BOOL dump_msft_custdata(seg_t *seg)
662
{
663
unsigned short vt;
664
unsigned n;
665
666
print_begin_block("CustData");
667
668
while (offset < seg->offset+seg->length)
669
{
670
print_offset();
671
672
vt = tlb_read_short();
673
printf("vt %d", vt);
674
n = tlb_read_int();
675
676
switch(vt) {
677
case VT_BSTR:
678
printf(" len %d: ", n);
679
dump_string(n, 2);
680
printf("\n");
681
break;
682
default:
683
printf(": %x ", n);
684
printf("\\%2.2x ", tlb_read_byte());
685
printf("\\%2.2x\n", tlb_read_byte());
686
}
687
}
688
689
print_end_block();
690
return TRUE;
691
}
692
693
static void dump_msft_cdguid(int n)
694
{
695
print_begin_block_id("CGUid", n);
696
697
print_hex("GuidOffset");
698
print_hex("DataOffset");
699
print_hex("next");
700
701
print_end_block();
702
}
703
704
static BOOL dump_msft_cdguids(seg_t *seg)
705
{
706
int i;
707
708
for(i = 0; offset < seg->offset+seg->length; i++)
709
dump_msft_cdguid(i);
710
711
assert(offset == seg->offset+seg->length);
712
return TRUE;
713
}
714
715
static BOOL dump_msft_res0e(seg_t *seg)
716
{
717
print_begin_block("res0e");
718
dump_binary(seg->length);
719
print_end_block();
720
721
return TRUE;
722
}
723
724
static BOOL dump_msft_res0f(seg_t *seg)
725
{
726
print_begin_block("res0f");
727
dump_binary(seg->length);
728
print_end_block();
729
730
return TRUE;
731
}
732
733
/* Used for function return value and arguments type */
734
static void dump_msft_datatype(const char *name)
735
{
736
int datatype;
737
738
print_offset();
739
datatype = tlb_read_int();
740
printf("%s = %08x", name, datatype);
741
if (datatype < 0) {
742
printf(", ");
743
print_vartype(datatype);
744
}
745
else {
746
const short *vt;
747
748
if (datatype > segdir[SEGDIR_TYPEDESC].length) {
749
printf(", invalid offset\n");
750
return;
751
}
752
753
/* FIXME: in case of VT_USERDEFINED use hreftype */
754
vt = PRD(segdir[SEGDIR_TYPEDESC].offset + datatype, 4*sizeof(short));
755
datatype = vt[0] & VT_TYPEMASK;
756
if (datatype == VT_PTR) {
757
printf(", VT_PTR -> ");
758
if (vt[3] < 0)
759
datatype = vt[2];
760
else {
761
vt = PRD(segdir[SEGDIR_TYPEDESC].offset + vt[2], 4*sizeof(short));
762
datatype = *vt;
763
}
764
}
765
else {
766
printf(", ");
767
datatype = *vt;
768
}
769
770
print_vartype(datatype);
771
}
772
}
773
774
static void dump_defaultvalue(int id)
775
{
776
int offset;
777
778
print_offset();
779
offset = tlb_read_int();
780
781
printf("default value[%d] = %08x", id, offset);
782
if (offset == -1)
783
printf("\n");
784
else if (offset < 0) {
785
printf(", ");
786
print_vartype((offset & 0x7c000000) >> 26);
787
}
788
else {
789
const unsigned short *vt;
790
791
if (offset > segdir[SEGDIR_CUSTDATA].length) {
792
printf(", invalid offset\n");
793
return;
794
}
795
796
vt = PRD(segdir[SEGDIR_CUSTDATA].offset + offset, sizeof(*vt));
797
printf(", ");
798
print_vartype(*vt);
799
}
800
}
801
802
static void dump_msft_func(int n)
803
{
804
int size, args_cnt, i, extra_attr, fkccic;
805
806
print_begin_block_id("FuncRecord", n);
807
808
size = print_short_hex("size");
809
print_short_hex("index");
810
dump_msft_datatype("retval type");
811
print_hex("flags");
812
print_short_hex("VtableOffset");
813
print_short_hex("funcdescsize");
814
fkccic = print_hex("FKCCIC");
815
args_cnt = print_short_hex("nrargs");
816
print_short_hex("noptargs");
817
818
extra_attr = size/sizeof(INT) - 6 - args_cnt*(fkccic&0x1000 ? 4 : 3);
819
820
if(extra_attr)
821
print_hex("helpcontext");
822
if(extra_attr >= 2)
823
print_hex("oHelpString");
824
if(extra_attr >= 3)
825
print_hex("toEntry");
826
if(extra_attr >= 4)
827
print_hex("res9");
828
if(extra_attr >= 5)
829
print_hex("resA");
830
if(extra_attr >= 6)
831
print_hex("HelpStringContext");
832
if(extra_attr >= 7)
833
print_hex("oCustData");
834
for(i = 0; i < extra_attr-7; i++)
835
print_hex_id("oArgCustData", i);
836
837
if(fkccic & 0x1000) {
838
for(i=0; i < args_cnt; i++)
839
dump_defaultvalue(i);
840
}
841
842
for(i=0; i < args_cnt; i++) {
843
print_begin_block_id("param", i);
844
845
/* FIXME: Handle default values */
846
dump_msft_datatype("datatype");
847
print_hex("name");
848
print_hex("paramflags");
849
850
print_end_block();
851
}
852
853
print_end_block();
854
}
855
856
static void dump_msft_var(int n)
857
{
858
INT size;
859
860
print_begin_block_id("VarRecord", n);
861
862
size = print_hex("recsize")&0x1ff;
863
print_hex("DataType");
864
print_hex("flags");
865
print_short_hex("VarKind");
866
print_short_hex("vardescsize");
867
print_hex("OffsValue");
868
869
if(size > 5*sizeof(INT))
870
dump_binary(size - 5*sizeof(INT));
871
872
print_end_block();
873
}
874
875
static void dump_msft_ref(int n)
876
{
877
print_begin_block_id("RefRecord", n);
878
879
print_hex("reftype");
880
print_hex("flags");
881
print_hex("oCustData");
882
print_hex("onext");
883
884
print_end_block();
885
}
886
887
static void dump_msft_coclass(int n)
888
{
889
int i;
890
891
print_dec("size");
892
893
for(i=0; i < msft_typeinfo_impltypes[n]; i++)
894
dump_msft_ref(i);
895
}
896
897
static BOOL dump_msft_typeinfo(int n)
898
{
899
int i;
900
901
print_begin_block_id("TypeInfo", n);
902
903
if((msft_typeinfo_kind[n] & 0xf) == TKIND_COCLASS) {
904
dump_msft_coclass(n);
905
print_end_block();
906
return TRUE;
907
}
908
909
print_dec("size");
910
911
for(i = 0; i < LOWORD(msft_typeinfo_elemcnt[n]); i++)
912
dump_msft_func(i);
913
914
for(i = 0; i < HIWORD(msft_typeinfo_elemcnt[n]); i++)
915
dump_msft_var(i);
916
917
for(i = 0; i < LOWORD(msft_typeinfo_elemcnt[n]); i++)
918
print_hex_id("func %d id", i);
919
920
for(i = 0; i < HIWORD(msft_typeinfo_elemcnt[n]); i++)
921
print_hex_id("var %d id", i);
922
923
for(i = 0; i < LOWORD(msft_typeinfo_elemcnt[n]); i++)
924
print_hex_id("func %d name", i);
925
926
for(i = 0; i < HIWORD(msft_typeinfo_elemcnt[n]); i++)
927
print_hex_id("var %d name", i);
928
929
for(i = 0; i < LOWORD(msft_typeinfo_elemcnt[n]); i++)
930
print_hex_id("func %d offset", i);
931
932
for(i = 0; i < HIWORD(msft_typeinfo_elemcnt[n]); i++)
933
print_hex_id("var %d offset", i);
934
935
print_end_block();
936
937
return TRUE;
938
}
939
940
static seg_t segdir[] = {
941
{"TypeInfoTab", dump_msft_typeinfobases, -1, -1},
942
{"ImpInfo", dump_msft_impinfos, -1, -1},
943
{"ImpFiles", dump_msft_impfiles, -1, -1},
944
{"RefTab", dump_msft_reftabs, -1, -1},
945
{"GuidHashTab", dump_msft_guidhashtab, -1, -1},
946
{"GuidTab", dump_msft_guidtab, -1, -1},
947
{"NameHashTab", dump_msft_namehashtab, -1, -1},
948
{"pNameTab", dump_msft_nametab, -1, -1},
949
{"pStringTab", dump_msft_stringtab, -1, -1},
950
{"TypedescTab", dump_msft_typedesctab, -1, -1},
951
{"ArrayDescriptions", dump_msft_arraydescs, -1, -1},
952
{"CustData", dump_msft_custdata, -1, -1},
953
{"CDGuid", dump_msft_cdguids, -1, -1},
954
{"res0e", dump_msft_res0e, -1, -1},
955
{"res0f", dump_msft_res0f, -1, -1}
956
};
957
958
static void dump_msft_seg(seg_t *seg)
959
{
960
print_begin_block(seg->name);
961
962
seg->offset = print_hex("offset");
963
seg->length = print_dec("length");
964
print_hex("res08");
965
print_hex("res0c");
966
967
print_end_block();
968
}
969
970
static void dump_msft_segdir(void)
971
{
972
int i;
973
974
print_begin_block("SegDir");
975
976
for(i=0; i < ARRAY_SIZE(segdir); i++)
977
dump_msft_seg(segdir+i);
978
979
print_end_block();
980
}
981
982
static BOOL dump_offset(void)
983
{
984
int i;
985
986
for(i=0; i < ARRAY_SIZE(segdir); i++)
987
if(segdir[i].offset == offset)
988
return segdir[i].func(segdir+i);
989
990
for(i=0; i < msft_typeinfo_cnt; i++)
991
if(msft_typeinfo_offs[i] == offset)
992
return dump_msft_typeinfo(i);
993
994
return FALSE;
995
}
996
997
static void msft_dump(void)
998
{
999
int i;
1000
1001
dump_msft_header();
1002
1003
for(i=0; i < typeinfo_cnt; i++)
1004
print_hex_id("typeinfo %d offset", i);
1005
1006
if(header_flags & HELPDLLFLAG)
1007
print_hex("help dll offset");
1008
print_offset();
1009
printf("\n");
1010
1011
dump_msft_segdir();
1012
1013
while(!msft_eof) {
1014
if(!dump_offset())
1015
print_hex("unknown");
1016
}
1017
}
1018
1019
/****************************** SLTG Typelibs ******************************/
1020
1021
struct block_entry
1022
{
1023
DWORD len;
1024
WORD index_string;
1025
WORD next;
1026
};
1027
1028
struct bitstream
1029
{
1030
const BYTE *buffer;
1031
DWORD length;
1032
WORD current;
1033
};
1034
1035
#pragma pack(push,1)
1036
struct sltg_typeinfo_header
1037
{
1038
short magic;
1039
int href_table;
1040
int res06;
1041
int elem_table;
1042
int res0e;
1043
int version;
1044
int res16;
1045
struct
1046
{
1047
unsigned unknown1 : 3;
1048
unsigned flags : 16;
1049
unsigned unknown2 : 5;
1050
unsigned typekind : 8;
1051
} misc;
1052
int res1e;
1053
};
1054
1055
struct sltg_member_header
1056
{
1057
short res00;
1058
short res02;
1059
char res04;
1060
int extra;
1061
};
1062
1063
struct sltg_tail
1064
{
1065
unsigned short cFuncs;
1066
unsigned short cVars;
1067
unsigned short cImplTypes;
1068
unsigned short res06; /* always 0000 */
1069
unsigned short funcs_off; /* offset to functions (starting from the member header) */
1070
unsigned short vars_off; /* offset to vars (starting from the member header) */
1071
unsigned short impls_off; /* offset to implemented types (starting from the member header) */
1072
unsigned short funcs_bytes; /* bytes used by function data */
1073
unsigned short vars_bytes; /* bytes used by var data */
1074
unsigned short impls_bytes; /* bytes used by implemented type data */
1075
unsigned short tdescalias_vt; /* for TKIND_ALIAS */
1076
unsigned short res16; /* always ffff */
1077
unsigned short res18; /* always 0000 */
1078
unsigned short res1a; /* always 0000 */
1079
unsigned short simple_alias; /* tdescalias_vt is a vt rather than an offset? */
1080
unsigned short res1e; /* always 0000 */
1081
unsigned short cbSizeInstance;
1082
unsigned short cbAlignment;
1083
unsigned short res24;
1084
unsigned short res26;
1085
unsigned short cbSizeVft;
1086
unsigned short res2a; /* always ffff */
1087
unsigned short res2c; /* always ffff */
1088
unsigned short res2e; /* always ffff */
1089
unsigned short res30; /* always ffff */
1090
unsigned short res32;
1091
unsigned short res34;
1092
};
1093
1094
struct sltg_variable
1095
{
1096
char magic; /* 0x0a */
1097
char flags;
1098
short next;
1099
short name;
1100
short byte_offs; /* pos in struct, or offset to const type or const data (if flags & 0x08) */
1101
short type; /* if flags & 0x02 this is the type, else offset to type */
1102
int memid;
1103
short helpcontext; /* ?? */
1104
short helpstring; /* ?? */
1105
#if 0
1106
short varflags; /* only present if magic & 0x20 */
1107
#endif
1108
};
1109
#pragma pack(pop)
1110
1111
static const char *lookup_code(const BYTE *table, DWORD table_size, struct bitstream *bits)
1112
{
1113
const BYTE *p = table;
1114
1115
while (p < table + table_size && *p == 0x80)
1116
{
1117
if (p + 2 >= table + table_size) return NULL;
1118
1119
if (!(bits->current & 0xff))
1120
{
1121
if (!bits->length) return NULL;
1122
bits->current = (*bits->buffer << 8) | 1;
1123
bits->buffer++;
1124
bits->length--;
1125
}
1126
1127
if (bits->current & 0x8000)
1128
{
1129
p += 3;
1130
}
1131
else
1132
{
1133
p = table + (*(p + 2) | (*(p + 1) << 8));
1134
}
1135
1136
bits->current <<= 1;
1137
}
1138
1139
if (p + 1 < table + table_size && *(p + 1))
1140
{
1141
/* FIXME: What is the meaning of *p? */
1142
const BYTE *q = p + 1;
1143
while (q < table + table_size && *q) q++;
1144
return (q < table + table_size) ? (const char *)(p + 1) : NULL;
1145
}
1146
1147
return NULL;
1148
}
1149
1150
static const char *decode_string(const BYTE *table, const char *stream, UINT stream_length, UINT *read_bytes)
1151
{
1152
char *buf;
1153
DWORD buf_size, table_size;
1154
const char *p;
1155
struct bitstream bits;
1156
1157
bits.buffer = (const BYTE *)stream;
1158
bits.length = stream_length;
1159
bits.current = 0;
1160
1161
buf_size = *(const WORD *)table;
1162
table += sizeof(WORD);
1163
table_size = *(const DWORD *)table;
1164
table += sizeof(DWORD);
1165
1166
buf = xmalloc(buf_size);
1167
buf[0] = 0;
1168
1169
while ((p = lookup_code(table, table_size, &bits)))
1170
{
1171
if (buf[0]) strcat(buf, " ");
1172
assert(strlen(buf) + strlen(p) + 1 <= buf_size);
1173
strcat(buf, p);
1174
}
1175
1176
if (read_bytes) *read_bytes = stream_length - bits.length;
1177
1178
return buf;
1179
}
1180
1181
static void print_sltg_name(const char *name)
1182
{
1183
unsigned short len = tlb_read_short();
1184
print_offset();
1185
printf("%s = %#x (", name, len);
1186
if (len != 0xffff) print_string(len);
1187
printf(")\n");
1188
}
1189
1190
static int dump_sltg_header(int *sltg_first_blk, int *size_of_index, int *size_of_pad)
1191
{
1192
int n_file_blocks;
1193
1194
print_begin_block("Header");
1195
1196
print_hex("magic");
1197
n_file_blocks = print_short_dec("# file blocks");
1198
*size_of_pad = print_short_hex("pad");
1199
*size_of_index = print_short_hex("size of index");
1200
*sltg_first_blk = print_short_dec("first block");
1201
print_guid("guid");
1202
print_hex("res1c");
1203
print_hex("res20");
1204
1205
print_end_block();
1206
1207
return n_file_blocks;
1208
}
1209
1210
static void dump_sltg_index(int count)
1211
{
1212
int i;
1213
1214
print_offset();
1215
printf("index:\n");
1216
1217
print_offset();
1218
print_string0();
1219
printf("\n");
1220
print_offset();
1221
print_string0();
1222
printf("\n");
1223
1224
for (i = 0; i < count - 2; i++)
1225
{
1226
print_offset();
1227
print_string0();
1228
printf("\n");
1229
}
1230
print_offset();
1231
printf("\n");
1232
}
1233
1234
static void dump_sltg_pad(int size_of_pad)
1235
{
1236
print_offset();
1237
printf("pad:\n");
1238
dump_binary(size_of_pad);
1239
print_offset();
1240
printf("\n");
1241
}
1242
1243
static void dump_sltg_block_entry(int idx, const char *index)
1244
{
1245
char name[32];
1246
short index_offset;
1247
1248
sprintf(name, "Block entry %d", idx);
1249
print_begin_block(name);
1250
1251
print_hex("len");
1252
index_offset = tlb_read_short();
1253
print_offset();
1254
printf("index string = %xh \"%s\"\n", index_offset, index + index_offset);
1255
print_short_hex("next");
1256
1257
print_end_block();
1258
}
1259
1260
static void dump_sltg_library_block(void)
1261
{
1262
print_begin_block("Library block entry");
1263
1264
print_short_hex("magic");
1265
print_short_hex("res02");
1266
print_sltg_name("name");
1267
print_short_hex("res06");
1268
print_sltg_name("helpstring");
1269
print_sltg_name("helpfile");
1270
print_hex("helpcontext");
1271
print_short_hex("syskind");
1272
print_short_hex("lcid");
1273
print_hex("res12");
1274
print_short_hex("libflags");
1275
dump_msft_version();
1276
print_guid("uuid");
1277
1278
print_end_block();
1279
}
1280
1281
static void skip_sltg_library_block(void)
1282
{
1283
unsigned short skip;
1284
1285
tlb_read_short();
1286
tlb_read_short();
1287
skip = tlb_read_short();
1288
if (skip != 0xffff) tlb_read(skip);
1289
tlb_read_short();
1290
skip = tlb_read_short();
1291
if (skip != 0xffff) tlb_read(skip);
1292
skip = tlb_read_short();
1293
if (skip != 0xffff) tlb_read(skip);
1294
tlb_read_int();
1295
tlb_read_short();
1296
tlb_read_short();
1297
tlb_read_int();
1298
tlb_read_short();
1299
tlb_read_int();
1300
tlb_read(sizeof(GUID));
1301
}
1302
1303
static void dump_sltg_other_typeinfo(int idx, const char *hlp_strings)
1304
{
1305
int hlpstr_len, saved_offset;
1306
char name[32];
1307
1308
sprintf(name, "Other typeinfo %d", idx);
1309
print_begin_block(name);
1310
1311
print_sltg_name("index name");
1312
print_sltg_name("other name");
1313
print_short_hex("res1a");
1314
print_short_hex("name offset");
1315
1316
print_offset();
1317
hlpstr_len = tlb_read_short();
1318
if (hlpstr_len)
1319
{
1320
const char *str;
1321
1322
saved_offset = offset;
1323
str = tlb_read(hlpstr_len);
1324
str = decode_string((const BYTE *)hlp_strings, str, hlpstr_len, NULL);
1325
printf("helpstring: \"%s\"\n", str);
1326
1327
offset = saved_offset;
1328
print_offset();
1329
printf("helpstring encoded bits: %d bytes\n", hlpstr_len);
1330
dump_binary(hlpstr_len);
1331
}
1332
else
1333
printf("helpstring: \"\"\n");
1334
1335
print_short_hex("res20");
1336
print_hex("helpcontext");
1337
print_short_hex("res26");
1338
print_guid("uuid");
1339
print_short_dec("typekind");
1340
1341
print_end_block();
1342
}
1343
1344
static void skip_sltg_other_typeinfo(void)
1345
{
1346
unsigned short skip;
1347
1348
skip = tlb_read_short();
1349
if (skip != 0xffff) tlb_read(skip);
1350
skip = tlb_read_short();
1351
if (skip != 0xffff) tlb_read(skip);
1352
tlb_read_short();
1353
tlb_read_short();
1354
skip = tlb_read_short();
1355
if (skip) tlb_read(skip);
1356
tlb_read_short();
1357
tlb_read_int();
1358
tlb_read_short();
1359
tlb_read(sizeof(GUID));
1360
tlb_read_short();
1361
}
1362
1363
static void sltg_print_simple_type(short type)
1364
{
1365
print_offset();
1366
if ((type & 0x0f00) == 0x0e00)
1367
printf("*");
1368
printf("%04x | (%d)\n", type & 0xff80, type & 0x7f);
1369
}
1370
1371
static void dump_safe_array(int array_offset)
1372
{
1373
int i, cDims, saved_offset = offset;
1374
1375
offset = array_offset;
1376
1377
print_offset();
1378
printf("safe array starts at %#x\n", offset);
1379
1380
cDims = print_short_dec("cDims");
1381
print_short_hex("fFeatures");
1382
print_dec("cbElements");
1383
print_dec("cLocks");
1384
print_hex("pvData");
1385
1386
for (i = 0; i < cDims; i++)
1387
dump_binary(8); /* sizeof(SAFEARRAYBOUND) */
1388
1389
print_offset();
1390
printf("safe array ends at %#x\n", offset);
1391
offset = saved_offset;
1392
}
1393
1394
static int sltg_print_compound_type(int vars_start_offset, int type_offset)
1395
{
1396
short type, vt;
1397
int type_bytes, saved_offset = offset;
1398
1399
offset = vars_start_offset + type_offset;
1400
print_offset();
1401
printf("type description starts at %#x\n", offset);
1402
1403
for (;;)
1404
{
1405
do
1406
{
1407
type = tlb_read_short();
1408
vt = type & 0x7f;
1409
1410
if (vt == VT_PTR)
1411
{
1412
print_offset();
1413
printf("%04x | VT_PTR\n", type & 0xff80);
1414
}
1415
} while (vt == VT_PTR);
1416
1417
if (vt == VT_USERDEFINED)
1418
{
1419
short href = tlb_read_short();
1420
print_offset();
1421
if ((type & 0x0f00) == 0x0e00)
1422
printf("*");
1423
printf("%04x | VT_USERDEFINED (href %d)\n", type & 0xff80, href);
1424
break;
1425
}
1426
else if (vt == VT_CARRAY)
1427
{
1428
short off;
1429
1430
off = tlb_read_short();
1431
print_offset();
1432
printf("VT_CARRAY: offset %#x (+%#x=%#x)\n",
1433
off, vars_start_offset, off + vars_start_offset);
1434
dump_safe_array(vars_start_offset + off);
1435
1436
/* type description follows */
1437
print_offset();
1438
printf("array element type:\n");
1439
continue;
1440
}
1441
else if (vt == VT_SAFEARRAY)
1442
{
1443
short off;
1444
1445
off = tlb_read_short();
1446
print_offset();
1447
printf("VT_SAFEARRAY: offset %#x (+%#x=%#x)\n",
1448
off, vars_start_offset, off + vars_start_offset);
1449
dump_safe_array(vars_start_offset + off);
1450
break;
1451
}
1452
else
1453
{
1454
sltg_print_simple_type(type);
1455
break;
1456
}
1457
}
1458
1459
print_offset();
1460
printf("type description ends at %#x\n", offset);
1461
type_bytes = offset - saved_offset;
1462
offset = saved_offset;
1463
1464
return type_bytes;
1465
}
1466
1467
static void dump_type(int len, const char *hlp_strings)
1468
{
1469
union
1470
{
1471
struct
1472
{
1473
unsigned unknown1 : 3;
1474
unsigned flags : 13;
1475
unsigned unknown2 : 8;
1476
unsigned typekind : 8;
1477
} s;
1478
unsigned flags;
1479
} misc;
1480
int typeinfo_start_offset, extra, member_offset, href_offset, i;
1481
int saved_offset;
1482
const void *block;
1483
const struct sltg_typeinfo_header *ti;
1484
const struct sltg_member_header *mem;
1485
const struct sltg_tail *tail;
1486
1487
typeinfo_start_offset = offset;
1488
block = tlb_read(len);
1489
offset = typeinfo_start_offset;
1490
1491
ti = block;
1492
mem = (const struct sltg_member_header *)((char *)block + ti->elem_table);
1493
tail = (const struct sltg_tail *)((char *)(mem + 1) + mem->extra);
1494
1495
typeinfo_start_offset = offset;
1496
1497
print_short_hex("magic");
1498
href_offset = tlb_read_int();
1499
print_offset();
1500
if (href_offset != -1)
1501
printf("href offset = %#x (+%#x=%#x)\n",
1502
href_offset, typeinfo_start_offset, href_offset + typeinfo_start_offset);
1503
else
1504
printf("href offset = ffffffffh\n");
1505
print_hex("res06");
1506
member_offset = tlb_read_int();
1507
print_offset();
1508
printf("member offset = %#x (+%#x=%#x)\n",
1509
member_offset, typeinfo_start_offset, member_offset + typeinfo_start_offset);
1510
print_hex("res0e");
1511
print_hex("version");
1512
print_hex("res16");
1513
misc.flags = print_hex("misc");
1514
print_offset();
1515
printf("misc: unknown1 %02x, flags %04x, unknown2 %02x, typekind %u (%s)\n",
1516
misc.s.unknown1, misc.s.flags, misc.s.unknown2, misc.s.typekind,
1517
misc.s.typekind < TKIND_MAX ? tkind[misc.s.typekind] : "unknown");
1518
print_hex("res1e");
1519
1520
if (href_offset != -1)
1521
{
1522
int i, number;
1523
1524
print_begin_block("href_table");
1525
1526
print_short_hex("magic");
1527
print_hex("res02");
1528
print_hex("res06");
1529
print_hex("res0a");
1530
print_hex("res0e");
1531
print_hex("res12");
1532
print_hex("res16");
1533
print_hex("res1a");
1534
print_hex("res1e");
1535
print_hex("res22");
1536
print_hex("res26");
1537
print_hex("res2a");
1538
print_hex("res2e");
1539
print_hex("res32");
1540
print_hex("res36");
1541
print_hex("res3a");
1542
print_hex("res3e");
1543
print_short_hex("res42");
1544
number = print_hex("number");
1545
1546
for (i = 0; i < number; i += 8)
1547
dump_binary(8);
1548
1549
print_short_hex("res50");
1550
print_byte("res52");
1551
print_hex("res53");
1552
1553
for (i = 0; i < number/8; i++)
1554
print_sltg_name("name");
1555
1556
print_byte("resxx");
1557
1558
print_end_block();
1559
}
1560
1561
print_offset();
1562
printf("member_header starts at %#x, current offset = %#x\n", typeinfo_start_offset + member_offset, offset);
1563
member_offset = offset;
1564
print_short_hex("res00");
1565
print_short_hex("res02");
1566
print_byte("res04");
1567
extra = print_hex("extra");
1568
1569
if (misc.s.typekind == TKIND_RECORD || misc.s.typekind == TKIND_ENUM)
1570
{
1571
int vars_start_offset = offset;
1572
1573
for (i = 0; i < tail->cVars; i++)
1574
{
1575
char name[32];
1576
int saved_off;
1577
char magic, flags;
1578
short next, value;
1579
1580
sprintf(name, "variable %d", i);
1581
print_begin_block(name);
1582
1583
saved_off = offset;
1584
dump_binary(sizeof(struct sltg_variable));
1585
offset = saved_off;
1586
1587
magic = print_byte("magic");
1588
flags = print_byte("flags");
1589
next = tlb_read_short();
1590
print_offset();
1591
if (next != -1)
1592
printf("next offset = %#x (+%#x=%#x)\n",
1593
next, vars_start_offset, next + vars_start_offset);
1594
else
1595
printf("next offset = ffffh\n");
1596
print_short_hex("name");
1597
1598
if (flags & 0x40)
1599
print_short_hex("dispatch");
1600
else if (flags & 0x10)
1601
{
1602
if (flags & 0x08)
1603
print_short_hex("const value");
1604
else
1605
{
1606
value = tlb_read_short();
1607
print_offset();
1608
printf("byte offset = %#x (+%#x=%#x)\n",
1609
value, vars_start_offset, value + vars_start_offset);
1610
}
1611
}
1612
else
1613
print_short_hex("oInst");
1614
1615
value = tlb_read_short();
1616
if (!(flags & 0x02))
1617
{
1618
print_offset();
1619
printf("type offset = %#x (+%#x=%#x)\n",
1620
value, vars_start_offset, value + vars_start_offset);
1621
print_offset();
1622
printf("type:\n");
1623
sltg_print_compound_type(vars_start_offset, value);
1624
}
1625
else
1626
{
1627
print_offset();
1628
printf("type:\n");
1629
sltg_print_simple_type(value);
1630
}
1631
1632
print_hex("memid");
1633
print_short_hex("helpcontext");
1634
1635
value = tlb_read_short();
1636
print_offset();
1637
if (value != -1)
1638
{
1639
const char *str;
1640
UINT hlpstr_maxlen;
1641
1642
printf("helpstring offset = %#x (+%#x=%#x)\n",
1643
value, vars_start_offset, value + vars_start_offset);
1644
1645
saved_offset = offset;
1646
1647
offset = value + vars_start_offset;
1648
1649
hlpstr_maxlen = member_offset + sizeof(struct sltg_member_header) + mem->extra - offset;
1650
1651
str = tlb_read(hlpstr_maxlen);
1652
str = decode_string((const BYTE *)hlp_strings, str, hlpstr_maxlen, &hlpstr_maxlen);
1653
print_offset();
1654
printf("helpstring: \"%s\"\n", str);
1655
1656
offset = value + vars_start_offset;
1657
print_offset();
1658
printf("helpstring encoded bits: %d bytes\n", hlpstr_maxlen);
1659
dump_binary(hlpstr_maxlen);
1660
1661
offset = saved_offset;
1662
}
1663
else
1664
printf("helpstring offset = ffffh\n");
1665
1666
if (magic & 0x20) print_short_hex("varflags");
1667
1668
if (next != -1)
1669
{
1670
if (offset != vars_start_offset + next)
1671
dump_binary(vars_start_offset + next - offset);
1672
}
1673
1674
print_end_block();
1675
}
1676
}
1677
else if (misc.s.typekind == TKIND_INTERFACE || misc.s.typekind == TKIND_COCLASS)
1678
{
1679
short next, i;
1680
int funcs_start_offset = offset;
1681
1682
for (i = 0; i < tail->cImplTypes; i++)
1683
{
1684
char name[64];
1685
1686
sprintf(name, "impl.type %d (current offset %#x)", i, offset);
1687
print_begin_block(name);
1688
1689
print_short_hex("res00");
1690
next = tlb_read_short();
1691
print_offset();
1692
if (next != -1)
1693
printf("next offset = %#x (+%#x=%#x)\n",
1694
next, funcs_start_offset, next + funcs_start_offset);
1695
else
1696
printf("next offset = ffffh\n");
1697
print_short_hex("res04");
1698
print_byte("impltypeflags");
1699
print_byte("res07");
1700
print_short_hex("res08");
1701
print_short_hex("ref");
1702
print_short_hex("res0c");
1703
print_short_hex("res0e");
1704
print_short_hex("res10");
1705
print_short_hex("res12");
1706
print_short_hex("pos in table");
1707
1708
print_end_block();
1709
}
1710
1711
for (i = 0; i < tail->cFuncs; i++)
1712
{
1713
char name[64];
1714
BYTE magic, flags;
1715
short args_off, value, n_params, j;
1716
1717
sprintf(name, "function %d (current offset %#x)", i, offset);
1718
print_begin_block(name);
1719
1720
magic = print_byte("magic");
1721
flags = tlb_read_byte();
1722
print_offset();
1723
printf("invoke_kind = %u\n", flags >> 4);
1724
next = tlb_read_short();
1725
print_offset();
1726
if (next != -1)
1727
printf("next offset = %#x (+%#x=%#x)\n",
1728
next, funcs_start_offset, next + funcs_start_offset);
1729
else
1730
printf("next offset = ffffh\n");
1731
print_short_hex("name");
1732
print_hex("dispid");
1733
print_short_hex("helpcontext");
1734
1735
value = tlb_read_short();
1736
print_offset();
1737
if (value != -1)
1738
{
1739
const char *str;
1740
UINT hlpstr_maxlen;
1741
1742
printf("helpstring offset = %#x (+%#x=%#x)\n",
1743
value, funcs_start_offset, value + funcs_start_offset);
1744
1745
saved_offset = offset;
1746
1747
offset = value + funcs_start_offset;
1748
1749
hlpstr_maxlen = member_offset + sizeof(struct sltg_member_header) + mem->extra - offset;
1750
1751
str = tlb_read(hlpstr_maxlen);
1752
str = decode_string((const BYTE *)hlp_strings, str, hlpstr_maxlen, &hlpstr_maxlen);
1753
print_offset();
1754
printf("helpstring: \"%s\"\n", str);
1755
1756
offset = value + funcs_start_offset;
1757
print_offset();
1758
printf("helpstring encoded bits: %d bytes\n", hlpstr_maxlen);
1759
dump_binary(hlpstr_maxlen);
1760
1761
offset = saved_offset;
1762
}
1763
else
1764
printf("helpstring offset = ffffh\n");
1765
1766
args_off = tlb_read_short();
1767
print_offset();
1768
if (args_off != -1)
1769
printf("args off = %#x (+%#x=%#x)\n",
1770
args_off, funcs_start_offset, args_off + funcs_start_offset);
1771
else
1772
printf("args off = ffffh\n");
1773
flags = tlb_read_byte();
1774
n_params = flags >> 3;
1775
print_offset();
1776
printf("callconv %u, cParams %u\n", flags & 0x7, n_params);
1777
1778
flags = tlb_read_byte();
1779
print_offset();
1780
printf("retnextop %02x, cParamsOpt %u\n", flags, (flags & 0x7e) >> 1);
1781
1782
value = print_short_hex("rettype");
1783
if (!(flags & 0x80))
1784
{
1785
print_offset();
1786
printf("rettype offset = %#x (+%#x=%#x)\n",
1787
value, funcs_start_offset, value + funcs_start_offset);
1788
print_offset();
1789
printf("rettype:\n");
1790
sltg_print_compound_type(funcs_start_offset, value);
1791
}
1792
else
1793
{
1794
print_offset();
1795
printf("rettype:\n");
1796
sltg_print_simple_type(value);
1797
}
1798
1799
print_short_hex("vtblpos");
1800
if (magic & 0x20)
1801
print_short_hex("funcflags");
1802
1803
if (n_params)
1804
{
1805
offset = args_off + funcs_start_offset;
1806
print_offset();
1807
printf("arguments start at %#x\n", offset);
1808
}
1809
1810
for (j = 0; j < n_params; j++)
1811
{
1812
char name[32];
1813
unsigned short name_offset;
1814
1815
sprintf(name, "arg %d", j);
1816
print_begin_block(name);
1817
1818
name_offset = tlb_read_short();
1819
print_offset();
1820
printf("name: %04xh\n", name_offset);
1821
1822
value = tlb_read_short();
1823
print_offset();
1824
printf("type/offset %04xh\n", value);
1825
if (name_offset & 1) /* type follows */
1826
{
1827
print_offset();
1828
printf("type follows, using current offset for type\n");
1829
offset -= 2;
1830
value = offset - funcs_start_offset;
1831
}
1832
1833
print_offset();
1834
printf("arg[%d] off = %#x (+%#x=%#x)\n",
1835
j, value, funcs_start_offset, value + funcs_start_offset);
1836
print_offset();
1837
printf("type:\n");
1838
value = sltg_print_compound_type(funcs_start_offset, value);
1839
if (name_offset & 1)
1840
offset += value;
1841
1842
print_end_block();
1843
}
1844
1845
if (n_params)
1846
{
1847
print_offset();
1848
printf("arguments end at %#x\n", offset);
1849
}
1850
1851
if (next != -1)
1852
{
1853
if (offset != funcs_start_offset + next)
1854
dump_binary(funcs_start_offset + next - offset);
1855
}
1856
1857
print_end_block();
1858
}
1859
}
1860
else
1861
{
1862
dump_binary(extra);
1863
}
1864
1865
if (offset < member_offset + sizeof(struct sltg_member_header) + mem->extra)
1866
{
1867
dump_binary(member_offset + sizeof(struct sltg_member_header) + mem->extra - offset);
1868
}
1869
1870
len -= offset - typeinfo_start_offset;
1871
print_offset();
1872
printf("sltg_tail %d (%#x) bytes:\n", len, len);
1873
saved_offset = offset;
1874
dump_binary(len);
1875
offset = saved_offset;
1876
print_short_hex("cFuncs");
1877
print_short_hex("cVars");
1878
print_short_hex("cImplTypes");
1879
print_short_hex("res06");
1880
print_short_hex("funcs_off");
1881
print_short_hex("vars_off");
1882
print_short_hex("impls_off");
1883
print_short_hex("funcs_bytes");
1884
print_short_hex("vars_bytes");
1885
print_short_hex("impls_bytes");
1886
print_short_hex("tdescalias_vt");
1887
print_short_hex("res16");
1888
print_short_hex("res18");
1889
print_short_hex("res1a");
1890
print_short_hex("simple_alias");
1891
print_short_hex("res1e");
1892
print_short_hex("cbSizeInstance");
1893
print_short_hex("cbAlignment");
1894
print_short_hex("res24");
1895
print_short_hex("res26");
1896
print_short_hex("cbSizeVft");
1897
print_short_hex("res2a");
1898
print_short_hex("res2c");
1899
print_short_hex("res2e");
1900
print_short_hex("res30");
1901
print_short_hex("res32");
1902
print_short_hex("res34");
1903
offset = saved_offset + len;
1904
}
1905
1906
static void sltg_dump(void)
1907
{
1908
int i, n_file_blocks, n_first_blk, size_of_index, size_of_pad;
1909
int name_table_start, name_table_size, saved_offset;
1910
int libblk_start, libblk_len, hlpstr_len, len;
1911
const char *index, *hlp_strings;
1912
const struct block_entry *entry;
1913
1914
n_file_blocks = dump_sltg_header(&n_first_blk, &size_of_index, &size_of_pad);
1915
1916
saved_offset = offset;
1917
entry = tlb_read((n_file_blocks - 1) * sizeof(*entry));
1918
if (!entry) return;
1919
index = tlb_read(size_of_index);
1920
if (!index) return;
1921
offset = saved_offset;
1922
1923
for (i = 0; i < n_file_blocks - 1; i++)
1924
dump_sltg_block_entry(i, index);
1925
1926
saved_offset = offset;
1927
dump_sltg_index(n_file_blocks);
1928
assert(offset - saved_offset == size_of_index);
1929
1930
dump_sltg_pad(size_of_pad);
1931
1932
/* read the helpstrings for later decoding */
1933
saved_offset = offset;
1934
1935
for (i = n_first_blk - 1; entry[i].next != 0; i = entry[i].next - 1)
1936
tlb_read(entry[i].len);
1937
1938
libblk_start = offset;
1939
skip_sltg_library_block();
1940
tlb_read(0x40);
1941
typeinfo_cnt = tlb_read_short();
1942
1943
for (i = 0; i < typeinfo_cnt; i++)
1944
skip_sltg_other_typeinfo();
1945
1946
len = tlb_read_int();
1947
hlpstr_len = (libblk_start + len) - offset;
1948
hlp_strings = tlb_read(hlpstr_len);
1949
assert(hlp_strings != NULL);
1950
/* check the helpstrings header values */
1951
len = *(int *)(hlp_strings + 2);
1952
assert(hlpstr_len == len + 6);
1953
1954
offset = saved_offset;
1955
1956
for (i = n_first_blk - 1; entry[i].next != 0; i = entry[i].next - 1)
1957
{
1958
short magic;
1959
char name[32];
1960
1961
saved_offset = offset;
1962
1963
sprintf(name, "Block %d", i);
1964
print_begin_block(name);
1965
magic = tlb_read_short();
1966
assert(magic == 0x0501);
1967
offset -= 2;
1968
dump_binary(entry[i].len);
1969
print_end_block();
1970
1971
offset = saved_offset;
1972
1973
print_begin_block(name);
1974
dump_type(entry[i].len, hlp_strings);
1975
print_end_block();
1976
1977
offset = saved_offset + entry[i].len;
1978
}
1979
1980
libblk_len = entry[i].len;
1981
1982
libblk_start = offset;
1983
dump_sltg_library_block();
1984
1985
print_offset();
1986
dump_binary(0x40);
1987
print_offset();
1988
printf("\n");
1989
typeinfo_cnt = print_short_dec("typeinfo count");
1990
print_offset();
1991
printf("\n");
1992
1993
for (i = 0; i < typeinfo_cnt; i++)
1994
dump_sltg_other_typeinfo(i, hlp_strings);
1995
1996
len = print_hex("offset from start of library block to name table");
1997
print_offset();
1998
printf("%#x + %#x = %#x\n", libblk_start, len, libblk_start + len);
1999
len = (libblk_start + len) - offset;
2000
print_offset();
2001
printf("skipping %#x bytes (encoded/compressed helpstrings)\n", len);
2002
print_offset();
2003
printf("max string length: %#x, strings length %#x\n", *(short *)hlp_strings, *(int *)(hlp_strings + 2));
2004
dump_binary(len);
2005
print_offset();
2006
printf("\n");
2007
2008
len = print_short_hex("name table jump");
2009
if (len == 0xffff)
2010
{
2011
dump_binary(0x000a);
2012
print_offset();
2013
printf("\n");
2014
}
2015
else if (len == 0x0200)
2016
{
2017
dump_binary(0x002a);
2018
print_offset();
2019
printf("\n");
2020
}
2021
else
2022
{
2023
printf("FIXME: please report! (%#x)\n", len);
2024
assert(0);
2025
}
2026
2027
dump_binary(0x200);
2028
print_offset();
2029
printf("\n");
2030
2031
name_table_size = print_hex("name table size");
2032
2033
name_table_start = offset;
2034
print_offset();
2035
printf("name table offset = %#x\n", offset);
2036
print_offset();
2037
printf("\n");
2038
2039
while (offset < name_table_start + name_table_size)
2040
{
2041
int aligned_len;
2042
2043
dump_binary(8);
2044
print_offset();
2045
print_string0();
2046
printf("\n");
2047
2048
len = offset - name_table_start;
2049
aligned_len = (len + 0x1f) & ~0x1f;
2050
if (aligned_len - len < 4)
2051
dump_binary(aligned_len - len);
2052
else
2053
dump_binary(len & 1);
2054
print_offset();
2055
printf("\n");
2056
}
2057
2058
print_hex("01ffff01");
2059
len = print_hex("length");
2060
dump_binary(len);
2061
print_offset();
2062
printf("\n");
2063
2064
len = (libblk_start + libblk_len) - offset;
2065
print_offset();
2066
printf("skipping libblk remainder %#x bytes\n", len);
2067
dump_binary(len);
2068
print_offset();
2069
printf("\n");
2070
2071
/* FIXME: msodumper/olestream.py parses this block differently
2072
print_short_hex("unknown");
2073
print_short_hex("byte order mark");
2074
i = tlb_read_short();
2075
printf("version = %u.%u\n", i & 0xff, i >> 8);
2076
print_short_hex("system identifier");
2077
print_hex("unknown");
2078
printf("\n");
2079
*/
2080
print_offset();
2081
printf("skipping 12 bytes\n");
2082
dump_binary(12);
2083
print_offset();
2084
printf("\n");
2085
2086
print_guid("uuid");
2087
print_offset();
2088
printf("\n");
2089
2090
/* 0x0008,"TYPELIB",0 */
2091
dump_binary(12);
2092
print_offset();
2093
printf("\n");
2094
2095
print_offset();
2096
printf("skipping 12 bytes\n");
2097
dump_binary(12);
2098
print_offset();
2099
printf("\n");
2100
2101
print_offset();
2102
printf("skipping remainder 0x10 bytes\n");
2103
dump_binary(0x10);
2104
}
2105
2106
void tlb_dump(void)
2107
{
2108
const DWORD *sig = PRD(0, sizeof(DWORD));
2109
if (*sig == MSFT_MAGIC)
2110
msft_dump();
2111
else
2112
sltg_dump();
2113
}
2114
2115
void tlb_dump_resource( void *ptr, size_t size, const char *prefix )
2116
{
2117
void *prev_dump_base = dump_base;
2118
size_t prev_dump_total_len = dump_total_len;
2119
const DWORD *sig;
2120
2121
dump_base = ptr;
2122
dump_total_len = size;
2123
dump_prefix = prefix;
2124
2125
sig = PRD(0, sizeof(DWORD));
2126
if (*sig == MSFT_MAGIC)
2127
msft_dump();
2128
else
2129
sltg_dump();
2130
2131
dump_base = prev_dump_base;
2132
dump_total_len = prev_dump_total_len;
2133
}
2134
2135
enum FileSig get_kind_tlb(void)
2136
{
2137
const DWORD *sig = PRD(0, sizeof(DWORD));
2138
if (sig && (*sig == MSFT_MAGIC || *sig == SLTG_MAGIC)) return SIG_TLB;
2139
return SIG_UNKNOWN;
2140
}
2141
2142