From f8fa387faee590994c4d23f8d1101cdb8457299b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 5 Jul 2011 18:26:12 -0400 Subject: [PATCH] libfreerdp-core: added GCC client data blocks --- cunit/test_transport.c | 2 +- include/freerdp/freerdp.h | 2 +- include/freerdp/settings.h | 44 ++++++----- include/freerdp/types/base.h | 8 ++ include/freerdp/utils/stream.h | 7 +- libfreerdp-core/gcc.c | 139 +++++++++++++++++++++++++++++++++ libfreerdp-core/gcc.h | 82 +++++++++++++++++++ libfreerdp-core/nego.c | 6 +- libfreerdp-gdi/gdi.c | 2 +- 9 files changed, 267 insertions(+), 25 deletions(-) diff --git a/cunit/test_transport.c b/cunit/test_transport.c index 795180ec3..e48b02356 100644 --- a/cunit/test_transport.c +++ b/cunit/test_transport.c @@ -81,7 +81,7 @@ void test_transport(void) CU_ASSERT(r == True); stream = stream_new(sizeof(test_x224_req)); - stream_write_buffer(stream, test_x224_req, sizeof(test_x224_req)); + stream_write(stream, test_x224_req, sizeof(test_x224_req)); r = transport_send(transport, stream); CU_ASSERT(r == 0); diff --git a/include/freerdp/freerdp.h b/include/freerdp/freerdp.h index d7c4f5d07..22310cd61 100644 --- a/include/freerdp/freerdp.h +++ b/include/freerdp/freerdp.h @@ -20,8 +20,8 @@ #ifndef __FREERDP_H #define __FREERDP_H -#include "settings.h" #include "types/ui.h" +#include "settings.h" #include "extension.h" #define FREERDP_INTERFACE_VERSION 4 diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index c3a04f750..af989b254 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -20,10 +20,12 @@ #ifndef __RDP_SETTINGS_H #define __RDP_SETTINGS_H +#include + struct rdp_chan { char name[8]; /* ui sets */ - int flags; /* ui sets */ + int options; /* ui sets */ int chan_id; /* core sets */ void * handle; /* just for ui */ }; @@ -45,8 +47,25 @@ struct rdp_monitor struct rdp_settings { - int width; - int height; + uint16 width; + uint16 height; + uint32 rdp_version; + uint16 color_depth; + uint32 kbd_layout; + uint32 kbd_type; + uint32 kbd_subtype; + uint32 kbd_fn_keys; + uint32 selected_protocol; + + uint32 session_id; + int console_session; + + int num_channels; + struct rdp_chan channels[16]; + + int num_monitors; + struct rdp_monitor monitors[16]; + char hostname[16]; char server[64]; char domain[16]; @@ -55,26 +74,19 @@ struct rdp_settings char directory[256]; char username[256]; int tcp_port_rdp; - int keyboard_layout; - int keyboard_type; - int keyboard_subtype; - int keyboard_functionkeys; - char xkb_layout[32]; - char xkb_variant[32]; + int performance_flags; + + int encryption; int tls_security; int nla_security; int rdp_security; - int encryption; - int rdp_version; + int remote_app; char app_name[64]; - int console_session; - int server_depth; int bitmap_cache; int bitmap_cache_persist_enable; int bitmap_cache_precache; int bitmap_compression; - int performanceflags; int desktop_save; int polygon_ellipse_orders; int autologin; @@ -87,12 +99,8 @@ struct rdp_settings int rfx_flags; int ui_decode_flags; int use_frame_ack; - int num_channels; int software_gdi; - struct rdp_chan channels[16]; struct rdp_ext_set extensions[16]; - int num_monitors; - struct rdp_monitor monitors[16]; }; #endif /* __RDP_SETTINGS_H */ diff --git a/include/freerdp/types/base.h b/include/freerdp/types/base.h index a8dd99548..7064a01cf 100644 --- a/include/freerdp/types/base.h +++ b/include/freerdp/types/base.h @@ -44,4 +44,12 @@ typedef signed long long sint64; typedef int boolean; +#ifndef MIN +#define MIN(x,y) (((x) < (y)) ? (x) : (y)) +#endif + +#ifndef MAX +#define MAX(x,y) (((x) > (y)) ? (x) : (y)) +#endif + #endif diff --git a/include/freerdp/utils/stream.h b/include/freerdp/utils/stream.h index d4a5617be..e6a9d6055 100644 --- a/include/freerdp/utils/stream.h +++ b/include/freerdp/utils/stream.h @@ -21,6 +21,7 @@ #ifndef __STREAM_UTILS_H #define __STREAM_UTILS_H +#include #include struct _STREAM @@ -93,10 +94,14 @@ stream_extend(STREAM * stream); *_s->ptr++ = ((_v) >> 40) & 0xFF; \ *_s->ptr++ = ((_v) >> 48) & 0xFF; \ *_s->ptr++ = ((_v) >> 56) & 0xFF; } while (0) -#define stream_write_buffer(_s, _b, _n) do { \ +#define stream_write(_s, _b, _n) do { \ memcpy(_s->ptr, (_b), (_n)); \ _s->ptr += (_n); \ } while (0) +#define stream_write_padding(_s, _n) do { \ + memset(_s->ptr, '\0', (_n)); \ + _s->ptr += (_n); \ + } while (0) #define stream_peek_uint8(_s, _v) do { _v = *_s->ptr; } while (0) #define stream_peek_uint16(_s, _v) do { _v = \ diff --git a/libfreerdp-core/gcc.c b/libfreerdp-core/gcc.c index 6c4961faa..5293b6c02 100644 --- a/libfreerdp-core/gcc.c +++ b/libfreerdp-core/gcc.c @@ -134,6 +134,21 @@ gcc_write_create_conference_request(STREAM* s, STREAM* user_data) per_write_octet_string(s, user_data->buffer, stream_get_length(user_data), 0); /* array of client data blocks */ } +/** + * Write a user data header (TS_UD_HEADER).\n + * @msdn{cc240509} + * @param s stream + * @param type data block type + * @param length data block length + */ + +void +gcc_write_user_data_header(STREAM* s, uint16 type, uint16 length) +{ + stream_write_uint16(s, type); /* type */ + stream_write_uint16(s, length); /* length */ +} + /** * Write a client core data block (TS_UD_CS_CORE).\n * @msdn{cc240510} @@ -144,7 +159,61 @@ gcc_write_create_conference_request(STREAM* s, STREAM* user_data) void gcc_write_client_core_data(STREAM* s, rdpSettings *settings) { + uint32 version; + uint16 highColorDepth; + uint16 supportedColorDepths; + uint16 earlyCapabilityFlags; + uint8 connectionType; + gcc_write_user_data_header(s, CS_CORE, 216); + + version = settings->rdp_version >= 5 ? RDP_VERSION_5_PLUS : RDP_VERSION_4; + + stream_write_uint32(s, version); /* version */ + stream_write_uint16(s, settings->width); /* desktopWidth */ + stream_write_uint16(s, settings->height); /* desktopHeight */ + stream_write_uint16(s, RNS_UD_COLOR_8BPP); /* colorDepth, ignored because of postBeta2ColorDepth */ + stream_write_uint16(s, RNS_UD_SAS_DEL); /* SASSequence (Secure Access Sequence) */ + stream_write_uint32(s, settings->kbd_layout); /* keyboardLayout */ + stream_write_uint32(s, 2600); /* clientBuild */ + + stream_write_padding(s, 32); /* clientName */ + + stream_write_uint32(s, settings->kbd_type); /* keyboardType */ + stream_write_uint32(s, settings->kbd_subtype); /* keyboardSubType */ + stream_write_uint32(s, settings->kbd_fn_keys); /* keyboardFunctionKey */ + + stream_write_padding(s, 64); /* imeFileName */ + + stream_write_uint16(s, RNS_UD_COLOR_8BPP); /* postBeta2ColorDepth */ + stream_write_uint16(s, 1); /* clientProductID */ + stream_write_uint16(s, 0); /* serialNumber (should be initialized to 0) */ + + highColorDepth = MIN(settings->color_depth, 24); + supportedColorDepths = RNS_UD_32BPP_SUPPORT | RNS_UD_24BPP_SUPPORT | RNS_UD_16BPP_SUPPORT | RNS_UD_15BPP_SUPPORT; + + stream_write_uint16(s, highColorDepth); /* highColorDepth */ + stream_write_uint16(s, supportedColorDepths); /* supportedColorDepths */ + + connectionType = 0; + earlyCapabilityFlags = RNS_UD_CS_SUPPORT_ERRINFO_PDU; + + if (settings->performance_flags == PERF_FLAG_NONE) + { + earlyCapabilityFlags |= RNS_UD_CS_VALID_CONNECTION_TYPE; + connectionType = CONNECTION_TYPE_LAN; + } + + if (settings->color_depth == 32) + earlyCapabilityFlags |= RNS_UD_CS_WANT_32BPP_SESSION; + + stream_write_uint16(s, earlyCapabilityFlags); /* earlyCapabilityFlags */ + stream_write_padding(s, 64); /* clientDigProductId (64 bytes) */ + + stream_write_uint8(s, connectionType); /* connectionType */ + stream_write_uint8(s, 0); /* pad1octet */ + + stream_write_uint32(s, settings->selected_protocol); /* serverSelectedProtocol */ } /** @@ -157,7 +226,23 @@ gcc_write_client_core_data(STREAM* s, rdpSettings *settings) void gcc_write_client_security_data(STREAM* s, rdpSettings *settings) { + uint16 encryptionMethods; + gcc_write_user_data_header(s, CS_SECURITY, 12); + + encryptionMethods = ENCRYPTION_40BIT_FLAG | ENCRYPTION_128BIT_FLAG; + + if (settings->encryption) + { + stream_write_uint32(s, encryptionMethods); /* encryptionMethods */ + stream_write_uint32(s, 0); /* extEncryptionMethods */ + } + else + { + /* French locale, disable encryption */ + stream_write_uint32(s, 0); /* encryptionMethods */ + stream_write_uint32(s, encryptionMethods); /* extEncryptionMethods */ + } } /** @@ -170,7 +255,24 @@ gcc_write_client_security_data(STREAM* s, rdpSettings *settings) void gcc_write_client_network_data(STREAM* s, rdpSettings *settings) { + int i; + uint16 length; + if (settings->num_channels > 0) + { + length = settings->num_channels * 12 + 8; + gcc_write_user_data_header(s, CS_NET, length); + + stream_write_uint32(s, settings->num_channels); /* channelCount */ + + /* channelDefArray */ + for (i = 0; i < settings->num_channels; i++) + { + /* CHANNEL_DEF */ + stream_write(s, settings->channels[i].name, 8); /* name (8 bytes) */ + stream_write_uint32(s, settings->channels[i].options); /* options (4 bytes) */ + } + } } /** @@ -183,7 +285,18 @@ gcc_write_client_network_data(STREAM* s, rdpSettings *settings) void gcc_write_client_cluster_data(STREAM* s, rdpSettings *settings) { + uint32 flags; + uint32 redirectedSessionID; + gcc_write_user_data_header(s, CS_CLUSTER, 12); + + flags = REDIRECTION_SUPPORTED | REDIRECTION_VERSION4; + + if (settings->console_session || settings->session_id) + flags |= REDIRECTED_SESSIONID_FIELD_VALID; + + stream_write_uint32(s, flags); /* flags */ + stream_write_uint32(s, settings->session_id); /* redirectedSessionID */ } /** @@ -196,5 +309,31 @@ gcc_write_client_cluster_data(STREAM* s, rdpSettings *settings) void gcc_write_client_monitor_data(STREAM* s, rdpSettings *settings) { + int i; + uint16 length; + uint32 left, top, right, bottom, flags; + if (settings->num_monitors > 1) + { + length = (20 * settings->num_monitors) + 12; + gcc_write_user_data_header(s, CS_MONITOR, length); + + stream_write_uint32(s, 0); /* flags */ + stream_write_uint32(s, settings->num_monitors); /* monitorCount */ + + for (i = 0; i < settings->num_monitors; i++) + { + left = settings->monitors[i].x; + top = settings->monitors[i].y; + right = settings->monitors[i].x + settings->monitors[i].width - 1; + bottom = settings->monitors[i].y + settings->monitors[i].height - 1; + flags = settings->monitors[i].is_primary ? MONITOR_PRIMARY : 0; + + stream_write_uint32(s, left); /* left */ + stream_write_uint32(s, top); /* top */ + stream_write_uint32(s, right); /* right */ + stream_write_uint32(s, bottom); /* bottom */ + stream_write_uint32(s, flags); /* flags */ + } + } } diff --git a/libfreerdp-core/gcc.h b/libfreerdp-core/gcc.h index 9348833f5..28de0acb5 100644 --- a/libfreerdp-core/gcc.h +++ b/libfreerdp-core/gcc.h @@ -25,9 +25,91 @@ #include #include +/* Client to Server (CS) data blocks */ +#define CS_CORE 0xC001 +#define CS_SECURITY 0xC002 +#define CS_NET 0xC003 +#define CS_CLUSTER 0xC004 +#define CS_MONITOR 0xC005 + +/* Server to Client (SC) data blocks */ +#define SC_CORE 0x0C01 +#define SC_SECURITY 0x0C02 +#define SC_NET 0x0C03 + +/* RDP version */ +#define RDP_VERSION_4 0x00080001 +#define RDP_VERSION_5_PLUS 0x00080004 + +/* Color depth */ +#define RNS_UD_COLOR_4BPP 0xCA00 +#define RNS_UD_COLOR_8BPP 0xCA01 +#define RNS_UD_COLOR_16BPP_555 0xCA02 +#define RNS_UD_COLOR_16BPP_565 0xCA03 +#define RNS_UD_COLOR_24BPP 0xCA04 + +/* Secure Access Sequence */ +#define RNS_UD_SAS_DEL 0xAA03 + +/* Supported Color Depths */ +#define RNS_UD_24BPP_SUPPORT 0x0001 +#define RNS_UD_16BPP_SUPPORT 0x0002 +#define RNS_UD_15BPP_SUPPORT 0x0004 +#define RNS_UD_32BPP_SUPPORT 0x0008 + +/* Early Capability Flags */ +#define RNS_UD_CS_SUPPORT_ERRINFO_PDU 0x0001 +#define RNS_UD_CS_WANT_32BPP_SESSION 0x0002 +#define RNS_UD_CS_SUPPORT_STATUSINFO_PDU 0x0004 +#define RNS_UD_CS_STRONG_ASYMMETRIC_KEYS 0x0008 +#define RNS_UD_CS_VALID_CONNECTION_TYPE 0x0020 +#define RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU 0x0040 + +/* Performance Flags */ +#define PERF_FLAG_NONE 0x00000000 +#define PERF_DISABLE_WALLPAPER 0x00000001 +#define PERF_DISABLE_FULLWINDOWDRAG 0x00000002 +#define PERF_DISABLE_MENUANIMATIONS 0x00000004 +#define PERF_DISABLE_THEMING 0x00000008 +#define PERF_RESERVED1 0x00000010 +#define PERF_DISABLE_CURSOR_SHADOW 0x00000020 +#define PERF_DISABLE_CURSORSETTINGS 0x00000040 +#define PERF_ENABLE_FONT_SMOOTHING 0x00000080 +#define PERF_ENABLE_DESKTOP_COMPOSITION 0x00000100 + +/* Connection Types */ +#define CONNECTION_TYPE_MODEM 0x01 +#define CONNECTION_TYPE_BROADBAND_LOW 0x02 +#define CONNECTION_TYPE_SATELLITE 0x03 +#define CONNECTION_TYPE_BROADBAND_HIGH 0x04 +#define CONNECTION_TYPE_WAN 0x05 +#define CONNECTION_TYPE_LAN 0x06 + +/* Encryption Methods */ +#define ENCRYPTION_40BIT_FLAG 0x00000001 +#define ENCRYPTION_128BIT_FLAG 0x00000002 +#define ENCRYPTION_56BIT_FLAG 0x00000008 +#define ENCRYPTION_FIPS_FLAG 0x00000010 + +/* Cluster Information Flags */ +#define REDIRECTION_SUPPORTED 0x00000001 +#define REDIRECTED_SESSIONID_FIELD_VALID 0x00000002 +#define REDIRECTED_SMARTCARD 0x00000040 + +#define REDIRECTION_VERSION1 0x00 +#define REDIRECTION_VERSION2 0x01 +#define REDIRECTION_VERSION3 0x02 +#define REDIRECTION_VERSION4 0x03 +#define REDIRECTION_VERSION5 0x04 + +/* Monitor Flags */ +#define MONITOR_PRIMARY 0x00000001 + void gcc_write_create_conference_request(STREAM* s, STREAM* user_data); +void +gcc_write_user_data_header(STREAM* s, uint16 type, uint16 length); void gcc_write_client_core_data(STREAM* s, rdpSettings *settings); void diff --git a/libfreerdp-core/nego.c b/libfreerdp-core/nego.c index f168d9984..b840c0fc5 100644 --- a/libfreerdp-core/nego.c +++ b/libfreerdp-core/nego.c @@ -257,8 +257,8 @@ void nego_send_negotiation_request(rdpNego *nego) if (nego->cookie) { int cookie_length = strlen(nego->cookie); - stream_write_buffer(s, "Cookie: mstshash=", 17); - stream_write_buffer(s, nego->cookie, cookie_length); + stream_write(s, "Cookie: mstshash=", 17); + stream_write(s, nego->cookie, cookie_length); stream_write_uint8(s, 0x0D); /* CR */ stream_write_uint8(s, 0x0A); /* LF */ length += cookie_length + 19; @@ -266,7 +266,7 @@ void nego_send_negotiation_request(rdpNego *nego) else if (nego->routing_token) { int routing_token_length = strlen(nego->routing_token); - stream_write_buffer(s, nego->routing_token, routing_token_length); + stream_write(s, nego->routing_token, routing_token_length); length += routing_token_length; } diff --git a/libfreerdp-gdi/gdi.c b/libfreerdp-gdi/gdi.c index 66babe757..369d51396 100644 --- a/libfreerdp-gdi/gdi.c +++ b/libfreerdp-gdi/gdi.c @@ -1117,7 +1117,7 @@ gdi_init(rdpInst * inst, uint32 flags) gdi->width = inst->settings->width; gdi->height = inst->settings->height; - gdi->srcBpp = inst->settings->server_depth; + gdi->srcBpp = inst->settings->color_depth; /* default internal buffer format */ gdi->dstBpp = 32;