use std::fs::{canonicalize, read_to_string, remove_file, File};
use std::io::Write;
use windows::Win32::Foundation::TRUE;
use windows::Win32::Storage::FileSystem::{ReplaceFileW, REPLACE_FILE_FLAGS};
use grob::{AsPCWSTR, WindowsPathString};
const TARGET: &str =
"This is a test. This is only a test. If the test works, this will be overwritten.";
const SOURCE: &str =
"This is a test. This is only a test. If the test works, this will be the new contents.";
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!();
let working_dir = canonicalize(".")?;
let target_path = working_dir.join("target.tmp");
let source_path = working_dir.join("source.tmp");
let backup_path = working_dir.join("backup.tmp");
let mut output = File::create(&target_path)?;
write!(output, "{}", TARGET)?;
drop(output);
let mut output = File::create(&source_path)?;
write!(output, "{}", SOURCE)?;
drop(output);
let rv = unsafe {
ReplaceFileW(
WindowsPathString::new(&target_path)?.as_param(),
WindowsPathString::new(&source_path)?.as_param(),
WindowsPathString::new(&backup_path)?.as_param(),
REPLACE_FILE_FLAGS(0),
None,
None,
)
};
if rv == TRUE {
println!("ReplaceFileW returned success.");
println!();
if !source_path.exists() {
println!(
"The source file, {}, does not exist as expected.",
source_path.display()
);
} else {
println!(
"The source file, {}, still exists. Something has gone wrong.",
source_path.display()
);
}
println!();
let t = read_to_string(&target_path)?;
if t == SOURCE {
println!(
"The contents of the source file, {}, replaced the target file, {}, as expected.",
source_path.display(),
target_path.display()
);
} else {
println!(
"The target file was supposed to contain...\n {}\n...but instead contains...\n {}\nSomething has gone wrong.",
SOURCE,
t);
}
println!();
let t = read_to_string(&backup_path)?;
if t == TARGET {
println!(
"The contents of the backup file, {}, are correct.",
backup_path.display()
);
} else {
println!(
"The backup file was supposed to contain...\n {}\n...but instead contains...\n {}\nSomething has gone wrong.",
TARGET,
t);
}
println!();
} else {
let loe = std::io::Error::last_os_error();
println!("ReplaceFileW failed. The error is...\n {:?}.", loe);
}
println!("Cleaning up.");
let _ = remove_file(&target_path);
let _ = remove_file(&source_path);
let _ = remove_file(&backup_path);
println!();
Ok(())
}