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