Merge branch 'master' of github.com:FreeRDP/xrdp

ulab-next
Jay Sorg 12 years ago
commit 3399b953eb

@ -5,6 +5,18 @@
# chkconfig: 2345 11 89 # chkconfig: 2345 11 89
# description: starts xrdp # description: starts xrdp
### BEGIN INIT INFO
# Provides: xrdp
# Required-Start:
# Required-Stop:
# Should-Start:
# Should-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start and stop xrdp
# Description: starts xrdp
### END INIT INFO
SBINDIR=/usr/local/sbin SBINDIR=/usr/local/sbin
LOG=/dev/null LOG=/dev/null
CFGDIR=/etc/xrdp CFGDIR=/etc/xrdp

@ -30,7 +30,8 @@ xrdp_chansrv_SOURCES = \
clipboard.c \ clipboard.c \
devredir.c \ devredir.c \
rail.c \ rail.c \
xcommon.c xcommon.c \
drdynvc.c
xrdp_chansrv_LDFLAGS = \ xrdp_chansrv_LDFLAGS = \
$(EXTRA_FLAGS) $(EXTRA_FLAGS)

@ -69,59 +69,132 @@ struct xrdp_api_data
}; };
/*****************************************************************************/ /*****************************************************************************/
/* add data to chan_item, on its way to the client */
/* returns error */ /* returns error */
int APP_CC static int APP_CC
send_channel_data(int chan_id, char* data, int size) add_data_to_chan_item(struct chan_item* chan_item, char* data, int size)
{
struct stream* s;
struct chan_out_data* cod;
make_stream(s);
init_stream(s, size);
g_memcpy(s->data, data, size);
s->end = s->data + size;
cod = (struct chan_out_data*)g_malloc(sizeof(struct chan_out_data), 1);
cod->s = s;
if (chan_item->tail == 0)
{
chan_item->tail = cod;
chan_item->head = cod;
}
else
{
chan_item->tail->next = cod;
chan_item->tail = cod;
}
return 0;
}
/*****************************************************************************/
/* returns error */
static int APP_CC
send_data_from_chan_item(struct chan_item* chan_item)
{ {
struct stream * s; struct stream* s;
struct chan_out_data* cod;
int bytes_left;
int size;
int chan_flags; int chan_flags;
int total_size; int error;
int sent;
int rv;
if (chan_id == -1) if (chan_item->head == 0)
{ {
return 1; return 0;
}
cod = chan_item->head;
bytes_left = (int)(cod->s->end - cod->s->p);
size = MIN(1600, bytes_left);
chan_flags = 0;
if (cod->s->p == cod->s->data)
{
chan_flags |= 1; /* first */
}
if (cod->s->p + size >= cod->s->end)
{
chan_flags |= 2; /* last */
} }
s = trans_get_out_s(g_con_trans, 8192); s = trans_get_out_s(g_con_trans, 8192);
if (s == 0) out_uint32_le(s, 0); /* version */
out_uint32_le(s, 8 + 8 + 2 + 2 + 2 + 4 + size); /* size */
out_uint32_le(s, 8); /* msg id */
out_uint32_le(s, 8 + 2 + 2 + 2 + 4 + size); /* size */
out_uint16_le(s, chan_item->id);
out_uint16_le(s, chan_flags);
out_uint16_le(s, size);
out_uint32_le(s, cod->s->size);
out_uint8a(s, cod->s->p, size);
s_mark_end(s);
LOGM((LOG_LEVEL_DEBUG, "chansrv::send_channel_data: -- "
"size %d chan_flags 0x%8.8x", size, chan_flags));
error = trans_force_write(g_con_trans);
if (error != 0)
{ {
return 1; return 1;
} }
rv = 0; cod->s->p += size;
sent = 0; if (cod->s->p >= cod->s->end)
total_size = size;
while (sent < total_size)
{ {
size = MIN(1600, total_size - sent); free_stream(cod->s);
chan_flags = 0; chan_item->head = chan_item->head->next;
if (sent == 0) if (chan_item->head == 0)
{ {
chan_flags |= 1; /* first */ chan_item->tail = 0;
} }
if (size + sent == total_size) g_free(cod);
}
return 0;
}
/*****************************************************************************/
/* returns error */
static int APP_CC
check_chan_items(void)
{
int index;
for (index = 0; index < g_num_chan_items; index++)
{
if (g_chan_items[index].head != 0)
{ {
chan_flags |= 2; /* last */ send_data_from_chan_item(g_chan_items + index);
} }
out_uint32_le(s, 0); /* version */ }
out_uint32_le(s, 8 + 8 + 2 + 2 + 2 + 4 + size); /* size */ return 0;
out_uint32_le(s, 8); /* msg id */ }
out_uint32_le(s, 8 + 2 + 2 + 2 + 4 + size); /* size */
out_uint16_le(s, chan_id); /*****************************************************************************/
out_uint16_le(s, chan_flags); /* returns error */
out_uint16_le(s, size); int APP_CC
out_uint32_le(s, total_size); send_channel_data(int chan_id, char* data, int size)
out_uint8a(s, data + sent, size); {
s_mark_end(s); int index;
rv = trans_force_write(g_con_trans);
if (rv != 0) LOGM((LOG_LEVEL_DEBUG, "chansrv::send_channel_data: size %d", size));
if (chan_id == -1)
{
return 1;
}
for (index = 0; index < g_num_chan_items; index++)
{
if (g_chan_items[index].id == chan_id)
{ {
break; add_data_to_chan_item(g_chan_items + index, data, size);
check_chan_items();
return 0;
} }
sent += size;
s = trans_get_out_s(g_con_trans, 8192);
} }
return rv; return 1;
} }
/*****************************************************************************/ /*****************************************************************************/
@ -131,7 +204,7 @@ send_init_response_message(void)
{ {
struct stream * s = (struct stream *)NULL; struct stream * s = (struct stream *)NULL;
LOGM((LOG_LEVEL_INFO,"send_init_response_message:")) LOGM((LOG_LEVEL_INFO, "send_init_response_message:"));
s = trans_get_out_s(g_con_trans, 8192); s = trans_get_out_s(g_con_trans, 8192);
if (s == 0) if (s == 0)
{ {
@ -339,6 +412,7 @@ static int APP_CC
process_message_channel_data_response(struct stream* s) process_message_channel_data_response(struct stream* s)
{ {
LOG(10, ("process_message_channel_data_response:")); LOG(10, ("process_message_channel_data_response:"));
check_chan_items();
return 0; return 0;
} }
@ -911,21 +985,41 @@ main(int argc, char** argv)
{ {
tbus waiters[4]; tbus waiters[4];
int pid = 0; int pid = 0;
char text[256] = ""; char text[256];
char* display_text = (char *)NULL; char* home_text;
#if XRDP_CHANNEL_LOG char* display_text;
char cfg_file[256]; char log_file[256];
enum logReturns error; enum logReturns error;
#endif struct log_config logconfig;
g_init("xrdp-chansrv"); /* os_calls */ g_init("xrdp-chansrv"); /* os_calls */
home_text = g_getenv("HOME");
if (home_text == 0)
{
g_writeln("error reading HOME environment variable");
g_deinit();
return 1;
}
read_ini(); read_ini();
pid = g_getpid(); pid = g_getpid();
#if XRDP_CHANNEL_LOG
/* starting logging subsystem */ /* starting logging subsystem */
g_snprintf(cfg_file, 255, "%s/sesman.ini", XRDP_CFG_PATH); g_memset(&logconfig, 0, sizeof(struct log_config));
error = log_start(cfg_file,"XRDP-Chansrv"); logconfig.program_name = "XRDP-Chansrv";
g_snprintf(log_file, 255, "%s/xrdp-chansrv.log", home_text);
g_writeln("chansrv::main: using log file [%s]", log_file);
if (g_file_exist(log_file))
{
g_file_delete(log_file);
}
logconfig.log_file = log_file;
logconfig.fd = -1;
logconfig.log_level = LOG_LEVEL_ERROR;
logconfig.enable_syslog = 0;
logconfig.syslog_level = 0;
error = log_start_from_param(&logconfig);
if (error != LOG_STARTUP_OK) if (error != LOG_STARTUP_OK)
{ {
switch (error) switch (error)
@ -942,10 +1036,9 @@ main(int argc, char** argv)
break; break;
} }
g_deinit(); g_deinit();
g_exit(1); return 1;
} }
LOGM((LOG_LEVEL_ALWAYS, "main: app started pid %d(0x%8.8x)", pid, pid)); LOGM((LOG_LEVEL_ALWAYS, "main: app started pid %d(0x%8.8x)", pid, pid));
#endif
/* set up signal handler */ /* set up signal handler */
g_signal_kill(term_signal_handler); /* SIGKILL */ g_signal_kill(term_signal_handler); /* SIGKILL */
g_signal_terminate(term_signal_handler); /* SIGTERM */ g_signal_terminate(term_signal_handler); /* SIGTERM */
@ -958,6 +1051,7 @@ main(int argc, char** argv)
if (g_display_num == 0) if (g_display_num == 0)
{ {
LOGM((LOG_LEVEL_ERROR, "main: error, display is zero")); LOGM((LOG_LEVEL_ERROR, "main: error, display is zero"));
g_deinit();
return 1; return 1;
} }
LOGM((LOG_LEVEL_INFO, "main: using DISPLAY %d", g_display_num)); LOGM((LOG_LEVEL_INFO, "main: using DISPLAY %d", g_display_num));

@ -21,14 +21,21 @@
#include "arch.h" #include "arch.h"
#include "parse.h" #include "parse.h"
#include "log.h"
#define XRDP_CHANNEL_LOG 0 struct chan_out_data
{
struct stream* s;
struct chan_out_data* next;
};
struct chan_item struct chan_item
{ {
int id; int id;
int flags; int flags;
char name[16]; char name[16];
struct chan_out_data* head;
struct chan_out_data* tail;
}; };
int APP_CC int APP_CC
@ -47,12 +54,7 @@ main_cleanup(void);
} \ } \
} }
#if XRDP_CHANNEL_LOG
#include "log.h"
#define LOGM(_args) do { log_message _args ; } while (0) #define LOGM(_args) do { log_message _args ; } while (0)
#else
#define LOGM(_args)
#endif
#ifndef GSET_UINT8 #ifndef GSET_UINT8
#define GSET_UINT8(_ptr, _offset, _data) \ #define GSET_UINT8(_ptr, _offset, _data) \

