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