[PATCH 1/5] oleaut32: Implement ICreateTypeInfo::AddRefTypeInfo

Andrew Eikum aeikum at codeweavers.com
Tue May 28 16:59:33 CDT 2013


This also corrects our HREFTYPE values a little bit.
---
 dlls/oleaut32/typelib.c | 204 ++++++++++++++++++++++++++++++++++++------------
 1 file changed, 155 insertions(+), 49 deletions(-)

diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c
index c9ee1cd..90d8c4d 100644
--- a/dlls/oleaut32/typelib.c
+++ b/dlls/oleaut32/typelib.c
@@ -1055,6 +1055,7 @@ typedef struct tagTLBRefType
 			       it the format is SLTG.  -2 indicates to
 			       use guid */
 
+    TYPEKIND tkind;
     GUID guid;              /* guid of the referenced type */
                             /* if index == TLB_REF_USE_GUID */
 
@@ -2337,7 +2338,7 @@ static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
                 break;
 
         if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
-            ref->reference = offset;
+            ref->reference = offset & (~0x3);
             ref->pImpTLInfo = pImpLib;
             if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
                 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
@@ -7121,22 +7122,27 @@ static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
         result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
     } else {
         TLBRefType *ref_type;
+        ITypeLib *pTLib = NULL;
         UINT i;
 
-        for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
-        {
-            if (This->pTypeLib->typeinfos[i]->hreftype == hRefType)
+        if(!(hRefType & 0x1)){
+            for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
             {
-                result = S_OK;
-                *ppTInfo = (ITypeInfo*)This->pTypeLib->typeinfos[i];
-                ITypeInfo_AddRef(*ppTInfo);
-                goto end;
+                if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
+                {
+                    result = S_OK;
+                    *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
+                    ITypeInfo_AddRef(*ppTInfo);
+                    goto end;
+                }
             }
+            result = TYPE_E_ELEMENTNOTFOUND;
+            goto end;
         }
 
         LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
         {
-            if(ref_type->reference == hRefType)
+            if(ref_type->reference == (hRefType & (~0x3)))
                 break;
         }
         if(&ref_type->entry == &This->pTypeLib->ref_list)
@@ -7144,46 +7150,44 @@ static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
             FIXME("Can't find pRefType for ref %x\n", hRefType);
             goto end;
         }
-        if(hRefType != -1) {
-            ITypeLib *pTLib = NULL;
 
-            if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
-	        UINT Index;
-		result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
-	    } else {
-                if(ref_type->pImpTLInfo->pImpTypeLib) {
-		    TRACE("typeinfo in imported typelib that is already loaded\n");
-                    pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
+        if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
+            UINT Index;
+            TRACE("internal reference\n");
+            result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
+        } else {
+            if(ref_type->pImpTLInfo->pImpTypeLib) {
+                TRACE("typeinfo in imported typelib that is already loaded\n");
+                pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
+                ITypeLib_AddRef(pTLib);
+                result = S_OK;
+            } else {
+                TRACE("typeinfo in imported typelib that isn't already loaded\n");
+                result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
+                                         ref_type->pImpTLInfo->wVersionMajor,
+                                         ref_type->pImpTLInfo->wVersionMinor,
+                                         ref_type->pImpTLInfo->lcid,
+                                         &pTLib);
+
+                if(FAILED(result)) {
+                    BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
+                    result=LoadTypeLib(libnam, &pTLib);
+                    SysFreeString(libnam);
+                }
+                if(SUCCEEDED(result)) {
+                    ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
                     ITypeLib_AddRef(pTLib);
-		    result = S_OK;
-		} else {
-		    TRACE("typeinfo in imported typelib that isn't already loaded\n");
-                    result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
-                                             ref_type->pImpTLInfo->wVersionMajor,
-                                             ref_type->pImpTLInfo->wVersionMinor,
-                                             ref_type->pImpTLInfo->lcid,
-					     &pTLib);
-
-                    if(FAILED(result)) {
-                        BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
-			result=LoadTypeLib(libnam, &pTLib);
-			SysFreeString(libnam);
-		    }
-		    if(SUCCEEDED(result)) {
-                        ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
-                        ITypeLib_AddRef(pTLib);
-		    }
-		}
-	    }
-	    if(SUCCEEDED(result)) {
-                if(ref_type->index == TLB_REF_USE_GUID)
-                    result = ITypeLib_GetTypeInfoOfGuid(pTLib, &ref_type->guid, ppTInfo);
-		else
-                    result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
-	    }
-	    if (pTLib != NULL)
-                ITypeLib_Release(pTLib);
-	}
+                }
+            }
+        }
+        if(SUCCEEDED(result)) {
+            if(ref_type->index == TLB_REF_USE_GUID)
+                result = ITypeLib_GetTypeInfoOfGuid(pTLib, &ref_type->guid, ppTInfo);
+            else
+                result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
+        }
+        if (pTLib != NULL)
+            ITypeLib_Release(pTLib);
     }
 
 end:
