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