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