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