Why is getting ole clipboard data returning an empty buffer using the windows crate

95 views Asked by At

So I'm entirely new to using the win32 api, and honestly most of unsafe rust despite the fact I've been using rust for like a year and a half. I'm trying to get copied files clipboard data use the ole api, but it keeps returning an empty buffer. Clearly, I am correctly getting the buffer length as the buffer length increases as I copy more files, but the buffer keeps returning empty.

enter image description here

println!("Syncing from local clipboard");

unsafe {
    match OleGetClipboard() {
        Ok(clipboard_data_handle) => {
            if
                let Ok(raw_clipboard_data_handle) = clipboard_data_handle.GetData(
                    &(FORMATETC {
                        cfFormat: 15 /* CF_HDROP */,
                        ptd: std::ptr::null_mut(),
                        dwAspect: 1 /* DVASPECT_CONTENT */,
                        lindex: -1,
                        tymed: 4 /* TYMED_ISTREAM */,
                    })
                )
            {
                match ManuallyDrop::into_inner(raw_clipboard_data_handle.u.pstm) {
                    Some(raw_clipboard_data_stream) => {
                        let mut raw_clipboard_data_stream_stat = STATSTG::default();

                        raw_clipboard_data_stream
                            .Stat(
                                &mut raw_clipboard_data_stream_stat,
                                STATFLAG(1 /* STATFLAG_NONAME */)
                            )
                            .expect(
                                "Failet to get raw clipboard data stream, couldn't get statstg of data istream"
                            );

                        let mut raw_clipboard_data =
                            vec![0u8; raw_clipboard_data_stream_stat.cbSize as usize];
                        let mut actual_bytes_read = 0u32;

                        raw_clipboard_data_stream
                            .Read(
                                raw_clipboard_data.as_mut_ptr().cast(),
                                raw_clipboard_data_stream_stat.cbSize as u32,
                                Some(&mut actual_bytes_read)
                            )
                            .ok()
                            .unwrap_or_else(|err|
                                eprintln!(
                                    "Failed to get raw clipboard data stream, reading from istream caused the following error: {err}"
                                )
                            );

                        println!(
                            "{} {} {:?}",
                            raw_clipboard_data_stream_stat.cbSize as u32,
                            actual_bytes_read,
                            raw_clipboard_data
                        );
                    }
                    None =>
                        eprintln!(
                            "Failed to get raw clipboard data stream, it doesn't exist"
                        ),
                }
            }
        }
        Err(err) => eprintln!("Failed to get ole clipboard {err}"),
    }
}

Side note, if you want to try this, it will only work when you copy files to your clipboard, I'm not trying to implement any other formats

And I know that this code is probably causing memory leaks, it's unfinished and I haven't taken the time to implement properly cleaning up my operations just yet, I'm getting there.

I really don't know what I'm doing wrong, I've been fumbling around trying to fix this, but I can't really find like any example code of reading from the clipboard using ole on the internet, and the win32 Api docs weren't much help. The function that is slipping up is the IStream::Read method: https://learn.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-istream_read and https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/System/Com/struct.IStream.html#method.Read, but the issue may be in the arguments I pass in the FORMATETC struct when I call GetData on the clipboard handle, I'm really not sure.

I am using the windows crate aswell, https://crates.io/crates/windows, not sure if something like winapi is a better choice, but as an amateur to the winapi and lower level rust all round, it looked like the easiest option to me, even though I might be wrong lol.

0

There are 0 answers