Fix/windows empty file clipboard on disconn (#10242)
* fix: windows, empty file clipboard on disconn Signed-off-by: fufesou <linlong1266@gmail.com> * refact: Don't send files copied before the conn Signed-off-by: fufesou <linlong1266@gmail.com> * refact: windows, file clipboard Empty clipboard if no `Ctrl+C` is pressed, but `CliprdrDataObject_GetData()` is called. `CliprdrDataObject_GetData()` is only called in the clipboard object set by RustDesk. Signed-off-by: fufesou <linlong1266@gmail.com> --------- Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
@@ -211,6 +211,11 @@ struct wf_clipboard
|
||||
BOOL sync;
|
||||
UINT32 capabilities;
|
||||
|
||||
// This flag is not really needed,
|
||||
// but we can use it to double confirm that files can only be pasted after `Ctrl+C`.
|
||||
// Not sure `is_file_descriptor_from_remote()` is engough to check all cases on all Windows.
|
||||
BOOL copied;
|
||||
|
||||
size_t map_size;
|
||||
size_t map_capacity;
|
||||
formatMapping *format_mappings;
|
||||
@@ -263,6 +268,8 @@ static UINT cliprdr_send_request_filecontents(wfClipboard *clipboard, UINT32 con
|
||||
ULONG index, UINT32 flag, DWORD positionhigh,
|
||||
DWORD positionlow, ULONG request);
|
||||
|
||||
static BOOL is_file_descriptor_from_remote();
|
||||
|
||||
static void CliprdrDataObject_Delete(CliprdrDataObject *instance);
|
||||
|
||||
static CliprdrEnumFORMATETC *CliprdrEnumFORMATETC_New(ULONG nFormats, FORMATETC *pFormatEtc);
|
||||
@@ -712,6 +719,15 @@ static HRESULT STDMETHODCALLTYPE CliprdrDataObject_GetData(IDataObject *This, FO
|
||||
if (!clipboard)
|
||||
return E_INVALIDARG;
|
||||
|
||||
// If `Ctrl+C` is not pressed yet, do not handle the file paste, and empty the clipboard.
|
||||
if (!clipboard->copied) {
|
||||
if (try_open_clipboard(clipboard->hwnd)) {
|
||||
EmptyClipboard();
|
||||
CloseClipboard();
|
||||
}
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if ((idx = cliprdr_lookup_format(instance, pFormatEtc)) == -1)
|
||||
{
|
||||
// empty clipboard here?
|
||||
@@ -1479,6 +1495,8 @@ static UINT cliprdr_send_format_list(wfClipboard *clipboard, UINT32 connID)
|
||||
|
||||
// send
|
||||
rc = clipboard->context->ClientFormatList(clipboard->context, &formatList);
|
||||
// No need to check `rc`, `copied` is only used to indicate `Ctrl+C` is pressed.
|
||||
clipboard->copied = TRUE;
|
||||
|
||||
for (index = 0; index < numFormats; index++)
|
||||
{
|
||||
@@ -2274,7 +2292,9 @@ static UINT wf_cliprdr_monitor_ready(CliprdrClientContext *context,
|
||||
if (rc != CHANNEL_RC_OK)
|
||||
return rc;
|
||||
|
||||
return cliprdr_send_format_list(clipboard, monitorReady->connID);
|
||||
return rc;
|
||||
// Don't send format list here, because we don't want to paste files copied before the connection.
|
||||
// return cliprdr_send_format_list(clipboard, monitorReady->connID);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2321,11 +2341,20 @@ static UINT wf_cliprdr_server_format_list(CliprdrClientContext *context,
|
||||
UINT32 i;
|
||||
formatMapping *mapping;
|
||||
CLIPRDR_FORMAT *format;
|
||||
wfClipboard *clipboard = (wfClipboard *)context->Custom;
|
||||
wfClipboard *clipboard = NULL;
|
||||
|
||||
if (!context || !formatList)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
clipboard = (wfClipboard *)context->Custom;
|
||||
if (!clipboard)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
if (!clear_format_map(clipboard))
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
clipboard->copied = TRUE;
|
||||
|
||||
for (i = 0; i < formatList->numFormats; i++)
|
||||
{
|
||||
format = &(formatList->formats[i]);
|
||||
@@ -3060,6 +3089,19 @@ wf_cliprdr_server_file_contents_response(CliprdrClientContext *context,
|
||||
return rc;
|
||||
}
|
||||
|
||||
BOOL is_file_descriptor_from_remote()
|
||||
{
|
||||
UINT fsid = 0;
|
||||
if (IsClipboardFormatAvailable(CF_HDROP)) {
|
||||
return FALSE;
|
||||
}
|
||||
fsid = RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW);
|
||||
if (IsClipboardFormatAvailable(fsid)) {
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL wf_cliprdr_init(wfClipboard *clipboard, CliprdrClientContext *cliprdr)
|
||||
{
|
||||
if (!clipboard || !cliprdr)
|
||||
@@ -3071,6 +3113,7 @@ BOOL wf_cliprdr_init(wfClipboard *clipboard, CliprdrClientContext *cliprdr)
|
||||
clipboard->map_size = 0;
|
||||
clipboard->hUser32 = LoadLibraryA("user32.dll");
|
||||
clipboard->data_obj = NULL;
|
||||
clipboard->copied = FALSE;
|
||||
|
||||
if (clipboard->hUser32)
|
||||
{
|
||||
@@ -3126,14 +3169,18 @@ BOOL wf_cliprdr_uninit(wfClipboard *clipboard, CliprdrClientContext *cliprdr)
|
||||
if (!clipboard || !cliprdr)
|
||||
return FALSE;
|
||||
|
||||
clipboard->copied = FALSE;
|
||||
cliprdr->Custom = NULL;
|
||||
|
||||
/* discard all contexts in clipboard */
|
||||
if (try_open_clipboard(clipboard->hwnd))
|
||||
{
|
||||
if (!EmptyClipboard())
|
||||
if (is_file_descriptor_from_remote())
|
||||
{
|
||||
DEBUG_CLIPRDR("EmptyClipboard failed with 0x%x", GetLastError());
|
||||
if (!EmptyClipboard())
|
||||
{
|
||||
DEBUG_CLIPRDR("EmptyClipboard failed with 0x%x", GetLastError());
|
||||
}
|
||||
}
|
||||
if (!CloseClipboard())
|
||||
{
|
||||
@@ -3227,6 +3274,8 @@ BOOL wf_do_empty_cliprdr(wfClipboard *clipboard)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
clipboard->copied = FALSE;
|
||||
|
||||
if (WaitForSingleObject(clipboard->data_obj_mutex, INFINITE) != WAIT_OBJECT_0)
|
||||
{
|
||||
return FALSE;
|
||||
@@ -3248,10 +3297,14 @@ BOOL wf_do_empty_cliprdr(wfClipboard *clipboard)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!EmptyClipboard())
|
||||
if (is_file_descriptor_from_remote())
|
||||
{
|
||||
rc = FALSE;
|
||||
if (!EmptyClipboard())
|
||||
{
|
||||
rc = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!CloseClipboard())
|
||||
{
|
||||
// critical error!!!
|
||||
|
||||
Reference in New Issue
Block a user