@@ -7875,6 +7879,7 @@ HRESULT WINAPI CreateDispTypeInfo(
     pTIIface->TypeAttr.cImplTypes = 0;
     pTIIface->TypeAttr.cVars = 0;
     pTIIface->TypeAttr.wTypeFlags = 0;
+    pTIIface->hreftype = 0;
 
     pTIIface->funcdescs = TLBFuncDesc_Constructor(pidata->cMembers);
     pFuncDesc = pTIIface->funcdescs;
@@ -7929,6 +7934,7 @@ HRESULT WINAPI CreateDispTypeInfo(
     pTIClass->TypeAttr.cImplTypes = 1;
     pTIClass->TypeAttr.cVars = 0;
     pTIClass->TypeAttr.wTypeFlags = 0;
+    pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
 
     pTIClass->impltypes = TLBImplType_Constructor(1);
 
@@ -8441,8 +8447,108 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
         ITypeInfo *typeInfo, HREFTYPE *refType)
 {
     ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
-    FIXME("%p %p %p - stub\n", This, typeInfo, refType);
-    return E_NOTIMPL;
+    UINT index;
+    ITypeLib *container;
+    TLBRefType *ref_type;
+    TLBImpLib *implib;
+    TYPEATTR *typeattr;
+    TLIBATTR *libattr;
+    HRESULT hres;
+
+    TRACE("%p %p %p\n", This, typeInfo, refType);
+
+    if (!typeInfo || !refType)
+        return E_INVALIDARG;
+
+    hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
+    if (FAILED(hres))
+        return hres;
+
+    if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
+        ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
+
+        ITypeLib_Release(container);
+
+        *refType = target->hreftype;
+
+        return S_OK;
+    }
+
+    hres = ITypeLib_GetLibAttr(container, &libattr);
+    if (FAILED(hres)) {
+        ITypeLib_Release(container);
+        return hres;
+    }
+
+    LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
+        if(IsEqualGUID(&implib->guid, &libattr->guid) &&
+                implib->lcid == libattr->lcid &&
+                implib->wVersionMajor == libattr->wMajorVerNum &&
+                implib->wVersionMinor == libattr->wMinorVerNum)
+            break;
+    }
+
+    if(&implib->entry == &This->pTypeLib->implib_list){
+        implib = heap_alloc_zero(sizeof(TLBImpLib));
+
+        if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
+            const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
+            implib->name = SysAllocString(our_container->path);
+        }else{
+            hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
+                    libattr->wMinorVerNum, libattr->lcid, &implib->name);
+            if(FAILED(hres)){
+                implib->name = NULL;
+                TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
+            }
+        }
+
+        implib->guid = libattr->guid;
+        implib->lcid = libattr->lcid;
+        implib->wVersionMajor = libattr->wMajorVerNum;
+        implib->wVersionMinor = libattr->wMinorVerNum;
+
+        list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
+    }
+
+    ITypeLib_ReleaseTLibAttr(container, libattr);
+    ITypeLib_Release(container);
+
+    hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
+    if (FAILED(hres))
+        return hres;
+
+    index = 0;
+    LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
+        if(ref_type->index == TLB_REF_USE_GUID &&
+                IsEqualGUID(&ref_type->guid, &typeattr->guid) &&
+                ref_type->tkind == typeattr->typekind)
+            break;
+        ++index;
+    }
+
+    if(&ref_type->entry == &This->pTypeLib->ref_list){
+        ref_type = heap_alloc_zero(sizeof(TLBRefType));
+
+        ref_type->tkind = typeattr->typekind;
+        ref_type->pImpTLInfo = implib;
+        ref_type->reference = index * sizeof(MSFT_ImpInfo);
+
+        ref_type->index = TLB_REF_USE_GUID;
+
+        ref_type->guid = typeattr->guid;
+
+        list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
+    }
+
+    ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
+
+    *refType = ref_type->reference | 0x1;
+
+    if(IsEqualGUID(&ref_type->guid, &IID_IDispatch))
+        This->pTypeLib->dispatch_href = *refType;
+
+    return S_OK;
 }
 
 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
-- 
1.8.3





More information about the wine-patches mailing list