gpt4 book ai didi

c# - 32 位与 64 位版本类型的条件编译的首选方法

转载 作者:太空狗 更新时间:2023-10-29 23:16:58 24 4
gpt4 key购买 nike

某项任务要求我枚举系统中的所有句柄。到目前为止,我发现的最佳方法是使用文档不足的 NtQuerySystemInformation带有类参数的 SystemHandleInformation 标志。

到目前为止一切顺利。然而,在 64 位 Windows 上以 32 位模式运行它,所需的结构如下:

// 32-bit version
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct SYSTEM_HANDLE_INFORMATION
{
public uint ProcessID;
public byte ObjectTypeNumber;
public byte Flags;
public ushort Handle;
public uint Object_Pointer;
public UInt32 GrantedAccess;
}

对于 64 位 Windows(x64,我没有测试 Itanium,我希望它没有什么不同......),结构如下:

// 64-bit version
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct SYSTEM_HANDLE_INFORMATION
{
public int Reserved; // unknown, no documentation found
public uint ProcessID;
public byte ObjectTypeNumber;
public byte Flags;
public ushort Handle;
public long Object_Pointer;
public UInt32 GrantedAccess;
}

现在,我应该将 Object_Pointer 更改为 IntPtr。我一度希望我可以对 ProcessId 做同样的事情,有一个引用说这实际上是一个 HANDLE,它实际上是一个 64 位值。但是,Reserved 始终为零,因此我无法以相同的方式将其合并到 IntPtr 中。

这可能不是唯一发生这种情况的情况。我正在寻找处理此类差异的最佳实践方法:

  • 使用像 #if WIN32 这样的常量(在 IntPtr 的引用源中内部使用)在这里不起作用,除非我想维护单独的二进制文件。
  • 我可以编写两个不同的函数和两个不同的结构,创建一个包装器并在代码中使用 if IntPtr.Size ==4。这适用于外部函数,但不适用于类型。
  • 我可以重载 GetType,但我不确定它指向何处(可能有助于编码?)。
  • 还有什么事吗?

这些似乎都不理想,但到目前为止,唯一万无一失的方法似乎是用 if IsWin64() 语句来填充我的系统。我很乐意听到比我更好的方法。

最佳答案

就是这样 - SystemHandleInformation 的结构只为您提供 16 位 PID。您可以在 XP 及更高版本上使用 SystemExtendedHandleInformation。

  [StructLayout(LayoutKind.Sequential, Pack = 1)]
public class SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX
{
public IntPtr Object;
public IntPtr UniqueProcessId;
public IntPtr HandleValue;
public uint GrantedAccess;
public ushort CreatorBackTraceIndex;
public ushort ObjectTypeIndex;
public uint HandleAttributes;
public uint Reserved;
}

internal enum SYSTEM_INFORMATION_CLASS
{
SystemBasicInformation = 0,
SystemPerformanceInformation = 2,
SystemTimeOfDayInformation = 3,
SystemProcessInformation = 5,
SystemProcessorPerformanceInformation = 8,
SystemHandleInformation = 16,
SystemInterruptInformation = 23,
SystemExceptionInformation = 33,
SystemRegistryQuotaInformation = 37,
SystemLookasideInformation = 45,
SystemExtendedHandleInformation = 64,
}


[DllImport("ntdll.dll", CharSet=CharSet.Auto)]
private static extern int NtQuerySystemInformation(int InfoType, IntPtr lpStructure, int StructSize, out int returnLength);



public static void Main(string[] args)
{
Console.WriteLine(Environment.Is64BitProcess ? "x64" : "x32");
Console.WriteLine();

var infoSize = Marshal.SizeOf(typeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX));

Console.WriteLine("sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX): {0}", infoSize);
int allSize = 1000 * infoSize;
var buffer = Marshal.AllocHGlobal(allSize);
var status = NtQuerySystemInformation((int)SYSTEM_INFORMATION_CLASS.SystemExtendedHandleInformation, buffer, allSize, out allSize);
Console.WriteLine("status: {0:x}, return len: {1}", status, allSize);

if (status != 0)
{
allSize += 40 * infoSize;
Marshal.FreeHGlobal(buffer);
buffer = Marshal.AllocHGlobal(allSize);
status = NtQuerySystemInformation((int)SYSTEM_INFORMATION_CLASS.SystemExtendedHandleInformation, buffer, allSize, out allSize);
Console.WriteLine("status: {0:x}, return len: {1}", status, allSize);
}

Console.WriteLine();
var info = new SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX();
//for (var i = 0; i < allSize; i += infoSize)
for (var i = 0; i < Math.Min(allSize, 20 * infoSize); i+= infoSize) // for testing purpose only 20
{
Marshal.PtrToStructure(IntPtr.Add(buffer, i), info);
Console.WriteLine("{0,16:x}, {1,16:x}, {2,16:x}, {3,6:x}, {4,8:x}", info.Object.ToInt64(), info.UniqueProcessId.ToInt64(), info.HandleValue.ToInt64(), info.GrantedAccess, info.HandleAttributes);
}
Marshal.FreeHGlobal(buffer);
}

输出:

x32

sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX): 28
status: c0000004, return len: 1850052
status: 0, return len: 1850052

10219, 0, 6729b30, 4, 1fffff
0, 0, dfa0, 4, 2001f
0, 0, 8eb0, 4, f000f
0, 0, fca0, 4, 0
0, 0, 225b0, 4, 20019
0, 0, 98210, 4, f003f
0, 0, 6758e60, 4, 1f0001
0, 0, 98040, 4, 2001f
0, 0, 67534e0, 4, 1f0001
0, 0, 9c560, 4, 2001f
0, 0, 6834620, 4, 1fffff
0, 0, 99250, 4, f003f
0, 0, 9a7c0, 4, f003f
0, 0, 95380, 4, f003f
0, 0, 62d80, 4, f003f
0, 0, 15e580, 4, 20019
0, 0, 6f3b940, 4, 2a
0, 0, 20da30, 4, e
0, 0, 7b07a0, 4, 10
0, 0, 9af83a0, 4, 20019

x64

sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX): 40
status: c0000004, return len: 2647576
status: 0, return len: 2647856

10294, 0, fffffa8006729b30, 4, 4
70000001fffff, 0, fffff8a00000dfa0, 4, 8
2300000002001f, 0, fffff8a000008eb0, 4, c
30000000f000f, 0, fffff8a00000fca0, 4, 10
23000000000000, 0, fffff8a0000225b0, 4, 14
23000000020019, 0, fffff8a000098210, 4, 18
230000000f003f, 0, fffffa8006758e60, 4, 1c
240000001f0001, 0, fffff8a000098040, 4, 20
2300000002001f, 0, fffffa80067534e0, 4, 24
240000001f0001, 0, fffff8a00009c560, 4, 28
2300000002001f, 0, fffffa8006834620, 4, 2c
80000001fffff, 0, fffff8a000099250, 4, 30
230000000f003f, 0, fffff8a00009a7c0, 4, 34
230000000f003f, 0, fffff8a000095380, 4, 38
230000000f003f, 0, fffff8a000062d80, 4, 3c
230000000f003f, 0, fffff8a00015e580, 4, 40
23000000020019, 0, fffffa8006f3b940, 4, 44
700000000002a, 0, fffff8a00020da30, 4, 48
500000000000e, 0, fffff8a0007b07a0, 4, 4c
23000000000010, 0, fffff8a009af83a0, 4, 50

关于c# - 32 位与 64 位版本类型的条件编译的首选方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9992585/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com