基于体系结构的C#结构行为

时间:2016-05-18 06:09:45

标签: c# windows winapi struct

我有一个问题,关于根据编译架构将多个结构提供给方法, 或者正确布局Thread_Basic_Information结构,这样我就可以使用单个结构来实现相同的方法而不管x64 / x86(参见参考:https://msdn.microsoft.com/en-us/library/windows/desktop/ms684283(v=vs.85).aspx

我已经确认它在x86上工作正常,如果我手动切换结构,它也适用于x64。 但是,我最近试图将我的方法从只是复制粘贴大量功能改为试图回收我的代码。

我有一个非常困难的时间试图找到有关结构的精确信息,我可以在C#中使用它以使其兼容x68 / x64,或者将2个不同的结构输入到取决于架构的方法相同。

也许StructLayout包大小?但是我不熟悉那个属性。

我希望可能有一种方法可以通用,例如IntPtr.Size == 8然后使用64位结构,否则使用32位结构。但是,如果没有重复粘贴的代码,我希望可能有一种方法可以用泛型做到这一点吗?

代码:

用于创建线程的方法:

public IRemoteThread Create(IntPtr address, bool isStarted = true)
{
    //Create the thread
    var thr = ThreadHelper.CreateRemoteThread(Process.Handle, address, IntPtr.Zero, ThreadCreationFlags.Suspended)
    //Acquire desired information from the thread
    var ret = ThreadHelper.NtQueryInformationThread(thr);

    // Do other stuff 
    return result;
}

查询我们想要的线程信息的支持方法:

public static 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
    var ret = Nt.NtQueryInformationThread(threadHandle, 0, ref info, MarshalType<ThreadBasicInformation>.Size,
        IntPtr.Zero);

    // If the function succeeded
    if (ret == 0)
        return info;

    // Else, couldn't get the thread info, throws an exception
    throw new ApplicationException($"Couldn't get the information from the thread, error code '{ret}'.");
}

上述方法中使用的32位结构:

[StructLayout(LayoutKind.Sequential)]
public struct ThreadBasicInformation
{
    public uint ExitStatus;

    public IntPtr TebBaseAdress;

    public int ProcessId;

    public int ThreadId;

    public uint AffinityMask;

    public uint Priority;

    public uint BasePriority;
}   

相同结构的x64变体

[StructLayout(LayoutKind.Explicit)]
public struct ThreadBasicInformation64
{
    [FieldOffset(0)]
    public uint ExitStatus;

    [FieldOffset(8)]
    public IntPtr TebBaseAdress;

    [FieldOffset(16)]
    public int ProcessId;

    [FieldOffset(24)]
    public int ThreadId;

    [FieldOffset(32)]
    public uint AffinityMask;

    [FieldOffset(40)]
    public uint Priority;

    [FieldOffset(44)]
    public uint BasePriority;
}

编辑:

C声明我发现:

typedef LONG KPRIORITY; 

typedef struct _CLIENT_ID { 
   HANDLE UniqueProcess; 
   HANDLE UniqueThread; 
} CLIENT_ID; 
typedef CLIENT_ID *PCLIENT_ID; 

typedef struct _THREAD_BASIC_INFORMATION 
{ 
   NTSTATUS                ExitStatus; 
   PVOID                   TebBaseAddress; 
   CLIENT_ID               ClientId; 
   KAFFINITY               AffinityMask; 
   KPRIORITY               Priority; 
   KPRIORITY               BasePriority; 
} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION; 

1 个答案:

答案 0 :(得分:4)

你的问题的前提是错误的,因为你错误翻译了结构。正确翻译之后,您会发现可以在C#代码中使用结构的单个声明,编译器将为所有目标体系结构正确地进行布局。

[StructLayout(LayoutKind.Sequential)]
public struct CLIENT_ID 
{
    public IntPtr UniqueProcess;
    public IntPtr UniqueThread;
}

[StructLayout(LayoutKind.Sequential)]
public struct THREAD_BASIC_INFORMATION
{
    public int ExitStatus;
    public IntPtr TebBaseAdress;
    public CLIENT_ID ClientId;
    public IntPtr AffinityMask;
    public int Priority;
    public int BasePriority;
}