Read/load type libraries. Implementation of ITypeLib, ITYpeInfo,
ITypeLib2 and ITypeInfo2 methods.

diff --git a/include/debugdefs.h b/include/debugdefs.h
index d6e0298..859302b 100644
--- a/include/debugdefs.h
+++ b/include/debugdefs.h
@@ -152,22 +152,23 @@
 int dbch_treeview = 141;
 int dbch_ttydrv = 142;
 int dbch_tweak = 143;
-int dbch_updown = 144;
-int dbch_ver = 145;
-int dbch_virtual = 146;
-int dbch_vxd = 147;
-int dbch_wave = 148;
-int dbch_win = 149;
-int dbch_win16drv = 150;
-int dbch_win32 = 151;
-int dbch_wing = 152;
-int dbch_winsock = 153;
-int dbch_winspool = 154;
-int dbch_wnet = 155;
-int dbch_x11 = 156;
-int dbch_x11drv = 157;
+int dbch_typelib = 144;
+int dbch_updown = 145;
+int dbch_ver = 146;
+int dbch_virtual = 147;
+int dbch_vxd = 148;
+int dbch_wave = 149;
+int dbch_win = 150;
+int dbch_win16drv = 151;
+int dbch_win32 = 152;
+int dbch_wing = 153;
+int dbch_winsock = 154;
+int dbch_winspool = 155;
+int dbch_wnet = 156;
+int dbch_x11 = 157;
+int dbch_x11drv = 158;
 
-#define DEBUG_CHANNEL_COUNT 158
+#define DEBUG_CHANNEL_COUNT 159
 
 char __debug_msg_enabled[DEBUG_CHANNEL_COUNT][DEBUG_CLASS_COUNT] = {
 {1, 1, 0, 0},
@@ -327,6 +328,7 @@
 {1, 1, 0, 0},
 {1, 1, 0, 0},
 {1, 1, 0, 0},
+{1, 1, 0, 0},
 {1, 1, 0, 0}
 };
 
@@ -475,6 +477,7 @@
 "treeview",
 "ttydrv",
 "tweak",
+"typelib",
 "updown",
 "ver",
 "virtual",
diff --git a/include/wine/obj_oleaut.h b/include/wine/obj_oleaut.h
index 619912b..5a6a6ef 100644
--- a/include/wine/obj_oleaut.h
+++ b/include/wine/obj_oleaut.h
@@ -199,6 +199,8 @@
 #define DISPID_DESTRUCTOR ( -7 )
 #define DISPID_COLLECT  ( -8 )
 
+#define MEMBERID_NIL DISPID_UNKNOWN
+
 typedef struct  tagDISPPARAMS
 {
   VARIANTARG* rgvarg;
@@ -238,6 +240,15 @@
 	USHORT wParamFlags;
 } PARAMDESC;
 
+#define PARAMFLAG_NONE      	(0x00)
+#define PARAMFLAG_FIN           (0x01)
+#define PARAMFLAG_FOUT          (0x02)
+#define PARAMFLAG_FLCID     	(0x04)
+#define PARAMFLAG_FRETVAL       (0x08)
+#define PARAMFLAG_FOPT          (0x10)
+#define PARAMFLAG_FHASDEFAULT   (0x20)
+
+
 typedef struct tagTYPEDESC
 {
 	union {
@@ -284,7 +295,7 @@
 	WORD cVars;
 	WORD cImplTypes;
 	WORD cbSizeVft;
-	WORD cAlignment;
+	WORD cbAlignment;
 	WORD wTypeFlags;
 	WORD wMajorVerNum;
 	WORD wMinorVerNum;
@@ -322,7 +333,7 @@
 	SCODE *lprgscode;
 	ELEMDESC *lprgelemdescParam;
 	FUNCKIND funckind;
-	INVOKEKIND invKind;
+	INVOKEKIND invkind;
 	CALLCONV callconv;
 	SHORT cParams;
 	SHORT cParamsOpt;
@@ -498,6 +509,19 @@
  * DISP_E_ARRAYISLOCKED : The variant contains an array that is locked.
  */
 
+
+typedef struct  tagCUSTDATAITEM {
+    GUID guid;
+    VARIANTARG varValue;
+} CUSTDATAITEM, *LPCUSTDATAITEM;
+
+typedef struct  tagCUSTDATA {
+    INT cCustData;
+    LPCUSTDATAITEM prgCustData; /* count cCustdata */
+} CUSTDATA, *LPCUSTDATA;
+
+
+
 /*****************************************************************************
  * IDispatch interface
  */
@@ -536,8 +560,9 @@
 	ICOM_METHOD2(HRESULT,GetFuncDesc, UINT,index, FUNCDESC**,ppFuncDesc) \
 	ICOM_METHOD2(HRESULT,GetVarDesc, UINT,index, VARDESC**,ppVarDesc) \
 	ICOM_METHOD4(HRESULT,GetNames, MEMBERID,memid, BSTR*,rgBstrNames, UINT,cMaxNames, UINT*,pcNames) \
-	ICOM_METHOD2(HRESULT,GetRefTypeOfImplType, UINT,index, INT*,pImplTypeFlags) \
-	ICOM_METHOD2(HRESULT,GetImplTypeFlags, UINT,index, INT*,pImplTypeFlags) \
+	ICOM_METHOD2(HRESULT,GetRefTypeOfImplType, UINT,index, HREFTYPE*,\
+		pRefType) \
+	ICOM_METHOD2(HRESULT,GetImplTypeFlags, UINT,index, INT*,pImplTypeFlags)\
 	ICOM_METHOD3(HRESULT,GetIDsOfNames, LPOLESTR*,rgszNames, UINT,cNames, MEMBERID*,pMemId) \
 	ICOM_METHOD7(HRESULT,Invoke, PVOID,pvInstance, MEMBERID,memid, WORD,wFlags, DISPPARAMS*,pDispParams, VARIANT*,pVarResult, EXCEPINFO*,pExcepInfo, UINT*,puArgErr) \
 	ICOM_METHOD5(HRESULT,GetDocumentation, MEMBERID,memid, BSTR*,pBstrName, BSTR*,pBstrDocString, DWORD*,pdwHelpContext, BSTR*,pBstrHelpFile) \
@@ -549,7 +574,38 @@
 	ICOM_METHOD2(HRESULT,GetContainingTypeLib, ITypeLib**,ppTLib, UINT*,pIndex) \
 	ICOM_METHOD1(HRESULT,ReleaseTypeAttr, TYPEATTR*,pTypeAttr) \
 	ICOM_METHOD1(HRESULT,ReleaseFuncDesc, FUNCDESC*,pFuncDesc) \
-	ICOM_METHOD1(HRESULT,ReleaseVarDesc, VARDESC*,pVarDesc) 
+	ICOM_METHOD1(HRESULT,ReleaseVarDesc, VARDESC*,pVarDesc)\
+\
+\
+	/* itypeinfo2 methods */\
+	ICOM_METHOD1(HRESULT, GetTypeKind, TYPEKIND*, pTypeKind) \
+	ICOM_METHOD1(HRESULT, GetTypeFlags, UINT*, pTypeFlags) \
+	ICOM_METHOD3(HRESULT, GetFuncIndexOfMemId, MEMBERID, memid, INVOKEKIND,\
+		invKind, UINT*, pFuncIndex) \
+	ICOM_METHOD2(HRESULT, GetVarIndexOfMemId, MEMBERID, memid, UINT*, \
+		pVarIndex) \
+	ICOM_METHOD2(HRESULT, GetCustData, REFGUID, guid, VARIANT*, pVarVal) \
+	ICOM_METHOD3(HRESULT, GetFuncCustData, UINT, index, REFGUID, guid,\
+		VARIANT*, pVarVal) \
+	ICOM_METHOD4(HRESULT, GetParamCustData, UINT, indexFunc, UINT,\
+		indexParam, REFGUID, guid, VARIANT*, pVarVal) \
+	ICOM_METHOD3(HRESULT, GetVarCustData, UINT, index, REFGUID, guid,\
+		VARIANT*, pVarVal) \
+	ICOM_METHOD3(HRESULT, GetImplTypeCustData, UINT, index, REFGUID, guid,\
+		VARIANT*, pVarVal) \
+	ICOM_METHOD5(HRESULT, GetDocumentation2, MEMBERID, memid, LCID, lcid,\
+		BSTR*, pbstrHelpString, INT*, pdwHelpStringContext,\
+		BSTR*, pbstrHelpStringDll) \
+	ICOM_METHOD1(HRESULT, GetAllCustData, CUSTDATA*, pCustData) \
+	ICOM_METHOD2(HRESULT, GetAllFuncCustData, UINT, index, CUSTDATA*,\
+		pCustData)\
+	ICOM_METHOD3(HRESULT, GetAllParamCustData, UINT, indexFunc, UINT,\
+		indexParam, CUSTDATA*, pCustData) \
+	ICOM_METHOD2(HRESULT, GetAllVarCustData, UINT, index, CUSTDATA*,\
+		pCustData) \
+	ICOM_METHOD2(HRESULT, GetAllImplTypeCustData, UINT, index, CUSTDATA*,\
+		pCustData)
+	
 #define ITypeInfo_IMETHODS \
 	IUnknown_IMETHODS \
 	ITypeInfo_METHODS
@@ -562,12 +618,12 @@
 #define ITypeInfo_AddRef(p)                     ICOM_CALL (AddRef,p)
 #define ITypeInfo_Release(p)                    ICOM_CALL (Release,p)
 /*** ITypeInfo methods ***/
-#define ITypeInfo_GetTypeAttr(p,a,b)            ICOM_CALL2(GetTypeAttr,p,a,b)
+#define ITypeInfo_GetTypeAttr(p,a)              ICOM_CALL1(GetTypeAttr,p,a)
 #define ITypeInfo_GetTypeComp(p,a)              ICOM_CALL1(GetTypeComp,p,a)
 #define ITypeInfo_GetFuncDesc(p,a,b)            ICOM_CALL2(GetFuncDesc,p,a,b)
 #define ITypeInfo_GetVarDesc(p,a,b)             ICOM_CALL2(GetVarDesc,p,a,b)
 #define ITypeInfo_GetNames(p,a,b,c,d)           ICOM_CALL4(GetNames,p,a,b,c,d)
-#define ITypeInfo_GetRefTypeOfImplType(p,a,b)   ICOM_CALL2(GetRefTypeOfImplType,p,a)
+#define ITypeInfo_GetRefTypeOfImplType(p,a,b)   ICOM_CALL2(GetRefTypeOfImplType,p,a,b)
 #define ITypeInfo_GetImplTypeFlags(p,a,b)       ICOM_CALL2(GetImplTypeFlags,p,a,b)
 #define ITypeInfo_GetIDsOfNames(p,a,b,c)        ICOM_CALL3(GetImplTypeFlags,p,a,b,c)
 #define ITypeInfo_Invoke(p,a,b,c,d,e,f,g)       ICOM_CALL7(Invoke,p,a,b,c,d,e,f,g)
@@ -589,7 +645,7 @@
  */
 #define ICOM_INTERFACE ITypeLib
 #define ITypeLib_METHODS \
-	ICOM_METHOD (HRESULT,GetTypeInfoCount) \
+	ICOM_METHOD (UINT,GetTypeInfoCount) \
 	ICOM_METHOD2(HRESULT,GetTypeInfo, UINT,index, ITypeInfo**,ppTInfo) \
 	ICOM_METHOD2(HRESULT,GetTypeInfoType, UINT,index, TYPEKIND*,pTKind) \
 	ICOM_METHOD2(HRESULT,GetTypeInfoOfGuid, REFGUID,guid, ITypeInfo**,ppTinfo) \
@@ -598,7 +654,16 @@
 	ICOM_METHOD5(HRESULT,GetDocumentation, INT,index, BSTR*,pBstrName, BSTR*,pBstrDocString, DWORD*,pdwHelpContext, BSTR*,pBstrHelpFile) \
 	ICOM_METHOD3(HRESULT,IsName, LPOLESTR,szNameBuf, ULONG,lHashVal, BOOL*,bfName) \
 	ICOM_METHOD5(HRESULT,FindName, LPOLESTR,szNameBuf, ULONG,lHashVal, ITypeInfo**,ppTInfo, MEMBERID*,rgMemId, USHORT*,pcFound) \
-	ICOM_METHOD1(HRESULT,ReleaseTLibAttr, TLIBATTR*,pTLibAttr) 
+	ICOM_METHOD1(VOID,ReleaseTLibAttr, TLIBATTR*,pTLibAttr)\
+\
+	ICOM_METHOD2(HRESULT,GetCustData, REFGUID,guid, VARIANT*, pVarVal)\
+	ICOM_METHOD2(HRESULT, GetLibStatistics, UINT *,pcUniqueNames, \
+			UINT*, pcchUniqueNames) \
+	ICOM_METHOD5(HRESULT, GetDocumentation2, INT, index, LCID, lcid,\
+		BSTR*, pbstrHelpString, INT*, pdwHelpStringContext,\
+		BSTR*, pbstrHelpStringDll)\
+	ICOM_METHOD1(HRESULT, GetAllCustData, CUSTDATA *, pCustData)
+	
 #define ITypeLib_IMETHODS \
 	IUnknown_IMETHODS \
 	ITypeLib_METHODS
diff --git a/ole/typelib.c b/ole/typelib.c
index b4bf48d..13e5549 100644
--- a/ole/typelib.c
+++ b/ole/typelib.c
@@ -2,6 +2,26 @@
  *	TYPELIB
  *
  *	Copyright 1997	Marcus Meissner
+ *		      1999  Rein Klazes
+ * there is much left to do here before it can be usefull for real world
+ * programs
+ * know problems:
+ * -. Only one format of typelibs is supported
+ * -. All testing until sofar is done using special written windows programs
+ * -. Data structures are straightforward, but slow for look-ups.
+ * -. (related) nothing is hashed
+ * -. a typelib is always read in its entirely into memory and never released.
+ * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
+ *      of them I don't know yet how to implement them.
+ * -. Most error return values are just guessed not checked with windows
+ *      behaviour.
+ * -. all locale stuf ignored
+ * -. move stuf to wine/dlls
+ * -. didn't bother with a c++ interface
+ * -. lousy fatal error handling
+ * -. some methods just return pointers to internal data structures, this is
+ *      partly laziness, partly I want to check how windows does it.
+ * 
  */
 
 #include <stdlib.h>
@@ -16,8 +36,13 @@
 #include "wine/obj_base.h"
 #include "debug.h"
 #include "winversion.h"
+/* FIXME: get rid of these */
+typedef struct ITypeInfoVtbl ITypeLib_VTable, *LPTYPEINFO_VTABLE ; 
+typedef struct ITypeLibVtbl *LPTYPELIB_VTABLE  ; 
+#include "typelib.h"
 
 DEFAULT_DEBUG_CHANNEL(ole)
+DECLARE_DEBUG_CHANNEL(typelib)
 
 /****************************************************************************
  *		QueryPathOfRegTypeLib16	[TYPELIB.14]
@@ -58,7 +83,7 @@
 }
  
 /****************************************************************************
- *		QueryPathOfRegTypeLib32	[OLEAUT32.164]
+ *		QueryPathOfRegTypeLib	[OLEAUT32.164]
  * RETURNS
  *	path of typelib
  */
@@ -97,7 +122,7 @@
 /******************************************************************************
  * LoadTypeLib [TYPELIB.3]  Loads and registers a type library
  * NOTES
- *    Docs: OLECHAR32 FAR* szFile
+ *    Docs: OLECHAR FAR* szFile
  *    Docs: iTypeLib FAR* FAR* pptLib
  *
  * RETURNS
@@ -117,53 +142,68 @@
 }
 
 /******************************************************************************
- *		LoadTypeLib32	[OLEAUT32.161]
+ *		LoadTypeLib	[OLEAUT32.161]
  * Loads and registers a type library
  * NOTES
- *    Docs: OLECHAR32 FAR* szFile
+ *    Docs: OLECHAR FAR* szFile
  *    Docs: iTypeLib FAR* FAR* pptLib
  *
  * RETURNS
  *    Success: S_OK
  *    Failure: Status
  */
+int TLB_ReadTypeLib(PCHAR file, ITypeLib **ppTypelib);
 HRESULT WINAPI LoadTypeLib(
     OLECHAR *szFile,   /* [in] Name of file to load from */
-    void * *pptLib) /* [out] Pointer to pointer to loaded type library */
+    ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
 {
-    FIXME(ole, "('%s',%p): stub\n",debugstr_w(szFile),pptLib);
+    LPSTR p;
+    HRESULT res;
+    TRACE(typelib, "('%s',%p)\n",debugstr_w(szFile),pptLib);
+    
+    p=HEAP_strdupWtoA(GetProcessHeap(),0,szFile);
+    res= TLB_ReadTypeLib(p, pptLib);
+    //XXX need to free p ??
 
-    if (pptLib!=0)
-      *pptLib=0;
+    TRACE( typelib, " returns %ld\n",res);
 
-    return E_FAIL;
+    return res;
 }
 
 /******************************************************************************
  *		LoadRegTypeLib	[OLEAUT32.162]
  */
-HRESULT WINAPI LoadRegTypeLib(
-  REFGUID        rguid,
-  unsigned short wVerMajor,
-  unsigned short wVerMinor,
-  LCID           lcid,
-  void**         pptLib)
-{
-  FIXME(ole, "(): stub\n");
+HRESULT WINAPI LoadRegTypeLib(	
+	REFGUID rguid,	/* [in] referenced guid */
+	WORD wVerMajor,	/* [in] major version */
+	WORD wVerMinor,	/* [in] minor version */
+	LCID lcid,	/* [in] locale id */
+	ITypeLib **ppTLib	/* [out] path of typelib */
+) {
+    BSTR bstr=NULL;
+    HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor,
+		    lcid, &bstr);
+    if(SUCCEEDED(res)){
+        res= LoadTypeLib(bstr, ppTLib);
+        SysFreeString(bstr);
+    }
+    if(TRACE_ON(typelib)){
+        char xriid[50];
+        WINE_StringFromCLSID((LPCLSID)rguid,xriid);
+        TRACE(typelib,"(IID: %s) load %s (%p)\n",xriid,
+                SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
+    }
+    return res;
+}	
 
-  if (pptLib!=0)
-    *pptLib=0;
-  
-  return E_FAIL;
-}
 
 /******************************************************************************
- *		RegisterTypeLib32	[OLEAUT32.163]
+ *		RegisterTypeLib	[OLEAUT32.163]
  * Adds information about a type library to the System Registry           
  * NOTES
  *    Docs: ITypeLib FAR * ptlib
- *    Docs: OLECHAR32 FAR* szFullPath
- *    Docs: OLECHAR32 FAR* szHelpDir
+ *    Docs: OLECHAR FAR* szFullPath
+ *    Docs: OLECHAR FAR* szHelpDir
  *
  * RETURNS
  *    Success: S_OK
@@ -172,11 +212,35 @@
 HRESULT WINAPI RegisterTypeLib(
      ITypeLib * ptlib,      /*[in] Pointer to the library*/
      OLECHAR * szFullPath, /*[in] full Path of the library*/
-     OLECHAR * szHelpDir)  /*[in] dir to the helpfile for the library, may be NULL*/
+     OLECHAR * szHelpDir)  /*[in] dir to the helpfile for the library,
+							 may be NULL*/
 {   FIXME(ole, "(%p,%s,%s): stub\n",ptlib, debugstr_w(szFullPath),debugstr_w(szHelpDir));
     return S_OK;	/* FIXME: pretend everything is OK */
 }
 
