/* Copyright (C) 2014-2019 de4dot@gmail.com This file is part of dnSpy dnSpy is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. dnSpy is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with dnSpy. If not, see . */ using System; using dnlib.DotNet; using dnlib.PE; namespace dnSpy.AsmEditor.Module { static class ModuleUtils { public static ModuleDef CreateNetModule(string name, Guid mvid, ClrVersion clrVersion) => CreateModule(name, mvid, clrVersion, ModuleKind.NetModule); public static ModuleDef CreateModule(string name, Guid mvid, ClrVersion clrVersion, ModuleKind kind, ModuleDef? existingModule = null) { var module = CreateModuleDef(name, mvid, clrVersion, existingModule); module.Kind = kind; module.Characteristics = Characteristics.Bit32Machine | Characteristics.ExecutableImage; if (kind == ModuleKind.Dll || kind == ModuleKind.NetModule) module.Characteristics |= Characteristics.Dll; module.DllCharacteristics = DllCharacteristics.TerminalServerAware | DllCharacteristics.NoSeh | DllCharacteristics.NxCompat | DllCharacteristics.DynamicBase; return module; } static ModuleDef CreateModuleDef(string name, Guid mvid, ClrVersion clrVersion, ModuleDef? existingModule) { var clrValues = ClrVersionValues.GetValues(clrVersion); if (clrValues is null) throw new ArgumentNullException(nameof(clrVersion)); ModuleDef module; if (existingModule is null) module = new ModuleDefUser(name, mvid, clrValues.CorLibRef); else { module = existingModule; module.Name = name; module.Mvid = mvid; OverwriteAssembly(module.CorLibTypes.AssemblyRef, clrValues.CorLibRef); } module.UpdateRowId(module); module.RuntimeVersion = clrValues.RuntimeVersion; module.Cor20HeaderRuntimeVersion = clrValues.Cor20HeaderRuntimeVersion; module.TablesHeaderVersion = clrValues.TablesHeaderVersion; module.Location = string.Empty; return module; } static void OverwriteAssembly(AssemblyRef dst, AssemblyRef src) { dst.Name = src.Name; dst.Version = src.Version; dst.PublicKeyOrToken = src.PublicKeyOrToken; dst.Culture = src.Culture; dst.Attributes = src.Attributes; dst.Hash = src.Hash; } public static AssemblyDef AddToNewAssemblyDef(ModuleDef module, ModuleKind moduleKind, out Characteristics characteristics) { var asmDef = module.UpdateRowId(new AssemblyDefUser(GetAssemblyName(module))); asmDef.Modules.Add(module); WriteNewModuleKind(module, moduleKind, out characteristics); return asmDef; } static string GetAssemblyName(ModuleDef module) { string name = module.Name; if (name.EndsWith(".exe", StringComparison.OrdinalIgnoreCase) || name.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) name = name.Substring(0, name.Length - 4); else if (name.EndsWith(".netmodule", StringComparison.OrdinalIgnoreCase)) name = name.Substring(0, name.Length - 10); if (!string.IsNullOrWhiteSpace(name)) return name; return module.Name; } public static void WriteNewModuleKind(ModuleDef module, ModuleKind moduleKind, out Characteristics characteristics) { module.Kind = moduleKind; characteristics = module.Characteristics; module.Characteristics = SaveModule.CharacteristicsHelper.GetCharacteristics(module.Characteristics, moduleKind); } } }