Created
April 23, 2020 05:01
-
-
Save decay88/b407aeb6748c77f9ee1e2ab6f3bebba4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.Win32.SafeHandles; | |
using System; | |
using System.ComponentModel; | |
/// <summary> | |
/// Static core class providing tools for manipulating threads. | |
/// </summary> | |
public static class ThreadCore | |
{ #region GetThreadContext | |
/// <summary> | |
/// Retrieves the context of the specified thread. | |
/// </summary> | |
/// <typeparam name="TContext">The type of the context to dump. | |
/// The type must be unmanaged, so it can be fixed while the native call is done. | |
/// The performance is increased if the structure is blittable, which is the case for the structures | |
/// provided with the library.</typeparam> | |
/// <param name="threadHandle">A handle to the thread whose context is to be retrieved.</param> | |
/// <param name="context">An instance of the structure where the context is loaded into.</param> | |
/// <exception cref="Win32Exception">The context cannot be retrieved from the thread.</exception> | |
public static unsafe void GetThreadContext<TContext>(SafeMemoryHandle threadHandle, ref TContext context) | |
where TContext : unmanaged | |
{ | |
// Check if the handle is valid | |
HandleManipulator.ValidateAsArgument(threadHandle, "threadHandle"); | |
// Get the pointer of the structure and pin it, so the GC does not move it | |
fixed (void* contextPtr = &context) | |
{ | |
// Get the thread context | |
if (NativeMethods.GetThreadContext(threadHandle, contextPtr) == (void*)0) | |
{ | |
throw new Win32Exception("The context cannot be retrieved from the thread."); | |
} | |
} | |
} | |
#endregion | |
#region NtQueryInformationThread | |
/// <summary> | |
/// Retrieves information about the specified thread. | |
/// </summary> | |
/// <param name="threadHandle">A handle to the thread to query.</param> | |
/// <returns>A <see cref="ThreadBasicInformation"/> structure containing thread information.</returns> | |
public static unsafe ThreadBasicInformation NtQueryInformationThread(SafeMemoryHandle threadHandle) | |
{ | |
// Check if the handle is valid | |
HandleManipulator.ValidateAsArgument(threadHandle, "threadHandle"); | |
// Create a structure to store thread info | |
var info = new ThreadBasicInformation(); | |
// Get the thread info | |
void* infoPtr = &info; // info is already fixed | |
var ret = NativeMethods.NtQueryInformationThread(threadHandle, ThreadInformationClass.ThreadBasicInformation, | |
infoPtr, MarshalType<ThreadBasicInformation>.SizeAsPointer, out var returnLength); | |
// If the function succeeded | |
if (ret == 0) | |
{ | |
return info; | |
} | |
// Else, couldn't get the thread info, throws an exception | |
throw new ApplicationException($"The thread information cannot be queried; error code '{ret}'."); | |
} | |
/// <summary> | |
/// Retrieves information about the specified thread. | |
/// </summary> | |
/// <param name="threadHandle">A handle to the thread to query.</param> | |
/// <param name="threadInformationClass">The class of the thread to retrieve.</param> | |
/// <returns>The requested data as an unsigned integer.</returns> | |
public static unsafe ulong NtQueryInformationThread(SafeMemoryHandle threadHandle, ThreadInformationClass threadInformationClass) | |
{ | |
// Check if the handle is valid | |
HandleManipulator.ValidateAsArgument(threadHandle, "threadHandle"); | |
// Get the thread info | |
ulong info = 0; | |
var ret = NativeMethods.NtQueryInformationThread(threadHandle, ThreadInformationClass.ThreadBasicInformation, | |
&info, new IntPtr(sizeof(ulong)), out var returnLength); | |
// If the function succeeded | |
if (ret == 0) | |
{ | |
return info; | |
} | |
// Else, couldn't get the thread info, throws an exception | |
throw new ApplicationException($"The thread information cannot be queried; error code '{ret}'."); | |
} | |
#endregion | |
#region ResumeThread | |
/// <summary> | |
/// Decrements a thread's suspend count. When the suspend count is decremented to zero, the execution of the thread is resumed. | |
/// </summary> | |
/// <param name="threadHandle">A handle to the thread to be restarted.</param> | |
/// <returns>The thread's previous suspend count.</returns> | |
public static uint ResumeThread(SafeMemoryHandle threadHandle) | |
{ | |
// Check if the handle is valid | |
HandleManipulator.ValidateAsArgument(threadHandle, "threadHandle"); | |
// Resume the thread | |
var ret = NativeMethods.ResumeThread(threadHandle); | |
// If the function failed | |
if (ret == uint.MaxValue) | |
throw new Win32Exception("Couldn't resume the thread."); | |
return ret; | |
} | |
#endregion | |
#region SetThreadContext | |
/// <summary> | |
/// Sets the context for the specified thread. | |
/// </summary> | |
/// <typeparam name="TContext">The type of the context to set. | |
/// The type must be unmanaged, so it can be fixed while the native call is done. | |
/// The performance is increased if the structure is blittable, which is the case for the structures | |
/// provided with the library.</typeparam> | |
/// <param name="threadHandle">A handle to the thread whose context is to be set.</param> | |
/// <param name="context">A pointer to a <see cref="ThreadContext32" /> structure that contains the context to be set in the specified thread.</param> | |
/// <exception cref="Win32Exception">The context cannot be set to the thread.</exception> | |
public static unsafe void SetThreadContext<TContext>(SafeMemoryHandle threadHandle, ref TContext context) | |
where TContext : unmanaged | |
{ | |
// Check if the handle is valid | |
HandleManipulator.ValidateAsArgument(threadHandle, "threadHandle"); | |
// Get the pointer of the structure and pin it, so the GC does not move it | |
fixed (void* contextPtr = &context) | |
{ | |
// Set the thread context | |
if (NativeMethods.SetThreadContext(threadHandle, contextPtr) == 0) | |
{ | |
throw new Win32Exception("The context cannot be set to the thread."); | |
} | |
} | |
} | |
#endregion | |
#region SuspendThread | |
/// <summary> | |
/// Suspends the specified thread. | |
/// </summary> | |
/// <param name="threadHandle">A handle to the thread that is to be suspended.</param> | |
/// <returns>The thread's previous suspend count.</returns> | |
public static uint SuspendThread(SafeMemoryHandle threadHandle) | |
{ | |
// Check if the handle is valid | |
HandleManipulator.ValidateAsArgument(threadHandle, "threadHandle"); | |
// Suspend the thread | |
var ret = NativeMethods.SuspendThread(threadHandle); | |
// If the function failed | |
if (ret == uint.MaxValue) | |
throw new Win32Exception("Couldn't suspend the thread."); | |
return ret; | |
} | |
#endregion | |
#region TerminateThread | |
/// <summary> | |
/// Terminates a thread. | |
/// </summary> | |
/// <param name="threadHandle">A handle to the thread to be terminated.</param> | |
/// <param name="exitCode">The exit code for the thread.</param> | |
public static void TerminateThread(SafeMemoryHandle threadHandle, int exitCode) | |
{ | |
// Check if the handle is valid | |
HandleManipulator.ValidateAsArgument(threadHandle, "threadHandle"); | |
// Terminate the thread | |
var ret = NativeMethods.TerminateThread(threadHandle, exitCode); | |
// If the function failed | |
if(!ret) | |
throw new Win32Exception("Couldn't terminate the thread."); | |
} | |
#endregion | |
#region ThreadContextFlags | |
/// <summary> | |
/// Determines which registers are returned or set when using <see cref="NativeMethods.GetThreadContext"/> or <see cref="NativeMethods.SetThreadContext"/>. | |
/// </summary> | |
[Flags] | |
public enum ThreadContextFlags : uint | |
{ | |
/// <summary> | |
/// The Intel 80386 microprocessor, also known as the i386. | |
/// </summary> | |
Intel386 = 0x10000, | |
/// <summary> | |
/// The Intel 80486 microprocessor, also known as the i486. | |
/// </summary> | |
Intel486 = 0x10000, | |
/// <summary> | |
/// SS:SP, CS:IP, FLAGS, BP | |
/// </summary> | |
Control = Intel386 | 0x01, | |
/// <summary> | |
/// AX, BX, CX, DX, SI, DI | |
/// </summary> | |
Integer = Intel386 | 0x02, | |
/// <summary> | |
/// DS, ES, FS, GS | |
/// </summary> | |
Segments = Intel386 | 0x04, | |
/// <summary> | |
/// 387 state | |
/// </summary> | |
FloatingPoint = Intel386 | 0x08, | |
/// <summary> | |
/// DB 0-3,6,7 | |
/// </summary> | |
DebugRegisters = Intel386 | 0x10, | |
/// <summary> | |
/// CPU specific extensions | |
/// </summary> | |
ExtendedRegisters = Intel386 | 0x20, | |
/// <summary> | |
/// All flags excepted FloatingPoint, DebugRegisters and ExtendedRegisters. | |
/// </summary> | |
Full = Control | Integer | Segments, | |
/// <summary> | |
/// All flags. | |
/// </summary> | |
All = Control | Integer | Segments | FloatingPoint | DebugRegisters | ExtendedRegisters | |
} | |
#endregion | |
#region ThreadInformationClass | |
/// <summary> | |
///The numeration that corresponds to the classes of thread information. | |
/// </summary> | |
public enum ThreadInformationClass : uint | |
{ | |
ThreadBasicInformation = 0, | |
ThreadTimes = 1, | |
ThreadPriority = 2, | |
ThreadBasePriority = 3, | |
ThreadAffinityMask = 4, | |
ThreadImpersonationToken = 5, | |
ThreadDescriptorTableEntry = 6, | |
ThreadEnableAlignmentFaultFixup = 7, | |
ThreadEventPair_Reusable = 8, | |
ThreadQuerySetWin32StartAddress = 9, | |
ThreadZeroTlsCell = 10, | |
ThreadPerformanceCount = 11, | |
ThreadAmILastThread = 12, | |
ThreadIdealProcessor = 13, | |
ThreadPriorityBoost = 14, | |
ThreadSetTlsArrayAddress = 15, | |
ThreadIsIoPending = 16, | |
ThreadHideFromDebugger = 17, | |
ThreadBreakOnTermination = 18, | |
ThreadSwitchLegacyState = 19, | |
ThreadIsTerminated = 20, | |
ThreadLastSystemCall = 21, | |
ThreadIoPriority = 22, | |
ThreadCycleTime = 23, | |
ThreadPagePriority = 24, | |
ThreadActualBasePriority = 25, | |
ThreadTebInformation = 26, | |
ThreadCSwitchMon = 27, | |
ThreadCSwitchPmu = 28, | |
ThreadWow64Context = 29, | |
ThreadGroupInformation = 30, | |
ThreadUmsInformation = 31, | |
ThreadCounterProfiling = 32, | |
ThreadIdealProcessorEx = 33, | |
ThreadCpuAccountingInformation = 34, | |
ThreadSuspendCount = 35, | |
ThreadHeterogeneousCpuPolicy = 36, | |
ThreadContainerId = 37, | |
ThreadNameInformation = 38, | |
ThreadSelectedCpuSets = 39, | |
ThreadSystemThreadInformation = 40, | |
ThreadActualGroupAffinity = 41, | |
ThreadDynamicCodePolicyInfo = 42, | |
ThreadExplicitCaseSensitivity = 43, | |
ThreadWorkOnBehalfTicket = 44, | |
ThreadSubsystemInformation = 45, | |
ThreadDbgkWerReportActive = 46, | |
ThreadAttachContainer = 47, | |
ThreadManageWritesToExecutableMemory = 48, | |
ThreadPowerThrottlingState = 49, | |
ThreadWorkloadClass = 50, | |
} | |
#endregion | |
#region ProcessBasicInformation | |
/// <summary> | |
/// Structure containing basic information about a process. | |
/// </summary> | |
[StructLayout(LayoutKind.Sequential)] | |
public struct ProcessBasicInformation | |
{ | |
/// <summary> | |
/// The exit status. | |
/// </summary> | |
public IntPtr ExitStatus; | |
/// <summary> | |
/// The base address of Process Environment Block. | |
/// </summary> | |
public IntPtr PebBaseAddress; | |
/// <summary> | |
/// The affinity mask. | |
/// </summary> | |
public IntPtr AffinityMask; | |
/// <summary> | |
/// The base priority. | |
/// </summary> | |
public IntPtr BasePriority; | |
/// <summary> | |
/// The process id. | |
/// </summary> | |
public IntPtr ProcessId; | |
/// <summary> | |
/// The process id of the parent process. | |
/// </summary> | |
public IntPtr InheritedFromUniqueProcessId; | |
} | |
#endregion ProcessBasicInformation | |
#region ThreadBasicInformation | |
/// <summary> | |
/// Structure containing basic information about a thread. | |
/// </summary> | |
[StructLayout(LayoutKind.Sequential)] | |
public struct ThreadBasicInformation | |
{ | |
/// <summary> | |
/// the exit status (NTSTATUS). | |
/// </summary> | |
public uint ExitStatus; | |
/// <summary> | |
/// The base address of Thread Environment Block. | |
/// </summary> | |
public IntPtr TebBaseAddress; | |
/// <summary> | |
/// The process and thread identifiers. | |
/// </summary> | |
public ClientIdStruct ClientIdStruct; | |
/// <summary> | |
/// The affinity mask. | |
/// </summary> | |
public IntPtr AffinityMask; | |
/// <summary> | |
/// The priority. | |
/// </summary> | |
public int Priority; | |
/// <summary> | |
/// The base priority. | |
/// </summary> | |
public int BasePriority; | |
} | |
#endregion ThreadBasicInformation | |
#region ThreadContext32 | |
/// <summary> | |
/// Represents a thread context for 32-bit processes on Windows. Create a new instance using the constructor with the | |
/// flags. | |
/// </summary> | |
/// <remarks> | |
/// This structure is blittable and therefore, does not require any marshaling from Platform Invoke. | |
/// Referenced on https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_wow64_context. | |
/// Refer to the header file WinNT.h for definitions of this structure for each processor architecture. | |
/// </remarks> | |
[StructLayout(LayoutKind.Explicit, Size = ThreadContext32Metadata.TotalSize)] | |
public unsafe struct ThreadContext32 | |
{ | |
/// <summary> | |
/// Initializes a new instance of the <see cref="ThreadContext32" /> struct. | |
/// </summary> | |
/// <param name="flags">Determines which registers are returned or set during the context query.</param> | |
public ThreadContext32(ThreadContextFlags flags) : this() | |
{ | |
ContextFlags = flags; | |
} | |
/// <summary> | |
/// Determines which registers are returned or set when using <see cref="NativeMethods.GetThreadContext" /> or | |
/// <see cref="NativeMethods.SetThreadContext" />. | |
/// If the context record is used as an INPUT parameter, then for each portion of the context record controlled by a flag | |
/// whose value is set, it is assumed that portion of the | |
/// context record contains valid context. If the context record is being used to modify a threads context, then only that | |
/// portion of the threads context will be modified. | |
/// If the context record is used as an INPUT/OUTPUT parameter to capture the context of a thread, then only those portions | |
/// of the thread's context corresponding to set flags will be returned. | |
/// The context record is never used as an OUTPUT only parameter. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.ContextFlags)] | |
public ThreadContextFlags ContextFlags; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag | |
/// <see cref="ThreadContextFlags.DebugRegisters" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.Dr0)] | |
public uint Dr0; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag | |
/// <see cref="ThreadContextFlags.DebugRegisters" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.Dr1)] | |
public uint Dr1; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag | |
/// <see cref="ThreadContextFlags.DebugRegisters" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.Dr2)] | |
public uint Dr2; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag | |
/// <see cref="ThreadContextFlags.DebugRegisters" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.Dr3)] | |
public uint Dr3; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag | |
/// <see cref="ThreadContextFlags.DebugRegisters" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.Dr6)] | |
public uint Dr6; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag | |
/// <see cref="ThreadContextFlags.DebugRegisters" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.Dr7)] | |
public uint Dr7; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag | |
/// <see cref="ThreadContextFlags.FloatingPoint" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.ControlWord)] | |
public uint ControlWord; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag | |
/// <see cref="ThreadContextFlags.FloatingPoint" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.StatusWord)] | |
public uint StatusWord; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag | |
/// <see cref="ThreadContextFlags.FloatingPoint" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.TagWord)] | |
public uint TagWord; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag | |
/// <see cref="ThreadContextFlags.FloatingPoint" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.ErrorOffset)] | |
public uint ErrorOffset; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag | |
/// <see cref="ThreadContextFlags.FloatingPoint" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.ErrorSelector)] | |
public uint ErrorSelector; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag | |
/// <see cref="ThreadContextFlags.FloatingPoint" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.DataOffset)] | |
public uint DataOffset; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag | |
/// <see cref="ThreadContextFlags.FloatingPoint" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.DataSelector)] | |
public uint DataSelector; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag | |
/// <see cref="ThreadContextFlags.FloatingPoint" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.RegisterArea)] | |
public fixed byte RegisterArea[ThreadContext32Metadata.Sizes.RegisterAreaSize]; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag | |
/// <see cref="ThreadContextFlags.FloatingPoint" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.Cr0NpxState)] | |
public uint Cr0NpxState; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag <see cref="ThreadContextFlags.Segments" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.SegGs)] | |
public uint SegGs; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag <see cref="ThreadContextFlags.Segments" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.SegFs)] | |
public uint SegFs; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag <see cref="ThreadContextFlags.Segments" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.SegEs)] | |
public uint SegEs; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag <see cref="ThreadContextFlags.Segments" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.SegDs)] | |
public uint SegDs; | |
/// <summary> | |
/// This register is specified/returned if the ContextFlags word contains the flag | |
/// <see cref="ThreadContextFlags.Integer" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.Edi)] | |
public uint Edi; | |
/// <summary> | |
/// This register is specified/returned if the ContextFlags word contains the flag | |
/// <see cref="ThreadContextFlags.Integer" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.Esi)] | |
public uint Esi; | |
/// <summary> | |
/// This register is specified/returned if the ContextFlags word contains the flag | |
/// <see cref="ThreadContextFlags.Integer" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.Ebx)] | |
public uint Ebx; | |
/// <summary> | |
/// This register is specified/returned if the ContextFlags word contains the flag | |
/// <see cref="ThreadContextFlags.Integer" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.Edx)] | |
public uint Edx; | |
/// <summary> | |
/// This register is specified/returned if the ContextFlags word contains the flag | |
/// <see cref="ThreadContextFlags.Integer" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.Ecx)] | |
public uint Ecx; | |
/// <summary> | |
/// This register is specified/returned if the ContextFlags word contains the flag | |
/// <see cref="ThreadContextFlags.Integer" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.Eax)] | |
public uint Eax; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag <see cref="ThreadContextFlags.Control" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.Ebp)] | |
public uint Ebp; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag <see cref="ThreadContextFlags.Control" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.Eip)] | |
public uint Eip; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag <see cref="ThreadContextFlags.Control" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.SegCs)] | |
public uint SegCs; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag <see cref="ThreadContextFlags.Control" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.EFlags)] | |
public uint EFlags; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag <see cref="ThreadContextFlags.Control" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.Esp)] | |
public uint Esp; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag <see cref="ThreadContextFlags.Control" />. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.SegSs)] | |
public uint SegSs; | |
/// <summary> | |
/// This is specified/returned if <see cref="ContextFlags" /> contains the flag | |
/// <see cref="ThreadContextFlags.ExtendedRegisters" />. | |
/// The format and contexts are processor specific. | |
/// </summary> | |
[FieldOffset(ThreadContext32Metadata.Offsets.ExtendedRegisters)] | |
public fixed byte ExtendedRegisters[ThreadContext32Metadata.Sizes.ExtendedRegistersSize]; | |
} | |
#endregion ThreadContext32 | |
#region ThreadContext64 | |
/// <summary> | |
/// Represents a thread context for 64-bit processes on Windows. Create a new instance using the constructor with the | |
/// flags. | |
/// </summary> | |
/// <remarks> | |
/// This structure is blittable and therefore, does not require any marshaling from Platform Invoke. | |
/// Referenced on https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_context. | |
/// Refer to the header file WinNT.h for definitions of this structure for each processor architecture. | |
/// </remarks> | |
[StructLayout(LayoutKind.Explicit, Size = ThreadContext64Metadata.TotalSize)] | |
public unsafe struct ThreadContext64 | |
{ | |
/// <summary> | |
/// Initializes a new instance of the <see cref="ThreadContext64" /> struct. | |
/// </summary> | |
/// <param name="flags">Determines which registers are returned or set during the context query.</param> | |
public ThreadContext64(ThreadContextFlags flags) : this() | |
{ | |
ContextFlags = flags; | |
} | |
[FieldOffset(ThreadContext64Metadata.Offsets.P1Home)] | |
public ulong P1Home; | |
[FieldOffset(ThreadContext64Metadata.Offsets.P2Home)] | |
public ulong P2Home; | |
[FieldOffset(ThreadContext64Metadata.Offsets.P3Home)] | |
public ulong P3Home; | |
[FieldOffset(ThreadContext64Metadata.Offsets.P4Home)] | |
public ulong P4Home; | |
[FieldOffset(ThreadContext64Metadata.Offsets.P5Home)] | |
public ulong P5Home; | |
[FieldOffset(ThreadContext64Metadata.Offsets.P6Home)] | |
public ulong P6Home; | |
/// <summary> | |
/// Determines which registers are returned or set when using <see cref="NativeMethods.GetThreadContext" /> or | |
/// <see cref="NativeMethods.SetThreadContext" />. | |
/// If the context record is used as an INPUT parameter, then for each portion of the context record controlled by a flag | |
/// whose value is set, it is assumed that portion of the | |
/// context record contains valid context. If the context record is being used to modify a threads context, then only that | |
/// portion of the threads context will be modified. | |
/// If the context record is used as an INPUT/OUTPUT parameter to capture the context of a thread, then only those portions | |
/// of the thread's context corresponding to set flags will be returned. | |
/// The context record is never used as an OUTPUT only parameter. | |
/// </summary> | |
[FieldOffset(ThreadContext64Metadata.Offsets.ContextFlags)] | |
public ThreadContextFlags ContextFlags; | |
[FieldOffset(ThreadContext64Metadata.Offsets.MxCsr)] | |
public uint MxCsr; | |
[FieldOffset(ThreadContext64Metadata.Offsets.SegCs)] | |
public ushort SegCs; | |
[FieldOffset(ThreadContext64Metadata.Offsets.SegDs)] | |
public ushort SegDs; | |
[FieldOffset(ThreadContext64Metadata.Offsets.SegEs)] | |
public ushort SegEs; | |
[FieldOffset(ThreadContext64Metadata.Offsets.SegFs)] | |
public ushort SegFs; | |
[FieldOffset(ThreadContext64Metadata.Offsets.SegGs)] | |
public ushort SegGs; | |
[FieldOffset(ThreadContext64Metadata.Offsets.SegSs)] | |
public ushort SegSs; | |
[FieldOffset(ThreadContext64Metadata.Offsets.EFlags)] | |
public uint EFlags; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Dr0)] | |
public ulong Dr0; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Dr1)] | |
public ulong Dr1; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Dr2)] | |
public ulong Dr2; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Dr3)] | |
public ulong Dr3; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Dr6)] | |
public ulong Dr6; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Dr7)] | |
public ulong Dr7; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Rax)] | |
public ulong Rax; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Rcx)] | |
public ulong Rcx; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Rdx)] | |
public ulong Rdx; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Rbx)] | |
public ulong Rbx; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Rsp)] | |
public ulong Rsp; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Rbp)] | |
public ulong Rbp; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Rsi)] | |
public ulong Rsi; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Rdi)] | |
public ulong Rdi; | |
[FieldOffset(ThreadContext64Metadata.Offsets.R8)] | |
public ulong R8; | |
[FieldOffset(ThreadContext64Metadata.Offsets.R9)] | |
public ulong R9; | |
[FieldOffset(ThreadContext64Metadata.Offsets.R10)] | |
public ulong R10; | |
[FieldOffset(ThreadContext64Metadata.Offsets.R11)] | |
public ulong R11; | |
[FieldOffset(ThreadContext64Metadata.Offsets.R12)] | |
public ulong R12; | |
[FieldOffset(ThreadContext64Metadata.Offsets.R13)] | |
public ulong R13; | |
[FieldOffset(ThreadContext64Metadata.Offsets.R14)] | |
public ulong R14; | |
[FieldOffset(ThreadContext64Metadata.Offsets.R15)] | |
public ulong R15; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Rip)] | |
public ulong Rip; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Header)] | |
public fixed ulong Header[ThreadContext64Metadata.Sizes.Header]; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Legacy)] | |
public fixed ulong Legacy[ThreadContext64Metadata.Sizes.Legacy]; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Xmm0)] | |
public M128A Xmm0; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Xmm1)] | |
public M128A Xmm1; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Xmm2)] | |
public M128A Xmm2; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Xmm3)] | |
public M128A Xmm3; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Xmm4)] | |
public M128A Xmm4; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Xmm5)] | |
public M128A Xmm5; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Xmm6)] | |
public M128A Xmm6; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Xmm7)] | |
public M128A Xmm7; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Xmm8)] | |
public M128A Xmm8; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Xmm9)] | |
public M128A Xmm9; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Xmm10)] | |
public M128A Xmm10; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Xmm11)] | |
public M128A Xmm11; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Xmm12)] | |
public M128A Xmm12; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Xmm13)] | |
public M128A Xmm13; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Xmm14)] | |
public M128A Xmm14; | |
[FieldOffset(ThreadContext64Metadata.Offsets.Xmm15)] | |
public M128A Xmm15; | |
[FieldOffset(ThreadContext64Metadata.Offsets.VectorRegister)] | |
public fixed ulong VectorRegister[ThreadContext64Metadata.Sizes.VectorRegister]; | |
[FieldOffset(ThreadContext64Metadata.Offsets.VectorControl)] | |
public ulong VectorControl; | |
[FieldOffset(ThreadContext64Metadata.Offsets.DebugControl)] | |
public ulong DebugControl; | |
[FieldOffset(ThreadContext64Metadata.Offsets.LastBranchToRip)] | |
public ulong LastBranchToRip; | |
[FieldOffset(ThreadContext64Metadata.Offsets.LastBranchFromRip)] | |
public ulong LastBranchFromRip; | |
[FieldOffset(ThreadContext64Metadata.Offsets.LastExceptionToRip)] | |
public ulong LastExceptionToRip; | |
[FieldOffset(ThreadContext64Metadata.Offsets.LastExceptionFromRip)] | |
public ulong LastExceptionFromRip; | |
} | |
#endregion ThreadContext64 | |
} | |
/// <summary> | |
/// Represents a Win32 handle safely managed. | |
/// </summary> | |
[SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)] | |
public sealed class SafeMemoryHandle : SafeHandleZeroOrMinusOneIsInvalid | |
{ | |
/// <summary> | |
/// Parameterless constructor for handles built by the system (like <see cref="NativeMethods.OpenProcess"/>). | |
/// </summary> | |
public SafeMemoryHandle() : base(true) { } | |
/// <summary> | |
/// Initializes a new instance of the <see cref="SafeMemoryHandle"/> class, specifying the handle to keep in safe. | |
/// </summary> | |
/// <param name="handle">The handle to keep in safe.</param> | |
public SafeMemoryHandle(IntPtr handle) : base(true) | |
{ | |
SetHandle(handle); | |
} | |
/// <summary> | |
/// Executes the code required to free the handle. | |
/// </summary> | |
/// <returns>True if the handle is released successfully; otherwise, in the event of a catastrophic failure, false. In this case, it generates a releaseHandleFailed MDA Managed Debugging Assistant.</returns> | |
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] | |
protected override bool ReleaseHandle() | |
{ | |
// Check whether the handle is set AND whether the handle has been successfully closed | |
return handle != IntPtr.Zero && NativeMethods.CloseHandle(handle); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment