Remove LibcFunction service (#1787)

This commit is contained in:
Haselnussbomber 2024-04-23 00:18:47 +02:00 committed by GitHub
parent bd2c9b2258
commit 51c2f77812
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 0 additions and 294 deletions

View file

@ -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);
}
}

View file

@ -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");
}
}

View file

@ -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;
}
}

View file

@ -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),
};
}
}
}

View file

@ -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);
}