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:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user