widl: Add support for interfaces to SLTG typelib generator.
[wine.git] / tools / widl / write_sltg.c
blobec233a119f3cef8e1496250958203b29e90d15b3
1 /*
2 * Typelib (SLTG) generation
4 * Copyright 2015,2016 Dmitry Timoshkov
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.
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.
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
21 #include "config.h"
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <ctype.h>
28 #include <time.h>
30 #include "widl.h"
31 #include "windef.h"
32 #include "winbase.h"
34 #include "typelib.h"
35 #include "typelib_struct.h"
36 #include "utils.h"
37 #include "header.h"
38 #include "typetree.h"
40 static const GUID sltg_library_guid = { 0x204ff,0,0,{ 0xc0,0,0,0,0,0,0,0x46 } };
42 struct sltg_data
44 int size, allocated;
45 char *data;
48 struct sltg_library
50 short name;
51 char *helpstring;
52 char *helpfile;
53 int helpcontext;
54 int syskind;
55 LCID lcid;
56 int libflags;
57 int version;
58 GUID uuid;
61 struct sltg_block
63 int length;
64 int index_string;
65 void *data;
68 struct sltg_typelib
70 typelib_t *typelib;
71 struct sltg_data index;
72 struct sltg_data name_table;
73 struct sltg_library library;
74 struct sltg_block *blocks;
75 int block_count;
76 int first_block;
77 short typeinfo_count;
78 int typeinfo_size;
79 struct sltg_block *typeinfo;
82 struct sltg_hrefmap
84 int href_count;
85 int *href;
88 #include "pshpack1.h"
89 struct sltg_typeinfo_header
91 short magic;
92 int href_offset;
93 int res06;
94 int member_offset;
95 int res0e;
96 int version;
97 int res16;
98 struct
100 unsigned unknown1 : 3;
101 unsigned flags : 13;
102 unsigned unknown2 : 8;
103 unsigned typekind : 8;
104 } misc;
105 int res1e;
108 struct sltg_member_header
110 short res00;
111 short res02;
112 char res04;
113 int extra;
116 struct sltg_variable
118 char magic; /* 0x0a */
119 char flags;
120 short next;
121 short name;
122 short byte_offs; /* pos in struct, or offset to const type or const data (if flags & 0x08) */
123 short type; /* if flags & 0x02 this is the type, else offset to type */
124 int memid;
125 short helpcontext;
126 short helpstring;
127 short varflags; /* only present if magic & 0x20 */
130 struct sltg_tail
132 short cFuncs;
133 short cVars;
134 short cImplTypes;
135 short res06; /* always 0000 */
136 short funcs_off; /* offset to functions (starting from the member header) */
137 short vars_off; /* offset to vars (starting from the member header) */
138 short impls_off; /* offset to implemented types (starting from the member header) */
139 short funcs_bytes; /* bytes used by function data */
140 short vars_bytes; /* bytes used by var data */
141 short impls_bytes; /* bytes used by implemented type data */
142 short tdescalias_vt; /* for TKIND_ALIAS */
143 short res16; /* always ffff */
144 short res18; /* always 0000 */
145 short res1a; /* always 0000 */
146 short simple_alias; /* tdescalias_vt is a vt rather than an offset? */
147 short res1e; /* always 0000 */
148 short cbSizeInstance;
149 short cbAlignment;
150 short res24;
151 short res26;
152 short cbSizeVft;
153 short res2a; /* always ffff */
154 short res2c; /* always ffff */
155 short res2e; /* always ffff */
156 short res30; /* always ffff */
157 short res32; /* unknown */
158 short type_bytes; /* bytes used by type descriptions */
161 struct sltg_hrefinfo
163 char magic; /* 0xdf */
164 char res01; /* 0x00 */
165 char res02[0x42]; /* 0xff... */
166 int number; /* this is 8 times the number of refs */
167 /* Now we have number bytes (8 for each ref) of SLTG_UnknownRefInfo */
169 short res50;/* 0xffff */
170 char res52; /* 0x01 */
171 int res53; /* 0x00000000 */
172 /* Now we have number/8 SLTG_Names (first WORD is no of bytes in the ascii
173 * string). Strings look like "*\Rxxxx*#n". If xxxx == ffff then the
174 * ref refers to the nth type listed in this library (0 based). Else
175 * the xxxx (which maybe fewer than 4 digits) is the offset into the name
176 * table to a string "*\G{<guid>}#1.0#0#C:\WINNT\System32\stdole32.tlb#"
177 * The guid is the typelib guid; the ref again refers to the nth type of
178 * the imported typelib.
181 char resxx; /* 0xdf */
184 struct sltg_function
186 char magic; /* 0x4c, 0xcb or 0x8b with optional SLTG_FUNCTION_FLAGS_PRESENT flag */
187 char flags; /* high nibble is INVOKE_KIND, low nibble = 2 */
188 short next; /* byte offset from beginning of group to next fn */
189 short name; /* Offset within name table to name */
190 int dispid; /* dispid */
191 short helpcontext; /* helpcontext (again 1 is special) */
192 short helpstring; /* helpstring offset to offset */
193 short arg_off; /* offset to args from start of block */
194 char nacc; /* lowest 3bits are CALLCONV, rest are no of args */
195 char retnextopt; /* if 0x80 bit set ret type follows else next WORD
196 is offset to ret type. No of optional args is
197 middle 6 bits */
198 short rettype; /* return type VT_?? or offset to ret type */
199 short vtblpos; /* position in vtbl? */
200 short funcflags; /* present if magic & 0x20 */
201 /* Param list starts, repeat next two as required */
202 #if 0
203 WORD name; /* offset to 2nd letter of name */
204 WORD+ type; /* VT_ of param */
205 #endif
208 #include "poppack.h"
210 static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type);
211 static void add_interface_typeinfo(struct sltg_typelib *typelib, type_t *type);
212 static void add_enum_typeinfo(struct sltg_typelib *typelib, type_t *type);
213 static void add_union_typeinfo(struct sltg_typelib *typelib, type_t *type);
214 static void add_coclass_typeinfo(struct sltg_typelib *typelib, type_t *type);
216 static void init_sltg_data(struct sltg_data *data)
218 data->size = 0;
219 data->allocated = 0;
220 data->data = NULL;
223 static int add_index(struct sltg_data *index, const char *name)
225 int name_offset = index->size;
226 int new_size = index->size + strlen(name) + 1;
228 chat("add_index: name_offset %d, \"%s\"\n", name_offset, name);
230 if (new_size > index->allocated)
232 index->allocated = index->allocated ? max(index->allocated * 2, new_size) : new_size;
233 index->data = xrealloc(index->data, index->allocated);
236 strcpy(index->data + index->size, name);
237 index->size = new_size;
239 return name_offset;
242 static void init_index(struct sltg_data *index)
244 static const char compobj[] = { 1,'C','o','m','p','O','b','j',0 };
246 init_sltg_data(index);
248 add_index(index, compobj);
251 static int add_name(struct sltg_data *name_table, const char *name)
253 int name_offset = name_table->size;
254 int new_size = name_table->size + strlen(name) + 1 + 8;
255 int aligned_size;
257 chat("add_name: %s\n", name);
259 aligned_size = (new_size + 0x1f) & ~0x1f;
260 if (aligned_size - new_size < 4)
261 new_size = aligned_size;
262 else
263 new_size = (new_size + 1) & ~1;
265 if (new_size > name_table->allocated)
267 name_table->allocated = name_table->allocated ? max(name_table->allocated * 2, new_size) : new_size;
268 name_table->data = xrealloc(name_table->data, name_table->allocated);
271 memset(name_table->data + name_table->size, 0xff, 8);
272 strcpy(name_table->data + name_table->size + 8, name);
273 name_table->size = new_size;
274 name_table->data[name_table->size - 1] = 0; /* clear alignment */
276 return name_offset;
279 static void init_name_table(struct sltg_data *name_table)
281 init_sltg_data(name_table);
284 static void init_library(struct sltg_typelib *sltg)
286 const attr_t *attr;
288 sltg->library.name = add_name(&sltg->name_table, sltg->typelib->name);
289 sltg->library.helpstring = NULL;
290 sltg->library.helpcontext = 0;
291 sltg->library.syskind = SYS_WIN32;
292 sltg->library.lcid = 0x0409;
293 sltg->library.libflags = 0;
294 sltg->library.version = 0;
295 sltg->library.helpfile = NULL;
296 memset(&sltg->library.uuid, 0, sizeof(sltg->library.uuid));
298 if (!sltg->typelib->attrs) return;
300 LIST_FOR_EACH_ENTRY(attr, sltg->typelib->attrs, const attr_t, entry)
302 const expr_t *expr;
304 switch (attr->type)
306 case ATTR_VERSION:
307 sltg->library.version = attr->u.ival;
308 break;
309 case ATTR_HELPSTRING:
310 sltg->library.helpstring = attr->u.pval;
311 break;
312 case ATTR_HELPFILE:
313 sltg->library.helpfile = attr->u.pval;
314 break;
315 case ATTR_UUID:
316 sltg->library.uuid = *(GUID *)attr->u.pval;
317 break;
318 case ATTR_HELPCONTEXT:
319 expr = attr->u.pval;
320 sltg->library.helpcontext = expr->cval;
321 break;
322 case ATTR_LIBLCID:
323 expr = attr->u.pval;
324 sltg->library.lcid = expr->cval;
325 break;
326 case ATTR_CONTROL:
327 sltg->library.libflags |= 0x02; /* LIBFLAG_FCONTROL */
328 break;
329 case ATTR_HIDDEN:
330 sltg->library.libflags |= 0x04; /* LIBFLAG_FHIDDEN */
331 break;
332 case ATTR_RESTRICTED:
333 sltg->library.libflags |= 0x01; /* LIBFLAG_FRESTRICTED */
334 break;
335 default:
336 break;
341 static void add_block(struct sltg_typelib *sltg, void *data, int length, const char *name)
343 chat("add_block: %p,%d,\"%s\"\n", data, length, name);
345 sltg->blocks = xrealloc(sltg->blocks, sizeof(sltg->blocks[0]) * (sltg->block_count + 1));
346 sltg->blocks[sltg->block_count].length = length;
347 sltg->blocks[sltg->block_count].data = data;
348 sltg->blocks[sltg->block_count].index_string = add_index(&sltg->index, name);
349 sltg->block_count++;
352 static void add_library_block(struct sltg_typelib *typelib)
354 void *block;
355 short *p;
356 int size;
358 size = sizeof(short) * 9 + sizeof(int) * 3 + sizeof(GUID);
359 if (typelib->library.helpstring) size += strlen(typelib->library.helpstring);
360 if (typelib->library.helpfile) size += strlen(typelib->library.helpfile);
362 block = xmalloc(size);
363 p = block;
364 *p++ = 0x51cc; /* magic */
365 *p++ = 3; /* res02 */
366 *p++ = typelib->library.name;
367 *p++ = 0xffff; /* res06 */
368 if (typelib->library.helpstring)
370 *p++ = strlen(typelib->library.helpstring);
371 strcpy((char *)p, typelib->library.helpstring);
372 p = (short *)((char *)p + strlen(typelib->library.helpstring));
374 else
375 *p++ = 0xffff;
376 if (typelib->library.helpfile)
378 *p++ = strlen(typelib->library.helpfile);
379 strcpy((char *)p, typelib->library.helpfile);
380 p = (short *)((char *)p + strlen(typelib->library.helpfile));
382 else
383 *p++ = 0xffff;
384 *(int *)p = typelib->library.helpcontext;
385 p += 2;
386 *p++ = typelib->library.syskind;
387 *p++ = typelib->library.lcid;
388 *(int *)p = 0; /* res12 */
389 p += 2;
390 *p++ = typelib->library.libflags;
391 *(int *)p = typelib->library.version;
392 p += 2;
393 *(GUID *)p = typelib->library.uuid;
395 add_block(typelib, block, size, "dir");
398 static const char *new_index_name(void)
400 static char name[11] = "AAAAAAAAAA";
401 static int pos = 0;
402 char *new_name;
404 if (name[pos] == 'Z')
406 pos++;
407 if (pos > 9)
408 error("too many index names\n");
411 name[pos]++;
413 new_name = xmalloc(sizeof(name));
414 strcpy(new_name, name);
415 return new_name;
418 static void sltg_add_typeinfo(struct sltg_typelib *sltg, void *data, int length, const char *name)
420 chat("sltg_add_typeinfo: %p,%d,%s\n", data, length, name);
422 sltg->typeinfo = xrealloc(sltg->typeinfo, sizeof(sltg->typeinfo[0]) * (sltg->typeinfo_count + 1));
423 sltg->typeinfo[sltg->typeinfo_count].length = length;
424 sltg->typeinfo[sltg->typeinfo_count].data = data;
425 sltg->typeinfo[sltg->typeinfo_count].index_string = 0;
426 sltg->typeinfo_count++;
427 sltg->typeinfo_size += length;
430 static void append_data(struct sltg_data *block, const void *data, int size)
432 int new_size = block->size + size;
434 if (new_size > block->allocated)
436 block->allocated = max(block->allocated * 2, new_size);
437 block->data = xrealloc(block->data, block->allocated);
440 memcpy(block->data + block->size, data, size);
441 block->size = new_size;
444 static void add_module_typeinfo(struct sltg_typelib *typelib, type_t *type)
446 error("add_module_typeinfo: %s not implemented\n", type->name);
449 static const char *add_typeinfo_block(struct sltg_typelib *typelib, const type_t *type, short kind)
451 struct sltg_data block;
452 const char *index_name, *other_name;
453 short val;
454 void *p;
455 int helpcontext = 0;
456 GUID guid = { 0 };
457 const expr_t *expr;
459 index_name = new_index_name();
460 other_name = new_index_name();
462 expr = get_attrp(type->attrs, ATTR_HELPCONTEXT);
463 if (expr) helpcontext = expr->cval;
465 p = get_attrp(type->attrs, ATTR_UUID);
466 if (p) guid = *(GUID *)p;
468 init_sltg_data(&block);
470 val = strlen(index_name);
471 append_data(&block, &val, sizeof(val));
472 append_data(&block, index_name, val);
473 val = strlen(other_name);
474 append_data(&block, &val, sizeof(val));
475 append_data(&block, other_name, val);
476 val = -1; /* res1a */
477 append_data(&block, &val, sizeof(val));
478 val = add_name(&typelib->name_table, type->name); /* name offset */
479 append_data(&block, &val, sizeof(val));
480 val = 0; /* FIXME: helpstring */
481 append_data(&block, &val, sizeof(val));
482 val = -1; /* res20 */
483 append_data(&block, &val, sizeof(val));
484 append_data(&block, &helpcontext, sizeof(helpcontext));
485 val = -1; /* res26 */
486 append_data(&block, &val, sizeof(val));
487 append_data(&block, &guid, sizeof(guid));
488 append_data(&block, &kind, sizeof(kind));
490 sltg_add_typeinfo(typelib, block.data, block.size, index_name);
492 return index_name;
495 static void init_typeinfo(struct sltg_typeinfo_header *ti, const type_t *type, short kind,
496 const struct sltg_hrefmap *hrefmap)
498 ti->magic = 0x0501;
499 ti->href_offset = -1;
500 ti->res06 = -1;
501 ti->member_offset = sizeof(*ti);
502 ti->res0e = -1;
503 ti->version = get_attrv(type->attrs, ATTR_VERSION);
504 ti->res16 = 0xfffe0000;
505 ti->misc.unknown1 = 0x02;
506 ti->misc.flags = 0; /* FIXME */
507 ti->misc.unknown2 = 0x02;
508 ti->misc.typekind = kind;
509 ti->res1e = 0;
511 if (hrefmap->href_count)
513 char name[64];
514 int i, hrefinfo_size;
516 hrefinfo_size = sizeof(struct sltg_hrefinfo);
518 for (i = 0; i < hrefmap->href_count; i++)
520 sprintf(name, "*\\Rffff*#%x", hrefmap->href[i]);
521 hrefinfo_size += 8 + 2 + strlen(name);
524 ti->href_offset = ti->member_offset;
525 ti->member_offset += hrefinfo_size;
529 static void write_hrefmap(struct sltg_data *data, const struct sltg_hrefmap *hrefmap)
531 struct sltg_hrefinfo hrefinfo;
532 char name[64];
533 int i;
535 if (!hrefmap->href_count) return;
537 hrefinfo.magic = 0xdf;
538 hrefinfo.res01 = 0;
539 memset(hrefinfo.res02, 0xff, sizeof(hrefinfo.res02));
540 hrefinfo.number = hrefmap->href_count * 8;
541 hrefinfo.res50 = -1;
542 hrefinfo.res52 = 1;
543 hrefinfo.res53 = 0;
544 hrefinfo.resxx = 0xdf;
546 append_data(data, &hrefinfo, offsetof(struct sltg_hrefinfo, res50));
548 for (i = 0; i < hrefmap->href_count; i++)
549 append_data(data, "\xff\xff\xff\xff\xff\xff\xff\xff", 8);
551 append_data(data, &hrefinfo.res50, 7);
553 for (i = 0; i < hrefmap->href_count; i++)
555 short len;
557 sprintf(name, "*\\Rffff*#%x", hrefmap->href[i]);
558 len = strlen(name);
560 append_data(data, &len, sizeof(len));
561 append_data(data, name, len);
564 append_data(data, &hrefinfo.resxx, sizeof(hrefinfo.resxx));
567 static void dump_var_desc(const char *data, int size)
569 const unsigned char *p = (const unsigned char *)data;
570 int i;
572 if (!(debuglevel & (DEBUGLEVEL_TRACE | DEBUGLEVEL_CHAT))) return;
574 chat("dump_var_desc: size %d bytes\n", size);
576 for (i = 0; i < size; i++)
577 fprintf(stderr, " %02x", *p++);
579 fprintf(stderr, "\n");
582 static int get_element_size(type_t *type)
584 int vt = get_type_vt(type);
586 switch (vt)
588 case VT_I1:
589 case VT_UI1:
590 return 1;
592 case VT_UI2:
593 case VT_I2:
594 case VT_BOOL:
595 return 2;
597 case VT_INT:
598 case VT_UINT:
599 case VT_I4:
600 case VT_UI4:
601 case VT_R4:
602 case VT_ERROR:
603 case VT_HRESULT:
604 return 4;
606 case VT_R8:
607 case VT_I8:
608 case VT_UI8:
609 case VT_CY:
610 case VT_DATE:
611 return 8;
613 case VT_DECIMAL:
614 return 16;
616 case VT_PTR:
617 case VT_UNKNOWN:
618 case VT_DISPATCH:
619 case VT_BSTR:
620 case VT_LPSTR:
621 case VT_LPWSTR:
622 return 4;
624 case VT_VOID:
625 return 0;
627 case VT_VARIANT:
628 return 16;
630 case VT_USERDEFINED:
631 return 0;
633 default:
634 error("get_element_size: unrecognized vt %d\n", vt);
635 break;
638 return 0;
641 static int local_href(struct sltg_hrefmap *hrefmap, int typelib_href)
643 int i, href = -1;
645 for (i = 0; i < hrefmap->href_count; i++)
647 if (hrefmap->href[i] == typelib_href)
649 href = i;
650 break;
654 if (href == -1)
656 href = hrefmap->href_count;
658 if (hrefmap->href)
659 hrefmap->href = xrealloc(hrefmap->href, sizeof(*hrefmap->href) * (hrefmap->href_count + 1));
660 else
661 hrefmap->href = xmalloc(sizeof(*hrefmap->href));
663 hrefmap->href[hrefmap->href_count] = typelib_href;
664 hrefmap->href_count++;
667 chat("typelib href %d mapped to local href %d\n", typelib_href, href);
669 return href << 2;
672 static short write_var_desc(struct sltg_typelib *typelib, struct sltg_data *data, type_t *type, short flags,
673 short base_offset, int *size_instance, struct sltg_hrefmap *hrefmap)
675 short vt, vt_flags, desc_offset;
677 chat("write_var_desc: type %p, type->name %s\n",
678 type, type->name ? type->name : "NULL");
680 if (is_array(type) && !type_array_is_decl_as_ptr(type))
682 int num_dims, elements, array_start, size, array_size;
683 type_t *atype;
684 struct
686 short cDims;
687 short fFeatures;
688 int cbElements;
689 int cLocks;
690 int pvData;
691 int bound[2];
692 } *array;
693 int *bound;
694 short vt_off[2];
696 elements = 1;
697 num_dims = 0;
699 atype = type;
701 while (is_array(atype) && !type_array_is_decl_as_ptr(atype))
703 num_dims++;
704 elements *= type_array_get_dim(atype);
706 atype = type_array_get_element_type(atype);
709 chat("write_var_desc: VT_CARRAY: %d dimensions, %d elements\n", num_dims, elements);
711 array_start = data->size;
713 size = sizeof(*array) + (num_dims - 1) * 8 /* sizeof(SAFEARRAYBOUND) */;
714 array = xmalloc(size);
716 array->cDims = num_dims;
717 array->fFeatures = 0x0004; /* FADF_EMBEDDED */
718 array->cbElements = get_element_size(atype);
719 array->cLocks = 0;
720 array->pvData = 0;
722 bound = array->bound;
724 array_size = array->cbElements;
725 atype = type;
727 while (is_array(atype) && !type_array_is_decl_as_ptr(atype))
729 bound[0] = type_array_get_dim(atype);
730 array_size *= bound[0];
731 bound[1] = 0;
732 bound += 2;
734 atype = type_array_get_element_type(atype);
737 if (size_instance)
739 *size_instance += array_size;
740 size_instance = NULL; /* don't account for element size */
744 append_data(data, array, size);
746 desc_offset = data->size;
748 vt_off[0] = VT_CARRAY;
749 vt_off[1] = array_start + base_offset;
750 append_data(data, vt_off, sizeof(vt_off));
752 /* fall through to write array element description */
753 type = atype;
755 else
756 desc_offset = data->size;
758 vt = get_type_vt(type);
760 if (vt == VT_PTR)
762 type_t *ref = is_ptr(type) ? type_pointer_get_ref_type(type) : type_array_get_element_type(type);
764 if (is_ptr(ref))
766 chat("write_var_desc: vt VT_PTR | 0x0400\n");
767 vt = VT_PTR | 0x0400;
768 append_data(data, &vt, sizeof(vt));
769 write_var_desc(typelib, data, ref, 0, base_offset, size_instance, hrefmap);
771 else
772 write_var_desc(typelib, data, ref, 0x0e00, base_offset, size_instance, hrefmap);
773 return desc_offset;
776 chat("write_var_desc: vt %d, flags %04x\n", vt, flags);
778 vt_flags = vt | flags;
779 append_data(data, &vt_flags, sizeof(vt_flags));
781 if (vt == VT_USERDEFINED)
783 short href;
785 while (type->typelib_idx < 0 && type_is_alias(type))
786 type = type_alias_get_aliasee_type(type);
788 chat("write_var_desc: VT_USERDEFINED, type %p, name %s, real type %d, href %d\n",
789 type, type->name, type_get_type(type), type->typelib_idx);
791 if (type->typelib_idx == -1)
793 chat("write_var_desc: trying to ref not added type\n");
795 switch (type_get_type(type))
797 case TYPE_STRUCT:
798 add_structure_typeinfo(typelib, type);
799 break;
800 case TYPE_INTERFACE:
801 add_interface_typeinfo(typelib, type);
802 break;
803 case TYPE_ENUM:
804 add_enum_typeinfo(typelib, type);
805 break;
806 case TYPE_UNION:
807 add_union_typeinfo(typelib, type);
808 break;
809 case TYPE_COCLASS:
810 add_coclass_typeinfo(typelib, type);
811 break;
812 default:
813 error("write_var_desc: VT_USERDEFINED - unhandled type %d\n",
814 type_get_type(type));
818 if (type->typelib_idx == -1)
819 error("write_var_desc: trying to ref not added type\n");
821 href = local_href(hrefmap, type->typelib_idx);
822 chat("write_var_desc: VT_USERDEFINED, local href %d\n", href);
824 append_data(data, &href, sizeof(href));
827 if (size_instance)
828 *size_instance += get_element_size(type);
830 return desc_offset;
833 static void init_sltg_tail(struct sltg_tail *tail)
835 tail->cFuncs = 0;
836 tail->cVars = 0;
837 tail->cImplTypes = 0;
838 tail->res06 = 0;
839 tail->funcs_off = -1;
840 tail->vars_off = -1;
841 tail->impls_off = -1;
842 tail->funcs_bytes = -1;
843 tail->vars_bytes = -1;
844 tail->impls_bytes = -1;
845 tail->tdescalias_vt = -1;
846 tail->res16 = -1;
847 tail->res18 = 0;
848 tail->res1a = 0;
849 tail->simple_alias = 0;
850 tail->res1e = 0;
851 tail->cbSizeInstance = 0;
852 tail->cbAlignment = 4;
853 tail->res24 = -1;
854 tail->res26 = -1;
855 tail->cbSizeVft = 0;
856 tail->res2a = -1;
857 tail->res2c = -1;
858 tail->res2e = -1;
859 tail->res30 = -1;
860 tail->res32 = 0;
861 tail->type_bytes = 0;
864 static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type)
866 struct sltg_data data, *var_data = NULL;
867 struct sltg_hrefmap hrefmap;
868 const char *index_name;
869 struct sltg_typeinfo_header ti;
870 struct sltg_member_header member;
871 struct sltg_tail tail;
872 int member_offset, var_count = 0, var_data_size = 0, size_instance = 0;
873 short *type_desc_offset = NULL;
875 if (type->typelib_idx != -1) return;
877 chat("add_structure_typeinfo: type %p, type->name %s\n", type, type->name);
879 type->typelib_idx = typelib->block_count;
881 hrefmap.href_count = 0;
882 hrefmap.href = NULL;
884 if (type_struct_get_fields(type))
886 int i = 0;
887 var_t *var;
889 var_count = list_count(type_struct_get_fields(type));
891 var_data = xmalloc(var_count * sizeof(*var_data));
892 type_desc_offset = xmalloc(var_count * sizeof(*type_desc_offset));
894 LIST_FOR_EACH_ENTRY(var, type_struct_get_fields(type), var_t, entry)
896 short base_offset;
898 chat("add_structure_typeinfo: var %p (%s), type %p (%s)\n",
899 var, var->name, var->declspec.type, var->declspec.type->name);
901 init_sltg_data(&var_data[i]);
903 base_offset = var_data_size + (i + 1) * sizeof(struct sltg_variable);
904 type_desc_offset[i] = write_var_desc(typelib, &var_data[i], var->declspec.type, 0, base_offset, &size_instance, &hrefmap);
905 dump_var_desc(var_data[i].data, var_data[i].size);
907 if (var_data[i].size > sizeof(short))
908 var_data_size += var_data[i].size;
909 i++;
913 init_sltg_data(&data);
915 index_name = add_typeinfo_block(typelib, type, TKIND_RECORD);
917 init_typeinfo(&ti, type, TKIND_RECORD, &hrefmap);
918 append_data(&data, &ti, sizeof(ti));
920 write_hrefmap(&data, &hrefmap);
922 member_offset = data.size;
924 member.res00 = 0x0001;
925 member.res02 = 0xffff;
926 member.res04 = 0x01;
927 member.extra = var_data_size + var_count * sizeof(struct sltg_variable);
928 append_data(&data, &member, sizeof(member));
930 var_data_size = 0;
932 if (type_struct_get_fields(type))
934 int i = 0;
935 short next = member_offset;
936 var_t *var;
938 LIST_FOR_EACH_ENTRY(var, type_struct_get_fields(type), var_t, entry)
940 struct sltg_variable variable;
942 next += sizeof(variable);
944 variable.magic = 0x2a; /* always write flags to simplify calculations */
945 variable.name = add_name(&typelib->name_table, var->name);
946 variable.byte_offs = 0;
947 if (var_data[i].size > sizeof(short))
949 variable.flags = 0;
950 var_data_size = next - member_offset + type_desc_offset[i];
951 variable.type = var_data_size;
952 next += var_data[i].size;
954 else
956 variable.flags = 0x02;
957 variable.type = *(short *)var_data[i].data;
959 variable.next = i < var_count - 1 ? next - member_offset : -1;
960 variable.memid = 0x40000000 + i;
961 variable.helpcontext = -2; /* 0xfffe */
962 variable.helpstring = -1;
963 variable.varflags = 0;
965 append_data(&data, &variable, sizeof(variable));
966 if (var_data[i].size > sizeof(short))
967 append_data(&data, var_data[i].data, var_data[i].size);
969 i++;
973 init_sltg_tail(&tail);
974 tail.cVars = var_count;
975 tail.vars_off = 0;
976 tail.vars_bytes = var_data_size;
977 tail.cbSizeInstance = size_instance;
978 tail.type_bytes = data.size - member_offset - sizeof(member);
979 append_data(&data, &tail, sizeof(tail));
981 add_block(typelib, data.data, data.size, index_name);
984 static importinfo_t *find_importinfo(typelib_t *typelib, const char *name)
986 importlib_t *importlib;
988 LIST_FOR_EACH_ENTRY(importlib, &typelib->importlibs, importlib_t, entry)
990 int i;
992 for (i = 0; i < importlib->ntypeinfos; i++)
994 if (!strcmp(name, importlib->importinfos[i].name))
996 chat("Found %s in importlib list\n", name);
997 return &importlib->importinfos[i];
1002 return NULL;
1005 static int get_func_flags(const var_t *func, int *dispid, int *invokekind, int *helpcontext, const char **helpstring)
1007 static int dispid_base = 0x60000000;
1008 const attr_t *attr;
1009 int flags;
1011 *dispid = dispid_base++;
1012 *invokekind = 1 /* INVOKE_FUNC */;
1013 *helpcontext = -2;
1014 *helpstring = NULL;
1016 if (!func->attrs) return 0;
1018 flags = 0;
1020 LIST_FOR_EACH_ENTRY(attr, func->attrs, const attr_t, entry)
1022 expr_t *expr = attr->u.pval;
1023 switch(attr->type)
1025 case ATTR_BINDABLE:
1026 flags |= 0x4; /* FUNCFLAG_FBINDABLE */
1027 break;
1028 case ATTR_DEFAULTBIND:
1029 flags |= 0x20; /* FUNCFLAG_FDEFAULTBIND */
1030 break;
1031 case ATTR_DEFAULTCOLLELEM:
1032 flags |= 0x100; /* FUNCFLAG_FDEFAULTCOLLELEM */
1033 break;
1034 case ATTR_DISPLAYBIND:
1035 flags |= 0x10; /* FUNCFLAG_FDISPLAYBIND */
1036 break;
1037 case ATTR_HELPCONTEXT:
1038 *helpcontext = expr->u.lval;
1039 break;
1040 case ATTR_HELPSTRING:
1041 *helpstring = attr->u.pval;
1042 break;
1043 case ATTR_HIDDEN:
1044 flags |= 0x40; /* FUNCFLAG_FHIDDEN */
1045 break;
1046 case ATTR_ID:
1047 *dispid = expr->cval;
1048 break;
1049 case ATTR_IMMEDIATEBIND:
1050 flags |= 0x1000; /* FUNCFLAG_FIMMEDIATEBIND */
1051 break;
1052 case ATTR_NONBROWSABLE:
1053 flags |= 0x400; /* FUNCFLAG_FNONBROWSABLE */
1054 break;
1055 case ATTR_PROPGET:
1056 *invokekind = 0x2; /* INVOKE_PROPERTYGET */
1057 break;
1058 case ATTR_PROPPUT:
1059 *invokekind = 0x4; /* INVOKE_PROPERTYPUT */
1060 break;
1061 case ATTR_PROPPUTREF:
1062 *invokekind = 0x8; /* INVOKE_PROPERTYPUTREF */
1063 break;
1064 /* FIXME: FUNCFLAG_FREPLACEABLE */
1065 case ATTR_REQUESTEDIT:
1066 flags |= 0x8; /* FUNCFLAG_FREQUESTEDIT */
1067 break;
1068 case ATTR_RESTRICTED:
1069 flags |= 0x1; /* FUNCFLAG_FRESTRICTED */
1070 break;
1071 case ATTR_SOURCE:
1072 flags |= 0x2; /* FUNCFLAG_FSOURCE */
1073 break;
1074 case ATTR_UIDEFAULT:
1075 flags |= 0x200; /* FUNCFLAG_FUIDEFAULT */
1076 break;
1077 case ATTR_USESGETLASTERROR:
1078 flags |= 0x80; /* FUNCFLAG_FUSESGETLASTERROR */
1079 break;
1080 default:
1081 break;
1085 return flags;
1088 static int add_func_desc(struct sltg_typelib *typelib, struct sltg_data *data, var_t *func,
1089 int idx, short base_offset, struct sltg_hrefmap *hrefmap)
1091 struct sltg_data ret_data, *arg_data;
1092 int arg_count = 0, arg_data_size, optional = 0, defaults = 0, old_size;
1093 int funcflags = 0, dispid, invokekind = 1 /* INVOKE_FUNC */, helpcontext;
1094 const char *helpstring;
1095 const var_t *arg;
1096 short ret_desc_offset, *arg_desc_offset, arg_offset;
1097 struct sltg_function func_desc;
1099 chat("add_func_desc: %s, idx %#x\n", func->name, idx);
1101 old_size = data->size;
1103 init_sltg_data(&ret_data);
1104 ret_desc_offset = write_var_desc(typelib, &ret_data, type_function_get_rettype(func->declspec.type),
1105 0, base_offset, NULL, hrefmap);
1106 dump_var_desc(ret_data.data, ret_data.size);
1108 arg_data_size = 0;
1109 arg_offset = base_offset + sizeof(struct sltg_function);
1111 if (ret_data.size > sizeof(short))
1113 arg_data_size += ret_data.size;
1114 arg_offset += ret_data.size;
1117 if (type_function_get_args(func->declspec.type))
1119 int i = 0;
1121 arg_count = list_count(type_function_get_args(func->declspec.type));
1123 arg_data = xmalloc(arg_count * sizeof(*arg_data));
1124 arg_desc_offset = xmalloc(arg_count * sizeof(*arg_desc_offset));
1126 arg_offset += arg_count * 2 * sizeof(short);
1128 LIST_FOR_EACH_ENTRY(arg, type_function_get_args(func->declspec.type), const var_t, entry)
1130 const attr_t *attr;
1132 chat("add_func_desc: arg[%d] %p (%s), type %p (%s)\n",
1133 i, arg, arg->name, arg->declspec.type, arg->declspec.type->name);
1135 init_sltg_data(&arg_data[i]);
1137 arg_desc_offset[i] = write_var_desc(typelib, &arg_data[i], arg->declspec.type, 0, arg_offset, NULL, hrefmap);
1138 dump_var_desc(arg_data[i].data, arg_data[i].size);
1140 if (arg_data[i].size > sizeof(short))
1142 arg_data_size += arg_data[i].size;
1143 arg_offset += arg_data[i].size;
1146 i++;
1148 if (!arg->attrs) continue;
1150 LIST_FOR_EACH_ENTRY(attr, arg->attrs, const attr_t, entry)
1152 if (attr->type == ATTR_DEFAULTVALUE)
1153 defaults++;
1154 else if(attr->type == ATTR_OPTIONAL)
1155 optional++;
1160 funcflags = get_func_flags(func, &dispid, &invokekind, &helpcontext, &helpstring);
1162 if (base_offset != -1)
1163 chat("add_func_desc: flags %#x, dispid %#x, invokekind %d, helpcontext %#x, helpstring %s\n",
1164 funcflags, dispid, invokekind, helpcontext, helpstring);
1166 func_desc.magic = 0x6c; /* always write flags to simplify calculations */
1167 func_desc.flags = (invokekind << 4) | 0x02;
1168 if (idx & 0x80000000)
1170 func_desc.next = -1;
1171 idx &= ~0x80000000;
1173 else
1174 func_desc.next = base_offset + sizeof(func_desc) + arg_data_size + arg_count * 2 * sizeof(short);
1175 func_desc.name = base_offset != -1 ? add_name(&typelib->name_table, func->name) : -1;
1176 func_desc.dispid = dispid;
1177 func_desc.helpcontext = helpcontext;
1178 func_desc.helpstring = (helpstring && base_offset != -1) ? add_name(&typelib->name_table, helpstring) : -1;
1179 func_desc.arg_off = arg_count ? base_offset + sizeof(func_desc) : -1;
1180 func_desc.nacc = (arg_count << 3) | 4 /* CC_STDCALL */;
1181 func_desc.retnextopt = (optional << 1);
1182 if (ret_data.size > sizeof(short))
1184 func_desc.rettype = base_offset + sizeof(func_desc) + ret_desc_offset;
1185 if (arg_count)
1186 func_desc.arg_off += ret_data.size;
1188 else
1190 func_desc.retnextopt |= 0x80;
1191 func_desc.rettype = *(short *)ret_data.data;
1193 func_desc.vtblpos = idx * pointer_size;
1194 func_desc.funcflags = funcflags;
1196 append_data(data, &func_desc, sizeof(func_desc));
1198 arg_offset = base_offset + sizeof(struct sltg_function);
1200 if (ret_data.size > sizeof(short))
1202 append_data(data, ret_data.data, ret_data.size);
1203 func_desc.arg_off += ret_data.size;
1204 arg_offset += ret_data.size;
1207 if (arg_count)
1209 int i = 0;
1211 arg_offset += arg_count * 2 * sizeof(short);
1213 LIST_FOR_EACH_ENTRY(arg, type_function_get_args(func->declspec.type), const var_t, entry)
1215 short name, type_offset;
1217 name = base_offset != -1 ? add_name(&typelib->name_table, arg->name) : -1;
1218 append_data(data, &name, sizeof(name));
1220 if (arg_data[i].size > sizeof(short))
1222 type_offset = (arg_offset + arg_desc_offset[i]);
1223 arg_offset += arg_data[i].size;
1225 else
1226 type_offset = *(short *)arg_data[i].data;
1228 append_data(data, &type_offset, sizeof(type_offset));
1230 if (base_offset != -1)
1231 chat("add_func_desc: arg[%d] - name %s (%#x), type_offset %#x\n",
1232 i, arg->name, name, type_offset);
1234 i++;
1237 for (i = 0; i < arg_count; i++)
1239 if (arg_data[i].size > sizeof(short))
1240 append_data(data, arg_data[i].data, arg_data[i].size);
1244 return data->size - old_size;
1247 static void add_interface_typeinfo(struct sltg_typelib *typelib, type_t *iface)
1249 const statement_t *stmt_func;
1250 importinfo_t *ref_importinfo = NULL;
1251 type_t *inherit;
1252 struct sltg_data data;
1253 struct sltg_hrefmap hrefmap;
1254 const char *index_name;
1255 struct sltg_typeinfo_header ti;
1256 struct sltg_member_header member;
1257 struct sltg_tail tail;
1258 int member_offset, base_offset, func_count, func_data_size, i;
1260 if (iface->typelib_idx != -1) return;
1262 chat("add_interface_typeinfo: type %p, type->name %s\n", iface, iface->name);
1264 if (!iface->details.iface)
1266 error("interface %s is referenced but not defined\n", iface->name);
1267 return;
1270 if (is_attr(iface->attrs, ATTR_DISPINTERFACE))
1272 error("support for dispinterface %s is not implemented\n", iface->name);
1273 return;
1276 inherit = type_iface_get_inherit(iface);
1278 if (inherit)
1280 chat("add_interface_typeinfo: inheriting from base interface %s\n", inherit->name);
1282 warning("inheriting from base interface %s is not implemented\n", inherit->name);
1284 ref_importinfo = find_importinfo(typelib->typelib, inherit->name);
1286 if (!ref_importinfo && type_iface_get_inherit(inherit))
1287 add_interface_typeinfo(typelib, inherit);
1289 if (ref_importinfo)
1290 error("support for imported interfaces is not implemented\n");
1293 /* check typelib_idx again, it could have been added while resolving the parent interface */
1294 if (iface->typelib_idx != -1) return;
1296 iface->typelib_idx = typelib->block_count;
1298 /* pass 1: calculate function descriptions data size */
1299 hrefmap.href_count = 0;
1300 hrefmap.href = NULL;
1302 init_sltg_data(&data);
1304 STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(iface))
1306 add_func_desc(typelib, &data, stmt_func->u.var, -1, -1, &hrefmap);
1309 func_data_size = data.size;
1311 /* pass 2: write function descriptions */
1312 init_sltg_data(&data);
1314 func_count = list_count(type_iface_get_stmts(iface));
1316 index_name = add_typeinfo_block(typelib, iface, TKIND_INTERFACE);
1318 init_typeinfo(&ti, iface, TKIND_INTERFACE, &hrefmap);
1319 append_data(&data, &ti, sizeof(ti));
1321 write_hrefmap(&data, &hrefmap);
1323 member_offset = data.size;
1325 member.res00 = 0x0001;
1326 member.res02 = 0xffff;
1327 member.res04 = 0x01;
1328 member.extra = func_data_size;
1329 append_data(&data, &member, sizeof(member));
1331 base_offset = 0;
1333 /* inheriting from base interface is not implemented yet
1334 if (type_iface_get_inherit(iface))
1335 add_impl_type(typeinfo, type_iface_get_inherit(iface), ref_importinfo);
1338 i = 0;
1340 STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(iface))
1342 if (i == func_count - 1) i |= 0x80000000;
1344 base_offset += add_func_desc(typelib, &data, stmt_func->u.var, i, base_offset, &hrefmap);
1345 i++;
1348 init_sltg_tail(&tail);
1350 tail.cFuncs = func_count;
1351 tail.funcs_off = 0;
1352 tail.funcs_bytes = func_data_size;
1353 tail.cbSizeInstance = pointer_size;
1354 tail.cbAlignment = pointer_size;
1355 tail.cbSizeVft = func_count * pointer_size;
1356 tail.type_bytes = data.size - member_offset - sizeof(member);
1357 tail.res24 = 0;
1358 tail.res26 = 0;
1359 append_data(&data, &tail, sizeof(tail));
1361 add_block(typelib, data.data, data.size, index_name);
1364 static void add_enum_typeinfo(struct sltg_typelib *typelib, type_t *type)
1366 error("add_enum_typeinfo: %s not implemented\n", type->name);
1369 static void add_union_typeinfo(struct sltg_typelib *typelib, type_t *type)
1371 error("add_union_typeinfo: %s not implemented\n", type->name);
1374 static void add_coclass_typeinfo(struct sltg_typelib *typelib, type_t *type)
1376 error("add_coclass_typeinfo: %s not implemented\n", type->name);
1379 static void add_type_typeinfo(struct sltg_typelib *typelib, type_t *type)
1381 chat("add_type_typeinfo: adding %s, type %d\n", type->name, type_get_type(type));
1383 switch (type_get_type(type))
1385 case TYPE_INTERFACE:
1386 add_interface_typeinfo(typelib, type);
1387 break;
1388 case TYPE_STRUCT:
1389 add_structure_typeinfo(typelib, type);
1390 break;
1391 case TYPE_ENUM:
1392 add_enum_typeinfo(typelib, type);
1393 break;
1394 case TYPE_UNION:
1395 add_union_typeinfo(typelib, type);
1396 break;
1397 case TYPE_COCLASS:
1398 add_coclass_typeinfo(typelib, type);
1399 break;
1400 case TYPE_BASIC:
1401 case TYPE_POINTER:
1402 break;
1403 default:
1404 error("add_type_typeinfo: unhandled type %d for %s\n", type_get_type(type), type->name);
1405 break;
1409 static void add_statement(struct sltg_typelib *typelib, const statement_t *stmt)
1411 switch(stmt->type)
1413 case STMT_LIBRARY:
1414 case STMT_IMPORT:
1415 case STMT_PRAGMA:
1416 case STMT_CPPQUOTE:
1417 case STMT_DECLARATION:
1418 /* not included in typelib */
1419 break;
1420 case STMT_IMPORTLIB:
1421 /* not processed here */
1422 break;
1424 case STMT_TYPEDEF:
1426 typeref_t *ref;
1428 if (!stmt->u.type_list)
1429 break;
1431 LIST_FOR_EACH_ENTRY(ref, stmt->u.type_list, typeref_t, entry)
1433 /* in old style typelibs all types are public */
1434 add_type_typeinfo(typelib, ref->type);
1436 break;
1439 case STMT_MODULE:
1440 add_module_typeinfo(typelib, stmt->u.type);
1441 break;
1443 case STMT_TYPE:
1444 case STMT_TYPEREF:
1446 type_t *type = stmt->u.type;
1447 add_type_typeinfo(typelib, type);
1448 break;
1451 default:
1452 error("add_statement: unhandled statement type %d\n", stmt->type);
1453 break;
1457 static void sltg_write_header(struct sltg_typelib *sltg, int *library_block_start)
1459 char pad[0x40];
1460 struct sltg_header
1462 int magic;
1463 short block_count;
1464 short res06;
1465 short size_of_index;
1466 short first_blk;
1467 GUID uuid;
1468 int res1c;
1469 int res20;
1470 } header;
1471 struct sltg_block_entry
1473 int length;
1474 short index_string;
1475 short next;
1476 } entry;
1477 int i;
1479 header.magic = 0x47544c53;
1480 header.block_count = sltg->block_count + 1; /* 1-based */
1481 header.res06 = 9;
1482 header.size_of_index = sltg->index.size;
1483 header.first_blk = 1; /* 1-based */
1484 header.uuid = sltg_library_guid;
1485 header.res1c = 0x00000044;
1486 header.res20 = 0xffff0000;
1488 put_data(&header, sizeof(header));
1490 /* library block is written separately */
1491 for (i = 0; i < sltg->block_count - 1; i++)
1493 entry.length = sltg->blocks[i].length;
1494 entry.index_string = sltg->blocks[i].index_string;
1495 entry.next = header.first_blk + i + 1; /* point to next block */
1496 chat("sltg_write_header: writing block entry %d: length %#x, index_string %#x, next %#x\n",
1497 i, entry.length, entry.index_string, entry.next);
1498 put_data(&entry, sizeof(entry));
1501 /* library block length includes helpstrings and name table */
1502 entry.length = sltg->blocks[sltg->block_count - 1].length + 0x40 /* pad after library block */ +
1503 sizeof(sltg->typeinfo_count) + sltg->typeinfo_size + 4 /* library block offset */ + 6 /* dummy help strings */ +
1504 12 /* name table header */ + 0x200 /* name table hash */ + sltg->name_table.size;
1505 entry.index_string = sltg->blocks[sltg->block_count - 1].index_string;
1506 entry.next = 0;
1507 chat("sltg_write_header: writing library block entry %d: length %#x, index_string %#x, next %#x\n",
1508 i, entry.length, entry.index_string, entry.next);
1509 put_data(&entry, sizeof(entry));
1511 chat("sltg_write_header: writing index: %d bytes\n", sltg->index.size);
1512 put_data(sltg->index.data, sltg->index.size);
1513 memset(pad, 0, 9);
1514 put_data(pad, 9);
1516 /* library block is written separately */
1517 for (i = 0; i < sltg->block_count - 1; i++)
1519 chat("sltg_write_header: writing block %d: %d bytes\n", i, sltg->blocks[i].length);
1520 put_data(sltg->blocks[i].data, sltg->blocks[i].length);
1523 /* library block */
1524 chat("library_block_start = %#x\n", (int)output_buffer_pos);
1525 *library_block_start = output_buffer_pos;
1526 chat("sltg_write_header: writing library block %d: %d bytes\n", i, sltg->blocks[i].length);
1527 put_data(sltg->blocks[sltg->block_count - 1].data, sltg->blocks[sltg->block_count - 1].length);
1529 chat("sltg_write_header: writing pad 0x40 bytes\n");
1530 memset(pad, 0xff, 0x40);
1531 put_data(pad, 0x40);
1534 static void sltg_write_typeinfo(struct sltg_typelib *typelib)
1536 short i;
1538 put_data(&typelib->typeinfo_count, sizeof(typelib->typeinfo_count));
1540 for (i = 0; i < typelib->typeinfo_count; i++)
1542 chat("sltg_write_typeinfo: writing block %d: %d bytes\n", i, typelib->typeinfo[i].length);
1543 put_data(typelib->typeinfo[i].data, typelib->typeinfo[i].length);
1547 static void sltg_write_helpstrings(struct sltg_typelib *typelib)
1549 static const char dummy[6];
1551 chat("sltg_write_helpstrings: writing dummy 6 bytes\n");
1553 put_data(dummy, sizeof(dummy));
1556 static void sltg_write_nametable(struct sltg_typelib *typelib)
1558 static const short dummy[6] = { 0xffff,1,2,0xff00,0xffff,0xffff };
1559 char pad[0x200];
1561 chat("sltg_write_nametable: writing 12+0x200+%d bytes\n", typelib->name_table.size);
1563 put_data(dummy, sizeof(dummy));
1564 memset(pad, 0xff, 0x200);
1565 put_data(pad, 0x200);
1566 put_data(&typelib->name_table.size, sizeof(typelib->name_table.size));
1567 put_data(typelib->name_table.data, typelib->name_table.size);
1570 static void sltg_write_remainder(void)
1572 static const short dummy1[] = { 1,0xfffe,0x0a03,0,0xffff,0xffff };
1573 static const short dummy2[] = { 0xffff,0xffff,0x0200,0,0,0 };
1574 static const char dummy3[] = { 0xf4,0x39,0xb2,0x71,0,0,0,0,0,0,0,0,0,0,0,0 };
1575 static const char TYPELIB[] = { 8,0,0,0,'T','Y','P','E','L','I','B',0 };
1576 int pad;
1578 pad = 0x01ffff01;
1579 put_data(&pad, sizeof(pad));
1580 pad = 0;
1581 put_data(&pad, sizeof(pad));
1583 put_data(dummy1, sizeof(dummy1));
1585 put_data(&sltg_library_guid, sizeof(sltg_library_guid));
1587 put_data(TYPELIB, sizeof(TYPELIB));
1589 put_data(dummy2, sizeof(dummy2));
1590 put_data(dummy3, sizeof(dummy3));
1593 static void save_all_changes(struct sltg_typelib *typelib)
1595 int library_block_start;
1596 int *name_table_offset;
1598 sltg_write_header(typelib, &library_block_start);
1599 sltg_write_typeinfo(typelib);
1601 name_table_offset = (int *)(output_buffer + output_buffer_pos);
1602 chat("name_table_offset = %#x\n", (int)output_buffer_pos);
1603 put_data(&library_block_start, sizeof(library_block_start));
1605 sltg_write_helpstrings(typelib);
1607 *name_table_offset = output_buffer_pos - library_block_start;
1608 chat("*name_table_offset = %#x\n", *name_table_offset);
1610 sltg_write_nametable(typelib);
1611 sltg_write_remainder();
1613 if (strendswith(typelib_name, ".res")) /* create a binary resource file */
1615 char typelib_id[13] = "#1";
1617 expr_t *expr = get_attrp(typelib->typelib->attrs, ATTR_ID);
1618 if (expr)
1619 sprintf(typelib_id, "#%d", expr->cval);
1620 add_output_to_resources("TYPELIB", typelib_id);
1621 if (strendswith(typelib_name, "_t.res")) /* add typelib registration */
1622 output_typelib_regscript(typelib->typelib);
1624 else flush_output_buffer(typelib_name);
1627 int create_sltg_typelib(typelib_t *typelib)
1629 struct sltg_typelib sltg;
1630 const statement_t *stmt;
1632 if (pointer_size != 4)
1633 error("Only 32-bit platform is supported\n");
1635 sltg.typelib = typelib;
1636 sltg.typeinfo_count = 0;
1637 sltg.typeinfo_size = 0;
1638 sltg.typeinfo = NULL;
1639 sltg.blocks = NULL;
1640 sltg.block_count = 0;
1641 sltg.first_block = 1;
1643 init_index(&sltg.index);
1644 init_name_table(&sltg.name_table);
1645 init_library(&sltg);
1647 add_library_block(&sltg);
1649 if (typelib->stmts)
1650 LIST_FOR_EACH_ENTRY(stmt, typelib->stmts, const statement_t, entry)
1651 add_statement(&sltg, stmt);
1653 save_all_changes(&sltg);
1655 return 1;