Remove unnecessary single quoting of debugstr_xxx strings.
[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 structures 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)) && myLCID)
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!\n");
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_(typelib)("%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_(typelib)("%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_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
558           TRACE_(typelib)("  href:0x%08lx\n", prt->reference);
559           prt = prt->next;
560         };
561 }
562
563 static void dump_Variant(VARIANT * pvar)
564 {
565     char szVarType[15];
566     
567     TRACE("(%p)\n", pvar);
568  
569     if (!pvar)  return;
570  
571     ZeroMemory(szVarType, sizeof(szVarType));
572                
573     /* FIXME : we could have better trace here, depending on the VARTYPE
574      * of the variant
575      */
576     switch(V_VT(pvar))
577     {
578         case VT_UI1:
579             sprintf(szVarType, "VT_UI");
580             break;
581             
582         case VT_I2:
583             sprintf(szVarType, "VT_I2");
584             break;
585  
586         case VT_I4:
587             sprintf(szVarType, "VT_I4");
588             break;
589  
590         case VT_R4:
591             sprintf(szVarType, "VT_R4");
592             break;
593  
594         case VT_R8:
595             sprintf(szVarType, "VT_R8");
596             break;
597  
598         case VT_BOOL:
599             sprintf(szVarType, "VT_BOOL");
600             break;
601  
602         case VT_ERROR:
603             sprintf(szVarType, "VT_ERROR");
604             break;
605             
606         case VT_CY:
607             sprintf(szVarType, "VT_CY");
608             break;
609             
610         case VT_DATE:
611             sprintf(szVarType, "VT_DATE");
612             break;
613             
614         case VT_BSTR:
615             sprintf(szVarType, "VT_BSTR");
616             break;
617             
618         case VT_BYREF:
619             case VT_UNKNOWN:
620             sprintf(szVarType, "VT_BYREF");
621             break;
622             
623         case VT_DISPATCH:
624             sprintf(szVarType, "VT_DISPATCH");
625             break;
626             
627         case VT_ARRAY:
628             sprintf(szVarType, "VT_ARRAY");
629             break;
630             
631         case VT_I1:
632             sprintf(szVarType, "VT_I2");
633             break;
634             
635         case VT_UI2:
636             sprintf(szVarType, "VT_UI2");
637             break;
638             
639         case VT_UI4:
640             sprintf(szVarType, "VT_UI4");
641             break;
642             
643         case VT_INT:
644             sprintf(szVarType, "VT_INT");
645             break;
646             
647         case VT_UINT:
648             sprintf(szVarType, "VT_UINT");
649             break;
650     }
651         
652     TRACE("VARTYPE: %s\n", szVarType);
653     
654     switch (V_VT(pvar))
655     {
656         case VT_R4:
657             TRACE("%3.3e\n", V_UNION(pvar, fltVal));
658             break;
659             
660         case VT_R8:
661             TRACE("%3.3e\n", V_UNION(pvar, dblVal));
662             break;
663             
664         default:
665             TRACE("%ld\n", V_UNION(pvar, lVal));
666             break;
667     }       
668
669     if (pvar->vt & VT_BYREF)
670       return dump_Variant(pvar->u.pvarVal);
671 }
672
673 static void dump_DispParms(DISPPARAMS * pdp)
674 {
675     int index = 0;
676     
677     TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
678
679     while (index < pdp->cArgs)
680     {
681         dump_Variant( &pdp->rgvarg[index] );
682         ++index;
683     }
684 }
685
686 static char * typekind_desc[] =
687 {
688         "TKIND_ENUM",
689         "TKIND_RECORD",
690         "TKIND_MODULE",
691         "TKIND_INTERFACE",
692         "TKIND_DISPATCH",
693         "TKIND_COCLASS",
694         "TKIND_ALIAS",
695         "TKIND_UNION",
696         "TKIND_MAX"
697 };
698
699 static void dump_TypeInfo(ITypeInfoImpl * pty)
700 {
701     TRACE("%p ref=%u\n", pty, pty->ref);
702     TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
703     TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
704     TRACE("fct:%u var:%u impl:%u\n",
705       pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
706     TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
707     TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
708     dump_TLBFuncDesc(pty->funclist);
709     dump_TLBVarDesc(pty->varlist);
710     dump_TLBRefType(pty->impltypelist);
711 }
712
713 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
714 {
715     /* VT_LPWSTR is largest type that */
716     /* may appear in type description*/
717     {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
718     {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
719     {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
720     {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
721     {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
722     {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
723     {{0},30},{{0},31}
724 };
725
726 static void TLB_abort()
727 {
728     DebugBreak();
729 }
730 static void * TLB_Alloc(unsigned size)
731 {
732     void * ret;
733     if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
734         /* FIXME */
735         ERR("cannot allocate memory\n");
736     }
737     return ret;
738 }
739
740 static void TLB_Free(void * ptr)
741 {
742     HeapFree(GetProcessHeap(), 0, ptr);
743 }
744 /* read function */
745 DWORD TLB_Read(void *buffer,  DWORD count, TLBContext *pcx, long where )
746 {
747     TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
748        pcx->pos, count, pcx->oStart, pcx->length, where);
749
750     if (where != DO_NOT_SEEK)
751     {
752         where += pcx->oStart;
753         if (where > pcx->length)
754         {
755             /* FIXME */
756             ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
757             TLB_abort();
758         }
759         pcx->pos = where;
760     }
761     if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
762     memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
763     pcx->pos += count;
764     return count;
765 }
766
767 static void TLB_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
768 {
769     TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
770
771     if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
772         memset(pGuid,0, sizeof(GUID));
773         return;
774     }
775     TLB_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
776 }
777
778 BSTR TLB_ReadName( TLBContext *pcx, int offset)
779 {
780     char * name;
781     TLBNameIntro niName;
782     int lengthInChars;
783     WCHAR* pwstring = NULL;
784     BSTR bstrName = NULL;
785
786     TLB_Read(&niName, sizeof(niName), pcx,
787                                 pcx->pTblDir->pNametab.offset+offset);
788     niName.namelen &= 0xFF; /* FIXME: correct ? */
789     name=TLB_Alloc((niName.namelen & 0xff) +1);
790     TLB_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
791     name[niName.namelen & 0xff]='\0';
792
793     lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
794                                         name, -1, NULL, 0);
795
796     /* no invalid characters in string */
797     if (lengthInChars)
798     {
799         pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
800
801         /* don't check for invalid character since this has been done previously */
802         MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
803
804         bstrName = SysAllocStringLen(pwstring, lengthInChars);
805         lengthInChars = SysStringLen(bstrName);
806         HeapFree(GetProcessHeap(), 0, pwstring);
807     }
808
809     TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
810     return bstrName;
811 }
812
813 BSTR TLB_ReadString( TLBContext *pcx, int offset)
814 {
815     char * string;
816     INT16 length;
817     int lengthInChars;
818     BSTR bstr = NULL;
819
820     if(offset<0) return NULL;
821     TLB_Read(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
822     if(length <= 0) return 0;
823     string=TLB_Alloc(length +1);
824     TLB_Read(string, length, pcx, DO_NOT_SEEK);
825     string[length]='\0';
826
827     lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
828                                         string, -1, NULL, 0);
829
830     /* no invalid characters in string */
831     if (lengthInChars)
832     {
833         WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
834
835         /* don't check for invalid character since this has been done previously */
836         MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
837
838         bstr = SysAllocStringLen(pwstring, lengthInChars);
839         lengthInChars = SysStringLen(bstr);
840         HeapFree(GetProcessHeap(), 0, pwstring);
841     }
842
843     TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
844     return bstr;
845 }
846 /*
847  * read a value and fill a VARIANT structure 
848  */
849 static void TLB_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
850 {
851     int size;
852
853     TRACE_(typelib)("\n");
854
855     if(offset <0) { /* data is packed in here */
856         pVar->vt = (offset & 0x7c000000 )>> 26;
857         V_UNION(pVar, iVal) = offset & 0xffff;
858         return;
859     }
860     TLB_Read(&(pVar->vt), sizeof(VARTYPE), pcx, 
861         pcx->pTblDir->pCustData.offset + offset );
862     TRACE_(typelib)("Vartype = %x\n", pVar->vt);
863     switch(pVar->vt){
864         case VT_EMPTY:  /* FIXME: is this right? */
865         case VT_NULL:   /* FIXME: is this right? */
866         case VT_I2  :   /* this should not happen */
867         case VT_I4  :
868         case VT_R4  :
869         case VT_ERROR   : 
870         case VT_BOOL    : 
871         case VT_I1  : 
872         case VT_UI1 : 
873         case VT_UI2 : 
874         case VT_UI4 : 
875         case VT_INT : 
876         case VT_UINT    : 
877         case VT_VOID    : /* FIXME: is this right? */
878         case VT_HRESULT : 
879             size=4; break;
880         case VT_R8  :
881         case VT_CY  :
882         case VT_DATE    : 
883         case VT_I8  : 
884         case VT_UI8 : 
885         case VT_DECIMAL :  /* FIXME: is this right? */
886         case VT_FILETIME :
887             size=8;break;
888             /* pointer types with known behaviour */
889         case VT_BSTR    :{
890             char * ptr;
891             TLB_Read(&size, sizeof(INT), pcx, DO_NOT_SEEK );
892             if(size <= 0) {
893                 FIXME("BSTR length = %d?\n", size);
894             } else {
895                 ptr=TLB_Alloc(size);/* allocate temp buffer */
896                 TLB_Read(ptr, size, pcx, DO_NOT_SEEK); /* read string (ANSI) */
897                 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
898                 /* FIXME: do we need a AtoW conversion here? */
899                 V_UNION(pVar, bstrVal[size])=L'\0';
900                 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
901                 TLB_Free(ptr);
902             }
903         }
904         size=-4; break;
905     /* FIXME: this will not work AT ALL when the variant contains a pointer */
906         case VT_DISPATCH :
907         case VT_VARIANT : 
908         case VT_UNKNOWN : 
909         case VT_PTR : 
910         case VT_SAFEARRAY :
911         case VT_CARRAY  : 
912         case VT_USERDEFINED : 
913         case VT_LPSTR   : 
914         case VT_LPWSTR  : 
915         case VT_BLOB    : 
916         case VT_STREAM  : 
917         case VT_STORAGE : 
918         case VT_STREAMED_OBJECT : 
919         case VT_STORED_OBJECT   : 
920         case VT_BLOB_OBJECT : 
921         case VT_CF  : 
922         case VT_CLSID   : 
923         default: 
924             size=0; 
925             FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
926                 pVar->vt);
927     }
928
929     if(size>0) /* (big|small) endian correct? */
930         TLB_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
931     return;
932 }
933 /*
934  * create a linked list with custom data
935  */
936 static int TLB_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
937 {
938     TLBCDGuid entry;
939     TLBCustData* pNew;
940     int count=0;
941
942     TRACE_(typelib)("\n");
943
944     while(offset >=0){
945         count++;
946         pNew=TLB_Alloc(sizeof(TLBCustData));
947         TLB_Read(&entry, sizeof(entry), pcx, 
948             pcx->pTblDir->pCDGuids.offset+offset);
949         TLB_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
950         TLB_ReadValue(&(pNew->data), entry.DataOffset, pcx);
951         /* add new custom data at head of the list */
952         pNew->next=*ppCustData;
953         *ppCustData=pNew;
954         offset = entry.next;
955     }
956     return count;
957 }
958
959 static void TLB_GetTdesc(TLBContext *pcx, INT type,TYPEDESC * pTd )
960 {
961     if(type <0)
962         pTd->vt=type & VT_TYPEMASK;
963     else
964         *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
965
966     TRACE_(typelib)("vt type = %X\n", pTd->vt);
967 }
968
969 static void 
970 TLB_DoFuncs(TLBContext*     pcx, 
971             int             cFuncs, 
972             int             cVars,
973             int             offset, 
974             TLBFuncDesc**   pptfd)
975 {
976     /* 
977      * member information is stored in a data structure at offset
978      * indicated by the memoffset field of the typeinfo structure
979      * There are several distinctive parts.
980      * the first part starts with a field that holds the total length 
981      * of this (first) part excluding this field. Then follow the records,
982      * for each member there is one record.
983      *
984      * First entry is always the length of the record (excluding this
985      * length word). 
986      * Rest of the record depends on the type of the member. If there is 
987      * a field indicating the member type (function variable intereface etc)
988      * I have not found it yet. At this time we depend on the information
989      * in the type info and the usual order how things are stored.
990      *
991      * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
992      * for each member;
993      * 
994      * Third is a equal sized array with file offsets to the name entry 
995      * of each member.
996      * 
997      * Forth and last (?) part is an array with offsets to the records in the
998      * first part of this file segment.
999      */
1000
1001     int infolen, nameoffset, reclength, nrattributes, i;
1002     int recoffset = offset + sizeof(INT);
1003
1004     char recbuf[512];
1005     TLBFuncRecord * pFuncRec=(TLBFuncRecord *) recbuf;
1006
1007     TRACE_(typelib)("\n");
1008
1009     TLB_Read(&infolen, sizeof(INT), pcx, offset);
1010
1011     for ( i = 0; i < cFuncs ; i++ )
1012     {
1013         *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1014
1015         /* name, eventually add to a hash table */
1016         TLB_Read(&nameoffset, 
1017                  sizeof(INT), 
1018                  pcx, 
1019                  offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1020
1021         (*pptfd)->Name = TLB_ReadName(pcx, nameoffset);
1022
1023         /* read the function information record */
1024         TLB_Read(&reclength, sizeof(INT), pcx, recoffset);
1025         
1026         reclength &= 0x1ff;
1027
1028         TLB_Read(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ; 
1029
1030         /* do the attributes */
1031         nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1032                        / sizeof(int);
1033
1034         if ( nrattributes > 0 )
1035         {
1036             (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1037             
1038             if ( nrattributes > 1 )
1039             {
1040                 (*pptfd)->HelpString = TLB_ReadString(pcx,
1041                                                       pFuncRec->OptAttr[1]) ;
1042
1043                 if ( nrattributes > 2 )
1044                 {
1045                     if ( pFuncRec->FKCCIC & 0x2000 )
1046                     {
1047                        (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1048                     }
1049                     else
1050                     {
1051                         (*pptfd)->Entry = TLB_ReadString(pcx,
1052                                                          pFuncRec->OptAttr[2]);
1053                     }
1054                     if( nrattributes > 5 )
1055                     {
1056                         (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1057
1058                         if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1059                         {
1060                             TLB_CustData(pcx, 
1061                                          pFuncRec->OptAttr[6],
1062                                          &(*pptfd)->pCustData);
1063                         }
1064                     }
1065                 }
1066             }
1067         }
1068
1069         /* fill the FuncDesc Structure */
1070         TLB_Read( & (*pptfd)->funcdesc.memid, 
1071                   sizeof(INT), pcx, 
1072                   offset + infolen + ( i + 1) * sizeof(INT));
1073
1074         (*pptfd)->funcdesc.funckind   =  (pFuncRec->FKCCIC)      & 0x7;
1075         (*pptfd)->funcdesc.invkind    =  (pFuncRec->FKCCIC) >> 3 & 0xF;
1076         (*pptfd)->funcdesc.callconv   =  (pFuncRec->FKCCIC) >> 8 & 0xF;
1077         (*pptfd)->funcdesc.cParams    =   pFuncRec->nrargs  ;
1078         (*pptfd)->funcdesc.cParamsOpt =   pFuncRec->nroargs ;
1079         (*pptfd)->funcdesc.oVft       =   pFuncRec->VtableOffset ;
1080         (*pptfd)->funcdesc.wFuncFlags =   LOWORD(pFuncRec->Flags) ;
1081
1082         TLB_GetTdesc(pcx, 
1083                      pFuncRec->DataType,   
1084                      &(*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1085
1086         /* do the parameters/arguments */
1087         if(pFuncRec->nrargs)
1088         {
1089             int j = 0;
1090             TLBParameterInfo paraminfo;
1091
1092             (*pptfd)->funcdesc.lprgelemdescParam = 
1093                 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1094
1095             (*pptfd)->pParamDesc = 
1096                 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1097
1098             TLB_Read(&paraminfo,
1099                      sizeof(paraminfo), 
1100                      pcx, 
1101                      recoffset + reclength -
1102                         pFuncRec->nrargs * sizeof(TLBParameterInfo));
1103
1104             for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1105             {
1106                 TYPEDESC* lpArgTypeDesc = 0;
1107
1108                 TLB_GetTdesc(pcx, 
1109                              paraminfo.DataType,   
1110                              &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc) ;
1111
1112                 V_UNION(& ((*pptfd)->funcdesc.lprgelemdescParam[j]),
1113                         paramdesc.wParamFlags) = paraminfo.Flags;
1114
1115                 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1116
1117                 /* SEEK value = jump to offset, 
1118                  * from there jump to the end of record,
1119                  * go back by (j-1) arguments
1120                  */
1121                 TLB_Read( &paraminfo ,
1122                           sizeof(TLBParameterInfo), pcx,
1123                           recoffset + reclength - ((pFuncRec->nrargs - j - 1) 
1124                                                    * sizeof(TLBParameterInfo)));
1125                 lpArgTypeDesc = 
1126                     & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1127
1128                 while ( lpArgTypeDesc != NULL )
1129                 {
1130                     switch ( lpArgTypeDesc->vt )
1131                     {
1132                     case VT_PTR:
1133                         lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1134                         break;
1135
1136                     case VT_CARRAY:
1137                         lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1138                         break;
1139
1140                     case VT_USERDEFINED:
1141                         (*pptfd)->pParamDesc[j].pRefType = 
1142                         TLB_Alloc(sizeof(TLBRefType));
1143
1144                         TLB_DoRefType(pcx, 
1145                                       lpArgTypeDesc->u.hreftype, 
1146                                       & ( (*pptfd)->pParamDesc[j].pRefType ));
1147
1148                         lpArgTypeDesc = NULL;
1149                         break;
1150
1151                     default:
1152                         lpArgTypeDesc = NULL;
1153                     }
1154                 }
1155             }
1156
1157
1158             /* parameter is the return value! */
1159             if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1160             {
1161                 TYPEDESC* lpArgTypeDesc;
1162
1163                 (*pptfd)->funcdesc.elemdescFunc = 
1164                 (*pptfd)->funcdesc.lprgelemdescParam[j];
1165
1166                 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1167
1168                 while ( lpArgTypeDesc != NULL )
1169                 {
1170                     switch ( lpArgTypeDesc->vt )
1171                     {
1172                     case VT_PTR:
1173                         lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1174                         break;
1175                     case VT_CARRAY:
1176                         lpArgTypeDesc = 
1177                         & (lpArgTypeDesc->u.lpadesc->tdescElem);
1178
1179                         break;
1180
1181                     case VT_USERDEFINED:
1182                         (*pptfd)->pParamDesc[j].pRefType 
1183                         = TLB_Alloc(sizeof(TLBRefType));
1184
1185                         TLB_DoRefType(pcx, 
1186                                       lpArgTypeDesc->u.hreftype, 
1187                                       &((*pptfd)->pParamDesc[j].pRefType));
1188
1189                         lpArgTypeDesc = NULL;
1190                         break;
1191
1192                     default:
1193                         lpArgTypeDesc = NULL;
1194                     }
1195                 }
1196             }
1197
1198             /* second time around */
1199             for(j=0;j<pFuncRec->nrargs;j++)
1200             {
1201                 /* name */
1202                 (*pptfd)->pParamDesc[j].Name =
1203                     TLB_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1204
1205                 /* default value */
1206                 if ( (PARAMFLAG_FHASDEFAULT & 
1207                       V_UNION(&((*pptfd)->funcdesc.lprgelemdescParam[j]),
1208                               paramdesc.wParamFlags)) &&
1209                      ((pFuncRec->FKCCIC) & 0x1000) )
1210                 {
1211                     INT* pInt = (INT *)((char *)pFuncRec + 
1212                                    reclength - 
1213                                    (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1214
1215                     PARAMDESC* pParamDesc = &V_UNION( 
1216                                   & ((*pptfd)->funcdesc.lprgelemdescParam[j]),
1217                                   paramdesc);
1218
1219                     pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1220                     pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1221                     
1222                     TLB_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue), 
1223                         pInt[j], pcx);
1224                 }
1225                 /* custom info */
1226                 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1227                 {
1228                     TLB_CustData(pcx, 
1229                                  pFuncRec->OptAttr[7+j],
1230                                  &(*pptfd)->pParamDesc[j].pCustData);
1231                 }
1232            }
1233         }
1234         
1235         /* scode is not used: archaic win16 stuff FIXME: right? */
1236         (*pptfd)->funcdesc.cScodes   = 0 ;
1237         (*pptfd)->funcdesc.lprgscode = NULL ;
1238         
1239         pptfd      = & ((*pptfd)->next);
1240         recoffset += reclength;
1241     }
1242 }
1243 static void TLB_DoVars(TLBContext *pcx, int cFuncs, int cVars,
1244                           int offset, TLBVarDesc ** pptvd)
1245 {
1246     int infolen, nameoffset, reclength;
1247     char recbuf[256];
1248     TLBVarRecord * pVarRec=(TLBVarRecord *) recbuf;
1249     int i;
1250     int recoffset;
1251
1252     TRACE_(typelib)("\n");
1253
1254     TLB_Read(&infolen,sizeof(INT), pcx, offset);
1255     TLB_Read(&recoffset,sizeof(INT), pcx, offset + infolen + 
1256         ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1257     recoffset += offset+sizeof(INT);
1258     for(i=0;i<cVars;i++){
1259         *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1260     /* name, eventually add to a hash table */
1261         TLB_Read(&nameoffset, sizeof(INT), pcx, 
1262             offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1263         (*pptvd)->Name=TLB_ReadName(pcx, nameoffset);
1264     /* read the variable information record */
1265         TLB_Read(&reclength, sizeof(INT), pcx, recoffset);
1266         reclength &=0xff;
1267         TLB_Read(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ; 
1268     /* Optional data */
1269         if(reclength >(6*sizeof(INT)) )
1270             (*pptvd)->HelpContext=pVarRec->HelpContext;
1271         if(reclength >(7*sizeof(INT)) )
1272             (*pptvd)->HelpString = TLB_ReadString(pcx, pVarRec->oHelpString) ;
1273         if(reclength >(8*sizeof(INT)) )
1274         if(reclength >(9*sizeof(INT)) )
1275             (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1276     /* fill the VarDesc Structure */
1277         TLB_Read(&(*pptvd)->vardesc.memid, sizeof(INT), pcx, 
1278             offset + infolen + ( i + 1) * sizeof(INT));
1279         (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1280         (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1281         TLB_GetTdesc(pcx, pVarRec->DataType,    
1282             &(*pptvd)->vardesc.elemdescVar.tdesc) ;
1283 /*   (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) fixme?? */
1284         if(pVarRec->VarKind == VAR_CONST ){
1285             V_UNION(&((*pptvd)->vardesc),lpvarValue)=TLB_Alloc(sizeof(VARIANT));
1286             TLB_ReadValue(V_UNION(&((*pptvd)->vardesc),lpvarValue), 
1287                 pVarRec->OffsValue, pcx);
1288         }else
1289             V_UNION(&((*pptvd)->vardesc),oInst)=pVarRec->OffsValue;
1290         pptvd=&((*pptvd)->next);
1291         recoffset += reclength;
1292     }
1293 }
1294 /* fill in data for a hreftype (offset). When the refernced type is contained
1295  * in the typelib, its just an (file) offset in the type info base dir.
1296  * If comes from import, its an offset+1 in the ImpInfo table
1297  * */
1298 static void TLB_DoRefType(TLBContext *pcx, 
1299                           int offset, TLBRefType ** pprtd)
1300 {
1301     int j;
1302
1303     TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1304
1305     if(!HREFTYPE_INTHISFILE( offset)) {
1306         /* external typelib */
1307         TLBImpInfo impinfo;
1308         TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1309
1310         TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1311
1312         TLB_Read(&impinfo, sizeof(impinfo), pcx, 
1313             pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1314         for(j=0;pImpLib;j++){   /* search the known offsets of all import libraries */
1315             if(pImpLib->offset==impinfo.oImpFile) break;
1316             pImpLib=pImpLib->next;
1317         }
1318         if(pImpLib){
1319             (*pprtd)->reference=offset;
1320             (*pprtd)->pImpTLInfo = pImpLib;
1321             TLB_ReadGuid(&(*pprtd)->guid, impinfo.oGuid, pcx);
1322         }else{
1323             ERR("Cannot find a reference\n");
1324             (*pprtd)->reference=-1;
1325             (*pprtd)->pImpTLInfo=(void *)-1;
1326         }
1327     }else{
1328         /* in this typelib */
1329         (*pprtd)->reference=offset;
1330         (*pprtd)->pImpTLInfo=(void *)-2;
1331     }
1332 }
1333
1334 /* process Implemented Interfaces of a com class */
1335 static void TLB_DoImplTypes(TLBContext *pcx, int count,
1336                           int offset, TLBRefType ** pprtd)
1337 {
1338     int i;
1339     TLBRefRecord refrec;
1340
1341     TRACE_(typelib)("\n");
1342
1343     for(i=0;i<count;i++){
1344         if(offset<0) break; /* paranoia */
1345         *pprtd=TLB_Alloc(sizeof(TLBRefType));
1346         TLB_Read(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1347         TLB_DoRefType(pcx, refrec.reftype, pprtd);
1348         (*pprtd)->flags=refrec.flags;
1349         (*pprtd)->ctCustData=
1350             TLB_CustData(pcx, refrec.oCustData, &(*pprtd)->pCustData);
1351         offset=refrec.onext;
1352         pprtd=&((*pprtd)->next);
1353     }
1354 }
1355 /*
1356  * process a typeinfo record
1357  */
1358 ITypeInfoImpl * TLB_DoTypeInfo(
1359     TLBContext *pcx,
1360     int count,
1361     ITypeLibImpl * pLibInfo)
1362 {
1363     TLBTypeInfoBase tiBase;
1364     ITypeInfoImpl *ptiRet;
1365
1366     TRACE_(typelib)("count=%u\n", count);
1367
1368     ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1369     TLB_Read(&tiBase, sizeof(tiBase) ,pcx ,
1370         pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1371 /* this is where we are coming from */
1372     ptiRet->pTypeLib = pLibInfo;
1373     ptiRet->index=count;
1374 /* fill in the typeattr fields */
1375     FIXME("Assign constructor/destrutor memid\n");
1376
1377     TLB_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
1378     ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid;   /* FIXME: correct? */
1379     ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
1380     ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
1381     ptiRet->TypeAttr.lpstrSchema=NULL;              /* reserved */
1382     ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
1383     ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
1384     ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
1385     ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
1386     ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
1387     ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
1388     ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
1389     ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
1390     ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
1391     ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
1392     if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
1393         TLB_GetTdesc(pcx, tiBase.datatype1, 
1394             &ptiRet->TypeAttr.tdescAlias) ;
1395
1396 /*  FIXME: */
1397 /*    IDLDESC  idldescType; *//* never saw this one != zero  */
1398
1399 /* name, eventually add to a hash table */
1400     ptiRet->Name=TLB_ReadName(pcx, tiBase.NameOffset);
1401     TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
1402     /* help info */
1403     ptiRet->DocString=TLB_ReadString(pcx, tiBase.docstringoffs);
1404     ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1405     ptiRet->dwHelpContext=tiBase.helpcontext;
1406 /* note: InfoType's Help file and HelpStringDll come from the containing
1407  * library. Further HelpString and Docstring appear to be the same thing :(
1408  */
1409     /* functions */
1410     if(ptiRet->TypeAttr.cFuncs >0 )
1411         TLB_DoFuncs(pcx, ptiRet->TypeAttr.cFuncs ,ptiRet->TypeAttr.cVars, 
1412         tiBase.memoffset, & ptiRet->funclist);
1413     /* variables */
1414     if(ptiRet->TypeAttr.cVars >0 )
1415         TLB_DoVars(pcx, ptiRet->TypeAttr.cFuncs ,ptiRet->TypeAttr.cVars, 
1416         tiBase.memoffset, & ptiRet->varlist);
1417     if(ptiRet->TypeAttr.cImplTypes >0 ){
1418         switch(ptiRet->TypeAttr.typekind)
1419         {
1420         case TKIND_COCLASS:
1421             TLB_DoImplTypes(pcx, ptiRet->TypeAttr.cImplTypes , 
1422                 tiBase.datatype1, & ptiRet->impltypelist);
1423             break;
1424         case TKIND_DISPATCH:
1425             ptiRet->impltypelist=TLB_Alloc(sizeof(TLBRefType));
1426             
1427             if (tiBase.datatype1 != -1)
1428             {
1429               TLB_DoRefType(pcx, tiBase.datatype1, & ptiRet->impltypelist);
1430             }
1431             else
1432             {
1433               char* szStdOle     = "stdole2.tlb\0";
1434               int   nStdOleLen = strlen(szStdOle);
1435                             
1436               ptiRet->impltypelist->guid             = IID_IDispatch;
1437               ptiRet->impltypelist->reference        = -1;
1438               ptiRet->impltypelist->pImpTLInfo       = TLB_Alloc(sizeof(TLBImpLib));
1439               ptiRet->impltypelist->pImpTLInfo->guid = IID_StdOle;             
1440               ptiRet->impltypelist->pImpTLInfo->name = SysAllocStringLen(NULL, nStdOleLen  + 1);
1441               
1442               MultiByteToWideChar(CP_ACP,
1443                                   MB_PRECOMPOSED,
1444                                   szStdOle,
1445                                   -1,
1446                                   ptiRet->impltypelist->pImpTLInfo->name,
1447                                   SysStringLen(ptiRet->impltypelist->pImpTLInfo->name));
1448                                   
1449               ptiRet->impltypelist->pImpTLInfo->lcid          = 0;
1450               ptiRet->impltypelist->pImpTLInfo->wVersionMajor = 2;
1451               ptiRet->impltypelist->pImpTLInfo->wVersionMinor = 0;
1452             }
1453             break;
1454         default:
1455             ptiRet->impltypelist=TLB_Alloc(sizeof(TLBRefType));
1456             TLB_DoRefType(pcx, tiBase.datatype1, & ptiRet->impltypelist);
1457             break;
1458         }
1459     }
1460     ptiRet->ctCustData=
1461         TLB_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
1462
1463     TRACE_(typelib)("%s guid: %s kind:%s\n",
1464        debugstr_w(ptiRet->Name),
1465        debugstr_guid(&ptiRet->TypeAttr.guid),
1466        typekind_desc[ptiRet->TypeAttr.typekind]);
1467
1468     return ptiRet;
1469 }
1470
1471 /****************************************************************************
1472  *      TLB_ReadTypeLib
1473  *
1474  * find the type of the typelib file and map the typelib resource into
1475  * the memory
1476  */
1477 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
1478 int TLB_ReadTypeLib(LPSTR pszFileName, ITypeLib2 **ppTypeLib)
1479 {
1480     int ret = E_FAIL;
1481     DWORD dwSignature = 0;
1482     HFILE hFile;
1483     int nStrLen = strlen(pszFileName);
1484     int i;
1485
1486     PCHAR pszTypeLibIndex = NULL;
1487     PCHAR pszDllName      = NULL;
1488
1489     TRACE_(typelib)("%s\n", pszFileName);
1490
1491     *ppTypeLib = NULL;
1492
1493     /* is it a DLL? */
1494         for (i=0 ; i < nStrLen ; ++i)
1495         {
1496             pszFileName[i] = tolower(pszFileName[i]);
1497         }
1498     pszTypeLibIndex = strstr(pszFileName, ".dll");
1499
1500     /* find if there's a back-slash after .DLL (good sign of the presence of a typelib index) */
1501     if (pszTypeLibIndex)
1502     {
1503       pszTypeLibIndex = strstr(pszTypeLibIndex, "\\");
1504     }
1505
1506     /* is there any thing after trailing back-slash  ? */
1507     if (pszTypeLibIndex && pszTypeLibIndex < pszFileName + nStrLen)
1508     {
1509       /* yes -> it's a index! store DLL name, without the trailing back-slash */
1510       size_t nMemToAlloc = pszTypeLibIndex - pszFileName;
1511       
1512       pszDllName = HeapAlloc(GetProcessHeap(),
1513                           HEAP_ZERO_MEMORY, 
1514                           nMemToAlloc + 1);
1515                           
1516       strncpy(pszDllName, pszFileName, nMemToAlloc);
1517       
1518       /* move index string pointer pass the backslash */
1519       while (*pszTypeLibIndex == '\\')
1520         ++pszTypeLibIndex;
1521     }
1522     else
1523     {
1524       /* No index, reset variable to 1 */
1525       pszDllName = HeapAlloc(GetProcessHeap(),
1526                           HEAP_ZERO_MEMORY, 
1527                           nStrLen + 1);
1528                           
1529       strncpy(pszDllName, pszFileName, nStrLen);
1530       
1531       pszTypeLibIndex = "1\0";
1532     }
1533
1534     TRACE_(typelib)("File name without index %s\n", pszDllName);
1535     TRACE_(typelib)("Index of typelib %s\n",        pszTypeLibIndex);
1536
1537
1538     /* check the signature of the file */
1539     hFile = CreateFileA( pszDllName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1540     if (INVALID_HANDLE_VALUE != hFile)
1541     {
1542       HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
1543       if (hMapping)
1544       {
1545         LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
1546         if(pBase)
1547         {
1548           /* first try to load as *.tlb */
1549           dwSignature = *((DWORD*) pBase);
1550           if ( dwSignature == MSFT_SIGNATURE)
1551           {
1552                 /* retrieve file size */
1553                 DWORD dwTLBLength = GetFileSize(hFile, NULL);
1554     
1555             *ppTypeLib = ITypeLib2_Constructor(pBase, dwTLBLength);
1556             ITypeLib2_AddRef(*ppTypeLib);
1557           }
1558           UnmapViewOfFile(pBase);
1559         }
1560         CloseHandle(hMapping);
1561       }
1562       CloseHandle(hFile);
1563     }
1564
1565     if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
1566     {
1567       /* find the typelibrary resource*/
1568       HINSTANCE hinstDLL = LoadLibraryExA(pszDllName, 0, DONT_RESOLVE_DLL_REFERENCES|
1569                                           LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
1570       if (hinstDLL)
1571       {
1572         HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(atoi(pszTypeLibIndex)), "TYPELIB");
1573         if (hrsrc)
1574         {
1575           HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
1576           if (hGlobal)
1577           {
1578             LPVOID pBase = LockResource(hGlobal);
1579             DWORD  dwTLBLength = SizeofResource(hinstDLL, hrsrc);
1580             
1581             if (pBase)
1582             {
1583               /* try to load as incore resource */
1584               dwSignature = *((DWORD*) pBase);
1585               if ( dwSignature == MSFT_SIGNATURE)
1586               {
1587                   *ppTypeLib = ITypeLib2_Constructor(pBase, dwTLBLength);
1588                   ITypeLib2_AddRef(*ppTypeLib);
1589               }
1590               else
1591               {
1592                   FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
1593               }
1594             }
1595             FreeResource( hGlobal );
1596           }
1597         }
1598         FreeLibrary(hinstDLL);
1599       }
1600     }
1601
1602     HeapFree(GetProcessHeap(), 0, pszDllName);
1603
1604     if(*ppTypeLib)
1605       ret = S_OK;
1606     else
1607       ERR("Loading of typelib %s failed with error 0x%08lx\n", pszFileName, GetLastError());
1608
1609     return ret;
1610 }
1611
1612 /*================== ITypeLib(2) Methods ===================================*/
1613
1614 /****************************************************************************
1615  *      ITypeLib2_Constructor
1616  *
1617  * loading a typelib from a in-memory image
1618  */
1619 static ITypeLib2* ITypeLib2_Constructor(LPVOID pLib, DWORD dwTLBLength)
1620 {
1621     TLBContext cx;
1622     long lPSegDir;
1623     TLB2Header tlbHeader;
1624     TLBSegDir tlbSegDir;
1625     ITypeLibImpl * pTypeLibImpl;
1626
1627     TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
1628
1629     pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
1630     if (!pTypeLibImpl) return NULL;
1631
1632     ICOM_VTBL(pTypeLibImpl) = &tlbvt;
1633     pTypeLibImpl->ref = 1;
1634
1635     /* get pointer to beginning of typelib data */
1636     cx.pos = 0;
1637     cx.oStart=0;
1638     cx.mapping = pLib;
1639     cx.pLibInfo = pTypeLibImpl;
1640     cx.length = dwTLBLength;
1641     
1642     /* read header */
1643     TLB_Read((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
1644     TRACE("header:\n");
1645     TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
1646     if (memcmp(&tlbHeader.magic1,TLBMAGIC2,4)) {
1647         FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
1648         return NULL;
1649     }
1650     /* there is a small number of information here until the next important
1651      * part:
1652      * the segment directory . Try to calculate the amount of data */
1653     lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
1654
1655     /* now read the segment directory */
1656     TRACE("read segment directory (at %ld)\n",lPSegDir);
1657     TLB_Read((void*)&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);  
1658     cx.pTblDir = &tlbSegDir;
1659
1660     /* just check two entries */
1661     if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
1662     {
1663         ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
1664         HeapFree(GetProcessHeap(),0,pTypeLibImpl);
1665         return NULL;
1666     }
1667
1668     /* now fill our internal data */
1669     /* TLIBATTR fields */
1670     TLB_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
1671     pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;
1672     pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
1673     pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
1674     pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
1675     pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
1676
1677     /* name, eventually add to a hash table */
1678     pTypeLibImpl->Name = TLB_ReadName(&cx, tlbHeader.NameOffset);
1679
1680     /* help info */
1681     pTypeLibImpl->DocString = TLB_ReadString(&cx, tlbHeader.helpstring);
1682     pTypeLibImpl->HelpFile = TLB_ReadString(&cx, tlbHeader.helpfile);
1683
1684     if( tlbHeader.varflags & HELPDLLFLAG)
1685     {
1686             int offset;
1687             TLB_Read(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
1688             pTypeLibImpl->HelpStringDll = TLB_ReadString(&cx, offset);
1689     }
1690
1691     pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
1692
1693     /* custom data */
1694     if(tlbHeader.CustomDataOffset >= 0)
1695     {
1696         pTypeLibImpl->ctCustData = TLB_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
1697     }
1698
1699     /* fill in typedescriptions */
1700     if(tlbSegDir.pTypdescTab.length > 0)
1701     {
1702         int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
1703         INT16 td[4];
1704         pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
1705         TLB_Read(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
1706         for(i=0; i<cTD; )
1707         {
1708             /* FIXME: add several sanity checks here */
1709             pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
1710             if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
1711             {
1712                 /* FIXME: check safearray */
1713                 if(td[3] < 0)
1714                     V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lptdesc)= & stndTypeDesc[td[2]];
1715                 else
1716                     V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lptdesc)= & pTypeLibImpl->pTypeDesc[td[2]/8];
1717             }
1718             else if(td[0] == VT_CARRAY)
1719             {
1720                 /* array descr table here */
1721                 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc) = (void *)((int) td[2]);  /* temp store offset in*/
1722             }                             
1723             else if(td[0] == VT_USERDEFINED)
1724             {
1725                 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),hreftype) = MAKELONG(td[2],td[3]);
1726             }
1727             if(++i<cTD) TLB_Read(td, sizeof(td), &cx, DO_NOT_SEEK);
1728         }
1729
1730         /* second time around to fill the array subscript info */
1731         for(i=0;i<cTD;i++)
1732         {
1733             if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
1734             if(tlbSegDir.pArrayDescriptions.offset>0)
1735             {
1736                 TLB_Read(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc));
1737                 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc) = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
1738
1739                 if(td[1]<0)
1740                     V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->tdescElem.vt = td[0] & VT_TYPEMASK;
1741                 else
1742                     V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->tdescElem = stndTypeDesc[td[0]/8];
1743
1744                 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->cDims = td[2];
1745
1746                 for(j = 0; j<td[2]; j++)
1747                 {
1748                     TLB_Read(& V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->rgbounds[j].cElements, 
1749                         sizeof(INT), &cx, DO_NOT_SEEK);
1750                     TLB_Read(& V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->rgbounds[j].lLbound, 
1751                         sizeof(INT), &cx, DO_NOT_SEEK);
1752                 }
1753             }
1754             else
1755             {
1756                 V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc) = NULL;
1757                 ERR("didn't find array description data\n");
1758             }
1759         }
1760     }
1761
1762     /* imported type libs */
1763     if(tlbSegDir.pImpFiles.offset>0)
1764     {
1765         TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
1766         int oGuid, offset = tlbSegDir.pImpFiles.offset;
1767         UINT16 size;
1768
1769         while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
1770         {
1771             *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
1772             (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
1773             TLB_Read(&oGuid, sizeof(INT), &cx, offset);
1774
1775                         TLB_Read(&(*ppImpLib)->lcid,          sizeof(LCID),   &cx, DO_NOT_SEEK);
1776             TLB_Read(&(*ppImpLib)->wVersionMajor, sizeof(WORD),   &cx, DO_NOT_SEEK);
1777             TLB_Read(&(*ppImpLib)->wVersionMinor, sizeof(WORD),   &cx, DO_NOT_SEEK);
1778             TLB_Read(& size,                      sizeof(UINT16), &cx, DO_NOT_SEEK);
1779
1780             size >>= 2;
1781             (*ppImpLib)->name = TLB_Alloc(size+1);
1782             TLB_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
1783             TLB_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
1784             offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & 0xfffffffc;
1785
1786             ppImpLib = &(*ppImpLib)->next;
1787         }
1788     }
1789
1790     /* type info's */
1791     if(tlbHeader.nrtypeinfos >= 0 )
1792     {
1793         /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
1794         ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
1795         int i;
1796
1797         for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
1798         {
1799             *ppTI = TLB_DoTypeInfo(&cx, i, pTypeLibImpl);
1800
1801             ITypeInfo_AddRef((ITypeInfo*) *ppTI);
1802             ppTI = &((*ppTI)->next);
1803             (pTypeLibImpl->TypeInfoCount)++;
1804         }
1805     }
1806
1807     TRACE("(%p)\n", pTypeLibImpl);
1808     return (ITypeLib2*) pTypeLibImpl;
1809 }
1810
1811 /* ITypeLib::QueryInterface
1812  */
1813 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
1814         ITypeLib2 * iface,
1815         REFIID riid,
1816         VOID **ppvObject)
1817 {
1818     ICOM_THIS( ITypeLibImpl, iface);
1819
1820     TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
1821
1822     *ppvObject=NULL;
1823     if(IsEqualIID(riid, &IID_IUnknown) || 
1824        IsEqualIID(riid,&IID_ITypeLib)||
1825        IsEqualIID(riid,&IID_ITypeLib2))
1826     {
1827         *ppvObject = This;
1828     }
1829
1830     if(*ppvObject)
1831     {
1832         ITypeLib2_AddRef(iface);
1833         TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
1834         return S_OK;
1835     }
1836     TRACE("-- Interface: E_NOINTERFACE\n");
1837     return E_NOINTERFACE;
1838 }
1839
1840 /* ITypeLib::AddRef
1841  */
1842 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
1843 {
1844     ICOM_THIS( ITypeLibImpl, iface);
1845
1846     TRACE("(%p)->ref is %u\n",This, This->ref);
1847
1848     return ++(This->ref);
1849 }
1850
1851 /* ITypeLib::Release
1852  */
1853 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
1854 {
1855     ICOM_THIS( ITypeLibImpl, iface);
1856
1857     --(This->ref);
1858     
1859     TRACE("(%p)->(%u)\n",This, This->ref);
1860
1861     if (!This->ref)
1862     {
1863       /* fixme destroy child objects */
1864
1865       TRACE(" destroying ITypeLib(%p)\n",This);
1866
1867       if (This->Name)
1868       {
1869           SysFreeString(This->Name);
1870           This->Name = NULL;
1871       }
1872
1873       if (This->DocString)
1874       {
1875           SysFreeString(This->DocString);
1876           This->DocString = NULL;
1877       }
1878
1879       if (This->HelpFile)
1880       {
1881           SysFreeString(This->HelpFile);
1882           This->HelpFile = NULL;
1883       }
1884
1885       if (This->HelpStringDll)
1886       {
1887           SysFreeString(This->HelpStringDll);
1888           This->HelpStringDll = NULL;
1889       }
1890     
1891       ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
1892       HeapFree(GetProcessHeap(),0,This);
1893       return 0;
1894     }
1895
1896     return This->ref;
1897 }
1898
1899 /* ITypeLib::GetTypeInfoCount
1900  * 
1901  * Returns the number of type descriptions in the type library
1902  */
1903 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
1904 {
1905     ICOM_THIS( ITypeLibImpl, iface);
1906     TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
1907     return This->TypeInfoCount;
1908 }
1909
1910 /* ITypeLib::GetTypeInfo
1911  *
1912  * retrieves the specified type description in the library.
1913  */
1914 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
1915     ITypeLib2 *iface,
1916     UINT index, 
1917     ITypeInfo **ppTInfo)
1918 {
1919     int i;
1920     
1921     ICOM_THIS( ITypeLibImpl, iface);
1922     ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
1923
1924     TRACE("(%p)->(index=%d) \n", This, index);
1925
1926     if (!ppTInfo) return E_INVALIDARG;
1927     
1928     /* search element n in list */
1929     for(i=0; i < index; i++)
1930     {
1931       pTypeInfo = pTypeInfo->next;
1932       if (!pTypeInfo)
1933       {
1934         TRACE("-- element not found\n");
1935         return TYPE_E_ELEMENTNOTFOUND;
1936       }
1937     }   
1938
1939     *ppTInfo = (ITypeInfo *) pTypeInfo;
1940     
1941     ITypeInfo_AddRef(*ppTInfo);
1942     TRACE("-- found (%p)\n",*ppTInfo);
1943     return S_OK;
1944 }
1945
1946
1947 /* ITypeLibs::GetTypeInfoType
1948  *
1949  * Retrieves the type of a type description.
1950  */
1951 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
1952     ITypeLib2 *iface,
1953     UINT index,
1954     TYPEKIND *pTKind)
1955 {
1956     ICOM_THIS( ITypeLibImpl, iface);
1957     int i;
1958     ITypeInfoImpl *pTInfo = This->pTypeInfo;
1959
1960     TRACE("(%p) index %d \n",This, index);
1961
1962     if(!pTKind) return E_INVALIDARG;
1963     
1964     /* search element n in list */
1965     for(i=0; i < index; i++)
1966     {
1967       if(!pTInfo)
1968       {
1969         TRACE("-- element not found\n");
1970         return TYPE_E_ELEMENTNOTFOUND;
1971       }
1972       pTInfo = pTInfo->next;
1973     }
1974
1975     *pTKind = pTInfo->TypeAttr.typekind;
1976     TRACE("-- found Type (%d)\n", *pTKind);
1977     return S_OK;
1978 }
1979
1980 /* ITypeLib::GetTypeInfoOfGuid
1981  *
1982  * Retrieves the type description that corresponds to the specified GUID.
1983  *
1984  */
1985 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
1986     ITypeLib2 *iface,
1987     REFGUID guid,
1988     ITypeInfo **ppTInfo)
1989 {
1990     ICOM_THIS( ITypeLibImpl, iface);
1991     ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
1992
1993     TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
1994
1995     if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
1996
1997     /* search linked list for guid */
1998     while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
1999     {
2000       pTypeInfo = pTypeInfo->next;
2001
2002       if (!pTypeInfo)
2003       {
2004         /* end of list reached */
2005         TRACE("-- element not found\n");
2006         return TYPE_E_ELEMENTNOTFOUND;
2007       }
2008     }
2009
2010     TRACE("-- found (%p, %s)\n", 
2011           pTypeInfo, 
2012           debugstr_w(pTypeInfo->Name));
2013
2014     *ppTInfo = (ITypeInfo*)pTypeInfo;
2015     ITypeInfo_AddRef(*ppTInfo);
2016     return S_OK;
2017 }
2018
2019 /* ITypeLib::GetLibAttr
2020  *
2021  * Retrieves the structure that contains the library's attributes.
2022  *
2023  */
2024 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
2025         ITypeLib2 *iface, 
2026         LPTLIBATTR *ppTLibAttr)
2027 {
2028     ICOM_THIS( ITypeLibImpl, iface);
2029     TRACE("(%p)\n",This);
2030     /* FIXME: must do a copy here */
2031     *ppTLibAttr=&This->LibAttr;
2032     return S_OK;
2033 }
2034
2035 /* ITypeLib::GetTypeComp
2036  *
2037  * Enables a client compiler to bind to a library's types, variables,
2038  * constants, and global functions.
2039  *
2040  */
2041 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
2042         ITypeLib2 *iface,
2043         ITypeComp **ppTComp)
2044 {
2045     ICOM_THIS( ITypeLibImpl, iface);
2046     FIXME("(%p): stub!\n",This);
2047     return E_NOTIMPL;
2048 }
2049
2050 /* ITypeLib::GetDocumentation
2051  *
2052  * Retrieves the library's documentation string, the complete Help file name
2053  * and path, and the context identifier for the library Help topic in the Help
2054  * file.
2055  *
2056  */
2057 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
2058     ITypeLib2 *iface,
2059     INT index,
2060     BSTR *pBstrName,
2061     BSTR *pBstrDocString,
2062     DWORD *pdwHelpContext, 
2063     BSTR *pBstrHelpFile)
2064 {
2065     ICOM_THIS( ITypeLibImpl, iface);
2066     
2067     HRESULT result = E_INVALIDARG;
2068     
2069     ITypeInfo *pTInfo;
2070
2071    
2072     TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
2073         This, index,
2074         pBstrName, pBstrDocString, 
2075         pdwHelpContext, pBstrHelpFile);
2076    
2077     if(index<0)
2078     { 
2079        /* documentation for the typelib */
2080        if(pBstrName && This->Name)
2081        {
2082            *pBstrName = SysAllocString(This->Name);
2083
2084            if (!(*pBstrName)) return STG_E_INSUFFICIENTMEMORY;
2085        }
2086        if(pBstrDocString && This->DocString)
2087        {
2088            *pBstrDocString = SysAllocString(This->DocString);
2089
2090            if (!(*pBstrDocString)) return STG_E_INSUFFICIENTMEMORY;
2091        }
2092     
2093        if(pdwHelpContext)
2094        {
2095             *pdwHelpContext = This->dwHelpContext;
2096        }
2097        if(pBstrHelpFile && This->HelpFile)
2098        {
2099             *pBstrHelpFile = SysAllocString(This->HelpFile);
2100
2101             if (!(*pBstrHelpFile)) return STG_E_INSUFFICIENTMEMORY;
2102        }
2103
2104        result = S_OK;
2105     }
2106     else 
2107     {
2108         /* for a typeinfo */
2109         result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
2110
2111         if(SUCCEEDED(result))
2112         {
2113             result = ITypeInfo_GetDocumentation(pTInfo, 
2114                                           MEMBERID_NIL,  
2115                                           pBstrName,
2116                                           pBstrDocString, 
2117                                           pdwHelpContext, pBstrHelpFile);
2118             
2119             ITypeInfo_Release(pTInfo);
2120         }
2121     }
2122     return result;
2123 }
2124
2125 /* ITypeLib::IsName
2126  *
2127  * Indicates whether a passed-in string contains the name of a type or member
2128  * described in the library.
2129  *
2130  */
2131 static HRESULT WINAPI ITypeLib2_fnIsName(
2132         ITypeLib2 *iface,
2133         LPOLESTR szNameBuf,
2134         ULONG lHashVal,
2135         BOOL *pfName)
2136 {
2137     ICOM_THIS( ITypeLibImpl, iface);
2138     ITypeInfoImpl *pTInfo;
2139     TLBFuncDesc *pFInfo;
2140     TLBVarDesc *pVInfo;
2141     int i;
2142     UINT nNameBufLen = SysStringLen(szNameBuf);
2143
2144     TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
2145           pfName);
2146
2147     *pfName=TRUE;
2148     for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
2149         if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
2150         for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
2151             if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
2152             for(i=0;i<pFInfo->funcdesc.cParams;i++)
2153                 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
2154                     goto ITypeLib2_fnIsName_exit;
2155         }
2156         for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
2157             if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
2158        
2159     }
2160     *pfName=FALSE;
2161
2162 ITypeLib2_fnIsName_exit:
2163     TRACE("(%p)slow! search for %s: %s found!\n", This,
2164           debugstr_w(szNameBuf), *pfName?"NOT":"");
2165     
2166     return S_OK;
2167 }
2168
2169 /* ITypeLib::FindName
2170  *
2171  * Finds occurrences of a type description in a type library. This may be used
2172  * to quickly verify that a name exists in a type library.
2173  *
2174  */
2175 static HRESULT WINAPI ITypeLib2_fnFindName(
2176         ITypeLib2 *iface,
2177         LPOLESTR szNameBuf,
2178         ULONG lHashVal,
2179         ITypeInfo **ppTInfo,
2180         MEMBERID *rgMemId,
2181         UINT16 *pcFound)
2182 {
2183     ICOM_THIS( ITypeLibImpl, iface);
2184     ITypeInfoImpl *pTInfo;
2185     TLBFuncDesc *pFInfo;
2186     TLBVarDesc *pVInfo;
2187     int i,j = 0;
2188    
2189     UINT nNameBufLen = SysStringLen(szNameBuf);
2190
2191     for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
2192         if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
2193         for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
2194             if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
2195             for(i=0;i<pFInfo->funcdesc.cParams;i++)
2196                 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
2197                     goto ITypeLib2_fnFindName_exit;
2198         }
2199         for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
2200             if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
2201         continue;
2202 ITypeLib2_fnFindName_exit:
2203         ITypeInfo_AddRef((ITypeInfo*)pTInfo);
2204         ppTInfo[j]=(LPTYPEINFO)pTInfo;
2205         j++;
2206     }
2207     TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
2208           This, *pcFound, debugstr_w(szNameBuf), j);
2209
2210     *pcFound=j;
2211     
2212     return S_OK;
2213 }
2214
2215 /* ITypeLib::ReleaseTLibAttr
2216  *
2217  * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
2218  *
2219  */
2220 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
2221         ITypeLib2 *iface,
2222         TLIBATTR *pTLibAttr)
2223 {
2224     ICOM_THIS( ITypeLibImpl, iface);
2225     TRACE("freeing (%p)\n",This);
2226     /* nothing to do */
2227 }
2228
2229 /* ITypeLib2::GetCustData
2230  *
2231  * gets the custom data
2232  */
2233 static HRESULT WINAPI ITypeLib2_fnGetCustData(
2234         ITypeLib2 * iface,
2235         REFGUID guid, 
2236         VARIANT *pVarVal)
2237 {
2238     ICOM_THIS( ITypeLibImpl, iface);
2239     TLBCustData *pCData;
2240
2241     for(pCData=This->pCustData; pCData; pCData = pCData->next)
2242     {
2243       if( IsEqualIID(guid, &pCData->guid)) break;
2244     }
2245     
2246     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
2247
2248     if(pCData)
2249     {
2250         VariantInit( pVarVal);
2251         VariantCopy( pVarVal, &pCData->data);
2252         return S_OK;
2253     }
2254     return E_INVALIDARG;  /* FIXME: correct? */
2255 }
2256
2257 /* ITypeLib2::GetLibStatistics
2258  *
2259  * Returns statistics about a type library that are required for efficient
2260  * sizing of hash tables.
2261  *
2262  */
2263 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
2264         ITypeLib2 * iface, 
2265         ULONG *pcUniqueNames,
2266         ULONG *pcchUniqueNames)
2267 {
2268     ICOM_THIS( ITypeLibImpl, iface);
2269
2270     FIXME("(%p): stub!\n", This);
2271
2272     if(pcUniqueNames) *pcUniqueNames=1;
2273     if(pcchUniqueNames) *pcchUniqueNames=1;
2274     return S_OK;
2275 }
2276
2277 /* ITypeLib2::GetDocumentation2
2278  *
2279  * Retrieves the library's documentation string, the complete Help file name
2280  * and path, the localization context to use, and the context ID for the
2281  * library Help topic in the Help file.
2282  *
2283  */
2284 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
2285         ITypeLib2 * iface, 
2286         INT index,
2287         LCID lcid,
2288         BSTR *pbstrHelpString,
2289         DWORD *pdwHelpStringContext,
2290         BSTR *pbstrHelpStringDll)
2291 {
2292     ICOM_THIS( ITypeLibImpl, iface);
2293     HRESULT result;
2294     ITypeInfo *pTInfo;
2295
2296     FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
2297
2298     /* the help string should be obtained from the helpstringdll,
2299      * using the _DLLGetDocumentation function, based on the supplied
2300      * lcid. Nice to do sometime...
2301      */
2302     if(index<0)
2303     {
2304       /* documentation for the typelib */
2305       if(pbstrHelpString)
2306         *pbstrHelpString=SysAllocString(This->DocString);
2307       if(pdwHelpStringContext)
2308         *pdwHelpStringContext=This->dwHelpContext;
2309       if(pbstrHelpStringDll)
2310         *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
2311
2312       result = S_OK;
2313     }
2314     else
2315     {
2316       /* for a typeinfo */
2317       result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
2318       
2319       if(SUCCEEDED(result))
2320       { 
2321         ITypeInfo2 * pTInfo2;
2322         result = ITypeInfo_QueryInterface(pTInfo, 
2323                                           &IID_ITypeInfo2, 
2324                                           (LPVOID*) &pTInfo2);
2325
2326         if(SUCCEEDED(result))
2327         {
2328           result = ITypeInfo2_GetDocumentation2(pTInfo2, 
2329                                            MEMBERID_NIL, 
2330                                            lcid,
2331                                            pbstrHelpString, 
2332                                            pdwHelpStringContext, 
2333                                            pbstrHelpStringDll);
2334   
2335           ITypeInfo2_Release(pTInfo2);
2336         }
2337             
2338         ITypeInfo_Release(pTInfo);
2339       }
2340     }
2341     return result;
2342 }
2343
2344 /* ITypeLib2::GetAllCustData
2345  *
2346  * Gets all custom data items for the library. 
2347  *
2348  */
2349 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
2350         ITypeLib2 * iface,
2351         CUSTDATA *pCustData)
2352 {
2353     ICOM_THIS( ITypeLibImpl, iface);
2354     TLBCustData *pCData;
2355     int i;
2356     TRACE("(%p) returning %d items\n", This, This->ctCustData); 
2357     pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
2358     if(pCustData->prgCustData ){
2359         pCustData->cCustData=This->ctCustData;
2360         for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
2361             pCustData->prgCustData[i].guid=pCData->guid;
2362             VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
2363         }
2364     }else{
2365         ERR(" OUT OF MEMORY! \n");
2366         return E_OUTOFMEMORY;
2367     }
2368     return S_OK;
2369 }
2370
2371 static ICOM_VTABLE(ITypeLib2) tlbvt = {
2372     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2373     ITypeLib2_fnQueryInterface,
2374     ITypeLib2_fnAddRef,
2375     ITypeLib2_fnRelease,
2376     ITypeLib2_fnGetTypeInfoCount,
2377     ITypeLib2_fnGetTypeInfo,
2378     ITypeLib2_fnGetTypeInfoType,
2379     ITypeLib2_fnGetTypeInfoOfGuid,
2380     ITypeLib2_fnGetLibAttr,
2381     ITypeLib2_fnGetTypeComp,
2382     ITypeLib2_fnGetDocumentation,
2383     ITypeLib2_fnIsName,
2384     ITypeLib2_fnFindName,
2385     ITypeLib2_fnReleaseTLibAttr,
2386
2387     ITypeLib2_fnGetCustData,
2388     ITypeLib2_fnGetLibStatistics,
2389     ITypeLib2_fnGetDocumentation2,
2390     ITypeLib2_fnGetAllCustData
2391  };
2392
2393 /*================== ITypeInfo(2) Methods ===================================*/
2394 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
2395 {
2396     ITypeInfoImpl * pTypeInfoImpl;
2397
2398     pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
2399     if (pTypeInfoImpl)
2400     {
2401       ICOM_VTBL(pTypeInfoImpl) = &tinfvt;
2402       pTypeInfoImpl->ref=1;
2403     }
2404     TRACE("(%p)\n", pTypeInfoImpl);
2405     return (ITypeInfo2*) pTypeInfoImpl;
2406 }
2407
2408 /* ITypeInfo::QueryInterface
2409  */
2410 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
2411         ITypeInfo2 *iface,
2412         REFIID riid,
2413         VOID **ppvObject)
2414 {
2415     ICOM_THIS( ITypeLibImpl, iface);
2416
2417     TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
2418
2419     *ppvObject=NULL;
2420     if(IsEqualIID(riid, &IID_IUnknown) || 
2421             IsEqualIID(riid,&IID_ITypeInfo)||
2422             IsEqualIID(riid,&IID_ITypeInfo2))
2423         *ppvObject = This;
2424
2425     if(*ppvObject){
2426         ITypeInfo_AddRef(iface);
2427         TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
2428         return S_OK;
2429     }
2430     TRACE("-- Interface: E_NOINTERFACE\n");
2431     return E_NOINTERFACE;
2432 }
2433
2434 /* ITypeInfo::AddRef
2435  */
2436 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
2437 {
2438     ICOM_THIS( ITypeInfoImpl, iface);
2439
2440     ++(This->ref);
2441
2442     TRACE("(%p)->ref is %u\n",This, This->ref);
2443     return This->ref;
2444 }
2445
2446 /* ITypeInfo::Release
2447  */
2448 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
2449 {
2450     ICOM_THIS( ITypeInfoImpl, iface);
2451
2452     --(This->ref);
2453     
2454     TRACE("(%p)->(%u)\n",This, This->ref);
2455
2456     if (!This->ref)
2457     {
2458       FIXME("destroy child objects\n");
2459
2460       TRACE("destroying ITypeInfo(%p)\n",This); 
2461       if (This->Name)
2462       {
2463           SysFreeString(This->Name);
2464           This->Name = 0;
2465       }
2466       
2467       if (This->DocString)
2468       {
2469           SysFreeString(This->DocString);
2470           This->DocString = 0;
2471       }
2472
2473       if (This->next)
2474       {
2475         ITypeInfo_Release((ITypeInfo*)This->next);
2476       }
2477
2478       HeapFree(GetProcessHeap(),0,This);
2479       return 0;
2480     }
2481     return This->ref;
2482 }
2483
2484 /* ITypeInfo::GetTypeAttr
2485  *
2486  * Retrieves a TYPEATTR structure that contains the attributes of the type
2487  * description.
2488  *
2489  */
2490 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
2491         LPTYPEATTR  *ppTypeAttr)
2492 {
2493     ICOM_THIS( ITypeInfoImpl, iface);
2494     TRACE("(%p)\n",This);
2495     /* FIXME: must do a copy here */
2496     *ppTypeAttr=&This->TypeAttr;
2497     return S_OK;
2498 }
2499
2500 /* ITypeInfo::GetTypeComp
2501  *
2502  * Retrieves the ITypeComp interface for the type description, which enables a
2503  * client compiler to bind to the type description's members.
2504  *
2505  */
2506 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
2507         ITypeComp  * *ppTComp)
2508 {
2509     ICOM_THIS( ITypeInfoImpl, iface);
2510     FIXME("(%p) stub!\n", This);
2511     return S_OK;
2512 }
2513
2514 /* ITypeInfo::GetFuncDesc
2515  *
2516  * Retrieves the FUNCDESC structure that contains information about a
2517  * specified function.
2518  *
2519  */
2520 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
2521         LPFUNCDESC  *ppFuncDesc)
2522 {
2523     ICOM_THIS( ITypeInfoImpl, iface);
2524     int i;
2525     TLBFuncDesc * pFDesc; 
2526     TRACE("(%p) index %d\n", This, index);
2527     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
2528         ;
2529     if(pFDesc){
2530         /* FIXME: must do a copy here */
2531         *ppFuncDesc=&pFDesc->funcdesc;
2532         return S_OK;
2533     }
2534     return E_INVALIDARG;
2535 }
2536
2537 /* ITypeInfo::GetVarDesc
2538  *
2539  * Retrieves a VARDESC structure that describes the specified variable. 
2540  *
2541  */
2542 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
2543         LPVARDESC  *ppVarDesc)
2544 {
2545     ICOM_THIS( ITypeInfoImpl, iface);
2546     int i;
2547     TLBVarDesc * pVDesc; 
2548     TRACE("(%p) index %d\n", This, index);
2549     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
2550         ;
2551     if(pVDesc){
2552         /* FIXME: must do a copy here */
2553         *ppVarDesc=&pVDesc->vardesc;
2554         return S_OK;
2555     }
2556     return E_INVALIDARG;
2557 }
2558
2559 /* ITypeInfo_GetNames
2560  *
2561  * Retrieves the variable with the specified member ID (or the name of the
2562  * property or method and its parameters) that correspond to the specified
2563  * function ID.
2564  */
2565 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
2566         BSTR  *rgBstrNames, UINT cMaxNames, UINT  *pcNames)
2567 {
2568     ICOM_THIS( ITypeInfoImpl, iface);
2569     TLBFuncDesc * pFDesc; 
2570     TLBVarDesc * pVDesc; 
2571     int i;
2572     TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
2573     for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
2574     if(pFDesc)
2575     {
2576       /* function found, now return function and parameter names */
2577       for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
2578       {
2579         if(!i)
2580                   *rgBstrNames=SysAllocString(pFDesc->Name);
2581         else
2582           rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
2583       }
2584       *pcNames=i;
2585     }
2586     else
2587     {
2588       for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
2589       if(pVDesc)
2590       {
2591         *rgBstrNames=SysAllocString(pVDesc->Name);
2592         *pcNames=1;
2593       }
2594       else
2595       {
2596         if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
2597         {
2598           /* recursive search */
2599           ITypeInfo *pTInfo;
2600           HRESULT result;
2601           result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->reference, &pTInfo);
2602           if(SUCCEEDED(result))
2603           {
2604             result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
2605             ITypeInfo_Release(pTInfo);
2606             return result;
2607           }
2608           WARN("Could not search inherited interface!\n");
2609         }
2610         else
2611         {
2612           WARN("no names found\n");
2613         }
2614         *pcNames=0;
2615         return TYPE_E_ELEMENTNOTFOUND;
2616       }
2617     }
2618     return S_OK;
2619 }
2620
2621
2622 /* ITypeInfo::GetRefTypeOfImplType
2623  *
2624  * If a type description describes a COM class, it retrieves the type
2625  * description of the implemented interface types. For an interface,
2626  * GetRefTypeOfImplType returns the type information for inherited interfaces,
2627  * if any exist.
2628  *
2629  */
2630 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
2631         ITypeInfo2 *iface,
2632         UINT index,
2633         HREFTYPE  *pRefType)
2634 {
2635     ICOM_THIS( ITypeInfoImpl, iface);
2636     int(i);
2637     TLBRefType *pIref = This->impltypelist;
2638
2639     TRACE("(%p) index %d\n", This, index);
2640     dump_TypeInfo(This);
2641
2642     if(index==(UINT)-1)
2643     {
2644       /* only valid on dual interfaces;
2645          retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
2646       */
2647       if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
2648       
2649       if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
2650           This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
2651       {
2652         *pRefType = -1;
2653       }
2654       else
2655       {
2656         if (!pIref) return TYPE_E_ELEMENTNOTFOUND;
2657         *pRefType = pIref->reference;
2658       }
2659     }
2660     else
2661     {
2662       /* get element n from linked list */
2663       for(i=0; pIref && i<index; i++)
2664       {
2665         pIref = pIref->next;
2666       }
2667       
2668       if (!pIref) return TYPE_E_ELEMENTNOTFOUND;
2669       
2670       *pRefType = pIref->reference;
2671       
2672       TRACE("-- 0x%08lx %s\n",pIref->reference, debugstr_guid(&pIref->guid) );
2673     }
2674     
2675     return S_OK;
2676    
2677 }
2678
2679 /* ITypeInfo::GetImplTypeFlags
2680  * 
2681  * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface 
2682  * or base interface in a type description.
2683  */
2684 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
2685         UINT index, INT  *pImplTypeFlags)
2686 {
2687     ICOM_THIS( ITypeInfoImpl, iface);
2688     int(i);
2689     TLBRefType *pIref;
2690     TRACE("(%p) index %d\n", This, index);
2691     for(i=0, pIref=This->impltypelist; i<index && pIref; i++, pIref=pIref->next)
2692         ;
2693     if(i==index && pIref){
2694         *pImplTypeFlags=pIref->flags;
2695         return S_OK;
2696     }
2697     *pImplTypeFlags=0;
2698     return TYPE_E_ELEMENTNOTFOUND;
2699 }
2700
2701 /* GetIDsOfNames
2702  * Maps between member names and member IDs, and parameter names and
2703  * parameter IDs.
2704  */
2705 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
2706         LPOLESTR  *rgszNames, UINT cNames, MEMBERID  *pMemId)
2707 {
2708     ICOM_THIS( ITypeInfoImpl, iface);
2709     TLBFuncDesc * pFDesc; 
2710     TLBVarDesc * pVDesc; 
2711     HRESULT ret=S_OK;
2712         UINT nNameLen = SysStringLen(*rgszNames);
2713         
2714     TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
2715             cNames);
2716     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
2717         int i, j;
2718         if( !memcmp(*rgszNames, pFDesc->Name, nNameLen)) {
2719             if(cNames) *pMemId=pFDesc->funcdesc.memid;
2720             for(i=1; i < cNames; i++){
2721                                 UINT nParamLen = SysStringLen(rgszNames[i]);
2722                 for(j=0; j<pFDesc->funcdesc.cParams; j++)
2723                     if(memcmp(rgszNames[i],pFDesc->pParamDesc[j].Name, nParamLen))
2724                             break;
2725                 if( j<pFDesc->funcdesc.cParams)
2726                     pMemId[i]=j;
2727                 else
2728                    ret=DISP_E_UNKNOWNNAME;
2729             };
2730             return ret;
2731         }
2732     }   
2733     for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
2734         if( !memcmp(*rgszNames, pVDesc->Name, nNameLen)) {
2735             if(cNames) *pMemId=pVDesc->vardesc.memid;
2736             return ret;
2737         }
2738     }
2739     /* not found, see if this is and interface with an inheritance */       
2740     if(This->TypeAttr.typekind==TKIND_INTERFACE && 
2741             This->TypeAttr.cImplTypes ){
2742         /* recursive search */
2743         ITypeInfo *pTInfo;
2744         ret=ITypeInfo_GetRefTypeInfo(iface, 
2745                 This->impltypelist->reference, &pTInfo);
2746         if(SUCCEEDED(ret)){
2747             ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
2748             ITypeInfo_Release(pTInfo);
2749             return ret;
2750         }
2751         WARN("Could not search inherited interface!\n");
2752     } else
2753         WARN("no names found\n");
2754     return DISP_E_UNKNOWNNAME;
2755 }
2756
2757 /* ITypeInfo::Invoke
2758  * 
2759  * Invokes a method, or accesses a property of an object, that implements the
2760  * interface described by the type description.
2761  */
2762 static HRESULT WINAPI ITypeInfo_fnInvoke(
2763         ITypeInfo2 *iface,
2764         VOID  *pIUnk,
2765         MEMBERID memid,
2766         UINT16 dwFlags,
2767         DISPPARAMS  *pDispParams,
2768         VARIANT  *pVarResult,
2769         EXCEPINFO  *pExcepInfo,
2770         UINT  *pArgErr)
2771 {
2772     ICOM_THIS( ITypeInfoImpl, iface);
2773     FIXME("(%p)(%p,id=0x%08lx,0x%08x,%p,%p,%p,%p) stub!\n",
2774       This, pIUnk, memid, dwFlags, pDispParams, pVarResult, pExcepInfo, pArgErr );
2775     dump_DispParms(pDispParams);
2776     return S_OK;
2777 }
2778
2779 /* ITypeInfo::GetDocumentation
2780  * 
2781  * Retrieves the documentation string, the complete Help file name and path,
2782  * and the context ID for the Help topic for a specified type description.
2783  */
2784 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
2785         MEMBERID memid, BSTR  *pBstrName, BSTR  *pBstrDocString,
2786         DWORD  *pdwHelpContext, BSTR  *pBstrHelpFile)
2787 {
2788     ICOM_THIS( ITypeInfoImpl, iface);
2789     TLBFuncDesc * pFDesc; 
2790     TLBVarDesc * pVDesc; 
2791     TRACE("(%p) memid %ld Name(%p) DocString(%p)"
2792           " HelpContext(%p) HelpFile(%p)\n",
2793         This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
2794     if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
2795         if(pBstrName)
2796             *pBstrName=SysAllocString(This->Name);
2797         if(pBstrDocString)
2798             *pBstrDocString=SysAllocString(This->DocString);
2799         if(pdwHelpContext)
2800             *pdwHelpContext=This->dwHelpContext;
2801         if(pBstrHelpFile)
2802             *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
2803         return S_OK;
2804     }else {/* for a member */
2805     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
2806         if(pFDesc->funcdesc.memid==memid){
2807             return S_OK;
2808         }
2809     for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
2810         if(pVDesc->vardesc.memid==memid){
2811             return S_OK;
2812         }
2813     }
2814     return TYPE_E_ELEMENTNOTFOUND;
2815 }
2816
2817 /*  ITypeInfo::GetDllEntry
2818  * 
2819  * Retrieves a description or specification of an entry point for a function
2820  * in a DLL.
2821  */
2822 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
2823         INVOKEKIND invKind, BSTR  *pBstrDllName, BSTR  *pBstrName,
2824         WORD  *pwOrdinal)
2825 {
2826     ICOM_THIS( ITypeInfoImpl, iface);
2827     FIXME("(%p) stub!\n", This);
2828     return E_FAIL;
2829 }
2830
2831 /* ITypeInfo::GetRefTypeInfo
2832  * 
2833  * If a type description references other type descriptions, it retrieves
2834  * the referenced type descriptions.
2835  */
2836 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
2837         ITypeInfo2 *iface,
2838         HREFTYPE hRefType,
2839         ITypeInfo  **ppTInfo)
2840 {
2841     ICOM_THIS( ITypeInfoImpl, iface);
2842     HRESULT result = E_FAIL;
2843
2844     if(HREFTYPE_INTHISFILE(hRefType))
2845     {
2846       ITypeLib *pTLib;
2847       int Index;
2848       result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
2849       if(SUCCEEDED( result ))
2850       {
2851         result=ITypeLib2_GetTypeInfo(pTLib, HREFTYPE_INDEX(hRefType), ppTInfo);
2852         ITypeLib2_Release(pTLib );
2853       }
2854     }
2855         else if (hRefType == -1 && 
2856              (((ITypeInfoImpl*) This)->TypeAttr.typekind   == TKIND_DISPATCH) &&
2857              (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags &  TYPEFLAG_FDUAL))
2858     {
2859           /* when we meet a DUAL dispinterface, we must create the interface 
2860           * version of it.
2861           */
2862           ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
2863
2864                 
2865           /* the interface version contains the same information as the dispinterface
2866            * copy the contents of the structs.
2867            */
2868           *pTypeInfoImpl = *This;
2869           pTypeInfoImpl->ref = 1;
2870                 
2871           /* change the type to interface */
2872           pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
2873                 
2874       *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
2875
2876           ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
2877
2878       result = S_OK;
2879         }
2880     else
2881     {
2882       /* imported type lib */
2883       TLBRefType   *pRefType     = NULL;
2884       
2885       /* search in implemented types */
2886       for( pRefType = This->impltypelist; 
2887            pRefType && (pRefType->reference != hRefType);
2888            pRefType = pRefType->next);
2889       
2890       if(!pRefType)
2891       {                       
2892         TYPEATTR*       pMyTypeAttr  = &This->TypeAttr;
2893         unsigned short  cFuncs       = pMyTypeAttr->cFuncs;
2894         unsigned short  cVars        = pMyTypeAttr->cVars;
2895         
2896         /* search in arguments */      
2897         if (cFuncs > 0)
2898         {
2899           unsigned short  cFuncIndex   = 0;
2900   
2901           TLBFuncDesc*    pCurrFunc    = This->funclist;
2902           
2903           for (cFuncIndex = 0; !pRefType && cFuncIndex < cFuncs ; ++cFuncIndex)
2904           {
2905             FUNCDESC*  pCurrFuncDesc = &pCurrFunc->funcdesc;
2906             
2907             short      cParams       = pCurrFuncDesc->cParams;
2908             short      cParamIndex   = 0;
2909               
2910             for (cParamIndex = 0 ; 
2911                  !pRefType && cParamIndex < cParams ; 
2912                  ++cParamIndex)
2913             {
2914               TLBParDesc* pCurrParamDesc = &(pCurrFunc->pParamDesc[cParamIndex]);
2915              
2916               if ( pCurrParamDesc->pRefType && pCurrParamDesc->pRefType->reference == hRefType)
2917               {
2918                 pRefType = pCurrParamDesc->pRefType;
2919                 break; /* also break from outer loop since pRefType != 0 */
2920               }
2921             }
2922             
2923             pCurrFunc = pCurrFunc->next;
2924           }
2925         }
2926         /* search in variables */
2927         else if (cVars > 0)
2928         {
2929           FIXME("search hreftype in variables, if any\n");
2930           result = E_INVALIDARG; // FIXME : correct?
2931         }
2932       }
2933       
2934       /* href-referenced typeinfo found! */
2935       if (pRefType || hRefType == -1)
2936       {
2937         ITypeLibImpl *pTypeLib = pRefType->pImpTLInfo->pImpTypeLib;
2938         
2939         if(pTypeLib) 
2940         {
2941           TRACE("typeinfo in imported typelib that is already loaded\n");
2942                   
2943           result = ITypeLib2_GetTypeInfoOfGuid((LPTYPELIB)pTypeLib, 
2944                                            &pRefType->guid, 
2945                                            ppTInfo);
2946         }
2947         else
2948         {
2949           result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
2950                       pRefType->pImpTLInfo->wVersionMajor,
2951                       pRefType->pImpTLInfo->wVersionMinor,
2952                       pRefType->pImpTLInfo->lcid,
2953                       (LPTYPELIB *)&pTypeLib);
2954           
2955           if(!SUCCEEDED(result))
2956                   {
2957             BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
2958             TRACE("typeinfo in imported typelib that isn't already loaded\n");
2959             result=LoadTypeLib(libnam, (LPTYPELIB *)&pTypeLib);
2960             SysFreeString(libnam);
2961           } 
2962           if(SUCCEEDED(result))
2963           {
2964             result=ITypeLib2_GetTypeInfoOfGuid((LPTYPELIB)pTypeLib, &pRefType->guid, ppTInfo);
2965             pRefType->pImpTLInfo->pImpTypeLib = pTypeLib;
2966                         ITypeLib2_AddRef((ITypeLib*) pTypeLib);
2967           }        
2968         }
2969       }
2970     }
2971
2972     TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
2973           SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
2974     return result;
2975 }
2976
2977 /* ITypeInfo::AddressOfMember
2978  * 
2979  * Retrieves the addresses of static functions or variables, such as those
2980  * defined in a DLL.
2981  */
2982 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
2983         MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
2984 {
2985     ICOM_THIS( ITypeInfoImpl, iface);
2986     FIXME("(%p) stub!\n", This);
2987     return S_OK;
2988 }
2989
2990 /* ITypeInfo::CreateInstance
2991  * 
2992  * Creates a new instance of a type that describes a component object class 
2993  * (coclass).
2994  */
2995 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface, 
2996         IUnknown *pUnk, REFIID riid, VOID  **ppvObj) 
2997 {
2998     ICOM_THIS( ITypeInfoImpl, iface);
2999     FIXME("(%p) stub!\n", This);
3000     return S_OK;
3001 }
3002
3003 /* ITypeInfo::GetMops
3004  *
3005  * Retrieves marshaling information.
3006  */
3007 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
3008                                 BSTR  *pBstrMops)
3009 {
3010     ICOM_THIS( ITypeInfoImpl, iface);
3011     FIXME("(%p) stub!\n", This);
3012     return S_OK;
3013 }
3014
3015 /* ITypeInfo::GetContainingTypeLib
3016  * 
3017  * Retrieves the containing type library and the index of the type description
3018  * within that type library.
3019  */
3020 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
3021         ITypeLib  * *ppTLib, UINT  *pIndex)
3022 {
3023     ICOM_THIS( ITypeInfoImpl, iface);
3024     if (!pIndex)
3025         return E_INVALIDARG;
3026     *ppTLib=(LPTYPELIB )(This->pTypeLib);
3027     *pIndex=This->index;
3028     ITypeLib2_AddRef(*ppTLib);
3029     TRACE("(%p) returns (%p) index %d!\n", This, *ppTLib, *pIndex);
3030     return S_OK;
3031 }
3032
3033 /* ITypeInfo::ReleaseTypeAttr
3034  *
3035  * Releases a TYPEATTR previously returned by GetTypeAttr.
3036  *
3037  */
3038 static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
3039         TYPEATTR* pTypeAttr)
3040 {
3041     ICOM_THIS( ITypeInfoImpl, iface);
3042     TRACE("(%p)->(%p)\n", This, pTypeAttr);
3043     return S_OK;
3044 }
3045
3046 /* ITypeInfo::ReleaseFuncDesc
3047  *
3048  * Releases a FUNCDESC previously returned by GetFuncDesc. *
3049  */
3050 static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc(
3051         ITypeInfo2 *iface,
3052         FUNCDESC *pFuncDesc)
3053 {
3054     ICOM_THIS( ITypeInfoImpl, iface);
3055     TRACE("(%p)->(%p)\n", This, pFuncDesc);
3056     return S_OK;
3057 }
3058
3059 /* ITypeInfo::ReleaseVarDesc
3060  *
3061  * Releases a VARDESC previously returned by GetVarDesc.
3062  */
3063 static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
3064         VARDESC *pVarDesc)
3065 {
3066     ICOM_THIS( ITypeInfoImpl, iface);
3067     TRACE("(%p)->(%p)\n", This, pVarDesc);
3068     return S_OK;
3069 }
3070
3071 /* ITypeInfo2::GetTypeKind
3072  *
3073  * Returns the TYPEKIND enumeration quickly, without doing any allocations.
3074  *
3075  */
3076 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
3077     TYPEKIND *pTypeKind)
3078 {
3079     ICOM_THIS( ITypeInfoImpl, iface);
3080     *pTypeKind=This->TypeAttr.typekind;
3081     TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
3082     return S_OK;
3083 }
3084
3085 /* ITypeInfo2::GetTypeFlags
3086  *
3087  * Returns the type flags without any allocations. This returns a DWORD type
3088  * flag, which expands the type flags without growing the TYPEATTR (type
3089  * attribute). 
3090  *
3091  */
3092 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 * iface,
3093     UINT *pTypeFlags)
3094 {
3095     ICOM_THIS( ITypeInfoImpl, iface);
3096     *pTypeFlags=This->TypeAttr.wTypeFlags;
3097     TRACE("(%p) flags 0x%04x\n", This,*pTypeFlags);
3098      return S_OK;
3099 }
3100
3101 /* ITypeInfo2::GetFuncIndexOfMemId
3102  * Binds to a specific member based on a known DISPID, where the member name
3103  * is not known (for example, when binding to a default member).
3104  *
3105  */
3106 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
3107     MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
3108 {
3109     ICOM_THIS( ITypeInfoImpl, iface);
3110     TLBFuncDesc *pFuncInfo;
3111     int i;
3112     HRESULT result;
3113     /* FIXME: should check for invKind??? */
3114     for(i=0, pFuncInfo=This->funclist;pFuncInfo && 
3115             memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
3116     if(pFuncInfo){
3117         *pFuncIndex=i;
3118         result= S_OK;
3119     }else{
3120         *pFuncIndex=0;
3121         result=E_INVALIDARG;
3122     }
3123     TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
3124           memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
3125     return result;
3126 }
3127
3128 /* TypeInfo2::GetVarIndexOfMemId
3129  *
3130  * Binds to a specific member based on a known DISPID, where the member name
3131  * is not known (for example, when binding to a default member). 
3132  *
3133  */
3134 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
3135     MEMBERID memid, UINT *pVarIndex)
3136 {
3137     ICOM_THIS( ITypeInfoImpl, iface);
3138     TLBVarDesc *pVarInfo;
3139     int i;
3140     HRESULT result;
3141     for(i=0, pVarInfo=This->varlist; pVarInfo && 
3142             memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
3143         ;
3144     if(pVarInfo){
3145         *pVarIndex=i;
3146         result= S_OK;
3147     }else{
3148         *pVarIndex=0;
3149         result=E_INVALIDARG;
3150     }
3151     TRACE("(%p) memid 0x%08lx -> %s\n", This,
3152           memid, SUCCEEDED(result)? "SUCCES":"FAILED");
3153     return result;
3154 }
3155
3156 /* ITypeInfo2::GetCustData
3157  *
3158  * Gets the custom data
3159  */
3160 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
3161         ITypeInfo2 * iface,
3162         REFGUID guid,
3163         VARIANT *pVarVal)
3164 {
3165     ICOM_THIS( ITypeInfoImpl, iface);
3166     TLBCustData *pCData;
3167
3168     for(pCData=This->pCustData; pCData; pCData = pCData->next)
3169         if( IsEqualIID(guid, &pCData->guid)) break;
3170
3171     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3172
3173     if(pCData)
3174     {
3175         VariantInit( pVarVal);
3176         VariantCopy( pVarVal, &pCData->data);
3177         return S_OK;
3178     }
3179     return E_INVALIDARG;  /* FIXME: correct? */
3180 }
3181
3182 /* ITypeInfo2::GetFuncCustData
3183  *
3184  * Gets the custom data
3185  */
3186 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
3187         ITypeInfo2 * iface,
3188         UINT index,
3189         REFGUID guid,
3190         VARIANT *pVarVal)
3191 {
3192     ICOM_THIS( ITypeInfoImpl, iface);
3193     TLBCustData *pCData=NULL;
3194     TLBFuncDesc * pFDesc; 
3195     int i;
3196     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
3197             pFDesc=pFDesc->next);
3198
3199     if(pFDesc)
3200         for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
3201             if( IsEqualIID(guid, &pCData->guid)) break;
3202
3203     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3204
3205     if(pCData){
3206         VariantInit( pVarVal);
3207         VariantCopy( pVarVal, &pCData->data);
3208         return S_OK;
3209     }
3210     return E_INVALIDARG;  /* FIXME: correct? */
3211 }
3212
3213 /* ITypeInfo2::GetParamCustData
3214  *
3215  * Gets the custom data
3216  */
3217 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
3218         ITypeInfo2 * iface,
3219         UINT indexFunc,
3220         UINT indexParam,
3221         REFGUID guid,
3222         VARIANT *pVarVal)
3223 {   
3224     ICOM_THIS( ITypeInfoImpl, iface);
3225     TLBCustData *pCData=NULL;
3226     TLBFuncDesc * pFDesc; 
3227     int i;
3228
3229     for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
3230
3231     if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
3232         for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData; 
3233                 pCData = pCData->next)
3234             if( IsEqualIID(guid, &pCData->guid)) break;
3235
3236     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3237
3238     if(pCData)
3239     {
3240         VariantInit( pVarVal);
3241         VariantCopy( pVarVal, &pCData->data);
3242         return S_OK;
3243     }
3244     return E_INVALIDARG;  /* FIXME: correct? */
3245 }
3246
3247 /* ITypeInfo2::GetVarcCustData
3248  *
3249  * Gets the custom data
3250  */
3251 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
3252         ITypeInfo2 * iface,
3253         UINT index,
3254         REFGUID guid,
3255         VARIANT *pVarVal)
3256 {   
3257     ICOM_THIS( ITypeInfoImpl, iface);
3258     TLBCustData *pCData=NULL;
3259     TLBVarDesc * pVDesc; 
3260     int i;
3261
3262     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
3263
3264     if(pVDesc)
3265     {
3266       for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
3267       {
3268         if( IsEqualIID(guid, &pCData->guid)) break;
3269       }
3270     }
3271
3272     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3273
3274     if(pCData)
3275     {
3276         VariantInit( pVarVal);
3277         VariantCopy( pVarVal, &pCData->data);
3278         return S_OK;
3279     }
3280     return E_INVALIDARG;  /* FIXME: correct? */
3281 }
3282
3283 /* ITypeInfo2::GetImplcCustData
3284  *
3285  * Gets the custom data
3286  */
3287 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
3288         ITypeInfo2 * iface,
3289         UINT index,
3290         REFGUID guid,
3291         VARIANT *pVarVal)
3292 {   
3293     ICOM_THIS( ITypeInfoImpl, iface);
3294     TLBCustData *pCData=NULL;
3295     TLBRefType * pRDesc; 
3296     int i;
3297
3298     for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
3299
3300     if(pRDesc)
3301     {
3302       for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
3303       {
3304         if( IsEqualIID(guid, &pCData->guid)) break;
3305       }
3306     }
3307     
3308     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3309
3310     if(pCData)
3311     {
3312         VariantInit( pVarVal);
3313         VariantCopy( pVarVal, &pCData->data);
3314         return S_OK;
3315     }
3316     return E_INVALIDARG;  /* FIXME: correct? */
3317 }
3318
3319 /* ITypeInfo2::GetDocumentation2
3320  * 
3321  * Retrieves the documentation string, the complete Help file name and path,
3322  * the localization context to use, and the context ID for the library Help
3323  * topic in the Help file.
3324  *
3325  */
3326 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
3327         ITypeInfo2 * iface,
3328         MEMBERID memid,
3329         LCID lcid,
3330         BSTR *pbstrHelpString,
3331         DWORD *pdwHelpStringContext,
3332         BSTR *pbstrHelpStringDll)
3333 {
3334     ICOM_THIS( ITypeInfoImpl, iface);
3335     TLBFuncDesc * pFDesc; 
3336     TLBVarDesc * pVDesc; 
3337     TRACE("(%p) memid %ld lcid(0x%lx)  HelpString(%p) "
3338           "HelpStringContext(%p) HelpStringDll(%p)\n",
3339           This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
3340           pbstrHelpStringDll );
3341     /* the help string should be obtained from the helpstringdll,
3342      * using the _DLLGetDocumentation function, based on the supplied
3343      * lcid. Nice to do sometime...
3344      */
3345     if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
3346         if(pbstrHelpString)
3347             *pbstrHelpString=SysAllocString(This->Name);
3348         if(pdwHelpStringContext)
3349             *pdwHelpStringContext=This->dwHelpStringContext;
3350         if(pbstrHelpStringDll)
3351             *pbstrHelpStringDll=
3352                 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
3353         return S_OK;
3354     }else {/* for a member */
3355     for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
3356         if(pFDesc->funcdesc.memid==memid){
3357              if(pbstrHelpString)
3358                 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
3359             if(pdwHelpStringContext)
3360                 *pdwHelpStringContext=pFDesc->HelpStringContext;
3361             if(pbstrHelpStringDll)
3362                 *pbstrHelpStringDll=
3363                     SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
3364         return S_OK;
3365     }
3366     for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
3367         if(pVDesc->vardesc.memid==memid){
3368              if(pbstrHelpString)
3369                 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
3370             if(pdwHelpStringContext)
3371                 *pdwHelpStringContext=pVDesc->HelpStringContext;
3372             if(pbstrHelpStringDll)
3373                 *pbstrHelpStringDll=
3374                     SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
3375             return S_OK;
3376         }
3377     }
3378     return TYPE_E_ELEMENTNOTFOUND;
3379 }
3380
3381 /* ITypeInfo2::GetAllCustData
3382  *
3383  * Gets all custom data items for the Type info. 
3384  *
3385  */
3386 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
3387         ITypeInfo2 * iface,
3388         CUSTDATA *pCustData)
3389 {
3390     ICOM_THIS( ITypeInfoImpl, iface);
3391     TLBCustData *pCData;
3392     int i;
3393
3394     TRACE("(%p) returning %d items\n", This, This->ctCustData); 
3395
3396     pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3397     if(pCustData->prgCustData ){
3398         pCustData->cCustData=This->ctCustData;
3399         for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3400             pCustData->prgCustData[i].guid=pCData->guid;
3401             VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3402         }
3403     }else{
3404         ERR(" OUT OF MEMORY! \n");
3405         return E_OUTOFMEMORY;
3406     }
3407     return S_OK;
3408 }
3409
3410 /* ITypeInfo2::GetAllFuncCustData
3411  *
3412  * Gets all custom data items for the specified Function
3413  *
3414  */
3415 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
3416         ITypeInfo2 * iface,
3417         UINT index,
3418         CUSTDATA *pCustData)
3419 {
3420     ICOM_THIS( ITypeInfoImpl, iface);
3421     TLBCustData *pCData;
3422     TLBFuncDesc * pFDesc; 
3423     int i;
3424     TRACE("(%p) index %d\n", This, index); 
3425     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
3426             pFDesc=pFDesc->next)
3427         ;
3428     if(pFDesc){
3429         pCustData->prgCustData =
3430             TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
3431         if(pCustData->prgCustData ){
3432             pCustData->cCustData=pFDesc->ctCustData;
3433             for(i=0, pCData=pFDesc->pCustData; pCData; i++,
3434                     pCData = pCData->next){
3435                 pCustData->prgCustData[i].guid=pCData->guid;
3436                 VariantCopy(& pCustData->prgCustData[i].varValue,
3437                         & pCData->data);
3438             }
3439         }else{
3440             ERR(" OUT OF MEMORY! \n");
3441             return E_OUTOFMEMORY;
3442         }
3443         return S_OK;
3444     }
3445     return TYPE_E_ELEMENTNOTFOUND;
3446 }
3447
3448 /* ITypeInfo2::GetAllParamCustData
3449  *
3450  * Gets all custom data items for the Functions
3451  *
3452  */
3453 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
3454     UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
3455 {
3456     ICOM_THIS( ITypeInfoImpl, iface);
3457     TLBCustData *pCData=NULL;
3458     TLBFuncDesc * pFDesc; 
3459     int i;
3460     TRACE("(%p) index %d\n", This, indexFunc); 
3461     for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
3462             pFDesc=pFDesc->next)
3463         ;
3464     if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
3465         pCustData->prgCustData = 
3466             TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
3467                     sizeof(CUSTDATAITEM));
3468         if(pCustData->prgCustData ){
3469             pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
3470             for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
3471                     pCData; i++, pCData = pCData->next){
3472                 pCustData->prgCustData[i].guid=pCData->guid;
3473                 VariantCopy(& pCustData->prgCustData[i].varValue,
3474                         & pCData->data);
3475             }
3476         }else{
3477             ERR(" OUT OF MEMORY! \n");
3478             return E_OUTOFMEMORY;
3479         }
3480         return S_OK;
3481     }
3482     return TYPE_E_ELEMENTNOTFOUND;
3483 }
3484
3485 /* ITypeInfo2::GetAllVarCustData
3486  *
3487  * Gets all custom data items for the specified Variable
3488  *
3489  */
3490 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
3491     UINT index, CUSTDATA *pCustData)
3492 {
3493     ICOM_THIS( ITypeInfoImpl, iface);
3494     TLBCustData *pCData;
3495     TLBVarDesc * pVDesc; 
3496     int i;
3497     TRACE("(%p) index %d\n", This, index); 
3498     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
3499             pVDesc=pVDesc->next)
3500         ;
3501     if(pVDesc){
3502         pCustData->prgCustData =
3503             TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
3504         if(pCustData->prgCustData ){
3505             pCustData->cCustData=pVDesc->ctCustData;
3506             for(i=0, pCData=pVDesc->pCustData; pCData; i++,
3507                     pCData = pCData->next){
3508                 pCustData->prgCustData[i].guid=pCData->guid;
3509                 VariantCopy(& pCustData->prgCustData[i].varValue,
3510                         & pCData->data);
3511             }
3512         }else{
3513             ERR(" OUT OF MEMORY! \n");
3514             return E_OUTOFMEMORY;
3515         }
3516         return S_OK;
3517     }
3518     return TYPE_E_ELEMENTNOTFOUND;
3519 }
3520
3521 /* ITypeInfo2::GetAllImplCustData
3522  *
3523  * Gets all custom data items for the specified implementation type
3524  *
3525  */
3526 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
3527         ITypeInfo2 * iface,
3528         UINT index,
3529         CUSTDATA *pCustData)
3530 {
3531     ICOM_THIS( ITypeInfoImpl, iface);
3532     TLBCustData *pCData;
3533     TLBRefType * pRDesc; 
3534     int i;
3535     TRACE("(%p) index %d\n", This, index); 
3536     for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
3537             pRDesc=pRDesc->next)
3538         ;
3539     if(pRDesc){
3540         pCustData->prgCustData =
3541             TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
3542         if(pCustData->prgCustData ){
3543             pCustData->cCustData=pRDesc->ctCustData;
3544             for(i=0, pCData=pRDesc->pCustData; pCData; i++,
3545                     pCData = pCData->next){
3546                 pCustData->prgCustData[i].guid=pCData->guid;
3547                 VariantCopy(& pCustData->prgCustData[i].varValue,
3548                         & pCData->data);
3549             }
3550         }else{
3551             ERR(" OUT OF MEMORY! \n");
3552             return E_OUTOFMEMORY;
3553         }
3554         return S_OK;
3555     }
3556     return TYPE_E_ELEMENTNOTFOUND;
3557 }
3558
3559 static ICOM_VTABLE(ITypeInfo2) tinfvt = 
3560 {
3561     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3562
3563     ITypeInfo_fnQueryInterface,
3564     ITypeInfo_fnAddRef,
3565     ITypeInfo_fnRelease,
3566
3567     ITypeInfo_fnGetTypeAttr,
3568     ITypeInfo_fnGetTypeComp,
3569     ITypeInfo_fnGetFuncDesc,
3570     ITypeInfo_fnGetVarDesc,
3571     ITypeInfo_fnGetNames,
3572     ITypeInfo_fnGetRefTypeOfImplType,
3573     ITypeInfo_fnGetImplTypeFlags,
3574     ITypeInfo_fnGetIDsOfNames,
3575     ITypeInfo_fnInvoke,
3576     ITypeInfo_fnGetDocumentation,
3577     ITypeInfo_fnGetDllEntry,
3578     ITypeInfo_fnGetRefTypeInfo,
3579     ITypeInfo_fnAddressOfMember,
3580     ITypeInfo_fnCreateInstance,
3581     ITypeInfo_fnGetMops,
3582     ITypeInfo_fnGetContainingTypeLib,
3583     ITypeInfo_fnReleaseTypeAttr,
3584     ITypeInfo_fnReleaseFuncDesc,
3585     ITypeInfo_fnReleaseVarDesc,
3586
3587     ITypeInfo2_fnGetTypeKind,
3588     ITypeInfo2_fnGetTypeFlags,
3589     ITypeInfo2_fnGetFuncIndexOfMemId,
3590     ITypeInfo2_fnGetVarIndexOfMemId,
3591     ITypeInfo2_fnGetCustData,
3592     ITypeInfo2_fnGetFuncCustData,
3593     ITypeInfo2_fnGetParamCustData,
3594     ITypeInfo2_fnGetVarCustData,
3595     ITypeInfo2_fnGetImplTypeCustData,
3596     ITypeInfo2_fnGetDocumentation2,
3597     ITypeInfo2_fnGetAllCustData,
3598     ITypeInfo2_fnGetAllFuncCustData,
3599     ITypeInfo2_fnGetAllParamCustData,
3600     ITypeInfo2_fnGetAllVarCustData,
3601     ITypeInfo2_fnGetAllImplTypeCustData,
3602 };