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