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