Search
Module:
Directory

   Desktop Functions:

   Smart Device Functions:


Show Recent Changes
Subscribe (RSS)
Misc. Pages
Comments
FAQ
Helpful Tools
Playground
Suggested Reading
Website TODO List
Download Visual Studio Add-In

GetThreadContext (kernel32)
 
.
Summary

C# Signature:

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool GetThreadContext(IntPtr hThread, ref CONTEXT lpContext);

// Get context of thread x64, in x64 application
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool GetThreadContext(IntPtr hThread, ref CONTEXT64 lpContext);

// Use Marshal.AllocHGlobal and Marshal.StructureToPtr to create IntPtr from either
// CONTEXT or CONTEXT64
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool GetThreadContext(IntPtr hThread, IntPtr lpContext);

Boo Signature:

[DllImport("kernel32.dll")]
def OpenThread(dwDesiredAccess as int, bInheritHandle as bool, dwThreadId as int) as IntPtr:
     pass

User-Defined Types:

Here are the structures and enums used by GetThreadContext:

public enum CONTEXT_FLAGS : uint
{
   CONTEXT_i386 = 0x10000,
   CONTEXT_i486 = 0x10000,   //  same as i386
   CONTEXT_CONTROL = CONTEXT_i386 | 0x01, // SS:SP, CS:IP, FLAGS, BP
   CONTEXT_INTEGER = CONTEXT_i386 | 0x02, // AX, BX, CX, DX, SI, DI
   CONTEXT_SEGMENTS = CONTEXT_i386 | 0x04, // DS, ES, FS, GS
   CONTEXT_FLOATING_POINT = CONTEXT_i386 | 0x08, // 387 state
   CONTEXT_DEBUG_REGISTERS = CONTEXT_i386 | 0x10, // DB 0-3,6,7
   CONTEXT_EXTENDED_REGISTERS = CONTEXT_i386 | 0x20, // cpu specific extensions
   CONTEXT_FULL = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS,
   CONTEXT_ALL = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS |  CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS |  CONTEXT_EXTENDED_REGISTERS
}


[StructLayout(LayoutKind.Sequential)]
public struct FLOATING_SAVE_AREA
{
     public uint ControlWord;
     public uint StatusWord;
     public uint TagWord;
     public uint ErrorOffset;
     public uint ErrorSelector;
     public uint DataOffset;
     public uint DataSelector;
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)]
     public byte[] RegisterArea;
     public uint Cr0NpxState;
}

[StructLayout(LayoutKind.Sequential)]
public struct CONTEXT
{
     public uint ContextFlags; //set this to an appropriate value
     // Retrieved by CONTEXT_DEBUG_REGISTERS
     public uint Dr0;  
     public uint Dr1;
     public uint Dr2;
     public uint Dr3;
     public uint Dr6;
     public uint Dr7;
     // Retrieved by CONTEXT_FLOATING_POINT
     public FLOATING_SAVE_AREA FloatSave;
     // Retrieved by CONTEXT_SEGMENTS
     public uint SegGs;
     public uint SegFs;
     public uint SegEs;
     public uint SegDs;
     // Retrieved by CONTEXT_INTEGER
     public uint Edi;
     public uint Esi;
     public uint Ebx;
     public uint Edx;
     public uint Ecx;
     public uint Eax;
     // Retrieved by CONTEXT_CONTROL
     public uint Ebp;
     public uint Eip;
     public uint SegCs;
     public uint EFlags;
     public uint Esp;
     public uint SegSs;
     // Retrieved by CONTEXT_EXTENDED_REGISTERS
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
     public byte[] ExtendedRegisters;
}

// Next x64

[StructLayout(LayoutKind.Sequential)]
public struct M128A
{
     public ulong High;
     public long Low;

     public override string ToString()
     {
    return string.Format("High:{0}, Low:{1}", this.High, this.Low);
     }
}

