Skip to content

Instantly share code, notes, and snippets.

@decay88
Created April 23, 2020 05:01
Show Gist options
  • Save decay88/b407aeb6748c77f9ee1e2ab6f3bebba4 to your computer and use it in GitHub Desktop.
Save decay88/b407aeb6748c77f9ee1e2ab6f3bebba4 to your computer and use it in GitHub Desktop.
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