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