diff --git a/libs/clipboard/src/cliprdr.h b/libs/clipboard/src/cliprdr.h index 9d56049ee..2edb473fd 100644 --- a/libs/clipboard/src/cliprdr.h +++ b/libs/clipboard/src/cliprdr.h @@ -150,6 +150,15 @@ extern "C" typedef struct _cliprdr_client_context CliprdrClientContext; + struct _NOTIFICATION_MESSAGE + { + // 0 - info, 1 - warning, 2 - error + UINT32 type; + char *msg; + char *details; + }; + typedef struct _NOTIFICATION_MESSAGE NOTIFICATION_MESSAGE; + typedef UINT (*pcCliprdrServerCapabilities)(CliprdrClientContext *context, const CLIPRDR_CAPABILITIES *capabilities); typedef UINT (*pcCliprdrClientCapabilities)(CliprdrClientContext *context, @@ -158,6 +167,9 @@ extern "C" const CLIPRDR_MONITOR_READY *monitorReady); typedef UINT (*pcCliprdrTempDirectory)(CliprdrClientContext *context, const CLIPRDR_TEMP_DIRECTORY *tempDirectory); + + typedef UINT (*pcNotifyClipboardMsg)(const NOTIFICATION_MESSAGE *msg); + typedef UINT (*pcCliprdrClientFormatList)(CliprdrClientContext *context, const CLIPRDR_FORMAT_LIST *formatList); typedef UINT (*pcCliprdrServerFormatList)(CliprdrClientContext *context, @@ -204,6 +216,7 @@ extern "C" pcCliprdrClientCapabilities ClientCapabilities; pcCliprdrMonitorReady MonitorReady; pcCliprdrTempDirectory TempDirectory; + pcNotifyClipboardMsg NotifyClipboardMsg; pcCliprdrClientFormatList ClientFormatList; pcCliprdrServerFormatList ServerFormatList; pcCliprdrClientFormatListResponse ClientFormatListResponse; @@ -229,4 +242,3 @@ extern "C" #endif #endif // WF_CLIPRDR_H__ - diff --git a/libs/clipboard/src/cliprdr.rs b/libs/clipboard/src/cliprdr.rs index 6bbb27ca0..60475f72b 100644 --- a/libs/clipboard/src/cliprdr.rs +++ b/libs/clipboard/src/cliprdr.rs @@ -324,6 +324,14 @@ pub struct _CLIPRDR_FILE_CONTENTS_RESPONSE { } pub type CLIPRDR_FILE_CONTENTS_RESPONSE = _CLIPRDR_FILE_CONTENTS_RESPONSE; pub type CliprdrClientContext = _cliprdr_client_context; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct _NOTIFICATION_MESSAGE { + pub r#type: UINT32, // 0 - info, 1 - warning, 2 - error + pub msg: *const BYTE, + pub details: *const BYTE, +} +pub type NOTIFICATION_MESSAGE = _NOTIFICATION_MESSAGE; pub type pcCliprdrServerCapabilities = ::std::option::Option< unsafe extern "C" fn( context: *mut CliprdrClientContext, @@ -348,6 +356,8 @@ pub type pcCliprdrTempDirectory = ::std::option::Option< tempDirectory: *const CLIPRDR_TEMP_DIRECTORY, ) -> UINT, >; +pub type pcNotifyClipboardMsg = + ::std::option::Option UINT>; pub type pcCliprdrClientFormatList = ::std::option::Option< unsafe extern "C" fn( context: *mut CliprdrClientContext, @@ -458,6 +468,7 @@ pub struct _cliprdr_client_context { pub ClientCapabilities: pcCliprdrClientCapabilities, pub MonitorReady: pcCliprdrMonitorReady, pub TempDirectory: pcCliprdrTempDirectory, + pub NotifyClipboardMsg: pcNotifyClipboardMsg, pub ClientFormatList: pcCliprdrClientFormatList, pub ServerFormatList: pcCliprdrServerFormatList, pub ClientFormatListResponse: pcCliprdrClientFormatListResponse, @@ -499,6 +510,8 @@ impl CliprdrClientContext { pub fn create( enable_files: bool, enable_others: bool, + response_wait_timeout_secs: u32, + notify_callback: pcNotifyClipboardMsg, client_format_list: pcCliprdrClientFormatList, client_format_list_response: pcCliprdrClientFormatListResponse, client_format_data_request: pcCliprdrClientFormatDataRequest, @@ -511,11 +524,12 @@ impl CliprdrClientContext { EnableFiles: if enable_files { TRUE } else { FALSE }, EnableOthers: if enable_others { TRUE } else { FALSE }, IsStopped: FALSE, - ResponseWaitTimeoutSecs: 60, + ResponseWaitTimeoutSecs: response_wait_timeout_secs, ServerCapabilities: None, ClientCapabilities: None, MonitorReady: None, TempDirectory: None, + NotifyClipboardMsg: notify_callback, ClientFormatList: client_format_list, ServerFormatList: None, ClientFormatListResponse: client_format_list_response, diff --git a/libs/clipboard/src/context_send.rs b/libs/clipboard/src/context_send.rs index 16363250e..76f8e4d7a 100644 --- a/libs/clipboard/src/context_send.rs +++ b/libs/clipboard/src/context_send.rs @@ -2,6 +2,8 @@ use crate::cliprdr::*; use hbb_common::log; use std::sync::Mutex; +const CLIPBOARD_RESPONSE_WAIT_TIMEOUT_SECS: u32 = 30; + lazy_static::lazy_static! { static ref CONTEXT_SEND: ContextSend = ContextSend{addr: Mutex::new(0)}; } @@ -27,7 +29,11 @@ impl ContextSend { let mut lock = CONTEXT_SEND.addr.lock().unwrap(); if enabled { if *lock == 0 { - match crate::create_cliprdr_context(true, false) { + match crate::create_cliprdr_context( + true, + false, + CLIPBOARD_RESPONSE_WAIT_TIMEOUT_SECS, + ) { Ok(context) => { log::info!("clipboard context for file transfer created."); *lock = Box::into_raw(context) as _; diff --git a/libs/clipboard/src/lib.rs b/libs/clipboard/src/lib.rs index c63817415..152dc0bcc 100644 --- a/libs/clipboard/src/lib.rs +++ b/libs/clipboard/src/lib.rs @@ -446,10 +446,13 @@ pub fn server_file_contents_response( pub fn create_cliprdr_context( enable_files: bool, enable_others: bool, + response_wait_timeout_secs: u32, ) -> ResultType> { Ok(CliprdrClientContext::create( enable_files, enable_others, + response_wait_timeout_secs, + Some(notify_callback), Some(client_format_list), Some(client_format_list_response), Some(client_format_data_request), @@ -459,6 +462,13 @@ pub fn create_cliprdr_context( )?) } +extern "C" fn notify_callback( + msg: *const NOTIFICATION_MESSAGE, +) -> UINT { + log::debug!("notify_callback called"); + 0 +} + extern "C" fn client_format_list( _context: *mut CliprdrClientContext, clip_format_list: *const CLIPRDR_FORMAT_LIST, diff --git a/libs/clipboard/src/windows/wf_cliprdr.c b/libs/clipboard/src/windows/wf_cliprdr.c index ea582d5b1..b9939121d 100644 --- a/libs/clipboard/src/windows/wf_cliprdr.c +++ b/libs/clipboard/src/windows/wf_cliprdr.c @@ -1455,7 +1455,8 @@ UINT wait_response_event(wfClipboard *clipboard, HANDLE event, void **data) clipboard->context->IsStopped = FALSE; DWORD waitOnceTimeoutMillis = 50; int waitCount = 1000 * clipboard->context->ResponseWaitTimeoutSecs / waitOnceTimeoutMillis; - for (int i = 0; i < waitCount * 3; i++) + int i = 0; + for (; i < waitCount; i++) { DWORD waitRes = WaitForSingleObject(event, waitOnceTimeoutMillis); if (waitRes == WAIT_TIMEOUT && clipboard->context->IsStopped == FALSE) @@ -1488,6 +1489,16 @@ UINT wait_response_event(wfClipboard *clipboard, HANDLE event, void **data) return rc; } + if (i == waitCount) + { + NOTIFICATION_MESSAGE msg; + msg.type = 2; + msg.msg = "timeout waiting for response"; + msg.details = NULL; + clipboard->context->NotifyClipboardMsg(&msg); + rc = ERROR_INTERNAL_ERROR; + } + if ((*data) != NULL) { if (!ResetEvent(event))