using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Process.NET.Marshaling;
using Process.NET.Native.Types;
using Process.NET.Utilities;
namespace Process.NET.Threads
{
///
/// Class providing tools for manipulating threads.
///
public class ThreadFactory : IThreadFactory
{
///
/// The reference of the object.
///
protected readonly IProcess Process;
///
/// Initializes a new instance of the class.
///
/// The reference of the object.
public ThreadFactory(IProcess process)
{
// Save the parameter
Process = process;
}
///
/// Gets the main thread of the remote process.
///
public IRemoteThread MainThread
{
get
{
return new RemoteThread(Process,
NativeThreads.Aggregate((current, next) => next.StartTime < current.StartTime ? next : current));
}
}
///
/// Gets the native threads from the remote process.
///
public IEnumerable NativeThreads
{
get
{
// Refresh the process info
Process.Native.Refresh();
// Enumerates all threads
return Process.Native.Threads.Cast();
}
}
///
/// Gets the threads from the remote process.
///
public IEnumerable RemoteThreads
{
get { return NativeThreads.Select(t => new RemoteThread(Process, t)); }
}
///
/// Gets the thread corresponding to an id.
///
/// The unique identifier of the thread to get.
/// A new instance of a class.
public IRemoteThread this[int threadId]
{
get { return new RemoteThread(Process, NativeThreads.First(t => t.Id == threadId)); }
}
///
/// Creates a thread that runs in the remote process.
///
///
/// A pointer to the application-defined function to be executed by the thread and represents
/// the starting address of the thread in the remote process.
///
/// A variable to be passed to the thread function.
/// Sets if the thread must be started just after being created.
/// A new instance of the class.
public IRemoteThread Create(IntPtr address, dynamic parameter, bool isStarted = true)
{
// Marshal the parameter
var marshalledParameter = MarshalValue.Marshal(Process, parameter);
//Create the thread
var ret = ThreadHelper.NtQueryInformationThread(
ThreadHelper.CreateRemoteThread(Process.Handle, address, marshalledParameter.Reference,
ThreadCreationFlags.Suspended));
// Find the managed object corresponding to this thread
var result = new RemoteThread(Process, Process.ThreadFactory.NativeThreads.First(t => t.Id == ret.ThreadId),
marshalledParameter);
if (isStarted)
result.Resume();
return result;
}
///
/// Creates a thread that runs in the remote process.
///
///
/// A pointer to the application-defined function to be executed by the thread and represents
/// the starting address of the thread in the remote process.
///
/// Sets if the thread must be started just after being created.
/// A new instance of the class.
public IRemoteThread Create(IntPtr address, bool isStarted = true)
{
//Create the thread
var ret = ThreadHelper.NtQueryInformationThread(
ThreadHelper.CreateRemoteThread(Process.Handle, address, IntPtr.Zero, ThreadCreationFlags.Suspended));
// Find the managed object corresponding to this thread
var result = new RemoteThread(Process, Process.ThreadFactory.NativeThreads.First(t => t.Id == ret.ThreadId));
// If the thread must be started
if (isStarted)
result.Resume();
return result;
}
///
/// Creates a thread in the remote process and blocks the calling thread until the thread terminates.
///
///
/// A pointer to the application-defined function to be executed by the thread and represents
/// the starting address of the thread in the remote process.
///
/// A variable to be passed to the thread function.
/// A new instance of the class.
public IRemoteThread CreateAndJoin(IntPtr address, dynamic parameter)
{
// Create the thread
var ret = Create(address, parameter);
// Wait the end of the thread
ret.Join();
// Return the thread
return ret;
}
///
/// Creates a thread in the remote process and blocks the calling thread until the thread terminates.
///
///
/// A pointer to the application-defined function to be executed by the thread and represents
/// the starting address of the thread in the remote process.
///
/// A new instance of the class.
public IRemoteThread CreateAndJoin(IntPtr address)
{
// Create the thread
var ret = Create(address);
// Wait the end of the thread
ret.Join();
// Return the thread
return ret;
}
///
/// Releases all resources used by the object.
///
public void Dispose()
{
// Nothing to dispose... yet
}
///
/// Gets a thread by its id in the remote process.
///
/// The id of the thread.
/// A new instance of the class.
public IRemoteThread GetThreadById(int id)
{
return new RemoteThread(Process, NativeThreads.First(t => t.Id == id));
}
///
/// Resumes all threads.
///
public void ResumeAll()
{
foreach (var thread in RemoteThreads)
thread.Resume();
}
///
/// Suspends all threads.
///
public void SuspendAll()
{
foreach (var thread in RemoteThreads)
thread.Suspend();
}
}
}