use std::vec::Vec;
use windows_core::{PCWSTR, Param, ParamValue};
use crate::Wtf16String;
fn as_callee_ptr<P: Param<PCWSTR>>(param: P) -> *const u16 {
let value = unsafe { param.param() };
match value {
ParamValue::Owned(pcwstr) => pcwstr.0,
ParamValue::Borrowed(pcwstr) => pcwstr.0,
}
}
#[cfg(windows)]
#[link(name = "kernel32")]
unsafe extern "system" {
fn lstrlenW(lpstring: *const u16) -> i32;
}
#[test]
fn param_hands_over_the_terminated_pointer_itself() {
let owned = Wtf16String::from("zero-conversion");
assert_eq!(
as_callee_ptr(&owned),
owned.as_terminated_ptr(),
"the callee must receive the string's own terminated pointer"
);
}
#[test]
fn param_pointer_is_nul_terminated_and_reads_back() {
for s in [
"",
"a",
"C:\\Windows\\System32",
"caf\u{E9} \u{65E5}\u{672C}",
] {
let owned = Wtf16String::from(s);
let ptr = as_callee_ptr(&owned);
let mut read = Vec::new();
let mut i = 0isize;
loop {
let unit = unsafe { *ptr.offset(i) };
if unit == 0 {
break;
}
read.push(unit);
i += 1;
}
assert_eq!(
read,
owned.as_units(),
"{s:?} round-trips through the pointer"
);
}
}
#[test]
fn param_survives_a_real_wide_win32_call() {
#[cfg(windows)]
for s in ["", "a", "a longer path-like value"] {
let owned = Wtf16String::from(s);
let ptr = as_callee_ptr(&owned);
let len = unsafe { lstrlenW(ptr) };
assert_eq!(len as usize, owned.len(), "lstrlenW disagrees for {s:?}");
}
}
#[test]
fn param_truncates_at_an_interior_nul_like_any_c_string() {
let owned = Wtf16String::from("visible\u{0}hidden");
assert!(owned.has_interior_nul());
let ptr = as_callee_ptr(&owned);
#[cfg(windows)]
{
let len = unsafe { lstrlenW(ptr) };
assert_eq!(len as usize, "visible".len(), "the callee stops at the NUL");
assert!(
(len as usize) < owned.len(),
"the truncation is what makes has_interior_nul worth checking"
);
}
#[cfg(not(windows))]
let _ = ptr;
}