xref: /reactos/sdk/tools/widl/write_msft.c (revision cc439606)
1 /*
2  *      Typelib v2 (MSFT) generation
3  *
4  *	Copyright 2004  Alastair Bridgewater
5  *                2004, 2005 Huw Davies
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  *
21  * --------------------------------------------------------------------------------------
22  *  Known problems:
23  *
24  *    Badly incomplete.
25  *
26  *    Only works on little-endian systems.
27  *
28  */
29 
30 #include "config.h"
31 #include "wine/port.h"
32 
33 #include <stdlib.h>
34 #include <string.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <ctype.h>
38 #include <time.h>
39 
40 #define NONAMELESSUNION
41 
42 #ifdef __REACTOS__
43 #include <typedefs.h>
44 #include <nls.h>
45 #else
46 #include "winerror.h"
47 #include "windef.h"
48 #include "winbase.h"
49 #include "winnls.h"
50 #endif
51 
52 #include "widl.h"
53 #include "typelib.h"
54 #include "typelib_struct.h"
55 #include "utils.h"
56 #include "header.h"
57 #include "hash.h"
58 #include "typetree.h"
59 #include "parser.h"
60 
61 #ifdef __REACTOS__
62 #define S_OK           0
63 #define S_FALSE        1
64 #define E_OUTOFMEMORY  ((HRESULT)0x8007000EL)
65 #endif
66 
67 enum MSFT_segment_index {
68     MSFT_SEG_TYPEINFO = 0,  /* type information */
69     MSFT_SEG_IMPORTINFO,    /* import information */
70     MSFT_SEG_IMPORTFILES,   /* import filenames */
71     MSFT_SEG_REFERENCES,    /* references (?) */
72     MSFT_SEG_GUIDHASH,      /* hash table for guids? */
73     MSFT_SEG_GUID,          /* guid storage */
74     MSFT_SEG_NAMEHASH,      /* hash table for names */
75     MSFT_SEG_NAME,          /* name storage */
76     MSFT_SEG_STRING,        /* string storage */
77     MSFT_SEG_TYPEDESC,      /* type descriptions */
78     MSFT_SEG_ARRAYDESC,     /* array descriptions */
79     MSFT_SEG_CUSTDATA,      /* custom data */
80     MSFT_SEG_CUSTDATAGUID,  /* custom data guids */
81     MSFT_SEG_UNKNOWN,       /* ??? */
82     MSFT_SEG_UNKNOWN2,      /* ??? */
83     MSFT_SEG_MAX            /* total number of segments */
84 };
85 
86 typedef struct tagMSFT_ImpFile {
87     int guid;
88     LCID lcid;
89     int version;
90     char filename[0]; /* preceded by two bytes of encoded (length << 2) + flags in the low two bits. */
91 } MSFT_ImpFile;
92 
93 typedef struct _msft_typelib_t
94 {
95     typelib_t *typelib;
96     MSFT_Header typelib_header;
97     MSFT_pSeg typelib_segdir[MSFT_SEG_MAX];
98     unsigned char *typelib_segment_data[MSFT_SEG_MAX];
99     int typelib_segment_block_length[MSFT_SEG_MAX];
100 
101     INT typelib_typeinfo_offsets[0x200]; /* Hope that's enough. */
102 
103     INT *typelib_namehash_segment;
104     INT *typelib_guidhash_segment;
105 
106     INT help_string_dll_offset;
107 
108     struct _msft_typeinfo_t *typeinfos;
109     struct _msft_typeinfo_t *last_typeinfo;
110 } msft_typelib_t;
111 
112 typedef struct _msft_typeinfo_t
113 {
114     msft_typelib_t *typelib;
115     MSFT_TypeInfoBase *typeinfo;
116 
117     int typekind;
118 
119     unsigned int var_data_allocated;
120     int *var_data;
121 
122     unsigned int func_data_allocated;
123     int *func_data;
124 
125     int vars_allocated;
126     int *var_indices;
127     int *var_names;
128     int *var_offsets;
129 
130     int funcs_allocated;
131     int *func_indices;
132     int *func_names;
133     int *func_offsets;
134 
135     int datawidth;
136 
137     struct _msft_typeinfo_t *next_typeinfo;
138 } msft_typeinfo_t;
139 
140 
141 
142 /*================== Internal functions ===================================*/
143 
144 /****************************************************************************
145  *	ctl2_init_header
146  *
147  *  Initializes the type library header of a new typelib.
148  */
149 static void ctl2_init_header(
150 	msft_typelib_t *typelib) /* [I] The typelib to initialize. */
151 {
152     typelib->typelib_header.magic1 = 0x5446534d;
153     typelib->typelib_header.magic2 = 0x00010002;
154     typelib->typelib_header.posguid = -1;
155     typelib->typelib_header.lcid = 0x0409;
156     typelib->typelib_header.lcid2 = 0x0;
157     typelib->typelib_header.varflags = 0x40;
158     typelib->typelib_header.version = 0;
159     typelib->typelib_header.flags = 0;
160     typelib->typelib_header.nrtypeinfos = 0;
161     typelib->typelib_header.helpstring = -1;
162     typelib->typelib_header.helpstringcontext = 0;
163     typelib->typelib_header.helpcontext = 0;
164     typelib->typelib_header.nametablecount = 0;
165     typelib->typelib_header.nametablechars = 0;
166     typelib->typelib_header.NameOffset = -1;
167     typelib->typelib_header.helpfile = -1;
168     typelib->typelib_header.CustomDataOffset = -1;
169     typelib->typelib_header.res44 = 0x20;
170     typelib->typelib_header.res48 = 0x80;
171     typelib->typelib_header.dispatchpos = -1;
172     typelib->typelib_header.nimpinfos = 0;
173 }
174 
175 /****************************************************************************
176  *	ctl2_init_segdir
177  *
178  *  Initializes the segment directory of a new typelib.
179  */
180 static void ctl2_init_segdir(
181 	msft_typelib_t *typelib) /* [I] The typelib to initialize. */
182 {
183     int i;
184     MSFT_pSeg *segdir;
185 
186     segdir = &typelib->typelib_segdir[MSFT_SEG_TYPEINFO];
187 
188     for (i = 0; i < MSFT_SEG_MAX; i++) {
189 	segdir[i].offset = -1;
190 	segdir[i].length = 0;
191 	segdir[i].res08 = -1;
192 	segdir[i].res0c = 0x0f;
193     }
194 }
195 
196 /****************************************************************************
197  *	ctl2_hash_guid
198  *
199  *  Generates a hash key from a GUID.
200  *
201  * RETURNS
202  *
203  *  The hash key for the GUID.
204  */
205 static int ctl2_hash_guid(
206 	REFGUID guid)                /* [I] The guid to hash. */
207 {
208     int hash;
209     int i;
210 
211     hash = 0;
212     for (i = 0; i < 8; i ++) {
213 	hash ^= ((const short *)guid)[i];
214     }
215 
216     return hash & 0x1f;
217 }
218 
219 /****************************************************************************
220  *	ctl2_find_guid
221  *
222  *  Locates a guid in a type library.
223  *
224  * RETURNS
225  *
226  *  The offset into the GUID segment of the guid, or -1 if not found.
227  */
228 static int ctl2_find_guid(
229 	msft_typelib_t *typelib,   /* [I] The typelib to operate against. */
230 	int hash_key,              /* [I] The hash key for the guid. */
231 	REFGUID guid)              /* [I] The guid to find. */
232 {
233     int offset;
234     MSFT_GuidEntry *guidentry;
235 
236     offset = typelib->typelib_guidhash_segment[hash_key];
237     while (offset != -1) {
238 	guidentry = (MSFT_GuidEntry *)&typelib->typelib_segment_data[MSFT_SEG_GUID][offset];
239 
240 	if (!memcmp(guidentry, guid, sizeof(GUID))) return offset;
241 
242 	offset = guidentry->next_hash;
243     }
244 
245     return offset;
246 }
247 
248 /****************************************************************************
249  *	ctl2_find_name
250  *
251  *  Locates a name in a type library.
252  *
253  * RETURNS
254  *
255  *  The offset into the NAME segment of the name, or -1 if not found.
256  *
257  * NOTES
258  *
259  *  The name must be encoded as with ctl2_encode_name().
260  */
261 static int ctl2_find_name(
262 	msft_typelib_t *typelib,   /* [I] The typelib to operate against. */
263 	char *name)                /* [I] The encoded name to find. */
264 {
265     int offset;
266     int *namestruct;
267 
268     offset = typelib->typelib_namehash_segment[name[2] & 0x7f];
269     while (offset != -1) {
270 	namestruct = (int *)&typelib->typelib_segment_data[MSFT_SEG_NAME][offset];
271 
272 	if (!((namestruct[2] ^ *((int *)name)) & 0xffff00ff)) {
273 	    /* hash codes and lengths match, final test */
274 	    if (!strncasecmp(name+4, (void *)(namestruct+3), name[0])) break;
275 	}
276 
277 	/* move to next item in hash bucket */
278 	offset = namestruct[1];
279     }
280 
281     return offset;
282 }
283 
284 /****************************************************************************
285  *	ctl2_encode_name
286  *
287  *  Encodes a name string to a form suitable for storing into a type library
288  *  or comparing to a name stored in a type library.
289  *
290  * RETURNS
291  *
292  *  The length of the encoded name, including padding and length+hash fields.
293  *
294  * NOTES
295  *
296  *  Will throw an exception if name or result are NULL. Is not multithread
297  *  safe in the slightest.
298  */
299 static int ctl2_encode_name(
300 	msft_typelib_t *typelib,   /* [I] The typelib to operate against (used for LCID only). */
301 	const char *name,          /* [I] The name string to encode. */
302 	char **result)             /* [O] A pointer to a pointer to receive the encoded name. */
303 {
304     int length;
305     static char converted_name[0x104];
306     int offset;
307     int value;
308 
309     length = strlen(name);
310     memcpy(converted_name + 4, name, length);
311 
312     converted_name[length + 4] = 0;
313 
314 
315     value = lhash_val_of_name_sys(typelib->typelib_header.varflags & 0x0f, typelib->typelib_header.lcid, converted_name + 4);
316 
317 #ifdef WORDS_BIGENDIAN
318     converted_name[3] = length & 0xff;
319     converted_name[2] = 0x00;
320     converted_name[1] = value;
321     converted_name[0] = value >> 8;
322 #else
323     converted_name[0] = length & 0xff;
324     converted_name[1] = 0x00;
325     converted_name[2] = value;
326     converted_name[3] = value >> 8;
327 #endif
328 
329     for (offset = (4 - length) & 3; offset; offset--) converted_name[length + offset + 3] = 0x57;
330 
331     *result = converted_name;
332 
333     return (length + 7) & ~3;
334 }
335 
336 /****************************************************************************
337  *	ctl2_encode_string
338  *
339  *  Encodes a string to a form suitable for storing into a type library or
340  *  comparing to a string stored in a type library.
341  *
342  * RETURNS
343  *
344  *  The length of the encoded string, including padding and length fields.
345  *
346  * NOTES
347  *
348  *  Will throw an exception if string or result are NULL. Is not multithread
349  *  safe in the slightest.
350  */
351 static int ctl2_encode_string(
352 	const char *string,        /* [I] The string to encode. */
353 	char **result)             /* [O] A pointer to a pointer to receive the encoded string. */
354 {
355     int length;
356     static char converted_string[0x104];
357     int offset;
358 
359     length = strlen(string);
360     memcpy(converted_string + 2, string, length);
361 
362 #ifdef WORDS_BIGENDIAN
363     converted_string[1] = length & 0xff;
364     converted_string[0] = (length >> 8) & 0xff;
365 #else
366     converted_string[0] = length & 0xff;
367     converted_string[1] = (length >> 8) & 0xff;
368 #endif
369 
370     if(length < 3) { /* strings of this length are padded with up to 8 bytes incl the 2 byte length */
371         for(offset = 0; offset < 4; offset++)
372             converted_string[length + offset + 2] = 0x57;
373         length += 4;
374     }
375     for (offset = (4 - (length + 2)) & 3; offset; offset--) converted_string[length + offset + 1] = 0x57;
376 
377     *result = converted_string;
378 
379     return (length + 5) & ~3;
380 }
381 
382 /****************************************************************************
383  *	ctl2_alloc_segment
384  *
385  *  Allocates memory from a segment in a type library.
386  *
387  * RETURNS
388  *
389  *  Success: The offset within the segment of the new data area.
390  *
391  * BUGS
392  *
393  *  Does not (yet) handle the case where the allocated segment memory needs to grow.
394  */
395 static int ctl2_alloc_segment(
396 	msft_typelib_t *typelib,         /* [I] The type library in which to allocate. */
397 	enum MSFT_segment_index segment, /* [I] The segment in which to allocate. */
398 	int size,                        /* [I] The amount to allocate. */
399 	int block_size)                  /* [I] Initial allocation block size, or 0 for default. */
400 {
401     int offset;
402 
403     if(!typelib->typelib_segment_data[segment]) {
404 	if (!block_size) block_size = 0x2000;
405 
406 	typelib->typelib_segment_block_length[segment] = block_size;
407 	typelib->typelib_segment_data[segment] = xmalloc(block_size);
408 	if (!typelib->typelib_segment_data[segment]) return -1;
409 	memset(typelib->typelib_segment_data[segment], 0x57, block_size);
410     }
411 
412     while ((typelib->typelib_segdir[segment].length + size) > typelib->typelib_segment_block_length[segment]) {
413 	unsigned char *block;
414 
415 	block_size = typelib->typelib_segment_block_length[segment];
416 	block = xrealloc(typelib->typelib_segment_data[segment], block_size << 1);
417 
418 	if (segment == MSFT_SEG_TYPEINFO) {
419 	    /* TypeInfos have a direct pointer to their memory space, so we have to fix them up. */
420 	    msft_typeinfo_t *typeinfo;
421 
422 	    for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
423 		typeinfo->typeinfo = (void *)&block[((unsigned char *)typeinfo->typeinfo) - typelib->typelib_segment_data[segment]];
424 	    }
425 	}
426 
427 	memset(block + block_size, 0x57, block_size);
428 	typelib->typelib_segment_block_length[segment] = block_size << 1;
429 	typelib->typelib_segment_data[segment] = block;
430     }
431 
432     offset = typelib->typelib_segdir[segment].length;
433     typelib->typelib_segdir[segment].length += size;
434 
435     return offset;
436 }
437 
438 /****************************************************************************
439  *	ctl2_alloc_typeinfo
440  *
441  *  Allocates and initializes a typeinfo structure in a type library.
442  *
443  * RETURNS
444  *
445  *  Success: The offset of the new typeinfo.
446  *  Failure: -1 (this is invariably an out of memory condition).
447  */
448 static int ctl2_alloc_typeinfo(
449 	msft_typelib_t *typelib,   /* [I] The type library to allocate in. */
450 	int nameoffset)            /* [I] The offset of the name for this typeinfo. */
451 {
452     int offset;
453     MSFT_TypeInfoBase *typeinfo;
454 
455     offset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEINFO, sizeof(MSFT_TypeInfoBase), 0);
456 
457     typelib->typelib_typeinfo_offsets[typelib->typelib_header.nrtypeinfos++] = offset;
458 
459     typeinfo = (void *)(typelib->typelib_segment_data[MSFT_SEG_TYPEINFO] + offset);
460 
461     typeinfo->typekind = (typelib->typelib_header.nrtypeinfos - 1) << 16;
462     typeinfo->memoffset = -1; /* should be EOF if no elements */
463     typeinfo->res2 = 0;
464     typeinfo->res3 = -1;
465     typeinfo->res4 = 3;
466     typeinfo->res5 = 0;
467     typeinfo->cElement = 0;
468     typeinfo->res7 = 0;
469     typeinfo->res8 = 0;
470     typeinfo->res9 = 0;
471     typeinfo->resA = 0;
472     typeinfo->posguid = -1;
473     typeinfo->flags = 0;
474     typeinfo->NameOffset = nameoffset;
475     typeinfo->version = 0;
476     typeinfo->docstringoffs = -1;
477     typeinfo->helpstringcontext = 0;
478     typeinfo->helpcontext = 0;
479     typeinfo->oCustData = -1;
480     typeinfo->cbSizeVft = 0;
481     typeinfo->cImplTypes = 0;
482     typeinfo->size = 0;
483     typeinfo->datatype1 = -1;
484     typeinfo->datatype2 = 0;
485     typeinfo->res18 = 0;
486     typeinfo->res19 = -1;
487 
488     return offset;
489 }
490 
491 /****************************************************************************
492  *	ctl2_alloc_guid
493  *
494  *  Allocates and initializes a GUID structure in a type library. Also updates
495  *  the GUID hash table as needed.
496  *
497  * RETURNS
498  *
499  *  Success: The offset of the new GUID.
500  */
501 static int ctl2_alloc_guid(
502 	msft_typelib_t *typelib,   /* [I] The type library to allocate in. */
503 	MSFT_GuidEntry *guid)      /* [I] The GUID to store. */
504 {
505     int offset;
506     MSFT_GuidEntry *guid_space;
507     int hash_key;
508 
509     chat("adding uuid {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
510          guid->guid.Data1, guid->guid.Data2, guid->guid.Data3,
511          guid->guid.Data4[0], guid->guid.Data4[1], guid->guid.Data4[2], guid->guid.Data4[3],
512          guid->guid.Data4[4], guid->guid.Data4[5], guid->guid.Data4[6], guid->guid.Data4[7]);
513 
514     hash_key = ctl2_hash_guid(&guid->guid);
515 
516     offset = ctl2_find_guid(typelib, hash_key, &guid->guid);
517     if (offset != -1)
518     {
519         if (is_warning_enabled(2368))
520             warning("duplicate uuid {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
521                     guid->guid.Data1, guid->guid.Data2, guid->guid.Data3,
522                     guid->guid.Data4[0], guid->guid.Data4[1], guid->guid.Data4[2], guid->guid.Data4[3],
523                     guid->guid.Data4[4], guid->guid.Data4[5], guid->guid.Data4[6], guid->guid.Data4[7]);
524         return -1;
525     }
526 
527     offset = ctl2_alloc_segment(typelib, MSFT_SEG_GUID, sizeof(MSFT_GuidEntry), 0);
528 
529     guid_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_GUID] + offset);
530     *guid_space = *guid;
531 
532     guid_space->next_hash = typelib->typelib_guidhash_segment[hash_key];
533     typelib->typelib_guidhash_segment[hash_key] = offset;
534 
535     return offset;
536 }
537 
538 /****************************************************************************
539  *	ctl2_alloc_name
540  *
541  *  Allocates and initializes a name within a type library. Also updates the
542  *  name hash table as needed.
543  *
544  * RETURNS
545  *
546  *  Success: The offset within the segment of the new name.
547  *  Failure: -1 (this is invariably an out of memory condition).
548  */
549 static int ctl2_alloc_name(
550 	msft_typelib_t *typelib,  /* [I] The type library to allocate in. */
551 	const char *name)         /* [I] The name to store. */
552 {
553     int length;
554     int offset;
555     MSFT_NameIntro *name_space;
556     char *encoded_name;
557 
558     length = ctl2_encode_name(typelib, name, &encoded_name);
559 
560     offset = ctl2_find_name(typelib, encoded_name);
561     if (offset != -1) return offset;
562 
563     offset = ctl2_alloc_segment(typelib, MSFT_SEG_NAME, length + 8, 0);
564 
565     name_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_NAME] + offset);
566     name_space->hreftype = -1;
567     name_space->next_hash = -1;
568     memcpy(&name_space->namelen, encoded_name, length);
569 
570     if (typelib->typelib_namehash_segment[encoded_name[2] & 0x7f] != -1)
571 	name_space->next_hash = typelib->typelib_namehash_segment[encoded_name[2] & 0x7f];
572 
573     typelib->typelib_namehash_segment[encoded_name[2] & 0x7f] = offset;
574 
575     typelib->typelib_header.nametablecount += 1;
576     typelib->typelib_header.nametablechars += *encoded_name;
577 
578     return offset;
579 }
580 
581 /****************************************************************************
582  *	ctl2_alloc_string
583  *
584  *  Allocates and initializes a string in a type library.
585  *
586  * RETURNS
587  *
588  *  Success: The offset within the segment of the new string.
589  *  Failure: -1 (this is invariably an out of memory condition).
590  */
591 static int ctl2_alloc_string(
592 	msft_typelib_t *typelib,  /* [I] The type library to allocate in. */
593 	const char *string)       /* [I] The string to store. */
594 {
595     int length;
596     int offset;
597     unsigned char *string_space;
598     char *encoded_string;
599 
600     length = ctl2_encode_string(string, &encoded_string);
601 
602     for (offset = 0; offset < typelib->typelib_segdir[MSFT_SEG_STRING].length;
603 	 offset += (((typelib->typelib_segment_data[MSFT_SEG_STRING][offset + 1] << 8) |
604 	      typelib->typelib_segment_data[MSFT_SEG_STRING][offset + 0]) + 5) & ~3) {
605 	if (!memcmp(encoded_string, typelib->typelib_segment_data[MSFT_SEG_STRING] + offset, length)) return offset;
606     }
607 
608     offset = ctl2_alloc_segment(typelib, MSFT_SEG_STRING, length, 0);
609 
610     string_space = typelib->typelib_segment_data[MSFT_SEG_STRING] + offset;
611     memcpy(string_space, encoded_string, length);
612 
613     return offset;
614 }
615 
616 /****************************************************************************
617  *	alloc_msft_importinfo
618  *
619  *  Allocates and initializes an import information structure in a type library.
620  *
621  * RETURNS
622  *
623  *  Success: The offset of the new importinfo.
624  *  Failure: -1 (this is invariably an out of memory condition).
625  */
626 static int alloc_msft_importinfo(
627         msft_typelib_t *typelib,   /* [I] The type library to allocate in. */
628         MSFT_ImpInfo *impinfo)     /* [I] The import information to store. */
629 {
630     int offset;
631     MSFT_ImpInfo *impinfo_space;
632 
633     for (offset = 0;
634 	 offset < typelib->typelib_segdir[MSFT_SEG_IMPORTINFO].length;
635 	 offset += sizeof(MSFT_ImpInfo)) {
636 	if (!memcmp(&(typelib->typelib_segment_data[MSFT_SEG_IMPORTINFO][offset]),
637 		    impinfo, sizeof(MSFT_ImpInfo))) {
638 	    return offset;
639 	}
640     }
641 
642     impinfo->flags |= typelib->typelib_header.nimpinfos++;
643 
644     offset = ctl2_alloc_segment(typelib, MSFT_SEG_IMPORTINFO, sizeof(MSFT_ImpInfo), 0);
645 
646     impinfo_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_IMPORTINFO] + offset);
647     *impinfo_space = *impinfo;
648 
649     return offset;
650 }
651 
652 /****************************************************************************
653  *	alloc_importfile
654  *
655  *  Allocates and initializes an import file definition in a type library.
656  *
657  * RETURNS
658  *
659  *  Success: The offset of the new importinfo.
660  *  Failure: -1 (this is invariably an out of memory condition).
661  */
662 static int alloc_importfile(
663         msft_typelib_t *typelib,   /* [I] The type library to allocate in. */
664         int guidoffset,            /* [I] The offset to the GUID for the imported library. */
665         int major_version,         /* [I] The major version number of the imported library. */
666         int minor_version,         /* [I] The minor version number of the imported library. */
667         const char *filename)      /* [I] The filename of the imported library. */
668 {
669     int length;
670     int offset;
671     MSFT_ImpFile *importfile;
672     char *encoded_string;
673 
674     length = ctl2_encode_string(filename, &encoded_string);
675 
676     encoded_string[0] <<= 2;
677     encoded_string[0] |= 1;
678 
679     for (offset = 0; offset < typelib->typelib_segdir[MSFT_SEG_IMPORTFILES].length;
680 	 offset += (((typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xd] << 8) |
681 	              typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xc]) >> 2) + 0xc) {
682 	if (!memcmp(encoded_string, typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES] + offset + 0xc, length)) return offset;
683     }
684 
685     offset = ctl2_alloc_segment(typelib, MSFT_SEG_IMPORTFILES, length + 0xc, 0);
686 
687     importfile = (MSFT_ImpFile *)&typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset];
688     importfile->guid = guidoffset;
689     importfile->lcid = typelib->typelib_header.lcid2;
690     importfile->version = major_version | (minor_version << 16);
691     memcpy(&importfile->filename, encoded_string, length);
692 
693     return offset;
694 }
695 
696 static void alloc_importinfo(msft_typelib_t *typelib, importinfo_t *importinfo)
697 {
698     importlib_t *importlib = importinfo->importlib;
699 
700     chat("alloc_importinfo: %s\n", importinfo->name);
701 
702     if(!importlib->allocated) {
703         MSFT_GuidEntry guid;
704         int guid_idx;
705 
706         chat("allocating importlib %s\n", importlib->name);
707 
708         importlib->allocated = -1;
709 
710         memcpy(&guid.guid, &importlib->guid, sizeof(GUID));
711         guid.hreftype = 2;
712 
713         guid_idx = ctl2_alloc_guid(typelib, &guid);
714 
715         alloc_importfile(typelib, guid_idx, importlib->version&0xffff,
716                          importlib->version>>16, importlib->name);
717     }
718 
719     if(importinfo->offset == -1 || !(importinfo->flags & MSFT_IMPINFO_OFFSET_IS_GUID)) {
720         MSFT_ImpInfo impinfo;
721 
722         impinfo.flags = importinfo->flags;
723         impinfo.oImpFile = 0;
724 
725         if(importinfo->flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
726             MSFT_GuidEntry guid;
727 
728             guid.hreftype = 0;
729             memcpy(&guid.guid, &importinfo->guid, sizeof(GUID));
730 
731             impinfo.oGuid = ctl2_alloc_guid(typelib, &guid);
732 
733             importinfo->offset = alloc_msft_importinfo(typelib, &impinfo);
734 
735             typelib->typelib_segment_data[MSFT_SEG_GUID][impinfo.oGuid+sizeof(GUID)]
736                 = importinfo->offset+1;
737 
738             if(!strcmp(importinfo->name, "IDispatch"))
739                 typelib->typelib_header.dispatchpos = importinfo->offset+1;
740         }else {
741             impinfo.oGuid = importinfo->id;
742             importinfo->offset = alloc_msft_importinfo(typelib, &impinfo);
743         }
744     }
745 }
746 
747 static importinfo_t *find_importinfo(msft_typelib_t *typelib, const char *name)
748 {
749     importlib_t *importlib;
750     int i;
751 
752     chat("search importlib %s\n", name);
753 
754     if(!name)
755         return NULL;
756 
757     LIST_FOR_EACH_ENTRY( importlib, &typelib->typelib->importlibs, importlib_t, entry )
758     {
759         for(i=0; i < importlib->ntypeinfos; i++) {
760             if(!strcmp(name, importlib->importinfos[i].name)) {
761                 chat("Found %s in importlib.\n", name);
762                 return importlib->importinfos+i;
763             }
764         }
765     }
766 
767     return NULL;
768 }
769 
770 static void add_structure_typeinfo(msft_typelib_t *typelib, type_t *structure);
771 static void add_interface_typeinfo(msft_typelib_t *typelib, type_t *interface);
772 static void add_enum_typeinfo(msft_typelib_t *typelib, type_t *enumeration);
773 static void add_union_typeinfo(msft_typelib_t *typelib, type_t *tunion);
774 static void add_coclass_typeinfo(msft_typelib_t *typelib, type_t *cls);
775 static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinterface);
776 
777 
778 /****************************************************************************
779  *	encode_type
780  *
781  *  Encodes a type, storing information in the TYPEDESC and ARRAYDESC
782  *  segments as needed.
783  *
784  * RETURNS
785  *
786  *  Success: 0.
787  *  Failure: -1.
788  */
789 static int encode_type(
790 	msft_typelib_t *typelib,   /* [I] The type library in which to encode the TYPEDESC. */
791         int vt,                    /* [I] vt to encode */
792 	type_t *type,              /* [I] type */
793 	int *encoded_type,         /* [O] The encoded type description. */
794 	int *width,                /* [O] The width of the type, or NULL. */
795 	int *alignment,            /* [O] The alignment of the type, or NULL. */
796 	int *decoded_size)         /* [O] The total size of the unencoded TYPEDESCs, including nested descs. */
797 {
798     int default_type;
799     int scratch;
800     int typeoffset;
801     int *typedata;
802     int target_type;
803     int child_size = 0;
804 
805     chat("encode_type vt %d type %p\n", vt, type);
806 
807     default_type = 0x80000000 | (vt << 16) | vt;
808     if (!width) width = &scratch;
809     if (!alignment) alignment = &scratch;
810     if (!decoded_size) decoded_size = &scratch;
811 
812     *decoded_size = 0;
813 
814     switch (vt) {
815     case VT_I1:
816     case VT_UI1:
817 	*encoded_type = default_type;
818 	*width = 1;
819 	*alignment = 1;
820 	break;
821 
822     case VT_INT:
823 	*encoded_type = 0x80000000 | (VT_I4 << 16) | VT_INT;
824 	if ((typelib->typelib_header.varflags & 0x0f) == SYS_WIN16) {
825 	    *width = 2;
826 	    *alignment = 2;
827 	} else {
828 	    *width = 4;
829 	    *alignment = 4;
830 	}
831 	break;
832 
833     case VT_UINT:
834 	*encoded_type = 0x80000000 | (VT_UI4 << 16) | VT_UINT;
835 	if ((typelib->typelib_header.varflags & 0x0f) == SYS_WIN16) {
836 	    *width = 2;
837 	    *alignment = 2;
838 	} else {
839 	    *width = 4;
840 	    *alignment = 4;
841 	}
842 	break;
843 
844     case VT_UI2:
845     case VT_I2:
846     case VT_BOOL:
847 	*encoded_type = default_type;
848 	*width = 2;
849 	*alignment = 2;
850 	break;
851 
852     case VT_I4:
853     case VT_UI4:
854     case VT_R4:
855     case VT_ERROR:
856     case VT_HRESULT:
857 	*encoded_type = default_type;
858 	*width = 4;
859 	*alignment = 4;
860 	break;
861 
862     case VT_R8:
863     case VT_I8:
864     case VT_UI8:
865 	*encoded_type = default_type;
866 	*width = 8;
867 	*alignment = 8;
868 	break;
869 
870     case VT_CY:
871     case VT_DATE:
872 	*encoded_type = default_type;
873 	*width = 8;
874 	*alignment = 8;
875 	break;
876 
877     case VT_DECIMAL:
878         *encoded_type = default_type;
879         *width = 16;
880         *alignment = 8;
881         break;
882 
883     case VT_VOID:
884 	*encoded_type = 0x80000000 | (VT_EMPTY << 16) | vt;
885 	*width = 0;
886 	*alignment = 1;
887 	break;
888 
889     case VT_UNKNOWN:
890     case VT_DISPATCH:
891     case VT_BSTR:
892         *encoded_type = default_type;
893         *width = pointer_size;
894         *alignment = 4;
895         break;
896 
897     case VT_VARIANT:
898         *encoded_type = default_type;
899         *width = 8 + 2 * pointer_size;
900         *alignment = 8;
901         break;
902 
903     case VT_LPSTR:
904     case VT_LPWSTR:
905         *encoded_type = 0xfffe0000 | vt;
906         *width = pointer_size;
907         *alignment = 4;
908         break;
909 
910     case VT_PTR:
911       {
912         int next_vt;
913         for(next_vt = 0; is_ptr(type); type = type_pointer_get_ref(type)) {
914             next_vt = get_type_vt(type_pointer_get_ref(type));
915             if (next_vt != 0)
916                 break;
917         }
918         /* if no type found then it must be void */
919         if (next_vt == 0)
920             next_vt = VT_VOID;
921 
922         encode_type(typelib, next_vt, type_pointer_get_ref(type),
923                     &target_type, NULL, NULL, &child_size);
924         /* these types already have an implicit pointer, so we don't need to
925          * add another */
926         if(next_vt == VT_DISPATCH || next_vt == VT_UNKNOWN) {
927             chat("encode_type: skipping ptr\n");
928             *encoded_type = target_type;
929             *width = pointer_size;
930             *alignment = 4;
931             *decoded_size = child_size;
932             break;
933         }
934 
935 	for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
936 	    typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
937 	    if (((typedata[0] & 0xffff) == VT_PTR) && (typedata[1] == target_type)) break;
938 	}
939 
940 	if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
941 	    int mix_field;
942 
943 	    if (target_type & 0x80000000) {
944 		mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF;
945 	    } else {
946 		typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
947 		mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
948 	    }
949 
950 	    typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
951 	    typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
952 
953 	    typedata[0] = (mix_field << 16) | VT_PTR;
954 	    typedata[1] = target_type;
955 	}
956 
957 	*encoded_type = typeoffset;
958 
959 	*width = pointer_size;
960 	*alignment = 4;
961 	*decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
962         break;
963     }
964 
965     case VT_SAFEARRAY:
966 	{
967 	type_t *element_type = type_alias_get_aliasee(type_array_get_element(type));
968 	int next_vt = get_type_vt(element_type);
969 
970 	encode_type(typelib, next_vt, type_alias_get_aliasee(type_array_get_element(type)), &target_type, NULL, NULL, &child_size);
971 
972 	for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
973 	    typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
974 	    if (((typedata[0] & 0xffff) == VT_SAFEARRAY) && (typedata[1] == target_type)) break;
975 	}
976 
977 	if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
978 	    int mix_field;
979 
980 	    if (target_type & 0x80000000) {
981 		mix_field = ((target_type >> 16) & VT_TYPEMASK) | VT_ARRAY;
982 	    } else {
983 		typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
984 		mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
985 	    }
986 
987 	    typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
988 	    typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
989 
990 	    typedata[0] = (mix_field << 16) | VT_SAFEARRAY;
991 	    typedata[1] = target_type;
992 	}
993 
994 	*encoded_type = typeoffset;
995 
996 	*width = pointer_size;
997 	*alignment = 4;
998 	*decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
999 	break;
1000 	}
1001 
1002     case VT_USERDEFINED:
1003       {
1004         int typeinfo_offset;
1005 
1006         /* typedef'd types without public attribute aren't included in the typelib */
1007         while (type->typelib_idx < 0 && type_is_alias(type) && !is_attr(type->attrs, ATTR_PUBLIC))
1008           type = type_alias_get_aliasee(type);
1009 
1010         chat("encode_type: VT_USERDEFINED - type %p name = %s real type %d idx %d\n", type,
1011              type->name, type_get_type(type), type->typelib_idx);
1012 
1013         if(type->typelib_idx == -1) {
1014             chat("encode_type: trying to ref not added type\n");
1015             switch (type_get_type(type)) {
1016             case TYPE_STRUCT:
1017                 add_structure_typeinfo(typelib, type);
1018                 break;
1019             case TYPE_INTERFACE:
1020                 add_interface_typeinfo(typelib, type);
1021                 break;
1022             case TYPE_ENUM:
1023                 add_enum_typeinfo(typelib, type);
1024                 break;
1025             case TYPE_UNION:
1026                 add_union_typeinfo(typelib, type);
1027                 break;
1028             case TYPE_COCLASS:
1029                 add_coclass_typeinfo(typelib, type);
1030                 break;
1031             default:
1032                 error("encode_type: VT_USERDEFINED - unhandled type %d\n",
1033                       type_get_type(type));
1034             }
1035         }
1036 
1037         typeinfo_offset = typelib->typelib_typeinfo_offsets[type->typelib_idx];
1038 	for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
1039 	    typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
1040 	    if ((typedata[0] == ((0x7fff << 16) | VT_USERDEFINED)) && (typedata[1] == typeinfo_offset)) break;
1041 	}
1042 
1043 	if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
1044 	    typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
1045 	    typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
1046 
1047 	    typedata[0] = (0x7fff << 16) | VT_USERDEFINED;
1048 	    typedata[1] = typeinfo_offset;
1049 	}
1050 
1051 	*encoded_type = typeoffset;
1052 	*width = 0;
1053 	*alignment = 1;
1054         break;
1055       }
1056 
1057     default:
1058 	error("encode_type: unrecognized type %d.\n", vt);
1059 	*encoded_type = default_type;
1060 	*width = 0;
1061 	*alignment = 1;
1062 	break;
1063     }
1064 
1065     return 0;
1066 }
1067 
1068 static void dump_type(type_t *t)
1069 {
1070     chat("dump_type: %p name %s type %d attrs %p\n", t, t->name, type_get_type(t), t->attrs);
1071 }
1072 
1073 static int encode_var(
1074 	msft_typelib_t *typelib,   /* [I] The type library in which to encode the TYPEDESC. */
1075 	type_t *type,              /* [I] The type description to encode. */
1076 	var_t *var,                /* [I] The var to encode. */
1077 	int *encoded_type,         /* [O] The encoded type description. */
1078 	int *width,                /* [O] The width of the type, or NULL. */
1079 	int *alignment,            /* [O] The alignment of the type, or NULL. */
1080 	int *decoded_size)         /* [O] The total size of the unencoded TYPEDESCs, including nested descs. */
1081 {
1082     int typeoffset;
1083     int *typedata;
1084     int target_type;
1085     int child_size;
1086     int vt;
1087     int scratch;
1088 
1089     if (!width) width = &scratch;
1090     if (!alignment) alignment = &scratch;
1091     if (!decoded_size) decoded_size = &scratch;
1092     *decoded_size = 0;
1093 
1094     chat("encode_var: var %p type %p type->name %s\n",
1095          var, type, type->name ? type->name : "NULL");
1096 
1097     if (is_array(type) && !type_array_is_decl_as_ptr(type)) {
1098         int num_dims, elements = 1, arrayoffset;
1099         type_t *atype;
1100         int *arraydata;
1101 
1102         num_dims = 0;
1103         for (atype = type;
1104              is_array(atype) && !type_array_is_decl_as_ptr(atype);
1105              atype = type_array_get_element(atype))
1106             ++num_dims;
1107 
1108         chat("array with %d dimensions\n", num_dims);
1109         encode_var(typelib, atype, var, &target_type, width, alignment, NULL);
1110         arrayoffset = ctl2_alloc_segment(typelib, MSFT_SEG_ARRAYDESC, (2 + 2 * num_dims) * sizeof(int), 0);
1111         arraydata = (void *)&typelib->typelib_segment_data[MSFT_SEG_ARRAYDESC][arrayoffset];
1112 
1113         arraydata[0] = target_type;
1114         arraydata[1] = num_dims;
1115         arraydata[1] |= ((num_dims * 2 * sizeof(int)) << 16);
1116 
1117         arraydata += 2;
1118         for (atype = type;
1119              is_array(atype) && !type_array_is_decl_as_ptr(atype);
1120              atype = type_array_get_element(atype))
1121         {
1122             arraydata[0] = type_array_get_dim(atype);
1123             arraydata[1] = 0;
1124             arraydata += 2;
1125             elements *= type_array_get_dim(atype);
1126         }
1127 
1128         typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
1129         typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
1130 
1131         typedata[0] = (0x7ffe << 16) | VT_CARRAY;
1132         typedata[1] = arrayoffset;
1133 
1134         *encoded_type = typeoffset;
1135         *width = *width * elements;
1136         *decoded_size = 20 /*sizeof(ARRAYDESC)*/ + (num_dims - 1) * 8 /*sizeof(SAFEARRAYBOUND)*/;
1137         return 0;
1138     }
1139 
1140     vt = get_type_vt(type);
1141     if (vt == VT_PTR) {
1142         type_t *ref = is_ptr(type) ?
1143             type_pointer_get_ref(type) : type_array_get_element(type);
1144         int skip_ptr = encode_var(typelib, ref, var,
1145                                   &target_type, NULL, NULL, &child_size);
1146 
1147         if(skip_ptr == 2) {
1148             chat("encode_var: skipping ptr\n");
1149             *encoded_type = target_type;
1150             *decoded_size = child_size;
1151             *width = pointer_size;
1152             *alignment = 4;
1153             return 0;
1154         }
1155 
1156 	for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
1157 	    typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
1158 	    if (((typedata[0] & 0xffff) == VT_PTR) && (typedata[1] == target_type)) break;
1159 	}
1160 
1161 	if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
1162 	    int mix_field;
1163 
1164 	    if (target_type & 0x80000000) {
1165 		mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF;
1166 	    } else if (is_array(ref)) {
1167 		type_t *element_type = type_alias_get_aliasee(type_array_get_element(ref));
1168 		mix_field = get_type_vt(element_type) | VT_ARRAY | VT_BYREF;
1169 	    } else {
1170 		typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
1171 		mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
1172 	    }
1173 
1174 	    typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
1175 	    typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
1176 
1177 	    typedata[0] = (mix_field << 16) | VT_PTR;
1178 	    typedata[1] = target_type;
1179 	}
1180 
1181 	*encoded_type = typeoffset;
1182 
1183 	*width = pointer_size;
1184 	*alignment = 4;
1185 	*decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
1186         return 0;
1187     }
1188 
1189     dump_type(type);
1190 
1191     encode_type(typelib, vt, type, encoded_type, width, alignment, decoded_size);
1192     /* these types already have an implicit pointer, so we don't need to
1193      * add another */
1194     if(vt == VT_DISPATCH || vt == VT_UNKNOWN) return 2;
1195     return 0;
1196 }
1197 
1198 static unsigned int get_ulong_val(unsigned int val, int vt)
1199 {
1200     switch(vt) {
1201     case VT_I2:
1202     case VT_BOOL:
1203     case VT_UI2:
1204         return val & 0xffff;
1205     case VT_I1:
1206     case VT_UI1:
1207         return val & 0xff;
1208     }
1209 
1210     return val;
1211 }
1212 
1213 static void write_value(msft_typelib_t* typelib, int *out, int vt, const void *value)
1214 {
1215     switch(vt) {
1216     case VT_I2:
1217     case VT_I4:
1218     case VT_R4:
1219     case VT_BOOL:
1220     case VT_I1:
1221     case VT_UI1:
1222     case VT_UI2:
1223     case VT_UI4:
1224     case VT_INT:
1225     case VT_UINT:
1226     case VT_HRESULT:
1227     case VT_PTR:
1228     case VT_UNKNOWN:
1229     case VT_DISPATCH:
1230       {
1231         const unsigned int lv = get_ulong_val(*(const unsigned int *)value, vt);
1232         if((lv & 0x3ffffff) == lv) {
1233             *out = 0x80000000;
1234             *out |= vt << 26;
1235             *out |= lv;
1236         } else {
1237             int offset = ctl2_alloc_segment(typelib, MSFT_SEG_CUSTDATA, 8, 0);
1238             *((unsigned short *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset]) = vt;
1239             memcpy(&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+2], value, 4);
1240             *((unsigned short *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+6]) = 0x5757;
1241             *out = offset;
1242         }
1243         return;
1244       }
1245     case VT_BSTR:
1246       {
1247         const char *s = (const char *) value;
1248         int len = strlen(s), seg_len = (len + 6 + 3) & ~0x3;
1249         int offset = ctl2_alloc_segment(typelib, MSFT_SEG_CUSTDATA, seg_len, 0);
1250         *((unsigned short *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset]) = vt;
1251         memcpy(&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+2], &len, sizeof(len));
1252         memcpy(&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+6], value, len);
1253         len += 6;
1254         while(len < seg_len) {
1255             *((char *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+len]) = 0x57;
1256             len++;
1257         }
1258         *out = offset;
1259         return;
1260       }
1261 
1262     default:
1263         warning("can't write value of type %d yet\n", vt);
1264     }
1265     return;
1266 }
1267 
1268 static HRESULT set_custdata(msft_typelib_t *typelib, REFGUID guid,
1269                             int vt, const void *value, int *offset)
1270 {
1271     MSFT_GuidEntry guidentry;
1272     int guidoffset;
1273     int custoffset;
1274     int *custdata;
1275     int data_out;
1276 
1277     guidentry.guid = *guid;
1278 
1279     guidentry.hreftype = -1;
1280     guidentry.next_hash = -1;
1281 
1282     guidoffset = ctl2_alloc_guid(typelib, &guidentry);
1283     write_value(typelib, &data_out, vt, value);
1284 
1285     custoffset = ctl2_alloc_segment(typelib, MSFT_SEG_CUSTDATAGUID, 12, 0);
1286 
1287     custdata = (int *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATAGUID][custoffset];
1288     custdata[0] = guidoffset;
1289     custdata[1] = data_out;
1290     custdata[2] = *offset;
1291     *offset = custoffset;
1292 
1293     return S_OK;
1294 }
1295 
1296 /* It's possible to have a default value for pointer arguments too.
1297    In this case default value has a referenced type, e.g.
1298    'LONG*' argument gets VT_I4, 'DOUBLE*' - VT_R8. IUnknown* and IDispatch*
1299    are recognised too and stored as VT_UNKNOWN and VT_DISPATCH.
1300    But IUnknown/IDispatch arguments can only have default value of 0
1301    (or expression that resolves to zero) while other pointers can have
1302    any default value. */
1303 static int get_defaultvalue_vt(type_t *type)
1304 {
1305     int vt;
1306     if (type_get_type(type) == TYPE_ENUM)
1307         vt = VT_I4;
1308     else
1309    {
1310         vt = get_type_vt(type);
1311         if (vt == VT_PTR && is_ptr(type)) {
1312             vt = get_type_vt(type_pointer_get_ref(type));
1313             /* The only acceptable value for pointers to non-basic types
1314                is NULL, it's stored as VT_I4 for both 32 and 64 bit typelibs. */
1315             if (vt == VT_USERDEFINED)
1316                 vt = VT_I4;
1317         }
1318     }
1319 
1320     return vt;
1321 }
1322 
1323 static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index)
1324 {
1325     int offset, name_offset;
1326     int *typedata, typedata_size;
1327     int i, id, next_idx;
1328     int decoded_size, extra_attr = 0;
1329     int num_params = 0, num_optional = 0, num_defaults = 0;
1330     var_t *arg;
1331     unsigned char *namedata;
1332     const attr_t *attr;
1333     unsigned int funcflags = 0, callconv = 4 /* CC_STDCALL */;
1334     unsigned int funckind, invokekind = 1 /* INVOKE_FUNC */;
1335     int help_context = 0, help_string_context = 0, help_string_offset = -1;
1336     int entry = -1, entry_is_ord = 0;
1337     int lcid_retval_count = 0;
1338 
1339     chat("add_func_desc(%p,%d)\n", typeinfo, index);
1340 
1341     id = ((0x6000 | (typeinfo->typeinfo->datatype2 & 0xffff)) << 16) | index;
1342 
1343     switch(typeinfo->typekind) {
1344     case TKIND_DISPATCH:
1345         funckind = 0x4; /* FUNC_DISPATCH */
1346         break;
1347     case TKIND_MODULE:
1348         funckind = 0x3; /* FUNC_STATIC */
1349         break;
1350     default:
1351         funckind = 0x1; /* FUNC_PUREVIRTUAL */
1352         break;
1353     }
1354 
1355     if (is_local( func->attrs )) {
1356         chat("add_func_desc: skipping local function\n");
1357         return S_FALSE;
1358     }
1359 
1360     if (type_get_function_args(func->type))
1361       LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), var_t, entry )
1362       {
1363         num_params++;
1364         if (arg->attrs) LIST_FOR_EACH_ENTRY( attr, arg->attrs, const attr_t, entry ) {
1365             if(attr->type == ATTR_DEFAULTVALUE)
1366                 num_defaults++;
1367             else if(attr->type == ATTR_OPTIONAL)
1368                 num_optional++;
1369         }
1370       }
1371 
1372     chat("add_func_desc: num of params %d\n", num_params);
1373 
1374     name_offset = ctl2_alloc_name(typeinfo->typelib, func->name);
1375 
1376     if (func->attrs) LIST_FOR_EACH_ENTRY( attr, func->attrs, const attr_t, entry ) {
1377         expr_t *expr = attr->u.pval;
1378         switch(attr->type) {
1379         case ATTR_BINDABLE:
1380             funcflags |= 0x4; /* FUNCFLAG_FBINDABLE */
1381             break;
1382         case ATTR_DEFAULTBIND:
1383             funcflags |= 0x20; /* FUNCFLAG_FDEFAULTBIND */
1384             break;
1385         case ATTR_DEFAULTCOLLELEM:
1386             funcflags |= 0x100; /* FUNCFLAG_FDEFAULTCOLLELEM */
1387             break;
1388         case ATTR_DISPLAYBIND:
1389             funcflags |= 0x10; /* FUNCFLAG_FDISPLAYBIND */
1390             break;
1391         case ATTR_ENTRY:
1392             extra_attr = max(extra_attr, 3);
1393             if (expr->type == EXPR_STRLIT || expr->type == EXPR_WSTRLIT)
1394               entry = ctl2_alloc_string(typeinfo->typelib, attr->u.pval);
1395             else {
1396               entry = expr->cval;
1397               entry_is_ord = 1;
1398             }
1399             break;
1400         case ATTR_HELPCONTEXT:
1401             extra_attr = max(extra_attr, 1);
1402             help_context = expr->u.lval;
1403             break;
1404         case ATTR_HELPSTRING:
1405             extra_attr = max(extra_attr, 2);
1406             help_string_offset = ctl2_alloc_string(typeinfo->typelib, attr->u.pval);
1407             break;
1408         case ATTR_HELPSTRINGCONTEXT:
1409             extra_attr = max(extra_attr, 6);
1410             help_string_context = expr->u.lval;
1411             break;
1412         case ATTR_HIDDEN:
1413             funcflags |= 0x40; /* FUNCFLAG_FHIDDEN */
1414             break;
1415         case ATTR_ID:
1416             id = expr->cval;
1417             break;
1418         case ATTR_IMMEDIATEBIND:
1419             funcflags |= 0x1000; /* FUNCFLAG_FIMMEDIATEBIND */
1420             break;
1421         case ATTR_NONBROWSABLE:
1422             funcflags |= 0x400; /* FUNCFLAG_FNONBROWSABLE */
1423             break;
1424         case ATTR_OUT:
1425             break;
1426         case ATTR_PROPGET:
1427             invokekind = 0x2; /* INVOKE_PROPERTYGET */
1428             break;
1429         case ATTR_PROPPUT:
1430             invokekind = 0x4; /* INVOKE_PROPERTYPUT */
1431             break;
1432         case ATTR_PROPPUTREF:
1433             invokekind = 0x8; /* INVOKE_PROPERTYPUTREF */
1434             break;
1435         /* FIXME: FUNCFLAG_FREPLACEABLE */
1436         case ATTR_REQUESTEDIT:
1437             funcflags |= 0x8; /* FUNCFLAG_FREQUESTEDIT */
1438             break;
1439         case ATTR_RESTRICTED:
1440             funcflags |= 0x1; /* FUNCFLAG_FRESTRICTED */
1441             break;
1442         case ATTR_SOURCE:
1443             funcflags |= 0x2; /* FUNCFLAG_FSOURCE */
1444             break;
1445         case ATTR_UIDEFAULT:
1446             funcflags |= 0x200; /* FUNCFLAG_FUIDEFAULT */
1447             break;
1448         case ATTR_USESGETLASTERROR:
1449             funcflags |= 0x80; /* FUNCFLAG_FUSESGETLASTERROR */
1450             break;
1451         case ATTR_VARARG:
1452             if (num_optional || num_defaults)
1453                 warning("add_func_desc: ignoring vararg in function with optional or defaultvalue params\n");
1454             else
1455                 num_optional = -1;
1456             break;
1457         default:
1458             break;
1459         }
1460     }
1461 
1462     /* allocate type data space for us */
1463     typedata_size = 0x18 + extra_attr * sizeof(int) + (num_params * (num_defaults ? 16 : 12));
1464 
1465     if (!typeinfo->func_data) {
1466         typeinfo->func_data = xmalloc(0x100);
1467         typeinfo->func_data_allocated = 0x100;
1468         typeinfo->func_data[0] = 0;
1469     }
1470 
1471     if(typeinfo->func_data[0] + typedata_size + sizeof(int) > typeinfo->func_data_allocated) {
1472         typeinfo->func_data_allocated = max(typeinfo->func_data_allocated * 2,
1473                                             typeinfo->func_data[0] + typedata_size + sizeof(int));
1474         typeinfo->func_data = xrealloc(typeinfo->func_data, typeinfo->func_data_allocated);
1475     }
1476 
1477     offset = typeinfo->func_data[0];
1478     typeinfo->func_data[0] += typedata_size;
1479     typedata = typeinfo->func_data + (offset >> 2) + 1;
1480 
1481 
1482     /* find func with the same name - if it exists use its id */
1483     for(i = 0; i < (typeinfo->typeinfo->cElement & 0xffff); i++) {
1484         if(name_offset == typeinfo->func_names[i]) {
1485             id = typeinfo->func_indices[i];
1486             break;
1487         }
1488     }
1489 
1490     /* find the first func with the same id and link via the hiword of typedata[4] */
1491     next_idx = index;
1492     for(i = 0; i < (typeinfo->typeinfo->cElement & 0xffff); i++) {
1493         if(id == typeinfo->func_indices[i]) {
1494             next_idx = typeinfo->func_data[(typeinfo->func_offsets[i] >> 2) + 1 + 4] >> 16;
1495             typeinfo->func_data[(typeinfo->func_offsets[i] >> 2) + 1 + 4] &= 0xffff;
1496             typeinfo->func_data[(typeinfo->func_offsets[i] >> 2) + 1 + 4] |= (index << 16);
1497             break;
1498         }
1499     }
1500 
1501     /* fill out the basic type information */
1502     typedata[0] = typedata_size | (index << 16);
1503     encode_var(typeinfo->typelib, type_function_get_rettype(func->type), func, &typedata[1], NULL, NULL, &decoded_size);
1504     typedata[2] = funcflags;
1505     typedata[3] = ((52 /*sizeof(FUNCDESC)*/ + decoded_size) << 16) | typeinfo->typeinfo->cbSizeVft;
1506     typedata[4] = (next_idx << 16) | (callconv << 8) | (invokekind << 3) | funckind;
1507     if(num_defaults) typedata[4] |= 0x1000;
1508     if(entry_is_ord) typedata[4] |= 0x2000;
1509     typedata[5] = (num_optional << 16) | num_params;
1510 
1511     /* NOTE: High word of typedata[3] is total size of FUNCDESC + size of all ELEMDESCs for params + TYPEDESCs for pointer params and return types. */
1512     /* That is, total memory allocation required to reconstitute the FUNCDESC in its entirety. */
1513     typedata[3] += (16 /*sizeof(ELEMDESC)*/ * num_params) << 16;
1514     typedata[3] += (24 /*sizeof(PARAMDESCEX)*/ * num_defaults) << 16;
1515 
1516     switch(extra_attr) {
1517     case 6: typedata[11] = help_string_context;
1518     case 5: typedata[10] = -1;
1519     case 4: typedata[9] = -1;
1520     case 3: typedata[8] = entry;
1521     case 2: typedata[7] = help_string_offset;
1522     case 1: typedata[6] = help_context;
1523     case 0:
1524         break;
1525     default:
1526         warning("unknown number of optional attrs\n");
1527     }
1528 
1529     if (type_get_function_args(func->type))
1530     {
1531       i = 0;
1532       LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), var_t, entry )
1533       {
1534         int paramflags = 0;
1535         int *paramdata = typedata + 6 + extra_attr + (num_defaults ? num_params : 0) + i * 3;
1536         int *defaultdata = num_defaults ? typedata + 6 + extra_attr + i : NULL;
1537 
1538         if(defaultdata) *defaultdata = -1;
1539 
1540 	encode_var(typeinfo->typelib, arg->type, arg, paramdata, NULL, NULL, &decoded_size);
1541         if (arg->attrs) LIST_FOR_EACH_ENTRY( attr, arg->attrs, const attr_t, entry ) {
1542             switch(attr->type) {
1543             case ATTR_DEFAULTVALUE:
1544               {
1545                 int vt;
1546                 expr_t *expr = (expr_t *)attr->u.pval;
1547                 vt = get_defaultvalue_vt(arg->type);
1548                 paramflags |= 0x30; /* PARAMFLAG_FHASDEFAULT | PARAMFLAG_FOPT */
1549                 if (expr->type == EXPR_STRLIT || expr->type == EXPR_WSTRLIT)
1550                 {
1551                   if (vt != VT_BSTR) error("string default value applied to non-string type\n");
1552                   chat("default value '%s'\n", expr->u.sval);
1553                   write_value(typeinfo->typelib, defaultdata, vt, expr->u.sval);
1554                 }
1555                 else
1556                 {
1557                   chat("default value %d\n", expr->cval);
1558                   write_value(typeinfo->typelib, defaultdata, vt, &expr->cval);
1559                 }
1560                 break;
1561               }
1562             case ATTR_IN:
1563                 paramflags |= 0x01; /* PARAMFLAG_FIN */
1564                 break;
1565             case ATTR_OPTIONAL:
1566                 paramflags |= 0x10; /* PARAMFLAG_FOPT */
1567                 break;
1568             case ATTR_OUT:
1569                 paramflags |= 0x02; /* PARAMFLAG_FOUT */
1570                 break;
1571             case ATTR_PARAMLCID:
1572                 paramflags |= 0x04; /* PARAMFLAG_LCID */
1573                 lcid_retval_count++;
1574                 break;
1575             case ATTR_RETVAL:
1576                 paramflags |= 0x08; /* PARAMFLAG_FRETVAL */
1577                 lcid_retval_count++;
1578                 break;
1579             default:
1580                 chat("unhandled param attr %d\n", attr->type);
1581                 break;
1582             }
1583         }
1584 	paramdata[1] = -1;
1585 	paramdata[2] = paramflags;
1586 	typedata[3] += decoded_size << 16;
1587 
1588         i++;
1589       }
1590     }
1591 
1592     if(lcid_retval_count == 1)
1593         typedata[4] |= 0x4000;
1594     else if(lcid_retval_count == 2)
1595         typedata[4] |= 0x8000;
1596 
1597     if(typeinfo->funcs_allocated == 0) {
1598         typeinfo->funcs_allocated = 10;
1599         typeinfo->func_indices = xmalloc(typeinfo->funcs_allocated * sizeof(int));
1600         typeinfo->func_names   = xmalloc(typeinfo->funcs_allocated * sizeof(int));
1601         typeinfo->func_offsets = xmalloc(typeinfo->funcs_allocated * sizeof(int));
1602     }
1603     if(typeinfo->funcs_allocated == (typeinfo->typeinfo->cElement & 0xffff)) {
1604         typeinfo->funcs_allocated *= 2;
1605         typeinfo->func_indices = xrealloc(typeinfo->func_indices, typeinfo->funcs_allocated * sizeof(int));
1606         typeinfo->func_names   = xrealloc(typeinfo->func_names,   typeinfo->funcs_allocated * sizeof(int));
1607         typeinfo->func_offsets = xrealloc(typeinfo->func_offsets, typeinfo->funcs_allocated * sizeof(int));
1608     }
1609 
1610     /* update the index data */
1611     typeinfo->func_indices[typeinfo->typeinfo->cElement & 0xffff] = id;
1612     typeinfo->func_offsets[typeinfo->typeinfo->cElement & 0xffff] = offset;
1613     typeinfo->func_names[typeinfo->typeinfo->cElement & 0xffff] = name_offset;
1614 
1615     /* ??? */
1616     if (!typeinfo->typeinfo->res2) typeinfo->typeinfo->res2 = 0x20;
1617     typeinfo->typeinfo->res2 <<= 1;
1618     /* ??? */
1619     if (index < 2) typeinfo->typeinfo->res2 += num_params << 4;
1620 
1621     if (typeinfo->typeinfo->res3 == -1) typeinfo->typeinfo->res3 = 0;
1622     typeinfo->typeinfo->res3 += 0x38 + num_params * 0x10;
1623     if(num_defaults) typeinfo->typeinfo->res3 += num_params * 0x4;
1624 
1625     /* adjust size of VTBL */
1626     if(funckind != 0x3 /* FUNC_STATIC */)
1627         typeinfo->typeinfo->cbSizeVft += pointer_size;
1628 
1629     /* Increment the number of function elements */
1630     typeinfo->typeinfo->cElement += 1;
1631 
1632     namedata = typeinfo->typelib->typelib_segment_data[MSFT_SEG_NAME] + name_offset;
1633     if (*((INT *)namedata) == -1) {
1634 	*((INT *)namedata) = typeinfo->typelib->typelib_typeinfo_offsets[typeinfo->typeinfo->typekind >> 16];
1635         if(typeinfo->typekind == TKIND_MODULE)
1636             namedata[9] |= 0x10;
1637     } else
1638         namedata[9] &= ~0x10;
1639 
1640     if(typeinfo->typekind == TKIND_MODULE)
1641         namedata[9] |= 0x20;
1642 
1643     if (type_get_function_args(func->type))
1644     {
1645         i = 0;
1646         LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), var_t, entry )
1647         {
1648             /* don't give the last arg of a [propput*] func a name */
1649             if(i != num_params - 1 || (invokekind != 0x4 /* INVOKE_PROPERTYPUT */ && invokekind != 0x8 /* INVOKE_PROPERTYPUTREF */))
1650             {
1651                 int *paramdata = typedata + 6 + extra_attr + (num_defaults ? num_params : 0) + i * 3;
1652                 offset = ctl2_alloc_name(typeinfo->typelib, arg->name);
1653                 paramdata[1] = offset;
1654             }
1655             i++;
1656         }
1657     }
1658     return S_OK;
1659 }
1660 
1661 static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var)
1662 {
1663     int offset, id;
1664     unsigned int typedata_size;
1665     INT *typedata;
1666     int var_datawidth;
1667     int var_alignment;
1668     int var_type_size, var_kind = 0 /* VAR_PERINSTANCE */;
1669     int alignment;
1670     int varflags = 0;
1671     const attr_t *attr;
1672     unsigned char *namedata;
1673     int var_num = (typeinfo->typeinfo->cElement >> 16) & 0xffff;
1674 
1675     chat("add_var_desc(%d, %s)\n", index, var->name);
1676 
1677     id = 0x40000000 + index;
1678 
1679     if (var->attrs) LIST_FOR_EACH_ENTRY( attr, var->attrs, const attr_t, entry ) {
1680         expr_t *expr = attr->u.pval;
1681         switch(attr->type) {
1682         case ATTR_BINDABLE:
1683             varflags |= 0x04; /* VARFLAG_FBINDABLE */
1684             break;
1685         case ATTR_DEFAULTBIND:
1686             varflags |= 0x20; /* VARFLAG_FDEFAULTBIND */
1687             break;
1688         case ATTR_DEFAULTCOLLELEM:
1689             varflags |= 0x100; /* VARFLAG_FDEFAULTCOLLELEM */
1690             break;
1691         case ATTR_DISPLAYBIND:
1692             varflags |= 0x10; /* VARFLAG_FDISPLAYBIND */
1693             break;
1694         case ATTR_HIDDEN:
1695             varflags |= 0x40; /* VARFLAG_FHIDDEN */
1696             break;
1697         case ATTR_ID:
1698             id = expr->cval;
1699             break;
1700         case ATTR_IMMEDIATEBIND:
1701             varflags |= 0x1000; /* VARFLAG_FIMMEDIATEBIND */
1702             break;
1703         case ATTR_NONBROWSABLE:
1704             varflags |= 0x400; /* VARFLAG_FNONBROWSABLE */
1705             break;
1706         case ATTR_READONLY:
1707             varflags |= 0x01; /* VARFLAG_FREADONLY */
1708             break;
1709         /* FIXME: VARFLAG_FREPLACEABLE */
1710         case ATTR_REQUESTEDIT:
1711             varflags |= 0x08; /* VARFLAG_FREQUESTEDIT */
1712             break;
1713         case ATTR_RESTRICTED:
1714             varflags |= 0x80; /* VARFLAG_FRESTRICTED */
1715             break;
1716         case ATTR_SOURCE:
1717             varflags |= 0x02; /* VARFLAG_FSOURCE */
1718             break;
1719         case ATTR_UIDEFAULT:
1720             varflags |= 0x0200; /* VARFLAG_FUIDEFAULT */
1721             break;
1722         default:
1723             break;
1724         }
1725     }
1726 
1727     /* allocate type data space for us */
1728     typedata_size = 0x14;
1729 
1730     if (!typeinfo->var_data) {
1731         typeinfo->var_data = xmalloc(0x100);
1732         typeinfo->var_data_allocated = 0x100;
1733         typeinfo->var_data[0] = 0;
1734     }
1735 
1736     if(typeinfo->var_data[0] + typedata_size + sizeof(int) > typeinfo->var_data_allocated) {
1737         typeinfo->var_data_allocated = max(typeinfo->var_data_allocated * 2,
1738                                             typeinfo->var_data[0] + typedata_size + sizeof(int));
1739         typeinfo->var_data = xrealloc(typeinfo->var_data, typeinfo->var_data_allocated);
1740     }
1741 
1742     offset = typeinfo->var_data[0];
1743     typeinfo->var_data[0] += typedata_size;
1744     typedata = typeinfo->var_data + (offset >> 2) + 1;
1745 
1746     /* fill out the basic type information */
1747     typedata[0] = typedata_size | (index << 16);
1748     typedata[2] = varflags;
1749     typedata[3] = (36 /*sizeof(VARDESC)*/ << 16) | 0;
1750 
1751     if(typeinfo->vars_allocated == 0) {
1752         typeinfo->vars_allocated = 10;
1753         typeinfo->var_indices = xmalloc(typeinfo->vars_allocated * sizeof(int));
1754         typeinfo->var_names   = xmalloc(typeinfo->vars_allocated * sizeof(int));
1755         typeinfo->var_offsets = xmalloc(typeinfo->vars_allocated * sizeof(int));
1756     }
1757     if(typeinfo->vars_allocated == var_num) {
1758         typeinfo->vars_allocated *= 2;
1759         typeinfo->var_indices = xrealloc(typeinfo->var_indices, typeinfo->vars_allocated * sizeof(int));
1760         typeinfo->var_names   = xrealloc(typeinfo->var_names,   typeinfo->vars_allocated * sizeof(int));
1761         typeinfo->var_offsets = xrealloc(typeinfo->var_offsets, typeinfo->vars_allocated * sizeof(int));
1762     }
1763     /* update the index data */
1764     typeinfo->var_indices[var_num] = id;
1765     typeinfo->var_names[var_num] = -1;
1766     typeinfo->var_offsets[var_num] = offset;
1767 
1768     /* figure out type widths and whatnot */
1769     encode_var(typeinfo->typelib, var->type, var, &typedata[1], &var_datawidth,
1770                &var_alignment, &var_type_size);
1771 
1772     /* pad out starting position to data width */
1773     typeinfo->datawidth += var_alignment - 1;
1774     typeinfo->datawidth &= ~(var_alignment - 1);
1775 
1776     switch(typeinfo->typekind) {
1777     case TKIND_ENUM:
1778         write_value(typeinfo->typelib, &typedata[4], VT_I4, &var->eval->cval);
1779         var_kind = 2; /* VAR_CONST */
1780         var_type_size += 16; /* sizeof(VARIANT) */
1781         typeinfo->datawidth = var_datawidth;
1782         break;
1783     case TKIND_RECORD:
1784         typedata[4] = typeinfo->datawidth;
1785         typeinfo->datawidth += var_datawidth;
1786         break;
1787     case TKIND_UNION:
1788         typedata[4] = typeinfo->datawidth;
1789         typeinfo->datawidth = max(typeinfo->datawidth, var_datawidth);
1790         break;
1791     case TKIND_DISPATCH:
1792         var_kind = 3; /* VAR_DISPATCH */
1793         typeinfo->datawidth = pointer_size;
1794         var_alignment = 4;
1795         break;
1796     default:
1797         error("add_var_desc: unhandled type kind %d\n", typeinfo->typekind);
1798         break;
1799     }
1800 
1801     /* add type description size to total required allocation */
1802     typedata[3] += var_type_size << 16 | var_kind;
1803 
1804     /* fix type alignment */
1805     alignment = (typeinfo->typeinfo->typekind >> 11) & 0x1f;
1806     if (alignment < var_alignment) {
1807 	alignment = var_alignment;
1808 	typeinfo->typeinfo->typekind &= ~0xffc0;
1809 	typeinfo->typeinfo->typekind |= alignment << 11 | alignment << 6;
1810     }
1811 
1812     /* ??? */
1813     if (!typeinfo->typeinfo->res2) typeinfo->typeinfo->res2 = 0x1a;
1814     if ((index == 0) || (index == 1) || (index == 2) || (index == 4) || (index == 9)) {
1815 	typeinfo->typeinfo->res2 <<= 1;
1816     }
1817 
1818     /* ??? */
1819     if (typeinfo->typeinfo->res3 == -1) typeinfo->typeinfo->res3 = 0;
1820     typeinfo->typeinfo->res3 += 0x2c;
1821 
1822     /* increment the number of variable elements */
1823     typeinfo->typeinfo->cElement += 0x10000;
1824 
1825     /* pad data width to alignment */
1826     typeinfo->typeinfo->size = (typeinfo->datawidth + (alignment - 1)) & ~(alignment - 1);
1827 
1828     offset = ctl2_alloc_name(typeinfo->typelib, var->name);
1829     if (offset == -1) return E_OUTOFMEMORY;
1830 
1831     namedata = typeinfo->typelib->typelib_segment_data[MSFT_SEG_NAME] + offset;
1832     if (*((INT *)namedata) == -1) {
1833 	*((INT *)namedata) = typeinfo->typelib->typelib_typeinfo_offsets[typeinfo->typeinfo->typekind >> 16];
1834         if(typeinfo->typekind != TKIND_DISPATCH)
1835             namedata[9] |= 0x10;
1836     } else
1837         namedata[9] &= ~0x10;
1838 
1839     if (typeinfo->typekind == TKIND_ENUM) {
1840 	namedata[9] |= 0x20;
1841     }
1842     typeinfo->var_names[var_num] = offset;
1843 
1844     return S_OK;
1845 }
1846 
1847 static HRESULT add_impl_type(msft_typeinfo_t *typeinfo, type_t *ref, importinfo_t *importinfo)
1848 {
1849     if(importinfo) {
1850         alloc_importinfo(typeinfo->typelib, importinfo);
1851         typeinfo->typeinfo->datatype1 = importinfo->offset+1;
1852     }else {
1853         if(ref->typelib_idx == -1)
1854             add_interface_typeinfo(typeinfo->typelib, ref);
1855         if(ref->typelib_idx == -1)
1856             error("add_impl_type: unable to add inherited interface\n");
1857 
1858         typeinfo->typeinfo->datatype1 = typeinfo->typelib->typelib_typeinfo_offsets[ref->typelib_idx];
1859     }
1860 
1861     typeinfo->typeinfo->cImplTypes++;
1862     return S_OK;
1863 }
1864 
1865 static msft_typeinfo_t *create_msft_typeinfo(msft_typelib_t *typelib, enum type_kind kind,
1866                                              const char *name, const attr_list_t *attrs)
1867 {
1868     const attr_t *attr;
1869     msft_typeinfo_t *msft_typeinfo;
1870     int nameoffset;
1871     int typeinfo_offset;
1872     MSFT_TypeInfoBase *typeinfo;
1873     MSFT_GuidEntry guidentry;
1874 
1875     chat("create_msft_typeinfo: name %s kind %d index %d\n", name, kind, typelib->typelib_header.nrtypeinfos);
1876 
1877     msft_typeinfo = xmalloc(sizeof(*msft_typeinfo));
1878     memset( msft_typeinfo, 0, sizeof(*msft_typeinfo) );
1879 
1880     msft_typeinfo->typelib = typelib;
1881 
1882     nameoffset = ctl2_alloc_name(typelib, name);
1883     typeinfo_offset = ctl2_alloc_typeinfo(typelib, nameoffset);
1884     typeinfo = (MSFT_TypeInfoBase *)&typelib->typelib_segment_data[MSFT_SEG_TYPEINFO][typeinfo_offset];
1885 
1886     typelib->typelib_segment_data[MSFT_SEG_NAME][nameoffset + 9] = 0x38;
1887     *((int *)&typelib->typelib_segment_data[MSFT_SEG_NAME][nameoffset]) = typeinfo_offset;
1888 
1889     msft_typeinfo->typekind = kind;
1890     msft_typeinfo->typeinfo = typeinfo;
1891 
1892     typeinfo->typekind |= kind | 0x20;
1893 
1894     if(kind == TKIND_COCLASS)
1895         typeinfo->flags |= 0x2; /* TYPEFLAG_FCANCREATE */
1896 
1897     if (attrs) LIST_FOR_EACH_ENTRY( attr, attrs, const attr_t, entry ) {
1898         switch(attr->type) {
1899         case ATTR_AGGREGATABLE:
1900             if (kind == TKIND_COCLASS)
1901                 typeinfo->flags |= 0x400; /* TYPEFLAG_FAGGREGATABLE */
1902             break;
1903 
1904         case ATTR_APPOBJECT:
1905             if (kind == TKIND_COCLASS)
1906                 typeinfo->flags |= 0x1; /* TYPEFLAG_FAPPOBJECT */
1907             break;
1908 
1909         case ATTR_CONTROL:
1910             if (kind == TKIND_COCLASS)
1911                 typeinfo->flags |= 0x20; /* TYPEFLAG_FCONTROL */
1912             break;
1913 
1914         case ATTR_DLLNAME:
1915           {
1916             int offset = ctl2_alloc_string(typelib, attr->u.pval);
1917             typeinfo->datatype1 = offset;
1918             break;
1919           }
1920 
1921         case ATTR_DUAL:
1922             /* FIXME: check interface is compatible */
1923             typeinfo->typekind = (typeinfo->typekind & ~0xff) | 0x34;
1924             typeinfo->flags |= 0x140; /* TYPEFLAG_FDUAL | TYPEFLAG_FOLEAUTOMATION */
1925             break;
1926 
1927         case ATTR_HELPCONTEXT:
1928           {
1929             expr_t *expr = (expr_t*)attr->u.pval;
1930             typeinfo->helpcontext = expr->cval;
1931             break;
1932           }
1933         case ATTR_HELPSTRING:
1934           {
1935             int offset = ctl2_alloc_string(typelib, attr->u.pval);
1936             if (offset == -1) break;
1937             typeinfo->docstringoffs = offset;
1938             break;
1939           }
1940         case ATTR_HELPSTRINGCONTEXT:
1941           {
1942             expr_t *expr = (expr_t*)attr->u.pval;
1943             typeinfo->helpstringcontext = expr->cval;
1944             break;
1945           }
1946         case ATTR_HIDDEN:
1947             typeinfo->flags |= 0x10; /* TYPEFLAG_FHIDDEN */
1948             break;
1949 
1950         case ATTR_LICENSED:
1951             typeinfo->flags |= 0x04; /* TYPEFLAG_FLICENSED */
1952             break;
1953 
1954         case ATTR_NONCREATABLE:
1955             typeinfo->flags &= ~0x2; /* TYPEFLAG_FCANCREATE */
1956             break;
1957 
1958         case ATTR_NONEXTENSIBLE:
1959             typeinfo->flags |= 0x80; /* TYPEFLAG_FNONEXTENSIBLE */
1960             break;
1961 
1962         case ATTR_OLEAUTOMATION:
1963             typeinfo->flags |= 0x100; /* TYPEFLAG_FOLEAUTOMATION */
1964             break;
1965 
1966         /* FIXME: TYPEFLAG_FPREDCLID */
1967 
1968         case ATTR_PROXY:
1969             typeinfo->flags |= 0x4000; /* TYPEFLAG_FPROXY */
1970             break;
1971 
1972         /* FIXME: TYPEFLAG_FREPLACEABLE */
1973 
1974         case ATTR_RESTRICTED:
1975             typeinfo->flags |= 0x200; /* TYPEFLAG_FRESTRICTED */
1976             break;
1977 
1978         case ATTR_UUID:
1979             guidentry.guid = *(GUID*)attr->u.pval;
1980             guidentry.hreftype = typelib->typelib_typeinfo_offsets[typeinfo->typekind >> 16];
1981             guidentry.next_hash = -1;
1982             typeinfo->posguid = ctl2_alloc_guid(typelib, &guidentry);
1983 #if 0
1984             if (IsEqualIID(guid, &IID_IDispatch)) {
1985                 typelib->typelib_header.dispatchpos = typelib->typelib_typeinfo_offsets[typeinfo->typekind >> 16];
1986             }
1987 #endif
1988             break;
1989 
1990         case ATTR_VERSION:
1991             typeinfo->version = attr->u.ival;
1992             break;
1993 
1994         default:
1995             break;
1996         }
1997     }
1998 
1999     if (typelib->last_typeinfo) typelib->last_typeinfo->next_typeinfo = msft_typeinfo;
2000     typelib->last_typeinfo = msft_typeinfo;
2001     if (!typelib->typeinfos) typelib->typeinfos = msft_typeinfo;
2002 
2003 
2004     return msft_typeinfo;
2005 }
2006 
2007 static void add_dispatch(msft_typelib_t *typelib)
2008 {
2009     int guid_offset, impfile_offset, hash_key;
2010     MSFT_GuidEntry guidentry;
2011     MSFT_ImpInfo impinfo;
2012     GUID stdole =        {0x00020430,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
2013     GUID iid_idispatch = {0x00020400,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
2014 
2015     if(typelib->typelib_header.dispatchpos != -1) return;
2016 
2017     guidentry.guid = stdole;
2018     guidentry.hreftype = 2;
2019     guidentry.next_hash = -1;
2020     hash_key = ctl2_hash_guid(&guidentry.guid);
2021     guid_offset = ctl2_find_guid(typelib, hash_key, &guidentry.guid);
2022     if (guid_offset == -1)
2023         guid_offset = ctl2_alloc_guid(typelib, &guidentry);
2024     impfile_offset = alloc_importfile(typelib, guid_offset, 2, 0, "stdole2.tlb");
2025 
2026     guidentry.guid = iid_idispatch;
2027     guidentry.hreftype = 1;
2028     guidentry.next_hash = -1;
2029     impinfo.flags = TKIND_INTERFACE << 24 | MSFT_IMPINFO_OFFSET_IS_GUID;
2030     impinfo.oImpFile = impfile_offset;
2031     hash_key = ctl2_hash_guid(&guidentry.guid);
2032     guid_offset = ctl2_find_guid(typelib, hash_key, &guidentry.guid);
2033     if (guid_offset == -1)
2034         guid_offset = ctl2_alloc_guid(typelib, &guidentry);
2035     impinfo.oGuid = guid_offset;
2036     typelib->typelib_header.dispatchpos = alloc_msft_importinfo(typelib, &impinfo) | 0x01;
2037 }
2038 
2039 static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinterface)
2040 {
2041     int idx = 0;
2042     var_t *func;
2043     var_t *var;
2044     msft_typeinfo_t *msft_typeinfo;
2045 
2046     if (-1 < dispinterface->typelib_idx)
2047         return;
2048 
2049     dispinterface->typelib_idx = typelib->typelib_header.nrtypeinfos;
2050     msft_typeinfo = create_msft_typeinfo(typelib, TKIND_DISPATCH, dispinterface->name,
2051                                          dispinterface->attrs);
2052 
2053     msft_typeinfo->typeinfo->size = pointer_size;
2054     msft_typeinfo->typeinfo->typekind |= 0x2100;
2055 
2056     msft_typeinfo->typeinfo->flags |= 0x1000; /* TYPEFLAG_FDISPATCHABLE */
2057     add_dispatch(typelib);
2058     msft_typeinfo->typeinfo->cImplTypes = 1;
2059 
2060     /* count the no of methods, as the variable indices come after the funcs */
2061     if (dispinterface->details.iface->disp_methods)
2062         LIST_FOR_EACH_ENTRY( func, dispinterface->details.iface->disp_methods, var_t, entry )
2063             idx++;
2064 
2065     if (type_dispiface_get_props(dispinterface))
2066         LIST_FOR_EACH_ENTRY( var, type_dispiface_get_props(dispinterface), var_t, entry )
2067             add_var_desc(msft_typeinfo, idx++, var);
2068 
2069     if (type_dispiface_get_methods(dispinterface))
2070     {
2071         idx = 0;
2072         LIST_FOR_EACH_ENTRY( func, type_dispiface_get_methods(dispinterface), var_t, entry )
2073             if(add_func_desc(msft_typeinfo, func, idx) == S_OK)
2074                 idx++;
2075     }
2076 }
2077 
2078 static void add_interface_typeinfo(msft_typelib_t *typelib, type_t *interface)
2079 {
2080     int idx = 0;
2081     const statement_t *stmt_func;
2082     type_t *ref;
2083     msft_typeinfo_t *msft_typeinfo;
2084     importinfo_t *ref_importinfo = NULL;
2085     int num_parents = 0, num_funcs = 0;
2086     type_t *inherit;
2087     const type_t *derived;
2088 
2089     if (-1 < interface->typelib_idx)
2090         return;
2091 
2092     if (!interface->details.iface)
2093     {
2094         error( "interface %s is referenced but not defined\n", interface->name );
2095         return;
2096     }
2097 
2098     if (is_attr(interface->attrs, ATTR_DISPINTERFACE)) {
2099         add_dispinterface_typeinfo(typelib, interface);
2100         return;
2101     }
2102 
2103     /* midl adds the parent interface first, unless the parent itself
2104        has no parent (i.e. it stops before IUnknown). */
2105 
2106     inherit = type_iface_get_inherit(interface);
2107 
2108     if(inherit) {
2109         ref_importinfo = find_importinfo(typelib, inherit->name);
2110 
2111         if(!ref_importinfo && type_iface_get_inherit(inherit) &&
2112            inherit->typelib_idx == -1)
2113             add_interface_typeinfo(typelib, inherit);
2114     }
2115 
2116     /* check typelib_idx again, it could have been added while resolving the parent interface */
2117     if (-1 < interface->typelib_idx)
2118         return;
2119 
2120     interface->typelib_idx = typelib->typelib_header.nrtypeinfos;
2121     msft_typeinfo = create_msft_typeinfo(typelib, TKIND_INTERFACE, interface->name, interface->attrs);
2122     msft_typeinfo->typeinfo->size = pointer_size;
2123     msft_typeinfo->typeinfo->typekind |= 0x2200;
2124 
2125     for (derived = inherit; derived; derived = type_iface_get_inherit(derived))
2126         if (derived->name && !strcmp(derived->name, "IDispatch"))
2127             msft_typeinfo->typeinfo->flags |= 0x1000; /* TYPEFLAG_FDISPATCHABLE */
2128 
2129     /* can't be dual if it doesn't derive from IDispatch */
2130     if (!(msft_typeinfo->typeinfo->flags & 0x1000)) /* TYPEFLAG_FDISPATCHABLE */
2131         msft_typeinfo->typeinfo->flags &= ~0x40; /* TYPEFLAG_FDUAL */
2132 
2133     if(type_iface_get_inherit(interface))
2134         add_impl_type(msft_typeinfo, type_iface_get_inherit(interface),
2135                       ref_importinfo);
2136 
2137     /* count the number of inherited interfaces and non-local functions */
2138     for(ref = inherit; ref; ref = type_iface_get_inherit(ref)) {
2139         num_parents++;
2140         STATEMENTS_FOR_EACH_FUNC( stmt_func, type_iface_get_stmts(ref) ) {
2141             var_t *func = stmt_func->u.var;
2142             if (!is_local(func->attrs)) num_funcs++;
2143         }
2144     }
2145     msft_typeinfo->typeinfo->datatype2 = num_funcs << 16 | num_parents;
2146     msft_typeinfo->typeinfo->cbSizeVft = num_funcs * pointer_size;
2147 
2148     STATEMENTS_FOR_EACH_FUNC( stmt_func, type_iface_get_stmts(interface) ) {
2149         var_t *func = stmt_func->u.var;
2150         if(add_func_desc(msft_typeinfo, func, idx) == S_OK)
2151             idx++;
2152     }
2153 }
2154 
2155 static void add_structure_typeinfo(msft_typelib_t *typelib, type_t *structure)
2156 {
2157     int idx = 0;
2158     var_t *cur;
2159     msft_typeinfo_t *msft_typeinfo;
2160 
2161     if (-1 < structure->typelib_idx)
2162         return;
2163 
2164     structure->typelib_idx = typelib->typelib_header.nrtypeinfos;
2165     msft_typeinfo = create_msft_typeinfo(typelib, TKIND_RECORD, structure->name, structure->attrs);
2166     msft_typeinfo->typeinfo->size = 0;
2167 
2168     if (type_struct_get_fields(structure))
2169         LIST_FOR_EACH_ENTRY( cur, type_struct_get_fields(structure), var_t, entry )
2170             add_var_desc(msft_typeinfo, idx++, cur);
2171 }
2172 
2173 static void add_enum_typeinfo(msft_typelib_t *typelib, type_t *enumeration)
2174 {
2175     int idx = 0;
2176     var_t *cur;
2177     msft_typeinfo_t *msft_typeinfo;
2178 
2179     if (-1 < enumeration->typelib_idx)
2180         return;
2181 
2182     enumeration->typelib_idx = typelib->typelib_header.nrtypeinfos;
2183     msft_typeinfo = create_msft_typeinfo(typelib, TKIND_ENUM, enumeration->name, enumeration->attrs);
2184     msft_typeinfo->typeinfo->size = 0;
2185 
2186     if (type_enum_get_values(enumeration))
2187         LIST_FOR_EACH_ENTRY( cur, type_enum_get_values(enumeration), var_t, entry )
2188             add_var_desc(msft_typeinfo, idx++, cur);
2189 }
2190 
2191 static void add_union_typeinfo(msft_typelib_t *typelib, type_t *tunion)
2192 {
2193     int idx = 0;
2194     var_t *cur;
2195     msft_typeinfo_t *msft_typeinfo;
2196 
2197     if (-1 < tunion->typelib_idx)
2198         return;
2199 
2200     tunion->typelib_idx = typelib->typelib_header.nrtypeinfos;
2201     msft_typeinfo = create_msft_typeinfo(typelib, TKIND_UNION, tunion->name, tunion->attrs);
2202     msft_typeinfo->typeinfo->size = 0;
2203 
2204     if (type_union_get_cases(tunion))
2205         LIST_FOR_EACH_ENTRY(cur, type_union_get_cases(tunion), var_t, entry)
2206             add_var_desc(msft_typeinfo, idx++, cur);
2207 }
2208 
2209 static void add_typedef_typeinfo(msft_typelib_t *typelib, type_t *tdef)
2210 {
2211     msft_typeinfo_t *msft_typeinfo = NULL;
2212     int alignment, datatype1, datatype2, size, duplicate = 0;
2213     type_t *type;
2214 
2215     if (-1 < tdef->typelib_idx)
2216         return;
2217 
2218     type = type_alias_get_aliasee(tdef);
2219 
2220     if (!type->name || strcmp(tdef->name, type->name) != 0)
2221     {
2222         tdef->typelib_idx = typelib->typelib_header.nrtypeinfos;
2223         msft_typeinfo = create_msft_typeinfo(typelib, TKIND_ALIAS, tdef->name, tdef->attrs);
2224     }
2225     else
2226         duplicate = 1;
2227 
2228     encode_type(typelib, get_type_vt(type), type,
2229                 &datatype1, &size, &alignment, &datatype2);
2230 
2231     if (msft_typeinfo)
2232     {
2233         msft_typeinfo->typeinfo->datatype1 = datatype1;
2234         msft_typeinfo->typeinfo->size = size;
2235         msft_typeinfo->typeinfo->datatype2 = datatype2;
2236         msft_typeinfo->typeinfo->typekind |= (alignment << 11 | alignment << 6);
2237     }
2238 
2239     /* avoid adding duplicate type definitions */
2240     if (duplicate)
2241         tdef->typelib_idx = type->typelib_idx;
2242 }
2243 
2244 static void add_coclass_typeinfo(msft_typelib_t *typelib, type_t *cls)
2245 {
2246     msft_typeinfo_t *msft_typeinfo;
2247     ifref_t *iref;
2248     int num_ifaces = 0, offset, i;
2249     MSFT_RefRecord *ref, *first = NULL, *first_source = NULL;
2250     int have_default = 0, have_default_source = 0;
2251     const attr_t *attr;
2252     ifref_list_t *ifaces;
2253 
2254     if (-1 < cls->typelib_idx)
2255         return;
2256 
2257     cls->typelib_idx = typelib->typelib_header.nrtypeinfos;
2258     msft_typeinfo = create_msft_typeinfo(typelib, TKIND_COCLASS, cls->name, cls->attrs);
2259 
2260     ifaces = type_coclass_get_ifaces(cls);
2261     if (ifaces) LIST_FOR_EACH_ENTRY( iref, ifaces, ifref_t, entry ) num_ifaces++;
2262 
2263     offset = msft_typeinfo->typeinfo->datatype1 = ctl2_alloc_segment(typelib, MSFT_SEG_REFERENCES,
2264                                                                      num_ifaces * sizeof(*ref), 0);
2265 
2266     i = 0;
2267     if (ifaces) LIST_FOR_EACH_ENTRY( iref, ifaces, ifref_t, entry ) {
2268         if(iref->iface->typelib_idx == -1)
2269             add_interface_typeinfo(typelib, iref->iface);
2270         ref = (MSFT_RefRecord*) (typelib->typelib_segment_data[MSFT_SEG_REFERENCES] + offset + i * sizeof(*ref));
2271         ref->reftype = typelib->typelib_typeinfo_offsets[iref->iface->typelib_idx];
2272         ref->flags = 0;
2273         ref->oCustData = -1;
2274         ref->onext = -1;
2275         if(i < num_ifaces - 1)
2276             ref->onext = offset + (i + 1) * sizeof(*ref);
2277 
2278         if (iref->attrs) LIST_FOR_EACH_ENTRY( attr, iref->attrs, const attr_t, entry ) {
2279             switch(attr->type) {
2280             case ATTR_DEFAULT:
2281                 ref->flags |= 0x1; /* IMPLTYPEFLAG_FDEFAULT */
2282                 break;
2283             case ATTR_DEFAULTVTABLE:
2284                 ref->flags |= 0x8; /* IMPLTYPEFLAG_FDEFAULTVTABLE */
2285                 break;
2286             case ATTR_RESTRICTED:
2287                 ref->flags |= 0x4; /* IMPLTYPEFLAG_FRESTRICTED */
2288                 break;
2289             case ATTR_SOURCE:
2290                 ref->flags |= 0x2; /* IMPLTYPEFLAG_FSOURCE */
2291                 break;
2292             default:
2293                 warning("add_coclass_typeinfo: unhandled attr %d\n", attr->type);
2294             }
2295         }
2296         if(ref->flags & 0x1) { /* IMPLTYPEFLAG_FDEFAULT */
2297             if(ref->flags & 0x2) /* IMPLTYPEFLAG_SOURCE */
2298                 have_default_source = 1;
2299             else
2300                 have_default = 1;
2301         }
2302 
2303         /* If the interface is non-restricted and we haven't already had one then
2304            remember it so that we can use it as a default later */
2305         if((ref->flags & 0x4) == 0) { /* IMPLTYPEFLAG_FRESTRICTED */
2306             if(ref->flags & 0x2) { /* IMPLTYPEFLAG_FSOURCE */
2307                 if(!first_source)
2308                     first_source = ref;
2309             }
2310             else if(!first)
2311                 first = ref;
2312         }
2313         i++;
2314     }
2315 
2316     /* If we haven't had a default interface, then set the default flags on the
2317        first ones */
2318     if(!have_default && first)
2319         first->flags |= 0x1;
2320     if(!have_default_source && first_source)
2321         first_source->flags |= 0x1;
2322 
2323     msft_typeinfo->typeinfo->cImplTypes = num_ifaces;
2324     msft_typeinfo->typeinfo->size = pointer_size;
2325     msft_typeinfo->typeinfo->typekind |= 0x2200;
2326 }
2327 
2328 static void add_module_typeinfo(msft_typelib_t *typelib, type_t *module)
2329 {
2330     int idx = 0;
2331     const statement_t *stmt;
2332     msft_typeinfo_t *msft_typeinfo;
2333 
2334     if (-1 < module->typelib_idx)
2335         return;
2336 
2337     module->typelib_idx = typelib->typelib_header.nrtypeinfos;
2338     msft_typeinfo = create_msft_typeinfo(typelib, TKIND_MODULE, module->name, module->attrs);
2339     msft_typeinfo->typeinfo->typekind |= 0x0a00;
2340 
2341     STATEMENTS_FOR_EACH_FUNC( stmt, module->details.module->stmts ) {
2342         var_t *func = stmt->u.var;
2343         if(add_func_desc(msft_typeinfo, func, idx) == S_OK)
2344             idx++;
2345     }
2346 
2347     msft_typeinfo->typeinfo->size = idx;
2348 }
2349 
2350 static void add_type_typeinfo(msft_typelib_t *typelib, type_t *type)
2351 {
2352     switch (type_get_type(type)) {
2353     case TYPE_INTERFACE:
2354         add_interface_typeinfo(typelib, type);
2355         break;
2356     case TYPE_STRUCT:
2357         add_structure_typeinfo(typelib, type);
2358         break;
2359     case TYPE_ENUM:
2360         add_enum_typeinfo(typelib, type);
2361         break;
2362     case TYPE_UNION:
2363         add_union_typeinfo(typelib, type);
2364         break;
2365     case TYPE_COCLASS:
2366         add_coclass_typeinfo(typelib, type);
2367         break;
2368     case TYPE_BASIC:
2369     case TYPE_POINTER:
2370         break;
2371     default:
2372         error("add_entry: unhandled type 0x%x for %s\n",
2373               type_get_type(type), type->name);
2374         break;
2375     }
2376 }
2377 
2378 static void add_entry(msft_typelib_t *typelib, const statement_t *stmt)
2379 {
2380     switch(stmt->type) {
2381     case STMT_LIBRARY:
2382     case STMT_IMPORT:
2383     case STMT_PRAGMA:
2384     case STMT_CPPQUOTE:
2385     case STMT_DECLARATION:
2386         /* not included in typelib */
2387         break;
2388     case STMT_IMPORTLIB:
2389         /* not processed here */
2390         break;
2391     case STMT_TYPEDEF:
2392     {
2393         const type_list_t *type_entry = stmt->u.type_list;
2394         for (; type_entry; type_entry = type_entry->next) {
2395             /* if the type is public then add the typedef, otherwise attempt
2396              * to add the aliased type */
2397             if (is_attr(type_entry->type->attrs, ATTR_PUBLIC))
2398                 add_typedef_typeinfo(typelib, type_entry->type);
2399             else
2400                 add_type_typeinfo(typelib, type_alias_get_aliasee(type_entry->type));
2401         }
2402         break;
2403     }
2404     case STMT_MODULE:
2405         add_module_typeinfo(typelib, stmt->u.type);
2406         break;
2407     case STMT_TYPE:
2408     case STMT_TYPEREF:
2409     {
2410         type_t *type = stmt->u.type;
2411         add_type_typeinfo(typelib, type);
2412         break;
2413     }
2414     }
2415 }
2416 
2417 static void set_name(msft_typelib_t *typelib)
2418 {
2419     int offset;
2420 
2421     offset = ctl2_alloc_name(typelib, typelib->typelib->name);
2422     if (offset == -1) return;
2423     typelib->typelib_header.NameOffset = offset;
2424     return;
2425 }
2426 
2427 static void set_version(msft_typelib_t *typelib)
2428 {
2429     typelib->typelib_header.version = get_attrv( typelib->typelib->attrs, ATTR_VERSION );
2430 }
2431 
2432 static void set_guid(msft_typelib_t *typelib)
2433 {
2434     MSFT_GuidEntry guidentry;
2435     int offset;
2436     void *ptr;
2437     GUID guid = {0,0,0,{0,0,0,0,0,0}};
2438 
2439     guidentry.guid = guid;
2440     guidentry.hreftype = -2;
2441     guidentry.next_hash = -1;
2442 
2443     ptr = get_attrp( typelib->typelib->attrs, ATTR_UUID );
2444     if (ptr) guidentry.guid = *(GUID *)ptr;
2445 
2446     offset = ctl2_alloc_guid(typelib, &guidentry);
2447     typelib->typelib_header.posguid = offset;
2448 
2449     return;
2450 }
2451 
2452 static void set_doc_string(msft_typelib_t *typelib)
2453 {
2454     char *str = get_attrp( typelib->typelib->attrs, ATTR_HELPSTRING );
2455 
2456     if (str)
2457     {
2458         int offset = ctl2_alloc_string(typelib, str);
2459         if (offset != -1) typelib->typelib_header.helpstring = offset;
2460     }
2461 }
2462 
2463 static void set_help_file_name(msft_typelib_t *typelib)
2464 {
2465     char *str = get_attrp( typelib->typelib->attrs, ATTR_HELPFILE );
2466 
2467     if (str)
2468     {
2469         int offset = ctl2_alloc_string(typelib, str);
2470         if (offset != -1)
2471         {
2472             typelib->typelib_header.helpfile = offset;
2473             typelib->typelib_header.varflags |= 0x10;
2474         }
2475     }
2476 }
2477 
2478 static void set_help_context(msft_typelib_t *typelib)
2479 {
2480     const expr_t *expr = get_attrp( typelib->typelib->attrs, ATTR_HELPCONTEXT );
2481     if (expr) typelib->typelib_header.helpcontext = expr->cval;
2482 }
2483 
2484 static void set_help_string_dll(msft_typelib_t *typelib)
2485 {
2486     char *str = get_attrp( typelib->typelib->attrs, ATTR_HELPSTRINGDLL );
2487 
2488     if (str)
2489     {
2490         int offset = ctl2_alloc_string(typelib, str);
2491         if (offset != -1)
2492         {
2493             typelib->help_string_dll_offset = offset;
2494             typelib->typelib_header.varflags |= 0x100;
2495         }
2496     }
2497 }
2498 
2499 static void set_help_string_context(msft_typelib_t *typelib)
2500 {
2501     const expr_t *expr = get_attrp( typelib->typelib->attrs, ATTR_HELPSTRINGCONTEXT );
2502     if (expr) typelib->typelib_header.helpstringcontext = expr->cval;
2503 }
2504 
2505 static void set_lcid(msft_typelib_t *typelib)
2506 {
2507     const expr_t *lcid_expr = get_attrp( typelib->typelib->attrs, ATTR_LIBLCID );
2508     if(lcid_expr)
2509     {
2510         typelib->typelib_header.lcid  = lcid_expr->cval;
2511         typelib->typelib_header.lcid2 = lcid_expr->cval;
2512     }
2513 }
2514 
2515 static void set_lib_flags(msft_typelib_t *typelib)
2516 {
2517     const attr_t *attr;
2518 
2519     typelib->typelib_header.flags = 0;
2520     if (!typelib->typelib->attrs) return;
2521     LIST_FOR_EACH_ENTRY( attr, typelib->typelib->attrs, const attr_t, entry )
2522     {
2523         switch(attr->type) {
2524         case ATTR_CONTROL:
2525             typelib->typelib_header.flags |= 0x02; /* LIBFLAG_FCONTROL */
2526             break;
2527         case ATTR_HIDDEN:
2528             typelib->typelib_header.flags |= 0x04; /* LIBFLAG_FHIDDEN */
2529             break;
2530         case ATTR_RESTRICTED:
2531             typelib->typelib_header.flags |= 0x01; /* LIBFLAG_FRESTRICTED */
2532             break;
2533         default:
2534             break;
2535         }
2536     }
2537     return;
2538 }
2539 
2540 static void ctl2_write_segment(msft_typelib_t *typelib, int segment)
2541 {
2542     put_data(typelib->typelib_segment_data[segment], typelib->typelib_segdir[segment].length);
2543 }
2544 
2545 static void ctl2_finalize_typeinfos(msft_typelib_t *typelib, int filesize)
2546 {
2547     msft_typeinfo_t *typeinfo;
2548 
2549     for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
2550 	typeinfo->typeinfo->memoffset = filesize;
2551 	if (typeinfo->func_data)
2552 	    filesize += typeinfo->func_data[0] + ((typeinfo->typeinfo->cElement & 0xffff) * 12);
2553 	if (typeinfo->var_data)
2554 	    filesize += typeinfo->var_data[0] + (((typeinfo->typeinfo->cElement >> 16) & 0xffff) * 12);
2555         if (typeinfo->func_data || typeinfo->var_data)
2556             filesize += 4;
2557     }
2558 }
2559 
2560 static int ctl2_finalize_segment(msft_typelib_t *typelib, int filepos, int segment)
2561 {
2562     if (typelib->typelib_segdir[segment].length) {
2563 	typelib->typelib_segdir[segment].offset = filepos;
2564     } else {
2565 	typelib->typelib_segdir[segment].offset = -1;
2566     }
2567 
2568     return typelib->typelib_segdir[segment].length;
2569 }
2570 
2571 
2572 static void ctl2_write_typeinfos(msft_typelib_t *typelib)
2573 {
2574     msft_typeinfo_t *typeinfo;
2575     int typedata_size;
2576 
2577     for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
2578         if (!typeinfo->func_data && !typeinfo->var_data) continue;
2579         typedata_size = 0;
2580 	if (typeinfo->func_data)
2581             typedata_size = typeinfo->func_data[0];
2582 	if (typeinfo->var_data)
2583             typedata_size += typeinfo->var_data[0];
2584 	put_data(&typedata_size, sizeof(int));
2585         if (typeinfo->func_data)
2586             put_data(typeinfo->func_data + 1, typeinfo->func_data[0]);
2587         if (typeinfo->var_data)
2588             put_data(typeinfo->var_data + 1, typeinfo->var_data[0]);
2589         if (typeinfo->func_indices)
2590             put_data(typeinfo->func_indices, (typeinfo->typeinfo->cElement & 0xffff) * 4);
2591         if (typeinfo->var_indices)
2592             put_data(typeinfo->var_indices, (typeinfo->typeinfo->cElement >> 16) * 4);
2593         if (typeinfo->func_names)
2594             put_data(typeinfo->func_names,   (typeinfo->typeinfo->cElement & 0xffff) * 4);
2595         if (typeinfo->var_names)
2596             put_data(typeinfo->var_names,   (typeinfo->typeinfo->cElement >> 16) * 4);
2597         if (typeinfo->func_offsets)
2598             put_data(typeinfo->func_offsets, (typeinfo->typeinfo->cElement & 0xffff) * 4);
2599         if (typeinfo->var_offsets) {
2600             int add = 0, i, offset;
2601             if(typeinfo->func_data)
2602                 add = typeinfo->func_data[0];
2603             for(i = 0; i < (typeinfo->typeinfo->cElement >> 16); i++) {
2604                 offset = typeinfo->var_offsets[i];
2605                 offset += add;
2606                 put_data(&offset, 4);
2607             }
2608         }
2609     }
2610 }
2611 
2612 static void save_all_changes(msft_typelib_t *typelib)
2613 {
2614     int filepos;
2615 
2616     chat("save_all_changes(%p)\n", typelib);
2617 
2618     filepos = sizeof(MSFT_Header) + sizeof(MSFT_SegDir);
2619     if(typelib->typelib_header.varflags & 0x100) filepos += 4; /* helpstringdll */
2620     filepos += typelib->typelib_header.nrtypeinfos * 4;
2621 
2622     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_TYPEINFO);
2623     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_GUIDHASH);
2624     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_GUID);
2625     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_REFERENCES);
2626     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_IMPORTINFO);
2627     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_IMPORTFILES);
2628     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_NAMEHASH);
2629     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_NAME);
2630     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_STRING);
2631     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_TYPEDESC);
2632     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_ARRAYDESC);
2633     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_CUSTDATA);
2634     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_CUSTDATAGUID);
2635 
2636     ctl2_finalize_typeinfos(typelib, filepos);
2637 
2638     byte_swapped = 0;
2639     init_output_buffer();
2640 
2641     put_data(&typelib->typelib_header, sizeof(typelib->typelib_header));
2642     if(typelib->typelib_header.varflags & 0x100)
2643         put_data(&typelib->help_string_dll_offset, sizeof(typelib->help_string_dll_offset));
2644 
2645     put_data(typelib->typelib_typeinfo_offsets, typelib->typelib_header.nrtypeinfos * 4);
2646     put_data(&typelib->typelib_segdir, sizeof(typelib->typelib_segdir));
2647     ctl2_write_segment( typelib, MSFT_SEG_TYPEINFO );
2648     ctl2_write_segment( typelib, MSFT_SEG_GUIDHASH );
2649     ctl2_write_segment( typelib, MSFT_SEG_GUID );
2650     ctl2_write_segment( typelib, MSFT_SEG_REFERENCES );
2651     ctl2_write_segment( typelib, MSFT_SEG_IMPORTINFO );
2652     ctl2_write_segment( typelib, MSFT_SEG_IMPORTFILES );
2653     ctl2_write_segment( typelib, MSFT_SEG_NAMEHASH );
2654     ctl2_write_segment( typelib, MSFT_SEG_NAME );
2655     ctl2_write_segment( typelib, MSFT_SEG_STRING );
2656     ctl2_write_segment( typelib, MSFT_SEG_TYPEDESC );
2657     ctl2_write_segment( typelib, MSFT_SEG_ARRAYDESC );
2658     ctl2_write_segment( typelib, MSFT_SEG_CUSTDATA );
2659     ctl2_write_segment( typelib, MSFT_SEG_CUSTDATAGUID );
2660 
2661     ctl2_write_typeinfos(typelib);
2662 
2663     if (strendswith( typelib_name, ".res" ))  /* create a binary resource file */
2664     {
2665         char typelib_id[13] = "#1";
2666 
2667         expr_t *expr = get_attrp( typelib->typelib->attrs, ATTR_ID );
2668         if (expr)
2669             sprintf( typelib_id, "#%d", expr->cval );
2670         add_output_to_resources( "TYPELIB", typelib_id );
2671         output_typelib_regscript( typelib->typelib );
2672         flush_output_resources( typelib_name );
2673     }
2674     else flush_output_buffer( typelib_name );
2675 }
2676 
2677 int create_msft_typelib(typelib_t *typelib)
2678 {
2679     msft_typelib_t *msft;
2680     int failed = 0;
2681     const statement_t *stmt;
2682     time_t cur_time;
2683     char *time_override;
2684     unsigned int version = 7 << 24 | 555; /* 7.00.0555 */
2685     GUID midl_time_guid    = {0xde77ba63,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}};
2686     GUID midl_version_guid = {0xde77ba64,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}};
2687     GUID midl_info_guid = {0xde77ba65,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}};
2688     char info_string[128];
2689 
2690     pointer_size = (typelib_kind == SYS_WIN64) ? 8 : 4;
2691 
2692     msft = xmalloc(sizeof(*msft));
2693     memset(msft, 0, sizeof(*msft));
2694     msft->typelib = typelib;
2695 
2696     ctl2_init_header(msft);
2697     ctl2_init_segdir(msft);
2698 
2699     msft->typelib_header.varflags |= typelib_kind;
2700 
2701     /*
2702      * The following two calls return an offset or -1 if out of memory. We
2703      * specifically need an offset of 0, however, so...
2704      */
2705     if (ctl2_alloc_segment(msft, MSFT_SEG_GUIDHASH, 0x80, 0x80)) { failed = 1; }
2706     if (ctl2_alloc_segment(msft, MSFT_SEG_NAMEHASH, 0x200, 0x200)) { failed = 1; }
2707 
2708     if(failed)
2709     {
2710         free(msft);
2711         return 0;
2712     }
2713 
2714     msft->typelib_guidhash_segment = (int *)msft->typelib_segment_data[MSFT_SEG_GUIDHASH];
2715     msft->typelib_namehash_segment = (int *)msft->typelib_segment_data[MSFT_SEG_NAMEHASH];
2716 
2717     memset(msft->typelib_guidhash_segment, 0xff, 0x80);
2718     memset(msft->typelib_namehash_segment, 0xff, 0x200);
2719 
2720     set_lib_flags(msft);
2721     set_lcid(msft);
2722     set_help_file_name(msft);
2723     set_doc_string(msft);
2724     set_guid(msft);
2725     set_version(msft);
2726     set_name(msft);
2727     set_help_context(msft);
2728     set_help_string_dll(msft);
2729     set_help_string_context(msft);
2730 
2731     /* midl adds two sets of custom data to the library: the current unix time
2732        and midl's version number */
2733     time_override = getenv( "WIDL_TIME_OVERRIDE");
2734     cur_time = time_override ? atol( time_override) : time(NULL);
2735     sprintf(info_string, "Created by WIDL version %s at %s\n", PACKAGE_VERSION, ctime(&cur_time));
2736     set_custdata(msft, &midl_info_guid, VT_BSTR, info_string, &msft->typelib_header.CustomDataOffset);
2737     set_custdata(msft, &midl_time_guid, VT_UI4, &cur_time, &msft->typelib_header.CustomDataOffset);
2738     set_custdata(msft, &midl_version_guid, VT_UI4, &version, &msft->typelib_header.CustomDataOffset);
2739 
2740     if (typelib->stmts)
2741         LIST_FOR_EACH_ENTRY( stmt, typelib->stmts, const statement_t, entry )
2742             add_entry(msft, stmt);
2743 
2744     save_all_changes(msft);
2745     free(msft);
2746     return 1;
2747 }
2748