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