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