// // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2015 Jb Evain // Copyright (c) 2008 - 2011 Novell, Inc. // // Licensed under the MIT/X11 license. // using MonoFN.Cecil.Cil; using MonoFN.Cecil.Metadata; using MonoFN.Cecil.PE; using MonoFN.Collections.Generic; using System; using System.Collections.Generic; using System.IO; using System.Threading; using SR = System.Reflection; namespace MonoFN.Cecil { public enum ReadingMode { Immediate = 1, Deferred = 2 } public sealed class ReaderParameters { internal IAssemblyResolver assembly_resolver; internal IMetadataResolver metadata_resolver; internal IMetadataImporterProvider metadata_importer_provider; internal IReflectionImporterProvider reflection_importer_provider; public ReadingMode ReadingMode { get; set; } public bool InMemory { get; set; } public IAssemblyResolver AssemblyResolver { get { return assembly_resolver; } set { assembly_resolver = value; } } public IMetadataResolver MetadataResolver { get { return metadata_resolver; } set { metadata_resolver = value; } } public IMetadataImporterProvider MetadataImporterProvider { get { return metadata_importer_provider; } set { metadata_importer_provider = value; } } public IReflectionImporterProvider ReflectionImporterProvider { get { return reflection_importer_provider; } set { reflection_importer_provider = value; } } public Stream SymbolStream { get; set; } public ISymbolReaderProvider SymbolReaderProvider { get; set; } public bool ReadSymbols { get; set; } public bool ThrowIfSymbolsAreNotMatching { get; set; } public bool ReadWrite { get; set; } public bool ApplyWindowsRuntimeProjections { get; set; } public ReaderParameters() : this(ReadingMode.Deferred) { } public ReaderParameters(ReadingMode readingMode) { ReadingMode = readingMode; ThrowIfSymbolsAreNotMatching = true; } } public sealed class ModuleParameters { public ModuleKind Kind { get; set; } public TargetRuntime Runtime { get; set; } public uint? Timestamp { get; set; } public TargetArchitecture Architecture { get; set; } public IAssemblyResolver AssemblyResolver { get; set; } public IMetadataResolver MetadataResolver { get; set; } public IMetadataImporterProvider MetadataImporterProvider { get; set; } public IReflectionImporterProvider ReflectionImporterProvider { get; set; } public ModuleParameters() { Kind = ModuleKind.Dll; Runtime = GetCurrentRuntime(); Architecture = TargetArchitecture.I386; } private static TargetRuntime GetCurrentRuntime() { return typeof(object).Assembly.ImageRuntimeVersion.ParseRuntime(); } } public sealed class WriterParameters { public uint? Timestamp { get; set; } public Stream SymbolStream { get; set; } public ISymbolWriterProvider SymbolWriterProvider { get; set; } public bool WriteSymbols { get; set; } public bool HasStrongNameKey { get { return StrongNameKeyPair != null || StrongNameKeyBlob != null || StrongNameKeyContainer != null; } } public byte[] StrongNameKeyBlob { get; set; } public string StrongNameKeyContainer { get; set; } public SR.StrongNameKeyPair StrongNameKeyPair { get; set; } public bool DeterministicMvid { get; set; } } public sealed class ModuleDefinition : ModuleReference, ICustomAttributeProvider, ICustomDebugInformationProvider, IDisposable { internal Image Image; internal MetadataSystem MetadataSystem; internal ReadingMode ReadingMode; internal ISymbolReaderProvider SymbolReaderProvider; internal ISymbolReader symbol_reader; internal Disposable assembly_resolver; internal IMetadataResolver metadata_resolver; internal TypeSystem type_system; internal readonly MetadataReader reader; internal string runtime_version; internal ModuleKind kind; private WindowsRuntimeProjections projections; private TargetRuntime runtime; internal ushort linker_version = 8; internal ushort subsystem_major = 4; internal ushort subsystem_minor = 0; internal uint timestamp; internal AssemblyDefinition assembly; private MethodDefinition entry_point; private bool entry_point_set; internal IReflectionImporter reflection_importer; internal IMetadataImporter metadata_importer; private Collection custom_attributes; private Collection references; private Collection modules; private Collection resources; private Collection exported_types; private TypeDefinitionCollection types; internal Collection custom_infos; internal MetadataBuilder metadata_builder; public bool IsMain { get { return kind != ModuleKind.NetModule; } } public ModuleKind Kind { get { return kind; } set { kind = value; } } public MetadataKind MetadataKind { get; set; } internal WindowsRuntimeProjections Projections { get { if (projections == null) Interlocked.CompareExchange(ref projections, new(this), null); return projections; } } public TargetRuntime Runtime { get { return runtime; } set { runtime = value; runtime_version = runtime.RuntimeVersionString(); } } public string RuntimeVersion { get { return runtime_version; } set { runtime_version = value; runtime = runtime_version.ParseRuntime(); } } public TargetArchitecture Architecture { get; set; } public ModuleAttributes Attributes { get; set; } public ModuleCharacteristics Characteristics { get; set; } [Obsolete("Use FileName")] public string FullyQualifiedName { get { return FileName; } } public string FileName { get; } public Guid Mvid { get; set; } internal bool HasImage { get { return Image != null; } } public bool HasSymbols { get { return symbol_reader != null; } } public ISymbolReader SymbolReader { get { return symbol_reader; } } public override MetadataScopeType MetadataScopeType { get { return MetadataScopeType.ModuleDefinition; } } public AssemblyDefinition Assembly { get { return assembly; } } internal IReflectionImporter ReflectionImporter { get { if (reflection_importer == null) Interlocked.CompareExchange(ref reflection_importer, new DefaultReflectionImporter(this), null); return reflection_importer; } } internal IMetadataImporter MetadataImporter { get { if (metadata_importer == null) Interlocked.CompareExchange(ref metadata_importer, new DefaultMetadataImporter(this), null); return metadata_importer; } } public IAssemblyResolver AssemblyResolver { get { if (assembly_resolver.value == null) { lock (SyncRoot) { assembly_resolver = Disposable.Owned(new DefaultAssemblyResolver() as IAssemblyResolver); } } return assembly_resolver.value; } } public IMetadataResolver MetadataResolver { get { if (metadata_resolver == null) Interlocked.CompareExchange(ref metadata_resolver, new MetadataResolver(AssemblyResolver), null); return metadata_resolver; } } public TypeSystem TypeSystem { get { if (type_system == null) Interlocked.CompareExchange(ref type_system, TypeSystem.CreateTypeSystem(this), null); return type_system; } } public bool HasAssemblyReferences { get { if (references != null) return references.Count > 0; return HasImage && Image.HasTable(Table.AssemblyRef); } } public Collection AssemblyReferences { get { if (references != null) return references; if (HasImage) return Read(ref references, this, (_, reader) => reader.ReadAssemblyReferences()); Interlocked.CompareExchange(ref references, new(), null); return references; } } public bool HasModuleReferences { get { if (modules != null) return modules.Count > 0; return HasImage && Image.HasTable(Table.ModuleRef); } } public Collection ModuleReferences { get { if (modules != null) return modules; if (HasImage) return Read(ref modules, this, (_, reader) => reader.ReadModuleReferences()); Interlocked.CompareExchange(ref modules, new(), null); return modules; } } public bool HasResources { get { if (resources != null) return resources.Count > 0; if (HasImage) return Image.HasTable(Table.ManifestResource) || Read(this, (_, reader) => reader.HasFileResource()); return false; } } public Collection Resources { get { if (resources != null) return resources; if (HasImage) return Read(ref resources, this, (_, reader) => reader.ReadResources()); Interlocked.CompareExchange(ref resources, new(), null); return resources; } } public bool HasCustomAttributes { get { if (custom_attributes != null) return custom_attributes.Count > 0; return this.GetHasCustomAttributes(this); } } public Collection CustomAttributes { get { return custom_attributes ?? this.GetCustomAttributes(ref custom_attributes, this); } } public bool HasTypes { get { if (types != null) return types.Count > 0; return HasImage && Image.HasTable(Table.TypeDef); } } public Collection Types { get { if (types != null) return types; if (HasImage) return Read(ref types, this, (_, reader) => reader.ReadTypes()); Interlocked.CompareExchange(ref types, new(this), null); return types; } } public bool HasExportedTypes { get { if (exported_types != null) return exported_types.Count > 0; return HasImage && Image.HasTable(Table.ExportedType); } } public Collection ExportedTypes { get { if (exported_types != null) return exported_types; if (HasImage) return Read(ref exported_types, this, (_, reader) => reader.ReadExportedTypes()); Interlocked.CompareExchange(ref exported_types, new(), null); return exported_types; } } public MethodDefinition EntryPoint { get { if (entry_point_set) return entry_point; if (HasImage) Read(ref entry_point, this, (_, reader) => reader.ReadEntryPoint()); else entry_point = null; entry_point_set = true; return entry_point; } set { entry_point = value; entry_point_set = true; } } public bool HasCustomDebugInformations { get { return custom_infos != null && custom_infos.Count > 0; } } public Collection CustomDebugInformations { get { if (custom_infos == null) Interlocked.CompareExchange(ref custom_infos, new(), null); return custom_infos; } } internal ModuleDefinition() { MetadataSystem = new(); token = new(TokenType.Module, 1); } internal ModuleDefinition(Image image) : this() { Image = image; kind = image.Kind; RuntimeVersion = image.RuntimeVersion; Architecture = image.Architecture; Attributes = image.Attributes; Characteristics = image.DllCharacteristics; linker_version = image.LinkerVersion; subsystem_major = image.SubSystemMajor; subsystem_minor = image.SubSystemMinor; FileName = image.FileName; timestamp = image.Timestamp; reader = new(this); } public void Dispose() { if (Image != null) Image.Dispose(); if (symbol_reader != null) symbol_reader.Dispose(); if (assembly_resolver.value != null) assembly_resolver.Dispose(); } public bool HasTypeReference(string fullName) { return HasTypeReference(string.Empty, fullName); } public bool HasTypeReference(string scope, string fullName) { Mixin.CheckFullName(fullName); if (!HasImage) return false; return GetTypeReference(scope, fullName) != null; } public bool TryGetTypeReference(string fullName, out TypeReference type) { return TryGetTypeReference(string.Empty, fullName, out type); } public bool TryGetTypeReference(string scope, string fullName, out TypeReference type) { Mixin.CheckFullName(fullName); if (!HasImage) { type = null; return false; } return (type = GetTypeReference(scope, fullName)) != null; } private TypeReference GetTypeReference(string scope, string fullname) { return Read(new Row(scope, fullname), (row, reader) => reader.GetTypeReference(row.Col1, row.Col2)); } public IEnumerable GetTypeReferences() { if (!HasImage) return Empty.Array; return Read(this, (_, reader) => reader.GetTypeReferences()); } public IEnumerable GetMemberReferences() { if (!HasImage) return Empty.Array; return Read(this, (_, reader) => reader.GetMemberReferences()); } public IEnumerable GetCustomAttributes() { if (!HasImage) return Empty.Array; return Read(this, (_, reader) => reader.GetCustomAttributes()); } public TypeReference GetType(string fullName, bool runtimeName) { return runtimeName ? TypeParser.ParseType(this, fullName, typeDefinitionOnly: true) : GetType(fullName); } public TypeDefinition GetType(string fullName) { Mixin.CheckFullName(fullName); int position = fullName.IndexOf('/'); if (position > 0) return GetNestedType(fullName); return ((TypeDefinitionCollection)Types).GetType(fullName); } public TypeDefinition GetType(string @namespace, string name) { Mixin.CheckName(name); return ((TypeDefinitionCollection)Types).GetType(@namespace ?? string.Empty, name); } public IEnumerable GetTypes() { return GetTypes(Types); } private static IEnumerable GetTypes(Collection types) { for (int i = 0; i < types.Count; i++) { TypeDefinition type = types[i]; yield return type; if (!type.HasNestedTypes) continue; foreach (TypeDefinition nested in GetTypes(type.NestedTypes)) yield return nested; } } private TypeDefinition GetNestedType(string fullname) { string[] names = fullname.Split('/'); TypeDefinition type = GetType(names[0]); if (type == null) return null; for (int i = 1; i < names.Length; i++) { TypeDefinition nested_type = type.GetNestedType(names[i]); if (nested_type == null) return null; type = nested_type; } return type; } internal FieldDefinition Resolve(FieldReference field) { return MetadataResolver.Resolve(field); } internal MethodDefinition Resolve(MethodReference method) { return MetadataResolver.Resolve(method); } internal TypeDefinition Resolve(TypeReference type) { return MetadataResolver.Resolve(type); } private static void CheckContext(IGenericParameterProvider context, ModuleDefinition module) { if (context == null) return; if (context.Module != module) throw new ArgumentException(); } [Obsolete("Use ImportReference", error: false)] public TypeReference Import(Type type) { return ImportReference(type, null); } public TypeReference ImportReference(Type type) { return ImportReference(type, null); } [Obsolete("Use ImportReference", error: false)] public TypeReference Import(Type type, IGenericParameterProvider context) { return ImportReference(type, context); } public TypeReference ImportReference(Type type, IGenericParameterProvider context) { Mixin.CheckType(type); CheckContext(context, this); return ReflectionImporter.ImportReference(type, context); } [Obsolete("Use ImportReference", error: false)] public FieldReference Import(SR.FieldInfo field) { return ImportReference(field, null); } [Obsolete("Use ImportReference", error: false)] public FieldReference Import(SR.FieldInfo field, IGenericParameterProvider context) { return ImportReference(field, context); } public FieldReference ImportReference(SR.FieldInfo field) { return ImportReference(field, null); } public FieldReference ImportReference(SR.FieldInfo field, IGenericParameterProvider context) { Mixin.CheckField(field); CheckContext(context, this); return ReflectionImporter.ImportReference(field, context); } [Obsolete("Use ImportReference", error: false)] public MethodReference Import(SR.MethodBase method) { return ImportReference(method, null); } [Obsolete("Use ImportReference", error: false)] public MethodReference Import(SR.MethodBase method, IGenericParameterProvider context) { return ImportReference(method, context); } public MethodReference ImportReference(SR.MethodBase method) { return ImportReference(method, null); } public MethodReference ImportReference(SR.MethodBase method, IGenericParameterProvider context) { Mixin.CheckMethod(method); CheckContext(context, this); return ReflectionImporter.ImportReference(method, context); } [Obsolete("Use ImportReference", error: false)] public TypeReference Import(TypeReference type) { return ImportReference(type, null); } [Obsolete("Use ImportReference", error: false)] public TypeReference Import(TypeReference type, IGenericParameterProvider context) { return ImportReference(type, context); } public TypeReference ImportReference(TypeReference type) { return ImportReference(type, null); } public TypeReference ImportReference(TypeReference type, IGenericParameterProvider context) { Mixin.CheckType(type); if (type.Module == this) return type; CheckContext(context, this); return MetadataImporter.ImportReference(type, context); } [Obsolete("Use ImportReference", error: false)] public FieldReference Import(FieldReference field) { return ImportReference(field, null); } [Obsolete("Use ImportReference", error: false)] public FieldReference Import(FieldReference field, IGenericParameterProvider context) { return ImportReference(field, context); } public FieldReference ImportReference(FieldReference field) { return ImportReference(field, null); } public FieldReference ImportReference(FieldReference field, IGenericParameterProvider context) { Mixin.CheckField(field); if (field.Module == this) return field; CheckContext(context, this); return MetadataImporter.ImportReference(field, context); } [Obsolete("Use ImportReference", error: false)] public MethodReference Import(MethodReference method) { return ImportReference(method, null); } [Obsolete("Use ImportReference", error: false)] public MethodReference Import(MethodReference method, IGenericParameterProvider context) { return ImportReference(method, context); } public MethodReference ImportReference(MethodReference method) { return ImportReference(method, null); } public MethodReference ImportReference(MethodReference method, IGenericParameterProvider context) { Mixin.CheckMethod(method); if (method.Module == this) return method; CheckContext(context, this); return MetadataImporter.ImportReference(method, context); } public IMetadataTokenProvider LookupToken(int token) { return LookupToken(new MetadataToken((uint)token)); } public IMetadataTokenProvider LookupToken(MetadataToken token) { return Read(token, (t, reader) => reader.LookupToken(t)); } public void ImmediateRead() { if (!HasImage) return; ReadingMode = ReadingMode.Immediate; ImmediateModuleReader moduleReader = new(Image); moduleReader.ReadModule(this, resolve_attributes: true); } internal object SyncRoot { get; } = new(); internal void Read(TItem item, Action read) { lock (SyncRoot) { int position = reader.position; IGenericContext context = reader.context; read(item, reader); reader.position = position; reader.context = context; } } internal TRet Read(TItem item, Func read) { lock (SyncRoot) { int position = reader.position; IGenericContext context = reader.context; TRet ret = read(item, reader); reader.position = position; reader.context = context; return ret; } } internal TRet Read(ref TRet variable, TItem item, Func read) where TRet : class { lock (SyncRoot) { if (variable != null) return variable; int position = reader.position; IGenericContext context = reader.context; TRet ret = read(item, reader); reader.position = position; reader.context = context; return variable = ret; } } public bool HasDebugHeader { get { return Image != null && Image.DebugHeader != null; } } public ImageDebugHeader GetDebugHeader() { return Image.DebugHeader ?? new ImageDebugHeader(); } public static ModuleDefinition CreateModule(string name, ModuleKind kind) { return CreateModule(name, new ModuleParameters { Kind = kind }); } public static ModuleDefinition CreateModule(string name, ModuleParameters parameters) { Mixin.CheckName(name); Mixin.CheckParameters(parameters); ModuleDefinition module = new() { Name = name, kind = parameters.Kind, timestamp = parameters.Timestamp ?? Mixin.GetTimestamp(), Runtime = parameters.Runtime, Architecture = parameters.Architecture, Mvid = Guid.NewGuid(), Attributes = ModuleAttributes.ILOnly, Characteristics = (ModuleCharacteristics)0x8540 }; if (parameters.AssemblyResolver != null) module.assembly_resolver = Disposable.NotOwned(parameters.AssemblyResolver); if (parameters.MetadataResolver != null) module.metadata_resolver = parameters.MetadataResolver; if (parameters.MetadataImporterProvider != null) module.metadata_importer = parameters.MetadataImporterProvider.GetMetadataImporter(module); if (parameters.ReflectionImporterProvider != null) module.reflection_importer = parameters.ReflectionImporterProvider.GetReflectionImporter(module); if (parameters.Kind != ModuleKind.NetModule) { AssemblyDefinition assembly = new(); module.assembly = assembly; module.assembly.Name = CreateAssemblyName(name); assembly.main_module = module; } module.Types.Add(new(string.Empty, "", TypeAttributes.NotPublic)); return module; } private static AssemblyNameDefinition CreateAssemblyName(string name) { if (name.EndsWith(".dll") || name.EndsWith(".exe")) name = name.Substring(0, name.Length - 4); return new(name, Mixin.ZeroVersion); } public void ReadSymbols() { if (string.IsNullOrEmpty(FileName)) throw new InvalidOperationException(); DefaultSymbolReaderProvider provider = new(throwIfNoSymbol: true); ReadSymbols(provider.GetSymbolReader(this, FileName), throwIfSymbolsAreNotMaching: true); } public void ReadSymbols(ISymbolReader reader) { ReadSymbols(reader, throwIfSymbolsAreNotMaching: true); } public void ReadSymbols(ISymbolReader reader, bool throwIfSymbolsAreNotMaching) { if (reader == null) throw new ArgumentNullException("reader"); symbol_reader = reader; if (!symbol_reader.ProcessDebugHeader(GetDebugHeader())) { symbol_reader = null; if (throwIfSymbolsAreNotMaching) throw new SymbolsNotMatchingException("Symbols were found but are not matching the assembly"); return; } if (HasImage && ReadingMode == ReadingMode.Immediate) { ImmediateModuleReader immediate_reader = new(Image); immediate_reader.ReadSymbols(this); } } public static ModuleDefinition ReadModule(string fileName) { return ReadModule(fileName, new(ReadingMode.Deferred)); } public static ModuleDefinition ReadModule(string fileName, ReaderParameters parameters) { Stream stream = GetFileStream(fileName, FileMode.Open, parameters.ReadWrite ? FileAccess.ReadWrite : FileAccess.Read, FileShare.Read); if (parameters.InMemory) { MemoryStream memory = new(stream.CanSeek ? (int)stream.Length : 0); using (stream) { stream.CopyTo(memory); } memory.Position = 0; stream = memory; } try { return ReadModule(Disposable.Owned(stream), fileName, parameters); } catch (Exception) { stream.Dispose(); throw; } } private static Stream GetFileStream(string fileName, FileMode mode, FileAccess access, FileShare share) { Mixin.CheckFileName(fileName); return new FileStream(fileName, mode, access, share); } public static ModuleDefinition ReadModule(Stream stream) { return ReadModule(stream, new(ReadingMode.Deferred)); } public static ModuleDefinition ReadModule(Stream stream, ReaderParameters parameters) { Mixin.CheckStream(stream); Mixin.CheckReadSeek(stream); return ReadModule(Disposable.NotOwned(stream), stream.GetFileName(), parameters); } private static ModuleDefinition ReadModule(Disposable stream, string fileName, ReaderParameters parameters) { Mixin.CheckParameters(parameters); return ModuleReader.CreateModule(ImageReader.ReadImage(stream, fileName), parameters); } public void Write(string fileName) { Write(fileName, new()); } public void Write(string fileName, WriterParameters parameters) { Mixin.CheckParameters(parameters); Stream file = GetFileStream(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.Read); ModuleWriter.WriteModule(this, Disposable.Owned(file), parameters); } public void Write() { Write(new WriterParameters()); } public void Write(WriterParameters parameters) { if (!HasImage) throw new InvalidOperationException(); Write(Image.Stream.value, parameters); } public void Write(Stream stream) { Write(stream, new()); } public void Write(Stream stream, WriterParameters parameters) { Mixin.CheckStream(stream); Mixin.CheckWriteSeek(stream); Mixin.CheckParameters(parameters); ModuleWriter.WriteModule(this, Disposable.NotOwned(stream), parameters); } } internal static partial class Mixin { public enum Argument { name, fileName, fullName, stream, type, method, field, parameters, module, modifierType, eventType, fieldType, declaringType, returnType, propertyType, interfaceType, constraintType } public static void CheckName(object name) { if (name == null) throw new ArgumentNullException(Argument.name.ToString()); } public static void CheckName(string name) { if (string.IsNullOrEmpty(name)) throw new ArgumentNullOrEmptyException(Argument.name.ToString()); } public static void CheckFileName(string fileName) { if (string.IsNullOrEmpty(fileName)) throw new ArgumentNullOrEmptyException(Argument.fileName.ToString()); } public static void CheckFullName(string fullName) { if (string.IsNullOrEmpty(fullName)) throw new ArgumentNullOrEmptyException(Argument.fullName.ToString()); } public static void CheckStream(object stream) { if (stream == null) throw new ArgumentNullException(Argument.stream.ToString()); } public static void CheckWriteSeek(Stream stream) { if (!stream.CanWrite || !stream.CanSeek) throw new ArgumentException("Stream must be writable and seekable."); } public static void CheckReadSeek(Stream stream) { if (!stream.CanRead || !stream.CanSeek) throw new ArgumentException("Stream must be readable and seekable."); } public static void CheckType(object type) { if (type == null) throw new ArgumentNullException(Argument.type.ToString()); } public static void CheckType(object type, Argument argument) { if (type == null) throw new ArgumentNullException(argument.ToString()); } public static void CheckField(object field) { if (field == null) throw new ArgumentNullException(Argument.field.ToString()); } public static void CheckMethod(object method) { if (method == null) throw new ArgumentNullException(Argument.method.ToString()); } public static void CheckParameters(object parameters) { if (parameters == null) throw new ArgumentNullException(Argument.parameters.ToString()); } public static uint GetTimestamp() { return (uint)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds; } public static bool HasImage(this ModuleDefinition self) { return self != null && self.HasImage; } public static string GetFileName(this Stream self) { FileStream file_stream = self as FileStream; if (file_stream == null) return string.Empty; return Path.GetFullPath(file_stream.Name); } public static TargetRuntime ParseRuntime(this string self) { if (string.IsNullOrEmpty(self)) return TargetRuntime.Net_4_0; switch (self[1]) { case '1': return self[3] == '0' ? TargetRuntime.Net_1_0 : TargetRuntime.Net_1_1; case '2': return TargetRuntime.Net_2_0; case '4': default: return TargetRuntime.Net_4_0; } } public static string RuntimeVersionString(this TargetRuntime runtime) { switch (runtime) { case TargetRuntime.Net_1_0: return "v1.0.3705"; case TargetRuntime.Net_1_1: return "v1.1.4322"; case TargetRuntime.Net_2_0: return "v2.0.50727"; case TargetRuntime.Net_4_0: default: return "v4.0.30319"; } } public static bool IsWindowsMetadata(this ModuleDefinition module) { return module.MetadataKind != MetadataKind.Ecma335; } public static byte[] ReadAll(this Stream self) { int read; MemoryStream memory = new((int)self.Length); byte[] buffer = new byte [1024]; while ((read = self.Read(buffer, 0, buffer.Length)) != 0) memory.Write(buffer, 0, read); return memory.ToArray(); } public static void Read(object o) { } } }