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