Description
Here is a list of type definitions from many different sources:
wintnt.h:
typedef void *HANDLE;
...
typedef PVOID HANDLE;
WinSock.h / WinSock2.h
typedef UINT_PTR SOCKET;
windows_sys::Win32::Foundation::HANDLE
windows_sys::Win32::Networking::WinSock::SOCKET
pub type HANDLE = isize;
pub type SOCKET = usize;
rust\library\std\src\sys\windows\c.rs:
rust\library\std\src\os\windows\c.rs:
pub type HANDLE = LPVOID;
pub type SOCKET = u64;
std::os::windows::raw::HANDLE:
std::os::windows::raw::SOCKET:
pub type HANDLE = *mut c_void;
pub type SOCKET = u64;
(I'm assuming this is talking about SOCKET, Microsoft's docs really hate linking these types.)
A socket handle can optionally be a file handle in Windows Sockets 2. A socket handle from a Winsock provider can be used with other non-Winsock functions such as ReadFile, WriteFile, ReadFileEx, and WriteFileEx.
So as part of strict_provenance I have been trying to make code more consistent / honest about values which are "pointers" vs "integers". These APIs are the bane of my existence.
- Everyone but windows_sys agrees a HANDLE is a pointer
- Everyone agrees SOCKET is an integer
- Micosoft's APIs then declare / require that it's ok to "pun" a SOCKET as a HANDLE
This made me very confused, and every time I checked a definition it was Slightly Different.
As far as I can tell both of these types are actually always integers (the kernel can't just hand userspace a pointer and then expect it to be a useful pointer if it's ever passed back to it, so it "must" be an integer and if you ask anyone with knowledge of the kernel they will say as much). Presumably HANDLE is just so ancient that Microsoft handn't figured out the Magic of UINT_PTR
yet.
So windows_sys is, in some sense, the one being Honest here. If these types are in fact always integers this mess is actually fine because under strict provenance it's "always ok for an integer to pretend to be a pointer For Fun". It's just, very hard to tell that this is what's Happening based on the surface definitions and types.