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