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
35 #include "typelib_struct.h"
40 static const GUID sltg_library_guid
= { 0x204ff,0,0,{ 0xc0,0,0,0,0,0,0,0x46 } };
71 struct sltg_data index
;
72 struct sltg_data name_table
;
73 struct sltg_library library
;
74 struct sltg_block
*blocks
;
79 struct sltg_block
*typeinfo
;
89 struct sltg_typeinfo_header
100 unsigned unknown1
: 3;
102 unsigned unknown2
: 8;
103 unsigned typekind
: 8;
108 struct sltg_member_header
118 char magic
; /* 0x0a */
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 */
127 short varflags
; /* only present if magic & 0x20 */
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
;
150 short res24
; /* always ffff */
151 short res26
; /* always ffff */
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 */
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 */
186 static void add_structure_typeinfo(struct sltg_typelib
*typelib
, type_t
*type
);
187 static void add_interface_typeinfo(struct sltg_typelib
*typelib
, type_t
*type
);
188 static void add_enum_typeinfo(struct sltg_typelib
*typelib
, type_t
*type
);
189 static void add_union_typeinfo(struct sltg_typelib
*typelib
, type_t
*type
);
190 static void add_coclass_typeinfo(struct sltg_typelib
*typelib
, type_t
*type
);
192 static void init_sltg_data(struct sltg_data
*data
)
199 static int add_index(struct sltg_data
*index
, const char *name
)
201 int name_offset
= index
->size
;
202 int new_size
= index
->size
+ strlen(name
) + 1;
204 chat("add_index: name_offset %d, \"%s\"\n", name_offset
, name
);
206 if (new_size
> index
->allocated
)
208 index
->allocated
= index
->allocated
? max(index
->allocated
* 2, new_size
) : new_size
;
209 index
->data
= xrealloc(index
->data
, index
->allocated
);
212 strcpy(index
->data
+ index
->size
, name
);
213 index
->size
= new_size
;
218 static void init_index(struct sltg_data
*index
)
220 static const char compobj
[] = { 1,'C','o','m','p','O','b','j',0 };
222 init_sltg_data(index
);
224 add_index(index
, compobj
);
227 static int add_name(struct sltg_data
*name_table
, const char *name
)
229 int name_offset
= name_table
->size
;
230 int new_size
= name_table
->size
+ strlen(name
) + 1 + 8;
233 chat("add_name: %s\n", name
);
235 aligned_size
= (new_size
+ 0x1f) & ~0x1f;
236 if (aligned_size
- new_size
< 4)
237 new_size
= aligned_size
;
239 new_size
= (new_size
+ 1) & ~1;
241 if (new_size
> name_table
->allocated
)
243 name_table
->allocated
= name_table
->allocated
? max(name_table
->allocated
* 2, new_size
) : new_size
;
244 name_table
->data
= xrealloc(name_table
->data
, name_table
->allocated
);
247 memset(name_table
->data
+ name_table
->size
, 0xff, 8);
248 strcpy(name_table
->data
+ name_table
->size
+ 8, name
);
249 name_table
->size
= new_size
;
250 name_table
->data
[name_table
->size
- 1] = 0; /* clear alignment */
255 static void init_name_table(struct sltg_data
*name_table
)
257 init_sltg_data(name_table
);
260 static void init_library(struct sltg_typelib
*sltg
)
264 sltg
->library
.name
= add_name(&sltg
->name_table
, sltg
->typelib
->name
);
265 sltg
->library
.helpstring
= NULL
;
266 sltg
->library
.helpcontext
= 0;
267 sltg
->library
.syskind
= SYS_WIN32
;
268 sltg
->library
.lcid
= 0x0409;
269 sltg
->library
.libflags
= 0;
270 sltg
->library
.version
= 0;
271 sltg
->library
.helpfile
= NULL
;
272 memset(&sltg
->library
.uuid
, 0, sizeof(sltg
->library
.uuid
));
274 if (!sltg
->typelib
->attrs
) return;
276 LIST_FOR_EACH_ENTRY(attr
, sltg
->typelib
->attrs
, const attr_t
, entry
)
283 sltg
->library
.version
= attr
->u
.ival
;
285 case ATTR_HELPSTRING
:
286 sltg
->library
.helpstring
= attr
->u
.pval
;
289 sltg
->library
.helpfile
= attr
->u
.pval
;
292 sltg
->library
.uuid
= *(GUID
*)attr
->u
.pval
;
294 case ATTR_HELPCONTEXT
:
296 sltg
->library
.helpcontext
= expr
->cval
;
300 sltg
->library
.lcid
= expr
->cval
;
303 sltg
->library
.libflags
|= 0x02; /* LIBFLAG_FCONTROL */
306 sltg
->library
.libflags
|= 0x04; /* LIBFLAG_FHIDDEN */
308 case ATTR_RESTRICTED
:
309 sltg
->library
.libflags
|= 0x01; /* LIBFLAG_FRESTRICTED */
317 static void add_block(struct sltg_typelib
*sltg
, void *data
, int length
, const char *name
)
319 chat("add_block: %p,%d,\"%s\"\n", data
, length
, name
);
321 sltg
->blocks
= xrealloc(sltg
->blocks
, sizeof(sltg
->blocks
[0]) * (sltg
->block_count
+ 1));
322 sltg
->blocks
[sltg
->block_count
].length
= length
;
323 sltg
->blocks
[sltg
->block_count
].data
= data
;
324 sltg
->blocks
[sltg
->block_count
].index_string
= add_index(&sltg
->index
, name
);
328 static void add_library_block(struct sltg_typelib
*typelib
)
334 size
= sizeof(short) * 9 + sizeof(int) * 3 + sizeof(GUID
);
335 if (typelib
->library
.helpstring
) size
+= strlen(typelib
->library
.helpstring
);
336 if (typelib
->library
.helpfile
) size
+= strlen(typelib
->library
.helpfile
);
338 block
= xmalloc(size
);
340 *p
++ = 0x51cc; /* magic */
341 *p
++ = 3; /* res02 */
342 *p
++ = typelib
->library
.name
;
343 *p
++ = 0xffff; /* res06 */
344 if (typelib
->library
.helpstring
)
346 *p
++ = strlen(typelib
->library
.helpstring
);
347 strcpy((char *)p
, typelib
->library
.helpstring
);
348 p
= (short *)((char *)p
+ strlen(typelib
->library
.helpstring
));
352 if (typelib
->library
.helpfile
)
354 *p
++ = strlen(typelib
->library
.helpfile
);
355 strcpy((char *)p
, typelib
->library
.helpfile
);
356 p
= (short *)((char *)p
+ strlen(typelib
->library
.helpfile
));
360 *(int *)p
= typelib
->library
.helpcontext
;
362 *p
++ = typelib
->library
.syskind
;
363 *p
++ = typelib
->library
.lcid
;
364 *(int *)p
= 0; /* res12 */
366 *p
++ = typelib
->library
.libflags
;
367 *(int *)p
= typelib
->library
.version
;
369 *(GUID
*)p
= typelib
->library
.uuid
;
371 add_block(typelib
, block
, size
, "dir");
374 static const char *new_index_name(void)
376 static char name
[11] = "AAAAAAAAAA";
380 if (name
[pos
] == 'Z')
384 error("too many index names\n");
389 new_name
= xmalloc(sizeof(name
));
390 strcpy(new_name
, name
);
394 static void sltg_add_typeinfo(struct sltg_typelib
*sltg
, void *data
, int length
, const char *name
)
396 chat("sltg_add_typeinfo: %p,%d,%s\n", data
, length
, name
);
398 sltg
->typeinfo
= xrealloc(sltg
->typeinfo
, sizeof(sltg
->typeinfo
[0]) * (sltg
->typeinfo_count
+ 1));
399 sltg
->typeinfo
[sltg
->typeinfo_count
].length
= length
;
400 sltg
->typeinfo
[sltg
->typeinfo_count
].data
= data
;
401 sltg
->typeinfo
[sltg
->typeinfo_count
].index_string
= 0;
402 sltg
->typeinfo_count
++;
403 sltg
->typeinfo_size
+= length
;
406 static void append_data(struct sltg_data
*block
, const void *data
, int size
)
408 int new_size
= block
->size
+ size
;
410 if (new_size
> block
->allocated
)
412 block
->allocated
= max(block
->allocated
* 2, new_size
);
413 block
->data
= xrealloc(block
->data
, block
->allocated
);
416 memcpy(block
->data
+ block
->size
, data
, size
);
417 block
->size
= new_size
;
420 static void add_module_typeinfo(struct sltg_typelib
*typelib
, type_t
*type
)
422 error("add_module_typeinfo: %s not implemented\n", type
->name
);
425 static void add_interface_typeinfo(struct sltg_typelib
*typelib
, type_t
*type
)
427 error("add_interface_typeinfo: %s not implemented\n", type
->name
);
430 static const char *add_typeinfo_block(struct sltg_typelib
*typelib
, const type_t
*type
, short kind
)
432 struct sltg_data block
;
433 const char *index_name
, *other_name
;
440 index_name
= new_index_name();
441 other_name
= new_index_name();
443 expr
= get_attrp(type
->attrs
, ATTR_HELPCONTEXT
);
444 if (expr
) helpcontext
= expr
->cval
;
446 p
= get_attrp(type
->attrs
, ATTR_UUID
);
447 if (p
) guid
= *(GUID
*)p
;
449 init_sltg_data(&block
);
451 val
= strlen(index_name
);
452 append_data(&block
, &val
, sizeof(val
));
453 append_data(&block
, index_name
, val
);
454 val
= strlen(other_name
);
455 append_data(&block
, &val
, sizeof(val
));
456 append_data(&block
, other_name
, val
);
457 val
= -1; /* res1a */
458 append_data(&block
, &val
, sizeof(val
));
459 val
= add_name(&typelib
->name_table
, type
->name
); /* name offset */
460 append_data(&block
, &val
, sizeof(val
));
461 val
= 0; /* FIXME: helpstring */
462 append_data(&block
, &val
, sizeof(val
));
463 val
= -1; /* res20 */
464 append_data(&block
, &val
, sizeof(val
));
465 append_data(&block
, &helpcontext
, sizeof(helpcontext
));
466 val
= -1; /* res26 */
467 append_data(&block
, &val
, sizeof(val
));
468 append_data(&block
, &guid
, sizeof(guid
));
469 append_data(&block
, &kind
, sizeof(kind
));
471 sltg_add_typeinfo(typelib
, block
.data
, block
.size
, index_name
);
476 static void init_typeinfo(struct sltg_typeinfo_header
*ti
, const type_t
*type
, short kind
,
477 const struct sltg_hrefmap
*hrefmap
)
480 ti
->href_offset
= -1;
482 ti
->member_offset
= sizeof(*ti
);
484 ti
->version
= get_attrv(type
->attrs
, ATTR_VERSION
);
485 ti
->res16
= 0xfffe0000;
486 ti
->misc
.unknown1
= 0x02;
487 ti
->misc
.flags
= 0; /* FIXME */
488 ti
->misc
.unknown2
= 0x02;
489 ti
->misc
.typekind
= kind
;
492 if (hrefmap
->href_count
)
495 int i
, hrefinfo_size
;
497 hrefinfo_size
= sizeof(struct sltg_hrefinfo
);
499 for (i
= 0; i
< hrefmap
->href_count
; i
++)
501 sprintf(name
, "*\\Rffff*#%x", hrefmap
->href
[i
]);
502 hrefinfo_size
+= 8 + 2 + strlen(name
);
505 ti
->href_offset
= ti
->member_offset
;
506 ti
->member_offset
+= hrefinfo_size
;
510 static void write_hrefmap(struct sltg_data
*data
, const struct sltg_hrefmap
*hrefmap
)
512 struct sltg_hrefinfo hrefinfo
;
516 if (!hrefmap
->href_count
) return;
518 hrefinfo
.magic
= 0xdf;
520 memset(hrefinfo
.res02
, 0xff, sizeof(hrefinfo
.res02
));
521 hrefinfo
.number
= hrefmap
->href_count
* 8;
525 hrefinfo
.resxx
= 0xdf;
527 append_data(data
, &hrefinfo
, offsetof(struct sltg_hrefinfo
, res50
));
529 for (i
= 0; i
< hrefmap
->href_count
; i
++)
530 append_data(data
, "\xff\xff\xff\xff\xff\xff\xff\xff", 8);
532 append_data(data
, &hrefinfo
.res50
, 7);
534 for (i
= 0; i
< hrefmap
->href_count
; i
++)
538 sprintf(name
, "*\\Rffff*#%x", hrefmap
->href
[i
]);
541 append_data(data
, &len
, sizeof(len
));
542 append_data(data
, name
, len
);
545 append_data(data
, &hrefinfo
.resxx
, sizeof(hrefinfo
.resxx
));
548 static void dump_var_desc(const char *data
, int size
)
550 const unsigned char *p
= (const unsigned char *)data
;
553 if (!(debuglevel
& (DEBUGLEVEL_TRACE
| DEBUGLEVEL_CHAT
))) return;
555 chat("dump_var_desc: size %d bytes\n", size
);
557 for (i
= 0; i
< size
; i
++)
558 fprintf(stderr
, " %02x", *p
++);
560 fprintf(stderr
, "\n");
563 static int get_element_size(type_t
*type
)
565 int vt
= get_type_vt(type
);
615 error("get_element_size: unrecognized vt %d\n", vt
);
622 static int local_href(struct sltg_hrefmap
*hrefmap
, int typelib_href
)
626 for (i
= 0; i
< hrefmap
->href_count
; i
++)
628 if (hrefmap
->href
[i
] == typelib_href
)
637 href
= hrefmap
->href_count
;
640 hrefmap
->href
= xrealloc(hrefmap
->href
, sizeof(*hrefmap
->href
) * (hrefmap
->href_count
+ 1));
642 hrefmap
->href
= xmalloc(sizeof(*hrefmap
->href
));
644 hrefmap
->href
[hrefmap
->href_count
] = typelib_href
;
645 hrefmap
->href_count
++;
648 chat("typelib href %d mapped to local href %d\n", typelib_href
, href
);
653 static short write_var_desc(struct sltg_typelib
*typelib
, struct sltg_data
*data
, type_t
*type
, short flags
,
654 short base_offset
, int *size_instance
, struct sltg_hrefmap
*hrefmap
)
656 short vt
, vt_flags
, desc_offset
;
658 chat("write_var_desc: type %p, type->name %s\n",
659 type
, type
->name
? type
->name
: "NULL");
661 if (is_array(type
) && !type_array_is_decl_as_ptr(type
))
663 int num_dims
, elements
, array_start
, size
, array_size
;
682 while (is_array(atype
) && !type_array_is_decl_as_ptr(atype
))
685 elements
*= type_array_get_dim(atype
);
687 atype
= type_array_get_element_type(atype
);
690 chat("write_var_desc: VT_CARRAY: %d dimensions, %d elements\n", num_dims
, elements
);
692 array_start
= data
->size
;
694 size
= sizeof(*array
) + (num_dims
- 1) * 8 /* sizeof(SAFEARRAYBOUND) */;
695 array
= xmalloc(size
);
697 array
->cDims
= num_dims
;
698 array
->fFeatures
= 0x0004; /* FADF_EMBEDDED */
699 array
->cbElements
= get_element_size(atype
);
703 bound
= array
->bound
;
705 array_size
= array
->cbElements
;
708 while (is_array(atype
) && !type_array_is_decl_as_ptr(atype
))
710 bound
[0] = type_array_get_dim(atype
);
711 array_size
*= bound
[0];
715 atype
= type_array_get_element_type(atype
);
718 *size_instance
+= array_size
;
719 size_instance
= NULL
; /* don't account for element size */
721 append_data(data
, array
, size
);
723 desc_offset
= data
->size
;
725 vt_off
[0] = VT_CARRAY
;
726 vt_off
[1] = array_start
+ base_offset
;
727 append_data(data
, vt_off
, sizeof(vt_off
));
729 /* fall through to write array element description */
733 desc_offset
= data
->size
;
735 vt
= get_type_vt(type
);
739 type_t
*ref
= is_ptr(type
) ? type_pointer_get_ref_type(type
) : type_array_get_element_type(type
);
743 chat("write_var_desc: vt VT_PTR | 0x0400\n");
744 vt
= VT_PTR
| 0x0400;
745 append_data(data
, &vt
, sizeof(vt
));
746 write_var_desc(typelib
, data
, ref
, 0, base_offset
, size_instance
, hrefmap
);
749 write_var_desc(typelib
, data
, ref
, 0x0e00, base_offset
, size_instance
, hrefmap
);
753 chat("write_var_desc: vt %d, flags %04x\n", vt
, flags
);
755 vt_flags
= vt
| flags
;
756 append_data(data
, &vt_flags
, sizeof(vt_flags
));
758 if (vt
== VT_USERDEFINED
)
762 while (type
->typelib_idx
< 0 && type_is_alias(type
))
763 type
= type_alias_get_aliasee_type(type
);
765 chat("write_var_desc: VT_USERDEFINED, type %p, name %s, real type %d, href %d\n",
766 type
, type
->name
, type_get_type(type
), type
->typelib_idx
);
768 if (type
->typelib_idx
== -1)
770 chat("write_var_desc: trying to ref not added type\n");
772 switch (type_get_type(type
))
775 add_structure_typeinfo(typelib
, type
);
778 add_interface_typeinfo(typelib
, type
);
781 add_enum_typeinfo(typelib
, type
);
784 add_union_typeinfo(typelib
, type
);
787 add_coclass_typeinfo(typelib
, type
);
790 error("write_var_desc: VT_USERDEFINED - unhandled type %d\n",
791 type_get_type(type
));
795 if (type
->typelib_idx
== -1)
796 error("write_var_desc: trying to ref not added type\n");
798 href
= local_href(hrefmap
, type
->typelib_idx
);
799 chat("write_var_desc: VT_USERDEFINED, local href %d\n", href
);
801 append_data(data
, &href
, sizeof(href
));
805 *size_instance
+= get_element_size(type
);
810 static void init_sltg_tail(struct sltg_tail
*tail
)
814 tail
->cImplTypes
= 0;
816 tail
->funcs_off
= -1;
818 tail
->impls_off
= -1;
819 tail
->funcs_bytes
= -1;
820 tail
->vars_bytes
= 0;
821 tail
->impls_bytes
= -1;
822 tail
->tdescalias_vt
= -1;
826 tail
->simple_alias
= 0;
828 tail
->cbSizeInstance
= 0;
829 tail
->cbAlignment
= 4;
838 tail
->type_bytes
= 0;
841 static void add_structure_typeinfo(struct sltg_typelib
*typelib
, type_t
*type
)
843 struct sltg_data data
, *var_data
= NULL
;
844 struct sltg_hrefmap hrefmap
;
845 const char *index_name
;
846 struct sltg_typeinfo_header ti
;
847 struct sltg_member_header member
;
848 struct sltg_tail tail
;
849 int member_offset
, var_count
= 0, var_data_size
= 0, size_instance
= 0;
850 short *type_desc_offset
= NULL
;
852 if (type
->typelib_idx
!= -1) return;
854 chat("add_structure_typeinfo: type %p, type->name %s\n", type
, type
->name
);
856 type
->typelib_idx
= typelib
->block_count
;
858 hrefmap
.href_count
= 0;
861 init_sltg_data(&data
);
863 if (type_struct_get_fields(type
))
868 var_count
= list_count(type_struct_get_fields(type
));
870 var_data
= xmalloc(var_count
* sizeof(*var_data
));
871 type_desc_offset
= xmalloc(var_count
* sizeof(*type_desc_offset
));
873 LIST_FOR_EACH_ENTRY(var
, type_struct_get_fields(type
), var_t
, entry
)
877 chat("add_structure_typeinfo: var %p (%s), type %p (%s)\n",
878 var
, var
->name
, var
->declspec
.type
, var
->declspec
.type
->name
);
880 init_sltg_data(&var_data
[i
]);
882 base_offset
= var_data_size
+ (i
+ 1) * sizeof(struct sltg_variable
);
883 type_desc_offset
[i
] = write_var_desc(typelib
, &var_data
[i
], var
->declspec
.type
, 0, base_offset
, &size_instance
, &hrefmap
);
884 dump_var_desc(var_data
[i
].data
, var_data
[i
].size
);
886 if (var_data
[i
].size
> sizeof(short))
887 var_data_size
+= var_data
[i
].size
;
892 index_name
= add_typeinfo_block(typelib
, type
, TKIND_RECORD
);
894 init_typeinfo(&ti
, type
, TKIND_RECORD
, &hrefmap
);
895 append_data(&data
, &ti
, sizeof(ti
));
897 write_hrefmap(&data
, &hrefmap
);
899 member_offset
= data
.size
;
901 member
.res00
= 0x0001;
902 member
.res02
= 0xffff;
904 member
.extra
= var_data_size
+ var_count
* sizeof(struct sltg_variable
);
905 append_data(&data
, &member
, sizeof(member
));
909 if (type_struct_get_fields(type
))
912 short next
= member_offset
;
915 LIST_FOR_EACH_ENTRY(var
, type_struct_get_fields(type
), var_t
, entry
)
917 struct sltg_variable variable
;
919 next
+= sizeof(variable
);
921 variable
.magic
= 0x2a; /* always write flags to simplify calculations */
922 variable
.name
= add_name(&typelib
->name_table
, var
->name
);
923 variable
.byte_offs
= 0;
924 if (var_data
[i
].size
> sizeof(short))
927 var_data_size
= next
- member_offset
+ type_desc_offset
[i
];
928 variable
.type
= var_data_size
;
929 next
+= var_data
[i
].size
;
933 variable
.flags
= 0x02;
934 variable
.type
= *(short *)var_data
[i
].data
;
936 variable
.next
= i
< var_count
- 1 ? next
- member_offset
: -1;
937 variable
.memid
= 0x40000000 + i
;
938 variable
.helpcontext
= -2; /* 0xfffe */
939 variable
.helpstring
= -1;
940 variable
.varflags
= 0;
942 append_data(&data
, &variable
, sizeof(variable
));
943 if (var_data
[i
].size
> sizeof(short))
944 append_data(&data
, var_data
[i
].data
, var_data
[i
].size
);
950 init_sltg_tail(&tail
);
951 tail
.cVars
= var_count
;
952 tail
.vars_bytes
= var_data_size
;
953 tail
.cbSizeInstance
= size_instance
;
954 tail
.type_bytes
= data
.size
- member_offset
- sizeof(member
);
955 append_data(&data
, &tail
, sizeof(tail
));
957 add_block(typelib
, data
.data
, data
.size
, index_name
);
960 static void add_enum_typeinfo(struct sltg_typelib
*typelib
, type_t
*type
)
962 error("add_enum_typeinfo: %s not implemented\n", type
->name
);
965 static void add_union_typeinfo(struct sltg_typelib
*typelib
, type_t
*type
)
967 error("add_union_typeinfo: %s not implemented\n", type
->name
);
970 static void add_coclass_typeinfo(struct sltg_typelib
*typelib
, type_t
*type
)
972 error("add_coclass_typeinfo: %s not implemented\n", type
->name
);
975 static void add_type_typeinfo(struct sltg_typelib
*typelib
, type_t
*type
)
977 chat("add_type_typeinfo: adding %s, type %d\n", type
->name
, type_get_type(type
));
979 switch (type_get_type(type
))
982 add_interface_typeinfo(typelib
, type
);
985 add_structure_typeinfo(typelib
, type
);
988 add_enum_typeinfo(typelib
, type
);
991 add_union_typeinfo(typelib
, type
);
994 add_coclass_typeinfo(typelib
, type
);
1000 error("add_type_typeinfo: unhandled type %d for %s\n", type_get_type(type
), type
->name
);
1005 static void add_statement(struct sltg_typelib
*typelib
, const statement_t
*stmt
)
1013 case STMT_DECLARATION
:
1014 /* not included in typelib */
1016 case STMT_IMPORTLIB
:
1017 /* not processed here */
1024 if (!stmt
->u
.type_list
)
1027 LIST_FOR_EACH_ENTRY(ref
, stmt
->u
.type_list
, typeref_t
, entry
)
1029 /* in old style typelibs all types are public */
1030 add_type_typeinfo(typelib
, ref
->type
);
1036 add_module_typeinfo(typelib
, stmt
->u
.type
);
1042 type_t
*type
= stmt
->u
.type
;
1043 add_type_typeinfo(typelib
, type
);
1048 error("add_statement: unhandled statement type %d\n", stmt
->type
);
1053 static void sltg_write_header(struct sltg_typelib
*sltg
, int *library_block_start
)
1061 short size_of_index
;
1067 struct sltg_block_entry
1075 header
.magic
= 0x47544c53;
1076 header
.block_count
= sltg
->block_count
+ 1; /* 1-based */
1078 header
.size_of_index
= sltg
->index
.size
;
1079 header
.first_blk
= 1; /* 1-based */
1080 header
.uuid
= sltg_library_guid
;
1081 header
.res1c
= 0x00000044;
1082 header
.res20
= 0xffff0000;
1084 put_data(&header
, sizeof(header
));
1086 /* library block is written separately */
1087 for (i
= 0; i
< sltg
->block_count
- 1; i
++)
1089 entry
.length
= sltg
->blocks
[i
].length
;
1090 entry
.index_string
= sltg
->blocks
[i
].index_string
;
1091 entry
.next
= header
.first_blk
+ i
+ 1; /* point to next block */
1092 chat("sltg_write_header: writing block entry %d: length %#x, index_string %#x, next %#x\n",
1093 i
, entry
.length
, entry
.index_string
, entry
.next
);
1094 put_data(&entry
, sizeof(entry
));
1097 /* library block length includes helpstrings and name table */
1098 entry
.length
= sltg
->blocks
[sltg
->block_count
- 1].length
+ 0x40 /* pad after library block */ +
1099 sizeof(sltg
->typeinfo_count
) + sltg
->typeinfo_size
+ 4 /* library block offset */ + 6 /* dummy help strings */ +
1100 12 /* name table header */ + 0x200 /* name table hash */ + sltg
->name_table
.size
;
1101 entry
.index_string
= sltg
->blocks
[sltg
->block_count
- 1].index_string
;
1103 chat("sltg_write_header: writing library block entry %d: length %#x, index_string %#x, next %#x\n",
1104 i
, entry
.length
, entry
.index_string
, entry
.next
);
1105 put_data(&entry
, sizeof(entry
));
1107 chat("sltg_write_header: writing index: %d bytes\n", sltg
->index
.size
);
1108 put_data(sltg
->index
.data
, sltg
->index
.size
);
1112 /* library block is written separately */
1113 for (i
= 0; i
< sltg
->block_count
- 1; i
++)
1115 chat("sltg_write_header: writing block %d: %d bytes\n", i
, sltg
->blocks
[i
].length
);
1116 put_data(sltg
->blocks
[i
].data
, sltg
->blocks
[i
].length
);
1120 chat("library_block_start = %#x\n", (int)output_buffer_pos
);
1121 *library_block_start
= output_buffer_pos
;
1122 chat("sltg_write_header: writing library block %d: %d bytes\n", i
, sltg
->blocks
[i
].length
);
1123 put_data(sltg
->blocks
[sltg
->block_count
- 1].data
, sltg
->blocks
[sltg
->block_count
- 1].length
);
1125 chat("sltg_write_header: writing pad 0x40 bytes\n");
1126 memset(pad
, 0xff, 0x40);
1127 put_data(pad
, 0x40);
1130 static void sltg_write_typeinfo(struct sltg_typelib
*typelib
)
1134 put_data(&typelib
->typeinfo_count
, sizeof(typelib
->typeinfo_count
));
1136 for (i
= 0; i
< typelib
->typeinfo_count
; i
++)
1138 chat("sltg_write_typeinfo: writing block %d: %d bytes\n", i
, typelib
->typeinfo
[i
].length
);
1139 put_data(typelib
->typeinfo
[i
].data
, typelib
->typeinfo
[i
].length
);
1143 static void sltg_write_helpstrings(struct sltg_typelib
*typelib
)
1145 static const char dummy
[6];
1147 chat("sltg_write_helpstrings: writing dummy 6 bytes\n");
1149 put_data(dummy
, sizeof(dummy
));
1152 static void sltg_write_nametable(struct sltg_typelib
*typelib
)
1154 static const short dummy
[6] = { 0xffff,1,2,0xff00,0xffff,0xffff };
1157 chat("sltg_write_nametable: writing 12+0x200+%d bytes\n", typelib
->name_table
.size
);
1159 put_data(dummy
, sizeof(dummy
));
1160 memset(pad
, 0xff, 0x200);
1161 put_data(pad
, 0x200);
1162 put_data(&typelib
->name_table
.size
, sizeof(typelib
->name_table
.size
));
1163 put_data(typelib
->name_table
.data
, typelib
->name_table
.size
);
1166 static void sltg_write_remainder(void)
1168 static const short dummy1
[] = { 1,0xfffe,0x0a03,0,0xffff,0xffff };
1169 static const short dummy2
[] = { 0xffff,0xffff,0x0200,0,0,0 };
1170 static const char dummy3
[] = { 0xf4,0x39,0xb2,0x71,0,0,0,0,0,0,0,0,0,0,0,0 };
1171 static const char TYPELIB
[] = { 8,0,0,0,'T','Y','P','E','L','I','B',0 };
1175 put_data(&pad
, sizeof(pad
));
1177 put_data(&pad
, sizeof(pad
));
1179 put_data(dummy1
, sizeof(dummy1
));
1181 put_data(&sltg_library_guid
, sizeof(sltg_library_guid
));
1183 put_data(TYPELIB
, sizeof(TYPELIB
));
1185 put_data(dummy2
, sizeof(dummy2
));
1186 put_data(dummy3
, sizeof(dummy3
));
1189 static void save_all_changes(struct sltg_typelib
*typelib
)
1191 int library_block_start
;
1192 int *name_table_offset
;
1194 sltg_write_header(typelib
, &library_block_start
);
1195 sltg_write_typeinfo(typelib
);
1197 name_table_offset
= (int *)(output_buffer
+ output_buffer_pos
);
1198 chat("name_table_offset = %#x\n", (int)output_buffer_pos
);
1199 put_data(&library_block_start
, sizeof(library_block_start
));
1201 sltg_write_helpstrings(typelib
);
1203 *name_table_offset
= output_buffer_pos
- library_block_start
;
1204 chat("*name_table_offset = %#x\n", *name_table_offset
);
1206 sltg_write_nametable(typelib
);
1207 sltg_write_remainder();
1209 if (strendswith(typelib_name
, ".res")) /* create a binary resource file */
1211 char typelib_id
[13] = "#1";
1213 expr_t
*expr
= get_attrp(typelib
->typelib
->attrs
, ATTR_ID
);
1215 sprintf(typelib_id
, "#%d", expr
->cval
);
1216 add_output_to_resources("TYPELIB", typelib_id
);
1217 if (strendswith(typelib_name
, "_t.res")) /* add typelib registration */
1218 output_typelib_regscript(typelib
->typelib
);
1220 else flush_output_buffer(typelib_name
);
1223 int create_sltg_typelib(typelib_t
*typelib
)
1225 struct sltg_typelib sltg
;
1226 const statement_t
*stmt
;
1228 if (pointer_size
!= 4)
1229 error("Only 32-bit platform is supported\n");
1231 sltg
.typelib
= typelib
;
1232 sltg
.typeinfo_count
= 0;
1233 sltg
.typeinfo_size
= 0;
1234 sltg
.typeinfo
= NULL
;
1236 sltg
.block_count
= 0;
1237 sltg
.first_block
= 1;
1239 init_index(&sltg
.index
);
1240 init_name_table(&sltg
.name_table
);
1241 init_library(&sltg
);
1243 add_library_block(&sltg
);
1246 LIST_FOR_EACH_ENTRY(stmt
, typelib
->stmts
, const statement_t
, entry
)
1247 add_statement(&sltg
, stmt
);
1249 save_all_changes(&sltg
);