On WinAPI, the HANDLE
type is defined as a void*
, thus on a 64 bit application the HANDLE
value may range from 0
to
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://docs.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.