diff --git a/channels/rail/rail_main.c b/channels/rail/rail_main.c index ca00d45d6..34dceb66e 100644 --- a/channels/rail/rail_main.c +++ b/channels/rail/rail_main.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "rail_orders.h" @@ -44,15 +45,25 @@ void rail_send_channel_data(void* rail_object, void* data, size_t length) static void on_free_rail_channel_event(RDP_EVENT* event) { - + if (event->event_class == RDP_EVENT_CLASS_RAIL) + { + rail_free_cloned_order(event->event_type, event->user_data); + } } void rail_send_channel_event(void* rail_object, uint16 event_type, void* param) { RDP_EVENT* out_event = NULL; railPlugin* plugin = (railPlugin*) rail_object; - out_event = freerdp_event_new(RDP_EVENT_CLASS_RAIL, event_type, on_free_rail_channel_event, param); - svc_plugin_send_event((rdpSvcPlugin*) plugin, out_event); + void * payload = NULL; + + payload = rail_clone_order(event_type, param); + if (payload != NULL) + { + out_event = freerdp_event_new(RDP_EVENT_CLASS_RAIL, event_type, + on_free_rail_channel_event, payload); + svc_plugin_send_event((rdpSvcPlugin*) plugin, out_event); + } } static void rail_process_connect(rdpSvcPlugin* plugin) diff --git a/client/X11/xf_rail.c b/client/X11/xf_rail.c index 20523f6df..744585d8c 100644 --- a/client/X11/xf_rail.c +++ b/client/X11/xf_rail.c @@ -19,6 +19,7 @@ #include #include +#include #include @@ -128,9 +129,30 @@ void xf_rail_register_callbacks(xfInfo* xfi, rdpRail* rail) rail->DestroyWindow = xf_rail_DestroyWindow; } +static void xf_on_free_rail_client_event(RDP_EVENT* event) +{ + if (event->event_class == RDP_EVENT_CLASS_RAIL) + { + rail_free_cloned_order(event->event_type, event->user_data); + } +} + +static void xf_send_rail_client_event(rdpChanMan* chanman, uint16 event_type, void* param) +{ + RDP_EVENT* out_event = NULL; + void * payload = NULL; + + payload = rail_clone_order(event_type, param); + if (payload != NULL) + { + out_event = freerdp_event_new(RDP_EVENT_CLASS_RAIL, event_type, + xf_on_free_rail_client_event, payload); + freerdp_chanman_send_event(chanman, out_event); + } +} + void xf_process_rail_get_sysparams_event(xfInfo* xfi, rdpChanMan* chanman, RDP_EVENT* event) { - RDP_EVENT* new_event; RAIL_SYSPARAM_ORDER* sysparam; sysparam = (RAIL_SYSPARAM_ORDER*) event->user_data; @@ -150,10 +172,7 @@ void xf_process_rail_get_sysparams_event(xfInfo* xfi, rdpChanMan* chanman, RDP_E sysparam->taskbarPos.right = 0; sysparam->taskbarPos.bottom = 0; - new_event = freerdp_event_new(RDP_EVENT_CLASS_RAIL, - RDP_EVENT_TYPE_RAIL_CLIENT_SET_SYSPARAMS, NULL, sysparam); - - freerdp_chanman_send_event(chanman, new_event); + xf_send_rail_client_event(chanman, RDP_EVENT_TYPE_RAIL_CLIENT_SET_SYSPARAMS, sysparam); } const char* error_code_names[] = diff --git a/cunit/test_rail.c b/cunit/test_rail.c index 9de6502cd..67774e582 100644 --- a/cunit/test_rail.c +++ b/cunit/test_rail.c @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -378,8 +379,6 @@ static uint8 server_app_get_resp_app_id[] = }; -#define RAIL_ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0])) - #define EMULATE_SERVER_SEND_CHANNEL_DATA(inst, byte_array) \ emulate_server_send_channel_data(inst, byte_array, RAIL_ARRAY_SIZE(byte_array)) @@ -477,6 +476,14 @@ int stream_equal_dump(void * dataS, size_t sizeS, void * data, size_t size) return 1; } //----------------------------------------------------------------------------- +static void test_on_free_rail_client_event(RDP_EVENT* event) +{ + if (event->event_class == RDP_EVENT_CLASS_RAIL) + { + rail_free_cloned_order(event->event_type, event->user_data); + } +} +//----------------------------------------------------------------------------- static void send_ui_event2plugin( rdpChanMan* chan_man, uint16 event_type, @@ -484,10 +491,15 @@ static void send_ui_event2plugin( ) { RDP_EVENT* out_event = NULL; - out_event = freerdp_event_new(RDP_EVENT_CLASS_RAIL, event_type, - NULL, data); + void * payload = NULL; - freerdp_chanman_send_event(chan_man, out_event); + payload = rail_clone_order(event_type, data); + if (payload != NULL) + { + out_event = freerdp_event_new(RDP_EVENT_CLASS_RAIL, event_type, + test_on_free_rail_client_event, payload); + freerdp_chanman_send_event(chan_man, out_event); + } } //----------------------------------------------------------------------------- static void emulate_server_send_channel_data( @@ -530,9 +542,9 @@ static int emulate_client_send_channel_data( printf("Client send to server (%d packet):\n", counter); freerdp_hexdump(data, size); + // add to global dumps list save_dump(data, size); - // add to global dumps list return 0; } //----------------------------------------------------------------------------- @@ -547,9 +559,19 @@ void save_event(RDP_EVENT* event, RAIL_EVENT* rail_event) break; case RDP_EVENT_TYPE_RAIL_CHANNEL_EXEC_RESULTS: - printf("UI receive Exec Results Event\n"); - memcpy(&rail_event->order_info.exec_result, event->user_data, - sizeof(RAIL_EXEC_ORDER)); + { + RAIL_EXEC_RESULT_ORDER* exec_result = (RAIL_EXEC_RESULT_ORDER*)event->user_data; + printf("UI receive Exec Results Event\n"); + memcpy(&rail_event->order_info.exec_result, event->user_data, + sizeof(RAIL_EXEC_RESULT_ORDER)); + + rail_unicode_string_alloc(&rail_event->order_info.exec_result.exeOrFile, + exec_result->exeOrFile.length); + + memcpy(rail_event->order_info.exec_result.exeOrFile.string, + exec_result->exeOrFile.string, + exec_result->exeOrFile.length); + } break; case RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_SYSPARAM: @@ -574,6 +596,9 @@ void save_event(RDP_EVENT* event, RAIL_EVENT* rail_event) printf("UI receive AppId Response Event\n"); memcpy(&rail_event->order_info.get_appid_resp, event->user_data, sizeof(RAIL_GET_APPID_RESP_ORDER)); + + rail_event->order_info.get_appid_resp.applicationId.string = + &rail_event->order_info.get_appid_resp.applicationIdBuffer[0]; break; case RDP_EVENT_TYPE_RAIL_CHANNEL_LANGBARINFO: @@ -605,13 +630,12 @@ static void process_events_and_channel_data_from_plugin(thread_param* param) event->event_type, counter); + // add to global event list if (param->in_events_number < RAIL_ARRAY_SIZE(param->in_events)) { save_event(event, ¶m->in_events[param->in_events_number]); param->in_events_number++; } - - // add to global event list freerdp_event_free(event); } diff --git a/include/freerdp/utils/rail.h b/include/freerdp/utils/rail.h index dc9f2f655..5a0bebf79 100644 --- a/include/freerdp/utils/rail.h +++ b/include/freerdp/utils/rail.h @@ -24,6 +24,8 @@ #include #include +#define RAIL_ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0])) + FREERDP_API void rail_unicode_string_alloc(UNICODE_STRING* unicode_string, uint16 cbString); FREERDP_API void rail_unicode_string_free(UNICODE_STRING* unicode_string); FREERDP_API void rail_read_unicode_string(STREAM* s, UNICODE_STRING* unicode_string); @@ -31,5 +33,7 @@ FREERDP_API void rail_write_unicode_string(STREAM* s, UNICODE_STRING* unicode_st FREERDP_API void rail_write_unicode_string_value(STREAM* s, UNICODE_STRING* unicode_string); FREERDP_API void rail_read_rectangle_16(STREAM* s, RECTANGLE_16* rectangle_16); FREERDP_API void rail_write_rectangle_16(STREAM* s, RECTANGLE_16* rectangle_16); +FREERDP_API void* rail_clone_order(uint32 event_type, void* order); +FREERDP_API void rail_free_cloned_order(uint32 event_type, void* order); #endif /* __RAIL_UTILS_H */ diff --git a/libfreerdp-utils/rail.c b/libfreerdp-utils/rail.c index c58be0bfc..a89329cd3 100644 --- a/libfreerdp-utils/rail.c +++ b/libfreerdp-utils/rail.c @@ -21,6 +21,7 @@ #include #include +#include void rail_unicode_string_alloc(UNICODE_STRING* unicode_string, uint16 cbString) { @@ -80,3 +81,104 @@ void rail_write_rectangle_16(STREAM* s, RECTANGLE_16* rectangle_16) stream_write_uint16(s, rectangle_16->bottom); /* bottom (2 bytes) */ } +void* rail_clone_order(uint32 event_type, void* order) +{ + struct + { + uint32 type; + uint32 size; + } ordersize_table[] = + { + {RDP_EVENT_TYPE_RAIL_CHANNEL_GET_SYSPARAMS, sizeof(RAIL_SYSPARAM_ORDER)}, + {RDP_EVENT_TYPE_RAIL_CHANNEL_EXEC_RESULTS, sizeof(RAIL_EXEC_RESULT_ORDER)}, + {RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_SYSPARAM, sizeof(RAIL_SYSPARAM_ORDER)}, + {RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_MINMAXINFO, sizeof(RAIL_MINMAXINFO_ORDER)}, + {RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_LOCALMOVESIZE, sizeof(RAIL_LOCALMOVESIZE_ORDER)}, + {RDP_EVENT_TYPE_RAIL_CHANNEL_APPID_RESP, sizeof(RAIL_GET_APPID_RESP_ORDER)}, + {RDP_EVENT_TYPE_RAIL_CHANNEL_LANGBARINFO, sizeof(RAIL_LANGBAR_INFO_ORDER)}, + {RDP_EVENT_TYPE_RAIL_CLIENT_SET_SYSPARAMS, sizeof(RAIL_SYSPARAM_ORDER)}, + {RDP_EVENT_TYPE_RAIL_CLIENT_EXEC_REMOTE_APP, sizeof(RDP_PLUGIN_DATA)}, + {RDP_EVENT_TYPE_RAIL_CLIENT_ACTIVATE, sizeof(RAIL_ACTIVATE_ORDER)}, + {RDP_EVENT_TYPE_RAIL_CLIENT_SYSMENU, sizeof(RAIL_SYSMENU_ORDER)}, + {RDP_EVENT_TYPE_RAIL_CLIENT_SYSCOMMAND, sizeof(RAIL_SYSCOMMAND_ORDER)}, + {RDP_EVENT_TYPE_RAIL_CLIENT_NOTIFY_EVENT, sizeof(RAIL_NOTIFY_EVENT_ORDER)}, + {RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, sizeof(RAIL_WINDOW_MOVE_ORDER)}, + {RDP_EVENT_TYPE_RAIL_CLIENT_APPID_REQ, sizeof(RAIL_GET_APPID_REQ_ORDER)}, + {RDP_EVENT_TYPE_RAIL_CLIENT_LANGBARINFO, sizeof(RAIL_LANGBAR_INFO_ORDER)}, + }; + size_t i = 0; + size_t order_size = 0; + void* new_order = NULL; + + for (i = 0; i < RAIL_ARRAY_SIZE(ordersize_table); i++) + { + if (event_type == ordersize_table[i].type) + { + order_size = ordersize_table[i].size; + break; + } + } + + // Event type not found. + if (order_size == 0) return NULL; + + new_order = xmalloc(order_size); + memcpy(new_order, order, order_size); + + //printf("rail_clone_order: type=%d order=%p\n", event_type, new_order); + + // Create copy of variable data for some orders + if ((event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_GET_SYSPARAMS) || + (event_type == RDP_EVENT_TYPE_RAIL_CLIENT_SET_SYSPARAMS)) + { + RAIL_SYSPARAM_ORDER* new_sysparam = (RAIL_SYSPARAM_ORDER*)new_order; + RAIL_SYSPARAM_ORDER* old_sysparam = (RAIL_SYSPARAM_ORDER*)order; + + rail_unicode_string_alloc(&new_sysparam->highContrast.colorScheme, + old_sysparam->highContrast.colorScheme.length); + + memcpy(new_sysparam->highContrast.colorScheme.string, + old_sysparam->highContrast.colorScheme.string, + old_sysparam->highContrast.colorScheme.length); + } + + if (event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_EXEC_RESULTS) + { + RAIL_EXEC_RESULT_ORDER* new_exec_result = (RAIL_EXEC_RESULT_ORDER*)new_order; + RAIL_EXEC_RESULT_ORDER* old_exec_result = (RAIL_EXEC_RESULT_ORDER*)order; + + rail_unicode_string_alloc(&new_exec_result->exeOrFile, + old_exec_result->exeOrFile.length); + + memcpy(new_exec_result->exeOrFile.string, + old_exec_result->exeOrFile.string, + old_exec_result->exeOrFile.length); + } + + if (event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_APPID_RESP) + { + RAIL_GET_APPID_RESP_ORDER* new_app_resp = (RAIL_GET_APPID_RESP_ORDER*)new_order; + + new_app_resp->applicationId.string = &new_app_resp->applicationIdBuffer[0]; + } + + return new_order; +} + +void rail_free_cloned_order(uint32 event_type, void* order) +{ + //printf("rail_free_cloned_order: type=%d order=%p\n", event_type, order); + if ((event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_GET_SYSPARAMS) || + (event_type == RDP_EVENT_TYPE_RAIL_CLIENT_SET_SYSPARAMS)) + { + RAIL_SYSPARAM_ORDER* sysparam = (RAIL_SYSPARAM_ORDER*)order; + rail_unicode_string_free(&sysparam->highContrast.colorScheme); + } + + if (event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_EXEC_RESULTS) + { + RAIL_EXEC_RESULT_ORDER* exec_result = (RAIL_EXEC_RESULT_ORDER*)order; + rail_unicode_string_free(&exec_result->exeOrFile); + } + xfree(order); +}