+
+/******************************************************************************
+ *	UnRegisterTypeLib	[OLEAUT32.186]
+ * Removes information about a type library from the System Registry           
+ * NOTES
+ *
+ * RETURNS
+ *    Success: S_OK
+ *    Failure: Status
+ */
+HRESULT WINAPI UnRegisterTypeLib(
+    REFGUID libid,	/* [in] Guid of the library */
+	WORD wVerMajor,	/* [in] major version */
+	WORD wVerMinor,	/* [in] minor version */
+	LCID lcid,	/* [in] locale id */
+	SYSKIND syskind)
+{   
+    char xriid[50];
+    WINE_StringFromCLSID((LPCLSID)libid,xriid);
+    TRACE(typelib,"(IID: %s): stub\n",xriid);
+    return S_OK;	/* FIXME: pretend everything is OK */
+}
+
 /****************************************************************************
  *	OABuildVersion				(TYPELIB.15)
  * RETURNS
@@ -196,3 +260,2280 @@
 	return MAKELONG(0xbd0, 0xa); /* return Win95A for now */
     }
 }
+
+/* for better debugging info leave the static out for the time being */
+#define static
+
+/*=======================Itypelib methods ===============================*/
+/* ITypeLib methods */
+static HRESULT WINAPI ITypeLib_fnQueryInterface( LPTYPELIB This, REFIID riid,
+    VOID **ppvObject); 
+static ULONG WINAPI ITypeLib_fnAddRef( LPTYPELIB This); 
+static ULONG WINAPI ITypeLib_fnRelease( LPTYPELIB This); 
+static UINT WINAPI ITypeLib_fnGetTypeInfoCount( LPTYPELIB This); 
+static HRESULT WINAPI ITypeLib_fnGetTypeInfo( LPTYPELIB This, UINT index, 
+    ITypeInfo **ppTInfo); 
+
+static HRESULT WINAPI ITypeLib_fnGetTypeInfoType( LPTYPELIB This, UINT index,
+    TYPEKIND *pTKind); 
+
+static HRESULT WINAPI ITypeLib_fnGetTypeInfoOfGuid( LPTYPELIB This, REFGUID guid,
+    ITypeInfo **ppTinfo);
+
+static HRESULT WINAPI ITypeLib_fnGetLibAttr( LPTYPELIB This, 
+    LPTLIBATTR *ppTLibAttr); 
+
+static HRESULT WINAPI ITypeLib_fnGetTypeComp( LPTYPELIB This,
+    ITypeComp **ppTComp); 
+
+static HRESULT WINAPI ITypeLib_fnGetDocumentation( LPTYPELIB This, INT index,
+    BSTR *pBstrName, BSTR *pBstrDocString, DWORD *pdwHelpContext, 
+    BSTR *pBstrHelpFile);
+
+static HRESULT WINAPI ITypeLib_fnIsName( LPTYPELIB This, LPOLESTR szNameBuf,
+    ULONG lHashVal, BOOL *pfName);
+
+static HRESULT WINAPI ITypeLib_fnFindName( LPTYPELIB This, LPOLESTR szNameBuf,
+    ULONG lHashVal, ITypeInfo **ppTInfo, MEMBERID *rgMemId, UINT16 *pcFound);
+
+static VOID WINAPI ITypeLib_fnReleaseTLibAttr( LPTYPELIB This,
+		TLIBATTR *pTLibAttr);
+
+static HRESULT WINAPI ITypeLib2_fnGetCustData( ITypeLib * This, REFGUID guid, 
+        VARIANT *pVarVal); 
+
+static HRESULT WINAPI ITypeLib2_fnGetLibStatistics( ITypeLib * This, 
+        UINT *pcUniqueNames, UINT *pcchUniqueNames); 
+
+static HRESULT WINAPI ITypeLib2_fnGetDocumentation2( ITypeLib * This, 
+        INT index, LCID lcid, BSTR *pbstrHelpString,
+        INT *pdwHelpStringContext, BSTR *pbstrHelpStringDll); 
+
+static HRESULT WINAPI ITypeLib2_fnGetAllCustData( ITypeLib * This,
+        CUSTDATA *pCustData);
+static ICOM_VTABLE(ITypeLib) tlbvt = {
+    ITypeLib_fnQueryInterface,
+    ITypeLib_fnAddRef,
+    ITypeLib_fnRelease,
+    ITypeLib_fnGetTypeInfoCount,
+    ITypeLib_fnGetTypeInfo,
+    ITypeLib_fnGetTypeInfoType,
+    ITypeLib_fnGetTypeInfoOfGuid,
+    ITypeLib_fnGetLibAttr,
+    ITypeLib_fnGetTypeComp,
+    ITypeLib_fnGetDocumentation,
+    ITypeLib_fnIsName,
+    ITypeLib_fnFindName,
+    ITypeLib_fnReleaseTLibAttr,
+    ITypeLib2_fnGetCustData,
+    ITypeLib2_fnGetLibStatistics,
+    ITypeLib2_fnGetDocumentation2,
+    ITypeLib2_fnGetAllCustData
+ };
+/* TypeInfo Methods */
+
+static HRESULT WINAPI ITypeInfo_fnQueryInterface( LPTYPEINFO This, REFIID riid,
+    VOID **ppvObject); 
+static ULONG WINAPI ITypeInfo_fnAddRef( LPTYPEINFO This); 
+static ULONG WINAPI ITypeInfo_fnRelease( LPTYPEINFO This); 
+static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( LPTYPEINFO This,
+        LPTYPEATTR  *ppTypeAttr); 
+
+static HRESULT WINAPI ITypeInfo_fnGetTypeComp( LPTYPEINFO This,
+        ITypeComp  * *ppTComp); 
+
+static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( LPTYPEINFO This, UINT index,
+        LPFUNCDESC  *ppFuncDesc); 
+
+static HRESULT WINAPI ITypeInfo_fnGetVarDesc( LPTYPEINFO This, UINT index,
+        LPVARDESC  *ppVarDesc); 
+
+static HRESULT WINAPI ITypeInfo_fnGetNames( LPTYPEINFO This, MEMBERID memid,
+        BSTR  *rgBstrNames, UINT cMaxNames, UINT  *pcNames);
+
+
+static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType( LPTYPEINFO This,
+        UINT index, HREFTYPE  *pRefType); 
+
+static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( LPTYPEINFO This,
+        UINT index, INT  *pImplTypeFlags); 
+
+static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( LPTYPEINFO This,
+        LPOLESTR  *rgszNames, UINT cNames, MEMBERID  *pMemId); 
+
+static HRESULT WINAPI ITypeInfo_fnInvoke( LPTYPEINFO This, VOID  *pIUnk,
+        MEMBERID memid, UINT16 dwFlags, DISPPARAMS  *pDispParams, 
+        VARIANT  *pVarResult, EXCEPINFO  *pExcepInfo, UINT  *pArgErr);
+
+static HRESULT WINAPI ITypeInfo_fnGetDocumentation( LPTYPEINFO This,
+        MEMBERID memid, BSTR  *pBstrName, BSTR  *pBstrDocString, 
+        DWORD  *pdwHelpContext, BSTR  *pBstrHelpFile); 
+
+static HRESULT WINAPI ITypeInfo_fnGetDllEntry( LPTYPEINFO This,
+        MEMBERID memid, INVOKEKIND invKind, BSTR  *pBstrDllName,
+        BSTR  *pBstrName, WORD  *pwOrdinal); 
+
+static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo( LPTYPEINFO This,
+        HREFTYPE hRefType, ITypeInfo  * *ppTInfo); 
+
+static HRESULT WINAPI ITypeInfo_fnAddressOfMember( LPTYPEINFO This,
+        MEMBERID memid, INVOKEKIND invKind, PVOID *ppv); 
+
+static HRESULT WINAPI ITypeInfo_fnCreateInstance( LPTYPEINFO This, 
+        IUnknown *pUnk, REFIID riid, VOID  * *ppvObj); 
+
+static HRESULT WINAPI ITypeInfo_fnGetMops( LPTYPEINFO This, MEMBERID memid, 
+        BSTR  *pBstrMops);
+
+
+static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( LPTYPEINFO This,
+        ITypeLib  * *ppTLib, UINT  *pIndex); 
+
+static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( LPTYPEINFO This,
+        TYPEATTR *pTypeAttr); 
+
+static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc( LPTYPEINFO This,
+        FUNCDESC *pFuncDesc); 
+
+static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( LPTYPEINFO This,
+        VARDESC *pVarDesc); 
+/* itypeinfo2 methods */
+static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo * This,
+    TYPEKIND *pTypeKind);
+static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo * This,
+    UINT *pTypeFlags);
+static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo * This,
+    MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex);
+static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo * This,
+    MEMBERID memid, UINT *pVarIndex);
+static HRESULT WINAPI ITypeInfo2_fnGetCustData( ITypeInfo * This,
+    REFGUID guid, VARIANT *pVarVal);
+static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData( ITypeInfo * This,
+    UINT index, REFGUID guid, VARIANT *pVarVal);
+static HRESULT WINAPI ITypeInfo2_fnGetParamCustData( ITypeInfo * This,
+    UINT indexFunc, UINT indexParam, REFGUID guid, VARIANT *pVarVal);
+static HRESULT WINAPI ITypeInfo2_fnGetVarCustData( ITypeInfo * This,
+    UINT index, REFGUID guid, VARIANT *pVarVal);
+static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData( ITypeInfo * This,
+    UINT index, REFGUID guid, VARIANT *pVarVal);
+static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2( ITypeInfo * This,
+    MEMBERID memid, LCID lcid, BSTR *pbstrHelpString,
+    INT *pdwHelpStringContext, BSTR *pbstrHelpStringDll);
+static HRESULT WINAPI ITypeInfo2_fnGetAllCustData( ITypeInfo * This,
+    CUSTDATA *pCustData);
+static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData( ITypeInfo * This,
+    UINT index, CUSTDATA *pCustData);
+static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo * This,
+    UINT indexFunc, UINT indexParam, CUSTDATA *pCustData);
+static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo * This,
+    UINT index, CUSTDATA *pCustData);
+static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData( ITypeInfo * This,
+    UINT index, CUSTDATA *pCustData);
+
+static ICOM_VTABLE(ITypeInfo) tinfvt = {
+    ITypeInfo_fnQueryInterface,
+    ITypeInfo_fnAddRef,
+    ITypeInfo_fnRelease,
+    ITypeInfo_fnGetTypeAttr,
+    ITypeInfo_fnGetTypeComp,
+    ITypeInfo_fnGetFuncDesc,
+    ITypeInfo_fnGetVarDesc,
+    ITypeInfo_fnGetNames,
+    ITypeInfo_fnGetRefTypeOfImplType,
+    ITypeInfo_fnGetImplTypeFlags,
+    ITypeInfo_fnGetIDsOfNames,
+    ITypeInfo_fnInvoke,
+    ITypeInfo_fnGetDocumentation,
+    ITypeInfo_fnGetDllEntry,
+    ITypeInfo_fnGetRefTypeInfo,
+    ITypeInfo_fnAddressOfMember,
+    ITypeInfo_fnCreateInstance,
+    ITypeInfo_fnGetMops,
+    ITypeInfo_fnGetContainingTypeLib,
+    ITypeInfo_fnReleaseTypeAttr,
+    ITypeInfo_fnReleaseFuncDesc,
+    ITypeInfo_fnReleaseVarDesc,
+
+    ITypeInfo2_fnGetTypeKind,
+    ITypeInfo2_fnGetTypeFlags,
+    ITypeInfo2_fnGetFuncIndexOfMemId,
+    ITypeInfo2_fnGetVarIndexOfMemId,
+    ITypeInfo2_fnGetCustData,
+    ITypeInfo2_fnGetFuncCustData,
+    ITypeInfo2_fnGetParamCustData,
+    ITypeInfo2_fnGetVarCustData,
+    ITypeInfo2_fnGetImplTypeCustData,
+    ITypeInfo2_fnGetDocumentation2,
+    ITypeInfo2_fnGetAllCustData,
+    ITypeInfo2_fnGetAllFuncCustData,
+    ITypeInfo2_fnGetAllParamCustData,
+    ITypeInfo2_fnGetAllVarCustData,
+    ITypeInfo2_fnGetAllImplTypeCustData,
+
+};
+
+static TYPEDESC stndTypeDesc[VT_LPWSTR+1]={/* VT_LPWSTR is largest type that */
+										/* may appear in type description*/
+	{{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
+        {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
+    {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
+        {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
+    {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
+        {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
+    {{0},30},{{0},31}};
+
+static void TLB_abort()
+{
+		*((int *)0)=0;
+}
+static void * TLB_Alloc(unsigned size)
+{
+    void * ret;
+    if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
+        /* FIXME */
+        ERR(ole,"cannot allocate memory\n");
+    }
+    return ret;
+}
+
+/* candidate for a more global appearance... */
+static BSTR  TLB_DupAtoBstr(PCHAR Astr)
+{
+    int len;
+    BSTR bstr;
+    DWORD *pdw  ;
+    if(!Astr)
+        return NULL;
+    len=strlen(Astr);
+    pdw  =TLB_Alloc((len+3)*sizeof(OLECHAR));
+    pdw[0]=(len)*sizeof(OLECHAR);
+    bstr=(BSTR)&( pdw[1]);
+    lstrcpyAtoW( bstr, Astr);
+    TRACE(typelib,"copying %s to (%p)\n", Astr, bstr);
+    return bstr;
+}
+
+static void TLB_Free(void * ptr)
+{
+    HeapFree(GetProcessHeap(), 0, ptr);
+}
+/* read function */
+DWORD TLB_Read(void *buffer,  DWORD count, TLBContext *pcx, long where )
+{
+	DWORD bytesread=0;
+	
+	if((where!=DO_NOT_SEEK && 
+		0xffffffff== SetFilePointer((HANDLE)pcx->hFile, where, 0, FILE_BEGIN))||
+		!ReadFile((HANDLE)pcx->hFile, buffer, count, &bytesread, NULL) ||
+		count != bytesread){
+        /* FIXME */
+		ERR( typelib, "read error is 0x%lx reading %ld bytes at 0x%lx\n",
+				GetLastError(), count, where);
+		TLB_abort();
+		exit(1);
+	}
+	return bytesread;
+}
+
+static void TLB_ReadGuid( GUID *pGuid, int offset,   TLBContext *pcx)
+{
+    if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
+        memset(pGuid,0, sizeof(GUID));
+        return;
+    }
+    TLB_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
+}
+
+PCHAR TLB_ReadName( TLBContext *pcx, int offset)
+{
+    char * name;
+    TLBNameIntro niName;
+    TLB_Read(&niName, sizeof(niName), pcx,
+				pcx->pTblDir->pNametab.offset+offset);
+    niName.namelen &= 0xFF; /* FIXME: correct ? */
+    name=TLB_Alloc((niName.namelen & 0xff) +1);
+    TLB_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
+    name[niName.namelen & 0xff]='\0';
+    return name;
+}
+PCHAR TLB_ReadString( TLBContext *pcx, int offset)
+{
+    char * string;
+    INT16 length;
+    if(offset<0) return NULL;
+    TLB_Read(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
+    if(length <= 0) return 0;
+    string=TLB_Alloc(length +1);
+    TLB_Read(string, length, pcx, DO_NOT_SEEK);
+    string[length]='\0';
+    return string;
+}
+/*
+ * read a value and fill a VARIANT structure 
+ */
+static void TLB_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
+{
+    int size;
+    if(offset <0) { /* data is packed in here */
+        pVar->vt = (offset & 0x7c000000 )>> 26;
+        V_UNION(pVar, iVal) = offset & 0xffff;
+        return;
+    }
+    TLB_Read(&(pVar->vt), sizeof(VARTYPE), pcx, 
+        pcx->pTblDir->pCustData.offset + offset );
+    switch(pVar->vt){
+        case VT_EMPTY:  /* FIXME: is this right? */
+        case VT_NULL:   /* FIXME: is this right? */
+        case VT_I2  :   /* this should not happen */
+        case VT_I4  :
+        case VT_R4  :
+        case VT_ERROR   : 
+        case VT_BOOL    : 
+        case VT_I1  : 
+        case VT_UI1 : 
+        case VT_UI2 : 
+        case VT_UI4 : 
+        case VT_INT : 
+        case VT_UINT    : 
+        case VT_VOID    : /* FIXME: is this right? */
+        case VT_HRESULT : 
+            size=4; break;
+        case VT_R8  :
+        case VT_CY  :
+        case VT_DATE    : 
+        case VT_I8  : 
+        case VT_UI8 : 
+        case VT_DECIMAL :  /* FIXME: is this right? */
+        case VT_FILETIME :
+            size=8;break;
+            /* pointer types with known behaviour */
+        case VT_BSTR    :{
+            char * ptr;
+            TLB_Read(&size, sizeof(INT), pcx, DO_NOT_SEEK );
+            ptr=TLB_Alloc(size);/* allocate temp buffer */
+            TLB_Read(ptr, size, pcx, DO_NOT_SEEK ); /* read string (ANSI) */
+            V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
+            /* FIXME: do we need a AtoW conversion here? */
+            V_UNION(pVar, bstrVal[size])=L'\0';
+            while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
+            TLB_Free(ptr);
+        }
+            size=-4; break;
+    /* FIXME: this will not work AT ALL when the variant contains a pointer */
+        case VT_DISPATCH :
+        case VT_VARIANT : 
+        case VT_UNKNOWN : 
+        case VT_PTR : 
+        case VT_SAFEARRAY :
+        case VT_CARRAY  : 
+        case VT_USERDEFINED : 
+        case VT_LPSTR   : 
+        case VT_LPWSTR  : 
+        case VT_BLOB    : 
+        case VT_STREAM  : 
+        case VT_STORAGE : 
+        case VT_STREAMED_OBJECT : 
+        case VT_STORED_OBJECT   : 
+        case VT_BLOB_OBJECT : 
+        case VT_CF  : 
+        case VT_CLSID   : 
+        default: 
+            size=0; 
+            FIXME(ole,"VARTYPE %d is not supported, setting pointer to NULL\n",
+                pVar->vt);
+    }
+
+    if(size>0) /* (big|small) endian correct? */
+        TLB_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
+        return ;
+}
+/*
+ * create a linked list with custom data
+ */
+static int TLB_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
+{
+    TLBCDGuid entry;
+    TLBCustData* pNew;
+    int count=0;
+    while(offset >=0){
+        count++;
+        pNew=TLB_Alloc(sizeof(TLBCustData));
+        TLB_Read(&entry, sizeof(entry), pcx, 
+            pcx->pTblDir->pCDGuids.offset+offset);
+        TLB_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
+        TLB_ReadValue(&(pNew->data), entry.DataOffset, pcx);
+        /* add new custom data at head of the list */
+        pNew->next=*ppCustData;
+        *ppCustData=pNew;
+        offset = entry.next;
+    }
+    return count;
+}
+
+static void TLB_GetTdesc(TLBContext *pcx, INT type,TYPEDESC * pTd )
+{
+    if(type <0)
+        pTd->vt=type & VT_TYPEMASK;
+    else
+        *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
+}
+static void TLB_DoFuncs(TLBContext *pcx, int cFuncs, int cVars,
+                          int offset, TLBFuncDesc ** pptfd)
+{
+    /* 
+     * member information is stored in a data structure at offset
+     * indicated by the memoffset field of the typeinfo structure
+     * There are several distinctive parts.
+     * the first part starts with a field that holds the total length 
+     * of this (first) part excluding this field. Then follow the records,
+     * for each member there is one record.
+     *
+     * First entry is always the length of the record (excluding this
+     * length word). 
+     * Rest of the record depends on the type of the member. If there is 
+     * a field indicating the member type (function variable intereface etc)
+     * I have not found it yet. At this time we depend on the information
+     * in the type info and the usual order how things are stored.
+     *
+     * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
+     * for each member;
+     * 
+     * Third is a equal sized array with file offsets to the name entry 
+     * of each member.
+     * 
+     * Forth and last (?) part is an array with offsets to the records in the
+     * first part of this file segment.
+     */
+
+    int infolen, nameoffset, reclength, nrattributes;
+    char recbuf[512];
+    TLBFuncRecord * pFuncRec=(TLBFuncRecord *) recbuf;
+    int i, j;
+    int recoffset=offset+sizeof(INT);
+    TLB_Read(&infolen,sizeof(INT), pcx, offset);
+    for(i=0;i<cFuncs;i++){
+        *pptfd=TLB_Alloc(sizeof(TLBFuncDesc));
+    /* name, eventually add to a hash table */
+        TLB_Read(&nameoffset, sizeof(INT), pcx, 
+            offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
+        (*pptfd)->Name=TLB_ReadName(pcx, nameoffset);
+    /* read the function information record */
+        TLB_Read(&reclength, sizeof(INT), pcx, recoffset);
+        reclength &=0x1ff;
+        TLB_Read(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ; 
+    /* do the attributes */
+        nrattributes=(reclength-pFuncRec->nrargs*3*sizeof(int)-0x18)
+            /sizeof(int);
+        if(nrattributes>0){
+            (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
+            if(nrattributes>1){
+                (*pptfd)->HelpString = TLB_ReadString(pcx,
+                                                      pFuncRec->OptAttr[1]) ;
+                if(nrattributes>2){
+                    if(pFuncRec->FKCCIC & 0x2000)
+                        (*pptfd)->Entry = (char *) pFuncRec->OptAttr[2] ;
+                    else
+                        (*pptfd)->Entry = TLB_ReadString(pcx,
+                                                         pFuncRec->OptAttr[2]);
+                    if(nrattributes>5 )
+                        (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
+                    if(nrattributes>6 && pFuncRec->FKCCIC & 0x80){
+                        TLB_CustData(pcx, pFuncRec->OptAttr[6],
+                                &(*pptfd)->pCustData);
+                    }
+                }
+            }
+        }
+    /* fill the FuncDesc Structure */
+        TLB_Read(&(*pptfd)->funcdesc.memid, sizeof(INT), pcx, 
+            offset + infolen + ( i + 1) * sizeof(INT));
+        (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
+        (*pptfd)->funcdesc.invkind = ((pFuncRec->FKCCIC) >>3) & 0xF;
+        (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >>8 & 0xF;
+        (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
+        (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
+        (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
+        (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags)  ;
+        TLB_GetTdesc(pcx, pFuncRec->DataType,   
+            &(*pptfd)->funcdesc.elemdescFunc.tdesc) ;
+                                    
+        /* do the parameters/arguments */
+        if(pFuncRec->nrargs){
+            TLBParameterInfo paraminfo;
+            (*pptfd)->funcdesc.lprgelemdescParam=
+                TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
+            (*pptfd)->pParamDesc=TLB_Alloc(pFuncRec->nrargs *
+                sizeof(TLBParDesc));
+
+            TLB_Read(&paraminfo,sizeof(paraminfo), pcx, recoffset+reclength -
+                pFuncRec->nrargs * sizeof(TLBParameterInfo));
+            for(j=0;j<pFuncRec->nrargs;j++){
+                TLB_GetTdesc(pcx, paraminfo.DataType,   
+                    &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc) ;
+                V_UNION(&((*pptfd)->funcdesc.lprgelemdescParam[j]),
+                    paramdesc.wParamFlags) = paraminfo.Flags;
+                (*pptfd)->pParamDesc[j].Name=(void *)paraminfo.oName;
+                TLB_Read(&paraminfo,sizeof(TLBParameterInfo), pcx,
+                        DO_NOT_SEEK);
+            }
+            /* second time around */
+            for(j=0;j<pFuncRec->nrargs;j++){
+                /* name */
+                (*pptfd)->pParamDesc[j].Name=
+                    TLB_ReadName(pcx, (int)(*pptfd)->pParamDesc[j].Name);
+                /* default value */
+                if((PARAMFLAG_FHASDEFAULT & V_UNION(&((*pptfd)->funcdesc.
+                    lprgelemdescParam[j]),paramdesc.wParamFlags)) &&
+                    ((pFuncRec->FKCCIC) & 0x1000)){
+                    INT *pInt=(INT *)((char *)pFuncRec + reclength -
+                        (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
+                    PARAMDESC * pParamDesc= &V_UNION(&((*pptfd)->funcdesc.
+                        lprgelemdescParam[j]),paramdesc);
+                    pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
+                    pParamDesc->pparamdescex->cBytes= sizeof(PARAMDESCEX);
+                    TLB_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue), 
+                        pInt[j], pcx);
+                }
+                /* custom info */
+                if(nrattributes>7+j && pFuncRec->FKCCIC & 0x80)
+                    TLB_CustData(pcx, pFuncRec->OptAttr[7+j],
+									&(*pptfd)->pParamDesc[j].pCustData);
+            }
+        }
+    /* scode is not used: archaic win16 stuff FIXME: right? */
+        (*pptfd)->funcdesc.cScodes = 0 ;
+        (*pptfd)->funcdesc.lprgscode = NULL ;
+        pptfd=&((*pptfd)->next);
+        recoffset += reclength;
+    }
+}
+static void TLB_DoVars(TLBContext *pcx, int cFuncs, int cVars,
+                          int offset, TLBVarDesc ** pptvd)
+{
+    int infolen, nameoffset, reclength;
+    char recbuf[256];
+    TLBVarRecord * pVarRec=(TLBVarRecord *) recbuf;
+    int i;
+    int recoffset;
+    TLB_Read(&infolen,sizeof(INT), pcx, offset);
+    TLB_Read(&recoffset,sizeof(INT), pcx, offset + infolen + 
+        ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
+    recoffset += offset+sizeof(INT);
+    for(i=0;i<cVars;i++){
+        *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
+    /* name, eventually add to a hash table */
+        TLB_Read(&nameoffset, sizeof(INT), pcx, 
+            offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
+        (*pptvd)->Name=TLB_ReadName(pcx, nameoffset);
+    /* read the variable information record */
+        TLB_Read(&reclength, sizeof(INT), pcx, recoffset);
+        reclength &=0xff;
+        TLB_Read(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ; 
+    /* Optional data */
+        if(reclength >(6*sizeof(INT)) )
+            (*pptvd)->HelpContext=pVarRec->HelpContext;
+        if(reclength >(7*sizeof(INT)) )
+            (*pptvd)->HelpString = TLB_ReadString(pcx, pVarRec->oHelpString) ;
+        if(reclength >(8*sizeof(INT)) )
+        if(reclength >(9*sizeof(INT)) )
+            (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
+    /* fill the VarDesc Structure */
+        TLB_Read(&(*pptvd)->vardesc.memid, sizeof(INT), pcx, 
+            offset + infolen + ( i + 1) * sizeof(INT));
+        (*pptvd)->vardesc.varkind = pVarRec->VarKind;
+        (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
+        TLB_GetTdesc(pcx, pVarRec->DataType,    
+            &(*pptvd)->vardesc.elemdescVar.tdesc) ;
+/*   (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) fixme?? */
+        if(pVarRec->VarKind == VAR_CONST ){
+            V_UNION(&((*pptvd)->vardesc),lpvarValue)=TLB_Alloc(sizeof(VARIANT));
+            TLB_ReadValue(V_UNION(&((*pptvd)->vardesc),lpvarValue), 
+                pVarRec->OffsValue, pcx);
+        }else
+            V_UNION(&((*pptvd)->vardesc),oInst)=pVarRec->OffsValue;
+        pptvd=&((*pptvd)->next);
+        recoffset += reclength;
+    }
+}
+/* fill in data for a hreftype (offset). When the refernced type is contained
+ * in the typelib, its just an (file) offset in the type info base dir.
+ * If comes fom import, its an offset+1 in the ImpInfo table
+ * */
+static void TLB_DoRefType(TLBContext *pcx, 
+                          int offset, TLBRefType ** pprtd)
+{
+    int j;
+    if(!HREFTYPE_INTHISFILE( offset)) {
+        /* external typelib */
+        TLBImpInfo impinfo;
+        TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
+        TLB_Read(&impinfo, sizeof(impinfo), pcx, 
+            pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
+        for(j=0;pImpLib;j++){   /* search the known offsets of all import libraries */
+            if(pImpLib->offset==impinfo.oImpFile) break;
+            pImpLib=pImpLib->next;
+        }
+        if(pImpLib){
+            (*pprtd)->reference=offset;
+            (*pprtd)->pImpTLInfo=pImpLib;
+            TLB_ReadGuid(&(*pprtd)->guid, impinfo.oGuid, pcx);
+        }else{
+            ERR( typelib ,"Cannot find a reference\n");
+            (*pprtd)->reference=-1;
+            (*pprtd)->pImpTLInfo=(void *)-1;
+        }
+    }else{
+        /* in this typelib */
+        (*pprtd)->reference=offset;
+        (*pprtd)->pImpTLInfo=(void *)-2;
+    }
+}
+
+/* process Implemented Interfaces of a com class */
+static void TLB_DoImplTypes(TLBContext *pcx, int count,
+                          int offset, TLBRefType ** pprtd)
+{
+    int i;
+    TLBRefRecord refrec;
+    for(i=0;i<count;i++){
+        if(offset<0) break; /* paranoia */
+        *pprtd=TLB_Alloc(sizeof(TLBRefType));
+        TLB_Read(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
+        TLB_DoRefType(pcx, refrec.reftype, pprtd);
+        (*pprtd)->flags=refrec.flags;
+        (*pprtd)->ctCustData=
+            TLB_CustData(pcx, refrec.oCustData, &(*pprtd)->pCustData);
+        offset=refrec.onext;
+        pprtd=&((*pprtd)->next);
+    }
+}
+/*
+ * process a typeinfo record
+ */
+TLBTypeInfo * TLB_DoTypeInfo(TLBContext *pcx, int count, TLBLibInfo* pLibInfo)
+{
+    TLBTypeInfoBase tiBase;
+    TLBTypeInfo *ptiRet;
+    ptiRet=TLB_Alloc(sizeof(TLBTypeInfo));
+    ptiRet->lpvtbl = &tinfvt;
+    ptiRet->ref=1;
+    TLB_Read(&tiBase, sizeof(tiBase) ,pcx ,
+        pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
+/* this where we are coming from */
+    ptiRet->pTypeLib=pLibInfo;
+    ptiRet->index=count;
+/* fill in the typeattr fields */
+    TLB_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
+    ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid;   /* FIXME: correct? */
+    ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
+    ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
+    ptiRet->TypeAttr.lpstrSchema=NULL;              /* reserved */
+    ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
+    ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
+    ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
+    ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
+    ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
+    ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
+    ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
+    ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
+    ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
+    ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
+    if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
+        TLB_GetTdesc(pcx, tiBase.datatype1, 
+            &ptiRet->TypeAttr.tdescAlias) ;
+/*  FIXME: */
+/*    IDLDESC  idldescType; *//* never saw this one != zero  */
+
+/* name, eventually add to a hash table */
+    ptiRet->Name=TLB_ReadName(pcx, tiBase.NameOffset);
+    TRACE( typelib,"reading %s\n", ptiRet->Name);
+    /* help info */
+    ptiRet->DocString=TLB_ReadString(pcx, tiBase.docstringoffs);
+    ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
+    ptiRet->dwHelpContext=tiBase.helpcontext;
+/* note: InfoType's Help file and HelpStringDll come from the containing
+ * library. Further HelpString and Docstring appear to be the same thing :(
+ */
+    /* functions */
+    if(ptiRet->TypeAttr.cFuncs >0 )
+        TLB_DoFuncs(pcx, ptiRet->TypeAttr.cFuncs ,ptiRet->TypeAttr.cVars, 
+        tiBase.memoffset, & ptiRet->funclist);
+    /* variables */
+    if(ptiRet->TypeAttr.cVars >0 )
+        TLB_DoVars(pcx, ptiRet->TypeAttr.cFuncs ,ptiRet->TypeAttr.cVars, 
+        tiBase.memoffset, & ptiRet->varlist);
+    if(ptiRet->TypeAttr.cImplTypes >0 ){
+        if(ptiRet->TypeAttr.typekind == TKIND_COCLASS)
+            TLB_DoImplTypes(pcx, ptiRet->TypeAttr.cImplTypes , 
+                tiBase.datatype1, & ptiRet->impltypelist);
+        else if(ptiRet->TypeAttr.typekind != TKIND_DISPATCH){
+            ptiRet->impltypelist=TLB_Alloc(sizeof(TLBRefType));
+            TLB_DoRefType(pcx, tiBase.datatype1, & ptiRet->impltypelist);
+        }
+	}
+    ptiRet->ctCustData=
+        TLB_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
+    return ptiRet;
+}
+
+
+long TLB_FindTlb(TLBContext *pcx)
+{/* FIXME: should parse the file properly
+  * hack to find our tlb data
+  */
+#define TLBBUFSZ 1024
+    char buff[TLBBUFSZ+1]; /* room for a trailing '\0' */
+    long ret=0;
+    int count;
+    char *pChr;
+	count=TLB_Read(buff, TLBBUFSZ, pcx, 0);
+    do {
+        buff[count]='\0';
+        if((pChr=strstr(buff,TLBMAGIC2))){
+            ret += pChr-buff;
+            break;
+        }
+        ret+=count;
+		count=TLB_Read(buff, TLBBUFSZ, pcx, DO_NOT_SEEK);
+    } while(count>0);
+    if(count)
+        return ret;
+/* try again for the other format */
+    ret=0;
+	count=TLB_Read(buff, TLBBUFSZ, pcx, 0);
+    do {
+        buff[count]='\0';
+        if((pChr=strstr(buff,TLBMAGIC1))){
+            ret += pChr-buff;
+            break;
+        }
+        ret+=count;
+		count=TLB_Read(buff, TLBBUFSZ, pcx, DO_NOT_SEEK);
+    } while(count>0);
+    if(count)
+        ERR(ole,"type library format not (yet) implemented\n");
+    else
+        ERR(ole,"not type library found in this file\n");
+    return -1;
+
+}
+
+int TLB_ReadTypeLib(PCHAR file, ITypeLib **ppTypeLib)
+{
+    TLBContext cx;
+	OFSTRUCT ofStruct;
+    long oStart,lPSegDir;
+    TLBLibInfo* pLibInfo=NULL;
+    TLB2Header tlbHeader;
+    TLBSegDir tlbSegDir;
+	if((cx.hFile=(HANDLE)OpenFile(file, &ofStruct, OF_READWRITE))
+		==(HANDLE)HFILE_ERROR){
+		ERR( typelib,"cannot open %s error 0x%lx\n",file, GetLastError());
+		exit(1);
+	}
+    /* get pointer to beginning of typelib data */
+    if((oStart=TLB_FindTlb(&cx))<0){
+        if(oStart==-1)
+            ERR( typelib,"cannot locate typelib in  %s\n",file);
+        else
+            ERR( typelib,"unsupported typelib format in  %s\n",file);
+        exit(1);
+    }
+    cx.oStart=oStart;
+    if((pLibInfo=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
+									sizeof(TLBLibInfo)))==NULL){
+		CloseHandle(cx.hFile);
+        return E_OUTOFMEMORY;
+    }
+    pLibInfo->lpvtbl = &tlbvt;
+    pLibInfo->ref=1;
+    cx.pLibInfo=pLibInfo;
+    /* read header */
+    TLB_Read((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
+    /* there is a small number of information here until the next important
+     * part:
+     * the segment directory . Try to calculate the amount of data */
+    lPSegDir=sizeof(tlbHeader)+
+            (tlbHeader.nrtypeinfos)*4+
+            (tlbHeader.varflags & HELPDLLFLAG? 4 :0);
+    /* now read the segment directory */
+    TLB_Read((void*)&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);  
+    cx.pTblDir=&tlbSegDir;
+    /* just check two entries */
+    if(tlbSegDir.pTypeInfoTab.res0c != 0x0F ||
+					tlbSegDir.pImpInfo.res0c != 0x0F){
+        ERR( typelib,"cannot find the table directory, ptr=0x%lx\n",lPSegDir);
+    }
+    /* now fill our internal data */
+    /* TLIBATTR fields */
+    TLB_ReadGuid(&pLibInfo->LibAttr.guid, tlbHeader.posguid, &cx);
+    pLibInfo->LibAttr.lcid=tlbHeader.lcid;
+    pLibInfo->LibAttr.syskind=tlbHeader.varflags & 0x0f; /* check the mask */
+    pLibInfo->LibAttr.wMajorVerNum=LOWORD(tlbHeader.version);
+    pLibInfo->LibAttr.wMinorVerNum=HIWORD(tlbHeader.version);
+    pLibInfo->LibAttr.wLibFlags=(WORD) tlbHeader.flags & 0xffff;/* check mask */
+    /* name, eventually add to a hash table */
+    pLibInfo->Name=TLB_ReadName(&cx, tlbHeader.NameOffset);
+    /* help info */
+    pLibInfo->DocString=TLB_ReadString(&cx, tlbHeader.helpstring);
+    pLibInfo->HelpFile=TLB_ReadString(&cx, tlbHeader.helpfile);
+    if( tlbHeader.varflags & HELPDLLFLAG){
+            int offset;
+            TLB_Read(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
+            pLibInfo->HelpStringDll=TLB_ReadString(&cx, offset);
+    }
+
+    pLibInfo->dwHelpContext=tlbHeader.helpstringcontext;
+    /* custom data */
+    if(tlbHeader.CustomDataOffset >= 0) {
+        pLibInfo->ctCustData=
+            TLB_CustData(&cx, tlbHeader.CustomDataOffset, &pLibInfo->pCustData);
+    }
+    /* fill in typedescriptions */
+    if(tlbSegDir.pTypdescTab.length >0){
+        int i, j, cTD=tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
+        INT16 td[4];
+        pLibInfo->pTypeDesc=
+            TLB_Alloc( cTD * sizeof(TYPEDESC));
+        TLB_Read(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
+        for(i=0;i<cTD;){
+            /* FIXME: add several sanity checks here */
+            pLibInfo->pTypeDesc[i].vt=td[0] & VT_TYPEMASK;
+            if(td[0]==VT_PTR ||td[0]==VT_SAFEARRAY){/* FIXME: check safearray */
+                if(td[3]<0)
+                    V_UNION(&(pLibInfo->pTypeDesc[i]),lptdesc)=
+                        & stndTypeDesc[td[2]];
+                else
+                    V_UNION(&(pLibInfo->pTypeDesc[i]),lptdesc)=
+                        & pLibInfo->pTypeDesc[td[3]/8];
+            }else if(td[0]==VT_CARRAY)
+                V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)=
+                    (void *)((int) td[2]);  /* temp store offset in*/
+                                            /* array descr table here */
+            else if(td[0]==VT_USERDEFINED)
+                V_UNION(&(pLibInfo->pTypeDesc[i]),hreftype)=MAKELONG(td[2],td[3]);
+            if(++i<cTD) TLB_Read(td, sizeof(td), &cx, DO_NOT_SEEK);
+        }
+        /* second time around to fill the array subscript info */
+        for(i=0;i<cTD;i++){
+            if(pLibInfo->pTypeDesc[i].vt != VT_CARRAY) continue;
+            if(tlbSegDir.pArrayDescriptions.offset>0){
+                TLB_Read(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset +
+                    (int) V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc));
+                V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)=
+                    TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
+                if(td[1]<0)
+                    V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)->tdescElem.vt=td[0] & VT_TYPEMASK;
+                else
+                    V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)->tdescElem=stndTypeDesc[td[0]/8];
+                V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)->cDims=td[2];
+                for(j=0;j<td[2];j++){
+                    TLB_Read(& V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)->rgbounds[j].cElements, 
+                        sizeof(INT), &cx, DO_NOT_SEEK);
+                    TLB_Read(& V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)
+                        ->rgbounds[j].lLbound, 
+                        sizeof(INT), &cx, DO_NOT_SEEK);
+                }
+            }else{
+                V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)=NULL;
+                ERR(ole, "didn't find array description data\n");
+            }
+        }
+    }
+    /* imported type libs */
+    if(tlbSegDir.pImpFiles.offset>0){
+        TLBImpLib **ppImpLib=&(pLibInfo->pImpLibs);
+        int offset=tlbSegDir.pImpFiles.offset;
+        int oGuid;
+        UINT16 size;
+        while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length){
+            *ppImpLib=TLB_Alloc(sizeof(TLBImpLib));
+            (*ppImpLib)->offset=offset - tlbSegDir.pImpFiles.offset;
+            TLB_Read(&oGuid, sizeof(INT), &cx, offset);
+            TLB_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
+            /* we are skipping some unknown info here */
+            TLB_Read(& size,sizeof(UINT16), &cx, offset+3*(sizeof(INT)));
+            size >>=2;
+            (*ppImpLib)->name=TLB_Alloc(size+1);
+            TLB_Read((*ppImpLib)->name,size, &cx, DO_NOT_SEEK);
+            offset=(offset+3*(sizeof(INT))+sizeof(UINT16)+size+3) & 0xfffffffc;
+
+            ppImpLib=&(*ppImpLib)->next;
+        }
+    }
+    /* type info's */
+    if(tlbHeader.nrtypeinfos >=0 ){
+        /*pLibInfo->TypeInfoCount=tlbHeader.nrtypeinfos; */
+        TLBTypeInfo **ppTI=&(pLibInfo->pTypeInfo);
+        int i;
+        for(i=0;i<(int)tlbHeader.nrtypeinfos;i++){
+            *ppTI=TLB_DoTypeInfo(&cx, i, pLibInfo);
+            ppTI=&((*ppTI)->next);
+            (pLibInfo->TypeInfoCount)++;
+        }
+    }
+
+    CloseHandle(cx.hFile);
+    *ppTypeLib=(LPTYPELIB)pLibInfo;
+    return S_OK;
+}
+
+/*================== ITypeLib(2) Methods ===================================*/
+
+/* ITypeLib::QueryInterface
+ */
+static HRESULT WINAPI ITypeLib_fnQueryInterface( LPTYPELIB This, REFIID riid,
+    VOID **ppvObject)
+{
+    if(TRACE_ON(typelib)){
+        char xriid[50];
+        WINE_StringFromCLSID((LPCLSID)riid,xriid);
+        TRACE(typelib,"(%p)->(IID: %s)\n",This,xriid);
+    }
+    *ppvObject=NULL;
+    if(IsEqualIID(riid, &IID_IUnknown) || 
+            IsEqualIID(riid,&IID_ITypeLib)||
+            IsEqualIID(riid,&IID_ITypeLib2))
+        *ppvObject = This;
+    if(*ppvObject){
+        (*(LPTYPELIB*)ppvObject)->lpvtbl->fnAddRef(This);
+        TRACE(typelib,"-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
+        return S_OK;
+    }
+    TRACE(typelib,"-- Interface: E_NOINTERFACE\n");
+    return E_NOINTERFACE;
+}
+
+/* ITypeLib::AddRef
+ */
+static ULONG WINAPI ITypeLib_fnAddRef( LPTYPELIB iface)
+{
+	ICOM_THIS( TLBLibInfo, iface);
+    TRACE(typelib,"(%p)->ref is %u\n",This, This->ref);
+    return ++(This->ref);
+}
+
+/* ITypeLib::Release
+ */
+static ULONG WINAPI ITypeLib_fnRelease( LPTYPELIB iface)
+{
+	ICOM_THIS( TLBLibInfo, iface);
+    FIXME(typelib,"(%p)->ref is %u:   stub\n",This, This->ref);
+    (This->ref)--;
+    return S_OK;
+}
+
+/* ITypeLib::GetTypeInfoCount
+ * 
+ * Returns the number of type descriptions in the type library
+ */
+static UINT WINAPI ITypeLib_fnGetTypeInfoCount( LPTYPELIB iface)
+{
+	ICOM_THIS( TLBLibInfo, iface);
+    TRACE(typelib,"(%p)->count is %d\n",This, This->TypeInfoCount);
+    return This->TypeInfoCount;
+}
+
+/* ITypeLib::GetTypeInfo
+ *
+ *etrieves the specified type description in the library.
+ */
+static HRESULT WINAPI ITypeLib_fnGetTypeInfo( LPTYPELIB iface, UINT index, 
+    ITypeInfo **ppTInfo)
+{
+    int i;
+	ICOM_THIS( TLBLibInfo, iface);
+	TLBTypeInfo **ppTLBTInfo=(TLBTypeInfo **)ppTInfo;
+    TRACE(typelib,"(%p) index %d \n",This, index);
+    for(i=0,*ppTLBTInfo=This->pTypeInfo;*ppTLBTInfo && i != index;i++)
+        *ppTLBTInfo=(*ppTLBTInfo)->next;
+    if(*ppTLBTInfo){
+        (*ppTLBTInfo)->lpvtbl->fnAddRef(*ppTInfo);
+        TRACE(typelib,"-- found (%p)->(%p)\n",ppTLBTInfo,*ppTLBTInfo);
+        return S_OK;
+    }
+    TRACE(typelib,"-- element not found\n");
+    return TYPE_E_ELEMENTNOTFOUND;
+}
+
+/* ITypeLibs::GetTypeInfoType
+ *
+ * Retrieves the type of a type description.
+ */
+static HRESULT WINAPI ITypeLib_fnGetTypeInfoType( LPTYPELIB iface, UINT index,
+    TYPEKIND *pTKind)
+{
+    int i;
+    TLBTypeInfo *pTInfo;
+	ICOM_THIS( TLBLibInfo, iface);
+    TRACE(typelib,"(%p) index %d \n",This, index);
+    for(i=0,pTInfo=This->pTypeInfo;pTInfo && i != index;i++)
+        pTInfo=(pTInfo)->next;
+    if(pTInfo){
+        *pTKind=pTInfo->TypeAttr.typekind;
+        TRACE(typelib,"-- found Type (%p)->%d\n",pTKind,*pTKind);
+        return S_OK;
+    }
+    TRACE(typelib,"-- element not found\n");
+    return TYPE_E_ELEMENTNOTFOUND;
+}
+
+/* ITypeLib::GetTypeInfoOfGuid
+ *
+ * Retrieves the type description that corresponds to the specified GUID.
+ *
+ */
+static HRESULT WINAPI ITypeLib_fnGetTypeInfoOfGuid( LPTYPELIB iface,
+				REFGUID guid, ITypeInfo **ppTInfo)
+{
+    int i;
+	ICOM_THIS( TLBLibInfo, iface);
+	TLBTypeInfo **ppTLBTInfo=(TLBTypeInfo **)ppTInfo;
+    if(TRACE_ON(typelib)){
+        char xriid[50];
+        WINE_StringFromCLSID((LPCLSID)guid,xriid);
+        TRACE(typelib,"(%p) guid %sx)\n",This,xriid);
+    }
+    for(i=0,*ppTLBTInfo=This->pTypeInfo;*ppTLBTInfo && 
+            !IsEqualIID(guid,&(*ppTLBTInfo)->TypeAttr.guid);i++)
+        *ppTLBTInfo=(*ppTLBTInfo)->next;
+    if(*ppTLBTInfo){
+        (*ppTLBTInfo)->lpvtbl->fnAddRef(*ppTInfo);
+        TRACE(typelib,"-- found (%p)->(%p)\n",ppTLBTInfo,*ppTLBTInfo);
+        return S_OK;
+    }
+    TRACE(typelib,"-- element not found\n");
+    return TYPE_E_ELEMENTNOTFOUND;
+}
+
+/* ITypeLib::GetLibAttr
+ *
+ * Retrieves the structure that contains the library's attributes.
+ *
+ */
+static HRESULT WINAPI ITypeLib_fnGetLibAttr( LPTYPELIB iface, 
+    LPTLIBATTR *ppTLibAttr)
+{
+	ICOM_THIS( TLBLibInfo, iface);
+    TRACE( typelib,"(%p)\n",This);
+    /* FIXME: must do a copy here */
+    *ppTLibAttr=&This->LibAttr;
+    return S_OK;
+}
+
+/* ITypeLib::GetTypeComp
+ *
+ * Enables a client compiler to bind to a library's types, variables,
+ * constants, and global functions.
+ *
+ */
+static HRESULT WINAPI ITypeLib_fnGetTypeComp( LPTYPELIB iface,
+    ITypeComp **ppTComp)
+{
+	ICOM_THIS( TLBLibInfo, iface);
+    FIXME(typelib,"(%p): stub!\n",This);
+    return E_NOTIMPL;
+}
+
+/* ITypeLib::GetDocumentation
+ *
+ * Retrieves the library's documentation string, the complete Help file name
+ * and path, and the context identifier for the library Help topic in the Help
+ * file.
+ *
+ */
+static HRESULT WINAPI ITypeLib_fnGetDocumentation( LPTYPELIB iface, INT index,
+    BSTR *pBstrName, BSTR *pBstrDocString, DWORD *pdwHelpContext, 
+    BSTR *pBstrHelpFile)
+{
+	ICOM_THIS( TLBLibInfo, iface);
+    HRESULT result;
+    ITypeInfo *pTInfo;
+    TRACE( typelib, "(%p) index %d Name(%p) DocString(%p)"
+           " HelpContext(%p) HelpFile(%p)\n",
+        This, index, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
+    if(index<0){ /* documentation for the typelib */
+        if(pBstrName)
+            *pBstrName=TLB_DupAtoBstr(This->Name);
+        if(pBstrDocString)
+            *pBstrName=TLB_DupAtoBstr(This->DocString);
+        if(pdwHelpContext)
+            *pdwHelpContext=This->dwHelpContext;
+        if(pBstrHelpFile)
+            *pBstrName=TLB_DupAtoBstr(This->HelpFile);
+    }else {/* for a typeinfo */
+        result=ITypeLib_fnGetTypeInfo(iface, index, &pTInfo);
+        if(SUCCEEDED(result)){
+            result=ITypeInfo_GetDocumentation(pTInfo, MEMBERID_NIL,  pBstrName,
+                pBstrDocString, pdwHelpContext, pBstrHelpFile);
+            ITypeInfo_Release(pTInfo);
+        }
+        if(!SUCCEEDED(result))
+            return result;
+    }
+    return S_OK;
+}
+
+/* ITypeLib::IsName
+ *
+ * Indicates whether a passed-in string contains the name of a type or member
+ * described in the library.
+ *
+ */
+static HRESULT WINAPI ITypeLib_fnIsName( LPTYPELIB iface, LPOLESTR szNameBuf,
+    ULONG lHashVal, BOOL *pfName)
+{
+	ICOM_THIS( TLBLibInfo, iface);
+    TLBTypeInfo *pTInfo;
+    TLBFuncDesc *pFInfo;
+    TLBVarDesc *pVInfo;
+    int i;
+    PCHAR astr= HEAP_strdupWtoA( GetProcessHeap(), 0, szNameBuf );
+    *pfName=TRUE;
+    if(!strcmp(astr,This->Name)) goto ITypeLib_fnIsName_exit;
+    for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
+        if(!strcmp(astr,pTInfo->Name)) goto ITypeLib_fnIsName_exit;
+        for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
+            if(!strcmp(astr,pFInfo->Name)) goto ITypeLib_fnIsName_exit;
+            for(i=0;i<pFInfo->funcdesc.cParams;i++)
+                if(!strcmp(astr,pFInfo->pParamDesc[i].Name))
+                    goto ITypeLib_fnIsName_exit;
+        }
+        for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next) ;
+            if(!strcmp(astr,pVInfo->Name)) goto ITypeLib_fnIsName_exit;
+       
+    }
+    *pfName=FALSE;
+
+ITypeLib_fnIsName_exit:
+    TRACE( typelib,"(%p)slow! search for %s: %s found!\n", This,
+            debugstr_a(astr), *pfName?"NOT":"");
+    
+    HeapFree( GetProcessHeap(), 0, astr );
+    return S_OK;
+}
+
+/* ITypeLib::FindName
+ *
+ * Finds occurrences of a type description in a type library. This may be used
+ * to quickly verify that a name exists in a type library.
+ *
+ */
+static HRESULT WINAPI ITypeLib_fnFindName( LPTYPELIB iface, LPOLESTR szNameBuf,
+    ULONG lHashVal, ITypeInfo **ppTInfo, MEMBERID *rgMemId, UINT16 *pcFound)
+{
+	ICOM_THIS( TLBLibInfo, iface);
+    TLBTypeInfo *pTInfo;
+    TLBFuncDesc *pFInfo;
+    TLBVarDesc *pVInfo;
+    int i,j = 0;
+    PCHAR astr= HEAP_strdupWtoA( GetProcessHeap(), 0, szNameBuf );
+    for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
+        if(!strcmp(astr,pTInfo->Name)) goto ITypeLib_fnFindName_exit;
+        for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
+            if(!strcmp(astr,pFInfo->Name)) goto ITypeLib_fnFindName_exit;
+            for(i=0;i<pFInfo->funcdesc.cParams;i++)
+                if(!strcmp(astr,pFInfo->pParamDesc[i].Name))
+                    goto ITypeLib_fnFindName_exit;
+        }
+        for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next) ;
+            if(!strcmp(astr,pVInfo->Name)) goto ITypeLib_fnFindName_exit;
+        continue;
+ITypeLib_fnFindName_exit:
+        pTInfo->lpvtbl->fnAddRef((LPTYPEINFO)pTInfo);
+        ppTInfo[j]=(LPTYPEINFO)pTInfo;
+        j++;
+    }
+    TRACE( typelib,"(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
+            This, *pcFound, debugstr_a(astr), j);
+
+    *pcFound=j;
+    
+    HeapFree( GetProcessHeap(), 0, astr );
+    return S_OK;
+}
+
+/* ITypeLib::ReleaseTLibAttr
+ *
+ * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
+ *
+ */
+static VOID WINAPI ITypeLib_fnReleaseTLibAttr( LPTYPELIB iface, TLIBATTR *pTLibAttr)
+{
+	ICOM_THIS( TLBLibInfo, iface);
+    TRACE( typelib,"freeing (%p)\n",This);
+    /* nothing to do */
+}
+
+/* ITypeLib2::GetCustData
+ *
+ * gets the custom data
+ */
+static HRESULT WINAPI ITypeLib2_fnGetCustData( ITypeLib * iface, REFGUID guid, 
+        VARIANT *pVarVal)
+{
+	ICOM_THIS( TLBLibInfo, iface);
+    TLBCustData *pCData;
+    for(pCData=This->pCustData; pCData; pCData = pCData->next)
+        if( IsEqualIID(guid, &pCData->guid)) break;
+    if(TRACE_ON(typelib)){
+        char xriid[50];
+        WINE_StringFromCLSID((LPCLSID)guid,xriid);
+        TRACE(typelib,"(%p) guid %s %s found!x)\n",This,xriid,
+                pCData? "" : "NOT");
+    }
+    if(pCData){
+        VariantInit( pVarVal);
+        VariantCopy( pVarVal, &pCData->data);
+        return S_OK;
+    }
+    return E_INVALIDARG;  /* FIXME: correct? */
+}
+
+/* ITypeLib2::GetLibStatistics
+ *
+ * Returns statistics about a type library that are required for efficient
+ * sizing of hash tables.
+ *
+ */
+static HRESULT WINAPI ITypeLib2_fnGetLibStatistics( ITypeLib * iface, 
+        UINT *pcUniqueNames, UINT *pcchUniqueNames)
+{
+	ICOM_THIS( TLBLibInfo, iface);
+    FIXME( typelib,"(%p): stub!\n", This);
+    if(pcUniqueNames) *pcUniqueNames=1;
+    if(pcchUniqueNames) *pcchUniqueNames=1;
+    return S_OK;
+}
+
+/* ITypeLib2::GetDocumentation2
+ *
+ * Retrieves the library's documentation string, the complete Help file name
+ * and path, the localization context to use, and the context ID for the
+ * library Help topic in the Help file.
+ *
+ */
+static HRESULT WINAPI ITypeLib2_fnGetDocumentation2( ITypeLib * iface, 
+        INT index, LCID lcid, BSTR *pbstrHelpString,
+        INT *pdwHelpStringContext, BSTR *pbstrHelpStringDll)
+{
+	ICOM_THIS( TLBLibInfo, iface);
+    HRESULT result;
+    ITypeInfo *pTInfo;
+    FIXME( typelib,"(%p) index %d lcid %ld half implemented stub!\n", This,
+            index, lcid);
+    /* the help string should be obtained from the helpstringdll,
+     * using the _DLLGetDocumentation function, based on the supplied
+     * lcid. Nice to do sometime...
+     */
+    if(index<0){ /* documentation for the typelib */
+        if(pbstrHelpString)
+            *pbstrHelpString=TLB_DupAtoBstr(This->DocString);
+        if(pdwHelpStringContext)
+            *pdwHelpStringContext=This->dwHelpContext;
+        if(pbstrHelpStringDll)
+            *pbstrHelpStringDll=TLB_DupAtoBstr(This->HelpStringDll);
+    }else {/* for a typeinfo */
+        result=ITypeLib_fnGetTypeInfo(iface, index, &pTInfo);
+        if(SUCCEEDED(result)){
+            result=ITypeInfo2_fnGetDocumentation2(pTInfo, MEMBERID_NIL, lcid,
+                pbstrHelpString, pdwHelpStringContext, pbstrHelpStringDll);
+            ITypeInfo_Release(pTInfo);
+        }
+        if(!SUCCEEDED(result))
+            return result;
+    }
+    return S_OK;
+}
+
+/* ITypeLib2::GetAllCustData
+ *
+ * Gets all custom data items for the library. 
+ *
+ */
+static HRESULT WINAPI ITypeLib2_fnGetAllCustData( ITypeLib * iface,
+        CUSTDATA *pCustData)
+{
+	ICOM_THIS( TLBLibInfo, iface);
+    TLBCustData *pCData;
+    int i;
+    TRACE( typelib,"(%p) returning %d items\n", This, This->ctCustData); 
+    pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
+    if(pCustData->prgCustData ){
+        pCustData->cCustData=This->ctCustData;
+        for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
+            pCustData->prgCustData[i].guid=pCData->guid;
+            VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
+        }
+    }else{
+        ERR( typelib," OUT OF MEMORY! \n");
+        return E_OUTOFMEMORY;
+    }
+    return S_OK;
+}
+
+
+/*================== ITypeInfo(2) Methods ===================================*/
+
+/* ITypeInfo::QueryInterface
+ */
+static HRESULT WINAPI ITypeInfo_fnQueryInterface( LPTYPEINFO iface, REFIID riid,
+    VOID **ppvObject)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    if(TRACE_ON(typelib)){
+        char xriid[50];
+        WINE_StringFromCLSID((LPCLSID)riid,xriid);
+        TRACE(typelib,"(%p)->(IID: %s)\n",This,xriid);
+    }
+    *ppvObject=NULL;
+    if(IsEqualIID(riid, &IID_IUnknown) || 
+            IsEqualIID(riid,&IID_ITypeInfo)||
+            IsEqualIID(riid,&IID_ITypeInfo2))
+        *ppvObject = This;
+    if(*ppvObject){
+        (*(LPTYPEINFO*)ppvObject)->lpvtbl->fnAddRef(iface);
+        TRACE(typelib,"-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
+        return S_OK;
+    }
+    TRACE(typelib,"-- Interface: E_NOINTERFACE\n");
+    return E_NOINTERFACE;
+}
+
+/* ITypeInfo::AddRef
+ */
+static ULONG WINAPI ITypeInfo_fnAddRef( LPTYPEINFO iface)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    TRACE(typelib,"(%p)->ref is %u\n",This, This->ref);
+    (This->pTypeLib->ref)++;
+    return ++(This->ref);
+}
+
+/* ITypeInfo::Release
+ */
+static ULONG WINAPI ITypeInfo_fnRelease( LPTYPEINFO iface)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    FIXME(typelib,"(%p)->ref is %u:   stub\n",This, This->ref);
+    (This->ref)--;
+    (This->pTypeLib->ref)--;
+    return S_OK;
+}
+
+/* ITypeInfo::GetTypeAttr
+ *
+ * Retrieves a TYPEATTR structure that contains the attributes of the type
+ * description.
+ *
+ */
+static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( LPTYPEINFO iface,
+        LPTYPEATTR  *ppTypeAttr)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+     TRACE( typelib,"(%p)\n",This);
+    /* FIXME: must do a copy here */
+    *ppTypeAttr=&This->TypeAttr;
+    return S_OK;
+}
+
+/* ITypeInfo::GetTypeComp
+ *
+ * Retrieves the ITypeComp interface for the type description, which enables a
+ * client compiler to bind to the type description's members.
+ *
+ */
+static HRESULT WINAPI ITypeInfo_fnGetTypeComp( LPTYPEINFO iface,
+        ITypeComp  * *ppTComp)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    FIXME( typelib,"(%p) stub!\n", This);
+    return S_OK;
+}
+
+/* ITypeInfo::GetFuncDesc
+ *
+ * Retrieves the FUNCDESC structure that contains information about a
+ * specified function.
+ *
+ */
+static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( LPTYPEINFO iface, UINT index,
+        LPFUNCDESC  *ppFuncDesc)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    int i;
+    TLBFuncDesc * pFDesc; 
+    TRACE( typelib,"(%p) index %d\n", This, index);
+    for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
+        ;
+    if(pFDesc){
+        /* FIXME: must do a copy here */
+        *ppFuncDesc=&pFDesc->funcdesc;
+        return S_OK;
+    }
+    return E_INVALIDARG;
+}
+
+/* ITypeInfo::GetVarDesc
+ *
+ * Retrieves a VARDESC structure that describes the specified variable. 
+ *
+ */
+static HRESULT WINAPI ITypeInfo_fnGetVarDesc( LPTYPEINFO iface, UINT index,
+        LPVARDESC  *ppVarDesc)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    int i;
+    TLBVarDesc * pVDesc; 
+    TRACE( typelib,"(%p) index %d\n", This, index);
+    for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
+        ;
+    if(pVDesc){
+        /* FIXME: must do a copy here */
+        *ppVarDesc=&pVDesc->vardesc;
+        return S_OK;
+    }
+    return E_INVALIDARG;
+}
+
+/* ITypeInfo_GetNames
+ *
+ * Retrieves the variable with the specified member ID (or the name of the
+ * property or method and its parameters) that correspond to the specified
+ * function ID.
+ */
+static HRESULT WINAPI ITypeInfo_fnGetNames( LPTYPEINFO iface, MEMBERID memid,
+        BSTR  *rgBstrNames, UINT cMaxNames, UINT  *pcNames)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    TLBFuncDesc * pFDesc; 
+    TLBVarDesc * pVDesc; 
+    int i;
+    TRACE( typelib,"(%p) memid=0x%08lx Maxname=%d\n", This, memid,
+            cMaxNames);
+    for(pFDesc=This->funclist; pFDesc->funcdesc.memid != memid && pFDesc;
+            pFDesc=pFDesc->next)
+        ;
+    if(pFDesc){
+        /* function found, now return function and parameter names */
+        for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++){
+            if(!i) *rgBstrNames=TLB_DupAtoBstr(pFDesc->Name);
+            else
+                rgBstrNames[i]=TLB_DupAtoBstr(pFDesc->pParamDesc[i-1].Name);
+                
+        }
+        *pcNames=i;
+    }else{
+        for(pVDesc=This->varlist; pVDesc->vardesc.memid != memid && pVDesc;
+                pVDesc=pVDesc->next)
+            ;
+        if(pVDesc){
+            *rgBstrNames=TLB_DupAtoBstr(pFDesc->Name);
+            *pcNames=1;
+        }else{
+            if(This->TypeAttr.typekind==TKIND_INTERFACE && 
+                    This->TypeAttr.cImplTypes ){
+                /* recursive search */
+                ITypeInfo *pTInfo;
+                HRESULT result;
+                result=This->lpvtbl->fnGetRefTypeInfo(iface, 
+                        This->impltypelist->reference, &pTInfo);
+                if(SUCCEEDED(result)){
+                    result=pTInfo->lpvtbl->fnGetNames(pTInfo, memid, rgBstrNames,
+                            cMaxNames, pcNames);
+                    pTInfo->lpvtbl->fnRelease(pTInfo);
+                    return result;
+                }
+                WARN( typelib,"Could not search inherited interface!\n");
+            } else
+                WARN( typelib,"no names found\n");
+            *pcNames=0;
+            return TYPE_E_ELEMENTNOTFOUND;
+        }
+    }
+    return S_OK;
+}
+
+
+/* ITypeInfo::GetRefTypeOfImplType
+ *
+ * If a type description describes a COM class, it retrieves the type
+ * description of the implemented interface types. For an interface,
+ * GetRefTypeOfImplType returns the type information for inherited interfaces,
+ * if any exist.
+ *
+ */
+static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType( LPTYPEINFO iface,
+        UINT index, HREFTYPE  *pRefType)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    int(i);
+    TLBRefType *pIref;
+    TRACE( typelib,"(%p) index %d\n", This, index);
+    for(i=0, pIref=This->impltypelist; i<index && pIref;
+            i++, pIref=pIref->next)
+        ;
+    if(i==index){
+        *pRefType=pIref->reference;
+        return S_OK;
+    }
+    return TYPE_E_ELEMENTNOTFOUND;
+}
+
+/* ITypeInfo::GetImplTypeFlags
+ * 
+ * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface 
+ * or base interface in a type description.
+ */
+static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( LPTYPEINFO iface,
+        UINT index, INT  *pImplTypeFlags)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    int(i);
+    TLBRefType *pIref;
+    TRACE( typelib,"(%p) index %d\n", This, index);
+    for(i=0, pIref=This->impltypelist; i<index && pIref; i++, pIref=pIref->next)
+        ;
+    if(i==index && pIref){
+        *pImplTypeFlags=pIref->flags;
+        return S_OK;
+    }
+    *pImplTypeFlags=0;
+    return TYPE_E_ELEMENTNOTFOUND;
+}
+
+/* GetIDsOfNames
+ * Maps between member names and member IDs, and parameter names and
+ * parameter IDs.
+ */
+static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( LPTYPEINFO iface,
+        LPOLESTR  *rgszNames, UINT cNames, MEMBERID  *pMemId)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    TLBFuncDesc * pFDesc; 
+    TLBVarDesc * pVDesc; 
+    HRESULT ret=S_OK;
+    PCHAR aszName= HEAP_strdupWtoA( GetProcessHeap(), 0, *rgszNames);
+    TRACE( typelib,"(%p) Name %s cNames %d\n", This, debugstr_a(aszName),
+            cNames);
+    for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
+        int i, j;
+        if( !strcmp(aszName, pFDesc->Name)) {
+            if(cNames) *pMemId=pFDesc->funcdesc.memid;
+            for(i=1; i < cNames; i++){
+                PCHAR aszPar= HEAP_strdupWtoA( GetProcessHeap(), 0,
+                        rgszNames[i]);
+                for(j=0; j<pFDesc->funcdesc.cParams; j++)
+                    if(strcmp(aszPar,pFDesc->pParamDesc[j].Name))
+                            break;
+                if( j<pFDesc->funcdesc.cParams)
+                    pMemId[i]=j;
+                else
+                   ret=DISP_E_UNKNOWNNAME;
+                HeapFree( GetProcessHeap(), 0, aszPar);         
+            };
+            HeapFree (GetProcessHeap(), 0, aszName);
+            return ret;
+        }
+    }   
+    for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
+        if( !strcmp(aszName, pVDesc->Name)) {
+            if(cNames) *pMemId=pVDesc->vardesc.memid;
+            HeapFree (GetProcessHeap(), 0, aszName);
+            return ret;
+        }
+    }
+    /* not found, see if this is and interface with an inheritance */       
+    if(This->TypeAttr.typekind==TKIND_INTERFACE && 
+            This->TypeAttr.cImplTypes ){
+        /* recursive search */
+        ITypeInfo *pTInfo;
+        ret=This->lpvtbl->fnGetRefTypeInfo(iface, 
+                This->impltypelist->reference, &pTInfo);
+        if(SUCCEEDED(ret)){
+            ret=pTInfo->lpvtbl->fnGetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
+            pTInfo->lpvtbl->fnRelease(pTInfo);
+            return ret;
+        }
+        WARN( typelib,"Could not search inherited interface!\n");
+    } else
+        WARN( typelib,"no names found\n");
+    return DISP_E_UNKNOWNNAME;
+}
+
+/* ITypeInfo::Invoke
+ * 
+ * Invokes a method, or accesses a property of an object, that implements the
+ * interface described by the type description.
+ */
+static HRESULT WINAPI ITypeInfo_fnInvoke( LPTYPEINFO iface, VOID  *pIUnk,
+        MEMBERID memid, UINT16 dwFlags, DISPPARAMS  *pDispParams,
+        VARIANT  *pVarResult, EXCEPINFO  *pExcepInfo, UINT  *pArgErr)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    FIXME( typelib,"(%p) stub!", This);
+    return S_OK;
+}
+
+/* ITypeInfo::GetDocumentation
+ * 
+ * Retrieves the documentation string, the complete Help file name and path,
+ * and the context ID for the Help topic for a specified type description.
+ */
+static HRESULT WINAPI ITypeInfo_fnGetDocumentation( LPTYPEINFO iface,
+        MEMBERID memid, BSTR  *pBstrName, BSTR  *pBstrDocString,
+        DWORD  *pdwHelpContext, BSTR  *pBstrHelpFile)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    TLBFuncDesc * pFDesc; 
+    TLBVarDesc * pVDesc; 
+    TRACE( typelib, "(%p) memid %ld Name(%p) DocString(%p)"
+           " HelpContext(%p) HelpFile(%p)\n",
+        This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
+    if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
+        if(pBstrName)
+            *pBstrName=TLB_DupAtoBstr(This->Name);
+        if(pBstrDocString)
+            *pBstrDocString=TLB_DupAtoBstr(This->DocString);
+        if(pdwHelpContext)
+            *pdwHelpContext=This->dwHelpContext;
+        if(pBstrHelpFile)
+            *pBstrHelpFile=TLB_DupAtoBstr(This->DocString);/* FIXME */
+        return S_OK;
+    }else {/* for a member */
+    for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
+        if(pFDesc->funcdesc.memid==memid){
+            return S_OK;
+        }
+    for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
+        if(pVDesc->vardesc.memid==memid){
+            return S_OK;
+        }
+    }
+    return TYPE_E_ELEMENTNOTFOUND;
+}
+
+/*  ITypeInfo::GetDllEntry
+ * 
+ * Retrieves a description or specification of an entry point for a function
+ * in a DLL.
+ */
+static HRESULT WINAPI ITypeInfo_fnGetDllEntry( LPTYPEINFO iface, MEMBERID memid,
+        INVOKEKIND invKind, BSTR  *pBstrDllName, BSTR  *pBstrName,
+        WORD  *pwOrdinal)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    FIXME( typelib,"(%p) stub!\n", This);
+    return E_FAIL;
+}
+
+/* ITypeInfo::GetRefTypeInfo
+ * 
+ * If a type description references other type descriptions, it retrieves
+ * the referenced type descriptions.
+ */
+static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo( LPTYPEINFO iface,
+        HREFTYPE hRefType, ITypeInfo  * *ppTInfo)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    HRESULT result;
+    if(HREFTYPE_INTHISFILE(hRefType)){
+        ITypeLib *pTLib;
+        int Index;
+        result=This->lpvtbl->fnGetContainingTypeLib(iface, &pTLib, 
+                &Index);
+        if(SUCCEEDED(result)){
+            result=pTLib->lpvtbl->fnGetTypeInfo(pTLib,
+                    HREFTYPE_INDEX(hRefType),
+                    ppTInfo);
+            pTLib->lpvtbl->fnRelease(pTLib );
+        }
+    } else{
+        /* imported type lib */
+        TLBRefType * pRefType;
+        TLBLibInfo *pTypeLib;
+        for( pRefType=This->impltypelist; pRefType &&
+                pRefType->reference != hRefType; pRefType=pRefType->next)
+            ;
+        if(!pRefType)
+            return TYPE_E_ELEMENTNOTFOUND; //FIXME : correct?
+        pTypeLib=pRefType->pImpTLInfo->pImpTypeLib;
+        if(pTypeLib) //  typelib already loaded
+            result=pTypeLib->lpvtbl->fnGetTypeInfoOfGuid(
+                    (LPTYPELIB)pTypeLib, &pRefType->guid, ppTInfo);
+        else{
+            result=LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
+                    0,0,0, /* FIXME */
+                    (LPTYPELIB *)&pTypeLib);
+            if(!SUCCEEDED(result)){
+                BSTR libnam=TLB_DupAtoBstr(pRefType->pImpTLInfo->name);
+                result=LoadTypeLib(libnam, (LPTYPELIB *)&pTypeLib);
+                SysFreeString(libnam);
+            }
+            if(SUCCEEDED(result)){
+                result=pTypeLib->lpvtbl->fnGetTypeInfoOfGuid(
+                        (LPTYPELIB)pTypeLib, &pRefType->guid, ppTInfo);
+                pRefType->pImpTLInfo->pImpTypeLib=pTypeLib;
+           }
+        }
+    }
+    TRACE( typelib,"(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
+            SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
+    return result;
+}
+
+/* ITypeInfo::AddressOfMember
+ * 
+ * Retrieves the addresses of static functions or variables, such as those
+ * defined in a DLL.
+ */
+static HRESULT WINAPI ITypeInfo_fnAddressOfMember( LPTYPEINFO iface,
+        MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    FIXME( typelib,"(%p) stub!\n", This);
+    return S_OK;
+}
+
+/* ITypeInfo::CreateInstance
+ * 
+ * Creates a new instance of a type that describes a component object class 
+ * (coclass).
+ */
+static HRESULT WINAPI ITypeInfo_fnCreateInstance( LPTYPEINFO iface, 
+        IUnknown *pUnk, REFIID riid, VOID  **ppvObj) 
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    FIXME( typelib,"(%p) stub!\n", This);
+    return S_OK;
+}
+
+/* ITypeInfo::GetMops
+ *
+ * Retrieves marshaling information.
+ */
+static HRESULT WINAPI ITypeInfo_fnGetMops( LPTYPEINFO iface, MEMBERID memid,
+				BSTR  *pBstrMops)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    FIXME( typelib,"(%p) stub!\n", This);
+    return S_OK;
+}
+
+/* ITypeInfo::GetContainingTypeLib
+ * 
+ * Retrieves the containing type library and the index of the type description
+ * within that type library.
+ */
+static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( LPTYPEINFO iface,
+        ITypeLib  * *ppTLib, UINT  *pIndex)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    *ppTLib=(LPTYPELIB )(This->pTypeLib);
+    *pIndex=This->index;
+    (*ppTLib)->lpvtbl->fnAddRef(*ppTLib);
+    TRACE( typelib,"(%p) returns (%p) index %d!\n", This, *ppTLib, *pIndex);
+    return S_OK;
+}
+
+/* ITypeInfo::ReleaseTypeAttr
+ *
+ * Releases a TYPEATTR previously returned by GetTypeAttr.
+ *
+ */
+static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( LPTYPEINFO iface,
+        TYPEATTR* pTypeAttr)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    TRACE( typelib,"(%p)->(%p)\n", This, pTypeAttr);
+    return S_OK;
+}
+
+/* ITypeInfo::ReleaseFuncDesc
+ *
+ * Releases a FUNCDESC previously returned by GetFuncDesc. *
+ */
+static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc( LPTYPEINFO iface,
+        FUNCDESC *pFuncDesc)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    TRACE( typelib,"(%p)->(%p)\n", This, pFuncDesc);
+    return S_OK;
+}
+
+/* ITypeInfo::ReleaseVarDesc
+ *
+ * Releases a VARDESC previously returned by GetVarDesc.
+ */
+static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( LPTYPEINFO iface,
+        VARDESC *pVarDesc)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    TRACE( typelib,"(%p)->(%p)\n", This, pVarDesc);
+    return S_OK;
+}
+
+/* ITypeInfo2::GetTypeKind
+ *
+ * Returns the TYPEKIND enumeration quickly, without doing any allocations.
+ *
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo * iface,
+    TYPEKIND *pTypeKind)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    *pTypeKind=This->TypeAttr.typekind;
+    TRACE( typelib,"(%p) type 0x%0x\n", This,*pTypeKind);
+    return S_OK;
+}
+
+/* ITypeInfo2::GetTypeFlags
+ *
+ * Returns the type flags without any allocations. This returns a DWORD type
+ * flag, which expands the type flags without growing the TYPEATTR (type
+ * attribute). 
+ *
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo * iface,
+    UINT *pTypeFlags)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    *pTypeFlags=This->TypeAttr.wTypeFlags;
+    TRACE( typelib,"(%p) flags 0x%04x\n", This,*pTypeFlags);
+     return S_OK;
+}
+
+/* ITypeInfo2::GetFuncIndexOfMemId
+ * Binds to a specific member based on a known DISPID, where the member name
+ * is not known (for example, when binding to a default member).
+ *
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo * iface,
+    MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    TLBFuncDesc *pFuncInfo;
+    int i;
+    HRESULT result;
+    /* FIXME: should check for invKind??? */
+    for(i=0, pFuncInfo=This->funclist;pFuncInfo && 
+            memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
+    if(pFuncInfo){
+        *pFuncIndex=i;
+        result= S_OK;
+    }else{
+        *pFuncIndex=0;
+        result=E_INVALIDARG;
+    }
+    TRACE( typelib,"(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
+            memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
+    return result;
+}
+
+/* TypeInfo2::GetVarIndexOfMemId
+ *
+ * Binds to a specific member based on a known DISPID, where the member name
+ * is not known (for example, when binding to a default member). 
+ *
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo * iface,
+    MEMBERID memid, UINT *pVarIndex)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    TLBVarDesc *pVarInfo;
+    int i;
+    HRESULT result;
+    for(i=0, pVarInfo=This->varlist; pVarInfo && 
+            memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
+        ;
+    if(pVarInfo){
+        *pVarIndex=i;
+        result= S_OK;
+    }else{
+        *pVarIndex=0;
+        result=E_INVALIDARG;
+    }
+    TRACE( typelib,"(%p) memid 0x%08lx -> %s\n", This,
+            memid, SUCCEEDED(result)? "SUCCES":"FAILED");
+    return result;
+}
+
+/* ITypeInfo2::GetCustData
+ *
+ * Gets the custom data
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetCustData( ITypeInfo * iface,
+    REFGUID guid, VARIANT *pVarVal)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    TLBCustData *pCData;
+    for(pCData=This->pCustData; pCData; pCData = pCData->next)
+        if( IsEqualIID(guid, &pCData->guid)) break;
+    if(TRACE_ON(typelib)){
+        char xriid[50];
+        WINE_StringFromCLSID((LPCLSID)guid,xriid);
+        TRACE(typelib,"(%p) guid %s %s found!x)\n", This, xriid,
+                pCData? "" : "NOT");
+    }
+    if(pCData){
+        VariantInit( pVarVal);
+        VariantCopy( pVarVal, &pCData->data);
+        return S_OK;
+    }
+    return E_INVALIDARG;  /* FIXME: correct? */
+}
+
+/* ITypeInfo2::GetFuncCustData
+ *
+ * Gets the custom data
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData( ITypeInfo * iface,
+    UINT index, REFGUID guid, VARIANT *pVarVal)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    TLBCustData *pCData=NULL;
+    TLBFuncDesc * pFDesc; 
+    int i;
+    for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
+            pFDesc=pFDesc->next)
+        ;
+    if(pFDesc)
+        for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
+            if( IsEqualIID(guid, &pCData->guid)) break;
+    if(TRACE_ON(typelib)){
+        char xriid[50];
+        WINE_StringFromCLSID((LPCLSID)guid,xriid);
+        TRACE(typelib,"(%p) guid %s %s found!x)\n",This,xriid,
+                pCData? "" : "NOT");
+    }
+    if(pCData){
+        VariantInit( pVarVal);
+        VariantCopy( pVarVal, &pCData->data);
+        return S_OK;
+    }
+    return E_INVALIDARG;  /* FIXME: correct? */
+}
+
+/* ITypeInfo2::GetParamCustData
+ *
+ * Gets the custom data
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetParamCustData( ITypeInfo * iface,
+    UINT indexFunc, UINT indexParam, REFGUID guid, VARIANT *pVarVal)
+{   
+	ICOM_THIS( TLBTypeInfo, iface);
+    TLBCustData *pCData=NULL;
+    TLBFuncDesc * pFDesc; 
+    int i;
+    for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
+            pFDesc=pFDesc->next)
+        ;
+    if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
+        for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData; 
+                pCData = pCData->next)
+            if( IsEqualIID(guid, &pCData->guid)) break;
+    if(TRACE_ON(typelib)){
+        char xriid[50];
+        WINE_StringFromCLSID((LPCLSID)guid,xriid);
+        TRACE(typelib,"(%p) guid %s %s found!x)\n",This,xriid,
+                pCData? "" : "NOT");
+    }
+    if(pCData){
+        VariantInit( pVarVal);
+        VariantCopy( pVarVal, &pCData->data);
+        return S_OK;
+    }
+    return E_INVALIDARG;  /* FIXME: correct? */
+}
+
+/* ITypeInfo2::GetVarcCustData
+ *
+ * Gets the custom data
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetVarCustData( ITypeInfo * iface,
+    UINT index, REFGUID guid, VARIANT *pVarVal)
+{   
+	ICOM_THIS( TLBTypeInfo, iface);
+    TLBCustData *pCData=NULL;
+    TLBVarDesc * pVDesc; 
+    int i;
+    for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
+            pVDesc=pVDesc->next)
+        ;
+    if(pVDesc)
+        for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
+            if( IsEqualIID(guid, &pCData->guid)) break;
+    if(TRACE_ON(typelib)){
+        char xriid[50];
+        WINE_StringFromCLSID((LPCLSID)guid,xriid);
+        TRACE(typelib,"(%p) guid %s %s found!x)\n",This,xriid,
+                pCData? "" : "NOT");
+    }
+    if(pCData){
+        VariantInit( pVarVal);
+        VariantCopy( pVarVal, &pCData->data);
+        return S_OK;
+    }
+    return E_INVALIDARG;  /* FIXME: correct? */
+}
+
+/* ITypeInfo2::GetImplcCustData
+ *
+ * Gets the custom data
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData( ITypeInfo * iface,
+    UINT index, REFGUID guid, VARIANT *pVarVal)
+{   
+	ICOM_THIS( TLBTypeInfo, iface);
+    TLBCustData *pCData=NULL;
+    TLBRefType * pRDesc; 
+    int i;
+    for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
+            pRDesc=pRDesc->next)
+        ;
+    if(pRDesc)
+        for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
+            if( IsEqualIID(guid, &pCData->guid)) break;
+    if(TRACE_ON(typelib)){
+        char xriid[50];
+        WINE_StringFromCLSID((LPCLSID)guid,xriid);
+        TRACE(typelib,"(%p) guid %s %s found!x)\n",This,xriid,
+                pCData? "" : "NOT");
+    }
+    if(pCData){
+        VariantInit( pVarVal);
+        VariantCopy( pVarVal, &pCData->data);
+        return S_OK;
+    }
+    return E_INVALIDARG;  /* FIXME: correct? */
+}
+
+/* ITypeInfo2::GetDocumentation2
+ * 
+ * Retrieves the documentation string, the complete Help file name and path,
+ * the localization context to use, and the context ID for the library Help
+ * topic in the Help file.
+ *
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2( ITypeInfo * iface,
+    MEMBERID memid, LCID lcid, BSTR *pbstrHelpString,
+    INT *pdwHelpStringContext, BSTR *pbstrHelpStringDll)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    TLBFuncDesc * pFDesc; 
+    TLBVarDesc * pVDesc; 
+    TRACE( typelib, "(%p) memid %ld lcid(0x%lx)  HelpString(%p) "
+           "HelpStringContext(%p) HelpStringDll(%p)\n",
+        This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
+        pbstrHelpStringDll );
+    /* the help string should be obtained from the helpstringdll,
+     * using the _DLLGetDocumentation function, based on the supplied
+     * lcid. Nice to do sometime...
+     */
+    if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
+        if(pbstrHelpString)
+            *pbstrHelpString=TLB_DupAtoBstr(This->Name);
+        if(pdwHelpStringContext)
+            *pdwHelpStringContext=This->dwHelpStringContext;
+        if(pbstrHelpStringDll)
+            *pbstrHelpStringDll=
+                TLB_DupAtoBstr(This->pTypeLib->HelpStringDll);/* FIXME */
+        return S_OK;
+    }else {/* for a member */
+    for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
+        if(pFDesc->funcdesc.memid==memid){
+             if(pbstrHelpString)
+                *pbstrHelpString=TLB_DupAtoBstr(pFDesc->HelpString);
+            if(pdwHelpStringContext)
+                *pdwHelpStringContext=pFDesc->HelpStringContext;
+            if(pbstrHelpStringDll)
+                *pbstrHelpStringDll=
+                    TLB_DupAtoBstr(This->pTypeLib->HelpStringDll);/* FIXME */
+        return S_OK;
+    }
+    for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
+        if(pVDesc->vardesc.memid==memid){
+             if(pbstrHelpString)
+                *pbstrHelpString=TLB_DupAtoBstr(pVDesc->HelpString);
+            if(pdwHelpStringContext)
+                *pdwHelpStringContext=pVDesc->HelpStringContext;
+            if(pbstrHelpStringDll)
+                *pbstrHelpStringDll=
+                    TLB_DupAtoBstr(This->pTypeLib->HelpStringDll);/* FIXME */
+            return S_OK;
+        }
+    }
+    return TYPE_E_ELEMENTNOTFOUND;
+}
+
+/* ITypeInfo2::GetAllCustData
+ *
+ * Gets all custom data items for the Type info. 
+ *
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetAllCustData( ITypeInfo * iface,
+    CUSTDATA *pCustData)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    TLBCustData *pCData;
+    int i;
+    TRACE( typelib,"(%p) returning %d items\n", This, This->ctCustData); 
+    pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
+    if(pCustData->prgCustData ){
+        pCustData->cCustData=This->ctCustData;
+        for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
+            pCustData->prgCustData[i].guid=pCData->guid;
+            VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
+        }
+    }else{
+        ERR( typelib," OUT OF MEMORY! \n");
+        return E_OUTOFMEMORY;
+    }
+    return S_OK;
+}
+
+/* ITypeInfo2::GetAllFuncCustData
+ *
+ * Gets all custom data items for the specified Function
+ *
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData( ITypeInfo * iface,
+    UINT index, CUSTDATA *pCustData)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    TLBCustData *pCData;
+    TLBFuncDesc * pFDesc; 
+    int i;
+    TRACE( typelib,"(%p) index %d\n", This, index); 
+    for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
+            pFDesc=pFDesc->next)
+        ;
+    if(pFDesc){
+        pCustData->prgCustData =
+            TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
+        if(pCustData->prgCustData ){
+            pCustData->cCustData=pFDesc->ctCustData;
+            for(i=0, pCData=pFDesc->pCustData; pCData; i++,
+                    pCData = pCData->next){
+                pCustData->prgCustData[i].guid=pCData->guid;
+                VariantCopy(& pCustData->prgCustData[i].varValue,
+                        & pCData->data);
+            }
+        }else{
+            ERR( typelib," OUT OF MEMORY! \n");
+            return E_OUTOFMEMORY;
+        }
+        return S_OK;
+    }
+    return TYPE_E_ELEMENTNOTFOUND;
+}
+
+/* ITypeInfo2::GetAllParamCustData
+ *
+ * Gets all custom data items for the Functions
+ *
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo * iface,
+    UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    TLBCustData *pCData=NULL;
+    TLBFuncDesc * pFDesc; 
+    int i;
+    TRACE( typelib,"(%p) index %d\n", This, indexFunc); 
+    for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
+            pFDesc=pFDesc->next)
+        ;
+    if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
+        pCustData->prgCustData = 
+            TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
+                    sizeof(CUSTDATAITEM));
+        if(pCustData->prgCustData ){
+            pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
+            for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
+                    pCData; i++, pCData = pCData->next){
+                pCustData->prgCustData[i].guid=pCData->guid;
+                VariantCopy(& pCustData->prgCustData[i].varValue,
+                        & pCData->data);
+            }
+        }else{
+            ERR( typelib," OUT OF MEMORY! \n");
+            return E_OUTOFMEMORY;
+        }
+        return S_OK;
+    }
+    return TYPE_E_ELEMENTNOTFOUND;
+}
+
+/* ITypeInfo2::GetAllVarCustData
+ *
+ * Gets all custom data items for the specified Variable
+ *
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo * iface,
+    UINT index, CUSTDATA *pCustData)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    TLBCustData *pCData;
+    TLBVarDesc * pVDesc; 
+    int i;
+    TRACE( typelib,"(%p) index %d\n", This, index); 
+    for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
+            pVDesc=pVDesc->next)
+        ;
+    if(pVDesc){
+        pCustData->prgCustData =
+            TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
+        if(pCustData->prgCustData ){
+            pCustData->cCustData=pVDesc->ctCustData;
+            for(i=0, pCData=pVDesc->pCustData; pCData; i++,
+                    pCData = pCData->next){
+                pCustData->prgCustData[i].guid=pCData->guid;
+                VariantCopy(& pCustData->prgCustData[i].varValue,
+                        & pCData->data);
+            }
+        }else{
+            ERR( typelib," OUT OF MEMORY! \n");
+            return E_OUTOFMEMORY;
+        }
+        return S_OK;
+    }
+    return TYPE_E_ELEMENTNOTFOUND;
+}
+
+/* ITypeInfo2::GetAllImplCustData
+ *
+ * Gets all custom data items for the specified implementation type
+ *
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData( ITypeInfo * iface,
+    UINT index, CUSTDATA *pCustData)
+{
+	ICOM_THIS( TLBTypeInfo, iface);
+    TLBCustData *pCData;
+    TLBRefType * pRDesc; 
+    int i;
+    TRACE( typelib,"(%p) index %d\n", This, index); 
+    for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
+            pRDesc=pRDesc->next)
+        ;
+    if(pRDesc){
+        pCustData->prgCustData =
+            TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
+        if(pCustData->prgCustData ){
+            pCustData->cCustData=pRDesc->ctCustData;
+            for(i=0, pCData=pRDesc->pCustData; pCData; i++,
+                    pCData = pCData->next){
+                pCustData->prgCustData[i].guid=pCData->guid;
+                VariantCopy(& pCustData->prgCustData[i].varValue,
+                        & pCData->data);
+            }
+        }else{
+            ERR( typelib," OUT OF MEMORY! \n");
+            return E_OUTOFMEMORY;
+        }
+        return S_OK;
+    }
+    return TYPE_E_ELEMENTNOTFOUND;
+}
+
diff --git a/ole/typelib.h b/ole/typelib.h
new file mode 100644
index 0000000..64d7aa0
--- /dev/null
+++ b/ole/typelib.h
@@ -0,0 +1,358 @@
+/*
+ * typelib.h  internal wine data structures
+ * used to decode typelib's
+ *
+ * Copyright 1999 Rein KLazes
+ *  
+ */
+#ifndef _WINE_TYPELIB_H
+#define _WINE_TYPELIB_H
+
+
+#include "ole2.h"
+#include "oleauto.h"
+#include "oaidl.h"
+
+
+#define TLBMAGIC2 "MSFT"
+#define TLBMAGIC1 "SLTG"
+#define HELPDLLFLAG (0x0100)
+#define DO_NOT_SEEK (-1)
+
+#define HREFTYPE_INTHISFILE(href) (!((href) & 3))
+#define HREFTYPE_INDEX(href) ((href) /sizeof(TLBTypeInfoBase))
+
+typedef struct tagTLBCustData {
+    GUID guid;
+    VARIANT data;
+    struct tagTLBCustData* next;
+} TLBCustData;
+
+/* internal Parameter data */
+typedef struct tagTLBParDesc{
+    PCHAR Name;
+    int ctCustData;
+    TLBCustData * pCustData;        /* linked list to cust data; */
+} TLBParDesc;
+
+
+/* internal Function data */
+typedef struct tagTLBFuncDesc{
+    FUNCDESC funcdesc;      /* lots of info on the function and its attributes. */
+    PCHAR Name;             /* the name of this function */
+    TLBParDesc *pParamDesc; /* array with name and custom data */
+    int helpcontext;
+    int HelpStringContext;
+    PCHAR HelpString;
+    PCHAR Entry;            /* if its Hiword==0, it numeric; -1 is not present*/
+    int ctCustData;
+    TLBCustData * pCustData;        /* linked list to cust data; */
+    struct tagTLBFuncDesc * next; 
+} TLBFuncDesc;
+
+/* internal Variable data */
+typedef struct tagTLBVarDesc{
+    VARDESC vardesc;        /* lots of info on the variable and its attributes. */
+    PCHAR Name;             /* the name of this variable */
+    int HelpContext;
+    int HelpStringContext;  /* fixme: where? */
+    PCHAR HelpString;
+    int ctCustData;
+    TLBCustData * pCustData;/* linked list to cust data; */
+    struct tagTLBVarDesc * next; 
+} TLBVarDesc;
+
+/* data for refernced types in a coclass, or an inherited interface */
+typedef struct tagTLBRefType {
+    GUID guid;              /* guid of the referenced type */
+                            /* (important if its a imported type) */
+    HREFTYPE reference;
+    int flags;
+    int ctCustData;
+    TLBCustData * pCustData;/* linked list to custom data; */
+    struct tagTLBImpLib *pImpTLInfo;
+    struct tagTLBRefType * next;
+    }TLBRefType;
+
+/* internal TypeInfo data */
+typedef struct tagTYPEINFO {
+    LPTYPEINFO_VTABLE lpvtbl;
+    UINT ref;
+    TYPEATTR TypeAttr ;         /* _lots_ of type information. */
+    struct tagTYPELIB * pTypeLib; /* back pointer to typelib */
+    int index;                  /* index in this typelib; */
+    /* type libs seem to store the doc strings in ascii 
+     * so why should we do it in unicode?
+     */
+    PCHAR Name;
+    PCHAR DocString;
+    unsigned long  dwHelpContext;
+    unsigned long  dwHelpStringContext;
+
+/* functions  */
+    TLBFuncDesc * funclist;     /* linked list with function descriptions */
+/* variables  */
+    TLBVarDesc * varlist;       /* linked list with variable descriptions */
+/* Implemented Interfaces  */
+    TLBRefType * impltypelist;      
+    int ctCustData;
+    TLBCustData * pCustData;        /* linked list to cust data; */
+    struct tagTYPEINFO * next;
+} TLBTypeInfo;
+
+/* data structure for import typelibs */
+typedef struct tagTLBImpLib {
+    int offset;                 /* offset in the file */
+    GUID guid;                  /* libid */
+    PCHAR name;                 /* name; */
+    struct tagTYPELIB *pImpTypeLib; /* pointer to loaded typelib */
+    struct tagTLBImpLib * next;
+    } TLBImpLib;
+
+/* internal TypeLib data */
+typedef struct tagTYPELIB  {
+    LPTYPELIB_VTABLE lpvtbl;
+    UINT ref;
+    TLIBATTR LibAttr;               /* guid,lcid,syskind,version,flags */
+    /* type libs seem to store the doc strings in ascii 
+     * so why should we do it in unicode?
+     */
+    PCHAR Name;
+    PCHAR DocString;
+    PCHAR HelpFile;
+    PCHAR HelpStringDll;
+    unsigned long  dwHelpContext;
+    int TypeInfoCount;          /* nr of typeinfo's in librarry */
+    TLBTypeInfo *pTypeInfo;     /* linked list of type info data */
+    int ctCustData;             /* number of items in cust data list */
+    TLBCustData * pCustData;    /* linked list to cust data; */
+    TLBImpLib   * pImpLibs;     /* linked list to all imported typelibs */
+    TYPEDESC * pTypeDesc;       /* array of TypeDescriptions found in the libary */
+} TLBLibInfo;
+
+/*-------------------------FILE STRUCTURES-----------------------------------*/
+
+
+/*
+ * structure of the typelib type2 header
+ * it is at the beginning of a type lib file
+ *  
+ */
+typedef struct tagTLB2Header {
+/*0x00*/INT magic1;       /* 0x5446534D "MSFT" */
+        INT   magic2;       /* 0x00010002 version nr? */
+        INT   posguid;      /* position of libid in guid table  */
+                            /* (should be,  else -1) */
+        INT   lcid;         /* locale id */
+/*0x10*/INT   lcid2;
+        INT   varflags;     /* (largely) unknown flags ,seems to be always 41 */
+                            /* becomes 0x51 with a helpfile defined */
+                            /* if help dll defined its 0x151 */
+                            /* update : the lower nibble is syskind */
+        INT   version;      /* set with SetVersion() */
+        INT   flags;        /* set with SetFlags() */
+/*0x20*/INT   nrtypeinfos;  /* number of typeinfo's (till so far) */
+        INT   helpstring;   /* position of help string in stringtable */
+        INT   helpstringcontext;
+        INT   helpcontext;
+/*0x30*/INT   nametablecount;   /* number of names in name table */
+        INT   nametablechars;   /* nr of characters in name table */
+        INT   NameOffset;       /* offset of name in name table */
+        INT   helpfile;         /* position of helpfile in stringtable */
+/*0x40*/INT   CustomDataOffset; /* if -1 no custom data, else it is offset */
+                                /* in customer data/guid offset table */
+        INT   res44;            /* unknown always: 0x20 */
+        INT   res48;            /* unknown always: 0x80 */
+        INT   dispatchpos;      /* gets a value (1+n*0x0c) with Idispatch interfaces */
+/*0x50*/INT   res50;            /* is zero becomes one when an interface is derived */
+} TLB2Header;
+
+/* segments in the type lib file have a structure like this: */
+typedef struct _tptag {
+        INT   offset;       /* absolute offset in file */
+        INT   length;       /* length of segment */
+        INT   res08;        /* unknown always -1 */
+        INT   res0c;        /* unknown always 0x0f in the header */
+                            /* 0x03 in the typeinfo_data */
+} pSeg;
+
+/* layout of the main segment directory */
+typedef struct tagTLBSegDir {
+/*1*/pSeg pTypeInfoTab; /* each type info get an entry of 0x64 bytes */
+                        /* (25 ints) */
+/*2*/pSeg pImpInfo;     /* table with info for imported types */
+/*3*/pSeg pImpFiles;    /* import libaries */
+/*4*/pSeg pRefTab;      /* References table */
+/*5*/pSeg pLibtab;      /* always exists, alway same size (0x80) */
+                        /* hash table w offsets to guid????? */
+/*6*/pSeg pGuidTab;     /* all guids are stored here together with  */
+                        /* offset in some table???? */
+/*7*/pSeg res07;        /* always created, alway same size (0x200) */
+                        /* purpose largely unknown */
+/*8*/pSeg pNametab;     /* name tables */
+/*9*/pSeg pStringtab;   /*string table */
+/*A*/pSeg pTypdescTab;  /* table with type descriptors */
+/*B*/pSeg pArrayDescriptions;
+/*C*/pSeg pCustData;    /*  data table, used for custom data and default */
+                        /* parameter values */
+/*D*/pSeg pCDGuids;     /* table with offsets for the guids and into the customer data table */
+/*E*/pSeg res0e;            /* unknown */
+/*F*/pSeg res0f;            /* unknown  */
+} TLBSegDir;
+
+
+/* base type info data */
+typedef struct tagTLBTypeInfoBase {
+/*000*/ INT   typekind;             /*  it is the TKIND_xxx */
+                                    /* some byte alignment stuf */
+        INT     memoffset;          /* points past the file, if no elements */
+        INT     res2;               /* zero if no element, N*0x40 */
+        INT     res3;               /* -1 if no lement, (N-1)*0x38 */
+/*010*/ INT     res4;               /* always? 3 */
+        INT     res5;               /* always? zero */
+        INT     cElement;           /* counts elements, HI=cVars, LO=cFuncs */
+        INT     res7;               /* always? zero */
+/*020*/ INT     res8;               /* always? zero */
+        INT     res9;               /* always? zero */
+        INT     resA;               /* always? zero */
+        INT     posguid;            /* position in guid table */
+/*030*/ INT     flags;              /* Typeflags */
+        INT     NameOffset;         /* offset in name table */
+        INT     version;            /* element version */
+        INT     docstringoffs;      /* offset of docstring in string tab */
+/*040*/ INT     helpstringcontext;  /*  */
+        INT     helpcontext;    /* */
+        INT     oCustData;          /* offset in customer data table */
+        INT16   cImplTypes;     /* nr of implemented interfaces */
+        INT16   cbSizeVft;      /* virtual table size, not including inherits */
+/*050*/ INT     size;           /* size in bytes, at least for structures */
+        /* fixme: name of this field */
+        INT     datatype1;      /* position in type description table */
+                                /* or in base intefaces */
+                                /* if coclass: offset in reftable */
+                                /* if interface: reference to inherited if */
+        INT     datatype2;      /* if 0x8000, entry above is valid */
+                                /* actually dunno */
+                                /* else it is zero? */
+        INT     res18;          /* always? 0 */
+/*060*/ INT     res19;          /* always? -1 */
+    } TLBTypeInfoBase;
+
+/* layout of an entry with information on imported types */
+typedef struct tagTLBImpInfo {
+    INT     res0;           /* unknown */
+    INT     oImpFile;       /* offset inthe Import File table */
+    INT     oGuid;          /* offset in Guid table */
+    } TLBImpInfo;
+
+/* function description data */
+typedef struct {
+/*  INT   recsize;       record size including some xtra stuff */
+    INT   DataType;     /* data type of the memeber, eg return of function */
+    INT   Flags;        /* something to do with attribute flags (LOWORD) */
+    INT16 VtableOffset; /* offset in vtable */
+    INT16 res3;         /* some offset into dunno what */
+    INT   FKCCIC;       /* bit string with the following  */
+                        /* meaning (bit 0 is the msb): */
+                        /* bit 2 indicates that oEntry is numeric */
+                        /* bit 3 that parameter has default values */
+                        /* calling convention (bits 4-7 ) */
+                        /* bit 8 indicates that custom data is present */
+                        /* Invokation kind (bits 9-12 ) */
+                        /* function kind (eg virtual), bits 13-15  */
+    INT16 nrargs;       /* number of arguments (including optional ????) */
+    INT16 nroargs;      /* nr of optional arguments */
+    /* optional attribute fields, the number of them is variable */
+    INT   OptAttr[1];
+/*
+0*  INT   helpcontext;
+1*  INT   oHelpString;
+2*  INT   oEntry;       // either offset in string table or numeric as it is //
+3*  INT   res9;         // unknown (-1) //
+4*  INT   resA;         // unknown (-1) //
+5*  INT   HelpStringContext;
+    // these are controlled by a bit set in the FKCCIC field  //
+6*  INT   oCustData;        // custom data for function //
+7*  INT   oArgCustData[1];  // custom data per argument //
+*/
+} TLBFuncRecord;
+
+/* after this may follow an array with default value pointers if the 
+ * appropriate bit in the FKCCIC field has been set: 
+ * INT   oDefautlValue[nrargs];
+ */
+
+    /* Parameter info one per argument*/
+typedef struct {
+        INT   DataType;
+        INT   oName;
+        INT   Flags;
+    } TLBParameterInfo;
+
+/* Variable description data */
+typedef struct {
+/*  INT   recsize;      // record size including some xtra stuff */
+    INT   DataType;     /* data type of the variable */
+    INT   Flags;        /* VarFlags (LOWORD) */
+    INT16 VarKind;      /* VarKind */
+    INT16 res3;         /* some offset into dunno what */
+    INT   OffsValue;    /* value of the variable or the offset  */
+                        /* in the data structure */
+    /* optional attribute fields, the number of them is variable */
+    /* controlled by record length */
+    INT   HelpContext;
+    INT   oHelpString;
+    INT   res9;         /* unknown (-1) */
+    INT   oCustData;        /* custom data for variable */
+    INT   HelpStringContext;
+
+} TLBVarRecord;
+
+/* Structure of the reference data  */
+typedef struct {
+    INT   reftype;  /* either offset in type info table, then its */
+                    /* a multiple of 64 */
+                    /* or offset in the external reference table */
+                    /* with an offset of 1 */
+    INT   flags;
+    INT   oCustData;    /* custom data */
+    INT   onext;    /* next offset, -1 if last */
+} TLBRefRecord;
+
+/* this is how a guid is stored */
+typedef struct {
+    GUID guid;
+    INT   unk10;        /* differntiate with libid, classid etc? */
+                        /* its -2 for a libary */
+                        /* it's 0 for an interface */
+    INT   unk14;        /* always? -1 */
+} TLBGuidEntry;
+/* some data preceding entries in the name table */
+typedef struct {
+    INT   unk00;        /* sometimes -1 (lib, parameter) ,
+                           sometimes 0 (interface, func) */
+    INT   unk10;        /* sometimes -1 (lib) , sometimes 0 (interface, func),
+                           sometime 0x10 (par) */
+    INT   namelen;      /* only lower 8 bits are valid */
+} TLBNameIntro;
+/* the custom data table directory has enties like this */
+typedef struct {
+    INT   GuidOffset;
+    INT   DataOffset;
+    INT   next;     /* next offset in the table, -1 if its the last */
+} TLBCDGuid;
+
+
+
+/*---------------------------END--------------------------------------------*/
+
+typedef struct tagTLBContext {
+    HANDLE   hFile;            /* open typelib file  */
+    long oStart;                /* start of TLB in file */
+    TLBSegDir * pTblDir;
+    TLBLibInfo* pLibInfo;
+} TLBContext;
+
+
+#endif
+
diff --git a/relay32/oleaut32.spec b/relay32/oleaut32.spec
index 7b5de51..ffc1e36 100644
--- a/relay32/oleaut32.spec
+++ b/relay32/oleaut32.spec
@@ -143,7 +143,7 @@
 183 stub LoadTypeLibEx
 184 stub SystemTimeToVariantTime
 185 stub VariantTimeToSystemTime
-186 stub UnRegisterTypeLib
+186 stdcall UnRegisterTypeLib (ptr long long long long) UnRegisterTypeLib
 190 stub VarDecFromUI1
 191 stub VarDecFromI2
 192 stub VarDecFromI4