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

Wine Cross Reference
wine/dlls/oleaut32/typelib2.c

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

  1 /*
  2  *      TYPELIB2
  3  *
  4  *      Copyright 2004  Alastair Bridgewater
  5  *
  6  * This library is free software; you can redistribute it and/or
  7  * modify it under the terms of the GNU Lesser General Public
  8  * License as published by the Free Software Foundation; either
  9  * version 2.1 of the License, or (at your option) any later version.
 10  *
 11  * This library is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14  * Lesser General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU Lesser General Public
 17  * License along with this library; if not, write to the Free Software
 18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 19  *
 20  * --------------------------------------------------------------------------------------
 21  *  Known problems:
 22  *
 23  *    Badly incomplete.
 24  *
 25  *    Only works on little-endian systems.
 26  *
 27  */
 28 
 29 #include "config.h"
 30 #include "wine/port.h"
 31 
 32 #include <stdlib.h>
 33 #include <string.h>
 34 #include <stdarg.h>
 35 #include <stdio.h>
 36 #include <ctype.h>
 37 
 38 #define COBJMACROS
 39 #define NONAMELESSUNION
 40 #define NONAMELESSSTRUCT
 41 
 42 #include "winerror.h"
 43 #include "windef.h"
 44 #include "winbase.h"
 45 #include "winnls.h"
 46 #include "winuser.h"
 47 
 48 #include "wine/unicode.h"
 49 #include "objbase.h"
 50 #include "typelib.h"
 51 #include "wine/debug.h"
 52 
 53 WINE_DEFAULT_DEBUG_CHANNEL(typelib2);
 54 /* WINE_DEFAULT_DEBUG_CHANNEL(ole); */
 55 
 56 
 57 /******************************************************************************
 58  * ICreateTypeLib2 {OLEAUT32}
 59  *
 60  * NOTES
 61  *  The ICreateTypeLib2 interface provides an interface whereby one may create
 62  *  new type library (.tlb) files.
 63  *
 64  *  This interface inherits from ICreateTypeLib, and can be freely cast back
 65  *  and forth between an ICreateTypeLib and an ICreateTypeLib2 on local clients.
 66  *  This dispensation applies only to ICreateTypeLib objects obtained on MSFT
 67  *  format type libraries (those made through CreateTypeLib2).
 68  *
 69  * METHODS
 70  */
 71 
 72 /******************************************************************************
 73  * ICreateTypeInfo2 {OLEAUT32}
 74  *
 75  * NOTES
 76  *  The ICreateTypeInfo2 interface provides an interface whereby one may add
 77  *  type information to type library (.tlb) files.
 78  *
 79  *  This interface inherits from ICreateTypeInfo, and can be freely cast back
 80  *  and forth between an ICreateTypeInfo and an ICreateTypeInfo2 on local clients.
 81  *  This dispensation applies only to ICreateTypeInfo objects obtained on MSFT
 82  *  format type libraries (those made through CreateTypeLib2).
 83  *
 84  * METHODS
 85  */
 86 
 87 /******************************************************************************
 88  * ITypeLib2 {OLEAUT32}
 89  *
 90  * NOTES
 91  *  The ITypeLib2 interface provides an interface whereby one may query MSFT
 92  *  format type library (.tlb) files.
 93  *
 94  *  This interface inherits from ITypeLib, and can be freely cast back and
 95  *  forth between an ITypeLib and an ITypeLib2 on local clients. This
 96  *  dispensation applies only to ITypeLib objects obtained on MSFT format type
 97  *  libraries (those made through CreateTypeLib2).
 98  *
 99  * METHODS
100  */
101 
102 /******************************************************************************
103  * ITypeInfo2 {OLEAUT32}
104  *
105  * NOTES
106  *  The ITypeInfo2 interface provides an interface whereby one may query type
107  *  information stored in MSFT format type library (.tlb) files.
108  *
109  *  This interface inherits from ITypeInfo, and can be freely cast back and
110  *  forth between an ITypeInfo and an ITypeInfo2 on local clients. This
111  *  dispensation applies only to ITypeInfo objects obtained on MSFT format type
112  *  libraries (those made through CreateTypeLib2).
113  *
114  * METHODS
115  */
116 
117 /*================== Implementation Structures ===================================*/
118 
119 enum MSFT_segment_index {
120     MSFT_SEG_TYPEINFO = 0,  /* type information */
121     MSFT_SEG_IMPORTINFO,    /* import information */
122     MSFT_SEG_IMPORTFILES,   /* import filenames */
123     MSFT_SEG_REFERENCES,    /* references (?) */
124     MSFT_SEG_GUIDHASH,      /* hash table for guids? */
125     MSFT_SEG_GUID,          /* guid storage */
126     MSFT_SEG_NAMEHASH,      /* hash table for names */
127     MSFT_SEG_NAME,          /* name storage */
128     MSFT_SEG_STRING,        /* string storage */
129     MSFT_SEG_TYPEDESC,      /* type descriptions */
130     MSFT_SEG_ARRAYDESC,     /* array descriptions */
131     MSFT_SEG_CUSTDATA,      /* custom data */
132     MSFT_SEG_CUSTDATAGUID,  /* custom data guids */
133     MSFT_SEG_UNKNOWN,       /* ??? */
134     MSFT_SEG_UNKNOWN2,      /* ??? */
135     MSFT_SEG_MAX            /* total number of segments */
136 };
137 
138 typedef struct tagMSFT_ImpFile {
139     int guid;
140     LCID lcid;
141     int version;
142     char filename[0]; /* preceded by two bytes of encoded (length << 2) + flags in the low two bits. */
143 } MSFT_ImpFile;
144 
145 typedef struct tagICreateTypeLib2Impl
146 {
147     const ICreateTypeLib2Vtbl *lpVtbl;
148     const ITypeLib2Vtbl       *lpVtblTypeLib2;
149 
150     LONG ref;
151 
152     WCHAR *filename;
153 
154     MSFT_Header typelib_header;
155     INT helpStringDll;
156     MSFT_pSeg typelib_segdir[MSFT_SEG_MAX];
157     char *typelib_segment_data[MSFT_SEG_MAX];
158     int typelib_segment_block_length[MSFT_SEG_MAX];
159 
160     INT typelib_typeinfo_offsets[0x200]; /* Hope that's enough. */
161 
162     INT *typelib_namehash_segment;
163     INT *typelib_guidhash_segment;
164 
165     struct tagICreateTypeInfo2Impl *typeinfos;
166     struct tagICreateTypeInfo2Impl *last_typeinfo;
167 } ICreateTypeLib2Impl;
168 
169 static inline ICreateTypeLib2Impl *impl_from_ITypeLib2( ITypeLib2 *iface )
170 {
171     return (ICreateTypeLib2Impl *)((char*)iface - FIELD_OFFSET(ICreateTypeLib2Impl, lpVtblTypeLib2));
172 }
173 
174 typedef struct tagICreateTypeInfo2Impl
175 {
176     const ICreateTypeInfo2Vtbl *lpVtbl;
177     const ITypeInfo2Vtbl       *lpVtblTypeInfo2;
178 
179     LONG ref;
180 
181     ICreateTypeLib2Impl *typelib;
182     MSFT_TypeInfoBase *typeinfo;
183 
184     INT *typedata;
185     int typedata_allocated;
186     int typedata_length;
187 
188     int indices[42];
189     int names[42];
190     int offsets[42];
191 
192     int datawidth;
193 
194     struct tagICreateTypeInfo2Impl *next_typeinfo;
195 } ICreateTypeInfo2Impl;
196 
197 static inline ICreateTypeInfo2Impl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
198 {
199     return (ICreateTypeInfo2Impl *)((char*)iface - FIELD_OFFSET(ICreateTypeInfo2Impl, lpVtblTypeInfo2));
200 }
201 
202 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface);
203 
204 
205 /*================== Internal functions ===================================*/
206 
207 /****************************************************************************
208  *      ctl2_init_header
209  *
210  *  Initializes the type library header of a new typelib.
211  */
212 static void ctl2_init_header(
213         ICreateTypeLib2Impl *This) /* [I] The typelib to initialize. */
214 {
215     This->typelib_header.magic1 = 0x5446534d;
216     This->typelib_header.magic2 = 0x00010002;
217     This->typelib_header.posguid = -1;
218     This->typelib_header.lcid = This->typelib_header.lcid2 = GetUserDefaultLCID();
219     This->typelib_header.varflags = 0x40;
220     This->typelib_header.version = 0;
221     This->typelib_header.flags = 0;
222     This->typelib_header.nrtypeinfos = 0;
223     This->typelib_header.helpstring = -1;
224     This->typelib_header.helpstringcontext = 0;
225     This->typelib_header.helpcontext = 0;
226     This->typelib_header.nametablecount = 0;
227     This->typelib_header.nametablechars = 0;
228     This->typelib_header.NameOffset = -1;
229     This->typelib_header.helpfile = -1;
230     This->typelib_header.CustomDataOffset = -1;
231     This->typelib_header.res44 = 0x20;
232     This->typelib_header.res48 = 0x80;
233     This->typelib_header.dispatchpos = -1;
234     This->typelib_header.nimpinfos = 0;
235     This->helpStringDll = -1;
236 }
237 
238 /****************************************************************************
239  *      ctl2_init_segdir
240  *
241  *  Initializes the segment directory of a new typelib.
242  */
243 static void ctl2_init_segdir(
244         ICreateTypeLib2Impl *This) /* [I] The typelib to initialize. */
245 {
246     int i;
247     MSFT_pSeg *segdir;
248 
249     segdir = &This->typelib_segdir[MSFT_SEG_TYPEINFO];
250 
251     for (i = 0; i < 15; i++) {
252         segdir[i].offset = -1;
253         segdir[i].length = 0;
254         segdir[i].res08 = -1;
255         segdir[i].res0c = 0x0f;
256     }
257 }
258 
259 /****************************************************************************
260  *      ctl2_hash_guid
261  *
262  *  Generates a hash key from a GUID.
263  *
264  * RETURNS
265  *
266  *  The hash key for the GUID.
267  */
268 static int ctl2_hash_guid(
269         REFGUID guid)                /* [I] The guid to find. */
270 {
271     int hash;
272     int i;
273 
274     hash = 0;
275     for (i = 0; i < 8; i ++) {
276         hash ^= ((const short *)guid)[i];
277     }
278 
279     return hash & 0x1f;
280 }
281 
282 /****************************************************************************
283  *      ctl2_find_guid
284  *
285  *  Locates a guid in a type library.
286  *
287  * RETURNS
288  *
289  *  The offset into the GUID segment of the guid, or -1 if not found.
290  */
291 static int ctl2_find_guid(
292         ICreateTypeLib2Impl *This, /* [I] The typelib to operate against. */
293         int hash_key,              /* [I] The hash key for the guid. */
294         REFGUID guid)                /* [I] The guid to find. */
295 {
296     int offset;
297     MSFT_GuidEntry *guidentry;
298 
299     offset = This->typelib_guidhash_segment[hash_key];
300     while (offset != -1) {
301         guidentry = (MSFT_GuidEntry *)&This->typelib_segment_data[MSFT_SEG_GUID][offset];
302 
303         if (!memcmp(guidentry, guid, sizeof(GUID))) return offset;
304 
305         offset = guidentry->next_hash;
306     }
307 
308     return offset;
309 }
310 
311 /****************************************************************************
312  *      ctl2_find_name
313  *
314  *  Locates a name in a type library.
315  *
316  * RETURNS
317  *
318  *  The offset into the NAME segment of the name, or -1 if not found.
319  *
320  * NOTES
321  *
322  *  The name must be encoded as with ctl2_encode_name().
323  */
324 static int ctl2_find_name(
325         ICreateTypeLib2Impl *This, /* [I] The typelib to operate against. */
326         const char *name)          /* [I] The encoded name to find. */
327 {
328     int offset;
329     int *namestruct;
330 
331     offset = This->typelib_namehash_segment[name[2] & 0x7f];
332     while (offset != -1) {
333         namestruct = (int *)&This->typelib_segment_data[MSFT_SEG_NAME][offset];
334 
335         if (!((namestruct[2] ^ *((const int *)name)) & 0xffff00ff)) {
336             /* hash codes and lengths match, final test */
337             if (!strncasecmp(name+4, (void *)(namestruct+3), name[0])) break;
338         }
339 
340         /* move to next item in hash bucket */
341         offset = namestruct[1];
342     }
343 
344     return offset;
345 }
346 
347 /****************************************************************************
348  *      ctl2_encode_name
349  *
350  *  Encodes a name string to a form suitable for storing into a type library
351  *  or comparing to a name stored in a type library.
352  *
353  * RETURNS
354  *
355  *  The length of the encoded name, including padding and length+hash fields.
356  *
357  * NOTES
358  *
359  *  Will throw an exception if name or result are NULL. Is not multithread
360  *  safe in the slightest.
361  */
362 static int ctl2_encode_name(
363         ICreateTypeLib2Impl *This, /* [I] The typelib to operate against (used for LCID only). */
364         const WCHAR *name,         /* [I] The name string to encode. */
365         char **result)             /* [O] A pointer to a pointer to receive the encoded name. */
366 {
367     int length;
368     static char converted_name[0x104];
369     int offset;
370     int value;
371 
372     length = WideCharToMultiByte(CP_ACP, 0, name, strlenW(name), converted_name+4, 0x100, NULL, NULL);
373     converted_name[0] = length & 0xff;
374 
375     converted_name[length + 4] = 0;
376 
377     converted_name[1] = 0x00;
378 
379     value = LHashValOfNameSysA(This->typelib_header.varflags & 0x0f, This->typelib_header.lcid, converted_name + 4);
380 
381     converted_name[2] = value;
382     converted_name[3] = value >> 8;
383 
384     for (offset = (4 - length) & 3; offset; offset--) converted_name[length + offset + 3] = 0x57;
385 
386     *result = converted_name;
387 
388     return (length + 7) & ~3;
389 }
390 
391 /****************************************************************************
392  *      ctl2_encode_string
393  *
394  *  Encodes a string to a form suitable for storing into a type library or
395  *  comparing to a string stored in a type library.
396  *
397  * RETURNS
398  *
399  *  The length of the encoded string, including padding and length fields.
400  *
401  * NOTES
402  *
403  *  Will throw an exception if string or result are NULL. Is not multithread
404  *  safe in the slightest.
405  */
406 static int ctl2_encode_string(
407         ICreateTypeLib2Impl *This, /* [I] The typelib to operate against (not used?). */
408         const WCHAR *string,       /* [I] The string to encode. */
409         char **result)             /* [O] A pointer to a pointer to receive the encoded string. */
410 {
411     int length;
412     static char converted_string[0x104];
413     int offset;
414 
415     length = WideCharToMultiByte(CP_ACP, 0, string, strlenW(string), converted_string+2, 0x102, NULL, NULL);
416     converted_string[0] = length & 0xff;
417     converted_string[1] = (length >> 8) & 0xff;
418 
419     for (offset = (4 - (length + 2)) & 3; offset; offset--) converted_string[length + offset + 1] = 0x57;
420 
421     *result = converted_string;
422 
423     return (length + 5) & ~3;
424 }
425 
426 /****************************************************************************
427  *      ctl2_alloc_segment
428  *
429  *  Allocates memory from a segment in a type library.
430  *
431  * RETURNS
432  *
433  *  Success: The offset within the segment of the new data area.
434  *  Failure: -1 (this is invariably an out of memory condition).
435  *
436  * BUGS
437  *
438  *  Does not (yet) handle the case where the allocated segment memory needs to grow.
439  */
440 static int ctl2_alloc_segment(
441         ICreateTypeLib2Impl *This,       /* [I] The type library in which to allocate. */
442         enum MSFT_segment_index segment, /* [I] The segment in which to allocate. */
443         int size,                        /* [I] The amount to allocate. */
444         int block_size)                  /* [I] Initial allocation block size, or 0 for default. */
445 {
446     int offset;
447 
448     if(!This->typelib_segment_data[segment]) {
449         if (!block_size) block_size = 0x2000;
450 
451         This->typelib_segment_block_length[segment] = block_size;
452         This->typelib_segment_data[segment] = HeapAlloc(GetProcessHeap(), 0, block_size);
453         if (!This->typelib_segment_data[segment]) return -1;
454         memset(This->typelib_segment_data[segment], 0x57, block_size);
455     }
456 
457     while ((This->typelib_segdir[segment].length + size) > This->typelib_segment_block_length[segment]) {
458         char *block;
459 
460         block_size = This->typelib_segment_block_length[segment];
461         block = HeapReAlloc(GetProcessHeap(), 0, This->typelib_segment_data[segment], block_size << 1);
462         if (!block) return -1;
463 
464         if (segment == MSFT_SEG_TYPEINFO) {
465             /* TypeInfos have a direct pointer to their memory space, so we have to fix them up. */
466             ICreateTypeInfo2Impl *typeinfo;
467 
468             for (typeinfo = This->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
469                 typeinfo->typeinfo = (void *)&block[((char *)typeinfo->typeinfo) - This->typelib_segment_data[segment]];
470             }
471         }
472 
473         memset(block + block_size, 0x57, block_size);
474         This->typelib_segment_block_length[segment] = block_size << 1;
475         This->typelib_segment_data[segment] = block;
476     }
477 
478     offset = This->typelib_segdir[segment].length;
479     This->typelib_segdir[segment].length += size;
480 
481     return offset;
482 }
483 
484 /****************************************************************************
485  *      ctl2_alloc_typeinfo
486  *
487  *  Allocates and initializes a typeinfo structure in a type library.
488  *
489  * RETURNS
490  *
491  *  Success: The offset of the new typeinfo.
492  *  Failure: -1 (this is invariably an out of memory condition).
493  */
494 static int ctl2_alloc_typeinfo(
495         ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
496         int nameoffset)            /* [I] The offset of the name for this typeinfo. */
497 {
498     int offset;
499     MSFT_TypeInfoBase *typeinfo;
500 
501     offset = ctl2_alloc_segment(This, MSFT_SEG_TYPEINFO, sizeof(MSFT_TypeInfoBase), 0);
502     if (offset == -1) return -1;
503 
504     This->typelib_typeinfo_offsets[This->typelib_header.nrtypeinfos++] = offset;
505 
506     typeinfo = (void *)(This->typelib_segment_data[MSFT_SEG_TYPEINFO] + offset);
507 
508     typeinfo->typekind = (This->typelib_header.nrtypeinfos - 1) << 16;
509     typeinfo->memoffset = -1; /* should be EOF if no elements */
510     typeinfo->res2 = 0;
511     typeinfo->res3 = -1;
512     typeinfo->res4 = 3;
513     typeinfo->res5 = 0;
514     typeinfo->cElement = 0;
515     typeinfo->res7 = 0;
516     typeinfo->res8 = 0;
517     typeinfo->res9 = 0;
518     typeinfo->resA = 0;
519     typeinfo->posguid = -1;
520     typeinfo->flags = 0;
521     typeinfo->NameOffset = nameoffset;
522     typeinfo->version = 0;
523     typeinfo->docstringoffs = -1;
524     typeinfo->helpstringcontext = 0;
525     typeinfo->helpcontext = 0;
526     typeinfo->oCustData = -1;
527     typeinfo->cbSizeVft = 0;
528     typeinfo->cImplTypes = 0;
529     typeinfo->size = 0;
530     typeinfo->datatype1 = -1;
531     typeinfo->datatype2 = 0;
532     typeinfo->res18 = 0;
533     typeinfo->res19 = -1;
534 
535     return offset;
536 }
537 
538 /****************************************************************************
539  *      ctl2_alloc_guid
540  *
541  *  Allocates and initializes a GUID structure in a type library. Also updates
542  *  the GUID hash table as needed.
543  *
544  * RETURNS
545  *
546  *  Success: The offset of the new GUID.
547  *  Failure: -1 (this is invariably an out of memory condition).
548  */
549 static int ctl2_alloc_guid(
550         ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
551         MSFT_GuidEntry *guid)      /* [I] The GUID to store. */
552 {
553     int offset;
554     MSFT_GuidEntry *guid_space;
555     int hash_key;
556 
557     hash_key = ctl2_hash_guid(&guid->guid);
558 
559     offset = ctl2_find_guid(This, hash_key, &guid->guid);
560     if (offset != -1) return offset;
561 
562     offset = ctl2_alloc_segment(This, MSFT_SEG_GUID, sizeof(MSFT_GuidEntry), 0);
563     if (offset == -1) return -1;
564 
565     guid_space = (void *)(This->typelib_segment_data[MSFT_SEG_GUID] + offset);
566     *guid_space = *guid;
567 
568     guid_space->next_hash = This->typelib_guidhash_segment[hash_key];
569     This->typelib_guidhash_segment[hash_key] = offset;
570 
571     return offset;
572 }
573 
574 /****************************************************************************
575  *      ctl2_alloc_name
576  *
577  *  Allocates and initializes a name within a type library. Also updates the
578  *  name hash table as needed.
579  *
580  * RETURNS
581  *
582  *  Success: The offset within the segment of the new name.
583  *  Failure: -1 (this is invariably an out of memory condition).
584  */
585 static int ctl2_alloc_name(
586         ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
587         const WCHAR *name)         /* [I] The name to store. */
588 {
589     int length;
590     int offset;
591     MSFT_NameIntro *name_space;
592     char *encoded_name;
593 
594     length = ctl2_encode_name(This, name, &encoded_name);
595 
596     offset = ctl2_find_name(This, encoded_name);
597     if (offset != -1) return offset;
598 
599     offset = ctl2_alloc_segment(This, MSFT_SEG_NAME, length + 8, 0);
600     if (offset == -1) return -1;
601 
602     name_space = (void *)(This->typelib_segment_data[MSFT_SEG_NAME] + offset);
603     name_space->hreftype = -1;
604     name_space->next_hash = -1;
605     memcpy(&name_space->namelen, encoded_name, length);
606 
607     if (This->typelib_namehash_segment[encoded_name[2] & 0x7f] != -1)
608         name_space->next_hash = This->typelib_namehash_segment[encoded_name[2] & 0x7f];
609 
610     This->typelib_namehash_segment[encoded_name[2] & 0x7f] = offset;
611 
612     This->typelib_header.nametablecount += 1;
613     This->typelib_header.nametablechars += *encoded_name;
614 
615     return offset;
616 }
617 
618 /****************************************************************************
619  *      ctl2_alloc_string
620  *
621  *  Allocates and initializes a string in a type library.
622  *
623  * RETURNS
624  *
625  *  Success: The offset within the segment of the new string.
626  *  Failure: -1 (this is invariably an out of memory condition).
627  */
628 static int ctl2_alloc_string(
629         ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
630         const WCHAR *string)       /* [I] The string to store. */
631 {
632     int length;
633     int offset;
634     char *string_space;
635     char *encoded_string;
636 
637     length = ctl2_encode_string(This, string, &encoded_string);
638 
639     for (offset = 0; offset < This->typelib_segdir[MSFT_SEG_STRING].length;
640          offset += ((((This->typelib_segment_data[MSFT_SEG_STRING][offset + 1] << 8) & 0xff)
641              | (This->typelib_segment_data[MSFT_SEG_STRING][offset + 0] & 0xff)) + 5) & ~3) {
642         if (!memcmp(encoded_string, This->typelib_segment_data[MSFT_SEG_STRING] + offset, length)) return offset;
643     }
644 
645     offset = ctl2_alloc_segment(This, MSFT_SEG_STRING, length, 0);
646     if (offset == -1) return -1;
647 
648     string_space = This->typelib_segment_data[MSFT_SEG_STRING] + offset;
649     memcpy(string_space, encoded_string, length);
650 
651     return offset;
652 }
653 
654 /****************************************************************************
655  *      ctl2_alloc_importinfo
656  *
657  *  Allocates and initializes an import information structure in a type library.
658  *
659  * RETURNS
660  *
661  *  Success: The offset of the new importinfo.
662  *  Failure: -1 (this is invariably an out of memory condition).
663  */
664 static int ctl2_alloc_importinfo(
665         ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
666         MSFT_ImpInfo *impinfo)     /* [I] The import information to store. */
667 {
668     int offset;
669     MSFT_ImpInfo *impinfo_space;
670 
671     for (offset = 0;
672          offset < This->typelib_segdir[MSFT_SEG_IMPORTINFO].length;
673          offset += sizeof(MSFT_ImpInfo)) {
674         if (!memcmp(&(This->typelib_segment_data[MSFT_SEG_IMPORTINFO][offset]),
675                     impinfo, sizeof(MSFT_ImpInfo))) {
676             return offset;
677         }
678     }
679 
680     impinfo->flags |= This->typelib_header.nimpinfos++;
681 
682     offset = ctl2_alloc_segment(This, MSFT_SEG_IMPORTINFO, sizeof(MSFT_ImpInfo), 0);
683     if (offset == -1) return -1;
684 
685     impinfo_space = (void *)(This->typelib_segment_data[MSFT_SEG_IMPORTINFO] + offset);
686     *impinfo_space = *impinfo;
687 
688     return offset;
689 }
690 
691 /****************************************************************************
692  *      ctl2_alloc_importfile
693  *
694  *  Allocates and initializes an import file definition in a type library.
695  *
696  * RETURNS
697  *
698  *  Success: The offset of the new importinfo.
699  *  Failure: -1 (this is invariably an out of memory condition).
700  */
701 static int ctl2_alloc_importfile(
702         ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
703         int guidoffset,            /* [I] The offset to the GUID for the imported library. */
704         int major_version,         /* [I] The major version number of the imported library. */
705         int minor_version,         /* [I] The minor version number of the imported library. */
706         const WCHAR *filename)     /* [I] The filename of the imported library. */
707 {
708     int length;
709     int offset;
710     MSFT_ImpFile *importfile;
711     char *encoded_string;
712 
713     length = ctl2_encode_string(This, filename, &encoded_string);
714 
715     encoded_string[0] <<= 2;
716     encoded_string[0] |= 1;
717 
718     for (offset = 0; offset < This->typelib_segdir[MSFT_SEG_IMPORTFILES].length;
719          offset += ((((This->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xd] << 8) & 0xff)
720              | (This->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xc] & 0xff)) >> 2) + 0xc) {
721         if (!memcmp(encoded_string, This->typelib_segment_data[MSFT_SEG_IMPORTFILES] + offset + 0xc, length)) return offset;
722     }
723 
724     offset = ctl2_alloc_segment(This, MSFT_SEG_IMPORTFILES, length + 0xc, 0);
725     if (offset == -1) return -1;
726 
727     importfile = (MSFT_ImpFile *)&This->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset];
728     importfile->guid = guidoffset;
729     importfile->lcid = This->typelib_header.lcid2;
730     importfile->version = major_version | (minor_version << 16);
731     memcpy(importfile->filename, encoded_string, length);
732 
733     return offset;
734 }
735 
736 /****************************************************************************
737  *      ctl2_alloc_custdata
738  *
739  *  Allocates and initializes a "custom data" value in a type library.
740  *
741  * RETURNS
742  *
743  *  Success: The offset of the new custdata.
744  *  Failure:
745  *
746  *    -1: Out of memory.
747  *    -2: Unable to encode VARIANT data (typically a bug).
748  */
749 static int ctl2_alloc_custdata(
750         ICreateTypeLib2Impl *This, /* [I] The type library in which to encode the value. */
751         VARIANT *pVarVal)          /* [I] The value to encode. */
752 {
753     int offset;
754 
755     TRACE("(%p,%p(%d))\n",This,pVarVal,V_VT(pVarVal));
756 
757     switch (V_VT(pVarVal)) {
758     case VT_UI4:
759         offset = ctl2_alloc_segment(This, MSFT_SEG_CUSTDATA, 8, 0);
760         if (offset == -1) return offset;
761 
762         *((unsigned short *)&This->typelib_segment_data[MSFT_SEG_CUSTDATA][offset]) = VT_UI4;
763         *((unsigned long *)&This->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+2]) = V_UI4(pVarVal);
764         break;
765 
766     default:
767         FIXME("Unknown variable encoding vt %d.\n", V_VT(pVarVal));
768         return -2;
769     }
770 
771     return offset;
772 }
773 
774 /****************************************************************************
775  *      ctl2_set_custdata
776  *
777  *  Adds a custom data element to an object in a type library.
778  *
779  * RETURNS
780  *
781  *  Success: S_OK.
782  *  Failure: One of E_INVALIDARG or E_OUTOFMEMORY.
783  */
784 static HRESULT ctl2_set_custdata(
785         ICreateTypeLib2Impl *This, /* [I] The type library to store the custom data in. */
786         REFGUID guid,              /* [I] The GUID used as a key to retrieve the custom data. */
787         VARIANT *pVarVal,          /* [I] The custom data itself. */
788         int *offset)               /* [I/O] The list of custom data to prepend to. */
789 {
790     MSFT_GuidEntry guidentry;
791     int dataoffset;
792     int guidoffset;
793     int custoffset;
794     int *custdata;
795 
796     guidentry.guid = *guid;
797 
798     guidentry.hreftype = -1;
799     guidentry.next_hash = -1;
800 
801     guidoffset = ctl2_alloc_guid(This, &guidentry);
802     if (guidoffset == -1) return E_OUTOFMEMORY;
803     dataoffset = ctl2_alloc_custdata(This, pVarVal);
804     if (dataoffset == -1) return E_OUTOFMEMORY;
805     if (dataoffset == -2) return E_INVALIDARG;
806 
807     custoffset = ctl2_alloc_segment(This, MSFT_SEG_CUSTDATAGUID, 12, 0);
808     if (custoffset == -1) return E_OUTOFMEMORY;
809 
810     custdata = (int *)&This->typelib_segment_data[MSFT_SEG_CUSTDATAGUID][custoffset];
811     custdata[0] = guidoffset;
812     custdata[1] = dataoffset;
813     custdata[2] = *offset;
814     *offset = custoffset;
815 
816     return S_OK;
817 }
818 
819 /****************************************************************************
820  *      ctl2_encode_typedesc
821  *
822  *  Encodes a type description, storing information in the TYPEDESC and ARRAYDESC
823  *  segments as needed.
824  *
825  * RETURNS
826  *
827  *  Success: 0.
828  *  Failure: -1.
829  */
830 static int ctl2_encode_typedesc(
831         ICreateTypeLib2Impl *This, /* [I] The type library in which to encode the TYPEDESC. */
832         const TYPEDESC *tdesc,     /* [I] The type description to encode. */
833         int *encoded_tdesc,        /* [O] The encoded type description. */
834         int *width,                /* [O] The width of the type, or NULL. */
835         int *alignment,            /* [O] The alignment of the type, or NULL. */
836         int *decoded_size)         /* [O] The total size of the unencoded TYPEDESCs, including nested descs. */
837 {
838     int default_tdesc;
839     int scratch;
840     int typeoffset;
841     int arrayoffset;
842     int *typedata;
843     int *arraydata;
844     int target_type;
845     int child_size;
846 
847     default_tdesc = 0x80000000 | (tdesc->vt << 16) | tdesc->vt;
848     if (!width) width = &scratch;
849     if (!alignment) alignment = &scratch;
850     if (!decoded_size) decoded_size = &scratch;
851 
852     *decoded_size = 0;
853 
854     switch (tdesc->vt) {
855     case VT_UI1:
856     case VT_I1:
857         *encoded_tdesc = default_tdesc;
858         *width = 1;
859         *alignment = 1;
860         break;
861 
862     case VT_INT:
863         *encoded_tdesc = 0x80000000 | (VT_I4 << 16) | VT_INT;
864         if ((This->typelib_header.varflags & 0x0f) == SYS_WIN16) {
865             *width = 2;
866             *alignment = 2;
867         } else {
868             *width = 4;
869             *alignment = 4;
870         }
871         break;
872 
873     case VT_UINT:
874         *encoded_tdesc = 0x80000000 | (VT_UI4 << 16) | VT_UINT;
875         if ((This->typelib_header.varflags & 0x0f) == SYS_WIN16) {
876             *width = 2;
877             *alignment = 2;
878         } else {
879             *width = 4;
880             *alignment = 4;
881         }
882         break;
883 
884     case VT_UI2:
885     case VT_I2:
886     case VT_BOOL:
887         *encoded_tdesc = default_tdesc;
888         *width = 2;
889         *alignment = 2;
890         break;
891 
892     case VT_I4:
893     case VT_UI4:
894     case VT_R4:
895     case VT_ERROR:
896     case VT_BSTR:
897     case VT_HRESULT:
898         *encoded_tdesc = default_tdesc;
899         *width = 4;
900         *alignment = 4;
901         break;
902 
903     case VT_CY:
904         *encoded_tdesc = default_tdesc;
905         *width = 8;
906         *alignment = 4; /* guess? */
907         break;
908 
909     case VT_VOID:
910         *encoded_tdesc = 0x80000000 | (VT_EMPTY << 16) | tdesc->vt;
911         *width = 0;
912         *alignment = 1;
913         break;
914 
915     case VT_PTR:
916         /* FIXME: Make with the error checking. */
917         FIXME("PTR vartype, may not work correctly.\n");
918 
919         ctl2_encode_typedesc(This, tdesc->u.lptdesc, &target_type, NULL, NULL, &child_size);
920 
921         for (typeoffset = 0; typeoffset < This->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
922             typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
923             if (((typedata[0] & 0xffff) == VT_PTR) && (typedata[1] == target_type)) break;
924         }
925 
926         if (typeoffset == This->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
927             int mix_field;
928             
929             if (target_type & 0x80000000) {
930                 mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF;
931             } else {
932                 typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
933                 mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
934             }
935 
936             typeoffset = ctl2_alloc_segment(This, MSFT_SEG_TYPEDESC, 8, 0);
937             typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
938 
939             typedata[0] = (mix_field << 16) | VT_PTR;
940             typedata[1] = target_type;
941         }
942 
943         *encoded_tdesc = typeoffset;
944 
945         *width = 4;
946         *alignment = 4;
947         *decoded_size = sizeof(TYPEDESC) + child_size;
948         break;
949 
950     case VT_SAFEARRAY:
951         /* FIXME: Make with the error checking. */
952         FIXME("SAFEARRAY vartype, may not work correctly.\n");
953 
954         ctl2_encode_typedesc(This, tdesc->u.lptdesc, &target_type, NULL, NULL, &child_size);
955 
956         for (typeoffset = 0; typeoffset < This->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
957             typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
958             if (((typedata[0] & 0xffff) == VT_SAFEARRAY) && (typedata[1] == target_type)) break;
959         }
960 
961         if (typeoffset == This->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
962             int mix_field;
963             
964             if (target_type & 0x80000000) {
965                 mix_field = ((target_type >> 16) & VT_TYPEMASK) | VT_ARRAY;