~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/tools/widl/write_msft.c

Version: ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  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 "header.h"
 53 #include "hash.h"
 54 
 55 enum MSFT_segment_index {
 56     MSFT_SEG_TYPEINFO = 0,  /* type information */
 57     MSFT_SEG_IMPORTINFO,    /* import information */
 58     MSFT_SEG_IMPORTFILES,   /* import filenames */
 59     MSFT_SEG_REFERENCES,    /* references (?) */
 60     MSFT_SEG_GUIDHASH,      /* hash table for guids? */
 61     MSFT_SEG_GUID,          /* guid storage */
 62     MSFT_SEG_NAMEHASH,      /* hash table for names */
 63     MSFT_SEG_NAME,          /* name storage */
 64     MSFT_SEG_STRING,        /* string storage */
 65     MSFT_SEG_TYPEDESC,      /* type descriptions */
 66     MSFT_SEG_ARRAYDESC,     /* array descriptions */
 67     MSFT_SEG_CUSTDATA,      /* custom data */
 68     MSFT_SEG_CUSTDATAGUID,  /* custom data guids */
 69     MSFT_SEG_UNKNOWN,       /* ??? */
 70     MSFT_SEG_UNKNOWN2,      /* ??? */
 71     MSFT_SEG_MAX            /* total number of segments */
 72 };
 73 
 74 typedef struct tagMSFT_ImpFile {
 75     int guid;
 76     LCID lcid;
 77     int version;
 78     char filename[0]; /* preceded by two bytes of encoded (length << 2) + flags in the low two bits. */
 79 } MSFT_ImpFile;
 80 
 81 typedef struct _msft_typelib_t
 82 {
 83     typelib_t *typelib;
 84     MSFT_Header typelib_header;
 85     MSFT_pSeg typelib_segdir[MSFT_SEG_MAX];
 86     char *typelib_segment_data[MSFT_SEG_MAX];
 87     int typelib_segment_block_length[MSFT_SEG_MAX];
 88 
 89     INT typelib_typeinfo_offsets[0x200]; /* Hope that's enough. */
 90 
 91     INT *typelib_namehash_segment;
 92     INT *typelib_guidhash_segment;
 93 
 94     INT help_string_dll_offset;
 95 
 96     struct _msft_typeinfo_t *typeinfos;
 97     struct _msft_typeinfo_t *last_typeinfo;
 98 } msft_typelib_t;
 99 
