channels/cliprdr: add missing callbacks and message definitions

This commit is contained in:
Marc-André Moreau 2014-10-23 18:17:53 -04:00
parent 765150e3ed
commit f76f8e3599
5 changed files with 645 additions and 54 deletions

View File

@ -111,7 +111,7 @@ void cliprdr_print_general_capability_flags(UINT32 flags)
WLog_INFO(TAG, "}"); WLog_INFO(TAG, "}");
} }
static void cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream* s) static int cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream* s)
{ {
UINT32 version; UINT32 version;
UINT32 generalFlags; UINT32 generalFlags;
@ -159,9 +159,11 @@ static void cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream*
caps_event->capabilities = generalFlags; caps_event->capabilities = generalFlags;
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) caps_event); svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) caps_event);
} }
return 1;
} }
static void cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s, UINT16 length, UINT16 flags) static int cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s, UINT16 length, UINT16 flags)
{ {
int i; int i;
UINT16 lengthCapability; UINT16 lengthCapability;
@ -187,6 +189,8 @@ static void cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s, UINT16
break; break;
} }
} }
return 1;
} }
static void cliprdr_send_clip_caps(cliprdrPlugin* cliprdr) static void cliprdr_send_clip_caps(cliprdrPlugin* cliprdr)
@ -210,7 +214,7 @@ static void cliprdr_send_clip_caps(cliprdrPlugin* cliprdr)
cliprdr_packet_send(cliprdr, s); cliprdr_packet_send(cliprdr, s);
} }
static void cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s, UINT16 length, UINT16 flags) static int cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s, UINT16 length, UINT16 flags)
{ {
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
@ -236,74 +240,178 @@ static void cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s, UI
event = (RDP_CB_MONITOR_READY_EVENT*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_MonitorReady, NULL, NULL); event = (RDP_CB_MONITOR_READY_EVENT*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_MonitorReady, NULL, NULL);
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) event); svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) event);
} }
return 1;
} }
static void cliprdr_process_filecontents_request(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags) static int cliprdr_process_filecontents_request(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags)
{ {
RDP_CB_FILECONTENTS_REQUEST_EVENT* cb_event; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
WLog_Print(cliprdr->log, WLOG_DEBUG, "FileContentsRequest"); WLog_Print(cliprdr->log, WLOG_DEBUG, "FileContentsRequest");
cb_event = (RDP_CB_FILECONTENTS_REQUEST_EVENT*) freerdp_event_new(CliprdrChannel_Class, if (context->custom)
CliprdrChannel_FilecontentsRequest, NULL, NULL); {
CLIPRDR_FILE_CONTENTS_REQUEST request;
Stream_Read_UINT32(s, cb_event->streamId); if (Stream_GetRemainingLength(s) < 28)
Stream_Read_UINT32(s, cb_event->lindex); return -1;
Stream_Read_UINT32(s, cb_event->dwFlags);
Stream_Read_UINT32(s, cb_event->nPositionLow); request.msgType = CB_FILECONTENTS_REQUEST;
Stream_Read_UINT32(s, cb_event->nPositionHigh); request.msgFlags = flags;
Stream_Read_UINT32(s, cb_event->cbRequested); request.dataLen = length;
//Stream_Read_UINT32(s, cb_event->clipDataId);
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event); Stream_Read_UINT32(s, request.streamId); /* streamId (4 bytes) */
Stream_Read_UINT32(s, request.listIndex); /* listIndex (4 bytes) */
Stream_Read_UINT32(s, request.dwFlags); /* dwFlags (4 bytes) */
Stream_Read_UINT32(s, request.nPositionLow); /* nPositionLow (4 bytes) */
Stream_Read_UINT32(s, request.nPositionHigh); /* nPositionHigh (4 bytes) */
Stream_Read_UINT32(s, request.cbRequested); /* cbRequested (4 bytes) */
Stream_Read_UINT32(s, request.clipDataId); /* clipDataId (4 bytes) */
if (context->ServerFileContentsRequest)
context->ServerFileContentsRequest(context, &request);
}
else
{
RDP_CB_FILECONTENTS_REQUEST_EVENT* cb_event;
cb_event = (RDP_CB_FILECONTENTS_REQUEST_EVENT*) freerdp_event_new(CliprdrChannel_Class,
CliprdrChannel_FilecontentsRequest, NULL, NULL);
Stream_Read_UINT32(s, cb_event->streamId);
Stream_Read_UINT32(s, cb_event->lindex);
Stream_Read_UINT32(s, cb_event->dwFlags);
Stream_Read_UINT32(s, cb_event->nPositionLow);
Stream_Read_UINT32(s, cb_event->nPositionHigh);
Stream_Read_UINT32(s, cb_event->cbRequested);
//Stream_Read_UINT32(s, cb_event->clipDataId);
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event);
}
return 1;
} }
static void cliprdr_process_filecontents_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags) static int cliprdr_process_filecontents_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags)
{ {
RDP_CB_FILECONTENTS_RESPONSE_EVENT* cb_event; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
WLog_Print(cliprdr->log, WLOG_DEBUG, "FileContentsResponse"); WLog_Print(cliprdr->log, WLOG_DEBUG, "FileContentsResponse");
cb_event = (RDP_CB_FILECONTENTS_RESPONSE_EVENT*) freerdp_event_new(CliprdrChannel_Class, if (context->custom)
CliprdrChannel_FilecontentsResponse, NULL, NULL);
Stream_Read_UINT32(s, cb_event->streamId);
if (length > 0)
{ {
cb_event->size = length - 4; CLIPRDR_FILE_CONTENTS_RESPONSE response;
cb_event->data = (BYTE*) malloc(cb_event->size);
CopyMemory(cb_event->data, Stream_Pointer(s), cb_event->size); if (Stream_GetRemainingLength(s) < 4)
return -1;
response.msgType = CB_FILECONTENTS_RESPONSE;
response.msgFlags = flags;
response.dataLen = length;
Stream_Read_UINT32(s, response.streamId); /* streamId (4 bytes) */
response.cbRequested = length - 4;
response.requestedData = Stream_Pointer(s); /* requestedFileContentsData */
if (context->ServerFileContentsResponse)
context->ServerFileContentsResponse(context, &response);
}
else
{
RDP_CB_FILECONTENTS_RESPONSE_EVENT* cb_event;
cb_event = (RDP_CB_FILECONTENTS_RESPONSE_EVENT*) freerdp_event_new(CliprdrChannel_Class,
CliprdrChannel_FilecontentsResponse, NULL, NULL);
Stream_Read_UINT32(s, cb_event->streamId);
if (length > 0)
{
cb_event->size = length - 4;
cb_event->data = (BYTE*) malloc(cb_event->size);
CopyMemory(cb_event->data, Stream_Pointer(s), cb_event->size);
}
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event);
} }
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event); return 1;
} }
static void cliprdr_process_lock_clipdata(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags) static int cliprdr_process_lock_clipdata(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags)
{ {
RDP_CB_LOCK_CLIPDATA_EVENT* cb_event; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
WLog_Print(cliprdr->log, WLOG_DEBUG, "LockClipData"); WLog_Print(cliprdr->log, WLOG_DEBUG, "LockClipData");
cb_event = (RDP_CB_LOCK_CLIPDATA_EVENT*) freerdp_event_new(CliprdrChannel_Class, if (context->custom)
CliprdrChannel_LockClipdata, NULL, NULL); {
CLIPRDR_LOCK_CLIPBOARD_DATA lockClipboardData;
Stream_Read_UINT32(s, cb_event->clipDataId); if (Stream_GetRemainingLength(s) < 4)
return -1;
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event); lockClipboardData.msgType = CB_LOCK_CLIPDATA;
lockClipboardData.msgFlags = flags;
lockClipboardData.dataLen = length;
Stream_Read_UINT32(s, lockClipboardData.clipDataId); /* clipDataId (4 bytes) */
if (context->ServerLockClipboardData)
context->ServerLockClipboardData(context, &lockClipboardData);
}
else
{
RDP_CB_LOCK_CLIPDATA_EVENT* cb_event;
cb_event = (RDP_CB_LOCK_CLIPDATA_EVENT*) freerdp_event_new(CliprdrChannel_Class,
CliprdrChannel_LockClipdata, NULL, NULL);
Stream_Read_UINT32(s, cb_event->clipDataId);
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event);
}
return 1;
} }
static void cliprdr_process_unlock_clipdata(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags) static int cliprdr_process_unlock_clipdata(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, UINT16 flags)
{ {
RDP_CB_UNLOCK_CLIPDATA_EVENT* cb_event; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
WLog_Print(cliprdr->log, WLOG_DEBUG, "UnlockClipData"); WLog_Print(cliprdr->log, WLOG_DEBUG, "UnlockClipData");
cb_event = (RDP_CB_UNLOCK_CLIPDATA_EVENT*) freerdp_event_new(CliprdrChannel_Class, if (context->custom)
CliprdrChannel_UnLockClipdata, NULL, NULL); {
CLIPRDR_UNLOCK_CLIPBOARD_DATA unlockClipboardData;
Stream_Read_UINT32(s, cb_event->clipDataId); if (Stream_GetRemainingLength(s) < 4)
return -1;
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event); unlockClipboardData.msgType = CB_UNLOCK_CLIPDATA;
unlockClipboardData.msgFlags = flags;
unlockClipboardData.dataLen = length;
Stream_Read_UINT32(s, unlockClipboardData.clipDataId); /* clipDataId (4 bytes) */
if (context->ServerUnlockClipboardData)
context->ServerUnlockClipboardData(context, &unlockClipboardData);
}
else
{
RDP_CB_UNLOCK_CLIPDATA_EVENT* cb_event;
cb_event = (RDP_CB_UNLOCK_CLIPDATA_EVENT*) freerdp_event_new(CliprdrChannel_Class,
CliprdrChannel_UnLockClipdata, NULL, NULL);
Stream_Read_UINT32(s, cb_event->clipDataId);
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event);
}
return 1;
} }
static void cliprdr_process_receive(rdpSvcPlugin* plugin, wStream* s) static void cliprdr_process_receive(rdpSvcPlugin* plugin, wStream* s)
@ -490,6 +598,36 @@ int cliprdr_client_capabilities(CliprdrClientContext* context, CLIPRDR_CAPABILIT
return 0; return 0;
} }
int cliprdr_temp_directory(CliprdrClientContext* context, CLIPRDR_TEMP_DIRECTORY* tempDirectory)
{
int length;
wStream* s;
WCHAR* wszTempDir = NULL;
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
s = cliprdr_packet_new(CB_TEMP_DIRECTORY, 0, 520 * 2);
length = ConvertToUnicode(CP_UTF8, 0, tempDirectory->szTempDir, -1, &wszTempDir, 0);
if (length < 0)
return -1;
if (length > 520)
length = 520;
Stream_Write(s, tempDirectory->szTempDir, length * 2);
Stream_Zero(s, (520 - length) * 2);
free(wszTempDir);
WLog_Print(cliprdr->log, WLOG_DEBUG, "TempDirectory: %s",
tempDirectory->szTempDir);
cliprdr_packet_send(cliprdr, s);
return 1;
}
int cliprdr_client_format_list(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList) int cliprdr_client_format_list(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList)
{ {
wStream* s; wStream* s;
@ -557,6 +695,40 @@ int cliprdr_client_format_list_response(CliprdrClientContext* context, CLIPRDR_F
return 0; return 0;
} }
int cliprdr_client_lock_clipboard_data(CliprdrClientContext* context, CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
{
wStream* s;
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
s = cliprdr_packet_new(CB_LOCK_CLIPDATA, 0, 4);
Stream_Write_UINT32(s, lockClipboardData->clipDataId); /* clipDataId (4 bytes) */
WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientLockClipboardData: clipDataId: 0x%04X",
lockClipboardData->clipDataId);
cliprdr_packet_send(cliprdr, s);
return 1;
}
int cliprdr_client_unlock_clipboard_data(CliprdrClientContext* context, CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
{
wStream* s;
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
s = cliprdr_packet_new(CB_UNLOCK_CLIPDATA, 0, 4);
Stream_Write_UINT32(s, unlockClipboardData->clipDataId); /* clipDataId (4 bytes) */
WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientUnlockClipboardData: clipDataId: 0x%04X",
unlockClipboardData->clipDataId);
cliprdr_packet_send(cliprdr, s);
return 1;
}
int cliprdr_client_format_data_request(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest) int cliprdr_client_format_data_request(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
{ {
wStream* s; wStream* s;
@ -592,6 +764,58 @@ int cliprdr_client_format_data_response(CliprdrClientContext* context, CLIPRDR_F
return 0; return 0;
} }
int cliprdr_client_file_contents_request(CliprdrClientContext* context, CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
{
wStream* s;
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
s = cliprdr_packet_new(CB_FILECONTENTS_REQUEST, 0, 28);
Stream_Write_UINT32(s, fileContentsRequest->streamId); /* streamId (4 bytes) */
Stream_Write_UINT32(s, fileContentsRequest->listIndex); /* listIndex (4 bytes) */
Stream_Write_UINT32(s, fileContentsRequest->dwFlags); /* dwFlags (4 bytes) */
Stream_Write_UINT32(s, fileContentsRequest->nPositionLow); /* nPositionLow (4 bytes) */
Stream_Write_UINT32(s, fileContentsRequest->nPositionHigh); /* nPositionHigh (4 bytes) */
Stream_Write_UINT32(s, fileContentsRequest->cbRequested); /* cbRequested (4 bytes) */
Stream_Write_UINT32(s, fileContentsRequest->clipDataId); /* clipDataId (4 bytes) */
WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientFileContentsRequest: streamId: 0x%04X",
fileContentsRequest->streamId);
cliprdr_packet_send(cliprdr, s);
return 1;
}
int cliprdr_client_file_contents_response(CliprdrClientContext* context, CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
{
wStream* s;
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
if (fileContentsResponse->dwFlags & FILECONTENTS_SIZE)
fileContentsResponse->cbRequested = sizeof(UINT64);
s = cliprdr_packet_new(CB_FILECONTENTS_REQUEST, 0,
4 + fileContentsResponse->cbRequested);
Stream_Write_UINT32(s, fileContentsResponse->streamId); /* streamId (4 bytes) */
/**
* requestedFileContentsData:
* FILECONTENTS_SIZE: file size as UINT64
* FILECONTENTS_RANGE: file data from requested range
*/
Stream_Write(s, fileContentsResponse->requestedData, fileContentsResponse->cbRequested);
WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientFileContentsResponse: streamId: 0x%04X",
fileContentsResponse->streamId);
cliprdr_packet_send(cliprdr, s);
return 1;
}
/* cliprdr is always built-in */ /* cliprdr is always built-in */
#define VirtualChannelEntry cliprdr_VirtualChannelEntry #define VirtualChannelEntry cliprdr_VirtualChannelEntry
@ -626,10 +850,15 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
context = (CliprdrClientContext*) calloc(1, sizeof(CliprdrClientContext)); context = (CliprdrClientContext*) calloc(1, sizeof(CliprdrClientContext));
context->handle = (void*) cliprdr; context->handle = (void*) cliprdr;
context->ClientCapabilities = cliprdr_client_capabilities; context->ClientCapabilities = cliprdr_client_capabilities;
context->TempDirectory = cliprdr_temp_directory;
context->ClientFormatList = cliprdr_client_format_list; context->ClientFormatList = cliprdr_client_format_list;
context->ClientFormatListResponse = cliprdr_client_format_list_response; context->ClientFormatListResponse = cliprdr_client_format_list_response;
context->ClientLockClipboardData = cliprdr_client_lock_clipboard_data;
context->ClientUnlockClipboardData = cliprdr_client_unlock_clipboard_data;
context->ClientFormatDataRequest = cliprdr_client_format_data_request; context->ClientFormatDataRequest = cliprdr_client_format_data_request;
context->ClientFormatDataResponse = cliprdr_client_format_data_response; context->ClientFormatDataResponse = cliprdr_client_format_data_response;
context->ClientFileContentsRequest = cliprdr_client_file_contents_request;
context->ClientFileContentsResponse = cliprdr_client_file_contents_response;
*(pEntryPointsEx->ppInterface) = (void*) context; *(pEntryPointsEx->ppInterface) = (void*) context;
} }

View File

@ -107,9 +107,6 @@ ULONG STDMETHODCALLTYPE CliprdrStream_Release(IStream* This)
} }
} }
#define FILECONTENTS_SIZE 0x00000001
#define FILECONTENTS_RANGE 0x00000002
HRESULT STDMETHODCALLTYPE CliprdrStream_Read(IStream* This, void *pv, ULONG cb, ULONG *pcbRead) HRESULT STDMETHODCALLTYPE CliprdrStream_Read(IStream* This, void *pv, ULONG cb, ULONG *pcbRead)
{ {
int ret; int ret;
@ -1215,7 +1212,7 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM
case WM_CLIPBOARDUPDATE: case WM_CLIPBOARDUPDATE:
DEBUG_CLIPRDR("info: %s - WM_CLIPBOARDUPDATE", __FUNCTION__); DEBUG_CLIPRDR("info: %s - WM_CLIPBOARDUPDATE", __FUNCTION__);
if (clipboard->channel_initialized) if (clipboard->sync)
{ {
if ((GetClipboardOwner() != clipboard->hwnd) && if ((GetClipboardOwner() != clipboard->hwnd) &&
(S_FALSE == OleIsCurrentClipboard(clipboard->data_obj))) (S_FALSE == OleIsCurrentClipboard(clipboard->data_obj)))
@ -1407,14 +1404,7 @@ static void wf_cliprdr_process_cb_clip_caps_event(wfClipboard* clipboard, RDP_CB
static void wf_cliprdr_process_cb_monitor_ready_event(wfClipboard* clipboard, RDP_CB_MONITOR_READY_EVENT* ready_event) static void wf_cliprdr_process_cb_monitor_ready_event(wfClipboard* clipboard, RDP_CB_MONITOR_READY_EVENT* ready_event)
{ {
#if 0 clipboard->sync = TRUE;
/*Disabled since the current function only sends the temp directory which is not
guaranteed to be accessible to the server
*/
cliprdr_send_tempdir(clipboard);
#endif
clipboard->channel_initialized = TRUE;
cliprdr_send_format_list(clipboard); cliprdr_send_format_list(clipboard);
} }
@ -2143,18 +2133,88 @@ void wf_process_cliprdr_event(wfContext* wfc, wMessage* event)
static int wf_cliprdr_monitor_ready(CliprdrClientContext* context, CLIPRDR_MONITOR_READY* monitorReady) static int wf_cliprdr_monitor_ready(CliprdrClientContext* context, CLIPRDR_MONITOR_READY* monitorReady)
{ {
wfClipboard* clipboard = (wfClipboard*) context->custom; wfClipboard* clipboard = (wfClipboard*) context->custom;
clipboard->sync = TRUE;
cliprdr_send_format_list(clipboard);
return 1; return 1;
} }
static int wf_cliprdr_server_capabilities(CliprdrClientContext* context, CLIPRDR_CAPABILITIES* capabilities) static int wf_cliprdr_server_capabilities(CliprdrClientContext* context, CLIPRDR_CAPABILITIES* capabilities)
{ {
UINT32 index;
CLIPRDR_CAPABILITY_SET* capabilitySet;
wfClipboard* clipboard = (wfClipboard*) context->custom; wfClipboard* clipboard = (wfClipboard*) context->custom;
for (index = 0; index < capabilities->cCapabilitiesSets; index++)
{
capabilitySet = &(capabilities->capabilitySets[index]);
if ((capabilitySet->capabilitySetType == CB_CAPSTYPE_GENERAL) &&
(capabilitySet->capabilitySetLength >= CB_CAPSTYPE_GENERAL_LEN))
{
CLIPRDR_GENERAL_CAPABILITY_SET* generalCapabilitySet
= (CLIPRDR_GENERAL_CAPABILITY_SET*) capabilitySet;
clipboard->capabilities = generalCapabilitySet->generalFlags;
break;
}
}
return 1; return 1;
} }
static int wf_cliprdr_server_format_list(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList) static int wf_cliprdr_server_format_list(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList)
{ {
UINT32 i, j;
formatMapping* mapping;
CLIPRDR_FORMAT* format;
wfClipboard* clipboard = (wfClipboard*) context->custom; wfClipboard* clipboard = (wfClipboard*) context->custom;
clear_format_map(clipboard);
for (i = j = 0; i < formatList->numFormats; i++)
{
format = &(formatList->formats[i]);
mapping = &(clipboard->format_mappings[j++]);
mapping->remote_format_id = format->formatId;
if (format->formatName)
{
mapping->name = _strdup(format->formatName);
mapping->local_format_id = RegisterClipboardFormatA((LPCSTR) mapping->name);
}
else
{
mapping->name = NULL;
mapping->local_format_id = mapping->remote_format_id;
}
clipboard->map_size++;
map_ensure_capacity(clipboard);
}
if (file_transferring(clipboard))
{
PostMessage(clipboard->hwnd, WM_CLIPRDR_MESSAGE, OLE_SETCLIPBOARD, 0);
}
else
{
if (!OpenClipboard(clipboard->hwnd))
return -1;
if (EmptyClipboard())
{
for (i = 0; i < (UINT32) clipboard->map_size; i++)
{
SetClipboardData(clipboard->format_mappings[i].local_format_id, NULL);
}
}
CloseClipboard();
}
return 1; return 1;
} }
@ -2164,13 +2224,238 @@ static int wf_cliprdr_server_format_list_response(CliprdrClientContext* context,
return 1; return 1;
} }
static int wf_cliprdr_server_format_data_request(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest) int wf_cliprdr_server_lock_clipboard_data(CliprdrClientContext* context, CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
{ {
wfClipboard* clipboard = (wfClipboard*) context->custom; wfClipboard* clipboard = (wfClipboard*) context->custom;
return 1; return 1;
} }
int wf_cliprdr_server_unlock_clipboard_data(CliprdrClientContext* context, CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
{
wfClipboard* clipboard = (wfClipboard*) context->custom;
return 1;
}
static int wf_cliprdr_server_format_data_request(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
{
int size = 0;
char* buff = NULL;
char* globlemem = NULL;
HANDLE hClipdata = NULL;
UINT32 requestedFormatId;
CLIPRDR_FORMAT_DATA_RESPONSE response;
wfClipboard* clipboard = (wfClipboard*) context->custom;
requestedFormatId = formatDataRequest->requestedFormatId;
if (requestedFormatId == RegisterClipboardFormatW(_T("FileGroupDescriptorW")))
{
int len;
int i;
WCHAR* wFileName;
unsigned int uSize;
HRESULT result;
LPDATAOBJECT dataObj;
FORMATETC format_etc;
STGMEDIUM stg_medium;
DROPFILES* dropFiles;
result = OleGetClipboard(&dataObj);
if (!SUCCEEDED(result))
return -1;
ZeroMemory(&format_etc, sizeof(FORMATETC));
ZeroMemory(&stg_medium, sizeof(STGMEDIUM));
/* try to get FileGroupDescriptorW struct from OLE */
format_etc.cfFormat = requestedFormatId;
format_etc.tymed = TYMED_HGLOBAL;
format_etc.dwAspect = 1;
format_etc.lindex = -1;
format_etc.ptd = 0;
result = IDataObject_GetData(dataObj, &format_etc, &stg_medium);
if (SUCCEEDED(result))
{
DEBUG_CLIPRDR("Got FileGroupDescriptorW.");
globlemem = (char*) GlobalLock(stg_medium.hGlobal);
uSize = GlobalSize(stg_medium.hGlobal);
size = uSize;
buff = (char*) malloc(uSize);
CopyMemory(buff, globlemem, uSize);
GlobalUnlock(stg_medium.hGlobal);
ReleaseStgMedium(&stg_medium);
clear_file_array(clipboard);
}
else
{
/* get DROPFILES struct from OLE */
format_etc.cfFormat = CF_HDROP;
format_etc.tymed = TYMED_HGLOBAL;
format_etc.dwAspect = 1;
format_etc.lindex = -1;
result = IDataObject_GetData(dataObj, &format_etc, &stg_medium);
if (!SUCCEEDED(result)) {
DEBUG_CLIPRDR("dataObj->GetData failed.");
}
globlemem = (char*) GlobalLock(stg_medium.hGlobal);
if (!globlemem)
{
GlobalUnlock(stg_medium.hGlobal);
ReleaseStgMedium(&stg_medium);
clipboard->nFiles = 0;
goto exit;
}
uSize = GlobalSize(stg_medium.hGlobal);
dropFiles = (DROPFILES*) malloc(uSize);
memcpy(dropFiles, globlemem, uSize);
GlobalUnlock(stg_medium.hGlobal);
ReleaseStgMedium(&stg_medium);
clear_file_array(clipboard);
if (dropFiles->fWide)
{
WCHAR* p;
int str_len;
int offset;
int pathLen;
/* dropFiles contains file names */
for (wFileName = (WCHAR*)((char*)dropFiles + dropFiles->pFiles); (len = wcslen(wFileName)) > 0; wFileName += len + 1)
{
/* get path name */
str_len = wcslen(wFileName);
offset = str_len;
/* find the last '\' in full file name */
for (p = wFileName + offset; *p != L'\\'; p--)
{
;
}
p += 1;
pathLen = wcslen(wFileName) - wcslen(p);
wf_cliprdr_add_to_file_arrays(clipboard, wFileName, pathLen);
if ((clipboard->fileDescriptor[clipboard->nFiles - 1]->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
{
/* this is a directory */
wf_cliprdr_traverse_directory(clipboard, wFileName, pathLen);
}
}
}
else
{
char* p;
for (p = (char*)((char*)dropFiles + dropFiles->pFiles); (len = strlen(p)) > 0; p += len + 1, clipboard->nFiles++)
{
int cchWideChar;
cchWideChar = MultiByteToWideChar(CP_ACP, MB_COMPOSITE, p, len, NULL, 0);
clipboard->file_names[clipboard->nFiles] = (LPWSTR) malloc(cchWideChar * 2);
MultiByteToWideChar(CP_ACP, MB_COMPOSITE, p, len, clipboard->file_names[clipboard->nFiles], cchWideChar);
if (clipboard->nFiles == clipboard->file_array_size)
{
clipboard->file_array_size *= 2;
clipboard->fileDescriptor = (FILEDESCRIPTORW**) realloc(clipboard->fileDescriptor, clipboard->file_array_size * sizeof(FILEDESCRIPTORW*));
clipboard->file_names = (WCHAR**) realloc(clipboard->file_names, clipboard->file_array_size * sizeof(WCHAR*));
}
}
}
exit:
size = 4 + clipboard->nFiles * sizeof(FILEDESCRIPTORW);
buff = (char*) malloc(size);
*((UINT32*) buff) = clipboard->nFiles;
for (i = 0; i < clipboard->nFiles; i++)
{
if (clipboard->fileDescriptor[i])
{
memcpy(buff + 4 + i * sizeof(FILEDESCRIPTORW), clipboard->fileDescriptor[i], sizeof(FILEDESCRIPTORW));
}
}
}
IDataObject_Release(dataObj);
}
else
{
if (!OpenClipboard(clipboard->hwnd))
return -1;
hClipdata = GetClipboardData(requestedFormatId);
if (!hClipdata)
{
CloseClipboard();
return -1;
}
globlemem = (char*) GlobalLock(hClipdata);
size = (int) GlobalSize(hClipdata);
buff = (char*) malloc(size);
CopyMemory(buff, globlemem, size);
GlobalUnlock(hClipdata);
CloseClipboard();
}
ZeroMemory(&response, sizeof(CLIPRDR_FORMAT_DATA_RESPONSE));
response.msgFlags = CB_RESPONSE_OK;
response.dataLen = size;
response.requestedFormatData = (BYTE*) buff;
clipboard->context->ClientFormatDataResponse(clipboard->context, &response);
free(buff);
return 1;
}
static int wf_cliprdr_server_format_data_response(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse) static int wf_cliprdr_server_format_data_response(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
{
BYTE* data;
HANDLE hMem;
wfClipboard* clipboard = (wfClipboard*) context->custom;
hMem = GlobalAlloc(GMEM_FIXED, formatDataResponse->dataLen);
data = (BYTE*) GlobalLock(hMem);
CopyMemory(data, formatDataResponse->requestedFormatData, formatDataResponse->dataLen);
GlobalUnlock(hMem);
clipboard->hmem = hMem;
SetEvent(clipboard->response_data_event);
return 1;
}
int wf_cliprdr_server_file_contents_request(CliprdrClientContext* context, CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
{
wfClipboard* clipboard = (wfClipboard*) context->custom;
return 1;
}
int wf_cliprdr_server_file_contents_response(CliprdrClientContext* context, CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
{ {
wfClipboard* clipboard = (wfClipboard*) context->custom; wfClipboard* clipboard = (wfClipboard*) context->custom;
return 1; return 1;
@ -2188,6 +2473,7 @@ void wf_cliprdr_init(wfContext* wfc, CliprdrClientContext* cliprdr)
clipboard = wfc->clipboard; clipboard = wfc->clipboard;
clipboard->wfc = wfc; clipboard->wfc = wfc;
clipboard->context = cliprdr;
if (0) if (0)
{ {
@ -2197,12 +2483,16 @@ void wf_cliprdr_init(wfContext* wfc, CliprdrClientContext* cliprdr)
cliprdr->ServerCapabilities = wf_cliprdr_server_capabilities; cliprdr->ServerCapabilities = wf_cliprdr_server_capabilities;
cliprdr->ServerFormatList = wf_cliprdr_server_format_list; cliprdr->ServerFormatList = wf_cliprdr_server_format_list;
cliprdr->ServerFormatListResponse = wf_cliprdr_server_format_list_response; cliprdr->ServerFormatListResponse = wf_cliprdr_server_format_list_response;
cliprdr->ServerLockClipboardData = wf_cliprdr_server_lock_clipboard_data;
cliprdr->ServerUnlockClipboardData = wf_cliprdr_server_unlock_clipboard_data;
cliprdr->ServerFormatDataRequest = wf_cliprdr_server_format_data_request; cliprdr->ServerFormatDataRequest = wf_cliprdr_server_format_data_request;
cliprdr->ServerFormatDataResponse = wf_cliprdr_server_format_data_response; cliprdr->ServerFormatDataResponse = wf_cliprdr_server_format_data_response;
cliprdr->ServerFileContentsRequest = wf_cliprdr_server_file_contents_request;
cliprdr->ServerFileContentsResponse = wf_cliprdr_server_file_contents_response;
} }
clipboard->channels = context->channels; clipboard->channels = context->channels;
clipboard->channel_initialized = FALSE; clipboard->sync = FALSE;
clipboard->map_capacity = 32; clipboard->map_capacity = 32;
clipboard->map_size = 0; clipboard->map_size = 0;

View File

@ -95,7 +95,9 @@ struct wf_clipboard
{ {
wfContext* wfc; wfContext* wfc;
rdpChannels* channels; rdpChannels* channels;
CliprdrClientContext* context;
BOOL sync;
UINT32 capabilities; UINT32 capabilities;
int map_size; int map_size;
@ -103,7 +105,6 @@ struct wf_clipboard
formatMapping* format_mappings; formatMapping* format_mappings;
UINT32 request_format; UINT32 request_format;
BOOL channel_initialized;
HWND hwnd; HWND hwnd;
HANDLE hmem; HANDLE hmem;

View File

@ -68,6 +68,10 @@
#define CB_FILECLIP_NO_FILE_PATHS 0x00000008 #define CB_FILECLIP_NO_FILE_PATHS 0x00000008
#define CB_CAN_LOCK_CLIPDATA 0x00000010 #define CB_CAN_LOCK_CLIPDATA 0x00000010
/* File Contents Request Flags */
#define FILECONTENTS_SIZE 0x00000001
#define FILECONTENTS_RANGE 0x00000002
#define DEFINE_CLIPRDR_HEADER_COMMON() \ #define DEFINE_CLIPRDR_HEADER_COMMON() \
UINT16 msgType; \ UINT16 msgType; \
UINT16 msgFlags; \ UINT16 msgFlags; \
@ -111,6 +115,14 @@ struct _CLIPRDR_MONITOR_READY
}; };
typedef struct _CLIPRDR_MONITOR_READY CLIPRDR_MONITOR_READY; typedef struct _CLIPRDR_MONITOR_READY CLIPRDR_MONITOR_READY;
struct _CLIPRDR_TEMP_DIRECTORY
{
DEFINE_CLIPRDR_HEADER_COMMON();
char szTempDir[520];
};
typedef struct _CLIPRDR_TEMP_DIRECTORY CLIPRDR_TEMP_DIRECTORY;
struct _CLIPRDR_FORMAT struct _CLIPRDR_FORMAT
{ {
UINT32 formatId; UINT32 formatId;
@ -133,6 +145,22 @@ struct _CLIPRDR_FORMAT_LIST_RESPONSE
}; };
typedef struct _CLIPRDR_FORMAT_LIST_RESPONSE CLIPRDR_FORMAT_LIST_RESPONSE; typedef struct _CLIPRDR_FORMAT_LIST_RESPONSE CLIPRDR_FORMAT_LIST_RESPONSE;
struct _CLIPRDR_LOCK_CLIPBOARD_DATA
{
DEFINE_CLIPRDR_HEADER_COMMON();
UINT32 clipDataId;
};
typedef struct _CLIPRDR_LOCK_CLIPBOARD_DATA CLIPRDR_LOCK_CLIPBOARD_DATA;
struct _CLIPRDR_UNLOCK_CLIPBOARD_DATA
{
DEFINE_CLIPRDR_HEADER_COMMON();
UINT32 clipDataId;
};
typedef struct _CLIPRDR_UNLOCK_CLIPBOARD_DATA CLIPRDR_UNLOCK_CLIPBOARD_DATA;
struct _CLIPRDR_FORMAT_DATA_REQUEST struct _CLIPRDR_FORMAT_DATA_REQUEST
{ {
DEFINE_CLIPRDR_HEADER_COMMON(); DEFINE_CLIPRDR_HEADER_COMMON();
@ -149,5 +177,30 @@ struct _CLIPRDR_FORMAT_DATA_RESPONSE
}; };
typedef struct _CLIPRDR_FORMAT_DATA_RESPONSE CLIPRDR_FORMAT_DATA_RESPONSE; typedef struct _CLIPRDR_FORMAT_DATA_RESPONSE CLIPRDR_FORMAT_DATA_RESPONSE;
struct _CLIPRDR_FILE_CONTENTS_REQUEST
{
DEFINE_CLIPRDR_HEADER_COMMON();
UINT32 streamId;
UINT32 listIndex;
UINT32 dwFlags;
UINT32 nPositionLow;
UINT32 nPositionHigh;
UINT32 cbRequested;
UINT32 clipDataId;
};
typedef struct _CLIPRDR_FILE_CONTENTS_REQUEST CLIPRDR_FILE_CONTENTS_REQUEST;
struct _CLIPRDR_FILE_CONTENTS_RESPONSE
{
DEFINE_CLIPRDR_HEADER_COMMON();
UINT32 streamId;
UINT32 dwFlags;
UINT32 cbRequested;
BYTE* requestedData;
};
typedef struct _CLIPRDR_FILE_CONTENTS_RESPONSE CLIPRDR_FILE_CONTENTS_RESPONSE;
#endif /* FREERDP_CHANNEL_CLIPRDR_H */ #endif /* FREERDP_CHANNEL_CLIPRDR_H */

View File

@ -34,14 +34,23 @@ typedef struct _cliprdr_client_context CliprdrClientContext;
typedef int (*pcCliprdrServerCapabilities)(CliprdrClientContext* context, CLIPRDR_CAPABILITIES* capabilities); typedef int (*pcCliprdrServerCapabilities)(CliprdrClientContext* context, CLIPRDR_CAPABILITIES* capabilities);
typedef int (*pcCliprdrClientCapabilities)(CliprdrClientContext* context, CLIPRDR_CAPABILITIES* capabilities); typedef int (*pcCliprdrClientCapabilities)(CliprdrClientContext* context, CLIPRDR_CAPABILITIES* capabilities);
typedef int (*pcCliprdrMonitorReady)(CliprdrClientContext* context, CLIPRDR_MONITOR_READY* monitorReady); typedef int (*pcCliprdrMonitorReady)(CliprdrClientContext* context, CLIPRDR_MONITOR_READY* monitorReady);
typedef int (*pcCliprdrTempDirectory)(CliprdrClientContext* context, CLIPRDR_TEMP_DIRECTORY* tempDirectory);
typedef int (*pcCliprdrClientFormatList)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList); typedef int (*pcCliprdrClientFormatList)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList);
typedef int (*pcCliprdrServerFormatList)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList); typedef int (*pcCliprdrServerFormatList)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList);
typedef int (*pcCliprdrClientFormatListResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse); typedef int (*pcCliprdrClientFormatListResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse);
typedef int (*pcCliprdrServerFormatListResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse); typedef int (*pcCliprdrServerFormatListResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse);
typedef int (*pcCliprdrClientLockClipboardData)(CliprdrClientContext* context, CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData);
typedef int (*pcCliprdrServerLockClipboardData)(CliprdrClientContext* context, CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData);
typedef int (*pcCliprdrClientUnlockClipboardData)(CliprdrClientContext* context, CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData);
typedef int (*pcCliprdrServerUnlockClipboardData)(CliprdrClientContext* context, CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData);
typedef int (*pcCliprdrClientFormatDataRequest)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest); typedef int (*pcCliprdrClientFormatDataRequest)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest);
typedef int (*pcCliprdrServerFormatDataRequest)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest); typedef int (*pcCliprdrServerFormatDataRequest)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest);
typedef int (*pcCliprdrClientFormatDataResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse); typedef int (*pcCliprdrClientFormatDataResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse);
typedef int (*pcCliprdrServerFormatDataResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse); typedef int (*pcCliprdrServerFormatDataResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse);
typedef int (*pcCliprdrClientFileContentsRequest)(CliprdrClientContext* context, CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest);
typedef int (*pcCliprdrServerFileContentsRequest)(CliprdrClientContext* context, CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest);
typedef int (*pcCliprdrClientFileContentsResponse)(CliprdrClientContext* context, CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse);
typedef int (*pcCliprdrServerFileContentsResponse)(CliprdrClientContext* context, CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse);
struct _cliprdr_client_context struct _cliprdr_client_context
{ {
@ -51,14 +60,23 @@ struct _cliprdr_client_context
pcCliprdrServerCapabilities ServerCapabilities; pcCliprdrServerCapabilities ServerCapabilities;
pcCliprdrClientCapabilities ClientCapabilities; pcCliprdrClientCapabilities ClientCapabilities;
pcCliprdrMonitorReady MonitorReady; pcCliprdrMonitorReady MonitorReady;
pcCliprdrTempDirectory TempDirectory;
pcCliprdrClientFormatList ClientFormatList; pcCliprdrClientFormatList ClientFormatList;
pcCliprdrServerFormatList ServerFormatList; pcCliprdrServerFormatList ServerFormatList;
pcCliprdrClientFormatListResponse ClientFormatListResponse; pcCliprdrClientFormatListResponse ClientFormatListResponse;
pcCliprdrServerFormatListResponse ServerFormatListResponse; pcCliprdrServerFormatListResponse ServerFormatListResponse;
pcCliprdrClientLockClipboardData ClientLockClipboardData;
pcCliprdrServerLockClipboardData ServerLockClipboardData;
pcCliprdrClientUnlockClipboardData ClientUnlockClipboardData;
pcCliprdrServerUnlockClipboardData ServerUnlockClipboardData;
pcCliprdrClientFormatDataRequest ClientFormatDataRequest; pcCliprdrClientFormatDataRequest ClientFormatDataRequest;
pcCliprdrServerFormatDataRequest ServerFormatDataRequest; pcCliprdrServerFormatDataRequest ServerFormatDataRequest;
pcCliprdrClientFormatDataResponse ClientFormatDataResponse; pcCliprdrClientFormatDataResponse ClientFormatDataResponse;
pcCliprdrServerFormatDataResponse ServerFormatDataResponse; pcCliprdrServerFormatDataResponse ServerFormatDataResponse;
pcCliprdrClientFileContentsRequest ClientFileContentsRequest;
pcCliprdrServerFileContentsRequest ServerFileContentsRequest;
pcCliprdrClientFileContentsResponse ClientFileContentsResponse;
pcCliprdrServerFileContentsResponse ServerFileContentsResponse;
}; };
struct _CLIPRDR_FORMAT_NAME struct _CLIPRDR_FORMAT_NAME