SecurityCustomAttribute/*?*/ ReadSecurityAttribute(SecurityAttribute securityAttribute) { string/*?*/ typeNameStr = this.GetSerializedString(); if (typeNameStr == null) return null; ITypeReference/*?*/ moduleTypeReference = this.PEFileToObjectModel.GetSerializedTypeNameAsTypeReference(typeNameStr); if (moduleTypeReference == null) return null; IMethodReference ctorReference = Dummy.MethodReference; ITypeDefinition attributeType = moduleTypeReference.ResolvedType; if (!(attributeType is Dummy)) { foreach (ITypeDefinitionMember member in attributeType.GetMembersNamed(this.PEFileToObjectModel.NameTable.Ctor, false)) { IMethodDefinition/*?*/ method = member as IMethodDefinition; if (method == null) continue; if (!IteratorHelper.EnumerableHasLength(method.Parameters, 1)) continue; //TODO: check that parameter has the right type ctorReference = method; break; } } else { int ctorKey = this.PEFileToObjectModel.NameTable.Ctor.UniqueKey; foreach (ITypeMemberReference mref in this.PEFileToObjectModel.GetMemberReferences()) { IMethodReference/*?*/ methRef = mref as IMethodReference; if (methRef == null) continue; if (methRef.ContainingType.InternedKey != moduleTypeReference.InternedKey) continue; if (methRef.Name.UniqueKey != ctorKey) continue; if (!IteratorHelper.EnumerableHasLength(methRef.Parameters, 1)) continue; //TODO: check that parameter has the right type ctorReference = methRef; break; } } if (ctorReference is Dummy) { ctorReference = new MethodReference(this.PEFileToObjectModel.ModuleReader.metadataReaderHost, moduleTypeReference, CallingConvention.Default|CallingConvention.HasThis, this.PEFileToObjectModel.PlatformType.SystemVoid, this.PEFileToObjectModel.NameTable.Ctor, 0, this.PEFileToObjectModel.PlatformType.SystemSecurityPermissionsSecurityAction); } this.SignatureMemoryReader.ReadCompressedUInt32(); // BlobSize... int numOfNamedArgs = this.SignatureMemoryReader.ReadCompressedUInt32(); FieldOrPropertyNamedArgumentExpression[]/*?*/ namedArgumentArray = null; if (numOfNamedArgs > 0) { namedArgumentArray = new FieldOrPropertyNamedArgumentExpression[numOfNamedArgs]; for (int i = 0; i < numOfNamedArgs; ++i) { bool isField = this.SignatureMemoryReader.ReadByte() == SerializationType.Field; ITypeReference/*?*/ memberType = this.GetFieldOrPropType(); if (memberType == null) return null; string/*?*/ memberStr = this.GetSerializedString(); if (memberStr == null) return null; IName memberName = this.PEFileToObjectModel.NameTable.GetNameFor(memberStr); ExpressionBase/*?*/ value = this.ReadSerializedValue(memberType); if (value == null) return null; namedArgumentArray[i] = new FieldOrPropertyNamedArgumentExpression(memberName, moduleTypeReference, isField, memberType, value); } } return new SecurityCustomAttribute(securityAttribute, ctorReference, namedArgumentArray); }
//^ [NotDelayed] internal CustomAttributeDecoder( PEFileToObjectModel peFileToObjectModel, MemoryReader signatureMemoryReader, uint customAttributeRowId, IModuleMethodReference attributeConstructor ) : base(peFileToObjectModel, signatureMemoryReader) { //^ this.SignatureMemoryReader = signatureMemoryReader; //TODO: Spec# bug. This assignment should not be necessary. this.CustomAttribute = Dummy.CustomAttribute; //^ base; ushort prolog = this.SignatureMemoryReader.ReadUInt16(); if (prolog != SerializationType.CustomAttributeStart) { return; } List<ExpressionBase> exprList = new List<ExpressionBase>(); IModuleParameterTypeInformation[] modParams = attributeConstructor.RequiredModuleParameterInfos.RawArray; int len = modParams.Length; for (int i = 0; i < len; ++i) { IModuleTypeReference/*?*/ moduleTypeRef = modParams[i].ModuleTypeReference; if (moduleTypeRef == null) { // Error... return; } ExpressionBase/*?*/ argument = this.ReadSerializedValue(moduleTypeRef); if (argument == null) { // Error... this.decodeFailed = true; return; } exprList.Add(argument); } ushort numOfNamedArgs = this.SignatureMemoryReader.ReadUInt16(); FieldOrPropertyNamedArgumentExpression[]/*?*/ namedArgumentArray = null; if (numOfNamedArgs > 0) { namedArgumentArray = new FieldOrPropertyNamedArgumentExpression[numOfNamedArgs]; for (ushort i = 0; i < numOfNamedArgs; ++i) { bool isField = this.SignatureMemoryReader.ReadByte() == SerializationType.Field; IModuleTypeReference/*?*/ memberType = this.GetFieldOrPropType(); if (memberType == null) { // Error... return; } string/*?*/ memberStr = this.GetSerializedString(); if (memberStr == null) return; IName memberName = this.PEFileToObjectModel.NameTable.GetNameFor(memberStr); ExpressionBase/*?*/ value = this.ReadSerializedValue(memberType); if (value == null) { // Error... return; } IModuleTypeReference/*?*/ moduleTypeRef = attributeConstructor.OwningTypeReference; if (moduleTypeRef == null) { // Error... return; } FieldOrPropertyNamedArgumentExpression namedArg = new FieldOrPropertyNamedArgumentExpression(memberName, moduleTypeRef, isField, memberType, value); namedArgumentArray[i] = namedArg; } } EnumerableArrayWrapper<ExpressionBase, IMetadataExpression> arguments = TypeCache.EmptyExpressionList; if (exprList.Count > 0) arguments = new EnumerableArrayWrapper<ExpressionBase, IMetadataExpression>(exprList.ToArray(), Dummy.Expression); EnumerableArrayWrapper<FieldOrPropertyNamedArgumentExpression, IMetadataNamedArgument> namedArguments = TypeCache.EmptyNamedArgumentList; if (namedArgumentArray != null) namedArguments = new EnumerableArrayWrapper<FieldOrPropertyNamedArgumentExpression, IMetadataNamedArgument>(namedArgumentArray, Dummy.NamedArgument); this.CustomAttribute = new CustomAttribute(this.PEFileToObjectModel, customAttributeRowId, attributeConstructor, arguments, namedArguments); }
internal CustomAttributeDecoder(PEFileToObjectModel peFileToObjectModel, MemoryReader signatureMemoryReader, uint customAttributeRowId, IMethodReference attributeConstructor) : base(peFileToObjectModel, signatureMemoryReader) { this.CustomAttribute = Dummy.CustomAttribute; ushort prolog = this.SignatureMemoryReader.ReadUInt16(); if (prolog != SerializationType.CustomAttributeStart) return; int len = attributeConstructor.ParameterCount; IMetadataExpression[]/*?*/ exprList = len == 0 ? null : new IMetadataExpression[len]; int i = 0; foreach (var parameter in attributeConstructor.Parameters) { var parameterType = parameter.Type; if (parameterType is Dummy) { // Error... return; } ExpressionBase/*?*/ argument = this.ReadSerializedValue(parameterType); if (argument == null) { // Error... this.decodeFailed = true; return; } exprList[i++] = argument; } IMetadataNamedArgument[]/*?*/ namedArgumentArray = null; if (2 <= (int)this.SignatureMemoryReader.RemainingBytes) { ushort numOfNamedArgs = this.SignatureMemoryReader.ReadUInt16(); if (numOfNamedArgs > 0) { namedArgumentArray = new IMetadataNamedArgument[numOfNamedArgs]; for (i = 0; i < numOfNamedArgs; ++i) { if (0 >= (int)this.SignatureMemoryReader.RemainingBytes) break; bool isField = this.SignatureMemoryReader.ReadByte() == SerializationType.Field; ITypeReference/*?*/ memberType = this.GetFieldOrPropType(); if (memberType == null) { // Error... return; } string/*?*/ memberStr = this.GetSerializedString(); if (memberStr == null) return; IName memberName = this.PEFileToObjectModel.NameTable.GetNameFor(memberStr); ExpressionBase/*?*/ value = this.ReadSerializedValue(memberType); if (value == null) { // Error... return; } ITypeReference/*?*/ moduleTypeRef = attributeConstructor.ContainingType; if (moduleTypeRef == null) { // Error... return; } FieldOrPropertyNamedArgumentExpression namedArg = new FieldOrPropertyNamedArgumentExpression(memberName, moduleTypeRef, isField, memberType, value); namedArgumentArray[i] = namedArg; } } } this.CustomAttribute = peFileToObjectModel.ModuleReader.metadataReaderHost.Rewrite(peFileToObjectModel.Module, new CustomAttribute(peFileToObjectModel, customAttributeRowId, attributeConstructor, exprList, namedArgumentArray)); }
/// <summary> /// Provides the host with an opportunity to substitute a custom attribute with another during metadata reading. /// This avoids the cost of rewriting the entire unit in order to make such changes. /// </summary> /// <param name="referringUnit">The unit that contains the custom attribute.</param> /// <param name="customAttribute">The custom attribute to rewrite (fix up).</param> /// <returns> /// Usually the value in customAttribute, but occassionally another custom attribute. /// </returns> public override ICustomAttribute Rewrite(IUnit referringUnit, ICustomAttribute customAttribute) { CustomAttribute customAttr = customAttribute as CustomAttribute; if (customAttr == null) return customAttribute; var referringModule = referringUnit as IModule; if (referringModule == null || referringModule.ContainingAssembly == null || !(referringModule.ContainingAssembly.ContainsForeignTypes)) return customAttribute; if (!TypeHelper.TypesAreEquivalent(customAttribute.Type, this.PlatformType.SystemAttributeUsageAttribute)) return customAttribute; //The custom attribute constructor has been redirected from Windows.Foundation.AttributeUsageAttribute, which has a different //set of flags from System.AttributeUsageAttribute for its first and only constructor parameter and also does not have an AllowMultiple property. var argArray = customAttr.Arguments; if (argArray == null || argArray.Length != 1) return customAttribute; var argConst = argArray[0] as ConstantExpression; if (argConst == null || !(argConst.value is int)) return customAttribute; int clrEnumValue = 0; switch ((int)argConst.Value) { case 0x00000001: clrEnumValue = 0x00001000; break; case 0x00000002: clrEnumValue = 0x00000010; break; case 0x00000004: clrEnumValue = 0x00000200; break; case 0x00000008: clrEnumValue = 0x00000100; break; case 0x00000010: clrEnumValue = 0x00000400; break; case 0x00000020: clrEnumValue = 0x00000000; break; case 0x00000040: clrEnumValue = 0x00000040; break; case 0x00000080: clrEnumValue = 0x00000800; break; case 0x00000100: clrEnumValue = 0x00000080; break; case 0x00000200: clrEnumValue = 0x00000004; break; case 0x00000400: clrEnumValue = 0x00000008; break; case 0x00000800: clrEnumValue = 0x00000000; break; case -1: clrEnumValue = 0x00007FFF; break; } argConst.value = clrEnumValue; if (this.FellowCustomAttributeIncludeAllowMultiple(customAttr)) { if (customAttr.NamedArguments != null) return customAttribute; var trueVal = new ConstantExpression(this.PlatformType.SystemBoolean, true); var namedArgArray = new IMetadataNamedArgument[1]; namedArgArray[0] = new FieldOrPropertyNamedArgumentExpression(this.AllowMultiple, Dummy.Type, false, this.PlatformType.SystemBoolean, trueVal); customAttr.NamedArguments = namedArgArray; } return customAttribute; }