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