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