Skip to content

Commit a9f6312

Browse files
committed
Switch to windows-bindgen
1 parent 953d763 commit a9f6312

File tree

6 files changed

+81
-31
lines changed

6 files changed

+81
-31
lines changed

Cargo.lock

Lines changed: 4 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,15 @@ cfg-if = "^1.0"
2626
libc = "^0.2"
2727

2828
[target.'cfg(target_os = "windows")'.dependencies]
29-
windows = { version = "^0.52", features = ["Win32_Foundation", "Win32_System_SystemInformation"] }
29+
windows-link = "0.1.1"
3030

3131
[dev-dependencies]
3232
version-sync = "0.9"
3333

34+
[target.'cfg(target_os = "windows")'.dev-dependencies]
35+
windows-bindgen = { version = "0.61" }
36+
similar-asserts = { version = "1.6.1" }
37+
3438
[package.metadata.docs.rs]
3539
features = ["set"]
3640
rustdoc-args = ["--cfg", "docsrs"]

src/windows/bindings.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#![allow(
2+
non_snake_case,
3+
non_upper_case_globals,
4+
non_camel_case_types,
5+
dead_code,
6+
clippy::all
7+
)]
8+
9+
windows_link::link!("kernel32.dll" "system" fn GetComputerNameExW(nametype : COMPUTER_NAME_FORMAT, lpbuffer : PWSTR, nsize : *mut u32) -> BOOL);
10+
windows_link::link!("kernel32.dll" "system" fn SetComputerNameExW(nametype : COMPUTER_NAME_FORMAT, lpbuffer : PCWSTR) -> BOOL);
11+
pub type BOOL = i32;
12+
pub type COMPUTER_NAME_FORMAT = i32;
13+
pub const ComputerNamePhysicalDnsHostname: COMPUTER_NAME_FORMAT = 5i32;
14+
pub type PCWSTR = *const u16;
15+
pub type PWSTR = *mut u16;

src/windows.rs renamed to src/windows/mod.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,58 +5,60 @@ use std::io;
55
#[cfg(feature = "set")]
66
use std::os::windows::ffi::OsStrExt;
77
use std::os::windows::ffi::OsStringExt;
8+
use std::ptr;
89

9-
use windows::core::PWSTR;
10-
use windows::Win32::System::SystemInformation::{
11-
ComputerNamePhysicalDnsHostname, GetComputerNameExW,
12-
};
10+
mod bindings;
11+
use bindings::{ComputerNamePhysicalDnsHostname, GetComputerNameExW, PWSTR};
1312

1413
pub fn get() -> io::Result<OsString> {
1514
let mut size = 0;
1615
unsafe {
1716
// Don't care much about the result here,
1817
// it is guaranteed to return an error,
1918
// since we passed the NULL pointer as a buffer
20-
let result = GetComputerNameExW(ComputerNamePhysicalDnsHostname, PWSTR::null(), &mut size);
21-
debug_assert!(result.is_err());
19+
let result =
20+
GetComputerNameExW(ComputerNamePhysicalDnsHostname, ptr::null_mut(), &mut size);
21+
debug_assert_eq!(result, 0);
2222
};
2323

2424
let mut buffer = Vec::with_capacity(size as usize);
2525

2626
let result = unsafe {
2727
GetComputerNameExW(
2828
ComputerNamePhysicalDnsHostname,
29-
PWSTR::from_raw(buffer.as_mut_ptr()),
29+
PWSTR::from(buffer.as_mut_ptr()),
3030
&mut size,
3131
)
3232
};
3333

3434
match result {
35-
Ok(_) => {
35+
0 => Err(io::Error::last_os_error()),
36+
_ => {
3637
unsafe {
3738
buffer.set_len(size as usize);
3839
}
3940

4041
Ok(OsString::from_wide(&buffer))
4142
}
42-
Err(e) => Err(io::Error::from_raw_os_error(e.code().0)),
4343
}
4444
}
4545

4646
#[cfg(feature = "set")]
4747
pub fn set(hostname: &OsStr) -> io::Result<()> {
48-
use windows::core::PCWSTR;
49-
use windows::Win32::System::SystemInformation::SetComputerNameExW;
48+
use bindings::{SetComputerNameExW, PCWSTR};
5049

5150
let mut buffer = hostname.encode_wide().collect::<Vec<_>>();
5251
buffer.push(0x00); // Appending the null terminator
5352

5453
let result = unsafe {
5554
SetComputerNameExW(
5655
ComputerNamePhysicalDnsHostname,
57-
PCWSTR::from_raw(buffer.as_ptr()),
56+
PCWSTR::from(buffer.as_ptr()),
5857
)
5958
};
6059

61-
result.map_err(|e| io::Error::from_raw_os_error(e.code().0))
60+
match result {
61+
0 => Err(io::Error::last_os_error()),
62+
_ => Ok(()),
63+
}
6264
}

tests/bindings.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
--out src/windows/bindings.rs
2+
--flat --sys --no-comment
3+
--filter
4+
ComputerNamePhysicalDnsHostname
5+
GetComputerNameExW
6+
SetComputerNameExW

tests/codegen.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#![cfg(windows)]
2+
3+
use std::fs;
4+
use std::process::Command;
5+
6+
use windows_bindgen::bindgen;
7+
8+
#[test]
9+
fn gen_bindings() {
10+
let output = "src/windows/bindings.rs";
11+
let existing = fs::read_to_string(output).unwrap();
12+
13+
bindgen(["--no-deps", "--etc", "tests/bindings.txt"]);
14+
let out = Command::new("rustfmt")
15+
.arg("--edition=2021")
16+
.arg(output)
17+
.output()
18+
.unwrap();
19+
20+
dbg!(String::from_utf8(out.stdout));
21+
22+
// Check the output is the same as before.
23+
// Depending on the git configuration the file may have been checked out with `\r\n` newlines or
24+
// with `\n`. Compare line-by-line to ignore this difference.
25+
let mut new = fs::read_to_string(output).unwrap();
26+
if existing.contains("\r\n") && !new.contains("\r\n") {
27+
new = new.replace("\n", "\r\n");
28+
} else if !existing.contains("\r\n") && new.contains("\r\n") {
29+
new = new.replace("\r\n", "\n");
30+
}
31+
32+
similar_asserts::assert_eq!(existing, new);
33+
if !new.lines().eq(existing.lines()) {
34+
panic!("generated file `{}` is changed.", output);
35+
}
36+
}

0 commit comments

Comments
 (0)