mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-04-14 14:21:29 +03:00
fix: win, file clipboard, try empty (#10609)
Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
@@ -107,6 +107,7 @@ pub enum ClipboardFile {
|
|||||||
stream_id: i32,
|
stream_id: i32,
|
||||||
requested_data: Vec<u8>,
|
requested_data: Vec<u8>,
|
||||||
},
|
},
|
||||||
|
TryEmpty,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MsgChannel {
|
struct MsgChannel {
|
||||||
@@ -226,6 +227,16 @@ fn send_data_to_channel(conn_id: i32, data: ClipboardFile) -> ResultType<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
pub fn send_data_exclude(conn_id: i32, data: ClipboardFile) {
|
||||||
|
use hbb_common::log;
|
||||||
|
for msg_channel in VEC_MSG_CHANNEL.read().unwrap().iter() {
|
||||||
|
if msg_channel.conn_id != conn_id {
|
||||||
|
allow_err!(msg_channel.sender.send(data.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "unix-file-copy-paste")]
|
#[cfg(feature = "unix-file-copy-paste")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn send_data_to_all(data: ClipboardFile) -> ResultType<()> {
|
fn send_data_to_all(data: ClipboardFile) -> ResultType<()> {
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
#![allow(deref_nullptr)]
|
#![allow(deref_nullptr)]
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
allow_err, send_data, ClipboardFile, CliprdrError, CliprdrServiceContext, ResultType,
|
send_data, send_data_exclude, ClipboardFile, CliprdrError, CliprdrServiceContext, ResultType,
|
||||||
ERR_CODE_INVALID_PARAMETER, ERR_CODE_SEND_MSG, ERR_CODE_SERVER_FUNCTION_NONE, VEC_MSG_CHANNEL,
|
ERR_CODE_INVALID_PARAMETER, ERR_CODE_SEND_MSG, ERR_CODE_SERVER_FUNCTION_NONE, VEC_MSG_CHANNEL,
|
||||||
};
|
};
|
||||||
use hbb_common::log;
|
use hbb_common::{allow_err, log};
|
||||||
use std::{
|
use std::{
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
ffi::{CStr, CString},
|
ffi::{CStr, CString},
|
||||||
@@ -643,6 +643,7 @@ pub fn server_clip_file(
|
|||||||
conn_id,
|
conn_id,
|
||||||
&format_list
|
&format_list
|
||||||
);
|
);
|
||||||
|
send_data_exclude(conn_id as _, ClipboardFile::TryEmpty);
|
||||||
ret = server_format_list(context, conn_id, format_list);
|
ret = server_format_list(context, conn_id, format_list);
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"server_format_list called, conn_id {}, return {}",
|
"server_format_list called, conn_id {}, return {}",
|
||||||
@@ -740,6 +741,11 @@ pub fn server_clip_file(
|
|||||||
ret
|
ret
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
ClipboardFile::TryEmpty => {
|
||||||
|
log::debug!("empty_clipboard called");
|
||||||
|
let ret = empty_clipboard(context, conn_id);
|
||||||
|
log::debug!("empty_clipboard called, conn_id {}, return {}", conn_id, ret);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -269,6 +269,7 @@ static UINT cliprdr_send_request_filecontents(wfClipboard *clipboard, UINT32 con
|
|||||||
DWORD positionlow, ULONG request);
|
DWORD positionlow, ULONG request);
|
||||||
|
|
||||||
static BOOL is_file_descriptor_from_remote();
|
static BOOL is_file_descriptor_from_remote();
|
||||||
|
static BOOL is_set_by_instance(wfClipboard *clipboard);
|
||||||
|
|
||||||
static void CliprdrDataObject_Delete(CliprdrDataObject *instance);
|
static void CliprdrDataObject_Delete(CliprdrDataObject *instance);
|
||||||
|
|
||||||
@@ -600,8 +601,11 @@ static CliprdrStream *CliprdrStream_New(UINT32 connID, ULONG index, void *pData,
|
|||||||
clipboard->req_fdata = NULL;
|
clipboard->req_fdata = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
|
instance->m_lSize.QuadPart =
|
||||||
|
((UINT64)instance->m_Dsc.nFileSizeHigh << 32) | instance->m_Dsc.nFileSizeLow;
|
||||||
success = TRUE;
|
success = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1745,8 +1749,7 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM
|
|||||||
DEBUG_CLIPRDR("info: WM_CLIPBOARDUPDATE");
|
DEBUG_CLIPRDR("info: WM_CLIPBOARDUPDATE");
|
||||||
// if (clipboard->sync)
|
// if (clipboard->sync)
|
||||||
{
|
{
|
||||||
if ((GetClipboardOwner() != clipboard->hwnd) &&
|
if (!is_set_by_instance(clipboard))
|
||||||
(S_FALSE == OleIsCurrentClipboard(clipboard->data_obj)))
|
|
||||||
{
|
{
|
||||||
if (clipboard->hmem)
|
if (clipboard->hmem)
|
||||||
{
|
{
|
||||||
@@ -2086,6 +2089,8 @@ static FILEDESCRIPTORW *wf_cliprdr_get_file_descriptor(WCHAR *file_name, size_t
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// to-do: use `fd->dwFlags = FD_ATTRIBUTES | FD_FILESIZE | FD_WRITESTIME | FD_PROGRESSUI`.
|
||||||
|
// We keep `fd->dwFlags = FD_ATTRIBUTES | FD_WRITESTIME | FD_PROGRESSUI` for compatibility.
|
||||||
// fd->dwFlags = FD_ATTRIBUTES | FD_FILESIZE | FD_WRITESTIME | FD_PROGRESSUI;
|
// fd->dwFlags = FD_ATTRIBUTES | FD_FILESIZE | FD_WRITESTIME | FD_PROGRESSUI;
|
||||||
fd->dwFlags = FD_ATTRIBUTES | FD_WRITESTIME | FD_PROGRESSUI;
|
fd->dwFlags = FD_ATTRIBUTES | FD_WRITESTIME | FD_PROGRESSUI;
|
||||||
fd->dwFileAttributes = GetFileAttributesW(file_name);
|
fd->dwFileAttributes = GetFileAttributesW(file_name);
|
||||||
@@ -2849,6 +2854,31 @@ wf_cliprdr_server_file_contents_request(CliprdrClientContext *context,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the clipboard is set by the instance, or the file descriptor is from remote,
|
||||||
|
// we should not process the request.
|
||||||
|
// Because this may be the following cases:
|
||||||
|
// 1. `A` -> `B`, `C`
|
||||||
|
// 2. Copy in `A`
|
||||||
|
// 3. Copy in `B`
|
||||||
|
// 4. Paste in `C`
|
||||||
|
// In this case, `C` should not get the file content from `A`. The clipboard is set by `B`.
|
||||||
|
//
|
||||||
|
// Or
|
||||||
|
// 1. `B` -> `A` -> `C`
|
||||||
|
// 2. Copy in `A`
|
||||||
|
// 2. Copy in `B`
|
||||||
|
// 3. Paste in `C`
|
||||||
|
// In this case, `C` should not get the file content from `A`. The clipboard is set by `B`.
|
||||||
|
//
|
||||||
|
// We can simply notify `C` to clear the clipboard when `A` received copy message from `B`,
|
||||||
|
// if connections are in the same process.
|
||||||
|
// But if connections are in different processes, it is not easy to notify the other process.
|
||||||
|
// So we just ignore the request from `C` in this case.
|
||||||
|
if (is_set_by_instance(clipboard) || is_file_descriptor_from_remote()) {
|
||||||
|
rc = ERROR_INTERNAL_ERROR;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
cbRequested = fileContentsRequest->cbRequested;
|
cbRequested = fileContentsRequest->cbRequested;
|
||||||
if (fileContentsRequest->dwFlags == FILECONTENTS_SIZE)
|
if (fileContentsRequest->dwFlags == FILECONTENTS_SIZE)
|
||||||
cbRequested = sizeof(UINT64);
|
cbRequested = sizeof(UINT64);
|
||||||
@@ -3089,6 +3119,14 @@ wf_cliprdr_server_file_contents_response(CliprdrClientContext *context,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL is_set_by_instance(wfClipboard *clipboard)
|
||||||
|
{
|
||||||
|
if (GetClipboardOwner() == clipboard->hwnd || S_OK == OleIsCurrentClipboard(clipboard->data_obj)) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL is_file_descriptor_from_remote()
|
BOOL is_file_descriptor_from_remote()
|
||||||
{
|
{
|
||||||
UINT fsid = 0;
|
UINT fsid = 0;
|
||||||
@@ -3175,7 +3213,7 @@ BOOL wf_cliprdr_uninit(wfClipboard *clipboard, CliprdrClientContext *cliprdr)
|
|||||||
/* discard all contexts in clipboard */
|
/* discard all contexts in clipboard */
|
||||||
if (try_open_clipboard(clipboard->hwnd))
|
if (try_open_clipboard(clipboard->hwnd))
|
||||||
{
|
{
|
||||||
if (is_file_descriptor_from_remote())
|
if (is_set_by_instance(clipboard) || is_file_descriptor_from_remote())
|
||||||
{
|
{
|
||||||
if (!EmptyClipboard())
|
if (!EmptyClipboard())
|
||||||
{
|
{
|
||||||
|
|||||||
Submodule libs/hbb_common updated: 49c6b24a7a...79f8ac2d68
@@ -134,6 +134,15 @@ pub fn clip_2_msg(clip: ClipboardFile) -> Message {
|
|||||||
})),
|
})),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
ClipboardFile::TryEmpty => Message {
|
||||||
|
union: Some(message::Union::Cliprdr(Cliprdr {
|
||||||
|
union: Some(cliprdr::Union::TryEmpty(CliprdrTryEmpty {
|
||||||
|
..Default::default()
|
||||||
|
})),
|
||||||
|
..Default::default()
|
||||||
|
})),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,6 +185,7 @@ pub fn msg_2_clip(msg: Cliprdr) -> Option<ClipboardFile> {
|
|||||||
requested_data: data.requested_data.into(),
|
requested_data: data.requested_data.into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Some(cliprdr::Union::TryEmpty(_)) => Some(ClipboardFile::TryEmpty),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user