64位应用程序上的Windows HANDLE的范围是多少



在WinAPI上,HANDLE类型被定义为void*,因此在64位应用程序上,HANDLE值的范围可能从018446744073709551615。但在实践中这是真的吗?是否有任何文件规定了HANDLE的积分范围?

例如,如果想将这个HANDLE作为int32_t存储在32位应用程序上,这是完全可以的,但在64位应用程序中,疑虑依然存在。

MSDN状态:

32位和64位应用程序之间的进程间通信

64位版本的Windows使用32位句柄实现互操作性。在32位和64位应用程序之间共享句柄时,只有较低的32位是有效的,因此截断句柄是安全的(从64位传递到32位时)或符号扩展句柄(从32位传递到64位时)。可以共享的句柄包括用户对象的句柄,如windows(HWND)、GDI的句柄笔和画笔(HBRUSH和HPEN)等对象,以及命名对象,如互斥对象、信号量和文件句柄。

同样值得注意的是,该页面上添加了以下评论:

跨流程边界共享此类句柄的正确方法是零扩展32位句柄到64位,反之亦然64位处理32位,丢弃最高位。

请注意"符号扩展"句柄与"零扩展"句柄之间的区别。

编辑:从这个问题的删除答案中看到的讨论来看,我认为符号扩展32位句柄以获得64位句柄而不是零扩展的意义在于保留句柄的INVALID_handle_VALUE值的正确处理。

我希望知道它的记录位置,但我的一位同事坚持认为64位HWND句柄总是适合32位。我从来没有见过这样的情况:它不是真的,但无法讲述未来,也无法记录在案。关于其他手柄,如HTREEITEM。。。。它们是满64位的,我一直认为它们太适合32位了。

为了补充前面的正确答案,让我注意到HWND也是跨进程的有效句柄。任何其他void*句柄(如HBRUSH、HBITMAP等)都可能是可截断的,因为只有低32位是有效的,但它在自己的进程之外是无效的。

对于GDI对象,它可能会起作用,因为这些对象实际上是索引(请参阅https://learn.microsoft.com/en-us/previous-versions/ms810501(v=msdn.10))

这里发生的是GDI对象的句柄是内部的作为偏移量实现到驻留在客户端上的句柄表中Win32子系统的一侧。(请记住,Win32客户端是一个DLL驻留在基于Win32的应用程序的地址空间中由应用程序调用。)换句话说,句柄表保持在以每个流程为基础,但它们没有被流程标记。这意味着属于进程a的对象的句柄可能是巧合看起来像进程B上下文中的有效句柄。因此从B中选择Object可能会成功,但B实际上已经选择了完全不同的对象进入其设备上下文——或者更糟的是,正确一选择正确的对象可能会更糟,因为对象可能碰巧是一样的,所以你认为它有效,但应用程序以后会有奇怪的行为。所以,不要将句柄传递给GDI对象应用程序之间;它们在不同的过程。

HWND是一个记录在案的例外。

最新更新