/// <summary>
/// x64
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 16)]
public struct XSAVE_FORMAT64
{
    public ushort ControlWord;
    public ushort StatusWord;
    public byte TagWord;
    public byte Reserved1;
    public ushort ErrorOpcode;
    public uint ErrorOffset;
    public ushort ErrorSelector;
    public ushort Reserved2;
    public uint DataOffset;
    public ushort DataSelector;
    public ushort Reserved3;
    public uint MxCsr;
    public uint MxCsr_Mask;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
    public M128A[] FloatRegisters;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
    public M128A[] XmmRegisters;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 96)]
    public byte[] Reserved4;
}

/// <summary>
/// x64
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 16)]
public struct CONTEXT64
{
    public ulong P1Home;
    public ulong P2Home;
    public ulong P3Home;
    public ulong P4Home;
    public ulong P5Home;
    public ulong P6Home;

    public CONTEXT_FLAGS ContextFlags;
    public uint MxCsr;

    public ushort SegCs;
    public ushort SegDs;
    public ushort SegEs;
    public ushort SegFs;
    public ushort SegGs;
    public ushort SegSs;
    public uint EFlags;

    public ulong Dr0;
    public ulong Dr1;
    public ulong Dr2;
    public ulong Dr3;
    public ulong Dr6;
    public ulong Dr7;

    public ulong Rax;
    public ulong Rcx;
    public ulong Rdx;
    public ulong Rbx;
    public ulong Rsp;
    public ulong Rbp;
    public ulong Rsi;
    public ulong Rdi;
    public ulong R8;
    public ulong R9;
    public ulong R10;
    public ulong R11;
    public ulong R12;
    public ulong R13;
    public ulong R14;
    public ulong R15;
    public ulong Rip;

    public XSAVE_FORMAT64 DUMMYUNIONNAME;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)]
    public M128A[] VectorRegister;
    public ulong VectorControl;

    public ulong DebugControl;
    public ulong LastBranchToRip;
    public ulong LastBranchFromRip;
    public ulong LastExceptionToRip;
    public ulong LastExceptionFromRip;
}

Notes:

None.

Tips & Tricks:

Please add some!

Sample Code:

class Program
{

     [DllImport("kernel32.dll", SetLastError = true)]
     static extern IntPtr OpenThread(uint dwDesiredAccess, bool bInheritHandle,
     uint dwThreadId);

     [DllImport("kernel32.dll", SetLastError=true)]
     static extern bool GetThreadContext (IntPtr hThread, ref CONTEXT lpContext);

     [DllImport("kernel32.dll", SetLastError=true)]
     static extern bool CloseHandle(IntPtr hObject);

     const uint GET_CONTEXT = 0x08;

     static uint threadId;

     static void Main()
     {
     CONTEXT context = new CONTEXT();
     context.ContextFlags = (uint)CONTEXT_FLAGS.CONTEXT_CONTROL;
     Thread t = new Thread(new ThreadStart(MyMethod));
     t.Start();
     t.Suspend();
     IntPtr hThread = OpenThread(GET_CONTEXT, false, threadId);
     if (GetThreadContext(hThread, ref context))
     {
        Console.WriteLine("Ebp    : {0}", context.Ebp);
        Console.WriteLine("Eip    : {0}", context.Eip);
        Console.WriteLine("SegCs  : {0}", context.SegCs);
        Console.WriteLine("EFlags : {0}", context.EFlags);
        Console.WriteLine("Esp    : {0}", context.Esp);
        Console.WriteLine("SegSs  : {0}", context.SegSs);
     }
     else
     {
        //Console.WriteLine("A problem occurred");
        throw new Win32Exception(Marshal.GetLastWin32Error());
     }
     CloseHandle(hThread);
     t.Resume();
     Console.WriteLine("\nPress any key to end program\n");
     Console.ReadKey();
     }

     static void MyMethod()  
     {
     threadId = (uint)AppDomain.GetCurrentThreadId();
     Thread.Sleep(1000);
     }
}

Alternative Managed API:

Do you know one? Please contribute it!

Documentation

Please edit this page!

Do you have...

  • helpful tips or sample code to share for using this API in managed code?
  • corrections to the existing content?
  • variations of the signature you want to share?
  • additional languages you want to include?

Select "Edit This Page" on the right hand toolbar and edit it! Or add new pages containing supporting types needed for this API (structures, delegates, and more).

 
Access PInvoke.net directly from VS:
Terms of Use
Find References
Show Printable Version
Revisions