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