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