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