commit
7d6bdbaef8
@ -41,37 +41,6 @@
|
||||
const char* type_FileGroupDescriptorW = "FileGroupDescriptorW";
|
||||
const char* type_FileContents = "FileContents";
|
||||
|
||||
static const char* CB_MSG_TYPE_STRINGS(UINT32 type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case CB_MONITOR_READY:
|
||||
return "CB_MONITOR_READY";
|
||||
case CB_FORMAT_LIST:
|
||||
return "CB_FORMAT_LIST";
|
||||
case CB_FORMAT_LIST_RESPONSE:
|
||||
return "CB_FORMAT_LIST_RESPONSE";
|
||||
case CB_FORMAT_DATA_REQUEST:
|
||||
return "CB_FORMAT_DATA_REQUEST";
|
||||
case CB_FORMAT_DATA_RESPONSE:
|
||||
return "CB_FORMAT_DATA_RESPONSE";
|
||||
case CB_TEMP_DIRECTORY:
|
||||
return "CB_TEMP_DIRECTORY";
|
||||
case CB_CLIP_CAPS:
|
||||
return "CB_CLIP_CAPS";
|
||||
case CB_FILECONTENTS_REQUEST:
|
||||
return "CB_FILECONTENTS_REQUEST";
|
||||
case CB_FILECONTENTS_RESPONSE:
|
||||
return "CB_FILECONTENTS_RESPONSE";
|
||||
case CB_LOCK_CLIPDATA:
|
||||
return "CB_LOCK_CLIPDATA";
|
||||
case CB_UNLOCK_CLIPDATA:
|
||||
return "CB_UNLOCK_CLIPDATA";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
CliprdrClientContext* cliprdr_get_client_interface(cliprdrPlugin* cliprdr)
|
||||
{
|
||||
CliprdrClientContext* pInterface = NULL;
|
||||
@ -475,8 +444,11 @@ static UINT cliprdr_order_recv(LPVOID userdata, wStream* s)
|
||||
if (!Stream_CheckAndLogRequiredLength(TAG, s, dataLen))
|
||||
return ERROR_INVALID_DATA;
|
||||
|
||||
WLog_DBG(TAG, "msgType: %s (%" PRIu16 "), msgFlags: %" PRIu16 " dataLen: %" PRIu32 "",
|
||||
CB_MSG_TYPE_STRINGS(msgType), msgType, msgFlags, dataLen);
|
||||
char buffer1[64] = { 0 };
|
||||
char buffer2[64] = { 0 };
|
||||
WLog_DBG(TAG, "msgType: %s (%" PRIu16 "), msgFlags: %s dataLen: %" PRIu32 "",
|
||||
CB_MSG_TYPE_STRING(msgType, buffer1, sizeof(buffer1)), msgType,
|
||||
CB_MSG_FLAGS_STRING(msgFlags, buffer2, sizeof(buffer2)), dataLen);
|
||||
|
||||
switch (msgType)
|
||||
{
|
||||
|
@ -28,6 +28,67 @@
|
||||
|
||||
#include "cliprdr_common.h"
|
||||
|
||||
static const char* CB_MSG_TYPE_STR(UINT32 type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case CB_MONITOR_READY:
|
||||
return "CB_MONITOR_READY";
|
||||
case CB_FORMAT_LIST:
|
||||
return "CB_FORMAT_LIST";
|
||||
case CB_FORMAT_LIST_RESPONSE:
|
||||
return "CB_FORMAT_LIST_RESPONSE";
|
||||
case CB_FORMAT_DATA_REQUEST:
|
||||
return "CB_FORMAT_DATA_REQUEST";
|
||||
case CB_FORMAT_DATA_RESPONSE:
|
||||
return "CB_FORMAT_DATA_RESPONSE";
|
||||
case CB_TEMP_DIRECTORY:
|
||||
return "CB_TEMP_DIRECTORY";
|
||||
case CB_CLIP_CAPS:
|
||||
return "CB_CLIP_CAPS";
|
||||
case CB_FILECONTENTS_REQUEST:
|
||||
return "CB_FILECONTENTS_REQUEST";
|
||||
case CB_FILECONTENTS_RESPONSE:
|
||||
return "CB_FILECONTENTS_RESPONSE";
|
||||
case CB_LOCK_CLIPDATA:
|
||||
return "CB_LOCK_CLIPDATA";
|
||||
case CB_UNLOCK_CLIPDATA:
|
||||
return "CB_UNLOCK_CLIPDATA";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
const char* CB_MSG_TYPE_STRING(UINT16 type, char* buffer, size_t size)
|
||||
{
|
||||
_snprintf(buffer, size, "%s [0x%04" PRIx16 "]", CB_MSG_TYPE_STR(type), type);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const char* CB_MSG_FLAGS_STRING(UINT16 msgFlags, char* buffer, size_t size)
|
||||
{
|
||||
if ((msgFlags & CB_RESPONSE_OK) != 0)
|
||||
winpr_str_append("CB_RESPONSE_OK", buffer, size, "|");
|
||||
if ((msgFlags & CB_RESPONSE_FAIL) != 0)
|
||||
winpr_str_append("CB_RESPONSE_FAIL", buffer, size, "|");
|
||||
if ((msgFlags & CB_ASCII_NAMES) != 0)
|
||||
winpr_str_append("CB_ASCII_NAMES", buffer, size, "|");
|
||||
|
||||
const size_t len = strnlen(buffer, size);
|
||||
if (len > 0)
|
||||
{
|
||||
/* remove trailing | */
|
||||
buffer[len - 1] = '\0';
|
||||
}
|
||||
else
|
||||
winpr_str_append("NONE", buffer, size, "");
|
||||
|
||||
char val[32] = { 0 };
|
||||
_snprintf(val, sizeof(val), "[0x%04" PRIx16 "]", msgFlags);
|
||||
winpr_str_append(val, buffer, size, "|");
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static BOOL cliprdr_validate_file_contents_request(const CLIPRDR_FILE_CONTENTS_REQUEST* request)
|
||||
{
|
||||
/*
|
||||
|
@ -29,6 +29,9 @@
|
||||
#include <freerdp/channels/cliprdr.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
FREERDP_LOCAL const char* CB_MSG_TYPE_STRING(UINT16 type, char* buffer, size_t size);
|
||||
FREERDP_LOCAL const char* CB_MSG_FLAGS_STRING(UINT16 msgFlags, char* buffer, size_t size);
|
||||
|
||||
FREERDP_LOCAL wStream* cliprdr_packet_new(UINT16 msgType, UINT16 msgFlags, UINT32 dataLen);
|
||||
FREERDP_LOCAL wStream*
|
||||
cliprdr_packet_lock_clipdata_new(const CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData);
|
||||
|
@ -902,10 +902,11 @@ static UINT cliprdr_server_receive_pdu(CliprdrServerContext* context, wStream* s
|
||||
WINPR_ASSERT(context);
|
||||
WINPR_ASSERT(header);
|
||||
|
||||
WLog_DBG(TAG,
|
||||
"CliprdrServerReceivePdu: msgType: %" PRIu16 " msgFlags: 0x%04" PRIX16
|
||||
" dataLen: %" PRIu32 "",
|
||||
header->msgType, header->msgFlags, header->dataLen);
|
||||
char buffer1[64] = { 0 };
|
||||
char buffer2[64] = { 0 };
|
||||
WLog_DBG(TAG, "CliprdrServerReceivePdu: msgType: %s, msgFlags: %s dataLen: %" PRIu32 "",
|
||||
CB_MSG_TYPE_STRING(header->msgType, buffer1, sizeof(buffer1)),
|
||||
CB_MSG_FLAGS_STRING(header->msgFlags, buffer2, sizeof(buffer2)), header->dataLen);
|
||||
|
||||
switch (header->msgType)
|
||||
{
|
||||
|
@ -785,7 +785,9 @@ void xf_lock_x11_(xfContext* xfc, const char* fkt)
|
||||
XLockDisplay(xfc->display);
|
||||
|
||||
xfc->locked++;
|
||||
#ifdef WITH_DEBUG_X11
|
||||
WLog_VRB(TAG, "[%" PRIu32 "] from %s", xfc->locked, fkt);
|
||||
#endif
|
||||
}
|
||||
|
||||
void xf_unlock_x11_(xfContext* xfc, const char* fkt)
|
||||
@ -793,7 +795,10 @@ void xf_unlock_x11_(xfContext* xfc, const char* fkt)
|
||||
if (xfc->locked == 0)
|
||||
WLog_WARN(TAG, "X11: trying to unlock although not locked!");
|
||||
|
||||
#ifdef WITH_DEBUG_X11
|
||||
WLog_VRB(TAG, "[%" PRIu32 "] from %s", xfc->locked - 1, fkt);
|
||||
#endif
|
||||
|
||||
if (!xfc->UseXThreads)
|
||||
ReleaseMutex(xfc->mutex);
|
||||
else
|
||||
|
@ -124,6 +124,7 @@ struct xf_clipboard
|
||||
BOOL incr_starts;
|
||||
BYTE* incr_data;
|
||||
int incr_data_length;
|
||||
long event_mask;
|
||||
|
||||
/* XFixes extension */
|
||||
int xfixes_event_base;
|
||||
@ -607,6 +608,23 @@ static CLIPRDR_FORMAT* xf_cliprdr_get_raw_server_formats(xfClipboard* clipboard,
|
||||
return formats;
|
||||
}
|
||||
|
||||
static BOOL xf_cliprdr_should_add_format(const CLIPRDR_FORMAT* formats, size_t count,
|
||||
const xfCliprdrFormat* xformat)
|
||||
{
|
||||
WINPR_ASSERT(formats);
|
||||
|
||||
if (!xformat)
|
||||
return FALSE;
|
||||
|
||||
for (size_t x = 0; x < count; x++)
|
||||
{
|
||||
const CLIPRDR_FORMAT* format = &formats[x];
|
||||
if (format->formatId == xformat->formatToRequest)
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static CLIPRDR_FORMAT* xf_cliprdr_get_formats_from_targets(xfClipboard* clipboard,
|
||||
UINT32* numFormats)
|
||||
{
|
||||
@ -647,10 +665,18 @@ static CLIPRDR_FORMAT* xf_cliprdr_get_formats_from_targets(xfClipboard* clipboar
|
||||
Atom tatom = ((Atom*)data)[i];
|
||||
const xfCliprdrFormat* format = xf_cliprdr_get_client_format_by_atom(clipboard, tatom);
|
||||
|
||||
if (format)
|
||||
if (xf_cliprdr_should_add_format(formats, *numFormats, format))
|
||||
{
|
||||
formats[*numFormats].formatId = format->formatToRequest;
|
||||
formats[*numFormats].formatName = _strdup(format->formatName);
|
||||
CLIPRDR_FORMAT* cformat = &formats[*numFormats];
|
||||
cformat->formatId = format->formatToRequest;
|
||||
if (format->formatName)
|
||||
{
|
||||
cformat->formatName = _strdup(format->formatName);
|
||||
WINPR_ASSERT(cformat->formatName);
|
||||
}
|
||||
else
|
||||
cformat->formatName = NULL;
|
||||
|
||||
*numFormats += 1;
|
||||
}
|
||||
}
|
||||
@ -837,8 +863,8 @@ static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard)
|
||||
xf_cliprdr_free_formats(formats, numFormats);
|
||||
}
|
||||
|
||||
static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasData, BYTE* data,
|
||||
int size)
|
||||
static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasData,
|
||||
const BYTE* data, size_t size)
|
||||
{
|
||||
BOOL bSuccess = 0;
|
||||
UINT32 SrcSize = 0;
|
||||
@ -871,7 +897,7 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa
|
||||
case CF_TEXT:
|
||||
case CF_OEMTEXT:
|
||||
case CF_UNICODETEXT:
|
||||
size = strlen((char*)data) + 1;
|
||||
size = strlen((const char*)data) + 1;
|
||||
srcFormatId = format->localFormat;
|
||||
break;
|
||||
|
||||
@ -944,6 +970,37 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa
|
||||
free(pDstData);
|
||||
}
|
||||
|
||||
static BOOL xf_add_input_flags(xfClipboard* clipboard, long mask)
|
||||
{
|
||||
WINPR_ASSERT(clipboard);
|
||||
|
||||
xfContext* xfc = clipboard->xfc;
|
||||
WINPR_ASSERT(xfc);
|
||||
|
||||
XWindowAttributes attr = { 0 };
|
||||
XGetWindowAttributes(xfc->display, xfc->drawable, &attr);
|
||||
if ((attr.all_event_masks & mask) == 0)
|
||||
clipboard->event_mask = attr.all_event_masks;
|
||||
|
||||
XSelectInput(xfc->display, xfc->drawable, attr.all_event_masks | mask);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL xf_restore_input_flags(xfClipboard* clipboard)
|
||||
{
|
||||
WINPR_ASSERT(clipboard);
|
||||
|
||||
xfContext* xfc = clipboard->xfc;
|
||||
WINPR_ASSERT(xfc);
|
||||
|
||||
if (clipboard->event_mask != 0)
|
||||
{
|
||||
XSelectInput(xfc->display, xfc->drawable, clipboard->event_mask);
|
||||
clipboard->event_mask = 0;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL xf_cliprdr_get_requested_data(xfClipboard* clipboard, Atom target)
|
||||
{
|
||||
Atom type = 0;
|
||||
@ -993,7 +1050,7 @@ static BOOL xf_cliprdr_get_requested_data(xfClipboard* clipboard, Atom target)
|
||||
|
||||
clipboard->incr_data_length = 0;
|
||||
has_data = TRUE; /* data will be followed in PropertyNotify event */
|
||||
XSelectInput(xfc->display, xfc->drawable, PropertyChangeMask);
|
||||
xf_add_input_flags(clipboard, PropertyChangeMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1004,7 +1061,11 @@ static BOOL xf_cliprdr_get_requested_data(xfClipboard* clipboard, Atom target)
|
||||
clipboard->incr_data = NULL;
|
||||
bytes_left = clipboard->incr_data_length;
|
||||
clipboard->incr_data_length = 0;
|
||||
clipboard->incr_starts = 0;
|
||||
clipboard->incr_starts = FALSE;
|
||||
|
||||
/* Restore previous event mask */
|
||||
xf_restore_input_flags(clipboard);
|
||||
|
||||
has_data = TRUE;
|
||||
}
|
||||
else if (LogTagAndXGetWindowProperty(
|
||||
@ -1210,7 +1271,6 @@ void xf_cliprdr_clear_cached_data(xfClipboard* clipboard)
|
||||
|
||||
ClipboardLock(clipboard->system);
|
||||
ClipboardEmpty(clipboard->system);
|
||||
cliprdr_file_context_clear(clipboard->file);
|
||||
|
||||
HashTable_Clear(clipboard->cachedData);
|
||||
HashTable_Clear(clipboard->cachedRawData);
|
||||
@ -1683,8 +1743,9 @@ static UINT xf_cliprdr_send_client_format_list(xfClipboard* clipboard, BOOL forc
|
||||
if (clipboard->owner && clipboard->owner != xfc->drawable)
|
||||
{
|
||||
/* Request the owner for TARGETS, and wait for SelectionNotify event */
|
||||
XConvertSelection(xfc->display, clipboard->clipboard_atom, clipboard->targets[1],
|
||||
clipboard->property_atom, xfc->drawable, CurrentTime);
|
||||
LogTagAndXConvertSelection(TAG, xfc->display, clipboard->clipboard_atom,
|
||||
clipboard->targets[1], clipboard->property_atom, xfc->drawable,
|
||||
CurrentTime);
|
||||
}
|
||||
|
||||
xf_cliprdr_free_formats(formats, numFormats);
|
||||
@ -1987,8 +2048,8 @@ xf_cliprdr_server_format_data_request(CliprdrClientContext* context,
|
||||
DEBUG_CLIPRDR("requested format 0x%08" PRIx32 " [%s] {local 0x%08" PRIx32 "} [%s]",
|
||||
format->formatToRequest, ClipboardGetFormatIdString(format->formatToRequest),
|
||||
format->localFormat, format->formatName);
|
||||
XConvertSelection(xfc->display, clipboard->clipboard_atom, format->atom,
|
||||
clipboard->property_atom, xfc->drawable, CurrentTime);
|
||||
LogTagAndXConvertSelection(TAG, xfc->display, clipboard->clipboard_atom, format->atom,
|
||||
clipboard->property_atom, xfc->drawable, CurrentTime);
|
||||
XFlush(xfc->display);
|
||||
/* After this point, we expect a SelectionNotify event from the clipboard owner. */
|
||||
return CHANNEL_RC_OK;
|
||||
|
@ -86,6 +86,34 @@ int LogDynAndXDeleteProperty_ex(wLog* log, const char* file, const char* fkt, si
|
||||
return XDeleteProperty(display, w, property);
|
||||
}
|
||||
|
||||
int LogTagAndXConvertSelection_ex(const char* tag, const char* file, const char* fkt, size_t line,
|
||||
Display* display, Atom selection, Atom target, Atom property,
|
||||
Window requestor, Time time)
|
||||
{
|
||||
wLog* log = WLog_Get(tag);
|
||||
return LogDynAndXConvertSelection_ex(log, file, fkt, line, display, selection, target, property,
|
||||
requestor, time);
|
||||
}
|
||||
|
||||
int LogDynAndXConvertSelection_ex(wLog* log, const char* file, const char* fkt, size_t line,
|
||||
Display* display, Atom selection, Atom target, Atom property,
|
||||
Window requestor, Time time)
|
||||
{
|
||||
if (WLog_IsLevelActive(log, log_level))
|
||||
{
|
||||
char* selectstr = Safe_XGetAtomName(log, display, selection);
|
||||
char* targetstr = Safe_XGetAtomName(log, display, target);
|
||||
char* propstr = Safe_XGetAtomName(log, display, property);
|
||||
write_log(log, log_level, file, fkt, line,
|
||||
"XConvertSelection(%p, %s [%d], %s [%d], %s [%d], %d, %lu)", display, selectstr,
|
||||
selection, targetstr, target, propstr, property, requestor, time);
|
||||
XFree(propstr);
|
||||
XFree(targetstr);
|
||||
XFree(selectstr);
|
||||
}
|
||||
return XConvertSelection(display, selection, target, property, requestor, time);
|
||||
}
|
||||
|
||||
int LogTagAndXGetWindowProperty_ex(const char* tag, const char* file, const char* fkt, size_t line,
|
||||
Display* display, Window w, Atom property, long long_offset,
|
||||
long long_length, int delete, Atom req_type,
|
||||
|
@ -76,3 +76,16 @@ int LogTagAndXDeleteProperty_ex(const char* tag, const char* file, const char* f
|
||||
LogDynAndXDeleteProperty_ex((log), __FILE__, __func__, __LINE__, (display), (w), (property))
|
||||
int LogDynAndXDeleteProperty_ex(wLog* log, const char* file, const char* fkt, size_t line,
|
||||
Display* display, Window w, Atom property);
|
||||
|
||||
#define LogTagAndXConvertSelection(tag, display, selection, target, property, requestor, time) \
|
||||
LogTagAndXConvertSelection_ex((tag), __FILE__, __func__, __LINE__, (display), (selection), \
|
||||
(target), (property), (requestor), (time))
|
||||
int LogTagAndXConvertSelection_ex(const char* tag, const char* file, const char* fkt, size_t line,
|
||||
Display* display, Atom selection, Atom target, Atom property,
|
||||
Window requestor, Time time);
|
||||
|
||||
#define LogDynAndXConvertSelection(log, display, selection, target, property, requestor, time) \
|
||||
LogDynAndXConvertSelection_ex((log), __FILE__, __func__, __LINE__, (display), (w), (property))
|
||||
int LogDynAndXConvertSelection_ex(wLog* log, const char* file, const char* fkt, size_t line,
|
||||
Display* display, Atom selection, Atom target, Atom property,
|
||||
Window requestor, Time time);
|
||||
|
Loading…
Reference in New Issue
Block a user