Piotr Caban : oleaut32: Improved ICreateTypeInfo2_AddRefTypeInfo implementation.

Alexandre Julliard julliard at winehq.org
Tue Feb 23 11:17:22 CST 2010


Module: wine
Branch: master
Commit: 3647c337a9483096ef9af5d36658805819b50dd7
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=3647c337a9483096ef9af5d36658805819b50dd7

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Mon Feb 22 23:14:40 2010 +0100

oleaut32: Improved ICreateTypeInfo2_AddRefTypeInfo implementation.

---

 dlls/oleaut32/tests/typelib.c |   23 ++++++++++-
 dlls/oleaut32/typelib2.c      |   94 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 109 insertions(+), 8 deletions(-)

diff --git a/dlls/oleaut32/tests/typelib.c b/dlls/oleaut32/tests/typelib.c
index bcf959c..c821fac 100644
--- a/dlls/oleaut32/tests/typelib.c
+++ b/dlls/oleaut32/tests/typelib.c
@@ -969,6 +969,7 @@ if(use_midl_tlb) {
 }
 
 static void test_CreateTypeLib(void) {
+    static const WCHAR stdoleW[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
     static OLECHAR interface1W[] = {'i','n','t','e','r','f','a','c','e','1',0};
     static WCHAR defaultW[] = {'d','e','f','a','u','l','t',0x3213,0};
     static OLECHAR func1W[] = {'f','u','n','c','1',0};
@@ -982,15 +983,23 @@ static void test_CreateTypeLib(void) {
     WCHAR filenameW[MAX_PATH];
     ICreateTypeLib2 *createtl;
     ICreateTypeInfo *createti;
-    ITypeLib *tl;
+    ITypeLib *tl, *stdole;
+    ITypeInfo *unknown;
     FUNCDESC funcdesc;
     ELEMDESC elemdesc[5];
     PARAMDESCEX paramdescex;
     TYPEDESC typedesc1, typedesc2;
+    HREFTYPE hreftype;
     HRESULT hres;
 
     trace("CreateTypeLib tests\n");
 
+    hres = LoadTypeLib(stdoleW, &stdole);
+    ok(hres == S_OK, "got %08x\n", hres);
+
+    hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IUnknown, &unknown);
+    ok(hres == S_OK, "got %08x\n", hres);
+
     GetTempFileNameA(".", "tlb", 0, filename);
     MultiByteToWideChar(CP_ACP, 0, filename, -1, filenameW, MAX_PATH);
 
@@ -1003,6 +1012,15 @@ static void test_CreateTypeLib(void) {
     hres = ICreateTypeInfo_LayOut(createti);
     ok(hres == S_OK, "got %08x\n", hres);
 
+    hres = ICreateTypeInfo_AddRefTypeInfo(createti, NULL, &hreftype);
+    ok(hres == E_INVALIDARG, "got %08x\n", hres);
+
+    hres = ICreateTypeInfo_AddRefTypeInfo(createti, unknown, NULL);
+    ok(hres == E_INVALIDARG, "got %08x\n", hres);
+
+    hres = ICreateTypeInfo_AddRefTypeInfo(createti, unknown, &hreftype);
+    ok(hres == S_OK, "got %08x\n", hres);
+
     memset(&funcdesc, 0, sizeof(FUNCDESC));
     funcdesc.funckind = FUNC_PUREVIRTUAL;
     funcdesc.invkind = INVOKE_PROPERTYGET;
@@ -1135,7 +1153,10 @@ static void test_CreateTypeLib(void) {
     hres = LoadTypeLib(filenameW,  &tl);
     ok(hres == S_OK, "got %08x\n", hres);
 
+    ITypeInfo_Release(unknown);
+
     ITypeLib_Release(tl);
+    ITypeLib_Release(stdole);
 
     DeleteFileA(filename);
 }
diff --git a/dlls/oleaut32/typelib2.c b/dlls/oleaut32/typelib2.c
index 907eae1..38e15ea 100644
--- a/dlls/oleaut32/typelib2.c
+++ b/dlls/oleaut32/typelib2.c
@@ -43,6 +43,7 @@
 #include "windef.h"
 #include "winbase.h"
 #include "winnls.h"
+#include "winreg.h"
 #include "winuser.h"
 
 #include "wine/unicode.h"
@@ -707,6 +708,7 @@ static int ctl2_alloc_importinfo(
 static int ctl2_alloc_importfile(
 	ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
 	int guidoffset,            /* [I] The offset to the GUID for the imported library. */
+        LCID lcid,                 /* [I] The LCID of imported library. */
 	int major_version,         /* [I] The major version number of the imported library. */
 	int minor_version,         /* [I] The minor version number of the imported library. */
 	const WCHAR *filename)     /* [I] The filename of the imported library. */
@@ -732,7 +734,7 @@ static int ctl2_alloc_importfile(
 
     importfile = (MSFT_ImpFile *)&This->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset];
     importfile->guid = guidoffset;
-    importfile->lcid = This->typelib_header.lcid2;
+    importfile->lcid = lcid;
     importfile->version = major_version | (minor_version << 16);
     memcpy(importfile->filename, encoded_string, length);
 
@@ -1370,7 +1372,8 @@ static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface, U
 	guidoffset = ctl2_alloc_guid(This->typelib, &foo);
 	if (guidoffset == -1) return E_OUTOFMEMORY;
 
-	fileoffset =  ctl2_alloc_importfile(This->typelib, guidoffset, 2, 0, stdole2tlb);
+	fileoffset =  ctl2_alloc_importfile(This->typelib, guidoffset,
+                This->typelib->typelib_header.lcid2, 2, 0, stdole2tlb);
 	if (fileoffset == -1) return E_OUTOFMEMORY;
 
 	foo.guid = IID_IDispatch;
@@ -1471,10 +1474,10 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(
 
     TRACE("(%p,%p,%p)\n", iface, pTInfo, phRefType);
 
+    if(!pTInfo || !phRefType)
+        return E_INVALIDARG;
+
     /*
-     * If this is one of ours, we set *phRefType to the TYPEINFO offset of
-     * the referred TypeInfo. Otherwise, we presumably have more magic to do.
-     *
      * Unfortunately, we can't rely on the passed-in TypeInfo even having the
      * same internal structure as one of ours. It could be from another
      * implementation of ITypeInfo. So we need to do the following...
@@ -1486,9 +1489,86 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(
     }
 
     if (container == (ITypeLib *)&This->typelib->lpVtblTypeLib2) {
+        /* Process locally defined TypeInfo */
 	*phRefType = This->typelib->typelib_typeinfo_offsets[index];
     } else {
-	FIXME("(%p,%p,%p), pTInfo from different typelib.\n", iface, pTInfo, phRefType);
+        static const WCHAR regkey[] = {'T','y','p','e','L','i','b','\\','{',
+            '%','0','8','x','-','%','0','4','x','-','%','0','4','x','-','%',
+            '0','2','x','%','0','2','x','-','%','0','2','x','%','0','2','x',
+            '%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x',
+            '}','\\','%','d','.','%','d','\\','0','\\','w','i','n','3','2',0};
+
+        WCHAR name[MAX_PATH], *p;
+        TLIBATTR *tlibattr;
+        TYPEATTR *typeattr;
+        MSFT_GuidEntry guid;
+        MSFT_ImpInfo impinfo;
+        int guid_offset, import_offset;
+        DWORD len;
+        HRESULT hres;
+
+        /* Allocate container GUID */
+        hres = ITypeLib_GetLibAttr(container, &tlibattr);
+        if(FAILED(hres))
+            return hres;
+
+        guid.guid = tlibattr->guid;
+        guid.hreftype = 2;
+        guid.next_hash = -1;
+
+        guid_offset = ctl2_alloc_guid(This->typelib, &guid);
+        if(guid_offset == -1) {
+            ITypeLib_ReleaseTLibAttr(container, tlibattr);
+            return E_OUTOFMEMORY;
+        }
+
+        /* Get import file name */
+        /* Check HKEY_CLASSES_ROOT\TypeLib\{GUID}\{Ver}\0\win32 */
+        len = MAX_PATH;
+        sprintfW(name, regkey, guid.guid.Data1, guid.guid.Data2,
+                guid.guid.Data3, guid.guid.Data4[0], guid.guid.Data4[1],
+                guid.guid.Data4[2], guid.guid.Data4[3], guid.guid.Data4[4],
+                guid.guid.Data4[5], guid.guid.Data4[6], guid.guid.Data4[7],
+                tlibattr->wMajorVerNum, tlibattr->wMinorVerNum);
+
+        if(RegGetValueW(HKEY_CLASSES_ROOT, name, NULL, RRF_RT_REG_SZ, NULL, name, &len)!=ERROR_SUCCESS
+            || (p=strrchrW(name, '\\'))==NULL) {
+            ERR("Error guessing typelib filename\n");
+            ITypeLib_ReleaseTLibAttr(container, tlibattr);
+            return E_NOTIMPL;
+        }
+        memmove(name, p+1, strlenW(p)*sizeof(WCHAR));
+
+        /* Import file */
+        import_offset = ctl2_alloc_importfile(This->typelib, guid_offset,
+                tlibattr->lcid, tlibattr->wMajorVerNum, tlibattr->wMinorVerNum, name);
+        ITypeLib_ReleaseTLibAttr(container, tlibattr);
+
+        if(import_offset == -1)
+            return E_OUTOFMEMORY;
+
+        /* Allocate referenced guid */
+        hres = ITypeInfo_GetTypeAttr(pTInfo, &typeattr);
+        if(FAILED(hres))
+            return hres;
+
+        guid.guid = typeattr->guid;
+        guid.hreftype = 1;
+        guid.next_hash = -1;
+        ITypeInfo_ReleaseTypeAttr(pTInfo, typeattr);
+
+        guid_offset = ctl2_alloc_guid(This->typelib, &guid);
+        if(guid_offset == -1)
+            return E_OUTOFMEMORY;
+
+        /* Allocate importinfo */
+        impinfo.flags = ((This->typeinfo->typekind&0xf)<<24) | MSFT_IMPINFO_OFFSET_IS_GUID;
+        impinfo.oImpFile = import_offset;
+        impinfo.oGuid = guid_offset;
+        *phRefType = ctl2_alloc_importinfo(This->typelib, &impinfo)+1;
+
+        if(!memcmp(&guid.guid, &IID_IDispatch, sizeof(GUID)))
+            This->typelib->typelib_header.dispatchpos = *phRefType;
     }
 
     ITypeLib_Release(container);
@@ -1613,7 +1693,7 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(
     }
 
     /* update the index data */
-    insert->indice = (This->typeinfo->cImplTypes << 16) | pFuncDesc->memid;
+    insert->indice = pFuncDesc->memid;
     insert->name = -1;
 
     /* insert type data to list */




More information about the wine-cvs mailing list