channels/rail: fixed multithread side effect by creating full orders copy for events.

This commit is contained in:
roman-b 2011-08-22 02:04:21 +03:00
parent e701bf1bcf
commit 7744e17ec2
5 changed files with 179 additions and 19 deletions

View File

@ -26,6 +26,7 @@
#include <freerdp/types.h>
#include <freerdp/utils/memory.h>
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/utils/rail.h>
#include <freerdp/rail.h>
#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)

View File

@ -19,6 +19,7 @@
#include <freerdp/utils/event.h>
#include <freerdp/utils/hexdump.h>
#include <freerdp/utils/rail.h>
#include <freerdp/rail/rail.h>
@ -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[] =

View File

@ -30,6 +30,7 @@
#include <freerdp/utils/event.h>
#include <freerdp/utils/hexdump.h>
#include <freerdp/utils/memory.h>
#include <freerdp/utils/rail.h>
#include <freerdp/rail.h>
@ -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, &param->in_events[param->in_events_number]);
param->in_events_number++;
}
// add to global event list
freerdp_event_free(event);
}

View File

@ -24,6 +24,8 @@
#include <freerdp/rail.h>
#include <freerdp/utils/stream.h>
#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 */

View File

@ -21,6 +21,7 @@
#include <freerdp/utils/memory.h>
#include <freerdp/utils/rail.h>
#include <freerdp/rail.h>
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);
}