diff --git a/instfiles/xrdp.sh b/instfiles/xrdp.sh index 3671004f..3e727433 100755 --- a/instfiles/xrdp.sh +++ b/instfiles/xrdp.sh @@ -5,6 +5,18 @@ # chkconfig: 2345 11 89 # 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 LOG=/dev/null CFGDIR=/etc/xrdp diff --git a/sesman/chansrv/Makefile.am b/sesman/chansrv/Makefile.am index 0beb7f0a..a1b5bed9 100644 --- a/sesman/chansrv/Makefile.am +++ b/sesman/chansrv/Makefile.am @@ -30,7 +30,8 @@ xrdp_chansrv_SOURCES = \ clipboard.c \ devredir.c \ rail.c \ - xcommon.c + xcommon.c \ + drdynvc.c xrdp_chansrv_LDFLAGS = \ $(EXTRA_FLAGS) diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index 7c74bb4f..10a42ef9 100644 --- a/sesman/chansrv/chansrv.c +++ b/sesman/chansrv/chansrv.c @@ -69,59 +69,132 @@ struct xrdp_api_data }; /*****************************************************************************/ +/* add data to chan_item, on its way to the client */ /* returns error */ -int APP_CC -send_channel_data(int chan_id, char* data, int size) +static int APP_CC +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 total_size; - int sent; - int rv; + int error; - 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); - 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; } - rv = 0; - sent = 0; - total_size = size; - while (sent < total_size) + cod->s->p += size; + if (cod->s->p >= cod->s->end) { - size = MIN(1600, total_size - sent); - chan_flags = 0; - if (sent == 0) + free_stream(cod->s); + chan_item->head = chan_item->head->next; + 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 */ - 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); - out_uint16_le(s, size); - out_uint32_le(s, total_size); - out_uint8a(s, data + sent, size); - s_mark_end(s); - rv = trans_force_write(g_con_trans); - if (rv != 0) + } + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int APP_CC +send_channel_data(int chan_id, char* data, int size) +{ + int index; + + 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; - 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); if (s == 0) { @@ -339,6 +412,7 @@ static int APP_CC process_message_channel_data_response(struct stream* s) { LOG(10, ("process_message_channel_data_response:")); + check_chan_items(); return 0; } @@ -911,21 +985,41 @@ main(int argc, char** argv) { tbus waiters[4]; int pid = 0; - char text[256] = ""; - char* display_text = (char *)NULL; -#if XRDP_CHANNEL_LOG - char cfg_file[256]; + char text[256]; + char* home_text; + char* display_text; + char log_file[256]; enum logReturns error; -#endif + struct log_config logconfig; 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(); pid = g_getpid(); -#if XRDP_CHANNEL_LOG /* starting logging subsystem */ - g_snprintf(cfg_file, 255, "%s/sesman.ini", XRDP_CFG_PATH); - error = log_start(cfg_file,"XRDP-Chansrv"); + g_memset(&logconfig, 0, sizeof(struct log_config)); + 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) { switch (error) @@ -942,10 +1036,9 @@ main(int argc, char** argv) break; } g_deinit(); - g_exit(1); + return 1; } LOGM((LOG_LEVEL_ALWAYS, "main: app started pid %d(0x%8.8x)", pid, pid)); -#endif /* set up signal handler */ g_signal_kill(term_signal_handler); /* SIGKILL */ g_signal_terminate(term_signal_handler); /* SIGTERM */ @@ -958,6 +1051,7 @@ main(int argc, char** argv) if (g_display_num == 0) { LOGM((LOG_LEVEL_ERROR, "main: error, display is zero")); + g_deinit(); return 1; } LOGM((LOG_LEVEL_INFO, "main: using DISPLAY %d", g_display_num)); diff --git a/sesman/chansrv/chansrv.h b/sesman/chansrv/chansrv.h index a7a0f3e7..ba593461 100644 --- a/sesman/chansrv/chansrv.h +++ b/sesman/chansrv/chansrv.h @@ -21,14 +21,21 @@ #include "arch.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 { int id; int flags; char name[16]; + struct chan_out_data* head; + struct chan_out_data* tail; }; 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) -#else -#define LOGM(_args) -#endif #ifndef GSET_UINT8 #define GSET_UINT8(_ptr, _offset, _data) \ diff --git a/sesman/chansrv/clipboard.c b/sesman/chansrv/clipboard.c index abb17e3e..3bea9704 100644 --- a/sesman/chansrv/clipboard.c +++ b/sesman/chansrv/clipboard.c @@ -95,14 +95,14 @@ static int g_want_image_data = 0; static XSelectionRequestEvent g_saved_selection_req_event; /* for clipboard INCR transfers */ -static Atom g_incr_atom; -static Atom g_incr_atom_type; -static Atom g_incr_atom_target; -static char* g_incr_data; -static int g_incr_data_size; -static int g_incr_in_progress = 0; +static Atom g_incr_atom; +static Atom g_incr_atom_type; +static Atom g_incr_atom_target; +static char* g_incr_data = 0; +static int g_incr_data_size = 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 */ @@ -176,10 +176,10 @@ clipboard_init(void) } 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)); 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)); g_clip_property_atom = XInternAtom(g_display, "XRDP_CLIP_PROPERTY_ATOM", False); @@ -194,6 +194,11 @@ clipboard_init(void) g_image_bmp_atom = XInternAtom(g_display, "image/bmp", 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), 0, 0, 4, 4, 0, 0, 0); @@ -327,10 +332,7 @@ clipboard_send_format_announce(tui32 format_id, char* format_name) struct stream* s; int size; int rv; - unsigned char format_buf[32]; - g_memset(format_buf, 0, 32); - g_snprintf(format_buf, 31, "Native"); make_stream(s); init_stream(s, 8192); 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 clipboard_process_format_announce(struct stream* s, int clip_msg_status, 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 clipboard_prcoess_format_ack(struct stream* s, int clip_msg_status, 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 clipboard_process_data_request(struct stream* s, int clip_msg_status, int clip_msg_len) @@ -576,7 +585,6 @@ clipboard_process_data_response_for_image(struct stream * s, char cdata; int len; int index; - int data_in_len; LOGM((LOG_LEVEL_DEBUG, "clipboard_process_data_response_for_image: " "CLIPRDR_DATA_RESPONSE_FOR_IMAGE")); @@ -600,7 +608,7 @@ clipboard_process_data_response_for_image(struct stream * s, } else { - return; + return 0; } 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 'CLIPBOARD' Atom - typedef struct { + typedef struct + { int type; unsigned long serial; Bool send_event; @@ -794,7 +803,7 @@ clipboard_data_in(struct stream* s, int chan_id, int chan_flags, int length, Atom selection; Time timestamp; Time selection_timestamp; -} XFixesSelectionNotifyEvent; */ + } XFixesSelectionNotifyEvent; */ static int APP_CC 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, AnyPropertyType, <ype, &lfmt, &ln_items, &llen_after, &lxdata); - XFree(lxdata); + if (lxdata != 0) + { + XFree(lxdata); + } if (ltype == 0) { /* XGetWindowProperty failed */ @@ -845,13 +857,14 @@ clipboard_get_window_property(Window wnd, Atom prop, Atom* type, int* fmt, if (ltype == g_incr_atom) { + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_property_notify: INCR start")); g_incr_in_progress = 1; g_incr_atom_type = prop; g_incr_data_size = 0; g_free(g_incr_data); g_incr_data = 0; XDeleteProperty(g_display, g_wnd, prop); - return; + return 0; } if (llen_after < 1) @@ -867,20 +880,29 @@ clipboard_get_window_property(Window wnd, Atom prop, Atom* type, int* fmt, if (ltype == 0) { /* XGetWindowProperty failed */ - XFree(lxdata); + if (lxdata != 0) + { + XFree(lxdata); + } return 1; } lxdata_size = (lfmt / 8) * ln_items; if (lxdata_size < 1) { /* should not happen */ - XFree(lxdata); + if (lxdata != 0) + { + XFree(lxdata); + } return 2; } if (llen_after > 0) { /* should not happen */ - XFree(lxdata); + if (lxdata != 0) + { + XFree(lxdata); + } return 3; } 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); g_memcpy(*xdata, lxdata, lxdata_size); } - XFree(lxdata); + if (lxdata != 0) + { + XFree(lxdata); + } if (xdata_size != 0) { *xdata_size = lxdata_size; @@ -937,10 +962,10 @@ clipboard_event_selection_notify(XEvent* xevent) int convert_to_bmp_image; int send_format_announce; int atom; - int* atoms; + Atom* atoms; Atom type; tui32 format_id; - unsigned char format_name[32]; + char format_name[32]; LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_notify:")); data_size = 0; @@ -948,7 +973,9 @@ clipboard_event_selection_notify(XEvent* xevent) fmt = 0; convert_to_string = 0; convert_to_utf8 = 0; + convert_to_bmp_image = 0; send_format_announce = 0; + format_id = 0; rv = 0; data = 0; type = 0; @@ -985,9 +1012,10 @@ clipboard_event_selection_notify(XEvent* xevent) { if (lxevent->target == g_targets_atom) { + /* on a 64 bit machine, actual_format_return of 32 implies long */ if ((type == XA_ATOM) && (fmt == 32)) { - atoms = (int*)data; + atoms = (Atom*)data; for (index = 0; index < n_items; 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_last_clip_data[g_last_clip_size] = 0; send_format_announce = 1; + format_id = CB_FORMAT_UNICODETEXT; } else if (lxevent->target == XA_STRING) { @@ -1124,7 +1153,6 @@ clipboard_event_selection_request(XEvent* xevent) int n_items; int xdata_size; char* xdata; - int i; lxev = (XSelectionRequestEvent*)xevent; LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: g_wnd %d, " @@ -1163,7 +1191,6 @@ clipboard_event_selection_request(XEvent* xevent) /* target, property pairs */ LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: " "g_multiple_atom")); -#if 0 if (clipboard_get_window_property(xev.xselection.requestor, xev.xselection.property, &type, &fmt, &n_items, &xdata, @@ -1174,7 +1201,6 @@ clipboard_event_selection_request(XEvent* xevent) /* todo */ g_free(xdata); } -#endif } else if ((lxev->target == XA_STRING) || (lxev->target == g_utf8_atom)) { @@ -1205,6 +1231,18 @@ clipboard_event_selection_request(XEvent* xevent) 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 { LOGM((LOG_LEVEL_ERROR,"clipboard_event_selection_request: unknown " @@ -1257,7 +1295,7 @@ clipboard_event_property_notify(XEvent* xevent) int format_in_bytes; int new_data_len; char* cptr; - unsigned char format_name[32]; + char format_name[32]; LOG(10, ("clipboard_check_wait_objs: PropertyNotify .window %d " ".state %d .atom %d", xevent->xproperty.window, @@ -1276,11 +1314,13 @@ clipboard_event_property_notify(XEvent* xevent) } if (bytes_left <= 0) { + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_property_notify: INCR done")); g_memset(format_name, 0, 32); /* clipboard INCR cycle has completed */ g_incr_in_progress = 0; g_last_clip_size = g_incr_data_size; g_last_clip_data = g_incr_data; + g_incr_data = 0; g_last_clip_type = g_incr_atom_target; 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); 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 */ format_in_bytes = 8; } 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); - 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) { + g_incr_data = 0; /* cannot add any more data */ if (data != 0) { XFree(data); - data = 0; } XDeleteProperty(g_display, g_wnd, g_incr_atom_type); return 0; @@ -1325,7 +1362,6 @@ clipboard_event_property_notify(XEvent* xevent) if (data) { XFree(data); - data = 0; } XDeleteProperty(g_display, g_wnd, g_incr_atom_type); } diff --git a/sesman/chansrv/drdynvc.c b/sesman/chansrv/drdynvc.c new file mode 100644 index 00000000..da0e8fe3 --- /dev/null +++ b/sesman/chansrv/drdynvc.c @@ -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. + */ diff --git a/sesman/chansrv/drdynvc.h b/sesman/chansrv/drdynvc.h new file mode 100644 index 00000000..14237835 --- /dev/null +++ b/sesman/chansrv/drdynvc.h @@ -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 diff --git a/sesman/chansrv/xcommon.c b/sesman/chansrv/xcommon.c index 5510a055..70b52694 100644 --- a/sesman/chansrv/xcommon.c +++ b/sesman/chansrv/xcommon.c @@ -164,7 +164,7 @@ xcommon_check_wait_objs(void) { time_diff = xcommon_get_local_time() - g_waiting_for_data_response_time; - if (time_diff > 1000) + if (time_diff > 10000) { LOGM((LOG_LEVEL_ERROR, "xcommon_check_wait_objs: warning, " "waiting for data response too long")); diff --git a/xorg/X11R7.6/rdp/rdpinput.c b/xorg/X11R7.6/rdp/rdpinput.c index 84418dc8..1256d0e0 100644 --- a/xorg/X11R7.6/rdp/rdpinput.c +++ b/xorg/X11R7.6/rdp/rdpinput.c @@ -791,6 +791,25 @@ check_keysa(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) { int rdp_scancode; @@ -799,63 +818,75 @@ KbdAddEvent(int down, int param1, int param2, int param3, int param4) int is_spe; 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; rdp_scancode = param3; is_ext = param4 & 256; /* 0x100 */ is_spe = param4 & 512; /* 0x200 */ x_scancode = 0; + 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 */ if (!down && !g_tab_down) { - check_keysa(); - /* leave x_scancode 0 here, we don't want the tab key up */ + check_keysa(); /* leave x_scancode 0 here, we don't want the tab key up */ } else { - x_scancode = 23; + sendDownUpKeyEvent(type, 23); } + g_tab_down = down; break; - case 28: /* Enter or Return */ - x_scancode = is_ext ? 108 : 36; - break; + case 29: /* left or right ctrl */ - /* this is to handle special case with pause key sending - control first */ + /* this is to handle special case with pause key sending control first */ if (is_spe) { 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 { x_scancode = is_ext ? 109 : 37; g_ctrl_down = down ? x_scancode : 0; + rdpEnqueueKey(type, x_scancode); } 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 */ if (g_pause_spe) { @@ -867,63 +898,96 @@ KbdAddEvent(int down, int param1, int param2, int param3, int param4) } else { - x_scancode = g_ctrl_down ? 110 : 77; + x_scancode = g_ctrl_down ? 110 : 77; } + sendDownUpKeyEvent(type, x_scancode); break; - case 70: /* scroll lock */ - x_scancode = 78; - if (!down) - { - g_scroll_lock_down = !g_scroll_lock_down; - } + + case 28: /* Enter or Return */ + x_scancode = is_ext ? 108 : 36; + sendDownUpKeyEvent(type, x_scancode); 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 */ x_scancode = is_ext ? 97 : 79; + sendDownUpKeyEvent(type, x_scancode); break; + case 72: /* 8 or Up */ x_scancode = is_ext ? 98 : 80; + sendDownUpKeyEvent(type, x_scancode); break; + case 73: /* 9 or PgUp */ x_scancode = is_ext ? 99 : 81; + sendDownUpKeyEvent(type, x_scancode); break; + case 75: /* 4 or Left */ x_scancode = is_ext ? 100 : 83; + sendDownUpKeyEvent(type, x_scancode); break; + case 77: /* 6 or Right */ x_scancode = is_ext ? 102 : 85; + sendDownUpKeyEvent(type, x_scancode); break; + case 79: /* 1 or End */ x_scancode = is_ext ? 103 : 87; + sendDownUpKeyEvent(type, x_scancode); break; + case 80: /* 2 or Down */ x_scancode = is_ext ? 104 : 88; + sendDownUpKeyEvent(type, x_scancode); break; + case 81: /* 3 or PgDn */ x_scancode = is_ext ? 105 : 89; + sendDownUpKeyEvent(type, x_scancode); break; + case 82: /* 0 or Insert */ x_scancode = is_ext ? 106 : 90; + sendDownUpKeyEvent(type, x_scancode); break; + case 83: /* . or Delete */ x_scancode = is_ext ? 107 : 91; + sendDownUpKeyEvent(type, x_scancode); break; + case 91: /* left win key */ - x_scancode = 115; + rdpEnqueueKey(type, 115); break; + case 92: /* right win key */ - x_scancode = 116; + rdpEnqueueKey(type, 116); break; + case 93: /* menu key */ - x_scancode = 117; + rdpEnqueueKey(type, 117); break; + default: x_scancode = rdp_scancode + MIN_KEY_CODE; + if (x_scancode > 0) + { + sendDownUpKeyEvent(type, x_scancode); + } break; } - if (x_scancode > 0) - { - rdpEnqueueKey(type, x_scancode); - } } /******************************************************************************/