feat: clipboard files, audit (#12730)

Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
fufesou
2025-08-25 22:29:53 +08:00
committed by GitHub
parent f4fb31d7a1
commit 6381f43f01
9 changed files with 242 additions and 31 deletions

View File

@@ -381,6 +381,9 @@ pub type pcCliprdrTempDirectory = ::std::option::Option<
pub type pcNotifyClipboardMsg = ::std::option::Option<
unsafe extern "C" fn(connID: UINT32, msg: *const NOTIFICATION_MESSAGE) -> UINT,
>;
pub type pcHandleClipboardFiles = ::std::option::Option<
unsafe extern "C" fn(connID: UINT32, nFiles: size_t, fileNames: *mut *mut WCHAR) -> UINT,
>;
pub type pcCliprdrClientFormatList = ::std::option::Option<
unsafe extern "C" fn(
context: *mut CliprdrClientContext,
@@ -492,6 +495,7 @@ pub struct _cliprdr_client_context {
pub MonitorReady: pcCliprdrMonitorReady,
pub TempDirectory: pcCliprdrTempDirectory,
pub NotifyClipboardMsg: pcNotifyClipboardMsg,
pub HandleClipboardFiles: pcHandleClipboardFiles,
pub ClientFormatList: pcCliprdrClientFormatList,
pub ServerFormatList: pcCliprdrServerFormatList,
pub ClientFormatListResponse: pcCliprdrClientFormatListResponse,
@@ -529,6 +533,7 @@ impl CliprdrClientContext {
enable_others: bool,
response_wait_timeout_secs: u32,
notify_callback: pcNotifyClipboardMsg,
handle_clipboard_files: pcHandleClipboardFiles,
client_format_list: pcCliprdrClientFormatList,
client_format_list_response: pcCliprdrClientFormatListResponse,
client_format_data_request: pcCliprdrClientFormatDataRequest,
@@ -547,6 +552,7 @@ impl CliprdrClientContext {
MonitorReady: None,
TempDirectory: None,
NotifyClipboardMsg: notify_callback,
HandleClipboardFiles: handle_clipboard_files,
ClientFormatList: client_format_list,
ServerFormatList: None,
ClientFormatListResponse: client_format_list_response,
@@ -758,6 +764,9 @@ pub fn server_clip_file(
ret
);
}
ClipboardFile::Files { .. } => {
// unreachable
}
}
ret
}
@@ -967,6 +976,7 @@ pub fn create_cliprdr_context(
enable_others,
response_wait_timeout_secs,
Some(notify_callback),
Some(handle_clipboard_files),
Some(client_format_list),
Some(client_format_list_response),
Some(client_format_data_request),
@@ -1021,6 +1031,61 @@ extern "C" fn notify_callback(conn_id: UINT32, msg: *const NOTIFICATION_MESSAGE)
0
}
extern "C" fn handle_clipboard_files(
conn_id: UINT32,
n_files: size_t,
file_names: *mut *mut WCHAR,
) -> UINT {
if n_files == 0 {
return 0;
}
let data = unsafe {
let mut files = Vec::new();
use std::ffi::OsString;
use std::os::windows::ffi::OsStringExt;
for i in 0..n_files {
let file_name_ptr = *file_names.offset(i as isize);
if !file_name_ptr.is_null() {
let mut len = 0;
while *file_name_ptr.offset(len) != 0 {
len += 1;
}
let slice = std::slice::from_raw_parts(file_name_ptr, len as usize);
let os_string = OsString::from_wide(slice);
match os_string.to_str() {
Some(n) => match std::fs::metadata(n) {
Ok(meta) => {
if meta.is_file() {
files.push((n.to_owned(), meta.len()));
}
}
Err(e) => {
log::warn!(
"handle_clipboard_files: Failed to get metadata for file '{}': {}",
n,
e
);
}
},
None => {
log::warn!("handle_clipboard_files: Failed to convert file name to UTF-8");
}
};
}
}
if files.is_empty() {
return 0;
}
ClipboardFile::Files { files }
};
// no need to handle result here
allow_err!(send_data(conn_id as _, data));
0
}
extern "C" fn client_format_list(
_context: *mut CliprdrClientContext,
clip_format_list: *const CLIPRDR_FORMAT_LIST,