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