diff --git a/channels/cliprdr/cliprdr_format.c b/channels/cliprdr/cliprdr_format.c index 1a7cc80b9..166ed112f 100644 --- a/channels/cliprdr/cliprdr_format.c +++ b/channels/cliprdr/cliprdr_format.c @@ -65,3 +65,70 @@ void cliprdr_process_format_list_event(cliprdrPlugin* cliprdr, FRDP_CB_FORMAT_LI cliprdr_packet_send(cliprdr, data_out); } + +static void cliprdr_send_format_list_response(cliprdrPlugin* cliprdr) +{ + STREAM* data_out; + + data_out = cliprdr_packet_new(CB_FORMAT_LIST_RESPONSE, CB_RESPONSE_OK, 0); + cliprdr_packet_send(cliprdr, data_out); +} + +void cliprdr_process_format_list(cliprdrPlugin* cliprdr, STREAM* data_in, uint32 dataLen) +{ + FRDP_CB_FORMAT_LIST_EVENT* cb_event; + uint32 format; + int num_formats; + int supported; + int i; + + cb_event = (FRDP_CB_FORMAT_LIST_EVENT*)freerdp_event_new(FRDP_EVENT_TYPE_CB_FORMAT_LIST, NULL, NULL); + num_formats = dataLen / 36; + cb_event->formats = (uint32*)xmalloc(sizeof(uint32) * num_formats); + cb_event->num_formats = 0; + if (num_formats * 36 != dataLen) + DEBUG_WARN("dataLen %d not devided by 36!"); + for (i = 0; i < num_formats; i++) + { + stream_read_uint32(data_in, format); + supported = 1; + switch (format) + { + case CB_FORMAT_TEXT: + case CB_FORMAT_DIB: + case CB_FORMAT_UNICODETEXT: + break; + + default: + if (memcmp(stream_get_tail(data_in), CFSTR_HTML, sizeof(CFSTR_HTML)) == 0) + { + format = CB_FORMAT_HTML; + break; + } + if (memcmp(stream_get_tail(data_in), CFSTR_PNG, sizeof(CFSTR_PNG)) == 0) + { + format = CB_FORMAT_PNG; + break; + } + if (memcmp(stream_get_tail(data_in), CFSTR_JPEG, sizeof(CFSTR_JPEG)) == 0) + { + format = CB_FORMAT_JPEG; + break; + } + if (memcmp(stream_get_tail(data_in), CFSTR_GIF, sizeof(CFSTR_GIF)) == 0) + { + format = CB_FORMAT_GIF; + break; + } + supported = 0; + break; + } + stream_seek(data_in, 32); + + if (supported) + cb_event->formats[cb_event->num_formats++] = format; + } + + svc_plugin_send_event((rdpSvcPlugin*)cliprdr, (FRDP_EVENT*)cb_event); + cliprdr_send_format_list_response(cliprdr); +} diff --git a/channels/cliprdr/cliprdr_format.h b/channels/cliprdr/cliprdr_format.h index 894e12d73..4abddc0e4 100644 --- a/channels/cliprdr/cliprdr_format.h +++ b/channels/cliprdr/cliprdr_format.h @@ -22,5 +22,6 @@ #define __CLIPRDR_FORMAT_H void cliprdr_process_format_list_event(cliprdrPlugin* cliprdr, FRDP_CB_FORMAT_LIST_EVENT* cb_event); +void cliprdr_process_format_list(cliprdrPlugin* cliprdr, STREAM* data_in, uint32 dataLen); #endif /* __CLIPRDR_FORMAT_H */ diff --git a/channels/cliprdr/cliprdr_main.c b/channels/cliprdr/cliprdr_main.c index f0e2819b1..13d342fd5 100644 --- a/channels/cliprdr/cliprdr_main.c +++ b/channels/cliprdr/cliprdr_main.c @@ -119,6 +119,10 @@ static void cliprdr_process_receive(rdpSvcPlugin* plugin, STREAM* data_in) cliprdr_process_monitor_ready(cliprdr); break; + case CB_FORMAT_LIST: + cliprdr_process_format_list(cliprdr, data_in, dataLen); + break; + default: DEBUG_WARN("unknown msgType %d", msgType); break; diff --git a/cunit/test_cliprdr.c b/cunit/test_cliprdr.c index 5836dbd77..cacf49978 100644 --- a/cunit/test_cliprdr.c +++ b/cunit/test_cliprdr.c @@ -60,10 +60,19 @@ static const uint8 test_monitor_ready_data[] = "\x01\x00\x00\x00\x00\x00\x00\x00" }; +static const uint8 test_format_list_data[] = +{ + "\x02\x00\x00\x00\x48\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\xd0\x00\x00" + "\x48\x00\x54\x00\x4D\x00\x4C\x00\x20\x00\x46\x00\x6F\x00\x72\x00" + "\x6D\x00\x61\x00\x74\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +}; + static int test_rdp_channel_data(rdpInst* inst, int chan_id, char* data, int data_size) { printf("chan_id %d data_size %d\n", chan_id, data_size); - freerdp_hexdump(data, data_size); + /*freerdp_hexdump(data, data_size);*/ } static int event_processed; @@ -81,6 +90,7 @@ void test_cliprdr(void) rdpInst inst = { 0 }; FRDP_EVENT* event; FRDP_CB_FORMAT_LIST_EVENT* format_list_event; + int i; settings.hostname = "testhost"; inst.settings = &settings; @@ -92,12 +102,14 @@ void test_cliprdr(void) freerdp_chanman_pre_connect(chan_man, &inst); freerdp_chanman_post_connect(chan_man, &inst); + /* server sends cliprdr capabilities and monitor ready PDU */ freerdp_chanman_data(&inst, 0, (char*)test_clip_caps_data, sizeof(test_clip_caps_data) - 1, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, sizeof(test_clip_caps_data) - 1); freerdp_chanman_data(&inst, 0, (char*)test_monitor_ready_data, sizeof(test_monitor_ready_data) - 1, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, sizeof(test_monitor_ready_data) - 1); + /* cliprdr sends clipboard_sync event to UI */ while ((event = freerdp_chanman_pop_event(chan_man)) == NULL) { freerdp_chanman_check_fds(chan_man, &inst); @@ -106,6 +118,7 @@ void test_cliprdr(void) CU_ASSERT(event->event_type == FRDP_EVENT_TYPE_CB_SYNC); freerdp_event_free(event); + /* UI sends format_list event to cliprdr */ event = freerdp_event_new(FRDP_EVENT_TYPE_CB_FORMAT_LIST, event_process_callback, NULL); format_list_event = (FRDP_CB_FORMAT_LIST_EVENT*)event; format_list_event->num_formats = 2; @@ -113,6 +126,7 @@ void test_cliprdr(void) format_list_event->formats[0] = CB_FORMAT_TEXT; format_list_event->formats[1] = CB_FORMAT_HTML; + /* cliprdr sends format list PDU to server */ event_processed = 0; freerdp_chanman_send_event(chan_man, "cliprdr", event); while (!event_processed) @@ -120,6 +134,25 @@ void test_cliprdr(void) freerdp_chanman_check_fds(chan_man, &inst); } + /* server sends format list PDU to cliprdr */ + freerdp_chanman_data(&inst, 0, (char*)test_format_list_data, sizeof(test_format_list_data) - 1, + CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, sizeof(test_format_list_data) - 1); + + /* cliprdr sends format_list event to UI */ + while ((event = freerdp_chanman_pop_event(chan_man)) == NULL) + { + freerdp_chanman_check_fds(chan_man, &inst); + } + printf("Got event %d\n", event->event_type); + CU_ASSERT(event->event_type == FRDP_EVENT_TYPE_CB_FORMAT_LIST); + if (event->event_type == FRDP_EVENT_TYPE_CB_FORMAT_LIST) + { + format_list_event = (FRDP_CB_FORMAT_LIST_EVENT*)event; + for (i = 0; i < format_list_event->num_formats; i++) + printf("Format: 0x%X\n", format_list_event->formats[i]); + } + freerdp_event_free(event); + freerdp_chanman_close(chan_man, &inst); freerdp_chanman_free(chan_man); }