mshtml: Print wine_gecko version in load_wine_gecko.
[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                                    libary. 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 * 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", 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                        (*pptfd)->Entry = SysAllocString((WCHAR*)pFuncRec->OptAttr[2]);
1817                     }
1818                     else
1819                     {
1820                         (*pptfd)->Entry = MSFT_ReadString(pcx,
1821                                                          pFuncRec->OptAttr[2]);
1822                     }
1823                     if( nrattributes > 5 )
1824                     {
1825                         (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1826
1827                         if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1828                         {
1829                             MSFT_CustData(pcx,
1830                                           pFuncRec->OptAttr[6],
1831                                           &(*pptfd)->pCustData);
1832                         }
1833                     }
1834                 }
1835             }
1836         }
1837
1838         /* fill the FuncDesc Structure */
1839         MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1840                            offset + infolen + ( i + 1) * sizeof(INT));
1841
1842         (*pptfd)->funcdesc.funckind   =  (pFuncRec->FKCCIC)      & 0x7;
1843         (*pptfd)->funcdesc.invkind    =  (pFuncRec->FKCCIC) >> 3 & 0xF;
1844         (*pptfd)->funcdesc.callconv   =  (pFuncRec->FKCCIC) >> 8 & 0xF;
1845         (*pptfd)->funcdesc.cParams    =   pFuncRec->nrargs  ;
1846         (*pptfd)->funcdesc.cParamsOpt =   pFuncRec->nroargs ;
1847         (*pptfd)->funcdesc.oVft       =   pFuncRec->VtableOffset ;
1848         (*pptfd)->funcdesc.wFuncFlags =   LOWORD(pFuncRec->Flags) ;
1849
1850         MSFT_GetTdesc(pcx,
1851                       pFuncRec->DataType,
1852                       &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1853                       pTI);
1854         MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1855
1856         /* do the parameters/arguments */
1857         if(pFuncRec->nrargs)
1858         {
1859             int j = 0;
1860             MSFT_ParameterInfo paraminfo;
1861
1862             (*pptfd)->funcdesc.lprgelemdescParam =
1863                 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1864
1865             (*pptfd)->pParamDesc =
1866                 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1867
1868             MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1869                               recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1870
1871             for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1872             {
1873                 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1874
1875                 MSFT_GetTdesc(pcx,
1876                               paraminfo.DataType,
1877                               &elemdesc->tdesc,
1878                               pTI);
1879
1880                 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1881
1882                 /* name */
1883                 if (paraminfo.oName == -1)
1884                     /* this occurs for [propput] or [propget] methods, so
1885                      * we should just set the name of the parameter to the
1886                      * name of the method. */
1887                     (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1888                 else
1889                     (*pptfd)->pParamDesc[j].Name =
1890                         MSFT_ReadName( pcx, paraminfo.oName );
1891                 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1892
1893                 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1894
1895                 /* default value */
1896                 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1897                      (pFuncRec->FKCCIC & 0x1000) )
1898                 {
1899                     INT* pInt = (INT *)((char *)pFuncRec +
1900                                    reclength -
1901                                    (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1902
1903                     PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1904
1905                     pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1906                     pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1907
1908                     MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1909                         pInt[j], pcx);
1910                 }
1911                 else
1912                     elemdesc->u.paramdesc.pparamdescex = NULL;
1913                 /* custom info */
1914                 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1915                 {
1916                     MSFT_CustData(pcx,
1917                                   pFuncRec->OptAttr[7+j],
1918                                   &(*pptfd)->pParamDesc[j].pCustData);
1919                 }
1920
1921                 /* SEEK value = jump to offset,
1922                  * from there jump to the end of record,
1923                  * go back by (j-1) arguments
1924                  */
1925                 MSFT_ReadLEDWords( &paraminfo ,
1926                            sizeof(MSFT_ParameterInfo), pcx,
1927                            recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1928                                                * sizeof(MSFT_ParameterInfo)));
1929             }
1930         }
1931
1932         /* scode is not used: archaic win16 stuff FIXME: right? */
1933         (*pptfd)->funcdesc.cScodes   = 0 ;
1934         (*pptfd)->funcdesc.lprgscode = NULL ;
1935
1936         ptfd_prev = *pptfd;
1937         pptfd      = & ((*pptfd)->next);
1938         recoffset += reclength;
1939     }
1940     HeapFree(GetProcessHeap(), 0, recbuf);
1941 }
1942
1943 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1944                        int cVars, int offset, TLBVarDesc ** pptvd)
1945 {
1946     int infolen, nameoffset, reclength;
1947     char recbuf[256];
1948     MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1949     int i;
1950     int recoffset;
1951
1952     TRACE_(typelib)("\n");
1953
1954     MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1955     MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1956                       ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1957     recoffset += offset+sizeof(INT);
1958     for(i=0;i<cVars;i++){
1959         *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1960     /* name, eventually add to a hash table */
1961         MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1962                           offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
1963         (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1964     /* read the variable information record */
1965         MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1966         reclength &=0xff;
1967         MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1968     /* Optional data */
1969         if(reclength >(6*sizeof(INT)) )
1970             (*pptvd)->HelpContext=pVarRec->HelpContext;
1971         if(reclength >(7*sizeof(INT)) )
1972             (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1973         if(reclength >(8*sizeof(INT)) )
1974         if(reclength >(9*sizeof(INT)) )
1975             (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1976     /* fill the VarDesc Structure */
1977         MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1978                           offset + infolen + (cFuncs + i + 1) * sizeof(INT));
1979         (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1980         (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1981         MSFT_GetTdesc(pcx, pVarRec->DataType,
1982             &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1983 /*   (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1984         if(pVarRec->VarKind == VAR_CONST ){
1985             (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1986             MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1987                 pVarRec->OffsValue, pcx);
1988         } else
1989             (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1990         MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
1991         pptvd=&((*pptvd)->next);
1992         recoffset += reclength;
1993     }
1994 }
1995 /* fill in data for a hreftype (offset). When the referenced type is contained
1996  * in the typelib, it's just an (file) offset in the type info base dir.
1997  * If comes from import, it's an offset+1 in the ImpInfo table
1998  * */
1999 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
2000                           int offset)
2001 {
2002     int j;
2003     TLBRefType **ppRefType = &pTI->reflist;
2004
2005     TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2006
2007     while(*ppRefType) {
2008         if((*ppRefType)->reference == offset)
2009             return;
2010         ppRefType = &(*ppRefType)->next;
2011     }
2012
2013     *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2014                            sizeof(**ppRefType));
2015
2016     if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2017         /* external typelib */
2018         MSFT_ImpInfo impinfo;
2019         TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2020
2021         TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2022
2023         MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2024                           pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2025         for(j=0;pImpLib;j++){   /* search the known offsets of all import libraries */
2026             if(pImpLib->offset==impinfo.oImpFile) break;
2027             pImpLib=pImpLib->next;
2028         }
2029         if(pImpLib){
2030             (*ppRefType)->reference=offset;
2031             (*ppRefType)->pImpTLInfo = pImpLib;
2032             if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2033                 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
2034                 TRACE("importing by guid %s\n", debugstr_guid(&(*ppRefType)->guid));
2035                 (*ppRefType)->index = TLB_REF_USE_GUID;
2036             } else
2037                 (*ppRefType)->index = impinfo.oGuid;
2038         }else{
2039             ERR("Cannot find a reference\n");
2040             (*ppRefType)->reference=-1;
2041             (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
2042         }
2043     }else{
2044         /* in this typelib */
2045         (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2046         (*ppRefType)->reference=offset;
2047         (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2048     }
2049 }
2050
2051 /* process Implemented Interfaces of a com class */
2052 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2053                             int offset)
2054 {
2055     int i;
2056     MSFT_RefRecord refrec;
2057     TLBImplType **ppImpl = &pTI->impltypelist;
2058
2059     TRACE_(typelib)("\n");
2060
2061     for(i=0;i<count;i++){
2062         if(offset<0) break; /* paranoia */
2063         *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2064         MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2065         MSFT_DoRefType(pcx, pTI, refrec.reftype);
2066         (*ppImpl)->hRef = refrec.reftype;
2067         (*ppImpl)->implflags=refrec.flags;
2068         (*ppImpl)->ctCustData=
2069             MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2070         offset=refrec.onext;
2071         ppImpl=&((*ppImpl)->next);
2072     }
2073 }
2074 /*
2075  * process a typeinfo record
2076  */
2077 static ITypeInfoImpl * MSFT_DoTypeInfo(
2078     TLBContext *pcx,
2079     int count,
2080     INT dispatch_href,
2081     ITypeLibImpl * pLibInfo)
2082 {
2083     MSFT_TypeInfoBase tiBase;
2084     ITypeInfoImpl *ptiRet;
2085
2086     TRACE_(typelib)("count=%u\n", count);
2087
2088     ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2089     MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2090                       pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2091
2092 /* this is where we are coming from */
2093     ptiRet->pTypeLib = pLibInfo;
2094     ptiRet->index=count;
2095 /* fill in the typeattr fields */
2096
2097     MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2098     ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid;   /* FIXME: correct? */
2099     ptiRet->TypeAttr.lpstrSchema=NULL;              /* reserved */
2100     ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2101     ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2102     ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2103     ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2104     ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2105     ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2106     ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2107     ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2108     ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2109     ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2110     if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2111         MSFT_GetTdesc(pcx, tiBase.datatype1,
2112             &ptiRet->TypeAttr.tdescAlias, ptiRet);
2113
2114 /*  FIXME: */
2115 /*    IDLDESC  idldescType; *//* never saw this one != zero  */
2116
2117 /* name, eventually add to a hash table */
2118     ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2119     ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2120     TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2121     /* help info */
2122     ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2123     ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2124     ptiRet->dwHelpContext=tiBase.helpcontext;
2125
2126     if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2127         ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2128
2129 /* note: InfoType's Help file and HelpStringDll come from the containing
2130  * library. Further HelpString and Docstring appear to be the same thing :(
2131  */
2132     /* functions */
2133     if(ptiRet->TypeAttr.cFuncs >0 )
2134         MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2135                     ptiRet->TypeAttr.cVars,
2136                     tiBase.memoffset, & ptiRet->funclist);
2137     /* variables */
2138     if(ptiRet->TypeAttr.cVars >0 )
2139         MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2140                    ptiRet->TypeAttr.cVars,
2141                    tiBase.memoffset, & ptiRet->varlist);
2142     if(ptiRet->TypeAttr.cImplTypes >0 ) {
2143         switch(ptiRet->TypeAttr.typekind)
2144         {
2145         case TKIND_COCLASS:
2146             MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2147                 tiBase.datatype1);
2148             break;
2149         case TKIND_DISPATCH:
2150             ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2151
2152             if (tiBase.datatype1 != -1)
2153             {
2154               MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2155               ptiRet->impltypelist->hRef = tiBase.datatype1;
2156             }
2157             else
2158             {
2159               MSFT_DoRefType(pcx, ptiRet, dispatch_href);
2160               ptiRet->impltypelist->hRef = dispatch_href;
2161             }
2162             break;
2163         default:
2164             ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2165             MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2166             ptiRet->impltypelist->hRef = tiBase.datatype1;
2167             break;
2168        }
2169     }
2170     ptiRet->ctCustData=
2171         MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2172
2173     TRACE_(typelib)("%s guid: %s kind:%s\n",
2174        debugstr_w(ptiRet->Name),
2175        debugstr_guid(&ptiRet->TypeAttr.guid),
2176        typekind_desc[ptiRet->TypeAttr.typekind]);
2177
2178     return ptiRet;
2179 }
2180
2181 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2182  * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2183  * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2184  * tradeoff here.
2185  */
2186 static ITypeLibImpl *tlb_cache_first;
2187 static CRITICAL_SECTION cache_section;
2188 static CRITICAL_SECTION_DEBUG cache_section_debug =
2189 {
2190     0, 0, &cache_section,
2191     { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2192       0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2193 };
2194 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2195
2196
2197 /****************************************************************************
2198  *      TLB_ReadTypeLib
2199  *
2200  * find the type of the typelib file and map the typelib resource into
2201  * the memory
2202  */
2203 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2204 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2205 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2206 {
2207     ITypeLibImpl *entry;
2208     int ret = TYPE_E_CANTLOADLIBRARY;
2209     INT index = 1;
2210     HINSTANCE hinstDLL;
2211
2212     *ppTypeLib = NULL;
2213
2214     lstrcpynW(pszPath, pszFileName, cchPath);
2215
2216     /* first try loading as a dll and access the typelib as a resource */
2217     hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES |
2218             LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2219     if (!hinstDLL)
2220     {
2221         /* it may have been specified with resource index appended to the
2222          * path, so remove it and try again */
2223         const WCHAR *pIndexStr = strrchrW(pszFileName, '\\');
2224         if(pIndexStr && pIndexStr != pszFileName && *++pIndexStr != '\0')
2225         {
2226             index = atoiW(pIndexStr);
2227             pszPath[pIndexStr - pszFileName - 1] = '\0';
2228
2229             hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES |
2230                     LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2231         }
2232     }
2233
2234     /* get the path to the specified typelib file */
2235     if (!hinstDLL)
2236     {
2237         /* otherwise, try loading as a regular file */
2238         if (!SearchPathW(NULL, pszFileName, NULL, cchPath, pszPath, NULL))
2239             return TYPE_E_CANTLOADLIBRARY;
2240     }
2241
2242     TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2243
2244     /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2245     EnterCriticalSection(&cache_section);
2246     for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2247     {
2248         if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2249         {
2250             TRACE("cache hit\n");
2251             *ppTypeLib = (ITypeLib2*)entry;
2252             ITypeLib_AddRef(*ppTypeLib);
2253             LeaveCriticalSection(&cache_section);
2254             FreeLibrary(hinstDLL);
2255             return S_OK;
2256         }
2257     }
2258     LeaveCriticalSection(&cache_section);
2259
2260     /* now actually load and parse the typelib */
2261     if (hinstDLL)
2262     {
2263         static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2264         HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2265         if (hrsrc)
2266         {
2267             HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2268             if (hGlobal)
2269             {
2270                 LPVOID pBase = LockResource(hGlobal);
2271                 DWORD  dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2272
2273                 if (pBase)
2274                 {
2275                     /* try to load as incore resource */
2276                     DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2277                     if (dwSignature == MSFT_SIGNATURE)
2278                         *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2279                     else if (dwSignature == SLTG_SIGNATURE)
2280                         *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2281                     else
2282                         FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2283                 }
2284                 FreeResource( hGlobal );
2285             }
2286         }
2287         FreeLibrary(hinstDLL);
2288     }
2289     else
2290     {
2291         HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2292         if (INVALID_HANDLE_VALUE != hFile)
2293         {
2294             HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2295             if (hMapping)
2296             {
2297                 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2298                 if(pBase)
2299                 {
2300                     /* retrieve file size */
2301                     DWORD dwTLBLength = GetFileSize(hFile, NULL);
2302                     DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2303
2304                     if (dwSignature == MSFT_SIGNATURE)
2305                         *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2306                     else if (dwSignature == SLTG_SIGNATURE)
2307                         *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2308
2309                     UnmapViewOfFile(pBase);
2310                 }
2311                 CloseHandle(hMapping);
2312             }
2313             CloseHandle(hFile);
2314         }
2315     }
2316
2317     if(*ppTypeLib) {
2318         ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2319
2320         TRACE("adding to cache\n");
2321         impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2322         lstrcpyW(impl->path, pszPath);
2323         /* We should really canonicalise the path here. */
2324         impl->index = index;
2325
2326         /* FIXME: check if it has added already in the meantime */
2327         EnterCriticalSection(&cache_section);
2328         if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2329         impl->prev = NULL;
2330         tlb_cache_first = impl;
2331         LeaveCriticalSection(&cache_section);
2332         ret = S_OK;
2333     } else
2334         ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2335
2336     return ret;
2337 }
2338
2339 /*================== ITypeLib(2) Methods ===================================*/
2340
2341 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2342 {
2343     ITypeLibImpl* pTypeLibImpl;
2344
2345     pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2346     if (!pTypeLibImpl) return NULL;
2347
2348     pTypeLibImpl->lpVtbl = &tlbvt;
2349     pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2350     pTypeLibImpl->ref = 1;
2351
2352     return pTypeLibImpl;
2353 }
2354
2355 /****************************************************************************
2356  *      ITypeLib2_Constructor_MSFT
2357  *
2358  * loading an MSFT typelib from an in-memory image
2359  */
2360 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2361 {
2362     TLBContext cx;
2363     long lPSegDir;
2364     MSFT_Header tlbHeader;
2365     MSFT_SegDir tlbSegDir;
2366     ITypeLibImpl * pTypeLibImpl;
2367
2368     TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2369
2370     pTypeLibImpl = TypeLibImpl_Constructor();
2371     if (!pTypeLibImpl) return NULL;
2372
2373     /* get pointer to beginning of typelib data */
2374     cx.pos = 0;
2375     cx.oStart=0;
2376     cx.mapping = pLib;
2377     cx.pLibInfo = pTypeLibImpl;
2378     cx.length = dwTLBLength;
2379
2380     /* read header */
2381     MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2382     TRACE_(typelib)("header:\n");
2383     TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2384     if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2385         FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2386         return NULL;
2387     }
2388     TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2389
2390     /* there is a small amount of information here until the next important
2391      * part:
2392      * the segment directory . Try to calculate the amount of data */
2393     lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2394
2395     /* now read the segment directory */
2396     TRACE("read segment directory (at %ld)\n",lPSegDir);
2397     MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2398     cx.pTblDir = &tlbSegDir;
2399
2400     /* just check two entries */
2401     if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2402     {
2403         ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2404         HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2405         return NULL;
2406     }
2407
2408     /* now fill our internal data */
2409     /* TLIBATTR fields */
2410     MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2411
2412     /*    pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2413     /* Windows seems to have zero here, is this correct? */
2414     if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2415       pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2416     else
2417       pTypeLibImpl->LibAttr.lcid = 0;
2418
2419     pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2420     pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2421     pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2422     pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2423
2424     /* name, eventually add to a hash table */
2425     pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2426
2427     /* help info */
2428     pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2429     pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2430
2431     if( tlbHeader.varflags & HELPDLLFLAG)
2432     {
2433             int offset;
2434             MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2435             pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2436     }
2437
2438     pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2439
2440     /* custom data */
2441     if(tlbHeader.CustomDataOffset >= 0)
2442     {
2443         pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2444     }
2445
2446     /* fill in typedescriptions */
2447     if(tlbSegDir.pTypdescTab.length > 0)
2448     {
2449         int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2450         INT16 td[4];
2451         pTypeLibImpl->ctTypeDesc = cTD;
2452         pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2453         MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2454         for(i=0; i<cTD; )
2455         {
2456             /* FIXME: add several sanity checks here */
2457             pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2458             if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2459             {
2460                 /* FIXME: check safearray */
2461                 if(td[3] < 0)
2462                     pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2463                 else
2464                     pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2465             }
2466             else if(td[0] == VT_CARRAY)
2467             {
2468                 /* array descr table here */
2469                 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]);  /* temp store offset in*/
2470             }
2471             else if(td[0] == VT_USERDEFINED)
2472             {
2473                 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2474             }
2475             if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2476         }
2477
2478         /* second time around to fill the array subscript info */
2479         for(i=0;i<cTD;i++)
2480         {
2481             if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2482             if(tlbSegDir.pArrayDescriptions.offset>0)
2483             {
2484                 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2485                 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2486
2487                 if(td[1]<0)
2488                     pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2489                 else
2490                     pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2491
2492                 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2493
2494                 for(j = 0; j<td[2]; j++)
2495                 {
2496                     MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2497                                       sizeof(INT), &cx, DO_NOT_SEEK);
2498                     MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2499                                       sizeof(INT), &cx, DO_NOT_SEEK);
2500                 }
2501             }
2502             else
2503             {
2504                 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2505                 ERR("didn't find array description data\n");
2506             }
2507         }
2508     }
2509
2510     /* imported type libs */
2511     if(tlbSegDir.pImpFiles.offset>0)
2512     {
2513         TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2514         int oGuid, offset = tlbSegDir.pImpFiles.offset;
2515         UINT16 size;
2516
2517         while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2518         {
2519             char *name;
2520             DWORD len;
2521
2522             *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2523             (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2524             MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2525
2526             MSFT_ReadLEDWords(&(*ppImpLib)->lcid,         sizeof(LCID),   &cx, DO_NOT_SEEK);
2527             MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD),   &cx, DO_NOT_SEEK);
2528             MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD),   &cx, DO_NOT_SEEK);
2529             MSFT_ReadLEWords(& size,                      sizeof(UINT16), &cx, DO_NOT_SEEK);
2530
2531             size >>= 2;
2532             name = TLB_Alloc(size+1);
2533             MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2534             len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2535             (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2536             MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2537             TLB_Free(name);
2538
2539             MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2540             offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2541
2542             ppImpLib = &(*ppImpLib)->next;
2543         }
2544     }
2545
2546     /* type info's */
2547     if(tlbHeader.nrtypeinfos >= 0 )
2548     {
2549         /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2550         ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2551         int i;
2552
2553         for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2554         {
2555             *ppTI = MSFT_DoTypeInfo(&cx, i, tlbHeader.dispatchpos, pTypeLibImpl);
2556
2557             ppTI = &((*ppTI)->next);
2558             (pTypeLibImpl->TypeInfoCount)++;
2559         }
2560     }
2561
2562     TRACE("(%p)\n", pTypeLibImpl);
2563     return (ITypeLib2*) pTypeLibImpl;
2564 }
2565
2566
2567 static BSTR TLB_MultiByteToBSTR(char *ptr)
2568 {
2569     DWORD len;
2570     WCHAR *nameW;
2571     BSTR ret;
2572
2573     len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2574     nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2575     MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2576     ret = SysAllocString(nameW);
2577     HeapFree(GetProcessHeap(), 0, nameW);
2578     return ret;
2579 }
2580
2581 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2582 {
2583   char b[3];
2584   int i;
2585   short s;
2586
2587   if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2588     FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2589     return FALSE;
2590   }
2591
2592   guid->Data4[0] = s >> 8;
2593   guid->Data4[1] = s & 0xff;
2594
2595   b[2] = '\0';
2596   for(i = 0; i < 6; i++) {
2597     memcpy(b, str + 24 + 2 * i, 2);
2598     guid->Data4[i + 2] = strtol(b, NULL, 16);
2599   }
2600   return TRUE;
2601 }
2602
2603 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2604 {
2605     WORD bytelen;
2606     DWORD len;
2607     WCHAR *nameW;
2608
2609     *pBstr = NULL;
2610     bytelen = *(WORD*)ptr;
2611     if(bytelen == 0xffff) return 2;
2612     len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2613     nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2614     len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2615     *pBstr = SysAllocStringLen(nameW, len);
2616     HeapFree(GetProcessHeap(), 0, nameW);
2617     return bytelen + 2;
2618 }
2619
2620 static WORD SLTG_ReadStringA(char *ptr, char **str)
2621 {
2622     WORD bytelen;
2623
2624     *str = NULL;
2625     bytelen = *(WORD*)ptr;
2626     if(bytelen == 0xffff) return 2;
2627     *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2628     memcpy(*str, ptr + 2, bytelen);
2629     (*str)[bytelen] = '\0';
2630     return bytelen + 2;
2631 }
2632
2633 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2634 {
2635     char *ptr = pLibBlk;
2636     WORD w;
2637
2638     if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2639         FIXME("libblk magic = %04x\n", w);
2640         return 0;
2641     }
2642
2643     ptr += 6;
2644     if((w = *(WORD*)ptr) != 0xffff) {
2645         FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2646         ptr += w;
2647     }
2648     ptr += 2;
2649
2650     ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2651
2652     ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2653
2654     pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2655     ptr += 4;
2656
2657     pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2658     ptr += 2;
2659
2660     if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2661         pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2662     else
2663         pTypeLibImpl->LibAttr.lcid = 0;
2664     ptr += 2;
2665
2666     ptr += 4; /* skip res12 */
2667
2668     pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2669     ptr += 2;
2670
2671     pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2672     ptr += 2;
2673
2674     pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2675     ptr += 2;
2676
2677     memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2678     ptr += sizeof(GUID);
2679
2680     return ptr - (char*)pLibBlk;
2681 }
2682
2683 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD)
2684 {
2685     BOOL done = FALSE;
2686
2687     while(!done) {
2688         if((*pType & 0xe00) == 0xe00) {
2689             pTD->vt = VT_PTR;
2690             pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2691                                        sizeof(TYPEDESC));
2692             pTD = pTD->u.lptdesc;
2693         }
2694         switch(*pType & 0x3f) {
2695         case VT_PTR:
2696             pTD->vt = VT_PTR;
2697             pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2698                                        sizeof(TYPEDESC));
2699             pTD = pTD->u.lptdesc;
2700             break;
2701
2702         case VT_USERDEFINED:
2703             pTD->vt = VT_USERDEFINED;
2704             pTD->u.hreftype = *(++pType) / 4;
2705             done = TRUE;
2706             break;
2707
2708         case VT_CARRAY:
2709           {
2710             /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2711                array */
2712
2713             SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2714
2715             pTD->vt = VT_CARRAY;
2716             pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2717                                 sizeof(ARRAYDESC) +
2718                                 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2719             pTD->u.lpadesc->cDims = pSA->cDims;
2720             memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2721                    pSA->cDims * sizeof(SAFEARRAYBOUND));
2722
2723             pTD = &pTD->u.lpadesc->tdescElem;
2724             break;
2725           }
2726
2727         case VT_SAFEARRAY:
2728           {
2729             /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2730                useful? */
2731
2732             pType++;
2733             pTD->vt = VT_SAFEARRAY;
2734             pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2735                                        sizeof(TYPEDESC));
2736             pTD = pTD->u.lptdesc;
2737             break;
2738           }
2739         default:
2740             pTD->vt = *pType & 0x3f;
2741             done = TRUE;
2742             break;
2743         }
2744         pType++;
2745     }
2746     return pType;
2747 }
2748
2749 static WORD *SLTG_DoElem(WORD *pType, char *pBlk, ELEMDESC *pElem)
2750 {
2751     /* Handle [in/out] first */
2752     if((*pType & 0xc000) == 0xc000)
2753         pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2754     else if(*pType & 0x8000)
2755         pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2756     else if(*pType & 0x4000)
2757         pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2758     else
2759         pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2760
2761     if(*pType & 0x2000)
2762         pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2763
2764     if(*pType & 0x80)
2765         pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2766
2767     return SLTG_DoType(pType, pBlk, &pElem->tdesc);
2768 }
2769
2770
2771 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2772                         char *pNameTable)
2773 {
2774     int ref;
2775     char *name;
2776     TLBRefType **ppRefType;
2777
2778     if(pRef->magic != SLTG_REF_MAGIC) {
2779         FIXME("Ref magic = %x\n", pRef->magic);
2780         return;
2781     }
2782     name = ( (char*)(&pRef->names) + pRef->number);
2783
2784     ppRefType = &pTI->reflist;
2785     for(ref = 0; ref < pRef->number >> 3; ref++) {
2786         char *refname;
2787         unsigned int lib_offs, type_num;
2788
2789         *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2790                                sizeof(**ppRefType));
2791
2792         name += SLTG_ReadStringA(name, &refname);
2793         if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2794             FIXME("Can't sscanf ref\n");
2795         if(lib_offs != 0xffff) {
2796             TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2797
2798             while(*import) {
2799                 if((*import)->offset == lib_offs)
2800                     break;
2801                 import = &(*import)->next;
2802             }
2803             if(!*import) {
2804                 char fname[MAX_PATH+1];
2805                 int len;
2806
2807                 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2808                                     sizeof(**import));
2809                 (*import)->offset = lib_offs;
2810                 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2811                                     &(*import)->guid);
2812                 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
2813                           &(*import)->wVersionMajor,
2814                           &(*import)->wVersionMinor,
2815                           &(*import)->lcid, fname) != 4) {
2816                   FIXME("can't sscanf ref %s\n",
2817                         pNameTable + lib_offs + 40);
2818                 }
2819                 len = strlen(fname);
2820                 if(fname[len-1] != '#')
2821                     FIXME("fname = %s\n", fname);
2822                 fname[len-1] = '\0';
2823                 (*import)->name = TLB_MultiByteToBSTR(fname);
2824             }
2825             (*ppRefType)->pImpTLInfo = *import;
2826         } else { /* internal ref */
2827           (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2828         }
2829         (*ppRefType)->reference = ref;
2830         (*ppRefType)->index = type_num;
2831
2832         HeapFree(GetProcessHeap(), 0, refname);
2833         ppRefType = &(*ppRefType)->next;
2834     }
2835     if((BYTE)*name != SLTG_REF_MAGIC)
2836       FIXME("End of ref block magic = %x\n", *name);
2837     dump_TLBRefType(pTI->reflist);
2838 }
2839
2840 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2841                           BOOL OneOnly)
2842 {
2843     SLTG_ImplInfo *info;
2844     TLBImplType **ppImplType = &pTI->impltypelist;
2845     /* I don't really get this structure, usually it's 0x16 bytes
2846        long, but iuser.tlb contains some that are 0x18 bytes long.
2847        That's ok because we can use the next ptr to jump to the next
2848        one. But how do we know the length of the last one?  The WORD
2849        at offs 0x8 might be the clue.  For now I'm just assuming that
2850        the last one is the regular 0x16 bytes. */
2851
2852     info = (SLTG_ImplInfo*)pBlk;
2853     while(1) {
2854         *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2855                                 sizeof(**ppImplType));
2856         (*ppImplType)->hRef = info->ref;
2857         (*ppImplType)->implflags = info->impltypeflags;
2858         pTI->TypeAttr.cImplTypes++;
2859         ppImplType = &(*ppImplType)->next;
2860
2861         if(info->next == 0xffff)
2862             break;
2863         if(OneOnly)
2864             FIXME("Interface inheriting more than one interface\n");
2865         info = (SLTG_ImplInfo*)(pBlk + info->next);
2866     }
2867     info++; /* see comment at top of function */
2868     return (char*)info;
2869 }
2870
2871 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars, char *pNameTable)
2872 {
2873   TLBVarDesc **ppVarDesc = &pTI->varlist;
2874   BSTR bstrPrevName = NULL;
2875   SLTG_Variable *pItem;
2876   unsigned short i;
2877   WORD *pType;
2878   char buf[300];
2879
2880   for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
2881       pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
2882
2883       *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2884                              sizeof(**ppVarDesc));
2885       (*ppVarDesc)->vardesc.memid = pItem->memid;
2886
2887       if (pItem->magic != SLTG_VAR_MAGIC &&
2888           pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
2889           FIXME_(typelib)("var magic = %02x\n", pItem->magic);
2890           return;
2891       }
2892
2893       if (pItem->name == 0xfffe)
2894         (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
2895       else
2896         (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2897
2898       TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
2899       TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
2900
2901       if (pItem->flags & 0x40) {
2902         TRACE_(typelib)("VAR_DISPATCH\n");
2903         (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
2904       }
2905       else if (pItem->flags & 0x10) {
2906         TRACE_(typelib)("VAR_CONST\n");
2907         (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2908         (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2909                                                        sizeof(VARIANT));
2910         V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2911         V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2912           *(INT*)(pBlk + pItem->byte_offs);
2913       }
2914       else {
2915         TRACE_(typelib)("VAR_PERINSTANCE\n");
2916         (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2917         (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2918       }
2919
2920       if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
2921         (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
2922
2923       if (pItem->flags & 0x80)
2924         (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
2925
2926       if(pItem->flags & 0x02)
2927           pType = &pItem->type;
2928       else
2929           pType = (WORD*)(pBlk + pItem->type);
2930
2931       if (pItem->flags & ~0xd2)
2932         FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xd2);
2933
2934       SLTG_DoElem(pType, pBlk,
2935                   &(*ppVarDesc)->vardesc.elemdescVar);
2936
2937       dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2938
2939       bstrPrevName = (*ppVarDesc)->Name;
2940       ppVarDesc = &((*ppVarDesc)->next);
2941   }
2942   pTI->TypeAttr.cVars = cVars;
2943 }
2944
2945 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cFuncs, char *pNameTable)
2946 {
2947     SLTG_Function *pFunc;
2948     unsigned short i;
2949     TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2950
2951     for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
2952         pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
2953
2954         int param;
2955         WORD *pType, *pArg;
2956
2957         *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2958                                 sizeof(**ppFuncDesc));
2959
2960         switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
2961         case SLTG_FUNCTION_MAGIC:
2962             (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
2963             break;
2964         case SLTG_DISPATCH_FUNCTION_MAGIC:
2965             (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
2966             break;
2967         case SLTG_STATIC_FUNCTION_MAGIC:
2968             (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
2969             break;
2970         default:
2971             FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
2972             HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
2973             *ppFuncDesc = NULL;
2974             return;
2975         }
2976         (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2977
2978         (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2979         (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2980         (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2981         (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2982         (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2983         (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2984
2985         if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
2986             (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2987
2988         if(pFunc->retnextopt & 0x80)
2989             pType = &pFunc->rettype;
2990         else
2991             pType = (WORD*)(pBlk + pFunc->rettype);
2992
2993         SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2994
2995         (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2996           HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2997                     (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2998         (*ppFuncDesc)->pParamDesc =
2999           HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3000                     (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3001
3002         pArg = (WORD*)(pBlk + pFunc->arg_off);
3003
3004         for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3005             char *paramName = pNameTable + *pArg;
3006             BOOL HaveOffs;
3007             /* If arg type follows then paramName points to the 2nd
3008                letter of the name, else the next WORD is an offset to
3009                the arg type and paramName points to the first letter.
3010                So let's take one char off paramName and see if we're
3011                pointing at an alpha-numeric char.  However if *pArg is
3012                0xffff or 0xfffe then the param has no name, the former
3013                meaning that the next WORD is the type, the latter
3014                meaning the the next WORD is an offset to the type. */
3015
3016             HaveOffs = FALSE;
3017             if(*pArg == 0xffff)
3018                 paramName = NULL;
3019             else if(*pArg == 0xfffe) {
3020                 paramName = NULL;
3021                 HaveOffs = TRUE;
3022             }
3023             else if(paramName[-1] && !isalnum(paramName[-1]))
3024                 HaveOffs = TRUE;
3025
3026             pArg++;
3027
3028             if(HaveOffs) { /* the next word is an offset to type */
3029                 pType = (WORD*)(pBlk + *pArg);
3030                 SLTG_DoElem(pType, pBlk,
3031                             &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
3032                 pArg++;
3033             } else {
3034                 if(paramName)
3035                   paramName--;
3036                 pArg = SLTG_DoElem(pArg, pBlk,
3037                            &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
3038             }
3039
3040             /* Are we an optional param ? */
3041             if((*ppFuncDesc)->funcdesc.cParams - param <=
3042                (*ppFuncDesc)->funcdesc.cParamsOpt)
3043               (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3044
3045             if(paramName) {
3046                 (*ppFuncDesc)->pParamDesc[param].Name =
3047                   TLB_MultiByteToBSTR(paramName);
3048             }
3049         }
3050
3051         ppFuncDesc = &((*ppFuncDesc)->next);
3052         if(pFunc->next == 0xffff) break;
3053     }
3054     pTI->TypeAttr.cFuncs = cFuncs;
3055 }
3056
3057 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3058                                 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3059                                 SLTG_TypeInfoTail *pTITail)
3060 {
3061     char *pFirstItem, *pNextItem;
3062
3063     if(pTIHeader->href_table != 0xffffffff) {
3064         SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3065                     pNameTable);
3066     }
3067
3068     pFirstItem = pNextItem = pBlk;
3069
3070     if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3071         pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
3072     }
3073 }
3074
3075
3076 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3077                                   char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3078                                   SLTG_TypeInfoTail *pTITail)
3079 {
3080     char *pFirstItem, *pNextItem;
3081
3082     if(pTIHeader->href_table != 0xffffffff) {
3083         SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3084                     pNameTable);
3085     }
3086
3087     pFirstItem = pNextItem = pBlk;
3088
3089     if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3090         pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
3091     }
3092
3093     if (pTITail->funcs_off != 0xffff)
3094         SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3095
3096     if (TRACE_ON(typelib))
3097         dump_TLBFuncDesc(pTI->funclist);
3098 }
3099
3100 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3101                                char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3102                                SLTG_TypeInfoTail *pTITail)
3103 {
3104   SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3105 }
3106
3107 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3108                               char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3109                               SLTG_TypeInfoTail *pTITail)
3110 {
3111   WORD *pType;
3112
3113   if (pTITail->simple_alias) {
3114     /* if simple alias, no more processing required */
3115     pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3116     return;
3117   }
3118
3119   if(pTIHeader->href_table != 0xffffffff) {
3120       SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3121                   pNameTable);
3122   }
3123
3124   /* otherwise it is an offset to a type */
3125   pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3126
3127   SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias);
3128 }
3129
3130 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3131                                  char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3132                                  SLTG_TypeInfoTail *pTITail)
3133 {
3134   if (pTIHeader->href_table != 0xffffffff)
3135       SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3136                                   pNameTable);
3137
3138   if (pTITail->vars_off != 0xffff)
3139     SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3140
3141   if (pTITail->funcs_off != 0xffff)
3142     SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3143
3144   /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3145    * of dispinterface functons including the IDispatch ones, so
3146    * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3147   pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3148
3149   if (TRACE_ON(typelib))
3150       dump_TLBFuncDesc(pTI->funclist);
3151 }
3152
3153 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3154                              char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3155                              SLTG_TypeInfoTail *pTITail)
3156 {
3157   SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3158 }
3159
3160 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3161                                char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3162                                SLTG_TypeInfoTail *pTITail)
3163 {
3164   if (pTIHeader->href_table != 0xffffffff)
3165       SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3166                                   pNameTable);
3167
3168   if (pTITail->vars_off != 0xffff)
3169     SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3170
3171   if (pTITail->funcs_off != 0xffff)
3172     SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3173 }
3174
3175 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3176    managable copy of it into this */
3177 typedef struct {
3178   WORD small_no;
3179   char *index_name;
3180   char *other_name;
3181   WORD res1a;
3182   WORD name_offs;
3183   WORD more_bytes;
3184   char *extra;
3185   WORD res20;
3186   DWORD helpcontext;
3187   WORD res26;
3188   GUID uuid;
3189 } SLTG_InternalOtherTypeInfo;
3190
3191 /****************************************************************************
3192  *      ITypeLib2_Constructor_SLTG
3193  *
3194  * loading a SLTG typelib from an in-memory image
3195  */
3196 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3197 {
3198     ITypeLibImpl *pTypeLibImpl;
3199     SLTG_Header *pHeader;
3200     SLTG_BlkEntry *pBlkEntry;
3201     SLTG_Magic *pMagic;
3202     SLTG_Index *pIndex;
3203     SLTG_Pad9 *pPad9;
3204     LPVOID pBlk, pFirstBlk;
3205     SLTG_LibBlk *pLibBlk;
3206     SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3207     char *pAfterOTIBlks = NULL;
3208     char *pNameTable, *ptr;
3209     int i;
3210     DWORD len, order;
3211     ITypeInfoImpl **ppTypeInfoImpl;
3212
3213     TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3214
3215
3216     pTypeLibImpl = TypeLibImpl_Constructor();
3217     if (!pTypeLibImpl) return NULL;
3218
3219     pHeader = pLib;
3220
3221     TRACE_(typelib)("header:\n");
3222     TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3223           pHeader->nrOfFileBlks );
3224     if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3225         FIXME("Header type magic 0x%08x not supported.\n",
3226               pHeader->SLTG_magic);
3227         return NULL;
3228     }
3229
3230     /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3231     pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3232
3233     /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3234     pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3235
3236     /* Next we have a magic block */
3237     pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3238
3239     /* Let's see if we're still in sync */
3240     if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3241               sizeof(SLTG_COMPOBJ_MAGIC))) {
3242         FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3243         return NULL;
3244     }
3245     if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3246               sizeof(SLTG_DIR_MAGIC))) {
3247         FIXME("dir magic = %s\n", pMagic->dir_magic);
3248         return NULL;
3249     }
3250
3251     pIndex = (SLTG_Index*)(pMagic+1);
3252
3253     pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3254
3255     pFirstBlk = (LPVOID)(pPad9 + 1);
3256
3257     /* We'll set up a ptr to the main library block, which is the last one. */
3258
3259     for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3260           pBlkEntry[order].next != 0;
3261           order = pBlkEntry[order].next - 1, i++) {
3262        pBlk = (char*)pBlk + pBlkEntry[order].len;
3263     }
3264     pLibBlk = pBlk;
3265
3266     len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3267
3268     /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3269        interspersed */
3270
3271     len += 0x40;
3272
3273     /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3274
3275     pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3276                                    sizeof(*pOtherTypeInfoBlks) *
3277                                    pTypeLibImpl->TypeInfoCount);
3278
3279
3280     ptr = (char*)pLibBlk + len;
3281
3282     for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3283         WORD w, extra;
3284         len = 0;
3285
3286         pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3287
3288         w = *(WORD*)(ptr + 2);
3289         if(w != 0xffff) {
3290             len += w;
3291             pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3292                                                          w+1);
3293             memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3294             pOtherTypeInfoBlks[i].index_name[w] = '\0';
3295         }
3296         w = *(WORD*)(ptr + 4 + len);
3297         if(w != 0xffff) {
3298             TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3299             len += w;
3300             pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3301                                                          w+1);
3302             memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3303             pOtherTypeInfoBlks[i].other_name[w] = '\0';
3304         }
3305         pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3306         pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3307         extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3308         if(extra) {
3309             pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3310                                                     extra);
3311             memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3312             len += extra;
3313         }
3314         pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3315         pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3316         pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3317         memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3318         len += sizeof(SLTG_OtherTypeInfo);
3319         ptr += len;
3320     }
3321
3322     pAfterOTIBlks = ptr;
3323
3324     /* Skip this WORD and get the next DWORD */
3325     len = *(DWORD*)(pAfterOTIBlks + 2);
3326
3327     /* Now add this to pLibBLk look at what we're pointing at and
3328        possibly add 0x20, then add 0x216, sprinkle a bit a magic
3329        dust and we should be pointing at the beginning of the name
3330        table */
3331
3332     pNameTable = (char*)pLibBlk + len;
3333
3334    switch(*(WORD*)pNameTable) {
3335    case 0xffff:
3336        break;
3337    case 0x0200:
3338        pNameTable += 0x20;
3339        break;
3340    default:
3341        FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3342        break;
3343    }
3344
3345     pNameTable += 0x216;
3346
3347     pNameTable += 2;
3348
3349     TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3350
3351     pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3352
3353
3354     /* Hopefully we now have enough ptrs set up to actually read in
3355        some TypeInfos.  It's not clear which order to do them in, so
3356        I'll just follow the links along the BlkEntry chain and read
3357        them in the order in which they are in the file */
3358
3359     ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3360
3361     for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3362         pBlkEntry[order].next != 0;
3363         order = pBlkEntry[order].next - 1, i++) {
3364
3365       SLTG_TypeInfoHeader *pTIHeader;
3366       SLTG_TypeInfoTail *pTITail;
3367       SLTG_MemberHeader *pMemHeader;
3368
3369       if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3370                 pOtherTypeInfoBlks[i].index_name)) {
3371         FIXME("Index strings don't match\n");
3372         return NULL;
3373       }
3374
3375       pTIHeader = pBlk;
3376       if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3377         FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3378         return NULL;
3379       }
3380       TRACE("pTIHeader->res06 = %x, pTIHeader->res0e = %x, pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3381         pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3382
3383       *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3384       (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3385       (*ppTypeInfoImpl)->index = i;
3386       (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3387                                              pOtherTypeInfoBlks[i].name_offs +
3388                                              pNameTable);
3389       (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3390       memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3391              sizeof(GUID));
3392       (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3393       (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3394       (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3395       (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3396         (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3397
3398       if((pTIHeader->typeflags1 & 7) != 2)
3399         FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3400       if(pTIHeader->typeflags3 != 2)
3401         FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3402
3403       TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3404             debugstr_w((*ppTypeInfoImpl)->Name),
3405             typekind_desc[pTIHeader->typekind],
3406             debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3407             (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3408
3409       pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3410
3411       pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3412
3413       (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3414       (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3415       (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3416
3417       switch(pTIHeader->typekind) {
3418       case TKIND_ENUM:
3419         SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3420                          pTIHeader, pTITail);
3421         break;
3422
3423       case TKIND_RECORD:
3424         SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3425                            pTIHeader, pTITail);
3426         break;
3427
3428       case TKIND_INTERFACE:
3429         SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3430                               pTIHeader, pTITail);
3431         break;
3432
3433       case TKIND_COCLASS:
3434         SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3435                             pTIHeader, pTITail);
3436         break;
3437
3438       case TKIND_ALIAS:
3439         SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3440                           pTIHeader, pTITail);
3441         break;
3442
3443       case TKIND_DISPATCH:
3444         SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3445                              pTIHeader, pTITail);
3446         break;
3447
3448       case TKIND_MODULE:
3449         SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3450                            pTIHeader, pTITail);
3451         break;
3452
3453       default:
3454         FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3455         break;
3456
3457       }
3458
3459       if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3460                        but we've already set those */
3461 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3462           X(06);
3463           X(16);
3464           X(18);
3465           X(1a);
3466           X(1e);
3467           X(24);
3468           X(26);
3469           X(2a);
3470           X(2c);
3471           X(2e);
3472           X(30);
3473           X(32);
3474           X(34);
3475       }
3476       ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3477       pBlk = (char*)pBlk + pBlkEntry[order].len;
3478     }
3479
3480     if(i != pTypeLibImpl->TypeInfoCount) {
3481       FIXME("Somehow processed %d TypeInfos\n", i);
3482       return NULL;
3483     }
3484
3485     HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3486     return (ITypeLib2*)pTypeLibImpl;
3487 }
3488
3489 /* ITypeLib::QueryInterface
3490  */
3491 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3492         ITypeLib2 * iface,
3493         REFIID riid,
3494         VOID **ppvObject)
3495 {
3496     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3497
3498     TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3499
3500     *ppvObject=NULL;
3501     if(IsEqualIID(riid, &IID_IUnknown) ||
3502        IsEqualIID(riid,&IID_ITypeLib)||
3503        IsEqualIID(riid,&IID_ITypeLib2))
3504     {
3505         *ppvObject = This;
3506     }
3507
3508     if(*ppvObject)
3509     {
3510         ITypeLib2_AddRef(iface);
3511         TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3512         return S_OK;
3513     }
3514     TRACE("-- Interface: E_NOINTERFACE\n");
3515     return E_NOINTERFACE;
3516 }
3517
3518 /* ITypeLib::AddRef
3519  */
3520 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3521 {
3522     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3523     ULONG ref = InterlockedIncrement(&This->ref);
3524
3525     TRACE("(%p)->ref was %u\n",This, ref - 1);
3526
3527     return ref;
3528 }
3529
3530 /* ITypeLib::Release
3531  */
3532 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3533 {
3534     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3535     ULONG ref = InterlockedDecrement(&This->ref);
3536
3537     TRACE("(%p)->(%u)\n",This, ref);
3538
3539     if (!ref)
3540     {
3541       TLBImpLib *pImpLib, *pImpLibNext;
3542       TLBCustData *pCustData, *pCustDataNext;
3543       int i;
3544
3545       /* remove cache entry */
3546       if(This->path)
3547       {
3548           TRACE("removing from cache list\n");
3549           EnterCriticalSection(&cache_section);
3550           if (This->next) This->next->prev = This->prev;
3551           if (This->prev) This->prev->next = This->next;
3552           else tlb_cache_first = This->next;
3553           LeaveCriticalSection(&cache_section);
3554           HeapFree(GetProcessHeap(), 0, This->path);
3555       }
3556       TRACE(" destroying ITypeLib(%p)\n",This);
3557
3558       if (This->Name)
3559       {
3560           SysFreeString(This->Name);
3561           This->Name = NULL;
3562       }
3563
3564       if (This->DocString)
3565       {
3566           SysFreeString(This->DocString);
3567           This->DocString = NULL;
3568       }
3569
3570       if (This->HelpFile)
3571       {
3572           SysFreeString(This->HelpFile);
3573           This->HelpFile = NULL;
3574       }
3575
3576       if (This->HelpStringDll)
3577       {
3578           SysFreeString(This->HelpStringDll);
3579           This->HelpStringDll = NULL;
3580       }
3581
3582       for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
3583       {
3584           VariantClear(&pCustData->data);
3585
3586           pCustDataNext = pCustData->next;
3587           TLB_Free(pCustData);
3588       }
3589
3590       for (i = 0; i < This->ctTypeDesc; i++)
3591           if (This->pTypeDesc[i].vt == VT_CARRAY)
3592               TLB_Free(This->pTypeDesc[i].u.lpadesc);
3593
3594       TLB_Free(This->pTypeDesc);
3595
3596       for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
3597       {
3598           if (pImpLib->pImpTypeLib)
3599               ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
3600           TLB_Free(pImpLib->name);
3601
3602           pImpLibNext = pImpLib->next;
3603           TLB_Free(pImpLib);
3604       }
3605
3606       if (This->pTypeInfo) /* can be NULL */
3607           ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3608       HeapFree(GetProcessHeap(),0,This);
3609       return 0;
3610     }
3611
3612     return ref;
3613 }
3614
3615 /* ITypeLib::GetTypeInfoCount
3616  *
3617  * Returns the number of type descriptions in the type library
3618  */
3619 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3620 {
3621     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3622     TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3623     return This->TypeInfoCount;
3624 }
3625
3626 /* ITypeLib::GetTypeInfo
3627  *
3628  * retrieves the specified type description in the library.
3629  */
3630 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3631     ITypeLib2 *iface,
3632     UINT index,
3633     ITypeInfo **ppTInfo)
3634 {
3635     int i;
3636
3637     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3638     ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3639
3640     TRACE("(%p)->(index=%d)\n", This, index);
3641
3642     if (!ppTInfo) return E_INVALIDARG;
3643
3644     /* search element n in list */
3645     for(i=0; i < index; i++)
3646     {
3647       pTypeInfo = pTypeInfo->next;
3648       if (!pTypeInfo)
3649       {
3650         TRACE("-- element not found\n");
3651         return TYPE_E_ELEMENTNOTFOUND;
3652       }
3653     }
3654
3655     *ppTInfo = (ITypeInfo *) pTypeInfo;
3656
3657     ITypeInfo_AddRef(*ppTInfo);
3658     TRACE("-- found (%p)\n",*ppTInfo);
3659     return S_OK;
3660 }
3661
3662
3663 /* ITypeLibs::GetTypeInfoType
3664  *
3665  * Retrieves the type of a type description.
3666  */
3667 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3668     ITypeLib2 *iface,
3669     UINT index,
3670     TYPEKIND *pTKind)
3671 {
3672     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3673     int i;
3674     ITypeInfoImpl *pTInfo = This->pTypeInfo;
3675     
3676     if ((ITypeLib2_fnGetTypeInfoCount(iface) < index + 1) || (index < 0))
3677          return TYPE_E_ELEMENTNOTFOUND;
3678
3679     TRACE("(%p) index %d\n", This, index);
3680
3681     if(!pTKind) return E_INVALIDARG;
3682
3683     /* search element n in list */
3684     for(i=0; i < index; i++)
3685     {
3686       if(!pTInfo)
3687       {
3688         TRACE("-- element not found\n");
3689         return TYPE_E_ELEMENTNOTFOUND;
3690       }
3691       pTInfo = pTInfo->next;
3692     }
3693
3694     *pTKind = pTInfo->TypeAttr.typekind;
3695     TRACE("-- found Type (%d)\n", *pTKind);
3696     return S_OK;
3697 }
3698
3699 /* ITypeLib::GetTypeInfoOfGuid
3700  *
3701  * Retrieves the type description that corresponds to the specified GUID.
3702  *
3703  */
3704 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3705     ITypeLib2 *iface,
3706     REFGUID guid,
3707     ITypeInfo **ppTInfo)
3708 {
3709     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3710     ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3711
3712     TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3713
3714     if (!pTypeInfo)
3715     {
3716         WARN("-- element not found\n");
3717         return TYPE_E_ELEMENTNOTFOUND;
3718     }
3719
3720     /* search linked list for guid */
3721     while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3722     {
3723       pTypeInfo = pTypeInfo->next;
3724
3725       if (!pTypeInfo)
3726       {
3727         /* end of list reached */
3728         WARN("-- element not found\n");
3729         return TYPE_E_ELEMENTNOTFOUND;
3730       }
3731     }
3732
3733     TRACE("-- found (%p, %s)\n",
3734           pTypeInfo,
3735           debugstr_w(pTypeInfo->Name));
3736
3737     *ppTInfo = (ITypeInfo*)pTypeInfo;
3738     ITypeInfo_AddRef(*ppTInfo);
3739     return S_OK;
3740 }
3741
3742 /* ITypeLib::GetLibAttr
3743  *
3744  * Retrieves the structure that contains the library's attributes.
3745  *
3746  */
3747 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3748         ITypeLib2 *iface,
3749         LPTLIBATTR *ppTLibAttr)
3750 {
3751     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3752     TRACE("(%p)\n",This);
3753     *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3754     memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3755     return S_OK;
3756 }
3757
3758 /* ITypeLib::GetTypeComp
3759  *
3760  * Enables a client compiler to bind to a library's types, variables,
3761  * constants, and global functions.
3762  *
3763  */
3764 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3765         ITypeLib2 *iface,
3766         ITypeComp **ppTComp)
3767 {
3768     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3769
3770     TRACE("(%p)->(%p)\n",This,ppTComp);
3771     *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3772     ITypeComp_AddRef(*ppTComp);
3773
3774     return S_OK;
3775 }
3776
3777 /* ITypeLib::GetDocumentation
3778  *
3779  * Retrieves the library's documentation string, the complete Help file name
3780  * and path, and the context identifier for the library Help topic in the Help
3781  * file.
3782  *
3783  * On a successful return all non-null BSTR pointers will have been set,
3784  * possibly to NULL.
3785  */
3786 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3787     ITypeLib2 *iface,
3788     INT index,
3789     BSTR *pBstrName,
3790     BSTR *pBstrDocString,
3791     DWORD *pdwHelpContext,
3792     BSTR *pBstrHelpFile)
3793 {
3794     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3795
3796     HRESULT result = E_INVALIDARG;
3797
3798     ITypeInfo *pTInfo;
3799
3800
3801     TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3802         This, index,
3803         pBstrName, pBstrDocString,
3804         pdwHelpContext, pBstrHelpFile);
3805
3806     if(index<0)
3807     {
3808         /* documentation for the typelib */
3809         if(pBstrName)
3810         {
3811             if (This->Name)
3812             {
3813                 if(!(*pBstrName = SysAllocString(This->Name)))
3814                     goto memerr1;
3815             }
3816             else
3817                 *pBstrName = NULL;
3818         }
3819         if(pBstrDocString)
3820         {
3821             if (This->DocString)
3822             {
3823                 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3824                     goto memerr2;
3825             }
3826             else if (This->Name)
3827             {
3828                 if(!(*pBstrDocString = SysAllocString(This->Name)))
3829                     goto memerr2;
3830             }
3831             else
3832                 *pBstrDocString = NULL;
3833         }
3834         if(pdwHelpContext)
3835         {
3836             *pdwHelpContext = This->dwHelpContext;
3837         }
3838         if(pBstrHelpFile)
3839         {
3840             if (This->HelpFile)
3841             {
3842                 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3843                     goto memerr3;
3844             }
3845             else
3846                 *pBstrHelpFile = NULL;
3847         }
3848
3849         result = S_OK;
3850     }
3851     else
3852     {
3853         /* for a typeinfo */
3854         result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3855
3856         if(SUCCEEDED(result))
3857         {
3858             result = ITypeInfo_GetDocumentation(pTInfo,
3859                                           MEMBERID_NIL,
3860                                           pBstrName,
3861                                           pBstrDocString,
3862                                           pdwHelpContext, pBstrHelpFile);
3863
3864             ITypeInfo_Release(pTInfo);
3865         }
3866     }
3867     return result;
3868 memerr3:
3869     if (pBstrDocString) SysFreeString (*pBstrDocString);
3870 memerr2:
3871     if (pBstrName) SysFreeString (*pBstrName);
3872 memerr1:
3873     return STG_E_INSUFFICIENTMEMORY;
3874 }
3875
3876 /* ITypeLib::IsName
3877  *
3878  * Indicates whether a passed-in string contains the name of a type or member
3879  * described in the library.
3880  *
3881  */
3882 static HRESULT WINAPI ITypeLib2_fnIsName(
3883         ITypeLib2 *iface,
3884         LPOLESTR szNameBuf,
3885         ULONG lHashVal,
3886         BOOL *pfName)
3887 {
3888     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3889     ITypeInfoImpl *pTInfo;
3890     TLBFuncDesc *pFInfo;
3891     TLBVarDesc *pVInfo;
3892     int i;
3893     UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3894
3895     TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3896           pfName);
3897
3898     *pfName=TRUE;
3899     for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3900         if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3901         for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3902             if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3903             for(i=0;i<pFInfo->funcdesc.cParams;i++)
3904                 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3905                     goto ITypeLib2_fnIsName_exit;
3906         }
3907         for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3908             if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3909
3910     }
3911     *pfName=FALSE;
3912
3913 ITypeLib2_fnIsName_exit:
3914     TRACE("(%p)slow! search for %s: %s found!\n", This,
3915           debugstr_w(szNameBuf), *pfName?"NOT":"");
3916
3917     return S_OK;
3918 }
3919
3920 /* ITypeLib::FindName
3921  *
3922  * Finds occurrences of a type description in a type library. This may be used
3923  * to quickly verify that a name exists in a type library.
3924  *
3925  */
3926 static HRESULT WINAPI ITypeLib2_fnFindName(
3927         ITypeLib2 *iface,
3928         LPOLESTR szNameBuf,
3929         ULONG lHashVal,
3930         ITypeInfo **ppTInfo,
3931         MEMBERID *rgMemId,
3932         UINT16 *pcFound)
3933 {
3934     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3935     ITypeInfoImpl *pTInfo;
3936     TLBFuncDesc *pFInfo;
3937     TLBVarDesc *pVInfo;
3938     int i,j = 0;
3939     UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3940
3941     for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3942         if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3943         for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3944             if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3945             for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3946                 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3947                     goto ITypeLib2_fnFindName_exit;
3948             }
3949         }
3950         for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3951             if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3952         continue;
3953 ITypeLib2_fnFindName_exit:
3954         ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3955         ppTInfo[j]=(LPTYPEINFO)pTInfo;
3956         j++;
3957     }
3958     TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3959           This, *pcFound, debugstr_w(szNameBuf), j);
3960
3961     *pcFound=j;
3962
3963     return S_OK;
3964 }
3965
3966 /* ITypeLib::ReleaseTLibAttr
3967  *
3968  * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3969  *
3970  */
3971 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3972         ITypeLib2 *iface,
3973         TLIBATTR *pTLibAttr)
3974 {
3975     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3976     TRACE("freeing (%p)\n",This);
3977     HeapFree(GetProcessHeap(),0,pTLibAttr);
3978
3979 }
3980
3981 /* ITypeLib2::GetCustData
3982  *
3983  * gets the custom data
3984  */
3985 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3986         ITypeLib2 * iface,
3987         REFGUID guid,
3988         VARIANT *pVarVal)
3989 {
3990     ITypeLibImpl *This = (ITypeLibImpl *)iface;
3991     TLBCustData *pCData;
3992
3993     for(pCData=This->pCustData; pCData; pCData = pCData->next)
3994     {
3995       if( IsEqualIID(guid, &pCData->guid)) break;
3996     }
3997
3998     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3999
4000     if(pCData)
4001     {
4002         VariantInit( pVarVal);
4003         VariantCopy( pVarVal, &pCData->data);
4004         return S_OK;
4005     }
4006     return E_INVALIDARG;  /* FIXME: correct? */
4007 }
4008
4009 /* ITypeLib2::GetLibStatistics
4010  *
4011  * Returns statistics about a type library that are required for efficient
4012  * sizing of hash tables.
4013  *
4014  */
4015 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4016         ITypeLib2 * iface,
4017         ULONG *pcUniqueNames,
4018         ULONG *pcchUniqueNames)
4019 {
4020     ITypeLibImpl *This = (ITypeLibImpl *)iface;
4021
4022     FIXME("(%p): stub!\n", This);
4023
4024     if(pcUniqueNames) *pcUniqueNames=1;
4025     if(pcchUniqueNames) *pcchUniqueNames=1;
4026     return S_OK;
4027 }
4028
4029 /* ITypeLib2::GetDocumentation2
4030  *
4031  * Retrieves the library's documentation string, the complete Help file name
4032  * and path, the localization context to use, and the context ID for the
4033  * library Help topic in the Help file.
4034  *
4035  */
4036 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4037         ITypeLib2 * iface,
4038         INT index,
4039         LCID lcid,
4040         BSTR *pbstrHelpString,
4041         DWORD *pdwHelpStringContext,
4042         BSTR *pbstrHelpStringDll)
4043 {
4044     ITypeLibImpl *This = (ITypeLibImpl *)iface;
4045     HRESULT result;
4046     ITypeInfo *pTInfo;
4047
4048     FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4049
4050     /* the help string should be obtained from the helpstringdll,
4051      * using the _DLLGetDocumentation function, based on the supplied
4052      * lcid. Nice to do sometime...
4053      */
4054     if(index<0)
4055     {
4056       /* documentation for the typelib */
4057       if(pbstrHelpString)
4058         *pbstrHelpString=SysAllocString(This->DocString);
4059       if(pdwHelpStringContext)
4060         *pdwHelpStringContext=This->dwHelpContext;
4061       if(pbstrHelpStringDll)
4062         *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4063
4064       result = S_OK;
4065     }
4066     else
4067     {
4068       /* for a typeinfo */
4069       result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4070
4071       if(SUCCEEDED(result))
4072       {
4073         ITypeInfo2 * pTInfo2;
4074         result = ITypeInfo_QueryInterface(pTInfo,
4075                                           &IID_ITypeInfo2,
4076                                           (LPVOID*) &pTInfo2);
4077
4078         if(SUCCEEDED(result))
4079         {
4080           result = ITypeInfo2_GetDocumentation2(pTInfo2,
4081                                            MEMBERID_NIL,
4082                                            lcid,
4083                                            pbstrHelpString,
4084                                            pdwHelpStringContext,
4085                                            pbstrHelpStringDll);
4086
4087           ITypeInfo2_Release(pTInfo2);
4088         }
4089
4090         ITypeInfo_Release(pTInfo);
4091       }
4092     }
4093     return result;
4094 }
4095
4096 /* ITypeLib2::GetAllCustData
4097  *
4098  * Gets all custom data items for the library.
4099  *
4100  */
4101 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4102         ITypeLib2 * iface,
4103         CUSTDATA *pCustData)
4104 {
4105     ITypeLibImpl *This = (ITypeLibImpl *)iface;
4106     TLBCustData *pCData;
4107     int i;
4108     TRACE("(%p) returning %d items\n", This, This->ctCustData);
4109     pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4110     if(pCustData->prgCustData ){
4111         pCustData->cCustData=This->ctCustData;
4112         for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4113             pCustData->prgCustData[i].guid=pCData->guid;
4114             VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4115         }
4116     }else{
4117         ERR(" OUT OF MEMORY!\n");
4118         return E_OUTOFMEMORY;
4119     }
4120     return S_OK;
4121 }
4122
4123 static const ITypeLib2Vtbl tlbvt = {
4124     ITypeLib2_fnQueryInterface,
4125     ITypeLib2_fnAddRef,
4126     ITypeLib2_fnRelease,
4127     ITypeLib2_fnGetTypeInfoCount,
4128     ITypeLib2_fnGetTypeInfo,
4129     ITypeLib2_fnGetTypeInfoType,
4130     ITypeLib2_fnGetTypeInfoOfGuid,
4131     ITypeLib2_fnGetLibAttr,
4132     ITypeLib2_fnGetTypeComp,
4133     ITypeLib2_fnGetDocumentation,
4134     ITypeLib2_fnIsName,
4135     ITypeLib2_fnFindName,
4136     ITypeLib2_fnReleaseTLibAttr,
4137
4138     ITypeLib2_fnGetCustData,
4139     ITypeLib2_fnGetLibStatistics,
4140     ITypeLib2_fnGetDocumentation2,
4141     ITypeLib2_fnGetAllCustData
4142  };
4143
4144
4145 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4146 {
4147     ITypeLibImpl *This = impl_from_ITypeComp(iface);
4148
4149     return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4150 }
4151
4152 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4153 {
4154     ITypeLibImpl *This = impl_from_ITypeComp(iface);
4155
4156     return ITypeLib2_AddRef((ITypeLib2 *)This);
4157 }
4158
4159 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4160 {
4161     ITypeLibImpl *This = impl_from_ITypeComp(iface);
4162
4163     return ITypeLib2_Release((ITypeLib2 *)This);
4164 }
4165
4166 static HRESULT WINAPI ITypeLibComp_fnBind(
4167     ITypeComp * iface,
4168     OLECHAR * szName,
4169     ULONG lHash,
4170     WORD wFlags,
4171     ITypeInfo ** ppTInfo,
4172     DESCKIND * pDescKind,
4173     BINDPTR * pBindPtr)
4174 {
4175     ITypeLibImpl *This = impl_from_ITypeComp(iface);
4176     ITypeInfoImpl *pTypeInfo;
4177
4178     TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4179
4180     *pDescKind = DESCKIND_NONE;
4181     pBindPtr->lptcomp = NULL;
4182     *ppTInfo = NULL;
4183
4184     for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4185     {
4186         TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4187
4188         /* FIXME: check wFlags here? */
4189         /* FIXME: we should use a hash table to look this info up using lHash
4190          * instead of an O(n) search */
4191         if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4192             (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4193         {
4194             if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4195             {
4196                 *pDescKind = DESCKIND_TYPECOMP;
4197                 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4198                 ITypeComp_AddRef(pBindPtr->lptcomp);
4199                 TRACE("module or enum: %s\n", debugstr_w(szName));
4200                 return S_OK;
4201             }
4202         }
4203
4204         if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4205             (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4206         {
4207             ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4208             HRESULT hr;
4209
4210             hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4211             if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4212             {
4213                 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4214                 return S_OK;
4215             }
4216         }
4217
4218         if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4219             (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4220         {
4221             ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4222             HRESULT hr;
4223             ITypeInfo *subtypeinfo;
4224             BINDPTR subbindptr;
4225             DESCKIND subdesckind;
4226
4227             hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4228                 &subtypeinfo, &subdesckind, &subbindptr);
4229             if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4230             {
4231                 TYPEDESC tdesc_appobject =
4232                 {
4233                     {
4234                         (TYPEDESC *)pTypeInfo->hreftype
4235                     },
4236                     VT_USERDEFINED
4237                 };
4238                 const VARDESC vardesc_appobject =
4239                 {
4240                     -2,         /* memid */
4241                     NULL,       /* lpstrSchema */
4242                     {
4243                         0       /* oInst */
4244                     },
4245                     {
4246                                 /* ELEMDESC */
4247                         {
4248                                 /* TYPEDESC */
4249                                 {
4250                                     &tdesc_appobject
4251                                 },
4252                                 VT_PTR
4253                         },
4254                     },
4255                     0,          /* wVarFlags */
4256                     VAR_STATIC  /* varkind */
4257                 };
4258
4259                 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4260
4261                 /* cleanup things filled in by Bind call so we can put our
4262                  * application object data in there instead */
4263                 switch (subdesckind)
4264                 {
4265                 case DESCKIND_FUNCDESC:
4266                     ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4267                     break;
4268                 case DESCKIND_VARDESC:
4269                     ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4270                     break;
4271                 default:
4272                     break;
4273                 }
4274                 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4275
4276                 if (pTypeInfo->hreftype == -1)
4277                     FIXME("no hreftype for interface %p\n", pTypeInfo);
4278
4279                 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4280                 if (FAILED(hr))
4281                     return hr;
4282
4283                 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4284                 *ppTInfo = (ITypeInfo *)pTypeInfo;
4285                 ITypeInfo_AddRef(*ppTInfo);
4286                 return S_OK;
4287             }
4288         }
4289     }
4290
4291     TRACE("name not found %s\n", debugstr_w(szName));
4292     return S_OK;
4293 }
4294
4295 static HRESULT WINAPI ITypeLibComp_fnBindType(
4296     ITypeComp * iface,
4297     OLECHAR * szName,
4298     ULONG lHash,
4299     ITypeInfo ** ppTInfo,
4300     ITypeComp ** ppTComp)
4301 {
4302     FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4303     return E_NOTIMPL;
4304 }
4305
4306 static const ITypeCompVtbl tlbtcvt =
4307 {
4308
4309     ITypeLibComp_fnQueryInterface,
4310     ITypeLibComp_fnAddRef,
4311     ITypeLibComp_fnRelease,
4312
4313     ITypeLibComp_fnBind,
4314     ITypeLibComp_fnBindType
4315 };
4316
4317 /*================== ITypeInfo(2) Methods ===================================*/
4318 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4319 {
4320     ITypeInfoImpl * pTypeInfoImpl;
4321
4322     pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4323     if (pTypeInfoImpl)
4324     {
4325       pTypeInfoImpl->lpVtbl = &tinfvt;
4326       pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4327       pTypeInfoImpl->ref=1;
4328       pTypeInfoImpl->hreftype = -1;
4329       pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4330       pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4331     }
4332     TRACE("(%p)\n", pTypeInfoImpl);
4333     return (ITypeInfo2*) pTypeInfoImpl;
4334 }
4335
4336 /* ITypeInfo::QueryInterface
4337  */
4338 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4339         ITypeInfo2 *iface,
4340         REFIID riid,
4341         VOID **ppvObject)
4342 {
4343     ITypeLibImpl *This = (ITypeLibImpl *)iface;
4344
4345     TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4346
4347     *ppvObject=NULL;
4348     if(IsEqualIID(riid, &IID_IUnknown) ||
4349             IsEqualIID(riid,&IID_ITypeInfo)||
4350             IsEqualIID(riid,&IID_ITypeInfo2))
4351         *ppvObject = This;
4352
4353     if(*ppvObject){
4354         ITypeInfo_AddRef(iface);
4355         TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4356         return S_OK;
4357     }
4358     TRACE("-- Interface: E_NOINTERFACE\n");
4359     return E_NOINTERFACE;
4360 }
4361
4362 /* ITypeInfo::AddRef
4363  */
4364 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4365 {
4366     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4367     ULONG ref = InterlockedIncrement(&This->ref);
4368
4369     ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4370
4371     TRACE("(%p)->ref is %u\n",This, ref);
4372     return ref;
4373 }
4374
4375 /* ITypeInfo::Release
4376  */
4377 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4378 {
4379     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4380     ULONG ref = InterlockedDecrement(&This->ref);
4381
4382     TRACE("(%p)->(%u)\n",This, ref);
4383
4384     if (ref)   {
4385       /* We don't release ITypeLib when ref=0 because
4386          it means that function is called by ITypeLib2_Release */
4387       ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4388     } else   {
4389       TLBFuncDesc *pFInfo, *pFInfoNext;
4390       TLBVarDesc *pVInfo, *pVInfoNext;
4391       TLBImplType *pImpl, *pImplNext;
4392       TLBRefType *pRefType,*pRefTypeNext;
4393       TLBCustData *pCustData, *pCustDataNext;
4394
4395       TRACE("destroying ITypeInfo(%p)\n",This);
4396
4397       if (This->no_free_data)
4398           goto finish_free;
4399
4400       if (This->Name)
4401       {
4402           SysFreeString(This->Name);
4403           This->Name = 0;
4404       }
4405
4406       if (This->DocString)
4407       {
4408           SysFreeString(This->DocString);
4409           This->DocString = 0;
4410       }
4411
4412       if (This->DllName)
4413       {
4414           SysFreeString(This->DllName);
4415           This->DllName = 0;
4416       }
4417
4418       for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4419       {
4420           UINT i;
4421           for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4422           {
4423               ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4424               if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4425               {
4426                   VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4427                   TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4428               }
4429               SysFreeString(pFInfo->pParamDesc[i].Name);
4430           }
4431           TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4432           TLB_Free(pFInfo->pParamDesc);
4433           for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4434           {
4435               VariantClear(&pCustData->data);
4436
4437               pCustDataNext = pCustData->next;
4438               TLB_Free(pCustData);
4439           }
4440           SysFreeString(pFInfo->Entry);
4441           SysFreeString(pFInfo->HelpString);
4442           SysFreeString(pFInfo->Name);
4443
4444           pFInfoNext = pFInfo->next;
4445           TLB_Free(pFInfo);
4446       }
4447       for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4448       {
4449           if (pVInfo->vardesc.varkind == VAR_CONST)
4450           {
4451               VariantClear(pVInfo->vardesc.u.lpvarValue);
4452               TLB_Free(pVInfo->vardesc.u.lpvarValue);
4453           }
4454           SysFreeString(pVInfo->Name);
4455           pVInfoNext = pVInfo->next;
4456           TLB_Free(pVInfo);
4457       }
4458       for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4459       {
4460           for (pCustData = pImpl->pCustData; pCustData; pCustData = pCustDataNext)
4461           {
4462               VariantClear(&pCustData->data);
4463
4464               pCustDataNext = pCustData->next;
4465               TLB_Free(pCustData);
4466           }
4467           pImplNext = pImpl->next;
4468           TLB_Free(pImpl);
4469       }
4470       for(pRefType = This->reflist; pRefType; pRefType = pRefTypeNext)
4471       {
4472           pRefTypeNext = pRefType->next;
4473           TLB_Free(pRefType);
4474       }
4475       TLB_Free(This->pCustData);
4476
4477 finish_free:
4478       if (This->next)
4479       {
4480         ITypeInfo_Release((ITypeInfo*)This->next);
4481       }
4482
4483       HeapFree(GetProcessHeap(),0,This);
4484       return 0;
4485     }
4486     return ref;
4487 }
4488
4489 /* ITypeInfo::GetTypeAttr
4490  *
4491  * Retrieves a TYPEATTR structure that contains the attributes of the type
4492  * description.
4493  *
4494  */
4495 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4496         LPTYPEATTR  *ppTypeAttr)
4497 {
4498     const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4499     SIZE_T size;
4500
4501     TRACE("(%p)\n",This);
4502
4503     size = sizeof(**ppTypeAttr);
4504     if (This->TypeAttr.typekind == TKIND_ALIAS)
4505         size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4506
4507     *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4508     if (!*ppTypeAttr)
4509         return E_OUTOFMEMORY;
4510
4511     memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4512
4513     if (This->TypeAttr.typekind == TKIND_ALIAS)
4514         TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4515             &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4516
4517     if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4518         (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4519                                                                  funcs */
4520         (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4521         (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4522     }
4523     return S_OK;
4524 }
4525
4526 /* ITypeInfo::GetTypeComp
4527  *
4528  * Retrieves the ITypeComp interface for the type description, which enables a
4529  * client compiler to bind to the type description's members.
4530  *
4531  */
4532 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4533         ITypeComp  * *ppTComp)
4534 {
4535     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4536
4537     TRACE("(%p)->(%p)\n", This, ppTComp);
4538
4539     *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4540     ITypeComp_AddRef(*ppTComp);
4541     return S_OK;
4542 }
4543
4544 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4545 {
4546     SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4547     if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4548         size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4549     return size;
4550 }
4551
4552 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4553 {
4554     memcpy(dest, src, sizeof(ELEMDESC));
4555     *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4556     if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4557     {
4558         const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4559         PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4560         *buffer += sizeof(PARAMDESCEX);
4561         memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4562         VariantInit(&pparamdescex_dest->varDefaultValue);
4563         return VariantCopy(&pparamdescex_dest->varDefaultValue, 
4564                            (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4565     }
4566     else
4567         dest->u.paramdesc.pparamdescex = NULL;
4568     return S_OK;
4569 }
4570
4571 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4572 {
4573     if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4574         VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4575 }
4576
4577 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4578 {
4579     FUNCDESC *dest;
4580     char *buffer;
4581     SIZE_T size = sizeof(*src);
4582     SHORT i;
4583     HRESULT hr;
4584
4585     size += sizeof(*src->lprgscode) * src->cScodes;
4586     size += TLB_SizeElemDesc(&src->elemdescFunc);
4587     for (i = 0; i < src->cParams; i++)
4588     {
4589         size += sizeof(ELEMDESC);
4590         size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4591     }
4592
4593     dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4594     if (!dest) return E_OUTOFMEMORY;
4595
4596     memcpy(dest, src, sizeof(FUNCDESC));
4597     buffer = (char *)(dest + 1);
4598
4599     dest->lprgscode = (SCODE *)buffer;
4600     memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4601     buffer += sizeof(*src->lprgscode) * src->cScodes;
4602
4603     hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4604     if (FAILED(hr))
4605     {
4606         SysFreeString((BSTR)dest);
4607         return hr;
4608     }
4609
4610     dest->lprgelemdescParam = (ELEMDESC *)buffer;
4611     buffer += sizeof(ELEMDESC) * src->cParams;
4612     for (i = 0; i < src->cParams; i++)
4613     {
4614         hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4615         if (FAILED(hr))
4616             break;
4617     }
4618     if (FAILED(hr))
4619     {
4620         /* undo the above actions */
4621         for (i = i - 1; i >= 0; i--)
4622             TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4623         TLB_FreeElemDesc(&dest->elemdescFunc);
4624         SysFreeString((BSTR)dest);
4625         return hr;
4626     }
4627
4628     /* special treatment for dispinterfaces: this makes functions appear
4629      * to return their [retval] value when it is really returning an
4630      * HRESULT */
4631     if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4632     {
4633         if (dest->cParams &&
4634             (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4635         {
4636             ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4637             if (elemdesc->tdesc.vt != VT_PTR)
4638             {
4639                 ERR("elemdesc should have started with VT_PTR instead of:\n");
4640                 if (ERR_ON(ole))
4641                     dump_ELEMDESC(elemdesc);
4642                 return E_UNEXPECTED;
4643             }
4644
4645             /* copy last parameter to the return value. we are using a flat
4646              * buffer so there is no danger of leaking memory in
4647              * elemdescFunc */
4648             dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4649
4650             /* remove the last parameter */
4651             dest->cParams--;
4652         }
4653         else
4654             /* otherwise this function is made to appear to have no return
4655              * value */
4656             dest->elemdescFunc.tdesc.vt = VT_VOID;
4657
4658     }
4659
4660     *dest_ptr = dest;
4661     return S_OK;
4662 }
4663
4664 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4665 {
4666     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4667     const TLBFuncDesc *pFDesc;
4668     int i;
4669
4670     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4671         ;
4672
4673     if (pFDesc)
4674     {
4675         *ppFuncDesc = &pFDesc->funcdesc;
4676         return S_OK;
4677     }
4678
4679     return E_INVALIDARG;
4680 }
4681
4682 /* internal function to make the inherited interfaces' methods appear
4683  * part of the interface */
4684 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
4685     UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs)
4686 {
4687     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4688     HRESULT hr;
4689     UINT i;
4690     UINT implemented_funcs = 0;
4691
4692     if (funcs)
4693         *funcs = 0;
4694
4695     for (i = 0; i < This->TypeAttr.cImplTypes; i++)
4696     {
4697         HREFTYPE href;
4698         ITypeInfo *pSubTypeInfo;
4699         UINT sub_funcs;
4700
4701         hr = ITypeInfo_GetRefTypeOfImplType(iface, i, &href);
4702         if (FAILED(hr))
4703             return hr;
4704         hr = ITypeInfo_GetRefTypeInfo(iface, href, &pSubTypeInfo);
4705         if (FAILED(hr))
4706             return hr;
4707
4708         hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
4709                                                        index,
4710                                                        ppFuncDesc,
4711                                                        &sub_funcs);
4712         implemented_funcs += sub_funcs;
4713         ITypeInfo_Release(pSubTypeInfo);
4714         if (SUCCEEDED(hr))
4715             return hr;
4716     }
4717
4718     if (funcs)
4719         *funcs = implemented_funcs + This->TypeAttr.cFuncs;
4720     
4721     if (index < implemented_funcs)
4722         return E_INVALIDARG;
4723     return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
4724                                              ppFuncDesc);
4725 }
4726
4727 /* ITypeInfo::GetFuncDesc
4728  *
4729  * Retrieves the FUNCDESC structure that contains information about a
4730  * specified function.
4731  *
4732  */
4733 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4734         LPFUNCDESC  *ppFuncDesc)
4735 {
4736     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4737     const FUNCDESC *internal_funcdesc;
4738     HRESULT hr;
4739
4740     TRACE("(%p) index %d\n", This, index);
4741
4742     if ((This->TypeAttr.typekind == TKIND_DISPATCH) &&
4743         (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4744         hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
4745                                                        &internal_funcdesc, NULL);
4746     else
4747         hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
4748                                                &internal_funcdesc);
4749     if (FAILED(hr))
4750     {
4751         WARN("description for function %d not found\n", index);
4752         return hr;
4753     }
4754
4755     return TLB_AllocAndInitFuncDesc(
4756         internal_funcdesc,
4757         ppFuncDesc,
4758         This->TypeAttr.typekind == TKIND_DISPATCH);
4759 }
4760
4761 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4762 {
4763     VARDESC *dest;
4764     char *buffer;
4765     SIZE_T size = sizeof(*src);
4766     HRESULT hr;
4767
4768     if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4769     if (src->varkind == VAR_CONST)
4770         size += sizeof(VARIANT);
4771     size += TLB_SizeElemDesc(&src->elemdescVar);
4772
4773     dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4774     if (!dest) return E_OUTOFMEMORY;
4775
4776     *dest = *src;
4777     buffer = (char *)(dest + 1);
4778     if (src->lpstrSchema)
4779     {
4780         int len;
4781         dest->lpstrSchema = (LPOLESTR)buffer;
4782         len = strlenW(src->lpstrSchema);
4783         memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4784         buffer += (len + 1) * sizeof(WCHAR);
4785     }
4786
4787     if (src->varkind == VAR_CONST)
4788     {
4789         HRESULT hr;
4790
4791         dest->u.lpvarValue = (VARIANT *)buffer;
4792         *dest->u.lpvarValue = *src->u.lpvarValue;
4793         buffer += sizeof(VARIANT);
4794         VariantInit(dest->u.lpvarValue);
4795         hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4796         if (FAILED(hr))
4797         {
4798             SysFreeString((BSTR)dest_ptr);
4799             return hr;
4800         }
4801     }
4802     hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4803     if (FAILED(hr))
4804     {
4805         if (src->varkind == VAR_CONST)
4806             VariantClear(dest->u.lpvarValue);
4807         SysFreeString((BSTR)dest);
4808         return hr;
4809     }
4810     *dest_ptr = dest;
4811     return S_OK;
4812 }
4813
4814 /* ITypeInfo::GetVarDesc
4815  *
4816  * Retrieves a VARDESC structure that describes the specified variable.
4817  *
4818  */
4819 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4820         LPVARDESC  *ppVarDesc)
4821 {
4822     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4823     int i;
4824     const TLBVarDesc *pVDesc;
4825
4826     TRACE("(%p) index %d\n", This, index);
4827
4828     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4829         ;
4830
4831     if (pVDesc)
4832         return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4833
4834     return E_INVALIDARG;
4835 }
4836
4837 /* ITypeInfo_GetNames
4838  *
4839  * Retrieves the variable with the specified member ID (or the name of the
4840  * property or method and its parameters) that correspond to the specified
4841  * function ID.
4842  */
4843 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4844         BSTR  *rgBstrNames, UINT cMaxNames, UINT  *pcNames)
4845 {
4846     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4847     const TLBFuncDesc *pFDesc;
4848     const TLBVarDesc *pVDesc;
4849     int i;
4850     TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
4851     for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4852     if(pFDesc)
4853     {
4854       /* function found, now return function and parameter names */
4855       for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4856       {
4857         if(!i)
4858           *rgBstrNames=SysAllocString(pFDesc->Name);
4859         else
4860           rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4861       }
4862       *pcNames=i;
4863     }
4864     else
4865     {
4866       for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4867       if(pVDesc)
4868       {
4869         *rgBstrNames=SysAllocString(pVDesc->Name);
4870         *pcNames=1;
4871       }
4872       else
4873       {
4874         if(This->TypeAttr.cImplTypes &&
4875            (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4876           /* recursive search */
4877           ITypeInfo *pTInfo;
4878           HRESULT result;
4879           result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4880                                           &pTInfo);
4881           if(SUCCEEDED(result))
4882           {
4883             result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4884             ITypeInfo_Release(pTInfo);
4885             return result;
4886           }
4887           WARN("Could not search inherited interface!\n");
4888         }
4889         else
4890         {
4891           WARN("no names found\n");
4892         }
4893         *pcNames=0;
4894         return TYPE_E_ELEMENTNOTFOUND;
4895       }
4896     }
4897     return S_OK;
4898 }
4899
4900
4901 /* ITypeInfo::GetRefTypeOfImplType
4902  *
4903  * If a type description describes a COM class, it retrieves the type
4904  * description of the implemented interface types. For an interface,
4905  * GetRefTypeOfImplType returns the type information for inherited interfaces,
4906  * if any exist.
4907  *
4908  */
4909 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4910         ITypeInfo2 *iface,
4911         UINT index,
4912         HREFTYPE  *pRefType)
4913 {
4914     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4915     int i;
4916     HRESULT hr = S_OK;
4917     const TLBImplType *pImpl = This->impltypelist;
4918
4919     TRACE("(%p) index %d\n", This, index);
4920     if (TRACE_ON(ole)) dump_TypeInfo(This);
4921
4922     if(index==(UINT)-1)
4923     {
4924       /* only valid on dual interfaces;
4925          retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4926       */
4927       if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4928
4929       if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4930           This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4931       {
4932         *pRefType = -1;
4933       }
4934       else
4935       {
4936         hr = TYPE_E_ELEMENTNOTFOUND;
4937       }
4938     }
4939     else
4940     {
4941       /* get element n from linked list */
4942       for(i=0; pImpl && i<index; i++)
4943       {
4944         pImpl = pImpl->next;
4945       }
4946
4947       if (pImpl)
4948         *pRefType = pImpl->hRef;
4949       else
4950         hr = TYPE_E_ELEMENTNOTFOUND;
4951     }
4952
4953     if(TRACE_ON(ole))
4954     {
4955         if(SUCCEEDED(hr))
4956             TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
4957         else
4958             TRACE("FAILURE -- hresult = 0x%08x\n", hr);
4959     }
4960
4961     return hr;
4962 }
4963
4964 /* ITypeInfo::GetImplTypeFlags
4965  *
4966  * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4967  * or base interface in a type description.
4968  */
4969 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4970         UINT index, INT  *pImplTypeFlags)
4971 {
4972     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4973     int i;
4974     TLBImplType *pImpl;
4975
4976     TRACE("(%p) index %d\n", This, index);
4977     for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4978         i++, pImpl=pImpl->next)
4979         ;
4980     if(i==index && pImpl){
4981         *pImplTypeFlags=pImpl->implflags;
4982         return S_OK;
4983     }
4984     *pImplTypeFlags=0;
4985     return TYPE_E_ELEMENTNOTFOUND;
4986 }
4987
4988 /* GetIDsOfNames
4989  * Maps between member names and member IDs, and parameter names and
4990  * parameter IDs.
4991  */
4992 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4993         LPOLESTR  *rgszNames, UINT cNames, MEMBERID  *pMemId)
4994 {
4995     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4996     const TLBFuncDesc *pFDesc;
4997     const TLBVarDesc *pVDesc;
4998     HRESULT ret=S_OK;
4999     int i;
5000
5001     TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5002             cNames);
5003
5004     /* init out parameters in case of failure */
5005     for (i = 0; i < cNames; i++)
5006         pMemId[i] = MEMBERID_NIL;
5007
5008     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5009         int j;
5010         if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5011             if(cNames) *pMemId=pFDesc->funcdesc.memid;
5012             for(i=1; i < cNames; i++){
5013                 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5014                     if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5015                             break;
5016                 if( j<pFDesc->funcdesc.cParams)
5017                     pMemId[i]=j;
5018                 else
5019                    ret=DISP_E_UNKNOWNNAME;
5020             };
5021             TRACE("-- 0x%08x\n", ret);
5022             return ret;
5023         }
5024     }
5025     for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5026         if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5027             if(cNames) *pMemId=pVDesc->vardesc.memid;
5028             return ret;
5029         }
5030     }
5031     /* not found, see if it can be found in an inherited interface */
5032     if(This->TypeAttr.cImplTypes) {
5033         /* recursive search */
5034         ITypeInfo *pTInfo;
5035         ret=ITypeInfo_GetRefTypeInfo(iface,
5036                 This->impltypelist->hRef, &pTInfo);
5037         if(SUCCEEDED(ret)){
5038             ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5039             ITypeInfo_Release(pTInfo);
5040             return ret;
5041         }
5042         WARN("Could not search inherited interface!\n");
5043     } else
5044         WARN("no names found\n");
5045     return DISP_E_UNKNOWNNAME;
5046 }
5047
5048 /* ITypeInfo::Invoke
5049  *
5050  * Invokes a method, or accesses a property of an object, that implements the
5051  * interface described by the type description.
5052  */
5053 DWORD
5054 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5055     DWORD res;
5056
5057     if (TRACE_ON(ole)) {
5058         int i;
5059         TRACE("Calling %p(",func);
5060         for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5061         TRACE(")\n");
5062     }
5063
5064     switch (callconv) {
5065     case CC_STDCALL:
5066
5067         switch (nrargs) {
5068         case 0:
5069                 res = func();
5070                 break;
5071         case 1:
5072                 res = func(args[0]);
5073                 break;
5074         case 2:
5075                 res = func(args[0],args[1]);
5076                 break;
5077         case 3:
5078                 res = func(args[0],args[1],args[2]);
5079                 break;
5080         case 4:
5081                 res = func(args[0],args[1],args[2],args[3]);
5082                 break;
5083         case 5:
5084                 res = func(args[0],args[1],args[2],args[3],args[4]);
5085                 break;
5086         case 6:
5087                 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5088                 break;
5089         case 7:
5090                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5091                 break;
5092         case 8:
5093                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5094                 break;
5095         case 9:
5096                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5097                 break;
5098         case 10:
5099                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5100                 break;
5101         case 11:
5102                 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5103                 break;
5104         case 12:
5105                 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]);
5106                 break;
5107         case 13:
5108                 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]);
5109                 break;
5110         case 14:
5111                 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]);
5112                 break;
5113         case 15:
5114                 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]);
5115                 break;
5116         case 16:
5117                 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]);
5118                 break;
5119         case 17:
5120                 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]);
5121                 break;
5122         case 18:
5123                 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]);
5124                 break;
5125         case 19:
5126                 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]);
5127                 break;
5128         case 20:
5129                 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]);
5130                 break;
5131         case 21:
5132                 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]);
5133                 break;
5134         case 22:
5135                 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]);
5136                 break;
5137         case 23:
5138                 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]);
5139                 break;
5140         default:
5141                 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5142                 res = -1;
5143                 break;
5144         }
5145         break;
5146     default:
5147         FIXME("unsupported calling convention %d\n",callconv);
5148         res = -1;
5149         break;
5150     }
5151     TRACE("returns %08x\n",res);
5152     return res;
5153 }
5154
5155 extern int _argsize(DWORD vt);
5156
5157 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5158 {
5159     HRESULT hr = S_OK;
5160     ITypeInfo *tinfo2 = NULL;
5161     TYPEATTR *tattr = NULL;
5162
5163     hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5164     if (hr)
5165     {
5166         ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5167             "hr = 0x%08x\n",
5168               tdesc->u.hreftype, hr);
5169         return hr;
5170     }
5171     hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5172     if (hr)
5173     {
5174         ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5175         ITypeInfo_Release(tinfo2);
5176         return hr;
5177     }
5178
5179     switch (tattr->typekind)
5180     {
5181     case TKIND_ENUM:
5182         *vt |= VT_I4;
5183         break;
5184
5185     case TKIND_ALIAS:
5186         tdesc = &tattr->tdescAlias;
5187         hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5188         break;
5189
5190     case TKIND_INTERFACE:
5191         if (IsEqualIID(&IID_IDispatch, &tattr->guid))
5192            *vt |= VT_DISPATCH;
5193         else
5194            *vt |= VT_UNKNOWN;
5195         break;
5196
5197     case TKIND_DISPATCH:
5198         *vt |= VT_DISPATCH;
5199         break;
5200
5201     case TKIND_COCLASS:
5202         *vt |= VT_UNKNOWN;
5203         break;
5204
5205     case TKIND_RECORD:
5206         FIXME("TKIND_RECORD unhandled.\n");
5207         hr = E_NOTIMPL;
5208         break;
5209
5210     case TKIND_UNION:
5211         FIXME("TKIND_UNION unhandled.\n");
5212         hr = E_NOTIMPL;
5213         break;
5214
5215     default:
5216         FIXME("TKIND %d unhandled.\n",tattr->typekind);
5217         hr = E_NOTIMPL;
5218         break;
5219     }
5220     ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5221     ITypeInfo_Release(tinfo2);
5222     return hr;
5223 }
5224
5225 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5226 {
5227     HRESULT hr = S_OK;
5228
5229     /* enforce only one level of pointer indirection */
5230     if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5231     {
5232         tdesc = tdesc->u.lptdesc;
5233
5234         /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5235          * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into 
5236          * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5237         if ((tdesc->vt == VT_USERDEFINED) ||
5238             ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5239         {
5240             VARTYPE vt_userdefined = 0;
5241             const TYPEDESC *tdesc_userdefined = tdesc;
5242             if (tdesc->vt == VT_PTR)
5243             {
5244                 vt_userdefined = VT_BYREF;
5245                 tdesc_userdefined = tdesc->u.lptdesc;
5246             }
5247             hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5248             if ((hr == S_OK) && 
5249                 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5250                  ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5251             {
5252                 *vt |= vt_userdefined;
5253                 return S_OK;
5254             }
5255         }
5256         *vt = VT_BYREF;
5257     }
5258
5259     switch (tdesc->vt)
5260     {
5261     case VT_HRESULT:
5262         *vt |= VT_ERROR;
5263         break;
5264     case VT_USERDEFINED:
5265         hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5266         break;
5267     case VT_VOID:
5268     case VT_CARRAY:
5269     case VT_PTR:
5270     case VT_LPSTR:
5271     case VT_LPWSTR:
5272         ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5273         hr = DISP_E_BADVARTYPE;
5274         break;
5275     case VT_SAFEARRAY:
5276         *vt |= VT_ARRAY;
5277         hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5278         break;
5279     default:
5280         *vt |= tdesc->vt;
5281         break;
5282     }
5283     return hr;
5284 }
5285
5286 /***********************************************************************
5287  *              DispCallFunc (OLEAUT32.@)
5288  *
5289  * Invokes a function of the specifed calling convention, passing the
5290  * specified arguments and returns the result.
5291  *
5292  * PARAMS
5293  *  pvInstance  [I] Optional pointer to the instance whose function to invoke.
5294  *  oVft        [I] The offset in the vtable. See notes.
5295  *  cc          [I] Calling convention of the function to call.
5296  *  vtReturn    [I] The return type of the function.
5297  *  cActuals    [I] Number of parameters.
5298  *  prgvt       [I] The types of the parameters to pass. This is used for sizing only.
5299  *  prgpvarg    [I] The arguments to pass.
5300  *  pvargResult [O] The return value of the function. Can be NULL.
5301  *
5302  * RETURNS
5303  *  Success: S_OK.
5304  *  Failure: HRESULT code.
5305  *
5306  * NOTES
5307  *  The HRESULT return value of this function is not affected by the return
5308  *  value of the user supplied function, which is returned in pvargResult.
5309  *
5310  *  If pvInstance is NULL then a non-object function is to be called and oVft
5311  *  is the address of the function to call.
5312  *
5313  * The cc parameter can be one of the following values:
5314  *|CC_FASTCALL
5315  *|CC_CDECL
5316  *|CC_PASCAL
5317  *|CC_STDCALL
5318  *|CC_FPFASTCALL
5319  *|CC_SYSCALL
5320  *|CC_MPWCDECL
5321  *|CC_MPWPASCAL
5322  *
5323  */
5324 HRESULT WINAPI
5325 DispCallFunc(
5326     void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5327     VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5328 {
5329     int i, argsize, argspos;
5330     DWORD *args;
5331     HRESULT hres;
5332
5333     TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5334         pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5335         pvargResult, V_VT(pvargResult));
5336
5337     argsize = 0;
5338     if (pvInstance)
5339         argsize++; /* for This pointer */
5340
5341     for (i=0;i<cActuals;i++)
5342     {
5343         TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5344         dump_Variant(prgpvarg[i]);
5345         argsize += _argsize(prgvt[i]);
5346     }
5347     args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5348
5349     argspos = 0;
5350     if (pvInstance)
5351     {
5352         args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5353         argspos++;
5354     }
5355
5356     for (i=0;i<cActuals;i++)
5357     {
5358         VARIANT *arg = prgpvarg[i];
5359         TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5360         if (prgvt[i] == VT_VARIANT)
5361             memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5362         else
5363             memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5364         argspos += _argsize(prgvt[i]);
5365     }
5366
5367     if (pvInstance)
5368     {
5369         FARPROC *vtable = *(FARPROC**)pvInstance;
5370         hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5371     }
5372     else
5373         /* if we aren't invoking an object then the function pointer is stored
5374          * in oVft */
5375         hres = _invoke((FARPROC)oVft, cc, argsize, args);
5376
5377     if (pvargResult && (vtReturn != VT_EMPTY))
5378     {
5379         TRACE("Method returned 0x%08x\n",hres);
5380         V_VT(pvargResult) = vtReturn;
5381         V_UI4(pvargResult) = hres;
5382     }
5383
5384     HeapFree(GetProcessHeap(),0,args);
5385     return S_OK;
5386 }
5387
5388 #define INVBUF_ELEMENT_SIZE \
5389     (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5390 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5391     ((VARIANTARG *)(buffer))
5392 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5393     ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5394 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5395     ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5396 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5397     ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5398
5399 static HRESULT WINAPI ITypeInfo_fnInvoke(
5400     ITypeInfo2 *iface,
5401     VOID  *pIUnk,
5402     MEMBERID memid,
5403     UINT16 wFlags,
5404     DISPPARAMS  *pDispParams,
5405     VARIANT  *pVarResult,
5406     EXCEPINFO  *pExcepInfo,
5407     UINT  *pArgErr)
5408 {
5409     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5410     int i;
5411     unsigned int var_index;
5412     TYPEKIND type_kind;
5413     HRESULT hres;
5414     const TLBFuncDesc *pFuncInfo;
5415
5416     TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5417       This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5418     );
5419
5420     if (!pDispParams)
5421     {
5422         ERR("NULL pDispParams not allowed\n");
5423         return E_INVALIDARG;
5424     }
5425
5426     dump_DispParms(pDispParams);
5427
5428     if (pDispParams->cNamedArgs > pDispParams->cArgs)
5429     {
5430         ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5431             pDispParams->cNamedArgs, pDispParams->cArgs);
5432         return E_INVALIDARG;
5433     }
5434
5435     /* we do this instead of using GetFuncDesc since it will return a fake
5436      * FUNCDESC for dispinterfaces and we want the real function description */
5437     for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5438         if ((memid == pFuncInfo->funcdesc.memid) &&
5439             (wFlags & pFuncInfo->funcdesc.invkind))
5440             break;
5441
5442     if (pFuncInfo) {
5443         const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5444
5445         if (TRACE_ON(ole))
5446         {
5447             TRACE("invoking:\n");
5448             dump_TLBFuncDescOne(pFuncInfo);
5449         }
5450         
5451         switch (func_desc->funckind) {
5452         case FUNC_PUREVIRTUAL:
5453         case FUNC_VIRTUAL: {
5454             void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5455             VARIANT varresult;
5456             VARIANT retval; /* pointer for storing byref retvals in */
5457             VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5458             VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5459             VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5460
5461             hres = S_OK;
5462             for (i = 0; i < func_desc->cParams; i++)
5463             {
5464                 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5465                 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5466                 if (FAILED(hres))
5467                     goto func_fail;
5468             }
5469
5470             TRACE("changing args\n");
5471             for (i = 0; i < func_desc->cParams; i++)
5472             {
5473                 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5474
5475                 if (wParamFlags & PARAMFLAG_FRETVAL)
5476                 {
5477                     /* note: this check is placed so that if the caller passes
5478                      * in a VARIANTARG for the retval we just ignore it, like
5479                      * native does */
5480                     if (i == func_desc->cParams - 1)
5481                     {
5482                         VARIANTARG *arg;
5483                         arg = prgpvarg[i] = &rgvarg[i];
5484                         memset(arg, 0, sizeof(*arg));
5485                         V_VT(arg) = rgvt[i];
5486                         memset(&retval, 0, sizeof(retval));
5487                         V_BYREF(arg) = &retval;
5488                     }
5489                     else
5490                     {
5491                         ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5492                         hres = E_UNEXPECTED;
5493                         break;
5494                     }
5495                 }
5496                 else if (i < pDispParams->cArgs)
5497                 {
5498                     VARIANTARG *src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5499                     dump_Variant(src_arg);
5500
5501                     if (rgvt[i] == VT_VARIANT)
5502                         hres = VariantCopy(&rgvarg[i], src_arg);
5503                     else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5504                     {
5505                         if (rgvt[i] == V_VT(src_arg))
5506                             V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5507                         else
5508                         {
5509                             VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5510                             hres = VariantCopy(&missing_arg[i], src_arg);
5511                             V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5512                         }
5513                         V_VT(&rgvarg[i]) = rgvt[i];
5514                     }
5515                     else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5516                     {
5517                         VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5518                         V_VT(&missing_arg[i]) = V_VT(src_arg);
5519                         hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5520                         V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5521                         V_VT(&rgvarg[i]) = rgvt[i];
5522                     }
5523                     else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5524                     {
5525                         V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5526                         V_VT(&rgvarg[i]) = rgvt[i];
5527                     }
5528                     else
5529                     {
5530                         /* FIXME: this doesn't work for VT_BYREF arguments if
5531                          * they are not the same type as in the paramdesc */
5532                         V_VT(&rgvarg[i]) = V_VT(src_arg);
5533                         hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5534                         V_VT(&rgvarg[i]) = rgvt[i];
5535                     }
5536
5537                     if (FAILED(hres))
5538                     {
5539                         ERR("failed to convert param %d to %s%s from %s%s\n", i,
5540                             debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5541                             debugstr_VT(src_arg), debugstr_VF(src_arg));
5542                         break;
5543                     }
5544                     prgpvarg[i] = &rgvarg[i];
5545                 }
5546                 else if (wParamFlags & PARAMFLAG_FOPT)
5547                 {
5548                     VARIANTARG *arg;
5549                     arg = prgpvarg[i] = &rgvarg[i];
5550                     if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5551                     {
5552                         hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5553                         if (FAILED(hres))
5554                             break;
5555                     }
5556                     else
5557                     {
5558                         VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5559                         V_VT(arg) = VT_VARIANT | VT_BYREF;
5560                         V_VARIANTREF(arg) = &missing_arg[i];
5561                         V_VT(V_VARIANTREF(arg)) = VT_ERROR;
5562                         V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND;
5563                     }
5564                 }
5565                 else
5566                 {
5567                     hres = DISP_E_BADPARAMCOUNT;
5568                     break;
5569                 }
5570             }
5571             if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5572             if (func_desc->cParamsOpt < 0)
5573             {
5574                 FIXME("Does not support safearray optional parameters\n");
5575                 hres = DISP_E_BADPARAMCOUNT;
5576                 goto func_fail; /* FIXME: we don't free changed types here */
5577             }
5578
5579             /* VT_VOID is a special case for return types, so it is not
5580              * handled in the general function */
5581             if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
5582                 V_VT(&varresult) = VT_EMPTY;
5583             else
5584             {
5585                 V_VT(&varresult) = 0;
5586                 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5587                 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5588             }
5589
5590             hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5591                                 V_VT(&varresult), func_desc->cParams, rgvt,
5592                                 prgpvarg, &varresult);
5593
5594             for (i = 0; i < func_desc->cParams; i++)
5595             {
5596                 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5597                 if (wParamFlags & PARAMFLAG_FRETVAL)
5598                 {
5599                     if (TRACE_ON(ole))
5600                     {
5601                         TRACE("[retval] value: ");
5602                         dump_Variant(prgpvarg[i]);
5603                     }
5604
5605                     if (pVarResult)
5606                     {
5607                         VariantInit(pVarResult);
5608                         /* deref return value */
5609                         hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5610                     }
5611
5612                     /* free data stored in varresult. Note that
5613                      * VariantClear doesn't do what we want because we are
5614                      * working with byref types. */
5615                     /* FIXME: clear safearrays, bstrs, records and
5616                      * variants here too */
5617                     if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5618                          (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5619                     {
5620                         if(*V_UNKNOWNREF(prgpvarg[i]))
5621                             IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5622                     }
5623                     break;
5624                 }
5625                 else if (i < pDispParams->cArgs)
5626                 {
5627                     if (wParamFlags & PARAMFLAG_FOUT)
5628                     {
5629                         VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5630
5631                         if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5632                             hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5633
5634                         if (FAILED(hres))
5635                         {
5636                             ERR("failed to convert param %d to vt %d\n", i,
5637                                 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5638                             break;
5639                         }
5640                     }
5641                     VariantClear(&rgvarg[i]);
5642                 }
5643                 else if (wParamFlags & PARAMFLAG_FOPT)
5644                 {
5645                     if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5646                         VariantClear(&rgvarg[i]);
5647                 }
5648             }
5649
5650             if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5651             {
5652                 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
5653                 hres = DISP_E_EXCEPTION;
5654                 if (pExcepInfo) pExcepInfo->scode = V_ERROR(&varresult);
5655             }
5656
5657 func_fail:
5658             HeapFree(GetProcessHeap(), 0, buffer);
5659             break;
5660         }
5661         case FUNC_DISPATCH:  {
5662            IDispatch *disp;
5663
5664            hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5665            if (SUCCEEDED(hres)) {
5666                FIXME("Calling Invoke in IDispatch iface. untested!\n");
5667                hres = IDispatch_Invoke(
5668                                      disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5669                                      pVarResult,pExcepInfo,pArgErr
5670                                      );
5671                if (FAILED(hres))
5672                    FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
5673                IDispatch_Release(disp);
5674            } else
5675                FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5676            break;
5677         }
5678         default:
5679             FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5680             hres = E_FAIL;
5681             break;
5682         }
5683
5684         TRACE("-- 0x%08x\n", hres);
5685         return hres;
5686
5687     } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5688         VARDESC *var_desc;
5689
5690         hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5691         if(FAILED(hres)) return hres;
5692         
5693         FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5694         dump_VARDESC(var_desc);
5695         ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5696         return E_NOTIMPL;
5697     }
5698
5699     /* not found, look for it in inherited interfaces */
5700     ITypeInfo2_GetTypeKind(iface, &type_kind);
5701     if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5702         HREFTYPE ref_type;
5703         if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5704             /* recursive search */
5705             ITypeInfo *pTInfo;
5706             hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5707             if(SUCCEEDED(hres)){
5708                 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5709                 ITypeInfo_Release(pTInfo);
5710                 return hres;
5711             }
5712             WARN("Could not search inherited interface!\n");
5713         }
5714     }
5715     ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
5716     return DISP_E_MEMBERNOTFOUND;
5717 }
5718
5719 /* ITypeInfo::GetDocumentation
5720  *
5721  * Retrieves the documentation string, the complete Help file name and path,
5722  * and the context ID for the Help topic for a specified type description.
5723  *
5724  * (Can be tested by the Visual Basic Editor in Word for instance.)
5725  */
5726 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5727         MEMBERID memid, BSTR  *pBstrName, BSTR  *pBstrDocString,
5728         DWORD  *pdwHelpContext, BSTR  *pBstrHelpFile)
5729 {
5730     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5731     const TLBFuncDesc *pFDesc;
5732     const TLBVarDesc *pVDesc;
5733     TRACE("(%p) memid %d Name(%p) DocString(%p)"
5734           " HelpContext(%p) HelpFile(%p)\n",
5735         This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5736     if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5737         if(pBstrName)
5738             *pBstrName=SysAllocString(This->Name);
5739         if(pBstrDocString)
5740             *pBstrDocString=SysAllocString(This->DocString);
5741         if(pdwHelpContext)
5742             *pdwHelpContext=This->dwHelpContext;
5743         if(pBstrHelpFile)
5744             *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5745         return S_OK;
5746     }else {/* for a member */
5747     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5748         if(pFDesc->funcdesc.memid==memid){
5749           if(pBstrName)
5750             *pBstrName = SysAllocString(pFDesc->Name);
5751           if(pBstrDocString)
5752             *pBstrDocString=SysAllocString(pFDesc->HelpString);
5753           if(pdwHelpContext)
5754             *pdwHelpContext=pFDesc->helpcontext;
5755           return S_OK;
5756         }
5757     for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5758         if(pVDesc->vardesc.memid==memid){
5759             if(pBstrName)
5760               *pBstrName = SysAllocString(pVDesc->Name);
5761             if(pBstrDocString)
5762               *pBstrDocString=SysAllocString(pVDesc->HelpString);
5763             if(pdwHelpContext)
5764               *pdwHelpContext=pVDesc->HelpContext;
5765             return S_OK;
5766         }
5767     }
5768
5769     if(This->TypeAttr.cImplTypes &&
5770        (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5771         /* recursive search */
5772         ITypeInfo *pTInfo;
5773         HRESULT result;
5774         result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5775                                         &pTInfo);
5776         if(SUCCEEDED(result)) {
5777             result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
5778                 pBstrDocString, pdwHelpContext, pBstrHelpFile);
5779             ITypeInfo_Release(pTInfo);
5780             return result;
5781         }
5782         WARN("Could not search inherited interface!\n");
5783     }
5784
5785     WARN("member %d not found\n", memid);
5786     return TYPE_E_ELEMENTNOTFOUND;
5787 }
5788
5789 /*  ITypeInfo::GetDllEntry
5790  *
5791  * Retrieves a description or specification of an entry point for a function
5792  * in a DLL.
5793  */
5794 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5795         INVOKEKIND invKind, BSTR  *pBstrDllName, BSTR  *pBstrName,
5796         WORD  *pwOrdinal)
5797 {
5798     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5799     const TLBFuncDesc *pFDesc;
5800
5801     TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5802
5803     if (pBstrDllName) *pBstrDllName = NULL;
5804     if (pBstrName) *pBstrName = NULL;
5805     if (pwOrdinal) *pwOrdinal = 0;
5806
5807     if (This->TypeAttr.typekind != TKIND_MODULE)
5808         return TYPE_E_BADMODULEKIND;
5809
5810     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5811         if(pFDesc->funcdesc.memid==memid){
5812             dump_TypeInfo(This);
5813             if (TRACE_ON(ole))
5814                 dump_TLBFuncDescOne(pFDesc);
5815
5816             if (pBstrDllName)
5817                 *pBstrDllName = SysAllocString(This->DllName);
5818
5819             if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5820                 if (pBstrName)
5821                     *pBstrName = SysAllocString(pFDesc->Entry);
5822                 if (pwOrdinal)
5823                     *pwOrdinal = -1;
5824                 return S_OK;
5825             }
5826             if (pBstrName)
5827                 *pBstrName = NULL;
5828             if (pwOrdinal)
5829                 *pwOrdinal = (DWORD)pFDesc->Entry;
5830             return S_OK;
5831         }
5832     return TYPE_E_ELEMENTNOTFOUND;
5833 }
5834
5835 /* ITypeInfo::GetRefTypeInfo
5836  *
5837  * If a type description references other type descriptions, it retrieves
5838  * the referenced type descriptions.
5839  */
5840 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5841         ITypeInfo2 *iface,
5842         HREFTYPE hRefType,
5843         ITypeInfo  **ppTInfo)
5844 {
5845     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5846     HRESULT result = E_FAIL;
5847
5848     if ((This->hreftype != -1) && (This->hreftype == hRefType))
5849     {
5850         *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5851         ITypeInfo_AddRef(*ppTInfo);
5852         result = S_OK;
5853     }
5854     else if (hRefType == -1 &&
5855         (((ITypeInfoImpl*) This)->TypeAttr.typekind   == TKIND_DISPATCH) &&
5856         (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags &  TYPEFLAG_FDUAL))
5857     {
5858           /* when we meet a DUAL dispinterface, we must create the interface
5859           * version of it.
5860           */
5861           ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5862
5863
5864           /* the interface version contains the same information as the dispinterface
5865            * copy the contents of the structs.
5866            */
5867           *pTypeInfoImpl = *This;
5868           pTypeInfoImpl->ref = 0;
5869
5870           /* change the type to interface */
5871           pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5872
5873           *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5874
5875           /* we use data structures from This, so we need to keep a reference
5876            * to it to stop it being destroyed and signal to the new instance to
5877            * not free its data structures when it is destroyed */
5878           pTypeInfoImpl->no_free_data = TRUE;
5879           pTypeInfoImpl->next = This;
5880           ITypeInfo_AddRef((ITypeInfo*) This);
5881
5882           ITypeInfo_AddRef(*ppTInfo);
5883
5884           result = S_OK;
5885
5886     } else {
5887         TLBRefType *pRefType;
5888         for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5889             if(pRefType->reference == hRefType)
5890                 break;
5891         }
5892         if(!pRefType)
5893           FIXME("Can't find pRefType for ref %x\n", hRefType);
5894         if(pRefType && hRefType != -1) {
5895             ITypeLib *pTLib = NULL;
5896
5897             if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5898                 UINT Index;
5899                 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5900             } else {
5901                 if(pRefType->pImpTLInfo->pImpTypeLib) {
5902                     TRACE("typeinfo in imported typelib that is already loaded\n");
5903                     pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5904                     ITypeLib2_AddRef((ITypeLib*) pTLib);
5905                     result = S_OK;
5906                 } else {
5907                     TRACE("typeinfo in imported typelib that isn't already loaded\n");
5908                     result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5909                                              pRefType->pImpTLInfo->wVersionMajor,
5910                                              pRefType->pImpTLInfo->wVersionMinor,
5911                                              pRefType->pImpTLInfo->lcid,
5912                                              &pTLib);
5913
5914                     if(!SUCCEEDED(result)) {
5915                         BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5916                         result=LoadTypeLib(libnam, &pTLib);
5917                         SysFreeString(libnam);
5918                     }
5919                     if(SUCCEEDED(result)) {
5920                         pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5921                         ITypeLib2_AddRef(pTLib);
5922                     }
5923                 }
5924             }
5925             if(SUCCEEDED(result)) {
5926                 if(pRefType->index == TLB_REF_USE_GUID)
5927                     result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5928                                                          &pRefType->guid,
5929                                                          ppTInfo);
5930                 else
5931                     result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5932                                                    ppTInfo);
5933             }
5934             if (pTLib != NULL)
5935                 ITypeLib2_Release(pTLib);
5936         }
5937     }
5938
5939     TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
5940           SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5941     return result;
5942 }
5943
5944 /* ITypeInfo::AddressOfMember
5945  *
5946  * Retrieves the addresses of static functions or variables, such as those
5947  * defined in a DLL.
5948  */
5949 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5950         MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5951 {
5952     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5953     HRESULT hr;
5954     BSTR dll, entry;
5955     WORD ordinal;
5956     HMODULE module;
5957
5958     TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
5959
5960     hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
5961     if (FAILED(hr))
5962         return hr;
5963
5964     module = LoadLibraryW(dll);
5965     if (!module)
5966     {
5967         ERR("couldn't load %s\n", debugstr_w(dll));
5968         SysFreeString(dll);
5969         if (entry) SysFreeString(entry);
5970         return STG_E_FILENOTFOUND;
5971     }
5972     /* FIXME: store library somewhere where we can free it */
5973
5974     if (entry)
5975     {
5976         LPSTR entryA;
5977         INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
5978         entryA = HeapAlloc(GetProcessHeap(), 0, len);
5979         WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
5980
5981         *ppv = GetProcAddress(module, entryA);
5982         if (!*ppv)
5983             ERR("function not found %s\n", debugstr_a(entryA));
5984
5985         HeapFree(GetProcessHeap(), 0, entryA);
5986     }
5987     else
5988     {
5989         *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
5990         if (!*ppv)
5991             ERR("function not found %d\n", ordinal);
5992     }
5993
5994     SysFreeString(dll);
5995     if (entry) SysFreeString(entry);
5996
5997     if (!*ppv)
5998         return TYPE_E_DLLFUNCTIONNOTFOUND;
5999
6000     return S_OK;
6001 }
6002
6003 /* ITypeInfo::CreateInstance
6004  *
6005  * Creates a new instance of a type that describes a component object class
6006  * (coclass).
6007  */
6008 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6009         IUnknown *pOuterUnk, REFIID riid, VOID  **ppvObj)
6010 {
6011     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6012     HRESULT hr;
6013     TYPEATTR *pTA;
6014
6015     TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6016
6017     *ppvObj = NULL;
6018
6019     if(pOuterUnk)
6020     {
6021         WARN("Not able to aggregate\n");
6022         return CLASS_E_NOAGGREGATION;
6023     }
6024
6025     hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6026     if(FAILED(hr)) return hr;
6027
6028     if(pTA->typekind != TKIND_COCLASS)
6029     {
6030         WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6031         hr = E_INVALIDARG;
6032         goto end;
6033     }
6034
6035     hr = S_FALSE;
6036     if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6037     {
6038         IUnknown *pUnk;
6039         hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6040         TRACE("GetActiveObject rets %08x\n", hr);
6041         if(hr == S_OK)
6042         {
6043             hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6044             IUnknown_Release(pUnk);
6045         }
6046     }
6047
6048     if(hr != S_OK)
6049         hr = CoCreateInstance(&pTA->guid, NULL,
6050                               CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6051                               riid, ppvObj);
6052
6053 end:
6054     ITypeInfo_ReleaseTypeAttr(iface, pTA);
6055     return hr;
6056 }
6057
6058 /* ITypeInfo::GetMops
6059  *
6060  * Retrieves marshalling information.
6061  */
6062 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6063                                 BSTR  *pBstrMops)
6064 {
6065     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6066     FIXME("(%p) stub!\n", This);
6067     return S_OK;
6068 }
6069
6070 /* ITypeInfo::GetContainingTypeLib
6071  *
6072  * Retrieves the containing type library and the index of the type description
6073  * within that type library.
6074  */
6075 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6076         ITypeLib  * *ppTLib, UINT  *pIndex)
6077 {
6078     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6079     
6080     /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6081     if (pIndex) {
6082       *pIndex=This->index;
6083       TRACE("returning pIndex=%d\n", *pIndex);
6084     }
6085     
6086     if (ppTLib) {
6087       *ppTLib=(LPTYPELIB )(This->pTypeLib);
6088       ITypeLib2_AddRef(*ppTLib);
6089       TRACE("returning ppTLib=%p\n", *ppTLib);
6090     }
6091     
6092     return S_OK;
6093 }
6094
6095 /* ITypeInfo::ReleaseTypeAttr
6096  *
6097  * Releases a TYPEATTR previously returned by GetTypeAttr.
6098  *
6099  */
6100 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6101         TYPEATTR* pTypeAttr)
6102 {
6103     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6104     TRACE("(%p)->(%p)\n", This, pTypeAttr);
6105     HeapFree(GetProcessHeap(), 0, pTypeAttr);
6106 }
6107
6108 /* ITypeInfo::ReleaseFuncDesc
6109  *
6110  * Releases a FUNCDESC previously returned by GetFuncDesc. *
6111  */
6112 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6113         ITypeInfo2 *iface,
6114         FUNCDESC *pFuncDesc)
6115 {
6116     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6117     SHORT i;
6118
6119     TRACE("(%p)->(%p)\n", This, pFuncDesc);
6120
6121     for (i = 0; i < pFuncDesc->cParams; i++)
6122         TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6123     TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6124
6125     SysFreeString((BSTR)pFuncDesc);
6126 }
6127
6128 /* ITypeInfo::ReleaseVarDesc
6129  *
6130  * Releases a VARDESC previously returned by GetVarDesc.
6131  */
6132 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6133         VARDESC *pVarDesc)
6134 {
6135     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6136     TRACE("(%p)->(%p)\n", This, pVarDesc);
6137
6138     TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6139     if (pVarDesc->varkind == VAR_CONST)
6140         VariantClear(pVarDesc->u.lpvarValue);
6141     SysFreeString((BSTR)pVarDesc);
6142 }
6143
6144 /* ITypeInfo2::GetTypeKind
6145  *
6146  * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6147  *
6148  */
6149 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6150     TYPEKIND *pTypeKind)
6151 {
6152     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6153     *pTypeKind=This->TypeAttr.typekind;
6154     TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6155     return S_OK;
6156 }
6157
6158 /* ITypeInfo2::GetTypeFlags
6159  *
6160  * Returns the type flags without any allocations. This returns a DWORD type
6161  * flag, which expands the type flags without growing the TYPEATTR (type
6162  * attribute).
6163  *
6164  */
6165 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6166 {
6167     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6168     *pTypeFlags=This->TypeAttr.wTypeFlags;
6169     TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6170     return S_OK;
6171 }
6172
6173 /* ITypeInfo2::GetFuncIndexOfMemId
6174  * Binds to a specific member based on a known DISPID, where the member name
6175  * is not known (for example, when binding to a default member).
6176  *
6177  */
6178 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6179     MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6180 {
6181     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6182     const TLBFuncDesc *pFuncInfo;
6183     int i;
6184     HRESULT result;
6185
6186     for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6187         if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6188             break;
6189     if(pFuncInfo) {
6190         *pFuncIndex = i;
6191         result = S_OK;
6192     } else
6193         result = TYPE_E_ELEMENTNOTFOUND;
6194
6195     TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6196           memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6197     return result;
6198 }
6199
6200 /* TypeInfo2::GetVarIndexOfMemId
6201  *
6202  * Binds to a specific member based on a known DISPID, where the member name
6203  * is not known (for example, when binding to a default member).
6204  *
6205  */
6206 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6207     MEMBERID memid, UINT *pVarIndex)
6208 {
6209     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6210     TLBVarDesc *pVarInfo;
6211     int i;
6212     HRESULT result;
6213     for(i=0, pVarInfo=This->varlist; pVarInfo &&
6214             memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6215         ;
6216     if(pVarInfo) {
6217         *pVarIndex = i;
6218         result = S_OK;
6219     } else
6220         result = TYPE_E_ELEMENTNOTFOUND;
6221
6222     TRACE("(%p) memid 0x%08x -> %s\n", This,
6223           memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6224     return result;
6225 }
6226
6227 /* ITypeInfo2::GetCustData
6228  *
6229  * Gets the custom data
6230  */
6231 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6232         ITypeInfo2 * iface,
6233         REFGUID guid,
6234         VARIANT *pVarVal)
6235 {
6236     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6237     TLBCustData *pCData;
6238
6239     for(pCData=This->pCustData; pCData; pCData = pCData->next)
6240         if( IsEqualIID(guid, &pCData->guid)) break;
6241
6242     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6243
6244     if(pCData)
6245     {
6246         VariantInit( pVarVal);
6247         VariantCopy( pVarVal, &pCData->data);
6248         return S_OK;
6249     }
6250     return E_INVALIDARG;  /* FIXME: correct? */
6251 }
6252
6253 /* ITypeInfo2::GetFuncCustData
6254  *
6255  * Gets the custom data
6256  */
6257 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6258         ITypeInfo2 * iface,
6259         UINT index,
6260         REFGUID guid,
6261         VARIANT *pVarVal)
6262 {
6263     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6264     TLBCustData *pCData=NULL;
6265     TLBFuncDesc * pFDesc;
6266     int i;
6267     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6268             pFDesc=pFDesc->next);
6269
6270     if(pFDesc)
6271         for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6272             if( IsEqualIID(guid, &pCData->guid)) break;
6273
6274     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6275
6276     if(pCData){
6277         VariantInit( pVarVal);
6278         VariantCopy( pVarVal, &pCData->data);
6279         return S_OK;
6280     }
6281     return E_INVALIDARG;  /* FIXME: correct? */
6282 }
6283
6284 /* ITypeInfo2::GetParamCustData
6285  *
6286  * Gets the custom data
6287  */
6288 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6289         ITypeInfo2 * iface,
6290         UINT indexFunc,
6291         UINT indexParam,
6292         REFGUID guid,
6293         VARIANT *pVarVal)
6294 {
6295     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6296     TLBCustData *pCData=NULL;
6297     TLBFuncDesc * pFDesc;
6298     int i;
6299
6300     for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6301
6302     if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
6303         for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6304                 pCData = pCData->next)
6305             if( IsEqualIID(guid, &pCData->guid)) break;
6306
6307     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6308
6309     if(pCData)
6310     {
6311         VariantInit( pVarVal);
6312         VariantCopy( pVarVal, &pCData->data);
6313         return S_OK;
6314     }
6315     return E_INVALIDARG;  /* FIXME: correct? */
6316 }
6317
6318 /* ITypeInfo2::GetVarCustData
6319  *
6320  * Gets the custom data
6321  */
6322 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6323         ITypeInfo2 * iface,
6324         UINT index,
6325         REFGUID guid,
6326         VARIANT *pVarVal)
6327 {
6328     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6329     TLBCustData *pCData=NULL;
6330     TLBVarDesc * pVDesc;
6331     int i;
6332
6333     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6334
6335     if(pVDesc)
6336     {
6337       for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6338       {
6339         if( IsEqualIID(guid, &pCData->guid)) break;
6340       }
6341     }
6342
6343     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6344
6345     if(pCData)
6346     {
6347         VariantInit( pVarVal);
6348         VariantCopy( pVarVal, &pCData->data);
6349         return S_OK;
6350     }
6351     return E_INVALIDARG;  /* FIXME: correct? */
6352 }
6353
6354 /* ITypeInfo2::GetImplCustData
6355  *
6356  * Gets the custom data
6357  */
6358 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6359         ITypeInfo2 * iface,
6360         UINT index,
6361         REFGUID guid,
6362         VARIANT *pVarVal)
6363 {
6364     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6365     TLBCustData *pCData=NULL;
6366     TLBImplType * pRDesc;
6367     int i;
6368
6369     for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6370
6371     if(pRDesc)
6372     {
6373       for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6374       {
6375         if( IsEqualIID(guid, &pCData->guid)) break;
6376       }
6377     }
6378
6379     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6380
6381     if(pCData)
6382     {
6383         VariantInit( pVarVal);
6384         VariantCopy( pVarVal, &pCData->data);
6385         return S_OK;
6386     }
6387     return E_INVALIDARG;  /* FIXME: correct? */
6388 }
6389
6390 /* ITypeInfo2::GetDocumentation2
6391  *
6392  * Retrieves the documentation string, the complete Help file name and path,
6393  * the localization context to use, and the context ID for the library Help
6394  * topic in the Help file.
6395  *
6396  */
6397 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6398         ITypeInfo2 * iface,
6399         MEMBERID memid,
6400         LCID lcid,
6401         BSTR *pbstrHelpString,
6402         DWORD *pdwHelpStringContext,
6403         BSTR *pbstrHelpStringDll)
6404 {
6405     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6406     const TLBFuncDesc *pFDesc;
6407     const TLBVarDesc *pVDesc;
6408     TRACE("(%p) memid %d lcid(0x%x)  HelpString(%p) "
6409           "HelpStringContext(%p) HelpStringDll(%p)\n",
6410           This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6411           pbstrHelpStringDll );
6412     /* the help string should be obtained from the helpstringdll,
6413      * using the _DLLGetDocumentation function, based on the supplied
6414      * lcid. Nice to do sometime...
6415      */
6416     if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6417         if(pbstrHelpString)
6418             *pbstrHelpString=SysAllocString(This->Name);
6419         if(pdwHelpStringContext)
6420             *pdwHelpStringContext=This->dwHelpStringContext;
6421         if(pbstrHelpStringDll)
6422             *pbstrHelpStringDll=
6423                 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6424         return S_OK;
6425     }else {/* for a member */
6426     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6427         if(pFDesc->funcdesc.memid==memid){
6428              if(pbstrHelpString)
6429                 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6430             if(pdwHelpStringContext)
6431                 *pdwHelpStringContext=pFDesc->HelpStringContext;
6432             if(pbstrHelpStringDll)
6433                 *pbstrHelpStringDll=
6434                     SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6435         return S_OK;
6436     }
6437     for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6438         if(pVDesc->vardesc.memid==memid){
6439              if(pbstrHelpString)
6440                 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6441             if(pdwHelpStringContext)
6442                 *pdwHelpStringContext=pVDesc->HelpStringContext;
6443             if(pbstrHelpStringDll)
6444                 *pbstrHelpStringDll=
6445                     SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6446             return S_OK;
6447         }
6448     }
6449     return TYPE_E_ELEMENTNOTFOUND;
6450 }
6451
6452 /* ITypeInfo2::GetAllCustData
6453  *
6454  * Gets all custom data items for the Type info.
6455  *
6456  */
6457 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6458         ITypeInfo2 * iface,
6459         CUSTDATA *pCustData)
6460 {
6461     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6462     TLBCustData *pCData;
6463     int i;
6464
6465     TRACE("(%p) returning %d items\n", This, This->ctCustData);
6466
6467     pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6468     if(pCustData->prgCustData ){
6469         pCustData->cCustData=This->ctCustData;
6470         for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6471             pCustData->prgCustData[i].guid=pCData->guid;
6472             VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6473         }
6474     }else{
6475         ERR(" OUT OF MEMORY!\n");
6476         return E_OUTOFMEMORY;
6477     }
6478     return S_OK;
6479 }
6480
6481 /* ITypeInfo2::GetAllFuncCustData
6482  *
6483  * Gets all custom data items for the specified Function
6484  *
6485  */
6486 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6487         ITypeInfo2 * iface,
6488         UINT index,
6489         CUSTDATA *pCustData)
6490 {
6491     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6492     TLBCustData *pCData;
6493     TLBFuncDesc * pFDesc;
6494     int i;
6495     TRACE("(%p) index %d\n", This, index);
6496     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6497             pFDesc=pFDesc->next)
6498         ;
6499     if(pFDesc){
6500         pCustData->prgCustData =
6501             TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6502         if(pCustData->prgCustData ){
6503             pCustData->cCustData=pFDesc->ctCustData;
6504             for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6505                     pCData = pCData->next){
6506                 pCustData->prgCustData[i].guid=pCData->guid;
6507                 VariantCopy(& pCustData->prgCustData[i].varValue,
6508                         & pCData->data);
6509             }
6510         }else{
6511             ERR(" OUT OF MEMORY!\n");
6512             return E_OUTOFMEMORY;
6513         }
6514         return S_OK;
6515     }
6516     return TYPE_E_ELEMENTNOTFOUND;
6517 }
6518
6519 /* ITypeInfo2::GetAllParamCustData
6520  *
6521  * Gets all custom data items for the Functions
6522  *
6523  */
6524 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6525     UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6526 {
6527     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6528     TLBCustData *pCData=NULL;
6529     TLBFuncDesc * pFDesc;
6530     int i;
6531     TRACE("(%p) index %d\n", This, indexFunc);
6532     for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6533             pFDesc=pFDesc->next)
6534         ;
6535     if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6536         pCustData->prgCustData =
6537             TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6538                     sizeof(CUSTDATAITEM));
6539         if(pCustData->prgCustData ){
6540             pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6541             for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6542                     pCData; i++, pCData = pCData->next){
6543                 pCustData->prgCustData[i].guid=pCData->guid;
6544                 VariantCopy(& pCustData->prgCustData[i].varValue,
6545                         & pCData->data);
6546             }
6547         }else{
6548             ERR(" OUT OF MEMORY!\n");
6549             return E_OUTOFMEMORY;
6550         }
6551         return S_OK;
6552     }
6553     return TYPE_E_ELEMENTNOTFOUND;
6554 }
6555
6556 /* ITypeInfo2::GetAllVarCustData
6557  *
6558  * Gets all custom data items for the specified Variable
6559  *
6560  */
6561 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6562     UINT index, CUSTDATA *pCustData)
6563 {
6564     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6565     TLBCustData *pCData;
6566     TLBVarDesc * pVDesc;
6567     int i;
6568     TRACE("(%p) index %d\n", This, index);
6569     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6570             pVDesc=pVDesc->next)
6571         ;
6572     if(pVDesc){
6573         pCustData->prgCustData =
6574             TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6575         if(pCustData->prgCustData ){
6576             pCustData->cCustData=pVDesc->ctCustData;
6577             for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6578                     pCData = pCData->next){
6579                 pCustData->prgCustData[i].guid=pCData->guid;
6580                 VariantCopy(& pCustData->prgCustData[i].varValue,
6581                         & pCData->data);
6582             }
6583         }else{
6584             ERR(" OUT OF MEMORY!\n");
6585             return E_OUTOFMEMORY;
6586         }
6587         return S_OK;
6588     }
6589     return TYPE_E_ELEMENTNOTFOUND;
6590 }
6591
6592 /* ITypeInfo2::GetAllImplCustData
6593  *
6594  * Gets all custom data items for the specified implementation type
6595  *
6596  */
6597 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6598         ITypeInfo2 * iface,
6599         UINT index,
6600         CUSTDATA *pCustData)
6601 {
6602     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6603     TLBCustData *pCData;
6604     TLBImplType * pRDesc;
6605     int i;
6606     TRACE("(%p) index %d\n", This, index);
6607     for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6608             pRDesc=pRDesc->next)
6609         ;
6610     if(pRDesc){
6611         pCustData->prgCustData =
6612             TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6613         if(pCustData->prgCustData ){
6614             pCustData->cCustData=pRDesc->ctCustData;
6615             for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6616                     pCData = pCData->next){
6617                 pCustData->prgCustData[i].guid=pCData->guid;
6618                 VariantCopy(& pCustData->prgCustData[i].varValue,
6619                         & pCData->data);
6620             }
6621         }else{
6622             ERR(" OUT OF MEMORY!\n");
6623             return E_OUTOFMEMORY;
6624         }
6625         return S_OK;
6626     }
6627     return TYPE_E_ELEMENTNOTFOUND;
6628 }
6629
6630 static const ITypeInfo2Vtbl tinfvt =
6631 {
6632
6633     ITypeInfo_fnQueryInterface,
6634     ITypeInfo_fnAddRef,
6635     ITypeInfo_fnRelease,
6636
6637     ITypeInfo_fnGetTypeAttr,
6638     ITypeInfo_fnGetTypeComp,
6639     ITypeInfo_fnGetFuncDesc,
6640     ITypeInfo_fnGetVarDesc,
6641     ITypeInfo_fnGetNames,
6642     ITypeInfo_fnGetRefTypeOfImplType,
6643     ITypeInfo_fnGetImplTypeFlags,
6644     ITypeInfo_fnGetIDsOfNames,
6645     ITypeInfo_fnInvoke,
6646     ITypeInfo_fnGetDocumentation,
6647     ITypeInfo_fnGetDllEntry,
6648     ITypeInfo_fnGetRefTypeInfo,
6649     ITypeInfo_fnAddressOfMember,
6650     ITypeInfo_fnCreateInstance,
6651     ITypeInfo_fnGetMops,
6652     ITypeInfo_fnGetContainingTypeLib,
6653     ITypeInfo_fnReleaseTypeAttr,
6654     ITypeInfo_fnReleaseFuncDesc,
6655     ITypeInfo_fnReleaseVarDesc,
6656
6657     ITypeInfo2_fnGetTypeKind,
6658     ITypeInfo2_fnGetTypeFlags,
6659     ITypeInfo2_fnGetFuncIndexOfMemId,
6660     ITypeInfo2_fnGetVarIndexOfMemId,
6661     ITypeInfo2_fnGetCustData,
6662     ITypeInfo2_fnGetFuncCustData,
6663     ITypeInfo2_fnGetParamCustData,
6664     ITypeInfo2_fnGetVarCustData,
6665     ITypeInfo2_fnGetImplTypeCustData,
6666     ITypeInfo2_fnGetDocumentation2,
6667     ITypeInfo2_fnGetAllCustData,
6668     ITypeInfo2_fnGetAllFuncCustData,
6669     ITypeInfo2_fnGetAllParamCustData,
6670     ITypeInfo2_fnGetAllVarCustData,
6671     ITypeInfo2_fnGetAllImplTypeCustData,
6672 };
6673
6674 /******************************************************************************
6675  * CreateDispTypeInfo [OLEAUT32.31]
6676  *
6677  * Build type information for an object so it can be called through an
6678  * IDispatch interface.
6679  *
6680  * RETURNS
6681  *  Success: S_OK. pptinfo contains the created ITypeInfo object.
6682  *  Failure: E_INVALIDARG, if one or more arguments is invalid.
6683  *
6684  * NOTES
6685  *  This call allows an objects methods to be accessed through IDispatch, by
6686  *  building an ITypeInfo object that IDispatch can use to call through.
6687  */
6688 HRESULT WINAPI CreateDispTypeInfo(
6689         INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6690         LCID lcid, /* [I] Locale Id */
6691         ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6692 {
6693     ITypeInfoImpl *pTIClass, *pTIIface;
6694     ITypeLibImpl *pTypeLibImpl;
6695     int param, func;
6696     TLBFuncDesc **ppFuncDesc;
6697
6698     TRACE("\n");
6699     pTypeLibImpl = TypeLibImpl_Constructor();
6700     if (!pTypeLibImpl) return E_FAIL;
6701
6702     pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6703     pTIIface->pTypeLib = pTypeLibImpl;
6704     pTIIface->index = 0;
6705     pTIIface->Name = NULL;
6706     pTIIface->dwHelpContext = -1;
6707     memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6708     pTIIface->TypeAttr.lcid = lcid;
6709     pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6710     pTIIface->TypeAttr.wMajorVerNum = 0;
6711     pTIIface->TypeAttr.wMinorVerNum = 0;
6712     pTIIface->TypeAttr.cbAlignment = 2;
6713     pTIIface->TypeAttr.cbSizeInstance = -1;
6714     pTIIface->TypeAttr.cbSizeVft = -1;
6715     pTIIface->TypeAttr.cFuncs = 0;
6716     pTIIface->TypeAttr.cImplTypes = 0;
6717     pTIIface->TypeAttr.cVars = 0;
6718     pTIIface->TypeAttr.wTypeFlags = 0;
6719
6720     ppFuncDesc = &pTIIface->funclist;
6721     for(func = 0; func < pidata->cMembers; func++) {
6722         METHODDATA *md = pidata->pmethdata + func;
6723         *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6724         (*ppFuncDesc)->Name = SysAllocString(md->szName);
6725         (*ppFuncDesc)->funcdesc.memid = md->dispid;
6726         (*ppFuncDesc)->funcdesc.lprgscode = NULL;
6727         (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6728         (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6729         (*ppFuncDesc)->funcdesc.callconv = md->cc;
6730         (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6731         (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6732         (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6733         (*ppFuncDesc)->funcdesc.cScodes = 0;
6734         (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6735         (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6736         (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6737         (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6738         (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6739                                                               md->cArgs * sizeof(ELEMDESC));
6740         (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6741                                               md->cArgs * sizeof(TLBParDesc));
6742         for(param = 0; param < md->cArgs; param++) {
6743             (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6744             (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6745         }
6746         (*ppFuncDesc)->helpcontext = 0;
6747         (*ppFuncDesc)->HelpStringContext = 0;
6748         (*ppFuncDesc)->HelpString = NULL;
6749         (*ppFuncDesc)->Entry = NULL;
6750         (*ppFuncDesc)->ctCustData = 0;
6751         (*ppFuncDesc)->pCustData = NULL;
6752         (*ppFuncDesc)->next = NULL;
6753         ppFuncDesc = &(*ppFuncDesc)->next;
6754     }
6755
6756     dump_TypeInfo(pTIIface);
6757
6758     pTypeLibImpl->pTypeInfo = pTIIface;
6759     pTypeLibImpl->TypeInfoCount++;
6760
6761     pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6762     pTIClass->pTypeLib = pTypeLibImpl;
6763     pTIClass->index = 1;
6764     pTIClass->Name = NULL;
6765     pTIClass->dwHelpContext = -1;
6766     memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6767     pTIClass->TypeAttr.lcid = lcid;
6768     pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6769     pTIClass->TypeAttr.wMajorVerNum = 0;
6770     pTIClass->TypeAttr.wMinorVerNum = 0;
6771     pTIClass->TypeAttr.cbAlignment = 2;
6772     pTIClass->TypeAttr.cbSizeInstance = -1;
6773     pTIClass->TypeAttr.cbSizeVft = -1;
6774     pTIClass->TypeAttr.cFuncs = 0;
6775     pTIClass->TypeAttr.cImplTypes = 1;
6776     pTIClass->TypeAttr.cVars = 0;
6777     pTIClass->TypeAttr.wTypeFlags = 0;
6778
6779     pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6780     pTIClass->impltypelist->hRef = 1;
6781
6782     pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist));
6783     pTIClass->reflist->index = 0;
6784     pTIClass->reflist->reference = 1;
6785     pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL;
6786
6787     dump_TypeInfo(pTIClass);
6788
6789     pTIIface->next = pTIClass;
6790     pTypeLibImpl->TypeInfoCount++;
6791
6792     *pptinfo = (ITypeInfo*)pTIClass;
6793
6794     ITypeInfo_AddRef(*pptinfo);
6795     ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
6796
6797     return S_OK;
6798
6799 }
6800
6801 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6802 {
6803     ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6804
6805     return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6806 }
6807
6808 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6809 {
6810     ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6811
6812     return ITypeInfo_AddRef((ITypeInfo *)This);
6813 }
6814
6815 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6816 {
6817     ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6818
6819     return ITypeInfo_Release((ITypeInfo *)This);
6820 }
6821
6822 static HRESULT WINAPI ITypeComp_fnBind(
6823     ITypeComp * iface,
6824     OLECHAR * szName,
6825     ULONG lHash,
6826     WORD wFlags,
6827     ITypeInfo ** ppTInfo,
6828     DESCKIND * pDescKind,
6829     BINDPTR * pBindPtr)
6830 {
6831     ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6832     const TLBFuncDesc *pFDesc;
6833     const TLBVarDesc *pVDesc;
6834     HRESULT hr = DISP_E_MEMBERNOTFOUND;
6835
6836     TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6837
6838     *pDescKind = DESCKIND_NONE;
6839     pBindPtr->lpfuncdesc = NULL;
6840     *ppTInfo = NULL;
6841
6842     for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6843         if (!strcmpiW(pFDesc->Name, szName)) {
6844             if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6845                 break;
6846             else
6847                 /* name found, but wrong flags */
6848                 hr = TYPE_E_TYPEMISMATCH;
6849         }
6850
6851     if (pFDesc)
6852     {
6853         HRESULT hr = TLB_AllocAndInitFuncDesc(
6854             &pFDesc->funcdesc,
6855             &pBindPtr->lpfuncdesc,
6856             This->TypeAttr.typekind == TKIND_DISPATCH);
6857         if (FAILED(hr))
6858             return hr;
6859         *pDescKind = DESCKIND_FUNCDESC;
6860         *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6861         ITypeInfo_AddRef(*ppTInfo);
6862         return S_OK;
6863     } else {
6864         for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6865             if (!strcmpiW(pVDesc->Name, szName)) {
6866                 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6867                 if (FAILED(hr))
6868                     return hr;
6869                 *pDescKind = DESCKIND_VARDESC;
6870                 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6871                 ITypeInfo_AddRef(*ppTInfo);
6872                 return S_OK;
6873             }
6874         }
6875     }
6876     /* FIXME: search each inherited interface, not just the first */
6877     if (hr == DISP_E_MEMBERNOTFOUND && This->TypeAttr.cImplTypes) {
6878         /* recursive search */
6879         ITypeInfo *pTInfo;
6880         ITypeComp *pTComp;
6881         HRESULT hr;
6882         hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6883         if (SUCCEEDED(hr))
6884         {
6885             hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6886             ITypeInfo_Release(pTInfo);
6887         }
6888         if (SUCCEEDED(hr))
6889         {
6890             hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6891             ITypeComp_Release(pTComp);
6892             return hr;
6893         }
6894         WARN("Could not search inherited interface!\n");
6895     }
6896     WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6897     return hr;
6898 }
6899
6900 static HRESULT WINAPI ITypeComp_fnBindType(
6901     ITypeComp * iface,
6902     OLECHAR * szName,
6903     ULONG lHash,
6904     ITypeInfo ** ppTInfo,
6905     ITypeComp ** ppTComp)
6906 {
6907     TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6908
6909     /* strange behaviour (does nothing) but like the
6910      * original */
6911
6912     if (!ppTInfo || !ppTComp)
6913         return E_POINTER;
6914
6915     *ppTInfo = NULL;
6916     *ppTComp = NULL;
6917
6918     return S_OK;
6919 }
6920
6921 static const ITypeCompVtbl tcompvt =
6922 {
6923
6924     ITypeComp_fnQueryInterface,
6925     ITypeComp_fnAddRef,
6926     ITypeComp_fnRelease,
6927
6928     ITypeComp_fnBind,
6929     ITypeComp_fnBindType
6930 };