BOOL GetThreadContext(
HANDLE hThread,
LPCONTEXT lpContext
);
And
[DllImport("kernel32.dll", SetLastError=true)]
static extern int GetThreadContext ( int hThread, ref CONTEXT lpContext)
but I can not use it cause I don't know what I should pass to the LPCONTEXT parameter!
Could anyone explain it for me with an example please?
AlanPosted Aug 20, 2007, 2:50 PM
Hi guys,
Yeah, I knew it wasn't on Pinvoke.net so if you could put it on, Mike, it'll fill in another piece in the interop jigsaw :)
Thomas SieverdingPosted Aug 20, 2007, 2:16 PM
Mike GoldPosted Aug 20, 2007, 1:02 PM
Nice one Alan! It wasn't even on http://www.pinvoke.net. Is it okay to add this code to their wiki?
AlanPosted Aug 20, 2007, 12:54 PM
To use GetThreadContext() from C#, you first need to define a CONTEXT structure. As I couldn't find a single C# example of this, I've had a go myself at translating the C code in winnt.h for the 32 bit X86 processor family and placed the ContextFlags you may need in an enum. The following example code seems to be working OK but you'll know better than me what sort of register values to expect:
using System;
using System.Threading;
using System.Diagnostics;
using System.Runtime.InteropServices;
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;
}
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");
}
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);
}
}