@ -95,14 +95,14 @@ static int g_want_image_data = 0;
static XSelectionRequestEvent g_saved_selection_req_event; static XSelectionRequestEvent g_saved_selection_req_event;
/* for clipboard INCR transfers */ /* for clipboard INCR transfers */
static Atom g_incr_atom; static Atom g_incr_atom;
static Atom g_incr_atom_type; static Atom g_incr_atom_type;
static Atom g_incr_atom_target; static Atom g_incr_atom_target;
static char* g_incr_data; static char* g_incr_data = 0;
static int g_incr_data_size; static int g_incr_data_size = 0;
static int g_incr_in_progress = 0; static int g_incr_in_progress = 0;
static clipboard_format_id = CB_FORMAT_UNICODETEXT; static int clipboard_format_id = CB_FORMAT_UNICODETEXT;
/*****************************************************************************/ /*****************************************************************************/
/* this is one way to get the current time from the x server */ /* this is one way to get the current time from the x server */
@ -176,10 +176,10 @@ clipboard_init(void)
} }
if (rv == 0) if (rv == 0)
{ {
LOGM((LOG_LEVEL_ERROR, "clipboard_init: g_xfixes_event_base %d", LOGM((LOG_LEVEL_DEBUG, "clipboard_init: g_xfixes_event_base %d",
g_xfixes_event_base)); g_xfixes_event_base));
st = XFixesQueryVersion(g_display, &ver_maj, &ver_min); st = XFixesQueryVersion(g_display, &ver_maj, &ver_min);
LOGM((LOG_LEVEL_ERROR, "clipboard_init st %d, maj %d min %d", st, LOGM((LOG_LEVEL_DEBUG, "clipboard_init st %d, maj %d min %d", st,
ver_maj, ver_min)); ver_maj, ver_min));
g_clip_property_atom = XInternAtom(g_display, "XRDP_CLIP_PROPERTY_ATOM", g_clip_property_atom = XInternAtom(g_display, "XRDP_CLIP_PROPERTY_ATOM",
False); False);
@ -194,6 +194,11 @@ clipboard_init(void)
g_image_bmp_atom = XInternAtom(g_display, "image/bmp", False); g_image_bmp_atom = XInternAtom(g_display, "image/bmp", False);
g_incr_atom = XInternAtom(g_display, "INCR", False); g_incr_atom = XInternAtom(g_display, "INCR", False);
if (g_image_bmp_atom == None)
{
LOGM((LOG_LEVEL_ERROR, "clipboard_init: g_image_bmp_atom was "
"not allocated"));
}
g_wnd = XCreateSimpleWindow(g_display, RootWindowOfScreen(g_screen), g_wnd = XCreateSimpleWindow(g_display, RootWindowOfScreen(g_screen),
0, 0, 4, 4, 0, 0, 0); 0, 0, 4, 4, 0, 0, 0);
@ -327,10 +332,7 @@ clipboard_send_format_announce(tui32 format_id, char* format_name)
struct stream* s; struct stream* s;
int size; int size;
int rv; int rv;
unsigned char format_buf[32];
g_memset(format_buf, 0, 32);
g_snprintf(format_buf, 31, "Native");
make_stream(s); make_stream(s);
init_stream(s, 8192); init_stream(s, 8192);
out_uint16_le(s, 2); /* CLIPRDR_FORMAT_ANNOUNCE */ out_uint16_le(s, 2); /* CLIPRDR_FORMAT_ANNOUNCE */
@ -521,6 +523,9 @@ clipboard_refuse_selection(XSelectionRequestEvent* req)
} }
/*****************************************************************************/ /*****************************************************************************/
/* sent by client or server when its local system clipboard is
updated with new clipboard data; contains Clipboard Format ID
and name pairs of new Clipboard Formats on the clipboard. */
static int APP_CC static int APP_CC
clipboard_process_format_announce(struct stream* s, int clip_msg_status, clipboard_process_format_announce(struct stream* s, int clip_msg_status,
int clip_msg_len) int clip_msg_len)
@ -540,6 +545,8 @@ clipboard_process_format_announce(struct stream* s, int clip_msg_status,
} }
/*****************************************************************************/ /*****************************************************************************/
/* response to CB_FORMAT_LIST; used to indicate whether
processing of the Format List PDU was successful */
static int APP_CC static int APP_CC
clipboard_prcoess_format_ack(struct stream* s, int clip_msg_status, clipboard_prcoess_format_ack(struct stream* s, int clip_msg_status,
int clip_msg_len) int clip_msg_len)
@ -550,6 +557,8 @@ clipboard_prcoess_format_ack(struct stream* s, int clip_msg_status,
} }
/*****************************************************************************/ /*****************************************************************************/
/* sent by recipient of CB_FORMAT_LIST; used to request data for one
of the formats that was listed in CB_FORMAT_LIST */
static int APP_CC static int APP_CC
clipboard_process_data_request(struct stream* s, int clip_msg_status, clipboard_process_data_request(struct stream* s, int clip_msg_status,
int clip_msg_len) int clip_msg_len)
@ -576,7 +585,6 @@ clipboard_process_data_response_for_image(struct stream * s,
char cdata; char cdata;
int len; int len;
int index; int index;
int data_in_len;
LOGM((LOG_LEVEL_DEBUG, "clipboard_process_data_response_for_image: " LOGM((LOG_LEVEL_DEBUG, "clipboard_process_data_response_for_image: "
"CLIPRDR_DATA_RESPONSE_FOR_IMAGE")); "CLIPRDR_DATA_RESPONSE_FOR_IMAGE"));
@ -600,7 +608,7 @@ clipboard_process_data_response_for_image(struct stream * s,
} }
else else
{ {
return; return 0;
} }
while (s_check(s)) while (s_check(s))
{ {
@ -783,7 +791,8 @@ clipboard_data_in(struct stream* s, int chan_id, int chan_flags, int length,
/*****************************************************************************/ /*****************************************************************************/
/* this happens when a new app copies something to the clipboard /* this happens when a new app copies something to the clipboard
'CLIPBOARD' Atom 'CLIPBOARD' Atom
typedef struct { typedef struct
{
int type; int type;
unsigned long serial; unsigned long serial;
Bool send_event; Bool send_event;
@ -794,7 +803,7 @@ clipboard_data_in(struct stream* s, int chan_id, int chan_flags, int length,
Atom selection; Atom selection;
Time timestamp; Time timestamp;
Time selection_timestamp; Time selection_timestamp;
} XFixesSelectionNotifyEvent; */ } XFixesSelectionNotifyEvent; */
static int APP_CC static int APP_CC
clipboard_event_selection_owner_notify(XEvent* xevent) clipboard_event_selection_owner_notify(XEvent* xevent)
{ {
@ -836,7 +845,10 @@ clipboard_get_window_property(Window wnd, Atom prop, Atom* type, int* fmt,
XGetWindowProperty(g_display, g_wnd, prop, 0, 0, 0, XGetWindowProperty(g_display, g_wnd, prop, 0, 0, 0,
AnyPropertyType, &ltype, &lfmt, &ln_items, AnyPropertyType, &ltype, &lfmt, &ln_items,
&llen_after, &lxdata); &llen_after, &lxdata);
XFree(lxdata); if (lxdata != 0)
{
XFree(lxdata);
}
if (ltype == 0) if (ltype == 0)
{ {
/* XGetWindowProperty failed */ /* XGetWindowProperty failed */
@ -845,13 +857,14 @@ clipboard_get_window_property(Window wnd, Atom prop, Atom* type, int* fmt,
if (ltype == g_incr_atom) if (ltype == g_incr_atom)
{ {
LOGM((LOG_LEVEL_DEBUG, "clipboard_event_property_notify: INCR start"));
g_incr_in_progress = 1; g_incr_in_progress = 1;
g_incr_atom_type = prop; g_incr_atom_type = prop;
g_incr_data_size = 0; g_incr_data_size = 0;
g_free(g_incr_data); g_free(g_incr_data);
g_incr_data = 0; g_incr_data = 0;
XDeleteProperty(g_display, g_wnd, prop); XDeleteProperty(g_display, g_wnd, prop);
return; return 0;
} }
if (llen_after < 1) if (llen_after < 1)
@ -867,20 +880,29 @@ clipboard_get_window_property(Window wnd, Atom prop, Atom* type, int* fmt,
if (ltype == 0) if (ltype == 0)
{ {
/* XGetWindowProperty failed */ /* XGetWindowProperty failed */
XFree(lxdata); if (lxdata != 0)
{
XFree(lxdata);
}
return 1; return 1;
} }
lxdata_size = (lfmt / 8) * ln_items; lxdata_size = (lfmt / 8) * ln_items;
if (lxdata_size < 1) if (lxdata_size < 1)
{ {
/* should not happen */ /* should not happen */
XFree(lxdata); if (lxdata != 0)
{
XFree(lxdata);
}
return 2; return 2;
} }
if (llen_after > 0) if (llen_after > 0)
{ {
/* should not happen */ /* should not happen */
XFree(lxdata); if (lxdata != 0)
{
XFree(lxdata);
}
return 3; return 3;
} }
if (xdata != 0) if (xdata != 0)
@ -888,7 +910,10 @@ clipboard_get_window_property(Window wnd, Atom prop, Atom* type, int* fmt,
*xdata = (char*)g_malloc(lxdata_size, 0); *xdata = (char*)g_malloc(lxdata_size, 0);
g_memcpy(*xdata, lxdata, lxdata_size); g_memcpy(*xdata, lxdata, lxdata_size);
} }
XFree(lxdata); if (lxdata != 0)
{
XFree(lxdata);
}
if (xdata_size != 0) if (xdata_size != 0)
{ {
*xdata_size = lxdata_size; *xdata_size = lxdata_size;
@ -937,10 +962,10 @@ clipboard_event_selection_notify(XEvent* xevent)
int convert_to_bmp_image; int convert_to_bmp_image;
int send_format_announce; int send_format_announce;
int atom; int atom;
int* atoms; Atom* atoms;
Atom type; Atom type;
tui32 format_id; tui32 format_id;
unsigned char format_name[32]; char format_name[32];
LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_notify:")); LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_notify:"));
data_size = 0; data_size = 0;
@ -948,7 +973,9 @@ clipboard_event_selection_notify(XEvent* xevent)
fmt = 0; fmt = 0;
convert_to_string = 0; convert_to_string = 0;
convert_to_utf8 = 0; convert_to_utf8 = 0;
convert_to_bmp_image = 0;
send_format_announce = 0; send_format_announce = 0;
format_id = 0;
rv = 0; rv = 0;
data = 0; data = 0;
type = 0; type = 0;
@ -985,9 +1012,10 @@ clipboard_event_selection_notify(XEvent* xevent)
{ {
if (lxevent->target == g_targets_atom) if (lxevent->target == g_targets_atom)
{ {
/* on a 64 bit machine, actual_format_return of 32 implies long */
if ((type == XA_ATOM) && (fmt == 32)) if ((type == XA_ATOM) && (fmt == 32))
{ {
atoms = (int*)data; atoms = (Atom*)data;
for (index = 0; index < n_items; index++) for (index = 0; index < n_items; index++)
{ {
atom = atoms[index]; atom = atoms[index];
@ -1026,6 +1054,7 @@ clipboard_event_selection_notify(XEvent* xevent)
g_memcpy(g_last_clip_data, data, g_last_clip_size); g_memcpy(g_last_clip_data, data, g_last_clip_size);
g_last_clip_data[g_last_clip_size] = 0; g_last_clip_data[g_last_clip_size] = 0;
send_format_announce = 1; send_format_announce = 1;
format_id = CB_FORMAT_UNICODETEXT;
} }
else if (lxevent->target == XA_STRING) else if (lxevent->target == XA_STRING)
{ {
@ -1124,7 +1153,6 @@ clipboard_event_selection_request(XEvent* xevent)
int n_items; int n_items;
int xdata_size; int xdata_size;
char* xdata; char* xdata;
int i;
lxev = (XSelectionRequestEvent*)xevent; lxev = (XSelectionRequestEvent*)xevent;
LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: g_wnd %d, " LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: g_wnd %d, "
@ -1163,7 +1191,6 @@ clipboard_event_selection_request(XEvent* xevent)
/* target, property pairs */ /* target, property pairs */
LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: " LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: "
"g_multiple_atom")); "g_multiple_atom"));
#if 0
if (clipboard_get_window_property(xev.xselection.requestor, if (clipboard_get_window_property(xev.xselection.requestor,
xev.xselection.property, xev.xselection.property,
&type, &fmt, &n_items, &xdata, &type, &fmt, &n_items, &xdata,
@ -1174,7 +1201,6 @@ clipboard_event_selection_request(XEvent* xevent)
/* todo */ /* todo */
g_free(xdata); g_free(xdata);
} }
#endif
} }
else if ((lxev->target == XA_STRING) || (lxev->target == g_utf8_atom)) else if ((lxev->target == XA_STRING) || (lxev->target == g_utf8_atom))
{ {
@ -1205,6 +1231,18 @@ clipboard_event_selection_request(XEvent* xevent)
return 0; return 0;
} }
} }
else if (lxev->target == g_image_bmp_atom)
{
g_memcpy(&g_saved_selection_req_event, lxev,
sizeof(g_saved_selection_req_event));
g_last_clip_type = g_image_bmp_atom;
g_want_image_data = 1;
clipboard_format_id = CB_FORMAT_DIB;
clipboard_send_data_request();
g_waiting_for_data_response = 1;
g_waiting_for_data_response_time = clipboard_get_local_time();
return 0;
}
else else
{ {
LOGM((LOG_LEVEL_ERROR,"clipboard_event_selection_request: unknown " LOGM((LOG_LEVEL_ERROR,"clipboard_event_selection_request: unknown "
@ -1257,7 +1295,7 @@ clipboard_event_property_notify(XEvent* xevent)
int format_in_bytes; int format_in_bytes;
int new_data_len; int new_data_len;
char* cptr; char* cptr;
unsigned char format_name[32]; char format_name[32];
LOG(10, ("clipboard_check_wait_objs: PropertyNotify .window %d " LOG(10, ("clipboard_check_wait_objs: PropertyNotify .window %d "
".state %d .atom %d", xevent->xproperty.window, ".state %d .atom %d", xevent->xproperty.window,
@ -1276,11 +1314,13 @@ clipboard_event_property_notify(XEvent* xevent)
} }
if (bytes_left <= 0) if (bytes_left <= 0)
{ {
LOGM((LOG_LEVEL_DEBUG, "clipboard_event_property_notify: INCR done"));
g_memset(format_name, 0, 32); g_memset(format_name, 0, 32);
/* clipboard INCR cycle has completed */ /* clipboard INCR cycle has completed */
g_incr_in_progress = 0; g_incr_in_progress = 0;
g_last_clip_size = g_incr_data_size; g_last_clip_size = g_incr_data_size;
g_last_clip_data = g_incr_data; g_last_clip_data = g_incr_data;
g_incr_data = 0;
g_last_clip_type = g_incr_atom_target; g_last_clip_type = g_incr_atom_target;
if (g_incr_atom_target == g_image_bmp_atom) if (g_incr_atom_target == g_image_bmp_atom)
{ {
@ -1296,25 +1336,22 @@ clipboard_event_property_notify(XEvent* xevent)
&nitems_returned, &bytes_left, (unsigned char **) &data); &nitems_returned, &bytes_left, (unsigned char **) &data);
format_in_bytes = actual_format_return / 8; format_in_bytes = actual_format_return / 8;
if (actual_format_return == 32 && sizeof(long) == 8) if ((actual_format_return == 32) && (sizeof(long) == 8))
{ {
/* on a 64 bit machine, actual_format_return of 32 implies long */ /* on a 64 bit machine, actual_format_return of 32 implies long */
format_in_bytes = 8; format_in_bytes = 8;
} }
new_data_len = nitems_returned * format_in_bytes; new_data_len = nitems_returned * format_in_bytes;
#if 1 cptr = (char*)g_malloc(g_incr_data_size + new_data_len, 0);
g_memcpy(cptr, g_incr_data, g_incr_data_size);
g_free(g_incr_data); g_free(g_incr_data);
cptr = (char *) g_malloc(g_incr_data_size + new_data_len, 0);
#else
cptr = (char *) realloc(g_incr_data, g_incr_data_size + new_data_len);
#endif
if (cptr == NULL) if (cptr == NULL)
{ {
g_incr_data = 0;
/* cannot add any more data */ /* cannot add any more data */
if (data != 0) if (data != 0)
{ {
XFree(data); XFree(data);
data = 0;
} }
XDeleteProperty(g_display, g_wnd, g_incr_atom_type); XDeleteProperty(g_display, g_wnd, g_incr_atom_type);
return 0; return 0;
@ -1325,7 +1362,6 @@ clipboard_event_property_notify(XEvent* xevent)
if (data) if (data)
{ {
XFree(data); XFree(data);
data = 0;
} }
XDeleteProperty(g_display, g_wnd, g_incr_atom_type); XDeleteProperty(g_display, g_wnd, g_incr_atom_type);
} }

@ -0,0 +1,17 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2012
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

@ -0,0 +1,25 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2012
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if !defined(DRDYNVC_H)
#define DRDYNVC_H
#include "arch.h"
#include "parse.h"
#endif

@ -164,7 +164,7 @@ xcommon_check_wait_objs(void)
{ {
time_diff = xcommon_get_local_time() - time_diff = xcommon_get_local_time() -
g_waiting_for_data_response_time; g_waiting_for_data_response_time;
if (time_diff > 1000) if (time_diff > 10000)
{ {
LOGM((LOG_LEVEL_ERROR, "xcommon_check_wait_objs: warning, " LOGM((LOG_LEVEL_ERROR, "xcommon_check_wait_objs: warning, "
"waiting for data response too long")); "waiting for data response too long"));

@ -791,6 +791,25 @@ check_keysa(void)
/******************************************************************************/ /******************************************************************************/
void void
sendDownUpKeyEvent(int type, int x_scancode)
{
/* if type is keydown, send keydown + keyup */
/* this allows us to ignore keyup events */
if (type == KeyPress)
{
rdpEnqueueKey(KeyPress, x_scancode);
rdpEnqueueKey(KeyRelease, x_scancode);
}
}
/**
* @param down - true for KeyDown events, false otherwise
* @param param1 - ASCII code of pressed key
* @param param2 -
* @param param3 - scancode of pressed key
* @param param4 -
******************************************************************************/
void
KbdAddEvent(int down, int param1, int param2, int param3, int param4) KbdAddEvent(int down, int param1, int param2, int param3, int param4)
{ {
int rdp_scancode; int rdp_scancode;
@ -799,63 +818,75 @@ KbdAddEvent(int down, int param1, int param2, int param3, int param4)
int is_spe; int is_spe;
int type; int type;
#if 0
fprintf(stderr, "down=0x%x param1=0x%x param2=0x%x param3=0x%x "
"param4=0x%x\n", down, param1, param2, param3, param4);
#endif
type = down ? KeyPress : KeyRelease; type = down ? KeyPress : KeyRelease;
rdp_scancode = param3; rdp_scancode = param3;
is_ext = param4 & 256; /* 0x100 */ is_ext = param4 & 256; /* 0x100 */
is_spe = param4 & 512; /* 0x200 */ is_spe = param4 & 512; /* 0x200 */
x_scancode = 0; x_scancode = 0;
switch (rdp_scancode) switch (rdp_scancode)
{ {
case 58: /* caps lock */
case 42: /* left shift */
case 54: /* right shift */
case 70: /* scroll lock */
x_scancode = rdp_scancode + MIN_KEY_CODE;
if (x_scancode > 0)
{
rdpEnqueueKey(type, x_scancode);
}
break;
case 56: /* left - right alt button */
if (is_ext)
{
x_scancode = 113; /* right alt button */
}
else
{
x_scancode = 64; /* left alt button */
}
rdpEnqueueKey(type, x_scancode);
break;
case 15: /* tab */ case 15: /* tab */
if (!down && !g_tab_down) if (!down && !g_tab_down)
{ {
check_keysa(); check_keysa(); /* leave x_scancode 0 here, we don't want the tab key up */
/* leave x_scancode 0 here, we don't want the tab key up */
} }
else else
{ {
x_scancode = 23; sendDownUpKeyEvent(type, 23);
} }
g_tab_down = down; g_tab_down = down;
break; break;
case 28: /* Enter or Return */
x_scancode = is_ext ? 108 : 36;
break;
case 29: /* left or right ctrl */ case 29: /* left or right ctrl */
/* this is to handle special case with pause key sending /* this is to handle special case with pause key sending control first */
control first */
if (is_spe) if (is_spe)
{ {
if (down) if (down)
{ {
g_pause_spe = 1; g_pause_spe = 1;
/* leave x_scancode 0 here, we don't want the control key down */
} }
/* leave x_scancode 0 here, we don't want the control key down */
} }
else else
{ {
x_scancode = is_ext ? 109 : 37; x_scancode = is_ext ? 109 : 37;
g_ctrl_down = down ? x_scancode : 0; g_ctrl_down = down ? x_scancode : 0;
rdpEnqueueKey(type, x_scancode);
} }
break; break;
case 42: /* left shift */
x_scancode = 50;
g_shift_down = down ? x_scancode : 0;
break;
case 53: /* / */
x_scancode = is_ext ? 112 : 61;
break;
case 54: /* right shift */
x_scancode = 62;
g_shift_down = down ? x_scancode : 0;
break;
case 55: /* * on KP or Print Screen */
x_scancode = is_ext ? 111 : 63;
break;
case 56: /* left or right alt */
x_scancode = is_ext ? 113 : 64;
g_alt_down = down ? x_scancode : 0;
break;
case 69: /* Pause or Num Lock */ case 69: /* Pause or Num Lock */
if (g_pause_spe) if (g_pause_spe)
{ {
@ -867,63 +898,96 @@ KbdAddEvent(int down, int param1, int param2, int param3, int param4)
} }
else else
{ {
x_scancode = g_ctrl_down ? 110 : 77; x_scancode = g_ctrl_down ? 110 : 77;
} }
sendDownUpKeyEvent(type, x_scancode);
break; break;
case 70: /* scroll lock */
x_scancode = 78; case 28: /* Enter or Return */
if (!down) x_scancode = is_ext ? 108 : 36;
{ sendDownUpKeyEvent(type, x_scancode);
g_scroll_lock_down = !g_scroll_lock_down;
}
break; break;
case 53: /* / */
x_scancode = is_ext ? 112 : 61;
sendDownUpKeyEvent(type, x_scancode);
break;
case 55: /* * on KP or Print Screen */
x_scancode = is_ext ? 111 : 63;
sendDownUpKeyEvent(type, x_scancode);
break;
case 71: /* 7 or Home */ case 71: /* 7 or Home */
x_scancode = is_ext ? 97 : 79; x_scancode = is_ext ? 97 : 79;
sendDownUpKeyEvent(type, x_scancode);
break; break;
case 72: /* 8 or Up */ case 72: /* 8 or Up */
x_scancode = is_ext ? 98 : 80; x_scancode = is_ext ? 98 : 80;
sendDownUpKeyEvent(type, x_scancode);
break; break;
case 73: /* 9 or PgUp */ case 73: /* 9 or PgUp */
x_scancode = is_ext ? 99 : 81; x_scancode = is_ext ? 99 : 81;
sendDownUpKeyEvent(type, x_scancode);
break; break;
case 75: /* 4 or Left */ case 75: /* 4 or Left */
x_scancode = is_ext ? 100 : 83; x_scancode = is_ext ? 100 : 83;
sendDownUpKeyEvent(type, x_scancode);
break; break;
case 77: /* 6 or Right */ case 77: /* 6 or Right */
x_scancode = is_ext ? 102 : 85; x_scancode = is_ext ? 102 : 85;
sendDownUpKeyEvent(type, x_scancode);
break; break;
case 79: /* 1 or End */ case 79: /* 1 or End */
x_scancode = is_ext ? 103 : 87; x_scancode = is_ext ? 103 : 87;
sendDownUpKeyEvent(type, x_scancode);
break; break;
case 80: /* 2 or Down */ case 80: /* 2 or Down */
x_scancode = is_ext ? 104 : 88; x_scancode = is_ext ? 104 : 88;
sendDownUpKeyEvent(type, x_scancode);
break; break;
case 81: /* 3 or PgDn */ case 81: /* 3 or PgDn */
x_scancode = is_ext ? 105 : 89; x_scancode = is_ext ? 105 : 89;
sendDownUpKeyEvent(type, x_scancode);
break; break;
case 82: /* 0 or Insert */ case 82: /* 0 or Insert */
x_scancode = is_ext ? 106 : 90; x_scancode = is_ext ? 106 : 90;
sendDownUpKeyEvent(type, x_scancode);
break; break;
case 83: /* . or Delete */ case 83: /* . or Delete */
x_scancode = is_ext ? 107 : 91; x_scancode = is_ext ? 107 : 91;
sendDownUpKeyEvent(type, x_scancode);
break; break;
case 91: /* left win key */ case 91: /* left win key */
x_scancode = 115; rdpEnqueueKey(type, 115);
break; break;
case 92: /* right win key */ case 92: /* right win key */
x_scancode = 116; rdpEnqueueKey(type, 116);
break; break;
case 93: /* menu key */ case 93: /* menu key */
x_scancode = 117; rdpEnqueueKey(type, 117);
break; break;
default: default:
x_scancode = rdp_scancode + MIN_KEY_CODE; x_scancode = rdp_scancode + MIN_KEY_CODE;
if (x_scancode > 0)
{
sendDownUpKeyEvent(type, x_scancode);
}
break; break;
} }
if (x_scancode > 0)
{
rdpEnqueueKey(type, x_scancode);
}
} }
/******************************************************************************/ /******************************************************************************/

Loading…
Cancel
Save