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