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