用于32位和64位版本类型的条件编译的首选方法 [英] Preferred approach for conditional compilation for 32-bit versus 64-bit versions of types

查看:153
本文介绍了用于32位和64位版本类型的条件编译的首选方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm required for a certain task to enumerate all handles in the system. The best approach I found so far is using the underdocumented NtQuerySystemInformation with the SystemHandleInformation flag for the class parameter.

到目前为止,一切都很好.但是,在64位Windows上以32位模式运行它时,所需的结构如下:

So far so good. However, running it in 32 bit mode on 64 bit Windows, the required structure is as follows:

// 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,我希望没有不同...),结构如下:

And for 64 bit Windows (x64, I didn't test Itanium, which I hope isn't different...), the structure is as follows:

// 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.

Now, I should change the Object_Pointer to an IntPtr. I hoped for a moment I could do the same with ProcessId, there was a reference saying this was actually a HANDLE which is actually a 64-bit value. However, Reserved is always zero, so I cannot merge that into an IntPtr the same way.

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

This is probably not the only scenario where this happens. I'm looking for a best practice way of dealing with such differences:

  • 除非我要维护单独的二进制文件,否则无法使用像#if WIN32这样的常量(在IntPtr的参考源内部使用)在这里无效.
  • 我可以编写两个不同的函数和两个不同的结构,创建一个包装器,并在代码中使用if IntPtr.Size ==4.这适用于外部函数,但不适用于类型.
  • 我可以超载GetType,但是我不确定那会导致什么(对编组有帮助吗?).
  • 还有什么?
  • Using a constant like #if WIN32 (used internally in the reference source of IntPtr) wouldn't work here unless I want to maintain separate binaries.
  • I can write two different functions and two different structs, create a wrapper and use if IntPtr.Size ==4 in code. This works for external functions, but doesn't work well with types.
  • I can overload GetType but I'm not sure where that leads (might help with Marshalling?).
  • Anything else?

这些都不是理想的,但是到目前为止,唯一简单的方法似乎是使用if IsWin64()语句为我的系统加油.我很想听到比我更好的方法.

None of these seem ideal, but so far, the only foolproof way seems to be to lard my system with if IsWin64() statements. I'd love to hear better approaches than mine.

推荐答案

鉴于IntPtr的大小不同,为什么不尝试以下操作:

Given IntPtr's size is different, why not try the following:

[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct SYSTEM_HANDLE_INFORMATION
{
    public IntPtr ProcessID;               // mask with 0xffffffff
    public byte ObjectTypeNumber;       
    public byte Flags;                  
    public ushort Handle;               
    public IntPtr Object_Pointer;          // again good for 32/64bit
    public UInt32 GrantedAccess;        
}

这应该适用于32位和64位不变.

This should work for both 32 and 64 bit unaltered.

这篇关于用于32位和64位版本类型的条件编译的首选方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