Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/tools/widl/write_sltg.c
4388 views
1
/*
2
* Typelib (SLTG) generation
3
*
4
* Copyright 2015,2016 Dmitry Timoshkov
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
23
#include <stdlib.h>
24
#include <string.h>
25
#include <stdarg.h>
26
#include <stdio.h>
27
#include <ctype.h>
28
#include <time.h>
29
30
#include "widl.h"
31
#include "windef.h"
32
#include "winbase.h"
33
34
#include "typelib.h"
35
#include "typelib_struct.h"
36
#include "utils.h"
37
#include "header.h"
38
#include "typetree.h"
39
40
static const GUID sltg_library_guid = { 0x204ff,0,0,{ 0xc0,0,0,0,0,0,0,0x46 } };
41
42
struct sltg_data
43
{
44
int size, allocated;
45
char *data;
46
};
47
48
struct sltg_library
49
{
50
short name;
51
char *helpstring;
52
char *helpfile;
53
int helpcontext;
54
int syskind;
55
LCID lcid;
56
int libflags;
57
int version;
58
GUID uuid;
59
};
60
61
struct sltg_block
62
{
63
int length;
64
int index_string;
65
void *data;
66
};
67
68
struct sltg_typelib
69
{
70
typelib_t *typelib;
71
struct sltg_data index;
72
struct sltg_data name_table;
73
struct sltg_library library;
74
struct sltg_block *blocks;
75
int block_count;
76
int first_block;
77
short typeinfo_count;
78
int typeinfo_size;
79
struct sltg_block *typeinfo;
80
};
81
82
struct sltg_hrefmap
83
{
84
int href_count;
85
int *href;
86
};
87
88
#pragma pack(push,1)
89
struct sltg_typeinfo_header
90
{
91
short magic;
92
int href_offset;
93
int res06;
94
int member_offset;
95
int res0e;
96
int version;
97
int res16;
98
struct
99
{
100
unsigned unknown1 : 3;
101
unsigned flags : 13;
102
unsigned unknown2 : 8;
103
unsigned typekind : 8;
104
} misc;
105
int res1e;
106
};
107
108
struct sltg_member_header
109
{
110
short res00;
111
short res02;
112
char res04;
113
int extra;
114
};
115
116
struct sltg_variable
117
{
118
char magic; /* 0x0a */
119
char flags;
120
short next;
121
short name;
122
short byte_offs; /* pos in struct, or offset to const type or const data (if flags & 0x08) */
123
short type; /* if flags & 0x02 this is the type, else offset to type */
124
int memid;
125
short helpcontext;
126
short helpstring;
127
short varflags; /* only present if magic & 0x20 */
128
};
129
130
struct sltg_tail
131
{
132
short cFuncs;
133
short cVars;
134
short cImplTypes;
135
short res06; /* always 0000 */
136
short funcs_off; /* offset to functions (starting from the member header) */
137
short vars_off; /* offset to vars (starting from the member header) */
138
short impls_off; /* offset to implemented types (starting from the member header) */
139
short funcs_bytes; /* bytes used by function data */
140
short vars_bytes; /* bytes used by var data */
141
short impls_bytes; /* bytes used by implemented type data */
142
short tdescalias_vt; /* for TKIND_ALIAS */
143
short res16; /* always ffff */
144
short res18; /* always 0000 */
145
short res1a; /* always 0000 */
146
short simple_alias; /* tdescalias_vt is a vt rather than an offset? */
147
short res1e; /* always 0000 */
148
short cbSizeInstance;
149
short cbAlignment;
150
short res24;
151
short res26;
152
short cbSizeVft;
153
short res2a; /* always ffff */
154
short res2c; /* always ffff */
155
short res2e; /* always ffff */
156
short res30; /* always ffff */
157
short res32; /* unknown */
158
short type_bytes; /* bytes used by type descriptions */
159
};
160
161
struct sltg_hrefinfo
162
{
163
char magic; /* 0xdf */
164
char res01; /* 0x00 */
165
char res02[0x42]; /* 0xff... */
166
int number; /* this is 8 times the number of refs */
167
/* Now we have number bytes (8 for each ref) of SLTG_UnknownRefInfo */
168
169
short res50;/* 0xffff */
170
char res52; /* 0x01 */
171
int res53; /* 0x00000000 */
172
/* Now we have number/8 SLTG_Names (first WORD is no of bytes in the ascii
173
* string). Strings look like "*\Rxxxx*#n". If xxxx == ffff then the
174
* ref refers to the nth type listed in this library (0 based). Else
175
* the xxxx (which maybe fewer than 4 digits) is the offset into the name
176
* table to a string "*\G{<guid>}#1.0#0#C:\WINNT\System32\stdole32.tlb#"
177
* The guid is the typelib guid; the ref again refers to the nth type of
178
* the imported typelib.
179
*/
180
181
char resxx; /* 0xdf */
182
};
183
184
struct sltg_function
185
{
186
char magic; /* 0x4c, 0xcb or 0x8b with optional SLTG_FUNCTION_FLAGS_PRESENT flag */
187
char flags; /* high nibble is INVOKE_KIND, low nibble = 2 */
188
short next; /* byte offset from beginning of group to next fn */
189
short name; /* Offset within name table to name */
190
int dispid; /* dispid */
191
short helpcontext; /* helpcontext (again 1 is special) */
192
short helpstring; /* helpstring offset to offset */
193
short arg_off; /* offset to args from start of block */
194
char nacc; /* lowest 3bits are CALLCONV, rest are no of args */
195
char retnextopt; /* if 0x80 bit set ret type follows else next WORD
196
is offset to ret type. No of optional args is
197
middle 6 bits */
198
short rettype; /* return type VT_?? or offset to ret type */
199
short vtblpos; /* position in vtbl? */
200
short funcflags; /* present if magic & 0x20 */
201
/* Param list starts, repeat next two as required */
202
#if 0
203
WORD name; /* offset to 2nd letter of name */
204
WORD+ type; /* VT_ of param */
205
#endif
206
};
207
208
struct sltg_impl_info
209
{
210
short res00;
211
short next;
212
short res04;
213
char impltypeflags;
214
char res07;
215
short res08;
216
short ref;
217
short res0c;
218
short res0e;
219
short res10;
220
short res12;
221
short pos;
222
};
223
224
#pragma pack(pop)
225
226
static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type);
227
static void add_interface_typeinfo(struct sltg_typelib *typelib, type_t *type);
228
static void add_enum_typeinfo(struct sltg_typelib *typelib, type_t *type);
229
static void add_union_typeinfo(struct sltg_typelib *typelib, type_t *type);
230
static void add_coclass_typeinfo(struct sltg_typelib *typelib, type_t *type);
231
232
static void init_sltg_data(struct sltg_data *data)
233
{
234
data->size = 0;
235
data->allocated = 0;
236
data->data = NULL;
237
}
238
239
static int add_index(struct sltg_data *index, const char *name)
240
{
241
int name_offset = index->size;
242
int new_size = index->size + strlen(name) + 1;
243
244
chat("add_index: name_offset %d, \"%s\"\n", name_offset, name);
245
246
if (new_size > index->allocated)
247
{
248
index->allocated = index->allocated ? max(index->allocated * 2, new_size) : new_size;
249
index->data = xrealloc(index->data, index->allocated);
250
}
251
252
strcpy(index->data + index->size, name);
253
index->size = new_size;
254
255
return name_offset;
256
}
257
258
static void init_index(struct sltg_data *index)
259
{
260
static const char compobj[] = { 1,'C','o','m','p','O','b','j',0 };
261
262
init_sltg_data(index);
263
264
add_index(index, compobj);
265
}
266
267
static int add_name(struct sltg_data *name_table, const char *name)
268
{
269
int name_offset = name_table->size;
270
int new_size = name_table->size + strlen(name) + 1 + 8;
271
int aligned_size;
272
273
chat("add_name: %s\n", name);
274
275
aligned_size = (new_size + 0x1f) & ~0x1f;
276
if (aligned_size - new_size < 4)
277
new_size = aligned_size;
278
else
279
new_size = (new_size + 1) & ~1;
280
281
if (new_size > name_table->allocated)
282
{
283
name_table->allocated = name_table->allocated ? max(name_table->allocated * 2, new_size) : new_size;
284
name_table->data = xrealloc(name_table->data, name_table->allocated);
285
}
286
287
memset(name_table->data + name_table->size, 0xff, 8);
288
strcpy(name_table->data + name_table->size + 8, name);
289
name_table->size = new_size;
290
name_table->data[name_table->size - 1] = 0; /* clear alignment */
291
292
return name_offset;
293
}
294
295
static void init_name_table(struct sltg_data *name_table)
296
{
297
init_sltg_data(name_table);
298
}
299
300
static void init_library(struct sltg_typelib *sltg)
301
{
302
const attr_t *attr;
303
304
sltg->library.name = add_name(&sltg->name_table, sltg->typelib->name);
305
sltg->library.helpstring = NULL;
306
sltg->library.helpcontext = 0;
307
sltg->library.syskind = SYS_WIN32;
308
sltg->library.lcid = 0x0409;
309
sltg->library.libflags = 0;
310
sltg->library.version = 0;
311
sltg->library.helpfile = NULL;
312
memset(&sltg->library.uuid, 0, sizeof(sltg->library.uuid));
313
314
if (!sltg->typelib->attrs) return;
315
316
LIST_FOR_EACH_ENTRY(attr, sltg->typelib->attrs, const attr_t, entry)
317
{
318
const expr_t *expr;
319
320
switch (attr->type)
321
{
322
case ATTR_VERSION:
323
{
324
const version_t *version = attr->u.pval;
325
unsigned short major = version ? version->major : 0, minor = version ? version->minor : 0;
326
327
sltg->library.version = (minor << 16) | major;
328
break;
329
}
330
case ATTR_HELPSTRING:
331
sltg->library.helpstring = attr->u.pval;
332
break;
333
case ATTR_HELPFILE:
334
sltg->library.helpfile = attr->u.pval;
335
break;
336
case ATTR_UUID:
337
sltg->library.uuid = *(GUID *)attr->u.pval;
338
break;
339
case ATTR_HELPCONTEXT:
340
expr = attr->u.pval;
341
sltg->library.helpcontext = expr->cval;
342
break;
343
case ATTR_LIBLCID:
344
expr = attr->u.pval;
345
sltg->library.lcid = expr->cval;
346
break;
347
case ATTR_CONTROL:
348
sltg->library.libflags |= 0x02; /* LIBFLAG_FCONTROL */
349
break;
350
case ATTR_HIDDEN:
351
sltg->library.libflags |= 0x04; /* LIBFLAG_FHIDDEN */
352
break;
353
case ATTR_RESTRICTED:
354
sltg->library.libflags |= 0x01; /* LIBFLAG_FRESTRICTED */
355
break;
356
default:
357
break;
358
}
359
}
360
}
361
362
static void add_block_index(struct sltg_typelib *sltg, void *data, int length, int index)
363
{
364
sltg->blocks = xrealloc(sltg->blocks, sizeof(sltg->blocks[0]) * (sltg->block_count + 1));
365
sltg->blocks[sltg->block_count].length = length;
366
sltg->blocks[sltg->block_count].data = data;
367
sltg->blocks[sltg->block_count].index_string = index;
368
sltg->block_count++;
369
}
370
371
static void add_block(struct sltg_typelib *sltg, void *data, int size, const char *name)
372
{
373
struct sltg_block *block = xmalloc(sizeof(*block));
374
int index;
375
376
chat("add_block: %p,%d,\"%s\"\n", data, size, name);
377
378
index = add_index(&sltg->index, name);
379
380
add_block_index(sltg, data, size, index);
381
}
382
383
static void *create_library_block(struct sltg_typelib *typelib, int *size, int *index)
384
{
385
void *block;
386
short *p;
387
388
*size = sizeof(short) * 9 + sizeof(int) * 3 + sizeof(GUID);
389
if (typelib->library.helpstring) *size += strlen(typelib->library.helpstring);
390
if (typelib->library.helpfile) *size += strlen(typelib->library.helpfile);
391
392
block = xmalloc(*size);
393
p = block;
394
*p++ = 0x51cc; /* magic */
395
*p++ = 3; /* res02 */
396
*p++ = typelib->library.name;
397
*p++ = 0xffff; /* res06 */
398
if (typelib->library.helpstring)
399
{
400
*p++ = strlen(typelib->library.helpstring);
401
strcpy((char *)p, typelib->library.helpstring);
402
p = (short *)((char *)p + strlen(typelib->library.helpstring));
403
}
404
else
405
*p++ = 0xffff;
406
if (typelib->library.helpfile)
407
{
408
*p++ = strlen(typelib->library.helpfile);
409
strcpy((char *)p, typelib->library.helpfile);
410
p = (short *)((char *)p + strlen(typelib->library.helpfile));
411
}
412
else
413
*p++ = 0xffff;
414
*(int *)p = typelib->library.helpcontext;
415
p += 2;
416
*p++ = typelib->library.syskind;
417
*p++ = typelib->library.lcid;
418
*(int *)p = 0; /* res12 */
419
p += 2;
420
*p++ = typelib->library.libflags;
421
*(int *)p = typelib->library.version;
422
p += 2;
423
*(GUID *)p = typelib->library.uuid;
424
425
*index = add_index(&typelib->index, "dir");
426
427
return block;
428
}
429
430
static const char *new_index_name(void)
431
{
432
static char name[11] = "AAAAAAAAAA";
433
static int pos = 0;
434
char *new_name;
435
436
if (name[pos] == 'Z')
437
{
438
pos++;
439
if (pos > 9)
440
error("too many index names\n");
441
}
442
443
name[pos]++;
444
445
new_name = xmalloc(sizeof(name));
446
strcpy(new_name, name);
447
return new_name;
448
}
449
450
static void sltg_add_typeinfo(struct sltg_typelib *sltg, void *data, int length, const char *name)
451
{
452
chat("sltg_add_typeinfo: %p,%d,%s\n", data, length, name);
453
454
sltg->typeinfo = xrealloc(sltg->typeinfo, sizeof(sltg->typeinfo[0]) * (sltg->typeinfo_count + 1));
455
sltg->typeinfo[sltg->typeinfo_count].length = length;
456
sltg->typeinfo[sltg->typeinfo_count].data = data;
457
sltg->typeinfo[sltg->typeinfo_count].index_string = 0;
458
sltg->typeinfo_count++;
459
sltg->typeinfo_size += length;
460
}
461
462
static void append_data(struct sltg_data *block, const void *data, int size)
463
{
464
int new_size = block->size + size;
465
466
if (new_size > block->allocated)
467
{
468
block->allocated = max(block->allocated * 2, new_size);
469
block->data = xrealloc(block->data, block->allocated);
470
}
471
472
memcpy(block->data + block->size, data, size);
473
block->size = new_size;
474
}
475
476
static void add_module_typeinfo(struct sltg_typelib *typelib, type_t *type)
477
{
478
error("add_module_typeinfo: %s not implemented\n", type->name);
479
}
480
481
static const char *add_typeinfo_block(struct sltg_typelib *typelib, const type_t *type, short kind)
482
{
483
struct sltg_data block;
484
const char *index_name, *other_name;
485
short val;
486
void *p;
487
int helpcontext = 0;
488
GUID guid = { 0 };
489
const expr_t *expr;
490
491
index_name = new_index_name();
492
other_name = new_index_name();
493
494
expr = get_attrp(type->attrs, ATTR_HELPCONTEXT);
495
if (expr) helpcontext = expr->cval;
496
497
p = get_attrp(type->attrs, ATTR_UUID);
498
if (p) guid = *(GUID *)p;
499
500
init_sltg_data(&block);
501
502
val = strlen(index_name);
503
append_data(&block, &val, sizeof(val));
504
append_data(&block, index_name, val);
505
val = strlen(other_name);
506
append_data(&block, &val, sizeof(val));
507
append_data(&block, other_name, val);
508
val = -1; /* res1a */
509
append_data(&block, &val, sizeof(val));
510
val = add_name(&typelib->name_table, type->name); /* name offset */
511
append_data(&block, &val, sizeof(val));
512
val = 0; /* FIXME: helpstring */
513
append_data(&block, &val, sizeof(val));
514
val = -1; /* res20 */
515
append_data(&block, &val, sizeof(val));
516
append_data(&block, &helpcontext, sizeof(helpcontext));
517
val = -1; /* res26 */
518
append_data(&block, &val, sizeof(val));
519
append_data(&block, &guid, sizeof(guid));
520
append_data(&block, &kind, sizeof(kind));
521
522
sltg_add_typeinfo(typelib, block.data, block.size, index_name);
523
524
return index_name;
525
}
526
527
static void init_typeinfo(struct sltg_typeinfo_header *ti, const type_t *type, short kind,
528
const struct sltg_hrefmap *hrefmap)
529
{
530
unsigned short major, minor;
531
532
get_version( type->attrs, &major, &minor );
533
534
ti->magic = 0x0501;
535
ti->href_offset = -1;
536
ti->res06 = -1;
537
ti->member_offset = sizeof(*ti);
538
ti->res0e = -1;
539
ti->version = minor << 16 | major;
540
ti->res16 = 0xfffe0000;
541
ti->misc.unknown1 = 0x02;
542
ti->misc.flags = 0; /* FIXME */
543
ti->misc.unknown2 = 0x02;
544
ti->misc.typekind = kind;
545
ti->res1e = 0;
546
547
if (hrefmap->href_count)
548
{
549
char name[64];
550
int i, hrefinfo_size;
551
552
hrefinfo_size = sizeof(struct sltg_hrefinfo);
553
554
for (i = 0; i < hrefmap->href_count; i++)
555
{
556
snprintf(name, sizeof(name), "*\\Rffff*#%x", hrefmap->href[i]);
557
hrefinfo_size += 8 + 2 + strlen(name);
558
}
559
560
ti->href_offset = ti->member_offset;
561
ti->member_offset += hrefinfo_size;
562
}
563
}
564
565
static void write_hrefmap(struct sltg_data *data, const struct sltg_hrefmap *hrefmap)
566
{
567
struct sltg_hrefinfo hrefinfo;
568
char name[64];
569
int i;
570
571
if (!hrefmap->href_count) return;
572
573
hrefinfo.magic = 0xdf;
574
hrefinfo.res01 = 0;
575
memset(hrefinfo.res02, 0xff, sizeof(hrefinfo.res02));
576
hrefinfo.number = hrefmap->href_count * 8;
577
hrefinfo.res50 = -1;
578
hrefinfo.res52 = 1;
579
hrefinfo.res53 = 0;
580
hrefinfo.resxx = 0xdf;
581
582
append_data(data, &hrefinfo, offsetof(struct sltg_hrefinfo, res50));
583
584
for (i = 0; i < hrefmap->href_count; i++)
585
append_data(data, "\xff\xff\xff\xff\xff\xff\xff\xff", 8);
586
587
append_data(data, &hrefinfo.res50, 7);
588
589
for (i = 0; i < hrefmap->href_count; i++)
590
{
591
short len;
592
593
snprintf(name, sizeof(name), "*\\Rffff*#%x", hrefmap->href[i]);
594
len = strlen(name);
595
596
append_data(data, &len, sizeof(len));
597
append_data(data, name, len);
598
}
599
600
append_data(data, &hrefinfo.resxx, sizeof(hrefinfo.resxx));
601
}
602
603
static void dump_var_desc(const char *data, int size)
604
{
605
const unsigned char *p = (const unsigned char *)data;
606
int i;
607
608
if (!(debuglevel & (DEBUGLEVEL_TRACE | DEBUGLEVEL_CHAT))) return;
609
610
chat("dump_var_desc: size %d bytes\n", size);
611
612
for (i = 0; i < size; i++)
613
fprintf(stderr, " %02x", *p++);
614
615
fprintf(stderr, "\n");
616
}
617
618
static int get_element_size(type_t *type)
619
{
620
int vt = get_type_vt(type);
621
622
switch (vt)
623
{
624
case VT_I1:
625
case VT_UI1:
626
return 1;
627
628
case VT_UI2:
629
case VT_I2:
630
case VT_BOOL:
631
return 2;
632
633
case VT_INT:
634
case VT_UINT:
635
case VT_I4:
636
case VT_UI4:
637
case VT_R4:
638
case VT_ERROR:
639
case VT_HRESULT:
640
return 4;
641
642
case VT_R8:
643
case VT_I8:
644
case VT_UI8:
645
case VT_CY:
646
case VT_DATE:
647
return 8;
648
649
case VT_DECIMAL:
650
return 16;
651
652
case VT_PTR:
653
case VT_UNKNOWN:
654
case VT_DISPATCH:
655
case VT_BSTR:
656
case VT_LPSTR:
657
case VT_LPWSTR:
658
return 4;
659
660
case VT_VOID:
661
return 0;
662
663
case VT_VARIANT:
664
return 16;
665
666
case VT_USERDEFINED:
667
return 0;
668
669
default:
670
error("get_element_size: unrecognized vt %d\n", vt);
671
break;
672
}
673
674
return 0;
675
}
676
677
static int local_href(struct sltg_hrefmap *hrefmap, int typelib_href)
678
{
679
int i, href = -1;
680
681
for (i = 0; i < hrefmap->href_count; i++)
682
{
683
if (hrefmap->href[i] == typelib_href)
684
{
685
href = i;
686
break;
687
}
688
}
689
690
if (href == -1)
691
{
692
href = hrefmap->href_count;
693
694
if (hrefmap->href)
695
hrefmap->href = xrealloc(hrefmap->href, sizeof(*hrefmap->href) * (hrefmap->href_count + 1));
696
else
697
hrefmap->href = xmalloc(sizeof(*hrefmap->href));
698
699
hrefmap->href[hrefmap->href_count] = typelib_href;
700
hrefmap->href_count++;
701
}
702
703
chat("typelib href %d mapped to local href %d\n", typelib_href, href);
704
705
return href << 2;
706
}
707
708
static short write_var_desc(struct sltg_typelib *typelib, struct sltg_data *data, type_t *type, short param_flags,
709
short flags, short base_offset, int *size_instance, struct sltg_hrefmap *hrefmap)
710
{
711
short vt, vt_flags, desc_offset;
712
713
chat("write_var_desc: type %p, type->name %s\n",
714
type, type->name ? type->name : "NULL");
715
716
if (is_array(type) && !type_array_is_decl_as_ptr(type))
717
{
718
int num_dims, elements, array_start, size, array_size;
719
type_t *atype;
720
struct
721
{
722
short cDims;
723
short fFeatures;
724
int cbElements;
725
int cLocks;
726
int pvData;
727
int bound[2];
728
} *array;
729
int *bound;
730
short vt_off[2];
731
732
elements = 1;
733
num_dims = 0;
734
735
atype = type;
736
737
while (is_array(atype) && !type_array_is_decl_as_ptr(atype))
738
{
739
num_dims++;
740
elements *= type_array_get_dim(atype);
741
742
atype = type_array_get_element_type(atype);
743
}
744
745
chat("write_var_desc: VT_CARRAY: %d dimensions, %d elements\n", num_dims, elements);
746
747
array_start = data->size;
748
749
size = sizeof(*array) + (num_dims - 1) * 8 /* sizeof(SAFEARRAYBOUND) */;
750
array = xmalloc(size);
751
752
array->cDims = num_dims;
753
array->fFeatures = 0x0004; /* FADF_EMBEDDED */
754
array->cbElements = get_element_size(atype);
755
array->cLocks = 0;
756
array->pvData = 0;
757
758
bound = array->bound;
759
760
array_size = array->cbElements;
761
atype = type;
762
763
while (is_array(atype) && !type_array_is_decl_as_ptr(atype))
764
{
765
bound[0] = type_array_get_dim(atype);
766
array_size *= bound[0];
767
bound[1] = 0;
768
bound += 2;
769
770
atype = type_array_get_element_type(atype);
771
}
772
773
if (size_instance)
774
{
775
*size_instance += array_size;
776
size_instance = NULL; /* don't account for element size */
777
}
778
779
append_data(data, array, size);
780
781
desc_offset = data->size;
782
783
vt_off[0] = VT_CARRAY;
784
vt_off[1] = array_start + base_offset;
785
append_data(data, vt_off, sizeof(vt_off));
786
787
/* fall through to write array element description */
788
type = atype;
789
}
790
else
791
desc_offset = data->size;
792
793
vt = get_type_vt(type);
794
795
if (vt == VT_PTR)
796
{
797
type_t *ref = is_ptr(type) ? type_pointer_get_ref_type(type) : type_array_get_element_type(type);
798
799
if (is_ptr(ref))
800
{
801
chat("write_var_desc: vt VT_PTR | 0x0400 | %04x\n", param_flags);
802
vt = VT_PTR | 0x0400 | param_flags;
803
append_data(data, &vt, sizeof(vt));
804
write_var_desc(typelib, data, ref, 0, 0, base_offset, size_instance, hrefmap);
805
}
806
else
807
write_var_desc(typelib, data, ref, param_flags, 0x0e00, base_offset, size_instance, hrefmap);
808
return desc_offset;
809
}
810
811
chat("write_var_desc: vt %d, flags %04x\n", vt, flags);
812
813
vt_flags = vt | flags | param_flags;
814
append_data(data, &vt_flags, sizeof(vt_flags));
815
816
if (vt == VT_USERDEFINED)
817
{
818
short href;
819
820
while (type->typelib_idx < 0 && type_is_alias(type))
821
type = type_alias_get_aliasee_type(type);
822
823
chat("write_var_desc: VT_USERDEFINED, type %p, name %s, real type %d, href %d\n",
824
type, type->name, type_get_type(type), type->typelib_idx);
825
826
if (type->typelib_idx == -1)
827
{
828
chat("write_var_desc: trying to ref not added type\n");
829
830
switch (type_get_type(type))
831
{
832
case TYPE_STRUCT:
833
add_structure_typeinfo(typelib, type);
834
break;
835
case TYPE_INTERFACE:
836
add_interface_typeinfo(typelib, type);
837
break;
838
case TYPE_ENUM:
839
add_enum_typeinfo(typelib, type);
840
break;
841
case TYPE_UNION:
842
add_union_typeinfo(typelib, type);
843
break;
844
case TYPE_COCLASS:
845
add_coclass_typeinfo(typelib, type);
846
break;
847
default:
848
error("write_var_desc: VT_USERDEFINED - unhandled type %d\n",
849
type_get_type(type));
850
}
851
}
852
853
if (type->typelib_idx == -1)
854
error("write_var_desc: trying to ref not added type\n");
855
856
href = local_href(hrefmap, type->typelib_idx);
857
chat("write_var_desc: VT_USERDEFINED, local href %d\n", href);
858
859
append_data(data, &href, sizeof(href));
860
}
861
862
if (size_instance)
863
*size_instance += get_element_size(type);
864
865
return desc_offset;
866
}
867
868
static void init_sltg_tail(struct sltg_tail *tail)
869
{
870
tail->cFuncs = 0;
871
tail->cVars = 0;
872
tail->cImplTypes = 0;
873
tail->res06 = 0;
874
tail->funcs_off = -1;
875
tail->vars_off = -1;
876
tail->impls_off = -1;
877
tail->funcs_bytes = -1;
878
tail->vars_bytes = -1;
879
tail->impls_bytes = -1;
880
tail->tdescalias_vt = -1;
881
tail->res16 = -1;
882
tail->res18 = 0;
883
tail->res1a = 0;
884
tail->simple_alias = 0;
885
tail->res1e = 0;
886
tail->cbSizeInstance = 0;
887
tail->cbAlignment = 4;
888
tail->res24 = -1;
889
tail->res26 = -1;
890
tail->cbSizeVft = 0;
891
tail->res2a = -1;
892
tail->res2c = -1;
893
tail->res2e = -1;
894
tail->res30 = -1;
895
tail->res32 = 0;
896
tail->type_bytes = 0;
897
}
898
899
static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type)
900
{
901
struct sltg_data data, *var_data = NULL;
902
struct sltg_hrefmap hrefmap;
903
const char *index_name;
904
struct sltg_typeinfo_header ti;
905
struct sltg_member_header member;
906
struct sltg_tail tail;
907
int member_offset, var_count = 0, var_data_size = 0, size_instance = 0;
908
short *type_desc_offset = NULL;
909
910
if (type->typelib_idx != -1) return;
911
912
chat("add_structure_typeinfo: type %p, type->name %s\n", type, type->name);
913
914
type->typelib_idx = typelib->block_count;
915
916
hrefmap.href_count = 0;
917
hrefmap.href = NULL;
918
919
if (type_struct_get_fields(type))
920
{
921
int i = 0;
922
var_t *var;
923
924
var_count = list_count(type_struct_get_fields(type));
925
926
var_data = xmalloc(var_count * sizeof(*var_data));
927
type_desc_offset = xmalloc(var_count * sizeof(*type_desc_offset));
928
929
LIST_FOR_EACH_ENTRY(var, type_struct_get_fields(type), var_t, entry)
930
{
931
short base_offset;
932
933
chat("add_structure_typeinfo: var %p (%s), type %p (%s)\n",
934
var, var->name, var->declspec.type, var->declspec.type->name);
935
936
init_sltg_data(&var_data[i]);
937
938
base_offset = var_data_size + (i + 1) * sizeof(struct sltg_variable);
939
type_desc_offset[i] = write_var_desc(typelib, &var_data[i], var->declspec.type, 0, 0,
940
base_offset, &size_instance, &hrefmap);
941
dump_var_desc(var_data[i].data, var_data[i].size);
942
943
if (var_data[i].size > sizeof(short))
944
var_data_size += var_data[i].size;
945
i++;
946
}
947
}
948
949
init_sltg_data(&data);
950
951
index_name = add_typeinfo_block(typelib, type, TKIND_RECORD);
952
953
init_typeinfo(&ti, type, TKIND_RECORD, &hrefmap);
954
append_data(&data, &ti, sizeof(ti));
955
956
write_hrefmap(&data, &hrefmap);
957
958
member_offset = data.size;
959
960
member.res00 = 0x0001;
961
member.res02 = 0xffff;
962
member.res04 = 0x01;
963
member.extra = var_data_size + var_count * sizeof(struct sltg_variable);
964
append_data(&data, &member, sizeof(member));
965
966
var_data_size = 0;
967
968
if (type_struct_get_fields(type))
969
{
970
int i = 0;
971
short next = member_offset;
972
var_t *var;
973
974
LIST_FOR_EACH_ENTRY(var, type_struct_get_fields(type), var_t, entry)
975
{
976
struct sltg_variable variable;
977
978
next += sizeof(variable);
979
980
variable.magic = 0x2a; /* always write flags to simplify calculations */
981
variable.name = add_name(&typelib->name_table, var->name);
982
variable.byte_offs = 0;
983
if (var_data[i].size > sizeof(short))
984
{
985
variable.flags = 0;
986
var_data_size = next - member_offset + type_desc_offset[i];
987
variable.type = var_data_size;
988
next += var_data[i].size;
989
}
990
else
991
{
992
variable.flags = 0x02;
993
variable.type = *(short *)var_data[i].data;
994
}
995
variable.next = i < var_count - 1 ? next - member_offset : -1;
996
variable.memid = 0x40000000 + i;
997
variable.helpcontext = -2; /* 0xfffe */
998
variable.helpstring = -1;
999
variable.varflags = 0;
1000
1001
append_data(&data, &variable, sizeof(variable));
1002
if (var_data[i].size > sizeof(short))
1003
append_data(&data, var_data[i].data, var_data[i].size);
1004
1005
i++;
1006
}
1007
}
1008
1009
init_sltg_tail(&tail);
1010
tail.cVars = var_count;
1011
tail.vars_off = 0;
1012
tail.vars_bytes = var_data_size;
1013
tail.cbSizeInstance = size_instance;
1014
tail.type_bytes = data.size - member_offset - sizeof(member);
1015
append_data(&data, &tail, sizeof(tail));
1016
1017
add_block(typelib, data.data, data.size, index_name);
1018
}
1019
1020
static importinfo_t *find_importinfo(typelib_t *typelib, const char *name)
1021
{
1022
importlib_t *importlib;
1023
1024
LIST_FOR_EACH_ENTRY(importlib, &typelib->importlibs, importlib_t, entry)
1025
{
1026
int i;
1027
1028
for (i = 0; i < importlib->ntypeinfos; i++)
1029
{
1030
if (!strcmp(name, importlib->importinfos[i].name))
1031
{
1032
chat("Found %s in importlib list\n", name);
1033
return &importlib->importinfos[i];
1034
}
1035
}
1036
}
1037
1038
return NULL;
1039
}
1040
1041
static int get_func_flags(const var_t *func, int *dispid, int *invokekind, int *helpcontext, const char **helpstring)
1042
{
1043
const attr_t *attr;
1044
int flags;
1045
1046
*invokekind = 1 /* INVOKE_FUNC */;
1047
*helpcontext = -2;
1048
*helpstring = NULL;
1049
1050
if (!func->attrs) return 0;
1051
1052
flags = 0;
1053
1054
LIST_FOR_EACH_ENTRY(attr, func->attrs, const attr_t, entry)
1055
{
1056
expr_t *expr = attr->u.pval;
1057
switch(attr->type)
1058
{
1059
case ATTR_BINDABLE:
1060
flags |= 0x4; /* FUNCFLAG_FBINDABLE */
1061
break;
1062
case ATTR_DEFAULTBIND:
1063
flags |= 0x20; /* FUNCFLAG_FDEFAULTBIND */
1064
break;
1065
case ATTR_DEFAULTCOLLELEM:
1066
flags |= 0x100; /* FUNCFLAG_FDEFAULTCOLLELEM */
1067
break;
1068
case ATTR_DISPLAYBIND:
1069
flags |= 0x10; /* FUNCFLAG_FDISPLAYBIND */
1070
break;
1071
case ATTR_HELPCONTEXT:
1072
*helpcontext = expr->u.integer.value;
1073
break;
1074
case ATTR_HELPSTRING:
1075
*helpstring = attr->u.pval;
1076
break;
1077
case ATTR_HIDDEN:
1078
flags |= 0x40; /* FUNCFLAG_FHIDDEN */
1079
break;
1080
case ATTR_ID:
1081
*dispid = expr->cval;
1082
break;
1083
case ATTR_IMMEDIATEBIND:
1084
flags |= 0x1000; /* FUNCFLAG_FIMMEDIATEBIND */
1085
break;
1086
case ATTR_NONBROWSABLE:
1087
flags |= 0x400; /* FUNCFLAG_FNONBROWSABLE */
1088
break;
1089
case ATTR_PROPGET:
1090
*invokekind = 0x2; /* INVOKE_PROPERTYGET */
1091
break;
1092
case ATTR_PROPPUT:
1093
*invokekind = 0x4; /* INVOKE_PROPERTYPUT */
1094
break;
1095
case ATTR_PROPPUTREF:
1096
*invokekind = 0x8; /* INVOKE_PROPERTYPUTREF */
1097
break;
1098
/* FIXME: FUNCFLAG_FREPLACEABLE */
1099
case ATTR_REQUESTEDIT:
1100
flags |= 0x8; /* FUNCFLAG_FREQUESTEDIT */
1101
break;
1102
case ATTR_RESTRICTED:
1103
flags |= 0x1; /* FUNCFLAG_FRESTRICTED */
1104
break;
1105
case ATTR_SOURCE:
1106
flags |= 0x2; /* FUNCFLAG_FSOURCE */
1107
break;
1108
case ATTR_UIDEFAULT:
1109
flags |= 0x200; /* FUNCFLAG_FUIDEFAULT */
1110
break;
1111
case ATTR_USESGETLASTERROR:
1112
flags |= 0x80; /* FUNCFLAG_FUSESGETLASTERROR */
1113
break;
1114
default:
1115
break;
1116
}
1117
}
1118
1119
return flags;
1120
}
1121
1122
static int get_param_flags(const var_t *param)
1123
{
1124
const attr_t *attr;
1125
int flags, in, out;
1126
1127
if (!param->attrs) return 0;
1128
1129
flags = 0;
1130
in = out = 0;
1131
1132
LIST_FOR_EACH_ENTRY(attr, param->attrs, const attr_t, entry)
1133
{
1134
switch(attr->type)
1135
{
1136
case ATTR_IN:
1137
in++;
1138
break;
1139
case ATTR_OUT:
1140
out++;
1141
break;
1142
case ATTR_PARAMLCID:
1143
flags |= 0x2000;
1144
break;
1145
case ATTR_RETVAL:
1146
flags |= 0x80;
1147
break;
1148
default:
1149
chat("unhandled param attr %d\n", attr->type);
1150
break;
1151
}
1152
}
1153
1154
if (out)
1155
flags |= in ? 0x8000 : 0x4000;
1156
else if (!in)
1157
flags |= 0xc000;
1158
1159
return flags;
1160
}
1161
1162
1163
static int add_func_desc(struct sltg_typelib *typelib, struct sltg_data *data, var_t *func,
1164
int idx, int dispid, short base_offset, struct sltg_hrefmap *hrefmap)
1165
{
1166
struct sltg_data ret_data, *arg_data;
1167
int arg_count = 0, arg_data_size, optional = 0, old_size;
1168
int funcflags = 0, invokekind = 1 /* INVOKE_FUNC */, helpcontext;
1169
const char *helpstring;
1170
const var_t *arg;
1171
short ret_desc_offset, *arg_desc_offset, arg_offset;
1172
struct sltg_function func_desc;
1173
1174
chat("add_func_desc: %s, idx %#x, dispid %#x\n", func->name, idx, dispid);
1175
1176
old_size = data->size;
1177
1178
init_sltg_data(&ret_data);
1179
ret_desc_offset = write_var_desc(typelib, &ret_data, type_function_get_rettype(func->declspec.type),
1180
0, 0, base_offset, NULL, hrefmap);
1181
dump_var_desc(ret_data.data, ret_data.size);
1182
1183
arg_data_size = 0;
1184
arg_offset = base_offset + sizeof(struct sltg_function);
1185
1186
if (ret_data.size > sizeof(short))
1187
{
1188
arg_data_size += ret_data.size;
1189
arg_offset += ret_data.size;
1190
}
1191
1192
if (type_function_get_args(func->declspec.type))
1193
{
1194
int i = 0;
1195
1196
arg_count = list_count(type_function_get_args(func->declspec.type));
1197
1198
arg_data = xmalloc(arg_count * sizeof(*arg_data));
1199
arg_desc_offset = xmalloc(arg_count * sizeof(*arg_desc_offset));
1200
1201
arg_offset += arg_count * 2 * sizeof(short);
1202
1203
LIST_FOR_EACH_ENTRY(arg, type_function_get_args(func->declspec.type), const var_t, entry)
1204
{
1205
const attr_t *attr;
1206
short param_flags = get_param_flags(arg);
1207
1208
chat("add_func_desc: arg[%d] %p (%s), type %p (%s)\n",
1209
i, arg, arg->name, arg->declspec.type, arg->declspec.type->name);
1210
1211
init_sltg_data(&arg_data[i]);
1212
1213
1214
arg_desc_offset[i] = write_var_desc(typelib, &arg_data[i], arg->declspec.type, param_flags, 0,
1215
arg_offset, NULL, hrefmap);
1216
dump_var_desc(arg_data[i].data, arg_data[i].size);
1217
1218
if (arg_data[i].size > sizeof(short))
1219
{
1220
arg_data_size += arg_data[i].size;
1221
arg_offset += arg_data[i].size;
1222
}
1223
1224
i++;
1225
1226
if (!arg->attrs) continue;
1227
1228
LIST_FOR_EACH_ENTRY(attr, arg->attrs, const attr_t, entry)
1229
{
1230
if (attr->type == ATTR_OPTIONAL)
1231
optional++;
1232
}
1233
}
1234
}
1235
1236
funcflags = get_func_flags(func, &dispid, &invokekind, &helpcontext, &helpstring);
1237
1238
if (base_offset != -1)
1239
chat("add_func_desc: flags %#x, dispid %#x, invokekind %d, helpcontext %#x, helpstring %s\n",
1240
funcflags, dispid, invokekind, helpcontext, helpstring);
1241
1242
func_desc.magic = 0x6c; /* always write flags to simplify calculations */
1243
func_desc.flags = (invokekind << 4) | 0x02;
1244
if (idx & 0x80000000)
1245
{
1246
func_desc.next = -1;
1247
idx &= ~0x80000000;
1248
}
1249
else
1250
func_desc.next = base_offset + sizeof(func_desc) + arg_data_size + arg_count * 2 * sizeof(short);
1251
func_desc.name = base_offset != -1 ? add_name(&typelib->name_table, func->name) : -1;
1252
func_desc.dispid = dispid;
1253
func_desc.helpcontext = helpcontext;
1254
func_desc.helpstring = (helpstring && base_offset != -1) ? add_name(&typelib->name_table, helpstring) : -1;
1255
func_desc.arg_off = arg_count ? base_offset + sizeof(func_desc) : -1;
1256
func_desc.nacc = (arg_count << 3) | 4 /* CC_STDCALL */;
1257
func_desc.retnextopt = (optional << 1);
1258
if (ret_data.size > sizeof(short))
1259
{
1260
func_desc.rettype = base_offset + sizeof(func_desc) + ret_desc_offset;
1261
if (arg_count)
1262
func_desc.arg_off += ret_data.size;
1263
}
1264
else
1265
{
1266
func_desc.retnextopt |= 0x80;
1267
func_desc.rettype = *(short *)ret_data.data;
1268
}
1269
func_desc.vtblpos = idx * pointer_size;
1270
func_desc.funcflags = funcflags;
1271
1272
append_data(data, &func_desc, sizeof(func_desc));
1273
1274
arg_offset = base_offset + sizeof(struct sltg_function);
1275
1276
if (ret_data.size > sizeof(short))
1277
{
1278
append_data(data, ret_data.data, ret_data.size);
1279
func_desc.arg_off += ret_data.size;
1280
arg_offset += ret_data.size;
1281
}
1282
1283
if (arg_count)
1284
{
1285
int i = 0;
1286
1287
arg_offset += arg_count * 2 * sizeof(short);
1288
1289
LIST_FOR_EACH_ENTRY(arg, type_function_get_args(func->declspec.type), const var_t, entry)
1290
{
1291
short name, type_offset;
1292
1293
name = base_offset != -1 ? add_name(&typelib->name_table, arg->name) : -1;
1294
1295
if (arg_data[i].size > sizeof(short))
1296
{
1297
type_offset = (arg_offset + arg_desc_offset[i]);
1298
arg_offset += arg_data[i].size;
1299
}
1300
else
1301
{
1302
name |= 1;
1303
type_offset = *(short *)arg_data[i].data;
1304
}
1305
1306
append_data(data, &name, sizeof(name));
1307
append_data(data, &type_offset, sizeof(type_offset));
1308
1309
if (base_offset != -1)
1310
chat("add_func_desc: arg[%d] - name %s (%#x), type_offset %#x\n",
1311
i, arg->name, name, type_offset);
1312
1313
i++;
1314
}
1315
1316
for (i = 0; i < arg_count; i++)
1317
{
1318
if (arg_data[i].size > sizeof(short))
1319
append_data(data, arg_data[i].data, arg_data[i].size);
1320
}
1321
}
1322
1323
return data->size - old_size;
1324
}
1325
1326
static void write_impl_href(struct sltg_data *data, short href)
1327
{
1328
struct sltg_impl_info impl_info;
1329
1330
impl_info.res00 = 0x004a;
1331
impl_info.next = -1;
1332
impl_info.res04 = -1;
1333
impl_info.impltypeflags = 0;
1334
impl_info.res07 = 0x80;
1335
impl_info.res08 = 0x0012;
1336
impl_info.ref = href;
1337
impl_info.res0c = 0x4001;
1338
impl_info.res0e = -2; /* 0xfffe */
1339
impl_info.res10 = -1;
1340
impl_info.res12 = 0x001d;
1341
impl_info.pos = 0;
1342
1343
append_data(data, &impl_info, sizeof(impl_info));
1344
}
1345
1346
static void add_interface_typeinfo(struct sltg_typelib *typelib, type_t *iface)
1347
{
1348
const statement_t *stmt_func;
1349
importinfo_t *ref_importinfo = NULL;
1350
short inherit_href = -1;
1351
struct sltg_data data;
1352
struct sltg_hrefmap hrefmap;
1353
const char *index_name;
1354
struct sltg_typeinfo_header ti;
1355
struct sltg_member_header member;
1356
struct sltg_tail tail;
1357
int member_offset, base_offset, func_data_size, i;
1358
int func_count, inherited_func_count = 0;
1359
int dispid, inherit_level = 0;
1360
1361
if (iface->typelib_idx != -1) return;
1362
1363
chat("add_interface_typeinfo: type %p, type->name %s\n", iface, iface->name);
1364
1365
if (!iface->details.iface)
1366
{
1367
error("interface %s is referenced but not defined\n", iface->name);
1368
return;
1369
}
1370
1371
if (is_attr(iface->attrs, ATTR_DISPINTERFACE))
1372
{
1373
error("support for dispinterface %s is not implemented\n", iface->name);
1374
return;
1375
}
1376
1377
hrefmap.href_count = 0;
1378
hrefmap.href = NULL;
1379
1380
if (type_iface_get_inherit(iface))
1381
{
1382
type_t *inherit;
1383
1384
inherit = type_iface_get_inherit(iface);
1385
1386
chat("add_interface_typeinfo: inheriting from base interface %s\n", inherit->name);
1387
1388
ref_importinfo = find_importinfo(typelib->typelib, inherit->name);
1389
1390
if (!ref_importinfo && type_iface_get_inherit(inherit))
1391
add_interface_typeinfo(typelib, inherit);
1392
1393
if (ref_importinfo)
1394
error("support for imported interfaces is not implemented\n");
1395
1396
inherit_href = local_href(&hrefmap, inherit->typelib_idx);
1397
1398
while (inherit)
1399
{
1400
inherit_level++;
1401
inherited_func_count += list_count(type_iface_get_stmts(inherit));
1402
inherit = type_iface_get_inherit(inherit);
1403
}
1404
}
1405
1406
/* check typelib_idx again, it could have been added while resolving the parent interface */
1407
if (iface->typelib_idx != -1) return;
1408
1409
iface->typelib_idx = typelib->block_count;
1410
1411
/* pass 1: calculate function descriptions data size */
1412
init_sltg_data(&data);
1413
1414
STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(iface))
1415
{
1416
add_func_desc(typelib, &data, stmt_func->u.var, -1, -1, -1, &hrefmap);
1417
}
1418
1419
func_data_size = data.size;
1420
1421
/* pass 2: write function descriptions */
1422
init_sltg_data(&data);
1423
1424
func_count = list_count(type_iface_get_stmts(iface));
1425
1426
index_name = add_typeinfo_block(typelib, iface, TKIND_INTERFACE);
1427
1428
init_typeinfo(&ti, iface, TKIND_INTERFACE, &hrefmap);
1429
append_data(&data, &ti, sizeof(ti));
1430
1431
write_hrefmap(&data, &hrefmap);
1432
1433
member_offset = data.size;
1434
base_offset = 0;
1435
1436
member.res00 = 0x0001;
1437
member.res02 = 0xffff;
1438
member.res04 = 0x01;
1439
member.extra = func_data_size;
1440
if (inherit_href != -1)
1441
{
1442
member.extra += sizeof(struct sltg_impl_info);
1443
base_offset += sizeof(struct sltg_impl_info);
1444
}
1445
append_data(&data, &member, sizeof(member));
1446
1447
if (inherit_href != -1)
1448
write_impl_href(&data, inherit_href);
1449
1450
i = 0;
1451
dispid = 0x60000000 | (inherit_level << 16);
1452
1453
STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(iface))
1454
{
1455
int idx = inherited_func_count + i;
1456
1457
if (i == func_count - 1) idx |= 0x80000000;
1458
1459
base_offset += add_func_desc(typelib, &data, stmt_func->u.var,
1460
idx, dispid + i, base_offset, &hrefmap);
1461
i++;
1462
}
1463
1464
init_sltg_tail(&tail);
1465
1466
tail.cFuncs = func_count;
1467
tail.funcs_off = 0;
1468
tail.funcs_bytes = func_data_size;
1469
tail.cbSizeInstance = pointer_size;
1470
tail.cbAlignment = pointer_size;
1471
tail.cbSizeVft = (inherited_func_count + func_count) * pointer_size;
1472
tail.type_bytes = data.size - member_offset - sizeof(member);
1473
tail.res24 = 0;
1474
tail.res26 = 0;
1475
if (inherit_href != -1)
1476
{
1477
tail.cImplTypes++;
1478
tail.impls_off = 0;
1479
tail.impls_bytes = 0;
1480
1481
tail.funcs_off += sizeof(struct sltg_impl_info);
1482
}
1483
append_data(&data, &tail, sizeof(tail));
1484
1485
add_block(typelib, data.data, data.size, index_name);
1486
}
1487
1488
static void add_enum_typeinfo(struct sltg_typelib *typelib, type_t *type)
1489
{
1490
error("add_enum_typeinfo: %s not implemented\n", type->name);
1491
}
1492
1493
static void add_union_typeinfo(struct sltg_typelib *typelib, type_t *type)
1494
{
1495
error("add_union_typeinfo: %s not implemented\n", type->name);
1496
}
1497
1498
static void add_coclass_typeinfo(struct sltg_typelib *typelib, type_t *type)
1499
{
1500
error("add_coclass_typeinfo: %s not implemented\n", type->name);
1501
}
1502
1503
static void add_type_typeinfo(struct sltg_typelib *typelib, type_t *type)
1504
{
1505
chat("add_type_typeinfo: adding %s, type %d\n", type->name, type_get_type(type));
1506
1507
switch (type_get_type(type))
1508
{
1509
case TYPE_INTERFACE:
1510
add_interface_typeinfo(typelib, type);
1511
break;
1512
case TYPE_STRUCT:
1513
add_structure_typeinfo(typelib, type);
1514
break;
1515
case TYPE_ENUM:
1516
add_enum_typeinfo(typelib, type);
1517
break;
1518
case TYPE_UNION:
1519
add_union_typeinfo(typelib, type);
1520
break;
1521
case TYPE_COCLASS:
1522
add_coclass_typeinfo(typelib, type);
1523
break;
1524
case TYPE_BASIC:
1525
case TYPE_POINTER:
1526
break;
1527
default:
1528
error("add_type_typeinfo: unhandled type %d for %s\n", type_get_type(type), type->name);
1529
break;
1530
}
1531
}
1532
1533
static void add_statement(struct sltg_typelib *typelib, const statement_t *stmt)
1534
{
1535
switch(stmt->type)
1536
{
1537
case STMT_LIBRARY:
1538
case STMT_IMPORT:
1539
case STMT_PRAGMA:
1540
case STMT_CPPQUOTE:
1541
case STMT_DECLARATION:
1542
/* not included in typelib */
1543
break;
1544
case STMT_IMPORTLIB:
1545
/* not processed here */
1546
break;
1547
1548
case STMT_TYPEDEF:
1549
{
1550
typeref_t *ref;
1551
1552
if (!stmt->u.type_list)
1553
break;
1554
1555
LIST_FOR_EACH_ENTRY(ref, stmt->u.type_list, typeref_t, entry)
1556
{
1557
/* in old style typelibs all types are public */
1558
add_type_typeinfo(typelib, ref->type);
1559
}
1560
break;
1561
}
1562
1563
case STMT_MODULE:
1564
add_module_typeinfo(typelib, stmt->u.type);
1565
break;
1566
1567
case STMT_TYPE:
1568
case STMT_TYPEREF:
1569
{
1570
type_t *type = stmt->u.type;
1571
add_type_typeinfo(typelib, type);
1572
break;
1573
}
1574
1575
default:
1576
error("add_statement: unhandled statement type %d\n", stmt->type);
1577
break;
1578
}
1579
}
1580
1581
static void sltg_write_header(struct sltg_typelib *sltg, int *library_block_start)
1582
{
1583
char pad[0x40];
1584
struct sltg_header
1585
{
1586
int magic;
1587
short block_count;
1588
short res06;
1589
short size_of_index;
1590
short first_blk;
1591
GUID uuid;
1592
int res1c;
1593
int res20;
1594
} header;
1595
struct sltg_block_entry
1596
{
1597
int length;
1598
short index_string;
1599
short next;
1600
} entry;
1601
int i;
1602
1603
header.magic = 0x47544c53;
1604
header.block_count = sltg->block_count + 1; /* 1-based */
1605
header.res06 = 9;
1606
header.size_of_index = sltg->index.size;
1607
header.first_blk = 1; /* 1-based */
1608
header.uuid = sltg_library_guid;
1609
header.res1c = 0x00000044;
1610
header.res20 = 0xffff0000;
1611
1612
put_data(&header, sizeof(header));
1613
1614
/* library block is written separately */
1615
for (i = 0; i < sltg->block_count - 1; i++)
1616
{
1617
entry.length = sltg->blocks[i].length;
1618
entry.index_string = sltg->blocks[i].index_string;
1619
entry.next = header.first_blk + i + 1; /* point to next block */
1620
chat("sltg_write_header: writing block entry %d: length %#x, index_string %#x, next %#x\n",
1621
i, entry.length, entry.index_string, entry.next);
1622
put_data(&entry, sizeof(entry));
1623
}
1624
1625
/* library block length includes helpstrings and name table */
1626
entry.length = sltg->blocks[sltg->block_count - 1].length + 0x40 /* pad after library block */ +
1627
sizeof(sltg->typeinfo_count) + sltg->typeinfo_size + 4 /* library block size */ + 6 /* dummy help strings */ +
1628
12 /* name table header */ + 0x200 /* name table hash */ +
1629
sizeof(sltg->name_table.size) + sltg->name_table.size +
1630
4 /* 0x01ffff01 */ + 4 /* 0 */;
1631
entry.index_string = sltg->blocks[sltg->block_count - 1].index_string;
1632
entry.next = 0;
1633
chat("sltg_write_header: writing library block entry %d: length %#x, index_string %#x, next %#x\n",
1634
i, entry.length, entry.index_string, entry.next);
1635
put_data(&entry, sizeof(entry));
1636
1637
chat("sltg_write_header: writing index: %d bytes\n", sltg->index.size);
1638
put_data(sltg->index.data, sltg->index.size);
1639
memset(pad, 0, 9);
1640
put_data(pad, 9);
1641
1642
/* library block is written separately */
1643
for (i = 0; i < sltg->block_count - 1; i++)
1644
{
1645
chat("sltg_write_header: writing block %d: %d bytes\n", i, sltg->blocks[i].length);
1646
put_data(sltg->blocks[i].data, sltg->blocks[i].length);
1647
}
1648
1649
/* library block */
1650
chat("library_block_start = %#x\n", (int)output_buffer_pos);
1651
*library_block_start = output_buffer_pos;
1652
chat("sltg_write_header: writing library block %d: %d bytes\n", i, sltg->blocks[i].length);
1653
put_data(sltg->blocks[sltg->block_count - 1].data, sltg->blocks[sltg->block_count - 1].length);
1654
1655
chat("sltg_write_header: writing pad 0x40 bytes\n");
1656
memset(pad, 0xff, 0x40);
1657
put_data(pad, 0x40);
1658
}
1659
1660
static void sltg_write_typeinfo(struct sltg_typelib *typelib)
1661
{
1662
short i;
1663
1664
put_data(&typelib->typeinfo_count, sizeof(typelib->typeinfo_count));
1665
1666
for (i = 0; i < typelib->typeinfo_count; i++)
1667
{
1668
chat("sltg_write_typeinfo: writing block %d: %d bytes\n", i, typelib->typeinfo[i].length);
1669
put_data(typelib->typeinfo[i].data, typelib->typeinfo[i].length);
1670
}
1671
}
1672
1673
static void sltg_write_helpstrings(struct sltg_typelib *typelib)
1674
{
1675
static const char dummy[6];
1676
1677
chat("sltg_write_helpstrings: writing dummy 6 bytes\n");
1678
1679
put_data(dummy, sizeof(dummy));
1680
}
1681
1682
static void sltg_write_nametable(struct sltg_typelib *typelib)
1683
{
1684
static const short dummy[6] = { 0xffff,1,2,0xff00,0xffff,0xffff };
1685
char pad[0x200];
1686
1687
chat("sltg_write_nametable: writing 12+0x200+%d bytes\n", typelib->name_table.size);
1688
1689
put_data(dummy, sizeof(dummy));
1690
memset(pad, 0xff, 0x200);
1691
put_data(pad, 0x200);
1692
put_data(&typelib->name_table.size, sizeof(typelib->name_table.size));
1693
put_data(typelib->name_table.data, typelib->name_table.size);
1694
}
1695
1696
static void sltg_write_remainder(void)
1697
{
1698
static const short dummy1[] = { 1,0xfffe,0x0a03,0,0xffff,0xffff };
1699
static const short dummy2[] = { 0xffff,0xffff,0x0200,0,0,0 };
1700
static const char dummy3[] = { 0xf4,0x39,0xb2,0x71,0,0,0,0,0,0,0,0,0,0,0,0 };
1701
static const char TYPELIB[] = { 8,0,0,0,'T','Y','P','E','L','I','B',0 };
1702
int pad;
1703
1704
pad = 0x01ffff01;
1705
put_data(&pad, sizeof(pad));
1706
pad = 0;
1707
put_data(&pad, sizeof(pad));
1708
1709
put_data(dummy1, sizeof(dummy1));
1710
1711
put_data(&sltg_library_guid, sizeof(sltg_library_guid));
1712
1713
put_data(TYPELIB, sizeof(TYPELIB));
1714
1715
put_data(dummy2, sizeof(dummy2));
1716
put_data(dummy3, sizeof(dummy3));
1717
}
1718
1719
static void save_all_changes(struct sltg_typelib *typelib)
1720
{
1721
int library_block_start;
1722
int *name_table_offset;
1723
1724
sltg_write_header(typelib, &library_block_start);
1725
sltg_write_typeinfo(typelib);
1726
1727
name_table_offset = (int *)(output_buffer + output_buffer_pos);
1728
chat("name_table_offset = %#x\n", (int)output_buffer_pos);
1729
put_data(&library_block_start, sizeof(library_block_start));
1730
1731
sltg_write_helpstrings(typelib);
1732
1733
*name_table_offset = output_buffer_pos - library_block_start;
1734
chat("*name_table_offset = %#x\n", *name_table_offset);
1735
1736
sltg_write_nametable(typelib);
1737
sltg_write_remainder();
1738
1739
if (strendswith(typelib_name, ".res")) /* create a binary resource file */
1740
{
1741
char typelib_id[13] = "#1";
1742
1743
expr_t *expr = get_attrp(typelib->typelib->attrs, ATTR_ID);
1744
if (expr)
1745
snprintf(typelib_id, sizeof(typelib_id), "#%d", expr->cval);
1746
add_output_to_resources("TYPELIB", typelib_id);
1747
if (strendswith(typelib_name, "_t.res")) /* add typelib registration */
1748
output_typelib_regscript(typelib->typelib);
1749
}
1750
else flush_output_buffer(typelib_name);
1751
}
1752
1753
int create_sltg_typelib(typelib_t *typelib)
1754
{
1755
struct sltg_typelib sltg;
1756
const statement_t *stmt;
1757
void *library_block;
1758
int library_block_size, library_block_index;
1759
1760
if (pointer_size != 4)
1761
error("Only 32-bit platform is supported\n");
1762
1763
sltg.typelib = typelib;
1764
sltg.typeinfo_count = 0;
1765
sltg.typeinfo_size = 0;
1766
sltg.typeinfo = NULL;
1767
sltg.blocks = NULL;
1768
sltg.block_count = 0;
1769
sltg.first_block = 1;
1770
1771
init_index(&sltg.index);
1772
init_name_table(&sltg.name_table);
1773
init_library(&sltg);
1774
1775
library_block = create_library_block(&sltg, &library_block_size, &library_block_index);
1776
1777
if (typelib->stmts)
1778
LIST_FOR_EACH_ENTRY(stmt, typelib->stmts, const statement_t, entry)
1779
add_statement(&sltg, stmt);
1780
1781
add_block_index(&sltg, library_block, library_block_size, library_block_index);
1782
1783
save_all_changes(&sltg);
1784
1785
return 1;
1786
}
1787
1788