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