Plugins: Add LoadPipelineStarting / LoadPipelineEnding, rename IsHandled to FullyProcessed
This commit is contained in:
@@ -572,6 +572,15 @@ namespace Il2CppInspector
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Multi-image binaries may contain more than one Il2Cpp image
|
// Multi-image binaries may contain more than one Il2Cpp image
|
||||||
|
var inspectors = LoadFromStream(stream, metadata, statusCallback);
|
||||||
|
|
||||||
|
Console.SetOut(stdout);
|
||||||
|
|
||||||
|
return inspectors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Il2CppInspector> LoadFromStream(IFileFormatStream stream, Metadata metadata, EventHandler<string> statusCallback = null) {
|
||||||
|
|
||||||
var processors = new List<Il2CppInspector>();
|
var processors = new List<Il2CppInspector>();
|
||||||
foreach (var image in stream.Images) {
|
foreach (var image in stream.Images) {
|
||||||
Console.WriteLine("Container format: " + image.Format);
|
Console.WriteLine("Container format: " + image.Format);
|
||||||
@@ -598,7 +607,9 @@ namespace Il2CppInspector
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.SetOut(stdout);
|
// Plugin hook LoadPipelineEnding
|
||||||
|
PluginHooks.LoadPipelineEnding(processors);
|
||||||
|
|
||||||
return processors;
|
return processors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,10 @@ namespace Il2CppInspector
|
|||||||
|
|
||||||
// Initialize metadata object from a stream
|
// Initialize metadata object from a stream
|
||||||
public static Metadata FromStream(MemoryStream stream, EventHandler<string> statusCallback = null) {
|
public static Metadata FromStream(MemoryStream stream, EventHandler<string> statusCallback = null) {
|
||||||
|
// TODO: This should really be placed before the Metadata object is created,
|
||||||
|
// but for now this ensures it is called regardless of which client is in use
|
||||||
|
PluginHooks.LoadPipelineStarting();
|
||||||
|
|
||||||
var metadata = new Metadata(statusCallback);
|
var metadata = new Metadata(statusCallback);
|
||||||
stream.Position = 0;
|
stream.Position = 0;
|
||||||
stream.CopyTo(metadata);
|
stream.CopyTo(metadata);
|
||||||
@@ -173,7 +177,7 @@ namespace Il2CppInspector
|
|||||||
|
|
||||||
// Get all metadata strings
|
// Get all metadata strings
|
||||||
var pluginGetStringsResult = PluginHooks.GetStrings(this);
|
var pluginGetStringsResult = PluginHooks.GetStrings(this);
|
||||||
if (pluginGetStringsResult.IsHandled)
|
if (pluginGetStringsResult.FullyProcessed && !pluginGetStringsResult.IsInvalid)
|
||||||
Strings = pluginGetStringsResult.Strings;
|
Strings = pluginGetStringsResult.Strings;
|
||||||
|
|
||||||
else {
|
else {
|
||||||
@@ -243,7 +247,7 @@ namespace Il2CppInspector
|
|||||||
|
|
||||||
// Get all string literals
|
// Get all string literals
|
||||||
var pluginGetStringLiteralsResult = PluginHooks.GetStringLiterals(this);
|
var pluginGetStringLiteralsResult = PluginHooks.GetStringLiterals(this);
|
||||||
if (pluginGetStringLiteralsResult.IsHandled)
|
if (pluginGetStringLiteralsResult.FullyProcessed)
|
||||||
StringLiterals = pluginGetStringLiteralsResult.StringLiterals.ToArray();
|
StringLiterals = pluginGetStringLiteralsResult.StringLiterals.ToArray();
|
||||||
|
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
using NoisyCowStudios.Bin2Object;
|
using NoisyCowStudios.Bin2Object;
|
||||||
using Il2CppInspector.Reflection;
|
using Il2CppInspector.Reflection;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Il2CppInspector.PluginAPI.V100
|
namespace Il2CppInspector.PluginAPI.V100
|
||||||
{
|
{
|
||||||
@@ -16,6 +17,11 @@ namespace Il2CppInspector.PluginAPI.V100
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ILoadPipeline
|
public interface ILoadPipeline
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A new load task is about to start. Perform per-load initialization here
|
||||||
|
/// </summary>
|
||||||
|
void LoadPipelineStarting(PluginLoadPipelineStartingEventInfo info) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Process global-metadata.dat when it is first opened as a sequence of bytes
|
/// Process global-metadata.dat when it is first opened as a sequence of bytes
|
||||||
/// Seek cursor will be at the start of the file
|
/// Seek cursor will be at the start of the file
|
||||||
@@ -42,6 +48,13 @@ namespace Il2CppInspector.PluginAPI.V100
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
void PostProcessPackage(Il2CppInspector package, PluginPostProcessPackageEventInfo data) { }
|
void PostProcessPackage(Il2CppInspector package, PluginPostProcessPackageEventInfo data) { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The current load task has finished. Perform per-load teardown code here
|
||||||
|
/// One Il2CppInspector per sub-image in the binary is supplied
|
||||||
|
/// We have closed all open files but the .NET type model has not been created yet
|
||||||
|
/// </summary>
|
||||||
|
void LoadPipelineEnding(List<Il2CppInspector> packages, PluginLoadPipelineEndingEventInfo info) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Post-process the .NET type model to make changes after it has been fully created
|
/// Post-process the .NET type model to make changes after it has been fully created
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace Il2CppInspector.PluginAPI.V100
|
|||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Object which allows plugins to report on what has happened during a call
|
/// Object which allows plugins to report on what has happened during a call
|
||||||
/// Changes made to this object propagate to the next plugin in the call chain until IsHandled is set to true
|
/// Changes made to this object propagate to the next plugin in the call chain until FullyProcessed is set to true
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class PluginEventInfo
|
public class PluginEventInfo
|
||||||
{
|
{
|
||||||
@@ -21,25 +21,25 @@ namespace Il2CppInspector.PluginAPI.V100
|
|||||||
/// Generally, this will prevent other plugins from processing the data
|
/// Generally, this will prevent other plugins from processing the data
|
||||||
/// Note that this should be set even if the processed data was invalid (<seealso cref="IsInvalid"/>)
|
/// Note that this should be set even if the processed data was invalid (<seealso cref="IsInvalid"/>)
|
||||||
/// If this is not set, the same event will be raised on the next available plugin
|
/// If this is not set, the same event will be raised on the next available plugin
|
||||||
/// Note that you can still do processing but set IsHandled to false to allow additional processing from other plugins
|
/// Note that you can still do processing but set FullyProcessed to false to allow additional processing from other plugins
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsHandled { get; set; } = false;
|
public bool FullyProcessed { get; set; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A plugin should set this when IsHandled = true but the data it processed was invalid, for example if the processing gave an unexpected result
|
/// A plugin should set this when the data it processed was invalid, for example if the processing gave an unexpected result
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsInvalid { get; set; } = false;
|
public bool IsInvalid { get; set; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A plugin should set this when it has directly modified the provided data structure (object)
|
/// A plugin should set this when it has directly modified the provided data structure (object)
|
||||||
/// This can be set even if IsHandled = false to indicate that changes have been made but more plugins can still be called
|
/// This can be set even if FullyProcessed = false to indicate that changes have been made but more plugins can still be called
|
||||||
/// Should be set to false if you have only queried (performed reads) on the data without changing it
|
/// Should be set to false if you have only queried (performed reads) on the data without changing it
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsDataModified { get; set; } = false;
|
public bool IsDataModified { get; set; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A plugin should set this when it has directly modified the supplied or underlying stream for the metadata or binary
|
/// A plugin should set this when it has directly modified the supplied or underlying stream for the metadata or binary
|
||||||
/// This can be set even if IsHandled = false to indicate that changes have been made but more plugins can still be called
|
/// This can be set even if FullyProcessed = false to indicate that changes have been made but more plugins can still be called
|
||||||
/// Should be set to false if you have only queried (performed reads) on the stream without changing it
|
/// Should be set to false if you have only queried (performed reads) on the stream without changing it
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsStreamModified { get; set; } = false;
|
public bool IsStreamModified { get; set; } = false;
|
||||||
@@ -50,6 +50,11 @@ namespace Il2CppInspector.PluginAPI.V100
|
|||||||
public PluginErrorEventArgs Error { get; set; } = null;
|
public PluginErrorEventArgs Error { get; set; } = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event info for LoadPipelineStarting
|
||||||
|
/// </summary>
|
||||||
|
public class PluginLoadPipelineStartingEventInfo : PluginEventInfo { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event info for PreProcessMetadata
|
/// Event info for PreProcessMetadata
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -102,4 +107,9 @@ namespace Il2CppInspector.PluginAPI.V100
|
|||||||
/// Event info for PostProcessTypeModel
|
/// Event info for PostProcessTypeModel
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class PluginPostProcessTypeModelEventInfo : PluginEventInfo { }
|
public class PluginPostProcessTypeModelEventInfo : PluginEventInfo { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event info for LoadPipelineEnding
|
||||||
|
/// </summary>
|
||||||
|
public class PluginLoadPipelineEndingEventInfo : PluginEventInfo { }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
All rights reserved.
|
All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using Il2CppInspector.Reflection;
|
using Il2CppInspector.Reflection;
|
||||||
using NoisyCowStudios.Bin2Object;
|
using NoisyCowStudios.Bin2Object;
|
||||||
|
|
||||||
@@ -16,6 +17,9 @@ namespace Il2CppInspector
|
|||||||
// Does not include hooks that should be called individually, eg. OptionsChanged
|
// Does not include hooks that should be called individually, eg. OptionsChanged
|
||||||
internal static class PluginHooks
|
internal static class PluginHooks
|
||||||
{
|
{
|
||||||
|
public static PluginLoadPipelineStartingEventInfo LoadPipelineStarting()
|
||||||
|
=> PluginManager.Try<ILoadPipeline, PluginLoadPipelineStartingEventInfo>((p, e) => p.LoadPipelineStarting(e));
|
||||||
|
|
||||||
public static PluginPreProcessMetadataEventInfo PreProcessMetadata(BinaryObjectStream stream)
|
public static PluginPreProcessMetadataEventInfo PreProcessMetadata(BinaryObjectStream stream)
|
||||||
=> PluginManager.Try<ILoadPipeline, PluginPreProcessMetadataEventInfo>((p, e) => {
|
=> PluginManager.Try<ILoadPipeline, PluginPreProcessMetadataEventInfo>((p, e) => {
|
||||||
stream.Position = 0;
|
stream.Position = 0;
|
||||||
@@ -34,8 +38,10 @@ namespace Il2CppInspector
|
|||||||
public static PluginPostProcessPackageEventInfo PostProcessPackage(Il2CppInspector package)
|
public static PluginPostProcessPackageEventInfo PostProcessPackage(Il2CppInspector package)
|
||||||
=> PluginManager.Try<ILoadPipeline, PluginPostProcessPackageEventInfo>((p, e) => p.PostProcessPackage(package, e));
|
=> PluginManager.Try<ILoadPipeline, PluginPostProcessPackageEventInfo>((p, e) => p.PostProcessPackage(package, e));
|
||||||
|
|
||||||
|
public static PluginLoadPipelineEndingEventInfo LoadPipelineEnding(List<Il2CppInspector> packages)
|
||||||
|
=> PluginManager.Try<ILoadPipeline, PluginLoadPipelineEndingEventInfo>((p, e) => p.LoadPipelineEnding(packages, e));
|
||||||
|
|
||||||
public static PluginPostProcessTypeModelEventInfo PostProcessTypeModel(TypeModel typeModel)
|
public static PluginPostProcessTypeModelEventInfo PostProcessTypeModel(TypeModel typeModel)
|
||||||
=> PluginManager.Try<ILoadPipeline, PluginPostProcessTypeModelEventInfo>((p, e) => p.PostProcessTypeModel(typeModel, e));
|
=> PluginManager.Try<ILoadPipeline, PluginPostProcessTypeModelEventInfo>((p, e) => p.PostProcessTypeModel(typeModel, e));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -258,7 +258,7 @@ namespace Il2CppInspector
|
|||||||
try {
|
try {
|
||||||
action(p, eventInfo);
|
action(p, eventInfo);
|
||||||
|
|
||||||
if (eventInfo.IsHandled)
|
if (eventInfo.FullyProcessed)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ namespace Il2CppInspectorGUI
|
|||||||
MessageBox.Show("Could not update plugin options. " + e.Error.Exception.Message, "Plugin error");
|
MessageBox.Show("Could not update plugin options. " + e.Error.Exception.Message, "Plugin error");
|
||||||
else
|
else
|
||||||
MessageBox.Show($"The plugin {e.Error.Plugin.Name} encountered an error while executing {e.Error.Operation}: {e.Error.Exception.Message}."
|
MessageBox.Show($"The plugin {e.Error.Plugin.Name} encountered an error while executing {e.Error.Operation}: {e.Error.Exception.Message}."
|
||||||
+ Environment.NewLine + Environment.NewLine + "The application will continue but may not behave as expected.", "Plugin error");
|
+ Environment.NewLine + Environment.NewLine + "Plugin has been disabled.", "Plugin error");
|
||||||
};
|
};
|
||||||
|
|
||||||
PluginManager.StatusHandler += (s, e) => StatusUpdate(e.Plugin, "[" + e.Plugin.Name + "]\n" + e.Text);
|
PluginManager.StatusHandler += (s, e) => StatusUpdate(e.Plugin, "[" + e.Plugin.Name + "]\n" + e.Text);
|
||||||
@@ -163,27 +163,20 @@ namespace Il2CppInspectorGUI
|
|||||||
throw new InvalidOperationException("Could not find any binary images in the file");
|
throw new InvalidOperationException("Could not find any binary images in the file");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multi-image binaries may contain more than one Il2Cpp image
|
// Get an Il2CppInspector for each image
|
||||||
AppModels.Clear();
|
var inspectors = Inspector.LoadFromStream(stream, metadata, StatusUpdate);
|
||||||
foreach (var image in stream.Images) {
|
|
||||||
// Architecture-agnostic load attempt
|
|
||||||
try {
|
|
||||||
// If we can't load the IL2CPP data here, it's probably packed or obfuscated; ignore it
|
|
||||||
if (Il2CppBinary.Load(image, metadata, StatusUpdate) is Il2CppBinary binary) {
|
|
||||||
var inspector = new Inspector(binary, metadata);
|
|
||||||
|
|
||||||
|
AppModels.Clear();
|
||||||
|
|
||||||
|
foreach (var inspector in inspectors) {
|
||||||
// Build type model
|
// Build type model
|
||||||
OnStatusUpdate?.Invoke(this, $"Building .NET type model for {image.Format}/{image.Arch} image");
|
OnStatusUpdate?.Invoke(this, $"Building .NET type model for {inspector.BinaryImage.Format}/{inspector.BinaryImage.Arch} image");
|
||||||
var typeModel = new TypeModel(inspector);
|
var typeModel = new TypeModel(inspector);
|
||||||
|
|
||||||
// Initialize (but don't build) application model
|
// Initialize (but don't build) application model
|
||||||
// We will build the model after the user confirms the Unity version and target compiler
|
// We will build the model after the user confirms the Unity version and target compiler
|
||||||
AppModels.Add(new AppModel(typeModel, makeDefaultBuild: false));
|
AppModels.Add(new AppModel(typeModel, makeDefaultBuild: false));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Unsupported architecture; ignore it
|
|
||||||
catch (NotImplementedException) { }
|
|
||||||
}
|
|
||||||
if (!AppModels.Any()) {
|
if (!AppModels.Any()) {
|
||||||
throw new InvalidOperationException("Could not auto-detect any IL2CPP binary images in the file. This may mean the binary file is packed, encrypted or obfuscated, that the file is not an IL2CPP image or that Il2CppInspector was not able to automatically find the required data. Please check the binary file in a disassembler to ensure that it is an unencrypted IL2CPP binary before submitting a bug report!");
|
throw new InvalidOperationException("Could not auto-detect any IL2CPP binary images in the file. This may mean the binary file is packed, encrypted or obfuscated, that the file is not an IL2CPP image or that Il2CppInspector was not able to automatically find the required data. Please check the binary file in a disassembler to ensure that it is an unencrypted IL2CPP binary before submitting a bug report!");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user