Compare commits

..

1 Commits

Author SHA1 Message Date
defnotken
5cee5e0fbe maybe? 2026-01-20 14:30:47 -06:00
4 changed files with 114 additions and 89 deletions

View File

@@ -127,7 +127,7 @@ public class PlayerDataFactory
{
nint basePtr = playerPointer;
if (!PtrGuard.LooksLikePtr(basePtr, _dalamudUtil.IsWine))
if (!PtrGuard.LooksLikePtr(basePtr))
return true;
nint drawObjAddr = basePtr + _drawObjectOffset;
@@ -135,10 +135,10 @@ public class PlayerDataFactory
if (!PtrGuard.IsReadable(drawObjAddr, (nuint)IntPtr.Size))
return true;
if (!PtrGuard.TryReadIntPtr(drawObjAddr, _dalamudUtil.IsWine, out var drawObj))
if (!PtrGuard.TryReadIntPtr(drawObjAddr, out var drawObj))
return true;
if (drawObj != 0 && !PtrGuard.LooksLikePtr(drawObj, _dalamudUtil.IsWine))
if (drawObj != 0 && !PtrGuard.LooksLikePtr(drawObj))
return true;
return drawObj == 0;

View File

@@ -173,6 +173,8 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase, IHighP
private void CheckAndUpdateObject() => CheckAndUpdateObject(allowPublish: true);
private unsafe void CheckAndUpdateObject(bool allowPublish)
{
try
{
var prevAddr = Address;
var prevDrawObj = DrawObjectAddress;
@@ -180,7 +182,7 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase, IHighP
var nextAddr = _getAddress();
if (nextAddr != IntPtr.Zero && !PtrGuard.LooksLikePtr(nextAddr, _dalamudUtil.IsWine))
if (nextAddr != IntPtr.Zero && !PtrGuard.LooksLikePtr(nextAddr))
{
nextAddr = IntPtr.Zero;
}
@@ -199,7 +201,7 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase, IHighP
var draw = (nint)gameObject->DrawObject;
if (!PtrGuard.LooksLikePtr(draw, _dalamudUtil.IsWine) || !PtrGuard.IsReadable(draw, (nuint)sizeof(DrawObject)))
if (!PtrGuard.LooksLikePtr(draw) || !PtrGuard.IsReadable(draw, (nuint)sizeof(DrawObject)))
draw = 0;
DrawObjectAddress = draw;
@@ -229,10 +231,28 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase, IHighP
bool drawObjDiff = DrawObjectAddress != prevDrawObj;
bool addrDiff = Address != prevAddr;
if (Address != IntPtr.Zero && DrawObjectAddress != IntPtr.Zero
&& PtrGuard.IsReadable(Address, (nuint)sizeof(Character))
&& PtrGuard.IsReadable(DrawObjectAddress, (nuint)sizeof(DrawObject)))
if (Address == IntPtr.Zero || DrawObjectAddress == IntPtr.Zero)
{
if (addrDiff || drawObjDiff)
{
CurrentDrawCondition = DrawCondition.DrawObjectZero;
Logger.LogTrace("[{this}] Changed", this);
if (_isOwnedObject && ObjectKind != ObjectKind.Player)
Mediator.Publish(new ClearCacheForObjectMessage(this));
}
return;
}
if (!PtrGuard.IsReadable(Address, (nuint)sizeof(Character)) ||
!PtrGuard.IsReadable(DrawObjectAddress, (nuint)sizeof(DrawObject)))
{
Logger.LogTrace("[{this}] Pointers became invalid during update", this);
Address = IntPtr.Zero;
DrawObjectAddress = IntPtr.Zero;
CurrentDrawCondition = DrawCondition.DrawObjectZero;
return;
}
var chara = (Character*)Address;
var drawObj = (DrawObject*)DrawObjectAddress;
@@ -315,12 +335,11 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase, IHighP
Mediator.Publish(new CreateCacheForObjectMessage(this));
}
}
else if (addrDiff || drawObjDiff)
catch (Exception ex)
{
Address = IntPtr.Zero;
DrawObjectAddress = IntPtr.Zero;
CurrentDrawCondition = DrawCondition.DrawObjectZero;
Logger.LogTrace("[{this}] Changed", this);
if (_isOwnedObject && ObjectKind != ObjectKind.Player)
Mediator.Publish(new ClearCacheForObjectMessage(this));
}
}
@@ -361,7 +380,7 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase, IHighP
private unsafe bool CompareAndUpdateMainHand(Weapon* weapon)
{
var p = (nint)weapon;
if (!PtrGuard.LooksLikePtr(p, _dalamudUtil.IsWine) || !PtrGuard.IsReadable(p, (nuint)sizeof(Weapon)))
if (!PtrGuard.LooksLikePtr(p) || !PtrGuard.IsReadable(p, (nuint)sizeof(Weapon)))
return false;
bool hasChanges = false;
@@ -377,7 +396,7 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase, IHighP
private unsafe bool CompareAndUpdateOffHand(Weapon* weapon)
{
var p = (nint)weapon;
if (!PtrGuard.LooksLikePtr(p, _dalamudUtil.IsWine) || !PtrGuard.IsReadable(p, (nuint)sizeof(Weapon)))
if (!PtrGuard.LooksLikePtr(p) || !PtrGuard.IsReadable(p, (nuint)sizeof(Weapon)))
return false;
bool hasChanges = false;
@@ -443,11 +462,18 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase, IHighP
{
if (Address == IntPtr.Zero) return DrawCondition.ObjectZero;
if (DrawObjectAddress == IntPtr.Zero) return DrawCondition.DrawObjectZero;
if (!PtrGuard.IsReadable(Address, (nuint)sizeof(FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject)))
return DrawCondition.ObjectZero;
var visibilityFlags = ((FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)Address)->RenderFlags;
if (visibilityFlags != VisibilityFlags.None) return DrawCondition.RenderFlags;
if (ObjectKind == ObjectKind.Player)
{
if (!PtrGuard.IsReadable(DrawObjectAddress, (nuint)sizeof(CharacterBase)))
return DrawCondition.DrawObjectZero;
var modelInSlotLoaded = (((CharacterBase*)DrawObjectAddress)->HasModelInSlotLoaded != 0);
if (modelInSlotLoaded) return DrawCondition.ModelInSlotLoaded;
var modelFilesInSlotLoaded = (((CharacterBase*)DrawObjectAddress)->HasModelFilesInSlotLoaded != 0);

View File

@@ -5,41 +5,40 @@ namespace LightlessSync.Utils
{
public static partial class PtrGuard
{
private static readonly nuint _hardMinWindows =
(nuint)(IntPtr.Size == 8 ? 0x0000000100000000UL : 0x0000000000010000UL);
private static readonly nuint _hardMaxWindows =
(nuint)(IntPtr.Size == 8 ? 0x00007FFFFFFFFFFFUL : 0x7FFFFFFFUL);
private const nuint _alignmentPtr = 0x7;
private const ulong _aligmentPtr = 0x7UL;
private static readonly nuint _minAppAddr = (nuint)GetMinAppAddr();
private static readonly nuint _maxAppAddr = (nuint)GetMaxAppAddr();
private static readonly (nuint min, nuint max) _sysRange = GetSysRange();
private static (nuint min, nuint max) GetSysRange()
private static nint GetMinAppAddr()
{
GetSystemInfo(out var si);
return ((nuint)si.lpMinimumApplicationAddress, (nuint)si.lpMaximumApplicationAddress);
return si.lpMinimumApplicationAddress;
}
private static nuint GetMinAppAddr(bool isWine) => isWine ? _sysRange.min : _hardMinWindows;
private static nuint GetMaxAppAddr(bool isWine) => isWine ? _sysRange.max : _hardMaxWindows;
private static nint GetMaxAppAddr()
{
GetSystemInfo(out var si);
return si.lpMaximumApplicationAddress;
}
public static bool LooksLikePtr(nint p, bool isWine = false)
public static bool LooksLikePtr(nint p)
{
if (p == 0) return false;
nuint u = (nuint)p;
if (u < GetMinAppAddr(isWine)) return false;
if (u > GetMaxAppAddr(isWine)) return false;
if ((u & _alignmentPtr) != 0) return false;
if (u < _minAppAddr) return false;
if (u > _maxAppAddr) return false;
if ((u & _aligmentPtr) != 0) return false;
if ((uint)u == 0x12345679u) return false;
return true;
}
public static bool TryReadIntPtr(nint addr, bool isWine, out nint value)
public static bool TryReadIntPtr(nint addr, out nint value)
{
value = 0;
if (!LooksLikePtr(addr, isWine))
if (!LooksLikePtr(addr))
return false;
return ReadProcessMemory(GetCurrentProcess(), addr, out value, (nuint)IntPtr.Size, out nuint bytesRead)
@@ -50,7 +49,7 @@ namespace LightlessSync.Utils
{
if (addr == 0 || size == 0) return false;
if (VirtualQuery(addr, out var mbi, (nuint)Marshal.SizeOf<MemoryBasicInformation>()) == 0)
if (VirtualQuery(addr, out var mbi, (nuint)Marshal.SizeOf<MEMORY_BASIC_INFORMATION>()) == 0)
return false;
const uint Commit = 0x1000;

View File

@@ -5,7 +5,7 @@ namespace LightlessSync.Utils
internal static class PtrGuardMemory
{
[StructLayout(LayoutKind.Sequential)]
internal struct MemoryBasicInformation
internal struct MEMORY_BASIC_INFORMATION
{
public nint BaseAddress;
public nint AllocationBase;
@@ -19,7 +19,7 @@ namespace LightlessSync.Utils
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern nuint VirtualQuery(
nint lpAddress,
out MemoryBasicInformation lpBuffer,
out MEMORY_BASIC_INFORMATION lpBuffer,
nuint dwLength);
[DllImport("kernel32.dll", SetLastError = true)]
@@ -34,10 +34,10 @@ namespace LightlessSync.Utils
internal static extern nint GetCurrentProcess();
[DllImport("kernel32.dll")]
internal static extern void GetSystemInfo(out SystemInfo lpSystemInfo);
internal static extern void GetSystemInfo(out SYSTEM_INFO lpSystemInfo);
[StructLayout(LayoutKind.Sequential)]
internal struct SystemInfo
internal struct SYSTEM_INFO
{
public ushort wProcessorArchitecture;
public ushort wReserved;