-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNativePatchUtils.cs
More file actions
76 lines (66 loc) · 3.06 KB
/
NativePatchUtils.cs
File metadata and controls
76 lines (66 loc) · 3.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Harmony;
using MelonLoader;
using UnhollowerBaseLib;
namespace ReMod.BundleVerifier
{
internal static class NativePatchUtils
{
// ReSharper disable once CollectionNeverQueried.Local
private static readonly List<Delegate> ourPinnedDelegates = new();
private static readonly Dictionary<IntPtr, IntPtr> ourOriginalPointers = new();
internal static void NativePatch<T>(MethodInfo original, out T callOriginal, MethodInfo patch)
where T : MulticastDelegate
{
var patchDelegate = (T)Delegate.CreateDelegate(typeof(T), patch);
NativePatch(original, out callOriginal, patchDelegate);
}
internal static void NativePatch<T>(IntPtr originalPointer, out T callOriginal, MethodInfo patch, string? context = null)
where T : MulticastDelegate
{
var patchDelegate = (T)Delegate.CreateDelegate(typeof(T), patch);
NativePatch(originalPointer, out callOriginal, patchDelegate, context);
}
internal static unsafe void NativePatch<T>(MethodInfo original, out T callOriginal, T patchDelegate) where T : MulticastDelegate
{
if (original == null) throw new ArgumentNullException(nameof(original));
var originalPointer = *(IntPtr*)(IntPtr)UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(original).GetValue(null);
NativePatch(originalPointer, out callOriginal, patchDelegate, original.FullDescription());
}
internal static unsafe void NativePatch<T>(IntPtr originalPointer, out T callOriginal, T patchDelegate, string? context = null) where T : MulticastDelegate
{
ourPinnedDelegates.Add(patchDelegate);
var patchPointer = Marshal.GetFunctionPointerForDelegate(patchDelegate);
MelonUtils.NativeHookAttach((IntPtr)(&originalPointer), patchPointer);
if (ourOriginalPointers.ContainsKey(originalPointer))
MelonLogger.Warning($"Method {context ?? patchDelegate.Method.FullDescription()} has multiple native patches within single mod. Bug?");
ourOriginalPointers[originalPointer] = patchPointer;
callOriginal = Marshal.GetDelegateForFunctionPointer<T>(originalPointer);
}
internal static unsafe void UnpatchAll()
{
foreach (var keyValuePair in ourOriginalPointers)
{
var pointer = keyValuePair.Key;
MelonUtils.NativeHookDetach((IntPtr)(&pointer), keyValuePair.Value);
}
ourOriginalPointers.Clear();
ourPinnedDelegates.Clear();
}
[StructLayout(LayoutKind.Sequential)]
internal struct NativeString
{
public IntPtr Data;
public long Capacity;
public long Unknown;
public long Length;
public int Unknown2;
}
}
}