internal static unsafe object[] GetCustomAttributes(Module decoratedModule, int decoratedMetadataToken, int pcaCount, RuntimeType attributeFilterType, bool mustBeInheritable, IList derivedAttributes) { if (decoratedModule.Assembly.ReflectionOnly) { throw new InvalidOperationException(Environment.GetResourceString("Arg_ReflectionOnlyCA")); } MetadataImport metadataImport = decoratedModule.MetadataImport; CustomAttributeRecord[] customAttributeRecords = CustomAttributeData.GetCustomAttributeRecords(decoratedModule, decoratedMetadataToken); Type elementType = (((attributeFilterType == null) || attributeFilterType.IsValueType) || attributeFilterType.ContainsGenericParameters) ? typeof(object) : attributeFilterType; if ((attributeFilterType == null) && (customAttributeRecords.Length == 0)) { return (Array.CreateInstance(elementType, 0) as object[]); } object[] attributes = Array.CreateInstance(elementType, customAttributeRecords.Length) as object[]; int length = 0; SecurityContextFrame frame = new SecurityContextFrame(); frame.Push(decoratedModule.Assembly.InternalAssembly); Assembly lastAptcaOkAssembly = null; for (int i = 0; i < customAttributeRecords.Length; i++) { bool flag2; bool flag3; object obj2 = null; CustomAttributeRecord caRecord = customAttributeRecords[i]; RuntimeMethodHandle ctor = new RuntimeMethodHandle(); RuntimeType attributeType = null; int namedArgs = 0; IntPtr signature = caRecord.blob.Signature; IntPtr blobEnd = (IntPtr) (((void*) signature) + caRecord.blob.Length); if (FilterCustomAttributeRecord(caRecord, metadataImport, ref lastAptcaOkAssembly, decoratedModule, decoratedMetadataToken, attributeFilterType, mustBeInheritable, attributes, derivedAttributes, out attributeType, out ctor, out flag2, out flag3)) { if (!ctor.IsNullHandle()) { ctor.CheckLinktimeDemands(decoratedModule, decoratedMetadataToken); } RuntimeConstructorInfo.CheckCanCreateInstance(attributeType, flag3); if (flag2) { obj2 = CreateCaObject(decoratedModule, ctor, ref signature, blobEnd, out namedArgs); } else { obj2 = attributeType.TypeHandle.CreateCaInstance(ctor); if (Marshal.ReadInt16(signature) != 1) { throw new CustomAttributeFormatException(); } signature = (IntPtr) (((void*) signature) + 2); namedArgs = Marshal.ReadInt16(signature); signature = (IntPtr) (((void*) signature) + 2); } for (int j = 0; j < namedArgs; j++) { string str; bool flag4; Type type3; object obj3; IntPtr ptr1 = caRecord.blob.Signature; GetPropertyOrFieldData(decoratedModule, ref signature, blobEnd, out str, out flag4, out type3, out obj3); try { if (flag4) { if ((type3 == null) && (obj3 != null)) { type3 = (obj3.GetType() == typeof(RuntimeType)) ? typeof(Type) : obj3.GetType(); } RuntimePropertyInfo property = null; if (type3 == null) { property = attributeType.GetProperty(str) as RuntimePropertyInfo; } else { property = attributeType.GetProperty(str, type3, Type.EmptyTypes) as RuntimePropertyInfo; } RuntimeMethodInfo setMethod = property.GetSetMethod(true) as RuntimeMethodInfo; if (setMethod.IsPublic) { setMethod.MethodHandle.CheckLinktimeDemands(decoratedModule, decoratedMetadataToken); setMethod.Invoke(obj2, BindingFlags.Default, null, new object[] { obj3 }, null, true); } } else { (attributeType.GetField(str) as RtFieldInfo).InternalSetValue(obj2, obj3, BindingFlags.Default, Type.DefaultBinder, null, false); } } catch (Exception exception) { throw new CustomAttributeFormatException(string.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString(flag4 ? "RFLCT.InvalidPropFail" : "RFLCT.InvalidFieldFail"), new object[] { str }), exception); } } if (!signature.Equals(blobEnd)) { throw new CustomAttributeFormatException(); } attributes[length++] = obj2; } } frame.Pop(); if ((length == customAttributeRecords.Length) && (pcaCount == 0)) { return attributes; } if (length == 0) { Array.CreateInstance(elementType, 0); } object[] destinationArray = Array.CreateInstance(elementType, (int) (length + pcaCount)) as object[]; Array.Copy(attributes, 0, destinationArray, 0, length); return destinationArray; }
internal unsafe static object[] GetCustomAttributes( Module decoratedModule, int decoratedMetadataToken, int pcaCount, RuntimeType attributeFilterType, bool mustBeInheritable, IList derivedAttributes) { if (decoratedModule.Assembly.ReflectionOnly) throw new InvalidOperationException(Environment.GetResourceString("Arg_ReflectionOnlyCA")); MetadataImport scope = decoratedModule.MetadataImport; CustomAttributeRecord[] car = CustomAttributeData.GetCustomAttributeRecords(decoratedModule, decoratedMetadataToken); bool useObjectArray = (attributeFilterType == null || attributeFilterType.IsValueType || attributeFilterType.ContainsGenericParameters); Type arrayType = useObjectArray ? typeof(object) : attributeFilterType; if (attributeFilterType == null && car.Length == 0) return Array.CreateInstance(arrayType, 0) as object[]; object[] attributes = Array.CreateInstance(arrayType, car.Length) as object[]; int cAttributes = 0; // Custom attribute security checks are done with respect to the assembly *decorated* with the // custom attribute as opposed to the *caller of GetCustomAttributes*. // Since this assembly might not be on the stack and the attribute ctor or property setters we're about to invoke may // make security demands, we push a frame on the stack as a proxy for the decorated assembly (this frame will be picked // up an interpreted by the security stackwalker). // Once we push the frame it will be automatically popped in the event of an exception, so no need to use CERs or the // like. SecurityContextFrame frame = new SecurityContextFrame(); frame.Push(decoratedModule.Assembly); // Optimization for the case where attributes decorate entities in the same assembly in which case // we can cache the successful APTCA check between the decorated and the declared assembly. Assembly lastAptcaOkAssembly = null; for (int i = 0; i < car.Length; i++) { object attribute = null; CustomAttributeRecord caRecord = car[i]; RuntimeMethodHandle ctor = new RuntimeMethodHandle(); RuntimeType attributeType = null; bool ctorHasParameters, isVarArg; int cNamedArgs = 0; IntPtr blobStart = caRecord.blob.Signature; IntPtr blobEnd = (IntPtr)((byte*)blobStart + caRecord.blob.Length); if (!FilterCustomAttributeRecord(caRecord, scope, ref lastAptcaOkAssembly, decoratedModule, decoratedMetadataToken, attributeFilterType, mustBeInheritable, attributes, derivedAttributes, out attributeType, out ctor, out ctorHasParameters, out isVarArg)) continue; if (!ctor.IsNullHandle()) { // Linktime demand checks // decoratedMetadataToken needed as it may be "transparent" in which case we do a full stack walk ctor.CheckLinktimeDemands(decoratedModule, decoratedMetadataToken); } else { } // Leverage RuntimeConstructorInfo standard .ctor verfication RuntimeConstructorInfo.CheckCanCreateInstance(attributeType, isVarArg); // Create custom attribute object if (ctorHasParameters) { attribute = CreateCaObject(decoratedModule, ctor, ref blobStart, blobEnd, out cNamedArgs); } else { attribute = attributeType.TypeHandle.CreateCaInstance(ctor); if (Marshal.ReadInt16(blobStart) != 1) throw new CustomAttributeFormatException(); blobStart = (IntPtr)((byte*)blobStart + 2); // skip 0x0001 prefix cNamedArgs = Marshal.ReadInt16(blobStart); blobStart = (IntPtr)((byte*)blobStart + 2); // skip namedArgs count } for (int j = 0; j < cNamedArgs; j++) { #region // Initialize named properties and fields string name; bool isProperty; Type type; object value; IntPtr blobItr = caRecord.blob.Signature; GetPropertyOrFieldData(decoratedModule, ref blobStart, blobEnd, out name, out isProperty, out type, out value); try { if (isProperty) { #region // Initialize property if (type == null && value != null) type = (value.GetType() == typeof(RuntimeType)) ? typeof(Type) : value.GetType(); RuntimePropertyInfo property = null; if (type == null) property = attributeType.GetProperty(name) as RuntimePropertyInfo; else property = attributeType.GetProperty(name, type, Type.EmptyTypes) as RuntimePropertyInfo; RuntimeMethodInfo setMethod = property.GetSetMethod(true) as RuntimeMethodInfo; // Public properties may have non-public setter methods if (!setMethod.IsPublic) continue; setMethod.MethodHandle.CheckLinktimeDemands(decoratedModule, decoratedMetadataToken); setMethod.Invoke(attribute, BindingFlags.Default, null, new object[] { value }, null, true); #endregion } else { RtFieldInfo field = attributeType.GetField(name) as RtFieldInfo; field.InternalSetValue(attribute, value, BindingFlags.Default, Type.DefaultBinder, null, false); } } catch (Exception e) { throw new CustomAttributeFormatException( String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString( isProperty ? "RFLCT.InvalidPropFail" : "RFLCT.InvalidFieldFail"), name), e); } #endregion } if (!blobStart.Equals(blobEnd)) throw new CustomAttributeFormatException(); attributes[cAttributes++] = attribute; } // The frame will be popped automatically if we take an exception any time after we pushed it. So no need of a catch or // finally or CERs here. frame.Pop(); if (cAttributes == car.Length && pcaCount == 0) return attributes; if (cAttributes == 0) Array.CreateInstance(arrayType, 0); object[] result = Array.CreateInstance(arrayType, cAttributes + pcaCount) as object[]; Array.Copy(attributes, 0, result, 0, cAttributes); return result; }