Type library creation, take 3, part 3 of 6

Nyef nyef at softhome.net
Sat Feb 7 06:11:59 CST 2004


Hello all.

This is the third of six patches covering my changes to the
type library creation code over the past fortnight.

This patch contains:

    Preliminary support for ICreateTypeInfo::AddImplType().
    Support for ICreateTypeInfo::SetImplTypeFlags().

--Alastair Bridgewater
-------------- next part --------------
--- typelib2.c.last	2004-02-07 06:53:01.000000000 -0500
+++ typelib2.c	2004-02-07 06:53:04.000000000 -0500
@@ -942,6 +942,31 @@
     return 0;
 }
 
+/****************************************************************************
+ *	ctl2_find_nth_reference
+ *
+ *  Finds a reference by index into the linked list of reference records.
+ *
+ * RETURNS
+ *
+ *  Success: Offset of the desired reference record.
+ *  Failure: -1.
+ */
+static int ctl2_find_nth_reference(
+	ICreateTypeLib2Impl *This, /* [I] The type library in which to search. */
+	int offset,                /* [I] The starting offset of the reference list. */
+	int index)                 /* [I] The index of the reference to find. */
+{
+    MSFT_RefRecord *ref;
+
+    for (; index && (offset != -1); index--) {
+	ref = (MSFT_RefRecord *)&This->typelib_segment_data[MSFT_SEG_REFERENCES][offset];
+	offset = ref->onext;
+    }
+
+    return offset;
+}
+
 /*================== ICreateTypeInfo2 Implementation ===================================*/
 
 /******************************************************************************
@@ -1288,8 +1313,63 @@
         UINT index,
         HREFTYPE hRefType)
 {
-    FIXME("(%p,%d,%ld), stub!\n", iface, index, hRefType);
-    return E_OUTOFMEMORY;
+    ICOM_THIS(ICreateTypeInfo2Impl, iface);
+
+    TRACE("(%p,%d,%ld)\n", iface, index, hRefType);
+
+    if ((This->typeinfo->typekind & 15) == TKIND_COCLASS) {
+	int offset;
+	MSFT_RefRecord *ref;
+
+	if (index == 0) {
+	    if (This->typeinfo->datatype1 != -1) return TYPE_E_ELEMENTNOTFOUND;
+
+	    offset = ctl2_alloc_segment(This->typelib, MSFT_SEG_REFERENCES, sizeof(MSFT_RefRecord), 0);
+	    if (offset == -1) return E_OUTOFMEMORY;
+
+	    This->typeinfo->datatype1 = offset;
+	} else {
+	    int lastoffset;
+
+	    lastoffset = ctl2_find_nth_reference(This->typelib, This->typeinfo->datatype1, index - 1);
+	    if (lastoffset == -1) return TYPE_E_ELEMENTNOTFOUND;
+
+	    ref = (MSFT_RefRecord *)&This->typelib->typelib_segment_data[MSFT_SEG_REFERENCES][lastoffset];
+	    if (ref->onext != -1) return TYPE_E_ELEMENTNOTFOUND;
+
+	    offset = ctl2_alloc_segment(This->typelib, MSFT_SEG_REFERENCES, sizeof(MSFT_RefRecord), 0);
+	    if (offset == -1) return E_OUTOFMEMORY;
+
+	    ref->onext = offset;
+	}
+
+	ref = (MSFT_RefRecord *)&This->typelib->typelib_segment_data[MSFT_SEG_REFERENCES][offset];
+
+	ref->reftype = hRefType;
+	ref->flags = 0;
+	ref->oCustData = -1;
+	ref->onext = -1;
+    } else if ((This->typeinfo->typekind & 15) == TKIND_DISPATCH) {
+	FIXME("dispatch case unhandled.\n");
+    } else if ((This->typeinfo->typekind & 15) == TKIND_INTERFACE) {
+	if (This->typeinfo->cImplTypes) {
+	    return (index == 1)? TYPE_E_BADMODULEKIND: TYPE_E_ELEMENTNOTFOUND;
+	}
+
+	if (index != 0)  return TYPE_E_ELEMENTNOTFOUND;
+
+	This->typeinfo->cImplTypes++;
+
+	/* hacked values for IDispatch only, and maybe only for stdole. */
+	This->typeinfo->cbSizeVft += 0x0c; /* hack */
+	This->typeinfo->datatype1 = hRefType;
+	This->typeinfo->datatype2 = (3 << 16) | 1; /* ? */
+    } else {
+	FIXME("AddImplType unsupported on typekind %d\n", This->typeinfo->typekind & 15);
+	return E_OUTOFMEMORY;
+    }
+
+    return S_OK;
 }
 
 /******************************************************************************
@@ -1302,8 +1382,23 @@
         UINT index,
         INT implTypeFlags)
 {
-    FIXME("(%p,%d,0x%x), stub!\n", iface, index, implTypeFlags);
-    return E_OUTOFMEMORY;
+    ICOM_THIS(ICreateTypeInfo2Impl, iface);
+    int offset;
+    MSFT_RefRecord *ref;
+
+    TRACE("(%p,%d,0x%x)\n", iface, index, implTypeFlags);
+
+    if ((This->typeinfo->typekind & 15) != TKIND_COCLASS) {
+	return TYPE_E_BADMODULEKIND;
+    }
+
+    offset = ctl2_find_nth_reference(This->typelib, This->typeinfo->datatype1, index);
+    if (offset == -1) return TYPE_E_ELEMENTNOTFOUND;
+
+    ref = (MSFT_RefRecord *)&This->typelib->typelib_segment_data[MSFT_SEG_REFERENCES][offset];
+    ref->flags = implTypeFlags;
+
+    return S_OK;
 }
 
 /******************************************************************************
@@ -3027,6 +3122,7 @@
     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_GUID);
     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_IMPORTINFO);
     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_IMPORTFILES);
+    filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_REFERENCES);
     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_NAMEHASH);
     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_NAME);
     filepos += ctl2_finalize_segment(This, filepos, MSFT_SEG_STRING);
@@ -3045,6 +3141,7 @@
     if (!ctl2_write_segment(This, hFile, MSFT_SEG_GUID        )) return retval;
     if (!ctl2_write_segment(This, hFile, MSFT_SEG_IMPORTINFO  )) return retval;
     if (!ctl2_write_segment(This, hFile, MSFT_SEG_IMPORTFILES )) return retval;
+    if (!ctl2_write_segment(This, hFile, MSFT_SEG_REFERENCES  )) return retval;
     if (!ctl2_write_segment(This, hFile, MSFT_SEG_NAMEHASH    )) return retval;
     if (!ctl2_write_segment(This, hFile, MSFT_SEG_NAME        )) return retval;
     if (!ctl2_write_segment(This, hFile, MSFT_SEG_STRING      )) return retval;


More information about the wine-patches mailing list