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