oleaut32: Better handle secondary type when generating type descriptors.

This commit is contained in:
Andrey Turkin 2010-07-17 11:40:23 +04:00 committed by Alexandre Julliard
parent fe7e384e07
commit 9fd7f392dc
1 changed files with 43 additions and 41 deletions

View File

@ -1080,65 +1080,49 @@ static int ctl2_encode_typedesc(
break; break;
case VT_PTR: 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: case VT_SAFEARRAY:
/* FIXME: Make with the error checking. */ /* FIXME: Make with the error checking. */
FIXME("SAFEARRAY vartype, may not work correctly.\n"); FIXME("PTR or SAFEARRAY vartype, may not work correctly.\n");
ctl2_encode_typedesc(This, tdesc->u.lptdesc, &target_type, NULL, NULL, &child_size); 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) { for (typeoffset = 0; typeoffset < This->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
if (((typedata[0] & 0xffff) == VT_SAFEARRAY) && (typedata[1] == target_type)) break; if (((typedata[0] & 0xffff) == tdesc->vt) && (typedata[1] == target_type)) break;
} }
if (typeoffset == This->typelib_segdir[MSFT_SEG_TYPEDESC].length) { if (typeoffset == This->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
int mix_field; int mix_field;
if (target_type & 0x80000000) { if (target_type & 0x80000000) {
mix_field = ((target_type >> 16) & VT_TYPEMASK) | VT_ARRAY; mix_field = (target_type >> 16) & VT_TYPEMASK;
} else { } else {
typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type]; typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe; switch((typedata[0]>>16) & ~VT_ARRAY)
{
case VT_UI1:
case VT_I1:
case VT_UI2:
case VT_I2:
case VT_I4:
case VT_UI4:
mix_field = typedata[0]>>16;
break;
default:
mix_field = 0x7fff;
break;
} }
}
if (tdesc->vt == VT_PTR)
mix_field |= VT_BYREF;
else if (tdesc->vt == VT_SAFEARRAY)
mix_field |= VT_ARRAY;
typeoffset = ctl2_alloc_segment(This, MSFT_SEG_TYPEDESC, 8, 0); typeoffset = ctl2_alloc_segment(This, MSFT_SEG_TYPEDESC, 8, 0);
typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
typedata[0] = (mix_field << 16) | VT_SAFEARRAY; typedata[0] = (mix_field << 16) | tdesc->vt;
typedata[1] = target_type; typedata[1] = target_type;
} }
@ -1182,17 +1166,34 @@ static int ctl2_encode_typedesc(
break; break;
} }
case VT_USERDEFINED: case VT_USERDEFINED:
{
const MSFT_TypeInfoBase *basetype;
INT basevt = 0x7fff;
TRACE("USERDEFINED.\n"); TRACE("USERDEFINED.\n");
if (tdesc->u.hreftype % sizeof(*basetype) == 0 && tdesc->u.hreftype < This->typelib_segdir[MSFT_SEG_TYPEINFO].length)
{
basetype = (MSFT_TypeInfoBase*)&(This->typelib_segment_data[MSFT_SEG_TYPEINFO][tdesc->u.hreftype]);
switch(basetype->typekind & 0xf)
{
case TKIND_ENUM:
basevt = VT_I4;
break;
default:
FIXME("USERDEFINED basetype %d not handled\n", basetype->typekind & 0xf);
break;
}
}
for (typeoffset = 0; typeoffset < This->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) { for (typeoffset = 0; typeoffset < This->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
if ((typedata[0] == ((0x7fff << 16) | VT_USERDEFINED)) && (typedata[1] == tdesc->u.hreftype)) break; if ((typedata[0] == ((basevt << 16) | VT_USERDEFINED)) && (typedata[1] == tdesc->u.hreftype)) break;
} }
if (typeoffset == This->typelib_segdir[MSFT_SEG_TYPEDESC].length) { if (typeoffset == This->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
typeoffset = ctl2_alloc_segment(This, MSFT_SEG_TYPEDESC, 8, 0); typeoffset = ctl2_alloc_segment(This, MSFT_SEG_TYPEDESC, 8, 0);
typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
typedata[0] = (0x7fff << 16) | VT_USERDEFINED; typedata[0] = (basevt << 16) | VT_USERDEFINED;
typedata[1] = tdesc->u.hreftype; typedata[1] = tdesc->u.hreftype;
} }
@ -1200,6 +1201,7 @@ static int ctl2_encode_typedesc(
*width = 0; *width = 0;
*alignment = 1; *alignment = 1;
break; break;
}
default: default:
FIXME("Unrecognized type %d.\n", tdesc->vt); FIXME("Unrecognized type %d.\n", tdesc->vt);