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