No longer directly accessing debuggee memory.
[wine] / dlls / oleaut32 / typelib.c
1 /*
2  *      TYPELIB
3  *
4  *      Copyright 1997  Marcus Meissner
5  *                    1999  Rein Klazes
6  * there is much left to do here before it can be useful for real world
7  * programs
8  * know problems:
9  * -. Only one format of typelibs is supported
10  * -. All testing so far is done using special written windows programs
11  * -. Data structures are straightforward, but slow for look-ups.
12  * -. (related) nothing is hashed
13  * -. a typelib is always read in its entirety into memory and never released.
14  * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
15  *      of them I don't know yet how to implement them.
16  * -. Most error return values are just guessed not checked with windows
17  *      behaviour.
18  * -. all locale stuff ignored
19  * -. move stuff to wine/dlls
20  * -. didn't bother with a c++ interface
21  * -. lousy fatal error handling
22  * -. some methods just return pointers to internal data structures, this is
23  *      partly laziness, partly I want to check how windows does it.
24  * 
25  */
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdio.h>
30 #include <assert.h>
31 #include "winerror.h"
32 #include "winreg.h"         /* for HKEY_LOCAL_MACHINE */
33 #include "winnls.h"         /* for PRIMARYLANGID */
34 #include "wine/winbase16.h" /* for RegQueryValue16(HKEY,LPSTR,LPSTR,LPDWORD) */
35 #include "heap.h"
36 #include "wine/obj_base.h"
37 #include "debugtools.h"
38 #include "winversion.h"
39 /* FIXME: get rid of these */
40 typedef struct ITypeInfoVtbl ITypeLib_VTable, *LPTYPEINFO_VTABLE ; 
41 typedef struct ITypeLibVtbl *LPTYPELIB_VTABLE  ; 
42 #include "typelib.h"
43
44 typedef struct tagTLBContext {
45         unsigned int oStart;  /* start of TLB in file */
46         unsigned int pos;     /* current pos */
47         unsigned int length;  /* total length */
48         void *mapping;        /* memory mapping */
49         TLBSegDir * pTblDir;
50         TLBLibInfo* pLibInfo;
51 } TLBContext;
52
53 DEFAULT_DEBUG_CHANNEL(ole);
54 DECLARE_DEBUG_CHANNEL(typelib);
55
56 /****************************************************************************
57  *              QueryPathOfRegTypeLib16 [TYPELIB.14]
58  *
59  * the path is "Classes\Typelib\<guid>\<major>.<minor>\<lcid>\win16\"
60  * RETURNS
61  *      path of typelib
62  */
63 HRESULT WINAPI
64 QueryPathOfRegTypeLib16(        
65         REFGUID guid,   /* [in] referenced guid */
66         WORD wMaj,      /* [in] major version */
67         WORD wMin,      /* [in] minor version */
68         LCID lcid,      /* [in] locale id */
69         LPBSTR16 path   /* [out] path of typelib */
70 ) {
71         char    xguid[80];
72         char    typelibkey[100],pathname[260];
73         DWORD   plen;
74
75         if (HIWORD(guid)) {
76                 WINE_StringFromCLSID(guid,xguid);
77                 sprintf(typelibkey,"SOFTWARE\\Classes\\Typelib\\%s\\%d.%d\\%lx\\win16",
78                         xguid,wMaj,wMin,lcid
79                 );
80         } else {
81                 sprintf(xguid,"<guid 0x%08lx>",(DWORD)guid);
82                 FIXME("(%s,%d,%d,0x%04lx,%p),can't handle non-string guids.\n",xguid,wMaj,wMin,(DWORD)lcid,path);
83                 return E_FAIL;
84         }
85         plen = sizeof(pathname);
86         if (RegQueryValue16(HKEY_LOCAL_MACHINE,typelibkey,pathname,&plen)) {
87                 /* try again without lang specific id */
88                 if (SUBLANGID(lcid))
89                         return QueryPathOfRegTypeLib16(guid,wMaj,wMin,PRIMARYLANGID(lcid),path);
90                 FIXME("key %s not found\n",typelibkey);
91                 return E_FAIL;
92         }
93         *path = SysAllocString16(pathname);
94         return S_OK;
95 }
96  
97 /****************************************************************************
98  *              QueryPathOfRegTypeLib   [OLEAUT32.164]
99  * RETURNS
100  *      path of typelib
101  */
102 HRESULT WINAPI
103 QueryPathOfRegTypeLib(  
104         REFGUID guid,   /* [in] referenced guid */
105         WORD wMaj,      /* [in] major version */
106         WORD wMin,      /* [in] minor version */
107         LCID lcid,      /* [in] locale id */
108         LPBSTR path     /* [out] path of typelib */
109 ) {
110         char    xguid[80];
111         char    typelibkey[100],pathname[260];
112         DWORD   plen;
113
114
115         if (HIWORD(guid)) {
116                 WINE_StringFromCLSID(guid,xguid);
117                 sprintf(typelibkey,"SOFTWARE\\Classes\\Typelib\\%s\\%d.%d\\%lx\\win32",
118                         xguid,wMaj,wMin,lcid
119                 );
120         } else {
121                 sprintf(xguid,"<guid 0x%08lx>",(DWORD)guid);
122                 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n",xguid,wMaj,wMin,(DWORD)lcid,path);
123                 return E_FAIL;
124         }
125         plen = sizeof(pathname);
126         if (RegQueryValue16(HKEY_LOCAL_MACHINE,typelibkey,pathname,&plen)) {
127                 /* try again without lang specific id */
128                 if (SUBLANGID(lcid))
129                         return QueryPathOfRegTypeLib(guid,wMaj,wMin,PRIMARYLANGID(lcid),path);
130                 FIXME("key %s not found\n",typelibkey);
131                 return E_FAIL;
132         }
133         *path = HEAP_strdupAtoW(GetProcessHeap(),0,pathname);
134         return S_OK;
135 }
136
137 /******************************************************************************
138  * LoadTypeLib [TYPELIB.3]  Loads and registers a type library
139  * NOTES
140  *    Docs: OLECHAR FAR* szFile
141  *    Docs: iTypeLib FAR* FAR* pptLib
142  *
143  * RETURNS
144  *    Success: S_OK
145  *    Failure: Status
146  */
147 HRESULT WINAPI LoadTypeLib16(
148     LPOLESTR szFile, /* [in] Name of file to load from */
149     void * *pptLib) /* [out] Pointer to pointer to loaded type library */
150 {
151     FIXME("('%s',%p): stub\n",debugstr_w((LPWSTR)szFile),pptLib);
152
153     if (pptLib!=0)
154       *pptLib=0;
155
156     return E_FAIL;
157 }
158
159 /******************************************************************************
160  *              LoadTypeLib     [OLEAUT32.161]
161  * Loads and registers a type library
162  * NOTES
163  *    Docs: OLECHAR FAR* szFile
164  *    Docs: iTypeLib FAR* FAR* pptLib
165  *
166  * RETURNS
167  *    Success: S_OK
168  *    Failure: Status
169  */
170 int TLB_ReadTypeLib(PCHAR file, ITypeLib **ppTypelib);
171 HRESULT WINAPI LoadTypeLib(
172     OLECHAR *szFile,   /* [in] Name of file to load from */
173     ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
174 {
175     return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
176 }
177
178 /******************************************************************************
179  *              LoadTypeLibEx   [OLEAUT32.183]
180  * Loads and optionally registers a type library
181  *
182  * RETURNS
183  *    Success: S_OK
184  *    Failure: Status
185  */
186 HRESULT WINAPI LoadTypeLibEx(
187     LPOLESTR szFile,   /* [in] Name of file to load from */
188     REGKIND  regkind,  /* specify kind of registration */
189     ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
190 {
191     LPSTR p;
192     HRESULT res;
193     TRACE("('%s',%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
194     
195     p=HEAP_strdupWtoA(GetProcessHeap(),0,szFile);
196     
197     if(regkind != REGKIND_NONE)
198         FIXME ("registration of typelibs not supported yet!\n");
199
200     res= TLB_ReadTypeLib(p, pptLib);
201     /* XXX need to free p ?? */
202
203     TRACE(" returns %ld\n",res);
204
205     return res;
206 }
207
208 /******************************************************************************
209  *              LoadRegTypeLib  [OLEAUT32.162]
210  */
211 HRESULT WINAPI LoadRegTypeLib(  
212         REFGUID rguid,  /* [in] referenced guid */
213         WORD wVerMajor, /* [in] major version */
214         WORD wVerMinor, /* [in] minor version */
215         LCID lcid,      /* [in] locale id */
216         ITypeLib **ppTLib       /* [out] path of typelib */
217 ) {
218     BSTR bstr=NULL;
219     HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor,
220                     lcid, &bstr);
221     if(SUCCEEDED(res)){
222         res= LoadTypeLib(bstr, ppTLib);
223         SysFreeString(bstr);
224     }
225     if(TRACE_ON(typelib)){
226         char xriid[50];
227         WINE_StringFromCLSID((LPCLSID)rguid,xriid);
228         TRACE("(IID: %s) load %s (%p)\n",xriid,
229               SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
230     }
231     return res;
232 }       
233
234
235 /******************************************************************************
236  *              RegisterTypeLib [OLEAUT32.163]
237  * Adds information about a type library to the System Registry           
238  * NOTES
239  *    Docs: ITypeLib FAR * ptlib
240  *    Docs: OLECHAR FAR* szFullPath
241  *    Docs: OLECHAR FAR* szHelpDir
242  *
243  * RETURNS
244  *    Success: S_OK
245  *    Failure: Status
246  */
247 HRESULT WINAPI RegisterTypeLib(
248      ITypeLib * ptlib,      /*[in] Pointer to the library*/
249      OLECHAR * szFullPath, /*[in] full Path of the library*/
250      OLECHAR * szHelpDir)  /*[in] dir to the helpfile for the library,
251                                                          may be NULL*/
252 {   FIXME("(%p,%s,%s): stub\n",ptlib, debugstr_w(szFullPath),debugstr_w(szHelpDir));
253     return S_OK;        /* FIXME: pretend everything is OK */
254 }
255
256
257 /******************************************************************************
258  *      UnRegisterTypeLib       [OLEAUT32.186]
259  * Removes information about a type library from the System Registry           
260  * NOTES
261  *
262  * RETURNS
263  *    Success: S_OK
264  *    Failure: Status
265  */
266 HRESULT WINAPI UnRegisterTypeLib(
267     REFGUID libid,      /* [in] Guid of the library */
268         WORD wVerMajor, /* [in] major version */
269         WORD wVerMinor, /* [in] minor version */
270         LCID lcid,      /* [in] locale id */
271         SYSKIND syskind)
272 {   
273     char xriid[50];
274     WINE_StringFromCLSID((LPCLSID)libid,xriid);
275     TRACE("(IID: %s): stub\n",xriid);
276     return S_OK;        /* FIXME: pretend everything is OK */
277 }
278
279 /****************************************************************************
280  *      OaBuildVersion                          (TYPELIB.15)
281  *
282  * known TYPELIB.DLL versions:
283  *
284  * OLE 2.01 no OaBuildVersion() avail   1993    --      ---
285  * OLE 2.02                             1993-94 02     3002
286  * OLE 2.03                                     23      730
287  * OLE 2.03                                     03     3025
288  * OLE 2.03 W98 SE orig. file !!        1993-95 10     3024
289  * OLE 2.1   NT                         1993-95 ??      ???
290  * OLE 2.3.1 W95                                23      700
291  */
292 DWORD WINAPI OaBuildVersion16(void)
293 {
294     FIXME("Please report to a.mohr@mailto.de if you get version error messages !\n");
295     switch(VERSION_GetVersion())
296     {
297       case WIN31:
298                 return MAKELONG(3027, 3); /* WfW 3.11 */
299         case WIN95:
300                 return MAKELONG(700, 23); /* Win95A */
301         case WIN98:
302                 return MAKELONG(3024, 10); /* W98 SE */
303       default:
304         FIXME_(ole)("Version value not known yet. Please investigate it !");
305                 return 0;
306     }
307 }
308
309 /* for better debugging info leave the static out for the time being */
310 #define static
311
312 /*=======================Itypelib methods ===============================*/
313 /* ITypeLib methods */
314 static HRESULT WINAPI ITypeLib_fnQueryInterface( LPTYPELIB This, REFIID riid,
315     VOID **ppvObject); 
316 static ULONG WINAPI ITypeLib_fnAddRef( LPTYPELIB This); 
317 static ULONG WINAPI ITypeLib_fnRelease( LPTYPELIB This); 
318 static UINT WINAPI ITypeLib_fnGetTypeInfoCount( LPTYPELIB This); 
319 static HRESULT WINAPI ITypeLib_fnGetTypeInfo( LPTYPELIB This, UINT index, 
320     ITypeInfo **ppTInfo); 
321
322 static HRESULT WINAPI ITypeLib_fnGetTypeInfoType( LPTYPELIB This, UINT index,
323     TYPEKIND *pTKind); 
324
325 static HRESULT WINAPI ITypeLib_fnGetTypeInfoOfGuid( LPTYPELIB This, REFGUID guid,
326     ITypeInfo **ppTinfo);
327
328 static HRESULT WINAPI ITypeLib_fnGetLibAttr( LPTYPELIB This, 
329     LPTLIBATTR *ppTLibAttr); 
330
331 static HRESULT WINAPI ITypeLib_fnGetTypeComp( LPTYPELIB This,
332     ITypeComp **ppTComp); 
333
334 static HRESULT WINAPI ITypeLib_fnGetDocumentation( LPTYPELIB This, INT index,
335     BSTR *pBstrName, BSTR *pBstrDocString, DWORD *pdwHelpContext, 
336     BSTR *pBstrHelpFile);
337
338 static HRESULT WINAPI ITypeLib_fnIsName( LPTYPELIB This, LPOLESTR szNameBuf,
339     ULONG lHashVal, BOOL *pfName);
340
341 static HRESULT WINAPI ITypeLib_fnFindName( LPTYPELIB This, LPOLESTR szNameBuf,
342     ULONG lHashVal, ITypeInfo **ppTInfo, MEMBERID *rgMemId, UINT16 *pcFound);
343
344 static VOID WINAPI ITypeLib_fnReleaseTLibAttr( LPTYPELIB This,
345                 TLIBATTR *pTLibAttr);
346
347 static HRESULT WINAPI ITypeLib2_fnGetCustData( ITypeLib * This, REFGUID guid, 
348         VARIANT *pVarVal); 
349
350 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics( ITypeLib * This, 
351         UINT *pcUniqueNames, UINT *pcchUniqueNames); 
352
353 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2( ITypeLib * This, 
354         INT index, LCID lcid, BSTR *pbstrHelpString,
355         INT *pdwHelpStringContext, BSTR *pbstrHelpStringDll); 
356
357 static HRESULT WINAPI ITypeLib2_fnGetAllCustData( ITypeLib * This,
358         CUSTDATA *pCustData);
359 static ICOM_VTABLE(ITypeLib) tlbvt = {
360     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
361     ITypeLib_fnQueryInterface,
362     ITypeLib_fnAddRef,
363     ITypeLib_fnRelease,
364     ITypeLib_fnGetTypeInfoCount,
365     ITypeLib_fnGetTypeInfo,
366     ITypeLib_fnGetTypeInfoType,
367     ITypeLib_fnGetTypeInfoOfGuid,
368     ITypeLib_fnGetLibAttr,
369     ITypeLib_fnGetTypeComp,
370     ITypeLib_fnGetDocumentation,
371     ITypeLib_fnIsName,
372     ITypeLib_fnFindName,
373     ITypeLib_fnReleaseTLibAttr,
374     ITypeLib2_fnGetCustData,
375     ITypeLib2_fnGetLibStatistics,
376     ITypeLib2_fnGetDocumentation2,
377     ITypeLib2_fnGetAllCustData
378  };
379 /* TypeInfo Methods */
380
381 static HRESULT WINAPI ITypeInfo_fnQueryInterface( LPTYPEINFO This, REFIID riid,
382     VOID **ppvObject); 
383 static ULONG WINAPI ITypeInfo_fnAddRef( LPTYPEINFO This); 
384 static ULONG WINAPI ITypeInfo_fnRelease( LPTYPEINFO This); 
385 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( LPTYPEINFO This,
386         LPTYPEATTR  *ppTypeAttr); 
387
388 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( LPTYPEINFO This,
389         ITypeComp  * *ppTComp); 
390
391 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( LPTYPEINFO This, UINT index,
392         LPFUNCDESC  *ppFuncDesc); 
393
394 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( LPTYPEINFO This, UINT index,
395         LPVARDESC  *ppVarDesc); 
396
397 static HRESULT WINAPI ITypeInfo_fnGetNames( LPTYPEINFO This, MEMBERID memid,
398         BSTR  *rgBstrNames, UINT cMaxNames, UINT  *pcNames);
399
400
401 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType( LPTYPEINFO This,
402         UINT index, HREFTYPE  *pRefType); 
403
404 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( LPTYPEINFO This,
405         UINT index, INT  *pImplTypeFlags); 
406
407 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( LPTYPEINFO This,
408         LPOLESTR  *rgszNames, UINT cNames, MEMBERID  *pMemId); 
409
410 static HRESULT WINAPI ITypeInfo_fnInvoke( LPTYPEINFO This, VOID  *pIUnk,
411         MEMBERID memid, UINT16 dwFlags, DISPPARAMS  *pDispParams, 
412         VARIANT  *pVarResult, EXCEPINFO  *pExcepInfo, UINT  *pArgErr);
413
414 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( LPTYPEINFO This,
415         MEMBERID memid, BSTR  *pBstrName, BSTR  *pBstrDocString, 
416         DWORD  *pdwHelpContext, BSTR  *pBstrHelpFile); 
417
418 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( LPTYPEINFO This,
419         MEMBERID memid, INVOKEKIND invKind, BSTR  *pBstrDllName,
420         BSTR  *pBstrName, WORD  *pwOrdinal); 
421
422 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo( LPTYPEINFO This,
423         HREFTYPE hRefType, ITypeInfo  * *ppTInfo); 
424
425 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( LPTYPEINFO This,
426         MEMBERID memid, INVOKEKIND invKind, PVOID *ppv); 
427
428 static HRESULT WINAPI ITypeInfo_fnCreateInstance( LPTYPEINFO This, 
429         IUnknown *pUnk, REFIID riid, VOID  * *ppvObj); 
430
431 static HRESULT WINAPI ITypeInfo_fnGetMops( LPTYPEINFO This, MEMBERID memid, 
432         BSTR  *pBstrMops);
433
434
435 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( LPTYPEINFO This,
436         ITypeLib  * *ppTLib, UINT  *pIndex); 
437
438 static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( LPTYPEINFO This,
439         TYPEATTR *pTypeAttr); 
440
441 static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc( LPTYPEINFO This,
442         FUNCDESC *pFuncDesc); 
443
444 static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( LPTYPEINFO This,
445         VARDESC *pVarDesc); 
446 /* itypeinfo2 methods */
447 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo * This,
448     TYPEKIND *pTypeKind);
449 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo * This,
450     UINT *pTypeFlags);
451 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo * This,
452     MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex);
453 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo * This,
454     MEMBERID memid, UINT *pVarIndex);
455 static HRESULT WINAPI ITypeInfo2_fnGetCustData( ITypeInfo * This,
456     REFGUID guid, VARIANT *pVarVal);
457 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData( ITypeInfo * This,
458     UINT index, REFGUID guid, VARIANT *pVarVal);
459 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData( ITypeInfo * This,
460     UINT indexFunc, UINT indexParam, REFGUID guid, VARIANT *pVarVal);
461 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData( ITypeInfo * This,
462     UINT index, REFGUID guid, VARIANT *pVarVal);
463 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData( ITypeInfo * This,
464     UINT index, REFGUID guid, VARIANT *pVarVal);
465 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2( ITypeInfo * This,
466     MEMBERID memid, LCID lcid, BSTR *pbstrHelpString,
467     INT *pdwHelpStringContext, BSTR *pbstrHelpStringDll);
468 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData( ITypeInfo * This,
469     CUSTDATA *pCustData);
470 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData( ITypeInfo * This,
471     UINT index, CUSTDATA *pCustData);
472 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo * This,
473     UINT indexFunc, UINT indexParam, CUSTDATA *pCustData);
474 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo * This,
475     UINT index, CUSTDATA *pCustData);
476 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData( ITypeInfo * This,
477     UINT index, CUSTDATA *pCustData);
478
479 static ICOM_VTABLE(ITypeInfo) tinfvt = {
480     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
481     ITypeInfo_fnQueryInterface,
482     ITypeInfo_fnAddRef,
483     ITypeInfo_fnRelease,
484     ITypeInfo_fnGetTypeAttr,
485     ITypeInfo_fnGetTypeComp,
486     ITypeInfo_fnGetFuncDesc,
487     ITypeInfo_fnGetVarDesc,
488     ITypeInfo_fnGetNames,
489     ITypeInfo_fnGetRefTypeOfImplType,
490     ITypeInfo_fnGetImplTypeFlags,
491     ITypeInfo_fnGetIDsOfNames,
492     ITypeInfo_fnInvoke,
493     ITypeInfo_fnGetDocumentation,
494     ITypeInfo_fnGetDllEntry,
495     ITypeInfo_fnGetRefTypeInfo,
496     ITypeInfo_fnAddressOfMember,
497     ITypeInfo_fnCreateInstance,
498     ITypeInfo_fnGetMops,
499     ITypeInfo_fnGetContainingTypeLib,
500     ITypeInfo_fnReleaseTypeAttr,
501     ITypeInfo_fnReleaseFuncDesc,
502     ITypeInfo_fnReleaseVarDesc,
503
504     ITypeInfo2_fnGetTypeKind,
505     ITypeInfo2_fnGetTypeFlags,
506     ITypeInfo2_fnGetFuncIndexOfMemId,
507     ITypeInfo2_fnGetVarIndexOfMemId,
508     ITypeInfo2_fnGetCustData,
509     ITypeInfo2_fnGetFuncCustData,
510     ITypeInfo2_fnGetParamCustData,
511     ITypeInfo2_fnGetVarCustData,
512     ITypeInfo2_fnGetImplTypeCustData,
513     ITypeInfo2_fnGetDocumentation2,
514     ITypeInfo2_fnGetAllCustData,
515     ITypeInfo2_fnGetAllFuncCustData,
516     ITypeInfo2_fnGetAllParamCustData,
517     ITypeInfo2_fnGetAllVarCustData,
518     ITypeInfo2_fnGetAllImplTypeCustData,
519
520 };
521
522 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]={/* VT_LPWSTR is largest type that */
523                                                                                 /* may appear in type description*/
524         {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
525         {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
526     {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
527         {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
528     {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
529         {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
530     {{0},30},{{0},31}};
531
532 static void TLB_abort()
533 {
534     DebugBreak();
535 }
536 static void * TLB_Alloc(unsigned size)
537 {
538     void * ret;
539     if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
540         /* FIXME */
541         ERR("cannot allocate memory\n");
542     }
543     return ret;
544 }
545
546 /* candidate for a more global appearance... */
547 static BSTR  TLB_DupAtoBstr(PCHAR Astr)
548 {
549     int len;
550     BSTR bstr;
551     DWORD *pdw  ;
552     if(!Astr)
553         return NULL;
554     len=strlen(Astr);
555     pdw  =TLB_Alloc((len+3)*sizeof(OLECHAR));
556     pdw[0]=(len)*sizeof(OLECHAR);
557     bstr=(BSTR)&( pdw[1]);
558     lstrcpyAtoW( bstr, Astr);
559     TRACE("copying %s to (%p)\n", Astr, bstr);
560     return bstr;
561 }
562
563 static void TLB_Free(void * ptr)
564 {
565     HeapFree(GetProcessHeap(), 0, ptr);
566 }
567 /* read function */
568 DWORD TLB_Read(void *buffer,  DWORD count, TLBContext *pcx, long where )
569 {
570     if (where != DO_NOT_SEEK)
571     {
572         where += pcx->oStart;
573         if (where > pcx->length)
574         {
575             /* FIXME */
576             ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
577             TLB_abort();
578         }
579         pcx->pos = where;
580     }
581     if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
582     memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
583     pcx->pos += count;
584     return count;
585 }
586
587 static void TLB_ReadGuid( GUID *pGuid, int offset,   TLBContext *pcx)
588 {
589     if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
590         memset(pGuid,0, sizeof(GUID));
591         return;
592     }
593     TLB_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
594 }
595
596 PCHAR TLB_ReadName( TLBContext *pcx, int offset)
597 {
598     char * name;
599     TLBNameIntro niName;
600     TLB_Read(&niName, sizeof(niName), pcx,
601                                 pcx->pTblDir->pNametab.offset+offset);
602     niName.namelen &= 0xFF; /* FIXME: correct ? */
603     name=TLB_Alloc((niName.namelen & 0xff) +1);
604     TLB_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
605     name[niName.namelen & 0xff]='\0';
606     return name;
607 }
608 PCHAR TLB_ReadString( TLBContext *pcx, int offset)
609 {
610     char * string;
611     INT16 length;
612     if(offset<0) return NULL;
613     TLB_Read(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
614     if(length <= 0) return 0;
615     string=TLB_Alloc(length +1);
616     TLB_Read(string, length, pcx, DO_NOT_SEEK);
617     string[length]='\0';
618     return string;
619 }
620 /*
621  * read a value and fill a VARIANT structure 
622  */
623 static void TLB_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
624 {
625     int size;
626     if(offset <0) { /* data is packed in here */
627         pVar->vt = (offset & 0x7c000000 )>> 26;
628         V_UNION(pVar, iVal) = offset & 0xffff;
629         return;
630     }
631     TLB_Read(&(pVar->vt), sizeof(VARTYPE), pcx, 
632         pcx->pTblDir->pCustData.offset + offset );
633     switch(pVar->vt){
634         case VT_EMPTY:  /* FIXME: is this right? */
635         case VT_NULL:   /* FIXME: is this right? */
636         case VT_I2  :   /* this should not happen */
637         case VT_I4  :
638         case VT_R4  :
639         case VT_ERROR   : 
640         case VT_BOOL    : 
641         case VT_I1  : 
642         case VT_UI1 : 
643         case VT_UI2 : 
644         case VT_UI4 : 
645         case VT_INT : 
646         case VT_UINT    : 
647         case VT_VOID    : /* FIXME: is this right? */
648         case VT_HRESULT : 
649             size=4; break;
650         case VT_R8  :
651         case VT_CY  :
652         case VT_DATE    : 
653         case VT_I8  : 
654         case VT_UI8 : 
655         case VT_DECIMAL :  /* FIXME: is this right? */
656         case VT_FILETIME :
657             size=8;break;
658             /* pointer types with known behaviour */
659         case VT_BSTR    :{
660             char * ptr;
661             TLB_Read(&size, sizeof(INT), pcx, DO_NOT_SEEK );
662             ptr=TLB_Alloc(size);/* allocate temp buffer */
663             TLB_Read(ptr, size, pcx, DO_NOT_SEEK ); /* read string (ANSI) */
664             V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
665             /* FIXME: do we need a AtoW conversion here? */
666             V_UNION(pVar, bstrVal[size])=L'\0';
667             while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
668             TLB_Free(ptr);
669         }
670             size=-4; break;
671     /* FIXME: this will not work AT ALL when the variant contains a pointer */
672         case VT_DISPATCH :
673         case VT_VARIANT : 
674         case VT_UNKNOWN : 
675         case VT_PTR : 
676         case VT_SAFEARRAY :
677         case VT_CARRAY  : 
678         case VT_USERDEFINED : 
679         case VT_LPSTR   : 
680         case VT_LPWSTR  : 
681         case VT_BLOB    : 
682         case VT_STREAM  : 
683         case VT_STORAGE : 
684         case VT_STREAMED_OBJECT : 
685         case VT_STORED_OBJECT   : 
686         case VT_BLOB_OBJECT : 
687         case VT_CF  : 
688         case VT_CLSID   : 
689         default: 
690             size=0; 
691             FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
692                 pVar->vt);
693     }
694
695     if(size>0) /* (big|small) endian correct? */
696         TLB_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
697         return ;
698 }
699 /*
700  * create a linked list with custom data
701  */
702 static int TLB_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
703 {
704     TLBCDGuid entry;
705     TLBCustData* pNew;
706     int count=0;
707     while(offset >=0){
708         count++;
709         pNew=TLB_Alloc(sizeof(TLBCustData));
710         TLB_Read(&entry, sizeof(entry), pcx, 
711             pcx->pTblDir->pCDGuids.offset+offset);
712         TLB_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
713         TLB_ReadValue(&(pNew->data), entry.DataOffset, pcx);
714         /* add new custom data at head of the list */
715         pNew->next=*ppCustData;
716         *ppCustData=pNew;
717         offset = entry.next;
718     }
719     return count;
720 }
721
722 static void TLB_GetTdesc(TLBContext *pcx, INT type,TYPEDESC * pTd )
723 {
724     if(type <0)
725         pTd->vt=type & VT_TYPEMASK;
726     else
727         *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
728 }
729 static void TLB_DoFuncs(TLBContext *pcx, int cFuncs, int cVars,
730                           int offset, TLBFuncDesc ** pptfd)
731 {
732     /* 
733      * member information is stored in a data structure at offset
734      * indicated by the memoffset field of the typeinfo structure
735      * There are several distinctive parts.
736      * the first part starts with a field that holds the total length 
737      * of this (first) part excluding this field. Then follow the records,
738      * for each member there is one record.
739      *
740      * First entry is always the length of the record (excluding this
741      * length word). 
742      * Rest of the record depends on the type of the member. If there is 
743      * a field indicating the member type (function variable intereface etc)
744      * I have not found it yet. At this time we depend on the information
745      * in the type info and the usual order how things are stored.
746      *
747      * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
748      * for each member;
749      * 
750      * Third is a equal sized array with file offsets to the name entry 
751      * of each member.
752      * 
753      * Forth and last (?) part is an array with offsets to the records in the
754      * first part of this file segment.
755      */
756
757     int infolen, nameoffset, reclength, nrattributes;
758     char recbuf[512];
759     TLBFuncRecord * pFuncRec=(TLBFuncRecord *) recbuf;
760     int i, j;
761     int recoffset=offset+sizeof(INT);
762     TLB_Read(&infolen,sizeof(INT), pcx, offset);
763     for(i=0;i<cFuncs;i++){
764         *pptfd=TLB_Alloc(sizeof(TLBFuncDesc));
765     /* name, eventually add to a hash table */
766         TLB_Read(&nameoffset, sizeof(INT), pcx, 
767             offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
768         (*pptfd)->Name=TLB_ReadName(pcx, nameoffset);
769     /* read the function information record */
770         TLB_Read(&reclength, sizeof(INT), pcx, recoffset);
771         reclength &=0x1ff;
772         TLB_Read(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ; 
773     /* do the attributes */
774         nrattributes=(reclength-pFuncRec->nrargs*3*sizeof(int)-0x18)
775             /sizeof(int);
776         if(nrattributes>0){
777             (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
778             if(nrattributes>1){
779                 (*pptfd)->HelpString = TLB_ReadString(pcx,
780                                                       pFuncRec->OptAttr[1]) ;
781                 if(nrattributes>2){
782                     if(pFuncRec->FKCCIC & 0x2000)
783                         (*pptfd)->Entry = (char *) pFuncRec->OptAttr[2] ;
784                     else
785                         (*pptfd)->Entry = TLB_ReadString(pcx,
786                                                          pFuncRec->OptAttr[2]);
787                     if(nrattributes>5 )
788                         (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
789                     if(nrattributes>6 && pFuncRec->FKCCIC & 0x80){
790                         TLB_CustData(pcx, pFuncRec->OptAttr[6],
791                                 &(*pptfd)->pCustData);
792                     }
793                 }
794             }
795         }
796     /* fill the FuncDesc Structure */
797         TLB_Read(&(*pptfd)->funcdesc.memid, sizeof(INT), pcx, 
798             offset + infolen + ( i + 1) * sizeof(INT));
799         (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
800         (*pptfd)->funcdesc.invkind = ((pFuncRec->FKCCIC) >>3) & 0xF;
801         (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >>8 & 0xF;
802         (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
803         (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
804         (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
805         (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags)  ;
806         TLB_GetTdesc(pcx, pFuncRec->DataType,   
807             &(*pptfd)->funcdesc.elemdescFunc.tdesc) ;
808                                     
809         /* do the parameters/arguments */
810         if(pFuncRec->nrargs){
811             TLBParameterInfo paraminfo;
812             (*pptfd)->funcdesc.lprgelemdescParam=
813                 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
814             (*pptfd)->pParamDesc=TLB_Alloc(pFuncRec->nrargs *
815                 sizeof(TLBParDesc));
816
817             TLB_Read(&paraminfo,sizeof(paraminfo), pcx, recoffset+reclength -
818                 pFuncRec->nrargs * sizeof(TLBParameterInfo));
819             for(j=0;j<pFuncRec->nrargs;j++){
820                 TLB_GetTdesc(pcx, paraminfo.DataType,   
821                     &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc) ;
822                 V_UNION(&((*pptfd)->funcdesc.lprgelemdescParam[j]),
823                     paramdesc.wParamFlags) = paraminfo.Flags;
824                 (*pptfd)->pParamDesc[j].Name=(void *)paraminfo.oName;
825                 TLB_Read(&paraminfo,sizeof(TLBParameterInfo), pcx,
826                         DO_NOT_SEEK);
827             }
828             /* second time around */
829             for(j=0;j<pFuncRec->nrargs;j++){
830                 /* name */
831                 (*pptfd)->pParamDesc[j].Name=
832                     TLB_ReadName(pcx, (int)(*pptfd)->pParamDesc[j].Name);
833                 /* default value */
834                 if((PARAMFLAG_FHASDEFAULT & V_UNION(&((*pptfd)->funcdesc.
835                     lprgelemdescParam[j]),paramdesc.wParamFlags)) &&
836                     ((pFuncRec->FKCCIC) & 0x1000)){
837                     INT *pInt=(INT *)((char *)pFuncRec + reclength -
838                         (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
839                     PARAMDESC * pParamDesc= &V_UNION(&((*pptfd)->funcdesc.
840                         lprgelemdescParam[j]),paramdesc);
841                     pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
842                     pParamDesc->pparamdescex->cBytes= sizeof(PARAMDESCEX);
843                     TLB_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue), 
844                         pInt[j], pcx);
845                 }
846                 /* custom info */
847                 if(nrattributes>7+j && pFuncRec->FKCCIC & 0x80)
848                     TLB_CustData(pcx, pFuncRec->OptAttr[7+j],
849                                                                         &(*pptfd)->pParamDesc[j].pCustData);
850             }
851         }
852     /* scode is not used: archaic win16 stuff FIXME: right? */
853         (*pptfd)->funcdesc.cScodes = 0 ;
854         (*pptfd)->funcdesc.lprgscode = NULL ;
855         pptfd=&((*pptfd)->next);
856         recoffset += reclength;
857     }
858 }
859 static void TLB_DoVars(TLBContext *pcx, int cFuncs, int cVars,
860                           int offset, TLBVarDesc ** pptvd)
861 {
862     int infolen, nameoffset, reclength;
863     char recbuf[256];
864     TLBVarRecord * pVarRec=(TLBVarRecord *) recbuf;
865     int i;
866     int recoffset;
867     TLB_Read(&infolen,sizeof(INT), pcx, offset);
868     TLB_Read(&recoffset,sizeof(INT), pcx, offset + infolen + 
869         ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
870     recoffset += offset+sizeof(INT);
871     for(i=0;i<cVars;i++){
872         *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
873     /* name, eventually add to a hash table */
874         TLB_Read(&nameoffset, sizeof(INT), pcx, 
875             offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
876         (*pptvd)->Name=TLB_ReadName(pcx, nameoffset);
877     /* read the variable information record */
878         TLB_Read(&reclength, sizeof(INT), pcx, recoffset);
879         reclength &=0xff;
880         TLB_Read(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ; 
881     /* Optional data */
882         if(reclength >(6*sizeof(INT)) )
883             (*pptvd)->HelpContext=pVarRec->HelpContext;
884         if(reclength >(7*sizeof(INT)) )
885             (*pptvd)->HelpString = TLB_ReadString(pcx, pVarRec->oHelpString) ;
886         if(reclength >(8*sizeof(INT)) )
887         if(reclength >(9*sizeof(INT)) )
888             (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
889     /* fill the VarDesc Structure */
890         TLB_Read(&(*pptvd)->vardesc.memid, sizeof(INT), pcx, 
891             offset + infolen + ( i + 1) * sizeof(INT));
892         (*pptvd)->vardesc.varkind = pVarRec->VarKind;
893         (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
894         TLB_GetTdesc(pcx, pVarRec->DataType,    
895             &(*pptvd)->vardesc.elemdescVar.tdesc) ;
896 /*   (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) fixme?? */
897         if(pVarRec->VarKind == VAR_CONST ){
898             V_UNION(&((*pptvd)->vardesc),lpvarValue)=TLB_Alloc(sizeof(VARIANT));
899             TLB_ReadValue(V_UNION(&((*pptvd)->vardesc),lpvarValue), 
900                 pVarRec->OffsValue, pcx);
901         }else
902             V_UNION(&((*pptvd)->vardesc),oInst)=pVarRec->OffsValue;
903         pptvd=&((*pptvd)->next);
904         recoffset += reclength;
905     }
906 }
907 /* fill in data for a hreftype (offset). When the refernced type is contained
908  * in the typelib, its just an (file) offset in the type info base dir.
909  * If comes fom import, its an offset+1 in the ImpInfo table
910  * */
911 static void TLB_DoRefType(TLBContext *pcx, 
912                           int offset, TLBRefType ** pprtd)
913 {
914     int j;
915     if(!HREFTYPE_INTHISFILE( offset)) {
916         /* external typelib */
917         TLBImpInfo impinfo;
918         TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
919         TLB_Read(&impinfo, sizeof(impinfo), pcx, 
920             pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
921         for(j=0;pImpLib;j++){   /* search the known offsets of all import libraries */
922             if(pImpLib->offset==impinfo.oImpFile) break;
923             pImpLib=pImpLib->next;
924         }
925         if(pImpLib){
926             (*pprtd)->reference=offset;
927             (*pprtd)->pImpTLInfo=pImpLib;
928             TLB_ReadGuid(&(*pprtd)->guid, impinfo.oGuid, pcx);
929         }else{
930             ERR("Cannot find a reference\n");
931             (*pprtd)->reference=-1;
932             (*pprtd)->pImpTLInfo=(void *)-1;
933         }
934     }else{
935         /* in this typelib */
936         (*pprtd)->reference=offset;
937         (*pprtd)->pImpTLInfo=(void *)-2;
938     }
939 }
940
941 /* process Implemented Interfaces of a com class */
942 static void TLB_DoImplTypes(TLBContext *pcx, int count,
943                           int offset, TLBRefType ** pprtd)
944 {
945     int i;
946     TLBRefRecord refrec;
947     for(i=0;i<count;i++){
948         if(offset<0) break; /* paranoia */
949         *pprtd=TLB_Alloc(sizeof(TLBRefType));
950         TLB_Read(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
951         TLB_DoRefType(pcx, refrec.reftype, pprtd);
952         (*pprtd)->flags=refrec.flags;
953         (*pprtd)->ctCustData=
954             TLB_CustData(pcx, refrec.oCustData, &(*pprtd)->pCustData);
955         offset=refrec.onext;
956         pprtd=&((*pprtd)->next);
957     }
958 }
959 /*
960  * process a typeinfo record
961  */
962 TLBTypeInfo * TLB_DoTypeInfo(TLBContext *pcx, int count, TLBLibInfo* pLibInfo)
963 {
964     TLBTypeInfoBase tiBase;
965     TLBTypeInfo *ptiRet;
966     ptiRet=TLB_Alloc(sizeof(TLBTypeInfo));
967     ptiRet->lpvtbl = &tinfvt;
968     ptiRet->ref=1;
969     TLB_Read(&tiBase, sizeof(tiBase) ,pcx ,
970         pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
971 /* this where we are coming from */
972     ptiRet->pTypeLib=pLibInfo;
973     ptiRet->index=count;
974 /* fill in the typeattr fields */
975     TLB_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
976     ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid;   /* FIXME: correct? */
977     ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
978     ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
979     ptiRet->TypeAttr.lpstrSchema=NULL;              /* reserved */
980     ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
981     ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
982     ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
983     ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
984     ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
985     ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
986     ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
987     ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
988     ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
989     ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
990     if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
991         TLB_GetTdesc(pcx, tiBase.datatype1, 
992             &ptiRet->TypeAttr.tdescAlias) ;
993 /*  FIXME: */
994 /*    IDLDESC  idldescType; *//* never saw this one != zero  */
995
996 /* name, eventually add to a hash table */
997     ptiRet->Name=TLB_ReadName(pcx, tiBase.NameOffset);
998     TRACE("reading %s\n", ptiRet->Name);
999     /* help info */
1000     ptiRet->DocString=TLB_ReadString(pcx, tiBase.docstringoffs);
1001     ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1002     ptiRet->dwHelpContext=tiBase.helpcontext;
1003 /* note: InfoType's Help file and HelpStringDll come from the containing
1004  * library. Further HelpString and Docstring appear to be the same thing :(
1005  */
1006     /* functions */
1007     if(ptiRet->TypeAttr.cFuncs >0 )
1008         TLB_DoFuncs(pcx, ptiRet->TypeAttr.cFuncs ,ptiRet->TypeAttr.cVars, 
1009         tiBase.memoffset, & ptiRet->funclist);
1010     /* variables */
1011     if(ptiRet->TypeAttr.cVars >0 )
1012         TLB_DoVars(pcx, ptiRet->TypeAttr.cFuncs ,ptiRet->TypeAttr.cVars, 
1013         tiBase.memoffset, & ptiRet->varlist);
1014     if(ptiRet->TypeAttr.cImplTypes >0 ){
1015         if(ptiRet->TypeAttr.typekind == TKIND_COCLASS)
1016             TLB_DoImplTypes(pcx, ptiRet->TypeAttr.cImplTypes , 
1017                 tiBase.datatype1, & ptiRet->impltypelist);
1018         else if(ptiRet->TypeAttr.typekind != TKIND_DISPATCH){
1019             ptiRet->impltypelist=TLB_Alloc(sizeof(TLBRefType));
1020             TLB_DoRefType(pcx, tiBase.datatype1, & ptiRet->impltypelist);
1021         }
1022         }
1023     ptiRet->ctCustData=
1024         TLB_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
1025     return ptiRet;
1026 }
1027
1028
1029 long TLB_FindTlb(TLBContext *pcx)
1030 {/* FIXME: should parse the file properly
1031   * hack to find our tlb data
1032   */
1033 #define TLBBUFSZ 1024
1034     char buff[TLBBUFSZ+1]; /* room for a trailing '\0' */
1035     long ret=0,found=0;
1036     int count;
1037     char *pChr;
1038
1039 #define LOOK_FOR_MAGIC(magic)                           \
1040     count=TLB_Read(buff, TLBBUFSZ, pcx, 0);             \
1041     do {                                                \
1042         buff[count]='\0';                               \
1043         pChr = buff;                                    \
1044         while (pChr) {                                  \
1045             pChr = memchr(pChr,magic[0],count-(pChr-buff));\
1046             if (pChr) {                                 \
1047                 if (!memcmp(pChr,magic,4)) {            \
1048                     ret+= pChr-buff;                    \
1049                     found = 1;                          \
1050                     break;                              \
1051                 }                                       \
1052                 pChr++;                                 \
1053             }                                           \
1054         }                                               \
1055         if (found) break;                               \
1056         ret+=count;                                     \
1057         count=TLB_Read(buff, TLBBUFSZ, pcx, DO_NOT_SEEK);\
1058     } while(count>0);
1059
1060
1061     LOOK_FOR_MAGIC(TLBMAGIC2);
1062     if(count)
1063         return ret;
1064
1065     LOOK_FOR_MAGIC(TLBMAGIC1);
1066     if(count)
1067         ERR("type library format not (yet) implemented\n");
1068     else
1069         ERR("not type library found in this file\n");
1070     return -1;
1071 }
1072 #undef LOOK_FOR_MAGIC
1073
1074 int TLB_ReadTypeLib(PCHAR file, ITypeLib **ppTypeLib)
1075 {
1076     TLBContext cx;
1077     OFSTRUCT ofStruct;
1078     long oStart,lPSegDir;
1079     TLBLibInfo* pLibInfo=NULL;
1080     TLB2Header tlbHeader;
1081     TLBSegDir tlbSegDir;
1082
1083     HANDLE hFile, hMap;
1084     if((hFile=OpenFile(file, &ofStruct, OF_READ))==HFILE_ERROR) {
1085         ERR("cannot open %s error 0x%lx\n",file, GetLastError());
1086         return E_FAIL;
1087     }
1088     cx.length = SetFilePointer( hFile, 0, NULL, FILE_END );
1089     if (!(hMap = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL )))
1090     {
1091         CloseHandle( hFile );
1092         ERR("cannot map %s error 0x%lx\n",file, GetLastError());
1093         return E_FAIL;
1094     }
1095     CloseHandle( hFile );
1096     cx.mapping = MapViewOfFile( hMap, FILE_MAP_READ, 0, 0, 0 );
1097     CloseHandle( hMap );
1098     if (!cx.mapping)
1099     {
1100         ERR("cannot map view of %s error 0x%lx\n",file, GetLastError());
1101         return E_FAIL;
1102     }
1103     /* get pointer to beginning of typelib data */
1104     cx.pos = 0;
1105     cx.oStart=0;
1106     if((oStart=TLB_FindTlb(&cx))<0){
1107         if(oStart==-1)
1108             ERR("cannot locate typelib in  %s\n",file);
1109         else
1110             ERR("unsupported typelib format in  %s\n",file);
1111         UnmapViewOfFile( cx.mapping );
1112         return E_FAIL;
1113     }
1114     cx.oStart=oStart;
1115     pLibInfo=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(TLBLibInfo));
1116     if (!pLibInfo){
1117         UnmapViewOfFile( cx.mapping );
1118         return E_OUTOFMEMORY;
1119     }
1120     pLibInfo->lpvtbl = &tlbvt;
1121     pLibInfo->ref=1;
1122     cx.pLibInfo=pLibInfo;
1123     /* read header */
1124     TLB_Read((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
1125     /* there is a small number of information here until the next important
1126      * part:
1127      * the segment directory . Try to calculate the amount of data */
1128     lPSegDir=sizeof(tlbHeader)+
1129             (tlbHeader.nrtypeinfos)*4+
1130             (tlbHeader.varflags & HELPDLLFLAG? 4 :0);
1131     /* now read the segment directory */
1132     TLB_Read((void*)&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);  
1133     cx.pTblDir=&tlbSegDir;
1134     /* just check two entries */
1135     if (        tlbSegDir.pTypeInfoTab.res0c != 0x0F ||
1136                 tlbSegDir.pImpInfo.res0c != 0x0F
1137     ) {
1138         ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
1139         UnmapViewOfFile( cx.mapping );
1140         return E_FAIL;
1141     }
1142     /* now fill our internal data */
1143     /* TLIBATTR fields */
1144     TLB_ReadGuid(&pLibInfo->LibAttr.guid, tlbHeader.posguid, &cx);
1145     pLibInfo->LibAttr.lcid=tlbHeader.lcid;
1146     pLibInfo->LibAttr.syskind=tlbHeader.varflags & 0x0f; /* check the mask */
1147     pLibInfo->LibAttr.wMajorVerNum=LOWORD(tlbHeader.version);
1148     pLibInfo->LibAttr.wMinorVerNum=HIWORD(tlbHeader.version);
1149     pLibInfo->LibAttr.wLibFlags=(WORD) tlbHeader.flags & 0xffff;/* check mask */
1150     /* name, eventually add to a hash table */
1151     pLibInfo->Name=TLB_ReadName(&cx, tlbHeader.NameOffset);
1152     /* help info */
1153     pLibInfo->DocString=TLB_ReadString(&cx, tlbHeader.helpstring);
1154     pLibInfo->HelpFile=TLB_ReadString(&cx, tlbHeader.helpfile);
1155     if( tlbHeader.varflags & HELPDLLFLAG){
1156             int offset;
1157             TLB_Read(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
1158             pLibInfo->HelpStringDll=TLB_ReadString(&cx, offset);
1159     }
1160
1161     pLibInfo->dwHelpContext=tlbHeader.helpstringcontext;
1162     /* custom data */
1163     if(tlbHeader.CustomDataOffset >= 0) {
1164         pLibInfo->ctCustData=
1165             TLB_CustData(&cx, tlbHeader.CustomDataOffset, &pLibInfo->pCustData);
1166     }
1167     /* fill in typedescriptions */
1168     if(tlbSegDir.pTypdescTab.length >0){
1169         int i, j, cTD=tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
1170         INT16 td[4];
1171         pLibInfo->pTypeDesc=
1172             TLB_Alloc( cTD * sizeof(TYPEDESC));
1173         TLB_Read(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
1174         for(i=0;i<cTD;){
1175             /* FIXME: add several sanity checks here */
1176             pLibInfo->pTypeDesc[i].vt=td[0] & VT_TYPEMASK;
1177             if(td[0]==VT_PTR ||td[0]==VT_SAFEARRAY){/* FIXME: check safearray */
1178                 if(td[3]<0)
1179                     V_UNION(&(pLibInfo->pTypeDesc[i]),lptdesc)=
1180                         & stndTypeDesc[td[2]];
1181                 else
1182                     V_UNION(&(pLibInfo->pTypeDesc[i]),lptdesc)=
1183                         & pLibInfo->pTypeDesc[td[3]/8];
1184             }else if(td[0]==VT_CARRAY)
1185                 V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)=
1186                     (void *)((int) td[2]);  /* temp store offset in*/
1187                                             /* array descr table here */
1188             else if(td[0]==VT_USERDEFINED)
1189                 V_UNION(&(pLibInfo->pTypeDesc[i]),hreftype)=MAKELONG(td[2],td[3]);
1190             if(++i<cTD) TLB_Read(td, sizeof(td), &cx, DO_NOT_SEEK);
1191         }
1192         /* second time around to fill the array subscript info */
1193         for(i=0;i<cTD;i++){
1194             if(pLibInfo->pTypeDesc[i].vt != VT_CARRAY) continue;
1195             if(tlbSegDir.pArrayDescriptions.offset>0){
1196                 TLB_Read(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset +
1197                     (int) V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc));
1198                 V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)=
1199                     TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
1200                 if(td[1]<0)
1201                     V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)->tdescElem.vt=td[0] & VT_TYPEMASK;
1202                 else
1203                     V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)->tdescElem=stndTypeDesc[td[0]/8];
1204                 V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)->cDims=td[2];
1205                 for(j=0;j<td[2];j++){
1206                     TLB_Read(& V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)->rgbounds[j].cElements, 
1207                         sizeof(INT), &cx, DO_NOT_SEEK);
1208                     TLB_Read(& V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)
1209                         ->rgbounds[j].lLbound, 
1210                         sizeof(INT), &cx, DO_NOT_SEEK);
1211                 }
1212             }else{
1213                 V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)=NULL;
1214                 ERR("didn't find array description data\n");
1215             }
1216         }
1217     }
1218     /* imported type libs */
1219     if(tlbSegDir.pImpFiles.offset>0){
1220         TLBImpLib **ppImpLib=&(pLibInfo->pImpLibs);
1221         int offset=tlbSegDir.pImpFiles.offset;
1222         int oGuid;
1223         UINT16 size;
1224         while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length){
1225             *ppImpLib=TLB_Alloc(sizeof(TLBImpLib));
1226             (*ppImpLib)->offset=offset - tlbSegDir.pImpFiles.offset;
1227             TLB_Read(&oGuid, sizeof(INT), &cx, offset);
1228             TLB_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
1229             /* we are skipping some unknown info here */
1230             TLB_Read(& size,sizeof(UINT16), &cx, offset+3*(sizeof(INT)));
1231             size >>=2;
1232             (*ppImpLib)->name=TLB_Alloc(size+1);
1233             TLB_Read((*ppImpLib)->name,size, &cx, DO_NOT_SEEK);
1234             offset=(offset+3*(sizeof(INT))+sizeof(UINT16)+size+3) & 0xfffffffc;
1235
1236             ppImpLib=&(*ppImpLib)->next;
1237         }
1238     }
1239     /* type info's */
1240     if(tlbHeader.nrtypeinfos >=0 ){
1241         /*pLibInfo->TypeInfoCount=tlbHeader.nrtypeinfos; */
1242         TLBTypeInfo **ppTI=&(pLibInfo->pTypeInfo);
1243         int i;
1244         for(i=0;i<(int)tlbHeader.nrtypeinfos;i++){
1245             *ppTI=TLB_DoTypeInfo(&cx, i, pLibInfo);
1246             ppTI=&((*ppTI)->next);
1247             (pLibInfo->TypeInfoCount)++;
1248         }
1249     }
1250
1251     UnmapViewOfFile( cx.mapping );
1252     *ppTypeLib=(LPTYPELIB)pLibInfo;
1253     return S_OK;
1254 }
1255
1256 /*================== ITypeLib(2) Methods ===================================*/
1257
1258 /* ITypeLib::QueryInterface
1259  */
1260 static HRESULT WINAPI ITypeLib_fnQueryInterface( LPTYPELIB This, REFIID riid,
1261     VOID **ppvObject)
1262 {
1263     if(TRACE_ON(typelib)){
1264         char xriid[50];
1265         WINE_StringFromCLSID((LPCLSID)riid,xriid);
1266         TRACE("(%p)->(IID: %s)\n",This,xriid);
1267     }
1268     *ppvObject=NULL;
1269     if(IsEqualIID(riid, &IID_IUnknown) || 
1270             IsEqualIID(riid,&IID_ITypeLib)||
1271             IsEqualIID(riid,&IID_ITypeLib2))
1272         *ppvObject = This;
1273     if(*ppvObject){
1274         ITypeLib_AddRef(This);
1275         TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
1276         return S_OK;
1277     }
1278     TRACE("-- Interface: E_NOINTERFACE\n");
1279     return E_NOINTERFACE;
1280 }
1281
1282 /* ITypeLib::AddRef
1283  */
1284 static ULONG WINAPI ITypeLib_fnAddRef( LPTYPELIB iface)
1285 {
1286         ICOM_THIS( TLBLibInfo, iface);
1287     TRACE("(%p)->ref is %u\n",This, This->ref);
1288     return ++(This->ref);
1289 }
1290
1291 /* ITypeLib::Release
1292  */
1293 static ULONG WINAPI ITypeLib_fnRelease( LPTYPELIB iface)
1294 {
1295         ICOM_THIS( TLBLibInfo, iface);
1296     FIXME("(%p)->ref is %u:   stub\n",This, This->ref);
1297     (This->ref)--;
1298     return S_OK;
1299 }
1300
1301 /* ITypeLib::GetTypeInfoCount
1302  * 
1303  * Returns the number of type descriptions in the type library
1304  */
1305 static UINT WINAPI ITypeLib_fnGetTypeInfoCount( LPTYPELIB iface)
1306 {
1307         ICOM_THIS( TLBLibInfo, iface);
1308     TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
1309     return This->TypeInfoCount;
1310 }
1311
1312 /* ITypeLib::GetTypeInfo
1313  *
1314  *etrieves the specified type description in the library.
1315  */
1316 static HRESULT WINAPI ITypeLib_fnGetTypeInfo( LPTYPELIB iface, UINT index, 
1317     ITypeInfo **ppTInfo)
1318 {
1319     int i;
1320         ICOM_THIS( TLBLibInfo, iface);
1321         TLBTypeInfo **ppTLBTInfo=(TLBTypeInfo **)ppTInfo;
1322     TRACE("(%p) index %d \n",This, index);
1323     for(i=0,*ppTLBTInfo=This->pTypeInfo;*ppTLBTInfo && i != index;i++)
1324         *ppTLBTInfo=(*ppTLBTInfo)->next;
1325     if(*ppTLBTInfo){
1326         (*ppTLBTInfo)->lpvtbl->fnAddRef(*ppTInfo);
1327         TRACE("-- found (%p)->(%p)\n",ppTLBTInfo,*ppTLBTInfo);
1328         return S_OK;
1329     }
1330     TRACE("-- element not found\n");
1331     return TYPE_E_ELEMENTNOTFOUND;
1332 }
1333
1334 /* ITypeLibs::GetTypeInfoType
1335  *
1336  * Retrieves the type of a type description.
1337  */
1338 static HRESULT WINAPI ITypeLib_fnGetTypeInfoType( LPTYPELIB iface, UINT index,
1339     TYPEKIND *pTKind)
1340 {
1341     int i;
1342     TLBTypeInfo *pTInfo;
1343         ICOM_THIS( TLBLibInfo, iface);
1344     TRACE("(%p) index %d \n",This, index);
1345     for(i=0,pTInfo=This->pTypeInfo;pTInfo && i != index;i++)
1346         pTInfo=(pTInfo)->next;
1347     if(pTInfo){
1348         *pTKind=pTInfo->TypeAttr.typekind;
1349         TRACE("-- found Type (%p)->%d\n",pTKind,*pTKind);
1350         return S_OK;
1351     }
1352     TRACE("-- element not found\n");
1353     return TYPE_E_ELEMENTNOTFOUND;
1354 }
1355
1356 /* ITypeLib::GetTypeInfoOfGuid
1357  *
1358  * Retrieves the type description that corresponds to the specified GUID.
1359  *
1360  */
1361 static HRESULT WINAPI ITypeLib_fnGetTypeInfoOfGuid( LPTYPELIB iface,
1362                                 REFGUID guid, ITypeInfo **ppTInfo)
1363 {
1364     int i;
1365         ICOM_THIS( TLBLibInfo, iface);
1366         TLBTypeInfo **ppTLBTInfo=(TLBTypeInfo **)ppTInfo;
1367     if(TRACE_ON(typelib)){
1368         char xriid[50];
1369         WINE_StringFromCLSID((LPCLSID)guid,xriid);
1370         TRACE("(%p) guid %sx)\n",This,xriid);
1371     }
1372     for(i=0,*ppTLBTInfo=This->pTypeInfo;*ppTLBTInfo && 
1373             !IsEqualIID(guid,&(*ppTLBTInfo)->TypeAttr.guid);i++)
1374         *ppTLBTInfo=(*ppTLBTInfo)->next;
1375     if(*ppTLBTInfo){
1376         (*ppTLBTInfo)->lpvtbl->fnAddRef(*ppTInfo);
1377         TRACE("-- found (%p)->(%p)\n",ppTLBTInfo,*ppTLBTInfo);
1378         return S_OK;
1379     }
1380     TRACE("-- element not found\n");
1381     return TYPE_E_ELEMENTNOTFOUND;
1382 }
1383
1384 /* ITypeLib::GetLibAttr
1385  *
1386  * Retrieves the structure that contains the library's attributes.
1387  *
1388  */
1389 static HRESULT WINAPI ITypeLib_fnGetLibAttr( LPTYPELIB iface, 
1390     LPTLIBATTR *ppTLibAttr)
1391 {
1392         ICOM_THIS( TLBLibInfo, iface);
1393     TRACE("(%p)\n",This);
1394     /* FIXME: must do a copy here */
1395     *ppTLibAttr=&This->LibAttr;
1396     return S_OK;
1397 }
1398
1399 /* ITypeLib::GetTypeComp
1400  *
1401  * Enables a client compiler to bind to a library's types, variables,
1402  * constants, and global functions.
1403  *
1404  */
1405 static HRESULT WINAPI ITypeLib_fnGetTypeComp( LPTYPELIB iface,
1406     ITypeComp **ppTComp)
1407 {
1408         ICOM_THIS( TLBLibInfo, iface);
1409     FIXME("(%p): stub!\n",This);
1410     return E_NOTIMPL;
1411 }
1412
1413 /* ITypeLib::GetDocumentation
1414  *
1415  * Retrieves the library's documentation string, the complete Help file name
1416  * and path, and the context identifier for the library Help topic in the Help
1417  * file.
1418  *
1419  */
1420 static HRESULT WINAPI ITypeLib_fnGetDocumentation( LPTYPELIB iface, INT index,
1421     BSTR *pBstrName, BSTR *pBstrDocString, DWORD *pdwHelpContext, 
1422     BSTR *pBstrHelpFile)
1423 {
1424         ICOM_THIS( TLBLibInfo, iface);
1425     HRESULT result;
1426     ITypeInfo *pTInfo;
1427     TRACE("(%p) index %d Name(%p) DocString(%p)"
1428            " HelpContext(%p) HelpFile(%p)\n",
1429         This, index, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
1430     if(index<0){ /* documentation for the typelib */
1431         if(pBstrName)
1432             *pBstrName=TLB_DupAtoBstr(This->Name);
1433         if(pBstrDocString)
1434             *pBstrName=TLB_DupAtoBstr(This->DocString);
1435         if(pdwHelpContext)
1436             *pdwHelpContext=This->dwHelpContext;
1437         if(pBstrHelpFile)
1438             *pBstrName=TLB_DupAtoBstr(This->HelpFile);
1439     }else {/* for a typeinfo */
1440         result=ITypeLib_fnGetTypeInfo(iface, index, &pTInfo);
1441         if(SUCCEEDED(result)){
1442             result=ITypeInfo_GetDocumentation(pTInfo, MEMBERID_NIL,  pBstrName,
1443                 pBstrDocString, pdwHelpContext, pBstrHelpFile);
1444             ITypeInfo_Release(pTInfo);
1445         }
1446         if(!SUCCEEDED(result))
1447             return result;
1448     }
1449     return S_OK;
1450 }
1451
1452 /* ITypeLib::IsName
1453  *
1454  * Indicates whether a passed-in string contains the name of a type or member
1455  * described in the library.
1456  *
1457  */
1458 static HRESULT WINAPI ITypeLib_fnIsName( LPTYPELIB iface, LPOLESTR szNameBuf,
1459     ULONG lHashVal, BOOL *pfName)
1460 {
1461         ICOM_THIS( TLBLibInfo, iface);
1462     TLBTypeInfo *pTInfo;
1463     TLBFuncDesc *pFInfo;
1464     TLBVarDesc *pVInfo;
1465     int i;
1466     PCHAR astr= HEAP_strdupWtoA( GetProcessHeap(), 0, szNameBuf );
1467     *pfName=TRUE;
1468     if(!strcmp(astr,This->Name)) goto ITypeLib_fnIsName_exit;
1469     for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
1470         if(!strcmp(astr,pTInfo->Name)) goto ITypeLib_fnIsName_exit;
1471         for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
1472             if(!strcmp(astr,pFInfo->Name)) goto ITypeLib_fnIsName_exit;
1473             for(i=0;i<pFInfo->funcdesc.cParams;i++)
1474                 if(!strcmp(astr,pFInfo->pParamDesc[i].Name))
1475                     goto ITypeLib_fnIsName_exit;
1476         }
1477         for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next) ;
1478             if(!strcmp(astr,pVInfo->Name)) goto ITypeLib_fnIsName_exit;
1479        
1480     }
1481     *pfName=FALSE;
1482
1483 ITypeLib_fnIsName_exit:
1484     TRACE("(%p)slow! search for %s: %s found!\n", This,
1485           debugstr_a(astr), *pfName?"NOT":"");
1486     
1487     HeapFree( GetProcessHeap(), 0, astr );
1488     return S_OK;
1489 }
1490
1491 /* ITypeLib::FindName
1492  *
1493  * Finds occurrences of a type description in a type library. This may be used
1494  * to quickly verify that a name exists in a type library.
1495  *
1496  */
1497 static HRESULT WINAPI ITypeLib_fnFindName( LPTYPELIB iface, LPOLESTR szNameBuf,
1498     ULONG lHashVal, ITypeInfo **ppTInfo, MEMBERID *rgMemId, UINT16 *pcFound)
1499 {
1500         ICOM_THIS( TLBLibInfo, iface);
1501     TLBTypeInfo *pTInfo;
1502     TLBFuncDesc *pFInfo;
1503     TLBVarDesc *pVInfo;
1504     int i,j = 0;
1505     PCHAR astr= HEAP_strdupWtoA( GetProcessHeap(), 0, szNameBuf );
1506     for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
1507         if(!strcmp(astr,pTInfo->Name)) goto ITypeLib_fnFindName_exit;
1508         for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
1509             if(!strcmp(astr,pFInfo->Name)) goto ITypeLib_fnFindName_exit;
1510             for(i=0;i<pFInfo->funcdesc.cParams;i++)
1511                 if(!strcmp(astr,pFInfo->pParamDesc[i].Name))
1512                     goto ITypeLib_fnFindName_exit;
1513         }
1514         for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next) ;
1515             if(!strcmp(astr,pVInfo->Name)) goto ITypeLib_fnFindName_exit;
1516         continue;
1517 ITypeLib_fnFindName_exit:
1518         pTInfo->lpvtbl->fnAddRef((LPTYPEINFO)pTInfo);
1519         ppTInfo[j]=(LPTYPEINFO)pTInfo;
1520         j++;
1521     }
1522     TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
1523           This, *pcFound, debugstr_a(astr), j);
1524
1525     *pcFound=j;
1526     
1527     HeapFree( GetProcessHeap(), 0, astr );
1528     return S_OK;
1529 }
1530
1531 /* ITypeLib::ReleaseTLibAttr
1532  *
1533  * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
1534  *
1535  */
1536 static VOID WINAPI ITypeLib_fnReleaseTLibAttr( LPTYPELIB iface, TLIBATTR *pTLibAttr)
1537 {
1538         ICOM_THIS( TLBLibInfo, iface);
1539     TRACE("freeing (%p)\n",This);
1540     /* nothing to do */
1541 }
1542
1543 /* ITypeLib2::GetCustData
1544  *
1545  * gets the custom data
1546  */
1547 static HRESULT WINAPI ITypeLib2_fnGetCustData( ITypeLib * iface, REFGUID guid, 
1548         VARIANT *pVarVal)
1549 {
1550         ICOM_THIS( TLBLibInfo, iface);
1551     TLBCustData *pCData;
1552     for(pCData=This->pCustData; pCData; pCData = pCData->next)
1553         if( IsEqualIID(guid, &pCData->guid)) break;
1554     if(TRACE_ON(typelib)){
1555         char xriid[50];
1556         WINE_StringFromCLSID((LPCLSID)guid,xriid);
1557         TRACE("(%p) guid %s %s found!x)\n", This, xriid, pCData? "" : "NOT");
1558     }
1559     if(pCData){
1560         VariantInit( pVarVal);
1561         VariantCopy( pVarVal, &pCData->data);
1562         return S_OK;
1563     }
1564     return E_INVALIDARG;  /* FIXME: correct? */
1565 }
1566
1567 /* ITypeLib2::GetLibStatistics
1568  *
1569  * Returns statistics about a type library that are required for efficient
1570  * sizing of hash tables.
1571  *
1572  */
1573 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics( ITypeLib * iface, 
1574         UINT *pcUniqueNames, UINT *pcchUniqueNames)
1575 {
1576         ICOM_THIS( TLBLibInfo, iface);
1577     FIXME("(%p): stub!\n", This);
1578     if(pcUniqueNames) *pcUniqueNames=1;
1579     if(pcchUniqueNames) *pcchUniqueNames=1;
1580     return S_OK;
1581 }
1582
1583 /* ITypeLib2::GetDocumentation2
1584  *
1585  * Retrieves the library's documentation string, the complete Help file name
1586  * and path, the localization context to use, and the context ID for the
1587  * library Help topic in the Help file.
1588  *
1589  */
1590 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2( ITypeLib * iface, 
1591         INT index, LCID lcid, BSTR *pbstrHelpString,
1592         INT *pdwHelpStringContext, BSTR *pbstrHelpStringDll)
1593 {
1594         ICOM_THIS( TLBLibInfo, iface);
1595     HRESULT result;
1596     ITypeInfo *pTInfo;
1597     FIXME("(%p) index %d lcid %ld half implemented stub!\n", This,
1598             index, lcid);
1599     /* the help string should be obtained from the helpstringdll,
1600      * using the _DLLGetDocumentation function, based on the supplied
1601      * lcid. Nice to do sometime...
1602      */
1603     if(index<0){ /* documentation for the typelib */
1604         if(pbstrHelpString)
1605             *pbstrHelpString=TLB_DupAtoBstr(This->DocString);
1606         if(pdwHelpStringContext)
1607             *pdwHelpStringContext=This->dwHelpContext;
1608         if(pbstrHelpStringDll)
1609             *pbstrHelpStringDll=TLB_DupAtoBstr(This->HelpStringDll);
1610     }else {/* for a typeinfo */
1611         result=ITypeLib_fnGetTypeInfo(iface, index, &pTInfo);
1612         if(SUCCEEDED(result)){
1613             result=ITypeInfo2_fnGetDocumentation2(pTInfo, MEMBERID_NIL, lcid,
1614                 pbstrHelpString, pdwHelpStringContext, pbstrHelpStringDll);
1615             ITypeInfo_Release(pTInfo);
1616         }
1617         if(!SUCCEEDED(result))
1618             return result;
1619     }
1620     return S_OK;
1621 }
1622
1623 /* ITypeLib2::GetAllCustData
1624  *
1625  * Gets all custom data items for the library. 
1626  *
1627  */
1628 static HRESULT WINAPI ITypeLib2_fnGetAllCustData( ITypeLib * iface,
1629         CUSTDATA *pCustData)
1630 {
1631         ICOM_THIS( TLBLibInfo, iface);
1632     TLBCustData *pCData;
1633     int i;
1634     TRACE("(%p) returning %d items\n", This, This->ctCustData); 
1635     pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
1636     if(pCustData->prgCustData ){
1637         pCustData->cCustData=This->ctCustData;
1638         for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
1639             pCustData->prgCustData[i].guid=pCData->guid;
1640             VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
1641         }
1642     }else{
1643         ERR(" OUT OF MEMORY! \n");
1644         return E_OUTOFMEMORY;
1645     }
1646     return S_OK;
1647 }
1648
1649
1650 /*================== ITypeInfo(2) Methods ===================================*/
1651
1652 /* ITypeInfo::QueryInterface
1653  */
1654 static HRESULT WINAPI ITypeInfo_fnQueryInterface( LPTYPEINFO iface, REFIID riid,
1655     VOID **ppvObject)
1656 {
1657         ICOM_THIS( TLBTypeInfo, iface);
1658     if(TRACE_ON(typelib)){
1659         char xriid[50];
1660         WINE_StringFromCLSID((LPCLSID)riid,xriid);
1661         TRACE("(%p)->(IID: %s)\n",This,xriid);
1662     }
1663     *ppvObject=NULL;
1664     if(IsEqualIID(riid, &IID_IUnknown) || 
1665             IsEqualIID(riid,&IID_ITypeInfo)||
1666             IsEqualIID(riid,&IID_ITypeInfo2))
1667         *ppvObject = This;
1668     if(*ppvObject){
1669         ITypeInfo_AddRef(iface);
1670         TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
1671         return S_OK;
1672     }
1673     TRACE("-- Interface: E_NOINTERFACE\n");
1674     return E_NOINTERFACE;
1675 }
1676
1677 /* ITypeInfo::AddRef
1678  */
1679 static ULONG WINAPI ITypeInfo_fnAddRef( LPTYPEINFO iface)
1680 {
1681         ICOM_THIS( TLBTypeInfo, iface);
1682     TRACE("(%p)->ref is %u\n",This, This->ref);
1683     (This->pTypeLib->ref)++;
1684     return ++(This->ref);
1685 }
1686
1687 /* ITypeInfo::Release
1688  */
1689 static ULONG WINAPI ITypeInfo_fnRelease( LPTYPEINFO iface)
1690 {
1691         ICOM_THIS( TLBTypeInfo, iface);
1692     FIXME("(%p)->ref is %u:   stub\n",This, This->ref);
1693     (This->ref)--;
1694     (This->pTypeLib->ref)--;
1695     return S_OK;
1696 }
1697
1698 /* ITypeInfo::GetTypeAttr
1699  *
1700  * Retrieves a TYPEATTR structure that contains the attributes of the type
1701  * description.
1702  *
1703  */
1704 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( LPTYPEINFO iface,
1705         LPTYPEATTR  *ppTypeAttr)
1706 {
1707         ICOM_THIS( TLBTypeInfo, iface);
1708      TRACE("(%p)\n",This);
1709     /* FIXME: must do a copy here */
1710     *ppTypeAttr=&This->TypeAttr;
1711     return S_OK;
1712 }
1713
1714 /* ITypeInfo::GetTypeComp
1715  *
1716  * Retrieves the ITypeComp interface for the type description, which enables a
1717  * client compiler to bind to the type description's members.
1718  *
1719  */
1720 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( LPTYPEINFO iface,
1721         ITypeComp  * *ppTComp)
1722 {
1723         ICOM_THIS( TLBTypeInfo, iface);
1724     FIXME("(%p) stub!\n", This);
1725     return S_OK;
1726 }
1727
1728 /* ITypeInfo::GetFuncDesc
1729  *
1730  * Retrieves the FUNCDESC structure that contains information about a
1731  * specified function.
1732  *
1733  */
1734 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( LPTYPEINFO iface, UINT index,
1735         LPFUNCDESC  *ppFuncDesc)
1736 {
1737         ICOM_THIS( TLBTypeInfo, iface);
1738     int i;
1739     TLBFuncDesc * pFDesc; 
1740     TRACE("(%p) index %d\n", This, index);
1741     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
1742         ;
1743     if(pFDesc){
1744         /* FIXME: must do a copy here */
1745         *ppFuncDesc=&pFDesc->funcdesc;
1746         return S_OK;
1747     }
1748     return E_INVALIDARG;
1749 }
1750
1751 /* ITypeInfo::GetVarDesc
1752  *
1753  * Retrieves a VARDESC structure that describes the specified variable. 
1754  *
1755  */
1756 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( LPTYPEINFO iface, UINT index,
1757         LPVARDESC  *ppVarDesc)
1758 {
1759         ICOM_THIS( TLBTypeInfo, iface);
1760     int i;
1761     TLBVarDesc * pVDesc; 
1762     TRACE("(%p) index %d\n", This, index);
1763     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
1764         ;
1765     if(pVDesc){
1766         /* FIXME: must do a copy here */
1767         *ppVarDesc=&pVDesc->vardesc;
1768         return S_OK;
1769     }
1770     return E_INVALIDARG;
1771 }
1772
1773 /* ITypeInfo_GetNames
1774  *
1775  * Retrieves the variable with the specified member ID (or the name of the
1776  * property or method and its parameters) that correspond to the specified
1777  * function ID.
1778  */
1779 static HRESULT WINAPI ITypeInfo_fnGetNames( LPTYPEINFO iface, MEMBERID memid,
1780         BSTR  *rgBstrNames, UINT cMaxNames, UINT  *pcNames)
1781 {
1782         ICOM_THIS( TLBTypeInfo, iface);
1783     TLBFuncDesc * pFDesc; 
1784     TLBVarDesc * pVDesc; 
1785     int i;
1786     TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid,
1787             cMaxNames);
1788     for(pFDesc=This->funclist; pFDesc->funcdesc.memid != memid && pFDesc;
1789             pFDesc=pFDesc->next)
1790         ;
1791     if(pFDesc){
1792         /* function found, now return function and parameter names */
1793         for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++){
1794             if(!i) *rgBstrNames=TLB_DupAtoBstr(pFDesc->Name);
1795             else
1796                 rgBstrNames[i]=TLB_DupAtoBstr(pFDesc->pParamDesc[i-1].Name);
1797                 
1798         }
1799         *pcNames=i;
1800     }else{
1801         for(pVDesc=This->varlist; pVDesc->vardesc.memid != memid && pVDesc;
1802                 pVDesc=pVDesc->next)
1803             ;
1804         if(pVDesc){
1805             *rgBstrNames=TLB_DupAtoBstr(pFDesc->Name);
1806             *pcNames=1;
1807         }else{
1808             if(This->TypeAttr.typekind==TKIND_INTERFACE && 
1809                     This->TypeAttr.cImplTypes ){
1810                 /* recursive search */
1811                 ITypeInfo *pTInfo;
1812                 HRESULT result;
1813                 result=This->lpvtbl->fnGetRefTypeInfo(iface, 
1814                         This->impltypelist->reference, &pTInfo);
1815                 if(SUCCEEDED(result)){
1816                     result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames,
1817                             cMaxNames, pcNames);
1818                     ITypeInfo_Release(pTInfo);
1819                     return result;
1820                 }
1821                 WARN("Could not search inherited interface!\n");
1822             } else
1823                 WARN("no names found\n");
1824             *pcNames=0;
1825             return TYPE_E_ELEMENTNOTFOUND;
1826         }
1827     }
1828     return S_OK;
1829 }
1830
1831
1832 /* ITypeInfo::GetRefTypeOfImplType
1833  *
1834  * If a type description describes a COM class, it retrieves the type
1835  * description of the implemented interface types. For an interface,
1836  * GetRefTypeOfImplType returns the type information for inherited interfaces,
1837  * if any exist.
1838  *
1839  */
1840 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType( LPTYPEINFO iface,
1841         UINT index, HREFTYPE  *pRefType)
1842 {
1843         ICOM_THIS( TLBTypeInfo, iface);
1844     int(i);
1845     TLBRefType *pIref;
1846     TRACE("(%p) index %d\n", This, index);
1847     for(i=0, pIref=This->impltypelist; i<index && pIref;
1848             i++, pIref=pIref->next)
1849         ;
1850     if(i==index){
1851         *pRefType=pIref->reference;
1852         return S_OK;
1853     }
1854     return TYPE_E_ELEMENTNOTFOUND;
1855 }
1856
1857 /* ITypeInfo::GetImplTypeFlags
1858  * 
1859  * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface 
1860  * or base interface in a type description.
1861  */
1862 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( LPTYPEINFO iface,
1863         UINT index, INT  *pImplTypeFlags)
1864 {
1865         ICOM_THIS( TLBTypeInfo, iface);
1866     int(i);
1867     TLBRefType *pIref;
1868     TRACE("(%p) index %d\n", This, index);
1869     for(i=0, pIref=This->impltypelist; i<index && pIref; i++, pIref=pIref->next)
1870         ;
1871     if(i==index && pIref){
1872         *pImplTypeFlags=pIref->flags;
1873         return S_OK;
1874     }
1875     *pImplTypeFlags=0;
1876     return TYPE_E_ELEMENTNOTFOUND;
1877 }
1878
1879 /* GetIDsOfNames
1880  * Maps between member names and member IDs, and parameter names and
1881  * parameter IDs.
1882  */
1883 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( LPTYPEINFO iface,
1884         LPOLESTR  *rgszNames, UINT cNames, MEMBERID  *pMemId)
1885 {
1886         ICOM_THIS( TLBTypeInfo, iface);
1887     TLBFuncDesc * pFDesc; 
1888     TLBVarDesc * pVDesc; 
1889     HRESULT ret=S_OK;
1890     PCHAR aszName= HEAP_strdupWtoA( GetProcessHeap(), 0, *rgszNames);
1891     TRACE("(%p) Name %s cNames %d\n", This, debugstr_a(aszName),
1892             cNames);
1893     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
1894         int i, j;
1895         if( !strcmp(aszName, pFDesc->Name)) {
1896             if(cNames) *pMemId=pFDesc->funcdesc.memid;
1897             for(i=1; i < cNames; i++){
1898                 PCHAR aszPar= HEAP_strdupWtoA( GetProcessHeap(), 0,
1899                         rgszNames[i]);
1900                 for(j=0; j<pFDesc->funcdesc.cParams; j++)
1901                     if(strcmp(aszPar,pFDesc->pParamDesc[j].Name))
1902                             break;
1903                 if( j<pFDesc->funcdesc.cParams)
1904                     pMemId[i]=j;
1905                 else
1906                    ret=DISP_E_UNKNOWNNAME;
1907                 HeapFree( GetProcessHeap(), 0, aszPar);         
1908             };
1909             HeapFree (GetProcessHeap(), 0, aszName);
1910             return ret;
1911         }
1912     }   
1913     for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
1914         if( !strcmp(aszName, pVDesc->Name)) {
1915             if(cNames) *pMemId=pVDesc->vardesc.memid;
1916             HeapFree (GetProcessHeap(), 0, aszName);
1917             return ret;
1918         }
1919     }
1920     /* not found, see if this is and interface with an inheritance */       
1921     if(This->TypeAttr.typekind==TKIND_INTERFACE && 
1922             This->TypeAttr.cImplTypes ){
1923         /* recursive search */
1924         ITypeInfo *pTInfo;
1925         ret=ITypeInfo_GetRefTypeInfo(iface, 
1926                 This->impltypelist->reference, &pTInfo);
1927         if(SUCCEEDED(ret)){
1928             ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
1929             ITypeInfo_Release(pTInfo);
1930             return ret;
1931         }
1932         WARN("Could not search inherited interface!\n");
1933     } else
1934         WARN("no names found\n");
1935     return DISP_E_UNKNOWNNAME;
1936 }
1937
1938 /* ITypeInfo::Invoke
1939  * 
1940  * Invokes a method, or accesses a property of an object, that implements the
1941  * interface described by the type description.
1942  */
1943 static HRESULT WINAPI ITypeInfo_fnInvoke( LPTYPEINFO iface, VOID  *pIUnk,
1944         MEMBERID memid, UINT16 dwFlags, DISPPARAMS  *pDispParams,
1945         VARIANT  *pVarResult, EXCEPINFO  *pExcepInfo, UINT  *pArgErr)
1946 {
1947         ICOM_THIS( TLBTypeInfo, iface);
1948     FIXME("(%p) stub!", This);
1949     return S_OK;
1950 }
1951
1952 /* ITypeInfo::GetDocumentation
1953  * 
1954  * Retrieves the documentation string, the complete Help file name and path,
1955  * and the context ID for the Help topic for a specified type description.
1956  */
1957 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( LPTYPEINFO iface,
1958         MEMBERID memid, BSTR  *pBstrName, BSTR  *pBstrDocString,
1959         DWORD  *pdwHelpContext, BSTR  *pBstrHelpFile)
1960 {
1961         ICOM_THIS( TLBTypeInfo, iface);
1962     TLBFuncDesc * pFDesc; 
1963     TLBVarDesc * pVDesc; 
1964     TRACE("(%p) memid %ld Name(%p) DocString(%p)"
1965           " HelpContext(%p) HelpFile(%p)\n",
1966         This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
1967     if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
1968         if(pBstrName)
1969             *pBstrName=TLB_DupAtoBstr(This->Name);
1970         if(pBstrDocString)
1971             *pBstrDocString=TLB_DupAtoBstr(This->DocString);
1972         if(pdwHelpContext)
1973             *pdwHelpContext=This->dwHelpContext;
1974         if(pBstrHelpFile)
1975             *pBstrHelpFile=TLB_DupAtoBstr(This->DocString);/* FIXME */
1976         return S_OK;
1977     }else {/* for a member */
1978     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
1979         if(pFDesc->funcdesc.memid==memid){
1980             return S_OK;
1981         }
1982     for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
1983         if(pVDesc->vardesc.memid==memid){
1984             return S_OK;
1985         }
1986     }
1987     return TYPE_E_ELEMENTNOTFOUND;
1988 }
1989
1990 /*  ITypeInfo::GetDllEntry
1991  * 
1992  * Retrieves a description or specification of an entry point for a function
1993  * in a DLL.
1994  */
1995 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( LPTYPEINFO iface, MEMBERID memid,
1996         INVOKEKIND invKind, BSTR  *pBstrDllName, BSTR  *pBstrName,
1997         WORD  *pwOrdinal)
1998 {
1999         ICOM_THIS( TLBTypeInfo, iface);
2000     FIXME("(%p) stub!\n", This);
2001     return E_FAIL;
2002 }
2003
2004 /* ITypeInfo::GetRefTypeInfo
2005  * 
2006  * If a type description references other type descriptions, it retrieves
2007  * the referenced type descriptions.
2008  */
2009 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo( LPTYPEINFO iface,
2010         HREFTYPE hRefType, ITypeInfo  * *ppTInfo)
2011 {
2012         ICOM_THIS( TLBTypeInfo, iface);
2013     HRESULT result;
2014     if(HREFTYPE_INTHISFILE(hRefType)){
2015         ITypeLib *pTLib;
2016         int Index;
2017         result=This->lpvtbl->fnGetContainingTypeLib(iface, &pTLib, 
2018                 &Index);
2019         if(SUCCEEDED(result)){
2020             result=ITypeLib_GetTypeInfo(pTLib,
2021                     HREFTYPE_INDEX(hRefType),
2022                     ppTInfo);
2023             ITypeLib_Release(pTLib );
2024         }
2025     } else{
2026         /* imported type lib */
2027         TLBRefType * pRefType;
2028         TLBLibInfo *pTypeLib;
2029         for( pRefType=This->impltypelist; pRefType &&
2030                 pRefType->reference != hRefType; pRefType=pRefType->next)
2031             ;
2032         if(!pRefType)
2033             return TYPE_E_ELEMENTNOTFOUND; /* FIXME : correct? */
2034         pTypeLib=pRefType->pImpTLInfo->pImpTypeLib;
2035         if(pTypeLib) /* typelib already loaded */
2036             result=ITypeLib_GetTypeInfoOfGuid(
2037                     (LPTYPELIB)pTypeLib, &pRefType->guid, ppTInfo);
2038         else{
2039             result=LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
2040                     0,0,0, /* FIXME */
2041                     (LPTYPELIB *)&pTypeLib);
2042             if(!SUCCEEDED(result)){
2043                 BSTR libnam=TLB_DupAtoBstr(pRefType->pImpTLInfo->name);
2044                 result=LoadTypeLib(libnam, (LPTYPELIB *)&pTypeLib);
2045                 SysFreeString(libnam);
2046             }
2047             if(SUCCEEDED(result)){
2048                 result=ITypeLib_GetTypeInfoOfGuid(
2049                         (LPTYPELIB)pTypeLib, &pRefType->guid, ppTInfo);
2050                 pRefType->pImpTLInfo->pImpTypeLib=pTypeLib;
2051            }
2052         }
2053     }
2054     TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
2055           SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
2056     return result;
2057 }
2058
2059 /* ITypeInfo::AddressOfMember
2060  * 
2061  * Retrieves the addresses of static functions or variables, such as those
2062  * defined in a DLL.
2063  */
2064 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( LPTYPEINFO iface,
2065         MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
2066 {
2067         ICOM_THIS( TLBTypeInfo, iface);
2068     FIXME("(%p) stub!\n", This);
2069     return S_OK;
2070 }
2071
2072 /* ITypeInfo::CreateInstance
2073  * 
2074  * Creates a new instance of a type that describes a component object class 
2075  * (coclass).
2076  */
2077 static HRESULT WINAPI ITypeInfo_fnCreateInstance( LPTYPEINFO iface, 
2078         IUnknown *pUnk, REFIID riid, VOID  **ppvObj) 
2079 {
2080         ICOM_THIS( TLBTypeInfo, iface);
2081     FIXME("(%p) stub!\n", This);
2082     return S_OK;
2083 }
2084
2085 /* ITypeInfo::GetMops
2086  *
2087  * Retrieves marshaling information.
2088  */
2089 static HRESULT WINAPI ITypeInfo_fnGetMops( LPTYPEINFO iface, MEMBERID memid,
2090                                 BSTR  *pBstrMops)
2091 {
2092         ICOM_THIS( TLBTypeInfo, iface);
2093     FIXME("(%p) stub!\n", This);
2094     return S_OK;
2095 }
2096
2097 /* ITypeInfo::GetContainingTypeLib
2098  * 
2099  * Retrieves the containing type library and the index of the type description
2100  * within that type library.
2101  */
2102 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( LPTYPEINFO iface,
2103         ITypeLib  * *ppTLib, UINT  *pIndex)
2104 {
2105         ICOM_THIS( TLBTypeInfo, iface);
2106     *ppTLib=(LPTYPELIB )(This->pTypeLib);
2107     *pIndex=This->index;
2108     ITypeLib_AddRef(*ppTLib);
2109     TRACE("(%p) returns (%p) index %d!\n", This, *ppTLib, *pIndex);
2110     return S_OK;
2111 }
2112
2113 /* ITypeInfo::ReleaseTypeAttr
2114  *
2115  * Releases a TYPEATTR previously returned by GetTypeAttr.
2116  *
2117  */
2118 static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( LPTYPEINFO iface,
2119         TYPEATTR* pTypeAttr)
2120 {
2121         ICOM_THIS( TLBTypeInfo, iface);
2122     TRACE("(%p)->(%p)\n", This, pTypeAttr);
2123     return S_OK;
2124 }
2125
2126 /* ITypeInfo::ReleaseFuncDesc
2127  *
2128  * Releases a FUNCDESC previously returned by GetFuncDesc. *
2129  */
2130 static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc( LPTYPEINFO iface,
2131         FUNCDESC *pFuncDesc)
2132 {
2133         ICOM_THIS( TLBTypeInfo, iface);
2134     TRACE("(%p)->(%p)\n", This, pFuncDesc);
2135     return S_OK;
2136 }
2137
2138 /* ITypeInfo::ReleaseVarDesc
2139  *
2140  * Releases a VARDESC previously returned by GetVarDesc.
2141  */
2142 static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( LPTYPEINFO iface,
2143         VARDESC *pVarDesc)
2144 {
2145         ICOM_THIS( TLBTypeInfo, iface);
2146     TRACE("(%p)->(%p)\n", This, pVarDesc);
2147     return S_OK;
2148 }
2149
2150 /* ITypeInfo2::GetTypeKind
2151  *
2152  * Returns the TYPEKIND enumeration quickly, without doing any allocations.
2153  *
2154  */
2155 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo * iface,
2156     TYPEKIND *pTypeKind)
2157 {
2158         ICOM_THIS( TLBTypeInfo, iface);
2159     *pTypeKind=This->TypeAttr.typekind;
2160     TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
2161     return S_OK;
2162 }
2163
2164 /* ITypeInfo2::GetTypeFlags
2165  *
2166  * Returns the type flags without any allocations. This returns a DWORD type
2167  * flag, which expands the type flags without growing the TYPEATTR (type
2168  * attribute). 
2169  *
2170  */
2171 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo * iface,
2172     UINT *pTypeFlags)
2173 {
2174         ICOM_THIS( TLBTypeInfo, iface);
2175     *pTypeFlags=This->TypeAttr.wTypeFlags;
2176     TRACE("(%p) flags 0x%04x\n", This,*pTypeFlags);
2177      return S_OK;
2178 }
2179
2180 /* ITypeInfo2::GetFuncIndexOfMemId
2181  * Binds to a specific member based on a known DISPID, where the member name
2182  * is not known (for example, when binding to a default member).
2183  *
2184  */
2185 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo * iface,
2186     MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
2187 {
2188         ICOM_THIS( TLBTypeInfo, iface);
2189     TLBFuncDesc *pFuncInfo;
2190     int i;
2191     HRESULT result;
2192     /* FIXME: should check for invKind??? */
2193     for(i=0, pFuncInfo=This->funclist;pFuncInfo && 
2194             memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
2195     if(pFuncInfo){
2196         *pFuncIndex=i;
2197         result= S_OK;
2198     }else{
2199         *pFuncIndex=0;
2200         result=E_INVALIDARG;
2201     }
2202     TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
2203           memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
2204     return result;
2205 }
2206
2207 /* TypeInfo2::GetVarIndexOfMemId
2208  *
2209  * Binds to a specific member based on a known DISPID, where the member name
2210  * is not known (for example, when binding to a default member). 
2211  *
2212  */
2213 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo * iface,
2214     MEMBERID memid, UINT *pVarIndex)
2215 {
2216         ICOM_THIS( TLBTypeInfo, iface);
2217     TLBVarDesc *pVarInfo;
2218     int i;
2219     HRESULT result;
2220     for(i=0, pVarInfo=This->varlist; pVarInfo && 
2221             memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
2222         ;
2223     if(pVarInfo){
2224         *pVarIndex=i;
2225         result= S_OK;
2226     }else{
2227         *pVarIndex=0;
2228         result=E_INVALIDARG;
2229     }
2230     TRACE("(%p) memid 0x%08lx -> %s\n", This,
2231           memid, SUCCEEDED(result)? "SUCCES":"FAILED");
2232     return result;
2233 }
2234
2235 /* ITypeInfo2::GetCustData
2236  *
2237  * Gets the custom data
2238  */
2239 static HRESULT WINAPI ITypeInfo2_fnGetCustData( ITypeInfo * iface,
2240     REFGUID guid, VARIANT *pVarVal)
2241 {
2242         ICOM_THIS( TLBTypeInfo, iface);
2243     TLBCustData *pCData;
2244     for(pCData=This->pCustData; pCData; pCData = pCData->next)
2245         if( IsEqualIID(guid, &pCData->guid)) break;
2246     if(TRACE_ON(typelib)){
2247         char xriid[50];
2248         WINE_StringFromCLSID((LPCLSID)guid,xriid);
2249         TRACE("(%p) guid %s %s found!x)\n", This, xriid, pCData? "" : "NOT");
2250     }
2251     if(pCData){
2252         VariantInit( pVarVal);
2253         VariantCopy( pVarVal, &pCData->data);
2254         return S_OK;
2255     }
2256     return E_INVALIDARG;  /* FIXME: correct? */
2257 }
2258
2259 /* ITypeInfo2::GetFuncCustData
2260  *
2261  * Gets the custom data
2262  */
2263 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData( ITypeInfo * iface,
2264     UINT index, REFGUID guid, VARIANT *pVarVal)
2265 {
2266         ICOM_THIS( TLBTypeInfo, iface);
2267     TLBCustData *pCData=NULL;
2268     TLBFuncDesc * pFDesc; 
2269     int i;
2270     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
2271             pFDesc=pFDesc->next)
2272         ;
2273     if(pFDesc)
2274         for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
2275             if( IsEqualIID(guid, &pCData->guid)) break;
2276     if(TRACE_ON(typelib)){
2277         char xriid[50];
2278         WINE_StringFromCLSID((LPCLSID)guid,xriid);
2279         TRACE("(%p) guid %s %s found!x)\n", This, xriid, pCData? "" : "NOT");
2280     }
2281     if(pCData){
2282         VariantInit( pVarVal);
2283         VariantCopy( pVarVal, &pCData->data);
2284         return S_OK;
2285     }
2286     return E_INVALIDARG;  /* FIXME: correct? */
2287 }
2288
2289 /* ITypeInfo2::GetParamCustData
2290  *
2291  * Gets the custom data
2292  */
2293 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData( ITypeInfo * iface,
2294     UINT indexFunc, UINT indexParam, REFGUID guid, VARIANT *pVarVal)
2295 {   
2296         ICOM_THIS( TLBTypeInfo, iface);
2297     TLBCustData *pCData=NULL;
2298     TLBFuncDesc * pFDesc; 
2299     int i;
2300     for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
2301             pFDesc=pFDesc->next)
2302         ;
2303     if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
2304         for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData; 
2305                 pCData = pCData->next)
2306             if( IsEqualIID(guid, &pCData->guid)) break;
2307     if(TRACE_ON(typelib)){
2308         char xriid[50];
2309         WINE_StringFromCLSID((LPCLSID)guid,xriid);
2310         TRACE("(%p) guid %s %s found!x)\n", This, xriid, pCData? "" : "NOT");
2311     }
2312     if(pCData){
2313         VariantInit( pVarVal);
2314         VariantCopy( pVarVal, &pCData->data);
2315         return S_OK;
2316     }
2317     return E_INVALIDARG;  /* FIXME: correct? */
2318 }
2319
2320 /* ITypeInfo2::GetVarcCustData
2321  *
2322  * Gets the custom data
2323  */
2324 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData( ITypeInfo * iface,
2325     UINT index, REFGUID guid, VARIANT *pVarVal)
2326 {   
2327         ICOM_THIS( TLBTypeInfo, iface);
2328     TLBCustData *pCData=NULL;
2329     TLBVarDesc * pVDesc; 
2330     int i;
2331     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
2332             pVDesc=pVDesc->next)
2333         ;
2334     if(pVDesc)
2335         for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
2336             if( IsEqualIID(guid, &pCData->guid)) break;
2337     if(TRACE_ON(typelib)){
2338         char xriid[50];
2339         WINE_StringFromCLSID((LPCLSID)guid,xriid);
2340         TRACE("(%p) guid %s %s found!x)\n", This, xriid, pCData? "" : "NOT");
2341     }
2342     if(pCData){
2343         VariantInit( pVarVal);
2344         VariantCopy( pVarVal, &pCData->data);
2345         return S_OK;
2346     }
2347     return E_INVALIDARG;  /* FIXME: correct? */
2348 }
2349
2350 /* ITypeInfo2::GetImplcCustData
2351  *
2352  * Gets the custom data
2353  */
2354 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData( ITypeInfo * iface,
2355     UINT index, REFGUID guid, VARIANT *pVarVal)
2356 {   
2357         ICOM_THIS( TLBTypeInfo, iface);
2358     TLBCustData *pCData=NULL;
2359     TLBRefType * pRDesc; 
2360     int i;
2361     for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
2362             pRDesc=pRDesc->next)
2363         ;
2364     if(pRDesc)
2365         for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
2366             if( IsEqualIID(guid, &pCData->guid)) break;
2367     if(TRACE_ON(typelib)){
2368         char xriid[50];
2369         WINE_StringFromCLSID((LPCLSID)guid,xriid);
2370         TRACE("(%p) guid %s %s found!x)\n", This, xriid, pCData? "" : "NOT");
2371     }
2372     if(pCData){
2373         VariantInit( pVarVal);
2374         VariantCopy( pVarVal, &pCData->data);
2375         return S_OK;
2376     }
2377     return E_INVALIDARG;  /* FIXME: correct? */
2378 }
2379
2380 /* ITypeInfo2::GetDocumentation2
2381  * 
2382  * Retrieves the documentation string, the complete Help file name and path,
2383  * the localization context to use, and the context ID for the library Help
2384  * topic in the Help file.
2385  *
2386  */
2387 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2( ITypeInfo * iface,
2388     MEMBERID memid, LCID lcid, BSTR *pbstrHelpString,
2389     INT *pdwHelpStringContext, BSTR *pbstrHelpStringDll)
2390 {
2391         ICOM_THIS( TLBTypeInfo, iface);
2392     TLBFuncDesc * pFDesc; 
2393     TLBVarDesc * pVDesc; 
2394     TRACE("(%p) memid %ld lcid(0x%lx)  HelpString(%p) "
2395           "HelpStringContext(%p) HelpStringDll(%p)\n",
2396           This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
2397           pbstrHelpStringDll );
2398     /* the help string should be obtained from the helpstringdll,
2399      * using the _DLLGetDocumentation function, based on the supplied
2400      * lcid. Nice to do sometime...
2401      */
2402     if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
2403         if(pbstrHelpString)
2404             *pbstrHelpString=TLB_DupAtoBstr(This->Name);
2405         if(pdwHelpStringContext)
2406             *pdwHelpStringContext=This->dwHelpStringContext;
2407         if(pbstrHelpStringDll)
2408             *pbstrHelpStringDll=
2409                 TLB_DupAtoBstr(This->pTypeLib->HelpStringDll);/* FIXME */
2410         return S_OK;
2411     }else {/* for a member */
2412     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
2413         if(pFDesc->funcdesc.memid==memid){
2414              if(pbstrHelpString)
2415                 *pbstrHelpString=TLB_DupAtoBstr(pFDesc->HelpString);
2416             if(pdwHelpStringContext)
2417                 *pdwHelpStringContext=pFDesc->HelpStringContext;
2418             if(pbstrHelpStringDll)
2419                 *pbstrHelpStringDll=
2420                     TLB_DupAtoBstr(This->pTypeLib->HelpStringDll);/* FIXME */
2421         return S_OK;
2422     }
2423     for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
2424         if(pVDesc->vardesc.memid==memid){
2425              if(pbstrHelpString)
2426                 *pbstrHelpString=TLB_DupAtoBstr(pVDesc->HelpString);
2427             if(pdwHelpStringContext)
2428                 *pdwHelpStringContext=pVDesc->HelpStringContext;
2429             if(pbstrHelpStringDll)
2430                 *pbstrHelpStringDll=
2431                     TLB_DupAtoBstr(This->pTypeLib->HelpStringDll);/* FIXME */
2432             return S_OK;
2433         }
2434     }
2435     return TYPE_E_ELEMENTNOTFOUND;
2436 }
2437
2438 /* ITypeInfo2::GetAllCustData
2439  *
2440  * Gets all custom data items for the Type info. 
2441  *
2442  */
2443 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData( ITypeInfo * iface,
2444     CUSTDATA *pCustData)
2445 {
2446         ICOM_THIS( TLBTypeInfo, iface);
2447     TLBCustData *pCData;
2448     int i;
2449     TRACE("(%p) returning %d items\n", This, This->ctCustData); 
2450     pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
2451     if(pCustData->prgCustData ){
2452         pCustData->cCustData=This->ctCustData;
2453         for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
2454             pCustData->prgCustData[i].guid=pCData->guid;
2455             VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
2456         }
2457     }else{
2458         ERR(" OUT OF MEMORY! \n");
2459         return E_OUTOFMEMORY;
2460     }
2461     return S_OK;
2462 }
2463
2464 /* ITypeInfo2::GetAllFuncCustData
2465  *
2466  * Gets all custom data items for the specified Function
2467  *
2468  */
2469 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData( ITypeInfo * iface,
2470     UINT index, CUSTDATA *pCustData)
2471 {
2472         ICOM_THIS( TLBTypeInfo, iface);
2473     TLBCustData *pCData;
2474     TLBFuncDesc * pFDesc; 
2475     int i;
2476     TRACE("(%p) index %d\n", This, index); 
2477     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
2478             pFDesc=pFDesc->next)
2479         ;
2480     if(pFDesc){
2481         pCustData->prgCustData =
2482             TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
2483         if(pCustData->prgCustData ){
2484             pCustData->cCustData=pFDesc->ctCustData;
2485             for(i=0, pCData=pFDesc->pCustData; pCData; i++,
2486                     pCData = pCData->next){
2487                 pCustData->prgCustData[i].guid=pCData->guid;
2488                 VariantCopy(& pCustData->prgCustData[i].varValue,
2489                         & pCData->data);
2490             }
2491         }else{
2492             ERR(" OUT OF MEMORY! \n");
2493             return E_OUTOFMEMORY;
2494         }
2495         return S_OK;
2496     }
2497     return TYPE_E_ELEMENTNOTFOUND;
2498 }
2499
2500 /* ITypeInfo2::GetAllParamCustData
2501  *
2502  * Gets all custom data items for the Functions
2503  *
2504  */
2505 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo * iface,
2506     UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
2507 {
2508         ICOM_THIS( TLBTypeInfo, iface);
2509     TLBCustData *pCData=NULL;
2510     TLBFuncDesc * pFDesc; 
2511     int i;
2512     TRACE("(%p) index %d\n", This, indexFunc); 
2513     for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
2514             pFDesc=pFDesc->next)
2515         ;
2516     if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
2517         pCustData->prgCustData = 
2518             TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
2519                     sizeof(CUSTDATAITEM));
2520         if(pCustData->prgCustData ){
2521             pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
2522             for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
2523                     pCData; i++, pCData = pCData->next){
2524                 pCustData->prgCustData[i].guid=pCData->guid;
2525                 VariantCopy(& pCustData->prgCustData[i].varValue,
2526                         & pCData->data);
2527             }
2528         }else{
2529             ERR(" OUT OF MEMORY! \n");
2530             return E_OUTOFMEMORY;
2531         }
2532         return S_OK;
2533     }
2534     return TYPE_E_ELEMENTNOTFOUND;
2535 }
2536
2537 /* ITypeInfo2::GetAllVarCustData
2538  *
2539  * Gets all custom data items for the specified Variable
2540  *
2541  */
2542 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo * iface,
2543     UINT index, CUSTDATA *pCustData)
2544 {
2545         ICOM_THIS( TLBTypeInfo, iface);
2546     TLBCustData *pCData;
2547     TLBVarDesc * pVDesc; 
2548     int i;
2549     TRACE("(%p) index %d\n", This, index); 
2550     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
2551             pVDesc=pVDesc->next)
2552         ;
2553     if(pVDesc){
2554         pCustData->prgCustData =
2555             TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
2556         if(pCustData->prgCustData ){
2557             pCustData->cCustData=pVDesc->ctCustData;
2558             for(i=0, pCData=pVDesc->pCustData; pCData; i++,
2559                     pCData = pCData->next){
2560                 pCustData->prgCustData[i].guid=pCData->guid;
2561                 VariantCopy(& pCustData->prgCustData[i].varValue,
2562                         & pCData->data);
2563             }
2564         }else{
2565             ERR(" OUT OF MEMORY! \n");
2566             return E_OUTOFMEMORY;
2567         }
2568         return S_OK;
2569     }
2570     return TYPE_E_ELEMENTNOTFOUND;
2571 }
2572
2573 /* ITypeInfo2::GetAllImplCustData
2574  *
2575  * Gets all custom data items for the specified implementation type
2576  *
2577  */
2578 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData( ITypeInfo * iface,
2579     UINT index, CUSTDATA *pCustData)
2580 {
2581         ICOM_THIS( TLBTypeInfo, iface);
2582     TLBCustData *pCData;
2583     TLBRefType * pRDesc; 
2584     int i;
2585     TRACE("(%p) index %d\n", This, index); 
2586     for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
2587             pRDesc=pRDesc->next)
2588         ;
2589     if(pRDesc){
2590         pCustData->prgCustData =
2591             TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
2592         if(pCustData->prgCustData ){
2593             pCustData->cCustData=pRDesc->ctCustData;
2594             for(i=0, pCData=pRDesc->pCustData; pCData; i++,
2595                     pCData = pCData->next){
2596                 pCustData->prgCustData[i].guid=pCData->guid;
2597                 VariantCopy(& pCustData->prgCustData[i].varValue,
2598                         & pCData->data);
2599             }
2600         }else{
2601             ERR(" OUT OF MEMORY! \n");
2602             return E_OUTOFMEMORY;
2603         }
2604         return S_OK;
2605     }
2606     return TYPE_E_ELEMENTNOTFOUND;
2607 }
2608