Skip to content

Commit 3e2e73c

Browse files
committed
Win: Add GetHostNameW fallback for win7 using gethostname
1 parent a3f2d5a commit 3e2e73c

4 files changed

Lines changed: 59 additions & 0 deletions

File tree

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,18 @@ compat_fn_with_fallback! {
227227
}
228228
}
229229

230+
#[cfg(target_vendor = "win7")]
231+
compat_fn_with_fallback! {
232+
pub static WS2_32: &CStr = c"ws2_32";
233+
234+
#[cfg(target_vendor = "win7")]
235+
pub fn GetHostNameW(name: PWSTR, namelen: i32) -> i32 {
236+
unsafe {
237+
crate::sys::winsock::hostname_fallback(name, namelen)
238+
}
239+
}
240+
}
241+
230242
cfg_select! {
231243
target_vendor = "uwp" => {
232244
windows_targets::link_raw_dylib!("ntdll.dll" "system" fn NtCreateFile(filehandle : *mut HANDLE, desiredaccess : FILE_ACCESS_RIGHTS, objectattributes : *const OBJECT_ATTRIBUTES, iostatusblock : *mut IO_STATUS_BLOCK, allocationsize : *const i64, fileattributes : FILE_FLAGS_AND_ATTRIBUTES, shareaccess : FILE_SHARE_MODE, createdisposition : NTCREATEFILE_CREATE_DISPOSITION, createoptions : NTCREATEFILE_CREATE_OPTIONS, eabuffer : *const core::ffi::c_void, ealength : u32) -> NTSTATUS);

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ CONSOLE_MODE
3333
CONSOLE_READCONSOLE_CONTROL
3434
CONTEXT
3535
CopyFileExW
36+
CP_ACP
3637
CP_UTF8
3738
CREATE_ALWAYS
3839
CREATE_BREAKAWAY_FROM_JOB
@@ -2170,6 +2171,7 @@ GetFileType
21702171
GETFINALPATHNAMEBYHANDLE_FLAGS
21712172
GetFinalPathNameByHandleW
21722173
GetFullPathNameW
2174+
gethostname
21732175
GetHostNameW
21742176
GetLastError
21752177
GetModuleFileNameW

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ windows_targets::link!("ws2_32.dll" "system" fn closesocket(s : SOCKET) -> i32);
130130
windows_targets::link!("ws2_32.dll" "system" fn connect(s : SOCKET, name : *const SOCKADDR, namelen : i32) -> i32);
131131
windows_targets::link!("ws2_32.dll" "system" fn freeaddrinfo(paddrinfo : *const ADDRINFOA));
132132
windows_targets::link!("ws2_32.dll" "system" fn getaddrinfo(pnodename : PCSTR, pservicename : PCSTR, phints : *const ADDRINFOA, ppresult : *mut *mut ADDRINFOA) -> i32);
133+
windows_targets::link!("ws2_32.dll" "system" fn gethostname(name : PSTR, namelen : i32) -> i32);
133134
windows_targets::link!("ws2_32.dll" "system" fn getpeername(s : SOCKET, name : *mut SOCKADDR, namelen : *mut i32) -> i32);
134135
windows_targets::link!("ws2_32.dll" "system" fn getsockname(s : SOCKET, name : *mut SOCKADDR, namelen : *mut i32) -> i32);
135136
windows_targets::link!("ws2_32.dll" "system" fn getsockopt(s : SOCKET, level : i32, optname : i32, optval : PSTR, optlen : *mut i32) -> i32);
@@ -444,6 +445,7 @@ pub struct CONTEXT_0_0 {
444445
pub type CONTEXT_FLAGS = u32;
445446
pub type COPYFILE_FLAGS = u32;
446447
pub type COPYPROGRESSROUTINE_PROGRESS = u32;
448+
pub const CP_ACP: u32 = 0u32;
447449
pub const CP_UTF8: u32 = 65001u32;
448450
pub const CREATE_ALWAYS: FILE_CREATION_DISPOSITION = 2u32;
449451
pub const CREATE_BREAKAWAY_FROM_JOB: PROCESS_CREATION_FLAGS = 16777216u32;

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

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,46 @@ where
7878
{
7979
cvt(f())
8080
}
81+
82+
#[cfg(target_vendor = "win7")]
83+
pub unsafe fn hostname_fallback(name: c::PWSTR, namelen: i32) -> i32 {
84+
assert!(namelen >= 1);
85+
86+
// The documentation of gethostname says that a buffer size of 256 is
87+
// always enough.
88+
let mut buffer = [const { mem::MaybeUninit::<u8>::uninit() }; 256];
89+
90+
// SAFETY: these parameters specify a valid, writable region of memory.
91+
unsafe {
92+
if c::gethostname(buffer.as_mut_ptr().cast(), buffer.len() as i32) == c::SOCKET_ERROR {
93+
return c::SOCKET_ERROR;
94+
}
95+
96+
// Subtract one to leave space for the null terminator, as MultiByteToWideChar doesn't terminate the output buffer
97+
// if the number of output characters is equal to the buffer length.
98+
let len = c::MultiByteToWideChar(
99+
c::CP_ACP,
100+
c::MB_ERR_INVALID_CHARS,
101+
buffer.as_mut_ptr().cast(),
102+
-1,
103+
name,
104+
namelen - 1,
105+
);
106+
107+
if len <= 0 {
108+
// GetHostNameW reports WSAEFAULT if the buffer is too small
109+
if c::GetLastError() == c::ERROR_INSUFFICIENT_BUFFER {
110+
c::SetLastError(c::WSAEFAULT as _);
111+
}
112+
return c::SOCKET_ERROR;
113+
}
114+
115+
// Ensure the output is always null terminated.
116+
// If MultiByteToWideChar has already written a null terminator, that null terminator will be included in len
117+
// and this will add a second one, but writing a zero is cheap enough to omit the length comparison.
118+
name.add(len as _).write(0);
119+
}
120+
121+
// Success
122+
0
123+
}

0 commit comments

Comments
 (0)