/// <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 TypeInfo GetUserDefinedTypeInfo(TypeInfo typeinfo) { return(typeinfo.GetRefTypeInfo(hreftype)); }
/// <summary> /// Test whether the typeDesc corresponds to a managed reference type /// </summary> private bool IsObjectType(TypeInfo typeInfo, TypeDesc typeDesc) { int nativeIndirection = 0; int vt = typeDesc.vt; // Strip off leading VT_PTR and VT_BYREF while (vt == (int)VarEnum.VT_PTR) { typeDesc = typeDesc.lptdesc; vt = typeDesc.vt; nativeIndirection++; } if ((vt & (int)VarEnum.VT_BYREF) != 0) { vt &= ~(int)VarEnum.VT_BYREF; nativeIndirection++; } // Determine if the field is/has object type. Debug.Assert(vt != (int)VarEnum.VT_PTR); switch ((VarEnum)vt) { // These are object types. case VarEnum.VT_BSTR: case VarEnum.VT_DISPATCH: case VarEnum.VT_VARIANT: case VarEnum.VT_UNKNOWN: case VarEnum.VT_SAFEARRAY: case VarEnum.VT_LPSTR: case VarEnum.VT_LPWSTR: return true; // A user-defined may or may not be/contain Object type. case VarEnum.VT_USERDEFINED: // User defined type. Get the TypeInfo. TypeInfo refTypeInfo = typeInfo.GetRefTypeInfo(typeDesc.hreftype); TypeAttr refTypeAttr = refTypeInfo.GetTypeAttr(); // Some user defined class. Is it a value class, or a VOS class? switch (refTypeAttr.typekind) { // Alias -- Is the aliased thing an Object type? case TypeLibTypes.Interop.TYPEKIND.TKIND_ALIAS: return IsObjectType(refTypeInfo, refTypeAttr.tdescAlias); // Record/Enum/Union -- Does it contain an Object type? case TypeLibTypes.Interop.TYPEKIND.TKIND_RECORD: case TypeLibTypes.Interop.TYPEKIND.TKIND_ENUM: case TypeLibTypes.Interop.TYPEKIND.TKIND_UNION: // Byref/Ptrto record is Object. Contained record might be. if (nativeIndirection > 0) return true; else return HasObjectFields(refTypeInfo); // Class/Interface -- An Object Type. case TypeLibTypes.Interop.TYPEKIND.TKIND_INTERFACE: case TypeLibTypes.Interop.TYPEKIND.TKIND_DISPATCH: case TypeLibTypes.Interop.TYPEKIND.TKIND_COCLASS: return true; default: return true; } // switch (psAttrAlias->typekind) case VarEnum.VT_CY: case VarEnum.VT_DATE: case VarEnum.VT_DECIMAL: // Pointer to the value type is an object. Contained one isn't. if (nativeIndirection > 0) return true; else return false; // A fixed array is an Object type. case VarEnum.VT_CARRAY: return true; // Other types I4, etc., are not Object types. default: return false; } // switch (vt=pType->vt) }
public TypeInfo GetUserDefinedTypeInfo(TypeInfo typeinfo) { if (typeinfo == null) throw new ArgumentNullException(nameof(typeinfo)); return typeinfo.GetRefTypeInfo(hreftype); }
private static string GetAliasName(ConverterInfo info, TypeInfo typeInfo, TypeDesc typeDesc) { // Drill down to the actual type that is pointed to. while (typeDesc.vt == (int)VarEnum.VT_PTR) typeDesc = typeDesc.lptdesc; // If the parameter is an alias then we need to add a custom attribute to the // parameter that describes the alias. if (typeDesc.vt == (int)VarEnum.VT_USERDEFINED) { TypeInfo refTypeInfo = typeInfo.GetRefTypeInfo(typeDesc.hreftype); using (TypeAttr refTypeAttr = refTypeInfo.GetTypeAttr()) { if (refTypeAttr.typekind == TypeLibTypes.Interop.TYPEKIND.TKIND_ALIAS) { return info.GetManagedName(refTypeInfo); } } } return null; }
/// <summary> /// Is this function a NewEnum function with the right parameters and DISPID? /// </summary> public static bool IsNewEnumFunc(ConverterInfo info, TypeInfo typeInfo, FuncDesc func, int index) { // // Support GUID_DispIdOverride // int dispid = func.memid; GetOverrideDispId(info, typeInfo, index, InterfaceMemberType.Method, ref dispid, false); if (dispid == WellKnownDispId.DISPID_NEWENUM) { TypeDesc typeDesc = null; if (func.funckind == TypeLibTypes.Interop.FUNCKIND.FUNC_DISPATCH) { if (func.IsPropertyGet || func.IsFunc) { if (func.cParams == 0) { typeDesc = func.elemdescFunc.tdesc; } else if (info.TransformDispRetVal && func.cParams == 1 && func.GetElemDesc(0).paramdesc.IsRetval) { typeDesc = func.GetElemDesc(0).tdesc.lptdesc; } } } else if (func.funckind == TypeLibTypes.Interop.FUNCKIND.FUNC_PUREVIRTUAL) { if ((func.cParams == 1) && (func.IsPropertyGet || func.IsFunc) && (func.GetElemDesc(0).paramdesc.IsRetval) && (func.GetElemDesc(0).tdesc.vt == (int)VarEnum.VT_PTR)) { typeDesc = func.GetElemDesc(0).tdesc.lptdesc; } } if (typeDesc != null) { if (typeDesc.vt == (int)VarEnum.VT_UNKNOWN || typeDesc.vt == (int)VarEnum.VT_DISPATCH) { // The member returns an IUnknown* or an IDispatch* which is valid. return true; } else if (typeDesc.vt == (int)VarEnum.VT_PTR) { typeDesc = typeDesc.lptdesc; if (typeDesc.vt == (int)VarEnum.VT_USERDEFINED) { TypeInfo type = typeInfo.GetRefTypeInfo(typeDesc.hreftype); using (TypeAttr attr = type.GetTypeAttr()) { if (attr.Guid == WellKnownGuids.IID_IUnknown || attr.Guid == WellKnownGuids.IID_IDispatch || attr.Guid == WellKnownGuids.IID_IEnumVARIANT) { return true; } } } } } } return false; }
/// <summary> /// Is this dispatch property a NewEnum property with the right type and DISPID? /// </summary> public static bool IsNewEnumDispatchProperty(ConverterInfo info, TypeInfo typeInfo, VarDesc var, int index) { // // Support GUID_DispIdOverride // int dispid = var.memid; GetOverrideDispId(info, typeInfo, index, InterfaceMemberType.Variable, ref dispid, false); if (dispid == WellKnownDispId.DISPID_NEWENUM && var.elemdescVar.paramdesc.IsRetval && var.IsReadOnly ) { TypeDesc typeDesc = var.elemdescVar.tdesc; if (typeDesc.vt == (int)VarEnum.VT_UNKNOWN || typeDesc.vt == (int)VarEnum.VT_DISPATCH) { return true; } else if (typeDesc.vt == (int)VarEnum.VT_PTR) { typeDesc = typeDesc.lptdesc; if (typeDesc.vt == (int)VarEnum.VT_USERDEFINED) { TypeInfo type = typeInfo.GetRefTypeInfo(typeDesc.hreftype); using (TypeAttr attr = type.GetTypeAttr()) { if (attr.Guid == WellKnownGuids.IID_IUnknown || attr.Guid == WellKnownGuids.IID_IDispatch || attr.Guid == WellKnownGuids.IID_IEnumVARIANT) { return true; } } } } } return false; }