Separated out 16bit sources for ole2disp.dll.
[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     FIXME("(%p, %ld, %d, %d, %d, %p, %p, %p)\n",
4105         pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult
4106     );
4107     argsize = 0;
4108     for (i=0;i<cActuals;i++) {
4109         FIXME("arg %d: type %d\n",i,prgvt[i]);
4110         dump_Variant(prgpvarg[i]);
4111         argsize += _argsize(prgvt[i]);
4112     }
4113     args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4114     argspos = 0;
4115     for (i=0;i<cActuals;i++) {
4116         int arglen;
4117         VARIANT *arg = prgpvarg[i];
4118
4119         arglen = _argsize(prgvt[i]);
4120         if (V_VT(arg) == prgvt[i]) {
4121             memcpy(&args[argspos],&V_UNION(arg,lVal), arglen*sizeof(DWORD));
4122         } else {
4123             if (prgvt[i] == VT_VARIANT) {
4124                 memcpy(&args[argspos],arg, arglen*sizeof(DWORD));
4125             } else {
4126                 ERR("Set arg %d to disparg type %d vs %d\n",i,
4127                         V_VT(arg),prgvt[i]
4128                 );
4129             }
4130         }
4131         argspos += arglen;
4132     }
4133
4134     FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4135
4136     hres = _invoke((*(DWORD***)pvInstance)[oVft/4],cc,argsize/4,args);
4137     HeapFree(GetProcessHeap(),0,args);
4138     return hres;
4139 }
4140
4141 static HRESULT WINAPI ITypeInfo_fnInvoke(
4142     ITypeInfo2 *iface,
4143     VOID  *pIUnk,
4144     MEMBERID memid,
4145     UINT16 dwFlags,
4146     DISPPARAMS  *pDispParams,
4147     VARIANT  *pVarResult,
4148     EXCEPINFO  *pExcepInfo,
4149     UINT  *pArgErr)
4150 {
4151     ICOM_THIS( ITypeInfoImpl, iface);
4152     TLBFuncDesc * pFDesc;
4153     TLBVarDesc * pVDesc;
4154     int i;
4155
4156     TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4157       This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4158     );
4159     dump_DispParms(pDispParams);
4160
4161     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4162         if (pFDesc->funcdesc.memid == memid) {
4163             if (pFDesc->funcdesc.invkind & dwFlags)
4164                 break;
4165         }
4166     if (pFDesc) {
4167         dump_TLBFuncDescOne(pFDesc);
4168         /* dump_FUNCDESC(&pFDesc->funcdesc);*/
4169         switch (pFDesc->funcdesc.funckind) {
4170         case FUNC_PUREVIRTUAL:
4171         case FUNC_VIRTUAL: {
4172             DWORD res;
4173             int   numargs, numargs2, argspos, args2pos;
4174             DWORD *args , *args2;
4175
4176
4177             numargs = 1; numargs2 = 0;
4178             for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4179                 if (i<pDispParams->cArgs)
4180                     numargs += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4181                 else {
4182                     numargs     += 1; /* sizeof(lpvoid) */
4183                     numargs2    += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4184                 }
4185             }
4186
4187             args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4188             args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4189
4190             args[0] = (DWORD)pIUnk;
4191             argspos = 1; args2pos = 0;
4192             for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4193                 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4194                 if (i<pDispParams->cArgs) {
4195                     VARIANT *arg = &pDispParams->rgvarg[pDispParams->cArgs-i-1];
4196                     TYPEDESC *tdesc = &pFDesc->funcdesc.lprgelemdescParam[i].tdesc;
4197
4198                     if (V_VT(arg) == tdesc->vt) {
4199                         memcpy(&args[argspos],&V_UNION(arg,lVal), arglen*sizeof(DWORD));
4200                    } else if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==tdesc->vt)) {
4201                        memcpy(&args[argspos],(void*)V_UNION(arg,lVal), arglen*sizeof(DWORD));
4202                     } else if (tdesc->vt == VT_VARIANT) {
4203                        memcpy(&args[argspos],arg, arglen*sizeof(DWORD));
4204                     } else {
4205                        ERR("Set arg %d to disparg type %d vs %d\n",i,
4206                            V_VT(arg),tdesc->vt
4207                        );
4208                     }
4209                     argspos += arglen;
4210                 } else {
4211                     TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4212                     if (tdesc->vt != VT_PTR)
4213                         FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4214                     /*FIXME: give pointers for the rest, so propertyget works*/
4215                     args[argspos] = (DWORD)&args2[args2pos];
4216
4217                     /* If pointer to variant, pass reference it. */
4218                     if ((tdesc->vt == VT_PTR) &&
4219                         (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4220                         pVarResult
4221                     )
4222                         args[argspos]= (DWORD)pVarResult;
4223                     argspos     += 1;
4224                     args2pos    += arglen;
4225                 }
4226             }
4227             if (pFDesc->funcdesc.cParamsOpt)
4228                 FIXME("Does not support optional parameters (%d)\n",
4229                         pFDesc->funcdesc.cParamsOpt
4230                 );
4231
4232             res = _invoke((*(DWORD***)pIUnk)[pFDesc->funcdesc.oVft/4],
4233                     pFDesc->funcdesc.callconv,
4234                     numargs,
4235                     args
4236             );
4237             if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4238                 args2pos = 0;
4239                 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4240                     int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4241                     TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4242                     /* If we are a pointer to a variant, we are done already */
4243                     if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4244                         continue;
4245
4246                     VariantInit(pVarResult);
4247                     memcpy(&V_UNION(pVarResult,intVal),&args2[args2pos],arglen*sizeof(DWORD));
4248
4249                     if (tdesc->vt == VT_PTR)
4250                         tdesc = tdesc->u.lptdesc;
4251                     V_VT(pVarResult) = tdesc->vt;
4252
4253                     /* HACK: VB5 likes this.
4254                      * I do not know why. There is 1 example in MSDN which uses
4255                      * this which appears broken (mixes int vals and
4256                      * IDispatch*.).
4257                      */
4258                     if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4259                         V_VT(pVarResult) = VT_DISPATCH;
4260                     TRACE("storing into variant:\n");
4261                     dump_Variant(pVarResult);
4262                     args2pos += arglen;
4263                 }
4264             }
4265             HeapFree(GetProcessHeap(),0,args2);
4266             HeapFree(GetProcessHeap(),0,args);
4267             return S_OK;
4268         }
4269         case FUNC_DISPATCH:  {
4270            IDispatch *disp;
4271            HRESULT hr;
4272
4273            hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4274            if (hr) {
4275                FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4276                return hr;
4277            }
4278            FIXME("Calling Invoke in IDispatch iface. untested!\n");
4279            hr = IDispatch_Invoke(
4280                disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4281                pVarResult,pExcepInfo,pArgErr
4282            );
4283            if (hr)
4284                FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4285            IDispatch_Release(disp);
4286            return hr;
4287         }
4288         default:
4289            FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4290            return E_FAIL;
4291         }
4292     } else {
4293         for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4294             if (pVDesc->vardesc.memid == memid) {
4295                 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4296                 dump_TLBVarDesc(pVDesc);
4297                 break;
4298             }
4299         }
4300     }
4301     /* not found, look for it in inherited interfaces */
4302     if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) {
4303         /* recursive search */
4304         ITypeInfo *pTInfo;
4305         HRESULT hr;
4306         hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4307         if(SUCCEEDED(hr)){
4308             hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4309             ITypeInfo_Release(pTInfo);
4310             return hr;
4311         }
4312         WARN("Could not search inherited interface!\n");
4313     }
4314     ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4315     return DISP_E_MEMBERNOTFOUND;
4316 }
4317
4318 /* ITypeInfo::GetDocumentation
4319  *
4320  * Retrieves the documentation string, the complete Help file name and path,
4321  * and the context ID for the Help topic for a specified type description.
4322  *
4323  * (Can be tested by the Visual Basic Editor in Word for instance.)
4324  */
4325 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4326         MEMBERID memid, BSTR  *pBstrName, BSTR  *pBstrDocString,
4327         DWORD  *pdwHelpContext, BSTR  *pBstrHelpFile)
4328 {
4329     ICOM_THIS( ITypeInfoImpl, iface);
4330     TLBFuncDesc * pFDesc;
4331     TLBVarDesc * pVDesc;
4332     TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4333           " HelpContext(%p) HelpFile(%p)\n",
4334         This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4335     if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4336         if(pBstrName)
4337             *pBstrName=SysAllocString(This->Name);
4338         if(pBstrDocString)
4339             *pBstrDocString=SysAllocString(This->DocString);
4340         if(pdwHelpContext)
4341             *pdwHelpContext=This->dwHelpContext;
4342         if(pBstrHelpFile)
4343             *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4344         return S_OK;
4345     }else {/* for a member */
4346     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4347         if(pFDesc->funcdesc.memid==memid){
4348           if(pBstrName)
4349             *pBstrName = SysAllocString(pFDesc->Name);
4350           if(pBstrDocString)
4351             *pBstrDocString=SysAllocString(pFDesc->HelpString);
4352           if(pdwHelpContext)
4353             *pdwHelpContext=pFDesc->helpcontext;
4354           return S_OK;
4355         }
4356     for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4357         if(pVDesc->vardesc.memid==memid){
4358             if(pBstrName)
4359               *pBstrName = SysAllocString(pVDesc->Name);
4360             if(pBstrDocString)
4361               *pBstrDocString=SysAllocString(pVDesc->HelpString);
4362             if(pdwHelpContext)
4363               *pdwHelpContext=pVDesc->HelpContext;
4364             return S_OK;
4365         }
4366     }
4367     return TYPE_E_ELEMENTNOTFOUND;
4368 }
4369
4370 /*  ITypeInfo::GetDllEntry
4371  *
4372  * Retrieves a description or specification of an entry point for a function
4373  * in a DLL.
4374  */
4375 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4376         INVOKEKIND invKind, BSTR  *pBstrDllName, BSTR  *pBstrName,
4377         WORD  *pwOrdinal)
4378 {
4379     ICOM_THIS( ITypeInfoImpl, iface);
4380     TLBFuncDesc *pFDesc;
4381
4382     FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
4383
4384     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4385         if(pFDesc->funcdesc.memid==memid){
4386             dump_TypeInfo(This);
4387             dump_TLBFuncDescOne(pFDesc);
4388
4389             /* FIXME: This is wrong, but how do you find that out? */
4390             if (pBstrDllName) {
4391                 const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
4392                 *pBstrDllName = SysAllocString(oleaut32W);
4393             }
4394
4395             if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
4396                 if (pBstrName)
4397                     *pBstrName = SysAllocString(pFDesc->Entry);
4398                 if (pwOrdinal)
4399                     *pwOrdinal = -1;
4400                 return S_OK;
4401             }
4402             if (pBstrName)
4403                 *pBstrName = NULL;
4404             if (pwOrdinal)
4405                 *pwOrdinal = (DWORD)pFDesc->Entry;
4406             return S_OK;
4407         }
4408     return E_FAIL;
4409 }
4410
4411 /* ITypeInfo::GetRefTypeInfo
4412  *
4413  * If a type description references other type descriptions, it retrieves
4414  * the referenced type descriptions.
4415  */
4416 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4417         ITypeInfo2 *iface,
4418         HREFTYPE hRefType,
4419         ITypeInfo  **ppTInfo)
4420 {
4421     ICOM_THIS( ITypeInfoImpl, iface);
4422     HRESULT result = E_FAIL;
4423
4424
4425     if (hRefType == -1 &&
4426         (((ITypeInfoImpl*) This)->TypeAttr.typekind   == TKIND_DISPATCH) &&
4427         (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags &  TYPEFLAG_FDUAL))
4428     {
4429           /* when we meet a DUAL dispinterface, we must create the interface
4430           * version of it.
4431           */
4432           ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4433
4434
4435           /* the interface version contains the same information as the dispinterface
4436            * copy the contents of the structs.
4437            */
4438           *pTypeInfoImpl = *This;
4439           pTypeInfoImpl->ref = 1;
4440
4441           /* change the type to interface */
4442           pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4443
4444           *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4445
4446           ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4447
4448           result = S_OK;
4449
4450     } else {
4451         TLBRefType *pRefType;
4452         for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4453             if(pRefType->reference == hRefType)
4454                 break;
4455         }
4456         if(!pRefType)
4457           FIXME("Can't find pRefType for ref %lx\n", hRefType);
4458         if(pRefType && hRefType != -1) {
4459             ITypeLib *pTLib = NULL;
4460
4461             if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4462                 int Index;
4463                 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4464             } else {
4465                 if(pRefType->pImpTLInfo->pImpTypeLib) {
4466                     TRACE("typeinfo in imported typelib that is already loaded\n");
4467                     pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
4468                     ITypeLib2_AddRef((ITypeLib*) pTLib);
4469                     result = S_OK;
4470                 } else {
4471                     TRACE("typeinfo in imported typelib that isn't already loaded\n");
4472                     result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
4473                                              pRefType->pImpTLInfo->wVersionMajor,
4474                                              pRefType->pImpTLInfo->wVersionMinor,
4475                                              pRefType->pImpTLInfo->lcid,
4476                                              &pTLib);
4477
4478                     if(!SUCCEEDED(result)) {
4479                         BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
4480                         result=LoadTypeLib(libnam, &pTLib);
4481                         SysFreeString(libnam);
4482                     }
4483                     if(SUCCEEDED(result)) {
4484                         pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
4485                         ITypeLib2_AddRef(pTLib);
4486                     }
4487                 }
4488             }
4489             if(SUCCEEDED(result)) {
4490                 if(pRefType->index == TLB_REF_USE_GUID)
4491                     result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
4492                                                          &pRefType->guid,
4493                                                          ppTInfo);
4494                 else
4495                     result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
4496                                                    ppTInfo);
4497             }
4498             if (pTLib != NULL)
4499                 ITypeLib2_Release(pTLib);
4500         }
4501     }
4502
4503     TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
4504           SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
4505     return result;
4506 }
4507
4508 /* ITypeInfo::AddressOfMember
4509  *
4510  * Retrieves the addresses of static functions or variables, such as those
4511  * defined in a DLL.
4512  */
4513 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
4514         MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
4515 {
4516     ICOM_THIS( ITypeInfoImpl, iface);
4517     FIXME("(%p) stub!\n", This);
4518     return S_OK;
4519 }
4520
4521 /* ITypeInfo::CreateInstance
4522  *
4523  * Creates a new instance of a type that describes a component object class
4524  * (coclass).
4525  */
4526 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
4527         IUnknown *pUnk, REFIID riid, VOID  **ppvObj)
4528 {
4529     ICOM_THIS( ITypeInfoImpl, iface);
4530     FIXME("(%p) stub!\n", This);
4531     return S_OK;
4532 }
4533
4534 /* ITypeInfo::GetMops
4535  *
4536  * Retrieves marshaling information.
4537  */
4538 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
4539                                 BSTR  *pBstrMops)
4540 {
4541     ICOM_THIS( ITypeInfoImpl, iface);
4542     FIXME("(%p) stub!\n", This);
4543     return S_OK;
4544 }
4545
4546 /* ITypeInfo::GetContainingTypeLib
4547  *
4548  * Retrieves the containing type library and the index of the type description
4549  * within that type library.
4550  */
4551 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
4552         ITypeLib  * *ppTLib, UINT  *pIndex)
4553 {
4554     ICOM_THIS( ITypeInfoImpl, iface);
4555     if (!pIndex)
4556         return E_INVALIDARG;
4557     *ppTLib=(LPTYPELIB )(This->pTypeLib);
4558     *pIndex=This->index;
4559     ITypeLib2_AddRef(*ppTLib);
4560     TRACE("(%p) returns (%p) index %d!\n", This, *ppTLib, *pIndex);
4561     return S_OK;
4562 }
4563
4564 /* ITypeInfo::ReleaseTypeAttr
4565  *
4566  * Releases a TYPEATTR previously returned by GetTypeAttr.
4567  *
4568  */
4569 static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
4570         TYPEATTR* pTypeAttr)
4571 {
4572     ICOM_THIS( ITypeInfoImpl, iface);
4573     TRACE("(%p)->(%p)\n", This, pTypeAttr);
4574     return S_OK;
4575 }
4576
4577 /* ITypeInfo::ReleaseFuncDesc
4578  *
4579  * Releases a FUNCDESC previously returned by GetFuncDesc. *
4580  */
4581 static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc(
4582         ITypeInfo2 *iface,
4583         FUNCDESC *pFuncDesc)
4584 {
4585     ICOM_THIS( ITypeInfoImpl, iface);
4586     TRACE("(%p)->(%p)\n", This, pFuncDesc);
4587     return S_OK;
4588 }
4589
4590 /* ITypeInfo::ReleaseVarDesc
4591  *
4592  * Releases a VARDESC previously returned by GetVarDesc.
4593  */
4594 static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
4595         VARDESC *pVarDesc)
4596 {
4597     ICOM_THIS( ITypeInfoImpl, iface);
4598     TRACE("(%p)->(%p)\n", This, pVarDesc);
4599     return S_OK;
4600 }
4601
4602 /* ITypeInfo2::GetTypeKind
4603  *
4604  * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4605  *
4606  */
4607 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
4608     TYPEKIND *pTypeKind)
4609 {
4610     ICOM_THIS( ITypeInfoImpl, iface);
4611     *pTypeKind=This->TypeAttr.typekind;
4612     TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
4613     return S_OK;
4614 }
4615
4616 /* ITypeInfo2::GetTypeFlags
4617  *
4618  * Returns the type flags without any allocations. This returns a DWORD type
4619  * flag, which expands the type flags without growing the TYPEATTR (type
4620  * attribute).
4621  *
4622  */
4623 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 * iface,
4624     UINT *pTypeFlags)
4625 {
4626     ICOM_THIS( ITypeInfoImpl, iface);
4627     *pTypeFlags=This->TypeAttr.wTypeFlags;
4628     TRACE("(%p) flags 0x%04x\n", This,*pTypeFlags);
4629      return S_OK;
4630 }
4631
4632 /* ITypeInfo2::GetFuncIndexOfMemId
4633  * Binds to a specific member based on a known DISPID, where the member name
4634  * is not known (for example, when binding to a default member).
4635  *
4636  */
4637 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
4638     MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
4639 {
4640     ICOM_THIS( ITypeInfoImpl, iface);
4641     TLBFuncDesc *pFuncInfo;
4642     int i;
4643     HRESULT result;
4644     /* FIXME: should check for invKind??? */
4645     for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
4646             memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
4647     if(pFuncInfo){
4648         *pFuncIndex=i;
4649         result= S_OK;
4650     }else{
4651         *pFuncIndex=0;
4652         result=E_INVALIDARG;
4653     }
4654     TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
4655           memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
4656     return result;
4657 }
4658
4659 /* TypeInfo2::GetVarIndexOfMemId
4660  *
4661  * Binds to a specific member based on a known DISPID, where the member name
4662  * is not known (for example, when binding to a default member).
4663  *
4664  */
4665 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
4666     MEMBERID memid, UINT *pVarIndex)
4667 {
4668     ICOM_THIS( ITypeInfoImpl, iface);
4669     TLBVarDesc *pVarInfo;
4670     int i;
4671     HRESULT result;
4672     for(i=0, pVarInfo=This->varlist; pVarInfo &&
4673             memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
4674         ;
4675     if(pVarInfo){
4676         *pVarIndex=i;
4677         result= S_OK;
4678     }else{
4679         *pVarIndex=0;
4680         result=E_INVALIDARG;
4681     }
4682     TRACE("(%p) memid 0x%08lx -> %s\n", This,
4683           memid, SUCCEEDED(result)? "SUCCES":"FAILED");
4684     return result;
4685 }
4686
4687 /* ITypeInfo2::GetCustData
4688  *
4689  * Gets the custom data
4690  */
4691 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
4692         ITypeInfo2 * iface,
4693         REFGUID guid,
4694         VARIANT *pVarVal)
4695 {
4696     ICOM_THIS( ITypeInfoImpl, iface);
4697     TLBCustData *pCData;
4698
4699     for(pCData=This->pCustData; pCData; pCData = pCData->next)
4700         if( IsEqualIID(guid, &pCData->guid)) break;
4701
4702     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4703
4704     if(pCData)
4705     {
4706         VariantInit( pVarVal);
4707         VariantCopy( pVarVal, &pCData->data);
4708         return S_OK;
4709     }
4710     return E_INVALIDARG;  /* FIXME: correct? */
4711 }
4712
4713 /* ITypeInfo2::GetFuncCustData
4714  *
4715  * Gets the custom data
4716  */
4717 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
4718         ITypeInfo2 * iface,
4719         UINT index,
4720         REFGUID guid,
4721         VARIANT *pVarVal)
4722 {
4723     ICOM_THIS( ITypeInfoImpl, iface);
4724     TLBCustData *pCData=NULL;
4725     TLBFuncDesc * pFDesc;
4726     int i;
4727     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4728             pFDesc=pFDesc->next);
4729
4730     if(pFDesc)
4731         for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
4732             if( IsEqualIID(guid, &pCData->guid)) break;
4733
4734     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4735
4736     if(pCData){
4737         VariantInit( pVarVal);
4738         VariantCopy( pVarVal, &pCData->data);
4739         return S_OK;
4740     }
4741     return E_INVALIDARG;  /* FIXME: correct? */
4742 }
4743
4744 /* ITypeInfo2::GetParamCustData
4745  *
4746  * Gets the custom data
4747  */
4748 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
4749         ITypeInfo2 * iface,
4750         UINT indexFunc,
4751         UINT indexParam,
4752         REFGUID guid,
4753         VARIANT *pVarVal)
4754 {
4755     ICOM_THIS( ITypeInfoImpl, iface);
4756     TLBCustData *pCData=NULL;
4757     TLBFuncDesc * pFDesc;
4758     int i;
4759
4760     for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
4761
4762     if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
4763         for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
4764                 pCData = pCData->next)
4765             if( IsEqualIID(guid, &pCData->guid)) break;
4766
4767     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4768
4769     if(pCData)
4770     {
4771         VariantInit( pVarVal);
4772         VariantCopy( pVarVal, &pCData->data);
4773         return S_OK;
4774     }
4775     return E_INVALIDARG;  /* FIXME: correct? */
4776 }
4777
4778 /* ITypeInfo2::GetVarCustData
4779  *
4780  * Gets the custom data
4781  */
4782 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
4783         ITypeInfo2 * iface,
4784         UINT index,
4785         REFGUID guid,
4786         VARIANT *pVarVal)
4787 {
4788     ICOM_THIS( ITypeInfoImpl, iface);
4789     TLBCustData *pCData=NULL;
4790     TLBVarDesc * pVDesc;
4791     int i;
4792
4793     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
4794
4795     if(pVDesc)
4796     {
4797       for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
4798       {
4799         if( IsEqualIID(guid, &pCData->guid)) break;
4800       }
4801     }
4802
4803     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4804
4805     if(pCData)
4806     {
4807         VariantInit( pVarVal);
4808         VariantCopy( pVarVal, &pCData->data);
4809         return S_OK;
4810     }
4811     return E_INVALIDARG;  /* FIXME: correct? */
4812 }
4813
4814 /* ITypeInfo2::GetImplCustData
4815  *
4816  * Gets the custom data
4817  */
4818 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
4819         ITypeInfo2 * iface,
4820         UINT index,
4821         REFGUID guid,
4822         VARIANT *pVarVal)
4823 {
4824     ICOM_THIS( ITypeInfoImpl, iface);
4825     TLBCustData *pCData=NULL;
4826     TLBImplType * pRDesc;
4827     int i;
4828
4829     for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
4830
4831     if(pRDesc)
4832     {
4833       for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
4834       {
4835         if( IsEqualIID(guid, &pCData->guid)) break;
4836       }
4837     }
4838
4839     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4840
4841     if(pCData)
4842     {
4843         VariantInit( pVarVal);
4844         VariantCopy( pVarVal, &pCData->data);
4845         return S_OK;
4846     }
4847     return E_INVALIDARG;  /* FIXME: correct? */
4848 }
4849
4850 /* ITypeInfo2::GetDocumentation2
4851  *
4852  * Retrieves the documentation string, the complete Help file name and path,
4853  * the localization context to use, and the context ID for the library Help
4854  * topic in the Help file.
4855  *
4856  */
4857 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
4858         ITypeInfo2 * iface,
4859         MEMBERID memid,
4860         LCID lcid,
4861         BSTR *pbstrHelpString,
4862         DWORD *pdwHelpStringContext,
4863         BSTR *pbstrHelpStringDll)
4864 {
4865     ICOM_THIS( ITypeInfoImpl, iface);
4866     TLBFuncDesc * pFDesc;
4867     TLBVarDesc * pVDesc;
4868     TRACE("(%p) memid %ld lcid(0x%lx)  HelpString(%p) "
4869           "HelpStringContext(%p) HelpStringDll(%p)\n",
4870           This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
4871           pbstrHelpStringDll );
4872     /* the help string should be obtained from the helpstringdll,
4873      * using the _DLLGetDocumentation function, based on the supplied
4874      * lcid. Nice to do sometime...
4875      */
4876     if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4877         if(pbstrHelpString)
4878             *pbstrHelpString=SysAllocString(This->Name);
4879         if(pdwHelpStringContext)
4880             *pdwHelpStringContext=This->dwHelpStringContext;
4881         if(pbstrHelpStringDll)
4882             *pbstrHelpStringDll=
4883                 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4884         return S_OK;
4885     }else {/* for a member */
4886     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4887         if(pFDesc->funcdesc.memid==memid){
4888              if(pbstrHelpString)
4889                 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
4890             if(pdwHelpStringContext)
4891                 *pdwHelpStringContext=pFDesc->HelpStringContext;
4892             if(pbstrHelpStringDll)
4893                 *pbstrHelpStringDll=
4894                     SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4895         return S_OK;
4896     }
4897     for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4898         if(pVDesc->vardesc.memid==memid){
4899              if(pbstrHelpString)
4900                 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
4901             if(pdwHelpStringContext)
4902                 *pdwHelpStringContext=pVDesc->HelpStringContext;
4903             if(pbstrHelpStringDll)
4904                 *pbstrHelpStringDll=
4905                     SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4906             return S_OK;
4907         }
4908     }
4909     return TYPE_E_ELEMENTNOTFOUND;
4910 }
4911
4912 /* ITypeInfo2::GetAllCustData
4913  *
4914  * Gets all custom data items for the Type info.
4915  *
4916  */
4917 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
4918         ITypeInfo2 * iface,
4919         CUSTDATA *pCustData)
4920 {
4921     ICOM_THIS( ITypeInfoImpl, iface);
4922     TLBCustData *pCData;
4923     int i;
4924
4925     TRACE("(%p) returning %d items\n", This, This->ctCustData);
4926
4927     pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4928     if(pCustData->prgCustData ){
4929         pCustData->cCustData=This->ctCustData;
4930         for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4931             pCustData->prgCustData[i].guid=pCData->guid;
4932             VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4933         }
4934     }else{
4935         ERR(" OUT OF MEMORY! \n");
4936         return E_OUTOFMEMORY;
4937     }
4938     return S_OK;
4939 }
4940
4941 /* ITypeInfo2::GetAllFuncCustData
4942  *
4943  * Gets all custom data items for the specified Function
4944  *
4945  */
4946 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
4947         ITypeInfo2 * iface,
4948         UINT index,
4949         CUSTDATA *pCustData)
4950 {
4951     ICOM_THIS( ITypeInfoImpl, iface);
4952     TLBCustData *pCData;
4953     TLBFuncDesc * pFDesc;
4954     int i;
4955     TRACE("(%p) index %d\n", This, index);
4956     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4957             pFDesc=pFDesc->next)
4958         ;
4959     if(pFDesc){
4960         pCustData->prgCustData =
4961             TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
4962         if(pCustData->prgCustData ){
4963             pCustData->cCustData=pFDesc->ctCustData;
4964             for(i=0, pCData=pFDesc->pCustData; pCData; i++,
4965                     pCData = pCData->next){
4966                 pCustData->prgCustData[i].guid=pCData->guid;
4967                 VariantCopy(& pCustData->prgCustData[i].varValue,
4968                         & pCData->data);
4969             }
4970         }else{
4971             ERR(" OUT OF MEMORY! \n");
4972             return E_OUTOFMEMORY;
4973         }
4974         return S_OK;
4975     }
4976     return TYPE_E_ELEMENTNOTFOUND;
4977 }
4978
4979 /* ITypeInfo2::GetAllParamCustData
4980  *
4981  * Gets all custom data items for the Functions
4982  *
4983  */
4984 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
4985     UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
4986 {
4987     ICOM_THIS( ITypeInfoImpl, iface);
4988     TLBCustData *pCData=NULL;
4989     TLBFuncDesc * pFDesc;
4990     int i;
4991     TRACE("(%p) index %d\n", This, indexFunc);
4992     for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
4993             pFDesc=pFDesc->next)
4994         ;
4995     if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
4996         pCustData->prgCustData =
4997             TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
4998                     sizeof(CUSTDATAITEM));
4999         if(pCustData->prgCustData ){
5000             pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5001             for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5002                     pCData; i++, pCData = pCData->next){
5003                 pCustData->prgCustData[i].guid=pCData->guid;
5004                 VariantCopy(& pCustData->prgCustData[i].varValue,
5005                         & pCData->data);
5006             }
5007         }else{
5008             ERR(" OUT OF MEMORY! \n");
5009             return E_OUTOFMEMORY;
5010         }
5011         return S_OK;
5012     }
5013     return TYPE_E_ELEMENTNOTFOUND;
5014 }
5015
5016 /* ITypeInfo2::GetAllVarCustData
5017  *
5018  * Gets all custom data items for the specified Variable
5019  *
5020  */
5021 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5022     UINT index, CUSTDATA *pCustData)
5023 {
5024     ICOM_THIS( ITypeInfoImpl, iface);
5025     TLBCustData *pCData;
5026     TLBVarDesc * pVDesc;
5027     int i;
5028     TRACE("(%p) index %d\n", This, index);
5029     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5030             pVDesc=pVDesc->next)
5031         ;
5032     if(pVDesc){
5033         pCustData->prgCustData =
5034             TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5035         if(pCustData->prgCustData ){
5036             pCustData->cCustData=pVDesc->ctCustData;
5037             for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5038                     pCData = pCData->next){
5039                 pCustData->prgCustData[i].guid=pCData->guid;
5040                 VariantCopy(& pCustData->prgCustData[i].varValue,
5041                         & pCData->data);
5042             }
5043         }else{
5044             ERR(" OUT OF MEMORY! \n");
5045             return E_OUTOFMEMORY;
5046         }
5047         return S_OK;
5048     }
5049     return TYPE_E_ELEMENTNOTFOUND;
5050 }
5051
5052 /* ITypeInfo2::GetAllImplCustData
5053  *
5054  * Gets all custom data items for the specified implementation type
5055  *
5056  */
5057 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5058         ITypeInfo2 * iface,
5059         UINT index,
5060         CUSTDATA *pCustData)
5061 {
5062     ICOM_THIS( ITypeInfoImpl, iface);
5063     TLBCustData *pCData;
5064     TLBImplType * pRDesc;
5065     int i;
5066     TRACE("(%p) index %d\n", This, index);
5067     for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5068             pRDesc=pRDesc->next)
5069         ;
5070     if(pRDesc){
5071         pCustData->prgCustData =
5072             TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5073         if(pCustData->prgCustData ){
5074             pCustData->cCustData=pRDesc->ctCustData;
5075             for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5076                     pCData = pCData->next){
5077                 pCustData->prgCustData[i].guid=pCData->guid;
5078                 VariantCopy(& pCustData->prgCustData[i].varValue,
5079                         & pCData->data);
5080             }
5081         }else{
5082             ERR(" OUT OF MEMORY! \n");
5083             return E_OUTOFMEMORY;
5084         }
5085         return S_OK;
5086     }
5087     return TYPE_E_ELEMENTNOTFOUND;
5088 }
5089
5090 static ICOM_VTABLE(ITypeInfo2) tinfvt =
5091 {
5092     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5093
5094     ITypeInfo_fnQueryInterface,
5095     ITypeInfo_fnAddRef,
5096     ITypeInfo_fnRelease,
5097
5098     ITypeInfo_fnGetTypeAttr,
5099     ITypeInfo_fnGetTypeComp,
5100     ITypeInfo_fnGetFuncDesc,
5101     ITypeInfo_fnGetVarDesc,
5102     ITypeInfo_fnGetNames,
5103     ITypeInfo_fnGetRefTypeOfImplType,
5104     ITypeInfo_fnGetImplTypeFlags,
5105     ITypeInfo_fnGetIDsOfNames,
5106     ITypeInfo_fnInvoke,
5107     ITypeInfo_fnGetDocumentation,
5108     ITypeInfo_fnGetDllEntry,
5109     ITypeInfo_fnGetRefTypeInfo,
5110     ITypeInfo_fnAddressOfMember,
5111     ITypeInfo_fnCreateInstance,
5112     ITypeInfo_fnGetMops,
5113     ITypeInfo_fnGetContainingTypeLib,
5114     ITypeInfo_fnReleaseTypeAttr,
5115     ITypeInfo_fnReleaseFuncDesc,
5116     ITypeInfo_fnReleaseVarDesc,
5117
5118     ITypeInfo2_fnGetTypeKind,
5119     ITypeInfo2_fnGetTypeFlags,
5120     ITypeInfo2_fnGetFuncIndexOfMemId,
5121     ITypeInfo2_fnGetVarIndexOfMemId,
5122     ITypeInfo2_fnGetCustData,
5123     ITypeInfo2_fnGetFuncCustData,
5124     ITypeInfo2_fnGetParamCustData,
5125     ITypeInfo2_fnGetVarCustData,
5126     ITypeInfo2_fnGetImplTypeCustData,
5127     ITypeInfo2_fnGetDocumentation2,
5128     ITypeInfo2_fnGetAllCustData,
5129     ITypeInfo2_fnGetAllFuncCustData,
5130     ITypeInfo2_fnGetAllParamCustData,
5131     ITypeInfo2_fnGetAllVarCustData,
5132     ITypeInfo2_fnGetAllImplTypeCustData,
5133 };