- Drop the false WOW64 claim from GetContext32/SetContext32 docs and guard them for 32-bit targets only.\n- Make FrozenThread dispose the thread handles it owns; make Freeze(predicate) dispose filtered-out threads.\n- Pass the already-validated handle through GetThreadById instead of opening a second one.\n- Add no-progress guard to MemoryBase.EnumerateRegions.\n- Dispose unmatched Process candidates in ApplicationFinder.OpenProcess.\n- Clean up RemoteThreadExecutor allocation formatting.
53 lines
1.4 KiB
C#
53 lines
1.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace WhiteMagic.Thread;
|
|
|
|
/// <summary>
|
|
/// A disposable scope that tracks a set of threads frozen by <see cref="ThreadFactory.Freeze"/>.
|
|
/// Disposing the scope resumes exactly those threads, in reverse order, even if the guarded
|
|
/// body throws, and then disposes the underlying thread handles.
|
|
/// </summary>
|
|
public sealed class FrozenThread : IDisposable
|
|
{
|
|
private readonly IReadOnlyList<RemoteThread> _threads;
|
|
private bool _disposed;
|
|
|
|
internal FrozenThread(IReadOnlyList<RemoteThread> threads)
|
|
{
|
|
_threads = threads ?? throw new ArgumentNullException(nameof(threads));
|
|
}
|
|
|
|
/// <summary>The threads suspended by this freeze scope.</summary>
|
|
public IEnumerable<RemoteThread> Threads => _threads;
|
|
|
|
/// <summary>
|
|
/// Resumes the frozen threads in reverse order, then disposes every thread handle.
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
if (_disposed)
|
|
return;
|
|
|
|
_disposed = true;
|
|
|
|
foreach (RemoteThread thread in _threads.Reverse())
|
|
{
|
|
try
|
|
{
|
|
thread.Resume();
|
|
}
|
|
catch
|
|
{
|
|
// Resume-on-dispose is best-effort; the handle is still disposed below.
|
|
}
|
|
}
|
|
|
|
foreach (RemoteThread thread in _threads)
|
|
{
|
|
thread.Dispose();
|
|
}
|
|
}
|
|
}
|