avoid waiting too long if the clipboard message is blocked

Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
fufesou 2023-06-19 22:52:17 +08:00
parent 5a8c2d9cd0
commit 733e4236c4
7 changed files with 111 additions and 115 deletions

View File

@ -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

View File

@ -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<Box<Self>, 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 {

View File

@ -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 {

View File

@ -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;

View File

@ -212,7 +212,9 @@ impl<T: InvokeUiSession> Remote<T> {
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);
}
}

View File

@ -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);
}
}

View File

@ -406,7 +406,9 @@ impl<T: InvokeUiCM> IpcTaskRunner<T> {
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<CliprdrClientContext>| -> u32 {
clipboard::server_clip_file(context, conn_id, _clip)
@ -461,7 +463,9 @@ impl<T: InvokeUiCM> IpcTaskRunner<T> {
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)));
}
}