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