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