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