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