100 typedef struct _msft_typeinfo_t
101 {
102     msft_typelib_t *typelib;
103     MSFT_TypeInfoBase *typeinfo;
104 
105     int typekind;
106 
107     unsigned int var_data_allocated;
108     int *var_data;
109 
110     unsigned int func_data_allocated;
111     int *func_data;
112 
113     int vars_allocated;
114     int *var_indices;
115     int *var_names;
116     int *var_offsets;
117 
118     int funcs_allocated;
119     int *func_indices;
120     int *func_names;
121     int *func_offsets;
122 
123     int datawidth;
124 
125     struct _msft_typeinfo_t *next_typeinfo;
126 } msft_typeinfo_t;
127 
128 
129 
130 /*================== Internal functions ===================================*/
131 
132 /****************************************************************************
133  *      ctl2_init_header
134  *
135  *  Initializes the type library header of a new typelib.
136  */
137 static void ctl2_init_header(
138         msft_typelib_t *typelib) /* [I] The typelib to initialize. */
139 {
140     typelib->typelib_header.magic1 = 0x5446534d;
141     typelib->typelib_header.magic2 = 0x00010002;
142     typelib->typelib_header.posguid = -1;
143     typelib->typelib_header.lcid = 0x0409; /* or do we use the current one? */
144     typelib->typelib_header.lcid2 = 0x0;
145     typelib->typelib_header.varflags = 0x40;
146     typelib->typelib_header.version = 0;
147     typelib->typelib_header.flags = 0;
148     typelib->typelib_header.nrtypeinfos = 0;
149     typelib->typelib_header.helpstring = -1;
150     typelib->typelib_header.helpstringcontext = 0;
151     typelib->typelib_header.helpcontext = 0;
152     typelib->typelib_header.nametablecount = 0;
153     typelib->typelib_header.nametablechars = 0;
154     typelib->typelib_header.NameOffset = -1;
155     typelib->typelib_header.helpfile = -1;
156     typelib->typelib_header.CustomDataOffset = -1;
157     typelib->typelib_header.res44 = 0x20;
158     typelib->typelib_header.res48 = 0x80;
159     typelib->typelib_header.dispatchpos = -1;
160     typelib->typelib_header.nimpinfos = 0;
161 }
162 
163 /****************************************************************************
164  *      ctl2_init_segdir
165  *
166  *  Initializes the segment directory of a new typelib.
167  */
168 static void ctl2_init_segdir(
169         msft_typelib_t *typelib) /* [I] The typelib to initialize. */
170 {
171     int i;
172     MSFT_pSeg *segdir;
173 
174     segdir = &typelib->typelib_segdir[MSFT_SEG_TYPEINFO];
175 
176     for (i = 0; i < 15; i++) {
177         segdir[i].offset = -1;
178         segdir[i].length = 0;
179         segdir[i].res08 = -1;
180         segdir[i].res0c = 0x0f;
181     }
182 }
183 
184 /****************************************************************************
185  *      ctl2_hash_guid
186  *
187  *  Generates a hash key from a GUID.
188  *
189  * RETURNS
190  *
191  *  The hash key for the GUID.
192  */
193 static int ctl2_hash_guid(
194         REFGUID guid)                /* [I] The guid to hash. */
195 {
196     int hash;
197     int i;
198 
199     hash = 0;
200     for (i = 0; i < 8; i ++) {
201         hash ^= ((const short *)guid)[i];
202     }
203 
204     return hash & 0x1f;
205 }
206 
207 /****************************************************************************
208  *      ctl2_find_guid
209  *
210  *  Locates a guid in a type library.
211  *
212  * RETURNS
213  *
214  *  The offset into the GUID segment of the guid, or -1 if not found.
215  */
216 static int ctl2_find_guid(
217         msft_typelib_t *typelib,   /* [I] The typelib to operate against. */
218         int hash_key,              /* [I] The hash key for the guid. */
219         REFGUID guid)              /* [I] The guid to find. */
220 {
221     int offset;
222     MSFT_GuidEntry *guidentry;
223 
224     offset = typelib->typelib_guidhash_segment[hash_key];
225     while (offset != -1) {
226         guidentry = (MSFT_GuidEntry *)&typelib->typelib_segment_data[MSFT_SEG_GUID][offset];
227 
228         if (!memcmp(guidentry, guid, sizeof(GUID))) return offset;
229 
230         offset = guidentry->next_hash;
231     }
232 
233     return offset;
234 }
235 
236 /****************************************************************************
237  *      ctl2_find_name
238  *
239  *  Locates a name in a type library.
240  *
241  * RETURNS
242  *
243  *  The offset into the NAME segment of the name, or -1 if not found.
244  *
245  * NOTES
246  *
247  *  The name must be encoded as with ctl2_encode_name().
248  */
249 static int ctl2_find_name(
250         msft_typelib_t *typelib,   /* [I] The typelib to operate against. */
251         char *name)                /* [I] The encoded name to find. */
252 {
253     int offset;
254     int *namestruct;
255 
256     offset = typelib->typelib_namehash_segment[name[2] & 0x7f];
257     while (offset != -1) {
258         namestruct = (int *)&typelib->typelib_segment_data[MSFT_SEG_NAME][offset];
259 
260         if (!((namestruct[2] ^ *((int *)name)) & 0xffff00ff)) {
261             /* hash codes and lengths match, final test */
262             if (!strncasecmp(name+4, (void *)(namestruct+3), name[0])) break;
263         }
264 
265         /* move to next item in hash bucket */
266         offset = namestruct[1];
267     }
268 
269     return offset;
270 }
271 
272 /****************************************************************************
273  *      ctl2_encode_name
274  *
275  *  Encodes a name string to a form suitable for storing into a type library
276  *  or comparing to a name stored in a type library.
277  *
278  * RETURNS
279  *
280  *  The length of the encoded name, including padding and length+hash fields.
281  *
282  * NOTES
283  *
284  *  Will throw an exception if name or result are NULL. Is not multithread
285  *  safe in the slightest.
286  */
287 static int ctl2_encode_name(
288         msft_typelib_t *typelib,   /* [I] The typelib to operate against (used for LCID only). */
289         const char *name,          /* [I] The name string to encode. */
290         char **result)             /* [O] A pointer to a pointer to receive the encoded name. */
291 {
292     int length;
293     static char converted_name[0x104];
294     int offset;
295     int value;
296 
297     length = strlen(name);
298     memcpy(converted_name + 4, name, length);
299 
300     converted_name[length + 4] = 0;
301 
302 
303     value = lhash_val_of_name_sys(typelib->typelib_header.varflags & 0x0f, typelib->typelib_header.lcid, converted_name + 4);
304 
305 #ifdef WORDS_BIGENDIAN
306     converted_name[3] = length & 0xff;
307     converted_name[2] = 0x00;
308     converted_name[1] = value;
309     converted_name[0] = value >> 8;
310 #else
311     converted_name[0] = length & 0xff;
312     converted_name[1] = 0x00;
313     converted_name[2] = value;
314     converted_name[3] = value >> 8;
315 #endif
316 
317     for (offset = (4 - length) & 3; offset; offset--) converted_name[length + offset + 3] = 0x57;
318 
319     *result = converted_name;
320 
321     return (length + 7) & ~3;
322 }
323 
324 /****************************************************************************
325  *      ctl2_encode_string
326  *
327  *  Encodes a string to a form suitable for storing into a type library or
328  *  comparing to a string stored in a type library.
329  *
330  * RETURNS
331  *
332  *  The length of the encoded string, including padding and length fields.
333  *
334  * NOTES
335  *
336  *  Will throw an exception if string or result are NULL. Is not multithread
337  *  safe in the slightest.
338  */
339 static int ctl2_encode_string(
340         const char *string,        /* [I] The string to encode. */
341         char **result)             /* [O] A pointer to a pointer to receive the encoded string. */
342 {
343     int length;
344     static char converted_string[0x104];
345     int offset;
346 
347     length = strlen(string);
348     memcpy(converted_string + 2, string, length);
349 
350 #ifdef WORDS_BIGENDIAN
351     converted_string[1] = length & 0xff;
352     converted_string[0] = (length >> 8) & 0xff;
353 #else
354     converted_string[0] = length & 0xff;
355     converted_string[1] = (length >> 8) & 0xff;
356 #endif
357 
358     if(length < 3) { /* strings of this length are padded with up to 8 bytes incl the 2 byte length */
359         for(offset = 0; offset < 4; offset++)
360             converted_string[length + offset + 2] = 0x57;
361         length += 4;
362     }
363     for (offset = (4 - (length + 2)) & 3; offset; offset--) converted_string[length + offset + 1] = 0x57;
364 
365     *result = converted_string;
366 
367     return (length + 5) & ~3;
368 }
369 
370 /****************************************************************************
371  *      ctl2_alloc_segment
372  *
373  *  Allocates memory from a segment in a type library.
374  *
375  * RETURNS
376  *
377  *  Success: The offset within the segment of the new data area.
378  *
379  * BUGS
380  *
381  *  Does not (yet) handle the case where the allocated segment memory needs to grow.
382  */
383 static int ctl2_alloc_segment(
384         msft_typelib_t *typelib,         /* [I] The type library in which to allocate. */
385         enum MSFT_segment_index segment, /* [I] The segment in which to allocate. */
386         int size,                        /* [I] The amount to allocate. */
387         int block_size)                  /* [I] Initial allocation block size, or 0 for default. */
388 {
389     int offset;
390 
391     if(!typelib->typelib_segment_data[segment]) {
392         if (!block_size) block_size = 0x2000;
393 
394         typelib->typelib_segment_block_length[segment] = block_size;
395         typelib->typelib_segment_data[segment] = xmalloc(block_size);
396         if (!typelib->typelib_segment_data[segment]) return -1;
397         memset(typelib->typelib_segment_data[segment], 0x57, block_size);
398     }
399 
400     while ((typelib->typelib_segdir[segment].length + size) > typelib->typelib_segment_block_length[segment]) {
401         char *block;
402 
403         block_size = typelib->typelib_segment_block_length[segment];
404         block = xrealloc(typelib->typelib_segment_data[segment], block_size << 1);
405 
406         if (segment == MSFT_SEG_TYPEINFO) {
407             /* TypeInfos have a direct pointer to their memory space, so we have to fix them up. */
408             msft_typeinfo_t *typeinfo;
409 
410             for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
411                 typeinfo->typeinfo = (void *)&block[((char *)typeinfo->typeinfo) - typelib->typelib_segment_data[segment]];
412             }
413         }
414 
415         memset(block + block_size, 0x57, block_size);
416         typelib->typelib_segment_block_length[segment] = block_size << 1;
417         typelib->typelib_segment_data[segment] = block;
418     }
419 
420     offset = typelib->typelib_segdir[segment].length;
421     typelib->typelib_segdir[segment].length += size;
422 
423     return offset;
424 }
425 
426 /****************************************************************************
427  *      ctl2_alloc_typeinfo
428  *
429  *  Allocates and initializes a typeinfo structure in a type library.
430  *
431  * RETURNS
432  *
433  *  Success: The offset of the new typeinfo.
434  *  Failure: -1 (this is invariably an out of memory condition).
435  */
436 static int ctl2_alloc_typeinfo(
437         msft_typelib_t *typelib,   /* [I] The type library to allocate in. */
438         int nameoffset)            /* [I] The offset of the name for this typeinfo. */
439 {
440     int offset;
441     MSFT_TypeInfoBase *typeinfo;
442 
443     offset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEINFO, sizeof(MSFT_TypeInfoBase), 0);
444 
445     typelib->typelib_typeinfo_offsets[typelib->typelib_header.nrtypeinfos++] = offset;
446 
447     typeinfo = (void *)(typelib->typelib_segment_data[MSFT_SEG_TYPEINFO] + offset);
448 
449     typeinfo->typekind = (typelib->typelib_header.nrtypeinfos - 1) << 16;
450     typeinfo->memoffset = -1; /* should be EOF if no elements */
451     typeinfo->res2 = 0;
452     typeinfo->res3 = -1;
453     typeinfo->res4 = 3;
454     typeinfo->res5 = 0;
455     typeinfo->cElement = 0;
456     typeinfo->res7 = 0;
457     typeinfo->res8 = 0;
458     typeinfo->res9 = 0;
459     typeinfo->resA = 0;
460     typeinfo->posguid = -1;
461     typeinfo->flags = 0;
462     typeinfo->NameOffset = nameoffset;
463     typeinfo->version = 0;
464     typeinfo->docstringoffs = -1;
465     typeinfo->helpstringcontext = 0;
466     typeinfo->helpcontext = 0;
467     typeinfo->oCustData = -1;
468     typeinfo->cbSizeVft = 0;
469     typeinfo->cImplTypes = 0;
470     typeinfo->size = 0;
471     typeinfo->datatype1 = -1;
472     typeinfo->datatype2 = 0;
473     typeinfo->res18 = 0;
474     typeinfo->res19 = -1;
475 
476     return offset;
477 }
478 
479 /****************************************************************************
480  *      ctl2_alloc_guid
481  *
482  *  Allocates and initializes a GUID structure in a type library. Also updates
483  *  the GUID hash table as needed.
484  *
485  * RETURNS
486  *
487  *  Success: The offset of the new GUID.
488  */
489 static int ctl2_alloc_guid(
490         msft_typelib_t *typelib,   /* [I] The type library to allocate in. */
491         MSFT_GuidEntry *guid)      /* [I] The GUID to store. */
492 {
493     int offset;
494     MSFT_GuidEntry *guid_space;
495     int hash_key;
496 
497     hash_key = ctl2_hash_guid(&guid->guid);
498 
499     offset = ctl2_find_guid(typelib, hash_key, &guid->guid);
500     if (offset != -1) return offset;
501 
502     offset = ctl2_alloc_segment(typelib, MSFT_SEG_GUID, sizeof(MSFT_GuidEntry), 0);
503 
504     guid_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_GUID] + offset);
505     *guid_space = *guid;
506 
507     guid_space->next_hash = typelib->typelib_guidhash_segment[hash_key];
508     typelib->typelib_guidhash_segment[hash_key] = offset;
509 
510     return offset;
511 }
512 
513 /****************************************************************************
514  *      ctl2_alloc_name
515  *
516  *  Allocates and initializes a name within a type library. Also updates the
517  *  name hash table as needed.
518  *
519  * RETURNS
520  *
521  *  Success: The offset within the segment of the new name.
522  *  Failure: -1 (this is invariably an out of memory condition).
523  */
524 static int ctl2_alloc_name(
525         msft_typelib_t *typelib,  /* [I] The type library to allocate in. */
526         const char *name)         /* [I] The name to store. */
527 {
528     int length;
529     int offset;
530     MSFT_NameIntro *name_space;
531     char *encoded_name;
532 
533     length = ctl2_encode_name(typelib, name, &encoded_name);
534 
535     offset = ctl2_find_name(typelib, encoded_name);
536     if (offset != -1) return offset;
537 
538     offset = ctl2_alloc_segment(typelib, MSFT_SEG_NAME, length + 8, 0);
539 
540     name_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_NAME] + offset);
541     name_space->hreftype = -1;
542     name_space->next_hash = -1;
543     memcpy(&name_space->namelen, encoded_name, length);
544 
545     if (typelib->typelib_namehash_segment[encoded_name[2] & 0x7f] != -1)
546         name_space->next_hash = typelib->typelib_namehash_segment[encoded_name[2] & 0x7f];
547 
548     typelib->typelib_namehash_segment[encoded_name[2] & 0x7f] = offset;
549 
550     typelib->typelib_header.nametablecount += 1;
551     typelib->typelib_header.nametablechars += *encoded_name;
552 
553     return offset;
554 }
555 
556 /****************************************************************************
557  *      ctl2_alloc_string
558  *
559  *  Allocates and initializes a string in a type library.
560  *
561  * RETURNS
562  *
563  *  Success: The offset within the segment of the new string.
564  *  Failure: -1 (this is invariably an out of memory condition).
565  */
566 static int ctl2_alloc_string(
567         msft_typelib_t *typelib,  /* [I] The type library to allocate in. */
568         const char *string)       /* [I] The string to store. */
569 {
570     int length;
571     int offset;
572     char *string_space;
573     char *encoded_string;
574 
575     length = ctl2_encode_string(string, &encoded_string);
576 
577     for (offset = 0; offset < typelib->typelib_segdir[MSFT_SEG_STRING].length;
578          offset += ((((typelib->typelib_segment_data[MSFT_SEG_STRING][offset + 1] << 8) & 0xff)
579              | (typelib->typelib_segment_data[MSFT_SEG_STRING][offset + 0] & 0xff)) + 5) & ~3) {
580         if (!memcmp(encoded_string, typelib->typelib_segment_data[MSFT_SEG_STRING] + offset, length)) return offset;
581     }
582 
583     offset = ctl2_alloc_segment(typelib, MSFT_SEG_STRING, length, 0);
584 
585     string_space = typelib->typelib_segment_data[MSFT_SEG_STRING] + offset;
586     memcpy(string_space, encoded_string, length);
587 
588     return offset;
589 }
590 
591 /****************************************************************************
592  *      alloc_msft_importinfo
593  *
594  *  Allocates and initializes an import information structure in a type library.
595  *
596  * RETURNS
597  *
598  *  Success: The offset of the new importinfo.
599  *  Failure: -1 (this is invariably an out of memory condition).
600  */
601 static int alloc_msft_importinfo(
602         msft_typelib_t *typelib,   /* [I] The type library to allocate in. */
603         MSFT_ImpInfo *impinfo)     /* [I] The import information to store. */
604 {
605     int offset;
606     MSFT_ImpInfo *impinfo_space;
607 
608     for (offset = 0;
609          offset < typelib->typelib_segdir[MSFT_SEG_IMPORTINFO].length;
610          offset += sizeof(MSFT_ImpInfo)) {
611         if (!memcmp(&(typelib->typelib_segment_data[MSFT_SEG_IMPORTINFO][offset]),
612                     impinfo, sizeof(MSFT_ImpInfo))) {
613             return offset;
614         }
615     }
616 
617     impinfo->flags |= typelib->typelib_header.nimpinfos++;
618 
619     offset = ctl2_alloc_segment(typelib, MSFT_SEG_IMPORTINFO, sizeof(MSFT_ImpInfo), 0);
620 
621     impinfo_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_IMPORTINFO] + offset);
622     *impinfo_space = *impinfo;
623 
624     return offset;
625 }
626 
627 /****************************************************************************
628  *      alloc_importfile
629  *
630  *  Allocates and initializes an import file definition in a type library.
631  *
632  * RETURNS
633  *
634  *  Success: The offset of the new importinfo.
635  *  Failure: -1 (this is invariably an out of memory condition).
636  */
637 static int alloc_importfile(
638         msft_typelib_t *typelib,   /* [I] The type library to allocate in. */
639         int guidoffset,            /* [I] The offset to the GUID for the imported library. */
640         int major_version,         /* [I] The major version number of the imported library. */
641         int minor_version,         /* [I] The minor version number of the imported library. */
642         const char *filename)      /* [I] The filename of the imported library. */
643 {
644     int length;
645     int offset;
646     MSFT_ImpFile *importfile;
647     char *encoded_string;
648 
649     length = ctl2_encode_string(filename, &encoded_string);
650 
651     encoded_string[0] <<= 2;
652     encoded_string[0] |= 1;
653 
654     for (offset = 0; offset < typelib->typelib_segdir[MSFT_SEG_IMPORTFILES].length;
655          offset += ((((typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xd] << 8) & 0xff)
656              | (typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xc] & 0xff)) >> 2) + 0xc) {
657         if (!memcmp(encoded_string, typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES] + offset + 0xc, length)) return offset;
658     }
659 
660     offset = ctl2_alloc_segment(typelib, MSFT_SEG_IMPORTFILES, length + 0xc, 0);
661 
662     importfile = (MSFT_ImpFile *)&typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset];
663     importfile->guid = guidoffset;
664     importfile->lcid = typelib->typelib_header.lcid2;
665     importfile->version = major_version | (minor_version << 16);
666     memcpy(&importfile->filename, encoded_string, length);
667 
668     return offset;
669 }
670 
671 static void alloc_importinfo(msft_typelib_t *typelib, importinfo_t *importinfo)
672 {
673     importlib_t *importlib = importinfo->importlib;
674 
675     chat("alloc_importinfo: %s\n", importinfo->name);
676 
677     if(!importlib->allocated) {
678         MSFT_GuidEntry guid;
679         int guid_idx;
680 
681         chat("allocating importlib %s\n", importlib->name);
682 
683         importlib->allocated = -1;
684 
685         memcpy(&guid.guid, &importlib->guid, sizeof(GUID));
686         guid.hreftype = 2;
687 
688         guid_idx = ctl2_alloc_guid(typelib, &guid);
689 
690         alloc_importfile(typelib, guid_idx, importlib->version&0xffff,
691                          importlib->version>>16, importlib->name);
692     }
693 
694     if(importinfo->offset == -1 || !(importinfo->flags & MSFT_IMPINFO_OFFSET_IS_GUID)) {
695         MSFT_ImpInfo impinfo;
696 
697         impinfo.flags = importinfo->flags;
698         impinfo.oImpFile = 0;
699 
700         if(importinfo->flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
701             MSFT_GuidEntry guid;
702 
703             guid.hreftype = 0;
704             memcpy(&guid.guid, &importinfo->guid, sizeof(GUID));
705 
706             impinfo.oGuid = ctl2_alloc_guid(typelib, &guid);
707 
708             importinfo->offset = alloc_msft_importinfo(typelib, &impinfo);
709 
710             typelib->typelib_segment_data[MSFT_SEG_GUID][impinfo.oGuid+sizeof(GUID)]
711                 = importinfo->offset+1;
712 
713             if(!strcmp(importinfo->name, "IDispatch"))
714                 typelib->typelib_header.dispatchpos = importinfo->offset+1;
715         }else {
716             impinfo.oGuid = importinfo->id;
717             importinfo->offset = alloc_msft_importinfo(typelib, &impinfo);
718         }
719     }
720 }
721 
722 static importinfo_t *find_importinfo(msft_typelib_t *typelib, const char *name)
723 {
724     importlib_t *importlib;
725     int i;
726 
727     chat("search importlib %s\n", name);
728 
729     if(!name)
730         return NULL;
731 
732     LIST_FOR_EACH_ENTRY( importlib, &typelib->typelib->importlibs, importlib_t, entry )
733     {
734         for(i=0; i < importlib->ntypeinfos; i++) {
735             if(!strcmp(name, importlib->importinfos[i].name)) {
736                 chat("Found %s in importlib.\n", name);
737                 return importlib->importinfos+i;
738             }
739         }
740     }
741 
742     return NULL;
743 }
744 
745 static void add_structure_typeinfo(msft_typelib_t *typelib, type_t *structure);
746 static void add_interface_typeinfo(msft_typelib_t *typelib, type_t *interface);
747 static void add_enum_typeinfo(msft_typelib_t *typelib, type_t *enumeration);
748 static void add_coclass_typeinfo(msft_typelib_t *typelib, type_t *cls);
749 static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinterface);
750 
751 
752 /****************************************************************************
753  *      encode_type
754  *
755  *  Encodes a type, storing information in the TYPEDESC and ARRAYDESC
756  *  segments as needed.
757  *
758  * RETURNS
759  *
760  *  Success: 0.
761  *  Failure: -1.
762  */
763 static int encode_type(
764         msft_typelib_t *typelib,   /* [I] The type library in which to encode the TYPEDESC. */
765         int vt,                    /* [I] vt to encode */
766         type_t *type,              /* [I] type */
767         int *encoded_type,         /* [O] The encoded type description. */
768         int *width,                /* [O] The width of the type, or NULL. */
769         int *alignment,            /* [O] The alignment of the type, or NULL. */
770         int *decoded_size)         /* [O] The total size of the unencoded TYPEDESCs, including nested descs. */
771 {
772     int default_type;
773     int scratch;
774     int typeoffset;
775     int *typedata;
776     int target_type;
777     int child_size = 0;
778 
779     chat("encode_type vt %d type %p\n", vt, type);
780 
781     default_type = 0x80000000 | (vt << 16) | vt;
782     if (!width) width = &scratch;
783     if (!alignment) alignment = &scratch;
784     if (!decoded_size) decoded_size = &scratch;
785 
786 
787     switch (vt) {
788     case VT_I1:
789     case VT_UI1:
790         *encoded_type = default_type;
791         *width = 1;
792         *alignment = 1;
793         break;
794 
795     case VT_INT:
796         *encoded_type = 0x80000000 | (VT_I4 << 16) | VT_INT;
797         if ((typelib->typelib_header.varflags & 0x0f) == SYS_WIN16) {
798             *width = 2;
799             *alignment = 2;
800         } else {
801             *width = 4;
802             *alignment = 4;
803         }
804         break;
805 
806     case VT_UINT:
807         *encoded_type = 0x80000000 | (VT_UI4 << 16) | VT_UINT;
808         if ((typelib->typelib_header.varflags & 0x0f) == SYS_WIN16) {
809             *width = 2;
810             *alignment = 2;
811         } else {
812             *width = 4;
813             *alignment = 4;
814         }
815         break;
816 
817     case VT_UI2:
818     case VT_I2:
819     case VT_BOOL:
820         *encoded_type = default_type;
821         *width = 2;
822         *alignment = 2;
823         break;
824 
825     case VT_I4:
826     case VT_UI4:
827     case VT_R4:
828     case VT_ERROR:
829     case VT_BSTR:
830     case VT_HRESULT:
831         *encoded_type = default_type;
832         *width = 4;
833         *alignment = 4;
834         break;
835 
836     case VT_R8:
837     case VT_I8:
838     case VT_UI8:
839         *encoded_type = default_type;
840         *width = 8;
841         *alignment = 8;
842         break;
843 
844     case VT_CY:
845     case VT_DATE:
846         *encoded_type = default_type;
847         *width = 8;
848         *alignment = 8;
849         break;
850 
851     case VT_VOID:
852         *encoded_type = 0x80000000 | (VT_EMPTY << 16) | vt;
853         *width = 0;
854         *alignment = 1;
855         break;
856 
857     case VT_UNKNOWN:
858     case VT_DISPATCH:
859         *encoded_type = default_type;
860         *width = 4;
861         *alignment = 4;
862         break;
863 
864     case VT_VARIANT:
865         *encoded_type = default_type;
866         break;
867 
868     case VT_LPSTR:
869     case VT_LPWSTR:
870         *encoded_type = 0xfffe0000 | vt;
871         *width = 4;
872         *alignment = 4;
873         break;
874 
875     case VT_PTR:
876       {
877         int next_vt;
878         for(next_vt = 0; type->ref; type = type->ref) {
879             next_vt = get_type_vt(type->ref);
880             if (next_vt != 0)
881                 break;
882         }
883         /* if no type found then it must be void */
884         if (next_vt == 0)
885             next_vt = VT_VOID;
886 
887         encode_type(typelib, next_vt, type->ref, &target_type, NULL, NULL, &child_size);
888         if(type->ref && (type->ref->type == RPC_FC_IP)) {
889             chat("encode_type: skipping ptr\n");
890             *encoded_type = target_type;
891             *width = 4;
892             *alignment = 4;
893             *decoded_size = child_size;
894             break;
895         }
896 
897         for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
898             typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
899             if (((typedata[0] & 0xffff) == VT_PTR) && (typedata[1] == target_type)) break;
900         }
901 
902         if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
903             int mix_field;
904             
905             if (target_type & 0x80000000) {
906                 mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF;
907             } else {
908                 typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
909                 mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
910             }
911 
912             typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
913             typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
914 
915             typedata[0] = (mix_field << 16) | VT_PTR;
916             typedata[1] = target_type;
917         }
918 
919         *encoded_type = typeoffset;
920 
921         *width = 4;
922         *alignment = 4;
923         *decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
924         break;
925     }
926 
927 
928     case VT_SAFEARRAY:
929         {
930         int next_vt;
931 
932         /* skip over SAFEARRAY type straight to element type */
933         type = type->ref;
934 
935         for(next_vt = 0; type->ref; type = type->ref) {
936             next_vt = get_type_vt(type->ref);
937             if (next_vt != 0)
938                 break;
939         }
940 
941         encode_type(typelib, next_vt, type->ref, &target_type, NULL, NULL, &child_size);
942 
943         for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
944             typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
945             if (((typedata[0] & 0xffff) == VT_SAFEARRAY) && (typedata[1] == target_type)) break;
946         }
947 
948         if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
949             int mix_field;
950             
951             if (target_type & 0x80000000) {
952                 mix_field = ((target_type >> 16) & VT_TYPEMASK) | VT_ARRAY;
953             } else {
954                 typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
955                 mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
956             }
957 
958             typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
959             typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
960 
961             typedata[0] = (mix_field << 16) | VT_SAFEARRAY;
962             typedata[1] = target_type;
963         }
964 
965         *encoded_type = typeoffset;
966 
967         *width = 4;
968         *alignment = 4;
969         *decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
970         break;
971         }
972 
973 
974     case VT_USERDEFINED:
975       {
976         int typeinfo_offset;
977 
978         /* typedef'd types without public attribute aren't included in the typelib */
979         while (type->typelib_idx < 0 && type->kind == TKIND_ALIAS && !is_attr(type->attrs, ATTR_PUBLIC))
980           type = type->orig;
981 
982         chat("encode_type: VT_USERDEFINED - type %p name = %s type->type %d idx %d\n", type,
983              type->name, type->type, type->typelib_idx);
984 
985         if(type->typelib_idx == -1) {