oleaut32: Handle NULL arguments to ITypeComp::BindType.
[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;
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;
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 && !strcmpW(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             SysFreeString(pFInfo->pParamDesc[i].Name);
5034         }
5035         heap_free(pFInfo->funcdesc.lprgelemdescParam);
5036         heap_free(pFInfo->pParamDesc);
5037         TLB_FreeCustData(pFInfo->pCustData);
5038         if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
5039             SysFreeString(pFInfo->Entry);
5040         SysFreeString(pFInfo->HelpString);
5041         SysFreeString(pFInfo->Name);
5042
5043         pFInfoNext = pFInfo->next;
5044         heap_free(pFInfo);
5045     }
5046     for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
5047     {
5048         if (pVInfo->vardesc.varkind == VAR_CONST)
5049         {
5050             VariantClear(pVInfo->vardesc.u.lpvarValue);
5051             heap_free(pVInfo->vardesc.u.lpvarValue);
5052         }
5053         TLB_FreeCustData(pVInfo->pCustData);
5054         SysFreeString(pVInfo->Name);
5055         pVInfoNext = pVInfo->next;
5056         heap_free(pVInfo);
5057     }
5058     for (pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
5059     {
5060         TLB_FreeCustData(pImpl->pCustData);
5061         pImplNext = pImpl->next;
5062         heap_free(pImpl);
5063     }
5064     TLB_FreeCustData(This->pCustData);
5065
5066     heap_free(This);
5067 }
5068
5069 /* ITypeInfo::Release
5070  */
5071 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5072 {
5073     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5074     ULONG ref = InterlockedDecrement(&This->ref);
5075
5076     TRACE("(%p)->(%u)\n",This, ref);
5077
5078     if (!ref)
5079     {
5080         BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5081         ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
5082         if (not_attached_to_typelib)
5083             heap_free(This);
5084         /* otherwise This will be freed when typelib is freed */
5085     }
5086
5087     return ref;
5088 }
5089
5090 /* ITypeInfo::GetTypeAttr
5091  *
5092  * Retrieves a TYPEATTR structure that contains the attributes of the type
5093  * description.
5094  *
5095  */
5096 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5097         LPTYPEATTR  *ppTypeAttr)
5098 {
5099     const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5100     SIZE_T size;
5101
5102     TRACE("(%p)\n",This);
5103
5104     size = sizeof(**ppTypeAttr);
5105     if (This->TypeAttr.typekind == TKIND_ALIAS)
5106         size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5107
5108     *ppTypeAttr = heap_alloc(size);
5109     if (!*ppTypeAttr)
5110         return E_OUTOFMEMORY;
5111
5112     **ppTypeAttr = This->TypeAttr;
5113
5114     if (This->TypeAttr.typekind == TKIND_ALIAS)
5115         TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5116             &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5117
5118     if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5119         /* This should include all the inherited funcs */
5120         (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5121         /* This is always the size of IDispatch's vtbl */
5122         (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5123         (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5124     }
5125     return S_OK;
5126 }
5127
5128 /* ITypeInfo::GetTypeComp
5129  *
5130  * Retrieves the ITypeComp interface for the type description, which enables a
5131  * client compiler to bind to the type description's members.
5132  *
5133  */
5134 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5135         ITypeComp  * *ppTComp)
5136 {
5137     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5138
5139     TRACE("(%p)->(%p)\n", This, ppTComp);
5140
5141     *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5142     ITypeComp_AddRef(*ppTComp);
5143     return S_OK;
5144 }
5145
5146 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5147 {
5148     SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5149     if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5150         size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5151     return size;
5152 }
5153
5154 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5155 {
5156     *dest = *src;
5157     *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5158     if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5159     {
5160         const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5161         PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5162         *buffer += sizeof(PARAMDESCEX);
5163         *pparamdescex_dest = *pparamdescex_src;
5164         VariantInit(&pparamdescex_dest->varDefaultValue);
5165         return VariantCopy(&pparamdescex_dest->varDefaultValue, 
5166                            (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5167     }
5168     else
5169         dest->u.paramdesc.pparamdescex = NULL;
5170     return S_OK;
5171 }
5172
5173 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5174 {
5175     if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5176         VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5177 }
5178
5179 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5180 {
5181     FUNCDESC *dest;
5182     char *buffer;
5183     SIZE_T size = sizeof(*src);
5184     SHORT i;
5185     HRESULT hr;
5186
5187     size += sizeof(*src->lprgscode) * src->cScodes;
5188     size += TLB_SizeElemDesc(&src->elemdescFunc);
5189     for (i = 0; i < src->cParams; i++)
5190     {
5191         size += sizeof(ELEMDESC);
5192         size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5193     }
5194
5195     dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5196     if (!dest) return E_OUTOFMEMORY;
5197
5198     *dest = *src;
5199     if (dispinterface)    /* overwrite funckind */
5200         dest->funckind = FUNC_DISPATCH;
5201     buffer = (char *)(dest + 1);
5202
5203     dest->lprgscode = (SCODE *)buffer;
5204     memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5205     buffer += sizeof(*src->lprgscode) * src->cScodes;
5206
5207     hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5208     if (FAILED(hr))
5209     {
5210         SysFreeString((BSTR)dest);
5211         return hr;
5212     }
5213
5214     dest->lprgelemdescParam = (ELEMDESC *)buffer;
5215     buffer += sizeof(ELEMDESC) * src->cParams;
5216     for (i = 0; i < src->cParams; i++)
5217     {
5218         hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5219         if (FAILED(hr))
5220             break;
5221     }
5222     if (FAILED(hr))
5223     {
5224         /* undo the above actions */
5225         for (i = i - 1; i >= 0; i--)
5226             TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5227         TLB_FreeElemDesc(&dest->elemdescFunc);
5228         SysFreeString((BSTR)dest);
5229         return hr;
5230     }
5231
5232     /* special treatment for dispinterfaces: this makes functions appear
5233      * to return their [retval] value when it is really returning an
5234      * HRESULT */
5235     if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5236     {
5237         if (dest->cParams &&
5238             (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5239         {
5240             ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5241             if (elemdesc->tdesc.vt != VT_PTR)
5242             {
5243                 ERR("elemdesc should have started with VT_PTR instead of:\n");
5244                 if (ERR_ON(ole))
5245                     dump_ELEMDESC(elemdesc);
5246                 return E_UNEXPECTED;
5247             }
5248
5249             /* copy last parameter to the return value. we are using a flat
5250              * buffer so there is no danger of leaking memory in
5251              * elemdescFunc */
5252             dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5253
5254             /* remove the last parameter */
5255             dest->cParams--;
5256         }
5257         else
5258             /* otherwise this function is made to appear to have no return
5259              * value */
5260             dest->elemdescFunc.tdesc.vt = VT_VOID;
5261
5262     }
5263
5264     *dest_ptr = dest;
5265     return S_OK;
5266 }
5267
5268 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5269 {
5270     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5271     const TLBFuncDesc *pFDesc;
5272     UINT i;
5273
5274     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5275         ;
5276
5277     if (pFDesc)
5278     {
5279         *ppFuncDesc = &pFDesc->funcdesc;
5280         return S_OK;
5281     }
5282
5283     return TYPE_E_ELEMENTNOTFOUND;
5284 }
5285
5286 /* internal function to make the inherited interfaces' methods appear
5287  * part of the interface */
5288 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5289     UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5290 {
5291     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5292     HRESULT hr;
5293     UINT implemented_funcs = 0;
5294
5295     if (funcs)
5296         *funcs = 0;
5297     else
5298         *hrefoffset = DISPATCH_HREF_OFFSET;
5299
5300     if(This->impltypelist)
5301     {
5302         ITypeInfo *pSubTypeInfo;
5303         UINT sub_funcs;
5304
5305         hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5306         if (FAILED(hr))
5307             return hr;
5308
5309         hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5310                                                        index,
5311                                                        ppFuncDesc,
5312                                                        &sub_funcs, hrefoffset);
5313         implemented_funcs += sub_funcs;
5314         ITypeInfo_Release(pSubTypeInfo);
5315         if (SUCCEEDED(hr))
5316             return hr;
5317         *hrefoffset += DISPATCH_HREF_OFFSET;
5318     }
5319
5320     if (funcs)
5321         *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5322     else
5323         *hrefoffset = 0;
5324     
5325     if (index < implemented_funcs)
5326         return E_INVALIDARG;
5327     return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5328                                              ppFuncDesc);
5329 }
5330
5331 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5332 {
5333     TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5334     while (TRUE)
5335     {
5336         switch (pTypeDesc->vt)
5337         {
5338         case VT_USERDEFINED:
5339             pTypeDesc->u.hreftype += hrefoffset;
5340             return;
5341         case VT_PTR:
5342         case VT_SAFEARRAY:
5343             pTypeDesc = pTypeDesc->u.lptdesc;
5344             break;
5345         case VT_CARRAY:
5346             pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5347             break;
5348         default:
5349             return;
5350         }
5351     }
5352 }
5353
5354 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5355 {
5356     SHORT i;
5357     for (i = 0; i < pFuncDesc->cParams; i++)
5358         ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5359     ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5360 }
5361
5362 /* ITypeInfo::GetFuncDesc
5363  *
5364  * Retrieves the FUNCDESC structure that contains information about a
5365  * specified function.
5366  *
5367  */
5368 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5369         LPFUNCDESC  *ppFuncDesc)
5370 {
5371     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5372     const FUNCDESC *internal_funcdesc;
5373     HRESULT hr;
5374     UINT hrefoffset = 0;
5375
5376     TRACE("(%p) index %d\n", This, index);
5377
5378     if (This->TypeAttr.typekind == TKIND_DISPATCH)
5379         hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5380                                                        &internal_funcdesc, NULL,
5381                                                        &hrefoffset);
5382     else
5383         hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5384                                                &internal_funcdesc);
5385     if (FAILED(hr))
5386     {
5387         WARN("description for function %d not found\n", index);
5388         return hr;
5389     }
5390
5391     hr = TLB_AllocAndInitFuncDesc(
5392         internal_funcdesc,
5393         ppFuncDesc,
5394         This->TypeAttr.typekind == TKIND_DISPATCH);
5395
5396     if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5397         ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5398
5399     TRACE("-- 0x%08x\n", hr);
5400     return hr;
5401 }
5402
5403 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5404 {
5405     VARDESC *dest;
5406     char *buffer;
5407     SIZE_T size = sizeof(*src);
5408     HRESULT hr;
5409
5410     if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5411     if (src->varkind == VAR_CONST)
5412         size += sizeof(VARIANT);
5413     size += TLB_SizeElemDesc(&src->elemdescVar);
5414
5415     dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5416     if (!dest) return E_OUTOFMEMORY;
5417
5418     *dest = *src;
5419     buffer = (char *)(dest + 1);
5420     if (src->lpstrSchema)
5421     {
5422         int len;
5423         dest->lpstrSchema = (LPOLESTR)buffer;
5424         len = strlenW(src->lpstrSchema);
5425         memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5426         buffer += (len + 1) * sizeof(WCHAR);
5427     }
5428
5429     if (src->varkind == VAR_CONST)
5430     {
5431         HRESULT hr;
5432
5433         dest->u.lpvarValue = (VARIANT *)buffer;
5434         *dest->u.lpvarValue = *src->u.lpvarValue;
5435         buffer += sizeof(VARIANT);
5436         VariantInit(dest->u.lpvarValue);
5437         hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5438         if (FAILED(hr))
5439         {
5440             SysFreeString((BSTR)dest);
5441             return hr;
5442         }
5443     }
5444     hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5445     if (FAILED(hr))
5446     {
5447         if (src->varkind == VAR_CONST)
5448             VariantClear(dest->u.lpvarValue);
5449         SysFreeString((BSTR)dest);
5450         return hr;
5451     }
5452     *dest_ptr = dest;
5453     return S_OK;
5454 }
5455
5456 /* ITypeInfo::GetVarDesc
5457  *
5458  * Retrieves a VARDESC structure that describes the specified variable.
5459  *
5460  */
5461 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5462         LPVARDESC  *ppVarDesc)
5463 {
5464     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5465     UINT i;
5466     const TLBVarDesc *pVDesc;
5467
5468     TRACE("(%p) index %d\n", This, index);
5469
5470     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5471         ;
5472
5473     if (pVDesc)
5474         return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5475
5476     return E_INVALIDARG;
5477 }
5478
5479 /* ITypeInfo_GetNames
5480  *
5481  * Retrieves the variable with the specified member ID (or the name of the
5482  * property or method and its parameters) that correspond to the specified
5483  * function ID.
5484  */
5485 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5486         BSTR  *rgBstrNames, UINT cMaxNames, UINT  *pcNames)
5487 {
5488     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5489     const TLBFuncDesc *pFDesc;
5490     const TLBVarDesc *pVDesc;
5491     int i;
5492     TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5493     for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5494     if(pFDesc)
5495     {
5496       /* function found, now return function and parameter names */
5497       for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5498       {
5499         if(!i)
5500           *rgBstrNames=SysAllocString(pFDesc->Name);
5501         else
5502           rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5503       }
5504       *pcNames=i;
5505     }
5506     else
5507     {
5508       for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5509       if(pVDesc)
5510       {
5511         *rgBstrNames=SysAllocString(pVDesc->Name);
5512         *pcNames=1;
5513       }
5514       else
5515       {
5516         if(This->impltypelist &&
5517            (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5518           /* recursive search */
5519           ITypeInfo *pTInfo;
5520           HRESULT result;
5521           result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5522                                           &pTInfo);
5523           if(SUCCEEDED(result))
5524           {
5525             result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5526             ITypeInfo_Release(pTInfo);
5527             return result;
5528           }
5529           WARN("Could not search inherited interface!\n");
5530         }
5531         else
5532         {
5533           WARN("no names found\n");
5534         }
5535         *pcNames=0;
5536         return TYPE_E_ELEMENTNOTFOUND;
5537       }
5538     }
5539     return S_OK;
5540 }
5541
5542
5543 /* ITypeInfo::GetRefTypeOfImplType
5544  *
5545  * If a type description describes a COM class, it retrieves the type
5546  * description of the implemented interface types. For an interface,
5547  * GetRefTypeOfImplType returns the type information for inherited interfaces,
5548  * if any exist.
5549  *
5550  */
5551 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5552         ITypeInfo2 *iface,
5553         UINT index,
5554         HREFTYPE  *pRefType)
5555 {
5556     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5557     UINT i;
5558     HRESULT hr = S_OK;
5559     const TLBImplType *pImpl = This->impltypelist;
5560
5561     TRACE("(%p) index %d\n", This, index);
5562     if (TRACE_ON(ole)) dump_TypeInfo(This);
5563
5564     if(index==(UINT)-1)
5565     {
5566       /* only valid on dual interfaces;
5567          retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5568       */
5569       if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5570
5571       if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5572       {
5573         *pRefType = -1;
5574       }
5575       else
5576       {
5577         hr = TYPE_E_ELEMENTNOTFOUND;
5578       }
5579     }
5580     else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5581     {
5582       /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5583       *pRefType = This->pTypeLib->dispatch_href;
5584     }
5585     else
5586     {
5587       /* get element n from linked list */
5588       for(i=0; pImpl && i<index; i++)
5589       {
5590         pImpl = pImpl->next;
5591       }
5592
5593       if (pImpl)
5594         *pRefType = pImpl->hRef;
5595       else
5596         hr = TYPE_E_ELEMENTNOTFOUND;
5597     }
5598
5599     if(TRACE_ON(ole))
5600     {
5601         if(SUCCEEDED(hr))
5602             TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5603         else
5604             TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5605     }
5606
5607     return hr;
5608 }
5609
5610 /* ITypeInfo::GetImplTypeFlags
5611  *
5612  * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5613  * or base interface in a type description.
5614  */
5615 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5616         UINT index, INT  *pImplTypeFlags)
5617 {
5618     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5619     UINT i;
5620     TLBImplType *pImpl;
5621
5622     TRACE("(%p) index %d\n", This, index);
5623     for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5624         i++, pImpl=pImpl->next)
5625         ;
5626     if(i==index && pImpl){
5627         *pImplTypeFlags=pImpl->implflags;
5628         return S_OK;
5629     }
5630     *pImplTypeFlags=0;
5631
5632     if(This->TypeAttr.typekind==TKIND_DISPATCH && !index)
5633         return S_OK;
5634
5635     WARN("ImplType %d not found\n", index);
5636     return TYPE_E_ELEMENTNOTFOUND;
5637 }
5638
5639 /* GetIDsOfNames
5640  * Maps between member names and member IDs, and parameter names and
5641  * parameter IDs.
5642  */
5643 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5644         LPOLESTR  *rgszNames, UINT cNames, MEMBERID  *pMemId)
5645 {
5646     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5647     const TLBFuncDesc *pFDesc;
5648     const TLBVarDesc *pVDesc;
5649     HRESULT ret=S_OK;
5650     UINT i;
5651
5652     TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5653             cNames);
5654
5655     /* init out parameters in case of failure */
5656     for (i = 0; i < cNames; i++)
5657         pMemId[i] = MEMBERID_NIL;
5658
5659     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5660         int j;
5661         if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5662             if(cNames) *pMemId=pFDesc->funcdesc.memid;
5663             for(i=1; i < cNames; i++){
5664                 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5665                     if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5666                             break;
5667                 if( j<pFDesc->funcdesc.cParams)
5668                     pMemId[i]=j;
5669                 else
5670                    ret=DISP_E_UNKNOWNNAME;
5671             };
5672             TRACE("-- 0x%08x\n", ret);
5673             return ret;
5674         }
5675     }
5676     for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5677         if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5678             if(cNames) *pMemId=pVDesc->vardesc.memid;
5679             return ret;
5680         }
5681     }
5682     /* not found, see if it can be found in an inherited interface */
5683     if(This->impltypelist) {
5684         /* recursive search */
5685         ITypeInfo *pTInfo;
5686         ret=ITypeInfo_GetRefTypeInfo(iface,
5687                 This->impltypelist->hRef, &pTInfo);
5688         if(SUCCEEDED(ret)){
5689             ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5690             ITypeInfo_Release(pTInfo);
5691             return ret;
5692         }
5693         WARN("Could not search inherited interface!\n");
5694     } else
5695         WARN("no names found\n");
5696     return DISP_E_UNKNOWNNAME;
5697 }
5698
5699
5700 #ifdef __i386__
5701
5702 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
5703 __ASM_GLOBAL_FUNC( call_method,
5704                    "pushl %ebp\n\t"
5705                    __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5706                    __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5707                    "movl %esp,%ebp\n\t"
5708                    __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5709                    "pushl %esi\n\t"
5710                   __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5711                    "pushl %edi\n\t"
5712                   __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5713                    "movl 12(%ebp),%edx\n\t"
5714                    "movl %esp,%edi\n\t"
5715                    "shll $2,%edx\n\t"
5716                    "jz 1f\n\t"
5717                    "subl %edx,%edi\n\t"
5718                    "andl $~15,%edi\n\t"
5719                    "movl %edi,%esp\n\t"
5720                    "movl 12(%ebp),%ecx\n\t"
5721                    "movl 16(%ebp),%esi\n\t"
5722                    "cld\n\t"
5723                    "rep; movsl\n"
5724                    "1:\tcall *8(%ebp)\n\t"
5725                    "subl %esp,%edi\n\t"
5726                    "movl 20(%ebp),%ecx\n\t"
5727                    "movl %edi,(%ecx)\n\t"
5728                    "leal -8(%ebp),%esp\n\t"
5729                    "popl %edi\n\t"
5730                    __ASM_CFI(".cfi_same_value %edi\n\t")
5731                    "popl %esi\n\t"
5732                    __ASM_CFI(".cfi_same_value %esi\n\t")
5733                    "popl %ebp\n\t"
5734                    __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5735                    __ASM_CFI(".cfi_same_value %ebp\n\t")
5736                    "ret" )
5737
5738 /* same function but returning floating point */
5739 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
5740
5741 /* ITypeInfo::Invoke
5742  *
5743  * Invokes a method, or accesses a property of an object, that implements the
5744  * interface described by the type description.
5745  */
5746 DWORD
5747 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5748     DWORD res;
5749     int stack_offset;
5750
5751     if (TRACE_ON(ole)) {
5752         int i;
5753         TRACE("Calling %p(",func);
5754         for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
5755         if (nrargs > 30) TRACE("...");
5756         TRACE(")\n");
5757     }
5758
5759     switch (callconv) {
5760     case CC_STDCALL:
5761     case CC_CDECL:
5762         res = call_method( func, nrargs, args, &stack_offset );
5763         break;
5764     default:
5765         FIXME("unsupported calling convention %d\n",callconv);
5766         res = -1;
5767         break;
5768     }
5769     TRACE("returns %08x\n",res);
5770     return res;
5771 }
5772
5773 #elif defined(__x86_64__)
5774
5775 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
5776 __ASM_GLOBAL_FUNC( call_method,
5777                    "pushq %rbp\n\t"
5778                    __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
5779                    __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
5780                    "movq %rsp,%rbp\n\t"
5781                    __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
5782                    "pushq %rsi\n\t"
5783                    __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
5784                    "pushq %rdi\n\t"
5785                    __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
5786                    "movq %rcx,%rax\n\t"
5787                    "movq $4,%rcx\n\t"
5788                    "cmp %rcx,%rdx\n\t"
5789                    "cmovgq %rdx,%rcx\n\t"
5790                    "leaq 0(,%rcx,8),%rdx\n\t"
5791                    "subq %rdx,%rsp\n\t"
5792                    "andq $~15,%rsp\n\t"
5793                    "movq %rsp,%rdi\n\t"
5794                    "movq %r8,%rsi\n\t"
5795                    "rep; movsq\n\t"
5796                    "movq 0(%rsp),%rcx\n\t"
5797                    "movq 8(%rsp),%rdx\n\t"
5798                    "movq 16(%rsp),%r8\n\t"
5799                    "movq 24(%rsp),%r9\n\t"
5800                    "movq %rcx,%xmm0\n\t"
5801                    "movq %rdx,%xmm1\n\t"
5802                    "movq %r8,%xmm2\n\t"
5803                    "movq %r9,%xmm3\n\t"
5804                    "callq *%rax\n\t"
5805                    "leaq -16(%rbp),%rsp\n\t"
5806                    "popq %rdi\n\t"
5807                    __ASM_CFI(".cfi_same_value %rdi\n\t")
5808                    "popq %rsi\n\t"
5809                    __ASM_CFI(".cfi_same_value %rsi\n\t")
5810                    __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
5811                    "popq %rbp\n\t"
5812                    __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
5813                    __ASM_CFI(".cfi_same_value %rbp\n\t")
5814                    "ret")
5815
5816 /* same function but returning floating point */
5817 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
5818
5819 #endif  /* __x86_64__ */
5820
5821 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5822 {
5823     HRESULT hr = S_OK;
5824     ITypeInfo *tinfo2 = NULL;
5825     TYPEATTR *tattr = NULL;
5826
5827     hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5828     if (hr)
5829     {
5830         ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5831             "hr = 0x%08x\n",
5832               tdesc->u.hreftype, hr);
5833         return hr;
5834     }
5835     hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5836     if (hr)
5837     {
5838         ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5839         ITypeInfo_Release(tinfo2);
5840         return hr;
5841     }
5842
5843     switch (tattr->typekind)
5844     {
5845     case TKIND_ENUM:
5846         *vt |= VT_I4;
5847         break;
5848
5849     case TKIND_ALIAS:
5850         tdesc = &tattr->tdescAlias;
5851         hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5852         break;
5853
5854     case TKIND_INTERFACE:
5855         if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5856            *vt |= VT_DISPATCH;
5857         else
5858            *vt |= VT_UNKNOWN;
5859         break;
5860
5861     case TKIND_DISPATCH:
5862         *vt |= VT_DISPATCH;
5863         break;
5864
5865     case TKIND_COCLASS:
5866         *vt |= VT_DISPATCH;
5867         break;
5868
5869     case TKIND_RECORD:
5870         FIXME("TKIND_RECORD unhandled.\n");
5871         hr = E_NOTIMPL;
5872         break;
5873
5874     case TKIND_UNION:
5875         FIXME("TKIND_UNION unhandled.\n");
5876         hr = E_NOTIMPL;
5877         break;
5878
5879     default:
5880         FIXME("TKIND %d unhandled.\n",tattr->typekind);
5881         hr = E_NOTIMPL;
5882         break;
5883     }
5884     ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5885     ITypeInfo_Release(tinfo2);
5886     return hr;
5887 }
5888
5889 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5890 {
5891     HRESULT hr = S_OK;
5892
5893     /* enforce only one level of pointer indirection */
5894     if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5895     {
5896         tdesc = tdesc->u.lptdesc;
5897
5898         /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5899          * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into 
5900          * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5901         if ((tdesc->vt == VT_USERDEFINED) ||
5902             ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5903         {
5904             VARTYPE vt_userdefined = 0;
5905             const TYPEDESC *tdesc_userdefined = tdesc;
5906             if (tdesc->vt == VT_PTR)
5907             {
5908                 vt_userdefined = VT_BYREF;
5909                 tdesc_userdefined = tdesc->u.lptdesc;
5910             }
5911             hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5912             if ((hr == S_OK) && 
5913                 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5914                  ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5915             {
5916                 *vt |= vt_userdefined;
5917                 return S_OK;
5918             }
5919         }
5920         *vt = VT_BYREF;
5921     }
5922
5923     switch (tdesc->vt)
5924     {
5925     case VT_HRESULT:
5926         *vt |= VT_ERROR;
5927         break;
5928     case VT_USERDEFINED:
5929         hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5930         break;
5931     case VT_VOID:
5932     case VT_CARRAY:
5933     case VT_PTR:
5934     case VT_LPSTR:
5935     case VT_LPWSTR:
5936         ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5937         hr = DISP_E_BADVARTYPE;
5938         break;
5939     case VT_SAFEARRAY:
5940         *vt |= VT_ARRAY;
5941         hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5942         break;
5943     case VT_INT:
5944         *vt |= VT_I4;
5945         break;
5946     case VT_UINT:
5947         *vt |= VT_UI4;
5948         break;
5949     default:
5950         *vt |= tdesc->vt;
5951         break;
5952     }
5953     return hr;
5954 }
5955
5956 /***********************************************************************
5957  *              DispCallFunc (OLEAUT32.@)
5958  *
5959  * Invokes a function of the specified calling convention, passing the
5960  * specified arguments and returns the result.
5961  *
5962  * PARAMS
5963  *  pvInstance  [I] Optional pointer to the instance whose function to invoke.
5964  *  oVft        [I] The offset in the vtable. See notes.
5965  *  cc          [I] Calling convention of the function to call.
5966  *  vtReturn    [I] The return type of the function.
5967  *  cActuals    [I] Number of parameters.
5968  *  prgvt       [I] The types of the parameters to pass. This is used for sizing only.
5969  *  prgpvarg    [I] The arguments to pass.
5970  *  pvargResult [O] The return value of the function. Can be NULL.
5971  *
5972  * RETURNS
5973  *  Success: S_OK.
5974  *  Failure: HRESULT code.
5975  *
5976  * NOTES
5977  *  The HRESULT return value of this function is not affected by the return
5978  *  value of the user supplied function, which is returned in pvargResult.
5979  *
5980  *  If pvInstance is NULL then a non-object function is to be called and oVft
5981  *  is the address of the function to call.
5982  *
5983  * The cc parameter can be one of the following values:
5984  *|CC_FASTCALL
5985  *|CC_CDECL
5986  *|CC_PASCAL
5987  *|CC_STDCALL
5988  *|CC_FPFASTCALL
5989  *|CC_SYSCALL
5990  *|CC_MPWCDECL
5991  *|CC_MPWPASCAL
5992  *
5993  */
5994 HRESULT WINAPI
5995 DispCallFunc(
5996     void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5997     VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5998 {
5999 #ifdef __i386__
6000     int argspos, stack_offset;
6001     void *func;
6002     UINT i;
6003     DWORD *args;
6004
6005     TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6006         pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6007         pvargResult, V_VT(pvargResult));
6008
6009     if (cc != CC_STDCALL && cc != CC_CDECL)
6010     {
6011         FIXME("unsupported calling convention %d\n",cc);
6012         return E_INVALIDARG;
6013     }
6014
6015     /* maximum size for an argument is sizeof(VARIANT) */
6016     args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6017
6018     /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6019     argspos = 1;
6020     if (pvInstance)
6021     {
6022         const FARPROC *vtable = *(FARPROC **)pvInstance;
6023         func = vtable[oVft/sizeof(void *)];
6024         args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6025     }
6026     else func = (void *)oVft;
6027
6028     for (i = 0; i < cActuals; i++)
6029     {
6030         VARIANT *arg = prgpvarg[i];
6031
6032         switch (prgvt[i])
6033         {
6034         case VT_EMPTY:
6035             break;
6036         case VT_I8:
6037         case VT_UI8:
6038         case VT_R8:
6039         case VT_DATE:
6040         case VT_CY:
6041             memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6042             argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6043             break;
6044         case VT_DECIMAL:
6045         case VT_VARIANT:
6046             memcpy( &args[argspos], arg, sizeof(*arg) );
6047             argspos += sizeof(*arg) / sizeof(DWORD);
6048             break;
6049         case VT_BOOL:  /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6050             args[argspos++] = V_BOOL(arg);
6051             break;
6052         default:
6053             args[argspos++] = V_UI4(arg);
6054             break;
6055         }
6056         TRACE("arg %u: type %d\n",i,prgvt[i]);
6057         dump_Variant(arg);
6058     }
6059
6060     switch (vtReturn)
6061     {
6062     case VT_EMPTY:
6063         call_method( func, argspos - 1, args + 1, &stack_offset );
6064         break;
6065     case VT_R4:
6066         V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6067         break;
6068     case VT_R8:
6069     case VT_DATE:
6070         V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6071         break;
6072     case VT_DECIMAL:
6073     case VT_VARIANT:
6074         args[0] = (DWORD)pvargResult;  /* arg 0 is a pointer to the result */
6075         call_method( func, argspos, args, &stack_offset );
6076         break;
6077     case VT_I8:
6078     case VT_UI8:
6079     case VT_CY:
6080         V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6081         break;
6082     default:
6083         V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6084         break;
6085     }
6086     heap_free( args );
6087     if (stack_offset && cc == CC_STDCALL)
6088     {
6089         WARN( "stack pointer off by %d\n", stack_offset );
6090         return DISP_E_BADCALLEE;
6091     }
6092     if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6093     TRACE("retval: "); dump_Variant(pvargResult);
6094     return S_OK;
6095
6096 #elif defined(__x86_64__)
6097     int argspos;
6098     UINT i;
6099     DWORD_PTR *args;
6100     void *func;
6101
6102     TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6103           pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6104           pvargResult, V_VT(pvargResult));
6105
6106     if (cc != CC_STDCALL && cc != CC_CDECL)
6107     {
6108         FIXME("unsupported calling convention %d\n",cc);
6109         return E_INVALIDARG;
6110     }
6111
6112     /* maximum size for an argument is sizeof(DWORD_PTR) */
6113     args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6114
6115     /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6116     argspos = 1;
6117     if (pvInstance)
6118     {
6119         const FARPROC *vtable = *(FARPROC **)pvInstance;
6120         func = vtable[oVft/sizeof(void *)];
6121         args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6122     }
6123     else func = (void *)oVft;
6124
6125     for (i = 0; i < cActuals; i++)
6126     {
6127         VARIANT *arg = prgpvarg[i];
6128
6129         switch (prgvt[i])
6130         {
6131         case VT_DECIMAL:
6132         case VT_VARIANT:
6133             args[argspos++] = (ULONG_PTR)arg;
6134             break;
6135         case VT_BOOL:  /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6136             args[argspos++] = V_BOOL(arg);
6137             break;
6138         default:
6139             args[argspos++] = V_UI8(arg);
6140             break;
6141         }
6142         TRACE("arg %u: type %d\n",i,prgvt[i]);
6143         dump_Variant(arg);
6144     }
6145
6146     switch (vtReturn)
6147     {
6148     case VT_R4:
6149         V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6150         break;
6151     case VT_R8:
6152     case VT_DATE:
6153         V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6154         break;
6155     case VT_DECIMAL:
6156     case VT_VARIANT:
6157         args[0] = (DWORD_PTR)pvargResult;  /* arg 0 is a pointer to the result */
6158         call_method( func, argspos, args );
6159         break;
6160     default:
6161         V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6162         break;
6163     }
6164     heap_free( args );
6165     if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6166     TRACE("retval: "); dump_Variant(pvargResult);
6167     return S_OK;
6168
6169 #else
6170     FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6171            pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6172     return E_NOTIMPL;
6173 #endif
6174 }
6175
6176 #define INVBUF_ELEMENT_SIZE \
6177     (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6178 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6179 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6180     ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6181 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6182     ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6183 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6184     ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6185
6186 static HRESULT WINAPI ITypeInfo_fnInvoke(
6187     ITypeInfo2 *iface,
6188     VOID  *pIUnk,
6189     MEMBERID memid,
6190     UINT16 wFlags,
6191     DISPPARAMS  *pDispParams,
6192     VARIANT  *pVarResult,
6193     EXCEPINFO  *pExcepInfo,
6194     UINT  *pArgErr)
6195 {
6196     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6197     int i;
6198     unsigned int var_index;
6199     TYPEKIND type_kind;
6200     HRESULT hres;
6201     const TLBFuncDesc *pFuncInfo;
6202
6203     TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6204       This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6205     );
6206
6207     if( This->TypeAttr.wTypeFlags & TYPEFLAG_FRESTRICTED )
6208         return DISP_E_MEMBERNOTFOUND;
6209
6210     if (!pDispParams)
6211     {
6212         ERR("NULL pDispParams not allowed\n");
6213         return E_INVALIDARG;
6214     }
6215
6216     dump_DispParms(pDispParams);
6217
6218     if (pDispParams->cNamedArgs > pDispParams->cArgs)
6219     {
6220         ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6221             pDispParams->cNamedArgs, pDispParams->cArgs);
6222         return E_INVALIDARG;
6223     }
6224
6225     /* we do this instead of using GetFuncDesc since it will return a fake
6226      * FUNCDESC for dispinterfaces and we want the real function description */
6227     for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
6228         if ((memid == pFuncInfo->funcdesc.memid) &&
6229             (wFlags & pFuncInfo->funcdesc.invkind) &&
6230             (pFuncInfo->funcdesc.wFuncFlags & FUNCFLAG_FRESTRICTED) == 0)
6231             break;
6232
6233     if (pFuncInfo) {
6234         const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6235
6236         if (TRACE_ON(ole))
6237         {
6238             TRACE("invoking:\n");
6239             dump_TLBFuncDescOne(pFuncInfo);
6240         }
6241         
6242         switch (func_desc->funckind) {
6243         case FUNC_PUREVIRTUAL:
6244         case FUNC_VIRTUAL: {
6245             void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6246             VARIANT varresult;
6247             VARIANT retval; /* pointer for storing byref retvals in */
6248             VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6249             VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6250             VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6251             UINT cNamedArgs = pDispParams->cNamedArgs;
6252             DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6253             UINT vargs_converted=0;
6254
6255             hres = S_OK;
6256
6257             if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6258             {
6259                 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6260                 {
6261                     ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6262                     hres = DISP_E_PARAMNOTFOUND;
6263                     goto func_fail;
6264                 }
6265             }
6266
6267             if (func_desc->cParamsOpt < 0 && cNamedArgs)
6268             {
6269                 ERR("functions with the vararg attribute do not support named arguments\n");
6270                 hres = DISP_E_NONAMEDARGS;
6271                 goto func_fail;
6272             }
6273
6274             for (i = 0; i < func_desc->cParams; i++)
6275             {
6276                 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6277                 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6278                 if (FAILED(hres))
6279                     goto func_fail;
6280             }
6281
6282             TRACE("changing args\n");
6283             for (i = 0; i < func_desc->cParams; i++)
6284             {
6285                 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6286                 VARIANTARG *src_arg;
6287
6288                 if (wParamFlags & PARAMFLAG_FLCID)
6289                 {
6290                     VARIANTARG *arg;
6291                     arg = prgpvarg[i] = &rgvarg[i];
6292                     V_VT(arg) = VT_I4;
6293                     V_I4(arg) = This->pTypeLib->lcid;
6294                     continue;
6295                 }
6296
6297                 src_arg = NULL;
6298
6299                 if (cNamedArgs)
6300                 {
6301                     USHORT j;
6302                     for (j = 0; j < cNamedArgs; j++)
6303                         if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6304                         {
6305                             src_arg = &pDispParams->rgvarg[j];
6306                             break;
6307                         }
6308                 }
6309
6310                 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6311                 {
6312                     src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6313                     vargs_converted++;
6314                 }
6315
6316                 if (wParamFlags & PARAMFLAG_FRETVAL)
6317                 {
6318                     /* under most conditions the caller is not allowed to
6319                      * pass in a dispparam arg in the index of what would be
6320                      * the retval parameter. however, there is an exception
6321                      * where the extra parameter is used in an extra
6322                      * IDispatch::Invoke below */
6323                     if ((i < pDispParams->cArgs) &&
6324                         ((func_desc->cParams != 1) || !pVarResult ||
6325                          !(func_desc->invkind & INVOKE_PROPERTYGET)))
6326                     {
6327                         hres = DISP_E_BADPARAMCOUNT;
6328                         break;
6329                     }
6330
6331                     /* note: this check is placed so that if the caller passes
6332                      * in a VARIANTARG for the retval we just ignore it, like
6333                      * native does */
6334                     if (i == func_desc->cParams - 1)
6335                     {
6336                         VARIANTARG *arg;
6337                         arg = prgpvarg[i] = &rgvarg[i];
6338                         memset(arg, 0, sizeof(*arg));
6339                         V_VT(arg) = rgvt[i];
6340                         memset(&retval, 0, sizeof(retval));
6341                         V_BYREF(arg) = &retval;
6342                     }
6343                     else
6344                     {
6345                         ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6346                         hres = E_UNEXPECTED;
6347                         break;
6348                     }
6349                 }
6350                 else if (src_arg)
6351                 {
6352                     dump_Variant(src_arg);
6353
6354                     if (rgvt[i] == VT_VARIANT)
6355                         hres = VariantCopy(&rgvarg[i], src_arg);
6356                     else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6357                     {
6358                         if (rgvt[i] == V_VT(src_arg))
6359                             V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6360                         else
6361                         {
6362                             VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6363                             if (wParamFlags & PARAMFLAG_FIN)
6364                                 hres = VariantCopy(&missing_arg[i], src_arg);
6365                             V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6366                         }
6367                         V_VT(&rgvarg[i]) = rgvt[i];
6368                     }
6369                     else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6370                     {
6371                         SAFEARRAY *a;
6372                         SAFEARRAYBOUND bound;
6373                         VARIANT *v;
6374                         LONG j;
6375                         bound.lLbound = 0;
6376                         bound.cElements = pDispParams->cArgs-i;
6377                         if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6378                         {
6379                             ERR("SafeArrayCreate failed\n");
6380                             break;
6381                         }
6382                         hres = SafeArrayAccessData(a, (LPVOID)&v);
6383                         if (hres != S_OK)
6384                         {
6385                             ERR("SafeArrayAccessData failed with %x\n", hres);
6386                             break;
6387                         }
6388                         for (j = 0; j < bound.cElements; j++)
6389                             VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6390                         hres = SafeArrayUnaccessData(a);
6391                         if (hres != S_OK)
6392                         {
6393                             ERR("SafeArrayUnaccessData failed with %x\n", hres);
6394                             break;
6395                         }
6396                         V_ARRAY(&rgvarg[i]) = a;
6397                         V_VT(&rgvarg[i]) = rgvt[i];
6398                     }
6399                     else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6400                     {
6401                         VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6402                         if (wParamFlags & PARAMFLAG_FIN)
6403                             hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6404                         else
6405                             V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6406                         V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6407                         V_VT(&rgvarg[i]) = rgvt[i];
6408                     }
6409                     else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6410                     {
6411                         V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6412                         V_VT(&rgvarg[i]) = rgvt[i];
6413                     }
6414                     else
6415                     {
6416                         /* FIXME: this doesn't work for VT_BYREF arguments if
6417                          * they are not the same type as in the paramdesc */
6418                         V_VT(&rgvarg[i]) = V_VT(src_arg);
6419                         hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6420                         V_VT(&rgvarg[i]) = rgvt[i];
6421                     }
6422
6423                     if (FAILED(hres))
6424                     {
6425                         ERR("failed to convert param %d to %s%s from %s%s\n", i,
6426                             debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6427                             debugstr_VT(src_arg), debugstr_VF(src_arg));
6428                         break;
6429                     }
6430                     prgpvarg[i] = &rgvarg[i];
6431                 }
6432                 else if (wParamFlags & PARAMFLAG_FOPT)
6433                 {
6434                     VARIANTARG *arg;
6435                     arg = prgpvarg[i] = &rgvarg[i];
6436                     if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6437                     {
6438                         hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6439                         if (FAILED(hres))
6440                             break;
6441                     }
6442                     else
6443                     {
6444                         VARIANTARG *missing_arg;
6445                         /* if the function wants a pointer to a variant then
6446                          * set that up, otherwise just pass the VT_ERROR in
6447                          * the argument by value */
6448                         if (rgvt[i] & VT_BYREF)
6449                         {
6450                             missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6451                             V_VT(arg) = VT_VARIANT | VT_BYREF;
6452                             V_VARIANTREF(arg) = missing_arg;
6453                         }
6454                         else
6455                             missing_arg = arg;
6456                         V_VT(missing_arg) = VT_ERROR;
6457                         V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6458                     }
6459                 }
6460                 else
6461                 {
6462                     hres = DISP_E_BADPARAMCOUNT;
6463                     break;
6464                 }
6465             }
6466             if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6467
6468             /* VT_VOID is a special case for return types, so it is not
6469              * handled in the general function */
6470             if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6471                 V_VT(&varresult) = VT_EMPTY;
6472             else
6473             {
6474                 V_VT(&varresult) = 0;
6475                 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6476                 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6477             }
6478
6479             hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6480                                 V_VT(&varresult), func_desc->cParams, rgvt,
6481                                 prgpvarg, &varresult);
6482
6483             vargs_converted = 0;
6484
6485             for (i = 0; i < func_desc->cParams; i++)
6486             {
6487                 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6488                 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6489
6490                 if (wParamFlags & PARAMFLAG_FLCID)
6491                     continue;
6492                 else if (wParamFlags & PARAMFLAG_FRETVAL)
6493                 {
6494                     if (TRACE_ON(ole))
6495                     {
6496                         TRACE("[retval] value: ");
6497                         dump_Variant(prgpvarg[i]);
6498                     }
6499
6500                     if (pVarResult)
6501                     {
6502                         VariantInit(pVarResult);
6503                         /* deref return value */
6504                         hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6505                     }
6506
6507                     VARIANT_ClearInd(prgpvarg[i]);
6508                 }
6509                 else if (vargs_converted < pDispParams->cArgs)
6510                 {
6511                     VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6512                     if (wParamFlags & PARAMFLAG_FOUT)
6513                     {
6514                         if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6515                         {
6516                             hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6517
6518                             if (FAILED(hres))
6519                             {
6520                                 ERR("failed to convert param %d to vt %d\n", i,
6521                                     V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6522                                 break;
6523                             }
6524                         }
6525                     }
6526                     else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6527                              func_desc->cParamsOpt < 0 &&
6528                              i == func_desc->cParams-1)
6529                     {
6530                         SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6531                         LONG j, ubound;
6532                         VARIANT *v;
6533                         hres = SafeArrayGetUBound(a, 1, &ubound);
6534                         if (hres != S_OK)
6535                         {
6536                             ERR("SafeArrayGetUBound failed with %x\n", hres);
6537                             break;
6538                         }
6539                         hres = SafeArrayAccessData(a, (LPVOID)&v);
6540                         if (hres != S_OK)
6541                         {
6542                             ERR("SafeArrayAccessData failed with %x\n", hres);
6543                             break;
6544                         }
6545                         for (j = 0; j <= ubound; j++)
6546                             VariantClear(&v[j]);
6547                         hres = SafeArrayUnaccessData(a);
6548                         if (hres != S_OK)
6549                         {
6550                             ERR("SafeArrayUnaccessData failed with %x\n", hres);
6551                             break;
6552                         }
6553                     }
6554                     VariantClear(&rgvarg[i]);
6555                     vargs_converted++;
6556                 }
6557                 else if (wParamFlags & PARAMFLAG_FOPT)
6558                 {
6559                     if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6560                         VariantClear(&rgvarg[i]);
6561                 }
6562
6563                 VariantClear(&missing_arg[i]);
6564             }
6565
6566             if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6567             {
6568                 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6569                 hres = DISP_E_EXCEPTION;
6570                 if (pExcepInfo)
6571                 {
6572                     IErrorInfo *pErrorInfo;
6573                     pExcepInfo->scode = V_ERROR(&varresult);
6574                     if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6575                     {
6576                         IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6577                         IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6578                         IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6579                         IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6580
6581                         IErrorInfo_Release(pErrorInfo);
6582                     }
6583                 }
6584             }
6585             if (V_VT(&varresult) != VT_ERROR)
6586             {
6587                 TRACE("varresult value: ");
6588                 dump_Variant(&varresult);
6589
6590                 if (pVarResult)
6591                 {
6592                     VariantClear(pVarResult);
6593                     *pVarResult = varresult;
6594                 }
6595                 else
6596                     VariantClear(&varresult);
6597             }
6598
6599             if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6600                 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6601                 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6602                 (pDispParams->cArgs != 0))
6603             {
6604                 if (V_VT(pVarResult) == VT_DISPATCH)
6605                 {
6606                     IDispatch *pDispatch = V_DISPATCH(pVarResult);
6607                     /* Note: not VariantClear; we still need the dispatch
6608                      * pointer to be valid */
6609                     VariantInit(pVarResult);
6610                     hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6611                         GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6612                         pDispParams, pVarResult, pExcepInfo, pArgErr);
6613                     IDispatch_Release(pDispatch);
6614                 }
6615                 else
6616                 {
6617                     VariantClear(pVarResult);
6618                     hres = DISP_E_NOTACOLLECTION;
6619                 }
6620             }
6621
6622 func_fail:
6623             heap_free(buffer);
6624             break;
6625         }
6626         case FUNC_DISPATCH:  {
6627            IDispatch *disp;
6628
6629            hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6630            if (SUCCEEDED(hres)) {
6631                FIXME("Calling Invoke in IDispatch iface. untested!\n");
6632                hres = IDispatch_Invoke(
6633                                      disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6634                                      pVarResult,pExcepInfo,pArgErr
6635                                      );
6636                if (FAILED(hres))
6637                    FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6638                IDispatch_Release(disp);
6639            } else
6640                FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6641            break;
6642         }
6643         default:
6644             FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6645             hres = E_FAIL;
6646             break;
6647         }
6648
6649         TRACE("-- 0x%08x\n", hres);
6650         return hres;
6651
6652     } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6653         VARDESC *var_desc;
6654
6655         hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6656         if(FAILED(hres)) return hres;
6657         
6658         FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6659         dump_VARDESC(var_desc);
6660         ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6661         return E_NOTIMPL;
6662     }
6663
6664     /* not found, look for it in inherited interfaces */
6665     ITypeInfo2_GetTypeKind(iface, &type_kind);
6666     if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6667         if(This->impltypelist) {
6668             /* recursive search */
6669             ITypeInfo *pTInfo;
6670             hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6671             if(SUCCEEDED(hres)){
6672                 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6673                 ITypeInfo_Release(pTInfo);
6674                 return hres;
6675             }
6676             WARN("Could not search inherited interface!\n");
6677         }
6678     }
6679     WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6680     return DISP_E_MEMBERNOTFOUND;
6681 }
6682
6683 /* ITypeInfo::GetDocumentation
6684  *
6685  * Retrieves the documentation string, the complete Help file name and path,
6686  * and the context ID for the Help topic for a specified type description.
6687  *
6688  * (Can be tested by the Visual Basic Editor in Word for instance.)
6689  */
6690 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6691         MEMBERID memid, BSTR  *pBstrName, BSTR  *pBstrDocString,
6692         DWORD  *pdwHelpContext, BSTR  *pBstrHelpFile)
6693 {
6694     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6695     const TLBFuncDesc *pFDesc;
6696     const TLBVarDesc *pVDesc;
6697     TRACE("(%p) memid %d Name(%p) DocString(%p)"
6698           " HelpContext(%p) HelpFile(%p)\n",
6699         This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6700     if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6701         if(pBstrName)
6702             *pBstrName=SysAllocString(This->Name);
6703         if(pBstrDocString)
6704             *pBstrDocString=SysAllocString(This->DocString);
6705         if(pdwHelpContext)
6706             *pdwHelpContext=This->dwHelpContext;
6707         if(pBstrHelpFile)
6708             *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6709         return S_OK;
6710     }else {/* for a member */
6711     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6712         if(pFDesc->funcdesc.memid==memid){
6713           if(pBstrName)
6714             *pBstrName = SysAllocString(pFDesc->Name);
6715           if(pBstrDocString)
6716             *pBstrDocString=SysAllocString(pFDesc->HelpString);
6717           if(pdwHelpContext)
6718             *pdwHelpContext=pFDesc->helpcontext;
6719           return S_OK;
6720         }
6721     for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6722         if(pVDesc->vardesc.memid==memid){
6723             if(pBstrName)
6724               *pBstrName = SysAllocString(pVDesc->Name);
6725             if(pBstrDocString)
6726               *pBstrDocString=SysAllocString(pVDesc->HelpString);
6727             if(pdwHelpContext)
6728               *pdwHelpContext=pVDesc->HelpContext;
6729             return S_OK;
6730         }
6731     }
6732
6733     if(This->impltypelist &&
6734        (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6735         /* recursive search */
6736         ITypeInfo *pTInfo;
6737         HRESULT result;
6738         result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6739                                         &pTInfo);
6740         if(SUCCEEDED(result)) {
6741             result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6742                 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6743             ITypeInfo_Release(pTInfo);
6744             return result;
6745         }
6746         WARN("Could not search inherited interface!\n");
6747     }
6748
6749     WARN("member %d not found\n", memid);
6750     return TYPE_E_ELEMENTNOTFOUND;
6751 }
6752
6753 /*  ITypeInfo::GetDllEntry
6754  *
6755  * Retrieves a description or specification of an entry point for a function
6756  * in a DLL.
6757  */
6758 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6759         INVOKEKIND invKind, BSTR  *pBstrDllName, BSTR  *pBstrName,
6760         WORD  *pwOrdinal)
6761 {
6762     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6763     const TLBFuncDesc *pFDesc;
6764
6765     TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6766
6767     if (pBstrDllName) *pBstrDllName = NULL;
6768     if (pBstrName) *pBstrName = NULL;
6769     if (pwOrdinal) *pwOrdinal = 0;
6770
6771     if (This->TypeAttr.typekind != TKIND_MODULE)
6772         return TYPE_E_BADMODULEKIND;
6773
6774     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6775         if(pFDesc->funcdesc.memid==memid){
6776             dump_TypeInfo(This);
6777             if (TRACE_ON(ole))
6778                 dump_TLBFuncDescOne(pFDesc);
6779
6780             if (pBstrDllName)
6781                 *pBstrDllName = SysAllocString(This->DllName);
6782
6783             if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6784                 if (pBstrName)
6785                     *pBstrName = SysAllocString(pFDesc->Entry);
6786                 if (pwOrdinal)
6787                     *pwOrdinal = -1;
6788                 return S_OK;
6789             }
6790             if (pBstrName)
6791                 *pBstrName = NULL;
6792             if (pwOrdinal)
6793                 *pwOrdinal = LOWORD(pFDesc->Entry);
6794             return S_OK;
6795         }
6796     return TYPE_E_ELEMENTNOTFOUND;
6797 }
6798
6799 /* internal function to make the inherited interfaces' methods appear
6800  * part of the interface */
6801 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6802     HREFTYPE *hRefType, ITypeInfo  **ppTInfo)
6803 {
6804     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6805     HRESULT hr;
6806
6807     TRACE("%p, 0x%x\n", iface, *hRefType);
6808
6809     if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6810     {
6811         ITypeInfo *pSubTypeInfo;
6812
6813         hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6814         if (FAILED(hr))
6815             return hr;
6816
6817         hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6818                                                   hRefType, ppTInfo);
6819         ITypeInfo_Release(pSubTypeInfo);
6820         if (SUCCEEDED(hr))
6821             return hr;
6822     }
6823     *hRefType -= DISPATCH_HREF_OFFSET;
6824
6825     if (!(*hRefType & DISPATCH_HREF_MASK))
6826         return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6827     else
6828         return E_FAIL;
6829 }
6830
6831 /* ITypeInfo::GetRefTypeInfo
6832  *
6833  * If a type description references other type descriptions, it retrieves
6834  * the referenced type descriptions.
6835  */
6836 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6837         ITypeInfo2 *iface,
6838         HREFTYPE hRefType,
6839         ITypeInfo  **ppTInfo)
6840 {
6841     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6842     HRESULT result = E_FAIL;
6843
6844     if ((This->hreftype != -1) && (This->hreftype == hRefType))
6845     {
6846         *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6847         ITypeInfo_AddRef(*ppTInfo);
6848         result = S_OK;
6849     }
6850     else if (hRefType == -1 &&
6851         (This->TypeAttr.typekind   == TKIND_DISPATCH) &&
6852         (This->TypeAttr.wTypeFlags &  TYPEFLAG_FDUAL))
6853     {
6854           /* when we meet a DUAL dispinterface, we must create the interface
6855           * version of it.
6856           */
6857           ITypeInfoImpl *pTypeInfoImpl = ITypeInfoImpl_Constructor();
6858
6859
6860           /* the interface version contains the same information as the dispinterface
6861            * copy the contents of the structs.
6862            */
6863           *pTypeInfoImpl = *This;
6864           pTypeInfoImpl->ref = 0;
6865
6866           /* change the type to interface */
6867           pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6868
6869           *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6870
6871           /* the AddRef implicitly adds a reference to the parent typelib, which
6872            * stops the copied data from being destroyed until the new typeinfo's
6873            * refcount goes to zero, but we need to signal to the new instance to
6874            * not free its data structures when it is destroyed */
6875           pTypeInfoImpl->not_attached_to_typelib = TRUE;
6876
6877           ITypeInfo_AddRef(*ppTInfo);
6878
6879           result = S_OK;
6880
6881     } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6882         (This->TypeAttr.typekind   == TKIND_DISPATCH))
6883     {
6884         HREFTYPE href_dispatch = hRefType;
6885         result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6886     } else {
6887         TLBRefType *ref_type;
6888         LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6889         {
6890             if(ref_type->reference == hRefType)
6891                 break;
6892         }
6893         if(&ref_type->entry == &This->pTypeLib->ref_list)
6894         {
6895             FIXME("Can't find pRefType for ref %x\n", hRefType);
6896             goto end;
6897         }
6898         if(hRefType != -1) {
6899             ITypeLib *pTLib = NULL;
6900
6901             if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6902                 UINT Index;
6903                 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6904             } else {
6905                 if(ref_type->pImpTLInfo->pImpTypeLib) {
6906                     TRACE("typeinfo in imported typelib that is already loaded\n");
6907                     pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6908                     ITypeLib2_AddRef(pTLib);
6909                     result = S_OK;
6910                 } else {
6911                     TRACE("typeinfo in imported typelib that isn't already loaded\n");
6912                     result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6913                                              ref_type->pImpTLInfo->wVersionMajor,
6914                                              ref_type->pImpTLInfo->wVersionMinor,
6915                                              ref_type->pImpTLInfo->lcid,
6916                                              &pTLib);
6917
6918                     if(FAILED(result)) {
6919                         BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6920                         result=LoadTypeLib(libnam, &pTLib);
6921                         SysFreeString(libnam);
6922                     }
6923                     if(SUCCEEDED(result)) {
6924                         ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6925                         ITypeLib2_AddRef(pTLib);
6926                     }
6927                 }
6928             }
6929             if(SUCCEEDED(result)) {
6930                 if(ref_type->index == TLB_REF_USE_GUID)
6931                     result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6932                                                          &ref_type->guid,
6933                                                          ppTInfo);
6934                 else
6935                     result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6936                                                    ppTInfo);
6937             }
6938             if (pTLib != NULL)
6939                 ITypeLib2_Release(pTLib);
6940         }
6941     }
6942
6943 end:
6944     TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6945           SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6946     return result;
6947 }
6948
6949 /* ITypeInfo::AddressOfMember
6950  *
6951  * Retrieves the addresses of static functions or variables, such as those
6952  * defined in a DLL.
6953  */
6954 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6955         MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6956 {
6957     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6958     HRESULT hr;
6959     BSTR dll, entry;
6960     WORD ordinal;
6961     HMODULE module;
6962
6963     TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6964
6965     hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6966     if (FAILED(hr))
6967         return hr;
6968
6969     module = LoadLibraryW(dll);
6970     if (!module)
6971     {
6972         ERR("couldn't load %s\n", debugstr_w(dll));
6973         SysFreeString(dll);
6974         SysFreeString(entry);
6975         return STG_E_FILENOTFOUND;
6976     }
6977     /* FIXME: store library somewhere where we can free it */
6978
6979     if (entry)
6980     {
6981         LPSTR entryA;
6982         INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6983         entryA = heap_alloc(len);
6984         WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6985
6986         *ppv = GetProcAddress(module, entryA);
6987         if (!*ppv)
6988             ERR("function not found %s\n", debugstr_a(entryA));
6989
6990         heap_free(entryA);
6991     }
6992     else
6993     {
6994         *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6995         if (!*ppv)
6996             ERR("function not found %d\n", ordinal);
6997     }
6998
6999     SysFreeString(dll);
7000     SysFreeString(entry);
7001
7002     if (!*ppv)
7003         return TYPE_E_DLLFUNCTIONNOTFOUND;
7004
7005     return S_OK;
7006 }
7007
7008 /* ITypeInfo::CreateInstance
7009  *
7010  * Creates a new instance of a type that describes a component object class
7011  * (coclass).
7012  */
7013 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7014         IUnknown *pOuterUnk, REFIID riid, VOID  **ppvObj)
7015 {
7016     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7017     HRESULT hr;
7018     TYPEATTR *pTA;
7019
7020     TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7021
7022     *ppvObj = NULL;
7023
7024     if(pOuterUnk)
7025     {
7026         WARN("Not able to aggregate\n");
7027         return CLASS_E_NOAGGREGATION;
7028     }
7029
7030     hr = ITypeInfo_GetTypeAttr(iface, &pTA);
7031     if(FAILED(hr)) return hr;
7032
7033     if(pTA->typekind != TKIND_COCLASS)
7034     {
7035         WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7036         hr = E_INVALIDARG;
7037         goto end;
7038     }
7039
7040     hr = S_FALSE;
7041     if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7042     {
7043         IUnknown *pUnk;
7044         hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7045         TRACE("GetActiveObject rets %08x\n", hr);
7046         if(hr == S_OK)
7047         {
7048             hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7049             IUnknown_Release(pUnk);
7050         }
7051     }
7052
7053     if(hr != S_OK)
7054         hr = CoCreateInstance(&pTA->guid, NULL,
7055                               CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7056                               riid, ppvObj);
7057
7058 end:
7059     ITypeInfo_ReleaseTypeAttr(iface, pTA);
7060     return hr;
7061 }
7062
7063 /* ITypeInfo::GetMops
7064  *
7065  * Retrieves marshalling information.
7066  */
7067 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7068                                 BSTR  *pBstrMops)
7069 {
7070     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7071     FIXME("(%p %d) stub!\n", This, memid);
7072     *pBstrMops = NULL;
7073     return S_OK;
7074 }
7075
7076 /* ITypeInfo::GetContainingTypeLib
7077  *
7078  * Retrieves the containing type library and the index of the type description
7079  * within that type library.
7080  */
7081 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7082         ITypeLib  * *ppTLib, UINT  *pIndex)
7083 {
7084     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7085     
7086     /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7087     if (pIndex) {
7088       *pIndex=This->index;
7089       TRACE("returning pIndex=%d\n", *pIndex);
7090     }
7091     
7092     if (ppTLib) {
7093       *ppTLib=(LPTYPELIB )(This->pTypeLib);
7094       ITypeLib2_AddRef(*ppTLib);
7095       TRACE("returning ppTLib=%p\n", *ppTLib);
7096     }
7097     
7098     return S_OK;
7099 }
7100
7101 /* ITypeInfo::ReleaseTypeAttr
7102  *
7103  * Releases a TYPEATTR previously returned by GetTypeAttr.
7104  *
7105  */
7106 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7107         TYPEATTR* pTypeAttr)
7108 {
7109     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7110     TRACE("(%p)->(%p)\n", This, pTypeAttr);
7111     heap_free(pTypeAttr);
7112 }
7113
7114 /* ITypeInfo::ReleaseFuncDesc
7115  *
7116  * Releases a FUNCDESC previously returned by GetFuncDesc. *
7117  */
7118 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7119         ITypeInfo2 *iface,
7120         FUNCDESC *pFuncDesc)
7121 {
7122     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7123     SHORT i;
7124
7125     TRACE("(%p)->(%p)\n", This, pFuncDesc);
7126
7127     for (i = 0; i < pFuncDesc->cParams; i++)
7128         TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7129     TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7130
7131     SysFreeString((BSTR)pFuncDesc);
7132 }
7133
7134 /* ITypeInfo::ReleaseVarDesc
7135  *
7136  * Releases a VARDESC previously returned by GetVarDesc.
7137  */
7138 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7139         VARDESC *pVarDesc)
7140 {
7141     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7142     TRACE("(%p)->(%p)\n", This, pVarDesc);
7143
7144     TLB_FreeElemDesc(&pVarDesc->elemdescVar);
7145     if (pVarDesc->varkind == VAR_CONST)
7146         VariantClear(pVarDesc->u.lpvarValue);
7147     SysFreeString((BSTR)pVarDesc);
7148 }
7149
7150 /* ITypeInfo2::GetTypeKind
7151  *
7152  * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7153  *
7154  */
7155 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7156     TYPEKIND *pTypeKind)
7157 {
7158     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7159     *pTypeKind=This->TypeAttr.typekind;
7160     TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7161     return S_OK;
7162 }
7163
7164 /* ITypeInfo2::GetTypeFlags
7165  *
7166  * Returns the type flags without any allocations. This returns a DWORD type
7167  * flag, which expands the type flags without growing the TYPEATTR (type
7168  * attribute).
7169  *
7170  */
7171 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7172 {
7173     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7174     *pTypeFlags=This->TypeAttr.wTypeFlags;
7175     TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7176     return S_OK;
7177 }
7178
7179 /* ITypeInfo2::GetFuncIndexOfMemId
7180  * Binds to a specific member based on a known DISPID, where the member name
7181  * is not known (for example, when binding to a default member).
7182  *
7183  */
7184 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7185     MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7186 {
7187     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7188     const TLBFuncDesc *pFuncInfo;
7189     int i;
7190     HRESULT result;
7191
7192     for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
7193         if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7194             break;
7195     if(pFuncInfo) {
7196         *pFuncIndex = i;
7197         result = S_OK;
7198     } else
7199         result = TYPE_E_ELEMENTNOTFOUND;
7200
7201     TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7202           memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7203     return result;
7204 }
7205
7206 /* TypeInfo2::GetVarIndexOfMemId
7207  *
7208  * Binds to a specific member based on a known DISPID, where the member name
7209  * is not known (for example, when binding to a default member).
7210  *
7211  */
7212 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7213     MEMBERID memid, UINT *pVarIndex)
7214 {
7215     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7216     TLBVarDesc *pVarInfo;
7217     int i;
7218     HRESULT result;
7219     for(i=0, pVarInfo=This->varlist; pVarInfo &&
7220             memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
7221         ;
7222     if(pVarInfo) {
7223         *pVarIndex = i;
7224         result = S_OK;
7225     } else
7226         result = TYPE_E_ELEMENTNOTFOUND;
7227
7228     TRACE("(%p) memid 0x%08x -> %s\n", This,
7229           memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7230     return result;
7231 }
7232
7233 /* ITypeInfo2::GetCustData
7234  *
7235  * Gets the custom data
7236  */
7237 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7238         ITypeInfo2 * iface,
7239         REFGUID guid,
7240         VARIANT *pVarVal)
7241 {
7242     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7243     TLBCustData *pCData;
7244
7245     for(pCData=This->pCustData; pCData; pCData = pCData->next)
7246         if( IsEqualIID(guid, &pCData->guid)) break;
7247
7248     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7249
7250     VariantInit( pVarVal);
7251     if (pCData)
7252         VariantCopy( pVarVal, &pCData->data);
7253     else
7254         VariantClear( pVarVal );
7255     return S_OK;
7256 }
7257
7258 /* ITypeInfo2::GetFuncCustData
7259  *
7260  * Gets the custom data
7261  */
7262 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7263         ITypeInfo2 * iface,
7264         UINT index,
7265         REFGUID guid,
7266         VARIANT *pVarVal)
7267 {
7268     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7269     TLBCustData *pCData=NULL;
7270     TLBFuncDesc * pFDesc;
7271     UINT i;
7272     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7273             pFDesc=pFDesc->next);
7274
7275     if(pFDesc)
7276         for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7277             if( IsEqualIID(guid, &pCData->guid)) break;
7278
7279     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7280
7281     if(pCData){
7282         VariantInit( pVarVal);
7283         VariantCopy( pVarVal, &pCData->data);
7284         return S_OK;
7285     }
7286     return E_INVALIDARG;  /* FIXME: correct? */
7287 }
7288
7289 /* ITypeInfo2::GetParamCustData
7290  *
7291  * Gets the custom data
7292  */
7293 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7294         ITypeInfo2 * iface,
7295         UINT indexFunc,
7296         UINT indexParam,
7297         REFGUID guid,
7298         VARIANT *pVarVal)
7299 {
7300     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7301     TLBCustData *pCData=NULL;
7302     TLBFuncDesc * pFDesc;
7303     UINT i;
7304
7305     for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7306
7307     if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7308         for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7309                 pCData = pCData->next)
7310             if( IsEqualIID(guid, &pCData->guid)) break;
7311
7312     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7313
7314     if(pCData)
7315     {
7316         VariantInit( pVarVal);
7317         VariantCopy( pVarVal, &pCData->data);
7318         return S_OK;
7319     }
7320     return E_INVALIDARG;  /* FIXME: correct? */
7321 }
7322
7323 /* ITypeInfo2::GetVarCustData
7324  *
7325  * Gets the custom data
7326  */
7327 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7328         ITypeInfo2 * iface,
7329         UINT index,
7330         REFGUID guid,
7331         VARIANT *pVarVal)
7332 {
7333     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7334     TLBCustData *pCData=NULL;
7335     TLBVarDesc * pVDesc;
7336     UINT i;
7337
7338     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7339
7340     if(pVDesc)
7341     {
7342       for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7343       {
7344         if( IsEqualIID(guid, &pCData->guid)) break;
7345       }
7346     }
7347
7348     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7349
7350     if(pCData)
7351     {
7352         VariantInit( pVarVal);
7353         VariantCopy( pVarVal, &pCData->data);
7354         return S_OK;
7355     }
7356     return E_INVALIDARG;  /* FIXME: correct? */
7357 }
7358
7359 /* ITypeInfo2::GetImplCustData
7360  *
7361  * Gets the custom data
7362  */
7363 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7364         ITypeInfo2 * iface,
7365         UINT index,
7366         REFGUID guid,
7367         VARIANT *pVarVal)
7368 {
7369     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7370     TLBCustData *pCData=NULL;
7371     TLBImplType * pRDesc;
7372     UINT i;
7373
7374     for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7375
7376     if(pRDesc)
7377     {
7378       for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7379       {
7380         if( IsEqualIID(guid, &pCData->guid)) break;
7381       }
7382     }
7383
7384     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7385
7386     if(pCData)
7387     {
7388         VariantInit( pVarVal);
7389         VariantCopy( pVarVal, &pCData->data);
7390         return S_OK;
7391     }
7392     return E_INVALIDARG;  /* FIXME: correct? */
7393 }
7394
7395 /* ITypeInfo2::GetDocumentation2
7396  *
7397  * Retrieves the documentation string, the complete Help file name and path,
7398  * the localization context to use, and the context ID for the library Help
7399  * topic in the Help file.
7400  *
7401  */
7402 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7403         ITypeInfo2 * iface,
7404         MEMBERID memid,
7405         LCID lcid,
7406         BSTR *pbstrHelpString,
7407         DWORD *pdwHelpStringContext,
7408         BSTR *pbstrHelpStringDll)
7409 {
7410     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7411     const TLBFuncDesc *pFDesc;
7412     const TLBVarDesc *pVDesc;
7413     TRACE("(%p) memid %d lcid(0x%x)  HelpString(%p) "
7414           "HelpStringContext(%p) HelpStringDll(%p)\n",
7415           This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7416           pbstrHelpStringDll );
7417     /* the help string should be obtained from the helpstringdll,
7418      * using the _DLLGetDocumentation function, based on the supplied
7419      * lcid. Nice to do sometime...
7420      */
7421     if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7422         if(pbstrHelpString)
7423             *pbstrHelpString=SysAllocString(This->Name);
7424         if(pdwHelpStringContext)
7425             *pdwHelpStringContext=This->dwHelpStringContext;
7426         if(pbstrHelpStringDll)
7427             *pbstrHelpStringDll=
7428                 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7429         return S_OK;
7430     }else {/* for a member */
7431     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7432         if(pFDesc->funcdesc.memid==memid){
7433              if(pbstrHelpString)
7434                 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7435             if(pdwHelpStringContext)
7436                 *pdwHelpStringContext=pFDesc->HelpStringContext;
7437             if(pbstrHelpStringDll)
7438                 *pbstrHelpStringDll=
7439                     SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7440         return S_OK;
7441     }
7442     for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7443         if(pVDesc->vardesc.memid==memid){
7444              if(pbstrHelpString)
7445                 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7446             if(pdwHelpStringContext)
7447                 *pdwHelpStringContext=pVDesc->HelpStringContext;
7448             if(pbstrHelpStringDll)
7449                 *pbstrHelpStringDll=
7450                     SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7451             return S_OK;
7452         }
7453     }
7454     return TYPE_E_ELEMENTNOTFOUND;
7455 }
7456
7457 /* ITypeInfo2::GetAllCustData
7458  *
7459  * Gets all custom data items for the Type info.
7460  *
7461  */
7462 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7463         ITypeInfo2 * iface,
7464         CUSTDATA *pCustData)
7465 {
7466     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7467     TLBCustData *pCData;
7468     int i;
7469
7470     TRACE("(%p) returning %d items\n", This, This->ctCustData);
7471
7472     pCustData->prgCustData = heap_alloc_zero(This->ctCustData * sizeof(CUSTDATAITEM));
7473     if(pCustData->prgCustData ){
7474         pCustData->cCustData=This->ctCustData;
7475         for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7476             pCustData->prgCustData[i].guid=pCData->guid;
7477             VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7478         }
7479     }else{
7480         ERR(" OUT OF MEMORY!\n");
7481         return E_OUTOFMEMORY;
7482     }
7483     return S_OK;
7484 }
7485
7486 /* ITypeInfo2::GetAllFuncCustData
7487  *
7488  * Gets all custom data items for the specified Function
7489  *
7490  */
7491 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7492         ITypeInfo2 * iface,
7493         UINT index,
7494         CUSTDATA *pCustData)
7495 {
7496     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7497     TLBCustData *pCData;
7498     TLBFuncDesc * pFDesc;
7499     UINT i;
7500     TRACE("(%p) index %d\n", This, index);
7501     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7502             pFDesc=pFDesc->next)
7503         ;
7504     if(pFDesc){
7505         pCustData->prgCustData =
7506             heap_alloc_zero(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7507         if(pCustData->prgCustData ){
7508             pCustData->cCustData=pFDesc->ctCustData;
7509             for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7510                     pCData = pCData->next){
7511                 pCustData->prgCustData[i].guid=pCData->guid;
7512                 VariantCopy(& pCustData->prgCustData[i].varValue,
7513                         & pCData->data);
7514             }
7515         }else{
7516             ERR(" OUT OF MEMORY!\n");
7517             return E_OUTOFMEMORY;
7518         }
7519         return S_OK;
7520     }
7521     return TYPE_E_ELEMENTNOTFOUND;
7522 }
7523
7524 /* ITypeInfo2::GetAllParamCustData
7525  *
7526  * Gets all custom data items for the Functions
7527  *
7528  */
7529 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7530     UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7531 {
7532     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7533     TLBCustData *pCData=NULL;
7534     TLBFuncDesc * pFDesc;
7535     UINT i;
7536     TRACE("(%p) index %d\n", This, indexFunc);
7537     for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7538             pFDesc=pFDesc->next)
7539         ;
7540     if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7541         pCustData->prgCustData =
7542             heap_alloc_zero(pFDesc->pParamDesc[indexParam].ctCustData *
7543                     sizeof(CUSTDATAITEM));
7544         if(pCustData->prgCustData ){
7545             pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7546             for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7547                     pCData; i++, pCData = pCData->next){
7548                 pCustData->prgCustData[i].guid=pCData->guid;
7549                 VariantCopy(& pCustData->prgCustData[i].varValue,
7550                         & pCData->data);
7551             }
7552         }else{
7553             ERR(" OUT OF MEMORY!\n");
7554             return E_OUTOFMEMORY;
7555         }
7556         return S_OK;
7557     }
7558     return TYPE_E_ELEMENTNOTFOUND;
7559 }
7560
7561 /* ITypeInfo2::GetAllVarCustData
7562  *
7563  * Gets all custom data items for the specified Variable
7564  *
7565  */
7566 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7567     UINT index, CUSTDATA *pCustData)
7568 {
7569     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7570     TLBCustData *pCData;
7571     TLBVarDesc * pVDesc;
7572     UINT i;
7573     TRACE("(%p) index %d\n", This, index);
7574     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7575             pVDesc=pVDesc->next)
7576         ;
7577     if(pVDesc){
7578         pCustData->prgCustData =
7579             heap_alloc_zero(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7580         if(pCustData->prgCustData ){
7581             pCustData->cCustData=pVDesc->ctCustData;
7582             for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7583                     pCData = pCData->next){
7584                 pCustData->prgCustData[i].guid=pCData->guid;
7585                 VariantCopy(& pCustData->prgCustData[i].varValue,
7586                         & pCData->data);
7587             }
7588         }else{
7589             ERR(" OUT OF MEMORY!\n");
7590             return E_OUTOFMEMORY;
7591         }
7592         return S_OK;
7593     }
7594     return TYPE_E_ELEMENTNOTFOUND;
7595 }
7596
7597 /* ITypeInfo2::GetAllImplCustData
7598  *
7599  * Gets all custom data items for the specified implementation type
7600  *
7601  */
7602 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7603         ITypeInfo2 * iface,
7604         UINT index,
7605         CUSTDATA *pCustData)
7606 {
7607     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7608     TLBCustData *pCData;
7609     TLBImplType * pRDesc;
7610     UINT i;
7611     TRACE("(%p) index %d\n", This, index);
7612     for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7613             pRDesc=pRDesc->next)
7614         ;
7615     if(pRDesc){
7616         pCustData->prgCustData =
7617             heap_alloc_zero(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7618         if(pCustData->prgCustData ){
7619             pCustData->cCustData=pRDesc->ctCustData;
7620             for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7621                     pCData = pCData->next){
7622                 pCustData->prgCustData[i].guid=pCData->guid;
7623                 VariantCopy(& pCustData->prgCustData[i].varValue,
7624                         & pCData->data);
7625             }
7626         }else{
7627             ERR(" OUT OF MEMORY!\n");
7628             return E_OUTOFMEMORY;
7629         }
7630         return S_OK;
7631     }
7632     return TYPE_E_ELEMENTNOTFOUND;
7633 }
7634
7635 static const ITypeInfo2Vtbl tinfvt =
7636 {
7637
7638     ITypeInfo_fnQueryInterface,
7639     ITypeInfo_fnAddRef,
7640     ITypeInfo_fnRelease,
7641
7642     ITypeInfo_fnGetTypeAttr,
7643     ITypeInfo_fnGetTypeComp,
7644     ITypeInfo_fnGetFuncDesc,
7645     ITypeInfo_fnGetVarDesc,
7646     ITypeInfo_fnGetNames,
7647     ITypeInfo_fnGetRefTypeOfImplType,
7648     ITypeInfo_fnGetImplTypeFlags,
7649     ITypeInfo_fnGetIDsOfNames,
7650     ITypeInfo_fnInvoke,
7651     ITypeInfo_fnGetDocumentation,
7652     ITypeInfo_fnGetDllEntry,
7653     ITypeInfo_fnGetRefTypeInfo,
7654     ITypeInfo_fnAddressOfMember,
7655     ITypeInfo_fnCreateInstance,
7656     ITypeInfo_fnGetMops,
7657     ITypeInfo_fnGetContainingTypeLib,
7658     ITypeInfo_fnReleaseTypeAttr,
7659     ITypeInfo_fnReleaseFuncDesc,
7660     ITypeInfo_fnReleaseVarDesc,
7661
7662     ITypeInfo2_fnGetTypeKind,
7663     ITypeInfo2_fnGetTypeFlags,
7664     ITypeInfo2_fnGetFuncIndexOfMemId,
7665     ITypeInfo2_fnGetVarIndexOfMemId,
7666     ITypeInfo2_fnGetCustData,
7667     ITypeInfo2_fnGetFuncCustData,
7668     ITypeInfo2_fnGetParamCustData,
7669     ITypeInfo2_fnGetVarCustData,
7670     ITypeInfo2_fnGetImplTypeCustData,
7671     ITypeInfo2_fnGetDocumentation2,
7672     ITypeInfo2_fnGetAllCustData,
7673     ITypeInfo2_fnGetAllFuncCustData,
7674     ITypeInfo2_fnGetAllParamCustData,
7675     ITypeInfo2_fnGetAllVarCustData,
7676     ITypeInfo2_fnGetAllImplTypeCustData,
7677 };
7678
7679 /******************************************************************************
7680  * CreateDispTypeInfo [OLEAUT32.31]
7681  *
7682  * Build type information for an object so it can be called through an
7683  * IDispatch interface.
7684  *
7685  * RETURNS
7686  *  Success: S_OK. pptinfo contains the created ITypeInfo object.
7687  *  Failure: E_INVALIDARG, if one or more arguments is invalid.
7688  *
7689  * NOTES
7690  *  This call allows an objects methods to be accessed through IDispatch, by
7691  *  building an ITypeInfo object that IDispatch can use to call through.
7692  */
7693 HRESULT WINAPI CreateDispTypeInfo(
7694         INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7695         LCID lcid, /* [I] Locale Id */
7696         ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7697 {
7698     ITypeInfoImpl *pTIClass, *pTIIface;
7699     ITypeLibImpl *pTypeLibImpl;
7700     unsigned int param, func;
7701     TLBFuncDesc **ppFuncDesc;
7702     TLBRefType *ref;
7703
7704     TRACE("\n");
7705     pTypeLibImpl = TypeLibImpl_Constructor();
7706     if (!pTypeLibImpl) return E_FAIL;
7707
7708     pTIIface = ITypeInfoImpl_Constructor();
7709     pTIIface->pTypeLib = pTypeLibImpl;
7710     pTIIface->index = 0;
7711     pTIIface->Name = NULL;
7712     pTIIface->dwHelpContext = -1;
7713     memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7714     pTIIface->TypeAttr.lcid = lcid;
7715     pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7716     pTIIface->TypeAttr.wMajorVerNum = 0;
7717     pTIIface->TypeAttr.wMinorVerNum = 0;
7718     pTIIface->TypeAttr.cbAlignment = 2;
7719     pTIIface->TypeAttr.cbSizeInstance = -1;
7720     pTIIface->TypeAttr.cbSizeVft = -1;
7721     pTIIface->TypeAttr.cFuncs = 0;
7722     pTIIface->TypeAttr.cImplTypes = 0;
7723     pTIIface->TypeAttr.cVars = 0;
7724     pTIIface->TypeAttr.wTypeFlags = 0;
7725
7726     ppFuncDesc = &pTIIface->funclist;
7727     for(func = 0; func < pidata->cMembers; func++) {
7728         METHODDATA *md = pidata->pmethdata + func;
7729         *ppFuncDesc = heap_alloc(sizeof(**ppFuncDesc));
7730         (*ppFuncDesc)->Name = SysAllocString(md->szName);
7731         (*ppFuncDesc)->funcdesc.memid = md->dispid;
7732         (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7733         (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7734         (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7735         (*ppFuncDesc)->funcdesc.callconv = md->cc;
7736         (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7737         (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7738         (*ppFuncDesc)->funcdesc.oVft = md->iMeth * sizeof(void *);
7739         (*ppFuncDesc)->funcdesc.cScodes = 0;
7740         (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7741         (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7742         (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7743         (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7744         (*ppFuncDesc)->funcdesc.lprgelemdescParam = heap_alloc_zero(md->cArgs * sizeof(ELEMDESC));
7745         (*ppFuncDesc)->pParamDesc = heap_alloc_zero(md->cArgs * sizeof(TLBParDesc));
7746         for(param = 0; param < md->cArgs; param++) {
7747             (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7748             (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7749         }
7750         (*ppFuncDesc)->helpcontext = 0;
7751         (*ppFuncDesc)->HelpStringContext = 0;
7752         (*ppFuncDesc)->HelpString = NULL;
7753         (*ppFuncDesc)->Entry = NULL;
7754         (*ppFuncDesc)->ctCustData = 0;
7755         (*ppFuncDesc)->pCustData = NULL;
7756         (*ppFuncDesc)->next = NULL;
7757         pTIIface->TypeAttr.cFuncs++;
7758         ppFuncDesc = &(*ppFuncDesc)->next;
7759     }
7760
7761     dump_TypeInfo(pTIIface);
7762
7763     pTypeLibImpl->pTypeInfo = pTIIface;
7764     pTypeLibImpl->TypeInfoCount++;
7765
7766     pTIClass = ITypeInfoImpl_Constructor();
7767     pTIClass->pTypeLib = pTypeLibImpl;
7768     pTIClass->index = 1;
7769     pTIClass->Name = NULL;
7770     pTIClass->dwHelpContext = -1;
7771     memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7772     pTIClass->TypeAttr.lcid = lcid;
7773     pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7774     pTIClass->TypeAttr.wMajorVerNum = 0;
7775     pTIClass->TypeAttr.wMinorVerNum = 0;
7776     pTIClass->TypeAttr.cbAlignment = 2;
7777     pTIClass->TypeAttr.cbSizeInstance = -1;
7778     pTIClass->TypeAttr.cbSizeVft = -1;
7779     pTIClass->TypeAttr.cFuncs = 0;
7780     pTIClass->TypeAttr.cImplTypes = 1;
7781     pTIClass->TypeAttr.cVars = 0;
7782     pTIClass->TypeAttr.wTypeFlags = 0;
7783
7784     pTIClass->impltypelist = heap_alloc_zero(sizeof(*pTIClass->impltypelist));
7785     pTIClass->impltypelist->hRef = 0;
7786
7787     ref = heap_alloc_zero(sizeof(*ref));
7788     ref->index = 0;
7789     ref->reference = 0;
7790     ref->pImpTLInfo = TLB_REF_INTERNAL;
7791     list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7792
7793     dump_TypeInfo(pTIClass);
7794
7795     pTIIface->next = pTIClass;
7796     pTypeLibImpl->TypeInfoCount++;
7797
7798     *pptinfo = (ITypeInfo*)pTIClass;
7799
7800     ITypeInfo_AddRef(*pptinfo);
7801     ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7802
7803     return S_OK;
7804
7805 }
7806
7807 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7808 {
7809     ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7810
7811     return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7812 }
7813
7814 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7815 {
7816     ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7817
7818     return ITypeInfo_AddRef((ITypeInfo *)This);
7819 }
7820
7821 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7822 {
7823     ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7824
7825     return ITypeInfo_Release((ITypeInfo *)This);
7826 }
7827
7828 static HRESULT WINAPI ITypeComp_fnBind(
7829     ITypeComp * iface,
7830     OLECHAR * szName,
7831     ULONG lHash,
7832     WORD wFlags,
7833     ITypeInfo ** ppTInfo,
7834     DESCKIND * pDescKind,
7835     BINDPTR * pBindPtr)
7836 {
7837     ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7838     const TLBFuncDesc *pFDesc;
7839     const TLBVarDesc *pVDesc;
7840     HRESULT hr = DISP_E_MEMBERNOTFOUND;
7841
7842     TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7843
7844     *pDescKind = DESCKIND_NONE;
7845     pBindPtr->lpfuncdesc = NULL;
7846     *ppTInfo = NULL;
7847
7848     for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7849         if (!strcmpiW(pFDesc->Name, szName)) {
7850             if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7851                 break;
7852             else
7853                 /* name found, but wrong flags */
7854                 hr = TYPE_E_TYPEMISMATCH;
7855         }
7856
7857     if (pFDesc)
7858     {
7859         HRESULT hr = TLB_AllocAndInitFuncDesc(
7860             &pFDesc->funcdesc,
7861             &pBindPtr->lpfuncdesc,
7862             This->TypeAttr.typekind == TKIND_DISPATCH);
7863         if (FAILED(hr))
7864             return hr;
7865         *pDescKind = DESCKIND_FUNCDESC;
7866         *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7867         ITypeInfo_AddRef(*ppTInfo);
7868         return S_OK;
7869     } else {
7870         for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7871             if (!strcmpiW(pVDesc->Name, szName)) {
7872                 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7873                 if (FAILED(hr))
7874                     return hr;
7875                 *pDescKind = DESCKIND_VARDESC;
7876                 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7877                 ITypeInfo_AddRef(*ppTInfo);
7878                 return S_OK;
7879             }
7880         }
7881     }
7882     /* FIXME: search each inherited interface, not just the first */
7883     if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7884         /* recursive search */
7885         ITypeInfo *pTInfo;
7886         ITypeComp *pTComp;
7887         HRESULT hr;
7888         hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7889         if (SUCCEEDED(hr))
7890         {
7891             hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7892             ITypeInfo_Release(pTInfo);
7893         }
7894         if (SUCCEEDED(hr))
7895         {
7896             hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7897             ITypeComp_Release(pTComp);
7898             return hr;
7899         }
7900         WARN("Could not search inherited interface!\n");
7901     }
7902     if (hr == DISP_E_MEMBERNOTFOUND)
7903         hr = S_OK;
7904     TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
7905     return hr;
7906 }
7907
7908 static HRESULT WINAPI ITypeComp_fnBindType(
7909     ITypeComp * iface,
7910     OLECHAR * szName,
7911     ULONG lHash,
7912     ITypeInfo ** ppTInfo,
7913     ITypeComp ** ppTComp)
7914 {
7915     TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7916
7917     /* strange behaviour (does nothing) but like the
7918      * original */
7919
7920     if (!ppTInfo || !ppTComp)
7921         return E_POINTER;
7922
7923     *ppTInfo = NULL;
7924     *ppTComp = NULL;
7925
7926     return S_OK;
7927 }
7928
7929 static const ITypeCompVtbl tcompvt =
7930 {
7931
7932     ITypeComp_fnQueryInterface,
7933     ITypeComp_fnAddRef,
7934     ITypeComp_fnRelease,
7935
7936     ITypeComp_fnBind,
7937     ITypeComp_fnBindType
7938 };