From 555ff0085adeb69651e9ccaefc269183d79d1a42 Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 22 Feb 2022 23:53:28 +0800 Subject: [PATCH] empty clipboard, debug crash & failed to copy Signed-off-by: fufesou --- libs/clipboard/src/cliprdr.rs | 6 ++--- libs/clipboard/src/lib.rs | 32 ++++++++++++++++++------- libs/clipboard/src/windows/wf_cliprdr.c | 24 +++++++++++++++++-- src/ui/cm.rs | 26 +++++++++++++++++--- 4 files changed, 72 insertions(+), 16 deletions(-) diff --git a/libs/clipboard/src/cliprdr.rs b/libs/clipboard/src/cliprdr.rs index f7233b6b5..184711595 100644 --- a/libs/clipboard/src/cliprdr.rs +++ b/libs/clipboard/src/cliprdr.rs @@ -496,10 +496,10 @@ pub struct _cliprdr_client_context { extern "C" { pub(crate) fn init_cliprdr(context: *mut CliprdrClientContext) -> BOOL; pub(crate) fn uninit_cliprdr(context: *mut CliprdrClientContext) -> BOOL; - pub fn empty_clipboard( + pub(crate) fn empty_cliprdr( context: *mut CliprdrClientContext, - server_conn_id: u32, - remote_conn_id: u32, + server_conn_id: UINT32, + remote_conn_id: UINT32, ) -> BOOL; } diff --git a/libs/clipboard/src/lib.rs b/libs/clipboard/src/lib.rs index 3ad696118..5e6998ce9 100644 --- a/libs/clipboard/src/lib.rs +++ b/libs/clipboard/src/lib.rs @@ -98,6 +98,20 @@ pub fn set_conn_enabled(server_conn_id: i32, remote_conn_id: i32, enabled: bool) } } +pub fn empty_clipboard( + context: &mut Box, + server_conn_id: i32, + remote_conn_id: i32, +) -> bool { + unsafe { + TRUE == cliprdr::empty_cliprdr( + &mut (**context), + server_conn_id as u32, + remote_conn_id as u32, + ) + } +} + pub fn server_clip_file( context: &mut Box, conn_id: ConnID, @@ -454,14 +468,16 @@ extern "C" fn check_enabled(server_conn_id: UINT32, remote_conn_id: UINT32) -> B server_conn_enabled = true; } - let mut remote_conn_enabled = false; - if remote_conn_id != 0 { - if let Some(true) = lock.remote_conn_enabled.get(&(remote_conn_id as i32)) { - remote_conn_enabled = true; - } - } else { - remote_conn_enabled = true; - } + // let mut remote_conn_enabled = false; + // remote connection is always enabled + // if remote_conn_id != 0 { + // if let Some(true) = lock.remote_conn_enabled.get(&(remote_conn_id as i32)) { + // remote_conn_enabled = true; + // } + // } else { + // remote_conn_enabled = true; + // } + let remote_conn_enabled = true; if server_conn_enabled && remote_conn_enabled { return TRUE; diff --git a/libs/clipboard/src/windows/wf_cliprdr.c b/libs/clipboard/src/windows/wf_cliprdr.c index c0d1b7af6..eb530917d 100644 --- a/libs/clipboard/src/windows/wf_cliprdr.c +++ b/libs/clipboard/src/windows/wf_cliprdr.c @@ -2792,6 +2792,23 @@ BOOL wf_cliprdr_uninit(wfClipboard *clipboard, CliprdrClientContext *cliprdr) cliprdr->custom = NULL; + /* discard all contexts in clipboard */ + if (try_open_clipboard(clipboard->hwnd)) + { + if (!EmptyClipboard()) + { + DEBUG_CLIPRDR("EmptyClipboard failed with 0x%x", GetLastError()); + } + if (!CloseClipboard()) + { + // critical error!!! + } + } + else + { + DEBUG_CLIPRDR("OpenClipboard failed with 0x%x", GetLastError()); + } + if (clipboard->hwnd) PostMessage(clipboard->hwnd, WM_QUIT, 0, 0); @@ -2810,6 +2827,9 @@ BOOL wf_cliprdr_uninit(wfClipboard *clipboard, CliprdrClientContext *cliprdr) if (clipboard->response_data_event) CloseHandle(clipboard->response_data_event); + if (clipboard->data_obj_mutex) + CloseHandle(clipboard->data_obj_mutex); + if (clipboard->req_fevent) CloseHandle(clipboard->req_fevent); @@ -2851,7 +2871,7 @@ BOOL empty_cliprdr(CliprdrClientContext *context, UINT32 server_conn_id, UINT32 return FALSE; } - while (0) + do { if (clipboard->data_obj != NULL) { @@ -2888,7 +2908,7 @@ BOOL empty_cliprdr(CliprdrClientContext *context, UINT32 server_conn_id, UINT32 // critical error!!! } rc = TRUE; - } + } while (0); if (!ReleaseMutex(clipboard->data_obj_mutex)) { diff --git a/src/ui/cm.rs b/src/ui/cm.rs index 6f38b22b9..31bd6b19b 100644 --- a/src/ui/cm.rs +++ b/src/ui/cm.rs @@ -1,7 +1,8 @@ use crate::ipc::{self, new_listener, Connection, Data}; #[cfg(windows)] use clipboard::{ - create_cliprdr_context, get_rx_clip_client, server_clip_file, set_conn_enabled, ConnID, + create_cliprdr_context, empty_clipboard, get_rx_clip_client, server_clip_file, + set_conn_enabled, ConnID, }; use hbb_common::{ allow_err, @@ -111,6 +112,7 @@ impl ConnectionManager { id: i32, data: Data, _tx_clip_file: &mpsc::UnboundedSender<(i32, ipc::ClipbaordFile)>, + _tx_clip_empty: &mpsc::UnboundedSender, write_jobs: &mut Vec, conn: &mut Connection, ) { @@ -197,6 +199,9 @@ impl ConnectionManager { } Data::ClipboardFileEnabled(enabled) => { set_conn_enabled(id, 0, enabled); + if !enabled { + allow_err!(_tx_clip_empty.send(id)); + } } _ => {} } @@ -339,10 +344,11 @@ impl sciter::EventHandler for ConnectionManager { #[tokio::main(flavor = "current_thread")] async fn start_ipc(cm: ConnectionManager) { let (tx_file, _rx_file) = mpsc::unbounded_channel::<(i32, ipc::ClipbaordFile)>(); + let (tx_clip_empty, _rx_clip_empty) = mpsc::unbounded_channel::(); #[cfg(windows)] let cm_clip = cm.clone(); #[cfg(windows)] - std::thread::spawn(move || start_clipboard_file(cm_clip, _rx_file)); + std::thread::spawn(move || start_clipboard_file(cm_clip, _rx_file, _rx_clip_empty)); match new_listener("_cm").await { Ok(mut incoming) => { @@ -352,6 +358,7 @@ async fn start_ipc(cm: ConnectionManager) { let mut stream = Connection::new(stream); let cm = cm.clone(); let tx_file = tx_file.clone(); + let tx_clip_empty = tx_clip_empty.clone(); tokio::spawn(async move { let mut conn_id: i32 = 0; let (tx, mut rx) = mpsc::unbounded_channel::(); @@ -372,11 +379,13 @@ async fn start_ipc(cm: ConnectionManager) { cm.add_connection(id, is_file_transfer, port_forward, peer_id, name, authorized, keyboard, clipboard, audio, file, tx.clone()); } Data::Close => { + allow_err!(tx_clip_empty.send(conn_id)); + set_conn_enabled(conn_id, 0, false); log::info!("cm ipc connection closed from connection request"); break; } _ => { - cm.handle_data(conn_id, data, &tx_file, &mut write_jobs, &mut stream).await; + cm.handle_data(conn_id, data, &tx_file, &tx_clip_empty, &mut write_jobs, &mut stream).await; } } } @@ -491,6 +500,7 @@ async fn start_pa() { async fn start_clipboard_file( cm: ConnectionManager, mut rx: mpsc::UnboundedReceiver<(i32, ipc::ClipbaordFile)>, + mut rx_clip_empty: mpsc::UnboundedReceiver, ) { let mut cliprdr_context = match create_cliprdr_context(true, false) { Ok(context) => { @@ -532,6 +542,16 @@ async fn start_clipboard_file( None => { break } + }, + server_conn_id = rx_clip_empty.recv() => match server_conn_id { + Some(server_conn_id) => { + if !empty_clipboard(&mut cliprdr_context, server_conn_id, 0) { + // log::error!("failed to empty clipboard"); + } + } + None => { + break + } } } }