[WIN32K]
[reactos.git] / dll / win32 / oleaut32 / typelib.c
index ceb2295..46c0d28 100644 (file)
@@ -64,6 +64,7 @@
 #include "winnls.h"
 #include "winreg.h"
 #include "winuser.h"
+#include "lzexpand.h"
 
 #include "wine/unicode.h"
 #include "objbase.h"
 WINE_DEFAULT_DEBUG_CHANNEL(ole);
 WINE_DECLARE_DEBUG_CHANNEL(typelib);
 
+typedef struct
+{
+    WORD     offset;
+    WORD     length;
+    WORD     flags;
+    WORD     id;
+    WORD     handle;
+    WORD     usage;
+} NE_NAMEINFO;
+
+typedef struct
+{
+    WORD        type_id;   /* Type identifier */
+    WORD        count;     /* Number of resources of this type */
+    DWORD       resloader; /* SetResourceHandler() */
+    /*
+     * Name info array.
+     */
+} NE_TYPEINFO;
+
 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
 
@@ -147,13 +168,13 @@ static void FromLEDWords(void *p_Val, int p_iSize)
 /*
  * Find a typelib key which matches a requested maj.min version.
  */
-static BOOL find_typelib_key( REFGUID guid, WORD wMaj, WORD *wMin )
+static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
 {
     static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
     WCHAR buffer[60];
     char key_name[16];
     DWORD len, i;
-    INT best_min = -1;
+    INT best_maj = -1, best_min = -1;
     HKEY hkey;
 
     memcpy( buffer, typelibW, sizeof(typelibW) );
@@ -172,20 +193,40 @@ static BOOL find_typelib_key( REFGUID guid, WORD wMaj, WORD *wMin )
         {
             TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
 
-            if (wMaj == v_maj)
+            if (*wMaj == 0xffff && *wMin == 0xffff)
+            {
+                if (v_maj > best_maj) best_maj = v_maj;
+                if (v_min > best_min) best_min = v_min;
+            }
+            else if (*wMaj == v_maj)
             {
+                best_maj = v_maj;
+
                 if (*wMin == v_min)
                 {
                     best_min = v_min;
                     break; /* exact match */
                 }
-                if (v_min > best_min) best_min = v_min;
+                if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
             }
         }
         len = sizeof(key_name);
     }
     RegCloseKey( hkey );
