Skip to content

Commit 40b1e40

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 e9d81a7 commit 40b1e40

File tree

3 files changed

+586
-3
lines changed

3 files changed

+586
-3
lines changed

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,27 @@ impl OwnedSocket {
9292
#[allow(fuzzy_provenance_casts)]
9393
#[cfg(not(target_vendor = "uwp"))]
9494
pub(crate) fn set_no_inherit(&self) -> io::Result<()> {
95-
cvt(unsafe {
95+
let res = cvt(unsafe {
9696
sys::c::SetHandleInformation(
9797
self.as_raw_socket() as sys::c::HANDLE,
9898
sys::c::HANDLE_FLAG_INHERIT,
9999
0,
100100
)
101101
})
102-
.map(drop)
102+
.map(drop);
103+
104+
match res {
105+
// SetHandleInformation is exported by kernel32 on Win9X/ME, but is just stubbed,
106+
// returning `ERROR_CALL_NOT_IMPLEMENTED`. Sockets are non-inheritable on these
107+
// systems anyways, so we "fail successfully" here.
108+
// https://www.betaarchive.com/wiki/index.php/Microsoft_KB_Archive/150523#MORE_INFORMATION
109+
110+
// SetHandleInformation is also unavailable on WinNT before 3.51. This is fine,
111+
// however, because MS did not supply WinSock 2 for Windows NT before 4.0, so this
112+
// function is not called.
113+
Err(e) if e.raw_os_error() == Some(sys::c::ERROR_CALL_NOT_IMPLEMENTED as i32) => Ok(()),
114+
res => res,
115+
}
103116
}
104117

105118
#[cfg(target_vendor = "uwp")]

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

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::ptr;
1313
use core::ffi::NonZero_c_ulong;
1414

1515
mod windows_sys;
16+
mod wspiapi;
1617
pub use windows_sys::*;
1718

1819
pub type DWORD = c_ulong;
@@ -265,7 +266,7 @@ pub unsafe fn getaddrinfo(
265266
hints: *const ADDRINFOA,
266267
res: *mut *mut ADDRINFOA,
267268
) -> c_int {
268-
windows_sys::getaddrinfo(node.cast::<u8>(), service.cast::<u8>(), hints, res)
269+
ws2_32::getaddrinfo(node.cast::<u8>(), service.cast::<u8>(), hints, res)
269270
}
270271

271272
cfg_if::cfg_if! {
@@ -398,6 +399,13 @@ compat_fn_with_fallback! {
398399
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
399400
FALSE
400401
}
402+
403+
// >= NT 3.51+
404+
// https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-sethandleinformation
405+
pub fn SetHandleInformation(hobject: HANDLE, dwmask: u32, dwflags: HANDLE_FLAGS) -> BOOL {
406+
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
407+
FALSE
408+
}
401409
}
402410

403411
compat_fn_lazy! {
@@ -646,3 +654,48 @@ pub struct WSADATA {
646654
pub iMaxUdpDg: u16,
647655
pub lpVendorInfo: PSTR,
648656
}
657+
658+
mod ws2_32 {
659+
use super::*;
660+
compat_fn_with_fallback! {
661+
pub static WS2_32: &CStr = c"ws2_32" => { load: true, unicows: false };
662+
663+
// >= NT4/2000 with IPv6 Tech Preview
664+
pub fn getaddrinfo(
665+
pnodename: PCSTR,
666+
pservicename: PCSTR,
667+
phints: *const ADDRINFOA,
668+
ppresult: *mut *mut ADDRINFOA,
669+
) -> i32 {
670+
wship6::getaddrinfo(pnodename, pservicename, phints, ppresult)
671+
}
672+
// >= NT4/2000 with IPv6 Tech Preview
673+
pub fn freeaddrinfo(paddrinfo: *const ADDRINFOA) -> () {
674+
wship6::freeaddrinfo(paddrinfo)
675+
}
676+
}
677+
}
678+
pub use ws2_32::freeaddrinfo;
679+
680+
mod wship6 {
681+
use super::wspiapi::{wspiapi_freeaddrinfo, wspiapi_getaddrinfo};
682+
use super::{ADDRINFOA, PCSTR};
683+
684+
compat_fn_with_fallback! {
685+
pub static WSHIP6: &CStr = c"wship6" => { load: true, unicows: false };
686+
687+
// >= 2000 with IPv6 Tech Preview
688+
pub fn getaddrinfo(
689+
pnodename: PCSTR,
690+
pservicename: PCSTR,
691+
phints: *const ADDRINFOA,
692+
ppresult: *mut *mut ADDRINFOA,
693+
) -> i32 {
694+
wspiapi_getaddrinfo(pnodename, pservicename, phints, ppresult)
695+
}
696+
// >= 2000 with IPv6 Tech Preview
697+
pub fn freeaddrinfo(paddrinfo: *const ADDRINFOA)-> () {
698+
wspiapi_freeaddrinfo(paddrinfo)
699+
}
700+
}
701+
}

0 commit comments

Comments
 (0)