A small number of cleanups.
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 NONAMELESSUNION
39 #define NONAMELESSSTRUCT
40 #include "winerror.h"
41 #include "windef.h"
42 #include "winbase.h"
43 #include "winnls.h"
44 #include "winreg.h"
45 #include "winuser.h"
46
47 #include "wine/unicode.h"
48 #include "objbase.h"
49 #include "heap.h"
50 #include "ole2disp.h"
51 #include "typelib.h"
52 #include "wine/debug.h"
53 #include "variant.h"
54
55 WINE_DEFAULT_DEBUG_CHANNEL(typelib2);
56 /* WINE_DEFAULT_DEBUG_CHANNEL(ole); */
57
58
59 /******************************************************************************
60  * ICreateTypeLib2 {OLEAUT32}
61  *
62  * NOTES
63  *  The ICreateTypeLib2 interface provides an interface whereby one may create
64  *  new type library (.tlb) files.
65  *
66  *  This interface inherits from ICreateTypeLib, and can be freely cast back
67  *  and forth between an ICreateTypeLib and an ICreateTypeLib2 on local clients.
68  *  This dispensation applies only to ICreateTypeLib objects obtained on MSFT
69  *  format type libraries (those made through CreateTypeLib2).
70  *
71  * METHODS
72  */
73
74 /******************************************************************************
75  * ICreateTypeInfo2 {OLEAUT32}
76  *
77  * NOTES
78  *  The ICreateTypeInfo2 interface provides an interface whereby one may add
79  *  type information to type library (.tlb) files.
80  *
81  *  This interface inherits from ICreateTypeInfo, and can be freely cast back
82  *  and forth between an ICreateTypeInfo and an ICreateTypeInfo2 on local clients.
83  *  This dispensation applies only to ICreateTypeInfo objects obtained on MSFT
84  *  format type libraries (those made through CreateTypeLib2).
85  *
86  * METHODS
87  */
88
89 /*================== Implementation Structures ===================================*/
90
91 enum MSFT_segment_index {
92     MSFT_SEG_TYPEINFO = 0,  /* type information */
93     MSFT_SEG_IMPORTINFO,    /* import information */
94     MSFT_SEG_IMPORTFILES,   /* import filenames */
95     MSFT_SEG_REFERENCES,    /* references (?) */
96     MSFT_SEG_GUIDHASH,      /* hash table for guids? */
97     MSFT_SEG_GUID,          /* guid storage */
98     MSFT_SEG_NAMEHASH,      /* hash table for names */
99     MSFT_SEG_NAME,          /* name storage */
100     MSFT_SEG_STRING,        /* string storage */
101     MSFT_SEG_TYPEDESC,      /* type descriptions */
102     MSFT_SEG_ARRAYDESC,     /* array descriptions */
103     MSFT_SEG_CUSTDATA,      /* custom data */
104     MSFT_SEG_CUSTDATAGUID,  /* custom data guids */
105     MSFT_SEG_UNKNOWN,       /* ??? */
106     MSFT_SEG_UNKNOWN2,      /* ??? */
107     MSFT_SEG_MAX            /* total number of segments */
108 };
109
110 typedef struct tagMSFT_ImpFile {
111     int guid;
112     LCID lcid;
113     int version;
114     char filename[0]; /* preceeded by two bytes of encoded (length << 2) + flags in the low two bits. */
115 } MSFT_ImpFile;
116
117 typedef struct tagICreateTypeLib2Impl
118 {
119     ICOM_VFIELD(ICreateTypeLib2);
120     UINT ref;
121
122     WCHAR *filename;
123
124     MSFT_Header typelib_header;
125     MSFT_pSeg typelib_segdir[MSFT_SEG_MAX];
126     char *typelib_segment_data[MSFT_SEG_MAX];
127     int typelib_segment_block_length[MSFT_SEG_MAX];
128
129     INT typelib_typeinfo_offsets[0x200]; /* Hope that's enough. */
130
131     INT *typelib_namehash_segment;
132     INT *typelib_guidhash_segment;
133
134     struct tagICreateTypeInfo2Impl *typeinfos;
135     struct tagICreateTypeInfo2Impl *last_typeinfo;
136 } ICreateTypeLib2Impl;
137
138 typedef struct tagICreateTypeInfo2Impl
139 {
140     ICOM_VFIELD(ICreateTypeInfo2);
141     UINT ref;
142
143     ICreateTypeLib2Impl *typelib;
144     MSFT_TypeInfoBase *typeinfo;
145
146     INT *typedata;
147     int typedata_allocated;
148     int typedata_length;
149
150     int indices[42];
151     int names[42];
152     int offsets[42];
153
154     int datawidth;
155
156     struct tagICreateTypeInfo2Impl *next_typeinfo;
157 } ICreateTypeInfo2Impl;
158
159 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface);
160
161
162 /*================== Internal functions ===================================*/
163
164 /****************************************************************************
165  *      ctl2_init_header
166  *
167  *  Initializes the type library header of a new typelib.
168  */
169 static void ctl2_init_header(
170         ICreateTypeLib2Impl *This) /* [I] The typelib to initialize. */
171 {
172     This->typelib_header.magic1 = 0x5446534d;
173     This->typelib_header.magic2 = 0x00010002;
174     This->typelib_header.posguid = -1;
175     This->typelib_header.lcid = 0x0409; /* or do we use the current one? */
176     This->typelib_header.lcid2 = 0x0409;
177     This->typelib_header.varflags = 0x41;
178     This->typelib_header.version = 0;
179     This->typelib_header.flags = 0;
180     This->typelib_header.nrtypeinfos = 0;
181     This->typelib_header.helpstring = -1;
182     This->typelib_header.helpstringcontext = 0;
183     This->typelib_header.helpcontext = 0;
184     This->typelib_header.nametablecount = 0;
185     This->typelib_header.nametablechars = 0;
186     This->typelib_header.NameOffset = -1;
187     This->typelib_header.helpfile = -1;
188     This->typelib_header.CustomDataOffset = -1;
189     This->typelib_header.res44 = 0x20;
190     This->typelib_header.res48 = 0x80;
191     This->typelib_header.dispatchpos = -1;
192     This->typelib_header.res50 = 0;
193 }
194
195 /****************************************************************************
196  *      ctl2_init_segdir
197  *
198  *  Initializes the segment directory of a new typelib.
199  */
200 static void ctl2_init_segdir(
201         ICreateTypeLib2Impl *This) /* [I] The typelib to initialize. */
202 {
203     int i;
204     MSFT_pSeg *segdir;
205
206     segdir = &This->typelib_segdir[MSFT_SEG_TYPEINFO];
207
208     for (i = 0; i < 15; i++) {
209         segdir[i].offset = -1;
210         segdir[i].length = 0;
211         segdir[i].res08 = -1;
212         segdir[i].res0c = 0x0f;
213     }
214 }
215
216 /****************************************************************************
217  *      ctl2_find_name
218  *
219  *  Locates a name in a type library.
220  *
221  * RETURNS
222  *
223  *  The offset into the NAME segment of the name, or -1 if not found.
224  *
225  * NOTES
226  *
227  *  The name must be encoded as with ctl2_encode_name().
228  */
229 static int ctl2_find_name(
230         ICreateTypeLib2Impl *This, /* [I] The typelib to operate against. */
231         char *name)                /* [I] The encoded name to find. */
232 {
233     int offset;
234     int *namestruct;
235
236     offset = This->typelib_namehash_segment[name[2] & 0x7f];
237     while (offset != -1) {
238         namestruct = (int *)&This->typelib_segment_data[MSFT_SEG_NAME][offset];
239
240         if (!((namestruct[2] ^ *((int *)name)) & 0xffff00ff)) {
241             /* hash codes and lengths match, final test */
242             if (!strncasecmp(name+4, (void *)(namestruct+3), name[0])) break;
243         }
244
245         /* move to next item in hash bucket */
246         offset = namestruct[1];
247     }
248
249     return offset;
250 }
251
252 /****************************************************************************
253  *      ctl2_encode_name
254  *
255  *  Encodes a name string to a form suitable for storing into a type library
256  *  or comparing to a name stored in a type library.
257  *
258  * RETURNS
259  *
260  *  The length of the encoded name, including padding and length+hash fields.
261  *
262  * NOTES
263  *
264  *  Will throw an exception if name or result are NULL. Is not multithread
265  *  safe in the slightest.
266  */
267 static int ctl2_encode_name(
268         ICreateTypeLib2Impl *This, /* [I] The typelib to operate against (used for LCID only). */
269         WCHAR *name,               /* [I] The name string to encode. */
270         char **result)             /* [O] A pointer to a pointer to recieve the encoded name. */
271 {
272     int length;
273     static char converted_name[0x104];
274     int offset;
275     int value;
276
277     length = WideCharToMultiByte(CP_ACP, 0, name, strlenW(name), converted_name+4, 0x100, NULL, NULL);
278     converted_name[0] = length & 0xff;
279
280     converted_name[length + 4] = 0;
281
282     converted_name[1] = 0x00;
283
284     value = LHashValOfNameSysA(This->typelib_header.varflags & 0x0f, This->typelib_header.lcid, converted_name + 4);
285
286     converted_name[2] = value;
287     converted_name[3] = value >> 8;
288
289     for (offset = (4 - length) & 3; offset; offset--) converted_name[length + offset + 3] = 0x57;
290
291     *result = converted_name;
292
293     return (length + 7) & ~3;
294 }
295
296 /****************************************************************************
297  *      ctl2_encode_string
298  *
299  *  Encodes a string to a form suitable for storing into a type library or
300  *  comparing to a string stored in a type library.
301  *
302  * RETURNS
303  *
304  *  The length of the encoded string, including padding and length fields.
305  *
306  * NOTES
307  *
308  *  Will throw an exception if string or result are NULL. Is not multithread
309  *  safe in the slightest.
310  */
311 static int ctl2_encode_string(
312         ICreateTypeLib2Impl *This, /* [I] The typelib to operate against (not used?). */
313         WCHAR *string,             /* [I] The string to encode. */
314         char **result)             /* [O] A pointer to a pointer to recieve the encoded string. */
315 {
316     int length;
317     static char converted_string[0x104];
318     int offset;
319
320     length = WideCharToMultiByte(CP_ACP, 0, string, strlenW(string), converted_string+2, 0x102, NULL, NULL);
321     converted_string[0] = length & 0xff;
322     converted_string[1] = (length >> 8) & 0xff;
323
324     for (offset = (4 - (length + 2)) & 3; offset; offset--) converted_string[length + offset + 1] = 0x57;
325
326     *result = converted_string;
327
328     return (length + 5) & ~3;
329 }
330
331 /****************************************************************************
332  *      ctl2_alloc_segment
333  *
334  *  Allocates memory from a segment in a type library.
335  *
336  * RETURNS
337  *
338  *  Success: The offset within the segment of the new data area.
339  *  Failure: -1 (this is invariably an out of memory condition).
340  *
341  * BUGS
342  *
343  *  Does not (yet) handle the case where the allocated segment memory needs to grow.
344  */
345 static int ctl2_alloc_segment(
346         ICreateTypeLib2Impl *This,       /* [I] The type library in which to allocate. */
347         enum MSFT_segment_index segment, /* [I] The segment in which to allocate. */
348         int size,                        /* [I] The amount to allocate. */
349         int block_size)                  /* [I] Initial allocation block size, or 0 for default. */
350 {
351     int offset;
352
353     if(!This->typelib_segment_data[segment]) {
354         if (!block_size) block_size = 0x2000;
355
356         This->typelib_segment_block_length[segment] = block_size;
357         This->typelib_segment_data[segment] = HeapAlloc(GetProcessHeap(), 0, block_size);
358         if (!This->typelib_segment_data[segment]) return -1;
359         memset(This->typelib_segment_data[segment], 0x57, block_size);
360     }
361
362     while ((This->typelib_segdir[segment].length + size) > This->typelib_segment_block_length[segment]) {
363         char *block;
364
365         block_size = This->typelib_segment_block_length[segment];
366         block = HeapReAlloc(GetProcessHeap(), 0, This->typelib_segment_data[segment], block_size << 1);
367         if (!block) return -1;
368
369         if (segment == MSFT_SEG_TYPEINFO) {
370             /* TypeInfos have a direct pointer to their memory space, so we have to fix them up. */
371             ICreateTypeInfo2Impl *typeinfo;
372
373             for (typeinfo = This->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
374                 typeinfo->typeinfo = (void *)&block[((char *)typeinfo->typeinfo) - This->typelib_segment_data[segment]];
375             }
376         }
377
378         memset(block + block_size, 0x57, block_size);
379         This->typelib_segment_block_length[segment] = block_size << 1;
380         This->typelib_segment_data[segment] = block;
381     }
382
383     offset = This->typelib_segdir[segment].length;
384     This->typelib_segdir[segment].length += size;
385
386     return offset;
387 }
388
389 /****************************************************************************
390  *      ctl2_alloc_typeinfo
391  *
392  *  Allocates and initializes a typeinfo structure in a type library.
393  *
394  * RETURNS
395  *
396  *  Success: The offset of the new typeinfo.
397  *  Failure: -1 (this is invariably an out of memory condition).
398  */
399 static int ctl2_alloc_typeinfo(
400         ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
401         int nameoffset)            /* [I] The offset of the name for this typeinfo. */
402 {
403     int offset;
404     MSFT_TypeInfoBase *typeinfo;
405
406     offset = ctl2_alloc_segment(This, MSFT_SEG_TYPEINFO, sizeof(MSFT_TypeInfoBase), 0);
407     if (offset == -1) return -1;
408
409     This->typelib_typeinfo_offsets[This->typelib_header.nrtypeinfos++] = offset;
410
411     typeinfo = (void *)(This->typelib_segment_data[MSFT_SEG_TYPEINFO] + offset);
412
413     typeinfo->typekind = (This->typelib_header.nrtypeinfos - 1) << 16;
414     typeinfo->memoffset = -1; /* should be EOF if no elements */
415     typeinfo->res2 = 0;
416     typeinfo->res3 = -1;
417     typeinfo->res4 = 3;
418     typeinfo->res5 = 0;
419     typeinfo->cElement = 0;
420     typeinfo->res7 = 0;
421     typeinfo->res8 = 0;
422     typeinfo->res9 = 0;
423     typeinfo->resA = 0;
424     typeinfo->posguid = -1;
425     typeinfo->flags = 0;
426     typeinfo->NameOffset = nameoffset;
427     typeinfo->version = 0;
428     typeinfo->docstringoffs = -1;
429     typeinfo->helpstringcontext = 0;
430     typeinfo->helpcontext = 0;
431     typeinfo->oCustData = -1;
432     typeinfo->cbSizeVft = 0;
433     typeinfo->cImplTypes = 0;
434     typeinfo->size = 0;
435     typeinfo->datatype1 = -1;
436     typeinfo->datatype2 = 0;
437     typeinfo->res18 = 0;
438     typeinfo->res19 = -1;
439
440     return offset;
441 }
442
443 /****************************************************************************
444  *      ctl2_alloc_guid
445  *
446  *  Allocates and initializes a GUID structure in a type library. Also updates
447  *  the GUID hash table as needed.
448  *
449  * RETURNS
450  *
451  *  Success: The offset of the new GUID.
452  *  Failure: -1 (this is invariably an out of memory condition).
453  */
454 static int ctl2_alloc_guid(
455         ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
456         MSFT_GuidEntry *guid)      /* [I] The GUID to store. */
457 {
458     int offset;
459     MSFT_GuidEntry *guid_space;
460     int hash;
461     int hash_key;
462     int i;
463
464     for (offset = 0; offset < This->typelib_segdir[MSFT_SEG_GUID].length;
465          offset += sizeof(MSFT_GuidEntry)) {
466         if (!memcmp(&(This->typelib_segment_data[MSFT_SEG_GUID][offset]),
467                     guid, sizeof(GUID))) {
468             return offset;
469         }
470     }
471
472     offset = ctl2_alloc_segment(This, MSFT_SEG_GUID, sizeof(MSFT_GuidEntry), 0);
473     if (offset == -1) return -1;
474
475     guid_space = (void *)(This->typelib_segment_data[MSFT_SEG_GUID] + offset);
476     *guid_space = *guid;
477
478     hash = 0;
479     for (i = 0; i < 16; i += 2) {
480         hash ^= *((short *)&This->typelib_segment_data[MSFT_SEG_GUID][offset + i]);
481     }
482
483     hash_key = (hash & 0xf) | ((hash & 0x10) & (0 - !!(hash & 0xe0)));
484     guid_space->unk14 = This->typelib_guidhash_segment[hash_key];
485     This->typelib_guidhash_segment[hash_key] = offset;
486
487     TRACE("Updating GUID hash table (%s,0x%x).\n", debugstr_guid(&guid->guid), hash);
488
489     return offset;
490 }
491
492 /****************************************************************************
493  *      ctl2_alloc_name
494  *
495  *  Allocates and initializes a name within a type library. Also updates the
496  *  name hash table as needed.
497  *
498  * RETURNS
499  *
500  *  Success: The offset within the segment of the new name.
501  *  Failure: -1 (this is invariably an out of memory condition).
502  */
503 static int ctl2_alloc_name(
504         ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
505         WCHAR *name)               /* [I] The name to store. */
506 {
507     int length;
508     int offset;
509     MSFT_NameIntro *name_space;
510     char *encoded_name;
511
512     length = ctl2_encode_name(This, name, &encoded_name);
513
514     offset = ctl2_find_name(This, encoded_name);
515     if (offset != -1) return offset;
516
517     offset = ctl2_alloc_segment(This, MSFT_SEG_NAME, length + 8, 0);
518     if (offset == -1) return -1;
519
520     name_space = (void *)(This->typelib_segment_data[MSFT_SEG_NAME] + offset);
521     name_space->unk00 = -1;
522     name_space->unk10 = -1;
523     memcpy(&name_space->namelen, encoded_name, length);
524
525     if (This->typelib_namehash_segment[encoded_name[2] & 0x7f] != -1)
526         name_space->unk10 = This->typelib_namehash_segment[encoded_name[2] & 0x7f];
527
528     This->typelib_namehash_segment[encoded_name[2] & 0x7f] = offset;
529
530     This->typelib_header.nametablecount += 1;
531     This->typelib_header.nametablechars += *encoded_name;
532
533     return offset;
534 }
535
536 /****************************************************************************
537  *      ctl2_alloc_string
538  *
539  *  Allocates and initializes a string in a type library.
540  *
541  * RETURNS
542  *
543  *  Success: The offset within the segment of the new string.
544  *  Failure: -1 (this is invariably an out of memory condition).
545  */
546 static int ctl2_alloc_string(
547         ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
548         WCHAR *string)             /* [I] The string to store. */
549 {
550     int length;
551     int offset;
552     char *string_space;
553     char *encoded_string;
554
555     length = ctl2_encode_string(This, string, &encoded_string);
556
557     for (offset = 0; offset < This->typelib_segdir[MSFT_SEG_STRING].length;
558          offset += ((((This->typelib_segment_data[MSFT_SEG_STRING][offset + 1] << 8) & 0xff)
559              | (This->typelib_segment_data[MSFT_SEG_STRING][offset + 0] & 0xff)) + 5) & ~3) {
560         if (!memcmp(encoded_string, This->typelib_segment_data[MSFT_SEG_STRING] + offset, length)) return offset;
561     }
562
563     offset = ctl2_alloc_segment(This, MSFT_SEG_STRING, length, 0);
564     if (offset == -1) return -1;
565
566     string_space = This->typelib_segment_data[MSFT_SEG_STRING] + offset;
567     memcpy(string_space, encoded_string, length);
568
569     return offset;
570 }
571
572 /****************************************************************************
573  *      ctl2_alloc_importinfo
574  *
575  *  Allocates and initializes an import information structure in a type library.
576  *
577  * RETURNS
578  *
579  *  Success: The offset of the new importinfo.
580  *  Failure: -1 (this is invariably an out of memory condition).
581  */
582 static int ctl2_alloc_importinfo(
583         ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
584         MSFT_ImpInfo *impinfo)     /* [I] The import information to store. */
585 {
586     int offset;
587     MSFT_ImpInfo *impinfo_space;
588
589     for (offset = 0;
590          offset < This->typelib_segdir[MSFT_SEG_IMPORTINFO].length;
591          offset += sizeof(MSFT_ImpInfo)) {
592         if (!memcmp(&(This->typelib_segment_data[MSFT_SEG_IMPORTINFO][offset]),
593                     impinfo, sizeof(MSFT_ImpInfo))) {
594             return offset;
595         }
596     }
597
598     offset = ctl2_alloc_segment(This, MSFT_SEG_IMPORTINFO, sizeof(MSFT_ImpInfo), 0);
599     if (offset == -1) return -1;
600
601     impinfo_space = (void *)(This->typelib_segment_data[MSFT_SEG_IMPORTINFO] + offset);
602     *impinfo_space = *impinfo;
603
604     return offset;
605 }
606
607 /****************************************************************************
608  *      ctl2_alloc_importfile
609  *
610  *  Allocates and initializes an import file definition in a type library.
611  *
612  * RETURNS
613  *
614  *  Success: The offset of the new importinfo.
615  *  Failure: -1 (this is invariably an out of memory condition).
616  */
617 static int ctl2_alloc_importfile(
618         ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
619         int guidoffset,            /* [I] The offset to the GUID for the imported library. */
620         int major_version,         /* [I] The major version number of the imported library. */
621         int minor_version,         /* [I] The minor version number of the imported library. */
622         WCHAR *filename)           /* [I] The filename of the imported library. */
623 {
624     int length;
625     int offset;
626     MSFT_ImpFile *importfile;
627     char *encoded_string;
628
629     length = ctl2_encode_string(This, filename, &encoded_string);
630
631     encoded_string[0] <<= 2;
632     encoded_string[0] |= 1;
633
634     for (offset = 0; offset < This->typelib_segdir[MSFT_SEG_IMPORTFILES].length;
635          offset += ((((This->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xd] << 8) & 0xff)
636              | (This->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xc] & 0xff)) >> 2) + 0xc) {
637         if (!memcmp(encoded_string, This->typelib_segment_data[MSFT_SEG_IMPORTFILES] + offset + 0xc, length)) return offset;
638     }
639
640     offset = ctl2_alloc_segment(This, MSFT_SEG_IMPORTFILES, length + 0xc, 0);
641     if (offset == -1) return -1;
642
643     importfile = (MSFT_ImpFile *)&This->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset];
644     importfile->guid = guidoffset;
645     importfile->lcid = This->typelib_header.lcid2;
646     importfile->version = major_version | (minor_version << 16);
647     memcpy(&importfile->filename, encoded_string, length);
648
649     return offset;
650 }
651
652
653 /*================== ICreateTypeInfo2 Implementation ===================================*/
654
655 /******************************************************************************
656  * ICreateTypeInfo2_QueryInterface {OLEAUT32}
657  *
658  *  See IUnknown_QueryInterface.
659  */
660 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(
661         ICreateTypeInfo2 * iface,
662         REFIID riid,
663         VOID **ppvObject)
664 {
665     ICOM_THIS( ICreateTypeInfo2Impl, iface);
666
667     TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
668
669     *ppvObject=NULL;
670     if(IsEqualIID(riid, &IID_IUnknown) ||
671        IsEqualIID(riid,&IID_ICreateTypeInfo)||
672        IsEqualIID(riid,&IID_ICreateTypeInfo2))
673     {
674         *ppvObject = This;
675     } else if (IsEqualIID(riid, &IID_ITypeInfo) ||
676                IsEqualIID(riid, &IID_ITypeInfo2)) {
677         FIXME("QI for ITypeInfo interfaces not supported yet.\n");
678     }
679
680     if(*ppvObject)
681     {
682         ICreateTypeLib2_AddRef(iface);
683         TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
684         return S_OK;
685     }
686     TRACE("-- Interface: E_NOINTERFACE\n");
687     return E_NOINTERFACE;
688 }
689
690 /******************************************************************************
691  * ICreateTypeInfo2_AddRef {OLEAUT32}
692  *
693  *  See IUnknown_AddRef.
694  */
695 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
696 {
697     ICOM_THIS( ICreateTypeInfo2Impl, iface);
698
699     TRACE("(%p)->ref was %u\n",This, This->ref);
700
701     return ++(This->ref);
702 }
703
704 /******************************************************************************
705  * ICreateTypeInfo2_Release {OLEAUT32}
706  *
707  *  See IUnknown_Release.
708  */
709 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
710 {
711     ICOM_THIS( ICreateTypeInfo2Impl, iface);
712
713     --(This->ref);
714
715     TRACE("(%p)->(%u)\n",This, This->ref);
716
717     if (!This->ref) {
718         if (This->typelib) {
719             ICreateTypeLib2_fnRelease((ICreateTypeLib2 *)This->typelib);
720             This->typelib = NULL;
721         }
722
723         /* ICreateTypeLib2 frees all ICreateTypeInfos when it releases. */
724         /* HeapFree(GetProcessHeap(),0,This); */
725         return 0;
726     }
727
728     return This->ref;
729 }
730
731
732 /******************************************************************************
733  * ICreateTypeInfo2_SetGuid {OLEAUT32}
734  *
735  *  See ICreateTypeInfo_SetGuid.
736  */
737 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface, REFGUID guid)
738 {
739     ICOM_THIS(ICreateTypeInfo2Impl, iface);
740
741     MSFT_GuidEntry guidentry;
742     int offset;
743
744     TRACE("(%p,%s)\n", iface, debugstr_guid(guid));
745
746     guidentry.guid = *guid;
747     guidentry.unk10 = 0;
748     guidentry.unk14 = 0x18;
749
750     offset = ctl2_alloc_guid(This->typelib, &guidentry);
751     
752     if (offset == -1) return E_OUTOFMEMORY;
753
754     This->typeinfo->posguid = offset;
755
756     return S_OK;
757 }
758
759 /******************************************************************************
760  * ICreateTypeInfo2_SetTypeFlags {OLEAUT32}
761  *
762  *  See ICreateTypeInfo_SetTypeFlags.
763  */
764 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface, UINT uTypeFlags)
765 {
766     ICOM_THIS( ICreateTypeInfo2Impl, iface);
767
768     TRACE("(%p,0x%x)\n", iface, uTypeFlags);
769
770     This->typeinfo->flags = uTypeFlags;
771
772     if (uTypeFlags & 0x1000) {
773         MSFT_GuidEntry foo;
774         int guidoffset;
775         int fileoffset;
776         MSFT_ImpInfo impinfo;
777         WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
778
779         foo.guid = IID_StdOle;
780         foo.unk10 = 2;
781         foo.unk14 = -1;
782         guidoffset = ctl2_alloc_guid(This->typelib, &foo);
783         if (guidoffset == -1) return E_OUTOFMEMORY;
784
785         fileoffset =  ctl2_alloc_importfile(This->typelib, guidoffset, 2, 0, stdole2tlb);
786         if (fileoffset == -1) return E_OUTOFMEMORY;
787
788         foo.guid = IID_IDispatch;
789         foo.unk10 = 1;
790         foo.unk14 = -1;
791         guidoffset = ctl2_alloc_guid(This->typelib, &foo);
792         if (guidoffset == -1) return E_OUTOFMEMORY;
793
794         impinfo.res0 = 0x03010000;
795         impinfo.oImpFile = fileoffset;
796         impinfo.oGuid = guidoffset;
797         ctl2_alloc_importinfo(This->typelib, &impinfo);
798
799         This->typelib->typelib_header.dispatchpos = 1;
800         This->typelib->typelib_header.res50 = 1;
801
802         This->typeinfo->typekind |= 0x10;
803         This->typeinfo->typekind &= ~0x0f;
804         This->typeinfo->typekind |= TKIND_DISPATCH;
805     }
806
807     return S_OK;
808 }
809
810 /******************************************************************************
811  * ICreateTypeInfo2_SetDocString {OLEAUT32}
812  *
813  *  See ICreateTypeInfo_SetDocString.
814  */
815 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(
816         ICreateTypeInfo2* iface,
817         LPOLESTR pStrDoc)
818 {
819     ICOM_THIS(ICreateTypeInfo2Impl, iface);
820
821     int offset;
822
823     TRACE("(%p,%s)\n", iface, debugstr_w(pStrDoc));
824
825     offset = ctl2_alloc_string(This->typelib, pStrDoc);
826     if (offset == -1) return E_OUTOFMEMORY;
827     This->typeinfo->docstringoffs = offset;
828     return S_OK;
829 }
830
831 /******************************************************************************
832  * ICreateTypeInfo2_SetHelpContext {OLEAUT32}
833  *
834  *  See ICreateTypeInfo_SetHelpContext.
835  */
836 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(
837         ICreateTypeInfo2* iface,
838         DWORD dwHelpContext)
839 {
840     FIXME("(%p,%ld), stub!\n", iface, dwHelpContext);
841     return E_OUTOFMEMORY;
842 }
843
844 /******************************************************************************
845  * ICreateTypeInfo2_SetVersion {OLEAUT32}
846  *
847  *  See ICreateTypeInfo_SetVersion.
848  */
849 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(
850         ICreateTypeInfo2* iface,
851         WORD wMajorVerNum,
852         WORD wMinorVerNum)
853 {
854     ICOM_THIS(ICreateTypeInfo2Impl, iface);
855
856     TRACE("(%p,%d,%d)\n", iface, wMajorVerNum, wMinorVerNum);
857
858     This->typeinfo->version = wMajorVerNum | (wMinorVerNum << 16);
859     return S_OK;
860 }
861
862 /******************************************************************************
863  * ICreateTypeInfo2_AddRefTypeInfo {OLEAUT32}
864  *
865  *  See ICreateTypeInfo_AddRefTypeInfo.
866  */
867 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(
868         ICreateTypeInfo2* iface,
869         ITypeInfo* pTInfo,
870         HREFTYPE* phRefType)
871 {
872     FIXME("(%p,%p,%p), stub!\n", iface, pTInfo, phRefType);
873     return E_OUTOFMEMORY;
874 }
875
876 /******************************************************************************
877  * ICreateTypeInfo2_AddFuncDesc {OLEAUT32}
878  *
879  *  See ICreateTypeInfo_AddFuncDesc.
880  */
881 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(
882         ICreateTypeInfo2* iface,
883         UINT index,
884         FUNCDESC* pFuncDesc)
885 {
886     FIXME("(%p,%d,%p), stub!\n", iface, index, pFuncDesc);
887     return E_OUTOFMEMORY;
888 }
889
890 /******************************************************************************
891  * ICreateTypeInfo2_AddImplType {OLEAUT32}
892  *
893  *  See ICreateTypeInfo_AddImplType.
894  */
895 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(
896         ICreateTypeInfo2* iface,
897         UINT index,
898         HREFTYPE hRefType)
899 {
900     FIXME("(%p,%d,%ld), stub!\n", iface, index, hRefType);
901     return E_OUTOFMEMORY;
902 }
903
904 /******************************************************************************
905  * ICreateTypeInfo2_SetImplTypeFlags {OLEAUT32}
906  *
907  *  See ICreateTypeInfo_SetImplTypeFlags.
908  */
909 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(
910         ICreateTypeInfo2* iface,
911         UINT index,
912         INT implTypeFlags)
913 {
914     FIXME("(%p,%d,0x%x), stub!\n", iface, index, implTypeFlags);
915     return E_OUTOFMEMORY;
916 }
917
918 /******************************************************************************
919  * ICreateTypeInfo2_SetAlignment {OLEAUT32}
920  *
921  *  See ICreateTypeInfo_SetAlignment.
922  */
923 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(
924         ICreateTypeInfo2* iface,
925         WORD cbAlignment)
926 {
927     FIXME("(%p,%d), stub!\n", iface, cbAlignment);
928     return E_OUTOFMEMORY;
929 }
930
931 /******************************************************************************
932  * ICreateTypeInfo2_SetSchema {OLEAUT32}
933  *
934  *  See ICreateTypeInfo_SetSchema.
935  */
936 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(
937         ICreateTypeInfo2* iface,
938         LPOLESTR pStrSchema)
939 {
940     FIXME("(%p,%s), stub!\n", iface, debugstr_w(pStrSchema));
941     return E_OUTOFMEMORY;
942 }
943
944 /******************************************************************************
945  * ICreateTypeInfo2_AddVarDesc {OLEAUT32}
946  *
947  *  See ICreateTypeInfo_AddVarDesc.
948  */
949 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(
950         ICreateTypeInfo2* iface,
951         UINT index,
952         VARDESC* pVarDesc)
953 {
954     ICOM_THIS(ICreateTypeInfo2Impl, iface);
955     int offset;
956     INT *typedata;
957     int var_datawidth;
958     int alignment;
959
960     TRACE("(%p,%d,%p), stub!\n", iface, index, pVarDesc);
961     TRACE("%ld, %p, %ld, {{%lx, %d}, {%p, %x}}, 0x%x, %d\n", pVarDesc->memid, pVarDesc->lpstrSchema, pVarDesc->u.oInst,
962           pVarDesc->elemdescVar.tdesc.u.hreftype, pVarDesc->elemdescVar.tdesc.vt,
963           pVarDesc->elemdescVar.u.paramdesc.pparamdescex, pVarDesc->elemdescVar.u.paramdesc.wParamFlags,
964           pVarDesc->wVarFlags, pVarDesc->varkind);
965
966     if ((This->typeinfo->cElement >> 16) != index) {
967         TRACE("Out-of-order element.\n");
968         return TYPE_E_ELEMENTNOTFOUND;
969     }
970
971     if (!This->typedata) {
972         This->typedata = HeapAlloc(GetProcessHeap(), 0, 0x2000);
973         This->typedata[0] = 0;
974     }
975
976     /* allocate type data space for us */
977     offset = This->typedata[0];
978     This->typedata[0] += 0x14;
979     typedata = This->typedata + (offset >> 2) + 1;
980
981     /* fill out the basic type information */
982     typedata[0] = 0x14 | (index << 16);
983     typedata[1] = 0x80000000 | (pVarDesc->elemdescVar.tdesc.vt << 16) | pVarDesc->elemdescVar.tdesc.vt;
984     typedata[2] = pVarDesc->wVarFlags;
985     typedata[3] = 0x00240000;
986     typedata[4] = This->datawidth;
987
988     /* update the index data */
989     This->indices[index] = 0x40000000 + index;
990     This->names[index] = -1;
991     This->offsets[index] = offset;
992
993     /* figure out type widths and whatnot */
994     if (pVarDesc->elemdescVar.tdesc.vt == VT_UI4) {
995         var_datawidth = 4;
996     } else if (pVarDesc->elemdescVar.tdesc.vt == VT_BSTR) {
997         var_datawidth = 4;
998     } else if (pVarDesc->elemdescVar.tdesc.vt == VT_UI2) {
999         var_datawidth = 2;
1000     } else if (pVarDesc->elemdescVar.tdesc.vt == VT_UI1) {
1001         var_datawidth = 1;
1002     } else if (pVarDesc->elemdescVar.tdesc.vt == VT_CARRAY) {
1003         int *typedesc;
1004         int *arraydesc;
1005         int typeoffset;
1006         int arrayoffset;
1007
1008         FIXME("Array vartype, hacking badly.\n");
1009         typeoffset = ctl2_alloc_segment(This->typelib, MSFT_SEG_TYPEDESC, 8, 0);
1010         arrayoffset = ctl2_alloc_segment(This->typelib, MSFT_SEG_ARRAYDESC, 16, 0);
1011
1012         typedesc = (void *)&This->typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
1013         arraydesc = (void *)&This->typelib->typelib_segment_data[MSFT_SEG_ARRAYDESC][arrayoffset];
1014
1015         typedesc[0] = 0x7ffe001c;
1016         typedesc[1] = arrayoffset;
1017
1018         arraydesc[0] = 0x80000000 | (pVarDesc->elemdescVar.tdesc.u.lpadesc->tdescElem.vt << 16) | pVarDesc->elemdescVar.tdesc.u.lpadesc->tdescElem.vt;
1019         arraydesc[1] = 0x00080001;
1020         arraydesc[2] = 0x8;
1021         arraydesc[3] = 0;
1022
1023         typedata[1] = typeoffset;
1024         typedata[3] = 0x00380000;
1025
1026         This->datawidth += 8;
1027         var_datawidth = 0; /* FIXME: Probably wrong. */
1028     } else {
1029         FIXME("Unrecognized vartype %d.\n", pVarDesc->elemdescVar.tdesc.vt);
1030         var_datawidth = 0;
1031     }
1032
1033     if (pVarDesc->elemdescVar.tdesc.vt != VT_CARRAY) {
1034         /* pad out starting position to data width */
1035         This->datawidth += var_datawidth - 1;
1036         This->datawidth &= ~(var_datawidth - 1);
1037         typedata[4] = This->datawidth;
1038         
1039         /* add the new variable to the total data width */
1040         This->datawidth += var_datawidth;
1041     }
1042
1043     /* fix type alignment */
1044     alignment = (This->typeinfo->typekind >> 11) & 0x1f;
1045     if (alignment < var_datawidth) {
1046         alignment = var_datawidth;
1047         This->typeinfo->typekind &= ~0xf800;
1048         This->typeinfo->typekind |= alignment << 11;
1049     }
1050
1051     /* ??? */
1052     if (!This->typeinfo->res2) This->typeinfo->res2 = 0x1a;
1053     if ((index == 0) || (index == 1) || (index == 2) || (index == 4) || (index == 9)) {
1054         This->typeinfo->res2 <<= 1;
1055     }
1056
1057     /* ??? */
1058     if (This->typeinfo->res3 == -1) This->typeinfo->res3 = 0;
1059     This->typeinfo->res3 += 0x2c;
1060
1061     /* increment the number of variable elements */
1062     This->typeinfo->cElement += 0x10000;
1063
1064     /* pad data width to alignment */
1065     This->typeinfo->size = (This->datawidth + (alignment - 1)) & ~(alignment - 1);
1066
1067     return S_OK;
1068 }
1069
1070 /******************************************************************************
1071  * ICreateTypeInfo2_SetFuncAndParamNames {OLEAUT32}
1072  *
1073  *  See ICreateTypeInfo_SetFuncAndParamNames.
1074  */
1075 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(
1076         ICreateTypeInfo2* iface,
1077         UINT index,
1078         LPOLESTR* rgszNames,
1079         UINT cNames)
1080 {
1081     FIXME("(%p,%d,%s,%d), stub!\n", iface, index, debugstr_w(*rgszNames), cNames);
1082     return E_OUTOFMEMORY;
1083 }
1084
1085 /******************************************************************************
1086  * ICreateTypeInfo2_SetVarName {OLEAUT32}
1087  *
1088  *  See ICreateTypeInfo_SetVarName.
1089  */
1090 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(
1091         ICreateTypeInfo2* iface,
1092         UINT index,
1093         LPOLESTR szName)
1094 {
1095     ICOM_THIS(ICreateTypeInfo2Impl, iface);
1096     int offset;
1097     char *namedata;
1098
1099     TRACE("(%p,%d,%s), stub!\n", iface, index, debugstr_w(szName));
1100
1101     if ((This->typeinfo->cElement >> 16) <= index) {
1102         TRACE("Out-of-order element.\n");
1103         return TYPE_E_ELEMENTNOTFOUND;
1104     }
1105
1106     offset = ctl2_alloc_name(This->typelib, szName);
1107     if (offset == -1) return E_OUTOFMEMORY;
1108
1109     namedata = This->typelib->typelib_segment_data[MSFT_SEG_NAME] + offset;
1110     *((INT *)namedata) = 0;
1111     namedata[9] = 0x10;
1112     This->names[index] = offset;
1113
1114     return S_OK;
1115 }
1116
1117 /******************************************************************************
1118  * ICreateTypeInfo2_SetTypeDescAlias {OLEAUT32}
1119  *
1120  *  See ICreateTypeInfo_SetTypeDescAlias.
1121  */
1122 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(
1123         ICreateTypeInfo2* iface,
1124         TYPEDESC* pTDescAlias)
1125 {
1126     FIXME("(%p,%p), stub!\n", iface, pTDescAlias);
1127     return E_OUTOFMEMORY;
1128 }
1129
1130 /******************************************************************************
1131  * ICreateTypeInfo2_DefineFuncAsDllEntry {OLEAUT32}
1132  *
1133  *  See ICreateTypeInfo_DefineFuncAsDllEntry.
1134  */
1135 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(
1136         ICreateTypeInfo2* iface,
1137         UINT index,
1138         LPOLESTR szDllName,
1139         LPOLESTR szProcName)
1140 {
1141     FIXME("(%p,%d,%s,%s), stub!\n", iface, index, debugstr_w(szDllName), debugstr_w(szProcName));
1142     return E_OUTOFMEMORY;
1143 }
1144
1145 /******************************************************************************
1146  * ICreateTypeInfo2_SetFuncDocString {OLEAUT32}
1147  *
1148  *  See ICreateTypeInfo_SetFuncDocString.
1149  */
1150 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(
1151         ICreateTypeInfo2* iface,
1152         UINT index,
1153         LPOLESTR szDocString)
1154 {
1155     FIXME("(%p,%d,%s), stub!\n", iface, index, debugstr_w(szDocString));
1156     return E_OUTOFMEMORY;
1157 }
1158
1159 /******************************************************************************
1160  * ICreateTypeInfo2_SetVarDocString {OLEAUT32}
1161  *
1162  *  See ICreateTypeInfo_SetVarDocString.
1163  */
1164 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(
1165         ICreateTypeInfo2* iface,
1166         UINT index,
1167         LPOLESTR szDocString)
1168 {
1169     ICOM_THIS(ICreateTypeInfo2Impl, iface);
1170
1171     FIXME("(%p,%d,%s), stub!\n", iface, index, debugstr_w(szDocString));
1172
1173     ctl2_alloc_string(This->typelib, szDocString);
1174
1175     return E_OUTOFMEMORY;
1176 }
1177
1178 /******************************************************************************
1179  * ICreateTypeInfo2_SetFuncHelpContext {OLEAUT32}
1180  *
1181  *  See ICreateTypeInfo_SetFuncHelpContext.
1182  */
1183 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(
1184         ICreateTypeInfo2* iface,
1185         UINT index,
1186         DWORD dwHelpContext)
1187 {
1188     FIXME("(%p,%d,%ld), stub!\n", iface, index, dwHelpContext);
1189     return E_OUTOFMEMORY;
1190 }
1191
1192 /******************************************************************************
1193  * ICreateTypeInfo2_SetVarHelpContext {OLEAUT32}
1194  *
1195  *  See ICreateTypeInfo_SetVarHelpContext.
1196  */
1197 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(
1198         ICreateTypeInfo2* iface,
1199         UINT index,
1200         DWORD dwHelpContext)
1201 {
1202     FIXME("(%p,%d,%ld), stub!\n", iface, index, dwHelpContext);
1203     return E_OUTOFMEMORY;
1204 }
1205
1206 /******************************************************************************
1207  * ICreateTypeInfo2_SetMops {OLEAUT32}
1208  *
1209  *  See ICreateTypeInfo_SetMops.
1210  */
1211 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(
1212         ICreateTypeInfo2* iface,
1213         UINT index,
1214         BSTR bstrMops)
1215 {
1216     FIXME("(%p,%d,%p), stub!\n", iface, index, bstrMops);
1217     return E_OUTOFMEMORY;
1218 }
1219
1220 /******************************************************************************
1221  * ICreateTypeInfo2_SetTypeIdldesc {OLEAUT32}
1222  *
1223  *  See ICreateTypeInfo_SetTypeIdldesc.
1224  */
1225 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(
1226         ICreateTypeInfo2* iface,
1227         IDLDESC* pIdlDesc)
1228 {
1229     FIXME("(%p,%p), stub!\n", iface, pIdlDesc);
1230     return E_OUTOFMEMORY;
1231 }
1232
1233 /******************************************************************************
1234  * ICreateTypeInfo2_LayOut {OLEAUT32}
1235  *
1236  *  See ICreateTypeInfo_LayOut.
1237  */
1238 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(
1239         ICreateTypeInfo2* iface)
1240 {
1241     TRACE("(%p), stub!\n", iface);
1242 /*     return E_OUTOFMEMORY; */
1243     return S_OK;
1244 }
1245
1246 /******************************************************************************
1247  * ICreateTypeInfo2_DeleteFuncDesc {OLEAUT32}
1248  *
1249  *  Delete a function description from a type.
1250  *
1251  * RETURNS
1252  *
1253  *  Success: S_OK.
1254  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
1255  */
1256 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(
1257         ICreateTypeInfo2* iface, /* [I] The typeinfo from which to delete a function. */
1258         UINT index)              /* [I] The index of the function to delete. */
1259 {
1260     FIXME("(%p,%d), stub!\n", iface, index);
1261     return E_OUTOFMEMORY;
1262 }
1263
1264 /******************************************************************************
1265  * ICreateTypeInfo2_DeleteFuncDescByMemId {OLEAUT32}
1266  *
1267  *  Delete a function description from a type.
1268  *
1269  * RETURNS
1270  *
1271  *  Success: S_OK.
1272  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
1273  */
1274 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(
1275         ICreateTypeInfo2* iface, /* [I] The typeinfo from which to delete a function. */
1276         MEMBERID memid,          /* [I] The member id of the function to delete. */
1277         INVOKEKIND invKind)      /* [I] The invocation type of the function to delete. (?) */
1278 {
1279     FIXME("(%p,%ld,%d), stub!\n", iface, memid, invKind);
1280     return E_OUTOFMEMORY;
1281 }
1282
1283 /******************************************************************************
1284  * ICreateTypeInfo2_DeleteVarDesc {OLEAUT32}
1285  *
1286  *  Delete a variable description from a type.
1287  *
1288  * RETURNS
1289  *
1290  *  Success: S_OK.
1291  *  Failure: One of E_OUTOFMEMORY, E_INVALIDARG, TYPE_E_IOERROR,
1292  *  TYPE_E_INVDATAREAD, TYPE_E_UNSUPFORMAT or TYPE_E_INVALIDSTATE.
1293  */
1294 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(
1295         ICreateTypeInfo2* iface, /* [I] The typeinfo from which to delete the variable description. */
1296         UINT index)              /* [I] The index of the variable description to delete. */
1297 {
1298     FIXME("(%p,%d), stub!\n", iface, index);
1299     return E_OUTOFMEMORY;
1300 }
1301
1302 /******************************************************************************
1303  * ICreateTypeInfo2_DeleteVarDescByMemId {OLEAUT32}
1304  *
1305  *  Delete a variable description from a type.
1306  *
1307  * RETURNS
1308  *
1309  *  Success: S_OK.
1310  *  Failure: One of E_OUTOFMEMORY, E_INVALIDARG, TYPE_E_IOERROR,
1311  *  TYPE_E_INVDATAREAD, TYPE_E_UNSUPFORMAT or TYPE_E_INVALIDSTATE.
1312  */
1313 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(
1314         ICreateTypeInfo2* iface, /* [I] The typeinfo from which to delete the variable description. */
1315         MEMBERID memid)          /* [I] The member id of the variable description to delete. */
1316 {
1317     FIXME("(%p,%ld), stub!\n", iface, memid);
1318     return E_OUTOFMEMORY;
1319 }
1320
1321 /******************************************************************************
1322  * ICreateTypeInfo2_DeleteImplType {OLEAUT32}
1323  *
1324  *  Delete an interface implementation from a type. (?)
1325  *
1326  * RETURNS
1327  *
1328  *  Success: S_OK.
1329  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
1330  */
1331 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(
1332         ICreateTypeInfo2* iface, /* [I] The typeinfo from which to delete. */
1333         UINT index)              /* [I] The index of the interface to delete. */
1334 {
1335     FIXME("(%p,%d), stub!\n", iface, index);
1336     return E_OUTOFMEMORY;
1337 }
1338
1339 /******************************************************************************
1340  * ICreateTypeInfo2_SetCustData {OLEAUT32}
1341  *
1342  *  Set the custom data for a type.
1343  *
1344  * RETURNS
1345  *
1346  *  Success: S_OK.
1347  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
1348  */
1349 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(
1350         ICreateTypeInfo2* iface, /* [I] The typeinfo in which to set the custom data. */
1351         REFGUID guid,            /* [I] The GUID used as a key to retrieve the custom data. */
1352         VARIANT* pVarVal)        /* [I] The custom data. */
1353 {
1354     FIXME("(%p,%s,%p), stub!\n", iface, debugstr_guid(guid), pVarVal);
1355     return E_OUTOFMEMORY;
1356 }
1357
1358 /******************************************************************************
1359  * ICreateTypeInfo2_SetFuncCustData {OLEAUT32}
1360  *
1361  *  Set the custom data for a function.
1362  *
1363  * RETURNS
1364  *
1365  *  Success: S_OK.
1366  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
1367  */
1368 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(
1369         ICreateTypeInfo2* iface, /* [I] The typeinfo in which to set the custom data. */
1370         UINT index,              /* [I] The index of the function for which to set the custom data. */
1371         REFGUID guid,            /* [I] The GUID used as a key to retrieve the custom data. */
1372         VARIANT* pVarVal)        /* [I] The custom data. */
1373 {
1374     FIXME("(%p,%d,%s,%p), stub!\n", iface, index, debugstr_guid(guid), pVarVal);
1375     return E_OUTOFMEMORY;
1376 }
1377
1378 /******************************************************************************
1379  * ICreateTypeInfo2_SetParamCustData {OLEAUT32}
1380  *
1381  *  Set the custom data for a function parameter.
1382  *
1383  * RETURNS
1384  *
1385  *  Success: S_OK.
1386  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
1387  */
1388 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(
1389         ICreateTypeInfo2* iface, /* [I] The typeinfo in which to set the custom data. */
1390         UINT indexFunc,          /* [I] The index of the function on which the parameter resides. */
1391         UINT indexParam,         /* [I] The index of the paramter on which to set the custom data. */
1392         REFGUID guid,            /* [I] The GUID used as a key to retrieve the custom data. */
1393         VARIANT* pVarVal)        /* [I] The custom data. */
1394 {
1395     FIXME("(%p,%d,%d,%s,%p), stub!\n", iface, indexFunc, indexParam, debugstr_guid(guid), pVarVal);
1396     return E_OUTOFMEMORY;
1397 }
1398
1399 /******************************************************************************
1400  * ICreateTypeInfo2_SetVarCustData {OLEAUT32}
1401  *
1402  *  Set the custom data for a variable.
1403  *
1404  * RETURNS
1405  *
1406  *  Success: S_OK.
1407  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
1408  */
1409 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(
1410         ICreateTypeInfo2* iface, /* [I] The typeinfo in which to set the custom data. */
1411         UINT index,              /* [I] The index of the variable on which to set the custom data. */
1412         REFGUID guid,            /* [I] The GUID used as a key to retrieve the custom data. */
1413         VARIANT* pVarVal)        /* [I] The custom data. */
1414 {
1415     FIXME("(%p,%d,%s,%p), stub!\n", iface, index, debugstr_guid(guid), pVarVal);
1416     return E_OUTOFMEMORY;
1417 }
1418
1419 /******************************************************************************
1420  * ICreateTypeInfo2_SetImplTypeCustData {OLEAUT32}
1421  *
1422  *  Set the custom data for an implemented interface.
1423  *
1424  * RETURNS
1425  *
1426  *  Success: S_OK.
1427  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
1428  */
1429 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(
1430         ICreateTypeInfo2* iface, /* [I] The typeinfo on which to set the custom data. */
1431         UINT index,              /* [I] The index of the implemented interface on which to set the custom data. */
1432         REFGUID guid,            /* [I] The GUID used as a key to retrieve the custom data. */
1433         VARIANT* pVarVal)        /* [I] The custom data. */
1434 {
1435     FIXME("(%p,%d,%s,%p), stub!\n", iface, index, debugstr_guid(guid), pVarVal);
1436     return E_OUTOFMEMORY;
1437 }
1438
1439 /******************************************************************************
1440  * ICreateTypeInfo2_SetHelpStringContext {OLEAUT32}
1441  *
1442  *  Set the help string context for the typeinfo.
1443  *
1444  * RETURNS
1445  *
1446  *  Success: S_OK.
1447  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
1448  */
1449 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(
1450         ICreateTypeInfo2* iface,   /* [I] The typeinfo on which to set the help string context. */
1451         ULONG dwHelpStringContext) /* [I] The help string context. */
1452 {
1453     FIXME("(%p,%ld), stub!\n", iface, dwHelpStringContext);
1454     return E_OUTOFMEMORY;
1455 }
1456
1457 /******************************************************************************
1458  * ICreateTypeInfo2_SetFuncHelpStringContext {OLEAUT32}
1459  *
1460  *  Set the help string context for a function.
1461  *
1462  * RETURNS
1463  *
1464  *  Success: S_OK.
1465  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
1466  */
1467 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(
1468         ICreateTypeInfo2* iface,   /* [I] The typeinfo on which to set the help string context. */
1469         UINT index,                /* [I] The index for the function on which to set the help string context. */
1470         ULONG dwHelpStringContext) /* [I] The help string context. */
1471 {
1472     FIXME("(%p,%d,%ld), stub!\n", iface, index, dwHelpStringContext);
1473     return E_OUTOFMEMORY;
1474 }
1475
1476 /******************************************************************************
1477  * ICreateTypeInfo2_SetVarHelpStringContext {OLEAUT32}
1478  *
1479  *  Set the help string context for a variable.
1480  *
1481  * RETURNS
1482  *
1483  *  Success: S_OK.
1484  *  Failure: One of E_OUTOFMEMORY or E_INVALIDARG.
1485  */
1486 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(
1487         ICreateTypeInfo2* iface,   /* [I] The typeinfo on which to set the help string context. */
1488         UINT index,                /* [I] The index of the variable on which to set the help string context. */
1489         ULONG dwHelpStringContext) /* [I] The help string context */
1490 {
1491     FIXME("(%p,%d,%ld), stub!\n", iface, index, dwHelpStringContext);
1492     return E_OUTOFMEMORY;
1493 }
1494
1495 /******************************************************************************
1496  * ICreateTypeInfo2_Invalidate {OLEAUT32}
1497  *
1498  *  Undocumented function. (!)
1499  */
1500 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(
1501         ICreateTypeInfo2* iface)
1502 {
1503     FIXME("(%p), stub!\n", iface);
1504     return E_OUTOFMEMORY;
1505 }
1506
1507 /******************************************************************************
1508  * ICreateTypeInfo2_SetName {OLEAUT32}
1509  *
1510  *  Set the name for a typeinfo.
1511  *
1512  * RETURNS
1513  *
1514  *  Success: S_OK.
1515  *  Failure: One of STG_E_INSUFFICIENTMEMORY, E_OUTOFMEMORY, E_INVALIDARG or TYPE_E_INVALIDSTATE.
1516  */
1517 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(
1518         ICreateTypeInfo2* iface,
1519         LPOLESTR szName)
1520 {
1521     FIXME("(%p,%s), stub!\n", iface, debugstr_w(szName));
1522     return E_OUTOFMEMORY;
1523 }
1524
1525
1526 static ICOM_VTABLE(ICreateTypeInfo2) ctypeinfo2vt =
1527 {
1528     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1529
1530     ICreateTypeInfo2_fnQueryInterface,
1531     ICreateTypeInfo2_fnAddRef,
1532     ICreateTypeInfo2_fnRelease,
1533
1534     ICreateTypeInfo2_fnSetGuid,
1535     ICreateTypeInfo2_fnSetTypeFlags,
1536     ICreateTypeInfo2_fnSetDocString,
1537     ICreateTypeInfo2_fnSetHelpContext,
1538     ICreateTypeInfo2_fnSetVersion,
1539     ICreateTypeInfo2_fnAddRefTypeInfo,
1540     ICreateTypeInfo2_fnAddFuncDesc,
1541     ICreateTypeInfo2_fnAddImplType,
1542     ICreateTypeInfo2_fnSetImplTypeFlags,
1543     ICreateTypeInfo2_fnSetAlignment,
1544     ICreateTypeInfo2_fnSetSchema,
1545     ICreateTypeInfo2_fnAddVarDesc,
1546     ICreateTypeInfo2_fnSetFuncAndParamNames,
1547     ICreateTypeInfo2_fnSetVarName,
1548     ICreateTypeInfo2_fnSetTypeDescAlias,
1549     ICreateTypeInfo2_fnDefineFuncAsDllEntry,
1550     ICreateTypeInfo2_fnSetFuncDocString,
1551     ICreateTypeInfo2_fnSetVarDocString,
1552     ICreateTypeInfo2_fnSetFuncHelpContext,
1553     ICreateTypeInfo2_fnSetVarHelpContext,
1554     ICreateTypeInfo2_fnSetMops,
1555     ICreateTypeInfo2_fnSetTypeIdldesc,
1556     ICreateTypeInfo2_fnLayOut,
1557
1558     ICreateTypeInfo2_fnDeleteFuncDesc,
1559     ICreateTypeInfo2_fnDeleteFuncDescByMemId,
1560     ICreateTypeInfo2_fnDeleteVarDesc,
1561     ICreateTypeInfo2_fnDeleteVarDescByMemId,
1562     ICreateTypeInfo2_fnDeleteImplType,
1563     ICreateTypeInfo2_fnSetCustData,
1564     ICreateTypeInfo2_fnSetFuncCustData,
1565     ICreateTypeInfo2_fnSetParamCustData,
1566     ICreateTypeInfo2_fnSetVarCustData,
1567     ICreateTypeInfo2_fnSetImplTypeCustData,
1568     ICreateTypeInfo2_fnSetHelpStringContext,
1569     ICreateTypeInfo2_fnSetFuncHelpStringContext,
1570     ICreateTypeInfo2_fnSetVarHelpStringContext,
1571     ICreateTypeInfo2_fnInvalidate,
1572     ICreateTypeInfo2_fnSetName
1573 };
1574
1575 static ICreateTypeInfo2 *ICreateTypeInfo2_Constructor(ICreateTypeLib2Impl *typelib, WCHAR *szName, TYPEKIND tkind)
1576 {
1577     ICreateTypeInfo2Impl *pCreateTypeInfo2Impl;
1578
1579     int nameoffset;
1580     int typeinfo_offset;
1581     MSFT_TypeInfoBase *typeinfo;
1582
1583     TRACE("Constructing ICreateTypeInfo2 for %s with tkind %d\n", debugstr_w(szName), tkind);
1584
1585     pCreateTypeInfo2Impl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ICreateTypeInfo2Impl));
1586     if (!pCreateTypeInfo2Impl) return NULL;
1587
1588     pCreateTypeInfo2Impl->lpVtbl = &ctypeinfo2vt;
1589     pCreateTypeInfo2Impl->ref = 1;
1590
1591     pCreateTypeInfo2Impl->typelib = typelib;
1592     typelib->ref++;
1593
1594     nameoffset = ctl2_alloc_name(typelib, szName);
1595     typeinfo_offset = ctl2_alloc_typeinfo(typelib, nameoffset);
1596     typeinfo = (MSFT_TypeInfoBase *)&typelib->typelib_segment_data[MSFT_SEG_TYPEINFO][typeinfo_offset];
1597
1598     typelib->typelib_segment_data[MSFT_SEG_NAME][nameoffset + 9] = 0x38;
1599     *((int *)&typelib->typelib_segment_data[MSFT_SEG_NAME][nameoffset]) = typeinfo_offset;
1600
1601     pCreateTypeInfo2Impl->typeinfo = typeinfo;
1602
1603     if (tkind == TKIND_ENUM) {
1604         typeinfo->typekind |= TKIND_ENUM | 0x2120;
1605         typeinfo->size = 4;
1606     } else if (tkind == TKIND_RECORD) {
1607         typeinfo->typekind |= TKIND_RECORD | 0x0920;
1608         typeinfo->size = 0;
1609     } else if (tkind == TKIND_MODULE) {
1610         typeinfo->typekind |= TKIND_MODULE | 0x0920;
1611         typeinfo->size = 2;
1612     } else if (tkind == TKIND_INTERFACE) {
1613         typeinfo->typekind |= TKIND_INTERFACE | 0x2120;
1614         typeinfo->size = 4;
1615     } else if (tkind == TKIND_DISPATCH) {
1616         typeinfo->typekind |= TKIND_DISPATCH | 0x2120;
1617         typeinfo->size = 4;
1618     } else if (tkind == TKIND_COCLASS) {
1619         typeinfo->typekind |= TKIND_COCLASS | 0x2120;
1620         typeinfo->size = 4;
1621     } else if (tkind == TKIND_ALIAS) {
1622         typeinfo->typekind |= TKIND_ALIAS | 0x2120;
1623         typeinfo->size = -0x75; /* ??? */
1624     } else if (tkind == TKIND_UNION) {
1625         typeinfo->typekind |= TKIND_UNION | 0x0920;
1626         typeinfo->size = 0;
1627     } else {
1628         FIXME("(%s,%d), unrecognized typekind %d\n", debugstr_w(szName), tkind, tkind);
1629         typeinfo->typekind |= tkind;
1630         typeinfo->size = 0xdeadbeef;
1631     }
1632
1633     if (typelib->last_typeinfo) typelib->last_typeinfo->next_typeinfo = pCreateTypeInfo2Impl;
1634     typelib->last_typeinfo = pCreateTypeInfo2Impl;
1635     if (!typelib->typeinfos) typelib->typeinfos = pCreateTypeInfo2Impl;
1636
1637     TRACE(" -- %p\n", pCreateTypeInfo2Impl);
1638
1639     return (ICreateTypeInfo2 *)pCreateTypeInfo2Impl;
1640 }
1641
1642
1643 /*================== ICreateTypeLib2 Implementation ===================================*/
1644
1645 /******************************************************************************
1646  * ICreateTypeLib2_QueryInterface {OLEAUT32}
1647  *
1648  *  See IUnknown_QueryInterface.
1649  */
1650 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(
1651         ICreateTypeLib2 * iface,
1652         REFIID riid,
1653         VOID **ppvObject)
1654 {
1655     ICOM_THIS( ICreateTypeLib2Impl, iface);
1656
1657     TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
1658
1659     *ppvObject=NULL;
1660     if(IsEqualIID(riid, &IID_IUnknown) ||
1661        IsEqualIID(riid,&IID_ICreateTypeLib)||
1662        IsEqualIID(riid,&IID_ICreateTypeLib2))
1663     {
1664         *ppvObject = This;
1665     } else if (IsEqualIID(riid, &IID_ITypeLib) ||
1666                IsEqualIID(riid, &IID_ITypeLib2)) {
1667         FIXME("QI for ITypeLib interfaces not supported yet.\n");
1668     }
1669
1670     if(*ppvObject)
1671     {
1672         ICreateTypeLib2_AddRef(iface);
1673         TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
1674         return S_OK;
1675     }
1676     TRACE("-- Interface: E_NOINTERFACE\n");
1677     return E_NOINTERFACE;
1678 }
1679
1680 /******************************************************************************
1681  * ICreateTypeLib2_AddRef {OLEAUT32}
1682  *
1683  *  See IUnknown_AddRef.
1684  */
1685 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
1686 {
1687     ICOM_THIS( ICreateTypeLib2Impl, iface);
1688
1689     TRACE("(%p)->ref was %u\n",This, This->ref);
1690
1691     return ++(This->ref);
1692 }
1693
1694 /******************************************************************************
1695  * ICreateTypeLib2_Release {OLEAUT32}
1696  *
1697  *  See IUnknown_Release.
1698  */
1699 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
1700 {
1701     ICOM_THIS( ICreateTypeLib2Impl, iface);
1702
1703     --(This->ref);
1704
1705     TRACE("(%p)->(%u)\n",This, This->ref);
1706
1707     if (!This->ref) {
1708         int i;
1709
1710         for (i = 0; i < MSFT_SEG_MAX; i++) {
1711             if (This->typelib_segment_data[i]) {
1712                 HeapFree(GetProcessHeap(), 0, This->typelib_segment_data[i]);
1713                 This->typelib_segment_data[i] = NULL;
1714             }
1715         }
1716
1717         if (This->filename) {
1718             HeapFree(GetProcessHeap(), 0, This->filename);
1719             This->filename = NULL;
1720         }
1721
1722         while (This->typeinfos) {
1723             ICreateTypeInfo2Impl *typeinfo = This->typeinfos;
1724             This->typeinfos = typeinfo->next_typeinfo;
1725             if (typeinfo->typedata) HeapFree(GetProcessHeap(), 0, typeinfo->typedata);
1726             HeapFree(GetProcessHeap(), 0, typeinfo);
1727         }
1728
1729         HeapFree(GetProcessHeap(),0,This);
1730         return 0;
1731     }
1732
1733     return This->ref;
1734 }
1735
1736
1737 /******************************************************************************
1738  * ICreateTypeLib2_CreateTypeInfo {OLEAUT32}
1739  *
1740  *  See ICreateTypeLib_CreateTypeInfo.
1741  */
1742 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(
1743         ICreateTypeLib2 * iface,
1744         LPOLESTR szName,
1745         TYPEKIND tkind,
1746         ICreateTypeInfo **ppCTInfo)
1747 {
1748     ICOM_THIS(ICreateTypeLib2Impl, iface);
1749
1750     TRACE("(%p,%s,%d,%p)\n", iface, debugstr_w(szName), tkind, ppCTInfo);
1751
1752     *ppCTInfo = (ICreateTypeInfo *)ICreateTypeInfo2_Constructor(This, szName, tkind);
1753
1754     if (!*ppCTInfo) return E_OUTOFMEMORY;
1755
1756     return S_OK;
1757 }
1758
1759 /******************************************************************************
1760  * ICreateTypeLib2_SetName {OLEAUT32}
1761  *
1762  *  See ICreateTypeLib_SetName.
1763  */
1764 static HRESULT WINAPI ICreateTypeLib2_fnSetName(
1765         ICreateTypeLib2 * iface,
1766         LPOLESTR szName)
1767 {
1768     ICOM_THIS(ICreateTypeLib2Impl, iface);
1769
1770     int offset;
1771
1772     TRACE("(%p,%s)\n", iface, debugstr_w(szName));
1773
1774     offset = ctl2_alloc_name(This, szName);
1775     if (offset == -1) return E_OUTOFMEMORY;
1776     This->typelib_header.NameOffset = offset;
1777     return S_OK;
1778 }
1779
1780 /******************************************************************************
1781  * ICreateTypeLib2_SetVersion {OLEAUT32}
1782  *
1783  *  See ICreateTypeLib_SetVersion.
1784  */
1785 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 * iface, WORD wMajorVerNum, WORD wMinorVerNum)
1786 {
1787     ICOM_THIS(ICreateTypeLib2Impl, iface);
1788
1789     TRACE("(%p,%d,%d)\n", iface, wMajorVerNum, wMinorVerNum);
1790
1791     This->typelib_header.version = wMajorVerNum | (wMinorVerNum << 16);
1792     return S_OK;
1793 }
1794
1795 /******************************************************************************
1796  * ICreateTypeLib2_SetGuid {OLEAUT32}
1797  *
1798  *  See ICreateTypeLib_SetGuid.
1799  */
1800 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 * iface, REFGUID guid)
1801 {
1802     ICOM_THIS(ICreateTypeLib2Impl, iface);
1803
1804     MSFT_GuidEntry guidentry;
1805     int offset;
1806
1807     TRACE("(%p,%s)\n", iface, debugstr_guid(guid));
1808
1809     guidentry.guid = *guid;
1810     guidentry.unk10 = -2;
1811     guidentry.unk14 = -1;
1812
1813     offset = ctl2_alloc_guid(This, &guidentry);
1814     
1815     if (offset == -1) return E_OUTOFMEMORY;
1816
1817     This->typelib_header.posguid = offset;
1818
1819     return S_OK;
1820 }
1821
1822 /******************************************************************************
1823  * ICreateTypeLib2_SetDocString {OLEAUT32}
1824  *
1825  *  See ICreateTypeLib_SetDocString.
1826  */
1827 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 * iface, LPOLESTR szDoc)
1828 {
1829     ICOM_THIS(ICreateTypeLib2Impl, iface);
1830
1831     int offset;
1832
1833     TRACE("(%p,%s)\n", iface, debugstr_w(szDoc));
1834
1835     offset = ctl2_alloc_string(This, szDoc);
1836     if (offset == -1) return E_OUTOFMEMORY;
1837     This->typelib_header.helpstring = offset;
1838     return S_OK;
1839 }
1840
1841 /******************************************************************************
1842  * ICreateTypeLib2_SetHelpFileName {OLEAUT32}
1843  *
1844  *  See ICreateTypeLib_SetHelpFileName.
1845  */
1846 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 * iface, LPOLESTR szHelpFileName)
1847 {
1848     ICOM_THIS(ICreateTypeLib2Impl, iface);
1849
1850     int offset;
1851
1852     TRACE("(%p,%s)\n", iface, debugstr_w(szHelpFileName));
1853
1854     offset = ctl2_alloc_string(This, szHelpFileName);
1855     if (offset == -1) return E_OUTOFMEMORY;
1856     This->typelib_header.helpfile = offset;
1857     This->typelib_header.varflags |= 0x10;
1858     return S_OK;
1859 }
1860
1861 /******************************************************************************
1862  * ICreateTypeLib2_SetHelpContext {OLEAUT32}
1863  *
1864  *  See ICreateTypeLib_SetHelpContext.
1865  */
1866 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 * iface, DWORD dwHelpContext)
1867 {
1868     FIXME("(%p,%ld), stub!\n", iface, dwHelpContext);
1869     return E_OUTOFMEMORY;
1870 }
1871
1872 /******************************************************************************
1873  * ICreateTypeLib2_SetLcid {OLEAUT32}
1874  *
1875  *  See ICreateTypeLib_SetLcid.
1876  */
1877 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 * iface, LCID lcid)
1878 {
1879     ICOM_THIS(ICreateTypeLib2Impl, iface);
1880
1881     TRACE("(%p,%ld)\n", iface, lcid);
1882
1883     This->typelib_header.lcid2 = lcid;
1884
1885     return S_OK;
1886 }
1887
1888 /******************************************************************************
1889  * ICreateTypeLib2_SetLibFlags {OLEAUT32}
1890  *
1891  *  See ICreateTypeLib_SetLibFlags.
1892  */
1893 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 * iface, UINT uLibFlags)
1894 {
1895     ICOM_THIS(ICreateTypeLib2Impl, iface);
1896
1897     TRACE("(%p,0x%x)\n", iface, uLibFlags);
1898
1899     This->typelib_header.flags = uLibFlags;
1900
1901     return S_OK;
1902 }
1903
1904 static int ctl2_write_chunk(HANDLE hFile, void *segment, int length)
1905 {
1906     if (!WriteFile(hFile, segment, length, NULL, 0)) {CloseHandle(hFile); return 0;}
1907     return -1;
1908 }
1909
1910 static int ctl2_write_segment(ICreateTypeLib2Impl *This, HANDLE hFile, int segment)
1911 {
1912     if (!WriteFile(hFile, This->typelib_segment_data[segment],
1913                    This->typelib_segdir[segment].length, NULL, 0)) {
1914         CloseHandle(hFile);
1915         return 0;
1916     }
1917
1918     return -1;
1919 }
1920
1921 static void ctl2_finalize_typeinfos(ICreateTypeLib2Impl *This, int filesize)
1922 {
1923     ICreateTypeInfo2Impl *typeinfo;
1924
1925     for (typeinfo = This->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
1926         typeinfo->typeinfo->memoffset = filesize;
1927         if (typeinfo->typedata) {
1928             ICreateTypeInfo2_fnLayOut((ICreateTypeInfo2 *)typeinfo);
1929             filesize += typeinfo->typedata[0] + ((typeinfo->typeinfo->cElement >> 16) * 12) + ((typeinfo->typeinfo->cElement & 0xffff) * 12) + 4;
1930         }
1931     }
1932 }
1933
1934 static int ctl2_finalize_segment(ICreateTypeLib2Impl *This, int filepos, int segment)
1935 {
1936     if (This->typelib_segdir[segment].length) {
1937         This->typelib_segdir[segment].offset = filepos;
1938     } else {
1939         This->typelib_segdir[segment].offset = -1;
1940     }
1941
1942     return This->typelib_segdir[segment].length;
1943 }
1944
1945 static void ctl2_write_typeinfos(ICreateTypeLib2Impl *This, HANDLE hFile)
1946 {
1947     ICreateTypeInfo2Impl *typeinfo;
1948
1949     for (typeinfo = This->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
1950         if (!typeinfo->typedata) continue;
1951
1952         ctl2_write_chunk(hFile, typeinfo->typedata, typeinfo->typedata[0] + 4);
1953         ctl2_write_chunk(hFile, typeinfo->indices, ((typeinfo->typeinfo->cElement & 0xffff) + (typeinfo->typeinfo->cElement >> 16)) * 4);
1954         ctl2_write_chunk(hFile, typeinfo->names, ((typeinfo->typeinfo->cElement & 0xffff) + (typeinfo->typeinfo->cElement >> 16)) * 4);
1955         ctl2_write_chunk(hFile, typeinfo->offsets, ((typeinfo->typeinfo->cElement & 0xffff) + (typeinfo->typeinfo->cElement >> 16)) * 4);
1956     }
1957 }
1958
1959 /******************************************************************************
1960  * ICreateTypeLib2_SaveAllChanges {OLEAUT32}
1961  *
1962  *  See ICreateTypeLib_SaveAllChanges.
1963  */
1964 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 * iface)
1965 {
1966     ICOM_THIS( ICreateTypeLib2Impl, iface);
1967
1968     int retval;
1969     int filepos;
1970     HANDLE hFile;
1971
1972     TRACE("(%p)\n", iface);
1973
1974     retval = TYPE_E_IOERROR;
1975
1976     hFile = CreateFileW(This->filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
1977     if (hFile == INVALID_HANDLE_VALUE) return retval;
1978
1979     filepos = sizeof(MSFT_Header) + sizeof(MSFT_SegDir);
1980     filepos += This->typelib_header.nrtypeinfos * 4;
1981
1982     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_TYPEINFO);
1983     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_GUIDHASH);
1984     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_GUID);
1985     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_IMPORTINFO);
1986     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_IMPORTFILES);
1987     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_NAMEHASH);
1988     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_NAME);
1989     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_STRING);
1990     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_TYPEDESC);
1991     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_ARRAYDESC);
1992     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_CUSTDATA);
1993     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_CUSTDATAGUID);
1994
1995     ctl2_finalize_typeinfos(This, filepos);
1996
1997     if (!ctl2_write_chunk(hFile, &This->typelib_header, sizeof(This->typelib_header))) return retval;
1998     if (!ctl2_write_chunk(hFile, This->typelib_typeinfo_offsets, This->typelib_header.nrtypeinfos * 4)) return retval;
1999     if (!ctl2_write_chunk(hFile, &This->typelib_segdir, sizeof(This->typelib_segdir))) return retval;
2000     if (!ctl2_write_segment(This, hFile, MSFT_SEG_TYPEINFO    )) return retval;
2001     if (!ctl2_write_segment(This, hFile, MSFT_SEG_GUIDHASH    )) return retval;
2002     if (!ctl2_write_segment(This, hFile, MSFT_SEG_GUID        )) return retval;
2003     if (!ctl2_write_segment(This, hFile, MSFT_SEG_IMPORTINFO  )) return retval;
2004     if (!ctl2_write_segment(This, hFile, MSFT_SEG_IMPORTFILES )) return retval;
2005     if (!ctl2_write_segment(This, hFile, MSFT_SEG_NAMEHASH    )) return retval;
2006     if (!ctl2_write_segment(This, hFile, MSFT_SEG_NAME        )) return retval;
2007     if (!ctl2_write_segment(This, hFile, MSFT_SEG_STRING      )) return retval;
2008     if (!ctl2_write_segment(This, hFile, MSFT_SEG_TYPEDESC    )) return retval;
2009     if (!ctl2_write_segment(This, hFile, MSFT_SEG_ARRAYDESC   )) return retval;
2010     if (!ctl2_write_segment(This, hFile, MSFT_SEG_CUSTDATA    )) return retval;
2011     if (!ctl2_write_segment(This, hFile, MSFT_SEG_CUSTDATAGUID)) return retval;
2012
2013     ctl2_write_typeinfos(This, hFile);
2014
2015     if (!CloseHandle(hFile)) return retval;
2016
2017     retval = S_OK;
2018     return retval;
2019 }
2020
2021
2022 /******************************************************************************
2023  * ICreateTypeLib2_DeleteTypeInfo {OLEAUT32}
2024  *
2025  *  Deletes a named TypeInfo from a type library.
2026  *
2027  * RETURNS
2028  *
2029  *  Success: S_OK
2030  *  Failure: E_OUTOFMEMORY or E_INVALIDARG.
2031  */
2032 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(
2033         ICreateTypeLib2 * iface, /* [I] The type library to delete from. */
2034         LPOLESTR szName)         /* [I] The name of the typeinfo to delete. */
2035 {
2036     FIXME("(%p,%s), stub!\n", iface, debugstr_w(szName));
2037     return E_OUTOFMEMORY;
2038 }
2039
2040 /******************************************************************************
2041  * ICreateTypeLib2_SetCustData {OLEAUT32}
2042  *
2043  *  Sets custom data for a type library.
2044  *
2045  * RETURNS
2046  *
2047  *  Success: S_OK
2048  *  Failure: E_OUTOFMEMORY or E_INVALIDARG.
2049  */
2050 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(
2051         ICreateTypeLib2 * iface, /* [I] The type library to store the custom data in. */
2052         REFGUID guid,            /* [I] The GUID used as a key to retrieve the custom data. */
2053         VARIANT *pVarVal)        /* [I] The custom data itself. */
2054 {
2055     FIXME("(%p,%s,%p), stub!\n", iface, debugstr_guid(guid), pVarVal);
2056     return E_OUTOFMEMORY;
2057 }
2058
2059 /******************************************************************************
2060  * ICreateTypeLib2_SetHelpStringContext {OLEAUT32}
2061  *
2062  *  Sets a context number for the library help string.
2063  *
2064  * RETURNS
2065  *
2066  *  Success: S_OK
2067  *  Failure: E_OUTOFMEMORY or E_INVALIDARG.
2068  */
2069 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(
2070         ICreateTypeLib2 * iface,   /* [I] The type library to set the help string context for. */
2071         ULONG dwHelpStringContext) /* [I] The help string context. */
2072 {
2073     FIXME("(%p,%ld), stub!\n", iface, dwHelpStringContext);
2074     return E_OUTOFMEMORY;
2075 }
2076
2077 /******************************************************************************
2078  * ICreateTypeLib2_SetHelpStringDll {OLEAUT32}
2079  *
2080  *  Sets the DLL used to look up localized help strings.
2081  *
2082  * RETURNS
2083  *
2084  *  Success: S_OK
2085  *  Failure: E_OUTOFMEMORY or E_INVALIDARG.
2086  */
2087 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(
2088         ICreateTypeLib2 * iface, /* [I] The type library to set the help DLL for. */
2089         LPOLESTR szFileName)     /* [I] The name of the help DLL. */
2090 {
2091     FIXME("(%p,%s), stub!\n", iface, debugstr_w(szFileName));
2092     return E_OUTOFMEMORY;
2093 }
2094
2095
2096 static ICOM_VTABLE(ICreateTypeLib2) ctypelib2vt =
2097 {
2098     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2099
2100     ICreateTypeLib2_fnQueryInterface,
2101     ICreateTypeLib2_fnAddRef,
2102     ICreateTypeLib2_fnRelease,
2103
2104     ICreateTypeLib2_fnCreateTypeInfo,
2105     ICreateTypeLib2_fnSetName,
2106     ICreateTypeLib2_fnSetVersion,
2107     ICreateTypeLib2_fnSetGuid,
2108     ICreateTypeLib2_fnSetDocString,
2109     ICreateTypeLib2_fnSetHelpFileName,
2110     ICreateTypeLib2_fnSetHelpContext,
2111     ICreateTypeLib2_fnSetLcid,
2112     ICreateTypeLib2_fnSetLibFlags,
2113     ICreateTypeLib2_fnSaveAllChanges,
2114
2115     ICreateTypeLib2_fnDeleteTypeInfo,
2116     ICreateTypeLib2_fnSetCustData,
2117     ICreateTypeLib2_fnSetHelpStringContext,
2118     ICreateTypeLib2_fnSetHelpStringDll
2119 };
2120
2121 static ICreateTypeLib2 *ICreateTypeLib2_Constructor(SYSKIND syskind, LPCOLESTR szFile)
2122 {
2123     ICreateTypeLib2Impl *pCreateTypeLib2Impl;
2124     int failed = 0;
2125
2126     TRACE("Constructing ICreateTypeLib2 (%d, %s)\n", syskind, debugstr_w(szFile));
2127
2128     pCreateTypeLib2Impl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ICreateTypeLib2Impl));
2129     if (!pCreateTypeLib2Impl) return NULL;
2130
2131     pCreateTypeLib2Impl->filename = HeapAlloc(GetProcessHeap(), 0, (strlenW(szFile) + 1) * sizeof(WCHAR));
2132     if (!pCreateTypeLib2Impl->filename) {
2133         HeapFree(GetProcessHeap(), 0, pCreateTypeLib2Impl);
2134         return NULL;
2135     }
2136     strcpyW(pCreateTypeLib2Impl->filename, szFile);
2137
2138     ctl2_init_header(pCreateTypeLib2Impl);
2139     ctl2_init_segdir(pCreateTypeLib2Impl);
2140
2141     /*
2142      * The following two calls return an offset or -1 if out of memory. We
2143      * specifically need an offset of 0, however, so...
2144      */
2145     if (ctl2_alloc_segment(pCreateTypeLib2Impl, MSFT_SEG_GUIDHASH, 0x80, 0x80)) { failed = 1; }
2146     if (ctl2_alloc_segment(pCreateTypeLib2Impl, MSFT_SEG_NAMEHASH, 0x200, 0x200)) { failed = 1; }
2147
2148     pCreateTypeLib2Impl->typelib_guidhash_segment = (int *)pCreateTypeLib2Impl->typelib_segment_data[MSFT_SEG_GUIDHASH];
2149     pCreateTypeLib2Impl->typelib_namehash_segment = (int *)pCreateTypeLib2Impl->typelib_segment_data[MSFT_SEG_NAMEHASH];
2150
2151     memset(pCreateTypeLib2Impl->typelib_guidhash_segment, 0xff, 0x80);
2152     memset(pCreateTypeLib2Impl->typelib_namehash_segment, 0xff, 0x200);
2153
2154     pCreateTypeLib2Impl->lpVtbl = &ctypelib2vt;
2155     pCreateTypeLib2Impl->ref = 1;
2156
2157     if (failed) {
2158         ICreateTypeLib2_fnRelease((ICreateTypeLib2 *)pCreateTypeLib2Impl);
2159         return 0;
2160     }
2161
2162     return (ICreateTypeLib2 *)pCreateTypeLib2Impl;
2163 }
2164
2165 /******************************************************************************
2166  * CreateTypeLib2 [OLEAUT32.180]
2167  *
2168  *  Obtains an ICreateTypeLib2 object for creating a new-style (MSFT) type
2169  *  library.
2170  *
2171  * NOTES
2172  *
2173  *  See also CreateTypeLib.
2174  *
2175  * RETURNS
2176  *    Success: S_OK
2177  *    Failure: Status
2178  */
2179 HRESULT WINAPI CreateTypeLib2(
2180         SYSKIND syskind,           /* [I] System type library is for */
2181         LPCOLESTR szFile,          /* [I] Type library file name */
2182         ICreateTypeLib2** ppctlib) /* [O] Storage for object returned */
2183 {
2184     TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
2185
2186     if (!szFile) return E_INVALIDARG;
2187     *ppctlib = ICreateTypeLib2_Constructor(syskind, szFile);
2188     return (*ppctlib)? S_OK: E_OUTOFMEMORY;
2189 }