-    if (best_min >= 0)
+
+    TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
+
+    if (*wMaj == 0xffff && *wMin == 0xffff)
+    {
+        if (best_maj >= 0 && best_min >= 0)
+        {
+            *wMaj = best_maj;
+            *wMin = best_min;
+            return TRUE;
+        }
+    }
+
+    if (*wMaj == best_maj && best_min >= 0)
     {
         *wMin = best_min;
         return TRUE;
@@ -224,12 +265,14 @@ static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
     static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
     static const WCHAR win16W[] = {'w','i','n','1','6',0};
     static const WCHAR win32W[] = {'w','i','n','3','2',0};
+    static const WCHAR win64W[] = {'w','i','n','6','4',0};
 
     sprintfW( buffer, LcidFormatW, lcid );
     switch(syskind)
     {
     case SYS_WIN16: strcatW( buffer, win16W ); break;
     case SYS_WIN32: strcatW( buffer, win32W ); break;
+    case SYS_WIN64: strcatW( buffer, win64W ); break;
     default:
         TRACE("Typelib is for unsupported syskind %i\n", syskind);
         return NULL;
@@ -240,30 +283,9 @@ static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
 
 
-/****************************************************************************
- *             QueryPathOfRegTypeLib   [OLEAUT32.164]
- *
- * Gets the path to a registered type library.
- *
- * PARAMS
- *  guid [I] referenced guid
- *  wMaj [I] major version
- *  wMin [I] minor version
- *  lcid [I] locale id
- *  path [O] path of typelib
- *
- * RETURNS
- *  Success: S_OK.
- *  Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
- *  or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
- *  opened.
- */
-HRESULT WINAPI QueryPathOfRegTypeLib(
-       REFGUID guid,
-       WORD wMaj,
-       WORD wMin,
-       LCID lcid,
-       LPBSTR path )
+/* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
+static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
+                                   SYSKIND syskind, LCID lcid, LPBSTR path )
 {
     HRESULT hr = TYPE_E_LIBNOTREGISTERED;
     LCID myLCID = lcid;
@@ -274,7 +296,7 @@ HRESULT WINAPI QueryPathOfRegTypeLib(
 
     TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
 
-    if (!find_typelib_key( guid, wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
+    if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
     get_typelib_key( guid, wMaj, wMin, buffer );
 
     res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
@@ -293,7 +315,7 @@ HRESULT WINAPI QueryPathOfRegTypeLib(
     {
         LONG dwPathLen = sizeof(Path);
 
-        get_lcid_subkey( myLCID, SYS_WIN32, buffer );
+        get_lcid_subkey( myLCID, syskind, buffer );
 
         if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
         {
@@ -325,6 +347,29 @@ HRESULT WINAPI QueryPathOfRegTypeLib(
     return hr;
 }
 
+/****************************************************************************
+ *             QueryPathOfRegTypeLib   [OLEAUT32.164]
+ *
+ * Gets the path to a registered type library.
+ *
+ * PARAMS
+ *  guid [I] referenced guid
+ *  wMaj [I] major version
+ *  wMin [I] minor version
+ *  lcid [I] locale id
+ *  path [O] path of typelib
+ *
+ * RETURNS
+ *  Success: S_OK.
+ *  Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
+ *  or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
+ *  opened.
+ */
+HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
+{
+    return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path );
+}
+
 /******************************************************************************
  * CreateTypeLib [OLEAUT32.160]  creates a typelib
  *
@@ -394,7 +439,7 @@ HRESULT WINAPI LoadTypeLibEx(
                 /* else fall-through */
 
             case REGKIND_REGISTER:
-                if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
+                if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
                 {
                     IUnknown_Release(*pptLib);
                     *pptLib = 0;
@@ -491,9 +536,15 @@ HRESULT WINAPI RegisterTypeLib(
     if (ptlib == NULL || szFullPath == NULL)
         return E_INVALIDARG;
 
-    if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
+    if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
         return E_FAIL;
 
+#ifdef _WIN64
+    if (attr->syskind != SYS_WIN64) return TYPE_E_BADMODULEKIND;
+#else
+    if (attr->syskind != SYS_WIN32 && attr->syskind != SYS_WIN16) return TYPE_E_BADMODULEKIND;
+#endif
+
     get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
 
     res = S_OK;
@@ -503,7 +554,9 @@ HRESULT WINAPI RegisterTypeLib(
         LPOLESTR doc;
 
         /* Set the human-readable name of the typelib */
-        if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
+        if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
+            res = E_FAIL;
+        else if (doc)
         {
             if (RegSetValueExW(key, NULL, 0, REG_SZ,
                 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
@@ -511,8 +564,6 @@ HRESULT WINAPI RegisterTypeLib(
 
             SysFreeString(doc);
         }
-        else
-            res = E_FAIL;
 
         /* Make up the name of the typelib path subkey */
         if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
@@ -642,7 +693,10 @@ HRESULT WINAPI RegisterTypeLib(
                        MESSAGE("\n");
                    }
 
-                   if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
+                    /* Register all dispinterfaces (which includes dual interfaces) and
+                       oleautomation interfaces */
+                   if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
+                        kind == TKIND_DISPATCH)
                    {
                        /* register interface<->typelib coupling */
                        get_interface_key( &tattr->guid, keyName );
@@ -739,7 +793,7 @@ HRESULT WINAPI UnRegisterTypeLib(
     /* Create the path to the key */
     get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
 
-    if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
+    if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
     {
         TRACE("Unsupported syskind %i\n", syskind);
         result = E_INVALIDARG;
@@ -747,7 +801,7 @@ HRESULT WINAPI UnRegisterTypeLib(
     }
 
     /* get the path to the typelib on disk */
-    if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
+    if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath) != S_OK) {
         result = E_INVALIDARG;
         goto end;
     }
@@ -783,19 +837,23 @@ HRESULT WINAPI UnRegisterTypeLib(
             goto enddeleteloop;
         }
 
-        /* the path to the type */
-        get_interface_key( &typeAttr->guid, subKeyName );
+        if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
+            kind == TKIND_DISPATCH)
+        {
+            /* the path to the type */
+            get_interface_key( &typeAttr->guid, subKeyName );
 
-        /* Delete its bits */
-        if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
-            goto enddeleteloop;
+            /* Delete its bits */
+            if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS)
+                goto enddeleteloop;
+
+            RegDeleteKeyW(subKey, ProxyStubClsidW);
+            RegDeleteKeyW(subKey, ProxyStubClsid32W);
+            RegDeleteKeyW(subKey, TypeLibW);
+            RegCloseKey(subKey);
+            subKey = NULL;
+            RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
         }
-        RegDeleteKeyW(subKey, ProxyStubClsidW);
-        RegDeleteKeyW(subKey, ProxyStubClsid32W);
-        RegDeleteKeyW(subKey, TypeLibW);
-        RegCloseKey(subKey);
-        subKey = NULL;
-        RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
 
 enddeleteloop:
         if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
@@ -838,13 +896,56 @@ enddeleteloop:
     }
 
 end:
-    if (tlibPath) SysFreeString(tlibPath);
+    SysFreeString(tlibPath);
     if (typeLib) ITypeLib_Release(typeLib);
     if (subKey) RegCloseKey(subKey);
     if (key) RegCloseKey(key);
     return result;
 }
 
+/******************************************************************************
+ *             RegisterTypeLibForUser  [OLEAUT32.442]
+ * Adds information about a type library to the user registry
+ * NOTES
+ *    Docs: ITypeLib FAR * ptlib
+ *    Docs: OLECHAR FAR* szFullPath
+ *    Docs: OLECHAR FAR* szHelpDir
+ *
+ * RETURNS
+ *    Success: S_OK
+ *    Failure: Status
+ */
+HRESULT WINAPI RegisterTypeLibForUser(
+     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*/
+{
+    FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
+          debugstr_w(szFullPath), debugstr_w(szHelpDir));
+    return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
+}
+
+/******************************************************************************
+ *     UnRegisterTypeLibForUser        [OLEAUT32.443]
+ * Removes information about a type library from the user registry
+ *
+ * RETURNS
+ *    Success: S_OK
+ *    Failure: Status
+ */
+HRESULT WINAPI UnRegisterTypeLibForUser(
+    REFGUID libid,     /* [in] GUID of the library */
+    WORD wVerMajor,    /* [in] major version */
+    WORD wVerMinor,    /* [in] minor version */
+    LCID lcid, /* [in] locale id */
+    SYSKIND syskind)
+{
+    FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
+          debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
+    return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
+}
+
 /*======================= ITypeLib implementation =======================*/
 
 typedef struct tagTLBCustData
@@ -881,6 +982,7 @@ typedef struct tagITypeLibImpl
     const ITypeCompVtbl *lpVtblTypeComp;
     LONG ref;
     TLIBATTR LibAttr;            /* guid,lcid,syskind,version,flags */
+    LCID lcid;
 
     /* strings can be stored in tlb as multibyte strings BUT they are *always*
      * exported to the application as a UNICODE string.
@@ -889,7 +991,7 @@ typedef struct tagITypeLibImpl
     BSTR DocString;
     BSTR HelpFile;
     BSTR HelpStringDll;
-    unsigned long  dwHelpContext;
+    DWORD dwHelpContext;
     int TypeInfoCount;          /* nr of typeinfo's in librarry */
     struct tagITypeInfoImpl *pTypeInfo;   /* linked list of type info data */
     int ctCustData;             /* number of items in cust data list */
@@ -963,7 +1065,7 @@ typedef struct tagTLBFuncDesc
     int helpcontext;
     int HelpStringContext;
     BSTR HelpString;
-    BSTR Entry;            /* if its Hiword==0, it numeric; -1 is not present*/
+    BSTR Entry;            /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
     int ctCustData;
     TLBCustData * pCustData;        /* linked list to cust data; */
     struct tagTLBFuncDesc * next;
@@ -998,7 +1100,7 @@ typedef struct tagITypeInfoImpl
     const ITypeInfo2Vtbl *lpVtbl;
     const ITypeCompVtbl  *lpVtblTypeComp;
     LONG ref;
-    BOOL no_free_data; /* don't free data structures */
+    BOOL not_attached_to_typelib;
     TYPEATTR TypeAttr ;         /* _lots_ of type information. */
     ITypeLibImpl * pTypeLib;        /* back pointer to typelib */
     int index;                  /* index in this typelib; */
@@ -1009,8 +1111,8 @@ typedef struct tagITypeInfoImpl
     BSTR Name;
     BSTR DocString;
     BSTR DllName;
-    unsigned long  dwHelpContext;
-    unsigned long  dwHelpStringContext;
+    DWORD dwHelpContext;
+    DWORD dwHelpStringContext;
 
     /* functions  */
     TLBFuncDesc * funclist;     /* linked list with function descriptions */
@@ -1034,7 +1136,8 @@ static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
 static const ITypeInfo2Vtbl tinfvt;
 static const ITypeCompVtbl  tcompvt;
 
-static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
+static ITypeInfo2 * ITypeInfo_Constructor(void);
+static void ITypeInfo_fnDestroy(ITypeInfoImpl *This);
 
 typedef struct tagTLBContext
 {
@@ -1294,7 +1397,7 @@ static void dump_Variant(const VARIANT * pvar)
 
 static void dump_DispParms(const DISPPARAMS * pdp)
 {
-    int index;
+    unsigned int index;
 
     TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
 
@@ -1459,7 +1562,7 @@ static inline unsigned int MSFT_Tell(const TLBContext *pcx)
     return pcx->pos;
 }
 
-static inline void MSFT_Seek(TLBContext *pcx, long where)
+static inline void MSFT_Seek(TLBContext *pcx, LONG where)
 {
     if (where != DO_NOT_SEEK)
     {
@@ -1467,7 +1570,7 @@ static inline void MSFT_Seek(TLBContext *pcx, long where)
         if (where > pcx->length)
         {
             /* FIXME */
-            ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
+            ERR("seek beyond end (%d/%d)\n", where, pcx->length );
             TLB_abort();
         }
         pcx->pos = where;
@@ -1475,9 +1578,9 @@ static inline void MSFT_Seek(TLBContext *pcx, long where)
 }
 
 /* read function */
-static DWORD MSFT_Read(void *buffer,  DWORD count, TLBContext *pcx, long where )
+static DWORD MSFT_Read(void *buffer,  DWORD count, TLBContext *pcx, LONG where )
 {
-    TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
+    TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
        pcx->pos, count, pcx->oStart, pcx->length, where);
 
     MSFT_Seek(pcx, where);
@@ -1488,7 +1591,7 @@ static DWORD MSFT_Read(void *buffer,  DWORD count, TLBContext *pcx, long where )
 }
 
 static DWORD MSFT_ReadLEDWords(void *buffer,  DWORD count, TLBContext *pcx,
-                              long where )
+                               LONG where )
 {
   DWORD ret;
 
@@ -1499,7 +1602,7 @@ static DWORD MSFT_ReadLEDWords(void *buffer,  DWORD count, TLBContext *pcx,
 }
 
 static DWORD MSFT_ReadLEWords(void *buffer,  DWORD count, TLBContext *pcx,
-                             long where )
+                              LONG where )
 {
   DWORD ret;
 
@@ -1848,9 +1951,9 @@ MSFT_DoFuncs(TLBContext*     pcx,
                 {
                     if ( pFuncRec->FKCCIC & 0x2000 )
                     {
-                       if (HIWORD(pFuncRec->OptAttr[2]) != 0)
-                           ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
-                       (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
+                       if (!IS_INTRESOURCE(pFuncRec->OptAttr[2]))
+                           ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->OptAttr[2]);
+                       (*pptfd)->Entry = (BSTR)(DWORD_PTR)LOWORD(pFuncRec->OptAttr[2]);
                     }
                     else
                     {
@@ -1885,7 +1988,7 @@ MSFT_DoFuncs(TLBContext*     pcx,
         (*pptfd)->funcdesc.callconv   =  (pFuncRec->FKCCIC) >> 8 & 0xF;
         (*pptfd)->funcdesc.cParams    =   pFuncRec->nrargs  ;
         (*pptfd)->funcdesc.cParamsOpt =   pFuncRec->nroargs ;
-        (*pptfd)->funcdesc.oVft       =   pFuncRec->VtableOffset ;
+        (*pptfd)->funcdesc.oVft       =   pFuncRec->VtableOffset;
         (*pptfd)->funcdesc.wFuncFlags =   LOWORD(pFuncRec->Flags) ;
 
         MSFT_GetTdesc(pcx,
@@ -2212,6 +2315,8 @@ static ITypeInfoImpl * MSFT_DoTypeInfo(
        debugstr_w(ptiRet->Name),
        debugstr_guid(&ptiRet->TypeAttr.guid),
        typekind_desc[ptiRet->TypeAttr.typekind]);
+    if (TRACE_ON(typelib))
+      dump_TypeInfo(ptiRet);
 
     return ptiRet;
 }
@@ -2326,6 +2431,220 @@ static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *p
     return TYPE_E_CANTLOADLIBRARY;
 }
 
+typedef struct TLB_NEFile
+{
+    const IUnknownVtbl *lpvtbl;
+    LONG refs;
+    LPVOID typelib_base;
+} TLB_NEFile;
+
+static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
+{
+    if (IsEqualIID(riid, &IID_IUnknown))
+    {
+        *ppv = iface;
+        IUnknown_AddRef(iface);
+        return S_OK;
+    }
+    *ppv = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
+{
+    TLB_NEFile *This = (TLB_NEFile *)iface;
+    return InterlockedIncrement(&This->refs);
+}
+
+static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
+{
+    TLB_NEFile *This = (TLB_NEFile *)iface;
+    ULONG refs = InterlockedDecrement(&This->refs);
+    if (!refs)
+    {
+        HeapFree(GetProcessHeap(), 0, This->typelib_base);
+        HeapFree(GetProcessHeap(), 0, This);
+    }
+    return refs;
+}
+
+static const IUnknownVtbl TLB_NEFile_Vtable =
+{
+    TLB_NEFile_QueryInterface,
+    TLB_NEFile_AddRef,
+    TLB_NEFile_Release
+};
+
+/***********************************************************************
+ *           read_xx_header         [internal]
+ */
+static int read_xx_header( HFILE lzfd )
+{
+    IMAGE_DOS_HEADER mzh;
+    char magic[3];
+
+    LZSeek( lzfd, 0, SEEK_SET );
+    if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
+        return 0;
+    if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
+        return 0;
+
+    LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
+    if ( 2 != LZRead( lzfd, magic, 2 ) )
+        return 0;
+
+    LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
+
+    if ( magic[0] == 'N' && magic[1] == 'E' )
+        return IMAGE_OS2_SIGNATURE;
+    if ( magic[0] == 'P' && magic[1] == 'E' )
+        return IMAGE_NT_SIGNATURE;
+
+    magic[2] = '\0';
+    WARN("Can't handle %s files.\n", magic );
+    return 0;
+}
+
+
+/***********************************************************************
+ *           find_ne_resource         [internal]
+ */
+static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
+                                DWORD *resLen, DWORD *resOff )
+{
+    IMAGE_OS2_HEADER nehd;
+    NE_TYPEINFO *typeInfo;
+    NE_NAMEINFO *nameInfo;
+    DWORD nehdoffset;
+    LPBYTE resTab;
+    DWORD resTabSize;
+    int count;
+
+    /* Read in NE header */
+    nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
+    if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
+
+    resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
+    if ( !resTabSize )
+    {
+        TRACE("No resources in NE dll\n" );
+        return FALSE;
+    }
+
+    /* Read in resource table */
+    resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
+    if ( !resTab ) return FALSE;
+
+    LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
+    if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
+    {
+        HeapFree( GetProcessHeap(), 0, resTab );
+        return FALSE;
+    }
+
+    /* Find resource */
+    typeInfo = (NE_TYPEINFO *)(resTab + 2);
+
+    if (!IS_INTRESOURCE(typeid))  /* named type */
+    {
+        BYTE len = strlen( typeid );
+        while (typeInfo->type_id)
+        {
+            if (!(typeInfo->type_id & 0x8000))
+            {
+                BYTE *p = resTab + typeInfo->type_id;
+                if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
+            }
+            typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
+                                       typeInfo->count * sizeof(NE_NAMEINFO));
+        }
+    }
+    else  /* numeric type id */
+    {
+        WORD id = LOWORD(typeid) | 0x8000;
+        while (typeInfo->type_id)
+        {
+            if (typeInfo->type_id == id) goto found_type;
+            typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
+                                       typeInfo->count * sizeof(NE_NAMEINFO));
+        }
+    }
+    TRACE("No typeid entry found for %p\n", typeid );
+    HeapFree( GetProcessHeap(), 0, resTab );
+    return FALSE;
+
+ found_type:
+    nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
+
+    if (!IS_INTRESOURCE(resid))  /* named resource */
+    {
+        BYTE len = strlen( resid );
+        for (count = typeInfo->count; count > 0; count--, nameInfo++)
+        {
+            BYTE *p = resTab + nameInfo->id;
+            if (nameInfo->id & 0x8000) continue;
+            if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
+        }
+    }
+    else  /* numeric resource id */
+    {
+        WORD id = LOWORD(resid) | 0x8000;
+        for (count = typeInfo->count; count > 0; count--, nameInfo++)
+            if (nameInfo->id == id) goto found_name;
+    }
+    TRACE("No resid entry found for %p\n", typeid );
+    HeapFree( GetProcessHeap(), 0, resTab );
+    return FALSE;
+
+ found_name:
+    /* Return resource data */
+    if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
+    if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
+
+    HeapFree( GetProcessHeap(), 0, resTab );
+    return TRUE;
+}
+
+static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
+
+    HFILE lzfd = -1;
+    OFSTRUCT ofs;
+    HRESULT hr = TYPE_E_CANTLOADLIBRARY;
+    TLB_NEFile *This = NULL;
+
+    This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
+    if (!This) return E_OUTOFMEMORY;
+
+    This->lpvtbl = &TLB_NEFile_Vtable;
+    This->refs = 1;
+    This->typelib_base = NULL;
+
+    lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
+    if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
+    {
+        DWORD reslen, offset;
+        if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
+        {
+            This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen);
+            if( !This->typelib_base )
+                hr = E_OUTOFMEMORY;
+            else
+            {
+                LZSeek( lzfd, offset, SEEK_SET );
+                reslen = LZRead( lzfd, This->typelib_base, reslen );
+                LZClose( lzfd );
+                *ppBase = This->typelib_base;
+                *pdwTLBLength = reslen;
+                *ppFile = (IUnknown *)&This->lpvtbl;
+                return S_OK;
+            }
+        }
+    }
+
+    if( lzfd >= 0) LZClose( lzfd );
+    TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
+    return hr;
+}
 
 typedef struct TLB_Mapping
 {
@@ -2438,7 +2757,7 @@ static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath
     if(index_str && *++index_str != '\0')
     {
         LPWSTR end_ptr;
-        long idx = strtolW(index_str, &end_ptr, 10);
+        LONG idx = strtolW(index_str, &end_ptr, 10);
         if(*end_ptr == '\0')
         {
             int str_len = index_str - pszFileName - 1;
@@ -2485,6 +2804,8 @@ static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath
     /* now actually load and parse the typelib */
 
     ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
+    if (ret == TYPE_E_CANTLOADLIBRARY)
+        ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
     if (ret == TYPE_E_CANTLOADLIBRARY)
         ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
     if (SUCCEEDED(ret))
@@ -2556,7 +2877,7 @@ static ITypeLibImpl* TypeLibImpl_Constructor(void)
 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
 {
     TLBContext cx;
-    long lPSegDir;
+    LONG lPSegDir;
     MSFT_Header tlbHeader;
     MSFT_SegDir tlbSegDir;
     ITypeLibImpl * pTypeLibImpl;
@@ -2589,14 +2910,14 @@ static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
     lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
 
     /* now read the segment directory */
-    TRACE("read segment directory (at %ld)\n",lPSegDir);
+    TRACE("read segment directory (at %d)\n",lPSegDir);
     MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
     cx.pTblDir = &tlbSegDir;
 
     /* just check two entries */
     if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
     {
-        ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
+        ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
        HeapFree(GetProcessHeap(),0,pTypeLibImpl);
        return NULL;
     }
@@ -2605,18 +2926,14 @@ static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
     /* TLIBATTR fields */
     MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
 
-    /*    pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
-    /* Windows seems to have zero here, is this correct? */
-    if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
-      pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
-    else
-      pTypeLibImpl->LibAttr.lcid = 0;
-
+    pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
     pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
     pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
     pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
     pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
 
+    pTypeLibImpl->lcid = tlbHeader.lcid;
+
     /* name, eventually add to a hash table */
     pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
 
@@ -2662,7 +2979,7 @@ static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
            else if(td[0] == VT_CARRAY)
             {
                /* array descr table here */
-               pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]);  /* temp store offset in*/
+               pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2];  /* temp store offset in*/
             }
             else if(td[0] == VT_USERDEFINED)
            {
@@ -2677,13 +2994,13 @@ static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
             if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
             if(tlbSegDir.pArrayDescriptions.offset>0)
            {
-                MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
+                MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
                 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
 
                 if(td[1]<0)
                     pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
                 else
-                    pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
+                    pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
 
                 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
 
@@ -2727,6 +3044,7 @@ static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
             name = TLB_Alloc(size+1);
             MSFT_Read(name, size, &cx, DO_NOT_SEEK);
             (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
+            TLB_Free(name);
 
             MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
             offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
@@ -2791,7 +3109,7 @@ static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
     bytelen = *(const WORD*)ptr;
     if(bytelen == 0xffff) return 2;
     len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
-    *pBstr = SysAllocStringLen(NULL, len - 1);
+    *pBstr = SysAllocStringLen(NULL, len);
     if (*pBstr)
         len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
     return bytelen + 2;
@@ -2838,9 +3156,9 @@ static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
     ptr += 2;
 
     if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
-        pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
+        pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
     else
-        pTypeLibImpl->LibAttr.lcid = 0;
+        pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
     ptr += 2;
 
     ptr += 4; /* skip res12 */
@@ -2870,7 +3188,7 @@ typedef struct
 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
                                    HREFTYPE *typelib_ref)
 {
-    if(typeinfo_ref < table->num)
+    if(table && typeinfo_ref < table->num)
     {
         *typelib_ref = table->refs[typeinfo_ref];
         return S_OK;
@@ -2973,7 +3291,7 @@ static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
                        char *pNameTable)
 {
-    int ref;
+    unsigned int ref;
     char *name;
     TLBRefType *ref_type;
     sltg_ref_lookup_t *table;
@@ -3412,6 +3730,9 @@ static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
   if (pTITail->funcs_off != 0xffff)
     SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
 
+  if (pTITail->impls_off != 0xffff)
+    SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
+
   /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
    * of dispinterface functions including the IDispatch ones, so
    * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
@@ -3528,7 +3849,7 @@ static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
 
     pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
 
-    pFirstBlk = (LPVOID)(pPad9 + 1);
+    pFirstBlk = pPad9 + 1;
 
     /* We'll set up a ptr to the main library block, which is the last one. */
 
@@ -3671,6 +3992,9 @@ static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
       (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
        (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
 
+      if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
+       (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
+
       if((pTIHeader->typeflags1 & 7) != 2)
        FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
       if(pTIHeader->typeflags3 != 2)
@@ -3732,23 +4056,23 @@ static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
 
       }
 
-      if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
+      /* could get cFuncs, cVars and cImplTypes from here
                       but we've already set those */
 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
-         X(06);
-         X(16);
-         X(18);
-         X(1a);
-         X(1e);
-         X(24);
-         X(26);
-         X(2a);
-         X(2c);
-         X(2e);
-         X(30);
-         X(32);
-         X(34);
-      }
+      X(06);
+      X(16);
+      X(18);
+      X(1a);
+      X(1e);
+      X(24);
+      X(26);
+      X(2a);
+      X(2c);
+      X(2e);
+      X(30);
+      X(32);
+      X(34);
+#undef X
       ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
       pBlk = (char*)pBlk + pBlkEntry[order].len;
     }
@@ -3819,6 +4143,7 @@ static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
       TLBRefType *ref_type;
       void *cursor2;
       int i;
+      ITypeInfoImpl *pTI, *pTINext;
 
       /* remove cache entry */
       if(This->path)
@@ -3833,29 +4158,17 @@ static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
       }
       TRACE(" destroying ITypeLib(%p)\n",This);
 
-      if (This->Name)
-      {
-          SysFreeString(This->Name);
-          This->Name = NULL;
-      }
+      SysFreeString(This->Name);
+      This->Name = NULL;
 
-      if (This->DocString)
-      {
-          SysFreeString(This->DocString);
-          This->DocString = NULL;
-      }
+      SysFreeString(This->DocString);
+      This->DocString = NULL;
 
-      if (This->HelpFile)
-      {
-          SysFreeString(This->HelpFile);
-          This->HelpFile = NULL;
-      }
+      SysFreeString(This->HelpFile);
+      This->HelpFile = NULL;
 
-      if (This->HelpStringDll)
-      {
-          SysFreeString(This->HelpStringDll);
-          This->HelpStringDll = NULL;
-      }
+      SysFreeString(This->HelpStringDll);
+      This->HelpStringDll = NULL;
 
       for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
       {
@@ -3887,8 +4200,11 @@ static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
           TLB_Free(ref_type);
       }
 
-      if (This->pTypeInfo) /* can be NULL */
-         ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
+      for (pTI = This->pTypeInfo; pTI; pTI = pTINext)
+      {
+          pTINext = pTI->next;
+          ITypeInfo_fnDestroy(pTI);
+      }
       HeapFree(GetProcessHeap(),0,This);
       return 0;
     }
@@ -3916,7 +4232,7 @@ static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
     UINT index,
     ITypeInfo **ppTInfo)
 {
-    int i;
+    UINT i;
 
     ITypeLibImpl *This = (ITypeLibImpl *)iface;
     ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
@@ -3954,9 +4270,9 @@ static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
     TYPEKIND *pTKind)
 {
     ITypeLibImpl *This = (ITypeLibImpl *)iface;
-    int i;
+    UINT i;
     ITypeInfoImpl *pTInfo = This->pTypeInfo;
-    
+
     if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
         return TYPE_E_ELEMENTNOTFOUND;
 
@@ -4458,6 +4774,7 @@ static HRESULT WINAPI ITypeLibComp_fnBind(
 {
     ITypeLibImpl *This = impl_from_ITypeComp(iface);
     ITypeInfoImpl *pTypeInfo;
+    int typemismatch=0;
 
     TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
 
@@ -4497,6 +4814,8 @@ static HRESULT WINAPI ITypeLibComp_fnBind(
                 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
                 return S_OK;
             }
+            else if (hr == TYPE_E_TYPEMISMATCH)
+                typemismatch = 1;
         }
 
         if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
@@ -4512,13 +4831,7 @@ static HRESULT WINAPI ITypeLibComp_fnBind(
                 &subtypeinfo, &subdesckind, &subbindptr);
             if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
             {
-                TYPEDESC tdesc_appobject =
-                {
-                    {
-                        (TYPEDESC *)pTypeInfo->hreftype
-                    },
-                    VT_USERDEFINED
-                };
+                TYPEDESC tdesc_appobject;
                 const VARDESC vardesc_appobject =
                 {
                     -2,         /* memid */
@@ -4540,6 +4853,9 @@ static HRESULT WINAPI ITypeLibComp_fnBind(
                     VAR_STATIC  /* varkind */
                 };
 
+                tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
+                tdesc_appobject.vt = VT_USERDEFINED;
+
                 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
 
                 /* cleanup things filled in by Bind call so we can put our
@@ -4569,11 +4885,21 @@ static HRESULT WINAPI ITypeLibComp_fnBind(
                 ITypeInfo_AddRef(*ppTInfo);
                 return S_OK;
             }
+            else if (hr == TYPE_E_TYPEMISMATCH)
+                typemismatch = 1;
         }
     }
 
-    TRACE("name not found %s\n", debugstr_w(szName));
-    return S_OK;
+    if (typemismatch)
+    {
+        TRACE("type mismatch %s\n", debugstr_w(szName));
+        return TYPE_E_TYPEMISMATCH;
+    }
+    else
+    {
+        TRACE("name not found %s\n", debugstr_w(szName));
+        return S_OK;
+    }
 }
 
 static HRESULT WINAPI ITypeLibComp_fnBindType(
@@ -4583,8 +4909,29 @@ static HRESULT WINAPI ITypeLibComp_fnBindType(
     ITypeInfo ** ppTInfo,
     ITypeComp ** ppTComp)
 {
-    FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
-    return E_NOTIMPL;
+    ITypeLibImpl *This = impl_from_ITypeComp(iface);
+    ITypeInfoImpl *pTypeInfo;
+
+    TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
+
+    for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
+    {
+        /* FIXME: should use lHash to do the search */
+        if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
+        {
+            TRACE("returning %p\n", pTypeInfo);
+            *ppTInfo = (ITypeInfo *)&pTypeInfo->lpVtbl;
+            ITypeInfo_AddRef(*ppTInfo);
+            *ppTComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
+            ITypeComp_AddRef(*ppTComp);
+            return S_OK;
+        }
+    }
+
+    TRACE("not found\n");
+    *ppTInfo = NULL;
+    *ppTComp = NULL;
+    return S_OK;
 }
 
 static const ITypeCompVtbl tlbtcvt =
@@ -4599,7 +4946,7 @@ static const ITypeCompVtbl tlbtcvt =
 };
 
 /*================== ITypeInfo(2) Methods ===================================*/
-static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
+static ITypeInfo2 * ITypeInfo_Constructor(void)
 {
     ITypeInfoImpl * pTypeInfoImpl;
 
@@ -4608,7 +4955,7 @@ static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
     {
       pTypeInfoImpl->lpVtbl = &tinfvt;
       pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
-      pTypeInfoImpl->ref=1;
+      pTypeInfoImpl->ref = 0;
       pTypeInfoImpl->hreftype = -1;
       pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
       pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
@@ -4650,106 +4997,96 @@ static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
     ULONG ref = InterlockedIncrement(&This->ref);
 
-    ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
-
     TRACE("(%p)->ref is %u\n",This, ref);
+
+    if (ref == 1 /* incremented from 0 */)
+        ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
+
     return ref;
 }
 
-/* ITypeInfo::Release
- */
-static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
+static void ITypeInfo_fnDestroy(ITypeInfoImpl *This)
 {
-    ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
-    ULONG ref = InterlockedDecrement(&This->ref);
-
-    TRACE("(%p)->(%u)\n",This, ref);
+    TLBFuncDesc *pFInfo, *pFInfoNext;
+    TLBVarDesc *pVInfo, *pVInfoNext;
+    TLBImplType *pImpl, *pImplNext;
 
-    if (ref)   {
-      /* We don't release ITypeLib when ref=0 because
-         it means that function is called by ITypeLib2_Release */
-      ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
-    } else   {
-      TLBFuncDesc *pFInfo, *pFInfoNext;
-      TLBVarDesc *pVInfo, *pVInfoNext;
-      TLBImplType *pImpl, *pImplNext;
+    TRACE("destroying ITypeInfo(%p)\n",This);
 
-      TRACE("destroying ITypeInfo(%p)\n",This);
+    SysFreeString(This->Name);
+    This->Name = NULL;
 
-      if (This->no_free_data)
-          goto finish_free;
+    SysFreeString(This->DocString);
+    This->DocString = NULL;
 
-      if (This->Name)
-      {
-          SysFreeString(This->Name);
-          This->Name = 0;
-      }
+    SysFreeString(This->DllName);
+    This->DllName = NULL;
 
-      if (This->DocString)
-      {
-          SysFreeString(This->DocString);
-          This->DocString = 0;
-      }
+    for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
+    {
+        INT i;
+        for(i = 0;i < pFInfo->funcdesc.cParams; i++)
+        {
+            ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
+            if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
+            {
+                VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
+                TLB_Free(elemdesc->u.paramdesc.pparamdescex);
+            }
+            SysFreeString(pFInfo->pParamDesc[i].Name);
+        }
+        TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
+        TLB_Free(pFInfo->pParamDesc);
+        TLB_FreeCustData(pFInfo->pCustData);
+        if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
+            SysFreeString(pFInfo->Entry);
+        SysFreeString(pFInfo->HelpString);
+        SysFreeString(pFInfo->Name);
+
+        pFInfoNext = pFInfo->next;
+        TLB_Free(pFInfo);
+    }
+    for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
+    {
+        if (pVInfo->vardesc.varkind == VAR_CONST)
+        {
+            VariantClear(pVInfo->vardesc.u.lpvarValue);
+            TLB_Free(pVInfo->vardesc.u.lpvarValue);
+        }
+        TLB_FreeCustData(pVInfo->pCustData);
+        SysFreeString(pVInfo->Name);
+        pVInfoNext = pVInfo->next;
+        TLB_Free(pVInfo);
+    }
+    for (pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
+    {
+        TLB_FreeCustData(pImpl->pCustData);
+        pImplNext = pImpl->next;
+        TLB_Free(pImpl);
+    }
+    TLB_FreeCustData(This->pCustData);
 
-      if (This->DllName)
-      {
-          SysFreeString(This->DllName);
-          This->DllName = 0;
-      }
+    HeapFree(GetProcessHeap(), 0, This);
+}
 
-      for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
-      {
-          UINT i;
-          for(i = 0;i < pFInfo->funcdesc.cParams; i++)
-          {
-              ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
-              if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
-              {
-                  VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
-                  TLB_Free(elemdesc->u.paramdesc.pparamdescex);
-              }
-              SysFreeString(pFInfo->pParamDesc[i].Name);
-          }
-          TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
-          TLB_Free(pFInfo->pParamDesc);
-          TLB_FreeCustData(pFInfo->pCustData);
-          if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1) 
-              SysFreeString(pFInfo->Entry);
-          SysFreeString(pFInfo->HelpString);
-          SysFreeString(pFInfo->Name);
-
-          pFInfoNext = pFInfo->next;
-          TLB_Free(pFInfo);
-      }
-      for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
-      {
-          if (pVInfo->vardesc.varkind == VAR_CONST)
-          {
-              VariantClear(pVInfo->vardesc.u.lpvarValue);
-              TLB_Free(pVInfo->vardesc.u.lpvarValue);
-          }
-          TLB_FreeCustData(pVInfo->pCustData);
-          SysFreeString(pVInfo->Name);
-          pVInfoNext = pVInfo->next;
-          TLB_Free(pVInfo);
-      }
-      for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
-      {
-          TLB_FreeCustData(pImpl->pCustData);
-          pImplNext = pImpl->next;
-          TLB_Free(pImpl);
-      }
-      TLB_FreeCustData(This->pCustData);
+/* ITypeInfo::Release
+ */
+static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
+{
+    ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+    ULONG ref = InterlockedDecrement(&This->ref);
 
-finish_free:
-      if (This->next)
-      {
-        ITypeInfo_Release((ITypeInfo*)This->next);
-      }
+    TRACE("(%p)->(%u)\n",This, ref);
 
-      HeapFree(GetProcessHeap(),0,This);
-      return 0;
+    if (!ref)
+    {
+        BOOL not_attached_to_typelib = This->not_attached_to_typelib;
+        ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
+        if (not_attached_to_typelib)
+            HeapFree(GetProcessHeap(), 0, This);
+        /* otherwise This will be freed when typelib is freed */
     }
+
     return ref;
 }
 
@@ -4779,12 +5116,12 @@ static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
 
     if (This->TypeAttr.typekind == TKIND_ALIAS)
         TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
-            &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
+            &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
 
     if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
-        (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
-                                                                 funcs */
-        (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
+        /* This should include all the inherited funcs */
+        (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
+        (*ppTypeAttr)->cbSizeVft = 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */
         (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
     }
     return S_OK;
@@ -4934,7 +5271,7 @@ HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const F
 {
     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
     const TLBFuncDesc *pFDesc;
-    int i;
+    UINT i;
 
     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
         ;
@@ -5102,7 +5439,7 @@ static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
         hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
         if (FAILED(hr))
         {
-            SysFreeString((BSTR)dest_ptr);
+            SysFreeString((BSTR)dest);
             return hr;
         }
     }
@@ -5127,7 +5464,7 @@ static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
         LPVARDESC  *ppVarDesc)
 {
     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
-    int i;
+    UINT i;
     const TLBVarDesc *pVDesc;
 
     TRACE("(%p) index %d\n", This, index);
@@ -5219,7 +5556,7 @@ static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
        HREFTYPE  *pRefType)
 {
     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
-    int i;
+    UINT i;
     HRESULT hr = S_OK;
     const TLBImplType *pImpl = This->impltypelist;
 
@@ -5233,8 +5570,7 @@ static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
       */
       if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
 
-      if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
-          This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
+      if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
       {
         *pRefType = -1;
       }
@@ -5282,7 +5618,7 @@ static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
         UINT index, INT  *pImplTypeFlags)
 {
     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
-    int i;
+    UINT i;
     TLBImplType *pImpl;
 
     TRACE("(%p) index %d\n", This, index);
@@ -5294,6 +5630,11 @@ static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
         return S_OK;
     }
     *pImplTypeFlags=0;
+
+    if(This->TypeAttr.typekind==TKIND_DISPATCH && !index)
+        return S_OK;
+
+    WARN("ImplType %d not found\n", index);
     return TYPE_E_ELEMENTNOTFOUND;
 }
 
@@ -5308,7 +5649,7 @@ static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
     const TLBFuncDesc *pFDesc;
     const TLBVarDesc *pVDesc;
     HRESULT ret=S_OK;
-    int i;
+    UINT i;
 
     TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
             cNames);
@@ -5357,6 +5698,41 @@ static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
     return DISP_E_UNKNOWNNAME;
 }
 
+
+#ifdef __i386__
+
+extern DWORD CDECL call_method( void *func, int nb_args, const DWORD *args );
+__ASM_GLOBAL_FUNC( call_method,
+                   "pushl %ebp\n\t"
+                   __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
+                   __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
+                   "movl %esp,%ebp\n\t"
+                   __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
+                   "pushl %esi\n\t"
+                  __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
+                   "pushl %edi\n\t"
+                  __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
+                   "movl 12(%ebp),%edx\n\t"
+                   "shll $2,%edx\n\t"
+                   "jz 1f\n\t"
+                   "subl %edx,%esp\n\t"
+                   "andl $~15,%esp\n\t"
+                   "movl 12(%ebp),%ecx\n\t"
+                   "movl 16(%ebp),%esi\n\t"
+                   "movl %esp,%edi\n\t"
+                   "cld\n\t"
+                   "rep; movsl\n"
+                   "1:\tcall *8(%ebp)\n\t"
+                   "leal -8(%ebp),%esp\n\t"
+                   "popl %edi\n\t"
+                   __ASM_CFI(".cfi_same_value %edi\n\t")
+                   "popl %esi\n\t"
+                   __ASM_CFI(".cfi_same_value %esi\n\t")
+                   "popl %ebp\n\t"
+                   __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
+                   __ASM_CFI(".cfi_same_value %ebp\n\t")
+                   "ret" )
+
 /* ITypeInfo::Invoke
  *
  * Invokes a method, or accesses a property of an object, that implements the
@@ -5369,112 +5745,15 @@ _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
     if (TRACE_ON(ole)) {
        int i;
        TRACE("Calling %p(",func);
-       for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
+       for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
+       if (nrargs > 30) TRACE("...");
        TRACE(")\n");
     }
 
     switch (callconv) {
     case CC_STDCALL:
-
-       switch (nrargs) {
-       case 0:
-               res = func();
-               break;
-       case 1:
-               res = func(args[0]);
-               break;
-       case 2:
-               res = func(args[0],args[1]);
-               break;
-       case 3:
-               res = func(args[0],args[1],args[2]);
-               break;
-       case 4:
-               res = func(args[0],args[1],args[2],args[3]);
-               break;
-       case 5:
-               res = func(args[0],args[1],args[2],args[3],args[4]);
-               break;
-       case 6:
-               res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
-               break;
-       case 7:
-               res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
-               break;
-       case 8:
-               res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
-               break;
-       case 9:
-               res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
-               break;
-       case 10:
-               res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
-               break;
-       case 11:
-               res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
-               break;
-       case 12:
-               res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]);
-               break;
-       case 13:
-               res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]);
-               break;
-       case 14:
-               res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]);
-               break;
-       case 15:
-               res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14]);
-               break;
-       case 16:
-               res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15]);
-               break;
-       case 17:
-               res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16]);
-               break;
-       case 18:
-               res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17]);
-               break;
-       case 19:
-               res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18]);
-               break;
-       case 20:
-               res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19]);
-               break;
-       case 21:
-               res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20]);
-               break;
-       case 22:
-               res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21]);
-               break;
-       case 23:
-               res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22]);
-               break;
-       case 24:
-                res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23]);
-                break;
-       case 25:
-                res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24]);
-                break;
-       case 26:
-                res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25]);
-                break;
-       case 27:
-                res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26]);
-                break;
-       case 28:
-                res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27]);
-                break;
-       case 29:
-                res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28]);
-                break;
-       case 30:
-                res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28],args[29]);
-                break;
-       default:
-               FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
-               res = -1;
-               break;
-       }
+    case CC_CDECL:
+        res = call_method( func, nrargs, args );
        break;
     default:
        FIXME("unsupported calling convention %d\n",callconv);
@@ -5488,7 +5767,7 @@ _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
 /* The size of the argument on the stack in DWORD units (in all x86 call
  * convetions the arguments on the stack are DWORD-aligned)
  */
-int _dispargsize(VARTYPE vt)
+static int _dispargsize(VARTYPE vt)
 {
     switch (vt) {
     case VT_I8:
@@ -5511,6 +5790,7 @@ int _dispargsize(VARTYPE vt)
        return 1;
     }
 }
+#endif /* __i386__ */
 
 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
 {
@@ -5634,6 +5914,12 @@ static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc,
         *vt |= VT_ARRAY;
         hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
         break;
+    case VT_INT:
+        *vt |= VT_I4;
+        break;
+    case VT_UINT:
+        *vt |= VT_UI4;
+        break;
     default:
         *vt |= tdesc->vt;
         break;
@@ -5684,7 +5970,9 @@ DispCallFunc(
     void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
     VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
 {
-    int i, argsize, argspos;
+#ifdef __i386__
+    int argsize, argspos;
+    UINT i;
     DWORD *args;
     HRESULT hres;
 
@@ -5698,7 +5986,7 @@ DispCallFunc(
 
     for (i=0;i<cActuals;i++)
     {
-        TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i]));
+        TRACE("arg %u: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i]));
         dump_Variant(prgpvarg[i]);
         argsize += _dispargsize(prgvt[i]);
     }
@@ -5714,7 +6002,7 @@ DispCallFunc(
     for (i=0;i<cActuals;i++)
     {
         VARIANT *arg = prgpvarg[i];
-        TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
+        TRACE("Storing arg %u (%d as %d)\n",i,V_VT(arg),prgvt[i]);
         if (prgvt[i] == VT_VARIANT)
             memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD));
         else
@@ -5738,15 +6026,18 @@ DispCallFunc(
         V_VT(pvargResult) = vtReturn;
         V_UI4(pvargResult) = hres;
     }
-
     HeapFree(GetProcessHeap(),0,args);
     return S_OK;
+#else
+    FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
+           pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
+    return E_NOTIMPL;
+#endif
 }
 
 #define INVBUF_ELEMENT_SIZE \
     (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
-#define INVBUF_GET_ARG_ARRAY(buffer, params) \
-    ((VARIANTARG *)(buffer))
+#define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
     ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
@@ -5775,6 +6066,9 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
       This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
     );
 
+    if( This->TypeAttr.wTypeFlags & TYPEFLAG_FRESTRICTED )
+        return DISP_E_MEMBERNOTFOUND;
+
     if (!pDispParams)
     {
         ERR("NULL pDispParams not allowed\n");
@@ -5794,7 +6088,8 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
      * FUNCDESC for dispinterfaces and we want the real function description */
     for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
         if ((memid == pFuncInfo->funcdesc.memid) &&
-            (wFlags & pFuncInfo->funcdesc.invkind))
+            (wFlags & pFuncInfo->funcdesc.invkind) &&
+            (pFuncInfo->funcdesc.wFuncFlags & FUNCFLAG_FRESTRICTED) == 0)
             break;
 
     if (pFuncInfo) {
@@ -5817,6 +6112,7 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
             VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
             UINT cNamedArgs = pDispParams->cNamedArgs;
             DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
+            UINT vargs_converted=0;
 
             hres = S_OK;
 
@@ -5828,9 +6124,6 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
                     hres = DISP_E_PARAMNOTFOUND;
                     goto func_fail;
                 }
-                /* ignore the DISPID_PROPERTYPUT named argument from now on */
-                cNamedArgs--;
-                rgdispidNamedArgs++;
             }
 
             if (func_desc->cParamsOpt < 0 && cNamedArgs)
@@ -5854,19 +6147,33 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
                 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
                 VARIANTARG *src_arg;
 
+                if (wParamFlags & PARAMFLAG_FLCID)
+                {
+                    VARIANTARG *arg;
+                    arg = prgpvarg[i] = &rgvarg[i];
+                    V_VT(arg) = VT_I4;
+                    V_I4(arg) = This->pTypeLib->lcid;
+                    continue;
+                }
+
+                src_arg = NULL;
+
                 if (cNamedArgs)
                 {
                     USHORT j;
-                    src_arg = NULL;
                     for (j = 0; j < cNamedArgs; j++)
-                        if (rgdispidNamedArgs[j] == i)
+                        if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
                         {
                             src_arg = &pDispParams->rgvarg[j];
                             break;
                         }
                 }
-                else
-                    src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
+
+                if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
+                {
+                    src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
+                    vargs_converted++;
+                }
 
                 if (wParamFlags & PARAMFLAG_FRETVAL)
                 {
@@ -5915,7 +6222,8 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
                         else
                         {
                             VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
-                            hres = VariantCopy(&missing_arg[i], src_arg);
+                            if (wParamFlags & PARAMFLAG_FIN)
+                                hres = VariantCopy(&missing_arg[i], src_arg);
                             V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
                         }
                         V_VT(&rgvarg[i]) = rgvt[i];
@@ -5953,8 +6261,10 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
                     else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
                     {
                         VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
-                        V_VT(&missing_arg[i]) = V_VT(src_arg);
-                        hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
+                        if (wParamFlags & PARAMFLAG_FIN)
+                            hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
+                        else
+                            V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
                         V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
                         V_VT(&rgvarg[i]) = rgvt[i];
                     }
@@ -6032,10 +6342,16 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
                                 V_VT(&varresult), func_desc->cParams, rgvt,
                                 prgpvarg, &varresult);
 
+            vargs_converted = 0;
+
             for (i = 0; i < func_desc->cParams; i++)
             {
                 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
-                if (wParamFlags & PARAMFLAG_FRETVAL)
+                VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
+
+                if (wParamFlags & PARAMFLAG_FLCID)
+                    continue;
+                else if (wParamFlags & PARAMFLAG_FRETVAL)
                 {
                     if (TRACE_ON(ole))
                     {
@@ -6050,33 +6366,23 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
                         hres = VariantCopyInd(pVarResult, prgpvarg[i]);
                     }
 
-                    /* free data stored in varresult. Note that
-                     * VariantClear doesn't do what we want because we are
-                     * working with byref types. */
-                    /* FIXME: clear safearrays, bstrs, records and
-                     * variants here too */
-                    if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
-                         (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
-                    {
-                        if(*V_UNKNOWNREF(prgpvarg[i]))
-                            IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
-                    }
-                    break;
+                    VARIANT_ClearInd(prgpvarg[i]);
                 }
-                else if (i < pDispParams->cArgs)
+                else if (vargs_converted < pDispParams->cArgs)
                 {
+                    VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
                     if (wParamFlags & PARAMFLAG_FOUT)
                     {
-                        VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
-
-                        if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
+                        if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
+                        {
                             hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
 
-                        if (FAILED(hres))
-                        {
-                            ERR("failed to convert param %d to vt %d\n", i,
-                                V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
-                            break;
+                            if (FAILED(hres))
+                            {
+                                ERR("failed to convert param %d to vt %d\n", i,
+                                    V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
+                                break;
+                            }
                         }
                     }
                     else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
@@ -6108,12 +6414,15 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
                         }
                     }
                     VariantClear(&rgvarg[i]);
+                    vargs_converted++;
                 }
                 else if (wParamFlags & PARAMFLAG_FOPT)
                 {
                     if (wParamFlags & PARAMFLAG_FHASDEFAULT)
                         VariantClear(&rgvarg[i]);
                 }
+
+                VariantClear(&missing_arg[i]);
             }
 
             if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
@@ -6229,7 +6538,7 @@ func_fail:
             WARN("Could not search inherited interface!\n");
         }
     }
-    ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
+    WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
     return DISP_E_MEMBERNOTFOUND;
 }
 
@@ -6333,7 +6642,7 @@ static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid
            if (pBstrDllName)
                *pBstrDllName = SysAllocString(This->DllName);
 
-           if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
+            if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
                if (pBstrName)
                    *pBstrName = SysAllocString(pFDesc->Entry);
                if (pwOrdinal)
@@ -6343,7 +6652,7 @@ static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid
            if (pBstrName)
                *pBstrName = NULL;
            if (pwOrdinal)
-               *pwOrdinal = (DWORD)pFDesc->Entry;
+               *pwOrdinal = LOWORD(pFDesc->Entry);
            return S_OK;
         }
     return TYPE_E_ELEMENTNOTFOUND;
@@ -6421,20 +6730,18 @@ static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
 
          *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
 
-         /* we use data structures from This, so we need to keep a reference
-          * to it to stop it being destroyed and signal to the new instance to
+         /* the AddRef implicitly adds a reference to the parent typelib, which
+          * stops the copied data from being destroyed until the new typeinfo's
+          * refcount goes to zero, but we need to signal to the new instance to
           * not free its data structures when it is destroyed */
-         pTypeInfoImpl->no_free_data = TRUE;
-         pTypeInfoImpl->next = This;
-         ITypeInfo_AddRef((ITypeInfo*) This);
+         pTypeInfoImpl->not_attached_to_typelib = TRUE;
 
          ITypeInfo_AddRef(*ppTInfo);
 
          result = S_OK;
 
     } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
-        (This->TypeAttr.typekind   == TKIND_DISPATCH) &&
-       (This->TypeAttr.wTypeFlags &  TYPEFLAG_FDUAL))
+        (This->TypeAttr.typekind   == TKIND_DISPATCH))
     {
         HREFTYPE href_dispatch = hRefType;
         result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
@@ -6470,7 +6777,7 @@ static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
                                              ref_type->pImpTLInfo->lcid,
                                             &pTLib);
 
-                   if(!SUCCEEDED(result)) {
+                    if(FAILED(result)) {
                         BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
                        result=LoadTypeLib(libnam, &pTLib);
                        SysFreeString(libnam);
@@ -6526,7 +6833,7 @@ static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
     {
         ERR("couldn't load %s\n", debugstr_w(dll));
         SysFreeString(dll);
-        if (entry) SysFreeString(entry);
+        SysFreeString(entry);
         return STG_E_FILENOTFOUND;
     }
     /* FIXME: store library somewhere where we can free it */
@@ -6552,7 +6859,7 @@ static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
     }
 
     SysFreeString(dll);
-    if (entry) SysFreeString(entry);
+    SysFreeString(entry);
 
     if (!*ppv)
         return TYPE_E_DLLFUNCTIONNOTFOUND;
@@ -6623,7 +6930,8 @@ static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
                                BSTR  *pBstrMops)
 {
     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
-    FIXME("(%p) stub!\n", This);
+    FIXME("(%p %d) stub!\n", This, memid);
+    *pBstrMops = NULL;
     return S_OK;
 }
 
@@ -6801,13 +7109,12 @@ static HRESULT WINAPI ITypeInfo2_fnGetCustData(
 
     TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
 
-    if(pCData)
-    {
-        VariantInit( pVarVal);
+    VariantInit( pVarVal);
+    if (pCData)
         VariantCopy( pVarVal, &pCData->data);
-        return S_OK;
-    }
-    return E_INVALIDARG;  /* FIXME: correct? */
+    else
+        VariantClear( pVarVal );
+    return S_OK;
 }
 
 /* ITypeInfo2::GetFuncCustData
@@ -6823,7 +7130,7 @@ static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
     TLBCustData *pCData=NULL;
     TLBFuncDesc * pFDesc;
-    int i;
+    UINT i;
     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
             pFDesc=pFDesc->next);
 
@@ -6855,7 +7162,7 @@ static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
     TLBCustData *pCData=NULL;
     TLBFuncDesc * pFDesc;
-    int i;
+    UINT i;
 
     for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
 
@@ -6888,7 +7195,7 @@ static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
     TLBCustData *pCData=NULL;
     TLBVarDesc * pVDesc;
-    int i;
+    UINT i;
 
     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
 
@@ -6924,7 +7231,7 @@ static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
     TLBCustData *pCData=NULL;
     TLBImplType * pRDesc;
-    int i;
+    UINT i;
 
     for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
 
@@ -7051,7 +7358,7 @@ static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
     TLBCustData *pCData;
     TLBFuncDesc * pFDesc;
-    int i;
+    UINT i;
     TRACE("(%p) index %d\n", This, index);
     for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
             pFDesc=pFDesc->next)
@@ -7087,7 +7394,7 @@ static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
     TLBCustData *pCData=NULL;
     TLBFuncDesc * pFDesc;
-    int i;
+    UINT i;
     TRACE("(%p) index %d\n", This, indexFunc);
     for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
             pFDesc=pFDesc->next)
@@ -7124,7 +7431,7 @@ static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
     TLBCustData *pCData;
     TLBVarDesc * pVDesc;
-    int i;
+    UINT i;
     TRACE("(%p) index %d\n", This, index);
     for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
             pVDesc=pVDesc->next)
@@ -7162,7 +7469,7 @@ static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
     TLBCustData *pCData;
     TLBImplType * pRDesc;
-    int i;
+    UINT i;
     TRACE("(%p) index %d\n", This, index);
     for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
             pRDesc=pRDesc->next)
@@ -7252,7 +7559,7 @@ HRESULT WINAPI CreateDispTypeInfo(
 {
     ITypeInfoImpl *pTIClass, *pTIIface;
     ITypeLibImpl *pTypeLibImpl;
-    int param, func;
+    unsigned int param, func;
     TLBFuncDesc **ppFuncDesc;
     TLBRefType *ref;
 
@@ -7290,7 +7597,7 @@ HRESULT WINAPI CreateDispTypeInfo(
         (*ppFuncDesc)->funcdesc.callconv = md->cc;
         (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
         (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
-        (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
+        (*ppFuncDesc)->funcdesc.oVft = md->iMeth * sizeof(void *);
         (*ppFuncDesc)->funcdesc.cScodes = 0;
         (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
         (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
@@ -7394,9 +7701,9 @@ static HRESULT WINAPI ITypeComp_fnBind(
     ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
     const TLBFuncDesc *pFDesc;
     const TLBVarDesc *pVDesc;
-    HRESULT hr = DISP_E_MEMBERNOTFOUND;
+    HRESULT hr = S_OK;
 
-    TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
+    TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
 
     *pDescKind = DESCKIND_NONE;
     pBindPtr->lpfuncdesc = NULL;
@@ -7456,7 +7763,7 @@ static HRESULT WINAPI ITypeComp_fnBind(
         }
         WARN("Could not search inherited interface!\n");
     }
-    WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
+    TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
     return hr;
 }