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