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