/// <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); } } }
public TypeInfoMatchTarget(TypeLib typeLib, TypeInfo typeInfo, TYPEKIND typeKind) { if (typeInfo == null) throw new ArgumentNullException(nameof(typeInfo)); m_typeLib = typeLib; m_typeInfo = typeInfo; m_typeKind = typeKind; m_typeString = TypeLibUtility.TypeKind2String(m_typeKind); m_guid = typeInfo.GetTypeAttr().Guid; }
private static void ProcessFields(TypeInfo parentTypeInfo, TreeNode parentTreeNode) { // // Walk through all vars (including elements from structs and disp interface, ...) // using (TypeAttr attr = parentTypeInfo.GetTypeAttr()) { for (int i = 0; i < attr.cVars; ++i) { FieldInfoMatchTarget variableInfo = new FieldInfoMatchTarget(parentTypeInfo, i); TreeNode dispVarTreeNode = new TreeNode(); dispVarTreeNode.Text = variableInfo.Name + ": " + variableInfo.Type; dispVarTreeNode.Tag = variableInfo; SetTlbTreeNodeImage(dispVarTreeNode); parentTreeNode.Nodes.Add(dispVarTreeNode); } } }
private static void ProcessFunctions(TypeInfo parentTypeInfo, TreeNode parentTreeNode) { using (TypeAttr attr = parentTypeInfo.GetTypeAttr()) { // // Walk through all the function/propput/propget/propref properties // for (int i = ConvCommon2.GetIndexOfFirstMethod(parentTypeInfo, attr); i < attr.cFuncs; ++i) { FunctionInfoMatchTarget functionInfo = new FunctionInfoMatchTarget(parentTypeInfo, (short) i); TreeNode funcTreeNode = new TreeNode(); if (functionInfo.FuncDesc.IsPropertyGet) { funcTreeNode.Text = functionInfo.Name + " (getter)" + ": " + functionInfo.Type; } else if (functionInfo.FuncDesc.IsPropertyPut || functionInfo.FuncDesc.IsPropertyPutRef) { funcTreeNode.Text = functionInfo.Name + " (setter)" + ": " + functionInfo.Type; } else { funcTreeNode.Text = functionInfo.Name + ": " + functionInfo.Type; } funcTreeNode.Tag = functionInfo; SetTlbTreeNodeImage(funcTreeNode); parentTreeNode.Nodes.Add(funcTreeNode); ProcessFuncParams(parentTypeInfo, functionInfo.Index, funcTreeNode); } } }
public static bool HasNewEnumMember(ConverterInfo info, TypeInfo typeInfo, string fullName) { bool hasNewEnumMember = false; bool hasDuplicateNewEnumMember = false; int firstNewEnum = -1; using (TypeAttr attr = typeInfo.GetTypeAttr()) { if (attr.IsDispatch || (attr.IsInterface && ConvCommon.IsDerivedFromIDispatch(typeInfo))) { // Check to see if the interface has a function with a DISPID of DISPID_NEWENUM. for (int i = 0; i < attr.cFuncs; ++i) { using(FuncDesc func = typeInfo.GetFuncDesc(i)) { if (IsNewEnumFunc(info, typeInfo, func, i)) { if (!hasNewEnumMember) firstNewEnum = func.memid; if (hasNewEnumMember) hasDuplicateNewEnumMember = true; // The interface has a function with a DISPID of DISPID_NEWENUM. hasNewEnumMember = true; } } } // Check to see if the interface as a property with a DISPID of DISPID_NEWENUM. for (int i = 0; i < attr.cVars; ++i) { using (VarDesc varDesc = typeInfo.GetVarDesc(i)) { if (IsNewEnumDispatchProperty(info, typeInfo, varDesc, i)) { if (!hasNewEnumMember) firstNewEnum = varDesc.memid; if (hasNewEnumMember) hasDuplicateNewEnumMember = true; // The interface has a property with a DISPID of DISPID_NEWENUM. hasNewEnumMember = true; } } } // Check to see if the ForceIEnumerable custom value exists on the type if (HasForceIEnumerableCustomAttribute(typeInfo)) hasNewEnumMember = true; if (hasDuplicateNewEnumMember) { info.ReportEvent( WarningCode.Wrn_MultiNewEnum, Resource.FormatString("Wrn_MultiNewEnum", fullName, typeInfo.GetDocumentation(firstNewEnum))); } } else { // Check to see if the ForceIEnumerable custom value exists on the type // If it does, spit out a warning. if (HasForceIEnumerableCustomAttribute(typeInfo)) { string msg = Resource.FormatString( "Wrn_IEnumCustomAttributeOnIUnknown", CustomAttributeGuids.GUID_ForceIEnumerable.ToString().ToUpper(), typeInfo.GetDocumentation()); info.ReportEvent(WarningCode.Wrn_IEnumCustomAttributeOnIUnknown, msg); } } } return hasNewEnumMember; }
private bool RuleEngineResolveRedirection(RuleSet ruleSet, TypeInfo typeInfo, out Type convertedType) { convertedType = null; if (ruleSet != null) { ICategory category = TypeCategory.GetInstance(); TypeLibTypes.Interop.TYPEKIND typeKind; using (TypeAttr attr = typeInfo.GetTypeAttr()) { typeKind = attr.typekind; } TypeInfoMatchTarget target = new TypeInfoMatchTarget(typeInfo.GetContainingTypeLib(), typeInfo, typeKind); AbstractActionManager actionManager = RuleEngine.GetActionManager(); List<Rule> resolveToRules = ruleSet.GetRule( category, ResolveToActionDef.GetInstance(), target); if (resolveToRules.Count != 0) { if (resolveToRules.Count > 1) { Output.WriteWarning(Resource.FormatString("Wrn_RuleMultipleMatch", ResolveToActionDef.GetInstance().GetActionName()), WarningCode.Wrn_RuleMultipleMatch); } Rule resolveToRule = resolveToRules[resolveToRules.Count - 1]; ResolveToAction action = resolveToRule.Action as ResolveToAction; try { Assembly assembly = Assembly.ReflectionOnlyLoad(action.AssemblyName); convertedType = assembly.GetType(action.ManagedTypeFullName); return true; } catch (Exception) { Output.WriteWarning(Resource.FormatString("Wrn_CannotLoadResolveToType", action.ManagedTypeFullName, action.AssemblyName), WarningCode.Wrn_CannotLoadResolveToType); } } } return false; }
public static TypeInfo GetDefaultInterface(TypeInfo coclass) { TypeInfo typeInfo = coclass; TypeAttr typeAttr = coclass.GetTypeAttr(); TypeInfo defaultInterface = null; for (int i = 0; i < typeAttr.cImplTypes; ++i) { TypeLibTypes.Interop.IMPLTYPEFLAGS flags = typeInfo.GetImplTypeFlags(i); // Non-source default interface? if ((flags & (TypeLibTypes.Interop.IMPLTYPEFLAGS.IMPLTYPEFLAG_FSOURCE | TypeLibTypes.Interop.IMPLTYPEFLAGS.IMPLTYPEFLAG_FDEFAULT)) == TypeLibTypes.Interop.IMPLTYPEFLAGS.IMPLTYPEFLAG_FDEFAULT) { return typeInfo.GetRefType(i); } else if ((flags & TypeLibTypes.Interop.IMPLTYPEFLAGS.IMPLTYPEFLAG_FSOURCE) == 0 && defaultInterface == null) { defaultInterface = typeInfo.GetRefType(i); } } return defaultInterface; }
/// <summary> /// Whether the ITypeInfo is derived from IDispatch. /// </summary> /// <return>True if ITypeInfo is derive from IID, false otherwise (including when ITypeInfo is IID)</return> public static bool IsDerivedFromIID(TypeInfo typeInfo, Guid iid) { using (TypeAttr attr = typeInfo.GetTypeAttr()) { // Return false if the ITypeInfo is IID if (attr.Guid == iid) return false; return IsDerivedFromIIDInternal(typeInfo, iid); } }
/// <summary> /// Common code shared by struct, enum, and union type creation /// </summary> public static TypeBuilder DefineTypeHelper(ConverterInfo info, TypeInfo typeInfo, TypeInfo nonAliasedTypeInfo, TypeAttributes attributes, Type typeParent, ConvType convType) { using (TypeAttr typeAttr = nonAliasedTypeInfo.GetTypeAttr()) { string name = info.GetUniqueManagedName(typeInfo, convType); TypeBuilder typeBuilder = info.ModuleBuilder.DefineType(name, attributes, typeParent); DefineGuid(typeInfo, nonAliasedTypeInfo, typeBuilder); // We only emit TypeLibType attribute for class/interface, according to MSDN // typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForTypeLibType((TypeLibTypeFlags)attr.wTypeFlags)); return typeBuilder; } }
/// <summary> /// Gets the non-aliased type if it is a alias /// </summary> public static TypeInfo GetAlias(TypeInfo typeInfo) { // // Support for alias // If it is an alias, then it must be an alias to a user defined type, which we'll duplicate // all the definitions under the alias' name // using (TypeAttr typeAttr = typeInfo.GetTypeAttr()) { if (typeAttr.IsAlias) { TypeInfo resolvedTypeInfo; TypeAttr resolvedTypeAttr; ConvCommon.ResolveAlias(typeInfo, typeAttr.tdescAlias, out resolvedTypeInfo, out resolvedTypeAttr); // If we resolved to an alias, this means this is an alias of built-in type and should never be // passed in Debug.Assert(!resolvedTypeAttr.IsAlias); return resolvedTypeInfo; } else return typeInfo; } }
/// <summary> /// Define guid for a certain type. Prefer the GUID on aliased type, otherwise the aliased type /// </summary> /// <param name="typeInfo"></param> /// <param name="nonAliasedTypeInfo"></param> /// <param name="typeBuilder"></param> public static void DefineGuid(TypeInfo typeInfo, TypeInfo nonAliasedTypeInfo, TypeBuilder typeBuilder) { // Prefer the GUID on the alias, otherwise the aliased type Guid guid = typeInfo.GetTypeAttr().Guid; if (guid == Guid.Empty) guid = nonAliasedTypeInfo.GetTypeAttr().Guid; if (guid != Guid.Empty) { // Handle the [Guid(...)] attribute typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForGuid(guid)); } }
private static bool IsDerivedFromIIDInternal(TypeInfo typeInfo, Guid iid) { using (TypeAttr attr = typeInfo.GetTypeAttr()) { if (attr.Guid == iid) return true; // If we've seen a IUnknown (note that if the iid is IUnknown, we've tested that already)), // we've recused far enough if (attr.Guid == WellKnownGuids.IID_IUnknown) return false; if (attr.cImplTypes == 1) { TypeInfo parent = typeInfo.GetRefType(0); return IsDerivedFromIIDInternal(parent, iid); } } return false; }
/// <summary> /// Create the constant fields on the TypeBuilder according to the VarDesc in the type /// </summary> public static void CreateConstantFields(ConverterInfo info, TypeInfo type, TypeBuilder typeBuilder, ConvType convType) { using (TypeAttr attr = type.GetTypeAttr()) { int cVars = attr.cVars; for (int n = 0; n < cVars; ++n) { using (VarDesc var = type.GetVarDesc(n)) { string fieldName = type.GetDocumentation(var.memid); // We don't want the same conversion rules as Field for VT_BOOL and VT_ARRAY, so use Element instead // Basically Element is the same as Field except that it doesn't have special rules for VT_BOOL/VT_ARRAY TypeConverter typeConverter = new TypeConverter(info, type, var.elemdescVar.tdesc, ConversionType.Element); if (typeConverter.ConvertedType == typeof(DateTime)) typeConverter = new TypeConverter(typeof(float)); Type fieldType = typeConverter.ConvertedType; if (typeConverter.IsConversionLoss) { // // Emit Wrn_UnconvertableField warning // info.ReportEvent( WarningCode.Wrn_UnconvertableField, Resource.FormatString("Wrn_UnconvertableField", typeBuilder.FullName, fieldName)); } Type targetType; if (convType == ConvType.Enum) targetType = typeBuilder; // use enum type as the field type for enum else targetType = fieldType; // use the real type as the field type FieldBuilder fieldBuilder = typeBuilder.DefineField(fieldName, targetType, FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal); typeConverter.ApplyAttributes(fieldBuilder); // // Emit TypeLibVarAttribute if necessary // if (var.wVarFlags != 0) { fieldBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForTypeLibVar((TypeLibVarFlags)var.wVarFlags)); } // Emit constant for static fields ConvCommon.SetDefaultValue(var, fieldType, fieldBuilder); } } } }
/// <summary> /// Test whether the specified VT_RECORD contains any field that can be converted to a managed reference type /// </summary> private bool HasObjectFields(TypeInfo typeInfo) { TypeAttr typeAttr = typeInfo.GetTypeAttr(); for (int i = 0; i < typeAttr.cVars; ++i) { VarDesc var = typeInfo.GetVarDesc(i); if (IsObjectType(typeInfo, var.elemdescVar.tdesc)) return true; } return false; }
public static int GetPointerSize(TypeInfo typeInfo) { using (TypeAttr attr = typeInfo.GetTypeAttr()) { if (attr.Guid == WellKnownGuids.IID_IUnknown || attr.Guid == WellKnownGuids.IID_IDispatch) { return attr.cbSizeInstance; } if (attr.cImplTypes == 1) { TypeInfo parent = typeInfo.GetRefType(0); return GetPointerSize(parent); } return attr.cbSizeInstance; } }
/// <summary> /// Implement methods in parent interfaces /// </summary> private void HandleParentInterface(TypeInfo type, bool bSource, ref bool isConversionLoss, bool isDefault) { using (TypeAttr attr = type.GetTypeAttr()) { InterfaceInfo interfaceInfo = new InterfaceInfo(m_info, m_typeBuilder, ConvCommon.InterfaceSupportsDispatch(type, attr), type, attr, true, bSource, type); interfaceInfo.IsDefaultInterface = isDefault; if (bSource) // When adding override methods to the interface, we need to use the event interface for source interfaces ConvCommon.CreateEventInterfaceCommon(interfaceInfo); else ConvCommon.CreateInterfaceCommon(interfaceInfo); isConversionLoss |= interfaceInfo.IsConversionLoss; } }
protected void DefineType(ConverterInfo info, TypeInfo typeInfo, bool dealWithAlias) { m_info = info; m_typeInfo = typeInfo; if (dealWithAlias) m_nonAliasedTypeInfo = ConvCommon.GetAlias(typeInfo); else m_nonAliasedTypeInfo = typeInfo; try { OnDefineType(); // // Emit SuppressUnmanagedCodeSecurityAttribute for /unsafe switch // if ((m_info.Settings.m_flags & TypeLibImporterFlags.UnsafeInterfaces) != 0) { if (ConvType != ConvType.ClassInterface && ConvType != ConvType.EventInterface) m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForSuppressUnmanagedCodeSecurity()); } // Rule Engine AddAttributeAction if (m_info.Settings.m_ruleSet != null) { ICategory category = TypeCategory.GetInstance(); TypeInfoMatchTarget target = null; using (TypeAttr attr = m_typeInfo.GetTypeAttr()) { TypeLibTypes.Interop.TYPEKIND kind = attr.typekind; target = new TypeInfoMatchTarget(m_typeInfo.GetContainingTypeLib(), m_typeInfo, kind); } AbstractActionManager actionManager = RuleEngine.GetActionManager(); List<Rule> addAttributeRules = m_info.Settings.m_ruleSet.GetRule( category, AddAttributeActionDef.GetInstance(), target); foreach (Rule rule in addAttributeRules) { var addAttributeAction = rule.Action as AddAttributeAction; ConstructorInfo attributeCtor; byte[] blob; bool success = true; if (addAttributeAction.GetCustomAttribute(out attributeCtor, out blob)) { try { m_typeBuilder.SetCustomAttribute(attributeCtor, blob); } catch (Exception) { success = false; } } else { success = false; } if (!success) { string name = m_typeInfo.GetDocumentation(); string msg = Resource.FormatString("Wrn_AddCustomAttributeFailed", addAttributeAction.TypeName, name); m_info.ReportEvent(WarningCode.Wrn_AddCustomAttributeFailed, msg); } } } } catch (ReflectionTypeLoadException) { throw; // Fatal failure. Throw } catch (TlbImpResolveRefFailWrapperException) { throw; // Fatal failure. Throw } catch (TlbImpGeneralException) { throw; // Fatal failure. Throw } catch (Exception) { string name = String.Empty; if (m_typeInfo != null) { try { name = m_typeInfo.GetDocumentation(); } catch (Exception) { } } if (name != String.Empty) { string msg = Resource.FormatString("Wrn_InvalidTypeInfo", name); m_info.ReportEvent(WarningCode.Wrn_InvalidTypeInfo, msg); } else { string msg = Resource.FormatString("Wrn_InvalidTypeInfo_Unnamed"); m_info.ReportEvent(WarningCode.Wrn_InvalidTypeInfo_Unnamed, msg); } // When failure, try to create the type anyway if (m_typeBuilder != null) { m_type = m_typeBuilder.CreateType(); } } }