From 3951a6e1c3f989bd8ed5bbae6a0931adf260cacc Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 21 Oct 2013 23:33:25 -0400 Subject: [PATCH] channels/rdpgfx: implement basic negotiation --- channels/rdpgfx/client/rdpgfx_common.c | 72 ++++++++++++++++++++++++++++++++++ channels/rdpgfx/client/rdpgfx_common.h | 9 +++++ channels/rdpgfx/client/rdpgfx_main.c | 9 +++++ client/common/cmdline.c | 16 ++++++++ include/freerdp/settings.h | 1 + libfreerdp/core/gcc.c | 9 +++++ libfreerdp/core/nego.c | 12 +++++- libfreerdp/core/nego.h | 1 + 8 files changed, 127 insertions(+), 2 deletions(-) diff --git a/channels/rdpgfx/client/rdpgfx_common.c b/channels/rdpgfx/client/rdpgfx_common.c index bd0a76f..c2ea76d 100644 --- a/channels/rdpgfx/client/rdpgfx_common.c +++ b/channels/rdpgfx/client/rdpgfx_common.c @@ -26,4 +26,76 @@ #include "rdpgfx_common.h" +int rdpgfx_read_point16(wStream* s, RDPGFX_POINT16* point16) +{ + Stream_Read_UINT16(s, point16->x); /* x (2 bytes) */ + Stream_Read_UINT16(s, point16->y); /* y (2 bytes) */ + return 0; +} + +int rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16) +{ + Stream_Write_UINT16(s, point16->x); /* x (2 bytes) */ + Stream_Write_UINT16(s, point16->y); /* y (2 bytes) */ + + return 0; +} + +int rdpgfx_read_rect16(wStream* s, RDPGFX_RECT16* rect16) +{ + Stream_Read_UINT16(s, rect16->left); /* left (2 bytes) */ + Stream_Read_UINT16(s, rect16->top); /* top (2 bytes) */ + Stream_Read_UINT16(s, rect16->right); /* right (2 bytes) */ + Stream_Read_UINT16(s, rect16->bottom); /* bottom (2 bytes) */ + + return 0; +} + +int rdpgfx_write_rect16(wStream* s, RDPGFX_RECT16* rect16) +{ + Stream_Write_UINT16(s, rect16->left); /* left (2 bytes) */ + Stream_Write_UINT16(s, rect16->top); /* top (2 bytes) */ + Stream_Write_UINT16(s, rect16->right); /* right (2 bytes) */ + Stream_Write_UINT16(s, rect16->bottom); /* bottom (2 bytes) */ + + return 0; +} + +int rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32) +{ + Stream_Read_UINT8(s, color32->B); /* B (1 byte) */ + Stream_Read_UINT8(s, color32->G); /* G (1 byte) */ + Stream_Read_UINT8(s, color32->R); /* R (1 byte) */ + Stream_Read_UINT8(s, color32->XA); /* XA (1 byte) */ + + return 0; +} + +int rdpgfx_write_color32(wStream* s, RDPGFX_COLOR32* color32) +{ + Stream_Write_UINT8(s, color32->B); /* B (1 byte) */ + Stream_Write_UINT8(s, color32->G); /* G (1 byte) */ + Stream_Write_UINT8(s, color32->R); /* R (1 byte) */ + Stream_Write_UINT8(s, color32->XA); /* XA (1 byte) */ + + return 0; +} + +int rdpgfx_read_header(wStream* s, RDPGFX_HEADER* header) +{ + Stream_Read_UINT16(s, header->cmdId); /* cmdId (2 bytes) */ + Stream_Read_UINT16(s, header->flags); /* flags (2 bytes) */ + Stream_Read_UINT16(s, header->pduLength); /* pduLength (4 bytes) */ + + return 0; +} + +int rdpgfx_write_header(wStream* s, RDPGFX_HEADER* header) +{ + Stream_Write_UINT16(s, header->cmdId); /* cmdId (2 bytes) */ + Stream_Write_UINT16(s, header->flags); /* flags (2 bytes) */ + Stream_Write_UINT16(s, header->pduLength); /* pduLength (4 bytes) */ + + return 0; +} diff --git a/channels/rdpgfx/client/rdpgfx_common.h b/channels/rdpgfx/client/rdpgfx_common.h index 20fd722..df80c2a 100644 --- a/channels/rdpgfx/client/rdpgfx_common.h +++ b/channels/rdpgfx/client/rdpgfx_common.h @@ -23,7 +23,16 @@ #include #include +#include +int rdpgfx_read_point16(wStream* s, RDPGFX_POINT16* point16); +int rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16); +int rdpgfx_read_rect16(wStream* s, RDPGFX_RECT16* rect16); +int rdpgfx_write_rect16(wStream* s, RDPGFX_RECT16* rect16); +int rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32); +int rdpgfx_write_color32(wStream* s, RDPGFX_COLOR32* color32); +int rdpgfx_read_header(wStream* s, RDPGFX_HEADER* header); +int rdpgfx_write_header(wStream* s, RDPGFX_HEADER* header); #endif /* FREERDP_CHANNEL_RDPGFX_CLIENT_COMMON_H */ diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index 889da5f..8c6d52b 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -80,6 +81,8 @@ static int rdpgfx_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, int status = 0; RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback; + fprintf(stderr, "RdpGfxOnDataReceived\n"); + s = Stream_New(pBuffer, cbSize); status = rdpgfx_recv_pdu(callback, s); @@ -117,6 +120,8 @@ static int rdpgfx_on_new_channel_connection(IWTSListenerCallback* pListenerCallb *ppCallback = (IWTSVirtualChannelCallback*) callback; + fprintf(stderr, "RdpGfxOnNewChannelConnection\n"); + return 0; } @@ -137,6 +142,8 @@ static int rdpgfx_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag rdpgfx->listener->pInterface = rdpgfx->iface.pInterface; + fprintf(stderr, "RdpGfxInitialize\n"); + return status; } @@ -191,6 +198,8 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) rdpgfx->iface.pInterface = (void*) context; + fprintf(stderr, "RdpGfxDVCPluginEntry\n"); + error = pEntryPoints->RegisterPlugin(pEntryPoints, "rdpgfx", (IWTSPlugin*) rdpgfx); } diff --git a/client/common/cmdline.c b/client/common/cmdline.c index b9f56a7..735a647 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -102,6 +102,7 @@ COMMAND_LINE_ARGUMENT_A args[] = { "themes", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Themes" }, { "wallpaper", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Wallpaper" }, { "gdi", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "GDI rendering" }, + { "gfx", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "RDP8 graphics pipeline (experimental)" }, { "rfx", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "RemoteFX" }, { "rfx-mode", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "RemoteFX mode" }, { "frame-ack", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Frame acknowledgement" }, @@ -1466,6 +1467,10 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, else if (strcmp(arg->Value, "hw") == 0) settings->SoftwareGdi = FALSE; } + CommandLineSwitchCase(arg, "gfx") + { + settings->SupportGraphicsPipeline = TRUE; + } CommandLineSwitchCase(arg, "rfx") { settings->RemoteFxCodec = TRUE; @@ -1819,6 +1824,17 @@ int freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings) freerdp_client_load_static_channel_addin(channels, settings, "rail", settings); } + if (settings->SupportGraphicsPipeline) + { + char* p[1]; + int count; + + count = 1; + p[0] = "rdpgfx"; + + freerdp_client_add_dynamic_channel(settings, count, p); + } + if (settings->DynamicChannelCount) { freerdp_client_load_static_channel_addin(channels, settings, "drdynvc", settings); diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index 406a318..7092753 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -94,6 +94,7 @@ #define RNS_UD_CS_SUPPORT_NETWORK_AUTODETECT 0x0080 #define RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL 0x0100 #define RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE 0x0200 +#define RNS_UD_CS_SUPPORT_HEARTBEAT_PDU 0x0400 /* Early Capability Flags (Server to Client) */ #define RNS_UD_SC_EDGE_ACTIONS_SUPPORTED 0x00000001 diff --git a/libfreerdp/core/gcc.c b/libfreerdp/core/gcc.c index 316f4f9..ee039a9 100644 --- a/libfreerdp/core/gcc.c +++ b/libfreerdp/core/gcc.c @@ -727,6 +727,15 @@ void gcc_write_client_core_data(wStream* s, rdpSettings* settings) earlyCapabilityFlags |= RNS_UD_CS_WANT_32BPP_SESSION; } + if (settings->NetworkAutoDetect) + earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_NETWORK_AUTODETECT; + + if (settings->SupportGraphicsPipeline) + earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL; + + if (settings->SupportDynamicTimeZone) + earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE; + Stream_Write_UINT16(s, highColorDepth); /* highColorDepth */ Stream_Write_UINT16(s, supportedColorDepths); /* supportedColorDepths */ diff --git a/libfreerdp/core/nego.c b/libfreerdp/core/nego.c index 2e97d05..13afb11 100644 --- a/libfreerdp/core/nego.c +++ b/libfreerdp/core/nego.c @@ -833,6 +833,7 @@ BOOL nego_send_negotiation_response(rdpNego* nego) int bm, em; BOOL status; wStream* s; + BYTE flags; rdpSettings* settings; status = TRUE; @@ -846,17 +847,24 @@ BOOL nego_send_negotiation_response(rdpNego* nego) if (nego->selected_protocol > PROTOCOL_RDP) { + flags = EXTENDED_CLIENT_DATA_SUPPORTED; + + if (settings->SupportGraphicsPipeline) + flags |= DYNVC_GFX_PROTOCOL_SUPPORTED; + /* RDP_NEG_DATA must be present for TLS and NLA */ Stream_Write_UINT8(s, TYPE_RDP_NEG_RSP); - Stream_Write_UINT8(s, EXTENDED_CLIENT_DATA_SUPPORTED); /* flags */ + Stream_Write_UINT8(s, flags); /* flags */ Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */ Stream_Write_UINT32(s, nego->selected_protocol); /* selectedProtocol */ length += 8; } else if (!settings->RdpSecurity) { + flags = 0; + Stream_Write_UINT8(s, TYPE_RDP_NEG_FAILURE); - Stream_Write_UINT8(s, 0); /* flags */ + Stream_Write_UINT8(s, flags); /* flags */ Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */ /* * TODO: Check for other possibilities, diff --git a/libfreerdp/core/nego.h b/libfreerdp/core/nego.h index e8f429f..7d3e08b 100644 --- a/libfreerdp/core/nego.h +++ b/libfreerdp/core/nego.h @@ -76,6 +76,7 @@ enum RDP_NEG_MSG #define EXTENDED_CLIENT_DATA_SUPPORTED 0x01 #define DYNVC_GFX_PROTOCOL_SUPPORTED 0x02 #define RDP_NEGRSP_RESERVED 0x04 +#define RESTRICTED_ADMIN_MODE_SUPPORTED 0x08 #define PRECONNECTION_PDU_V1_SIZE 16 #define PRECONNECTION_PDU_V2_MIN_SIZE (PRECONNECTION_PDU_V1_SIZE + 2) -- 2.7.4