mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
Remove LibcFunction service (#1787)
This commit is contained in:
parent
bd2c9b2258
commit
51c2f77812
5 changed files with 0 additions and 294 deletions
|
|
@ -1,72 +0,0 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
using Dalamud.IoC;
|
||||
using Dalamud.IoC.Internal;
|
||||
using Dalamud.Plugin.Services;
|
||||
|
||||
namespace Dalamud.Game.Libc;
|
||||
|
||||
/// <summary>
|
||||
/// This class handles creating cstrings utilizing native game methods.
|
||||
/// </summary>
|
||||
[PluginInterface]
|
||||
[InterfaceVersion("1.0")]
|
||||
[ServiceManager.EarlyLoadedService]
|
||||
#pragma warning disable SA1015
|
||||
[ResolveVia<ILibcFunction>]
|
||||
#pragma warning restore SA1015
|
||||
internal sealed class LibcFunction : IServiceType, ILibcFunction
|
||||
{
|
||||
private readonly LibcFunctionAddressResolver address;
|
||||
private readonly StdStringFromCStringDelegate stdStringCtorCString;
|
||||
private readonly StdStringDeallocateDelegate stdStringDeallocate;
|
||||
|
||||
[ServiceManager.ServiceConstructor]
|
||||
private LibcFunction(TargetSigScanner sigScanner)
|
||||
{
|
||||
this.address = new LibcFunctionAddressResolver();
|
||||
this.address.Setup(sigScanner);
|
||||
|
||||
this.stdStringCtorCString = Marshal.GetDelegateForFunctionPointer<StdStringFromCStringDelegate>(this.address.StdStringFromCstring);
|
||||
this.stdStringDeallocate = Marshal.GetDelegateForFunctionPointer<StdStringDeallocateDelegate>(this.address.StdStringDeallocate);
|
||||
}
|
||||
|
||||
// TODO: prolly callconv is not okay in x86
|
||||
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
|
||||
private delegate IntPtr StdStringFromCStringDelegate(IntPtr pStdString, [MarshalAs(UnmanagedType.LPArray)] byte[] content, IntPtr size);
|
||||
|
||||
// TODO: prolly callconv is not okay in x86
|
||||
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
|
||||
private delegate IntPtr StdStringDeallocateDelegate(IntPtr address);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public OwnedStdString NewString(byte[] content)
|
||||
{
|
||||
// While 0x70 bytes in the memory should be enough in DX11 version,
|
||||
// I don't trust my analysis so we're just going to allocate almost two times more than that.
|
||||
var pString = Marshal.AllocHGlobal(256);
|
||||
|
||||
// Initialize a string
|
||||
var size = new IntPtr(content.Length);
|
||||
var pReallocString = this.stdStringCtorCString(pString, content, size);
|
||||
|
||||
// Log.Verbose("Prev: {Prev} Now: {Now}", pString, pReallocString);
|
||||
|
||||
return new OwnedStdString(pReallocString, this.DeallocateStdString);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public OwnedStdString NewString(string content, Encoding? encoding = null)
|
||||
{
|
||||
encoding ??= Encoding.UTF8;
|
||||
|
||||
return this.NewString(encoding.GetBytes(content));
|
||||
}
|
||||
|
||||
private void DeallocateStdString(IntPtr address)
|
||||
{
|
||||
this.stdStringDeallocate(address);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace Dalamud.Game.Libc;
|
||||
|
||||
/// <summary>
|
||||
/// The address resolver for the <see cref="LibcFunction"/> class.
|
||||
/// </summary>
|
||||
internal sealed class LibcFunctionAddressResolver : BaseAddressResolver
|
||||
{
|
||||
private delegate IntPtr StringFromCString();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the address of the native StdStringFromCstring method.
|
||||
/// </summary>
|
||||
public IntPtr StdStringFromCstring { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the address of the native StdStringDeallocate method.
|
||||
/// </summary>
|
||||
public IntPtr StdStringDeallocate { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Setup64Bit(ISigScanner sig)
|
||||
{
|
||||
this.StdStringFromCstring = sig.ScanText("48 89 5C 24 08 48 89 74 24 10 57 48 83 EC 20 48 8D 41 22 66 C7 41 20 01 01 48 89 01 49 8B D8");
|
||||
this.StdStringDeallocate = sig.ScanText("80 79 21 00 75 12 48 8B 51 08 41 B8 33 00 00 00 48 8B 09 E9 ?? ?? ?? 00 C3");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Dalamud.Game.Libc;
|
||||
|
||||
/// <summary>
|
||||
/// An address wrapper around the <see cref="StdString"/> class.
|
||||
/// </summary>
|
||||
public sealed partial class OwnedStdString
|
||||
{
|
||||
private readonly DeallocatorDelegate dealloc;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OwnedStdString"/> class.
|
||||
/// Construct a wrapper around std::string.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Violating any of these might cause an undefined hehaviour.
|
||||
/// 1. This function takes the ownership of the address.
|
||||
/// 2. A memory pointed by address argument is assumed to be allocated by Marshal.AllocHGlobal thus will try to call Marshal.FreeHGlobal on the address.
|
||||
/// 3. std::string object pointed by address must be initialized before calling this function.
|
||||
/// </remarks>
|
||||
/// <param name="address">The address of the owned std string.</param>
|
||||
/// <param name="dealloc">A deallocator function.</param>
|
||||
internal OwnedStdString(IntPtr address, DeallocatorDelegate dealloc)
|
||||
{
|
||||
this.Address = address;
|
||||
this.dealloc = dealloc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The delegate type that deallocates a std string.
|
||||
/// </summary>
|
||||
/// <param name="address">Address to deallocate.</param>
|
||||
internal delegate void DeallocatorDelegate(IntPtr address);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the address of the std string.
|
||||
/// </summary>
|
||||
public IntPtr Address { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Read the wrapped StdString.
|
||||
/// </summary>
|
||||
/// <returns>The StdString.</returns>
|
||||
public StdString Read() => StdString.ReadFromPointer(this.Address);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements IDisposable.
|
||||
/// </summary>
|
||||
public sealed partial class OwnedStdString : IDisposable
|
||||
{
|
||||
private bool isDisposed;
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="OwnedStdString"/> class.
|
||||
/// </summary>
|
||||
~OwnedStdString() => this.Dispose(false);
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of managed and unmanaged resources.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
this.Dispose(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of managed and unmanaged resources.
|
||||
/// </summary>
|
||||
/// <param name="disposing">A value indicating whether this was called via Dispose or finalized.</param>
|
||||
public void Dispose(bool disposing)
|
||||
{
|
||||
if (this.isDisposed)
|
||||
return;
|
||||
|
||||
this.isDisposed = true;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
|
||||
if (this.Address == IntPtr.Zero)
|
||||
{
|
||||
// Something got seriously fucked.
|
||||
throw new AccessViolationException();
|
||||
}
|
||||
|
||||
// Deallocate inner string first
|
||||
this.dealloc(this.Address);
|
||||
|
||||
// Free the heap
|
||||
Marshal.FreeHGlobal(this.Address);
|
||||
|
||||
// Better safe (running on a nullptr) than sorry. (running on a dangling pointer)
|
||||
this.Address = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Dalamud.Game.Libc;
|
||||
|
||||
/// <summary>
|
||||
/// Interation with std::string.
|
||||
/// </summary>
|
||||
public class StdString
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StdString"/> class.
|
||||
/// </summary>
|
||||
private StdString()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the cstring.
|
||||
/// </summary>
|
||||
public string Value { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the raw byte representation of the cstring.
|
||||
/// </summary>
|
||||
public byte[] RawData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Marshal a null terminated cstring from memory to a UTF-8 encoded string.
|
||||
/// </summary>
|
||||
/// <param name="cstring">Address of the cstring.</param>
|
||||
/// <returns>A UTF-8 encoded string.</returns>
|
||||
public static StdString ReadFromPointer(IntPtr cstring)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
if (cstring == IntPtr.Zero)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(cstring));
|
||||
}
|
||||
|
||||
var innerAddress = Marshal.ReadIntPtr(cstring);
|
||||
if (innerAddress == IntPtr.Zero)
|
||||
{
|
||||
throw new NullReferenceException("Inner reference to the cstring is null.");
|
||||
}
|
||||
|
||||
// Count the number of chars. String is assumed to be zero-terminated.
|
||||
|
||||
var count = 0;
|
||||
while (Marshal.ReadByte(innerAddress, count) != 0)
|
||||
{
|
||||
count += 1;
|
||||
}
|
||||
|
||||
// raw copy, as UTF8 string conversion is lossy
|
||||
var rawData = new byte[count];
|
||||
Marshal.Copy(innerAddress, rawData, 0, count);
|
||||
|
||||
return new StdString
|
||||
{
|
||||
RawData = rawData,
|
||||
Value = Encoding.UTF8.GetString(rawData),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
using System.Text;
|
||||
|
||||
using Dalamud.Game.Libc;
|
||||
|
||||
namespace Dalamud.Plugin.Services;
|
||||
|
||||
/// <summary>
|
||||
/// This class handles creating cstrings utilizing native game methods.
|
||||
/// </summary>
|
||||
public interface ILibcFunction
|
||||
{
|
||||
/// <summary>
|
||||
/// Create a new string from the given bytes.
|
||||
/// </summary>
|
||||
/// <param name="content">The bytes to convert.</param>
|
||||
/// <returns>An owned std string object.</returns>
|
||||
public OwnedStdString NewString(byte[] content);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new string form the given bytes.
|
||||
/// </summary>
|
||||
/// <param name="content">The bytes to convert.</param>
|
||||
/// <param name="encoding">A non-default encoding.</param>
|
||||
/// <returns>An owned std string object.</returns>
|
||||
public OwnedStdString NewString(string content, Encoding? encoding = null);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue