You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Windows crate获取OLE剪贴板数据返回空缓冲区的问题

问题:通过OLE API读取剪贴板文件数据返回空内容,缓冲区长度却正确变化

我使用Rust已有一年半,但完全不熟悉Win32 API及大部分unsafe Rust语法。尝试通过OLE API获取剪贴板中的文件数据时,缓冲区长度会随复制文件数量增加而正确变化,但始终返回空内容。

相关代码

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}"),
    }
}

注:该代码仅在复制文件到剪贴板时生效,暂未实现其他格式

我知道当前代码可能存在内存泄漏,尚未完成资源清理工作。目前无法确定问题所在,怀疑是IStream::Read方法或调用GetData时传入的FORMATETC结构体参数有误,找不到相关示例代码,Win32 API文档也未能提供有效帮助。我使用的是windows crate,不确定是否winapi crate更合适。


内容的提问来源于stack exchange,提问作者Jamzy01

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 23:30:14