Skip to content

Commit e1e1430

Browse files
committed
WinSock2 fallbacks
Add fallback implementations for `getaddrinfo` and `freeaddrinfo` These fall back to wship6.dll (NT4/2000) if available, or are impl'd via a translation of the header-only wspiapi.h implementations (IPv4 only, all Windows versions with WS2 support). Stub `SetHandleInformation`/`Socket::set_no_inherit` SetHandleInformation is exported by kernel32 on Win9X/ME, but is just stubbed, returning `ERROR_CALL_NOT_IMPLEMENTED`. Sockets are non-inheritable on these systems anyways, so we "fail successfully". https://www.betaarchive.com/wiki/index.php/Microsoft_KB_Archive/150523#MORE_INFORMATION SetHandleInformation is also unavailable on WinNT before 3.51. This is fine, however, because MS did not supply WinSock 2 for Windows NT before 4.0, so this function is not called.
1 parent 6770392 commit e1e1430

File tree

5 files changed

+648
-1
lines changed

5 files changed

+648
-1
lines changed

library/std/src/os/windows/io/socket.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ impl OwnedSocket {
8787

8888
// FIXME(strict_provenance_magic): we defined RawSocket to be a u64 ;-;
8989
#[allow(fuzzy_provenance_casts)]
90-
#[cfg(not(target_vendor = "uwp"))]
90+
#[cfg(not(any(target_vendor = "uwp", target_vendor = "rust9x")))]
9191
pub(crate) fn set_no_inherit(&self) -> io::Result<()> {
9292
cvt(unsafe {
9393
sys::c::SetHandleInformation(
@@ -98,6 +98,31 @@ impl OwnedSocket {
9898
})
9999
.map(drop)
100100
}
101+
#[allow(fuzzy_provenance_casts)]
102+
#[cfg(target_vendor = "rust9x")]
103+
pub(crate) fn set_no_inherit(&self) -> io::Result<()> {
104+
let res = cvt(unsafe {
105+
sys::c::SetHandleInformation(
106+
self.as_raw_socket() as sys::c::HANDLE,
107+
sys::c::HANDLE_FLAG_INHERIT,
108+
0,
109+
)
110+
})
111+
.map(drop);
112+
113+
match res {
114+
// SetHandleInformation is exported by kernel32 on Win9X/ME, but only returns
115+
// `ERROR_CALL_NOT_IMPLEMENTED`. Sockets are non-inheritable on these systems anyways,
116+
// so we "fail successfully" here.
117+
// https://www.betaarchive.com/wiki/index.php/Microsoft_KB_Archive/150523#MORE_INFORMATION
118+
119+
// SetHandleInformation is also unavailable on WinNT before 3.51. This is fine,
120+
// however, because MS did not supply WinSock 2 for Windows NT before 4.0, so this
121+
// function is not called.
122+
Err(e) if e.raw_os_error() == Some(sys::c::ERROR_CALL_NOT_IMPLEMENTED as i32) => Ok(()),
123+
res => res,
124+
}
125+
}
101126

102127
#[cfg(target_vendor = "uwp")]
103128
pub(crate) fn set_no_inherit(&self) -> io::Result<()> {

library/std/src/sys/pal/windows/c.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ use core::{mem, ptr};
1313
mod windows_sys;
1414
pub use windows_sys::*;
1515

16+
#[cfg(target_vendor = "rust9x")]
17+
pub(crate) mod wspiapi;
18+
1619
pub type WCHAR = u16;
1720

1821
pub const INVALID_HANDLE_VALUE: HANDLE = ::core::ptr::without_provenance_mut(-1i32 as _);
@@ -543,3 +546,63 @@ compat_fn_with_fallback! {
543546
FALSE
544547
}
545548
}
549+
550+
#[cfg(target_vendor = "rust9x")]
551+
compat_fn_with_fallback! {
552+
pub static KERNEL32: &CStr = c"kernel32" => { load: false, unicows: false };
553+
// >= NT 3.51+
554+
// https://learn.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-sethandleinformation
555+
pub fn SetHandleInformation(hobject: HANDLE, dwmask: u32, dwflags: HANDLE_FLAGS) -> BOOL {
556+
unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as u32); };
557+
FALSE
558+
}
559+
}
560+
561+
#[cfg(target_vendor = "rust9x")]
562+
mod ws2_32 {
563+
use super::*;
564+
compat_fn_with_fallback! {
565+
pub static WS2_32: &CStr = c"ws2_32" => { load: true, unicows: false };
566+
567+
// >= NT4/2000 with IPv6 Tech Preview
568+
// https://learn.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfo
569+
pub fn getaddrinfo(
570+
pnodename: PCSTR,
571+
pservicename: PCSTR,
572+
phints: *const ADDRINFOA,
573+
ppresult: *mut *mut ADDRINFOA,
574+
) -> i32 {
575+
unsafe { wship6::getaddrinfo(pnodename, pservicename, phints, ppresult) }
576+
}
577+
// >= NT4/2000 with IPv6 Tech Preview
578+
pub fn freeaddrinfo(paddrinfo: *const ADDRINFOA) -> () {
579+
unsafe { wship6::freeaddrinfo(paddrinfo) }
580+
}
581+
}
582+
}
583+
#[cfg(target_vendor = "rust9x")]
584+
pub use ws2_32::{freeaddrinfo, getaddrinfo};
585+
586+
#[cfg(target_vendor = "rust9x")]
587+
mod wship6 {
588+
use super::wspiapi::{wspiapi_freeaddrinfo, wspiapi_getaddrinfo};
589+
use super::{ADDRINFOA, PCSTR};
590+
591+
compat_fn_with_fallback! {
592+
pub static WSHIP6: &CStr = c"wship6" => { load: true, unicows: false };
593+
594+
// >= 2000 with IPv6 Tech Preview
595+
pub fn getaddrinfo(
596+
pnodename: PCSTR,
597+
pservicename: PCSTR,
598+
phints: *const ADDRINFOA,
599+
ppresult: *mut *mut ADDRINFOA,
600+
) -> i32 {
601+
unsafe { wspiapi_getaddrinfo(pnodename, pservicename, phints, ppresult) }
602+
}
603+
// >= 2000 with IPv6 Tech Preview
604+
pub fn freeaddrinfo(paddrinfo: *const ADDRINFOA)-> () {
605+
unsafe { wspiapi_freeaddrinfo(paddrinfo) }
606+
}
607+
}
608+
}

library/std/src/sys/pal/windows/c/bindings.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1978,11 +1978,15 @@ Windows.Win32.Networking.WinSock.FD_SET
19781978
Windows.Win32.Networking.WinSock.FIONBIO
19791979
Windows.Win32.Networking.WinSock.freeaddrinfo
19801980
Windows.Win32.Networking.WinSock.getaddrinfo
1981+
Windows.Win32.Networking.WinSock.gethostbyname
19811982
Windows.Win32.Networking.WinSock.getpeername
1983+
Windows.Win32.Networking.WinSock.getservbyname
19821984
Windows.Win32.Networking.WinSock.getsockname
19831985
Windows.Win32.Networking.WinSock.getsockopt
19841986
Windows.Win32.Networking.WinSock.IN6_ADDR
19851987
Windows.Win32.Networking.WinSock.IN_ADDR
1988+
Windows.Win32.Networking.WinSock.inet_addr
1989+
Windows.Win32.Networking.WinSock.inet_ntoa
19861990
Windows.Win32.Networking.WinSock.INVALID_SOCKET
19871991
Windows.Win32.Networking.WinSock.ioctlsocket
19881992
Windows.Win32.Networking.WinSock.IP_ADD_MEMBERSHIP

library/std/src/sys/pal/windows/c/windows_sys.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,13 @@ windows_targets::link!("ws2_32.dll" "system" fn closesocket(s : SOCKET) -> i32);
149149
windows_targets::link!("ws2_32.dll" "system" fn connect(s : SOCKET, name : *const SOCKADDR, namelen : i32) -> i32);
150150
windows_targets::link!("ws2_32.dll" "system" fn freeaddrinfo(paddrinfo : *const ADDRINFOA));
151151
windows_targets::link!("ws2_32.dll" "system" fn getaddrinfo(pnodename : PCSTR, pservicename : PCSTR, phints : *const ADDRINFOA, ppresult : *mut *mut ADDRINFOA) -> i32);
152+
windows_targets::link!("ws2_32.dll" "system" fn gethostbyname(name : PCSTR) -> *mut HOSTENT);
152153
windows_targets::link!("ws2_32.dll" "system" fn getpeername(s : SOCKET, name : *mut SOCKADDR, namelen : *mut i32) -> i32);
154+
windows_targets::link!("ws2_32.dll" "system" fn getservbyname(name : PCSTR, proto : PCSTR) -> *mut SERVENT);
153155
windows_targets::link!("ws2_32.dll" "system" fn getsockname(s : SOCKET, name : *mut SOCKADDR, namelen : *mut i32) -> i32);
154156
windows_targets::link!("ws2_32.dll" "system" fn getsockopt(s : SOCKET, level : i32, optname : i32, optval : PSTR, optlen : *mut i32) -> i32);
157+
windows_targets::link!("ws2_32.dll" "system" fn inet_addr(cp : PCSTR) -> u32);
158+
windows_targets::link!("ws2_32.dll" "system" fn inet_ntoa(r#in : IN_ADDR) -> PSTR);
155159
windows_targets::link!("ws2_32.dll" "system" fn ioctlsocket(s : SOCKET, cmd : i32, argp : *mut u32) -> i32);
156160
windows_targets::link!("ws2_32.dll" "system" fn listen(s : SOCKET, backlog : i32) -> i32);
157161
windows_targets::link!("ws2_32.dll" "system" fn recv(s : SOCKET, buf : PSTR, len : i32, flags : SEND_RECV_FLAGS) -> i32);
@@ -2667,6 +2671,15 @@ pub const HANDLE_FLAG_PROTECT_FROM_CLOSE: HANDLE_FLAGS = 2u32;
26672671
pub const HIGH_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 128u32;
26682672
pub type HLOCAL = *mut core::ffi::c_void;
26692673
pub type HMODULE = *mut core::ffi::c_void;
2674+
#[repr(C)]
2675+
#[derive(Clone, Copy)]
2676+
pub struct HOSTENT {
2677+
pub h_name: PSTR,
2678+
pub h_aliases: *mut *mut i8,
2679+
pub h_addrtype: i16,
2680+
pub h_length: i16,
2681+
pub h_addr_list: *mut *mut i8,
2682+
}
26702683
pub type HRESULT = i32;
26712684
pub const IDLE_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 64u32;
26722685
#[repr(C)]
@@ -2975,6 +2988,24 @@ pub const SECURITY_IMPERSONATION: FILE_FLAGS_AND_ATTRIBUTES = 131072u32;
29752988
pub const SECURITY_SQOS_PRESENT: FILE_FLAGS_AND_ATTRIBUTES = 1048576u32;
29762989
pub const SECURITY_VALID_SQOS_FLAGS: FILE_FLAGS_AND_ATTRIBUTES = 2031616u32;
29772990
pub type SEND_RECV_FLAGS = i32;
2991+
#[repr(C)]
2992+
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
2993+
#[derive(Clone, Copy)]
2994+
pub struct SERVENT {
2995+
pub s_name: PSTR,
2996+
pub s_aliases: *mut *mut i8,
2997+
pub s_proto: PSTR,
2998+
pub s_port: i16,
2999+
}
3000+
#[repr(C)]
3001+
#[cfg(target_arch = "x86")]
3002+
#[derive(Clone, Copy)]
3003+
pub struct SERVENT {
3004+
pub s_name: PSTR,
3005+
pub s_aliases: *mut *mut i8,
3006+
pub s_port: i16,
3007+
pub s_proto: PSTR,
3008+
}
29783009
pub type SET_FILE_POINTER_MOVE_METHOD = u32;
29793010
#[repr(C)]
29803011
#[derive(Clone, Copy)]

0 commit comments

Comments
 (0)