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