Address review findings for thread control and process discovery

- 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.
This commit is contained in:
kbe
2026-07-22 17:18:48 +02:00
parent 3e294dc846
commit 1169fdb994
6 changed files with 78 additions and 19 deletions
+40 -6
View File
@@ -86,7 +86,13 @@ public sealed class ThreadFactory
if (threadId <= 0)
throw new ArgumentException("Thread ID must be positive.", nameof(threadId));
SafeMemoryHandle handle = NativeMethods.OpenThread(ThreadAccess.QueryInformation, false, threadId);
const ThreadAccess requiredAccess =
ThreadAccess.SuspendResume |
ThreadAccess.GetContext |
ThreadAccess.SetContext |
ThreadAccess.QueryInformation;
SafeMemoryHandle handle = NativeMethods.OpenThread(requiredAccess, false, threadId);
if (handle.IsInvalid)
{
int error = Marshal.GetLastPInvokeError();
@@ -115,12 +121,13 @@ public sealed class ThreadFactory
$"Thread {threadId} does not belong to process {_memory.ProcessId}.");
}
// Open a handle with the rights the public RemoteThread surface needs.
return new RemoteThread(_memory, threadId);
// Ownership of the validated handle transfers to the RemoteThread.
return new RemoteThread(_memory, threadId, handle);
}
finally
catch
{
handle.Dispose();
throw;
}
}
@@ -202,12 +209,39 @@ public sealed class ThreadFactory
}
/// <summary>
/// Suspends all threads selected by <paramref name="predicate"/>.
/// Suspends all target threads selected by <paramref name="predicate"/>.
/// </summary>
public FrozenThread Freeze(Func<RemoteThread, bool> predicate)
{
ArgumentNullException.ThrowIfNull(predicate);
return Freeze(Enumerate().Where(predicate));
var selected = new List<RemoteThread>();
try
{
foreach (RemoteThread thread in Enumerate())
{
try
{
if (predicate(thread))
selected.Add(thread);
else
thread.Dispose();
}
catch
{
thread.Dispose();
throw;
}
}
return Freeze(selected);
}
catch
{
foreach (RemoteThread thread in selected)
thread.Dispose();
throw;
}
}
private long GetCreationTime(int threadId)