Type library creation, take 2, part 2 of 5
Nyef
nyef at softhome.net
Mon Jan 26 11:16:21 CST 2004
Hello all.
Attached is the second of five patches against typelib2.c covering
the just over two weeks of work done since the original patch.
This patch contains:
Improvements to ICreateTypeInfo2_fnAddVarDesc().
A separate function to encode TYPEINFO structures.
--Alastair Bridgewater
-------------- next part --------------
--- typelib2.c.last 2004-01-26 10:57:34.000000000 -0500
+++ typelib2.c 2004-01-26 11:00:34.000000000 -0500
@@ -649,6 +649,208 @@
return offset;
}
+/****************************************************************************
+ * ctl2_encode_typedesc
+ *
+ * Encodes a type description, storing information in the TYPEDESC and ARRAYDESC
+ * segments as needed.
+ *
+ * RETURNS
+ *
+ * Success: 0.
+ * Failure: -1.
+ */
+static int ctl2_encode_typedesc(
+ ICreateTypeLib2Impl *This, /* [I] The type library in which to encode the TYPEDESC. */
+ TYPEDESC *tdesc, /* [I] The type description to encode. */
+ int *encoded_tdesc, /* [O] The encoded type description. */
+ int *width, /* [O] The width of the type, or NULL. */
+ int *alignment, /* [O] The alignment of the type, or NULL. */
+ int *decoded_size) /* [O] The total size of the unencoded TYPEDESCs, including nested descs. */
+{
+ int default_tdesc;
+ int scratch;
+ int typeoffset;
+ int arrayoffset;
+ int *typedata;
+ int *arraydata;
+ int target_type;
+ int child_size;
+
+ default_tdesc = 0x80000000 | (tdesc->vt << 16) | tdesc->vt;
+ if (!width) width = &scratch;
+ if (!alignment) alignment = &scratch;
+ if (!decoded_size) decoded_size = &scratch;
+
+ *decoded_size = 0;
+
+ switch (tdesc->vt) {
+ case VT_UI1:
+ case VT_I1:
+ *encoded_tdesc = default_tdesc;
+ *width = 1;
+ *alignment = 1;
+ break;
+
+ case VT_UINT:
+ *encoded_tdesc = 0x80000000 | (VT_UI4 << 16) | VT_UINT;
+ if ((This->typelib_header.varflags & 0x0f) == SYS_WIN16) {
+ *width = 2;
+ *alignment = 2;
+ } else {
+ *width = 4;
+ *alignment = 4;
+ }
+ break;
+
+ case VT_UI2:
+ *encoded_tdesc = default_tdesc;
+ *width = 2;
+ *alignment = 2;
+ break;
+
+ case VT_I4:
+ case VT_UI4:
+ case VT_ERROR:
+ case VT_BSTR:
+ case VT_HRESULT:
+ *encoded_tdesc = default_tdesc;
+ *width = 4;
+ *alignment = 4;
+ break;
+
+ case VT_VOID:
+ *encoded_tdesc = 0x80000000 | (VT_EMPTY << 16) | tdesc->vt;
+ *width = 0;
+ *alignment = 1;
+ break;
+
+ case VT_PTR:
+ /* FIXME: Make with the error checking. */
+ FIXME("PTR vartype, may not work correctly.\n");
+
+ ctl2_encode_typedesc(This, tdesc->u.lptdesc, &target_type, NULL, NULL, &child_size);
+
+ for (typeoffset = 0; typeoffset < This->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
+ typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+ if (((typedata[0] & 0xffff) == VT_PTR) && (typedata[1] == target_type)) break;
+ }
+
+ if (typeoffset == This->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
+ int mix_field;
+
+ if (target_type & 0x80000000) {
+ mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF;
+ } else {
+ typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
+ mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
+ }
+
+ typeoffset = ctl2_alloc_segment(This, MSFT_SEG_TYPEDESC, 8, 0);
+ typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+
+ typedata[0] = (mix_field << 16) | VT_PTR;
+ typedata[1] = target_type;
+ }
+
+ *encoded_tdesc = typeoffset;
+
+ *width = 4;
+ *alignment = 4;
+ *decoded_size = sizeof(TYPEDESC) + child_size;
+ break;
+
+ case VT_SAFEARRAY:
+ /* FIXME: Make with the error checking. */
+ FIXME("SAFEARRAY vartype, may not work correctly.\n");
+
+ ctl2_encode_typedesc(This, tdesc->u.lptdesc, &target_type, NULL, NULL, &child_size);
+
+ for (typeoffset = 0; typeoffset < This->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
+ typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+ if (((typedata[0] & 0xffff) == VT_SAFEARRAY) && (typedata[1] == target_type)) break;
+ }
+
+ if (typeoffset == This->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
+ int mix_field;
+
+ if (target_type & 0x80000000) {
+ mix_field = ((target_type >> 16) & VT_TYPEMASK) | VT_ARRAY;
+ } else {
+ typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
+ mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
+ }
+
+ typeoffset = ctl2_alloc_segment(This, MSFT_SEG_TYPEDESC, 8, 0);
+ typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+
+ typedata[0] = (mix_field << 16) | VT_SAFEARRAY;
+ typedata[1] = target_type;
+ }
+
+ *encoded_tdesc = typeoffset;
+
+ *width = 4;
+ *alignment = 4;
+ *decoded_size = sizeof(TYPEDESC) + child_size;
+ break;
+
+ case VT_CARRAY:
+ /* FIXME: Make with the error checking. */
+ FIXME("Array vartype, hacking badly.\n");
+
+ ctl2_encode_typedesc(This, &tdesc->u.lpadesc->tdescElem, &target_type, width, alignment, NULL);
+ arrayoffset = ctl2_alloc_segment(This, MSFT_SEG_ARRAYDESC, 16, 0);
+ arraydata = (void *)&This->typelib_segment_data[MSFT_SEG_ARRAYDESC][arrayoffset];
+
+ arraydata[0] = target_type;
+ arraydata[1] = 0x00080001;
+ arraydata[2] = 0x8;
+ arraydata[3] = 0;
+
+ typeoffset = ctl2_alloc_segment(This, MSFT_SEG_TYPEDESC, 8, 0);
+ typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+
+ typedata[0] = (0x7ffe << 16) | VT_CARRAY;
+ typedata[1] = arrayoffset;
+
+ *encoded_tdesc = typeoffset;
+ *width = 8;
+ *alignment = 1;
+ *decoded_size = sizeof(ARRAYDESC);
+
+ break;
+
+ case VT_USERDEFINED:
+ TRACE("USERDEFINED.\n");
+ for (typeoffset = 0; typeoffset < This->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
+ typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+ if ((typedata[0] == ((0x7fff << 16) | VT_USERDEFINED)) && (typedata[1] == tdesc->u.hreftype)) break;
+ }
+
+ if (typeoffset == This->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
+ typeoffset = ctl2_alloc_segment(This, MSFT_SEG_TYPEDESC, 8, 0);
+ typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+
+ typedata[0] = (0x7fff << 16) | VT_USERDEFINED;
+ typedata[1] = tdesc->u.hreftype;
+ }
+
+ *encoded_tdesc = typeoffset;
+ *width = 0;
+ *alignment = 1;
+ break;
+
+ default:
+ FIXME("Unrecognized type %d.\n", tdesc->vt);
+ *encoded_tdesc = default_tdesc;
+ *width = 0;
+ *alignment = 1;
+ break;
+ }
+
+ return 0;
+}
/*================== ICreateTypeInfo2 Implementation ===================================*/
@@ -955,6 +1157,8 @@
int offset;
INT *typedata;
int var_datawidth;
+ int var_alignment;
+ int var_type_size;
int alignment;
TRACE("(%p,%d,%p), stub!\n", iface, index, pVarDesc);
@@ -980,10 +1184,8 @@
/* fill out the basic type information */
typedata[0] = 0x14 | (index << 16);
- typedata[1] = 0x80000000 | (pVarDesc->elemdescVar.tdesc.vt << 16) | pVarDesc->elemdescVar.tdesc.vt;
typedata[2] = pVarDesc->wVarFlags;
- typedata[3] = 0x00240000;
- typedata[4] = This->datawidth;
+ typedata[3] = (sizeof(VARDESC) << 16) | 0;
/* update the index data */
This->indices[index] = 0x40000000 + index;
@@ -991,59 +1193,25 @@
This->offsets[index] = offset;
/* figure out type widths and whatnot */
- if (pVarDesc->elemdescVar.tdesc.vt == VT_UI4) {
- var_datawidth = 4;
- } else if (pVarDesc->elemdescVar.tdesc.vt == VT_BSTR) {
- var_datawidth = 4;
- } else if (pVarDesc->elemdescVar.tdesc.vt == VT_UI2) {
- var_datawidth = 2;
- } else if (pVarDesc->elemdescVar.tdesc.vt == VT_UI1) {
- var_datawidth = 1;
- } else if (pVarDesc->elemdescVar.tdesc.vt == VT_CARRAY) {
- int *typedesc;
- int *arraydesc;
- int typeoffset;
- int arrayoffset;
-
- FIXME("Array vartype, hacking badly.\n");
- typeoffset = ctl2_alloc_segment(This->typelib, MSFT_SEG_TYPEDESC, 8, 0);
- arrayoffset = ctl2_alloc_segment(This->typelib, MSFT_SEG_ARRAYDESC, 16, 0);
-
- typedesc = (void *)&This->typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
- arraydesc = (void *)&This->typelib->typelib_segment_data[MSFT_SEG_ARRAYDESC][arrayoffset];
-
- typedesc[0] = 0x7ffe001c;
- typedesc[1] = arrayoffset;
-
- arraydesc[0] = 0x80000000 | (pVarDesc->elemdescVar.tdesc.u.lpadesc->tdescElem.vt << 16) | pVarDesc->elemdescVar.tdesc.u.lpadesc->tdescElem.vt;
- arraydesc[1] = 0x00080001;
- arraydesc[2] = 0x8;
- arraydesc[3] = 0;
-
- typedata[1] = typeoffset;
- typedata[3] = 0x00380000;
-
- This->datawidth += 8;
- var_datawidth = 0; /* FIXME: Probably wrong. */
- } else {
- FIXME("Unrecognized vartype %d.\n", pVarDesc->elemdescVar.tdesc.vt);
- var_datawidth = 0;
- }
+ ctl2_encode_typedesc(This->typelib, &pVarDesc->elemdescVar.tdesc,
+ &typedata[1], &var_datawidth, &var_alignment,
+ &var_type_size);
+
+ /* pad out starting position to data width */
+ This->datawidth += var_alignment - 1;
+ This->datawidth &= ~(var_alignment - 1);
+ typedata[4] = This->datawidth;
+
+ /* add the new variable to the total data width */
+ This->datawidth += var_datawidth;
- if (pVarDesc->elemdescVar.tdesc.vt != VT_CARRAY) {
- /* pad out starting position to data width */
- This->datawidth += var_datawidth - 1;
- This->datawidth &= ~(var_datawidth - 1);
- typedata[4] = This->datawidth;
-
- /* add the new variable to the total data width */
- This->datawidth += var_datawidth;
- }
+ /* add type description size to total required allocation */
+ typedata[3] += var_type_size << 16;
/* fix type alignment */
alignment = (This->typeinfo->typekind >> 11) & 0x1f;
- if (alignment < var_datawidth) {
- alignment = var_datawidth;
+ if (alignment < var_alignment) {
+ alignment = var_alignment;
This->typeinfo->typekind &= ~0xf800;
This->typeinfo->typekind |= alignment << 11;
}
@@ -1107,8 +1275,11 @@
if (offset == -1) return E_OUTOFMEMORY;
namedata = This->typelib->typelib_segment_data[MSFT_SEG_NAME] + offset;
- *((INT *)namedata) = 0;
+ *((INT *)namedata) = This->typelib->typelib_typeinfo_offsets[This->typeinfo->typekind >> 16];
namedata[9] = 0x10;
+ if ((This->typeinfo->typekind & 15) == TKIND_ENUM) {
+ namedata[9] |= 0x20;
+ }
This->names[index] = offset;
return S_OK;
More information about the wine-patches
mailing list