Add encoding for VT_R8.
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 "wine/unicode.h"
49
50 #include "widltypes.h"
51 #include "typelib.h"
52 #include "typelib_struct.h"
53 #include "utils.h"
54 #include "hash.h"
55
56 enum MSFT_segment_index {
57     MSFT_SEG_TYPEINFO = 0,  /* type information */
58     MSFT_SEG_IMPORTINFO,    /* import information */
59     MSFT_SEG_IMPORTFILES,   /* import filenames */
60     MSFT_SEG_REFERENCES,    /* references (?) */
61     MSFT_SEG_GUIDHASH,      /* hash table for guids? */
62     MSFT_SEG_GUID,          /* guid storage */
63     MSFT_SEG_NAMEHASH,      /* hash table for names */
64     MSFT_SEG_NAME,          /* name storage */
65     MSFT_SEG_STRING,        /* string storage */
66     MSFT_SEG_TYPEDESC,      /* type descriptions */
67     MSFT_SEG_ARRAYDESC,     /* array descriptions */
68     MSFT_SEG_CUSTDATA,      /* custom data */
69     MSFT_SEG_CUSTDATAGUID,  /* custom data guids */
70     MSFT_SEG_UNKNOWN,       /* ??? */
71     MSFT_SEG_UNKNOWN2,      /* ??? */
72     MSFT_SEG_MAX            /* total number of segments */
73 };
74
75 typedef struct tagMSFT_ImpFile {
76     int guid;
77     LCID lcid;
78     int version;
79     char filename[0]; /* preceeded by two bytes of encoded (length << 2) + flags in the low two bits. */
80 } MSFT_ImpFile;
81
82 typedef struct _msft_typelib_t
83 {
84     typelib_t *typelib;
85     MSFT_Header typelib_header;
86     MSFT_pSeg typelib_segdir[MSFT_SEG_MAX];
87     char *typelib_segment_data[MSFT_SEG_MAX];
88     int typelib_segment_block_length[MSFT_SEG_MAX];
89
90     INT typelib_typeinfo_offsets[0x200]; /* Hope that's enough. */
91
92     INT *typelib_namehash_segment;
93     INT *typelib_guidhash_segment;
94
95     INT help_string_dll_offset;
96
97     struct _msft_typeinfo_t *typeinfos;
98     struct _msft_typeinfo_t *last_typeinfo;
99 } msft_typelib_t;
100
101 typedef struct _msft_typeinfo_t
102 {
103     msft_typelib_t *typelib;
104     MSFT_TypeInfoBase *typeinfo;
105
106     INT *typedata;
107     int typedata_allocated;
108     int typedata_length;
109
110     int indices[42];
111     int names[42];
112     int offsets[42];
113
114     int datawidth;
115
116     struct _msft_typeinfo_t *next_typeinfo;
117 } msft_typeinfo_t;
118
119
120
121 /*================== Internal functions ===================================*/
122
123 /****************************************************************************
124  *      ctl2_init_header
125  *
126  *  Initializes the type library header of a new typelib.
127  */
128 static void ctl2_init_header(
129         msft_typelib_t *typelib) /* [I] The typelib to initialize. */
130 {
131     typelib->typelib_header.magic1 = 0x5446534d;
132     typelib->typelib_header.magic2 = 0x00010002;
133     typelib->typelib_header.posguid = -1;
134     typelib->typelib_header.lcid = 0x0409; /* or do we use the current one? */
135     typelib->typelib_header.lcid2 = 0x0;
136     typelib->typelib_header.varflags = 0x40;
137     typelib->typelib_header.version = 0;
138     typelib->typelib_header.flags = 0;
139     typelib->typelib_header.nrtypeinfos = 0;
140     typelib->typelib_header.helpstring = -1;
141     typelib->typelib_header.helpstringcontext = 0;
142     typelib->typelib_header.helpcontext = 0;
143     typelib->typelib_header.nametablecount = 0;
144     typelib->typelib_header.nametablechars = 0;
145     typelib->typelib_header.NameOffset = -1;
146     typelib->typelib_header.helpfile = -1;
147     typelib->typelib_header.CustomDataOffset = -1;
148     typelib->typelib_header.res44 = 0x20;
149     typelib->typelib_header.res48 = 0x80;
150     typelib->typelib_header.dispatchpos = -1;
151     typelib->typelib_header.res50 = 0;
152 }
153
154 /****************************************************************************
155  *      ctl2_init_segdir
156  *
157  *  Initializes the segment directory of a new typelib.
158  */
159 static void ctl2_init_segdir(
160         msft_typelib_t *typelib) /* [I] The typelib to initialize. */
161 {
162     int i;
163     MSFT_pSeg *segdir;
164
165     segdir = &typelib->typelib_segdir[MSFT_SEG_TYPEINFO];
166
167     for (i = 0; i < 15; i++) {
168         segdir[i].offset = -1;
169         segdir[i].length = 0;
170         segdir[i].res08 = -1;
171         segdir[i].res0c = 0x0f;
172     }
173 }
174
175 /****************************************************************************
176  *      ctl2_hash_guid
177  *
178  *  Generates a hash key from a GUID.
179  *
180  * RETURNS
181  *
182  *  The hash key for the GUID.
183  */
184 static int ctl2_hash_guid(
185         REFGUID guid)                /* [I] The guid to hash. */
186 {
187     int hash;
188     int i;
189
190     hash = 0;
191     for (i = 0; i < 8; i ++) {
192         hash ^= ((const short *)guid)[i];
193     }
194
195     return hash & 0x1f;
196 }
197
198 /****************************************************************************
199  *      ctl2_find_guid
200  *
201  *  Locates a guid in a type library.
202  *
203  * RETURNS
204  *
205  *  The offset into the GUID segment of the guid, or -1 if not found.
206  */
207 static int ctl2_find_guid(
208         msft_typelib_t *typelib,   /* [I] The typelib to operate against. */
209         int hash_key,              /* [I] The hash key for the guid. */
210         REFGUID guid)              /* [I] The guid to find. */
211 {
212     int offset;
213     MSFT_GuidEntry *guidentry;
214
215     offset = typelib->typelib_guidhash_segment[hash_key];
216     while (offset != -1) {
217         guidentry = (MSFT_GuidEntry *)&typelib->typelib_segment_data[MSFT_SEG_GUID][offset];
218
219         if (!memcmp(guidentry, guid, sizeof(GUID))) return offset;
220
221         offset = guidentry->next_hash;
222     }
223
224     return offset;
225 }
226
227 /****************************************************************************
228  *      ctl2_find_name
229  *
230  *  Locates a name in a type library.
231  *
232  * RETURNS
233  *
234  *  The offset into the NAME segment of the name, or -1 if not found.
235  *
236  * NOTES
237  *
238  *  The name must be encoded as with ctl2_encode_name().
239  */
240 static int ctl2_find_name(
241         msft_typelib_t *typelib,   /* [I] The typelib to operate against. */
242         char *name)                /* [I] The encoded name to find. */
243 {
244     int offset;
245     int *namestruct;
246
247     offset = typelib->typelib_namehash_segment[name[2] & 0x7f];
248     while (offset != -1) {
249         namestruct = (int *)&typelib->typelib_segment_data[MSFT_SEG_NAME][offset];
250
251         if (!((namestruct[2] ^ *((int *)name)) & 0xffff00ff)) {
252             /* hash codes and lengths match, final test */
253             if (!strncasecmp(name+4, (void *)(namestruct+3), name[0])) break;
254         }
255
256         /* move to next item in hash bucket */
257         offset = namestruct[1];
258     }
259
260     return offset;
261 }
262
263 /****************************************************************************
264  *      ctl2_encode_name
265  *
266  *  Encodes a name string to a form suitable for storing into a type library
267  *  or comparing to a name stored in a type library.
268  *
269  * RETURNS
270  *
271  *  The length of the encoded name, including padding and length+hash fields.
272  *
273  * NOTES
274  *
275  *  Will throw an exception if name or result are NULL. Is not multithread
276  *  safe in the slightest.
277  */
278 static int ctl2_encode_name(
279         msft_typelib_t *typelib,   /* [I] The typelib to operate against (used for LCID only). */
280         const char *name,          /* [I] The name string to encode. */
281         char **result)             /* [O] A pointer to a pointer to receive the encoded name. */
282 {
283     int length;
284     static char converted_name[0x104];
285     int offset;
286     int value;
287
288     length = strlen(name);
289     memcpy(converted_name + 4, name, length);
290     converted_name[0] = length & 0xff;
291
292     converted_name[length + 4] = 0;
293
294     converted_name[1] = 0x00;
295
296     value = lhash_val_of_name_sys(typelib->typelib_header.varflags & 0x0f, typelib->typelib_header.lcid, converted_name + 4);
297
298     converted_name[2] = value;
299     converted_name[3] = value >> 8;
300
301     for (offset = (4 - length) & 3; offset; offset--) converted_name[length + offset + 3] = 0x57;
302
303     *result = converted_name;
304
305     return (length + 7) & ~3;
306 }
307
308 /****************************************************************************
309  *      ctl2_encode_string
310  *
311  *  Encodes a string to a form suitable for storing into a type library or
312  *  comparing to a string stored in a type library.
313  *
314  * RETURNS
315  *
316  *  The length of the encoded string, including padding and length fields.
317  *
318  * NOTES
319  *
320  *  Will throw an exception if string or result are NULL. Is not multithread
321  *  safe in the slightest.
322  */
323 static int ctl2_encode_string(
324         msft_typelib_t *typelib,   /* [I] The typelib to operate against (not used?). */
325         const char *string,        /* [I] The string to encode. */
326         char **result)             /* [O] A pointer to a pointer to receive the encoded string. */
327 {
328     int length;
329     static char converted_string[0x104];
330     int offset;
331
332     length = strlen(string);
333     memcpy(converted_string + 2, string, length);
334     converted_string[0] = length & 0xff;
335     converted_string[1] = (length >> 8) & 0xff;
336
337     if(length < 3) { /* strings of this length are padded with upto 8 bytes incl the 2 byte length */
338         for(offset = 0; offset < 4; offset++)
339             converted_string[length + offset + 2] = 0x57;
340         length += 4;
341     }
342     for (offset = (4 - (length + 2)) & 3; offset; offset--) converted_string[length + offset + 1] = 0x57;
343
344     *result = converted_string;
345
346     return (length + 5) & ~3;
347 }
348
349 /****************************************************************************
350  *      ctl2_alloc_segment
351  *
352  *  Allocates memory from a segment in a type library.
353  *
354  * RETURNS
355  *
356  *  Success: The offset within the segment of the new data area.
357  *  Failure: -1 (this is invariably an out of memory condition).
358  *
359  * BUGS
360  *
361  *  Does not (yet) handle the case where the allocated segment memory needs to grow.
362  */
363 static int ctl2_alloc_segment(
364         msft_typelib_t *typelib,         /* [I] The type library in which to allocate. */
365         enum MSFT_segment_index segment, /* [I] The segment in which to allocate. */
366         int size,                        /* [I] The amount to allocate. */
367         int block_size)                  /* [I] Initial allocation block size, or 0 for default. */
368 {
369     int offset;
370
371     if(!typelib->typelib_segment_data[segment]) {
372         if (!block_size) block_size = 0x2000;
373
374         typelib->typelib_segment_block_length[segment] = block_size;
375         typelib->typelib_segment_data[segment] = xmalloc(block_size);
376         if (!typelib->typelib_segment_data[segment]) return -1;
377         memset(typelib->typelib_segment_data[segment], 0x57, block_size);
378     }
379
380     while ((typelib->typelib_segdir[segment].length + size) > typelib->typelib_segment_block_length[segment]) {
381         char *block;
382
383         block_size = typelib->typelib_segment_block_length[segment];
384         block = realloc(typelib->typelib_segment_data[segment], block_size << 1);
385         if (!block) return -1;
386
387         if (segment == MSFT_SEG_TYPEINFO) {
388             /* TypeInfos have a direct pointer to their memory space, so we have to fix them up. */
389             msft_typeinfo_t *typeinfo;
390
391             for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
392                 typeinfo->typeinfo = (void *)&block[((char *)typeinfo->typeinfo) - typelib->typelib_segment_data[segment]];
393             }
394         }
395
396         memset(block + block_size, 0x57, block_size);
397         typelib->typelib_segment_block_length[segment] = block_size << 1;
398         typelib->typelib_segment_data[segment] = block;
399     }
400
401     offset = typelib->typelib_segdir[segment].length;
402     typelib->typelib_segdir[segment].length += size;
403
404     return offset;
405 }
406
407 /****************************************************************************
408  *      ctl2_alloc_typeinfo
409  *
410  *  Allocates and initializes a typeinfo structure in a type library.
411  *
412  * RETURNS
413  *
414  *  Success: The offset of the new typeinfo.
415  *  Failure: -1 (this is invariably an out of memory condition).
416  */
417 static int ctl2_alloc_typeinfo(
418         msft_typelib_t *typelib,   /* [I] The type library to allocate in. */
419         int nameoffset)            /* [I] The offset of the name for this typeinfo. */
420 {
421     int offset;
422     MSFT_TypeInfoBase *typeinfo;
423
424     offset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEINFO, sizeof(MSFT_TypeInfoBase), 0);
425     if (offset == -1) return -1;
426
427     typelib->typelib_typeinfo_offsets[typelib->typelib_header.nrtypeinfos++] = offset;
428
429     typeinfo = (void *)(typelib->typelib_segment_data[MSFT_SEG_TYPEINFO] + offset);
430
431     typeinfo->typekind = (typelib->typelib_header.nrtypeinfos - 1) << 16;
432     typeinfo->memoffset = -1; /* should be EOF if no elements */
433     typeinfo->res2 = 0;
434     typeinfo->res3 = -1;
435     typeinfo->res4 = 3;
436     typeinfo->res5 = 0;
437     typeinfo->cElement = 0;
438     typeinfo->res7 = 0;
439     typeinfo->res8 = 0;
440     typeinfo->res9 = 0;
441     typeinfo->resA = 0;
442     typeinfo->posguid = -1;
443     typeinfo->flags = 0;
444     typeinfo->NameOffset = nameoffset;
445     typeinfo->version = 0;
446     typeinfo->docstringoffs = -1;
447     typeinfo->helpstringcontext = 0;
448     typeinfo->helpcontext = 0;
449     typeinfo->oCustData = -1;
450     typeinfo->cbSizeVft = 0;
451     typeinfo->cImplTypes = 0;
452     typeinfo->size = 0;
453     typeinfo->datatype1 = -1;
454     typeinfo->datatype2 = 0;
455     typeinfo->res18 = 0;
456     typeinfo->res19 = -1;
457
458     return offset;
459 }
460
461 /****************************************************************************
462  *      ctl2_alloc_guid
463  *
464  *  Allocates and initializes a GUID structure in a type library. Also updates
465  *  the GUID hash table as needed.
466  *
467  * RETURNS
468  *
469  *  Success: The offset of the new GUID.
470  *  Failure: -1 (this is invariably an out of memory condition).
471  */
472 static int ctl2_alloc_guid(
473         msft_typelib_t *typelib,   /* [I] The type library to allocate in. */
474         MSFT_GuidEntry *guid)      /* [I] The GUID to store. */
475 {
476     int offset;
477     MSFT_GuidEntry *guid_space;
478     int hash_key;
479
480     hash_key = ctl2_hash_guid(&guid->guid);
481
482     offset = ctl2_find_guid(typelib, hash_key, &guid->guid);
483     if (offset != -1) return offset;
484
485     offset = ctl2_alloc_segment(typelib, MSFT_SEG_GUID, sizeof(MSFT_GuidEntry), 0);
486     if (offset == -1) return -1;
487
488     guid_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_GUID] + offset);
489     *guid_space = *guid;
490
491     guid_space->next_hash = typelib->typelib_guidhash_segment[hash_key];
492     typelib->typelib_guidhash_segment[hash_key] = offset;
493
494     return offset;
495 }
496
497 /****************************************************************************
498  *      ctl2_alloc_name
499  *
500  *  Allocates and initializes a name within a type library. Also updates the
501  *  name hash table as needed.
502  *
503  * RETURNS
504  *
505  *  Success: The offset within the segment of the new name.
506  *  Failure: -1 (this is invariably an out of memory condition).
507  */
508 static int ctl2_alloc_name(
509         msft_typelib_t *typelib,  /* [I] The type library to allocate in. */
510         const char *name)         /* [I] The name to store. */
511 {
512     int length;
513     int offset;
514     MSFT_NameIntro *name_space;
515     char *encoded_name;
516
517     length = ctl2_encode_name(typelib, name, &encoded_name);
518
519     offset = ctl2_find_name(typelib, encoded_name);
520     if (offset != -1) return offset;
521
522     offset = ctl2_alloc_segment(typelib, MSFT_SEG_NAME, length + 8, 0);
523     if (offset == -1) return -1;
524
525     name_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_NAME] + offset);
526     name_space->hreftype = -1;
527     name_space->next_hash = -1;
528     memcpy(&name_space->namelen, encoded_name, length);
529
530     if (typelib->typelib_namehash_segment[encoded_name[2] & 0x7f] != -1)
531         name_space->next_hash = typelib->typelib_namehash_segment[encoded_name[2] & 0x7f];
532
533     typelib->typelib_namehash_segment[encoded_name[2] & 0x7f] = offset;
534
535     typelib->typelib_header.nametablecount += 1;
536     typelib->typelib_header.nametablechars += *encoded_name;
537
538     return offset;
539 }
540
541 /****************************************************************************
542  *      ctl2_alloc_string
543  *
544  *  Allocates and initializes a string in a type library.
545  *
546  * RETURNS
547  *
548  *  Success: The offset within the segment of the new string.
549  *  Failure: -1 (this is invariably an out of memory condition).
550  */
551 static int ctl2_alloc_string(
552         msft_typelib_t *typelib,  /* [I] The type library to allocate in. */
553         const char *string)       /* [I] The string to store. */
554 {
555     int length;
556     int offset;
557     char *string_space;
558     char *encoded_string;
559
560     length = ctl2_encode_string(typelib, string, &encoded_string);
561
562     for (offset = 0; offset < typelib->typelib_segdir[MSFT_SEG_STRING].length;
563          offset += ((((typelib->typelib_segment_data[MSFT_SEG_STRING][offset + 1] << 8) & 0xff)
564              | (typelib->typelib_segment_data[MSFT_SEG_STRING][offset + 0] & 0xff)) + 5) & ~3) {
565         if (!memcmp(encoded_string, typelib->typelib_segment_data[MSFT_SEG_STRING] + offset, length)) return offset;
566     }
567
568     offset = ctl2_alloc_segment(typelib, MSFT_SEG_STRING, length, 0);
569     if (offset == -1) return -1;
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  *      ctl2_alloc_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 ctl2_alloc_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     offset = ctl2_alloc_segment(typelib, MSFT_SEG_IMPORTINFO, sizeof(MSFT_ImpInfo), 0);
604     if (offset == -1) return -1;
605
606     impinfo_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_IMPORTINFO] + offset);
607     *impinfo_space = *impinfo;
608
609     return offset;
610 }
611
612 /****************************************************************************
613  *      ctl2_alloc_importfile
614  *
615  *  Allocates and initializes an import file definition in a type library.
616  *
617  * RETURNS
618  *
619  *  Success: The offset of the new importinfo.
620  *  Failure: -1 (this is invariably an out of memory condition).
621  */
622 static int ctl2_alloc_importfile(
623         msft_typelib_t *typelib,   /* [I] The type library to allocate in. */
624         int guidoffset,            /* [I] The offset to the GUID for the imported library. */
625         int major_version,         /* [I] The major version number of the imported library. */
626         int minor_version,         /* [I] The minor version number of the imported library. */
627         const char *filename)      /* [I] The filename of the imported library. */
628 {
629     int length;
630     int offset;
631     MSFT_ImpFile *importfile;
632     char *encoded_string;
633
634     length = ctl2_encode_string(typelib, filename, &encoded_string);
635
636     encoded_string[0] <<= 2;
637     encoded_string[0] |= 1;
638
639     for (offset = 0; offset < typelib->typelib_segdir[MSFT_SEG_IMPORTFILES].length;
640          offset += ((((typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xd] << 8) & 0xff)
641              | (typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xc] & 0xff)) >> 2) + 0xc) {
642         if (!memcmp(encoded_string, typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES] + offset + 0xc, length)) return offset;
643     }
644
645     offset = ctl2_alloc_segment(typelib, MSFT_SEG_IMPORTFILES, length + 0xc, 0);
646     if (offset == -1) return -1;
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 add_structure_typeinfo(msft_typelib_t *typelib, type_t *structure);
658 static void add_interface_typeinfo(msft_typelib_t *typelib, type_t *interface);
659
660 /****************************************************************************
661  *      encode_type
662  *
663  *  Encodes a type, storing information in the TYPEDESC and ARRAYDESC
664  *  segments as needed.
665  *
666  * RETURNS
667  *
668  *  Success: 0.
669  *  Failure: -1.
670  */
671 static int encode_type(
672         msft_typelib_t *typelib,   /* [I] The type library in which to encode the TYPEDESC. */
673         int vt,                    /* [I] vt to encode */
674         type_t *type,              /* [I] type */
675         int *encoded_type,         /* [O] The encoded type description. */
676         int *width,                /* [O] The width of the type, or NULL. */
677         int *alignment,            /* [O] The alignment of the type, or NULL. */
678         int *decoded_size)         /* [O] The total size of the unencoded TYPEDESCs, including nested descs. */
679 {
680     int default_type;
681     int scratch;
682     int typeoffset;
683     int *typedata;
684     int target_type;
685     int child_size = 0;
686
687     chat("encode_type vt %d type %p\n", vt, type);
688
689     default_type = 0x80000000 | (vt << 16) | vt;
690     if (!width) width = &scratch;
691     if (!alignment) alignment = &scratch;
692     if (!decoded_size) decoded_size = &scratch;
693
694
695     switch (vt) {
696     case VT_I1:
697     case VT_UI1:
698         *encoded_type = default_type;
699         *width = 1;
700         *alignment = 1;
701         break;
702
703     case VT_INT:
704         *encoded_type = 0x80000000 | (VT_I4 << 16) | VT_INT;
705         if ((typelib->typelib_header.varflags & 0x0f) == SYS_WIN16) {
706             *width = 2;
707             *alignment = 2;
708         } else {
709             *width = 4;
710             *alignment = 4;
711         }
712         break;
713
714     case VT_UINT:
715         *encoded_type = 0x80000000 | (VT_UI4 << 16) | VT_UINT;
716         if ((typelib->typelib_header.varflags & 0x0f) == SYS_WIN16) {
717             *width = 2;
718             *alignment = 2;
719         } else {
720             *width = 4;
721             *alignment = 4;
722         }
723         break;
724
725     case VT_UI2:
726     case VT_I2:
727     case VT_BOOL:
728         *encoded_type = default_type;
729         *width = 2;
730         *alignment = 2;
731         break;
732
733     case VT_I4:
734     case VT_UI4:
735     case VT_R4:
736     case VT_ERROR:
737     case VT_BSTR:
738     case VT_HRESULT:
739         *encoded_type = default_type;
740         *width = 4;
741         *alignment = 4;
742         break;
743
744     case VT_R8:
745         *encoded_type = default_type;
746         *width = 8;
747         *alignment = 8;
748         break;
749
750     case VT_CY:
751         *encoded_type = default_type;
752         *width = 8;
753         *alignment = 4; /* guess? */
754         break;
755
756     case VT_VOID:
757         *encoded_type = 0x80000000 | (VT_EMPTY << 16) | vt;
758         *width = 0;
759         *alignment = 1;
760         break;
761
762     case VT_UNKNOWN:
763     case VT_DISPATCH:
764         *encoded_type = default_type;
765         *width = 4;
766         *alignment = 4;
767         break;
768
769     case VT_VARIANT:
770         *encoded_type = default_type;
771         break;
772
773     case VT_PTR:
774       {
775         int next_vt;
776         while((next_vt = get_type_vt(type->ref)) == 0) {
777             if(type->ref == NULL) {
778                 next_vt = VT_VOID;
779                 break;
780             }
781             type = type->ref;
782         }
783
784         encode_type(typelib, next_vt, type->ref, &target_type, NULL, NULL, &child_size);
785         if(type->ref->type == RPC_FC_IP) {
786             chat("encode_type: skipping ptr\n");
787             *encoded_type = target_type;
788             *width = 4;
789             *alignment = 4;
790             *decoded_size = child_size;
791             break;
792         }
793
794         for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
795             typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
796             if (((typedata[0] & 0xffff) == VT_PTR) && (typedata[1] == target_type)) break;
797         }
798
799         if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
800             int mix_field;
801             
802             if (target_type & 0x80000000) {
803                 mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF;
804             } else {
805                 typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
806                 mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
807             }
808
809             typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
810             typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
811
812             typedata[0] = (mix_field << 16) | VT_PTR;
813             typedata[1] = target_type;
814         }
815
816         *encoded_type = typeoffset;
817
818         *width = 4;
819         *alignment = 4;
820         *decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
821         break;
822     }
823 #if 0
824
825
826     case VT_SAFEARRAY:
827         /* FIXME: Make with the error checking. */
828         FIXME("SAFEARRAY vartype, may not work correctly.\n");
829
830         ctl2_encode_typedesc(typelib, tdesc->u.lptdesc, &target_type, NULL, NULL, &child_size);
831
832         for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
833             typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
834             if (((typedata[0] & 0xffff) == VT_SAFEARRAY) && (typedata[1] == target_type)) break;
835         }
836
837         if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
838             int mix_field;
839             
840             if (target_type & 0x80000000) {
841                 mix_field = ((target_type >> 16) & VT_TYPEMASK) | VT_ARRAY;
842             } else {
843                 typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
844                 mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
845             }
846
847             typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
848             typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
849
850             typedata[0] = (mix_field << 16) | VT_SAFEARRAY;
851             typedata[1] = target_type;
852         }
853
854         *encoded_tdesc = typeoffset;
855
856         *width = 4;
857         *alignment = 4;
858         *decoded_size = sizeof(TYPEDESC) + child_size;
859         break;
860
861
862 #endif
863
864     case VT_USERDEFINED:
865       {
866         int typeinfo_offset;
867         chat("encode_type: VT_USERDEFINED - type %p name = %s type->type %d idx %d\n", type,
868              type->name, type->type, type->typelib_idx);
869
870         if(type->typelib_idx == -1) {
871             chat("encode_type: trying to ref not added type\n");
872             switch(type->type) {
873             case RPC_FC_STRUCT:
874                 add_structure_typeinfo(typelib, type);
875                 break;
876             case RPC_FC_IP:
877                 add_interface_typeinfo(typelib, type);
878                 break;
879             default:
880                 error("encode_type: VT_USERDEFINED - unhandled type %d\n", type->type);
881             }
882         }
883
884         typeinfo_offset = typelib->typelib_typeinfo_offsets[type->typelib_idx];
885         for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
886             typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
887             if ((typedata[0] == ((0x7fff << 16) | VT_USERDEFINED)) && (typedata[1] == typeinfo_offset)) break;
888         }
889
890         if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
891             typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
892             typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
893
894             typedata[0] = (0x7fff << 16) | VT_USERDEFINED;
895             typedata[1] = typeinfo_offset;
896         }
897
898         *encoded_type = typeoffset;
899         *width = 0;
900         *alignment = 1;
901
902         if(type->type == RPC_FC_IP) {
903             typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
904             typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
905
906             typedata[0] = (0x7fff << 16) | VT_PTR;
907             typedata[1] = *encoded_type;
908             *encoded_type = typeoffset;
909             *width = 4;
910             *alignment = 4;
911             *decoded_size += 8;
912         }            
913         break;
914       }
915
916     default:
917         error("encode_type: unrecognized type %d.\n", vt);
918         *encoded_type = default_type;
919         *width = 0;
920         *alignment = 1;
921         break;
922     }
923
924     return 0;
925 }
926
927 static void dump_type(type_t *t)
928 {
929     chat("dump_type: %p name %s type %d ref %p rname %s\n", t, t->name, t->type, t->ref, t->rname);
930     if(t->ref) dump_type(t->ref);
931 }
932
933 static int encode_var(
934         msft_typelib_t *typelib,   /* [I] The type library in which to encode the TYPEDESC. */
935         var_t *var,                /* [I] The type description to encode. */
936         int *encoded_type,         /* [O] The encoded type description. */
937         int *width,                /* [O] The width of the type, or NULL. */
938         int *alignment,            /* [O] The alignment of the type, or NULL. */
939         int *decoded_size)         /* [O] The total size of the unencoded TYPEDESCs, including nested descs. */
940 {
941     int typeoffset;
942     int *typedata;
943     int target_type;
944     int child_size;
945     int vt;
946     int scratch;
947     type_t *type;
948
949     if (!width) width = &scratch;
950     if (!alignment) alignment = &scratch;
951     if (!decoded_size) decoded_size = &scratch;
952     *decoded_size = 0;
953
954     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);
955     if(var->ptr_level) {
956         int skip_ptr;
957         var->ptr_level--;
958         skip_ptr = encode_var(typelib, var, &target_type, NULL, NULL, &child_size);
959         var->ptr_level++;
960
961         if(skip_ptr == 2) {
962             chat("encode_var: skipping ptr\n");
963             *encoded_type = target_type;
964             *decoded_size = child_size;
965             *width = 4;
966             *alignment = 4;
967             return 0;
968         }
969
970         for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
971             typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
972             if (((typedata[0] & 0xffff) == VT_PTR) && (typedata[1] == target_type)) break;
973         }
974
975         if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
976             int mix_field;
977             
978             if (target_type & 0x80000000) {
979                 mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF;
980             } else {
981                 typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
982                 mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
983             }
984
985             typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
986             typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
987
988             typedata[0] = (mix_field << 16) | VT_PTR;
989             typedata[1] = target_type;
990         }
991
992         *encoded_type = typeoffset;
993
994         *width = 4;
995         *alignment = 4;
996         *decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
997         return 0;
998     }
999
1000     if(var->array) {
1001         expr_t *dim = var->array;
1002         expr_t *array_save;
1003         int num_dims = 1, elements = 1, arrayoffset;
1004         int *arraydata;
1005
1006         while(NEXT_LINK(dim)) {
1007             dim = NEXT_LINK(dim);
1008             num_dims++;
1009         }
1010         chat("array with %d dimensions\n", num_dims);
1011         array_save = var->array;
1012         var->array = NULL;
1013         encode_var(typelib, var, &target_type, width, alignment, NULL);
1014         var->array = array_save;
1015         arrayoffset = ctl2_alloc_segment(typelib, MSFT_SEG_ARRAYDESC, (2 + 2 * num_dims) * sizeof(long), 0);
1016         arraydata = (void *)&typelib->typelib_segment_data[MSFT_SEG_ARRAYDESC][arrayoffset];
1017
1018         arraydata[0] = target_type;
1019         arraydata[1] = num_dims;
1020         arraydata[1] |= ((num_dims * 2 * sizeof(long)) << 16);
1021
1022         arraydata += 2;
1023         while(dim) {
1024             arraydata[0] = dim->cval;
1025             arraydata[1] = 0;
1026             arraydata += 2;
1027             elements *= dim->cval;
1028             dim = PREV_LINK(dim);
1029         }
1030
1031         typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
1032         typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
1033
1034         typedata[0] = (0x7ffe << 16) | VT_CARRAY;
1035         typedata[1] = arrayoffset;
1036
1037         *encoded_type = typeoffset;
1038         *width = *width * elements;
1039         *decoded_size = 20 /*sizeof(ARRAYDESC)*/ + (num_dims - 1) * 8 /*sizeof(SAFEARRAYBOUND)*/;
1040         return 0;
1041     }
1042     dump_type(var->type);
1043
1044     vt = get_var_vt(var);
1045     type = var->type;
1046     while(!vt) {
1047         if(type->ref == NULL) {
1048             vt = VT_VOID;
1049             break;
1050         }
1051         type = type->ref;
1052         vt = get_type_vt(type);
1053     }
1054     encode_type(typelib, vt, type, encoded_type, width, alignment, decoded_size);
1055     if(type->type == RPC_FC_IP) return 2;
1056     return 0;
1057 }
1058
1059     
1060 /****************************************************************************
1061  *      ctl2_find_nth_reference
1062  *
1063  *  Finds a reference by index into the linked list of reference records.
1064  *
1065  * RETURNS
1066  *
1067  *  Success: Offset of the desired reference record.
1068  *  Failure: -1.
1069  */
1070 static int ctl2_find_nth_reference(
1071         msft_typelib_t *typelib,   /* [I] The type library in which to search. */
1072         int offset,                /* [I] The starting offset of the reference list. */
1073         int index)                 /* [I] The index of the reference to find. */
1074 {
1075     MSFT_RefRecord *ref;
1076
1077     for (; index && (offset != -1); index--) {
1078         ref = (MSFT_RefRecord *)&typelib->typelib_segment_data[MSFT_SEG_REFERENCES][offset];
1079         offset = ref->onext;
1080     }
1081
1082     return offset;
1083 }
1084
1085
1086 static void write_value(msft_typelib_t* typelib, int *out, int vt, void *value)
1087 {
1088     switch(vt) {
1089     case VT_I2:
1090     case VT_I4:
1091     case VT_R4:
1092     case VT_BOOL:
1093     case VT_I1:
1094     case VT_UI1:
1095     case VT_UI2:
1096     case VT_UI4:
1097     case VT_INT:
1098     case VT_UINT:
1099     case VT_HRESULT:
1100       {
1101         unsigned long *lv = value;
1102         if((*lv & 0x3ffffff) == *lv) {
1103             *out = 0x80000000;
1104             *out |= vt << 26;
1105             *out |= *lv;
1106         } else {
1107             int offset = ctl2_alloc_segment(typelib, MSFT_SEG_CUSTDATA, 8, 0);
1108             *((unsigned short *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset]) = vt;
1109             memcpy(&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+2], value, 4);
1110             *((unsigned short *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+6]) = 0x5757;
1111             *out = offset;
1112         }
1113         return;
1114       }
1115     case VT_BSTR:
1116       {
1117         char *s = (char *) value;
1118         int len = strlen(s), seg_len = (len + 6 + 3) & ~0x3;
1119         int offset = ctl2_alloc_segment(typelib, MSFT_SEG_CUSTDATA, seg_len, 0);
1120         *((unsigned short *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset]) = vt;
1121         *((unsigned int *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+2]) = len;        
1122         memcpy(&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+6], value, len);
1123         len += 6;
1124         while(len < seg_len) {
1125             *((char *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+len]) = 0x57;
1126             len++;
1127         }
1128         *out = offset;
1129         return;
1130       }
1131
1132     default:
1133         warning("can't write value of type %d yet\n", vt);
1134     }
1135     return;
1136 }
1137
1138 static HRESULT set_custdata(msft_typelib_t *typelib, REFGUID guid,
1139                             int vt, void *value, int *offset)
1140 {
1141     MSFT_GuidEntry guidentry;
1142     int guidoffset;
1143     int custoffset;
1144     int *custdata;
1145     int data_out;
1146
1147     guidentry.guid = *guid;
1148
1149     guidentry.hreftype = -1;
1150     guidentry.next_hash = -1;
1151
1152     guidoffset = ctl2_alloc_guid(typelib, &guidentry);
1153     if (guidoffset == -1) return E_OUTOFMEMORY;
1154     write_value(typelib, &data_out, vt, value);
1155
1156     custoffset = ctl2_alloc_segment(typelib, MSFT_SEG_CUSTDATAGUID, 12, 0);
1157     if (custoffset == -1) return E_OUTOFMEMORY;
1158
1159     custdata = (int *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATAGUID][custoffset];
1160     custdata[0] = guidoffset;
1161     custdata[1] = data_out;
1162     custdata[2] = *offset;
1163     *offset = custoffset;
1164
1165     return S_OK;
1166 }
1167
1168 static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, func_t *func, int index)
1169 {
1170     int offset;
1171     int *typedata;
1172     int i, id;
1173     int decoded_size, extra_attr = 0;
1174     int num_params = 0, num_defaults = 0;
1175     var_t *arg, *last_arg = NULL;
1176     char *namedata;
1177     attr_t *attr;
1178     unsigned int funcflags = 0, callconv = 4 /* CC_STDCALL */;
1179     unsigned int funckind = 1 /* FUNC_PUREVIRTUAL */, invokekind = 1 /* INVOKE_FUNC */;
1180     int help_context = 0, help_string_context = 0, help_string_offset = -1;
1181
1182     id = ((0x6000 | typeinfo->typeinfo->cImplTypes) << 16) | index;
1183
1184     chat("add_func_desc(%p,%d)\n", typeinfo, index);
1185
1186     for(attr = func->def->attrs; attr; attr = NEXT_LINK(attr)) {
1187         if(attr->type == ATTR_LOCAL) {
1188             chat("add_func_desc: skipping local function\n");
1189             return S_FALSE;
1190         }
1191     }
1192
1193     if (!typeinfo->typedata) {
1194         typeinfo->typedata = xmalloc(0x2000);
1195         typeinfo->typedata[0] = 0;
1196     }
1197
1198     for(arg = func->args; arg; arg = NEXT_LINK(arg)) {
1199         last_arg = arg;
1200         num_params++;
1201         for(attr = arg->attrs; attr; attr = NEXT_LINK(attr)) {
1202             if(attr->type == ATTR_DEFAULTVALUE_EXPR || attr->type == ATTR_DEFAULTVALUE_STRING) {
1203                 num_defaults++;
1204                 break;
1205             }
1206         }
1207     }
1208
1209     chat("add_func_desc: num of params %d\n", num_params);
1210
1211     for(attr = func->def->attrs; attr; attr = NEXT_LINK(attr)) {
1212         expr_t *expr = attr->u.pval; 
1213         switch(attr->type) {
1214         case ATTR_HELPCONTEXT:
1215             extra_attr = 1;
1216             help_context = expr->u.lval;
1217             break;
1218         case ATTR_HELPSTRING:
1219             extra_attr = 2;
1220             help_string_offset = ctl2_alloc_string(typeinfo->typelib, attr->u.pval);
1221             break;
1222         case ATTR_HELPSTRINGCONTEXT:
1223             extra_attr = 6;
1224             help_string_context = expr->u.lval;
1225             break;
1226         case ATTR_HIDDEN:
1227             funcflags |= 0x40; /* FUNCFLAG_FHIDDEN */
1228             break;
1229         case ATTR_ID:
1230             id = expr->u.lval;
1231             break;
1232         case ATTR_OUT:
1233             break;
1234         case ATTR_PROPGET:
1235             invokekind = 0x2; /* INVOKE_PROPERTYGET */
1236             break;
1237         case ATTR_PROPPUT:
1238             invokekind = 0x4; /* INVOKE_PROPERTYPUT */
1239             break;
1240         case ATTR_RESTRICTED:
1241             funcflags |= 0x1; /* FUNCFLAG_FRESTRICTED */
1242             break;
1243         default:
1244             warning("add_func_desc: ignoring attr %d\n", attr->type);
1245             break;
1246         }
1247     }
1248     /* allocate type data space for us */
1249     offset = typeinfo->typedata[0];
1250     typeinfo->typedata[0] += 0x18 + extra_attr * sizeof(int) + (num_params * (num_defaults ? 16 : 12));
1251     typedata = typeinfo->typedata + (offset >> 2) + 1;
1252
1253     /* fill out the basic type information */
1254     typedata[0] = (0x18 + extra_attr * sizeof(int) + (num_params * (num_defaults ? 16 : 12))) | (index << 16);
1255     encode_var(typeinfo->typelib, func->def, &typedata[1], NULL, NULL, &decoded_size);
1256     typedata[2] = funcflags;
1257     typedata[3] = ((52 /*sizeof(FUNCDESC)*/ + decoded_size) << 16) | typeinfo->typeinfo->cbSizeVft;
1258     typedata[4] = (index << 16) | (callconv << 8) | (invokekind << 3) | funckind;
1259     if(num_defaults) typedata[4] |= 0x1000;
1260     typedata[5] = num_params;
1261
1262     /* NOTE: High word of typedata[3] is total size of FUNCDESC + size of all ELEMDESCs for params + TYPEDESCs for pointer params and return types. */
1263     /* That is, total memory allocation required to reconstitute the FUNCDESC in its entirety. */
1264     typedata[3] += (16 /*sizeof(ELEMDESC)*/ * num_params) << 16;
1265     typedata[3] += (24 /*sizeof(PARAMDESCEX)*/ * num_defaults) << 16;
1266
1267     switch(extra_attr) {
1268     case 6: typedata[11] = help_string_context;
1269     case 5: typedata[10] = -1;
1270     case 4: typedata[9] = -1;
1271     case 3: typedata[8] = -1;
1272     case 2: typedata[7] = help_string_offset;
1273     case 1: typedata[6] = help_context;
1274     case 0:
1275         break;
1276     default:
1277         warning("unknown number of optional attrs\n");
1278     }
1279
1280     for (arg = last_arg, i = 0; arg; arg = PREV_LINK(arg), i++) {
1281         attr_t *attr;
1282         int paramflags = 0;
1283         int *paramdata = typedata + 6 + extra_attr + (num_defaults ? num_params : 0) + i * 3;
1284         int *defaultdata = num_defaults ? typedata + 6 + extra_attr + i : NULL;
1285
1286         if(defaultdata) *defaultdata = -1;
1287
1288         encode_var(typeinfo->typelib, arg, paramdata, NULL, NULL, &decoded_size);
1289         for(attr = arg->attrs; attr; attr = NEXT_LINK(attr)) {
1290             switch(attr->type) {
1291             case ATTR_DEFAULTVALUE_EXPR:
1292               {
1293                 expr_t *expr = (expr_t *)attr->u.pval;
1294                 paramflags |= 0x30; /* PARAMFLAG_FHASDEFAULT | PARAMFLAG_FOPT */
1295                 chat("default value %ld\n", expr->cval);
1296                 write_value(typeinfo->typelib, defaultdata, (*paramdata >> 16) & 0x1ff, &expr->cval);
1297                 break;
1298               }
1299             case ATTR_DEFAULTVALUE_STRING:
1300               {
1301                 char *s = (char *)attr->u.pval;
1302                 paramflags |= 0x30; /* PARAMFLAG_FHASDEFAULT | PARAMFLAG_FOPT */
1303                 chat("default value '%s'\n", s);
1304                 write_value(typeinfo->typelib, defaultdata, (*paramdata >> 16) & 0x1ff, s);
1305                 break;
1306               }
1307             case ATTR_IN:
1308                 paramflags |= 0x01; /* PARAMFLAG_FIN */
1309                 break;
1310             case ATTR_OPTIONAL:
1311                 paramflags |= 0x10; /* PARAMFLAG_FOPT */
1312                 break;
1313             case ATTR_OUT:
1314                 paramflags |= 0x02; /* PARAMFLAG_FOUT */
1315                 break;
1316             case ATTR_RETVAL:
1317                 paramflags |= 0x08; /* PARAMFLAG_FRETVAL */
1318                 break;
1319             default:
1320                 chat("unhandled param attr %d\n", attr->type);
1321                 break;
1322             }
1323         }
1324         paramdata[1] = -1;
1325         paramdata[2] = paramflags;
1326         typedata[3] += decoded_size << 16;
1327     }
1328
1329     /* update the index data */
1330     typeinfo->indices[index] = id; 
1331     typeinfo->names[index] = -1;
1332     typeinfo->offsets[index] = offset;
1333
1334     /* ??? */
1335     if (!typeinfo->typeinfo->res2) typeinfo->typeinfo->res2 = 0x20;
1336     typeinfo->typeinfo->res2 <<= 1;
1337     /* ??? */
1338     if (index < 2) typeinfo->typeinfo->res2 += num_params << 4;
1339
1340     if (typeinfo->typeinfo->res3 == -1) typeinfo->typeinfo->res3 = 0;
1341     typeinfo->typeinfo->res3 += 0x38 + num_params * 0x10;
1342     if(num_defaults) typeinfo->typeinfo->res3 += num_params * 0x4;
1343
1344     /* adjust size of VTBL */
1345     typeinfo->typeinfo->cbSizeVft += 4;
1346
1347     /* Increment the number of function elements */
1348     typeinfo->typeinfo->cElement += 1;
1349
1350
1351     offset = ctl2_alloc_name(typeinfo->typelib, func->def->name);
1352     chat("name offset = %d index %d\n", offset, index);
1353     typeinfo->names[index] = offset;
1354
1355     namedata = typeinfo->typelib->typelib_segment_data[MSFT_SEG_NAME] + offset;
1356     namedata[9] &= ~0x10;
1357     if (*((INT *)namedata) == -1) {
1358         *((INT *)namedata) = typeinfo->typelib->typelib_typeinfo_offsets[typeinfo->typeinfo->typekind >> 16];
1359     }
1360
1361     for (arg = last_arg, i = 0; arg; arg = PREV_LINK(arg), i++) {
1362         /* FIXME: Almost certainly easy to break */
1363         int *paramdata = &typeinfo->typedata[typeinfo->offsets[index] >> 2];
1364         paramdata += 7 + extra_attr + (num_defaults ? num_params : 0) + i * 3;
1365         offset = ctl2_alloc_name(typeinfo->typelib, arg->name);
1366         paramdata[1] = offset;
1367         chat("param %d name %s offset %d\n", i, arg->name, offset);
1368     }
1369     return S_OK;
1370 }
1371
1372
1373 static void set_alignment(
1374         msft_typeinfo_t* typeinfo,
1375         WORD cbAlignment)
1376 {
1377
1378     if (!cbAlignment) return;
1379     if (cbAlignment > 16) return;
1380
1381     typeinfo->typeinfo->typekind &= ~0xf800;
1382
1383     /* FIXME: There's probably some way to simplify this. */
1384     switch (typeinfo->typeinfo->typekind & 15) {
1385     case TKIND_ALIAS:
1386     default:
1387         break;
1388
1389     case TKIND_ENUM:
1390     case TKIND_INTERFACE:
1391     case TKIND_DISPATCH:
1392     case TKIND_COCLASS:
1393         if (cbAlignment > 4) cbAlignment = 4;
1394         break;
1395
1396     case TKIND_RECORD:
1397     case TKIND_MODULE:
1398     case TKIND_UNION:
1399         cbAlignment = 1;
1400         break;
1401     }
1402
1403     typeinfo->typeinfo->typekind |= cbAlignment << 11;
1404
1405     return;
1406 }
1407
1408 static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var)
1409 {
1410     int offset;
1411     INT *typedata;
1412     int var_datawidth;
1413     int var_alignment;
1414     int var_type_size;
1415     int alignment;
1416     int varflags = 0;
1417     attr_t *attr;
1418     char *namedata;
1419
1420     chat("add_var_desc(%d,%s) array %p\n", index, var->name, var->array);
1421
1422     if ((typeinfo->typeinfo->cElement >> 16) != index) {
1423         error("Out-of-order element.\n");
1424         return TYPE_E_ELEMENTNOTFOUND;
1425     }
1426
1427
1428     for(attr = var->attrs; attr; attr = NEXT_LINK(attr)) {
1429         switch(attr->type) {
1430         default:
1431             warning("AddVarDesc: unhandled attr type %d\n", attr->type);
1432             break;
1433         }
1434     }
1435
1436     if (!typeinfo->typedata) {
1437         typeinfo->typedata = xmalloc(0x2000);
1438         typeinfo->typedata[0] = 0;
1439     }
1440
1441     /* allocate type data space for us */
1442     offset = typeinfo->typedata[0];
1443     typeinfo->typedata[0] += 0x14;
1444     typedata = typeinfo->typedata + (offset >> 2) + 1;
1445
1446     /* fill out the basic type information */
1447     typedata[0] = 0x14 | (index << 16);
1448     typedata[2] = varflags;
1449     typedata[3] = (36 /*sizeof(VARDESC)*/ << 16) | 0;
1450
1451     /* update the index data */
1452     typeinfo->indices[index] = 0x40000000 + index;
1453     typeinfo->names[index] = -1;
1454     typeinfo->offsets[index] = offset;
1455
1456     /* figure out type widths and whatnot */
1457     encode_var(typeinfo->typelib, var, &typedata[1], &var_datawidth,
1458                &var_alignment, &var_type_size);
1459
1460     /* pad out starting position to data width */
1461     typeinfo->datawidth += var_alignment - 1;
1462     typeinfo->datawidth &= ~(var_alignment - 1);
1463     typedata[4] = typeinfo->datawidth;
1464     
1465     /* add the new variable to the total data width */
1466     typeinfo->datawidth += var_datawidth;
1467
1468     /* add type description size to total required allocation */
1469     typedata[3] += var_type_size << 16;
1470
1471     /* fix type alignment */
1472     alignment = (typeinfo->typeinfo->typekind >> 11) & 0x1f;
1473     if (alignment < var_alignment) {
1474         alignment = var_alignment;
1475         typeinfo->typeinfo->typekind &= ~0xf800;
1476         typeinfo->typeinfo->typekind |= alignment << 11;
1477     }
1478
1479     /* ??? */
1480     if (!typeinfo->typeinfo->res2) typeinfo->typeinfo->res2 = 0x1a;
1481     if ((index == 0) || (index == 1) || (index == 2) || (index == 4) || (index == 9)) {
1482         typeinfo->typeinfo->res2 <<= 1;
1483     }
1484
1485     /* ??? */
1486     if (typeinfo->typeinfo->res3 == -1) typeinfo->typeinfo->res3 = 0;
1487     typeinfo->typeinfo->res3 += 0x2c;
1488
1489     /* increment the number of variable elements */
1490     typeinfo->typeinfo->cElement += 0x10000;
1491
1492     /* pad data width to alignment */
1493     typeinfo->typeinfo->size = (typeinfo->datawidth + (alignment - 1)) & ~(alignment - 1);
1494
1495     offset = ctl2_alloc_name(typeinfo->typelib, var->name);
1496     if (offset == -1) return E_OUTOFMEMORY;
1497
1498     namedata = typeinfo->typelib->typelib_segment_data[MSFT_SEG_NAME] + offset;
1499     if (*((INT *)namedata) == -1) {
1500         *((INT *)namedata) = typeinfo->typelib->typelib_typeinfo_offsets[typeinfo->typeinfo->typekind >> 16];
1501         namedata[9] |= 0x10;
1502     }
1503     if ((typeinfo->typeinfo->typekind & 15) == TKIND_ENUM) {
1504         namedata[9] |= 0x20;
1505     }
1506     typeinfo->names[index] = offset;
1507
1508     return S_OK;
1509 }
1510
1511 static HRESULT add_impl_type(msft_typeinfo_t *typeinfo, type_t *ref)
1512 {
1513     if(ref->typelib_idx == -1)
1514         add_interface_typeinfo(typeinfo->typelib, ref);
1515     if(ref->typelib_idx == -1)
1516         error("add_impl_type: unable to add inherited interface\n");
1517
1518     typeinfo->typeinfo->datatype1 = typeinfo->typelib->typelib_typeinfo_offsets[ref->typelib_idx];
1519     typeinfo->typeinfo->cImplTypes++;
1520     return S_OK;
1521 }
1522
1523 static msft_typeinfo_t *create_msft_typeinfo(msft_typelib_t *typelib, enum type_kind kind,
1524                                              char *name, attr_t *attr, int idx)
1525 {
1526     msft_typeinfo_t *msft_typeinfo;
1527     int nameoffset;
1528     int typeinfo_offset;
1529     MSFT_TypeInfoBase *typeinfo;
1530     MSFT_GuidEntry guidentry;
1531
1532     chat("create_msft_typeinfo: name %s kind %d\n", name, kind);
1533
1534     msft_typeinfo = xmalloc(sizeof(*msft_typeinfo));
1535
1536     msft_typeinfo->typelib = typelib;
1537
1538     nameoffset = ctl2_alloc_name(typelib, name);
1539     typeinfo_offset = ctl2_alloc_typeinfo(typelib, nameoffset);
1540     typeinfo = (MSFT_TypeInfoBase *)&typelib->typelib_segment_data[MSFT_SEG_TYPEINFO][typeinfo_offset];
1541
1542     typelib->typelib_segment_data[MSFT_SEG_NAME][nameoffset + 9] = 0x38;
1543     *((int *)&typelib->typelib_segment_data[MSFT_SEG_NAME][nameoffset]) = typeinfo_offset;
1544
1545     msft_typeinfo->typeinfo = typeinfo;
1546
1547     typeinfo->typekind |= kind | 0x220;
1548     set_alignment(msft_typeinfo, 4);
1549
1550     for( ; attr; attr = NEXT_LINK(attr)) {
1551         switch(attr->type) {
1552         case ATTR_HELPCONTEXT:
1553           {
1554             expr_t *expr = (expr_t*)attr->u.pval;
1555             typeinfo->helpcontext = expr->cval;
1556             break;
1557           }
1558         case ATTR_HELPSTRING:
1559           {
1560             int offset = ctl2_alloc_string(typelib, attr->u.pval);
1561             if (offset == -1) break;
1562             typeinfo->docstringoffs = offset;
1563             break;
1564           }
1565         case ATTR_HELPSTRINGCONTEXT:
1566           {
1567             expr_t *expr = (expr_t*)attr->u.pval;
1568             typeinfo->helpstringcontext = expr->cval;
1569             break;
1570           }
1571         case ATTR_HIDDEN:
1572             typeinfo->flags |= 0x10; /* TYPEFLAG_FHIDDEN */
1573             break;
1574
1575         case ATTR_ODL:
1576             break;
1577
1578         case ATTR_RESTRICTED:
1579             typeinfo->flags |= 0x200; /* TYPEFLAG_FRESTRICTED */
1580             break;
1581
1582         case ATTR_UUID:
1583             guidentry.guid = *(GUID*)attr->u.pval;
1584             guidentry.hreftype = typelib->typelib_typeinfo_offsets[typeinfo->typekind >> 16];
1585             guidentry.next_hash = -1;
1586             typeinfo->posguid = ctl2_alloc_guid(typelib, &guidentry);
1587 #if 0
1588             if (IsEqualIID(guid, &IID_IDispatch)) {
1589                 typelib->typelib_header.dispatchpos = typelib->typelib_typeinfo_offsets[typeinfo->typekind >> 16];
1590             }
1591 #endif
1592             break;
1593
1594         case ATTR_VERSION:
1595             typeinfo->version = attr->u.ival;
1596             break;
1597
1598         default:
1599             warning("create_msft_typeinfo: ignoring attr %d\n", attr->type);
1600             break;
1601         }
1602     }
1603
1604     if (typelib->last_typeinfo) typelib->last_typeinfo->next_typeinfo = msft_typeinfo;
1605     typelib->last_typeinfo = msft_typeinfo;
1606     if (!typelib->typeinfos) typelib->typeinfos = msft_typeinfo;
1607
1608
1609     return msft_typeinfo;
1610 }
1611
1612
1613 static void add_interface_typeinfo(msft_typelib_t *typelib, type_t *interface)
1614 {
1615     int idx = 0;
1616     func_t *cur = interface->funcs;
1617     msft_typeinfo_t *msft_typeinfo;
1618
1619     interface->typelib_idx = typelib->typelib_header.nrtypeinfos;
1620     msft_typeinfo = create_msft_typeinfo(typelib, TKIND_INTERFACE, interface->name, interface->attrs,
1621                                          typelib->typelib_header.nrtypeinfos);
1622     msft_typeinfo->typeinfo->size = 4;
1623
1624     if(interface->ref)
1625         add_impl_type(msft_typeinfo, interface->ref);
1626
1627     while(NEXT_LINK(cur)) cur = NEXT_LINK(cur);
1628     while(cur) {
1629         if(add_func_desc(msft_typeinfo, cur, idx) == S_OK)
1630             idx++;
1631         cur = PREV_LINK(cur);
1632     }
1633 }
1634
1635 static void add_structure_typeinfo(msft_typelib_t *typelib, type_t *structure)
1636 {
1637     int idx = 0;
1638     var_t *cur = structure->fields;
1639     msft_typeinfo_t *msft_typeinfo;
1640
1641     structure->typelib_idx = typelib->typelib_header.nrtypeinfos;
1642     msft_typeinfo = create_msft_typeinfo(typelib, TKIND_RECORD, structure->name, structure->attrs,
1643                                          typelib->typelib_header.nrtypeinfos);
1644     msft_typeinfo->typeinfo->size = 0;
1645
1646     while(NEXT_LINK(cur)) cur = NEXT_LINK(cur);
1647     while(cur) {
1648         add_var_desc(msft_typeinfo, idx, cur);
1649         idx++;
1650         cur = PREV_LINK(cur);
1651     }
1652 }
1653
1654 static void add_entry(msft_typelib_t *typelib, typelib_entry_t *entry)
1655 {
1656     switch(entry->kind) {
1657     case TKIND_INTERFACE:
1658         add_interface_typeinfo(typelib, entry->u.interface);
1659         break;
1660
1661     case TKIND_RECORD:
1662         add_structure_typeinfo(typelib, entry->u.structure);
1663         break;
1664
1665     default:
1666         error("add_entry: unhandled type %d\n", entry->kind);
1667         break;
1668     }
1669 }
1670
1671
1672 static void set_name(msft_typelib_t *typelib)
1673 {
1674     int offset;
1675
1676     offset = ctl2_alloc_name(typelib, typelib->typelib->name);
1677     if (offset == -1) return;
1678     typelib->typelib_header.NameOffset = offset;
1679     return;
1680 }
1681
1682 static void set_version(msft_typelib_t *typelib)
1683 {
1684     long version = MAKELONG(0,0);
1685     attr_t *attr;
1686
1687     for(attr = typelib->typelib->attrs; attr; attr = NEXT_LINK(attr)) {
1688         if(attr->type == ATTR_VERSION) {
1689             version = attr->u.ival;
1690         }
1691     }
1692     typelib->typelib_header.version = version;
1693     return;
1694 }
1695
1696 static void set_guid(msft_typelib_t *typelib)
1697 {
1698     MSFT_GuidEntry guidentry;
1699     int offset;
1700     attr_t *attr;
1701     GUID guid = {0,0,0,{0,0,0,0,0,0}};
1702
1703     guidentry.guid = guid;
1704     guidentry.hreftype = -2;
1705     guidentry.next_hash = -1;
1706
1707     for(attr = typelib->typelib->attrs; attr; attr = NEXT_LINK(attr)) {
1708         if(attr->type == ATTR_UUID) {
1709             guidentry.guid = *(GUID*)(attr->u.pval);
1710         }
1711     }
1712
1713     offset = ctl2_alloc_guid(typelib, &guidentry);
1714     
1715     if (offset == -1) return;
1716
1717     typelib->typelib_header.posguid = offset;
1718
1719     return;
1720 }
1721
1722 static void set_doc_string(msft_typelib_t *typelib)
1723 {
1724     attr_t *attr;
1725     int offset;
1726
1727     for(attr = typelib->typelib->attrs; attr; attr = NEXT_LINK(attr)) {
1728         if(attr->type == ATTR_HELPSTRING) {
1729             offset = ctl2_alloc_string(typelib, attr->u.pval);
1730             if (offset == -1) return;
1731             typelib->typelib_header.helpstring = offset;
1732         }
1733     }
1734     return;
1735 }
1736
1737 static void set_help_file_name(msft_typelib_t *typelib)
1738 {
1739     int offset;
1740     attr_t *attr;
1741     for(attr = typelib->typelib->attrs; attr; attr = NEXT_LINK(attr)) {
1742         if(attr->type == ATTR_HELPFILE) {
1743             offset = ctl2_alloc_string(typelib, attr->u.pval);
1744             if (offset == -1) return;
1745             typelib->typelib_header.helpfile = offset;
1746             typelib->typelib_header.varflags |= 0x10;
1747         }
1748     }
1749     return;
1750 }
1751
1752 static void set_help_context(msft_typelib_t *typelib)
1753 {
1754     attr_t *attr;
1755     for(attr = typelib->typelib->attrs; attr; attr = NEXT_LINK(attr)) {
1756         if(attr->type == ATTR_HELPCONTEXT) {
1757             expr_t *expr = (expr_t *)attr->u.pval;
1758             typelib->typelib_header.helpcontext = expr->cval;
1759         }
1760     }
1761     return;
1762 }
1763
1764 static void set_help_string_dll(msft_typelib_t *typelib)
1765 {
1766     int offset;
1767     attr_t *attr;
1768     for(attr = typelib->typelib->attrs; attr; attr = NEXT_LINK(attr)) {
1769         if(attr->type == ATTR_HELPSTRINGDLL) {
1770             offset = ctl2_alloc_string(typelib, attr->u.pval);
1771             if (offset == -1) return;
1772             typelib->help_string_dll_offset = offset;
1773             typelib->typelib_header.varflags |= 0x100;
1774         }
1775     }
1776     return;
1777 }
1778
1779 static void set_help_string_context(msft_typelib_t *typelib)
1780 {
1781     attr_t *attr;
1782     for(attr = typelib->typelib->attrs; attr; attr = NEXT_LINK(attr)) {
1783         if(attr->type == ATTR_HELPSTRINGCONTEXT) {
1784             expr_t *expr = (expr_t *)attr->u.pval;
1785             typelib->typelib_header.helpstringcontext = expr->cval;
1786         }
1787     }
1788     return;
1789 }
1790
1791 static void set_lcid(msft_typelib_t *typelib)
1792 {
1793     typelib->typelib_header.lcid2 = 0x0;
1794     return;
1795 }
1796
1797 static void set_lib_flags(msft_typelib_t *typelib)
1798 {
1799     attr_t *attr;
1800
1801     typelib->typelib_header.flags = 0;
1802     for(attr = typelib->typelib->attrs; attr; attr = NEXT_LINK(attr)) {
1803         switch(attr->type) {
1804         case ATTR_CONTROL:
1805             typelib->typelib_header.flags |= 0x02; /* LIBFLAG_FCONTROL */
1806             break;
1807         case ATTR_HIDDEN:
1808             typelib->typelib_header.flags |= 0x04; /* LIBFLAG_FHIDDEN */
1809             break;
1810         case ATTR_RESTRICTED:
1811             typelib->typelib_header.flags |= 0x01; /* LIBFLAG_FRESTRICTED */
1812             break;
1813         default:
1814             break;
1815         }
1816     }
1817     return;
1818 }
1819
1820 static int ctl2_write_chunk(int fd, void *segment, int length)
1821 {
1822     if (write(fd, segment, length) != length) {
1823         close(fd);
1824         return 0;
1825     }
1826     return -1;
1827 }
1828
1829 static int ctl2_write_segment(msft_typelib_t *typelib, int fd, int segment)
1830 {
1831     if (write(fd, typelib->typelib_segment_data[segment], typelib->typelib_segdir[segment].length)
1832         != typelib->typelib_segdir[segment].length) {
1833         close(fd);
1834         return 0;
1835     }
1836
1837     return -1;
1838 }
1839
1840 static void ctl2_finalize_typeinfos(msft_typelib_t *typelib, int filesize)
1841 {
1842     msft_typeinfo_t *typeinfo;
1843
1844     for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
1845         typeinfo->typeinfo->memoffset = filesize;
1846         if (typeinfo->typedata) {
1847             /*LayOut(typeinfo);*/
1848             filesize += typeinfo->typedata[0] + ((typeinfo->typeinfo->cElement >> 16) * 12) + ((typeinfo->typeinfo->cElement & 0xffff) * 12) + 4;
1849         }
1850     }
1851 }
1852
1853 static int ctl2_finalize_segment(msft_typelib_t *typelib, int filepos, int segment)
1854 {
1855     if (typelib->typelib_segdir[segment].length) {
1856         typelib->typelib_segdir[segment].offset = filepos;
1857     } else {
1858         typelib->typelib_segdir[segment].offset = -1;
1859     }
1860
1861     return typelib->typelib_segdir[segment].length;
1862 }
1863
1864
1865 static void ctl2_write_typeinfos(msft_typelib_t *typelib, int fd)
1866 {
1867     msft_typeinfo_t *typeinfo;
1868
1869     for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
1870         if (!typeinfo->typedata) continue;
1871
1872         ctl2_write_chunk(fd, typeinfo->typedata, typeinfo->typedata[0] + 4);
1873         ctl2_write_chunk(fd, typeinfo->indices, ((typeinfo->typeinfo->cElement & 0xffff) + (typeinfo->typeinfo->cElement >> 16)) * 4);
1874         chat("writing name chunk len %d %08lx\n", ((typeinfo->typeinfo->cElement & 0xffff) + (typeinfo->typeinfo->cElement >> 16)) * 4, *(DWORD*)typeinfo->names);
1875         ctl2_write_chunk(fd, typeinfo->names, ((typeinfo->typeinfo->cElement & 0xffff) + (typeinfo->typeinfo->cElement >> 16)) * 4);
1876         ctl2_write_chunk(fd, typeinfo->offsets, ((typeinfo->typeinfo->cElement & 0xffff) + (typeinfo->typeinfo->cElement >> 16)) * 4);
1877     }
1878 }
1879
1880 static int save_all_changes(msft_typelib_t *typelib)
1881 {
1882     int retval;
1883     int filepos;
1884     int fd;
1885
1886     chat("save_all_changes(%p)\n", typelib);
1887
1888     retval = TYPE_E_IOERROR;
1889
1890     fd = creat(typelib->typelib->filename, 0666);
1891     if (fd == -1) return retval;
1892
1893     filepos = sizeof(MSFT_Header) + sizeof(MSFT_SegDir);
1894     if(typelib->typelib_header.varflags & 0x100) filepos += 4; /* helpstringdll */
1895     filepos += typelib->typelib_header.nrtypeinfos * 4;
1896
1897     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_TYPEINFO);
1898     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_GUIDHASH);
1899     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_GUID);
1900     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_IMPORTINFO);
1901     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_IMPORTFILES);
1902     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_REFERENCES);
1903     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_NAMEHASH);
1904     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_NAME);
1905     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_STRING);
1906     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_TYPEDESC);
1907     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_ARRAYDESC);
1908     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_CUSTDATA);
1909     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_CUSTDATAGUID);
1910
1911     ctl2_finalize_typeinfos(typelib, filepos);
1912
1913     if (!ctl2_write_chunk(fd, &typelib->typelib_header, sizeof(typelib->typelib_header))) return retval;
1914     if(typelib->typelib_header.varflags & 0x100)
1915         if (!ctl2_write_chunk(fd, &typelib->help_string_dll_offset, sizeof(typelib->help_string_dll_offset)))
1916             return retval;
1917
1918     if (!ctl2_write_chunk(fd, typelib->typelib_typeinfo_offsets, typelib->typelib_header.nrtypeinfos * 4)) return retval;
1919     if (!ctl2_write_chunk(fd, &typelib->typelib_segdir, sizeof(typelib->typelib_segdir))) return retval;
1920     if (!ctl2_write_segment(typelib, fd, MSFT_SEG_TYPEINFO    )) return retval;
1921     if (!ctl2_write_segment(typelib, fd, MSFT_SEG_GUIDHASH    )) return retval;
1922     if (!ctl2_write_segment(typelib, fd, MSFT_SEG_GUID        )) return retval;
1923     if (!ctl2_write_segment(typelib, fd, MSFT_SEG_IMPORTINFO  )) return retval;
1924     if (!ctl2_write_segment(typelib, fd, MSFT_SEG_IMPORTFILES )) return retval;
1925     if (!ctl2_write_segment(typelib, fd, MSFT_SEG_REFERENCES  )) return retval;
1926     if (!ctl2_write_segment(typelib, fd, MSFT_SEG_NAMEHASH    )) return retval;
1927     if (!ctl2_write_segment(typelib, fd, MSFT_SEG_NAME        )) return retval;
1928     if (!ctl2_write_segment(typelib, fd, MSFT_SEG_STRING      )) return retval;
1929     if (!ctl2_write_segment(typelib, fd, MSFT_SEG_TYPEDESC    )) return retval;
1930     if (!ctl2_write_segment(typelib, fd, MSFT_SEG_ARRAYDESC   )) return retval;
1931     if (!ctl2_write_segment(typelib, fd, MSFT_SEG_CUSTDATA    )) return retval;
1932     if (!ctl2_write_segment(typelib, fd, MSFT_SEG_CUSTDATAGUID)) return retval;
1933
1934     ctl2_write_typeinfos(typelib, fd);
1935
1936     if (close(fd) == -1) return retval;
1937
1938     retval = S_OK;
1939     return retval;
1940 }
1941
1942 int create_msft_typelib(typelib_t *typelib)
1943 {
1944     msft_typelib_t *msft;
1945     int failed = 0;
1946     typelib_entry_t *entry;
1947     time_t cur_time;
1948     unsigned int version = 5 << 24 | 1 << 16 | 164; /* 5.01.0164 */
1949     GUID midl_time_guid    = {0xde77ba63,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}}; 
1950     GUID midl_version_guid = {0xde77ba64,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}}; 
1951
1952     msft = malloc(sizeof(*msft));
1953     if (!msft) return 0;
1954     memset(msft, 0, sizeof(*msft));
1955     msft->typelib = typelib;
1956
1957     ctl2_init_header(msft);
1958     ctl2_init_segdir(msft);
1959
1960     msft->typelib_header.varflags |= SYS_WIN32;
1961
1962     /*
1963      * The following two calls return an offset or -1 if out of memory. We
1964      * specifically need an offset of 0, however, so...
1965      */
1966     if (ctl2_alloc_segment(msft, MSFT_SEG_GUIDHASH, 0x80, 0x80)) { failed = 1; }
1967     if (ctl2_alloc_segment(msft, MSFT_SEG_NAMEHASH, 0x200, 0x200)) { failed = 1; }
1968
1969     if(failed) return 0;
1970
1971     msft->typelib_guidhash_segment = (int *)msft->typelib_segment_data[MSFT_SEG_GUIDHASH];
1972     msft->typelib_namehash_segment = (int *)msft->typelib_segment_data[MSFT_SEG_NAMEHASH];
1973
1974     memset(msft->typelib_guidhash_segment, 0xff, 0x80);
1975     memset(msft->typelib_namehash_segment, 0xff, 0x200);
1976
1977     set_lib_flags(msft);
1978     set_lcid(msft);
1979     set_help_file_name(msft);
1980     set_doc_string(msft);
1981     set_guid(msft);
1982     set_version(msft);
1983     set_name(msft);
1984     set_help_context(msft);
1985     set_help_string_dll(msft);
1986     set_help_string_context(msft);
1987     
1988     /* midl adds two sets of custom data to the library: the current unix time
1989        and midl's version number */
1990     cur_time = time(NULL);
1991     set_custdata(msft, &midl_time_guid, VT_UI4, &cur_time, &msft->typelib_header.CustomDataOffset);
1992     set_custdata(msft, &midl_version_guid, VT_UI4, &version, &msft->typelib_header.CustomDataOffset);
1993
1994     for(entry = typelib->entry; NEXT_LINK(entry); entry = NEXT_LINK(entry))
1995         ;
1996
1997     for( ; entry; entry = PREV_LINK(entry))
1998         add_entry(msft, entry);
1999
2000     save_all_changes(msft);
2001     return 1;
2002 }