What is the range of a Windows HANDLE on a 64 bits application?
Asked Answered
T

3

34

On WinAPI, the HANDLE type is defined as a void*, thus on a 64 bit application the HANDLE value may range from 0 to 18446744073709551615. But is that true in practice? Does any documentation specify the integral range of such a HANDLE?

If for instance one wants to store this HANDLE as an int32_t on a 32 bit application that's completely fine, but on a 64 bit application the doubts sticks.

Tirrell answered 16/8, 2013 at 5:50 Comment(2)
Why do you need to store an HANDLE in an int? Sounds problematic. Consider a std::map<int, HANDLE>.Schnozzle
@Schnozzle That's related to POSIX file descriptors (that are int). I'm using C, so no STL, but yes, I could create a second handle system that points to a Windows HANDLE, But that would be slower than a simple cast, so I am here asking.Tirrell
S
33

MSDN states:

Interprocess Communication Between 32-bit and 64-bit Applications

64-bit versions of Windows use 32-bit handles for interoperability. When sharing a handle between 32-bit and 64-bit applications, only the lower 32 bits are significant, so it is safe to truncate the handle (when passing it from 64-bit to 32-bit) or sign-extend the handle (when passing it from 32-bit to 64-bit). Handles that can be shared include handles to user objects such as windows (HWND), handles to GDI objects such as pens and brushes (HBRUSH and HPEN), and handles to named objects such as mutexes, semaphores, and file handles.

It's also worth noting this comment added on that page:

The proper way to share such handles across process boundaries is by zero-extending 32 bits handles to 64 bits, or vice versa by truncating 64 bits handles to 32 bits discarding the top bits.

Note the distinction between "sign-extending" a handle versus "zero-extending" a handle.

Edit: Judging from discussion seen in a deleted answer to this question, I suppose that the significance of sign-extending a 32-bit handle to arrive at a 64-bit handle instead of zero-extending it is to retain proper treatment of the INVALID_HANDLE_VALUE value for a handle.

Sodom answered 8/4, 2015 at 22:52 Comment(4)
The comment you are relying on has zero authority. Follow the documentation.Laise
Also, you have enough reputation to see the highest voted answer on this page (the deletion of which is questionable) which covered this, and where MSalters also participated in the comments.Laise
@BenVoigt Currently I don't have this hability to see deleted answer (awesome, didn't know that) but It was the accepted answer before it has been deleted, any ideia for the reason? On the comments perhaps? Out of curiosity, undelete is possible if the author wants?Tirrell
@thelink2012: It shows that it was deleted by a (now retired) diamond moderator, but I can't see any reason for it, and already flagged for another moderator to take a look.Laise
R
3

I wish knew of where it is documented, but a colleague of mine insists that 64-bit HWND handles always fit in 32-bits. I've never seen a case where it is not true, but cannot speak to the future or where it is documented. Regarding other handles like say, HTREEITEM.... They are full 64-bits and I have been bit by the assumption that they too fit in 32 bits.

Reannareap answered 24/10, 2014 at 19:38 Comment(6)
"A colleague of mine" is not a reliable source of information, especially considering the official documentation (see accepted answer) disagrees.Arlie
@BoundaryImposition, Joe Willcoxson is correct. HTREEITEMs from 64-bit process can very easily be larger than 32-bits. This is stated also in the Microsoft docs, specifically that handles to OS objects will be 32-bit, and to sign extend, but this does not include other types of handles such as HTREEITEM. Maybe his colleague works for Microsoft. +1 for him mentioning this very useful aspect. I am staring at one that truncates 3 nibbles of the handle through SendMessage to a 64-bit process right now.Guglielmo
@Joe Willcoxson 32-bit and 64-bit Interoperability (MSDN): msdn.microsoft.com/en-us/library/windows/desktop/…Guglielmo
@Celess Thanks. That must be the article my colleague was quoting.Reannareap
"A colleague of mine" in this answer relates to the other claim, that "64-bit HWND handles always fit in 32-bits". I did not address the HTREEITEM claim.Arlie
HWNDs on 64-bit Windows always fit into 32 bits. This is explicitly documented under Interprocess Communication Between 32-bit and 64-bit Applications.Aminopyrine
G
0

To add to the previous correct answers, let me note that a HWND is also a valid handle across processes. Any other void* handle (like HBRUSH, HBITMAP etc) might be truncatable because only the lower 32 bits are significant all right, but it's not valid outside its own process.

For GDI objects it might work because these are actually indices (see https://learn.microsoft.com/en-us/previous-versions/ms810501(v=msdn.10))

Well, what happens here is that handles to GDI objects are internally implemented as offsets into a handle table that resides on the client side of the Win32 subsystem. (Remember that the Win32 client is a DLL that resides in a Win32-based application's address space and is called by the application.) In other words, handle tables are kept on a per-process basis, but they are not process-tagged. That means that a handle to an object that belongs to process A might coincidentally look like a valid handle in process B's context. Thus, a call to SelectObject from B might succeed, but B will actually have selected a totally different object into its device context—or worse, the right one. Selecting the right object may be worse because the objects might coincidentally be the same, so you think it works, but the application will behave weirdly later on. So, do not pass handles to GDI objects between applications; they have totally different meanings in different processes.

HWND is a documented exception to this.

Gilgamesh answered 30/5, 2019 at 20:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.