use std::{ffi::OsString, io};
use windows_sys::Win32::System::SystemInformation::{
GetComputerNameExW, COMPUTER_NAME_FORMAT,
};
#[derive(Clone, Copy, Debug)]
#[non_exhaustive]
pub enum ComputerNameKind {
DnsDomain,
DnsFullyQualified,
DnsHostname,
NetBios,
PhysicalDnsDomain,
PhysicalDnsFullyQualified,
PhysicalDnsHostname,
PhysicalNetBios,
}
impl ComputerNameKind {
fn to_format(&self) -> COMPUTER_NAME_FORMAT {
use self::ComputerNameKind::*;
use windows_sys::Win32::System::SystemInformation;
match *self {
DnsDomain => SystemInformation::ComputerNameDnsDomain,
DnsFullyQualified => {
SystemInformation::ComputerNameDnsFullyQualified
}
DnsHostname => SystemInformation::ComputerNameDnsHostname,
NetBios => SystemInformation::ComputerNameNetBIOS,
PhysicalDnsDomain => {
SystemInformation::ComputerNamePhysicalDnsDomain
}
PhysicalDnsFullyQualified => {
SystemInformation::ComputerNamePhysicalDnsFullyQualified
}
PhysicalDnsHostname => {
SystemInformation::ComputerNamePhysicalDnsHostname
}
PhysicalNetBios => SystemInformation::ComputerNamePhysicalNetBIOS,
}
}
}
pub fn get_computer_name(kind: ComputerNameKind) -> io::Result<OsString> {
use std::os::windows::ffi::OsStringExt;
let format = kind.to_format();
let mut len1 = 0;
let _ =
unsafe { GetComputerNameExW(format, std::ptr::null_mut(), &mut len1) };
let len = match usize::try_from(len1) {
Ok(len) => len,
Err(_) => {
return Err(io::Error::new(
io::ErrorKind::Other,
"GetComputerNameExW buffer length overflowed usize",
))
}
};
let mut buf = vec![0; len];
let mut len2 = len1;
let rc =
unsafe { GetComputerNameExW(format, buf.as_mut_ptr(), &mut len2) };
if rc == 0 {
return Err(io::Error::last_os_error());
}
if len1 <= len2 {
let msg = format!(
"GetComputerNameExW buffer length mismatch, \
expected length strictly less than {} \
but got {}",
len1, len2,
);
return Err(io::Error::new(io::ErrorKind::Other, msg));
}
let len = usize::try_from(len2).expect("len1 fits implies len2 fits");
Ok(OsString::from_wide(&buf[..len]))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn itworks() {
let kinds = [
ComputerNameKind::DnsDomain,
ComputerNameKind::DnsFullyQualified,
ComputerNameKind::DnsHostname,
ComputerNameKind::NetBios,
ComputerNameKind::PhysicalDnsDomain,
ComputerNameKind::PhysicalDnsFullyQualified,
ComputerNameKind::PhysicalDnsHostname,
ComputerNameKind::PhysicalNetBios,
];
for kind in kinds {
let result = get_computer_name(kind);
let name = result.unwrap();
println!("{kind:?}: {name:?}");
}
}
}