mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-04-16 09:11:27 +03:00
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;
|
BOOL sync;
|
||||||
UINT32 capabilities;
|
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_size;
|
||||||
size_t map_capacity;
|
size_t map_capacity;
|
||||||
formatMapping *format_mappings;
|
formatMapping *format_mappings;
|
||||||
@@ -263,6 +268,8 @@ static UINT cliprdr_send_request_filecontents(wfClipboard *clipboard, UINT32 con
|
|||||||
ULONG index, UINT32 flag, DWORD positionhigh,
|
ULONG index, UINT32 flag, DWORD positionhigh,
|
||||||
DWORD positionlow, ULONG request);
|
DWORD positionlow, ULONG request);
|
||||||
|
|
||||||
|
static BOOL is_file_descriptor_from_remote();
|
||||||
|
|
||||||
static void CliprdrDataObject_Delete(CliprdrDataObject *instance);
|
static void CliprdrDataObject_Delete(CliprdrDataObject *instance);
|
||||||
|
|
||||||
static CliprdrEnumFORMATETC *CliprdrEnumFORMATETC_New(ULONG nFormats, FORMATETC *pFormatEtc);
|
static CliprdrEnumFORMATETC *CliprdrEnumFORMATETC_New(ULONG nFormats, FORMATETC *pFormatEtc);
|
||||||
@@ -712,6 +719,15 @@ static HRESULT STDMETHODCALLTYPE CliprdrDataObject_GetData(IDataObject *This, FO
|
|||||||
if (!clipboard)
|
if (!clipboard)
|
||||||
return E_INVALIDARG;
|
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)
|
if ((idx = cliprdr_lookup_format(instance, pFormatEtc)) == -1)
|
||||||
{
|
{
|
||||||
// empty clipboard here?
|
// empty clipboard here?
|
||||||
@@ -1479,6 +1495,8 @@ static UINT cliprdr_send_format_list(wfClipboard *clipboard, UINT32 connID)
|
|||||||
|
|
||||||
// send
|
// send
|
||||||
rc = clipboard->context->ClientFormatList(clipboard->context, &formatList);
|
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++)
|
for (index = 0; index < numFormats; index++)
|
||||||
{
|
{
|
||||||
@@ -2274,7 +2292,9 @@ static UINT wf_cliprdr_monitor_ready(CliprdrClientContext *context,
|
|||||||
if (rc != CHANNEL_RC_OK)
|
if (rc != CHANNEL_RC_OK)
|
||||||
return rc;
|
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;
|
UINT32 i;
|
||||||
formatMapping *mapping;
|
formatMapping *mapping;
|
||||||
CLIPRDR_FORMAT *format;
|
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))
|
if (!clear_format_map(clipboard))
|
||||||
return ERROR_INTERNAL_ERROR;
|
return ERROR_INTERNAL_ERROR;
|
||||||
|
|
||||||
|
clipboard->copied = TRUE;
|
||||||
|
|
||||||
for (i = 0; i < formatList->numFormats; i++)
|
for (i = 0; i < formatList->numFormats; i++)
|
||||||
{
|
{
|
||||||
format = &(formatList->formats[i]);
|
format = &(formatList->formats[i]);
|
||||||
@@ -3060,6 +3089,19 @@ wf_cliprdr_server_file_contents_response(CliprdrClientContext *context,
|
|||||||
return rc;
|
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)
|
BOOL wf_cliprdr_init(wfClipboard *clipboard, CliprdrClientContext *cliprdr)
|
||||||
{
|
{
|
||||||
if (!clipboard || !cliprdr)
|
if (!clipboard || !cliprdr)
|
||||||
@@ -3071,6 +3113,7 @@ BOOL wf_cliprdr_init(wfClipboard *clipboard, CliprdrClientContext *cliprdr)
|
|||||||
clipboard->map_size = 0;
|
clipboard->map_size = 0;
|
||||||
clipboard->hUser32 = LoadLibraryA("user32.dll");
|
clipboard->hUser32 = LoadLibraryA("user32.dll");
|
||||||
clipboard->data_obj = NULL;
|
clipboard->data_obj = NULL;
|
||||||
|
clipboard->copied = FALSE;
|
||||||
|
|
||||||
if (clipboard->hUser32)
|
if (clipboard->hUser32)
|
||||||
{
|
{
|
||||||
@@ -3126,14 +3169,18 @@ BOOL wf_cliprdr_uninit(wfClipboard *clipboard, CliprdrClientContext *cliprdr)
|
|||||||
if (!clipboard || !cliprdr)
|
if (!clipboard || !cliprdr)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
clipboard->copied = FALSE;
|
||||||
cliprdr->Custom = NULL;
|
cliprdr->Custom = NULL;
|
||||||
|
|
||||||
/* discard all contexts in clipboard */
|
/* discard all contexts in clipboard */
|
||||||
if (try_open_clipboard(clipboard->hwnd))
|
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())
|
if (!CloseClipboard())
|
||||||
{
|
{
|
||||||
@@ -3227,6 +3274,8 @@ BOOL wf_do_empty_cliprdr(wfClipboard *clipboard)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clipboard->copied = FALSE;
|
||||||
|
|
||||||
if (WaitForSingleObject(clipboard->data_obj_mutex, INFINITE) != WAIT_OBJECT_0)
|
if (WaitForSingleObject(clipboard->data_obj_mutex, INFINITE) != WAIT_OBJECT_0)
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -3248,10 +3297,14 @@ BOOL wf_do_empty_cliprdr(wfClipboard *clipboard)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EmptyClipboard())
|
if (is_file_descriptor_from_remote())
|
||||||
{
|
{
|
||||||
rc = FALSE;
|
if (!EmptyClipboard())
|
||||||
|
{
|
||||||
|
rc = FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CloseClipboard())
|
if (!CloseClipboard())
|
||||||
{
|
{
|
||||||
// critical error!!!
|
// critical error!!!
|
||||||
|
|||||||
Reference in New Issue
Block a user