/// <summary> /// If the type is aliased, return the ultimated non-aliased type if the type is user-defined, otherwise, return /// the aliased type directly. So the result could still be aliased to a built-in type. /// If the type is not aliased, just return the type directly /// </summary> public static void ResolveAlias(TypeInfo type, TypeDesc typeDesc, out TypeInfo realType, out TypeAttr realAttr) { if (type == null) throw new ArgumentNullException(nameof(type)); if (typeDesc == null) throw new ArgumentNullException(nameof(typeDesc)); if ((VarEnum)typeDesc.vt != VarEnum.VT_USERDEFINED) { // Already resolved realType = type; realAttr = type.GetTypeAttr(); return; } else { TypeInfo refType = type.GetRefTypeInfo(typeDesc.hreftype); TypeAttr refAttr = refType.GetTypeAttr(); // If the userdefined typeinfo is not itself an alias, then it is what the alias aliases. // Also, if the userdefined typeinfo is an alias to a builtin type, then the builtin // type is what the alias aliases. if (refAttr.typekind != TypeLibTypes.Interop.TYPEKIND.TKIND_ALIAS || (VarEnum)refAttr.tdescAlias.vt != VarEnum.VT_USERDEFINED) { // Resolved realType = refType; realAttr = refAttr; } else { // Continue resolving the type ResolveAlias(refType, refAttr.tdescAlias, out realType, out realAttr); } } }
/// <summary> /// This function is used to workaround around the fact that the TypeInfo might return IUnknown/IDispatch methods (in the case of dual interfaces) /// So we should always call this function to get the first index for different TypeInfo and never save the id /// </summary> public static int GetIndexOfFirstMethod(TypeInfo type, TypeAttr attr) { if (type == null) throw new ArgumentNullException(nameof(type)); if (attr == null) throw new ArgumentNullException(nameof(attr)); if (attr.typekind != TypeLibTypes.Interop.TYPEKIND.TKIND_DISPATCH) return 0; int nIndex = 0; if (attr.cFuncs >= 3) { // Check for IUnknown first using (FuncDesc func = type.GetFuncDesc(0)) { if (func.memid == 0x60000000 && func.elemdescFunc.tdesc.vt == (int)VarEnum.VT_VOID && func.cParams == 2 && func.GetElemDesc(0).tdesc.vt == (int)VarEnum.VT_PTR && func.GetElemDesc(1).tdesc.vt == (int)VarEnum.VT_PTR && "QueryInterface" == type.GetDocumentation(func.memid)) { nIndex = 3; } } if (attr.cFuncs >= 7) { using (FuncDesc func = type.GetFuncDesc(3)) { // Check IDispatch if (func.memid == 0x60010000 && func.elemdescFunc.tdesc.vt == (int)VarEnum.VT_VOID && func.cParams == 1 && func.GetElemDesc(0).tdesc.vt == (int)VarEnum.VT_PTR && "GetTypeInfoCount" == type.GetDocumentation(func.memid)) { nIndex = 7; } } } } return nIndex; }
private void CreateField(TypeInfo type, TypeAttr attr, VarDesc var, ref bool isConversionLoss) { TypeDesc fieldTypeDesc = var.elemdescVar.tdesc; TypeConverter typeConverter = new TypeConverter(m_info, type, fieldTypeDesc, ConversionType.Field); Type fieldType = typeConverter.ConvertedType; string fieldName = type.GetDocumentation(var.memid); FieldBuilder field = m_typeBuilder.DefineField(fieldName, fieldType, FieldAttributes.Public); typeConverter.ApplyAttributes(field); isConversionLoss |= typeConverter.IsConversionLoss; // // Emit ComConversionLossAttribute for fields if necessary // if (typeConverter.IsConversionLoss) { field.SetCustomAttribute(CustomAttributeHelper.GetBuilderForComConversionLoss()); // // Emit Wrn_UnconvertableField warning // m_info.ReportEvent( WarningCode.Wrn_UnconvertableField, Resource.FormatString("Wrn_UnconvertableField", m_typeBuilder.FullName, fieldName)); } // // Emit TypeLibVarAttribute if necessary // if (var.wVarFlags != 0) { field.SetCustomAttribute(CustomAttributeHelper.GetBuilderForTypeLibVar((TypeLibVarFlags)var.wVarFlags)); } }
private void CreateField(TypeInfo type, TypeAttr attr, VarDesc var, ref bool isConversionLoss) { if (IsObjectType(type, var.elemdescVar.tdesc)) { isConversionLoss = true; } else { TypeConverter typeConverter = new TypeConverter(m_info, type, var.elemdescVar.tdesc, ConversionType.Field); Type fieldType = typeConverter.ConvertedType; // TlbImp2 will only skip reference types, instead of skipping every field // Also, TlbImp1 will skip ValueType *, which doesn't make any sense. TlbImp2 will keep ValueType * as IntPtr string fieldName = type.GetDocumentation(var.memid); // Generates the [FieldOffset(0)] layout declarations that approximate unions in managed code FieldBuilder field = m_typeBuilder.DefineField(fieldName, fieldType, FieldAttributes.Public); field.SetCustomAttribute(CustomAttributeHelper.GetBuilderForFieldOffset(0)); typeConverter.ApplyAttributes(field); isConversionLoss |= typeConverter.IsConversionLoss; // // Emit ComConversionLossAttribute for fields if necessary // if (typeConverter.IsConversionLoss) { field.SetCustomAttribute(CustomAttributeHelper.GetBuilderForComConversionLoss()); // // Emit Wrn_UnconvertableField warning // m_info.ReportEvent( WarningCode.Wrn_UnconvertableField, Resource.FormatString("Wrn_UnconvertableField", m_typeBuilder.FullName, fieldName)); } } }
public InterfaceInfo(ConverterInfo info, TypeBuilder typeBuilder, bool supportsDispatch, TypeInfo type, TypeAttr attr, bool bCoClass) { Init(info, typeBuilder, supportsDispatch, type, attr, bCoClass, false, null); }
public InterfaceInfo(ConverterInfo info, TypeBuilder typeBuilder, bool supportsDispatch, TypeInfo type, TypeAttr attr, bool bCoClass, bool bSource, TypeInfo implementingInterface) { Init(info, typeBuilder, supportsDispatch, type, attr, bCoClass, bSource, implementingInterface); }
private void Init(ConverterInfo info, TypeBuilder typeBuilder, bool emitDispId, TypeInfo type, TypeAttr attr, bool bCoClass, bool bSource, TypeInfo implementingInterface) { m_typeStack = new Stack<TypeInfo>(); m_attrStack = new Stack<TypeAttr>(); PushType(type, attr); m_info = info; m_typeBuilder = typeBuilder; m_emitDispId = emitDispId; m_bCoClass = bCoClass; m_propertyInfo = new PropertyInfo(this); m_bSource = bSource; IsConversionLoss = false; IsDefaultInterface = false; m_currentSlot = 0; m_currentImplementingInterface = implementingInterface; }
public void PushType(TypeInfo type, TypeAttr attr) { m_typeStack.Push(type); m_attrStack.Push(attr); }
/// <summary> /// Is this interface explicitly derives from IEnumerable (from mscorlib.tlb)? /// </summary> /// <param name="lookupPartner">Whether we look at the partner interface</param> public static bool ExplicitlyImplementsIEnumerable(TypeInfo typeInfo, TypeAttr typeAttr, bool lookupPartner) { // Look through each of the implemented/inherited interfaces for (int i = 0; i < typeAttr.cImplTypes; ++i) { TypeInfo interfaceTypeInfo = typeInfo.GetRefType(i); using (TypeAttr interfaceTypeAttr = interfaceTypeInfo.GetTypeAttr()) { if ((typeInfo.GetImplTypeFlags(i) & TypeLibTypes.Interop.IMPLTYPEFLAGS.IMPLTYPEFLAG_FSOURCE) == 0) { if (interfaceTypeAttr.Guid == WellKnownGuids.IID_IEnumerable) return true; if (ExplicitlyImplementsIEnumerable(interfaceTypeInfo, interfaceTypeAttr)) return true; } } } if (lookupPartner) { TypeInfo partnerTypeInfo = typeInfo.GetRefTypeNoComThrow(); if (partnerTypeInfo != null) { using (TypeAttr partnerTypeAttr = partnerTypeInfo.GetTypeAttr()) { if (partnerTypeAttr.Guid == WellKnownGuids.IID_IEnumerable) return true; if (ExplicitlyImplementsIEnumerable(partnerTypeInfo, partnerTypeAttr, false)) return true; } } } return false; }
/// <summary> /// Is this interface explicitly derives from IEnumerable (from mscorlib.tlb)? /// </summary> public static bool ExplicitlyImplementsIEnumerable(TypeInfo typeInfo, TypeAttr typeAttr) { return ExplicitlyImplementsIEnumerable(typeInfo, typeAttr, true); }
public static bool InterfaceSupportsDispatch(TypeInfo typeInfo, TypeAttr attr) { return attr.IsDual || attr.typekind == TypeLibTypes.Interop.TYPEKIND.TKIND_DISPATCH; }