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