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