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