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