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