From e3ffad77ca4665f047635e72753ff83030e8f48e Mon Sep 17 00:00:00 2001 From: TOMATO-ONE Date: Tue, 20 Jul 2021 01:08:45 +0900 Subject: [PATCH] neutrinordp: Allow fixed keyboard lauout information to be sent to remote. #1933 --- common/string_calls.c | 24 +++++++++++++ common/string_calls.h | 9 +++++ neutrinordp/xrdp-neutrinordp.c | 63 ++++++++++++++++++++++++++++++++++ neutrinordp/xrdp-neutrinordp.h | 10 ++++++ xrdp/xrdp.ini.in | 7 ++++ 5 files changed, 113 insertions(+) diff --git a/common/string_calls.c b/common/string_calls.c index b3a4a9a7..151a5dc4 100644 --- a/common/string_calls.c +++ b/common/string_calls.c @@ -407,6 +407,30 @@ g_atoi(const char *str) return atoi(str); } +/*****************************************************************************/ +/* As g_atoi() but allows for hexadecimal too */ +int +g_atoix(const char *str) +{ + int base = 10; + if (str == NULL) + { + str = "0"; + } + + while (isspace(*str)) + { + ++str; + } + + if (*str == '0' && tolower(*(str + 1)) == 'x') + { + str += 2; + base = 16; + } + return strtol(str, NULL, base); +} + /*****************************************************************************/ int g_htoi(char *str) diff --git a/common/string_calls.h b/common/string_calls.h index 6552e90b..2767a754 100644 --- a/common/string_calls.h +++ b/common/string_calls.h @@ -155,6 +155,15 @@ int g_strncmp_d(const char *c1, const char *c2, const char delim, int len); int g_strcasecmp(const char *c1, const char *c2); int g_strncasecmp(const char *c1, const char *c2, int len); int g_atoi(const char *str); +/** + * Extends g_atoi(), Converts decimal and hexadecimal number String to integer + * + * Prefix hexadecimal numbers with '0x' + * + * @param str String to convert to an integer + * @return int Integer expression of a string + */ +int g_atoix(const char *str); int g_htoi(char *str); int g_bytes_to_hexstr(const void *bytes, int num_bytes, char *out_str, int bytes_out_str); diff --git a/neutrinordp/xrdp-neutrinordp.c b/neutrinordp/xrdp-neutrinordp.c index feb6953e..fae459b8 100644 --- a/neutrinordp/xrdp-neutrinordp.c +++ b/neutrinordp/xrdp-neutrinordp.c @@ -97,6 +97,7 @@ lxrdp_start(struct mod *mod, int w, int h, int bpp) static void set_keyboard_overrides(struct mod *mod) { + const struct kbd_overrides *ko = &mod->kbd_overrides; rdpSettings *settings = mod->inst->settings; if (mod->allow_client_kbd_settings) @@ -126,6 +127,42 @@ set_keyboard_overrides(struct mod *mod) /* Nothing to do. */ } } + + if (ko->type != 0) + { + LOG(LOG_LEVEL_INFO, "overrode kbd_type 0x%02X with 0x%02X", + settings->kbd_type, ko->type); + settings->kbd_type = ko->type; + } + + if (ko->subtype != 0) + { + LOG(LOG_LEVEL_INFO, "overrode kbd_subtype 0x%02X with 0x%02X", + settings->kbd_subtype, ko->subtype); + settings->kbd_subtype = ko->subtype; + } + + if (ko->fn_keys != 0) + { + LOG(LOG_LEVEL_INFO, "overrode kbd_fn_keys %d with %d", + settings->kbd_fn_keys, ko->fn_keys); + settings->kbd_fn_keys = ko->fn_keys; + } + + if (ko->layout != 0) + { + LOG(LOG_LEVEL_INFO, "overrode kbd_layout 0x%08X with 0x%08X", + settings->kbd_layout, ko->layout); + settings->kbd_layout = ko->layout; + } + + if (ko->layout_mask != 0) + { + LOG(LOG_LEVEL_INFO, "Masked kbd_layout 0x%08X to 0x%08X", + settings->kbd_layout, settings->kbd_layout & ko->layout_mask); + settings->kbd_layout &= ko->layout_mask; + } + LOG(LOG_LEVEL_INFO, "NeutrinoRDP proxy remote keyboard settings, " "kbd_type:[0x%02X], kbd_subtype:[0x%02X], " "kbd_fn_keys:[%02d], kbd_layout:[0x%08X]", @@ -529,6 +566,7 @@ lxrdp_set_param(struct mod *mod, const char *name, const char *value) } else if (g_strcmp(name, "keylayout") == 0) { + LOG(LOG_LEVEL_DEBUG, "%s:[0x%08X]", name, g_atoi(value)); } else if (g_strcmp(name, "name") == 0) { @@ -2237,6 +2275,31 @@ lfreerdp_receive_channel_data(freerdp *instance, int channelId, uint8 *data, LOG(LOG_LEVEL_ERROR, "lfreerdp_receive_channel_data: error %d", error); } } + else if (g_strcmp(name, "neutrinordp.allow_client_keyboardLayout") == 0) + { + mod->allow_client_kbd_settings = g_text2bool(value); + } + else if (g_strcmp(name, "neutrinordp.override_keyboardLayout_mask") == 0) + { + /* Keyboard values are stored for later processing */ + mod->kbd_overrides.layout_mask = g_atoix(value); + } + else if (g_strcmp(name, "neutrinordp.override_kbd_type") == 0) + { + mod->kbd_overrides.type = g_atoix(value); + } + else if (g_strcmp(name, "neutrinordp.override_kbd_subtype") == 0) + { + mod->kbd_overrides.subtype = g_atoix(value); + } + else if (g_strcmp(name, "neutrinordp.override_kbd_fn_keys") == 0) + { + mod->kbd_overrides.fn_keys = g_atoix(value); + } + else if (g_strcmp(name, "neutrinordp.override_kbd_layout") == 0) + { + mod->kbd_overrides.layout = g_atoix(value); + } else { LOG(LOG_LEVEL_ERROR, "lfreerdp_receive_channel_data: bad lchid"); diff --git a/neutrinordp/xrdp-neutrinordp.h b/neutrinordp/xrdp-neutrinordp.h index ce478fa2..72451a7a 100644 --- a/neutrinordp/xrdp-neutrinordp.h +++ b/neutrinordp/xrdp-neutrinordp.h @@ -63,6 +63,15 @@ struct pointer_item struct source_info; +struct kbd_overrides +{ + int type; + int subtype; + int fn_keys; + int layout; + int layout_mask; +}; + struct mod { int size; /* size of this struct */ @@ -223,4 +232,5 @@ struct mod int perf_settings_override_mask; /* Performance bits overridden in ini file */ int perf_settings_values_mask; /* Values of overridden performance bits */ int allow_client_kbd_settings; + struct kbd_overrides kbd_overrides; /* neutrinordp.overide_kbd_* values */ }; diff --git a/xrdp/xrdp.ini.in b/xrdp/xrdp.ini.in index 615ffbdb..c84aad13 100644 --- a/xrdp/xrdp.ini.in +++ b/xrdp/xrdp.ini.in @@ -279,6 +279,13 @@ password=ask ; If you want to tell the remote the keyboard layout of the RDP Client, ; by uncommenting the following line. #neutrinordp.allow_client_keyboardLayout=true +; The following options will override the remote keyboard layout settings. +; These options are for DEBUG and are not recommended for regular use. +#neutrinordp.override_keyboardLayout_mask=0x0000FFFF +#neutrinordp.override_kbd_type=0x04 +#neutrinordp.override_kbd_subtype=0x01 +#neutrinordp.override_kbd_fn_keys=12 +#neutrinordp.override_kbd_layout=0x00000409 ; You can override the common channel settings for each session type #channel.rdpdr=true