Is there a way to statically link to my binary so I don't need the WinDivert.dll with it? I don't understand the build system and linking, it's possible to statically link WinDivert here and here
EDIT: The vendored
feature should be enabled by default to make the library buildable and usable by default and reduce required intervention and setup by default, the alternative already requires many additional steps to download, extract, compile, and set an environment variable anyway, optionally disabling default features (vendored) is not a concern, you could also leave the logic the same which would allow providing WINDIVERT_PATH
even while vendored is still enabled, not requiring the user to disable or enable features at all.
Copying the built WinDivert.dll
to the binary directory relative to OUT_DIR
(up a few parent directories) by default would make binaries usable by default (in addition to the above change) without any additional intervention (setting an arbitrary WINDIVERT_PATH
environment variable).
EDIT2: Maybe a guard to uninstall the driver on drop/crash would be a good improvement.
Unrelated:
I created a build.rs
for anyone that wants to use the officially built and signed binaries easier
use std::{fs::File, path::Path};
use anyhow::Result;
use zip::ZipArchive;
fn main() -> Result<()> {
let out_dir = std::env::var("OUT_DIR")?;
let out_dir_path = Path::new(&out_dir);
let zip_name = "WinDivert-2.2.2-A.zip";
let zip_path = out_dir_path.join(zip_name);
if !zip_path.exists() {
let base_url = "https://reqrypt.org/download";
let file_url = format!("{base_url}/{zip_name}");
let mut response = reqwest::blocking::get(file_url)?;
let mut zip_file = File::create(&zip_path)?;
std::io::copy(&mut response, &mut zip_file)?;
}
let zip_file = File::open(&zip_path)?;
let mut zip_archive = ZipArchive::new(zip_file)?;
zip_archive.extract(out_dir_path)?;
let partial_file_names = [
"x64/WinDivert.dll",
"x64/WinDivert.lib",
"x64/WinDivert32.sys",
"x64/WinDivert64.sys",
"x64/windivertctl.exe", // Good for debugging
];
let full_file_names = zip_archive
.file_names()
.filter(|full_file_name| {
partial_file_names
.iter()
.any(|partial_file_name| full_file_name.ends_with(partial_file_name))
})
.collect::<Vec<_>>();
for fill_file_name in full_file_names {
let full_file_path = out_dir_path.join(fill_file_name);
let Some(partial_file_name) = fill_file_name.split('/').last() else {
continue
};
let Ok(mut old_file) = File::open(full_file_path) else {
continue
};
let Ok(mut new_file) = File::create(format!("{out_dir}/../../../{partial_file_name}")) else {
continue
};
if std::io::copy(&mut old_file, &mut new_file).is_err() {
println!("cargo:warning={old_file:?} -> {new_file:?} failed to copy")
}
}
Ok(())
}