oleaut32: Add a helper to return INVOKEKIND flags value.
[wine] / dlls / oleaut32 / typelib2.c
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 "winreg.h"
47 #include "winuser.h"
48
49 #include "wine/unicode.h"
50 #include "objbase.h"
51 #include "typelib.h"
52 #include "wine/debug.h"
53
54 WINE_DEFAULT_DEBUG_CHANNEL(typelib2);
55 /* WINE_DEFAULT_DEBUG_CHANNEL(ole); */
56
57
58 /******************************************************************************
59  * ICreateTypeLib2 {OLEAUT32}
60  *
61  * NOTES
62  *  The ICreateTypeLib2 interface provides an interface whereby one may create
63  *  new type library (.tlb) files.
64  *
65  *  This interface inherits from ICreateTypeLib, and can be freely cast back
66  *  and forth between an ICreateTypeLib and an ICreateTypeLib2 on local clients.
67  *  This dispensation applies only to ICreateTypeLib objects obtained on MSFT
68  *  format type libraries (those made through CreateTypeLib2).
69  *
70  * METHODS
71  */
72
73 /******************************************************************************
74  * ICreateTypeInfo2 {OLEAUT32}
75  *
76  * NOTES
77  *  The ICreateTypeInfo2 interface provides an interface whereby one may add
78  *  type information to type library (.tlb) files.
79  *
80  *  This interface inherits from ICreateTypeInfo, and can be freely cast back
81  *  and forth between an ICreateTypeInfo and an ICreateTypeInfo2 on local clients.
82  *  This dispensation applies only to ICreateTypeInfo objects obtained on MSFT
83  *  format type libraries (those made through CreateTypeLib2).
84  *
85  * METHODS
86  */
87
88 /******************************************************************************
89  * ITypeLib2 {OLEAUT32}
90  *
91  * NOTES
92  *  The ITypeLib2 interface provides an interface whereby one may query MSFT
93  *  format type library (.tlb) files.
94  *
95  *  This interface inherits from ITypeLib, and can be freely cast back and
96  *  forth between an ITypeLib and an ITypeLib2 on local clients. This
97  *  dispensation applies only to ITypeLib objects obtained on MSFT format type
98  *  libraries (those made through CreateTypeLib2).
99  *
100  * METHODS
101  */
102
103 /******************************************************************************
104  * ITypeInfo2 {OLEAUT32}
105  *
106  * NOTES
107  *  The ITypeInfo2 interface provides an interface whereby one may query type
108  *  information stored in MSFT format type library (.tlb) files.
109  *
110  *  This interface inherits from ITypeInfo, and can be freely cast back and
111  *  forth between an ITypeInfo and an ITypeInfo2 on local clients. This
112  *  dispensation applies only to ITypeInfo objects obtained on MSFT format type
113  *  libraries (those made through CreateTypeLib2).
114  *
115  * METHODS
116  */
117
118 /*================== Implementation Structures ===================================*/
119
120 /* Used for storing cyclic list. Tail address is kept */
121 typedef enum tagCyclicListElementType {
122     CyclicListSentinel,
123     CyclicListFunc,
124     CyclicListVar
125 } CyclicListElementType;
126 typedef struct tagCyclicList {
127     struct tagCyclicList *next;
128     int indice;
129     int name;
130     CyclicListElementType type;
131
132     union {
133         int val;
134         int *data;
135     }u;
136 } CyclicList;
137
138 enum MSFT_segment_index {
139     MSFT_SEG_TYPEINFO = 0,  /* type information */
140     MSFT_SEG_IMPORTINFO,    /* import information */
141     MSFT_SEG_IMPORTFILES,   /* import filenames */
142     MSFT_SEG_REFERENCES,    /* references (?) */
143     MSFT_SEG_GUIDHASH,      /* hash table for guids? */
144     MSFT_SEG_GUID,          /* guid storage */
145     MSFT_SEG_NAMEHASH,      /* hash table for names */
146     MSFT_SEG_NAME,          /* name storage */
147     MSFT_SEG_STRING,        /* string storage */
148     MSFT_SEG_TYPEDESC,      /* type descriptions */
149     MSFT_SEG_ARRAYDESC,     /* array descriptions */
150     MSFT_SEG_CUSTDATA,      /* custom data */
151     MSFT_SEG_CUSTDATAGUID,  /* custom data guids */
152     MSFT_SEG_UNKNOWN,       /* ??? */
153     MSFT_SEG_UNKNOWN2,      /* ??? */
154     MSFT_SEG_MAX            /* total number of segments */
155 };
156
157 typedef struct tagMSFT_ImpFile {
158     int guid;
159     LCID lcid;
160     int version;
161     char filename[0]; /* preceded by two bytes of encoded (length << 2) + flags in the low two bits. */
162 } MSFT_ImpFile;
163
164 typedef struct tagICreateTypeLib2Impl
165 {
166     const ICreateTypeLib2Vtbl *lpVtbl;
167     const ITypeLib2Vtbl       *lpVtblTypeLib2;
168
169     LONG ref;
170
171     WCHAR *filename;
172
173     MSFT_Header typelib_header;
174     INT helpStringDll;
175     MSFT_pSeg typelib_segdir[MSFT_SEG_MAX];
176     char *typelib_segment_data[MSFT_SEG_MAX];
177     int typelib_segment_block_length[MSFT_SEG_MAX];
178
179     int typelib_guids; /* Number of defined typelib guids */
180     int typeinfo_guids; /* Number of defined typeinfo guids */
181
182     INT typelib_typeinfo_offsets[0x200]; /* Hope that's enough. */
183
184     INT *typelib_namehash_segment;
185     INT *typelib_guidhash_segment;
186
187     struct tagICreateTypeInfo2Impl *typeinfos;
188     struct tagICreateTypeInfo2Impl *last_typeinfo;
189 } ICreateTypeLib2Impl;
190
191 static inline ICreateTypeLib2Impl *impl_from_ITypeLib2( ITypeLib2 *iface )
192 {
193     return (ICreateTypeLib2Impl *)((char*)iface - FIELD_OFFSET(ICreateTypeLib2Impl, lpVtblTypeLib2));
194 }
195
196 typedef struct tagICreateTypeInfo2Impl
197 {
198     const ICreateTypeInfo2Vtbl *lpVtbl;
199     const ITypeInfo2Vtbl       *lpVtblTypeInfo2;
200
201     LONG ref;
202
203     ICreateTypeLib2Impl *typelib;
204     MSFT_TypeInfoBase *typeinfo;
205
206     struct tagCyclicList *typedata; /* tail of cyclic list */
207
208     TYPEKIND typekind;
209     int datawidth;
210
211     struct tagICreateTypeInfo2Impl *next_typeinfo;
212     struct tagICreateTypeInfo2Impl *dual;
213 } ICreateTypeInfo2Impl;
214
215 static inline ICreateTypeInfo2Impl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
216 {
217     return (ICreateTypeInfo2Impl *)((char*)iface - FIELD_OFFSET(ICreateTypeInfo2Impl, lpVtblTypeInfo2));
218 }
219
220 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface);
221
222 static CyclicList *alloc_cyclic_list_item(CyclicListElementType type)
223 {
224     CyclicList *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CyclicList));
225     if (!ret)
226         return NULL;
227     ret->type = type;
228     return ret;
229 }
230
231 /*================== Internal functions ===================================*/
232
233 static inline UINT cti2_get_var_count(const MSFT_TypeInfoBase *typeinfo)
234 {
235     return typeinfo->cElement >> 16;
236 }
237
238 static inline UINT cti2_get_func_count(const MSFT_TypeInfoBase *typeinfo)
239 {
240     return typeinfo->cElement & 0xFFFF;
241 }
242
243 /* NOTE: entry always assumed to be a function */
244 static inline INVOKEKIND ctl2_get_invokekind(const CyclicList *func)
245 {
246     /* INVOKEKIND uses bit flags up to 8 */
247     return (func->u.data[4] >> 3) & 0xF;
248 }
249
250 /****************************************************************************
251  *      ctl2_init_header
252  *
253  *  Initializes the type library header of a new typelib.
254  */
255 static void ctl2_init_header(
256         ICreateTypeLib2Impl *This) /* [I] The typelib to initialize. */
257 {
258     This->typelib_header.magic1 = 0x5446534d;
259     This->typelib_header.magic2 = 0x00010002;
260     This->typelib_header.posguid = -1;
261     This->typelib_header.lcid = This->typelib_header.lcid2 = GetUserDefaultLCID();
262     This->typelib_header.varflags = 0x40;
263     This->typelib_header.version = 0;
264     This->typelib_header.flags = 0;
265     This->typelib_header.nrtypeinfos = 0;
266     This->typelib_header.helpstring = -1;
267     This->typelib_header.helpstringcontext = 0;
268     This->typelib_header.helpcontext = 0;
269     This->typelib_header.nametablecount = 0;
270     This->typelib_header.nametablechars = 0;
271     This->typelib_header.NameOffset = -1;
272     This->typelib_header.helpfile = -1;
273     This->typelib_header.CustomDataOffset = -1;
274     This->typelib_header.res44 = 0x20;
275     This->typelib_header.res48 = 0x80;
276     This->typelib_header.dispatchpos = -1;
277     This->typelib_header.nimpinfos = 0;
278     This->helpStringDll = -1;
279 }
280
281 /****************************************************************************
282  *      ctl2_init_segdir
283  *
284  *  Initializes the segment directory of a new typelib.
285  */
286 static void ctl2_init_segdir(
287         ICreateTypeLib2Impl *This) /* [I] The typelib to initialize. */
288 {
289     int i;
290     MSFT_pSeg *segdir;
291
292     segdir = &This->typelib_segdir[MSFT_SEG_TYPEINFO];
293
294     for (i = 0; i < 15; i++) {
295         segdir[i].offset = -1;
296         segdir[i].length = 0;
297         segdir[i].res08 = -1;
298         segdir[i].res0c = 0x0f;
299     }
300 }
301
302 /****************************************************************************
303  *      ctl2_hash_guid
304  *
305  *  Generates a hash key from a GUID.
306  *
307  * RETURNS
308  *
309  *  The hash key for the GUID.
310  */
311 static int ctl2_hash_guid(
312         REFGUID guid)                /* [I] The guid to find. */
313 {
314     int hash;
315     int i;
316
317     hash = 0;
318     for (i = 0; i < 8; i ++) {
319         hash ^= ((const short *)guid)[i];
320     }
321
322     return hash & 0x1f;
323 }
324
325 /****************************************************************************
326  *      ctl2_find_guid
327  *
328  *  Locates a guid in a type library.
329  *
330  * RETURNS
331  *
332  *  The offset into the GUID segment of the guid, or -1 if not found.
333  */
334 static int ctl2_find_guid(
335         ICreateTypeLib2Impl *This, /* [I] The typelib to operate against. */
336         int hash_key,              /* [I] The hash key for the guid. */
337         REFGUID guid)                /* [I] The guid to find. */
338 {
339     int offset;
340     MSFT_GuidEntry *guidentry;
341
342     offset = This->typelib_guidhash_segment[hash_key];
343     while (offset != -1) {
344         guidentry = (MSFT_GuidEntry *)&This->typelib_segment_data[MSFT_SEG_GUID][offset];
345
346         if (IsEqualGUID(guidentry, guid)) return offset;
347
348         offset = guidentry->next_hash;
349     }
350
351     return offset;
352 }
353
354 /****************************************************************************
355  *      ctl2_find_name
356  *
357  *  Locates a name in a type library.
358  *
359  * RETURNS
360  *
361  *  The offset into the NAME segment of the name, or -1 if not found.
362  *
363  * NOTES
364  *
365  *  The name must be encoded as with ctl2_encode_name().
366  */
367 static int ctl2_find_name(
368         ICreateTypeLib2Impl *This, /* [I] The typelib to operate against. */
369         const char *name)          /* [I] The encoded name to find. */
370 {
371     int offset;
372     int *namestruct;
373
374     offset = This->typelib_namehash_segment[name[2] & 0x7f];
375     while (offset != -1) {
376         namestruct = (int *)&This->typelib_segment_data[MSFT_SEG_NAME][offset];
377
378         if (!((namestruct[2] ^ *((const int *)name)) & 0xffff00ff)) {
379             /* hash codes and lengths match, final test */
380             if (!strncasecmp(name+4, (void *)(namestruct+3), name[0])) break;
381         }
382
383         /* move to next item in hash bucket */
384         offset = namestruct[1];
385     }
386
387     return offset;
388 }
389
390 /****************************************************************************
391  *      ctl2_encode_name
392  *
393  *  Encodes a name string to a form suitable for storing into a type library
394  *  or comparing to a name stored in a type library.
395  *
396  * RETURNS
397  *
398  *  The length of the encoded name, including padding and length+hash fields.
399  *
400  * NOTES
401  *
402  *  Will throw an exception if name or result are NULL. Is not multithread
403  *  safe in the slightest.
404  */
405 static int ctl2_encode_name(
406         ICreateTypeLib2Impl *This, /* [I] The typelib to operate against (used for LCID only). */
407         const WCHAR *name,         /* [I] The name string to encode. */
408         char **result)             /* [O] A pointer to a pointer to receive the encoded name. */
409 {
410     int length;
411     static char converted_name[0x104];
412     int offset;
413     int value;
414
415     length = WideCharToMultiByte(CP_ACP, 0, name, strlenW(name), converted_name+4, 0x100, NULL, NULL);
416     converted_name[0] = length & 0xff;
417
418     converted_name[length + 4] = 0;
419
420     converted_name[1] = 0x00;
421
422     value = LHashValOfNameSysA(This->typelib_header.varflags & 0x0f, This->typelib_header.lcid, converted_name + 4);
423
424     converted_name[2] = value;
425     converted_name[3] = value >> 8;
426
427     for (offset = (4 - length) & 3; offset; offset--) converted_name[length + offset + 3] = 0x57;
428
429     *result = converted_name;
430
431     return (length + 7) & ~3;
432 }
433
434 /****************************************************************************
435  *      ctl2_decode_name
436  *
437  * Converts string stored in typelib data to unicode.
438  */
439 static void ctl2_decode_name(
440         char *data,         /* [I] String to be decoded */
441         WCHAR **string)     /* [O] Decoded string */
442 {
443     int i, length;
444     static WCHAR converted_string[0x104];
445
446     length = data[0];
447
448     for(i=0; i<length; i++)
449         converted_string[i] = data[i+4];
450     converted_string[length] = '\0';
451
452     *string = converted_string;
453 }
454
455 /****************************************************************************
456  *      ctl2_encode_string
457  *
458  *  Encodes a string to a form suitable for storing into a type library or
459  *  comparing to a string stored in a type library.
460  *
461  * RETURNS
462  *
463  *  The length of the encoded string, including padding and length fields.
464  *
465  * NOTES
466  *
467  *  Will throw an exception if string or result are NULL. Is not multithread
468  *  safe in the slightest.
469  */
470 static int ctl2_encode_string(
471         ICreateTypeLib2Impl *This, /* [I] The typelib to operate against (not used?). */
472         const WCHAR *string,       /* [I] The string to encode. */
473         char **result)             /* [O] A pointer to a pointer to receive the encoded string. */
474 {
475     int length;
476     static char converted_string[0x104];
477     int offset;
478
479     length = WideCharToMultiByte(CP_ACP, 0, string, strlenW(string), converted_string+2, 0x102, NULL, NULL);
480     converted_string[0] = length & 0xff;
481     converted_string[1] = (length >> 8) & 0xff;
482
483     for (offset = (4 - (length + 2)) & 3; offset; offset--) converted_string[length + offset + 1] = 0x57;
484
485     *result = converted_string;
486
487     return (length + 5) & ~3;
488 }
489
490 /****************************************************************************
491  *      ctl2_decode_string
492  *
493  * Converts string stored in typelib data to unicode.
494  */
495 static void ctl2_decode_string(
496         char *data,         /* [I] String to be decoded */
497         WCHAR **string)     /* [O] Decoded string */
498 {
499     int i, length;
500     static WCHAR converted_string[0x104];
501
502     length = data[0] + (data[1]<<8);
503     if((length&0x3) == 1)
504         length >>= 2;
505
506     for(i=0; i<length; i++)
507         converted_string[i] = data[i+2];
508     converted_string[length] = '\0';
509
510     *string = converted_string;
511 }
512
513 /****************************************************************************
514  *      ctl2_alloc_segment
515  *
516  *  Allocates memory from a segment in a type library.
517  *
518  * RETURNS
519  *
520  *  Success: The offset within the segment of the new data area.
521  *  Failure: -1 (this is invariably an out of memory condition).
522  *
523  * BUGS
524  *
525  *  Does not (yet) handle the case where the allocated segment memory needs to grow.
526  */
527 static int ctl2_alloc_segment(
528         ICreateTypeLib2Impl *This,       /* [I] The type library in which to allocate. */
529         enum MSFT_segment_index segment, /* [I] The segment in which to allocate. */
530         int size,                        /* [I] The amount to allocate. */
531         int block_size)                  /* [I] Initial allocation block size, or 0 for default. */
532 {
533     int offset;
534
535     if(!This->typelib_segment_data[segment]) {
536         if (!block_size) block_size = 0x2000;
537
538         This->typelib_segment_block_length[segment] = block_size;
539         This->typelib_segment_data[segment] = HeapAlloc(GetProcessHeap(), 0, block_size);
540         if (!This->typelib_segment_data[segment]) return -1;
541         memset(This->typelib_segment_data[segment], 0x57, block_size);
542     }
543
544     while ((This->typelib_segdir[segment].length + size) > This->typelib_segment_block_length[segment]) {
545         char *block;
546
547         block_size = This->typelib_segment_block_length[segment];
548         block = HeapReAlloc(GetProcessHeap(), 0, This->typelib_segment_data[segment], block_size << 1);
549         if (!block) return -1;
550
551         if (segment == MSFT_SEG_TYPEINFO) {
552             /* TypeInfos have a direct pointer to their memory space, so we have to fix them up. */
553             ICreateTypeInfo2Impl *typeinfo;
554
555             for (typeinfo = This->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
556                 typeinfo->typeinfo = (void *)&block[((char *)typeinfo->typeinfo) - This->typelib_segment_data[segment]];
557             }
558         }
559
560         memset(block + block_size, 0x57, block_size);
561         This->typelib_segment_block_length[segment] = block_size << 1;
562         This->typelib_segment_data[segment] = block;
563     }
564
565     offset = This->typelib_segdir[segment].length;
566     This->typelib_segdir[segment].length += size;
567
568     return offset;
569 }
570
571 /****************************************************************************
572  *      ctl2_alloc_typeinfo
573  *
574  *  Allocates and initializes a typeinfo structure in a type library.
575  *
576  * RETURNS
577  *
578  *  Success: The offset of the new typeinfo.
579  *  Failure: -1 (this is invariably an out of memory condition).
580  */
581 static int ctl2_alloc_typeinfo(
582         ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
583         int nameoffset)            /* [I] The offset of the name for this typeinfo. */
584 {
585     int offset;
586     MSFT_TypeInfoBase *typeinfo;
587
588     offset = ctl2_alloc_segment(This, MSFT_SEG_TYPEINFO, sizeof(MSFT_TypeInfoBase), 0);
589     if (offset == -1) return -1;
590
591     This->typelib_typeinfo_offsets[This->typelib_header.nrtypeinfos++] = offset;
592
593     typeinfo = (void *)(This->typelib_segment_data[MSFT_SEG_TYPEINFO] + offset);
594
595     typeinfo->typekind = (This->typelib_header.nrtypeinfos - 1) << 16;
596     typeinfo->memoffset = -1; /* should be EOF if no elements */
597     typeinfo->res2 = 0;
598     typeinfo->res3 = 0;
599     typeinfo->res4 = 3;
600     typeinfo->res5 = 0;
601     typeinfo->cElement = 0;
602     typeinfo->res7 = 0;
603     typeinfo->res8 = 0;
604     typeinfo->res9 = 0;
605     typeinfo->resA = 0;
606     typeinfo->posguid = -1;
607     typeinfo->flags = 0;
608     typeinfo->NameOffset = nameoffset;
609     typeinfo->version = 0;
610     typeinfo->docstringoffs = -1;
611     typeinfo->helpstringcontext = 0;
612     typeinfo->helpcontext = 0;
613     typeinfo->oCustData = -1;
614     typeinfo->cbSizeVft = 0;
615     typeinfo->cImplTypes = 0;
616     typeinfo->size = 0;
617     typeinfo->datatype1 = -1;
618     typeinfo->datatype2 = 0;
619     typeinfo->res18 = 0;
620     typeinfo->res19 = -1;
621
622     return offset;
623 }
624
625 /****************************************************************************
626  *      ctl2_alloc_guid
627  *
628  *  Allocates and initializes a GUID structure in a type library. Also updates
629  *  the GUID hash table as needed.
630  *
631  * RETURNS
632  *
633  *  Success: The offset of the new GUID.
634  *  Failure: -1 (this is invariably an out of memory condition).
635  */
636 static int ctl2_alloc_guid(
637         ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
638         MSFT_GuidEntry *guid)      /* [I] The GUID to store. */
639 {
640     int offset;
641     MSFT_GuidEntry *guid_space;
642     int hash_key;
643
644     hash_key = ctl2_hash_guid(&guid->guid);
645
646     offset = ctl2_find_guid(This, hash_key, &guid->guid);
647     if (offset != -1) return offset;
648
649     offset = ctl2_alloc_segment(This, MSFT_SEG_GUID, sizeof(MSFT_GuidEntry), 0);
650     if (offset == -1) return -1;
651
652     guid_space = (void *)(This->typelib_segment_data[MSFT_SEG_GUID] + offset);
653     *guid_space = *guid;
654
655     guid_space->next_hash = This->typelib_guidhash_segment[hash_key];
656     This->typelib_guidhash_segment[hash_key] = offset;
657
658     return offset;
659 }
660
661 /****************************************************************************
662  *      ctl2_alloc_name
663  *
664  *  Allocates and initializes a name within a type library. Also updates the
665  *  name hash table as needed.
666  *
667  * RETURNS
668  *
669  *  Success: The offset within the segment of the new name.
670  *  Failure: -1 (this is invariably an out of memory condition).
671  */
672 static int ctl2_alloc_name(
673         ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
674         const WCHAR *name)         /* [I] The name to store. */
675 {
676     int length;
677     int offset;
678     MSFT_NameIntro *name_space;
679     char *encoded_name;
680
681     length = ctl2_encode_name(This, name, &encoded_name);
682
683     offset = ctl2_find_name(This, encoded_name);
684     if (offset != -1) return offset;
685
686     offset = ctl2_alloc_segment(This, MSFT_SEG_NAME, length + 8, 0);
687     if (offset == -1) return -1;
688
689     name_space = (void *)(This->typelib_segment_data[MSFT_SEG_NAME] + offset);
690     name_space->hreftype = -1;
691     name_space->next_hash = -1;
692     memcpy(&name_space->namelen, encoded_name, length);
693
694     if (This->typelib_namehash_segment[encoded_name[2] & 0x7f] != -1)
695         name_space->next_hash = This->typelib_namehash_segment[encoded_name[2] & 0x7f];
696
697     This->typelib_namehash_segment[encoded_name[2] & 0x7f] = offset;
698
699     This->typelib_header.nametablecount += 1;
700     This->typelib_header.nametablechars += *encoded_name;
701
702     return offset;
703 }
704
705 /****************************************************************************
706  *      ctl2_alloc_string
707  *
708  *  Allocates and initializes a string in a type library.
709  *
710  * RETURNS
711  *
712  *  Success: The offset within the segment of the new string.
713  *  Failure: -1 (this is invariably an out of memory condition).
714  */
715 static int ctl2_alloc_string(
716         ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
717         const WCHAR *string)       /* [I] The string to store. */
718 {
719     int length;
720     int offset;
721     char *string_space;
722     char *encoded_string;
723
724     length = ctl2_encode_string(This, string, &encoded_string);
725
726     for (offset = 0; offset < This->typelib_segdir[MSFT_SEG_STRING].length;
727          offset += ((((This->typelib_segment_data[MSFT_SEG_STRING][offset + 1] << 8) & 0xff)
728              | (This->typelib_segment_data[MSFT_SEG_STRING][offset + 0] & 0xff)) + 5) & ~3) {
729         if (!memcmp(encoded_string, This->typelib_segment_data[MSFT_SEG_STRING] + offset, length)) return offset;
730     }
731
732     offset = ctl2_alloc_segment(This, MSFT_SEG_STRING, length, 0);
733     if (offset == -1) return -1;
734
735     string_space = This->typelib_segment_data[MSFT_SEG_STRING] + offset;
736     memcpy(string_space, encoded_string, length);
737
738     return offset;
739 }
740
741 /****************************************************************************
742  *      ctl2_alloc_importinfo
743  *
744  *  Allocates and initializes an import information structure in a type library.
745  *
746  * RETURNS
747  *
748  *  Success: The offset of the new importinfo.
749  *  Failure: -1 (this is invariably an out of memory condition).
750  */
751 static int ctl2_alloc_importinfo(
752         ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
753         MSFT_ImpInfo *impinfo)     /* [I] The import information to store. */
754 {
755     int offset;
756     MSFT_ImpInfo *impinfo_space;
757
758     impinfo_space = (MSFT_ImpInfo*)&This->typelib_segment_data[MSFT_SEG_IMPORTINFO][0];
759     for (offset=0; offset<This->typelib_segdir[MSFT_SEG_IMPORTINFO].length;
760             offset+=sizeof(MSFT_ImpInfo)) {
761         if(impinfo_space->oImpFile == impinfo->oImpFile
762                 && impinfo_space->oGuid == impinfo->oGuid)
763             return offset;
764
765         impinfo_space += 1;
766     }
767
768     impinfo->flags |= This->typelib_header.nimpinfos++;
769
770     offset = ctl2_alloc_segment(This, MSFT_SEG_IMPORTINFO, sizeof(MSFT_ImpInfo), 0);
771     if (offset == -1) return -1;
772
773     impinfo_space = (void *)(This->typelib_segment_data[MSFT_SEG_IMPORTINFO] + offset);
774     *impinfo_space = *impinfo;
775
776     return offset;
777 }
778
779 /****************************************************************************
780  *      ctl2_alloc_importfile
781  *
782  *  Allocates and initializes an import file definition in a type library.
783  *
784  * RETURNS
785  *
786  *  Success: The offset of the new importinfo.
787  *  Failure: -1 (this is invariably an out of memory condition).
788  */
789 static int ctl2_alloc_importfile(
790         ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
791         int guidoffset,            /* [I] The offset to the GUID for the imported library. */
792         LCID lcid,                 /* [I] The LCID of imported library. */
793         int major_version,         /* [I] The major version number of the imported library. */
794         int minor_version,         /* [I] The minor version number of the imported library. */
795         const WCHAR *filename)     /* [I] The filename of the imported library. */
796 {
797     int length;
798     int offset;
799     MSFT_ImpFile *importfile;
800     char *encoded_string;
801
802     length = ctl2_encode_string(This, filename, &encoded_string);
803
804     encoded_string[0] <<= 2;
805     encoded_string[0] |= 1;
806
807     for (offset = 0; offset < This->typelib_segdir[MSFT_SEG_IMPORTFILES].length;
808          offset += ((((((This->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xd] << 8) & 0xff00)
809              | (This->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xc] & 0xff)) >> 2) + 5) & 0xfffc) + 0xc) {
810         if (!memcmp(encoded_string, This->typelib_segment_data[MSFT_SEG_IMPORTFILES] + offset + 0xc, length)) return offset;
811     }
812
813     offset = ctl2_alloc_segment(This, MSFT_SEG_IMPORTFILES, length + 0xc, 0);
814     if (offset == -1) return -1;
815
816     importfile = (MSFT_ImpFile *)&This->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset];
817     importfile->guid = guidoffset;
818     importfile->lcid = lcid;
819     importfile->version = major_version | (minor_version << 16);
820     memcpy(importfile->filename, encoded_string, length);
821
822     return offset;
823 }
824
825 /****************************************************************************
826  *      ctl2_encode_variant
827  *
828  *  Encodes a variant, inline if possible or in custom data segment
829  *
830  * RETURNS
831  *
832  *  Success: S_OK
833  *  Failure: Error code from winerror.h
834  */
835 static HRESULT ctl2_encode_variant(
836         ICreateTypeLib2Impl *This, /* [I] The typelib to allocate data in */
837         int *encoded_value,        /* [O] The encoded default value or data offset */
838         VARIANT *value,            /* [I] Default value to be encoded */
839         VARTYPE arg_type)          /* [I] Argument type */
840 {
841     VARIANT v;
842     HRESULT hres;
843     int mask = 0;
844
845     TRACE("%p %d %d\n", This, V_VT(value), arg_type);
846
847     if(arg_type == VT_INT)
848         arg_type = VT_I4;
849     if(arg_type == VT_UINT)
850         arg_type = VT_UI4;
851
852     v = *value;
853     if(V_VT(value) != arg_type) {
854         hres = VariantChangeType(&v, value, 0, arg_type);
855         if(FAILED(hres))
856             return hres;
857     }
858
859     /* Check if default value can be stored in encoded_value */
860     switch(arg_type) {
861     case VT_I4:
862     case VT_UI4:
863         mask = 0x3ffffff;
864         if(V_UI4(&v)>0x3ffffff)
865             break;
866     case VT_I1:
867     case VT_UI1:
868     case VT_BOOL:
869          if(!mask)
870              mask = 0xff;
871     case VT_I2:
872     case VT_UI2:
873         if(!mask)
874             mask = 0xffff;
875         *encoded_value = (V_UI4(&v)&mask) | ((0x80+0x4*arg_type)<<24);
876         return S_OK;
877     }
878
879     switch(arg_type) {
880     case VT_I4:
881     case VT_R4:
882     case VT_UI4:
883     case VT_INT:
884     case VT_UINT:
885     case VT_HRESULT:
886     case VT_PTR: {
887         /* Construct the data to be allocated */
888         int data[2];
889         data[0] = arg_type + (V_UI4(&v)<<16);
890         data[1] = (V_UI4(&v)>>16) + 0x57570000;
891
892         /* Check if the data was already allocated */
893         /* Currently the structures doesn't allow to do it in a nice way */
894         for(*encoded_value=0; *encoded_value<=This->typelib_segdir[MSFT_SEG_CUSTDATA].length-8; *encoded_value+=4)
895             if(!memcmp(&This->typelib_segment_data[MSFT_SEG_CUSTDATA][*encoded_value], data, 8))
896                 return S_OK;
897
898         /* Allocate the data */
899         *encoded_value = ctl2_alloc_segment(This, MSFT_SEG_CUSTDATA, 8, 0);
900         if(*encoded_value == -1)
901             return E_OUTOFMEMORY;
902
903         memcpy(&This->typelib_segment_data[MSFT_SEG_CUSTDATA][*encoded_value], data, 8);
904         return S_OK;
905     }
906     case VT_BSTR: {
907         /* Construct the data */
908         int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
909         char *data = HeapAlloc(GetProcessHeap(), 0, len);
910
911         if(!data)
912             return E_OUTOFMEMORY;
913
914         *((unsigned short*)data) = arg_type;
915         *((unsigned*)(data+2)) = SysStringLen(V_BSTR(&v));
916         for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
917             if(V_BSTR(&v)[i] <= 0x7f)
918                 data[i+6] = V_BSTR(&v)[i];
919             else
920                 data[i+6] = '?';
921         }
922         WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
923         for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
924             data[i] = 0x57;
925
926         /* Check if the data was already allocated */
927         for(*encoded_value=0; *encoded_value<=This->typelib_segdir[MSFT_SEG_CUSTDATA].length-len; *encoded_value+=4)
928             if(!memcmp(&This->typelib_segment_data[MSFT_SEG_CUSTDATA][*encoded_value], data, len)) {
929                 HeapFree(GetProcessHeap(), 0, data);
930                 return S_OK;
931             }
932
933         /* Allocate the data */
934         *encoded_value = ctl2_alloc_segment(This, MSFT_SEG_CUSTDATA, len, 0);
935         if(*encoded_value == -1) {
936             HeapFree(GetProcessHeap(), 0, data);
937             return E_OUTOFMEMORY;
938         }
939
940         memcpy(&This->typelib_segment_data[MSFT_SEG_CUSTDATA][*encoded_value], data, len);
941         HeapFree(GetProcessHeap(), 0, data);
942         return S_OK;
943     }
944     default:
945         FIXME("Argument type not yet handled\n");
946         return E_NOTIMPL;
947     }
948 }
949
950 static int ctl2_find_custdata(
951     ICreateTypeLib2Impl *This,
952     REFGUID guid,
953     int offset)
954 {
955     while (offset != -1) {
956         MSFT_CDGuid *cdentry =
957             (MSFT_CDGuid *)&This->typelib_segment_data[MSFT_SEG_CUSTDATAGUID][offset];
958         MSFT_GuidEntry *guidentry =
959             (MSFT_GuidEntry *)&This->typelib_segment_data[MSFT_SEG_GUID][cdentry->GuidOffset];
960
961         if (IsEqualGUID(guidentry, guid))
962             return offset;
963
964         offset = cdentry->next;
965     }
966
967     return -1;
968 }
969
970 /****************************************************************************
971  *      ctl2_decode_variant
972  *
973  *  Decodes a variant
974  *
975  * RETURNS
976  *
977  *  Success: S_OK
978  *  Failure: Error code from winerror.h
979  */
980 static HRESULT ctl2_decode_variant(
981         ICreateTypeLib2Impl *This, /* [I] The typelib that contains the variant */
982         int data_offs,             /* [I] Offset within the data array, or the encoded value itself */
983         VARIANT *value)            /* [O] Decoded value */
984 {
985     char *encoded_data;
986     VARTYPE type;
987
988     if (data_offs & 0x80000000) {
989         /* data_offs contains the encoded value */
990         V_VT(value) = (data_offs & ~0x80000000) >> 26;
991         V_UI4(value) = data_offs & ~0xFF000000;
992         return S_OK;
993     }
994
995     encoded_data = &This->typelib_segment_data[MSFT_SEG_CUSTDATA][data_offs];
996     type = *encoded_data;
997
998     switch(type) {
999     case VT_I4:
1000     case VT_R4:
1001     case VT_UI4:
1002     case VT_INT:
1003     case VT_UINT:
1004     case VT_HRESULT:
1005     case VT_PTR: {
1006         V_VT(value) = type;
1007         V_UI4(value) = *(unsigned*)(encoded_data + 2);
1008         return S_OK;
1009     }
1010     case VT_BSTR: {
1011         unsigned len, i;
1012
1013         len = *(unsigned*)(encoded_data + 2);
1014
1015         V_VT(value) = type;
1016         V_BSTR(value) = SysAllocStringByteLen(NULL, len * sizeof(OLECHAR));
1017         for (i = 0; i < len; ++i)
1018             V_BSTR(value)[i] = *(encoded_data + 6 + i);
1019
1020         return S_OK;
1021     }
1022     default:
1023         FIXME("Don't yet have decoder for this VARTYPE: %u\n", type);
1024         return E_NOTIMPL;
1025     }
1026 }
1027
1028 /****************************************************************************
1029  *      ctl2_set_custdata
1030  *
1031  *  Adds a custom data element to an object in a type library.
1032  *
1033  * RETURNS
1034  *
1035  *  Success: S_OK.
1036  *  Failure: One of E_INVALIDARG or E_OUTOFMEMORY.
1037  */
1038 static HRESULT ctl2_set_custdata(
1039         ICreateTypeLib2Impl *This, /* [I] The type library to store the custom data in. */
1040         REFGUID guid,              /* [I] The GUID used as a key to retrieve the custom data. */
1041         VARIANT *pVarVal,          /* [I] The custom data itself. */
1042         int *offset)               /* [I/O] The list of custom data to prepend to. */
1043 {
1044     MSFT_GuidEntry guidentry;
1045     HRESULT status;
1046     int dataoffset;
1047     int guidoffset;
1048     int custoffset;
1049     int *custdata;
1050     BOOL new_segment = FALSE;
1051
1052     switch(V_VT(pVarVal))
1053     {
1054     case VT_I4:
1055     case VT_R4:
1056     case VT_UI4:
1057     case VT_INT:
1058     case VT_UINT:
1059     case VT_HRESULT:
1060     case VT_BSTR:
1061         /* empty */
1062         break;
1063     default:
1064         return DISP_E_BADVARTYPE;
1065     }
1066
1067     guidentry.guid = *guid;
1068
1069     guidentry.hreftype = -1;
1070     guidentry.next_hash = -1;
1071
1072     guidoffset = ctl2_alloc_guid(This, &guidentry);
1073     if (guidoffset == -1) return E_OUTOFMEMORY;
1074
1075     status = ctl2_encode_variant(This, &dataoffset, pVarVal, V_VT(pVarVal));
1076     if (status)
1077         return status;
1078
1079     custoffset = ctl2_find_custdata(This, guid, *offset);
1080     if (custoffset == -1) {
1081         custoffset = ctl2_alloc_segment(This, MSFT_SEG_CUSTDATAGUID, 12, 0);
1082         if (custoffset == -1)
1083             return E_OUTOFMEMORY;
1084         new_segment = TRUE;
1085     }
1086
1087     custdata = (int *)&This->typelib_segment_data[MSFT_SEG_CUSTDATAGUID][custoffset];
1088     custdata[0] = guidoffset;
1089     custdata[1] = dataoffset;
1090     if (new_segment) {
1091         custdata[2] = *offset;
1092         *offset = custoffset;
1093     }
1094
1095     return S_OK;
1096 }
1097
1098 /****************************************************************************
1099  *      ctl2_encode_typedesc
1100  *
1101  *  Encodes a type description, storing information in the TYPEDESC and ARRAYDESC
1102  *  segments as needed.
1103  *
1104  * RETURNS
1105  *
1106  *  Success: 0.
1107  *  Failure: -1.
1108  */
1109 static int ctl2_encode_typedesc(
1110         ICreateTypeLib2Impl *This, /* [I] The type library in which to encode the TYPEDESC. */
1111         const TYPEDESC *tdesc,     /* [I] The type description to encode. */
1112         int *encoded_tdesc,        /* [O] The encoded type description. */
1113         int *width,                /* [O] The width of the type, or NULL. */
1114         int *alignment,            /* [O] The alignment of the type, or NULL. */
1115         int *decoded_size)         /* [O] The total size of the unencoded TYPEDESCs, including nested descs. */
1116 {
1117     int default_tdesc;
1118     int scratch;
1119     int typeoffset;
1120     int arrayoffset;
1121     int *typedata;
1122     int *arraydata;
1123     int target_type;
1124     int child_size;
1125
1126     default_tdesc = 0x80000000 | (tdesc->vt << 16) | tdesc->vt;
1127     if (!width) width = &scratch;
1128     if (!alignment) alignment = &scratch;
1129     if (!decoded_size) decoded_size = &scratch;
1130
1131     *decoded_size = 0;
1132
1133     switch (tdesc->vt) {
1134     case VT_UI1:
1135     case VT_I1:
1136         *encoded_tdesc = default_tdesc;
1137         *width = 1;
1138         *alignment = 1;
1139         break;
1140
1141     case VT_INT:
1142         *encoded_tdesc = 0x80000000 | (VT_I4 << 16) | VT_INT;
1143         if ((This->typelib_header.varflags & 0x0f) == SYS_WIN16) {
1144             *width = 2;
1145             *alignment = 2;
1146         } else {
1147             *width = 4;
1148             *alignment = 4;
1149         }
1150         break;
1151
1152     case VT_UINT:
1153         *encoded_tdesc = 0x80000000 | (VT_UI4 << 16) | VT_UINT;
1154         if ((This->typelib_header.varflags & 0x0f) == SYS_WIN16) {
1155             *width = 2;
1156             *alignment = 2;
1157         } else {
1158             *width = 4;
1159             *alignment = 4;
1160         }
1161         break;
1162
1163     case VT_UI2:
1164     case VT_I2:
1165     case VT_BOOL:
1166         *encoded_tdesc = default_tdesc;
1167         *width = 2;
1168         *alignment = 2;
1169         break;
1170
1171     case VT_I4:
1172     case VT_UI4:
1173     case VT_R4:
1174     case VT_ERROR:
1175     case VT_BSTR:
1176     case VT_HRESULT:
1177         *encoded_tdesc = default_tdesc;
1178         *width = 4;
1179         *alignment = 4;
1180         break;
1181
1182     case VT_CY:
1183         *encoded_tdesc = default_tdesc;
1184         *width = 8;
1185         *alignment = 4; /* guess? */
1186         break;
1187
1188     case VT_VOID:
1189         *encoded_tdesc = 0x80000000 | (VT_EMPTY << 16) | tdesc->vt;
1190         *width = 0;
1191         *alignment = 1;
1192         break;
1193
1194     case VT_PTR:
1195     case VT_SAFEARRAY:
1196         /* FIXME: Make with the error checking. */
1197         FIXME("PTR or SAFEARRAY vartype, may not work correctly.\n");
1198
1199         ctl2_encode_typedesc(This, tdesc->u.lptdesc, &target_type, NULL, NULL, &child_size);
1200
1201         for (typeoffset = 0; typeoffset < This->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
1202             typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
1203             if (((typedata[0] & 0xffff) == tdesc->vt) && (typedata[1] == target_type)) break;
1204         }
1205
1206         if (typeoffset == This->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
1207             int mix_field;
1208             
1209             if (target_type & 0x80000000) {
1210                 mix_field = (target_type >> 16) & VT_TYPEMASK;
1211             } else {
1212                 typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
1213                 switch((typedata[0]>>16) & ~VT_ARRAY)
1214                 {
1215                     case VT_UI1:
1216                     case VT_I1:
1217                     case VT_UI2:
1218                     case VT_I2:
1219                     case VT_I4:
1220                     case VT_UI4:
1221                         mix_field = typedata[0]>>16;
1222                         break;
1223                     default:
1224                         mix_field = ((typedata[0] >> 16) == 0x7fff) ? 0x7fff : 0x7ffe;
1225                         break;
1226                 }
1227             }
1228
1229             if (tdesc->vt == VT_PTR)
1230                 mix_field |= VT_BYREF;
1231             else if (tdesc->vt == VT_SAFEARRAY)
1232                 mix_field |= VT_ARRAY;
1233
1234             typeoffset = ctl2_alloc_segment(This, MSFT_SEG_TYPEDESC, 8, 0);
1235             typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
1236
1237             typedata[0] = (mix_field << 16) | tdesc->vt;
1238             typedata[1] = target_type;
1239         }
1240
1241         *encoded_tdesc = typeoffset;
1242
1243         *width = 4;
1244         *alignment = 4;
1245         *decoded_size = sizeof(TYPEDESC) + child_size;
1246         break;
1247
1248     case VT_CARRAY:
1249       {
1250         /* FIXME: Make with the error checking. */
1251         int num_dims = tdesc->u.lpadesc->cDims, elements = 1, dim;
1252
1253         ctl2_encode_typedesc(This, &tdesc->u.lpadesc->tdescElem, &target_type, width, alignment, NULL);
1254         arrayoffset = ctl2_alloc_segment(This, MSFT_SEG_ARRAYDESC, (2 + 2 * num_dims) * sizeof(int), 0);
1255         arraydata = (void *)&This->typelib_segment_data[MSFT_SEG_ARRAYDESC][arrayoffset];
1256
1257         arraydata[0] = target_type;
1258         arraydata[1] = num_dims;
1259         arraydata[1] |= ((num_dims * 2 * sizeof(int)) << 16);
1260         arraydata += 2;
1261
1262         for(dim = 0; dim < num_dims; dim++) {
1263             arraydata[0] = tdesc->u.lpadesc->rgbounds[dim].cElements;
1264             arraydata[1] = tdesc->u.lpadesc->rgbounds[dim].lLbound;
1265             elements *= tdesc->u.lpadesc->rgbounds[dim].cElements;
1266             arraydata += 2;
1267         }
1268         typeoffset = ctl2_alloc_segment(This, MSFT_SEG_TYPEDESC, 8, 0);
1269         typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
1270
1271         typedata[0] = (0x7ffe << 16) | VT_CARRAY;
1272         typedata[1] = arrayoffset;
1273
1274         *encoded_tdesc = typeoffset;
1275         *width = *width * elements;
1276         *decoded_size = sizeof(ARRAYDESC) + (num_dims - 1) * sizeof(SAFEARRAYBOUND);
1277
1278         break;
1279       }
1280     case VT_USERDEFINED:
1281       {
1282         const MSFT_TypeInfoBase *basetype;
1283         INT basevt = 0x7fff;
1284
1285         TRACE("USERDEFINED.\n");
1286         if (tdesc->u.hreftype % sizeof(*basetype) == 0 && tdesc->u.hreftype < This->typelib_segdir[MSFT_SEG_TYPEINFO].length)
1287         {
1288             basetype = (MSFT_TypeInfoBase*)&(This->typelib_segment_data[MSFT_SEG_TYPEINFO][tdesc->u.hreftype]);
1289             switch(basetype->typekind & 0xf)
1290             {
1291                 case TKIND_ENUM:
1292                     basevt = VT_I4;
1293                     break;
1294                 default:
1295                     FIXME("USERDEFINED basetype %d not handled\n", basetype->typekind & 0xf);
1296                     break;
1297             }
1298         }
1299         for (typeoffset = 0; typeoffset < This->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
1300             typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
1301             if ((typedata[0] == ((basevt << 16) | VT_USERDEFINED)) && (typedata[1] == tdesc->u.hreftype)) break;
1302         }
1303
1304         if (typeoffset == This->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
1305             typeoffset = ctl2_alloc_segment(This, MSFT_SEG_TYPEDESC, 8, 0);
1306             typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
1307
1308             typedata[0] = (basevt << 16) | VT_USERDEFINED;
1309             typedata[1] = tdesc->u.hreftype;
1310         }
1311
1312         *encoded_tdesc = typeoffset;
1313         *width = 0;
1314         *alignment = 1;
1315         break;
1316       }
1317
1318     default:
1319         FIXME("Unrecognized type %d.\n", tdesc->vt);
1320         *encoded_tdesc = default_tdesc;
1321         *width = 0;
1322         *alignment = 1;
1323         break;
1324     }
1325
1326     return 0;
1327 }
1328
1329 /****************************************************************************
1330  *      ctl2_decode_typedesc
1331  *
1332  *  Decodes a type description from an ICreateTypeLib2Impl.
1333  *
1334  * RETURNS
1335  *
1336  *  Success: S_OK.
1337  *  Failure: HRESULT error code.
1338  */
1339 static HRESULT ctl2_decode_typedesc(
1340         ICreateTypeLib2Impl *This, /* [I] The type library from which to decode the TYPEDESC. */
1341         int encoded_tdesc,         /* [I] The encoded type description. */
1342         TYPEDESC *tdesc)           /* [O] The decoded type description. */
1343 {
1344     int *typedata, i;
1345     HRESULT hres;
1346
1347     if (encoded_tdesc & 0x80000000) {
1348         tdesc->vt = encoded_tdesc & VT_TYPEMASK;
1349         tdesc->u.lptdesc = NULL;
1350         return S_OK;
1351     }
1352
1353     typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][encoded_tdesc];
1354
1355     tdesc->vt = typedata[0] & 0xFFFF;
1356
1357     switch(tdesc->vt) {
1358     case VT_PTR:
1359     case VT_SAFEARRAY:
1360         tdesc->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TYPEDESC));
1361         if (!tdesc->u.lptdesc)
1362             return E_OUTOFMEMORY;
1363
1364         hres = ctl2_decode_typedesc(This, typedata[1], tdesc->u.lptdesc);
1365         if (FAILED(hres)) {
1366             HeapFree(GetProcessHeap(), 0, tdesc->u.lptdesc);
1367             return hres;
1368         }
1369
1370         return S_OK;
1371
1372     case VT_CARRAY: {
1373         int arrayoffset, *arraydata, num_dims;
1374
1375         arrayoffset = typedata[1];
1376         arraydata = (void *)&This->typelib_segment_data[MSFT_SEG_ARRAYDESC][arrayoffset];
1377         num_dims = arraydata[1] & 0xFFFF;
1378
1379         tdesc->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1380                 sizeof(ARRAYDESC) + sizeof(SAFEARRAYBOUND) * (num_dims - 1));
1381         if (!tdesc->u.lpadesc)
1382             return E_OUTOFMEMORY;
1383
1384         hres = ctl2_decode_typedesc(This, arraydata[0], &tdesc->u.lpadesc->tdescElem);
1385         if (FAILED(hres)) {
1386             HeapFree(GetProcessHeap(), 0, tdesc->u.lpadesc);
1387             return E_OUTOFMEMORY;
1388         }
1389
1390         for (i = 0; i < num_dims; ++i) {
1391             tdesc->u.lpadesc->rgbounds[i].cElements = arraydata[2 + i * 2];
1392             tdesc->u.lpadesc->rgbounds[i].lLbound = arraydata[3 + i * 2];
1393         }
1394
1395         return S_OK;
1396     }
1397     case VT_USERDEFINED:
1398         tdesc->u.hreftype = typedata[1];
1399         return S_OK;
1400     default:
1401         FIXME("unable to decode typedesc (%08x): unknown VT: %d\n", encoded_tdesc, tdesc->vt);
1402         return E_NOTIMPL;
1403     }
1404 }
1405
1406 /****************************************************************************
1407  *      ctl2_find_nth_reference
1408  *
1409  *  Finds a reference by index into the linked list of reference records.
1410  *
1411  * RETURNS
1412  *
1413  *  Success: Offset of the desired reference record.
1414  *  Failure: -1.
1415  */
1416 static int ctl2_find_nth_reference(
1417         ICreateTypeLib2Impl *This, /* [I] The type library in which to search. */
1418         int offset,                /* [I] The starting offset of the reference list. */
1419         int index)                 /* [I] The index of the reference to find. */
1420 {
1421     MSFT_RefRecord *ref;
1422
1423     for (; index && (offset != -1); index--) {
1424         ref = (MSFT_RefRecord *)&This->typelib_segment_data[MSFT_SEG_REFERENCES][offset];
1425         offset = ref->onext;
1426     }
1427
1428     return offset;
1429 }
1430
1431 /****************************************************************************
1432  *      ctl2_find_typeinfo_from_offset
1433  *
1434  *  Finds an ITypeInfo given an offset into the TYPEINFO segment.
1435  *
1436  * RETURNS
1437  *
1438  *  Success: S_OK.
1439  *  Failure: TYPE_E_ELEMENTNOTFOUND.
1440  */
1441 static HRESULT ctl2_find_typeinfo_from_offset(
1442         ICreateTypeLib2Impl *This, /* [I] The typelib to find the typeinfo in. */
1443         int offset,                /* [I] The offset of the desired typeinfo. */
1444         ITypeInfo **ppTinfo)       /* [I] The typeinfo found. */
1445 {
1446     void *typeinfodata;
1447     ICreateTypeInfo2Impl *typeinfo;
1448
1449     typeinfodata = &This->typelib_segment_data[MSFT_SEG_TYPEINFO][offset];
1450
1451     for (typeinfo = This->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
1452         if (typeinfo->typeinfo == typeinfodata) {
1453             *ppTinfo = (ITypeInfo *)&typeinfo->lpVtblTypeInfo2;
1454             ITypeInfo2_AddRef(*ppTinfo);
1455             return S_OK;
1456         }
1457     }
1458
1459     ERR("Failed to find typeinfo, invariant varied.\n");
1460
1461     return TYPE_E_ELEMENTNOTFOUND;
1462 }
1463
1464 /****************************************************************************
1465  *      funcrecord_reallochdr
1466  *
1467  *  Ensure FuncRecord data block contains header of required size
1468  *
1469  *  PARAMS
1470  *
1471  *   typedata [IO] - reference to pointer to data block
1472  *   need     [I]  - required size of block in bytes
1473  *
1474  * RETURNS
1475  *
1476  *  Number of additionally allocated bytes
1477  */
1478 static INT funcrecord_reallochdr(INT **typedata, int need)
1479 {
1480     int tail = (*typedata)[5]*((*typedata)[4]&0x1000?16:12);
1481     int hdr = (*typedata)[0] - tail;
1482     int i;
1483
1484     if (hdr >= need)
1485         return 0;
1486
1487     *typedata = HeapReAlloc(GetProcessHeap(), 0, *typedata, need + tail);
1488     if (!*typedata)
1489         return -1;
1490
1491     if (tail)
1492         memmove((char*)*typedata + need, (const char*)*typedata + hdr, tail);
1493     (*typedata)[0] = need + tail;
1494
1495     /* fill in default values */
1496     for(i = (hdr+3)/4; (i+1)*4 <= need; i++)
1497     {
1498         switch(i)
1499         {
1500             case 2:
1501                 (*typedata)[i] = 0;
1502                 break;
1503             case 7:
1504                 (*typedata)[i] = -1;
1505                 break;
1506             case 8:
1507                 (*typedata)[i] = -1;
1508                 break;
1509             case 9:
1510                 (*typedata)[i] = -1;
1511                 break;
1512             case 10:
1513                 (*typedata)[i] = -1;
1514                 break;
1515             case 11:
1516                 (*typedata)[i] = 0;
1517                 break;
1518             case 12:
1519                 (*typedata)[i] = -1;
1520                 break;
1521         }
1522     }
1523
1524     return need - hdr;
1525 }
1526
1527 /*================== ICreateTypeInfo2 Implementation ===================================*/
1528
1529 /******************************************************************************
1530  * ICreateTypeInfo2_QueryInterface {OLEAUT32}
1531  *
1532  *  See IUnknown_QueryInterface.
1533  */
1534 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(
1535         ICreateTypeInfo2 * iface,
1536         REFIID riid,
1537         VOID **ppvObject)
1538 {
1539     ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
1540
1541     TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
1542
1543     *ppvObject=NULL;
1544     if(IsEqualIID(riid, &IID_IUnknown) ||
1545        IsEqualIID(riid,&IID_ICreateTypeInfo)||
1546        IsEqualIID(riid,&IID_ICreateTypeInfo2))
1547     {
1548         *ppvObject = This;
1549     } else if (IsEqualIID(riid, &IID_ITypeInfo) ||
1550                IsEqualIID(riid, &IID_ITypeInfo2)) {
1551         *ppvObject = &This->lpVtblTypeInfo2;
1552     }
1553
1554     if(*ppvObject)
1555     {
1556         ICreateTypeInfo2_AddRef(iface);
1557         TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
1558         return S_OK;
1559     }
1560     TRACE("-- Interface: E_NOINTERFACE\n");
1561     return E_NOINTERFACE;
1562 }
1563
1564 /******************************************************************************
1565  * ICreateTypeInfo2_AddRef {OLEAUT32}
1566  *
1567  *  See IUnknown_AddRef.
1568  */
1569 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
1570 {
1571     ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
1572     ULONG ref = InterlockedIncrement(&This->ref);
1573
1574     TRACE("(%p)->ref was %u\n",This, ref - 1);
1575
1576     if(ref==1 && This->typelib)
1577         ICreateTypeLib2_AddRef((ICreateTypeLib2 *)This->typelib);
1578
1579     return ref;
1580 }
1581
1582 /******************************************************************************
1583  * ICreateTypeInfo2_Release {OLEAUT32}
1584  *
1585  *  See IUnknown_Release.
1586  */
1587 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
1588 {
1589     ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
1590     ULONG ref = InterlockedDecrement(&This->ref);
1591
1592     TRACE("(%p)->(%u)\n",This, ref);
1593
1594     if (!ref) {
1595         if (This->typelib) {
1596             ICreateTypeLib2_fnRelease((ICreateTypeLib2 *)This->typelib);
1597             /* Keep This->typelib reference to make stored ICreateTypeInfo structure valid */
1598             /* This->typelib = NULL; */
1599         }
1600
1601         /* ICreateTypeLib2 frees all ICreateTypeInfos when it releases. */
1602         /* HeapFree(GetProcessHeap(),0,This); */
1603         return 0;
1604     }
1605
1606     return ref;
1607 }
1608
1609
1610 /******************************************************************************
1611  * ICreateTypeInfo2_SetGuid {OLEAUT32}
1612  *
1613  *  See ICreateTypeInfo_SetGuid.
1614  */
1615 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface, REFGUID guid)
1616 {
1617     ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
1618
1619     MSFT_GuidEntry guidentry;
1620     int offset;
1621
1622     TRACE("(%p,%s)\n", iface, debugstr_guid(guid));
1623
1624     guidentry.guid = *guid;
1625     guidentry.hreftype = This->typelib->typelib_typeinfo_offsets[This->typeinfo->typekind >> 16];
1626     guidentry.next_hash = -1;
1627
1628     offset = ctl2_alloc_guid(This->typelib, &guidentry);
1629     
1630     if (offset == -1) return E_OUTOFMEMORY;
1631
1632     This->typeinfo->posguid = offset;
1633
1634     if (IsEqualIID(guid, &IID_IDispatch)) {
1635         This->typelib->typelib_header.dispatchpos = This->typelib->typelib_typeinfo_offsets[This->typeinfo->typekind >> 16];
1636     }
1637
1638     return S_OK;
1639 }
1640
1641 /******************************************************************************
1642  * ICreateTypeInfo2_SetTypeFlags {OLEAUT32}
1643  *
1644  *  See ICreateTypeInfo_SetTypeFlags.
1645  */
1646 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface, UINT uTypeFlags)
1647 {
1648     ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
1649
1650     TRACE("(%p,0x%x)\n", iface, uTypeFlags);
1651
1652     if(uTypeFlags & TYPEFLAG_FDUAL) {
1653         This->typeinfo->typekind |= 0x10;
1654         This->typeinfo->typekind &= ~0x0f;
1655         This->typeinfo->typekind |= TKIND_DISPATCH;
1656
1657         if(!This->dual) {
1658             This->dual = HeapAlloc(GetProcessHeap(), 0, sizeof(ICreateTypeInfo2Impl));
1659             if(!This->dual)
1660                 return E_OUTOFMEMORY;
1661
1662             memcpy(This->dual, This, sizeof(ICreateTypeInfo2Impl));
1663             This->dual->ref = 0;
1664             This->dual->typekind = This->typekind==TKIND_DISPATCH ?
1665                 TKIND_INTERFACE : TKIND_DISPATCH;
1666             This->dual->dual = This;
1667         }
1668
1669         /* Make sure dispatch is in typeinfos queue */
1670         if(This->typekind != TKIND_DISPATCH) {
1671             if(This->typelib->last_typeinfo == This)
1672                 This->typelib->last_typeinfo = This->dual;
1673
1674             if(This->typelib->typeinfos == This)
1675                 This->typelib->typeinfos = This->dual;
1676             else {
1677                 ICreateTypeInfo2Impl *iter;
1678
1679                 for(iter=This->typelib->typeinfos; iter->next_typeinfo!=This; iter=iter->next_typeinfo);
1680                 iter->next_typeinfo = This->dual;
1681             }
1682         } else
1683             iface = (ICreateTypeInfo2*)&This->dual->lpVtbl;
1684     }
1685
1686     if (uTypeFlags & (TYPEFLAG_FDISPATCHABLE|TYPEFLAG_FDUAL)) {
1687         static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
1688         ITypeLib *stdole;
1689         ITypeInfo *dispatch;
1690         HREFTYPE hreftype;
1691         HRESULT hres;
1692
1693         hres = LoadTypeLib(stdole2tlb, &stdole);
1694         if(FAILED(hres))
1695             return hres;
1696
1697         hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
1698         ITypeLib_Release(stdole);
1699         if(FAILED(hres))
1700             return hres;
1701
1702         hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
1703         ITypeInfo_Release(dispatch);
1704         if(FAILED(hres))
1705             return hres;
1706     }
1707
1708     This->typeinfo->flags = uTypeFlags;
1709     return S_OK;
1710 }
1711
1712 /******************************************************************************
1713  * ICreateTypeInfo2_SetDocString {OLEAUT32}
1714  *
1715  *  See ICreateTypeInfo_SetDocString.
1716  */
1717 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(
1718         ICreateTypeInfo2* iface,
1719         LPOLESTR pStrDoc)
1720 {
1721     ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
1722
1723     int offset;
1724
1725     TRACE("(%p,%s)\n", iface, debugstr_w(pStrDoc));
1726     if (!pStrDoc)
1727         return E_INVALIDARG;
1728
1729     offset = ctl2_alloc_string(This->typelib, pStrDoc);
1730     if (offset == -1) return E_OUTOFMEMORY;
1731     This->typeinfo->docstringoffs = offset;
1732     return S_OK;
1733 }
1734
1735 /******************************************************************************
1736  * ICreateTypeInfo2_SetHelpContext {OLEAUT32}
1737  *
1738  *  See ICreateTypeInfo_SetHelpContext.
1739  */
1740 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(
1741         ICreateTypeInfo2* iface,
1742         DWORD dwHelpContext)
1743 {
1744     ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
1745
1746     TRACE("(%p,%d)\n", iface, dwHelpContext);
1747
1748     This->typeinfo->helpcontext = dwHelpContext;
1749
1750     return S_OK;
1751 }
1752
1753 /******************************************************************************
1754  * ICreateTypeInfo2_SetVersion {OLEAUT32}
1755  *
1756  *  See ICreateTypeInfo_SetVersion.
1757  */
1758 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(
1759         ICreateTypeInfo2* iface,
1760         WORD wMajorVerNum,
1761         WORD wMinorVerNum)
1762 {
1763     ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
1764
1765     TRACE("(%p,%d,%d)\n", iface, wMajorVerNum, wMinorVerNum);
1766
1767     This->typeinfo->version = wMajorVerNum | (wMinorVerNum << 16);
1768     return S_OK;
1769 }
1770
1771 /******************************************************************************
1772  * ICreateTypeInfo2_AddRefTypeInfo {OLEAUT32}
1773  *
1774  *  See ICreateTypeInfo_AddRefTypeInfo.
1775  */
1776 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(
1777         ICreateTypeInfo2* iface,
1778         ITypeInfo* pTInfo,
1779         HREFTYPE* phRefType)
1780 {
1781     ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
1782
1783     ITypeLib *container;
1784     UINT index;
1785     HRESULT res;
1786
1787     TRACE("(%p,%p,%p)\n", iface, pTInfo, phRefType);
1788
1789     if(!pTInfo || !phRefType)
1790         return E_INVALIDARG;
1791
1792     /*
1793      * Unfortunately, we can't rely on the passed-in TypeInfo even having the
1794      * same internal structure as one of ours. It could be from another
1795      * implementation of ITypeInfo. So we need to do the following...
1796      */
1797     res = ITypeInfo_GetContainingTypeLib(pTInfo, &container, &index);
1798     if (FAILED(res)) {
1799         TRACE("failed to find containing typelib.\n");
1800         return res;
1801     }
1802
1803     if (container == (ITypeLib *)&This->typelib->lpVtblTypeLib2) {
1804         /* Process locally defined TypeInfo */
1805         *phRefType = This->typelib->typelib_typeinfo_offsets[index];
1806     } else {
1807         BSTR name;
1808         TLIBATTR *tlibattr;
1809         TYPEATTR *typeattr;
1810         TYPEKIND typekind;
1811         MSFT_GuidEntry guid, *check_guid;
1812         MSFT_ImpInfo impinfo;
1813         int guid_offset, import_offset;
1814         HRESULT hres;
1815
1816         /* Allocate container GUID */
1817         hres = ITypeLib_GetLibAttr(container, &tlibattr);
1818         if(FAILED(hres)) {
1819             ITypeLib_Release(container);
1820             return hres;
1821         }
1822
1823         guid.guid = tlibattr->guid;
1824         guid.hreftype = This->typelib->typelib_segdir[MSFT_SEG_IMPORTFILES].length+2;
1825         guid.next_hash = -1;
1826
1827         guid_offset = ctl2_alloc_guid(This->typelib, &guid);
1828         if(guid_offset == -1) {
1829             ITypeLib_ReleaseTLibAttr(container, tlibattr);
1830             ITypeLib_Release(container);
1831             return E_OUTOFMEMORY;
1832         }
1833
1834         check_guid = (MSFT_GuidEntry*)&This->typelib->typelib_segment_data[MSFT_SEG_GUID][guid_offset];
1835         if(check_guid->hreftype == guid.hreftype)
1836             This->typelib->typelib_guids++;
1837
1838         /* Get import file name */
1839         hres = QueryPathOfRegTypeLib(&guid.guid, tlibattr->wMajorVerNum,
1840                 tlibattr->wMinorVerNum, tlibattr->lcid, &name);
1841         if(FAILED(hres)) {
1842             ITypeLib_ReleaseTLibAttr(container, tlibattr);
1843             ITypeLib_Release(container);
1844             return hres;
1845         }
1846
1847         /* Import file */
1848         import_offset = ctl2_alloc_importfile(This->typelib, guid_offset, tlibattr->lcid,
1849                 tlibattr->wMajorVerNum, tlibattr->wMinorVerNum, strrchrW(name, '\\')+1);
1850         ITypeLib_ReleaseTLibAttr(container, tlibattr);
1851         SysFreeString(name);
1852
1853         if(import_offset == -1) {
1854             ITypeLib_Release(container);
1855             return E_OUTOFMEMORY;
1856         }
1857
1858         /* Allocate referenced guid */
1859         hres = ITypeInfo_GetTypeAttr(pTInfo, &typeattr);
1860         if(FAILED(hres)) {
1861             ITypeLib_Release(container);
1862             return hres;
1863         }
1864
1865         guid.guid = typeattr->guid;
1866         guid.hreftype = This->typelib->typeinfo_guids*12+1;
1867         guid.next_hash = -1;
1868         typekind = typeattr->typekind;
1869         ITypeInfo_ReleaseTypeAttr(pTInfo, typeattr);
1870
1871         guid_offset = ctl2_alloc_guid(This->typelib, &guid);
1872         if(guid_offset == -1) {
1873             ITypeLib_Release(container);
1874             return E_OUTOFMEMORY;
1875         }
1876
1877         check_guid = (MSFT_GuidEntry*)&This->typelib->typelib_segment_data[MSFT_SEG_GUID][guid_offset];
1878         if(check_guid->hreftype == guid.hreftype)
1879             This->typelib->typeinfo_guids++;
1880
1881         /* Allocate importinfo */
1882         impinfo.flags = (typekind<<24) | MSFT_IMPINFO_OFFSET_IS_GUID;
1883         impinfo.oImpFile = import_offset;
1884         impinfo.oGuid = guid_offset;
1885         *phRefType = ctl2_alloc_importinfo(This->typelib, &impinfo)+1;
1886
1887         if(IsEqualGUID(&guid.guid, &IID_IDispatch))
1888             This->typelib->typelib_header.dispatchpos = *phRefType;
1889     }
1890
1891     ITypeLib_Release(container);
1892     return S_OK;
1893 }
1894
1895 /******************************************************************************
1896  * ICreateTypeInfo2_AddFuncDesc {OLEAUT32}
1897  *
1898  *  See ICreateTypeInfo_AddFuncDesc.
1899  */
1900 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(
1901         ICreateTypeInfo2* iface,
1902         UINT index,
1903         FUNCDESC* pFuncDesc)
1904 {
1905     ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
1906
1907     CyclicList *iter, *insert;
1908     int *typedata;
1909     int i, num_defaults = 0, num_retval = 0;
1910     int decoded_size;
1911     HRESULT hres;
1912
1913     TRACE("(%p,%d,%p)\n", iface, index, pFuncDesc);
1914
1915     if(!pFuncDesc || pFuncDesc->oVft&3)
1916         return E_INVALIDARG;
1917
1918     TRACE("{%d,%p,%p,%d,%d,%d,%d,%d,%d,%d,{%d},%d}\n", pFuncDesc->memid,
1919             pFuncDesc->lprgscode, pFuncDesc->lprgelemdescParam, pFuncDesc->funckind,
1920             pFuncDesc->invkind, pFuncDesc->callconv, pFuncDesc->cParams,
1921             pFuncDesc->cParamsOpt, pFuncDesc->oVft, pFuncDesc->cScodes,
1922             pFuncDesc->elemdescFunc.tdesc.vt, pFuncDesc->wFuncFlags);
1923
1924     if(pFuncDesc->cParamsOpt || pFuncDesc->cScodes)
1925         FIXME("Unimplemented parameter - created typelib will be incorrect\n");
1926
1927     switch(This->typekind) {
1928     case TKIND_MODULE:
1929         if(pFuncDesc->funckind != FUNC_STATIC)
1930             return TYPE_E_BADMODULEKIND;
1931         break;
1932     case TKIND_DISPATCH:
1933         if(pFuncDesc->funckind != FUNC_DISPATCH)
1934             return TYPE_E_BADMODULEKIND;
1935         break;
1936     default:
1937         if(pFuncDesc->funckind != FUNC_PUREVIRTUAL)
1938             return TYPE_E_BADMODULEKIND;
1939     }
1940
1941     if(cti2_get_func_count(This->typeinfo) < index)
1942         return TYPE_E_ELEMENTNOTFOUND;
1943
1944     if((pFuncDesc->invkind&(INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF)) &&
1945         !pFuncDesc->cParams)
1946         return TYPE_E_INCONSISTENTPROPFUNCS;
1947
1948     /* get number of arguments with default values specified */
1949     for (i = 0; i < pFuncDesc->cParams; i++) {
1950         if(pFuncDesc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
1951             num_defaults++;
1952         if(pFuncDesc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL)
1953             num_retval++;
1954     }
1955
1956     if (!This->typedata) {
1957         This->typedata = alloc_cyclic_list_item(CyclicListSentinel);
1958         if(!This->typedata)
1959             return E_OUTOFMEMORY;
1960
1961         This->typedata->next = This->typedata;
1962
1963         if(This->dual)
1964             This->dual->typedata = This->typedata;
1965     }
1966
1967     /* allocate type data space for us */
1968     insert = alloc_cyclic_list_item(CyclicListFunc);
1969     if(!insert)
1970         return E_OUTOFMEMORY;
1971     insert->u.data = HeapAlloc(GetProcessHeap(), 0, sizeof(int[6])+sizeof(int[(num_defaults?4:3)])*pFuncDesc->cParams);
1972     if(!insert->u.data) {
1973         HeapFree(GetProcessHeap(), 0, insert);
1974         return E_OUTOFMEMORY;
1975     }
1976
1977     /* fill out the basic type information */
1978     typedata = insert->u.data;
1979     typedata[0] = 0x18 + pFuncDesc->cParams*(num_defaults?16:12);
1980     ctl2_encode_typedesc(This->typelib, &pFuncDesc->elemdescFunc.tdesc, &typedata[1], NULL, NULL, &decoded_size);
1981     typedata[2] = pFuncDesc->wFuncFlags;
1982     typedata[3] = ((sizeof(FUNCDESC) + decoded_size) << 16) | (unsigned short)(pFuncDesc->oVft?pFuncDesc->oVft+1:0);
1983     typedata[4] = (pFuncDesc->callconv << 8) | (pFuncDesc->invkind << 3) | pFuncDesc->funckind;
1984     if(num_defaults) typedata[4] |= 0x1000;
1985     if (num_retval) typedata[4] |= 0x4000;
1986     typedata[5] = pFuncDesc->cParams;
1987
1988     /* NOTE: High word of typedata[3] is total size of FUNCDESC + size of all ELEMDESCs for params + TYPEDESCs for pointer params and return types. */
1989     /* That is, total memory allocation required to reconstitute the FUNCDESC in its entirety. */
1990     typedata[3] += (sizeof(ELEMDESC) * pFuncDesc->cParams) << 16;
1991     typedata[3] += (sizeof(PARAMDESCEX) * num_defaults) << 16;
1992
1993     /* add default values */
1994     if(num_defaults) {
1995         for (i = 0; i < pFuncDesc->cParams; i++)
1996             if(pFuncDesc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) {
1997                 hres = ctl2_encode_variant(This->typelib, typedata+6+i,
1998                         &pFuncDesc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue,
1999                         pFuncDesc->lprgelemdescParam[i].tdesc.vt);
2000
2001                 if(FAILED(hres)) {
2002                     HeapFree(GetProcessHeap(), 0, insert->u.data);
2003                     HeapFree(GetProcessHeap(), 0, insert);
2004                     return hres;
2005                 }
2006             } else
2007                 typedata[6+i] = 0xffffffff;
2008
2009         num_defaults = pFuncDesc->cParams;
2010     }
2011
2012     /* add arguments */
2013     for (i = 0; i < pFuncDesc->cParams; i++) {
2014         ctl2_encode_typedesc(This->typelib, &pFuncDesc->lprgelemdescParam[i].tdesc,
2015                 &typedata[6+num_defaults+(i*3)], NULL, NULL, &decoded_size);
2016         typedata[7+num_defaults+(i*3)] = -1;
2017         typedata[8+num_defaults+(i*3)] = pFuncDesc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
2018         typedata[3] += decoded_size << 16;
2019     }
2020
2021     /* update the index data */
2022     insert->indice = pFuncDesc->memid;
2023     insert->name = -1;
2024
2025     /* insert type data to list */
2026     if(index == cti2_get_func_count(This->typeinfo)) {
2027         insert->next = This->typedata->next;
2028         This->typedata->next = insert;
2029         This->typedata = insert;
2030
2031         if(This->dual)
2032             This->dual->typedata = This->typedata;
2033     } else {
2034         iter = This->typedata->next;
2035         for(i=0; i<index; i++)
2036             iter = iter->next;
2037
2038         insert->next = iter->next;
2039         iter->next = insert;
2040     }
2041
2042     /* update type data size */
2043     This->typedata->next->u.val += 0x18 + pFuncDesc->cParams*(num_defaults?16:12);
2044
2045     /* Increment the number of function elements */
2046     This->typeinfo->cElement += 1;
2047
2048     return S_OK;
2049 }
2050
2051 /******************************************************************************
2052  * ICreateTypeInfo2_AddImplType {OLEAUT32}
2053  *
2054  *  See ICreateTypeInfo_AddImplType.
2055  */
2056 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(
2057         ICreateTypeInfo2* iface,
2058         UINT index,
2059         HREFTYPE hRefType)
2060 {
2061     ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
2062
2063     TRACE("(%p,%d,%d)\n", iface, index, hRefType);
2064
2065     if (This->typekind == TKIND_COCLASS) {
2066         int offset;
2067         MSFT_RefRecord *ref;
2068
2069         if (index == 0) {
2070             if (This->typeinfo->datatype1 != -1) return TYPE_E_ELEMENTNOTFOUND;
2071
2072             offset = ctl2_alloc_segment(This->typelib, MSFT_SEG_REFERENCES, sizeof(MSFT_RefRecord), 0);
2073             if (offset == -1) return E_OUTOFMEMORY;
2074
2075             This->typeinfo->datatype1 = offset;
2076         } else {
2077             int lastoffset;
2078
2079             lastoffset = ctl2_find_nth_reference(This->typelib, This->typeinfo->datatype1, index - 1);
2080             if (lastoffset == -1) return TYPE_E_ELEMENTNOTFOUND;
2081
2082             ref = (MSFT_RefRecord *)&This->typelib->typelib_segment_data[MSFT_SEG_REFERENCES][lastoffset];
2083             if (ref->onext != -1) return TYPE_E_ELEMENTNOTFOUND;
2084
2085             offset = ctl2_alloc_segment(This->typelib, MSFT_SEG_REFERENCES, sizeof(MSFT_RefRecord), 0);
2086             if (offset == -1) return E_OUTOFMEMORY;
2087
2088             ref->onext = offset;
2089         }
2090
2091         ref = (MSFT_RefRecord *)&This->typelib->typelib_segment_data[MSFT_SEG_REFERENCES][offset];
2092
2093         ref->reftype = hRefType;
2094         ref->flags = 0;
2095         ref->oCustData = -1;
2096         ref->onext = -1;
2097         This->typeinfo->cImplTypes++;
2098     } else if (This->typekind == TKIND_INTERFACE) {
2099         if (This->typeinfo->cImplTypes && index==1)
2100             return TYPE_E_BADMODULEKIND;
2101
2102         if( index != 0)  return TYPE_E_ELEMENTNOTFOUND;
2103
2104         This->typeinfo->datatype1 = hRefType;
2105         This->typeinfo->cImplTypes = 1;
2106     } else if (This->typekind == TKIND_DISPATCH) {
2107         if(index != 0) return TYPE_E_ELEMENTNOTFOUND;
2108
2109         /* FIXME: Check if referenced typeinfo is IDispatch */
2110         This->typeinfo->flags |= TYPEFLAG_FDISPATCHABLE;
2111         This->typeinfo->cImplTypes = 1;
2112     } else {
2113         FIXME("AddImplType unsupported on typekind %d\n", This->typekind);
2114         return E_OUTOFMEMORY;
2115     }
2116
2117     return S_OK;
2118 }
2119
2120 /******************************************************************************
2121  * ICreateTypeInfo2_SetImplTypeFlags {OLEAUT32}
2122  *
2123  *  See ICreateTypeInfo_SetImplTypeFlags.
2124  */
2125 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(
2126         ICreateTypeInfo2* iface,
2127         UINT index,
2128         INT implTypeFlags)
2129 {
2130     ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
2131     int offset;
2132     MSFT_RefRecord *ref;
2133
2134     TRACE("(%p,%d,0x%x)\n", iface, index, implTypeFlags);
2135
2136     if (This->typekind != TKIND_COCLASS) {
2137         return TYPE_E_BADMODULEKIND;
2138     }
2139
2140     offset = ctl2_find_nth_reference(This->typelib, This->typeinfo->datatype1, index);
2141     if (offset == -1) return TYPE_E_ELEMENTNOTFOUND;
2142
2143     ref = (MSFT_RefRecord *)&This->typelib->typelib_segment_data[MSFT_SEG_REFERENCES][offset];
2144     ref->flags = implTypeFlags;
2145
2146     return S_OK;
2147 }
2148
2149 /******************************************************************************
2150  * ICreateTypeInfo2_SetAlignment {OLEAUT32}
2151  *
2152  *  See ICreateTypeInfo_SetAlignment.
2153  */
2154 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(
2155         ICreateTypeInfo2* iface,
2156         WORD cbAlignment)
2157 {
2158     ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
2159
2160     TRACE("(%p,%d)\n", iface, cbAlignment);
2161
2162     if (!cbAlignment) return E_INVALIDARG;
2163     if (cbAlignment > 16) return E_INVALIDARG;
2164
2165     This->typeinfo->typekind &= ~0xffc0;
2166     This->typeinfo->typekind |= cbAlignment << 6;
2167
2168     /* FIXME: There's probably some way to simplify this. */
2169     switch (This->typekind) {
2170     case TKIND_ALIAS:
2171     default:
2172         break;
2173
2174     case TKIND_ENUM:
2175     case TKIND_INTERFACE:
2176     case TKIND_DISPATCH:
2177     case TKIND_COCLASS:
2178         if (cbAlignment > 4) cbAlignment = 4;
2179         break;
2180
2181     case TKIND_RECORD:
2182     case TKIND_MODULE:
2183     case TKIND_UNION:
2184         cbAlignment = 1;
2185         break;
2186     }
2187
2188     This->typeinfo->typekind |= cbAlignment << 11;
2189
2190     return S_OK;
2191 }
2192
2193 /******************************************************************************
2194  * ICreateTypeInfo2_SetSchema {OLEAUT32}
2195  *
2196  *  See ICreateTypeInfo_SetSchema.
2197  */
2198 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(
2199         ICreateTypeInfo2* iface,
2200         LPOLESTR pStrSchema)
2201 {
2202     FIXME("(%p,%s), stub!\n", iface, debugstr_w(pStrSchema));
2203     return E_OUTOFMEMORY;
2204 }
2205
2206 /******************************************************************************
2207  * ICreateTypeInfo2_AddVarDesc {OLEAUT32}
2208  *
2209  *  See ICreateTypeInfo_AddVarDesc.
2210  */
2211 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(
2212         ICreateTypeInfo2* iface,
2213         UINT index,
2214         VARDESC* pVarDesc)
2215 {
2216     ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
2217
2218     HRESULT status = S_OK;
2219     CyclicList *insert;
2220     INT *typedata;
2221     int var_datawidth;
2222     int var_alignment;
2223     int var_type_size;
2224     int alignment;
2225
2226     TRACE("(%p,%d,%p)\n", iface, index, pVarDesc);
2227     TRACE("%d, %p, %d, {{%x, %d}, {%p, %x}}, 0x%x, %d\n", pVarDesc->memid, pVarDesc->lpstrSchema, pVarDesc->u.oInst,
2228           pVarDesc->elemdescVar.tdesc.u.hreftype, pVarDesc->elemdescVar.tdesc.vt,
2229           pVarDesc->elemdescVar.u.paramdesc.pparamdescex, pVarDesc->elemdescVar.u.paramdesc.wParamFlags,
2230           pVarDesc->wVarFlags, pVarDesc->varkind);
2231
2232     if (cti2_get_var_count(This->typeinfo) != index)
2233         return TYPE_E_ELEMENTNOTFOUND;
2234
2235     if (!This->typedata) {
2236         This->typedata = alloc_cyclic_list_item(CyclicListSentinel);
2237         if(!This->typedata)
2238             return E_OUTOFMEMORY;
2239
2240         This->typedata->next = This->typedata;
2241
2242         if(This->dual)
2243             This->dual->typedata = This->typedata;
2244     }
2245
2246     /* allocate type data space for us */
2247     insert = alloc_cyclic_list_item(CyclicListVar);
2248     if(!insert)
2249         return E_OUTOFMEMORY;
2250     insert->u.data = HeapAlloc(GetProcessHeap(), 0, sizeof(int[5]));
2251     if(!insert->u.data) {
2252         HeapFree(GetProcessHeap(), 0, insert);
2253         return E_OUTOFMEMORY;
2254     }
2255
2256     insert->next = This->typedata->next;
2257     This->typedata->next = insert;
2258     This->typedata = insert;
2259
2260     if(This->dual)
2261         This->dual->typedata = This->typedata;
2262
2263     This->typedata->next->u.val += 0x14;
2264     typedata = This->typedata->u.data;
2265
2266     /* fill out the basic type information */
2267     typedata[0] = 0x14 | (index << 16);
2268     typedata[2] = pVarDesc->wVarFlags;
2269     typedata[3] = (sizeof(VARDESC) << 16) | pVarDesc->varkind;
2270
2271     /* update the index data */
2272     insert->indice = 0x40000000 + index;
2273     insert->name = -1;
2274
2275     /* figure out type widths and whatnot */
2276     ctl2_encode_typedesc(This->typelib, &pVarDesc->elemdescVar.tdesc,
2277                          &typedata[1], &var_datawidth, &var_alignment,
2278                          &var_type_size);
2279
2280     if (pVarDesc->varkind != VAR_CONST)
2281     {
2282         /* pad out starting position to data width */
2283         This->datawidth += var_alignment - 1;
2284         This->datawidth &= ~(var_alignment - 1);
2285         typedata[4] = This->datawidth;
2286
2287         /* add the new variable to the total data width */
2288         This->datawidth += var_datawidth;
2289         if(This->dual)
2290             This->dual->datawidth = This->datawidth;
2291
2292         /* add type description size to total required allocation */
2293         typedata[3] += var_type_size << 16;
2294
2295         /* fix type alignment */
2296         alignment = (This->typeinfo->typekind >> 11) & 0x1f;
2297         if (alignment < var_alignment) {
2298             alignment = var_alignment;
2299             This->typeinfo->typekind &= ~0xf800;
2300             This->typeinfo->typekind |= alignment << 11;
2301         }
2302
2303         /* ??? */
2304         if (!This->typeinfo->res2) This->typeinfo->res2 = 0x1a;
2305         if ((index == 0) || (index == 1) || (index == 2) || (index == 4) || (index == 9)) {
2306             This->typeinfo->res2 <<= 1;
2307         }
2308
2309         /* ??? */
2310         if (This->typeinfo->res3 == -1) This->typeinfo->res3 = 0;
2311         This->typeinfo->res3 += 0x2c;
2312
2313         /* pad data width to alignment */
2314         This->typeinfo->size = (This->datawidth + (alignment - 1)) & ~(alignment - 1);
2315     } else {
2316         VARIANT *value = pVarDesc->DUMMYUNIONNAME.lpvarValue;
2317         status = ctl2_encode_variant(This->typelib, typedata+4, value, V_VT(value));
2318         /* ??? native sets size 0x34 */
2319         typedata[3] += 0x10 << 16;
2320     }
2321
2322     /* increment the number of variable elements */
2323     This->typeinfo->cElement += 0x10000;
2324
2325     return status;
2326 }
2327
2328 /******************************************************************************
2329  * ICreateTypeInfo2_SetFuncAndParamNames {OLEAUT32}
2330  *
2331  *  See ICreateTypeInfo_SetFuncAndParamNames.
2332  */
2333 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(
2334         ICreateTypeInfo2* iface,
2335         UINT index,
2336         LPOLESTR* names,
2337         UINT cNames)
2338 {
2339     ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
2340     CyclicList *iter, *iter2;
2341     int offset, len, i;
2342     char *namedata;
2343
2344     TRACE("(%p %d %p %d)\n", This, index, names, cNames);
2345
2346     if(!names)
2347         return E_INVALIDARG;
2348
2349     if(index >= cti2_get_func_count(This->typeinfo) || cNames == 0)
2350         return TYPE_E_ELEMENTNOTFOUND;
2351
2352     for(iter=This->typedata->next->next, i=0; /* empty */; iter=iter->next)
2353         if (iter->type == CyclicListFunc)
2354             if (i++ >= index)
2355                 break;
2356
2357     /* cNames == cParams for put or putref accessor, cParams+1 otherwise */
2358     if(cNames != iter->u.data[5] + (ctl2_get_invokekind(iter) & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF) ? 0 : 1))
2359         return TYPE_E_ELEMENTNOTFOUND;
2360
2361     TRACE("function name %s\n", debugstr_w(names[0]));
2362     len = ctl2_encode_name(This->typelib, names[0], &namedata);
2363     for(iter2=This->typedata->next->next; iter2!=This->typedata->next; iter2=iter2->next) {
2364         if(iter2->name!=-1 && !memcmp(namedata,
2365                     This->typelib->typelib_segment_data[MSFT_SEG_NAME]+iter2->name+8, len)) {
2366             /* getters/setters can have a same name */
2367             if (iter2->type == CyclicListFunc) {
2368                 INVOKEKIND inv1 = ctl2_get_invokekind(iter2);
2369                 INVOKEKIND inv2 = ctl2_get_invokekind(iter);
2370
2371                 if (((inv1&(INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF)) && (inv2&INVOKE_PROPERTYGET)) ||
2372                     ((inv2&(INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF)) && (inv1&INVOKE_PROPERTYGET)))
2373                     continue;
2374             }
2375
2376             return TYPE_E_AMBIGUOUSNAME;
2377         }
2378     }
2379
2380     offset = ctl2_alloc_name(This->typelib, names[0]);
2381     if(offset == -1)
2382         return E_OUTOFMEMORY;
2383
2384     iter->name = offset;
2385
2386     namedata = This->typelib->typelib_segment_data[MSFT_SEG_NAME] + offset;
2387     if (*((INT*)namedata) == -1)
2388             *((INT *)namedata) = This->typelib->typelib_typeinfo_offsets[This->typeinfo->typekind >> 16];
2389
2390     len = (iter->u.data[0]&0xFFFF)/4 - iter->u.data[5]*3;
2391
2392     for (i = 1; i < cNames; i++) {
2393         offset = ctl2_alloc_name(This->typelib, names[i]);
2394         iter->u.data[len + ((i-1)*3) + 1] = offset;
2395     }
2396
2397     return S_OK;
2398 }
2399
2400 /******************************************************************************
2401  * ICreateTypeInfo2_SetVarName {OLEAUT32}
2402  *
2403  *  See ICreateTypeInfo_SetVarName.
2404  */
2405 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(
2406         ICreateTypeInfo2* iface,
2407         UINT index,
2408         LPOLESTR szName)
2409 {
2410     ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
2411     CyclicList *iter;
2412     int offset, i;
2413     char *namedata;
2414
2415     TRACE("(%p,%d,%s)\n", This, index, debugstr_w(szName));
2416
2417     if (cti2_get_var_count(This->typeinfo) <= index)
2418         return TYPE_E_ELEMENTNOTFOUND;
2419
2420     offset = ctl2_alloc_name(This->typelib, szName);
2421     if (offset == -1) return E_OUTOFMEMORY;
2422
2423     namedata = This->typelib->typelib_segment_data[MSFT_SEG_NAME] + offset;
2424     if (*((INT *)namedata) == -1) {
2425         *((INT *)namedata) = This->typelib->typelib_typeinfo_offsets[This->typeinfo->typekind >> 16];
2426         namedata[9] |= 0x10;
2427     }
2428     if (This->typekind == TKIND_ENUM) {
2429         namedata[9] |= 0x20;
2430     }
2431
2432     for(iter = This->typedata->next->next, i = 0; /* empty */; iter = iter->next)
2433         if (iter->type == CyclicListVar)
2434             if (i++ >= index)
2435                 break;
2436
2437     iter->name = offset;
2438     return S_OK;
2439 }
2440
2441 /******************************************************************************
2442  * ICreateTypeInfo2_SetTypeDescAlias {OLEAUT32}
2443  *
2444  *  See ICreateTypeInfo_SetTypeDescAlias.
2445  */
2446 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(
2447         ICreateTypeInfo2* iface,
2448         TYPEDESC* pTDescAlias)
2449 {
2450     ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
2451
2452     int encoded_typedesc;
2453     int width;
2454
2455     if (This->typekind != TKIND_ALIAS) {
2456         return TYPE_E_WRONGTYPEKIND;
2457     }
2458
2459     FIXME("(%p,%p), hack!\n", iface, pTDescAlias);
2460
2461     if (ctl2_encode_typedesc(This->typelib, pTDescAlias, &encoded_typedesc, &width, NULL, NULL) == -1) {
2462         return E_OUTOFMEMORY;
2463     }
2464
2465     This->typeinfo->size = width;
2466     This->typeinfo->datatype1 = encoded_typedesc;
2467
2468     return S_OK;
2469 }
2470
2471 /******************************************************************************
2472  * ICreateTypeInfo2_DefineFuncAsDllEntry {OLEAUT32}
2473  *
2474  *  See ICreateTypeInfo_DefineFuncAsDllEntry.
2475  */
2476 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(
2477         ICreateTypeInfo2* iface,
2478         UINT index,
2479         LPOLESTR szDllName,
2480         LPOLESTR szProcName)
2481 {
2482     FIXME("(%p,%d,%s,%s), stub!\n", iface, index, debugstr_w(szDllName), debugstr_w(szProcName));
2483     return E_OUTOFMEMORY;
2484 }
2485
2486 /******************************************************************************
2487  * ICreateTypeInfo2_SetFuncDocString {OLEAUT32}
2488  *
2489  *  See ICreateTypeInfo_SetFuncDocString.
2490  */
2491 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(
2492         ICreateTypeInfo2* iface,
2493         UINT index,
2494         LPOLESTR szDocString)
2495 {
2496     FIXME("(%p,%d,%s), stub!\n", iface, index, debugstr_w(szDocString));
2497     return E_OUTOFMEMORY;
2498 }
2499
2500 /******************************************************************************
2501  * ICreateTypeInfo2_SetVarDocString {OLEAUT32}
2502  *
2503  *  See ICreateTypeInfo_SetVarDocString.
2504  */
2505 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(
2506         ICreateTypeInfo2* iface,
2507         UINT index,
2508         LPOLESTR szDocString)
2509 {
2510     ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
2511
2512     FIXME("(%p,%d,%s), stub!\n", iface, index, debugstr_w(szDocString));
2513
2514     ctl2_alloc_string(This->typelib, szDocString);
2515
2516     return E_OUTOFMEMORY;
2517 }
2518
2519 /******************************************************************************
2520  * ICreateTypeInfo2_SetFuncHelpContext {OLEAUT32}
2521  *
2522  *  See ICreateTypeInfo_SetFuncHelpContext.
2523  */
2524 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(
2525         ICreateTypeInfo2* iface,
2526         UINT index,
2527         DWORD dwHelpContext)
2528 {
2529     ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
2530     CyclicList *func;
2531
2532     TRACE("(%p,%d,%d)\n", iface, index, dwHelpContext);
2533
2534     if(cti2_get_func_count(This->typeinfo) < index)
2535         return TYPE_E_ELEMENTNOTFOUND;
2536
2537     if(cti2_get_func_count(This->typeinfo) == index && This->typedata->type == CyclicListFunc)
2538         func = This->typedata;
2539     else
2540         for(func=This->typedata->next->next; func!=This->typedata; func=func->next)
2541             if (func->type == CyclicListFunc)
2542                 if(index-- == 0)
2543                     break;
2544
2545     This->typedata->next->u.val += funcrecord_reallochdr(&func->u.data, 7*sizeof(int));
2546     if(!func->u.data)
2547         return E_OUTOFMEMORY;
2548
2549     func->u.data[6] = dwHelpContext;
2550     return S_OK;
2551 }
2552
2553 /******************************************************************************
2554  * ICreateTypeInfo2_SetVarHelpContext {OLEAUT32}
2555  *
2556  *  See ICreateTypeInfo_SetVarHelpContext.
2557  */
2558 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(
2559         ICreateTypeInfo2* iface,
2560         UINT index,
2561         DWORD context)
2562 {
2563     ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
2564     CyclicList *iter;
2565
2566     TRACE("(%p,%d,%d)\n", This, index, context);
2567
2568     if (cti2_get_var_count(This->typeinfo) <= index)
2569         return TYPE_E_ELEMENTNOTFOUND;
2570
2571     for (iter = This->typedata->next->next; iter != This->typedata->next; iter = iter->next)
2572        if (iter->type == CyclicListVar)
2573        {
2574            if (index-- == 0)
2575            {
2576                iter->u.data[5] = context;
2577                return S_OK;
2578            }
2579        }
2580
2581     return TYPE_E_ELEMENTNOTFOUND;
2582 }
2583
2584 /******************************************************************************
2585  * ICreateTypeInfo2_SetMops {OLEAUT32}
2586  *
2587  *  See ICreateTypeInfo_SetMops.
2588  */
2589 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(
2590         ICreateTypeInfo2* iface,
2591         UINT index,
2592         BSTR bstrMops)
2593 {
2594     FIXME("(%p,%d,%p), stub!\n", iface, index, bstrMops);
2595     return E_OUTOFMEMORY;
2596 }
2597
2598 /******************************************************************************
2599  * ICreateTypeInfo2_SetTypeIdldesc {OLEAUT32}
2600  *
2601  *  See ICreateTypeInfo_SetTypeIdldesc.
2602  */
2603 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(
2604         ICreateTypeInfo2* iface,
2605         IDLDESC* pIdlDesc)
2606 {
2607     FIXME("(%p,%p), stub!\n", iface, pIdlDesc);
2608     return E_OUTOFMEMORY;
2609 }
2610
2611 /******************************************************************************
2612  * ICreateTypeInfo2_LayOut {OLEAUT32}
2613  *
2614  *  See ICreateTypeInfo_LayOut.
2615  */
2616 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(
2617         ICreateTypeInfo2* iface)
2618 {
2619     ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
2620     CyclicList *iter, *iter2, *last = NULL, **typedata;
2621     HREFTYPE hreftype;
2622     HRESULT hres;
2623     unsigned user_vft = 0;
2624     int i;
2625
2626     TRACE("(%p)\n", iface);
2627
2628     /* FIXME: LayOut should be run on all ImplTypes */
2629     if(This->typekind == TKIND_COCLASS)
2630         return S_OK;
2631
2632     /* Validate inheritance */
2633     This->typeinfo->datatype2 = 0;
2634     hreftype = This->typeinfo->datatype1;
2635
2636     /* Process internally defined interfaces */
2637     for(i=0; i<This->typelib->typelib_header.nrtypeinfos; i++) {
2638         MSFT_TypeInfoBase *header;
2639
2640         if(hreftype&1)
2641             break;
2642
2643         header = (MSFT_TypeInfoBase*)&(This->typelib->typelib_segment_data[MSFT_SEG_TYPEINFO][hreftype]);
2644         This->typeinfo->datatype2 += (header->cElement<<16) + 1;
2645         hreftype = header->datatype1;
2646     }
2647     if(i == This->typelib->typelib_header.nrtypeinfos)
2648         return TYPE_E_CIRCULARTYPE;
2649
2650     /* Process externally defined interfaces */
2651     if(hreftype != -1) {
2652         ITypeInfo *cur, *next;
2653         TYPEATTR *typeattr;
2654
2655         hres = ICreateTypeInfo_QueryInterface(iface, &IID_ITypeInfo, (void**)&next);
2656         if(FAILED(hres))
2657             return hres;
2658
2659         hres = ITypeInfo_GetRefTypeInfo(next, hreftype, &cur);
2660         ITypeInfo_Release(next);
2661         if(FAILED(hres))
2662             return hres;
2663
2664
2665         while(1) {
2666             hres = ITypeInfo_GetTypeAttr(cur, &typeattr);
2667             if(FAILED(hres)) {
2668                 ITypeInfo_Release(cur);
2669                 return hres;
2670             }
2671
2672             if(IsEqualGUID(&typeattr->guid, &IID_IDispatch))
2673                 This->typeinfo->flags |= TYPEFLAG_FDISPATCHABLE;
2674
2675             This->typeinfo->datatype2 += (typeattr->cFuncs<<16) + 1;
2676             ITypeInfo_ReleaseTypeAttr(cur, typeattr);
2677
2678             hres = ITypeInfo_GetRefTypeOfImplType(cur, 0, &hreftype);
2679             if(hres == TYPE_E_ELEMENTNOTFOUND)
2680                 break;
2681             if(FAILED(hres)) {
2682                 ITypeInfo_Release(cur);
2683                 return hres;
2684             }
2685
2686             hres = ITypeInfo_GetRefTypeInfo(cur, hreftype, &next);
2687             if(FAILED(hres)) {
2688                 ITypeInfo_Release(cur);
2689                 return hres;
2690             }
2691
2692             ITypeInfo_Release(cur);
2693             cur = next;
2694         }
2695         ITypeInfo_Release(cur);
2696     }
2697
2698     /* Get cbSizeVft of inherited interface */
2699     /* Makes LayOut running recursively */
2700     if(This->typeinfo->datatype1 != -1) {
2701         ITypeInfo *cur, *inherited;
2702         TYPEATTR *typeattr;
2703
2704         hres = ICreateTypeInfo_QueryInterface(iface, &IID_ITypeInfo, (void**)&cur);
2705         if(FAILED(hres))
2706             return hres;
2707
2708         hres = ITypeInfo_GetRefTypeInfo(cur, This->typeinfo->datatype1, &inherited);
2709         ITypeInfo_Release(cur);
2710         if(FAILED(hres))
2711             return hres;
2712
2713         hres = ITypeInfo_GetTypeAttr(inherited, &typeattr);
2714         if(FAILED(hres)) {
2715             ITypeInfo_Release(inherited);
2716             return hres;
2717         }
2718
2719         This->typeinfo->cbSizeVft = typeattr->cbSizeVft * 4 / sizeof(void *);
2720
2721         ITypeInfo_ReleaseTypeAttr(inherited, typeattr);
2722         ITypeInfo_Release(inherited);
2723     } else
2724         This->typeinfo->cbSizeVft = 0;
2725
2726     if(!This->typedata)
2727         return S_OK;
2728
2729     typedata = HeapAlloc(GetProcessHeap(), 0, sizeof(CyclicList*)*cti2_get_func_count(This->typeinfo));
2730     if(!typedata)
2731         return E_OUTOFMEMORY;
2732
2733     /* Assign IDs and VTBL entries */
2734     for(iter=This->typedata->next->next; iter!=This->typedata->next; iter=iter->next)
2735         if (iter->type == CyclicListFunc)
2736             last = iter;
2737
2738     if(last && last->u.data[3]&1)
2739         user_vft = last->u.data[3]&0xffff;
2740
2741     i = 0;
2742     for(iter=This->typedata->next->next; iter!=This->typedata->next; iter=iter->next) {
2743         /* Assign MEMBERID if MEMBERID_NIL was specified */
2744         if(iter->indice == MEMBERID_NIL) {
2745             iter->indice = 0x60000000 + i + (This->typeinfo->datatype2<<16);
2746
2747             for(iter2=This->typedata->next->next; iter2!=This->typedata->next; iter2=iter2->next) {
2748                 if(iter == iter2) continue;
2749                 if(iter2->indice == iter->indice) {
2750                     iter->indice = 0x60000000 + This->typeinfo->cElement + (This->typeinfo->datatype2<<16);
2751
2752                     for(iter2=This->typedata->next->next; iter2!=This->typedata->next; iter2=iter2->next) {
2753                         if(iter == iter2) continue;
2754                         if(iter2->indice == iter->indice) {
2755                             ++iter->indice;
2756                             iter2 = This->typedata->next;
2757                         }
2758                     }
2759
2760                     break;
2761                 }
2762             }
2763         }
2764
2765         if (iter->type != CyclicListFunc)
2766             continue;
2767
2768         typedata[i] = iter;
2769
2770         iter->u.data[0] = (iter->u.data[0]&0xffff) | (i<<16);
2771
2772         if((iter->u.data[3]&1) != (user_vft&1)) {
2773             HeapFree(GetProcessHeap(), 0, typedata);
2774             return TYPE_E_INVALIDID;
2775         }
2776
2777         if(user_vft&1) {
2778             if(user_vft < (iter->u.data[3]&0xffff))
2779                 user_vft = (iter->u.data[3]&0xffff);
2780
2781             if((iter->u.data[3]&0xffff) < This->typeinfo->cbSizeVft) {
2782                 HeapFree(GetProcessHeap(), 0, typedata);
2783                 return TYPE_E_INVALIDID;
2784             }
2785         } else if(This->typekind != TKIND_MODULE) {
2786             iter->u.data[3] = (iter->u.data[3]&0xffff0000) | This->typeinfo->cbSizeVft;
2787             This->typeinfo->cbSizeVft += 4;
2788         }
2789
2790         /* Construct a list of elements with the same memberid */
2791         iter->u.data[4] = (iter->u.data[4]&0xffff) | (i<<16);
2792         for(iter2=This->typedata->next->next; iter2!=iter; iter2=iter2->next) {
2793             if(iter->indice == iter2->indice) {
2794                 int v1, v2;
2795
2796                 v1 = iter->u.data[4] >> 16;
2797                 v2 = iter2->u.data[4] >> 16;
2798
2799                 iter->u.data[4] = (iter->u.data[4]&0xffff) | (v2<<16);
2800                 iter2->u.data[4] = (iter2->u.data[4]&0xffff) | (v1<<16);
2801                 break;
2802             }
2803         }
2804
2805         i++;
2806     }
2807
2808     if(user_vft)
2809         This->typeinfo->cbSizeVft = user_vft+3;
2810
2811     for(i=0; i< cti2_get_func_count(This->typeinfo); i++) {
2812         if(typedata[i]->u.data[4]>>16 > i) {
2813             INVOKEKIND inv = ctl2_get_invokekind(typedata[i]);
2814
2815             i = typedata[i]->u.data[4] >> 16;
2816
2817             while(i > typedata[i]->u.data[4]>>16) {
2818                 INVOKEKIND invkind = ctl2_get_invokekind(typedata[i]);
2819
2820                 if(inv & invkind) {
2821                     HeapFree(GetProcessHeap(), 0, typedata);
2822                     return TYPE_E_DUPLICATEID;
2823                 }
2824
2825                 i = typedata[i]->u.data[4] >> 16;
2826                 inv |= invkind;
2827             }
2828
2829             if(inv & INVOKE_FUNC) {
2830                 HeapFree(GetProcessHeap(), 0, typedata);
2831                 return TYPE_E_INCONSISTENTPROPFUNCS;
2832             }
2833         }
2834     }
2835
2836     HeapFree(GetProcessHeap(), 0, typedata);
2837     return S_OK;
2838 }
2839
2840 /******************************************************************************
2841  * ICreateTypeInfo2_DeleteFuncDesc {OLEAUT32}
2842  *
2843  *  Delete a function description from a type.
2844  *
2845  * RETURNS
2846  *
2847  *  Success: S_OK.
2848  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
2849  */
2850 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(
2851         ICreateTypeInfo2* iface, /* [I] The typeinfo from which to delete a function. */
2852         UINT index)              /* [I] The index of the function to delete. */
2853 {
2854     FIXME("(%p,%d), stub!\n", iface, index);
2855     return E_OUTOFMEMORY;
2856 }
2857
2858 /******************************************************************************
2859  * ICreateTypeInfo2_DeleteFuncDescByMemId {OLEAUT32}
2860  *
2861  *  Delete a function description from a type.
2862  *
2863  * RETURNS
2864  *
2865  *  Success: S_OK.
2866  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
2867  */
2868 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(
2869         ICreateTypeInfo2* iface, /* [I] The typeinfo from which to delete a function. */
2870         MEMBERID memid,          /* [I] The member id of the function to delete. */
2871         INVOKEKIND invKind)      /* [I] The invocation type of the function to delete. (?) */
2872 {
2873     FIXME("(%p,%d,%d), stub!\n", iface, memid, invKind);
2874     return E_OUTOFMEMORY;
2875 }
2876
2877 /******************************************************************************
2878  * ICreateTypeInfo2_DeleteVarDesc {OLEAUT32}
2879  *
2880  *  Delete a variable description from a type.
2881  *
2882  * RETURNS
2883  *
2884  *  Success: S_OK.
2885  *  Failure: One of E_OUTOFMEMORY, E_INVALIDARG, TYPE_E_IOERROR,
2886  *  TYPE_E_INVDATAREAD, TYPE_E_UNSUPFORMAT or TYPE_E_INVALIDSTATE.
2887  */
2888 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(
2889         ICreateTypeInfo2* iface, /* [I] The typeinfo from which to delete the variable description. */
2890         UINT index)              /* [I] The index of the variable description to delete. */
2891 {
2892     FIXME("(%p,%d), stub!\n", iface, index);
2893     return E_OUTOFMEMORY;
2894 }
2895
2896 /******************************************************************************
2897  * ICreateTypeInfo2_DeleteVarDescByMemId {OLEAUT32}
2898  *
2899  *  Delete a variable description from a type.
2900  *
2901  * RETURNS
2902  *
2903  *  Success: S_OK.
2904  *  Failure: One of E_OUTOFMEMORY, E_INVALIDARG, TYPE_E_IOERROR,
2905  *  TYPE_E_INVDATAREAD, TYPE_E_UNSUPFORMAT or TYPE_E_INVALIDSTATE.
2906  */
2907 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(
2908         ICreateTypeInfo2* iface, /* [I] The typeinfo from which to delete the variable description. */
2909         MEMBERID memid)          /* [I] The member id of the variable description to delete. */
2910 {
2911     FIXME("(%p,%d), stub!\n", iface, memid);
2912     return E_OUTOFMEMORY;
2913 }
2914
2915 /******************************************************************************
2916  * ICreateTypeInfo2_DeleteImplType {OLEAUT32}
2917  *
2918  *  Delete an interface implementation from a type. (?)
2919  *
2920  * RETURNS
2921  *
2922  *  Success: S_OK.
2923  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
2924  */
2925 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(
2926         ICreateTypeInfo2* iface, /* [I] The typeinfo from which to delete. */
2927         UINT index)              /* [I] The index of the interface to delete. */
2928 {
2929     FIXME("(%p,%d), stub!\n", iface, index);
2930     return E_OUTOFMEMORY;
2931 }
2932
2933 /******************************************************************************
2934  * ICreateTypeInfo2_SetCustData {OLEAUT32}
2935  *
2936  *  Set the custom data for a type.
2937  *
2938  * RETURNS
2939  *
2940  *  Success: S_OK.
2941  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
2942  */
2943 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(
2944         ICreateTypeInfo2* iface, /* [I] The typeinfo in which to set the custom data. */
2945         REFGUID guid,            /* [I] The GUID used as a key to retrieve the custom data. */
2946         VARIANT* pVarVal)        /* [I] The custom data. */
2947 {
2948     ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
2949
2950     TRACE("(%p,%s,%p)!\n", iface, debugstr_guid(guid), pVarVal);
2951
2952     if (!pVarVal)
2953             return E_INVALIDARG;
2954
2955     return ctl2_set_custdata(This->typelib, guid, pVarVal, &This->typeinfo->oCustData);
2956 }
2957
2958 /******************************************************************************
2959  * ICreateTypeInfo2_SetFuncCustData {OLEAUT32}
2960  *
2961  *  Set the custom data for a function.
2962  *
2963  * RETURNS
2964  *
2965  *  Success: S_OK.
2966  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
2967  */
2968 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(
2969         ICreateTypeInfo2* iface, /* [I] The typeinfo in which to set the custom data. */
2970         UINT index,              /* [I] The index of the function for which to set the custom data. */
2971         REFGUID guid,            /* [I] The GUID used as a key to retrieve the custom data. */
2972         VARIANT* pVarVal)        /* [I] The custom data. */
2973 {
2974     ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
2975     CyclicList *iter;
2976
2977     TRACE("(%p,%d,%s,%p)\n", iface, index, debugstr_guid(guid), pVarVal);
2978
2979     if(index >= cti2_get_func_count(This->typeinfo))
2980         return TYPE_E_ELEMENTNOTFOUND;
2981
2982     for(iter=This->typedata->next->next; /* empty */; iter=iter->next)
2983         if (iter->type == CyclicListFunc)
2984             if (index-- == 0)
2985                 break;
2986
2987     This->typedata->next->u.val += funcrecord_reallochdr(&iter->u.data, 13*sizeof(int));
2988     if(!iter->u.data)
2989         return E_OUTOFMEMORY;
2990
2991     iter->u.data[4] |= 0x80;
2992     return ctl2_set_custdata(This->typelib, guid, pVarVal, &iter->u.data[12]);
2993 }
2994
2995 /******************************************************************************
2996  * ICreateTypeInfo2_SetParamCustData {OLEAUT32}
2997  *
2998  *  Set the custom data for a function parameter.
2999  *
3000  * RETURNS
3001  *
3002  *  Success: S_OK.
3003  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
3004  */
3005 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(
3006         ICreateTypeInfo2* iface, /* [I] The typeinfo in which to set the custom data. */
3007         UINT indexFunc,          /* [I] The index of the function on which the parameter resides. */
3008         UINT indexParam,         /* [I] The index of the parameter on which to set the custom data. */
3009         REFGUID guid,            /* [I] The GUID used as a key to retrieve the custom data. */
3010         VARIANT* pVarVal)        /* [I] The custom data. */
3011 {
3012     FIXME("(%p,%d,%d,%s,%p), stub!\n", iface, indexFunc, indexParam, debugstr_guid(guid), pVarVal);
3013     return E_OUTOFMEMORY;
3014 }
3015
3016 /******************************************************************************
3017  * ICreateTypeInfo2_SetVarCustData {OLEAUT32}
3018  *
3019  *  Set the custom data for a variable.
3020  *
3021  * RETURNS
3022  *
3023  *  Success: S_OK.
3024  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
3025  */
3026 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(
3027         ICreateTypeInfo2* iface, /* [I] The typeinfo in which to set the custom data. */
3028         UINT index,              /* [I] The index of the variable on which to set the custom data. */
3029         REFGUID guid,            /* [I] The GUID used as a key to retrieve the custom data. */
3030         VARIANT* pVarVal)        /* [I] The custom data. */
3031 {
3032     FIXME("(%p,%d,%s,%p), stub!\n", iface, index, debugstr_guid(guid), pVarVal);
3033     return E_OUTOFMEMORY;
3034 }
3035
3036 /******************************************************************************
3037  * ICreateTypeInfo2_SetImplTypeCustData {OLEAUT32}
3038  *
3039  *  Set the custom data for an implemented interface.
3040  *
3041  * RETURNS
3042  *
3043  *  Success: S_OK.
3044  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
3045  */
3046 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(
3047         ICreateTypeInfo2* iface, /* [I] The typeinfo on which to set the custom data. */
3048         UINT index,              /* [I] The index of the implemented interface on which to set the custom data. */
3049         REFGUID guid,            /* [I] The GUID used as a key to retrieve the custom data. */
3050         VARIANT* pVarVal)        /* [I] The custom data. */
3051 {
3052     FIXME("(%p,%d,%s,%p), stub!\n", iface, index, debugstr_guid(guid), pVarVal);
3053     return E_OUTOFMEMORY;
3054 }
3055
3056 /******************************************************************************
3057  * ICreateTypeInfo2_SetHelpStringContext {OLEAUT32}
3058  *
3059  *  Set the help string context for the typeinfo.
3060  *
3061  * RETURNS
3062  *
3063  *  Success: S_OK.
3064  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
3065  */
3066 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(
3067         ICreateTypeInfo2* iface,   /* [I] The typeinfo on which to set the help string context. */
3068         ULONG dwHelpStringContext) /* [I] The help string context. */
3069 {
3070     FIXME("(%p,%d), stub!\n", iface, dwHelpStringContext);
3071     return E_OUTOFMEMORY;
3072 }
3073
3074 /******************************************************************************
3075  * ICreateTypeInfo2_SetFuncHelpStringContext {OLEAUT32}
3076  *
3077  *  Set the help string context for a function.
3078  *
3079  * RETURNS
3080  *
3081  *  Success: S_OK.
3082  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
3083  */
3084 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(
3085         ICreateTypeInfo2* iface,   /* [I] The typeinfo on which to set the help string context. */
3086         UINT index,                /* [I] The index for the function on which to set the help string context. */
3087         ULONG dwHelpStringContext) /* [I] The help string context. */
3088 {
3089     FIXME("(%p,%d,%d), stub!\n", iface, index, dwHelpStringContext);
3090     return E_OUTOFMEMORY;
3091 }
3092
3093 /******************************************************************************
3094  * ICreateTypeInfo2_SetVarHelpStringContext {OLEAUT32}
3095  *
3096  *  Set the help string context for a variable.
3097  *
3098  * RETURNS
3099  *
3100  *  Success: S_OK.
3101  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
3102  */
3103 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(
3104         ICreateTypeInfo2* iface,   /* [I] The typeinfo on which to set the help string context. */
3105         UINT index,                /* [I] The index of the variable on which to set the help string context. */
3106         ULONG dwHelpStringContext) /* [I] The help string context */
3107 {
3108     FIXME("(%p,%d,%d), stub!\n", iface, index, dwHelpStringContext);
3109     return E_OUTOFMEMORY;
3110 }
3111
3112 /******************************************************************************
3113  * ICreateTypeInfo2_Invalidate {OLEAUT32}
3114  *
3115  *  Undocumented function. (!)
3116  */
3117 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(
3118         ICreateTypeInfo2* iface)
3119 {
3120     FIXME("(%p), stub!\n", iface);
3121     return E_OUTOFMEMORY;
3122 }
3123
3124 /******************************************************************************
3125  * ICreateTypeInfo2_SetName {OLEAUT32}
3126  *
3127  *  Set the name for a typeinfo.
3128  *
3129  * RETURNS
3130  *
3131  *  Success: S_OK.
3132  *  Failure: One of STG_E_INSUFFICIENTMEMORY, E_OUTOFMEMORY, E_INVALIDARG or TYPE_E_INVALIDSTATE.
3133  */
3134 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(
3135         ICreateTypeInfo2* iface,
3136         LPOLESTR szName)
3137 {
3138     FIXME("(%p,%s), stub!\n", iface, debugstr_w(szName));
3139     return E_OUTOFMEMORY;
3140 }
3141
3142 /*================== ITypeInfo2 Implementation ===================================*/
3143
3144 /******************************************************************************
3145  * ITypeInfo2_QueryInterface {OLEAUT32}
3146  *
3147  *  See IUnknown_QueryInterface.
3148  */
3149 static HRESULT WINAPI ITypeInfo2_fnQueryInterface(ITypeInfo2 * iface, REFIID riid, LPVOID * ppv)
3150 {
3151     ICreateTypeInfo2Impl *This = impl_from_ITypeInfo2(iface);
3152
3153     return ICreateTypeInfo2_QueryInterface((ICreateTypeInfo2 *)This, riid, ppv);
3154 }
3155
3156 /******************************************************************************
3157  * ITypeInfo2_AddRef {OLEAUT32}
3158  *
3159  *  See IUnknown_AddRef.
3160  */
3161 static ULONG WINAPI ITypeInfo2_fnAddRef(ITypeInfo2 * iface)
3162 {
3163     ICreateTypeInfo2Impl *This = impl_from_ITypeInfo2(iface);
3164
3165     return ICreateTypeInfo2_AddRef((ICreateTypeInfo2 *)This);
3166 }
3167
3168 /******************************************************************************
3169  * ITypeInfo2_Release {OLEAUT32}
3170  *
3171  *  See IUnknown_Release.
3172  */
3173 static ULONG WINAPI ITypeInfo2_fnRelease(ITypeInfo2 * iface)
3174 {
3175     ICreateTypeInfo2Impl *This = impl_from_ITypeInfo2(iface);
3176
3177     return ICreateTypeInfo2_Release((ICreateTypeInfo2 *)This);
3178 }
3179
3180 /******************************************************************************
3181  * ITypeInfo2_GetTypeAttr {OLEAUT32}
3182  *
3183  *  See ITypeInfo_GetTypeAttr.
3184  */
3185 static HRESULT WINAPI ITypeInfo2_fnGetTypeAttr(
3186         ITypeInfo2* iface,
3187         TYPEATTR** ppTypeAttr)
3188 {
3189     ICreateTypeInfo2Impl *This = impl_from_ITypeInfo2(iface);
3190     HRESULT hres;
3191
3192     TRACE("(%p,%p)\n", iface, ppTypeAttr);
3193
3194     if(!ppTypeAttr)
3195         return E_INVALIDARG;
3196
3197     hres = ICreateTypeInfo_LayOut((ICreateTypeInfo*)This);
3198     if(FAILED(hres))
3199         return hres;
3200
3201     *ppTypeAttr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TYPEATTR));
3202     if(!*ppTypeAttr)
3203         return E_OUTOFMEMORY;
3204
3205     if(This->typeinfo->posguid != -1) {
3206         MSFT_GuidEntry *guid;
3207
3208         guid = (MSFT_GuidEntry*)&This->typelib->typelib_segment_data[MSFT_SEG_GUID][This->typeinfo->posguid];
3209         (*ppTypeAttr)->guid = guid->guid;
3210     }
3211
3212     (*ppTypeAttr)->lcid = This->typelib->typelib_header.lcid;
3213     (*ppTypeAttr)->cbSizeInstance = This->typeinfo->size;
3214     (*ppTypeAttr)->typekind = This->typekind;
3215     (*ppTypeAttr)->cFuncs = cti2_get_func_count(This->typeinfo);
3216     if(This->typeinfo->flags&TYPEFLAG_FDUAL && This->typekind==TKIND_DISPATCH)
3217         (*ppTypeAttr)->cFuncs += 7;
3218     (*ppTypeAttr)->cVars = cti2_get_var_count(This->typeinfo);
3219     (*ppTypeAttr)->cImplTypes = This->typeinfo->cImplTypes;
3220     (*ppTypeAttr)->cbSizeVft = This->typekind==TKIND_DISPATCH ? 7 * sizeof(void*) : This->typeinfo->cbSizeVft;
3221     (*ppTypeAttr)->cbAlignment = (This->typeinfo->typekind>>11) & 0x1f;
3222     (*ppTypeAttr)->wTypeFlags = This->typeinfo->flags;
3223     (*ppTypeAttr)->wMajorVerNum = LOWORD(This->typeinfo->version);
3224     (*ppTypeAttr)->wMinorVerNum = HIWORD(This->typeinfo->version);
3225
3226     if((*ppTypeAttr)->typekind == TKIND_ALIAS)
3227         FIXME("TKIND_ALIAS handling not implemented\n");
3228
3229     return S_OK;
3230 }
3231
3232 /******************************************************************************
3233  * ITypeInfo2_GetTypeComp {OLEAUT32}
3234  *
3235  *  See ITypeInfo_GetTypeComp.
3236  */
3237 static HRESULT WINAPI ITypeInfo2_fnGetTypeComp(
3238         ITypeInfo2* iface,
3239         ITypeComp** ppTComp)
3240 {
3241     FIXME("(%p,%p), stub!\n", iface, ppTComp);
3242     return E_OUTOFMEMORY;
3243 }
3244
3245 /******************************************************************************
3246  * ITypeInfo2_GetFuncDesc {OLEAUT32}
3247  *
3248  *  See ITypeInfo_GetFuncDesc.
3249  */
3250 static HRESULT WINAPI ITypeInfo2_fnGetFuncDesc(
3251         ITypeInfo2* iface,
3252         UINT index,
3253         FUNCDESC** ppFuncDesc)
3254 {
3255     ICreateTypeInfo2Impl *This = impl_from_ITypeInfo2(iface);
3256     int i, *typedata, num_defaults = 0, hdr_len, tail, has_defaults;
3257     CyclicList *desc;
3258     HRESULT hres;
3259
3260     TRACE("(%p,%d,%p), semi-stub\n", iface, index, ppFuncDesc);
3261
3262     if (!ppFuncDesc)
3263         return E_INVALIDARG;
3264
3265     if (index >= cti2_get_func_count(This->typeinfo))
3266         return TYPE_E_ELEMENTNOTFOUND;
3267
3268     hres = ICreateTypeInfo2_LayOut((ICreateTypeInfo2*)This);
3269     if (FAILED(hres))
3270         return hres;
3271
3272     desc = This->typedata->next;
3273     for (i = index; i >= 0; ) {
3274         desc = desc->next;
3275         if (desc->type == CyclicListFunc)
3276             --i;
3277     }
3278
3279     typedata = desc->u.data;
3280
3281     *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FUNCDESC));
3282     if (!*ppFuncDesc)
3283         return E_OUTOFMEMORY;
3284
3285     (*ppFuncDesc)->memid = desc->indice;
3286     (*ppFuncDesc)->lprgscode = NULL; /* FIXME: Unimplemented */
3287     (*ppFuncDesc)->funckind = typedata[4] & 0x7;
3288     (*ppFuncDesc)->invkind = (typedata[4] >> 3) & 0xF;
3289     (*ppFuncDesc)->callconv = (typedata[4] >> 8) & 0xF;
3290     (*ppFuncDesc)->cParams = typedata[5];
3291     (*ppFuncDesc)->cParamsOpt = 0; /* FIXME: Unimplemented*/
3292     (*ppFuncDesc)->oVft = typedata[3] & 0xFFFF;
3293     if ((*ppFuncDesc)->oVft)
3294         --(*ppFuncDesc)->oVft;
3295     (*ppFuncDesc)->cScodes = 0; /* FIXME: Unimplemented*/
3296     hres = ctl2_decode_typedesc(This->typelib, typedata[1],
3297             &(*ppFuncDesc)->elemdescFunc.tdesc);
3298     if (FAILED(hres)) {
3299         HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3300         return hres;
3301     }
3302     (*ppFuncDesc)->wFuncFlags = typedata[2];
3303
3304     has_defaults = typedata[4] & 0x1000;
3305     tail = typedata[5] * (has_defaults ? 16 : 12);
3306     hdr_len = ((typedata[0] & 0xFFFF) - tail) / sizeof(int);
3307
3308     if ((*ppFuncDesc)->cParams > 0) {
3309         (*ppFuncDesc)->lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (*ppFuncDesc)->cParams * sizeof(ELEMDESC));
3310         if (!(*ppFuncDesc)->lprgelemdescParam) {
3311             HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3312             return E_OUTOFMEMORY;
3313         }
3314         if (has_defaults) {
3315             num_defaults = (*ppFuncDesc)->cParams;
3316
3317             for (i = 0; i < num_defaults; ++i) {
3318                 if (typedata[hdr_len + i] != 0xFFFFFFFF) {
3319                     (*ppFuncDesc)->lprgelemdescParam[i].u.paramdesc.wParamFlags |= PARAMFLAG_FHASDEFAULT;
3320
3321                     (*ppFuncDesc)->lprgelemdescParam[i].u.paramdesc.pparamdescex = HeapAlloc(GetProcessHeap(), 0, sizeof(PARAMDESCEX));
3322                     if (!(*ppFuncDesc)->lprgelemdescParam[i].u.paramdesc.pparamdescex) {
3323                         ITypeInfo2_ReleaseFuncDesc(iface, *ppFuncDesc);
3324                         return E_OUTOFMEMORY;
3325                     }
3326
3327                     (*ppFuncDesc)->lprgelemdescParam[i].u.paramdesc.pparamdescex->cBytes = sizeof(PARAMDESCEX);
3328                     hres = ctl2_decode_variant(This->typelib, typedata[hdr_len + i],
3329                             &(*ppFuncDesc)->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
3330                     if (FAILED(hres)) {
3331                         ITypeInfo2_ReleaseFuncDesc(iface, *ppFuncDesc);
3332                         return hres;
3333                     }
3334                 }
3335             }
3336         }
3337
3338         for (i = 0; i < (*ppFuncDesc)->cParams; ++i) {
3339             hres = ctl2_decode_typedesc(This->typelib, typedata[hdr_len + num_defaults + (i * 3)],
3340                     &((*ppFuncDesc)->lprgelemdescParam + i)->tdesc);
3341             if (FAILED(hres)) {
3342                 ITypeInfo2_ReleaseFuncDesc(iface, *ppFuncDesc);
3343                 return hres;
3344             }
3345             (*ppFuncDesc)->lprgelemdescParam[i].u.paramdesc.wParamFlags = typedata[hdr_len + num_defaults + (i * 3) + 2];
3346         }
3347     }
3348
3349     return S_OK;
3350 }
3351
3352 /******************************************************************************
3353  * ITypeInfo2_GetVarDesc {OLEAUT32}
3354  *
3355  *  See ITypeInfo_GetVarDesc.
3356  */
3357 static HRESULT WINAPI ITypeInfo2_fnGetVarDesc(
3358         ITypeInfo2* iface,
3359         UINT index,
3360         VARDESC** ppVarDesc)
3361 {
3362     FIXME("(%p,%d,%p), stub!\n", iface, index, ppVarDesc);
3363     return E_OUTOFMEMORY;
3364 }
3365
3366 /******************************************************************************
3367  * ITypeInfo2_GetNames {OLEAUT32}
3368  *
3369  *  See ITypeInfo_GetNames.
3370  */
3371 static HRESULT WINAPI ITypeInfo2_fnGetNames(
3372         ITypeInfo2* iface,
3373         MEMBERID memid,
3374         BSTR* rgBstrNames,
3375         UINT cMaxNames,
3376         UINT* pcNames)
3377 {
3378     FIXME("(%p,%d,%p,%d,%p), stub!\n", iface, memid, rgBstrNames, cMaxNames, pcNames);
3379     return E_OUTOFMEMORY;
3380 }
3381
3382 /******************************************************************************
3383  * ITypeInfo2_GetRefTypeOfImplType {OLEAUT32}
3384  *
3385  *  See ITypeInfo_GetRefTypeOfImplType.
3386  */
3387 static HRESULT WINAPI ITypeInfo2_fnGetRefTypeOfImplType(
3388         ITypeInfo2* iface,
3389         UINT index,
3390         HREFTYPE* pRefType)
3391 {
3392     ICreateTypeInfo2Impl *This = impl_from_ITypeInfo2(iface);
3393     MSFT_RefRecord *ref;
3394     int offset;
3395
3396     TRACE("(%p,%d,%p)\n", iface, index, pRefType);
3397
3398     if(!pRefType)
3399         return E_INVALIDARG;
3400
3401     if(This->typeinfo->flags&TYPEFLAG_FDUAL) {
3402         if(index == -1) {
3403             *pRefType = -2;
3404             return S_OK;
3405         }
3406
3407         if(This->typekind == TKIND_DISPATCH)
3408             return ITypeInfo2_GetRefTypeOfImplType((ITypeInfo2*)&This->dual->lpVtblTypeInfo2,
3409                     index, pRefType);
3410     }
3411
3412     if(index>=This->typeinfo->cImplTypes)
3413         return TYPE_E_ELEMENTNOTFOUND;
3414
3415     if(This->typekind == TKIND_INTERFACE) {
3416         *pRefType = This->typeinfo->datatype1 + 2;
3417         return S_OK;
3418     }
3419
3420     offset = ctl2_find_nth_reference(This->typelib, This->typeinfo->datatype1, index);
3421     if(offset == -1)
3422         return TYPE_E_ELEMENTNOTFOUND;
3423
3424     ref = (MSFT_RefRecord *)&This->typelib->typelib_segment_data[MSFT_SEG_REFERENCES][offset];
3425     *pRefType = ref->reftype;
3426     return S_OK;
3427 }
3428
3429 /******************************************************************************
3430  * ITypeInfo2_GetImplTypeFlags {OLEAUT32}
3431  *
3432  *  See ITypeInfo_GetImplTypeFlags.
3433  */
3434 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeFlags(
3435         ITypeInfo2* iface,
3436         UINT index,
3437         INT* pImplTypeFlags)
3438 {
3439     ICreateTypeInfo2Impl *This = impl_from_ITypeInfo2(iface);
3440     int offset;
3441     MSFT_RefRecord *ref;
3442
3443     TRACE("(%p,%d,%p)\n", iface, index, pImplTypeFlags);
3444
3445     if(!pImplTypeFlags)
3446         return E_INVALIDARG;
3447
3448     if(index >= This->typeinfo->cImplTypes)
3449         return TYPE_E_ELEMENTNOTFOUND;
3450
3451     if(This->typekind != TKIND_COCLASS) {
3452         *pImplTypeFlags = 0;
3453         return S_OK;
3454     }
3455
3456     offset = ctl2_find_nth_reference(This->typelib, This->typeinfo->datatype1, index);
3457     if(offset == -1)
3458         return TYPE_E_ELEMENTNOTFOUND;
3459
3460     ref = (MSFT_RefRecord *)&This->typelib->typelib_segment_data[MSFT_SEG_REFERENCES][offset];
3461     *pImplTypeFlags = ref->flags;
3462     return S_OK;
3463 }
3464
3465 /******************************************************************************
3466  * ITypeInfo2_GetIDsOfNames {OLEAUT32}
3467  *
3468  *  See ITypeInfo_GetIDsOfNames.
3469  */
3470 static HRESULT WINAPI ITypeInfo2_fnGetIDsOfNames(
3471         ITypeInfo2* iface,
3472         LPOLESTR* rgszNames,
3473         UINT cNames,
3474         MEMBERID* pMemId)
3475 {
3476     FIXME("(%p,%p,%d,%p), stub!\n", iface, rgszNames, cNames, pMemId);
3477     return E_OUTOFMEMORY;
3478 }
3479
3480 /******************************************************************************
3481  * ITypeInfo2_Invoke {OLEAUT32}
3482  *
3483  *  See ITypeInfo_Invoke.
3484  */
3485 static HRESULT WINAPI ITypeInfo2_fnInvoke(
3486         ITypeInfo2* iface,
3487         PVOID pvInstance,
3488         MEMBERID memid,
3489         WORD wFlags,
3490         DISPPARAMS* pDispParams,
3491         VARIANT* pVarResult,
3492         EXCEPINFO* pExcepInfo,
3493         UINT* puArgErr)
3494 {
3495     FIXME("(%p,%p,%d,%x,%p,%p,%p,%p), stub!\n", iface, pvInstance, memid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
3496     return E_OUTOFMEMORY;
3497 }
3498
3499 /******************************************************************************
3500  * ITypeInfo2_GetDocumentation {OLEAUT32}
3501  *
3502  *  See ITypeInfo_GetDocumentation.
3503  */
3504 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation(
3505         ITypeInfo2* iface,
3506         MEMBERID memid,
3507         BSTR* pBstrName,
3508         BSTR* pBstrDocString,
3509         DWORD* pdwHelpContext,
3510         BSTR* pBstrHelpFile)
3511 {
3512     ICreateTypeInfo2Impl *This = impl_from_ITypeInfo2(iface);
3513     HRESULT status = TYPE_E_ELEMENTNOTFOUND;
3514     INT nameoffset, docstringoffset, helpcontext;
3515
3516     TRACE("(%p,%d,%p,%p,%p,%p)\n", iface, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
3517
3518     if (memid == -1)
3519     {
3520         nameoffset = This->typeinfo->NameOffset;
3521         docstringoffset = This->typeinfo->docstringoffs;
3522         helpcontext = This->typeinfo->helpcontext;
3523         status = S_OK;
3524     } else {
3525         CyclicList *iter;
3526         if (This->typedata) {
3527             for(iter=This->typedata->next->next; iter!=This->typedata->next; iter=iter->next) {
3528                 if (iter->indice == memid) {
3529                     if (iter->type == CyclicListFunc) {
3530                         const int *typedata = iter->u.data;
3531                         int   size = (typedata[0]&0xFFFF) - typedata[5]*(typedata[4]&0x1000?16:12);
3532
3533                         nameoffset = iter->name;
3534                         /* FIXME implement this once SetFuncDocString is implemented */
3535                         docstringoffset = -1;
3536                         helpcontext = (size < 7*sizeof(int)) ? 0 : typedata[6];
3537
3538                         status = S_OK;
3539                     } else {
3540                         FIXME("Not implemented for variable members\n");
3541                     }
3542
3543                     break;
3544                 }
3545             }
3546         }
3547     }
3548
3549     if (!status) {
3550         WCHAR *string;
3551         if (pBstrName) {
3552             if (nameoffset == -1)
3553                 *pBstrName = NULL;
3554             else {
3555                 MSFT_NameIntro *name = (MSFT_NameIntro*)&This->typelib->
3556                         typelib_segment_data[MSFT_SEG_NAME][nameoffset];
3557                 ctl2_decode_name((char*)&name->namelen, &string);
3558                 *pBstrName = SysAllocString(string);
3559                 if(!*pBstrName)
3560                     return E_OUTOFMEMORY;
3561             }
3562         }
3563
3564         if (pBstrDocString) {
3565             if (docstringoffset == -1)
3566                 *pBstrDocString = NULL;
3567             else {
3568                 MSFT_NameIntro *name = (MSFT_NameIntro*)&This->typelib->
3569                         typelib_segment_data[MSFT_SEG_NAME][docstringoffset];
3570                 ctl2_decode_name((char*)&name->namelen, &string);
3571                 *pBstrDocString = SysAllocString(string);
3572                 if(!*pBstrDocString) {
3573                     if (pBstrName) SysFreeString(*pBstrName);
3574                     return E_OUTOFMEMORY;
3575                 }
3576             }
3577         }
3578
3579         if (pdwHelpContext) {
3580             *pdwHelpContext = helpcontext;
3581         }
3582
3583         if (pBstrHelpFile) {
3584             status = ITypeLib_GetDocumentation((ITypeLib*)&This->typelib->lpVtblTypeLib2,
3585                     -1, NULL, NULL, NULL, pBstrHelpFile);
3586             if (status) {
3587                 if (pBstrName) SysFreeString(*pBstrName);
3588                 if (pBstrDocString) SysFreeString(*pBstrDocString);
3589             }
3590         }
3591     }
3592
3593     return status;
3594 }
3595
3596 /******************************************************************************
3597  * ITypeInfo2_GetDllEntry {OLEAUT32}
3598  *
3599  *  See ITypeInfo_GetDllEntry.
3600  */
3601 static HRESULT WINAPI ITypeInfo2_fnGetDllEntry(
3602         ITypeInfo2* iface,
3603         MEMBERID memid,
3604         INVOKEKIND invKind,
3605         BSTR* pBstrDllName,
3606         BSTR* pBstrName,
3607         WORD* pwOrdinal)
3608 {
3609     FIXME("(%p,%d,%d,%p,%p,%p), stub!\n", iface, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
3610     return E_OUTOFMEMORY;
3611 }
3612
3613 /******************************************************************************
3614  * ITypeInfo2_GetRefTypeInfo {OLEAUT32}
3615  *
3616  *  See ITypeInfo_GetRefTypeInfo.
3617  */
3618 static HRESULT WINAPI ITypeInfo2_fnGetRefTypeInfo(
3619         ITypeInfo2* iface,
3620         HREFTYPE hRefType,
3621         ITypeInfo** ppTInfo)
3622 {
3623     ICreateTypeInfo2Impl *This = impl_from_ITypeInfo2(iface);
3624
3625     TRACE("(%p,%d,%p)\n", iface, hRefType, ppTInfo);
3626
3627     if(!ppTInfo)
3628         return E_INVALIDARG;
3629
3630     if(hRefType==-2 && This->dual) {
3631         *ppTInfo = (ITypeInfo*)&This->dual->lpVtblTypeInfo2;
3632         ITypeInfo_AddRef(*ppTInfo);
3633         return S_OK;
3634     }
3635
3636     if(hRefType&1) {
3637         ITypeLib *tl;
3638         MSFT_ImpInfo *impinfo;
3639         MSFT_ImpFile *impfile;
3640         MSFT_GuidEntry *guid;
3641         WCHAR *filename;
3642         HRESULT hres;
3643
3644         if((hRefType&(~0x3)) >= This->typelib->typelib_segdir[MSFT_SEG_IMPORTINFO].length)
3645             return E_FAIL;
3646
3647         impinfo = (MSFT_ImpInfo*)&This->typelib->typelib_segment_data[MSFT_SEG_IMPORTINFO][hRefType&(~0x3)];
3648         impfile = (MSFT_ImpFile*)&This->typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][impinfo->oImpFile];
3649         guid = (MSFT_GuidEntry*)&This->typelib->typelib_segment_data[MSFT_SEG_GUID][impinfo->oGuid];
3650
3651         ctl2_decode_string(impfile->filename, &filename);
3652
3653         hres = LoadTypeLib(filename, &tl);
3654         if(FAILED(hres))
3655             return hres;
3656
3657         hres = ITypeLib_GetTypeInfoOfGuid(tl, &guid->guid, ppTInfo);
3658
3659         ITypeLib_Release(tl);
3660         return hres;
3661     } else {
3662         ICreateTypeInfo2Impl *iter;
3663         int i = 0;
3664
3665         for(iter=This->typelib->typeinfos; iter; iter=iter->next_typeinfo) {
3666             if(This->typelib->typelib_typeinfo_offsets[i] == (hRefType&(~0x3))) {
3667                 *ppTInfo = (ITypeInfo*)&iter->lpVtblTypeInfo2;
3668
3669                 ITypeLib_AddRef(*ppTInfo);
3670                 return S_OK;
3671             }
3672             i++;
3673         }
3674     }
3675
3676     return E_FAIL;
3677 }
3678
3679 /******************************************************************************
3680  * ITypeInfo2_AddressOfMember {OLEAUT32}
3681  *
3682  *  See ITypeInfo_AddressOfMember.
3683  */
3684 static HRESULT WINAPI ITypeInfo2_fnAddressOfMember(
3685         ITypeInfo2* iface,
3686         MEMBERID memid,
3687         INVOKEKIND invKind,
3688         PVOID* ppv)
3689 {
3690     FIXME("(%p,%d,%d,%p), stub!\n", iface, memid, invKind, ppv);
3691     return E_OUTOFMEMORY;
3692 }
3693
3694 /******************************************************************************
3695  * ITypeInfo2_CreateInstance {OLEAUT32}
3696  *
3697  *  See ITypeInfo_CreateInstance.
3698  */
3699 static HRESULT WINAPI ITypeInfo2_fnCreateInstance(
3700         ITypeInfo2* iface,
3701         IUnknown* pUnkOuter,
3702         REFIID riid,
3703         PVOID* ppvObj)
3704 {
3705     FIXME("(%p,%p,%s,%p), stub!\n", iface, pUnkOuter, debugstr_guid(riid), ppvObj);
3706     return E_OUTOFMEMORY;
3707 }
3708
3709 /******************************************************************************
3710  * ITypeInfo2_GetMops {OLEAUT32}
3711  *
3712  *  See ITypeInfo_GetMops.
3713  */
3714 static HRESULT WINAPI ITypeInfo2_fnGetMops(
3715         ITypeInfo2* iface,
3716         MEMBERID memid,
3717         BSTR* pBstrMops)
3718 {
3719     FIXME("(%p,%d,%p), stub!\n", iface, memid, pBstrMops);
3720     return E_OUTOFMEMORY;
3721 }
3722
3723 /******************************************************************************
3724  * ITypeInfo2_GetContainingTypeLib {OLEAUT32}
3725  *
3726  *  See ITypeInfo_GetContainingTypeLib.
3727  */
3728 static HRESULT WINAPI ITypeInfo2_fnGetContainingTypeLib(
3729         ITypeInfo2* iface,
3730         ITypeLib** ppTLib,
3731         UINT* pIndex)
3732 {
3733     ICreateTypeInfo2Impl *This = impl_from_ITypeInfo2(iface);
3734
3735     TRACE("(%p,%p,%p)\n", iface, ppTLib, pIndex);
3736     
3737     *ppTLib = (ITypeLib *)&This->typelib->lpVtblTypeLib2;
3738     ICreateTypeLib_AddRef((ICreateTypeLib*)This->typelib);
3739     *pIndex = This->typeinfo->typekind >> 16;
3740
3741     return S_OK;
3742 }
3743
3744 static void release_typedesc(TYPEDESC *tdesc)
3745 {
3746     while (tdesc) {
3747         TYPEDESC *next;
3748         if (tdesc->vt == VT_USERDEFINED)
3749             next = NULL;
3750         else
3751             next = tdesc->u.lptdesc;
3752         HeapFree(GetProcessHeap(), 0, tdesc);
3753         tdesc = next;
3754     }
3755 }
3756
3757 /******************************************************************************
3758  * ITypeInfo2_ReleaseTypeAttr {OLEAUT32}
3759  *
3760  *  See ITypeInfo_ReleaseTypeAttr.
3761  */
3762 static void WINAPI ITypeInfo2_fnReleaseTypeAttr(
3763         ITypeInfo2* iface,
3764         TYPEATTR* pTypeAttr)
3765 {
3766     TRACE("(%p,%p)\n", iface, pTypeAttr);
3767
3768     if (pTypeAttr->tdescAlias.vt != VT_USERDEFINED)
3769         release_typedesc(pTypeAttr->tdescAlias.u.lptdesc);
3770
3771     HeapFree(GetProcessHeap(), 0, pTypeAttr);
3772 }
3773
3774 /******************************************************************************
3775  * ITypeInfo2_ReleaseFuncDesc {OLEAUT32}
3776  *
3777  *  See ITypeInfo_ReleaseFuncDesc.
3778  */
3779 static void WINAPI ITypeInfo2_fnReleaseFuncDesc(
3780         ITypeInfo2* iface,
3781         FUNCDESC* pFuncDesc)
3782 {
3783     int i;
3784
3785     TRACE("(%p,%p)\n", iface, pFuncDesc);
3786
3787     HeapFree(GetProcessHeap(), 0, pFuncDesc->lprgscode);
3788
3789     if (pFuncDesc->lprgelemdescParam) {
3790         for (i = 0; i < pFuncDesc->cParams; ++i) {
3791             if (pFuncDesc->lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED)
3792                 release_typedesc(pFuncDesc->lprgelemdescParam[i].tdesc.u.lptdesc);
3793
3794             HeapFree(GetProcessHeap(), 0, pFuncDesc->lprgelemdescParam[i].u.paramdesc.pparamdescex);
3795         }
3796         HeapFree(GetProcessHeap(), 0, pFuncDesc->lprgelemdescParam);
3797     }
3798
3799     HeapFree(GetProcessHeap(), 0, pFuncDesc->elemdescFunc.u.paramdesc.pparamdescex);
3800
3801     if (pFuncDesc->elemdescFunc.tdesc.vt != VT_USERDEFINED)
3802         release_typedesc(pFuncDesc->elemdescFunc.tdesc.u.lptdesc);
3803
3804     HeapFree(GetProcessHeap(), 0, pFuncDesc);
3805 }
3806
3807 /******************************************************************************
3808  * ITypeInfo2_ReleaseVarDesc {OLEAUT32}
3809  *
3810  *  See ITypeInfo_ReleaseVarDesc.
3811  */
3812 static void WINAPI ITypeInfo2_fnReleaseVarDesc(
3813         ITypeInfo2* iface,
3814         VARDESC* pVarDesc)
3815 {
3816     FIXME("(%p,%p), stub!\n", iface, pVarDesc);
3817 }
3818
3819 /******************************************************************************
3820  * ITypeInfo2_GetTypeKind {OLEAUT32}
3821  *
3822  *  Get the TYPEKIND value for a TypeInfo.
3823  *
3824  * RETURNS
3825  *
3826  *  Success: S_OK.
3827  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
3828  */
3829 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind(
3830         ITypeInfo2* iface,   /* [I] The TypeInfo to obtain the typekind for. */
3831         TYPEKIND* pTypeKind) /* [O] The typekind for this TypeInfo. */
3832 {
3833     FIXME("(%p,%p), stub!\n", iface, pTypeKind);
3834     return E_OUTOFMEMORY;
3835 }
3836
3837 /******************************************************************************
3838  * ITypeInfo2_GetTypeFlags {OLEAUT32}
3839  *
3840  *  Get the Type Flags for a TypeInfo.
3841  *
3842  * RETURNS
3843  *
3844  *  Success: S_OK.
3845  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
3846  */
3847 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags(
3848         ITypeInfo2* iface, /* [I] The TypeInfo to obtain the typeflags for. */
3849         ULONG* pTypeFlags) /* [O] The type flags for this TypeInfo. */
3850 {
3851     FIXME("(%p,%p), stub!\n", iface, pTypeFlags);
3852     return E_OUTOFMEMORY;
3853 }
3854
3855 /******************************************************************************
3856  * ITypeInfo2_GetFuncIndexOfMemId {OLEAUT32}
3857  *
3858  *  Gets the index of a function given its member id.
3859  *
3860  * RETURNS
3861  *
3862  *  Success: S_OK.
3863  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
3864  */
3865 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId(
3866         ITypeInfo2* iface,  /* [I] The TypeInfo in which to find the function. */
3867         MEMBERID memid,     /* [I] The member id for the function. */
3868         INVOKEKIND invKind, /* [I] The invocation kind for the function. */
3869         UINT* pFuncIndex)   /* [O] The index of the function. */
3870 {
3871     FIXME("(%p,%d,%d,%p), stub!\n", iface, memid, invKind, pFuncIndex);
3872     return E_OUTOFMEMORY;
3873 }
3874
3875 /******************************************************************************
3876  * ITypeInfo2_GetVarIndexOfMemId {OLEAUT32}
3877  *
3878  *  Gets the index of a variable given its member id.
3879  *
3880  * RETURNS
3881  *
3882  *  Success: S_OK.
3883  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
3884  */
3885 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId(
3886         ITypeInfo2* iface, /* [I] The TypeInfo in which to find the variable. */
3887         MEMBERID memid,    /* [I] The member id for the variable. */
3888         UINT* pVarIndex)   /* [O] The index of the variable. */
3889 {
3890     FIXME("(%p,%d,%p), stub!\n", iface, memid, pVarIndex);
3891     return E_OUTOFMEMORY;
3892 }
3893
3894 /******************************************************************************
3895  * ITypeInfo2_GetCustData {OLEAUT32}
3896  *
3897  *  Gets a custom data element from a TypeInfo.
3898  *
3899  * RETURNS
3900  *
3901  *  Success: S_OK.
3902  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
3903  */
3904 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
3905         ITypeInfo2* iface, /* [I] The TypeInfo in which to find the custom data. */
3906         REFGUID guid,      /* [I] The GUID under which the custom data is stored. */
3907         VARIANT* pVarVal)  /* [O] The custom data. */
3908 {
3909     ICreateTypeInfo2Impl *This = impl_from_ITypeInfo2(iface);
3910     MSFT_CDGuid *cdentry;
3911     int offset;
3912
3913     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(guid), pVarVal);
3914
3915     if (!guid || !pVarVal)
3916         return E_INVALIDARG;
3917
3918     VariantClear(pVarVal);
3919
3920     offset = ctl2_find_custdata(This->typelib, guid, This->typeinfo->oCustData);
3921     if (offset == -1)
3922         return S_OK;
3923
3924     cdentry = (MSFT_CDGuid *)&This->typelib->typelib_segment_data[MSFT_SEG_CUSTDATAGUID][offset];
3925     return ctl2_decode_variant(This->typelib, cdentry->DataOffset, pVarVal);
3926 }
3927
3928 /******************************************************************************
3929  * ITypeInfo2_GetFuncCustData {OLEAUT32}
3930  *
3931  *  Gets a custom data element from a function.
3932  *
3933  * RETURNS
3934  *
3935  *  Success: S_OK.
3936  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
3937  */
3938 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
3939         ITypeInfo2* iface, /* [I] The TypeInfo in which to find the custom data. */
3940         UINT index,        /* [I] The index of the function for which to retrieve the custom data. */
3941         REFGUID guid,      /* [I] The GUID under which the custom data is stored. */
3942         VARIANT* pVarVal)  /* [O] The custom data. */
3943 {
3944     FIXME("(%p,%d,%s,%p), stub!\n", iface, index, debugstr_guid(guid), pVarVal);
3945     return E_OUTOFMEMORY;
3946 }
3947
3948 /******************************************************************************
3949  * ITypeInfo2_GetParamCustData {OLEAUT32}
3950  *
3951  *  Gets a custom data element from a parameter.
3952  *
3953  * RETURNS
3954  *
3955  *  Success: S_OK.
3956  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
3957  */
3958 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
3959         ITypeInfo2* iface, /* [I] The TypeInfo in which to find the custom data. */
3960         UINT indexFunc,    /* [I] The index of the function for which to retrieve the custom data. */
3961         UINT indexParam,   /* [I] The index of the parameter for which to retrieve the custom data. */
3962         REFGUID guid,      /* [I] The GUID under which the custom data is stored. */
3963         VARIANT* pVarVal)  /* [O] The custom data. */
3964 {
3965     FIXME("(%p,%d,%d,%s,%p), stub!\n", iface, indexFunc, indexParam, debugstr_guid(guid), pVarVal);
3966     return E_OUTOFMEMORY;
3967 }
3968
3969 /******************************************************************************
3970  * ITypeInfo2_GetVarCustData {OLEAUT32}
3971  *
3972  *  Gets a custom data element from a variable.
3973  *
3974  * RETURNS
3975  *
3976  *  Success: S_OK.
3977  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
3978  */
3979 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
3980         ITypeInfo2* iface, /* [I] The TypeInfo in which to find the custom data. */
3981         UINT index,        /* [I] The index of the variable for which to retrieve the custom data. */
3982         REFGUID guid,      /* [I] The GUID under which the custom data is stored. */
3983         VARIANT* pVarVal)  /* [O] The custom data. */
3984 {
3985     FIXME("(%p,%d,%s,%p), stub!\n", iface, index, debugstr_guid(guid), pVarVal);
3986     return E_OUTOFMEMORY;
3987 }
3988
3989 /******************************************************************************
3990  * ITypeInfo2_GetImplTypeCustData {OLEAUT32}
3991  *
3992  *  Gets a custom data element from an implemented type of a TypeInfo.
3993  *
3994  * RETURNS
3995  *
3996  *  Success: S_OK.
3997  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
3998  */
3999 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
4000         ITypeInfo2* iface, /* [I] The TypeInfo in which to find the custom data. */
4001         UINT index,        /* [I] The index of the implemented type for which to retrieve the custom data. */
4002         REFGUID guid,      /* [I] The GUID under which the custom data is stored. */
4003         VARIANT* pVarVal)  /* [O] The custom data. */
4004 {
4005     FIXME("(%p,%d,%s,%p), stub!\n", iface, index, debugstr_guid(guid), pVarVal);
4006     return E_OUTOFMEMORY;
4007 }
4008
4009 /******************************************************************************
4010  * ITypeInfo2_GetDocumentation2 {OLEAUT32}
4011  *
4012  *  Gets some documentation from a TypeInfo in a locale-aware fashion.
4013  *
4014  * RETURNS
4015  *
4016  *  Success: S_OK.
4017  *  Failure: One of STG_E_INSUFFICIENTMEMORY or E_INVALIDARG.
4018  */
4019 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
4020         ITypeInfo2* iface,           /* [I] The TypeInfo to retrieve the documentation from. */
4021         MEMBERID memid,              /* [I] The member id (why?). */
4022         LCID lcid,                   /* [I] The locale (why?). */
4023         BSTR* pbstrHelpString,       /* [O] The help string. */
4024         DWORD* pdwHelpStringContext, /* [O] The help string context. */
4025         BSTR* pbstrHelpStringDll)    /* [O] The help file name. */
4026 {
4027     FIXME("(%p,%d,%d,%p,%p,%p), stub!\n", iface, memid, lcid, pbstrHelpString, pdwHelpStringContext, pbstrHelpStringDll);
4028     return E_OUTOFMEMORY;
4029 }
4030
4031 /******************************************************************************
4032  * ITypeInfo2_GetAllCustData {OLEAUT32}
4033  *
4034  *  Gets all of the custom data associated with a TypeInfo.
4035  *
4036  * RETURNS
4037  *
4038  *  Success: S_OK.
4039  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
4040  */
4041 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
4042         ITypeInfo2* iface,   /* [I] The TypeInfo in which to find the custom data. */
4043         CUSTDATA* pCustData) /* [O] A pointer to the custom data. */
4044 {
4045     FIXME("(%p,%p), stub!\n", iface, pCustData);
4046     return E_OUTOFMEMORY;
4047 }
4048
4049 /******************************************************************************
4050  * ITypeInfo2_GetAllFuncCustData {OLEAUT32}
4051  *
4052  *  Gets all of the custom data associated with a function.
4053  *
4054  * RETURNS
4055  *
4056  *  Success: S_OK.
4057  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
4058  */
4059 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
4060         ITypeInfo2* iface,   /* [I] The TypeInfo in which to find the custom data. */
4061         UINT index,          /* [I] The index of the function for which to retrieve the custom data. */
4062         CUSTDATA* pCustData) /* [O] A pointer to the custom data. */
4063 {
4064     FIXME("(%p,%d,%p), stub!\n", iface, index, pCustData);
4065     return E_OUTOFMEMORY;
4066 }
4067
4068 /******************************************************************************
4069  * ITypeInfo2_GetAllParamCustData {OLEAUT32}
4070  *
4071  *  Gets all of the custom data associated with a parameter.
4072  *
4073  * RETURNS
4074  *
4075  *  Success: S_OK.
4076  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
4077  */
4078 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData(
4079         ITypeInfo2* iface,   /* [I] The TypeInfo in which to find the custom data. */
4080         UINT indexFunc,      /* [I] The index of the function for which to retrieve the custom data. */
4081         UINT indexParam,     /* [I] The index of the parameter for which to retrieve the custom data. */
4082         CUSTDATA* pCustData) /* [O] A pointer to the custom data. */
4083 {
4084     FIXME("(%p,%d,%d,%p), stub!\n", iface, indexFunc, indexParam, pCustData);
4085     return E_OUTOFMEMORY;
4086 }
4087
4088 /******************************************************************************
4089  * ITypeInfo2_GetAllVarCustData {OLEAUT32}
4090  *
4091  *  Gets all of the custom data associated with a variable.
4092  *
4093  * RETURNS
4094  *
4095  *  Success: S_OK.
4096  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
4097  */
4098 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData(
4099         ITypeInfo2* iface,   /* [I] The TypeInfo in which to find the custom data. */
4100         UINT index,          /* [I] The index of the variable for which to retrieve the custom data. */
4101         CUSTDATA* pCustData) /* [O] A pointer to the custom data. */
4102 {
4103     FIXME("(%p,%d,%p), stub!\n", iface, index, pCustData);
4104     return E_OUTOFMEMORY;
4105 }
4106
4107 /******************************************************************************
4108  * ITypeInfo2_GetAllImplTypeCustData {OLEAUT32}
4109  *
4110  *  Gets all of the custom data associated with an implemented type.
4111  *
4112  * RETURNS
4113  *
4114  *  Success: S_OK.
4115  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
4116  */
4117 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
4118         ITypeInfo2* iface,   /* [I] The TypeInfo in which to find the custom data. */
4119         UINT index,          /* [I] The index of the implemented type for which to retrieve the custom data. */
4120         CUSTDATA* pCustData) /* [O] A pointer to the custom data. */
4121 {
4122     FIXME("(%p,%d,%p), stub!\n", iface, index, pCustData);
4123     return E_OUTOFMEMORY;
4124 }
4125
4126
4127 /*================== ICreateTypeInfo2 & ITypeInfo2 VTABLEs And Creation ===================================*/
4128
4129 static const ICreateTypeInfo2Vtbl ctypeinfo2vt =
4130 {
4131
4132     ICreateTypeInfo2_fnQueryInterface,
4133     ICreateTypeInfo2_fnAddRef,
4134     ICreateTypeInfo2_fnRelease,
4135
4136     ICreateTypeInfo2_fnSetGuid,
4137     ICreateTypeInfo2_fnSetTypeFlags,
4138     ICreateTypeInfo2_fnSetDocString,
4139     ICreateTypeInfo2_fnSetHelpContext,
4140     ICreateTypeInfo2_fnSetVersion,
4141     ICreateTypeInfo2_fnAddRefTypeInfo,
4142     ICreateTypeInfo2_fnAddFuncDesc,
4143     ICreateTypeInfo2_fnAddImplType,
4144     ICreateTypeInfo2_fnSetImplTypeFlags,
4145     ICreateTypeInfo2_fnSetAlignment,
4146     ICreateTypeInfo2_fnSetSchema,
4147     ICreateTypeInfo2_fnAddVarDesc,
4148     ICreateTypeInfo2_fnSetFuncAndParamNames,
4149     ICreateTypeInfo2_fnSetVarName,
4150     ICreateTypeInfo2_fnSetTypeDescAlias,
4151     ICreateTypeInfo2_fnDefineFuncAsDllEntry,
4152     ICreateTypeInfo2_fnSetFuncDocString,
4153     ICreateTypeInfo2_fnSetVarDocString,
4154     ICreateTypeInfo2_fnSetFuncHelpContext,
4155     ICreateTypeInfo2_fnSetVarHelpContext,
4156     ICreateTypeInfo2_fnSetMops,
4157     ICreateTypeInfo2_fnSetTypeIdldesc,
4158     ICreateTypeInfo2_fnLayOut,
4159
4160     ICreateTypeInfo2_fnDeleteFuncDesc,
4161     ICreateTypeInfo2_fnDeleteFuncDescByMemId,
4162     ICreateTypeInfo2_fnDeleteVarDesc,
4163     ICreateTypeInfo2_fnDeleteVarDescByMemId,
4164     ICreateTypeInfo2_fnDeleteImplType,
4165     ICreateTypeInfo2_fnSetCustData,
4166     ICreateTypeInfo2_fnSetFuncCustData,
4167     ICreateTypeInfo2_fnSetParamCustData,
4168     ICreateTypeInfo2_fnSetVarCustData,
4169     ICreateTypeInfo2_fnSetImplTypeCustData,
4170     ICreateTypeInfo2_fnSetHelpStringContext,
4171     ICreateTypeInfo2_fnSetFuncHelpStringContext,
4172     ICreateTypeInfo2_fnSetVarHelpStringContext,
4173     ICreateTypeInfo2_fnInvalidate,
4174     ICreateTypeInfo2_fnSetName
4175 };
4176
4177 static const ITypeInfo2Vtbl typeinfo2vt =
4178 {
4179
4180     ITypeInfo2_fnQueryInterface,
4181     ITypeInfo2_fnAddRef,
4182     ITypeInfo2_fnRelease,
4183
4184     ITypeInfo2_fnGetTypeAttr,
4185     ITypeInfo2_fnGetTypeComp,
4186     ITypeInfo2_fnGetFuncDesc,
4187     ITypeInfo2_fnGetVarDesc,
4188     ITypeInfo2_fnGetNames,
4189     ITypeInfo2_fnGetRefTypeOfImplType,
4190     ITypeInfo2_fnGetImplTypeFlags,
4191     ITypeInfo2_fnGetIDsOfNames,
4192     ITypeInfo2_fnInvoke,
4193     ITypeInfo2_fnGetDocumentation,
4194     ITypeInfo2_fnGetDllEntry,
4195     ITypeInfo2_fnGetRefTypeInfo,
4196     ITypeInfo2_fnAddressOfMember,
4197     ITypeInfo2_fnCreateInstance,
4198     ITypeInfo2_fnGetMops,
4199     ITypeInfo2_fnGetContainingTypeLib,
4200     ITypeInfo2_fnReleaseTypeAttr,
4201     ITypeInfo2_fnReleaseFuncDesc,
4202     ITypeInfo2_fnReleaseVarDesc,
4203
4204     ITypeInfo2_fnGetTypeKind,
4205     ITypeInfo2_fnGetTypeFlags,
4206     ITypeInfo2_fnGetFuncIndexOfMemId,
4207     ITypeInfo2_fnGetVarIndexOfMemId,
4208     ITypeInfo2_fnGetCustData,
4209     ITypeInfo2_fnGetFuncCustData,
4210     ITypeInfo2_fnGetParamCustData,
4211     ITypeInfo2_fnGetVarCustData,
4212     ITypeInfo2_fnGetImplTypeCustData,
4213     ITypeInfo2_fnGetDocumentation2,
4214     ITypeInfo2_fnGetAllCustData,
4215     ITypeInfo2_fnGetAllFuncCustData,
4216     ITypeInfo2_fnGetAllParamCustData,
4217     ITypeInfo2_fnGetAllVarCustData,
4218     ITypeInfo2_fnGetAllImplTypeCustData,
4219 };
4220
4221 static ICreateTypeInfo2 *ICreateTypeInfo2_Constructor(ICreateTypeLib2Impl *typelib, WCHAR *szName, TYPEKIND tkind)
4222 {
4223     ICreateTypeInfo2Impl *pCreateTypeInfo2Impl;
4224
4225     int nameoffset;
4226     int typeinfo_offset;
4227     MSFT_TypeInfoBase *typeinfo;
4228
4229     TRACE("Constructing ICreateTypeInfo2 for %s with tkind %d\n", debugstr_w(szName), tkind);
4230
4231     pCreateTypeInfo2Impl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ICreateTypeInfo2Impl));
4232     if (!pCreateTypeInfo2Impl) return NULL;
4233
4234     pCreateTypeInfo2Impl->lpVtbl = &ctypeinfo2vt;
4235     pCreateTypeInfo2Impl->lpVtblTypeInfo2 = &typeinfo2vt;
4236     pCreateTypeInfo2Impl->ref = 1;
4237
4238     pCreateTypeInfo2Impl->typelib = typelib;
4239     ICreateTypeLib_AddRef((ICreateTypeLib*)typelib);
4240
4241     nameoffset = ctl2_alloc_name(typelib, szName);
4242     typeinfo_offset = ctl2_alloc_typeinfo(typelib, nameoffset);
4243     typeinfo = (MSFT_TypeInfoBase *)&typelib->typelib_segment_data[MSFT_SEG_TYPEINFO][typeinfo_offset];
4244
4245     typelib->typelib_segment_data[MSFT_SEG_NAME][nameoffset + 9] = 0x38;
4246     *((int *)&typelib->typelib_segment_data[MSFT_SEG_NAME][nameoffset]) = typeinfo_offset;
4247
4248     pCreateTypeInfo2Impl->typeinfo = typeinfo;
4249
4250     pCreateTypeInfo2Impl->typekind = tkind;
4251     typeinfo->typekind |= tkind | 0x20;
4252     ICreateTypeInfo2_SetAlignment((ICreateTypeInfo2 *)pCreateTypeInfo2Impl, 4);
4253
4254     switch (tkind) {
4255     case TKIND_ENUM:
4256     case TKIND_INTERFACE:
4257     case TKIND_DISPATCH:
4258     case TKIND_COCLASS:
4259         typeinfo->size = 4;
4260         break;
4261
4262     case TKIND_RECORD:
4263     case TKIND_UNION:
4264         typeinfo->size = 0;
4265         break;
4266
4267     case TKIND_MODULE:
4268         typeinfo->size = 2;
4269         break;
4270
4271     case TKIND_ALIAS:
4272         typeinfo->size = -0x75;
4273         break;
4274
4275     default:
4276         FIXME("(%s,%d), unrecognized typekind %d\n", debugstr_w(szName), tkind, tkind);
4277         typeinfo->size = 0xdeadbeef;
4278         break;
4279     }
4280
4281     if (typelib->last_typeinfo) typelib->last_typeinfo->next_typeinfo = pCreateTypeInfo2Impl;
4282     typelib->last_typeinfo = pCreateTypeInfo2Impl;
4283     if (!typelib->typeinfos) typelib->typeinfos = pCreateTypeInfo2Impl;
4284
4285     TRACE(" -- %p\n", pCreateTypeInfo2Impl);
4286
4287     return (ICreateTypeInfo2 *)pCreateTypeInfo2Impl;
4288 }
4289
4290
4291 /*================== ICreateTypeLib2 Implementation ===================================*/
4292
4293 /******************************************************************************
4294  * ICreateTypeLib2_QueryInterface {OLEAUT32}
4295  *
4296  *  See IUnknown_QueryInterface.
4297  */
4298 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(
4299         ICreateTypeLib2 * iface,
4300         REFIID riid,
4301         VOID **ppvObject)
4302 {
4303     ICreateTypeLib2Impl *This = (ICreateTypeLib2Impl *)iface;
4304
4305     TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4306
4307     *ppvObject=NULL;
4308     if(IsEqualIID(riid, &IID_IUnknown) ||
4309        IsEqualIID(riid,&IID_ICreateTypeLib)||
4310        IsEqualIID(riid,&IID_ICreateTypeLib2))
4311     {
4312         *ppvObject = This;
4313     } else if (IsEqualIID(riid, &IID_ITypeLib) ||
4314                IsEqualIID(riid, &IID_ITypeLib2)) {
4315         *ppvObject = &This->lpVtblTypeLib2;
4316     }
4317
4318     if(*ppvObject)
4319     {
4320         ICreateTypeLib2_AddRef(iface);
4321         TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4322         return S_OK;
4323     }
4324     TRACE("-- Interface: E_NOINTERFACE\n");
4325     return E_NOINTERFACE;
4326 }
4327
4328 /******************************************************************************
4329  * ICreateTypeLib2_AddRef {OLEAUT32}
4330  *
4331  *  See IUnknown_AddRef.
4332  */
4333 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
4334 {
4335     ICreateTypeLib2Impl *This = (ICreateTypeLib2Impl *)iface;
4336     ULONG ref = InterlockedIncrement(&This->ref);
4337
4338     TRACE("(%p)->ref was %u\n",This, ref - 1);
4339
4340     return ref;
4341 }
4342
4343 /******************************************************************************
4344  * ICreateTypeLib2_Release {OLEAUT32}
4345  *
4346  *  See IUnknown_Release.
4347  */
4348 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
4349 {
4350     ICreateTypeLib2Impl *This = (ICreateTypeLib2Impl *)iface;
4351     ULONG ref = InterlockedDecrement(&This->ref);
4352
4353     TRACE("(%p)->(%u)\n",This, ref);
4354
4355     if (!ref) {
4356         int i;
4357
4358         for (i = 0; i < MSFT_SEG_MAX; i++) {
4359             HeapFree(GetProcessHeap(), 0, This->typelib_segment_data[i]);
4360             This->typelib_segment_data[i] = NULL;
4361         }
4362
4363         HeapFree(GetProcessHeap(), 0, This->filename);
4364         This->filename = NULL;
4365
4366         while (This->typeinfos) {
4367             ICreateTypeInfo2Impl *typeinfo = This->typeinfos;
4368             This->typeinfos = typeinfo->next_typeinfo;
4369             if(typeinfo->typedata) {
4370                 CyclicList *iter, *rem;
4371
4372                 rem = typeinfo->typedata->next;
4373                 typeinfo->typedata->next = NULL;
4374                 iter = rem->next;
4375                 HeapFree(GetProcessHeap(), 0, rem);
4376
4377                 while(iter) {
4378                     rem = iter;
4379                     iter = iter->next;
4380                     HeapFree(GetProcessHeap(), 0, rem->u.data);
4381                     HeapFree(GetProcessHeap(), 0, rem);
4382                 }
4383             }
4384
4385             HeapFree(GetProcessHeap(), 0, typeinfo->dual);
4386             HeapFree(GetProcessHeap(), 0, typeinfo);
4387         }
4388
4389         HeapFree(GetProcessHeap(),0,This);
4390         return 0;
4391     }
4392
4393     return ref;
4394 }
4395
4396
4397 /******************************************************************************
4398  * ICreateTypeLib2_CreateTypeInfo {OLEAUT32}
4399  *
4400  *  See ICreateTypeLib_CreateTypeInfo.
4401  */
4402 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(
4403         ICreateTypeLib2 * iface,
4404         LPOLESTR szName,
4405         TYPEKIND tkind,
4406         ICreateTypeInfo **tinfo)
4407 {
4408     ICreateTypeLib2Impl *This = (ICreateTypeLib2Impl *)iface;
4409     char *name;
4410
4411     TRACE("(%p,%s,%d,%p)\n", iface, debugstr_w(szName), tkind, tinfo);
4412
4413     if (!szName || !tinfo) return E_INVALIDARG;
4414
4415     ctl2_encode_name(This, szName, &name);
4416     if(ctl2_find_name(This, name) != -1)
4417         return TYPE_E_NAMECONFLICT;
4418
4419     *tinfo = (ICreateTypeInfo *)ICreateTypeInfo2_Constructor(This, szName, tkind);
4420     if (!*tinfo) return E_OUTOFMEMORY;
4421
4422     return S_OK;
4423 }
4424
4425 /******************************************************************************
4426  * ICreateTypeLib2_SetName {OLEAUT32}
4427  *
4428  *  See ICreateTypeLib_SetName.
4429  */
4430 static HRESULT WINAPI ICreateTypeLib2_fnSetName(
4431         ICreateTypeLib2 * iface,
4432         LPOLESTR szName)
4433 {
4434     ICreateTypeLib2Impl *This = (ICreateTypeLib2Impl *)iface;
4435
4436     int offset;
4437
4438     TRACE("(%p,%s)\n", iface, debugstr_w(szName));
4439
4440     offset = ctl2_alloc_name(This, szName);
4441     if (offset == -1) return E_OUTOFMEMORY;
4442     This->typelib_header.NameOffset = offset;
4443     return S_OK;
4444 }
4445
4446 /******************************************************************************
4447  * ICreateTypeLib2_SetVersion {OLEAUT32}
4448  *
4449  *  See ICreateTypeLib_SetVersion.
4450  */
4451 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 * iface, WORD wMajorVerNum, WORD wMinorVerNum)
4452 {
4453     ICreateTypeLib2Impl *This = (ICreateTypeLib2Impl *)iface;
4454
4455     TRACE("(%p,%d,%d)\n", iface, wMajorVerNum, wMinorVerNum);
4456
4457     This->typelib_header.version = wMajorVerNum | (wMinorVerNum << 16);
4458     return S_OK;
4459 }
4460
4461 /******************************************************************************
4462  * ICreateTypeLib2_SetGuid {OLEAUT32}
4463  *
4464  *  See ICreateTypeLib_SetGuid.
4465  */
4466 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 * iface, REFGUID guid)
4467 {
4468     ICreateTypeLib2Impl *This = (ICreateTypeLib2Impl *)iface;
4469
4470     MSFT_GuidEntry guidentry;
4471     int offset;
4472
4473     TRACE("(%p,%s)\n", iface, debugstr_guid(guid));
4474
4475     guidentry.guid = *guid;
4476     guidentry.hreftype = -2;
4477     guidentry.next_hash = -1;
4478
4479     offset = ctl2_alloc_guid(This, &guidentry);
4480     
4481     if (offset == -1) return E_OUTOFMEMORY;
4482
4483     This->typelib_header.posguid = offset;
4484
4485     return S_OK;
4486 }
4487
4488 /******************************************************************************
4489  * ICreateTypeLib2_SetDocString {OLEAUT32}
4490  *
4491  *  See ICreateTypeLib_SetDocString.
4492  */
4493 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 * iface, LPOLESTR szDoc)
4494 {
4495     ICreateTypeLib2Impl *This = (ICreateTypeLib2Impl *)iface;
4496
4497     int offset;
4498
4499     TRACE("(%p,%s)\n", iface, debugstr_w(szDoc));
4500     if (!szDoc)
4501         return E_INVALIDARG;
4502
4503     offset = ctl2_alloc_string(This, szDoc);
4504     if (offset == -1) return E_OUTOFMEMORY;
4505     This->typelib_header.helpstring = offset;
4506     return S_OK;
4507 }
4508
4509 /******************************************************************************
4510  * ICreateTypeLib2_SetHelpFileName {OLEAUT32}
4511  *
4512  *  See ICreateTypeLib_SetHelpFileName.
4513  */
4514 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 * iface, LPOLESTR szHelpFileName)
4515 {
4516     ICreateTypeLib2Impl *This = (ICreateTypeLib2Impl *)iface;
4517
4518     int offset;
4519
4520     TRACE("(%p,%s)\n", iface, debugstr_w(szHelpFileName));
4521
4522     offset = ctl2_alloc_string(This, szHelpFileName);
4523     if (offset == -1) return E_OUTOFMEMORY;
4524     This->typelib_header.helpfile = offset;
4525     This->typelib_header.varflags |= 0x10;
4526     return S_OK;
4527 }
4528
4529 /******************************************************************************
4530  * ICreateTypeLib2_SetHelpContext {OLEAUT32}
4531  *
4532  *  See ICreateTypeLib_SetHelpContext.
4533  */
4534 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 * iface, DWORD dwHelpContext)
4535 {
4536     ICreateTypeLib2Impl *This = (ICreateTypeLib2Impl *)iface;
4537
4538     TRACE("(%p,%d)\n", iface, dwHelpContext);
4539     This->typelib_header.helpcontext = dwHelpContext;
4540     return S_OK;
4541 }
4542
4543 /******************************************************************************
4544  * ICreateTypeLib2_SetLcid {OLEAUT32}
4545  *
4546  * Sets both the lcid and lcid2 members in the header to lcid.
4547  *
4548  * As a special case if lcid == LOCALE_NEUTRAL (0), then the first header lcid
4549  * is set to US English while the second one is set to 0.
4550  */
4551 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 * iface, LCID lcid)
4552 {
4553     ICreateTypeLib2Impl *This = (ICreateTypeLib2Impl *)iface;
4554
4555     TRACE("(%p,%d)\n", iface, lcid);
4556
4557     This->typelib_header.lcid = This->typelib_header.lcid2 = lcid;
4558
4559     if(lcid == LOCALE_NEUTRAL) This->typelib_header.lcid = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
4560
4561     return S_OK;
4562 }
4563
4564 /******************************************************************************
4565  * ICreateTypeLib2_SetLibFlags {OLEAUT32}
4566  *
4567  *  See ICreateTypeLib_SetLibFlags.
4568  */
4569 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 * iface, UINT uLibFlags)
4570 {
4571     ICreateTypeLib2Impl *This = (ICreateTypeLib2Impl *)iface;
4572
4573     TRACE("(%p,0x%x)\n", iface, uLibFlags);
4574
4575     This->typelib_header.flags = uLibFlags;
4576
4577     return S_OK;
4578 }
4579
4580 static int ctl2_write_chunk(HANDLE hFile, const void *segment, int length)
4581 {
4582     DWORD dwWritten;
4583     if (!WriteFile(hFile, segment, length, &dwWritten, 0)) {
4584         CloseHandle(hFile);
4585         return 0;
4586     }
4587     return -1;
4588 }
4589
4590 static int ctl2_write_segment(ICreateTypeLib2Impl *This, HANDLE hFile, int segment)
4591 {
4592     DWORD dwWritten;
4593     if (!WriteFile(hFile, This->typelib_segment_data[segment],
4594                    This->typelib_segdir[segment].length, &dwWritten, 0)) {
4595         CloseHandle(hFile);
4596         return 0;
4597     }
4598
4599     return -1;
4600 }
4601
4602 static HRESULT ctl2_finalize_typeinfos(ICreateTypeLib2Impl *This, int filesize)
4603 {
4604     ICreateTypeInfo2Impl *typeinfo;
4605     HRESULT hres;
4606
4607     for (typeinfo = This->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
4608         typeinfo->typeinfo->memoffset = filesize;
4609
4610         hres = ICreateTypeInfo2_fnLayOut((ICreateTypeInfo2 *)typeinfo);
4611         if(FAILED(hres))
4612             return hres;
4613
4614         if (typeinfo->typedata)
4615             filesize += typeinfo->typedata->next->u.val
4616                 + cti2_get_var_count(typeinfo->typeinfo) * 12
4617                 + cti2_get_func_count(typeinfo->typeinfo) * 12 + 4;
4618     }
4619
4620     return S_OK;
4621 }
4622
4623 static int ctl2_finalize_segment(ICreateTypeLib2Impl *This, int filepos, int segment)
4624 {
4625     if (This->typelib_segdir[segment].length) {
4626         This->typelib_segdir[segment].offset = filepos;
4627     } else {
4628         This->typelib_segdir[segment].offset = -1;
4629     }
4630
4631     return This->typelib_segdir[segment].length;
4632 }
4633
4634 static void ctl2_write_typeinfos(ICreateTypeLib2Impl *This, HANDLE hFile)
4635 {
4636     ICreateTypeInfo2Impl *typeinfo;
4637
4638     for (typeinfo = This->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
4639         CyclicList *iter;
4640         int offset = 0;
4641
4642         if (!typeinfo->typedata) continue;
4643
4644         iter = typeinfo->typedata->next;
4645         ctl2_write_chunk(hFile, &iter->u.val, sizeof(int));
4646         for(iter=iter->next; iter!=typeinfo->typedata->next; iter=iter->next)
4647             ctl2_write_chunk(hFile, iter->u.data, iter->u.data[0] & 0xffff);
4648
4649         for(iter=typeinfo->typedata->next->next; iter!=typeinfo->typedata->next; iter=iter->next)
4650             ctl2_write_chunk(hFile, &iter->indice, sizeof(int));
4651
4652         for(iter=typeinfo->typedata->next->next; iter!=typeinfo->typedata->next; iter=iter->next)
4653             ctl2_write_chunk(hFile, &iter->name, sizeof(int));
4654
4655         for(iter=typeinfo->typedata->next->next; iter!=typeinfo->typedata->next; iter=iter->next) {
4656             ctl2_write_chunk(hFile, &offset, sizeof(int));
4657             offset += iter->u.data[0] & 0xffff;
4658         }
4659     }
4660 }
4661
4662 /******************************************************************************
4663  * ICreateTypeLib2_SaveAllChanges {OLEAUT32}
4664  *
4665  *  See ICreateTypeLib_SaveAllChanges.
4666  */
4667 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 * iface)
4668 {
4669     ICreateTypeLib2Impl *This = (ICreateTypeLib2Impl *)iface;
4670
4671     int retval;
4672     int filepos;
4673     HANDLE hFile;
4674     HRESULT hres;
4675
4676     TRACE("(%p)\n", iface);
4677
4678     retval = TYPE_E_IOERROR;
4679
4680     hFile = CreateFileW(This->filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
4681     if (hFile == INVALID_HANDLE_VALUE) return retval;
4682
4683     filepos = sizeof(MSFT_Header) + sizeof(MSFT_SegDir);
4684     filepos += This->typelib_header.nrtypeinfos * 4;
4685
4686     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_TYPEINFO);
4687     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_GUIDHASH);
4688     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_GUID);
4689     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_REFERENCES);
4690     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_IMPORTINFO);
4691     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_IMPORTFILES);
4692     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_NAMEHASH);
4693     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_NAME);
4694     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_STRING);
4695     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_TYPEDESC);
4696     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_ARRAYDESC);
4697     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_CUSTDATA);
4698     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_CUSTDATAGUID);
4699
4700     hres = ctl2_finalize_typeinfos(This, filepos);
4701     if(FAILED(hres)) {
4702         CloseHandle(hFile);
4703         return hres;
4704     }
4705
4706     if (!ctl2_write_chunk(hFile, &This->typelib_header, sizeof(This->typelib_header))) return retval;
4707     if (This->typelib_header.varflags & HELPDLLFLAG)
4708         if (!ctl2_write_chunk(hFile, &This->helpStringDll, sizeof(This->helpStringDll))) return retval;
4709     if (!ctl2_write_chunk(hFile, This->typelib_typeinfo_offsets, This->typelib_header.nrtypeinfos * 4)) return retval;
4710     if (!ctl2_write_chunk(hFile, This->typelib_segdir, sizeof(This->typelib_segdir))) return retval;
4711     if (!ctl2_write_segment(This, hFile, MSFT_SEG_TYPEINFO    )) return retval;
4712     if (!ctl2_write_segment(This, hFile, MSFT_SEG_GUIDHASH    )) return retval;
4713     if (!ctl2_write_segment(This, hFile, MSFT_SEG_GUID        )) return retval;
4714     if (!ctl2_write_segment(This, hFile, MSFT_SEG_REFERENCES  )) return retval;
4715     if (!ctl2_write_segment(This, hFile, MSFT_SEG_IMPORTINFO  )) return retval;
4716     if (!ctl2_write_segment(This, hFile, MSFT_SEG_IMPORTFILES )) return retval;
4717     if (!ctl2_write_segment(This, hFile, MSFT_SEG_NAMEHASH    )) return retval;
4718     if (!ctl2_write_segment(This, hFile, MSFT_SEG_NAME        )) return retval;
4719     if (!ctl2_write_segment(This, hFile, MSFT_SEG_STRING      )) return retval;
4720     if (!ctl2_write_segment(This, hFile, MSFT_SEG_TYPEDESC    )) return retval;
4721     if (!ctl2_write_segment(This, hFile, MSFT_SEG_ARRAYDESC   )) return retval;
4722     if (!ctl2_write_segment(This, hFile, MSFT_SEG_CUSTDATA    )) return retval;
4723     if (!ctl2_write_segment(This, hFile, MSFT_SEG_CUSTDATAGUID)) return retval;
4724
4725     ctl2_write_typeinfos(This, hFile);
4726
4727     if (!CloseHandle(hFile)) return retval;
4728
4729     return S_OK;
4730 }
4731
4732
4733 /******************************************************************************
4734  * ICreateTypeLib2_DeleteTypeInfo {OLEAUT32}
4735  *
4736  *  Deletes a named TypeInfo from a type library.
4737  *
4738  * RETURNS
4739  *
4740  *  Success: S_OK
4741  *  Failure: E_OUTOFMEMORY or E_INVALIDARG.
4742  */
4743 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(
4744         ICreateTypeLib2 * iface, /* [I] The type library to delete from. */
4745         LPOLESTR szName)         /* [I] The name of the typeinfo to delete. */
4746 {
4747     FIXME("(%p,%s), stub!\n", iface, debugstr_w(szName));
4748     return E_OUTOFMEMORY;
4749 }
4750
4751 /******************************************************************************
4752  * ICreateTypeLib2_SetCustData {OLEAUT32}
4753  *
4754  *  Sets custom data for a type library.
4755  *
4756  * RETURNS
4757  *
4758  *  Success: S_OK
4759  *  Failure: E_OUTOFMEMORY or E_INVALIDARG.
4760  */
4761 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(
4762         ICreateTypeLib2 * iface, /* [I] The type library to store the custom data in. */
4763         REFGUID guid,            /* [I] The GUID used as a key to retrieve the custom data. */
4764         VARIANT *pVarVal)        /* [I] The custom data itself. */
4765 {
4766     ICreateTypeLib2Impl *This = (ICreateTypeLib2Impl *)iface;
4767
4768     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(guid), pVarVal);
4769
4770     return ctl2_set_custdata(This, guid, pVarVal, &This->typelib_header.CustomDataOffset);
4771 }
4772
4773 /******************************************************************************
4774  * ICreateTypeLib2_SetHelpStringContext {OLEAUT32}
4775  *
4776  *  Sets a context number for the library help string.
4777  *
4778  * PARAMS
4779  *  iface     [I] The type library to set the help string context for.
4780  *  dwContext [I] The help string context.
4781  *
4782  * RETURNS
4783  *  Success: S_OK
4784  *  Failure: E_OUTOFMEMORY or E_INVALIDARG.
4785  */
4786 static
4787 HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 * iface,
4788                                                       ULONG dwContext)
4789 {
4790     ICreateTypeLib2Impl *This = (ICreateTypeLib2Impl *)iface;
4791
4792     TRACE("(%p,%d)\n", iface, dwContext);
4793
4794     This->typelib_header.helpstringcontext = dwContext;
4795     return S_OK;
4796 }
4797
4798 /******************************************************************************
4799  * ICreateTypeLib2_SetHelpStringDll {OLEAUT32}
4800  *
4801  *  Set the DLL used to look up localized help strings.
4802  *
4803  * PARAMS
4804  *  iface     [I] The type library to set the help DLL for.
4805  *  szDllName [I] The name of the help DLL.
4806  *
4807  * RETURNS
4808  *  Success: S_OK
4809  *  Failure: E_OUTOFMEMORY or E_INVALIDARG.
4810  */
4811 static
4812 HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 * iface,
4813                                                   LPOLESTR szDllName)
4814 {
4815     ICreateTypeLib2Impl *This = (ICreateTypeLib2Impl *)iface;
4816     int offset;
4817
4818     TRACE("(%p,%s)\n", iface, debugstr_w(szDllName));
4819     if (!szDllName)
4820         return E_INVALIDARG;
4821
4822     offset = ctl2_alloc_string(This, szDllName);
4823     if (offset == -1)
4824         return E_OUTOFMEMORY;
4825     This->typelib_header.varflags |= HELPDLLFLAG;
4826     This->helpStringDll = offset;
4827     return S_OK;
4828 }
4829
4830 /*================== ITypeLib2 Implementation ===================================*/
4831
4832 /******************************************************************************
4833  * ITypeLib2_QueryInterface {OLEAUT32}
4834  *
4835  *  See IUnknown_QueryInterface.
4836  */
4837 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 * iface, REFIID riid, LPVOID * ppv)
4838 {
4839     ICreateTypeLib2Impl *This = impl_from_ITypeLib2(iface);
4840
4841     return ICreateTypeLib2_QueryInterface((ICreateTypeLib2 *)This, riid, ppv);
4842 }
4843
4844 /******************************************************************************
4845  * ITypeLib2_AddRef {OLEAUT32}
4846  *
4847  *  See IUnknown_AddRef.
4848  */
4849 static ULONG WINAPI ITypeLib2_fnAddRef(ITypeLib2 * iface)
4850 {
4851     ICreateTypeLib2Impl *This = impl_from_ITypeLib2(iface);
4852
4853     return ICreateTypeLib2_AddRef((ICreateTypeLib2 *)This);
4854 }
4855
4856 /******************************************************************************
4857  * ITypeLib2_Release {OLEAUT32}
4858  *
4859  *  See IUnknown_Release.
4860  */
4861 static ULONG WINAPI ITypeLib2_fnRelease(ITypeLib2 * iface)
4862 {
4863     ICreateTypeLib2Impl *This = impl_from_ITypeLib2(iface);
4864
4865     return ICreateTypeLib2_Release((ICreateTypeLib2 *)This);
4866 }
4867
4868 /******************************************************************************
4869  * ITypeLib2_GetTypeInfoCount {OLEAUT32}
4870  *
4871  *  See ITypeLib_GetTypeInfoCount.
4872  */
4873 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount(
4874         ITypeLib2 * iface)
4875 {
4876     ICreateTypeLib2Impl *This = impl_from_ITypeLib2(iface);
4877
4878     TRACE("(%p)\n", iface);
4879
4880     return This->typelib_header.nrtypeinfos;
4881 }
4882
4883 /******************************************************************************
4884  * ITypeLib2_GetTypeInfo {OLEAUT32}
4885  *
4886  *  See ITypeLib_GetTypeInfo.
4887  */
4888 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4889         ITypeLib2 * iface,
4890         UINT index,
4891         ITypeInfo** ppTInfo)
4892 {
4893     ICreateTypeLib2Impl *This = impl_from_ITypeLib2(iface);
4894
4895     TRACE("(%p,%d,%p)\n", iface, index, ppTInfo);
4896
4897     if (!ppTInfo) return E_INVALIDARG;
4898
4899     if (index >= This->typelib_header.nrtypeinfos) {
4900         return TYPE_E_ELEMENTNOTFOUND;
4901     }
4902
4903     return ctl2_find_typeinfo_from_offset(This, This->typelib_typeinfo_offsets[index], ppTInfo);
4904 }
4905
4906 /******************************************************************************
4907  * ITypeLib2_GetTypeInfoType {OLEAUT32}
4908  *
4909  *  See ITypeLib_GetTypeInfoType.
4910  */
4911 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4912         ITypeLib2 * iface,
4913         UINT index,
4914         TYPEKIND* kind)
4915 {
4916     ICreateTypeLib2Impl *This = impl_from_ITypeLib2(iface);
4917
4918     TRACE("(%p,%d,%p)\n", iface, index, kind);
4919
4920     if (!kind) return E_INVALIDARG;
4921
4922     if (index >= This->typelib_header.nrtypeinfos) {
4923         return TYPE_E_ELEMENTNOTFOUND;
4924     }
4925
4926     *kind = (This->typelib_segment_data[MSFT_SEG_TYPEINFO][This->typelib_typeinfo_offsets[index]]) & 0xF;
4927
4928     return S_OK;
4929 }
4930
4931 /******************************************************************************
4932  * ITypeLib2_GetTypeInfoOfGuid {OLEAUT32}
4933  *
4934  *  See ITypeLib_GetTypeInfoOfGuid.
4935  */
4936 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4937         ITypeLib2 * iface,
4938         REFGUID guid,
4939         ITypeInfo** ppTinfo)
4940 {
4941     ICreateTypeLib2Impl *This = impl_from_ITypeLib2(iface);
4942
4943     int guidoffset;
4944     int typeinfo;
4945
4946     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(guid), ppTinfo);
4947
4948     guidoffset = ctl2_find_guid(This, ctl2_hash_guid(guid), guid);
4949     if (guidoffset == -1) return TYPE_E_ELEMENTNOTFOUND;
4950
4951     typeinfo = ((MSFT_GuidEntry *)&This->typelib_segment_data[MSFT_SEG_GUID][guidoffset])->hreftype;
4952     if (typeinfo < 0) return TYPE_E_ELEMENTNOTFOUND;
4953
4954     return ctl2_find_typeinfo_from_offset(This, typeinfo, ppTinfo);
4955 }
4956
4957 /******************************************************************************
4958  * ITypeLib2_GetLibAttr {OLEAUT32}
4959  *
4960  *  See ITypeLib_GetLibAttr.
4961  */
4962 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4963         ITypeLib2 * iface,
4964         TLIBATTR** ppTLibAttr)
4965 {
4966     ICreateTypeLib2Impl *This = impl_from_ITypeLib2(iface);
4967
4968     TRACE("(%p,%p)\n", This, ppTLibAttr);
4969
4970     if(!ppTLibAttr)
4971         return E_INVALIDARG;
4972
4973     *ppTLibAttr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TLIBATTR));
4974     if(!*ppTLibAttr)
4975         return E_OUTOFMEMORY;
4976
4977     if(This->typelib_header.posguid != -1) {
4978         MSFT_GuidEntry *guid;
4979
4980         guid = (MSFT_GuidEntry*)&This->typelib_segment_data[MSFT_SEG_GUID][This->typelib_header.posguid];
4981         (*ppTLibAttr)->guid = guid->guid;
4982     }
4983
4984     (*ppTLibAttr)->lcid = This->typelib_header.lcid;
4985     (*ppTLibAttr)->syskind = This->typelib_header.varflags&0x3;
4986     (*ppTLibAttr)->wMajorVerNum = This->typelib_header.version&0xffff;
4987     (*ppTLibAttr)->wMinorVerNum = This->typelib_header.version>>16;
4988     (*ppTLibAttr)->wLibFlags = This->typelib_header.flags;
4989     return S_OK;
4990 }
4991
4992 /******************************************************************************
4993  * ITypeLib2_GetTypeComp {OLEAUT32}
4994  *
4995  *  See ITypeLib_GetTypeComp.
4996  */
4997 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4998         ITypeLib2 * iface,
4999         ITypeComp** ppTComp)
5000 {
5001     ICreateTypeLib2Impl *This = impl_from_ITypeLib2(iface);
5002
5003     FIXME("(%p,%p), stub!\n", This, ppTComp);
5004
5005     return E_OUTOFMEMORY;
5006 }
5007
5008 /******************************************************************************
5009  * ITypeLib2_GetDocumentation {OLEAUT32}
5010  *
5011  *  See ITypeLib_GetDocumentation.
5012  */
5013 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
5014         ITypeLib2 * iface,
5015         INT index,
5016         BSTR* pBstrName,
5017         BSTR* pBstrDocString,
5018         DWORD* pdwHelpContext,
5019         BSTR* pBstrHelpFile)
5020 {
5021     ICreateTypeLib2Impl *This = impl_from_ITypeLib2(iface);
5022     WCHAR *string;
5023
5024     TRACE("(%p,%d,%p,%p,%p,%p)\n", This, index, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5025
5026     if(index != -1) {
5027         ICreateTypeInfo2Impl *iter;
5028
5029         for(iter=This->typeinfos; iter!=NULL && index!=0; iter=iter->next_typeinfo)
5030             index--;
5031
5032         if(!iter)
5033             return TYPE_E_ELEMENTNOTFOUND;
5034
5035         return ITypeInfo_GetDocumentation((ITypeInfo*)&iter->lpVtblTypeInfo2,
5036                 -1, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5037     }
5038
5039     if(pBstrName) {
5040         if(This->typelib_header.NameOffset == -1)
5041             *pBstrName = NULL;
5042         else {
5043             MSFT_NameIntro *name = (MSFT_NameIntro*)&This->
5044                 typelib_segment_data[MSFT_SEG_NAME][This->typelib_header.NameOffset];
5045
5046             ctl2_decode_name((char*)&name->namelen, &string);
5047
5048             *pBstrName = SysAllocString(string);
5049             if(!*pBstrName)
5050                 return E_OUTOFMEMORY;
5051         }
5052     }
5053
5054     if(pBstrDocString) {
5055         if(This->typelib_header.helpstring == -1)
5056             *pBstrDocString = NULL;
5057         else {
5058             ctl2_decode_string(&This->typelib_segment_data[MSFT_SEG_STRING][This->typelib_header.helpstring], &string);
5059
5060             *pBstrDocString = SysAllocString(string);
5061             if(!*pBstrDocString) {
5062                 if(pBstrName) SysFreeString(*pBstrName);
5063                 return E_OUTOFMEMORY;
5064             }
5065         }
5066     }
5067
5068     if(pdwHelpContext)
5069         *pdwHelpContext = This->typelib_header.helpcontext;
5070
5071     if(pBstrHelpFile) {
5072         if(This->typelib_header.helpfile == -1)
5073             *pBstrHelpFile = NULL;
5074         else {
5075             ctl2_decode_string(&This->typelib_segment_data[MSFT_SEG_STRING][This->typelib_header.helpfile], &string);
5076
5077             *pBstrHelpFile = SysAllocString(string);
5078             if(!*pBstrHelpFile) {
5079                 if(pBstrName) SysFreeString(*pBstrName);
5080                 if(pBstrDocString) SysFreeString(*pBstrDocString);
5081                 return E_OUTOFMEMORY;
5082             }
5083         }
5084     }
5085
5086     return S_OK;
5087 }
5088
5089 /******************************************************************************
5090  * ITypeLib2_IsName {OLEAUT32}
5091  *
5092  *  See ITypeLib_IsName.
5093  */
5094 static HRESULT WINAPI ITypeLib2_fnIsName(
5095         ITypeLib2 * iface,
5096         LPOLESTR szNameBuf,
5097         ULONG lHashVal,
5098         BOOL* pfName)
5099 {
5100     ICreateTypeLib2Impl *This = impl_from_ITypeLib2(iface);
5101
5102     char *encoded_name;
5103     int nameoffset;
5104     MSFT_NameIntro *nameintro;
5105
5106     TRACE("(%p,%s,%x,%p)\n", iface, debugstr_w(szNameBuf), lHashVal, pfName);
5107
5108     ctl2_encode_name(This, szNameBuf, &encoded_name);
5109     nameoffset = ctl2_find_name(This, encoded_name);
5110
5111     *pfName = 0;
5112
5113     if (nameoffset == -1) return S_OK;
5114
5115     nameintro = (MSFT_NameIntro *)(&This->typelib_segment_data[MSFT_SEG_NAME][nameoffset]);
5116     if (nameintro->hreftype == -1) return S_OK;
5117
5118     *pfName = 1;
5119
5120     FIXME("Should be decoding our copy of the name over szNameBuf.\n");
5121
5122     return S_OK;
5123 }
5124
5125 /******************************************************************************
5126  * ITypeLib2_FindName {OLEAUT32}
5127  *
5128  *  See ITypeLib_FindName.
5129  */
5130 static HRESULT WINAPI ITypeLib2_fnFindName(
5131         ITypeLib2 * iface,
5132         LPOLESTR szNameBuf,
5133         ULONG lHashVal,
5134         ITypeInfo** ppTInfo,
5135         MEMBERID* rgMemId,
5136         USHORT* pcFound)
5137 {
5138     ICreateTypeLib2Impl *This = impl_from_ITypeLib2(iface);
5139
5140     FIXME("(%p,%s,%x,%p,%p,%p), stub!\n", This, debugstr_w(szNameBuf), lHashVal, ppTInfo, rgMemId, pcFound);
5141
5142     return E_OUTOFMEMORY;
5143 }
5144
5145 /******************************************************************************
5146  * ITypeLib2_ReleaseTLibAttr {OLEAUT32}
5147  *
5148  *  See ITypeLib_ReleaseTLibAttr.
5149  */
5150 static void WINAPI ITypeLib2_fnReleaseTLibAttr(
5151         ITypeLib2 * iface,
5152         TLIBATTR* pTLibAttr)
5153 {
5154     TRACE("(%p,%p)\n", iface, pTLibAttr);
5155
5156     HeapFree(GetProcessHeap(), 0, pTLibAttr);
5157 }
5158
5159 /******************************************************************************
5160  * ICreateTypeLib2_GetCustData {OLEAUT32}
5161  *
5162  *  Retrieves a custom data value stored on a type library.
5163  *
5164  * RETURNS
5165  *
5166  *  Success: S_OK
5167  *  Failure: E_OUTOFMEMORY or E_INVALIDARG.
5168  */
5169 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5170         ITypeLib2 * iface, /* [I] The type library in which to find the custom data. */
5171         REFGUID guid,      /* [I] The GUID under which the custom data is stored. */
5172         VARIANT* pVarVal)  /* [O] The custom data. */
5173 {
5174     ICreateTypeLib2Impl *This = impl_from_ITypeLib2(iface);
5175
5176     FIXME("(%p,%s,%p), stub!\n", This, debugstr_guid(guid), pVarVal);
5177
5178     return E_OUTOFMEMORY;
5179 }
5180
5181 /******************************************************************************
5182  * ICreateTypeLib2_GetLibStatistics {OLEAUT32}
5183  *
5184  *  Retrieves some statistics about names in a type library, supposedly for
5185  *  hash table optimization purposes.
5186  *
5187  * RETURNS
5188  *
5189  *  Success: S_OK
5190  *  Failure: E_OUTOFMEMORY or E_INVALIDARG.
5191  */
5192 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5193         ITypeLib2 * iface,      /* [I] The type library to get statistics about. */
5194         ULONG* pcUniqueNames,   /* [O] The number of unique names in the type library. */
5195         ULONG* pcchUniqueNames) /* [O] The number of changed (?) characters in names in the type library. */
5196 {
5197     ICreateTypeLib2Impl *This = impl_from_ITypeLib2(iface);
5198
5199     FIXME("(%p,%p,%p), stub!\n", This, pcUniqueNames, pcchUniqueNames);
5200
5201     return E_OUTOFMEMORY;
5202 }
5203
5204 /******************************************************************************
5205  * ICreateTypeLib2_GetDocumentation2 {OLEAUT32}
5206  *
5207  *  Obtain locale-aware help string information.
5208  *
5209  * RETURNS
5210  *
5211  *  Success: S_OK
5212  *  Failure: STG_E_INSUFFICIENTMEMORY or E_INVALIDARG.
5213  */
5214 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5215         ITypeLib2 * iface,
5216         INT index,
5217         LCID lcid,
5218         BSTR* pbstrHelpString,
5219         DWORD* pdwHelpStringContext,
5220         BSTR* pbstrHelpStringDll)
5221 {
5222     ICreateTypeLib2Impl *This = impl_from_ITypeLib2(iface);
5223
5224     FIXME("(%p,%d,%d,%p,%p,%p), stub!\n", This, index, lcid, pbstrHelpString, pdwHelpStringContext, pbstrHelpStringDll);
5225
5226     return E_OUTOFMEMORY;
5227 }
5228
5229 /******************************************************************************
5230  * ICreateTypeLib2_GetAllCustData {OLEAUT32}
5231  *
5232  *  Retrieve all of the custom data for a type library.
5233  *
5234  * RETURNS
5235  *
5236  *  Success: S_OK
5237  *  Failure: E_OUTOFMEMORY or E_INVALIDARG.
5238  */
5239 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5240         ITypeLib2 * iface,   /* [I] The type library in which to find the custom data. */
5241         CUSTDATA* pCustData) /* [O] The structure in which to place the custom data. */
5242 {
5243     ICreateTypeLib2Impl *This = impl_from_ITypeLib2(iface);
5244
5245     FIXME("(%p,%p), stub!\n", This, pCustData);
5246
5247     return E_OUTOFMEMORY;
5248 }
5249
5250
5251 /*================== ICreateTypeLib2 & ITypeLib2 VTABLEs And Creation ===================================*/
5252
5253 static const ICreateTypeLib2Vtbl ctypelib2vt =
5254 {
5255
5256     ICreateTypeLib2_fnQueryInterface,
5257     ICreateTypeLib2_fnAddRef,
5258     ICreateTypeLib2_fnRelease,
5259
5260     ICreateTypeLib2_fnCreateTypeInfo,
5261     ICreateTypeLib2_fnSetName,
5262     ICreateTypeLib2_fnSetVersion,
5263     ICreateTypeLib2_fnSetGuid,
5264     ICreateTypeLib2_fnSetDocString,
5265     ICreateTypeLib2_fnSetHelpFileName,
5266     ICreateTypeLib2_fnSetHelpContext,
5267     ICreateTypeLib2_fnSetLcid,
5268     ICreateTypeLib2_fnSetLibFlags,
5269     ICreateTypeLib2_fnSaveAllChanges,
5270
5271     ICreateTypeLib2_fnDeleteTypeInfo,
5272     ICreateTypeLib2_fnSetCustData,
5273     ICreateTypeLib2_fnSetHelpStringContext,
5274     ICreateTypeLib2_fnSetHelpStringDll
5275 };
5276
5277 static const ITypeLib2Vtbl typelib2vt =
5278 {
5279
5280     ITypeLib2_fnQueryInterface,
5281     ITypeLib2_fnAddRef,
5282     ITypeLib2_fnRelease,
5283
5284     ITypeLib2_fnGetTypeInfoCount,
5285     ITypeLib2_fnGetTypeInfo,
5286     ITypeLib2_fnGetTypeInfoType,
5287     ITypeLib2_fnGetTypeInfoOfGuid,
5288     ITypeLib2_fnGetLibAttr,
5289     ITypeLib2_fnGetTypeComp,
5290     ITypeLib2_fnGetDocumentation,
5291     ITypeLib2_fnIsName,
5292     ITypeLib2_fnFindName,
5293     ITypeLib2_fnReleaseTLibAttr,
5294
5295     ITypeLib2_fnGetCustData,
5296     ITypeLib2_fnGetLibStatistics,
5297     ITypeLib2_fnGetDocumentation2,
5298     ITypeLib2_fnGetAllCustData,
5299 };
5300
5301 static ICreateTypeLib2 *ICreateTypeLib2_Constructor(SYSKIND syskind, LPCOLESTR szFile)
5302 {
5303     ICreateTypeLib2Impl *pCreateTypeLib2Impl;
5304     int failed = 0;
5305
5306     TRACE("Constructing ICreateTypeLib2 (%d, %s)\n", syskind, debugstr_w(szFile));
5307
5308     pCreateTypeLib2Impl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ICreateTypeLib2Impl));
5309     if (!pCreateTypeLib2Impl) return NULL;
5310
5311     pCreateTypeLib2Impl->filename = HeapAlloc(GetProcessHeap(), 0, (strlenW(szFile) + 1) * sizeof(WCHAR));
5312     if (!pCreateTypeLib2Impl->filename) {
5313         HeapFree(GetProcessHeap(), 0, pCreateTypeLib2Impl);
5314         return NULL;
5315     }
5316     strcpyW(pCreateTypeLib2Impl->filename, szFile);
5317
5318     ctl2_init_header(pCreateTypeLib2Impl);
5319     ctl2_init_segdir(pCreateTypeLib2Impl);
5320
5321     pCreateTypeLib2Impl->typelib_header.varflags |= syskind;
5322
5323     /*
5324      * The following two calls return an offset or -1 if out of memory. We
5325      * specifically need an offset of 0, however, so...
5326      */
5327     if (ctl2_alloc_segment(pCreateTypeLib2Impl, MSFT_SEG_GUIDHASH, 0x80, 0x80)) { failed = 1; }
5328     if (ctl2_alloc_segment(pCreateTypeLib2Impl, MSFT_SEG_NAMEHASH, 0x200, 0x200)) { failed = 1; }
5329
5330     pCreateTypeLib2Impl->typelib_guidhash_segment = (int *)pCreateTypeLib2Impl->typelib_segment_data[MSFT_SEG_GUIDHASH];
5331     pCreateTypeLib2Impl->typelib_namehash_segment = (int *)pCreateTypeLib2Impl->typelib_segment_data[MSFT_SEG_NAMEHASH];
5332
5333     memset(pCreateTypeLib2Impl->typelib_guidhash_segment, 0xff, 0x80);
5334     memset(pCreateTypeLib2Impl->typelib_namehash_segment, 0xff, 0x200);
5335
5336     pCreateTypeLib2Impl->lpVtbl = &ctypelib2vt;
5337     pCreateTypeLib2Impl->lpVtblTypeLib2 = &typelib2vt;
5338     pCreateTypeLib2Impl->ref = 1;
5339
5340     if (failed) {
5341         ICreateTypeLib2_fnRelease((ICreateTypeLib2 *)pCreateTypeLib2Impl);
5342         return 0;
5343     }
5344
5345     return (ICreateTypeLib2 *)pCreateTypeLib2Impl;
5346 }
5347
5348 /******************************************************************************
5349  * CreateTypeLib2 [OLEAUT32.180]
5350  *
5351  *  Obtains an ICreateTypeLib2 object for creating a new-style (MSFT) type
5352  *  library.
5353  *
5354  * NOTES
5355  *
5356  *  See also CreateTypeLib.
5357  *
5358  * RETURNS
5359  *    Success: S_OK
5360  *    Failure: Status
5361  */
5362 HRESULT WINAPI CreateTypeLib2(
5363         SYSKIND syskind,           /* [I] System type library is for */
5364         LPCOLESTR szFile,          /* [I] Type library file name */
5365         ICreateTypeLib2** ppctlib) /* [O] Storage for object returned */
5366 {
5367     TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
5368
5369     if (!szFile) return E_INVALIDARG;
5370     *ppctlib = ICreateTypeLib2_Constructor(syskind, szFile);
5371     return (*ppctlib)? S_OK: E_OUTOFMEMORY;
5372 }
5373
5374 /******************************************************************************
5375  * ClearCustData (OLEAUT32.171)
5376  *
5377  * Clear a custom data types' data.
5378  *
5379  * PARAMS
5380  *  lpCust [I] The custom data type instance
5381  *
5382  * RETURNS
5383  *  Nothing.
5384  */
5385 void WINAPI ClearCustData(LPCUSTDATA lpCust)
5386 {
5387     if (lpCust && lpCust->cCustData)
5388     {
5389         if (lpCust->prgCustData)
5390         {
5391             DWORD i;
5392
5393             for (i = 0; i < lpCust->cCustData; i++)
5394                 VariantClear(&lpCust->prgCustData[i].varValue);
5395
5396             /* FIXME - Should be using a per-thread IMalloc */
5397             HeapFree(GetProcessHeap(), 0, lpCust->prgCustData);
5398             lpCust->prgCustData = NULL;
5399         }
5400         lpCust->cCustData = 0;
5401     }
5402 }