user32: ClipCursor should use virtual screen resolution for empty/invalid rects.
[wine] / dlls / oleaut32 / typelib.c
1 /*
2  *      TYPELIB
3  *
4  *      Copyright 1997  Marcus Meissner
5  *                    1999  Rein Klazes
6  *                    2000  Francois Jacques
7  *                    2001  Huw D M Davies for CodeWeavers
8  *                    2005  Robert Shearman, for CodeWeavers
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  *
24  * --------------------------------------------------------------------------------------
25  * Known problems (2000, Francois Jacques)
26  *
27  * - Tested using OLEVIEW (Platform SDK tool) only.
28  *
29  * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30  *   creating by doing a straight copy of the dispinterface instance and just changing
31  *   its typekind. Pointed structures aren't copied - only the address of the pointers.
32  *
33  * - locale stuff is partially implemented but hasn't been tested.
34  *
35  * - typelib file is still read in its entirety, but it is released now.
36  *
37  * --------------------------------------------------------------------------------------
38  *  Known problems left from previous implementation (1999, Rein Klazes) :
39  *
40  * -. Data structures are straightforward, but slow for look-ups.
41  * -. (related) nothing is hashed
42  * -. Most error return values are just guessed not checked with windows
43  *      behaviour.
44  * -. lousy fatal error handling
45  *
46  */
47
48 #include "config.h"
49 #include "wine/port.h"
50
51 #include <stdlib.h>
52 #include <string.h>
53 #include <stdarg.h>
54 #include <stdio.h>
55 #include <ctype.h>
56
57 #define COBJMACROS
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
60
61 #include "winerror.h"
62 #include "windef.h"
63 #include "winbase.h"
64 #include "winnls.h"
65 #include "winreg.h"
66 #include "winuser.h"
67
68 #include "wine/unicode.h"
69 #include "objbase.h"
70 #include "typelib.h"
71 #include "wine/debug.h"
72 #include "variant.h"
73
74 WINE_DEFAULT_DEBUG_CHANNEL(ole);
75 WINE_DECLARE_DEBUG_CHANNEL(typelib);
76
77 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
78 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
79
80 /****************************************************************************
81  *              FromLExxx
82  *
83  * Takes p_iVal (which is in little endian) and returns it
84  *   in the host machine's byte order.
85  */
86 #ifdef WORDS_BIGENDIAN
87 static WORD FromLEWord(WORD p_iVal)
88 {
89   return (((p_iVal & 0x00FF) << 8) |
90           ((p_iVal & 0xFF00) >> 8));
91 }
92
93
94 static DWORD FromLEDWord(DWORD p_iVal)
95 {
96   return (((p_iVal & 0x000000FF) << 24) |
97           ((p_iVal & 0x0000FF00) <<  8) |
98           ((p_iVal & 0x00FF0000) >>  8) |
99           ((p_iVal & 0xFF000000) >> 24));
100 }
101 #else
102 #define FromLEWord(X)  (X)
103 #define FromLEDWord(X) (X)
104 #endif
105
106
107 /****************************************************************************
108  *              FromLExxx
109  *
110  * Fix byte order in any structure if necessary
111  */
112 #ifdef WORDS_BIGENDIAN
113 static void FromLEWords(void *p_Val, int p_iSize)
114 {
115   WORD *Val = p_Val;
116
117   p_iSize /= sizeof(WORD);
118
119   while (p_iSize) {
120     *Val = FromLEWord(*Val);
121     Val++;
122     p_iSize--;
123   }
124 }
125
126
127 static void FromLEDWords(void *p_Val, int p_iSize)
128 {
129   DWORD *Val = p_Val;
130
131   p_iSize /= sizeof(DWORD);
132
133   while (p_iSize) {
134     *Val = FromLEDWord(*Val);
135     Val++;
136     p_iSize--;
137   }
138 }
139 #else
140 #define FromLEWords(X,Y) /*nothing*/
141 #define FromLEDWords(X,Y) /*nothing*/
142 #endif
143
144 /*
145  * Find a typelib key which matches a requested maj.min version.
146  */
147 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
148 {
149     static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
150     WCHAR buffer[60];
151     char key_name[16];
152     DWORD len, i;
153     INT best_min = -1;
154     HKEY hkey;
155
156     memcpy( buffer, typelibW, sizeof(typelibW) );
157     StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
158
159     if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
160         return FALSE;
161
162     len = sizeof(key_name);
163     i = 0;
164     while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
165     {
166         INT v_maj, v_min;
167
168         if (sscanf(key_name, "%u.%u", &v_maj, &v_min) == 2)
169         {
170             TRACE("found %s: %u.%u\n", debugstr_w(buffer), v_maj, v_min);
171
172             if (*wMaj == v_maj)
173             {
174                 if (*wMin == v_min)
175                 {
176                     best_min = v_min;
177                     break; /* exact match */
178                 }
179                 if (v_min > best_min) best_min = v_min;
180             }
181         }
182         len = sizeof(key_name);
183     }
184     RegCloseKey( hkey );
185     if (best_min >= 0)
186     {
187         *wMin = best_min;
188         return TRUE;
189     }
190     return FALSE;
191 }
192
193 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
194 /* buffer must be at least 60 characters long */
195 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
196 {
197     static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
198     static const WCHAR VersionFormatW[] = {'\\','%','u','.','%','u',0};
199
200     memcpy( buffer, TypelibW, sizeof(TypelibW) );
201     StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
202     sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
203     return buffer;
204 }
205
206 /* get the path of an interface key, in the form "Interface\\<guid>" */
207 /* buffer must be at least 50 characters long */
208 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
209 {
210     static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
211
212     memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
213     StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
214     return buffer;
215 }
216
217 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
218 /* buffer must be at least 16 characters long */
219 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
220 {
221     static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
222     static const WCHAR win16W[] = {'w','i','n','1','6',0};
223     static const WCHAR win32W[] = {'w','i','n','3','2',0};
224
225     sprintfW( buffer, LcidFormatW, lcid );
226     switch(syskind)
227     {
228     case SYS_WIN16: strcatW( buffer, win16W ); break;
229     case SYS_WIN32: strcatW( buffer, win32W ); break;
230     default:
231         TRACE("Typelib is for unsupported syskind %i\n", syskind);
232         return NULL;
233     }
234     return buffer;
235 }
236
237 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
238
239
240 /****************************************************************************
241  *              QueryPathOfRegTypeLib   [OLEAUT32.164]
242  *
243  * Gets the path to a registered type library.
244  *
245  * PARAMS
246  *  guid [I] referenced guid
247  *  wMaj [I] major version
248  *  wMin [I] minor version
249  *  lcid [I] locale id
250  *  path [O] path of typelib
251  *
252  * RETURNS
253  *  Success: S_OK.
254  *  Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
255  *  or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
256  *  opened.
257  */
258 HRESULT WINAPI QueryPathOfRegTypeLib(
259         REFGUID guid,
260         WORD wMaj,
261         WORD wMin,
262         LCID lcid,
263         LPBSTR path )
264 {
265     HRESULT hr = TYPE_E_LIBNOTREGISTERED;
266     LCID myLCID = lcid;
267     HKEY hkey;
268     WCHAR buffer[60];
269     WCHAR Path[MAX_PATH];
270     LONG res;
271
272     TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
273
274     if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
275     get_typelib_key( guid, wMaj, wMin, buffer );
276
277     res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
278     if (res == ERROR_FILE_NOT_FOUND)
279     {
280         TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
281         return TYPE_E_LIBNOTREGISTERED;
282     }
283     else if (res != ERROR_SUCCESS)
284     {
285         TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
286         return TYPE_E_REGISTRYACCESS;
287     }
288
289     while (hr != S_OK)
290     {
291         LONG dwPathLen = sizeof(Path);
292
293         get_lcid_subkey( myLCID, SYS_WIN32, buffer );
294
295         if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
296         {
297             if (!lcid)
298                 break;
299             else if (myLCID == lcid)
300             {
301                 /* try with sub-langid */
302                 myLCID = SUBLANGID(lcid);
303             }
304             else if ((myLCID == SUBLANGID(lcid)) && myLCID)
305             {
306                 /* try with system langid */
307                 myLCID = 0;
308             }
309             else
310             {
311                 break;
312             }
313         }
314         else
315         {
316             *path = SysAllocString( Path );
317             hr = S_OK;
318         }
319     }
320     RegCloseKey( hkey );
321     TRACE_(typelib)("-- 0x%08x\n", hr);
322     return hr;
323 }
324
325 /******************************************************************************
326  * CreateTypeLib [OLEAUT32.160]  creates a typelib
327  *
328  * RETURNS
329  *    Success: S_OK
330  *    Failure: Status
331  */
332 HRESULT WINAPI CreateTypeLib(
333         SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
334 ) {
335     FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
336     return E_FAIL;
337 }
338
339 /******************************************************************************
340  *              LoadTypeLib     [OLEAUT32.161]
341  *
342  * Loads a type library
343  *
344  * PARAMS
345  *  szFile [I] Name of file to load from.
346  *  pptLib [O] Pointer that receives ITypeLib object on success.
347  *
348  * RETURNS
349  *    Success: S_OK
350  *    Failure: Status
351  *
352  * SEE
353  *  LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
354  */
355 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
356 {
357     TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
358     return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
359 }
360
361 /******************************************************************************
362  *              LoadTypeLibEx   [OLEAUT32.183]
363  *
364  * Loads and optionally registers a type library
365  *
366  * RETURNS
367  *    Success: S_OK
368  *    Failure: Status
369  */
370 HRESULT WINAPI LoadTypeLibEx(
371     LPCOLESTR szFile,  /* [in] Name of file to load from */
372     REGKIND  regkind,  /* [in] Specify kind of registration */
373     ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
374 {
375     WCHAR szPath[MAX_PATH+1];
376     HRESULT res;
377
378     TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
379
380     *pptLib = NULL;
381
382     res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
383
384     if (SUCCEEDED(res))
385         switch(regkind)
386         {
387             case REGKIND_DEFAULT:
388                 /* don't register typelibs supplied with full path. Experimentation confirms the following */
389                 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
390                     (szFile[0] && (szFile[1] == ':'))) break;
391                 /* else fall-through */
392
393             case REGKIND_REGISTER:
394                 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
395                 {
396                     IUnknown_Release(*pptLib);
397                     *pptLib = 0;
398                 }
399                 break;
400             case REGKIND_NONE:
401                 break;
402         }
403
404     TRACE(" returns %08x\n",res);
405     return res;
406 }
407
408 /******************************************************************************
409  *              LoadRegTypeLib  [OLEAUT32.162]
410  *
411  * Loads a registered type library.
412  *
413  * PARAMS
414  *  rguid     [I] GUID of the registered type library.
415  *  wVerMajor [I] major version.
416  *  wVerMinor [I] minor version.
417  *  lcid      [I] locale ID.
418  *  ppTLib    [O] pointer that receives an ITypeLib object on success.
419  *
420  * RETURNS
421  *  Success: S_OK.
422  *  Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
423  *  LoadTypeLib.
424  */
425 HRESULT WINAPI LoadRegTypeLib(
426         REFGUID rguid,
427         WORD wVerMajor,
428         WORD wVerMinor,
429         LCID lcid,
430         ITypeLib **ppTLib)
431 {
432     BSTR bstr=NULL;
433     HRESULT res;
434
435     *ppTLib = NULL;
436
437     res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
438
439     if(SUCCEEDED(res))
440     {
441         res= LoadTypeLib(bstr, ppTLib);
442         SysFreeString(bstr);
443     }
444
445     TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
446
447     return res;
448 }
449
450
451 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
452 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
453 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
454 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
455 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
456 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
457
458 /******************************************************************************
459  *              RegisterTypeLib [OLEAUT32.163]
460  * Adds information about a type library to the System Registry
461  * NOTES
462  *    Docs: ITypeLib FAR * ptlib
463  *    Docs: OLECHAR FAR* szFullPath
464  *    Docs: OLECHAR FAR* szHelpDir
465  *
466  * RETURNS
467  *    Success: S_OK
468  *    Failure: Status
469  */
470 HRESULT WINAPI RegisterTypeLib(
471      ITypeLib * ptlib,     /* [in] Pointer to the library*/
472      OLECHAR * szFullPath, /* [in] full Path of the library*/
473      OLECHAR * szHelpDir)  /* [in] dir to the helpfile for the library,
474                                                          may be NULL*/
475 {
476     static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
477                                  '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
478                                  '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
479     HRESULT res;
480     TLIBATTR *attr;
481     WCHAR keyName[60];
482     WCHAR tmp[16];
483     HKEY key, subKey;
484     UINT types, tidx;
485     TYPEKIND kind;
486     DWORD disposition;
487
488     if (ptlib == NULL || szFullPath == NULL)
489         return E_INVALIDARG;
490
491     if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
492         return E_FAIL;
493
494     get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
495
496     res = S_OK;
497     if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
498         KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
499     {
500         LPOLESTR doc;
501
502         /* Set the human-readable name of the typelib */
503         if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
504         {
505             if (RegSetValueExW(key, NULL, 0, REG_SZ,
506                 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
507                 res = E_FAIL;
508
509             SysFreeString(doc);
510         }
511         else
512             res = E_FAIL;
513
514         /* Make up the name of the typelib path subkey */
515         if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
516
517         /* Create the typelib path subkey */
518         if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
519             KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
520         {
521             if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
522                 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
523                 res = E_FAIL;
524
525             RegCloseKey(subKey);
526         }
527         else
528             res = E_FAIL;
529
530         /* Create the flags subkey */
531         if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
532             KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
533         {
534             /* FIXME: is %u correct? */
535             static const WCHAR formatW[] = {'%','u',0};
536             WCHAR buf[20];
537             sprintfW(buf, formatW, attr->wLibFlags);
538             if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
539                                (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
540                 res = E_FAIL;
541
542             RegCloseKey(subKey);
543         }
544         else
545             res = E_FAIL;
546
547         /* create the helpdir subkey */
548         if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
549             KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
550         {
551             BOOL freeHelpDir = FALSE;
552             OLECHAR* pIndexStr;
553
554             /* if we created a new key, and helpDir was null, set the helpdir
555                to the directory which contains the typelib. However,
556                if we just opened an existing key, we leave the helpdir alone */
557             if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
558                 szHelpDir = SysAllocString(szFullPath);
559                 pIndexStr = strrchrW(szHelpDir, '\\');
560                 if (pIndexStr) {
561                     *pIndexStr = 0;
562                 }
563                 freeHelpDir = TRUE;
564             }
565
566             /* if we have an szHelpDir, set it! */
567             if (szHelpDir != NULL) {
568                 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
569                     (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
570                     res = E_FAIL;
571                 }
572             }
573
574             /* tidy up */
575             if (freeHelpDir) SysFreeString(szHelpDir);
576             RegCloseKey(subKey);
577
578         } else {
579             res = E_FAIL;
580         }
581
582         RegCloseKey(key);
583     }
584     else
585         res = E_FAIL;
586
587     /* register OLE Automation-compatible interfaces for this typelib */
588     types = ITypeLib_GetTypeInfoCount(ptlib);
589     for (tidx=0; tidx<types; tidx++) {
590         if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
591             LPOLESTR name = NULL;
592             ITypeInfo *tinfo = NULL;
593
594             ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
595
596             switch (kind) {
597             case TKIND_INTERFACE:
598                 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
599                 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
600                 break;
601
602             case TKIND_DISPATCH:
603                 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
604                 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
605                 break;
606
607             default:
608                 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
609                 break;
610             }
611
612             if (tinfo) {
613                 TYPEATTR *tattr = NULL;
614                 ITypeInfo_GetTypeAttr(tinfo, &tattr);
615
616                 if (tattr) {
617                     TRACE_(typelib)("guid=%s, flags=%04x (",
618                                     debugstr_guid(&tattr->guid),
619                                     tattr->wTypeFlags);
620
621                     if (TRACE_ON(typelib)) {
622 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
623                         XX(FAPPOBJECT);
624                         XX(FCANCREATE);
625                         XX(FLICENSED);
626                         XX(FPREDECLID);
627                         XX(FHIDDEN);
628                         XX(FCONTROL);
629                         XX(FDUAL);
630                         XX(FNONEXTENSIBLE);
631                         XX(FOLEAUTOMATION);
632                         XX(FRESTRICTED);
633                         XX(FAGGREGATABLE);
634                         XX(FREPLACEABLE);
635                         XX(FDISPATCHABLE);
636                         XX(FREVERSEBIND);
637                         XX(FPROXY);
638 #undef XX
639                         MESSAGE("\n");
640                     }
641
642                     if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
643                     {
644                         /* register interface<->typelib coupling */
645                         get_interface_key( &tattr->guid, keyName );
646                         if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
647                                             KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
648                         {
649                             if (name)
650                                 RegSetValueExW(key, NULL, 0, REG_SZ,
651                                                (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
652
653                             if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
654                                 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
655                                 RegSetValueExW(subKey, NULL, 0, REG_SZ,
656                                                (const BYTE *)PSOA, sizeof PSOA);
657                                 RegCloseKey(subKey);
658                             }
659
660                             if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
661                                 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
662                                 RegSetValueExW(subKey, NULL, 0, REG_SZ,
663                                                (const BYTE *)PSOA, sizeof PSOA);
664                                 RegCloseKey(subKey);
665                             }
666
667                             if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
668                                 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
669                             {
670                                 WCHAR buffer[40];
671                                 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
672                                 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
673
674                                 StringFromGUID2(&attr->guid, buffer, 40);
675                                 RegSetValueExW(subKey, NULL, 0, REG_SZ,
676                                                (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
677                                 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
678                                 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
679                                                (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
680                                 RegCloseKey(subKey);
681                             }
682
683                             RegCloseKey(key);
684                         }
685                     }
686
687                     ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
688                 }
689
690                 ITypeInfo_Release(tinfo);
691             }
692
693             SysFreeString(name);
694         }
695     }
696
697     ITypeLib_ReleaseTLibAttr(ptlib, attr);
698
699     return res;
700 }
701
702
703 /******************************************************************************
704  *      UnRegisterTypeLib       [OLEAUT32.186]
705  * Removes information about a type library from the System Registry
706  * NOTES
707  *
708  * RETURNS
709  *    Success: S_OK
710  *    Failure: Status
711  */
712 HRESULT WINAPI UnRegisterTypeLib(
713     REFGUID libid,      /* [in] Guid of the library */
714         WORD wVerMajor, /* [in] major version */
715         WORD wVerMinor, /* [in] minor version */
716         LCID lcid,      /* [in] locale id */
717         SYSKIND syskind)
718 {
719     BSTR tlibPath = NULL;
720     DWORD tmpLength;
721     WCHAR keyName[60];
722     WCHAR subKeyName[50];
723     int result = S_OK;
724     DWORD i = 0;
725     BOOL deleteOtherStuff;
726     HKEY key = NULL;
727     HKEY subKey = NULL;
728     TYPEATTR* typeAttr = NULL;
729     TYPEKIND kind;
730     ITypeInfo* typeInfo = NULL;
731     ITypeLib* typeLib = NULL;
732     int numTypes;
733
734     TRACE("(IID: %s)\n",debugstr_guid(libid));
735
736     /* Create the path to the key */
737     get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
738
739     if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
740     {
741         TRACE("Unsupported syskind %i\n", syskind);
742         result = E_INVALIDARG;
743         goto end;
744     }
745
746     /* get the path to the typelib on disk */
747     if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
748         result = E_INVALIDARG;
749         goto end;
750     }
751
752     /* Try and open the key to the type library. */
753     if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
754         result = E_INVALIDARG;
755         goto end;
756     }
757
758     /* Try and load the type library */
759     if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
760         result = TYPE_E_INVALIDSTATE;
761         goto end;
762     }
763
764     /* remove any types registered with this typelib */
765     numTypes = ITypeLib_GetTypeInfoCount(typeLib);
766     for (i=0; i<numTypes; i++) {
767         /* get the kind of type */
768         if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
769             goto enddeleteloop;
770         }
771
772         /* skip non-interfaces, and get type info for the type */
773         if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
774             goto enddeleteloop;
775         }
776         if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
777             goto enddeleteloop;
778         }
779         if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
780             goto enddeleteloop;
781         }
782
783         /* the path to the type */
784         get_interface_key( &typeAttr->guid, subKeyName );
785
786         /* Delete its bits */
787         if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
788             goto enddeleteloop;
789         }
790         RegDeleteKeyW(subKey, ProxyStubClsidW);
791         RegDeleteKeyW(subKey, ProxyStubClsid32W);
792         RegDeleteKeyW(subKey, TypeLibW);
793         RegCloseKey(subKey);
794         subKey = NULL;
795         RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
796
797 enddeleteloop:
798         if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
799         typeAttr = NULL;
800         if (typeInfo) ITypeInfo_Release(typeInfo);
801         typeInfo = NULL;
802     }
803
804     /* Now, delete the type library path subkey */
805     get_lcid_subkey( lcid, syskind, subKeyName );
806     RegDeleteKeyW(key, subKeyName);
807     *strrchrW( subKeyName, '\\' ) = 0;  /* remove last path component */
808     RegDeleteKeyW(key, subKeyName);
809
810     /* check if there is anything besides the FLAGS/HELPDIR keys.
811        If there is, we don't delete them */
812     tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
813     deleteOtherStuff = TRUE;
814     i = 0;
815     while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
816         tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
817
818         /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
819         if (!strcmpW(subKeyName, FLAGSW)) continue;
820         if (!strcmpW(subKeyName, HELPDIRW)) continue;
821         deleteOtherStuff = FALSE;
822         break;
823     }
824
825     /* only delete the other parts of the key if we're absolutely sure */
826     if (deleteOtherStuff) {
827         RegDeleteKeyW(key, FLAGSW);
828         RegDeleteKeyW(key, HELPDIRW);
829         RegCloseKey(key);
830         key = NULL;
831
832         RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
833         *strrchrW( keyName, '\\' ) = 0;  /* remove last path component */
834         RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
835     }
836
837 end:
838     if (tlibPath) SysFreeString(tlibPath);
839     if (typeLib) ITypeLib_Release(typeLib);
840     if (subKey) RegCloseKey(subKey);
841     if (key) RegCloseKey(key);
842     return result;
843 }
844
845 /*======================= ITypeLib implementation =======================*/
846
847 typedef struct tagTLBCustData
848 {
849     GUID guid;
850     VARIANT data;
851     struct tagTLBCustData* next;
852 } TLBCustData;
853
854 /* data structure for import typelibs */
855 typedef struct tagTLBImpLib
856 {
857     int offset;                 /* offset in the file (MSFT)
858                                    offset in nametable (SLTG)
859                                    just used to identify library while reading
860                                    data from file */
861     GUID guid;                  /* libid */
862     BSTR name;                  /* name */
863
864     LCID lcid;                  /* lcid of imported typelib */
865
866     WORD wVersionMajor;         /* major version number */
867     WORD wVersionMinor;         /* minor version number */
868
869     struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
870                                             NULL if not yet loaded */
871     struct tagTLBImpLib * next;
872 } TLBImpLib;
873
874 /* internal ITypeLib data */
875 typedef struct tagITypeLibImpl
876 {
877     const ITypeLib2Vtbl *lpVtbl;
878     const ITypeCompVtbl *lpVtblTypeComp;
879     LONG ref;
880     TLIBATTR LibAttr;            /* guid,lcid,syskind,version,flags */
881
882     /* strings can be stored in tlb as multibyte strings BUT they are *always*
883      * exported to the application as a UNICODE string.
884      */
885     BSTR Name;
886     BSTR DocString;
887     BSTR HelpFile;
888     BSTR HelpStringDll;
889     unsigned long  dwHelpContext;
890     int TypeInfoCount;          /* nr of typeinfo's in librarry */
891     struct tagITypeInfoImpl *pTypeInfo;   /* linked list of type info data */
892     int ctCustData;             /* number of items in cust data list */
893     TLBCustData * pCustData;    /* linked list to cust data */
894     TLBImpLib   * pImpLibs;     /* linked list to all imported typelibs */
895     int ctTypeDesc;             /* number of items in type desc array */
896     TYPEDESC * pTypeDesc;       /* array of TypeDescriptions found in the
897                                    library. Only used while read MSFT
898                                    typelibs */
899
900     /* typelibs are cached, keyed by path and index, so store the linked list info within them */
901     struct tagITypeLibImpl *next, *prev;
902     WCHAR *path;
903     INT index;
904 } ITypeLibImpl;
905
906 static const ITypeLib2Vtbl tlbvt;
907 static const ITypeCompVtbl tlbtcvt;
908
909 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
910 {
911     return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
912 }
913
914 /* ITypeLib methods */
915 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
916 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
917
918 /*======================= ITypeInfo implementation =======================*/
919
920 /* data for referenced types */
921 typedef struct tagTLBRefType
922 {
923     INT index;              /* Type index for internal ref or for external ref
924                                it the format is SLTG.  -2 indicates to
925                                use guid */
926
927     GUID guid;              /* guid of the referenced type */
928                             /* if index == TLB_REF_USE_GUID */
929
930     HREFTYPE reference;     /* The href of this ref */
931     TLBImpLib *pImpTLInfo;  /* If ref is external ptr to library data
932                                TLB_REF_INTERNAL for internal refs
933                                TLB_REF_NOT_FOUND for broken refs */
934
935     struct tagTLBRefType * next;
936 } TLBRefType;
937
938 #define TLB_REF_USE_GUID -2
939
940 #define TLB_REF_INTERNAL (void*)-2
941 #define TLB_REF_NOT_FOUND (void*)-1
942
943 /* internal Parameter data */
944 typedef struct tagTLBParDesc
945 {
946     BSTR Name;
947     int ctCustData;
948     TLBCustData * pCustData;        /* linked list to cust data */
949 } TLBParDesc;
950
951 /* internal Function data */
952 typedef struct tagTLBFuncDesc
953 {
954     FUNCDESC funcdesc;      /* lots of info on the function and its attributes. */
955     BSTR Name;             /* the name of this function */
956     TLBParDesc *pParamDesc; /* array with param names and custom data */
957     int helpcontext;
958     int HelpStringContext;
959     BSTR HelpString;
960     BSTR Entry;            /* if its Hiword==0, it numeric; -1 is not present*/
961     int ctCustData;
962     TLBCustData * pCustData;        /* linked list to cust data; */
963     struct tagTLBFuncDesc * next;
964 } TLBFuncDesc;
965
966 /* internal Variable data */
967 typedef struct tagTLBVarDesc
968 {
969     VARDESC vardesc;        /* lots of info on the variable and its attributes. */
970     BSTR Name;             /* the name of this variable */
971     int HelpContext;
972     int HelpStringContext;  /* FIXME: where? */
973     BSTR HelpString;
974     int ctCustData;
975     TLBCustData * pCustData;/* linked list to cust data; */
976     struct tagTLBVarDesc * next;
977 } TLBVarDesc;
978
979 /* internal implemented interface data */
980 typedef struct tagTLBImplType
981 {
982     HREFTYPE hRef;          /* hRef of interface */
983     int implflags;          /* IMPLFLAG_*s */
984     int ctCustData;
985     TLBCustData * pCustData;/* linked list to custom data; */
986     struct tagTLBImplType *next;
987 } TLBImplType;
988
989 /* internal TypeInfo data */
990 typedef struct tagITypeInfoImpl
991 {
992     const ITypeInfo2Vtbl *lpVtbl;
993     const ITypeCompVtbl  *lpVtblTypeComp;
994     LONG ref;
995     BOOL no_free_data; /* don't free data structurees */
996     TYPEATTR TypeAttr ;         /* _lots_ of type information. */
997     ITypeLibImpl * pTypeLib;        /* back pointer to typelib */
998     int index;                  /* index in this typelib; */
999     HREFTYPE hreftype;          /* hreftype for app object binding */
1000     /* type libs seem to store the doc strings in ascii
1001      * so why should we do it in unicode?
1002      */
1003     BSTR Name;
1004     BSTR DocString;
1005     BSTR DllName;
1006     unsigned long  dwHelpContext;
1007     unsigned long  dwHelpStringContext;
1008
1009     /* functions  */
1010     TLBFuncDesc * funclist;     /* linked list with function descriptions */
1011
1012     /* variables  */
1013     TLBVarDesc * varlist;       /* linked list with variable descriptions */
1014
1015     /* Implemented Interfaces  */
1016     TLBImplType * impltypelist;
1017
1018     TLBRefType * reflist;
1019     int ctCustData;
1020     TLBCustData * pCustData;        /* linked list to cust data; */
1021     struct tagITypeInfoImpl * next;
1022 } ITypeInfoImpl;
1023
1024 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1025 {
1026     return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1027 }
1028
1029 static const ITypeInfo2Vtbl tinfvt;
1030 static const ITypeCompVtbl  tcompvt;
1031
1032 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1033
1034 typedef struct tagTLBContext
1035 {
1036         unsigned int oStart;  /* start of TLB in file */
1037         unsigned int pos;     /* current pos */
1038         unsigned int length;  /* total length */
1039         void *mapping;        /* memory mapping */
1040         MSFT_SegDir * pTblDir;
1041         ITypeLibImpl* pLibInfo;
1042 } TLBContext;
1043
1044
1045 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1046
1047 /*
1048  debug
1049 */
1050 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1051     if (pTD->vt & VT_RESERVED)
1052         szVarType += strlen(strcpy(szVarType, "reserved | "));
1053     if (pTD->vt & VT_BYREF)
1054         szVarType += strlen(strcpy(szVarType, "ref to "));
1055     if (pTD->vt & VT_ARRAY)
1056         szVarType += strlen(strcpy(szVarType, "array of "));
1057     if (pTD->vt & VT_VECTOR)
1058         szVarType += strlen(strcpy(szVarType, "vector of "));
1059     switch(pTD->vt & VT_TYPEMASK) {
1060     case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1061     case VT_I2: sprintf(szVarType, "VT_I2"); break;
1062     case VT_I4: sprintf(szVarType, "VT_I4"); break;
1063     case VT_R4: sprintf(szVarType, "VT_R4"); break;
1064     case VT_R8: sprintf(szVarType, "VT_R8"); break;
1065     case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1066     case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1067     case VT_CY: sprintf(szVarType, "VT_CY"); break;
1068     case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1069     case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1070     case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1071     case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1072     case VT_I1: sprintf(szVarType, "VT_I1"); break;
1073     case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1074     case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1075     case VT_INT: sprintf(szVarType, "VT_INT"); break;
1076     case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1077     case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1078     case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1079     case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1080     case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1081                                  pTD->u.hreftype); break;
1082     case VT_PTR: sprintf(szVarType, "ptr to ");
1083       dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1084       break;
1085     case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1086       dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1087       break;
1088     case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1089                             pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1090       dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1091       break;
1092
1093     default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1094     }
1095 }
1096
1097 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1098   char buf[200];
1099   USHORT flags = edesc->u.paramdesc.wParamFlags;
1100   dump_TypeDesc(&edesc->tdesc,buf);
1101   MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1102   MESSAGE("\t\tu.paramdesc.wParamFlags");
1103   if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1104   if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1105   if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1106   if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1107   if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1108   if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1109   if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1110   if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1111   MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1112 }
1113 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1114   int i;
1115   MESSAGE("memid is %08x\n",funcdesc->memid);
1116   for (i=0;i<funcdesc->cParams;i++) {
1117       MESSAGE("Param %d:\n",i);
1118       dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1119   }
1120   MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1121   switch (funcdesc->funckind) {
1122   case FUNC_VIRTUAL: MESSAGE("virtual");break;
1123   case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1124   case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1125   case FUNC_STATIC: MESSAGE("static");break;
1126   case FUNC_DISPATCH: MESSAGE("dispatch");break;
1127   default: MESSAGE("unknown");break;
1128   }
1129   MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1130   switch (funcdesc->invkind) {
1131   case INVOKE_FUNC: MESSAGE("func");break;
1132   case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1133   case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1134   case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1135   }
1136   MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1137   switch (funcdesc->callconv) {
1138   case CC_CDECL: MESSAGE("cdecl");break;
1139   case CC_PASCAL: MESSAGE("pascal");break;
1140   case CC_STDCALL: MESSAGE("stdcall");break;
1141   case CC_SYSCALL: MESSAGE("syscall");break;
1142   default:break;
1143   }
1144   MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1145   MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1146   MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1147
1148   MESSAGE("\telemdescFunc (return value type):\n");
1149   dump_ELEMDESC(&funcdesc->elemdescFunc);
1150 }
1151
1152 static const char * const typekind_desc[] =
1153 {
1154         "TKIND_ENUM",
1155         "TKIND_RECORD",
1156         "TKIND_MODULE",
1157         "TKIND_INTERFACE",
1158         "TKIND_DISPATCH",
1159         "TKIND_COCLASS",
1160         "TKIND_ALIAS",
1161         "TKIND_UNION",
1162         "TKIND_MAX"
1163 };
1164
1165 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1166 {
1167   int i;
1168   MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1169   for (i=0;i<pfd->funcdesc.cParams;i++)
1170       MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1171
1172
1173   dump_FUNCDESC(&(pfd->funcdesc));
1174
1175   MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1176   MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1177 }
1178 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1179 {
1180         while (pfd)
1181         {
1182           dump_TLBFuncDescOne(pfd);
1183           pfd = pfd->next;
1184         };
1185 }
1186 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1187 {
1188         while (pvd)
1189         {
1190           TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1191           pvd = pvd->next;
1192         };
1193 }
1194
1195 static void dump_TLBImpLib(const TLBImpLib *import)
1196 {
1197     TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1198                     debugstr_w(import->name));
1199     TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1200                     import->wVersionMinor, import->lcid, import->offset);
1201 }
1202
1203 static void dump_TLBRefType(const TLBRefType * prt)
1204 {
1205         while (prt)
1206         {
1207           TRACE_(typelib)("href:0x%08x\n", prt->reference);
1208           if(prt->index == -1)
1209             TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1210           else
1211             TRACE_(typelib)("type no: %d\n", prt->index);
1212
1213           if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1214              prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1215               TRACE_(typelib)("in lib\n");
1216               dump_TLBImpLib(prt->pImpTLInfo);
1217           }
1218           prt = prt->next;
1219         };
1220 }
1221
1222 static void dump_TLBImplType(const TLBImplType * impl)
1223 {
1224     while (impl) {
1225         TRACE_(typelib)(
1226                 "implementing/inheriting interface hRef = %x implflags %x\n",
1227                 impl->hRef, impl->implflags);
1228         impl = impl->next;
1229     }
1230 }
1231
1232 void dump_Variant(const VARIANT * pvar)
1233 {
1234     SYSTEMTIME st;
1235
1236     TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1237
1238     if (pvar)
1239     {
1240       if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1241           V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1242       {
1243         TRACE(",%p", V_BYREF(pvar));
1244       }
1245       else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1246       {
1247         TRACE(",%p", V_ARRAY(pvar));
1248       }
1249       else switch (V_TYPE(pvar))
1250       {
1251       case VT_I1:   TRACE(",%d", V_I1(pvar)); break;
1252       case VT_UI1:  TRACE(",%d", V_UI1(pvar)); break;
1253       case VT_I2:   TRACE(",%d", V_I2(pvar)); break;
1254       case VT_UI2:  TRACE(",%d", V_UI2(pvar)); break;
1255       case VT_INT:
1256       case VT_I4:   TRACE(",%d", V_I4(pvar)); break;
1257       case VT_UINT:
1258       case VT_UI4:  TRACE(",%d", V_UI4(pvar)); break;
1259       case VT_I8:   TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1260                           (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1261       case VT_UI8:  TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1262                           (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1263       case VT_R4:   TRACE(",%3.3e", V_R4(pvar)); break;
1264       case VT_R8:   TRACE(",%3.3e", V_R8(pvar)); break;
1265       case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1266       case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1267       case VT_CY:   TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1268                            V_CY(pvar).s.Lo); break;
1269       case VT_DATE:
1270         if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1271           TRACE(",<invalid>");
1272         else
1273           TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1274                 st.wHour, st.wMinute, st.wSecond);
1275         break;
1276       case VT_ERROR:
1277       case VT_VOID:
1278       case VT_USERDEFINED:
1279       case VT_EMPTY:
1280       case VT_NULL:  break;
1281       default:       TRACE(",?"); break;
1282       }
1283     }
1284     TRACE("}\n");
1285 }
1286
1287 static void dump_DispParms(const DISPPARAMS * pdp)
1288 {
1289     int index;
1290
1291     TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1292
1293     if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1294     {
1295         TRACE("named args:\n");
1296         for (index = 0; index < pdp->cNamedArgs; index++)
1297             TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1298     }
1299
1300     if (pdp->cArgs && pdp->rgvarg)
1301     {
1302         TRACE("args:\n");
1303         for (index = 0; index < pdp->cArgs; index++)
1304             dump_Variant( &pdp->rgvarg[index] );
1305     }
1306 }
1307
1308 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1309 {
1310     TRACE("%p ref=%u\n", pty, pty->ref);
1311     TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1312     TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1313     TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1314     TRACE("fct:%u var:%u impl:%u\n",
1315       pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1316     TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1317     TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1318     if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1319     if (TRACE_ON(ole))
1320         dump_TLBFuncDesc(pty->funclist);
1321     dump_TLBVarDesc(pty->varlist);
1322     dump_TLBImplType(pty->impltypelist);
1323 }
1324
1325 static void dump_VARDESC(const VARDESC *v)
1326 {
1327     MESSAGE("memid %d\n",v->memid);
1328     MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1329     MESSAGE("oInst %d\n",v->u.oInst);
1330     dump_ELEMDESC(&(v->elemdescVar));
1331     MESSAGE("wVarFlags %x\n",v->wVarFlags);
1332     MESSAGE("varkind %d\n",v->varkind);
1333 }
1334
1335 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1336 {
1337     /* VT_LPWSTR is largest type that */
1338     /* may appear in type description*/
1339     {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1340     {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1341     {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1342     {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1343     {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1344     {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1345     {{0},30},{{0},31}
1346 };
1347
1348 static void TLB_abort(void)
1349 {
1350     DebugBreak();
1351 }
1352 static void * TLB_Alloc(unsigned size)
1353 {
1354     void * ret;
1355     if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1356         /* FIXME */
1357         ERR("cannot allocate memory\n");
1358     }
1359     return ret;
1360 }
1361
1362 static void TLB_Free(void * ptr)
1363 {
1364     HeapFree(GetProcessHeap(), 0, ptr);
1365 }
1366
1367 /* returns the size required for a deep copy of a typedesc into a
1368  * flat buffer */
1369 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1370 {
1371     SIZE_T size = 0;
1372
1373     if (alloc_initial_space)
1374         size += sizeof(TYPEDESC);
1375
1376     switch (tdesc->vt)
1377     {
1378     case VT_PTR:
1379     case VT_SAFEARRAY:
1380         size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1381         break;
1382     case VT_CARRAY:
1383         size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1384         size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1385         break;
1386     }
1387     return size;
1388 }
1389
1390 /* deep copy a typedesc into a flat buffer */
1391 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1392 {
1393     if (!dest)
1394     {
1395         dest = buffer;
1396         buffer = (char *)buffer + sizeof(TYPEDESC);
1397     }
1398
1399     *dest = *src;
1400
1401     switch (src->vt)
1402     {
1403     case VT_PTR:
1404     case VT_SAFEARRAY:
1405         dest->u.lptdesc = buffer;
1406         buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1407         break;
1408     case VT_CARRAY:
1409         dest->u.lpadesc = buffer;
1410         memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1411         buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1412         buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1413         break;
1414     }
1415     return buffer;
1416 }
1417
1418 /**********************************************************************
1419  *
1420  *  Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1421  */
1422 static inline unsigned int MSFT_Tell(TLBContext *pcx)
1423 {
1424     return pcx->pos;
1425 }
1426
1427 static inline void MSFT_Seek(TLBContext *pcx, long where)
1428 {
1429     if (where != DO_NOT_SEEK)
1430     {
1431         where += pcx->oStart;
1432         if (where > pcx->length)
1433         {
1434             /* FIXME */
1435             ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1436             TLB_abort();
1437         }
1438         pcx->pos = where;
1439     }
1440 }
1441
1442 /* read function */
1443 static DWORD MSFT_Read(void *buffer,  DWORD count, TLBContext *pcx, long where )
1444 {
1445     TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1446        pcx->pos, count, pcx->oStart, pcx->length, where);
1447
1448     MSFT_Seek(pcx, where);
1449     if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1450     memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1451     pcx->pos += count;
1452     return count;
1453 }
1454
1455 static DWORD MSFT_ReadLEDWords(void *buffer,  DWORD count, TLBContext *pcx,
1456                                long where )
1457 {
1458   DWORD ret;
1459
1460   ret = MSFT_Read(buffer, count, pcx, where);
1461   FromLEDWords(buffer, ret);
1462
1463   return ret;
1464 }
1465
1466 static DWORD MSFT_ReadLEWords(void *buffer,  DWORD count, TLBContext *pcx,
1467                               long where )
1468 {
1469   DWORD ret;
1470
1471   ret = MSFT_Read(buffer, count, pcx, where);
1472   FromLEWords(buffer, ret);
1473
1474   return ret;
1475 }
1476
1477 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1478 {
1479     if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1480         memset(pGuid,0, sizeof(GUID));
1481         return;
1482     }
1483     MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1484     pGuid->Data1 = FromLEDWord(pGuid->Data1);
1485     pGuid->Data2 = FromLEWord(pGuid->Data2);
1486     pGuid->Data3 = FromLEWord(pGuid->Data3);
1487     TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1488 }
1489
1490 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1491 {
1492     MSFT_NameIntro niName;
1493
1494     if (offset < 0)
1495     {
1496         ERR_(typelib)("bad offset %d\n", offset);
1497         return -1;
1498     }
1499
1500     MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1501                       pcx->pTblDir->pNametab.offset+offset);
1502
1503     return niName.hreftype;
1504 }
1505
1506 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1507 {
1508     char * name;
1509     MSFT_NameIntro niName;
1510     int lengthInChars;
1511     BSTR bstrName = NULL;
1512
1513     if (offset < 0)
1514     {
1515         ERR_(typelib)("bad offset %d\n", offset);
1516         return NULL;
1517     }
1518     MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1519                       pcx->pTblDir->pNametab.offset+offset);
1520     niName.namelen &= 0xFF; /* FIXME: correct ? */
1521     name=TLB_Alloc((niName.namelen & 0xff) +1);
1522     MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1523     name[niName.namelen & 0xff]='\0';
1524
1525     lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1526                                         name, -1, NULL, 0);
1527
1528     /* no invalid characters in string */
1529     if (lengthInChars)
1530     {
1531         bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1532
1533         /* don't check for invalid character since this has been done previously */
1534         MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1535     }
1536     TLB_Free(name);
1537
1538     TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1539     return bstrName;
1540 }
1541
1542 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1543 {
1544     char * string;
1545     INT16 length;
1546     int lengthInChars;
1547     BSTR bstr = NULL;
1548
1549     if(offset<0) return NULL;
1550     MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1551     if(length <= 0) return 0;
1552     string=TLB_Alloc(length +1);
1553     MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1554     string[length]='\0';
1555
1556     lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1557                                         string, -1, NULL, 0);
1558
1559     /* no invalid characters in string */
1560     if (lengthInChars)
1561     {
1562         bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1563
1564         /* don't check for invalid character since this has been done previously */
1565         MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1566     }
1567     TLB_Free(string);
1568
1569     TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1570     return bstr;
1571 }
1572 /*
1573  * read a value and fill a VARIANT structure
1574  */
1575 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1576 {
1577     int size;
1578
1579     TRACE_(typelib)("\n");
1580
1581     if(offset <0) { /* data are packed in here */
1582         V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1583         V_I4(pVar) = offset & 0x3ffffff;
1584         return;
1585     }
1586     MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1587                      pcx->pTblDir->pCustData.offset + offset );
1588     TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1589     switch (V_VT(pVar)){
1590         case VT_EMPTY:  /* FIXME: is this right? */
1591         case VT_NULL:   /* FIXME: is this right? */
1592         case VT_I2  :   /* this should not happen */
1593         case VT_I4  :
1594         case VT_R4  :
1595         case VT_ERROR   :
1596         case VT_BOOL    :
1597         case VT_I1  :
1598         case VT_UI1 :
1599         case VT_UI2 :
1600         case VT_UI4 :
1601         case VT_INT :
1602         case VT_UINT    :
1603         case VT_VOID    : /* FIXME: is this right? */
1604         case VT_HRESULT :
1605             size=4; break;
1606         case VT_R8  :
1607         case VT_CY  :
1608         case VT_DATE    :
1609         case VT_I8  :
1610         case VT_UI8 :
1611         case VT_DECIMAL :  /* FIXME: is this right? */
1612         case VT_FILETIME :
1613             size=8;break;
1614             /* pointer types with known behaviour */
1615         case VT_BSTR    :{
1616             char * ptr;
1617             MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1618             if(size < 0) {
1619                 char next;
1620                 DWORD origPos = MSFT_Tell(pcx), nullPos;
1621
1622                 do {
1623                     MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1624                 } while (next);
1625                 nullPos = MSFT_Tell(pcx);
1626                 size = nullPos - origPos;
1627                 MSFT_Seek(pcx, origPos);
1628             }
1629             ptr=TLB_Alloc(size);/* allocate temp buffer */
1630             MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1631             V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1632             /* FIXME: do we need a AtoW conversion here? */
1633             V_UNION(pVar, bstrVal[size])=L'\0';
1634             while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1635             TLB_Free(ptr);
1636         }
1637         size=-4; break;
1638     /* FIXME: this will not work AT ALL when the variant contains a pointer */
1639         case VT_DISPATCH :
1640         case VT_VARIANT :
1641         case VT_UNKNOWN :
1642         case VT_PTR :
1643         case VT_SAFEARRAY :
1644         case VT_CARRAY  :
1645         case VT_USERDEFINED :
1646         case VT_LPSTR   :
1647         case VT_LPWSTR  :
1648         case VT_BLOB    :
1649         case VT_STREAM  :
1650         case VT_STORAGE :
1651         case VT_STREAMED_OBJECT :
1652         case VT_STORED_OBJECT   :
1653         case VT_BLOB_OBJECT :
1654         case VT_CF  :
1655         case VT_CLSID   :
1656         default:
1657             size=0;
1658             FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1659                 V_VT(pVar));
1660     }
1661
1662     if(size>0) /* (big|small) endian correct? */
1663         MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1664     return;
1665 }
1666 /*
1667  * create a linked list with custom data
1668  */
1669 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1670 {
1671     MSFT_CDGuid entry;
1672     TLBCustData* pNew;
1673     int count=0;
1674
1675     TRACE_(typelib)("\n");
1676
1677     while(offset >=0){
1678         count++;
1679         pNew=TLB_Alloc(sizeof(TLBCustData));
1680         MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1681         MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1682         MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1683         /* add new custom data at head of the list */
1684         pNew->next=*ppCustData;
1685         *ppCustData=pNew;
1686         offset = entry.next;
1687     }
1688     return count;
1689 }
1690
1691 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1692                           ITypeInfoImpl *pTI)
1693 {
1694     if(type <0)
1695         pTd->vt=type & VT_TYPEMASK;
1696     else
1697         *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1698
1699     if(pTd->vt == VT_USERDEFINED)
1700       MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1701
1702     TRACE_(typelib)("vt type = %X\n", pTd->vt);
1703 }
1704
1705 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1706 {
1707     /* resolve referenced type if any */
1708     while (lpTypeDesc)
1709     {
1710         switch (lpTypeDesc->vt)
1711         {
1712         case VT_PTR:
1713             lpTypeDesc = lpTypeDesc->u.lptdesc;
1714             break;
1715
1716         case VT_CARRAY:
1717             lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1718             break;
1719
1720         case VT_USERDEFINED:
1721             MSFT_DoRefType(pcx, pTI,
1722                            lpTypeDesc->u.hreftype);
1723
1724             lpTypeDesc = NULL;
1725             break;
1726
1727         default:
1728             lpTypeDesc = NULL;
1729         }
1730     }
1731 }
1732
1733 static void
1734 MSFT_DoFuncs(TLBContext*     pcx,
1735             ITypeInfoImpl*  pTI,
1736             int             cFuncs,
1737             int             cVars,
1738             int             offset,
1739             TLBFuncDesc**   pptfd)
1740 {
1741     /*
1742      * member information is stored in a data structure at offset
1743      * indicated by the memoffset field of the typeinfo structure
1744      * There are several distinctive parts.
1745      * The first part starts with a field that holds the total length
1746      * of this (first) part excluding this field. Then follow the records,
1747      * for each member there is one record.
1748      *
1749      * The first entry is always the length of the record (including this
1750      * length word).
1751      * The rest of the record depends on the type of the member. If there is
1752      * a field indicating the member type (function, variable, interface, etc)
1753      * I have not found it yet. At this time we depend on the information
1754      * in the type info and the usual order how things are stored.
1755      *
1756      * Second follows an array sized nrMEM*sizeof(INT) with a member id
1757      * for each member;
1758      *
1759      * Third is an equal sized array with file offsets to the name entry
1760      * of each member.
1761      *
1762      * The fourth and last (?) part is an array with offsets to the records
1763      * in the first part of this file segment.
1764      */
1765
1766     int infolen, nameoffset, reclength, nrattributes, i;
1767     int recoffset = offset + sizeof(INT);
1768
1769     char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1770     MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1771     TLBFuncDesc *ptfd_prev = NULL;
1772
1773     TRACE_(typelib)("\n");
1774
1775     MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1776
1777     for ( i = 0; i < cFuncs ; i++ )
1778     {
1779         *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1780
1781         /* name, eventually add to a hash table */
1782         MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1783                           offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1784
1785         /* nameoffset is sometimes -1 on the second half of a propget/propput
1786          * pair of functions */
1787         if ((nameoffset == -1) && (i > 0))
1788             (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1789         else
1790             (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1791
1792         /* read the function information record */
1793         MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1794
1795         reclength &= 0xffff;
1796
1797         MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1798
1799         /* do the attributes */
1800         nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1801                        / sizeof(int);
1802
1803         if ( nrattributes > 0 )
1804         {
1805             (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1806
1807             if ( nrattributes > 1 )
1808             {
1809                 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1810                                                       pFuncRec->OptAttr[1]) ;
1811
1812                 if ( nrattributes > 2 )
1813                 {
1814                     if ( pFuncRec->FKCCIC & 0x2000 )
1815                     {
1816                        if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1817                            ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1818                        (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1819                     }
1820                     else
1821                     {
1822                         (*pptfd)->Entry = MSFT_ReadString(pcx,
1823                                                          pFuncRec->OptAttr[2]);
1824                     }
1825                     if( nrattributes > 5 )
1826                     {
1827                         (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1828
1829                         if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1830                         {
1831                             MSFT_CustData(pcx,
1832                                           pFuncRec->OptAttr[6],
1833                                           &(*pptfd)->pCustData);
1834                         }
1835                     }
1836                 }
1837                 else
1838                 {
1839                     (*pptfd)->Entry = (BSTR)-1;
1840                 }
1841             }
1842         }
1843
1844         /* fill the FuncDesc Structure */
1845         MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1846                            offset + infolen + ( i + 1) * sizeof(INT));
1847
1848         (*pptfd)->funcdesc.funckind   =  (pFuncRec->FKCCIC)      & 0x7;
1849         (*pptfd)->funcdesc.invkind    =  (pFuncRec->FKCCIC) >> 3 & 0xF;
1850         (*pptfd)->funcdesc.callconv   =  (pFuncRec->FKCCIC) >> 8 & 0xF;
1851         (*pptfd)->funcdesc.cParams    =   pFuncRec->nrargs  ;
1852         (*pptfd)->funcdesc.cParamsOpt =   pFuncRec->nroargs ;
1853         (*pptfd)->funcdesc.oVft       =   pFuncRec->VtableOffset ;
1854         (*pptfd)->funcdesc.wFuncFlags =   LOWORD(pFuncRec->Flags) ;
1855
1856         MSFT_GetTdesc(pcx,
1857                       pFuncRec->DataType,
1858                       &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1859                       pTI);
1860         MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1861
1862         /* do the parameters/arguments */
1863         if(pFuncRec->nrargs)
1864         {
1865             int j = 0;
1866             MSFT_ParameterInfo paraminfo;
1867
1868             (*pptfd)->funcdesc.lprgelemdescParam =
1869                 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1870
1871             (*pptfd)->pParamDesc =
1872                 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1873
1874             MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1875                               recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1876
1877             for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1878             {
1879                 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1880
1881                 MSFT_GetTdesc(pcx,
1882                               paraminfo.DataType,
1883                               &elemdesc->tdesc,
1884                               pTI);
1885
1886                 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1887
1888                 /* name */
1889                 if (paraminfo.oName == -1)
1890                     /* this occurs for [propput] or [propget] methods, so
1891                      * we should just set the name of the parameter to the
1892                      * name of the method. */
1893                     (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1894                 else
1895                     (*pptfd)->pParamDesc[j].Name =
1896                         MSFT_ReadName( pcx, paraminfo.oName );
1897                 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1898
1899                 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1900
1901                 /* default value */
1902                 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1903                      (pFuncRec->FKCCIC & 0x1000) )
1904                 {
1905                     INT* pInt = (INT *)((char *)pFuncRec +
1906                                    reclength -
1907                                    (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1908
1909                     PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1910
1911                     pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1912                     pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1913
1914                     MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1915                         pInt[j], pcx);
1916                 }
1917                 else
1918                     elemdesc->u.paramdesc.pparamdescex = NULL;
1919                 /* custom info */
1920                 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1921                 {
1922                     MSFT_CustData(pcx,
1923                                   pFuncRec->OptAttr[7+j],
1924                                   &(*pptfd)->pParamDesc[j].pCustData);
1925                 }
1926
1927                 /* SEEK value = jump to offset,
1928                  * from there jump to the end of record,
1929                  * go back by (j-1) arguments
1930                  */
1931                 MSFT_ReadLEDWords( &paraminfo ,
1932                            sizeof(MSFT_ParameterInfo), pcx,
1933                            recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1934                                                * sizeof(MSFT_ParameterInfo)));
1935             }
1936         }
1937
1938         /* scode is not used: archaic win16 stuff FIXME: right? */
1939         (*pptfd)->funcdesc.cScodes   = 0 ;
1940         (*pptfd)->funcdesc.lprgscode = NULL ;
1941
1942         ptfd_prev = *pptfd;
1943         pptfd      = & ((*pptfd)->next);
1944         recoffset += reclength;
1945     }
1946     HeapFree(GetProcessHeap(), 0, recbuf);
1947 }
1948
1949 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1950                        int cVars, int offset, TLBVarDesc ** pptvd)
1951 {
1952     int infolen, nameoffset, reclength;
1953     char recbuf[256];
1954     MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1955     int i;
1956     int recoffset;
1957
1958     TRACE_(typelib)("\n");
1959
1960     MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1961     MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1962                       ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1963     recoffset += offset+sizeof(INT);
1964     for(i=0;i<cVars;i++){
1965         *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1966     /* name, eventually add to a hash table */
1967         MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1968                           offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
1969         (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1970     /* read the variable information record */
1971         MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1972         reclength &=0xff;
1973         MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1974     /* Optional data */
1975         if(reclength >(6*sizeof(INT)) )
1976             (*pptvd)->HelpContext=pVarRec->HelpContext;
1977         if(reclength >(7*sizeof(INT)) )
1978             (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1979         if(reclength >(8*sizeof(INT)) )
1980         if(reclength >(9*sizeof(INT)) )
1981             (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1982     /* fill the VarDesc Structure */
1983         MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1984                           offset + infolen + (cFuncs + i + 1) * sizeof(INT));
1985         (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1986         (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1987         MSFT_GetTdesc(pcx, pVarRec->DataType,
1988             &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1989 /*   (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1990         if(pVarRec->VarKind == VAR_CONST ){
1991             (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1992             MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1993                 pVarRec->OffsValue, pcx);
1994         } else
1995             (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1996         MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
1997         pptvd=&((*pptvd)->next);
1998         recoffset += reclength;
1999     }
2000 }
2001 /* fill in data for a hreftype (offset). When the referenced type is contained
2002  * in the typelib, it's just an (file) offset in the type info base dir.
2003  * If comes from import, it's an offset+1 in the ImpInfo table
2004  * */
2005 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
2006                           int offset)
2007 {
2008     int j;
2009     TLBRefType **ppRefType = &pTI->reflist;
2010
2011     TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2012
2013     while(*ppRefType) {
2014         if((*ppRefType)->reference == offset)
2015             return;
2016         ppRefType = &(*ppRefType)->next;
2017     }
2018
2019     *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2020                            sizeof(**ppRefType));
2021
2022     if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2023         /* external typelib */
2024         MSFT_ImpInfo impinfo;
2025         TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2026
2027         TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2028
2029         MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2030                           pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2031         for(j=0;pImpLib;j++){   /* search the known offsets of all import libraries */
2032             if(pImpLib->offset==impinfo.oImpFile) break;
2033             pImpLib=pImpLib->next;
2034         }
2035         if(pImpLib){
2036             (*ppRefType)->reference=offset;
2037             (*ppRefType)->pImpTLInfo = pImpLib;
2038             if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2039                 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
2040                 TRACE("importing by guid %s\n", debugstr_guid(&(*ppRefType)->guid));
2041                 (*ppRefType)->index = TLB_REF_USE_GUID;
2042             } else
2043                 (*ppRefType)->index = impinfo.oGuid;
2044         }else{
2045             ERR("Cannot find a reference\n");
2046             (*ppRefType)->reference=-1;
2047             (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
2048         }
2049     }else{
2050         /* in this typelib */
2051         (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2052         (*ppRefType)->reference=offset;
2053         (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2054     }
2055 }
2056
2057 /* process Implemented Interfaces of a com class */
2058 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2059                             int offset)
2060 {
2061     int i;
2062     MSFT_RefRecord refrec;
2063     TLBImplType **ppImpl = &pTI->impltypelist;
2064
2065     TRACE_(typelib)("\n");
2066
2067     for(i=0;i<count;i++){
2068         if(offset<0) break; /* paranoia */
2069         *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2070         MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2071         MSFT_DoRefType(pcx, pTI, refrec.reftype);
2072         (*ppImpl)->hRef = refrec.reftype;
2073         (*ppImpl)->implflags=refrec.flags;
2074         (*ppImpl)->ctCustData=
2075             MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2076         offset=refrec.onext;
2077         ppImpl=&((*ppImpl)->next);
2078     }
2079 }
2080 /*
2081  * process a typeinfo record
2082  */
2083 static ITypeInfoImpl * MSFT_DoTypeInfo(
2084     TLBContext *pcx,
2085     int count,
2086     INT dispatch_href,
2087     ITypeLibImpl * pLibInfo)
2088 {
2089     MSFT_TypeInfoBase tiBase;
2090     ITypeInfoImpl *ptiRet;
2091
2092     TRACE_(typelib)("count=%u\n", count);
2093
2094     ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2095     MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2096                       pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2097
2098 /* this is where we are coming from */
2099     ptiRet->pTypeLib = pLibInfo;
2100     ptiRet->index=count;
2101 /* fill in the typeattr fields */
2102
2103     MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2104     ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid;   /* FIXME: correct? */
2105     ptiRet->TypeAttr.lpstrSchema=NULL;              /* reserved */
2106     ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2107     ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2108     ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2109     ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2110     ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2111     ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2112     ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2113     ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2114     ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2115     ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2116     if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2117         MSFT_GetTdesc(pcx, tiBase.datatype1,
2118             &ptiRet->TypeAttr.tdescAlias, ptiRet);
2119
2120 /*  FIXME: */
2121 /*    IDLDESC  idldescType; *//* never saw this one != zero  */
2122
2123 /* name, eventually add to a hash table */
2124     ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2125     ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2126     TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2127     /* help info */
2128     ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2129     ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2130     ptiRet->dwHelpContext=tiBase.helpcontext;
2131
2132     if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2133         ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2134
2135 /* note: InfoType's Help file and HelpStringDll come from the containing
2136  * library. Further HelpString and Docstring appear to be the same thing :(
2137  */
2138     /* functions */
2139     if(ptiRet->TypeAttr.cFuncs >0 )
2140         MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2141                     ptiRet->TypeAttr.cVars,
2142                     tiBase.memoffset, & ptiRet->funclist);
2143     /* variables */
2144     if(ptiRet->TypeAttr.cVars >0 )
2145         MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2146                    ptiRet->TypeAttr.cVars,
2147                    tiBase.memoffset, & ptiRet->varlist);
2148     if(ptiRet->TypeAttr.cImplTypes >0 ) {
2149         switch(ptiRet->TypeAttr.typekind)
2150         {
2151         case TKIND_COCLASS:
2152             MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2153                 tiBase.datatype1);
2154             break;
2155         case TKIND_DISPATCH:
2156             ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2157
2158             if (tiBase.datatype1 != -1)
2159             {
2160               MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2161               ptiRet->impltypelist->hRef = tiBase.datatype1;
2162             }
2163             else
2164             {
2165               MSFT_DoRefType(pcx, ptiRet, dispatch_href);
2166               ptiRet->impltypelist->hRef = dispatch_href;
2167             }
2168             break;
2169         default:
2170             ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2171             MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2172             ptiRet->impltypelist->hRef = tiBase.datatype1;
2173             break;
2174        }
2175     }
2176     ptiRet->ctCustData=
2177         MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2178
2179     TRACE_(typelib)("%s guid: %s kind:%s\n",
2180        debugstr_w(ptiRet->Name),
2181        debugstr_guid(&ptiRet->TypeAttr.guid),
2182        typekind_desc[ptiRet->TypeAttr.typekind]);
2183
2184     return ptiRet;
2185 }
2186
2187 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2188  * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2189  * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2190  * tradeoff here.
2191  */
2192 static ITypeLibImpl *tlb_cache_first;
2193 static CRITICAL_SECTION cache_section;
2194 static CRITICAL_SECTION_DEBUG cache_section_debug =
2195 {
2196     0, 0, &cache_section,
2197     { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2198       0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2199 };
2200 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2201
2202
2203 /****************************************************************************
2204  *      TLB_ReadTypeLib
2205  *
2206  * find the type of the typelib file and map the typelib resource into
2207  * the memory
2208  */
2209 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2210 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2211 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2212 {
2213     ITypeLibImpl *entry;
2214     int ret = TYPE_E_CANTLOADLIBRARY;
2215     INT index = 1;
2216     HINSTANCE hinstDLL;
2217
2218     *ppTypeLib = NULL;
2219
2220     lstrcpynW(pszPath, pszFileName, cchPath);
2221
2222     /* first try loading as a dll and access the typelib as a resource */
2223     hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES |
2224             LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2225     if (!hinstDLL)
2226     {
2227         /* it may have been specified with resource index appended to the
2228          * path, so remove it and try again */
2229         const WCHAR *pIndexStr = strrchrW(pszFileName, '\\');
2230         if(pIndexStr && pIndexStr != pszFileName && *++pIndexStr != '\0')
2231         {
2232             index = atoiW(pIndexStr);
2233             pszPath[pIndexStr - pszFileName - 1] = '\0';
2234
2235             hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES |
2236                     LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2237         }
2238     }
2239
2240     /* get the path to the specified typelib file */
2241     if (!hinstDLL)
2242     {
2243         /* otherwise, try loading as a regular file */
2244         if (!SearchPathW(NULL, pszFileName, NULL, cchPath, pszPath, NULL))
2245             return TYPE_E_CANTLOADLIBRARY;
2246     }
2247
2248     TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2249
2250     /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2251     EnterCriticalSection(&cache_section);
2252     for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2253     {
2254         if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2255         {
2256             TRACE("cache hit\n");
2257             *ppTypeLib = (ITypeLib2*)entry;
2258             ITypeLib_AddRef(*ppTypeLib);
2259             LeaveCriticalSection(&cache_section);
2260             FreeLibrary(hinstDLL);
2261             return S_OK;
2262         }
2263     }
2264     LeaveCriticalSection(&cache_section);
2265
2266     /* now actually load and parse the typelib */
2267     if (hinstDLL)
2268     {
2269         static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2270         HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2271         if (hrsrc)
2272         {
2273             HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2274             if (hGlobal)
2275             {
2276                 LPVOID pBase = LockResource(hGlobal);
2277                 DWORD  dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2278
2279                 if (pBase)
2280                 {
2281                     /* try to load as incore resource */
2282                     DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2283                     if (dwSignature == MSFT_SIGNATURE)
2284                         *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2285                     else if (dwSignature == SLTG_SIGNATURE)
2286                         *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2287                     else
2288                         FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2289                 }
2290                 FreeResource( hGlobal );
2291             }
2292         }
2293         FreeLibrary(hinstDLL);
2294     }
2295     else
2296     {
2297         HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2298         if (INVALID_HANDLE_VALUE != hFile)
2299         {
2300             HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2301             if (hMapping)
2302             {
2303                 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2304                 if(pBase)
2305                 {
2306                     /* retrieve file size */
2307                     DWORD dwTLBLength = GetFileSize(hFile, NULL);
2308                     DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2309
2310                     if (dwSignature == MSFT_SIGNATURE)
2311                         *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2312                     else if (dwSignature == SLTG_SIGNATURE)
2313                         *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2314
2315                     UnmapViewOfFile(pBase);
2316                 }
2317                 CloseHandle(hMapping);
2318             }
2319             CloseHandle(hFile);
2320         }
2321     }
2322
2323     if(*ppTypeLib) {
2324         ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2325
2326         TRACE("adding to cache\n");
2327         impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2328         lstrcpyW(impl->path, pszPath);
2329         /* We should really canonicalise the path here. */
2330         impl->index = index;
2331
2332         /* FIXME: check if it has added already in the meantime */
2333         EnterCriticalSection(&cache_section);
2334         if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2335         impl->prev = NULL;
2336         tlb_cache_first = impl;
2337         LeaveCriticalSection(&cache_section);
2338         ret = S_OK;
2339     } else
2340         ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2341
2342     return ret;
2343 }
2344
2345 /*================== ITypeLib(2) Methods ===================================*/
2346
2347 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2348 {
2349     ITypeLibImpl* pTypeLibImpl;
2350
2351     pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2352     if (!pTypeLibImpl) return NULL;
2353
2354     pTypeLibImpl->lpVtbl = &tlbvt;
2355     pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2356     pTypeLibImpl->ref = 1;
2357
2358     return pTypeLibImpl;
2359 }
2360
2361 /****************************************************************************
2362  *      ITypeLib2_Constructor_MSFT
2363  *
2364  * loading an MSFT typelib from an in-memory image
2365  */
2366 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2367 {
2368     TLBContext cx;
2369     long lPSegDir;
2370     MSFT_Header tlbHeader;
2371     MSFT_SegDir tlbSegDir;
2372     ITypeLibImpl * pTypeLibImpl;
2373
2374     TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2375
2376     pTypeLibImpl = TypeLibImpl_Constructor();
2377     if (!pTypeLibImpl) return NULL;
2378
2379     /* get pointer to beginning of typelib data */
2380     cx.pos = 0;
2381     cx.oStart=0;
2382     cx.mapping = pLib;
2383     cx.pLibInfo = pTypeLibImpl;
2384     cx.length = dwTLBLength;
2385
2386     /* read header */
2387     MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2388     TRACE_(typelib)("header:\n");
2389     TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2390     if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2391         FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2392         return NULL;
2393     }
2394     TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2395
2396     /* there is a small amount of information here until the next important
2397      * part:
2398      * the segment directory . Try to calculate the amount of data */
2399     lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2400
2401     /* now read the segment directory */
2402     TRACE("read segment directory (at %ld)\n",lPSegDir);
2403     MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2404     cx.pTblDir = &tlbSegDir;
2405
2406     /* just check two entries */
2407     if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2408     {
2409         ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2410         HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2411         return NULL;
2412     }
2413
2414     /* now fill our internal data */
2415     /* TLIBATTR fields */
2416     MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2417
2418     /*    pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2419     /* Windows seems to have zero here, is this correct? */
2420     if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2421       pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2422     else
2423       pTypeLibImpl->LibAttr.lcid = 0;
2424
2425     pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2426     pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2427     pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2428     pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2429
2430     /* name, eventually add to a hash table */
2431     pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2432
2433     /* help info */
2434     pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2435     pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2436
2437     if( tlbHeader.varflags & HELPDLLFLAG)
2438     {
2439             int offset;
2440             MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2441             pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2442     }
2443
2444     pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2445
2446     /* custom data */
2447     if(tlbHeader.CustomDataOffset >= 0)
2448     {
2449         pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2450     }
2451
2452     /* fill in typedescriptions */
2453     if(tlbSegDir.pTypdescTab.length > 0)
2454     {
2455         int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2456         INT16 td[4];
2457         pTypeLibImpl->ctTypeDesc = cTD;
2458         pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2459         MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2460         for(i=0; i<cTD; )
2461         {
2462             /* FIXME: add several sanity checks here */
2463             pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2464             if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2465             {
2466                 /* FIXME: check safearray */
2467                 if(td[3] < 0)
2468                     pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2469                 else
2470                     pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2471             }
2472             else if(td[0] == VT_CARRAY)
2473             {
2474                 /* array descr table here */
2475                 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]);  /* temp store offset in*/
2476             }
2477             else if(td[0] == VT_USERDEFINED)
2478             {
2479                 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2480             }
2481             if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2482         }
2483
2484         /* second time around to fill the array subscript info */
2485         for(i=0;i<cTD;i++)
2486         {
2487             if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2488             if(tlbSegDir.pArrayDescriptions.offset>0)
2489             {
2490                 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2491                 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2492
2493                 if(td[1]<0)
2494                     pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2495                 else
2496                     pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2497
2498                 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2499
2500                 for(j = 0; j<td[2]; j++)
2501                 {
2502                     MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2503                                       sizeof(INT), &cx, DO_NOT_SEEK);
2504                     MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2505                                       sizeof(INT), &cx, DO_NOT_SEEK);
2506                 }
2507             }
2508             else
2509             {
2510                 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2511                 ERR("didn't find array description data\n");
2512             }
2513         }
2514     }
2515
2516     /* imported type libs */
2517     if(tlbSegDir.pImpFiles.offset>0)
2518     {
2519         TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2520         int oGuid, offset = tlbSegDir.pImpFiles.offset;
2521         UINT16 size;
2522
2523         while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2524         {
2525             char *name;
2526             DWORD len;
2527
2528             *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2529             (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2530             MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2531
2532             MSFT_ReadLEDWords(&(*ppImpLib)->lcid,         sizeof(LCID),   &cx, DO_NOT_SEEK);
2533             MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD),   &cx, DO_NOT_SEEK);
2534             MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD),   &cx, DO_NOT_SEEK);
2535             MSFT_ReadLEWords(& size,                      sizeof(UINT16), &cx, DO_NOT_SEEK);
2536
2537             size >>= 2;
2538             name = TLB_Alloc(size+1);
2539             MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2540             len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2541             (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2542             MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2543             TLB_Free(name);
2544
2545             MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2546             offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2547
2548             ppImpLib = &(*ppImpLib)->next;
2549         }
2550     }
2551
2552     /* type info's */
2553     if(tlbHeader.nrtypeinfos >= 0 )
2554     {
2555         /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2556         ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2557         int i;
2558
2559         for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2560         {
2561             *ppTI = MSFT_DoTypeInfo(&cx, i, tlbHeader.dispatchpos, pTypeLibImpl);
2562
2563             ppTI = &((*ppTI)->next);
2564             (pTypeLibImpl->TypeInfoCount)++;
2565         }
2566     }
2567
2568     TRACE("(%p)\n", pTypeLibImpl);
2569     return (ITypeLib2*) pTypeLibImpl;
2570 }
2571
2572
2573 static BSTR TLB_MultiByteToBSTR(char *ptr)
2574 {
2575     DWORD len;
2576     WCHAR *nameW;
2577     BSTR ret;
2578
2579     len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2580     nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2581     MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2582     ret = SysAllocString(nameW);
2583     HeapFree(GetProcessHeap(), 0, nameW);
2584     return ret;
2585 }
2586
2587 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2588 {
2589   char b[3];
2590   int i;
2591   short s;
2592
2593   if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2594     FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2595     return FALSE;
2596   }
2597
2598   guid->Data4[0] = s >> 8;
2599   guid->Data4[1] = s & 0xff;
2600
2601   b[2] = '\0';
2602   for(i = 0; i < 6; i++) {
2603     memcpy(b, str + 24 + 2 * i, 2);
2604     guid->Data4[i + 2] = strtol(b, NULL, 16);
2605   }
2606   return TRUE;
2607 }
2608
2609 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2610 {
2611     WORD bytelen;
2612     DWORD len;
2613     WCHAR *nameW;
2614
2615     *pBstr = NULL;
2616     bytelen = *(WORD*)ptr;
2617     if(bytelen == 0xffff) return 2;
2618     len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2619     nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2620     len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2621     *pBstr = SysAllocStringLen(nameW, len);
2622     HeapFree(GetProcessHeap(), 0, nameW);
2623     return bytelen + 2;
2624 }
2625
2626 static WORD SLTG_ReadStringA(char *ptr, char **str)
2627 {
2628     WORD bytelen;
2629
2630     *str = NULL;
2631     bytelen = *(WORD*)ptr;
2632     if(bytelen == 0xffff) return 2;
2633     *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2634     memcpy(*str, ptr + 2, bytelen);
2635     (*str)[bytelen] = '\0';
2636     return bytelen + 2;
2637 }
2638
2639 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2640 {
2641     char *ptr = pLibBlk;
2642     WORD w;
2643
2644     if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2645         FIXME("libblk magic = %04x\n", w);
2646         return 0;
2647     }
2648
2649     ptr += 6;
2650     if((w = *(WORD*)ptr) != 0xffff) {
2651         FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2652         ptr += w;
2653     }
2654     ptr += 2;
2655
2656     ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2657
2658     ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2659
2660     pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2661     ptr += 4;
2662
2663     pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2664     ptr += 2;
2665
2666     if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2667         pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2668     else
2669         pTypeLibImpl->LibAttr.lcid = 0;
2670     ptr += 2;
2671
2672     ptr += 4; /* skip res12 */
2673
2674     pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2675     ptr += 2;
2676
2677     pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2678     ptr += 2;
2679
2680     pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2681     ptr += 2;
2682
2683     memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2684     ptr += sizeof(GUID);
2685
2686     return ptr - (char*)pLibBlk;
2687 }
2688
2689 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD)
2690 {
2691     BOOL done = FALSE;
2692
2693     while(!done) {
2694         if((*pType & 0xe00) == 0xe00) {
2695             pTD->vt = VT_PTR;
2696             pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2697                                        sizeof(TYPEDESC));
2698             pTD = pTD->u.lptdesc;
2699         }
2700         switch(*pType & 0x3f) {
2701         case VT_PTR:
2702             pTD->vt = VT_PTR;
2703             pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2704                                        sizeof(TYPEDESC));
2705             pTD = pTD->u.lptdesc;
2706             break;
2707
2708         case VT_USERDEFINED:
2709             pTD->vt = VT_USERDEFINED;
2710             pTD->u.hreftype = *(++pType) / 4;
2711             done = TRUE;
2712             break;
2713
2714         case VT_CARRAY:
2715           {
2716             /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2717                array */
2718
2719             SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2720
2721             pTD->vt = VT_CARRAY;
2722             pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2723                                 sizeof(ARRAYDESC) +
2724                                 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2725             pTD->u.lpadesc->cDims = pSA->cDims;
2726             memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2727                    pSA->cDims * sizeof(SAFEARRAYBOUND));
2728
2729             pTD = &pTD->u.lpadesc->tdescElem;
2730             break;
2731           }
2732
2733         case VT_SAFEARRAY:
2734           {
2735             /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2736                useful? */
2737
2738             pType++;
2739             pTD->vt = VT_SAFEARRAY;
2740             pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2741                                        sizeof(TYPEDESC));
2742             pTD = pTD->u.lptdesc;
2743             break;
2744           }
2745         default:
2746             pTD->vt = *pType & 0x3f;
2747             done = TRUE;
2748             break;
2749         }
2750         pType++;
2751     }
2752     return pType;
2753 }
2754
2755 static WORD *SLTG_DoElem(WORD *pType, char *pBlk, ELEMDESC *pElem)
2756 {
2757     /* Handle [in/out] first */
2758     if((*pType & 0xc000) == 0xc000)
2759         pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2760     else if(*pType & 0x8000)
2761         pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2762     else if(*pType & 0x4000)
2763         pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2764     else
2765         pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2766
2767     if(*pType & 0x2000)
2768         pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2769
2770     if(*pType & 0x80)
2771         pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2772
2773     return SLTG_DoType(pType, pBlk, &pElem->tdesc);
2774 }
2775
2776
2777 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2778                         char *pNameTable)
2779 {
2780     int ref;
2781     char *name;
2782     TLBRefType **ppRefType;
2783
2784     if(pRef->magic != SLTG_REF_MAGIC) {
2785         FIXME("Ref magic = %x\n", pRef->magic);
2786         return;
2787     }
2788     name = ( (char*)(&pRef->names) + pRef->number);
2789
2790     ppRefType = &pTI->reflist;
2791     for(ref = 0; ref < pRef->number >> 3; ref++) {
2792         char *refname;
2793         unsigned int lib_offs, type_num;
2794
2795         *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2796                                sizeof(**ppRefType));
2797
2798         name += SLTG_ReadStringA(name, &refname);
2799         if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2800             FIXME("Can't sscanf ref\n");
2801         if(lib_offs != 0xffff) {
2802             TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2803
2804             while(*import) {
2805                 if((*import)->offset == lib_offs)
2806                     break;
2807                 import = &(*import)->next;
2808             }
2809             if(!*import) {
2810                 char fname[MAX_PATH+1];
2811                 int len;
2812
2813                 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2814                                     sizeof(**import));
2815                 (*import)->offset = lib_offs;
2816                 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2817                                     &(*import)->guid);
2818                 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
2819                           &(*import)->wVersionMajor,
2820                           &(*import)->wVersionMinor,
2821                           &(*import)->lcid, fname) != 4) {
2822                   FIXME("can't sscanf ref %s\n",
2823                         pNameTable + lib_offs + 40);
2824                 }
2825                 len = strlen(fname);
2826                 if(fname[len-1] != '#')
2827                     FIXME("fname = %s\n", fname);
2828                 fname[len-1] = '\0';
2829                 (*import)->name = TLB_MultiByteToBSTR(fname);
2830             }
2831             (*ppRefType)->pImpTLInfo = *import;
2832         } else { /* internal ref */
2833           (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2834         }
2835         (*ppRefType)->reference = ref;
2836         (*ppRefType)->index = type_num;
2837
2838         HeapFree(GetProcessHeap(), 0, refname);
2839         ppRefType = &(*ppRefType)->next;
2840     }
2841     if((BYTE)*name != SLTG_REF_MAGIC)
2842       FIXME("End of ref block magic = %x\n", *name);
2843     dump_TLBRefType(pTI->reflist);
2844 }
2845
2846 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2847                           BOOL OneOnly)
2848 {
2849     SLTG_ImplInfo *info;
2850     TLBImplType **ppImplType = &pTI->impltypelist;
2851     /* I don't really get this structure, usually it's 0x16 bytes
2852        long, but iuser.tlb contains some that are 0x18 bytes long.
2853        That's ok because we can use the next ptr to jump to the next
2854        one. But how do we know the length of the last one?  The WORD
2855        at offs 0x8 might be the clue.  For now I'm just assuming that
2856        the last one is the regular 0x16 bytes. */
2857
2858     info = (SLTG_ImplInfo*)pBlk;
2859     while(1) {
2860         *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2861                                 sizeof(**ppImplType));
2862         (*ppImplType)->hRef = info->ref;
2863         (*ppImplType)->implflags = info->impltypeflags;
2864         pTI->TypeAttr.cImplTypes++;
2865         ppImplType = &(*ppImplType)->next;
2866
2867         if(info->next == 0xffff)
2868             break;
2869         if(OneOnly)
2870             FIXME("Interface inheriting more than one interface\n");
2871         info = (SLTG_ImplInfo*)(pBlk + info->next);
2872     }
2873     info++; /* see comment at top of function */
2874     return (char*)info;
2875 }
2876
2877 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars, char *pNameTable)
2878 {
2879   TLBVarDesc **ppVarDesc = &pTI->varlist;
2880   BSTR bstrPrevName = NULL;
2881   SLTG_Variable *pItem;
2882   unsigned short i;
2883   WORD *pType;
2884   char buf[300];
2885
2886   for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
2887       pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
2888
2889       *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2890                              sizeof(**ppVarDesc));
2891       (*ppVarDesc)->vardesc.memid = pItem->memid;
2892
2893       if (pItem->magic != SLTG_VAR_MAGIC &&
2894           pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
2895           FIXME_(typelib)("var magic = %02x\n", pItem->magic);
2896           return;
2897       }
2898
2899       if (pItem->name == 0xfffe)
2900         (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
2901       else
2902         (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2903
2904       TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
2905       TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
2906
2907       if (pItem->flags & 0x40) {
2908         TRACE_(typelib)("VAR_DISPATCH\n");
2909         (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
2910       }
2911       else if (pItem->flags & 0x10) {
2912         TRACE_(typelib)("VAR_CONST\n");
2913         (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2914         (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2915                                                        sizeof(VARIANT));
2916         V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2917         V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2918           *(INT*)(pBlk + pItem->byte_offs);
2919       }
2920       else {
2921         TRACE_(typelib)("VAR_PERINSTANCE\n");
2922         (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2923         (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2924       }
2925
2926       if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
2927         (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
2928
2929       if (pItem->flags & 0x80)
2930         (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
2931
2932       if(pItem->flags & 0x02)
2933           pType = &pItem->type;
2934       else
2935           pType = (WORD*)(pBlk + pItem->type);
2936
2937       if (pItem->flags & ~0xd2)
2938         FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xd2);
2939
2940       SLTG_DoElem(pType, pBlk,
2941                   &(*ppVarDesc)->vardesc.elemdescVar);
2942
2943       dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2944
2945       bstrPrevName = (*ppVarDesc)->Name;
2946       ppVarDesc = &((*ppVarDesc)->next);
2947   }
2948   pTI->TypeAttr.cVars = cVars;
2949 }
2950
2951 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cFuncs, char *pNameTable)
2952 {
2953     SLTG_Function *pFunc;
2954     unsigned short i;
2955     TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2956
2957     for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
2958         pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
2959
2960         int param;
2961         WORD *pType, *pArg;
2962
2963         *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2964                                 sizeof(**ppFuncDesc));
2965
2966         switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
2967         case SLTG_FUNCTION_MAGIC:
2968             (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
2969             break;
2970         case SLTG_DISPATCH_FUNCTION_MAGIC:
2971             (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
2972             break;
2973         case SLTG_STATIC_FUNCTION_MAGIC:
2974             (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
2975             break;
2976         default:
2977             FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
2978             HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
2979             *ppFuncDesc = NULL;
2980             return;
2981         }
2982         (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2983
2984         (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2985         (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2986         (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2987         (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2988         (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2989         (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2990
2991         if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
2992             (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2993
2994         if(pFunc->retnextopt & 0x80)
2995             pType = &pFunc->rettype;
2996         else
2997             pType = (WORD*)(pBlk + pFunc->rettype);
2998
2999         SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc);
3000
3001         (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3002           HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3003                     (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3004         (*ppFuncDesc)->pParamDesc =
3005           HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3006                     (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3007
3008         pArg = (WORD*)(pBlk + pFunc->arg_off);
3009
3010         for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3011             char *paramName = pNameTable + *pArg;
3012             BOOL HaveOffs;
3013             /* If arg type follows then paramName points to the 2nd
3014                letter of the name, else the next WORD is an offset to
3015                the arg type and paramName points to the first letter.
3016                So let's take one char off paramName and see if we're
3017                pointing at an alpha-numeric char.  However if *pArg is
3018                0xffff or 0xfffe then the param has no name, the former
3019                meaning that the next WORD is the type, the latter
3020                meaning the the next WORD is an offset to the type. */
3021
3022             HaveOffs = FALSE;
3023             if(*pArg == 0xffff)
3024                 paramName = NULL;
3025             else if(*pArg == 0xfffe) {
3026                 paramName = NULL;
3027                 HaveOffs = TRUE;
3028             }
3029             else if(paramName[-1] && !isalnum(paramName[-1]))
3030                 HaveOffs = TRUE;
3031
3032             pArg++;
3033
3034             if(HaveOffs) { /* the next word is an offset to type */
3035                 pType = (WORD*)(pBlk + *pArg);
3036                 SLTG_DoElem(pType, pBlk,
3037                             &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
3038                 pArg++;
3039             } else {
3040                 if(paramName)
3041                   paramName--;
3042                 pArg = SLTG_DoElem(pArg, pBlk,
3043                            &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
3044             }
3045
3046             /* Are we an optional param ? */
3047             if((*ppFuncDesc)->funcdesc.cParams - param <=
3048                (*ppFuncDesc)->funcdesc.cParamsOpt)
3049               (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3050
3051             if(paramName) {
3052                 (*ppFuncDesc)->pParamDesc[param].Name =
3053                   TLB_MultiByteToBSTR(paramName);
3054             }
3055         }
3056
3057         ppFuncDesc = &((*ppFuncDesc)->next);
3058         if(pFunc->next == 0xffff) break;
3059     }
3060     pTI->TypeAttr.cFuncs = cFuncs;
3061 }
3062
3063 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3064                                 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3065                                 SLTG_TypeInfoTail *pTITail)
3066 {
3067     char *pFirstItem, *pNextItem;
3068
3069     if(pTIHeader->href_table != 0xffffffff) {
3070         SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3071                     pNameTable);
3072     }
3073
3074     pFirstItem = pNextItem = pBlk;
3075
3076     if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3077         pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
3078     }
3079 }
3080
3081
3082 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3083                                   char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3084                                   SLTG_TypeInfoTail *pTITail)
3085 {
3086     char *pFirstItem, *pNextItem;
3087
3088     if(pTIHeader->href_table != 0xffffffff) {
3089         SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3090                     pNameTable);
3091     }
3092
3093     pFirstItem = pNextItem = pBlk;
3094
3095     if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3096         pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
3097     }
3098
3099     if (pTITail->funcs_off != 0xffff)
3100         SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3101
3102     if (TRACE_ON(typelib))
3103         dump_TLBFuncDesc(pTI->funclist);
3104 }
3105
3106 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3107                                char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3108                                SLTG_TypeInfoTail *pTITail)
3109 {
3110   SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3111 }
3112
3113 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3114                               char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3115                               SLTG_TypeInfoTail *pTITail)
3116 {
3117   WORD *pType;
3118
3119   if (pTITail->simple_alias) {
3120     /* if simple alias, no more processing required */
3121     pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3122     return;
3123   }
3124
3125   if(pTIHeader->href_table != 0xffffffff) {
3126       SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3127                   pNameTable);
3128   }
3129
3130   /* otherwise it is an offset to a type */
3131   pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3132
3133   SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias);
3134 }
3135
3136 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3137                                  char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3138                                  SLTG_TypeInfoTail *pTITail)
3139 {
3140   if (pTIHeader->href_table != 0xffffffff)
3141       SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3142                                   pNameTable);
3143
3144   if (pTITail->vars_off != 0xffff)
3145     SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3146
3147   if (pTITail->funcs_off != 0xffff)
3148     SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3149
3150   /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3151    * of dispinterface functons including the IDispatch ones, so
3152    * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3153   pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3154
3155   if (TRACE_ON(typelib))
3156       dump_TLBFuncDesc(pTI->funclist);
3157 }
3158
3159 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3160                              char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3161                              SLTG_TypeInfoTail *pTITail)
3162 {
3163   SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3164 }
3165
3166 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3167                                char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3168                                SLTG_TypeInfoTail *pTITail)
3169 {
3170   if (pTIHeader->href_table != 0xffffffff)
3171       SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3172                                   pNameTable);
3173
3174   if (pTITail->vars_off != 0xffff)
3175     SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3176
3177   if (pTITail->funcs_off != 0xffff)
3178     SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3179 }
3180
3181 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3182    managable copy of it into this */
3183 typedef struct {
3184   WORD small_no;
3185   char *index_name;
3186   char *other_name;
3187   WORD res1a;
3188   WORD name_offs;
3189   WORD more_bytes;
3190   char *extra;
3191   WORD res20;
3192   DWORD helpcontext;
3193   WORD res26;
3194   GUID uuid;
3195 } SLTG_InternalOtherTypeInfo;
3196
3197 /****************************************************************************
3198  *      ITypeLib2_Constructor_SLTG
3199  *
3200  * loading a SLTG typelib from an in-memory image
3201  */
3202 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3203 {
3204     ITypeLibImpl *pTypeLibImpl;
3205     SLTG_Header *pHeader;
3206     SLTG_BlkEntry *pBlkEntry;
3207     SLTG_Magic *pMagic;
3208     SLTG_Index *pIndex;
3209     SLTG_Pad9 *pPad9;
3210     LPVOID pBlk, pFirstBlk;
3211     SLTG_LibBlk *pLibBlk;
3212     SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3213     char *pAfterOTIBlks = NULL;
3214     char *pNameTable, *ptr;
3215     int i;
3216     DWORD len, order;
3217     ITypeInfoImpl **ppTypeInfoImpl;
3218
3219     TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3220
3221
3222     pTypeLibImpl = TypeLibImpl_Constructor();
3223     if (!pTypeLibImpl) return NULL;
3224
3225     pHeader = pLib;
3226
3227     TRACE_(typelib)("header:\n");
3228     TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3229           pHeader->nrOfFileBlks );
3230     if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3231         FIXME("Header type magic 0x%08x not supported.\n",
3232               pHeader->SLTG_magic);
3233         return NULL;
3234     }
3235
3236     /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3237     pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3238
3239     /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3240     pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3241
3242     /* Next we have a magic block */
3243     pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3244
3245     /* Let's see if we're still in sync */
3246     if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3247               sizeof(SLTG_COMPOBJ_MAGIC))) {
3248         FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3249         return NULL;
3250     }
3251     if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3252               sizeof(SLTG_DIR_MAGIC))) {
3253         FIXME("dir magic = %s\n", pMagic->dir_magic);
3254         return NULL;
3255     }
3256
3257     pIndex = (SLTG_Index*)(pMagic+1);
3258
3259     pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3260
3261     pFirstBlk = (LPVOID)(pPad9 + 1);
3262
3263     /* We'll set up a ptr to the main library block, which is the last one. */
3264
3265     for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3266           pBlkEntry[order].next != 0;
3267           order = pBlkEntry[order].next - 1, i++) {
3268        pBlk = (char*)pBlk + pBlkEntry[order].len;
3269     }
3270     pLibBlk = pBlk;
3271
3272     len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3273
3274     /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3275        interspersed */
3276
3277     len += 0x40;
3278
3279     /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3280
3281     pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3282                                    sizeof(*pOtherTypeInfoBlks) *
3283                                    pTypeLibImpl->TypeInfoCount);
3284
3285
3286     ptr = (char*)pLibBlk + len;
3287
3288     for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3289         WORD w, extra;
3290         len = 0;
3291
3292         pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3293
3294         w = *(WORD*)(ptr + 2);
3295         if(w != 0xffff) {
3296             len += w;
3297             pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3298                                                          w+1);
3299             memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3300             pOtherTypeInfoBlks[i].index_name[w] = '\0';
3301         }
3302         w = *(WORD*)(ptr + 4 + len);
3303         if(w != 0xffff) {
3304             TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3305             len += w;
3306             pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3307                                                          w+1);
3308             memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3309             pOtherTypeInfoBlks[i].other_name[w] = '\0';
3310         }
3311         pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3312         pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3313         extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3314         if(extra) {
3315             pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3316                                                     extra);
3317             memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3318             len += extra;
3319         }
3320         pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3321         pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3322         pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3323         memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3324         len += sizeof(SLTG_OtherTypeInfo);
3325         ptr += len;
3326     }
3327
3328     pAfterOTIBlks = ptr;
3329
3330     /* Skip this WORD and get the next DWORD */
3331     len = *(DWORD*)(pAfterOTIBlks + 2);
3332
3333     /* Now add this to pLibBLk look at what we're pointing at and
3334        possibly add 0x20, then add 0x216, sprinkle a bit a magic
3335        dust and we should be pointing at the beginning of the name
3336        table */
3337
3338     pNameTable = (char*)pLibBlk + len;
3339
3340    switch(*(WORD*)pNameTable) {
3341    case 0xffff:
3342        break;
3343    case 0x0200:
3344        pNameTable += 0x20;
3345        break;
3346    default:
3347        FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3348        break;
3349    }
3350
3351     pNameTable += 0x216;
3352
3353     pNameTable += 2;
3354
3355     TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3356
3357     pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3358
3359
3360     /* Hopefully we now have enough ptrs set up to actually read in
3361        some TypeInfos.  It's not clear which order to do them in, so
3362        I'll just follow the links along the BlkEntry chain and read
3363        them in the order in which they are in the file */
3364
3365     ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3366
3367     for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3368         pBlkEntry[order].next != 0;
3369         order = pBlkEntry[order].next - 1, i++) {
3370
3371       SLTG_TypeInfoHeader *pTIHeader;
3372       SLTG_TypeInfoTail *pTITail;
3373       SLTG_MemberHeader *pMemHeader;
3374
3375       if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3376                 pOtherTypeInfoBlks[i].index_name)) {
3377         FIXME("Index strings don't match\n");
3378         return NULL;
3379       }
3380
3381       pTIHeader = pBlk;
3382       if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3383         FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3384         return NULL;
3385       }
3386       TRACE("pTIHeader->res06 = %x, pTIHeader->res0e = %x, pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3387         pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3388
3389       *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3390       (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3391       (*ppTypeInfoImpl)->index = i;
3392       (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3393                                              pOtherTypeInfoBlks[i].name_offs +
3394                                              pNameTable);
3395       (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3396       memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3397              sizeof(GUID));
3398       (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3399       (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3400       (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3401       (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3402         (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3403
3404       if((pTIHeader->typeflags1 & 7) != 2)
3405         FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3406       if(pTIHeader->typeflags3 != 2)
3407         FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3408
3409       TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3410             debugstr_w((*ppTypeInfoImpl)->Name),
3411             typekind_desc[pTIHeader->typekind],
3412             debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3413             (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3414
3415       pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3416
3417       pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3418
3419       (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3420       (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3421       (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3422
3423       switch(pTIHeader->typekind) {
3424       case TKIND_ENUM:
3425         SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3426                          pTIHeader, pTITail);
3427         break;
3428
3429       case TKIND_RECORD:
3430         SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3431                            pTIHeader, pTITail);
3432         break;
3433
3434       case TKIND_INTERFACE:
3435         SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3436                               pTIHeader, pTITail);
3437         break;
3438
3439       case TKIND_COCLASS:
3440         SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3441                             pTIHeader, pTITail);
3442         break;
3443
3444       case TKIND_ALIAS:
3445         SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3446                           pTIHeader, pTITail);
3447         break;
3448
3449       case TKIND_DISPATCH:
3450         SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3451                              pTIHeader, pTITail);
3452         break;
3453
3454       case TKIND_MODULE:
3455         SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3456                            pTIHeader, pTITail);
3457         break;
3458
3459       default:
3460         FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3461         break;
3462
3463       }
3464
3465       if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3466                        but we've already set those */
3467 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3468           X(06);
3469           X(16);
3470           X(18);
3471           X(1a);
3472           X(1e);
3473           X(24);
3474           X(26);
3475           X(2a);
3476           X(2c);
3477           X(2e);
3478           X(30);
3479           X(32);
3480           X(34);
3481       }
3482       ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3483       pBlk = (char*)pBlk + pBlkEntry[order].len;
3484     }
3485
3486     if(i != pTypeLibImpl->TypeInfoCount) {
3487       FIXME("Somehow processed %d TypeInfos\n", i);
3488       return NULL;
3489     }
3490
3491     HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3492     return (ITypeLib2*)pTypeLibImpl;
3493 }
3494
3495 /* ITypeLib::QueryInterface
3496  */
3497 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3498         ITypeLib2 * iface,
3499         REFIID riid,
3500         VOID **ppvObject)
3501 {
3502     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3503
3504     TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3505
3506     *ppvObject=NULL;
3507     if(IsEqualIID(riid, &IID_IUnknown) ||
3508        IsEqualIID(riid,&IID_ITypeLib)||
3509        IsEqualIID(riid,&IID_ITypeLib2))
3510     {
3511         *ppvObject = This;
3512     }
3513
3514     if(*ppvObject)
3515     {
3516         ITypeLib2_AddRef(iface);
3517         TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3518         return S_OK;
3519     }
3520     TRACE("-- Interface: E_NOINTERFACE\n");
3521     return E_NOINTERFACE;
3522 }
3523
3524 /* ITypeLib::AddRef
3525  */
3526 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3527 {
3528     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3529     ULONG ref = InterlockedIncrement(&This->ref);
3530
3531     TRACE("(%p)->ref was %u\n",This, ref - 1);
3532
3533     return ref;
3534 }
3535
3536 /* ITypeLib::Release
3537  */
3538 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3539 {
3540     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3541     ULONG ref = InterlockedDecrement(&This->ref);
3542
3543     TRACE("(%p)->(%u)\n",This, ref);
3544
3545     if (!ref)
3546     {
3547       TLBImpLib *pImpLib, *pImpLibNext;
3548       TLBCustData *pCustData, *pCustDataNext;
3549       int i;
3550
3551       /* remove cache entry */
3552       if(This->path)
3553       {
3554           TRACE("removing from cache list\n");
3555           EnterCriticalSection(&cache_section);
3556           if (This->next) This->next->prev = This->prev;
3557           if (This->prev) This->prev->next = This->next;
3558           else tlb_cache_first = This->next;
3559           LeaveCriticalSection(&cache_section);
3560           HeapFree(GetProcessHeap(), 0, This->path);
3561       }
3562       TRACE(" destroying ITypeLib(%p)\n",This);
3563
3564       if (This->Name)
3565       {
3566           SysFreeString(This->Name);
3567           This->Name = NULL;
3568       }
3569
3570       if (This->DocString)
3571       {
3572           SysFreeString(This->DocString);
3573           This->DocString = NULL;
3574       }
3575
3576       if (This->HelpFile)
3577       {
3578           SysFreeString(This->HelpFile);
3579           This->HelpFile = NULL;
3580       }
3581
3582       if (This->HelpStringDll)
3583       {
3584           SysFreeString(This->HelpStringDll);
3585           This->HelpStringDll = NULL;
3586       }
3587
3588       for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
3589       {
3590           VariantClear(&pCustData->data);
3591
3592           pCustDataNext = pCustData->next;
3593           TLB_Free(pCustData);
3594       }
3595
3596       for (i = 0; i < This->ctTypeDesc; i++)
3597           if (This->pTypeDesc[i].vt == VT_CARRAY)
3598               TLB_Free(This->pTypeDesc[i].u.lpadesc);
3599
3600       TLB_Free(This->pTypeDesc);
3601
3602       for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
3603       {
3604           if (pImpLib->pImpTypeLib)
3605               ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
3606           TLB_Free(pImpLib->name);
3607
3608           pImpLibNext = pImpLib->next;
3609           TLB_Free(pImpLib);
3610       }
3611
3612       if (This->pTypeInfo) /* can be NULL */
3613           ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3614       HeapFree(GetProcessHeap(),0,This);
3615       return 0;
3616     }
3617
3618     return ref;
3619 }
3620
3621 /* ITypeLib::GetTypeInfoCount
3622  *
3623  * Returns the number of type descriptions in the type library
3624  */
3625 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3626 {
3627     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3628     TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3629     return This->TypeInfoCount;
3630 }
3631
3632 /* ITypeLib::GetTypeInfo
3633  *
3634  * retrieves the specified type description in the library.
3635  */
3636 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3637     ITypeLib2 *iface,
3638     UINT index,
3639     ITypeInfo **ppTInfo)
3640 {
3641     int i;
3642
3643     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3644     ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3645
3646     TRACE("(%p)->(index=%d)\n", This, index);
3647
3648     if (!ppTInfo) return E_INVALIDARG;
3649
3650     /* search element n in list */
3651     for(i=0; i < index; i++)
3652     {
3653       pTypeInfo = pTypeInfo->next;
3654       if (!pTypeInfo)
3655       {
3656         TRACE("-- element not found\n");
3657         return TYPE_E_ELEMENTNOTFOUND;
3658       }
3659     }
3660
3661     *ppTInfo = (ITypeInfo *) pTypeInfo;
3662
3663     ITypeInfo_AddRef(*ppTInfo);
3664     TRACE("-- found (%p)\n",*ppTInfo);
3665     return S_OK;
3666 }
3667
3668
3669 /* ITypeLibs::GetTypeInfoType
3670  *
3671  * Retrieves the type of a type description.
3672  */
3673 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3674     ITypeLib2 *iface,
3675     UINT index,
3676     TYPEKIND *pTKind)
3677 {
3678     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3679     int i;
3680     ITypeInfoImpl *pTInfo = This->pTypeInfo;
3681     
3682     if ((ITypeLib2_fnGetTypeInfoCount(iface) < index + 1) || (index < 0))
3683          return TYPE_E_ELEMENTNOTFOUND;
3684
3685     TRACE("(%p) index %d\n", This, index);
3686
3687     if(!pTKind) return E_INVALIDARG;
3688
3689     /* search element n in list */
3690     for(i=0; i < index; i++)
3691     {
3692       if(!pTInfo)
3693       {
3694         TRACE("-- element not found\n");
3695         return TYPE_E_ELEMENTNOTFOUND;
3696       }
3697       pTInfo = pTInfo->next;
3698     }
3699
3700     *pTKind = pTInfo->TypeAttr.typekind;
3701     TRACE("-- found Type (%d)\n", *pTKind);
3702     return S_OK;
3703 }
3704
3705 /* ITypeLib::GetTypeInfoOfGuid
3706  *
3707  * Retrieves the type description that corresponds to the specified GUID.
3708  *
3709  */
3710 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3711     ITypeLib2 *iface,
3712     REFGUID guid,
3713     ITypeInfo **ppTInfo)
3714 {
3715     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3716     ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3717
3718     TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3719
3720     if (!pTypeInfo)
3721     {
3722         WARN("-- element not found\n");
3723         return TYPE_E_ELEMENTNOTFOUND;
3724     }
3725
3726     /* search linked list for guid */
3727     while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3728     {
3729       pTypeInfo = pTypeInfo->next;
3730
3731       if (!pTypeInfo)
3732       {
3733         /* end of list reached */
3734         WARN("-- element not found\n");
3735         return TYPE_E_ELEMENTNOTFOUND;
3736       }
3737     }
3738
3739     TRACE("-- found (%p, %s)\n",
3740           pTypeInfo,
3741           debugstr_w(pTypeInfo->Name));
3742
3743     *ppTInfo = (ITypeInfo*)pTypeInfo;
3744     ITypeInfo_AddRef(*ppTInfo);
3745     return S_OK;
3746 }
3747
3748 /* ITypeLib::GetLibAttr
3749  *
3750  * Retrieves the structure that contains the library's attributes.
3751  *
3752  */
3753 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3754         ITypeLib2 *iface,
3755         LPTLIBATTR *ppTLibAttr)
3756 {
3757     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3758     TRACE("(%p)\n",This);
3759     *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3760     memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3761     return S_OK;
3762 }
3763
3764 /* ITypeLib::GetTypeComp
3765  *
3766  * Enables a client compiler to bind to a library's types, variables,
3767  * constants, and global functions.
3768  *
3769  */
3770 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3771         ITypeLib2 *iface,
3772         ITypeComp **ppTComp)
3773 {
3774     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3775
3776     TRACE("(%p)->(%p)\n",This,ppTComp);
3777     *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3778     ITypeComp_AddRef(*ppTComp);
3779
3780     return S_OK;
3781 }
3782
3783 /* ITypeLib::GetDocumentation
3784  *
3785  * Retrieves the library's documentation string, the complete Help file name
3786  * and path, and the context identifier for the library Help topic in the Help
3787  * file.
3788  *
3789  * On a successful return all non-null BSTR pointers will have been set,
3790  * possibly to NULL.
3791  */
3792 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3793     ITypeLib2 *iface,
3794     INT index,
3795     BSTR *pBstrName,
3796     BSTR *pBstrDocString,
3797     DWORD *pdwHelpContext,
3798     BSTR *pBstrHelpFile)
3799 {
3800     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3801
3802     HRESULT result = E_INVALIDARG;
3803
3804     ITypeInfo *pTInfo;
3805
3806
3807     TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3808         This, index,
3809         pBstrName, pBstrDocString,
3810         pdwHelpContext, pBstrHelpFile);
3811
3812     if(index<0)
3813     {
3814         /* documentation for the typelib */
3815         if(pBstrName)
3816         {
3817             if (This->Name)
3818             {
3819                 if(!(*pBstrName = SysAllocString(This->Name)))
3820                     goto memerr1;
3821             }
3822             else
3823                 *pBstrName = NULL;
3824         }
3825         if(pBstrDocString)
3826         {
3827             if (This->DocString)
3828             {
3829                 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3830                     goto memerr2;
3831             }
3832             else if (This->Name)
3833             {
3834                 if(!(*pBstrDocString = SysAllocString(This->Name)))
3835                     goto memerr2;
3836             }
3837             else
3838                 *pBstrDocString = NULL;
3839         }
3840         if(pdwHelpContext)
3841         {
3842             *pdwHelpContext = This->dwHelpContext;
3843         }
3844         if(pBstrHelpFile)
3845         {
3846             if (This->HelpFile)
3847             {
3848                 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3849                     goto memerr3;
3850             }
3851             else
3852                 *pBstrHelpFile = NULL;
3853         }
3854
3855         result = S_OK;
3856     }
3857     else
3858     {
3859         /* for a typeinfo */
3860         result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3861
3862         if(SUCCEEDED(result))
3863         {
3864             result = ITypeInfo_GetDocumentation(pTInfo,
3865                                           MEMBERID_NIL,
3866                                           pBstrName,
3867                                           pBstrDocString,
3868                                           pdwHelpContext, pBstrHelpFile);
3869
3870             ITypeInfo_Release(pTInfo);
3871         }
3872     }
3873     return result;
3874 memerr3:
3875     if (pBstrDocString) SysFreeString (*pBstrDocString);
3876 memerr2:
3877     if (pBstrName) SysFreeString (*pBstrName);
3878 memerr1:
3879     return STG_E_INSUFFICIENTMEMORY;
3880 }
3881
3882 /* ITypeLib::IsName
3883  *
3884  * Indicates whether a passed-in string contains the name of a type or member
3885  * described in the library.
3886  *
3887  */
3888 static HRESULT WINAPI ITypeLib2_fnIsName(
3889         ITypeLib2 *iface,
3890         LPOLESTR szNameBuf,
3891         ULONG lHashVal,
3892         BOOL *pfName)
3893 {
3894     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3895     ITypeInfoImpl *pTInfo;
3896     TLBFuncDesc *pFInfo;
3897     TLBVarDesc *pVInfo;
3898     int i;
3899     UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3900
3901     TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3902           pfName);
3903
3904     *pfName=TRUE;
3905     for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3906         if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3907         for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3908             if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3909             for(i=0;i<pFInfo->funcdesc.cParams;i++)
3910                 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3911                     goto ITypeLib2_fnIsName_exit;
3912         }
3913         for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3914             if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3915
3916     }
3917     *pfName=FALSE;
3918
3919 ITypeLib2_fnIsName_exit:
3920     TRACE("(%p)slow! search for %s: %s found!\n", This,
3921           debugstr_w(szNameBuf), *pfName?"NOT":"");
3922
3923     return S_OK;
3924 }
3925
3926 /* ITypeLib::FindName
3927  *
3928  * Finds occurrences of a type description in a type library. This may be used
3929  * to quickly verify that a name exists in a type library.
3930  *
3931  */
3932 static HRESULT WINAPI ITypeLib2_fnFindName(
3933         ITypeLib2 *iface,
3934         LPOLESTR szNameBuf,
3935         ULONG lHashVal,
3936         ITypeInfo **ppTInfo,
3937         MEMBERID *rgMemId,
3938         UINT16 *pcFound)
3939 {
3940     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3941     ITypeInfoImpl *pTInfo;
3942     TLBFuncDesc *pFInfo;
3943     TLBVarDesc *pVInfo;
3944     int i,j = 0;
3945     UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3946
3947     for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3948         if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3949         for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3950             if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3951             for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3952                 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3953                     goto ITypeLib2_fnFindName_exit;
3954             }
3955         }
3956         for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3957             if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3958         continue;
3959 ITypeLib2_fnFindName_exit:
3960         ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3961         ppTInfo[j]=(LPTYPEINFO)pTInfo;
3962         j++;
3963     }
3964     TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3965           This, *pcFound, debugstr_w(szNameBuf), j);
3966
3967     *pcFound=j;
3968
3969     return S_OK;
3970 }
3971
3972 /* ITypeLib::ReleaseTLibAttr
3973  *
3974  * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3975  *
3976  */
3977 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3978         ITypeLib2 *iface,
3979         TLIBATTR *pTLibAttr)
3980 {
3981     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3982     TRACE("freeing (%p)\n",This);
3983     HeapFree(GetProcessHeap(),0,pTLibAttr);
3984
3985 }
3986
3987 /* ITypeLib2::GetCustData
3988  *
3989  * gets the custom data
3990  */
3991 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3992         ITypeLib2 * iface,
3993         REFGUID guid,
3994         VARIANT *pVarVal)
3995 {
3996     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3997     TLBCustData *pCData;
3998
3999     for(pCData=This->pCustData; pCData; pCData = pCData->next)
4000     {
4001       if( IsEqualIID(guid, &pCData->guid)) break;
4002     }
4003
4004     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4005
4006     if(pCData)
4007     {
4008         VariantInit( pVarVal);
4009         VariantCopy( pVarVal, &pCData->data);
4010         return S_OK;
4011     }
4012     return E_INVALIDARG;  /* FIXME: correct? */
4013 }
4014
4015 /* ITypeLib2::GetLibStatistics
4016  *
4017  * Returns statistics about a type library that are required for efficient
4018  * sizing of hash tables.
4019  *
4020  */
4021 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4022         ITypeLib2 * iface,
4023         ULONG *pcUniqueNames,
4024         ULONG *pcchUniqueNames)
4025 {
4026     ITypeLibImpl *This = (ITypeLibImpl *)iface;
4027
4028     FIXME("(%p): stub!\n", This);
4029
4030     if(pcUniqueNames) *pcUniqueNames=1;
4031     if(pcchUniqueNames) *pcchUniqueNames=1;
4032     return S_OK;
4033 }
4034
4035 /* ITypeLib2::GetDocumentation2
4036  *
4037  * Retrieves the library's documentation string, the complete Help file name
4038  * and path, the localization context to use, and the context ID for the
4039  * library Help topic in the Help file.
4040  *
4041  */
4042 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4043         ITypeLib2 * iface,
4044         INT index,
4045         LCID lcid,
4046         BSTR *pbstrHelpString,
4047         DWORD *pdwHelpStringContext,
4048         BSTR *pbstrHelpStringDll)
4049 {
4050     ITypeLibImpl *This = (ITypeLibImpl *)iface;
4051     HRESULT result;
4052     ITypeInfo *pTInfo;
4053
4054     FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4055
4056     /* the help string should be obtained from the helpstringdll,
4057      * using the _DLLGetDocumentation function, based on the supplied
4058      * lcid. Nice to do sometime...
4059      */
4060     if(index<0)
4061     {
4062       /* documentation for the typelib */
4063       if(pbstrHelpString)
4064         *pbstrHelpString=SysAllocString(This->DocString);
4065       if(pdwHelpStringContext)
4066         *pdwHelpStringContext=This->dwHelpContext;
4067       if(pbstrHelpStringDll)
4068         *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4069
4070       result = S_OK;
4071     }
4072     else
4073     {
4074       /* for a typeinfo */
4075       result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4076
4077       if(SUCCEEDED(result))
4078       {
4079         ITypeInfo2 * pTInfo2;
4080         result = ITypeInfo_QueryInterface(pTInfo,
4081                                           &IID_ITypeInfo2,
4082                                           (LPVOID*) &pTInfo2);
4083
4084         if(SUCCEEDED(result))
4085         {
4086           result = ITypeInfo2_GetDocumentation2(pTInfo2,
4087                                            MEMBERID_NIL,
4088                                            lcid,
4089                                            pbstrHelpString,
4090                                            pdwHelpStringContext,
4091                                            pbstrHelpStringDll);
4092
4093           ITypeInfo2_Release(pTInfo2);
4094         }
4095
4096         ITypeInfo_Release(pTInfo);
4097       }
4098     }
4099     return result;
4100 }
4101
4102 /* ITypeLib2::GetAllCustData
4103  *
4104  * Gets all custom data items for the library.
4105  *
4106  */
4107 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4108         ITypeLib2 * iface,
4109         CUSTDATA *pCustData)
4110 {
4111     ITypeLibImpl *This = (ITypeLibImpl *)iface;
4112     TLBCustData *pCData;
4113     int i;
4114     TRACE("(%p) returning %d items\n", This, This->ctCustData);
4115     pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4116     if(pCustData->prgCustData ){
4117         pCustData->cCustData=This->ctCustData;
4118         for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4119             pCustData->prgCustData[i].guid=pCData->guid;
4120             VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4121         }
4122     }else{
4123         ERR(" OUT OF MEMORY!\n");
4124         return E_OUTOFMEMORY;
4125     }
4126     return S_OK;
4127 }
4128
4129 static const ITypeLib2Vtbl tlbvt = {
4130     ITypeLib2_fnQueryInterface,
4131     ITypeLib2_fnAddRef,
4132     ITypeLib2_fnRelease,
4133     ITypeLib2_fnGetTypeInfoCount,
4134     ITypeLib2_fnGetTypeInfo,
4135     ITypeLib2_fnGetTypeInfoType,
4136     ITypeLib2_fnGetTypeInfoOfGuid,
4137     ITypeLib2_fnGetLibAttr,
4138     ITypeLib2_fnGetTypeComp,
4139     ITypeLib2_fnGetDocumentation,
4140     ITypeLib2_fnIsName,
4141     ITypeLib2_fnFindName,
4142     ITypeLib2_fnReleaseTLibAttr,
4143
4144     ITypeLib2_fnGetCustData,
4145     ITypeLib2_fnGetLibStatistics,
4146     ITypeLib2_fnGetDocumentation2,
4147     ITypeLib2_fnGetAllCustData
4148  };
4149
4150
4151 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4152 {
4153     ITypeLibImpl *This = impl_from_ITypeComp(iface);
4154
4155     return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4156 }
4157
4158 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4159 {
4160     ITypeLibImpl *This = impl_from_ITypeComp(iface);
4161
4162     return ITypeLib2_AddRef((ITypeLib2 *)This);
4163 }
4164
4165 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4166 {
4167     ITypeLibImpl *This = impl_from_ITypeComp(iface);
4168
4169     return ITypeLib2_Release((ITypeLib2 *)This);
4170 }
4171
4172 static HRESULT WINAPI ITypeLibComp_fnBind(
4173     ITypeComp * iface,
4174     OLECHAR * szName,
4175     ULONG lHash,
4176     WORD wFlags,
4177     ITypeInfo ** ppTInfo,
4178     DESCKIND * pDescKind,
4179     BINDPTR * pBindPtr)
4180 {
4181     ITypeLibImpl *This = impl_from_ITypeComp(iface);
4182     ITypeInfoImpl *pTypeInfo;
4183
4184     TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4185
4186     *pDescKind = DESCKIND_NONE;
4187     pBindPtr->lptcomp = NULL;
4188     *ppTInfo = NULL;
4189
4190     for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4191     {
4192         TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4193
4194         /* FIXME: check wFlags here? */
4195         /* FIXME: we should use a hash table to look this info up using lHash
4196          * instead of an O(n) search */
4197         if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4198             (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4199         {
4200             if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4201             {
4202                 *pDescKind = DESCKIND_TYPECOMP;
4203                 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4204                 ITypeComp_AddRef(pBindPtr->lptcomp);
4205                 TRACE("module or enum: %s\n", debugstr_w(szName));
4206                 return S_OK;
4207             }
4208         }
4209
4210         if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4211             (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4212         {
4213             ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4214             HRESULT hr;
4215
4216             hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4217             if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4218             {
4219                 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4220                 return S_OK;
4221             }
4222         }
4223
4224         if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4225             (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4226         {
4227             ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4228             HRESULT hr;
4229             ITypeInfo *subtypeinfo;
4230             BINDPTR subbindptr;
4231             DESCKIND subdesckind;
4232
4233             hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4234                 &subtypeinfo, &subdesckind, &subbindptr);
4235             if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4236             {
4237                 TYPEDESC tdesc_appobject =
4238                 {
4239                     {
4240                         (TYPEDESC *)pTypeInfo->hreftype
4241                     },
4242                     VT_USERDEFINED
4243                 };
4244                 const VARDESC vardesc_appobject =
4245                 {
4246                     -2,         /* memid */
4247                     NULL,       /* lpstrSchema */
4248                     {
4249                         0       /* oInst */
4250                     },
4251                     {
4252                                 /* ELEMDESC */
4253                         {
4254                                 /* TYPEDESC */
4255                                 {
4256                                     &tdesc_appobject
4257                                 },
4258                                 VT_PTR
4259                         },
4260                     },
4261                     0,          /* wVarFlags */
4262                     VAR_STATIC  /* varkind */
4263                 };
4264
4265                 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4266
4267                 /* cleanup things filled in by Bind call so we can put our
4268                  * application object data in there instead */
4269                 switch (subdesckind)
4270                 {
4271                 case DESCKIND_FUNCDESC:
4272                     ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4273                     break;
4274                 case DESCKIND_VARDESC:
4275                     ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4276                     break;
4277                 default:
4278                     break;
4279                 }
4280                 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4281
4282                 if (pTypeInfo->hreftype == -1)
4283                     FIXME("no hreftype for interface %p\n", pTypeInfo);
4284
4285                 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4286                 if (FAILED(hr))
4287                     return hr;
4288
4289                 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4290                 *ppTInfo = (ITypeInfo *)pTypeInfo;
4291                 ITypeInfo_AddRef(*ppTInfo);
4292                 return S_OK;
4293             }
4294         }
4295     }
4296
4297     TRACE("name not found %s\n", debugstr_w(szName));
4298     return S_OK;
4299 }
4300
4301 static HRESULT WINAPI ITypeLibComp_fnBindType(
4302     ITypeComp * iface,
4303     OLECHAR * szName,
4304     ULONG lHash,
4305     ITypeInfo ** ppTInfo,
4306     ITypeComp ** ppTComp)
4307 {
4308     FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4309     return E_NOTIMPL;
4310 }
4311
4312 static const ITypeCompVtbl tlbtcvt =
4313 {
4314
4315     ITypeLibComp_fnQueryInterface,
4316     ITypeLibComp_fnAddRef,
4317     ITypeLibComp_fnRelease,
4318
4319     ITypeLibComp_fnBind,
4320     ITypeLibComp_fnBindType
4321 };
4322
4323 /*================== ITypeInfo(2) Methods ===================================*/
4324 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4325 {
4326     ITypeInfoImpl * pTypeInfoImpl;
4327
4328     pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4329     if (pTypeInfoImpl)
4330     {
4331       pTypeInfoImpl->lpVtbl = &tinfvt;
4332       pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4333       pTypeInfoImpl->ref=1;
4334       pTypeInfoImpl->hreftype = -1;
4335       pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4336       pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4337     }
4338     TRACE("(%p)\n", pTypeInfoImpl);
4339     return (ITypeInfo2*) pTypeInfoImpl;
4340 }
4341
4342 /* ITypeInfo::QueryInterface
4343  */
4344 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4345         ITypeInfo2 *iface,
4346         REFIID riid,
4347         VOID **ppvObject)
4348 {
4349     ITypeLibImpl *This = (ITypeLibImpl *)iface;
4350
4351     TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4352
4353     *ppvObject=NULL;
4354     if(IsEqualIID(riid, &IID_IUnknown) ||
4355             IsEqualIID(riid,&IID_ITypeInfo)||
4356             IsEqualIID(riid,&IID_ITypeInfo2))
4357         *ppvObject = This;
4358
4359     if(*ppvObject){
4360         ITypeInfo_AddRef(iface);
4361         TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4362         return S_OK;
4363     }
4364     TRACE("-- Interface: E_NOINTERFACE\n");
4365     return E_NOINTERFACE;
4366 }
4367
4368 /* ITypeInfo::AddRef
4369  */
4370 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4371 {
4372     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4373     ULONG ref = InterlockedIncrement(&This->ref);
4374
4375     ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4376
4377     TRACE("(%p)->ref is %u\n",This, ref);
4378     return ref;
4379 }
4380
4381 /* ITypeInfo::Release
4382  */
4383 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4384 {
4385     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4386     ULONG ref = InterlockedDecrement(&This->ref);
4387
4388     TRACE("(%p)->(%u)\n",This, ref);
4389
4390     if (ref)   {
4391       /* We don't release ITypeLib when ref=0 because
4392          it means that function is called by ITypeLib2_Release */
4393       ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4394     } else   {
4395       TLBFuncDesc *pFInfo, *pFInfoNext;
4396       TLBVarDesc *pVInfo, *pVInfoNext;
4397       TLBImplType *pImpl, *pImplNext;
4398       TLBRefType *pRefType,*pRefTypeNext;
4399       TLBCustData *pCustData, *pCustDataNext;
4400
4401       TRACE("destroying ITypeInfo(%p)\n",This);
4402
4403       if (This->no_free_data)
4404           goto finish_free;
4405
4406       if (This->Name)
4407       {
4408           SysFreeString(This->Name);
4409           This->Name = 0;
4410       }
4411
4412       if (This->DocString)
4413       {
4414           SysFreeString(This->DocString);
4415           This->DocString = 0;
4416       }
4417
4418       if (This->DllName)
4419       {
4420           SysFreeString(This->DllName);
4421           This->DllName = 0;
4422       }
4423
4424       for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4425       {
4426           UINT i;
4427           for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4428           {
4429               ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4430               if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4431               {
4432                   VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4433                   TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4434               }
4435               SysFreeString(pFInfo->pParamDesc[i].Name);
4436           }
4437           TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4438           TLB_Free(pFInfo->pParamDesc);
4439           for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4440           {
4441               VariantClear(&pCustData->data);
4442
4443               pCustDataNext = pCustData->next;
4444               TLB_Free(pCustData);
4445           }
4446           if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1) 
4447               SysFreeString(pFInfo->Entry);
4448           SysFreeString(pFInfo->HelpString);
4449           SysFreeString(pFInfo->Name);
4450
4451           pFInfoNext = pFInfo->next;
4452           TLB_Free(pFInfo);
4453       }
4454       for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4455       {
4456           if (pVInfo->vardesc.varkind == VAR_CONST)
4457           {
4458               VariantClear(pVInfo->vardesc.u.lpvarValue);
4459               TLB_Free(pVInfo->vardesc.u.lpvarValue);
4460           }
4461           SysFreeString(pVInfo->Name);
4462           pVInfoNext = pVInfo->next;
4463           TLB_Free(pVInfo);
4464       }
4465       for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4466       {
4467           for (pCustData = pImpl->pCustData; pCustData; pCustData = pCustDataNext)
4468           {
4469               VariantClear(&pCustData->data);
4470
4471               pCustDataNext = pCustData->next;
4472               TLB_Free(pCustData);
4473           }
4474           pImplNext = pImpl->next;
4475           TLB_Free(pImpl);
4476       }
4477       for(pRefType = This->reflist; pRefType; pRefType = pRefTypeNext)
4478       {
4479           pRefTypeNext = pRefType->next;
4480           TLB_Free(pRefType);
4481       }
4482       TLB_Free(This->pCustData);
4483
4484 finish_free:
4485       if (This->next)
4486       {
4487         ITypeInfo_Release((ITypeInfo*)This->next);
4488       }
4489
4490       HeapFree(GetProcessHeap(),0,This);
4491       return 0;
4492     }
4493     return ref;
4494 }
4495
4496 /* ITypeInfo::GetTypeAttr
4497  *
4498  * Retrieves a TYPEATTR structure that contains the attributes of the type
4499  * description.
4500  *
4501  */
4502 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4503         LPTYPEATTR  *ppTypeAttr)
4504 {
4505     const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4506     SIZE_T size;
4507
4508     TRACE("(%p)\n",This);
4509
4510     size = sizeof(**ppTypeAttr);
4511     if (This->TypeAttr.typekind == TKIND_ALIAS)
4512         size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4513
4514     *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4515     if (!*ppTypeAttr)
4516         return E_OUTOFMEMORY;
4517
4518     memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4519
4520     if (This->TypeAttr.typekind == TKIND_ALIAS)
4521         TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4522             &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4523
4524     if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4525         (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4526                                                                  funcs */
4527         (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4528         (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4529     }
4530     return S_OK;
4531 }
4532
4533 /* ITypeInfo::GetTypeComp
4534  *
4535  * Retrieves the ITypeComp interface for the type description, which enables a
4536  * client compiler to bind to the type description's members.
4537  *
4538  */
4539 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4540         ITypeComp  * *ppTComp)
4541 {
4542     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4543
4544     TRACE("(%p)->(%p)\n", This, ppTComp);
4545
4546     *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4547     ITypeComp_AddRef(*ppTComp);
4548     return S_OK;
4549 }
4550
4551 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4552 {
4553     SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4554     if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4555         size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4556     return size;
4557 }
4558
4559 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4560 {
4561     memcpy(dest, src, sizeof(ELEMDESC));
4562     *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4563     if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4564     {
4565         const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4566         PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4567         *buffer += sizeof(PARAMDESCEX);
4568         memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4569         VariantInit(&pparamdescex_dest->varDefaultValue);
4570         return VariantCopy(&pparamdescex_dest->varDefaultValue, 
4571                            (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4572     }
4573     else
4574         dest->u.paramdesc.pparamdescex = NULL;
4575     return S_OK;
4576 }
4577
4578 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4579 {
4580     if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4581         VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4582 }
4583
4584 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4585 {
4586     FUNCDESC *dest;
4587     char *buffer;
4588     SIZE_T size = sizeof(*src);
4589     SHORT i;
4590     HRESULT hr;
4591
4592     size += sizeof(*src->lprgscode) * src->cScodes;
4593     size += TLB_SizeElemDesc(&src->elemdescFunc);
4594     for (i = 0; i < src->cParams; i++)
4595     {
4596         size += sizeof(ELEMDESC);
4597         size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4598     }
4599
4600     dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4601     if (!dest) return E_OUTOFMEMORY;
4602
4603     memcpy(dest, src, sizeof(FUNCDESC));
4604     buffer = (char *)(dest + 1);
4605
4606     dest->lprgscode = (SCODE *)buffer;
4607     memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4608     buffer += sizeof(*src->lprgscode) * src->cScodes;
4609
4610     hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4611     if (FAILED(hr))
4612     {
4613         SysFreeString((BSTR)dest);
4614         return hr;
4615     }
4616
4617     dest->lprgelemdescParam = (ELEMDESC *)buffer;
4618     buffer += sizeof(ELEMDESC) * src->cParams;
4619     for (i = 0; i < src->cParams; i++)
4620     {
4621         hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4622         if (FAILED(hr))
4623             break;
4624     }
4625     if (FAILED(hr))
4626     {
4627         /* undo the above actions */
4628         for (i = i - 1; i >= 0; i--)
4629             TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4630         TLB_FreeElemDesc(&dest->elemdescFunc);
4631         SysFreeString((BSTR)dest);
4632         return hr;
4633     }
4634
4635     /* special treatment for dispinterfaces: this makes functions appear
4636      * to return their [retval] value when it is really returning an
4637      * HRESULT */
4638     if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4639     {
4640         if (dest->cParams &&
4641             (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4642         {
4643             ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4644             if (elemdesc->tdesc.vt != VT_PTR)
4645             {
4646                 ERR("elemdesc should have started with VT_PTR instead of:\n");
4647                 if (ERR_ON(ole))
4648                     dump_ELEMDESC(elemdesc);
4649                 return E_UNEXPECTED;
4650             }
4651
4652             /* copy last parameter to the return value. we are using a flat
4653              * buffer so there is no danger of leaking memory in
4654              * elemdescFunc */
4655             dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4656
4657             /* remove the last parameter */
4658             dest->cParams--;
4659         }
4660         else
4661             /* otherwise this function is made to appear to have no return
4662              * value */
4663             dest->elemdescFunc.tdesc.vt = VT_VOID;
4664
4665     }
4666
4667     *dest_ptr = dest;
4668     return S_OK;
4669 }
4670
4671 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4672 {
4673     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4674     const TLBFuncDesc *pFDesc;
4675     int i;
4676
4677     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4678         ;
4679
4680     if (pFDesc)
4681     {
4682         *ppFuncDesc = &pFDesc->funcdesc;
4683         return S_OK;
4684     }
4685
4686     return E_INVALIDARG;
4687 }
4688
4689 /* internal function to make the inherited interfaces' methods appear
4690  * part of the interface */
4691 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
4692     UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs)
4693 {
4694     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4695     HRESULT hr;
4696     UINT i;
4697     UINT implemented_funcs = 0;
4698
4699     if (funcs)
4700         *funcs = 0;
4701
4702     for (i = 0; i < This->TypeAttr.cImplTypes; i++)
4703     {
4704         HREFTYPE href;
4705         ITypeInfo *pSubTypeInfo;
4706         UINT sub_funcs;
4707
4708         hr = ITypeInfo_GetRefTypeOfImplType(iface, i, &href);
4709         if (FAILED(hr))
4710             return hr;
4711         hr = ITypeInfo_GetRefTypeInfo(iface, href, &pSubTypeInfo);
4712         if (FAILED(hr))
4713             return hr;
4714
4715         hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
4716                                                        index,
4717                                                        ppFuncDesc,
4718                                                        &sub_funcs);
4719         implemented_funcs += sub_funcs;
4720         ITypeInfo_Release(pSubTypeInfo);
4721         if (SUCCEEDED(hr))
4722             return hr;
4723     }
4724
4725     if (funcs)
4726         *funcs = implemented_funcs + This->TypeAttr.cFuncs;
4727     
4728     if (index < implemented_funcs)
4729         return E_INVALIDARG;
4730     return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
4731                                              ppFuncDesc);
4732 }
4733
4734 /* ITypeInfo::GetFuncDesc
4735  *
4736  * Retrieves the FUNCDESC structure that contains information about a
4737  * specified function.
4738  *
4739  */
4740 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4741         LPFUNCDESC  *ppFuncDesc)
4742 {
4743     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4744     const FUNCDESC *internal_funcdesc;
4745     HRESULT hr;
4746
4747     TRACE("(%p) index %d\n", This, index);
4748
4749     if ((This->TypeAttr.typekind == TKIND_DISPATCH) &&
4750         (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4751         hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
4752                                                        &internal_funcdesc, NULL);
4753     else
4754         hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
4755                                                &internal_funcdesc);
4756     if (FAILED(hr))
4757     {
4758         WARN("description for function %d not found\n", index);
4759         return hr;
4760     }
4761
4762     return TLB_AllocAndInitFuncDesc(
4763         internal_funcdesc,
4764         ppFuncDesc,
4765         This->TypeAttr.typekind == TKIND_DISPATCH);
4766 }
4767
4768 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4769 {
4770     VARDESC *dest;
4771     char *buffer;
4772     SIZE_T size = sizeof(*src);
4773     HRESULT hr;
4774
4775     if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4776     if (src->varkind == VAR_CONST)
4777         size += sizeof(VARIANT);
4778     size += TLB_SizeElemDesc(&src->elemdescVar);
4779
4780     dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4781     if (!dest) return E_OUTOFMEMORY;
4782
4783     *dest = *src;
4784     buffer = (char *)(dest + 1);
4785     if (src->lpstrSchema)
4786     {
4787         int len;
4788         dest->lpstrSchema = (LPOLESTR)buffer;
4789         len = strlenW(src->lpstrSchema);
4790         memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4791         buffer += (len + 1) * sizeof(WCHAR);
4792     }
4793
4794     if (src->varkind == VAR_CONST)
4795     {
4796         HRESULT hr;
4797
4798         dest->u.lpvarValue = (VARIANT *)buffer;
4799         *dest->u.lpvarValue = *src->u.lpvarValue;
4800         buffer += sizeof(VARIANT);
4801         VariantInit(dest->u.lpvarValue);
4802         hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4803         if (FAILED(hr))
4804         {
4805             SysFreeString((BSTR)dest_ptr);
4806             return hr;
4807         }
4808     }
4809     hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4810     if (FAILED(hr))
4811     {
4812         if (src->varkind == VAR_CONST)
4813             VariantClear(dest->u.lpvarValue);
4814         SysFreeString((BSTR)dest);
4815         return hr;
4816     }
4817     *dest_ptr = dest;
4818     return S_OK;
4819 }
4820
4821 /* ITypeInfo::GetVarDesc
4822  *
4823  * Retrieves a VARDESC structure that describes the specified variable.
4824  *
4825  */
4826 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4827         LPVARDESC  *ppVarDesc)
4828 {
4829     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4830     int i;
4831     const TLBVarDesc *pVDesc;
4832
4833     TRACE("(%p) index %d\n", This, index);
4834
4835     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4836         ;
4837
4838     if (pVDesc)
4839         return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4840
4841     return E_INVALIDARG;
4842 }
4843
4844 /* ITypeInfo_GetNames
4845  *
4846  * Retrieves the variable with the specified member ID (or the name of the
4847  * property or method and its parameters) that correspond to the specified
4848  * function ID.
4849  */
4850 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4851         BSTR  *rgBstrNames, UINT cMaxNames, UINT  *pcNames)
4852 {
4853     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4854     const TLBFuncDesc *pFDesc;
4855     const TLBVarDesc *pVDesc;
4856     int i;
4857     TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
4858     for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4859     if(pFDesc)
4860     {
4861       /* function found, now return function and parameter names */
4862       for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4863       {
4864         if(!i)
4865           *rgBstrNames=SysAllocString(pFDesc->Name);
4866         else
4867           rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4868       }
4869       *pcNames=i;
4870     }
4871     else
4872     {
4873       for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4874       if(pVDesc)
4875       {
4876         *rgBstrNames=SysAllocString(pVDesc->Name);
4877         *pcNames=1;
4878       }
4879       else
4880       {
4881         if(This->TypeAttr.cImplTypes &&
4882            (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4883           /* recursive search */
4884           ITypeInfo *pTInfo;
4885           HRESULT result;
4886           result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4887                                           &pTInfo);
4888           if(SUCCEEDED(result))
4889           {
4890             result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4891             ITypeInfo_Release(pTInfo);
4892             return result;
4893           }
4894           WARN("Could not search inherited interface!\n");
4895         }
4896         else
4897         {
4898           WARN("no names found\n");
4899         }
4900         *pcNames=0;
4901         return TYPE_E_ELEMENTNOTFOUND;
4902       }
4903     }
4904     return S_OK;
4905 }
4906
4907
4908 /* ITypeInfo::GetRefTypeOfImplType
4909  *
4910  * If a type description describes a COM class, it retrieves the type
4911  * description of the implemented interface types. For an interface,
4912  * GetRefTypeOfImplType returns the type information for inherited interfaces,
4913  * if any exist.
4914  *
4915  */
4916 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4917         ITypeInfo2 *iface,
4918         UINT index,
4919         HREFTYPE  *pRefType)
4920 {
4921     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4922     int i;
4923     HRESULT hr = S_OK;
4924     const TLBImplType *pImpl = This->impltypelist;
4925
4926     TRACE("(%p) index %d\n", This, index);
4927     if (TRACE_ON(ole)) dump_TypeInfo(This);
4928
4929     if(index==(UINT)-1)
4930     {
4931       /* only valid on dual interfaces;
4932          retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4933       */
4934       if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4935
4936       if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4937           This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4938       {
4939         *pRefType = -1;
4940       }
4941       else
4942       {
4943         hr = TYPE_E_ELEMENTNOTFOUND;
4944       }
4945     }
4946     else
4947     {
4948       /* get element n from linked list */
4949       for(i=0; pImpl && i<index; i++)
4950       {
4951         pImpl = pImpl->next;
4952       }
4953
4954       if (pImpl)
4955         *pRefType = pImpl->hRef;
4956       else
4957         hr = TYPE_E_ELEMENTNOTFOUND;
4958     }
4959
4960     if(TRACE_ON(ole))
4961     {
4962         if(SUCCEEDED(hr))
4963             TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
4964         else
4965             TRACE("FAILURE -- hresult = 0x%08x\n", hr);
4966     }
4967
4968     return hr;
4969 }
4970
4971 /* ITypeInfo::GetImplTypeFlags
4972  *
4973  * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4974  * or base interface in a type description.
4975  */
4976 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4977         UINT index, INT  *pImplTypeFlags)
4978 {
4979     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4980     int i;
4981     TLBImplType *pImpl;
4982
4983     TRACE("(%p) index %d\n", This, index);
4984     for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4985         i++, pImpl=pImpl->next)
4986         ;
4987     if(i==index && pImpl){
4988         *pImplTypeFlags=pImpl->implflags;
4989         return S_OK;
4990     }
4991     *pImplTypeFlags=0;
4992     return TYPE_E_ELEMENTNOTFOUND;
4993 }
4994
4995 /* GetIDsOfNames
4996  * Maps between member names and member IDs, and parameter names and
4997  * parameter IDs.
4998  */
4999 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5000         LPOLESTR  *rgszNames, UINT cNames, MEMBERID  *pMemId)
5001 {
5002     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5003     const TLBFuncDesc *pFDesc;
5004     const TLBVarDesc *pVDesc;
5005     HRESULT ret=S_OK;
5006     int i;
5007
5008     TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5009             cNames);
5010
5011     /* init out parameters in case of failure */
5012     for (i = 0; i < cNames; i++)
5013         pMemId[i] = MEMBERID_NIL;
5014
5015     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5016         int j;
5017         if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5018             if(cNames) *pMemId=pFDesc->funcdesc.memid;
5019             for(i=1; i < cNames; i++){
5020                 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5021                     if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5022                             break;
5023                 if( j<pFDesc->funcdesc.cParams)
5024                     pMemId[i]=j;
5025                 else
5026                    ret=DISP_E_UNKNOWNNAME;
5027             };
5028             TRACE("-- 0x%08x\n", ret);
5029             return ret;
5030         }
5031     }
5032     for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5033         if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5034             if(cNames) *pMemId=pVDesc->vardesc.memid;
5035             return ret;
5036         }
5037     }
5038     /* not found, see if it can be found in an inherited interface */
5039     if(This->TypeAttr.cImplTypes) {
5040         /* recursive search */
5041         ITypeInfo *pTInfo;
5042         ret=ITypeInfo_GetRefTypeInfo(iface,
5043                 This->impltypelist->hRef, &pTInfo);
5044         if(SUCCEEDED(ret)){
5045             ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5046             ITypeInfo_Release(pTInfo);
5047             return ret;
5048         }
5049         WARN("Could not search inherited interface!\n");
5050     } else
5051         WARN("no names found\n");
5052     return DISP_E_UNKNOWNNAME;
5053 }
5054
5055 /* ITypeInfo::Invoke
5056  *
5057  * Invokes a method, or accesses a property of an object, that implements the
5058  * interface described by the type description.
5059  */
5060 DWORD
5061 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5062     DWORD res;
5063
5064     if (TRACE_ON(ole)) {
5065         int i;
5066         TRACE("Calling %p(",func);
5067         for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5068         TRACE(")\n");
5069     }
5070
5071     switch (callconv) {
5072     case CC_STDCALL:
5073
5074         switch (nrargs) {
5075         case 0:
5076                 res = func();
5077                 break;
5078         case 1:
5079                 res = func(args[0]);
5080                 break;
5081         case 2:
5082                 res = func(args[0],args[1]);
5083                 break;
5084         case 3:
5085                 res = func(args[0],args[1],args[2]);
5086                 break;
5087         case 4:
5088                 res = func(args[0],args[1],args[2],args[3]);
5089                 break;
5090         case 5:
5091                 res = func(args[0],args[1],args[2],args[3],args[4]);
5092                 break;
5093         case 6:
5094                 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5095                 break;
5096         case 7:
5097                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5098                 break;
5099         case 8:
5100                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5101                 break;
5102         case 9:
5103                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5104                 break;
5105         case 10:
5106                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5107                 break;
5108         case 11:
5109                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5110                 break;
5111         case 12:
5112                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]);
5113                 break;
5114         case 13:
5115                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]);
5116                 break;
5117         case 14:
5118                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]);
5119                 break;
5120         case 15:
5121                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14]);
5122                 break;
5123         case 16:
5124                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15]);
5125                 break;
5126         case 17:
5127                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16]);
5128                 break;
5129         case 18:
5130                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17]);
5131                 break;
5132         case 19:
5133                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18]);
5134                 break;
5135         case 20:
5136                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19]);
5137                 break;
5138         case 21:
5139                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20]);
5140                 break;
5141         case 22:
5142                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21]);
5143                 break;
5144         case 23:
5145                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22]);
5146                 break;
5147         default:
5148                 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5149                 res = -1;
5150                 break;
5151         }
5152         break;
5153     default:
5154         FIXME("unsupported calling convention %d\n",callconv);
5155         res = -1;
5156         break;
5157     }
5158     TRACE("returns %08x\n",res);
5159     return res;
5160 }
5161
5162 extern int _argsize(DWORD vt);
5163
5164 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5165 {
5166     HRESULT hr = S_OK;
5167     ITypeInfo *tinfo2 = NULL;
5168     TYPEATTR *tattr = NULL;
5169
5170     hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5171     if (hr)
5172     {
5173         ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5174             "hr = 0x%08x\n",
5175               tdesc->u.hreftype, hr);
5176         return hr;
5177     }
5178     hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5179     if (hr)
5180     {
5181         ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5182         ITypeInfo_Release(tinfo2);
5183         return hr;
5184     }
5185
5186     switch (tattr->typekind)
5187     {
5188     case TKIND_ENUM:
5189         *vt |= VT_I4;
5190         break;
5191
5192     case TKIND_ALIAS:
5193         tdesc = &tattr->tdescAlias;
5194         hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5195         break;
5196
5197     case TKIND_INTERFACE:
5198         if (IsEqualIID(&IID_IDispatch, &tattr->guid))
5199            *vt |= VT_DISPATCH;
5200         else
5201            *vt |= VT_UNKNOWN;
5202         break;
5203
5204     case TKIND_DISPATCH:
5205         *vt |= VT_DISPATCH;
5206         break;
5207
5208     case TKIND_COCLASS:
5209         *vt |= VT_UNKNOWN;
5210         break;
5211
5212     case TKIND_RECORD:
5213         FIXME("TKIND_RECORD unhandled.\n");
5214         hr = E_NOTIMPL;
5215         break;
5216
5217     case TKIND_UNION:
5218         FIXME("TKIND_UNION unhandled.\n");
5219         hr = E_NOTIMPL;
5220         break;
5221
5222     default:
5223         FIXME("TKIND %d unhandled.\n",tattr->typekind);
5224         hr = E_NOTIMPL;
5225         break;
5226     }
5227     ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5228     ITypeInfo_Release(tinfo2);
5229     return hr;
5230 }
5231
5232 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5233 {
5234     HRESULT hr = S_OK;
5235
5236     /* enforce only one level of pointer indirection */
5237     if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5238     {
5239         tdesc = tdesc->u.lptdesc;
5240
5241         /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5242          * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into 
5243          * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5244         if ((tdesc->vt == VT_USERDEFINED) ||
5245             ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5246         {
5247             VARTYPE vt_userdefined = 0;
5248             const TYPEDESC *tdesc_userdefined = tdesc;
5249             if (tdesc->vt == VT_PTR)
5250             {
5251                 vt_userdefined = VT_BYREF;
5252                 tdesc_userdefined = tdesc->u.lptdesc;
5253             }
5254             hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5255             if ((hr == S_OK) && 
5256                 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5257                  ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5258             {
5259                 *vt |= vt_userdefined;
5260                 return S_OK;
5261             }
5262         }
5263         *vt = VT_BYREF;
5264     }
5265
5266     switch (tdesc->vt)
5267     {
5268     case VT_HRESULT:
5269         *vt |= VT_ERROR;
5270         break;
5271     case VT_USERDEFINED:
5272         hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5273         break;
5274     case VT_VOID:
5275     case VT_CARRAY:
5276     case VT_PTR:
5277     case VT_LPSTR:
5278     case VT_LPWSTR:
5279         ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5280         hr = DISP_E_BADVARTYPE;
5281         break;
5282     case VT_SAFEARRAY:
5283         *vt |= VT_ARRAY;
5284         hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5285         break;
5286     default:
5287         *vt |= tdesc->vt;
5288         break;
5289     }
5290     return hr;
5291 }
5292
5293 /***********************************************************************
5294  *              DispCallFunc (OLEAUT32.@)
5295  *
5296  * Invokes a function of the specifed calling convention, passing the
5297  * specified arguments and returns the result.
5298  *
5299  * PARAMS
5300  *  pvInstance  [I] Optional pointer to the instance whose function to invoke.
5301  *  oVft        [I] The offset in the vtable. See notes.
5302  *  cc          [I] Calling convention of the function to call.
5303  *  vtReturn    [I] The return type of the function.
5304  *  cActuals    [I] Number of parameters.
5305  *  prgvt       [I] The types of the parameters to pass. This is used for sizing only.
5306  *  prgpvarg    [I] The arguments to pass.
5307  *  pvargResult [O] The return value of the function. Can be NULL.
5308  *
5309  * RETURNS
5310  *  Success: S_OK.
5311  *  Failure: HRESULT code.
5312  *
5313  * NOTES
5314  *  The HRESULT return value of this function is not affected by the return
5315  *  value of the user supplied function, which is returned in pvargResult.
5316  *
5317  *  If pvInstance is NULL then a non-object function is to be called and oVft
5318  *  is the address of the function to call.
5319  *
5320  * The cc parameter can be one of the following values:
5321  *|CC_FASTCALL
5322  *|CC_CDECL
5323  *|CC_PASCAL
5324  *|CC_STDCALL
5325  *|CC_FPFASTCALL
5326  *|CC_SYSCALL
5327  *|CC_MPWCDECL
5328  *|CC_MPWPASCAL
5329  *
5330  */
5331 HRESULT WINAPI
5332 DispCallFunc(
5333     void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5334     VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5335 {
5336     int i, argsize, argspos;
5337     DWORD *args;
5338     HRESULT hres;
5339
5340     TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5341         pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5342         pvargResult, V_VT(pvargResult));
5343
5344     argsize = 0;
5345     if (pvInstance)
5346         argsize++; /* for This pointer */
5347
5348     for (i=0;i<cActuals;i++)
5349     {
5350         TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5351         dump_Variant(prgpvarg[i]);
5352         argsize += _argsize(prgvt[i]);
5353     }
5354     args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5355
5356     argspos = 0;
5357     if (pvInstance)
5358     {
5359         args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5360         argspos++;
5361     }
5362
5363     for (i=0;i<cActuals;i++)
5364     {
5365         VARIANT *arg = prgpvarg[i];
5366         TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5367         if (prgvt[i] == VT_VARIANT)
5368             memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5369         else
5370             memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5371         argspos += _argsize(prgvt[i]);
5372     }
5373
5374     if (pvInstance)
5375     {
5376         FARPROC *vtable = *(FARPROC**)pvInstance;
5377         hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5378     }
5379     else
5380         /* if we aren't invoking an object then the function pointer is stored
5381          * in oVft */
5382         hres = _invoke((FARPROC)oVft, cc, argsize, args);
5383
5384     if (pvargResult && (vtReturn != VT_EMPTY))
5385     {
5386         TRACE("Method returned 0x%08x\n",hres);
5387         V_VT(pvargResult) = vtReturn;
5388         V_UI4(pvargResult) = hres;
5389     }
5390
5391     HeapFree(GetProcessHeap(),0,args);
5392     return S_OK;
5393 }
5394
5395 #define INVBUF_ELEMENT_SIZE \
5396     (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5397 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5398     ((VARIANTARG *)(buffer))
5399 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5400     ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5401 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5402     ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5403 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5404     ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5405
5406 static HRESULT WINAPI ITypeInfo_fnInvoke(
5407     ITypeInfo2 *iface,
5408     VOID  *pIUnk,
5409     MEMBERID memid,
5410     UINT16 wFlags,
5411     DISPPARAMS  *pDispParams,
5412     VARIANT  *pVarResult,
5413     EXCEPINFO  *pExcepInfo,
5414     UINT  *pArgErr)
5415 {
5416     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5417     int i;
5418     unsigned int var_index;
5419     TYPEKIND type_kind;
5420     HRESULT hres;
5421     const TLBFuncDesc *pFuncInfo;
5422
5423     TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5424       This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5425     );
5426
5427     if (!pDispParams)
5428     {
5429         ERR("NULL pDispParams not allowed\n");
5430         return E_INVALIDARG;
5431     }
5432
5433     dump_DispParms(pDispParams);
5434
5435     if (pDispParams->cNamedArgs > pDispParams->cArgs)
5436     {
5437         ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5438             pDispParams->cNamedArgs, pDispParams->cArgs);
5439         return E_INVALIDARG;
5440     }
5441
5442     /* we do this instead of using GetFuncDesc since it will return a fake
5443      * FUNCDESC for dispinterfaces and we want the real function description */
5444     for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5445         if ((memid == pFuncInfo->funcdesc.memid) &&
5446             (wFlags & pFuncInfo->funcdesc.invkind))
5447             break;
5448
5449     if (pFuncInfo) {
5450         const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5451
5452         if (TRACE_ON(ole))
5453         {
5454             TRACE("invoking:\n");
5455             dump_TLBFuncDescOne(pFuncInfo);
5456         }
5457         
5458         switch (func_desc->funckind) {
5459         case FUNC_PUREVIRTUAL:
5460         case FUNC_VIRTUAL: {
5461             void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5462             VARIANT varresult;
5463             VARIANT retval; /* pointer for storing byref retvals in */
5464             VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5465             VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5466             VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5467
5468             hres = S_OK;
5469             for (i = 0; i < func_desc->cParams; i++)
5470             {
5471                 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5472                 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5473                 if (FAILED(hres))
5474                     goto func_fail;
5475             }
5476
5477             TRACE("changing args\n");
5478             for (i = 0; i < func_desc->cParams; i++)
5479             {
5480                 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5481
5482                 if (wParamFlags & PARAMFLAG_FRETVAL)
5483                 {
5484                     /* note: this check is placed so that if the caller passes
5485                      * in a VARIANTARG for the retval we just ignore it, like
5486                      * native does */
5487                     if (i == func_desc->cParams - 1)
5488                     {
5489                         VARIANTARG *arg;
5490                         arg = prgpvarg[i] = &rgvarg[i];
5491                         memset(arg, 0, sizeof(*arg));
5492                         V_VT(arg) = rgvt[i];
5493                         memset(&retval, 0, sizeof(retval));
5494                         V_BYREF(arg) = &retval;
5495                     }
5496                     else
5497                     {
5498                         ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5499                         hres = E_UNEXPECTED;
5500                         break;
5501                     }
5502                 }
5503                 else if (i < pDispParams->cArgs)
5504                 {
5505                     VARIANTARG *src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5506                     dump_Variant(src_arg);
5507
5508                     if (rgvt[i] == VT_VARIANT)
5509                         hres = VariantCopy(&rgvarg[i], src_arg);
5510                     else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5511                     {
5512                         if (rgvt[i] == V_VT(src_arg))
5513                             V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5514                         else
5515                         {
5516                             VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5517                             hres = VariantCopy(&missing_arg[i], src_arg);
5518                             V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5519                         }
5520                         V_VT(&rgvarg[i]) = rgvt[i];
5521                     }
5522                     else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5523                     {
5524                         VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5525                         V_VT(&missing_arg[i]) = V_VT(src_arg);
5526                         hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5527                         V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5528                         V_VT(&rgvarg[i]) = rgvt[i];
5529                     }
5530                     else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5531                     {
5532                         V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5533                         V_VT(&rgvarg[i]) = rgvt[i];
5534                     }
5535                     else
5536                     {
5537                         /* FIXME: this doesn't work for VT_BYREF arguments if
5538                          * they are not the same type as in the paramdesc */
5539                         V_VT(&rgvarg[i]) = V_VT(src_arg);
5540                         hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5541                         V_VT(&rgvarg[i]) = rgvt[i];
5542                     }
5543
5544                     if (FAILED(hres))
5545                     {
5546                         ERR("failed to convert param %d to %s%s from %s%s\n", i,
5547                             debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5548                             debugstr_VT(src_arg), debugstr_VF(src_arg));
5549                         break;
5550                     }
5551                     prgpvarg[i] = &rgvarg[i];
5552                 }
5553                 else if (wParamFlags & PARAMFLAG_FOPT)
5554                 {
5555                     VARIANTARG *arg;
5556                     arg = prgpvarg[i] = &rgvarg[i];
5557                     if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5558                     {
5559                         hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5560                         if (FAILED(hres))
5561                             break;
5562                     }
5563                     else
5564                     {
5565                         VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5566                         V_VT(arg) = VT_VARIANT | VT_BYREF;
5567                         V_VARIANTREF(arg) = &missing_arg[i];
5568                         V_VT(V_VARIANTREF(arg)) = VT_ERROR;
5569                         V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND;
5570                     }
5571                 }
5572                 else
5573                 {
5574                     hres = DISP_E_BADPARAMCOUNT;
5575                     break;
5576                 }
5577             }
5578             if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5579             if (func_desc->cParamsOpt < 0)
5580             {
5581                 FIXME("Does not support safearray optional parameters\n");
5582                 hres = DISP_E_BADPARAMCOUNT;
5583                 goto func_fail; /* FIXME: we don't free changed types here */
5584             }
5585
5586             /* VT_VOID is a special case for return types, so it is not
5587              * handled in the general function */
5588             if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
5589                 V_VT(&varresult) = VT_EMPTY;
5590             else
5591             {
5592                 V_VT(&varresult) = 0;
5593                 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5594                 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5595             }
5596
5597             hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5598                                 V_VT(&varresult), func_desc->cParams, rgvt,
5599                                 prgpvarg, &varresult);
5600
5601             for (i = 0; i < func_desc->cParams; i++)
5602             {
5603                 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5604                 if (wParamFlags & PARAMFLAG_FRETVAL)
5605                 {
5606                     if (TRACE_ON(ole))
5607                     {
5608                         TRACE("[retval] value: ");
5609                         dump_Variant(prgpvarg[i]);
5610                     }
5611
5612                     if (pVarResult)
5613                     {
5614                         VariantInit(pVarResult);
5615                         /* deref return value */
5616                         hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5617                     }
5618
5619                     /* free data stored in varresult. Note that
5620                      * VariantClear doesn't do what we want because we are
5621                      * working with byref types. */
5622                     /* FIXME: clear safearrays, bstrs, records and
5623                      * variants here too */
5624                     if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5625                          (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5626                     {
5627                         if(*V_UNKNOWNREF(prgpvarg[i]))
5628                             IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5629                     }
5630                     break;
5631                 }
5632                 else if (i < pDispParams->cArgs)
5633                 {
5634                     if (wParamFlags & PARAMFLAG_FOUT)
5635                     {
5636                         VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5637
5638                         if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5639                             hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5640
5641                         if (FAILED(hres))
5642                         {
5643                             ERR("failed to convert param %d to vt %d\n", i,
5644                                 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5645                             break;
5646                         }
5647                     }
5648                     VariantClear(&rgvarg[i]);
5649                 }
5650                 else if (wParamFlags & PARAMFLAG_FOPT)
5651                 {
5652                     if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5653                         VariantClear(&rgvarg[i]);
5654                 }
5655             }
5656
5657             if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5658             {
5659                 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
5660                 hres = DISP_E_EXCEPTION;
5661                 if (pExcepInfo) pExcepInfo->scode = V_ERROR(&varresult);
5662             }
5663
5664 func_fail:
5665             HeapFree(GetProcessHeap(), 0, buffer);
5666             break;
5667         }
5668         case FUNC_DISPATCH:  {
5669            IDispatch *disp;
5670
5671            hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5672            if (SUCCEEDED(hres)) {
5673                FIXME("Calling Invoke in IDispatch iface. untested!\n");
5674                hres = IDispatch_Invoke(
5675                                      disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5676                                      pVarResult,pExcepInfo,pArgErr
5677                                      );
5678                if (FAILED(hres))
5679                    FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
5680                IDispatch_Release(disp);
5681            } else
5682                FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5683            break;
5684         }
5685         default:
5686             FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5687             hres = E_FAIL;
5688             break;
5689         }
5690
5691         TRACE("-- 0x%08x\n", hres);
5692         return hres;
5693
5694     } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5695         VARDESC *var_desc;
5696
5697         hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5698         if(FAILED(hres)) return hres;
5699         
5700         FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5701         dump_VARDESC(var_desc);
5702         ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5703         return E_NOTIMPL;
5704     }
5705
5706     /* not found, look for it in inherited interfaces */
5707     ITypeInfo2_GetTypeKind(iface, &type_kind);
5708     if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5709         HREFTYPE ref_type;
5710         if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5711             /* recursive search */
5712             ITypeInfo *pTInfo;
5713             hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5714             if(SUCCEEDED(hres)){
5715                 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5716                 ITypeInfo_Release(pTInfo);
5717                 return hres;
5718             }
5719             WARN("Could not search inherited interface!\n");
5720         }
5721     }
5722     ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
5723     return DISP_E_MEMBERNOTFOUND;
5724 }
5725
5726 /* ITypeInfo::GetDocumentation
5727  *
5728  * Retrieves the documentation string, the complete Help file name and path,
5729  * and the context ID for the Help topic for a specified type description.
5730  *
5731  * (Can be tested by the Visual Basic Editor in Word for instance.)
5732  */
5733 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5734         MEMBERID memid, BSTR  *pBstrName, BSTR  *pBstrDocString,
5735         DWORD  *pdwHelpContext, BSTR  *pBstrHelpFile)
5736 {
5737     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5738     const TLBFuncDesc *pFDesc;
5739     const TLBVarDesc *pVDesc;
5740     TRACE("(%p) memid %d Name(%p) DocString(%p)"
5741           " HelpContext(%p) HelpFile(%p)\n",
5742         This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5743     if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5744         if(pBstrName)
5745             *pBstrName=SysAllocString(This->Name);
5746         if(pBstrDocString)
5747             *pBstrDocString=SysAllocString(This->DocString);
5748         if(pdwHelpContext)
5749             *pdwHelpContext=This->dwHelpContext;
5750         if(pBstrHelpFile)
5751             *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5752         return S_OK;
5753     }else {/* for a member */
5754     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5755         if(pFDesc->funcdesc.memid==memid){
5756           if(pBstrName)
5757             *pBstrName = SysAllocString(pFDesc->Name);
5758           if(pBstrDocString)
5759             *pBstrDocString=SysAllocString(pFDesc->HelpString);
5760           if(pdwHelpContext)
5761             *pdwHelpContext=pFDesc->helpcontext;
5762           return S_OK;
5763         }
5764     for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5765         if(pVDesc->vardesc.memid==memid){
5766             if(pBstrName)
5767               *pBstrName = SysAllocString(pVDesc->Name);
5768             if(pBstrDocString)
5769               *pBstrDocString=SysAllocString(pVDesc->HelpString);
5770             if(pdwHelpContext)
5771               *pdwHelpContext=pVDesc->HelpContext;
5772             return S_OK;
5773         }
5774     }
5775
5776     if(This->TypeAttr.cImplTypes &&
5777        (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5778         /* recursive search */
5779         ITypeInfo *pTInfo;
5780         HRESULT result;
5781         result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5782                                         &pTInfo);
5783         if(SUCCEEDED(result)) {
5784             result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
5785                 pBstrDocString, pdwHelpContext, pBstrHelpFile);
5786             ITypeInfo_Release(pTInfo);
5787             return result;
5788         }
5789         WARN("Could not search inherited interface!\n");
5790     }
5791
5792     WARN("member %d not found\n", memid);
5793     return TYPE_E_ELEMENTNOTFOUND;
5794 }
5795
5796 /*  ITypeInfo::GetDllEntry
5797  *
5798  * Retrieves a description or specification of an entry point for a function
5799  * in a DLL.
5800  */
5801 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5802         INVOKEKIND invKind, BSTR  *pBstrDllName, BSTR  *pBstrName,
5803         WORD  *pwOrdinal)
5804 {
5805     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5806     const TLBFuncDesc *pFDesc;
5807
5808     TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5809
5810     if (pBstrDllName) *pBstrDllName = NULL;
5811     if (pBstrName) *pBstrName = NULL;
5812     if (pwOrdinal) *pwOrdinal = 0;
5813
5814     if (This->TypeAttr.typekind != TKIND_MODULE)
5815         return TYPE_E_BADMODULEKIND;
5816
5817     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5818         if(pFDesc->funcdesc.memid==memid){
5819             dump_TypeInfo(This);
5820             if (TRACE_ON(ole))
5821                 dump_TLBFuncDescOne(pFDesc);
5822
5823             if (pBstrDllName)
5824                 *pBstrDllName = SysAllocString(This->DllName);
5825
5826             if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5827                 if (pBstrName)
5828                     *pBstrName = SysAllocString(pFDesc->Entry);
5829                 if (pwOrdinal)
5830                     *pwOrdinal = -1;
5831                 return S_OK;
5832             }
5833             if (pBstrName)
5834                 *pBstrName = NULL;
5835             if (pwOrdinal)
5836                 *pwOrdinal = (DWORD)pFDesc->Entry;
5837             return S_OK;
5838         }
5839     return TYPE_E_ELEMENTNOTFOUND;
5840 }
5841
5842 /* ITypeInfo::GetRefTypeInfo
5843  *
5844  * If a type description references other type descriptions, it retrieves
5845  * the referenced type descriptions.
5846  */
5847 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5848         ITypeInfo2 *iface,
5849         HREFTYPE hRefType,
5850         ITypeInfo  **ppTInfo)
5851 {
5852     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5853     HRESULT result = E_FAIL;
5854
5855     if ((This->hreftype != -1) && (This->hreftype == hRefType))
5856     {
5857         *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5858         ITypeInfo_AddRef(*ppTInfo);
5859         result = S_OK;
5860     }
5861     else if (hRefType == -1 &&
5862         (((ITypeInfoImpl*) This)->TypeAttr.typekind   == TKIND_DISPATCH) &&
5863         (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags &  TYPEFLAG_FDUAL))
5864     {
5865           /* when we meet a DUAL dispinterface, we must create the interface
5866           * version of it.
5867           */
5868           ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5869
5870
5871           /* the interface version contains the same information as the dispinterface
5872            * copy the contents of the structs.
5873            */
5874           *pTypeInfoImpl = *This;
5875           pTypeInfoImpl->ref = 0;
5876
5877           /* change the type to interface */
5878           pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5879
5880           *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5881
5882           /* we use data structures from This, so we need to keep a reference
5883            * to it to stop it being destroyed and signal to the new instance to
5884            * not free its data structures when it is destroyed */
5885           pTypeInfoImpl->no_free_data = TRUE;
5886           pTypeInfoImpl->next = This;
5887           ITypeInfo_AddRef((ITypeInfo*) This);
5888
5889           ITypeInfo_AddRef(*ppTInfo);
5890
5891           result = S_OK;
5892
5893     } else {
5894         TLBRefType *pRefType;
5895         for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5896             if(pRefType->reference == hRefType)
5897                 break;
5898         }
5899         if(!pRefType)
5900           FIXME("Can't find pRefType for ref %x\n", hRefType);
5901         if(pRefType && hRefType != -1) {
5902             ITypeLib *pTLib = NULL;
5903
5904             if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5905                 UINT Index;
5906                 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5907             } else {
5908                 if(pRefType->pImpTLInfo->pImpTypeLib) {
5909                     TRACE("typeinfo in imported typelib that is already loaded\n");
5910                     pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5911                     ITypeLib2_AddRef((ITypeLib*) pTLib);
5912                     result = S_OK;
5913                 } else {
5914                     TRACE("typeinfo in imported typelib that isn't already loaded\n");
5915                     result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5916                                              pRefType->pImpTLInfo->wVersionMajor,
5917                                              pRefType->pImpTLInfo->wVersionMinor,
5918                                              pRefType->pImpTLInfo->lcid,
5919                                              &pTLib);
5920
5921                     if(!SUCCEEDED(result)) {
5922                         BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5923                         result=LoadTypeLib(libnam, &pTLib);
5924                         SysFreeString(libnam);
5925                     }
5926                     if(SUCCEEDED(result)) {
5927                         pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5928                         ITypeLib2_AddRef(pTLib);
5929                     }
5930                 }
5931             }
5932             if(SUCCEEDED(result)) {
5933                 if(pRefType->index == TLB_REF_USE_GUID)
5934                     result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5935                                                          &pRefType->guid,
5936                                                          ppTInfo);
5937                 else
5938                     result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5939                                                    ppTInfo);
5940             }
5941             if (pTLib != NULL)
5942                 ITypeLib2_Release(pTLib);
5943         }
5944     }
5945
5946     TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
5947           SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5948     return result;
5949 }
5950
5951 /* ITypeInfo::AddressOfMember
5952  *
5953  * Retrieves the addresses of static functions or variables, such as those
5954  * defined in a DLL.
5955  */
5956 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5957         MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5958 {
5959     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5960     HRESULT hr;
5961     BSTR dll, entry;
5962     WORD ordinal;
5963     HMODULE module;
5964
5965     TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
5966
5967     hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
5968     if (FAILED(hr))
5969         return hr;
5970
5971     module = LoadLibraryW(dll);
5972     if (!module)
5973     {
5974         ERR("couldn't load %s\n", debugstr_w(dll));
5975         SysFreeString(dll);
5976         if (entry) SysFreeString(entry);
5977         return STG_E_FILENOTFOUND;
5978     }
5979     /* FIXME: store library somewhere where we can free it */
5980
5981     if (entry)
5982     {
5983         LPSTR entryA;
5984         INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
5985         entryA = HeapAlloc(GetProcessHeap(), 0, len);
5986         WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
5987
5988         *ppv = GetProcAddress(module, entryA);
5989         if (!*ppv)
5990             ERR("function not found %s\n", debugstr_a(entryA));
5991
5992         HeapFree(GetProcessHeap(), 0, entryA);
5993     }
5994     else
5995     {
5996         *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
5997         if (!*ppv)
5998             ERR("function not found %d\n", ordinal);
5999     }
6000
6001     SysFreeString(dll);
6002     if (entry) SysFreeString(entry);
6003
6004     if (!*ppv)
6005         return TYPE_E_DLLFUNCTIONNOTFOUND;
6006
6007     return S_OK;
6008 }
6009
6010 /* ITypeInfo::CreateInstance
6011  *
6012  * Creates a new instance of a type that describes a component object class
6013  * (coclass).
6014  */
6015 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6016         IUnknown *pOuterUnk, REFIID riid, VOID  **ppvObj)
6017 {
6018     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6019     HRESULT hr;
6020     TYPEATTR *pTA;
6021
6022     TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6023
6024     *ppvObj = NULL;
6025
6026     if(pOuterUnk)
6027     {
6028         WARN("Not able to aggregate\n");
6029         return CLASS_E_NOAGGREGATION;
6030     }
6031
6032     hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6033     if(FAILED(hr)) return hr;
6034
6035     if(pTA->typekind != TKIND_COCLASS)
6036     {
6037         WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6038         hr = E_INVALIDARG;
6039         goto end;
6040     }
6041
6042     hr = S_FALSE;
6043     if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6044     {
6045         IUnknown *pUnk;
6046         hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6047         TRACE("GetActiveObject rets %08x\n", hr);
6048         if(hr == S_OK)
6049         {
6050             hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6051             IUnknown_Release(pUnk);
6052         }
6053     }
6054
6055     if(hr != S_OK)
6056         hr = CoCreateInstance(&pTA->guid, NULL,
6057                               CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6058                               riid, ppvObj);
6059
6060 end:
6061     ITypeInfo_ReleaseTypeAttr(iface, pTA);
6062     return hr;
6063 }
6064
6065 /* ITypeInfo::GetMops
6066  *
6067  * Retrieves marshalling information.
6068  */
6069 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6070                                 BSTR  *pBstrMops)
6071 {
6072     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6073     FIXME("(%p) stub!\n", This);
6074     return S_OK;
6075 }
6076
6077 /* ITypeInfo::GetContainingTypeLib
6078  *
6079  * Retrieves the containing type library and the index of the type description
6080  * within that type library.
6081  */
6082 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6083         ITypeLib  * *ppTLib, UINT  *pIndex)
6084 {
6085     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6086     
6087     /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6088     if (pIndex) {
6089       *pIndex=This->index;
6090       TRACE("returning pIndex=%d\n", *pIndex);
6091     }
6092     
6093     if (ppTLib) {
6094       *ppTLib=(LPTYPELIB )(This->pTypeLib);
6095       ITypeLib2_AddRef(*ppTLib);
6096       TRACE("returning ppTLib=%p\n", *ppTLib);
6097     }
6098     
6099     return S_OK;
6100 }
6101
6102 /* ITypeInfo::ReleaseTypeAttr
6103  *
6104  * Releases a TYPEATTR previously returned by GetTypeAttr.
6105  *
6106  */
6107 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6108         TYPEATTR* pTypeAttr)
6109 {
6110     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6111     TRACE("(%p)->(%p)\n", This, pTypeAttr);
6112     HeapFree(GetProcessHeap(), 0, pTypeAttr);
6113 }
6114
6115 /* ITypeInfo::ReleaseFuncDesc
6116  *
6117  * Releases a FUNCDESC previously returned by GetFuncDesc. *
6118  */
6119 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6120         ITypeInfo2 *iface,
6121         FUNCDESC *pFuncDesc)
6122 {
6123     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6124     SHORT i;
6125
6126     TRACE("(%p)->(%p)\n", This, pFuncDesc);
6127
6128     for (i = 0; i < pFuncDesc->cParams; i++)
6129         TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6130     TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6131
6132     SysFreeString((BSTR)pFuncDesc);
6133 }
6134
6135 /* ITypeInfo::ReleaseVarDesc
6136  *
6137  * Releases a VARDESC previously returned by GetVarDesc.
6138  */
6139 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6140         VARDESC *pVarDesc)
6141 {
6142     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6143     TRACE("(%p)->(%p)\n", This, pVarDesc);
6144
6145     TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6146     if (pVarDesc->varkind == VAR_CONST)
6147         VariantClear(pVarDesc->u.lpvarValue);
6148     SysFreeString((BSTR)pVarDesc);
6149 }
6150
6151 /* ITypeInfo2::GetTypeKind
6152  *
6153  * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6154  *
6155  */
6156 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6157     TYPEKIND *pTypeKind)
6158 {
6159     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6160     *pTypeKind=This->TypeAttr.typekind;
6161     TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6162     return S_OK;
6163 }
6164
6165 /* ITypeInfo2::GetTypeFlags
6166  *
6167  * Returns the type flags without any allocations. This returns a DWORD type
6168  * flag, which expands the type flags without growing the TYPEATTR (type
6169  * attribute).
6170  *
6171  */
6172 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6173 {
6174     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6175     *pTypeFlags=This->TypeAttr.wTypeFlags;
6176     TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6177     return S_OK;
6178 }
6179
6180 /* ITypeInfo2::GetFuncIndexOfMemId
6181  * Binds to a specific member based on a known DISPID, where the member name
6182  * is not known (for example, when binding to a default member).
6183  *
6184  */
6185 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6186     MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6187 {
6188     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6189     const TLBFuncDesc *pFuncInfo;
6190     int i;
6191     HRESULT result;
6192
6193     for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6194         if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6195             break;
6196     if(pFuncInfo) {
6197         *pFuncIndex = i;
6198         result = S_OK;
6199     } else
6200         result = TYPE_E_ELEMENTNOTFOUND;
6201
6202     TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6203           memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6204     return result;
6205 }
6206
6207 /* TypeInfo2::GetVarIndexOfMemId
6208  *
6209  * Binds to a specific member based on a known DISPID, where the member name
6210  * is not known (for example, when binding to a default member).
6211  *
6212  */
6213 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6214     MEMBERID memid, UINT *pVarIndex)
6215 {
6216     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6217     TLBVarDesc *pVarInfo;
6218     int i;
6219     HRESULT result;
6220     for(i=0, pVarInfo=This->varlist; pVarInfo &&
6221             memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6222         ;
6223     if(pVarInfo) {
6224         *pVarIndex = i;
6225         result = S_OK;
6226     } else
6227         result = TYPE_E_ELEMENTNOTFOUND;
6228
6229     TRACE("(%p) memid 0x%08x -> %s\n", This,
6230           memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6231     return result;
6232 }
6233
6234 /* ITypeInfo2::GetCustData
6235  *
6236  * Gets the custom data
6237  */
6238 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6239         ITypeInfo2 * iface,
6240         REFGUID guid,
6241         VARIANT *pVarVal)
6242 {
6243     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6244     TLBCustData *pCData;
6245
6246     for(pCData=This->pCustData; pCData; pCData = pCData->next)
6247         if( IsEqualIID(guid, &pCData->guid)) break;
6248
6249     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6250
6251     if(pCData)
6252     {
6253         VariantInit( pVarVal);
6254         VariantCopy( pVarVal, &pCData->data);
6255         return S_OK;
6256     }
6257     return E_INVALIDARG;  /* FIXME: correct? */
6258 }
6259
6260 /* ITypeInfo2::GetFuncCustData
6261  *
6262  * Gets the custom data
6263  */
6264 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6265         ITypeInfo2 * iface,
6266         UINT index,
6267         REFGUID guid,
6268         VARIANT *pVarVal)
6269 {
6270     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6271     TLBCustData *pCData=NULL;
6272     TLBFuncDesc * pFDesc;
6273     int i;
6274     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6275             pFDesc=pFDesc->next);
6276
6277     if(pFDesc)
6278         for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6279             if( IsEqualIID(guid, &pCData->guid)) break;
6280
6281     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6282
6283     if(pCData){
6284         VariantInit( pVarVal);
6285         VariantCopy( pVarVal, &pCData->data);
6286         return S_OK;
6287     }
6288     return E_INVALIDARG;  /* FIXME: correct? */
6289 }
6290
6291 /* ITypeInfo2::GetParamCustData
6292  *
6293  * Gets the custom data
6294  */
6295 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6296         ITypeInfo2 * iface,
6297         UINT indexFunc,
6298         UINT indexParam,
6299         REFGUID guid,
6300         VARIANT *pVarVal)
6301 {
6302     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6303     TLBCustData *pCData=NULL;
6304     TLBFuncDesc * pFDesc;
6305     int i;
6306
6307     for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6308
6309     if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
6310         for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6311                 pCData = pCData->next)
6312             if( IsEqualIID(guid, &pCData->guid)) break;
6313
6314     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6315
6316     if(pCData)
6317     {
6318         VariantInit( pVarVal);
6319         VariantCopy( pVarVal, &pCData->data);
6320         return S_OK;
6321     }
6322     return E_INVALIDARG;  /* FIXME: correct? */
6323 }
6324
6325 /* ITypeInfo2::GetVarCustData
6326  *
6327  * Gets the custom data
6328  */
6329 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6330         ITypeInfo2 * iface,
6331         UINT index,
6332         REFGUID guid,
6333         VARIANT *pVarVal)
6334 {
6335     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6336     TLBCustData *pCData=NULL;
6337     TLBVarDesc * pVDesc;
6338     int i;
6339
6340     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6341
6342     if(pVDesc)
6343     {
6344       for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6345       {
6346         if( IsEqualIID(guid, &pCData->guid)) break;
6347       }
6348     }
6349
6350     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6351
6352     if(pCData)
6353     {
6354         VariantInit( pVarVal);
6355         VariantCopy( pVarVal, &pCData->data);
6356         return S_OK;
6357     }
6358     return E_INVALIDARG;  /* FIXME: correct? */
6359 }
6360
6361 /* ITypeInfo2::GetImplCustData
6362  *
6363  * Gets the custom data
6364  */
6365 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6366         ITypeInfo2 * iface,
6367         UINT index,
6368         REFGUID guid,
6369         VARIANT *pVarVal)
6370 {
6371     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6372     TLBCustData *pCData=NULL;
6373     TLBImplType * pRDesc;
6374     int i;
6375
6376     for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6377
6378     if(pRDesc)
6379     {
6380       for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6381       {
6382         if( IsEqualIID(guid, &pCData->guid)) break;
6383       }
6384     }
6385
6386     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6387
6388     if(pCData)
6389     {
6390         VariantInit( pVarVal);
6391         VariantCopy( pVarVal, &pCData->data);
6392         return S_OK;
6393     }
6394     return E_INVALIDARG;  /* FIXME: correct? */
6395 }
6396
6397 /* ITypeInfo2::GetDocumentation2
6398  *
6399  * Retrieves the documentation string, the complete Help file name and path,
6400  * the localization context to use, and the context ID for the library Help
6401  * topic in the Help file.
6402  *
6403  */
6404 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6405         ITypeInfo2 * iface,
6406         MEMBERID memid,
6407         LCID lcid,
6408         BSTR *pbstrHelpString,
6409         DWORD *pdwHelpStringContext,
6410         BSTR *pbstrHelpStringDll)
6411 {
6412     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6413     const TLBFuncDesc *pFDesc;
6414     const TLBVarDesc *pVDesc;
6415     TRACE("(%p) memid %d lcid(0x%x)  HelpString(%p) "
6416           "HelpStringContext(%p) HelpStringDll(%p)\n",
6417           This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6418           pbstrHelpStringDll );
6419     /* the help string should be obtained from the helpstringdll,
6420      * using the _DLLGetDocumentation function, based on the supplied
6421      * lcid. Nice to do sometime...
6422      */
6423     if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6424         if(pbstrHelpString)
6425             *pbstrHelpString=SysAllocString(This->Name);
6426         if(pdwHelpStringContext)
6427             *pdwHelpStringContext=This->dwHelpStringContext;
6428         if(pbstrHelpStringDll)
6429             *pbstrHelpStringDll=
6430                 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6431         return S_OK;
6432     }else {/* for a member */
6433     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6434         if(pFDesc->funcdesc.memid==memid){
6435              if(pbstrHelpString)
6436                 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6437             if(pdwHelpStringContext)
6438                 *pdwHelpStringContext=pFDesc->HelpStringContext;
6439             if(pbstrHelpStringDll)
6440                 *pbstrHelpStringDll=
6441                     SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6442         return S_OK;
6443     }
6444     for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6445         if(pVDesc->vardesc.memid==memid){
6446              if(pbstrHelpString)
6447                 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6448             if(pdwHelpStringContext)
6449                 *pdwHelpStringContext=pVDesc->HelpStringContext;
6450             if(pbstrHelpStringDll)
6451                 *pbstrHelpStringDll=
6452                     SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6453             return S_OK;
6454         }
6455     }
6456     return TYPE_E_ELEMENTNOTFOUND;
6457 }
6458
6459 /* ITypeInfo2::GetAllCustData
6460  *
6461  * Gets all custom data items for the Type info.
6462  *
6463  */
6464 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6465         ITypeInfo2 * iface,
6466         CUSTDATA *pCustData)
6467 {
6468     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6469     TLBCustData *pCData;
6470     int i;
6471
6472     TRACE("(%p) returning %d items\n", This, This->ctCustData);
6473
6474     pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6475     if(pCustData->prgCustData ){
6476         pCustData->cCustData=This->ctCustData;
6477         for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6478             pCustData->prgCustData[i].guid=pCData->guid;
6479             VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6480         }
6481     }else{
6482         ERR(" OUT OF MEMORY!\n");
6483         return E_OUTOFMEMORY;
6484     }
6485     return S_OK;
6486 }
6487
6488 /* ITypeInfo2::GetAllFuncCustData
6489  *
6490  * Gets all custom data items for the specified Function
6491  *
6492  */
6493 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6494         ITypeInfo2 * iface,
6495         UINT index,
6496         CUSTDATA *pCustData)
6497 {
6498     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6499     TLBCustData *pCData;
6500     TLBFuncDesc * pFDesc;
6501     int i;
6502     TRACE("(%p) index %d\n", This, index);
6503     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6504             pFDesc=pFDesc->next)
6505         ;
6506     if(pFDesc){
6507         pCustData->prgCustData =
6508             TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6509         if(pCustData->prgCustData ){
6510             pCustData->cCustData=pFDesc->ctCustData;
6511             for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6512                     pCData = pCData->next){
6513                 pCustData->prgCustData[i].guid=pCData->guid;
6514                 VariantCopy(& pCustData->prgCustData[i].varValue,
6515                         & pCData->data);
6516             }
6517         }else{
6518             ERR(" OUT OF MEMORY!\n");
6519             return E_OUTOFMEMORY;
6520         }
6521         return S_OK;
6522     }
6523     return TYPE_E_ELEMENTNOTFOUND;
6524 }
6525
6526 /* ITypeInfo2::GetAllParamCustData
6527  *
6528  * Gets all custom data items for the Functions
6529  *
6530  */
6531 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6532     UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6533 {
6534     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6535     TLBCustData *pCData=NULL;
6536     TLBFuncDesc * pFDesc;
6537     int i;
6538     TRACE("(%p) index %d\n", This, indexFunc);
6539     for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6540             pFDesc=pFDesc->next)
6541         ;
6542     if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6543         pCustData->prgCustData =
6544             TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6545                     sizeof(CUSTDATAITEM));
6546         if(pCustData->prgCustData ){
6547             pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6548             for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6549                     pCData; i++, pCData = pCData->next){
6550                 pCustData->prgCustData[i].guid=pCData->guid;
6551                 VariantCopy(& pCustData->prgCustData[i].varValue,
6552                         & pCData->data);
6553             }
6554         }else{
6555             ERR(" OUT OF MEMORY!\n");
6556             return E_OUTOFMEMORY;
6557         }
6558         return S_OK;
6559     }
6560     return TYPE_E_ELEMENTNOTFOUND;
6561 }
6562
6563 /* ITypeInfo2::GetAllVarCustData
6564  *
6565  * Gets all custom data items for the specified Variable
6566  *
6567  */
6568 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6569     UINT index, CUSTDATA *pCustData)
6570 {
6571     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6572     TLBCustData *pCData;
6573     TLBVarDesc * pVDesc;
6574     int i;
6575     TRACE("(%p) index %d\n", This, index);
6576     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6577             pVDesc=pVDesc->next)
6578         ;
6579     if(pVDesc){
6580         pCustData->prgCustData =
6581             TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6582         if(pCustData->prgCustData ){
6583             pCustData->cCustData=pVDesc->ctCustData;
6584             for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6585                     pCData = pCData->next){
6586                 pCustData->prgCustData[i].guid=pCData->guid;
6587                 VariantCopy(& pCustData->prgCustData[i].varValue,
6588                         & pCData->data);
6589             }
6590         }else{
6591             ERR(" OUT OF MEMORY!\n");
6592             return E_OUTOFMEMORY;
6593         }
6594         return S_OK;
6595     }
6596     return TYPE_E_ELEMENTNOTFOUND;
6597 }
6598
6599 /* ITypeInfo2::GetAllImplCustData
6600  *
6601  * Gets all custom data items for the specified implementation type
6602  *
6603  */
6604 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6605         ITypeInfo2 * iface,
6606         UINT index,
6607         CUSTDATA *pCustData)
6608 {
6609     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6610     TLBCustData *pCData;
6611     TLBImplType * pRDesc;
6612     int i;
6613     TRACE("(%p) index %d\n", This, index);
6614     for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6615             pRDesc=pRDesc->next)
6616         ;
6617     if(pRDesc){
6618         pCustData->prgCustData =
6619             TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6620         if(pCustData->prgCustData ){
6621             pCustData->cCustData=pRDesc->ctCustData;
6622             for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6623                     pCData = pCData->next){
6624                 pCustData->prgCustData[i].guid=pCData->guid;
6625                 VariantCopy(& pCustData->prgCustData[i].varValue,
6626                         & pCData->data);
6627             }
6628         }else{
6629             ERR(" OUT OF MEMORY!\n");
6630             return E_OUTOFMEMORY;
6631         }
6632         return S_OK;
6633     }
6634     return TYPE_E_ELEMENTNOTFOUND;
6635 }
6636
6637 static const ITypeInfo2Vtbl tinfvt =
6638 {
6639
6640     ITypeInfo_fnQueryInterface,
6641     ITypeInfo_fnAddRef,
6642     ITypeInfo_fnRelease,
6643
6644     ITypeInfo_fnGetTypeAttr,
6645     ITypeInfo_fnGetTypeComp,
6646     ITypeInfo_fnGetFuncDesc,
6647     ITypeInfo_fnGetVarDesc,
6648     ITypeInfo_fnGetNames,
6649     ITypeInfo_fnGetRefTypeOfImplType,
6650     ITypeInfo_fnGetImplTypeFlags,
6651     ITypeInfo_fnGetIDsOfNames,
6652     ITypeInfo_fnInvoke,
6653     ITypeInfo_fnGetDocumentation,
6654     ITypeInfo_fnGetDllEntry,
6655     ITypeInfo_fnGetRefTypeInfo,
6656     ITypeInfo_fnAddressOfMember,
6657     ITypeInfo_fnCreateInstance,
6658     ITypeInfo_fnGetMops,
6659     ITypeInfo_fnGetContainingTypeLib,
6660     ITypeInfo_fnReleaseTypeAttr,
6661     ITypeInfo_fnReleaseFuncDesc,
6662     ITypeInfo_fnReleaseVarDesc,
6663
6664     ITypeInfo2_fnGetTypeKind,
6665     ITypeInfo2_fnGetTypeFlags,
6666     ITypeInfo2_fnGetFuncIndexOfMemId,
6667     ITypeInfo2_fnGetVarIndexOfMemId,
6668     ITypeInfo2_fnGetCustData,
6669     ITypeInfo2_fnGetFuncCustData,
6670     ITypeInfo2_fnGetParamCustData,
6671     ITypeInfo2_fnGetVarCustData,
6672     ITypeInfo2_fnGetImplTypeCustData,
6673     ITypeInfo2_fnGetDocumentation2,
6674     ITypeInfo2_fnGetAllCustData,
6675     ITypeInfo2_fnGetAllFuncCustData,
6676     ITypeInfo2_fnGetAllParamCustData,
6677     ITypeInfo2_fnGetAllVarCustData,
6678     ITypeInfo2_fnGetAllImplTypeCustData,
6679 };
6680
6681 /******************************************************************************
6682  * CreateDispTypeInfo [OLEAUT32.31]
6683  *
6684  * Build type information for an object so it can be called through an
6685  * IDispatch interface.
6686  *
6687  * RETURNS
6688  *  Success: S_OK. pptinfo contains the created ITypeInfo object.
6689  *  Failure: E_INVALIDARG, if one or more arguments is invalid.
6690  *
6691  * NOTES
6692  *  This call allows an objects methods to be accessed through IDispatch, by
6693  *  building an ITypeInfo object that IDispatch can use to call through.
6694  */
6695 HRESULT WINAPI CreateDispTypeInfo(
6696         INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6697         LCID lcid, /* [I] Locale Id */
6698         ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6699 {
6700     ITypeInfoImpl *pTIClass, *pTIIface;
6701     ITypeLibImpl *pTypeLibImpl;
6702     int param, func;
6703     TLBFuncDesc **ppFuncDesc;
6704
6705     TRACE("\n");
6706     pTypeLibImpl = TypeLibImpl_Constructor();
6707     if (!pTypeLibImpl) return E_FAIL;
6708
6709     pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6710     pTIIface->pTypeLib = pTypeLibImpl;
6711     pTIIface->index = 0;
6712     pTIIface->Name = NULL;
6713     pTIIface->dwHelpContext = -1;
6714     memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6715     pTIIface->TypeAttr.lcid = lcid;
6716     pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6717     pTIIface->TypeAttr.wMajorVerNum = 0;
6718     pTIIface->TypeAttr.wMinorVerNum = 0;
6719     pTIIface->TypeAttr.cbAlignment = 2;
6720     pTIIface->TypeAttr.cbSizeInstance = -1;
6721     pTIIface->TypeAttr.cbSizeVft = -1;
6722     pTIIface->TypeAttr.cFuncs = 0;
6723     pTIIface->TypeAttr.cImplTypes = 0;
6724     pTIIface->TypeAttr.cVars = 0;
6725     pTIIface->TypeAttr.wTypeFlags = 0;
6726
6727     ppFuncDesc = &pTIIface->funclist;
6728     for(func = 0; func < pidata->cMembers; func++) {
6729         METHODDATA *md = pidata->pmethdata + func;
6730         *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6731         (*ppFuncDesc)->Name = SysAllocString(md->szName);
6732         (*ppFuncDesc)->funcdesc.memid = md->dispid;
6733         (*ppFuncDesc)->funcdesc.lprgscode = NULL;
6734         (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6735         (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6736         (*ppFuncDesc)->funcdesc.callconv = md->cc;
6737         (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6738         (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6739         (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6740         (*ppFuncDesc)->funcdesc.cScodes = 0;
6741         (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6742         (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6743         (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6744         (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6745         (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6746                                                               md->cArgs * sizeof(ELEMDESC));
6747         (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6748                                               md->cArgs * sizeof(TLBParDesc));
6749         for(param = 0; param < md->cArgs; param++) {
6750             (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6751             (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6752         }
6753         (*ppFuncDesc)->helpcontext = 0;
6754         (*ppFuncDesc)->HelpStringContext = 0;
6755         (*ppFuncDesc)->HelpString = NULL;
6756         (*ppFuncDesc)->Entry = NULL;
6757         (*ppFuncDesc)->ctCustData = 0;
6758         (*ppFuncDesc)->pCustData = NULL;
6759         (*ppFuncDesc)->next = NULL;
6760         ppFuncDesc = &(*ppFuncDesc)->next;
6761     }
6762
6763     dump_TypeInfo(pTIIface);
6764
6765     pTypeLibImpl->pTypeInfo = pTIIface;
6766     pTypeLibImpl->TypeInfoCount++;
6767
6768     pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6769     pTIClass->pTypeLib = pTypeLibImpl;
6770     pTIClass->index = 1;
6771     pTIClass->Name = NULL;
6772     pTIClass->dwHelpContext = -1;
6773     memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6774     pTIClass->TypeAttr.lcid = lcid;
6775     pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6776     pTIClass->TypeAttr.wMajorVerNum = 0;
6777     pTIClass->TypeAttr.wMinorVerNum = 0;
6778     pTIClass->TypeAttr.cbAlignment = 2;
6779     pTIClass->TypeAttr.cbSizeInstance = -1;
6780     pTIClass->TypeAttr.cbSizeVft = -1;
6781     pTIClass->TypeAttr.cFuncs = 0;
6782     pTIClass->TypeAttr.cImplTypes = 1;
6783     pTIClass->TypeAttr.cVars = 0;
6784     pTIClass->TypeAttr.wTypeFlags = 0;
6785
6786     pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6787     pTIClass->impltypelist->hRef = 1;
6788
6789     pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist));
6790     pTIClass->reflist->index = 0;
6791     pTIClass->reflist->reference = 1;
6792     pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL;
6793
6794     dump_TypeInfo(pTIClass);
6795
6796     pTIIface->next = pTIClass;
6797     pTypeLibImpl->TypeInfoCount++;
6798
6799     *pptinfo = (ITypeInfo*)pTIClass;
6800
6801     ITypeInfo_AddRef(*pptinfo);
6802     ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
6803
6804     return S_OK;
6805
6806 }
6807
6808 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6809 {
6810     ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6811
6812     return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6813 }
6814
6815 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6816 {
6817     ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6818
6819     return ITypeInfo_AddRef((ITypeInfo *)This);
6820 }
6821
6822 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6823 {
6824     ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6825
6826     return ITypeInfo_Release((ITypeInfo *)This);
6827 }
6828
6829 static HRESULT WINAPI ITypeComp_fnBind(
6830     ITypeComp * iface,
6831     OLECHAR * szName,
6832     ULONG lHash,
6833     WORD wFlags,
6834     ITypeInfo ** ppTInfo,
6835     DESCKIND * pDescKind,
6836     BINDPTR * pBindPtr)
6837 {
6838     ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6839     const TLBFuncDesc *pFDesc;
6840     const TLBVarDesc *pVDesc;
6841     HRESULT hr = DISP_E_MEMBERNOTFOUND;
6842
6843     TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6844
6845     *pDescKind = DESCKIND_NONE;
6846     pBindPtr->lpfuncdesc = NULL;
6847     *ppTInfo = NULL;
6848
6849     for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6850         if (!strcmpiW(pFDesc->Name, szName)) {
6851             if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6852                 break;
6853             else
6854                 /* name found, but wrong flags */
6855                 hr = TYPE_E_TYPEMISMATCH;
6856         }
6857
6858     if (pFDesc)
6859     {
6860         HRESULT hr = TLB_AllocAndInitFuncDesc(
6861             &pFDesc->funcdesc,
6862             &pBindPtr->lpfuncdesc,
6863             This->TypeAttr.typekind == TKIND_DISPATCH);
6864         if (FAILED(hr))
6865             return hr;
6866         *pDescKind = DESCKIND_FUNCDESC;
6867         *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6868         ITypeInfo_AddRef(*ppTInfo);
6869         return S_OK;
6870     } else {
6871         for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6872             if (!strcmpiW(pVDesc->Name, szName)) {
6873                 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6874                 if (FAILED(hr))
6875                     return hr;
6876                 *pDescKind = DESCKIND_VARDESC;
6877                 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6878                 ITypeInfo_AddRef(*ppTInfo);
6879                 return S_OK;
6880             }
6881         }
6882     }
6883     /* FIXME: search each inherited interface, not just the first */
6884     if (hr == DISP_E_MEMBERNOTFOUND && This->TypeAttr.cImplTypes) {
6885         /* recursive search */
6886         ITypeInfo *pTInfo;
6887         ITypeComp *pTComp;
6888         HRESULT hr;
6889         hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6890         if (SUCCEEDED(hr))
6891         {
6892             hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6893             ITypeInfo_Release(pTInfo);
6894         }
6895         if (SUCCEEDED(hr))
6896         {
6897             hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6898             ITypeComp_Release(pTComp);
6899             return hr;
6900         }
6901         WARN("Could not search inherited interface!\n");
6902     }
6903     WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6904     return hr;
6905 }
6906
6907 static HRESULT WINAPI ITypeComp_fnBindType(
6908     ITypeComp * iface,
6909     OLECHAR * szName,
6910     ULONG lHash,
6911     ITypeInfo ** ppTInfo,
6912     ITypeComp ** ppTComp)
6913 {
6914     TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6915
6916     /* strange behaviour (does nothing) but like the
6917      * original */
6918
6919     if (!ppTInfo || !ppTComp)
6920         return E_POINTER;
6921
6922     *ppTInfo = NULL;
6923     *ppTComp = NULL;
6924
6925     return S_OK;
6926 }
6927
6928 static const ITypeCompVtbl tcompvt =
6929 {
6930
6931     ITypeComp_fnQueryInterface,
6932     ITypeComp_fnAddRef,
6933     ITypeComp_fnRelease,
6934
6935     ITypeComp_fnBind,
6936     ITypeComp_fnBindType
6937 };