impr: Get rid of cimgui shared library by hooking pinvoke handler

This commit is contained in:
WerWolv
2024-03-12 23:17:49 +01:00
parent 876f091244
commit fdf01dfb50
15 changed files with 135 additions and 57 deletions

View File

@@ -15,6 +15,8 @@
#include <nethost.h>
#include <coreclr_delegates.h>
#include <hostfxr.h>
#include <imgui.h>
#include <hex/api/plugin_manager.hpp>
#include <hex/helpers/fs.hpp>
#include <wolv/io/fs.hpp>
@@ -22,6 +24,9 @@
#include <wolv/utils/string.hpp>
#include <hex/helpers/fmt.hpp>
#include <hex/helpers/logger.hpp>
#include <hex/helpers/utils.hpp>
extern "C" void igSetCurrentContext(ImGuiContext* ctx);
namespace hex::script::loader {
@@ -64,6 +69,20 @@ namespace hex::script::loader {
hostfxr_initialize_for_runtime_config_fn hostfxr_initialize_for_runtime_config = nullptr;
hostfxr_get_runtime_delegate_fn hostfxr_get_runtime_delegate = nullptr;
hostfxr_close_fn hostfxr_close = nullptr;
hostfxr_set_runtime_property_value_fn hostfxr_set_runtime_property_value = nullptr;
hostfxr_set_error_writer_fn hostfxr_set_error_writer = nullptr;
void* pInvokeOverride(const char *libraryName, const char *symbolName) {
auto library = std::string_view(libraryName);
if (library == "cimgui") {
return getExport<void*>(ImHexApi::System::getLibImHexModuleHandle(), symbolName);
} else if (library == "ImHex") {
auto address = getExport<void*>(hex::getContainingModule((void*)&pInvokeOverride), symbolName);
return address;
}
return nullptr;
}
bool loadHostfxr() {
#if defined(OS_WINDOWS)
@@ -108,13 +127,26 @@ namespace hex::script::loader {
= getExport<hostfxr_get_runtime_delegate_fn>(hostfxrLibrary, "hostfxr_get_runtime_delegate");
hostfxr_close
= getExport<hostfxr_close_fn>(hostfxrLibrary, "hostfxr_close");
hostfxr_set_runtime_property_value
= getExport<hostfxr_set_runtime_property_value_fn>(hostfxrLibrary, "hostfxr_set_runtime_property_value");
hostfxr_set_error_writer
= getExport<hostfxr_set_error_writer_fn>(hostfxrLibrary, "hostfxr_set_error_writer");
}
hostfxr_set_error_writer([] HOSTFXR_CALLTYPE (const char_t *message) {
if constexpr (std::same_as<char_t, wchar_t>) {
log::error("{}", utf16ToUtf8(message));
} else {
log::error("{}", message);
}
});
return
hostfxr_initialize_for_runtime_config != nullptr &&
hostfxr_get_runtime_delegate != nullptr &&
hostfxr_close != nullptr;
hostfxr_close != nullptr &&
hostfxr_set_runtime_property_value != nullptr &&
hostfxr_set_error_writer != nullptr;
}
load_assembly_and_get_function_pointer_fn getLoadAssemblyFunction(const std::fs::path &path) {
@@ -131,6 +163,8 @@ namespace hex::script::loader {
throw std::runtime_error(hex::format("Failed to initialize command line {:X}", result));
}
hostfxr_set_runtime_property_value(ctx, STRING("PINVOKE_OVERRIDE"), utf8ToUtf16(hex::format("{}", (void*)pInvokeOverride)).c_str());
result = hostfxr_get_runtime_delegate(
ctx,
hostfxr_delegate_type::hdt_load_assembly_and_get_function_pointer,
@@ -237,4 +271,4 @@ namespace hex::script::loader {
return true;
}
}
}

View File

@@ -6,10 +6,10 @@ using System.Text;
namespace ImHex
{
public class Bookmarks
public partial class Bookmarks
{
[DllImport(Library.Name)]
private static extern void createBookmarkV1(UInt64 address, UInt64 size, UInt32 color, byte[] name, byte[] description);
[LibraryImport("ImHex")]
private static partial void createBookmarkV1(UInt64 address, UInt64 size, UInt32 color, byte[] name, byte[] description);
public static void CreateBookmark(long address, long size, Color color, string name = "", string description = "")
{

View File

@@ -1,7 +0,0 @@
namespace ImHex
{
public static class Library
{
public const string Name = "script_loader.hexplug";
}
}

View File

@@ -1,6 +1,5 @@
#pragma warning disable SYSLIB1054
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text;
@@ -34,7 +33,7 @@ namespace ImHex
string getTypeName();
string getName();
}
public class Memory
public partial class Memory
{
private static List<IProvider> _registeredProviders = new();
private static List<Delegate> _registeredDelegates = new();
@@ -42,17 +41,17 @@ namespace ImHex
private delegate void DataAccessDelegate(UInt64 address, IntPtr buffer, UInt64 size);
private delegate UInt64 GetSizeDelegate();
[DllImport(Library.Name)]
private static extern void readMemoryV1(UInt64 address, UInt64 size, IntPtr buffer);
[LibraryImport("ImHex")]
private static partial void readMemoryV1(UInt64 address, UInt64 size, IntPtr buffer);
[DllImport(Library.Name)]
private static extern void writeMemoryV1(UInt64 address, UInt64 size, IntPtr buffer);
[LibraryImport("ImHex")]
private static partial void writeMemoryV1(UInt64 address, UInt64 size, IntPtr buffer);
[DllImport(Library.Name)]
private static extern bool getSelectionV1(IntPtr start, IntPtr end);
[LibraryImport("ImHex")]
private static partial int getSelectionV1(IntPtr start, IntPtr end);
[DllImport(Library.Name)]
private static extern void registerProviderV1(byte[] typeName, byte[] name, IntPtr readFunction, IntPtr writeFunction, IntPtr getSizeFunction);
[LibraryImport("ImHex")]
private static partial void registerProviderV1(byte[] typeName, byte[] name, IntPtr readFunction, IntPtr writeFunction, IntPtr getSizeFunction);
public static byte[] Read(ulong address, ulong size)
@@ -87,7 +86,7 @@ namespace ImHex
unsafe
{
UInt64 start = 0, end = 0;
if (!getSelectionV1((nint)(&start), (nint)(&end)))
if (getSelectionV1((nint)(&start), (nint)(&end)) == 0)
{
return null;
}

View File

@@ -1,33 +1,31 @@
#pragma warning disable SYSLIB1054
using System.Runtime.InteropServices;
using System.Runtime.InteropServices;
using System.Text;
namespace ImHex
{
public class UI
public partial class UI
{
private delegate void DrawContentDelegate();
private static List<Delegate> _registeredDelegates = new();
[DllImport(Library.Name)]
private static extern void showMessageBoxV1(byte[] message);
[LibraryImport("ImHex")]
private static partial void showMessageBoxV1(byte[] message);
[DllImport(Library.Name)]
private static extern void showInputTextBoxV1(byte[] title, byte[] message, StringBuilder buffer, int bufferSize);
[LibraryImport("ImHex")]
private static unsafe partial void showInputTextBoxV1(byte[] title, byte[] message, IntPtr buffer, int bufferSize);
[DllImport(Library.Name)]
private static extern unsafe void showYesNoQuestionBoxV1(byte[] title, byte[] message, bool* result);
[LibraryImport("ImHex")]
private static unsafe partial void showYesNoQuestionBoxV1(byte[] title, byte[] message, bool* result);
[DllImport(Library.Name)]
private static extern void showToastV1(byte[] message, UInt32 type);
[LibraryImport("ImHex")]
private static partial void showToastV1(byte[] message, UInt32 type);
[DllImport(Library.Name)]
private static extern IntPtr getImGuiContextV1();
[LibraryImport("ImHex")]
private static partial IntPtr getImGuiContextV1();
[DllImport(Library.Name)]
private static extern void registerViewV1(byte[] icon, byte[] name, IntPtr drawFunction);
[LibraryImport("ImHex")]
private static partial void registerViewV1(byte[] icon, byte[] name, IntPtr drawFunction);
public static void ShowMessageBox(string message)
{
@@ -46,13 +44,22 @@ namespace ImHex
public static string? ShowInputTextBox(string title, string message, int maxSize)
{
StringBuilder buffer = new(maxSize);
showInputTextBoxV1(Encoding.UTF8.GetBytes(title), Encoding.UTF8.GetBytes(message), buffer, buffer.Capacity);
unsafe
{
var buffer = new byte[maxSize];
GCHandle pinnedArray = GCHandle.Alloc(buffer, GCHandleType.Pinned);
showInputTextBoxV1(Encoding.UTF8.GetBytes(title), Encoding.UTF8.GetBytes(message), pinnedArray.AddrOfPinnedObject(), maxSize);
pinnedArray.Free();
if (buffer.Length == 0 || buffer[0] == '\x00')
return null;
else
return buffer.ToString();
if (buffer.Length == 0 || buffer[0] == '\x00')
{
return null;
}
else
{
return Encoding.UTF8.GetString(buffer);
}
}
}
public enum ToastType

View File

@@ -1,8 +1,18 @@
using ImHex;
using ImGuiNET;
class Script {
public static void OnLoad() {
// This function is executed the first time the Plugin is loaded
UI.RegisterView(new byte[]{ 0xEE, 0xAC, 0x89 }, "Test View", () =>
{
ImGui.SetCurrentContext(UI.GetImGuiContext());
ImGui.TextUnformatted("Test Text");
if (ImGui.Button("Hello World"))
{
UI.ShowToast("Hello World");
}
});
}
public static void Main()