void Write(CustomAttribute ca) { if (ca == null) { helper.Error("The custom attribute is null"); return; } // Check whether it's raw first. If it is, we don't care whether the ctor is // invalid. Just use the raw data. if (ca.IsRawBlob) { if ((ca.ConstructorArguments != null && ca.ConstructorArguments.Count > 0) || (ca.NamedArguments != null && ca.NamedArguments.Count > 0)) { helper.Error("Raw custom attribute contains arguments and/or named arguments"); } writer.WriteBytes(ca.RawData); return; } if (ca.Constructor == null) { helper.Error("Custom attribute ctor is null"); return; } var methodSig = GetMethodSig(ca.Constructor); if (methodSig == null) { helper.Error("Custom attribute ctor's method signature is invalid"); return; } if (ca.ConstructorArguments.Count != methodSig.Params.Count) { helper.Error("Custom attribute arguments count != method sig arguments count"); } if (methodSig.ParamsAfterSentinel != null && methodSig.ParamsAfterSentinel.Count > 0) { helper.Error("Custom attribute ctor has parameters after the sentinel"); } if (ca.NamedArguments.Count > ushort.MaxValue) { helper.Error("Custom attribute has too many named arguments"); } if (ca.Constructor is MemberRef mrCtor && mrCtor.Class is TypeSpec owner && owner.TypeSig is GenericInstSig gis) { genericArguments = new GenericArguments(); genericArguments.PushTypeArgs(gis.GenericArguments); } writer.WriteUInt16((ushort)1); int numArgs = Math.Min(methodSig.Params.Count, ca.ConstructorArguments.Count); for (int i = 0; i < numArgs; i++) { WriteValue(FixTypeSig(methodSig.Params[i]), ca.ConstructorArguments[i]); } int numNamedArgs = Math.Min((int)ushort.MaxValue, ca.NamedArguments.Count); writer.WriteUInt16((ushort)numNamedArgs); for (int i = 0; i < numNamedArgs; i++) { Write(ca.NamedArguments[i]); } }
byte[] Write(MarshalType marshalType) { if (marshalType == null) { return(null); } var type = marshalType.NativeType; if (type != NativeType.RawBlob) { if ((uint)type > byte.MaxValue) { helper.Error("Invalid MarshalType.NativeType"); } writer.WriteByte((byte)type); } bool canWrite = true; switch (type) { case NativeType.FixedSysString: var fixedSysString = (FixedSysStringMarshalType)marshalType; if (fixedSysString.IsSizeValid) { WriteCompressedUInt32((uint)fixedSysString.Size); } break; case NativeType.SafeArray: var safeArray = (SafeArrayMarshalType)marshalType; if (UpdateCanWrite(safeArray.IsVariantTypeValid, "VariantType", ref canWrite)) { WriteCompressedUInt32((uint)safeArray.VariantType); } if (UpdateCanWrite(safeArray.IsUserDefinedSubTypeValid, "UserDefinedSubType", ref canWrite)) { Write(safeArray.UserDefinedSubType.AssemblyQualifiedName); } break; case NativeType.FixedArray: var fixedArray = (FixedArrayMarshalType)marshalType; if (UpdateCanWrite(fixedArray.IsSizeValid, "Size", ref canWrite)) { WriteCompressedUInt32((uint)fixedArray.Size); } if (UpdateCanWrite(fixedArray.IsElementTypeValid, "ElementType", ref canWrite)) { WriteCompressedUInt32((uint)fixedArray.ElementType); } break; case NativeType.Array: var array = (ArrayMarshalType)marshalType; if (UpdateCanWrite(array.IsElementTypeValid, "ElementType", ref canWrite)) { WriteCompressedUInt32((uint)array.ElementType); } if (UpdateCanWrite(array.IsParamNumberValid, "ParamNumber", ref canWrite)) { WriteCompressedUInt32((uint)array.ParamNumber); } if (UpdateCanWrite(array.IsSizeValid, "Size", ref canWrite)) { WriteCompressedUInt32((uint)array.Size); } if (UpdateCanWrite(array.IsFlagsValid, "Flags", ref canWrite)) { WriteCompressedUInt32((uint)array.Flags); } break; case NativeType.CustomMarshaler: var custMarshaler = (CustomMarshalType)marshalType; Write(custMarshaler.Guid); Write(custMarshaler.NativeTypeName); var cm = custMarshaler.CustomMarshaler; var cmName = cm == null ? string.Empty : FullNameFactory.AssemblyQualifiedName(cm, this); Write(cmName); Write(custMarshaler.Cookie); break; case NativeType.IUnknown: case NativeType.IDispatch: case NativeType.IntF: var iface = (InterfaceMarshalType)marshalType; if (iface.IsIidParamIndexValid) { WriteCompressedUInt32((uint)iface.IidParamIndex); } break; case NativeType.RawBlob: var data = ((RawMarshalType)marshalType).Data; if (data != null) { writer.WriteBytes(data); } break; default: break; } return(outStream.ToArray()); }