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