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