You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

121 lines
3.3 KiB

  1. using Mono.Cecil;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Reflection;
  7. using System.Text;
  8. namespace IPA.Injector
  9. {
  10. internal class VirtualizedModule
  11. {
  12. private const string ENTRY_TYPE = "Display";
  13. public FileInfo file;
  14. public ModuleDefinition module;
  15. public static VirtualizedModule Load(string engineFile)
  16. {
  17. return new VirtualizedModule(engineFile);
  18. }
  19. private VirtualizedModule(string assemblyFile)
  20. {
  21. file = new FileInfo(assemblyFile);
  22. LoadModules();
  23. }
  24. private void LoadModules()
  25. {
  26. module = ModuleDefinition.ReadModule(file.FullName);
  27. }
  28. /// <summary>
  29. ///
  30. /// </summary>
  31. /// <param name="module"></param>
  32. public void Virtualize(AssemblyName selfName, Action beforeChangeCallback = null)
  33. {
  34. bool changed = false;
  35. bool virtualize = true;
  36. foreach (var r in module.AssemblyReferences)
  37. {
  38. if (r.Name == selfName.Name)
  39. {
  40. virtualize = false;
  41. if (r.Version != selfName.Version)
  42. {
  43. r.Version = selfName.Version;
  44. changed = true;
  45. }
  46. }
  47. }
  48. if (virtualize)
  49. {
  50. changed = true;
  51. module.AssemblyReferences.Add(new AssemblyNameReference(selfName.Name, selfName.Version));
  52. foreach (var type in module.Types)
  53. {
  54. VirtualizeType(type);
  55. }
  56. }
  57. if (changed)
  58. {
  59. beforeChangeCallback?.Invoke();
  60. module.Write(file.FullName);
  61. }
  62. }
  63. private void VirtualizeType(TypeDefinition type)
  64. {
  65. if(type.IsSealed)
  66. {
  67. // Unseal
  68. type.IsSealed = false;
  69. }
  70. if (type.IsInterface) return;
  71. if (type.IsAbstract) return;
  72. // These two don't seem to work.
  73. if (type.Name == "SceneControl" || type.Name == "ConfigUI") return;
  74. // Take care of sub types
  75. foreach (var subType in type.NestedTypes)
  76. {
  77. VirtualizeType(subType);
  78. }
  79. foreach (var method in type.Methods)
  80. {
  81. if (method.IsManaged
  82. && method.IsIL
  83. && !method.IsStatic
  84. && !method.IsVirtual
  85. && !method.IsAbstract
  86. && !method.IsAddOn
  87. && !method.IsConstructor
  88. && !method.IsSpecialName
  89. && !method.IsGenericInstance
  90. && !method.HasOverrides)
  91. {
  92. method.IsVirtual = true;
  93. method.IsPublic = true;
  94. method.IsPrivate = false;
  95. method.IsNewSlot = true;
  96. method.IsHideBySig = true;
  97. }
  98. }
  99. foreach (var field in type.Fields)
  100. {
  101. if (field.IsPrivate) field.IsFamily = true;
  102. }
  103. }
  104. }
  105. }