use windows::core::PWSTR;
use windows::Win32::Foundation::HMODULE;
use windows::Win32::System::LibraryLoader::GetModuleFileNameW;
use grob::{
FillBufferAction, GrowForStoredIsReturned, GrowStrategy, GrowableBuffer, RvIsSize, StackBuffer,
ToResult, WriteBuffer, CAPACITY_FOR_PATHS,
};
struct PrintNextCapacity {
wrapped: Box<dyn GrowStrategy>,
}
impl PrintNextCapacity {
fn new<GS>(wrapped: GS) -> Self
where
GS: GrowStrategy + 'static,
{
let wrapped = Box::new(wrapped);
Self { wrapped }
}
}
impl GrowStrategy for PrintNextCapacity {
fn next_capacity(&self, tries: usize, desired_capacity: u32) -> u32 {
let rv = self.wrapped.next_capacity(tries, desired_capacity);
println!(
"next_capacity(tries={}, desired_capacity={}) = {}",
tries, desired_capacity, rv
);
rv
}
}
fn common(initial_buffer: &mut dyn WriteBuffer) -> Result<(), Box<dyn std::error::Error>> {
let grow_strategy = PrintNextCapacity::new(GrowForStoredIsReturned::<0>::new());
let mut growable_buffer = GrowableBuffer::<u16, PWSTR>::new(initial_buffer, &grow_strategy);
loop {
let mut argument = growable_buffer.argument();
let rv = unsafe { GetModuleFileNameW(HMODULE(0), argument.as_mut_slice()) };
let rv: RvIsSize = rv.into();
let result = rv.to_result(&mut argument);
match result? {
FillBufferAction::Commit => {
argument.commit();
break;
}
FillBufferAction::Grow => {
argument.grow();
}
FillBufferAction::NoData => {
argument.commit_no_data();
break;
}
}
}
let frozen_buffer = growable_buffer.freeze();
let path = frozen_buffer.to_path_buf().unwrap();
println!("GetModuleFileNameW returned \"{}\"", path.display());
Ok(())
}
fn just_heap_buffer() -> Result<(), Box<dyn std::error::Error>> {
let mut initial_buffer = StackBuffer::<0>::new();
common(&mut initial_buffer)
}
fn start_with_stack_buffer() -> Result<(), Box<dyn std::error::Error>> {
let mut initial_buffer = StackBuffer::<CAPACITY_FOR_PATHS>::new();
common(&mut initial_buffer)
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!();
println!("Try with a reasonably sized stack buffer...");
start_with_stack_buffer()?;
println!();
println!("Try with a zero sized stack buffer and no floor...");
just_heap_buffer()?;
println!();
println!();
Ok(())
}