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