user10454073
user10454073

Reputation:

Is there a way to remove unused variables from a struct?

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

Answers (2)

Brian Clink
Brian Clink

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

Simon Mourier
Simon Mourier

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

Related Questions