#[cfg(windows)]
fn main() {
windows::run();
}
#[cfg(not(windows))]
fn main() {
eprintln!("win32_round_trip is Windows-only; nothing to demonstrate here.");
}
#[cfg(windows)]
mod windows {
use wtf_string::{Wtf16Str, Wtf16String};
#[link(name = "kernel32")]
unsafe extern "system" {
fn GetFullPathNameW(
lpfilename: *const u16,
nbufferlength: u32,
lpbuffer: *mut u16,
lpfilepart: *mut *mut u16,
) -> u32;
fn CompareStringOrdinal(
lpstring1: *const u16,
cchcount1: i32,
lpstring2: *const u16,
cchcount2: i32,
bignorecase: i32,
) -> i32;
}
const CSTR_LESS_THAN: i32 = 1;
const CSTR_EQUAL: i32 = 2;
const CSTR_GREATER_THAN: i32 = 3;
pub fn run() {
let input = Wtf16String::from(r"C:\Windows\System32\..\Temp");
println!("input : {input}");
match full_path(&input) {
Some(expanded) => println!("expanded: {expanded}"),
None => println!("expanded: <GetFullPathNameW failed>"),
}
compare(&Wtf16String::from("alpha"), &Wtf16String::from("beta"));
compare(&Wtf16String::from("beta"), &Wtf16String::from("alpha"));
compare(&Wtf16String::from("same"), &Wtf16String::from("same"));
let units: Vec<u16> = "borrowed".encode_utf16().collect();
let borrowed = Wtf16Str::from_units(&units);
println!(
"borrowed slice of {} units compares equal to itself: {}",
borrowed.len(),
ordinal(borrowed, borrowed) == CSTR_EQUAL
);
}
fn full_path(input: &Wtf16String) -> Option<Wtf16String> {
let needed = unsafe {
GetFullPathNameW(
input.as_terminated_ptr(),
0,
core::ptr::null_mut(),
core::ptr::null_mut(),
)
};
if needed == 0 {
return None;
}
let mut out = Wtf16String::with_capacity(needed as usize - 1);
let written = unsafe {
GetFullPathNameW(
input.as_terminated_ptr(),
needed,
out.as_mut_ptr(),
core::ptr::null_mut(),
)
};
if written == 0 || written >= needed {
unsafe { out.set_len_from_ffi(0) };
return None;
}
unsafe { out.set_len_from_ffi(written as usize) };
Some(out)
}
fn ordinal(a: &Wtf16Str, b: &Wtf16Str) -> i32 {
unsafe {
CompareStringOrdinal(
a.as_ptr(),
a.len() as i32,
b.as_ptr(),
b.len() as i32,
0, )
}
}
fn compare(a: &Wtf16String, b: &Wtf16String) {
let verdict = match ordinal(a, b) {
CSTR_LESS_THAN => "<",
CSTR_EQUAL => "==",
CSTR_GREATER_THAN => ">",
_ => "?(failed)",
};
println!("compare: {a} {verdict} {b}");
}
}