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