ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

write_msft.c
Go to the documentation of this file.
00001 /*
00002  *      Typelib v2 (MSFT) generation
00003  *
00004  *  Copyright 2004  Alastair Bridgewater
00005  *                2004, 2005 Huw Davies
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  *
00021  * --------------------------------------------------------------------------------------
00022  *  Known problems:
00023  *
00024  *    Badly incomplete.
00025  *
00026  *    Only works on little-endian systems.
00027  *
00028  */
00029 
00030 #include "config.h"
00031 #include "wine/port.h"
00032 
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <stdarg.h>
00036 #include <stdio.h>
00037 #include <ctype.h>
00038 #include <time.h>
00039 
00040 #define NONAMELESSUNION
00041 #define NONAMELESSSTRUCT
00042 
00043 #include <typedefs.h>
00044 #include <nls.h>
00045 
00046 #include "widl.h"
00047 #include "typelib.h"
00048 #include "typelib_struct.h"
00049 #include "utils.h"
00050 #include "header.h"
00051 #include "hash.h"
00052 #include "typetree.h"
00053 
00054 enum MSFT_segment_index {
00055     MSFT_SEG_TYPEINFO = 0,  /* type information */
00056     MSFT_SEG_IMPORTINFO,    /* import information */
00057     MSFT_SEG_IMPORTFILES,   /* import filenames */
00058     MSFT_SEG_REFERENCES,    /* references (?) */
00059     MSFT_SEG_GUIDHASH,      /* hash table for guids? */
00060     MSFT_SEG_GUID,          /* guid storage */
00061     MSFT_SEG_NAMEHASH,      /* hash table for names */
00062     MSFT_SEG_NAME,          /* name storage */
00063     MSFT_SEG_STRING,        /* string storage */
00064     MSFT_SEG_TYPEDESC,      /* type descriptions */
00065     MSFT_SEG_ARRAYDESC,     /* array descriptions */
00066     MSFT_SEG_CUSTDATA,      /* custom data */
00067     MSFT_SEG_CUSTDATAGUID,  /* custom data guids */
00068     MSFT_SEG_UNKNOWN,       /* ??? */
00069     MSFT_SEG_UNKNOWN2,      /* ??? */
00070     MSFT_SEG_MAX            /* total number of segments */
00071 };
00072 
00073 typedef struct tagMSFT_ImpFile {
00074     int guid;
00075     LCID lcid;
00076     int version;
00077     char filename[0]; /* preceded by two bytes of encoded (length << 2) + flags in the low two bits. */
00078 } MSFT_ImpFile;
00079 
00080 typedef struct _msft_typelib_t
00081 {
00082     typelib_t *typelib;
00083     MSFT_Header typelib_header;
00084     MSFT_pSeg typelib_segdir[MSFT_SEG_MAX];
00085     unsigned char *typelib_segment_data[MSFT_SEG_MAX];
00086     int typelib_segment_block_length[MSFT_SEG_MAX];
00087 
00088     INT typelib_typeinfo_offsets[0x200]; /* Hope that's enough. */
00089 
00090     INT *typelib_namehash_segment;
00091     INT *typelib_guidhash_segment;
00092 
00093     INT help_string_dll_offset;
00094 
00095     struct _msft_typeinfo_t *typeinfos;
00096     struct _msft_typeinfo_t *last_typeinfo;
00097 } msft_typelib_t;
00098 
00099 typedef struct _msft_typeinfo_t
00100 {
00101     msft_typelib_t *typelib;
00102     MSFT_TypeInfoBase *typeinfo;
00103 
00104     int typekind;
00105 
00106     unsigned int var_data_allocated;
00107     int *var_data;
00108 
00109     unsigned int func_data_allocated;
00110     int *func_data;
00111 
00112     int vars_allocated;
00113     int *var_indices;
00114     int *var_names;
00115     int *var_offsets;
00116 
00117     int funcs_allocated;
00118     int *func_indices;
00119     int *func_names;
00120     int *func_offsets;
00121 
00122     int datawidth;
00123 
00124     struct _msft_typeinfo_t *next_typeinfo;
00125 } msft_typeinfo_t;
00126 
00127 
00128 
00129 /*================== Internal functions ===================================*/
00130 
00131 /****************************************************************************
00132  *  ctl2_init_header
00133  *
00134  *  Initializes the type library header of a new typelib.
00135  */
00136 static void ctl2_init_header(
00137     msft_typelib_t *typelib) /* [I] The typelib to initialize. */
00138 {
00139     typelib->typelib_header.magic1 = 0x5446534d;
00140     typelib->typelib_header.magic2 = 0x00010002;
00141     typelib->typelib_header.posguid = -1;
00142     typelib->typelib_header.lcid = 0x0409;
00143     typelib->typelib_header.lcid2 = 0x0;
00144     typelib->typelib_header.varflags = 0x40;
00145     typelib->typelib_header.version = 0;
00146     typelib->typelib_header.flags = 0;
00147     typelib->typelib_header.nrtypeinfos = 0;
00148     typelib->typelib_header.helpstring = -1;
00149     typelib->typelib_header.helpstringcontext = 0;
00150     typelib->typelib_header.helpcontext = 0;
00151     typelib->typelib_header.nametablecount = 0;
00152     typelib->typelib_header.nametablechars = 0;
00153     typelib->typelib_header.NameOffset = -1;
00154     typelib->typelib_header.helpfile = -1;
00155     typelib->typelib_header.CustomDataOffset = -1;
00156     typelib->typelib_header.res44 = 0x20;
00157     typelib->typelib_header.res48 = 0x80;
00158     typelib->typelib_header.dispatchpos = -1;
00159     typelib->typelib_header.nimpinfos = 0;
00160 }
00161 
00162 /****************************************************************************
00163  *  ctl2_init_segdir
00164  *
00165  *  Initializes the segment directory of a new typelib.
00166  */
00167 static void ctl2_init_segdir(
00168     msft_typelib_t *typelib) /* [I] The typelib to initialize. */
00169 {
00170     int i;
00171     MSFT_pSeg *segdir;
00172 
00173     segdir = &typelib->typelib_segdir[MSFT_SEG_TYPEINFO];
00174 
00175     for (i = 0; i < 15; i++) {
00176     segdir[i].offset = -1;
00177     segdir[i].length = 0;
00178     segdir[i].res08 = -1;
00179     segdir[i].res0c = 0x0f;
00180     }
00181 }
00182 
00183 /****************************************************************************
00184  *  ctl2_hash_guid
00185  *
00186  *  Generates a hash key from a GUID.
00187  *
00188  * RETURNS
00189  *
00190  *  The hash key for the GUID.
00191  */
00192 static int ctl2_hash_guid(
00193     REFGUID guid)                /* [I] The guid to hash. */
00194 {
00195     int hash;
00196     int i;
00197 
00198     hash = 0;
00199     for (i = 0; i < 8; i ++) {
00200     hash ^= ((const short *)guid)[i];
00201     }
00202 
00203     return hash & 0x1f;
00204 }
00205 
00206 /****************************************************************************
00207  *  ctl2_find_guid
00208  *
00209  *  Locates a guid in a type library.
00210  *
00211  * RETURNS
00212  *
00213  *  The offset into the GUID segment of the guid, or -1 if not found.
00214  */
00215 static int ctl2_find_guid(
00216     msft_typelib_t *typelib,   /* [I] The typelib to operate against. */
00217     int hash_key,              /* [I] The hash key for the guid. */
00218     REFGUID guid)              /* [I] The guid to find. */
00219 {
00220     int offset;
00221     MSFT_GuidEntry *guidentry;
00222 
00223     offset = typelib->typelib_guidhash_segment[hash_key];
00224     while (offset != -1) {
00225     guidentry = (MSFT_GuidEntry *)&typelib->typelib_segment_data[MSFT_SEG_GUID][offset];
00226 
00227     if (!memcmp(guidentry, guid, sizeof(GUID))) return offset;
00228 
00229     offset = guidentry->next_hash;
00230     }
00231 
00232     return offset;
00233 }
00234 
00235 /****************************************************************************
00236  *  ctl2_find_name
00237  *
00238  *  Locates a name in a type library.
00239  *
00240  * RETURNS
00241  *
00242  *  The offset into the NAME segment of the name, or -1 if not found.
00243  *
00244  * NOTES
00245  *
00246  *  The name must be encoded as with ctl2_encode_name().
00247  */
00248 static int ctl2_find_name(
00249     msft_typelib_t *typelib,   /* [I] The typelib to operate against. */
00250     char *name)                /* [I] The encoded name to find. */
00251 {
00252     int offset;
00253     int *namestruct;
00254 
00255     offset = typelib->typelib_namehash_segment[name[2] & 0x7f];
00256     while (offset != -1) {
00257     namestruct = (int *)&typelib->typelib_segment_data[MSFT_SEG_NAME][offset];
00258 
00259     if (!((namestruct[2] ^ *((int *)name)) & 0xffff00ff)) {
00260         /* hash codes and lengths match, final test */
00261         if (!strncasecmp(name+4, (void *)(namestruct+3), name[0])) break;
00262     }
00263 
00264     /* move to next item in hash bucket */
00265     offset = namestruct[1];
00266     }
00267 
00268     return offset;
00269 }
00270 
00271 /****************************************************************************
00272  *  ctl2_encode_name
00273  *
00274  *  Encodes a name string to a form suitable for storing into a type library
00275  *  or comparing to a name stored in a type library.
00276  *
00277  * RETURNS
00278  *
00279  *  The length of the encoded name, including padding and length+hash fields.
00280  *
00281  * NOTES
00282  *
00283  *  Will throw an exception if name or result are NULL. Is not multithread
00284  *  safe in the slightest.
00285  */
00286 static int ctl2_encode_name(
00287     msft_typelib_t *typelib,   /* [I] The typelib to operate against (used for LCID only). */
00288     const char *name,          /* [I] The name string to encode. */
00289     char **result)             /* [O] A pointer to a pointer to receive the encoded name. */
00290 {
00291     int length;
00292     static char converted_name[0x104];
00293     int offset;
00294     int value;
00295 
00296     length = strlen(name);
00297     memcpy(converted_name + 4, name, length);
00298 
00299     converted_name[length + 4] = 0;
00300 
00301 
00302     value = lhash_val_of_name_sys(typelib->typelib_header.varflags & 0x0f, typelib->typelib_header.lcid, converted_name + 4);
00303 
00304 #ifdef WORDS_BIGENDIAN
00305     converted_name[3] = length & 0xff;
00306     converted_name[2] = 0x00;
00307     converted_name[1] = value;
00308     converted_name[0] = value >> 8;
00309 #else
00310     converted_name[0] = length & 0xff;
00311     converted_name[1] = 0x00;
00312     converted_name[2] = value;
00313     converted_name[3] = value >> 8;
00314 #endif
00315 
00316     for (offset = (4 - length) & 3; offset; offset--) converted_name[length + offset + 3] = 0x57;
00317 
00318     *result = converted_name;
00319 
00320     return (length + 7) & ~3;
00321 }
00322 
00323 /****************************************************************************
00324  *  ctl2_encode_string
00325  *
00326  *  Encodes a string to a form suitable for storing into a type library or
00327  *  comparing to a string stored in a type library.
00328  *
00329  * RETURNS
00330  *
00331  *  The length of the encoded string, including padding and length fields.
00332  *
00333  * NOTES
00334  *
00335  *  Will throw an exception if string or result are NULL. Is not multithread
00336  *  safe in the slightest.
00337  */
00338 static int ctl2_encode_string(
00339     const char *string,        /* [I] The string to encode. */
00340     char **result)             /* [O] A pointer to a pointer to receive the encoded string. */
00341 {
00342     int length;
00343     static char converted_string[0x104];
00344     int offset;
00345 
00346     length = strlen(string);
00347     memcpy(converted_string + 2, string, length);
00348 
00349 #ifdef WORDS_BIGENDIAN
00350     converted_string[1] = length & 0xff;
00351     converted_string[0] = (length >> 8) & 0xff;
00352 #else
00353     converted_string[0] = length & 0xff;
00354     converted_string[1] = (length >> 8) & 0xff;
00355 #endif
00356 
00357     if(length < 3) { /* strings of this length are padded with up to 8 bytes incl the 2 byte length */
00358         for(offset = 0; offset < 4; offset++)
00359             converted_string[length + offset + 2] = 0x57;
00360         length += 4;
00361     }
00362     for (offset = (4 - (length + 2)) & 3; offset; offset--) converted_string[length + offset + 1] = 0x57;
00363 
00364     *result = converted_string;
00365 
00366     return (length + 5) & ~3;
00367 }
00368 
00369 /****************************************************************************
00370  *  ctl2_alloc_segment
00371  *
00372  *  Allocates memory from a segment in a type library.
00373  *
00374  * RETURNS
00375  *
00376  *  Success: The offset within the segment of the new data area.
00377  *
00378  * BUGS
00379  *
00380  *  Does not (yet) handle the case where the allocated segment memory needs to grow.
00381  */
00382 static int ctl2_alloc_segment(
00383     msft_typelib_t *typelib,         /* [I] The type library in which to allocate. */
00384     enum MSFT_segment_index segment, /* [I] The segment in which to allocate. */
00385     int size,                        /* [I] The amount to allocate. */
00386     int block_size)                  /* [I] Initial allocation block size, or 0 for default. */
00387 {
00388     int offset;
00389 
00390     if(!typelib->typelib_segment_data[segment]) {
00391     if (!block_size) block_size = 0x2000;
00392 
00393     typelib->typelib_segment_block_length[segment] = block_size;
00394     typelib->typelib_segment_data[segment] = xmalloc(block_size);
00395     if (!typelib->typelib_segment_data[segment]) return -1;
00396     memset(typelib->typelib_segment_data[segment], 0x57, block_size);
00397     }
00398 
00399     while ((typelib->typelib_segdir[segment].length + size) > typelib->typelib_segment_block_length[segment]) {
00400     unsigned char *block;
00401 
00402     block_size = typelib->typelib_segment_block_length[segment];
00403     block = xrealloc(typelib->typelib_segment_data[segment], block_size << 1);
00404 
00405     if (segment == MSFT_SEG_TYPEINFO) {
00406         /* TypeInfos have a direct pointer to their memory space, so we have to fix them up. */
00407         msft_typeinfo_t *typeinfo;
00408 
00409         for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
00410         typeinfo->typeinfo = (void *)&block[((unsigned char *)typeinfo->typeinfo) - typelib->typelib_segment_data[segment]];
00411         }
00412     }
00413 
00414     memset(block + block_size, 0x57, block_size);
00415     typelib->typelib_segment_block_length[segment] = block_size << 1;
00416     typelib->typelib_segment_data[segment] = block;
00417     }
00418 
00419     offset = typelib->typelib_segdir[segment].length;
00420     typelib->typelib_segdir[segment].length += size;
00421 
00422     return offset;
00423 }
00424 
00425 /****************************************************************************
00426  *  ctl2_alloc_typeinfo
00427  *
00428  *  Allocates and initializes a typeinfo structure in a type library.
00429  *
00430  * RETURNS
00431  *
00432  *  Success: The offset of the new typeinfo.
00433  *  Failure: -1 (this is invariably an out of memory condition).
00434  */
00435 static int ctl2_alloc_typeinfo(
00436     msft_typelib_t *typelib,   /* [I] The type library to allocate in. */
00437     int nameoffset)            /* [I] The offset of the name for this typeinfo. */
00438 {
00439     int offset;
00440     MSFT_TypeInfoBase *typeinfo;
00441 
00442     offset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEINFO, sizeof(MSFT_TypeInfoBase), 0);
00443 
00444     typelib->typelib_typeinfo_offsets[typelib->typelib_header.nrtypeinfos++] = offset;
00445 
00446     typeinfo = (void *)(typelib->typelib_segment_data[MSFT_SEG_TYPEINFO] + offset);
00447 
00448     typeinfo->typekind = (typelib->typelib_header.nrtypeinfos - 1) << 16;
00449     typeinfo->memoffset = -1; /* should be EOF if no elements */
00450     typeinfo->res2 = 0;
00451     typeinfo->res3 = -1;
00452     typeinfo->res4 = 3;
00453     typeinfo->res5 = 0;
00454     typeinfo->cElement = 0;
00455     typeinfo->res7 = 0;
00456     typeinfo->res8 = 0;
00457     typeinfo->res9 = 0;
00458     typeinfo->resA = 0;
00459     typeinfo->posguid = -1;
00460     typeinfo->flags = 0;
00461     typeinfo->NameOffset = nameoffset;
00462     typeinfo->version = 0;
00463     typeinfo->docstringoffs = -1;
00464     typeinfo->helpstringcontext = 0;
00465     typeinfo->helpcontext = 0;
00466     typeinfo->oCustData = -1;
00467     typeinfo->cbSizeVft = 0;
00468     typeinfo->cImplTypes = 0;
00469     typeinfo->size = 0;
00470     typeinfo->datatype1 = -1;
00471     typeinfo->datatype2 = 0;
00472     typeinfo->res18 = 0;
00473     typeinfo->res19 = -1;
00474 
00475     return offset;
00476 }
00477 
00478 /****************************************************************************
00479  *  ctl2_alloc_guid
00480  *
00481  *  Allocates and initializes a GUID structure in a type library. Also updates
00482  *  the GUID hash table as needed.
00483  *
00484  * RETURNS
00485  *
00486  *  Success: The offset of the new GUID.
00487  */
00488 static int ctl2_alloc_guid(
00489     msft_typelib_t *typelib,   /* [I] The type library to allocate in. */
00490     MSFT_GuidEntry *guid)      /* [I] The GUID to store. */
00491 {
00492     int offset;
00493     MSFT_GuidEntry *guid_space;
00494     int hash_key;
00495 
00496     hash_key = ctl2_hash_guid(&guid->guid);
00497 
00498     offset = ctl2_find_guid(typelib, hash_key, &guid->guid);
00499     if (offset != -1) return offset;
00500 
00501     offset = ctl2_alloc_segment(typelib, MSFT_SEG_GUID, sizeof(MSFT_GuidEntry), 0);
00502 
00503     guid_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_GUID] + offset);
00504     *guid_space = *guid;
00505 
00506     guid_space->next_hash = typelib->typelib_guidhash_segment[hash_key];
00507     typelib->typelib_guidhash_segment[hash_key] = offset;
00508 
00509     return offset;
00510 }
00511 
00512 /****************************************************************************
00513  *  ctl2_alloc_name
00514  *
00515  *  Allocates and initializes a name within a type library. Also updates the
00516  *  name hash table as needed.
00517  *
00518  * RETURNS
00519  *
00520  *  Success: The offset within the segment of the new name.
00521  *  Failure: -1 (this is invariably an out of memory condition).
00522  */
00523 static int ctl2_alloc_name(
00524     msft_typelib_t *typelib,  /* [I] The type library to allocate in. */
00525     const char *name)         /* [I] The name to store. */
00526 {
00527     int length;
00528     int offset;
00529     MSFT_NameIntro *name_space;
00530     char *encoded_name;
00531 
00532     length = ctl2_encode_name(typelib, name, &encoded_name);
00533 
00534     offset = ctl2_find_name(typelib, encoded_name);
00535     if (offset != -1) return offset;
00536 
00537     offset = ctl2_alloc_segment(typelib, MSFT_SEG_NAME, length + 8, 0);
00538 
00539     name_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_NAME] + offset);
00540     name_space->hreftype = -1;
00541     name_space->next_hash = -1;
00542     memcpy(&name_space->namelen, encoded_name, length);
00543 
00544     if (typelib->typelib_namehash_segment[encoded_name[2] & 0x7f] != -1)
00545     name_space->next_hash = typelib->typelib_namehash_segment[encoded_name[2] & 0x7f];
00546 
00547     typelib->typelib_namehash_segment[encoded_name[2] & 0x7f] = offset;
00548 
00549     typelib->typelib_header.nametablecount += 1;
00550     typelib->typelib_header.nametablechars += *encoded_name;
00551 
00552     return offset;
00553 }
00554 
00555 /****************************************************************************
00556  *  ctl2_alloc_string
00557  *
00558  *  Allocates and initializes a string in a type library.
00559  *
00560  * RETURNS
00561  *
00562  *  Success: The offset within the segment of the new string.
00563  *  Failure: -1 (this is invariably an out of memory condition).
00564  */
00565 static int ctl2_alloc_string(
00566     msft_typelib_t *typelib,  /* [I] The type library to allocate in. */
00567     const char *string)       /* [I] The string to store. */
00568 {
00569     int length;
00570     int offset;
00571     unsigned char *string_space;
00572     char *encoded_string;
00573 
00574     length = ctl2_encode_string(string, &encoded_string);
00575 
00576     for (offset = 0; offset < typelib->typelib_segdir[MSFT_SEG_STRING].length;
00577      offset += (((typelib->typelib_segment_data[MSFT_SEG_STRING][offset + 1] << 8) |
00578           typelib->typelib_segment_data[MSFT_SEG_STRING][offset + 0]) + 5) & ~3) {
00579     if (!memcmp(encoded_string, typelib->typelib_segment_data[MSFT_SEG_STRING] + offset, length)) return offset;
00580     }
00581 
00582     offset = ctl2_alloc_segment(typelib, MSFT_SEG_STRING, length, 0);
00583 
00584     string_space = typelib->typelib_segment_data[MSFT_SEG_STRING] + offset;
00585     memcpy(string_space, encoded_string, length);
00586 
00587     return offset;
00588 }
00589 
00590 /****************************************************************************
00591  *  alloc_msft_importinfo
00592  *
00593  *  Allocates and initializes an import information structure in a type library.
00594  *
00595  * RETURNS
00596  *
00597  *  Success: The offset of the new importinfo.
00598  *  Failure: -1 (this is invariably an out of memory condition).
00599  */
00600 static int alloc_msft_importinfo(
00601         msft_typelib_t *typelib,   /* [I] The type library to allocate in. */
00602         MSFT_ImpInfo *impinfo)     /* [I] The import information to store. */
00603 {
00604     int offset;
00605     MSFT_ImpInfo *impinfo_space;
00606 
00607     for (offset = 0;
00608      offset < typelib->typelib_segdir[MSFT_SEG_IMPORTINFO].length;
00609      offset += sizeof(MSFT_ImpInfo)) {
00610     if (!memcmp(&(typelib->typelib_segment_data[MSFT_SEG_IMPORTINFO][offset]),
00611             impinfo, sizeof(MSFT_ImpInfo))) {
00612         return offset;
00613     }
00614     }
00615 
00616     impinfo->flags |= typelib->typelib_header.nimpinfos++;
00617 
00618     offset = ctl2_alloc_segment(typelib, MSFT_SEG_IMPORTINFO, sizeof(MSFT_ImpInfo), 0);
00619 
00620     impinfo_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_IMPORTINFO] + offset);
00621     *impinfo_space = *impinfo;
00622 
00623     return offset;
00624 }
00625 
00626 /****************************************************************************
00627  *  alloc_importfile
00628  *
00629  *  Allocates and initializes an import file definition in a type library.
00630  *
00631  * RETURNS
00632  *
00633  *  Success: The offset of the new importinfo.
00634  *  Failure: -1 (this is invariably an out of memory condition).
00635  */
00636 static int alloc_importfile(
00637         msft_typelib_t *typelib,   /* [I] The type library to allocate in. */
00638         int guidoffset,            /* [I] The offset to the GUID for the imported library. */
00639         int major_version,         /* [I] The major version number of the imported library. */
00640         int minor_version,         /* [I] The minor version number of the imported library. */
00641         const char *filename)      /* [I] The filename of the imported library. */
00642 {
00643     int length;
00644     int offset;
00645     MSFT_ImpFile *importfile;
00646     char *encoded_string;
00647 
00648     length = ctl2_encode_string(filename, &encoded_string);
00649 
00650     encoded_string[0] <<= 2;
00651     encoded_string[0] |= 1;
00652 
00653     for (offset = 0; offset < typelib->typelib_segdir[MSFT_SEG_IMPORTFILES].length;
00654      offset += (((typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xd] << 8) |
00655                   typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xc]) >> 2) + 0xc) {
00656     if (!memcmp(encoded_string, typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES] + offset + 0xc, length)) return offset;
00657     }
00658 
00659     offset = ctl2_alloc_segment(typelib, MSFT_SEG_IMPORTFILES, length + 0xc, 0);
00660 
00661     importfile = (MSFT_ImpFile *)&typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset];
00662     importfile->guid = guidoffset;
00663     importfile->lcid = typelib->typelib_header.lcid2;
00664     importfile->version = major_version | (minor_version << 16);
00665     memcpy(&importfile->filename, encoded_string, length);
00666 
00667     return offset;
00668 }
00669 
00670 static void alloc_importinfo(msft_typelib_t *typelib, importinfo_t *importinfo)
00671 {
00672     importlib_t *importlib = importinfo->importlib;
00673 
00674     chat("alloc_importinfo: %s\n", importinfo->name);
00675 
00676     if(!importlib->allocated) {
00677         MSFT_GuidEntry guid;
00678         int guid_idx;
00679 
00680         chat("allocating importlib %s\n", importlib->name);
00681 
00682         importlib->allocated = -1;
00683 
00684         memcpy(&guid.guid, &importlib->guid, sizeof(GUID));
00685         guid.hreftype = 2;
00686 
00687         guid_idx = ctl2_alloc_guid(typelib, &guid);
00688 
00689         alloc_importfile(typelib, guid_idx, importlib->version&0xffff,
00690                          importlib->version>>16, importlib->name);
00691     }
00692 
00693     if(importinfo->offset == -1 || !(importinfo->flags & MSFT_IMPINFO_OFFSET_IS_GUID)) {
00694         MSFT_ImpInfo impinfo;
00695 
00696         impinfo.flags = importinfo->flags;
00697         impinfo.oImpFile = 0;
00698 
00699         if(importinfo->flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
00700             MSFT_GuidEntry guid;
00701 
00702             guid.hreftype = 0;
00703             memcpy(&guid.guid, &importinfo->guid, sizeof(GUID));
00704 
00705             impinfo.oGuid = ctl2_alloc_guid(typelib, &guid);
00706 
00707             importinfo->offset = alloc_msft_importinfo(typelib, &impinfo);
00708 
00709             typelib->typelib_segment_data[MSFT_SEG_GUID][impinfo.oGuid+sizeof(GUID)]
00710                 = importinfo->offset+1;
00711 
00712             if(!strcmp(importinfo->name, "IDispatch"))
00713                 typelib->typelib_header.dispatchpos = importinfo->offset+1;
00714         }else {
00715             impinfo.oGuid = importinfo->id;
00716             importinfo->offset = alloc_msft_importinfo(typelib, &impinfo);
00717         }
00718     }
00719 }
00720 
00721 static importinfo_t *find_importinfo(msft_typelib_t *typelib, const char *name)
00722 {
00723     importlib_t *importlib;
00724     int i;
00725 
00726     chat("search importlib %s\n", name);
00727 
00728     if(!name)
00729         return NULL;
00730 
00731     LIST_FOR_EACH_ENTRY( importlib, &typelib->typelib->importlibs, importlib_t, entry )
00732     {
00733         for(i=0; i < importlib->ntypeinfos; i++) {
00734             if(!strcmp(name, importlib->importinfos[i].name)) {
00735                 chat("Found %s in importlib.\n", name);
00736                 return importlib->importinfos+i;
00737             }
00738         }
00739     }
00740 
00741     return NULL;
00742 }
00743 
00744 static void add_structure_typeinfo(msft_typelib_t *typelib, type_t *structure);
00745 static void add_interface_typeinfo(msft_typelib_t *typelib, type_t *interface);
00746 static void add_enum_typeinfo(msft_typelib_t *typelib, type_t *enumeration);
00747 static void add_coclass_typeinfo(msft_typelib_t *typelib, type_t *cls);
00748 static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinterface);
00749 
00750 
00751 /****************************************************************************
00752  *  encode_type
00753  *
00754  *  Encodes a type, storing information in the TYPEDESC and ARRAYDESC
00755  *  segments as needed.
00756  *
00757  * RETURNS
00758  *
00759  *  Success: 0.
00760  *  Failure: -1.
00761  */
00762 static int encode_type(
00763     msft_typelib_t *typelib,   /* [I] The type library in which to encode the TYPEDESC. */
00764         int vt,                    /* [I] vt to encode */
00765     type_t *type,              /* [I] type */
00766     int *encoded_type,         /* [O] The encoded type description. */
00767     int *width,                /* [O] The width of the type, or NULL. */
00768     int *alignment,            /* [O] The alignment of the type, or NULL. */
00769     int *decoded_size)         /* [O] The total size of the unencoded TYPEDESCs, including nested descs. */
00770 {
00771     int default_type;
00772     int scratch;
00773     int typeoffset;
00774     int *typedata;
00775     int target_type;
00776     int child_size = 0;
00777 
00778     chat("encode_type vt %d type %p\n", vt, type);
00779 
00780     default_type = 0x80000000 | (vt << 16) | vt;
00781     if (!width) width = &scratch;
00782     if (!alignment) alignment = &scratch;
00783     if (!decoded_size) decoded_size = &scratch;
00784 
00785 
00786     switch (vt) {
00787     case VT_I1:
00788     case VT_UI1:
00789     *encoded_type = default_type;
00790     *width = 1;
00791     *alignment = 1;
00792     break;
00793 
00794     case VT_INT:
00795     *encoded_type = 0x80000000 | (VT_I4 << 16) | VT_INT;
00796     if ((typelib->typelib_header.varflags & 0x0f) == SYS_WIN16) {
00797         *width = 2;
00798         *alignment = 2;
00799     } else {
00800         *width = 4;
00801         *alignment = 4;
00802     }
00803     break;
00804 
00805     case VT_UINT:
00806     *encoded_type = 0x80000000 | (VT_UI4 << 16) | VT_UINT;
00807     if ((typelib->typelib_header.varflags & 0x0f) == SYS_WIN16) {
00808         *width = 2;
00809         *alignment = 2;
00810     } else {
00811         *width = 4;
00812         *alignment = 4;
00813     }
00814     break;
00815 
00816     case VT_UI2:
00817     case VT_I2:
00818     case VT_BOOL:
00819     *encoded_type = default_type;
00820     *width = 2;
00821     *alignment = 2;
00822     break;
00823 
00824     case VT_I4:
00825     case VT_UI4:
00826     case VT_R4:
00827     case VT_ERROR:
00828     case VT_BSTR:
00829     case VT_HRESULT:
00830     *encoded_type = default_type;
00831     *width = 4;
00832     *alignment = 4;
00833     break;
00834 
00835     case VT_R8:
00836     case VT_I8:
00837     case VT_UI8:
00838     *encoded_type = default_type;
00839     *width = 8;
00840     *alignment = 8;
00841     break;
00842 
00843     case VT_CY:
00844     case VT_DATE:
00845     *encoded_type = default_type;
00846     *width = 8;
00847     *alignment = 8;
00848     break;
00849 
00850     case VT_DECIMAL:
00851         *encoded_type = default_type;
00852         *width = 16;
00853         *alignment = 8;
00854         break;
00855 
00856     case VT_VOID:
00857     *encoded_type = 0x80000000 | (VT_EMPTY << 16) | vt;
00858     *width = 0;
00859     *alignment = 1;
00860     break;
00861 
00862     case VT_UNKNOWN:
00863     case VT_DISPATCH:
00864         *encoded_type = default_type;
00865         *width = 4;
00866         *alignment = 4;
00867         break;
00868 
00869     case VT_VARIANT:
00870         *encoded_type = default_type;
00871         break;
00872 
00873     case VT_LPSTR:
00874     case VT_LPWSTR:
00875         *encoded_type = 0xfffe0000 | vt;
00876         *width = 4;
00877         *alignment = 4;
00878         break;
00879 
00880     case VT_PTR:
00881       {
00882         int next_vt;
00883         for(next_vt = 0; is_ptr(type); type = type_pointer_get_ref(type)) {
00884             next_vt = get_type_vt(type_pointer_get_ref(type));
00885             if (next_vt != 0)
00886                 break;
00887         }
00888         /* if no type found then it must be void */
00889         if (next_vt == 0)
00890             next_vt = VT_VOID;
00891 
00892         encode_type(typelib, next_vt, type_pointer_get_ref(type),
00893                     &target_type, NULL, NULL, &child_size);
00894         /* these types already have an implicit pointer, so we don't need to
00895          * add another */
00896         if(next_vt == VT_DISPATCH || next_vt == VT_UNKNOWN) {
00897             chat("encode_type: skipping ptr\n");
00898             *encoded_type = target_type;
00899             *width = 4;
00900             *alignment = 4;
00901             *decoded_size = child_size;
00902             break;
00903         }
00904 
00905     for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
00906         typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
00907         if (((typedata[0] & 0xffff) == VT_PTR) && (typedata[1] == target_type)) break;
00908     }
00909 
00910     if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
00911         int mix_field;
00912         
00913         if (target_type & 0x80000000) {
00914         mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF;
00915         } else {
00916         typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
00917         mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
00918         }
00919 
00920         typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
00921         typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
00922 
00923         typedata[0] = (mix_field << 16) | VT_PTR;
00924         typedata[1] = target_type;
00925     }
00926 
00927     *encoded_type = typeoffset;
00928 
00929     *width = 4;
00930     *alignment = 4;
00931     *decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
00932         break;
00933     }
00934 
00935 
00936     case VT_SAFEARRAY:
00937     {
00938     type_t *element_type = type_alias_get_aliasee(type_array_get_element(type));
00939     int next_vt = get_type_vt(element_type);
00940 
00941     encode_type(typelib, next_vt, type_alias_get_aliasee(type_array_get_element(type)), &target_type, NULL, NULL, &child_size);
00942 
00943     for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
00944         typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
00945         if (((typedata[0] & 0xffff) == VT_SAFEARRAY) && (typedata[1] == target_type)) break;
00946     }
00947 
00948     if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
00949         int mix_field;
00950         
00951         if (target_type & 0x80000000) {
00952         mix_field = ((target_type >> 16) & VT_TYPEMASK) | VT_ARRAY;
00953         } else {
00954         typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
00955         mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
00956         }
00957 
00958         typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
00959         typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
00960 
00961         typedata[0] = (mix_field << 16) | VT_SAFEARRAY;
00962         typedata[1] = target_type;
00963     }
00964 
00965     *encoded_type = typeoffset;
00966 
00967     *width = 4;
00968     *alignment = 4;
00969     *decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
00970     break;
00971     }
00972 
00973 
00974     case VT_USERDEFINED:
00975       {
00976         int typeinfo_offset;
00977 
00978         /* typedef'd types without public attribute aren't included in the typelib */
00979         while (type->typelib_idx < 0 && type_is_alias(type) && !is_attr(type->attrs, ATTR_PUBLIC))
00980           type = type_alias_get_aliasee(type);
00981 
00982         chat("encode_type: VT_USERDEFINED - type %p name = %s real type %d idx %d\n", type,
00983              type->name, type_get_type(type), type->typelib_idx);
00984 
00985         if(type->typelib_idx == -1) {
00986             chat("encode_type: trying to ref not added type\n");
00987             switch (type_get_type(type)) {
00988             case TYPE_STRUCT:
00989                 add_structure_typeinfo(typelib, type);
00990                 break;
00991             case TYPE_INTERFACE:
00992                 add_interface_typeinfo(typelib, type);
00993                 break;
00994             case TYPE_ENUM:
00995                 add_enum_typeinfo(typelib, type);
00996                 break;
00997             case TYPE_COCLASS:
00998                 add_coclass_typeinfo(typelib, type);
00999                 break;
01000             default:
01001                 error("encode_type: VT_USERDEFINED - unhandled type %d\n",
01002                       type_get_type(type));
01003             }
01004         }
01005 
01006         typeinfo_offset = typelib->typelib_typeinfo_offsets[type->typelib_idx];
01007     for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
01008         typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
01009         if ((typedata[0] == ((0x7fff << 16) | VT_USERDEFINED)) && (typedata[1] == typeinfo_offset)) break;
01010     }
01011 
01012     if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
01013         typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
01014         typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
01015 
01016         typedata[0] = (0x7fff << 16) | VT_USERDEFINED;
01017         typedata[1] = typeinfo_offset;
01018     }
01019 
01020     *encoded_type = typeoffset;
01021     *width = 0;
01022     *alignment = 1;
01023         break;
01024       }
01025 
01026     default:
01027     error("encode_type: unrecognized type %d.\n", vt);
01028     *encoded_type = default_type;
01029     *width = 0;
01030     *alignment = 1;
01031     break;
01032     }
01033 
01034     return 0;
01035 }
01036 
01037 static void dump_type(type_t *t)
01038 {
01039     chat("dump_type: %p name %s type %d attrs %p\n", t, t->name, type_get_type(t), t->attrs);
01040 }
01041 
01042 static int encode_var(
01043     msft_typelib_t *typelib,   /* [I] The type library in which to encode the TYPEDESC. */
01044     type_t *type,              /* [I] The type description to encode. */
01045     var_t *var,                /* [I] The var to encode. */
01046     int *encoded_type,         /* [O] The encoded type description. */
01047     int *width,                /* [O] The width of the type, or NULL. */
01048     int *alignment,            /* [O] The alignment of the type, or NULL. */
01049     int *decoded_size)         /* [O] The total size of the unencoded TYPEDESCs, including nested descs. */
01050 {
01051     int typeoffset;
01052     int *typedata;
01053     int target_type;
01054     int child_size;
01055     int vt;
01056     int scratch;
01057 
01058     if (!width) width = &scratch;
01059     if (!alignment) alignment = &scratch;
01060     if (!decoded_size) decoded_size = &scratch;
01061     *decoded_size = 0;
01062 
01063     chat("encode_var: var %p type %p type->name %s\n",
01064          var, type, type->name ? type->name : "NULL");
01065 
01066     if (is_array(type) && !type_array_is_decl_as_ptr(type)) {
01067         int num_dims, elements = 1, arrayoffset;
01068         type_t *atype;
01069         int *arraydata;
01070 
01071         num_dims = 0;
01072         for (atype = type;
01073              is_array(atype) && !type_array_is_decl_as_ptr(atype);
01074              atype = type_array_get_element(atype))
01075             ++num_dims;
01076 
01077         chat("array with %d dimensions\n", num_dims);
01078         encode_var(typelib, atype, var, &target_type, width, alignment, NULL);
01079         arrayoffset = ctl2_alloc_segment(typelib, MSFT_SEG_ARRAYDESC, (2 + 2 * num_dims) * sizeof(int), 0);
01080         arraydata = (void *)&typelib->typelib_segment_data[MSFT_SEG_ARRAYDESC][arrayoffset];
01081 
01082         arraydata[0] = target_type;
01083         arraydata[1] = num_dims;
01084         arraydata[1] |= ((num_dims * 2 * sizeof(int)) << 16);
01085 
01086         arraydata += 2;
01087         for (atype = type;
01088              is_array(atype) && !type_array_is_decl_as_ptr(atype);
01089              atype = type_array_get_element(atype))
01090         {
01091             arraydata[0] = type_array_get_dim(atype);
01092             arraydata[1] = 0;
01093             arraydata += 2;
01094             elements *= type_array_get_dim(atype);
01095         }
01096 
01097         typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
01098         typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
01099 
01100         typedata[0] = (0x7ffe << 16) | VT_CARRAY;
01101         typedata[1] = arrayoffset;
01102 
01103         *encoded_type = typeoffset;
01104         *width = *width * elements;
01105         *decoded_size = 20 /*sizeof(ARRAYDESC)*/ + (num_dims - 1) * 8 /*sizeof(SAFEARRAYBOUND)*/;
01106         return 0;
01107     }
01108 
01109     vt = get_type_vt(type);
01110     if (vt == VT_PTR) {
01111         type_t *ref = is_ptr(type) ?
01112             type_pointer_get_ref(type) : type_array_get_element(type);
01113         int skip_ptr = encode_var(typelib, ref, var,
01114                                   &target_type, NULL, NULL, &child_size);
01115 
01116         if(skip_ptr == 2) {
01117             chat("encode_var: skipping ptr\n");
01118             *encoded_type = target_type;
01119             *decoded_size = child_size;
01120             *width = 4;
01121             *alignment = 4;
01122             return 0;
01123         }
01124 
01125     for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
01126         typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
01127         if (((typedata[0] & 0xffff) == VT_PTR) && (typedata[1] == target_type)) break;
01128     }
01129 
01130     if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
01131         int mix_field;
01132         
01133         if (target_type & 0x80000000) {
01134         mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF;
01135         } else {
01136         typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
01137         mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
01138         }
01139 
01140         typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
01141         typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
01142 
01143         typedata[0] = (mix_field << 16) | VT_PTR;
01144         typedata[1] = target_type;
01145     }
01146 
01147     *encoded_type = typeoffset;
01148 
01149     *width = 4;
01150     *alignment = 4;
01151     *decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
01152         return 0;
01153     }
01154 
01155     dump_type(type);
01156 
01157     encode_type(typelib, vt, type, encoded_type, width, alignment, decoded_size);
01158     /* these types already have an implicit pointer, so we don't need to
01159      * add another */
01160     if(vt == VT_DISPATCH || vt == VT_UNKNOWN) return 2;
01161     return 0;
01162 }
01163 
01164 static unsigned int get_ulong_val(unsigned int val, int vt)
01165 {
01166     switch(vt) {
01167     case VT_I2:
01168     case VT_BOOL:
01169     case VT_UI2:
01170         return val & 0xffff;
01171     case VT_I1:
01172     case VT_UI1:
01173         return val & 0xff;
01174     }
01175 
01176     return val;
01177 }
01178 
01179 static void write_value(msft_typelib_t* typelib, int *out, int vt, const void *value)
01180 {
01181     switch(vt) {
01182     case VT_I2:
01183     case VT_I4:
01184     case VT_R4:
01185     case VT_BOOL:
01186     case VT_I1:
01187     case VT_UI1:
01188     case VT_UI2:
01189     case VT_UI4:
01190     case VT_INT:
01191     case VT_UINT:
01192     case VT_HRESULT:
01193     case VT_PTR:
01194       {
01195         const unsigned int lv = get_ulong_val(*(const unsigned int *)value, vt);
01196         if((lv & 0x3ffffff) == lv) {
01197             *out = 0x80000000;
01198             *out |= vt << 26;
01199             *out |= lv;
01200         } else {
01201             int offset = ctl2_alloc_segment(typelib, MSFT_SEG_CUSTDATA, 8, 0);
01202             *((unsigned short *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset]) = vt;
01203             memcpy(&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+2], value, 4);
01204             *((unsigned short *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+6]) = 0x5757;
01205             *out = offset;
01206         }
01207         return;
01208       }
01209     case VT_BSTR:
01210       {
01211         const char *s = (const char *) value;
01212         int len = strlen(s), seg_len = (len + 6 + 3) & ~0x3;
01213         int offset = ctl2_alloc_segment(typelib, MSFT_SEG_CUSTDATA, seg_len, 0);
01214         *((unsigned short *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset]) = vt;
01215         memcpy(&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+2], &len, sizeof(len));
01216         memcpy(&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+6], value, len);
01217         len += 6;
01218         while(len < seg_len) {
01219             *((char *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+len]) = 0x57;
01220             len++;
01221         }
01222         *out = offset;
01223         return;
01224       }
01225 
01226     default:
01227         warning("can't write value of type %d yet\n", vt);
01228     }
01229     return;
01230 }
01231 
01232 static HRESULT set_custdata(msft_typelib_t *typelib, REFGUID guid,
01233                             int vt, int value, int *offset)
01234 {
01235     MSFT_GuidEntry guidentry;
01236     int guidoffset;
01237     int custoffset;
01238     int *custdata;
01239     int data_out;
01240 
01241     guidentry.guid = *guid;
01242 
01243     guidentry.hreftype = -1;
01244     guidentry.next_hash = -1;
01245 
01246     guidoffset = ctl2_alloc_guid(typelib, &guidentry);
01247     write_value(typelib, &data_out, vt, &value);
01248 
01249     custoffset = ctl2_alloc_segment(typelib, MSFT_SEG_CUSTDATAGUID, 12, 0);
01250 
01251     custdata = (int *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATAGUID][custoffset];
01252     custdata[0] = guidoffset;
01253     custdata[1] = data_out;
01254     custdata[2] = *offset;
01255     *offset = custoffset;
01256 
01257     return S_OK;
01258 }
01259 
01260 static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index)
01261 {
01262     int offset, name_offset;
01263     int *typedata, typedata_size;
01264     int i, id, next_idx;
01265     int decoded_size, extra_attr = 0;
01266     int num_params = 0, num_optional = 0, num_defaults = 0;
01267     var_t *arg;
01268     unsigned char *namedata;
01269     const attr_t *attr;
01270     unsigned int funcflags = 0, callconv = 4 /* CC_STDCALL */;
01271     unsigned int funckind, invokekind = 1 /* INVOKE_FUNC */;
01272     int help_context = 0, help_string_context = 0, help_string_offset = -1;
01273     int entry = -1, entry_is_ord = 0;
01274     int lcid_retval_count = 0;
01275 
01276     chat("add_func_desc(%p,%d)\n", typeinfo, index);
01277 
01278     id = ((0x6000 | (typeinfo->typeinfo->datatype2 & 0xffff)) << 16) | index;
01279 
01280     switch(typeinfo->typekind) {
01281     case TKIND_DISPATCH:
01282         funckind = 0x4; /* FUNC_DISPATCH */
01283         break;
01284     case TKIND_MODULE:
01285         funckind = 0x3; /* FUNC_STATIC */
01286         break;
01287     default:
01288         funckind = 0x1; /* FUNC_PUREVIRTUAL */
01289         break;
01290     }
01291 
01292     if (is_local( func->attrs )) {
01293         chat("add_func_desc: skipping local function\n");
01294         return S_FALSE;
01295     }
01296 
01297     if (type_get_function_args(func->type))
01298       LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), var_t, entry )
01299       {
01300         num_params++;
01301         if (arg->attrs) LIST_FOR_EACH_ENTRY( attr, arg->attrs, const attr_t, entry ) {
01302             if(attr->type == ATTR_DEFAULTVALUE)
01303                 num_defaults++;
01304             else if(attr->type == ATTR_OPTIONAL)
01305                 num_optional++;
01306         }
01307       }
01308 
01309     chat("add_func_desc: num of params %d\n", num_params);
01310 
01311     name_offset = ctl2_alloc_name(typeinfo->typelib, func->name);
01312 
01313     if (func->attrs) LIST_FOR_EACH_ENTRY( attr, func->attrs, const attr_t, entry ) {
01314         expr_t *expr = attr->u.pval;
01315         switch(attr->type) {
01316         case ATTR_BINDABLE:
01317             funcflags |= 0x4; /* FUNCFLAG_FBINDABLE */
01318             break;
01319         case ATTR_DEFAULTBIND:
01320             funcflags |= 0x20; /* FUNCFLAG_FDEFAULTBIND */
01321             break;
01322         case ATTR_DEFAULTCOLLELEM:
01323             funcflags |= 0x100; /* FUNCFLAG_FDEFAULTCOLLELEM */
01324             break;
01325         case ATTR_DISPLAYBIND:
01326             funcflags |= 0x10; /* FUNCFLAG_FDISPLAYBIND */
01327             break;
01328         case ATTR_ENTRY:
01329             extra_attr = max(extra_attr, 3);
01330             if (expr->type == EXPR_STRLIT || expr->type == EXPR_WSTRLIT)
01331               entry = ctl2_alloc_string(typeinfo->typelib, attr->u.pval);
01332             else {
01333               entry = expr->cval;
01334               entry_is_ord = 1;
01335             }
01336             break;
01337         case ATTR_HELPCONTEXT:
01338             extra_attr = max(extra_attr, 1);
01339             help_context = expr->u.lval;
01340             break;
01341         case ATTR_HELPSTRING:
01342             extra_attr = max(extra_attr, 2);
01343             help_string_offset = ctl2_alloc_string(typeinfo->typelib, attr->u.pval);
01344             break;
01345         case ATTR_HELPSTRINGCONTEXT:
01346             extra_attr = max(extra_attr, 6);
01347             help_string_context = expr->u.lval;
01348             break;
01349         case ATTR_HIDDEN:
01350             funcflags |= 0x40; /* FUNCFLAG_FHIDDEN */
01351             break;
01352         case ATTR_ID:
01353             id = expr->cval;
01354             break;
01355         case ATTR_IMMEDIATEBIND:
01356             funcflags |= 0x1000; /* FUNCFLAG_FIMMEDIATEBIND */
01357             break;
01358         case ATTR_NONBROWSABLE:
01359             funcflags |= 0x400; /* FUNCFLAG_FNONBROWSABLE */
01360             break;
01361         case ATTR_OUT:
01362             break;
01363         case ATTR_PROPGET:
01364             invokekind = 0x2; /* INVOKE_PROPERTYGET */
01365             break;
01366         case ATTR_PROPPUT:
01367             invokekind = 0x4; /* INVOKE_PROPERTYPUT */
01368             break;
01369         case ATTR_PROPPUTREF:
01370             invokekind = 0x8; /* INVOKE_PROPERTYPUTREF */
01371             break;
01372         /* FIXME: FUNCFLAG_FREPLACEABLE */
01373         case ATTR_REQUESTEDIT:
01374             funcflags |= 0x8; /* FUNCFLAG_FREQUESTEDIT */
01375             break;
01376         case ATTR_RESTRICTED:
01377             funcflags |= 0x1; /* FUNCFLAG_FRESTRICTED */
01378             break;
01379         case ATTR_SOURCE:
01380             funcflags |= 0x2; /* FUNCFLAG_FSOURCE */
01381             break;
01382         case ATTR_UIDEFAULT:
01383             funcflags |= 0x200; /* FUNCFLAG_FUIDEFAULT */
01384             break;
01385         case ATTR_USESGETLASTERROR:
01386             funcflags |= 0x80; /* FUNCFLAG_FUSESGETLASTERROR */
01387             break;
01388         case ATTR_VARARG:
01389             if (num_optional || num_defaults)
01390                 warning("add_func_desc: ignoring vararg in function with optional or defaultvalue params\n");
01391             else
01392                 num_optional = -1;
01393             break;
01394         default:
01395             break;
01396         }
01397     }
01398 
01399     /* allocate type data space for us */
01400     typedata_size = 0x18 + extra_attr * sizeof(int) + (num_params * (num_defaults ? 16 : 12));
01401 
01402     if (!typeinfo->func_data) {
01403         typeinfo->func_data = xmalloc(0x100);
01404         typeinfo->func_data_allocated = 0x100;
01405         typeinfo->func_data[0] = 0;
01406     }
01407 
01408     if(typeinfo->func_data[0] + typedata_size + sizeof(int) > typeinfo->func_data_allocated) {
01409         typeinfo->func_data_allocated = max(typeinfo->func_data_allocated * 2,
01410                                             typeinfo->func_data[0] + typedata_size + sizeof(int));
01411         typeinfo->func_data = xrealloc(typeinfo->func_data, typeinfo->func_data_allocated);
01412     }
01413 
01414     offset = typeinfo->func_data[0];
01415     typeinfo->func_data[0] += typedata_size;
01416     typedata = typeinfo->func_data + (offset >> 2) + 1;
01417 
01418 
01419     /* find func with the same name - if it exists use its id */
01420     for(i = 0; i < (typeinfo->typeinfo->cElement & 0xffff); i++) {
01421         if(name_offset == typeinfo->func_names[i]) {
01422             id = typeinfo->func_indices[i];
01423             break;
01424         }
01425     }
01426 
01427     /* find the first func with the same id and link via the hiword of typedata[4] */
01428     next_idx = index;
01429     for(i = 0; i < (typeinfo->typeinfo->cElement & 0xffff); i++) {
01430         if(id == typeinfo->func_indices[i]) {
01431             next_idx = typeinfo->func_data[(typeinfo->func_offsets[i] >> 2) + 1 + 4] >> 16;
01432             typeinfo->func_data[(typeinfo->func_offsets[i] >> 2) + 1 + 4] &= 0xffff;
01433             typeinfo->func_data[(typeinfo->func_offsets[i] >> 2) + 1 + 4] |= (index << 16);
01434             break;
01435         }
01436     }
01437 
01438     /* fill out the basic type information */
01439     typedata[0] = typedata_size | (index << 16);
01440     encode_var(typeinfo->typelib, type_function_get_rettype(func->type), func, &typedata[1], NULL, NULL, &decoded_size);
01441     typedata[2] = funcflags;
01442     typedata[3] = ((52 /*sizeof(FUNCDESC)*/ + decoded_size) << 16) | typeinfo->typeinfo->cbSizeVft;
01443     typedata[4] = (next_idx << 16) | (callconv << 8) | (invokekind << 3) | funckind;
01444     if(num_defaults) typedata[4] |= 0x1000;
01445     if(entry_is_ord) typedata[4] |= 0x2000;
01446     typedata[5] = (num_optional << 16) | num_params;
01447 
01448     /* NOTE: High word of typedata[3] is total size of FUNCDESC + size of all ELEMDESCs for params + TYPEDESCs for pointer params and return types. */
01449     /* That is, total memory allocation required to reconstitute the FUNCDESC in its entirety. */
01450     typedata[3] += (16 /*sizeof(ELEMDESC)*/ * num_params) << 16;
01451     typedata[3] += (24 /*sizeof(PARAMDESCEX)*/ * num_defaults) << 16;
01452 
01453     switch(extra_attr) {
01454     case 6: typedata[11] = help_string_context;
01455     case 5: typedata[10] = -1;
01456     case 4: typedata[9] = -1;
01457     case 3: typedata[8] = entry;
01458     case 2: typedata[7] = help_string_offset;
01459     case 1: typedata[6] = help_context;
01460     case 0:
01461         break;
01462     default:
01463         warning("unknown number of optional attrs\n");
01464     }
01465 
01466     if (type_get_function_args(func->type))
01467     {
01468       i = 0;
01469       LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), var_t, entry )
01470       {
01471         int paramflags = 0;
01472         int *paramdata = typedata + 6 + extra_attr + (num_defaults ? num_params : 0) + i * 3;
01473         int *defaultdata = num_defaults ? typedata + 6 + extra_attr + i : NULL;
01474 
01475         if(defaultdata) *defaultdata = -1;
01476 
01477     encode_var(typeinfo->typelib, arg->type, arg, paramdata, NULL, NULL, &decoded_size);
01478         if (arg->attrs) LIST_FOR_EACH_ENTRY( attr, arg->attrs, const attr_t, entry ) {
01479             switch(attr->type) {
01480             case ATTR_DEFAULTVALUE:
01481               {
01482                 int vt;
01483                 expr_t *expr = (expr_t *)attr->u.pval;
01484                 if (type_get_type(arg->type) == TYPE_ENUM)
01485                     vt = VT_INT;
01486                 else
01487                     vt = get_type_vt(arg->type);
01488                 paramflags |= 0x30; /* PARAMFLAG_FHASDEFAULT | PARAMFLAG_FOPT */
01489                 if (expr->type == EXPR_STRLIT || expr->type == EXPR_WSTRLIT)
01490                 {
01491                   if (vt != VT_BSTR) error("string default value applied to non-string type\n");
01492                   chat("default value '%s'\n", expr->u.sval);
01493                   write_value(typeinfo->typelib, defaultdata, vt, expr->u.sval);
01494                 }
01495                 else
01496                 {
01497                   chat("default value %d\n", expr->cval);
01498                   write_value(typeinfo->typelib, defaultdata, vt, &expr->cval);
01499                 }
01500                 break;
01501               }
01502             case ATTR_IN:
01503                 paramflags |= 0x01; /* PARAMFLAG_FIN */
01504                 break;
01505             case ATTR_OPTIONAL:
01506                 paramflags |= 0x10; /* PARAMFLAG_FOPT */
01507                 break;
01508             case ATTR_OUT:
01509                 paramflags |= 0x02; /* PARAMFLAG_FOUT */
01510                 break;
01511             case ATTR_PARAMLCID:
01512                 paramflags |= 0x04; /* PARAMFLAG_LCID */
01513                 lcid_retval_count++;
01514                 break;
01515             case ATTR_RETVAL:
01516                 paramflags |= 0x08; /* PARAMFLAG_FRETVAL */
01517                 lcid_retval_count++;
01518                 break;
01519             default:
01520                 chat("unhandled param attr %d\n", attr->type);
01521                 break;
01522             }
01523         }
01524     paramdata[1] = -1;
01525     paramdata[2] = paramflags;
01526     typedata[3] += decoded_size << 16;
01527 
01528         i++;
01529       }
01530     }
01531 
01532     if(lcid_retval_count == 1)
01533         typedata[4] |= 0x4000;
01534     else if(lcid_retval_count == 2)
01535         typedata[4] |= 0x8000;
01536 
01537     if(typeinfo->funcs_allocated == 0) {
01538         typeinfo->funcs_allocated = 10;
01539         typeinfo->func_indices = xmalloc(typeinfo->funcs_allocated * sizeof(int));
01540         typeinfo->func_names   = xmalloc(typeinfo->funcs_allocated * sizeof(int));
01541         typeinfo->func_offsets = xmalloc(typeinfo->funcs_allocated * sizeof(int));
01542     }
01543     if(typeinfo->funcs_allocated == (typeinfo->typeinfo->cElement & 0xffff)) {
01544         typeinfo->funcs_allocated *= 2;
01545         typeinfo->func_indices = xrealloc(typeinfo->func_indices, typeinfo->funcs_allocated * sizeof(int));
01546         typeinfo->func_names   = xrealloc(typeinfo->func_names,   typeinfo->funcs_allocated * sizeof(int));
01547         typeinfo->func_offsets = xrealloc(typeinfo->func_offsets, typeinfo->funcs_allocated * sizeof(int));
01548     }
01549 
01550     /* update the index data */
01551     typeinfo->func_indices[typeinfo->typeinfo->cElement & 0xffff] = id; 
01552     typeinfo->func_offsets[typeinfo->typeinfo->cElement & 0xffff] = offset;
01553     typeinfo->func_names[typeinfo->typeinfo->cElement & 0xffff] = name_offset;
01554 
01555     /* ??? */
01556     if (!typeinfo->typeinfo->res2) typeinfo->typeinfo->res2 = 0x20;
01557     typeinfo->typeinfo->res2 <<= 1;
01558     /* ??? */
01559     if (index < 2) typeinfo->typeinfo->res2 += num_params << 4;
01560 
01561     if (typeinfo->typeinfo->res3 == -1) typeinfo->typeinfo->res3 = 0;
01562     typeinfo->typeinfo->res3 += 0x38 + num_params * 0x10;
01563     if(num_defaults) typeinfo->typeinfo->res3 += num_params * 0x4;
01564 
01565     /* adjust size of VTBL */
01566     if(funckind != 0x3 /* FUNC_STATIC */)
01567         typeinfo->typeinfo->cbSizeVft += pointer_size;
01568 
01569     /* Increment the number of function elements */
01570     typeinfo->typeinfo->cElement += 1;
01571 
01572     namedata = typeinfo->typelib->typelib_segment_data[MSFT_SEG_NAME] + name_offset;
01573     if (*((INT *)namedata) == -1) {
01574     *((INT *)namedata) = typeinfo->typelib->typelib_typeinfo_offsets[typeinfo->typeinfo->typekind >> 16];
01575         if(typeinfo->typekind == TKIND_MODULE)
01576             namedata[9] |= 0x10;
01577     } else
01578         namedata[9] &= ~0x10;
01579 
01580     if(typeinfo->typekind == TKIND_MODULE)
01581         namedata[9] |= 0x20;
01582 
01583     if (type_get_function_args(func->type))
01584     {
01585         i = 0;
01586         LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), var_t, entry )
01587         {
01588             /* don't give the last arg of a [propput*] func a name */
01589             if(i != num_params - 1 || (invokekind != 0x4 /* INVOKE_PROPERTYPUT */ && invokekind != 0x8 /* INVOKE_PROPERTYPUTREF */))
01590             {
01591                 int *paramdata = typedata + 6 + extra_attr + (num_defaults ? num_params : 0) + i * 3;
01592                 offset = ctl2_alloc_name(typeinfo->typelib, arg->name);
01593                 paramdata[1] = offset;
01594             }
01595             i++;
01596         }
01597     }
01598     return S_OK;
01599 }
01600 
01601 static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var)
01602 {
01603     int offset, id;
01604     unsigned int typedata_size;
01605     INT *typedata;
01606     int var_datawidth;
01607     int var_alignment;
01608     int var_type_size, var_kind = 0 /* VAR_PERINSTANCE */; 
01609     int alignment;
01610     int varflags = 0;
01611     const attr_t *attr;
01612     unsigned char *namedata;
01613     int var_num = (typeinfo->typeinfo->cElement >> 16) & 0xffff;
01614 
01615     chat("add_var_desc(%d, %s)\n", index, var->name);
01616 
01617     id = 0x40000000 + index;
01618 
01619     if (var->attrs) LIST_FOR_EACH_ENTRY( attr, var->attrs, const attr_t, entry ) {
01620         expr_t *expr = attr->u.pval;
01621         switch(attr->type) {
01622         case ATTR_BINDABLE:
01623             varflags |= 0x04; /* VARFLAG_FBINDABLE */
01624             break;
01625         case ATTR_DEFAULTBIND:
01626             varflags |= 0x20; /* VARFLAG_FDEFAULTBIND */
01627             break;
01628         case ATTR_DEFAULTCOLLELEM:
01629             varflags |= 0x100; /* VARFLAG_FDEFAULTCOLLELEM */
01630             break;
01631         case ATTR_DISPLAYBIND:
01632             varflags |= 0x10; /* VARFLAG_FDISPLAYBIND */
01633             break;
01634         case ATTR_HIDDEN:
01635             varflags |= 0x40; /* VARFLAG_FHIDDEN */
01636             break;
01637         case ATTR_ID:
01638             id = expr->cval;
01639             break;
01640         case ATTR_IMMEDIATEBIND:
01641             varflags |= 0x1000; /* VARFLAG_FIMMEDIATEBIND */
01642             break;
01643         case ATTR_NONBROWSABLE:
01644             varflags |= 0x400; /* VARFLAG_FNONBROWSABLE */
01645             break;
01646         case ATTR_READONLY:
01647             varflags |= 0x01; /* VARFLAG_FREADONLY */
01648             break;
01649         /* FIXME: VARFLAG_FREPLACEABLE */
01650         case ATTR_REQUESTEDIT:
01651             varflags |= 0x08; /* VARFLAG_FREQUESTEDIT */
01652             break;
01653         case ATTR_RESTRICTED:
01654             varflags |= 0x80; /* VARFLAG_FRESTRICTED */
01655             break;
01656         case ATTR_SOURCE:
01657             varflags |= 0x02; /* VARFLAG_FSOURCE */
01658             break;
01659         case ATTR_UIDEFAULT:
01660             varflags |= 0x0200; /* VARFLAG_FUIDEFAULT */
01661             break;
01662         default:
01663             break;
01664         }
01665     }
01666 
01667     /* allocate type data space for us */
01668     typedata_size = 0x14;
01669 
01670     if (!typeinfo->var_data) {
01671         typeinfo->var_data = xmalloc(0x100);
01672         typeinfo->var_data_allocated = 0x100;
01673         typeinfo->var_data[0] = 0;
01674     }
01675 
01676     if(typeinfo->var_data[0] + typedata_size + sizeof(int) > typeinfo->var_data_allocated) {
01677         typeinfo->var_data_allocated = max(typeinfo->var_data_allocated * 2,
01678                                             typeinfo->var_data[0] + typedata_size + sizeof(int));
01679         typeinfo->var_data = xrealloc(typeinfo->var_data, typeinfo->var_data_allocated);
01680     }
01681 
01682     offset = typeinfo->var_data[0];
01683     typeinfo->var_data[0] += typedata_size;
01684     typedata = typeinfo->var_data + (offset >> 2) + 1;
01685 
01686     /* fill out the basic type information */
01687     typedata[0] = typedata_size | (index << 16);
01688     typedata[2] = varflags;
01689     typedata[3] = (36 /*sizeof(VARDESC)*/ << 16) | 0;
01690 
01691     if(typeinfo->vars_allocated == 0) {
01692         typeinfo->vars_allocated = 10;
01693         typeinfo->var_indices = xmalloc(typeinfo->vars_allocated * sizeof(int));
01694         typeinfo->var_names   = xmalloc(typeinfo->vars_allocated * sizeof(int));
01695         typeinfo->var_offsets = xmalloc(typeinfo->vars_allocated * sizeof(int));
01696     }
01697     if(typeinfo->vars_allocated == var_num) {
01698         typeinfo->vars_allocated *= 2;
01699         typeinfo->var_indices = xrealloc(typeinfo->var_indices, typeinfo->vars_allocated * sizeof(int));
01700         typeinfo->var_names   = xrealloc(typeinfo->var_names,   typeinfo->vars_allocated * sizeof(int));
01701         typeinfo->var_offsets = xrealloc(typeinfo->var_offsets, typeinfo->vars_allocated * sizeof(int));
01702     }
01703     /* update the index data */
01704     typeinfo->var_indices[var_num] = id;
01705     typeinfo->var_names[var_num] = -1;
01706     typeinfo->var_offsets[var_num] = offset;
01707 
01708     /* figure out type widths and whatnot */
01709     encode_var(typeinfo->typelib, var->type, var, &typedata[1], &var_datawidth,
01710                &var_alignment, &var_type_size);
01711 
01712     /* pad out starting position to data width */
01713     typeinfo->datawidth += var_alignment - 1;
01714     typeinfo->datawidth &= ~(var_alignment - 1);
01715 
01716     switch(typeinfo->typekind) {
01717     case TKIND_ENUM:
01718         write_value(typeinfo->typelib, &typedata[4], VT_I4, &var->eval->cval);
01719         var_kind = 2; /* VAR_CONST */
01720         var_type_size += 16; /* sizeof(VARIANT) */
01721         typeinfo->datawidth = var_datawidth;
01722         break;
01723     case TKIND_RECORD:
01724         typedata[4] = typeinfo->datawidth;
01725         typeinfo->datawidth += var_datawidth;
01726         break;
01727     case TKIND_DISPATCH:
01728         var_kind = 3; /* VAR_DISPATCH */
01729         typeinfo->datawidth = 4;
01730         var_alignment = 4;
01731         break;
01732     default:
01733         error("add_var_desc: unhandled type kind %d\n", typeinfo->typekind);
01734         break;
01735     }
01736 
01737     /* add type description size to total required allocation */
01738     typedata[3] += var_type_size << 16 | var_kind;
01739 
01740     /* fix type alignment */
01741     alignment = (typeinfo->typeinfo->typekind >> 11) & 0x1f;
01742     if (alignment < var_alignment) {
01743     alignment = var_alignment;
01744     typeinfo->typeinfo->typekind &= ~0xffc0;
01745     typeinfo->typeinfo->typekind |= alignment << 11 | alignment << 6;
01746     }
01747 
01748     /* ??? */
01749     if (!typeinfo->typeinfo->res2) typeinfo->typeinfo->res2 = 0x1a;
01750     if ((index == 0) || (index == 1) || (index == 2) || (index == 4) || (index == 9)) {
01751     typeinfo->typeinfo->res2 <<= 1;
01752     }
01753 
01754     /* ??? */
01755     if (typeinfo->typeinfo->res3 == -1) typeinfo->typeinfo->res3 = 0;
01756     typeinfo->typeinfo->res3 += 0x2c;
01757 
01758     /* increment the number of variable elements */
01759     typeinfo->typeinfo->cElement += 0x10000;
01760 
01761     /* pad data width to alignment */
01762     typeinfo->typeinfo->size = (typeinfo->datawidth + (alignment - 1)) & ~(alignment - 1);
01763 
01764     offset = ctl2_alloc_name(typeinfo->typelib, var->name);
01765     if (offset == -1) return E_OUTOFMEMORY;
01766 
01767     namedata = typeinfo->typelib->typelib_segment_data[MSFT_SEG_NAME] + offset;
01768     if (*((INT *)namedata) == -1) {
01769     *((INT *)namedata) = typeinfo->typelib->typelib_typeinfo_offsets[typeinfo->typeinfo->typekind >> 16];
01770         if(typeinfo->typekind != TKIND_DISPATCH)
01771             namedata[9] |= 0x10;
01772     } else
01773         namedata[9] &= ~0x10;
01774 
01775     if (typeinfo->typekind == TKIND_ENUM) {
01776     namedata[9] |= 0x20;
01777     }
01778     typeinfo->var_names[var_num] = offset;
01779 
01780     return S_OK;
01781 }
01782 
01783 static HRESULT add_impl_type(msft_typeinfo_t *typeinfo, type_t *ref, importinfo_t *importinfo)
01784 {
01785     if(importinfo) {
01786         alloc_importinfo(typeinfo->typelib, importinfo);
01787         typeinfo->typeinfo->datatype1 = importinfo->offset+1;
01788     }else {
01789         if(ref->typelib_idx == -1)
01790             add_interface_typeinfo(typeinfo->typelib, ref);
01791         if(ref->typelib_idx == -1)
01792             error("add_impl_type: unable to add inherited interface\n");
01793 
01794         typeinfo->typeinfo->datatype1 = typeinfo->typelib->typelib_typeinfo_offsets[ref->typelib_idx];
01795     }
01796 
01797     typeinfo->typeinfo->cImplTypes++;
01798     return S_OK;
01799 }
01800 
01801 static msft_typeinfo_t *create_msft_typeinfo(msft_typelib_t *typelib, enum type_kind kind,
01802                                              const char *name, const attr_list_t *attrs)
01803 {
01804     const attr_t *attr;
01805     msft_typeinfo_t *msft_typeinfo;
01806     int nameoffset;
01807     int typeinfo_offset;
01808     MSFT_TypeInfoBase *typeinfo;
01809     MSFT_GuidEntry guidentry;
01810 
01811     chat("create_msft_typeinfo: name %s kind %d\n", name, kind);
01812 
01813     msft_typeinfo = xmalloc(sizeof(*msft_typeinfo));
01814     memset( msft_typeinfo, 0, sizeof(*msft_typeinfo) );
01815 
01816     msft_typeinfo->typelib = typelib;
01817 
01818     nameoffset = ctl2_alloc_name(typelib, name);
01819     typeinfo_offset = ctl2_alloc_typeinfo(typelib, nameoffset);
01820     typeinfo = (MSFT_TypeInfoBase *)&typelib->typelib_segment_data[MSFT_SEG_TYPEINFO][typeinfo_offset];
01821 
01822     typelib->typelib_segment_data[MSFT_SEG_NAME][nameoffset + 9] = 0x38;
01823     *((int *)&typelib->typelib_segment_data[MSFT_SEG_NAME][nameoffset]) = typeinfo_offset;
01824 
01825     msft_typeinfo->typekind = kind;
01826     msft_typeinfo->typeinfo = typeinfo;
01827 
01828     typeinfo->typekind |= kind | 0x20;
01829 
01830     if(kind == TKIND_COCLASS)
01831         typeinfo->flags |= 0x2; /* TYPEFLAG_FCANCREATE */
01832 
01833     if (attrs) LIST_FOR_EACH_ENTRY( attr, attrs, const attr_t, entry ) {
01834         switch(attr->type) {
01835         case ATTR_AGGREGATABLE:
01836             if (kind == TKIND_COCLASS)
01837                 typeinfo->flags |= 0x400; /* TYPEFLAG_FAGGREGATABLE */
01838             break;
01839 
01840         case ATTR_APPOBJECT:
01841             if (kind == TKIND_COCLASS)
01842                 typeinfo->flags |= 0x1; /* TYPEFLAG_FAPPOBJECT */
01843             break;
01844 
01845         case ATTR_CONTROL:
01846             if (kind == TKIND_COCLASS)
01847                 typeinfo->flags |= 0x20; /* TYPEFLAG_FCONTROL */
01848             break;
01849 
01850         case ATTR_DLLNAME:
01851           {
01852             int offset = ctl2_alloc_string(typelib, attr->u.pval);
01853             typeinfo->datatype1 = offset;
01854             break;
01855           }
01856 
01857         case ATTR_DUAL:
01858             /* FIXME: check interface is compatible */
01859             typeinfo->typekind = (typeinfo->typekind & ~0xff) | 0x34;
01860             typeinfo->flags |= 0x140; /* TYPEFLAG_FDUAL | TYPEFLAG_FOLEAUTOMATION */
01861             break;
01862 
01863         case ATTR_HELPCONTEXT:
01864           {
01865             expr_t *expr = (expr_t*)attr->u.pval;
01866             typeinfo->helpcontext = expr->cval;
01867             break;
01868           }
01869         case ATTR_HELPSTRING:
01870           {
01871             int offset = ctl2_alloc_string(typelib, attr->u.pval);
01872             if (offset == -1) break;
01873             typeinfo->docstringoffs = offset;
01874             break;
01875           }
01876         case ATTR_HELPSTRINGCONTEXT:
01877           {
01878             expr_t *expr = (expr_t*)attr->u.pval;
01879             typeinfo->helpstringcontext = expr->cval;
01880             break;
01881           }
01882         case ATTR_HIDDEN:
01883             typeinfo->flags |= 0x10; /* TYPEFLAG_FHIDDEN */
01884             break;
01885 
01886         case ATTR_LICENSED:
01887             typeinfo->flags |= 0x04; /* TYPEFLAG_FLICENSED */
01888             break;
01889 
01890         case ATTR_NONCREATABLE:
01891             typeinfo->flags &= ~0x2; /* TYPEFLAG_FCANCREATE */
01892             break;
01893 
01894         case ATTR_NONEXTENSIBLE:
01895             typeinfo->flags |= 0x80; /* TYPEFLAG_FNONEXTENSIBLE */
01896             break;
01897 
01898         case ATTR_OLEAUTOMATION:
01899             typeinfo->flags |= 0x100; /* TYPEFLAG_FOLEAUTOMATION */
01900             break;
01901 
01902         /* FIXME: TYPEFLAG_FPREDCLID */
01903 
01904         case ATTR_PROXY:
01905             typeinfo->flags |= 0x4000; /* TYPEFLAG_FPROXY */
01906             break;
01907 
01908         /* FIXME: TYPEFLAG_FREPLACEABLE */
01909 
01910         case ATTR_RESTRICTED:
01911             typeinfo->flags |= 0x200; /* TYPEFLAG_FRESTRICTED */
01912             break;
01913 
01914         case ATTR_UUID:
01915             guidentry.guid = *(GUID*)attr->u.pval;
01916             guidentry.hreftype = typelib->typelib_typeinfo_offsets[typeinfo->typekind >> 16];
01917             guidentry.next_hash = -1;
01918             typeinfo->posguid = ctl2_alloc_guid(typelib, &guidentry);
01919 #if 0
01920             if (IsEqualIID(guid, &IID_IDispatch)) {
01921                 typelib->typelib_header.dispatchpos = typelib->typelib_typeinfo_offsets[typeinfo->typekind >> 16];
01922             }
01923 #endif
01924             break;
01925 
01926         case ATTR_VERSION:
01927             typeinfo->version = attr->u.ival;
01928             break;
01929 
01930         default:
01931             break;
01932         }
01933     }
01934 
01935     if (typelib->last_typeinfo) typelib->last_typeinfo->next_typeinfo = msft_typeinfo;
01936     typelib->last_typeinfo = msft_typeinfo;
01937     if (!typelib->typeinfos) typelib->typeinfos = msft_typeinfo;
01938 
01939 
01940     return msft_typeinfo;
01941 }
01942 
01943 static void add_dispatch(msft_typelib_t *typelib)
01944 {
01945     int guid_offset, impfile_offset;
01946     MSFT_GuidEntry guidentry;
01947     MSFT_ImpInfo impinfo;
01948     GUID stdole =        {0x00020430,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
01949     GUID iid_idispatch = {0x00020400,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
01950 
01951     if(typelib->typelib_header.dispatchpos != -1) return;
01952 
01953     guidentry.guid = stdole;
01954     guidentry.hreftype = 2;
01955     guidentry.next_hash = -1;
01956     guid_offset = ctl2_alloc_guid(typelib, &guidentry);
01957     impfile_offset = alloc_importfile(typelib, guid_offset, 2, 0, "stdole2.tlb");
01958 
01959     guidentry.guid = iid_idispatch;
01960     guidentry.hreftype = 1;
01961     guidentry.next_hash = -1;
01962     impinfo.flags = TKIND_INTERFACE << 24 | MSFT_IMPINFO_OFFSET_IS_GUID;
01963     impinfo.oImpFile = impfile_offset;
01964     impinfo.oGuid = ctl2_alloc_guid(typelib, &guidentry);
01965     typelib->typelib_header.dispatchpos = alloc_msft_importinfo(typelib, &impinfo) | 0x01;
01966 }
01967 
01968 static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinterface)
01969 {
01970     int idx = 0;
01971     var_t *func;
01972     var_t *var;
01973     msft_typeinfo_t *msft_typeinfo;
01974 
01975     if (-1 < dispinterface->typelib_idx)
01976         return;
01977 
01978     dispinterface->typelib_idx = typelib->typelib_header.nrtypeinfos;
01979     msft_typeinfo = create_msft_typeinfo(typelib, TKIND_DISPATCH, dispinterface->name,
01980                                          dispinterface->attrs);
01981 
01982     msft_typeinfo->typeinfo->size = 4;
01983     msft_typeinfo->typeinfo->typekind |= 0x2100;
01984 
01985     msft_typeinfo->typeinfo->flags |= 0x1000; /* TYPEFLAG_FDISPATCHABLE */
01986     add_dispatch(typelib);
01987     msft_typeinfo->typeinfo->cImplTypes = 1;
01988 
01989     /* count the no of methods, as the variable indices come after the funcs */
01990     if (dispinterface->details.iface->disp_methods)
01991         LIST_FOR_EACH_ENTRY( func, dispinterface->details.iface->disp_methods, var_t, entry )
01992             idx++;
01993 
01994     if (type_dispiface_get_props(dispinterface))
01995         LIST_FOR_EACH_ENTRY( var, type_dispiface_get_props(dispinterface), var_t, entry )
01996             add_var_desc(msft_typeinfo, idx++, var);
01997 
01998     if (type_dispiface_get_methods(dispinterface))
01999     {
02000         idx = 0;
02001         LIST_FOR_EACH_ENTRY( func, type_dispiface_get_methods(dispinterface), var_t, entry )
02002             if(add_func_desc(msft_typeinfo, func, idx) == S_OK)
02003                 idx++;
02004     }
02005 }
02006 
02007 static void add_interface_typeinfo(msft_typelib_t *typelib, type_t *interface)
02008 {
02009     int idx = 0;
02010     const statement_t *stmt_func;
02011     type_t *ref;
02012     msft_typeinfo_t *msft_typeinfo;
02013     importinfo_t *ref_importinfo = NULL;
02014     int num_parents = 0, num_funcs = 0;
02015     type_t *inherit;
02016     const type_t *derived;
02017 
02018     if (-1 < interface->typelib_idx)
02019         return;
02020 
02021     if (!interface->details.iface)
02022     {
02023         error( "interface %s is referenced but not defined\n", interface->name );
02024         return;
02025     }
02026 
02027     if (is_attr(interface->attrs, ATTR_DISPINTERFACE))
02028         return add_dispinterface_typeinfo(typelib, interface);
02029 
02030     /* midl adds the parent interface first, unless the parent itself
02031        has no parent (i.e. it stops before IUnknown). */
02032 
02033     inherit = type_iface_get_inherit(interface);
02034 
02035     if(inherit) {
02036         ref_importinfo = find_importinfo(typelib, inherit->name);
02037 
02038         if(!ref_importinfo && type_iface_get_inherit(inherit) &&
02039            inherit->typelib_idx == -1)
02040             add_interface_typeinfo(typelib, inherit);
02041     }
02042 
02043     interface->typelib_idx = typelib->typelib_header.nrtypeinfos;
02044     msft_typeinfo = create_msft_typeinfo(typelib, TKIND_INTERFACE, interface->name, interface->attrs);
02045     msft_typeinfo->typeinfo->size = 4;
02046     msft_typeinfo->typeinfo->typekind |= 0x2200;
02047 
02048     for (derived = inherit; derived; derived = type_iface_get_inherit(derived))
02049         if (derived->name && !strcmp(derived->name, "IDispatch"))
02050             msft_typeinfo->typeinfo->flags |= 0x1000; /* TYPEFLAG_FDISPATCHABLE */
02051 
02052     /* can't be dual if it doesn't derive from IDispatch */
02053     if (!(msft_typeinfo->typeinfo->flags & 0x1000)) /* TYPEFLAG_FDISPATCHABLE */
02054         msft_typeinfo->typeinfo->flags &= ~0x40; /* TYPEFLAG_FDUAL */
02055 
02056     if(type_iface_get_inherit(interface))
02057         add_impl_type(msft_typeinfo, type_iface_get_inherit(interface),
02058                       ref_importinfo);
02059 
02060     /* count the number of inherited interfaces and non-local functions */
02061     for(ref = inherit; ref; ref = type_iface_get_inherit(ref)) {
02062         num_parents++;
02063         STATEMENTS_FOR_EACH_FUNC( stmt_func, type_iface_get_stmts(ref) ) {
02064             var_t *func = stmt_func->u.var;
02065             if (!is_local(func->attrs)) num_funcs++;
02066         }
02067     }
02068     msft_typeinfo->typeinfo->datatype2 = num_funcs << 16 | num_parents;
02069     msft_typeinfo->typeinfo->cbSizeVft = num_funcs * pointer_size;
02070 
02071     STATEMENTS_FOR_EACH_FUNC( stmt_func, type_iface_get_stmts(interface) ) {
02072         var_t *func = stmt_func->u.var;
02073         if(add_func_desc(msft_typeinfo, func, idx) == S_OK)
02074             idx++;
02075     }
02076 }
02077 
02078 static void add_structure_typeinfo(msft_typelib_t *typelib, type_t *structure)
02079 {
02080     int idx = 0;
02081     var_t *cur;
02082     msft_typeinfo_t *msft_typeinfo;
02083 
02084     if (-1 < structure->typelib_idx)
02085         return;
02086 
02087     structure->typelib_idx = typelib->typelib_header.nrtypeinfos;
02088     msft_typeinfo = create_msft_typeinfo(typelib, TKIND_RECORD, structure->name, structure->attrs);
02089     msft_typeinfo->typeinfo->size = 0;
02090 
02091     if (type_struct_get_fields(structure))
02092         LIST_FOR_EACH_ENTRY( cur, type_struct_get_fields(structure), var_t, entry )
02093             add_var_desc(msft_typeinfo, idx++, cur);
02094 }
02095 
02096 static void add_enum_typeinfo(msft_typelib_t *typelib, type_t *enumeration)
02097 {
02098     int idx = 0;
02099     var_t *cur;
02100     msft_typeinfo_t *msft_typeinfo;
02101 
02102     enumeration->typelib_idx = typelib->typelib_header.nrtypeinfos;
02103     msft_typeinfo = create_msft_typeinfo(typelib, TKIND_ENUM, enumeration->name, enumeration->attrs);
02104     msft_typeinfo->typeinfo->size = 0;
02105 
02106     if (type_enum_get_values(enumeration))
02107         LIST_FOR_EACH_ENTRY( cur, type_enum_get_values(enumeration), var_t, entry )
02108             add_var_desc(msft_typeinfo, idx++, cur);
02109 }
02110 
02111 static void add_typedef_typeinfo(msft_typelib_t *typelib, type_t *tdef)
02112 {
02113     msft_typeinfo_t *msft_typeinfo;
02114     int alignment;
02115 
02116     if (-1 < tdef->typelib_idx)
02117         return;
02118 
02119     tdef->typelib_idx = typelib->typelib_header.nrtypeinfos;
02120     msft_typeinfo = create_msft_typeinfo(typelib, TKIND_ALIAS, tdef->name, tdef->attrs);
02121     encode_type(typelib, get_type_vt(type_alias_get_aliasee(tdef)),
02122                 type_alias_get_aliasee(tdef),
02123                 &msft_typeinfo->typeinfo->datatype1,
02124                 &msft_typeinfo->typeinfo->size,
02125                 &alignment, &msft_typeinfo->typeinfo->datatype2);
02126     msft_typeinfo->typeinfo->typekind |= (alignment << 11 | alignment << 6);
02127 }
02128 
02129 static void add_coclass_typeinfo(msft_typelib_t *typelib, type_t *cls)
02130 {
02131     msft_typeinfo_t *msft_typeinfo;
02132     ifref_t *iref;
02133     int num_ifaces = 0, offset, i;
02134     MSFT_RefRecord *ref, *first = NULL, *first_source = NULL;
02135     int have_default = 0, have_default_source = 0;
02136     const attr_t *attr;
02137     ifref_list_t *ifaces;
02138 
02139     if (-1 < cls->typelib_idx)
02140         return;
02141 
02142     cls->typelib_idx = typelib->typelib_header.nrtypeinfos;
02143     msft_typeinfo = create_msft_typeinfo(typelib, TKIND_COCLASS, cls->name, cls->attrs);
02144 
02145     ifaces = type_coclass_get_ifaces(cls);
02146     if (ifaces) LIST_FOR_EACH_ENTRY( iref, ifaces, ifref_t, entry ) num_ifaces++;
02147 
02148     offset = msft_typeinfo->typeinfo->datatype1 = ctl2_alloc_segment(typelib, MSFT_SEG_REFERENCES,
02149                                                                      num_ifaces * sizeof(*ref), 0);
02150 
02151     i = 0;
02152     if (ifaces) LIST_FOR_EACH_ENTRY( iref, ifaces, ifref_t, entry ) {
02153         if(iref->iface->typelib_idx == -1)
02154             add_interface_typeinfo(typelib, iref->iface);
02155         ref = (MSFT_RefRecord*) (typelib->typelib_segment_data[MSFT_SEG_REFERENCES] + offset + i * sizeof(*ref));
02156         ref->reftype = typelib->typelib_typeinfo_offsets[iref->iface->typelib_idx];
02157         ref->flags = 0;
02158         ref->oCustData = -1;
02159         ref->onext = -1;
02160         if(i < num_ifaces - 1)
02161             ref->onext = offset + (i + 1) * sizeof(*ref);
02162 
02163         if (iref->attrs) LIST_FOR_EACH_ENTRY( attr, iref->attrs, const attr_t, entry ) {
02164             switch(attr->type) {
02165             case ATTR_DEFAULT:
02166                 ref->flags |= 0x1; /* IMPLTYPEFLAG_FDEFAULT */
02167                 break;
02168             case ATTR_DEFAULTVTABLE:
02169                 ref->flags |= 0x8; /* IMPLTYPEFLAG_FDEFAULTVTABLE */
02170                 break;
02171             case ATTR_RESTRICTED:
02172                 ref->flags |= 0x4; /* IMPLTYPEFLAG_FRESTRICTED */
02173                 break;
02174             case ATTR_SOURCE:
02175                 ref->flags |= 0x2; /* IMPLTYPEFLAG_FSOURCE */
02176                 break;
02177             default:
02178                 warning("add_coclass_typeinfo: unhandled attr %d\n", attr->type);
02179             }
02180         }
02181         if(ref->flags & 0x1) { /* IMPLTYPEFLAG_FDEFAULT */
02182             if(ref->flags & 0x2) /* IMPLTYPEFLAG_SOURCE */
02183                 have_default_source = 1;
02184             else
02185                 have_default = 1;
02186         }
02187 
02188         /* If the interface is non-restricted and we haven't already had one then
02189            remember it so that we can use it as a default later */
02190         if((ref->flags & 0x4) == 0) { /* IMPLTYPEFLAG_FRESTRICTED */
02191             if(ref->flags & 0x2) { /* IMPLTYPEFLAG_FSOURCE */
02192                 if(!first_source)
02193                     first_source = ref;
02194             }
02195             else if(!first)
02196                 first = ref;
02197         }
02198         i++;
02199     }
02200 
02201     /* If we haven't had a default interface, then set the default flags on the
02202        first ones */
02203     if(!have_default && first)
02204         first->flags |= 0x1;
02205     if(!have_default_source && first_source)
02206         first_source->flags |= 0x1;
02207 
02208     msft_typeinfo->typeinfo->cImplTypes = num_ifaces;
02209     msft_typeinfo->typeinfo->size = 4;
02210     msft_typeinfo->typeinfo->typekind |= 0x2200;
02211 }
02212 
02213 static void add_module_typeinfo(msft_typelib_t *typelib, type_t *module)
02214 {
02215     int idx = 0;
02216     const statement_t *stmt;
02217     msft_typeinfo_t *msft_typeinfo;
02218 
02219     if (-1 < module->typelib_idx)
02220         return;
02221 
02222     module->typelib_idx = typelib->typelib_header.nrtypeinfos;
02223     msft_typeinfo = create_msft_typeinfo(typelib, TKIND_MODULE, module->name, module->attrs);
02224     msft_typeinfo->typeinfo->typekind |= 0x0a00;
02225 
02226     STATEMENTS_FOR_EACH_FUNC( stmt, module->details.module->stmts ) {
02227         var_t *func = stmt->u.var;
02228         if(add_func_desc(msft_typeinfo, func, idx) == S_OK)
02229             idx++;
02230     }
02231 
02232     msft_typeinfo->typeinfo->size = idx;
02233 }
02234 
02235 static void add_type_typeinfo(msft_typelib_t *typelib, type_t *type)
02236 {
02237     switch (type_get_type(type)) {
02238     case TYPE_INTERFACE:
02239         add_interface_typeinfo(typelib, type);
02240         break;
02241     case TYPE_STRUCT:
02242         add_structure_typeinfo(typelib, type);
02243         break;
02244     case TYPE_ENUM:
02245         add_enum_typeinfo(typelib, type);
02246         break;
02247     case TYPE_COCLASS:
02248         add_coclass_typeinfo(typelib, type);
02249         break;
02250     case TYPE_BASIC:
02251     case TYPE_POINTER:
02252         break;
02253     default:
02254         error("add_entry: unhandled type 0x%x for %s\n",
02255               type_get_type(type), type->name);
02256         break;
02257     }
02258 }
02259 
02260 static void add_entry(msft_typelib_t *typelib, const statement_t *stmt)
02261 {
02262     switch(stmt->type) {
02263     case STMT_LIBRARY:
02264     case STMT_IMPORT:
02265     case STMT_CPPQUOTE:
02266     case STMT_DECLARATION:
02267         /* not included in typelib */
02268         break;
02269     case STMT_IMPORTLIB:
02270         /* not processed here */
02271         break;
02272     case STMT_TYPEDEF:
02273     {
02274         const type_list_t *type_entry = stmt->u.type_list;
02275         for (; type_entry; type_entry = type_entry->next) {
02276             /* if the type is public then add the typedef, otherwise attempt
02277              * to add the aliased type */
02278             if (is_attr(type_entry->type->attrs, ATTR_PUBLIC))
02279                 add_typedef_typeinfo(typelib, type_entry->type);
02280             else
02281                 add_type_typeinfo(typelib, type_alias_get_aliasee(type_entry->type));
02282         }
02283         break;
02284     }
02285     case STMT_MODULE:
02286         add_module_typeinfo(typelib, stmt->u.type);
02287         break;
02288     case STMT_TYPE:
02289     case STMT_TYPEREF:
02290     {
02291         type_t *type = stmt->u.type;
02292         add_type_typeinfo(typelib, type);
02293         break;
02294     }
02295     }
02296 }
02297 
02298 static void set_name(msft_typelib_t *typelib)
02299 {
02300     int offset;
02301 
02302     offset = ctl2_alloc_name(typelib, typelib->typelib->name);
02303     if (offset == -1) return;
02304     typelib->typelib_header.NameOffset = offset;
02305     return;
02306 }
02307 
02308 static void set_version(msft_typelib_t *typelib)
02309 {
02310     typelib->typelib_header.version = get_attrv( typelib->typelib->attrs, ATTR_VERSION );
02311 }
02312 
02313 static void set_guid(msft_typelib_t *typelib)
02314 {
02315     MSFT_GuidEntry guidentry;
02316     int offset;
02317     void *ptr;
02318     GUID guid = {0,0,0,{0,0,0,0,0,0}};
02319 
02320     guidentry.guid = guid;
02321     guidentry.hreftype = -2;
02322     guidentry.next_hash = -1;
02323 
02324     ptr = get_attrp( typelib->typelib->attrs, ATTR_UUID );
02325     if (ptr) guidentry.guid = *(GUID *)ptr;
02326 
02327     offset = ctl2_alloc_guid(typelib, &guidentry);
02328     typelib->typelib_header.posguid = offset;
02329 
02330     return;
02331 }
02332 
02333 static void set_doc_string(msft_typelib_t *typelib)
02334 {
02335     char *str = get_attrp( typelib->typelib->attrs, ATTR_HELPSTRING );
02336 
02337     if (str)
02338     {
02339         int offset = ctl2_alloc_string(typelib, str);
02340         if (offset != -1) typelib->typelib_header.helpstring = offset;
02341     }
02342 }
02343 
02344 static void set_help_file_name(msft_typelib_t *typelib)
02345 {
02346     char *str = get_attrp( typelib->typelib->attrs, ATTR_HELPFILE );
02347 
02348     if (str)
02349     {
02350         int offset = ctl2_alloc_string(typelib, str);
02351         if (offset != -1)
02352         {
02353             typelib->typelib_header.helpfile = offset;
02354             typelib->typelib_header.varflags |= 0x10;
02355         }
02356     }
02357 }
02358 
02359 static void set_help_context(msft_typelib_t *typelib)
02360 {
02361     const expr_t *expr = get_attrp( typelib->typelib->attrs, ATTR_HELPCONTEXT );
02362     if (expr) typelib->typelib_header.helpcontext = expr->cval;
02363 }
02364 
02365 static void set_help_string_dll(msft_typelib_t *typelib)
02366 {
02367     char *str = get_attrp( typelib->typelib->attrs, ATTR_HELPSTRINGDLL );
02368 
02369     if (str)
02370     {
02371         int offset = ctl2_alloc_string(typelib, str);
02372         if (offset != -1)
02373         {
02374             typelib->help_string_dll_offset = offset;
02375             typelib->typelib_header.varflags |= 0x100;
02376         }
02377     }
02378 }
02379 
02380 static void set_help_string_context(msft_typelib_t *typelib)
02381 {
02382     const expr_t *expr = get_attrp( typelib->typelib->attrs, ATTR_HELPSTRINGCONTEXT );
02383     if (expr) typelib->typelib_header.helpstringcontext = expr->cval;
02384 }
02385 
02386 static void set_lcid(msft_typelib_t *typelib)
02387 {
02388     const expr_t *lcid_expr = get_attrp( typelib->typelib->attrs, ATTR_LIBLCID );
02389     if(lcid_expr)
02390     {
02391         typelib->typelib_header.lcid  = lcid_expr->cval;
02392         typelib->typelib_header.lcid2 = lcid_expr->cval;
02393     }
02394 }
02395 
02396 static void set_lib_flags(msft_typelib_t *typelib)
02397 {
02398     const attr_t *attr;
02399 
02400     typelib->typelib_header.flags = 0;
02401     if (!typelib->typelib->attrs) return;
02402     LIST_FOR_EACH_ENTRY( attr, typelib->typelib->attrs, const attr_t, entry )
02403     {
02404         switch(attr->type) {
02405         case ATTR_CONTROL:
02406             typelib->typelib_header.flags |= 0x02; /* LIBFLAG_FCONTROL */
02407             break;
02408         case ATTR_HIDDEN:
02409             typelib->typelib_header.flags |= 0x04; /* LIBFLAG_FHIDDEN */
02410             break;
02411         case ATTR_RESTRICTED:
02412             typelib->typelib_header.flags |= 0x01; /* LIBFLAG_FRESTRICTED */
02413             break;
02414         default:
02415             break;
02416         }
02417     }
02418     return;
02419 }
02420 
02421 static void ctl2_write_segment(msft_typelib_t *typelib, int segment)
02422 {
02423     put_data(typelib->typelib_segment_data[segment], typelib->typelib_segdir[segment].length);
02424 }
02425 
02426 static void ctl2_finalize_typeinfos(msft_typelib_t *typelib, int filesize)
02427 {
02428     msft_typeinfo_t *typeinfo;
02429 
02430     for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
02431     typeinfo->typeinfo->memoffset = filesize;
02432     if (typeinfo->func_data)
02433         filesize += typeinfo->func_data[0] + ((typeinfo->typeinfo->cElement & 0xffff) * 12);
02434     if (typeinfo->var_data)
02435         filesize += typeinfo->var_data[0] + (((typeinfo->typeinfo->cElement >> 16) & 0xffff) * 12);
02436         if (typeinfo->func_data || typeinfo->var_data)
02437             filesize += 4;
02438     }
02439 }
02440 
02441 static int ctl2_finalize_segment(msft_typelib_t *typelib, int filepos, int segment)
02442 {
02443     if (typelib->typelib_segdir[segment].length) {
02444     typelib->typelib_segdir[segment].offset = filepos;
02445     } else {
02446     typelib->typelib_segdir[segment].offset = -1;
02447     }
02448 
02449     return typelib->typelib_segdir[segment].length;
02450 }
02451 
02452 
02453 static void ctl2_write_typeinfos(msft_typelib_t *typelib)
02454 {
02455     msft_typeinfo_t *typeinfo;
02456     int typedata_size;
02457 
02458     for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
02459         if (!typeinfo->func_data && !typeinfo->var_data) continue;
02460         typedata_size = 0;
02461     if (typeinfo->func_data)
02462             typedata_size = typeinfo->func_data[0];
02463     if (typeinfo->var_data)
02464             typedata_size += typeinfo->var_data[0];
02465     put_data(&typedata_size, sizeof(int));
02466         if (typeinfo->func_data)
02467             put_data(typeinfo->func_data + 1, typeinfo->func_data[0]);
02468         if (typeinfo->var_data)
02469             put_data(typeinfo->var_data + 1, typeinfo->var_data[0]);
02470         if (typeinfo->func_indices)
02471             put_data(typeinfo->func_indices, (typeinfo->typeinfo->cElement & 0xffff) * 4);
02472         if (typeinfo->var_indices)
02473             put_data(typeinfo->var_indices, (typeinfo->typeinfo->cElement >> 16) * 4);
02474         if (typeinfo->func_names)
02475             put_data(typeinfo->func_names,   (typeinfo->typeinfo->cElement & 0xffff) * 4);
02476         if (typeinfo->var_names)
02477             put_data(typeinfo->var_names,   (typeinfo->typeinfo->cElement >> 16) * 4);
02478         if (typeinfo->func_offsets)
02479             put_data(typeinfo->func_offsets, (typeinfo->typeinfo->cElement & 0xffff) * 4);
02480         if (typeinfo->var_offsets) {
02481             int add = 0, i, offset;
02482             if(typeinfo->func_data)
02483                 add = typeinfo->func_data[0];
02484             for(i = 0; i < (typeinfo->typeinfo->cElement >> 16); i++) {
02485                 offset = typeinfo->var_offsets[i];
02486                 offset += add;
02487                 put_data(&offset, 4);
02488             }
02489         }
02490     }
02491 }
02492 
02493 static void save_all_changes(msft_typelib_t *typelib)
02494 {
02495     int filepos;
02496 
02497     chat("save_all_changes(%p)\n", typelib);
02498 
02499     filepos = sizeof(MSFT_Header) + sizeof(MSFT_SegDir);
02500     if(typelib->typelib_header.varflags & 0x100) filepos += 4; /* helpstringdll */
02501     filepos += typelib->typelib_header.nrtypeinfos * 4;
02502 
02503     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_TYPEINFO);
02504     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_GUIDHASH);
02505     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_GUID);
02506     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_REFERENCES);
02507     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_IMPORTINFO);
02508     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_IMPORTFILES);
02509     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_NAMEHASH);
02510     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_NAME);
02511     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_STRING);
02512     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_TYPEDESC);
02513     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_ARRAYDESC);
02514     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_CUSTDATA);
02515     filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_CUSTDATAGUID);
02516 
02517     ctl2_finalize_typeinfos(typelib, filepos);
02518 
02519     byte_swapped = 0;
02520     init_output_buffer();
02521 
02522     put_data(&typelib->typelib_header, sizeof(typelib->typelib_header));
02523     if(typelib->typelib_header.varflags & 0x100)
02524         put_data(&typelib->help_string_dll_offset, sizeof(typelib->help_string_dll_offset));
02525 
02526     put_data(typelib->typelib_typeinfo_offsets, typelib->typelib_header.nrtypeinfos * 4);
02527     put_data(&typelib->typelib_segdir, sizeof(typelib->typelib_segdir));
02528     ctl2_write_segment( typelib, MSFT_SEG_TYPEINFO );
02529     ctl2_write_segment( typelib, MSFT_SEG_GUIDHASH );
02530     ctl2_write_segment( typelib, MSFT_SEG_GUID );
02531     ctl2_write_segment( typelib, MSFT_SEG_REFERENCES );
02532     ctl2_write_segment( typelib, MSFT_SEG_IMPORTINFO );
02533     ctl2_write_segment( typelib, MSFT_SEG_IMPORTFILES );
02534     ctl2_write_segment( typelib, MSFT_SEG_NAMEHASH );
02535     ctl2_write_segment( typelib, MSFT_SEG_NAME );
02536     ctl2_write_segment( typelib, MSFT_SEG_STRING );
02537     ctl2_write_segment( typelib, MSFT_SEG_TYPEDESC );
02538     ctl2_write_segment( typelib, MSFT_SEG_ARRAYDESC );
02539     ctl2_write_segment( typelib, MSFT_SEG_CUSTDATA );
02540     ctl2_write_segment( typelib, MSFT_SEG_CUSTDATAGUID );
02541 
02542     ctl2_write_typeinfos(typelib);
02543 
02544     if (strendswith( typelib_name, ".res" ))  /* create a binary resource file */
02545     {
02546         add_output_to_resources( "TYPELIB", "#1" );
02547         output_typelib_regscript( typelib->typelib );
02548         flush_output_resources( typelib_name );
02549     }
02550     else flush_output_buffer( typelib_name );
02551 }
02552 
02553 int create_msft_typelib(typelib_t *typelib)
02554 {
02555     msft_typelib_t *msft;
02556     int failed = 0;
02557     const statement_t *stmt;
02558     time_t cur_time;
02559     char *time_override;
02560     unsigned int version = 5 << 24 | 1 << 16 | 164; /* 5.01.0164 */
02561     GUID midl_time_guid    = {0xde77ba63,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}}; 
02562     GUID midl_version_guid = {0xde77ba64,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}}; 
02563 
02564     pointer_size = (typelib_kind == SYS_WIN64) ? 8 : 4;
02565 
02566     msft = xmalloc(sizeof(*msft));
02567     memset(msft, 0, sizeof(*msft));
02568     msft->typelib = typelib;
02569 
02570     ctl2_init_header(msft);
02571     ctl2_init_segdir(msft);
02572 
02573     msft->typelib_header.varflags |= typelib_kind;
02574 
02575     /*
02576      * The following two calls return an offset or -1 if out of memory. We
02577      * specifically need an offset of 0, however, so...
02578      */
02579     if (ctl2_alloc_segment(msft, MSFT_SEG_GUIDHASH, 0x80, 0x80)) { failed = 1; }
02580     if (ctl2_alloc_segment(msft, MSFT_SEG_NAMEHASH, 0x200, 0x200)) { failed = 1; }
02581 
02582     if(failed)
02583     {
02584         free(msft);
02585         return 0;
02586     }
02587 
02588     msft->typelib_guidhash_segment = (int *)msft->typelib_segment_data[MSFT_SEG_GUIDHASH];
02589     msft->typelib_namehash_segment = (int *)msft->typelib_segment_data[MSFT_SEG_NAMEHASH];
02590 
02591     memset(msft->typelib_guidhash_segment, 0xff, 0x80);
02592     memset(msft->typelib_namehash_segment, 0xff, 0x200);
02593 
02594     set_lib_flags(msft);
02595     set_lcid(msft);
02596     set_help_file_name(msft);
02597     set_doc_string(msft);
02598     set_guid(msft);
02599     set_version(msft);
02600     set_name(msft);
02601     set_help_context(msft);
02602     set_help_string_dll(msft);
02603     set_help_string_context(msft);
02604     
02605     /* midl adds two sets of custom data to the library: the current unix time
02606        and midl's version number */
02607     time_override = getenv( "WIDL_TIME_OVERRIDE");
02608     cur_time = time_override ? atol( time_override) : time(NULL);
02609     set_custdata(msft, &midl_time_guid, VT_UI4, cur_time, &msft->typelib_header.CustomDataOffset);
02610     set_custdata(msft, &midl_version_guid, VT_UI4, version, &msft->typelib_header.CustomDataOffset);
02611 
02612     if (typelib->stmts)
02613         LIST_FOR_EACH_ENTRY( stmt, typelib->stmts, const statement_t, entry )
02614             add_entry(msft, stmt);
02615 
02616     save_all_changes(msft);
02617     free(msft);
02618     return 1;
02619 }

Generated on Sat May 26 2012 04:36:55 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.