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