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