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