/* * Process Hacker - * thread handle * * Copyright (C) 2008-2009 wj32 * * This file is part of Process Hacker. * * Process Hacker is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Process Hacker is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Process Hacker. If not, see . */ using System; using System.Runtime.InteropServices; namespace ProcessHacker { public partial class Win32 { /// /// Represents a handle to a Windows thread. /// public class ThreadHandle : Win32Handle, IWithToken { /// /// Creates a thread handle using an existing handle. /// The handle will not be closed automatically. /// /// The handle value. /// The thread handle. public static ThreadHandle FromHandle(int Handle) { return new ThreadHandle(Handle, false); } internal ThreadHandle(int Handle, bool Owned) : base(Handle, Owned) { } /// /// Creates a new thread handle. /// /// The ID of the thread to open. public ThreadHandle(int tid) : this(tid, THREAD_RIGHTS.THREAD_ALL_ACCESS) { } /// /// Creates a new thread handle. /// /// The ID of the thread to open. /// The desired access to the thread. public ThreadHandle(int tid, THREAD_RIGHTS access) { if (Program.Aggressive) { if (Program.KPH != null) this.Handle = Program.KPH.KphOpenThread(tid, Program.MinThreadQueryRights); else this.Handle = OpenThread(Program.MinThreadQueryRights, 0, tid); if (this.Handle == 0) ThrowLastWin32Error(); int newHandle; try { ZwDuplicateObject(-1, this.Handle, -1, out newHandle, (int)access, 0, 0); } finally { CloseHandle(this.Handle); } this.Handle = newHandle; } else { if (Program.KPH != null) this.Handle = Program.KPH.KphOpenThread(tid, access); else this.Handle = OpenThread(access, 0, tid); if (this.Handle == 0) ThrowLastWin32Error(); } } /// /// Puts the thread in an alerted state. /// public void Alert() { if (ZwAlertThread(this) < 0) ThrowLastWin32Error(); } /// /// Gets the thread's basic information. /// /// A THREAD_BASIC_INFORMATION structure. public THREAD_BASIC_INFORMATION GetBasicInformation() { THREAD_BASIC_INFORMATION basicInfo = new THREAD_BASIC_INFORMATION(); int retLen; if (ZwQueryInformationThread(this, THREAD_INFORMATION_CLASS.ThreadBasicInformation, ref basicInfo, Marshal.SizeOf(basicInfo), out retLen) < 0) ThrowLastWin32Error(); return basicInfo; } /// /// Gets the thread's context. /// /// A CONTEXT struct. public CONTEXT GetContext(CONTEXT_FLAGS flags) { CONTEXT context = new CONTEXT(); context.ContextFlags = flags; if (!GetThreadContext(this, ref context)) ThrowLastWin32Error(); return context; } /// /// Gets the number of processor cycles consumed by the thread. /// public ulong GetCycleTime() { ulong cycles; if (!QueryThreadCycleTime(this, out cycles)) ThrowLastWin32Error(); return cycles; } /// /// Gets the thread's exit code. /// /// A number. public int GetExitCode() { int exitCode; if (!GetExitCodeThread(this, out exitCode)) ThrowLastWin32Error(); return exitCode; } /// /// Gets the thread's priority level. /// /// A ThreadPriorityLevel enum. public System.Diagnostics.ThreadPriorityLevel GetPriorityLevel() { int priority = GetThreadPriority(this); if (priority == 0x7fffffff) ThrowLastWin32Error(); return (System.Diagnostics.ThreadPriorityLevel)priority; } /// /// Adds an user-mode asynchronous procedure call (APC) to the thread's APC queue. /// This requires the THREAD_SET_CONTEXT permission. /// /// The address of the APC procedure. /// The parameter to pass to the procedure. public void QueueAPC(int address, int parameter) { if (!QueueUserAPC(address, this, parameter)) ThrowLastWin32Error(); } /// /// Sets the thread's context. /// /// A CONTEXT struct. public void SetContext(CONTEXT context) { if (!SetThreadContext(this, ref context)) ThrowLastWin32Error(); } /// /// Sets the thread's priority level. /// /// The priority of the thread. public void SetPriorityLevel(System.Diagnostics.ThreadPriorityLevel priority) { if (!SetThreadPriority(this, (int)priority)) ThrowLastWin32Error(); } /// /// Suspends the thread. /// public void Suspend() { if (SuspendThread(this) == -1) ThrowLastWin32Error(); } /// /// Resumes the thread. /// public void Resume() { if (ResumeThread(this) == -1) ThrowLastWin32Error(); } /// /// Terminates the thread. /// public void Terminate() { this.Terminate(0); } /// /// Terminates the thread, specifying an exit code. /// /// The exit code. public void Terminate(int ExitCode) { if (!TerminateThread(this, ExitCode)) ThrowLastWin32Error(); } /// /// Opens and returns a handle to the thread's token. /// /// A handle to the thread's token. public TokenHandle GetToken() { return GetToken(TOKEN_RIGHTS.TOKEN_ALL_ACCESS); } /// /// Opens and returns a handle to the thread's token. /// /// The desired access to the token. /// A handle to the thread's token. public TokenHandle GetToken(TOKEN_RIGHTS access) { return new TokenHandle(this, access); } } } }