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