From 733e4236c4db494e3c9cac5ef25278cf6398afd3 Mon Sep 17 00:00:00 2001 From: fufesou Date: Mon, 19 Jun 2023 22:52:17 +0800 Subject: [PATCH] avoid waiting too long if the clipboard message is blocked Signed-off-by: fufesou --- libs/clipboard/src/cliprdr.h | 9 +- libs/clipboard/src/cliprdr.rs | 23 ++-- libs/clipboard/src/context_send.rs | 7 + libs/clipboard/src/windows/wf_cliprdr.c | 171 +++++++++++------------- src/client/io_loop.rs | 4 +- src/server/connection.rs | 4 +- src/ui_cm_interface.rs | 8 +- 7 files changed, 111 insertions(+), 115 deletions(-) diff --git a/libs/clipboard/src/cliprdr.h b/libs/clipboard/src/cliprdr.h index 2fa16e201..57cae5f8f 100644 --- a/libs/clipboard/src/cliprdr.h +++ b/libs/clipboard/src/cliprdr.h @@ -194,10 +194,11 @@ extern "C" // TODO: hide more members of clipboard context struct _cliprdr_client_context { - void *custom; - BOOL enableFiles; - BOOL enableOthers; + void *Custom; + BOOL EnableFiles; + BOOL EnableOthers; + BOOL IsStopped; pcCliprdrServerCapabilities ServerCapabilities; pcCliprdrClientCapabilities ClientCapabilities; pcCliprdrMonitorReady MonitorReady; @@ -219,7 +220,7 @@ extern "C" pcCliprdrClientFileContentsResponse ClientFileContentsResponse; pcCliprdrServerFileContentsResponse ServerFileContentsResponse; - UINT32 lastRequestedFormatId; + UINT32 LastRequestedFormatId; }; #ifdef __cplusplus diff --git a/libs/clipboard/src/cliprdr.rs b/libs/clipboard/src/cliprdr.rs index 2bc626536..e5bc3e7ef 100644 --- a/libs/clipboard/src/cliprdr.rs +++ b/libs/clipboard/src/cliprdr.rs @@ -449,9 +449,10 @@ pub type pcCliprdrServerFileContentsResponse = ::std::option::Option< #[repr(C)] #[derive(Debug, Clone)] pub struct _cliprdr_client_context { - pub custom: *mut ::std::os::raw::c_void, - pub enableFiles: BOOL, - pub enableOthers: BOOL, + pub Custom: *mut ::std::os::raw::c_void, + pub EnableFiles: BOOL, + pub EnableOthers: BOOL, + pub IsStopped: BOOL, pub ServerCapabilities: pcCliprdrServerCapabilities, pub ClientCapabilities: pcCliprdrClientCapabilities, pub MonitorReady: pcCliprdrMonitorReady, @@ -472,7 +473,7 @@ pub struct _cliprdr_client_context { pub ServerFileContentsRequest: pcCliprdrServerFileContentsRequest, pub ClientFileContentsResponse: pcCliprdrClientFileContentsResponse, pub ServerFileContentsResponse: pcCliprdrServerFileContentsResponse, - pub lastRequestedFormatId: UINT32, + pub LastRequestedFormatId: UINT32, } // #[link(name = "user32")] @@ -480,10 +481,7 @@ 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(crate) fn empty_cliprdr( - context: *mut CliprdrClientContext, - connID: UINT32, - ) -> BOOL; + pub(crate) fn empty_cliprdr(context: *mut CliprdrClientContext, connID: UINT32) -> BOOL; } #[derive(Error, Debug)] @@ -508,9 +506,10 @@ impl CliprdrClientContext { client_file_contents_response: pcCliprdrClientFileContentsResponse, ) -> Result, CliprdrError> { let context = CliprdrClientContext { - custom: 0 as *mut _, - enableFiles: if enable_files { TRUE } else { FALSE }, - enableOthers: if enable_others { TRUE } else { FALSE }, + Custom: 0 as *mut _, + EnableFiles: if enable_files { TRUE } else { FALSE }, + EnableOthers: if enable_others { TRUE } else { FALSE }, + IsStopped: FALSE, ServerCapabilities: None, ClientCapabilities: None, MonitorReady: None, @@ -531,7 +530,7 @@ impl CliprdrClientContext { ServerFileContentsRequest: None, ClientFileContentsResponse: client_file_contents_response, ServerFileContentsResponse: None, - lastRequestedFormatId: 0, + LastRequestedFormatId: 0, }; let mut context = Box::new(context); unsafe { diff --git a/libs/clipboard/src/context_send.rs b/libs/clipboard/src/context_send.rs index e847e3a72..a195850f2 100644 --- a/libs/clipboard/src/context_send.rs +++ b/libs/clipboard/src/context_send.rs @@ -24,6 +24,13 @@ impl ContextSend { CONTEXT_SEND.lock().unwrap().cm_enabled } + pub fn set_is_stopped() { + let _res = Self::proc(|c| { + c.IsStopped = TRUE; + 0 + }); + } + pub fn enable(enabled: bool, is_cm_side: bool, is_server_process: bool) { let mut lock = CONTEXT_SEND.lock().unwrap(); if enabled { diff --git a/libs/clipboard/src/windows/wf_cliprdr.c b/libs/clipboard/src/windows/wf_cliprdr.c index c17390cb4..8bfc69d93 100644 --- a/libs/clipboard/src/windows/wf_cliprdr.c +++ b/libs/clipboard/src/windows/wf_cliprdr.c @@ -1,3 +1,5 @@ +// to-do: TOO MANY compilation warnings. Fix them. + /** * FreeRDP: A Remote Desktop Protocol Implementation * Windows Clipboard Redirection @@ -136,11 +138,13 @@ typedef struct _FORMAT_IDS FORMAT_IDS; #define TAG "windows" #ifdef WITH_DEBUG_CLIPRDR -#define DEBUG_CLIPRDR(fmt, ...) fprintf(stderr, "DEBUG %s[%d] %s() " fmt "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__);fflush(stderr) +#define DEBUG_CLIPRDR(fmt, ...) \ + fprintf(stderr, "DEBUG %s[%d] %s() " fmt "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ + fflush(stderr) #else #define DEBUG_CLIPRDR(fmt, ...) \ - do \ - { \ + do \ + { \ } while (0) #endif @@ -1440,6 +1444,55 @@ static UINT cliprdr_send_format_list(wfClipboard *clipboard, UINT32 connID) return rc; } +UINT wait_response_event(wfClipboard *clipboard, HANDLE event, void *data) +{ + UINT rc = ERROR_INTERNAL_ERROR; + clipboard->context->IsStopped = FALSE; + // with default 3min timeout + for (int i = 0; i < 20 * 60 * 3; i++) + { + DWORD waitRes = WaitForSingleObject(event, 50); + if (waitRes == WAIT_TIMEOUT && clipboard->context->IsStopped == FALSE) + { + continue; + } + + if (clipboard->context->IsStopped == TRUE) + { + wf_do_empty_cliprdr(clipboard); + } + + if (waitRes != WAIT_OBJECT_0) + { + return ERROR_INTERNAL_ERROR; + } + + if (!ResetEvent(event)) + { + // NOTE: critical error here, crash may be better + rc = ERROR_INTERNAL_ERROR; + } + + if (data == NULL) + { + rc = ERROR_INTERNAL_ERROR; + } + + return rc; + } + + if (data != NULL) + { + if (!ResetEvent(event)) + { + // NOTE: critical error here, crash may be better + } + return ERROR_SUCCESS; + } + + return ERROR_INTERNAL_ERROR; +} + static UINT cliprdr_send_data_request(UINT32 connID, wfClipboard *clipboard, UINT32 formatId) { UINT rc; @@ -1460,44 +1513,7 @@ static UINT cliprdr_send_data_request(UINT32 connID, wfClipboard *clipboard, UIN return rc; } - // with default 3min timeout - for (int i = 0; i < 20 * 60 * 3; i++) - { - DWORD waitRes = WaitForSingleObject(clipboard->response_data_event, 50); - if (waitRes == WAIT_TIMEOUT) - { - continue; - } - - if (waitRes != WAIT_OBJECT_0) - { - return ERROR_INTERNAL_ERROR; - } - - if (!ResetEvent(clipboard->response_data_event)) - { - // NOTE: critical error here, crash may be better - rc = ERROR_INTERNAL_ERROR; - } - - if (!clipboard->hmem) - { - rc = ERROR_INTERNAL_ERROR; - } - - return rc; - } - - if (clipboard->hmem) - { - if (!ResetEvent(clipboard->response_data_event)) - { - // NOTE: critical error here, crash may be better - } - return ERROR_SUCCESS; - } - - return ERROR_INTERNAL_ERROR; + wait_response_event(clipboard, clipboard->response_data_event, clipboard->hmem); } UINT cliprdr_send_request_filecontents(wfClipboard *clipboard, UINT32 connID, const void *streamid, ULONG index, @@ -1525,43 +1541,7 @@ UINT cliprdr_send_request_filecontents(wfClipboard *clipboard, UINT32 connID, co return rc; } - // with default 3min timeout - for (int i = 0; i < 20 * 60 * 3; i++) - { - DWORD waitRes = WaitForSingleObject(clipboard->req_fevent, 50); - if (waitRes == WAIT_TIMEOUT) - { - continue; - } - - if (waitRes != WAIT_OBJECT_0) - { - return ERROR_INTERNAL_ERROR; - } - - if (!ResetEvent(clipboard->req_fevent)) - { - // NOTE: critical error here, crash may be better - rc = ERROR_INTERNAL_ERROR; - } - if (!clipboard->req_fdata) - { - rc = ERROR_INTERNAL_ERROR; - } - - return rc; - } - - if (clipboard->req_fdata) - { - if (!ResetEvent(clipboard->req_fevent)) - { - // NOTE: critical error here, crash may be better - } - return ERROR_SUCCESS; - } - - return ERROR_INTERNAL_ERROR; + return wait_response_event(clipboard, clipboard->req_fevent, clipboard->req_fdata); } static UINT cliprdr_send_response_filecontents( @@ -2069,8 +2049,8 @@ static BOOL wf_cliprdr_traverse_directory(wfClipboard *clipboard, WCHAR *Dir, si while (FindNextFileW(hFind, &FindFileData)) { // if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0 && - // wcscmp(FindFileData.cFileName, _T(".")) == 0 || - // wcscmp(FindFileData.cFileName, _T("..")) == 0) + // wcscmp(FindFileData.cFileName, _T(".")) == 0 || + // wcscmp(FindFileData.cFileName, _T("..")) == 0) if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0 && wcscmp(FindFileData.cFileName, L".") == 0 || wcscmp(FindFileData.cFileName, L"..") == 0) @@ -2123,7 +2103,8 @@ static UINT wf_cliprdr_send_client_capabilities(wfClipboard *clipboard) return ERROR_INTERNAL_ERROR; // Ignore ClientCapabilities for now - if (!clipboard->context->ClientCapabilities) { + if (!clipboard->context->ClientCapabilities) + { return CHANNEL_RC_OK; } @@ -2147,7 +2128,7 @@ static UINT wf_cliprdr_monitor_ready(CliprdrClientContext *context, const CLIPRDR_MONITOR_READY *monitorReady) { UINT rc; - wfClipboard *clipboard = (wfClipboard *)context->custom; + wfClipboard *clipboard = (wfClipboard *)context->Custom; if (!context || !monitorReady) return ERROR_INTERNAL_ERROR; @@ -2171,7 +2152,7 @@ static UINT wf_cliprdr_server_capabilities(CliprdrClientContext *context, { UINT32 index; CLIPRDR_CAPABILITY_SET *capabilitySet; - wfClipboard *clipboard = (wfClipboard *)context->custom; + wfClipboard *clipboard = (wfClipboard *)context->Custom; if (!context || !capabilities) return ERROR_INTERNAL_ERROR; @@ -2205,7 +2186,7 @@ static UINT wf_cliprdr_server_format_list(CliprdrClientContext *context, UINT32 i; formatMapping *mapping; CLIPRDR_FORMAT *format; - wfClipboard *clipboard = (wfClipboard *)context->custom; + wfClipboard *clipboard = (wfClipboard *)context->Custom; if (!clear_format_map(clipboard)) return ERROR_INTERNAL_ERROR; @@ -2241,7 +2222,7 @@ static UINT wf_cliprdr_server_format_list(CliprdrClientContext *context, if (file_transferring(clipboard)) { - if (context->enableFiles) + if (context->EnableFiles) { UINT32 *p_conn_id = (UINT32 *)calloc(1, sizeof(UINT32)); *p_conn_id = formatList->connID; @@ -2255,7 +2236,7 @@ static UINT wf_cliprdr_server_format_list(CliprdrClientContext *context, } else { - if (context->enableOthers) + if (context->EnableOthers) { if (!try_open_clipboard(clipboard->hwnd)) return CHANNEL_RC_OK; /* Ignore, other app holding clipboard */ @@ -2264,7 +2245,7 @@ static UINT wf_cliprdr_server_format_list(CliprdrClientContext *context, { // Modified: do not apply delayed rendering // for (i = 0; i < (UINT32)clipboard->map_size; i++) - // SetClipboardData(clipboard->format_mappings[i].local_format_id, NULL); + // SetClipboardData(clipboard->format_mappings[i].local_format_id, NULL); FORMAT_IDS *format_ids = (FORMAT_IDS *)calloc(1, sizeof(FORMAT_IDS)); format_ids->connID = formatList->connID; @@ -2399,7 +2380,7 @@ wf_cliprdr_server_format_data_request(CliprdrClientContext *context, goto exit; } - clipboard = (wfClipboard *)context->custom; + clipboard = (wfClipboard *)context->Custom; if (!clipboard) { @@ -2579,7 +2560,7 @@ wf_cliprdr_server_format_data_response(CliprdrClientContext *context, break; } - clipboard = (wfClipboard *)context->custom; + clipboard = (wfClipboard *)context->Custom; if (!clipboard) { rc = ERROR_INTERNAL_ERROR; @@ -2660,7 +2641,7 @@ wf_cliprdr_server_file_contents_request(CliprdrClientContext *context, goto exit; } - clipboard = (wfClipboard *)context->custom; + clipboard = (wfClipboard *)context->Custom; if (!clipboard) { @@ -2838,7 +2819,7 @@ exit: } // if (sRc != CHANNEL_RC_OK) - // return sRc; + // return sRc; return rc; } @@ -2863,7 +2844,7 @@ wf_cliprdr_server_file_contents_response(CliprdrClientContext *context, break; } - clipboard = (wfClipboard *)context->custom; + clipboard = (wfClipboard *)context->Custom; if (!clipboard) { rc = ERROR_INTERNAL_ERROR; @@ -2951,7 +2932,7 @@ BOOL wf_cliprdr_init(wfClipboard *clipboard, CliprdrClientContext *cliprdr) cliprdr->ServerFormatDataResponse = wf_cliprdr_server_format_data_response; cliprdr->ServerFileContentsRequest = wf_cliprdr_server_file_contents_request; cliprdr->ServerFileContentsResponse = wf_cliprdr_server_file_contents_response; - cliprdr->custom = (void *)clipboard; + cliprdr->Custom = (void *)clipboard; return TRUE; error: wf_cliprdr_uninit(clipboard, cliprdr); @@ -2963,7 +2944,7 @@ BOOL wf_cliprdr_uninit(wfClipboard *clipboard, CliprdrClientContext *cliprdr) if (!clipboard || !cliprdr) return FALSE; - cliprdr->custom = NULL; + cliprdr->Custom = NULL; /* discard all contexts in clipboard */ if (try_open_clipboard(clipboard->hwnd)) @@ -3038,7 +3019,7 @@ BOOL empty_cliprdr(CliprdrClientContext *context, UINT32 connID) return TRUE; } - clipboard = (wfClipboard *)context->custom; + clipboard = (wfClipboard *)context->Custom; if (!clipboard) { return FALSE; diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs index 0769d3bea..2957a0bc8 100644 --- a/src/client/io_loop.rs +++ b/src/client/io_loop.rs @@ -212,7 +212,9 @@ impl Remote { let file_transfer_enabled = self.handler.lc.read().unwrap().enable_file_transfer.v; let stop = is_stopping_allowed && !(server_file_transfer_enabled && file_transfer_enabled); log::debug!("Process clipboard message from system, stop: {}, is_stopping_allowed: {}, server_file_transfer_enabled: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, server_file_transfer_enabled, file_transfer_enabled); - if !stop { + if stop { + ContextSend::set_is_stopped(); + } else { allow_err!(peer.send(&crate::clipboard_file::clip_2_msg(clip)).await); } } diff --git a/src/server/connection.rs b/src/server/connection.rs index 968c2ed80..7ca6aac72 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -442,7 +442,9 @@ impl Connection { let file_transfer_enabled = conn.file_transfer_enabled(); let stop = is_stopping_allowed && !file_transfer_enabled; log::debug!("Process clipboard message from cm, stop: {}, is_stopping_allowed: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, file_transfer_enabled); - if !stop { + if stop { + clipboard::ContextSend::set_is_stopped(); + } else { allow_err!(conn.stream.send(&clip_2_msg(clip)).await); } } diff --git a/src/ui_cm_interface.rs b/src/ui_cm_interface.rs index 4c9d54153..067c22de1 100644 --- a/src/ui_cm_interface.rs +++ b/src/ui_cm_interface.rs @@ -406,7 +406,9 @@ impl IpcTaskRunner { let file_transfer_enabled = self.file_transfer_enabled; let stop = !is_stopping_allowed && !(is_clipboard_enabled && file_transfer_enabled); log::debug!("Process clipboard message from peer, stop: {}, is_stopping_allowed: {}, is_clipboard_enabled: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, is_clipboard_enabled, file_transfer_enabled); - if !stop { + if stop { + ContextSend::set_is_stopped(); + } else { let conn_id = self.conn_id; ContextSend::proc(|context: &mut Box| -> u32 { clipboard::server_clip_file(context, conn_id, _clip) @@ -461,7 +463,9 @@ impl IpcTaskRunner { let file_transfer_enabled = self.file_transfer_enabled; let stop = is_stopping_allowed && !(is_clipboard_enabled && file_transfer_enabled); log::debug!("Process clipboard message from cm, stop: {}, is_stopping_allowed: {}, is_clipboard_enabled: {}, file_transfer_enabled: {}", stop, is_stopping_allowed, is_clipboard_enabled, file_transfer_enabled); - if !stop { + if stop { + ContextSend::set_is_stopped(); + } else { allow_err!(self.tx.send(Data::ClipboardFile(_clip))); } }