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