Reputation:
I have a struct like this
[StructLayout(LayoutKind.Sequential)]
internal struct Context
{
internal uint ContextFlags;
private readonly IntPtr Dr0;
private readonly IntPtr Dr1;
private readonly IntPtr Dr2;
private readonly IntPtr Dr3;
private readonly IntPtr Dr6;
private readonly IntPtr Dr7;
private readonly FloatingSaveArea FloatingSave;
private readonly IntPtr SegGs;
private readonly IntPtr SegFs;
private readonly IntPtr SegEs;
private readonly IntPtr SegDs;
private readonly IntPtr Edi;
private readonly IntPtr Esi;
private readonly IntPtr Ebx;
private readonly IntPtr Edx;
private readonly IntPtr Ecx;
private readonly IntPtr Eax;
private readonly IntPtr Ebp;
internal IntPtr Eip;
private readonly IntPtr SegCs;
private readonly IntPtr EFlags;
private readonly IntPtr Esp;
private readonly IntPtr SegSs;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
private readonly byte[] ExtendedRegisters;
}
It is filled with data using the following pinvoke method
[DllImport("kernel32.dll")]
internal static extern bool GetThreadContext(IntPtr hThread, ref Context lpContext);
I only need access to the variables ContextFlags
and Eip
Ideally, I would like to remove all the other variables from the struct that I don't need, however, when I do this, the Eip
variable is no longer filled with the correct value.
I have also tried the following
[StructLayout(LayoutKind.Explicit)]
internal struct Context
{
[FieldOffset(0)]
internal uint ContextFlags;
[FieldOffset(184)]
internal IntPtr Eip;
}
The field offset of 184 comes from
uint offsetEip = (uint) Marshal.OffsetOf(typeof(Context), "Eip");
This also doesn't work
Is there a way to achieve this? Maybe through using a class instead of a struct?
Upvotes: 1
Views: 172
Reputation: 317
The structure is defined in a Windows header file, to correspond to the Windows API function, and it assumes you are passing an address to a allocated/owned memory location of the same size of the complete structure. Since the Windows API function is only getting a pointer, it has to assume you have passed a pointer to the whole structure, although you will only be using two of the members. You can create your own structure of the same size, to expose only the two members that you need.
Upvotes: 0
Reputation: 139055
Of course it can work, in the end, it's just an opaque array of bytes, but you must make sure the whole structure size is the same and matches the current hardware/software context, so, just define it like this for an x86 process:
[StructLayout(LayoutKind.Explicit, Size = 716)] // size is 716 for x86
internal struct X86Context
{
[FieldOffset(0)]
internal uint ContextFlags;
[FieldOffset(184)]
internal IntPtr Eip;
}
Upvotes: 1