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