diff options
Diffstat (limited to 'library/std/src/sys/pal')
| -rw-r--r-- | library/std/src/sys/pal/windows/c/bindings.txt | 2 | ||||
| -rw-r--r-- | library/std/src/sys/pal/windows/c/windows_sys.rs | 2 | ||||
| -rw-r--r-- | library/std/src/sys/pal/windows/mod.rs | 1 | ||||
| -rw-r--r-- | library/std/src/sys/pal/windows/winsock.rs | 80 |
4 files changed, 85 insertions, 0 deletions
diff --git a/library/std/src/sys/pal/windows/c/bindings.txt b/library/std/src/sys/pal/windows/c/bindings.txt index abc1c19827f..9009aa09f48 100644 --- a/library/std/src/sys/pal/windows/c/bindings.txt +++ b/library/std/src/sys/pal/windows/c/bindings.txt @@ -2170,6 +2170,7 @@ GetFileType GETFINALPATHNAMEBYHANDLE_FLAGS GetFinalPathNameByHandleW GetFullPathNameW +GetHostNameW GetLastError GetModuleFileNameW GetModuleHandleA @@ -2270,6 +2271,7 @@ LPPROGRESS_ROUTINE LPPROGRESS_ROUTINE_CALLBACK_REASON LPTHREAD_START_ROUTINE LPWSAOVERLAPPED_COMPLETION_ROUTINE +lstrlenW M128A MAX_PATH MAXIMUM_REPARSE_DATA_BUFFER_SIZE diff --git a/library/std/src/sys/pal/windows/c/windows_sys.rs b/library/std/src/sys/pal/windows/c/windows_sys.rs index 989a1246650..98f277b3378 100644 --- a/library/std/src/sys/pal/windows/c/windows_sys.rs +++ b/library/std/src/sys/pal/windows/c/windows_sys.rs @@ -49,6 +49,7 @@ windows_targets::link!("kernel32.dll" "system" fn GetFileSizeEx(hfile : HANDLE, windows_targets::link!("kernel32.dll" "system" fn GetFileType(hfile : HANDLE) -> FILE_TYPE); windows_targets::link!("kernel32.dll" "system" fn GetFinalPathNameByHandleW(hfile : HANDLE, lpszfilepath : PWSTR, cchfilepath : u32, dwflags : GETFINALPATHNAMEBYHANDLE_FLAGS) -> u32); windows_targets::link!("kernel32.dll" "system" fn GetFullPathNameW(lpfilename : PCWSTR, nbufferlength : u32, lpbuffer : PWSTR, lpfilepart : *mut PWSTR) -> u32); +windows_targets::link!("ws2_32.dll" "system" fn GetHostNameW(name : PWSTR, namelen : i32) -> i32); windows_targets::link!("kernel32.dll" "system" fn GetLastError() -> WIN32_ERROR); windows_targets::link!("kernel32.dll" "system" fn GetModuleFileNameW(hmodule : HMODULE, lpfilename : PWSTR, nsize : u32) -> u32); windows_targets::link!("kernel32.dll" "system" fn GetModuleHandleA(lpmodulename : PCSTR) -> HMODULE); @@ -134,6 +135,7 @@ windows_targets::link!("ws2_32.dll" "system" fn getsockname(s : SOCKET, name : * windows_targets::link!("ws2_32.dll" "system" fn getsockopt(s : SOCKET, level : i32, optname : i32, optval : PSTR, optlen : *mut i32) -> i32); windows_targets::link!("ws2_32.dll" "system" fn ioctlsocket(s : SOCKET, cmd : i32, argp : *mut u32) -> i32); windows_targets::link!("ws2_32.dll" "system" fn listen(s : SOCKET, backlog : i32) -> i32); +windows_targets::link!("kernel32.dll" "system" fn lstrlenW(lpstring : PCWSTR) -> i32); windows_targets::link!("ws2_32.dll" "system" fn recv(s : SOCKET, buf : PSTR, len : i32, flags : SEND_RECV_FLAGS) -> i32); windows_targets::link!("ws2_32.dll" "system" fn recvfrom(s : SOCKET, buf : PSTR, len : i32, flags : i32, from : *mut SOCKADDR, fromlen : *mut i32) -> i32); windows_targets::link!("ws2_32.dll" "system" fn select(nfds : i32, readfds : *mut FD_SET, writefds : *mut FD_SET, exceptfds : *mut FD_SET, timeout : *const TIMEVAL) -> i32); diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index b7578b01584..18ab3498267 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -31,6 +31,7 @@ cfg_select! { pub use self::stack_overflow_uwp as stack_overflow; } } +pub mod winsock; /// Map a [`Result<T, WinError>`] to [`io::Result<T>`](crate::io::Result<T>). pub trait IoResult<T> { diff --git a/library/std/src/sys/pal/windows/winsock.rs b/library/std/src/sys/pal/windows/winsock.rs new file mode 100644 index 00000000000..b110a43ef3a --- /dev/null +++ b/library/std/src/sys/pal/windows/winsock.rs @@ -0,0 +1,80 @@ +use super::c; +use crate::ffi::c_int; +use crate::sync::atomic::Atomic; +use crate::sync::atomic::Ordering::{AcqRel, Relaxed}; +use crate::{io, mem}; + +static WSA_STARTED: Atomic<bool> = Atomic::<bool>::new(false); + +/// Checks whether the Windows socket interface has been started already, and +/// if not, starts it. +#[inline] +pub fn startup() { + if !WSA_STARTED.load(Relaxed) { + wsa_startup(); + } +} + +#[cold] +fn wsa_startup() { + unsafe { + let mut data: c::WSADATA = mem::zeroed(); + let ret = c::WSAStartup( + 0x202, // version 2.2 + &mut data, + ); + assert_eq!(ret, 0); + if WSA_STARTED.swap(true, AcqRel) { + // If another thread raced with us and called WSAStartup first then call + // WSACleanup so it's as though WSAStartup was only called once. + c::WSACleanup(); + } + } +} + +pub fn cleanup() { + // We don't need to call WSACleanup here because exiting the process will cause + // the OS to clean everything for us, which is faster than doing it manually. + // See #141799. +} + +/// Returns the last error from the Windows socket interface. +pub fn last_error() -> io::Error { + io::Error::from_raw_os_error(unsafe { c::WSAGetLastError() }) +} + +#[doc(hidden)] +pub trait IsMinusOne { + fn is_minus_one(&self) -> bool; +} + +macro_rules! impl_is_minus_one { + ($($t:ident)*) => ($(impl IsMinusOne for $t { + fn is_minus_one(&self) -> bool { + *self == -1 + } + })*) +} + +impl_is_minus_one! { i8 i16 i32 i64 isize } + +/// Checks if the signed integer is the Windows constant `SOCKET_ERROR` (-1) +/// and if so, returns the last error from the Windows socket interface. This +/// function must be called before another call to the socket API is made. +pub fn cvt<T: IsMinusOne>(t: T) -> io::Result<T> { + if t.is_minus_one() { Err(last_error()) } else { Ok(t) } +} + +/// A variant of `cvt` for `getaddrinfo` which return 0 for a success. +pub fn cvt_gai(err: c_int) -> io::Result<()> { + if err == 0 { Ok(()) } else { Err(last_error()) } +} + +/// Just to provide the same interface as sys/pal/unix/net.rs +pub fn cvt_r<T, F>(mut f: F) -> io::Result<T> +where + T: IsMinusOne, + F: FnMut() -> T, +{ + cvt(f()) +} |
