From a5b62aa82e8df185ff5a02e4ae350e4268f90eaa Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 25 Mar 2017 19:59:04 -0700 Subject: [PATCH 001/109] GUACAMOLE-249: Migrate to newer API (partial). --- configure.ac | 6 +-- src/protocols/rdp/Makefile.am | 66 +++++++++++++------------- src/protocols/rdp/guac_ai/ai_service.c | 10 ++-- src/protocols/rdp/rdp.c | 2 + src/protocols/rdp/rdp.h | 2 + src/protocols/rdp/rdp_bitmap.c | 20 +++++--- src/protocols/rdp/rdp_bitmap.h | 14 +++--- src/protocols/rdp/rdp_gdi.c | 6 ++- src/protocols/rdp/rdp_glyph.c | 21 +++++--- src/protocols/rdp/rdp_glyph.h | 14 +++--- src/protocols/rdp/rdp_pointer.c | 6 ++- src/protocols/rdp/rdp_pointer.h | 4 +- src/protocols/rdp/rdp_stream.h | 4 ++ src/protocols/rdp/user.c | 6 +++ 14 files changed, 108 insertions(+), 73 deletions(-) diff --git a/configure.ac b/configure.ac index e1950efd..afc8fdca 100644 --- a/configure.ac +++ b/configure.ac @@ -554,11 +554,11 @@ then # libfreerdp-core / libfreerdp AC_CHECK_LIB([freerdp-core], [freerdp_new], [RDP_LIBS="$RDP_LIBS -lfreerdp-core"], - [AC_CHECK_LIB([freerdp], [freerdp_new], - [RDP_LIBS="$RDP_LIBS -lfreerdp -lfreerdp-client"], + [AC_CHECK_LIB([freerdp2], [freerdp_new], + [RDP_LIBS="$RDP_LIBS -lfreerdp2 -lfreerdp-client2"], [AC_MSG_WARN([ -------------------------------------------- - Unable to find libfreerdp-core / libfreerdp + Unable to find libfreerdp2 RDP will be disabled. --------------------------------------------]) have_freerdp=no])]) diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index 1ba406c6..6c08da56 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -55,7 +55,6 @@ libguac_client_rdp_la_SOURCES = \ rdp_rail.c \ rdp_settings.c \ rdp_stream.c \ - rdp_svc.c \ resolution.c \ unicode.c \ user.c @@ -127,7 +126,6 @@ noinst_HEADERS = \ rdp_settings.h \ rdp_status.h \ rdp_stream.h \ - rdp_svc.h \ resolution.h \ unicode.h \ user.h @@ -283,59 +281,59 @@ if LEGACY_FREERDP_EXTENSIONS # FreeRDP 1.0-style extensions freerdp_LTLIBRARIES = \ - guacai.la \ - guacdr.la \ - guacsnd.la \ - guacsvc.la + guacai.la +# guacdr.la \ +# guacsnd.la \ +# guacsvc.la guacai_la_SOURCES = ${guacai_sources} guacai_la_CFLAGS = ${guacai_cflags} guacai_la_LDFLAGS = ${guacai_ldflags} guacai_la_LIBADD = ${guacai_libadd} -guacdr_la_SOURCES = ${guacdr_sources} -guacdr_la_CFLAGS = ${guacdr_cflags} -guacdr_la_LDFLAGS = ${guacdr_ldflags} -guacdr_la_LIBADD = ${guacdr_libadd} +#guacdr_la_SOURCES = ${guacdr_sources} +#guacdr_la_CFLAGS = ${guacdr_cflags} +#guacdr_la_LDFLAGS = ${guacdr_ldflags} +#guacdr_la_LIBADD = ${guacdr_libadd} -guacsnd_la_SOURCES = ${guacsnd_sources} -guacsnd_la_CFLAGS = ${guacsnd_cflags} -guacsnd_la_LDFLAGS = ${guacsnd_ldflags} -guacsnd_la_LIBADD = ${guacsnd_libadd} +#guacsnd_la_SOURCES = ${guacsnd_sources} +#guacsnd_la_CFLAGS = ${guacsnd_cflags} +#guacsnd_la_LDFLAGS = ${guacsnd_ldflags} +#guacsnd_la_LIBADD = ${guacsnd_libadd} -guacsvc_la_SOURCES = ${guacsvc_sources} -guacsvc_la_CFLAGS = ${guacsvc_cflags} -guacsvc_la_LDFLAGS = ${guacsvc_ldflags} -guacsvc_la_LIBADD = ${guacsvc_libadd} +#guacsvc_la_SOURCES = ${guacsvc_sources} +#guacsvc_la_CFLAGS = ${guacsvc_cflags} +#guacsvc_la_LDFLAGS = ${guacsvc_ldflags} +#guacsvc_la_LIBADD = ${guacsvc_libadd} else # FreeRDP 1.1 (and hopefully onward) extensions freerdp_LTLIBRARIES = \ - guacai-client.la \ - guacdr-client.la \ - guacsnd-client.la \ - guacsvc-client.la + guacai-client.la +# guacdr-client.la \ +# guacsnd-client.la \ +# guacsvc-client.la guacai_client_la_SOURCES = ${guacai_sources} guacai_client_la_CFLAGS = ${guacai_cflags} guacai_client_la_LDFLAGS = ${guacai_ldflags} guacai_client_la_LIBADD = ${guacai_libadd} -guacdr_client_la_SOURCES = ${guacdr_sources} -guacdr_client_la_CFLAGS = ${guacdr_cflags} -guacdr_client_la_LDFLAGS = ${guacdr_ldflags} -guacdr_client_la_LIBADD = ${guacdr_libadd} +#guacdr_client_la_SOURCES = ${guacdr_sources} +#guacdr_client_la_CFLAGS = ${guacdr_cflags} +#guacdr_client_la_LDFLAGS = ${guacdr_ldflags} +#guacdr_client_la_LIBADD = ${guacdr_libadd} -guacsnd_client_la_SOURCES = ${guacsnd_sources} -guacsnd_client_la_CFLAGS = ${guacsnd_cflags} -guacsnd_client_la_LDFLAGS = ${guacsnd_ldflags} -guacsnd_client_la_LIBADD = ${guacsnd_libadd} +#guacsnd_client_la_SOURCES = ${guacsnd_sources} +#guacsnd_client_la_CFLAGS = ${guacsnd_cflags} +#guacsnd_client_la_LDFLAGS = ${guacsnd_ldflags} +#guacsnd_client_la_LIBADD = ${guacsnd_libadd} -guacsvc_client_la_SOURCES = ${guacsvc_sources} -guacsvc_client_la_CFLAGS = ${guacsvc_cflags} -guacsvc_client_la_LDFLAGS = ${guacsvc_ldflags} -guacsvc_client_la_LIBADD = ${guacsvc_libadd} +#guacsvc_client_la_SOURCES = ${guacsvc_sources} +#guacsvc_client_la_CFLAGS = ${guacsvc_cflags} +#guacsvc_client_la_LDFLAGS = ${guacsvc_ldflags} +#guacsvc_client_la_LIBADD = ${guacsvc_libadd} endif diff --git a/src/protocols/rdp/guac_ai/ai_service.c b/src/protocols/rdp/guac_ai/ai_service.c index 5058ea0a..72b43d89 100644 --- a/src/protocols/rdp/guac_ai/ai_service.c +++ b/src/protocols/rdp/guac_ai/ai_service.c @@ -143,7 +143,7 @@ static int guac_rdp_ai_data(IWTSVirtualChannelCallback* channel_callback, * @return * Always zero. */ -static int guac_rdp_ai_data(IWTSVirtualChannelCallback* channel_callback, +static UINT guac_rdp_ai_data(IWTSVirtualChannelCallback* channel_callback, wStream* stream) { guac_rdp_ai_channel_callback* ai_channel_callback = @@ -169,7 +169,7 @@ static int guac_rdp_ai_data(IWTSVirtualChannelCallback* channel_callback, * @return * Always zero. */ -static int guac_rdp_ai_close(IWTSVirtualChannelCallback* channel_callback) { +static UINT guac_rdp_ai_close(IWTSVirtualChannelCallback* channel_callback) { guac_rdp_ai_channel_callback* ai_channel_callback = (guac_rdp_ai_channel_callback*) channel_callback; @@ -219,7 +219,7 @@ static int guac_rdp_ai_close(IWTSVirtualChannelCallback* channel_callback) { * @return * Always zero. */ -static int guac_rdp_ai_new_connection( +static UINT guac_rdp_ai_new_connection( IWTSListenerCallback* listener_callback, IWTSVirtualChannel* channel, BYTE* data, int* accept, IWTSVirtualChannelCallback** channel_callback) { @@ -261,7 +261,7 @@ static int guac_rdp_ai_new_connection( * @return * Always zero. */ -static int guac_rdp_ai_initialize(IWTSPlugin* plugin, +static UINT guac_rdp_ai_initialize(IWTSPlugin* plugin, IWTSVirtualChannelManager* manager) { /* Allocate new listener callback */ @@ -295,7 +295,7 @@ static int guac_rdp_ai_initialize(IWTSPlugin* plugin, * @return * Always zero. */ -static int guac_rdp_ai_terminated(IWTSPlugin* plugin) { +static UINT guac_rdp_ai_terminated(IWTSPlugin* plugin) { guac_rdp_ai_plugin* ai_plugin = (guac_rdp_ai_plugin*) plugin; guac_client* client = ai_plugin->client; diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 86f50967..922febe1 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -38,7 +38,9 @@ #include "rdp_pointer.h" #include "rdp_rail.h" #include "rdp_stream.h" +#if 0 #include "rdp_svc.h" +#endif #ifdef ENABLE_COMMON_SSH #include "common-ssh/sftp.h" diff --git a/src/protocols/rdp/rdp.h b/src/protocols/rdp/rdp.h index 1d2eb110..ec0f939d 100644 --- a/src/protocols/rdp/rdp.h +++ b/src/protocols/rdp/rdp.h @@ -191,10 +191,12 @@ typedef struct rdp_freerdp_context { */ guac_client* client; +#if 0 /** * Color conversion structure to be used to convert RDP images to PNGs. */ CLRCONV* clrconv; +#endif /** * The current color palette, as received from the RDP server. diff --git a/src/protocols/rdp/rdp_bitmap.c b/src/protocols/rdp/rdp_bitmap.c index f77bbaea..659c72b0 100644 --- a/src/protocols/rdp/rdp_bitmap.c +++ b/src/protocols/rdp/rdp_bitmap.c @@ -42,7 +42,7 @@ #include #include -void guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap) { +BOOL guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; @@ -70,9 +70,11 @@ void guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap) { /* Store buffer reference in bitmap */ ((guac_rdp_bitmap*) bitmap)->layer = buffer; + return TRUE; + } -void guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap) { +BOOL guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap) { /* Convert image data if present */ if (bitmap->data != NULL && bitmap->bpp != 32) { @@ -103,9 +105,11 @@ void guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap) { /* Start at zero usage */ ((guac_rdp_bitmap*) bitmap)->used = 0; + return TRUE; + } -void guac_rdp_bitmap_paint(rdpContext* context, rdpBitmap* bitmap) { +BOOL guac_rdp_bitmap_paint(rdpContext* context, rdpBitmap* bitmap) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; @@ -145,6 +149,8 @@ void guac_rdp_bitmap_paint(rdpContext* context, rdpBitmap* bitmap) { /* Increment usage counter */ ((guac_rdp_bitmap*) bitmap)->used++; + return TRUE; + } void guac_rdp_bitmap_free(rdpContext* context, rdpBitmap* bitmap) { @@ -159,7 +165,7 @@ void guac_rdp_bitmap_free(rdpContext* context, rdpBitmap* bitmap) { } -void guac_rdp_bitmap_setsurface(rdpContext* context, rdpBitmap* bitmap, BOOL primary) { +BOOL guac_rdp_bitmap_setsurface(rdpContext* context, rdpBitmap* bitmap, BOOL primary) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; @@ -184,14 +190,16 @@ void guac_rdp_bitmap_setsurface(rdpContext* context, rdpBitmap* bitmap, BOOL pri } + return TRUE; + } #ifdef LEGACY_RDPBITMAP void guac_rdp_bitmap_decompress(rdpContext* context, rdpBitmap* bitmap, UINT8* data, int width, int height, int bpp, int length, BOOL compressed) { #else -void guac_rdp_bitmap_decompress(rdpContext* context, rdpBitmap* bitmap, UINT8* data, - int width, int height, int bpp, int length, BOOL compressed, int codec_id) { +BOOL guac_rdp_bitmap_decompress(rdpContext* context, rdpBitmap* bitmap, const BYTE* data, + UINT32 width, UINT32 height, UINT32 bpp, UINT32 length, BOOL compressed, UINT32 codec_id) { #endif int size = width * height * 4; diff --git a/src/protocols/rdp/rdp_bitmap.h b/src/protocols/rdp/rdp_bitmap.h index dda3f763..e2aaa120 100644 --- a/src/protocols/rdp/rdp_bitmap.h +++ b/src/protocols/rdp/rdp_bitmap.h @@ -67,7 +67,7 @@ typedef struct guac_rdp_bitmap { * @param bitmap * The bitmap to cache. */ -void guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap); +BOOL guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap); /** * Initializes the given newly-created rdpBitmap. @@ -78,7 +78,7 @@ void guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap); * @param bitmap * The bitmap to initialize. */ -void guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap); +BOOL guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap); /** * Paints the given rdpBitmap on the primary display surface. Note that this @@ -93,7 +93,7 @@ void guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap); * the paint operation to perform, including the destination X/Y * coordinates. */ -void guac_rdp_bitmap_paint(rdpContext* context, rdpBitmap* bitmap); +BOOL guac_rdp_bitmap_paint(rdpContext* context, rdpBitmap* bitmap); /** * Frees any Guacamole-specific data associated with the given rdpBitmap. @@ -123,7 +123,7 @@ void guac_rdp_bitmap_free(rdpContext* context, rdpBitmap* bitmap); * surface should be reset to the primary drawing surface of the remote * display, FALSE otherwise. */ -void guac_rdp_bitmap_setsurface(rdpContext* context, rdpBitmap* bitmap, +BOOL guac_rdp_bitmap_setsurface(rdpContext* context, rdpBitmap* bitmap, BOOL primary); #ifdef LEGACY_RDPBITMAP @@ -195,9 +195,9 @@ void guac_rdp_bitmap_decompress(rdpContext* context, rdpBitmap* bitmap, * The ID of the codec used to compress the image data. This parameter is * currently ignored. */ -void guac_rdp_bitmap_decompress(rdpContext* context, rdpBitmap* bitmap, - UINT8* data, int width, int height, int bpp, int length, - BOOL compressed, int codec_id); +BOOL guac_rdp_bitmap_decompress(rdpContext* context, rdpBitmap* bitmap, + const BYTE* data, UINT32 width, UINT32 height, UINT32 bpp, UINT32 length, + BOOL compressed, UINT32 codec_id); #endif #endif diff --git a/src/protocols/rdp/rdp_gdi.c b/src/protocols/rdp/rdp_gdi.c index 59fe64cd..703dd32a 100644 --- a/src/protocols/rdp/rdp_gdi.c +++ b/src/protocols/rdp/rdp_gdi.c @@ -345,6 +345,7 @@ void guac_rdp_gdi_opaquerect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect } +#if 0 /** * Updates the palette within a FreeRDP CLRCONV object using the new palette * entries provided by an RDP palette update. @@ -368,6 +369,7 @@ static void guac_rdp_update_clrconv(CLRCONV* clrconv, #endif } +#endif /** * Updates a raw ARGB32 palette using the new palette entries provided by an @@ -402,14 +404,14 @@ static void guac_rdp_update_palette(UINT32* guac_palette, } void guac_rdp_gdi_palette_update(rdpContext* context, PALETTE_UPDATE* palette) { - +#if 0 CLRCONV* clrconv = ((rdp_freerdp_context*) context)->clrconv; UINT32* guac_palette = ((rdp_freerdp_context*) context)->palette; /* Update internal palette representations */ guac_rdp_update_clrconv(clrconv, palette); guac_rdp_update_palette(guac_palette, palette); - +#endif } void guac_rdp_gdi_set_bounds(rdpContext* context, rdpBounds* bounds) { diff --git a/src/protocols/rdp/rdp_glyph.c b/src/protocols/rdp/rdp_glyph.c index 8ba1087b..ee8a211a 100644 --- a/src/protocols/rdp/rdp_glyph.c +++ b/src/protocols/rdp/rdp_glyph.c @@ -44,7 +44,7 @@ #define cairo_format_stride_for_width(format, width) (width*4) #endif -void guac_rdp_glyph_new(rdpContext* context, rdpGlyph* glyph) { +BOOL guac_rdp_glyph_new(rdpContext* context, const rdpGlyph* glyph) { int x, y, i; int stride; @@ -95,9 +95,13 @@ void guac_rdp_glyph_new(rdpContext* context, rdpGlyph* glyph) { ((guac_rdp_glyph*) glyph)->surface = cairo_image_surface_create_for_data( image_buffer, CAIRO_FORMAT_ARGB32, width, height, stride); + return TRUE; + } -void guac_rdp_glyph_draw(rdpContext* context, rdpGlyph* glyph, int x, int y) { +BOOL guac_rdp_glyph_draw(rdpContext* context, const rdpGlyph* glyph, + UINT32 x, UINT32 y, UINT32 w, UINT32 h, UINT32 sx, UINT32 sy, + BOOL redundant); guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; @@ -110,6 +114,8 @@ void guac_rdp_glyph_draw(rdpContext* context, rdpGlyph* glyph, int x, int y) { (fgcolor & 0x00FF00) >> 8, fgcolor & 0x0000FF); + return TRUE; + } void guac_rdp_glyph_free(rdpContext* context, rdpGlyph* glyph) { @@ -123,8 +129,8 @@ void guac_rdp_glyph_free(rdpContext* context, rdpGlyph* glyph) { } -void guac_rdp_glyph_begindraw(rdpContext* context, - int x, int y, int width, int height, UINT32 fgcolor, UINT32 bgcolor) { +BOOL guac_rdp_glyph_begindraw(rdpContext* context, + UINT32 x, UINT32 y, UINT32 width, UINT32 height, UINT32 fgcolor, UINT32 bgcolor, BOOL redundant) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = @@ -148,10 +154,13 @@ void guac_rdp_glyph_begindraw(rdpContext* context, /* Convert foreground color */ rdp_client->glyph_color = guac_rdp_convert_color(context, fgcolor); + return TRUE; + } -void guac_rdp_glyph_enddraw(rdpContext* context, - int x, int y, int width, int height, UINT32 fgcolor, UINT32 bgcolor) { +BOOL guac_rdp_glyph_enddraw(rdpContext* context, + UINT32 x, UINT32 y, UINT32 width, UINT32 height, UINT32 fgcolor, UINT32 bgcolor) { /* IGNORE */ + return TRUE; } diff --git a/src/protocols/rdp/rdp_glyph.h b/src/protocols/rdp/rdp_glyph.h index 0fe0eeff..0c8b747b 100644 --- a/src/protocols/rdp/rdp_glyph.h +++ b/src/protocols/rdp/rdp_glyph.h @@ -59,7 +59,7 @@ typedef struct guac_rdp_glyph { * @param glyph * The glyph to cache. */ -void guac_rdp_glyph_new(rdpContext* context, rdpGlyph* glyph); +BOOL guac_rdp_glyph_new(rdpContext* context, const rdpGlyph* glyph); /** * Draws a previously-cached glyph at the given coordinates within the current @@ -77,7 +77,9 @@ void guac_rdp_glyph_new(rdpContext* context, rdpGlyph* glyph); * @param y * The destination Y coordinate of the upper-left corner of the glyph. */ -void guac_rdp_glyph_draw(rdpContext* context, rdpGlyph* glyph, int x, int y); +BOOL guac_rdp_glyph_draw(rdpContext* context, const rdpGlyph* glyph, + UINT32 x, UINT32 y, UINT32 w, UINT32 h, UINT32 sx, UINT32 sy, + BOOL redundant); /** * Frees any Guacamole-specific data associated with the given glyph, such that @@ -126,8 +128,8 @@ void guac_rdp_glyph_free(rdpContext* context, rdpGlyph* glyph); * be translated via guac_rdp_convert_color(). If the background is * transparent, this value is undefined. */ -void guac_rdp_glyph_begindraw(rdpContext* context, - int x, int y, int width, int height, UINT32 fgcolor, UINT32 bgcolor); +BOOL guac_rdp_glyph_begindraw(rdpContext* context, + UINT32 x, UINT32 y, UINT32 width, UINT32 height, UINT32 fgcolor, UINT32 bgcolor, BOOL redundant); /** * Called immediately after rendering a series of glyphs. Unlike @@ -163,7 +165,7 @@ void guac_rdp_glyph_begindraw(rdpContext* context, * be translated via guac_rdp_convert_color(). If the background is * transparent, this value is undefined. */ -void guac_rdp_glyph_enddraw(rdpContext* context, - int x, int y, int width, int height, UINT32 fgcolor, UINT32 bgcolor); +BOOL guac_rdp_glyph_enddraw(rdpContext* context, + UINT32 x, UINT32 y, UINT32 width, UINT32 height, UINT32 fgcolor, UINT32 bgcolor); #endif diff --git a/src/protocols/rdp/rdp_pointer.c b/src/protocols/rdp/rdp_pointer.c index f510b578..fae8ed01 100644 --- a/src/protocols/rdp/rdp_pointer.c +++ b/src/protocols/rdp/rdp_pointer.c @@ -93,11 +93,13 @@ void guac_rdp_pointer_free(rdpContext* context, rdpPointer* pointer) { } -void guac_rdp_pointer_set_null(rdpContext* context) { +BOOL guac_rdp_pointer_set_null(rdpContext* context) { /* STUB */ + return TRUE; } -void guac_rdp_pointer_set_default(rdpContext* context) { +BOOL guac_rdp_pointer_set_default(rdpContext* context) { /* STUB */ + return TRUE; } diff --git a/src/protocols/rdp/rdp_pointer.h b/src/protocols/rdp/rdp_pointer.h index 995c8d6f..4ce98777 100644 --- a/src/protocols/rdp/rdp_pointer.h +++ b/src/protocols/rdp/rdp_pointer.h @@ -85,7 +85,7 @@ void guac_rdp_pointer_free(rdpContext* context, rdpPointer* pointer); * @param context * The rdpContext associated with the current RDP session. */ -void guac_rdp_pointer_set_null(rdpContext* context); +BOOL guac_rdp_pointer_set_null(rdpContext* context); /** * Sets the system-dependent (as in dependent on the client system) default @@ -94,6 +94,6 @@ void guac_rdp_pointer_set_null(rdpContext* context); * @param context * The rdpContext associated with the current RDP session. */ -void guac_rdp_pointer_set_default(rdpContext* context); +BOOL guac_rdp_pointer_set_default(rdpContext* context); #endif diff --git a/src/protocols/rdp/rdp_stream.h b/src/protocols/rdp/rdp_stream.h index c9c3838e..427e091f 100644 --- a/src/protocols/rdp/rdp_stream.h +++ b/src/protocols/rdp/rdp_stream.h @@ -23,7 +23,9 @@ #include "config.h" #include "common/json.h" +#if 0 #include "rdp_svc.h" +#endif #include #include @@ -150,10 +152,12 @@ typedef struct guac_rdp_stream { */ guac_rdp_ls_status ls_status; +#if 0 /** * Associated SVC instance. Only valid for GUAC_RDP_INBOUND_SVC_STREAM. */ guac_rdp_svc* svc; +#endif } guac_rdp_stream; diff --git a/src/protocols/rdp/user.c b/src/protocols/rdp/user.c index 6aa71ae9..04238e8c 100644 --- a/src/protocols/rdp/user.c +++ b/src/protocols/rdp/user.c @@ -26,7 +26,9 @@ #include "rdp.h" #include "rdp_settings.h" #include "rdp_stream.h" +#if 0 #include "rdp_svc.h" +#endif #ifdef ENABLE_COMMON_SSH #include "sftp.h" @@ -85,8 +87,10 @@ int guac_rdp_user_join_handler(guac_user* user, int argc, char** argv) { if (rdp_client->audio) guac_audio_stream_add_user(rdp_client->audio, user); +#if 0 /* Bring user up to date with any registered static channels */ guac_rdp_svc_send_pipes(user); +#endif /* Synchronize with current display */ guac_common_display_dup(rdp_client->display, user, user->socket); @@ -108,8 +112,10 @@ int guac_rdp_user_join_handler(guac_user* user, int argc, char** argv) { /* Set generic (non-filesystem) file upload handler */ user->file_handler = guac_rdp_user_file_handler; +#if 0 /* Inbound arbitrary named pipes */ user->pipe_handler = guac_rdp_svc_pipe_handler; +#endif } From 17d31d94b77b3be71012b0bc6fcb1d1c3db88e5f Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 21 Sep 2019 12:25:06 -0700 Subject: [PATCH 002/109] GUACAMOLE-249: Remove all legacy FreeRDP compatibility. --- configure.ac | 505 +----------------- src/protocols/rdp/Makefile.am | 45 -- src/protocols/rdp/client.c | 12 +- src/protocols/rdp/compat/client-cliprdr.h | 35 -- src/protocols/rdp/compat/rail.h | 39 -- src/protocols/rdp/compat/winpr-stream.c | 47 -- src/protocols/rdp/compat/winpr-stream.h | 71 --- src/protocols/rdp/compat/winpr-wtypes.h | 39 -- src/protocols/rdp/dvc.c | 29 - src/protocols/rdp/guac_ai/ai_messages.c | 5 - src/protocols/rdp/guac_ai/ai_messages.h | 5 - src/protocols/rdp/guac_ai/ai_service.c | 47 +- .../rdp/guac_rdpdr/rdpdr_fs_messages.c | 6 - .../rdp/guac_rdpdr/rdpdr_fs_messages.h | 4 - .../guac_rdpdr/rdpdr_fs_messages_dir_info.c | 5 - .../guac_rdpdr/rdpdr_fs_messages_dir_info.h | 4 - .../guac_rdpdr/rdpdr_fs_messages_file_info.c | 6 - .../guac_rdpdr/rdpdr_fs_messages_file_info.h | 4 - .../guac_rdpdr/rdpdr_fs_messages_vol_info.c | 6 - .../guac_rdpdr/rdpdr_fs_messages_vol_info.h | 4 - .../rdp/guac_rdpdr/rdpdr_fs_service.c | 5 - src/protocols/rdp/guac_rdpdr/rdpdr_messages.c | 5 - src/protocols/rdp/guac_rdpdr/rdpdr_messages.h | 4 - src/protocols/rdp/guac_rdpdr/rdpdr_printer.c | 5 - src/protocols/rdp/guac_rdpdr/rdpdr_printer.h | 4 - src/protocols/rdp/guac_rdpdr/rdpdr_service.c | 5 - src/protocols/rdp/guac_rdpdr/rdpdr_service.h | 5 - .../rdp/guac_rdpsnd/rdpsnd_messages.c | 6 - .../rdp/guac_rdpsnd/rdpsnd_messages.h | 4 - .../rdp/guac_rdpsnd/rdpsnd_service.c | 5 - .../rdp/guac_rdpsnd/rdpsnd_service.h | 5 - src/protocols/rdp/guac_svc/svc_service.c | 5 - src/protocols/rdp/guac_svc/svc_service.h | 5 - src/protocols/rdp/keymaps/generate.pl | 5 - src/protocols/rdp/rdp.c | 142 +---- src/protocols/rdp/rdp_bitmap.c | 41 +- src/protocols/rdp/rdp_bitmap.h | 41 -- src/protocols/rdp/rdp_cliprdr.c | 22 +- src/protocols/rdp/rdp_cliprdr.h | 12 +- src/protocols/rdp/rdp_color.c | 23 - src/protocols/rdp/rdp_color.h | 5 - src/protocols/rdp/rdp_disp.c | 13 +- src/protocols/rdp/rdp_disp.h | 9 +- src/protocols/rdp/rdp_fs.h | 12 - src/protocols/rdp/rdp_gdi.c | 9 - src/protocols/rdp/rdp_glyph.c | 5 - src/protocols/rdp/rdp_glyph.h | 5 - src/protocols/rdp/rdp_keymap.h | 4 - src/protocols/rdp/rdp_rail.c | 26 +- src/protocols/rdp/rdp_rail.h | 5 - src/protocols/rdp/rdp_settings.c | 187 ------- src/protocols/rdp/rdp_settings.h | 4 - src/protocols/rdp/rdp_stream.c | 13 +- src/protocols/rdp/rdp_svc.c | 5 - 54 files changed, 28 insertions(+), 1541 deletions(-) delete mode 100644 src/protocols/rdp/compat/client-cliprdr.h delete mode 100644 src/protocols/rdp/compat/rail.h delete mode 100644 src/protocols/rdp/compat/winpr-stream.c delete mode 100644 src/protocols/rdp/compat/winpr-stream.h delete mode 100644 src/protocols/rdp/compat/winpr-wtypes.h diff --git a/configure.ac b/configure.ac index afc8fdca..6635c77e 100644 --- a/configure.ac +++ b/configure.ac @@ -528,10 +528,10 @@ then fi # -# FreeRDP +# FreeRDP 2 # -have_freerdp=disabled +have_freerdp2=disabled RDP_LIBS= AC_ARG_WITH([rdp], [AS_HELP_STRING([--with-rdp], @@ -541,505 +541,20 @@ AC_ARG_WITH([rdp], if test "x$with_rdp" != "xno" then - have_winpr=yes - have_freerdp=yes - legacy_freerdp_extensions=no - rdpsettings_interface=unknown - rdpsettings_audiocapture=yes - rdpsettings_audioplayback=yes - rdpsettings_deviceredirection=yes - freerdp_interface=unknown - event_interface=unknown + have_freerdp2=yes - # libfreerdp-core / libfreerdp - AC_CHECK_LIB([freerdp-core], [freerdp_new], - [RDP_LIBS="$RDP_LIBS -lfreerdp-core"], - [AC_CHECK_LIB([freerdp2], [freerdp_new], - [RDP_LIBS="$RDP_LIBS -lfreerdp2 -lfreerdp-client2"], - [AC_MSG_WARN([ + # libfreerdp2 + AC_CHECK_LIB([freerdp2], [freerdp_new], + [RDP_LIBS="$RDP_LIBS -lfreerdp2 -lfreerdp-client2 -lwinpr2"], + [AC_MSG_WARN([ -------------------------------------------- Unable to find libfreerdp2 RDP will be disabled. --------------------------------------------]) - have_freerdp=no])]) + have_freerdp2=no]) fi - -# libfreerdp-cache -if test "x${have_freerdp}" = "xyes" -then - AC_CHECK_LIB([freerdp-cache], [glyph_cache_register_callbacks], - [RDP_LIBS="$RDP_LIBS -lfreerdp-cache"]) -fi - -# libfreerdp-channels (1.0) / libfreerdp-client + libfreerdp-core (1.1) -if test "x${have_freerdp}" = "xyes" -then - AC_CHECK_LIB([freerdp-client], [freerdp_channels_new], - [RDP_LIBS="$RDP_LIBS -lfreerdp-client"], - [AC_CHECK_LIB([freerdp-channels], [freerdp_channels_new], - [RDP_LIBS="$RDP_LIBS -lfreerdp-channels" - legacy_freerdp_extensions=yes])], - [-lfreerdp-core]) -fi - -# libfreerdp-utils -if test "x${have_freerdp}" = "xyes" -then - AC_CHECK_LIB([freerdp-utils], [svc_plugin_init], - [RDP_LIBS="$RDP_LIBS -lfreerdp-utils"]) -fi - -# libfreerdp-codec -if test "x${have_freerdp}" = "xyes" -then - AC_CHECK_LIB([freerdp-codec], [freerdp_image_convert], - [RDP_LIBS="$RDP_LIBS -lfreerdp-codec"]) -fi - -# Available color conversion functions -if test "x${have_freerdp}" = "xyes" -then - AC_CHECK_DECL([freerdp_convert_gdi_order_color], - [AC_DEFINE([HAVE_FREERDP_CONVERT_GDI_ORDER_COLOR],, - [Whether freerdp_convert_gdi_order_color() is defined])],, - [#include ]) - - AC_CHECK_DECL([freerdp_color_convert_drawing_order_color_to_gdi_color], - [AC_DEFINE([HAVE_FREERDP_COLOR_CONVERT_DRAWING_ORDER_COLOR_TO_GDI_COLOR],, - [Whether freerdp_color_convert_drawing_order_color_to_gdi_color() is defined])],, - [#include ]) -fi - -# Check for interval polling in plugins -if test "x${have_freerdp}" = "xyes" -then - AC_CHECK_MEMBERS([rdpSvcPlugin.interval_ms],,, - [[#include ]]) -fi - -# Keyboard layout header -if test "x${have_freerdp}" = "xyes" -then - AC_CHECK_HEADERS([freerdp/locale/keyboard.h],, - [AC_CHECK_HEADERS([freerdp/kbd/layouts.h],, - [AC_MSG_WARN([ - -------------------------------------------- - Unable to find keyboard layout headers - RDP will be disabled. - --------------------------------------------]) - have_freerdp=no])]) -fi - -# New headers defining addins -if test "x${have_freerdp}" = "xyes" -then - AC_CHECK_HEADERS([freerdp/addin.h freerdp/client/channels.h]) -fi - -# Header defining cliprdr -if test "x${have_freerdp}" = "xyes" -then - AC_CHECK_HEADERS([freerdp/client/cliprdr.h],, - [AC_CHECK_HEADERS([freerdp/plugins/cliprdr.h],, - [AC_MSG_WARN([ - -------------------------------------------- - Unable to find cliprdr headers - RDP will be disabled. - --------------------------------------------]) - have_freerdp=no], - [#include ])], - [#include - #include ]) -fi - -# Header defining display update channel -if test "x${have_freerdp}" = "xyes" -then - AC_CHECK_HEADERS([freerdp/client/disp.h], - [AC_DEFINE([HAVE_FREERDP_DISPLAY_UPDATE_SUPPORT],, - [Whether FreeRDP supports the display update channel])] - [AC_CHECK_MEMBERS([rdpSettings.SupportDisplayControl],,, - [[#include ]])],, - [#include - #include ]) -fi - -# Support for RDP gateways -if test "x${have_freerdp}" = "xyes" -then - AC_CHECK_MEMBERS([rdpSettings.GatewayEnabled], - [AC_DEFINE([HAVE_FREERDP_GATEWAY_SUPPORT],, - [Whether FreeRDP supports RDP gateways])],, - [[#include ]]) -fi - -# Support for load balancing via connection brokers -if test "x${have_freerdp}" = "xyes" -then - AC_CHECK_MEMBERS([rdpSettings.LoadBalanceInfo], - [AC_DEFINE([HAVE_FREERDP_LOAD_BALANCER_SUPPORT],, - [Whether FreeRDP supports load balancers])],, - [[#include ]]) -fi - -# Support for "PubSub" event system -if test "x${have_freerdp}" = "xyes" -then - AC_CHECK_DECL([PubSub_SubscribeChannelConnected], - [AC_DEFINE([HAVE_FREERDP_EVENT_PUBSUB],, - [Whether this version of FreeRDP provides the PubSub event system])],, - [#include ]) -fi - -# Addin registration variations -if test "x${have_freerdp}" = "xyes" -then - AC_CHECK_DECL([freerdp_register_addin_provider], - [AC_DEFINE([HAVE_FREERDP_REGISTER_ADDIN_PROVIDER],, - [Whether freerdp_register_addin_provider() is defined])],, - [#include ]) - - AC_CHECK_DECL([freerdp_channels_global_init], - [AC_DEFINE([HAVE_FREERDP_CHANNELS_GLOBAL_INIT],, - [Whether freerdp_channels_global_init() is defined])],, - [#include ]) -fi - -# Availability of ADDIN_ARGV structure for configuring plugins -if test "x${have_freerdp}" = "xyes" -then - AC_CHECK_TYPE([ADDIN_ARGV], - [AC_DEFINE([HAVE_ADDIN_ARGV],, - [Whether the ADDIN_ARGV type is available])],, - [#include ]) -fi - -# -# FreeRDP: WinPR -# - -# Check for stream support via WinPR -if test "x${have_freerdp}" = "xyes" -then - AC_CHECK_HEADER(winpr/stream.h,, - [have_winpr=no, - AC_CHECK_DECL([stream_write_uint8],, - [AC_MSG_WARN([ - -------------------------------------------- - Unable to find stream support - RDP will be disabled. - --------------------------------------------]) - have_freerdp=no], - [#include ])]) -fi - -# Check for types in WinPR -if test "x${have_freerdp}" = "xyes" -then - AC_CHECK_HEADER(winpr/wtypes.h,, - [have_winpr=no, - AC_CHECK_HEADER(freerdp/types.h,, - [AC_MSG_WARN([ - -------------------------------------------- - Unable to find type definitions - RDP will be disabled. - --------------------------------------------]) - have_freerdp=no])]) -fi - -if test "x${have_freerdp}" = "xyes" -a "x${have_winpr}" = "xyes" -then - AC_DEFINE([ENABLE_WINPR],, - [Whether library support for WinPR types was found]) -fi - -# -# FreeRDP: freerdp -# - -if test "x${have_freerdp}" = "xyes" -then - # Check for current (as of 1.1) freerdp interface - AC_CHECK_MEMBERS([freerdp.ContextSize], - [freerdp_interface=stable],, - [[#include ]]) - - # If not current, check for legacy interface - if test "x${freerdp_interface}" = "xunknown" - then - AC_CHECK_MEMBERS([freerdp.context_size], - [freerdp_interface=legacy],, - [[#include ]]) - fi - - # Set defines based on interface type, warn if unknown - if test "x${freerdp_interface}" = "xlegacy"; then - AC_DEFINE([LEGACY_FREERDP],, - [Whether the older version of the FreeRDP API was found]) - elif test "x${freerdp_interface}" = "xunknown"; then - AC_MSG_WARN([ - -------------------------------------------- - Unknown FreeRDP interface - RDP will be disabled. - --------------------------------------------]) - have_freerdp=no - fi -fi - -# -# FreeRDP: rdpSettings -# - -if test "x${have_freerdp}" = "xyes" -then - # Check for current (as of 1.1) rdpSettings interface - AC_CHECK_MEMBERS([rdpSettings.Width, - rdpSettings.Height, - rdpSettings.FastPathInput, - rdpSettings.FastPathOutput, - rdpSettings.SendPreconnectionPdu, - rdpSettings.OrderSupport], - [rdpsettings_interface=stable],, - [[#include ]]) - - # If not current, check for legacy interface - if test "x${rdpsettings_interface}" = "xunknown" - then - AC_CHECK_MEMBERS([rdpSettings.width, - rdpSettings.height, - rdpSettings.order_support], - [rdpsettings_interface=legacy],, - [[#include ]]) - fi - - # Set defines based on interface type, warn if unknown - if test "x${rdpsettings_interface}" = "xlegacy"; then - AC_DEFINE([LEGACY_RDPSETTINGS],, - [Whether the legacy version of the rdpSettings API was found]) - - # Legacy interface may not have AudioPlayback settings - AC_CHECK_MEMBERS([rdpSettings.audio_playback],, - [rdpsettings_audioplayback=no], - [[#include ]]) - - # Legacy interface may not have AudioCapture settings - AC_CHECK_MEMBERS([rdpSettings.audio_capture],, - [rdpsettings_audiocapture=no], - [[#include ]]) - - # Legacy interface may not have DeviceRedirection settings - AC_CHECK_MEMBERS([rdpSettings.device_redirection],, - [rdpsettings_deviceredirection=no], - [[#include ]]) - - elif test "x${rdpsettings_interface}" = "xunknown"; then - AC_MSG_WARN([ - -------------------------------------------- - Unknown rdpSettings interface - RDP will be disabled. - --------------------------------------------]) - have_freerdp=no - fi -fi - -# Activate audio playback settings if present -if test "x${have_freerdp}" = "xyes" -a "x${rdpsettings_audioplayback}" = "xyes"; then - AC_DEFINE([HAVE_RDPSETTINGS_AUDIOPLAYBACK],, - [Whether the rdpSettings structure has AudioPlayback settings]) -fi - -# Activate audio capture settings if present -if test "x${have_freerdp}" = "xyes" -a "x${rdpsettings_audiocapture}" = "xyes"; then - AC_DEFINE([HAVE_RDPSETTINGS_AUDIOCAPTURE],, - [Whether the rdpSettings structure has AudioCapture settings]) -fi - -# Activate device redirection settings if present -if test "x${have_freerdp}" = "xyes" -a "x${rdpsettings_deviceredirection}" = "xyes"; then - AC_DEFINE([HAVE_RDPSETTINGS_DEVICEREDIRECTION],, - [Whether the rdpSettings structure has DeviceRedirection settings]) -fi - -# Check if the type CHANNEL_ENTRY_POINTS_FREERDP exists, if not define it to CHANNEL_ENTRY_POINTS_EX -if test "x${have_freerdp}" = "xyes" -then - AC_CHECK_TYPE([CHANNEL_ENTRY_POINTS_FREERDP],, - AC_DEFINE([CHANNEL_ENTRY_POINTS_FREERDP],[CHANNEL_ENTRY_POINTS_EX], [Type compatibility]), - [[#include ]]) -fi - -# Check if the freerdp version header exists -if test "x${have_freerdp}" = "xyes" -then - AC_CHECK_HEADERS([freerdp/version.h]) -fi - -# -# FreeRDP: rdpBitmap -# - -if test "x${have_freerdp}" = "xyes" -then - AC_MSG_CHECKING([whether rdpBitmap.Decompress() requires the codec_id]) - AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include - #include - void __decompress(rdpContext* context, - rdpBitmap* bitmap, - UINT8* data, - int width, - int height, - int bpp, - int length, - BOOL compressed, - int codec_id); - rdpBitmap b = { .Decompress = __decompress };]])], - [AC_MSG_RESULT([yes])], - [AC_MSG_RESULT([no]) - AC_DEFINE([LEGACY_RDPBITMAP],, - [Whether the legacy rdpBitmap API was found])]) -fi - -# -# FreeRDP: IWTSVirtualChannelCallback -# - -if test "x${have_freerdp}" = "xyes" -then - AC_MSG_CHECKING([whether IWTSVirtualChannelCallback.OnDataReceived() uses a wStream]) - AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include - #include - #include - int __data_received( - IWTSVirtualChannelCallback* channel_callback, - wStream* stream); - IWTSVirtualChannelCallback cb = { - .OnDataReceived = __data_received - }; - int main() { - return - cb.OnDataReceived(NULL, NULL); - }]])], - [AC_MSG_RESULT([yes])], - [AC_MSG_RESULT([no]) - AC_DEFINE([LEGACY_IWTSVIRTUALCHANNELCALLBACK],, - [Whether the legacy IWTSVirtualChannelCallback API was found])]) -fi - -# -# FreeRDP: Decompression function variants -# - -# Check whether interleaved_decompress() can handle the palette -if test "x${have_freerdp}" = "xyes" -then - AC_MSG_CHECKING([whether interleaved_decompress() accepts an additional palette parameter]) - AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include - - int main() { - BYTE* palette = NULL; - interleaved_decompress(NULL, NULL, 0, 0, NULL, 0, 0, 0, 0, 0, 0, palette); - }]])], - [AC_MSG_RESULT([yes]) - AC_DEFINE([INTERLEAVED_DECOMPRESS_TAKES_PALETTE],, - [Whether interleaved_decompress() accepts an additional palette parameter])], - [AC_MSG_RESULT([no])]) -fi - -# Check whether planar_decompress() will handle flipping -if test "x${have_freerdp}" = "xyes" -then - AC_MSG_CHECKING([whether planar_decompress() can flip]) - AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include - - int main() { - BOOL* flip = TRUE; - planar_decompress(NULL, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, flip); - }]])], - [AC_MSG_RESULT([yes]) - AC_DEFINE([PLANAR_DECOMPRESS_CAN_FLIP],, - [Whether planar_decompress() can flip])], - [AC_MSG_RESULT([no])]) -fi - -# -# FreeRDP: rdpContext -# - -# Check for rdpContext.codecs -if test "x${have_freerdp}" = "xyes" -then - AC_CHECK_MEMBERS([rdpContext.codecs], - [AC_DEFINE([FREERDP_BITMAP_REQUIRES_ALIGNED_MALLOC],, - [Whether this version of FreeRDP requires _aligned_malloc() for bitmap data])],, - [[#include ]]) -fi - -# -# FreeRDP: rdpPalette -# - -if test "x${have_freerdp}" = "xyes" -then - AC_MSG_CHECKING([whether rdpPalette.entries is static]) - AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include - rdpPalette p; - PALETTE_ENTRY* foo = p.entries;]])], - [AC_MSG_RESULT([yes])], - [AC_MSG_RESULT([no]) - AC_DEFINE([LEGACY_RDPPALETTE],, - [Whether the legacy rdpPalette API was found])]) -fi - -# -# FreeRDP: rdpPointer -# - -# Check for SetDefault and SetNull members of rdpPointer -if test "x${have_freerdp}" = "xyes" -then - AC_CHECK_MEMBERS([rdpPointer.SetDefault, - rdpPointer.SetNull], - ,, - [[#include ]]) -fi - -# -# FreeRDP: wMessage / RDP_EVENT -# - -# Check for current (as of 1.1) wMessage interface -if test "x${have_freerdp}" = "xyes" -then - AC_CHECK_MEMBERS([wMessage.id], - [event_interface=stable],, - [[#include ]]) - - # If not current, check for legacy (RDP_EVENT) interface - if test "x${event_interface}" = "xunknown" - then - AC_CHECK_MEMBERS([RDP_EVENT.event_class], - [event_interface=legacy],, - [[#include ]]) - fi - - # Set defines based on interface type, warn if unknown - if test "x${event_interface}" = "xlegacy"; then - AC_DEFINE([LEGACY_EVENT],, - [Whether the legacy RDP_EVENT API was found]) - elif test "x${event_interface}" = "xunknown"; then - AC_MSG_WARN([ - -------------------------------------------- - Unknown event interface - RDP will be disabled. - --------------------------------------------]) - have_freerdp=no - fi -fi - -AM_CONDITIONAL([LEGACY_FREERDP_EXTENSIONS], [test "x${legacy_freerdp_extensions}" = "xyes"]) -AM_CONDITIONAL([ENABLE_WINPR], [test "x${have_winpr}" = "xyes"]) -AM_CONDITIONAL([ENABLE_RDP], [test "x${have_freerdp}" = "xyes"]) +AM_CONDITIONAL([ENABLE_RDP], [test "x${have_freerdp2}" = "xyes"]) AC_SUBST(RDP_LIBS) @@ -1382,7 +897,7 @@ $PACKAGE_NAME version $PACKAGE_VERSION Library status: - freerdp ............. ${have_freerdp} + freerdp2 ............ ${have_freerdp2} pango ............... ${have_pango} libavcodec .......... ${have_libavcodec} libavutil ........... ${have_libavutil} diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index 6c08da56..3ced7e0d 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -88,8 +88,6 @@ guacdr_sources = \ unicode.c noinst_HEADERS = \ - compat/client-cliprdr.h \ - compat/rail.h \ guac_ai/ai_messages.h \ guac_ai/ai_service.h \ guac_rdpdr/rdpdr_fs_messages.h \ @@ -130,16 +128,6 @@ noinst_HEADERS = \ unicode.h \ user.h -# Add compatibility layer for WinPR if not available -if ! ENABLE_WINPR -noinst_HEADERS += compat/winpr-stream.h compat/winpr-wtypes.h -libguac_client_rdp_la_SOURCES += compat/winpr-stream.c -guacai_sources += compat/winpr-stream.c -guacsvc_sources += compat/winpr-stream.c -guacsnd_sources += compat/winpr-stream.c -guacdr_sources += compat/winpr-stream.c -endif - # # Main RDP client library # @@ -277,37 +265,6 @@ EXTRA_DIST = \ $(rdp_keymaps) \ keymaps/generate.pl -if LEGACY_FREERDP_EXTENSIONS - -# FreeRDP 1.0-style extensions -freerdp_LTLIBRARIES = \ - guacai.la -# guacdr.la \ -# guacsnd.la \ -# guacsvc.la - -guacai_la_SOURCES = ${guacai_sources} -guacai_la_CFLAGS = ${guacai_cflags} -guacai_la_LDFLAGS = ${guacai_ldflags} -guacai_la_LIBADD = ${guacai_libadd} - -#guacdr_la_SOURCES = ${guacdr_sources} -#guacdr_la_CFLAGS = ${guacdr_cflags} -#guacdr_la_LDFLAGS = ${guacdr_ldflags} -#guacdr_la_LIBADD = ${guacdr_libadd} - -#guacsnd_la_SOURCES = ${guacsnd_sources} -#guacsnd_la_CFLAGS = ${guacsnd_cflags} -#guacsnd_la_LDFLAGS = ${guacsnd_ldflags} -#guacsnd_la_LIBADD = ${guacsnd_libadd} - -#guacsvc_la_SOURCES = ${guacsvc_sources} -#guacsvc_la_CFLAGS = ${guacsvc_cflags} -#guacsvc_la_LDFLAGS = ${guacsvc_ldflags} -#guacsvc_la_LIBADD = ${guacsvc_libadd} - -else - # FreeRDP 1.1 (and hopefully onward) extensions freerdp_LTLIBRARIES = \ guacai-client.la @@ -335,7 +292,5 @@ guacai_client_la_LIBADD = ${guacai_libadd} #guacsvc_client_la_LDFLAGS = ${guacsvc_ldflags} #guacsvc_client_la_LIBADD = ${guacsvc_libadd} -endif - freerdpdir = ${libdir}/freerdp diff --git a/src/protocols/rdp/client.c b/src/protocols/rdp/client.c index 6b9a0a6b..e2f8a4c2 100644 --- a/src/protocols/rdp/client.c +++ b/src/protocols/rdp/client.c @@ -35,21 +35,13 @@ #include #include +#include +#include #include #include #include #include -#ifdef HAVE_FREERDP_CLIENT_CLIPRDR_H -#include -#else -#include "compat/client-cliprdr.h" -#endif - -#ifdef HAVE_FREERDP_CLIENT_CHANNELS_H -#include -#endif - #include #include #include diff --git a/src/protocols/rdp/compat/client-cliprdr.h b/src/protocols/rdp/compat/client-cliprdr.h deleted file mode 100644 index f1e2aabe..00000000 --- a/src/protocols/rdp/compat/client-cliprdr.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - - -#ifndef __GUAC_CLIENT_CLIPRDR_COMPAT_H -#define __GUAC_CLIENT_CLIPRDR_COMPAT_H - -#include "config.h" - -#include - -#define CliprdrChannel_Class RDP_EVENT_CLASS_CLIPRDR -#define CliprdrChannel_FormatList RDP_EVENT_TYPE_CB_FORMAT_LIST -#define CliprdrChannel_MonitorReady RDP_EVENT_TYPE_CB_MONITOR_READY -#define CliprdrChannel_DataRequest RDP_EVENT_TYPE_CB_DATA_REQUEST -#define CliprdrChannel_DataResponse RDP_EVENT_TYPE_CB_DATA_RESPONSE - -#endif - diff --git a/src/protocols/rdp/compat/rail.h b/src/protocols/rdp/compat/rail.h deleted file mode 100644 index 32d75b43..00000000 --- a/src/protocols/rdp/compat/rail.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - - -#ifndef __GUAC_RAIL_COMPAT_H -#define __GUAC_RAIL_COMPAT_H - -#include "config.h" - -#include - -#define RailChannel_Class RDP_EVENT_CLASS_RAIL -#define RailChannel_ClientSystemParam RDP_EVENT_TYPE_RAIL_CLIENT_SET_SYSPARAMS -#define RailChannel_GetSystemParam RDP_EVENT_TYPE_RAIL_CHANNEL_GET_SYSPARAMS -#define RailChannel_ServerExecuteResult RDP_EVENT_TYPE_RAIL_CHANNEL_EXEC_RESULTS -#define RailChannel_ServerSystemParam RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_SYSPARAM -#define RailChannel_ServerMinMaxInfo RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_MINMAXINFO -#define RailChannel_ServerLocalMoveSize RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_LOCALMOVESIZE -#define RailChannel_ServerGetAppIdResponse RDP_EVENT_TYPE_RAIL_CHANNEL_APPID_RESP -#define RailChannel_ServerLanguageBarInfo RDP_EVENT_TYPE_RAIL_CHANNEL_LANGBARINFO - -#endif - diff --git a/src/protocols/rdp/compat/winpr-stream.c b/src/protocols/rdp/compat/winpr-stream.c deleted file mode 100644 index 8be45466..00000000 --- a/src/protocols/rdp/compat/winpr-stream.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -#include "config.h" - -#include "winpr-stream.h" -#include "winpr-wtypes.h" - -wStream* Stream_New(BYTE* buffer, size_t size) { - - /* If no buffer is provided, allocate a new stream of the given size */ - if (buffer == NULL) - return stream_new(size); - - /* Otherwise allocate an empty stream and assign the given buffer */ - wStream* stream = stream_new(0); - stream_attach(stream, buffer, size); - return stream; - -} - -void Stream_Free(wStream* s, BOOL bFreeBuffer) { - - /* Disassociate buffer if it will be freed externally */ - if (!bFreeBuffer) - stream_detach(s); - - stream_free(s); - -} - diff --git a/src/protocols/rdp/compat/winpr-stream.h b/src/protocols/rdp/compat/winpr-stream.h deleted file mode 100644 index e2195c0d..00000000 --- a/src/protocols/rdp/compat/winpr-stream.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - - -#ifndef __GUAC_WINPR_STREAM_COMPAT_H -#define __GUAC_WINPR_STREAM_COMPAT_H - -#include "config.h" - -#include "winpr-wtypes.h" - -#include - -#include - -/* FreeRDP 1.0 streams */ - -#define Stream_Write stream_write -#define Stream_Write_UINT8 stream_write_uint8 -#define Stream_Write_UINT16 stream_write_uint16 -#define Stream_Write_UINT32 stream_write_uint32 -#define Stream_Write_UINT64 stream_write_uint64 - -#define Stream_Read stream_read -#define Stream_Read_UINT8 stream_read_uint8 -#define Stream_Read_UINT16 stream_read_uint16 -#define Stream_Read_UINT32 stream_read_uint32 -#define Stream_Read_UINT64 stream_read_uint64 - -#define Stream_Seek stream_seek -#define Stream_Seek_UINT8 stream_seek_uint8 -#define Stream_Seek_UINT16 stream_seek_uint16 -#define Stream_Seek_UINT32 stream_seek_uint32 -#define Stream_Seek_UINT64 stream_seek_uint64 - -#define Stream_GetPointer stream_get_mark -#define Stream_EnsureRemainingCapacity stream_check_size -#define Stream_Write stream_write -#define Stream_Zero stream_write_zero -#define Stream_Fill stream_set_byte -#define Stream_GetPosition stream_get_pos -#define Stream_SetPosition stream_set_pos -#define Stream_SetPointer stream_set_mark -#define Stream_Buffer stream_get_head -#define Stream_Pointer stream_get_tail -#define Stream_Length stream_get_size - -#define wStream STREAM -#define wMessage RDP_EVENT - -wStream* Stream_New(BYTE* buffer, size_t size); -void Stream_Free(wStream* s, BOOL bFreeBuffer); - -#endif - diff --git a/src/protocols/rdp/compat/winpr-wtypes.h b/src/protocols/rdp/compat/winpr-wtypes.h deleted file mode 100644 index e1d3e1ba..00000000 --- a/src/protocols/rdp/compat/winpr-wtypes.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - - -#ifndef __GUAC_WINPR_WTYPES_COMPAT_H -#define __GUAC_WINPR_WTYPES_COMPAT_H - -#include "config.h" - -#include - -typedef uint8 BYTE; -typedef uint8 UINT8; -typedef uint16 UINT16; -typedef uint32 UINT32; -typedef uint64 UINT64; -typedef boolean BOOL; - -#define TRUE true -#define FALSE false - -#endif - diff --git a/src/protocols/rdp/dvc.c b/src/protocols/rdp/dvc.c index 34406c9b..ee1c886b 100644 --- a/src/protocols/rdp/dvc.c +++ b/src/protocols/rdp/dvc.c @@ -117,14 +117,6 @@ int guac_rdp_load_drdynvc(rdpContext* context, guac_rdp_dvc_list* list) { if (list->channel_count == 0) return 0; -#ifndef HAVE_ADDIN_ARGV - /* Allocate plugin data array */ - RDP_PLUGIN_DATA* all_plugin_data = - calloc(list->channel_count + 1, sizeof(RDP_PLUGIN_DATA)); - - RDP_PLUGIN_DATA* current_plugin_data = all_plugin_data; -#endif - /* For each channel */ guac_common_list_element* current = list->channels->head; while (current != NULL) { @@ -143,41 +135,20 @@ int guac_rdp_load_drdynvc(rdpContext* context, guac_rdp_dvc_list* list) { guac_client_log(client, GUAC_LOG_DEBUG, "Registering DVC plugin \"%s\"", dvc->argv[0]); -#ifdef HAVE_ADDIN_ARGV /* Register plugin with FreeRDP */ ADDIN_ARGV* args = malloc(sizeof(ADDIN_ARGV)); args->argc = dvc->argc; args->argv = dvc->argv; freerdp_dynamic_channel_collection_add(context->settings, args); -#else - /* Copy all arguments */ - for (int i = 0; i < dvc->argc; i++) - current_plugin_data->data[i] = dvc->argv[i]; - - /* Store size of entry */ - current_plugin_data->size = sizeof(*current_plugin_data); - - /* Advance to next set of plugin data */ - current_plugin_data++; -#endif /* Rely on FreeRDP to free argv storage */ dvc->argv = NULL; } -#ifdef HAVE_ADDIN_ARGV /* Load virtual channel management plugin */ return freerdp_channels_load_plugin(channels, context->instance->settings, "drdynvc", context->instance->settings); -#else - /* Terminate with empty RDP_PLUGIN_DATA element */ - current_plugin_data->size = 0; - - /* Load virtual channel management plugin */ - return freerdp_channels_load_plugin(channels, context->instance->settings, - "drdynvc", all_plugin_data); -#endif } diff --git a/src/protocols/rdp/guac_ai/ai_messages.c b/src/protocols/rdp/guac_ai/ai_messages.c index c3465878..e0161d59 100644 --- a/src/protocols/rdp/guac_ai/ai_messages.c +++ b/src/protocols/rdp/guac_ai/ai_messages.c @@ -29,12 +29,7 @@ #include #include #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-stream.h" -#endif /** * Reads AUDIO_FORMAT data from the given stream into the given struct. diff --git a/src/protocols/rdp/guac_ai/ai_messages.h b/src/protocols/rdp/guac_ai/ai_messages.h index 55cf6e9a..1d825af0 100644 --- a/src/protocols/rdp/guac_ai/ai_messages.h +++ b/src/protocols/rdp/guac_ai/ai_messages.h @@ -24,12 +24,7 @@ #include #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-stream.h" -#endif /** * The format tag associated with raw wave audio (WAVE_FORMAT_PCM). This format diff --git a/src/protocols/rdp/guac_ai/ai_service.c b/src/protocols/rdp/guac_ai/ai_service.c index 72b43d89..aa6bca75 100644 --- a/src/protocols/rdp/guac_ai/ai_service.c +++ b/src/protocols/rdp/guac_ai/ai_service.c @@ -32,12 +32,7 @@ #include #include #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-stream.h" -#endif /** * Handles the given data received along the AUDIO_INPUT channel of the RDP @@ -95,43 +90,9 @@ static void guac_rdp_ai_handle_data(guac_client* client, } -#ifdef LEGACY_IWTSVIRTUALCHANNELCALLBACK /** * Callback which is invoked when data is received along a connection to the - * AUDIO_INPUT plugin. This callback is specific to FreeRDP 1.1 and older. - * - * @param channel_callback - * The IWTSVirtualChannelCallback structure to which this callback was - * originally assigned. - * - * @param size - * The number of bytes received. - * - * @param buffer - * A buffer containing all bytes received. - * - * @return - * Always zero. - */ -static int guac_rdp_ai_data(IWTSVirtualChannelCallback* channel_callback, - UINT32 size, BYTE* buffer) { - - guac_rdp_ai_channel_callback* ai_channel_callback = - (guac_rdp_ai_channel_callback*) channel_callback; - IWTSVirtualChannel* channel = ai_channel_callback->channel; - - /* Invoke generalized (API-independent) data handler */ - wStream* stream = Stream_New(buffer, size); - guac_rdp_ai_handle_data(ai_channel_callback->client, channel, stream); - Stream_Free(stream, FALSE); - - return 0; - -} -#else -/** - * Callback which is invoked when data is received along a connection to the - * AUDIO_INPUT plugin. This callback is specific to FreeRDP 1.2 and newer. + * AUDIO_INPUT plugin. * * @param channel_callback * The IWTSVirtualChannelCallback structure to which this callback was @@ -156,7 +117,6 @@ static UINT guac_rdp_ai_data(IWTSVirtualChannelCallback* channel_callback, return 0; } -#endif /** * Callback which is invoked when a connection to the AUDIO_INPUT plugin is @@ -315,13 +275,8 @@ static UINT guac_rdp_ai_terminated(IWTSPlugin* plugin) { int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { /* Pull guac_client from arguments */ -#ifdef HAVE_ADDIN_ARGV ADDIN_ARGV* args = pEntryPoints->GetPluginData(pEntryPoints); guac_client* client = (guac_client*) guac_rdp_string_to_ptr(args->argv[1]); -#else - RDP_PLUGIN_DATA* data = pEntryPoints->GetPluginData(pEntryPoints); - guac_client* client = (guac_client*) guac_rdp_string_to_ptr(data->data[1]); -#endif /* Pull previously-allocated plugin */ guac_rdp_ai_plugin* ai_plugin = (guac_rdp_ai_plugin*) diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.c b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.c index 54d30861..bad3f46e 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.c @@ -31,14 +31,8 @@ #include #include - -#ifdef ENABLE_WINPR #include #include -#else -#include "compat/winpr-stream.h" -#include "compat/winpr-wtypes.h" -#endif #include #include diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.h b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.h index 4e484b4d..af0c87e1 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.h +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.h @@ -33,11 +33,7 @@ #include "rdpdr_service.h" -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-stream.h" -#endif /** * Handles a Server Create Drive Request. Despite its name, this request opens diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_dir_info.c b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_dir_info.c index c53eedc6..3ab31e5f 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_dir_info.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_dir_info.c @@ -26,12 +26,7 @@ #include #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-stream.h" -#endif #include diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_dir_info.h b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_dir_info.h index 06e2074e..9e0fcaf6 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_dir_info.h +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_dir_info.h @@ -33,11 +33,7 @@ #include "rdpdr_service.h" -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-stream.h" -#endif /** * Processes a query request for FileDirectoryInformation. From the diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_file_info.c b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_file_info.c index b23e7bd2..e65ef9c1 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_file_info.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_file_info.c @@ -25,14 +25,8 @@ #include "unicode.h" #include - -#ifdef ENABLE_WINPR #include #include -#else -#include "compat/winpr-stream.h" -#include "compat/winpr-wtypes.h" -#endif #include #include diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_file_info.h b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_file_info.h index aa53eadf..de5559ad 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_file_info.h +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_file_info.h @@ -32,11 +32,7 @@ #include "rdpdr_service.h" -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-stream.h" -#endif /** * Processes a query for FileBasicInformation. From the documentation, this is diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_vol_info.c b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_vol_info.c index c1072957..27defb0e 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_vol_info.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_vol_info.c @@ -26,14 +26,8 @@ #include #include - -#ifdef ENABLE_WINPR #include #include -#else -#include "compat/winpr-stream.h" -#include "compat/winpr-wtypes.h" -#endif void guac_rdpdr_fs_process_query_volume_info(guac_rdpdr_device* device, wStream* input_stream, int file_id, int completion_id) { diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_vol_info.h b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_vol_info.h index 0c82a2f1..b0e3629f 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_vol_info.h +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_vol_info.h @@ -33,11 +33,7 @@ #include "rdpdr_service.h" -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-stream.h" -#endif /** * Processes a query request for FileFsVolumeInformation. According to the diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_service.c b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_service.c index e064d4de..63425ba6 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_service.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_service.c @@ -30,12 +30,7 @@ #include #include #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-stream.h" -#endif static void guac_rdpdr_device_fs_iorequest_handler(guac_rdpdr_device* device, wStream* input_stream, int file_id, int completion_id, int major_func, int minor_func) { diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.c b/src/protocols/rdp/guac_rdpdr/rdpdr_messages.c index 66626adb..507b4d7c 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_messages.c @@ -27,12 +27,7 @@ #include #include #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-stream.h" -#endif #include #include diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h b/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h index 1e489245..b719ab0c 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h @@ -25,11 +25,7 @@ #include "rdpdr_service.h" -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-stream.h" -#endif #include diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_printer.c b/src/protocols/rdp/guac_rdpdr/rdpdr_printer.c index ace025c4..e8c2a5da 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_printer.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_printer.c @@ -34,12 +34,7 @@ #include #include #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-stream.h" -#endif #include #include diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_printer.h b/src/protocols/rdp/guac_rdpdr/rdpdr_printer.h index 9dbeb42c..c6abcde5 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_printer.h +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_printer.h @@ -25,11 +25,7 @@ #include "rdpdr_service.h" -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-stream.h" -#endif /** * Registers a new printer device within the RDPDR plugin. This must be done diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_service.c b/src/protocols/rdp/guac_rdpdr/rdpdr_service.c index 4901deca..40a1e51e 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_service.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_service.c @@ -37,12 +37,7 @@ #include #include #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-stream.h" -#endif /** * Entry point for RDPDR virtual channel. diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_service.h b/src/protocols/rdp/guac_rdpdr/rdpdr_service.h index ea5cb577..064ce32d 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_service.h +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_service.h @@ -25,12 +25,7 @@ #include #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-stream.h" -#endif /** * The maximum number of bytes to allow for a device read. diff --git a/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.c b/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.c index ba0224c1..4893ad49 100644 --- a/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.c +++ b/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.c @@ -29,14 +29,8 @@ #include #include #include - -#ifdef ENABLE_WINPR #include #include -#else -#include "compat/winpr-stream.h" -#include "compat/winpr-wtypes.h" -#endif /* MESSAGE HANDLERS */ diff --git a/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.h b/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.h index 7083b844..5fceca77 100644 --- a/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.h +++ b/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.h @@ -25,11 +25,7 @@ #include "rdpsnd_service.h" -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-stream.h" -#endif /* * PDU Message Types diff --git a/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c b/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c index cc367c4f..d3bce560 100644 --- a/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c +++ b/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c @@ -28,12 +28,7 @@ #include #include #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-stream.h" -#endif /** * Entry point for RDPSND virtual channel. diff --git a/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.h b/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.h index b6a93962..7a4aff52 100644 --- a/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.h +++ b/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.h @@ -25,12 +25,7 @@ #include #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-stream.h" -#endif /** * The maximum number of PCM formats to accept during the initial RDPSND diff --git a/src/protocols/rdp/guac_svc/svc_service.c b/src/protocols/rdp/guac_svc/svc_service.c index c40c6c5f..70e86f12 100644 --- a/src/protocols/rdp/guac_svc/svc_service.c +++ b/src/protocols/rdp/guac_svc/svc_service.c @@ -30,12 +30,7 @@ #include #include #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-stream.h" -#endif /** * Entry point for arbitrary SVC. diff --git a/src/protocols/rdp/guac_svc/svc_service.h b/src/protocols/rdp/guac_svc/svc_service.h index 219aaece..8aec6ca9 100644 --- a/src/protocols/rdp/guac_svc/svc_service.h +++ b/src/protocols/rdp/guac_svc/svc_service.h @@ -24,12 +24,7 @@ #include "rdp_svc.h" #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-stream.h" -#endif /** * Structure representing the current state of an arbitrary static virtual diff --git a/src/protocols/rdp/keymaps/generate.pl b/src/protocols/rdp/keymaps/generate.pl index 263b616a..8ca2a6b9 100755 --- a/src/protocols/rdp/keymaps/generate.pl +++ b/src/protocols/rdp/keymaps/generate.pl @@ -45,12 +45,7 @@ print OUTPUT '#include "config.h"' . "\n" . '#include "rdp_keymap.h"' . "\n" . '#include ' . "\n" - . "\n" - . '#ifdef HAVE_FREERDP_LOCALE_KEYBOARD_H' . "\n" . '#include ' . "\n" - . '#else' . "\n" - . '#include ' . "\n" - . '#endif' . "\n" . "\n" . '#include ' . "\n" . "\n"; diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 922febe1..97807934 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -48,6 +48,7 @@ #include "common-ssh/user.h" #endif +#include #include #include #include @@ -55,50 +56,19 @@ #include #include #include +#include +#include +#include +#include #include +#include +#include #include #include #include #include #include - -#ifdef HAVE_FREERDP_CLIENT_CLIPRDR_H -#include -#else -#include "compat/client-cliprdr.h" -#endif - -#ifdef HAVE_FREERDP_CLIENT_DISP_H -#include -#endif - -#ifdef HAVE_FREERDP_EVENT_PUBSUB -#include -#endif - -#ifdef LEGACY_FREERDP -#include "compat/rail.h" -#else -#include -#endif - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-wtypes.h" -#endif - -#ifdef HAVE_FREERDP_ADDIN_H -#include -#endif - -#ifdef HAVE_FREERDP_CLIENT_CHANNELS_H -#include -#endif - -#ifdef HAVE_FREERDP_VERSION_H -#include -#endif #include #include @@ -108,58 +78,6 @@ #include #include -/** - * Callback invoked by FreeRDP for data received along a channel. This is the - * most recent version of the callback and uses a 16-bit unsigned integer for - * the channel ID, as well as different type naming for the datatype of the - * data itself. This function does nothing more than invoke - * freerdp_channels_data() with the given arguments. The prototypes of these - * functions are compatible in 1.2 and later, but not necessarily prior to - * that, hence the conditional compilation of differing prototypes. - * - * Beware that the official purpose of these parameters is an undocumented - * mystery. The meanings below are derived from looking at how the function is - * used within FreeRDP. - * - * @param rdp_inst - * The RDP client instance associated with the channel receiving the data. - * - * @param channelId - * The integer ID of the channel that received the data. - * - * @param data - * A buffer containing the received data. - * - * @param size - * The number of bytes received and contained in the given buffer (the - * number of bytes received within the PDU that resulted in this function - * being inboked). - * - * @param flags - * Channel control flags, as defined by the CHANNEL_PDU_HEADER in the RDP - * specification. - * - * @param total_size - * The total length of the chanel data being received, which may span - * multiple PDUs (see the "length" field of CHANNEL_PDU_HEADER). - * - * @return - * Zero if the received channel data was successfully handled, non-zero - * otherwise. Note that this return value is discarded in practice. - */ -#if defined(FREERDP_VERSION_MAJOR) \ - && (FREERDP_VERSION_MAJOR > 1 || FREERDP_VERSION_MINOR >= 2) -static int __guac_receive_channel_data(freerdp* rdp_inst, UINT16 channelId, - BYTE* data, int size, int flags, int total_size) { -#else -static int __guac_receive_channel_data(freerdp* rdp_inst, int channelId, - UINT8* data, int size, int flags, int total_size) { -#endif - return freerdp_channels_data(rdp_inst, channelId, - data, size, flags, total_size); -} - -#ifdef HAVE_FREERDP_EVENT_PUBSUB /** * Called whenever a channel connects via the PubSub event system within * FreeRDP. @@ -179,7 +97,6 @@ static void guac_rdp_channel_connected(rdpContext* context, guac_rdp_settings* settings = rdp_client->settings; if (settings->resize_method == GUAC_RESIZE_DISPLAY_UPDATE) { -#ifdef HAVE_RDPSETTINGS_SUPPORTDISPLAYCONTROL /* Store reference to the display update plugin once it's connected */ if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) == 0) { @@ -196,11 +113,9 @@ static void guac_rdp_channel_connected(rdpContext* context, "Display update channel connected."); } -#endif } } -#endif BOOL rdp_freerdp_pre_connect(freerdp* instance) { @@ -219,22 +134,16 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { guac_rdp_dvc_list* dvc_list = guac_rdp_dvc_list_alloc(); -#ifdef HAVE_FREERDP_REGISTER_ADDIN_PROVIDER /* Init FreeRDP add-in provider */ freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0); -#endif -#ifdef HAVE_FREERDP_EVENT_PUBSUB /* Subscribe to and handle channel connected events */ PubSub_SubscribeChannelConnected(context->pubSub, (pChannelConnectedEventHandler) guac_rdp_channel_connected); -#endif -#ifdef HAVE_FREERDP_DISPLAY_UPDATE_SUPPORT /* Load "disp" plugin for display update */ if (settings->resize_method == GUAC_RESIZE_DISPLAY_UPDATE) guac_rdp_disp_load_plugin(instance->context, dvc_list); -#endif /* Load "AUDIO_INPUT" plugin for audio input*/ if (settings->enable_audio_input) { @@ -273,29 +182,11 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { /* Load RAIL plugin if RemoteApp in use */ if (settings->remote_app != NULL) { -#ifdef LEGACY_FREERDP - RDP_PLUGIN_DATA* plugin_data = malloc(sizeof(RDP_PLUGIN_DATA) * 2); - - plugin_data[0].size = sizeof(RDP_PLUGIN_DATA); - plugin_data[0].data[0] = settings->remote_app; - plugin_data[0].data[1] = settings->remote_app_dir; - plugin_data[0].data[2] = settings->remote_app_args; - plugin_data[0].data[3] = NULL; - - plugin_data[1].size = 0; - - /* Attempt to load rail */ - if (freerdp_channels_load_plugin(channels, instance->settings, - "rail", plugin_data)) - guac_client_log(client, GUAC_LOG_WARNING, - "Failed to load rail plugin. RemoteApp will not work."); -#else /* Attempt to load rail */ if (freerdp_channels_load_plugin(channels, instance->settings, "rail", instance->settings)) guac_client_log(client, GUAC_LOG_WARNING, "Failed to load rail plugin. RemoteApp will not work."); -#endif } @@ -375,12 +266,8 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { pointer->New = guac_rdp_pointer_new; pointer->Free = guac_rdp_pointer_free; pointer->Set = guac_rdp_pointer_set; -#ifdef HAVE_RDPPOINTER_SETNULL pointer->SetNull = guac_rdp_pointer_set_null; -#endif -#ifdef HAVE_RDPPOINTER_SETDEFAULT pointer->SetDefault = guac_rdp_pointer_set_default; -#endif graphics_register_pointer(context->graphics, pointer); free(pointer); @@ -689,9 +576,7 @@ static int guac_rdp_handle_connection(guac_client* client) { rdp_client->requested_clipboard_format = CB_FORMAT_TEXT; rdp_client->available_svc = guac_common_list_alloc(); -#ifdef HAVE_FREERDP_CHANNELS_GLOBAL_INIT freerdp_channels_global_init(); -#endif /* Init client */ freerdp* rdp_inst = freerdp_new(); @@ -699,14 +584,10 @@ static int guac_rdp_handle_connection(guac_client* client) { rdp_inst->PostConnect = rdp_freerdp_post_connect; rdp_inst->Authenticate = rdp_freerdp_authenticate; rdp_inst->VerifyCertificate = rdp_freerdp_verify_certificate; - rdp_inst->ReceiveChannelData = __guac_receive_channel_data; + rdp_inst->ReceiveChannelData = freerdp_channels_data; /* Allocate FreeRDP context */ -#ifdef LEGACY_FREERDP - rdp_inst->context_size = sizeof(rdp_freerdp_context); -#else rdp_inst->ContextSize = sizeof(rdp_freerdp_context); -#endif rdp_inst->ContextNew = (pContextNew) rdp_freerdp_context_new; rdp_inst->ContextFree = (pContextFree) rdp_freerdp_context_free; @@ -780,17 +661,10 @@ static int guac_rdp_handle_connection(guac_client* client) { if (event) { /* Handle channel events (clipboard and RAIL) */ -#ifdef LEGACY_EVENT - if (event->event_class == CliprdrChannel_Class) - guac_rdp_process_cliprdr_event(client, event); - else if (event->event_class == RailChannel_Class) - guac_rdp_process_rail_event(client, event); -#else if (GetMessageClass(event->id) == CliprdrChannel_Class) guac_rdp_process_cliprdr_event(client, event); else if (GetMessageClass(event->id) == RailChannel_Class) guac_rdp_process_rail_event(client, event); -#endif freerdp_event_free(event); diff --git a/src/protocols/rdp/rdp_bitmap.c b/src/protocols/rdp/rdp_bitmap.c index 659c72b0..e6343d49 100644 --- a/src/protocols/rdp/rdp_bitmap.c +++ b/src/protocols/rdp/rdp_bitmap.c @@ -32,12 +32,7 @@ #include #include #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-wtypes.h" -#endif #include #include @@ -87,11 +82,7 @@ BOOL guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap) { /* Free existing image, if any */ if (image_buffer != bitmap->data) { -#ifdef FREERDP_BITMAP_REQUIRES_ALIGNED_MALLOC _aligned_free(bitmap->data); -#else - free(bitmap->data); -#endif } /* Store converted image in bitmap */ @@ -194,69 +185,39 @@ BOOL guac_rdp_bitmap_setsurface(rdpContext* context, rdpBitmap* bitmap, BOOL pri } -#ifdef LEGACY_RDPBITMAP -void guac_rdp_bitmap_decompress(rdpContext* context, rdpBitmap* bitmap, UINT8* data, - int width, int height, int bpp, int length, BOOL compressed) { -#else BOOL guac_rdp_bitmap_decompress(rdpContext* context, rdpBitmap* bitmap, const BYTE* data, UINT32 width, UINT32 height, UINT32 bpp, UINT32 length, BOOL compressed, UINT32 codec_id) { -#endif int size = width * height * 4; -#ifdef FREERDP_BITMAP_REQUIRES_ALIGNED_MALLOC /* Free pre-existing data, if any (might be reused) */ if (bitmap->data != NULL) _aligned_free(bitmap->data); - /* Allocate new data */ + /* Allocate new data - this MUST be allocated with _aligned_malloc() */ bitmap->data = (UINT8*) _aligned_malloc(size, 16); -#else - /* Free pre-existing data, if any (might be reused) */ - free(bitmap->data); - - /* Allocate new data */ - bitmap->data = (UINT8*) malloc(size); -#endif if (compressed) { -#ifdef HAVE_RDPCONTEXT_CODECS rdpCodecs* codecs = context->codecs; /* Decode as interleaved if less than 32 bits per pixel */ if (bpp < 32) { freerdp_client_codecs_prepare(codecs, FREERDP_CODEC_INTERLEAVED); -#ifdef INTERLEAVED_DECOMPRESS_TAKES_PALETTE interleaved_decompress(codecs->interleaved, data, length, bpp, &(bitmap->data), PIXEL_FORMAT_XRGB32, -1, 0, 0, width, height, (BYTE*) ((rdp_freerdp_context*) context)->palette); bitmap->bpp = 32; -#else - interleaved_decompress(codecs->interleaved, data, length, bpp, - &(bitmap->data), PIXEL_FORMAT_XRGB32, -1, 0, 0, width, height); - bitmap->bpp = bpp; -#endif } /* Otherwise, decode as planar */ else { freerdp_client_codecs_prepare(codecs, FREERDP_CODEC_PLANAR); -#ifdef PLANAR_DECOMPRESS_CAN_FLIP planar_decompress(codecs->planar, data, length, &(bitmap->data), PIXEL_FORMAT_XRGB32, -1, 0, 0, width, height, TRUE); bitmap->bpp = 32; -#else - planar_decompress(codecs->planar, data, length, - &(bitmap->data), PIXEL_FORMAT_XRGB32, -1, 0, 0, width, height); - bitmap->bpp = bpp; -#endif } -#else - bitmap_decompress(data, bitmap->data, width, height, length, bpp, bpp); - bitmap->bpp = bpp; -#endif } else { diff --git a/src/protocols/rdp/rdp_bitmap.h b/src/protocols/rdp/rdp_bitmap.h index e2aaa120..23c56404 100644 --- a/src/protocols/rdp/rdp_bitmap.h +++ b/src/protocols/rdp/rdp_bitmap.h @@ -26,12 +26,7 @@ #include #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-wtypes.h" -#endif /** * Guacamole-specific rdpBitmap data. @@ -126,41 +121,6 @@ void guac_rdp_bitmap_free(rdpContext* context, rdpBitmap* bitmap); BOOL guac_rdp_bitmap_setsurface(rdpContext* context, rdpBitmap* bitmap, BOOL primary); -#ifdef LEGACY_RDPBITMAP -/** - * Decompresses or copies the given image data, storing the result within the - * given bitmap, depending on the compressed flag. Note that even if the - * received data is not compressed, it is the duty of this function to also - * flip received data, if the row order is backwards. - * - * @param context - * The rdpContext associated with the current RDP session. - * - * @param bitmap - * The bitmap in which the decompressed/copied data should be stored. - * - * @param data - * Possibly-compressed image data. - * - * @param width - * The width of the image data, in pixels. - * - * @param height - * The height of the image data, in pixels. - * - * @param bpp - * The number of bits per pixel in the image data. - * - * @param length - * The length of the image data, in bytes. - * - * @param compressed - * TRUE if the image data is compressed, FALSE otherwise. - */ -void guac_rdp_bitmap_decompress(rdpContext* context, rdpBitmap* bitmap, - UINT8* data, int width, int height, int bpp, int length, - BOOL compressed); -#else /** * Decompresses or copies the given image data, storing the result within the * given bitmap, depending on the compressed flag. Note that even if the @@ -198,6 +158,5 @@ void guac_rdp_bitmap_decompress(rdpContext* context, rdpBitmap* bitmap, BOOL guac_rdp_bitmap_decompress(rdpContext* context, rdpBitmap* bitmap, const BYTE* data, UINT32 width, UINT32 height, UINT32 bpp, UINT32 length, BOOL compressed, UINT32 codec_id); -#endif #endif diff --git a/src/protocols/rdp/rdp_cliprdr.c b/src/protocols/rdp/rdp_cliprdr.c index 53019115..620923d8 100644 --- a/src/protocols/rdp/rdp_cliprdr.c +++ b/src/protocols/rdp/rdp_cliprdr.c @@ -26,32 +26,18 @@ #include "rdp_cliprdr.h" #include +#include #include #include #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-wtypes.h" -#endif - -#ifdef HAVE_FREERDP_CLIENT_CLIPRDR_H -#include -#else -#include "compat/client-cliprdr.h" -#endif #include #include void guac_rdp_process_cliprdr_event(guac_client* client, wMessage* event) { -#ifdef LEGACY_EVENT switch (event->event_type) { -#else - switch (GetMessageType(event->id)) { -#endif case CliprdrChannel_MonitorReady: guac_rdp_process_cb_monitor_ready(client, event); @@ -73,15 +59,9 @@ void guac_rdp_process_cliprdr_event(guac_client* client, wMessage* event) { break; default: -#ifdef LEGACY_EVENT - guac_client_log(client, GUAC_LOG_INFO, - "Unknown cliprdr event type: 0x%x", - event->event_type); -#else guac_client_log(client, GUAC_LOG_INFO, "Unknown cliprdr event type: 0x%x", GetMessageType(event->id)); -#endif } diff --git a/src/protocols/rdp/rdp_cliprdr.h b/src/protocols/rdp/rdp_cliprdr.h index b66e1b76..b279d5f8 100644 --- a/src/protocols/rdp/rdp_cliprdr.h +++ b/src/protocols/rdp/rdp_cliprdr.h @@ -24,18 +24,8 @@ #include "config.h" #include - -#ifdef ENABLE_WINPR -#include -#else -#include "compat/winpr-stream.h" -#endif - -#ifdef HAVE_FREERDP_CLIENT_CLIPRDR_H #include -#else -#include "compat/client-cliprdr.h" -#endif +#include /** * Clipboard format for text encoded in Windows CP1252. diff --git a/src/protocols/rdp/rdp_color.c b/src/protocols/rdp/rdp_color.c index 0b7de7fc..98345a12 100644 --- a/src/protocols/rdp/rdp_color.c +++ b/src/protocols/rdp/rdp_color.c @@ -25,38 +25,15 @@ #include #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-wtypes.h" -#endif UINT32 guac_rdp_convert_color(rdpContext* context, UINT32 color) { -#ifdef HAVE_FREERDP_CONVERT_GDI_ORDER_COLOR - UINT32* palette = ((rdp_freerdp_context*) context)->palette; - - /* Convert given color to ARGB32 */ - return freerdp_convert_gdi_order_color(color, - guac_rdp_get_depth(context->instance), PIXEL_FORMAT_ARGB32, - (BYTE*) palette); - -#elif defined(HAVE_FREERDP_COLOR_CONVERT_DRAWING_ORDER_COLOR_TO_GDI_COLOR) CLRCONV* clrconv = ((rdp_freerdp_context*) context)->clrconv; /* Convert given color to ARGB32 */ return freerdp_color_convert_drawing_order_color_to_gdi_color(color, guac_rdp_get_depth(context->instance), clrconv); -#else - CLRCONV* clrconv = ((rdp_freerdp_context*) context)->clrconv; - - /* Convert given color to ARGB32 */ - return freerdp_color_convert_var(color, - guac_rdp_get_depth(context->instance), 32, - clrconv); -#endif - } diff --git a/src/protocols/rdp/rdp_color.h b/src/protocols/rdp/rdp_color.h index 40712ba8..0617194b 100644 --- a/src/protocols/rdp/rdp_color.h +++ b/src/protocols/rdp/rdp_color.h @@ -21,12 +21,7 @@ #define GUAC_RDP_COLOR_H #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-wtypes.h" -#endif /** * Converts the given color to ARGB32. The color given may be an index diff --git a/src/protocols/rdp/rdp_disp.c b/src/protocols/rdp/rdp_disp.c index 7c7e059d..b26806e1 100644 --- a/src/protocols/rdp/rdp_disp.c +++ b/src/protocols/rdp/rdp_disp.c @@ -24,22 +24,17 @@ #include "rdp_disp.h" #include "rdp_settings.h" +#include #include #include #include -#ifdef HAVE_FREERDP_CLIENT_DISP_H -#include -#endif - guac_rdp_disp* guac_rdp_disp_alloc() { guac_rdp_disp* disp = malloc(sizeof(guac_rdp_disp)); -#ifdef HAVE_FREERDP_DISPLAY_UPDATE_SUPPORT /* Not yet connected */ disp->disp = NULL; -#endif /* No requests have been made */ disp->last_request = guac_timestamp_current(); @@ -57,20 +52,16 @@ void guac_rdp_disp_free(guac_rdp_disp* disp) { void guac_rdp_disp_load_plugin(rdpContext* context, guac_rdp_dvc_list* list) { -#ifdef HAVE_RDPSETTINGS_SUPPORTDISPLAYCONTROL context->settings->SupportDisplayControl = TRUE; -#endif /* Add "disp" channel */ guac_rdp_dvc_list_add(list, "disp", NULL); } -#ifdef HAVE_FREERDP_DISPLAY_UPDATE_SUPPORT void guac_rdp_disp_connect(guac_rdp_disp* guac_disp, DispClientContext* disp) { guac_disp->disp = disp; } -#endif /** * Fits a given dimension within the allowed bounds for Display Update @@ -172,7 +163,6 @@ void guac_rdp_disp_update_size(guac_rdp_disp* disp, } else if (settings->resize_method == GUAC_RESIZE_DISPLAY_UPDATE) { -#ifdef HAVE_FREERDP_DISPLAY_UPDATE_SUPPORT DISPLAY_CONTROL_MONITOR_LAYOUT monitors[1] = {{ .Flags = 0x1, /* DISPLAYCONTROL_MONITOR_PRIMARY */ .Left = 0, @@ -189,7 +179,6 @@ void guac_rdp_disp_update_size(guac_rdp_disp* disp, /* Send display update notification if display channel is connected */ if (disp->disp != NULL) disp->disp->SendMonitorLayout(disp->disp, 1, monitors); -#endif } } diff --git a/src/protocols/rdp/rdp_disp.h b/src/protocols/rdp/rdp_disp.h index 0f34fe12..562ffb65 100644 --- a/src/protocols/rdp/rdp_disp.h +++ b/src/protocols/rdp/rdp_disp.h @@ -23,11 +23,8 @@ #include "dvc.h" #include "rdp_settings.h" -#include - -#ifdef HAVE_FREERDP_CLIENT_DISP_H #include -#endif +#include /** * The minimum value for width or height, in pixels. @@ -50,12 +47,10 @@ */ typedef struct guac_rdp_disp { -#ifdef HAVE_FREERDP_DISPLAY_UPDATE_SUPPORT /** * Display control interface. */ DispClientContext* disp; -#endif /** * The timestamp of the last display update request, or 0 if no request @@ -117,7 +112,6 @@ void guac_rdp_disp_free(guac_rdp_disp* disp); */ void guac_rdp_disp_load_plugin(rdpContext* context, guac_rdp_dvc_list* list); -#ifdef HAVE_FREERDP_DISPLAY_UPDATE_SUPPORT /** * Stores the given DispClientContext within the given guac_rdp_disp, such that * display updates can be properly sent. Until this is called, changes to the @@ -129,7 +123,6 @@ void guac_rdp_disp_load_plugin(rdpContext* context, guac_rdp_dvc_list* list); * display update channel. */ void guac_rdp_disp_connect(guac_rdp_disp* guac_disp, DispClientContext* disp); -#endif /** * Requests a display size update, which may then be sent immediately to the diff --git a/src/protocols/rdp/rdp_fs.h b/src/protocols/rdp/rdp_fs.h index 7ceb5ff9..8586810b 100644 --- a/src/protocols/rdp/rdp_fs.h +++ b/src/protocols/rdp/rdp_fs.h @@ -131,18 +131,6 @@ #define DISP_FILE_OVERWRITE 0x00000004 #define DISP_FILE_OVERWRITE_IF 0x00000005 -/* - * Information constants. - * FreeRDP 1.1+ already defines those constants - */ -#ifdef LEGACY_FREERDP - -#define FILE_SUPERSEDED 0x00000000 -#define FILE_OPENED 0x00000001 -#define FILE_OVERWRITTEN 0x00000003 - -#endif - /* * File attributes. */ diff --git a/src/protocols/rdp/rdp_gdi.c b/src/protocols/rdp/rdp_gdi.c index 703dd32a..7ea64cae 100644 --- a/src/protocols/rdp/rdp_gdi.c +++ b/src/protocols/rdp/rdp_gdi.c @@ -30,12 +30,7 @@ #include #include #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-wtypes.h" -#endif #include @@ -361,12 +356,8 @@ static void guac_rdp_update_clrconv(CLRCONV* clrconv, PALETTE_UPDATE* palette) { clrconv->palette->count = palette->number; -#ifdef LEGACY_RDPPALETTE - clrconv->palette->entries = palette->entries; -#else memcpy(clrconv->palette->entries, palette->entries, sizeof(palette->entries)); -#endif } #endif diff --git a/src/protocols/rdp/rdp_glyph.c b/src/protocols/rdp/rdp_glyph.c index ee8a211a..6bb8f59d 100644 --- a/src/protocols/rdp/rdp_glyph.c +++ b/src/protocols/rdp/rdp_glyph.c @@ -28,12 +28,7 @@ #include #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-wtypes.h" -#endif #include #include diff --git a/src/protocols/rdp/rdp_glyph.h b/src/protocols/rdp/rdp_glyph.h index 0c8b747b..10b79cd2 100644 --- a/src/protocols/rdp/rdp_glyph.h +++ b/src/protocols/rdp/rdp_glyph.h @@ -25,12 +25,7 @@ #include #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-wtypes.h" -#endif /** * Guacamole-specific rdpGlyph data. diff --git a/src/protocols/rdp/rdp_keymap.h b/src/protocols/rdp/rdp_keymap.h index f15ddea0..05ed6db5 100644 --- a/src/protocols/rdp/rdp_keymap.h +++ b/src/protocols/rdp/rdp_keymap.h @@ -23,11 +23,7 @@ #include "config.h" -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-wtypes.h" -#endif /** * Represents a keysym-to-scancode mapping for RDP, with extra information diff --git a/src/protocols/rdp/rdp_rail.c b/src/protocols/rdp/rdp_rail.c index 671be8db..56ba6358 100644 --- a/src/protocols/rdp/rdp_rail.c +++ b/src/protocols/rdp/rdp_rail.c @@ -26,30 +26,16 @@ #include #include +#include #include #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-wtypes.h" -#endif - -#ifdef LEGACY_FREERDP -#include "compat/rail.h" -#else -#include -#endif #include void guac_rdp_process_rail_event(guac_client* client, wMessage* event) { -#ifdef LEGACY_EVENT - switch (event->event_type) { -#else switch (GetMessageType(event->id)) { -#endif /* Get system parameters */ case RailChannel_GetSystemParam: @@ -66,15 +52,9 @@ void guac_rdp_process_rail_event(guac_client* client, wMessage* event) { break; default: -#ifdef LEGACY_EVENT - guac_client_log(client, GUAC_LOG_INFO, - "Unknown rail event type: 0x%x", - event->event_type); -#else guac_client_log(client, GUAC_LOG_INFO, "Unknown rail event type: 0x%x", GetMessageType(event->id)); -#endif } @@ -90,11 +70,7 @@ void guac_rdp_process_rail_get_sysparam(guac_client* client, wMessage* event) { rdpChannels* channels = rdp_client->rdp_inst->context->channels; /* Get sysparam structure */ -#ifdef LEGACY_EVENT - sysparam = (RAIL_SYSPARAM_ORDER*) event->user_data; -#else sysparam = (RAIL_SYSPARAM_ORDER*) event->wParam; -#endif response = freerdp_event_new(RailChannel_Class, RailChannel_ClientSystemParam, diff --git a/src/protocols/rdp/rdp_rail.h b/src/protocols/rdp/rdp_rail.h index 949eb3e4..e19f25fc 100644 --- a/src/protocols/rdp/rdp_rail.h +++ b/src/protocols/rdp/rdp_rail.h @@ -24,12 +24,7 @@ #include "config.h" #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-stream.h" -#endif /** * Dispatches a given RAIL event to the appropriate handler. diff --git a/src/protocols/rdp/rdp_settings.c b/src/protocols/rdp/rdp_settings.c index 51214a61..2bfd197b 100644 --- a/src/protocols/rdp/rdp_settings.c +++ b/src/protocols/rdp/rdp_settings.c @@ -29,12 +29,7 @@ #include #include #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-wtypes.h" -#endif #include #include @@ -107,17 +102,13 @@ const char* GUAC_RDP_CLIENT_ARGS[] = { "enable-audio-input", "read-only", -#ifdef HAVE_FREERDP_GATEWAY_SUPPORT "gateway-hostname", "gateway-port", "gateway-domain", "gateway-username", "gateway-password", -#endif -#ifdef HAVE_FREERDP_LOAD_BALANCER_SUPPORT "load-balance-info", -#endif NULL }; @@ -499,7 +490,6 @@ enum RDP_ARGS_IDX { */ IDX_READ_ONLY, -#ifdef HAVE_FREERDP_GATEWAY_SUPPORT /** * The hostname of the remote desktop gateway that should be used as an * intermediary for the remote desktop connection. If omitted, a gateway @@ -536,15 +526,12 @@ enum RDP_ARGS_IDX { * gateway, if a gateway is being used. */ IDX_GATEWAY_PASSWORD, -#endif -#ifdef HAVE_FREERDP_LOAD_BALANCER_SUPPORT /** * The load balancing information/cookie which should be provided to * the connection broker, if a connection broker is being used. */ IDX_LOAD_BALANCE_INFO, -#endif RDP_ARGS_COUNT }; @@ -797,7 +784,6 @@ guac_rdp_settings* guac_rdp_parse_args(guac_user* user, "Preconnection BLOB: \"%s\"", settings->preconnection_blob); } -#ifndef HAVE_RDPSETTINGS_SENDPRECONNECTIONPDU /* Warn if support for the preconnection BLOB / ID is absent */ if (settings->preconnection_blob != NULL || settings->preconnection_id != -1) { @@ -806,7 +792,6 @@ guac_rdp_settings* guac_rdp_parse_args(guac_user* user, "preconnection PDU. The specified preconnection BLOB and/or " "ID will be ignored."); } -#endif /* Audio enable/disable */ settings->audio_enabled = @@ -974,7 +959,6 @@ guac_rdp_settings* guac_rdp_parse_args(guac_user* user, guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_ENABLE_AUDIO_INPUT, 0); -#ifdef HAVE_FREERDP_GATEWAY_SUPPORT /* Set gateway hostname */ settings->gateway_hostname = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, @@ -999,14 +983,11 @@ guac_rdp_settings* guac_rdp_parse_args(guac_user* user, settings->gateway_password = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_GATEWAY_PASSWORD, NULL); -#endif -#ifdef HAVE_FREERDP_LOAD_BALANCER_SUPPORT /* Set load balance info */ settings->load_balance_info = guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_LOAD_BALANCE_INFO, NULL); -#endif /* Success */ return settings; @@ -1061,18 +1042,14 @@ void guac_rdp_settings_free(guac_rdp_settings* settings) { free(settings->sftp_username); #endif -#ifdef HAVE_FREERDP_GATEWAY_SUPPORT /* Free RD gateway information */ free(settings->gateway_hostname); free(settings->gateway_domain); free(settings->gateway_username); free(settings->gateway_password); -#endif -#ifdef HAVE_FREERDP_LOAD_BALANCER_SUPPORT /* Free load balancer information string */ free(settings->load_balance_info); -#endif /* Free settings structure */ free(settings); @@ -1080,27 +1057,15 @@ void guac_rdp_settings_free(guac_rdp_settings* settings) { } int guac_rdp_get_width(freerdp* rdp) { -#ifdef LEGACY_RDPSETTINGS - return rdp->settings->width; -#else return rdp->settings->DesktopWidth; -#endif } int guac_rdp_get_height(freerdp* rdp) { -#ifdef LEGACY_RDPSETTINGS - return rdp->settings->height; -#else return rdp->settings->DesktopHeight; -#endif } int guac_rdp_get_depth(freerdp* rdp) { -#ifdef LEGACY_RDPSETTINGS - return rdp->settings->color_depth; -#else return rdp->settings->ColorDepth; -#endif } /** @@ -1177,56 +1142,22 @@ void guac_rdp_push_settings(guac_client* client, rdpSettings* rdp_settings = rdp->settings; /* Authentication */ -#ifdef LEGACY_RDPSETTINGS - rdp_settings->domain = guac_rdp_strdup(guac_settings->domain); - rdp_settings->username = guac_rdp_strdup(guac_settings->username); - rdp_settings->password = guac_rdp_strdup(guac_settings->password); -#else rdp_settings->Domain = guac_rdp_strdup(guac_settings->domain); rdp_settings->Username = guac_rdp_strdup(guac_settings->username); rdp_settings->Password = guac_rdp_strdup(guac_settings->password); -#endif /* Connection */ -#ifdef LEGACY_RDPSETTINGS - rdp_settings->hostname = guac_rdp_strdup(guac_settings->hostname); - rdp_settings->port = guac_settings->port; -#else rdp_settings->ServerHostname = guac_rdp_strdup(guac_settings->hostname); rdp_settings->ServerPort = guac_settings->port; -#endif /* Session */ -#ifdef LEGACY_RDPSETTINGS - rdp_settings->color_depth = guac_settings->color_depth; - rdp_settings->width = guac_settings->width; - rdp_settings->height = guac_settings->height; - rdp_settings->shell = guac_rdp_strdup(guac_settings->initial_program); - rdp_settings->kbd_layout = guac_settings->server_layout->freerdp_keyboard_layout; -#else rdp_settings->ColorDepth = guac_settings->color_depth; rdp_settings->DesktopWidth = guac_settings->width; rdp_settings->DesktopHeight = guac_settings->height; rdp_settings->AlternateShell = guac_rdp_strdup(guac_settings->initial_program); rdp_settings->KeyboardLayout = guac_settings->server_layout->freerdp_keyboard_layout; -#endif /* Performance flags */ -#ifdef LEGACY_RDPSETTINGS - - /* Explicitly set flag value */ - rdp_settings->performance_flags = guac_rdp_get_performance_flags(guac_settings); - - /* Set individual flags - some FreeRDP versions overwrite the above */ - rdp_settings->smooth_fonts = guac_settings->font_smoothing_enabled; - rdp_settings->disable_wallpaper = !guac_settings->wallpaper_enabled; - rdp_settings->disable_full_window_drag = !guac_settings->full_window_drag_enabled; - rdp_settings->disable_menu_animations = !guac_settings->menu_animations_enabled; - rdp_settings->disable_theming = !guac_settings->theming_enabled; - rdp_settings->desktop_composition = guac_settings->desktop_composition_enabled; - -#else - /* Explicitly set flag value */ rdp_settings->PerformanceFlags = guac_rdp_get_performance_flags(guac_settings); @@ -1238,49 +1169,21 @@ void guac_rdp_push_settings(guac_client* client, rdp_settings->DisableThemes = !guac_settings->theming_enabled; rdp_settings->AllowDesktopComposition = guac_settings->desktop_composition_enabled; -#endif - /* Client name */ if (guac_settings->client_name != NULL) { -#ifdef LEGACY_RDPSETTINGS - guac_strlcpy(rdp_settings->client_hostname, guac_settings->client_name, - RDP_CLIENT_HOSTNAME_SIZE); -#else guac_strlcpy(rdp_settings->ClientHostname, guac_settings->client_name, RDP_CLIENT_HOSTNAME_SIZE); -#endif } /* Console */ -#ifdef LEGACY_RDPSETTINGS - rdp_settings->console_session = guac_settings->console; - rdp_settings->console_audio = guac_settings->console_audio; -#else rdp_settings->ConsoleSession = guac_settings->console; rdp_settings->RemoteConsoleAudio = guac_settings->console_audio; -#endif /* Audio */ -#ifdef LEGACY_RDPSETTINGS -#ifdef HAVE_RDPSETTINGS_AUDIOPLAYBACK - rdp_settings->audio_playback = guac_settings->audio_enabled; -#endif -#else -#ifdef HAVE_RDPSETTINGS_AUDIOPLAYBACK rdp_settings->AudioPlayback = guac_settings->audio_enabled; -#endif -#endif /* Audio capture */ -#ifdef LEGACY_RDPSETTINGS -#ifdef HAVE_RDPSETTINGS_AUDIOCAPTURE - rdp_settings->audio_capture = guac_settings->enable_audio_input; -#endif -#else -#ifdef HAVE_RDPSETTINGS_AUDIOCAPTURE rdp_settings->AudioCapture = guac_settings->enable_audio_input; -#endif -#endif /* Timezone redirection */ if (guac_settings->timezone) { @@ -1292,35 +1195,15 @@ void guac_rdp_push_settings(guac_client* client, } /* Device redirection */ -#ifdef LEGACY_RDPSETTINGS -#ifdef HAVE_RDPSETTINGS_DEVICEREDIRECTION - rdp_settings->device_redirection = guac_settings->audio_enabled - || guac_settings->drive_enabled - || guac_settings->printing_enabled; -#endif -#else -#ifdef HAVE_RDPSETTINGS_DEVICEREDIRECTION rdp_settings->DeviceRedirection = guac_settings->audio_enabled || guac_settings->drive_enabled || guac_settings->printing_enabled; -#endif -#endif /* Security */ switch (guac_settings->security_mode) { /* Standard RDP encryption */ case GUAC_SECURITY_RDP: -#ifdef LEGACY_RDPSETTINGS - rdp_settings->rdp_security = TRUE; - rdp_settings->tls_security = FALSE; - rdp_settings->nla_security = FALSE; - rdp_settings->encryption_level = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; - rdp_settings->encryption_method = - ENCRYPTION_METHOD_40BIT - | ENCRYPTION_METHOD_128BIT - | ENCRYPTION_METHOD_FIPS; -#else rdp_settings->RdpSecurity = TRUE; rdp_settings->TlsSecurity = FALSE; rdp_settings->NlaSecurity = FALSE; @@ -1329,78 +1212,46 @@ void guac_rdp_push_settings(guac_client* client, ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS; -#endif break; /* TLS encryption */ case GUAC_SECURITY_TLS: -#ifdef LEGACY_RDPSETTINGS - rdp_settings->rdp_security = FALSE; - rdp_settings->tls_security = TRUE; - rdp_settings->nla_security = FALSE; -#else rdp_settings->RdpSecurity = FALSE; rdp_settings->TlsSecurity = TRUE; rdp_settings->NlaSecurity = FALSE; -#endif break; /* Network level authentication */ case GUAC_SECURITY_NLA: -#ifdef LEGACY_RDPSETTINGS - rdp_settings->rdp_security = FALSE; - rdp_settings->tls_security = FALSE; - rdp_settings->nla_security = TRUE; -#else rdp_settings->RdpSecurity = FALSE; rdp_settings->TlsSecurity = FALSE; rdp_settings->NlaSecurity = TRUE; -#endif break; /* All security types */ case GUAC_SECURITY_ANY: -#ifdef LEGACY_RDPSETTINGS - rdp_settings->rdp_security = TRUE; - rdp_settings->tls_security = TRUE; - rdp_settings->nla_security = TRUE; -#else rdp_settings->RdpSecurity = TRUE; rdp_settings->TlsSecurity = TRUE; rdp_settings->NlaSecurity = TRUE; -#endif break; } /* Authentication */ -#ifdef LEGACY_RDPSETTINGS - rdp_settings->authentication = !guac_settings->disable_authentication; - rdp_settings->ignore_certificate = guac_settings->ignore_certificate; - rdp_settings->encryption = TRUE; -#else rdp_settings->Authentication = !guac_settings->disable_authentication; rdp_settings->IgnoreCertificate = guac_settings->ignore_certificate; rdp_settings->DisableEncryption = FALSE; -#endif /* RemoteApp */ if (guac_settings->remote_app != NULL) { -#ifdef LEGACY_RDPSETTINGS - rdp_settings->workarea = TRUE; - rdp_settings->remote_app = TRUE; - rdp_settings->rail_langbar_supported = TRUE; -#else rdp_settings->Workarea = TRUE; rdp_settings->RemoteApplicationMode = TRUE; rdp_settings->RemoteAppLanguageBarSupported = TRUE; rdp_settings->RemoteApplicationProgram = guac_settings->remote_app; rdp_settings->ShellWorkingDirectory = guac_rdp_strdup(guac_settings->remote_app_dir); rdp_settings->RemoteApplicationCmdLine = guac_settings->remote_app_args; -#endif } -#ifdef HAVE_RDPSETTINGS_SENDPRECONNECTIONPDU /* Preconnection ID */ if (guac_settings->preconnection_id != -1) { rdp_settings->NegotiateSecurityLayer = FALSE; @@ -1414,9 +1265,7 @@ void guac_rdp_push_settings(guac_client* client, rdp_settings->SendPreconnectionPdu = TRUE; rdp_settings->PreconnectionBlob = guac_settings->preconnection_blob; } -#endif -#ifdef HAVE_FREERDP_GATEWAY_SUPPORT /* Enable use of RD gateway if a gateway hostname is provided */ if (guac_settings->gateway_hostname != NULL) { @@ -1434,49 +1283,14 @@ void guac_rdp_push_settings(guac_client* client, rdp_settings->GatewayPassword = guac_rdp_strdup(guac_settings->gateway_password); } -#endif -#ifdef HAVE_FREERDP_LOAD_BALANCER_SUPPORT /* Store load balance info (and calculate length) if provided */ if (guac_settings->load_balance_info != NULL) { rdp_settings->LoadBalanceInfo = (BYTE*) guac_rdp_strdup(guac_settings->load_balance_info); rdp_settings->LoadBalanceInfoLength = strlen(guac_settings->load_balance_info); } -#endif /* Order support */ -#ifdef LEGACY_RDPSETTINGS - rdp_settings->bitmap_cache = bitmap_cache; - rdp_settings->offscreen_bitmap_cache = !guac_settings->disable_offscreen_caching; - rdp_settings->glyph_cache = !guac_settings->disable_glyph_caching; - rdp_settings->os_major_type = OSMAJORTYPE_UNSPECIFIED; - rdp_settings->os_minor_type = OSMINORTYPE_UNSPECIFIED; - rdp_settings->desktop_resize = TRUE; - rdp_settings->order_support[NEG_DSTBLT_INDEX] = TRUE; - rdp_settings->order_support[NEG_PATBLT_INDEX] = FALSE; /* PATBLT not yet supported */ - rdp_settings->order_support[NEG_SCRBLT_INDEX] = TRUE; - rdp_settings->order_support[NEG_OPAQUE_RECT_INDEX] = TRUE; - rdp_settings->order_support[NEG_DRAWNINEGRID_INDEX] = FALSE; - rdp_settings->order_support[NEG_MULTIDSTBLT_INDEX] = FALSE; - rdp_settings->order_support[NEG_MULTIPATBLT_INDEX] = FALSE; - rdp_settings->order_support[NEG_MULTISCRBLT_INDEX] = FALSE; - rdp_settings->order_support[NEG_MULTIOPAQUERECT_INDEX] = FALSE; - rdp_settings->order_support[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE; - rdp_settings->order_support[NEG_LINETO_INDEX] = FALSE; - rdp_settings->order_support[NEG_POLYLINE_INDEX] = FALSE; - rdp_settings->order_support[NEG_MEMBLT_INDEX] = bitmap_cache; - rdp_settings->order_support[NEG_MEM3BLT_INDEX] = FALSE; - rdp_settings->order_support[NEG_MEMBLT_V2_INDEX] = bitmap_cache; - rdp_settings->order_support[NEG_MEM3BLT_V2_INDEX] = FALSE; - rdp_settings->order_support[NEG_SAVEBITMAP_INDEX] = FALSE; - rdp_settings->order_support[NEG_GLYPH_INDEX_INDEX] = TRUE; - rdp_settings->order_support[NEG_FAST_INDEX_INDEX] = TRUE; - rdp_settings->order_support[NEG_FAST_GLYPH_INDEX] = TRUE; - rdp_settings->order_support[NEG_POLYGON_SC_INDEX] = FALSE; - rdp_settings->order_support[NEG_POLYGON_CB_INDEX] = FALSE; - rdp_settings->order_support[NEG_ELLIPSE_SC_INDEX] = FALSE; - rdp_settings->order_support[NEG_ELLIPSE_CB_INDEX] = FALSE; -#else rdp_settings->BitmapCacheEnabled = bitmap_cache; rdp_settings->OffscreenSupportLevel = !guac_settings->disable_offscreen_caching; rdp_settings->GlyphSupportLevel = !guac_settings->disable_glyph_caching ? GLYPH_SUPPORT_FULL : GLYPH_SUPPORT_NONE; @@ -1507,7 +1321,6 @@ void guac_rdp_push_settings(guac_client* client, rdp_settings->OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE; rdp_settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE; rdp_settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE; -#endif } diff --git a/src/protocols/rdp/rdp_settings.h b/src/protocols/rdp/rdp_settings.h index 6955ed58..0d655f6b 100644 --- a/src/protocols/rdp/rdp_settings.h +++ b/src/protocols/rdp/rdp_settings.h @@ -466,7 +466,6 @@ typedef struct guac_rdp_settings { */ int enable_audio_input; -#ifdef HAVE_FREERDP_GATEWAY_SUPPORT /** * The hostname of the remote desktop gateway that should be used as an * intermediary for the remote desktop connection. If no gateway should @@ -501,15 +500,12 @@ typedef struct guac_rdp_settings { * gateway, if a gateway is being used. */ char* gateway_password; -#endif -#ifdef HAVE_FREERDP_LOAD_BALANCER_SUPPORT /** * The load balancing information/cookie which should be provided to * the connection broker, if a connection broker is being used. */ char* load_balance_info; -#endif } guac_rdp_settings; diff --git a/src/protocols/rdp/rdp_stream.c b/src/protocols/rdp/rdp_stream.c index 533ff07e..bf7222e3 100644 --- a/src/protocols/rdp/rdp_stream.c +++ b/src/protocols/rdp/rdp_stream.c @@ -28,25 +28,14 @@ #include #include +#include #include #include #include #include #include - -#ifdef HAVE_FREERDP_CLIENT_CLIPRDR_H -#include -#else -#include "compat/client-cliprdr.h" -#endif - -#ifdef ENABLE_WINPR #include #include -#else -#include "compat/winpr-stream.h" -#include "compat/winpr-wtypes.h" -#endif #include diff --git a/src/protocols/rdp/rdp_svc.c b/src/protocols/rdp/rdp_svc.c index 0a6eb246..97434991 100644 --- a/src/protocols/rdp/rdp_svc.c +++ b/src/protocols/rdp/rdp_svc.c @@ -26,12 +26,7 @@ #include #include #include - -#ifdef ENABLE_WINPR #include -#else -#include "compat/winpr-stream.h" -#endif #include From 554251cc72e84c3545a454e81f292711e7b989a7 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 21 Sep 2019 16:09:50 -0700 Subject: [PATCH 003/109] GUACAMOLE-249: Remove usage of CLRCONV. --- src/protocols/rdp/rdp.c | 11 ------ src/protocols/rdp/rdp.h | 7 ---- src/protocols/rdp/rdp_bitmap.c | 22 ++++++----- src/protocols/rdp/rdp_color.c | 52 +++++++++++++++++++++++--- src/protocols/rdp/rdp_gdi.c | 65 --------------------------------- src/protocols/rdp/rdp_pointer.c | 14 +++---- 6 files changed, 66 insertions(+), 105 deletions(-) diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 97807934..01ceabac 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -130,7 +130,6 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { rdpGlyph* glyph; rdpPointer* pointer; rdpPrimaryUpdate* primary; - CLRCONV* clrconv; guac_rdp_dvc_list* dvc_list = guac_rdp_dvc_list_alloc(); @@ -227,14 +226,6 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { /* Dynamic virtual channel list is no longer needed */ guac_rdp_dvc_list_free(dvc_list); - /* Init color conversion structure */ - clrconv = calloc(1, sizeof(CLRCONV)); - clrconv->alpha = 1; - clrconv->invert = 0; - clrconv->rgb555 = 0; - clrconv->palette = calloc(1, sizeof(rdpPalette)); - ((rdp_freerdp_context*) context)->clrconv = clrconv; - /* Init FreeRDP cache */ instance->context->cache = cache_new(instance->settings); @@ -274,7 +265,6 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { /* Set up GDI */ instance->update->DesktopResize = guac_rdp_gdi_desktop_resize; instance->update->EndPaint = guac_rdp_gdi_end_paint; - instance->update->Palette = guac_rdp_gdi_palette_update; instance->update->SetBounds = guac_rdp_gdi_set_bounds; primary = instance->update->primary; @@ -740,7 +730,6 @@ static int guac_rdp_handle_connection(guac_client* client) { freerdp_disconnect(rdp_inst); /* Clean up RDP client context */ - freerdp_clrconv_free(((rdp_freerdp_context*) rdp_inst->context)->clrconv); cache_free(rdp_inst->context->cache); freerdp_context_free(rdp_inst); diff --git a/src/protocols/rdp/rdp.h b/src/protocols/rdp/rdp.h index ec0f939d..5d181a18 100644 --- a/src/protocols/rdp/rdp.h +++ b/src/protocols/rdp/rdp.h @@ -191,13 +191,6 @@ typedef struct rdp_freerdp_context { */ guac_client* client; -#if 0 - /** - * Color conversion structure to be used to convert RDP images to PNGs. - */ - CLRCONV* clrconv; -#endif - /** * The current color palette, as received from the RDP server. */ diff --git a/src/protocols/rdp/rdp_bitmap.c b/src/protocols/rdp/rdp_bitmap.c index e6343d49..b6c126c7 100644 --- a/src/protocols/rdp/rdp_bitmap.c +++ b/src/protocols/rdp/rdp_bitmap.c @@ -74,19 +74,21 @@ BOOL guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap) { /* Convert image data if present */ if (bitmap->data != NULL && bitmap->bpp != 32) { - /* Convert image data to 32-bit RGB */ - unsigned char* image_buffer = freerdp_image_convert(bitmap->data, NULL, - bitmap->width, bitmap->height, - guac_rdp_get_depth(context->instance), - 32, ((rdp_freerdp_context*) context)->clrconv); + /* Allocate sufficient space for converted image */ + unsigned char* image_buffer = _aligned_malloc(bitmap->width * bitmap->height * 4, 16); - /* Free existing image, if any */ - if (image_buffer != bitmap->data) { - _aligned_free(bitmap->data); + /* Attempt image conversion */ + if (!freerdp_image_copy(image_buffer, PIXEL_FORMAT_ARGB32, 0, 0, 0, + bitmap->width, bitmap->height, bitmap->data, bitmap->format, + 0, 0, 0, &context->gdi->palette, FREERDP_FLIP_NONE)) { + _aligned_free(image_buffer); } - /* Store converted image in bitmap */ - bitmap->data = image_buffer; + /* If successful, replace original image with converted image */ + else { + _aligned_free(bitmap->data); + bitmap->data = image_buffer; + } } diff --git a/src/protocols/rdp/rdp_color.c b/src/protocols/rdp/rdp_color.c index 98345a12..b2d0d0bc 100644 --- a/src/protocols/rdp/rdp_color.c +++ b/src/protocols/rdp/rdp_color.c @@ -27,13 +27,55 @@ #include #include -UINT32 guac_rdp_convert_color(rdpContext* context, UINT32 color) { +/** + * Returns the integer constant used by the FreeRDP API to represent the colors + * used by a connection having the given bit depth. These constants each have + * corresponding PIXEL_FORMAT_* macros defined within freerdp/codec/color.h. + * + * @param depth + * The color depth which should be translated into the integer constant + * defined by FreeRDP's corresponding PIXEL_FORMAT_* macro. + * + * @return + * The integer value of the PIXEL_FORMAT_* macro corresponding to the + * given color depth. + */ +static UINT32 guac_rdp_get_pixel_format(int depth) { - CLRCONV* clrconv = ((rdp_freerdp_context*) context)->clrconv; + switch (depth) { - /* Convert given color to ARGB32 */ - return freerdp_color_convert_drawing_order_color_to_gdi_color(color, - guac_rdp_get_depth(context->instance), clrconv); + /* 32- and 24-bit RGB (8 bits per color component) */ + case 32: + case 24: + return PIXEL_FORMAT_BGR24; + + /* 16-bit palette (6-bit green, 5-bit red and blue) */ + case 16: + return PIXEL_FORMAT_RGB16; + + /* 15-bit RGB (5 bits per color component) */ + case 15: + return PIXEL_FORMAT_RGB15; + + /* 8-bit palette */ + case 8: + return PIXEL_FORMAT_RGB8; + + } + + /* Unknown format */ + return PIXEL_FORMAT_BGR24; + +} + +UINT32 guac_rdp_convert_color(rdpContext* context, UINT32 color) { + + int depth = guac_rdp_get_depth(context->instance); + rdpGdi* gdi = context->gdi; + + /* Convert given color to ARGB32 */ + return FreeRDPConvertColor(color, guac_rdp_get_pixel_format(depth), + PIXEL_FORMAT_ARGB32, &gdi->palette); } diff --git a/src/protocols/rdp/rdp_gdi.c b/src/protocols/rdp/rdp_gdi.c index 7ea64cae..fef672c1 100644 --- a/src/protocols/rdp/rdp_gdi.c +++ b/src/protocols/rdp/rdp_gdi.c @@ -340,71 +340,6 @@ void guac_rdp_gdi_opaquerect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect } -#if 0 -/** - * Updates the palette within a FreeRDP CLRCONV object using the new palette - * entries provided by an RDP palette update. - * - * @param clrconv - * The FreeRDP CLRCONV object to update. - * - * @param palette - * An RDP palette update message containing the palette to store within the - * given CLRCONV object. - */ -static void guac_rdp_update_clrconv(CLRCONV* clrconv, - PALETTE_UPDATE* palette) { - - clrconv->palette->count = palette->number; - memcpy(clrconv->palette->entries, palette->entries, - sizeof(palette->entries)); - -} -#endif - -/** - * Updates a raw ARGB32 palette using the new palette entries provided by an - * RDP palette update. - * - * @param guac_palette - * An array of 256 ARGB32 colors, with each entry corresponding to an - * entry in the color palette. - * - * @param palette - * An RDP palette update message containing the palette to store within the - * given array of ARGB32 colors. - */ -static void guac_rdp_update_palette(UINT32* guac_palette, - PALETTE_UPDATE* palette) { - - PALETTE_ENTRY* entry = palette->entries; - int i; - - /* Copy each palette entry as ARGB32 */ - for (i=0; i < palette->number; i++) { - - *guac_palette = 0xFF000000 - | (entry->red << 16) - | (entry->green << 8) - | entry->blue; - - guac_palette++; - entry++; - } - -} - -void guac_rdp_gdi_palette_update(rdpContext* context, PALETTE_UPDATE* palette) { -#if 0 - CLRCONV* clrconv = ((rdp_freerdp_context*) context)->clrconv; - UINT32* guac_palette = ((rdp_freerdp_context*) context)->palette; - - /* Update internal palette representations */ - guac_rdp_update_clrconv(clrconv, palette); - guac_rdp_update_palette(guac_palette, palette); -#endif -} - void guac_rdp_gdi_set_bounds(rdpContext* context, rdpBounds* bounds) { guac_client* client = ((rdp_freerdp_context*) context)->client; diff --git a/src/protocols/rdp/rdp_pointer.c b/src/protocols/rdp/rdp_pointer.c index fae8ed01..303b6ef0 100644 --- a/src/protocols/rdp/rdp_pointer.c +++ b/src/protocols/rdp/rdp_pointer.c @@ -41,17 +41,17 @@ void guac_rdp_pointer_new(rdpContext* context, rdpPointer* pointer) { rdp_client->display, pointer->width, pointer->height); /* Allocate data for image */ - unsigned char* data = - (unsigned char*) malloc(pointer->width * pointer->height * 4); + unsigned char* data = _aligned_malloc(pointer->width * pointer->height * 4, 16); cairo_surface_t* surface; /* Convert to alpha cursor if mask data present */ if (pointer->andMaskData && pointer->xorMaskData) - freerdp_alpha_cursor_convert(data, - pointer->xorMaskData, pointer->andMaskData, - pointer->width, pointer->height, pointer->xorBpp, - ((rdp_freerdp_context*) context)->clrconv); + freerdp_image_copy_from_pointer_data(data, 0, 0, 0, + pointer->width, pointer->height, + pointer->xorMaskData, pointer->lengthXorMask, + pointer->andMaskData, pointer->lengthAndMask, + pointer->xorBpp, &context->gdi->palette); /* Create surface from image data */ surface = cairo_image_surface_create_for_data( @@ -63,7 +63,7 @@ void guac_rdp_pointer_new(rdpContext* context, rdpPointer* pointer) { /* Free surface */ cairo_surface_destroy(surface); - free(data); + _aligned_free(data); /* Remember buffer */ ((guac_rdp_pointer*) pointer)->layer = buffer; From 9b08a716d615dc1bdc47b6bff7f640a621211665 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 21 Sep 2019 20:59:04 -0700 Subject: [PATCH 004/109] GUACAMOLE-249: Comment out remaining usage of SVC. --- src/protocols/rdp/rdp.c | 2 ++ src/protocols/rdp/rdp_stream.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 01ceabac..7b0644b2 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -189,6 +189,7 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { } +#if 0 /* Load SVC plugin instances for all static channels */ if (settings->svc_names != NULL) { @@ -216,6 +217,7 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { } while (*(++current) != NULL); } +#endif /* Load DRDYNVC plugin if required */ if (guac_rdp_load_drdynvc(instance->context, dvc_list)) diff --git a/src/protocols/rdp/rdp_stream.c b/src/protocols/rdp/rdp_stream.c index bf7222e3..609eeaaf 100644 --- a/src/protocols/rdp/rdp_stream.c +++ b/src/protocols/rdp/rdp_stream.c @@ -23,7 +23,9 @@ #include "common/clipboard.h" #include "rdp.h" #include "rdp_fs.h" +#if 0 #include "rdp_svc.h" +#endif #include "rdp_stream.h" #include From e4a68d776fdcb68f29fb4269914df6b6c037ea91 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 22 Sep 2019 11:09:44 -0700 Subject: [PATCH 005/109] GUACAMOLE-249: Correct prototypes of glyph handlers. --- src/protocols/rdp/rdp_glyph.c | 11 ++++++----- src/protocols/rdp/rdp_glyph.h | 11 ++++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/protocols/rdp/rdp_glyph.c b/src/protocols/rdp/rdp_glyph.c index 6bb8f59d..01ea7d4d 100644 --- a/src/protocols/rdp/rdp_glyph.c +++ b/src/protocols/rdp/rdp_glyph.c @@ -95,7 +95,7 @@ BOOL guac_rdp_glyph_new(rdpContext* context, const rdpGlyph* glyph) { } BOOL guac_rdp_glyph_draw(rdpContext* context, const rdpGlyph* glyph, - UINT32 x, UINT32 y, UINT32 w, UINT32 h, UINT32 sx, UINT32 sy, + INT32 x, INT32 y, INT32 w, INT32 h, INT32 sx, INT32 sy, BOOL redundant); guac_client* client = ((rdp_freerdp_context*) context)->client; @@ -124,8 +124,9 @@ void guac_rdp_glyph_free(rdpContext* context, rdpGlyph* glyph) { } -BOOL guac_rdp_glyph_begindraw(rdpContext* context, - UINT32 x, UINT32 y, UINT32 width, UINT32 height, UINT32 fgcolor, UINT32 bgcolor, BOOL redundant) { +BOOL guac_rdp_glyph_begindraw(rdpContext* context, INT32 x, INT32 y, + INT32 width, INT32 height, UINT32 fgcolor, UINT32 bgcolor, + BOOL redundant) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = @@ -153,8 +154,8 @@ BOOL guac_rdp_glyph_begindraw(rdpContext* context, } -BOOL guac_rdp_glyph_enddraw(rdpContext* context, - UINT32 x, UINT32 y, UINT32 width, UINT32 height, UINT32 fgcolor, UINT32 bgcolor) { +BOOL guac_rdp_glyph_enddraw(rdpContext* context, INT32 x, INT32 y, + INT32 width, INT32 height, UINT32 fgcolor, UINT32 bgcolor) { /* IGNORE */ return TRUE; } diff --git a/src/protocols/rdp/rdp_glyph.h b/src/protocols/rdp/rdp_glyph.h index 10b79cd2..c14efbbc 100644 --- a/src/protocols/rdp/rdp_glyph.h +++ b/src/protocols/rdp/rdp_glyph.h @@ -73,7 +73,7 @@ BOOL guac_rdp_glyph_new(rdpContext* context, const rdpGlyph* glyph); * The destination Y coordinate of the upper-left corner of the glyph. */ BOOL guac_rdp_glyph_draw(rdpContext* context, const rdpGlyph* glyph, - UINT32 x, UINT32 y, UINT32 w, UINT32 h, UINT32 sx, UINT32 sy, + INT32 x, INT32 y, INT32 w, INT32 h, INT32 sx, INT32 sy, BOOL redundant); /** @@ -123,8 +123,9 @@ void guac_rdp_glyph_free(rdpContext* context, rdpGlyph* glyph); * be translated via guac_rdp_convert_color(). If the background is * transparent, this value is undefined. */ -BOOL guac_rdp_glyph_begindraw(rdpContext* context, - UINT32 x, UINT32 y, UINT32 width, UINT32 height, UINT32 fgcolor, UINT32 bgcolor, BOOL redundant); +BOOL guac_rdp_glyph_begindraw(rdpContext* context, INT32 x, INT32 y, + INT32 width, INT32 height, UINT32 fgcolor, UINT32 bgcolor, + BOOL redundant); /** * Called immediately after rendering a series of glyphs. Unlike @@ -160,7 +161,7 @@ BOOL guac_rdp_glyph_begindraw(rdpContext* context, * be translated via guac_rdp_convert_color(). If the background is * transparent, this value is undefined. */ -BOOL guac_rdp_glyph_enddraw(rdpContext* context, - UINT32 x, UINT32 y, UINT32 width, UINT32 height, UINT32 fgcolor, UINT32 bgcolor); +BOOL guac_rdp_glyph_enddraw(rdpContext* context, INT32 x, INT32 y, + INT32 width, INT32 height, UINT32 fgcolor, UINT32 bgcolor); #endif From fbfbaff54011656294bfc0f1bbff0c433734f977 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 22 Sep 2019 11:10:01 -0700 Subject: [PATCH 006/109] GUACAMOLE-249: Correct prototypes of pointer handlers. --- src/protocols/rdp/rdp_pointer.c | 8 ++++++-- src/protocols/rdp/rdp_pointer.h | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/protocols/rdp/rdp_pointer.c b/src/protocols/rdp/rdp_pointer.c index 303b6ef0..d475a2c8 100644 --- a/src/protocols/rdp/rdp_pointer.c +++ b/src/protocols/rdp/rdp_pointer.c @@ -31,7 +31,7 @@ #include -void guac_rdp_pointer_new(rdpContext* context, rdpPointer* pointer) { +BOOL guac_rdp_pointer_new(rdpContext* context, rdpPointer* pointer) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; @@ -68,9 +68,11 @@ void guac_rdp_pointer_new(rdpContext* context, rdpPointer* pointer) { /* Remember buffer */ ((guac_rdp_pointer*) pointer)->layer = buffer; + return TRUE; + } -void guac_rdp_pointer_set(rdpContext* context, rdpPointer* pointer) { +BOOL guac_rdp_pointer_set(rdpContext* context, const rdpPointer* pointer) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; @@ -80,6 +82,8 @@ void guac_rdp_pointer_set(rdpContext* context, rdpPointer* pointer) { pointer->xPos, pointer->yPos, ((guac_rdp_pointer*) pointer)->layer->surface); + return TRUE; + } void guac_rdp_pointer_free(rdpContext* context, rdpPointer* pointer) { diff --git a/src/protocols/rdp/rdp_pointer.h b/src/protocols/rdp/rdp_pointer.h index 4ce98777..d3809e92 100644 --- a/src/protocols/rdp/rdp_pointer.h +++ b/src/protocols/rdp/rdp_pointer.h @@ -53,7 +53,7 @@ typedef struct guac_rdp_pointer { * @param pointer * The pointer to cache. */ -void guac_rdp_pointer_new(rdpContext* context, rdpPointer* pointer); +BOOL guac_rdp_pointer_new(rdpContext* context, rdpPointer* pointer); /** * Sets the given cached pointer as the current pointer. The given pointer must @@ -65,7 +65,7 @@ void guac_rdp_pointer_new(rdpContext* context, rdpPointer* pointer); * @param pointer * The pointer to set as the current mouse pointer. */ -void guac_rdp_pointer_set(rdpContext* context, rdpPointer* pointer); +BOOL guac_rdp_pointer_set(rdpContext* context, const rdpPointer* pointer); /** * Frees all Guacamole-related data associated with the given pointer, allowing From 82664b4e6bc68a3c5c0ba95bc9f6cc72436a0918 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 22 Sep 2019 11:16:55 -0700 Subject: [PATCH 007/109] GUACAMOLE-249: Correct prototypes of GDI handlers. --- src/protocols/rdp/rdp_gdi.c | 31 +++++++++++++++++++++++-------- src/protocols/rdp/rdp_gdi.h | 29 +++++++++-------------------- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/src/protocols/rdp/rdp_gdi.c b/src/protocols/rdp/rdp_gdi.c index fef672c1..c3332f6a 100644 --- a/src/protocols/rdp/rdp_gdi.c +++ b/src/protocols/rdp/rdp_gdi.c @@ -92,7 +92,7 @@ guac_transfer_function guac_rdp_rop3_transfer_function(guac_client* client, } -void guac_rdp_gdi_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt) { +BOOL guac_rdp_gdi_dstblt(rdpContext* context, const DSTBLT_ORDER* dstblt) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_common_surface* current_surface = ((guac_rdp_client*) client->data)->current_surface; @@ -135,9 +135,11 @@ void guac_rdp_gdi_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt) { } + return TRUE; + } -void guac_rdp_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) { +BOOL guac_rdp_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) { /* * Note that this is not a full implementation of PATBLT. This is a @@ -203,9 +205,11 @@ void guac_rdp_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) { } + return TRUE; + } -void guac_rdp_gdi_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt) { +BOOL guac_rdp_gdi_scrblt(rdpContext* context, const SCRBLT_ORDER* scrblt) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_common_surface* current_surface = ((guac_rdp_client*) client->data)->current_surface; @@ -224,9 +228,11 @@ void guac_rdp_gdi_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt) { guac_common_surface_copy(rdp_client->display->default_surface, x_src, y_src, w, h, current_surface, x, y); + return TRUE; + } -void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) { +BOOL guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_common_surface* current_surface = ((guac_rdp_client*) client->data)->current_surface; @@ -316,9 +322,11 @@ void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) { } + return TRUE; + } -void guac_rdp_gdi_opaquerect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect) { +BOOL guac_rdp_gdi_opaquerect(rdpContext* context, const OPAQUE_RECT_ORDER* opaque_rect) { /* Get client data */ guac_client* client = ((rdp_freerdp_context*) context)->client; @@ -338,9 +346,11 @@ void guac_rdp_gdi_opaquerect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect (color ) & 0xFF, 0xFF); + return TRUE; + } -void guac_rdp_gdi_set_bounds(rdpContext* context, rdpBounds* bounds) { +BOOL guac_rdp_gdi_set_bounds(rdpContext* context, const rdpBounds* bounds) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; @@ -356,13 +366,16 @@ void guac_rdp_gdi_set_bounds(rdpContext* context, rdpBounds* bounds) { bounds->right - bounds->left + 1, bounds->bottom - bounds->top + 1); + return TRUE; + } -void guac_rdp_gdi_end_paint(rdpContext* context) { +BOOL guac_rdp_gdi_end_paint(rdpContext* context) { /* IGNORE */ + return TRUE; } -void guac_rdp_gdi_desktop_resize(rdpContext* context) { +BOOL guac_rdp_gdi_desktop_resize(rdpContext* context) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; @@ -377,6 +390,8 @@ void guac_rdp_gdi_desktop_resize(rdpContext* context) { guac_rdp_get_width(context->instance), guac_rdp_get_height(context->instance)); + return TRUE; + } diff --git a/src/protocols/rdp/rdp_gdi.h b/src/protocols/rdp/rdp_gdi.h index cbe3c753..29d29478 100644 --- a/src/protocols/rdp/rdp_gdi.h +++ b/src/protocols/rdp/rdp_gdi.h @@ -54,7 +54,7 @@ guac_composite_mode guac_rdp_rop3_transfer_function(guac_client* client, * @param dstblt * The DSTBLT update to handle. */ -void guac_rdp_gdi_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt); +BOOL guac_rdp_gdi_dstblt(rdpContext* context, const DSTBLT_ORDER* dstblt); /** * Handler for RDP PATBLT update. @@ -65,7 +65,7 @@ void guac_rdp_gdi_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt); * @param patblt * The PATBLT update to handle. */ -void guac_rdp_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt); +BOOL guac_rdp_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt); /** * Handler for RDP SCRBLT update. @@ -76,7 +76,7 @@ void guac_rdp_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt); * @param scrblt * The SCRBLT update to handle. */ -void guac_rdp_gdi_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt); +BOOL guac_rdp_gdi_scrblt(rdpContext* context, const SCRBLT_ORDER* scrblt); /** * Handler for RDP MEMBLT update. @@ -87,7 +87,7 @@ void guac_rdp_gdi_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt); * @param memblt * The MEMBLT update to handle. */ -void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt); +BOOL guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt); /** * Handler for RDP OPAQUE RECT update. @@ -98,19 +98,8 @@ void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt); * @param opaque_rect * The OPAQUE RECT update to handle. */ -void guac_rdp_gdi_opaquerect(rdpContext* context, - OPAQUE_RECT_ORDER* opaque_rect); - -/** - * Handler called when the remote color palette is changing. - * - * @param context - * The rdpContext associated with the current RDP session. - * - * @param palette - * The PALETTE update containing the new palette. - */ -void guac_rdp_gdi_palette_update(rdpContext* context, PALETTE_UPDATE* palette); +BOOL guac_rdp_gdi_opaquerect(rdpContext* context, + const OPAQUE_RECT_ORDER* opaque_rect); /** * Handler called prior to calling the handlers for specific updates when @@ -125,7 +114,7 @@ void guac_rdp_gdi_palette_update(rdpContext* context, PALETTE_UPDATE* palette); * The clipping rectangle to set, or NULL to remove any applied clipping * rectangle. */ -void guac_rdp_gdi_set_bounds(rdpContext* context, rdpBounds* bounds); +BOOL guac_rdp_gdi_set_bounds(rdpContext* context, const rdpBounds* bounds); /** * Handler called when a paint operation is complete. We don't actually @@ -134,7 +123,7 @@ void guac_rdp_gdi_set_bounds(rdpContext* context, rdpBounds* bounds); * @param context * The rdpContext associated with the current RDP session. */ -void guac_rdp_gdi_end_paint(rdpContext* context); +BOOL guac_rdp_gdi_end_paint(rdpContext* context); /** * Handler called when the desktop dimensions change, either from a @@ -148,6 +137,6 @@ void guac_rdp_gdi_end_paint(rdpContext* context); * @param context * The rdpContext associated with the current RDP session. */ -void guac_rdp_gdi_desktop_resize(rdpContext* context); +BOOL guac_rdp_gdi_desktop_resize(rdpContext* context); #endif From 3b560044bcb81202c7fcb837f5f7df59c97bcf0a Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 22 Sep 2019 12:12:26 -0700 Subject: [PATCH 008/109] GUACAMOLE-249: Correct prototype of certificate verification callback. If accepting the certificate, request that FreeRDP not store it. --- src/protocols/rdp/rdp.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 7b0644b2..a9e4b7d6 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -378,8 +378,9 @@ static BOOL rdp_freerdp_authenticate(freerdp* instance, char** username, * @return * TRUE if the certificate passes verification, FALSE otherwise. */ -static BOOL rdp_freerdp_verify_certificate(freerdp* instance, char* subject, - char* issuer, char* fingerprint) { +static DWORD rdp_freerdp_verify_certificate(freerdp* instance, + const char* common_name, const char* subject, const char* issuer, + const char* fingerprint, BOOL host_mismatch) { rdpContext* context = instance->context; guac_client* client = ((rdp_freerdp_context*) context)->client; @@ -389,11 +390,11 @@ static BOOL rdp_freerdp_verify_certificate(freerdp* instance, char* subject, /* Bypass validation if ignore_certificate given */ if (rdp_client->settings->ignore_certificate) { guac_client_log(client, GUAC_LOG_INFO, "Certificate validation bypassed"); - return TRUE; + return 2; /* Accept only for this session */ } guac_client_log(client, GUAC_LOG_INFO, "Certificate validation failed"); - return FALSE; + return 0; /* Reject certificate */ } From 9fa9adbd5899550e497f89d3707a9164f01653dc Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 22 Sep 2019 12:24:16 -0700 Subject: [PATCH 009/109] GUACAMOLE-249: Migrate to libwinpr "CF_*" constants for clipboard formats. The "CB_FORMAT_*" constants which used to be defined by FreeRDP no longer exist. --- src/protocols/rdp/rdp.c | 2 +- src/protocols/rdp/rdp_cliprdr.c | 20 ++++++++++---------- src/protocols/rdp/rdp_stream.c | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index a9e4b7d6..d015d3b5 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -566,7 +566,7 @@ static int guac_rdp_handle_connection(guac_client* client) { rdp_client->current_surface = rdp_client->display->default_surface; - rdp_client->requested_clipboard_format = CB_FORMAT_TEXT; + rdp_client->requested_clipboard_format = CF_TEXT; rdp_client->available_svc = guac_common_list_alloc(); freerdp_channels_global_init(); diff --git a/src/protocols/rdp/rdp_cliprdr.c b/src/protocols/rdp/rdp_cliprdr.c index 620923d8..735d3329 100644 --- a/src/protocols/rdp/rdp_cliprdr.c +++ b/src/protocols/rdp/rdp_cliprdr.c @@ -82,8 +82,8 @@ void guac_rdp_process_cb_monitor_ready(guac_client* client, wMessage* event) { /* Respond with supported format list */ format_list->formats = (UINT32*) malloc(sizeof(UINT32)*2); - format_list->formats[0] = CB_FORMAT_TEXT; - format_list->formats[1] = CB_FORMAT_UNICODETEXT; + format_list->formats[0] = CF_TEXT; + format_list->formats[1] = CF_UNICODETEXT; format_list->num_formats = 2; freerdp_channels_send_event(channels, (wMessage*) format_list); @@ -132,22 +132,22 @@ void guac_rdp_process_cb_format_list(guac_client* client, for (i=0; inum_formats; i++) { /* If plain text available, request it */ - if (event->formats[i] == CB_FORMAT_TEXT) + if (event->formats[i] == CF_TEXT) formats |= GUAC_RDP_CLIPBOARD_FORMAT_CP1252; - else if (event->formats[i] == CB_FORMAT_UNICODETEXT) + else if (event->formats[i] == CF_UNICODETEXT) formats |= GUAC_RDP_CLIPBOARD_FORMAT_UTF16; } /* Prefer Unicode to plain text */ if (formats & GUAC_RDP_CLIPBOARD_FORMAT_UTF16) { - __guac_rdp_cb_request_format(client, CB_FORMAT_UNICODETEXT); + __guac_rdp_cb_request_format(client, CF_UNICODETEXT); return; } /* Use plain text if Unicode unavailable */ if (formats & GUAC_RDP_CLIPBOARD_FORMAT_CP1252) { - __guac_rdp_cb_request_format(client, CB_FORMAT_TEXT); + __guac_rdp_cb_request_format(client, CF_TEXT); return; } @@ -171,11 +171,11 @@ void guac_rdp_process_cb_data_request(guac_client* client, /* Determine output encoding */ switch (event->format) { - case CB_FORMAT_TEXT: + case CF_TEXT: writer = GUAC_WRITE_CP1252; break; - case CB_FORMAT_UNICODETEXT: + case CF_UNICODETEXT: writer = GUAC_WRITE_UTF16; break; @@ -218,12 +218,12 @@ void guac_rdp_process_cb_data_response(guac_client* client, switch (rdp_client->requested_clipboard_format) { /* Non-Unicode */ - case CB_FORMAT_TEXT: + case CF_TEXT: reader = GUAC_READ_CP1252; break; /* Unicode (UTF-16) */ - case CB_FORMAT_UNICODETEXT: + case CF_UNICODETEXT: reader = GUAC_READ_UTF16; break; diff --git a/src/protocols/rdp/rdp_stream.c b/src/protocols/rdp/rdp_stream.c index 609eeaaf..b90b4365 100644 --- a/src/protocols/rdp/rdp_stream.c +++ b/src/protocols/rdp/rdp_stream.c @@ -293,8 +293,8 @@ int guac_rdp_clipboard_end_handler(guac_user* user, guac_stream* stream) { /* Notify server that text data is now available */ format_list->formats = (UINT32*) malloc(sizeof(UINT32) * 2); - format_list->formats[0] = CB_FORMAT_TEXT; - format_list->formats[1] = CB_FORMAT_UNICODETEXT; + format_list->formats[0] = CF_TEXT; + format_list->formats[1] = CF_UNICODETEXT; format_list->num_formats = 2; freerdp_channels_send_event(channels, (wMessage*) format_list); From ad7ab67571ff482bc40e2e15f5d2be242d37ac85 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 22 Sep 2019 14:36:34 -0700 Subject: [PATCH 010/109] GUACAMOLE-249: The freerdp/gdi/gdi.h header is required to access contents of rdpGdi struct. --- src/protocols/rdp/rdp_bitmap.c | 5 +++-- src/protocols/rdp/rdp_color.c | 1 + src/protocols/rdp/rdp_pointer.c | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/protocols/rdp/rdp_bitmap.c b/src/protocols/rdp/rdp_bitmap.c index b6c126c7..a7021124 100644 --- a/src/protocols/rdp/rdp_bitmap.c +++ b/src/protocols/rdp/rdp_bitmap.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -72,13 +73,13 @@ BOOL guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap) { BOOL guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap) { /* Convert image data if present */ - if (bitmap->data != NULL && bitmap->bpp != 32) { + if (bitmap->data != NULL && bitmap->format != PIXEL_FORMAT_XRGB32) { /* Allocate sufficient space for converted image */ unsigned char* image_buffer = _aligned_malloc(bitmap->width * bitmap->height * 4, 16); /* Attempt image conversion */ - if (!freerdp_image_copy(image_buffer, PIXEL_FORMAT_ARGB32, 0, 0, 0, + if (!freerdp_image_copy(image_buffer, PIXEL_FORMAT_XRGB32, 0, 0, 0, bitmap->width, bitmap->height, bitmap->data, bitmap->format, 0, 0, 0, &context->gdi->palette, FREERDP_FLIP_NONE)) { _aligned_free(image_buffer); diff --git a/src/protocols/rdp/rdp_color.c b/src/protocols/rdp/rdp_color.c index b2d0d0bc..1d88089d 100644 --- a/src/protocols/rdp/rdp_color.c +++ b/src/protocols/rdp/rdp_color.c @@ -25,6 +25,7 @@ #include #include +#include #include /** diff --git a/src/protocols/rdp/rdp_pointer.c b/src/protocols/rdp/rdp_pointer.c index d475a2c8..99752448 100644 --- a/src/protocols/rdp/rdp_pointer.c +++ b/src/protocols/rdp/rdp_pointer.c @@ -27,6 +27,7 @@ #include #include +#include #include #include From 703ce5c2234dca1c3dc7c95d72f3c51eb0ea8433 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 29 Sep 2019 14:15:13 -0700 Subject: [PATCH 011/109] GUACAMOLE-249: Remove usage of old FreeRDP channels interface. --- src/protocols/rdp/rdp.c | 70 ----------------------------------------- 1 file changed, 70 deletions(-) diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index d015d3b5..43cca5b3 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -283,39 +283,6 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { offscreen_cache_register_callbacks(instance->update); palette_cache_register_callbacks(instance->update); - /* Init channels (pre-connect) */ - if (freerdp_channels_pre_connect(channels, instance)) { - guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Error initializing RDP client channel manager"); - return FALSE; - } - - return TRUE; - -} - -/** - * Callback invoked by FreeRDP just after the connection is established with - * the RDP server. Implementations are required to manually invoke - * freerdp_channels_post_connect(). - * - * @param instance - * The FreeRDP instance that has just connected. - * - * @return - * TRUE if successful, FALSE if an error occurs. - */ -static BOOL rdp_freerdp_post_connect(freerdp* instance) { - - rdpContext* context = instance->context; - guac_client* client = ((rdp_freerdp_context*) context)->client; - rdpChannels* channels = instance->context->channels; - - /* Init channels (post-connect) */ - if (freerdp_channels_post_connect(channels, instance)) { - guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Error initializing RDP client channel manager"); - return FALSE; - } - return TRUE; } @@ -398,36 +365,6 @@ static DWORD rdp_freerdp_verify_certificate(freerdp* instance, } -/** - * Callback invoked by FreeRDP after a new rdpContext has been allocated and - * associated with the current FreeRDP instance. Implementations are required - * to manually invoke freerdp_channels_new() at this point. - * - * @param instance - * The FreeRDP instance whose context has just been allocated. - * - * @param context - * The newly-allocated FreeRDP context. - */ -static void rdp_freerdp_context_new(freerdp* instance, rdpContext* context) { - context->channels = freerdp_channels_new(); -} - -/** - * Callback invoked by FreeRDP when the rdpContext is being freed. This must be - * provided, but there is no Guacamole-specific data associated with the - * FreeRDP context, so nothing is done here. - * - * @param instance - * The FreeRDP instance whose context is being freed. - * - * @param context - * The FreeRDP context being freed. - */ -static void rdp_freerdp_context_free(freerdp* instance, rdpContext* context) { - /* EMPTY */ -} - /** * Waits for messages from the RDP server for the given number of milliseconds. * @@ -569,20 +506,15 @@ static int guac_rdp_handle_connection(guac_client* client) { rdp_client->requested_clipboard_format = CF_TEXT; rdp_client->available_svc = guac_common_list_alloc(); - freerdp_channels_global_init(); - /* Init client */ freerdp* rdp_inst = freerdp_new(); rdp_inst->PreConnect = rdp_freerdp_pre_connect; - rdp_inst->PostConnect = rdp_freerdp_post_connect; rdp_inst->Authenticate = rdp_freerdp_authenticate; rdp_inst->VerifyCertificate = rdp_freerdp_verify_certificate; rdp_inst->ReceiveChannelData = freerdp_channels_data; /* Allocate FreeRDP context */ rdp_inst->ContextSize = sizeof(rdp_freerdp_context); - rdp_inst->ContextNew = (pContextNew) rdp_freerdp_context_new; - rdp_inst->ContextFree = (pContextFree) rdp_freerdp_context_free; freerdp_context_new(rdp_inst); ((rdp_freerdp_context*) rdp_inst->context)->client = client; @@ -728,8 +660,6 @@ static int guac_rdp_handle_connection(guac_client* client) { pthread_mutex_lock(&(rdp_client->rdp_lock)); /* Disconnect client and channels */ - freerdp_channels_close(channels, rdp_inst); - freerdp_channels_free(channels); freerdp_disconnect(rdp_inst); /* Clean up RDP client context */ From 6886665f65e0283b43990559666e67a93ff3c65d Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 29 Sep 2019 14:15:41 -0700 Subject: [PATCH 012/109] GUACAMOLE-249: Comment out usage of old event interface. --- src/protocols/rdp/rdp.c | 2 ++ src/protocols/rdp/rdp_cliprdr.c | 17 ++++++++--------- src/protocols/rdp/rdp_rail.c | 5 ++--- src/protocols/rdp/rdp_stream.c | 6 ++++++ 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 43cca5b3..2eba211e 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -582,6 +582,7 @@ static int guac_rdp_handle_connection(guac_client* client) { } /* Check for channel events */ +#if 0 wMessage* event = freerdp_channels_pop_event(channels); if (event) { @@ -594,6 +595,7 @@ static int guac_rdp_handle_connection(guac_client* client) { freerdp_event_free(event); } +#endif pthread_mutex_unlock(&(rdp_client->rdp_lock)); diff --git a/src/protocols/rdp/rdp_cliprdr.c b/src/protocols/rdp/rdp_cliprdr.c index 735d3329..52960e01 100644 --- a/src/protocols/rdp/rdp_cliprdr.c +++ b/src/protocols/rdp/rdp_cliprdr.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -36,7 +35,7 @@ #include void guac_rdp_process_cliprdr_event(guac_client* client, wMessage* event) { - +#if 0 switch (event->event_type) { case CliprdrChannel_MonitorReady: @@ -64,11 +63,11 @@ void guac_rdp_process_cliprdr_event(guac_client* client, wMessage* event) { GetMessageType(event->id)); } - +#endif } void guac_rdp_process_cb_monitor_ready(guac_client* client, wMessage* event) { - +#if 0 rdpChannels* channels = ((guac_rdp_client*) client->data)->rdp_inst->context->channels; @@ -87,7 +86,7 @@ void guac_rdp_process_cb_monitor_ready(guac_client* client, wMessage* event) { format_list->num_formats = 2; freerdp_channels_send_event(channels, (wMessage*) format_list); - +#endif } /** @@ -101,7 +100,7 @@ void guac_rdp_process_cb_monitor_ready(guac_client* client, wMessage* event) { * documented values used by the CLIPRDR channel for clipboard format IDs. */ static void __guac_rdp_cb_request_format(guac_client* client, int format) { - +#if 0 guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; rdpChannels* channels = rdp_client->rdp_inst->context->channels; @@ -118,7 +117,7 @@ static void __guac_rdp_cb_request_format(guac_client* client, int format) { /* Send request */ freerdp_channels_send_event(channels, (wMessage*) data_request); - +#endif } void guac_rdp_process_cb_format_list(guac_client* client, @@ -158,7 +157,7 @@ void guac_rdp_process_cb_format_list(guac_client* client, void guac_rdp_process_cb_data_request(guac_client* client, RDP_CB_DATA_REQUEST_EVENT* event) { - +#if 0 guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; rdpChannels* channels = rdp_client->rdp_inst->context->channels; @@ -201,7 +200,7 @@ void guac_rdp_process_cb_data_request(guac_client* client, /* Send response */ freerdp_channels_send_event(channels, (wMessage*) data_response); - +#endif } void guac_rdp_process_cb_data_response(guac_client* client, diff --git a/src/protocols/rdp/rdp_rail.c b/src/protocols/rdp/rdp_rail.c index 56ba6358..b351ea6f 100644 --- a/src/protocols/rdp/rdp_rail.c +++ b/src/protocols/rdp/rdp_rail.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -61,7 +60,7 @@ void guac_rdp_process_rail_event(guac_client* client, wMessage* event) { } void guac_rdp_process_rail_get_sysparam(guac_client* client, wMessage* event) { - +#if 0 wMessage* response; RAIL_SYSPARAM_ORDER* sysparam; @@ -93,6 +92,6 @@ void guac_rdp_process_rail_get_sysparam(guac_client* client, wMessage* event) { /* Send response */ freerdp_channels_send_event(channels, response); - +#endif } diff --git a/src/protocols/rdp/rdp_stream.c b/src/protocols/rdp/rdp_stream.c index b90b4365..1e1d4708 100644 --- a/src/protocols/rdp/rdp_stream.c +++ b/src/protocols/rdp/rdp_stream.c @@ -123,6 +123,7 @@ int guac_rdp_upload_file_handler(guac_user* user, guac_stream* stream, int guac_rdp_svc_pipe_handler(guac_user* user, guac_stream* stream, char* mimetype, char* name) { +#if 0 guac_rdp_stream* rdp_stream; guac_rdp_svc* svc = guac_rdp_get_svc(user->client, name); @@ -146,6 +147,7 @@ int guac_rdp_svc_pipe_handler(guac_user* user, guac_stream* stream, stream->blob_handler = guac_rdp_svc_blob_handler; rdp_stream->type = GUAC_RDP_INBOUND_SVC_STREAM; rdp_stream->svc = svc; +#endif return 0; @@ -221,10 +223,12 @@ int guac_rdp_upload_blob_handler(guac_user* user, guac_stream* stream, int guac_rdp_svc_blob_handler(guac_user* user, guac_stream* stream, void* data, int length) { +#if 0 guac_rdp_stream* rdp_stream = (guac_rdp_stream*) stream->data; /* Write blob data to SVC directly */ guac_rdp_svc_write(rdp_stream->svc, data, length); +#endif guac_protocol_send_ack(user->socket, stream, "OK (DATA RECEIVED)", GUAC_PROTOCOL_STATUS_SUCCESS); @@ -280,6 +284,7 @@ int guac_rdp_clipboard_end_handler(guac_user* user, guac_stream* stream) { guac_common_clipboard_append(rdp_client->clipboard, "", 1); /* Notify RDP server of new data, if connected */ +#if 0 freerdp* rdp_inst = rdp_client->rdp_inst; if (rdp_inst != NULL) { @@ -300,6 +305,7 @@ int guac_rdp_clipboard_end_handler(guac_user* user, guac_stream* stream) { freerdp_channels_send_event(channels, (wMessage*) format_list); } +#endif return 0; } From a76e307176c667579dcdeb47f758e43014d0d7c4 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 29 Sep 2019 14:25:47 -0700 Subject: [PATCH 013/109] GUACAMOLE-249: RDP "DisableEncryption" settings flag has been inverted and renamed to "UseRdpSecurityLayer". --- src/protocols/rdp/rdp_settings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/rdp/rdp_settings.c b/src/protocols/rdp/rdp_settings.c index 2bfd197b..c0af4736 100644 --- a/src/protocols/rdp/rdp_settings.c +++ b/src/protocols/rdp/rdp_settings.c @@ -1207,6 +1207,7 @@ void guac_rdp_push_settings(guac_client* client, rdp_settings->RdpSecurity = TRUE; rdp_settings->TlsSecurity = FALSE; rdp_settings->NlaSecurity = FALSE; + rdp_settings->UseRdpSecurityLayer = TRUE; rdp_settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; rdp_settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT @@ -1240,7 +1241,6 @@ void guac_rdp_push_settings(guac_client* client, /* Authentication */ rdp_settings->Authentication = !guac_settings->disable_authentication; rdp_settings->IgnoreCertificate = guac_settings->ignore_certificate; - rdp_settings->DisableEncryption = FALSE; /* RemoteApp */ if (guac_settings->remote_app != NULL) { From 2ed0d042a37959874ea6eba0d5f62c1fc8a1ed32 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 29 Sep 2019 14:34:05 -0700 Subject: [PATCH 014/109] GUACAMOLE-249: Default to negotiated security mode, not old "RDP" encryption. --- src/protocols/rdp/rdp_settings.c | 13 +++++++------ src/protocols/rdp/rdp_settings.h | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/protocols/rdp/rdp_settings.c b/src/protocols/rdp/rdp_settings.c index c0af4736..75fb1604 100644 --- a/src/protocols/rdp/rdp_settings.c +++ b/src/protocols/rdp/rdp_settings.c @@ -232,7 +232,8 @@ enum RDP_ARGS_IDX { /** * The type of security to use for the connection. Valid values are "rdp", - * "tls", "nla", or "any". By default, "rdp" security is used. + * "tls", "nla", "nla-ext", or "any". By default, the security mode is + * negotiated ("any"). */ IDX_SECURITY, @@ -587,16 +588,16 @@ guac_rdp_settings* guac_rdp_parse_args(guac_user* user, settings->security_mode = GUAC_SECURITY_RDP; } - /* ANY security (allow server to choose) */ + /* Negotiate security (allow server to choose) */ else if (strcmp(argv[IDX_SECURITY], "any") == 0) { - guac_user_log(user, GUAC_LOG_INFO, "Security mode: ANY"); + guac_user_log(user, GUAC_LOG_INFO, "Security mode: Negotiate (ANY)"); settings->security_mode = GUAC_SECURITY_ANY; } /* If nothing given, default to RDP */ else { - guac_user_log(user, GUAC_LOG_INFO, "No security mode specified. Defaulting to RDP."); - settings->security_mode = GUAC_SECURITY_RDP; + guac_user_log(user, GUAC_LOG_INFO, "No security mode specified. Defaulting to security mode negotiation with server."); + settings->security_mode = GUAC_SECURITY_ANY; } /* Set hostname */ @@ -1202,7 +1203,7 @@ void guac_rdp_push_settings(guac_client* client, /* Security */ switch (guac_settings->security_mode) { - /* Standard RDP encryption */ + /* Legacy RDP encryption */ case GUAC_SECURITY_RDP: rdp_settings->RdpSecurity = TRUE; rdp_settings->TlsSecurity = FALSE; diff --git a/src/protocols/rdp/rdp_settings.h b/src/protocols/rdp/rdp_settings.h index 0d655f6b..d330c486 100644 --- a/src/protocols/rdp/rdp_settings.h +++ b/src/protocols/rdp/rdp_settings.h @@ -64,7 +64,7 @@ typedef enum guac_rdp_security { /** - * Standard RDP encryption. + * Legacy RDP encryption. */ GUAC_SECURITY_RDP, @@ -79,7 +79,7 @@ typedef enum guac_rdp_security { GUAC_SECURITY_NLA, /** - * Any method supported by the server. + * Negotiate a security method supported by both server and client. */ GUAC_SECURITY_ANY From 7332e633dcb75154ca49889651a33f4d83c364f8 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 29 Sep 2019 14:34:35 -0700 Subject: [PATCH 015/109] GUACAMOLE-249: Add "nla-ext" option for extended NLA mode. --- src/protocols/rdp/rdp_settings.c | 18 ++++++++++++++++++ src/protocols/rdp/rdp_settings.h | 5 +++++ 2 files changed, 23 insertions(+) diff --git a/src/protocols/rdp/rdp_settings.c b/src/protocols/rdp/rdp_settings.c index 75fb1604..5c86742c 100644 --- a/src/protocols/rdp/rdp_settings.c +++ b/src/protocols/rdp/rdp_settings.c @@ -576,6 +576,12 @@ guac_rdp_settings* guac_rdp_parse_args(guac_user* user, settings->security_mode = GUAC_SECURITY_NLA; } + /* Extended NLA security */ + else if (strcmp(argv[IDX_SECURITY], "nla-ext") == 0) { + guac_user_log(user, GUAC_LOG_INFO, "Security mode: Extended NLA"); + settings->security_mode = GUAC_SECURITY_EXTENDED_NLA; + } + /* TLS security */ else if (strcmp(argv[IDX_SECURITY], "tls") == 0) { guac_user_log(user, GUAC_LOG_INFO, "Security mode: TLS"); @@ -1208,6 +1214,7 @@ void guac_rdp_push_settings(guac_client* client, rdp_settings->RdpSecurity = TRUE; rdp_settings->TlsSecurity = FALSE; rdp_settings->NlaSecurity = FALSE; + rdp_settings->ExtSecurity = FALSE; rdp_settings->UseRdpSecurityLayer = TRUE; rdp_settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; rdp_settings->EncryptionMethods = @@ -1221,6 +1228,7 @@ void guac_rdp_push_settings(guac_client* client, rdp_settings->RdpSecurity = FALSE; rdp_settings->TlsSecurity = TRUE; rdp_settings->NlaSecurity = FALSE; + rdp_settings->ExtSecurity = FALSE; break; /* Network level authentication */ @@ -1228,6 +1236,15 @@ void guac_rdp_push_settings(guac_client* client, rdp_settings->RdpSecurity = FALSE; rdp_settings->TlsSecurity = FALSE; rdp_settings->NlaSecurity = TRUE; + rdp_settings->ExtSecurity = FALSE; + break; + + /* Extended network level authentication */ + case GUAC_SECURITY_EXTENDED_NLA: + rdp_settings->RdpSecurity = FALSE; + rdp_settings->TlsSecurity = FALSE; + rdp_settings->NlaSecurity = FALSE; + rdp_settings->ExtSecurity = TRUE; break; /* All security types */ @@ -1235,6 +1252,7 @@ void guac_rdp_push_settings(guac_client* client, rdp_settings->RdpSecurity = TRUE; rdp_settings->TlsSecurity = TRUE; rdp_settings->NlaSecurity = TRUE; + rdp_settings->ExtSecurity = TRUE; break; } diff --git a/src/protocols/rdp/rdp_settings.h b/src/protocols/rdp/rdp_settings.h index d330c486..ae27e9d2 100644 --- a/src/protocols/rdp/rdp_settings.h +++ b/src/protocols/rdp/rdp_settings.h @@ -78,6 +78,11 @@ typedef enum guac_rdp_security { */ GUAC_SECURITY_NLA, + /** + * Extended network level authentication. + */ + GUAC_SECURITY_EXTENDED_NLA, + /** * Negotiate a security method supported by both server and client. */ From 1e692094bed9262b3d3de009cd0651b50f4f2a03 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 29 Sep 2019 15:01:23 -0700 Subject: [PATCH 016/109] GUACAMOLE-249: Correct remaining void returns from BOOL handlers. --- src/protocols/rdp/rdp_bitmap.c | 2 +- src/protocols/rdp/rdp_gdi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/protocols/rdp/rdp_bitmap.c b/src/protocols/rdp/rdp_bitmap.c index a7021124..48eb485a 100644 --- a/src/protocols/rdp/rdp_bitmap.c +++ b/src/protocols/rdp/rdp_bitmap.c @@ -172,7 +172,7 @@ BOOL guac_rdp_bitmap_setsurface(rdpContext* context, rdpBitmap* bitmap, BOOL pri /* Make sure that the recieved bitmap is not NULL before processing */ if (bitmap == NULL) { guac_client_log(client, GUAC_LOG_INFO, "NULL bitmap found in bitmap_setsurface instruction."); - return; + return TRUE; } /* If not available as a surface, make available. */ diff --git a/src/protocols/rdp/rdp_gdi.c b/src/protocols/rdp/rdp_gdi.c index c3332f6a..33de873a 100644 --- a/src/protocols/rdp/rdp_gdi.c +++ b/src/protocols/rdp/rdp_gdi.c @@ -249,7 +249,7 @@ BOOL guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) { /* Make sure that the recieved bitmap is not NULL before processing */ if (bitmap == NULL) { guac_client_log(client, GUAC_LOG_INFO, "NULL bitmap found in memblt instruction."); - return; + return TRUE; } switch (memblt->bRop) { From c311d8bde96dbcb9fc8c3c2ded2be2f19478d3f9 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 29 Sep 2019 15:02:06 -0700 Subject: [PATCH 017/109] GUACAMOLE-249: Rely on default bitmap/GDI/pointer handlers for all but those that must be overridden. --- src/protocols/rdp/rdp.c | 58 +++++++++++++++------------------- src/protocols/rdp/rdp_bitmap.c | 45 -------------------------- 2 files changed, 25 insertions(+), 78 deletions(-) diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 2eba211e..cc13507c 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -121,16 +121,12 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { rdpContext* context = instance->context; rdpChannels* channels = context->channels; + rdpGraphics* graphics = context->graphics; guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_settings* settings = rdp_client->settings; - rdpBitmap* bitmap; - rdpGlyph* glyph; - rdpPointer* pointer; - rdpPrimaryUpdate* primary; - guac_rdp_dvc_list* dvc_list = guac_rdp_dvc_list_alloc(); /* Init FreeRDP add-in provider */ @@ -232,44 +228,40 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { instance->context->cache = cache_new(instance->settings); /* Set up bitmap handling */ - bitmap = calloc(1, sizeof(rdpBitmap)); - bitmap->size = sizeof(guac_rdp_bitmap); - bitmap->New = guac_rdp_bitmap_new; - bitmap->Free = guac_rdp_bitmap_free; - bitmap->Paint = guac_rdp_bitmap_paint; - bitmap->Decompress = guac_rdp_bitmap_decompress; - bitmap->SetSurface = guac_rdp_bitmap_setsurface; - graphics_register_bitmap(context->graphics, bitmap); - free(bitmap); + rdpBitmap bitmap = *graphics->Bitmap_Prototype; + bitmap.size = sizeof(guac_rdp_bitmap); + bitmap.New = guac_rdp_bitmap_new; + bitmap.Free = guac_rdp_bitmap_free; + bitmap.Paint = guac_rdp_bitmap_paint; + bitmap.SetSurface = guac_rdp_bitmap_setsurface; + graphics_register_bitmap(graphics, &bitmap); /* Set up glyph handling */ - glyph = calloc(1, sizeof(rdpGlyph)); - glyph->size = sizeof(guac_rdp_glyph); - glyph->New = guac_rdp_glyph_new; - glyph->Free = guac_rdp_glyph_free; - glyph->Draw = guac_rdp_glyph_draw; - glyph->BeginDraw = guac_rdp_glyph_begindraw; - glyph->EndDraw = guac_rdp_glyph_enddraw; - graphics_register_glyph(context->graphics, glyph); - free(glyph); + rdpGlyph glyph = *graphics->Glyph_Prototype; + glyph.size = sizeof(guac_rdp_glyph); + glyph.New = guac_rdp_glyph_new; + glyph.Free = guac_rdp_glyph_free; + glyph.Draw = guac_rdp_glyph_draw; + glyph.BeginDraw = guac_rdp_glyph_begindraw; + glyph.EndDraw = guac_rdp_glyph_enddraw; + graphics_register_glyph(graphics, &glyph); /* Set up pointer handling */ - pointer = calloc(1, sizeof(rdpPointer)); - pointer->size = sizeof(guac_rdp_pointer); - pointer->New = guac_rdp_pointer_new; - pointer->Free = guac_rdp_pointer_free; - pointer->Set = guac_rdp_pointer_set; - pointer->SetNull = guac_rdp_pointer_set_null; - pointer->SetDefault = guac_rdp_pointer_set_default; - graphics_register_pointer(context->graphics, pointer); - free(pointer); + rdpPointer pointer = *graphics->Pointer_Prototype; + pointer.size = sizeof(guac_rdp_pointer); + pointer.New = guac_rdp_pointer_new; + pointer.Free = guac_rdp_pointer_free; + pointer.Set = guac_rdp_pointer_set; + pointer.SetNull = guac_rdp_pointer_set_null; + pointer.SetDefault = guac_rdp_pointer_set_default; + graphics_register_pointer(graphics, &pointer); /* Set up GDI */ instance->update->DesktopResize = guac_rdp_gdi_desktop_resize; instance->update->EndPaint = guac_rdp_gdi_end_paint; instance->update->SetBounds = guac_rdp_gdi_set_bounds; - primary = instance->update->primary; + rdpPrimaryUpdate* primary = instance->update->primary; primary->DstBlt = guac_rdp_gdi_dstblt; primary->PatBlt = guac_rdp_gdi_patblt; primary->ScrBlt = guac_rdp_gdi_scrblt; diff --git a/src/protocols/rdp/rdp_bitmap.c b/src/protocols/rdp/rdp_bitmap.c index 48eb485a..5a904233 100644 --- a/src/protocols/rdp/rdp_bitmap.c +++ b/src/protocols/rdp/rdp_bitmap.c @@ -188,48 +188,3 @@ BOOL guac_rdp_bitmap_setsurface(rdpContext* context, rdpBitmap* bitmap, BOOL pri } -BOOL guac_rdp_bitmap_decompress(rdpContext* context, rdpBitmap* bitmap, const BYTE* data, - UINT32 width, UINT32 height, UINT32 bpp, UINT32 length, BOOL compressed, UINT32 codec_id) { - - int size = width * height * 4; - - /* Free pre-existing data, if any (might be reused) */ - if (bitmap->data != NULL) - _aligned_free(bitmap->data); - - /* Allocate new data - this MUST be allocated with _aligned_malloc() */ - bitmap->data = (UINT8*) _aligned_malloc(size, 16); - - if (compressed) { - - rdpCodecs* codecs = context->codecs; - - /* Decode as interleaved if less than 32 bits per pixel */ - if (bpp < 32) { - freerdp_client_codecs_prepare(codecs, FREERDP_CODEC_INTERLEAVED); - interleaved_decompress(codecs->interleaved, data, length, bpp, - &(bitmap->data), PIXEL_FORMAT_XRGB32, -1, 0, 0, width, height, - (BYTE*) ((rdp_freerdp_context*) context)->palette); - bitmap->bpp = 32; - } - - /* Otherwise, decode as planar */ - else { - freerdp_client_codecs_prepare(codecs, FREERDP_CODEC_PLANAR); - planar_decompress(codecs->planar, data, length, - &(bitmap->data), PIXEL_FORMAT_XRGB32, -1, 0, 0, width, height, - TRUE); - bitmap->bpp = 32; - } - - } - else { - freerdp_image_flip(data, bitmap->data, width, height, bpp); - bitmap->bpp = bpp; - } - - bitmap->compressed = FALSE; - bitmap->length = size; - -} - From 65fe6c973551c37ba9a6fe4a6391eff502af3933 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 29 Sep 2019 15:03:40 -0700 Subject: [PATCH 018/109] GUACAMOLE-249: Correct incorrect syntax introduced by initial partial migration (commit a5b62aa82). --- src/protocols/rdp/rdp_glyph.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/rdp/rdp_glyph.c b/src/protocols/rdp/rdp_glyph.c index 01ea7d4d..96c4a14e 100644 --- a/src/protocols/rdp/rdp_glyph.c +++ b/src/protocols/rdp/rdp_glyph.c @@ -96,7 +96,7 @@ BOOL guac_rdp_glyph_new(rdpContext* context, const rdpGlyph* glyph) { BOOL guac_rdp_glyph_draw(rdpContext* context, const rdpGlyph* glyph, INT32 x, INT32 y, INT32 w, INT32 h, INT32 sx, INT32 sy, - BOOL redundant); + BOOL redundant) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; From 7a7ffc2c19038ba34f8f3c5672658a2bf42da9ee Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 29 Sep 2019 15:08:06 -0700 Subject: [PATCH 019/109] GUACAMOLE-249: Add missing pixel format parameter to pointer image copy. --- src/protocols/rdp/rdp_pointer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/protocols/rdp/rdp_pointer.c b/src/protocols/rdp/rdp_pointer.c index 99752448..58497793 100644 --- a/src/protocols/rdp/rdp_pointer.c +++ b/src/protocols/rdp/rdp_pointer.c @@ -48,8 +48,8 @@ BOOL guac_rdp_pointer_new(rdpContext* context, rdpPointer* pointer) { /* Convert to alpha cursor if mask data present */ if (pointer->andMaskData && pointer->xorMaskData) - freerdp_image_copy_from_pointer_data(data, 0, 0, 0, - pointer->width, pointer->height, + freerdp_image_copy_from_pointer_data(data, PIXEL_FORMAT_ARGB32, + 0, 0, 0, pointer->width, pointer->height, pointer->xorMaskData, pointer->lengthXorMask, pointer->andMaskData, pointer->lengthAndMask, pointer->xorBpp, &context->gdi->palette); From 7904d9c002bd5525398ca4e5bd374e54a89e93ad Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 29 Sep 2019 15:37:09 -0700 Subject: [PATCH 020/109] GUACAMOLE-249: Initialize FreeRDP's GDI implementation (default GDI handlers will otherwise fail). --- src/protocols/rdp/rdp.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index cc13507c..134de7de 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include @@ -227,6 +228,10 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { /* Init FreeRDP cache */ instance->context->cache = cache_new(instance->settings); + /* Init FreeRDP internal GDI implementation */ + if (!gdi_init(instance, PIXEL_FORMAT_XRGB32)) + return FALSE; + /* Set up bitmap handling */ rdpBitmap bitmap = *graphics->Bitmap_Prototype; bitmap.size = sizeof(guac_rdp_bitmap); From 17045d5d3aef14d17e4be543abbaf7cb7bf8833b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 29 Sep 2019 16:08:27 -0700 Subject: [PATCH 021/109] GUACAMOLE-249: Use reversed byte order for colors locally (verification needed). --- src/protocols/rdp/rdp.c | 2 +- src/protocols/rdp/rdp_bitmap.c | 4 ++-- src/protocols/rdp/rdp_color.c | 6 +++--- src/protocols/rdp/rdp_pointer.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 134de7de..d249f676 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -229,7 +229,7 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { instance->context->cache = cache_new(instance->settings); /* Init FreeRDP internal GDI implementation */ - if (!gdi_init(instance, PIXEL_FORMAT_XRGB32)) + if (!gdi_init(instance, PIXEL_FORMAT_BGRX32)) return FALSE; /* Set up bitmap handling */ diff --git a/src/protocols/rdp/rdp_bitmap.c b/src/protocols/rdp/rdp_bitmap.c index 5a904233..2dcf77a2 100644 --- a/src/protocols/rdp/rdp_bitmap.c +++ b/src/protocols/rdp/rdp_bitmap.c @@ -73,13 +73,13 @@ BOOL guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap) { BOOL guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap) { /* Convert image data if present */ - if (bitmap->data != NULL && bitmap->format != PIXEL_FORMAT_XRGB32) { + if (bitmap->data != NULL && bitmap->format != PIXEL_FORMAT_BGRX32) { /* Allocate sufficient space for converted image */ unsigned char* image_buffer = _aligned_malloc(bitmap->width * bitmap->height * 4, 16); /* Attempt image conversion */ - if (!freerdp_image_copy(image_buffer, PIXEL_FORMAT_XRGB32, 0, 0, 0, + if (!freerdp_image_copy(image_buffer, PIXEL_FORMAT_BGRX32, 0, 0, 0, bitmap->width, bitmap->height, bitmap->data, bitmap->format, 0, 0, 0, &context->gdi->palette, FREERDP_FLIP_NONE)) { _aligned_free(image_buffer); diff --git a/src/protocols/rdp/rdp_color.c b/src/protocols/rdp/rdp_color.c index 1d88089d..0132fb25 100644 --- a/src/protocols/rdp/rdp_color.c +++ b/src/protocols/rdp/rdp_color.c @@ -48,7 +48,7 @@ static UINT32 guac_rdp_get_pixel_format(int depth) { /* 32- and 24-bit RGB (8 bits per color component) */ case 32: case 24: - return PIXEL_FORMAT_BGR24; + return PIXEL_FORMAT_RGB24; /* 16-bit palette (6-bit green, 5-bit red and blue) */ case 16: @@ -65,7 +65,7 @@ static UINT32 guac_rdp_get_pixel_format(int depth) { } /* Unknown format */ - return PIXEL_FORMAT_BGR24; + return PIXEL_FORMAT_RGB24; } @@ -76,7 +76,7 @@ UINT32 guac_rdp_convert_color(rdpContext* context, UINT32 color) { /* Convert given color to ARGB32 */ return FreeRDPConvertColor(color, guac_rdp_get_pixel_format(depth), - PIXEL_FORMAT_ARGB32, &gdi->palette); + PIXEL_FORMAT_BGRA32, &gdi->palette); } diff --git a/src/protocols/rdp/rdp_pointer.c b/src/protocols/rdp/rdp_pointer.c index 58497793..fb789842 100644 --- a/src/protocols/rdp/rdp_pointer.c +++ b/src/protocols/rdp/rdp_pointer.c @@ -48,7 +48,7 @@ BOOL guac_rdp_pointer_new(rdpContext* context, rdpPointer* pointer) { /* Convert to alpha cursor if mask data present */ if (pointer->andMaskData && pointer->xorMaskData) - freerdp_image_copy_from_pointer_data(data, PIXEL_FORMAT_ARGB32, + freerdp_image_copy_from_pointer_data(data, PIXEL_FORMAT_BGRA32, 0, 0, 0, pointer->width, pointer->height, pointer->xorMaskData, pointer->lengthXorMask, pointer->andMaskData, pointer->lengthAndMask, From b89ed7ff153a37e82ca7217cb04d192b9fdb987b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 6 Oct 2019 14:32:12 -0700 Subject: [PATCH 022/109] GUACAMOLE-249: Migrate wait mechanism to event handle interface. --- src/protocols/rdp/rdp.c | 82 ++++++++--------------------------------- 1 file changed, 16 insertions(+), 66 deletions(-) diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index d249f676..b6b84c5f 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -380,78 +380,30 @@ static int rdp_guac_client_wait_for_messages(guac_client* client, guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; freerdp* rdp_inst = rdp_client->rdp_inst; - rdpChannels* channels = rdp_inst->context->channels; - int result; - int index; + HANDLE handles[GUAC_RDP_MAX_FILE_DESCRIPTORS]; + int num_handles = freerdp_get_event_handles(rdp_inst->context, handles, + GUAC_RDP_MAX_FILE_DESCRIPTORS); - /* List of all file descriptors which we may read data from */ - void* read_fds[GUAC_RDP_MAX_FILE_DESCRIPTORS]; - int read_count = 0; + /* Wait for data and construct a reasonable frame */ + int result = WaitForMultipleObjects(num_handles, handles, FALSE, + timeout_msecs); - /* List of all file descriptors which data may be written to. These will - * ultimately be ignored, but FreeRDP requires that both read and write - * file descriptors be retrieved simultaneously. */ - void* write_fds[GUAC_RDP_MAX_FILE_DESCRIPTORS]; - int write_count = 0; + /* Translate WaitForMultipleObjects() return values */ + switch (result) { - struct pollfd fds[GUAC_RDP_MAX_FILE_DESCRIPTORS]; - - /* Get RDP file descriptors */ - if (!freerdp_get_fds(rdp_inst, read_fds, &read_count, - write_fds, &write_count)) { - guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, - "Unable to read RDP file descriptors."); - return -1; - } - - /* Get RDP channel file descriptors */ - if (!freerdp_channels_get_fds(channels, rdp_inst, read_fds, &read_count, - write_fds, &write_count)) { - guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, - "Unable to read RDP channel file descriptors."); - return -1; - } - - /* If no file descriptors, error */ - if (read_count == 0) { - guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, - "No file descriptors associated with RDP connection."); - return -1; - } - - /* Populate poll() array of read file descriptors */ - for (index = 0; index < read_count; index++) { - - struct pollfd* current = &fds[index]; - - /* Init poll() array element with RDP file descriptor */ - current->fd = (int)(long) (read_fds[index]); - current->events = POLLIN; - current->revents = 0; - - } - - /* Wait until data can be read from RDP file descriptors */ - result = poll(fds, read_count, timeout_msecs); - if (result < 0) { - - /* If error ignorable, pretend timout occurred */ - if (errno == EAGAIN - || errno == EWOULDBLOCK - || errno == EINPROGRESS - || errno == EINTR) + /* Timeout elapsed before wait could complete */ + case WAIT_TIMEOUT: return 0; - /* Otherwise, return as error */ - guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_UNAVAILABLE, - "Error waiting for file descriptor."); - return -1; + /* Attempt to wait failed due to an error */ + case WAIT_FAILED: + return -1; } - /* Return wait result */ - return result; + /* Wait was successful */ + return 1; } @@ -535,7 +487,6 @@ static int guac_rdp_handle_connection(guac_client* client) { /* Connection complete */ rdp_client->rdp_inst = rdp_inst; - rdpChannels* channels = rdp_inst->context->channels; guac_timestamp last_frame_end = guac_timestamp_current(); @@ -568,8 +519,7 @@ static int guac_rdp_handle_connection(guac_client* client) { pthread_mutex_lock(&(rdp_client->rdp_lock)); /* Check the libfreerdp fds */ - if (!freerdp_check_fds(rdp_inst) - || !freerdp_channels_check_fds(channels, rdp_inst)) { + if (!freerdp_check_event_handles(rdp_inst->context)) { /* Flag connection failure */ wait_result = -1; From 16be3af03c49e6815f830e18690120799362f7ee Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 6 Oct 2019 14:44:06 -0700 Subject: [PATCH 023/109] GUACAMOLE-249: Load FreeRDP plugins regardless of entry point interface. Most plugins built into FreeRDP implement the PVIRTUALCHANNELENTRYEX entry point, but the FreeRDP standard function for loading plugins only supports PVIRTUALCHANNELENTRY. It appears that only the commandline argument parser included with FreeRDP was updated to leverage the new entry points. --- src/protocols/rdp/Makefile.am | 2 ++ src/protocols/rdp/channels.c | 46 ++++++++++++++++++++++++ src/protocols/rdp/channels.h | 66 +++++++++++++++++++++++++++++++++++ src/protocols/rdp/dvc.c | 6 ++-- src/protocols/rdp/rdp.c | 11 +++--- 5 files changed, 124 insertions(+), 7 deletions(-) create mode 100644 src/protocols/rdp/channels.c create mode 100644 src/protocols/rdp/channels.h diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index 3ced7e0d..d3d0cf08 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -34,6 +34,7 @@ nodist_libguac_client_rdp_la_SOURCES = \ libguac_client_rdp_la_SOURCES = \ audio_input.c \ + channels.c \ client.c \ decompose.c \ dvc.c \ @@ -103,6 +104,7 @@ noinst_HEADERS = \ guac_svc/svc_service.h \ audio_input.h \ client.h \ + channels.h \ decompose.h \ dvc.h \ error.h \ diff --git a/src/protocols/rdp/channels.c b/src/protocols/rdp/channels.c new file mode 100644 index 00000000..6719f49b --- /dev/null +++ b/src/protocols/rdp/channels.c @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#include "config.h" + +#include +#include + +int guac_freerdp_channels_load_plugin(rdpChannels* channels, + rdpSettings* settings, const char* name, void* data) { + + /* Load plugin using "ex" version of the channel plugin entry point, if it exists */ + PVIRTUALCHANNELENTRYEX entry_ex = (PVIRTUALCHANNELENTRYEX) (void*) freerdp_load_channel_addin_entry(name, + NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC | FREERDP_ADDIN_CHANNEL_ENTRYEX); + + if (entry_ex != NULL) + return freerdp_channels_client_load_ex(channels, settings, entry_ex, data); + + /* Lacking the "ex" entry point, attempt to load using the non-ex version */ + PVIRTUALCHANNELENTRY entry = freerdp_load_channel_addin_entry(name, + NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC); + + if (entry != NULL) + return freerdp_channels_client_load(channels, settings, entry, data); + + /* The plugin does not exist / cannot be loaded */ + return 1; + +} + diff --git a/src/protocols/rdp/channels.h b/src/protocols/rdp/channels.h new file mode 100644 index 00000000..1e7fb6b1 --- /dev/null +++ b/src/protocols/rdp/channels.h @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#ifndef GUAC_RDP_CHANNELS_H +#define GUAC_RDP_CHANNELS_H + +#include "config.h" + +#include +#include + +/** + * Loads the FreeRDP plugin having the given name. This function is a drop-in + * replacement for freerdp_channels_load_plugin() which additionally loads + * plugins implementing the PVIRTUALCHANNELENTRYEX version of the channel + * plugin entry point. The freerdp_channels_load_plugin() function which is + * part of FreeRDP can load only plugins which implement the + * PVIRTUALCHANNELENTRY version of the entry point. + * + * @param channels + * The rdpChannels structure with which the plugin should be registered + * once loaded. This structure should be retrieved directly from the + * relevant FreeRDP instance. + * + * @param settings + * The rdpSettings structure associated with the FreeRDP instance, already + * populated with any settings applicable to the plugin being loaded. + * + * @param name + * The name of the plugin to load. If the plugin is not statically built + * into FreeRDP, this name will determine the filename of the library to be + * loaded dynamically. For a plugin named "NAME", the library called + * "libNAME-client" will be loaded from the "freerdp2" subdirectory of the + * main directory containing the FreeRDP libraries. + * + * @param data + * Arbitrary data to be passed to the plugin entry point. For most plugins + * which are built into FreeRDP, this will be another reference to the + * rdpSettings struct. The source of the relevant plugin must be consulted + * to determine the proper value to pass here. + * + * @return + * Zero if the plugin was loaded successfully, non-zero if the plugin could + * not be loaded. + */ +int guac_freerdp_channels_load_plugin(rdpChannels* channels, + rdpSettings* settings, const char* name, void* data); + +#endif + diff --git a/src/protocols/rdp/dvc.c b/src/protocols/rdp/dvc.c index ee1c886b..55bf85b5 100644 --- a/src/protocols/rdp/dvc.c +++ b/src/protocols/rdp/dvc.c @@ -19,6 +19,7 @@ #include "config.h" #include "common/list.h" +#include "channels.h" #include "dvc.h" #include "rdp.h" @@ -147,8 +148,9 @@ int guac_rdp_load_drdynvc(rdpContext* context, guac_rdp_dvc_list* list) { } /* Load virtual channel management plugin */ - return freerdp_channels_load_plugin(channels, context->instance->settings, - "drdynvc", context->instance->settings); + return guac_freerdp_channels_load_plugin(channels, + context->instance->settings, "drdynvc", + context->instance->settings); } diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index b6b84c5f..d62c05aa 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -20,6 +20,7 @@ #include "config.h" #include "audio_input.h" +#include "channels.h" #include "client.h" #include "common/cursor.h" #include "common/display.h" @@ -148,7 +149,7 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { } /* Load clipboard plugin */ - if (freerdp_channels_load_plugin(channels, instance->settings, + if (guac_freerdp_channels_load_plugin(channels, instance->settings, "cliprdr", NULL)) guac_client_log(client, GUAC_LOG_WARNING, "Failed to load cliprdr plugin. Clipboard will not work."); @@ -159,14 +160,14 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { || settings->audio_enabled) { /* Load RDPDR plugin */ - if (freerdp_channels_load_plugin(channels, instance->settings, + if (guac_freerdp_channels_load_plugin(channels, instance->settings, "guacdr", client)) guac_client_log(client, GUAC_LOG_WARNING, "Failed to load guacdr plugin. Drive redirection and " "printing will not work. Sound MAY not work."); /* Load RDPSND plugin */ - if (freerdp_channels_load_plugin(channels, instance->settings, + if (guac_freerdp_channels_load_plugin(channels, instance->settings, "guacsnd", client)) guac_client_log(client, GUAC_LOG_WARNING, "Failed to load guacsnd alongside guacdr plugin. Sound " @@ -179,7 +180,7 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { if (settings->remote_app != NULL) { /* Attempt to load rail */ - if (freerdp_channels_load_plugin(channels, instance->settings, + if (guac_freerdp_channels_load_plugin(channels, instance->settings, "rail", instance->settings)) guac_client_log(client, GUAC_LOG_WARNING, "Failed to load rail plugin. RemoteApp will not work."); @@ -196,7 +197,7 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { guac_rdp_svc* svc = guac_rdp_alloc_svc(client, *current); /* Attempt to load guacsvc plugin for new static channel */ - if (freerdp_channels_load_plugin(channels, instance->settings, + if (guac_freerdp_channels_load_plugin(channels, instance->settings, "guacsvc", svc)) { guac_client_log(client, GUAC_LOG_WARNING, "Cannot create static channel \"%s\": failed to load guacsvc plugin.", From cc7cd78e5be2d80e2fff6ef1f6a8e121f6a765cb Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 8 Oct 2019 11:44:26 -0700 Subject: [PATCH 024/109] GUACAMOLE-249: Centralize handling of connected channels. --- src/protocols/rdp/channels.c | 18 +++++++++++++++++ src/protocols/rdp/channels.h | 14 +++++++++++++ src/protocols/rdp/rdp.c | 39 ------------------------------------ src/protocols/rdp/rdp_disp.c | 23 ++++++++++++++++++++- src/protocols/rdp/rdp_disp.h | 20 ++++++++++-------- 5 files changed, 66 insertions(+), 48 deletions(-) diff --git a/src/protocols/rdp/channels.c b/src/protocols/rdp/channels.c index 6719f49b..ac474304 100644 --- a/src/protocols/rdp/channels.c +++ b/src/protocols/rdp/channels.c @@ -18,9 +18,27 @@ */ #include "config.h" +#include "rdp.h" #include #include +#include + +void guac_rdp_channel_connected(rdpContext* context, + ChannelConnectedEventArgs* e) { + + guac_client* client = ((rdp_freerdp_context*) context)->client; + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + + guac_client_log(client, GUAC_LOG_DEBUG, "Channel \"%s\" connected.", e->name); + + /* Display update channel */ + if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) == 0) { + DispClientContext* disp = (DispClientContext*) e->pInterface; + guac_rdp_disp_connect(rdp_client->disp, context, disp); + } + +} int guac_freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, const char* name, void* data) { diff --git a/src/protocols/rdp/channels.h b/src/protocols/rdp/channels.h index 1e7fb6b1..f8c7bcc6 100644 --- a/src/protocols/rdp/channels.h +++ b/src/protocols/rdp/channels.h @@ -25,6 +25,20 @@ #include #include +/** + * Called whenever a channel connects via the PubSub event system within + * FreeRDP. + * + * @param context + * The rdpContext associated with the active RDP session. + * + * @param e + * Event-specific arguments, mainly the name of the channel, and a + * reference to the associated plugin loaded for that channel by FreeRDP. + */ +void guac_rdp_channel_connected(rdpContext* context, + ChannelConnectedEventArgs* e); + /** * Loads the FreeRDP plugin having the given name. This function is a drop-in * replacement for freerdp_channels_load_plugin() which additionally loads diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index d62c05aa..ad490b8b 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -80,45 +80,6 @@ #include #include -/** - * Called whenever a channel connects via the PubSub event system within - * FreeRDP. - * - * @param context - * The rdpContext associated with the active RDP session. - * - * @param e - * Event-specific arguments, mainly the name of the channel, and a - * reference to the associated plugin loaded for that channel by FreeRDP. - */ -static void guac_rdp_channel_connected(rdpContext* context, - ChannelConnectedEventArgs* e) { - - guac_client* client = ((rdp_freerdp_context*) context)->client; - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - guac_rdp_settings* settings = rdp_client->settings; - - if (settings->resize_method == GUAC_RESIZE_DISPLAY_UPDATE) { - /* Store reference to the display update plugin once it's connected */ - if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) == 0) { - - DispClientContext* disp = (DispClientContext*) e->pInterface; - - /* Init module with current display size */ - guac_rdp_disp_set_size(rdp_client->disp, rdp_client->settings, - context->instance, guac_rdp_get_width(context->instance), - guac_rdp_get_height(context->instance)); - - /* Store connected channel */ - guac_rdp_disp_connect(rdp_client->disp, disp); - guac_client_log(client, GUAC_LOG_DEBUG, - "Display update channel connected."); - - } - } - -} - BOOL rdp_freerdp_pre_connect(freerdp* instance) { rdpContext* context = instance->context; diff --git a/src/protocols/rdp/rdp_disp.c b/src/protocols/rdp/rdp_disp.c index b26806e1..f152fa53 100644 --- a/src/protocols/rdp/rdp_disp.c +++ b/src/protocols/rdp/rdp_disp.c @@ -59,8 +59,29 @@ void guac_rdp_disp_load_plugin(rdpContext* context, guac_rdp_dvc_list* list) { } -void guac_rdp_disp_connect(guac_rdp_disp* guac_disp, DispClientContext* disp) { +void guac_rdp_disp_connect(guac_rdp_disp* guac_disp, rdpContext* context, + DispClientContext* disp) { + + guac_client* client = ((rdp_freerdp_context*) context)->client; + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + guac_rdp_settings* settings = rdp_client->settings; + + /* Ignore connected channel if not configured to use the display update + * channel for resize */ + if (settings->resize_method != GUAC_RESIZE_DISPLAY_UPDATE) + return; + + /* Init module with current display size */ + guac_rdp_disp_set_size(rdp_client->disp, rdp_client->settings, + context->instance, guac_rdp_get_width(context->instance), + guac_rdp_get_height(context->instance)); + + /* Store reference to the display update plugin once it's connected */ guac_disp->disp = disp; + + guac_client_log(client, GUAC_LOG_DEBUG, "Display update channel " + "will be used for display size changes."); + } /** diff --git a/src/protocols/rdp/rdp_disp.h b/src/protocols/rdp/rdp_disp.h index 562ffb65..fa39b491 100644 --- a/src/protocols/rdp/rdp_disp.h +++ b/src/protocols/rdp/rdp_disp.h @@ -91,9 +91,6 @@ guac_rdp_disp* guac_rdp_disp_alloc(); */ void guac_rdp_disp_free(guac_rdp_disp* disp); -/** - * @param context The rdpContext associated with the active RDP session. - */ /** * Adds FreeRDP's "disp" plugin to the list of dynamic virtual channel plugins * to be loaded by FreeRDP's "drdynvc" plugin. The plugin will only be loaded @@ -117,12 +114,19 @@ void guac_rdp_disp_load_plugin(rdpContext* context, guac_rdp_dvc_list* list); * display updates can be properly sent. Until this is called, changes to the * display size will be deferred. * - * @param guac_disp The display update module to associate with the connected - * display update channel. - * @param disp The DispClientContext associated by FreeRDP with the connected - * display update channel. + * @param guac_disp + * The display update module to associate with the connected display update + * channel. + * + * @param context + * The rdpContext associated with the active RDP session. + * + * @param disp + * The DispClientContext associated by FreeRDP with the connected display + * update channel. */ -void guac_rdp_disp_connect(guac_rdp_disp* guac_disp, DispClientContext* disp); +void guac_rdp_disp_connect(guac_rdp_disp* guac_disp, rdpContext* context, + DispClientContext* disp); /** * Requests a display size update, which may then be sent immediately to the From 831606a4e96d6b9c30b65eb790c31c092189bcea Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 11 Oct 2019 16:42:30 -0700 Subject: [PATCH 025/109] GUACAMOLE-249: Use pkg-config to determine location of FreeRDP headers. --- configure.ac | 16 +++++----------- src/protocols/rdp/Makefile.am | 15 ++++++++++----- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/configure.ac b/configure.ac index 6635c77e..928c4363 100644 --- a/configure.ac +++ b/configure.ac @@ -528,11 +528,10 @@ then fi # -# FreeRDP 2 +# FreeRDP 2 (libfreerdp2, libfreerdp-client2, and libwinpr2) # have_freerdp2=disabled -RDP_LIBS= AC_ARG_WITH([rdp], [AS_HELP_STRING([--with-rdp], [support RDP @<:@default=check@:>@])], @@ -542,22 +541,17 @@ AC_ARG_WITH([rdp], if test "x$with_rdp" != "xno" then have_freerdp2=yes - - # libfreerdp2 - AC_CHECK_LIB([freerdp2], [freerdp_new], - [RDP_LIBS="$RDP_LIBS -lfreerdp2 -lfreerdp-client2 -lwinpr2"], - [AC_MSG_WARN([ + PKG_CHECK_MODULES([RDP], [freerdp2 freerdp-client2 winpr2],, + [AC_MSG_WARN([ -------------------------------------------- - Unable to find libfreerdp2 + Unable to find FreeRDP (libfreerdp2 / libfreerdp-client2 / libwinpr2) RDP will be disabled. --------------------------------------------]) - have_freerdp2=no]) + have_freerdp2=no]) fi AM_CONDITIONAL([ENABLE_RDP], [test "x${have_freerdp2}" = "xyes"]) -AC_SUBST(RDP_LIBS) - # # libssh2 # diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index d3d0cf08..c22f5288 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -138,7 +138,8 @@ libguac_client_rdp_la_CFLAGS = \ -Werror -Wall -Iinclude \ @COMMON_INCLUDE@ \ @COMMON_SSH_INCLUDE@ \ - @LIBGUAC_INCLUDE@ + @LIBGUAC_INCLUDE@ \ + @RDP_CFLAGS@ libguac_client_rdp_la_LDFLAGS = \ -version-info 0:0:0 \ @@ -158,7 +159,8 @@ guacdr_cflags = \ -Werror -Wall -Iinclude \ @COMMON_INCLUDE@ \ @COMMON_SSH_INCLUDE@ \ - @LIBGUAC_INCLUDE@ + @LIBGUAC_INCLUDE@ \ + @RDP_CFLAGS@ guacdr_ldflags = \ -module -avoid-version -shared \ @@ -177,7 +179,8 @@ guacai_cflags = \ -Werror -Wall -Iinclude \ @COMMON_INCLUDE@ \ @COMMON_SSH_INCLUDE@ \ - @LIBGUAC_INCLUDE@ + @LIBGUAC_INCLUDE@ \ + @RDP_CFLAGS@ guacai_ldflags = \ -module -avoid-version -shared \ @@ -196,7 +199,8 @@ guacsnd_cflags = \ -Werror -Wall -Iinclude \ @COMMON_INCLUDE@ \ @COMMON_SSH_INCLUDE@ \ - @LIBGUAC_INCLUDE@ + @LIBGUAC_INCLUDE@ \ + @RDP_CFLAGS@ guacsnd_ldflags = \ -module -avoid-version -shared \ @@ -215,7 +219,8 @@ guacsvc_cflags = \ -Werror -Wall -Iinclude \ @COMMON_INCLUDE@ \ @COMMON_SSH_INCLUDE@ \ - @LIBGUAC_INCLUDE@ + @LIBGUAC_INCLUDE@ \ + @RDP_CFLAGS@ guacsvc_ldflags = \ -module -avoid-version -shared \ From b64b8f375a4c79bf2092ae4042042a78a2db7b35 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 11 Oct 2019 17:01:26 -0700 Subject: [PATCH 026/109] GUACAMOLE-249: Restore support for CLIPRDR channel. --- src/protocols/rdp/Makefile.am | 4 +- src/protocols/rdp/client.c | 6 +- src/protocols/rdp/clipboard.c | 527 ++++++++++++++++++++++++++++++++ src/protocols/rdp/clipboard.h | 144 +++++++++ src/protocols/rdp/rdp.c | 10 +- src/protocols/rdp/rdp.h | 13 +- src/protocols/rdp/rdp_cliprdr.c | 249 --------------- src/protocols/rdp/rdp_cliprdr.h | 110 ------- src/protocols/rdp/rdp_stream.c | 64 ---- src/protocols/rdp/rdp_stream.h | 22 +- 10 files changed, 684 insertions(+), 465 deletions(-) create mode 100644 src/protocols/rdp/clipboard.c create mode 100644 src/protocols/rdp/clipboard.h delete mode 100644 src/protocols/rdp/rdp_cliprdr.c delete mode 100644 src/protocols/rdp/rdp_cliprdr.h diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index c22f5288..b8f0ae28 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -36,6 +36,7 @@ libguac_client_rdp_la_SOURCES = \ audio_input.c \ channels.c \ client.c \ + clipboard.c \ decompose.c \ dvc.c \ error.c \ @@ -44,7 +45,6 @@ libguac_client_rdp_la_SOURCES = \ ptr_string.c \ rdp.c \ rdp_bitmap.c \ - rdp_cliprdr.c \ rdp_color.c \ rdp_disp.c \ rdp_fs.c \ @@ -104,6 +104,7 @@ noinst_HEADERS = \ guac_svc/svc_service.h \ audio_input.h \ client.h \ + clipboard.h \ channels.h \ decompose.h \ dvc.h \ @@ -113,7 +114,6 @@ noinst_HEADERS = \ ptr_string.h \ rdp.h \ rdp_bitmap.h \ - rdp_cliprdr.h \ rdp_color.h \ rdp_disp.h \ rdp_fs.h \ diff --git a/src/protocols/rdp/client.c b/src/protocols/rdp/client.c index e2f8a4c2..d99ce8b4 100644 --- a/src/protocols/rdp/client.c +++ b/src/protocols/rdp/client.c @@ -56,7 +56,7 @@ int guac_client_init(guac_client* client, int argc, char** argv) { client->data = rdp_client; /* Init clipboard */ - rdp_client->clipboard = guac_common_clipboard_alloc(GUAC_RDP_CLIPBOARD_MAX_LENGTH); + rdp_client->clipboard = guac_rdp_clipboard_alloc(client); /* Init display update module */ rdp_client->disp = guac_rdp_disp_alloc(); @@ -92,6 +92,9 @@ int guac_rdp_client_free_handler(guac_client* client) { if (rdp_client->settings != NULL) guac_rdp_settings_free(rdp_client->settings); + /* Clean up clipboard */ + guac_rdp_clipboard_free(rdp_client->clipboard); + /* Free display update module */ guac_rdp_disp_free(rdp_client->disp); @@ -128,7 +131,6 @@ int guac_rdp_client_free_handler(guac_client* client) { guac_rdp_audio_buffer_free(rdp_client->audio_input); /* Free client data */ - guac_common_clipboard_free(rdp_client->clipboard); free(rdp_client); return 0; diff --git a/src/protocols/rdp/clipboard.c b/src/protocols/rdp/clipboard.c new file mode 100644 index 00000000..b543b276 --- /dev/null +++ b/src/protocols/rdp/clipboard.c @@ -0,0 +1,527 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#include "config.h" + +#include "channels.h" +#include "client.h" +#include "clipboard.h" +#include "common/clipboard.h" +#include "common/iconv.h" +#include "rdp.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +/** + * Sends a Format List PDU to the RDP server containing the formats of + * clipboard data supported. This PDU is used both to indicate the general + * clipboard formats supported at the begining of an RDP session and to inform + * the RDP server that new clipboard data is available within the listed + * formats. + * + * @param cliprdr + * The CliprdrClientContext structure used by FreeRDP to handle the + * CLIPRDR channel for the current RDP session. + * + * @return + * CHANNEL_RC_OK (zero) if the Format List PDU was sent successfully, an + * error code (non-zero) otherwise. + */ +static UINT guac_rdp_cliprdr_send_format_list(CliprdrClientContext* cliprdr) { + + /* We support CP-1252 and UTF-16 text */ + CLIPRDR_FORMAT_LIST format_list = { + .formats = (CLIPRDR_FORMAT[]) { + { .formatId = CF_TEXT }, + { .formatId = CF_UNICODETEXT } + }, + .numFormats = 2, + .msgFlags = CB_RESPONSE_OK + }; + + return cliprdr->ClientFormatList(cliprdr, &format_list); + +} + +/** + * Callback invoked by the FreeRDP CLIPRDR plugin for received Monitor Ready + * PDUs. The Monitor Ready PDU is sent by the RDP server only during + * initialization of the CLIPRDR channel. It is part of the CLIPRDR channel + * handshake and indicates that the RDP server's handling of clipboard + * redirection is ready to proceed. + * + * @param cliprdr + * The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR + * channel for the current RDP session. + * + * @param monitor_ready + * The CLIPRDR_MONITOR_READY structure representing the Monitor Ready PDU + * that was received. + * + * @return + * CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code + * (non-zero) otherwise. + */ +static UINT guac_rdp_cliprdr_monitor_ready(CliprdrClientContext* cliprdr, + const CLIPRDR_MONITOR_READY* monitor_ready) { + + /* Respond with supported format list */ + return guac_rdp_cliprdr_send_format_list(cliprdr); + +} + +/** + * Sends a Format Data Request PDU to the RDP server, requesting that available + * clipboard data be sent to the client in the specified format. This PDU is + * sent when the server indicating that clipboard data is available via a + * Format List PDU. + * + * @param client + * The guac_client associated with the current RDP session. + * + * @param format + * The clipboard format to request. This format must be one of the + * documented values used by the CLIPRDR channel for clipboard format IDs. + * + * @return + * CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code + * (non-zero) otherwise. + */ +static UINT guac_rdp_cliprdr_send_format_data_request( + CliprdrClientContext* cliprdr, UINT32 format) { + + /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not + * callable, until after the relevant guac_rdp_clipboard structure is + * allocated and associated with the CliprdrClientContext */ + guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom; + assert(clipboard != NULL); + + /* Create new data request */ + CLIPRDR_FORMAT_DATA_REQUEST data_request = { + .requestedFormatId = format + }; + + /* Note the format we've requested for reference later when the requested + * data is received via a Format Data Response PDU */ + clipboard->requested_format = format; + + /* Send request */ + return cliprdr->ClientFormatDataRequest(cliprdr, &data_request); + +} + +/** + * Returns whether the given Format List PDU indicates support for the given + * clipboard format. + * + * @param format_list + * The CLIPRDR_FORMAT_LIST structure representing the Format List PDU + * being tested. + * + * @param format_id + * The ID of the clipboard format to test, such as CF_TEXT or + * CF_UNICODETEXT. + * + * @return + * Non-zero if the given Format List PDU indicates support for the given + * clipboard format, zero otherwise. + */ +static int guac_rdp_cliprdr_format_supported(const CLIPRDR_FORMAT_LIST* format_list, + UINT format_id) { + + /* Search format list for matching ID */ + for (int i = 0; i < format_list->numFormats; i++) { + if (format_list->formats[i].formatId == format_id) + return 1; + } + + /* If no matching ID, format is not supported */ + return 0; + +} + +/** + * Callback invoked by the FreeRDP CLIPRDR plugin for received Format List + * PDUs. The Format List PDU is sent by the RDP server to indicate that new + * clipboard data has been copied and is available for retrieval in the formats + * listed. A client wishing to retrieve that data responds with a Format Data + * Request PDU. + * + * @param cliprdr + * The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR + * channel for the current RDP session. + * + * @param format_list + * The CLIPRDR_FORMAT_LIST structure representing the Format List PDU that + * was received. + * + * @return + * CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code + * (non-zero) otherwise. + */ +static UINT guac_rdp_cliprdr_format_list(CliprdrClientContext* cliprdr, + const CLIPRDR_FORMAT_LIST* format_list) { + + /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not + * callable, until after the relevant guac_rdp_clipboard structure is + * allocated and associated with the CliprdrClientContext */ + guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom; + assert(clipboard != NULL); + + /* Prefer Unicode (in this case, UTF-16) */ + if (guac_rdp_cliprdr_format_supported(format_list, CF_UNICODETEXT)) + return guac_rdp_cliprdr_send_format_data_request(cliprdr, CF_UNICODETEXT); + + /* Use Windows' CP-1252 if Unicode unavailable */ + if (guac_rdp_cliprdr_format_supported(format_list, CF_TEXT)) + return guac_rdp_cliprdr_send_format_data_request(cliprdr, CF_TEXT); + + /* Ignore any unsupported data */ + guac_client_log(clipboard->client, GUAC_LOG_DEBUG, "Ignoring unsupported " + "clipboard data. Only Unicode and text clipboard formats are " + "currently supported."); + return CHANNEL_RC_OK; + +} + +/** + * Callback invoked by the FreeRDP CLIPRDR plugin for received Format Data + * Request PDUs. The Format Data Request PDU is sent by the RDP server when + * requesting that clipboard data be sent, in response to a received Format + * List PDU. The client is required to respond with a Format Data Response PDU + * containing the requested data. + * + * @param cliprdr + * The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR + * channel for the current RDP session. + * + * @param format_data_request + * The CLIPRDR_FORMAT_DATA_REQUEST structure representing the Format Data + * Request PDU that was received. + * + * @return + * CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code + * (non-zero) otherwise. + */ +static UINT guac_rdp_cliprdr_format_data_request(CliprdrClientContext* cliprdr, + const CLIPRDR_FORMAT_DATA_REQUEST* format_data_request) { + + /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not + * callable, until after the relevant guac_rdp_clipboard structure is + * allocated and associated with the CliprdrClientContext */ + guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom; + assert(clipboard != NULL); + + guac_iconv_write* writer; + const char* input = clipboard->clipboard->buffer; + char* output = malloc(GUAC_RDP_CLIPBOARD_MAX_LENGTH); + + /* Map requested clipboard format to a guac_iconv writer */ + switch (format_data_request->requestedFormatId) { + + case CF_TEXT: + writer = GUAC_WRITE_CP1252; + break; + + case CF_UNICODETEXT: + writer = GUAC_WRITE_UTF16; + break; + + /* Warn if clipboard data cannot be sent as intended due to a violation + * of the CLIPRDR spec */ + default: + guac_client_log(clipboard->client, GUAC_LOG_WARNING, "Received " + "clipboard data cannot be sent to the RDP server because " + "the RDP server has requested a clipboard format which " + "was not declared as available. This violates the " + "specification for the CLIPRDR channel."); + free(output); + return CHANNEL_RC_OK; + + } + + /* Send received clipboard data to the RDP server in the format + * requested */ + BYTE* start = (BYTE*) output; + guac_iconv(GUAC_READ_UTF8, &input, clipboard->clipboard->length, + writer, &output, GUAC_RDP_CLIPBOARD_MAX_LENGTH); + + CLIPRDR_FORMAT_DATA_RESPONSE data_response = { + .requestedFormatData = (BYTE*) output, + .dataLen = ((BYTE*) output) - start + }; + + return cliprdr->ClientFormatDataResponse(cliprdr, &data_response); + +} + +/** + * Callback invoked by the FreeRDP CLIPRDR plugin for received Format Data + * Response PDUs. The Format Data Response PDU is sent by the RDP server when + * fullfilling a request for clipboard data received via a Format Data Request + * PDU. + * + * @param cliprdr + * The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR + * channel for the current RDP session. + * + * @param format_data_response + * The CLIPRDR_FORMAT_DATA_RESPONSE structure representing the Format Data + * Response PDU that was received. + * + * @return + * CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code + * (non-zero) otherwise. + */ +static UINT guac_rdp_cliprdr_format_data_response(CliprdrClientContext* cliprdr, + const CLIPRDR_FORMAT_DATA_RESPONSE* format_data_response) { + + /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not + * callable, until after the relevant guac_rdp_clipboard structure is + * allocated and associated with the CliprdrClientContext */ + guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom; + assert(clipboard != NULL); + + char received_data[GUAC_RDP_CLIPBOARD_MAX_LENGTH]; + + guac_iconv_read* reader; + const char* input = (char*) format_data_response->requestedFormatData; + char* output = received_data; + + /* Find correct source encoding */ + switch (clipboard->requested_format) { + + /* Non-Unicode (Windows CP-1252) */ + case CF_TEXT: + reader = GUAC_READ_CP1252; + break; + + /* Unicode (UTF-16) */ + case CF_UNICODETEXT: + reader = GUAC_READ_UTF16; + break; + + /* If the format ID stored within the guac_rdp_clipboard structure is actually + * not supported here, then something has been implemented incorrectly. + * Either incorrect values are (somehow) being stored, or support for + * the format indicated by that value is incomplete and must be added + * here. The values which may be stored within requested_format are + * completely within our control. */ + default: + guac_client_log(clipboard->client, GUAC_LOG_DEBUG, "Requested " + "clipboard data in unsupported format (0x%X).", + clipboard->requested_format); + return CHANNEL_RC_OK; + + } + + /* Convert, store, and forward the clipboard data received from RDP + * server */ + if (guac_iconv(reader, &input, format_data_response->dataLen, + GUAC_WRITE_UTF8, &output, sizeof(received_data))) { + int length = strnlen(received_data, sizeof(received_data)); + guac_common_clipboard_reset(clipboard->clipboard, "text/plain"); + guac_common_clipboard_append(clipboard->clipboard, received_data, length); + guac_common_clipboard_send(clipboard->clipboard, clipboard->client); + } + + return CHANNEL_RC_OK; + +} + +/** + * Callback which associates handlers specific to Guacamole with the + * CliprdrClientContext instance allocated by FreeRDP to deal with received + * CLIPRDR (clipboard redirection) messages. + * + * This function is called whenever a channel connects via the PubSub event + * system within FreeRDP, but only has any effect if the connected channel is + * the CLIPRDR channel. This specific callback is registered with the PubSub + * system of the relevant rdpContext when guac_rdp_clipboard_load_plugin() is + * called. + * + * @param context + * The rdpContext associated with the active RDP session. + * + * @param e + * Event-specific arguments, mainly the name of the channel, and a + * reference to the associated plugin loaded for that channel by FreeRDP. + */ +static void guac_rdp_cliprdr_channel_connected(rdpContext* context, + ChannelConnectedEventArgs* e) { + + guac_client* client = ((rdp_freerdp_context*) context)->client; + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + guac_rdp_clipboard* clipboard = rdp_client->clipboard; + + /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not + * callable, until after the relevant guac_rdp_clipboard structure is + * allocated and associated with the guac_rdp_client */ + assert(clipboard != NULL); + + /* Ignore connection event if it's not for the CLIPRDR channel */ + if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) != 0) + return; + + /* The structure pointed to by pInterface is guaranteed to be a + * CliprdrClientContext if the channel is CLIPRDR */ + CliprdrClientContext* cliprdr = (CliprdrClientContext*) e->pInterface; + + /* Associate FreeRDP CLIPRDR context and its Guacamole counterpart with + * eachother */ + cliprdr->custom = clipboard; + clipboard->cliprdr = cliprdr; + + cliprdr->MonitorReady = guac_rdp_cliprdr_monitor_ready; + cliprdr->ServerFormatList = guac_rdp_cliprdr_format_list; + cliprdr->ServerFormatDataRequest = guac_rdp_cliprdr_format_data_request; + cliprdr->ServerFormatDataResponse = guac_rdp_cliprdr_format_data_response; + + guac_client_log(client, GUAC_LOG_DEBUG, "CLIPRDR (clipboard redirection) " + "channel connected."); + +} + +guac_rdp_clipboard* guac_rdp_clipboard_alloc(guac_client* client) { + + /* Allocate clipboard and underlying storage */ + guac_rdp_clipboard* clipboard = calloc(1, sizeof(guac_rdp_clipboard)); + clipboard->client = client; + clipboard->clipboard = guac_common_clipboard_alloc(GUAC_RDP_CLIPBOARD_MAX_LENGTH); + clipboard->requested_format = CF_TEXT; + + return clipboard; + +} + +void guac_rdp_clipboard_load_plugin(guac_rdp_clipboard* clipboard, + rdpContext* context) { + + /* Attempt to load FreeRDP support for the CLIPRDR channel */ + if (guac_freerdp_channels_load_plugin(context->channels, context->settings, "cliprdr", NULL)) { + guac_client_log(clipboard->client, GUAC_LOG_WARNING, + "Support for the CLIPRDR channel (clipboard redirection) " + "could not be loaded. This support normally takes the form of " + "a plugin which is built into FreeRDP. Lacking this support, " + "clipboard will not work."); + return; + } + + /* Complete RDP side of initialization when channel is connected */ + PubSub_SubscribeChannelConnected(context->pubSub, + (pChannelConnectedEventHandler) guac_rdp_cliprdr_channel_connected); + + guac_client_log(clipboard->client, GUAC_LOG_DEBUG, "Support for CLIPRDR " + "(clipboard redirection) registered. Awaiting channel " + "connection."); + +} + +void guac_rdp_clipboard_free(guac_rdp_clipboard* clipboard) { + + /* Do nothing if the clipboard is not actually allocated */ + if (clipboard == NULL) + return; + + /* Free clipboard and underlying storage */ + guac_common_clipboard_free(clipboard->clipboard); + free(clipboard); + +} + +int guac_rdp_clipboard_handler(guac_user* user, guac_stream* stream, + char* mimetype) { + + guac_client* client = user->client; + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + + /* Ignore stream creation if no clipboard structure is available to handle + * received data */ + guac_rdp_clipboard* clipboard = rdp_client->clipboard; + if (clipboard == NULL) + return 0; + + /* Handle any future "blob" and "end" instructions for this stream with + * handlers that are aware of the RDP clipboard state */ + stream->blob_handler = guac_rdp_clipboard_blob_handler; + stream->end_handler = guac_rdp_clipboard_end_handler; + + /* Clear any current contents, assigning the mimetype the data which will + * be received */ + guac_common_clipboard_reset(clipboard->clipboard, mimetype); + return 0; + +} + +int guac_rdp_clipboard_blob_handler(guac_user* user, guac_stream* stream, + void* data, int length) { + + guac_client* client = user->client; + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + + /* Ignore received data if no clipboard structure is available to handle + * that data */ + guac_rdp_clipboard* clipboard = rdp_client->clipboard; + if (clipboard == NULL) + return 0; + + /* Append received data to current clipboard contents */ + guac_common_clipboard_append(clipboard->clipboard, (char*) data, length); + return 0; + +} + + +int guac_rdp_clipboard_end_handler(guac_user* user, guac_stream* stream) { + + guac_client* client = user->client; + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + + /* Ignore end of stream if no clipboard structure is available to handle + * the data that was received */ + guac_rdp_clipboard* clipboard = rdp_client->clipboard; + if (clipboard == NULL) + return 0; + + /* Terminate clipboard data with NULL */ + guac_common_clipboard_append(clipboard->clipboard, "", 1); + + /* Notify RDP server of new data, if connected */ + if (clipboard->cliprdr != NULL) { + guac_client_log(client, GUAC_LOG_DEBUG, "Clipboard data received. " + "Reporting availability of clipboard data to RDP server."); + guac_rdp_cliprdr_send_format_list(clipboard->cliprdr); + } + else + guac_client_log(client, GUAC_LOG_DEBUG, "Clipboard data has been " + "received, but cannot be sent to the RDP server because the " + "CLIPRDR channel is not yet connected."); + + return 0; + +} + diff --git a/src/protocols/rdp/clipboard.h b/src/protocols/rdp/clipboard.h new file mode 100644 index 00000000..2562f12e --- /dev/null +++ b/src/protocols/rdp/clipboard.h @@ -0,0 +1,144 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#ifndef GUAC_RDP_CLIPBOARD_H +#define GUAC_RDP_CLIPBOARD_H + +#include "config.h" +#include "common/clipboard.h" + +#include +#include +#include + +/** + * RDP clipboard, leveraging the "CLIPRDR" channel. + */ +typedef struct guac_rdp_clipboard { + + /** + * The guac_client associated with the RDP connection. The broadcast + * socket of this client will receive any clipboard data received from the + * RDP server. + */ + guac_client* client; + + /** + * CLIPRDR control interface. + */ + CliprdrClientContext* cliprdr; + + /** + * The current clipboard contents. + */ + guac_common_clipboard* clipboard; + + /** + * The format of the clipboard which was requested. Data received from + * the RDP server should conform to this format. This will be one of + * several legal clipboard format values defined within FreeRDP's WinPR + * library, such as CF_TEXT. + */ + UINT requested_format; + +} guac_rdp_clipboard; + +/** + * Allocates a new guac_rdp_clipboard which has been initialized for processing + * of Guacamole clipboard data. Support for the RDP side of the clipboard (the + * CLIPRDR channel) must be loaded separately during FreeRDP's PreConnect event + * using guac_rdp_clipboard_load_plugin(). + * + * @param client + * The guac_client associated with the Guacamole side of the RDP + * connection. + * + * @return + * A newly-allocated instance of guac_rdp_clipboard which has been + * initialized for processing Guacamole clipboard data. + */ +guac_rdp_clipboard* guac_rdp_clipboard_alloc(guac_client* client); + +/** + * Initializes clipboard support for RDP and handling of the CLIPRDR channel. + * If failures occur, messages noting the specifics of those failures will be + * logged, and the RDP side of clipboard support will not be functional. + * + * This MUST be called within the PreConnect callback of the freerdp instance + * for CLIPRDR support to be loaded. + * + * @param clipboard + * The guac_rdp_clipboard instance which has been allocated for the current + * RDP connection. + * + * @param rdpContext + * The rdpContext associated with the FreeRDP side of the RDP connection. + */ +void guac_rdp_clipboard_load_plugin(guac_rdp_clipboard* clipboard, + rdpContext* context); + +/** + * Frees the resources associated with clipboard support for RDP and handling + * of the CLIPRDR channel. Only resources specific to Guacamole are freed. + * Resources specific to FreeRDP's handling of the CLIPRDR channel will be + * freed by FreeRDP. If the provided guac_rdp_clipboard is NULL, this function + * has no effect. + * + * @param clipboard + * The guac_rdp_clipboard instance which was been allocated for the current + * RDP connection. + */ +void guac_rdp_clipboard_free(guac_rdp_clipboard* clipboard); + +/** + * Handler for inbound clipboard data, received via the stream created by an + * inbound "clipboard" instruction. This handler will assign the + * stream-specific handlers for processing "blob" and "end" instructions which + * will eventually be received as clipboard data is sent. This specific handler + * is expected to be assigned to the guac_user object of any user that may send + * clipboard data. The guac_rdp_clipboard instance which will receive this data + * MUST already be stored on the guac_rdp_client structure associated with the + * current RDP connection. + */ +guac_user_clipboard_handler guac_rdp_clipboard_handler; + +/** + * Handler for stream data related to clipboard, received via "blob" + * instructions for a stream which has already been created with an inbound + * "clipboard" instruction. This specific handler is assigned to the + * guac_stream structure associated with that clipboard stream by + * guac_rdp_clipboard_handler(). The guac_rdp_clipboard instance which will + * receive this data MUST already be stored on the guac_rdp_client structure + * associated with the current RDP connection. + */ +guac_user_blob_handler guac_rdp_clipboard_blob_handler; + +/** + * Handler for end-of-stream related to clipboard, indicated via an "end" + * instruction for a stream which has already been created with an inbound + * "clipboard" instruction. This specific handler is assigned to the + * guac_stream structure associated with that clipboard stream by + * guac_rdp_clipboard_handler(). The guac_rdp_clipboard instance which will + * receive this data MUST already be stored on the guac_rdp_client structure + * associated with the current RDP connection. + */ +guac_user_end_handler guac_rdp_clipboard_end_handler; + +#endif + diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index ad490b8b..1497517d 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -22,6 +22,7 @@ #include "audio_input.h" #include "channels.h" #include "client.h" +#include "clipboard.h" #include "common/cursor.h" #include "common/display.h" #include "common/recording.h" @@ -30,7 +31,6 @@ #include "keyboard.h" #include "rdp.h" #include "rdp_bitmap.h" -#include "rdp_cliprdr.h" #include "rdp_disp.h" #include "rdp_fs.h" #include "rdp_print_job.h" @@ -109,11 +109,8 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { guac_rdp_audio_load_plugin(instance->context, dvc_list); } - /* Load clipboard plugin */ - if (guac_freerdp_channels_load_plugin(channels, instance->settings, - "cliprdr", NULL)) - guac_client_log(client, GUAC_LOG_WARNING, - "Failed to load cliprdr plugin. Clipboard will not work."); + /* Load "cliprdr" plugin for clipboard support */ + guac_rdp_clipboard_load_plugin(rdp_client->clipboard, context); /* If RDPSND/RDPDR required, load them */ if (settings->printing_enabled @@ -414,7 +411,6 @@ static int guac_rdp_handle_connection(guac_client* client) { rdp_client->current_surface = rdp_client->display->default_surface; - rdp_client->requested_clipboard_format = CF_TEXT; rdp_client->available_svc = guac_common_list_alloc(); /* Init client */ diff --git a/src/protocols/rdp/rdp.h b/src/protocols/rdp/rdp.h index 5d181a18..910e6853 100644 --- a/src/protocols/rdp/rdp.h +++ b/src/protocols/rdp/rdp.h @@ -23,6 +23,7 @@ #include "config.h" #include "audio_input.h" +#include "clipboard.h" #include "common/clipboard.h" #include "common/display.h" #include "common/list.h" @@ -95,17 +96,9 @@ typedef struct guac_rdp_client { guac_rdp_keyboard* keyboard; /** - * The current clipboard contents. + * The current state of the clipboard and the CLIPRDR channel. */ - guac_common_clipboard* clipboard; - - /** - * The format of the clipboard which was requested. Data received from - * the RDP server should conform to this format. This will be one of - * several legal clipboard format values defined within FreeRDP, such as - * CB_FORMAT_TEXT. - */ - int requested_clipboard_format; + guac_rdp_clipboard* clipboard; /** * Audio output, if any. diff --git a/src/protocols/rdp/rdp_cliprdr.c b/src/protocols/rdp/rdp_cliprdr.c deleted file mode 100644 index 52960e01..00000000 --- a/src/protocols/rdp/rdp_cliprdr.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -#include "config.h" - -#include "client.h" -#include "common/clipboard.h" -#include "common/iconv.h" -#include "rdp.h" -#include "rdp_cliprdr.h" - -#include -#include -#include -#include -#include - -#include -#include - -void guac_rdp_process_cliprdr_event(guac_client* client, wMessage* event) { -#if 0 - switch (event->event_type) { - - case CliprdrChannel_MonitorReady: - guac_rdp_process_cb_monitor_ready(client, event); - break; - - case CliprdrChannel_FormatList: - guac_rdp_process_cb_format_list(client, - (RDP_CB_FORMAT_LIST_EVENT*) event); - break; - - case CliprdrChannel_DataRequest: - guac_rdp_process_cb_data_request(client, - (RDP_CB_DATA_REQUEST_EVENT*) event); - break; - - case CliprdrChannel_DataResponse: - guac_rdp_process_cb_data_response(client, - (RDP_CB_DATA_RESPONSE_EVENT*) event); - break; - - default: - guac_client_log(client, GUAC_LOG_INFO, - "Unknown cliprdr event type: 0x%x", - GetMessageType(event->id)); - - } -#endif -} - -void guac_rdp_process_cb_monitor_ready(guac_client* client, wMessage* event) { -#if 0 - rdpChannels* channels = - ((guac_rdp_client*) client->data)->rdp_inst->context->channels; - - RDP_CB_FORMAT_LIST_EVENT* format_list = - (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new( - CliprdrChannel_Class, - CliprdrChannel_FormatList, - NULL, NULL); - - /* Received notification of clipboard support. */ - - /* Respond with supported format list */ - format_list->formats = (UINT32*) malloc(sizeof(UINT32)*2); - format_list->formats[0] = CF_TEXT; - format_list->formats[1] = CF_UNICODETEXT; - format_list->num_formats = 2; - - freerdp_channels_send_event(channels, (wMessage*) format_list); -#endif -} - -/** - * Sends a clipboard data request for the given format. - * - * @param client - * The guac_client associated with the current RDP session. - * - * @param format - * The clipboard format to request. This format must be one of the - * documented values used by the CLIPRDR channel for clipboard format IDs. - */ -static void __guac_rdp_cb_request_format(guac_client* client, int format) { -#if 0 - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - rdpChannels* channels = rdp_client->rdp_inst->context->channels; - - /* Create new data request */ - RDP_CB_DATA_REQUEST_EVENT* data_request = - (RDP_CB_DATA_REQUEST_EVENT*) freerdp_event_new( - CliprdrChannel_Class, - CliprdrChannel_DataRequest, - NULL, NULL); - - /* Set to requested format */ - rdp_client->requested_clipboard_format = format; - data_request->format = format; - - /* Send request */ - freerdp_channels_send_event(channels, (wMessage*) data_request); -#endif -} - -void guac_rdp_process_cb_format_list(guac_client* client, - RDP_CB_FORMAT_LIST_EVENT* event) { - - int formats = 0; - - /* Received notification of available data */ - - int i; - for (i=0; inum_formats; i++) { - - /* If plain text available, request it */ - if (event->formats[i] == CF_TEXT) - formats |= GUAC_RDP_CLIPBOARD_FORMAT_CP1252; - else if (event->formats[i] == CF_UNICODETEXT) - formats |= GUAC_RDP_CLIPBOARD_FORMAT_UTF16; - - } - - /* Prefer Unicode to plain text */ - if (formats & GUAC_RDP_CLIPBOARD_FORMAT_UTF16) { - __guac_rdp_cb_request_format(client, CF_UNICODETEXT); - return; - } - - /* Use plain text if Unicode unavailable */ - if (formats & GUAC_RDP_CLIPBOARD_FORMAT_CP1252) { - __guac_rdp_cb_request_format(client, CF_TEXT); - return; - } - - /* Ignore if no supported format available */ - guac_client_log(client, GUAC_LOG_INFO, "Ignoring unsupported clipboard data"); - -} - -void guac_rdp_process_cb_data_request(guac_client* client, - RDP_CB_DATA_REQUEST_EVENT* event) { -#if 0 - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - rdpChannels* channels = rdp_client->rdp_inst->context->channels; - - guac_iconv_write* writer; - const char* input = rdp_client->clipboard->buffer; - char* output = malloc(GUAC_RDP_CLIPBOARD_MAX_LENGTH); - - RDP_CB_DATA_RESPONSE_EVENT* data_response; - - /* Determine output encoding */ - switch (event->format) { - - case CF_TEXT: - writer = GUAC_WRITE_CP1252; - break; - - case CF_UNICODETEXT: - writer = GUAC_WRITE_UTF16; - break; - - default: - guac_client_log(client, GUAC_LOG_ERROR, - "Server requested unsupported clipboard data type"); - free(output); - return; - - } - - /* Create new data response */ - data_response = (RDP_CB_DATA_RESPONSE_EVENT*) freerdp_event_new( - CliprdrChannel_Class, - CliprdrChannel_DataResponse, - NULL, NULL); - - /* Set data and size */ - data_response->data = (BYTE*) output; - guac_iconv(GUAC_READ_UTF8, &input, rdp_client->clipboard->length, - writer, &output, GUAC_RDP_CLIPBOARD_MAX_LENGTH); - data_response->size = ((BYTE*) output) - data_response->data; - - /* Send response */ - freerdp_channels_send_event(channels, (wMessage*) data_response); -#endif -} - -void guac_rdp_process_cb_data_response(guac_client* client, - RDP_CB_DATA_RESPONSE_EVENT* event) { - - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - char received_data[GUAC_RDP_CLIPBOARD_MAX_LENGTH]; - - guac_iconv_read* reader; - const char* input = (char*) event->data; - char* output = received_data; - - /* Find correct source encoding */ - switch (rdp_client->requested_clipboard_format) { - - /* Non-Unicode */ - case CF_TEXT: - reader = GUAC_READ_CP1252; - break; - - /* Unicode (UTF-16) */ - case CF_UNICODETEXT: - reader = GUAC_READ_UTF16; - break; - - default: - guac_client_log(client, GUAC_LOG_ERROR, "Requested clipboard data in " - "unsupported format %i", - rdp_client->requested_clipboard_format); - return; - - } - - /* Convert send clipboard data */ - if (guac_iconv(reader, &input, event->size, - GUAC_WRITE_UTF8, &output, sizeof(received_data))) { - - int length = strnlen(received_data, sizeof(received_data)); - guac_common_clipboard_reset(rdp_client->clipboard, "text/plain"); - guac_common_clipboard_append(rdp_client->clipboard, received_data, length); - guac_common_clipboard_send(rdp_client->clipboard, client); - - } - -} - diff --git a/src/protocols/rdp/rdp_cliprdr.h b/src/protocols/rdp/rdp_cliprdr.h deleted file mode 100644 index b279d5f8..00000000 --- a/src/protocols/rdp/rdp_cliprdr.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - - -#ifndef __GUAC_RDP_RDP_CLIPRDR_H -#define __GUAC_RDP_RDP_CLIPRDR_H - -#include "config.h" - -#include -#include -#include - -/** - * Clipboard format for text encoded in Windows CP1252. - */ -#define GUAC_RDP_CLIPBOARD_FORMAT_CP1252 1 - -/** - * Clipboard format for text encoded in UTF-16. - */ -#define GUAC_RDP_CLIPBOARD_FORMAT_UTF16 2 - -/** - * Called within the main RDP connection thread whenever a CLIPRDR message is - * received. This function will dispatch that message to an appropriate - * function, specific to that message type. - * - * @param client - * The guac_client associated with the current RDP session. - * - * @param event - * The received CLIPRDR message. - */ -void guac_rdp_process_cliprdr_event(guac_client* client, wMessage* event); - -/** - * Handles the given CLIPRDR event, which MUST be a Monitor Ready event. It - * is the responsibility of this function to respond to the Monitor Ready - * event with a list of supported clipboard formats. - * - * @param client - * The guac_client associated with the current RDP session. - * - * @param event - * The received CLIPRDR message, which must be a Monitor Ready event. - */ -void guac_rdp_process_cb_monitor_ready(guac_client* client, wMessage* event); - -/** - * Handles the given CLIPRDR event, which MUST be a Format List event. It - * is the responsibility of this function to respond to the Format List - * event with a request for clipboard data in one of the enumerated formats. - * This event is fired whenever remote clipboard data is available. - * - * @param client - * The guac_client associated with the current RDP session. - * - * @param event - * The received CLIPRDR message, which must be a Format List event. - */ -void guac_rdp_process_cb_format_list(guac_client* client, - RDP_CB_FORMAT_LIST_EVENT* event); - -/** - * Handles the given CLIPRDR event, which MUST be a Data Request event. It - * is the responsibility of this function to respond to the Data Request - * event with a data response containing the current clipoard contents. - * - * @param client - * The guac_client associated with the current RDP session. - * - * @param event - * The received CLIPRDR message, which must be a Data Request event. - */ -void guac_rdp_process_cb_data_request(guac_client* client, - RDP_CB_DATA_REQUEST_EVENT* event); - -/** - * Handles the given CLIPRDR event, which MUST be a Data Response event. It - * is the responsibility of this function to read and forward the received - * clipboard data to connected clients. - * - * @param client - * The guac_client associated with the current RDP session. - * - * @param event - * The received CLIPRDR message, which must be a Data Response event. - */ -void guac_rdp_process_cb_data_response(guac_client* client, - RDP_CB_DATA_RESPONSE_EVENT* event); - -#endif - diff --git a/src/protocols/rdp/rdp_stream.c b/src/protocols/rdp/rdp_stream.c index 1e1d4708..3d33ea20 100644 --- a/src/protocols/rdp/rdp_stream.c +++ b/src/protocols/rdp/rdp_stream.c @@ -20,7 +20,6 @@ #include "config.h" #include "client.h" -#include "common/clipboard.h" #include "rdp.h" #include "rdp_fs.h" #if 0 @@ -153,24 +152,6 @@ int guac_rdp_svc_pipe_handler(guac_user* user, guac_stream* stream, } -int guac_rdp_clipboard_handler(guac_user* user, guac_stream* stream, - char* mimetype) { - - guac_client* client = user->client; - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - guac_rdp_stream* rdp_stream; - - /* Init stream data */ - stream->data = rdp_stream = malloc(sizeof(guac_rdp_stream)); - stream->blob_handler = guac_rdp_clipboard_blob_handler; - stream->end_handler = guac_rdp_clipboard_end_handler; - rdp_stream->type = GUAC_RDP_INBOUND_CLIPBOARD_STREAM; - - guac_common_clipboard_reset(rdp_client->clipboard, mimetype); - return 0; - -} - int guac_rdp_upload_blob_handler(guac_user* user, guac_stream* stream, void* data, int length) { @@ -237,16 +218,6 @@ int guac_rdp_svc_blob_handler(guac_user* user, guac_stream* stream, } -int guac_rdp_clipboard_blob_handler(guac_user* user, guac_stream* stream, - void* data, int length) { - - guac_client* client = user->client; - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - guac_common_clipboard_append(rdp_client->clipboard, (char*) data, length); - - return 0; -} - int guac_rdp_upload_end_handler(guac_user* user, guac_stream* stream) { guac_client* client = user->client; @@ -275,41 +246,6 @@ int guac_rdp_upload_end_handler(guac_user* user, guac_stream* stream) { } -int guac_rdp_clipboard_end_handler(guac_user* user, guac_stream* stream) { - - guac_client* client = user->client; - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - - /* Terminate clipboard data with NULL */ - guac_common_clipboard_append(rdp_client->clipboard, "", 1); - - /* Notify RDP server of new data, if connected */ -#if 0 - freerdp* rdp_inst = rdp_client->rdp_inst; - if (rdp_inst != NULL) { - - rdpChannels* channels = rdp_inst->context->channels; - - RDP_CB_FORMAT_LIST_EVENT* format_list = - (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new( - CliprdrChannel_Class, - CliprdrChannel_FormatList, - NULL, NULL); - - /* Notify server that text data is now available */ - format_list->formats = (UINT32*) malloc(sizeof(UINT32) * 2); - format_list->formats[0] = CF_TEXT; - format_list->formats[1] = CF_UNICODETEXT; - format_list->num_formats = 2; - - freerdp_channels_send_event(channels, (wMessage*) format_list); - - } -#endif - - return 0; -} - int guac_rdp_download_ack_handler(guac_user* user, guac_stream* stream, char* message, guac_protocol_status status) { diff --git a/src/protocols/rdp/rdp_stream.h b/src/protocols/rdp/rdp_stream.h index 427e091f..6aaa1b97 100644 --- a/src/protocols/rdp/rdp_stream.h +++ b/src/protocols/rdp/rdp_stream.h @@ -118,12 +118,7 @@ typedef enum guac_rdp_stream_type { /** * The inbound half of a static virtual channel. */ - GUAC_RDP_INBOUND_SVC_STREAM, - - /** - * An inbound stream of clipboard data. - */ - GUAC_RDP_INBOUND_CLIPBOARD_STREAM + GUAC_RDP_INBOUND_SVC_STREAM } guac_rdp_stream_type; @@ -171,11 +166,6 @@ guac_user_file_handler guac_rdp_upload_file_handler; */ guac_user_pipe_handler guac_rdp_svc_pipe_handler; -/** - * Handler for inbound clipboard data. - */ -guac_user_clipboard_handler guac_rdp_clipboard_handler; - /** * Handler for stream data related to file uploads. */ @@ -186,21 +176,11 @@ guac_user_blob_handler guac_rdp_upload_blob_handler; */ guac_user_blob_handler guac_rdp_svc_blob_handler; -/** - * Handler for stream data related to clipboard. - */ -guac_user_blob_handler guac_rdp_clipboard_blob_handler; - /** * Handler for end-of-stream related to file uploads. */ guac_user_end_handler guac_rdp_upload_end_handler; -/** - * Handler for end-of-stream related to clipboard. - */ -guac_user_end_handler guac_rdp_clipboard_end_handler; - /** * Handler for acknowledgements of receipt of data related to file downloads. */ From 8c7984d201d8d8d21d2d443ad91fe9db4aad8b2d Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 11 Oct 2019 20:38:46 -0700 Subject: [PATCH 027/109] GUACAMOLE-249: Free GDI implementation. Do not allocate cache (unnecessary). --- src/protocols/rdp/rdp.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 1497517d..46d541ff 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -184,9 +184,6 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { /* Dynamic virtual channel list is no longer needed */ guac_rdp_dvc_list_free(dvc_list); - /* Init FreeRDP cache */ - instance->context->cache = cache_new(instance->settings); - /* Init FreeRDP internal GDI implementation */ if (!gdi_init(instance, PIXEL_FORMAT_BGRX32)) return FALSE; @@ -569,8 +566,10 @@ static int guac_rdp_handle_connection(guac_client* client) { /* Disconnect client and channels */ freerdp_disconnect(rdp_inst); + /* Clean up FreeRDP internal GDI implementation */ + gdi_free(rdp_inst); + /* Clean up RDP client context */ - cache_free(rdp_inst->context->cache); freerdp_context_free(rdp_inst); /* Clean up RDP client */ From 9dd1555c8179a095e0b0d7a60493162f0044209c Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 12 Oct 2019 13:47:50 -0700 Subject: [PATCH 028/109] GUACAMOLE-249: Do not include CB_RESPONSE_OK flag in Format List PDU. The CLIPRDR specification requires that the msgFlags field for the Format List PDU be set to 0x0000. The function within FreeRDP overrides this value to 0x0000, but it is still incorrect to attempt to set it. --- src/protocols/rdp/clipboard.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/protocols/rdp/clipboard.c b/src/protocols/rdp/clipboard.c index b543b276..ec58c151 100644 --- a/src/protocols/rdp/clipboard.c +++ b/src/protocols/rdp/clipboard.c @@ -59,8 +59,7 @@ static UINT guac_rdp_cliprdr_send_format_list(CliprdrClientContext* cliprdr) { { .formatId = CF_TEXT }, { .formatId = CF_UNICODETEXT } }, - .numFormats = 2, - .msgFlags = CB_RESPONSE_OK + .numFormats = 2 }; return cliprdr->ClientFormatList(cliprdr, &format_list); From de493ba959365c3ba3d5c2bdf085134abb69ce0b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 12 Oct 2019 13:49:57 -0700 Subject: [PATCH 029/109] GUACAMOLE-249: Send Format List Response PDU after successfully processing a Format List PDU. --- src/protocols/rdp/clipboard.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/protocols/rdp/clipboard.c b/src/protocols/rdp/clipboard.c index ec58c151..38d13948 100644 --- a/src/protocols/rdp/clipboard.c +++ b/src/protocols/rdp/clipboard.c @@ -191,6 +191,13 @@ static UINT guac_rdp_cliprdr_format_list(CliprdrClientContext* cliprdr, guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom; assert(clipboard != NULL); + CLIPRDR_FORMAT_LIST_RESPONSE format_list_response = { + .msgFlags = CB_RESPONSE_OK + }; + + /* Report successful processing of format list */ + cliprdr->ClientFormatListResponse(cliprdr, &format_list_response); + /* Prefer Unicode (in this case, UTF-16) */ if (guac_rdp_cliprdr_format_supported(format_list, CF_UNICODETEXT)) return guac_rdp_cliprdr_send_format_data_request(cliprdr, CF_UNICODETEXT); From eab07b4a6127ea1237bc19eed47fcbf57796d919 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 12 Oct 2019 13:50:55 -0700 Subject: [PATCH 030/109] GUACAMOLE-249: Add trace-level logging of received and sent CLIPRDR PDUs. --- src/protocols/rdp/clipboard.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/protocols/rdp/clipboard.c b/src/protocols/rdp/clipboard.c index 38d13948..77b3dabd 100644 --- a/src/protocols/rdp/clipboard.c +++ b/src/protocols/rdp/clipboard.c @@ -53,6 +53,13 @@ */ static UINT guac_rdp_cliprdr_send_format_list(CliprdrClientContext* cliprdr) { + /* This function is only invoked within FreeRDP-specific handlers for + * CLIPRDR, which are not assigned, and thus not callable, until after the + * relevant guac_rdp_clipboard structure is allocated and associated with + * the CliprdrClientContext */ + guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom; + assert(clipboard != NULL); + /* We support CP-1252 and UTF-16 text */ CLIPRDR_FORMAT_LIST format_list = { .formats = (CLIPRDR_FORMAT[]) { @@ -62,6 +69,9 @@ static UINT guac_rdp_cliprdr_send_format_list(CliprdrClientContext* cliprdr) { .numFormats = 2 }; + guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending " + "format list"); + return cliprdr->ClientFormatList(cliprdr, &format_list); } @@ -88,6 +98,15 @@ static UINT guac_rdp_cliprdr_send_format_list(CliprdrClientContext* cliprdr) { static UINT guac_rdp_cliprdr_monitor_ready(CliprdrClientContext* cliprdr, const CLIPRDR_MONITOR_READY* monitor_ready) { + /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not + * callable, until after the relevant guac_rdp_clipboard structure is + * allocated and associated with the CliprdrClientContext */ + guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom; + assert(clipboard != NULL); + + guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received " + "monitor ready."); + /* Respond with supported format list */ return guac_rdp_cliprdr_send_format_list(cliprdr); @@ -128,6 +147,9 @@ static UINT guac_rdp_cliprdr_send_format_data_request( * data is received via a Format Data Response PDU */ clipboard->requested_format = format; + guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending " + "format data request."); + /* Send request */ return cliprdr->ClientFormatDataRequest(cliprdr, &data_request); @@ -191,6 +213,9 @@ static UINT guac_rdp_cliprdr_format_list(CliprdrClientContext* cliprdr, guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom; assert(clipboard != NULL); + guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received " + "format list."); + CLIPRDR_FORMAT_LIST_RESPONSE format_list_response = { .msgFlags = CB_RESPONSE_OK }; @@ -210,6 +235,7 @@ static UINT guac_rdp_cliprdr_format_list(CliprdrClientContext* cliprdr, guac_client_log(clipboard->client, GUAC_LOG_DEBUG, "Ignoring unsupported " "clipboard data. Only Unicode and text clipboard formats are " "currently supported."); + return CHANNEL_RC_OK; } @@ -242,6 +268,9 @@ static UINT guac_rdp_cliprdr_format_data_request(CliprdrClientContext* cliprdr, guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom; assert(clipboard != NULL); + guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received " + "format data request."); + guac_iconv_write* writer; const char* input = clipboard->clipboard->buffer; char* output = malloc(GUAC_RDP_CLIPBOARD_MAX_LENGTH); @@ -281,6 +310,9 @@ static UINT guac_rdp_cliprdr_format_data_request(CliprdrClientContext* cliprdr, .dataLen = ((BYTE*) output) - start }; + guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending " + "format data response."); + return cliprdr->ClientFormatDataResponse(cliprdr, &data_response); } @@ -312,6 +344,9 @@ static UINT guac_rdp_cliprdr_format_data_response(CliprdrClientContext* cliprdr, guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom; assert(clipboard != NULL); + guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received " + "format data response."); + char received_data[GUAC_RDP_CLIPBOARD_MAX_LENGTH]; guac_iconv_read* reader; From 07f6e6afc28f8c65bed2e3d1e53d1a43b768c18d Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 13 Oct 2019 15:30:02 -0700 Subject: [PATCH 031/109] GUACAMOLE-249: Remove guac_rdp_dvc_list, relying instead on the DVC channel collection within rdpSettings. --- src/protocols/rdp/Makefile.am | 6 +- src/protocols/rdp/audio_input.c | 6 +- src/protocols/rdp/audio_input.h | 12 +- src/protocols/rdp/channels.c | 49 ++++--- src/protocols/rdp/channels.h | 57 +++++++-- src/protocols/rdp/client.c | 2 +- src/protocols/rdp/{rdp_disp.c => disp.c} | 57 ++++++--- src/protocols/rdp/{rdp_disp.h => disp.h} | 63 ++++----- src/protocols/rdp/dvc.c | 156 ----------------------- src/protocols/rdp/dvc.h | 138 -------------------- src/protocols/rdp/input.c | 2 +- src/protocols/rdp/rdp.c | 23 ++-- src/protocols/rdp/rdp.h | 2 +- src/protocols/rdp/rdp_settings.c | 4 + 14 files changed, 166 insertions(+), 411 deletions(-) rename src/protocols/rdp/{rdp_disp.c => disp.c} (78%) rename src/protocols/rdp/{rdp_disp.h => disp.h} (78%) delete mode 100644 src/protocols/rdp/dvc.c delete mode 100644 src/protocols/rdp/dvc.h diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index b8f0ae28..a1d3600a 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -38,7 +38,7 @@ libguac_client_rdp_la_SOURCES = \ client.c \ clipboard.c \ decompose.c \ - dvc.c \ + disp.c \ error.c \ input.c \ keyboard.c \ @@ -46,7 +46,6 @@ libguac_client_rdp_la_SOURCES = \ rdp.c \ rdp_bitmap.c \ rdp_color.c \ - rdp_disp.c \ rdp_fs.c \ rdp_gdi.c \ rdp_glyph.c \ @@ -107,7 +106,7 @@ noinst_HEADERS = \ clipboard.h \ channels.h \ decompose.h \ - dvc.h \ + disp.h \ error.h \ input.h \ keyboard.h \ @@ -115,7 +114,6 @@ noinst_HEADERS = \ rdp.h \ rdp_bitmap.h \ rdp_color.h \ - rdp_disp.h \ rdp_fs.h \ rdp_gdi.h \ rdp_glyph.h \ diff --git a/src/protocols/rdp/audio_input.c b/src/protocols/rdp/audio_input.c index 014ea2db..a0dd24a8 100644 --- a/src/protocols/rdp/audio_input.c +++ b/src/protocols/rdp/audio_input.c @@ -19,7 +19,7 @@ #include "config.h" #include "audio_input.h" -#include "dvc.h" +#include "channels.h" #include "ptr_string.h" #include "rdp.h" @@ -182,14 +182,14 @@ int guac_rdp_audio_end_handler(guac_user* user, guac_stream* stream) { } -void guac_rdp_audio_load_plugin(rdpContext* context, guac_rdp_dvc_list* list) { +void guac_rdp_audio_load_plugin(rdpContext* context) { guac_client* client = ((rdp_freerdp_context*) context)->client; char client_ref[GUAC_RDP_PTR_STRING_LENGTH]; /* Add "AUDIO_INPUT" channel */ guac_rdp_ptr_to_string(client, client_ref); - guac_rdp_dvc_list_add(list, "guacai", client_ref, NULL); + guac_freerdp_dynamic_channel_collection_add(context->settings, "guacai", client_ref, NULL); } diff --git a/src/protocols/rdp/audio_input.h b/src/protocols/rdp/audio_input.h index 62806628..3f987619 100644 --- a/src/protocols/rdp/audio_input.h +++ b/src/protocols/rdp/audio_input.h @@ -21,7 +21,6 @@ #define GUAC_RDP_AUDIO_INPUT_H #include "config.h" -#include "dvc.h" #include #include @@ -296,18 +295,13 @@ guac_user_end_handler guac_rdp_audio_end_handler; /** * Adds Guacamole's "guacai" plugin to the list of dynamic virtual channel * plugins to be loaded by FreeRDP's "drdynvc" plugin. The plugin will only - * be loaded once guac_rdp_load_drdynvc() is invoked with the guac_rdp_dvc_list - * passed to this function. The "guacai" plugin ultimately adds support for the - * "AUDIO_INPUT" dynamic virtual channel. + * be loaded once the "drdynvc" plugin is loaded. The "guacai" plugin + * ultimately adds support for the "AUDIO_INPUT" dynamic virtual channel. * * @param context * The rdpContext associated with the active RDP session. - * - * @param list - * The guac_rdp_dvc_list to which the "guacai" plugin should be added, such - * that it may later be loaded by guac_rdp_load_drdynvc(). */ -void guac_rdp_audio_load_plugin(rdpContext* context, guac_rdp_dvc_list* list); +void guac_rdp_audio_load_plugin(rdpContext* context); #endif diff --git a/src/protocols/rdp/channels.c b/src/protocols/rdp/channels.c index ac474304..63512fe0 100644 --- a/src/protocols/rdp/channels.c +++ b/src/protocols/rdp/channels.c @@ -24,22 +24,6 @@ #include #include -void guac_rdp_channel_connected(rdpContext* context, - ChannelConnectedEventArgs* e) { - - guac_client* client = ((rdp_freerdp_context*) context)->client; - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - - guac_client_log(client, GUAC_LOG_DEBUG, "Channel \"%s\" connected.", e->name); - - /* Display update channel */ - if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) == 0) { - DispClientContext* disp = (DispClientContext*) e->pInterface; - guac_rdp_disp_connect(rdp_client->disp, context, disp); - } - -} - int guac_freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, const char* name, void* data) { @@ -62,3 +46,36 @@ int guac_freerdp_channels_load_plugin(rdpChannels* channels, } +void guac_freerdp_dynamic_channel_collection_add(rdpSettings* settings, + const char* name, ...) { + + va_list args; + + ADDIN_ARGV* freerdp_args = malloc(sizeof(ADDIN_ARGV)); + + va_start(args, name); + + /* Count number of arguments (excluding terminating NULL) */ + freerdp_args->argc = 1; + while (va_arg(args, char*) != NULL) + freerdp_args->argc++; + + /* Reset va_list */ + va_end(args); + va_start(args, name); + + /* Copy argument values into DVC entry */ + freerdp_args->argv = malloc(sizeof(char*) * freerdp_args->argc); + freerdp_args->argv[0] = strdup(name); + int i; + for (i = 1; i < freerdp_args->argc; i++) + freerdp_args->argv[i] = strdup(va_arg(args, char*)); + + va_end(args); + + /* Register plugin with FreeRDP */ + settings->SupportDynamicChannels = TRUE; + freerdp_dynamic_channel_collection_add(settings, freerdp_args); + +} + diff --git a/src/protocols/rdp/channels.h b/src/protocols/rdp/channels.h index f8c7bcc6..d8a8f619 100644 --- a/src/protocols/rdp/channels.h +++ b/src/protocols/rdp/channels.h @@ -25,20 +25,6 @@ #include #include -/** - * Called whenever a channel connects via the PubSub event system within - * FreeRDP. - * - * @param context - * The rdpContext associated with the active RDP session. - * - * @param e - * Event-specific arguments, mainly the name of the channel, and a - * reference to the associated plugin loaded for that channel by FreeRDP. - */ -void guac_rdp_channel_connected(rdpContext* context, - ChannelConnectedEventArgs* e); - /** * Loads the FreeRDP plugin having the given name. This function is a drop-in * replacement for freerdp_channels_load_plugin() which additionally loads @@ -47,6 +33,9 @@ void guac_rdp_channel_connected(rdpContext* context, * part of FreeRDP can load only plugins which implement the * PVIRTUALCHANNELENTRY version of the entry point. * + * This MUST be called within the PreConnect callback of the freerdp instance + * for the referenced plugin to be loaded correctly. + * * @param channels * The rdpChannels structure with which the plugin should be registered * once loaded. This structure should be retrieved directly from the @@ -76,5 +65,45 @@ void guac_rdp_channel_connected(rdpContext* context, int guac_freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, const char* name, void* data); +/** + * Schedules loading of the FreeRDP dynamic virtual channel plugin having the + * given name. This function is essentially a wrapper for + * freerdp_dynamic_channel_collection_add() which additionally takes care of + * housekeeping tasks which would otherwise need to be performed manually: + * + * - The ADDIN_ARGV structure used to pass arguments to dynamic virtual + * channel plugins is automatically allocated and populated with any given + * arguments. + * - The SupportDynamicChannels member of the rdpSettings structure is + * automatically set to TRUE. + * + * The "drdynvc" plugin must still eventually be loaded for this function to + * have any effect, as it is the "drdynvc" plugin which processes the + * collection this function manipulates. + * + * This MUST be called within the PreConnect callback of the freerdp instance + * and the "drdynvc" plugin MUST be loaded at some point after this function is + * called for the referenced dynamic channel plugin to be loaded correctly. + * + * @param settings + * The rdpSettings structure associated with the FreeRDP instance, already + * populated with any settings applicable to the plugin being loaded. + * + * @param name + * The name of the plugin to load. If the plugin is not statically built + * into FreeRDP, this name will determine the filename of the library to be + * loaded dynamically. For a plugin named "NAME", the library called + * "libNAME-client" will be loaded from the "freerdp2" subdirectory of the + * main directory containing the FreeRDP libraries. + * + * @param ... + * Arbitrary arguments to be passed to the plugin entry point. For most + * plugins which are built into FreeRDP, this will be another reference to + * the rdpSettings struct or NULL. The source of the relevant plugin must + * be consulted to determine the proper value(s) to pass here. + */ +void guac_freerdp_dynamic_channel_collection_add(rdpSettings* settings, + const char* name, ...); + #endif diff --git a/src/protocols/rdp/client.c b/src/protocols/rdp/client.c index d99ce8b4..0c0b4bb8 100644 --- a/src/protocols/rdp/client.c +++ b/src/protocols/rdp/client.c @@ -22,8 +22,8 @@ #include "audio_input.h" #include "common/recording.h" #include "client.h" +#include "disp.h" #include "rdp.h" -#include "rdp_disp.h" #include "rdp_fs.h" #include "user.h" diff --git a/src/protocols/rdp/rdp_disp.c b/src/protocols/rdp/disp.c similarity index 78% rename from src/protocols/rdp/rdp_disp.c rename to src/protocols/rdp/disp.c index f152fa53..cb37d8bb 100644 --- a/src/protocols/rdp/rdp_disp.c +++ b/src/protocols/rdp/disp.c @@ -18,16 +18,17 @@ */ #include "config.h" +#include "channels.h" #include "client.h" -#include "dvc.h" +#include "disp.h" #include "rdp.h" -#include "rdp_disp.h" #include "rdp_settings.h" #include #include #include #include +#include guac_rdp_disp* guac_rdp_disp_alloc() { @@ -50,33 +51,42 @@ void guac_rdp_disp_free(guac_rdp_disp* disp) { free(disp); } -void guac_rdp_disp_load_plugin(rdpContext* context, guac_rdp_dvc_list* list) { - - context->settings->SupportDisplayControl = TRUE; - - /* Add "disp" channel */ - guac_rdp_dvc_list_add(list, "disp", NULL); - -} - -void guac_rdp_disp_connect(guac_rdp_disp* guac_disp, rdpContext* context, - DispClientContext* disp) { +/** + * Callback which associates handlers specific to Guacamole with the + * DispClientContext instance allocated by FreeRDP to deal with received + * Display Update (client-initiated dynamic display resizing) messages. + * + * This function is called whenever a channel connects via the PubSub event + * system within FreeRDP, but only has any effect if the connected channel is + * the Display Update channel. This specific callback is registered with the + * PubSub system of the relevant rdpContext when guac_rdp_disp_load_plugin() is + * called. + * + * @param context + * The rdpContext associated with the active RDP session. + * + * @param e + * Event-specific arguments, mainly the name of the channel, and a + * reference to the associated plugin loaded for that channel by FreeRDP. + */ +static void guac_rdp_disp_channel_connected(rdpContext* context, + ChannelConnectedEventArgs* e) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - guac_rdp_settings* settings = rdp_client->settings; + guac_rdp_disp* guac_disp = rdp_client->disp; - /* Ignore connected channel if not configured to use the display update - * channel for resize */ - if (settings->resize_method != GUAC_RESIZE_DISPLAY_UPDATE) + /* Ignore connection event if it's not for the Display Update channel */ + if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) != 0) return; /* Init module with current display size */ - guac_rdp_disp_set_size(rdp_client->disp, rdp_client->settings, + guac_rdp_disp_set_size(guac_disp, rdp_client->settings, context->instance, guac_rdp_get_width(context->instance), guac_rdp_get_height(context->instance)); /* Store reference to the display update plugin once it's connected */ + DispClientContext* disp = (DispClientContext*) e->pInterface; guac_disp->disp = disp; guac_client_log(client, GUAC_LOG_DEBUG, "Display update channel " @@ -84,6 +94,17 @@ void guac_rdp_disp_connect(guac_rdp_disp* guac_disp, rdpContext* context, } +void guac_rdp_disp_load_plugin(rdpContext* context) { + + /* Subscribe to and handle channel connected events */ + PubSub_SubscribeChannelConnected(context->pubSub, + (pChannelConnectedEventHandler) guac_rdp_disp_channel_connected); + + /* Add "disp" channel */ + guac_freerdp_dynamic_channel_collection_add(context->settings, "disp", NULL); + +} + /** * Fits a given dimension within the allowed bounds for Display Update * messages, adjusting the other dimension such that aspect ratio is diff --git a/src/protocols/rdp/rdp_disp.h b/src/protocols/rdp/disp.h similarity index 78% rename from src/protocols/rdp/rdp_disp.h rename to src/protocols/rdp/disp.h index fa39b491..04df7527 100644 --- a/src/protocols/rdp/rdp_disp.h +++ b/src/protocols/rdp/disp.h @@ -20,11 +20,12 @@ #ifndef GUAC_RDP_DISP_H #define GUAC_RDP_DISP_H -#include "dvc.h" #include "rdp_settings.h" #include #include +#include +#include /** * The minimum value for width or height, in pixels. @@ -78,55 +79,43 @@ typedef struct guac_rdp_disp { /** * Allocates a new display update module, which will ultimately control the - * display update channel once conected. + * display update channel once connected. * - * @return A new display update module. + * @return + * A newly-allocated display update module. */ guac_rdp_disp* guac_rdp_disp_alloc(); /** - * Frees the given display update module. + * Frees the resources associated with support for the RDP Display Update + * channel. Only resources specific to Guacamole are freed. Resources specific + * to FreeRDP's handling of the Display Update channel will be freed by + * FreeRDP. If no resources are currently allocated for Display Update support, + * this function has no effect. * - * @param disp The display update module to free. + * @param disp + * The display update module to free. */ void guac_rdp_disp_free(guac_rdp_disp* disp); /** * Adds FreeRDP's "disp" plugin to the list of dynamic virtual channel plugins - * to be loaded by FreeRDP's "drdynvc" plugin. The plugin will only be loaded - * once guac_rdp_load_drdynvc() is invoked with the guac_rdp_dvc_list passed to - * this function. The "disp" plugin ultimately adds support for the Display - * Update channel. NOTE: It is still up to external code to detect when the - * "disp" channel is connected, and update the guac_rdp_disp with a call to - * guac_rdp_disp_connect(). + * to be loaded by FreeRDP's "drdynvc" plugin. The context of the plugin will + * automatically be assicated with the guac_rdp_disp instance pointed to by the + * current guac_rdp_client. The plugin will only be loaded once the "drdynvc" + * plugin is loaded. The "disp" plugin ultimately adds support for the Display + * Update channel. + * + * If failures occur, messages noting the specifics of those failures will be + * logged, and the RDP side of Display Update support will not be functional. + * + * This MUST be called within the PreConnect callback of the freerdp instance + * for Display Update support to be loaded. * * @param context * The rdpContext associated with the active RDP session. - * - * @param list - * The guac_rdp_dvc_list to which the "disp" plugin should be added, such - * that it may later be loaded by guac_rdp_load_drdynvc(). */ -void guac_rdp_disp_load_plugin(rdpContext* context, guac_rdp_dvc_list* list); - -/** - * Stores the given DispClientContext within the given guac_rdp_disp, such that - * display updates can be properly sent. Until this is called, changes to the - * display size will be deferred. - * - * @param guac_disp - * The display update module to associate with the connected display update - * channel. - * - * @param context - * The rdpContext associated with the active RDP session. - * - * @param disp - * The DispClientContext associated by FreeRDP with the connected display - * update channel. - */ -void guac_rdp_disp_connect(guac_rdp_disp* guac_disp, rdpContext* context, - DispClientContext* disp); +void guac_rdp_disp_load_plugin(rdpContext* context); /** * Requests a display size update, which may then be sent immediately to the @@ -197,6 +186,10 @@ void guac_rdp_disp_reconnect_complete(guac_rdp_disp* disp); * Returns whether a full RDP reconnect is required for display update changes * to take effect. * + * @param client + * The guac_client associated with the Guacamole side of the RDP + * connection. + * * @return * Non-zero if a reconnect is needed, zero otherwise. */ diff --git a/src/protocols/rdp/dvc.c b/src/protocols/rdp/dvc.c deleted file mode 100644 index 55bf85b5..00000000 --- a/src/protocols/rdp/dvc.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -#include "config.h" -#include "common/list.h" -#include "channels.h" -#include "dvc.h" -#include "rdp.h" - -#include -#include -#include - -#include -#include - -guac_rdp_dvc_list* guac_rdp_dvc_list_alloc() { - - guac_rdp_dvc_list* list = malloc(sizeof(guac_rdp_dvc_list)); - - /* Initialize with empty backing list */ - list->channels = guac_common_list_alloc(); - list->channel_count = 0; - - return list; - -} - -void guac_rdp_dvc_list_add(guac_rdp_dvc_list* list, const char* name, ...) { - - va_list args; - - guac_rdp_dvc* dvc = malloc(sizeof(guac_rdp_dvc)); - - va_start(args, name); - - /* Count number of arguments (excluding terminating NULL) */ - dvc->argc = 1; - while (va_arg(args, char*) != NULL) - dvc->argc++; - - /* Reset va_list */ - va_end(args); - va_start(args, name); - - /* Copy argument values into DVC entry */ - dvc->argv = malloc(sizeof(char*) * dvc->argc); - dvc->argv[0] = strdup(name); - int i; - for (i = 1; i < dvc->argc; i++) - dvc->argv[i] = strdup(va_arg(args, char*)); - - va_end(args); - - /* Add entry to DVC list */ - guac_common_list_add(list->channels, dvc); - - /* Update channel count */ - list->channel_count++; - -} - -void guac_rdp_dvc_list_free(guac_rdp_dvc_list* list) { - - /* For each channel */ - guac_common_list_element* current = list->channels->head; - while (current != NULL) { - - /* Free arguments declaration for current channel */ - guac_rdp_dvc* dvc = (guac_rdp_dvc*) current->data; - - /* Free the underlying arguments list if not delegated to FreeRDP */ - if (dvc->argv != NULL) { - - /* Free each argument value */ - for (int i = 0; i < dvc->argc; i++) - free(dvc->argv[i]); - - free(dvc->argv); - } - - free(dvc); - - current = current->next; - - } - - /* Free underlying list */ - guac_common_list_free(list->channels); - - /* Free the DVC list itself */ - free(list); - -} - -int guac_rdp_load_drdynvc(rdpContext* context, guac_rdp_dvc_list* list) { - - guac_client* client = ((rdp_freerdp_context*) context)->client; - rdpChannels* channels = context->channels; - - /* Skip if no channels will be loaded */ - if (list->channel_count == 0) - return 0; - - /* For each channel */ - guac_common_list_element* current = list->channels->head; - while (current != NULL) { - - /* Get channel arguments */ - guac_rdp_dvc* dvc = (guac_rdp_dvc*) current->data; - current = current->next; - - /* guac_rdp_dvc_list_add() guarantees at one argument */ - assert(dvc->argc >= 1); - - /* guac_rdp_load_drdynvc() MUST only be invoked once */ - assert(dvc->argv != NULL); - - /* Log registration of plugin for current channel */ - guac_client_log(client, GUAC_LOG_DEBUG, - "Registering DVC plugin \"%s\"", dvc->argv[0]); - - /* Register plugin with FreeRDP */ - ADDIN_ARGV* args = malloc(sizeof(ADDIN_ARGV)); - args->argc = dvc->argc; - args->argv = dvc->argv; - freerdp_dynamic_channel_collection_add(context->settings, args); - - /* Rely on FreeRDP to free argv storage */ - dvc->argv = NULL; - - } - - /* Load virtual channel management plugin */ - return guac_freerdp_channels_load_plugin(channels, - context->instance->settings, "drdynvc", - context->instance->settings); - -} - diff --git a/src/protocols/rdp/dvc.h b/src/protocols/rdp/dvc.h deleted file mode 100644 index 63694f53..00000000 --- a/src/protocols/rdp/dvc.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -#ifndef GUAC_RDP_DVC_H -#define GUAC_RDP_DVC_H - -#include "config.h" -#include "common/list.h" - -#include - -/** - * The set of all arguments that should be passed to a given dynamic virtual - * channel plugin, including the name of that plugin. - */ -typedef struct guac_rdp_dvc { - - /** - * The number of arguments in the argv array. This MUST be at least 1. - */ - int argc; - - /** - * The argument values being passed to the dynamic virtual channel plugin. - * The first entry in this array is always the name of the plugin. If - * guac_rdp_load_drdynvc() has been invoked, and freeing the argument - * values is being delegated to FreeRDP, this will be NULL. - */ - char** argv; - -} guac_rdp_dvc; - -/** - * A list of dynamic virtual channels which should be provided to the DRDYNVC - * plugin once loaded via guac_rdp_load_drdynvc(). This interface exists purely - * to bridge incompatibilities between differing versions of FreeRDP and its - * DRDYNVC plugin. Any allocated guac_rdp_dvc_list is unlikely to be needed - * after the DRDYNVC plugin has been loaded. - */ -typedef struct guac_rdp_dvc_list { - - /** - * Array of all dynamic virtual channels which should be registered with - * the DRDYNVC plugin once loaded. Each list element will point to a - * guac_rdp_dvc structure which must eventually be freed. - */ - guac_common_list* channels; - - /** - * The number of channels within the list. - */ - int channel_count; - -} guac_rdp_dvc_list; - -/** - * Allocates a new, empty list of dynamic virtual channels. New channels may - * be added via guac_rdp_dvc_list_add(). The loading of those channels' - * associated plugins will be deferred until guac_rdp_load_drdynvc() is - * invoked. - * - * @return - * A newly-allocated, empty list of dynamic virtual channels. - */ -guac_rdp_dvc_list* guac_rdp_dvc_list_alloc(); - -/** - * Adds the given dynamic virtual channel plugin name and associated arguments - * to the list. The provied arguments list is NOT optional and MUST be - * NULL-terminated, even if there are no arguments for the named dynamic - * virtual channel plugin. Though FreeRDP requires that the arguments for a - * dynamic virtual channel plugin contain the name of the plugin itself as the - * first argument, the name must be excluded from the arguments provided here. - * This function will automatically take care of adding the plugin name to - * the arguments. - * - * @param list - * The guac_rdp_dvc_list to which the given plugin name and arguments - * should be added, for later bulk registration via - * guac_rdp_load_drdynvc(). - * - * @param name - * The name of the dynamic virtual channel plugin that should be given - * the provided arguments when guac_rdp_load_drdynvc() is invoked. - * - * @param ... - * The string (char*) arguments which should be passed to the dynamic - * virtual channel plugin when it is loaded via guac_rdp_load_drdynvc(), - * excluding the plugin name itself. - */ -void guac_rdp_dvc_list_add(guac_rdp_dvc_list* list, const char* name, ...); - -/** - * Frees the given list of dynamic virtual channels. Note that, while each - * individual entry within this list will be freed, it is partially up to - * FreeRDP to free the storage associated with the arguments passed to the - * virtual channels. - * - * @param list - * The list to free. - */ -void guac_rdp_dvc_list_free(guac_rdp_dvc_list* list); - -/** - * Loads FreeRDP's DRDYNVC plugin and registers the dynamic virtual channel - * plugins described by the given guac_rdp_dvc_list. This function MUST be - * invoked no more than once per RDP connection. Invoking this function - * multiple times, even if the guac_rdp_dvc_list is different each time, will - * result in undefined behavior. - * - * @param context - * The rdpContext associated with the RDP connection for which the DRDYNVC - * plugin should be loaded. - * - * @param list - * A guac_rdp_dvc_list describing the dynamic virtual channel plugins that - * should be registered with the DRDYNVC plugin, along with any arguments. - */ -int guac_rdp_load_drdynvc(rdpContext* context, guac_rdp_dvc_list* list); - -#endif - diff --git a/src/protocols/rdp/input.c b/src/protocols/rdp/input.c index 96507db2..2c3ef14b 100644 --- a/src/protocols/rdp/input.c +++ b/src/protocols/rdp/input.c @@ -21,10 +21,10 @@ #include "client.h" #include "common/recording.h" +#include "disp.h" #include "input.h" #include "keyboard.h" #include "rdp.h" -#include "rdp_disp.h" #include #include diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 46d541ff..0923a53c 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -26,12 +26,11 @@ #include "common/cursor.h" #include "common/display.h" #include "common/recording.h" -#include "dvc.h" +#include "disp.h" #include "error.h" #include "keyboard.h" #include "rdp.h" #include "rdp_bitmap.h" -#include "rdp_disp.h" #include "rdp_fs.h" #include "rdp_print_job.h" #include "rdp_gdi.h" @@ -90,23 +89,17 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_settings* settings = rdp_client->settings; - guac_rdp_dvc_list* dvc_list = guac_rdp_dvc_list_alloc(); - /* Init FreeRDP add-in provider */ freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0); - /* Subscribe to and handle channel connected events */ - PubSub_SubscribeChannelConnected(context->pubSub, - (pChannelConnectedEventHandler) guac_rdp_channel_connected); - /* Load "disp" plugin for display update */ if (settings->resize_method == GUAC_RESIZE_DISPLAY_UPDATE) - guac_rdp_disp_load_plugin(instance->context, dvc_list); + guac_rdp_disp_load_plugin(context); /* Load "AUDIO_INPUT" plugin for audio input*/ if (settings->enable_audio_input) { rdp_client->audio_input = guac_rdp_audio_buffer_alloc(); - guac_rdp_audio_load_plugin(instance->context, dvc_list); + guac_rdp_audio_load_plugin(instance->context); } /* Load "cliprdr" plugin for clipboard support */ @@ -175,14 +168,14 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { } #endif - /* Load DRDYNVC plugin if required */ - if (guac_rdp_load_drdynvc(instance->context, dvc_list)) + /* Load plugin providing Dynamic Virtual Channel support, if required */ + if (instance->settings->SupportDynamicChannels && + guac_freerdp_channels_load_plugin(channels, instance->settings, + "drdynvc", instance->settings)) { guac_client_log(client, GUAC_LOG_WARNING, "Failed to load drdynvc plugin. Display update and audio " "input support will be disabled."); - - /* Dynamic virtual channel list is no longer needed */ - guac_rdp_dvc_list_free(dvc_list); + } /* Init FreeRDP internal GDI implementation */ if (!gdi_init(instance, PIXEL_FORMAT_BGRX32)) diff --git a/src/protocols/rdp/rdp.h b/src/protocols/rdp/rdp.h index 910e6853..5220a6c2 100644 --- a/src/protocols/rdp/rdp.h +++ b/src/protocols/rdp/rdp.h @@ -29,8 +29,8 @@ #include "common/list.h" #include "common/recording.h" #include "common/surface.h" +#include "disp.h" #include "keyboard.h" -#include "rdp_disp.h" #include "rdp_fs.h" #include "rdp_print_job.h" #include "rdp_settings.h" diff --git a/src/protocols/rdp/rdp_settings.c b/src/protocols/rdp/rdp_settings.c index 5c86742c..e64aa07a 100644 --- a/src/protocols/rdp/rdp_settings.c +++ b/src/protocols/rdp/rdp_settings.c @@ -1192,6 +1192,10 @@ void guac_rdp_push_settings(guac_client* client, /* Audio capture */ rdp_settings->AudioCapture = guac_settings->enable_audio_input; + /* Display Update channel */ + rdp_settings->SupportDisplayControl = + (guac_settings->resize_method == GUAC_RESIZE_DISPLAY_UPDATE); + /* Timezone redirection */ if (guac_settings->timezone) { if (setenv("TZ", guac_settings->timezone, 1)) { From 6dc8b57ca4abe704b43ad6afa9385e3207df9202 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 14 Oct 2019 11:12:53 -0700 Subject: [PATCH 032/109] GUACAMOLE-249: Update RAIL (RemoteApp) support to FreeRDP 2.0.0 API. --- src/protocols/rdp/Makefile.am | 4 +- src/protocols/rdp/rail.c | 136 +++++++++++++++++++++++ src/protocols/rdp/{rdp_rail.h => rail.h} | 34 ++---- src/protocols/rdp/rdp.c | 29 +---- src/protocols/rdp/rdp_rail.c | 97 ---------------- 5 files changed, 151 insertions(+), 149 deletions(-) create mode 100644 src/protocols/rdp/rail.c rename src/protocols/rdp/{rdp_rail.h => rail.h} (54%) delete mode 100644 src/protocols/rdp/rdp_rail.c diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index a1d3600a..6cb60167 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -43,6 +43,7 @@ libguac_client_rdp_la_SOURCES = \ input.c \ keyboard.c \ ptr_string.c \ + rail.c \ rdp.c \ rdp_bitmap.c \ rdp_color.c \ @@ -52,7 +53,6 @@ libguac_client_rdp_la_SOURCES = \ rdp_keymap.c \ rdp_print_job.c \ rdp_pointer.c \ - rdp_rail.c \ rdp_settings.c \ rdp_stream.c \ resolution.c \ @@ -111,6 +111,7 @@ noinst_HEADERS = \ input.h \ keyboard.h \ ptr_string.h \ + rail.h \ rdp.h \ rdp_bitmap.h \ rdp_color.h \ @@ -120,7 +121,6 @@ noinst_HEADERS = \ rdp_keymap.h \ rdp_pointer.h \ rdp_print_job.h \ - rdp_rail.h \ rdp_settings.h \ rdp_status.h \ rdp_stream.h \ diff --git a/src/protocols/rdp/rail.c b/src/protocols/rdp/rail.c new file mode 100644 index 00000000..5f06155e --- /dev/null +++ b/src/protocols/rdp/rail.c @@ -0,0 +1,136 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#include "config.h" + +#include "channels.h" +#include "client.h" +#include "rail.h" +#include "rdp.h" +#include "rdp_settings.h" + +#include +#include +#include +#include + +#include + +/** + * Callback which is invoked when a Server System Parameters Update PDU is + * received from the RDP server. The Server System Parameters Update PDU, also + * referred to as a "sysparam order", is used by the server to update system + * parameters for RemoteApp. + * + * @param rail + * The RailClientContext structure used by FreeRDP to handle the RAIL + * channel for the current RDP session. + * + * @param sysparam + * The RAIL_SYSPARAM_ORDER structure representing the Server System + * Parameters Update PDU that was received. + * + * @return + * CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code + * (non-zero) otherwise. + */ +static UINT guac_rdp_rail_sysparam(RailClientContext* rail, + const RAIL_SYSPARAM_ORDER* sysparam) { + + guac_client* client = (guac_client*) rail->custom; + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + + RAIL_SYSPARAM_ORDER response = { + .workArea = { + .left = 0, + .top = 0, + .right = rdp_client->settings->width, + .bottom = rdp_client->settings->height + }, + .dragFullWindows = FALSE + }; + + return rail->ClientSystemParam(rail, &response); + +} + +/** + * Callback which associates handlers specific to Guacamole with the + * RailClientContext instance allocated by FreeRDP to deal with received + * RAIL (RemoteApp) messages. + * + * This function is called whenever a channel connects via the PubSub event + * system within FreeRDP, but only has any effect if the connected channel is + * the RAIL channel. This specific callback is registered with the PubSub + * system of the relevant rdpContext when guac_rdp_rail_load_plugin() is + * called. + * + * @param context + * The rdpContext associated with the active RDP session. + * + * @param e + * Event-specific arguments, mainly the name of the channel, and a + * reference to the associated plugin loaded for that channel by FreeRDP. + */ +static void guac_rdp_rail_channel_connected(rdpContext* context, + ChannelConnectedEventArgs* e) { + + guac_client* client = ((rdp_freerdp_context*) context)->client; + + /* Ignore connection event if it's not for the RAIL channel */ + if (strcmp(e->name, RAIL_SVC_CHANNEL_NAME) != 0) + return; + + /* The structure pointed to by pInterface is guaranteed to be a + * RailClientContext if the channel is RAIL */ + RailClientContext* rail = (RailClientContext*) e->pInterface; + + /* Init FreeRDP RAIL context, ensuring the guac_client can be accessed from + * within any RAIL-specific callbacks */ + rail->custom = client; + rail->ServerSystemParam = guac_rdp_rail_sysparam; + + guac_client_log(client, GUAC_LOG_DEBUG, "RAIL (RemoteApp) channel " + "connected."); + +} + +void guac_rdp_rail_load_plugin(rdpContext* context) { + + guac_client* client = ((rdp_freerdp_context*) context)->client; + + /* Attempt to load FreeRDP support for the RAIL channel */ + if (guac_freerdp_channels_load_plugin(context->channels, context->settings, "rail", context->settings)) { + guac_client_log(client, GUAC_LOG_WARNING, + "Support for the RAIL channel (RemoteApp) could not be " + "loaded. This support normally takes the form of a plugin " + "which is built into FreeRDP. Lacking this support, " + "RemoteApp will not work."); + return; + } + + /* Complete RDP side of initialization when channel is connected */ + PubSub_SubscribeChannelConnected(context->pubSub, + (pChannelConnectedEventHandler) guac_rdp_rail_channel_connected); + + guac_client_log(client, GUAC_LOG_DEBUG, "Support for RAIL (RemoteApp) " + "registered. Awaiting channel connection."); + +} + diff --git a/src/protocols/rdp/rdp_rail.h b/src/protocols/rdp/rail.h similarity index 54% rename from src/protocols/rdp/rdp_rail.h rename to src/protocols/rdp/rail.h index e19f25fc..718c62b3 100644 --- a/src/protocols/rdp/rdp_rail.h +++ b/src/protocols/rdp/rail.h @@ -17,37 +17,23 @@ * under the License. */ - -#ifndef __GUAC_RDP_RDP_RAIL_H -#define __GUAC_RDP_RDP_RAIL_H +#ifndef GUAC_RDP_RAIL_H +#define GUAC_RDP_RAIL_H #include "config.h" -#include -#include - /** - * Dispatches a given RAIL event to the appropriate handler. + * Initializes RemoteApp support for RDP and handling of the RAIL channel. If + * failures occur, messages noting the specifics of those failures will be + * logged, and RemoteApp support will not be functional. * - * @param client - * The guac_client associated with the current RDP session. + * This MUST be called within the PreConnect callback of the freerdp instance + * for RAIL support to be loaded. * - * @param event - * The RAIL event to process. + * @param rdpContext + * The rdpContext associated with the FreeRDP side of the RDP connection. */ -void guac_rdp_process_rail_event(guac_client* client, wMessage* event); - -/** - * Handles the event sent when updating system parameters. The event given - * MUST be a SYSPARAM event. - * - * @param client - * The guac_client associated with the current RDP session. - * - * @param event - * The system parameter event to process. - */ -void guac_rdp_process_rail_get_sysparam(guac_client* client, wMessage* event); +void guac_rdp_rail_load_plugin(rdpContext* context); #endif diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 0923a53c..b41527c4 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -29,6 +29,7 @@ #include "disp.h" #include "error.h" #include "keyboard.h" +#include "rail.h" #include "rdp.h" #include "rdp_bitmap.h" #include "rdp_fs.h" @@ -36,7 +37,6 @@ #include "rdp_gdi.h" #include "rdp_glyph.h" #include "rdp_pointer.h" -#include "rdp_rail.h" #include "rdp_stream.h" #if 0 #include "rdp_svc.h" @@ -128,15 +128,8 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { } /* Load RAIL plugin if RemoteApp in use */ - if (settings->remote_app != NULL) { - - /* Attempt to load rail */ - if (guac_freerdp_channels_load_plugin(channels, instance->settings, - "rail", instance->settings)) - guac_client_log(client, GUAC_LOG_WARNING, - "Failed to load rail plugin. RemoteApp will not work."); - - } + if (settings->remote_app != NULL) + guac_rdp_rail_load_plugin(context); #if 0 /* Load SVC plugin instances for all static channels */ @@ -476,22 +469,6 @@ static int guac_rdp_handle_connection(guac_client* client) { } - /* Check for channel events */ -#if 0 - wMessage* event = freerdp_channels_pop_event(channels); - if (event) { - - /* Handle channel events (clipboard and RAIL) */ - if (GetMessageClass(event->id) == CliprdrChannel_Class) - guac_rdp_process_cliprdr_event(client, event); - else if (GetMessageClass(event->id) == RailChannel_Class) - guac_rdp_process_rail_event(client, event); - - freerdp_event_free(event); - - } -#endif - pthread_mutex_unlock(&(rdp_client->rdp_lock)); /* Calculate time remaining in frame */ diff --git a/src/protocols/rdp/rdp_rail.c b/src/protocols/rdp/rdp_rail.c deleted file mode 100644 index b351ea6f..00000000 --- a/src/protocols/rdp/rdp_rail.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -#include "config.h" - -#include "client.h" -#include "rdp.h" -#include "rdp_rail.h" -#include "rdp_settings.h" - -#include -#include -#include -#include -#include - -#include - -void guac_rdp_process_rail_event(guac_client* client, wMessage* event) { - - switch (GetMessageType(event->id)) { - - /* Get system parameters */ - case RailChannel_GetSystemParam: - guac_rdp_process_rail_get_sysparam(client, event); - break; - - /* Currently ignored events */ - case RailChannel_ServerSystemParam: - case RailChannel_ServerExecuteResult: - case RailChannel_ServerMinMaxInfo: - case RailChannel_ServerLocalMoveSize: - case RailChannel_ServerGetAppIdResponse: - case RailChannel_ServerLanguageBarInfo: - break; - - default: - guac_client_log(client, GUAC_LOG_INFO, - "Unknown rail event type: 0x%x", - GetMessageType(event->id)); - - } - -} - -void guac_rdp_process_rail_get_sysparam(guac_client* client, wMessage* event) { -#if 0 - wMessage* response; - RAIL_SYSPARAM_ORDER* sysparam; - - /* Get channels */ - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - rdpChannels* channels = rdp_client->rdp_inst->context->channels; - - /* Get sysparam structure */ - sysparam = (RAIL_SYSPARAM_ORDER*) event->wParam; - - response = freerdp_event_new(RailChannel_Class, - RailChannel_ClientSystemParam, - NULL, - sysparam); - - /* Work area */ - sysparam->workArea.left = 0; - sysparam->workArea.top = 0; - sysparam->workArea.right = rdp_client->settings->width; - sysparam->workArea.bottom = rdp_client->settings->height; - - /* Taskbar */ - sysparam->taskbarPos.left = 0; - sysparam->taskbarPos.top = 0; - sysparam->taskbarPos.right = 0; - sysparam->taskbarPos.bottom = 0; - - sysparam->dragFullWindows = FALSE; - - /* Send response */ - freerdp_channels_send_event(channels, response); -#endif -} - From 77a32398e52182a6695cfcab175532812f6721ac Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 14 Oct 2019 11:39:00 -0700 Subject: [PATCH 033/109] GUACAMOLE-249: Migrate to plugin naming style used by FreeRDP 2.0.0. --- src/protocols/rdp/Makefile.am | 203 ++++++++++++++++------------------ 1 file changed, 93 insertions(+), 110 deletions(-) diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index 6cb60167..2bdd8225 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -29,6 +29,10 @@ ACLOCAL_AMFLAGS = -I m4 lib_LTLIBRARIES = libguac-client-rdp.la SUBDIRS = . tests +# +# Main RDP client library +# + nodist_libguac_client_rdp_la_SOURCES = \ _generated_keymaps.c @@ -59,34 +63,6 @@ libguac_client_rdp_la_SOURCES = \ unicode.c \ user.c -guacai_sources = \ - audio_input.c \ - guac_ai/ai_messages.c \ - guac_ai/ai_service.c \ - ptr_string.c - -guacsvc_sources = \ - guac_svc/svc_service.c \ - rdp_svc.c - -guacsnd_sources = \ - guac_rdpsnd/rdpsnd_messages.c \ - guac_rdpsnd/rdpsnd_service.c - -guacdr_sources = \ - guac_rdpdr/rdpdr_fs_messages.c \ - guac_rdpdr/rdpdr_fs_messages_dir_info.c \ - guac_rdpdr/rdpdr_fs_messages_file_info.c \ - guac_rdpdr/rdpdr_fs_messages_vol_info.c \ - guac_rdpdr/rdpdr_fs_service.c \ - guac_rdpdr/rdpdr_messages.c \ - guac_rdpdr/rdpdr_printer.c \ - guac_rdpdr/rdpdr_service.c \ - rdp_fs.c \ - rdp_print_job.c \ - rdp_stream.c \ - unicode.c - noinst_HEADERS = \ guac_ai/ai_messages.h \ guac_ai/ai_service.h \ @@ -128,10 +104,6 @@ noinst_HEADERS = \ unicode.h \ user.h -# -# Main RDP client library -# - libguac_client_rdp_la_CFLAGS = \ -Werror -Wall -Iinclude \ @COMMON_INCLUDE@ \ @@ -149,85 +121,125 @@ libguac_client_rdp_la_LIBADD = \ @COMMON_LTLIB@ \ @LIBGUAC_LTLIB@ +# +# Plugins for FreeRDP +# + +freerdp_LTLIBRARIES = \ + libguacai-client.la +# libguacdr-client.la \ +# libguacsnd-client.la \ +# libguacsvc-client.la + +freerdpdir = ${libdir}/freerdp2 + # # RDPDR # -guacdr_cflags = \ - -Werror -Wall -Iinclude \ - @COMMON_INCLUDE@ \ - @COMMON_SSH_INCLUDE@ \ - @LIBGUAC_INCLUDE@ \ - @RDP_CFLAGS@ - -guacdr_ldflags = \ - -module -avoid-version -shared \ - @PTHREAD_LIBS@ \ - @RDP_LIBS@ - -guacdr_libadd = \ - @COMMON_LTLIB@ \ - @LIBGUAC_LTLIB@ +#libguacdr_client_la_SOURCES = \ +# guac_rdpdr/rdpdr_fs_messages.c \ +# guac_rdpdr/rdpdr_fs_messages_dir_info.c \ +# guac_rdpdr/rdpdr_fs_messages_file_info.c \ +# guac_rdpdr/rdpdr_fs_messages_vol_info.c \ +# guac_rdpdr/rdpdr_fs_service.c \ +# guac_rdpdr/rdpdr_messages.c \ +# guac_rdpdr/rdpdr_printer.c \ +# guac_rdpdr/rdpdr_service.c \ +# rdp_fs.c \ +# rdp_print_job.c \ +# rdp_stream.c \ +# unicode.c +# +#libguacdr_client_la_CFLAGS = \ +# -Werror -Wall -Iinclude \ +# @COMMON_INCLUDE@ \ +# @COMMON_SSH_INCLUDE@ \ +# @LIBGUAC_INCLUDE@ \ +# @RDP_CFLAGS@ +# +#libguacdr_client_la_LDFLAGS = \ +# -module -avoid-version -shared \ +# @PTHREAD_LIBS@ \ +# @RDP_LIBS@ +# +#libguacdr_client_la_LIBADD = \ +# @COMMON_LTLIB@ \ +# @LIBGUAC_LTLIB@ # # Audio Input # -guacai_cflags = \ +libguacai_client_la_SOURCES = \ + audio_input.c \ + guac_ai/ai_messages.c \ + guac_ai/ai_service.c \ + ptr_string.c + +libguacai_client_la_CFLAGS = \ -Werror -Wall -Iinclude \ @COMMON_INCLUDE@ \ @COMMON_SSH_INCLUDE@ \ @LIBGUAC_INCLUDE@ \ @RDP_CFLAGS@ -guacai_ldflags = \ +libguacai_client_la_LDFLAGS = \ -module -avoid-version -shared \ @PTHREAD_LIBS@ \ @RDP_LIBS@ -guacai_libadd = \ - @COMMON_LTLIB@ \ +libguacai_client_la_LIBADD = \ + @COMMON_LTLIB@ \ @LIBGUAC_LTLIB@ # # RDPSND # -guacsnd_cflags = \ - -Werror -Wall -Iinclude \ - @COMMON_INCLUDE@ \ - @COMMON_SSH_INCLUDE@ \ - @LIBGUAC_INCLUDE@ \ - @RDP_CFLAGS@ - -guacsnd_ldflags = \ - -module -avoid-version -shared \ - @PTHREAD_LIBS@ \ - @RDP_LIBS@ - -guacsnd_libadd = \ - @COMMON_LTLIB@ \ - @LIBGUAC_LTLIB@ +#libguacsnd_client_la_SOURCES = \ +# guac_rdpsnd/rdpsnd_messages.c \ +# guac_rdpsnd/rdpsnd_service.c +# +#libguacsnd_client_la_CFLAGS = \ +# -Werror -Wall -Iinclude \ +# @COMMON_INCLUDE@ \ +# @COMMON_SSH_INCLUDE@ \ +# @LIBGUAC_INCLUDE@ \ +# @RDP_CFLAGS@ +# +#libguacsnd_client_la_LDFLAGS = \ +# -module -avoid-version -shared \ +# @PTHREAD_LIBS@ \ +# @RDP_LIBS@ +# +#libguacsnd_client_la_LIBADD = \ +# @COMMON_LTLIB@ \ +# @LIBGUAC_LTLIB@ # # Static Virtual Channels # -guacsvc_cflags = \ - -Werror -Wall -Iinclude \ - @COMMON_INCLUDE@ \ - @COMMON_SSH_INCLUDE@ \ - @LIBGUAC_INCLUDE@ \ - @RDP_CFLAGS@ - -guacsvc_ldflags = \ - -module -avoid-version -shared \ - @PTHREAD_LIBS@ \ - @RDP_LIBS@ - -guacsvc_libadd = \ - @COMMON_LTLIB@ \ - @LIBGUAC_LTLIB@ +#libguacsvc_client_la_SOURCES = \ +# guac_svc/svc_service.c \ +# rdp_svc.c +# +#libguacsvc_client_la_CFLAGS = \ +# -Werror -Wall -Iinclude \ +# @COMMON_INCLUDE@ \ +# @COMMON_SSH_INCLUDE@ \ +# @LIBGUAC_INCLUDE@ \ +# @RDP_CFLAGS@ +# +#libguacsvc_client_la_LDFLAGS = \ +# -module -avoid-version -shared \ +# @PTHREAD_LIBS@ \ +# @RDP_LIBS@ +# +#libguacsvc_client_la_LIBADD = \ +# @COMMON_LTLIB@ \ +# @LIBGUAC_LTLIB@ # # Optional SFTP support @@ -270,32 +282,3 @@ EXTRA_DIST = \ $(rdp_keymaps) \ keymaps/generate.pl -# FreeRDP 1.1 (and hopefully onward) extensions -freerdp_LTLIBRARIES = \ - guacai-client.la -# guacdr-client.la \ -# guacsnd-client.la \ -# guacsvc-client.la - -guacai_client_la_SOURCES = ${guacai_sources} -guacai_client_la_CFLAGS = ${guacai_cflags} -guacai_client_la_LDFLAGS = ${guacai_ldflags} -guacai_client_la_LIBADD = ${guacai_libadd} - -#guacdr_client_la_SOURCES = ${guacdr_sources} -#guacdr_client_la_CFLAGS = ${guacdr_cflags} -#guacdr_client_la_LDFLAGS = ${guacdr_ldflags} -#guacdr_client_la_LIBADD = ${guacdr_libadd} - -#guacsnd_client_la_SOURCES = ${guacsnd_sources} -#guacsnd_client_la_CFLAGS = ${guacsnd_cflags} -#guacsnd_client_la_LDFLAGS = ${guacsnd_ldflags} -#guacsnd_client_la_LIBADD = ${guacsnd_libadd} - -#guacsvc_client_la_SOURCES = ${guacsvc_sources} -#guacsvc_client_la_CFLAGS = ${guacsvc_cflags} -#guacsvc_client_la_LDFLAGS = ${guacsvc_ldflags} -#guacsvc_client_la_LIBADD = ${guacsvc_libadd} - -freerdpdir = ${libdir}/freerdp - From fa0ad267b8105a14aeef366d270e922b610c0f40 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 4 Nov 2019 19:26:04 -0800 Subject: [PATCH 034/109] GUACAMOLE-249: Update Docker build to use FreeRDP 2.0.0. --- Dockerfile | 7 +++---- src/guacd-docker/bin/link-freerdp-plugins.sh | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index f5f7a425..a109edd3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,9 +37,9 @@ ARG BUILD_DIR=/tmp/guacd-docker-BUILD ARG BUILD_DEPENDENCIES=" \ autoconf \ automake \ + freerdp2-dev \ gcc \ libcairo2-dev \ - libfreerdp-dev \ libjpeg62-turbo-dev \ libossp-uuid-dev \ libpango1.0-dev \ @@ -71,7 +71,7 @@ RUN ${PREFIX_DIR}/bin/build-guacd.sh "$BUILD_DIR" "$PREFIX_DIR" RUN ${PREFIX_DIR}/bin/list-dependencies.sh \ ${PREFIX_DIR}/sbin/guacd \ ${PREFIX_DIR}/lib/libguac-client-*.so \ - ${PREFIX_DIR}/lib/freerdp/guac*.so \ + ${PREFIX_DIR}/lib/freerdp2/guac*.so \ > ${PREFIX_DIR}/DEPENDENCIES # Use same Debian as the base for the runtime image @@ -92,7 +92,6 @@ ENV GUACD_LOG_LEVEL=info ARG RUNTIME_DEPENDENCIES=" \ ca-certificates \ ghostscript \ - libfreerdp-plugins-standard \ fonts-liberation \ fonts-dejavu \ xfonts-terminus" @@ -108,7 +107,7 @@ RUN apt-get update && \ # Link FreeRDP plugins into proper path RUN ${PREFIX_DIR}/bin/link-freerdp-plugins.sh \ - ${PREFIX_DIR}/lib/freerdp/guac*.so + ${PREFIX_DIR}/lib/freerdp2/libguac*.so # Expose the default listener port EXPOSE 4822 diff --git a/src/guacd-docker/bin/link-freerdp-plugins.sh b/src/guacd-docker/bin/link-freerdp-plugins.sh index 332d4c0f..625e85b3 100755 --- a/src/guacd-docker/bin/link-freerdp-plugins.sh +++ b/src/guacd-docker/bin/link-freerdp-plugins.sh @@ -70,7 +70,7 @@ while [ -n "$1" ]; do # Determine correct install location for FreeRDP plugins FREERDP_DIR="$(where_is_freerdp "$1")" - FREERDP_PLUGIN_DIR="${FREERDP_DIR}/freerdp" + FREERDP_PLUGIN_DIR="${FREERDP_DIR}/freerdp2" # Add symbolic link if necessary if [ ! -e "$FREERDP_PLUGIN_DIR/$(basename "$1")" ]; then From 233c0555c3949c79e548427f4e112f3bbdf15823 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 15 Dec 2019 18:58:04 -0800 Subject: [PATCH 035/109] GUACAMOLE-249: Migrate SVC support to FreeRDP 2.0.0 plugin API. --- src/protocols/rdp/Makefile.am | 51 ++-- src/protocols/rdp/guac_svc/svc_service.c | 316 +++++++++++++++++------ src/protocols/rdp/guac_svc/svc_service.h | 72 ------ src/protocols/rdp/rdp.c | 26 +- src/protocols/rdp/rdp_stream.c | 53 ---- src/protocols/rdp/rdp_stream.h | 27 +- src/protocols/rdp/rdp_svc.c | 171 ------------ src/protocols/rdp/rdp_svc.h | 168 ------------ src/protocols/rdp/svc.c | 227 ++++++++++++++++ src/protocols/rdp/svc.h | 215 +++++++++++++++ src/protocols/rdp/user.c | 8 +- 11 files changed, 713 insertions(+), 621 deletions(-) delete mode 100644 src/protocols/rdp/guac_svc/svc_service.h delete mode 100644 src/protocols/rdp/rdp_svc.c delete mode 100644 src/protocols/rdp/rdp_svc.h create mode 100644 src/protocols/rdp/svc.c create mode 100644 src/protocols/rdp/svc.h diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index 2bdd8225..2849a2ca 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -60,6 +60,7 @@ libguac_client_rdp_la_SOURCES = \ rdp_settings.c \ rdp_stream.c \ resolution.c \ + svc.c \ unicode.c \ user.c @@ -76,7 +77,6 @@ noinst_HEADERS = \ guac_rdpdr/rdpdr_service.h \ guac_rdpsnd/rdpsnd_messages.h \ guac_rdpsnd/rdpsnd_service.h \ - guac_svc/svc_service.h \ audio_input.h \ client.h \ clipboard.h \ @@ -101,6 +101,7 @@ noinst_HEADERS = \ rdp_status.h \ rdp_stream.h \ resolution.h \ + svc.h \ unicode.h \ user.h @@ -125,11 +126,11 @@ libguac_client_rdp_la_LIBADD = \ # Plugins for FreeRDP # -freerdp_LTLIBRARIES = \ - libguacai-client.la -# libguacdr-client.la \ -# libguacsnd-client.la \ -# libguacsvc-client.la +freerdp_LTLIBRARIES = \ + libguacai-client.la \ + libguacsvc-client.la +# libguacdr-client.la +# libguacsnd-client.la freerdpdir = ${libdir}/freerdp2 @@ -221,25 +222,25 @@ libguacai_client_la_LIBADD = \ # Static Virtual Channels # -#libguacsvc_client_la_SOURCES = \ -# guac_svc/svc_service.c \ -# rdp_svc.c -# -#libguacsvc_client_la_CFLAGS = \ -# -Werror -Wall -Iinclude \ -# @COMMON_INCLUDE@ \ -# @COMMON_SSH_INCLUDE@ \ -# @LIBGUAC_INCLUDE@ \ -# @RDP_CFLAGS@ -# -#libguacsvc_client_la_LDFLAGS = \ -# -module -avoid-version -shared \ -# @PTHREAD_LIBS@ \ -# @RDP_LIBS@ -# -#libguacsvc_client_la_LIBADD = \ -# @COMMON_LTLIB@ \ -# @LIBGUAC_LTLIB@ +libguacsvc_client_la_SOURCES = \ + guac_svc/svc_service.c \ + svc.c + +libguacsvc_client_la_CFLAGS = \ + -Werror -Wall -Iinclude \ + @COMMON_INCLUDE@ \ + @COMMON_SSH_INCLUDE@ \ + @LIBGUAC_INCLUDE@ \ + @RDP_CFLAGS@ + +libguacsvc_client_la_LDFLAGS = \ + -module -avoid-version -shared \ + @PTHREAD_LIBS@ \ + @RDP_LIBS@ + +libguacsvc_client_la_LIBADD = \ + @COMMON_LTLIB@ \ + @LIBGUAC_LTLIB@ # # Optional SFTP support diff --git a/src/protocols/rdp/guac_svc/svc_service.c b/src/protocols/rdp/guac_svc/svc_service.c index 70e86f12..07f17fb9 100644 --- a/src/protocols/rdp/guac_svc/svc_service.c +++ b/src/protocols/rdp/guac_svc/svc_service.c @@ -19,13 +19,12 @@ #include "config.h" -#include "svc_service.h" +#include "svc.h" #include #include #include -#include #include #include #include @@ -33,60 +32,142 @@ #include /** - * Entry point for arbitrary SVC. + * Processes data received along an SVC via a CHANNEL_EVENT_DATA_RECEIVED + * event, forwarding the data along an established, outbound pipe stream to the + * Guacamole client. + * + * @param svc + * The guac_rdp_svc structure representing the SVC that received the data. + * + * @param data + * The data that was received. + * + * @param length + * The number of bytes received. */ -int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) { +static void guac_rdp_svc_process_receive(guac_rdp_svc* svc, + void* data, int length) { - /* Gain access to plugin data */ - CHANNEL_ENTRY_POINTS_FREERDP* entry_points_ex = - (CHANNEL_ENTRY_POINTS_FREERDP*) pEntryPoints; + /* Fail if output not created */ + if (svc->output_pipe == NULL) { + guac_client_log(svc->client, GUAC_LOG_WARNING, "%i bytes of data " + "received from within the remote desktop session for SVC " + "\"%s\" are being dropped because the outbound pipe stream " + "for that SVC is not yet open. This should NOT happen.", + length, svc->channel_def.name); + return; + } - /* Allocate plugin */ - guac_svcPlugin* svc_plugin = - (guac_svcPlugin*) calloc(1, sizeof(guac_svcPlugin)); - - /* Get SVC descriptor from plugin parameters */ - guac_rdp_svc* svc = (guac_rdp_svc*) entry_points_ex->pExtendedData; - - /* Init channel def */ - guac_strlcpy(svc_plugin->plugin.channel_def.name, svc->name, - GUAC_RDP_SVC_MAX_LENGTH); - svc_plugin->plugin.channel_def.options = - CHANNEL_OPTION_INITIALIZED - | CHANNEL_OPTION_ENCRYPT_RDP - | CHANNEL_OPTION_COMPRESS_RDP; - - /* Init plugin */ - svc_plugin->svc = svc; - - /* Set callbacks */ - svc_plugin->plugin.connect_callback = guac_svc_process_connect; - svc_plugin->plugin.receive_callback = guac_svc_process_receive; - svc_plugin->plugin.event_callback = guac_svc_process_event; - svc_plugin->plugin.terminate_callback = guac_svc_process_terminate; - - /* Store plugin reference in SVC */ - svc->plugin = (rdpSvcPlugin*) svc_plugin; - - /* Finish init */ - svc_plugin_init((rdpSvcPlugin*) svc_plugin, pEntryPoints); - return 1; + /* Send blob */ + guac_protocol_send_blob(svc->client->socket, svc->output_pipe, data, length); + guac_socket_flush(svc->client->socket); } -/* - * Service Handlers +/** + * Event handler for events which deal with data transmitted over an open SVC. + * This specific implementation of the event handler currently handles only the + * CHANNEL_EVENT_DATA_RECEIVED event, delegating actual handling of that event + * to guac_rdp_svc_process_receive(). + * + * The FreeRDP requirements for this function follow those of the + * VirtualChannelOpenEventEx callback defined within Microsoft's RDP API: + * + * https://docs.microsoft.com/en-us/previous-versions/windows/embedded/aa514754%28v%3dmsdn.10%29 + * + * @param user_param + * The pointer to arbitrary data originally passed via the first parameter + * of the pVirtualChannelInitEx() function call when the associated channel + * was initialized. The pVirtualChannelInitEx() function is exposed within + * the channel entry points structure. + * + * @param open_handle + * The handle which identifies the channel itself, typically referred to + * within the FreeRDP source as OpenHandle. + * + * @param event + * An integer representing the event that should be handled. This will be + * either CHANNEL_EVENT_DATA_RECEIVED, CHANNEL_EVENT_WRITE_CANCELLED, or + * CHANNEL_EVENT_WRITE_COMPLETE. + * + * @param data + * The data received, for CHANNEL_EVENT_DATA_RECEIVED events, and the value + * passed as user data to pVirtualChannelWriteEx() for + * CHANNEL_EVENT_WRITE_* events (note that user data for + * pVirtualChannelWriteEx() as implemented by FreeRDP MUST either be NULL + * or a wStream containing the data written). + * + * @param data_length + * The number of bytes of event-specific data. + * + * @param total_length + * The total number of bytes written to the RDP server in a single write + * operation. + * + * NOTE: The meaning of total_length is unclear. The above description was + * written mainly through referencing the documentation in MSDN. Real-world + * use will need to be consulted, likely within the FreeRDP source, before + * this value can be reliably used. The current implementation of this + * handler ignores this parameter. + * + * @param data_flags + * The result of a bitwise OR of the CHANNEL_FLAG_* flags which apply to + * the data received. This value is relevant only to + * CHANNEL_EVENT_DATA_RECEIVED events. Valid flags are CHANNEL_FLAG_FIRST, + * CHANNEL_FLAG_LAST, and CHANNEL_FLAG_ONLY. The flag CHANNEL_FLAG_MIDDLE + * is not itself a flag, but the absence of both CHANNEL_FLAG_FIRST and + * CHANNEL_FLAG_LAST. */ +static VOID guac_rdp_svc_handle_open_event(LPVOID user_param, + DWORD open_handle, UINT event, LPVOID data, UINT32 data_length, + UINT32 total_length, UINT32 data_flags) { -void guac_svc_process_connect(rdpSvcPlugin* plugin) { + /* Ignore all events except for received data */ + if (event != CHANNEL_EVENT_DATA_RECEIVED) + return; - /* Get corresponding guac_rdp_svc */ - guac_svcPlugin* svc_plugin = (guac_svcPlugin*) plugin; - guac_rdp_svc* svc = svc_plugin->svc; + guac_rdp_svc* svc = (guac_rdp_svc*) user_param; - /* NULL out pExtendedData so we don't lose our guac_rdp_svc due to an - * automatic free() within libfreerdp */ - plugin->channel_entry_points.pExtendedData = NULL; + /* Validate relevant handle matches that of SVC */ + if (open_handle != svc->open_handle) { + guac_client_log(svc->client, GUAC_LOG_WARNING, "%i bytes of data " + "received from within the remote desktop session for SVC " + "\"%s\" are being dropped because the relevant open handle " + "(0x%X) does not match the open handle of the SVC (0x%X).", + data_length, svc->channel_def.name, open_handle, + svc->open_handle); + return; + } + + guac_rdp_svc_process_receive(svc, data, data_length); + +} + +/** + * Processes a CHANNEL_EVENT_CONNECTED event, completing the + * connection/initialization process of the SVC. + * + * @param svc + * The guac_rdp_svc structure representing the SVC that is now connected. + */ +static void guac_rdp_svc_process_connect(guac_rdp_svc* svc) { + + /* Open FreeRDP side of connected channel */ + UINT32 open_status = + svc->entry_points.pVirtualChannelOpenEx(svc->init_handle, + &svc->open_handle, svc->channel_def.name, + guac_rdp_svc_handle_open_event); + + /* Warn if the channel cannot be opened after all */ + if (open_status != CHANNEL_RC_OK) { + guac_client_log(svc->client, GUAC_LOG_WARNING, "SVC \"%s\" could not " + "be opened: %s (error %i)", svc->channel_def.name, + WTSErrorToString(open_status), open_status); + return; + } + + /* SVC may now receive data from client */ + guac_rdp_svc_add(svc->client, svc); /* Create pipe */ svc->output_pipe = guac_client_alloc_stream(svc->client); @@ -96,50 +177,135 @@ void guac_svc_process_connect(rdpSvcPlugin* plugin) { /* Log connection to static channel */ guac_client_log(svc->client, GUAC_LOG_INFO, - "Static channel \"%s\" connected.", svc->name); + "Static channel \"%s\" connected.", svc->channel_def.name); } -void guac_svc_process_terminate(rdpSvcPlugin* plugin) { - - /* Get corresponding guac_rdp_svc */ - guac_svcPlugin* svc_plugin = (guac_svcPlugin*) plugin; - guac_rdp_svc* svc = svc_plugin->svc; +/** + * Processes a CHANNEL_EVENT_TERMINATED event, freeing all resources associated + * with the SVC. + * + * @param svc + * The guac_rdp_svc structure representing the SVC that has been + * terminated. + */ +static void guac_rdp_svc_process_terminate(guac_rdp_svc* svc) { /* Remove and free SVC */ - guac_client_log(svc->client, GUAC_LOG_INFO, "Closing channel \"%s\"...", svc->name); - guac_rdp_remove_svc(svc->client, svc->name); + guac_client_log(svc->client, GUAC_LOG_INFO, "Closing channel \"%s\"...", svc->channel_def.name); + guac_rdp_svc_remove(svc->client, svc->channel_def.name); free(svc); - free(plugin); - } -void guac_svc_process_event(rdpSvcPlugin* plugin, wMessage* event) { - freerdp_event_free(event); -} +/** + * Event handler for events which deal with the overall lifecycle of an SVC. + * This specific implementation of the event handler currently handles only + * CHANNEL_EVENT_CONNECTED and CHANNEL_EVENT_TERMINATED events, delegating + * actual handling of those events to guac_rdp_svc_process_connect() and + * guac_rdp_svc_process_terminate() respectively. + * + * The FreeRDP requirements for this function follow those of the + * VirtualChannelInitEventEx callback defined within Microsoft's RDP API: + * + * https://docs.microsoft.com/en-us/previous-versions/windows/embedded/aa514727%28v%3dmsdn.10%29 + * + * @param user_param + * The pointer to arbitrary data originally passed via the first parameter + * of the pVirtualChannelInitEx() function call when the associated channel + * was initialized. The pVirtualChannelInitEx() function is exposed within + * the channel entry points structure. + * + * @param init_handle + * The handle which identifies the client connection, typically referred to + * within the FreeRDP source as pInitHandle. + * + * @param event + * An integer representing the event that should be handled. This will be + * either CHANNEL_EVENT_CONNECTED, CHANNEL_EVENT_DISCONNECTED, + * CHANNEL_EVENT_INITIALIZED, CHANNEL_EVENT_TERMINATED, or + * CHANNEL_EVENT_V1_CONNECTED. + * + * @param data + * NULL in all cases except the CHANNEL_EVENT_CONNECTED event, in which + * case this is a null-terminated string containing the name of the server. + * + * @param data_length + * The number of bytes of data, if any. + */ +static VOID guac_rdp_svc_handle_init_event(LPVOID user_param, + LPVOID init_handle, UINT event, LPVOID data, UINT data_length) { -void guac_svc_process_receive(rdpSvcPlugin* plugin, - wStream* input_stream) { + guac_rdp_svc* svc = (guac_rdp_svc*) user_param; - /* Get corresponding guac_rdp_svc */ - guac_svcPlugin* svc_plugin = (guac_svcPlugin*) plugin; - guac_rdp_svc* svc = svc_plugin->svc; - - /* Fail if output not created */ - if (svc->output_pipe == NULL) { - guac_client_log(svc->client, GUAC_LOG_ERROR, - "Output for channel \"%s\" dropped.", - svc->name); + /* Validate relevant handle matches that of SVC */ + if (init_handle != svc->init_handle) { + guac_client_log(svc->client, GUAC_LOG_WARNING, "An init event (#%i) " + "for SVC \"%s\" has been dropped because the relevant init " + "handle (0x%X) does not match the init handle of the SVC " + "(0x%X).", event, svc->channel_def.name, init_handle, + svc->init_handle); return; } - /* Send blob */ - guac_protocol_send_blob(svc->client->socket, svc->output_pipe, - Stream_Buffer(input_stream), - Stream_Length(input_stream)); + switch (event) { - guac_socket_flush(svc->client->socket); + /* The remote desktop side of the SVC has been connected */ + case CHANNEL_EVENT_CONNECTED: + guac_rdp_svc_process_connect(svc); + break; + + /* The channel has disconnected and now must be cleaned up */ + case CHANNEL_EVENT_TERMINATED: + guac_rdp_svc_process_terminate(svc); + break; + + } + +} + +/** + * Entry point for FreeRDP plugins. This function is automatically invoked when + * the plugin is loaded. + * + * @param entry_points + * Functions and data specific to the FreeRDP side of the virtual channel + * and plugin. This structure must be copied within implementation-specific + * storage such that the functions it references can be invoked when + * needed. + * + * @param init_handle + * The handle which identifies the client connection, typically referred to + * within the FreeRDP source as pInitHandle. This handle is also provided + * to the channel init event handler. The handle must eventually be used + * within the channel open event handler to obtain a handle to the channel + * itself. + * + * @return + * TRUE if the plugin has initialized successfully, FALSE otherwise. + */ +BOOL VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS entry_points, + PVOID init_handle) { + + CHANNEL_ENTRY_POINTS_FREERDP_EX* entry_points_ex = + (CHANNEL_ENTRY_POINTS_FREERDP_EX*) entry_points; + + /* Get structure representing the Guacamole side of the SVC from plugin + * parameters */ + guac_rdp_svc* svc = (guac_rdp_svc*) entry_points_ex->pExtendedData; + + /* Copy FreeRDP data into SVC structure for future reference */ + svc->entry_points = *entry_points_ex; + svc->init_handle = init_handle; + + /* Complete initialization */ + if (svc->entry_points.pVirtualChannelInitEx(svc, svc, init_handle, + &svc->channel_def, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, + guac_rdp_svc_handle_init_event) != CHANNEL_RC_OK) { + return FALSE; + } + + return TRUE; } diff --git a/src/protocols/rdp/guac_svc/svc_service.h b/src/protocols/rdp/guac_svc/svc_service.h deleted file mode 100644 index 8aec6ca9..00000000 --- a/src/protocols/rdp/guac_svc/svc_service.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -#ifndef __GUAC_SVC_SERVICE_H -#define __GUAC_SVC_SERVICE_H - -#include "config.h" -#include "rdp_svc.h" - -#include -#include - -/** - * Structure representing the current state of an arbitrary static virtual - * channel. - */ -typedef struct guac_svcPlugin { - - /** - * The FreeRDP parts of this plugin. This absolutely MUST be first. - * FreeRDP depends on accessing this structure as if it were an instance - * of rdpSvcPlugin. - */ - rdpSvcPlugin plugin; - - /** - * The Guacamole-specific SVC structure describing the channel this - * instance represents. - */ - guac_rdp_svc* svc; - -} guac_svcPlugin; - -/** - * Handler called when this plugin is loaded by FreeRDP. - */ -void guac_svc_process_connect(rdpSvcPlugin* plugin); - -/** - * Handler called when this plugin receives data along its designated channel. - */ -void guac_svc_process_receive(rdpSvcPlugin* plugin, - wStream* input_stream); - -/** - * Handler called when this plugin is being unloaded. - */ -void guac_svc_process_terminate(rdpSvcPlugin* plugin); - -/** - * Handler called when this plugin receives an event. - */ -void guac_svc_process_event(rdpSvcPlugin* plugin, wMessage* event); - -#endif - diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index b41527c4..e2ba5938 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -38,9 +38,7 @@ #include "rdp_glyph.h" #include "rdp_pointer.h" #include "rdp_stream.h" -#if 0 -#include "rdp_svc.h" -#endif +#include "svc.h" #ifdef ENABLE_COMMON_SSH #include "common-ssh/sftp.h" @@ -131,35 +129,15 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { if (settings->remote_app != NULL) guac_rdp_rail_load_plugin(context); -#if 0 /* Load SVC plugin instances for all static channels */ if (settings->svc_names != NULL) { char** current = settings->svc_names; do { - - guac_rdp_svc* svc = guac_rdp_alloc_svc(client, *current); - - /* Attempt to load guacsvc plugin for new static channel */ - if (guac_freerdp_channels_load_plugin(channels, instance->settings, - "guacsvc", svc)) { - guac_client_log(client, GUAC_LOG_WARNING, - "Cannot create static channel \"%s\": failed to load guacsvc plugin.", - svc->name); - guac_rdp_free_svc(svc); - } - - /* Store and log on success */ - else { - guac_rdp_add_svc(client, svc); - guac_client_log(client, GUAC_LOG_INFO, "Created static channel \"%s\"...", - svc->name); - } - + guac_rdp_svc_load_plugin(context, *current); } while (*(++current) != NULL); } -#endif /* Load plugin providing Dynamic Virtual Channel support, if required */ if (instance->settings->SupportDynamicChannels && diff --git a/src/protocols/rdp/rdp_stream.c b/src/protocols/rdp/rdp_stream.c index 3d33ea20..a497c928 100644 --- a/src/protocols/rdp/rdp_stream.c +++ b/src/protocols/rdp/rdp_stream.c @@ -22,9 +22,6 @@ #include "client.h" #include "rdp.h" #include "rdp_fs.h" -#if 0 -#include "rdp_svc.h" -#endif #include "rdp_stream.h" #include @@ -119,39 +116,6 @@ int guac_rdp_upload_file_handler(guac_user* user, guac_stream* stream, } -int guac_rdp_svc_pipe_handler(guac_user* user, guac_stream* stream, - char* mimetype, char* name) { - -#if 0 - guac_rdp_stream* rdp_stream; - guac_rdp_svc* svc = guac_rdp_get_svc(user->client, name); - - /* Fail if no such SVC */ - if (svc == NULL) { - guac_user_log(user, GUAC_LOG_ERROR, - "Requested non-existent pipe: \"%s\".", - name); - guac_protocol_send_ack(user->socket, stream, "FAIL (NO SUCH PIPE)", - GUAC_PROTOCOL_STATUS_CLIENT_BAD_REQUEST); - guac_socket_flush(user->socket); - return 0; - } - else - guac_user_log(user, GUAC_LOG_ERROR, - "Inbound half of channel \"%s\" connected.", - name); - - /* Init stream data */ - stream->data = rdp_stream = malloc(sizeof(guac_rdp_stream)); - stream->blob_handler = guac_rdp_svc_blob_handler; - rdp_stream->type = GUAC_RDP_INBOUND_SVC_STREAM; - rdp_stream->svc = svc; -#endif - - return 0; - -} - int guac_rdp_upload_blob_handler(guac_user* user, guac_stream* stream, void* data, int length) { @@ -201,23 +165,6 @@ int guac_rdp_upload_blob_handler(guac_user* user, guac_stream* stream, } -int guac_rdp_svc_blob_handler(guac_user* user, guac_stream* stream, - void* data, int length) { - -#if 0 - guac_rdp_stream* rdp_stream = (guac_rdp_stream*) stream->data; - - /* Write blob data to SVC directly */ - guac_rdp_svc_write(rdp_stream->svc, data, length); -#endif - - guac_protocol_send_ack(user->socket, stream, "OK (DATA RECEIVED)", - GUAC_PROTOCOL_STATUS_SUCCESS); - guac_socket_flush(user->socket); - return 0; - -} - int guac_rdp_upload_end_handler(guac_user* user, guac_stream* stream) { guac_client* client = user->client; diff --git a/src/protocols/rdp/rdp_stream.h b/src/protocols/rdp/rdp_stream.h index 6aaa1b97..3ae8b0ff 100644 --- a/src/protocols/rdp/rdp_stream.h +++ b/src/protocols/rdp/rdp_stream.h @@ -23,9 +23,6 @@ #include "config.h" #include "common/json.h" -#if 0 -#include "rdp_svc.h" -#endif #include #include @@ -113,12 +110,7 @@ typedef enum guac_rdp_stream_type { /** * An in-progress stream of a directory listing. */ - GUAC_RDP_LS_STREAM, - - /** - * The inbound half of a static virtual channel. - */ - GUAC_RDP_INBOUND_SVC_STREAM + GUAC_RDP_LS_STREAM } guac_rdp_stream_type; @@ -147,13 +139,6 @@ typedef struct guac_rdp_stream { */ guac_rdp_ls_status ls_status; -#if 0 - /** - * Associated SVC instance. Only valid for GUAC_RDP_INBOUND_SVC_STREAM. - */ - guac_rdp_svc* svc; -#endif - } guac_rdp_stream; /** @@ -161,21 +146,11 @@ typedef struct guac_rdp_stream { */ guac_user_file_handler guac_rdp_upload_file_handler; -/** - * Handler for inbound pipes related to static virtual channels. - */ -guac_user_pipe_handler guac_rdp_svc_pipe_handler; - /** * Handler for stream data related to file uploads. */ guac_user_blob_handler guac_rdp_upload_blob_handler; -/** - * Handler for stream data related to static virtual channels. - */ -guac_user_blob_handler guac_rdp_svc_blob_handler; - /** * Handler for end-of-stream related to file uploads. */ diff --git a/src/protocols/rdp/rdp_svc.c b/src/protocols/rdp/rdp_svc.c deleted file mode 100644 index 97434991..00000000 --- a/src/protocols/rdp/rdp_svc.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -#include "config.h" -#include "client.h" -#include "common/list.h" -#include "rdp.h" -#include "rdp_svc.h" - -#include -#include -#include -#include - -#include - -guac_rdp_svc* guac_rdp_alloc_svc(guac_client* client, char* name) { - - guac_rdp_svc* svc = malloc(sizeof(guac_rdp_svc)); - - /* Init SVC */ - svc->client = client; - svc->plugin = NULL; - svc->output_pipe = NULL; - - /* Init name */ - int name_length = guac_strlcpy(svc->name, name, GUAC_RDP_SVC_MAX_LENGTH); - - /* Warn about name length */ - if (name_length >= GUAC_RDP_SVC_MAX_LENGTH) - guac_client_log(client, GUAC_LOG_INFO, - "Static channel name \"%s\" exceeds maximum of %i characters " - "and will be truncated", name, GUAC_RDP_SVC_MAX_LENGTH - 1); - - return svc; -} - -void guac_rdp_free_svc(guac_rdp_svc* svc) { - free(svc); -} - -void guac_rdp_svc_send_pipe(guac_socket* socket, guac_rdp_svc* svc) { - - /* Send pipe instruction for the SVC's output stream */ - guac_protocol_send_pipe(socket, svc->output_pipe, - "application/octet-stream", svc->name); - -} - -void guac_rdp_svc_send_pipes(guac_user* user) { - - guac_client* client = user->client; - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - - guac_common_list_lock(rdp_client->available_svc); - - /* Send pipe for each allocated SVC's output stream */ - guac_common_list_element* current = rdp_client->available_svc->head; - while (current != NULL) { - guac_rdp_svc_send_pipe(user->socket, (guac_rdp_svc*) current->data); - current = current->next; - } - - guac_common_list_unlock(rdp_client->available_svc); - -} - -void guac_rdp_add_svc(guac_client* client, guac_rdp_svc* svc) { - - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - - /* Add to list of available SVC */ - guac_common_list_lock(rdp_client->available_svc); - guac_common_list_add(rdp_client->available_svc, svc); - guac_common_list_unlock(rdp_client->available_svc); - -} - -guac_rdp_svc* guac_rdp_get_svc(guac_client* client, const char* name) { - - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - guac_common_list_element* current; - guac_rdp_svc* found = NULL; - - /* For each available SVC */ - guac_common_list_lock(rdp_client->available_svc); - current = rdp_client->available_svc->head; - while (current != NULL) { - - /* If name matches, found */ - guac_rdp_svc* current_svc = (guac_rdp_svc*) current->data; - if (strcmp(current_svc->name, name) == 0) { - found = current_svc; - break; - } - - current = current->next; - - } - guac_common_list_unlock(rdp_client->available_svc); - - return found; - -} - -guac_rdp_svc* guac_rdp_remove_svc(guac_client* client, const char* name) { - - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - guac_common_list_element* current; - guac_rdp_svc* found = NULL; - - /* For each available SVC */ - guac_common_list_lock(rdp_client->available_svc); - current = rdp_client->available_svc->head; - while (current != NULL) { - - /* If name matches, remove entry */ - guac_rdp_svc* current_svc = (guac_rdp_svc*) current->data; - if (strcmp(current_svc->name, name) == 0) { - guac_common_list_remove(rdp_client->available_svc, current); - found = current_svc; - break; - } - - current = current->next; - - } - guac_common_list_unlock(rdp_client->available_svc); - - /* Return removed entry, if any */ - return found; - -} - -void guac_rdp_svc_write(guac_rdp_svc* svc, void* data, int length) { - - wStream* output_stream; - - /* Do not write of plugin not associated */ - if (svc->plugin == NULL) { - guac_client_log(svc->client, GUAC_LOG_ERROR, - "Channel \"%s\" output dropped.", - svc->name); - return; - } - - /* Build packet */ - output_stream = Stream_New(NULL, length); - Stream_Write(output_stream, data, length); - - /* Send packet */ - svc_plugin_send(svc->plugin, output_stream); - -} - diff --git a/src/protocols/rdp/rdp_svc.h b/src/protocols/rdp/rdp_svc.h deleted file mode 100644 index ebb3a13f..00000000 --- a/src/protocols/rdp/rdp_svc.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -#ifndef __GUAC_RDP_RDP_SVC_H -#define __GUAC_RDP_RDP_SVC_H - -#include "config.h" - -#include -#include -#include - -/** - * The maximum number of bytes to allow within each channel name, including - * null terminator. - */ -#define GUAC_RDP_SVC_MAX_LENGTH 8 - -/** - * Structure describing a static virtual channel, and the corresponding - * Guacamole pipes. - */ -typedef struct guac_rdp_svc { - - /** - * Reference to the client owning this static channel. - */ - guac_client* client; - - /** - * Reference to associated SVC plugin. - */ - rdpSvcPlugin* plugin; - - /** - * The name of the RDP channel in use, and the name to use for each pipe. - */ - char name[GUAC_RDP_SVC_MAX_LENGTH]; - - /** - * The output pipe, opened when the RDP server receives a connection to - * the static channel. - */ - guac_stream* output_pipe; - -} guac_rdp_svc; - -/** - * Allocate a new SVC with the given name. - * - * @param client - * The guac_client associated with the current RDP session. - * - * @param name - * The name of the virtual channel to allocate. - * - * @return - * A newly-allocated static virtual channel. - */ -guac_rdp_svc* guac_rdp_alloc_svc(guac_client* client, char* name); - -/** - * Free the given SVC. - * - * @param svc - * The static virtual channel to free. - */ -void guac_rdp_free_svc(guac_rdp_svc* svc); - -/** - * Sends the "pipe" instruction describing the given static virtual channel - * along the given socket. This pipe instruction will relate the SVC's - * underlying output stream with the SVC's name and the mimetype - * "application/octet-stream". - * - * @param socket - * The socket along which the "pipe" instruction should be sent. - * - * @param svc - * The static virtual channel that the "pipe" instruction should describe. - */ -void guac_rdp_svc_send_pipe(guac_socket* socket, guac_rdp_svc* svc); - -/** - * Sends the "pipe" instructions describing all static virtual channels - * available to the given user along that user's socket. Each pipe instruction - * will relate the associated SVC's underlying output stream with the SVC's - * name and the mimetype "application/octet-stream". - * - * @param user - * The user to send the "pipe" instructions to. - */ -void guac_rdp_svc_send_pipes(guac_user* user); - -/** - * Add the given SVC to the list of all available SVCs. - * - * @param client - * The guac_client associated with the current RDP session. - * - * @param svc - * The static virtual channel to add to the list of all such channels - * available. - */ -void guac_rdp_add_svc(guac_client* client, guac_rdp_svc* svc); - -/** - * Retrieve the SVC with the given name from the list stored in the client. - * - * @param client - * The guac_client associated with the current RDP session. - * - * @param name - * The name of the static virtual channel to retrieve. - * - * @return - * The static virtual channel with the given name, or NULL if no such - * virtual channel exists. - */ -guac_rdp_svc* guac_rdp_get_svc(guac_client* client, const char* name); - -/** - * Remove the SVC with the given name from the list stored in the client. - * - * @param client - * The guac_client associated with the current RDP session. - * - * @param name - * The name of the static virtual channel to remove. - * - * @return - * The static virtual channel that was removed, or NULL if no such virtual - * channel exists. - */ -guac_rdp_svc* guac_rdp_remove_svc(guac_client* client, const char* name); - -/** - * Write the given blob of data to the virtual channel. - * - * @param svc - * The static virtual channel to write data to. - * - * @param data - * The data to write. - * - * @param length - * The number of bytes to write. - */ -void guac_rdp_svc_write(guac_rdp_svc* svc, void* data, int length); - -#endif - diff --git a/src/protocols/rdp/svc.c b/src/protocols/rdp/svc.c new file mode 100644 index 00000000..be420727 --- /dev/null +++ b/src/protocols/rdp/svc.c @@ -0,0 +1,227 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#include "config.h" + +#include "channels.h" +#include "client.h" +#include "common/list.h" +#include "rdp.h" +#include "svc.h" + +#include +#include +#include +#include +#include + +#include + +void guac_rdp_svc_send_pipe(guac_socket* socket, guac_rdp_svc* svc) { + + /* Send pipe instruction for the SVC's output stream */ + guac_protocol_send_pipe(socket, svc->output_pipe, + "application/octet-stream", svc->channel_def.name); + +} + +void guac_rdp_svc_send_pipes(guac_user* user) { + + guac_client* client = user->client; + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + + guac_common_list_lock(rdp_client->available_svc); + + /* Send pipe for each allocated SVC's output stream */ + guac_common_list_element* current = rdp_client->available_svc->head; + while (current != NULL) { + guac_rdp_svc_send_pipe(user->socket, (guac_rdp_svc*) current->data); + current = current->next; + } + + guac_common_list_unlock(rdp_client->available_svc); + +} + +void guac_rdp_svc_add(guac_client* client, guac_rdp_svc* svc) { + + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + + /* Add to list of available SVC */ + guac_common_list_lock(rdp_client->available_svc); + guac_common_list_add(rdp_client->available_svc, svc); + guac_common_list_unlock(rdp_client->available_svc); + +} + +guac_rdp_svc* guac_rdp_svc_get(guac_client* client, const char* name) { + + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + guac_common_list_element* current; + guac_rdp_svc* found = NULL; + + /* For each available SVC */ + guac_common_list_lock(rdp_client->available_svc); + current = rdp_client->available_svc->head; + while (current != NULL) { + + /* If name matches, found */ + guac_rdp_svc* current_svc = (guac_rdp_svc*) current->data; + if (strcmp(current_svc->channel_def.name, name) == 0) { + found = current_svc; + break; + } + + current = current->next; + + } + guac_common_list_unlock(rdp_client->available_svc); + + return found; + +} + +guac_rdp_svc* guac_rdp_svc_remove(guac_client* client, const char* name) { + + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + guac_common_list_element* current; + guac_rdp_svc* found = NULL; + + /* For each available SVC */ + guac_common_list_lock(rdp_client->available_svc); + current = rdp_client->available_svc->head; + while (current != NULL) { + + /* If name matches, remove entry */ + guac_rdp_svc* current_svc = (guac_rdp_svc*) current->data; + if (strcmp(current_svc->channel_def.name, name) == 0) { + guac_common_list_remove(rdp_client->available_svc, current); + found = current_svc; + break; + } + + current = current->next; + + } + guac_common_list_unlock(rdp_client->available_svc); + + /* Return removed entry, if any */ + return found; + +} + +void guac_rdp_svc_write(guac_rdp_svc* svc, void* data, int length) { + + /* Do not write of plugin not associated */ + if (!svc->open_handle) { + guac_client_log(svc->client, GUAC_LOG_WARNING, "%i bytes of data " + "received from the Guacamole client for SVC \"%s\" are being " + "dropped because the remote desktop side of that SVC is " + "connected.", length, svc->channel_def.name); + return; + } + + /* FreeRDP_VirtualChannelWriteEx() assumes that sent data is dynamically + * allocated and will free() the data after it is sent */ + void* data_copy = malloc(length); + memcpy(data_copy, data, length); + + /* Send received data */ + svc->entry_points.pVirtualChannelWriteEx(svc->init_handle, + svc->open_handle, data_copy, length, + NULL /* NOTE: If non-NULL, this MUST be a pointer to a wStream + containing the supplied buffer, and that wStream will be + automatically freed when FreeRDP handles the write */); + +} + +int guac_rdp_svc_pipe_handler(guac_user* user, guac_stream* stream, + char* mimetype, char* name) { + + guac_rdp_svc* svc = guac_rdp_svc_get(user->client, name); + + /* Fail if no such SVC */ + if (svc == NULL) { + guac_user_log(user, GUAC_LOG_WARNING, "User requested non-existent " + "pipe (no such SVC configured): \"%s\"", name); + guac_protocol_send_ack(user->socket, stream, "FAIL (NO SUCH PIPE)", + GUAC_PROTOCOL_STATUS_CLIENT_BAD_REQUEST); + guac_socket_flush(user->socket); + return 0; + } + else + guac_user_log(user, GUAC_LOG_DEBUG, "Inbound half of channel \"%s\" " + "connected.", name); + + /* Init stream data */ + stream->data = svc; + stream->blob_handler = guac_rdp_svc_blob_handler; + + return 0; + +} + +int guac_rdp_svc_blob_handler(guac_user* user, guac_stream* stream, + void* data, int length) { + + /* Write blob data to SVC directly */ + guac_rdp_svc* svc = (guac_rdp_svc*) stream->data; + guac_rdp_svc_write(svc, data, length); + + guac_protocol_send_ack(user->socket, stream, "OK (DATA RECEIVED)", + GUAC_PROTOCOL_STATUS_SUCCESS); + guac_socket_flush(user->socket); + return 0; + +} + +void guac_rdp_svc_load_plugin(rdpContext* context, char* name) { + + guac_client* client = ((rdp_freerdp_context*) context)->client; + guac_rdp_svc* svc = calloc(1, sizeof(guac_rdp_svc)); + svc->client = client; + + /* Init FreeRDP channel definition */ + int name_length = guac_strlcpy(svc->channel_def.name, name, GUAC_RDP_SVC_MAX_LENGTH); + svc->channel_def.options = CHANNEL_OPTION_INITIALIZED + | CHANNEL_OPTION_ENCRYPT_RDP + | CHANNEL_OPTION_COMPRESS_RDP; + + /* Warn about name length */ + if (name_length >= GUAC_RDP_SVC_MAX_LENGTH) + guac_client_log(client, GUAC_LOG_WARNING, + "Static channel name \"%s\" exceeds maximum length of %i " + "characters and will be truncated to \"%s\".", + name, GUAC_RDP_SVC_MAX_LENGTH - 1, svc->channel_def.name); + + /* Attempt to load guacsvc plugin for new static channel */ + if (guac_freerdp_channels_load_plugin(context->channels, context->settings, "guacsvc", svc)) { + guac_client_log(client, GUAC_LOG_WARNING, "Cannot create static " + "channel \"%s\": failed to load guacsvc plugin.", + svc->channel_def.name); + free(svc); + } + + /* Store and log on success (SVC structure will be freed on channel termination) */ + else + guac_client_log(client, GUAC_LOG_INFO, "Created static channel " + "\"%s\"...", svc->channel_def.name); + +} + diff --git a/src/protocols/rdp/svc.h b/src/protocols/rdp/svc.h new file mode 100644 index 00000000..232b8c2c --- /dev/null +++ b/src/protocols/rdp/svc.h @@ -0,0 +1,215 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#ifndef GUAC_RDP_SVC_H +#define GUAC_RDP_SVC_H + +#include "config.h" + +#include +#include +#include +#include + +/** + * The maximum number of bytes to allow within each channel name, including + * null terminator. + */ +#define GUAC_RDP_SVC_MAX_LENGTH 8 + +/** + * Structure describing a static virtual channel, and the corresponding + * Guacamole pipes and FreeRDP resources. + */ +typedef struct guac_rdp_svc { + + /** + * Reference to the client owning this static channel. + */ + guac_client* client; + + /** + * The output pipe, opened when the RDP server receives a connection to + * the static channel. + */ + guac_stream* output_pipe; + + /** + * The definition of this static virtual channel, including its name. The + * name of the SVC is also used as the name of the associated Guacamole + * pipe streams. + */ + CHANNEL_DEF channel_def; + + /** + * Functions and data specific to the FreeRDP side of the virtual channel + * and plugin. + */ + CHANNEL_ENTRY_POINTS_FREERDP_EX entry_points; + + /** + * Handle which identifies the client connection, typically referred to + * within the FreeRDP source as pInitHandle. This handle is provided to the + * channel entry point and the channel init event handler. The handle must + * eventually be used within the channel open event handler to obtain a + * handle to the channel itself. + */ + PVOID init_handle; + + /** + * Handle which identifies the channel itself, typically referred to within + * the FreeRDP source as OpenHandle. This handle is obtained through a call + * to entry_points.pVirtualChannelOpenEx() in response to receiving a + * CHANNEL_EVENT_CONNECTED event via the init event handler. + * + * Data is received in CHANNEL_EVENT_DATA_RECEIVED events via the open + * event handler, and data is written through calls to + * entry_points.pVirtualChannelWriteEx(). + */ + DWORD open_handle; + +} guac_rdp_svc; + +/** + * Initializes arbitrary static virtual channel (SVC) support for RDP, loading + * a new instance of Guacamole's arbitrary SVC plugin for FreeRDP ("guacsvc") + * supporting the channel having the given name. Data sent from within the RDP + * session using this channel will be sent along an identically-named pipe + * stream to the Guacamole client, and data sent along a pipe stream having the + * same name will be written to the SVC and received within the RDP session. If + * failures occur while loading the plugin, messages noting the specifics of + * those failures will be logged, and support for the given channel will not be + * functional. + * + * This MUST be called within the PreConnect callback of the freerdp instance + * for static virtual channel support to be loaded. + * + * @param rdpContext + * The rdpContext associated with the FreeRDP side of the RDP connection. + * + * @param name + * The name of the SVC which should be handled by the new instance of the + * plugin. + */ +void guac_rdp_svc_load_plugin(rdpContext* context, char* name); + +/** + * Sends the "pipe" instruction describing the given static virtual channel + * along the given socket. This pipe instruction will relate the SVC's + * underlying output stream with the SVC's name and the mimetype + * "application/octet-stream". + * + * @param socket + * The socket along which the "pipe" instruction should be sent. + * + * @param svc + * The static virtual channel that the "pipe" instruction should describe. + */ +void guac_rdp_svc_send_pipe(guac_socket* socket, guac_rdp_svc* svc); + +/** + * Sends the "pipe" instructions describing all static virtual channels + * available to the given user along that user's socket. Each pipe instruction + * will relate the associated SVC's underlying output stream with the SVC's + * name and the mimetype "application/octet-stream". + * + * @param user + * The user to send the "pipe" instructions to. + */ +void guac_rdp_svc_send_pipes(guac_user* user); + +/** + * Add the given SVC to the list of all available SVCs. This function must be + * invoked after the SVC is connected for inbound pipe streams having that + * SVC's name to result in received data being sent into the RDP session. + * + * @param client + * The guac_client associated with the current RDP session. + * + * @param svc + * The static virtual channel to add to the list of all such channels + * available. + */ +void guac_rdp_svc_add(guac_client* client, guac_rdp_svc* svc); + +/** + * Retrieve the SVC with the given name from the list stored in the client. The + * requested SVC must previously have been added using guac_rdp_svc_add(). + * + * @param client + * The guac_client associated with the current RDP session. + * + * @param name + * The name of the static virtual channel to retrieve. + * + * @return + * The static virtual channel with the given name, or NULL if no such + * virtual channel exists. + */ +guac_rdp_svc* guac_rdp_svc_get(guac_client* client, const char* name); + +/** + * Removes the SVC with the given name from the list stored in the client. + * Inbound pipe streams having the given name will no longer be routed to the + * associated SVC. + * + * @param client + * The guac_client associated with the current RDP session. + * + * @param name + * The name of the static virtual channel to remove. + * + * @return + * The static virtual channel that was removed, or NULL if no such virtual + * channel exists. + */ +guac_rdp_svc* guac_rdp_svc_remove(guac_client* client, const char* name); + +/** + * Writes the given blob of data to the virtual channel such that it can be + * received within the RDP session. + * + * @param svc + * The static virtual channel to write data to. + * + * @param data + * The data to write. + * + * @param length + * The number of bytes to write. + */ +void guac_rdp_svc_write(guac_rdp_svc* svc, void* data, int length); + +/** + * Handler for "blob" instructions which automatically writes received data to + * the associated SVC using guac_rdp_svc_write(). + */ +guac_user_blob_handler guac_rdp_svc_blob_handler; + +/** + * Handler for "pipe" instructions which automatically prepares received pipe + * streams to automatically write received blobs to the SVC having the same + * name as the pipe stream. Received pipe streams are associated with the + * relevant guac_rdp_svc instance and the SVC-specific "blob" instructino + * handler (guac_rdp_svc_blob_handler). + */ +guac_user_pipe_handler guac_rdp_svc_pipe_handler; + +#endif + diff --git a/src/protocols/rdp/user.c b/src/protocols/rdp/user.c index 04238e8c..47ba93ad 100644 --- a/src/protocols/rdp/user.c +++ b/src/protocols/rdp/user.c @@ -26,9 +26,7 @@ #include "rdp.h" #include "rdp_settings.h" #include "rdp_stream.h" -#if 0 -#include "rdp_svc.h" -#endif +#include "svc.h" #ifdef ENABLE_COMMON_SSH #include "sftp.h" @@ -87,10 +85,8 @@ int guac_rdp_user_join_handler(guac_user* user, int argc, char** argv) { if (rdp_client->audio) guac_audio_stream_add_user(rdp_client->audio, user); -#if 0 /* Bring user up to date with any registered static channels */ guac_rdp_svc_send_pipes(user); -#endif /* Synchronize with current display */ guac_common_display_dup(rdp_client->display, user, user->socket); @@ -112,10 +108,8 @@ int guac_rdp_user_join_handler(guac_user* user, int argc, char** argv) { /* Set generic (non-filesystem) file upload handler */ user->file_handler = guac_rdp_user_file_handler; -#if 0 /* Inbound arbitrary named pipes */ user->pipe_handler = guac_rdp_svc_pipe_handler; -#endif } From f3cef7e2f02737eee163eab4bbd1d560fc45cc25 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 15 Dec 2019 22:29:10 -0800 Subject: [PATCH 036/109] GUACAMOLE-249: Add example for testing arbitrary SVC support. --- src/protocols/rdp/doc/svc-example/.gitignore | 2 + src/protocols/rdp/doc/svc-example/Makefile | 43 +++++ src/protocols/rdp/doc/svc-example/README.md | 169 ++++++++++++++++++ .../rdp/doc/svc-example/svc-example.c | 71 ++++++++ 4 files changed, 285 insertions(+) create mode 100644 src/protocols/rdp/doc/svc-example/.gitignore create mode 100644 src/protocols/rdp/doc/svc-example/Makefile create mode 100644 src/protocols/rdp/doc/svc-example/README.md create mode 100644 src/protocols/rdp/doc/svc-example/svc-example.c diff --git a/src/protocols/rdp/doc/svc-example/.gitignore b/src/protocols/rdp/doc/svc-example/.gitignore new file mode 100644 index 00000000..51e8bef6 --- /dev/null +++ b/src/protocols/rdp/doc/svc-example/.gitignore @@ -0,0 +1,2 @@ +!Makefile +*.exe diff --git a/src/protocols/rdp/doc/svc-example/Makefile b/src/protocols/rdp/doc/svc-example/Makefile new file mode 100644 index 00000000..8c38e594 --- /dev/null +++ b/src/protocols/rdp/doc/svc-example/Makefile @@ -0,0 +1,43 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# +# NOTE: Parts of this file (Makefile.am) are automatically transcluded verbatim +# into Makefile.in. Though the build system (GNU Autotools) automatically adds +# its own license boilerplate to the generated Makefile.in, that boilerplate +# does not apply to the transcluded portions of Makefile.am which are licensed +# to you by the ASF under the Apache License, Version 2.0, as described above. +# + +LDFLAGS=-lwtsapi32 + +# Requires at least Windows Vista (Windows Server 2008 qualifies) +WINVER=0x600 + +# Windows cross compiler (MinGW) +CC=i686-w64-mingw32-gcc + +all: svc-example.exe + +clean: + $(RM) svc-example.exe + +svc-example.exe: svc-example.c + $(CC) svc-example.c $(LDFLAGS) \ + -D_WIN32_WINNT=$(WINVER) \ + -DWINVER=$(WINVER) -o svc-example.exe + diff --git a/src/protocols/rdp/doc/svc-example/README.md b/src/protocols/rdp/doc/svc-example/README.md new file mode 100644 index 00000000..337a733e --- /dev/null +++ b/src/protocols/rdp/doc/svc-example/README.md @@ -0,0 +1,169 @@ +Static Virtual Channel example +============================== + +Guacamole supports use of static virtual channels (SVCs) for transmission of +arbitrary data between the JavaScript client and applications running within +RDP sessions. This example is intended to demonstrate how bidirectional +communication between the Guacamole client and applications within the RDP +server can be accomplished. + +Arbitrary SVCs are enabled on RDP connections by specfying their names as the +value of [the `static-channels` +parameter](http://guacamole.apache.org/doc/gug/configuring-guacamole.html#rdp-device-redirection). +Each name is limited to a maximum of 7 characters. Multiple names may be listed +by separating those names with commas. + +This example consists of a single file, [`svc-example.c`](svc-example.c), which +leverages the terminal server API exposed by Windows to: + + 1. Open a channel called "EXAMPLE" + 2. Wait for blocks of data to be received + 3. Send each received block of data back, unmodified. + +Building the example +-------------------- + +A `Makefile` is provided which uses MinGW to build the `svc-example.exe` +executable, and thus can be used to produce the example application on Linux. +The `Makefile` is not platform-independent, and changes may be needed for +`make` to succeed with your installation of MinGW. If not using MinGW, the C +source itself is standard and should compile with other tools. + +To build on Linux using `make`: + +```console +$ make +i686-w64-mingw32-gcc svc-example.c -lwtsapi32 \ + -D_WIN32_WINNT=0x600 \ + -DWINVER=0x600 -o svc-example.exe +$ +``` + +You can then copy the resulting `svc-example.exe` to the remote desktop that +you wish to test and run it within a command prompt within the remote desktop +session. + +Using the example (and SVCs in general) +--------------------------------------- + +On the remote desktop server side (within the Windows application leveraging +SVCs to communicate with Guacamole), the following functions are used +specifically for reading/writing to the SVC: + + * [`WTSVirtualChannelOpenEx()`](https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsvirtualchannelopenex) + * [`WTSVirtualChannelRead()`](https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsvirtualchannelread) + * [`WTSVirtualChannelWrite()`](https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsvirtualchannelwrite) + * [`WTSVirtualChannelClose()`](https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsvirtualchannelclose) + +On the Guacamole side, bidirectional communication is established using: + + * The `static-channels` connection parameter (in the case of the example, this should be set to `EXAMPLE`). + * An [`onpipe`](http://guacamole.apache.org/doc/guacamole-common-js/Guacamole.Client.html#event:onpipe) + handler which handles inbound (server-to-client) pipe streams named identically + to the SVC. The inbound pipe stream will be received upon establishing the RDP + connection and is used to transmit any data sent along the SVC **from** within + the remote desktop session. For example: + + ```js + client.onpipe = function pipeReceived(stream, mimetype, name) { + + // Receive output of SVC + if (name === 'EXAMPLE') { + + // Log start of stream + var reader = new Guacamole.StringReader(stream); + console.log('pipe: %s: stream begins', name); + + // Log each received blob of text + reader.ontext = function textReceived(text) { + console.log('pipe: %s: \"%s\"', name, text); + }; + + // Log end of stream + reader.onend = function streamEnded() { + console.log('pipe: %s: stream ends', name); + }; + + } + + // All other inbound pipe streams are unsupported + else + stream.sendAck('Pipe stream not supported.', + Guacamole.Status.Code.UNSUPPORTED); + + }; + ``` + + * Calls to [`createPipeStream()`](http://guacamole.apache.org/doc/guacamole-common-js/Guacamole.Client.html#createPipeStream) + as needed to establish outbound (client-to-server) pipe streams named + identically to the SVC. Outbound pipe streams with the same name as the SVC + will be automatically handled by the Guacamole server, with any received data + sent along the SVC **to** the remote desktop session. For example: + + ```js + var example = new Guacamole.StringWriter(client.createPipeStream('text/plain', 'EXAMPLE')); + example.sendText('This is a test.'); + example.sendEnd(); + ``` + + These pipe streams may be created and destroyed as desired. As long as they + have the same name as the SVC, data sent along the pipe stream will be sent + along the SVC. + +Example output +-------------- + +If the `static-channels` parameter is set to `EXAMPLE`, the successful creation +of the "EXAMPLE" channel should be logged by guacd when the connection is +established: + +``` +guacd[12057]: INFO: Created static channel "EXAMPLE"... +guacd[12057]: INFO: Static channel "EXAMPLE" connected. +``` + +On the client side, the `onpipe` handler should be invoked immediately. If +using the example code shown above, receipt of the pipe stream for the +"EXAMPLE" channel is logged: + +``` +pipe: EXAMPLE: stream begins +``` + +Running `svc-example.exe` within a command prompt inside the remote desktop +session, the application logs that the "EXAMPLE" channel has been successfully +opened: + +``` +Microsoft Windows [Version 10.0.17763.437] +(c) 2018 Microsoft Corporation. All rights reserved. + +C:\Users\test>svc-example.exe +SVC "EXAMPLE" open. Reading... +``` + +Once `createPipeStream()` has been invoked on the Guacamole client side and +using the same name as the SVC (in this case, "EXAMPLE") guacd should log the +inbound half the channel is now connected: + +``` +guacd[12057]: DEBUG: Inbound half of channel "EXAMPLE" connected. +``` + +Sending the string `This is a test.` along the client-to-server pipe (as shown +in the example code above) results in `svc-example.exe` logging that it +received those 15 bytes and has resent the same 15 bytes back along the SVC: + +``` +Received 15 bytes. +Wrote 15 bytes. +``` + +The data sent from within the remote desktop session is received on the client +side via the server-to-client pipe stream. If using the example code shown +above, the received data is logged: + +``` +pipe: EXAMPLE: "This is a test." +``` + diff --git a/src/protocols/rdp/doc/svc-example/svc-example.c b/src/protocols/rdp/doc/svc-example/svc-example.c new file mode 100644 index 00000000..681b3f91 --- /dev/null +++ b/src/protocols/rdp/doc/svc-example/svc-example.c @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#include +#include +#include + +#include + +/** + * The name of the RDP static virtual channel (SVC). + */ +#define SVC_NAME "EXAMPLE" + +int main() { + + ULONG bytes_read; + ULONG bytes_written; + + char message[4096]; + + /* Open SVC */ + HANDLE svc = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, SVC_NAME, 0); + + /* Fail if we cannot open an SVC at all */ + if (svc == NULL) { + printf("Cannot open SVC \"" SVC_NAME "\"\n"); + return 0; + } + + printf("SVC \"" SVC_NAME "\" open. Reading...\n"); + + /* Continuously read from SVC */ + while (WTSVirtualChannelRead(svc, INFINITE, message, sizeof(message), &bytes_read)) { + + printf("Received %i bytes.\n", bytes_read); + + /* Write all received data back to the SVC, possibly spreading the data + * across multiple writes */ + char* current = message; + while (bytes_read > 0 && WTSVirtualChannelWrite(svc, current, + bytes_read, &bytes_written)) { + printf("Wrote %i bytes.\n", bytes_written); + bytes_read -= bytes_written; + } + + } + + /* Close SVC */ + WTSVirtualChannelClose(svc); + printf("SVC \"" SVC_NAME "\" closed.\n"); + return 1; + +} + From 0497a33ece16dc263691a969446debbb93cf266c Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 21 Dec 2019 14:03:32 -0800 Subject: [PATCH 037/109] GUACAMOLE-249: Migrate loading of RDPSND support ("guacsnd" plugin) to abstract function. --- src/protocols/rdp/Makefile.am | 2 ++ src/protocols/rdp/rdp.c | 8 ++----- src/protocols/rdp/rdpsnd.c | 43 +++++++++++++++++++++++++++++++++++ src/protocols/rdp/rdpsnd.h | 39 +++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 src/protocols/rdp/rdpsnd.c create mode 100644 src/protocols/rdp/rdpsnd.h diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index 2849a2ca..10029c14 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -59,6 +59,7 @@ libguac_client_rdp_la_SOURCES = \ rdp_pointer.c \ rdp_settings.c \ rdp_stream.c \ + rdpsnd.c \ resolution.c \ svc.c \ unicode.c \ @@ -100,6 +101,7 @@ noinst_HEADERS = \ rdp_settings.h \ rdp_status.h \ rdp_stream.h \ + rdpsnd.h \ resolution.h \ svc.h \ unicode.h \ diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index e2ba5938..17da6e6d 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -38,6 +38,7 @@ #include "rdp_glyph.h" #include "rdp_pointer.h" #include "rdp_stream.h" +#include "rdpsnd.h" #include "svc.h" #ifdef ENABLE_COMMON_SSH @@ -116,12 +117,7 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { "printing will not work. Sound MAY not work."); /* Load RDPSND plugin */ - if (guac_freerdp_channels_load_plugin(channels, instance->settings, - "guacsnd", client)) - guac_client_log(client, GUAC_LOG_WARNING, - "Failed to load guacsnd alongside guacdr plugin. Sound " - "will not work. Drive redirection and printing MAY not " - "work."); + guac_rdpsnd_load_plugin(context); } diff --git a/src/protocols/rdp/rdpsnd.c b/src/protocols/rdp/rdpsnd.c new file mode 100644 index 00000000..23b31336 --- /dev/null +++ b/src/protocols/rdp/rdpsnd.c @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#include "config.h" +#include "channels.h" +#include "rdp.h" + +#include +#include + +void guac_rdpsnd_load_plugin(rdpContext* context) { + + guac_client* client = ((rdp_freerdp_context*) context)->client; + + /* Load RDPSND plugin */ + if (guac_freerdp_channels_load_plugin(context->channels, context->settings, "guacsnd", client)) { + guac_client_log(client, GUAC_LOG_WARNING, "Support for the RDPSND " + "channel (audio output) could not be loaded. Sound will not " + "work. Drive redirection and printing MAY not work."); + return; + } + + guac_client_log(client, GUAC_LOG_DEBUG, "Support for RDPSND (audio " + "output) registered. Awaiting channel connection."); + +} + diff --git a/src/protocols/rdp/rdpsnd.h b/src/protocols/rdp/rdpsnd.h new file mode 100644 index 00000000..51e86150 --- /dev/null +++ b/src/protocols/rdp/rdpsnd.h @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#ifndef GUAC_RDP_RDPSND_H +#define GUAC_RDP_RDPSND_H + +#include "config.h" + +/** + * Initializes audio output support for RDP and handling of the RDPSND channel. + * If failures occur, messages noting the specifics of those failures will be + * logged, and the RDP side of audio output support will not be functional. + * + * This MUST be called within the PreConnect callback of the freerdp instance + * for RDPSND support to be loaded. + * + * @param rdpContext + * The rdpContext associated with the FreeRDP side of the RDP connection. + */ +void guac_rdpsnd_load_plugin(rdpContext* context); + +#endif + From 6f2b12447259c370076497f90fd22acfffe6ff07 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 21 Dec 2019 17:44:43 -0800 Subject: [PATCH 038/109] GUACAMOLE-249: Migrate RDPSND support to FreeRDP 2.0.0 plugin API. --- src/protocols/rdp/Makefile.am | 40 +-- .../rdp/guac_rdpsnd/rdpsnd_messages.c | 41 +-- .../rdp/guac_rdpsnd/rdpsnd_messages.h | 14 +- .../rdp/guac_rdpsnd/rdpsnd_service.c | 311 ++++++++++++++---- .../rdp/guac_rdpsnd/rdpsnd_service.h | 72 ++-- 5 files changed, 333 insertions(+), 145 deletions(-) diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index 10029c14..a5eb77f2 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -130,9 +130,9 @@ libguac_client_rdp_la_LIBADD = \ freerdp_LTLIBRARIES = \ libguacai-client.la \ + libguacsnd-client.la \ libguacsvc-client.la # libguacdr-client.la -# libguacsnd-client.la freerdpdir = ${libdir}/freerdp2 @@ -200,25 +200,25 @@ libguacai_client_la_LIBADD = \ # RDPSND # -#libguacsnd_client_la_SOURCES = \ -# guac_rdpsnd/rdpsnd_messages.c \ -# guac_rdpsnd/rdpsnd_service.c -# -#libguacsnd_client_la_CFLAGS = \ -# -Werror -Wall -Iinclude \ -# @COMMON_INCLUDE@ \ -# @COMMON_SSH_INCLUDE@ \ -# @LIBGUAC_INCLUDE@ \ -# @RDP_CFLAGS@ -# -#libguacsnd_client_la_LDFLAGS = \ -# -module -avoid-version -shared \ -# @PTHREAD_LIBS@ \ -# @RDP_LIBS@ -# -#libguacsnd_client_la_LIBADD = \ -# @COMMON_LTLIB@ \ -# @LIBGUAC_LTLIB@ +libguacsnd_client_la_SOURCES = \ + guac_rdpsnd/rdpsnd_messages.c \ + guac_rdpsnd/rdpsnd_service.c + +libguacsnd_client_la_CFLAGS = \ + -Werror -Wall -Iinclude \ + @COMMON_INCLUDE@ \ + @COMMON_SSH_INCLUDE@ \ + @LIBGUAC_INCLUDE@ \ + @RDP_CFLAGS@ + +libguacsnd_client_la_LDFLAGS = \ + -module -avoid-version -shared \ + @PTHREAD_LIBS@ \ + @RDP_LIBS@ + +libguacsnd_client_la_LIBADD = \ + @COMMON_LTLIB@ \ + @LIBGUAC_LTLIB@ # # Static Virtual Channels diff --git a/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.c b/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.c index 4893ad49..90c59a18 100644 --- a/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.c +++ b/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.c @@ -26,7 +26,6 @@ #include #include -#include #include #include #include @@ -34,7 +33,7 @@ /* MESSAGE HANDLERS */ -void guac_rdpsnd_formats_handler(guac_rdpsndPlugin* rdpsnd, +void guac_rdpsnd_formats_handler(guac_rdpsnd* rdpsnd, wStream* input_stream, guac_rdpsnd_pdu_header* header) { int server_format_count; @@ -182,8 +181,9 @@ void guac_rdpsnd_formats_handler(guac_rdpsndPlugin* rdpsnd, Stream_SetPointer(output_stream, output_stream_end); /* Send accepted formats */ - pthread_mutex_lock(&(rdp_client->rdp_lock)); - svc_plugin_send((rdpSvcPlugin*)rdpsnd, output_stream); + rdpsnd->entry_points.pVirtualChannelWriteEx(rdpsnd->init_handle, + rdpsnd->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); /* If version greater than 6, must send Quality Mode PDU */ if (server_version >= 6) { @@ -196,24 +196,21 @@ void guac_rdpsnd_formats_handler(guac_rdpsndPlugin* rdpsnd, Stream_Write_UINT16(output_stream, HIGH_QUALITY); Stream_Write_UINT16(output_stream, 0); - svc_plugin_send((rdpSvcPlugin*)rdpsnd, output_stream); - } + rdpsnd->entry_points.pVirtualChannelWriteEx(rdpsnd->init_handle, + rdpsnd->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); - pthread_mutex_unlock(&(rdp_client->rdp_lock)); + } } /* server is getting a feel of the round trip time */ -void guac_rdpsnd_training_handler(guac_rdpsndPlugin* rdpsnd, +void guac_rdpsnd_training_handler(guac_rdpsnd* rdpsnd, wStream* input_stream, guac_rdpsnd_pdu_header* header) { int data_size; wStream* output_stream; - /* Get associated client data */ - guac_client* client = rdpsnd->client; - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - /* Read timestamp and data size */ Stream_Read_UINT16(input_stream, rdpsnd->server_timestamp); Stream_Read_UINT16(input_stream, data_size); @@ -226,13 +223,13 @@ void guac_rdpsnd_training_handler(guac_rdpsndPlugin* rdpsnd, Stream_Write_UINT16(output_stream, rdpsnd->server_timestamp); Stream_Write_UINT16(output_stream, data_size); - pthread_mutex_lock(&(rdp_client->rdp_lock)); - svc_plugin_send((rdpSvcPlugin*) rdpsnd, output_stream); - pthread_mutex_unlock(&(rdp_client->rdp_lock)); + rdpsnd->entry_points.pVirtualChannelWriteEx(rdpsnd->init_handle, + rdpsnd->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } -void guac_rdpsnd_wave_info_handler(guac_rdpsndPlugin* rdpsnd, +void guac_rdpsnd_wave_info_handler(guac_rdpsnd* rdpsnd, wStream* input_stream, guac_rdpsnd_pdu_header* header) { int format; @@ -270,11 +267,9 @@ void guac_rdpsnd_wave_info_handler(guac_rdpsndPlugin* rdpsnd, } -void guac_rdpsnd_wave_handler(guac_rdpsndPlugin* rdpsnd, +void guac_rdpsnd_wave_handler(guac_rdpsnd* rdpsnd, wStream* input_stream, guac_rdpsnd_pdu_header* header) { - rdpSvcPlugin* plugin = (rdpSvcPlugin*)rdpsnd; - /* Get associated client data */ guac_client* client = rdpsnd->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; @@ -307,16 +302,16 @@ void guac_rdpsnd_wave_handler(guac_rdpsndPlugin* rdpsnd, Stream_Write_UINT8(output_stream, 0); /* Send Wave Confirmation PDU */ - pthread_mutex_lock(&(rdp_client->rdp_lock)); - svc_plugin_send(plugin, output_stream); - pthread_mutex_unlock(&(rdp_client->rdp_lock)); + rdpsnd->entry_points.pVirtualChannelWriteEx(rdpsnd->init_handle, + rdpsnd->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); /* We no longer expect to receive wave data */ rdpsnd->next_pdu_is_wave = FALSE; } -void guac_rdpsnd_close_handler(guac_rdpsndPlugin* rdpsnd, +void guac_rdpsnd_close_handler(guac_rdpsnd* rdpsnd, wStream* input_stream, guac_rdpsnd_pdu_header* header) { /* Do nothing */ diff --git a/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.h b/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.h index 5fceca77..700c41b6 100644 --- a/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.h +++ b/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.h @@ -18,8 +18,8 @@ */ -#ifndef __GUAC_RDPSND_MESSAGES_H -#define __GUAC_RDPSND_MESSAGES_H +#ifndef GUAC_RDPSND_MESSAGES_H +#define GUAC_RDPSND_MESSAGES_H #include "config.h" @@ -128,7 +128,7 @@ typedef struct guac_rdpsnd_pdu_header { * The header content of the SNDC_FORMATS PDU. All RDPSND messages contain * the same header information. */ -void guac_rdpsnd_formats_handler(guac_rdpsndPlugin* rdpsnd, +void guac_rdpsnd_formats_handler(guac_rdpsnd* rdpsnd, wStream* input_stream, guac_rdpsnd_pdu_header* header); /** @@ -149,7 +149,7 @@ void guac_rdpsnd_formats_handler(guac_rdpsndPlugin* rdpsnd, * The header content of the SNDC_TRAINING PDU. All RDPSND messages contain * the same header information. */ -void guac_rdpsnd_training_handler(guac_rdpsndPlugin* rdpsnd, +void guac_rdpsnd_training_handler(guac_rdpsnd* rdpsnd, wStream* input_stream, guac_rdpsnd_pdu_header* header); /** @@ -172,7 +172,7 @@ void guac_rdpsnd_training_handler(guac_rdpsndPlugin* rdpsnd, * The header content of the SNDC_WAVE PDU. All RDPSND messages contain * the same header information. */ -void guac_rdpsnd_wave_info_handler(guac_rdpsndPlugin* rdpsnd, +void guac_rdpsnd_wave_info_handler(guac_rdpsnd* rdpsnd, wStream* input_stream, guac_rdpsnd_pdu_header* header); /** @@ -191,7 +191,7 @@ void guac_rdpsnd_wave_info_handler(guac_rdpsndPlugin* rdpsnd, * The header content of the SNDWAV PDU. All RDPSND messages contain * the same header information. */ -void guac_rdpsnd_wave_handler(guac_rdpsndPlugin* rdpsnd, +void guac_rdpsnd_wave_handler(guac_rdpsnd* rdpsnd, wStream* input_stream, guac_rdpsnd_pdu_header* header); /** @@ -211,7 +211,7 @@ void guac_rdpsnd_wave_handler(guac_rdpsndPlugin* rdpsnd, * The header content of the SNDC_CLOSE PDU. All RDPSND messages contain * the same header information. */ -void guac_rdpsnd_close_handler(guac_rdpsndPlugin* rdpsnd, +void guac_rdpsnd_close_handler(guac_rdpsnd* rdpsnd, wStream* input_stream, guac_rdpsnd_pdu_header* header); #endif diff --git a/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c b/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c index d3bce560..b18a2652 100644 --- a/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c +++ b/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c @@ -26,74 +26,23 @@ #include #include -#include #include #include /** - * Entry point for RDPSND virtual channel. + * Processes data received along the RDPSND channel via a + * CHANNEL_EVENT_DATA_RECEIVED event, forwarding the data along an established, + * outbound pipe stream to the Guacamole client. + * + * @param rdpsnd + * The guac_rdpsnd structure representing the RDPSND channel. + * + * @param input_stream + * The data that was received. */ -int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) { - - /* Allocate plugin */ - guac_rdpsndPlugin* rdpsnd = - (guac_rdpsndPlugin*) calloc(1, sizeof(guac_rdpsndPlugin)); - - /* Init channel def */ - strcpy(rdpsnd->plugin.channel_def.name, "rdpsnd"); - rdpsnd->plugin.channel_def.options = - CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP; - - /* Set callbacks */ - rdpsnd->plugin.connect_callback = guac_rdpsnd_process_connect; - rdpsnd->plugin.receive_callback = guac_rdpsnd_process_receive; - rdpsnd->plugin.event_callback = guac_rdpsnd_process_event; - rdpsnd->plugin.terminate_callback = guac_rdpsnd_process_terminate; - - /* Finish init */ - svc_plugin_init((rdpSvcPlugin*) rdpsnd, pEntryPoints); - return 1; - -} - -/* - * Service Handlers - */ - -void guac_rdpsnd_process_connect(rdpSvcPlugin* plugin) { - - guac_rdpsndPlugin* rdpsnd = (guac_rdpsndPlugin*) plugin; - - /* Get client from plugin parameters */ - guac_client* client = rdpsnd->client = - (guac_client*) plugin->channel_entry_points.pExtendedData; - - /* NULL out pExtendedData so we don't lose our guac_client due to an - * automatic free() within libfreerdp */ - plugin->channel_entry_points.pExtendedData = NULL; - -#ifdef RDPSVCPLUGIN_INTERVAL_MS - /* Update every 10 ms */ - plugin->interval_ms = 10; -#endif - - /* Log that sound has been loaded */ - guac_client_log(client, GUAC_LOG_INFO, "guacsnd connected."); - -} - -void guac_rdpsnd_process_terminate(rdpSvcPlugin* plugin) { - free(plugin); -} - -void guac_rdpsnd_process_event(rdpSvcPlugin* plugin, wMessage* event) { - freerdp_event_free(event); -} - -void guac_rdpsnd_process_receive(rdpSvcPlugin* plugin, +static void guac_rdpsnd_process_receive(guac_rdpsnd* rdpsnd, wStream* input_stream) { - guac_rdpsndPlugin* rdpsnd = (guac_rdpsndPlugin*) plugin; guac_rdpsnd_pdu_header header; /* Read RDPSND PDU header */ @@ -137,3 +86,243 @@ void guac_rdpsnd_process_receive(rdpSvcPlugin* plugin, } +/** + * Event handler for events which deal with data transmitted over the RDPSND + * channel. This specific implementation of the event handler currently + * handles only the CHANNEL_EVENT_DATA_RECEIVED event, delegating actual + * handling of that event to guac_rdpsnd_process_receive(). + * + * The FreeRDP requirements for this function follow those of the + * VirtualChannelOpenEventEx callback defined within Microsoft's RDP API: + * + * https://docs.microsoft.com/en-us/previous-versions/windows/embedded/aa514754%28v%3dmsdn.10%29 + * + * @param user_param + * The pointer to arbitrary data originally passed via the first parameter + * of the pVirtualChannelInitEx() function call when the associated channel + * was initialized. The pVirtualChannelInitEx() function is exposed within + * the channel entry points structure. + * + * @param open_handle + * The handle which identifies the channel itself, typically referred to + * within the FreeRDP source as OpenHandle. + * + * @param event + * An integer representing the event that should be handled. This will be + * either CHANNEL_EVENT_DATA_RECEIVED, CHANNEL_EVENT_WRITE_CANCELLED, or + * CHANNEL_EVENT_WRITE_COMPLETE. + * + * @param data + * The data received, for CHANNEL_EVENT_DATA_RECEIVED events, and the value + * passed as user data to pVirtualChannelWriteEx() for + * CHANNEL_EVENT_WRITE_* events (note that user data for + * pVirtualChannelWriteEx() as implemented by FreeRDP MUST either be NULL + * or a wStream containing the data written). + * + * @param data_length + * The number of bytes of event-specific data. + * + * @param total_length + * The total number of bytes written to the RDP server in a single write + * operation. + * + * NOTE: The meaning of total_length is unclear. The above description was + * written mainly through referencing the documentation in MSDN. Real-world + * use will need to be consulted, likely within the FreeRDP source, before + * this value can be reliably used. The current implementation of this + * handler ignores this parameter. + * + * @param data_flags + * The result of a bitwise OR of the CHANNEL_FLAG_* flags which apply to + * the data received. This value is relevant only to + * CHANNEL_EVENT_DATA_RECEIVED events. Valid flags are CHANNEL_FLAG_FIRST, + * CHANNEL_FLAG_LAST, and CHANNEL_FLAG_ONLY. The flag CHANNEL_FLAG_MIDDLE + * is not itself a flag, but the absence of both CHANNEL_FLAG_FIRST and + * CHANNEL_FLAG_LAST. + */ +static VOID guac_rdpsnd_handle_open_event(LPVOID user_param, + DWORD open_handle, UINT event, LPVOID data, UINT32 data_length, + UINT32 total_length, UINT32 data_flags) { + + /* Ignore all events except for received data */ + if (event != CHANNEL_EVENT_DATA_RECEIVED) + return; + + guac_rdpsnd* rdpsnd = (guac_rdpsnd*) user_param; + + /* Validate relevant handle matches that of the RDPSND channel */ + if (open_handle != rdpsnd->open_handle) { + guac_client_log(rdpsnd->client, GUAC_LOG_WARNING, "%i bytes of data " + "received from within the remote desktop session for the " + "RDPSND channel are being dropped because the relevant open " + "handle (0x%X) does not match the open handle of RDPSND " + "(0x%X).", data_length, rdpsnd->channel_def.name, open_handle, + rdpsnd->open_handle); + return; + } + + wStream* input_stream = Stream_New(data, data_length); + guac_rdpsnd_process_receive(rdpsnd, input_stream); + Stream_Free(input_stream, FALSE); + +} + +/** + * Processes a CHANNEL_EVENT_CONNECTED event, completing the + * connection/initialization process of the RDPSND channel. + * + * @param rdpsnd + * The guac_rdpsnd structure representing the RDPSND channel. + */ +static void guac_rdpsnd_process_connect(guac_rdpsnd* rdpsnd) { + + /* Open FreeRDP side of connected channel */ + UINT32 open_status = + rdpsnd->entry_points.pVirtualChannelOpenEx(rdpsnd->init_handle, + &rdpsnd->open_handle, rdpsnd->channel_def.name, + guac_rdpsnd_handle_open_event); + + /* Warn if the channel cannot be opened after all */ + if (open_status != CHANNEL_RC_OK) { + guac_client_log(rdpsnd->client, GUAC_LOG_WARNING, "RDPSND channel " + "could not be opened: %s (error %i)", + WTSErrorToString(open_status), open_status); + return; + } + + /* Log that sound has been loaded */ + guac_client_log(rdpsnd->client, GUAC_LOG_INFO, "RDPSND channel " + "connected."); + +} + +/** + * Processes a CHANNEL_EVENT_TERMINATED event, freeing all resources associated + * with the RDPSND channel. + * + * @param rdpsnd + * The guac_rdpsnd structure representing the RDPSND channel. + */ +static void guac_rdpsnd_process_terminate(guac_rdpsnd* rdpsnd) { + guac_client_log(rdpsnd->client, GUAC_LOG_INFO, "RDPSND channel disconnected."); + free(rdpsnd); +} + +/** + * Event handler for events which deal with the overall lifecycle of the RDPSND + * channel. This specific implementation of the event handler currently + * handles only CHANNEL_EVENT_CONNECTED and CHANNEL_EVENT_TERMINATED events, + * delegating actual handling of those events to guac_rdpsnd_process_connect() + * and guac_rdpsnd_process_terminate() respectively. + * + * The FreeRDP requirements for this function follow those of the + * VirtualChannelInitEventEx callback defined within Microsoft's RDP API: + * + * https://docs.microsoft.com/en-us/previous-versions/windows/embedded/aa514727%28v%3dmsdn.10%29 + * + * @param user_param + * The pointer to arbitrary data originally passed via the first parameter + * of the pVirtualChannelInitEx() function call when the associated channel + * was initialized. The pVirtualChannelInitEx() function is exposed within + * the channel entry points structure. + * + * @param init_handle + * The handle which identifies the client connection, typically referred to + * within the FreeRDP source as pInitHandle. + * + * @param event + * An integer representing the event that should be handled. This will be + * either CHANNEL_EVENT_CONNECTED, CHANNEL_EVENT_DISCONNECTED, + * CHANNEL_EVENT_INITIALIZED, CHANNEL_EVENT_TERMINATED, or + * CHANNEL_EVENT_V1_CONNECTED. + * + * @param data + * NULL in all cases except the CHANNEL_EVENT_CONNECTED event, in which + * case this is a null-terminated string containing the name of the server. + * + * @param data_length + * The number of bytes of data, if any. + */ +static VOID guac_rdpsnd_handle_init_event(LPVOID user_param, + LPVOID init_handle, UINT event, LPVOID data, UINT data_length) { + + guac_rdpsnd* rdpsnd = (guac_rdpsnd*) user_param; + + /* Validate relevant handle matches that of the RDPSND channel */ + if (init_handle != rdpsnd->init_handle) { + guac_client_log(rdpsnd->client, GUAC_LOG_WARNING, "An init event " + "(#%i) for the RDPSND channel has been dropped because the " + "relevant init handle (0x%X) does not match the init handle " + "of the RDPSND channel (0x%X).", event, init_handle, + rdpsnd->init_handle); + return; + } + + switch (event) { + + /* The RDPSND channel has been connected */ + case CHANNEL_EVENT_CONNECTED: + guac_rdpsnd_process_connect(rdpsnd); + break; + + /* The RDPSND channel has disconnected and now must be cleaned up */ + case CHANNEL_EVENT_TERMINATED: + guac_rdpsnd_process_terminate(rdpsnd); + break; + + } + +} + +/** + * Entry point for FreeRDP plugins. This function is automatically invoked when + * the plugin is loaded. + * + * @param entry_points + * Functions and data specific to the FreeRDP side of the virtual channel + * and plugin. This structure must be copied within implementation-specific + * storage such that the functions it references can be invoked when + * needed. + * + * @param init_handle + * The handle which identifies the client connection, typically referred to + * within the FreeRDP source as pInitHandle. This handle is also provided + * to the channel init event handler. The handle must eventually be used + * within the channel open event handler to obtain a handle to the channel + * itself. + * + * @return + * TRUE if the plugin has initialized successfully, FALSE otherwise. + */ +BOOL VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS entry_points, + PVOID init_handle) { + + CHANNEL_ENTRY_POINTS_FREERDP_EX* entry_points_ex = + (CHANNEL_ENTRY_POINTS_FREERDP_EX*) entry_points; + + /* Allocate plugin */ + guac_rdpsnd* rdpsnd = (guac_rdpsnd*) calloc(1, sizeof(guac_rdpsnd)); + + /* Init channel def */ + strcpy(rdpsnd->channel_def.name, "rdpsnd"); + rdpsnd->channel_def.options = CHANNEL_OPTION_INITIALIZED + | CHANNEL_OPTION_ENCRYPT_RDP; + + /* Maintain reference to associated guac_client */ + rdpsnd->client = (guac_client*) entry_points_ex->pExtendedData; + + /* Copy FreeRDP data into RDPSND structure for future reference */ + rdpsnd->entry_points = *entry_points_ex; + rdpsnd->init_handle = init_handle; + + /* Complete initialization */ + if (rdpsnd->entry_points.pVirtualChannelInitEx(rdpsnd, rdpsnd, init_handle, + &rdpsnd->channel_def, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, + guac_rdpsnd_handle_init_event) != CHANNEL_RC_OK) { + return FALSE; + } + + return TRUE; + +} + diff --git a/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.h b/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.h index 7a4aff52..de615ab0 100644 --- a/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.h +++ b/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.h @@ -18,14 +18,15 @@ */ -#ifndef __GUAC_RDPSND_SERVICE_H -#define __GUAC_RDPSND_SERVICE_H +#ifndef GUAC_RDPSND_SERVICE_H +#define GUAC_RDPSND_SERVICE_H #include "config.h" -#include +#include #include #include +#include /** * The maximum number of PCM formats to accept during the initial RDPSND @@ -62,14 +63,7 @@ typedef struct guac_pcm_format { * Structure representing the current state of the Guacamole RDPSND plugin for * FreeRDP. */ -typedef struct guac_rdpsndPlugin { - - /** - * The FreeRDP parts of this plugin. This absolutely MUST be first. - * FreeRDP depends on accessing this structure as if it were an instance - * of rdpSvcPlugin. - */ - rdpSvcPlugin plugin; +typedef struct guac_rdpsnd { /** * The Guacamole client associated with the guac_audio_stream that this @@ -77,6 +71,38 @@ typedef struct guac_rdpsndPlugin { */ guac_client* client; + /** + * The definition of this virtual channel (RDPSND). + */ + CHANNEL_DEF channel_def; + + /** + * Functions and data specific to the FreeRDP side of the virtual channel + * and plugin. + */ + CHANNEL_ENTRY_POINTS_FREERDP_EX entry_points; + + /** + * Handle which identifies the client connection, typically referred to + * within the FreeRDP source as pInitHandle. This handle is provided to the + * channel entry point and the channel init event handler. The handle must + * eventually be used within the channel open event handler to obtain a + * handle to the channel itself. + */ + PVOID init_handle; + + /** + * Handle which identifies the channel itself, typically referred to within + * the FreeRDP source as OpenHandle. This handle is obtained through a call + * to entry_points.pVirtualChannelOpenEx() in response to receiving a + * CHANNEL_EVENT_CONNECTED event via the init event handler. + * + * Data is received in CHANNEL_EVENT_DATA_RECEIVED events via the open + * event handler, and data is written through calls to + * entry_points.pVirtualChannelWriteEx(). + */ + DWORD open_handle; + /** * The block number of the last SNDC_WAVE (WaveInfo) PDU received. */ @@ -118,29 +144,7 @@ typedef struct guac_rdpsndPlugin { */ int format_count; -} guac_rdpsndPlugin; - -/** - * Handler called when this plugin is loaded by FreeRDP. - */ -void guac_rdpsnd_process_connect(rdpSvcPlugin* plugin); - -/** - * Handler called when this plugin receives data along its designated channel. - */ -void guac_rdpsnd_process_receive(rdpSvcPlugin* plugin, - wStream* input_stream); - -/** - * Handler called when this plugin is being unloaded. - */ -void guac_rdpsnd_process_terminate(rdpSvcPlugin* plugin); - -/** - * Handler called when this plugin receives an event. For the sake of RDPSND, - * all events will be ignored and simply free'd. - */ -void guac_rdpsnd_process_event(rdpSvcPlugin* plugin, wMessage* event); +} guac_rdpsnd; #endif From 68710a6702db1a23d03478259c65d49a4a6324a3 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 21 Dec 2019 19:36:20 -0800 Subject: [PATCH 039/109] GUACAMOLE-249: Migrate loading of RDPDR support (guacdr plugin) to abstract function. --- src/protocols/rdp/Makefile.am | 2 ++ src/protocols/rdp/rdp.c | 12 ++-------- src/protocols/rdp/rdpdr.c | 43 +++++++++++++++++++++++++++++++++++ src/protocols/rdp/rdpdr.h | 40 ++++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 10 deletions(-) create mode 100644 src/protocols/rdp/rdpdr.c create mode 100644 src/protocols/rdp/rdpdr.h diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index a5eb77f2..97f36535 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -59,6 +59,7 @@ libguac_client_rdp_la_SOURCES = \ rdp_pointer.c \ rdp_settings.c \ rdp_stream.c \ + rdpdr.c \ rdpsnd.c \ resolution.c \ svc.c \ @@ -101,6 +102,7 @@ noinst_HEADERS = \ rdp_settings.h \ rdp_status.h \ rdp_stream.h \ + rdpdr.h \ rdpsnd.h \ resolution.h \ svc.h \ diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 17da6e6d..b42035ca 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -38,6 +38,7 @@ #include "rdp_glyph.h" #include "rdp_pointer.h" #include "rdp_stream.h" +#include "rdpdr.h" #include "rdpsnd.h" #include "svc.h" @@ -108,17 +109,8 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { if (settings->printing_enabled || settings->drive_enabled || settings->audio_enabled) { - - /* Load RDPDR plugin */ - if (guac_freerdp_channels_load_plugin(channels, instance->settings, - "guacdr", client)) - guac_client_log(client, GUAC_LOG_WARNING, - "Failed to load guacdr plugin. Drive redirection and " - "printing will not work. Sound MAY not work."); - - /* Load RDPSND plugin */ + guac_rdpdr_load_plugin(context); guac_rdpsnd_load_plugin(context); - } /* Load RAIL plugin if RemoteApp in use */ diff --git a/src/protocols/rdp/rdpdr.c b/src/protocols/rdp/rdpdr.c new file mode 100644 index 00000000..e39d393a --- /dev/null +++ b/src/protocols/rdp/rdpdr.c @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#include "config.h" +#include "channels.h" +#include "rdp.h" + +#include +#include + +void guac_rdpdr_load_plugin(rdpContext* context) { + + guac_client* client = ((rdp_freerdp_context*) context)->client; + + /* Load RDPDR plugin */ + if (guac_freerdp_channels_load_plugin(context->channels, context->settings, "guacdr", client)) { + guac_client_log(client, GUAC_LOG_WARNING, "Support for the RDPDR " + "channel (device redirection) could not be loaded. Drive " + "redirection and printing will not work. Sound MAY not work."); + return; + } + + guac_client_log(client, GUAC_LOG_DEBUG, "Support for RDPDR (device " + "redirection) registered. Awaiting channel connection."); + +} + diff --git a/src/protocols/rdp/rdpdr.h b/src/protocols/rdp/rdpdr.h new file mode 100644 index 00000000..0a18a58c --- /dev/null +++ b/src/protocols/rdp/rdpdr.h @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#ifndef GUAC_RDP_RDPDR_H +#define GUAC_RDP_RDPDR_H + +#include "config.h" + +/** + * Initializes device redirection support (file transfer, printing, etc.) for + * RDP and handling of the RDPDR channel. If failures occur, messages noting + * the specifics of those failures will be logged, and the RDP side of + * device redirection support will not be functional. + * + * This MUST be called within the PreConnect callback of the freerdp instance + * for RDPDR support to be loaded. + * + * @param rdpContext + * The rdpContext associated with the FreeRDP side of the RDP connection. + */ +void guac_rdpdr_load_plugin(rdpContext* context); + +#endif + From ee4d91ea986f2583ca03cc477c391f9f43c5e2ac Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 21 Dec 2019 19:36:35 -0800 Subject: [PATCH 040/109] GUACAMOLE-249: Migrate RDPDR support to FreeRDP 2.0.0 plugin API. --- src/protocols/rdp/Makefile.am | 60 +-- .../rdp/guac_rdpdr/rdpdr_fs_messages.c | 33 +- .../guac_rdpdr/rdpdr_fs_messages_dir_info.c | 17 +- .../guac_rdpdr/rdpdr_fs_messages_file_info.c | 33 +- .../guac_rdpdr/rdpdr_fs_messages_vol_info.c | 21 +- .../rdp/guac_rdpdr/rdpdr_fs_service.c | 3 +- .../rdp/guac_rdpdr/rdpdr_fs_service.h | 2 +- src/protocols/rdp/guac_rdpdr/rdpdr_messages.c | 41 +- src/protocols/rdp/guac_rdpdr/rdpdr_messages.h | 16 +- src/protocols/rdp/guac_rdpdr/rdpdr_printer.c | 15 +- src/protocols/rdp/guac_rdpdr/rdpdr_printer.h | 2 +- src/protocols/rdp/guac_rdpdr/rdpdr_service.c | 360 ++++++++++++++---- src/protocols/rdp/guac_rdpdr/rdpdr_service.h | 70 ++-- 13 files changed, 463 insertions(+), 210 deletions(-) diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index 97f36535..aacfda6a 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -132,9 +132,9 @@ libguac_client_rdp_la_LIBADD = \ freerdp_LTLIBRARIES = \ libguacai-client.la \ + libguacdr-client.la \ libguacsnd-client.la \ libguacsvc-client.la -# libguacdr-client.la freerdpdir = ${libdir}/freerdp2 @@ -142,35 +142,35 @@ freerdpdir = ${libdir}/freerdp2 # RDPDR # -#libguacdr_client_la_SOURCES = \ -# guac_rdpdr/rdpdr_fs_messages.c \ -# guac_rdpdr/rdpdr_fs_messages_dir_info.c \ -# guac_rdpdr/rdpdr_fs_messages_file_info.c \ -# guac_rdpdr/rdpdr_fs_messages_vol_info.c \ -# guac_rdpdr/rdpdr_fs_service.c \ -# guac_rdpdr/rdpdr_messages.c \ -# guac_rdpdr/rdpdr_printer.c \ -# guac_rdpdr/rdpdr_service.c \ -# rdp_fs.c \ -# rdp_print_job.c \ -# rdp_stream.c \ -# unicode.c -# -#libguacdr_client_la_CFLAGS = \ -# -Werror -Wall -Iinclude \ -# @COMMON_INCLUDE@ \ -# @COMMON_SSH_INCLUDE@ \ -# @LIBGUAC_INCLUDE@ \ -# @RDP_CFLAGS@ -# -#libguacdr_client_la_LDFLAGS = \ -# -module -avoid-version -shared \ -# @PTHREAD_LIBS@ \ -# @RDP_LIBS@ -# -#libguacdr_client_la_LIBADD = \ -# @COMMON_LTLIB@ \ -# @LIBGUAC_LTLIB@ +libguacdr_client_la_SOURCES = \ + guac_rdpdr/rdpdr_fs_messages.c \ + guac_rdpdr/rdpdr_fs_messages_dir_info.c \ + guac_rdpdr/rdpdr_fs_messages_file_info.c \ + guac_rdpdr/rdpdr_fs_messages_vol_info.c \ + guac_rdpdr/rdpdr_fs_service.c \ + guac_rdpdr/rdpdr_messages.c \ + guac_rdpdr/rdpdr_printer.c \ + guac_rdpdr/rdpdr_service.c \ + rdp_fs.c \ + rdp_print_job.c \ + rdp_stream.c \ + unicode.c + +libguacdr_client_la_CFLAGS = \ + -Werror -Wall -Iinclude \ + @COMMON_INCLUDE@ \ + @COMMON_SSH_INCLUDE@ \ + @LIBGUAC_INCLUDE@ \ + @RDP_CFLAGS@ + +libguacdr_client_la_LDFLAGS = \ + -module -avoid-version -shared \ + @PTHREAD_LIBS@ \ + @RDP_LIBS@ + +libguacdr_client_la_LIBADD = \ + @COMMON_LTLIB@ \ + @LIBGUAC_LTLIB@ # # Audio Input diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.c b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.c index bad3f46e..1336e6f9 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.c @@ -29,7 +29,6 @@ #include "rdp_status.h" #include "unicode.h" -#include #include #include #include @@ -110,7 +109,9 @@ void guac_rdpdr_fs_process_create(guac_rdpdr_device* device, } - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } @@ -158,7 +159,9 @@ void guac_rdpdr_fs_process_read(guac_rdpdr_device* device, Stream_Write(output_stream, buffer, bytes_read); /* ReadData */ } - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); free(buffer); } @@ -201,7 +204,9 @@ void guac_rdpdr_fs_process_write(guac_rdpdr_device* device, Stream_Write_UINT8(output_stream, 0); /* Padding */ } - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } @@ -234,7 +239,9 @@ void guac_rdpdr_fs_process_close(guac_rdpdr_device* device, STATUS_SUCCESS, 4); Stream_Write(output_stream, "\0\0\0\0", 4); /* Padding */ - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } @@ -322,7 +329,9 @@ void guac_rdpdr_fs_process_set_volume_info(guac_rdpdr_device* device, "%s: [file_id=%i] Set volume info not supported", __func__, file_id); - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } @@ -385,7 +394,9 @@ void guac_rdpdr_fs_process_device_control(guac_rdpdr_device* device, /* No content for now */ Stream_Write_UINT32(output_stream, 0); - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } @@ -501,7 +512,9 @@ void guac_rdpdr_fs_process_query_directory(guac_rdpdr_device* device, wStream* i Stream_Write_UINT32(output_stream, 0); /* Length */ Stream_Write_UINT8(output_stream, 0); /* Padding */ - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } @@ -517,7 +530,9 @@ void guac_rdpdr_fs_process_lock_control(guac_rdpdr_device* device, wStream* inpu Stream_Zero(output_stream, 5); /* Padding */ - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_dir_info.c b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_dir_info.c index 3ab31e5f..303e7af7 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_dir_info.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_dir_info.c @@ -24,7 +24,6 @@ #include "rdp_status.h" #include "unicode.h" -#include #include #include @@ -72,7 +71,9 @@ void guac_rdpdr_fs_process_query_directory_info(guac_rdpdr_device* device, Stream_Write(output_stream, utf16_entry_name, utf16_length); /* FileName */ Stream_Write(output_stream, "\0\0", 2); - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } @@ -119,7 +120,9 @@ void guac_rdpdr_fs_process_query_full_directory_info(guac_rdpdr_device* device, Stream_Write(output_stream, utf16_entry_name, utf16_length); /* FileName */ Stream_Write(output_stream, "\0\0", 2); - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } @@ -170,7 +173,9 @@ void guac_rdpdr_fs_process_query_both_directory_info(guac_rdpdr_device* device, Stream_Write(output_stream, utf16_entry_name, utf16_length); /* FileName */ Stream_Write(output_stream, "\0\0", 2); - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } @@ -208,7 +213,9 @@ void guac_rdpdr_fs_process_query_names_info(guac_rdpdr_device* device, Stream_Write(output_stream, utf16_entry_name, utf16_length); /* FileName */ Stream_Write(output_stream, "\0\0", 2); - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_file_info.c b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_file_info.c index e65ef9c1..c69046cb 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_file_info.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_file_info.c @@ -24,7 +24,6 @@ #include "rdp_status.h" #include "unicode.h" -#include #include #include @@ -59,7 +58,9 @@ void guac_rdpdr_fs_process_query_basic_info(guac_rdpdr_device* device, wStream* /* Reserved field must not be sent */ - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } @@ -94,7 +95,9 @@ void guac_rdpdr_fs_process_query_standard_info(guac_rdpdr_device* device, wStrea /* Reserved field must not be sent */ - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } @@ -122,7 +125,9 @@ void guac_rdpdr_fs_process_query_attribute_tag_info(guac_rdpdr_device* device, /* Reserved field must not be sent */ - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } @@ -179,7 +184,9 @@ void guac_rdpdr_fs_process_set_rename_info(guac_rdpdr_device* device, } Stream_Write_UINT32(output_stream, length); - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } @@ -207,7 +214,9 @@ void guac_rdpdr_fs_process_set_allocation_info(guac_rdpdr_device* device, completion_id, STATUS_SUCCESS, 4); Stream_Write_UINT32(output_stream, length); - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } @@ -231,7 +240,9 @@ void guac_rdpdr_fs_process_set_disposition_info(guac_rdpdr_device* device, Stream_Write_UINT32(output_stream, length); - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } @@ -259,7 +270,9 @@ void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdpdr_device* device, completion_id, STATUS_SUCCESS, 4); Stream_Write_UINT32(output_stream, length); - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } @@ -276,7 +289,9 @@ void guac_rdpdr_fs_process_set_basic_info(guac_rdpdr_device* device, "%s: [file_id=%i] IGNORED", __func__, file_id); - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_vol_info.c b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_vol_info.c index 27defb0e..1cc051f0 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_vol_info.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_vol_info.c @@ -24,7 +24,6 @@ #include "rdp_fs.h" #include "rdp_status.h" -#include #include #include #include @@ -47,7 +46,9 @@ void guac_rdpdr_fs_process_query_volume_info(guac_rdpdr_device* device, /* Reserved field must not be sent */ Stream_Write(output_stream, GUAC_FILESYSTEM_LABEL, GUAC_FILESYSTEM_LABEL_LENGTH); - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } @@ -70,7 +71,9 @@ void guac_rdpdr_fs_process_query_size_info(guac_rdpdr_device* device, wStream* i Stream_Write_UINT32(output_stream, 1); /* SectorsPerAllocationUnit */ Stream_Write_UINT32(output_stream, info.block_size); /* BytesPerSector */ - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } @@ -88,7 +91,9 @@ void guac_rdpdr_fs_process_query_device_info(guac_rdpdr_device* device, wStream* Stream_Write_UINT32(output_stream, FILE_DEVICE_DISK); /* DeviceType */ Stream_Write_UINT32(output_stream, 0); /* Characteristics */ - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } @@ -113,7 +118,9 @@ void guac_rdpdr_fs_process_query_attribute_info(guac_rdpdr_device* device, wStre Stream_Write_UINT32(output_stream, name_len); Stream_Write(output_stream, device->device_name, name_len); - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } @@ -137,7 +144,9 @@ void guac_rdpdr_fs_process_query_full_size_info(guac_rdpdr_device* device, wStre Stream_Write_UINT32(output_stream, 1); /* SectorsPerAllocationUnit */ Stream_Write_UINT32(output_stream, info.block_size); /* BytesPerSector */ - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_service.c b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_service.c index 63425ba6..187bf9c4 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_service.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_service.c @@ -25,7 +25,6 @@ #include "rdpdr_messages.h" #include "rdpdr_service.h" -#include #include #include #include @@ -114,7 +113,7 @@ static void guac_rdpdr_device_fs_free_handler(guac_rdpdr_device* device) { } -void guac_rdpdr_register_fs(guac_rdpdrPlugin* rdpdr, char* drive_name) { +void guac_rdpdr_register_fs(guac_rdpdr* rdpdr, char* drive_name) { guac_client* client = rdpdr->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_service.h b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_service.h index f990806b..af44ac8b 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_service.h +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_service.h @@ -48,7 +48,7 @@ * @param drive_name * The name of the redirected drive to display in the RDP connection. */ -void guac_rdpdr_register_fs(guac_rdpdrPlugin* rdpdr, char* drive_name); +void guac_rdpdr_register_fs(guac_rdpdr* rdpdr, char* drive_name); #endif diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.c b/src/protocols/rdp/guac_rdpdr/rdpdr_messages.c index 507b4d7c..d300ccaf 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_messages.c @@ -24,7 +24,6 @@ #include "rdpdr_service.h" #include "unicode.h" -#include #include #include #include @@ -32,7 +31,7 @@ #include #include -static void guac_rdpdr_send_client_announce_reply(guac_rdpdrPlugin* rdpdr, +static void guac_rdpdr_send_client_announce_reply(guac_rdpdr* rdpdr, unsigned int major, unsigned int minor, unsigned int client_id) { wStream* output_stream = Stream_New(NULL, 12); @@ -46,11 +45,13 @@ static void guac_rdpdr_send_client_announce_reply(guac_rdpdrPlugin* rdpdr, Stream_Write_UINT16(output_stream, minor); Stream_Write_UINT32(output_stream, client_id); - svc_plugin_send((rdpSvcPlugin*) rdpdr, output_stream); + rdpdr->entry_points.pVirtualChannelWriteEx(rdpdr->init_handle, + rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } -static void guac_rdpdr_send_client_name_request(guac_rdpdrPlugin* rdpdr, const char* name) { +static void guac_rdpdr_send_client_name_request(guac_rdpdr* rdpdr, const char* name) { int name_bytes = strlen(name) + 1; wStream* output_stream = Stream_New(NULL, 16 + name_bytes); @@ -65,11 +66,13 @@ static void guac_rdpdr_send_client_name_request(guac_rdpdrPlugin* rdpdr, const c Stream_Write_UINT32(output_stream, name_bytes); Stream_Write(output_stream, name, name_bytes); - svc_plugin_send((rdpSvcPlugin*) rdpdr, output_stream); + rdpdr->entry_points.pVirtualChannelWriteEx(rdpdr->init_handle, + rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } -static void guac_rdpdr_send_client_capability(guac_rdpdrPlugin* rdpdr) { +static void guac_rdpdr_send_client_capability(guac_rdpdr* rdpdr) { wStream* output_stream = Stream_New(NULL, 256); guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Sending capabilities..."); @@ -112,12 +115,14 @@ static void guac_rdpdr_send_client_capability(guac_rdpdrPlugin* rdpdr) { Stream_Write_UINT16(output_stream, 8); Stream_Write_UINT32(output_stream, DRIVE_CAPABILITY_VERSION_02); - svc_plugin_send((rdpSvcPlugin*) rdpdr, output_stream); + rdpdr->entry_points.pVirtualChannelWriteEx(rdpdr->init_handle, + rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Capabilities sent."); } -static void guac_rdpdr_send_client_device_list_announce_request(guac_rdpdrPlugin* rdpdr) { +static void guac_rdpdr_send_client_device_list_announce_request(guac_rdpdr* rdpdr) { /* Calculate number of bytes needed for the stream */ int streamBytes = 16; @@ -144,12 +149,14 @@ static void guac_rdpdr_send_client_device_list_announce_request(guac_rdpdrPlugin } - svc_plugin_send((rdpSvcPlugin*) rdpdr, output_stream); + rdpdr->entry_points.pVirtualChannelWriteEx(rdpdr->init_handle, + rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); guac_client_log(rdpdr->client, GUAC_LOG_INFO, "All supported devices sent."); } -void guac_rdpdr_process_server_announce(guac_rdpdrPlugin* rdpdr, +void guac_rdpdr_process_server_announce(guac_rdpdr* rdpdr, wStream* input_stream) { unsigned int major, minor, client_id; @@ -172,11 +179,11 @@ void guac_rdpdr_process_server_announce(guac_rdpdrPlugin* rdpdr, } -void guac_rdpdr_process_clientid_confirm(guac_rdpdrPlugin* rdpdr, wStream* input_stream) { +void guac_rdpdr_process_clientid_confirm(guac_rdpdr* rdpdr, wStream* input_stream) { guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Client ID confirmed"); } -void guac_rdpdr_process_device_reply(guac_rdpdrPlugin* rdpdr, wStream* input_stream) { +void guac_rdpdr_process_device_reply(guac_rdpdr* rdpdr, wStream* input_stream) { unsigned int device_id, ntstatus; int severity, c, n, facility, code; @@ -210,7 +217,7 @@ void guac_rdpdr_process_device_reply(guac_rdpdrPlugin* rdpdr, wStream* input_str } -void guac_rdpdr_process_device_iorequest(guac_rdpdrPlugin* rdpdr, wStream* input_stream) { +void guac_rdpdr_process_device_iorequest(guac_rdpdr* rdpdr, wStream* input_stream) { int device_id, file_id, completion_id, major_func, minor_func; @@ -236,7 +243,7 @@ void guac_rdpdr_process_device_iorequest(guac_rdpdrPlugin* rdpdr, wStream* input } -void guac_rdpdr_process_server_capability(guac_rdpdrPlugin* rdpdr, wStream* input_stream) { +void guac_rdpdr_process_server_capability(guac_rdpdr* rdpdr, wStream* input_stream) { int count; int i; @@ -265,17 +272,17 @@ void guac_rdpdr_process_server_capability(guac_rdpdrPlugin* rdpdr, wStream* inpu } -void guac_rdpdr_process_user_loggedon(guac_rdpdrPlugin* rdpdr, wStream* input_stream) { +void guac_rdpdr_process_user_loggedon(guac_rdpdr* rdpdr, wStream* input_stream) { guac_client_log(rdpdr->client, GUAC_LOG_INFO, "User logged on"); guac_rdpdr_send_client_device_list_announce_request(rdpdr); } -void guac_rdpdr_process_prn_cache_data(guac_rdpdrPlugin* rdpdr, wStream* input_stream) { +void guac_rdpdr_process_prn_cache_data(guac_rdpdr* rdpdr, wStream* input_stream) { guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Ignoring printer cached configuration data"); } -void guac_rdpdr_process_prn_using_xps(guac_rdpdrPlugin* rdpdr, wStream* input_stream) { +void guac_rdpdr_process_prn_using_xps(guac_rdpdr* rdpdr, wStream* input_stream) { guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Printer unexpectedly switched to XPS mode"); } diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h b/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h index b719ab0c..451554e4 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h @@ -204,14 +204,14 @@ * Message handlers. */ -void guac_rdpdr_process_server_announce(guac_rdpdrPlugin* rdpdr, wStream* input_stream); -void guac_rdpdr_process_clientid_confirm(guac_rdpdrPlugin* rdpdr, wStream* input_stream); -void guac_rdpdr_process_device_reply(guac_rdpdrPlugin* rdpdr, wStream* input_stream); -void guac_rdpdr_process_device_iorequest(guac_rdpdrPlugin* rdpdr, wStream* input_stream); -void guac_rdpdr_process_server_capability(guac_rdpdrPlugin* rdpdr, wStream* input_stream); -void guac_rdpdr_process_user_loggedon(guac_rdpdrPlugin* rdpdr, wStream* input_stream); -void guac_rdpdr_process_prn_cache_data(guac_rdpdrPlugin* rdpdr, wStream* input_stream); -void guac_rdpdr_process_prn_using_xps(guac_rdpdrPlugin* rdpdr, wStream* input_stream); +void guac_rdpdr_process_server_announce(guac_rdpdr* rdpdr, wStream* input_stream); +void guac_rdpdr_process_clientid_confirm(guac_rdpdr* rdpdr, wStream* input_stream); +void guac_rdpdr_process_device_reply(guac_rdpdr* rdpdr, wStream* input_stream); +void guac_rdpdr_process_device_iorequest(guac_rdpdr* rdpdr, wStream* input_stream); +void guac_rdpdr_process_server_capability(guac_rdpdr* rdpdr, wStream* input_stream); +void guac_rdpdr_process_user_loggedon(guac_rdpdr* rdpdr, wStream* input_stream); +void guac_rdpdr_process_prn_cache_data(guac_rdpdr* rdpdr, wStream* input_stream); +void guac_rdpdr_process_prn_using_xps(guac_rdpdr* rdpdr, wStream* input_stream); #endif diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_printer.c b/src/protocols/rdp/guac_rdpdr/rdpdr_printer.c index e8c2a5da..98a3eccb 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_printer.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_printer.c @@ -27,7 +27,6 @@ #include "rdp_status.h" #include "unicode.h" -#include #include #include #include @@ -61,7 +60,9 @@ void guac_rdpdr_process_print_job_create(guac_rdpdr_device* device, completion_id, STATUS_SUCCESS, 4); Stream_Write_UINT32(output_stream, 0); /* fileId */ - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } @@ -100,7 +101,9 @@ void guac_rdpdr_process_print_job_write(guac_rdpdr_device* device, Stream_Write_UINT32(output_stream, length); Stream_Write_UINT8(output_stream, 0); /* Padding */ - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); } @@ -121,7 +124,9 @@ void guac_rdpdr_process_print_job_close(guac_rdpdr_device* device, completion_id, STATUS_SUCCESS, 4); Stream_Write_UINT32(output_stream, 0); /* Padding */ - svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); + device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, + device->rdpdr->open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); /* Log end of print job */ guac_client_log(client, GUAC_LOG_INFO, "Print job closed"); @@ -164,7 +169,7 @@ static void guac_rdpdr_device_printer_free_handler(guac_rdpdr_device* device) { } -void guac_rdpdr_register_printer(guac_rdpdrPlugin* rdpdr, char* printer_name) { +void guac_rdpdr_register_printer(guac_rdpdr* rdpdr, char* printer_name) { int id = rdpdr->devices_registered++; diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_printer.h b/src/protocols/rdp/guac_rdpdr/rdpdr_printer.h index c6abcde5..210d512c 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_printer.h +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_printer.h @@ -38,7 +38,7 @@ * The name of the printer that will be registered with the RDP * connection and passed through to the server. */ -void guac_rdpdr_register_printer(guac_rdpdrPlugin* rdpdr, char* printer_name); +void guac_rdpdr_register_printer(guac_rdpdr* rdpdr, char* printer_name); #endif diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_service.c b/src/protocols/rdp/guac_rdpdr/rdpdr_service.c index 40a1e51e..d20f7d83 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_service.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_service.c @@ -32,7 +32,6 @@ #include #include -#include #include #include #include @@ -40,92 +39,19 @@ #include /** - * Entry point for RDPDR virtual channel. + * Processes data received along the RDPDR channel via a + * CHANNEL_EVENT_DATA_RECEIVED event, forwarding the data along an established, + * outbound pipe stream to the Guacamole client. + * + * @param rdpdr + * The guac_rdpdr structure representing the RDPDR channel. + * + * @param input_stream + * The data that was received. */ -int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) { - - /* Allocate plugin */ - guac_rdpdrPlugin* rdpdr = - (guac_rdpdrPlugin*) calloc(1, sizeof(guac_rdpdrPlugin)); - - /* Init channel def */ - strcpy(rdpdr->plugin.channel_def.name, "rdpdr"); - rdpdr->plugin.channel_def.options = - CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP | CHANNEL_OPTION_COMPRESS_RDP; - - /* Set callbacks */ - rdpdr->plugin.connect_callback = guac_rdpdr_process_connect; - rdpdr->plugin.receive_callback = guac_rdpdr_process_receive; - rdpdr->plugin.event_callback = guac_rdpdr_process_event; - rdpdr->plugin.terminate_callback = guac_rdpdr_process_terminate; - - /* Finish init */ - svc_plugin_init((rdpSvcPlugin*) rdpdr, pEntryPoints); - return 1; - -} - -/* - * Service Handlers - */ - -void guac_rdpdr_process_connect(rdpSvcPlugin* plugin) { - - /* Get RDPDR plugin */ - guac_rdpdrPlugin* rdpdr = (guac_rdpdrPlugin*) plugin; - - /* Get client from plugin parameters */ - guac_client* client = (guac_client*) - plugin->channel_entry_points.pExtendedData; - - /* NULL out pExtendedData so we don't lose our guac_client due to an - * automatic free() within libfreerdp */ - plugin->channel_entry_points.pExtendedData = NULL; - - /* Get data from client */ - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - - /* Init plugin */ - rdpdr->client = client; - rdpdr->devices_registered = 0; - - /* Register printer if enabled */ - if (rdp_client->settings->printing_enabled) - guac_rdpdr_register_printer(rdpdr, rdp_client->settings->printer_name); - - /* Register drive if enabled */ - if (rdp_client->settings->drive_enabled) - guac_rdpdr_register_fs(rdpdr, rdp_client->settings->drive_name); - - /* Log that printing, etc. has been loaded */ - guac_client_log(client, GUAC_LOG_INFO, "guacdr connected."); - -} - -void guac_rdpdr_process_terminate(rdpSvcPlugin* plugin) { - - guac_rdpdrPlugin* rdpdr = (guac_rdpdrPlugin*) plugin; - int i; - - for (i=0; idevices_registered; i++) { - guac_rdpdr_device* device = &(rdpdr->devices[i]); - guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Unloading device %i (%s)", - device->device_id, device->device_name); - device->free_handler(device); - } - - free(plugin); -} - -void guac_rdpdr_process_event(rdpSvcPlugin* plugin, wMessage* event) { - freerdp_event_free(event); -} - -void guac_rdpdr_process_receive(rdpSvcPlugin* plugin, +static void guac_rdpdr_process_receive(guac_rdpdr* rdpdr, wStream* input_stream) { - guac_rdpdrPlugin* rdpdr = (guac_rdpdrPlugin*) plugin; - int component; int packet_id; @@ -306,3 +232,269 @@ void guac_rdpdr_start_download(guac_rdpdr_device* device, char* path) { } +/** + * Event handler for events which deal with data transmitted over the RDPDR + * channel. This specific implementation of the event handler currently + * handles only the CHANNEL_EVENT_DATA_RECEIVED event, delegating actual + * handling of that event to guac_rdpdr_process_receive(). + * + * The FreeRDP requirements for this function follow those of the + * VirtualChannelOpenEventEx callback defined within Microsoft's RDP API: + * + * https://docs.microsoft.com/en-us/previous-versions/windows/embedded/aa514754%28v%3dmsdn.10%29 + * + * @param user_param + * The pointer to arbitrary data originally passed via the first parameter + * of the pVirtualChannelInitEx() function call when the associated channel + * was initialized. The pVirtualChannelInitEx() function is exposed within + * the channel entry points structure. + * + * @param open_handle + * The handle which identifies the channel itself, typically referred to + * within the FreeRDP source as OpenHandle. + * + * @param event + * An integer representing the event that should be handled. This will be + * either CHANNEL_EVENT_DATA_RECEIVED, CHANNEL_EVENT_WRITE_CANCELLED, or + * CHANNEL_EVENT_WRITE_COMPLETE. + * + * @param data + * The data received, for CHANNEL_EVENT_DATA_RECEIVED events, and the value + * passed as user data to pVirtualChannelWriteEx() for + * CHANNEL_EVENT_WRITE_* events (note that user data for + * pVirtualChannelWriteEx() as implemented by FreeRDP MUST either be NULL + * or a wStream containing the data written). + * + * @param data_length + * The number of bytes of event-specific data. + * + * @param total_length + * The total number of bytes written to the RDP server in a single write + * operation. + * + * NOTE: The meaning of total_length is unclear. The above description was + * written mainly through referencing the documentation in MSDN. Real-world + * use will need to be consulted, likely within the FreeRDP source, before + * this value can be reliably used. The current implementation of this + * handler ignores this parameter. + * + * @param data_flags + * The result of a bitwise OR of the CHANNEL_FLAG_* flags which apply to + * the data received. This value is relevant only to + * CHANNEL_EVENT_DATA_RECEIVED events. Valid flags are CHANNEL_FLAG_FIRST, + * CHANNEL_FLAG_LAST, and CHANNEL_FLAG_ONLY. The flag CHANNEL_FLAG_MIDDLE + * is not itself a flag, but the absence of both CHANNEL_FLAG_FIRST and + * CHANNEL_FLAG_LAST. + */ +static VOID guac_rdpdr_handle_open_event(LPVOID user_param, + DWORD open_handle, UINT event, LPVOID data, UINT32 data_length, + UINT32 total_length, UINT32 data_flags) { + + /* Ignore all events except for received data */ + if (event != CHANNEL_EVENT_DATA_RECEIVED) + return; + + guac_rdpdr* rdpdr = (guac_rdpdr*) user_param; + + /* Validate relevant handle matches that of the RDPDR channel */ + if (open_handle != rdpdr->open_handle) { + guac_client_log(rdpdr->client, GUAC_LOG_WARNING, "%i bytes of data " + "received from within the remote desktop session for the " + "RDPDR channel are being dropped because the relevant open " + "handle (0x%X) does not match the open handle of RDPDR " + "(0x%X).", data_length, rdpdr->channel_def.name, open_handle, + rdpdr->open_handle); + return; + } + + wStream* input_stream = Stream_New(data, data_length); + guac_rdpdr_process_receive(rdpdr, input_stream); + Stream_Free(input_stream, FALSE); + +} + +/** + * Processes a CHANNEL_EVENT_CONNECTED event, completing the + * connection/initialization process of the RDPDR channel. + * + * @param rdpdr + * The guac_rdpdr structure representing the RDPDR channel. + */ +static void guac_rdpdr_process_connect(guac_rdpdr* rdpdr) { + + /* Get data from client */ + guac_client* client = rdpdr->client; + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + + /* Open FreeRDP side of connected channel */ + UINT32 open_status = + rdpdr->entry_points.pVirtualChannelOpenEx(rdpdr->init_handle, + &rdpdr->open_handle, rdpdr->channel_def.name, + guac_rdpdr_handle_open_event); + + /* Warn if the channel cannot be opened after all */ + if (open_status != CHANNEL_RC_OK) { + guac_client_log(client, GUAC_LOG_WARNING, "RDPDR channel could not be " + "opened: %s (error %i)", WTSErrorToString(open_status), + open_status); + return; + } + + /* Register printer if enabled */ + if (rdp_client->settings->printing_enabled) + guac_rdpdr_register_printer(rdpdr, rdp_client->settings->printer_name); + + /* Register drive if enabled */ + if (rdp_client->settings->drive_enabled) + guac_rdpdr_register_fs(rdpdr, rdp_client->settings->drive_name); + + /* Log that printing, etc. has been loaded */ + guac_client_log(client, GUAC_LOG_INFO, "RDPDR channel connected."); + +} + +/** + * Processes a CHANNEL_EVENT_TERMINATED event, freeing all resources associated + * with the RDPDR channel. + * + * @param rdpdr + * The guac_rdpdr structure representing the RDPDR channel. + */ +static void guac_rdpdr_process_terminate(guac_rdpdr* rdpdr) { + + int i; + + for (i=0; idevices_registered; i++) { + guac_rdpdr_device* device = &(rdpdr->devices[i]); + guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Unloading device %i (%s)", + device->device_id, device->device_name); + device->free_handler(device); + } + + guac_client_log(rdpdr->client, GUAC_LOG_INFO, "RDPDR channel disconnected."); + free(rdpdr); + +} + +/** + * Event handler for events which deal with the overall lifecycle of the RDPDR + * channel. This specific implementation of the event handler currently + * handles only CHANNEL_EVENT_CONNECTED and CHANNEL_EVENT_TERMINATED events, + * delegating actual handling of those events to guac_rdpdr_process_connect() + * and guac_rdpdr_process_terminate() respectively. + * + * The FreeRDP requirements for this function follow those of the + * VirtualChannelInitEventEx callback defined within Microsoft's RDP API: + * + * https://docs.microsoft.com/en-us/previous-versions/windows/embedded/aa514727%28v%3dmsdn.10%29 + * + * @param user_param + * The pointer to arbitrary data originally passed via the first parameter + * of the pVirtualChannelInitEx() function call when the associated channel + * was initialized. The pVirtualChannelInitEx() function is exposed within + * the channel entry points structure. + * + * @param init_handle + * The handle which identifies the client connection, typically referred to + * within the FreeRDP source as pInitHandle. + * + * @param event + * An integer representing the event that should be handled. This will be + * either CHANNEL_EVENT_CONNECTED, CHANNEL_EVENT_DISCONNECTED, + * CHANNEL_EVENT_INITIALIZED, CHANNEL_EVENT_TERMINATED, or + * CHANNEL_EVENT_V1_CONNECTED. + * + * @param data + * NULL in all cases except the CHANNEL_EVENT_CONNECTED event, in which + * case this is a null-terminated string containing the name of the server. + * + * @param data_length + * The number of bytes of data, if any. + */ +static VOID guac_rdpdr_handle_init_event(LPVOID user_param, + LPVOID init_handle, UINT event, LPVOID data, UINT data_length) { + + guac_rdpdr* rdpdr = (guac_rdpdr*) user_param; + + /* Validate relevant handle matches that of the RDPDR channel */ + if (init_handle != rdpdr->init_handle) { + guac_client_log(rdpdr->client, GUAC_LOG_WARNING, "An init event " + "(#%i) for the RDPDR channel has been dropped because the " + "relevant init handle (0x%X) does not match the init handle " + "of the RDPDR channel (0x%X).", event, init_handle, + rdpdr->init_handle); + return; + } + + switch (event) { + + /* The RDPDR channel has been connected */ + case CHANNEL_EVENT_CONNECTED: + guac_rdpdr_process_connect(rdpdr); + break; + + /* The RDPDR channel has disconnected and now must be cleaned up */ + case CHANNEL_EVENT_TERMINATED: + guac_rdpdr_process_terminate(rdpdr); + break; + + } + +} + +/** + * Entry point for FreeRDP plugins. This function is automatically invoked when + * the plugin is loaded. + * + * @param entry_points + * Functions and data specific to the FreeRDP side of the virtual channel + * and plugin. This structure must be copied within implementation-specific + * storage such that the functions it references can be invoked when + * needed. + * + * @param init_handle + * The handle which identifies the client connection, typically referred to + * within the FreeRDP source as pInitHandle. This handle is also provided + * to the channel init event handler. The handle must eventually be used + * within the channel open event handler to obtain a handle to the channel + * itself. + * + * @return + * TRUE if the plugin has initialized successfully, FALSE otherwise. + */ +BOOL VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS entry_points, + PVOID init_handle) { + + CHANNEL_ENTRY_POINTS_FREERDP_EX* entry_points_ex = + (CHANNEL_ENTRY_POINTS_FREERDP_EX*) entry_points; + + /* Allocate plugin */ + guac_rdpdr* rdpdr = (guac_rdpdr*) calloc(1, sizeof(guac_rdpdr)); + + /* Init channel def */ + strcpy(rdpdr->channel_def.name, "rdpdr"); + rdpdr->channel_def.options = CHANNEL_OPTION_INITIALIZED + | CHANNEL_OPTION_ENCRYPT_RDP + | CHANNEL_OPTION_COMPRESS_RDP; + + /* Maintain reference to associated guac_client */ + rdpdr->client = (guac_client*) entry_points_ex->pExtendedData; + + /* No devices are connected initially */ + rdpdr->devices_registered = 0; + + /* Copy FreeRDP data into RDPSND structure for future reference */ + rdpdr->entry_points = *entry_points_ex; + rdpdr->init_handle = init_handle; + + /* Complete initialization */ + if (rdpdr->entry_points.pVirtualChannelInitEx(rdpdr, rdpdr, init_handle, + &rdpdr->channel_def, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, + guac_rdpdr_handle_init_event) != CHANNEL_RC_OK) { + return FALSE; + } + + return TRUE; + +} + diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_service.h b/src/protocols/rdp/guac_rdpdr/rdpdr_service.h index 064ce32d..1fa3b126 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_service.h +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_service.h @@ -23,16 +23,17 @@ #include "config.h" -#include +#include #include #include +#include /** * The maximum number of bytes to allow for a device read. */ #define GUAC_RDP_MAX_READ_BUFFER 4194304 -typedef struct guac_rdpdrPlugin guac_rdpdrPlugin; +typedef struct guac_rdpdr guac_rdpdr; typedef struct guac_rdpdr_device guac_rdpdr_device; /** @@ -61,7 +62,7 @@ struct guac_rdpdr_device { /** * The RDPDR plugin owning this device. */ - guac_rdpdrPlugin* rdpdr; + guac_rdpdr* rdpdr; /** * The ID assigned to this device by the RDPDR plugin. @@ -115,20 +116,45 @@ struct guac_rdpdr_device { * Structure representing the current state of the Guacamole RDPDR plugin for * FreeRDP. */ -struct guac_rdpdrPlugin { - - /** - * The FreeRDP parts of this plugin. This absolutely MUST be first. - * FreeRDP depends on accessing this structure as if it were an instance - * of rdpSvcPlugin. - */ - rdpSvcPlugin plugin; +struct guac_rdpdr { /** * Reference to the client owning this instance of the RDPDR plugin. */ guac_client* client; + /** + * The definition of this virtual channel (RDPDR). + */ + CHANNEL_DEF channel_def; + + /** + * Functions and data specific to the FreeRDP side of the virtual channel + * and plugin. + */ + CHANNEL_ENTRY_POINTS_FREERDP_EX entry_points; + + /** + * Handle which identifies the client connection, typically referred to + * within the FreeRDP source as pInitHandle. This handle is provided to the + * channel entry point and the channel init event handler. The handle must + * eventually be used within the channel open event handler to obtain a + * handle to the channel itself. + */ + PVOID init_handle; + + /** + * Handle which identifies the channel itself, typically referred to within + * the FreeRDP source as OpenHandle. This handle is obtained through a call + * to entry_points.pVirtualChannelOpenEx() in response to receiving a + * CHANNEL_EVENT_CONNECTED event via the init event handler. + * + * Data is received in CHANNEL_EVENT_DATA_RECEIVED events via the open + * event handler, and data is written through calls to + * entry_points.pVirtualChannelWriteEx(). + */ + DWORD open_handle; + /** * The number of devices registered within the devices array. */ @@ -141,28 +167,6 @@ struct guac_rdpdrPlugin { }; -/** - * Handler called when this plugin is loaded by FreeRDP. - */ -void guac_rdpdr_process_connect(rdpSvcPlugin* plugin); - -/** - * Handler called when this plugin receives data along its designated channel. - */ -void guac_rdpdr_process_receive(rdpSvcPlugin* plugin, - wStream* input_stream); - -/** - * Handler called when this plugin is being unloaded. - */ -void guac_rdpdr_process_terminate(rdpSvcPlugin* plugin); - -/** - * Handler called when this plugin receives an event. For the sake of RDPDR, - * all events will be ignored and simply free'd. - */ -void guac_rdpdr_process_event(rdpSvcPlugin* plugin, wMessage* event); - /** * Creates a new stream which contains the common DR_DEVICE_IOCOMPLETION header * used for virtually all responses. From a7352b14294508464778168d110b06afd4e4c70c Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 21 Dec 2019 20:02:17 -0800 Subject: [PATCH 041/109] GUACAMOLE-249: Remove lock around usage of FreeRDP (new library appears threadsafe). --- src/protocols/rdp/client.c | 3 --- src/protocols/rdp/input.c | 10 +--------- src/protocols/rdp/keyboard.c | 24 +++--------------------- src/protocols/rdp/rdp.c | 13 ------------- src/protocols/rdp/rdp.h | 7 ------- 5 files changed, 4 insertions(+), 53 deletions(-) diff --git a/src/protocols/rdp/client.c b/src/protocols/rdp/client.c index 0c0b4bb8..4e724aae 100644 --- a/src/protocols/rdp/client.c +++ b/src/protocols/rdp/client.c @@ -66,9 +66,6 @@ int guac_client_init(guac_client* client, int argc, char** argv) { pthread_mutexattr_settype(&(rdp_client->attributes), PTHREAD_MUTEX_RECURSIVE); - /* Init RDP lock */ - pthread_mutex_init(&(rdp_client->rdp_lock), &(rdp_client->attributes)); - /* Set handlers */ client->join_handler = guac_rdp_user_join_handler; client->free_handler = guac_rdp_client_free_handler; diff --git a/src/protocols/rdp/input.c b/src/protocols/rdp/input.c index 2c3ef14b..9e455160 100644 --- a/src/protocols/rdp/input.c +++ b/src/protocols/rdp/input.c @@ -38,14 +38,10 @@ int guac_rdp_user_mouse_handler(guac_user* user, int x, int y, int mask) { guac_client* client = user->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - pthread_mutex_lock(&(rdp_client->rdp_lock)); - /* Skip if not yet connected */ freerdp* rdp_inst = rdp_client->rdp_inst; - if (rdp_inst == NULL) { - pthread_mutex_unlock(&(rdp_client->rdp_lock)); + if (rdp_inst == NULL) return 0; - } /* Store current mouse location/state */ guac_common_cursor_update(rdp_client->display->cursor, user, x, y, mask); @@ -118,8 +114,6 @@ int guac_rdp_user_mouse_handler(guac_user* user, int x, int y, int mask) { rdp_client->mouse_button_mask = mask; } - pthread_mutex_unlock(&(rdp_client->rdp_lock)); - return 0; } @@ -155,9 +149,7 @@ int guac_rdp_user_size_handler(guac_user* user, int width, int height) { height = height * settings->resolution / user->info.optimal_resolution; /* Send display update */ - pthread_mutex_lock(&(rdp_client->rdp_lock)); guac_rdp_disp_set_size(rdp_client->disp, settings, rdp_inst, width, height); - pthread_mutex_unlock(&(rdp_client->rdp_lock)); return 0; diff --git a/src/protocols/rdp/keyboard.c b/src/protocols/rdp/keyboard.c index 88cf2daf..b0a0188b 100644 --- a/src/protocols/rdp/keyboard.c +++ b/src/protocols/rdp/keyboard.c @@ -102,21 +102,15 @@ static void guac_rdp_send_key_event(guac_rdp_client* rdp_client, else pressed_flags = KBD_FLAGS_RELEASE; - pthread_mutex_lock(&(rdp_client->rdp_lock)); - /* Skip if not yet connected */ freerdp* rdp_inst = rdp_client->rdp_inst; - if (rdp_inst == NULL) { - pthread_mutex_unlock(&(rdp_client->rdp_lock)); + if (rdp_inst == NULL) return; - } /* Send actual key */ rdp_inst->input->KeyboardEvent(rdp_inst->input, flags | pressed_flags, scancode); - pthread_mutex_unlock(&(rdp_client->rdp_lock)); - } /** @@ -136,22 +130,16 @@ static void guac_rdp_send_key_event(guac_rdp_client* rdp_client, static void guac_rdp_send_unicode_event(guac_rdp_client* rdp_client, int codepoint) { - pthread_mutex_lock(&(rdp_client->rdp_lock)); - /* Skip if not yet connected */ freerdp* rdp_inst = rdp_client->rdp_inst; - if (rdp_inst == NULL) { - pthread_mutex_unlock(&(rdp_client->rdp_lock)); + if (rdp_inst == NULL) return; - } /* Send Unicode event */ rdp_inst->input->UnicodeKeyboardEvent( rdp_inst->input, 0, codepoint); - pthread_mutex_unlock(&(rdp_client->rdp_lock)); - } /** @@ -171,20 +159,14 @@ static void guac_rdp_send_unicode_event(guac_rdp_client* rdp_client, static void guac_rdp_send_synchronize_event(guac_rdp_client* rdp_client, int flags) { - pthread_mutex_lock(&(rdp_client->rdp_lock)); - /* Skip if not yet connected */ freerdp* rdp_inst = rdp_client->rdp_inst; - if (rdp_inst == NULL) { - pthread_mutex_unlock(&(rdp_client->rdp_lock)); + if (rdp_inst == NULL) return; - } /* Synchronize lock key states */ rdp_inst->input->SynchronizeEvent(rdp_inst->input, flags); - pthread_mutex_unlock(&(rdp_client->rdp_lock)); - } /** diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index b42035ca..6d5d2254 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -405,9 +405,7 @@ static int guac_rdp_handle_connection(guac_client* client) { && !guac_rdp_disp_reconnect_needed(rdp_client->disp)) { /* Update remote display size */ - pthread_mutex_lock(&(rdp_client->rdp_lock)); guac_rdp_disp_update_size(rdp_client->disp, settings, rdp_inst); - pthread_mutex_unlock(&(rdp_client->rdp_lock)); /* Wait for data and construct a reasonable frame */ int wait_result = rdp_guac_client_wait_for_messages(client, @@ -423,20 +421,15 @@ static int guac_rdp_handle_connection(guac_client* client) { guac_timestamp frame_end; int frame_remaining; - pthread_mutex_lock(&(rdp_client->rdp_lock)); - /* Check the libfreerdp fds */ if (!freerdp_check_event_handles(rdp_inst->context)) { /* Flag connection failure */ wait_result = -1; - pthread_mutex_unlock(&(rdp_client->rdp_lock)); break; } - pthread_mutex_unlock(&(rdp_client->rdp_lock)); - /* Calculate time remaining in frame */ frame_end = guac_timestamp_current(); frame_remaining = frame_start + GUAC_RDP_FRAME_DURATION @@ -469,9 +462,7 @@ static int guac_rdp_handle_connection(guac_client* client) { } /* Test whether the RDP server is closing the connection */ - pthread_mutex_lock(&(rdp_client->rdp_lock)); int connection_closing = freerdp_shall_disconnect(rdp_inst); - pthread_mutex_unlock(&(rdp_client->rdp_lock)); /* Close connection cleanly if server is disconnecting */ if (connection_closing) @@ -497,8 +488,6 @@ static int guac_rdp_handle_connection(guac_client* client) { guac_rdp_print_job_free(rdp_client->active_job); } - pthread_mutex_lock(&(rdp_client->rdp_lock)); - /* Disconnect client and channels */ freerdp_disconnect(rdp_inst); @@ -521,8 +510,6 @@ static int guac_rdp_handle_connection(guac_client* client) { /* Free display */ guac_common_display_free(rdp_client->display); - pthread_mutex_unlock(&(rdp_client->rdp_lock)); - /* Client is now disconnected */ guac_client_log(client, GUAC_LOG_INFO, "Internal RDP client disconnected"); diff --git a/src/protocols/rdp/rdp.h b/src/protocols/rdp/rdp.h index 5220a6c2..5394bb36 100644 --- a/src/protocols/rdp/rdp.h +++ b/src/protocols/rdp/rdp.h @@ -153,13 +153,6 @@ typedef struct guac_rdp_client { */ guac_common_list* available_svc; - /** - * Lock which is locked and unlocked for each RDP message, and for each - * part of the RDP client instance which may be dynamically freed and - * reallocated during reconnection. - */ - pthread_mutex_t rdp_lock; - /** * Common attributes for locks. */ From 7b93b3d2e923d5e7603a10bcbf7a31219b50b270 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 21 Dec 2019 22:51:43 -0800 Subject: [PATCH 042/109] GUACAMOLE-249: Gradually reassemble received chunks of RDPSND data. --- .../rdp/guac_rdpsnd/rdpsnd_service.c | 42 +++++++++++++++++-- .../rdp/guac_rdpsnd/rdpsnd_service.h | 15 +++++++ 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c b/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c index b18a2652..88048a3a 100644 --- a/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c +++ b/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c @@ -161,9 +161,45 @@ static VOID guac_rdpsnd_handle_open_event(LPVOID user_param, return; } - wStream* input_stream = Stream_New(data, data_length); - guac_rdpsnd_process_receive(rdpsnd, input_stream); - Stream_Free(input_stream, FALSE); + /* If receiving first chunk, allocate sufficient space for all remaining + * chunks */ + if (data_flags & CHANNEL_FLAG_FIRST) { + + /* Limit maximum received size */ + if (total_length > GUAC_SVC_MAX_ASSEMBLED_LENGTH) { + guac_client_log(rdpsnd->client, GUAC_LOG_WARNING, "RDP server has " + "requested to send a sequence of %i bytes, but this " + "exceeds the maximum buffer space of %i bytes. Received " + "data may be truncated.", total_length, + GUAC_SVC_MAX_ASSEMBLED_LENGTH); + total_length = GUAC_SVC_MAX_ASSEMBLED_LENGTH; + } + + rdpsnd->input_stream = Stream_New(NULL, total_length); + } + + /* Add chunk to buffer only if sufficient space remains */ + if (Stream_EnsureRemainingCapacity(rdpsnd->input_stream, data_length)) + Stream_Write(rdpsnd->input_stream, data, data_length); + else + guac_client_log(rdpsnd->client, GUAC_LOG_WARNING, "%i bytes of data " + "received from within the remote desktop session for the " + "RDPSND channel are being dropped because the maximum " + "available space for received data has been exceeded.", + data_length, rdpsnd->channel_def.name, open_handle, + rdpsnd->open_handle); + + /* Fire event once last chunk has been received */ + if (data_flags & CHANNEL_FLAG_LAST) { + + Stream_SealLength(rdpsnd->input_stream); + Stream_SetPosition(rdpsnd->input_stream, 0); + + guac_rdpsnd_process_receive(rdpsnd, rdpsnd->input_stream); + + Stream_Free(rdpsnd->input_stream, TRUE); + + } } diff --git a/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.h b/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.h index de615ab0..f78df847 100644 --- a/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.h +++ b/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.h @@ -34,6 +34,13 @@ */ #define GUAC_RDP_MAX_FORMATS 16 +/** + * The maximum number of bytes that the RDP server will be allowed to send + * within any single write operation, regardless of the number of chunks that + * write is split into. Bytes beyond this limit may be dropped. + */ +#define GUAC_SVC_MAX_ASSEMBLED_LENGTH 1048576 + /** * Abstract representation of a PCM format, including the sample rate, number * of channels, and bits per sample. @@ -103,6 +110,14 @@ typedef struct guac_rdpsnd { */ DWORD open_handle; + /** + * All data that has been received thus far from the current RDP server + * write operation. Data received along virtual channels is sent in chunks + * (typically 1600 bytes), and thus must be gradually reassembled as it is + * received. + */ + wStream* input_stream; + /** * The block number of the last SNDC_WAVE (WaveInfo) PDU received. */ From 352b9c517c24f9d8894b83b8d26a1909ba848d3c Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 22 Dec 2019 12:18:01 -0800 Subject: [PATCH 043/109] GUACAMOLE-249: Add common SVC plugin implementation as future simplified basis for RDPSND, RDPDR, etc. --- src/protocols/rdp/Makefile.am | 30 +- src/protocols/rdp/common-svc.c | 103 ++++++ src/protocols/rdp/common-svc.h | 230 +++++++++++++ .../rdp/guac-common-svc/common-svc-main.c | 310 ++++++++++++++++++ 4 files changed, 669 insertions(+), 4 deletions(-) create mode 100644 src/protocols/rdp/common-svc.c create mode 100644 src/protocols/rdp/common-svc.h create mode 100644 src/protocols/rdp/guac-common-svc/common-svc-main.c diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index aacfda6a..9a3a5fe2 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -41,6 +41,7 @@ libguac_client_rdp_la_SOURCES = \ channels.c \ client.c \ clipboard.c \ + common-svc.c \ decompose.c \ disp.c \ error.c \ @@ -83,6 +84,7 @@ noinst_HEADERS = \ client.h \ clipboard.h \ channels.h \ + common-svc.h \ decompose.h \ disp.h \ error.h \ @@ -130,14 +132,34 @@ libguac_client_rdp_la_LIBADD = \ # Plugins for FreeRDP # -freerdp_LTLIBRARIES = \ - libguacai-client.la \ - libguacdr-client.la \ - libguacsnd-client.la \ +freerdp_LTLIBRARIES = \ + libguac-common-svc-client.la \ + libguacai-client.la \ + libguacdr-client.la \ + libguacsnd-client.la \ libguacsvc-client.la freerdpdir = ${libdir}/freerdp2 +# +# Common SVC plugin (shared by RDPDR, RDPSND, etc.) +# + +libguac_common_svc_client_la_SOURCES = \ + guac-common-svc/common-svc-main.c + +libguac_common_svc_client_la_CFLAGS = \ + -Werror -Wall -Iinclude \ + @LIBGUAC_INCLUDE@ \ + @RDP_CFLAGS@ + +libguac_common_svc_client_la_LDFLAGS = \ + -module -avoid-version -shared \ + @RDP_LIBS@ + +libguac_common_svc_client_la_LIBADD = \ + @LIBGUAC_LTLIB@ + # # RDPDR # diff --git a/src/protocols/rdp/common-svc.c b/src/protocols/rdp/common-svc.c new file mode 100644 index 00000000..3e092a95 --- /dev/null +++ b/src/protocols/rdp/common-svc.c @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#include "config.h" +#include "channels.h" +#include "common-svc.h" +#include "rdp.h" + +#include +#include +#include +#include +#include +#include +#include + +int guac_rdp_common_svc_load_plugin(rdpContext* context, + char* name, ULONG channel_options, + guac_rdp_common_svc_connect_handler* connect_handler, + guac_rdp_common_svc_receive_handler* receive_handler, + guac_rdp_common_svc_terminate_handler* terminate_handler) { + + guac_client* client = ((rdp_freerdp_context*) context)->client; + + guac_rdp_common_svc* svc = calloc(1, sizeof(guac_rdp_common_svc)); + svc->client = client; + svc->name = svc->_channel_def.name; + svc->_connect_handler = connect_handler; + svc->_receive_handler = receive_handler; + svc->_terminate_handler = terminate_handler; + + /* Init FreeRDP channel definition */ + int name_length = guac_strlcpy(svc->_channel_def.name, name, GUAC_RDP_SVC_MAX_LENGTH); + svc->_channel_def.options = + CHANNEL_OPTION_INITIALIZED + | CHANNEL_OPTION_ENCRYPT_RDP + | channel_options; + + /* Warn about name length */ + if (name_length >= GUAC_RDP_SVC_MAX_LENGTH) + guac_client_log(client, GUAC_LOG_WARNING, + "Static channel name \"%s\" exceeds maximum length of %i " + "characters and will be truncated to \"%s\".", + name, GUAC_RDP_SVC_MAX_LENGTH - 1, svc->name); + + int result = guac_freerdp_channels_load_plugin(context->channels, + context->settings, "guac-common-svc", svc); + + /* Attempt to load the common SVC plugin for new static channel */ + if (result) { + guac_client_log(client, GUAC_LOG_WARNING, "Cannot create static " + "channel \"%s\": failed to load \"guac-common-svc\" plugin " + "for FreeRDP.", svc->name); + free(svc); + } + + /* Store and log on success (SVC structure will be freed on channel termination) */ + else + guac_client_log(client, GUAC_LOG_DEBUG, "Support for static channel " + "\"%s\" loaded.", svc->name); + + return result; + +} + +void guac_rdp_common_svc_write(guac_rdp_common_svc* svc, + wStream* output_stream) { + + /* Do not write if plugin not associated */ + if (!svc->_open_handle) { + guac_client_log(svc->client, GUAC_LOG_WARNING, "%i bytes of data " + "written to SVC \"%s\" are being dropped because the remote " + "desktop side of that SVC is not yet connected.", + Stream_Length(output_stream), svc->name); + return; + } + + /* NOTE: Data sent via pVirtualChannelWriteEx MUST always be dynamically + * allocated, as it will be automatically freed using free(). If provided, + * the last parameter (user data) MUST be a pointer to a wStream, as it + * will automatically be freed by FreeRDP using Stream_Free() */ + svc->_entry_points.pVirtualChannelWriteEx(svc->_init_handle, + svc->_open_handle, Stream_Buffer(output_stream), + Stream_GetPosition(output_stream), output_stream); + +} + diff --git a/src/protocols/rdp/common-svc.h b/src/protocols/rdp/common-svc.h new file mode 100644 index 00000000..5370d5f6 --- /dev/null +++ b/src/protocols/rdp/common-svc.h @@ -0,0 +1,230 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#ifndef GUAC_RDP_SVC_H +#define GUAC_RDP_SVC_H + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +/** + * The maximum number of bytes to allow within each channel name, including + * null terminator. + */ +#define GUAC_RDP_SVC_MAX_LENGTH 8 + +/** + * The maximum number of bytes that the RDP server will be allowed to send + * within any single write operation, regardless of the number of chunks that + * write is split into. Bytes beyond this limit may be dropped. + */ +#define GUAC_SVC_MAX_ASSEMBLED_LENGTH 1048576 + +/** + * Structure describing a static virtual channel, and the corresponding + * Guacamole pipes and FreeRDP resources. + */ +typedef struct guac_rdp_common_svc guac_rdp_common_svc; + +/** + * Handler which is invoked when a CHANNEL_EVENT_CONNECTED event has been + * processed and the connection/initialization process of the SVC is now + * complete. + * + * @param svc + * The guac_rdp_common_svc structure representing the SVC that is now + * connected. + */ +typedef void guac_rdp_common_svc_connect_handler(guac_rdp_common_svc* svc); + +/** + * Handler which is invoked when a logical block of data has been received + * along an SVC, having been reassembled from a series of + * CHANNEL_EVENT_DATA_RECEIVED events. + * + * @param svc + * The guac_rdp_common_svc structure representing the SVC that received the + * data. + * + * @param input_stream + * The reassembled block of data that was received. + */ +typedef void guac_rdp_common_svc_receive_handler(guac_rdp_common_svc* svc, wStream* input_stream); + +/** + * Handler which is invoked when a CHANNEL_EVENT_TERMINATED event has been + * processed and all resources associated with the SVC must now be freed. + * + * @param svc + * The guac_rdp_common_svc structure representing the SVC that has been + * terminated. + */ +typedef void guac_rdp_common_svc_terminate_handler(guac_rdp_common_svc* svc); + +struct guac_rdp_common_svc { + + /** + * Reference to the client owning this static channel. + */ + guac_client* client; + + /** + * The name of the static virtual channel, as specified to + * guac_rdp_common_svc_load_plugin(). This value is stored and defined + * internally by the CHANNEL_DEF. + */ + const char* name; + + /** + * Arbitrary channel-specific data which may be assigned and referenced by + * channel implementations leveraging the "guac-common-svc" plugin. + */ + void* data; + + /** + * Handler which is invoked when handling a CHANNEL_EVENT_CONNECTED event. + */ + guac_rdp_common_svc_connect_handler* _connect_handler; + + /** + * Handler which is invoked when all chunks of data for a single logical + * block have been received via CHANNEL_EVENT_DATA_RECEIVED events and + * reassembled. + */ + guac_rdp_common_svc_receive_handler* _receive_handler; + + /** + * Handler which is invokved when the SVC has been disconnected and is + * about to be freed. + */ + guac_rdp_common_svc_terminate_handler* _terminate_handler; + + /** + * The definition of this static virtual channel, including its name. + */ + CHANNEL_DEF _channel_def; + + /** + * Functions and data specific to the FreeRDP side of the virtual channel + * and plugin. + */ + CHANNEL_ENTRY_POINTS_FREERDP_EX _entry_points; + + /** + * Handle which identifies the client connection, typically referred to + * within the FreeRDP source as pInitHandle. This handle is provided to the + * channel entry point and the channel init event handler. The handle must + * eventually be used within the channel open event handler to obtain a + * handle to the channel itself. + */ + PVOID _init_handle; + + /** + * Handle which identifies the channel itself, typically referred to within + * the FreeRDP source as OpenHandle. This handle is obtained through a call + * to entry_points.pVirtualChannelOpenEx() in response to receiving a + * CHANNEL_EVENT_CONNECTED event via the init event handler. + * + * Data is received in CHANNEL_EVENT_DATA_RECEIVED events via the open + * event handler, and data is written through calls to + * entry_points.pVirtualChannelWriteEx(). + */ + DWORD _open_handle; + + /** + * All data that has been received thus far from the current RDP server + * write operation. Data received along virtual channels is sent in chunks + * (typically 1600 bytes), and thus must be gradually reassembled as it is + * received. + */ + wStream* _input_stream; + +}; + +/** + * Initializes arbitrary static virtual channel (SVC) support for RDP, loading + * a new instance of Guacamole's arbitrary SVC plugin for FreeRDP ("guacsvc") + * supporting the channel having the given name. Data sent from within the RDP + * session using this channel will be sent along an identically-named pipe + * stream to the Guacamole client, and data sent along a pipe stream having the + * same name will be written to the SVC and received within the RDP session. If + * failures occur while loading the plugin, messages noting the specifics of + * those failures will be logged, and support for the given channel will not be + * functional. + * + * This MUST be called within the PreConnect callback of the freerdp instance + * for static virtual channel support to be loaded. + * + * @param rdpContext + * The rdpContext associated with the FreeRDP side of the RDP connection. + * + * @param name + * The name of the SVC which should be handled by the new instance of the + * plugin. + * + * @param channel_options + * Bitwise OR of any of the several CHANNEL_OPTION_* flags. Regardless of + * whether specified here, the CHANNEL_OPTION_INTIALIZED and + * CHANNEL_OPTION_ENCRYPT_RDP flags will automatically be set. + * + * @param connect_handler + * The function to invoke when the SVC has been connected. + * + * @param receive_handler + * The function to invoke when the SVC has received a logical block of + * data, reassembled from perhaps several smaller chunks of data. + * + * @param terminate_handler + * The function to invoke when the SVC has been disconnected and is about + * to be freed. + * + * @return + * Zero if the plugin was loaded successfully, non-zero if the plugin could + * not be loaded. + */ +int guac_rdp_common_svc_load_plugin(rdpContext* context, + char* name, ULONG channel_options, + guac_rdp_common_svc_connect_handler* connect_handler, + guac_rdp_common_svc_receive_handler* receive_handler, + guac_rdp_common_svc_terminate_handler* terminate_handler); + +/** + * Writes the given data to the virtual channel such that it can be received + * within the RDP session. The given data MUST be dynamically allocated, as the + * write operation may be queued and the actual write may not occur until + * later. The provided wStream and the buffer it points to will be + * automatically freed after the write occurs. + * + * @param svc + * The static virtual channel to write data to. + * + * @param output_stream + * The data to write, which MUST be dynamically allocated. + */ +void guac_rdp_common_svc_write(guac_rdp_common_svc* svc, + wStream* output_stream); + +#endif + diff --git a/src/protocols/rdp/guac-common-svc/common-svc-main.c b/src/protocols/rdp/guac-common-svc/common-svc-main.c new file mode 100644 index 00000000..441823b7 --- /dev/null +++ b/src/protocols/rdp/guac-common-svc/common-svc-main.c @@ -0,0 +1,310 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#include "config.h" +#include "common-svc.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/** + * Event handler for events which deal with data transmitted over an open SVC. + * This specific implementation of the event handler currently handles only the + * CHANNEL_EVENT_DATA_RECEIVED event, delegating actual handling of that event + * to guac_rdp_common_svc_process_receive(). + * + * The FreeRDP requirements for this function follow those of the + * VirtualChannelOpenEventEx callback defined within Microsoft's RDP API: + * + * https://docs.microsoft.com/en-us/previous-versions/windows/embedded/aa514754%28v%3dmsdn.10%29 + * + * @param user_param + * The pointer to arbitrary data originally passed via the first parameter + * of the pVirtualChannelInitEx() function call when the associated channel + * was initialized. The pVirtualChannelInitEx() function is exposed within + * the channel entry points structure. + * + * @param open_handle + * The handle which identifies the channel itself, typically referred to + * within the FreeRDP source as OpenHandle. + * + * @param event + * An integer representing the event that should be handled. This will be + * either CHANNEL_EVENT_DATA_RECEIVED, CHANNEL_EVENT_WRITE_CANCELLED, or + * CHANNEL_EVENT_WRITE_COMPLETE. + * + * @param data + * The data received, for CHANNEL_EVENT_DATA_RECEIVED events, and the value + * passed as user data to pVirtualChannelWriteEx() for + * CHANNEL_EVENT_WRITE_* events (note that user data for + * pVirtualChannelWriteEx() as implemented by FreeRDP MUST either be NULL + * or a wStream containing the data written). + * + * @param data_length + * The number of bytes of event-specific data. + * + * @param total_length + * The total number of bytes expected to be received from the RDP server + * due to this single write (from the server's perspective). Each write may + * actually be split into multiple chunks, thus resulting in multiple + * receive events for the same logical block of data. The relationship + * between chunks is indicated with the CHANNEL_FLAG_FIRST and + * CHANNEL_FLAG_LAST flags. + * + * @param data_flags + * The result of a bitwise OR of the CHANNEL_FLAG_* flags which apply to + * the data received. This value is relevant only to + * CHANNEL_EVENT_DATA_RECEIVED events. Valid flags are CHANNEL_FLAG_FIRST, + * CHANNEL_FLAG_LAST, and CHANNEL_FLAG_ONLY. The flag CHANNEL_FLAG_MIDDLE + * is not itself a flag, but the absence of both CHANNEL_FLAG_FIRST and + * CHANNEL_FLAG_LAST. + */ +static VOID guac_rdp_common_svc_handle_open_event(LPVOID user_param, + DWORD open_handle, UINT event, LPVOID data, UINT32 data_length, + UINT32 total_length, UINT32 data_flags) { + + /* Ignore all events except for received data */ + if (event != CHANNEL_EVENT_DATA_RECEIVED) + return; + + guac_rdp_common_svc* svc = (guac_rdp_common_svc*) user_param; + + /* Validate relevant handle matches that of SVC */ + if (open_handle != svc->_open_handle) { + guac_client_log(svc->client, GUAC_LOG_WARNING, "%i bytes of data " + "received from within the remote desktop session for SVC " + "\"%s\" are being dropped because the relevant open handle " + "(0x%X) does not match the open handle of the SVC (0x%X).", + data_length, svc->name, open_handle, svc->_open_handle); + return; + } + + /* If receiving first chunk, allocate sufficient space for all remaining + * chunks */ + if (data_flags & CHANNEL_FLAG_FIRST) { + + /* Limit maximum received size */ + if (total_length > GUAC_SVC_MAX_ASSEMBLED_LENGTH) { + guac_client_log(svc->client, GUAC_LOG_WARNING, "RDP server has " + "requested to send a sequence of %i bytes, but this " + "exceeds the maximum buffer space of %i bytes. Received " + "data may be truncated.", total_length, + GUAC_SVC_MAX_ASSEMBLED_LENGTH); + total_length = GUAC_SVC_MAX_ASSEMBLED_LENGTH; + } + + svc->_input_stream = Stream_New(NULL, total_length); + } + + /* Add chunk to buffer only if sufficient space remains */ + if (Stream_EnsureRemainingCapacity(svc->_input_stream, data_length)) + Stream_Write(svc->_input_stream, data, data_length); + else + guac_client_log(svc->client, GUAC_LOG_WARNING, "%i bytes of data " + "received from within the remote desktop session for SVC " + "\"%s\" are being dropped because the maximum available " + "space for received data has been exceeded.", data_length, + svc->name); + + /* Fire event once last chunk has been received */ + if (data_flags & CHANNEL_FLAG_LAST) { + + Stream_SealLength(svc->_input_stream); + Stream_SetPosition(svc->_input_stream, 0); + + /* Handle channel-specific data receipt tasks, if any */ + if (svc->_receive_handler) + svc->_receive_handler(svc, svc->_input_stream); + + Stream_Free(svc->_input_stream, TRUE); + + } + +} + +/** + * Processes a CHANNEL_EVENT_CONNECTED event, completing the + * connection/initialization process of the channel. + * + * @param rdpsnd + * The guac_rdp_common_svc structure representing the channel. + */ +static void guac_rdp_common_svc_process_connect(guac_rdp_common_svc* svc) { + + /* Open FreeRDP side of connected channel */ + UINT32 open_status = + svc->_entry_points.pVirtualChannelOpenEx(svc->_init_handle, + &svc->_open_handle, svc->_channel_def.name, + guac_rdp_common_svc_handle_open_event); + + /* Warn if the channel cannot be opened after all */ + if (open_status != CHANNEL_RC_OK) { + guac_client_log(svc->client, GUAC_LOG_WARNING, "SVC \"%s\" could not " + "be opened: %s (error %i)", svc->name, + WTSErrorToString(open_status), open_status); + return; + } + + /* Handle channel-specific connect tasks, if any */ + if (svc->_connect_handler) + svc->_connect_handler(svc); + + /* Channel is now ready */ + guac_client_log(svc->client, GUAC_LOG_DEBUG, "SVC \"%s\" connected.", + svc->name); + +} + +/** + * Processes a CHANNEL_EVENT_TERMINATED event, freeing all resources associated + * with the channel. + * + * @param svc + * The guac_rdp_common_svc structure representing the channel. + */ +static void guac_rdp_common_svc_process_terminate(guac_rdp_common_svc* svc) { + + /* Handle channel-specific termination tasks, if any */ + if (svc->_terminate_handler) + svc->_terminate_handler(svc); + + guac_client_log(svc->client, GUAC_LOG_DEBUG, "SVC \"%s\" disconnected.", + svc->name); + free(svc); + +} + +/** + * Event handler for events which deal with the overall lifecycle of an SVC. + * This specific implementation of the event handler currently handles only + * CHANNEL_EVENT_CONNECTED and CHANNEL_EVENT_TERMINATED events, delegating + * actual handling of those events to guac_rdp_common_svc_process_connect() and + * guac_rdp_common_svc_process_terminate() respectively. + * + * The FreeRDP requirements for this function follow those of the + * VirtualChannelInitEventEx callback defined within Microsoft's RDP API: + * + * https://docs.microsoft.com/en-us/previous-versions/windows/embedded/aa514727%28v%3dmsdn.10%29 + * + * @param user_param + * The pointer to arbitrary data originally passed via the first parameter + * of the pVirtualChannelInitEx() function call when the associated channel + * was initialized. The pVirtualChannelInitEx() function is exposed within + * the channel entry points structure. + * + * @param init_handle + * The handle which identifies the client connection, typically referred to + * within the FreeRDP source as pInitHandle. + * + * @param event + * An integer representing the event that should be handled. This will be + * either CHANNEL_EVENT_CONNECTED, CHANNEL_EVENT_DISCONNECTED, + * CHANNEL_EVENT_INITIALIZED, CHANNEL_EVENT_TERMINATED, or + * CHANNEL_EVENT_V1_CONNECTED. + * + * @param data + * NULL in all cases except the CHANNEL_EVENT_CONNECTED event, in which + * case this is a null-terminated string containing the name of the server. + * + * @param data_length + * The number of bytes of data, if any. + */ +static VOID guac_rdp_common_svc_handle_init_event(LPVOID user_param, + LPVOID init_handle, UINT event, LPVOID data, UINT data_length) { + + guac_rdp_common_svc* svc = (guac_rdp_common_svc*) user_param; + + /* Validate relevant handle matches that of SVC */ + if (init_handle != svc->_init_handle) { + guac_client_log(svc->client, GUAC_LOG_WARNING, "An init event (#%i) " + "for SVC \"%s\" has been dropped because the relevant init " + "handle (0x%X) does not match the init handle of the SVC " + "(0x%X).", event, svc->name, init_handle, svc->_init_handle); + return; + } + + switch (event) { + + /* The remote desktop side of the SVC has been connected */ + case CHANNEL_EVENT_CONNECTED: + guac_rdp_common_svc_process_connect(svc); + break; + + /* The channel has disconnected and now must be cleaned up */ + case CHANNEL_EVENT_TERMINATED: + guac_rdp_common_svc_process_terminate(svc); + break; + + } + +} + +/** + * Entry point for FreeRDP plugins. This function is automatically invoked when + * the plugin is loaded. + * + * @param entry_points + * Functions and data specific to the FreeRDP side of the virtual channel + * and plugin. This structure must be copied within implementation-specific + * storage such that the functions it references can be invoked when + * needed. + * + * @param init_handle + * The handle which identifies the client connection, typically referred to + * within the FreeRDP source as pInitHandle. This handle is also provided + * to the channel init event handler. The handle must eventually be used + * within the channel open event handler to obtain a handle to the channel + * itself. + * + * @return + * TRUE if the plugin has initialized successfully, FALSE otherwise. + */ +BOOL VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS entry_points, + PVOID init_handle) { + + CHANNEL_ENTRY_POINTS_FREERDP_EX* entry_points_ex = + (CHANNEL_ENTRY_POINTS_FREERDP_EX*) entry_points; + + /* Get structure representing the Guacamole side of the SVC from plugin + * parameters */ + guac_rdp_common_svc* svc = (guac_rdp_common_svc*) entry_points_ex->pExtendedData; + + /* Copy FreeRDP data into SVC structure for future reference */ + svc->_entry_points = *entry_points_ex; + svc->_init_handle = init_handle; + + /* Complete initialization */ + if (svc->_entry_points.pVirtualChannelInitEx(svc, svc, init_handle, + &svc->_channel_def, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, + guac_rdp_common_svc_handle_init_event) != CHANNEL_RC_OK) { + return FALSE; + } + + return TRUE; + +} + From 3255b182ab6ca1f73a54f4eee2cccdda497d83cc Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 22 Dec 2019 13:33:08 -0800 Subject: [PATCH 044/109] GUACAMOLE-249: Remove "guacsvc" plugin in favor of leveraging common SVC implementation. --- src/protocols/rdp/Makefile.am | 31 +-- src/protocols/rdp/guac_svc/svc_service.c | 311 ----------------------- src/protocols/rdp/{svc.c => pipe-svc.c} | 156 ++++++------ src/protocols/rdp/{svc.h => pipe-svc.h} | 121 ++++----- src/protocols/rdp/rdp.c | 4 +- src/protocols/rdp/user.c | 6 +- 6 files changed, 133 insertions(+), 496 deletions(-) delete mode 100644 src/protocols/rdp/guac_svc/svc_service.c rename src/protocols/rdp/{svc.c => pipe-svc.c} (51%) rename src/protocols/rdp/{svc.h => pipe-svc.h} (59%) diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index 9a3a5fe2..0df45a30 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -47,6 +47,7 @@ libguac_client_rdp_la_SOURCES = \ error.c \ input.c \ keyboard.c \ + pipe-svc.c \ ptr_string.c \ rail.c \ rdp.c \ @@ -63,7 +64,6 @@ libguac_client_rdp_la_SOURCES = \ rdpdr.c \ rdpsnd.c \ resolution.c \ - svc.c \ unicode.c \ user.c @@ -90,6 +90,7 @@ noinst_HEADERS = \ error.h \ input.h \ keyboard.h \ + pipe-svc.h \ ptr_string.h \ rail.h \ rdp.h \ @@ -107,7 +108,6 @@ noinst_HEADERS = \ rdpdr.h \ rdpsnd.h \ resolution.h \ - svc.h \ unicode.h \ user.h @@ -136,8 +136,7 @@ freerdp_LTLIBRARIES = \ libguac-common-svc-client.la \ libguacai-client.la \ libguacdr-client.la \ - libguacsnd-client.la \ - libguacsvc-client.la + libguacsnd-client.la freerdpdir = ${libdir}/freerdp2 @@ -244,30 +243,6 @@ libguacsnd_client_la_LIBADD = \ @COMMON_LTLIB@ \ @LIBGUAC_LTLIB@ -# -# Static Virtual Channels -# - -libguacsvc_client_la_SOURCES = \ - guac_svc/svc_service.c \ - svc.c - -libguacsvc_client_la_CFLAGS = \ - -Werror -Wall -Iinclude \ - @COMMON_INCLUDE@ \ - @COMMON_SSH_INCLUDE@ \ - @LIBGUAC_INCLUDE@ \ - @RDP_CFLAGS@ - -libguacsvc_client_la_LDFLAGS = \ - -module -avoid-version -shared \ - @PTHREAD_LIBS@ \ - @RDP_LIBS@ - -libguacsvc_client_la_LIBADD = \ - @COMMON_LTLIB@ \ - @LIBGUAC_LTLIB@ - # # Optional SFTP support # diff --git a/src/protocols/rdp/guac_svc/svc_service.c b/src/protocols/rdp/guac_svc/svc_service.c deleted file mode 100644 index 07f17fb9..00000000 --- a/src/protocols/rdp/guac_svc/svc_service.c +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -#include "config.h" - -#include "svc.h" - -#include -#include - -#include -#include -#include -#include -#include -#include - -/** - * Processes data received along an SVC via a CHANNEL_EVENT_DATA_RECEIVED - * event, forwarding the data along an established, outbound pipe stream to the - * Guacamole client. - * - * @param svc - * The guac_rdp_svc structure representing the SVC that received the data. - * - * @param data - * The data that was received. - * - * @param length - * The number of bytes received. - */ -static void guac_rdp_svc_process_receive(guac_rdp_svc* svc, - void* data, int length) { - - /* Fail if output not created */ - if (svc->output_pipe == NULL) { - guac_client_log(svc->client, GUAC_LOG_WARNING, "%i bytes of data " - "received from within the remote desktop session for SVC " - "\"%s\" are being dropped because the outbound pipe stream " - "for that SVC is not yet open. This should NOT happen.", - length, svc->channel_def.name); - return; - } - - /* Send blob */ - guac_protocol_send_blob(svc->client->socket, svc->output_pipe, data, length); - guac_socket_flush(svc->client->socket); - -} - -/** - * Event handler for events which deal with data transmitted over an open SVC. - * This specific implementation of the event handler currently handles only the - * CHANNEL_EVENT_DATA_RECEIVED event, delegating actual handling of that event - * to guac_rdp_svc_process_receive(). - * - * The FreeRDP requirements for this function follow those of the - * VirtualChannelOpenEventEx callback defined within Microsoft's RDP API: - * - * https://docs.microsoft.com/en-us/previous-versions/windows/embedded/aa514754%28v%3dmsdn.10%29 - * - * @param user_param - * The pointer to arbitrary data originally passed via the first parameter - * of the pVirtualChannelInitEx() function call when the associated channel - * was initialized. The pVirtualChannelInitEx() function is exposed within - * the channel entry points structure. - * - * @param open_handle - * The handle which identifies the channel itself, typically referred to - * within the FreeRDP source as OpenHandle. - * - * @param event - * An integer representing the event that should be handled. This will be - * either CHANNEL_EVENT_DATA_RECEIVED, CHANNEL_EVENT_WRITE_CANCELLED, or - * CHANNEL_EVENT_WRITE_COMPLETE. - * - * @param data - * The data received, for CHANNEL_EVENT_DATA_RECEIVED events, and the value - * passed as user data to pVirtualChannelWriteEx() for - * CHANNEL_EVENT_WRITE_* events (note that user data for - * pVirtualChannelWriteEx() as implemented by FreeRDP MUST either be NULL - * or a wStream containing the data written). - * - * @param data_length - * The number of bytes of event-specific data. - * - * @param total_length - * The total number of bytes written to the RDP server in a single write - * operation. - * - * NOTE: The meaning of total_length is unclear. The above description was - * written mainly through referencing the documentation in MSDN. Real-world - * use will need to be consulted, likely within the FreeRDP source, before - * this value can be reliably used. The current implementation of this - * handler ignores this parameter. - * - * @param data_flags - * The result of a bitwise OR of the CHANNEL_FLAG_* flags which apply to - * the data received. This value is relevant only to - * CHANNEL_EVENT_DATA_RECEIVED events. Valid flags are CHANNEL_FLAG_FIRST, - * CHANNEL_FLAG_LAST, and CHANNEL_FLAG_ONLY. The flag CHANNEL_FLAG_MIDDLE - * is not itself a flag, but the absence of both CHANNEL_FLAG_FIRST and - * CHANNEL_FLAG_LAST. - */ -static VOID guac_rdp_svc_handle_open_event(LPVOID user_param, - DWORD open_handle, UINT event, LPVOID data, UINT32 data_length, - UINT32 total_length, UINT32 data_flags) { - - /* Ignore all events except for received data */ - if (event != CHANNEL_EVENT_DATA_RECEIVED) - return; - - guac_rdp_svc* svc = (guac_rdp_svc*) user_param; - - /* Validate relevant handle matches that of SVC */ - if (open_handle != svc->open_handle) { - guac_client_log(svc->client, GUAC_LOG_WARNING, "%i bytes of data " - "received from within the remote desktop session for SVC " - "\"%s\" are being dropped because the relevant open handle " - "(0x%X) does not match the open handle of the SVC (0x%X).", - data_length, svc->channel_def.name, open_handle, - svc->open_handle); - return; - } - - guac_rdp_svc_process_receive(svc, data, data_length); - -} - -/** - * Processes a CHANNEL_EVENT_CONNECTED event, completing the - * connection/initialization process of the SVC. - * - * @param svc - * The guac_rdp_svc structure representing the SVC that is now connected. - */ -static void guac_rdp_svc_process_connect(guac_rdp_svc* svc) { - - /* Open FreeRDP side of connected channel */ - UINT32 open_status = - svc->entry_points.pVirtualChannelOpenEx(svc->init_handle, - &svc->open_handle, svc->channel_def.name, - guac_rdp_svc_handle_open_event); - - /* Warn if the channel cannot be opened after all */ - if (open_status != CHANNEL_RC_OK) { - guac_client_log(svc->client, GUAC_LOG_WARNING, "SVC \"%s\" could not " - "be opened: %s (error %i)", svc->channel_def.name, - WTSErrorToString(open_status), open_status); - return; - } - - /* SVC may now receive data from client */ - guac_rdp_svc_add(svc->client, svc); - - /* Create pipe */ - svc->output_pipe = guac_client_alloc_stream(svc->client); - - /* Notify of pipe's existence */ - guac_rdp_svc_send_pipe(svc->client->socket, svc); - - /* Log connection to static channel */ - guac_client_log(svc->client, GUAC_LOG_INFO, - "Static channel \"%s\" connected.", svc->channel_def.name); - -} - -/** - * Processes a CHANNEL_EVENT_TERMINATED event, freeing all resources associated - * with the SVC. - * - * @param svc - * The guac_rdp_svc structure representing the SVC that has been - * terminated. - */ -static void guac_rdp_svc_process_terminate(guac_rdp_svc* svc) { - - /* Remove and free SVC */ - guac_client_log(svc->client, GUAC_LOG_INFO, "Closing channel \"%s\"...", svc->channel_def.name); - guac_rdp_svc_remove(svc->client, svc->channel_def.name); - free(svc); - -} - -/** - * Event handler for events which deal with the overall lifecycle of an SVC. - * This specific implementation of the event handler currently handles only - * CHANNEL_EVENT_CONNECTED and CHANNEL_EVENT_TERMINATED events, delegating - * actual handling of those events to guac_rdp_svc_process_connect() and - * guac_rdp_svc_process_terminate() respectively. - * - * The FreeRDP requirements for this function follow those of the - * VirtualChannelInitEventEx callback defined within Microsoft's RDP API: - * - * https://docs.microsoft.com/en-us/previous-versions/windows/embedded/aa514727%28v%3dmsdn.10%29 - * - * @param user_param - * The pointer to arbitrary data originally passed via the first parameter - * of the pVirtualChannelInitEx() function call when the associated channel - * was initialized. The pVirtualChannelInitEx() function is exposed within - * the channel entry points structure. - * - * @param init_handle - * The handle which identifies the client connection, typically referred to - * within the FreeRDP source as pInitHandle. - * - * @param event - * An integer representing the event that should be handled. This will be - * either CHANNEL_EVENT_CONNECTED, CHANNEL_EVENT_DISCONNECTED, - * CHANNEL_EVENT_INITIALIZED, CHANNEL_EVENT_TERMINATED, or - * CHANNEL_EVENT_V1_CONNECTED. - * - * @param data - * NULL in all cases except the CHANNEL_EVENT_CONNECTED event, in which - * case this is a null-terminated string containing the name of the server. - * - * @param data_length - * The number of bytes of data, if any. - */ -static VOID guac_rdp_svc_handle_init_event(LPVOID user_param, - LPVOID init_handle, UINT event, LPVOID data, UINT data_length) { - - guac_rdp_svc* svc = (guac_rdp_svc*) user_param; - - /* Validate relevant handle matches that of SVC */ - if (init_handle != svc->init_handle) { - guac_client_log(svc->client, GUAC_LOG_WARNING, "An init event (#%i) " - "for SVC \"%s\" has been dropped because the relevant init " - "handle (0x%X) does not match the init handle of the SVC " - "(0x%X).", event, svc->channel_def.name, init_handle, - svc->init_handle); - return; - } - - switch (event) { - - /* The remote desktop side of the SVC has been connected */ - case CHANNEL_EVENT_CONNECTED: - guac_rdp_svc_process_connect(svc); - break; - - /* The channel has disconnected and now must be cleaned up */ - case CHANNEL_EVENT_TERMINATED: - guac_rdp_svc_process_terminate(svc); - break; - - } - -} - -/** - * Entry point for FreeRDP plugins. This function is automatically invoked when - * the plugin is loaded. - * - * @param entry_points - * Functions and data specific to the FreeRDP side of the virtual channel - * and plugin. This structure must be copied within implementation-specific - * storage such that the functions it references can be invoked when - * needed. - * - * @param init_handle - * The handle which identifies the client connection, typically referred to - * within the FreeRDP source as pInitHandle. This handle is also provided - * to the channel init event handler. The handle must eventually be used - * within the channel open event handler to obtain a handle to the channel - * itself. - * - * @return - * TRUE if the plugin has initialized successfully, FALSE otherwise. - */ -BOOL VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS entry_points, - PVOID init_handle) { - - CHANNEL_ENTRY_POINTS_FREERDP_EX* entry_points_ex = - (CHANNEL_ENTRY_POINTS_FREERDP_EX*) entry_points; - - /* Get structure representing the Guacamole side of the SVC from plugin - * parameters */ - guac_rdp_svc* svc = (guac_rdp_svc*) entry_points_ex->pExtendedData; - - /* Copy FreeRDP data into SVC structure for future reference */ - svc->entry_points = *entry_points_ex; - svc->init_handle = init_handle; - - /* Complete initialization */ - if (svc->entry_points.pVirtualChannelInitEx(svc, svc, init_handle, - &svc->channel_def, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, - guac_rdp_svc_handle_init_event) != CHANNEL_RC_OK) { - return FALSE; - } - - return TRUE; - -} - diff --git a/src/protocols/rdp/svc.c b/src/protocols/rdp/pipe-svc.c similarity index 51% rename from src/protocols/rdp/svc.c rename to src/protocols/rdp/pipe-svc.c index be420727..05cd758c 100644 --- a/src/protocols/rdp/svc.c +++ b/src/protocols/rdp/pipe-svc.c @@ -22,8 +22,9 @@ #include "channels.h" #include "client.h" #include "common/list.h" +#include "common-svc.h" +#include "pipe-svc.h" #include "rdp.h" -#include "svc.h" #include #include @@ -33,15 +34,15 @@ #include -void guac_rdp_svc_send_pipe(guac_socket* socket, guac_rdp_svc* svc) { +void guac_rdp_pipe_svc_send_pipe(guac_socket* socket, guac_rdp_pipe_svc* pipe_svc) { /* Send pipe instruction for the SVC's output stream */ - guac_protocol_send_pipe(socket, svc->output_pipe, - "application/octet-stream", svc->channel_def.name); + guac_protocol_send_pipe(socket, pipe_svc->output_pipe, + "application/octet-stream", pipe_svc->svc->name); } -void guac_rdp_svc_send_pipes(guac_user* user) { +void guac_rdp_pipe_svc_send_pipes(guac_user* user) { guac_client* client = user->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; @@ -51,7 +52,7 @@ void guac_rdp_svc_send_pipes(guac_user* user) { /* Send pipe for each allocated SVC's output stream */ guac_common_list_element* current = rdp_client->available_svc->head; while (current != NULL) { - guac_rdp_svc_send_pipe(user->socket, (guac_rdp_svc*) current->data); + guac_rdp_pipe_svc_send_pipe(user->socket, (guac_rdp_pipe_svc*) current->data); current = current->next; } @@ -59,22 +60,22 @@ void guac_rdp_svc_send_pipes(guac_user* user) { } -void guac_rdp_svc_add(guac_client* client, guac_rdp_svc* svc) { +void guac_rdp_pipe_svc_add(guac_client* client, guac_rdp_pipe_svc* pipe_svc) { guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Add to list of available SVC */ guac_common_list_lock(rdp_client->available_svc); - guac_common_list_add(rdp_client->available_svc, svc); + guac_common_list_add(rdp_client->available_svc, pipe_svc); guac_common_list_unlock(rdp_client->available_svc); } -guac_rdp_svc* guac_rdp_svc_get(guac_client* client, const char* name) { +guac_rdp_pipe_svc* guac_rdp_pipe_svc_get(guac_client* client, const char* name) { guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_common_list_element* current; - guac_rdp_svc* found = NULL; + guac_rdp_pipe_svc* found = NULL; /* For each available SVC */ guac_common_list_lock(rdp_client->available_svc); @@ -82,8 +83,8 @@ guac_rdp_svc* guac_rdp_svc_get(guac_client* client, const char* name) { while (current != NULL) { /* If name matches, found */ - guac_rdp_svc* current_svc = (guac_rdp_svc*) current->data; - if (strcmp(current_svc->channel_def.name, name) == 0) { + guac_rdp_pipe_svc* current_svc = (guac_rdp_pipe_svc*) current->data; + if (strcmp(current_svc->svc->name, name) == 0) { found = current_svc; break; } @@ -97,11 +98,11 @@ guac_rdp_svc* guac_rdp_svc_get(guac_client* client, const char* name) { } -guac_rdp_svc* guac_rdp_svc_remove(guac_client* client, const char* name) { +guac_rdp_pipe_svc* guac_rdp_pipe_svc_remove(guac_client* client, const char* name) { guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_common_list_element* current; - guac_rdp_svc* found = NULL; + guac_rdp_pipe_svc* found = NULL; /* For each available SVC */ guac_common_list_lock(rdp_client->available_svc); @@ -109,8 +110,8 @@ guac_rdp_svc* guac_rdp_svc_remove(guac_client* client, const char* name) { while (current != NULL) { /* If name matches, remove entry */ - guac_rdp_svc* current_svc = (guac_rdp_svc*) current->data; - if (strcmp(current_svc->channel_def.name, name) == 0) { + guac_rdp_pipe_svc* current_svc = (guac_rdp_pipe_svc*) current->data; + if (strcmp(current_svc->svc->name, name) == 0) { guac_common_list_remove(rdp_client->available_svc, current); found = current_svc; break; @@ -126,38 +127,13 @@ guac_rdp_svc* guac_rdp_svc_remove(guac_client* client, const char* name) { } -void guac_rdp_svc_write(guac_rdp_svc* svc, void* data, int length) { - - /* Do not write of plugin not associated */ - if (!svc->open_handle) { - guac_client_log(svc->client, GUAC_LOG_WARNING, "%i bytes of data " - "received from the Guacamole client for SVC \"%s\" are being " - "dropped because the remote desktop side of that SVC is " - "connected.", length, svc->channel_def.name); - return; - } - - /* FreeRDP_VirtualChannelWriteEx() assumes that sent data is dynamically - * allocated and will free() the data after it is sent */ - void* data_copy = malloc(length); - memcpy(data_copy, data, length); - - /* Send received data */ - svc->entry_points.pVirtualChannelWriteEx(svc->init_handle, - svc->open_handle, data_copy, length, - NULL /* NOTE: If non-NULL, this MUST be a pointer to a wStream - containing the supplied buffer, and that wStream will be - automatically freed when FreeRDP handles the write */); - -} - -int guac_rdp_svc_pipe_handler(guac_user* user, guac_stream* stream, +int guac_rdp_pipe_svc_pipe_handler(guac_user* user, guac_stream* stream, char* mimetype, char* name) { - guac_rdp_svc* svc = guac_rdp_svc_get(user->client, name); + guac_rdp_pipe_svc* pipe_svc = guac_rdp_pipe_svc_get(user->client, name); /* Fail if no such SVC */ - if (svc == NULL) { + if (pipe_svc == NULL) { guac_user_log(user, GUAC_LOG_WARNING, "User requested non-existent " "pipe (no such SVC configured): \"%s\"", name); guac_protocol_send_ack(user->socket, stream, "FAIL (NO SUCH PIPE)", @@ -170,19 +146,22 @@ int guac_rdp_svc_pipe_handler(guac_user* user, guac_stream* stream, "connected.", name); /* Init stream data */ - stream->data = svc; - stream->blob_handler = guac_rdp_svc_blob_handler; + stream->data = pipe_svc; + stream->blob_handler = guac_rdp_pipe_svc_blob_handler; return 0; } -int guac_rdp_svc_blob_handler(guac_user* user, guac_stream* stream, +int guac_rdp_pipe_svc_blob_handler(guac_user* user, guac_stream* stream, void* data, int length) { + guac_rdp_pipe_svc* pipe_svc = (guac_rdp_pipe_svc*) stream->data; + /* Write blob data to SVC directly */ - guac_rdp_svc* svc = (guac_rdp_svc*) stream->data; - guac_rdp_svc_write(svc, data, length); + wStream* output_stream = Stream_New(NULL, length); + Stream_Write(output_stream, data, length); + guac_rdp_common_svc_write(pipe_svc->svc, output_stream); guac_protocol_send_ack(user->socket, stream, "OK (DATA RECEIVED)", GUAC_PROTOCOL_STATUS_SUCCESS); @@ -191,37 +170,60 @@ int guac_rdp_svc_blob_handler(guac_user* user, guac_stream* stream, } -void guac_rdp_svc_load_plugin(rdpContext* context, char* name) { +void guac_rdp_pipe_svc_process_connect(guac_rdp_common_svc* svc) { - guac_client* client = ((rdp_freerdp_context*) context)->client; - guac_rdp_svc* svc = calloc(1, sizeof(guac_rdp_svc)); - svc->client = client; + /* Associate SVC with new Guacamole pipe */ + guac_rdp_pipe_svc* pipe_svc = malloc(sizeof(guac_rdp_pipe_svc)); + pipe_svc->svc = svc; + pipe_svc->output_pipe = guac_client_alloc_stream(svc->client); + svc->data = pipe_svc; - /* Init FreeRDP channel definition */ - int name_length = guac_strlcpy(svc->channel_def.name, name, GUAC_RDP_SVC_MAX_LENGTH); - svc->channel_def.options = CHANNEL_OPTION_INITIALIZED - | CHANNEL_OPTION_ENCRYPT_RDP - | CHANNEL_OPTION_COMPRESS_RDP; + /* SVC may now receive data from client */ + guac_rdp_pipe_svc_add(svc->client, pipe_svc); - /* Warn about name length */ - if (name_length >= GUAC_RDP_SVC_MAX_LENGTH) - guac_client_log(client, GUAC_LOG_WARNING, - "Static channel name \"%s\" exceeds maximum length of %i " - "characters and will be truncated to \"%s\".", - name, GUAC_RDP_SVC_MAX_LENGTH - 1, svc->channel_def.name); - - /* Attempt to load guacsvc plugin for new static channel */ - if (guac_freerdp_channels_load_plugin(context->channels, context->settings, "guacsvc", svc)) { - guac_client_log(client, GUAC_LOG_WARNING, "Cannot create static " - "channel \"%s\": failed to load guacsvc plugin.", - svc->channel_def.name); - free(svc); - } - - /* Store and log on success (SVC structure will be freed on channel termination) */ - else - guac_client_log(client, GUAC_LOG_INFO, "Created static channel " - "\"%s\"...", svc->channel_def.name); + /* Notify of pipe's existence */ + guac_rdp_pipe_svc_send_pipe(svc->client->socket, pipe_svc); + +} + +void guac_rdp_pipe_svc_process_receive(guac_rdp_common_svc* svc, + wStream* input_stream) { + + guac_rdp_pipe_svc* pipe_svc = (guac_rdp_pipe_svc*) svc->data; + + /* Fail if output not created */ + if (pipe_svc->output_pipe == NULL) { + guac_client_log(svc->client, GUAC_LOG_WARNING, "%i bytes of data " + "received from within the remote desktop session for SVC " + "\"%s\" are being dropped because the outbound pipe stream " + "for that SVC is not yet open. This should NOT happen.", + Stream_Length(input_stream), svc->name); + return; + } + + /* Send received data as blob */ + guac_protocol_send_blob(svc->client->socket, pipe_svc->output_pipe, Stream_Buffer(input_stream), Stream_Length(input_stream)); + guac_socket_flush(svc->client->socket); + +} + +void guac_rdp_pipe_svc_process_terminate(guac_rdp_common_svc* svc) { + + guac_rdp_pipe_svc* pipe_svc = (guac_rdp_pipe_svc*) svc->data; + + /* Remove and free SVC */ + guac_rdp_pipe_svc_remove(svc->client, svc->name); + free(pipe_svc); + +} + +void guac_rdp_pipe_svc_load_plugin(rdpContext* context, char* name) { + + /* Attempt to load support for static channel */ + guac_rdp_common_svc_load_plugin(context, name, CHANNEL_OPTION_COMPRESS_RDP, + guac_rdp_pipe_svc_process_connect, + guac_rdp_pipe_svc_process_receive, + guac_rdp_pipe_svc_process_terminate); } diff --git a/src/protocols/rdp/svc.h b/src/protocols/rdp/pipe-svc.h similarity index 59% rename from src/protocols/rdp/svc.h rename to src/protocols/rdp/pipe-svc.h index 232b8c2c..1abcf09c 100644 --- a/src/protocols/rdp/svc.h +++ b/src/protocols/rdp/pipe-svc.h @@ -17,10 +17,11 @@ * under the License. */ -#ifndef GUAC_RDP_SVC_H -#define GUAC_RDP_SVC_H +#ifndef GUAC_RDP_PIPE_SVC_H +#define GUAC_RDP_PIPE_SVC_H #include "config.h" +#include "common-svc.h" #include #include @@ -34,15 +35,10 @@ #define GUAC_RDP_SVC_MAX_LENGTH 8 /** - * Structure describing a static virtual channel, and the corresponding - * Guacamole pipes and FreeRDP resources. + * Structure describing a static virtual channel and a corresponding Guacamole + * pipe stream; */ -typedef struct guac_rdp_svc { - - /** - * Reference to the client owning this static channel. - */ - guac_client* client; +typedef struct guac_rdp_pipe_svc { /** * The output pipe, opened when the RDP server receives a connection to @@ -51,46 +47,19 @@ typedef struct guac_rdp_svc { guac_stream* output_pipe; /** - * The definition of this static virtual channel, including its name. The - * name of the SVC is also used as the name of the associated Guacamole - * pipe streams. + * The underlying static channel. Data written to this SVC by the RDP + * server will be forwarded along the pipe stream to the Guacamole client, + * and data written to the pipe stream by the Guacamole client will be + * forwarded along the SVC to the RDP server. */ - CHANNEL_DEF channel_def; + guac_rdp_common_svc* svc; - /** - * Functions and data specific to the FreeRDP side of the virtual channel - * and plugin. - */ - CHANNEL_ENTRY_POINTS_FREERDP_EX entry_points; - - /** - * Handle which identifies the client connection, typically referred to - * within the FreeRDP source as pInitHandle. This handle is provided to the - * channel entry point and the channel init event handler. The handle must - * eventually be used within the channel open event handler to obtain a - * handle to the channel itself. - */ - PVOID init_handle; - - /** - * Handle which identifies the channel itself, typically referred to within - * the FreeRDP source as OpenHandle. This handle is obtained through a call - * to entry_points.pVirtualChannelOpenEx() in response to receiving a - * CHANNEL_EVENT_CONNECTED event via the init event handler. - * - * Data is received in CHANNEL_EVENT_DATA_RECEIVED events via the open - * event handler, and data is written through calls to - * entry_points.pVirtualChannelWriteEx(). - */ - DWORD open_handle; - -} guac_rdp_svc; +} guac_rdp_pipe_svc; /** - * Initializes arbitrary static virtual channel (SVC) support for RDP, loading - * a new instance of Guacamole's arbitrary SVC plugin for FreeRDP ("guacsvc") - * supporting the channel having the given name. Data sent from within the RDP - * session using this channel will be sent along an identically-named pipe + * Initializes arbitrary static virtual channel (SVC) support for RDP, handling + * communication for the SVC having the given name. Data sent from within the + * RDP session using this channel will be sent along an identically-named pipe * stream to the Guacamole client, and data sent along a pipe stream having the * same name will be written to the SVC and received within the RDP session. If * failures occur while loading the plugin, messages noting the specifics of @@ -104,10 +73,9 @@ typedef struct guac_rdp_svc { * The rdpContext associated with the FreeRDP side of the RDP connection. * * @param name - * The name of the SVC which should be handled by the new instance of the - * plugin. + * The name of the SVC which should be handled. */ -void guac_rdp_svc_load_plugin(rdpContext* context, char* name); +void guac_rdp_pipe_svc_load_plugin(rdpContext* context, char* name); /** * Sends the "pipe" instruction describing the given static virtual channel @@ -121,7 +89,7 @@ void guac_rdp_svc_load_plugin(rdpContext* context, char* name); * @param svc * The static virtual channel that the "pipe" instruction should describe. */ -void guac_rdp_svc_send_pipe(guac_socket* socket, guac_rdp_svc* svc); +void guac_rdp_pipe_svc_send_pipe(guac_socket* socket, guac_rdp_pipe_svc* svc); /** * Sends the "pipe" instructions describing all static virtual channels @@ -132,7 +100,7 @@ void guac_rdp_svc_send_pipe(guac_socket* socket, guac_rdp_svc* svc); * @param user * The user to send the "pipe" instructions to. */ -void guac_rdp_svc_send_pipes(guac_user* user); +void guac_rdp_pipe_svc_send_pipes(guac_user* user); /** * Add the given SVC to the list of all available SVCs. This function must be @@ -146,11 +114,11 @@ void guac_rdp_svc_send_pipes(guac_user* user); * The static virtual channel to add to the list of all such channels * available. */ -void guac_rdp_svc_add(guac_client* client, guac_rdp_svc* svc); +void guac_rdp_pipe_svc_add(guac_client* client, guac_rdp_pipe_svc* svc); /** * Retrieve the SVC with the given name from the list stored in the client. The - * requested SVC must previously have been added using guac_rdp_svc_add(). + * requested SVC must previously have been added using guac_rdp_pipe_svc_add(). * * @param client * The guac_client associated with the current RDP session. @@ -162,7 +130,7 @@ void guac_rdp_svc_add(guac_client* client, guac_rdp_svc* svc); * The static virtual channel with the given name, or NULL if no such * virtual channel exists. */ -guac_rdp_svc* guac_rdp_svc_get(guac_client* client, const char* name); +guac_rdp_pipe_svc* guac_rdp_pipe_svc_get(guac_client* client, const char* name); /** * Removes the SVC with the given name from the list stored in the client. @@ -179,37 +147,40 @@ guac_rdp_svc* guac_rdp_svc_get(guac_client* client, const char* name); * The static virtual channel that was removed, or NULL if no such virtual * channel exists. */ -guac_rdp_svc* guac_rdp_svc_remove(guac_client* client, const char* name); - -/** - * Writes the given blob of data to the virtual channel such that it can be - * received within the RDP session. - * - * @param svc - * The static virtual channel to write data to. - * - * @param data - * The data to write. - * - * @param length - * The number of bytes to write. - */ -void guac_rdp_svc_write(guac_rdp_svc* svc, void* data, int length); +guac_rdp_pipe_svc* guac_rdp_pipe_svc_remove(guac_client* client, const char* name); /** * Handler for "blob" instructions which automatically writes received data to - * the associated SVC using guac_rdp_svc_write(). + * the associated SVC using guac_rdp_pipe_svc_write(). */ -guac_user_blob_handler guac_rdp_svc_blob_handler; +guac_user_blob_handler guac_rdp_pipe_svc_blob_handler; /** * Handler for "pipe" instructions which automatically prepares received pipe * streams to automatically write received blobs to the SVC having the same * name as the pipe stream. Received pipe streams are associated with the - * relevant guac_rdp_svc instance and the SVC-specific "blob" instructino - * handler (guac_rdp_svc_blob_handler). + * relevant guac_rdp_pipe_svc instance and the SVC-specific "blob" instructino + * handler (guac_rdp_pipe_svc_blob_handler). */ -guac_user_pipe_handler guac_rdp_svc_pipe_handler; +guac_user_pipe_handler guac_rdp_pipe_svc_pipe_handler; + +/** + * Handler which is invoked when an SVC associated with a Guacamole pipe stream + * is connected to the RDP server. + */ +guac_rdp_common_svc_connect_handler guac_rdp_pipe_svc_process_connect; + +/** + * Handler which is invoked when an SVC associated with a Guacamole pipe stream + * received data from the RDP server. + */ +guac_rdp_common_svc_receive_handler guac_rdp_pipe_svc_process_receive; + +/** + * Handler which is invoked when an SVC associated with a Guacamole pipe stream + * has disconnected and is about to be freed. + */ +guac_rdp_common_svc_terminate_handler guac_rdp_pipe_svc_process_terminate; #endif diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 6d5d2254..b2423da8 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -29,6 +29,7 @@ #include "disp.h" #include "error.h" #include "keyboard.h" +#include "pipe-svc.h" #include "rail.h" #include "rdp.h" #include "rdp_bitmap.h" @@ -40,7 +41,6 @@ #include "rdp_stream.h" #include "rdpdr.h" #include "rdpsnd.h" -#include "svc.h" #ifdef ENABLE_COMMON_SSH #include "common-ssh/sftp.h" @@ -122,7 +122,7 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { char** current = settings->svc_names; do { - guac_rdp_svc_load_plugin(context, *current); + guac_rdp_pipe_svc_load_plugin(context, *current); } while (*(++current) != NULL); } diff --git a/src/protocols/rdp/user.c b/src/protocols/rdp/user.c index 47ba93ad..1fc1189e 100644 --- a/src/protocols/rdp/user.c +++ b/src/protocols/rdp/user.c @@ -23,10 +23,10 @@ #include "common/display.h" #include "input.h" #include "user.h" +#include "pipe-svc.h" #include "rdp.h" #include "rdp_settings.h" #include "rdp_stream.h" -#include "svc.h" #ifdef ENABLE_COMMON_SSH #include "sftp.h" @@ -86,7 +86,7 @@ int guac_rdp_user_join_handler(guac_user* user, int argc, char** argv) { guac_audio_stream_add_user(rdp_client->audio, user); /* Bring user up to date with any registered static channels */ - guac_rdp_svc_send_pipes(user); + guac_rdp_pipe_svc_send_pipes(user); /* Synchronize with current display */ guac_common_display_dup(rdp_client->display, user, user->socket); @@ -109,7 +109,7 @@ int guac_rdp_user_join_handler(guac_user* user, int argc, char** argv) { user->file_handler = guac_rdp_user_file_handler; /* Inbound arbitrary named pipes */ - user->pipe_handler = guac_rdp_svc_pipe_handler; + user->pipe_handler = guac_rdp_pipe_svc_pipe_handler; } From 4612e79b8db10196b221568aa17863af3f2488fc Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 22 Dec 2019 14:01:43 -0800 Subject: [PATCH 045/109] GUACAMOLE-249: Remove "guacsnd" plugin in favor of leveraging common SVC implementation. --- src/protocols/rdp/Makefile.am | 31 +- .../rdp/guac_rdpsnd/rdpsnd_service.c | 364 ------------------ .../rdp/guac_rdpsnd/rdpsnd_service.h | 165 -------- src/protocols/rdp/rdpsnd.c | 77 +++- src/protocols/rdp/rdpsnd.h | 101 +++++ .../rdp/{guac_rdpsnd => }/rdpsnd_messages.c | 53 +-- .../rdp/{guac_rdpsnd => }/rdpsnd_messages.h | 33 +- 7 files changed, 211 insertions(+), 613 deletions(-) delete mode 100644 src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c delete mode 100644 src/protocols/rdp/guac_rdpsnd/rdpsnd_service.h rename src/protocols/rdp/{guac_rdpsnd => }/rdpsnd_messages.c (86%) rename src/protocols/rdp/{guac_rdpsnd => }/rdpsnd_messages.h (88%) diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index 0df45a30..0a832514 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -63,6 +63,7 @@ libguac_client_rdp_la_SOURCES = \ rdp_stream.c \ rdpdr.c \ rdpsnd.c \ + rdpsnd_messages.c \ resolution.c \ unicode.c \ user.c @@ -78,8 +79,6 @@ noinst_HEADERS = \ guac_rdpdr/rdpdr_messages.h \ guac_rdpdr/rdpdr_printer.h \ guac_rdpdr/rdpdr_service.h \ - guac_rdpsnd/rdpsnd_messages.h \ - guac_rdpsnd/rdpsnd_service.h \ audio_input.h \ client.h \ clipboard.h \ @@ -107,6 +106,7 @@ noinst_HEADERS = \ rdp_stream.h \ rdpdr.h \ rdpsnd.h \ + rdpsnd_messages.h \ resolution.h \ unicode.h \ user.h @@ -135,8 +135,7 @@ libguac_client_rdp_la_LIBADD = \ freerdp_LTLIBRARIES = \ libguac-common-svc-client.la \ libguacai-client.la \ - libguacdr-client.la \ - libguacsnd-client.la + libguacdr-client.la freerdpdir = ${libdir}/freerdp2 @@ -219,30 +218,6 @@ libguacai_client_la_LIBADD = \ @COMMON_LTLIB@ \ @LIBGUAC_LTLIB@ -# -# RDPSND -# - -libguacsnd_client_la_SOURCES = \ - guac_rdpsnd/rdpsnd_messages.c \ - guac_rdpsnd/rdpsnd_service.c - -libguacsnd_client_la_CFLAGS = \ - -Werror -Wall -Iinclude \ - @COMMON_INCLUDE@ \ - @COMMON_SSH_INCLUDE@ \ - @LIBGUAC_INCLUDE@ \ - @RDP_CFLAGS@ - -libguacsnd_client_la_LDFLAGS = \ - -module -avoid-version -shared \ - @PTHREAD_LIBS@ \ - @RDP_LIBS@ - -libguacsnd_client_la_LIBADD = \ - @COMMON_LTLIB@ \ - @LIBGUAC_LTLIB@ - # # Optional SFTP support # diff --git a/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c b/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c deleted file mode 100644 index 88048a3a..00000000 --- a/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -#include "config.h" - -#include "rdpsnd_service.h" -#include "rdpsnd_messages.h" - -#include -#include - -#include -#include -#include - -/** - * Processes data received along the RDPSND channel via a - * CHANNEL_EVENT_DATA_RECEIVED event, forwarding the data along an established, - * outbound pipe stream to the Guacamole client. - * - * @param rdpsnd - * The guac_rdpsnd structure representing the RDPSND channel. - * - * @param input_stream - * The data that was received. - */ -static void guac_rdpsnd_process_receive(guac_rdpsnd* rdpsnd, - wStream* input_stream) { - - guac_rdpsnd_pdu_header header; - - /* Read RDPSND PDU header */ - Stream_Read_UINT8(input_stream, header.message_type); - Stream_Seek_UINT8(input_stream); - Stream_Read_UINT16(input_stream, header.body_size); - - /* - * If next PDU is SNDWAVE (due to receiving WaveInfo PDU previously), - * ignore the header and parse as a Wave PDU. - */ - if (rdpsnd->next_pdu_is_wave) { - guac_rdpsnd_wave_handler(rdpsnd, input_stream, &header); - return; - } - - /* Dispatch message to standard handlers */ - switch (header.message_type) { - - /* Server Audio Formats and Version PDU */ - case SNDC_FORMATS: - guac_rdpsnd_formats_handler(rdpsnd, input_stream, &header); - break; - - /* Training PDU */ - case SNDC_TRAINING: - guac_rdpsnd_training_handler(rdpsnd, input_stream, &header); - break; - - /* WaveInfo PDU */ - case SNDC_WAVE: - guac_rdpsnd_wave_info_handler(rdpsnd, input_stream, &header); - break; - - /* Close PDU */ - case SNDC_CLOSE: - guac_rdpsnd_close_handler(rdpsnd, input_stream, &header); - break; - - } - -} - -/** - * Event handler for events which deal with data transmitted over the RDPSND - * channel. This specific implementation of the event handler currently - * handles only the CHANNEL_EVENT_DATA_RECEIVED event, delegating actual - * handling of that event to guac_rdpsnd_process_receive(). - * - * The FreeRDP requirements for this function follow those of the - * VirtualChannelOpenEventEx callback defined within Microsoft's RDP API: - * - * https://docs.microsoft.com/en-us/previous-versions/windows/embedded/aa514754%28v%3dmsdn.10%29 - * - * @param user_param - * The pointer to arbitrary data originally passed via the first parameter - * of the pVirtualChannelInitEx() function call when the associated channel - * was initialized. The pVirtualChannelInitEx() function is exposed within - * the channel entry points structure. - * - * @param open_handle - * The handle which identifies the channel itself, typically referred to - * within the FreeRDP source as OpenHandle. - * - * @param event - * An integer representing the event that should be handled. This will be - * either CHANNEL_EVENT_DATA_RECEIVED, CHANNEL_EVENT_WRITE_CANCELLED, or - * CHANNEL_EVENT_WRITE_COMPLETE. - * - * @param data - * The data received, for CHANNEL_EVENT_DATA_RECEIVED events, and the value - * passed as user data to pVirtualChannelWriteEx() for - * CHANNEL_EVENT_WRITE_* events (note that user data for - * pVirtualChannelWriteEx() as implemented by FreeRDP MUST either be NULL - * or a wStream containing the data written). - * - * @param data_length - * The number of bytes of event-specific data. - * - * @param total_length - * The total number of bytes written to the RDP server in a single write - * operation. - * - * NOTE: The meaning of total_length is unclear. The above description was - * written mainly through referencing the documentation in MSDN. Real-world - * use will need to be consulted, likely within the FreeRDP source, before - * this value can be reliably used. The current implementation of this - * handler ignores this parameter. - * - * @param data_flags - * The result of a bitwise OR of the CHANNEL_FLAG_* flags which apply to - * the data received. This value is relevant only to - * CHANNEL_EVENT_DATA_RECEIVED events. Valid flags are CHANNEL_FLAG_FIRST, - * CHANNEL_FLAG_LAST, and CHANNEL_FLAG_ONLY. The flag CHANNEL_FLAG_MIDDLE - * is not itself a flag, but the absence of both CHANNEL_FLAG_FIRST and - * CHANNEL_FLAG_LAST. - */ -static VOID guac_rdpsnd_handle_open_event(LPVOID user_param, - DWORD open_handle, UINT event, LPVOID data, UINT32 data_length, - UINT32 total_length, UINT32 data_flags) { - - /* Ignore all events except for received data */ - if (event != CHANNEL_EVENT_DATA_RECEIVED) - return; - - guac_rdpsnd* rdpsnd = (guac_rdpsnd*) user_param; - - /* Validate relevant handle matches that of the RDPSND channel */ - if (open_handle != rdpsnd->open_handle) { - guac_client_log(rdpsnd->client, GUAC_LOG_WARNING, "%i bytes of data " - "received from within the remote desktop session for the " - "RDPSND channel are being dropped because the relevant open " - "handle (0x%X) does not match the open handle of RDPSND " - "(0x%X).", data_length, rdpsnd->channel_def.name, open_handle, - rdpsnd->open_handle); - return; - } - - /* If receiving first chunk, allocate sufficient space for all remaining - * chunks */ - if (data_flags & CHANNEL_FLAG_FIRST) { - - /* Limit maximum received size */ - if (total_length > GUAC_SVC_MAX_ASSEMBLED_LENGTH) { - guac_client_log(rdpsnd->client, GUAC_LOG_WARNING, "RDP server has " - "requested to send a sequence of %i bytes, but this " - "exceeds the maximum buffer space of %i bytes. Received " - "data may be truncated.", total_length, - GUAC_SVC_MAX_ASSEMBLED_LENGTH); - total_length = GUAC_SVC_MAX_ASSEMBLED_LENGTH; - } - - rdpsnd->input_stream = Stream_New(NULL, total_length); - } - - /* Add chunk to buffer only if sufficient space remains */ - if (Stream_EnsureRemainingCapacity(rdpsnd->input_stream, data_length)) - Stream_Write(rdpsnd->input_stream, data, data_length); - else - guac_client_log(rdpsnd->client, GUAC_LOG_WARNING, "%i bytes of data " - "received from within the remote desktop session for the " - "RDPSND channel are being dropped because the maximum " - "available space for received data has been exceeded.", - data_length, rdpsnd->channel_def.name, open_handle, - rdpsnd->open_handle); - - /* Fire event once last chunk has been received */ - if (data_flags & CHANNEL_FLAG_LAST) { - - Stream_SealLength(rdpsnd->input_stream); - Stream_SetPosition(rdpsnd->input_stream, 0); - - guac_rdpsnd_process_receive(rdpsnd, rdpsnd->input_stream); - - Stream_Free(rdpsnd->input_stream, TRUE); - - } - -} - -/** - * Processes a CHANNEL_EVENT_CONNECTED event, completing the - * connection/initialization process of the RDPSND channel. - * - * @param rdpsnd - * The guac_rdpsnd structure representing the RDPSND channel. - */ -static void guac_rdpsnd_process_connect(guac_rdpsnd* rdpsnd) { - - /* Open FreeRDP side of connected channel */ - UINT32 open_status = - rdpsnd->entry_points.pVirtualChannelOpenEx(rdpsnd->init_handle, - &rdpsnd->open_handle, rdpsnd->channel_def.name, - guac_rdpsnd_handle_open_event); - - /* Warn if the channel cannot be opened after all */ - if (open_status != CHANNEL_RC_OK) { - guac_client_log(rdpsnd->client, GUAC_LOG_WARNING, "RDPSND channel " - "could not be opened: %s (error %i)", - WTSErrorToString(open_status), open_status); - return; - } - - /* Log that sound has been loaded */ - guac_client_log(rdpsnd->client, GUAC_LOG_INFO, "RDPSND channel " - "connected."); - -} - -/** - * Processes a CHANNEL_EVENT_TERMINATED event, freeing all resources associated - * with the RDPSND channel. - * - * @param rdpsnd - * The guac_rdpsnd structure representing the RDPSND channel. - */ -static void guac_rdpsnd_process_terminate(guac_rdpsnd* rdpsnd) { - guac_client_log(rdpsnd->client, GUAC_LOG_INFO, "RDPSND channel disconnected."); - free(rdpsnd); -} - -/** - * Event handler for events which deal with the overall lifecycle of the RDPSND - * channel. This specific implementation of the event handler currently - * handles only CHANNEL_EVENT_CONNECTED and CHANNEL_EVENT_TERMINATED events, - * delegating actual handling of those events to guac_rdpsnd_process_connect() - * and guac_rdpsnd_process_terminate() respectively. - * - * The FreeRDP requirements for this function follow those of the - * VirtualChannelInitEventEx callback defined within Microsoft's RDP API: - * - * https://docs.microsoft.com/en-us/previous-versions/windows/embedded/aa514727%28v%3dmsdn.10%29 - * - * @param user_param - * The pointer to arbitrary data originally passed via the first parameter - * of the pVirtualChannelInitEx() function call when the associated channel - * was initialized. The pVirtualChannelInitEx() function is exposed within - * the channel entry points structure. - * - * @param init_handle - * The handle which identifies the client connection, typically referred to - * within the FreeRDP source as pInitHandle. - * - * @param event - * An integer representing the event that should be handled. This will be - * either CHANNEL_EVENT_CONNECTED, CHANNEL_EVENT_DISCONNECTED, - * CHANNEL_EVENT_INITIALIZED, CHANNEL_EVENT_TERMINATED, or - * CHANNEL_EVENT_V1_CONNECTED. - * - * @param data - * NULL in all cases except the CHANNEL_EVENT_CONNECTED event, in which - * case this is a null-terminated string containing the name of the server. - * - * @param data_length - * The number of bytes of data, if any. - */ -static VOID guac_rdpsnd_handle_init_event(LPVOID user_param, - LPVOID init_handle, UINT event, LPVOID data, UINT data_length) { - - guac_rdpsnd* rdpsnd = (guac_rdpsnd*) user_param; - - /* Validate relevant handle matches that of the RDPSND channel */ - if (init_handle != rdpsnd->init_handle) { - guac_client_log(rdpsnd->client, GUAC_LOG_WARNING, "An init event " - "(#%i) for the RDPSND channel has been dropped because the " - "relevant init handle (0x%X) does not match the init handle " - "of the RDPSND channel (0x%X).", event, init_handle, - rdpsnd->init_handle); - return; - } - - switch (event) { - - /* The RDPSND channel has been connected */ - case CHANNEL_EVENT_CONNECTED: - guac_rdpsnd_process_connect(rdpsnd); - break; - - /* The RDPSND channel has disconnected and now must be cleaned up */ - case CHANNEL_EVENT_TERMINATED: - guac_rdpsnd_process_terminate(rdpsnd); - break; - - } - -} - -/** - * Entry point for FreeRDP plugins. This function is automatically invoked when - * the plugin is loaded. - * - * @param entry_points - * Functions and data specific to the FreeRDP side of the virtual channel - * and plugin. This structure must be copied within implementation-specific - * storage such that the functions it references can be invoked when - * needed. - * - * @param init_handle - * The handle which identifies the client connection, typically referred to - * within the FreeRDP source as pInitHandle. This handle is also provided - * to the channel init event handler. The handle must eventually be used - * within the channel open event handler to obtain a handle to the channel - * itself. - * - * @return - * TRUE if the plugin has initialized successfully, FALSE otherwise. - */ -BOOL VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS entry_points, - PVOID init_handle) { - - CHANNEL_ENTRY_POINTS_FREERDP_EX* entry_points_ex = - (CHANNEL_ENTRY_POINTS_FREERDP_EX*) entry_points; - - /* Allocate plugin */ - guac_rdpsnd* rdpsnd = (guac_rdpsnd*) calloc(1, sizeof(guac_rdpsnd)); - - /* Init channel def */ - strcpy(rdpsnd->channel_def.name, "rdpsnd"); - rdpsnd->channel_def.options = CHANNEL_OPTION_INITIALIZED - | CHANNEL_OPTION_ENCRYPT_RDP; - - /* Maintain reference to associated guac_client */ - rdpsnd->client = (guac_client*) entry_points_ex->pExtendedData; - - /* Copy FreeRDP data into RDPSND structure for future reference */ - rdpsnd->entry_points = *entry_points_ex; - rdpsnd->init_handle = init_handle; - - /* Complete initialization */ - if (rdpsnd->entry_points.pVirtualChannelInitEx(rdpsnd, rdpsnd, init_handle, - &rdpsnd->channel_def, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, - guac_rdpsnd_handle_init_event) != CHANNEL_RC_OK) { - return FALSE; - } - - return TRUE; - -} - diff --git a/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.h b/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.h deleted file mode 100644 index f78df847..00000000 --- a/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - - -#ifndef GUAC_RDPSND_SERVICE_H -#define GUAC_RDPSND_SERVICE_H - -#include "config.h" - -#include -#include -#include -#include - -/** - * The maximum number of PCM formats to accept during the initial RDPSND - * handshake with the RDP server. - */ -#define GUAC_RDP_MAX_FORMATS 16 - -/** - * The maximum number of bytes that the RDP server will be allowed to send - * within any single write operation, regardless of the number of chunks that - * write is split into. Bytes beyond this limit may be dropped. - */ -#define GUAC_SVC_MAX_ASSEMBLED_LENGTH 1048576 - -/** - * Abstract representation of a PCM format, including the sample rate, number - * of channels, and bits per sample. - */ -typedef struct guac_pcm_format { - - /** - * The sample rate of this PCM format. - */ - int rate; - - /** - * The number off channels used by this PCM format. This will typically - * be 1 or 2. - */ - int channels; - - /** - * The number of bits per sample within this PCM format. This should be - * either 8 or 16. - */ - int bps; - -} guac_pcm_format; - -/** - * Structure representing the current state of the Guacamole RDPSND plugin for - * FreeRDP. - */ -typedef struct guac_rdpsnd { - - /** - * The Guacamole client associated with the guac_audio_stream that this - * plugin should use to stream received audio packets. - */ - guac_client* client; - - /** - * The definition of this virtual channel (RDPSND). - */ - CHANNEL_DEF channel_def; - - /** - * Functions and data specific to the FreeRDP side of the virtual channel - * and plugin. - */ - CHANNEL_ENTRY_POINTS_FREERDP_EX entry_points; - - /** - * Handle which identifies the client connection, typically referred to - * within the FreeRDP source as pInitHandle. This handle is provided to the - * channel entry point and the channel init event handler. The handle must - * eventually be used within the channel open event handler to obtain a - * handle to the channel itself. - */ - PVOID init_handle; - - /** - * Handle which identifies the channel itself, typically referred to within - * the FreeRDP source as OpenHandle. This handle is obtained through a call - * to entry_points.pVirtualChannelOpenEx() in response to receiving a - * CHANNEL_EVENT_CONNECTED event via the init event handler. - * - * Data is received in CHANNEL_EVENT_DATA_RECEIVED events via the open - * event handler, and data is written through calls to - * entry_points.pVirtualChannelWriteEx(). - */ - DWORD open_handle; - - /** - * All data that has been received thus far from the current RDP server - * write operation. Data received along virtual channels is sent in chunks - * (typically 1600 bytes), and thus must be gradually reassembled as it is - * received. - */ - wStream* input_stream; - - /** - * The block number of the last SNDC_WAVE (WaveInfo) PDU received. - */ - int waveinfo_block_number; - - /** - * Whether the next PDU coming is a SNDWAVE (Wave) PDU. Wave PDUs do not - * have headers, and are indicated by the receipt of a WaveInfo PDU. - */ - int next_pdu_is_wave; - - /** - * The wave data received within the last SNDC_WAVE (WaveInfo) PDU. - */ - unsigned char initial_wave_data[4]; - - /** - * The size, in bytes, of the wave data in the coming Wave PDU, if any. - * This does not include the initial wave data received within the last - * SNDC_WAVE (WaveInfo) PDU, which is always the first four bytes of the - * actual wave data block. - */ - int incoming_wave_size; - - /** - * The last received server timestamp. - */ - int server_timestamp; - - /** - * All formats agreed upon by server and client during the initial format - * exchange. All of these formats will be PCM, which is the only format - * guaranteed to be supported (based on the official RDP documentation). - */ - guac_pcm_format formats[GUAC_RDP_MAX_FORMATS]; - - /** - * The total number of formats. - */ - int format_count; - -} guac_rdpsnd; - -#endif - diff --git a/src/protocols/rdp/rdpsnd.c b/src/protocols/rdp/rdpsnd.c index 23b31336..0e1d2369 100644 --- a/src/protocols/rdp/rdpsnd.c +++ b/src/protocols/rdp/rdpsnd.c @@ -18,26 +18,89 @@ */ #include "config.h" -#include "channels.h" +#include "common-svc.h" #include "rdp.h" +#include "rdpsnd.h" +#include "rdpsnd_messages.h" #include #include +#include +#include + +#include + +void guac_rdpsnd_process_receive(guac_rdp_common_svc* svc, + wStream* input_stream) { + + guac_rdpsnd* rdpsnd = (guac_rdpsnd*) svc->data; + guac_rdpsnd_pdu_header header; + + /* Read RDPSND PDU header */ + Stream_Read_UINT8(input_stream, header.message_type); + Stream_Seek_UINT8(input_stream); + Stream_Read_UINT16(input_stream, header.body_size); + + /* + * If next PDU is SNDWAVE (due to receiving WaveInfo PDU previously), + * ignore the header and parse as a Wave PDU. + */ + if (rdpsnd->next_pdu_is_wave) { + guac_rdpsnd_wave_handler(svc, input_stream, &header); + return; + } + + /* Dispatch message to standard handlers */ + switch (header.message_type) { + + /* Server Audio Formats and Version PDU */ + case SNDC_FORMATS: + guac_rdpsnd_formats_handler(svc, input_stream, &header); + break; + + /* Training PDU */ + case SNDC_TRAINING: + guac_rdpsnd_training_handler(svc, input_stream, &header); + break; + + /* WaveInfo PDU */ + case SNDC_WAVE: + guac_rdpsnd_wave_info_handler(svc, input_stream, &header); + break; + + /* Close PDU */ + case SNDC_CLOSE: + guac_rdpsnd_close_handler(svc, input_stream, &header); + break; + + } + +} + +void guac_rdpsnd_process_connect(guac_rdp_common_svc* svc) { + + guac_rdpsnd* rdpsnd = (guac_rdpsnd*) calloc(1, sizeof(guac_rdpsnd)); + svc->data = rdpsnd; + +} + +void guac_rdpsnd_process_terminate(guac_rdp_common_svc* svc) { + guac_rdpsnd* rdpsnd = (guac_rdpsnd*) svc->data; + free(rdpsnd); +} void guac_rdpsnd_load_plugin(rdpContext* context) { guac_client* client = ((rdp_freerdp_context*) context)->client; - /* Load RDPSND plugin */ - if (guac_freerdp_channels_load_plugin(context->channels, context->settings, "guacsnd", client)) { + /* Load support for RDPSND */ + if (guac_rdp_common_svc_load_plugin(context, "rdpsnd", 0, + guac_rdpsnd_process_connect, guac_rdpsnd_process_receive, + guac_rdpsnd_process_terminate)) { guac_client_log(client, GUAC_LOG_WARNING, "Support for the RDPSND " "channel (audio output) could not be loaded. Sound will not " "work. Drive redirection and printing MAY not work."); - return; } - guac_client_log(client, GUAC_LOG_DEBUG, "Support for RDPSND (audio " - "output) registered. Awaiting channel connection."); - } diff --git a/src/protocols/rdp/rdpsnd.h b/src/protocols/rdp/rdpsnd.h index 51e86150..deec0de3 100644 --- a/src/protocols/rdp/rdpsnd.h +++ b/src/protocols/rdp/rdpsnd.h @@ -21,6 +21,89 @@ #define GUAC_RDP_RDPSND_H #include "config.h" +#include "common-svc.h" + +#include + +/** + * The maximum number of PCM formats to accept during the initial RDPSND + * handshake with the RDP server. + */ +#define GUAC_RDP_MAX_FORMATS 16 + +/** + * Abstract representation of a PCM format, including the sample rate, number + * of channels, and bits per sample. + */ +typedef struct guac_rdpsnd_pcm_format { + + /** + * The sample rate of this PCM format. + */ + int rate; + + /** + * The number off channels used by this PCM format. This will typically + * be 1 or 2. + */ + int channels; + + /** + * The number of bits per sample within this PCM format. This should be + * either 8 or 16. + */ + int bps; + +} guac_rdpsnd_pcm_format; + +/** + * Structure representing the current state of the Guacamole RDPSND plugin for + * FreeRDP. + */ +typedef struct guac_rdpsnd { + + /** + * The block number of the last SNDC_WAVE (WaveInfo) PDU received. + */ + int waveinfo_block_number; + + /** + * Whether the next PDU coming is a SNDWAVE (Wave) PDU. Wave PDUs do not + * have headers, and are indicated by the receipt of a WaveInfo PDU. + */ + int next_pdu_is_wave; + + /** + * The wave data received within the last SNDC_WAVE (WaveInfo) PDU. + */ + unsigned char initial_wave_data[4]; + + /** + * The size, in bytes, of the wave data in the coming Wave PDU, if any. + * This does not include the initial wave data received within the last + * SNDC_WAVE (WaveInfo) PDU, which is always the first four bytes of the + * actual wave data block. + */ + int incoming_wave_size; + + /** + * The last received server timestamp. + */ + int server_timestamp; + + /** + * All formats agreed upon by server and client during the initial format + * exchange. All of these formats will be PCM, which is the only format + * guaranteed to be supported (based on the official RDP documentation). + */ + guac_rdpsnd_pcm_format formats[GUAC_RDP_MAX_FORMATS]; + + /** + * The total number of formats. + */ + int format_count; + +} guac_rdpsnd; /** * Initializes audio output support for RDP and handling of the RDPSND channel. @@ -35,5 +118,23 @@ */ void guac_rdpsnd_load_plugin(rdpContext* context); +/** + * Handler which is invoked when the RDPSND channel is connected to the RDP + * server. + */ +guac_rdp_common_svc_connect_handler guac_rdpsnd_process_connect; + +/** + * Handler which is invoked when the RDPSND channel has received data from the + * RDP server. + */ +guac_rdp_common_svc_receive_handler guac_rdpsnd_process_receive; + +/** + * Handler which is invoked when the RDPSND channel has disconnected and is + * about to be freed. + */ +guac_rdp_common_svc_terminate_handler guac_rdpsnd_process_terminate; + #endif diff --git a/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.c b/src/protocols/rdp/rdpsnd_messages.c similarity index 86% rename from src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.c rename to src/protocols/rdp/rdpsnd_messages.c index 90c59a18..0102e283 100644 --- a/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.c +++ b/src/protocols/rdp/rdpsnd_messages.c @@ -20,8 +20,8 @@ #include "config.h" #include "rdp.h" +#include "rdpsnd.h" #include "rdpsnd_messages.h" -#include "rdpsnd_service.h" #include #include @@ -31,9 +31,7 @@ #include #include -/* MESSAGE HANDLERS */ - -void guac_rdpsnd_formats_handler(guac_rdpsnd* rdpsnd, +void guac_rdpsnd_formats_handler(guac_rdp_common_svc* svc, wStream* input_stream, guac_rdpsnd_pdu_header* header) { int server_format_count; @@ -44,11 +42,10 @@ void guac_rdpsnd_formats_handler(guac_rdpsnd* rdpsnd, int output_body_size; unsigned char* output_stream_end; - /* Get associated client data */ - guac_client* client = rdpsnd->client; - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + guac_client* client = svc->client; + guac_rdpsnd* rdpsnd = (guac_rdpsnd*) svc->data; - /* Get audio stream from client data */ + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_audio_stream* audio = rdp_client->audio; /* Reset own format count */ @@ -181,9 +178,7 @@ void guac_rdpsnd_formats_handler(guac_rdpsnd* rdpsnd, Stream_SetPointer(output_stream, output_stream_end); /* Send accepted formats */ - rdpsnd->entry_points.pVirtualChannelWriteEx(rdpsnd->init_handle, - rdpsnd->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); /* If version greater than 6, must send Quality Mode PDU */ if (server_version >= 6) { @@ -196,21 +191,21 @@ void guac_rdpsnd_formats_handler(guac_rdpsnd* rdpsnd, Stream_Write_UINT16(output_stream, HIGH_QUALITY); Stream_Write_UINT16(output_stream, 0); - rdpsnd->entry_points.pVirtualChannelWriteEx(rdpsnd->init_handle, - rdpsnd->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } } /* server is getting a feel of the round trip time */ -void guac_rdpsnd_training_handler(guac_rdpsnd* rdpsnd, +void guac_rdpsnd_training_handler(guac_rdp_common_svc* svc, wStream* input_stream, guac_rdpsnd_pdu_header* header) { int data_size; wStream* output_stream; + guac_rdpsnd* rdpsnd = (guac_rdpsnd*) svc->data; + /* Read timestamp and data size */ Stream_Read_UINT16(input_stream, rdpsnd->server_timestamp); Stream_Read_UINT16(input_stream, data_size); @@ -223,22 +218,19 @@ void guac_rdpsnd_training_handler(guac_rdpsnd* rdpsnd, Stream_Write_UINT16(output_stream, rdpsnd->server_timestamp); Stream_Write_UINT16(output_stream, data_size); - rdpsnd->entry_points.pVirtualChannelWriteEx(rdpsnd->init_handle, - rdpsnd->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -void guac_rdpsnd_wave_info_handler(guac_rdpsnd* rdpsnd, +void guac_rdpsnd_wave_info_handler(guac_rdp_common_svc* svc, wStream* input_stream, guac_rdpsnd_pdu_header* header) { int format; - /* Get associated client data */ - guac_client* client = rdpsnd->client; - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + guac_client* client = svc->client; + guac_rdpsnd* rdpsnd = (guac_rdpsnd*) svc->data; - /* Get audio stream from client data */ + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_audio_stream* audio = rdp_client->audio; /* Read wave information */ @@ -267,14 +259,13 @@ void guac_rdpsnd_wave_info_handler(guac_rdpsnd* rdpsnd, } -void guac_rdpsnd_wave_handler(guac_rdpsnd* rdpsnd, +void guac_rdpsnd_wave_handler(guac_rdp_common_svc* svc, wStream* input_stream, guac_rdpsnd_pdu_header* header) { - /* Get associated client data */ - guac_client* client = rdpsnd->client; - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + guac_client* client = svc->client; + guac_rdpsnd* rdpsnd = (guac_rdpsnd*) svc->data; - /* Get audio stream from client data */ + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_audio_stream* audio = rdp_client->audio; /* Wave Confirmation PDU */ @@ -302,16 +293,14 @@ void guac_rdpsnd_wave_handler(guac_rdpsnd* rdpsnd, Stream_Write_UINT8(output_stream, 0); /* Send Wave Confirmation PDU */ - rdpsnd->entry_points.pVirtualChannelWriteEx(rdpsnd->init_handle, - rdpsnd->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); /* We no longer expect to receive wave data */ rdpsnd->next_pdu_is_wave = FALSE; } -void guac_rdpsnd_close_handler(guac_rdpsnd* rdpsnd, +void guac_rdpsnd_close_handler(guac_rdp_common_svc* svc, wStream* input_stream, guac_rdpsnd_pdu_header* header) { /* Do nothing */ diff --git a/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.h b/src/protocols/rdp/rdpsnd_messages.h similarity index 88% rename from src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.h rename to src/protocols/rdp/rdpsnd_messages.h index 700c41b6..91d0223b 100644 --- a/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.h +++ b/src/protocols/rdp/rdpsnd_messages.h @@ -22,8 +22,7 @@ #define GUAC_RDPSND_MESSAGES_H #include "config.h" - -#include "rdpsnd_service.h" +#include "common-svc.h" #include @@ -117,8 +116,8 @@ typedef struct guac_rdpsnd_pdu_header { * SNDC_FORMATS PDU describes all audio formats supported by the RDP server, as * well as the version of RDPSND implemented. * - * @param rdpsnd - * The Guacamole RDPSND plugin receiving the SNDC_FORMATS PDU. + * @param svc + * The RDPSND channel receiving the SNDC_FORMATS PDU. * * @param input_stream * The FreeRDP input stream containing the remaining raw bytes (after the @@ -128,7 +127,7 @@ typedef struct guac_rdpsnd_pdu_header { * The header content of the SNDC_FORMATS PDU. All RDPSND messages contain * the same header information. */ -void guac_rdpsnd_formats_handler(guac_rdpsnd* rdpsnd, +void guac_rdpsnd_formats_handler(guac_rdp_common_svc* svc, wStream* input_stream, guac_rdpsnd_pdu_header* header); /** @@ -138,8 +137,8 @@ void guac_rdpsnd_formats_handler(guac_rdpsnd* rdpsnd, * * https://msdn.microsoft.com/en-us/library/cc240961.aspx * - * @param rdpsnd - * The Guacamole RDPSND plugin receiving the SNDC_TRAINING PDU. + * @param svc + * The RDPSND channel receiving the SNDC_TRAINING PDU. * * @param input_stream * The FreeRDP input stream containing the remaining raw bytes (after the @@ -149,7 +148,7 @@ void guac_rdpsnd_formats_handler(guac_rdpsnd* rdpsnd, * The header content of the SNDC_TRAINING PDU. All RDPSND messages contain * the same header information. */ -void guac_rdpsnd_training_handler(guac_rdpsnd* rdpsnd, +void guac_rdpsnd_training_handler(guac_rdp_common_svc* svc, wStream* input_stream, guac_rdpsnd_pdu_header* header); /** @@ -161,8 +160,8 @@ void guac_rdpsnd_training_handler(guac_rdpsnd* rdpsnd, * * https://msdn.microsoft.com/en-us/library/cc240963.aspx * - * @param rdpsnd - * The Guacamole RDPSND plugin receiving the SNDC_WAVE PDU. + * @param svc + * The RDPSND channel receiving the SNDC_WAVE PDU. * * @param input_stream * The FreeRDP input stream containing the remaining raw bytes (after the @@ -172,7 +171,7 @@ void guac_rdpsnd_training_handler(guac_rdpsnd* rdpsnd, * The header content of the SNDC_WAVE PDU. All RDPSND messages contain * the same header information. */ -void guac_rdpsnd_wave_info_handler(guac_rdpsnd* rdpsnd, +void guac_rdpsnd_wave_info_handler(guac_rdp_common_svc* svc, wStream* input_stream, guac_rdpsnd_pdu_header* header); /** @@ -180,8 +179,8 @@ void guac_rdpsnd_wave_info_handler(guac_rdpsnd* rdpsnd, * PDU contains the actual audio data, less the four bytes of audio data * included in the SNDC_WAVE PDU. * - * @param rdpsnd - * The Guacamole RDPSND plugin receiving the SNDWAV PDU. + * @param svc + * The RDPSND channel receiving the SNDWAV PDU. * * @param input_stream * The FreeRDP input stream containing the remaining raw bytes (after the @@ -191,7 +190,7 @@ void guac_rdpsnd_wave_info_handler(guac_rdpsnd* rdpsnd, * The header content of the SNDWAV PDU. All RDPSND messages contain * the same header information. */ -void guac_rdpsnd_wave_handler(guac_rdpsnd* rdpsnd, +void guac_rdpsnd_wave_handler(guac_rdp_common_svc* svc, wStream* input_stream, guac_rdpsnd_pdu_header* header); /** @@ -200,8 +199,8 @@ void guac_rdpsnd_wave_handler(guac_rdpsnd* rdpsnd, * * https://msdn.microsoft.com/en-us/library/cc240970.aspx * - * @param rdpsnd - * The Guacamole RDPSND plugin receiving the SNDC_CLOSE PDU. + * @param svc + * The RDPSND channel receiving the SNDC_CLOSE PDU. * * @param input_stream * The FreeRDP input stream containing the remaining raw bytes (after the @@ -211,7 +210,7 @@ void guac_rdpsnd_wave_handler(guac_rdpsnd* rdpsnd, * The header content of the SNDC_CLOSE PDU. All RDPSND messages contain * the same header information. */ -void guac_rdpsnd_close_handler(guac_rdpsnd* rdpsnd, +void guac_rdpsnd_close_handler(guac_rdp_common_svc* svc, wStream* input_stream, guac_rdpsnd_pdu_header* header); #endif From 664586ea544e189eb5eb392dbaaa71867c002b7b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 22 Dec 2019 17:33:35 -0800 Subject: [PATCH 046/109] GUACAMOLE-249: VirtualChannelEntryEx entry point is supposed to accept a PCHANNEL_ENTRY_POINTS_EX. --- src/protocols/rdp/Makefile.am | 119 ++--- .../rdp/guac-common-svc/common-svc-main.c | 2 +- src/protocols/rdp/guac_rdpdr/rdpdr_service.c | 500 ------------------ src/protocols/rdp/guac_rdpdr/rdpdr_service.h | 183 ------- src/protocols/rdp/rdpdr.c | 250 ++++++++- src/protocols/rdp/rdpdr.h | 133 +++++ .../rdp/{guac_rdpdr => }/rdpdr_fs_messages.c | 178 +++---- .../rdp/{guac_rdpdr => }/rdpdr_fs_messages.h | 66 ++- .../rdpdr_fs_messages_dir_info.c | 47 +- .../rdpdr_fs_messages_dir_info.h | 28 +- .../rdpdr_fs_messages_file_info.c | 93 ++-- .../rdpdr_fs_messages_file_info.h | 48 +- .../rdpdr_fs_messages_vol_info.c | 58 +- .../rdpdr_fs_messages_vol_info.h | 32 +- .../rdp/{guac_rdpdr => }/rdpdr_fs_service.c | 56 +- .../rdp/{guac_rdpdr => }/rdpdr_fs_service.h | 9 +- .../rdp/{guac_rdpdr => }/rdpdr_messages.c | 95 ++-- .../rdp/{guac_rdpdr => }/rdpdr_messages.h | 23 +- .../rdp/{guac_rdpdr => }/rdpdr_printer.c | 56 +- .../rdp/{guac_rdpdr => }/rdpdr_printer.h | 9 +- 20 files changed, 830 insertions(+), 1155 deletions(-) delete mode 100644 src/protocols/rdp/guac_rdpdr/rdpdr_service.c delete mode 100644 src/protocols/rdp/guac_rdpdr/rdpdr_service.h rename src/protocols/rdp/{guac_rdpdr => }/rdpdr_fs_messages.c (69%) rename src/protocols/rdp/{guac_rdpdr => }/rdpdr_fs_messages.h (58%) rename src/protocols/rdp/{guac_rdpdr => }/rdpdr_fs_messages_dir_info.c (80%) rename src/protocols/rdp/{guac_rdpdr => }/rdpdr_fs_messages_dir_info.h (68%) rename src/protocols/rdp/{guac_rdpdr => }/rdpdr_fs_messages_file_info.c (67%) rename src/protocols/rdp/{guac_rdpdr => }/rdpdr_fs_messages_file_info.h (61%) rename src/protocols/rdp/{guac_rdpdr => }/rdpdr_fs_messages_vol_info.c (66%) rename src/protocols/rdp/{guac_rdpdr => }/rdpdr_fs_messages_vol_info.h (61%) rename src/protocols/rdp/{guac_rdpdr => }/rdpdr_fs_service.c (65%) rename src/protocols/rdp/{guac_rdpdr => }/rdpdr_fs_service.h (91%) rename src/protocols/rdp/{guac_rdpdr => }/rdpdr_messages.c (68%) rename src/protocols/rdp/{guac_rdpdr => }/rdpdr_messages.h (87%) rename src/protocols/rdp/{guac_rdpdr => }/rdpdr_printer.c (76%) rename src/protocols/rdp/{guac_rdpdr => }/rdpdr_printer.h (88%) diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index 0a832514..8657420e 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -36,49 +36,48 @@ SUBDIRS = . tests nodist_libguac_client_rdp_la_SOURCES = \ _generated_keymaps.c -libguac_client_rdp_la_SOURCES = \ - audio_input.c \ - channels.c \ - client.c \ - clipboard.c \ - common-svc.c \ - decompose.c \ - disp.c \ - error.c \ - input.c \ - keyboard.c \ - pipe-svc.c \ - ptr_string.c \ - rail.c \ - rdp.c \ - rdp_bitmap.c \ - rdp_color.c \ - rdp_fs.c \ - rdp_gdi.c \ - rdp_glyph.c \ - rdp_keymap.c \ - rdp_print_job.c \ - rdp_pointer.c \ - rdp_settings.c \ - rdp_stream.c \ - rdpdr.c \ - rdpsnd.c \ - rdpsnd_messages.c \ - resolution.c \ - unicode.c \ +libguac_client_rdp_la_SOURCES = \ + audio_input.c \ + channels.c \ + client.c \ + clipboard.c \ + common-svc.c \ + decompose.c \ + disp.c \ + error.c \ + input.c \ + keyboard.c \ + pipe-svc.c \ + ptr_string.c \ + rail.c \ + rdp.c \ + rdp_bitmap.c \ + rdp_color.c \ + rdp_fs.c \ + rdp_gdi.c \ + rdp_glyph.c \ + rdp_keymap.c \ + rdp_print_job.c \ + rdp_pointer.c \ + rdp_settings.c \ + rdp_stream.c \ + rdpdr.c \ + rdpdr_fs_messages.c \ + rdpdr_fs_messages_dir_info.c \ + rdpdr_fs_messages_file_info.c \ + rdpdr_fs_messages_vol_info.c \ + rdpdr_fs_service.c \ + rdpdr_messages.c \ + rdpdr_printer.c \ + rdpsnd.c \ + rdpsnd_messages.c \ + resolution.c \ + unicode.c \ user.c noinst_HEADERS = \ guac_ai/ai_messages.h \ guac_ai/ai_service.h \ - guac_rdpdr/rdpdr_fs_messages.h \ - guac_rdpdr/rdpdr_fs_messages_dir_info.h \ - guac_rdpdr/rdpdr_fs_messages_file_info.h \ - guac_rdpdr/rdpdr_fs_messages_vol_info.h \ - guac_rdpdr/rdpdr_fs_service.h \ - guac_rdpdr/rdpdr_messages.h \ - guac_rdpdr/rdpdr_printer.h \ - guac_rdpdr/rdpdr_service.h \ audio_input.h \ client.h \ clipboard.h \ @@ -105,6 +104,13 @@ noinst_HEADERS = \ rdp_status.h \ rdp_stream.h \ rdpdr.h \ + rdpdr_fs_messages.h \ + rdpdr_fs_messages_dir_info.h \ + rdpdr_fs_messages_file_info.h \ + rdpdr_fs_messages_vol_info.h \ + rdpdr_fs_service.h \ + rdpdr_messages.h \ + rdpdr_printer.h \ rdpsnd.h \ rdpsnd_messages.h \ resolution.h \ @@ -134,8 +140,7 @@ libguac_client_rdp_la_LIBADD = \ freerdp_LTLIBRARIES = \ libguac-common-svc-client.la \ - libguacai-client.la \ - libguacdr-client.la + libguacai-client.la freerdpdir = ${libdir}/freerdp2 @@ -158,40 +163,6 @@ libguac_common_svc_client_la_LDFLAGS = \ libguac_common_svc_client_la_LIBADD = \ @LIBGUAC_LTLIB@ -# -# RDPDR -# - -libguacdr_client_la_SOURCES = \ - guac_rdpdr/rdpdr_fs_messages.c \ - guac_rdpdr/rdpdr_fs_messages_dir_info.c \ - guac_rdpdr/rdpdr_fs_messages_file_info.c \ - guac_rdpdr/rdpdr_fs_messages_vol_info.c \ - guac_rdpdr/rdpdr_fs_service.c \ - guac_rdpdr/rdpdr_messages.c \ - guac_rdpdr/rdpdr_printer.c \ - guac_rdpdr/rdpdr_service.c \ - rdp_fs.c \ - rdp_print_job.c \ - rdp_stream.c \ - unicode.c - -libguacdr_client_la_CFLAGS = \ - -Werror -Wall -Iinclude \ - @COMMON_INCLUDE@ \ - @COMMON_SSH_INCLUDE@ \ - @LIBGUAC_INCLUDE@ \ - @RDP_CFLAGS@ - -libguacdr_client_la_LDFLAGS = \ - -module -avoid-version -shared \ - @PTHREAD_LIBS@ \ - @RDP_LIBS@ - -libguacdr_client_la_LIBADD = \ - @COMMON_LTLIB@ \ - @LIBGUAC_LTLIB@ - # # Audio Input # diff --git a/src/protocols/rdp/guac-common-svc/common-svc-main.c b/src/protocols/rdp/guac-common-svc/common-svc-main.c index 441823b7..572a1d2c 100644 --- a/src/protocols/rdp/guac-common-svc/common-svc-main.c +++ b/src/protocols/rdp/guac-common-svc/common-svc-main.c @@ -283,7 +283,7 @@ static VOID guac_rdp_common_svc_handle_init_event(LPVOID user_param, * @return * TRUE if the plugin has initialized successfully, FALSE otherwise. */ -BOOL VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS entry_points, +BOOL VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX entry_points, PVOID init_handle) { CHANNEL_ENTRY_POINTS_FREERDP_EX* entry_points_ex = diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_service.c b/src/protocols/rdp/guac_rdpdr/rdpdr_service.c deleted file mode 100644 index d20f7d83..00000000 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_service.c +++ /dev/null @@ -1,500 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -#include "config.h" - -#include "rdp.h" -#include "rdp_fs.h" -#include "rdp_settings.h" -#include "rdp_stream.h" -#include "rdpdr_fs_service.h" -#include "rdpdr_messages.h" -#include "rdpdr_printer.h" -#include "rdpdr_service.h" - -#include -#include - -#include -#include -#include -#include -#include -#include - -/** - * Processes data received along the RDPDR channel via a - * CHANNEL_EVENT_DATA_RECEIVED event, forwarding the data along an established, - * outbound pipe stream to the Guacamole client. - * - * @param rdpdr - * The guac_rdpdr structure representing the RDPDR channel. - * - * @param input_stream - * The data that was received. - */ -static void guac_rdpdr_process_receive(guac_rdpdr* rdpdr, - wStream* input_stream) { - - int component; - int packet_id; - - /* Read header */ - Stream_Read_UINT16(input_stream, component); - Stream_Read_UINT16(input_stream, packet_id); - - /* Core component */ - if (component == RDPDR_CTYP_CORE) { - - /* Dispatch handlers based on packet ID */ - switch (packet_id) { - - case PAKID_CORE_SERVER_ANNOUNCE: - guac_rdpdr_process_server_announce(rdpdr, input_stream); - break; - - case PAKID_CORE_CLIENTID_CONFIRM: - guac_rdpdr_process_clientid_confirm(rdpdr, input_stream); - break; - - case PAKID_CORE_DEVICE_REPLY: - guac_rdpdr_process_device_reply(rdpdr, input_stream); - break; - - case PAKID_CORE_DEVICE_IOREQUEST: - guac_rdpdr_process_device_iorequest(rdpdr, input_stream); - break; - - case PAKID_CORE_SERVER_CAPABILITY: - guac_rdpdr_process_server_capability(rdpdr, input_stream); - break; - - case PAKID_CORE_USER_LOGGEDON: - guac_rdpdr_process_user_loggedon(rdpdr, input_stream); - break; - - default: - guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Ignoring RDPDR core packet with unexpected ID: 0x%04x", packet_id); - - } - - } /* end if core */ - - /* Printer component */ - else if (component == RDPDR_CTYP_PRN) { - - /* Dispatch handlers based on packet ID */ - switch (packet_id) { - - case PAKID_PRN_CACHE_DATA: - guac_rdpdr_process_prn_cache_data(rdpdr, input_stream); - break; - - case PAKID_PRN_USING_XPS: - guac_rdpdr_process_prn_using_xps(rdpdr, input_stream); - break; - - default: - guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Ignoring RDPDR printer packet with unexpected ID: 0x%04x", packet_id); - - } - - } /* end if printer */ - - else - guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Ignoring packet for unknown RDPDR component: 0x%04x", component); - -} - -wStream* guac_rdpdr_new_io_completion(guac_rdpdr_device* device, - int completion_id, int status, int size) { - - wStream* output_stream = Stream_New(NULL, 16+size); - - /* Write header */ - Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE); - Stream_Write_UINT16(output_stream, PAKID_CORE_DEVICE_IOCOMPLETION); - - /* Write content */ - Stream_Write_UINT32(output_stream, device->device_id); - Stream_Write_UINT32(output_stream, completion_id); - Stream_Write_UINT32(output_stream, status); - - return output_stream; - -} - -/** - * Callback invoked on the current connection owner (if any) when a file - * download is being initiated using the magic "Download" folder. - * - * @param owner - * The guac_user that is the owner of the connection, or NULL if the - * connection owner has left. - * - * @param data - * The full absolute path to the file that should be downloaded. - * - * @return - * The stream allocated for the file download, or NULL if the download has - * failed to start. - */ -static void* guac_rdpdr_download_to_owner(guac_user* owner, void* data) { - - /* Do not bother attempting the download if the owner has left */ - if (owner == NULL) - return NULL; - - guac_client* client = owner->client; - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - guac_rdp_fs* filesystem = rdp_client->filesystem; - - /* Ignore download if filesystem has been unloaded */ - if (filesystem == NULL) - return NULL; - - /* Attempt to open requested file */ - char* path = (char*) data; - int file_id = guac_rdp_fs_open(filesystem, path, - ACCESS_FILE_READ_DATA, 0, DISP_FILE_OPEN, 0); - - /* If file opened successfully, start stream */ - if (file_id >= 0) { - - guac_rdp_stream* rdp_stream; - const char* basename; - - int i; - char c; - - /* Associate stream with transfer status */ - guac_stream* stream = guac_user_alloc_stream(owner); - stream->data = rdp_stream = malloc(sizeof(guac_rdp_stream)); - stream->ack_handler = guac_rdp_download_ack_handler; - rdp_stream->type = GUAC_RDP_DOWNLOAD_STREAM; - rdp_stream->download_status.file_id = file_id; - rdp_stream->download_status.offset = 0; - - /* Get basename from absolute path */ - i=0; - basename = path; - do { - - c = path[i]; - if (c == '/' || c == '\\') - basename = &(path[i+1]); - - i++; - - } while (c != '\0'); - - guac_user_log(owner, GUAC_LOG_DEBUG, "%s: Initiating download " - "of \"%s\"", __func__, path); - - /* Begin stream */ - guac_protocol_send_file(owner->socket, stream, - "application/octet-stream", basename); - guac_socket_flush(owner->socket); - - /* Download started successfully */ - return stream; - - } - - /* Download failed */ - guac_user_log(owner, GUAC_LOG_ERROR, "Unable to download \"%s\"", path); - return NULL; - -} - -void guac_rdpdr_start_download(guac_rdpdr_device* device, char* path) { - - guac_client* client = device->rdpdr->client; - - /* Initiate download to the owner of the connection */ - guac_client_for_owner(client, guac_rdpdr_download_to_owner, path); - -} - -/** - * Event handler for events which deal with data transmitted over the RDPDR - * channel. This specific implementation of the event handler currently - * handles only the CHANNEL_EVENT_DATA_RECEIVED event, delegating actual - * handling of that event to guac_rdpdr_process_receive(). - * - * The FreeRDP requirements for this function follow those of the - * VirtualChannelOpenEventEx callback defined within Microsoft's RDP API: - * - * https://docs.microsoft.com/en-us/previous-versions/windows/embedded/aa514754%28v%3dmsdn.10%29 - * - * @param user_param - * The pointer to arbitrary data originally passed via the first parameter - * of the pVirtualChannelInitEx() function call when the associated channel - * was initialized. The pVirtualChannelInitEx() function is exposed within - * the channel entry points structure. - * - * @param open_handle - * The handle which identifies the channel itself, typically referred to - * within the FreeRDP source as OpenHandle. - * - * @param event - * An integer representing the event that should be handled. This will be - * either CHANNEL_EVENT_DATA_RECEIVED, CHANNEL_EVENT_WRITE_CANCELLED, or - * CHANNEL_EVENT_WRITE_COMPLETE. - * - * @param data - * The data received, for CHANNEL_EVENT_DATA_RECEIVED events, and the value - * passed as user data to pVirtualChannelWriteEx() for - * CHANNEL_EVENT_WRITE_* events (note that user data for - * pVirtualChannelWriteEx() as implemented by FreeRDP MUST either be NULL - * or a wStream containing the data written). - * - * @param data_length - * The number of bytes of event-specific data. - * - * @param total_length - * The total number of bytes written to the RDP server in a single write - * operation. - * - * NOTE: The meaning of total_length is unclear. The above description was - * written mainly through referencing the documentation in MSDN. Real-world - * use will need to be consulted, likely within the FreeRDP source, before - * this value can be reliably used. The current implementation of this - * handler ignores this parameter. - * - * @param data_flags - * The result of a bitwise OR of the CHANNEL_FLAG_* flags which apply to - * the data received. This value is relevant only to - * CHANNEL_EVENT_DATA_RECEIVED events. Valid flags are CHANNEL_FLAG_FIRST, - * CHANNEL_FLAG_LAST, and CHANNEL_FLAG_ONLY. The flag CHANNEL_FLAG_MIDDLE - * is not itself a flag, but the absence of both CHANNEL_FLAG_FIRST and - * CHANNEL_FLAG_LAST. - */ -static VOID guac_rdpdr_handle_open_event(LPVOID user_param, - DWORD open_handle, UINT event, LPVOID data, UINT32 data_length, - UINT32 total_length, UINT32 data_flags) { - - /* Ignore all events except for received data */ - if (event != CHANNEL_EVENT_DATA_RECEIVED) - return; - - guac_rdpdr* rdpdr = (guac_rdpdr*) user_param; - - /* Validate relevant handle matches that of the RDPDR channel */ - if (open_handle != rdpdr->open_handle) { - guac_client_log(rdpdr->client, GUAC_LOG_WARNING, "%i bytes of data " - "received from within the remote desktop session for the " - "RDPDR channel are being dropped because the relevant open " - "handle (0x%X) does not match the open handle of RDPDR " - "(0x%X).", data_length, rdpdr->channel_def.name, open_handle, - rdpdr->open_handle); - return; - } - - wStream* input_stream = Stream_New(data, data_length); - guac_rdpdr_process_receive(rdpdr, input_stream); - Stream_Free(input_stream, FALSE); - -} - -/** - * Processes a CHANNEL_EVENT_CONNECTED event, completing the - * connection/initialization process of the RDPDR channel. - * - * @param rdpdr - * The guac_rdpdr structure representing the RDPDR channel. - */ -static void guac_rdpdr_process_connect(guac_rdpdr* rdpdr) { - - /* Get data from client */ - guac_client* client = rdpdr->client; - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - - /* Open FreeRDP side of connected channel */ - UINT32 open_status = - rdpdr->entry_points.pVirtualChannelOpenEx(rdpdr->init_handle, - &rdpdr->open_handle, rdpdr->channel_def.name, - guac_rdpdr_handle_open_event); - - /* Warn if the channel cannot be opened after all */ - if (open_status != CHANNEL_RC_OK) { - guac_client_log(client, GUAC_LOG_WARNING, "RDPDR channel could not be " - "opened: %s (error %i)", WTSErrorToString(open_status), - open_status); - return; - } - - /* Register printer if enabled */ - if (rdp_client->settings->printing_enabled) - guac_rdpdr_register_printer(rdpdr, rdp_client->settings->printer_name); - - /* Register drive if enabled */ - if (rdp_client->settings->drive_enabled) - guac_rdpdr_register_fs(rdpdr, rdp_client->settings->drive_name); - - /* Log that printing, etc. has been loaded */ - guac_client_log(client, GUAC_LOG_INFO, "RDPDR channel connected."); - -} - -/** - * Processes a CHANNEL_EVENT_TERMINATED event, freeing all resources associated - * with the RDPDR channel. - * - * @param rdpdr - * The guac_rdpdr structure representing the RDPDR channel. - */ -static void guac_rdpdr_process_terminate(guac_rdpdr* rdpdr) { - - int i; - - for (i=0; idevices_registered; i++) { - guac_rdpdr_device* device = &(rdpdr->devices[i]); - guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Unloading device %i (%s)", - device->device_id, device->device_name); - device->free_handler(device); - } - - guac_client_log(rdpdr->client, GUAC_LOG_INFO, "RDPDR channel disconnected."); - free(rdpdr); - -} - -/** - * Event handler for events which deal with the overall lifecycle of the RDPDR - * channel. This specific implementation of the event handler currently - * handles only CHANNEL_EVENT_CONNECTED and CHANNEL_EVENT_TERMINATED events, - * delegating actual handling of those events to guac_rdpdr_process_connect() - * and guac_rdpdr_process_terminate() respectively. - * - * The FreeRDP requirements for this function follow those of the - * VirtualChannelInitEventEx callback defined within Microsoft's RDP API: - * - * https://docs.microsoft.com/en-us/previous-versions/windows/embedded/aa514727%28v%3dmsdn.10%29 - * - * @param user_param - * The pointer to arbitrary data originally passed via the first parameter - * of the pVirtualChannelInitEx() function call when the associated channel - * was initialized. The pVirtualChannelInitEx() function is exposed within - * the channel entry points structure. - * - * @param init_handle - * The handle which identifies the client connection, typically referred to - * within the FreeRDP source as pInitHandle. - * - * @param event - * An integer representing the event that should be handled. This will be - * either CHANNEL_EVENT_CONNECTED, CHANNEL_EVENT_DISCONNECTED, - * CHANNEL_EVENT_INITIALIZED, CHANNEL_EVENT_TERMINATED, or - * CHANNEL_EVENT_V1_CONNECTED. - * - * @param data - * NULL in all cases except the CHANNEL_EVENT_CONNECTED event, in which - * case this is a null-terminated string containing the name of the server. - * - * @param data_length - * The number of bytes of data, if any. - */ -static VOID guac_rdpdr_handle_init_event(LPVOID user_param, - LPVOID init_handle, UINT event, LPVOID data, UINT data_length) { - - guac_rdpdr* rdpdr = (guac_rdpdr*) user_param; - - /* Validate relevant handle matches that of the RDPDR channel */ - if (init_handle != rdpdr->init_handle) { - guac_client_log(rdpdr->client, GUAC_LOG_WARNING, "An init event " - "(#%i) for the RDPDR channel has been dropped because the " - "relevant init handle (0x%X) does not match the init handle " - "of the RDPDR channel (0x%X).", event, init_handle, - rdpdr->init_handle); - return; - } - - switch (event) { - - /* The RDPDR channel has been connected */ - case CHANNEL_EVENT_CONNECTED: - guac_rdpdr_process_connect(rdpdr); - break; - - /* The RDPDR channel has disconnected and now must be cleaned up */ - case CHANNEL_EVENT_TERMINATED: - guac_rdpdr_process_terminate(rdpdr); - break; - - } - -} - -/** - * Entry point for FreeRDP plugins. This function is automatically invoked when - * the plugin is loaded. - * - * @param entry_points - * Functions and data specific to the FreeRDP side of the virtual channel - * and plugin. This structure must be copied within implementation-specific - * storage such that the functions it references can be invoked when - * needed. - * - * @param init_handle - * The handle which identifies the client connection, typically referred to - * within the FreeRDP source as pInitHandle. This handle is also provided - * to the channel init event handler. The handle must eventually be used - * within the channel open event handler to obtain a handle to the channel - * itself. - * - * @return - * TRUE if the plugin has initialized successfully, FALSE otherwise. - */ -BOOL VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS entry_points, - PVOID init_handle) { - - CHANNEL_ENTRY_POINTS_FREERDP_EX* entry_points_ex = - (CHANNEL_ENTRY_POINTS_FREERDP_EX*) entry_points; - - /* Allocate plugin */ - guac_rdpdr* rdpdr = (guac_rdpdr*) calloc(1, sizeof(guac_rdpdr)); - - /* Init channel def */ - strcpy(rdpdr->channel_def.name, "rdpdr"); - rdpdr->channel_def.options = CHANNEL_OPTION_INITIALIZED - | CHANNEL_OPTION_ENCRYPT_RDP - | CHANNEL_OPTION_COMPRESS_RDP; - - /* Maintain reference to associated guac_client */ - rdpdr->client = (guac_client*) entry_points_ex->pExtendedData; - - /* No devices are connected initially */ - rdpdr->devices_registered = 0; - - /* Copy FreeRDP data into RDPSND structure for future reference */ - rdpdr->entry_points = *entry_points_ex; - rdpdr->init_handle = init_handle; - - /* Complete initialization */ - if (rdpdr->entry_points.pVirtualChannelInitEx(rdpdr, rdpdr, init_handle, - &rdpdr->channel_def, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, - guac_rdpdr_handle_init_event) != CHANNEL_RC_OK) { - return FALSE; - } - - return TRUE; - -} - diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_service.h b/src/protocols/rdp/guac_rdpdr/rdpdr_service.h deleted file mode 100644 index 1fa3b126..00000000 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_service.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - - -#ifndef __GUAC_RDPDR_SERVICE_H -#define __GUAC_RDPDR_SERVICE_H - -#include "config.h" - -#include -#include -#include -#include - -/** - * The maximum number of bytes to allow for a device read. - */ -#define GUAC_RDP_MAX_READ_BUFFER 4194304 - -typedef struct guac_rdpdr guac_rdpdr; -typedef struct guac_rdpdr_device guac_rdpdr_device; - -/** - * Handler for client device list announce. Each implementing device must write - * its announcement header and data to the given output stream. - */ -typedef void guac_rdpdr_device_announce_handler(guac_rdpdr_device* device, wStream* output_stream, - int device_id); - -/** - * Handler for device I/O requests. - */ -typedef void guac_rdpdr_device_iorequest_handler(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id, int major_func, int minor_func); - -/** - * Handler for cleaning up the dynamically-allocated portions of a device. - */ -typedef void guac_rdpdr_device_free_handler(guac_rdpdr_device* device); - -/** - * Arbitrary device forwarded over the RDPDR channel. - */ -struct guac_rdpdr_device { - - /** - * The RDPDR plugin owning this device. - */ - guac_rdpdr* rdpdr; - - /** - * The ID assigned to this device by the RDPDR plugin. - */ - int device_id; - - /** - * Device name, used for logging and for passthrough to the - * server. - */ - const char* device_name; - - /** - * The type of RDPDR device that this represents. - */ - uint32_t device_type; - - /** - * The DOS name of the device. Max 8 bytes, including terminator. - */ - const char *dos_name; - - /** - * The stream that stores the RDPDR device announcement for this device. - */ - wStream* device_announce; - - /** - * The length of the device_announce wStream. - */ - int device_announce_len; - - /** - * Handler which should be called for every I/O request received. - */ - guac_rdpdr_device_iorequest_handler* iorequest_handler; - - /** - * Handler which should be called when the device is being freed. - */ - guac_rdpdr_device_free_handler* free_handler; - - /** - * Arbitrary data, used internally by the handlers for this device. - */ - void* data; - -}; - -/** - * Structure representing the current state of the Guacamole RDPDR plugin for - * FreeRDP. - */ -struct guac_rdpdr { - - /** - * Reference to the client owning this instance of the RDPDR plugin. - */ - guac_client* client; - - /** - * The definition of this virtual channel (RDPDR). - */ - CHANNEL_DEF channel_def; - - /** - * Functions and data specific to the FreeRDP side of the virtual channel - * and plugin. - */ - CHANNEL_ENTRY_POINTS_FREERDP_EX entry_points; - - /** - * Handle which identifies the client connection, typically referred to - * within the FreeRDP source as pInitHandle. This handle is provided to the - * channel entry point and the channel init event handler. The handle must - * eventually be used within the channel open event handler to obtain a - * handle to the channel itself. - */ - PVOID init_handle; - - /** - * Handle which identifies the channel itself, typically referred to within - * the FreeRDP source as OpenHandle. This handle is obtained through a call - * to entry_points.pVirtualChannelOpenEx() in response to receiving a - * CHANNEL_EVENT_CONNECTED event via the init event handler. - * - * Data is received in CHANNEL_EVENT_DATA_RECEIVED events via the open - * event handler, and data is written through calls to - * entry_points.pVirtualChannelWriteEx(). - */ - DWORD open_handle; - - /** - * The number of devices registered within the devices array. - */ - int devices_registered; - - /** - * Array of registered devices. - */ - guac_rdpdr_device devices[8]; - -}; - -/** - * Creates a new stream which contains the common DR_DEVICE_IOCOMPLETION header - * used for virtually all responses. - */ -wStream* guac_rdpdr_new_io_completion(guac_rdpdr_device* device, - int completion_id, int status, int size); - -/** - * Begins streaming the given file to the user via a Guacamole file stream. - */ -void guac_rdpdr_start_download(guac_rdpdr_device* device, char* path); - -#endif - diff --git a/src/protocols/rdp/rdpdr.c b/src/protocols/rdp/rdpdr.c index e39d393a..aabe9399 100644 --- a/src/protocols/rdp/rdpdr.c +++ b/src/protocols/rdp/rdpdr.c @@ -20,24 +20,262 @@ #include "config.h" #include "channels.h" #include "rdp.h" +#include "rdp_fs.h" +#include "rdp_settings.h" +#include "rdp_stream.h" +#include "rdpdr.h" +#include "rdpdr_fs_service.h" +#include "rdpdr_messages.h" +#include "rdpdr_printer.h" #include #include +#include +#include +#include +#include + +#include +#include + +void guac_rdpdr_process_receive(guac_rdp_common_svc* svc, + wStream* input_stream) { + + int component; + int packet_id; + + /* Read header */ + Stream_Read_UINT16(input_stream, component); + Stream_Read_UINT16(input_stream, packet_id); + + /* Core component */ + if (component == RDPDR_CTYP_CORE) { + + /* Dispatch handlers based on packet ID */ + switch (packet_id) { + + case PAKID_CORE_SERVER_ANNOUNCE: + guac_rdpdr_process_server_announce(svc, input_stream); + break; + + case PAKID_CORE_CLIENTID_CONFIRM: + guac_rdpdr_process_clientid_confirm(svc, input_stream); + break; + + case PAKID_CORE_DEVICE_REPLY: + guac_rdpdr_process_device_reply(svc, input_stream); + break; + + case PAKID_CORE_DEVICE_IOREQUEST: + guac_rdpdr_process_device_iorequest(svc, input_stream); + break; + + case PAKID_CORE_SERVER_CAPABILITY: + guac_rdpdr_process_server_capability(svc, input_stream); + break; + + case PAKID_CORE_USER_LOGGEDON: + guac_rdpdr_process_user_loggedon(svc, input_stream); + break; + + default: + guac_client_log(svc->client, GUAC_LOG_DEBUG, "Ignoring " + "RDPDR core packet with unexpected ID: 0x%04x", + packet_id); + + } + + } /* end if core */ + + /* Printer component */ + else if (component == RDPDR_CTYP_PRN) { + + /* Dispatch handlers based on packet ID */ + switch (packet_id) { + + case PAKID_PRN_CACHE_DATA: + guac_rdpdr_process_prn_cache_data(svc, input_stream); + break; + + case PAKID_PRN_USING_XPS: + guac_rdpdr_process_prn_using_xps(svc, input_stream); + break; + + default: + guac_client_log(svc->client, GUAC_LOG_DEBUG, "Ignoring RDPDR " + "printer packet with unexpected ID: 0x%04x", + packet_id); + + } + + } /* end if printer */ + + else + guac_client_log(svc->client, GUAC_LOG_DEBUG, "Ignoring packet for " + "unknown RDPDR component: 0x%04x", component); + +} + +wStream* guac_rdpdr_new_io_completion(guac_rdpdr_device* device, + int completion_id, int status, int size) { + + wStream* output_stream = Stream_New(NULL, 16+size); + + /* Write header */ + Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE); + Stream_Write_UINT16(output_stream, PAKID_CORE_DEVICE_IOCOMPLETION); + + /* Write content */ + Stream_Write_UINT32(output_stream, device->device_id); + Stream_Write_UINT32(output_stream, completion_id); + Stream_Write_UINT32(output_stream, status); + + return output_stream; + +} + +/** + * Callback invoked on the current connection owner (if any) when a file + * download is being initiated using the magic "Download" folder. + * + * @param owner + * The guac_user that is the owner of the connection, or NULL if the + * connection owner has left. + * + * @param data + * The full absolute path to the file that should be downloaded. + * + * @return + * The stream allocated for the file download, or NULL if the download has + * failed to start. + */ +static void* guac_rdpdr_download_to_owner(guac_user* owner, void* data) { + + /* Do not bother attempting the download if the owner has left */ + if (owner == NULL) + return NULL; + + guac_client* client = owner->client; + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + guac_rdp_fs* filesystem = rdp_client->filesystem; + + /* Ignore download if filesystem has been unloaded */ + if (filesystem == NULL) + return NULL; + + /* Attempt to open requested file */ + char* path = (char*) data; + int file_id = guac_rdp_fs_open(filesystem, path, + ACCESS_FILE_READ_DATA, 0, DISP_FILE_OPEN, 0); + + /* If file opened successfully, start stream */ + if (file_id >= 0) { + + guac_rdp_stream* rdp_stream; + const char* basename; + + int i; + char c; + + /* Associate stream with transfer status */ + guac_stream* stream = guac_user_alloc_stream(owner); + stream->data = rdp_stream = malloc(sizeof(guac_rdp_stream)); + stream->ack_handler = guac_rdp_download_ack_handler; + rdp_stream->type = GUAC_RDP_DOWNLOAD_STREAM; + rdp_stream->download_status.file_id = file_id; + rdp_stream->download_status.offset = 0; + + /* Get basename from absolute path */ + i=0; + basename = path; + do { + + c = path[i]; + if (c == '/' || c == '\\') + basename = &(path[i+1]); + + i++; + + } while (c != '\0'); + + guac_user_log(owner, GUAC_LOG_DEBUG, "%s: Initiating download " + "of \"%s\"", __func__, path); + + /* Begin stream */ + guac_protocol_send_file(owner->socket, stream, + "application/octet-stream", basename); + guac_socket_flush(owner->socket); + + /* Download started successfully */ + return stream; + + } + + /* Download failed */ + guac_user_log(owner, GUAC_LOG_ERROR, "Unable to download \"%s\"", path); + return NULL; + +} + +void guac_rdpdr_start_download(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, char* path) { + + guac_client* client = svc->client; + + /* Initiate download to the owner of the connection */ + guac_client_for_owner(client, guac_rdpdr_download_to_owner, path); + +} + +void guac_rdpdr_process_connect(guac_rdp_common_svc* svc) { + + /* Get data from client */ + guac_client* client = svc->client; + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + + guac_rdpdr* rdpdr = (guac_rdpdr*) calloc(1, sizeof(guac_rdpdr)); + svc->data = rdpdr; + + /* Register printer if enabled */ + if (rdp_client->settings->printing_enabled) + guac_rdpdr_register_printer(svc, rdp_client->settings->printer_name); + + /* Register drive if enabled */ + if (rdp_client->settings->drive_enabled) + guac_rdpdr_register_fs(svc, rdp_client->settings->drive_name); + +} + +void guac_rdpdr_process_terminate(guac_rdp_common_svc* svc) { + + guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data; + + int i; + + for (i=0; idevices_registered; i++) { + guac_rdpdr_device* device = &(rdpdr->devices[i]); + guac_client_log(svc->client, GUAC_LOG_DEBUG, "Unloading device %i " + "(%s)", device->device_id, device->device_name); + device->free_handler(svc, device); + } + + free(rdpdr); + +} + void guac_rdpdr_load_plugin(rdpContext* context) { guac_client* client = ((rdp_freerdp_context*) context)->client; - /* Load RDPDR plugin */ - if (guac_freerdp_channels_load_plugin(context->channels, context->settings, "guacdr", client)) { + /* Load support for RDPDR */ + if (guac_rdp_common_svc_load_plugin(context, "rdpdr", + CHANNEL_OPTION_COMPRESS_RDP, guac_rdpdr_process_connect, + guac_rdpdr_process_receive, guac_rdpdr_process_terminate)) { guac_client_log(client, GUAC_LOG_WARNING, "Support for the RDPDR " "channel (device redirection) could not be loaded. Drive " "redirection and printing will not work. Sound MAY not work."); - return; } - guac_client_log(client, GUAC_LOG_DEBUG, "Support for RDPDR (device " - "redirection) registered. Awaiting channel connection."); - } diff --git a/src/protocols/rdp/rdpdr.h b/src/protocols/rdp/rdpdr.h index 0a18a58c..b5e59f0a 100644 --- a/src/protocols/rdp/rdpdr.h +++ b/src/protocols/rdp/rdpdr.h @@ -21,6 +21,121 @@ #define GUAC_RDP_RDPDR_H #include "config.h" +#include "common-svc.h" + +#include +#include + +/** + * The maximum number of bytes to allow for a device read. + */ +#define GUAC_RDP_MAX_READ_BUFFER 4194304 + +/** + * Arbitrary device forwarded over the RDPDR channel. + */ +typedef struct guac_rdpdr_device guac_rdpdr_device; + +/** + * Handler for client device list announce. Each implementing device must write + * its announcement header and data to the given output stream. + */ +typedef void guac_rdpdr_device_announce_handler(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* output_stream, int device_id); + +/** + * Handler for device I/O requests. + */ +typedef void guac_rdpdr_device_iorequest_handler(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id, int major_func, int minor_func); + +/** + * Handler for cleaning up the dynamically-allocated portions of a device. + */ +typedef void guac_rdpdr_device_free_handler(guac_rdp_common_svc* svc, + guac_rdpdr_device* device); + +struct guac_rdpdr_device { + + /** + * The ID assigned to this device by the RDPDR plugin. + */ + int device_id; + + /** + * Device name, used for logging and for passthrough to the + * server. + */ + const char* device_name; + + /** + * The type of RDPDR device that this represents. + */ + uint32_t device_type; + + /** + * The DOS name of the device. Max 8 bytes, including terminator. + */ + const char *dos_name; + + /** + * The stream that stores the RDPDR device announcement for this device. + */ + wStream* device_announce; + + /** + * The length of the device_announce wStream. + */ + int device_announce_len; + + /** + * Handler which should be called for every I/O request received. + */ + guac_rdpdr_device_iorequest_handler* iorequest_handler; + + /** + * Handler which should be called when the device is being freed. + */ + guac_rdpdr_device_free_handler* free_handler; + + /** + * Arbitrary data, used internally by the handlers for this device. + */ + void* data; + +}; + +/** + * Structure representing the current state of the Guacamole RDPDR plugin for + * FreeRDP. + */ +typedef struct guac_rdpdr { + + /** + * The number of devices registered within the devices array. + */ + int devices_registered; + + /** + * Array of registered devices. + */ + guac_rdpdr_device devices[8]; + +} guac_rdpdr; + +/** + * Creates a new stream which contains the common DR_DEVICE_IOCOMPLETION header + * used for virtually all responses. + */ +wStream* guac_rdpdr_new_io_completion(guac_rdpdr_device* device, + int completion_id, int status, int size); + +/** + * Begins streaming the given file to the user via a Guacamole file stream. + */ +void guac_rdpdr_start_download(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, char* path); /** * Initializes device redirection support (file transfer, printing, etc.) for @@ -36,5 +151,23 @@ */ void guac_rdpdr_load_plugin(rdpContext* context); +/** + * Handler which is invoked when the RDPDR channel is connected to the RDP + * server. + */ +guac_rdp_common_svc_connect_handler guac_rdpdr_process_connect; + +/** + * Handler which is invoked when the RDPDR channel has received data from the + * RDP server. + */ +guac_rdp_common_svc_receive_handler guac_rdpdr_process_receive; + +/** + * Handler which is invoked when the RDPDR channel has disconnected and is + * about to be freed. + */ +guac_rdp_common_svc_terminate_handler guac_rdpdr_process_terminate; + #endif diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.c b/src/protocols/rdp/rdpdr_fs_messages.c similarity index 69% rename from src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.c rename to src/protocols/rdp/rdpdr_fs_messages.c index 1336e6f9..b23a0107 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.c +++ b/src/protocols/rdp/rdpdr_fs_messages.c @@ -18,13 +18,12 @@ */ #include "config.h" - +#include "rdpdr.h" #include "rdpdr_fs_messages_dir_info.h" #include "rdpdr_fs_messages_file_info.h" #include "rdpdr_fs_messages.h" #include "rdpdr_fs_messages_vol_info.h" #include "rdpdr_messages.h" -#include "rdpdr_service.h" #include "rdp_fs.h" #include "rdp_status.h" #include "unicode.h" @@ -38,8 +37,8 @@ #include #include -void guac_rdpdr_fs_process_create(guac_rdpdr_device* device, - wStream* input_stream, int completion_id) { +void guac_rdpdr_fs_process_create(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int completion_id) { wStream* output_stream; int file_id; @@ -66,7 +65,7 @@ void guac_rdpdr_fs_process_create(guac_rdpdr_device* device, desired_access, file_attributes, create_disposition, create_options); - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] " "desired_access=0x%x, file_attributes=0x%x, " "create_disposition=0x%x, create_options=0x%x, path=\"%s\"", @@ -76,7 +75,7 @@ void guac_rdpdr_fs_process_create(guac_rdpdr_device* device, /* If an error occurred, notify server */ if (file_id < 0) { - guac_client_log(device->rdpdr->client, GUAC_LOG_ERROR, + guac_client_log(svc->client, GUAC_LOG_ERROR, "File open refused (%i): \"%s\"", file_id, path); output_stream = guac_rdpdr_new_io_completion(device, completion_id, @@ -109,14 +108,13 @@ void guac_rdpdr_fs_process_create(guac_rdpdr_device* device, } - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -void guac_rdpdr_fs_process_read(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id) { +void guac_rdpdr_fs_process_read(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id) { UINT32 length; UINT64 offset; @@ -129,7 +127,7 @@ void guac_rdpdr_fs_process_read(guac_rdpdr_device* device, Stream_Read_UINT32(input_stream, length); Stream_Read_UINT64(input_stream, offset); - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] length=%i, offset=%" PRIu64, __func__, file_id, length, (uint64_t) offset); @@ -159,15 +157,14 @@ void guac_rdpdr_fs_process_read(guac_rdpdr_device* device, Stream_Write(output_stream, buffer, bytes_read); /* ReadData */ } - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); free(buffer); } -void guac_rdpdr_fs_process_write(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id) { +void guac_rdpdr_fs_process_write(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id) { UINT32 length; UINT64 offset; @@ -180,7 +177,7 @@ void guac_rdpdr_fs_process_write(guac_rdpdr_device* device, Stream_Read_UINT64(input_stream, offset); Stream_Seek(input_stream, 20); /* Padding */ - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] length=%i, offset=%" PRIu64, __func__, file_id, length, (uint64_t) offset); @@ -204,19 +201,18 @@ void guac_rdpdr_fs_process_write(guac_rdpdr_device* device, Stream_Write_UINT8(output_stream, 0); /* Padding */ } - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -void guac_rdpdr_fs_process_close(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id) { +void guac_rdpdr_fs_process_close(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id) { wStream* output_stream; guac_rdp_fs_file* file; - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, file_id); @@ -228,7 +224,7 @@ void guac_rdpdr_fs_process_close(guac_rdpdr_device* device, /* If file was written to, and it's in the \Download folder, start stream */ if (file->bytes_written > 0 && strncmp(file->absolute_path, "\\Download\\", 10) == 0) { - guac_rdpdr_start_download(device, file->absolute_path); + guac_rdpdr_start_download(svc, device, file->absolute_path); guac_rdp_fs_delete((guac_rdp_fs*) device->data, file_id); } @@ -239,14 +235,13 @@ void guac_rdpdr_fs_process_close(guac_rdpdr_device* device, STATUS_SUCCESS, 4); Stream_Write(output_stream, "\0\0\0\0", 4); /* Padding */ - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -void guac_rdpdr_fs_process_volume_info(guac_rdpdr_device* device, wStream* input_stream, - int file_id, int completion_id) { +void guac_rdpdr_fs_process_volume_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id) { int fs_information_class; @@ -256,39 +251,40 @@ void guac_rdpdr_fs_process_volume_info(guac_rdpdr_device* device, wStream* input switch (fs_information_class) { case FileFsVolumeInformation: - guac_rdpdr_fs_process_query_volume_info(device, input_stream, + guac_rdpdr_fs_process_query_volume_info(svc, device, input_stream, file_id, completion_id); break; case FileFsSizeInformation: - guac_rdpdr_fs_process_query_size_info(device, input_stream, + guac_rdpdr_fs_process_query_size_info(svc, device, input_stream, file_id, completion_id); break; case FileFsDeviceInformation: - guac_rdpdr_fs_process_query_device_info(device, input_stream, + guac_rdpdr_fs_process_query_device_info(svc, device, input_stream, file_id, completion_id); break; case FileFsAttributeInformation: - guac_rdpdr_fs_process_query_attribute_info(device, input_stream, - file_id, completion_id); + guac_rdpdr_fs_process_query_attribute_info(svc, device, + input_stream, file_id, completion_id); break; case FileFsFullSizeInformation: - guac_rdpdr_fs_process_query_full_size_info(device, input_stream, - file_id, completion_id); + guac_rdpdr_fs_process_query_full_size_info(svc, device, + input_stream, file_id, completion_id); break; default: - guac_client_log(device->rdpdr->client, GUAC_LOG_INFO, + guac_client_log(svc->client, GUAC_LOG_INFO, "Unknown volume information class: 0x%x", fs_information_class); } } -void guac_rdpdr_fs_process_file_info(guac_rdpdr_device* device, wStream* input_stream, - int file_id, int completion_id) { +void guac_rdpdr_fs_process_file_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id) { int fs_information_class; @@ -298,45 +294,45 @@ void guac_rdpdr_fs_process_file_info(guac_rdpdr_device* device, wStream* input_s switch (fs_information_class) { case FileBasicInformation: - guac_rdpdr_fs_process_query_basic_info(device, input_stream, + guac_rdpdr_fs_process_query_basic_info(svc, device, input_stream, file_id, completion_id); break; case FileStandardInformation: - guac_rdpdr_fs_process_query_standard_info(device, input_stream, - file_id, completion_id); + guac_rdpdr_fs_process_query_standard_info(svc, device, + input_stream, file_id, completion_id); break; case FileAttributeTagInformation: - guac_rdpdr_fs_process_query_attribute_tag_info(device, input_stream, - file_id, completion_id); + guac_rdpdr_fs_process_query_attribute_tag_info(svc, device, + input_stream, file_id, completion_id); break; default: - guac_client_log(device->rdpdr->client, GUAC_LOG_INFO, + guac_client_log(svc->client, GUAC_LOG_INFO, "Unknown file information class: 0x%x", fs_information_class); } } -void guac_rdpdr_fs_process_set_volume_info(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id) { +void guac_rdpdr_fs_process_set_volume_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id) { wStream* output_stream = guac_rdpdr_new_io_completion(device, completion_id, STATUS_NOT_SUPPORTED, 0); - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] Set volume info not supported", __func__, file_id); - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -void guac_rdpdr_fs_process_set_file_info(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id) { +void guac_rdpdr_fs_process_set_file_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id) { int fs_information_class; int length; @@ -349,68 +345,69 @@ void guac_rdpdr_fs_process_set_file_info(guac_rdpdr_device* device, switch (fs_information_class) { case FileBasicInformation: - guac_rdpdr_fs_process_set_basic_info(device, input_stream, + guac_rdpdr_fs_process_set_basic_info(svc, device, input_stream, file_id, completion_id, length); break; case FileEndOfFileInformation: - guac_rdpdr_fs_process_set_end_of_file_info(device, input_stream, - file_id, completion_id, length); + guac_rdpdr_fs_process_set_end_of_file_info(svc, device, + input_stream, file_id, completion_id, length); break; case FileDispositionInformation: - guac_rdpdr_fs_process_set_disposition_info(device, input_stream, - file_id, completion_id, length); + guac_rdpdr_fs_process_set_disposition_info(svc, device, + input_stream, file_id, completion_id, length); break; case FileRenameInformation: - guac_rdpdr_fs_process_set_rename_info(device, input_stream, + guac_rdpdr_fs_process_set_rename_info(svc, device, input_stream, file_id, completion_id, length); break; case FileAllocationInformation: - guac_rdpdr_fs_process_set_allocation_info(device, input_stream, - file_id, completion_id, length); + guac_rdpdr_fs_process_set_allocation_info(svc, device, + input_stream, file_id, completion_id, length); break; default: - guac_client_log(device->rdpdr->client, GUAC_LOG_INFO, + guac_client_log(svc->client, GUAC_LOG_INFO, "Unknown file information class: 0x%x", fs_information_class); } } -void guac_rdpdr_fs_process_device_control(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id) { +void guac_rdpdr_fs_process_device_control(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id) { wStream* output_stream = guac_rdpdr_new_io_completion(device, completion_id, STATUS_INVALID_PARAMETER, 4); - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] IGNORED", __func__, file_id); /* No content for now */ Stream_Write_UINT32(output_stream, 0); - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -void guac_rdpdr_fs_process_notify_change_directory(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id) { +void guac_rdpdr_fs_process_notify_change_directory(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id) { - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] Not implemented", __func__, file_id); } -void guac_rdpdr_fs_process_query_directory(guac_rdpdr_device* device, wStream* input_stream, - int file_id, int completion_id) { +void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id) { wStream* output_stream; @@ -441,7 +438,7 @@ void guac_rdpdr_fs_process_query_directory(guac_rdpdr_device* device, wStream* i } - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] initial_query=%i, dir_pattern=\"%s\"", __func__, file_id, initial_query, file->dir_pattern); @@ -470,27 +467,29 @@ void guac_rdpdr_fs_process_query_directory(guac_rdpdr_device* device, wStream* i switch (fs_information_class) { case FileDirectoryInformation: - guac_rdpdr_fs_process_query_directory_info(device, + guac_rdpdr_fs_process_query_directory_info(svc, device, entry_name, entry_file_id, completion_id); break; case FileFullDirectoryInformation: - guac_rdpdr_fs_process_query_full_directory_info(device, - entry_name, entry_file_id, completion_id); + guac_rdpdr_fs_process_query_full_directory_info(svc, + device, entry_name, entry_file_id, + completion_id); break; case FileBothDirectoryInformation: - guac_rdpdr_fs_process_query_both_directory_info(device, - entry_name, entry_file_id, completion_id); + guac_rdpdr_fs_process_query_both_directory_info(svc, + device, entry_name, entry_file_id, + completion_id); break; case FileNamesInformation: - guac_rdpdr_fs_process_query_names_info(device, + guac_rdpdr_fs_process_query_names_info(svc, device, entry_name, entry_file_id, completion_id); break; default: - guac_client_log(device->rdpdr->client, GUAC_LOG_INFO, + guac_client_log(svc->client, GUAC_LOG_INFO, "Unknown dir information class: 0x%x", fs_information_class); } @@ -512,27 +511,24 @@ void guac_rdpdr_fs_process_query_directory(guac_rdpdr_device* device, wStream* i Stream_Write_UINT32(output_stream, 0); /* Length */ Stream_Write_UINT8(output_stream, 0); /* Padding */ - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -void guac_rdpdr_fs_process_lock_control(guac_rdpdr_device* device, wStream* input_stream, - int file_id, int completion_id) { +void guac_rdpdr_fs_process_lock_control(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id) { wStream* output_stream = guac_rdpdr_new_io_completion(device, completion_id, STATUS_NOT_SUPPORTED, 5); - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] Lock not supported", __func__, file_id); Stream_Zero(output_stream, 5); /* Padding */ - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.h b/src/protocols/rdp/rdpdr_fs_messages.h similarity index 58% rename from src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.h rename to src/protocols/rdp/rdpdr_fs_messages.h index af0c87e1..a2018f2d 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.h +++ b/src/protocols/rdp/rdpdr_fs_messages.h @@ -18,8 +18,8 @@ */ -#ifndef __GUAC_RDPDR_FS_MESSAGES_H -#define __GUAC_RDPDR_FS_MESSAGES_H +#ifndef GUAC_RDPDR_FS_MESSAGES_H +#define GUAC_RDPDR_FS_MESSAGES_H /** * Handlers for core drive I/O requests. Requests handled here may be simple @@ -30,8 +30,7 @@ */ #include "config.h" - -#include "rdpdr_service.h" +#include "rdpdr.h" #include @@ -39,33 +38,37 @@ * Handles a Server Create Drive Request. Despite its name, this request opens * a file. */ -void guac_rdpdr_fs_process_create(guac_rdpdr_device* device, - wStream* input_stream, int completion_id); +void guac_rdpdr_fs_process_create(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int completion_id); /** * Handles a Server Close Drive Reqiest. This request closes an open file. */ -void guac_rdpdr_fs_process_close(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id); +void guac_rdpdr_fs_process_close(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id); /** * Handles a Server Drive Read Request. This request reads from a file. */ -void guac_rdpdr_fs_process_read(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id); +void guac_rdpdr_fs_process_read(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id); /** * Handles a Server Drive Write Request. This request writes to a file. */ -void guac_rdpdr_fs_process_write(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id); +void guac_rdpdr_fs_process_write(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id); /** * Handles a Server Drive Control Request. This request handles one of any * number of Windows FSCTL_* control functions. */ -void guac_rdpdr_fs_process_device_control(guac_rdpdr_device* device, wStream* input_stream, - int file_id, int completion_id); +void guac_rdpdr_fs_process_device_control(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id); /** * Handles a Server Drive Query Volume Information Request. This request @@ -73,53 +76,60 @@ void guac_rdpdr_fs_process_device_control(guac_rdpdr_device* device, wStream* in * has several query types which have their own handlers defined in a * separate file. */ -void guac_rdpdr_fs_process_volume_info(guac_rdpdr_device* device, wStream* input_stream, - int file_id, int completion_id); +void guac_rdpdr_fs_process_volume_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id); /** * Handles a Server Drive Set Volume Information Request. Currently, this * RDPDR implementation does not support setting of volume information. */ -void guac_rdpdr_fs_process_set_volume_info(guac_rdpdr_device* device, wStream* input_stream, - int file_id, int completion_id); +void guac_rdpdr_fs_process_set_volume_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id); /** * Handles a Server Drive Query Information Request. This request queries * information about a specific file. This request has several query types * which have their own handlers defined in a separate file. */ -void guac_rdpdr_fs_process_file_info(guac_rdpdr_device* device, wStream* input_stream, - int file_id, int completion_id); +void guac_rdpdr_fs_process_file_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id); /** * Handles a Server Drive Set Information Request. This request sets * information about a specific file. Currently, this RDPDR implementation does * not support setting of file information. */ -void guac_rdpdr_fs_process_set_file_info(guac_rdpdr_device* device, wStream* input_stream, - int file_id, int completion_id); +void guac_rdpdr_fs_process_set_file_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id); /** * Handles a Server Drive Query Directory Request. This request queries * information about a specific directory. This request has several query types * which have their own handlers defined in a separate file. */ -void guac_rdpdr_fs_process_query_directory(guac_rdpdr_device* device, wStream* input_stream, - int file_id, int completion_id); +void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id); /** * Handles a Server Drive NotifyChange Directory Request. This request requests * directory change notification. */ -void guac_rdpdr_fs_process_notify_change_directory(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id); +void guac_rdpdr_fs_process_notify_change_directory(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id); /** * Handles a Server Drive Lock Control Request. This request locks or unlocks * portions of a file. */ -void guac_rdpdr_fs_process_lock_control(guac_rdpdr_device* device, wStream* input_stream, - int file_id, int completion_id); +void guac_rdpdr_fs_process_lock_control(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id); #endif diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_dir_info.c b/src/protocols/rdp/rdpdr_fs_messages_dir_info.c similarity index 80% rename from src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_dir_info.c rename to src/protocols/rdp/rdpdr_fs_messages_dir_info.c index 303e7af7..23626941 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_dir_info.c +++ b/src/protocols/rdp/rdpdr_fs_messages_dir_info.c @@ -18,8 +18,7 @@ */ #include "config.h" - -#include "rdpdr_service.h" +#include "rdpdr.h" #include "rdp_fs.h" #include "rdp_status.h" #include "unicode.h" @@ -29,8 +28,9 @@ #include -void guac_rdpdr_fs_process_query_directory_info(guac_rdpdr_device* device, - const char* entry_name, int file_id, int completion_id) { +void guac_rdpdr_fs_process_query_directory_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, const char* entry_name, int file_id, + int completion_id) { guac_rdp_fs_file* file; @@ -47,7 +47,7 @@ void guac_rdpdr_fs_process_query_directory_info(guac_rdpdr_device* device, if (file == NULL) return; - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i (entry_name=\"%s\")]", __func__, file_id, entry_name); @@ -71,14 +71,13 @@ void guac_rdpdr_fs_process_query_directory_info(guac_rdpdr_device* device, Stream_Write(output_stream, utf16_entry_name, utf16_length); /* FileName */ Stream_Write(output_stream, "\0\0", 2); - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -void guac_rdpdr_fs_process_query_full_directory_info(guac_rdpdr_device* device, - const char* entry_name, int file_id, int completion_id) { +void guac_rdpdr_fs_process_query_full_directory_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, const char* entry_name, int file_id, + int completion_id) { guac_rdp_fs_file* file; @@ -95,7 +94,7 @@ void guac_rdpdr_fs_process_query_full_directory_info(guac_rdpdr_device* device, if (file == NULL) return; - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i (entry_name=\"%s\")]", __func__, file_id, entry_name); @@ -120,14 +119,13 @@ void guac_rdpdr_fs_process_query_full_directory_info(guac_rdpdr_device* device, Stream_Write(output_stream, utf16_entry_name, utf16_length); /* FileName */ Stream_Write(output_stream, "\0\0", 2); - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -void guac_rdpdr_fs_process_query_both_directory_info(guac_rdpdr_device* device, - const char* entry_name, int file_id, int completion_id) { +void guac_rdpdr_fs_process_query_both_directory_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, const char* entry_name, int file_id, + int completion_id) { guac_rdp_fs_file* file; @@ -144,7 +142,7 @@ void guac_rdpdr_fs_process_query_both_directory_info(guac_rdpdr_device* device, if (file == NULL) return; - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i (entry_name=\"%s\")]", __func__, file_id, entry_name); @@ -173,14 +171,13 @@ void guac_rdpdr_fs_process_query_both_directory_info(guac_rdpdr_device* device, Stream_Write(output_stream, utf16_entry_name, utf16_length); /* FileName */ Stream_Write(output_stream, "\0\0", 2); - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -void guac_rdpdr_fs_process_query_names_info(guac_rdpdr_device* device, - const char* entry_name, int file_id, int completion_id) { +void guac_rdpdr_fs_process_query_names_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, const char* entry_name, int file_id, + int completion_id) { guac_rdp_fs_file* file; @@ -197,7 +194,7 @@ void guac_rdpdr_fs_process_query_names_info(guac_rdpdr_device* device, if (file == NULL) return; - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i (entry_name=\"%s\")]", __func__, file_id, entry_name); @@ -213,9 +210,7 @@ void guac_rdpdr_fs_process_query_names_info(guac_rdpdr_device* device, Stream_Write(output_stream, utf16_entry_name, utf16_length); /* FileName */ Stream_Write(output_stream, "\0\0", 2); - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_dir_info.h b/src/protocols/rdp/rdpdr_fs_messages_dir_info.h similarity index 68% rename from src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_dir_info.h rename to src/protocols/rdp/rdpdr_fs_messages_dir_info.h index 9e0fcaf6..8d493406 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_dir_info.h +++ b/src/protocols/rdp/rdpdr_fs_messages_dir_info.h @@ -18,8 +18,8 @@ */ -#ifndef __GUAC_RDPDR_FS_MESSAGES_DIR_INFO_H -#define __GUAC_RDPDR_FS_MESSAGES_DIR_INFO_H +#ifndef GUAC_RDPDR_FS_MESSAGES_DIR_INFO_H +#define GUAC_RDPDR_FS_MESSAGES_DIR_INFO_H /** * Handlers for directory queries received over the RDPDR channel via the @@ -30,8 +30,8 @@ */ #include "config.h" - -#include "rdpdr_service.h" +#include "common-svc.h" +#include "rdpdr.h" #include @@ -40,31 +40,35 @@ * documentation this is "defined as the file's name, time stamp, and size, or its * attributes." */ -void guac_rdpdr_fs_process_query_directory_info(guac_rdpdr_device* device, - const char* entry_name, int file_id, int completion_id); +void guac_rdpdr_fs_process_query_directory_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, const char* entry_name, int file_id, + int completion_id); /** * Processes a query request for FileFullDirectoryInformation. From the * documentation, this is "defined as all the basic information, plus extended * attribute size." */ -void guac_rdpdr_fs_process_query_full_directory_info(guac_rdpdr_device* device, - const char* entry_name, int file_id, int completion_id); +void guac_rdpdr_fs_process_query_full_directory_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, const char* entry_name, int file_id, + int completion_id); /** * Processes a query request for FileBothDirectoryInformation. From the * documentation, this absurdly-named request is "basic information plus * extended attribute size and short name about a file or directory." */ -void guac_rdpdr_fs_process_query_both_directory_info(guac_rdpdr_device* device, - const char* entry_name, int file_id, int completion_id); +void guac_rdpdr_fs_process_query_both_directory_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, const char* entry_name, int file_id, + int completion_id); /** * Processes a query request for FileNamesInformation. From the documentation, * this is "detailed information on the names of files in a directory." */ -void guac_rdpdr_fs_process_query_names_info(guac_rdpdr_device* device, - const char* entry_name, int file_id, int completion_id); +void guac_rdpdr_fs_process_query_names_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, const char* entry_name, int file_id, + int completion_id); #endif diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_file_info.c b/src/protocols/rdp/rdpdr_fs_messages_file_info.c similarity index 67% rename from src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_file_info.c rename to src/protocols/rdp/rdpdr_fs_messages_file_info.c index c69046cb..4395a2f3 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_file_info.c +++ b/src/protocols/rdp/rdpdr_fs_messages_file_info.c @@ -18,8 +18,7 @@ */ #include "config.h" - -#include "rdpdr_service.h" +#include "rdpdr.h" #include "rdp_fs.h" #include "rdp_status.h" #include "unicode.h" @@ -31,8 +30,9 @@ #include #include -void guac_rdpdr_fs_process_query_basic_info(guac_rdpdr_device* device, wStream* input_stream, - int file_id, int completion_id) { +void guac_rdpdr_fs_process_query_basic_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id) { wStream* output_stream; guac_rdp_fs_file* file; @@ -42,7 +42,7 @@ void guac_rdpdr_fs_process_query_basic_info(guac_rdpdr_device* device, wStream* if (file == NULL) return; - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, file_id); @@ -58,14 +58,13 @@ void guac_rdpdr_fs_process_query_basic_info(guac_rdpdr_device* device, wStream* /* Reserved field must not be sent */ - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -void guac_rdpdr_fs_process_query_standard_info(guac_rdpdr_device* device, wStream* input_stream, - int file_id, int completion_id) { +void guac_rdpdr_fs_process_query_standard_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id) { wStream* output_stream; guac_rdp_fs_file* file; @@ -76,7 +75,7 @@ void guac_rdpdr_fs_process_query_standard_info(guac_rdpdr_device* device, wStrea if (file == NULL) return; - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, file_id); @@ -95,14 +94,13 @@ void guac_rdpdr_fs_process_query_standard_info(guac_rdpdr_device* device, wStrea /* Reserved field must not be sent */ - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -void guac_rdpdr_fs_process_query_attribute_tag_info(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id) { +void guac_rdpdr_fs_process_query_attribute_tag_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id) { wStream* output_stream; guac_rdp_fs_file* file; @@ -112,7 +110,7 @@ void guac_rdpdr_fs_process_query_attribute_tag_info(guac_rdpdr_device* device, if (file == NULL) return; - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, file_id); @@ -125,14 +123,13 @@ void guac_rdpdr_fs_process_query_attribute_tag_info(guac_rdpdr_device* device, /* Reserved field must not be sent */ - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -void guac_rdpdr_fs_process_set_rename_info(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id, int length) { +void guac_rdpdr_fs_process_set_rename_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id, int length) { int result; int filename_length; @@ -148,7 +145,7 @@ void guac_rdpdr_fs_process_set_rename_info(guac_rdpdr_device* device, guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), filename_length/2, destination_path, sizeof(destination_path)); - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] destination_path=\"%s\"", __func__, file_id, destination_path); @@ -163,7 +160,7 @@ void guac_rdpdr_fs_process_set_rename_info(guac_rdpdr_device* device, return; /* Initiate download, pretend move succeeded */ - guac_rdpdr_start_download(device, file->absolute_path); + guac_rdpdr_start_download(svc, device, file->absolute_path); output_stream = guac_rdpdr_new_io_completion(device, completion_id, STATUS_SUCCESS, 4); @@ -184,14 +181,13 @@ void guac_rdpdr_fs_process_set_rename_info(guac_rdpdr_device* device, } Stream_Write_UINT32(output_stream, length); - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -void guac_rdpdr_fs_process_set_allocation_info(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id, int length) { +void guac_rdpdr_fs_process_set_allocation_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id, int length) { int result; UINT64 size; @@ -200,7 +196,7 @@ void guac_rdpdr_fs_process_set_allocation_info(guac_rdpdr_device* device, /* Read new size */ Stream_Read_UINT64(input_stream, size); /* AllocationSize */ - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] size=%" PRIu64, __func__, file_id, (uint64_t) size); @@ -214,14 +210,13 @@ void guac_rdpdr_fs_process_set_allocation_info(guac_rdpdr_device* device, completion_id, STATUS_SUCCESS, 4); Stream_Write_UINT32(output_stream, length); - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -void guac_rdpdr_fs_process_set_disposition_info(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id, int length) { +void guac_rdpdr_fs_process_set_disposition_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id, int length) { wStream* output_stream; @@ -234,20 +229,19 @@ void guac_rdpdr_fs_process_set_disposition_info(guac_rdpdr_device* device, output_stream = guac_rdpdr_new_io_completion(device, completion_id, STATUS_SUCCESS, 4); - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, file_id); Stream_Write_UINT32(output_stream, length); - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id, int length) { +void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id, int length) { int result; UINT64 size; @@ -256,7 +250,7 @@ void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdpdr_device* device, /* Read new size */ Stream_Read_UINT64(input_stream, size); /* AllocationSize */ - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] size=%" PRIu64, __func__, file_id, (uint64_t) size); @@ -270,14 +264,13 @@ void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdpdr_device* device, completion_id, STATUS_SUCCESS, 4); Stream_Write_UINT32(output_stream, length); - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -void guac_rdpdr_fs_process_set_basic_info(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id, int length) { +void guac_rdpdr_fs_process_set_basic_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id, int length) { wStream* output_stream = guac_rdpdr_new_io_completion(device, completion_id, STATUS_SUCCESS, 4); @@ -285,13 +278,11 @@ void guac_rdpdr_fs_process_set_basic_info(guac_rdpdr_device* device, /* Currently do nothing, just respond */ Stream_Write_UINT32(output_stream, length); - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] IGNORED", __func__, file_id); - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_file_info.h b/src/protocols/rdp/rdpdr_fs_messages_file_info.h similarity index 61% rename from src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_file_info.h rename to src/protocols/rdp/rdpdr_fs_messages_file_info.h index de5559ad..56941d72 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_file_info.h +++ b/src/protocols/rdp/rdpdr_fs_messages_file_info.h @@ -18,8 +18,8 @@ */ -#ifndef __GUAC_RDPDR_FS_MESSAGES_FILE_INFO_H -#define __GUAC_RDPDR_FS_MESSAGES_FILE_INFO_H +#ifndef GUAC_RDPDR_FS_MESSAGES_FILE_INFO_H +#define GUAC_RDPDR_FS_MESSAGES_FILE_INFO_H /** * Handlers for file queries received over the RDPDR channel via the @@ -29,8 +29,8 @@ */ #include "config.h" - -#include "rdpdr_service.h" +#include "common-svc.h" +#include "rdpdr.h" #include @@ -39,59 +39,67 @@ * "used to query a file for the times of creation, last access, last write, * and change, in addition to file attribute information." */ -void guac_rdpdr_fs_process_query_basic_info(guac_rdpdr_device* device, wStream* input_stream, - int file_id, int completion_id); +void guac_rdpdr_fs_process_query_basic_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id); /** * Processes a query for FileStandardInformation. From the documentation, this * is "used to query for file information such as allocation size, end-of-file * position, and number of links." */ -void guac_rdpdr_fs_process_query_standard_info(guac_rdpdr_device* device, wStream* input_stream, - int file_id, int completion_id); +void guac_rdpdr_fs_process_query_standard_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id); /** * Processes a query for FileAttributeTagInformation. From the documentation * this is "used to query for file attribute and reparse tag information." */ -void guac_rdpdr_fs_process_query_attribute_tag_info(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id); +void guac_rdpdr_fs_process_query_attribute_tag_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id); /** * Process a set operation for FileRenameInformation. From the documentation, * this operation is used to rename a file. */ -void guac_rdpdr_fs_process_set_rename_info(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id, int length); +void guac_rdpdr_fs_process_set_rename_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id, int length); /** * Process a set operation for FileAllocationInformation. From the * documentation, this operation is used to set a file's allocation size. */ -void guac_rdpdr_fs_process_set_allocation_info(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id, int length); +void guac_rdpdr_fs_process_set_allocation_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id, int length); /** * Process a set operation for FileDispositionInformation. From the * documentation, this operation is used to mark a file for deletion. */ -void guac_rdpdr_fs_process_set_disposition_info(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id, int length); +void guac_rdpdr_fs_process_set_disposition_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id, int length); /** * Process a set operation for FileEndOfFileInformation. From the * documentation, this operation is used "to set end-of-file information for * a file." */ -void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id, int length); +void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id, int length); /** * Process a set operation for FileBasicInformation. From the documentation, * this is "used to set file information such as the times of creation, last * access, last write, and change, in addition to file attributes." */ -void guac_rdpdr_fs_process_set_basic_info(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id, int length); +void guac_rdpdr_fs_process_set_basic_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id, int length); #endif diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_vol_info.c b/src/protocols/rdp/rdpdr_fs_messages_vol_info.c similarity index 66% rename from src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_vol_info.c rename to src/protocols/rdp/rdpdr_fs_messages_vol_info.c index 1cc051f0..dc3a5e10 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_vol_info.c +++ b/src/protocols/rdp/rdpdr_fs_messages_vol_info.c @@ -18,9 +18,8 @@ */ #include "config.h" - +#include "rdpdr.h" #include "rdpdr_messages.h" -#include "rdpdr_service.h" #include "rdp_fs.h" #include "rdp_status.h" @@ -28,13 +27,14 @@ #include #include -void guac_rdpdr_fs_process_query_volume_info(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id) { +void guac_rdpdr_fs_process_query_volume_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id) { wStream* output_stream = guac_rdpdr_new_io_completion(device, completion_id, STATUS_SUCCESS, 21 + GUAC_FILESYSTEM_LABEL_LENGTH); - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, file_id); @@ -46,14 +46,13 @@ void guac_rdpdr_fs_process_query_volume_info(guac_rdpdr_device* device, /* Reserved field must not be sent */ Stream_Write(output_stream, GUAC_FILESYSTEM_LABEL, GUAC_FILESYSTEM_LABEL_LENGTH); - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -void guac_rdpdr_fs_process_query_size_info(guac_rdpdr_device* device, wStream* input_stream, - int file_id, int completion_id) { +void guac_rdpdr_fs_process_query_size_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id) { guac_rdp_fs_info info = {0}; guac_rdp_fs_get_info((guac_rdp_fs*) device->data, &info); @@ -61,7 +60,7 @@ void guac_rdpdr_fs_process_query_size_info(guac_rdpdr_device* device, wStream* i wStream* output_stream = guac_rdpdr_new_io_completion(device, completion_id, STATUS_SUCCESS, 28); - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, file_id); @@ -71,19 +70,18 @@ void guac_rdpdr_fs_process_query_size_info(guac_rdpdr_device* device, wStream* i Stream_Write_UINT32(output_stream, 1); /* SectorsPerAllocationUnit */ Stream_Write_UINT32(output_stream, info.block_size); /* BytesPerSector */ - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -void guac_rdpdr_fs_process_query_device_info(guac_rdpdr_device* device, wStream* input_stream, - int file_id, int completion_id) { +void guac_rdpdr_fs_process_query_device_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id) { wStream* output_stream = guac_rdpdr_new_io_completion(device, completion_id, STATUS_SUCCESS, 12); - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, file_id); @@ -91,21 +89,20 @@ void guac_rdpdr_fs_process_query_device_info(guac_rdpdr_device* device, wStream* Stream_Write_UINT32(output_stream, FILE_DEVICE_DISK); /* DeviceType */ Stream_Write_UINT32(output_stream, 0); /* Characteristics */ - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -void guac_rdpdr_fs_process_query_attribute_info(guac_rdpdr_device* device, wStream* input_stream, - int file_id, int completion_id) { +void guac_rdpdr_fs_process_query_attribute_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id) { int name_len = guac_utf8_strlen(device->device_name); wStream* output_stream = guac_rdpdr_new_io_completion(device, completion_id, STATUS_SUCCESS, 16 + name_len); - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, file_id); @@ -118,14 +115,13 @@ void guac_rdpdr_fs_process_query_attribute_info(guac_rdpdr_device* device, wStre Stream_Write_UINT32(output_stream, name_len); Stream_Write(output_stream, device->device_name, name_len); - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -void guac_rdpdr_fs_process_query_full_size_info(guac_rdpdr_device* device, wStream* input_stream, - int file_id, int completion_id) { +void guac_rdpdr_fs_process_query_full_size_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id) { guac_rdp_fs_info info = {0}; guac_rdp_fs_get_info((guac_rdp_fs*) device->data, &info); @@ -133,7 +129,7 @@ void guac_rdpdr_fs_process_query_full_size_info(guac_rdpdr_device* device, wStre wStream* output_stream = guac_rdpdr_new_io_completion(device, completion_id, STATUS_SUCCESS, 36); - guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, file_id); @@ -144,9 +140,7 @@ void guac_rdpdr_fs_process_query_full_size_info(guac_rdpdr_device* device, wStre Stream_Write_UINT32(output_stream, 1); /* SectorsPerAllocationUnit */ Stream_Write_UINT32(output_stream, info.block_size); /* BytesPerSector */ - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_vol_info.h b/src/protocols/rdp/rdpdr_fs_messages_vol_info.h similarity index 61% rename from src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_vol_info.h rename to src/protocols/rdp/rdpdr_fs_messages_vol_info.h index b0e3629f..1c34127e 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages_vol_info.h +++ b/src/protocols/rdp/rdpdr_fs_messages_vol_info.h @@ -18,8 +18,8 @@ */ -#ifndef __GUAC_RDPDR_FS_MESSAGES_VOL_INFO_H -#define __GUAC_RDPDR_FS_MESSAGES_VOL_INFO_H +#ifndef GUAC_RDPDR_FS_MESSAGES_VOL_INFO_H +#define GUAC_RDPDR_FS_MESSAGES_VOL_INFO_H /** * Handlers for directory queries received over the RDPDR channel via the @@ -30,8 +30,7 @@ */ #include "config.h" - -#include "rdpdr_service.h" +#include "rdpdr.h" #include @@ -40,32 +39,37 @@ * documentation, this is "used to query information for a volume on which a * file system is mounted." */ -void guac_rdpdr_fs_process_query_volume_info(guac_rdpdr_device* device, wStream* input_stream, - int file_id, int completion_id); +void guac_rdpdr_fs_process_query_volume_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id); /** * Processes a query request for FileFsSizeInformation. */ -void guac_rdpdr_fs_process_query_size_info(guac_rdpdr_device* device, wStream* input_stream, - int file_id, int completion_id); +void guac_rdpdr_fs_process_query_size_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id); /** * Processes a query request for FileFsAttributeInformation. */ -void guac_rdpdr_fs_process_query_attribute_info(guac_rdpdr_device* device, wStream* input_stream, - int file_id, int completion_id); +void guac_rdpdr_fs_process_query_attribute_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id); /** * Processes a query request for FileFsFullSizeInformation. */ -void guac_rdpdr_fs_process_query_full_size_info(guac_rdpdr_device* device, wStream* input_stream, - int file_id, int completion_id); +void guac_rdpdr_fs_process_query_full_size_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id); /** * Processes a query request for FileFsDeviceInformation. */ -void guac_rdpdr_fs_process_query_device_info(guac_rdpdr_device* device, wStream* input_stream, - int file_id, int completion_id); +void guac_rdpdr_fs_process_query_device_info(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id); #endif diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_service.c b/src/protocols/rdp/rdpdr_fs_service.c similarity index 65% rename from src/protocols/rdp/guac_rdpdr/rdpdr_fs_service.c rename to src/protocols/rdp/rdpdr_fs_service.c index 187bf9c4..d0532022 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_service.c +++ b/src/protocols/rdp/rdpdr_fs_service.c @@ -19,11 +19,10 @@ #include "config.h" - #include "rdp.h" +#include "rdpdr.h" #include "rdpdr_fs_messages.h" #include "rdpdr_messages.h" -#include "rdpdr_service.h" #include #include @@ -31,99 +30,114 @@ #include #include -static void guac_rdpdr_device_fs_iorequest_handler(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id, int major_func, int minor_func) { +static void guac_rdpdr_device_fs_iorequest_handler(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id, int major_func, int minor_func) { switch (major_func) { /* File open */ case IRP_MJ_CREATE: - guac_rdpdr_fs_process_create(device, input_stream, completion_id); + guac_rdpdr_fs_process_create(svc, device, input_stream, + completion_id); break; /* File close */ case IRP_MJ_CLOSE: - guac_rdpdr_fs_process_close(device, input_stream, file_id, completion_id); + guac_rdpdr_fs_process_close(svc, device, input_stream, file_id, + completion_id); break; /* File read */ case IRP_MJ_READ: - guac_rdpdr_fs_process_read(device, input_stream, file_id, completion_id); + guac_rdpdr_fs_process_read(svc, device, input_stream, file_id, + completion_id); break; /* File write */ case IRP_MJ_WRITE: - guac_rdpdr_fs_process_write(device, input_stream, file_id, completion_id); + guac_rdpdr_fs_process_write(svc, device, input_stream, file_id, + completion_id); break; /* Device control request (Windows FSCTL_ control codes) */ case IRP_MJ_DEVICE_CONTROL: - guac_rdpdr_fs_process_device_control(device, input_stream, file_id, completion_id); + guac_rdpdr_fs_process_device_control(svc, device, input_stream, + file_id, completion_id); break; /* Query volume (drive) information */ case IRP_MJ_QUERY_VOLUME_INFORMATION: - guac_rdpdr_fs_process_volume_info(device, input_stream, file_id, completion_id); + guac_rdpdr_fs_process_volume_info(svc, device, input_stream, + file_id, completion_id); break; /* Set volume (drive) information */ case IRP_MJ_SET_VOLUME_INFORMATION: - guac_rdpdr_fs_process_set_volume_info(device, input_stream, file_id, completion_id); + guac_rdpdr_fs_process_set_volume_info(svc, device, input_stream, + file_id, completion_id); break; /* Query file information */ case IRP_MJ_QUERY_INFORMATION: - guac_rdpdr_fs_process_file_info(device, input_stream, file_id, completion_id); + guac_rdpdr_fs_process_file_info(svc, device, input_stream, file_id, + completion_id); break; /* Set file information */ case IRP_MJ_SET_INFORMATION: - guac_rdpdr_fs_process_set_file_info(device, input_stream, file_id, completion_id); + guac_rdpdr_fs_process_set_file_info(svc, device, input_stream, + file_id, completion_id); break; case IRP_MJ_DIRECTORY_CONTROL: /* Enumerate directory contents */ if (minor_func == IRP_MN_QUERY_DIRECTORY) - guac_rdpdr_fs_process_query_directory(device, input_stream, file_id, completion_id); + guac_rdpdr_fs_process_query_directory(svc, device, + input_stream, file_id, completion_id); /* Request notification of changes to directory */ else if (minor_func == IRP_MN_NOTIFY_CHANGE_DIRECTORY) - guac_rdpdr_fs_process_notify_change_directory(device, input_stream, + guac_rdpdr_fs_process_notify_change_directory(svc, device, + input_stream, file_id, completion_id); break; /* Lock/unlock portions of a file */ case IRP_MJ_LOCK_CONTROL: - guac_rdpdr_fs_process_lock_control(device, input_stream, file_id, completion_id); + guac_rdpdr_fs_process_lock_control(svc, device, input_stream, + file_id, completion_id); break; default: - guac_client_log(device->rdpdr->client, GUAC_LOG_ERROR, + guac_client_log(svc->client, GUAC_LOG_ERROR, "Unknown filesystem I/O request function: 0x%x/0x%x", major_func, minor_func); } } -static void guac_rdpdr_device_fs_free_handler(guac_rdpdr_device* device) { +static void guac_rdpdr_device_fs_free_handler(guac_rdp_common_svc* svc, + guac_rdpdr_device* device) { Stream_Free(device->device_announce, 1); } -void guac_rdpdr_register_fs(guac_rdpdr* rdpdr, char* drive_name) { +void guac_rdpdr_register_fs(guac_rdp_common_svc* svc, char* drive_name) { - guac_client* client = rdpdr->client; + guac_client* client = svc->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + + guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data; int id = rdpdr->devices_registered++; /* Get new device */ guac_rdpdr_device* device = &(rdpdr->devices[id]); /* Init device */ - device->rdpdr = rdpdr; device->device_id = id; device->device_name = drive_name; int device_name_len = guac_utf8_strlen(device->device_name); diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_service.h b/src/protocols/rdp/rdpdr_fs_service.h similarity index 91% rename from src/protocols/rdp/guac_rdpdr/rdpdr_fs_service.h rename to src/protocols/rdp/rdpdr_fs_service.h index af44ac8b..a3775f95 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_service.h +++ b/src/protocols/rdp/rdpdr_fs_service.h @@ -18,8 +18,8 @@ */ -#ifndef __GUAC_RDPDR_FS_H -#define __GUAC_RDPDR_FS_H +#ifndef GUAC_RDPDR_FS_H +#define GUAC_RDPDR_FS_H /** * Functions and macros specific to filesystem handling and initialization @@ -33,8 +33,7 @@ */ #include "config.h" - -#include "rdpdr_service.h" +#include "rdpdr.h" #include @@ -48,7 +47,7 @@ * @param drive_name * The name of the redirected drive to display in the RDP connection. */ -void guac_rdpdr_register_fs(guac_rdpdr* rdpdr, char* drive_name); +void guac_rdpdr_register_fs(guac_rdp_common_svc* svc, char* drive_name); #endif diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.c b/src/protocols/rdp/rdpdr_messages.c similarity index 68% rename from src/protocols/rdp/guac_rdpdr/rdpdr_messages.c rename to src/protocols/rdp/rdpdr_messages.c index d300ccaf..8be7c43e 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.c +++ b/src/protocols/rdp/rdpdr_messages.c @@ -18,10 +18,9 @@ */ #include "config.h" - #include "rdp.h" +#include "rdpdr.h" #include "rdpdr_messages.h" -#include "rdpdr_service.h" #include "unicode.h" #include @@ -31,7 +30,7 @@ #include #include -static void guac_rdpdr_send_client_announce_reply(guac_rdpdr* rdpdr, +static void guac_rdpdr_send_client_announce_reply(guac_rdp_common_svc* svc, unsigned int major, unsigned int minor, unsigned int client_id) { wStream* output_stream = Stream_New(NULL, 12); @@ -45,13 +44,12 @@ static void guac_rdpdr_send_client_announce_reply(guac_rdpdr* rdpdr, Stream_Write_UINT16(output_stream, minor); Stream_Write_UINT32(output_stream, client_id); - rdpdr->entry_points.pVirtualChannelWriteEx(rdpdr->init_handle, - rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -static void guac_rdpdr_send_client_name_request(guac_rdpdr* rdpdr, const char* name) { +static void guac_rdpdr_send_client_name_request(guac_rdp_common_svc* svc, + const char* name) { int name_bytes = strlen(name) + 1; wStream* output_stream = Stream_New(NULL, 16 + name_bytes); @@ -66,16 +64,14 @@ static void guac_rdpdr_send_client_name_request(guac_rdpdr* rdpdr, const char* n Stream_Write_UINT32(output_stream, name_bytes); Stream_Write(output_stream, name, name_bytes); - rdpdr->entry_points.pVirtualChannelWriteEx(rdpdr->init_handle, - rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -static void guac_rdpdr_send_client_capability(guac_rdpdr* rdpdr) { +static void guac_rdpdr_send_client_capability(guac_rdp_common_svc* svc) { wStream* output_stream = Stream_New(NULL, 256); - guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Sending capabilities..."); + guac_client_log(svc->client, GUAC_LOG_INFO, "Sending capabilities..."); /* Write header */ Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE); @@ -115,14 +111,14 @@ static void guac_rdpdr_send_client_capability(guac_rdpdr* rdpdr) { Stream_Write_UINT16(output_stream, 8); Stream_Write_UINT32(output_stream, DRIVE_CAPABILITY_VERSION_02); - rdpdr->entry_points.pVirtualChannelWriteEx(rdpdr->init_handle, - rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); - guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Capabilities sent."); + guac_rdp_common_svc_write(svc, output_stream); + guac_client_log(svc->client, GUAC_LOG_INFO, "Capabilities sent."); } -static void guac_rdpdr_send_client_device_list_announce_request(guac_rdpdr* rdpdr) { +static void guac_rdpdr_send_client_device_list_announce_request(guac_rdp_common_svc* svc) { + + guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data; /* Calculate number of bytes needed for the stream */ int streamBytes = 16; @@ -144,19 +140,17 @@ static void guac_rdpdr_send_client_device_list_announce_request(guac_rdpdr* rdpd Stream_Buffer(rdpdr->devices[i].device_announce), rdpdr->devices[i].device_announce_len); - guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Registered device %i (%s)", + guac_client_log(svc->client, GUAC_LOG_INFO, "Registered device %i (%s)", rdpdr->devices[i].device_id, rdpdr->devices[i].device_name); } - rdpdr->entry_points.pVirtualChannelWriteEx(rdpdr->init_handle, - rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); - guac_client_log(rdpdr->client, GUAC_LOG_INFO, "All supported devices sent."); + guac_rdp_common_svc_write(svc, output_stream); + guac_client_log(svc->client, GUAC_LOG_INFO, "All supported devices sent."); } -void guac_rdpdr_process_server_announce(guac_rdpdr* rdpdr, +void guac_rdpdr_process_server_announce(guac_rdp_common_svc* svc, wStream* input_stream) { unsigned int major, minor, client_id; @@ -169,21 +163,25 @@ void guac_rdpdr_process_server_announce(guac_rdpdr* rdpdr, if (minor < 12) client_id = random() & 0xFFFF; - guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Connected to RDPDR %u.%u as client 0x%04x", major, minor, client_id); + guac_client_log(svc->client, GUAC_LOG_INFO, "Connected to RDPDR %u.%u as client 0x%04x", major, minor, client_id); /* Respond to announce */ - guac_rdpdr_send_client_announce_reply(rdpdr, major, minor, client_id); + guac_rdpdr_send_client_announce_reply(svc, major, minor, client_id); /* Name request */ - guac_rdpdr_send_client_name_request(rdpdr, ((guac_rdp_client *)rdpdr->client->data)->settings->client_name); + guac_rdpdr_send_client_name_request(svc, ((guac_rdp_client*) svc->client->data)->settings->client_name); } -void guac_rdpdr_process_clientid_confirm(guac_rdpdr* rdpdr, wStream* input_stream) { - guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Client ID confirmed"); +void guac_rdpdr_process_clientid_confirm(guac_rdp_common_svc* svc, + wStream* input_stream) { + guac_client_log(svc->client, GUAC_LOG_INFO, "Client ID confirmed"); } -void guac_rdpdr_process_device_reply(guac_rdpdr* rdpdr, wStream* input_stream) { +void guac_rdpdr_process_device_reply(guac_rdp_common_svc* svc, + wStream* input_stream) { + + guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data; unsigned int device_id, ntstatus; int severity, c, n, facility, code; @@ -201,11 +199,11 @@ void guac_rdpdr_process_device_reply(guac_rdpdr* rdpdr, wStream* input_stream) { if (device_id < rdpdr->devices_registered) { if (severity == 0x0) - guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Device %i (%s) connected successfully", + guac_client_log(svc->client, GUAC_LOG_INFO, "Device %i (%s) connected successfully", device_id, rdpdr->devices[device_id].device_name); else - guac_client_log(rdpdr->client, GUAC_LOG_ERROR, "Problem connecting device %i (%s): " + guac_client_log(svc->client, GUAC_LOG_ERROR, "Problem connecting device %i (%s): " "severity=0x%x, c=0x%x, n=0x%x, facility=0x%x, code=0x%x", device_id, rdpdr->devices[device_id].device_name, severity, c, n, facility, code); @@ -213,11 +211,14 @@ void guac_rdpdr_process_device_reply(guac_rdpdr* rdpdr, wStream* input_stream) { } else - guac_client_log(rdpdr->client, GUAC_LOG_ERROR, "Unknown device ID: 0x%08x", device_id); + guac_client_log(svc->client, GUAC_LOG_ERROR, "Unknown device ID: 0x%08x", device_id); } -void guac_rdpdr_process_device_iorequest(guac_rdpdr* rdpdr, wStream* input_stream) { +void guac_rdpdr_process_device_iorequest(guac_rdp_common_svc* svc, + wStream* input_stream) { + + guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data; int device_id, file_id, completion_id, major_func, minor_func; @@ -233,17 +234,18 @@ void guac_rdpdr_process_device_iorequest(guac_rdpdr* rdpdr, wStream* input_strea /* Call handler on device */ guac_rdpdr_device* device = &(rdpdr->devices[device_id]); - device->iorequest_handler(device, input_stream, + device->iorequest_handler(svc, device, input_stream, file_id, completion_id, major_func, minor_func); } else - guac_client_log(rdpdr->client, GUAC_LOG_ERROR, "Unknown device ID: 0x%08x", device_id); + guac_client_log(svc->client, GUAC_LOG_ERROR, "Unknown device ID: 0x%08x", device_id); } -void guac_rdpdr_process_server_capability(guac_rdpdr* rdpdr, wStream* input_stream) { +void guac_rdpdr_process_server_capability(guac_rdp_common_svc* svc, + wStream* input_stream) { int count; int i; @@ -262,27 +264,30 @@ void guac_rdpdr_process_server_capability(guac_rdpdr* rdpdr, wStream* input_stre Stream_Read_UINT16(input_stream, length); /* Ignore all for now */ - guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Ignoring server capability set type=0x%04x, length=%i", type, length); + guac_client_log(svc->client, GUAC_LOG_INFO, "Ignoring server capability set type=0x%04x, length=%i", type, length); Stream_Seek(input_stream, length - 4); } /* Send own capabilities */ - guac_rdpdr_send_client_capability(rdpdr); + guac_rdpdr_send_client_capability(svc); } -void guac_rdpdr_process_user_loggedon(guac_rdpdr* rdpdr, wStream* input_stream) { +void guac_rdpdr_process_user_loggedon(guac_rdp_common_svc* svc, + wStream* input_stream) { - guac_client_log(rdpdr->client, GUAC_LOG_INFO, "User logged on"); - guac_rdpdr_send_client_device_list_announce_request(rdpdr); + guac_client_log(svc->client, GUAC_LOG_INFO, "User logged on"); + guac_rdpdr_send_client_device_list_announce_request(svc); } -void guac_rdpdr_process_prn_cache_data(guac_rdpdr* rdpdr, wStream* input_stream) { - guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Ignoring printer cached configuration data"); +void guac_rdpdr_process_prn_cache_data(guac_rdp_common_svc* svc, + wStream* input_stream) { + guac_client_log(svc->client, GUAC_LOG_INFO, "Ignoring printer cached configuration data"); } -void guac_rdpdr_process_prn_using_xps(guac_rdpdr* rdpdr, wStream* input_stream) { - guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Printer unexpectedly switched to XPS mode"); +void guac_rdpdr_process_prn_using_xps(guac_rdp_common_svc* svc, + wStream* input_stream) { + guac_client_log(svc->client, GUAC_LOG_INFO, "Printer unexpectedly switched to XPS mode"); } diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h b/src/protocols/rdp/rdpdr_messages.h similarity index 87% rename from src/protocols/rdp/guac_rdpdr/rdpdr_messages.h rename to src/protocols/rdp/rdpdr_messages.h index 451554e4..19c7aaa2 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h +++ b/src/protocols/rdp/rdpdr_messages.h @@ -18,12 +18,11 @@ */ -#ifndef __GUAC_RDPDR_MESSAGES_H -#define __GUAC_RDPDR_MESSAGES_H +#ifndef GUAC_RDPDR_MESSAGES_H +#define GUAC_RDPDR_MESSAGES_H #include "config.h" - -#include "rdpdr_service.h" +#include "rdpdr.h" #include @@ -204,14 +203,14 @@ * Message handlers. */ -void guac_rdpdr_process_server_announce(guac_rdpdr* rdpdr, wStream* input_stream); -void guac_rdpdr_process_clientid_confirm(guac_rdpdr* rdpdr, wStream* input_stream); -void guac_rdpdr_process_device_reply(guac_rdpdr* rdpdr, wStream* input_stream); -void guac_rdpdr_process_device_iorequest(guac_rdpdr* rdpdr, wStream* input_stream); -void guac_rdpdr_process_server_capability(guac_rdpdr* rdpdr, wStream* input_stream); -void guac_rdpdr_process_user_loggedon(guac_rdpdr* rdpdr, wStream* input_stream); -void guac_rdpdr_process_prn_cache_data(guac_rdpdr* rdpdr, wStream* input_stream); -void guac_rdpdr_process_prn_using_xps(guac_rdpdr* rdpdr, wStream* input_stream); +void guac_rdpdr_process_server_announce(guac_rdp_common_svc* svc, wStream* input_stream); +void guac_rdpdr_process_clientid_confirm(guac_rdp_common_svc* svc, wStream* input_stream); +void guac_rdpdr_process_device_reply(guac_rdp_common_svc* svc, wStream* input_stream); +void guac_rdpdr_process_device_iorequest(guac_rdp_common_svc* svc, wStream* input_stream); +void guac_rdpdr_process_server_capability(guac_rdp_common_svc* svc, wStream* input_stream); +void guac_rdpdr_process_user_loggedon(guac_rdp_common_svc* svc, wStream* input_stream); +void guac_rdpdr_process_prn_cache_data(guac_rdp_common_svc* svc, wStream* input_stream); +void guac_rdpdr_process_prn_using_xps(guac_rdp_common_svc* svc, wStream* input_stream); #endif diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_printer.c b/src/protocols/rdp/rdpdr_printer.c similarity index 76% rename from src/protocols/rdp/guac_rdpdr/rdpdr_printer.c rename to src/protocols/rdp/rdpdr_printer.c index 98a3eccb..dbe16de3 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_printer.c +++ b/src/protocols/rdp/rdpdr_printer.c @@ -18,10 +18,9 @@ */ #include "config.h" - +#include "rdpdr.h" #include "rdpdr_messages.h" #include "rdpdr_printer.h" -#include "rdpdr_service.h" #include "rdp.h" #include "rdp_print_job.h" #include "rdp_status.h" @@ -42,10 +41,10 @@ #include #include -void guac_rdpdr_process_print_job_create(guac_rdpdr_device* device, - wStream* input_stream, int completion_id) { +void guac_rdpdr_process_print_job_create(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int completion_id) { - guac_client* client = device->rdpdr->client; + guac_client* client = svc->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Log creation of print job */ @@ -60,16 +59,14 @@ void guac_rdpdr_process_print_job_create(guac_rdpdr_device* device, completion_id, STATUS_SUCCESS, 4); Stream_Write_UINT32(output_stream, 0); /* fileId */ - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -void guac_rdpdr_process_print_job_write(guac_rdpdr_device* device, - wStream* input_stream, int completion_id) { +void guac_rdpdr_process_print_job_write(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int completion_id) { - guac_client* client = device->rdpdr->client; + guac_client* client = svc->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_print_job* job = (guac_rdp_print_job*) rdp_client->active_job; @@ -101,16 +98,14 @@ void guac_rdpdr_process_print_job_write(guac_rdpdr_device* device, Stream_Write_UINT32(output_stream, length); Stream_Write_UINT8(output_stream, 0); /* Padding */ - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); } -void guac_rdpdr_process_print_job_close(guac_rdpdr_device* device, - wStream* input_stream, int completion_id) { +void guac_rdpdr_process_print_job_close(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int completion_id) { - guac_client* client = device->rdpdr->client; + guac_client* client = svc->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_print_job* job = (guac_rdp_print_job*) rdp_client->active_job; @@ -124,38 +119,40 @@ void guac_rdpdr_process_print_job_close(guac_rdpdr_device* device, completion_id, STATUS_SUCCESS, 4); Stream_Write_UINT32(output_stream, 0); /* Padding */ - device->rdpdr->entry_points.pVirtualChannelWriteEx(device->rdpdr->init_handle, - device->rdpdr->open_handle, Stream_Buffer(output_stream), - Stream_GetPosition(output_stream), output_stream); + guac_rdp_common_svc_write(svc, output_stream); /* Log end of print job */ guac_client_log(client, GUAC_LOG_INFO, "Print job closed"); } -static void guac_rdpdr_device_printer_iorequest_handler(guac_rdpdr_device* device, - wStream* input_stream, int file_id, int completion_id, int major_func, int minor_func) { +static void guac_rdpdr_device_printer_iorequest_handler(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, wStream* input_stream, int file_id, + int completion_id, int major_func, int minor_func) { switch (major_func) { /* Print job create */ case IRP_MJ_CREATE: - guac_rdpdr_process_print_job_create(device, input_stream, completion_id); + guac_rdpdr_process_print_job_create(svc, device, input_stream, + completion_id); break; /* Printer job write */ case IRP_MJ_WRITE: - guac_rdpdr_process_print_job_write(device, input_stream, completion_id); + guac_rdpdr_process_print_job_write(svc, device, input_stream, + completion_id); break; /* Printer job close */ case IRP_MJ_CLOSE: - guac_rdpdr_process_print_job_close(device, input_stream, completion_id); + guac_rdpdr_process_print_job_close(svc, device, input_stream, + completion_id); break; /* Log unknown */ default: - guac_client_log(device->rdpdr->client, GUAC_LOG_ERROR, + guac_client_log(svc->client, GUAC_LOG_ERROR, "Unknown printer I/O request function: 0x%x/0x%x", major_func, minor_func); @@ -163,21 +160,22 @@ static void guac_rdpdr_device_printer_iorequest_handler(guac_rdpdr_device* devic } -static void guac_rdpdr_device_printer_free_handler(guac_rdpdr_device* device) { +static void guac_rdpdr_device_printer_free_handler(guac_rdp_common_svc* svc, + guac_rdpdr_device* device) { Stream_Free(device->device_announce, 1); } -void guac_rdpdr_register_printer(guac_rdpdr* rdpdr, char* printer_name) { +void guac_rdpdr_register_printer(guac_rdp_common_svc* svc, char* printer_name) { + guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data; int id = rdpdr->devices_registered++; /* Get new device */ guac_rdpdr_device* device = &(rdpdr->devices[id]); /* Init device */ - device->rdpdr = rdpdr; device->device_id = id; device->device_name = printer_name; int device_name_len = guac_utf8_strlen(device->device_name); diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_printer.h b/src/protocols/rdp/rdpdr_printer.h similarity index 88% rename from src/protocols/rdp/guac_rdpdr/rdpdr_printer.h rename to src/protocols/rdp/rdpdr_printer.h index 210d512c..c9b30ddc 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_printer.h +++ b/src/protocols/rdp/rdpdr_printer.h @@ -18,12 +18,11 @@ */ -#ifndef __GUAC_RDPDR_PRINTER_H -#define __GUAC_RDPDR_PRINTER_H +#ifndef GUAC_RDPDR_PRINTER_H +#define GUAC_RDPDR_PRINTER_H #include "config.h" - -#include "rdpdr_service.h" +#include "rdpdr.h" #include @@ -38,7 +37,7 @@ * The name of the printer that will be registered with the RDP * connection and passed through to the server. */ -void guac_rdpdr_register_printer(guac_rdpdr* rdpdr, char* printer_name); +void guac_rdpdr_register_printer(guac_rdp_common_svc* svc, char* printer_name); #endif From 875d51c1ed788b68f93f5bbcbc19595d9a5aeba9 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 22 Dec 2019 20:14:44 -0800 Subject: [PATCH 047/109] GUACAMOLE-249: Dynamically wrap channel entry points (FreeRDP will refuse to associate the same entry point with multiple channels). --- src/protocols/rdp/.gitignore | 1 + src/protocols/rdp/Makefile.am | 24 +++-- src/protocols/rdp/channels.c | 49 +++++++++- src/protocols/rdp/channels.h | 94 ++++++++++++++++++++ src/protocols/rdp/generate-entry-wrappers.pl | 77 ++++++++++++++++ 5 files changed, 236 insertions(+), 9 deletions(-) create mode 100755 src/protocols/rdp/generate-entry-wrappers.pl diff --git a/src/protocols/rdp/.gitignore b/src/protocols/rdp/.gitignore index 9f87ecb2..5cb764a7 100644 --- a/src/protocols/rdp/.gitignore +++ b/src/protocols/rdp/.gitignore @@ -4,5 +4,6 @@ _generated_runner.c test_rdp # Autogenerated sources +_generated_channel_entry_wrappers.c _generated_keymaps.c diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index 8657420e..443ed0b6 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -33,7 +33,8 @@ SUBDIRS = . tests # Main RDP client library # -nodist_libguac_client_rdp_la_SOURCES = \ +nodist_libguac_client_rdp_la_SOURCES = \ + _generated_channel_entry_wrappers.c \ _generated_keymaps.c libguac_client_rdp_la_SOURCES = \ @@ -200,11 +201,16 @@ libguac_client_rdp_la_LIBADD += @COMMON_SSH_LTLIB@ endif # -# Autogenerate keymaps +# Autogenerated keymaps and channel wrapper functions # -CLEANFILES = _generated_keymaps.c -BUILT_SOURCES = _generated_keymaps.c +CLEANFILES = \ + _generated_channel_entry_wrappers.c \ + _generated_keymaps.c + +BUILT_SOURCES = \ + _generated_channel_entry_wrappers.c \ + _generated_keymaps.c rdp_keymaps = \ $(srcdir)/keymaps/base.keymap \ @@ -224,9 +230,13 @@ rdp_keymaps = \ $(srcdir)/keymaps/tr_tr_qwerty.keymap _generated_keymaps.c: $(rdp_keymaps) - $(srcdir)/keymaps/generate.pl $(rdp_keymaps) + $(AM_V_GEN) $(srcdir)/keymaps/generate.pl $(rdp_keymaps) -EXTRA_DIST = \ - $(rdp_keymaps) \ +_generated_channel_entry_wrappers.c: $(srcdir)/channels.h $(srcdir)/generate-entry-wrappers.pl + $(AM_V_GEN) $(srcdir)/generate-entry-wrappers.pl $(srcdir)/channels.h + +EXTRA_DIST = \ + $(rdp_keymaps) \ + generate-entry-wrappers.pl \ keymaps/generate.pl diff --git a/src/protocols/rdp/channels.c b/src/protocols/rdp/channels.c index 63512fe0..368846a8 100644 --- a/src/protocols/rdp/channels.c +++ b/src/protocols/rdp/channels.c @@ -18,12 +18,53 @@ */ #include "config.h" +#include "channels.h" #include "rdp.h" #include #include #include +int guac_rdp_wrapped_entry_ex_count = 0; + +int guac_rdp_wrapped_entry_count = 0; + +PVIRTUALCHANNELENTRYEX guac_rdp_wrapped_entry_ex[GUAC_RDP_MAX_CHANNELS] = { NULL }; + +PVIRTUALCHANNELENTRY guac_rdp_wrapped_entry[GUAC_RDP_MAX_CHANNELS] = { NULL }; + +PVIRTUALCHANNELENTRYEX guac_rdp_plugin_wrap_entry_ex(PVIRTUALCHANNELENTRYEX entry_ex) { + + /* Do not wrap if there is insufficient space to store the wrapped + * function */ + if (guac_rdp_wrapped_entry_ex_count == GUAC_RDP_MAX_CHANNELS) + return entry_ex; + + /* Generate wrapped version of provided entry point */ + PVIRTUALCHANNELENTRYEX wrapper = guac_rdp_entry_ex_wrappers[guac_rdp_wrapped_entry_ex_count]; + guac_rdp_wrapped_entry_ex[guac_rdp_wrapped_entry_ex_count] = entry_ex; + guac_rdp_wrapped_entry_ex_count++; + + return wrapper; + +} + +PVIRTUALCHANNELENTRY guac_rdp_plugin_wrap_entry(PVIRTUALCHANNELENTRY entry) { + + /* Do not wrap if there is insufficient space to store the wrapped + * function */ + if (guac_rdp_wrapped_entry_count == GUAC_RDP_MAX_CHANNELS) + return entry; + + /* Generate wrapped version of provided entry point */ + PVIRTUALCHANNELENTRY wrapper = guac_rdp_entry_wrappers[guac_rdp_wrapped_entry_count]; + guac_rdp_wrapped_entry[guac_rdp_wrapped_entry_count] = entry; + guac_rdp_wrapped_entry_count++; + + return wrapper; + +} + int guac_freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, const char* name, void* data) { @@ -31,15 +72,19 @@ int guac_freerdp_channels_load_plugin(rdpChannels* channels, PVIRTUALCHANNELENTRYEX entry_ex = (PVIRTUALCHANNELENTRYEX) (void*) freerdp_load_channel_addin_entry(name, NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC | FREERDP_ADDIN_CHANNEL_ENTRYEX); - if (entry_ex != NULL) + if (entry_ex != NULL) { + entry_ex = guac_rdp_plugin_wrap_entry_ex(entry_ex); return freerdp_channels_client_load_ex(channels, settings, entry_ex, data); + } /* Lacking the "ex" entry point, attempt to load using the non-ex version */ PVIRTUALCHANNELENTRY entry = freerdp_load_channel_addin_entry(name, NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC); - if (entry != NULL) + if (entry != NULL) { + entry = guac_rdp_plugin_wrap_entry(entry); return freerdp_channels_client_load(channels, settings, entry, data); + } /* The plugin does not exist / cannot be loaded */ return 1; diff --git a/src/protocols/rdp/channels.h b/src/protocols/rdp/channels.h index d8a8f619..d31a685b 100644 --- a/src/protocols/rdp/channels.h +++ b/src/protocols/rdp/channels.h @@ -25,6 +25,22 @@ #include #include +/** + * The maximum number of static channels supported by Guacamole's RDP support. + * This value should be given a value which is at least the value of FreeRDP's + * CHANNEL_MAX_COUNT. + * + * NOTE: The value of this macro must be specified statically (not as a + * reference to CHANNEL_MAX_COUNT), as its value is extracted and used by the + * entry point wrapper code generator (generate-entry-wrappers.pl). + */ +#define GUAC_RDP_MAX_CHANNELS 64 + +/* Validate GUAC_RDP_MAX_CHANNELS is sane at compile time */ +#if GUAC_RDP_MAX_CHANNELS < CHANNEL_MAX_COUNT +#error "GUAC_RDP_MAX_CHANNELS must not be less than CHANNEL_MAX_COUNT" +#endif + /** * Loads the FreeRDP plugin having the given name. This function is a drop-in * replacement for freerdp_channels_load_plugin() which additionally loads @@ -105,5 +121,83 @@ int guac_freerdp_channels_load_plugin(rdpChannels* channels, void guac_freerdp_dynamic_channel_collection_add(rdpSettings* settings, const char* name, ...); +/** + * The number of wrapped channel entry points currently stored within + * guac_rdp_wrapped_entry_ex. + */ +extern int guac_rdp_wrapped_entry_ex_count; + +/** + * All currently wrapped entry points that use the PVIRTUALCHANNELENTRYEX + * variant. + */ +extern PVIRTUALCHANNELENTRYEX guac_rdp_wrapped_entry_ex[GUAC_RDP_MAX_CHANNELS]; + +/** + * Lookup table of wrapper functions for PVIRTUALCHANNELENTRYEX entry points. + * Each function within this array is generated at compile time by the entry + * point wrapper code generator (generate-entry-wrappers.pl) and automatically + * invokes the corresponding wrapped entry point stored within + * guac_rdp_wrapped_entry_ex. + */ +extern PVIRTUALCHANNELENTRYEX guac_rdp_entry_ex_wrappers[GUAC_RDP_MAX_CHANNELS]; + +/** + * Wraps the provided entry point function, returning a different entry point + * which simply invokes the original. As long as this function is not invoked + * more than GUAC_RDP_MAX_CHANNELS times, each returned entry point will be + * unique, even if the provided entry point is not. As FreeRDP will refuse to + * load a plugin if its entry point is already loaded, this allows a single + * FreeRDP plugin to be loaded multiple times. + * + * @param entry_ex + * The entry point function to wrap. + * + * @return + * A wrapped version of the provided entry point, or the unwrapped entry + * point if there is insufficient space remaining within + * guac_rdp_entry_ex_wrappers to wrap the entry point. + */ +PVIRTUALCHANNELENTRYEX guac_rdp_plugin_wrap_entry_ex(PVIRTUALCHANNELENTRYEX entry_ex); + +/** + * The number of wrapped channel entry points currently stored within + * guac_rdp_wrapped_entry. + */ +extern int guac_rdp_wrapped_entry_count; + +/** + * All currently wrapped entry points that use the PVIRTUALCHANNELENTRY + * variant. + */ +extern PVIRTUALCHANNELENTRY guac_rdp_wrapped_entry[GUAC_RDP_MAX_CHANNELS]; + +/** + * Lookup table of wrapper functions for PVIRTUALCHANNELENTRY entry points. + * Each function within this array is generated at compile time by the entry + * point wrapper code generator (generate-entry-wrappers.pl) and automatically + * invokes the corresponding wrapped entry point stored within + * guac_rdp_wrapped_entry. + */ +extern PVIRTUALCHANNELENTRY guac_rdp_entry_wrappers[GUAC_RDP_MAX_CHANNELS]; + +/** + * Wraps the provided entry point function, returning a different entry point + * which simply invokes the original. As long as this function is not invoked + * more than GUAC_RDP_MAX_CHANNELS times, each returned entry point will be + * unique, even if the provided entry point is not. As FreeRDP will refuse to + * load a plugin if its entry point is already loaded, this allows a single + * FreeRDP plugin to be loaded multiple times. + * + * @param entry + * The entry point function to wrap. + * + * @return + * A wrapped version of the provided entry point, or the unwrapped entry + * point if there is insufficient space remaining within + * guac_rdp_entry_wrappers to wrap the entry point. + */ +PVIRTUALCHANNELENTRY guac_rdp_plugin_wrap_entry(PVIRTUALCHANNELENTRY entry); + #endif diff --git a/src/protocols/rdp/generate-entry-wrappers.pl b/src/protocols/rdp/generate-entry-wrappers.pl new file mode 100755 index 00000000..21efdbca --- /dev/null +++ b/src/protocols/rdp/generate-entry-wrappers.pl @@ -0,0 +1,77 @@ +#!/usr/bin/env perl +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# + +# +# generate-entry-wrappers.pl +# +# Generates C source which defines wrapper functions for FreeRDP plugin entry +# points, allowing multiple instances of the same plugin to be loaded despite +# otherwise always having the same entry point. +# +# The resulting source is stored within "_generated_channel_entry_wrappers.c". +# + +use strict; + +## +## The maximum number of static channels supported by Guacamole's RDP support. +## +my $GUAC_RDP_MAX_CHANNELS; + +# Extract value of GUAC_RDP_MAX_CHANNELS macro from provided source +while (<>) { + if ((my $value) = m/^\s*#define\s+GUAC_RDP_MAX_CHANNELS\s+(\d+)\s*$/) { + $GUAC_RDP_MAX_CHANNELS = $value; + } +} + +open OUTPUT, ">", "_generated_channel_entry_wrappers.c"; + +# Generate required headers +print OUTPUT <<"EOF"; +#include "channels.h" +#include +#include +EOF + +# Generate wrapper definitions for PVIRTUALCHANNELENTRYEX entry point variant +print OUTPUT <<"EOF" for (1..$GUAC_RDP_MAX_CHANNELS); +static BOOL guac_rdp_plugin_entry_ex_wrapper$_(PCHANNEL_ENTRY_POINTS_EX entry_points_ex, PVOID init_handle) { + return guac_rdp_wrapped_entry_ex[$_ - 1](entry_points_ex, init_handle); +} +EOF + +# Generate wrapper definitions for PVIRTUALCHANNELENTRY entry point variant +print OUTPUT <<"EOF" for (1..$GUAC_RDP_MAX_CHANNELS); +static BOOL guac_rdp_plugin_entry_wrapper$_(PCHANNEL_ENTRY_POINTS entry_points) { + return guac_rdp_wrapped_entry[$_ - 1](entry_points); +} +EOF + +# Populate lookup table of PVIRTUALCHANNELENTRYEX wrapper functions +print OUTPUT "PVIRTUALCHANNELENTRYEX guac_rdp_entry_ex_wrappers[$GUAC_RDP_MAX_CHANNELS] = {\n"; +print OUTPUT " guac_rdp_plugin_entry_ex_wrapper$_,\n" for (1..$GUAC_RDP_MAX_CHANNELS); +print OUTPUT "};\n"; + +# Populate lookup table of PVIRTUALCHANNELENTRY wrapper functions +print OUTPUT "PVIRTUALCHANNELENTRY guac_rdp_entry_wrappers[$GUAC_RDP_MAX_CHANNELS] = {\n"; +print OUTPUT " guac_rdp_plugin_entry_wrapper$_,\n" for (1..$GUAC_RDP_MAX_CHANNELS); +print OUTPUT "};\n"; + From 827951dcf61f3edb7191f4374f72c7c91caace03 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 22 Dec 2019 21:24:07 -0800 Subject: [PATCH 048/109] GUACAMOLE-249: Remove RDP constant definitions which are defined within FreeRDP headers. --- src/protocols/rdp/rdpdr.c | 1 + src/protocols/rdp/rdpdr_fs_messages.c | 1 + src/protocols/rdp/rdpdr_fs_service.c | 1 + src/protocols/rdp/rdpdr_messages.c | 15 +-- src/protocols/rdp/rdpdr_messages.h | 152 -------------------------- src/protocols/rdp/rdpdr_printer.c | 1 + src/protocols/rdp/rdpsnd.c | 1 + src/protocols/rdp/rdpsnd_messages.c | 1 + src/protocols/rdp/rdpsnd_messages.h | 68 ------------ 9 files changed, 14 insertions(+), 227 deletions(-) diff --git a/src/protocols/rdp/rdpdr.c b/src/protocols/rdp/rdpdr.c index aabe9399..f334e5e5 100644 --- a/src/protocols/rdp/rdpdr.c +++ b/src/protocols/rdp/rdpdr.c @@ -28,6 +28,7 @@ #include "rdpdr_messages.h" #include "rdpdr_printer.h" +#include #include #include #include diff --git a/src/protocols/rdp/rdpdr_fs_messages.c b/src/protocols/rdp/rdpdr_fs_messages.c index b23a0107..02646191 100644 --- a/src/protocols/rdp/rdpdr_fs_messages.c +++ b/src/protocols/rdp/rdpdr_fs_messages.c @@ -28,6 +28,7 @@ #include "rdp_status.h" #include "unicode.h" +#include #include #include #include diff --git a/src/protocols/rdp/rdpdr_fs_service.c b/src/protocols/rdp/rdpdr_fs_service.c index d0532022..933cd7e5 100644 --- a/src/protocols/rdp/rdpdr_fs_service.c +++ b/src/protocols/rdp/rdpdr_fs_service.c @@ -24,6 +24,7 @@ #include "rdpdr_fs_messages.h" #include "rdpdr_messages.h" +#include #include #include #include diff --git a/src/protocols/rdp/rdpdr_messages.c b/src/protocols/rdp/rdpdr_messages.c index 8be7c43e..06f1c55c 100644 --- a/src/protocols/rdp/rdpdr_messages.c +++ b/src/protocols/rdp/rdpdr_messages.c @@ -23,6 +23,7 @@ #include "rdpdr_messages.h" #include "unicode.h" +#include #include #include #include @@ -87,15 +88,15 @@ static void guac_rdpdr_send_client_capability(guac_rdp_common_svc* svc) { Stream_Write_UINT32(output_stream, GENERAL_CAPABILITY_VERSION_02); /* General capability data */ - Stream_Write_UINT32(output_stream, GUAC_OS_TYPE); /* osType - required to be ignored */ - Stream_Write_UINT32(output_stream, 0); /* osVersion */ - Stream_Write_UINT16(output_stream, RDP_CLIENT_MAJOR_ALL); /* protocolMajor */ - Stream_Write_UINT16(output_stream, RDP_CLIENT_MINOR_5_2); /* protocolMinor */ - Stream_Write_UINT32(output_stream, 0xFFFF); /* ioCode1 */ - Stream_Write_UINT32(output_stream, 0); /* ioCode2 */ + Stream_Write_UINT32(output_stream, GUAC_OS_TYPE); /* osType - required to be ignored */ + Stream_Write_UINT32(output_stream, 0); /* osVersion */ + Stream_Write_UINT16(output_stream, 1); /* protocolMajor - must be set to 1 */ + Stream_Write_UINT16(output_stream, RDPDR_MINOR_RDP_VERSION_5_2); /* protocolMinor */ + Stream_Write_UINT32(output_stream, 0xFFFF); /* ioCode1 */ + Stream_Write_UINT32(output_stream, 0); /* ioCode2 */ Stream_Write_UINT32(output_stream, RDPDR_DEVICE_REMOVE_PDUS - | RDPDR_CLIENT_DISPLAY_NAME + | RDPDR_CLIENT_DISPLAY_NAME_PDU | RDPDR_USER_LOGGEDON_PDU); /* extendedPDU */ Stream_Write_UINT32(output_stream, 0); /* extraFlags1 */ Stream_Write_UINT32(output_stream, 0); /* extraFlags2 */ diff --git a/src/protocols/rdp/rdpdr_messages.h b/src/protocols/rdp/rdpdr_messages.h index 19c7aaa2..221db893 100644 --- a/src/protocols/rdp/rdpdr_messages.h +++ b/src/protocols/rdp/rdpdr_messages.h @@ -28,36 +28,6 @@ #include -/** - * Identifies the "core" component of RDPDR as the destination of the received - * packet. - */ -#define RDPDR_CTYP_CORE 0x4472 - -/** - * Identifies the printing component of RDPDR as the destination of the - * received packet. - */ -#define RDPDR_CTYP_PRN 0x5052 - -/* - * Packet IDs as required by the RDP spec (see: [MS-RDPEFS].pdf) - */ - -#define PAKID_CORE_SERVER_ANNOUNCE 0x496E -#define PAKID_CORE_CLIENTID_CONFIRM 0x4343 -#define PAKID_CORE_CLIENT_NAME 0x434E -#define PAKID_CORE_DEVICELIST_ANNOUNCE 0x4441 -#define PAKID_CORE_DEVICE_REPLY 0x6472 -#define PAKID_CORE_DEVICE_IOREQUEST 0x4952 -#define PAKID_CORE_DEVICE_IOCOMPLETION 0x4943 -#define PAKID_CORE_SERVER_CAPABILITY 0x5350 -#define PAKID_CORE_CLIENT_CAPABILITY 0x4350 -#define PAKID_CORE_DEVICELIST_REMOVE 0x444D -#define PAKID_PRN_CACHE_DATA 0x5043 -#define PAKID_CORE_USER_LOGGEDON 0x554C -#define PAKID_PRN_USING_XPS 0x5543 - /** * A 32-bit arbitrary value for the osType field of certain requests. As this * value is defined as completely arbitrary and required to be ignored by the @@ -77,128 +47,6 @@ #define GUAC_FILESYSTEM_LABEL "G\0U\0A\0C\0F\0I\0L\0E\0" #define GUAC_FILESYSTEM_LABEL_LENGTH 16 -/* - * Capability types - */ - -#define CAP_GENERAL_TYPE 1 -#define CAP_PRINTER_TYPE 2 -#define CAP_PORT_TYPE 3 -#define CAP_DRIVE_TYPE 4 -#define CAP_SMARTCARD_TYPE 5 - -/* - * General capability header versions. - */ - -#define GENERAL_CAPABILITY_VERSION_01 1 -#define GENERAL_CAPABILITY_VERSION_02 2 - -/* - * Print capability header versions. - */ - -#define PRINT_CAPABILITY_VERSION_01 1 - -/* - * Drive capability header versions. - */ -#define DRIVE_CAPABILITY_VERSION_01 1 -#define DRIVE_CAPABILITY_VERSION_02 2 - -/* - * Legal client major version numbers. - */ - -#define RDP_CLIENT_MAJOR_ALL 1 - -/* - * Legal client minor version numbers. - */ - -#define RDP_CLIENT_MINOR_6_1 0xC -#define RDP_CLIENT_MINOR_5_2 0xA -#define RDP_CLIENT_MINOR_5_1 0x5 -#define RDP_CLIENT_MINOR_5_0 0x2 - -/* - * PDU flags used by the extendedPDU field. - */ - -#define RDPDR_DEVICE_REMOVE_PDUS 0x1 -#define RDPDR_CLIENT_DISPLAY_NAME 0x2 -#define RDPDR_USER_LOGGEDON_PDU 0x4 - -/* - * Device types. - */ - -#define RDPDR_DTYP_SERIAL 0x00000001 -#define RDPDR_DTYP_PARALLEL 0x00000002 -#define RDPDR_DTYP_PRINT 0x00000004 -#define RDPDR_DTYP_FILESYSTEM 0x00000008 -#define RDPDR_DTYP_SMARTCARD 0x00000020 - -/* - * Printer flags. - */ - -#define RDPDR_PRINTER_ANNOUNCE_FLAG_ASCII 0x00000001 -#define RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER 0x00000002 -#define RDPDR_PRINTER_ANNOUNCE_FLAG_NETWORKPRINTER 0x00000004 -#define RDPDR_PRINTER_ANNOUNCE_FLAG_TSPRINTER 0x00000008 -#define RDPDR_PRINTER_ANNOUNCE_FLAG_XPSFORMAT 0x00000010 - -/* - * I/O requests. - */ - -#define IRP_MJ_CREATE 0x00000000 -#define IRP_MJ_CLOSE 0x00000002 -#define IRP_MJ_READ 0x00000003 -#define IRP_MJ_WRITE 0x00000004 -#define IRP_MJ_DEVICE_CONTROL 0x0000000E -#define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0000000A -#define IRP_MJ_SET_VOLUME_INFORMATION 0x0000000B -#define IRP_MJ_QUERY_INFORMATION 0x00000005 -#define IRP_MJ_SET_INFORMATION 0x00000006 -#define IRP_MJ_DIRECTORY_CONTROL 0x0000000C -#define IRP_MJ_LOCK_CONTROL 0x00000011 - -#define IRP_MN_QUERY_DIRECTORY 0x00000001 -#define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x00000002 - -/* - * Volume information constants. - */ - -#define FileFsVolumeInformation 0x00000001 -#define FileFsSizeInformation 0x00000003 -#define FileFsDeviceInformation 0x00000004 -#define FileFsAttributeInformation 0x00000005 -#define FileFsFullSizeInformation 0x00000007 - -/* - * File information constants. - */ - -#define FileBasicInformation 0x00000004 -#define FileStandardInformation 0x00000005 -#define FileRenameInformation 0x0000000A -#define FileDispositionInformation 0x0000000D -#define FileAllocationInformation 0x00000013 -#define FileEndOfFileInformation 0x00000014 -#define FileAttributeTagInformation 0x00000023 - -/* - * Directory information constants. - */ - -#define FileDirectoryInformation 0x00000001 -#define FileFullDirectoryInformation 0x00000002 -#define FileBothDirectoryInformation 0x00000003 -#define FileNamesInformation 0x0000000C - /* * Message handlers. */ diff --git a/src/protocols/rdp/rdpdr_printer.c b/src/protocols/rdp/rdpdr_printer.c index dbe16de3..9f5c1211 100644 --- a/src/protocols/rdp/rdpdr_printer.c +++ b/src/protocols/rdp/rdpdr_printer.c @@ -26,6 +26,7 @@ #include "rdp_status.h" #include "unicode.h" +#include #include #include #include diff --git a/src/protocols/rdp/rdpsnd.c b/src/protocols/rdp/rdpsnd.c index 0e1d2369..04ef5379 100644 --- a/src/protocols/rdp/rdpsnd.c +++ b/src/protocols/rdp/rdpsnd.c @@ -23,6 +23,7 @@ #include "rdpsnd.h" #include "rdpsnd_messages.h" +#include #include #include #include diff --git a/src/protocols/rdp/rdpsnd_messages.c b/src/protocols/rdp/rdpsnd_messages.c index 0102e283..5bed83b7 100644 --- a/src/protocols/rdp/rdpsnd_messages.c +++ b/src/protocols/rdp/rdpsnd_messages.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include diff --git a/src/protocols/rdp/rdpsnd_messages.h b/src/protocols/rdp/rdpsnd_messages.h index 91d0223b..4a621d86 100644 --- a/src/protocols/rdp/rdpsnd_messages.h +++ b/src/protocols/rdp/rdpsnd_messages.h @@ -26,74 +26,6 @@ #include -/* - * PDU Message Types - */ - -/** - * Close PDU - */ -#define SNDC_CLOSE 1 - -/** - * WaveInfo PDU. This PDU is sent just before wave data is sent. - */ -#define SNDC_WAVE 2 - -/** - * Wave Confirm PDU. This PDU is sent in response to the WaveInfo PDU, - * confirming it has been received and played. - */ -#define SNDC_WAVECONFIRM 5 - -/** - * Training PDU. This PDU is sent by the server occasionally and must be - * responded to with another training PDU, similar to Guac's sync message. - */ -#define SNDC_TRAINING 6 - -/** - * Server Audio Formats and Version PDU. This PDU is sent by the server to - * advertise to the client which audio formats are supported. - */ -#define SNDC_FORMATS 7 - -/** - * Quality Mode PDU. This PDU must be sent by the client to select an audio - * quality mode if the server is at least version 6. - */ -#define SNDC_QUALITYMODE 12 - -/* - * Quality Modes - */ - -/** - * Dynamic Quality. The server will choose the audio quality based on its - * perception of latency. - */ -#define DYNAMIC_QUALITY 0x0000 - -/** - * Medium Quality. The server prioritizes bandwidth over quality. - */ -#define MEDIUM_QUALITY 0x0001 - -/** - * High Quality. The server prioritizes quality over bandwidth. - */ -#define HIGH_QUALITY 0x0002 - -/* - * Capabilities - */ -#define TSSNDCAPS_ALIVE 1 - -/* - * Sound Formats - */ -#define WAVE_FORMAT_PCM 1 - /** * The header common to all RDPSND PDUs. */ From a63dcb46b2262ad10724ccda16b20c8b818c9fec Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 23 Dec 2019 12:48:22 -0800 Subject: [PATCH 049/109] GUACAMOLE-249: Rename and restructure RDP source files more sensibly. --- src/protocols/rdp/Makefile.am | 228 +++++++++--------- src/protocols/rdp/{rdp_bitmap.c => bitmap.c} | 4 +- src/protocols/rdp/{rdp_bitmap.h => bitmap.h} | 0 .../{audio_input.c => channels/audio-input.c} | 6 +- .../{audio_input.h => channels/audio-input.h} | 0 .../rdp/{clipboard.c => channels/cliprdr.c} | 4 +- .../rdp/{clipboard.h => channels/cliprdr.h} | 0 src/protocols/rdp/{ => channels}/common-svc.c | 4 +- src/protocols/rdp/{ => channels}/common-svc.h | 0 src/protocols/rdp/{ => channels}/disp.c | 6 +- src/protocols/rdp/{ => channels}/disp.h | 2 +- src/protocols/rdp/{ => channels}/pipe-svc.c | 6 +- src/protocols/rdp/{ => channels}/pipe-svc.h | 2 +- src/protocols/rdp/{ => channels}/rail.c | 6 +- src/protocols/rdp/{ => channels}/rail.h | 0 .../rdpdr/rdpdr-fs-messages-dir-info.c} | 6 +- .../rdpdr/rdpdr-fs-messages-dir-info.h} | 4 +- .../rdpdr/rdpdr-fs-messages-file-info.c} | 6 +- .../rdpdr/rdpdr-fs-messages-file-info.h} | 4 +- .../rdpdr/rdpdr-fs-messages-vol-info.c} | 8 +- .../rdpdr/rdpdr-fs-messages-vol-info.h} | 2 +- .../rdpdr/rdpdr-fs-messages.c} | 16 +- .../rdpdr/rdpdr-fs-messages.h} | 2 +- .../rdpdr/rdpdr-fs.c} | 6 +- .../rdpdr/rdpdr-fs.h} | 2 +- .../rdpdr/rdpdr-messages.c} | 4 +- .../rdpdr/rdpdr-messages.h} | 2 +- .../rdpdr/rdpdr-printer.c} | 10 +- .../rdpdr/rdpdr-printer.h} | 2 +- .../rdp/{ => channels/rdpdr}/rdpdr.c | 16 +- .../rdp/{ => channels/rdpdr}/rdpdr.h | 2 +- .../rdpsnd/rdpsnd-messages.c} | 4 +- .../rdpsnd/rdpsnd-messages.h} | 2 +- .../rdp/{ => channels/rdpsnd}/rdpsnd.c | 6 +- .../rdp/{ => channels/rdpsnd}/rdpsnd.h | 2 +- src/protocols/rdp/client.c | 6 +- src/protocols/rdp/{rdp_color.c => color.c} | 2 +- src/protocols/rdp/{rdp_color.h => color.h} | 0 src/protocols/rdp/{rdp_fs.c => fs.c} | 6 +- src/protocols/rdp/{rdp_fs.h => fs.h} | 0 src/protocols/rdp/{rdp_gdi.c => gdi.c} | 6 +- src/protocols/rdp/{rdp_gdi.h => gdi.h} | 0 src/protocols/rdp/{rdp_glyph.c => glyph.c} | 6 +- src/protocols/rdp/{rdp_glyph.h => glyph.h} | 0 src/protocols/rdp/input.c | 4 +- src/protocols/rdp/{ => keyboard}/decompose.c | 2 +- src/protocols/rdp/{ => keyboard}/decompose.h | 2 +- src/protocols/rdp/{ => keyboard}/keyboard.c | 6 +- src/protocols/rdp/{ => keyboard}/keyboard.h | 2 +- .../rdp/{rdp_keymap.c => keyboard/keymap.c} | 2 +- .../rdp/{rdp_keymap.h => keyboard/keymap.h} | 0 .../rdp/{ => keyboard}/keymaps/base.keymap | 0 .../keymaps/da_dk_qwerty.keymap | 0 .../keymaps/de_ch_qwertz.keymap | 0 .../keymaps/de_de_qwertz.keymap | 0 .../keymaps/en_gb_qwerty.keymap | 0 .../keymaps/en_us_qwerty.keymap | 0 .../keymaps/es_es_qwerty.keymap | 0 .../{ => keyboard}/keymaps/failsafe.keymap | 0 .../keymaps/fr_ch_qwertz.keymap | 0 .../keymaps/fr_fr_azerty.keymap | 0 .../rdp/{ => keyboard}/keymaps/generate.pl | 2 +- .../keymaps/it_it_qwerty.keymap | 0 .../keymaps/ja_jp_qwerty.keymap | 0 .../keymaps/pt_br_qwerty.keymap | 0 .../keymaps/sv_se_qwerty.keymap | 0 .../keymaps/tr_tr_qwerty.keymap | 0 src/protocols/rdp/{ => plugins}/channels.c | 2 +- src/protocols/rdp/{ => plugins}/channels.h | 0 .../{ => plugins}/generate-entry-wrappers.pl | 2 +- .../guac-common-svc/guac-common-svc.c} | 2 +- .../guacai/guacai-messages.c} | 4 +- .../guacai/guacai-messages.h} | 0 .../ai_service.c => plugins/guacai/guacai.c} | 8 +- .../ai_service.h => plugins/guacai/guacai.h} | 0 .../{ptr_string.c => plugins/ptr-string.c} | 2 +- .../{ptr_string.h => plugins/ptr-string.h} | 0 .../rdp/{rdp_pointer.c => pointer.c} | 2 +- .../rdp/{rdp_pointer.h => pointer.h} | 0 .../rdp/{rdp_print_job.c => print-job.c} | 2 +- .../rdp/{rdp_print_job.h => print-job.h} | 0 src/protocols/rdp/rdp.c | 32 +-- src/protocols/rdp/rdp.h | 14 +- .../rdp/{rdp_settings.c => settings.c} | 2 +- .../rdp/{rdp_settings.h => settings.h} | 2 +- src/protocols/rdp/{rdp_status.h => status.h} | 0 src/protocols/rdp/{rdp_stream.c => stream.c} | 4 +- src/protocols/rdp/{rdp_stream.h => stream.h} | 0 src/protocols/rdp/tests/fs/normalize_path.c | 2 +- src/protocols/rdp/user.c | 8 +- 90 files changed, 254 insertions(+), 254 deletions(-) rename src/protocols/rdp/{rdp_bitmap.c => bitmap.c} (99%) rename src/protocols/rdp/{rdp_bitmap.h => bitmap.h} (100%) rename src/protocols/rdp/{audio_input.c => channels/audio-input.c} (99%) rename src/protocols/rdp/{audio_input.h => channels/audio-input.h} (100%) rename src/protocols/rdp/{clipboard.c => channels/cliprdr.c} (99%) rename src/protocols/rdp/{clipboard.h => channels/cliprdr.h} (100%) rename src/protocols/rdp/{ => channels}/common-svc.c (98%) rename src/protocols/rdp/{ => channels}/common-svc.h (100%) rename src/protocols/rdp/{ => channels}/disp.c (98%) rename src/protocols/rdp/{ => channels}/disp.h (99%) rename src/protocols/rdp/{ => channels}/pipe-svc.c (98%) rename src/protocols/rdp/{ => channels}/pipe-svc.h (99%) rename src/protocols/rdp/{ => channels}/rail.c (98%) rename src/protocols/rdp/{ => channels}/rail.h (100%) rename src/protocols/rdp/{rdpdr_fs_messages_dir_info.c => channels/rdpdr/rdpdr-fs-messages-dir-info.c} (99%) rename src/protocols/rdp/{rdpdr_fs_messages_dir_info.h => channels/rdpdr/rdpdr-fs-messages-dir-info.h} (97%) rename src/protocols/rdp/{rdpdr_fs_messages_file_info.c => channels/rdpdr/rdpdr-fs-messages-file-info.c} (99%) rename src/protocols/rdp/{rdpdr_fs_messages_file_info.h => channels/rdpdr/rdpdr-fs-messages-file-info.h} (98%) rename src/protocols/rdp/{rdpdr_fs_messages_vol_info.c => channels/rdpdr/rdpdr-fs-messages-vol-info.c} (97%) rename src/protocols/rdp/{rdpdr_fs_messages_vol_info.h => channels/rdpdr/rdpdr-fs-messages-vol-info.h} (98%) rename src/protocols/rdp/{rdpdr_fs_messages.c => channels/rdpdr/rdpdr-fs-messages.c} (98%) rename src/protocols/rdp/{rdpdr_fs_messages.h => channels/rdpdr/rdpdr-fs-messages.h} (99%) rename src/protocols/rdp/{rdpdr_fs_service.c => channels/rdpdr/rdpdr-fs.c} (97%) rename src/protocols/rdp/{rdpdr_fs_service.h => channels/rdpdr/rdpdr-fs.h} (98%) rename src/protocols/rdp/{rdpdr_messages.c => channels/rdpdr/rdpdr-messages.c} (99%) rename src/protocols/rdp/{rdpdr_messages.h => channels/rdpdr/rdpdr-messages.h} (98%) rename src/protocols/rdp/{rdpdr_printer.c => channels/rdpdr/rdpdr-printer.c} (97%) rename src/protocols/rdp/{rdpdr_printer.h => channels/rdpdr/rdpdr-printer.h} (97%) rename src/protocols/rdp/{ => channels/rdpdr}/rdpdr.c (97%) rename src/protocols/rdp/{ => channels/rdpdr}/rdpdr.h (99%) rename src/protocols/rdp/{rdpsnd_messages.c => channels/rdpsnd/rdpsnd-messages.c} (99%) rename src/protocols/rdp/{rdpsnd_messages.h => channels/rdpsnd/rdpsnd-messages.h} (99%) rename src/protocols/rdp/{ => channels/rdpsnd}/rdpsnd.c (96%) rename src/protocols/rdp/{ => channels/rdpsnd}/rdpsnd.h (99%) rename src/protocols/rdp/{rdp_color.c => color.c} (98%) rename src/protocols/rdp/{rdp_color.h => color.h} (100%) rename src/protocols/rdp/{rdp_fs.c => fs.c} (99%) rename src/protocols/rdp/{rdp_fs.h => fs.h} (100%) rename src/protocols/rdp/{rdp_gdi.c => gdi.c} (99%) rename src/protocols/rdp/{rdp_gdi.h => gdi.h} (100%) rename src/protocols/rdp/{rdp_glyph.c => glyph.c} (98%) rename src/protocols/rdp/{rdp_glyph.h => glyph.h} (100%) rename src/protocols/rdp/{ => keyboard}/decompose.c (99%) rename src/protocols/rdp/{ => keyboard}/decompose.h (98%) rename src/protocols/rdp/{ => keyboard}/keyboard.c (99%) rename src/protocols/rdp/{ => keyboard}/keyboard.h (99%) rename src/protocols/rdp/{rdp_keymap.c => keyboard/keymap.c} (98%) rename src/protocols/rdp/{rdp_keymap.h => keyboard/keymap.h} (100%) rename src/protocols/rdp/{ => keyboard}/keymaps/base.keymap (100%) rename src/protocols/rdp/{ => keyboard}/keymaps/da_dk_qwerty.keymap (100%) rename src/protocols/rdp/{ => keyboard}/keymaps/de_ch_qwertz.keymap (100%) rename src/protocols/rdp/{ => keyboard}/keymaps/de_de_qwertz.keymap (100%) rename src/protocols/rdp/{ => keyboard}/keymaps/en_gb_qwerty.keymap (100%) rename src/protocols/rdp/{ => keyboard}/keymaps/en_us_qwerty.keymap (100%) rename src/protocols/rdp/{ => keyboard}/keymaps/es_es_qwerty.keymap (100%) rename src/protocols/rdp/{ => keyboard}/keymaps/failsafe.keymap (100%) rename src/protocols/rdp/{ => keyboard}/keymaps/fr_ch_qwertz.keymap (100%) rename src/protocols/rdp/{ => keyboard}/keymaps/fr_fr_azerty.keymap (100%) rename src/protocols/rdp/{ => keyboard}/keymaps/generate.pl (99%) rename src/protocols/rdp/{ => keyboard}/keymaps/it_it_qwerty.keymap (100%) rename src/protocols/rdp/{ => keyboard}/keymaps/ja_jp_qwerty.keymap (100%) rename src/protocols/rdp/{ => keyboard}/keymaps/pt_br_qwerty.keymap (100%) rename src/protocols/rdp/{ => keyboard}/keymaps/sv_se_qwerty.keymap (100%) rename src/protocols/rdp/{ => keyboard}/keymaps/tr_tr_qwerty.keymap (100%) rename src/protocols/rdp/{ => plugins}/channels.c (99%) rename src/protocols/rdp/{ => plugins}/channels.h (100%) rename src/protocols/rdp/{ => plugins}/generate-entry-wrappers.pl (98%) rename src/protocols/rdp/{guac-common-svc/common-svc-main.c => plugins/guac-common-svc/guac-common-svc.c} (99%) rename src/protocols/rdp/{guac_ai/ai_messages.c => plugins/guacai/guacai-messages.c} (99%) rename src/protocols/rdp/{guac_ai/ai_messages.h => plugins/guacai/guacai-messages.h} (100%) rename src/protocols/rdp/{guac_ai/ai_service.c => plugins/guacai/guacai.c} (98%) rename src/protocols/rdp/{guac_ai/ai_service.h => plugins/guacai/guacai.h} (100%) rename src/protocols/rdp/{ptr_string.c => plugins/ptr-string.c} (97%) rename src/protocols/rdp/{ptr_string.h => plugins/ptr-string.h} (100%) rename src/protocols/rdp/{rdp_pointer.c => pointer.c} (99%) rename src/protocols/rdp/{rdp_pointer.h => pointer.h} (100%) rename src/protocols/rdp/{rdp_print_job.c => print-job.c} (99%) rename src/protocols/rdp/{rdp_print_job.h => print-job.h} (100%) rename src/protocols/rdp/{rdp_settings.c => settings.c} (99%) rename src/protocols/rdp/{rdp_settings.h => settings.h} (99%) rename src/protocols/rdp/{rdp_status.h => status.h} (100%) rename src/protocols/rdp/{rdp_stream.c => stream.c} (99%) rename src/protocols/rdp/{rdp_stream.h => stream.h} (100%) diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index 443ed0b6..880df9bb 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -37,85 +37,85 @@ nodist_libguac_client_rdp_la_SOURCES = \ _generated_channel_entry_wrappers.c \ _generated_keymaps.c -libguac_client_rdp_la_SOURCES = \ - audio_input.c \ - channels.c \ - client.c \ - clipboard.c \ - common-svc.c \ - decompose.c \ - disp.c \ - error.c \ - input.c \ - keyboard.c \ - pipe-svc.c \ - ptr_string.c \ - rail.c \ - rdp.c \ - rdp_bitmap.c \ - rdp_color.c \ - rdp_fs.c \ - rdp_gdi.c \ - rdp_glyph.c \ - rdp_keymap.c \ - rdp_print_job.c \ - rdp_pointer.c \ - rdp_settings.c \ - rdp_stream.c \ - rdpdr.c \ - rdpdr_fs_messages.c \ - rdpdr_fs_messages_dir_info.c \ - rdpdr_fs_messages_file_info.c \ - rdpdr_fs_messages_vol_info.c \ - rdpdr_fs_service.c \ - rdpdr_messages.c \ - rdpdr_printer.c \ - rdpsnd.c \ - rdpsnd_messages.c \ - resolution.c \ - unicode.c \ +libguac_client_rdp_la_SOURCES = \ + bitmap.c \ + channels/audio-input.c \ + channels/cliprdr.c \ + channels/common-svc.c \ + channels/disp.c \ + channels/pipe-svc.c \ + channels/rail.c \ + channels/rdpdr/rdpdr-fs-messages-dir-info.c \ + channels/rdpdr/rdpdr-fs-messages-file-info.c \ + channels/rdpdr/rdpdr-fs-messages-vol-info.c \ + channels/rdpdr/rdpdr-fs-messages.c \ + channels/rdpdr/rdpdr-fs.c \ + channels/rdpdr/rdpdr-messages.c \ + channels/rdpdr/rdpdr-printer.c \ + channels/rdpdr/rdpdr.c \ + channels/rdpsnd/rdpsnd-messages.c \ + channels/rdpsnd/rdpsnd.c \ + client.c \ + color.c \ + error.c \ + fs.c \ + gdi.c \ + glyph.c \ + input.c \ + keyboard/decompose.c \ + keyboard/keyboard.c \ + keyboard/keymap.c \ + plugins/channels.c \ + plugins/ptr-string.c \ + pointer.c \ + print-job.c \ + rdp.c \ + resolution.c \ + settings.c \ + stream.c \ + unicode.c \ user.c -noinst_HEADERS = \ - guac_ai/ai_messages.h \ - guac_ai/ai_service.h \ - audio_input.h \ - client.h \ - clipboard.h \ - channels.h \ - common-svc.h \ - decompose.h \ - disp.h \ - error.h \ - input.h \ - keyboard.h \ - pipe-svc.h \ - ptr_string.h \ - rail.h \ - rdp.h \ - rdp_bitmap.h \ - rdp_color.h \ - rdp_fs.h \ - rdp_gdi.h \ - rdp_glyph.h \ - rdp_keymap.h \ - rdp_pointer.h \ - rdp_print_job.h \ - rdp_settings.h \ - rdp_status.h \ - rdp_stream.h \ - rdpdr.h \ - rdpdr_fs_messages.h \ - rdpdr_fs_messages_dir_info.h \ - rdpdr_fs_messages_file_info.h \ - rdpdr_fs_messages_vol_info.h \ - rdpdr_fs_service.h \ - rdpdr_messages.h \ - rdpdr_printer.h \ - rdpsnd.h \ - rdpsnd_messages.h \ - resolution.h \ - unicode.h \ +noinst_HEADERS = \ + bitmap.h \ + channels/audio-input.h \ + channels/cliprdr.h \ + channels/common-svc.h \ + channels/disp.h \ + channels/pipe-svc.h \ + channels/rail.h \ + channels/rdpdr/rdpdr-fs-messages-dir-info.h \ + channels/rdpdr/rdpdr-fs-messages-file-info.h \ + channels/rdpdr/rdpdr-fs-messages-vol-info.h \ + channels/rdpdr/rdpdr-fs-messages.h \ + channels/rdpdr/rdpdr-fs.h \ + channels/rdpdr/rdpdr-messages.h \ + channels/rdpdr/rdpdr-printer.h \ + channels/rdpdr/rdpdr.h \ + channels/rdpsnd/rdpsnd-messages.h \ + channels/rdpsnd/rdpsnd.h \ + client.h \ + color.h \ + error.h \ + fs.h \ + gdi.h \ + glyph.h \ + input.h \ + keyboard/decompose.h \ + keyboard/keyboard.h \ + keyboard/keymap.h \ + plugins/channels.h \ + plugins/guacai/guacai-messages.h \ + plugins/guacai/guacai.h \ + plugins/ptr-string.h \ + pointer.h \ + print-job.h \ + rdp.h \ + resolution.h \ + settings.h \ + status.h \ + stream.h \ + unicode.h \ user.h libguac_client_rdp_la_CFLAGS = \ @@ -131,8 +131,8 @@ libguac_client_rdp_la_LDFLAGS = \ @PTHREAD_LIBS@ \ @RDP_LIBS@ -libguac_client_rdp_la_LIBADD = \ - @COMMON_LTLIB@ \ +libguac_client_rdp_la_LIBADD = \ + @COMMON_LTLIB@ \ @LIBGUAC_LTLIB@ # @@ -149,8 +149,8 @@ freerdpdir = ${libdir}/freerdp2 # Common SVC plugin (shared by RDPDR, RDPSND, etc.) # -libguac_common_svc_client_la_SOURCES = \ - guac-common-svc/common-svc-main.c +libguac_common_svc_client_la_SOURCES = \ + plugins/guac-common-svc/guac-common-svc.c libguac_common_svc_client_la_CFLAGS = \ -Werror -Wall -Iinclude \ @@ -168,17 +168,17 @@ libguac_common_svc_client_la_LIBADD = \ # Audio Input # -libguacai_client_la_SOURCES = \ - audio_input.c \ - guac_ai/ai_messages.c \ - guac_ai/ai_service.c \ - ptr_string.c +libguacai_client_la_SOURCES = \ + channels/audio-input.c \ + plugins/guacai/guacai-messages.c \ + plugins/guacai/guacai.c \ + plugins/ptr-string.c -libguacai_client_la_CFLAGS = \ - -Werror -Wall -Iinclude \ - @COMMON_INCLUDE@ \ - @COMMON_SSH_INCLUDE@ \ - @LIBGUAC_INCLUDE@ \ +libguacai_client_la_CFLAGS = \ + -Werror -Wall -Iinclude \ + @COMMON_INCLUDE@ \ + @COMMON_SSH_INCLUDE@ \ + @LIBGUAC_INCLUDE@ \ @RDP_CFLAGS@ libguacai_client_la_LDFLAGS = \ @@ -212,31 +212,31 @@ BUILT_SOURCES = \ _generated_channel_entry_wrappers.c \ _generated_keymaps.c -rdp_keymaps = \ - $(srcdir)/keymaps/base.keymap \ - $(srcdir)/keymaps/failsafe.keymap \ - $(srcdir)/keymaps/de_de_qwertz.keymap \ - $(srcdir)/keymaps/de_ch_qwertz.keymap \ - $(srcdir)/keymaps/en_gb_qwerty.keymap \ - $(srcdir)/keymaps/en_us_qwerty.keymap \ - $(srcdir)/keymaps/es_es_qwerty.keymap \ - $(srcdir)/keymaps/fr_fr_azerty.keymap \ - $(srcdir)/keymaps/fr_ch_qwertz.keymap \ - $(srcdir)/keymaps/it_it_qwerty.keymap \ - $(srcdir)/keymaps/ja_jp_qwerty.keymap \ - $(srcdir)/keymaps/pt_br_qwerty.keymap \ - $(srcdir)/keymaps/sv_se_qwerty.keymap \ - $(srcdir)/keymaps/da_dk_qwerty.keymap \ - $(srcdir)/keymaps/tr_tr_qwerty.keymap +rdp_keymaps = \ + $(srcdir)/keyboard/keymaps/base.keymap \ + $(srcdir)/keyboard/keymaps/failsafe.keymap \ + $(srcdir)/keyboard/keymaps/de_de_qwertz.keymap \ + $(srcdir)/keyboard/keymaps/de_ch_qwertz.keymap \ + $(srcdir)/keyboard/keymaps/en_gb_qwerty.keymap \ + $(srcdir)/keyboard/keymaps/en_us_qwerty.keymap \ + $(srcdir)/keyboard/keymaps/es_es_qwerty.keymap \ + $(srcdir)/keyboard/keymaps/fr_fr_azerty.keymap \ + $(srcdir)/keyboard/keymaps/fr_ch_qwertz.keymap \ + $(srcdir)/keyboard/keymaps/it_it_qwerty.keymap \ + $(srcdir)/keyboard/keymaps/ja_jp_qwerty.keymap \ + $(srcdir)/keyboard/keymaps/pt_br_qwerty.keymap \ + $(srcdir)/keyboard/keymaps/sv_se_qwerty.keymap \ + $(srcdir)/keyboard/keymaps/da_dk_qwerty.keymap \ + $(srcdir)/keyboard/keymaps/tr_tr_qwerty.keymap _generated_keymaps.c: $(rdp_keymaps) - $(AM_V_GEN) $(srcdir)/keymaps/generate.pl $(rdp_keymaps) + $(AM_V_GEN) $(srcdir)/keyboard/keymaps/generate.pl $(rdp_keymaps) -_generated_channel_entry_wrappers.c: $(srcdir)/channels.h $(srcdir)/generate-entry-wrappers.pl - $(AM_V_GEN) $(srcdir)/generate-entry-wrappers.pl $(srcdir)/channels.h +_generated_channel_entry_wrappers.c: $(srcdir)/plugins/channels.h $(srcdir)/plugins/generate-entry-wrappers.pl + $(AM_V_GEN) $(srcdir)/plugins/generate-entry-wrappers.pl $(srcdir)/plugins/channels.h -EXTRA_DIST = \ - $(rdp_keymaps) \ - generate-entry-wrappers.pl \ - keymaps/generate.pl +EXTRA_DIST = \ + $(rdp_keymaps) \ + plugins/generate-entry-wrappers.pl \ + keyboard/keymaps/generate.pl diff --git a/src/protocols/rdp/rdp_bitmap.c b/src/protocols/rdp/bitmap.c similarity index 99% rename from src/protocols/rdp/rdp_bitmap.c rename to src/protocols/rdp/bitmap.c index 2dcf77a2..093dae15 100644 --- a/src/protocols/rdp/rdp_bitmap.c +++ b/src/protocols/rdp/bitmap.c @@ -23,8 +23,8 @@ #include "common/display.h" #include "common/surface.h" #include "rdp.h" -#include "rdp_bitmap.h" -#include "rdp_settings.h" +#include "bitmap.h" +#include "settings.h" #include #include diff --git a/src/protocols/rdp/rdp_bitmap.h b/src/protocols/rdp/bitmap.h similarity index 100% rename from src/protocols/rdp/rdp_bitmap.h rename to src/protocols/rdp/bitmap.h diff --git a/src/protocols/rdp/audio_input.c b/src/protocols/rdp/channels/audio-input.c similarity index 99% rename from src/protocols/rdp/audio_input.c rename to src/protocols/rdp/channels/audio-input.c index a0dd24a8..055ce83d 100644 --- a/src/protocols/rdp/audio_input.c +++ b/src/protocols/rdp/channels/audio-input.c @@ -18,9 +18,9 @@ */ #include "config.h" -#include "audio_input.h" -#include "channels.h" -#include "ptr_string.h" +#include "channels/audio-input.h" +#include "plugins/channels.h" +#include "plugins/ptr-string.h" #include "rdp.h" #include diff --git a/src/protocols/rdp/audio_input.h b/src/protocols/rdp/channels/audio-input.h similarity index 100% rename from src/protocols/rdp/audio_input.h rename to src/protocols/rdp/channels/audio-input.h diff --git a/src/protocols/rdp/clipboard.c b/src/protocols/rdp/channels/cliprdr.c similarity index 99% rename from src/protocols/rdp/clipboard.c rename to src/protocols/rdp/channels/cliprdr.c index 77b3dabd..8cc43fec 100644 --- a/src/protocols/rdp/clipboard.c +++ b/src/protocols/rdp/channels/cliprdr.c @@ -19,9 +19,9 @@ #include "config.h" -#include "channels.h" +#include "plugins/channels.h" #include "client.h" -#include "clipboard.h" +#include "channels/cliprdr.h" #include "common/clipboard.h" #include "common/iconv.h" #include "rdp.h" diff --git a/src/protocols/rdp/clipboard.h b/src/protocols/rdp/channels/cliprdr.h similarity index 100% rename from src/protocols/rdp/clipboard.h rename to src/protocols/rdp/channels/cliprdr.h diff --git a/src/protocols/rdp/common-svc.c b/src/protocols/rdp/channels/common-svc.c similarity index 98% rename from src/protocols/rdp/common-svc.c rename to src/protocols/rdp/channels/common-svc.c index 3e092a95..0ba83220 100644 --- a/src/protocols/rdp/common-svc.c +++ b/src/protocols/rdp/channels/common-svc.c @@ -18,8 +18,8 @@ */ #include "config.h" -#include "channels.h" -#include "common-svc.h" +#include "plugins/channels.h" +#include "channels/common-svc.h" #include "rdp.h" #include diff --git a/src/protocols/rdp/common-svc.h b/src/protocols/rdp/channels/common-svc.h similarity index 100% rename from src/protocols/rdp/common-svc.h rename to src/protocols/rdp/channels/common-svc.h diff --git a/src/protocols/rdp/disp.c b/src/protocols/rdp/channels/disp.c similarity index 98% rename from src/protocols/rdp/disp.c rename to src/protocols/rdp/channels/disp.c index cb37d8bb..73920f46 100644 --- a/src/protocols/rdp/disp.c +++ b/src/protocols/rdp/channels/disp.c @@ -18,11 +18,11 @@ */ #include "config.h" -#include "channels.h" +#include "plugins/channels.h" #include "client.h" -#include "disp.h" +#include "channels/disp.h" #include "rdp.h" -#include "rdp_settings.h" +#include "settings.h" #include #include diff --git a/src/protocols/rdp/disp.h b/src/protocols/rdp/channels/disp.h similarity index 99% rename from src/protocols/rdp/disp.h rename to src/protocols/rdp/channels/disp.h index 04df7527..e88e8e48 100644 --- a/src/protocols/rdp/disp.h +++ b/src/protocols/rdp/channels/disp.h @@ -20,7 +20,7 @@ #ifndef GUAC_RDP_DISP_H #define GUAC_RDP_DISP_H -#include "rdp_settings.h" +#include "settings.h" #include #include diff --git a/src/protocols/rdp/pipe-svc.c b/src/protocols/rdp/channels/pipe-svc.c similarity index 98% rename from src/protocols/rdp/pipe-svc.c rename to src/protocols/rdp/channels/pipe-svc.c index 05cd758c..68017ab1 100644 --- a/src/protocols/rdp/pipe-svc.c +++ b/src/protocols/rdp/channels/pipe-svc.c @@ -19,11 +19,11 @@ #include "config.h" -#include "channels.h" +#include "plugins/channels.h" #include "client.h" #include "common/list.h" -#include "common-svc.h" -#include "pipe-svc.h" +#include "channels/common-svc.h" +#include "channels/pipe-svc.h" #include "rdp.h" #include diff --git a/src/protocols/rdp/pipe-svc.h b/src/protocols/rdp/channels/pipe-svc.h similarity index 99% rename from src/protocols/rdp/pipe-svc.h rename to src/protocols/rdp/channels/pipe-svc.h index 1abcf09c..0744740f 100644 --- a/src/protocols/rdp/pipe-svc.h +++ b/src/protocols/rdp/channels/pipe-svc.h @@ -21,7 +21,7 @@ #define GUAC_RDP_PIPE_SVC_H #include "config.h" -#include "common-svc.h" +#include "channels/common-svc.h" #include #include diff --git a/src/protocols/rdp/rail.c b/src/protocols/rdp/channels/rail.c similarity index 98% rename from src/protocols/rdp/rail.c rename to src/protocols/rdp/channels/rail.c index 5f06155e..65bc9717 100644 --- a/src/protocols/rdp/rail.c +++ b/src/protocols/rdp/channels/rail.c @@ -19,11 +19,11 @@ #include "config.h" -#include "channels.h" +#include "plugins/channels.h" #include "client.h" -#include "rail.h" +#include "channels/rail.h" #include "rdp.h" -#include "rdp_settings.h" +#include "settings.h" #include #include diff --git a/src/protocols/rdp/rail.h b/src/protocols/rdp/channels/rail.h similarity index 100% rename from src/protocols/rdp/rail.h rename to src/protocols/rdp/channels/rail.h diff --git a/src/protocols/rdp/rdpdr_fs_messages_dir_info.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.c similarity index 99% rename from src/protocols/rdp/rdpdr_fs_messages_dir_info.c rename to src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.c index 23626941..1a445d0a 100644 --- a/src/protocols/rdp/rdpdr_fs_messages_dir_info.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.c @@ -18,9 +18,9 @@ */ #include "config.h" -#include "rdpdr.h" -#include "rdp_fs.h" -#include "rdp_status.h" +#include "channels/rdpdr/rdpdr.h" +#include "fs.h" +#include "status.h" #include "unicode.h" #include diff --git a/src/protocols/rdp/rdpdr_fs_messages_dir_info.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h similarity index 97% rename from src/protocols/rdp/rdpdr_fs_messages_dir_info.h rename to src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h index 8d493406..02acfdd4 100644 --- a/src/protocols/rdp/rdpdr_fs_messages_dir_info.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h @@ -30,8 +30,8 @@ */ #include "config.h" -#include "common-svc.h" -#include "rdpdr.h" +#include "channels/common-svc.h" +#include "channels/rdpdr/rdpdr.h" #include diff --git a/src/protocols/rdp/rdpdr_fs_messages_file_info.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.c similarity index 99% rename from src/protocols/rdp/rdpdr_fs_messages_file_info.c rename to src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.c index 4395a2f3..ee134e51 100644 --- a/src/protocols/rdp/rdpdr_fs_messages_file_info.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.c @@ -18,9 +18,9 @@ */ #include "config.h" -#include "rdpdr.h" -#include "rdp_fs.h" -#include "rdp_status.h" +#include "channels/rdpdr/rdpdr.h" +#include "fs.h" +#include "status.h" #include "unicode.h" #include diff --git a/src/protocols/rdp/rdpdr_fs_messages_file_info.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h similarity index 98% rename from src/protocols/rdp/rdpdr_fs_messages_file_info.h rename to src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h index 56941d72..f2bb0d8f 100644 --- a/src/protocols/rdp/rdpdr_fs_messages_file_info.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h @@ -29,8 +29,8 @@ */ #include "config.h" -#include "common-svc.h" -#include "rdpdr.h" +#include "channels/common-svc.h" +#include "channels/rdpdr/rdpdr.h" #include diff --git a/src/protocols/rdp/rdpdr_fs_messages_vol_info.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.c similarity index 97% rename from src/protocols/rdp/rdpdr_fs_messages_vol_info.c rename to src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.c index dc3a5e10..afacde67 100644 --- a/src/protocols/rdp/rdpdr_fs_messages_vol_info.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.c @@ -18,10 +18,10 @@ */ #include "config.h" -#include "rdpdr.h" -#include "rdpdr_messages.h" -#include "rdp_fs.h" -#include "rdp_status.h" +#include "channels/rdpdr/rdpdr.h" +#include "channels/rdpdr/rdpdr-messages.h" +#include "fs.h" +#include "status.h" #include #include diff --git a/src/protocols/rdp/rdpdr_fs_messages_vol_info.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.h similarity index 98% rename from src/protocols/rdp/rdpdr_fs_messages_vol_info.h rename to src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.h index 1c34127e..e6a95dd5 100644 --- a/src/protocols/rdp/rdpdr_fs_messages_vol_info.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.h @@ -30,7 +30,7 @@ */ #include "config.h" -#include "rdpdr.h" +#include "channels/rdpdr/rdpdr.h" #include diff --git a/src/protocols/rdp/rdpdr_fs_messages.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c similarity index 98% rename from src/protocols/rdp/rdpdr_fs_messages.c rename to src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c index 02646191..67bf3495 100644 --- a/src/protocols/rdp/rdpdr_fs_messages.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c @@ -18,14 +18,14 @@ */ #include "config.h" -#include "rdpdr.h" -#include "rdpdr_fs_messages_dir_info.h" -#include "rdpdr_fs_messages_file_info.h" -#include "rdpdr_fs_messages.h" -#include "rdpdr_fs_messages_vol_info.h" -#include "rdpdr_messages.h" -#include "rdp_fs.h" -#include "rdp_status.h" +#include "channels/rdpdr/rdpdr.h" +#include "channels/rdpdr/rdpdr-fs-messages-dir-info.h" +#include "channels/rdpdr/rdpdr-fs-messages-file-info.h" +#include "channels/rdpdr/rdpdr-fs-messages.h" +#include "channels/rdpdr/rdpdr-fs-messages-vol-info.h" +#include "channels/rdpdr/rdpdr-messages.h" +#include "fs.h" +#include "status.h" #include "unicode.h" #include diff --git a/src/protocols/rdp/rdpdr_fs_messages.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.h similarity index 99% rename from src/protocols/rdp/rdpdr_fs_messages.h rename to src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.h index a2018f2d..27aba844 100644 --- a/src/protocols/rdp/rdpdr_fs_messages.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.h @@ -30,7 +30,7 @@ */ #include "config.h" -#include "rdpdr.h" +#include "channels/rdpdr/rdpdr.h" #include diff --git a/src/protocols/rdp/rdpdr_fs_service.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs.c similarity index 97% rename from src/protocols/rdp/rdpdr_fs_service.c rename to src/protocols/rdp/channels/rdpdr/rdpdr-fs.c index 933cd7e5..89f2ba6f 100644 --- a/src/protocols/rdp/rdpdr_fs_service.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs.c @@ -20,9 +20,9 @@ #include "config.h" #include "rdp.h" -#include "rdpdr.h" -#include "rdpdr_fs_messages.h" -#include "rdpdr_messages.h" +#include "channels/rdpdr/rdpdr.h" +#include "channels/rdpdr/rdpdr-fs-messages.h" +#include "channels/rdpdr/rdpdr-messages.h" #include #include diff --git a/src/protocols/rdp/rdpdr_fs_service.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h similarity index 98% rename from src/protocols/rdp/rdpdr_fs_service.h rename to src/protocols/rdp/channels/rdpdr/rdpdr-fs.h index a3775f95..63f4a5d7 100644 --- a/src/protocols/rdp/rdpdr_fs_service.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h @@ -33,7 +33,7 @@ */ #include "config.h" -#include "rdpdr.h" +#include "channels/rdpdr/rdpdr.h" #include diff --git a/src/protocols/rdp/rdpdr_messages.c b/src/protocols/rdp/channels/rdpdr/rdpdr-messages.c similarity index 99% rename from src/protocols/rdp/rdpdr_messages.c rename to src/protocols/rdp/channels/rdpdr/rdpdr-messages.c index 06f1c55c..b063bbfa 100644 --- a/src/protocols/rdp/rdpdr_messages.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-messages.c @@ -19,8 +19,8 @@ #include "config.h" #include "rdp.h" -#include "rdpdr.h" -#include "rdpdr_messages.h" +#include "channels/rdpdr/rdpdr.h" +#include "channels/rdpdr/rdpdr-messages.h" #include "unicode.h" #include diff --git a/src/protocols/rdp/rdpdr_messages.h b/src/protocols/rdp/channels/rdpdr/rdpdr-messages.h similarity index 98% rename from src/protocols/rdp/rdpdr_messages.h rename to src/protocols/rdp/channels/rdpdr/rdpdr-messages.h index 221db893..1f2db3be 100644 --- a/src/protocols/rdp/rdpdr_messages.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-messages.h @@ -22,7 +22,7 @@ #define GUAC_RDPDR_MESSAGES_H #include "config.h" -#include "rdpdr.h" +#include "channels/rdpdr/rdpdr.h" #include diff --git a/src/protocols/rdp/rdpdr_printer.c b/src/protocols/rdp/channels/rdpdr/rdpdr-printer.c similarity index 97% rename from src/protocols/rdp/rdpdr_printer.c rename to src/protocols/rdp/channels/rdpdr/rdpdr-printer.c index 9f5c1211..dd16a5c4 100644 --- a/src/protocols/rdp/rdpdr_printer.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-printer.c @@ -18,12 +18,12 @@ */ #include "config.h" -#include "rdpdr.h" -#include "rdpdr_messages.h" -#include "rdpdr_printer.h" +#include "channels/rdpdr/rdpdr.h" +#include "channels/rdpdr/rdpdr-messages.h" +#include "channels/rdpdr/rdpdr-printer.h" #include "rdp.h" -#include "rdp_print_job.h" -#include "rdp_status.h" +#include "print-job.h" +#include "status.h" #include "unicode.h" #include diff --git a/src/protocols/rdp/rdpdr_printer.h b/src/protocols/rdp/channels/rdpdr/rdpdr-printer.h similarity index 97% rename from src/protocols/rdp/rdpdr_printer.h rename to src/protocols/rdp/channels/rdpdr/rdpdr-printer.h index c9b30ddc..8e967c7a 100644 --- a/src/protocols/rdp/rdpdr_printer.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-printer.h @@ -22,7 +22,7 @@ #define GUAC_RDPDR_PRINTER_H #include "config.h" -#include "rdpdr.h" +#include "channels/rdpdr/rdpdr.h" #include diff --git a/src/protocols/rdp/rdpdr.c b/src/protocols/rdp/channels/rdpdr/rdpdr.c similarity index 97% rename from src/protocols/rdp/rdpdr.c rename to src/protocols/rdp/channels/rdpdr/rdpdr.c index f334e5e5..6fe4c65e 100644 --- a/src/protocols/rdp/rdpdr.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr.c @@ -18,15 +18,15 @@ */ #include "config.h" -#include "channels.h" +#include "plugins/channels.h" #include "rdp.h" -#include "rdp_fs.h" -#include "rdp_settings.h" -#include "rdp_stream.h" -#include "rdpdr.h" -#include "rdpdr_fs_service.h" -#include "rdpdr_messages.h" -#include "rdpdr_printer.h" +#include "fs.h" +#include "settings.h" +#include "stream.h" +#include "channels/rdpdr/rdpdr.h" +#include "channels/rdpdr/rdpdr-fs.h" +#include "channels/rdpdr/rdpdr-messages.h" +#include "channels/rdpdr/rdpdr-printer.h" #include #include diff --git a/src/protocols/rdp/rdpdr.h b/src/protocols/rdp/channels/rdpdr/rdpdr.h similarity index 99% rename from src/protocols/rdp/rdpdr.h rename to src/protocols/rdp/channels/rdpdr/rdpdr.h index b5e59f0a..3984d9c4 100644 --- a/src/protocols/rdp/rdpdr.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr.h @@ -21,7 +21,7 @@ #define GUAC_RDP_RDPDR_H #include "config.h" -#include "common-svc.h" +#include "channels/common-svc.h" #include #include diff --git a/src/protocols/rdp/rdpsnd_messages.c b/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.c similarity index 99% rename from src/protocols/rdp/rdpsnd_messages.c rename to src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.c index 5bed83b7..76856833 100644 --- a/src/protocols/rdp/rdpsnd_messages.c +++ b/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.c @@ -20,8 +20,8 @@ #include "config.h" #include "rdp.h" -#include "rdpsnd.h" -#include "rdpsnd_messages.h" +#include "channels/rdpsnd/rdpsnd.h" +#include "channels/rdpsnd/rdpsnd-messages.h" #include #include diff --git a/src/protocols/rdp/rdpsnd_messages.h b/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.h similarity index 99% rename from src/protocols/rdp/rdpsnd_messages.h rename to src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.h index 4a621d86..737f6222 100644 --- a/src/protocols/rdp/rdpsnd_messages.h +++ b/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.h @@ -22,7 +22,7 @@ #define GUAC_RDPSND_MESSAGES_H #include "config.h" -#include "common-svc.h" +#include "channels/common-svc.h" #include diff --git a/src/protocols/rdp/rdpsnd.c b/src/protocols/rdp/channels/rdpsnd/rdpsnd.c similarity index 96% rename from src/protocols/rdp/rdpsnd.c rename to src/protocols/rdp/channels/rdpsnd/rdpsnd.c index 04ef5379..59913445 100644 --- a/src/protocols/rdp/rdpsnd.c +++ b/src/protocols/rdp/channels/rdpsnd/rdpsnd.c @@ -18,10 +18,10 @@ */ #include "config.h" -#include "common-svc.h" +#include "channels/common-svc.h" #include "rdp.h" -#include "rdpsnd.h" -#include "rdpsnd_messages.h" +#include "channels/rdpsnd/rdpsnd.h" +#include "channels/rdpsnd/rdpsnd-messages.h" #include #include diff --git a/src/protocols/rdp/rdpsnd.h b/src/protocols/rdp/channels/rdpsnd/rdpsnd.h similarity index 99% rename from src/protocols/rdp/rdpsnd.h rename to src/protocols/rdp/channels/rdpsnd/rdpsnd.h index deec0de3..0c2abcee 100644 --- a/src/protocols/rdp/rdpsnd.h +++ b/src/protocols/rdp/channels/rdpsnd/rdpsnd.h @@ -21,7 +21,7 @@ #define GUAC_RDP_RDPSND_H #include "config.h" -#include "common-svc.h" +#include "channels/common-svc.h" #include diff --git a/src/protocols/rdp/client.c b/src/protocols/rdp/client.c index 4e724aae..d1e294be 100644 --- a/src/protocols/rdp/client.c +++ b/src/protocols/rdp/client.c @@ -19,12 +19,12 @@ #include "config.h" -#include "audio_input.h" +#include "channels/audio-input.h" #include "common/recording.h" #include "client.h" -#include "disp.h" +#include "channels/disp.h" #include "rdp.h" -#include "rdp_fs.h" +#include "fs.h" #include "user.h" #ifdef ENABLE_COMMON_SSH diff --git a/src/protocols/rdp/rdp_color.c b/src/protocols/rdp/color.c similarity index 98% rename from src/protocols/rdp/rdp_color.c rename to src/protocols/rdp/color.c index 0132fb25..a0d7170f 100644 --- a/src/protocols/rdp/rdp_color.c +++ b/src/protocols/rdp/color.c @@ -21,7 +21,7 @@ #include "client.h" #include "rdp.h" -#include "rdp_settings.h" +#include "settings.h" #include #include diff --git a/src/protocols/rdp/rdp_color.h b/src/protocols/rdp/color.h similarity index 100% rename from src/protocols/rdp/rdp_color.h rename to src/protocols/rdp/color.h diff --git a/src/protocols/rdp/rdp_fs.c b/src/protocols/rdp/fs.c similarity index 99% rename from src/protocols/rdp/rdp_fs.c rename to src/protocols/rdp/fs.c index 0e7345f9..fc8be597 100644 --- a/src/protocols/rdp/rdp_fs.c +++ b/src/protocols/rdp/fs.c @@ -19,9 +19,9 @@ #include "config.h" -#include "rdp_fs.h" -#include "rdp_status.h" -#include "rdp_stream.h" +#include "fs.h" +#include "status.h" +#include "stream.h" #include #include diff --git a/src/protocols/rdp/rdp_fs.h b/src/protocols/rdp/fs.h similarity index 100% rename from src/protocols/rdp/rdp_fs.h rename to src/protocols/rdp/fs.h diff --git a/src/protocols/rdp/rdp_gdi.c b/src/protocols/rdp/gdi.c similarity index 99% rename from src/protocols/rdp/rdp_gdi.c rename to src/protocols/rdp/gdi.c index 33de873a..5aed6061 100644 --- a/src/protocols/rdp/rdp_gdi.c +++ b/src/protocols/rdp/gdi.c @@ -22,9 +22,9 @@ #include "client.h" #include "common/surface.h" #include "rdp.h" -#include "rdp_bitmap.h" -#include "rdp_color.h" -#include "rdp_settings.h" +#include "bitmap.h" +#include "color.h" +#include "settings.h" #include #include diff --git a/src/protocols/rdp/rdp_gdi.h b/src/protocols/rdp/gdi.h similarity index 100% rename from src/protocols/rdp/rdp_gdi.h rename to src/protocols/rdp/gdi.h diff --git a/src/protocols/rdp/rdp_glyph.c b/src/protocols/rdp/glyph.c similarity index 98% rename from src/protocols/rdp/rdp_glyph.c rename to src/protocols/rdp/glyph.c index 96c4a14e..fe21df02 100644 --- a/src/protocols/rdp/rdp_glyph.c +++ b/src/protocols/rdp/glyph.c @@ -22,9 +22,9 @@ #include "client.h" #include "common/surface.h" #include "rdp.h" -#include "rdp_color.h" -#include "rdp_glyph.h" -#include "rdp_settings.h" +#include "color.h" +#include "glyph.h" +#include "settings.h" #include #include diff --git a/src/protocols/rdp/rdp_glyph.h b/src/protocols/rdp/glyph.h similarity index 100% rename from src/protocols/rdp/rdp_glyph.h rename to src/protocols/rdp/glyph.h diff --git a/src/protocols/rdp/input.c b/src/protocols/rdp/input.c index 9e455160..b1031e3f 100644 --- a/src/protocols/rdp/input.c +++ b/src/protocols/rdp/input.c @@ -21,9 +21,9 @@ #include "client.h" #include "common/recording.h" -#include "disp.h" +#include "channels/disp.h" #include "input.h" -#include "keyboard.h" +#include "keyboard/keyboard.h" #include "rdp.h" #include diff --git a/src/protocols/rdp/decompose.c b/src/protocols/rdp/keyboard/decompose.c similarity index 99% rename from src/protocols/rdp/decompose.c rename to src/protocols/rdp/keyboard/decompose.c index 5f559d99..1495f51c 100644 --- a/src/protocols/rdp/decompose.c +++ b/src/protocols/rdp/keyboard/decompose.c @@ -18,7 +18,7 @@ */ #include "config.h" -#include "keyboard.h" +#include "keyboard/keyboard.h" /** * The X11 keysym for the dead key which types a grave (`). diff --git a/src/protocols/rdp/decompose.h b/src/protocols/rdp/keyboard/decompose.h similarity index 98% rename from src/protocols/rdp/decompose.h rename to src/protocols/rdp/keyboard/decompose.h index a7ab1465..0d5a0765 100644 --- a/src/protocols/rdp/decompose.h +++ b/src/protocols/rdp/keyboard/decompose.h @@ -21,7 +21,7 @@ #define GUAC_RDP_DECOMPOSE_H #include "config.h" -#include "keyboard.h" +#include "keyboard/keyboard.h" /** * Attempts to type the given keysym by decomposing the associated character diff --git a/src/protocols/rdp/keyboard.c b/src/protocols/rdp/keyboard/keyboard.c similarity index 99% rename from src/protocols/rdp/keyboard.c rename to src/protocols/rdp/keyboard/keyboard.c index b0a0188b..90fc99df 100644 --- a/src/protocols/rdp/keyboard.c +++ b/src/protocols/rdp/keyboard/keyboard.c @@ -20,10 +20,10 @@ #include "config.h" #include "client.h" -#include "decompose.h" -#include "keyboard.h" +#include "keyboard/decompose.h" +#include "keyboard/keyboard.h" #include "rdp.h" -#include "rdp_keymap.h" +#include "keyboard/keymap.h" #include #include diff --git a/src/protocols/rdp/keyboard.h b/src/protocols/rdp/keyboard/keyboard.h similarity index 99% rename from src/protocols/rdp/keyboard.h rename to src/protocols/rdp/keyboard/keyboard.h index 79eed758..d280fa41 100644 --- a/src/protocols/rdp/keyboard.h +++ b/src/protocols/rdp/keyboard/keyboard.h @@ -20,7 +20,7 @@ #ifndef GUAC_RDP_KEYBOARD_H #define GUAC_RDP_KEYBOARD_H -#include "rdp_keymap.h" +#include "keyboard/keymap.h" #include diff --git a/src/protocols/rdp/rdp_keymap.c b/src/protocols/rdp/keyboard/keymap.c similarity index 98% rename from src/protocols/rdp/rdp_keymap.c rename to src/protocols/rdp/keyboard/keymap.c index 3be48a7d..b6ea7579 100644 --- a/src/protocols/rdp/rdp_keymap.c +++ b/src/protocols/rdp/keyboard/keymap.c @@ -19,7 +19,7 @@ #include "config.h" -#include "rdp_keymap.h" +#include "keyboard/keymap.h" #include diff --git a/src/protocols/rdp/rdp_keymap.h b/src/protocols/rdp/keyboard/keymap.h similarity index 100% rename from src/protocols/rdp/rdp_keymap.h rename to src/protocols/rdp/keyboard/keymap.h diff --git a/src/protocols/rdp/keymaps/base.keymap b/src/protocols/rdp/keyboard/keymaps/base.keymap similarity index 100% rename from src/protocols/rdp/keymaps/base.keymap rename to src/protocols/rdp/keyboard/keymaps/base.keymap diff --git a/src/protocols/rdp/keymaps/da_dk_qwerty.keymap b/src/protocols/rdp/keyboard/keymaps/da_dk_qwerty.keymap similarity index 100% rename from src/protocols/rdp/keymaps/da_dk_qwerty.keymap rename to src/protocols/rdp/keyboard/keymaps/da_dk_qwerty.keymap diff --git a/src/protocols/rdp/keymaps/de_ch_qwertz.keymap b/src/protocols/rdp/keyboard/keymaps/de_ch_qwertz.keymap similarity index 100% rename from src/protocols/rdp/keymaps/de_ch_qwertz.keymap rename to src/protocols/rdp/keyboard/keymaps/de_ch_qwertz.keymap diff --git a/src/protocols/rdp/keymaps/de_de_qwertz.keymap b/src/protocols/rdp/keyboard/keymaps/de_de_qwertz.keymap similarity index 100% rename from src/protocols/rdp/keymaps/de_de_qwertz.keymap rename to src/protocols/rdp/keyboard/keymaps/de_de_qwertz.keymap diff --git a/src/protocols/rdp/keymaps/en_gb_qwerty.keymap b/src/protocols/rdp/keyboard/keymaps/en_gb_qwerty.keymap similarity index 100% rename from src/protocols/rdp/keymaps/en_gb_qwerty.keymap rename to src/protocols/rdp/keyboard/keymaps/en_gb_qwerty.keymap diff --git a/src/protocols/rdp/keymaps/en_us_qwerty.keymap b/src/protocols/rdp/keyboard/keymaps/en_us_qwerty.keymap similarity index 100% rename from src/protocols/rdp/keymaps/en_us_qwerty.keymap rename to src/protocols/rdp/keyboard/keymaps/en_us_qwerty.keymap diff --git a/src/protocols/rdp/keymaps/es_es_qwerty.keymap b/src/protocols/rdp/keyboard/keymaps/es_es_qwerty.keymap similarity index 100% rename from src/protocols/rdp/keymaps/es_es_qwerty.keymap rename to src/protocols/rdp/keyboard/keymaps/es_es_qwerty.keymap diff --git a/src/protocols/rdp/keymaps/failsafe.keymap b/src/protocols/rdp/keyboard/keymaps/failsafe.keymap similarity index 100% rename from src/protocols/rdp/keymaps/failsafe.keymap rename to src/protocols/rdp/keyboard/keymaps/failsafe.keymap diff --git a/src/protocols/rdp/keymaps/fr_ch_qwertz.keymap b/src/protocols/rdp/keyboard/keymaps/fr_ch_qwertz.keymap similarity index 100% rename from src/protocols/rdp/keymaps/fr_ch_qwertz.keymap rename to src/protocols/rdp/keyboard/keymaps/fr_ch_qwertz.keymap diff --git a/src/protocols/rdp/keymaps/fr_fr_azerty.keymap b/src/protocols/rdp/keyboard/keymaps/fr_fr_azerty.keymap similarity index 100% rename from src/protocols/rdp/keymaps/fr_fr_azerty.keymap rename to src/protocols/rdp/keyboard/keymaps/fr_fr_azerty.keymap diff --git a/src/protocols/rdp/keymaps/generate.pl b/src/protocols/rdp/keyboard/keymaps/generate.pl similarity index 99% rename from src/protocols/rdp/keymaps/generate.pl rename to src/protocols/rdp/keyboard/keymaps/generate.pl index 8ca2a6b9..2aa360f6 100755 --- a/src/protocols/rdp/keymaps/generate.pl +++ b/src/protocols/rdp/keyboard/keymaps/generate.pl @@ -43,7 +43,7 @@ my @keymaps = (); open OUTPUT, ">", "_generated_keymaps.c"; print OUTPUT '#include "config.h"' . "\n" - . '#include "rdp_keymap.h"' . "\n" + . '#include "keyboard/keymap.h"' . "\n" . '#include ' . "\n" . '#include ' . "\n" . "\n" diff --git a/src/protocols/rdp/keymaps/it_it_qwerty.keymap b/src/protocols/rdp/keyboard/keymaps/it_it_qwerty.keymap similarity index 100% rename from src/protocols/rdp/keymaps/it_it_qwerty.keymap rename to src/protocols/rdp/keyboard/keymaps/it_it_qwerty.keymap diff --git a/src/protocols/rdp/keymaps/ja_jp_qwerty.keymap b/src/protocols/rdp/keyboard/keymaps/ja_jp_qwerty.keymap similarity index 100% rename from src/protocols/rdp/keymaps/ja_jp_qwerty.keymap rename to src/protocols/rdp/keyboard/keymaps/ja_jp_qwerty.keymap diff --git a/src/protocols/rdp/keymaps/pt_br_qwerty.keymap b/src/protocols/rdp/keyboard/keymaps/pt_br_qwerty.keymap similarity index 100% rename from src/protocols/rdp/keymaps/pt_br_qwerty.keymap rename to src/protocols/rdp/keyboard/keymaps/pt_br_qwerty.keymap diff --git a/src/protocols/rdp/keymaps/sv_se_qwerty.keymap b/src/protocols/rdp/keyboard/keymaps/sv_se_qwerty.keymap similarity index 100% rename from src/protocols/rdp/keymaps/sv_se_qwerty.keymap rename to src/protocols/rdp/keyboard/keymaps/sv_se_qwerty.keymap diff --git a/src/protocols/rdp/keymaps/tr_tr_qwerty.keymap b/src/protocols/rdp/keyboard/keymaps/tr_tr_qwerty.keymap similarity index 100% rename from src/protocols/rdp/keymaps/tr_tr_qwerty.keymap rename to src/protocols/rdp/keyboard/keymaps/tr_tr_qwerty.keymap diff --git a/src/protocols/rdp/channels.c b/src/protocols/rdp/plugins/channels.c similarity index 99% rename from src/protocols/rdp/channels.c rename to src/protocols/rdp/plugins/channels.c index 368846a8..9cf5a36b 100644 --- a/src/protocols/rdp/channels.c +++ b/src/protocols/rdp/plugins/channels.c @@ -18,7 +18,7 @@ */ #include "config.h" -#include "channels.h" +#include "plugins/channels.h" #include "rdp.h" #include diff --git a/src/protocols/rdp/channels.h b/src/protocols/rdp/plugins/channels.h similarity index 100% rename from src/protocols/rdp/channels.h rename to src/protocols/rdp/plugins/channels.h diff --git a/src/protocols/rdp/generate-entry-wrappers.pl b/src/protocols/rdp/plugins/generate-entry-wrappers.pl similarity index 98% rename from src/protocols/rdp/generate-entry-wrappers.pl rename to src/protocols/rdp/plugins/generate-entry-wrappers.pl index 21efdbca..f3fc0038 100755 --- a/src/protocols/rdp/generate-entry-wrappers.pl +++ b/src/protocols/rdp/plugins/generate-entry-wrappers.pl @@ -46,7 +46,7 @@ open OUTPUT, ">", "_generated_channel_entry_wrappers.c"; # Generate required headers print OUTPUT <<"EOF"; -#include "channels.h" +#include "plugins/channels.h" #include #include EOF diff --git a/src/protocols/rdp/guac-common-svc/common-svc-main.c b/src/protocols/rdp/plugins/guac-common-svc/guac-common-svc.c similarity index 99% rename from src/protocols/rdp/guac-common-svc/common-svc-main.c rename to src/protocols/rdp/plugins/guac-common-svc/guac-common-svc.c index 572a1d2c..7318e1e5 100644 --- a/src/protocols/rdp/guac-common-svc/common-svc-main.c +++ b/src/protocols/rdp/plugins/guac-common-svc/guac-common-svc.c @@ -18,7 +18,7 @@ */ #include "config.h" -#include "common-svc.h" +#include "channels/common-svc.h" #include #include diff --git a/src/protocols/rdp/guac_ai/ai_messages.c b/src/protocols/rdp/plugins/guacai/guacai-messages.c similarity index 99% rename from src/protocols/rdp/guac_ai/ai_messages.c rename to src/protocols/rdp/plugins/guacai/guacai-messages.c index e0161d59..341914af 100644 --- a/src/protocols/rdp/guac_ai/ai_messages.c +++ b/src/protocols/rdp/plugins/guacai/guacai-messages.c @@ -19,8 +19,8 @@ #include "config.h" -#include "ai_messages.h" -#include "audio_input.h" +#include "plugins/guacai/guacai-messages.h" +#include "channels/audio-input.h" #include "rdp.h" #include diff --git a/src/protocols/rdp/guac_ai/ai_messages.h b/src/protocols/rdp/plugins/guacai/guacai-messages.h similarity index 100% rename from src/protocols/rdp/guac_ai/ai_messages.h rename to src/protocols/rdp/plugins/guacai/guacai-messages.h diff --git a/src/protocols/rdp/guac_ai/ai_service.c b/src/protocols/rdp/plugins/guacai/guacai.c similarity index 98% rename from src/protocols/rdp/guac_ai/ai_service.c rename to src/protocols/rdp/plugins/guacai/guacai.c index aa6bca75..ba660786 100644 --- a/src/protocols/rdp/guac_ai/ai_service.c +++ b/src/protocols/rdp/plugins/guacai/guacai.c @@ -19,10 +19,10 @@ #include "config.h" -#include "ai_messages.h" -#include "ai_service.h" -#include "audio_input.h" -#include "ptr_string.h" +#include "plugins/guacai/guacai-messages.h" +#include "plugins/guacai/guacai.h" +#include "channels/audio-input.h" +#include "plugins/ptr-string.h" #include "rdp.h" #include diff --git a/src/protocols/rdp/guac_ai/ai_service.h b/src/protocols/rdp/plugins/guacai/guacai.h similarity index 100% rename from src/protocols/rdp/guac_ai/ai_service.h rename to src/protocols/rdp/plugins/guacai/guacai.h diff --git a/src/protocols/rdp/ptr_string.c b/src/protocols/rdp/plugins/ptr-string.c similarity index 97% rename from src/protocols/rdp/ptr_string.c rename to src/protocols/rdp/plugins/ptr-string.c index 5ec1b623..91311871 100644 --- a/src/protocols/rdp/ptr_string.c +++ b/src/protocols/rdp/plugins/ptr-string.c @@ -18,7 +18,7 @@ */ #include "config.h" -#include "ptr_string.h" +#include "plugins/ptr-string.h" #include diff --git a/src/protocols/rdp/ptr_string.h b/src/protocols/rdp/plugins/ptr-string.h similarity index 100% rename from src/protocols/rdp/ptr_string.h rename to src/protocols/rdp/plugins/ptr-string.h diff --git a/src/protocols/rdp/rdp_pointer.c b/src/protocols/rdp/pointer.c similarity index 99% rename from src/protocols/rdp/rdp_pointer.c rename to src/protocols/rdp/pointer.c index fb789842..3883e211 100644 --- a/src/protocols/rdp/rdp_pointer.c +++ b/src/protocols/rdp/pointer.c @@ -23,7 +23,7 @@ #include "common/cursor.h" #include "common/display.h" #include "rdp.h" -#include "rdp_pointer.h" +#include "pointer.h" #include #include diff --git a/src/protocols/rdp/rdp_pointer.h b/src/protocols/rdp/pointer.h similarity index 100% rename from src/protocols/rdp/rdp_pointer.h rename to src/protocols/rdp/pointer.h diff --git a/src/protocols/rdp/rdp_print_job.c b/src/protocols/rdp/print-job.c similarity index 99% rename from src/protocols/rdp/rdp_print_job.c rename to src/protocols/rdp/print-job.c index a3b51bc1..8e6211e4 100644 --- a/src/protocols/rdp/rdp_print_job.c +++ b/src/protocols/rdp/print-job.c @@ -19,7 +19,7 @@ #include "config.h" -#include "rdp_print_job.h" +#include "print-job.h" #include #include diff --git a/src/protocols/rdp/rdp_print_job.h b/src/protocols/rdp/print-job.h similarity index 100% rename from src/protocols/rdp/rdp_print_job.h rename to src/protocols/rdp/print-job.h diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index b2423da8..4bfc0c8d 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -19,28 +19,28 @@ #include "config.h" -#include "audio_input.h" -#include "channels.h" +#include "channels/audio-input.h" +#include "plugins/channels.h" #include "client.h" -#include "clipboard.h" +#include "channels/cliprdr.h" #include "common/cursor.h" #include "common/display.h" #include "common/recording.h" -#include "disp.h" +#include "channels/disp.h" #include "error.h" -#include "keyboard.h" -#include "pipe-svc.h" -#include "rail.h" +#include "keyboard/keyboard.h" +#include "channels/pipe-svc.h" +#include "channels/rail.h" #include "rdp.h" -#include "rdp_bitmap.h" -#include "rdp_fs.h" -#include "rdp_print_job.h" -#include "rdp_gdi.h" -#include "rdp_glyph.h" -#include "rdp_pointer.h" -#include "rdp_stream.h" -#include "rdpdr.h" -#include "rdpsnd.h" +#include "bitmap.h" +#include "fs.h" +#include "print-job.h" +#include "gdi.h" +#include "glyph.h" +#include "pointer.h" +#include "stream.h" +#include "channels/rdpdr/rdpdr.h" +#include "channels/rdpsnd/rdpsnd.h" #ifdef ENABLE_COMMON_SSH #include "common-ssh/sftp.h" diff --git a/src/protocols/rdp/rdp.h b/src/protocols/rdp/rdp.h index 5394bb36..64a5a507 100644 --- a/src/protocols/rdp/rdp.h +++ b/src/protocols/rdp/rdp.h @@ -22,18 +22,18 @@ #include "config.h" -#include "audio_input.h" -#include "clipboard.h" +#include "channels/audio-input.h" +#include "channels/cliprdr.h" #include "common/clipboard.h" #include "common/display.h" #include "common/list.h" #include "common/recording.h" #include "common/surface.h" -#include "disp.h" -#include "keyboard.h" -#include "rdp_fs.h" -#include "rdp_print_job.h" -#include "rdp_settings.h" +#include "channels/disp.h" +#include "keyboard/keyboard.h" +#include "fs.h" +#include "print-job.h" +#include "settings.h" #include #include diff --git a/src/protocols/rdp/rdp_settings.c b/src/protocols/rdp/settings.c similarity index 99% rename from src/protocols/rdp/rdp_settings.c rename to src/protocols/rdp/settings.c index e64aa07a..86e315ad 100644 --- a/src/protocols/rdp/rdp_settings.c +++ b/src/protocols/rdp/settings.c @@ -22,7 +22,7 @@ #include "client.h" #include "common/string.h" #include "rdp.h" -#include "rdp_settings.h" +#include "settings.h" #include "resolution.h" #include diff --git a/src/protocols/rdp/rdp_settings.h b/src/protocols/rdp/settings.h similarity index 99% rename from src/protocols/rdp/rdp_settings.h rename to src/protocols/rdp/settings.h index ae27e9d2..92fc3b83 100644 --- a/src/protocols/rdp/rdp_settings.h +++ b/src/protocols/rdp/settings.h @@ -23,7 +23,7 @@ #include "config.h" -#include "rdp_keymap.h" +#include "keyboard/keymap.h" #include diff --git a/src/protocols/rdp/rdp_status.h b/src/protocols/rdp/status.h similarity index 100% rename from src/protocols/rdp/rdp_status.h rename to src/protocols/rdp/status.h diff --git a/src/protocols/rdp/rdp_stream.c b/src/protocols/rdp/stream.c similarity index 99% rename from src/protocols/rdp/rdp_stream.c rename to src/protocols/rdp/stream.c index a497c928..fedec507 100644 --- a/src/protocols/rdp/rdp_stream.c +++ b/src/protocols/rdp/stream.c @@ -21,8 +21,8 @@ #include "config.h" #include "client.h" #include "rdp.h" -#include "rdp_fs.h" -#include "rdp_stream.h" +#include "fs.h" +#include "stream.h" #include #include diff --git a/src/protocols/rdp/rdp_stream.h b/src/protocols/rdp/stream.h similarity index 100% rename from src/protocols/rdp/rdp_stream.h rename to src/protocols/rdp/stream.h diff --git a/src/protocols/rdp/tests/fs/normalize_path.c b/src/protocols/rdp/tests/fs/normalize_path.c index ccf23e01..22a2d809 100644 --- a/src/protocols/rdp/tests/fs/normalize_path.c +++ b/src/protocols/rdp/tests/fs/normalize_path.c @@ -17,7 +17,7 @@ * under the License. */ -#include "rdp_fs.h" +#include "fs.h" #include #include diff --git a/src/protocols/rdp/user.c b/src/protocols/rdp/user.c index 1fc1189e..f2569f41 100644 --- a/src/protocols/rdp/user.c +++ b/src/protocols/rdp/user.c @@ -19,14 +19,14 @@ #include "config.h" -#include "audio_input.h" +#include "channels/audio-input.h" #include "common/display.h" #include "input.h" #include "user.h" -#include "pipe-svc.h" +#include "channels/pipe-svc.h" #include "rdp.h" -#include "rdp_settings.h" -#include "rdp_stream.h" +#include "settings.h" +#include "stream.h" #ifdef ENABLE_COMMON_SSH #include "sftp.h" From d7bbee35b01e85241979549a8f8bddf8bcbe37b0 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 23 Dec 2019 13:29:13 -0800 Subject: [PATCH 050/109] GUACAMOLE-249: Reorganize includes to match code standard. --- src/protocols/rdp/bitmap.c | 3 +-- src/protocols/rdp/bitmap.h | 5 ++-- src/protocols/rdp/channels/audio-input.h | 4 ++-- src/protocols/rdp/channels/cliprdr.c | 4 ++-- src/protocols/rdp/channels/cliprdr.h | 4 ++-- src/protocols/rdp/channels/common-svc.c | 2 +- src/protocols/rdp/channels/common-svc.h | 4 ++-- src/protocols/rdp/channels/disp.c | 4 ++-- src/protocols/rdp/channels/disp.h | 4 ++-- src/protocols/rdp/channels/pipe-svc.c | 7 +++--- src/protocols/rdp/channels/pipe-svc.h | 4 ++-- src/protocols/rdp/channels/rail.c | 5 ++-- src/protocols/rdp/channels/rail.h | 6 +++-- .../rdpdr/rdpdr-fs-messages-dir-info.h | 5 ++-- .../rdpdr/rdpdr-fs-messages-file-info.h | 5 ++-- .../rdpdr/rdpdr-fs-messages-vol-info.c | 2 +- .../rdpdr/rdpdr-fs-messages-vol-info.h | 5 ++-- .../rdp/channels/rdpdr/rdpdr-fs-messages.c | 4 ++-- .../rdp/channels/rdpdr/rdpdr-fs-messages.h | 5 ++-- src/protocols/rdp/channels/rdpdr/rdpdr-fs.c | 5 ++-- src/protocols/rdp/channels/rdpdr/rdpdr-fs.h | 5 ++-- .../rdp/channels/rdpdr/rdpdr-messages.c | 4 ++-- .../rdp/channels/rdpdr/rdpdr-messages.h | 5 ++-- .../rdp/channels/rdpdr/rdpdr-printer.c | 4 ++-- .../rdp/channels/rdpdr/rdpdr-printer.h | 5 ++-- src/protocols/rdp/channels/rdpdr/rdpdr.c | 12 +++++----- src/protocols/rdp/channels/rdpdr/rdpdr.h | 4 ++-- .../rdp/channels/rdpsnd/rdpsnd-messages.c | 10 ++++---- .../rdp/channels/rdpsnd/rdpsnd-messages.h | 5 ++-- src/protocols/rdp/channels/rdpsnd/rdpsnd.c | 4 ++-- src/protocols/rdp/channels/rdpsnd/rdpsnd.h | 4 ++-- src/protocols/rdp/client.c | 7 +++--- src/protocols/rdp/error.c | 1 - src/protocols/rdp/fs.c | 14 +++++------ src/protocols/rdp/fs.h | 5 ++-- src/protocols/rdp/gdi.c | 5 ++-- src/protocols/rdp/gdi.h | 5 ++-- src/protocols/rdp/glyph.c | 5 ++-- src/protocols/rdp/glyph.h | 5 ++-- src/protocols/rdp/input.c | 3 +-- src/protocols/rdp/keyboard/decompose.h | 4 ++-- src/protocols/rdp/keyboard/keyboard.c | 3 +-- src/protocols/rdp/keyboard/keymap.h | 5 ++-- src/protocols/rdp/plugins/channels.h | 4 ++-- .../plugins/guac-common-svc/guac-common-svc.c | 6 ++--- .../rdp/plugins/guacai/guacai-messages.c | 9 ++++---- .../rdp/plugins/guacai/guacai-messages.h | 4 ++-- src/protocols/rdp/plugins/guacai/guacai.c | 11 ++++----- src/protocols/rdp/plugins/guacai/guacai.h | 6 ++--- src/protocols/rdp/plugins/ptr-string.h | 4 ++-- src/protocols/rdp/pointer.c | 3 +-- src/protocols/rdp/pointer.h | 5 ++-- src/protocols/rdp/print-job.c | 1 - src/protocols/rdp/rdp.c | 23 +++++++++---------- src/protocols/rdp/rdp.h | 5 ++-- src/protocols/rdp/settings.c | 3 +-- src/protocols/rdp/settings.h | 6 ++--- src/protocols/rdp/status.h | 5 ++-- src/protocols/rdp/stream.c | 5 ++-- src/protocols/rdp/stream.h | 5 ++-- src/protocols/rdp/unicode.c | 4 ++-- src/protocols/rdp/user.c | 5 ++-- 62 files changed, 146 insertions(+), 179 deletions(-) diff --git a/src/protocols/rdp/bitmap.c b/src/protocols/rdp/bitmap.c index 093dae15..56d80e35 100644 --- a/src/protocols/rdp/bitmap.c +++ b/src/protocols/rdp/bitmap.c @@ -18,12 +18,11 @@ */ #include "config.h" - +#include "bitmap.h" #include "client.h" #include "common/display.h" #include "common/surface.h" #include "rdp.h" -#include "bitmap.h" #include "settings.h" #include diff --git a/src/protocols/rdp/bitmap.h b/src/protocols/rdp/bitmap.h index 23c56404..07d3688d 100644 --- a/src/protocols/rdp/bitmap.h +++ b/src/protocols/rdp/bitmap.h @@ -17,9 +17,8 @@ * under the License. */ - -#ifndef _GUAC_RDP_RDP_BITMAP_H -#define _GUAC_RDP_RDP_BITMAP_H +#ifndef GUAC_RDP_BITMAP_H +#define GUAC_RDP_BITMAP_H #include "config.h" #include "common/display.h" diff --git a/src/protocols/rdp/channels/audio-input.h b/src/protocols/rdp/channels/audio-input.h index 3f987619..19b6f66c 100644 --- a/src/protocols/rdp/channels/audio-input.h +++ b/src/protocols/rdp/channels/audio-input.h @@ -17,8 +17,8 @@ * under the License. */ -#ifndef GUAC_RDP_AUDIO_INPUT_H -#define GUAC_RDP_AUDIO_INPUT_H +#ifndef GUAC_RDP_CHANNELS_AUDIO_INPUT_H +#define GUAC_RDP_CHANNELS_AUDIO_INPUT_H #include "config.h" diff --git a/src/protocols/rdp/channels/cliprdr.c b/src/protocols/rdp/channels/cliprdr.c index 8cc43fec..fc0e31eb 100644 --- a/src/protocols/rdp/channels/cliprdr.c +++ b/src/protocols/rdp/channels/cliprdr.c @@ -19,11 +19,11 @@ #include "config.h" -#include "plugins/channels.h" -#include "client.h" #include "channels/cliprdr.h" +#include "client.h" #include "common/clipboard.h" #include "common/iconv.h" +#include "plugins/channels.h" #include "rdp.h" #include diff --git a/src/protocols/rdp/channels/cliprdr.h b/src/protocols/rdp/channels/cliprdr.h index 2562f12e..42cfddec 100644 --- a/src/protocols/rdp/channels/cliprdr.h +++ b/src/protocols/rdp/channels/cliprdr.h @@ -17,8 +17,8 @@ * under the License. */ -#ifndef GUAC_RDP_CLIPBOARD_H -#define GUAC_RDP_CLIPBOARD_H +#ifndef GUAC_RDP_CHANNELS_CLIPRDR_H +#define GUAC_RDP_CHANNELS_CLIPRDR_H #include "config.h" #include "common/clipboard.h" diff --git a/src/protocols/rdp/channels/common-svc.c b/src/protocols/rdp/channels/common-svc.c index 0ba83220..a089bac5 100644 --- a/src/protocols/rdp/channels/common-svc.c +++ b/src/protocols/rdp/channels/common-svc.c @@ -18,8 +18,8 @@ */ #include "config.h" -#include "plugins/channels.h" #include "channels/common-svc.h" +#include "plugins/channels.h" #include "rdp.h" #include diff --git a/src/protocols/rdp/channels/common-svc.h b/src/protocols/rdp/channels/common-svc.h index 5370d5f6..3be2c006 100644 --- a/src/protocols/rdp/channels/common-svc.h +++ b/src/protocols/rdp/channels/common-svc.h @@ -17,8 +17,8 @@ * under the License. */ -#ifndef GUAC_RDP_SVC_H -#define GUAC_RDP_SVC_H +#ifndef GUAC_RDP_CHANNELS_COMMON_SVC_H +#define GUAC_RDP_CHANNELS_COMMON_SVC_H #include "config.h" diff --git a/src/protocols/rdp/channels/disp.c b/src/protocols/rdp/channels/disp.c index 73920f46..d487a043 100644 --- a/src/protocols/rdp/channels/disp.c +++ b/src/protocols/rdp/channels/disp.c @@ -18,9 +18,9 @@ */ #include "config.h" -#include "plugins/channels.h" -#include "client.h" #include "channels/disp.h" +#include "client.h" +#include "plugins/channels.h" #include "rdp.h" #include "settings.h" diff --git a/src/protocols/rdp/channels/disp.h b/src/protocols/rdp/channels/disp.h index e88e8e48..650f7ad8 100644 --- a/src/protocols/rdp/channels/disp.h +++ b/src/protocols/rdp/channels/disp.h @@ -17,8 +17,8 @@ * under the License. */ -#ifndef GUAC_RDP_DISP_H -#define GUAC_RDP_DISP_H +#ifndef GUAC_RDP_CHANNELS_DISP_H +#define GUAC_RDP_CHANNELS_DISP_H #include "settings.h" diff --git a/src/protocols/rdp/channels/pipe-svc.c b/src/protocols/rdp/channels/pipe-svc.c index 68017ab1..3bf90ed9 100644 --- a/src/protocols/rdp/channels/pipe-svc.c +++ b/src/protocols/rdp/channels/pipe-svc.c @@ -18,12 +18,11 @@ */ #include "config.h" - -#include "plugins/channels.h" -#include "client.h" -#include "common/list.h" #include "channels/common-svc.h" #include "channels/pipe-svc.h" +#include "client.h" +#include "common/list.h" +#include "plugins/channels.h" #include "rdp.h" #include diff --git a/src/protocols/rdp/channels/pipe-svc.h b/src/protocols/rdp/channels/pipe-svc.h index 0744740f..f75cebbf 100644 --- a/src/protocols/rdp/channels/pipe-svc.h +++ b/src/protocols/rdp/channels/pipe-svc.h @@ -17,8 +17,8 @@ * under the License. */ -#ifndef GUAC_RDP_PIPE_SVC_H -#define GUAC_RDP_PIPE_SVC_H +#ifndef GUAC_RDP_CHANNELS_PIPE_SVC_H +#define GUAC_RDP_CHANNELS_PIPE_SVC_H #include "config.h" #include "channels/common-svc.h" diff --git a/src/protocols/rdp/channels/rail.c b/src/protocols/rdp/channels/rail.c index 65bc9717..a96c0ad9 100644 --- a/src/protocols/rdp/channels/rail.c +++ b/src/protocols/rdp/channels/rail.c @@ -18,10 +18,9 @@ */ #include "config.h" - -#include "plugins/channels.h" -#include "client.h" #include "channels/rail.h" +#include "client.h" +#include "plugins/channels.h" #include "rdp.h" #include "settings.h" diff --git a/src/protocols/rdp/channels/rail.h b/src/protocols/rdp/channels/rail.h index 718c62b3..cb5e0891 100644 --- a/src/protocols/rdp/channels/rail.h +++ b/src/protocols/rdp/channels/rail.h @@ -17,11 +17,13 @@ * under the License. */ -#ifndef GUAC_RDP_RAIL_H -#define GUAC_RDP_RAIL_H +#ifndef GUAC_RDP_CHANNELS_RAIL_H +#define GUAC_RDP_CHANNELS_RAIL_H #include "config.h" +#include + /** * Initializes RemoteApp support for RDP and handling of the RAIL channel. If * failures occur, messages noting the specifics of those failures will be diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h index 02acfdd4..6f344171 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h @@ -17,9 +17,8 @@ * under the License. */ - -#ifndef GUAC_RDPDR_FS_MESSAGES_DIR_INFO_H -#define GUAC_RDPDR_FS_MESSAGES_DIR_INFO_H +#ifndef GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_DIR_INFO_H +#define RDP_CHANNELS_GUAC_RDPDR_FS_MESSAGES_DIR_INFO_H /** * Handlers for directory queries received over the RDPDR channel via the diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h index f2bb0d8f..5ce84424 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h @@ -17,9 +17,8 @@ * under the License. */ - -#ifndef GUAC_RDPDR_FS_MESSAGES_FILE_INFO_H -#define GUAC_RDPDR_FS_MESSAGES_FILE_INFO_H +#ifndef GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_FILE_INFO_H +#define GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_FILE_INFO_H /** * Handlers for file queries received over the RDPDR channel via the diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.c index afacde67..c6f90b94 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.c @@ -18,8 +18,8 @@ */ #include "config.h" -#include "channels/rdpdr/rdpdr.h" #include "channels/rdpdr/rdpdr-messages.h" +#include "channels/rdpdr/rdpdr.h" #include "fs.h" #include "status.h" diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.h index e6a95dd5..46ccdab2 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.h @@ -17,9 +17,8 @@ * under the License. */ - -#ifndef GUAC_RDPDR_FS_MESSAGES_VOL_INFO_H -#define GUAC_RDPDR_FS_MESSAGES_VOL_INFO_H +#ifndef GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_VOL_INFO_H +#define GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_VOL_INFO_H /** * Handlers for directory queries received over the RDPDR channel via the diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c index 67bf3495..38727ec9 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c @@ -18,12 +18,12 @@ */ #include "config.h" -#include "channels/rdpdr/rdpdr.h" #include "channels/rdpdr/rdpdr-fs-messages-dir-info.h" #include "channels/rdpdr/rdpdr-fs-messages-file-info.h" -#include "channels/rdpdr/rdpdr-fs-messages.h" #include "channels/rdpdr/rdpdr-fs-messages-vol-info.h" +#include "channels/rdpdr/rdpdr-fs-messages.h" #include "channels/rdpdr/rdpdr-messages.h" +#include "channels/rdpdr/rdpdr.h" #include "fs.h" #include "status.h" #include "unicode.h" diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.h index 27aba844..74f3ccda 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.h @@ -17,9 +17,8 @@ * under the License. */ - -#ifndef GUAC_RDPDR_FS_MESSAGES_H -#define GUAC_RDPDR_FS_MESSAGES_H +#ifndef GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_H +#define GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_H /** * Handlers for core drive I/O requests. Requests handled here may be simple diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs.c index 89f2ba6f..3ca862cf 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs.c @@ -17,12 +17,11 @@ * under the License. */ - #include "config.h" -#include "rdp.h" -#include "channels/rdpdr/rdpdr.h" #include "channels/rdpdr/rdpdr-fs-messages.h" #include "channels/rdpdr/rdpdr-messages.h" +#include "channels/rdpdr/rdpdr.h" +#include "rdp.h" #include #include diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h index 63f4a5d7..295a0225 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h @@ -17,9 +17,8 @@ * under the License. */ - -#ifndef GUAC_RDPDR_FS_H -#define GUAC_RDPDR_FS_H +#ifndef GUAC_RDP_RDPDR_FS_H +#define GUAC_RDP_RDPDR_FS_H /** * Functions and macros specific to filesystem handling and initialization diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-messages.c b/src/protocols/rdp/channels/rdpdr/rdpdr-messages.c index b063bbfa..b9b67383 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-messages.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-messages.c @@ -18,9 +18,9 @@ */ #include "config.h" -#include "rdp.h" -#include "channels/rdpdr/rdpdr.h" #include "channels/rdpdr/rdpdr-messages.h" +#include "channels/rdpdr/rdpdr.h" +#include "rdp.h" #include "unicode.h" #include diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-messages.h b/src/protocols/rdp/channels/rdpdr/rdpdr-messages.h index 1f2db3be..d1352d72 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-messages.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-messages.h @@ -17,9 +17,8 @@ * under the License. */ - -#ifndef GUAC_RDPDR_MESSAGES_H -#define GUAC_RDPDR_MESSAGES_H +#ifndef GUAC_RDP_CHANNELS_RDPDR_MESSAGES_H +#define GUAC_RDP_CHANNELS_RDPDR_MESSAGES_H #include "config.h" #include "channels/rdpdr/rdpdr.h" diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-printer.c b/src/protocols/rdp/channels/rdpdr/rdpdr-printer.c index dd16a5c4..8ee8bb7b 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-printer.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-printer.c @@ -18,11 +18,11 @@ */ #include "config.h" -#include "channels/rdpdr/rdpdr.h" #include "channels/rdpdr/rdpdr-messages.h" #include "channels/rdpdr/rdpdr-printer.h" -#include "rdp.h" +#include "channels/rdpdr/rdpdr.h" #include "print-job.h" +#include "rdp.h" #include "status.h" #include "unicode.h" diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-printer.h b/src/protocols/rdp/channels/rdpdr/rdpdr-printer.h index 8e967c7a..3e0df55d 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-printer.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-printer.h @@ -17,9 +17,8 @@ * under the License. */ - -#ifndef GUAC_RDPDR_PRINTER_H -#define GUAC_RDPDR_PRINTER_H +#ifndef GUAC_RDP_CHANNELS_RDPDR_PRINTER_H +#define GUAC_RDP_CHANNELS_RDPDR_PRINTER_H #include "config.h" #include "channels/rdpdr/rdpdr.h" diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr.c b/src/protocols/rdp/channels/rdpdr/rdpdr.c index 6fe4c65e..10b594f6 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr.c @@ -18,15 +18,15 @@ */ #include "config.h" -#include "plugins/channels.h" -#include "rdp.h" -#include "fs.h" -#include "settings.h" -#include "stream.h" -#include "channels/rdpdr/rdpdr.h" #include "channels/rdpdr/rdpdr-fs.h" #include "channels/rdpdr/rdpdr-messages.h" #include "channels/rdpdr/rdpdr-printer.h" +#include "channels/rdpdr/rdpdr.h" +#include "fs.h" +#include "plugins/channels.h" +#include "rdp.h" +#include "settings.h" +#include "stream.h" #include #include diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr.h b/src/protocols/rdp/channels/rdpdr/rdpdr.h index 3984d9c4..fa25f3d2 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr.h @@ -17,8 +17,8 @@ * under the License. */ -#ifndef GUAC_RDP_RDPDR_H -#define GUAC_RDP_RDPDR_H +#ifndef GUAC_RDP_CHANNELS_RDPDR_H +#define GUAC_RDP_CHANNELS_RDPDR_H #include "config.h" #include "channels/common-svc.h" diff --git a/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.c b/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.c index 76856833..f0dedaa0 100644 --- a/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.c +++ b/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.c @@ -19,12 +19,9 @@ #include "config.h" -#include "rdp.h" -#include "channels/rdpsnd/rdpsnd.h" #include "channels/rdpsnd/rdpsnd-messages.h" - -#include -#include +#include "channels/rdpsnd/rdpsnd.h" +#include "rdp.h" #include #include @@ -32,6 +29,9 @@ #include #include +#include +#include + void guac_rdpsnd_formats_handler(guac_rdp_common_svc* svc, wStream* input_stream, guac_rdpsnd_pdu_header* header) { diff --git a/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.h b/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.h index 737f6222..3c3733c6 100644 --- a/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.h +++ b/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.h @@ -17,9 +17,8 @@ * under the License. */ - -#ifndef GUAC_RDPSND_MESSAGES_H -#define GUAC_RDPSND_MESSAGES_H +#ifndef GUAC_RDP_CHANNELS_RDPSND_MESSAGES_H +#define GUAC_RDP_CHANNELS_RDPSND_MESSAGES_H #include "config.h" #include "channels/common-svc.h" diff --git a/src/protocols/rdp/channels/rdpsnd/rdpsnd.c b/src/protocols/rdp/channels/rdpsnd/rdpsnd.c index 59913445..5859d4e3 100644 --- a/src/protocols/rdp/channels/rdpsnd/rdpsnd.c +++ b/src/protocols/rdp/channels/rdpsnd/rdpsnd.c @@ -19,9 +19,9 @@ #include "config.h" #include "channels/common-svc.h" -#include "rdp.h" -#include "channels/rdpsnd/rdpsnd.h" #include "channels/rdpsnd/rdpsnd-messages.h" +#include "channels/rdpsnd/rdpsnd.h" +#include "rdp.h" #include #include diff --git a/src/protocols/rdp/channels/rdpsnd/rdpsnd.h b/src/protocols/rdp/channels/rdpsnd/rdpsnd.h index 0c2abcee..014d04d8 100644 --- a/src/protocols/rdp/channels/rdpsnd/rdpsnd.h +++ b/src/protocols/rdp/channels/rdpsnd/rdpsnd.h @@ -17,8 +17,8 @@ * under the License. */ -#ifndef GUAC_RDP_RDPSND_H -#define GUAC_RDP_RDPSND_H +#ifndef GUAC_RDP_CHANNELS_RDPSND_H +#define GUAC_RDP_CHANNELS_RDPSND_H #include "config.h" #include "channels/common-svc.h" diff --git a/src/protocols/rdp/client.c b/src/protocols/rdp/client.c index d1e294be..123e1339 100644 --- a/src/protocols/rdp/client.c +++ b/src/protocols/rdp/client.c @@ -18,13 +18,12 @@ */ #include "config.h" - #include "channels/audio-input.h" -#include "common/recording.h" -#include "client.h" #include "channels/disp.h" -#include "rdp.h" +#include "client.h" +#include "common/recording.h" #include "fs.h" +#include "rdp.h" #include "user.h" #ifdef ENABLE_COMMON_SSH diff --git a/src/protocols/rdp/error.c b/src/protocols/rdp/error.c index e3403625..0fbc6de9 100644 --- a/src/protocols/rdp/error.c +++ b/src/protocols/rdp/error.c @@ -18,7 +18,6 @@ */ #include "config.h" - #include "error.h" #include "rdp.h" diff --git a/src/protocols/rdp/fs.c b/src/protocols/rdp/fs.c index fc8be597..68689cd2 100644 --- a/src/protocols/rdp/fs.c +++ b/src/protocols/rdp/fs.c @@ -23,6 +23,13 @@ #include "status.h" #include "stream.h" +#include +#include +#include +#include +#include +#include + #include #include #include @@ -35,13 +42,6 @@ #include #include -#include -#include -#include -#include -#include -#include - guac_rdp_fs* guac_rdp_fs_alloc(guac_client* client, const char* drive_path, int create_drive_path) { diff --git a/src/protocols/rdp/fs.h b/src/protocols/rdp/fs.h index 8586810b..1f140bb8 100644 --- a/src/protocols/rdp/fs.h +++ b/src/protocols/rdp/fs.h @@ -17,9 +17,8 @@ * under the License. */ - -#ifndef __GUAC_RDP_FS_H -#define __GUAC_RDP_FS_H +#ifndef GUAC_RDP_FS_H +#define GUAC_RDP_FS_H /** * Functions and macros specific to filesystem handling and initialization diff --git a/src/protocols/rdp/gdi.c b/src/protocols/rdp/gdi.c index 5aed6061..1961fdb5 100644 --- a/src/protocols/rdp/gdi.c +++ b/src/protocols/rdp/gdi.c @@ -18,12 +18,11 @@ */ #include "config.h" - +#include "bitmap.h" #include "client.h" +#include "color.h" #include "common/surface.h" #include "rdp.h" -#include "bitmap.h" -#include "color.h" #include "settings.h" #include diff --git a/src/protocols/rdp/gdi.h b/src/protocols/rdp/gdi.h index 29d29478..983a6e6a 100644 --- a/src/protocols/rdp/gdi.h +++ b/src/protocols/rdp/gdi.h @@ -17,9 +17,8 @@ * under the License. */ - -#ifndef _GUAC_RDP_RDP_GDI_H -#define _GUAC_RDP_RDP_GDI_H +#ifndef GUAC_RDP_GDI_H +#define GUAC_RDP_GDI_H #include "config.h" diff --git a/src/protocols/rdp/glyph.c b/src/protocols/rdp/glyph.c index fe21df02..6a0aaab8 100644 --- a/src/protocols/rdp/glyph.c +++ b/src/protocols/rdp/glyph.c @@ -18,12 +18,11 @@ */ #include "config.h" - #include "client.h" -#include "common/surface.h" -#include "rdp.h" #include "color.h" +#include "common/surface.h" #include "glyph.h" +#include "rdp.h" #include "settings.h" #include diff --git a/src/protocols/rdp/glyph.h b/src/protocols/rdp/glyph.h index c14efbbc..fa824e66 100644 --- a/src/protocols/rdp/glyph.h +++ b/src/protocols/rdp/glyph.h @@ -17,9 +17,8 @@ * under the License. */ - -#ifndef _GUAC_RDP_RDP_GLYPH_H -#define _GUAC_RDP_RDP_GLYPH_H +#ifndef GUAC_RDP_GLYPH_H +#define GUAC_RDP_GLYPH_H #include "config.h" diff --git a/src/protocols/rdp/input.c b/src/protocols/rdp/input.c index b1031e3f..44a46998 100644 --- a/src/protocols/rdp/input.c +++ b/src/protocols/rdp/input.c @@ -18,10 +18,9 @@ */ #include "config.h" - +#include "channels/disp.h" #include "client.h" #include "common/recording.h" -#include "channels/disp.h" #include "input.h" #include "keyboard/keyboard.h" #include "rdp.h" diff --git a/src/protocols/rdp/keyboard/decompose.h b/src/protocols/rdp/keyboard/decompose.h index 0d5a0765..0c3765ed 100644 --- a/src/protocols/rdp/keyboard/decompose.h +++ b/src/protocols/rdp/keyboard/decompose.h @@ -17,8 +17,8 @@ * under the License. */ -#ifndef GUAC_RDP_DECOMPOSE_H -#define GUAC_RDP_DECOMPOSE_H +#ifndef GUAC_RDP_KEYBOARD_DECOMPOSE_H +#define GUAC_RDP_KEYBOARD_DECOMPOSE_H #include "config.h" #include "keyboard/keyboard.h" diff --git a/src/protocols/rdp/keyboard/keyboard.c b/src/protocols/rdp/keyboard/keyboard.c index 90fc99df..7b1414c8 100644 --- a/src/protocols/rdp/keyboard/keyboard.c +++ b/src/protocols/rdp/keyboard/keyboard.c @@ -18,12 +18,11 @@ */ #include "config.h" - #include "client.h" #include "keyboard/decompose.h" #include "keyboard/keyboard.h" -#include "rdp.h" #include "keyboard/keymap.h" +#include "rdp.h" #include #include diff --git a/src/protocols/rdp/keyboard/keymap.h b/src/protocols/rdp/keyboard/keymap.h index 05ed6db5..d0074e52 100644 --- a/src/protocols/rdp/keyboard/keymap.h +++ b/src/protocols/rdp/keyboard/keymap.h @@ -17,9 +17,8 @@ * under the License. */ - -#ifndef _GUAC_RDP_RDP_KEYMAP_H -#define _GUAC_RDP_RDP_KEYMAP_H +#ifndef GUAC_RDP_KEYBOARD_KEYMAP_H +#define GUAC_RDP_KEYBOARD_KEYMAP_H #include "config.h" diff --git a/src/protocols/rdp/plugins/channels.h b/src/protocols/rdp/plugins/channels.h index d31a685b..f324f876 100644 --- a/src/protocols/rdp/plugins/channels.h +++ b/src/protocols/rdp/plugins/channels.h @@ -17,8 +17,8 @@ * under the License. */ -#ifndef GUAC_RDP_CHANNELS_H -#define GUAC_RDP_CHANNELS_H +#ifndef GUAC_RDP_PLUGINS_CHANNELS_H +#define GUAC_RDP_PLUGINS_CHANNELS_H #include "config.h" diff --git a/src/protocols/rdp/plugins/guac-common-svc/guac-common-svc.c b/src/protocols/rdp/plugins/guac-common-svc/guac-common-svc.c index 7318e1e5..c55b606e 100644 --- a/src/protocols/rdp/plugins/guac-common-svc/guac-common-svc.c +++ b/src/protocols/rdp/plugins/guac-common-svc/guac-common-svc.c @@ -20,9 +20,6 @@ #include "config.h" #include "channels/common-svc.h" -#include -#include - #include #include #include @@ -31,6 +28,9 @@ #include #include +#include +#include + /** * Event handler for events which deal with data transmitted over an open SVC. * This specific implementation of the event handler currently handles only the diff --git a/src/protocols/rdp/plugins/guacai/guacai-messages.c b/src/protocols/rdp/plugins/guacai/guacai-messages.c index 341914af..083d7ae3 100644 --- a/src/protocols/rdp/plugins/guacai/guacai-messages.c +++ b/src/protocols/rdp/plugins/guacai/guacai-messages.c @@ -18,19 +18,18 @@ */ #include "config.h" - -#include "plugins/guacai/guacai-messages.h" #include "channels/audio-input.h" +#include "plugins/guacai/guacai-messages.h" #include "rdp.h" -#include - -#include #include #include +#include #include #include +#include + /** * Reads AUDIO_FORMAT data from the given stream into the given struct. * diff --git a/src/protocols/rdp/plugins/guacai/guacai-messages.h b/src/protocols/rdp/plugins/guacai/guacai-messages.h index 1d825af0..a2d35050 100644 --- a/src/protocols/rdp/plugins/guacai/guacai-messages.h +++ b/src/protocols/rdp/plugins/guacai/guacai-messages.h @@ -17,8 +17,8 @@ * under the License. */ -#ifndef GUAC_RDP_AI_MESSAGES_H -#define GUAC_RDP_AI_MESSAGES_H +#ifndef GUAC_RDP_PLUGINS_GUACAI_MESSAGES_H +#define GUAC_RDP_PLUGINS_GUACAI_MESSAGES_H #include "config.h" diff --git a/src/protocols/rdp/plugins/guacai/guacai.c b/src/protocols/rdp/plugins/guacai/guacai.c index ba660786..ac1f67b3 100644 --- a/src/protocols/rdp/plugins/guacai/guacai.c +++ b/src/protocols/rdp/plugins/guacai/guacai.c @@ -18,22 +18,21 @@ */ #include "config.h" - +#include "channels/audio-input.h" #include "plugins/guacai/guacai-messages.h" #include "plugins/guacai/guacai.h" -#include "channels/audio-input.h" #include "plugins/ptr-string.h" #include "rdp.h" -#include -#include - -#include #include #include +#include #include #include +#include +#include + /** * Handles the given data received along the AUDIO_INPUT channel of the RDP * connection associated with the given guac_client. This handler is diff --git a/src/protocols/rdp/plugins/guacai/guacai.h b/src/protocols/rdp/plugins/guacai/guacai.h index 28f2227e..dacf531a 100644 --- a/src/protocols/rdp/plugins/guacai/guacai.h +++ b/src/protocols/rdp/plugins/guacai/guacai.h @@ -17,14 +17,14 @@ * under the License. */ -#ifndef GUAC_RDP_AI_SERVICE_H -#define GUAC_RDP_AI_SERVICE_H +#ifndef GUAC_RDP_PLUGINS_GUACAI_H +#define GUAC_RDP_PLUGINS_GUACAI_H #include "config.h" -#include #include #include +#include #include /** diff --git a/src/protocols/rdp/plugins/ptr-string.h b/src/protocols/rdp/plugins/ptr-string.h index 9a9156bf..bcc226c4 100644 --- a/src/protocols/rdp/plugins/ptr-string.h +++ b/src/protocols/rdp/plugins/ptr-string.h @@ -17,8 +17,8 @@ * under the License. */ -#ifndef GUAC_RDP_PTR_STRING_H -#define GUAC_RDP_PTR_STRING_H +#ifndef GUAC_RDP_PLUGINS_PTR_STRING_H +#define GUAC_RDP_PLUGINS_PTR_STRING_H #include "config.h" diff --git a/src/protocols/rdp/pointer.c b/src/protocols/rdp/pointer.c index 3883e211..498bc883 100644 --- a/src/protocols/rdp/pointer.c +++ b/src/protocols/rdp/pointer.c @@ -18,12 +18,11 @@ */ #include "config.h" - #include "client.h" #include "common/cursor.h" #include "common/display.h" -#include "rdp.h" #include "pointer.h" +#include "rdp.h" #include #include diff --git a/src/protocols/rdp/pointer.h b/src/protocols/rdp/pointer.h index d3809e92..7f4547b7 100644 --- a/src/protocols/rdp/pointer.h +++ b/src/protocols/rdp/pointer.h @@ -17,9 +17,8 @@ * under the License. */ - -#ifndef _GUAC_RDP_RDP_POINTER_H -#define _GUAC_RDP_RDP_POINTER_H +#ifndef GUAC_RDP_POINTER_H +#define GUAC_RDP_POINTER_H #include "config.h" #include "common/display.h" diff --git a/src/protocols/rdp/print-job.c b/src/protocols/rdp/print-job.c index 8e6211e4..fed49bb3 100644 --- a/src/protocols/rdp/print-job.c +++ b/src/protocols/rdp/print-job.c @@ -17,7 +17,6 @@ * under the License. */ - #include "config.h" #include "print-job.h" diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 4bfc0c8d..7e91ef11 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -18,29 +18,28 @@ */ #include "config.h" - +#include "bitmap.h" #include "channels/audio-input.h" -#include "plugins/channels.h" -#include "client.h" #include "channels/cliprdr.h" +#include "channels/disp.h" +#include "channels/pipe-svc.h" +#include "channels/rail.h" +#include "channels/rdpdr/rdpdr.h" +#include "channels/rdpsnd/rdpsnd.h" +#include "client.h" #include "common/cursor.h" #include "common/display.h" #include "common/recording.h" -#include "channels/disp.h" #include "error.h" -#include "keyboard/keyboard.h" -#include "channels/pipe-svc.h" -#include "channels/rail.h" -#include "rdp.h" -#include "bitmap.h" #include "fs.h" -#include "print-job.h" #include "gdi.h" #include "glyph.h" +#include "keyboard/keyboard.h" +#include "plugins/channels.h" #include "pointer.h" +#include "print-job.h" +#include "rdp.h" #include "stream.h" -#include "channels/rdpdr/rdpdr.h" -#include "channels/rdpsnd/rdpsnd.h" #ifdef ENABLE_COMMON_SSH #include "common-ssh/sftp.h" diff --git a/src/protocols/rdp/rdp.h b/src/protocols/rdp/rdp.h index 64a5a507..41f99a2b 100644 --- a/src/protocols/rdp/rdp.h +++ b/src/protocols/rdp/rdp.h @@ -21,17 +21,16 @@ #define GUAC_RDP_H #include "config.h" - #include "channels/audio-input.h" #include "channels/cliprdr.h" +#include "channels/disp.h" #include "common/clipboard.h" #include "common/display.h" #include "common/list.h" #include "common/recording.h" #include "common/surface.h" -#include "channels/disp.h" -#include "keyboard/keyboard.h" #include "fs.h" +#include "keyboard/keyboard.h" #include "print-job.h" #include "settings.h" diff --git a/src/protocols/rdp/settings.c b/src/protocols/rdp/settings.c index 86e315ad..861a2994 100644 --- a/src/protocols/rdp/settings.c +++ b/src/protocols/rdp/settings.c @@ -18,12 +18,11 @@ */ #include "config.h" - #include "client.h" #include "common/string.h" #include "rdp.h" -#include "settings.h" #include "resolution.h" +#include "settings.h" #include #include diff --git a/src/protocols/rdp/settings.h b/src/protocols/rdp/settings.h index 92fc3b83..7679ae1e 100644 --- a/src/protocols/rdp/settings.h +++ b/src/protocols/rdp/settings.h @@ -17,15 +17,15 @@ * under the License. */ - -#ifndef __GUAC_RDP_SETTINGS_H -#define __GUAC_RDP_SETTINGS_H +#ifndef GUAC_RDP_SETTINGS_H +#define GUAC_RDP_SETTINGS_H #include "config.h" #include "keyboard/keymap.h" #include +#include /** * The maximum number of bytes in the client hostname claimed during diff --git a/src/protocols/rdp/status.h b/src/protocols/rdp/status.h index 6a2d5b6b..a624732f 100644 --- a/src/protocols/rdp/status.h +++ b/src/protocols/rdp/status.h @@ -17,9 +17,8 @@ * under the License. */ - -#ifndef __GUAC_RDP_STATUS_H -#define __GUAC_RDP_STATUS_H +#ifndef GUAC_RDP_STATUS_H +#define GUAC_RDP_STATUS_H /** * RDP-specific status constants. diff --git a/src/protocols/rdp/stream.c b/src/protocols/rdp/stream.c index fedec507..3e7bdfaa 100644 --- a/src/protocols/rdp/stream.c +++ b/src/protocols/rdp/stream.c @@ -17,16 +17,15 @@ * under the License. */ - #include "config.h" #include "client.h" -#include "rdp.h" #include "fs.h" +#include "rdp.h" #include "stream.h" -#include #include #include +#include #include #include #include diff --git a/src/protocols/rdp/stream.h b/src/protocols/rdp/stream.h index 3ae8b0ff..3317c6cb 100644 --- a/src/protocols/rdp/stream.h +++ b/src/protocols/rdp/stream.h @@ -17,9 +17,8 @@ * under the License. */ - -#ifndef _GUAC_RDP_STREAM_H -#define _GUAC_RDP_STREAM_H +#ifndef GUAC_RDP_STREAM_H +#define GUAC_RDP_STREAM_H #include "config.h" #include "common/json.h" diff --git a/src/protocols/rdp/unicode.c b/src/protocols/rdp/unicode.c index 628615ac..5369f4c4 100644 --- a/src/protocols/rdp/unicode.c +++ b/src/protocols/rdp/unicode.c @@ -19,10 +19,10 @@ #include "config.h" -#include - #include +#include + void guac_rdp_utf16_to_utf8(const unsigned char* utf16, int length, char* utf8, int size) { diff --git a/src/protocols/rdp/user.c b/src/protocols/rdp/user.c index f2569f41..a22d138b 100644 --- a/src/protocols/rdp/user.c +++ b/src/protocols/rdp/user.c @@ -18,15 +18,14 @@ */ #include "config.h" - #include "channels/audio-input.h" +#include "channels/pipe-svc.h" #include "common/display.h" #include "input.h" -#include "user.h" -#include "channels/pipe-svc.h" #include "rdp.h" #include "settings.h" #include "stream.h" +#include "user.h" #ifdef ENABLE_COMMON_SSH #include "sftp.h" From 4752863b5b9e1326d215aa7c396a1f36ca2abc1d Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 23 Dec 2019 13:35:32 -0800 Subject: [PATCH 051/109] GUACAMOLE-249: Remove now-unnecessary status.h FreeRDP compatibility header. --- src/protocols/rdp/Makefile.am | 1 - .../rdpdr/rdpdr-fs-messages-dir-info.c | 2 +- .../rdpdr/rdpdr-fs-messages-file-info.c | 2 +- .../rdpdr/rdpdr-fs-messages-vol-info.c | 2 +- .../rdp/channels/rdpdr/rdpdr-fs-messages.c | 2 +- .../rdp/channels/rdpdr/rdpdr-printer.c | 2 +- src/protocols/rdp/fs.c | 2 +- src/protocols/rdp/status.h | 65 ------------------- 8 files changed, 6 insertions(+), 72 deletions(-) delete mode 100644 src/protocols/rdp/status.h diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index 880df9bb..3ba1da05 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -113,7 +113,6 @@ noinst_HEADERS = \ rdp.h \ resolution.h \ settings.h \ - status.h \ stream.h \ unicode.h \ user.h diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.c index 1a445d0a..256ac14a 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.c @@ -20,10 +20,10 @@ #include "config.h" #include "channels/rdpdr/rdpdr.h" #include "fs.h" -#include "status.h" #include "unicode.h" #include +#include #include #include diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.c index ee134e51..4629ca59 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.c @@ -20,9 +20,9 @@ #include "config.h" #include "channels/rdpdr/rdpdr.h" #include "fs.h" -#include "status.h" #include "unicode.h" +#include #include #include diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.c index c6f90b94..77f4cce8 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.c @@ -21,9 +21,9 @@ #include "channels/rdpdr/rdpdr-messages.h" #include "channels/rdpdr/rdpdr.h" #include "fs.h" -#include "status.h" #include +#include #include #include diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c index 38727ec9..bdf76f6c 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c @@ -25,11 +25,11 @@ #include "channels/rdpdr/rdpdr-messages.h" #include "channels/rdpdr/rdpdr.h" #include "fs.h" -#include "status.h" #include "unicode.h" #include #include +#include #include #include diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-printer.c b/src/protocols/rdp/channels/rdpdr/rdpdr-printer.c index 8ee8bb7b..c3359631 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-printer.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-printer.c @@ -23,7 +23,6 @@ #include "channels/rdpdr/rdpdr.h" #include "print-job.h" #include "rdp.h" -#include "status.h" #include "unicode.h" #include @@ -33,6 +32,7 @@ #include #include #include +#include #include #include diff --git a/src/protocols/rdp/fs.c b/src/protocols/rdp/fs.c index 68689cd2..0b39d836 100644 --- a/src/protocols/rdp/fs.c +++ b/src/protocols/rdp/fs.c @@ -20,7 +20,6 @@ #include "config.h" #include "fs.h" -#include "status.h" #include "stream.h" #include @@ -29,6 +28,7 @@ #include #include #include +#include #include #include diff --git a/src/protocols/rdp/status.h b/src/protocols/rdp/status.h deleted file mode 100644 index a624732f..00000000 --- a/src/protocols/rdp/status.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -#ifndef GUAC_RDP_STATUS_H -#define GUAC_RDP_STATUS_H - -/** - * RDP-specific status constants. - * - * @file rdp_status.h - */ - -#include "config.h" - -/* Include any constants from winpr/file.h, if available */ - -#ifdef ENABLE_WINPR -#include -#endif - -/* Constants which MAY be defined within FreeRDP */ - -#ifndef STATUS_SUCCESS -#define STATUS_SUCCESS 0x00000000 -#define STATUS_NO_MORE_FILES 0x80000006 -#define STATUS_DEVICE_OFF_LINE 0x80000010 -#define STATUS_NOT_IMPLEMENTED 0xC0000002 -#define STATUS_INVALID_PARAMETER 0xC000000D -#define STATUS_NO_SUCH_FILE 0xC000000F -#define STATUS_END_OF_FILE 0xC0000011 -#define STATUS_ACCESS_DENIED 0xC0000022 -#define STATUS_OBJECT_NAME_COLLISION 0xC0000035 -#define STATUS_DISK_FULL 0xC000007F -#define STATUS_FILE_INVALID 0xC0000098 -#define STATUS_FILE_IS_A_DIRECTORY 0xC00000BA -#define STATUS_NOT_SUPPORTED 0xC00000BB -#define STATUS_NOT_A_DIRECTORY 0xC0000103 -#define STATUS_TOO_MANY_OPENED_FILES 0xC000011F -#define STATUS_CANNOT_DELETE 0xC0000121 -#define STATUS_FILE_DELETED 0xC0000123 -#define STATUS_FILE_CLOSED 0xC0000128 -#endif - -/* Constants which are NEVER defined within FreeRDP */ - -#define STATUS_FILE_SYSTEM_LIMITATION 0xC0000427 -#define STATUS_FILE_TOO_LARGE 0xC0000904 - -#endif From 024fc2a1f7a4074b906c6e0c1fa8878b5a075fec Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 23 Dec 2019 19:26:49 -0800 Subject: [PATCH 052/109] GUACAMOLE-249: Callbacks for "drdynvc" plugin should return CHANNEL_RC_OK, including entry point. --- src/protocols/rdp/plugins/guacai/guacai.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/protocols/rdp/plugins/guacai/guacai.c b/src/protocols/rdp/plugins/guacai/guacai.c index ac1f67b3..de9dfb91 100644 --- a/src/protocols/rdp/plugins/guacai/guacai.c +++ b/src/protocols/rdp/plugins/guacai/guacai.c @@ -113,7 +113,7 @@ static UINT guac_rdp_ai_data(IWTSVirtualChannelCallback* channel_callback, /* Invoke generalized (API-independent) data handler */ guac_rdp_ai_handle_data(ai_channel_callback->client, channel, stream); - return 0; + return CHANNEL_RC_OK; } @@ -143,7 +143,7 @@ static UINT guac_rdp_ai_close(IWTSVirtualChannelCallback* channel_callback) { guac_rdp_audio_buffer_end(audio_buffer); free(ai_channel_callback); - return 0; + return CHANNEL_RC_OK; } @@ -202,7 +202,8 @@ static UINT guac_rdp_ai_new_connection( /* Return callback through pointer */ *channel_callback = (IWTSVirtualChannelCallback*) ai_channel_callback; - return 0; + + return CHANNEL_RC_OK; } @@ -240,7 +241,7 @@ static UINT guac_rdp_ai_initialize(IWTSPlugin* plugin, manager->CreateListener(manager, "AUDIO_INPUT", 0, (IWTSListenerCallback*) ai_listener_callback, NULL); - return 0; + return CHANNEL_RC_OK; } @@ -264,7 +265,7 @@ static UINT guac_rdp_ai_terminated(IWTSPlugin* plugin) { free(ai_plugin); guac_client_log(client, GUAC_LOG_DEBUG, "AUDIO_INPUT plugin unloaded."); - return 0; + return CHANNEL_RC_OK; } @@ -297,7 +298,7 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { guac_client_log(client, GUAC_LOG_DEBUG, "AUDIO_INPUT plugin loaded."); } - return 1; + return CHANNEL_RC_OK; } From bced87cff991f50c4944c5c38b525c702bdaa2d5 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 25 Dec 2019 01:34:57 -0800 Subject: [PATCH 053/109] GUACAMOLE-249: FreeRDP 2.0.0 requires the Clipboard Capabilities PDU to be manually sent. --- src/protocols/rdp/channels/cliprdr.c | 33 +++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/protocols/rdp/channels/cliprdr.c b/src/protocols/rdp/channels/cliprdr.c index fc0e31eb..4350455d 100644 --- a/src/protocols/rdp/channels/cliprdr.c +++ b/src/protocols/rdp/channels/cliprdr.c @@ -76,6 +76,36 @@ static UINT guac_rdp_cliprdr_send_format_list(CliprdrClientContext* cliprdr) { } +/** + * Sends a Clipboard Capabilities PDU to the RDP server describing the features + * of the CLIPRDR channel that are supported by the client. + * + * @param cliprdr + * The CliprdrClientContext structure used by FreeRDP to handle the + * CLIPRDR channel for the current RDP session. + * + * @return + * CHANNEL_RC_OK (zero) if the Clipboard Capabilities PDU was sent + * successfully, an error code (non-zero) otherwise. + */ +static UINT guac_rdp_cliprdr_send_capabilities(CliprdrClientContext* cliprdr) { + + CLIPRDR_GENERAL_CAPABILITY_SET cap_set = { + .capabilitySetType = CB_CAPSTYPE_GENERAL, /* CLIPRDR specification requires that this is CB_CAPSTYPE_GENERAL, the only defined set type */ + .capabilitySetLength = 12, /* The size of the capability set within the PDU - for CB_CAPSTYPE_GENERAL, this is ALWAYS 12 bytes */ + .version = CB_CAPS_VERSION_2, /* The version of the CLIPRDR specification supported */ + .generalFlags = CB_USE_LONG_FORMAT_NAMES /* Bitwise OR of all supported feature flags */ + }; + + CLIPRDR_CAPABILITIES caps = { + .cCapabilitiesSets = 1, + .capabilitySets = (CLIPRDR_CAPABILITY_SET*) &cap_set + }; + + return cliprdr->ClientCapabilities(cliprdr, &caps); + +} + /** * Callback invoked by the FreeRDP CLIPRDR plugin for received Monitor Ready * PDUs. The Monitor Ready PDU is sent by the RDP server only during @@ -107,7 +137,8 @@ static UINT guac_rdp_cliprdr_monitor_ready(CliprdrClientContext* cliprdr, guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received " "monitor ready."); - /* Respond with supported format list */ + /* Respond with capabilities and supported format list */ + guac_rdp_cliprdr_send_capabilities(cliprdr); return guac_rdp_cliprdr_send_format_list(cliprdr); } From 0c7091198f09e0df3f0def147e9ac667f4a2cfcd Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 25 Dec 2019 02:03:23 -0800 Subject: [PATCH 054/109] GUACAMOLE-249: Use correct start location of clipboard buffer (accidentally used pointer to end). --- src/protocols/rdp/channels/cliprdr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/rdp/channels/cliprdr.c b/src/protocols/rdp/channels/cliprdr.c index 4350455d..663ac71a 100644 --- a/src/protocols/rdp/channels/cliprdr.c +++ b/src/protocols/rdp/channels/cliprdr.c @@ -337,7 +337,7 @@ static UINT guac_rdp_cliprdr_format_data_request(CliprdrClientContext* cliprdr, writer, &output, GUAC_RDP_CLIPBOARD_MAX_LENGTH); CLIPRDR_FORMAT_DATA_RESPONSE data_response = { - .requestedFormatData = (BYTE*) output, + .requestedFormatData = (BYTE*) start, .dataLen = ((BYTE*) output) - start }; From 47a1dcc82eb1c6e1c7aca36468c62bed8659b197 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 25 Dec 2019 02:04:13 -0800 Subject: [PATCH 055/109] GUACAMOLE-249: Message flags of clipboard data response must be set to CB_RESPONSE_OK for data to be accepted. --- src/protocols/rdp/channels/cliprdr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/protocols/rdp/channels/cliprdr.c b/src/protocols/rdp/channels/cliprdr.c index 663ac71a..30e02f78 100644 --- a/src/protocols/rdp/channels/cliprdr.c +++ b/src/protocols/rdp/channels/cliprdr.c @@ -338,7 +338,8 @@ static UINT guac_rdp_cliprdr_format_data_request(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_DATA_RESPONSE data_response = { .requestedFormatData = (BYTE*) start, - .dataLen = ((BYTE*) output) - start + .dataLen = ((BYTE*) output) - start, + .msgFlags = CB_RESPONSE_OK }; guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending " From 69831995cb0746291134ebd309588b7b1fbc3455 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 27 Dec 2019 15:24:25 -0800 Subject: [PATCH 056/109] GUACAMOLE-249: Remove prototype for guac_rdp_bitmap_decompress(), which is no longer defined nor used. --- src/protocols/rdp/bitmap.h | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/src/protocols/rdp/bitmap.h b/src/protocols/rdp/bitmap.h index 07d3688d..6ccd04f4 100644 --- a/src/protocols/rdp/bitmap.h +++ b/src/protocols/rdp/bitmap.h @@ -120,42 +120,4 @@ void guac_rdp_bitmap_free(rdpContext* context, rdpBitmap* bitmap); BOOL guac_rdp_bitmap_setsurface(rdpContext* context, rdpBitmap* bitmap, BOOL primary); -/** - * Decompresses or copies the given image data, storing the result within the - * given bitmap, depending on the compressed flag. Note that even if the - * received data is not compressed, it is the duty of this function to also - * flip received data, if the row order is backwards. - * - * @param context - * The rdpContext associated with the current RDP session. - * - * @param bitmap - * The bitmap in which the decompressed/copied data should be stored. - * - * @param data - * Possibly-compressed image data. - * - * @param width - * The width of the image data, in pixels. - * - * @param height - * The height of the image data, in pixels. - * - * @param bpp - * The number of bits per pixel in the image data. - * - * @param length - * The length of the image data, in bytes. - * - * @param compressed - * TRUE if the image data is compressed, FALSE otherwise. - * - * @param codec_id - * The ID of the codec used to compress the image data. This parameter is - * currently ignored. - */ -BOOL guac_rdp_bitmap_decompress(rdpContext* context, rdpBitmap* bitmap, - const BYTE* data, UINT32 width, UINT32 height, UINT32 bpp, UINT32 length, - BOOL compressed, UINT32 codec_id); - #endif From 598b86a4cf190650d5e881c8b73361e4a958ceaf Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 27 Dec 2019 20:55:06 -0800 Subject: [PATCH 057/109] GUACAMOLE-249: Correct @file annotations within Doxygen comments of renamed headers. --- src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h | 2 +- src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h | 2 +- src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.h | 2 +- src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.h | 2 +- src/protocols/rdp/channels/rdpdr/rdpdr-fs.h | 2 +- src/protocols/rdp/fs.h | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h index 6f344171..25f745b5 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h @@ -25,7 +25,7 @@ * IRP_MJ_DIRECTORY_CONTROL major function and the IRP_MN_QUERY_DIRECTORY minor * function. * - * @file rdpdr_fs_messages_dir_info.h + * @file rdpdr-fs-messages-dir-info.h */ #include "config.h" diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h index 5ce84424..d2198f5d 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h @@ -24,7 +24,7 @@ * Handlers for file queries received over the RDPDR channel via the * IRP_MJ_QUERY_INFORMATION major function. * - * @file rdpdr_fs_messages_file_info.h + * @file rdpdr-fs-messages-file-info.h */ #include "config.h" diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.h index 46ccdab2..9f0d10aa 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.h @@ -25,7 +25,7 @@ * IRP_MJ_DIRECTORY_CONTROL major function and the IRP_MN_QUERY_DIRECTORY minor * function. * - * @file rdpdr_fs_messages_vol_info.h + * @file rdpdr-fs-messages-vol-info.h */ #include "config.h" diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.h index 74f3ccda..dd5454cc 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.h @@ -25,7 +25,7 @@ * messages handled directly, or more complex multi-type messages handled * elsewhere. * - * @file rdpdr_fs_messages.h + * @file rdpdr-fs-messages.h */ #include "config.h" diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h index 295a0225..ba2c5fa6 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h @@ -28,7 +28,7 @@ * system calls and structures, using the guac_rdpdr_device structure as a home * for common data. * - * @file rdpdr_fs.h + * @file rdpdr-fs.h */ #include "config.h" diff --git a/src/protocols/rdp/fs.h b/src/protocols/rdp/fs.h index 1f140bb8..1abd5e1a 100644 --- a/src/protocols/rdp/fs.h +++ b/src/protocols/rdp/fs.h @@ -28,7 +28,7 @@ * system calls and structures, using the guac_rdp_fs structure as a home * for common data. * - * @file rdp_fs.h + * @file fs.h */ #include "config.h" From 6c239a7b98d30cd0818228b1d886814246d468f3 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 27 Dec 2019 21:12:18 -0800 Subject: [PATCH 058/109] GUACAMOLE-249: Use filesystem constants defined by FreeRDP and WinPR headers rather than defining our own. --- .../rdp/channels/rdpdr/rdpdr-fs-messages.c | 5 +- src/protocols/rdp/channels/rdpdr/rdpdr.c | 2 +- src/protocols/rdp/fs.c | 28 ++++---- src/protocols/rdp/fs.h | 67 ++----------------- src/protocols/rdp/stream.c | 13 ++-- 5 files changed, 30 insertions(+), 85 deletions(-) diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c index bdf76f6c..c8113d1a 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c @@ -100,8 +100,7 @@ void guac_rdpdr_fs_process_create(guac_rdp_common_svc* svc, if (file != NULL && strcmp(file->absolute_path, "\\") == 0) { int download_id = guac_rdp_fs_open((guac_rdp_fs*) device->data, "\\Download", - ACCESS_GENERIC_READ, 0, - DISP_FILE_OPEN_IF, FILE_DIRECTORY_FILE); + GENERIC_READ, 0, FILE_OPEN_IF, FILE_DIRECTORY_FILE); if (download_id >= 0) guac_rdp_fs_close((guac_rdp_fs*) device->data, download_id); @@ -460,7 +459,7 @@ void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc, /* Open directory entry */ entry_file_id = guac_rdp_fs_open((guac_rdp_fs*) device->data, - entry_path, ACCESS_FILE_READ_DATA, 0, DISP_FILE_OPEN, 0); + entry_path, FILE_READ_DATA, 0, FILE_OPEN, 0); if (entry_file_id >= 0) { diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr.c b/src/protocols/rdp/channels/rdpdr/rdpdr.c index 10b594f6..39da918d 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr.c @@ -167,7 +167,7 @@ static void* guac_rdpdr_download_to_owner(guac_user* owner, void* data) { /* Attempt to open requested file */ char* path = (char*) data; int file_id = guac_rdp_fs_open(filesystem, path, - ACCESS_FILE_READ_DATA, 0, DISP_FILE_OPEN, 0); + FILE_READ_DATA, 0, FILE_OPEN, 0); /* If file opened successfully, start stream */ if (file_id >= 0) { diff --git a/src/protocols/rdp/fs.c b/src/protocols/rdp/fs.c index 0b39d836..7dd3ea7a 100644 --- a/src/protocols/rdp/fs.c +++ b/src/protocols/rdp/fs.c @@ -244,16 +244,16 @@ int guac_rdp_fs_open(guac_rdp_fs* fs, const char* path, } /* Translate access into flags */ - if (access & ACCESS_GENERIC_ALL) + if (access & GENERIC_ALL) flags = O_RDWR; - else if ((access & ( ACCESS_GENERIC_WRITE - | ACCESS_FILE_WRITE_DATA - | ACCESS_FILE_APPEND_DATA)) - && (access & (ACCESS_GENERIC_READ | ACCESS_FILE_READ_DATA))) + else if ((access & ( GENERIC_WRITE + | FILE_WRITE_DATA + | FILE_APPEND_DATA)) + && (access & (GENERIC_READ | FILE_READ_DATA))) flags = O_RDWR; - else if (access & ( ACCESS_GENERIC_WRITE - | ACCESS_FILE_WRITE_DATA - | ACCESS_FILE_APPEND_DATA)) + else if (access & ( GENERIC_WRITE + | FILE_WRITE_DATA + | FILE_APPEND_DATA)) flags = O_WRONLY; else flags = O_RDONLY; @@ -279,32 +279,32 @@ int guac_rdp_fs_open(guac_rdp_fs* fs, const char* path, switch (create_disposition) { /* Create if not exist, fail otherwise */ - case DISP_FILE_CREATE: + case FILE_CREATE: flags |= O_CREAT | O_EXCL; break; /* Open file if exists and do not overwrite, fail otherwise */ - case DISP_FILE_OPEN: + case FILE_OPEN: /* No flag necessary - default functionality of open */ break; /* Open if exists, create otherwise */ - case DISP_FILE_OPEN_IF: + case FILE_OPEN_IF: flags |= O_CREAT; break; /* Overwrite if exists, fail otherwise */ - case DISP_FILE_OVERWRITE: + case FILE_OVERWRITE: flags |= O_TRUNC; break; /* Overwrite if exists, create otherwise */ - case DISP_FILE_OVERWRITE_IF: + case FILE_OVERWRITE_IF: flags |= O_CREAT | O_TRUNC; break; /* Supersede (replace) if exists, otherwise create */ - case DISP_FILE_SUPERSEDE: + case FILE_SUPERSEDE: unlink(real_path); flags |= O_CREAT | O_TRUNC; break; diff --git a/src/protocols/rdp/fs.h b/src/protocols/rdp/fs.h index 1abd5e1a..681f5e76 100644 --- a/src/protocols/rdp/fs.h +++ b/src/protocols/rdp/fs.h @@ -108,59 +108,6 @@ */ #define GUAC_RDP_FS_ENOTSUP -10 -/* - * Access constants. - */ -#define ACCESS_GENERIC_READ 0x80000000 -#define ACCESS_GENERIC_WRITE 0x40000000 -#define ACCESS_GENERIC_ALL 0x10000000 -#define ACCESS_FILE_READ_DATA 0x00000001 -#define ACCESS_FILE_WRITE_DATA 0x00000002 -#define ACCESS_FILE_APPEND_DATA 0x00000004 -#define ACCESS_DELETE 0x00010000 - -/* - * Create disposition constants. - */ - -#define DISP_FILE_SUPERSEDE 0x00000000 -#define DISP_FILE_OPEN 0x00000001 -#define DISP_FILE_CREATE 0x00000002 -#define DISP_FILE_OPEN_IF 0x00000003 -#define DISP_FILE_OVERWRITE 0x00000004 -#define DISP_FILE_OVERWRITE_IF 0x00000005 - -/* - * File attributes. - */ - -#define FILE_ATTRIBUTE_READONLY 0x00000001 -#define FILE_ATTRIBUTE_HIDDEN 0x00000002 -#define FILE_ATTRIBUTE_DIRECTORY 0x00000010 -#define FILE_ATTRIBUTE_ARCHIVE 0x00000020 -#define FILE_ATTRIBUTE_NORMAL 0x00000080 - -/* - * Filesystem attributes. - */ - -#define FILE_CASE_SENSITIVE_SEARCH 0x00000001 -#define FILE_CASE_PRESERVED_NAMES 0x00000002 -#define FILE_UNICODE_ON_DISK 0x00000004 - -/* - * File create options. - */ - -#define FILE_DIRECTORY_FILE 0x00000001 -#define FILE_NON_DIRECTORY_FILE 0x00000040 - -/* - * File device types. - */ - -#define FILE_DEVICE_DISK 0x00000007 - #define SEC_TO_UNIX_EPOCH 11644473600 /** @@ -425,10 +372,10 @@ int guac_rdp_fs_get_status(int err); * The absolute path to the file within the simulated filesystem. * * @param access - * A bitwise-OR of various RDPDR access flags, such as ACCESS_GENERIC_ALL - * or ACCESS_GENERIC_WRITE. This value will ultimately be translated to a - * standard O_RDWR, O_WRONLY, etc. value when opening the real file on the - * local filesystem. + * A bitwise-OR of various RDPDR access flags, such as GENERIC_ALL or + * GENERIC_WRITE. This value will ultimately be translated to a standard + * O_RDWR, O_WRONLY, etc. value when opening the real file on the local + * filesystem. * * @param file_attributes * The attributes to apply to the file, if created. This parameter is @@ -436,9 +383,9 @@ int guac_rdp_fs_get_status(int err); * * @param create_disposition * Any one of several RDPDR file creation dispositions, such as - * DISP_FILE_CREATE, DISP_FILE_OPEN_IF, etc. The creation disposition - * dictates whether a new file should be created, whether the file can - * already exist, whether existing contents should be truncated, etc. + * FILE_CREATE, FILE_OPEN_IF, etc. The creation disposition dictates + * whether a new file should be created, whether the file can already + * exist, whether existing contents should be truncated, etc. * * @param create_options * A bitwise-OR of various RDPDR options dictating how a file is to be diff --git a/src/protocols/rdp/stream.c b/src/protocols/rdp/stream.c index 3e7bdfaa..21391a5b 100644 --- a/src/protocols/rdp/stream.c +++ b/src/protocols/rdp/stream.c @@ -90,8 +90,8 @@ int guac_rdp_upload_file_handler(guac_user* user, guac_stream* stream, __generate_upload_path(filename, file_path); /* Open file */ - file_id = guac_rdp_fs_open(fs, file_path, ACCESS_GENERIC_WRITE, 0, - DISP_FILE_OVERWRITE_IF, 0); + file_id = guac_rdp_fs_open(fs, file_path, GENERIC_WRITE, 0, + FILE_OVERWRITE_IF, 0); if (file_id < 0) { guac_protocol_send_ack(user->socket, stream, "FAIL (CANNOT OPEN)", GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN); @@ -293,7 +293,7 @@ int guac_rdp_ls_ack_handler(guac_user* user, guac_stream* stream, /* Attempt to open file to determine type */ int file_id = guac_rdp_fs_open(rdp_stream->ls_status.fs, absolute_path, - ACCESS_GENERIC_READ, 0, DISP_FILE_OPEN, 0); + GENERIC_READ, 0, FILE_OPEN, 0); if (file_id < 0) continue; @@ -359,8 +359,7 @@ int guac_rdp_download_get_handler(guac_user* user, guac_object* object, return 0; /* Attempt to open file for reading */ - int file_id = guac_rdp_fs_open(fs, name, ACCESS_GENERIC_READ, 0, - DISP_FILE_OPEN, 0); + int file_id = guac_rdp_fs_open(fs, name, GENERIC_READ, 0, FILE_OPEN, 0); if (file_id < 0) { guac_user_log(user, GUAC_LOG_INFO, "Unable to read file \"%s\"", name); @@ -442,8 +441,8 @@ int guac_rdp_upload_put_handler(guac_user* user, guac_object* object, } /* Open file */ - int file_id = guac_rdp_fs_open(fs, name, ACCESS_GENERIC_WRITE, 0, - DISP_FILE_OVERWRITE_IF, 0); + int file_id = guac_rdp_fs_open(fs, name, GENERIC_WRITE, 0, + FILE_OVERWRITE_IF, 0); /* Abort on failure */ if (file_id < 0) { From 12febd516215aad467643b21c3d1645a31adb286 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 27 Dec 2019 21:12:39 -0800 Subject: [PATCH 059/109] GUACAMOLE-249: Remove unused SEC_TO_UNIX_EPOCH constant. --- src/protocols/rdp/fs.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/protocols/rdp/fs.h b/src/protocols/rdp/fs.h index 681f5e76..168f2df1 100644 --- a/src/protocols/rdp/fs.h +++ b/src/protocols/rdp/fs.h @@ -108,8 +108,6 @@ */ #define GUAC_RDP_FS_ENOTSUP -10 -#define SEC_TO_UNIX_EPOCH 11644473600 - /** * Converts a Windows timestamp (100 nanosecond intervals since Jan 1, 1601 * UTC) to UNIX timestamp (seconds since Jan 1, 1970 UTC). From ab0550249438e1a518cf20c01dddef6285563dae Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 27 Dec 2019 23:22:55 -0800 Subject: [PATCH 060/109] GUACAMOLE-249: Correct missing/incorrect documentation for RDP callback parameters. --- src/protocols/rdp/channels/cliprdr.h | 2 +- src/protocols/rdp/channels/common-svc.h | 2 +- src/protocols/rdp/channels/disp.h | 6 ++-- src/protocols/rdp/channels/pipe-svc.h | 2 +- src/protocols/rdp/channels/rail.h | 2 +- src/protocols/rdp/channels/rdpdr/rdpdr-fs.h | 4 +-- .../rdp/channels/rdpdr/rdpdr-printer.h | 4 +-- src/protocols/rdp/channels/rdpdr/rdpdr.h | 2 +- src/protocols/rdp/channels/rdpsnd/rdpsnd.h | 2 +- src/protocols/rdp/glyph.h | 32 +++++++++++++++++++ 10 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/protocols/rdp/channels/cliprdr.h b/src/protocols/rdp/channels/cliprdr.h index 42cfddec..e9b7c9a0 100644 --- a/src/protocols/rdp/channels/cliprdr.h +++ b/src/protocols/rdp/channels/cliprdr.h @@ -87,7 +87,7 @@ guac_rdp_clipboard* guac_rdp_clipboard_alloc(guac_client* client); * The guac_rdp_clipboard instance which has been allocated for the current * RDP connection. * - * @param rdpContext + * @param context * The rdpContext associated with the FreeRDP side of the RDP connection. */ void guac_rdp_clipboard_load_plugin(guac_rdp_clipboard* clipboard, diff --git a/src/protocols/rdp/channels/common-svc.h b/src/protocols/rdp/channels/common-svc.h index 3be2c006..82a9a63d 100644 --- a/src/protocols/rdp/channels/common-svc.h +++ b/src/protocols/rdp/channels/common-svc.h @@ -177,7 +177,7 @@ struct guac_rdp_common_svc { * This MUST be called within the PreConnect callback of the freerdp instance * for static virtual channel support to be loaded. * - * @param rdpContext + * @param context * The rdpContext associated with the FreeRDP side of the RDP connection. * * @param name diff --git a/src/protocols/rdp/channels/disp.h b/src/protocols/rdp/channels/disp.h index 650f7ad8..2aff7c2d 100644 --- a/src/protocols/rdp/channels/disp.h +++ b/src/protocols/rdp/channels/disp.h @@ -186,9 +186,9 @@ void guac_rdp_disp_reconnect_complete(guac_rdp_disp* disp); * Returns whether a full RDP reconnect is required for display update changes * to take effect. * - * @param client - * The guac_client associated with the Guacamole side of the RDP - * connection. + * @param disp + * The display update module that should be checked to determine whether a + * reconnect is required. * * @return * Non-zero if a reconnect is needed, zero otherwise. diff --git a/src/protocols/rdp/channels/pipe-svc.h b/src/protocols/rdp/channels/pipe-svc.h index f75cebbf..6ab43f96 100644 --- a/src/protocols/rdp/channels/pipe-svc.h +++ b/src/protocols/rdp/channels/pipe-svc.h @@ -69,7 +69,7 @@ typedef struct guac_rdp_pipe_svc { * This MUST be called within the PreConnect callback of the freerdp instance * for static virtual channel support to be loaded. * - * @param rdpContext + * @param context * The rdpContext associated with the FreeRDP side of the RDP connection. * * @param name diff --git a/src/protocols/rdp/channels/rail.h b/src/protocols/rdp/channels/rail.h index cb5e0891..9b0d231a 100644 --- a/src/protocols/rdp/channels/rail.h +++ b/src/protocols/rdp/channels/rail.h @@ -32,7 +32,7 @@ * This MUST be called within the PreConnect callback of the freerdp instance * for RAIL support to be loaded. * - * @param rdpContext + * @param context * The rdpContext associated with the FreeRDP side of the RDP connection. */ void guac_rdp_rail_load_plugin(rdpContext* context); diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h index ba2c5fa6..ab8a13db 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h @@ -40,8 +40,8 @@ * Registers a new filesystem device within the RDPDR plugin. This must be done * before RDPDR connection finishes. * - * @param rdpdr - * The RDP device redirection plugin with which to register the device. + * @param svc + * The static virtual channel instance being used for RDPDR. * * @param drive_name * The name of the redirected drive to display in the RDP connection. diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-printer.h b/src/protocols/rdp/channels/rdpdr/rdpdr-printer.h index 3e0df55d..0addc6fb 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-printer.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-printer.h @@ -29,8 +29,8 @@ * Registers a new printer device within the RDPDR plugin. This must be done * before RDPDR connection finishes. * - * @param rdpdr - * The RDP device redirection plugin where the device is registered. + * @param svc + * The static virtual channel instance being used for RDPDR. * * @param printer_name * The name of the printer that will be registered with the RDP diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr.h b/src/protocols/rdp/channels/rdpdr/rdpdr.h index fa25f3d2..f75df0f0 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr.h @@ -146,7 +146,7 @@ void guac_rdpdr_start_download(guac_rdp_common_svc* svc, * This MUST be called within the PreConnect callback of the freerdp instance * for RDPDR support to be loaded. * - * @param rdpContext + * @param context * The rdpContext associated with the FreeRDP side of the RDP connection. */ void guac_rdpdr_load_plugin(rdpContext* context); diff --git a/src/protocols/rdp/channels/rdpsnd/rdpsnd.h b/src/protocols/rdp/channels/rdpsnd/rdpsnd.h index 014d04d8..97b6085f 100644 --- a/src/protocols/rdp/channels/rdpsnd/rdpsnd.h +++ b/src/protocols/rdp/channels/rdpsnd/rdpsnd.h @@ -113,7 +113,7 @@ typedef struct guac_rdpsnd { * This MUST be called within the PreConnect callback of the freerdp instance * for RDPSND support to be loaded. * - * @param rdpContext + * @param context * The rdpContext associated with the FreeRDP side of the RDP connection. */ void guac_rdpsnd_load_plugin(rdpContext* context); diff --git a/src/protocols/rdp/glyph.h b/src/protocols/rdp/glyph.h index fa824e66..0d4bf7b0 100644 --- a/src/protocols/rdp/glyph.h +++ b/src/protocols/rdp/glyph.h @@ -52,6 +52,9 @@ typedef struct guac_rdp_glyph { * * @param glyph * The glyph to cache. + * + * @return + * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_glyph_new(rdpContext* context, const rdpGlyph* glyph); @@ -70,6 +73,26 @@ BOOL guac_rdp_glyph_new(rdpContext* context, const rdpGlyph* glyph); * * @param y * The destination Y coordinate of the upper-left corner of the glyph. + * + * @param w + * The width of the glyph being drawn. + * + * @param h + * The height of the glyph being drawn. + * + * @param sx + * The X coordinare of the upper-left corner of the glyph within the source + * cache surface containing the glyph. + * + * @param sy + * The Y coordinare of the upper-left corner of the glyph within the source + * cache surface containing the glyph. + * + * @param redundant + * Whether the background rectangle specified is redundant (transparent). + * + * @return + * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_glyph_draw(rdpContext* context, const rdpGlyph* glyph, INT32 x, INT32 y, INT32 w, INT32 h, INT32 sx, INT32 sy, @@ -121,6 +144,12 @@ void guac_rdp_glyph_free(rdpContext* context, rdpGlyph* glyph); * colorspace of the RDP session, and may even be a palette index, and must * be translated via guac_rdp_convert_color(). If the background is * transparent, this value is undefined. + * + * @param redundant + * Whether the background rectangle specified is redundant (transparent). + * + * @return + * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_glyph_begindraw(rdpContext* context, INT32 x, INT32 y, INT32 width, INT32 height, UINT32 fgcolor, UINT32 bgcolor, @@ -159,6 +188,9 @@ BOOL guac_rdp_glyph_begindraw(rdpContext* context, INT32 x, INT32 y, * colorspace of the RDP session, and may even be a palette index, and must * be translated via guac_rdp_convert_color(). If the background is * transparent, this value is undefined. + * + * @return + * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_glyph_enddraw(rdpContext* context, INT32 x, INT32 y, INT32 width, INT32 height, UINT32 fgcolor, UINT32 bgcolor); From fbb759ab820fe31a69aad8ccd0caed3a93d40932 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 28 Dec 2019 12:01:44 -0800 Subject: [PATCH 061/109] GUACAMOLE-249: Correct mismatched ifndef/define header include check. --- src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h index 25f745b5..8bb4ac68 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h @@ -18,7 +18,7 @@ */ #ifndef GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_DIR_INFO_H -#define RDP_CHANNELS_GUAC_RDPDR_FS_MESSAGES_DIR_INFO_H +#define GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_DIR_INFO_H /** * Handlers for directory queries received over the RDPDR channel via the From a54c61e860d3a1324ea6c30ba2c53525fec74c81 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 28 Dec 2019 12:23:08 -0800 Subject: [PATCH 062/109] GUACAMOLE-249: Support for OpaqueRect MUST NOT be claimed without supporting PatBlt. OpaqueRect implies PatBlt and vice versa. --- src/protocols/rdp/settings.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/protocols/rdp/settings.c b/src/protocols/rdp/settings.c index 861a2994..3942b370 100644 --- a/src/protocols/rdp/settings.c +++ b/src/protocols/rdp/settings.c @@ -1320,9 +1320,9 @@ void guac_rdp_push_settings(guac_client* client, rdp_settings->OsMinorType = OSMINORTYPE_UNSPECIFIED; rdp_settings->DesktopResize = TRUE; rdp_settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE; - rdp_settings->OrderSupport[NEG_PATBLT_INDEX] = FALSE; /* PATBLT not yet supported */ + rdp_settings->OrderSupport[NEG_PATBLT_INDEX] = FALSE; /* PATBLT not implemented */ rdp_settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE; - rdp_settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE; + rdp_settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] = FALSE; /* PATBLT not implemented, and OPAQUE_RECT implies PATBLT */ rdp_settings->OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE; rdp_settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE; rdp_settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE; From 36545cc92cf61dc9664b9df33f6020b8db08d8ad Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 28 Dec 2019 12:29:09 -0800 Subject: [PATCH 063/109] GUACAMOLE-249: Document absolutely all parameters and return types for RDP support. --- src/protocols/rdp/bitmap.h | 12 ++++ src/protocols/rdp/gdi.h | 56 +++++++++++++++++-- .../rdp/plugins/guacai/guacai-messages.c | 15 ++++- .../rdp/plugins/guacai/guacai-messages.h | 9 +++ src/protocols/rdp/pointer.h | 12 ++++ src/protocols/rdp/print-job.h | 3 + src/protocols/rdp/stream.c | 7 +++ 7 files changed, 108 insertions(+), 6 deletions(-) diff --git a/src/protocols/rdp/bitmap.h b/src/protocols/rdp/bitmap.h index 6ccd04f4..70068b56 100644 --- a/src/protocols/rdp/bitmap.h +++ b/src/protocols/rdp/bitmap.h @@ -60,6 +60,9 @@ typedef struct guac_rdp_bitmap { * * @param bitmap * The bitmap to cache. + * + * @return + * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap); @@ -71,6 +74,9 @@ BOOL guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap); * * @param bitmap * The bitmap to initialize. + * + * @return + * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap); @@ -86,6 +92,9 @@ BOOL guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap); * The bitmap to paint. This structure will also contain the specifics of * the paint operation to perform, including the destination X/Y * coordinates. + * + * @return + * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_bitmap_paint(rdpContext* context, rdpBitmap* bitmap); @@ -116,6 +125,9 @@ void guac_rdp_bitmap_free(rdpContext* context, rdpBitmap* bitmap); * TRUE if the bitmap parameter should be ignored, and the current drawing * surface should be reset to the primary drawing surface of the remote * display, FALSE otherwise. + * + * @return + * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_bitmap_setsurface(rdpContext* context, rdpBitmap* bitmap, BOOL primary); diff --git a/src/protocols/rdp/gdi.h b/src/protocols/rdp/gdi.h index 983a6e6a..006e61ed 100644 --- a/src/protocols/rdp/gdi.h +++ b/src/protocols/rdp/gdi.h @@ -45,57 +45,94 @@ guac_composite_mode guac_rdp_rop3_transfer_function(guac_client* client, int rop3); /** - * Handler for RDP DSTBLT update. + * Handler for the DstBlt Primary Drawing Order. A DstBlt Primary Drawing Order + * paints a rectangle of image data using a raster operation which considers + * the destination only. See: + * + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpegdi/87ea30df-59d6-438e-a735-83f0225fbf91 * * @param context * The rdpContext associated with the current RDP session. * * @param dstblt * The DSTBLT update to handle. + * + * @return + * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_gdi_dstblt(rdpContext* context, const DSTBLT_ORDER* dstblt); /** - * Handler for RDP PATBLT update. + * Handler for the PatBlt Primary Drawing Order. A PatBlt Primary Drawing Order + * paints a rectangle of image data, a brush pattern, and a three-way raster + * operation which considers the source data, the destination, AND the brush + * pattern. See: + * + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpegdi/bd4bf5e7-b988-45f9-8201-3b22cc9aeeb8 * * @param context * The rdpContext associated with the current RDP session. * * @param patblt * The PATBLT update to handle. + * + * @return + * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt); /** - * Handler for RDP SCRBLT update. + * Handler for the ScrBlt Primary Drawing Order. A ScrBlt Primary Drawing Order + * paints a rectangle of image data using a raster operation which considers + * the source and destination. See: + * + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpegdi/a4e322b0-cd64-4dfc-8e1a-f24dc0edc99d * * @param context * The rdpContext associated with the current RDP session. * * @param scrblt * The SCRBLT update to handle. + * + * @return + * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_gdi_scrblt(rdpContext* context, const SCRBLT_ORDER* scrblt); /** - * Handler for RDP MEMBLT update. + * Handler for the MemBlt Primary Drawing Order. A MemBlt Primary Drawing Order + * paints a rectangle of cached image data from a cached surface to the screen + * using a raster operation which considers the source and destination. See: + * + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpegdi/84c2ec2f-f776-405b-9b48-6894a28b1b14 * * @param context * The rdpContext associated with the current RDP session. * * @param memblt * The MEMBLT update to handle. + * + * @return + * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt); /** - * Handler for RDP OPAQUE RECT update. + * Handler for the OpaqueRect Primary Drawing Order. An OpaqueRect Primary + * Drawing Order draws an opaque rectangle of a single solid color. Note that + * support for OpaqueRect cannot be claimed without also supporting PatBlt, as + * both use the same negotiation order number. See: + * + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpegdi/1eead7aa-ac63-411a-9f8c-b1b227526877 * * @param context * The rdpContext associated with the current RDP session. * * @param opaque_rect * The OPAQUE RECT update to handle. + * + * @return + * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_gdi_opaquerect(rdpContext* context, const OPAQUE_RECT_ORDER* opaque_rect); @@ -112,6 +149,9 @@ BOOL guac_rdp_gdi_opaquerect(rdpContext* context, * @param bounds * The clipping rectangle to set, or NULL to remove any applied clipping * rectangle. + * + * @return + * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_gdi_set_bounds(rdpContext* context, const rdpBounds* bounds); @@ -121,6 +161,9 @@ BOOL guac_rdp_gdi_set_bounds(rdpContext* context, const rdpBounds* bounds); * * @param context * The rdpContext associated with the current RDP session. + * + * @return + * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_gdi_end_paint(rdpContext* context); @@ -135,6 +178,9 @@ BOOL guac_rdp_gdi_end_paint(rdpContext* context); * * @param context * The rdpContext associated with the current RDP session. + * + * @return + * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_gdi_desktop_resize(rdpContext* context); diff --git a/src/protocols/rdp/plugins/guacai/guacai-messages.c b/src/protocols/rdp/plugins/guacai/guacai-messages.c index 083d7ae3..bb759e56 100644 --- a/src/protocols/rdp/plugins/guacai/guacai-messages.c +++ b/src/protocols/rdp/plugins/guacai/guacai-messages.c @@ -107,6 +107,19 @@ static void guac_rdp_ai_send_incoming_data(IWTSVirtualChannel* channel) { } +/** + * Sends a Data PDU along the given channel. A Data PDU is used by the client + * to send actual audio data following a Data Incoming PDU. + * + * @param channel + * The channel along which the PDU should be sent. + * + * @param buffer + * The audio data to send. + * + * @param length + * The number of bytes of audio data to send. + */ static void guac_rdp_ai_send_data(IWTSVirtualChannel* channel, char* buffer, int length) { @@ -280,7 +293,7 @@ void guac_rdp_ai_process_formats(guac_client* client, } -static void guac_rdp_ai_flush_packet(char* buffer, int length, void* data) { +void guac_rdp_ai_flush_packet(char* buffer, int length, void* data) { IWTSVirtualChannel* channel = (IWTSVirtualChannel*) data; diff --git a/src/protocols/rdp/plugins/guacai/guacai-messages.h b/src/protocols/rdp/plugins/guacai/guacai-messages.h index a2d35050..91173c3d 100644 --- a/src/protocols/rdp/plugins/guacai/guacai-messages.h +++ b/src/protocols/rdp/plugins/guacai/guacai-messages.h @@ -207,5 +207,14 @@ void guac_rdp_ai_process_open(guac_client* client, void guac_rdp_ai_process_formatchange(guac_client* client, IWTSVirtualChannel* channel, wStream* stream); +/** + * Audio buffer flush handler which sends audio data along the active audio + * input channel using a Data Incoming PDU and Data PDU. The arbitrary data + * provided to the handler by the audio buffer implementation is in this case + * the IWTSVirtualChannel structure representing the active audio input + * channel. + */ +guac_rdp_audio_buffer_flush_handler guac_rdp_ai_flush_packet; + #endif diff --git a/src/protocols/rdp/pointer.h b/src/protocols/rdp/pointer.h index 7f4547b7..c5ba319f 100644 --- a/src/protocols/rdp/pointer.h +++ b/src/protocols/rdp/pointer.h @@ -51,6 +51,9 @@ typedef struct guac_rdp_pointer { * * @param pointer * The pointer to cache. + * + * @return + * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_pointer_new(rdpContext* context, rdpPointer* pointer); @@ -63,6 +66,9 @@ BOOL guac_rdp_pointer_new(rdpContext* context, rdpPointer* pointer); * * @param pointer * The pointer to set as the current mouse pointer. + * + * @return + * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_pointer_set(rdpContext* context, const rdpPointer* pointer); @@ -83,6 +89,9 @@ void guac_rdp_pointer_free(rdpContext* context, rdpPointer* pointer); * * @param context * The rdpContext associated with the current RDP session. + * + * @return + * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_pointer_set_null(rdpContext* context); @@ -92,6 +101,9 @@ BOOL guac_rdp_pointer_set_null(rdpContext* context); * * @param context * The rdpContext associated with the current RDP session. + * + * @return + * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_pointer_set_default(rdpContext* context); diff --git a/src/protocols/rdp/print-job.h b/src/protocols/rdp/print-job.h index 5682f186..98897ec1 100644 --- a/src/protocols/rdp/print-job.h +++ b/src/protocols/rdp/print-job.h @@ -79,6 +79,9 @@ typedef enum guac_rdp_print_job_state { */ typedef struct guac_rdp_print_job { + /** + * The Guacamole client associated with the RDP session. + */ guac_client* client; /** diff --git a/src/protocols/rdp/stream.c b/src/protocols/rdp/stream.c index 21391a5b..71fd0357 100644 --- a/src/protocols/rdp/stream.c +++ b/src/protocols/rdp/stream.c @@ -39,6 +39,13 @@ /** * Writes the given filename to the given upload path, sanitizing the filename * and translating the filename to the root directory. + * + * @param filename + * The filename to sanitize and move to the root directory. + * + * @param path + * A pointer to a buffer which should receive the sanitized path. The + * buffer must hav at least GUAC_RDP_FS_MAX_PATH bytes available. */ static void __generate_upload_path(const char* filename, char* path) { From d2083a1aed38008cb8d01e465bb035449f0547ca Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 29 Dec 2019 18:04:27 -0800 Subject: [PATCH 064/109] GUACAMOLE-249: Refactor RDPDR to be more documentable. Document RDPDR fully. --- .../rdpdr/rdpdr-fs-messages-dir-info.c | 53 ++--- .../rdpdr/rdpdr-fs-messages-dir-info.h | 44 +++-- .../rdpdr/rdpdr-fs-messages-file-info.c | 124 ++++++------ .../rdpdr/rdpdr-fs-messages-file-info.h | 64 ++++--- .../rdpdr/rdpdr-fs-messages-vol-info.c | 57 +++--- .../rdpdr/rdpdr-fs-messages-vol-info.h | 20 +- .../rdp/channels/rdpdr/rdpdr-fs-messages.c | 181 ++++++++---------- .../rdp/channels/rdpdr/rdpdr-fs-messages.h | 49 ++--- src/protocols/rdp/channels/rdpdr/rdpdr-fs.c | 54 +++--- src/protocols/rdp/channels/rdpdr/rdpdr-fs.h | 10 + .../rdp/channels/rdpdr/rdpdr-messages.c | 81 ++++++-- .../rdp/channels/rdpdr/rdpdr-messages.h | 105 ++++++++-- .../rdp/channels/rdpdr/rdpdr-printer.c | 40 ++-- .../rdp/channels/rdpdr/rdpdr-printer.h | 39 ++++ src/protocols/rdp/channels/rdpdr/rdpdr.h | 97 +++++++++- 15 files changed, 625 insertions(+), 393 deletions(-) diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.c index 256ac14a..25d355f5 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.c @@ -18,6 +18,7 @@ */ #include "config.h" +#include "channels/rdpdr/rdpdr-fs-messages-dir-info.h" #include "channels/rdpdr/rdpdr.h" #include "fs.h" #include "unicode.h" @@ -29,8 +30,8 @@ #include void guac_rdpdr_fs_process_query_directory_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, const char* entry_name, int file_id, - int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + const char* entry_name, int entry_file_id) { guac_rdp_fs_file* file; @@ -43,16 +44,17 @@ void guac_rdpdr_fs_process_query_directory_info(guac_rdp_common_svc* svc, (char*) utf16_entry_name, sizeof(utf16_entry_name)); /* Get file */ - file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id); + file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, entry_file_id); if (file == NULL) return; guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i (entry_name=\"%s\")]", - __func__, file_id, entry_name); + __func__, entry_file_id, entry_name); - output_stream = guac_rdpdr_new_io_completion(device, completion_id, - STATUS_SUCCESS, 4 + 64 + utf16_length + 2); + output_stream = guac_rdpdr_new_io_completion(device, + iorequest->completion_id, STATUS_SUCCESS, + 4 + 64 + utf16_length + 2); Stream_Write_UINT32(output_stream, 64 + utf16_length + 2); /* Length */ @@ -76,8 +78,8 @@ void guac_rdpdr_fs_process_query_directory_info(guac_rdp_common_svc* svc, } void guac_rdpdr_fs_process_query_full_directory_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, const char* entry_name, int file_id, - int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + const char* entry_name, int entry_file_id) { guac_rdp_fs_file* file; @@ -90,16 +92,17 @@ void guac_rdpdr_fs_process_query_full_directory_info(guac_rdp_common_svc* svc, (char*) utf16_entry_name, sizeof(utf16_entry_name)); /* Get file */ - file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id); + file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, entry_file_id); if (file == NULL) return; guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i (entry_name=\"%s\")]", - __func__, file_id, entry_name); + __func__, entry_file_id, entry_name); - output_stream = guac_rdpdr_new_io_completion(device, completion_id, - STATUS_SUCCESS, 4 + 68 + utf16_length + 2); + output_stream = guac_rdpdr_new_io_completion(device, + iorequest->completion_id, STATUS_SUCCESS, + 4 + 68 + utf16_length + 2); Stream_Write_UINT32(output_stream, 68 + utf16_length + 2); /* Length */ @@ -124,8 +127,8 @@ void guac_rdpdr_fs_process_query_full_directory_info(guac_rdp_common_svc* svc, } void guac_rdpdr_fs_process_query_both_directory_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, const char* entry_name, int file_id, - int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + const char* entry_name, int entry_file_id) { guac_rdp_fs_file* file; @@ -138,16 +141,17 @@ void guac_rdpdr_fs_process_query_both_directory_info(guac_rdp_common_svc* svc, (char*) utf16_entry_name, sizeof(utf16_entry_name)); /* Get file */ - file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id); + file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, entry_file_id); if (file == NULL) return; guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i (entry_name=\"%s\")]", - __func__, file_id, entry_name); + __func__, entry_file_id, entry_name); - output_stream = guac_rdpdr_new_io_completion(device, completion_id, - STATUS_SUCCESS, 4 + 69 + 24 + utf16_length + 2); + output_stream = guac_rdpdr_new_io_completion(device, + iorequest->completion_id, STATUS_SUCCESS, + 4 + 69 + 24 + utf16_length + 2); Stream_Write_UINT32(output_stream, 69 + 24 + utf16_length + 2); /* Length */ @@ -176,8 +180,8 @@ void guac_rdpdr_fs_process_query_both_directory_info(guac_rdp_common_svc* svc, } void guac_rdpdr_fs_process_query_names_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, const char* entry_name, int file_id, - int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + const char* entry_name, int entry_file_id) { guac_rdp_fs_file* file; @@ -190,16 +194,17 @@ void guac_rdpdr_fs_process_query_names_info(guac_rdp_common_svc* svc, (char*) utf16_entry_name, sizeof(utf16_entry_name)); /* Get file */ - file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id); + file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, entry_file_id); if (file == NULL) return; guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i (entry_name=\"%s\")]", - __func__, file_id, entry_name); + __func__, entry_file_id, entry_name); - output_stream = guac_rdpdr_new_io_completion(device, completion_id, - STATUS_SUCCESS, 4 + 12 + utf16_length + 2); + output_stream = guac_rdpdr_new_io_completion(device, + iorequest->completion_id, STATUS_SUCCESS, + 4 + 12 + utf16_length + 2); Stream_Write_UINT32(output_stream, 12 + utf16_length + 2); /* Length */ diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h index 8bb4ac68..c4b0f8ad 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h @@ -34,40 +34,60 @@ #include +/** + * Handler for Device I/O Requests which query information about the files + * within a directory. + * + * @param svc + * The guac_rdp_common_svc representing the static virtual channel being + * used for RDPDR. + * + * @param device + * The guac_rdpdr_device of the relevant device, as dictated by the + * deviceId field of common RDPDR header within the received PDU. Within + * the guac_rdpdr_iorequest structure, the deviceId field is stored within + * device_id. + * + * @param iorequest + * The contents of the common RDPDR Device I/O Request header shared by all + * RDPDR devices. + * + * @param entry_name + * The filename of the file being queried. + * + * @param entry_file_id + * The ID of the file being queried. + */ +typedef void guac_rdpdr_directory_query_handler(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + const char* entry_name, int entry_file_id); + /** * Processes a query request for FileDirectoryInformation. From the * documentation this is "defined as the file's name, time stamp, and size, or its * attributes." */ -void guac_rdpdr_fs_process_query_directory_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, const char* entry_name, int file_id, - int completion_id); +guac_rdpdr_directory_query_handler guac_rdpdr_fs_process_query_directory_info; /** * Processes a query request for FileFullDirectoryInformation. From the * documentation, this is "defined as all the basic information, plus extended * attribute size." */ -void guac_rdpdr_fs_process_query_full_directory_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, const char* entry_name, int file_id, - int completion_id); +guac_rdpdr_directory_query_handler guac_rdpdr_fs_process_query_full_directory_info; /** * Processes a query request for FileBothDirectoryInformation. From the * documentation, this absurdly-named request is "basic information plus * extended attribute size and short name about a file or directory." */ -void guac_rdpdr_fs_process_query_both_directory_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, const char* entry_name, int file_id, - int completion_id); +guac_rdpdr_directory_query_handler guac_rdpdr_fs_process_query_both_directory_info; /** * Processes a query request for FileNamesInformation. From the documentation, * this is "detailed information on the names of files in a directory." */ -void guac_rdpdr_fs_process_query_names_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, const char* entry_name, int file_id, - int completion_id); +guac_rdpdr_directory_query_handler guac_rdpdr_fs_process_query_names_info; #endif diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.c index 4629ca59..509087b8 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.c @@ -18,6 +18,7 @@ */ #include "config.h" +#include "channels/rdpdr/rdpdr-fs-messages-file-info.h" #include "channels/rdpdr/rdpdr.h" #include "fs.h" #include "unicode.h" @@ -31,23 +32,22 @@ #include void guac_rdpdr_fs_process_query_basic_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { wStream* output_stream; guac_rdp_fs_file* file; /* Get file */ - file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id); + file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id); if (file == NULL) return; - guac_client_log(svc->client, GUAC_LOG_DEBUG, - "%s: [file_id=%i]", - __func__, file_id); + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, + iorequest->file_id); - output_stream = guac_rdpdr_new_io_completion(device, completion_id, - STATUS_SUCCESS, 40); + output_stream = guac_rdpdr_new_io_completion(device, + iorequest->completion_id, STATUS_SUCCESS, 40); Stream_Write_UINT32(output_stream, 36); Stream_Write_UINT64(output_stream, file->ctime); /* CreationTime */ @@ -63,27 +63,26 @@ void guac_rdpdr_fs_process_query_basic_info(guac_rdp_common_svc* svc, } void guac_rdpdr_fs_process_query_standard_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { wStream* output_stream; guac_rdp_fs_file* file; BOOL is_directory = FALSE; /* Get file */ - file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id); + file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id); if (file == NULL) return; - guac_client_log(svc->client, GUAC_LOG_DEBUG, - "%s: [file_id=%i]", - __func__, file_id); + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, + iorequest->file_id); if (file->attributes & FILE_ATTRIBUTE_DIRECTORY) is_directory = TRUE; - output_stream = guac_rdpdr_new_io_completion(device, completion_id, - STATUS_SUCCESS, 26); + output_stream = guac_rdpdr_new_io_completion(device, + iorequest->completion_id, STATUS_SUCCESS, 26); Stream_Write_UINT32(output_stream, 22); Stream_Write_UINT64(output_stream, file->size); /* AllocationSize */ @@ -99,23 +98,22 @@ void guac_rdpdr_fs_process_query_standard_info(guac_rdp_common_svc* svc, } void guac_rdpdr_fs_process_query_attribute_tag_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { wStream* output_stream; guac_rdp_fs_file* file; /* Get file */ - file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id); + file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id); if (file == NULL) return; - guac_client_log(svc->client, GUAC_LOG_DEBUG, - "%s: [file_id=%i]", - __func__, file_id); + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, + iorequest->file_id); - output_stream = guac_rdpdr_new_io_completion(device, completion_id, - STATUS_SUCCESS, 12); + output_stream = guac_rdpdr_new_io_completion(device, + iorequest->completion_id, STATUS_SUCCESS, 12); Stream_Write_UINT32(output_stream, 8); Stream_Write_UINT32(output_stream, file->attributes); /* FileAttributes */ @@ -128,8 +126,8 @@ void guac_rdpdr_fs_process_query_attribute_tag_info(guac_rdp_common_svc* svc, } void guac_rdpdr_fs_process_set_rename_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id, int length) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + int length, wStream* input_stream) { int result; int filename_length; @@ -145,9 +143,9 @@ void guac_rdpdr_fs_process_set_rename_info(guac_rdp_common_svc* svc, guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), filename_length/2, destination_path, sizeof(destination_path)); - guac_client_log(svc->client, GUAC_LOG_DEBUG, - "%s: [file_id=%i] destination_path=\"%s\"", - __func__, file_id, destination_path); + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]" + "destination_path=\"%s\"", __func__, iorequest->file_id, + destination_path); /* If file moving to \Download folder, start stream, do not move */ if (strncmp(destination_path, "\\Download\\", 10) == 0) { @@ -155,28 +153,28 @@ void guac_rdpdr_fs_process_set_rename_info(guac_rdp_common_svc* svc, guac_rdp_fs_file* file; /* Get file */ - file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id); + file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id); if (file == NULL) return; /* Initiate download, pretend move succeeded */ guac_rdpdr_start_download(svc, device, file->absolute_path); output_stream = guac_rdpdr_new_io_completion(device, - completion_id, STATUS_SUCCESS, 4); + iorequest->completion_id, STATUS_SUCCESS, 4); } /* Otherwise, rename as requested */ else { - result = guac_rdp_fs_rename((guac_rdp_fs*) device->data, file_id, - destination_path); + result = guac_rdp_fs_rename((guac_rdp_fs*) device->data, + iorequest->file_id, destination_path); if (result < 0) output_stream = guac_rdpdr_new_io_completion(device, - completion_id, guac_rdp_fs_get_status(result), 4); + iorequest->completion_id, guac_rdp_fs_get_status(result), 4); else output_stream = guac_rdpdr_new_io_completion(device, - completion_id, STATUS_SUCCESS, 4); + iorequest->completion_id, STATUS_SUCCESS, 4); } @@ -186,8 +184,8 @@ void guac_rdpdr_fs_process_set_rename_info(guac_rdp_common_svc* svc, } void guac_rdpdr_fs_process_set_allocation_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id, int length) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + int length, wStream* input_stream) { int result; UINT64 size; @@ -196,18 +194,17 @@ void guac_rdpdr_fs_process_set_allocation_info(guac_rdp_common_svc* svc, /* Read new size */ Stream_Read_UINT64(input_stream, size); /* AllocationSize */ - guac_client_log(svc->client, GUAC_LOG_DEBUG, - "%s: [file_id=%i] size=%" PRIu64, - __func__, file_id, (uint64_t) size); + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] " + "size=%" PRIu64, __func__, iorequest->file_id, (uint64_t) size); /* Truncate file */ - result = guac_rdp_fs_truncate((guac_rdp_fs*) device->data, file_id, size); + result = guac_rdp_fs_truncate((guac_rdp_fs*) device->data, iorequest->file_id, size); if (result < 0) output_stream = guac_rdpdr_new_io_completion(device, - completion_id, guac_rdp_fs_get_status(result), 4); + iorequest->completion_id, guac_rdp_fs_get_status(result), 4); else output_stream = guac_rdpdr_new_io_completion(device, - completion_id, STATUS_SUCCESS, 4); + iorequest->completion_id, STATUS_SUCCESS, 4); Stream_Write_UINT32(output_stream, length); guac_rdp_common_svc_write(svc, output_stream); @@ -215,23 +212,22 @@ void guac_rdpdr_fs_process_set_allocation_info(guac_rdp_common_svc* svc, } void guac_rdpdr_fs_process_set_disposition_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id, int length) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + int length, wStream* input_stream) { wStream* output_stream; /* Delete file */ - int result = guac_rdp_fs_delete((guac_rdp_fs*) device->data, file_id); + int result = guac_rdp_fs_delete((guac_rdp_fs*) device->data, iorequest->file_id); if (result < 0) output_stream = guac_rdpdr_new_io_completion(device, - completion_id, guac_rdp_fs_get_status(result), 4); + iorequest->completion_id, guac_rdp_fs_get_status(result), 4); else output_stream = guac_rdpdr_new_io_completion(device, - completion_id, STATUS_SUCCESS, 4); + iorequest->completion_id, STATUS_SUCCESS, 4); - guac_client_log(svc->client, GUAC_LOG_DEBUG, - "%s: [file_id=%i]", - __func__, file_id); + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, + iorequest->file_id); Stream_Write_UINT32(output_stream, length); @@ -240,8 +236,8 @@ void guac_rdpdr_fs_process_set_disposition_info(guac_rdp_common_svc* svc, } void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id, int length) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + int length, wStream* input_stream) { int result; UINT64 size; @@ -250,18 +246,17 @@ void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdp_common_svc* svc, /* Read new size */ Stream_Read_UINT64(input_stream, size); /* AllocationSize */ - guac_client_log(svc->client, GUAC_LOG_DEBUG, - "%s: [file_id=%i] size=%" PRIu64, - __func__, file_id, (uint64_t) size); + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] " + "size=%" PRIu64, __func__, iorequest->file_id, (uint64_t) size); /* Truncate file */ - result = guac_rdp_fs_truncate((guac_rdp_fs*) device->data, file_id, size); + result = guac_rdp_fs_truncate((guac_rdp_fs*) device->data, iorequest->file_id, size); if (result < 0) output_stream = guac_rdpdr_new_io_completion(device, - completion_id, guac_rdp_fs_get_status(result), 4); + iorequest->completion_id, guac_rdp_fs_get_status(result), 4); else output_stream = guac_rdpdr_new_io_completion(device, - completion_id, STATUS_SUCCESS, 4); + iorequest->completion_id, STATUS_SUCCESS, 4); Stream_Write_UINT32(output_stream, length); guac_rdp_common_svc_write(svc, output_stream); @@ -269,18 +264,17 @@ void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdp_common_svc* svc, } void guac_rdpdr_fs_process_set_basic_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id, int length) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + int length, wStream* input_stream) { wStream* output_stream = guac_rdpdr_new_io_completion(device, - completion_id, STATUS_SUCCESS, 4); + iorequest->completion_id, STATUS_SUCCESS, 4); /* Currently do nothing, just respond */ Stream_Write_UINT32(output_stream, length); - guac_client_log(svc->client, GUAC_LOG_DEBUG, - "%s: [file_id=%i] IGNORED", - __func__, file_id); + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] IGNORED", + __func__, iorequest->file_id); guac_rdp_common_svc_write(svc, output_stream); diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h index d2198f5d..dfd207ae 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h @@ -33,72 +33,88 @@ #include +/** + * Handler for Device I/O Requests which set/update file information. + * + * @param svc + * The guac_rdp_common_svc representing the static virtual channel being + * used for RDPDR. + * + * @param device + * The guac_rdpdr_device of the relevant device, as dictated by the + * deviceId field of common RDPDR header within the received PDU. Within + * the guac_rdpdr_iorequest structure, the deviceId field is stored within + * device_id. + * + * @param iorequest + * The contents of the common RDPDR Device I/O Request header shared by all + * RDPDR devices. + * + * @param length + * The length of the SetBuffer field of the I/O request, in bytes. Whether + * the SetBuffer field is applicable to a particular request, as well as + * the specific contents of that field, depend on the type of request. + * + * @param input_stream + * The remaining data within the received PDU, following the common RDPDR + * Device I/O Request header and length field. If the SetBuffer field is + * used for this request, the first byte of SetBuffer will be the first + * byte read from this stream. + */ +typedef void guac_rdpdr_set_information_request_handler(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + int length, wStream* input_stream); + /** * Processes a query for FileBasicInformation. From the documentation, this is * "used to query a file for the times of creation, last access, last write, * and change, in addition to file attribute information." */ -void guac_rdpdr_fs_process_query_basic_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id); +guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_basic_info; /** * Processes a query for FileStandardInformation. From the documentation, this * is "used to query for file information such as allocation size, end-of-file * position, and number of links." */ -void guac_rdpdr_fs_process_query_standard_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id); +guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_standard_info; /** * Processes a query for FileAttributeTagInformation. From the documentation * this is "used to query for file attribute and reparse tag information." */ -void guac_rdpdr_fs_process_query_attribute_tag_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id); +guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_attribute_tag_info; /** * Process a set operation for FileRenameInformation. From the documentation, * this operation is used to rename a file. */ -void guac_rdpdr_fs_process_set_rename_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id, int length); +guac_rdpdr_set_information_request_handler guac_rdpdr_fs_process_set_rename_info; /** * Process a set operation for FileAllocationInformation. From the * documentation, this operation is used to set a file's allocation size. */ -void guac_rdpdr_fs_process_set_allocation_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id, int length); +guac_rdpdr_set_information_request_handler guac_rdpdr_fs_process_set_allocation_info; /** * Process a set operation for FileDispositionInformation. From the * documentation, this operation is used to mark a file for deletion. */ -void guac_rdpdr_fs_process_set_disposition_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id, int length); +guac_rdpdr_set_information_request_handler guac_rdpdr_fs_process_set_disposition_info; /** * Process a set operation for FileEndOfFileInformation. From the * documentation, this operation is used "to set end-of-file information for * a file." */ -void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id, int length); +guac_rdpdr_set_information_request_handler guac_rdpdr_fs_process_set_end_of_file_info; /** * Process a set operation for FileBasicInformation. From the documentation, * this is "used to set file information such as the times of creation, last * access, last write, and change, in addition to file attributes." */ -void guac_rdpdr_fs_process_set_basic_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id, int length); +guac_rdpdr_set_information_request_handler guac_rdpdr_fs_process_set_basic_info; #endif diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.c index 77f4cce8..1ab9dd21 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.c @@ -19,6 +19,8 @@ #include "config.h" #include "channels/rdpdr/rdpdr-messages.h" +#include "channels/rdpdr/rdpdr-fs-messages-vol-info.h" +#include "channels/rdpdr/rdpdr-fs.h" #include "channels/rdpdr/rdpdr.h" #include "fs.h" @@ -28,15 +30,14 @@ #include void guac_rdpdr_fs_process_query_volume_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { wStream* output_stream = guac_rdpdr_new_io_completion(device, - completion_id, STATUS_SUCCESS, 21 + GUAC_FILESYSTEM_LABEL_LENGTH); + iorequest->completion_id, STATUS_SUCCESS, 21 + GUAC_FILESYSTEM_LABEL_LENGTH); - guac_client_log(svc->client, GUAC_LOG_DEBUG, - "%s: [file_id=%i]", - __func__, file_id); + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, + iorequest->file_id); Stream_Write_UINT32(output_stream, 17 + GUAC_FILESYSTEM_LABEL_LENGTH); Stream_Write_UINT64(output_stream, 0); /* VolumeCreationTime */ @@ -51,18 +52,17 @@ void guac_rdpdr_fs_process_query_volume_info(guac_rdp_common_svc* svc, } void guac_rdpdr_fs_process_query_size_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { guac_rdp_fs_info info = {0}; guac_rdp_fs_get_info((guac_rdp_fs*) device->data, &info); wStream* output_stream = guac_rdpdr_new_io_completion(device, - completion_id, STATUS_SUCCESS, 28); + iorequest->completion_id, STATUS_SUCCESS, 28); - guac_client_log(svc->client, GUAC_LOG_DEBUG, - "%s: [file_id=%i]", - __func__, file_id); + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, + iorequest->file_id); Stream_Write_UINT32(output_stream, 24); Stream_Write_UINT64(output_stream, info.blocks_total); /* TotalAllocationUnits */ @@ -75,15 +75,14 @@ void guac_rdpdr_fs_process_query_size_info(guac_rdp_common_svc* svc, } void guac_rdpdr_fs_process_query_device_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { wStream* output_stream = guac_rdpdr_new_io_completion(device, - completion_id, STATUS_SUCCESS, 12); + iorequest->completion_id, STATUS_SUCCESS, 12); - guac_client_log(svc->client, GUAC_LOG_DEBUG, - "%s: [file_id=%i]", - __func__, file_id); + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, + iorequest->file_id); Stream_Write_UINT32(output_stream, 8); Stream_Write_UINT32(output_stream, FILE_DEVICE_DISK); /* DeviceType */ @@ -94,17 +93,16 @@ void guac_rdpdr_fs_process_query_device_info(guac_rdp_common_svc* svc, } void guac_rdpdr_fs_process_query_attribute_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { int name_len = guac_utf8_strlen(device->device_name); wStream* output_stream = guac_rdpdr_new_io_completion(device, - completion_id, STATUS_SUCCESS, 16 + name_len); + iorequest->completion_id, STATUS_SUCCESS, 16 + name_len); - guac_client_log(svc->client, GUAC_LOG_DEBUG, - "%s: [file_id=%i]", - __func__, file_id); + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, + iorequest->file_id); Stream_Write_UINT32(output_stream, 12 + name_len); Stream_Write_UINT32(output_stream, @@ -120,18 +118,17 @@ void guac_rdpdr_fs_process_query_attribute_info(guac_rdp_common_svc* svc, } void guac_rdpdr_fs_process_query_full_size_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { guac_rdp_fs_info info = {0}; guac_rdp_fs_get_info((guac_rdp_fs*) device->data, &info); wStream* output_stream = guac_rdpdr_new_io_completion(device, - completion_id, STATUS_SUCCESS, 36); + iorequest->completion_id, STATUS_SUCCESS, 36); - guac_client_log(svc->client, GUAC_LOG_DEBUG, - "%s: [file_id=%i]", - __func__, file_id); + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", __func__, + iorequest->file_id); Stream_Write_UINT32(output_stream, 32); Stream_Write_UINT64(output_stream, info.blocks_total); /* TotalAllocationUnits */ diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.h index 9f0d10aa..87c0745c 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.h @@ -38,37 +38,27 @@ * documentation, this is "used to query information for a volume on which a * file system is mounted." */ -void guac_rdpdr_fs_process_query_volume_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id); +guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_volume_info; /** * Processes a query request for FileFsSizeInformation. */ -void guac_rdpdr_fs_process_query_size_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id); +guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_size_info; /** * Processes a query request for FileFsAttributeInformation. */ -void guac_rdpdr_fs_process_query_attribute_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id); +guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_attribute_info; /** * Processes a query request for FileFsFullSizeInformation. */ -void guac_rdpdr_fs_process_query_full_size_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id); +guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_full_size_info; /** * Processes a query request for FileFsDeviceInformation. */ -void guac_rdpdr_fs_process_query_device_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id); +guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_device_info; #endif diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c index c8113d1a..4fede57a 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c @@ -39,7 +39,8 @@ #include void guac_rdpdr_fs_process_create(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { wStream* output_stream; int file_id; @@ -79,8 +80,8 @@ void guac_rdpdr_fs_process_create(guac_rdp_common_svc* svc, guac_client_log(svc->client, GUAC_LOG_ERROR, "File open refused (%i): \"%s\"", file_id, path); - output_stream = guac_rdpdr_new_io_completion(device, completion_id, - guac_rdp_fs_get_status(file_id), 5); + output_stream = guac_rdpdr_new_io_completion(device, + iorequest->completion_id, guac_rdp_fs_get_status(file_id), 5); Stream_Write_UINT32(output_stream, 0); /* fileId */ Stream_Write_UINT8(output_stream, 0); /* information */ } @@ -90,8 +91,8 @@ void guac_rdpdr_fs_process_create(guac_rdp_common_svc* svc, guac_rdp_fs_file* file; - output_stream = guac_rdpdr_new_io_completion(device, completion_id, - STATUS_SUCCESS, 5); + output_stream = guac_rdpdr_new_io_completion(device, + iorequest->completion_id, STATUS_SUCCESS, 5); Stream_Write_UINT32(output_stream, file_id); /* fileId */ Stream_Write_UINT8(output_stream, 0); /* information */ @@ -113,8 +114,8 @@ void guac_rdpdr_fs_process_create(guac_rdp_common_svc* svc, } void guac_rdpdr_fs_process_read(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { UINT32 length; UINT64 offset; @@ -129,7 +130,7 @@ void guac_rdpdr_fs_process_read(guac_rdp_common_svc* svc, guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] length=%i, offset=%" PRIu64, - __func__, file_id, length, (uint64_t) offset); + __func__, iorequest->file_id, length, (uint64_t) offset); /* Ensure buffer size does not exceed a safe maximum */ if (length > GUAC_RDP_MAX_READ_BUFFER) @@ -139,20 +140,20 @@ void guac_rdpdr_fs_process_read(guac_rdp_common_svc* svc, buffer = malloc(length); /* Attempt read */ - bytes_read = guac_rdp_fs_read((guac_rdp_fs*) device->data, file_id, offset, - buffer, length); + bytes_read = guac_rdp_fs_read((guac_rdp_fs*) device->data, + iorequest->file_id, offset, buffer, length); /* If error, return invalid parameter */ if (bytes_read < 0) { - output_stream = guac_rdpdr_new_io_completion(device, completion_id, - guac_rdp_fs_get_status(bytes_read), 4); + output_stream = guac_rdpdr_new_io_completion(device, + iorequest->completion_id, guac_rdp_fs_get_status(bytes_read), 4); Stream_Write_UINT32(output_stream, 0); /* Length */ } /* Otherwise, send bytes read */ else { - output_stream = guac_rdpdr_new_io_completion(device, completion_id, - STATUS_SUCCESS, 4+bytes_read); + output_stream = guac_rdpdr_new_io_completion(device, + iorequest->completion_id, STATUS_SUCCESS, 4+bytes_read); Stream_Write_UINT32(output_stream, bytes_read); /* Length */ Stream_Write(output_stream, buffer, bytes_read); /* ReadData */ } @@ -163,8 +164,8 @@ void guac_rdpdr_fs_process_read(guac_rdp_common_svc* svc, } void guac_rdpdr_fs_process_write(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { UINT32 length; UINT64 offset; @@ -179,24 +180,24 @@ void guac_rdpdr_fs_process_write(guac_rdp_common_svc* svc, guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] length=%i, offset=%" PRIu64, - __func__, file_id, length, (uint64_t) offset); + __func__, iorequest->file_id, length, (uint64_t) offset); /* Attempt write */ - bytes_written = guac_rdp_fs_write((guac_rdp_fs*) device->data, file_id, - offset, Stream_Pointer(input_stream), length); + bytes_written = guac_rdp_fs_write((guac_rdp_fs*) device->data, + iorequest->file_id, offset, Stream_Pointer(input_stream), length); /* If error, return invalid parameter */ if (bytes_written < 0) { - output_stream = guac_rdpdr_new_io_completion(device, completion_id, - guac_rdp_fs_get_status(bytes_written), 5); + output_stream = guac_rdpdr_new_io_completion(device, + iorequest->completion_id, guac_rdp_fs_get_status(bytes_written), 5); Stream_Write_UINT32(output_stream, 0); /* Length */ Stream_Write_UINT8(output_stream, 0); /* Padding */ } /* Otherwise, send success */ else { - output_stream = guac_rdpdr_new_io_completion(device, completion_id, - STATUS_SUCCESS, 5); + output_stream = guac_rdpdr_new_io_completion(device, + iorequest->completion_id, STATUS_SUCCESS, 5); Stream_Write_UINT32(output_stream, bytes_written); /* Length */ Stream_Write_UINT8(output_stream, 0); /* Padding */ } @@ -206,18 +207,17 @@ void guac_rdpdr_fs_process_write(guac_rdp_common_svc* svc, } void guac_rdpdr_fs_process_close(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { wStream* output_stream; guac_rdp_fs_file* file; - guac_client_log(svc->client, GUAC_LOG_DEBUG, - "%s: [file_id=%i]", - __func__, file_id); + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i]", + __func__, iorequest->file_id); /* Get file */ - file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id); + file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id); if (file == NULL) return; @@ -225,14 +225,14 @@ void guac_rdpdr_fs_process_close(guac_rdp_common_svc* svc, if (file->bytes_written > 0 && strncmp(file->absolute_path, "\\Download\\", 10) == 0) { guac_rdpdr_start_download(svc, device, file->absolute_path); - guac_rdp_fs_delete((guac_rdp_fs*) device->data, file_id); + guac_rdp_fs_delete((guac_rdp_fs*) device->data, iorequest->file_id); } /* Close file */ - guac_rdp_fs_close((guac_rdp_fs*) device->data, file_id); + guac_rdp_fs_close((guac_rdp_fs*) device->data, iorequest->file_id); - output_stream = guac_rdpdr_new_io_completion(device, completion_id, - STATUS_SUCCESS, 4); + output_stream = guac_rdpdr_new_io_completion(device, + iorequest->completion_id, STATUS_SUCCESS, 4); Stream_Write(output_stream, "\0\0\0\0", 4); /* Padding */ guac_rdp_common_svc_write(svc, output_stream); @@ -240,8 +240,8 @@ void guac_rdpdr_fs_process_close(guac_rdp_common_svc* svc, } void guac_rdpdr_fs_process_volume_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { int fs_information_class; @@ -251,28 +251,23 @@ void guac_rdpdr_fs_process_volume_info(guac_rdp_common_svc* svc, switch (fs_information_class) { case FileFsVolumeInformation: - guac_rdpdr_fs_process_query_volume_info(svc, device, input_stream, - file_id, completion_id); + guac_rdpdr_fs_process_query_volume_info(svc, device, iorequest, input_stream); break; case FileFsSizeInformation: - guac_rdpdr_fs_process_query_size_info(svc, device, input_stream, - file_id, completion_id); + guac_rdpdr_fs_process_query_size_info(svc, device, iorequest, input_stream); break; case FileFsDeviceInformation: - guac_rdpdr_fs_process_query_device_info(svc, device, input_stream, - file_id, completion_id); + guac_rdpdr_fs_process_query_device_info(svc, device, iorequest, input_stream); break; case FileFsAttributeInformation: - guac_rdpdr_fs_process_query_attribute_info(svc, device, - input_stream, file_id, completion_id); + guac_rdpdr_fs_process_query_attribute_info(svc, device, iorequest, input_stream); break; case FileFsFullSizeInformation: - guac_rdpdr_fs_process_query_full_size_info(svc, device, - input_stream, file_id, completion_id); + guac_rdpdr_fs_process_query_full_size_info(svc, device, iorequest, input_stream); break; default: @@ -283,8 +278,8 @@ void guac_rdpdr_fs_process_volume_info(guac_rdp_common_svc* svc, } void guac_rdpdr_fs_process_file_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { int fs_information_class; @@ -294,18 +289,15 @@ void guac_rdpdr_fs_process_file_info(guac_rdp_common_svc* svc, switch (fs_information_class) { case FileBasicInformation: - guac_rdpdr_fs_process_query_basic_info(svc, device, input_stream, - file_id, completion_id); + guac_rdpdr_fs_process_query_basic_info(svc, device, iorequest, input_stream); break; case FileStandardInformation: - guac_rdpdr_fs_process_query_standard_info(svc, device, - input_stream, file_id, completion_id); + guac_rdpdr_fs_process_query_standard_info(svc, device, iorequest, input_stream); break; case FileAttributeTagInformation: - guac_rdpdr_fs_process_query_attribute_tag_info(svc, device, - input_stream, file_id, completion_id); + guac_rdpdr_fs_process_query_attribute_tag_info(svc, device, iorequest, input_stream); break; default: @@ -316,23 +308,23 @@ void guac_rdpdr_fs_process_file_info(guac_rdp_common_svc* svc, } void guac_rdpdr_fs_process_set_volume_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { wStream* output_stream = guac_rdpdr_new_io_completion(device, - completion_id, STATUS_NOT_SUPPORTED, 0); + iorequest->completion_id, STATUS_NOT_SUPPORTED, 0); guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] Set volume info not supported", - __func__, file_id); + __func__, iorequest->file_id); guac_rdp_common_svc_write(svc, output_stream); } void guac_rdpdr_fs_process_set_file_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { int fs_information_class; int length; @@ -345,28 +337,23 @@ void guac_rdpdr_fs_process_set_file_info(guac_rdp_common_svc* svc, switch (fs_information_class) { case FileBasicInformation: - guac_rdpdr_fs_process_set_basic_info(svc, device, input_stream, - file_id, completion_id, length); + guac_rdpdr_fs_process_set_basic_info(svc, device, iorequest, length, input_stream); break; case FileEndOfFileInformation: - guac_rdpdr_fs_process_set_end_of_file_info(svc, device, - input_stream, file_id, completion_id, length); + guac_rdpdr_fs_process_set_end_of_file_info(svc, device, iorequest, length, input_stream); break; case FileDispositionInformation: - guac_rdpdr_fs_process_set_disposition_info(svc, device, - input_stream, file_id, completion_id, length); + guac_rdpdr_fs_process_set_disposition_info(svc, device, iorequest, length, input_stream); break; case FileRenameInformation: - guac_rdpdr_fs_process_set_rename_info(svc, device, input_stream, - file_id, completion_id, length); + guac_rdpdr_fs_process_set_rename_info(svc, device, iorequest, length, input_stream); break; case FileAllocationInformation: - guac_rdpdr_fs_process_set_allocation_info(svc, device, - input_stream, file_id, completion_id, length); + guac_rdpdr_fs_process_set_allocation_info(svc, device, iorequest, length, input_stream); break; default: @@ -378,15 +365,14 @@ void guac_rdpdr_fs_process_set_file_info(guac_rdp_common_svc* svc, } void guac_rdpdr_fs_process_device_control(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { wStream* output_stream = guac_rdpdr_new_io_completion(device, - completion_id, STATUS_INVALID_PARAMETER, 4); + iorequest->completion_id, STATUS_INVALID_PARAMETER, 4); - guac_client_log(svc->client, GUAC_LOG_DEBUG, - "%s: [file_id=%i] IGNORED", - __func__, file_id); + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] IGNORED", + __func__, iorequest->file_id); /* No content for now */ Stream_Write_UINT32(output_stream, 0); @@ -396,18 +382,17 @@ void guac_rdpdr_fs_process_device_control(guac_rdp_common_svc* svc, } void guac_rdpdr_fs_process_notify_change_directory(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { - guac_client_log(svc->client, GUAC_LOG_DEBUG, - "%s: [file_id=%i] Not implemented", - __func__, file_id); + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] Not " + "implemented", __func__, iorequest->file_id); } void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { wStream* output_stream; @@ -418,7 +403,7 @@ void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc, const char* entry_name; /* Get file */ - file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id); + file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, iorequest->file_id); if (file == NULL) return; @@ -438,13 +423,13 @@ void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc, } - guac_client_log(svc->client, GUAC_LOG_DEBUG, - "%s: [file_id=%i] initial_query=%i, dir_pattern=\"%s\"", - __func__, file_id, initial_query, file->dir_pattern); + guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] " + "initial_query=%i, dir_pattern=\"%s\"", __func__, + iorequest->file_id, initial_query, file->dir_pattern); /* Find first matching entry in directory */ while ((entry_name = guac_rdp_fs_read_dir((guac_rdp_fs*) device->data, - file_id)) != NULL) { + iorequest->file_id)) != NULL) { /* Convert to absolute path */ char entry_path[GUAC_RDP_FS_MAX_PATH]; @@ -468,24 +453,22 @@ void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc, case FileDirectoryInformation: guac_rdpdr_fs_process_query_directory_info(svc, device, - entry_name, entry_file_id, completion_id); + iorequest, entry_name, entry_file_id); break; case FileFullDirectoryInformation: guac_rdpdr_fs_process_query_full_directory_info(svc, - device, entry_name, entry_file_id, - completion_id); + device, iorequest, entry_name, entry_file_id); break; case FileBothDirectoryInformation: guac_rdpdr_fs_process_query_both_directory_info(svc, - device, entry_name, entry_file_id, - completion_id); + device, iorequest, entry_name, entry_file_id); break; case FileNamesInformation: guac_rdpdr_fs_process_query_names_info(svc, device, - entry_name, entry_file_id, completion_id); + iorequest, entry_name, entry_file_id); break; default: @@ -505,8 +488,8 @@ void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc, * Handle errors as a lack of files. */ - output_stream = guac_rdpdr_new_io_completion(device, completion_id, - STATUS_NO_MORE_FILES, 5); + output_stream = guac_rdpdr_new_io_completion(device, + iorequest->completion_id, STATUS_NO_MORE_FILES, 5); Stream_Write_UINT32(output_stream, 0); /* Length */ Stream_Write_UINT8(output_stream, 0); /* Padding */ @@ -516,15 +499,15 @@ void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc, } void guac_rdpdr_fs_process_lock_control(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { wStream* output_stream = guac_rdpdr_new_io_completion(device, - completion_id, STATUS_NOT_SUPPORTED, 5); + iorequest->completion_id, STATUS_NOT_SUPPORTED, 5); guac_client_log(svc->client, GUAC_LOG_DEBUG, "%s: [file_id=%i] Lock not supported", - __func__, file_id); + __func__, iorequest->file_id); Stream_Zero(output_stream, 5); /* Padding */ diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.h index dd5454cc..bfc8312b 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.h @@ -37,37 +37,28 @@ * Handles a Server Create Drive Request. Despite its name, this request opens * a file. */ -void guac_rdpdr_fs_process_create(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int completion_id); +guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_create; /** - * Handles a Server Close Drive Reqiest. This request closes an open file. + * Handles a Server Close Drive Request. This request closes an open file. */ -void guac_rdpdr_fs_process_close(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id); +guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_close; /** * Handles a Server Drive Read Request. This request reads from a file. */ -void guac_rdpdr_fs_process_read(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id); +guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_read; /** * Handles a Server Drive Write Request. This request writes to a file. */ -void guac_rdpdr_fs_process_write(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id); +guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_write; /** * Handles a Server Drive Control Request. This request handles one of any * number of Windows FSCTL_* control functions. */ -void guac_rdpdr_fs_process_device_control(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id); +guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_device_control; /** * Handles a Server Drive Query Volume Information Request. This request @@ -75,60 +66,46 @@ void guac_rdpdr_fs_process_device_control(guac_rdp_common_svc* svc, * has several query types which have their own handlers defined in a * separate file. */ -void guac_rdpdr_fs_process_volume_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id); +guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_volume_info; /** * Handles a Server Drive Set Volume Information Request. Currently, this * RDPDR implementation does not support setting of volume information. */ -void guac_rdpdr_fs_process_set_volume_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id); +guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_set_volume_info; /** * Handles a Server Drive Query Information Request. This request queries * information about a specific file. This request has several query types * which have their own handlers defined in a separate file. */ -void guac_rdpdr_fs_process_file_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id); +guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_file_info; /** * Handles a Server Drive Set Information Request. This request sets * information about a specific file. Currently, this RDPDR implementation does * not support setting of file information. */ -void guac_rdpdr_fs_process_set_file_info(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id); +guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_set_file_info; /** * Handles a Server Drive Query Directory Request. This request queries * information about a specific directory. This request has several query types * which have their own handlers defined in a separate file. */ -void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id); +guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_query_directory; /** * Handles a Server Drive NotifyChange Directory Request. This request requests * directory change notification. */ -void guac_rdpdr_fs_process_notify_change_directory(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id); +guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_notify_change_directory; /** * Handles a Server Drive Lock Control Request. This request locks or unlocks * portions of a file. */ -void guac_rdpdr_fs_process_lock_control(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id); +guac_rdpdr_device_iorequest_handler guac_rdpdr_fs_process_lock_control; #endif diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs.c index 3ca862cf..87e7d9fc 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs.c @@ -19,6 +19,7 @@ #include "config.h" #include "channels/rdpdr/rdpdr-fs-messages.h" +#include "channels/rdpdr/rdpdr-fs.h" #include "channels/rdpdr/rdpdr-messages.h" #include "channels/rdpdr/rdpdr.h" #include "rdp.h" @@ -30,96 +31,85 @@ #include #include -static void guac_rdpdr_device_fs_iorequest_handler(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id, int major_func, int minor_func) { +void guac_rdpdr_device_fs_iorequest_handler(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { - switch (major_func) { + switch (iorequest->major_func) { /* File open */ case IRP_MJ_CREATE: - guac_rdpdr_fs_process_create(svc, device, input_stream, - completion_id); + guac_rdpdr_fs_process_create(svc, device, iorequest, input_stream); break; /* File close */ case IRP_MJ_CLOSE: - guac_rdpdr_fs_process_close(svc, device, input_stream, file_id, - completion_id); + guac_rdpdr_fs_process_close(svc, device, iorequest, input_stream); break; /* File read */ case IRP_MJ_READ: - guac_rdpdr_fs_process_read(svc, device, input_stream, file_id, - completion_id); + guac_rdpdr_fs_process_read(svc, device, iorequest, input_stream); break; /* File write */ case IRP_MJ_WRITE: - guac_rdpdr_fs_process_write(svc, device, input_stream, file_id, - completion_id); + guac_rdpdr_fs_process_write(svc, device, iorequest, input_stream); break; /* Device control request (Windows FSCTL_ control codes) */ case IRP_MJ_DEVICE_CONTROL: - guac_rdpdr_fs_process_device_control(svc, device, input_stream, - file_id, completion_id); + guac_rdpdr_fs_process_device_control(svc, device, iorequest, input_stream); break; /* Query volume (drive) information */ case IRP_MJ_QUERY_VOLUME_INFORMATION: - guac_rdpdr_fs_process_volume_info(svc, device, input_stream, - file_id, completion_id); + guac_rdpdr_fs_process_volume_info(svc, device, iorequest, input_stream); break; /* Set volume (drive) information */ case IRP_MJ_SET_VOLUME_INFORMATION: - guac_rdpdr_fs_process_set_volume_info(svc, device, input_stream, - file_id, completion_id); + guac_rdpdr_fs_process_set_volume_info(svc, device, iorequest, input_stream); break; /* Query file information */ case IRP_MJ_QUERY_INFORMATION: - guac_rdpdr_fs_process_file_info(svc, device, input_stream, file_id, - completion_id); + guac_rdpdr_fs_process_file_info(svc, device, iorequest, input_stream); break; /* Set file information */ case IRP_MJ_SET_INFORMATION: - guac_rdpdr_fs_process_set_file_info(svc, device, input_stream, - file_id, completion_id); + guac_rdpdr_fs_process_set_file_info(svc, device, iorequest, input_stream); break; case IRP_MJ_DIRECTORY_CONTROL: /* Enumerate directory contents */ - if (minor_func == IRP_MN_QUERY_DIRECTORY) - guac_rdpdr_fs_process_query_directory(svc, device, - input_stream, file_id, completion_id); + if (iorequest->minor_func == IRP_MN_QUERY_DIRECTORY) + guac_rdpdr_fs_process_query_directory(svc, device, iorequest, + input_stream); /* Request notification of changes to directory */ - else if (minor_func == IRP_MN_NOTIFY_CHANGE_DIRECTORY) + else if (iorequest->minor_func == IRP_MN_NOTIFY_CHANGE_DIRECTORY) guac_rdpdr_fs_process_notify_change_directory(svc, device, - input_stream, - file_id, completion_id); + iorequest, input_stream); break; /* Lock/unlock portions of a file */ case IRP_MJ_LOCK_CONTROL: - guac_rdpdr_fs_process_lock_control(svc, device, input_stream, - file_id, completion_id); + guac_rdpdr_fs_process_lock_control(svc, device, iorequest, input_stream); break; default: guac_client_log(svc->client, GUAC_LOG_ERROR, "Unknown filesystem I/O request function: 0x%x/0x%x", - major_func, minor_func); + iorequest->major_func, iorequest->minor_func); } } -static void guac_rdpdr_device_fs_free_handler(guac_rdp_common_svc* svc, +void guac_rdpdr_device_fs_free_handler(guac_rdp_common_svc* svc, guac_rdpdr_device* device) { Stream_Free(device->device_announce, 1); diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h index ab8a13db..6f6e5d1d 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h @@ -36,6 +36,16 @@ #include +/** + * The UTF-16 string that should be sent as the label of the filesystem. + */ +#define GUAC_FILESYSTEM_LABEL "G\0U\0A\0C\0F\0I\0L\0E\0" + +/** + * The size of GUAC_FILESYSTEM_LABEL in bytes. + */ +#define GUAC_FILESYSTEM_LABEL_LENGTH 16 + /** * Registers a new filesystem device within the RDPDR plugin. This must be done * before RDPDR connection finishes. diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-messages.c b/src/protocols/rdp/channels/rdpdr/rdpdr-messages.c index b9b67383..21bb3162 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-messages.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-messages.c @@ -31,6 +31,28 @@ #include #include +/** + * Sends a Client Announce Reply message. The Client Announce Reply message is + * required to be sent in response to the Server Announce Request message. See: + * + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/d6fe6d1b-c145-4a6f-99aa-4fe3cdcea398 + * + * @param svc + * The guac_rdp_common_svc representing the static virtual channel being + * used for RDPDR. + * + * @param major + * The major version of the RDPDR protocol in use. This value must always + * be 1. + * + * @param minor + * The minor version of the RDPDR protocol in use. This value must be + * either 2, 5, 10, 12, or 13. + * + * @param client_id + * The client ID received in the Server Announce Request, or a randomly + * generated ID. + */ static void guac_rdpdr_send_client_announce_reply(guac_rdp_common_svc* svc, unsigned int major, unsigned int minor, unsigned int client_id) { @@ -49,6 +71,19 @@ static void guac_rdpdr_send_client_announce_reply(guac_rdp_common_svc* svc, } +/** + * Sends a Client Name Request message. The Client Name Request message is used + * by the client to announce its own name. See: + * + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/902497f1-3b1c-4aee-95f8-1668f9b7b7d2 + * + * @param svc + * The guac_rdp_common_svc representing the static virtual channel being + * used for RDPDR. + * + * @param name + * The name that should be used for the client. + */ static void guac_rdpdr_send_client_name_request(guac_rdp_common_svc* svc, const char* name) { @@ -69,6 +104,18 @@ static void guac_rdpdr_send_client_name_request(guac_rdp_common_svc* svc, } +/** + * Sends a Client Core Capability Response message. The Client Core Capability + * Response message is used to announce the client's capabilities, in response + * to receiving the server's capabilities via a Server Core Capability Request. + * See: + * + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/f513bf87-cca0-488a-ac5c-18cf18f4a7e1 + * + * @param svc + * The guac_rdp_common_svc representing the static virtual channel being + * used for RDPDR. + */ static void guac_rdpdr_send_client_capability(guac_rdp_common_svc* svc) { wStream* output_stream = Stream_New(NULL, 256); @@ -117,6 +164,17 @@ static void guac_rdpdr_send_client_capability(guac_rdp_common_svc* svc) { } +/** + * Sends a Client Device List Announce Request message. The Client Device List + * Announce Request message is used by the client to enumerate all devices + * which should be made available within the RDP session via RDPDR. See: + * + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/10ef9ada-cba2-4384-ab60-7b6290ed4a9a + * + * @param svc + * The guac_rdp_common_svc representing the static virtual channel being + * used for RDPDR. + */ static void guac_rdpdr_send_client_device_list_announce_request(guac_rdp_common_svc* svc) { guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data; @@ -220,28 +278,27 @@ void guac_rdpdr_process_device_iorequest(guac_rdp_common_svc* svc, wStream* input_stream) { guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data; - - int device_id, file_id, completion_id, major_func, minor_func; + guac_rdpdr_iorequest iorequest; /* Read header */ - Stream_Read_UINT32(input_stream, device_id); - Stream_Read_UINT32(input_stream, file_id); - Stream_Read_UINT32(input_stream, completion_id); - Stream_Read_UINT32(input_stream, major_func); - Stream_Read_UINT32(input_stream, minor_func); + Stream_Read_UINT32(input_stream, iorequest.device_id); + Stream_Read_UINT32(input_stream, iorequest.file_id); + Stream_Read_UINT32(input_stream, iorequest.completion_id); + Stream_Read_UINT32(input_stream, iorequest.major_func); + Stream_Read_UINT32(input_stream, iorequest.minor_func); /* If printer, run printer handlers */ - if (device_id >= 0 && device_id < rdpdr->devices_registered) { + if (iorequest.device_id >= 0 && iorequest.device_id < rdpdr->devices_registered) { /* Call handler on device */ - guac_rdpdr_device* device = &(rdpdr->devices[device_id]); - device->iorequest_handler(svc, device, input_stream, - file_id, completion_id, major_func, minor_func); + guac_rdpdr_device* device = &(rdpdr->devices[iorequest.device_id]); + device->iorequest_handler(svc, device, &iorequest, input_stream); } else - guac_client_log(svc->client, GUAC_LOG_ERROR, "Unknown device ID: 0x%08x", device_id); + guac_client_log(svc->client, GUAC_LOG_ERROR, "Unknown device ID: " + "0x%08x", iorequest.device_id); } diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-messages.h b/src/protocols/rdp/channels/rdpdr/rdpdr-messages.h index d1352d72..27684cf2 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-messages.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-messages.h @@ -35,29 +35,102 @@ #define GUAC_OS_TYPE (*((uint32_t*) "GUAC")) /** - * Name of the printer driver that should be used on the server. + * Handler which processes a message specific to the RDPDR channel. + * + * @param svc + * The guac_rdp_common_svc representing the static virtual channel being + * used for RDPDR. + * + * @param input_stream + * A wStream containing the entire received message. */ -#define GUAC_PRINTER_DRIVER "M\0S\0 \0P\0u\0b\0l\0i\0s\0h\0e\0r\0 \0I\0m\0a\0g\0e\0s\0e\0t\0t\0e\0r\0\0\0" -#define GUAC_PRINTER_DRIVER_LENGTH 50 +typedef void guac_rdpdr_message_handler(guac_rdp_common_svc* svc, + wStream* input_stream); /** - * Label of the filesystem. + * Handler which processes a received Server Announce Request message. The + * Server Announce Request message begins the RDPDR exchange and provides a + * client ID which the RDPDR client may use. The client may also supply its + * own, randomly-generated ID, and is required to do so for older versions of + * RDPDR. See: + * + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/046047aa-62d8-49f9-bf16-7fe41880aaf4 */ -#define GUAC_FILESYSTEM_LABEL "G\0U\0A\0C\0F\0I\0L\0E\0" -#define GUAC_FILESYSTEM_LABEL_LENGTH 16 +guac_rdpdr_message_handler guac_rdpdr_process_server_announce; -/* - * Message handlers. +/** + * Handler which processes a received Server Client ID Confirm message. The + * Server Client ID Confirm message is sent by the server to confirm the client + * ID requested by the client (in its response to the Server Announce Request) + * has been accepted. See: + * + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/bbbb9666-6994-4cf6-8e65-0d46eb319c6e */ +guac_rdpdr_message_handler guac_rdpdr_process_clientid_confirm; -void guac_rdpdr_process_server_announce(guac_rdp_common_svc* svc, wStream* input_stream); -void guac_rdpdr_process_clientid_confirm(guac_rdp_common_svc* svc, wStream* input_stream); -void guac_rdpdr_process_device_reply(guac_rdp_common_svc* svc, wStream* input_stream); -void guac_rdpdr_process_device_iorequest(guac_rdp_common_svc* svc, wStream* input_stream); -void guac_rdpdr_process_server_capability(guac_rdp_common_svc* svc, wStream* input_stream); -void guac_rdpdr_process_user_loggedon(guac_rdp_common_svc* svc, wStream* input_stream); -void guac_rdpdr_process_prn_cache_data(guac_rdp_common_svc* svc, wStream* input_stream); -void guac_rdpdr_process_prn_using_xps(guac_rdp_common_svc* svc, wStream* input_stream); +/** + * Handler which processes a received Server Device Announce Response message. + * The Server Device Announce Response message is sent in response to a Client + * Device List Announce message to communicate the success/failure status of + * device creation. See: + * + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/a4c0b619-6e87-4721-bdc4-5d2db7f485f3 + */ +guac_rdpdr_message_handler guac_rdpdr_process_device_reply; + +/** + * Handler which processes a received Device I/O Request message. The Device + * I/O Request message makes up the majority of traffic once RDPDR is + * established. Each I/O request consists of a device-specific major/minor + * function number pair, as well as several parameters. Device-specific + * handling of I/O requests within Guacamole is delegated to device- and + * function-specific implementations of yet another function type: + * guac_rdpdr_device_iorequest_handler. + * + * See: + * + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/a087ffa8-d0d5-4874-ac7b-0494f63e2d5d + */ +guac_rdpdr_message_handler guac_rdpdr_process_device_iorequest; + +/** + * Handler which processes a received Server Core Capability Request message. + * The Server Core Capability Request message is sent by the server to + * communicate its capabilities and to request that the client communicate the + * same. See: + * + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/702789c3-b924-4bc2-9280-3221bc7d6797 + */ +guac_rdpdr_message_handler guac_rdpdr_process_server_capability; + +/** + * Handler which processes a received Server User Logged On message. The Server + * User Logged On message is sent by the server to notify that the user has + * logged on to the session. See: + * + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/dfc0e8ed-a242-4d00-bb88-e779e08f2f61 + */ +guac_rdpdr_message_handler guac_rdpdr_process_user_loggedon; + +/** + * Handler which processes any one of several RDPDR messages specific to cached + * printer configuration data, each of these messages having the same + * PAKID_PRN_CACHE_DATA packet ID. The Guacamole RDPDR implementation ignores + * all PAKID_PRN_CACHE_DATA messages. See: + * + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpepc/7fccae60-f077-433b-9dee-9bad4238bf40 + */ +guac_rdpdr_message_handler guac_rdpdr_process_prn_cache_data; + +/** + * Handler which processes a received Server Printer Set XPS Mode message. The + * Server Printer Set XPS Mode message is specific to printers and requests + * that the client printer be set to XPS mode. The Guacamole RDPDR + * implementation ignores any request to set the printer to XPS mode. See: + * + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpepc/f1789a66-bcd0-4df3-bfc2-6e7330d63145 + */ +guac_rdpdr_message_handler guac_rdpdr_process_prn_using_xps; #endif diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-printer.c b/src/protocols/rdp/channels/rdpdr/rdpdr-printer.c index c3359631..e435d32b 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-printer.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-printer.c @@ -43,7 +43,8 @@ #include void guac_rdpdr_process_print_job_create(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { guac_client* client = svc->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; @@ -57,7 +58,7 @@ void guac_rdpdr_process_print_job_create(guac_rdp_common_svc* svc, /* Respond with success */ wStream* output_stream = guac_rdpdr_new_io_completion(device, - completion_id, STATUS_SUCCESS, 4); + iorequest->completion_id, STATUS_SUCCESS, 4); Stream_Write_UINT32(output_stream, 0); /* fileId */ guac_rdp_common_svc_write(svc, output_stream); @@ -65,7 +66,8 @@ void guac_rdpdr_process_print_job_create(guac_rdp_common_svc* svc, } void guac_rdpdr_process_print_job_write(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { guac_client* client = svc->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; @@ -94,7 +96,7 @@ void guac_rdpdr_process_print_job_write(guac_rdp_common_svc* svc, } wStream* output_stream = guac_rdpdr_new_io_completion(device, - completion_id, status, 5); + iorequest->completion_id, status, 5); Stream_Write_UINT32(output_stream, length); Stream_Write_UINT8(output_stream, 0); /* Padding */ @@ -104,7 +106,8 @@ void guac_rdpdr_process_print_job_write(guac_rdp_common_svc* svc, } void guac_rdpdr_process_print_job_close(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int completion_id) { + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { guac_client* client = svc->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; @@ -117,7 +120,7 @@ void guac_rdpdr_process_print_job_close(guac_rdp_common_svc* svc, } wStream* output_stream = guac_rdpdr_new_io_completion(device, - completion_id, STATUS_SUCCESS, 4); + iorequest->completion_id, STATUS_SUCCESS, 4); Stream_Write_UINT32(output_stream, 0); /* Padding */ guac_rdp_common_svc_write(svc, output_stream); @@ -127,41 +130,38 @@ void guac_rdpdr_process_print_job_close(guac_rdp_common_svc* svc, } -static void guac_rdpdr_device_printer_iorequest_handler(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id, int major_func, int minor_func) { +void guac_rdpdr_device_printer_iorequest_handler(guac_rdp_common_svc* svc, + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream) { - switch (major_func) { + switch (iorequest->major_func) { /* Print job create */ case IRP_MJ_CREATE: - guac_rdpdr_process_print_job_create(svc, device, input_stream, - completion_id); + guac_rdpdr_process_print_job_create(svc, device, iorequest, input_stream); break; /* Printer job write */ case IRP_MJ_WRITE: - guac_rdpdr_process_print_job_write(svc, device, input_stream, - completion_id); + guac_rdpdr_process_print_job_write(svc, device, iorequest, input_stream); break; /* Printer job close */ case IRP_MJ_CLOSE: - guac_rdpdr_process_print_job_close(svc, device, input_stream, - completion_id); + guac_rdpdr_process_print_job_close(svc, device, iorequest, input_stream); break; /* Log unknown */ default: - guac_client_log(svc->client, GUAC_LOG_ERROR, - "Unknown printer I/O request function: 0x%x/0x%x", - major_func, minor_func); + guac_client_log(svc->client, GUAC_LOG_ERROR, "Unknown printer " + "I/O request function: 0x%x/0x%x", iorequest->major_func, + iorequest->minor_func); } } -static void guac_rdpdr_device_printer_free_handler(guac_rdp_common_svc* svc, +void guac_rdpdr_device_printer_free_handler(guac_rdp_common_svc* svc, guac_rdpdr_device* device) { Stream_Free(device->device_announce, 1); diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-printer.h b/src/protocols/rdp/channels/rdpdr/rdpdr-printer.h index 0addc6fb..106d6be3 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-printer.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-printer.h @@ -25,6 +25,16 @@ #include +/** + * Name of the printer driver that should be used on the server. + */ +#define GUAC_PRINTER_DRIVER "M\0S\0 \0P\0u\0b\0l\0i\0s\0h\0e\0r\0 \0I\0m\0a\0g\0e\0s\0e\0t\0t\0e\0r\0\0\0" + +/** + * The size of GUAC_PRINTER_DRIVER in bytes. + */ +#define GUAC_PRINTER_DRIVER_LENGTH 50 + /** * Registers a new printer device within the RDPDR plugin. This must be done * before RDPDR connection finishes. @@ -38,5 +48,34 @@ */ void guac_rdpdr_register_printer(guac_rdp_common_svc* svc, char* printer_name); +/** + * I/O request handler which processes a print job creation request. + */ +guac_rdpdr_device_iorequest_handler guac_rdpdr_process_print_job_create; + +/** + * I/O request handler which processes a request to write data to an existing + * print job. + */ +guac_rdpdr_device_iorequest_handler guac_rdpdr_process_print_job_write; + +/** + * I/O request handler which processes a request to close an existing print + * job. + */ +guac_rdpdr_device_iorequest_handler guac_rdpdr_process_print_job_close; + +/** + * Handler for RDPDR Device I/O Requests which processes received messages on + * behalf of a printer device, in this case a simulated printer which produces + * PDF output. + */ +guac_rdpdr_device_iorequest_handler guac_rdpdr_device_printer_iorequest_handler; + +/** + * Free handler which frees all data specific to the simulated printer device. + */ +guac_rdpdr_device_free_handler guac_rdpdr_device_printer_free_handler; + #endif diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr.h b/src/protocols/rdp/channels/rdpdr/rdpdr.h index f75df0f0..19f178d0 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr.h @@ -37,21 +37,79 @@ typedef struct guac_rdpdr_device guac_rdpdr_device; /** - * Handler for client device list announce. Each implementing device must write - * its announcement header and data to the given output stream. + * The contents of the header common to all RDPDR Device I/O Requests. See: + * + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/a087ffa8-d0d5-4874-ac7b-0494f63e2d5d */ -typedef void guac_rdpdr_device_announce_handler(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* output_stream, int device_id); +typedef struct guac_rdpdr_iorequest { + + /** + * The unique ID assigned to the device receiving this I/O request. + */ + int device_id; + + /** + * The unique ID which identifies the relevant file, as returned when the + * file was opened. This field may not be relevant to all requests. + */ + int file_id; + + /** + * The unique ID that should be used to refer to this I/O request in future + * responses. + */ + int completion_id; + + /** + * Integer ID which identifies the function being requested, such as + * IRP_MJ_CREATE (open a file within a shared drive) or IRP_MJ_WRITE (write + * data to an open file). + */ + int major_func; + + /** + * Integer ID which identifies a variant of the function denoted by + * major_func. This value is only valid for IRP_MJ_DIRECTORY_CONTROL. + */ + int minor_func; + +} guac_rdpdr_iorequest; /** - * Handler for device I/O requests. + * Handler for Device I/O Requests. RDPDR devices must provide an + * implementation of this function to be able to handle inbound I/O requests. + * + * @param svc + * The guac_rdp_common_svc representing the static virtual channel being + * used for RDPDR. + * + * @param device + * The guac_rdpdr_device of the relevant device, as dictated by the + * deviceId field of common RDPDR header within the received PDU. Within + * the guac_rdpdr_iorequest structure, the deviceId field is stored within + * device_id. + * + * @param iorequest + * The contents of the common RDPDR Device I/O Request header shared by all + * RDPDR devices. + * + * @param input_stream + * The remaining data within the received PDU, following the common RDPDR + * Device I/O Request header. */ typedef void guac_rdpdr_device_iorequest_handler(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, wStream* input_stream, int file_id, - int completion_id, int major_func, int minor_func); + guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, + wStream* input_stream); /** * Handler for cleaning up the dynamically-allocated portions of a device. + * + * @param svc + * The guac_rdp_common_svc representing the static virtual channel being + * used for RDPDR. + * + * @param device + * The guac_rdpdr_device of the device being freed. */ typedef void guac_rdpdr_device_free_handler(guac_rdp_common_svc* svc, guac_rdpdr_device* device); @@ -126,7 +184,30 @@ typedef struct guac_rdpdr { /** * Creates a new stream which contains the common DR_DEVICE_IOCOMPLETION header - * used for virtually all responses. + * used for virtually all responses. Depending on the specific I/O completion + * being sent, additional space may be reserved within the resulting stream for + * additional fields. See: + * + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/10ef9ada-cba2-4384-ab60-7b6290ed4a9a + * + * @param device + * The device that completed the operation requested by a prior I/O + * request. + * + * @param completion_id + * The completion ID of the I/O request that requested the operation. + * + * @param status + * An NTSTATUS code describing the success/failure of the operation that + * was completed. + * + * @param size + * The number of additional bytes to reserve at the end of the resulting + * stream for additional fields to be appended. + * + * @return + * A new wStream containing an I/O completion header, followed by the + * requested additional free space. */ wStream* guac_rdpdr_new_io_completion(guac_rdpdr_device* device, int completion_id, int status, int size); From 6940875e6e16c6e4034b2c59a8748a1ac1bca305 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 29 Dec 2019 17:55:15 -0800 Subject: [PATCH 065/109] GUACAMOLE-249: Refactor away old stream.h and guac_rdp_stream. --- src/protocols/rdp/Makefile.am | 8 +- .../rdpdr/rdpdr-fs-messages-file-info.c | 3 +- .../rdp/channels/rdpdr/rdpdr-fs-messages.c | 3 +- src/protocols/rdp/channels/rdpdr/rdpdr.c | 94 ---- src/protocols/rdp/channels/rdpdr/rdpdr.h | 6 - src/protocols/rdp/download.c | 242 +++++++++ src/protocols/rdp/download.h | 70 +++ src/protocols/rdp/fs.c | 3 +- src/protocols/rdp/ls.c | 127 +++++ src/protocols/rdp/ls.h | 66 +++ src/protocols/rdp/rdp.c | 1 - src/protocols/rdp/stream.c | 479 ------------------ src/protocols/rdp/stream.h | 184 ------- src/protocols/rdp/upload.c | 241 +++++++++ src/protocols/rdp/upload.h | 73 +++ src/protocols/rdp/user.c | 2 +- 16 files changed, 832 insertions(+), 770 deletions(-) create mode 100644 src/protocols/rdp/download.c create mode 100644 src/protocols/rdp/download.h create mode 100644 src/protocols/rdp/ls.c create mode 100644 src/protocols/rdp/ls.h delete mode 100644 src/protocols/rdp/stream.c delete mode 100644 src/protocols/rdp/stream.h create mode 100644 src/protocols/rdp/upload.c create mode 100644 src/protocols/rdp/upload.h diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index 3ba1da05..19c81c2e 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -57,6 +57,7 @@ libguac_client_rdp_la_SOURCES = \ channels/rdpsnd/rdpsnd.c \ client.c \ color.c \ + download.c \ error.c \ fs.c \ gdi.c \ @@ -65,6 +66,7 @@ libguac_client_rdp_la_SOURCES = \ keyboard/decompose.c \ keyboard/keyboard.c \ keyboard/keymap.c \ + ls.c \ plugins/channels.c \ plugins/ptr-string.c \ pointer.c \ @@ -72,8 +74,8 @@ libguac_client_rdp_la_SOURCES = \ rdp.c \ resolution.c \ settings.c \ - stream.c \ unicode.c \ + upload.c \ user.c noinst_HEADERS = \ @@ -96,6 +98,7 @@ noinst_HEADERS = \ channels/rdpsnd/rdpsnd.h \ client.h \ color.h \ + download.h \ error.h \ fs.h \ gdi.h \ @@ -104,6 +107,7 @@ noinst_HEADERS = \ keyboard/decompose.h \ keyboard/keyboard.h \ keyboard/keymap.h \ + ls.h \ plugins/channels.h \ plugins/guacai/guacai-messages.h \ plugins/guacai/guacai.h \ @@ -113,8 +117,8 @@ noinst_HEADERS = \ rdp.h \ resolution.h \ settings.h \ - stream.h \ unicode.h \ + upload.h \ user.h libguac_client_rdp_la_CFLAGS = \ diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.c index 509087b8..0e4f66f0 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.c @@ -20,6 +20,7 @@ #include "config.h" #include "channels/rdpdr/rdpdr-fs-messages-file-info.h" #include "channels/rdpdr/rdpdr.h" +#include "download.h" #include "fs.h" #include "unicode.h" @@ -158,7 +159,7 @@ void guac_rdpdr_fs_process_set_rename_info(guac_rdp_common_svc* svc, return; /* Initiate download, pretend move succeeded */ - guac_rdpdr_start_download(svc, device, file->absolute_path); + guac_client_for_owner(svc->client, guac_rdp_download_to_user, file->absolute_path); output_stream = guac_rdpdr_new_io_completion(device, iorequest->completion_id, STATUS_SUCCESS, 4); diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c index 4fede57a..8475ce94 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c @@ -24,6 +24,7 @@ #include "channels/rdpdr/rdpdr-fs-messages.h" #include "channels/rdpdr/rdpdr-messages.h" #include "channels/rdpdr/rdpdr.h" +#include "download.h" #include "fs.h" #include "unicode.h" @@ -224,7 +225,7 @@ void guac_rdpdr_fs_process_close(guac_rdp_common_svc* svc, /* If file was written to, and it's in the \Download folder, start stream */ if (file->bytes_written > 0 && strncmp(file->absolute_path, "\\Download\\", 10) == 0) { - guac_rdpdr_start_download(svc, device, file->absolute_path); + guac_client_for_owner(svc->client, guac_rdp_download_to_user, file->absolute_path); guac_rdp_fs_delete((guac_rdp_fs*) device->data, iorequest->file_id); } diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr.c b/src/protocols/rdp/channels/rdpdr/rdpdr.c index 39da918d..d0d3143e 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr.c @@ -26,7 +26,6 @@ #include "plugins/channels.h" #include "rdp.h" #include "settings.h" -#include "stream.h" #include #include @@ -135,99 +134,6 @@ wStream* guac_rdpdr_new_io_completion(guac_rdpdr_device* device, } -/** - * Callback invoked on the current connection owner (if any) when a file - * download is being initiated using the magic "Download" folder. - * - * @param owner - * The guac_user that is the owner of the connection, or NULL if the - * connection owner has left. - * - * @param data - * The full absolute path to the file that should be downloaded. - * - * @return - * The stream allocated for the file download, or NULL if the download has - * failed to start. - */ -static void* guac_rdpdr_download_to_owner(guac_user* owner, void* data) { - - /* Do not bother attempting the download if the owner has left */ - if (owner == NULL) - return NULL; - - guac_client* client = owner->client; - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - guac_rdp_fs* filesystem = rdp_client->filesystem; - - /* Ignore download if filesystem has been unloaded */ - if (filesystem == NULL) - return NULL; - - /* Attempt to open requested file */ - char* path = (char*) data; - int file_id = guac_rdp_fs_open(filesystem, path, - FILE_READ_DATA, 0, FILE_OPEN, 0); - - /* If file opened successfully, start stream */ - if (file_id >= 0) { - - guac_rdp_stream* rdp_stream; - const char* basename; - - int i; - char c; - - /* Associate stream with transfer status */ - guac_stream* stream = guac_user_alloc_stream(owner); - stream->data = rdp_stream = malloc(sizeof(guac_rdp_stream)); - stream->ack_handler = guac_rdp_download_ack_handler; - rdp_stream->type = GUAC_RDP_DOWNLOAD_STREAM; - rdp_stream->download_status.file_id = file_id; - rdp_stream->download_status.offset = 0; - - /* Get basename from absolute path */ - i=0; - basename = path; - do { - - c = path[i]; - if (c == '/' || c == '\\') - basename = &(path[i+1]); - - i++; - - } while (c != '\0'); - - guac_user_log(owner, GUAC_LOG_DEBUG, "%s: Initiating download " - "of \"%s\"", __func__, path); - - /* Begin stream */ - guac_protocol_send_file(owner->socket, stream, - "application/octet-stream", basename); - guac_socket_flush(owner->socket); - - /* Download started successfully */ - return stream; - - } - - /* Download failed */ - guac_user_log(owner, GUAC_LOG_ERROR, "Unable to download \"%s\"", path); - return NULL; - -} - -void guac_rdpdr_start_download(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, char* path) { - - guac_client* client = svc->client; - - /* Initiate download to the owner of the connection */ - guac_client_for_owner(client, guac_rdpdr_download_to_owner, path); - -} - void guac_rdpdr_process_connect(guac_rdp_common_svc* svc) { /* Get data from client */ diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr.h b/src/protocols/rdp/channels/rdpdr/rdpdr.h index 19f178d0..fc494ee1 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr.h @@ -212,12 +212,6 @@ typedef struct guac_rdpdr { wStream* guac_rdpdr_new_io_completion(guac_rdpdr_device* device, int completion_id, int status, int size); -/** - * Begins streaming the given file to the user via a Guacamole file stream. - */ -void guac_rdpdr_start_download(guac_rdp_common_svc* svc, - guac_rdpdr_device* device, char* path); - /** * Initializes device redirection support (file transfer, printing, etc.) for * RDP and handling of the RDPDR channel. If failures occur, messages noting diff --git a/src/protocols/rdp/download.c b/src/protocols/rdp/download.c new file mode 100644 index 00000000..34f7e2e6 --- /dev/null +++ b/src/protocols/rdp/download.c @@ -0,0 +1,242 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#include "config.h" +#include "client.h" +#include "download.h" +#include "fs.h" +#include "ls.h" +#include "rdp.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +int guac_rdp_download_ack_handler(guac_user* user, guac_stream* stream, + char* message, guac_protocol_status status) { + + guac_client* client = user->client; + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + guac_rdp_download_status* download_status = (guac_rdp_download_status*) stream->data; + + /* Get filesystem, return error if no filesystem */ + guac_rdp_fs* fs = rdp_client->filesystem; + if (fs == NULL) { + guac_protocol_send_ack(user->socket, stream, "FAIL (NO FS)", + GUAC_PROTOCOL_STATUS_SERVER_ERROR); + guac_socket_flush(user->socket); + return 0; + } + + /* If successful, read data */ + if (status == GUAC_PROTOCOL_STATUS_SUCCESS) { + + /* Attempt read into buffer */ + char buffer[4096]; + int bytes_read = guac_rdp_fs_read(fs, + download_status->file_id, + download_status->offset, buffer, sizeof(buffer)); + + /* If bytes read, send as blob */ + if (bytes_read > 0) { + download_status->offset += bytes_read; + guac_protocol_send_blob(user->socket, stream, + buffer, bytes_read); + } + + /* If EOF, send end */ + else if (bytes_read == 0) { + guac_protocol_send_end(user->socket, stream); + guac_user_free_stream(user, stream); + free(download_status); + } + + /* Otherwise, fail stream */ + else { + guac_user_log(user, GUAC_LOG_ERROR, + "Error reading file for download"); + guac_protocol_send_end(user->socket, stream); + guac_user_free_stream(user, stream); + free(download_status); + } + + guac_socket_flush(user->socket); + + } + + /* Otherwise, return stream to user */ + else + guac_user_free_stream(user, stream); + + return 0; + +} + +int guac_rdp_download_get_handler(guac_user* user, guac_object* object, + char* name) { + + guac_client* client = user->client; + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + + /* Get filesystem, ignore request if no filesystem */ + guac_rdp_fs* fs = rdp_client->filesystem; + if (fs == NULL) + return 0; + + /* Attempt to open file for reading */ + int file_id = guac_rdp_fs_open(fs, name, GENERIC_READ, 0, FILE_OPEN, 0); + if (file_id < 0) { + guac_user_log(user, GUAC_LOG_INFO, "Unable to read file \"%s\"", + name); + return 0; + } + + /* Get opened file */ + guac_rdp_fs_file* file = guac_rdp_fs_get_file(fs, file_id); + if (file == NULL) { + guac_client_log(fs->client, GUAC_LOG_DEBUG, + "%s: Successful open produced bad file_id: %i", + __func__, file_id); + return 0; + } + + /* If directory, send contents of directory */ + if (file->attributes & FILE_ATTRIBUTE_DIRECTORY) { + + /* Create stream data */ + guac_rdp_ls_status* ls_status = malloc(sizeof(guac_rdp_ls_status)); + ls_status->fs = fs; + ls_status->file_id = file_id; + guac_strlcpy(ls_status->directory_name, name, + sizeof(ls_status->directory_name)); + + /* Allocate stream for body */ + guac_stream* stream = guac_user_alloc_stream(user); + stream->ack_handler = guac_rdp_ls_ack_handler; + stream->data = ls_status; + + /* Init JSON object state */ + guac_common_json_begin_object(user, stream, + &ls_status->json_state); + + /* Associate new stream with get request */ + guac_protocol_send_body(user->socket, object, stream, + GUAC_USER_STREAM_INDEX_MIMETYPE, name); + + } + + /* Otherwise, send file contents */ + else { + + /* Create stream data */ + guac_rdp_download_status* download_status = malloc(sizeof(guac_rdp_download_status)); + download_status->file_id = file_id; + download_status->offset = 0; + + /* Allocate stream for body */ + guac_stream* stream = guac_user_alloc_stream(user); + stream->data = download_status; + stream->ack_handler = guac_rdp_download_ack_handler; + + /* Associate new stream with get request */ + guac_protocol_send_body(user->socket, object, stream, + "application/octet-stream", name); + + } + + guac_socket_flush(user->socket); + return 0; +} + +void* guac_rdp_download_to_user(guac_user* user, void* data) { + + /* Do not bother attempting the download if the user has left */ + if (user == NULL) + return NULL; + + guac_client* client = user->client; + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + guac_rdp_fs* filesystem = rdp_client->filesystem; + + /* Ignore download if filesystem has been unloaded */ + if (filesystem == NULL) + return NULL; + + /* Attempt to open requested file */ + char* path = (char*) data; + int file_id = guac_rdp_fs_open(filesystem, path, + FILE_READ_DATA, 0, FILE_OPEN, 0); + + /* If file opened successfully, start stream */ + if (file_id >= 0) { + + guac_rdp_download_status* download_status; + const char* basename; + + int i; + char c; + + /* Associate stream with transfer status */ + guac_stream* stream = guac_user_alloc_stream(user); + stream->data = download_status = malloc(sizeof(guac_rdp_download_status)); + stream->ack_handler = guac_rdp_download_ack_handler; + download_status->file_id = file_id; + download_status->offset = 0; + + /* Get basename from absolute path */ + i=0; + basename = path; + do { + + c = path[i]; + if (c == '/' || c == '\\') + basename = &(path[i+1]); + + i++; + + } while (c != '\0'); + + guac_user_log(user, GUAC_LOG_DEBUG, "%s: Initiating download " + "of \"%s\"", __func__, path); + + /* Begin stream */ + guac_protocol_send_file(user->socket, stream, + "application/octet-stream", basename); + guac_socket_flush(user->socket); + + /* Download started successfully */ + return stream; + + } + + /* Download failed */ + guac_user_log(user, GUAC_LOG_ERROR, "Unable to download \"%s\"", path); + return NULL; + +} + diff --git a/src/protocols/rdp/download.h b/src/protocols/rdp/download.h new file mode 100644 index 00000000..c15dba67 --- /dev/null +++ b/src/protocols/rdp/download.h @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#ifndef GUAC_RDP_DOWNLOAD_H +#define GUAC_RDP_DOWNLOAD_H + +#include "config.h" +#include "common/json.h" + +#include +#include +#include + +#include + +/** + * The transfer status of a file being downloaded. + */ +typedef struct guac_rdp_download_status { + + /** + * The file ID of the file being downloaded. + */ + int file_id; + + /** + * The current position within the file. + */ + uint64_t offset; + +} guac_rdp_download_status; + +/** + * Handler for acknowledgements of receipt of data related to file downloads. + */ +guac_user_ack_handler guac_rdp_download_ack_handler; + +/** + * Handler for get messages. In context of downloads and the filesystem exposed + * via the Guacamole protocol, get messages request the body of a file within + * the filesystem. + */ +guac_user_get_handler guac_rdp_download_get_handler; + +/** + * Callback for guac_client_for_user() and similar functions which initiates a + * file download to a specific user if that user is still connected. The path + * for the file to be downloaded must be passed as the arbitrary data parameter + * for the function invoking this callback. + */ +guac_user_callback guac_rdp_download_to_user; + +#endif + diff --git a/src/protocols/rdp/fs.c b/src/protocols/rdp/fs.c index 7dd3ea7a..8b48b945 100644 --- a/src/protocols/rdp/fs.c +++ b/src/protocols/rdp/fs.c @@ -19,8 +19,9 @@ #include "config.h" +#include "download.h" #include "fs.h" -#include "stream.h" +#include "upload.h" #include #include diff --git a/src/protocols/rdp/ls.c b/src/protocols/rdp/ls.c new file mode 100644 index 00000000..f008da90 --- /dev/null +++ b/src/protocols/rdp/ls.c @@ -0,0 +1,127 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#include "config.h" +#include "client.h" +#include "fs.h" +#include "ls.h" +#include "rdp.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +int guac_rdp_ls_ack_handler(guac_user* user, guac_stream* stream, + char* message, guac_protocol_status status) { + + int blob_written = 0; + const char* filename; + + guac_rdp_ls_status* ls_status = (guac_rdp_ls_status*) stream->data; + + /* If unsuccessful, free stream and abort */ + if (status != GUAC_PROTOCOL_STATUS_SUCCESS) { + guac_rdp_fs_close(ls_status->fs, ls_status->file_id); + guac_user_free_stream(user, stream); + free(ls_status); + return 0; + } + + /* While directory entries remain */ + while ((filename = guac_rdp_fs_read_dir(ls_status->fs, + ls_status->file_id)) != NULL + && !blob_written) { + + char absolute_path[GUAC_RDP_FS_MAX_PATH]; + + /* Skip current and parent directory entries */ + if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0) + continue; + + /* Concatenate into absolute path - skip if invalid */ + if (!guac_rdp_fs_append_filename(absolute_path, + ls_status->directory_name, filename)) { + + guac_user_log(user, GUAC_LOG_DEBUG, + "Skipping filename \"%s\" - filename is invalid or " + "resulting path is too long", filename); + + continue; + } + + /* Attempt to open file to determine type */ + int file_id = guac_rdp_fs_open(ls_status->fs, absolute_path, + GENERIC_READ, 0, FILE_OPEN, 0); + if (file_id < 0) + continue; + + /* Get opened file */ + guac_rdp_fs_file* file = guac_rdp_fs_get_file(ls_status->fs, file_id); + if (file == NULL) { + guac_user_log(user, GUAC_LOG_DEBUG, "%s: Successful open produced " + "bad file_id: %i", __func__, file_id); + return 0; + } + + /* Determine mimetype */ + const char* mimetype; + if (file->attributes & FILE_ATTRIBUTE_DIRECTORY) + mimetype = GUAC_USER_STREAM_INDEX_MIMETYPE; + else + mimetype = "application/octet-stream"; + + /* Write entry */ + blob_written |= guac_common_json_write_property(user, stream, + &ls_status->json_state, absolute_path, mimetype); + + guac_rdp_fs_close(ls_status->fs, file_id); + + } + + /* Complete JSON and cleanup at end of directory */ + if (filename == NULL) { + + /* Complete JSON object */ + guac_common_json_end_object(user, stream, &ls_status->json_state); + guac_common_json_flush(user, stream, &ls_status->json_state); + + /* Clean up resources */ + guac_rdp_fs_close(ls_status->fs, ls_status->file_id); + free(ls_status); + + /* Signal of stream */ + guac_protocol_send_end(user->socket, stream); + guac_user_free_stream(user, stream); + + } + + guac_socket_flush(user->socket); + return 0; + +} + diff --git a/src/protocols/rdp/ls.h b/src/protocols/rdp/ls.h new file mode 100644 index 00000000..21a2eb85 --- /dev/null +++ b/src/protocols/rdp/ls.h @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#ifndef GUAC_RDP_LS_H +#define GUAC_RDP_LS_H + +#include "config.h" +#include "common/json.h" + +#include +#include +#include + +#include + +/** + * The current state of a directory listing operation. + */ +typedef struct guac_rdp_ls_status { + + /** + * The filesystem associated with the directory being listed. + */ + guac_rdp_fs* fs; + + /** + * The file ID of the directory being listed. + */ + int file_id; + + /** + * The absolute path of the directory being listed. + */ + char directory_name[GUAC_RDP_FS_MAX_PATH]; + + /** + * The current state of the JSON directory object being written. + */ + guac_common_json_state json_state; + +} guac_rdp_ls_status; + +/** + * Handler for ack messages received due to receipt of a "body" or "blob" + * instruction associated with a directory list operation. + */ +guac_user_ack_handler guac_rdp_ls_ack_handler; + +#endif + diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 7e91ef11..5a6fb875 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -39,7 +39,6 @@ #include "pointer.h" #include "print-job.h" #include "rdp.h" -#include "stream.h" #ifdef ENABLE_COMMON_SSH #include "common-ssh/sftp.h" diff --git a/src/protocols/rdp/stream.c b/src/protocols/rdp/stream.c deleted file mode 100644 index 71fd0357..00000000 --- a/src/protocols/rdp/stream.c +++ /dev/null @@ -1,479 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -#include "config.h" -#include "client.h" -#include "fs.h" -#include "rdp.h" -#include "stream.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/** - * Writes the given filename to the given upload path, sanitizing the filename - * and translating the filename to the root directory. - * - * @param filename - * The filename to sanitize and move to the root directory. - * - * @param path - * A pointer to a buffer which should receive the sanitized path. The - * buffer must hav at least GUAC_RDP_FS_MAX_PATH bytes available. - */ -static void __generate_upload_path(const char* filename, char* path) { - - int i; - - /* Add initial backslash */ - *(path++) = '\\'; - - for (i=1; iclient; - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - - int file_id; - guac_rdp_stream* rdp_stream; - char file_path[GUAC_RDP_FS_MAX_PATH]; - - /* Get filesystem, return error if no filesystem */ - guac_rdp_fs* fs = rdp_client->filesystem; - if (fs == NULL) { - guac_protocol_send_ack(user->socket, stream, "FAIL (NO FS)", - GUAC_PROTOCOL_STATUS_SERVER_ERROR); - guac_socket_flush(user->socket); - return 0; - } - - /* Translate name */ - __generate_upload_path(filename, file_path); - - /* Open file */ - file_id = guac_rdp_fs_open(fs, file_path, GENERIC_WRITE, 0, - FILE_OVERWRITE_IF, 0); - if (file_id < 0) { - guac_protocol_send_ack(user->socket, stream, "FAIL (CANNOT OPEN)", - GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN); - guac_socket_flush(user->socket); - return 0; - } - - /* Init upload status */ - rdp_stream = malloc(sizeof(guac_rdp_stream)); - rdp_stream->type = GUAC_RDP_UPLOAD_STREAM; - rdp_stream->upload_status.offset = 0; - rdp_stream->upload_status.file_id = file_id; - stream->data = rdp_stream; - stream->blob_handler = guac_rdp_upload_blob_handler; - stream->end_handler = guac_rdp_upload_end_handler; - - guac_protocol_send_ack(user->socket, stream, "OK (STREAM BEGIN)", - GUAC_PROTOCOL_STATUS_SUCCESS); - guac_socket_flush(user->socket); - return 0; - -} - -int guac_rdp_upload_blob_handler(guac_user* user, guac_stream* stream, - void* data, int length) { - - int bytes_written; - guac_rdp_stream* rdp_stream = (guac_rdp_stream*) stream->data; - - /* Get filesystem, return error if no filesystem 0*/ - guac_client* client = user->client; - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - guac_rdp_fs* fs = rdp_client->filesystem; - if (fs == NULL) { - guac_protocol_send_ack(user->socket, stream, "FAIL (NO FS)", - GUAC_PROTOCOL_STATUS_SERVER_ERROR); - guac_socket_flush(user->socket); - return 0; - } - - /* Write entire block */ - while (length > 0) { - - /* Attempt write */ - bytes_written = guac_rdp_fs_write(fs, - rdp_stream->upload_status.file_id, - rdp_stream->upload_status.offset, - data, length); - - /* On error, abort */ - if (bytes_written < 0) { - guac_protocol_send_ack(user->socket, stream, - "FAIL (BAD WRITE)", - GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN); - guac_socket_flush(user->socket); - return 0; - } - - /* Update counters */ - rdp_stream->upload_status.offset += bytes_written; - data += bytes_written; - length -= bytes_written; - - } - - guac_protocol_send_ack(user->socket, stream, "OK (DATA RECEIVED)", - GUAC_PROTOCOL_STATUS_SUCCESS); - guac_socket_flush(user->socket); - return 0; - -} - -int guac_rdp_upload_end_handler(guac_user* user, guac_stream* stream) { - - guac_client* client = user->client; - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - guac_rdp_stream* rdp_stream = (guac_rdp_stream*) stream->data; - - /* Get filesystem, return error if no filesystem */ - guac_rdp_fs* fs = rdp_client->filesystem; - if (fs == NULL) { - guac_protocol_send_ack(user->socket, stream, "FAIL (NO FS)", - GUAC_PROTOCOL_STATUS_SERVER_ERROR); - guac_socket_flush(user->socket); - return 0; - } - - /* Close file */ - guac_rdp_fs_close(fs, rdp_stream->upload_status.file_id); - - /* Acknowledge stream end */ - guac_protocol_send_ack(user->socket, stream, "OK (STREAM END)", - GUAC_PROTOCOL_STATUS_SUCCESS); - guac_socket_flush(user->socket); - - free(rdp_stream); - return 0; - -} - -int guac_rdp_download_ack_handler(guac_user* user, guac_stream* stream, - char* message, guac_protocol_status status) { - - guac_client* client = user->client; - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - guac_rdp_stream* rdp_stream = (guac_rdp_stream*) stream->data; - - /* Get filesystem, return error if no filesystem */ - guac_rdp_fs* fs = rdp_client->filesystem; - if (fs == NULL) { - guac_protocol_send_ack(user->socket, stream, "FAIL (NO FS)", - GUAC_PROTOCOL_STATUS_SERVER_ERROR); - guac_socket_flush(user->socket); - return 0; - } - - /* If successful, read data */ - if (status == GUAC_PROTOCOL_STATUS_SUCCESS) { - - /* Attempt read into buffer */ - char buffer[4096]; - int bytes_read = guac_rdp_fs_read(fs, - rdp_stream->download_status.file_id, - rdp_stream->download_status.offset, buffer, sizeof(buffer)); - - /* If bytes read, send as blob */ - if (bytes_read > 0) { - rdp_stream->download_status.offset += bytes_read; - guac_protocol_send_blob(user->socket, stream, - buffer, bytes_read); - } - - /* If EOF, send end */ - else if (bytes_read == 0) { - guac_protocol_send_end(user->socket, stream); - guac_user_free_stream(user, stream); - free(rdp_stream); - } - - /* Otherwise, fail stream */ - else { - guac_user_log(user, GUAC_LOG_ERROR, - "Error reading file for download"); - guac_protocol_send_end(user->socket, stream); - guac_user_free_stream(user, stream); - free(rdp_stream); - } - - guac_socket_flush(user->socket); - - } - - /* Otherwise, return stream to user */ - else - guac_user_free_stream(user, stream); - - return 0; - -} - -int guac_rdp_ls_ack_handler(guac_user* user, guac_stream* stream, - char* message, guac_protocol_status status) { - - int blob_written = 0; - const char* filename; - - guac_rdp_stream* rdp_stream = (guac_rdp_stream*) stream->data; - - /* If unsuccessful, free stream and abort */ - if (status != GUAC_PROTOCOL_STATUS_SUCCESS) { - guac_rdp_fs_close(rdp_stream->ls_status.fs, - rdp_stream->ls_status.file_id); - guac_user_free_stream(user, stream); - free(rdp_stream); - return 0; - } - - /* While directory entries remain */ - while ((filename = guac_rdp_fs_read_dir(rdp_stream->ls_status.fs, - rdp_stream->ls_status.file_id)) != NULL - && !blob_written) { - - char absolute_path[GUAC_RDP_FS_MAX_PATH]; - - /* Skip current and parent directory entries */ - if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0) - continue; - - /* Concatenate into absolute path - skip if invalid */ - if (!guac_rdp_fs_append_filename(absolute_path, - rdp_stream->ls_status.directory_name, filename)) { - - guac_user_log(user, GUAC_LOG_DEBUG, - "Skipping filename \"%s\" - filename is invalid or " - "resulting path is too long", filename); - - continue; - } - - /* Attempt to open file to determine type */ - int file_id = guac_rdp_fs_open(rdp_stream->ls_status.fs, absolute_path, - GENERIC_READ, 0, FILE_OPEN, 0); - if (file_id < 0) - continue; - - /* Get opened file */ - guac_rdp_fs_file* file = guac_rdp_fs_get_file(rdp_stream->ls_status.fs, - file_id); - if (file == NULL) { - guac_client_log(rdp_stream->ls_status.fs->client, GUAC_LOG_DEBUG, - "%s: Successful open produced bad file_id: %i", - __func__, file_id); - return 0; - } - - /* Determine mimetype */ - const char* mimetype; - if (file->attributes & FILE_ATTRIBUTE_DIRECTORY) - mimetype = GUAC_USER_STREAM_INDEX_MIMETYPE; - else - mimetype = "application/octet-stream"; - - /* Write entry */ - blob_written |= guac_common_json_write_property(user, stream, - &rdp_stream->ls_status.json_state, absolute_path, mimetype); - - guac_rdp_fs_close(rdp_stream->ls_status.fs, file_id); - - } - - /* Complete JSON and cleanup at end of directory */ - if (filename == NULL) { - - /* Complete JSON object */ - guac_common_json_end_object(user, stream, - &rdp_stream->ls_status.json_state); - guac_common_json_flush(user, stream, - &rdp_stream->ls_status.json_state); - - /* Clean up resources */ - guac_rdp_fs_close(rdp_stream->ls_status.fs, - rdp_stream->ls_status.file_id); - free(rdp_stream); - - /* Signal of stream */ - guac_protocol_send_end(user->socket, stream); - guac_user_free_stream(user, stream); - - } - - guac_socket_flush(user->socket); - return 0; - -} - -int guac_rdp_download_get_handler(guac_user* user, guac_object* object, - char* name) { - - guac_client* client = user->client; - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - - /* Get filesystem, ignore request if no filesystem */ - guac_rdp_fs* fs = rdp_client->filesystem; - if (fs == NULL) - return 0; - - /* Attempt to open file for reading */ - int file_id = guac_rdp_fs_open(fs, name, GENERIC_READ, 0, FILE_OPEN, 0); - if (file_id < 0) { - guac_user_log(user, GUAC_LOG_INFO, "Unable to read file \"%s\"", - name); - return 0; - } - - /* Get opened file */ - guac_rdp_fs_file* file = guac_rdp_fs_get_file(fs, file_id); - if (file == NULL) { - guac_client_log(fs->client, GUAC_LOG_DEBUG, - "%s: Successful open produced bad file_id: %i", - __func__, file_id); - return 0; - } - - /* If directory, send contents of directory */ - if (file->attributes & FILE_ATTRIBUTE_DIRECTORY) { - - /* Create stream data */ - guac_rdp_stream* rdp_stream = malloc(sizeof(guac_rdp_stream)); - rdp_stream->type = GUAC_RDP_LS_STREAM; - rdp_stream->ls_status.fs = fs; - rdp_stream->ls_status.file_id = file_id; - guac_strlcpy(rdp_stream->ls_status.directory_name, name, - sizeof(rdp_stream->ls_status.directory_name)); - - /* Allocate stream for body */ - guac_stream* stream = guac_user_alloc_stream(user); - stream->ack_handler = guac_rdp_ls_ack_handler; - stream->data = rdp_stream; - - /* Init JSON object state */ - guac_common_json_begin_object(user, stream, - &rdp_stream->ls_status.json_state); - - /* Associate new stream with get request */ - guac_protocol_send_body(user->socket, object, stream, - GUAC_USER_STREAM_INDEX_MIMETYPE, name); - - } - - /* Otherwise, send file contents */ - else { - - /* Create stream data */ - guac_rdp_stream* rdp_stream = malloc(sizeof(guac_rdp_stream)); - rdp_stream->type = GUAC_RDP_DOWNLOAD_STREAM; - rdp_stream->download_status.file_id = file_id; - rdp_stream->download_status.offset = 0; - - /* Allocate stream for body */ - guac_stream* stream = guac_user_alloc_stream(user); - stream->data = rdp_stream; - stream->ack_handler = guac_rdp_download_ack_handler; - - /* Associate new stream with get request */ - guac_protocol_send_body(user->socket, object, stream, - "application/octet-stream", name); - - } - - guac_socket_flush(user->socket); - return 0; -} - -int guac_rdp_upload_put_handler(guac_user* user, guac_object* object, - guac_stream* stream, char* mimetype, char* name) { - - guac_client* client = user->client; - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - - /* Get filesystem, return error if no filesystem */ - guac_rdp_fs* fs = rdp_client->filesystem; - if (fs == NULL) { - guac_protocol_send_ack(user->socket, stream, "FAIL (NO FS)", - GUAC_PROTOCOL_STATUS_SERVER_ERROR); - guac_socket_flush(user->socket); - return 0; - } - - /* Open file */ - int file_id = guac_rdp_fs_open(fs, name, GENERIC_WRITE, 0, - FILE_OVERWRITE_IF, 0); - - /* Abort on failure */ - if (file_id < 0) { - guac_protocol_send_ack(user->socket, stream, "FAIL (CANNOT OPEN)", - GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN); - guac_socket_flush(user->socket); - return 0; - } - - /* Init upload stream data */ - guac_rdp_stream* rdp_stream = malloc(sizeof(guac_rdp_stream)); - rdp_stream->type = GUAC_RDP_UPLOAD_STREAM; - rdp_stream->upload_status.offset = 0; - rdp_stream->upload_status.file_id = file_id; - - /* Allocate stream, init for file upload */ - stream->data = rdp_stream; - stream->blob_handler = guac_rdp_upload_blob_handler; - stream->end_handler = guac_rdp_upload_end_handler; - - /* Acknowledge stream creation */ - guac_protocol_send_ack(user->socket, stream, "OK (STREAM BEGIN)", - GUAC_PROTOCOL_STATUS_SUCCESS); - guac_socket_flush(user->socket); - return 0; -} - diff --git a/src/protocols/rdp/stream.h b/src/protocols/rdp/stream.h deleted file mode 100644 index 3317c6cb..00000000 --- a/src/protocols/rdp/stream.h +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -#ifndef GUAC_RDP_STREAM_H -#define GUAC_RDP_STREAM_H - -#include "config.h" -#include "common/json.h" - -#include -#include -#include - -#include - -/** - * The transfer status of a file being downloaded. - */ -typedef struct guac_rdp_download_status { - - /** - * The file ID of the file being downloaded. - */ - int file_id; - - /** - * The current position within the file. - */ - uint64_t offset; - -} guac_rdp_download_status; - -/** - * Structure which represents the current state of an upload. - */ -typedef struct guac_rdp_upload_status { - - /** - * The overall offset within the file that the next write should - * occur at. - */ - int offset; - - /** - * The ID of the file being written to. - */ - int file_id; - -} guac_rdp_upload_status; - -/** - * The current state of a directory listing operation. - */ -typedef struct guac_rdp_ls_status { - - /** - * The filesystem associated with the directory being listed. - */ - guac_rdp_fs* fs; - - /** - * The file ID of the directory being listed. - */ - int file_id; - - /** - * The absolute path of the directory being listed. - */ - char directory_name[GUAC_RDP_FS_MAX_PATH]; - - /** - * The current state of the JSON directory object being written. - */ - guac_common_json_state json_state; - -} guac_rdp_ls_status; - -/** - * All available stream types. - */ -typedef enum guac_rdp_stream_type { - - /** - * An in-progress file upload. - */ - GUAC_RDP_UPLOAD_STREAM, - - /** - * An in-progress file download. - */ - GUAC_RDP_DOWNLOAD_STREAM, - - /** - * An in-progress stream of a directory listing. - */ - GUAC_RDP_LS_STREAM - -} guac_rdp_stream_type; - -/** - * Variable-typed stream data. - */ -typedef struct guac_rdp_stream { - - /** - * The type of this stream. - */ - guac_rdp_stream_type type; - - /** - * The file upload status. Only valid for GUAC_RDP_UPLOAD_STREAM. - */ - guac_rdp_upload_status upload_status; - - /** - * The file upload status. Only valid for GUAC_RDP_DOWNLOAD_STREAM. - */ - guac_rdp_download_status download_status; - - /** - * The directory list status. Only valid for GUAC_RDP_LS_STREAM. - */ - guac_rdp_ls_status ls_status; - -} guac_rdp_stream; - -/** - * Handler for inbound files related to file uploads. - */ -guac_user_file_handler guac_rdp_upload_file_handler; - -/** - * Handler for stream data related to file uploads. - */ -guac_user_blob_handler guac_rdp_upload_blob_handler; - -/** - * Handler for end-of-stream related to file uploads. - */ -guac_user_end_handler guac_rdp_upload_end_handler; - -/** - * Handler for acknowledgements of receipt of data related to file downloads. - */ -guac_user_ack_handler guac_rdp_download_ack_handler; - -/** - * Handler for ack messages received due to receipt of a "body" or "blob" - * instruction associated with a directory list operation. - */ -guac_user_ack_handler guac_rdp_ls_ack_handler; - -/** - * Handler for get messages. In context of downloads and the filesystem exposed - * via the Guacamole protocol, get messages request the body of a file within - * the filesystem. - */ -guac_user_get_handler guac_rdp_download_get_handler; - -/** - * Handler for put messages. In context of uploads and the filesystem exposed - * via the Guacamole protocol, put messages request write access to a file - * within the filesystem. - */ -guac_user_put_handler guac_rdp_upload_put_handler; - -#endif - diff --git a/src/protocols/rdp/upload.c b/src/protocols/rdp/upload.c new file mode 100644 index 00000000..24295ec5 --- /dev/null +++ b/src/protocols/rdp/upload.c @@ -0,0 +1,241 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#include "config.h" +#include "client.h" +#include "fs.h" +#include "rdp.h" +#include "upload.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/** + * Writes the given filename to the given upload path, sanitizing the filename + * and translating the filename to the root directory. + * + * @param filename + * The filename to sanitize and move to the root directory. + * + * @param path + * A pointer to a buffer which should receive the sanitized path. The + * buffer must hav at least GUAC_RDP_FS_MAX_PATH bytes available. + */ +static void __generate_upload_path(const char* filename, char* path) { + + int i; + + /* Add initial backslash */ + *(path++) = '\\'; + + for (i=1; iclient; + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + + int file_id; + char file_path[GUAC_RDP_FS_MAX_PATH]; + + /* Get filesystem, return error if no filesystem */ + guac_rdp_fs* fs = rdp_client->filesystem; + if (fs == NULL) { + guac_protocol_send_ack(user->socket, stream, "FAIL (NO FS)", + GUAC_PROTOCOL_STATUS_SERVER_ERROR); + guac_socket_flush(user->socket); + return 0; + } + + /* Translate name */ + __generate_upload_path(filename, file_path); + + /* Open file */ + file_id = guac_rdp_fs_open(fs, file_path, GENERIC_WRITE, 0, + FILE_OVERWRITE_IF, 0); + if (file_id < 0) { + guac_protocol_send_ack(user->socket, stream, "FAIL (CANNOT OPEN)", + GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN); + guac_socket_flush(user->socket); + return 0; + } + + /* Init upload status */ + guac_rdp_upload_status* upload_status = malloc(sizeof(guac_rdp_upload_status)); + upload_status->offset = 0; + upload_status->file_id = file_id; + stream->data = upload_status; + stream->blob_handler = guac_rdp_upload_blob_handler; + stream->end_handler = guac_rdp_upload_end_handler; + + guac_protocol_send_ack(user->socket, stream, "OK (STREAM BEGIN)", + GUAC_PROTOCOL_STATUS_SUCCESS); + guac_socket_flush(user->socket); + return 0; + +} + +int guac_rdp_upload_blob_handler(guac_user* user, guac_stream* stream, + void* data, int length) { + + int bytes_written; + guac_rdp_upload_status* upload_status = (guac_rdp_upload_status*) stream->data; + + /* Get filesystem, return error if no filesystem 0*/ + guac_client* client = user->client; + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + guac_rdp_fs* fs = rdp_client->filesystem; + if (fs == NULL) { + guac_protocol_send_ack(user->socket, stream, "FAIL (NO FS)", + GUAC_PROTOCOL_STATUS_SERVER_ERROR); + guac_socket_flush(user->socket); + return 0; + } + + /* Write entire block */ + while (length > 0) { + + /* Attempt write */ + bytes_written = guac_rdp_fs_write(fs, upload_status->file_id, + upload_status->offset, data, length); + + /* On error, abort */ + if (bytes_written < 0) { + guac_protocol_send_ack(user->socket, stream, + "FAIL (BAD WRITE)", + GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN); + guac_socket_flush(user->socket); + return 0; + } + + /* Update counters */ + upload_status->offset += bytes_written; + data += bytes_written; + length -= bytes_written; + + } + + guac_protocol_send_ack(user->socket, stream, "OK (DATA RECEIVED)", + GUAC_PROTOCOL_STATUS_SUCCESS); + guac_socket_flush(user->socket); + return 0; + +} + +int guac_rdp_upload_end_handler(guac_user* user, guac_stream* stream) { + + guac_client* client = user->client; + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + guac_rdp_upload_status* upload_status = (guac_rdp_upload_status*) stream->data; + + /* Get filesystem, return error if no filesystem */ + guac_rdp_fs* fs = rdp_client->filesystem; + if (fs == NULL) { + guac_protocol_send_ack(user->socket, stream, "FAIL (NO FS)", + GUAC_PROTOCOL_STATUS_SERVER_ERROR); + guac_socket_flush(user->socket); + return 0; + } + + /* Close file */ + guac_rdp_fs_close(fs, upload_status->file_id); + + /* Acknowledge stream end */ + guac_protocol_send_ack(user->socket, stream, "OK (STREAM END)", + GUAC_PROTOCOL_STATUS_SUCCESS); + guac_socket_flush(user->socket); + + free(upload_status); + return 0; + +} + +int guac_rdp_upload_put_handler(guac_user* user, guac_object* object, + guac_stream* stream, char* mimetype, char* name) { + + guac_client* client = user->client; + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + + /* Get filesystem, return error if no filesystem */ + guac_rdp_fs* fs = rdp_client->filesystem; + if (fs == NULL) { + guac_protocol_send_ack(user->socket, stream, "FAIL (NO FS)", + GUAC_PROTOCOL_STATUS_SERVER_ERROR); + guac_socket_flush(user->socket); + return 0; + } + + /* Open file */ + int file_id = guac_rdp_fs_open(fs, name, GENERIC_WRITE, 0, + FILE_OVERWRITE_IF, 0); + + /* Abort on failure */ + if (file_id < 0) { + guac_protocol_send_ack(user->socket, stream, "FAIL (CANNOT OPEN)", + GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN); + guac_socket_flush(user->socket); + return 0; + } + + /* Init upload stream data */ + guac_rdp_upload_status* upload_status = malloc(sizeof(guac_rdp_upload_status)); + upload_status->offset = 0; + upload_status->file_id = file_id; + + /* Allocate stream, init for file upload */ + stream->data = upload_status; + stream->blob_handler = guac_rdp_upload_blob_handler; + stream->end_handler = guac_rdp_upload_end_handler; + + /* Acknowledge stream creation */ + guac_protocol_send_ack(user->socket, stream, "OK (STREAM BEGIN)", + GUAC_PROTOCOL_STATUS_SUCCESS); + guac_socket_flush(user->socket); + return 0; +} + diff --git a/src/protocols/rdp/upload.h b/src/protocols/rdp/upload.h new file mode 100644 index 00000000..b7563ffe --- /dev/null +++ b/src/protocols/rdp/upload.h @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#ifndef GUAC_RDP_UPLOAD_H +#define GUAC_RDP_UPLOAD_H + +#include "config.h" +#include "common/json.h" + +#include +#include +#include + +#include + +/** + * Structure which represents the current state of an upload. + */ +typedef struct guac_rdp_upload_status { + + /** + * The overall offset within the file that the next write should + * occur at. + */ + int offset; + + /** + * The ID of the file being written to. + */ + int file_id; + +} guac_rdp_upload_status; + +/** + * Handler for inbound files related to file uploads. + */ +guac_user_file_handler guac_rdp_upload_file_handler; + +/** + * Handler for stream data related to file uploads. + */ +guac_user_blob_handler guac_rdp_upload_blob_handler; + +/** + * Handler for end-of-stream related to file uploads. + */ +guac_user_end_handler guac_rdp_upload_end_handler; + +/** + * Handler for put messages. In context of uploads and the filesystem exposed + * via the Guacamole protocol, put messages request write access to a file + * within the filesystem. + */ +guac_user_put_handler guac_rdp_upload_put_handler; + +#endif + diff --git a/src/protocols/rdp/user.c b/src/protocols/rdp/user.c index a22d138b..b070b4a2 100644 --- a/src/protocols/rdp/user.c +++ b/src/protocols/rdp/user.c @@ -24,7 +24,7 @@ #include "input.h" #include "rdp.h" #include "settings.h" -#include "stream.h" +#include "upload.h" #include "user.h" #ifdef ENABLE_COMMON_SSH From 9ad3bc9a49d464fef6956b35dab50654a219afe2 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 29 Dec 2019 18:12:01 -0800 Subject: [PATCH 066/109] GUACAMOLE-249: Log RDPDR debug messages at GUAC_LOG_DEBUG level. --- .../rdp/channels/rdpdr/rdpdr-fs-messages.c | 8 ++++---- src/protocols/rdp/channels/rdpdr/rdpdr-fs.c | 2 +- .../rdp/channels/rdpdr/rdpdr-messages.c | 20 +++++++++---------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c index 8475ce94..60fa6852 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c @@ -272,7 +272,7 @@ void guac_rdpdr_fs_process_volume_info(guac_rdp_common_svc* svc, break; default: - guac_client_log(svc->client, GUAC_LOG_INFO, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "Unknown volume information class: 0x%x", fs_information_class); } @@ -302,7 +302,7 @@ void guac_rdpdr_fs_process_file_info(guac_rdp_common_svc* svc, break; default: - guac_client_log(svc->client, GUAC_LOG_INFO, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "Unknown file information class: 0x%x", fs_information_class); } @@ -358,7 +358,7 @@ void guac_rdpdr_fs_process_set_file_info(guac_rdp_common_svc* svc, break; default: - guac_client_log(svc->client, GUAC_LOG_INFO, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "Unknown file information class: 0x%x", fs_information_class); } @@ -473,7 +473,7 @@ void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc, break; default: - guac_client_log(svc->client, GUAC_LOG_INFO, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "Unknown dir information class: 0x%x", fs_information_class); } diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs.c index 87e7d9fc..50f3c287 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs.c @@ -102,7 +102,7 @@ void guac_rdpdr_device_fs_iorequest_handler(guac_rdp_common_svc* svc, break; default: - guac_client_log(svc->client, GUAC_LOG_ERROR, + guac_client_log(svc->client, GUAC_LOG_DEBUG, "Unknown filesystem I/O request function: 0x%x/0x%x", iorequest->major_func, iorequest->minor_func); } diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-messages.c b/src/protocols/rdp/channels/rdpdr/rdpdr-messages.c index 21bb3162..c4d4b032 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-messages.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-messages.c @@ -119,7 +119,7 @@ static void guac_rdpdr_send_client_name_request(guac_rdp_common_svc* svc, static void guac_rdpdr_send_client_capability(guac_rdp_common_svc* svc) { wStream* output_stream = Stream_New(NULL, 256); - guac_client_log(svc->client, GUAC_LOG_INFO, "Sending capabilities..."); + guac_client_log(svc->client, GUAC_LOG_DEBUG, "Sending capabilities..."); /* Write header */ Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE); @@ -160,7 +160,7 @@ static void guac_rdpdr_send_client_capability(guac_rdp_common_svc* svc) { Stream_Write_UINT32(output_stream, DRIVE_CAPABILITY_VERSION_02); guac_rdp_common_svc_write(svc, output_stream); - guac_client_log(svc->client, GUAC_LOG_INFO, "Capabilities sent."); + guac_client_log(svc->client, GUAC_LOG_DEBUG, "Capabilities sent."); } @@ -199,13 +199,13 @@ static void guac_rdpdr_send_client_device_list_announce_request(guac_rdp_common_ Stream_Buffer(rdpdr->devices[i].device_announce), rdpdr->devices[i].device_announce_len); - guac_client_log(svc->client, GUAC_LOG_INFO, "Registered device %i (%s)", + guac_client_log(svc->client, GUAC_LOG_DEBUG, "Registered device %i (%s)", rdpdr->devices[i].device_id, rdpdr->devices[i].device_name); } guac_rdp_common_svc_write(svc, output_stream); - guac_client_log(svc->client, GUAC_LOG_INFO, "All supported devices sent."); + guac_client_log(svc->client, GUAC_LOG_DEBUG, "All supported devices sent."); } @@ -234,7 +234,7 @@ void guac_rdpdr_process_server_announce(guac_rdp_common_svc* svc, void guac_rdpdr_process_clientid_confirm(guac_rdp_common_svc* svc, wStream* input_stream) { - guac_client_log(svc->client, GUAC_LOG_INFO, "Client ID confirmed"); + guac_client_log(svc->client, GUAC_LOG_DEBUG, "Client ID confirmed"); } void guac_rdpdr_process_device_reply(guac_rdp_common_svc* svc, @@ -258,7 +258,7 @@ void guac_rdpdr_process_device_reply(guac_rdp_common_svc* svc, if (device_id < rdpdr->devices_registered) { if (severity == 0x0) - guac_client_log(svc->client, GUAC_LOG_INFO, "Device %i (%s) connected successfully", + guac_client_log(svc->client, GUAC_LOG_DEBUG, "Device %i (%s) connected successfully", device_id, rdpdr->devices[device_id].device_name); else @@ -322,7 +322,7 @@ void guac_rdpdr_process_server_capability(guac_rdp_common_svc* svc, Stream_Read_UINT16(input_stream, length); /* Ignore all for now */ - guac_client_log(svc->client, GUAC_LOG_INFO, "Ignoring server capability set type=0x%04x, length=%i", type, length); + guac_client_log(svc->client, GUAC_LOG_DEBUG, "Ignoring server capability set type=0x%04x, length=%i", type, length); Stream_Seek(input_stream, length - 4); } @@ -335,17 +335,17 @@ void guac_rdpdr_process_server_capability(guac_rdp_common_svc* svc, void guac_rdpdr_process_user_loggedon(guac_rdp_common_svc* svc, wStream* input_stream) { - guac_client_log(svc->client, GUAC_LOG_INFO, "User logged on"); + guac_client_log(svc->client, GUAC_LOG_INFO, "RDPDR user logged on"); guac_rdpdr_send_client_device_list_announce_request(svc); } void guac_rdpdr_process_prn_cache_data(guac_rdp_common_svc* svc, wStream* input_stream) { - guac_client_log(svc->client, GUAC_LOG_INFO, "Ignoring printer cached configuration data"); + guac_client_log(svc->client, GUAC_LOG_DEBUG, "Ignoring printer cached configuration data"); } void guac_rdpdr_process_prn_using_xps(guac_rdp_common_svc* svc, wStream* input_stream) { - guac_client_log(svc->client, GUAC_LOG_INFO, "Printer unexpectedly switched to XPS mode"); + guac_client_log(svc->client, GUAC_LOG_WARNING, "Printer unexpectedly switched to XPS mode"); } From 0926864ecbb0ba54f00a5af85a22495c844a9eef Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 29 Dec 2019 18:44:41 -0800 Subject: [PATCH 067/109] GUACAMOLE-249: Redirect FreeRDP log messages to debug level of guac_client_log(). --- src/protocols/rdp/Makefile.am | 2 + src/protocols/rdp/client.c | 5 +++ src/protocols/rdp/log.c | 71 +++++++++++++++++++++++++++++++++++ src/protocols/rdp/log.h | 35 +++++++++++++++++ 4 files changed, 113 insertions(+) create mode 100644 src/protocols/rdp/log.c create mode 100644 src/protocols/rdp/log.h diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index 19c81c2e..3d9d5a50 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -66,6 +66,7 @@ libguac_client_rdp_la_SOURCES = \ keyboard/decompose.c \ keyboard/keyboard.c \ keyboard/keymap.c \ + log.c \ ls.c \ plugins/channels.c \ plugins/ptr-string.c \ @@ -107,6 +108,7 @@ noinst_HEADERS = \ keyboard/decompose.h \ keyboard/keyboard.h \ keyboard/keymap.h \ + log.h \ ls.h \ plugins/channels.h \ plugins/guacai/guacai-messages.h \ diff --git a/src/protocols/rdp/client.c b/src/protocols/rdp/client.c index 123e1339..c8150acb 100644 --- a/src/protocols/rdp/client.c +++ b/src/protocols/rdp/client.c @@ -23,6 +23,7 @@ #include "client.h" #include "common/recording.h" #include "fs.h" +#include "log.h" #include "rdp.h" #include "user.h" @@ -40,6 +41,7 @@ #include #include #include +#include #include #include @@ -60,6 +62,9 @@ int guac_client_init(guac_client* client, int argc, char** argv) { /* Init display update module */ rdp_client->disp = guac_rdp_disp_alloc(); + /* Redirect FreeRDP log messages to guac_client_log() */ + guac_rdp_redirect_wlog(client); + /* Recursive attribute for locks */ pthread_mutexattr_init(&(rdp_client->attributes)); pthread_mutexattr_settype(&(rdp_client->attributes), diff --git a/src/protocols/rdp/log.c b/src/protocols/rdp/log.c new file mode 100644 index 00000000..fa0a074f --- /dev/null +++ b/src/protocols/rdp/log.c @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#include +#include + +/** + * The guac_client that should be used within this process for FreeRDP log + * messages. As all Guacamole connections are isolated at the process level, + * this will only ever be set to the guac_client of the current process' + * connection. + */ +static guac_client* current_client = NULL; + +/** + * Logs the text data within the given message to the logging facilities of the + * guac_client currently stored under current_client (the guac_client of the + * current process). + * + * @param message + * The message to log. + * + * @return + * TRUE if the message was successfully logged, FALSE otherwise. + */ +static BOOL guac_rdp_wlog_text_message(const wLogMessage* message) { + + /* Fail if log not yet redirected */ + if (current_client == NULL) + return FALSE; + + /* Log all received messages at the debug level */ + guac_client_log(current_client, GUAC_LOG_DEBUG, "%s", message->TextString); + return TRUE; + +} + +void guac_rdp_redirect_wlog(guac_client* client) { + + wLogCallbacks callbacks = { + .message = guac_rdp_wlog_text_message + }; + + current_client = client; + + /* Reconfigure root logger to use callback appender */ + wLog* root = WLog_GetRoot(); + WLog_SetLogAppenderType(root, WLOG_APPENDER_CALLBACK); + + /* Set appender callbacks to our own */ + wLogAppender* appender = WLog_GetLogAppender(root); + WLog_ConfigureAppender(appender, "callbacks", &callbacks); + +} + diff --git a/src/protocols/rdp/log.h b/src/protocols/rdp/log.h new file mode 100644 index 00000000..3b40aeef --- /dev/null +++ b/src/protocols/rdp/log.h @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#ifndef GUAC_RDP_LOG_H +#define GUAC_RDP_LOG_H + +#include + +/** + * Redirects the core FreeRDP logging facility, wLog, such that it logs all + * messages at the debug level using guac_client_log(). + * + * @param client + * The guac_client that should receive all log messages. + */ +void guac_rdp_redirect_wlog(guac_client* client); + +#endif + From 8dda26af541f1d007a1be75288cadd5031ab952d Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 30 Dec 2019 16:11:13 -0800 Subject: [PATCH 068/109] GUACAMOLE-249: Free rdpBitmap and rdpGlyph within custom free handlers (not automatically freed like rdpPointer). --- src/protocols/rdp/bitmap.c | 7 +++++++ src/protocols/rdp/glyph.c | 7 +++++++ src/protocols/rdp/pointer.c | 3 +++ 3 files changed, 17 insertions(+) diff --git a/src/protocols/rdp/bitmap.c b/src/protocols/rdp/bitmap.c index 56d80e35..f0c499ad 100644 --- a/src/protocols/rdp/bitmap.c +++ b/src/protocols/rdp/bitmap.c @@ -156,6 +156,13 @@ void guac_rdp_bitmap_free(rdpContext* context, rdpBitmap* bitmap) { if (buffer != NULL) guac_common_display_free_buffer(rdp_client->display, buffer); + /* NOTE: FreeRDP-allocated memory for the rdpBitmap will NOT be + * automatically released after this free handler is invoked, thus we must + * do so manually here */ + + _aligned_free(bitmap->data); + free(bitmap); + } BOOL guac_rdp_bitmap_setsurface(rdpContext* context, rdpBitmap* bitmap, BOOL primary) { diff --git a/src/protocols/rdp/glyph.c b/src/protocols/rdp/glyph.c index 6a0aaab8..576149b8 100644 --- a/src/protocols/rdp/glyph.c +++ b/src/protocols/rdp/glyph.c @@ -121,6 +121,13 @@ void guac_rdp_glyph_free(rdpContext* context, rdpGlyph* glyph) { cairo_surface_destroy(((guac_rdp_glyph*) glyph)->surface); free(image_buffer); + /* NOTE: FreeRDP-allocated memory for the rdpGlyph will NOT be + * automatically released after this free handler is invoked, thus we must + * do so manually here */ + + free(glyph->aj); + free(glyph); + } BOOL guac_rdp_glyph_begindraw(rdpContext* context, INT32 x, INT32 y, diff --git a/src/protocols/rdp/pointer.c b/src/protocols/rdp/pointer.c index 498bc883..079637bb 100644 --- a/src/protocols/rdp/pointer.c +++ b/src/protocols/rdp/pointer.c @@ -95,6 +95,9 @@ void guac_rdp_pointer_free(rdpContext* context, rdpPointer* pointer) { /* Free buffer */ guac_common_display_free_buffer(rdp_client->display, buffer); + /* NOTE: FreeRDP-allocated memory for the rdpPointer will be automatically + * released after this free handler is invoked */ + } BOOL guac_rdp_pointer_set_null(rdpContext* context) { From f33416949ff26f839873b7ec2dbe28fd41ae131e Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 30 Dec 2019 17:43:39 -0800 Subject: [PATCH 069/109] GUACAMOLE-249: RAIL plugin for FreeRDP 2.0.0 requires that the Client Execute PDU be sent manually. --- src/protocols/rdp/channels/rail.c | 88 ++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 14 deletions(-) diff --git a/src/protocols/rdp/channels/rail.c b/src/protocols/rdp/channels/rail.c index a96c0ad9..37017c43 100644 --- a/src/protocols/rdp/channels/rail.c +++ b/src/protocols/rdp/channels/rail.c @@ -32,30 +32,29 @@ #include /** - * Callback which is invoked when a Server System Parameters Update PDU is - * received from the RDP server. The Server System Parameters Update PDU, also - * referred to as a "sysparam order", is used by the server to update system - * parameters for RemoteApp. + * Completes initialization of the RemoteApp session, sending client system + * parameters and executing the desired RemoteApp command using the Client + * System Parameters Update PDU and Client Execute PDU respectively. These PDUs + * MUST be sent for the desired RemoteApp to run, and MUST NOT be sent until + * after a Handshake or HandshakeEx PDU has been received. See: + * + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdperp/60344497-883f-4711-8b9a-828d1c580195 (System Parameters Update PDU) + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdperp/98a6e3c3-c2a9-42cc-ad91-0d9a6c211138 (Client Execute PDU) * * @param rail * The RailClientContext structure used by FreeRDP to handle the RAIL * channel for the current RDP session. * - * @param sysparam - * The RAIL_SYSPARAM_ORDER structure representing the Server System - * Parameters Update PDU that was received. - * * @return - * CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code + * CHANNEL_RC_OK (zero) if the PDUs were sent successfully, an error code * (non-zero) otherwise. */ -static UINT guac_rdp_rail_sysparam(RailClientContext* rail, - const RAIL_SYSPARAM_ORDER* sysparam) { +static UINT guac_rdp_rail_complete_handshake(RailClientContext* rail) { guac_client* client = (guac_client*) rail->custom; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - RAIL_SYSPARAM_ORDER response = { + RAIL_SYSPARAM_ORDER sysparam = { .workArea = { .left = 0, .top = 0, @@ -65,8 +64,68 @@ static UINT guac_rdp_rail_sysparam(RailClientContext* rail, .dragFullWindows = FALSE }; - return rail->ClientSystemParam(rail, &response); + /* Send client system parameters */ + UINT status = rail->ClientSystemParam(rail, &sysparam); + if (status != CHANNEL_RC_OK) + return status; + RAIL_EXEC_ORDER exec = { + .RemoteApplicationProgram = rdp_client->settings->remote_app, + .RemoteApplicationWorkingDir = rdp_client->settings->remote_app_dir, + .RemoteApplicationArguments = rdp_client->settings->remote_app_args, + }; + + /* Execute desired RemoteApp command */ + return rail->ClientExecute(rail, &exec); + +} + +/** + * Callback which is invoked when a Handshake PDU is received from the RDP + * server. No communication for RemoteApp may occur until the Handshake PDU + * (or, alternatively, the HandshakeEx PDU) is received. See: + * + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdperp/cec4eb83-b304-43c9-8378-b5b8f5e7082a + * + * @param rail + * The RailClientContext structure used by FreeRDP to handle the RAIL + * channel for the current RDP session. + * + * @param handshake + * The RAIL_HANDSHAKE_ORDER structure representing the Handshake PDU that + * was received. + * + * @return + * CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code + * (non-zero) otherwise. + */ +static UINT guac_rdp_rail_handshake(RailClientContext* rail, + const RAIL_HANDSHAKE_ORDER* handshake) { + return guac_rdp_rail_complete_handshake(rail); +} + +/** + * Callback which is invoked when a HandshakeEx PDU is received from the RDP + * server. No communication for RemoteApp may occur until the HandshakeEx PDU + * (or, alternatively, the Handshake PDU) is received. See: + * + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdperp/5cec5414-27de-442e-8d4a-c8f8b41f3899 + * + * @param rail + * The RailClientContext structure used by FreeRDP to handle the RAIL + * channel for the current RDP session. + * + * @param handshake_ex + * The RAIL_HANDSHAKE_EX_ORDER structure representing the HandshakeEx PDU + * that was received. + * + * @return + * CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code + * (non-zero) otherwise. + */ +static UINT guac_rdp_rail_handshake_ex(RailClientContext* rail, + const RAIL_HANDSHAKE_EX_ORDER* handshake_ex) { + return guac_rdp_rail_complete_handshake(rail); } /** @@ -103,7 +162,8 @@ static void guac_rdp_rail_channel_connected(rdpContext* context, /* Init FreeRDP RAIL context, ensuring the guac_client can be accessed from * within any RAIL-specific callbacks */ rail->custom = client; - rail->ServerSystemParam = guac_rdp_rail_sysparam; + rail->ServerHandshake = guac_rdp_rail_handshake; + rail->ServerHandshakeEx = guac_rdp_rail_handshake_ex; guac_client_log(client, GUAC_LOG_DEBUG, "RAIL (RemoteApp) channel " "connected."); From 7ef1dcafbacc56e745b71aebee7246595424f603 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 31 Dec 2019 16:17:36 -0800 Subject: [PATCH 070/109] GUACAMOLE-249: Convert absolutely all rdpBitmaps before attempting to draw. --- src/protocols/rdp/bitmap.c | 53 ++++++++++++++++++++++++-------------- src/protocols/rdp/bitmap.h | 19 ++++++++++++++ src/protocols/rdp/gdi.c | 3 +++ 3 files changed, 55 insertions(+), 20 deletions(-) diff --git a/src/protocols/rdp/bitmap.c b/src/protocols/rdp/bitmap.c index f0c499ad..829280e0 100644 --- a/src/protocols/rdp/bitmap.c +++ b/src/protocols/rdp/bitmap.c @@ -37,6 +37,31 @@ #include #include +BOOL guac_rdp_bitmap_convert(rdpContext* context, rdpBitmap* bitmap) { + + /* No need to convert if there is no image data or the image data is + * already in the format used by libguac (the format used by Cairo) */ + if (bitmap->data == NULL || bitmap->format == PIXEL_FORMAT_BGRX32) + return TRUE; + + /* Allocate sufficient space for converted image */ + unsigned char* image_buffer = _aligned_malloc(bitmap->width * bitmap->height * 4, 16); + + /* Attempt image conversion, replacing existing image data if successful */ + if (freerdp_image_copy(image_buffer, PIXEL_FORMAT_BGRX32, 0, 0, 0, + bitmap->width, bitmap->height, bitmap->data, bitmap->format, + 0, 0, 0, &context->gdi->palette, FREERDP_FLIP_NONE)) { + _aligned_free(bitmap->data); + bitmap->data = image_buffer; + bitmap->format = PIXEL_FORMAT_BGRX32; + return TRUE; + } + + _aligned_free(image_buffer); + return FALSE; + +} + BOOL guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap) { guac_client* client = ((rdp_freerdp_context*) context)->client; @@ -49,6 +74,9 @@ BOOL guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap) { /* Cache image data if present */ if (bitmap->data != NULL) { + /* Convert image data to format used by libguac */ + guac_rdp_bitmap_convert(context, bitmap); + /* Create surface from image data */ cairo_surface_t* image = cairo_image_surface_create_for_data( bitmap->data, CAIRO_FORMAT_RGB24, @@ -71,26 +99,8 @@ BOOL guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap) { BOOL guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap) { - /* Convert image data if present */ - if (bitmap->data != NULL && bitmap->format != PIXEL_FORMAT_BGRX32) { - - /* Allocate sufficient space for converted image */ - unsigned char* image_buffer = _aligned_malloc(bitmap->width * bitmap->height * 4, 16); - - /* Attempt image conversion */ - if (!freerdp_image_copy(image_buffer, PIXEL_FORMAT_BGRX32, 0, 0, 0, - bitmap->width, bitmap->height, bitmap->data, bitmap->format, - 0, 0, 0, &context->gdi->palette, FREERDP_FLIP_NONE)) { - _aligned_free(image_buffer); - } - - /* If successful, replace original image with converted image */ - else { - _aligned_free(bitmap->data); - bitmap->data = image_buffer; - } - - } + /* Convert image data to format used by libguac */ + guac_rdp_bitmap_convert(context, bitmap); /* No corresponding surface yet - caching is deferred. */ ((guac_rdp_bitmap*) bitmap)->layer = NULL; @@ -125,6 +135,9 @@ BOOL guac_rdp_bitmap_paint(rdpContext* context, rdpBitmap* bitmap) { /* Otherwise, draw with stored image data */ else if (bitmap->data != NULL) { + /* Convert image data to format used by libguac */ + guac_rdp_bitmap_convert(context, bitmap); + /* Create surface from image data */ cairo_surface_t* image = cairo_image_surface_create_for_data( bitmap->data, CAIRO_FORMAT_RGB24, diff --git a/src/protocols/rdp/bitmap.h b/src/protocols/rdp/bitmap.h index 70068b56..42108bc1 100644 --- a/src/protocols/rdp/bitmap.h +++ b/src/protocols/rdp/bitmap.h @@ -49,6 +49,25 @@ typedef struct guac_rdp_bitmap { } guac_rdp_bitmap; +/** + * Converts the image data within the given rdpBitmap to the pixel format used + * by libguac (Cairo) for 24-bit RGB images lacking an alpha channel. Any + * existing image data within the bitmap is freed and replaced with + * newly-allocated image data in the needed format, and the format field of the + * rdpBitmap is updated to match. + * + * @param context + * The rdpContext associated with the current RDP session. + * + * @param bitmap + * The rdpBitmap to convert. + * + * @return + * TRUE if image conversion was successful or there was no image data to + * convert, FALSE otherwise. + */ +BOOL guac_rdp_bitmap_convert(rdpContext* context, rdpBitmap* bitmap); + /** * Caches the given bitmap immediately, storing its data in a remote Guacamole * buffer. As RDP bitmaps are frequently created, used once, and immediately diff --git a/src/protocols/rdp/gdi.c b/src/protocols/rdp/gdi.c index 1961fdb5..69528dfb 100644 --- a/src/protocols/rdp/gdi.c +++ b/src/protocols/rdp/gdi.c @@ -274,6 +274,9 @@ BOOL guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) { if (bitmap->layer == NULL) { if (memblt->bitmap->data != NULL) { + /* Convert image data to format used by libguac */ + guac_rdp_bitmap_convert(context, memblt->bitmap); + /* Create surface from image data */ cairo_surface_t* surface = cairo_image_surface_create_for_data( memblt->bitmap->data + 4*(x_src + y_src*memblt->bitmap->width), From d7151e0d84af76f285678d2ef96ae17eeeccda4b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 31 Dec 2019 16:23:28 -0800 Subject: [PATCH 071/109] GUACAMOLE-249: Push FreeRDP settings in preconnect hander (OrderSupport is reset otherwise). We set the values within the OrderSupport array to match which RDP messages we have implemented within guac_rdp_push_settings(). This array is reset to its default values prior to the preconnect handler being invoked, thus guac_rdp_push_settings() MUST be invoked within the preconnect handler for its settings to have the intended effect. Without proper values within OrderSupport, the initial RDP negotiation process will claim support for messages that we don't actually support, resulting in graphical artifacts and unexpected behavior. --- src/protocols/rdp/rdp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 5a6fb875..a33fd11c 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -87,6 +87,9 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_settings* settings = rdp_client->settings; + /* Push desired settings to FreeRDP */ + guac_rdp_push_settings(client, settings, instance); + /* Init FreeRDP add-in provider */ freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0); @@ -380,9 +383,6 @@ static int guac_rdp_handle_connection(guac_client* client) { /* Set default pointer */ guac_common_cursor_set_pointer(rdp_client->display->cursor); - /* Push desired settings to FreeRDP */ - guac_rdp_push_settings(client, settings, rdp_inst); - /* Connect to RDP server */ if (!freerdp_connect(rdp_inst)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_NOT_FOUND, From 2d4412316fc16d276318bb310e780546220a0c89 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 1 Jan 2020 20:33:46 -0800 Subject: [PATCH 072/109] GUACAMOLE-249: Do not draw background for glyphs when "redundant" (transparent). --- src/protocols/rdp/glyph.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/rdp/glyph.c b/src/protocols/rdp/glyph.c index 576149b8..3050c65c 100644 --- a/src/protocols/rdp/glyph.c +++ b/src/protocols/rdp/glyph.c @@ -139,7 +139,7 @@ BOOL guac_rdp_glyph_begindraw(rdpContext* context, INT32 x, INT32 y, (guac_rdp_client*) client->data; /* Fill background with color if specified */ - if (width != 0 && height != 0) { + if (width != 0 && height != 0 && !redundant) { /* Convert background color */ bgcolor = guac_rdp_convert_color(context, bgcolor); From 36f227586ecc42ad8ae7181a80905403ea7dc9eb Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 3 Jan 2020 16:35:34 -0800 Subject: [PATCH 073/109] GUACAMOLE-249: Defer draws to unrealized (server-side) buffers until they are actually needed client-side. Though deferred creation of buffers is already intended, creation was not actually being deferred in practice as the act of initializing the buffer with a solid rect of color was causing the buffer to be realized, even if that initialization process is the only drawing operation that will ever occur to that buffer. --- src/common/surface.c | 95 ++++++++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 43 deletions(-) diff --git a/src/common/surface.c b/src/common/surface.c index c31dfbf0..ccac11da 100644 --- a/src/common/surface.c +++ b/src/common/surface.c @@ -260,58 +260,67 @@ static int __guac_common_surface_is_opaque(guac_common_surface* surface, /** * Returns whether the given rectangle should be combined into the existing - * dirty rectangle, to be eventually flushed as a "png" instruction. + * dirty rectangle, to be eventually flushed as image data, or would be best + * kept independent of the current rectangle. * - * @param surface The surface to be queried. - * @param rect The update rectangle. - * @param rect_only Non-zero if this update, by its nature, contains only - * metainformation about the update's rectangle, zero if - * the update also contains image data. - * @return Non-zero if the update should be combined with any existing update, - * zero otherwise. + * @param surface + * The surface being updated. + * + * @param rect + * The bounding rectangle of the updating being made to the surface. + * + * @param rect_only + * Non-zero if this update, by its nature, contains only metainformation + * about the update's bounding rectangle, zero if the update also contains + * image data. + * + * @return + * Non-zero if the update should be combined with any existing update, zero + * otherwise. */ static int __guac_common_should_combine(guac_common_surface* surface, const guac_common_rect* rect, int rect_only) { - if (surface->dirty) { + int combined_cost, dirty_cost, update_cost; - int combined_cost, dirty_cost, update_cost; + /* Always favor combining updates if surface is currently a purely + * server-side scratch area */ + if (!surface->realized) + return 1; - /* Simulate combination */ - guac_common_rect combined = surface->dirty_rect; - guac_common_rect_extend(&combined, rect); + /* Simulate combination */ + guac_common_rect combined = surface->dirty_rect; + guac_common_rect_extend(&combined, rect); - /* Combine if result is still small */ - if (combined.width <= GUAC_SURFACE_NEGLIGIBLE_WIDTH && combined.height <= GUAC_SURFACE_NEGLIGIBLE_HEIGHT) + /* Combine if result is still small */ + if (combined.width <= GUAC_SURFACE_NEGLIGIBLE_WIDTH && combined.height <= GUAC_SURFACE_NEGLIGIBLE_HEIGHT) + return 1; + + /* Estimate costs of the existing update, new update, and both combined */ + combined_cost = GUAC_SURFACE_BASE_COST + combined.width * combined.height; + dirty_cost = GUAC_SURFACE_BASE_COST + surface->dirty_rect.width * surface->dirty_rect.height; + update_cost = GUAC_SURFACE_BASE_COST + rect->width * rect->height; + + /* Reduce cost if no image data */ + if (rect_only) + update_cost /= GUAC_SURFACE_DATA_FACTOR; + + /* Combine if cost estimate shows benefit */ + if (combined_cost <= update_cost + dirty_cost) + return 1; + + /* Combine if increase in cost is negligible */ + if (combined_cost - dirty_cost <= dirty_cost / GUAC_SURFACE_NEGLIGIBLE_INCREASE) + return 1; + + if (combined_cost - update_cost <= update_cost / GUAC_SURFACE_NEGLIGIBLE_INCREASE) + return 1; + + /* Combine if we anticipate further updates, as this update follows a common fill pattern */ + if (rect->x == surface->dirty_rect.x && rect->y == surface->dirty_rect.y + surface->dirty_rect.height) { + if (combined_cost <= (dirty_cost + update_cost) * GUAC_SURFACE_FILL_PATTERN_FACTOR) return 1; - - /* Estimate costs of the existing update, new update, and both combined */ - combined_cost = GUAC_SURFACE_BASE_COST + combined.width * combined.height; - dirty_cost = GUAC_SURFACE_BASE_COST + surface->dirty_rect.width * surface->dirty_rect.height; - update_cost = GUAC_SURFACE_BASE_COST + rect->width * rect->height; - - /* Reduce cost if no image data */ - if (rect_only) - update_cost /= GUAC_SURFACE_DATA_FACTOR; - - /* Combine if cost estimate shows benefit */ - if (combined_cost <= update_cost + dirty_cost) - return 1; - - /* Combine if increase in cost is negligible */ - if (combined_cost - dirty_cost <= dirty_cost / GUAC_SURFACE_NEGLIGIBLE_INCREASE) - return 1; - - if (combined_cost - update_cost <= update_cost / GUAC_SURFACE_NEGLIGIBLE_INCREASE) - return 1; - - /* Combine if we anticipate further updates, as this update follows a common fill pattern */ - if (rect->x == surface->dirty_rect.x && rect->y == surface->dirty_rect.y + surface->dirty_rect.height) { - if (combined_cost <= (dirty_cost + update_cost) * GUAC_SURFACE_FILL_PATTERN_FACTOR) - return 1; - } - } - + /* Otherwise, do not combine */ return 0; From 1bc9384ea8ca54165eaed30191ba1ece4fe08d22 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 3 Jan 2020 17:29:16 -0800 Subject: [PATCH 074/109] GUACAMOLE-249: Claim support only for RDP orders that are explicitly supported, independently of any FreeRDP defaults. --- src/protocols/rdp/settings.c | 34 +++++++++------------------------- src/protocols/rdp/settings.h | 10 ++++++++++ 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/src/protocols/rdp/settings.c b/src/protocols/rdp/settings.c index 3942b370..872f14f8 100644 --- a/src/protocols/rdp/settings.c +++ b/src/protocols/rdp/settings.c @@ -1144,7 +1144,6 @@ static char* guac_rdp_strdup(const char* str) { void guac_rdp_push_settings(guac_client* client, guac_rdp_settings* guac_settings, freerdp* rdp) { - BOOL bitmap_cache = !guac_settings->disable_bitmap_caching; rdpSettings* rdp_settings = rdp->settings; /* Authentication */ @@ -1312,37 +1311,22 @@ void guac_rdp_push_settings(guac_client* client, rdp_settings->LoadBalanceInfoLength = strlen(guac_settings->load_balance_info); } - /* Order support */ - rdp_settings->BitmapCacheEnabled = bitmap_cache; + rdp_settings->BitmapCacheEnabled = !guac_settings->disable_bitmap_caching; rdp_settings->OffscreenSupportLevel = !guac_settings->disable_offscreen_caching; rdp_settings->GlyphSupportLevel = !guac_settings->disable_glyph_caching ? GLYPH_SUPPORT_FULL : GLYPH_SUPPORT_NONE; rdp_settings->OsMajorType = OSMAJORTYPE_UNSPECIFIED; rdp_settings->OsMinorType = OSMINORTYPE_UNSPECIFIED; rdp_settings->DesktopResize = TRUE; + + /* Claim support only for specific updates, independent of FreeRDP defaults */ + ZeroMemory(rdp_settings->OrderSupport, GUAC_RDP_ORDER_SUPPORT_LENGTH); rdp_settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE; - rdp_settings->OrderSupport[NEG_PATBLT_INDEX] = FALSE; /* PATBLT not implemented */ rdp_settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE; - rdp_settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] = FALSE; /* PATBLT not implemented, and OPAQUE_RECT implies PATBLT */ - rdp_settings->OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE; - rdp_settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE; - rdp_settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE; - rdp_settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE; - rdp_settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = FALSE; - rdp_settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE; - rdp_settings->OrderSupport[NEG_LINETO_INDEX] = FALSE; - rdp_settings->OrderSupport[NEG_POLYLINE_INDEX] = FALSE; - rdp_settings->OrderSupport[NEG_MEMBLT_INDEX] = bitmap_cache; - rdp_settings->OrderSupport[NEG_MEM3BLT_INDEX] = FALSE; - rdp_settings->OrderSupport[NEG_MEMBLT_V2_INDEX] = bitmap_cache; - rdp_settings->OrderSupport[NEG_MEM3BLT_V2_INDEX] = FALSE; - rdp_settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE; - rdp_settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = TRUE; - rdp_settings->OrderSupport[NEG_FAST_INDEX_INDEX] = TRUE; - rdp_settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = TRUE; - rdp_settings->OrderSupport[NEG_POLYGON_SC_INDEX] = FALSE; - rdp_settings->OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE; - rdp_settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE; - rdp_settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE; + rdp_settings->OrderSupport[NEG_MEMBLT_INDEX] = !guac_settings->disable_bitmap_caching; + rdp_settings->OrderSupport[NEG_MEMBLT_V2_INDEX] = !guac_settings->disable_bitmap_caching; + rdp_settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = !guac_settings->disable_glyph_caching; + rdp_settings->OrderSupport[NEG_FAST_INDEX_INDEX] = !guac_settings->disable_glyph_caching; + rdp_settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = !guac_settings->disable_glyph_caching; } diff --git a/src/protocols/rdp/settings.h b/src/protocols/rdp/settings.h index 7679ae1e..bd1daf01 100644 --- a/src/protocols/rdp/settings.h +++ b/src/protocols/rdp/settings.h @@ -58,6 +58,16 @@ */ #define GUAC_RDP_DEFAULT_RECORDING_NAME "recording" +/** + * The number of entries contained within the OrderSupport BYTE array + * referenced by the rdpSettings structure. This value is defined by the RDP + * negotiation process (there are 32 bytes available within the order + * negotiation field sent during the connection handshake) and is hard-coded + * within FreeRDP. There is no public constant for this value defined within + * the FreeRDP headers. + */ +#define GUAC_RDP_ORDER_SUPPORT_LENGTH 32 + /** * All supported combinations of security types. */ From 902c5e1bd41b8276a9db51180197892e50f57d45 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 3 Jan 2020 23:42:34 -0800 Subject: [PATCH 075/109] GUACAMOLE-249: Alpha component must be in highest-order byte. --- src/protocols/rdp/color.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/rdp/color.c b/src/protocols/rdp/color.c index a0d7170f..a97f8310 100644 --- a/src/protocols/rdp/color.c +++ b/src/protocols/rdp/color.c @@ -76,7 +76,7 @@ UINT32 guac_rdp_convert_color(rdpContext* context, UINT32 color) { /* Convert given color to ARGB32 */ return FreeRDPConvertColor(color, guac_rdp_get_pixel_format(depth), - PIXEL_FORMAT_BGRA32, &gdi->palette); + PIXEL_FORMAT_ABGR32, &gdi->palette); } From 555973f6b06e336cdf3e023c97317c738b24c966 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 4 Jan 2020 00:00:21 -0800 Subject: [PATCH 076/109] GUACAMOLE-249: Remove unnecessary bitmap conversion - will happen automatically when FreeRDP invokes bitmap->Decompress(). --- src/protocols/rdp/bitmap.c | 34 ---------------------------------- src/protocols/rdp/bitmap.h | 19 ------------------- src/protocols/rdp/gdi.c | 3 --- 3 files changed, 56 deletions(-) diff --git a/src/protocols/rdp/bitmap.c b/src/protocols/rdp/bitmap.c index 829280e0..252f66c7 100644 --- a/src/protocols/rdp/bitmap.c +++ b/src/protocols/rdp/bitmap.c @@ -37,31 +37,6 @@ #include #include -BOOL guac_rdp_bitmap_convert(rdpContext* context, rdpBitmap* bitmap) { - - /* No need to convert if there is no image data or the image data is - * already in the format used by libguac (the format used by Cairo) */ - if (bitmap->data == NULL || bitmap->format == PIXEL_FORMAT_BGRX32) - return TRUE; - - /* Allocate sufficient space for converted image */ - unsigned char* image_buffer = _aligned_malloc(bitmap->width * bitmap->height * 4, 16); - - /* Attempt image conversion, replacing existing image data if successful */ - if (freerdp_image_copy(image_buffer, PIXEL_FORMAT_BGRX32, 0, 0, 0, - bitmap->width, bitmap->height, bitmap->data, bitmap->format, - 0, 0, 0, &context->gdi->palette, FREERDP_FLIP_NONE)) { - _aligned_free(bitmap->data); - bitmap->data = image_buffer; - bitmap->format = PIXEL_FORMAT_BGRX32; - return TRUE; - } - - _aligned_free(image_buffer); - return FALSE; - -} - BOOL guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap) { guac_client* client = ((rdp_freerdp_context*) context)->client; @@ -74,9 +49,6 @@ BOOL guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap) { /* Cache image data if present */ if (bitmap->data != NULL) { - /* Convert image data to format used by libguac */ - guac_rdp_bitmap_convert(context, bitmap); - /* Create surface from image data */ cairo_surface_t* image = cairo_image_surface_create_for_data( bitmap->data, CAIRO_FORMAT_RGB24, @@ -99,9 +71,6 @@ BOOL guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap) { BOOL guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap) { - /* Convert image data to format used by libguac */ - guac_rdp_bitmap_convert(context, bitmap); - /* No corresponding surface yet - caching is deferred. */ ((guac_rdp_bitmap*) bitmap)->layer = NULL; @@ -135,9 +104,6 @@ BOOL guac_rdp_bitmap_paint(rdpContext* context, rdpBitmap* bitmap) { /* Otherwise, draw with stored image data */ else if (bitmap->data != NULL) { - /* Convert image data to format used by libguac */ - guac_rdp_bitmap_convert(context, bitmap); - /* Create surface from image data */ cairo_surface_t* image = cairo_image_surface_create_for_data( bitmap->data, CAIRO_FORMAT_RGB24, diff --git a/src/protocols/rdp/bitmap.h b/src/protocols/rdp/bitmap.h index 42108bc1..70068b56 100644 --- a/src/protocols/rdp/bitmap.h +++ b/src/protocols/rdp/bitmap.h @@ -49,25 +49,6 @@ typedef struct guac_rdp_bitmap { } guac_rdp_bitmap; -/** - * Converts the image data within the given rdpBitmap to the pixel format used - * by libguac (Cairo) for 24-bit RGB images lacking an alpha channel. Any - * existing image data within the bitmap is freed and replaced with - * newly-allocated image data in the needed format, and the format field of the - * rdpBitmap is updated to match. - * - * @param context - * The rdpContext associated with the current RDP session. - * - * @param bitmap - * The rdpBitmap to convert. - * - * @return - * TRUE if image conversion was successful or there was no image data to - * convert, FALSE otherwise. - */ -BOOL guac_rdp_bitmap_convert(rdpContext* context, rdpBitmap* bitmap); - /** * Caches the given bitmap immediately, storing its data in a remote Guacamole * buffer. As RDP bitmaps are frequently created, used once, and immediately diff --git a/src/protocols/rdp/gdi.c b/src/protocols/rdp/gdi.c index 69528dfb..1961fdb5 100644 --- a/src/protocols/rdp/gdi.c +++ b/src/protocols/rdp/gdi.c @@ -274,9 +274,6 @@ BOOL guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) { if (bitmap->layer == NULL) { if (memblt->bitmap->data != NULL) { - /* Convert image data to format used by libguac */ - guac_rdp_bitmap_convert(context, memblt->bitmap); - /* Create surface from image data */ cairo_surface_t* surface = cairo_image_surface_create_for_data( memblt->bitmap->data + 4*(x_src + y_src*memblt->bitmap->width), From f57382f885bce318dd4004be228d8ea39008bd3f Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 4 Jan 2020 01:11:05 -0800 Subject: [PATCH 077/109] GUACAMOLE-249: Determine FreeRDP pixel format corresponding to local Cairo surfaces based on local platform endianness. --- src/protocols/rdp/color.c | 49 +++++++++---------------------------- src/protocols/rdp/color.h | 20 +++++++++++++++ src/protocols/rdp/pointer.c | 12 +++++---- src/protocols/rdp/rdp.c | 3 ++- 4 files changed, 41 insertions(+), 43 deletions(-) diff --git a/src/protocols/rdp/color.c b/src/protocols/rdp/color.c index a97f8310..c7db078d 100644 --- a/src/protocols/rdp/color.c +++ b/src/protocols/rdp/color.c @@ -28,44 +28,19 @@ #include #include -/** - * Returns the integer constant used by the FreeRDP API to represent the colors - * used by a connection having the given bit depth. These constants each have - * corresponding PIXEL_FORMAT_* macros defined within freerdp/codec/color.h. - * - * @param depth - * The color depth which should be translated into the integer constant - * defined by FreeRDP's corresponding PIXEL_FORMAT_* macro. - * - * @return - * The integer value of the PIXEL_FORMAT_* macro corresponding to the - * given color depth. - */ -static UINT32 guac_rdp_get_pixel_format(int depth) { +UINT32 guac_rdp_get_native_pixel_format(BOOL alpha) { - switch (depth) { + uint8_t color[] = { 0x0A, 0x0B, 0x0C, 0x0D }; - /* 32- and 24-bit RGB (8 bits per color component) */ - case 32: - case 24: - return PIXEL_FORMAT_RGB24; + /* Local platform stores bytes in decreasing order of significance + * (big-endian) */ + if (*((uint32_t*) color) == 0x0A0B0C0D) + return alpha ? PIXEL_FORMAT_ARGB32 : PIXEL_FORMAT_XRGB32; - /* 16-bit palette (6-bit green, 5-bit red and blue) */ - case 16: - return PIXEL_FORMAT_RGB16; - - /* 15-bit RGB (5 bits per color component) */ - case 15: - return PIXEL_FORMAT_RGB15; - - /* 8-bit palette */ - case 8: - return PIXEL_FORMAT_RGB8; - - } - - /* Unknown format */ - return PIXEL_FORMAT_RGB24; + /* Local platform stores bytes in increasing order of significance + * (little-endian) */ + else + return alpha ? PIXEL_FORMAT_BGRA32 : PIXEL_FORMAT_BGRX32; } @@ -75,8 +50,8 @@ UINT32 guac_rdp_convert_color(rdpContext* context, UINT32 color) { rdpGdi* gdi = context->gdi; /* Convert given color to ARGB32 */ - return FreeRDPConvertColor(color, guac_rdp_get_pixel_format(depth), - PIXEL_FORMAT_ABGR32, &gdi->palette); + return FreeRDPConvertColor(color, gdi_get_pixel_format(depth), + guac_rdp_get_native_pixel_format(TRUE), &gdi->palette); } diff --git a/src/protocols/rdp/color.h b/src/protocols/rdp/color.h index 0617194b..43910a58 100644 --- a/src/protocols/rdp/color.h +++ b/src/protocols/rdp/color.h @@ -23,6 +23,26 @@ #include #include +/** + * Returns the FreeRDP pixel format ID corresponding to the 32-bit RGB format + * used by the Cairo library's image surfaces. Cairo handles colors in terms of + * integers in native endianness, with CAIRO_FORMAT_ARGB32 representing a color + * format where the alpha channel is stored in the most significant byte, + * followed by red, green, and blue. FreeRDP handles colors in terms of + * absolute byte order, with PIXEL_FORMAT_ARGB32 representing a color format + * where the alpha channel is in byte 0, followed by red at byte 1, etc. + * + * @param alpha + * TRUE if the returned FreeRDP pixel format should correspond to Cairo's + * CAIRO_FORMAT_ARGB32, FALSE if the returned format should correspond to + * Cairo's CAIRO_FORMAT_RGB24. + * + * @return + * The FreeRDP pixel format ID that corresponds to the 32-bit RGB format + * used by the Cairo library. + */ +UINT32 guac_rdp_get_native_pixel_format(BOOL alpha); + /** * Converts the given color to ARGB32. The color given may be an index * referring to the palette, a 16-bit or 32-bit color, etc. all depending on diff --git a/src/protocols/rdp/pointer.c b/src/protocols/rdp/pointer.c index 079637bb..41fa5f4c 100644 --- a/src/protocols/rdp/pointer.c +++ b/src/protocols/rdp/pointer.c @@ -19,6 +19,7 @@ #include "config.h" #include "client.h" +#include "color.h" #include "common/cursor.h" #include "common/display.h" #include "pointer.h" @@ -47,11 +48,12 @@ BOOL guac_rdp_pointer_new(rdpContext* context, rdpPointer* pointer) { /* Convert to alpha cursor if mask data present */ if (pointer->andMaskData && pointer->xorMaskData) - freerdp_image_copy_from_pointer_data(data, PIXEL_FORMAT_BGRA32, - 0, 0, 0, pointer->width, pointer->height, - pointer->xorMaskData, pointer->lengthXorMask, - pointer->andMaskData, pointer->lengthAndMask, - pointer->xorBpp, &context->gdi->palette); + freerdp_image_copy_from_pointer_data(data, + guac_rdp_get_native_pixel_format(TRUE), 0, 0, 0, + pointer->width, pointer->height, pointer->xorMaskData, + pointer->lengthXorMask, pointer->andMaskData, + pointer->lengthAndMask, pointer->xorBpp, + &context->gdi->palette); /* Create surface from image data */ surface = cairo_image_surface_create_for_data( diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index a33fd11c..bf60b7c4 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -27,6 +27,7 @@ #include "channels/rdpdr/rdpdr.h" #include "channels/rdpsnd/rdpsnd.h" #include "client.h" +#include "color.h" #include "common/cursor.h" #include "common/display.h" #include "common/recording.h" @@ -138,7 +139,7 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { } /* Init FreeRDP internal GDI implementation */ - if (!gdi_init(instance, PIXEL_FORMAT_BGRX32)) + if (!gdi_init(instance, guac_rdp_get_native_pixel_format(FALSE))) return FALSE; /* Set up bitmap handling */ From 2bbc4bfbffffddcb3351b939973f7080d0fd730b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 4 Jan 2020 11:43:32 -0800 Subject: [PATCH 078/109] GUACAMOLE-249: Move keyboard-related source back to root of RDP (ease merge). Not truly needed as much as the rest of the restructure. --- src/protocols/rdp/Makefile.am | 50 +++++++++---------- src/protocols/rdp/{keyboard => }/decompose.c | 2 +- src/protocols/rdp/{keyboard => }/decompose.h | 6 +-- src/protocols/rdp/input.c | 2 +- src/protocols/rdp/{keyboard => }/keyboard.c | 6 +-- src/protocols/rdp/{keyboard => }/keyboard.h | 2 +- src/protocols/rdp/{keyboard => }/keymap.c | 2 +- src/protocols/rdp/{keyboard => }/keymap.h | 4 +- .../rdp/{keyboard => }/keymaps/base.keymap | 0 .../keymaps/da_dk_qwerty.keymap | 0 .../keymaps/de_ch_qwertz.keymap | 0 .../keymaps/de_de_qwertz.keymap | 0 .../keymaps/en_gb_qwerty.keymap | 0 .../keymaps/en_us_qwerty.keymap | 0 .../keymaps/es_es_qwerty.keymap | 0 .../{keyboard => }/keymaps/failsafe.keymap | 0 .../keymaps/fr_ch_qwertz.keymap | 0 .../keymaps/fr_fr_azerty.keymap | 0 .../rdp/{keyboard => }/keymaps/generate.pl | 2 +- .../keymaps/it_it_qwerty.keymap | 0 .../keymaps/ja_jp_qwerty.keymap | 0 .../keymaps/pt_br_qwerty.keymap | 0 .../keymaps/sv_se_qwerty.keymap | 0 .../keymaps/tr_tr_qwerty.keymap | 0 src/protocols/rdp/rdp.c | 2 +- src/protocols/rdp/rdp.h | 2 +- src/protocols/rdp/settings.h | 2 +- 27 files changed, 41 insertions(+), 41 deletions(-) rename src/protocols/rdp/{keyboard => }/decompose.c (99%) rename src/protocols/rdp/{keyboard => }/decompose.h (94%) rename src/protocols/rdp/{keyboard => }/keyboard.c (99%) rename src/protocols/rdp/{keyboard => }/keyboard.h (99%) rename src/protocols/rdp/{keyboard => }/keymap.c (98%) rename src/protocols/rdp/{keyboard => }/keymap.h (98%) rename src/protocols/rdp/{keyboard => }/keymaps/base.keymap (100%) rename src/protocols/rdp/{keyboard => }/keymaps/da_dk_qwerty.keymap (100%) rename src/protocols/rdp/{keyboard => }/keymaps/de_ch_qwertz.keymap (100%) rename src/protocols/rdp/{keyboard => }/keymaps/de_de_qwertz.keymap (100%) rename src/protocols/rdp/{keyboard => }/keymaps/en_gb_qwerty.keymap (100%) rename src/protocols/rdp/{keyboard => }/keymaps/en_us_qwerty.keymap (100%) rename src/protocols/rdp/{keyboard => }/keymaps/es_es_qwerty.keymap (100%) rename src/protocols/rdp/{keyboard => }/keymaps/failsafe.keymap (100%) rename src/protocols/rdp/{keyboard => }/keymaps/fr_ch_qwertz.keymap (100%) rename src/protocols/rdp/{keyboard => }/keymaps/fr_fr_azerty.keymap (100%) rename src/protocols/rdp/{keyboard => }/keymaps/generate.pl (99%) rename src/protocols/rdp/{keyboard => }/keymaps/it_it_qwerty.keymap (100%) rename src/protocols/rdp/{keyboard => }/keymaps/ja_jp_qwerty.keymap (100%) rename src/protocols/rdp/{keyboard => }/keymaps/pt_br_qwerty.keymap (100%) rename src/protocols/rdp/{keyboard => }/keymaps/sv_se_qwerty.keymap (100%) rename src/protocols/rdp/{keyboard => }/keymaps/tr_tr_qwerty.keymap (100%) diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index 3d9d5a50..8766b76a 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -57,15 +57,15 @@ libguac_client_rdp_la_SOURCES = \ channels/rdpsnd/rdpsnd.c \ client.c \ color.c \ + decompose.c \ download.c \ error.c \ fs.c \ gdi.c \ glyph.c \ input.c \ - keyboard/decompose.c \ - keyboard/keyboard.c \ - keyboard/keymap.c \ + keyboard.c \ + keymap.c \ log.c \ ls.c \ plugins/channels.c \ @@ -99,15 +99,15 @@ noinst_HEADERS = \ channels/rdpsnd/rdpsnd.h \ client.h \ color.h \ + decompose.h \ download.h \ error.h \ fs.h \ gdi.h \ glyph.h \ input.h \ - keyboard/decompose.h \ - keyboard/keyboard.h \ - keyboard/keymap.h \ + keyboard.h \ + keymap.h \ log.h \ ls.h \ plugins/channels.h \ @@ -217,31 +217,31 @@ BUILT_SOURCES = \ _generated_channel_entry_wrappers.c \ _generated_keymaps.c -rdp_keymaps = \ - $(srcdir)/keyboard/keymaps/base.keymap \ - $(srcdir)/keyboard/keymaps/failsafe.keymap \ - $(srcdir)/keyboard/keymaps/de_de_qwertz.keymap \ - $(srcdir)/keyboard/keymaps/de_ch_qwertz.keymap \ - $(srcdir)/keyboard/keymaps/en_gb_qwerty.keymap \ - $(srcdir)/keyboard/keymaps/en_us_qwerty.keymap \ - $(srcdir)/keyboard/keymaps/es_es_qwerty.keymap \ - $(srcdir)/keyboard/keymaps/fr_fr_azerty.keymap \ - $(srcdir)/keyboard/keymaps/fr_ch_qwertz.keymap \ - $(srcdir)/keyboard/keymaps/it_it_qwerty.keymap \ - $(srcdir)/keyboard/keymaps/ja_jp_qwerty.keymap \ - $(srcdir)/keyboard/keymaps/pt_br_qwerty.keymap \ - $(srcdir)/keyboard/keymaps/sv_se_qwerty.keymap \ - $(srcdir)/keyboard/keymaps/da_dk_qwerty.keymap \ - $(srcdir)/keyboard/keymaps/tr_tr_qwerty.keymap +rdp_keymaps = \ + $(srcdir)/keymaps/base.keymap \ + $(srcdir)/keymaps/failsafe.keymap \ + $(srcdir)/keymaps/de_de_qwertz.keymap \ + $(srcdir)/keymaps/de_ch_qwertz.keymap \ + $(srcdir)/keymaps/en_gb_qwerty.keymap \ + $(srcdir)/keymaps/en_us_qwerty.keymap \ + $(srcdir)/keymaps/es_es_qwerty.keymap \ + $(srcdir)/keymaps/fr_fr_azerty.keymap \ + $(srcdir)/keymaps/fr_ch_qwertz.keymap \ + $(srcdir)/keymaps/it_it_qwerty.keymap \ + $(srcdir)/keymaps/ja_jp_qwerty.keymap \ + $(srcdir)/keymaps/pt_br_qwerty.keymap \ + $(srcdir)/keymaps/sv_se_qwerty.keymap \ + $(srcdir)/keymaps/da_dk_qwerty.keymap \ + $(srcdir)/keymaps/tr_tr_qwerty.keymap _generated_keymaps.c: $(rdp_keymaps) - $(AM_V_GEN) $(srcdir)/keyboard/keymaps/generate.pl $(rdp_keymaps) + $(AM_V_GEN) $(srcdir)/keymaps/generate.pl $(rdp_keymaps) _generated_channel_entry_wrappers.c: $(srcdir)/plugins/channels.h $(srcdir)/plugins/generate-entry-wrappers.pl $(AM_V_GEN) $(srcdir)/plugins/generate-entry-wrappers.pl $(srcdir)/plugins/channels.h EXTRA_DIST = \ $(rdp_keymaps) \ - plugins/generate-entry-wrappers.pl \ - keyboard/keymaps/generate.pl + keymaps/generate.pl \ + plugins/generate-entry-wrappers.pl diff --git a/src/protocols/rdp/keyboard/decompose.c b/src/protocols/rdp/decompose.c similarity index 99% rename from src/protocols/rdp/keyboard/decompose.c rename to src/protocols/rdp/decompose.c index 1495f51c..5f559d99 100644 --- a/src/protocols/rdp/keyboard/decompose.c +++ b/src/protocols/rdp/decompose.c @@ -18,7 +18,7 @@ */ #include "config.h" -#include "keyboard/keyboard.h" +#include "keyboard.h" /** * The X11 keysym for the dead key which types a grave (`). diff --git a/src/protocols/rdp/keyboard/decompose.h b/src/protocols/rdp/decompose.h similarity index 94% rename from src/protocols/rdp/keyboard/decompose.h rename to src/protocols/rdp/decompose.h index 0c3765ed..a7ab1465 100644 --- a/src/protocols/rdp/keyboard/decompose.h +++ b/src/protocols/rdp/decompose.h @@ -17,11 +17,11 @@ * under the License. */ -#ifndef GUAC_RDP_KEYBOARD_DECOMPOSE_H -#define GUAC_RDP_KEYBOARD_DECOMPOSE_H +#ifndef GUAC_RDP_DECOMPOSE_H +#define GUAC_RDP_DECOMPOSE_H #include "config.h" -#include "keyboard/keyboard.h" +#include "keyboard.h" /** * Attempts to type the given keysym by decomposing the associated character diff --git a/src/protocols/rdp/input.c b/src/protocols/rdp/input.c index 44a46998..5e08dd6e 100644 --- a/src/protocols/rdp/input.c +++ b/src/protocols/rdp/input.c @@ -22,7 +22,7 @@ #include "client.h" #include "common/recording.h" #include "input.h" -#include "keyboard/keyboard.h" +#include "keyboard.h" #include "rdp.h" #include diff --git a/src/protocols/rdp/keyboard/keyboard.c b/src/protocols/rdp/keyboard.c similarity index 99% rename from src/protocols/rdp/keyboard/keyboard.c rename to src/protocols/rdp/keyboard.c index 7b1414c8..71aba14f 100644 --- a/src/protocols/rdp/keyboard/keyboard.c +++ b/src/protocols/rdp/keyboard.c @@ -19,9 +19,9 @@ #include "config.h" #include "client.h" -#include "keyboard/decompose.h" -#include "keyboard/keyboard.h" -#include "keyboard/keymap.h" +#include "decompose.h" +#include "keyboard.h" +#include "keymap.h" #include "rdp.h" #include diff --git a/src/protocols/rdp/keyboard/keyboard.h b/src/protocols/rdp/keyboard.h similarity index 99% rename from src/protocols/rdp/keyboard/keyboard.h rename to src/protocols/rdp/keyboard.h index d280fa41..19f46d2b 100644 --- a/src/protocols/rdp/keyboard/keyboard.h +++ b/src/protocols/rdp/keyboard.h @@ -20,7 +20,7 @@ #ifndef GUAC_RDP_KEYBOARD_H #define GUAC_RDP_KEYBOARD_H -#include "keyboard/keymap.h" +#include "keymap.h" #include diff --git a/src/protocols/rdp/keyboard/keymap.c b/src/protocols/rdp/keymap.c similarity index 98% rename from src/protocols/rdp/keyboard/keymap.c rename to src/protocols/rdp/keymap.c index b6ea7579..04b1409e 100644 --- a/src/protocols/rdp/keyboard/keymap.c +++ b/src/protocols/rdp/keymap.c @@ -19,7 +19,7 @@ #include "config.h" -#include "keyboard/keymap.h" +#include "keymap.h" #include diff --git a/src/protocols/rdp/keyboard/keymap.h b/src/protocols/rdp/keymap.h similarity index 98% rename from src/protocols/rdp/keyboard/keymap.h rename to src/protocols/rdp/keymap.h index d0074e52..9e4958cf 100644 --- a/src/protocols/rdp/keyboard/keymap.h +++ b/src/protocols/rdp/keymap.h @@ -17,8 +17,8 @@ * under the License. */ -#ifndef GUAC_RDP_KEYBOARD_KEYMAP_H -#define GUAC_RDP_KEYBOARD_KEYMAP_H +#ifndef GUAC_RDP_KEYMAP_H +#define GUAC_RDP_KEYMAP_H #include "config.h" diff --git a/src/protocols/rdp/keyboard/keymaps/base.keymap b/src/protocols/rdp/keymaps/base.keymap similarity index 100% rename from src/protocols/rdp/keyboard/keymaps/base.keymap rename to src/protocols/rdp/keymaps/base.keymap diff --git a/src/protocols/rdp/keyboard/keymaps/da_dk_qwerty.keymap b/src/protocols/rdp/keymaps/da_dk_qwerty.keymap similarity index 100% rename from src/protocols/rdp/keyboard/keymaps/da_dk_qwerty.keymap rename to src/protocols/rdp/keymaps/da_dk_qwerty.keymap diff --git a/src/protocols/rdp/keyboard/keymaps/de_ch_qwertz.keymap b/src/protocols/rdp/keymaps/de_ch_qwertz.keymap similarity index 100% rename from src/protocols/rdp/keyboard/keymaps/de_ch_qwertz.keymap rename to src/protocols/rdp/keymaps/de_ch_qwertz.keymap diff --git a/src/protocols/rdp/keyboard/keymaps/de_de_qwertz.keymap b/src/protocols/rdp/keymaps/de_de_qwertz.keymap similarity index 100% rename from src/protocols/rdp/keyboard/keymaps/de_de_qwertz.keymap rename to src/protocols/rdp/keymaps/de_de_qwertz.keymap diff --git a/src/protocols/rdp/keyboard/keymaps/en_gb_qwerty.keymap b/src/protocols/rdp/keymaps/en_gb_qwerty.keymap similarity index 100% rename from src/protocols/rdp/keyboard/keymaps/en_gb_qwerty.keymap rename to src/protocols/rdp/keymaps/en_gb_qwerty.keymap diff --git a/src/protocols/rdp/keyboard/keymaps/en_us_qwerty.keymap b/src/protocols/rdp/keymaps/en_us_qwerty.keymap similarity index 100% rename from src/protocols/rdp/keyboard/keymaps/en_us_qwerty.keymap rename to src/protocols/rdp/keymaps/en_us_qwerty.keymap diff --git a/src/protocols/rdp/keyboard/keymaps/es_es_qwerty.keymap b/src/protocols/rdp/keymaps/es_es_qwerty.keymap similarity index 100% rename from src/protocols/rdp/keyboard/keymaps/es_es_qwerty.keymap rename to src/protocols/rdp/keymaps/es_es_qwerty.keymap diff --git a/src/protocols/rdp/keyboard/keymaps/failsafe.keymap b/src/protocols/rdp/keymaps/failsafe.keymap similarity index 100% rename from src/protocols/rdp/keyboard/keymaps/failsafe.keymap rename to src/protocols/rdp/keymaps/failsafe.keymap diff --git a/src/protocols/rdp/keyboard/keymaps/fr_ch_qwertz.keymap b/src/protocols/rdp/keymaps/fr_ch_qwertz.keymap similarity index 100% rename from src/protocols/rdp/keyboard/keymaps/fr_ch_qwertz.keymap rename to src/protocols/rdp/keymaps/fr_ch_qwertz.keymap diff --git a/src/protocols/rdp/keyboard/keymaps/fr_fr_azerty.keymap b/src/protocols/rdp/keymaps/fr_fr_azerty.keymap similarity index 100% rename from src/protocols/rdp/keyboard/keymaps/fr_fr_azerty.keymap rename to src/protocols/rdp/keymaps/fr_fr_azerty.keymap diff --git a/src/protocols/rdp/keyboard/keymaps/generate.pl b/src/protocols/rdp/keymaps/generate.pl similarity index 99% rename from src/protocols/rdp/keyboard/keymaps/generate.pl rename to src/protocols/rdp/keymaps/generate.pl index 2aa360f6..f1059a75 100755 --- a/src/protocols/rdp/keyboard/keymaps/generate.pl +++ b/src/protocols/rdp/keymaps/generate.pl @@ -43,7 +43,7 @@ my @keymaps = (); open OUTPUT, ">", "_generated_keymaps.c"; print OUTPUT '#include "config.h"' . "\n" - . '#include "keyboard/keymap.h"' . "\n" + . '#include "keymap.h"' . "\n" . '#include ' . "\n" . '#include ' . "\n" . "\n" diff --git a/src/protocols/rdp/keyboard/keymaps/it_it_qwerty.keymap b/src/protocols/rdp/keymaps/it_it_qwerty.keymap similarity index 100% rename from src/protocols/rdp/keyboard/keymaps/it_it_qwerty.keymap rename to src/protocols/rdp/keymaps/it_it_qwerty.keymap diff --git a/src/protocols/rdp/keyboard/keymaps/ja_jp_qwerty.keymap b/src/protocols/rdp/keymaps/ja_jp_qwerty.keymap similarity index 100% rename from src/protocols/rdp/keyboard/keymaps/ja_jp_qwerty.keymap rename to src/protocols/rdp/keymaps/ja_jp_qwerty.keymap diff --git a/src/protocols/rdp/keyboard/keymaps/pt_br_qwerty.keymap b/src/protocols/rdp/keymaps/pt_br_qwerty.keymap similarity index 100% rename from src/protocols/rdp/keyboard/keymaps/pt_br_qwerty.keymap rename to src/protocols/rdp/keymaps/pt_br_qwerty.keymap diff --git a/src/protocols/rdp/keyboard/keymaps/sv_se_qwerty.keymap b/src/protocols/rdp/keymaps/sv_se_qwerty.keymap similarity index 100% rename from src/protocols/rdp/keyboard/keymaps/sv_se_qwerty.keymap rename to src/protocols/rdp/keymaps/sv_se_qwerty.keymap diff --git a/src/protocols/rdp/keyboard/keymaps/tr_tr_qwerty.keymap b/src/protocols/rdp/keymaps/tr_tr_qwerty.keymap similarity index 100% rename from src/protocols/rdp/keyboard/keymaps/tr_tr_qwerty.keymap rename to src/protocols/rdp/keymaps/tr_tr_qwerty.keymap diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index bf60b7c4..1bcedb1f 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -35,7 +35,7 @@ #include "fs.h" #include "gdi.h" #include "glyph.h" -#include "keyboard/keyboard.h" +#include "keyboard.h" #include "plugins/channels.h" #include "pointer.h" #include "print-job.h" diff --git a/src/protocols/rdp/rdp.h b/src/protocols/rdp/rdp.h index 41f99a2b..d50b8d26 100644 --- a/src/protocols/rdp/rdp.h +++ b/src/protocols/rdp/rdp.h @@ -30,7 +30,7 @@ #include "common/recording.h" #include "common/surface.h" #include "fs.h" -#include "keyboard/keyboard.h" +#include "keyboard.h" #include "print-job.h" #include "settings.h" diff --git a/src/protocols/rdp/settings.h b/src/protocols/rdp/settings.h index bd1daf01..6d72bbb2 100644 --- a/src/protocols/rdp/settings.h +++ b/src/protocols/rdp/settings.h @@ -22,7 +22,7 @@ #include "config.h" -#include "keyboard/keymap.h" +#include "keymap.h" #include #include From 9855d875c794e9517567e89ad13acccd7e7e03d0 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 4 Jan 2020 11:53:11 -0800 Subject: [PATCH 079/109] GUACAMOLE-249: Remove handlers for PatBlt and OpaqueRect. FreeRDP will not invoke these if the corresponding OrderSupport element is FALSE, thus they will never be called. --- src/protocols/rdp/gdi.c | 94 ----------------------------------------- src/protocols/rdp/gdi.h | 39 ----------------- src/protocols/rdp/rdp.c | 2 - 3 files changed, 135 deletions(-) diff --git a/src/protocols/rdp/gdi.c b/src/protocols/rdp/gdi.c index 1961fdb5..98502c89 100644 --- a/src/protocols/rdp/gdi.c +++ b/src/protocols/rdp/gdi.c @@ -138,76 +138,6 @@ BOOL guac_rdp_gdi_dstblt(rdpContext* context, const DSTBLT_ORDER* dstblt) { } -BOOL guac_rdp_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) { - - /* - * Note that this is not a full implementation of PATBLT. This is a - * fallback implementation which only renders a solid block of background - * color using the specified ROP3 operation, ignoring whatever brush - * was actually specified. - * - * As libguac-client-rdp explicitly tells the server not to send PATBLT, - * well-behaved RDP servers will not use this operation at all, while - * others will at least have a fallback. - */ - - /* Get client and current layer */ - guac_client* client = ((rdp_freerdp_context*) context)->client; - guac_common_surface* current_surface = - ((guac_rdp_client*) client->data)->current_surface; - - int x = patblt->nLeftRect; - int y = patblt->nTopRect; - int w = patblt->nWidth; - int h = patblt->nHeight; - - /* - * Warn that rendering is a fallback, as the server should not be sending - * this order. - */ - guac_client_log(client, GUAC_LOG_INFO, "Using fallback PATBLT (server is ignoring " - "negotiated client capabilities)"); - - /* Render rectangle based on ROP */ - switch (patblt->bRop) { - - /* If blackness, send black rectangle */ - case 0x00: - guac_common_surface_set(current_surface, x, y, w, h, - 0x00, 0x00, 0x00, 0xFF); - break; - - /* If NOP, do nothing */ - case 0xAA: - break; - - /* If operation is just a copy, send foreground only */ - case 0xCC: - case 0xF0: - guac_common_surface_set(current_surface, x, y, w, h, - (patblt->foreColor >> 16) & 0xFF, - (patblt->foreColor >> 8 ) & 0xFF, - (patblt->foreColor ) & 0xFF, - 0xFF); - break; - - /* If whiteness, send white rectangle */ - case 0xFF: - guac_common_surface_set(current_surface, x, y, w, h, - 0xFF, 0xFF, 0xFF, 0xFF); - break; - - /* Otherwise, invert entire rect */ - default: - guac_common_surface_transfer(current_surface, x, y, w, h, - GUAC_TRANSFER_BINARY_NDEST, current_surface, x, y); - - } - - return TRUE; - -} - BOOL guac_rdp_gdi_scrblt(rdpContext* context, const SCRBLT_ORDER* scrblt) { guac_client* client = ((rdp_freerdp_context*) context)->client; @@ -325,30 +255,6 @@ BOOL guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) { } -BOOL guac_rdp_gdi_opaquerect(rdpContext* context, const OPAQUE_RECT_ORDER* opaque_rect) { - - /* Get client data */ - guac_client* client = ((rdp_freerdp_context*) context)->client; - - UINT32 color = guac_rdp_convert_color(context, opaque_rect->color); - - guac_common_surface* current_surface = ((guac_rdp_client*) client->data)->current_surface; - - int x = opaque_rect->nLeftRect; - int y = opaque_rect->nTopRect; - int w = opaque_rect->nWidth; - int h = opaque_rect->nHeight; - - guac_common_surface_set(current_surface, x, y, w, h, - (color >> 16) & 0xFF, - (color >> 8 ) & 0xFF, - (color ) & 0xFF, - 0xFF); - - return TRUE; - -} - BOOL guac_rdp_gdi_set_bounds(rdpContext* context, const rdpBounds* bounds) { guac_client* client = ((rdp_freerdp_context*) context)->client; diff --git a/src/protocols/rdp/gdi.h b/src/protocols/rdp/gdi.h index 006e61ed..fa09c87f 100644 --- a/src/protocols/rdp/gdi.h +++ b/src/protocols/rdp/gdi.h @@ -62,25 +62,6 @@ guac_composite_mode guac_rdp_rop3_transfer_function(guac_client* client, */ BOOL guac_rdp_gdi_dstblt(rdpContext* context, const DSTBLT_ORDER* dstblt); -/** - * Handler for the PatBlt Primary Drawing Order. A PatBlt Primary Drawing Order - * paints a rectangle of image data, a brush pattern, and a three-way raster - * operation which considers the source data, the destination, AND the brush - * pattern. See: - * - * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpegdi/bd4bf5e7-b988-45f9-8201-3b22cc9aeeb8 - * - * @param context - * The rdpContext associated with the current RDP session. - * - * @param patblt - * The PATBLT update to handle. - * - * @return - * TRUE if successful, FALSE otherwise. - */ -BOOL guac_rdp_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt); - /** * Handler for the ScrBlt Primary Drawing Order. A ScrBlt Primary Drawing Order * paints a rectangle of image data using a raster operation which considers @@ -117,26 +98,6 @@ BOOL guac_rdp_gdi_scrblt(rdpContext* context, const SCRBLT_ORDER* scrblt); */ BOOL guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt); -/** - * Handler for the OpaqueRect Primary Drawing Order. An OpaqueRect Primary - * Drawing Order draws an opaque rectangle of a single solid color. Note that - * support for OpaqueRect cannot be claimed without also supporting PatBlt, as - * both use the same negotiation order number. See: - * - * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpegdi/1eead7aa-ac63-411a-9f8c-b1b227526877 - * - * @param context - * The rdpContext associated with the current RDP session. - * - * @param opaque_rect - * The OPAQUE RECT update to handle. - * - * @return - * TRUE if successful, FALSE otherwise. - */ -BOOL guac_rdp_gdi_opaquerect(rdpContext* context, - const OPAQUE_RECT_ORDER* opaque_rect); - /** * Handler called prior to calling the handlers for specific updates when * those updates are clipped by a bounding rectangle. This is not a true RDP diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 1bcedb1f..49795f12 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -178,10 +178,8 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { rdpPrimaryUpdate* primary = instance->update->primary; primary->DstBlt = guac_rdp_gdi_dstblt; - primary->PatBlt = guac_rdp_gdi_patblt; primary->ScrBlt = guac_rdp_gdi_scrblt; primary->MemBlt = guac_rdp_gdi_memblt; - primary->OpaqueRect = guac_rdp_gdi_opaquerect; pointer_cache_register_callbacks(instance->update); glyph_cache_register_callbacks(instance->update); From e325dbc672e3ad1d0d77d0e400a3656fed3bb9cb Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 4 Jan 2020 13:07:28 -0800 Subject: [PATCH 080/109] GUACAMOLE-249: Add/remove headers as necessary based on run through Include What You Use (IWYU) tool. --- src/protocols/rdp/bitmap.c | 8 +------- src/protocols/rdp/bitmap.h | 1 + src/protocols/rdp/channels/audio-input.c | 7 ++++--- src/protocols/rdp/channels/audio-input.h | 3 --- src/protocols/rdp/channels/cliprdr.c | 7 ++++--- src/protocols/rdp/channels/cliprdr.h | 6 ++++-- src/protocols/rdp/channels/common-svc.c | 6 +++--- src/protocols/rdp/channels/common-svc.h | 5 +++-- src/protocols/rdp/channels/disp.c | 7 ++++--- src/protocols/rdp/channels/pipe-svc.c | 12 ++++++------ src/protocols/rdp/channels/pipe-svc.h | 4 +++- src/protocols/rdp/channels/rail.c | 6 ++++-- src/protocols/rdp/channels/rail.h | 2 -- .../rdpdr/rdpdr-fs-messages-dir-info.c | 5 +++-- .../rdpdr/rdpdr-fs-messages-dir-info.h | 1 - .../rdpdr/rdpdr-fs-messages-file-info.c | 4 ++-- .../rdpdr/rdpdr-fs-messages-file-info.h | 1 - .../rdpdr/rdpdr-fs-messages-vol-info.c | 6 ++++-- .../rdpdr/rdpdr-fs-messages-vol-info.h | 1 - .../rdp/channels/rdpdr/rdpdr-fs-messages.c | 6 ++---- .../rdp/channels/rdpdr/rdpdr-fs-messages.h | 1 - src/protocols/rdp/channels/rdpdr/rdpdr-fs.c | 9 ++++----- src/protocols/rdp/channels/rdpdr/rdpdr-fs.h | 2 +- .../rdp/channels/rdpdr/rdpdr-messages.c | 4 +--- .../rdp/channels/rdpdr/rdpdr-messages.h | 2 +- .../rdp/channels/rdpdr/rdpdr-printer.c | 14 ++------------ .../rdp/channels/rdpdr/rdpdr-printer.h | 2 +- src/protocols/rdp/channels/rdpdr/rdpdr.c | 10 ++-------- src/protocols/rdp/channels/rdpdr/rdpdr.h | 6 +++++- .../rdp/channels/rdpsnd/rdpsnd-messages.c | 4 +--- .../rdp/channels/rdpsnd/rdpsnd-messages.h | 1 - src/protocols/rdp/channels/rdpsnd/rdpsnd.c | 4 +--- src/protocols/rdp/channels/rdpsnd/rdpsnd.h | 2 +- src/protocols/rdp/client.c | 16 +++++----------- src/protocols/rdp/client.h | 2 -- src/protocols/rdp/color.c | 6 ++---- src/protocols/rdp/decompose.c | 1 - src/protocols/rdp/download.c | 12 +++++------- src/protocols/rdp/download.h | 3 +-- src/protocols/rdp/error.c | 1 - src/protocols/rdp/fs.c | 7 +++---- src/protocols/rdp/fs.h | 4 ++-- src/protocols/rdp/gdi.c | 7 ++++--- src/protocols/rdp/glyph.c | 5 +---- src/protocols/rdp/glyph.h | 3 +-- src/protocols/rdp/input.c | 7 ++++--- src/protocols/rdp/keyboard.c | 3 --- src/protocols/rdp/keymap.c | 2 -- src/protocols/rdp/keymap.h | 4 ++-- src/protocols/rdp/log.c | 3 +++ src/protocols/rdp/ls.c | 13 ++++--------- src/protocols/rdp/ls.h | 4 ++-- src/protocols/rdp/plugins/channels.c | 9 ++++++--- src/protocols/rdp/plugins/channels.h | 4 ++-- .../plugins/guac-common-svc/guac-common-svc.c | 8 ++------ .../rdp/plugins/guacai/guacai-messages.c | 3 --- .../rdp/plugins/guacai/guacai-messages.h | 3 ++- src/protocols/rdp/plugins/guacai/guacai.c | 9 ++++----- src/protocols/rdp/plugins/guacai/guacai.h | 2 -- src/protocols/rdp/plugins/ptr-string.c | 4 ---- src/protocols/rdp/plugins/ptr-string.h | 2 -- src/protocols/rdp/pointer.c | 7 +++---- src/protocols/rdp/pointer.h | 3 ++- src/protocols/rdp/print-job.c | 1 - src/protocols/rdp/print-job.h | 2 -- src/protocols/rdp/rdp.c | 18 +++++++----------- src/protocols/rdp/rdp.h | 13 +++++++------ src/protocols/rdp/settings.c | 8 +++++--- src/protocols/rdp/settings.h | 2 +- src/protocols/rdp/sftp.c | 3 --- src/protocols/rdp/sftp.h | 2 -- src/protocols/rdp/unicode.c | 2 -- src/protocols/rdp/upload.c | 11 +++-------- src/protocols/rdp/upload.h | 3 +-- src/protocols/rdp/user.c | 6 +++++- 75 files changed, 157 insertions(+), 230 deletions(-) diff --git a/src/protocols/rdp/bitmap.c b/src/protocols/rdp/bitmap.c index 252f66c7..61621f2e 100644 --- a/src/protocols/rdp/bitmap.c +++ b/src/protocols/rdp/bitmap.c @@ -17,21 +17,15 @@ * under the License. */ -#include "config.h" #include "bitmap.h" -#include "client.h" #include "common/display.h" #include "common/surface.h" #include "rdp.h" -#include "settings.h" #include -#include -#include #include -#include #include -#include +#include #include #include diff --git a/src/protocols/rdp/bitmap.h b/src/protocols/rdp/bitmap.h index 70068b56..ef3e5476 100644 --- a/src/protocols/rdp/bitmap.h +++ b/src/protocols/rdp/bitmap.h @@ -24,6 +24,7 @@ #include "common/display.h" #include +#include #include #include diff --git a/src/protocols/rdp/channels/audio-input.c b/src/protocols/rdp/channels/audio-input.c index 055ce83d..29b48169 100644 --- a/src/protocols/rdp/channels/audio-input.c +++ b/src/protocols/rdp/channels/audio-input.c @@ -17,14 +17,13 @@ * under the License. */ -#include "config.h" #include "channels/audio-input.h" #include "plugins/channels.h" #include "plugins/ptr-string.h" #include "rdp.h" #include -#include +#include #include #include #include @@ -32,8 +31,10 @@ #include #include -#include #include +#include +#include +#include /** * Parses the given raw audio mimetype, producing the corresponding rate, diff --git a/src/protocols/rdp/channels/audio-input.h b/src/protocols/rdp/channels/audio-input.h index 19b6f66c..366500ac 100644 --- a/src/protocols/rdp/channels/audio-input.h +++ b/src/protocols/rdp/channels/audio-input.h @@ -20,12 +20,9 @@ #ifndef GUAC_RDP_CHANNELS_AUDIO_INPUT_H #define GUAC_RDP_CHANNELS_AUDIO_INPUT_H -#include "config.h" - #include #include #include - #include /** diff --git a/src/protocols/rdp/channels/cliprdr.c b/src/protocols/rdp/channels/cliprdr.c index 30e02f78..e62bbb14 100644 --- a/src/protocols/rdp/channels/cliprdr.c +++ b/src/protocols/rdp/channels/cliprdr.c @@ -17,8 +17,6 @@ * under the License. */ -#include "config.h" - #include "channels/cliprdr.h" #include "client.h" #include "common/clipboard.h" @@ -26,10 +24,13 @@ #include "plugins/channels.h" #include "rdp.h" -#include #include +#include #include #include +#include +#include +#include #include #include diff --git a/src/protocols/rdp/channels/cliprdr.h b/src/protocols/rdp/channels/cliprdr.h index e9b7c9a0..4c920bfb 100644 --- a/src/protocols/rdp/channels/cliprdr.h +++ b/src/protocols/rdp/channels/cliprdr.h @@ -20,12 +20,14 @@ #ifndef GUAC_RDP_CHANNELS_CLIPRDR_H #define GUAC_RDP_CHANNELS_CLIPRDR_H -#include "config.h" #include "common/clipboard.h" -#include #include +#include +#include +#include #include +#include /** * RDP clipboard, leveraging the "CLIPRDR" channel. diff --git a/src/protocols/rdp/channels/common-svc.c b/src/protocols/rdp/channels/common-svc.c index a089bac5..20254ad7 100644 --- a/src/protocols/rdp/channels/common-svc.c +++ b/src/protocols/rdp/channels/common-svc.c @@ -17,19 +17,19 @@ * under the License. */ -#include "config.h" #include "channels/common-svc.h" #include "plugins/channels.h" #include "rdp.h" -#include +#include #include -#include #include #include #include #include +#include + int guac_rdp_common_svc_load_plugin(rdpContext* context, char* name, ULONG channel_options, guac_rdp_common_svc_connect_handler* connect_handler, diff --git a/src/protocols/rdp/channels/common-svc.h b/src/protocols/rdp/channels/common-svc.h index 82a9a63d..aaa7aab4 100644 --- a/src/protocols/rdp/channels/common-svc.h +++ b/src/protocols/rdp/channels/common-svc.h @@ -20,8 +20,7 @@ #ifndef GUAC_RDP_CHANNELS_COMMON_SVC_H #define GUAC_RDP_CHANNELS_COMMON_SVC_H -#include "config.h" - +#include #include #include #include @@ -29,6 +28,8 @@ #include #include +struct guac_rdp_common_svc; + /** * The maximum number of bytes to allow within each channel name, including * null terminator. diff --git a/src/protocols/rdp/channels/disp.c b/src/protocols/rdp/channels/disp.c index d487a043..a25f6fa9 100644 --- a/src/protocols/rdp/channels/disp.c +++ b/src/protocols/rdp/channels/disp.c @@ -17,18 +17,19 @@ * under the License. */ -#include "config.h" #include "channels/disp.h" -#include "client.h" #include "plugins/channels.h" #include "rdp.h" #include "settings.h" #include #include +#include #include #include -#include + +#include +#include guac_rdp_disp* guac_rdp_disp_alloc() { diff --git a/src/protocols/rdp/channels/pipe-svc.c b/src/protocols/rdp/channels/pipe-svc.c index 3bf90ed9..e918fe7c 100644 --- a/src/protocols/rdp/channels/pipe-svc.c +++ b/src/protocols/rdp/channels/pipe-svc.c @@ -17,21 +17,21 @@ * under the License. */ -#include "config.h" #include "channels/common-svc.h" #include "channels/pipe-svc.h" -#include "client.h" #include "common/list.h" -#include "plugins/channels.h" #include "rdp.h" -#include +#include #include -#include +#include +#include +#include +#include #include -#include #include +#include void guac_rdp_pipe_svc_send_pipe(guac_socket* socket, guac_rdp_pipe_svc* pipe_svc) { diff --git a/src/protocols/rdp/channels/pipe-svc.h b/src/protocols/rdp/channels/pipe-svc.h index 6ab43f96..4ba64be1 100644 --- a/src/protocols/rdp/channels/pipe-svc.h +++ b/src/protocols/rdp/channels/pipe-svc.h @@ -20,12 +20,14 @@ #ifndef GUAC_RDP_CHANNELS_PIPE_SVC_H #define GUAC_RDP_CHANNELS_PIPE_SVC_H -#include "config.h" #include "channels/common-svc.h" +#include #include #include #include +#include +#include #include /** diff --git a/src/protocols/rdp/channels/rail.c b/src/protocols/rdp/channels/rail.c index 37017c43..eb645a8f 100644 --- a/src/protocols/rdp/channels/rail.c +++ b/src/protocols/rdp/channels/rail.c @@ -17,19 +17,21 @@ * under the License. */ -#include "config.h" #include "channels/rail.h" -#include "client.h" #include "plugins/channels.h" #include "rdp.h" #include "settings.h" #include +#include #include +#include #include #include +#include #include +#include /** * Completes initialization of the RemoteApp session, sending client system diff --git a/src/protocols/rdp/channels/rail.h b/src/protocols/rdp/channels/rail.h index 9b0d231a..08560343 100644 --- a/src/protocols/rdp/channels/rail.h +++ b/src/protocols/rdp/channels/rail.h @@ -20,8 +20,6 @@ #ifndef GUAC_RDP_CHANNELS_RAIL_H #define GUAC_RDP_CHANNELS_RAIL_H -#include "config.h" - #include /** diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.c index 25d355f5..70eb8cd5 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.c @@ -17,16 +17,17 @@ * under the License. */ -#include "config.h" #include "channels/rdpdr/rdpdr-fs-messages-dir-info.h" #include "channels/rdpdr/rdpdr.h" #include "fs.h" #include "unicode.h" +#include #include -#include +#include #include +#include #include void guac_rdpdr_fs_process_query_directory_info(guac_rdp_common_svc* svc, diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h index c4b0f8ad..fb49ce93 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h @@ -28,7 +28,6 @@ * @file rdpdr-fs-messages-dir-info.h */ -#include "config.h" #include "channels/common-svc.h" #include "channels/rdpdr/rdpdr.h" diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.c index 0e4f66f0..0f453038 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.c @@ -17,18 +17,18 @@ * under the License. */ -#include "config.h" #include "channels/rdpdr/rdpdr-fs-messages-file-info.h" #include "channels/rdpdr/rdpdr.h" #include "download.h" #include "fs.h" #include "unicode.h" +#include #include +#include #include #include -#include #include #include diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h index dfd207ae..25f13cee 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h @@ -27,7 +27,6 @@ * @file rdpdr-fs-messages-file-info.h */ -#include "config.h" #include "channels/common-svc.h" #include "channels/rdpdr/rdpdr.h" diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.c index 1ab9dd21..0ce46844 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.c @@ -17,15 +17,17 @@ * under the License. */ -#include "config.h" -#include "channels/rdpdr/rdpdr-messages.h" +#include "channels/common-svc.h" #include "channels/rdpdr/rdpdr-fs-messages-vol-info.h" #include "channels/rdpdr/rdpdr-fs.h" #include "channels/rdpdr/rdpdr.h" #include "fs.h" +#include #include #include +#include +#include #include #include diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.h index 87c0745c..b8c9522e 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-vol-info.h @@ -28,7 +28,6 @@ * @file rdpdr-fs-messages-vol-info.h */ -#include "config.h" #include "channels/rdpdr/rdpdr.h" #include diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c index 60fa6852..529eea57 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c @@ -17,12 +17,11 @@ * under the License. */ -#include "config.h" +#include "channels/common-svc.h" #include "channels/rdpdr/rdpdr-fs-messages-dir-info.h" #include "channels/rdpdr/rdpdr-fs-messages-file-info.h" #include "channels/rdpdr/rdpdr-fs-messages-vol-info.h" #include "channels/rdpdr/rdpdr-fs-messages.h" -#include "channels/rdpdr/rdpdr-messages.h" #include "channels/rdpdr/rdpdr.h" #include "download.h" #include "fs.h" @@ -30,11 +29,10 @@ #include #include -#include +#include #include #include -#include #include #include #include diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.h index bfc8312b..63fcbb9a 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.h @@ -28,7 +28,6 @@ * @file rdpdr-fs-messages.h */ -#include "config.h" #include "channels/rdpdr/rdpdr.h" #include diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs.c index 50f3c287..ed67ac6f 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs.c @@ -17,20 +17,19 @@ * under the License. */ -#include "config.h" -#include "channels/rdpdr/rdpdr-fs-messages.h" #include "channels/rdpdr/rdpdr-fs.h" -#include "channels/rdpdr/rdpdr-messages.h" +#include "channels/rdpdr/rdpdr-fs-messages.h" #include "channels/rdpdr/rdpdr.h" #include "rdp.h" #include +#include #include -#include -#include #include #include +#include + void guac_rdpdr_device_fs_iorequest_handler(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, wStream* input_stream) { diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h index 6f6e5d1d..129fb267 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h @@ -31,7 +31,7 @@ * @file rdpdr-fs.h */ -#include "config.h" +#include "channels/common-svc.h" #include "channels/rdpdr/rdpdr.h" #include diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-messages.c b/src/protocols/rdp/channels/rdpdr/rdpdr-messages.c index c4d4b032..28a27e67 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-messages.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-messages.c @@ -17,15 +17,13 @@ * under the License. */ -#include "config.h" #include "channels/rdpdr/rdpdr-messages.h" #include "channels/rdpdr/rdpdr.h" #include "rdp.h" -#include "unicode.h" +#include "settings.h" #include #include -#include #include #include diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-messages.h b/src/protocols/rdp/channels/rdpdr/rdpdr-messages.h index 27684cf2..a79c83b4 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-messages.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-messages.h @@ -20,7 +20,7 @@ #ifndef GUAC_RDP_CHANNELS_RDPDR_MESSAGES_H #define GUAC_RDP_CHANNELS_RDPDR_MESSAGES_H -#include "config.h" +#include "channels/common-svc.h" #include "channels/rdpdr/rdpdr.h" #include diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-printer.c b/src/protocols/rdp/channels/rdpdr/rdpdr-printer.c index e435d32b..d90116f5 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-printer.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-printer.c @@ -17,8 +17,6 @@ * under the License. */ -#include "config.h" -#include "channels/rdpdr/rdpdr-messages.h" #include "channels/rdpdr/rdpdr-printer.h" #include "channels/rdpdr/rdpdr.h" #include "print-job.h" @@ -26,21 +24,13 @@ #include "unicode.h" #include +#include #include -#include -#include -#include #include -#include -#include +#include #include -#include -#include -#include #include -#include -#include void guac_rdpdr_process_print_job_create(guac_rdp_common_svc* svc, guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest, diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-printer.h b/src/protocols/rdp/channels/rdpdr/rdpdr-printer.h index 106d6be3..a6865d84 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-printer.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-printer.h @@ -20,7 +20,7 @@ #ifndef GUAC_RDP_CHANNELS_RDPDR_PRINTER_H #define GUAC_RDP_CHANNELS_RDPDR_PRINTER_H -#include "config.h" +#include "channels/common-svc.h" #include "channels/rdpdr/rdpdr.h" #include diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr.c b/src/protocols/rdp/channels/rdpdr/rdpdr.c index d0d3143e..f67a55be 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr.c @@ -17,26 +17,20 @@ * under the License. */ -#include "config.h" +#include "channels/rdpdr/rdpdr.h" #include "channels/rdpdr/rdpdr-fs.h" #include "channels/rdpdr/rdpdr-messages.h" #include "channels/rdpdr/rdpdr-printer.h" -#include "channels/rdpdr/rdpdr.h" -#include "fs.h" -#include "plugins/channels.h" #include "rdp.h" #include "settings.h" #include #include +#include #include -#include -#include -#include #include #include -#include void guac_rdpdr_process_receive(guac_rdp_common_svc* svc, wStream* input_stream) { diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr.h b/src/protocols/rdp/channels/rdpdr/rdpdr.h index fc494ee1..b074348a 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr.h @@ -20,11 +20,15 @@ #ifndef GUAC_RDP_CHANNELS_RDPDR_H #define GUAC_RDP_CHANNELS_RDPDR_H -#include "config.h" #include "channels/common-svc.h" #include #include +#include + +#include + +struct guac_rdpdr_device; /** * The maximum number of bytes to allow for a device read. diff --git a/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.c b/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.c index f0dedaa0..1d69e069 100644 --- a/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.c +++ b/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.c @@ -17,8 +17,6 @@ * under the License. */ -#include "config.h" - #include "channels/rdpsnd/rdpsnd-messages.h" #include "channels/rdpsnd/rdpsnd.h" #include "rdp.h" @@ -29,8 +27,8 @@ #include #include -#include #include +#include void guac_rdpsnd_formats_handler(guac_rdp_common_svc* svc, wStream* input_stream, guac_rdpsnd_pdu_header* header) { diff --git a/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.h b/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.h index 3c3733c6..9271151f 100644 --- a/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.h +++ b/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.h @@ -20,7 +20,6 @@ #ifndef GUAC_RDP_CHANNELS_RDPSND_MESSAGES_H #define GUAC_RDP_CHANNELS_RDPSND_MESSAGES_H -#include "config.h" #include "channels/common-svc.h" #include diff --git a/src/protocols/rdp/channels/rdpsnd/rdpsnd.c b/src/protocols/rdp/channels/rdpsnd/rdpsnd.c index 5859d4e3..be6034d2 100644 --- a/src/protocols/rdp/channels/rdpsnd/rdpsnd.c +++ b/src/protocols/rdp/channels/rdpsnd/rdpsnd.c @@ -17,16 +17,14 @@ * under the License. */ -#include "config.h" #include "channels/common-svc.h" -#include "channels/rdpsnd/rdpsnd-messages.h" #include "channels/rdpsnd/rdpsnd.h" +#include "channels/rdpsnd/rdpsnd-messages.h" #include "rdp.h" #include #include #include -#include #include #include diff --git a/src/protocols/rdp/channels/rdpsnd/rdpsnd.h b/src/protocols/rdp/channels/rdpsnd/rdpsnd.h index 97b6085f..cd7fe233 100644 --- a/src/protocols/rdp/channels/rdpsnd/rdpsnd.h +++ b/src/protocols/rdp/channels/rdpsnd/rdpsnd.h @@ -20,9 +20,9 @@ #ifndef GUAC_RDP_CHANNELS_RDPSND_H #define GUAC_RDP_CHANNELS_RDPSND_H -#include "config.h" #include "channels/common-svc.h" +#include #include /** diff --git a/src/protocols/rdp/client.c b/src/protocols/rdp/client.c index c8150acb..8cbc1635 100644 --- a/src/protocols/rdp/client.c +++ b/src/protocols/rdp/client.c @@ -17,14 +17,16 @@ * under the License. */ -#include "config.h" -#include "channels/audio-input.h" -#include "channels/disp.h" #include "client.h" +#include "channels/audio-input.h" +#include "channels/cliprdr.h" +#include "channels/disp.h" #include "common/recording.h" +#include "config.h" #include "fs.h" #include "log.h" #include "rdp.h" +#include "settings.h" #include "user.h" #ifdef ENABLE_COMMON_SSH @@ -33,19 +35,11 @@ #include "common-ssh/user.h" #endif -#include -#include -#include -#include -#include #include #include -#include -#include #include #include -#include int guac_client_init(guac_client* client, int argc, char** argv) { diff --git a/src/protocols/rdp/client.h b/src/protocols/rdp/client.h index 4f6c2662..9acd33ab 100644 --- a/src/protocols/rdp/client.h +++ b/src/protocols/rdp/client.h @@ -20,8 +20,6 @@ #ifndef GUAC_RDP_CLIENT_H #define GUAC_RDP_CLIENT_H -#include "config.h" - #include /** diff --git a/src/protocols/rdp/color.c b/src/protocols/rdp/color.c index c7db078d..cfe8d344 100644 --- a/src/protocols/rdp/color.c +++ b/src/protocols/rdp/color.c @@ -17,10 +17,6 @@ * under the License. */ -#include "config.h" - -#include "client.h" -#include "rdp.h" #include "settings.h" #include @@ -28,6 +24,8 @@ #include #include +#include + UINT32 guac_rdp_get_native_pixel_format(BOOL alpha) { uint8_t color[] = { 0x0A, 0x0B, 0x0C, 0x0D }; diff --git a/src/protocols/rdp/decompose.c b/src/protocols/rdp/decompose.c index 5f559d99..e42a7697 100644 --- a/src/protocols/rdp/decompose.c +++ b/src/protocols/rdp/decompose.c @@ -17,7 +17,6 @@ * under the License. */ -#include "config.h" #include "keyboard.h" /** diff --git a/src/protocols/rdp/download.c b/src/protocols/rdp/download.c index 34f7e2e6..ceb211ed 100644 --- a/src/protocols/rdp/download.c +++ b/src/protocols/rdp/download.c @@ -17,23 +17,21 @@ * under the License. */ -#include "config.h" -#include "client.h" +#include "common/json.h" #include "download.h" #include "fs.h" #include "ls.h" #include "rdp.h" -#include -#include -#include #include +#include #include #include #include #include -#include -#include +#include +#include +#include #include diff --git a/src/protocols/rdp/download.h b/src/protocols/rdp/download.h index c15dba67..2989658c 100644 --- a/src/protocols/rdp/download.h +++ b/src/protocols/rdp/download.h @@ -20,12 +20,11 @@ #ifndef GUAC_RDP_DOWNLOAD_H #define GUAC_RDP_DOWNLOAD_H -#include "config.h" #include "common/json.h" -#include #include #include +#include #include diff --git a/src/protocols/rdp/error.c b/src/protocols/rdp/error.c index 0fbc6de9..de0e1cd3 100644 --- a/src/protocols/rdp/error.c +++ b/src/protocols/rdp/error.c @@ -17,7 +17,6 @@ * under the License. */ -#include "config.h" #include "error.h" #include "rdp.h" diff --git a/src/protocols/rdp/fs.c b/src/protocols/rdp/fs.c index 8b48b945..74664b4b 100644 --- a/src/protocols/rdp/fs.c +++ b/src/protocols/rdp/fs.c @@ -17,19 +17,19 @@ * under the License. */ -#include "config.h" - -#include "download.h" #include "fs.h" +#include "download.h" #include "upload.h" #include #include #include +#include #include #include #include #include +#include #include #include @@ -40,7 +40,6 @@ #include #include #include -#include #include guac_rdp_fs* guac_rdp_fs_alloc(guac_client* client, const char* drive_path, diff --git a/src/protocols/rdp/fs.h b/src/protocols/rdp/fs.h index 168f2df1..56c134f0 100644 --- a/src/protocols/rdp/fs.h +++ b/src/protocols/rdp/fs.h @@ -31,10 +31,10 @@ * @file fs.h */ -#include "config.h" - #include +#include #include +#include #include #include diff --git a/src/protocols/rdp/gdi.c b/src/protocols/rdp/gdi.c index 98502c89..feb6505d 100644 --- a/src/protocols/rdp/gdi.c +++ b/src/protocols/rdp/gdi.c @@ -17,20 +17,21 @@ * under the License. */ -#include "config.h" #include "bitmap.h" -#include "client.h" -#include "color.h" +#include "common/display.h" #include "common/surface.h" #include "rdp.h" #include "settings.h" #include #include +#include +#include #include #include #include +#include #include guac_transfer_function guac_rdp_rop3_transfer_function(guac_client* client, diff --git a/src/protocols/rdp/glyph.c b/src/protocols/rdp/glyph.c index 3050c65c..cecaa8d9 100644 --- a/src/protocols/rdp/glyph.c +++ b/src/protocols/rdp/glyph.c @@ -17,19 +17,16 @@ * under the License. */ -#include "config.h" -#include "client.h" #include "color.h" #include "common/surface.h" +#include "config.h" #include "glyph.h" #include "rdp.h" -#include "settings.h" #include #include #include -#include #include #include diff --git a/src/protocols/rdp/glyph.h b/src/protocols/rdp/glyph.h index 0d4bf7b0..1e9b389b 100644 --- a/src/protocols/rdp/glyph.h +++ b/src/protocols/rdp/glyph.h @@ -20,10 +20,9 @@ #ifndef GUAC_RDP_GLYPH_H #define GUAC_RDP_GLYPH_H -#include "config.h" - #include #include +#include #include /** diff --git a/src/protocols/rdp/input.c b/src/protocols/rdp/input.c index 5e08dd6e..8f77dc06 100644 --- a/src/protocols/rdp/input.c +++ b/src/protocols/rdp/input.c @@ -17,19 +17,20 @@ * under the License. */ -#include "config.h" #include "channels/disp.h" -#include "client.h" +#include "common/cursor.h" +#include "common/display.h" #include "common/recording.h" #include "input.h" #include "keyboard.h" #include "rdp.h" +#include "settings.h" #include #include #include +#include -#include #include int guac_rdp_user_mouse_handler(guac_user* user, int x, int y, int mask) { diff --git a/src/protocols/rdp/keyboard.c b/src/protocols/rdp/keyboard.c index 71aba14f..42cc4db6 100644 --- a/src/protocols/rdp/keyboard.c +++ b/src/protocols/rdp/keyboard.c @@ -17,8 +17,6 @@ * under the License. */ -#include "config.h" -#include "client.h" #include "decompose.h" #include "keyboard.h" #include "keymap.h" @@ -28,7 +26,6 @@ #include #include -#include #include /** diff --git a/src/protocols/rdp/keymap.c b/src/protocols/rdp/keymap.c index 04b1409e..b71b402d 100644 --- a/src/protocols/rdp/keymap.c +++ b/src/protocols/rdp/keymap.c @@ -17,8 +17,6 @@ * under the License. */ -#include "config.h" - #include "keymap.h" #include diff --git a/src/protocols/rdp/keymap.h b/src/protocols/rdp/keymap.h index 9e4958cf..6ec627f5 100644 --- a/src/protocols/rdp/keymap.h +++ b/src/protocols/rdp/keymap.h @@ -20,10 +20,10 @@ #ifndef GUAC_RDP_KEYMAP_H #define GUAC_RDP_KEYMAP_H -#include "config.h" - #include +struct guac_rdp_keymap; + /** * Represents a keysym-to-scancode mapping for RDP, with extra information * about the state of prerequisite keysyms. diff --git a/src/protocols/rdp/log.c b/src/protocols/rdp/log.c index fa0a074f..29414c17 100644 --- a/src/protocols/rdp/log.c +++ b/src/protocols/rdp/log.c @@ -19,6 +19,9 @@ #include #include +#include + +#include /** * The guac_client that should be used within this process for FreeRDP log diff --git a/src/protocols/rdp/ls.c b/src/protocols/rdp/ls.c index f008da90..300bf93c 100644 --- a/src/protocols/rdp/ls.c +++ b/src/protocols/rdp/ls.c @@ -17,24 +17,19 @@ * under the License. */ -#include "config.h" -#include "client.h" #include "fs.h" #include "ls.h" -#include "rdp.h" -#include -#include -#include #include #include #include #include -#include -#include -#include +#include +#include +#include #include +#include int guac_rdp_ls_ack_handler(guac_user* user, guac_stream* stream, char* message, guac_protocol_status status) { diff --git a/src/protocols/rdp/ls.h b/src/protocols/rdp/ls.h index 21a2eb85..be6a10c7 100644 --- a/src/protocols/rdp/ls.h +++ b/src/protocols/rdp/ls.h @@ -20,12 +20,12 @@ #ifndef GUAC_RDP_LS_H #define GUAC_RDP_LS_H -#include "config.h" #include "common/json.h" +#include "fs.h" -#include #include #include +#include #include diff --git a/src/protocols/rdp/plugins/channels.c b/src/protocols/rdp/plugins/channels.c index 9cf5a36b..a183b667 100644 --- a/src/protocols/rdp/plugins/channels.c +++ b/src/protocols/rdp/plugins/channels.c @@ -17,13 +17,16 @@ * under the License. */ -#include "config.h" #include "plugins/channels.h" -#include "rdp.h" #include #include -#include +#include +#include + +#include +#include +#include int guac_rdp_wrapped_entry_ex_count = 0; diff --git a/src/protocols/rdp/plugins/channels.h b/src/protocols/rdp/plugins/channels.h index f324f876..59d6c829 100644 --- a/src/protocols/rdp/plugins/channels.h +++ b/src/protocols/rdp/plugins/channels.h @@ -20,10 +20,10 @@ #ifndef GUAC_RDP_PLUGINS_CHANNELS_H #define GUAC_RDP_PLUGINS_CHANNELS_H -#include "config.h" - #include #include +#include +#include /** * The maximum number of static channels supported by Guacamole's RDP support. diff --git a/src/protocols/rdp/plugins/guac-common-svc/guac-common-svc.c b/src/protocols/rdp/plugins/guac-common-svc/guac-common-svc.c index c55b606e..fbba4842 100644 --- a/src/protocols/rdp/plugins/guac-common-svc/guac-common-svc.c +++ b/src/protocols/rdp/plugins/guac-common-svc/guac-common-svc.c @@ -17,19 +17,15 @@ * under the License. */ -#include "config.h" #include "channels/common-svc.h" -#include +#include #include -#include -#include -#include #include +#include #include #include -#include /** * Event handler for events which deal with data transmitted over an open SVC. diff --git a/src/protocols/rdp/plugins/guacai/guacai-messages.c b/src/protocols/rdp/plugins/guacai/guacai-messages.c index bb759e56..9e4b4142 100644 --- a/src/protocols/rdp/plugins/guacai/guacai-messages.c +++ b/src/protocols/rdp/plugins/guacai/guacai-messages.c @@ -17,14 +17,11 @@ * under the License. */ -#include "config.h" #include "channels/audio-input.h" #include "plugins/guacai/guacai-messages.h" #include "rdp.h" -#include #include -#include #include #include diff --git a/src/protocols/rdp/plugins/guacai/guacai-messages.h b/src/protocols/rdp/plugins/guacai/guacai-messages.h index 91173c3d..49fbd1cb 100644 --- a/src/protocols/rdp/plugins/guacai/guacai-messages.h +++ b/src/protocols/rdp/plugins/guacai/guacai-messages.h @@ -20,11 +20,12 @@ #ifndef GUAC_RDP_PLUGINS_GUACAI_MESSAGES_H #define GUAC_RDP_PLUGINS_GUACAI_MESSAGES_H -#include "config.h" +#include "channels/audio-input.h" #include #include #include +#include /** * The format tag associated with raw wave audio (WAVE_FORMAT_PCM). This format diff --git a/src/protocols/rdp/plugins/guacai/guacai.c b/src/protocols/rdp/plugins/guacai/guacai.c index de9dfb91..80dd87f3 100644 --- a/src/protocols/rdp/plugins/guacai/guacai.c +++ b/src/protocols/rdp/plugins/guacai/guacai.c @@ -17,21 +17,20 @@ * under the License. */ -#include "config.h" #include "channels/audio-input.h" -#include "plugins/guacai/guacai-messages.h" #include "plugins/guacai/guacai.h" +#include "plugins/guacai/guacai-messages.h" #include "plugins/ptr-string.h" #include "rdp.h" -#include #include -#include +#include #include #include +#include +#include #include -#include /** * Handles the given data received along the AUDIO_INPUT channel of the RDP diff --git a/src/protocols/rdp/plugins/guacai/guacai.h b/src/protocols/rdp/plugins/guacai/guacai.h index dacf531a..d26563cd 100644 --- a/src/protocols/rdp/plugins/guacai/guacai.h +++ b/src/protocols/rdp/plugins/guacai/guacai.h @@ -20,8 +20,6 @@ #ifndef GUAC_RDP_PLUGINS_GUACAI_H #define GUAC_RDP_PLUGINS_GUACAI_H -#include "config.h" - #include #include #include diff --git a/src/protocols/rdp/plugins/ptr-string.c b/src/protocols/rdp/plugins/ptr-string.c index 91311871..324a5195 100644 --- a/src/protocols/rdp/plugins/ptr-string.c +++ b/src/protocols/rdp/plugins/ptr-string.c @@ -17,13 +17,9 @@ * under the License. */ -#include "config.h" #include "plugins/ptr-string.h" -#include - #include -#include void guac_rdp_ptr_to_string(void* data, char* str) { diff --git a/src/protocols/rdp/plugins/ptr-string.h b/src/protocols/rdp/plugins/ptr-string.h index bcc226c4..ef682b1d 100644 --- a/src/protocols/rdp/plugins/ptr-string.h +++ b/src/protocols/rdp/plugins/ptr-string.h @@ -20,8 +20,6 @@ #ifndef GUAC_RDP_PLUGINS_PTR_STRING_H #define GUAC_RDP_PLUGINS_PTR_STRING_H -#include "config.h" - #include /** diff --git a/src/protocols/rdp/pointer.c b/src/protocols/rdp/pointer.c index 41fa5f4c..9f66c6a4 100644 --- a/src/protocols/rdp/pointer.c +++ b/src/protocols/rdp/pointer.c @@ -17,20 +17,19 @@ * under the License. */ -#include "config.h" -#include "client.h" #include "color.h" #include "common/cursor.h" #include "common/display.h" +#include "common/surface.h" #include "pointer.h" #include "rdp.h" #include +#include #include #include #include - -#include +#include BOOL guac_rdp_pointer_new(rdpContext* context, rdpPointer* pointer) { diff --git a/src/protocols/rdp/pointer.h b/src/protocols/rdp/pointer.h index c5ba319f..b5fa6a23 100644 --- a/src/protocols/rdp/pointer.h +++ b/src/protocols/rdp/pointer.h @@ -20,10 +20,11 @@ #ifndef GUAC_RDP_POINTER_H #define GUAC_RDP_POINTER_H -#include "config.h" #include "common/display.h" #include +#include +#include /** * Guacamole-specific rdpPointer data. diff --git a/src/protocols/rdp/print-job.c b/src/protocols/rdp/print-job.c index fed49bb3..5a75c6eb 100644 --- a/src/protocols/rdp/print-job.c +++ b/src/protocols/rdp/print-job.c @@ -17,7 +17,6 @@ * under the License. */ -#include "config.h" #include "print-job.h" #include diff --git a/src/protocols/rdp/print-job.h b/src/protocols/rdp/print-job.h index 98897ec1..fb990a82 100644 --- a/src/protocols/rdp/print-job.h +++ b/src/protocols/rdp/print-job.h @@ -20,8 +20,6 @@ #ifndef GUAC_RDP_PRINT_JOB_H #define GUAC_RDP_PRINT_JOB_H -#include "config.h" - #include #include #include diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 49795f12..45914b27 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -17,7 +17,6 @@ * under the License. */ -#include "config.h" #include "bitmap.h" #include "channels/audio-input.h" #include "channels/cliprdr.h" @@ -31,6 +30,7 @@ #include "common/cursor.h" #include "common/display.h" #include "common/recording.h" +#include "config.h" #include "error.h" #include "fs.h" #include "gdi.h" @@ -56,26 +56,22 @@ #include #include #include -#include -#include -#include #include #include -#include -#include +#include +#include +#include +#include #include #include #include #include #include +#include +#include #include -#include -#include -#include #include -#include -#include #include BOOL rdp_freerdp_pre_connect(freerdp* instance) { diff --git a/src/protocols/rdp/rdp.h b/src/protocols/rdp/rdp.h index d50b8d26..43f6dc2d 100644 --- a/src/protocols/rdp/rdp.h +++ b/src/protocols/rdp/rdp.h @@ -20,7 +20,6 @@ #ifndef GUAC_RDP_H #define GUAC_RDP_H -#include "config.h" #include "channels/audio-input.h" #include "channels/cliprdr.h" #include "channels/disp.h" @@ -29,22 +28,24 @@ #include "common/list.h" #include "common/recording.h" #include "common/surface.h" +#include "config.h" #include "fs.h" #include "keyboard.h" #include "print-job.h" #include "settings.h" -#include -#include -#include -#include - #ifdef ENABLE_COMMON_SSH #include "common-ssh/sftp.h" #include "common-ssh/ssh.h" #include "common-ssh/user.h" #endif +#include +#include +#include +#include +#include + #include #include diff --git a/src/protocols/rdp/settings.c b/src/protocols/rdp/settings.c index 872f14f8..97e9dafe 100644 --- a/src/protocols/rdp/settings.c +++ b/src/protocols/rdp/settings.c @@ -17,21 +17,23 @@ * under the License. */ -#include "config.h" -#include "client.h" #include "common/string.h" -#include "rdp.h" +#include "config.h" #include "resolution.h" #include "settings.h" #include #include +#include +#include #include #include +#include #include #include #include +#include #include /* Client plugin arguments */ diff --git a/src/protocols/rdp/settings.h b/src/protocols/rdp/settings.h index 6d72bbb2..0935f843 100644 --- a/src/protocols/rdp/settings.h +++ b/src/protocols/rdp/settings.h @@ -21,10 +21,10 @@ #define GUAC_RDP_SETTINGS_H #include "config.h" - #include "keymap.h" #include +#include #include /** diff --git a/src/protocols/rdp/sftp.c b/src/protocols/rdp/sftp.c index ecfe35fe..0fc25803 100644 --- a/src/protocols/rdp/sftp.c +++ b/src/protocols/rdp/sftp.c @@ -17,14 +17,11 @@ * under the License. */ -#include "config.h" - #include "common-ssh/sftp.h" #include "rdp.h" #include "sftp.h" #include -#include #include int guac_rdp_sftp_file_handler(guac_user* user, guac_stream* stream, diff --git a/src/protocols/rdp/sftp.h b/src/protocols/rdp/sftp.h index d7683243..3f7f9e2c 100644 --- a/src/protocols/rdp/sftp.h +++ b/src/protocols/rdp/sftp.h @@ -20,8 +20,6 @@ #ifndef GUAC_RDP_SFTP_H #define GUAC_RDP_SFTP_H -#include "config.h" - #include #include diff --git a/src/protocols/rdp/unicode.c b/src/protocols/rdp/unicode.c index 5369f4c4..f055bea6 100644 --- a/src/protocols/rdp/unicode.c +++ b/src/protocols/rdp/unicode.c @@ -17,8 +17,6 @@ * under the License. */ -#include "config.h" - #include #include diff --git a/src/protocols/rdp/upload.c b/src/protocols/rdp/upload.c index 24295ec5..07cb8cad 100644 --- a/src/protocols/rdp/upload.c +++ b/src/protocols/rdp/upload.c @@ -17,22 +17,17 @@ * under the License. */ -#include "config.h" -#include "client.h" #include "fs.h" #include "rdp.h" #include "upload.h" -#include -#include -#include #include +#include #include #include #include -#include -#include -#include +#include +#include #include diff --git a/src/protocols/rdp/upload.h b/src/protocols/rdp/upload.h index b7563ffe..254538f6 100644 --- a/src/protocols/rdp/upload.h +++ b/src/protocols/rdp/upload.h @@ -20,12 +20,11 @@ #ifndef GUAC_RDP_UPLOAD_H #define GUAC_RDP_UPLOAD_H -#include "config.h" #include "common/json.h" -#include #include #include +#include #include diff --git a/src/protocols/rdp/user.c b/src/protocols/rdp/user.c index b070b4a2..2e96b9a2 100644 --- a/src/protocols/rdp/user.c +++ b/src/protocols/rdp/user.c @@ -17,10 +17,12 @@ * under the License. */ -#include "config.h" #include "channels/audio-input.h" +#include "channels/cliprdr.h" #include "channels/pipe-svc.h" +#include "common/cursor.h" #include "common/display.h" +#include "config.h" #include "input.h" #include "rdp.h" #include "settings.h" @@ -35,9 +37,11 @@ #include #include #include +#include #include #include +#include int guac_rdp_user_join_handler(guac_user* user, int argc, char** argv) { From a54a12362ca0fc571184e2698e1c27718e288f53 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 6 Jan 2020 11:04:12 -0800 Subject: [PATCH 081/109] GUACAMOLE-249: Use ReadColor() / WriteColor() around FreeRDPConvertColor(). The latter expects color input to be in an intermediate representation resulting from using ReadColor(), and produces color output which cannot be used until converted back with WriteColor(). --- src/protocols/rdp/color.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/protocols/rdp/color.c b/src/protocols/rdp/color.c index cfe8d344..9befcfb3 100644 --- a/src/protocols/rdp/color.c +++ b/src/protocols/rdp/color.c @@ -45,11 +45,23 @@ UINT32 guac_rdp_get_native_pixel_format(BOOL alpha) { UINT32 guac_rdp_convert_color(rdpContext* context, UINT32 color) { int depth = guac_rdp_get_depth(context->instance); + int src_format = gdi_get_pixel_format(depth); + int dst_format = guac_rdp_get_native_pixel_format(TRUE); rdpGdi* gdi = context->gdi; - /* Convert given color to ARGB32 */ - return FreeRDPConvertColor(color, gdi_get_pixel_format(depth), - guac_rdp_get_native_pixel_format(TRUE), &gdi->palette); + /* Convert provided color into the intermediate representation expected by + * FreeRDPConvertColor() */ + UINT32 intermed = ReadColor((BYTE*) &color, src_format); + + /* Convert color from RDP source format to the native format used by Cairo, + * still maintaining intermediate representation */ + intermed = FreeRDPConvertColor(intermed, src_format, dst_format, + &gdi->palette); + + /* Convert color from intermediate representation to the actual desired + * format */ + WriteColor((BYTE*) &color, dst_format, intermed); + return color; } From 0677a9ae4d660bfc7c90e0507f96be7dced8a79c Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 6 Jan 2020 11:15:00 -0800 Subject: [PATCH 082/109] GUACAMOLE-249: Common surface should still pay attention to dirty flag, regardless of the new special case for unrealized surfaces. --- src/common/surface.c | 66 +++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/src/common/surface.c b/src/common/surface.c index ccac11da..98d234dc 100644 --- a/src/common/surface.c +++ b/src/common/surface.c @@ -280,47 +280,51 @@ static int __guac_common_surface_is_opaque(guac_common_surface* surface, */ static int __guac_common_should_combine(guac_common_surface* surface, const guac_common_rect* rect, int rect_only) { - int combined_cost, dirty_cost, update_cost; - /* Always favor combining updates if surface is currently a purely * server-side scratch area */ if (!surface->realized) return 1; - /* Simulate combination */ - guac_common_rect combined = surface->dirty_rect; - guac_common_rect_extend(&combined, rect); + if (surface->dirty) { - /* Combine if result is still small */ - if (combined.width <= GUAC_SURFACE_NEGLIGIBLE_WIDTH && combined.height <= GUAC_SURFACE_NEGLIGIBLE_HEIGHT) - return 1; + int combined_cost, dirty_cost, update_cost; - /* Estimate costs of the existing update, new update, and both combined */ - combined_cost = GUAC_SURFACE_BASE_COST + combined.width * combined.height; - dirty_cost = GUAC_SURFACE_BASE_COST + surface->dirty_rect.width * surface->dirty_rect.height; - update_cost = GUAC_SURFACE_BASE_COST + rect->width * rect->height; + /* Simulate combination */ + guac_common_rect combined = surface->dirty_rect; + guac_common_rect_extend(&combined, rect); - /* Reduce cost if no image data */ - if (rect_only) - update_cost /= GUAC_SURFACE_DATA_FACTOR; - - /* Combine if cost estimate shows benefit */ - if (combined_cost <= update_cost + dirty_cost) - return 1; - - /* Combine if increase in cost is negligible */ - if (combined_cost - dirty_cost <= dirty_cost / GUAC_SURFACE_NEGLIGIBLE_INCREASE) - return 1; - - if (combined_cost - update_cost <= update_cost / GUAC_SURFACE_NEGLIGIBLE_INCREASE) - return 1; - - /* Combine if we anticipate further updates, as this update follows a common fill pattern */ - if (rect->x == surface->dirty_rect.x && rect->y == surface->dirty_rect.y + surface->dirty_rect.height) { - if (combined_cost <= (dirty_cost + update_cost) * GUAC_SURFACE_FILL_PATTERN_FACTOR) + /* Combine if result is still small */ + if (combined.width <= GUAC_SURFACE_NEGLIGIBLE_WIDTH && combined.height <= GUAC_SURFACE_NEGLIGIBLE_HEIGHT) return 1; - } + /* Estimate costs of the existing update, new update, and both combined */ + combined_cost = GUAC_SURFACE_BASE_COST + combined.width * combined.height; + dirty_cost = GUAC_SURFACE_BASE_COST + surface->dirty_rect.width * surface->dirty_rect.height; + update_cost = GUAC_SURFACE_BASE_COST + rect->width * rect->height; + + /* Reduce cost if no image data */ + if (rect_only) + update_cost /= GUAC_SURFACE_DATA_FACTOR; + + /* Combine if cost estimate shows benefit */ + if (combined_cost <= update_cost + dirty_cost) + return 1; + + /* Combine if increase in cost is negligible */ + if (combined_cost - dirty_cost <= dirty_cost / GUAC_SURFACE_NEGLIGIBLE_INCREASE) + return 1; + + if (combined_cost - update_cost <= update_cost / GUAC_SURFACE_NEGLIGIBLE_INCREASE) + return 1; + + /* Combine if we anticipate further updates, as this update follows a common fill pattern */ + if (rect->x == surface->dirty_rect.x && rect->y == surface->dirty_rect.y + surface->dirty_rect.height) { + if (combined_cost <= (dirty_cost + update_cost) * GUAC_SURFACE_FILL_PATTERN_FACTOR) + return 1; + } + + } + /* Otherwise, do not combine */ return 0; From 1f24c47e29b6fe93d831b51744d30311316a68a7 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 6 Jan 2020 11:38:22 -0800 Subject: [PATCH 083/109] GUACAMOLE-249: Remove empty struct definitions added by Include What You Use. --- src/protocols/rdp/channels/common-svc.h | 2 -- src/protocols/rdp/channels/rdpdr/rdpdr.h | 2 -- src/protocols/rdp/keymap.h | 2 -- 3 files changed, 6 deletions(-) diff --git a/src/protocols/rdp/channels/common-svc.h b/src/protocols/rdp/channels/common-svc.h index aaa7aab4..0a420bc7 100644 --- a/src/protocols/rdp/channels/common-svc.h +++ b/src/protocols/rdp/channels/common-svc.h @@ -28,8 +28,6 @@ #include #include -struct guac_rdp_common_svc; - /** * The maximum number of bytes to allow within each channel name, including * null terminator. diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr.h b/src/protocols/rdp/channels/rdpdr/rdpdr.h index b074348a..105b50aa 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr.h @@ -28,8 +28,6 @@ #include -struct guac_rdpdr_device; - /** * The maximum number of bytes to allow for a device read. */ diff --git a/src/protocols/rdp/keymap.h b/src/protocols/rdp/keymap.h index 6ec627f5..bac1a7fa 100644 --- a/src/protocols/rdp/keymap.h +++ b/src/protocols/rdp/keymap.h @@ -22,8 +22,6 @@ #include -struct guac_rdp_keymap; - /** * Represents a keysym-to-scancode mapping for RDP, with extra information * about the state of prerequisite keysyms. From 80988cd6f49fe6e7302fbb9fecf6dae4014ca355 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 6 Jan 2020 13:09:51 -0800 Subject: [PATCH 084/109] GUACAMOLE-249: Provide SetNull and SetDefault implementations for rdpPointer. --- src/protocols/rdp/pointer.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/protocols/rdp/pointer.c b/src/protocols/rdp/pointer.c index 9f66c6a4..5a72c787 100644 --- a/src/protocols/rdp/pointer.c +++ b/src/protocols/rdp/pointer.c @@ -102,12 +102,25 @@ void guac_rdp_pointer_free(rdpContext* context, rdpPointer* pointer) { } BOOL guac_rdp_pointer_set_null(rdpContext* context) { - /* STUB */ + + guac_client* client = ((rdp_freerdp_context*) context)->client; + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + + /* Set cursor to empty/blank graphic */ + guac_common_cursor_set_blank(rdp_client->display->cursor); + return TRUE; + } BOOL guac_rdp_pointer_set_default(rdpContext* context) { - /* STUB */ + + guac_client* client = ((rdp_freerdp_context*) context)->client; + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + + /* Set cursor to embedded pointer */ + guac_common_cursor_set_pointer(rdp_client->display->cursor); + return TRUE; } From dc8c60f30fd234b5f9676ea628cd45cce1f9f75c Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 6 Jan 2020 13:22:24 -0800 Subject: [PATCH 085/109] GUACAMOLE-249: freerdp_channels_data() is already the default value of ReceiveChannelData. --- src/protocols/rdp/rdp.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 45914b27..c6435e10 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -363,7 +363,6 @@ static int guac_rdp_handle_connection(guac_client* client) { rdp_inst->PreConnect = rdp_freerdp_pre_connect; rdp_inst->Authenticate = rdp_freerdp_authenticate; rdp_inst->VerifyCertificate = rdp_freerdp_verify_certificate; - rdp_inst->ReceiveChannelData = freerdp_channels_data; /* Allocate FreeRDP context */ rdp_inst->ContextSize = sizeof(rdp_freerdp_context); From 67c5bdfdfec591b44495533bbcb4e2dede96650c Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 6 Jan 2020 13:35:08 -0800 Subject: [PATCH 086/109] GUACAMOLE-249: Do not attempt to free SVC-specific data if it hasn't actually been allocated. --- src/protocols/rdp/channels/pipe-svc.c | 2 ++ src/protocols/rdp/channels/rdpdr/rdpdr.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/protocols/rdp/channels/pipe-svc.c b/src/protocols/rdp/channels/pipe-svc.c index e918fe7c..2db42d68 100644 --- a/src/protocols/rdp/channels/pipe-svc.c +++ b/src/protocols/rdp/channels/pipe-svc.c @@ -209,6 +209,8 @@ void guac_rdp_pipe_svc_process_receive(guac_rdp_common_svc* svc, void guac_rdp_pipe_svc_process_terminate(guac_rdp_common_svc* svc) { guac_rdp_pipe_svc* pipe_svc = (guac_rdp_pipe_svc*) svc->data; + if (pipe_svc == NULL) + return; /* Remove and free SVC */ guac_rdp_pipe_svc_remove(svc->client, svc->name); diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr.c b/src/protocols/rdp/channels/rdpdr/rdpdr.c index f67a55be..e04bc9d7 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr.c @@ -150,6 +150,8 @@ void guac_rdpdr_process_connect(guac_rdp_common_svc* svc) { void guac_rdpdr_process_terminate(guac_rdp_common_svc* svc) { guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data; + if (rdpdr == NULL) + return; int i; From 666c4fb299e068f3fb31dc7c36ce600db2dd5cfd Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 6 Jan 2020 13:39:59 -0800 Subject: [PATCH 087/109] GUACAMOLE-249: Do not include "extended mode" NLA in security negotiation as negotiation fails (see FreeRDP defaults). --- src/protocols/rdp/settings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/rdp/settings.c b/src/protocols/rdp/settings.c index 97e9dafe..224a281f 100644 --- a/src/protocols/rdp/settings.c +++ b/src/protocols/rdp/settings.c @@ -1256,7 +1256,7 @@ void guac_rdp_push_settings(guac_client* client, rdp_settings->RdpSecurity = TRUE; rdp_settings->TlsSecurity = TRUE; rdp_settings->NlaSecurity = TRUE; - rdp_settings->ExtSecurity = TRUE; + rdp_settings->ExtSecurity = FALSE; break; } From 55959b54564cd7ce8800225ed8d3741345eb90a2 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 6 Jan 2020 13:47:19 -0800 Subject: [PATCH 088/109] GUACAMOLE-249: Until parameter prompting is available, do not auto-negotiate for NLA if username and password have not been provided. --- src/protocols/rdp/settings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/rdp/settings.c b/src/protocols/rdp/settings.c index 224a281f..a2cc7dfa 100644 --- a/src/protocols/rdp/settings.c +++ b/src/protocols/rdp/settings.c @@ -1255,7 +1255,7 @@ void guac_rdp_push_settings(guac_client* client, case GUAC_SECURITY_ANY: rdp_settings->RdpSecurity = TRUE; rdp_settings->TlsSecurity = TRUE; - rdp_settings->NlaSecurity = TRUE; + rdp_settings->NlaSecurity = guac_settings->username && guac_settings->password; rdp_settings->ExtSecurity = FALSE; break; From 2139d40e97d30031044c73f5285648ffc5df4c6f Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 9 Jan 2020 13:00:56 -0800 Subject: [PATCH 089/109] GUACAMOLE-249: Remove accidental double spaces from RDP comments. --- src/protocols/rdp/channels/audio-input.h | 2 +- src/protocols/rdp/channels/rdpdr/rdpdr-fs.h | 2 +- src/protocols/rdp/channels/rdpdr/rdpdr.h | 4 ++-- src/protocols/rdp/fs.h | 2 +- src/protocols/rdp/gdi.h | 2 +- src/protocols/rdp/keyboard.h | 4 ++-- src/protocols/rdp/settings.c | 10 +++++----- src/protocols/rdp/settings.h | 8 ++++---- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/protocols/rdp/channels/audio-input.h b/src/protocols/rdp/channels/audio-input.h index 366500ac..1ff76d58 100644 --- a/src/protocols/rdp/channels/audio-input.h +++ b/src/protocols/rdp/channels/audio-input.h @@ -293,7 +293,7 @@ guac_user_end_handler guac_rdp_audio_end_handler; * Adds Guacamole's "guacai" plugin to the list of dynamic virtual channel * plugins to be loaded by FreeRDP's "drdynvc" plugin. The plugin will only * be loaded once the "drdynvc" plugin is loaded. The "guacai" plugin - * ultimately adds support for the "AUDIO_INPUT" dynamic virtual channel. + * ultimately adds support for the "AUDIO_INPUT" dynamic virtual channel. * * @param context * The rdpContext associated with the active RDP session. diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h index 129fb267..ae90045f 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs.h @@ -22,7 +22,7 @@ /** * Functions and macros specific to filesystem handling and initialization - * independent of RDP. The functions here may deal with the RDPDR device + * independent of RDP. The functions here may deal with the RDPDR device * directly, but their semantics must not deal with RDP protocol messaging. * Functions here represent a virtual Windows-style filesystem on top of UNIX * system calls and structures, using the guac_rdpdr_device structure as a home diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr.h b/src/protocols/rdp/channels/rdpdr/rdpdr.h index 105b50aa..a5f5798d 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr.h @@ -135,7 +135,7 @@ struct guac_rdpdr_device { uint32_t device_type; /** - * The DOS name of the device. Max 8 bytes, including terminator. + * The DOS name of the device. Max 8 bytes, including terminator. */ const char *dos_name; @@ -216,7 +216,7 @@ wStream* guac_rdpdr_new_io_completion(guac_rdpdr_device* device, /** * Initializes device redirection support (file transfer, printing, etc.) for - * RDP and handling of the RDPDR channel. If failures occur, messages noting + * RDP and handling of the RDPDR channel. If failures occur, messages noting * the specifics of those failures will be logged, and the RDP side of * device redirection support will not be functional. * diff --git a/src/protocols/rdp/fs.h b/src/protocols/rdp/fs.h index 56c134f0..04f76b8e 100644 --- a/src/protocols/rdp/fs.h +++ b/src/protocols/rdp/fs.h @@ -22,7 +22,7 @@ /** * Functions and macros specific to filesystem handling and initialization - * independent of RDP. The functions here may deal with the filesystem device + * independent of RDP. The functions here may deal with the filesystem device * directly, but their semantics must not deal with RDP protocol messaging. * Functions here represent a virtual Windows-style filesystem on top of UNIX * system calls and structures, using the guac_rdp_fs structure as a home diff --git a/src/protocols/rdp/gdi.h b/src/protocols/rdp/gdi.h index fa09c87f..9ad5713c 100644 --- a/src/protocols/rdp/gdi.h +++ b/src/protocols/rdp/gdi.h @@ -65,7 +65,7 @@ BOOL guac_rdp_gdi_dstblt(rdpContext* context, const DSTBLT_ORDER* dstblt); /** * Handler for the ScrBlt Primary Drawing Order. A ScrBlt Primary Drawing Order * paints a rectangle of image data using a raster operation which considers - * the source and destination. See: + * the source and destination. See: * * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpegdi/a4e322b0-cd64-4dfc-8e1a-f24dc0edc99d * diff --git a/src/protocols/rdp/keyboard.h b/src/protocols/rdp/keyboard.h index 19f46d2b..6296a71d 100644 --- a/src/protocols/rdp/keyboard.h +++ b/src/protocols/rdp/keyboard.h @@ -94,7 +94,7 @@ typedef struct guac_rdp_keyboard { /** * The local state of all keys, as well as the necessary information to - * translate received keysyms into scancodes or sequences of scancodes for + * translate received keysyms into scancodes or sequences of scancodes for * RDP. The state of each key is updated based on received Guacamole key * events, while the information describing the behavior and scancode * mapping of each key is populated based on an associated keymap. @@ -180,7 +180,7 @@ int guac_rdp_keyboard_send_event(guac_rdp_keyboard* keyboard, /** * For every keysym in the given NULL-terminated array of keysyms, send the RDP * key events required to update the remote state of those keys as specified, - * depending on the current local state of those keysyms. For each key in the + * depending on the current local state of those keysyms. For each key in the * "from" state, that key will be updated to the "to" state. The locally-stored * state of each key is remains untouched. * diff --git a/src/protocols/rdp/settings.c b/src/protocols/rdp/settings.c index a2cc7dfa..bac74ff1 100644 --- a/src/protocols/rdp/settings.c +++ b/src/protocols/rdp/settings.c @@ -309,7 +309,7 @@ enum RDP_ARGS_IDX { /** * "true" if desktop composition (Aero) should be enabled during the - * session, "false" or blank otherwise. As desktop composition provides + * session, "false" or blank otherwise. As desktop composition provides * alpha blending and other special effects, this increases the amount of * bandwidth used. */ @@ -354,7 +354,7 @@ enum RDP_ARGS_IDX { /** * The timezone to pass through to the RDP connection, in IANA format, which - * will be translated into Windows formats. See the following page for + * will be translated into Windows formats. See the following page for * information and list of valid values: * https://en.wikipedia.org/wiki/List_of_tz_database_time_zones */ @@ -374,7 +374,7 @@ enum RDP_ARGS_IDX { IDX_SFTP_HOSTNAME, /** - * The public SSH host key of the SFTP server. Optional. + * The public SSH host key of the SFTP server. Optional. */ IDX_SFTP_HOST_KEY, @@ -423,7 +423,7 @@ enum RDP_ARGS_IDX { /** * The interval at which SSH keepalive messages are sent to the server for - * SFTP connections. The default is 0 (disabling keepalives), and a value + * SFTP connections. The default is 0 (disabling keepalives), and a value * of 1 is automatically increased to 2 by libssh2 to avoid busy loop corner * cases. */ @@ -461,7 +461,7 @@ enum RDP_ARGS_IDX { /** * Whether keys pressed and released should be included in the session * recording. Key events are NOT included by default within the recording, - * as doing so has privacy and security implications. Including key events + * as doing so has privacy and security implications. Including key events * may be necessary in certain auditing contexts, but should only be done * with caution. Key events can easily contain sensitive information, such * as passwords, credit card numbers, etc. diff --git a/src/protocols/rdp/settings.h b/src/protocols/rdp/settings.h index 0935f843..2e0dd3bd 100644 --- a/src/protocols/rdp/settings.h +++ b/src/protocols/rdp/settings.h @@ -325,19 +325,19 @@ typedef struct guac_rdp_settings { int menu_animations_enabled; /** - * Whether bitmap caching should be disabled. By default it is + * Whether bitmap caching should be disabled. By default it is * enabled - this allows users to explicitly disable it. */ int disable_bitmap_caching; /** - * Whether offscreen caching should be disabled. By default it is + * Whether offscreen caching should be disabled. By default it is * enabled - this allows users to explicitly disable it. */ int disable_offscreen_caching; /** - * Whether glyph caching should be disabled. By default it is enabled + * Whether glyph caching should be disabled. By default it is enabled * - this allows users to explicitly disable it. */ int disable_glyph_caching; @@ -421,7 +421,7 @@ typedef struct guac_rdp_settings { /** * The interval at which SSH keepalive messages are sent to the server for - * SFTP connections. The default is 0 (disabling keepalives), and a value + * SFTP connections. The default is 0 (disabling keepalives), and a value * of 1 is automatically increased to 2 by libssh2 to avoid busy loop corner * cases. */ From feb376ea1e206f26327d3e2516f248fb8e81812a Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 9 Jan 2020 13:10:05 -0800 Subject: [PATCH 090/109] GUACAMOLE-249: Fix misspelled "instruction" and "have" in comments. --- src/protocols/rdp/channels/pipe-svc.h | 2 +- src/protocols/rdp/upload.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/protocols/rdp/channels/pipe-svc.h b/src/protocols/rdp/channels/pipe-svc.h index 4ba64be1..6878f3a0 100644 --- a/src/protocols/rdp/channels/pipe-svc.h +++ b/src/protocols/rdp/channels/pipe-svc.h @@ -161,7 +161,7 @@ guac_user_blob_handler guac_rdp_pipe_svc_blob_handler; * Handler for "pipe" instructions which automatically prepares received pipe * streams to automatically write received blobs to the SVC having the same * name as the pipe stream. Received pipe streams are associated with the - * relevant guac_rdp_pipe_svc instance and the SVC-specific "blob" instructino + * relevant guac_rdp_pipe_svc instance and the SVC-specific "blob" instruction * handler (guac_rdp_pipe_svc_blob_handler). */ guac_user_pipe_handler guac_rdp_pipe_svc_pipe_handler; diff --git a/src/protocols/rdp/upload.c b/src/protocols/rdp/upload.c index 07cb8cad..14344b85 100644 --- a/src/protocols/rdp/upload.c +++ b/src/protocols/rdp/upload.c @@ -40,7 +40,7 @@ * * @param path * A pointer to a buffer which should receive the sanitized path. The - * buffer must hav at least GUAC_RDP_FS_MAX_PATH bytes available. + * buffer must have at least GUAC_RDP_FS_MAX_PATH bytes available. */ static void __generate_upload_path(const char* filename, char* path) { From c4f6c5161cc3c7711fd54fa8995792c62021c0c3 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 9 Jan 2020 13:11:45 -0800 Subject: [PATCH 091/109] GUACAMOLE-249: Remove accidentally-inserted "0" from end of comment. --- src/protocols/rdp/upload.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/rdp/upload.c b/src/protocols/rdp/upload.c index 14344b85..5317edbc 100644 --- a/src/protocols/rdp/upload.c +++ b/src/protocols/rdp/upload.c @@ -121,7 +121,7 @@ int guac_rdp_upload_blob_handler(guac_user* user, guac_stream* stream, int bytes_written; guac_rdp_upload_status* upload_status = (guac_rdp_upload_status*) stream->data; - /* Get filesystem, return error if no filesystem 0*/ + /* Get filesystem, return error if no filesystem */ guac_client* client = user->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_fs* fs = rdp_client->filesystem; From b3a713bf7a5ce5fdc102f115b282152681e36412 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 9 Jan 2020 13:36:37 -0800 Subject: [PATCH 092/109] GUACAMOLE-249: Clean up basename logic of file downloads. Add unit test. --- src/protocols/rdp/download.c | 24 ++--------- src/protocols/rdp/fs.c | 15 +++++++ src/protocols/rdp/fs.h | 14 +++++++ src/protocols/rdp/tests/Makefile.am | 1 + src/protocols/rdp/tests/fs/basename.c | 59 +++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 21 deletions(-) create mode 100644 src/protocols/rdp/tests/fs/basename.c diff --git a/src/protocols/rdp/download.c b/src/protocols/rdp/download.c index ceb211ed..34a8c8a1 100644 --- a/src/protocols/rdp/download.c +++ b/src/protocols/rdp/download.c @@ -193,38 +193,20 @@ void* guac_rdp_download_to_user(guac_user* user, void* data) { /* If file opened successfully, start stream */ if (file_id >= 0) { - guac_rdp_download_status* download_status; - const char* basename; - - int i; - char c; - /* Associate stream with transfer status */ guac_stream* stream = guac_user_alloc_stream(user); - stream->data = download_status = malloc(sizeof(guac_rdp_download_status)); + guac_rdp_download_status* download_status = malloc(sizeof(guac_rdp_download_status)); + stream->data = download_status; stream->ack_handler = guac_rdp_download_ack_handler; download_status->file_id = file_id; download_status->offset = 0; - /* Get basename from absolute path */ - i=0; - basename = path; - do { - - c = path[i]; - if (c == '/' || c == '\\') - basename = &(path[i+1]); - - i++; - - } while (c != '\0'); - guac_user_log(user, GUAC_LOG_DEBUG, "%s: Initiating download " "of \"%s\"", __func__, path); /* Begin stream */ guac_protocol_send_file(user->socket, stream, - "application/octet-stream", basename); + "application/octet-stream", guac_rdp_fs_basename(path)); guac_socket_flush(user->socket); /* Download started successfully */ diff --git a/src/protocols/rdp/fs.c b/src/protocols/rdp/fs.c index 74664b4b..66bb8e92 100644 --- a/src/protocols/rdp/fs.c +++ b/src/protocols/rdp/fs.c @@ -605,6 +605,21 @@ const char* guac_rdp_fs_read_dir(guac_rdp_fs* fs, int file_id) { } +const char* guac_rdp_fs_basename(const char* path) { + + for (const char* c = path; *c != '\0'; c++) { + + /* Reset beginning of path if a path separator is found */ + if (*c == '/' || *c == '\\') + path = c + 1; + + } + + /* path now points to the first character after the last path separator */ + return path; + +} + int guac_rdp_fs_normalize_path(const char* path, char* abs_path) { int path_depth = 0; diff --git a/src/protocols/rdp/fs.h b/src/protocols/rdp/fs.h index 04f76b8e..b95af555 100644 --- a/src/protocols/rdp/fs.h +++ b/src/protocols/rdp/fs.h @@ -524,6 +524,20 @@ int guac_rdp_fs_truncate(guac_rdp_fs* fs, int file_id, int length); */ void guac_rdp_fs_close(guac_rdp_fs* fs, int file_id); +/** + * Given an arbitrary path, returns a pointer to the first character following + * the last path separator in the path (the basename of the path). For example, + * given "/foo/bar/baz" or "\foo\bar\baz", this function would return a pointer + * to "baz". + * + * @param path + * The path to determine the basename of. + * + * @return + * A pointer to the first character of the basename within the path. + */ +const char* guac_rdp_fs_basename(const char* path); + /** * Given an arbitrary path, which may contain ".." and ".", creates an * absolute path which does NOT contain ".." or ".". The given path MUST diff --git a/src/protocols/rdp/tests/Makefile.am b/src/protocols/rdp/tests/Makefile.am index 3f57bbf3..33136696 100644 --- a/src/protocols/rdp/tests/Makefile.am +++ b/src/protocols/rdp/tests/Makefile.am @@ -34,6 +34,7 @@ check_PROGRAMS = test_rdp TESTS = $(check_PROGRAMS) test_rdp_SOURCES = \ + fs/basename.c \ fs/normalize_path.c test_rdp_CFLAGS = \ diff --git a/src/protocols/rdp/tests/fs/basename.c b/src/protocols/rdp/tests/fs/basename.c new file mode 100644 index 00000000..9ac60977 --- /dev/null +++ b/src/protocols/rdp/tests/fs/basename.c @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#include "fs.h" + +#include +#include + +/** + * Test which verifies basenames are correctly extracted from Windows-style + * paths. + */ +void test_fs__basename_windows() { + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("\\foo\\bar\\baz"), "baz") + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("\\foo\\bar\\..\\baz\\"), "") + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("bar\\..\\..\\baz\\a\\..\\b"), "b") + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename(".\\bar\\potato"), "potato") + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("..\\..\\..\\..\\..\\..\\baz"), "baz") +} + +/** + * Test which verifies basenames are correctly extracted from UNIX-style paths. + */ +void test_fs__basename_unix() { + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("/foo/bar/baz"), "baz") + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("/foo/bar/../baz/"), "") + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("bar/../../baz/a/../b"), "b") + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("./bar/potato"), "potato") + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("../../../../../../baz"), "baz") +} + +/** + * Test which verifies basenames are correctly extracted from paths consisting + * of mixed Windows and UNIX path separators. + */ +void test_fs__basename_mixed() { + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("\\foo/bar\\baz"), "baz") + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("/foo\\bar/..\\baz/"), "") + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("bar\\../../baz\\a\\..\\b"), "b") + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename(".\\bar/potato"), "potato") + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("../..\\..\\..\\../..\\baz"), "baz") +} + From 62ee36142dde087aa9fe309e606e0e08b941a212 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 9 Jan 2020 14:12:08 -0800 Subject: [PATCH 093/109] GUACAMOLE-249: Refactor guac_freerdp_channels_load_plugin() to log a warning if plugin limits are reached. --- src/protocols/rdp/channels/cliprdr.c | 2 +- src/protocols/rdp/channels/common-svc.c | 4 +-- src/protocols/rdp/channels/rail.c | 2 +- src/protocols/rdp/plugins/channels.c | 33 +++++++++++++------ src/protocols/rdp/plugins/channels.h | 42 ++++++++++++++----------- src/protocols/rdp/rdp.c | 5 ++- 6 files changed, 51 insertions(+), 37 deletions(-) diff --git a/src/protocols/rdp/channels/cliprdr.c b/src/protocols/rdp/channels/cliprdr.c index e62bbb14..3ca41ce2 100644 --- a/src/protocols/rdp/channels/cliprdr.c +++ b/src/protocols/rdp/channels/cliprdr.c @@ -496,7 +496,7 @@ void guac_rdp_clipboard_load_plugin(guac_rdp_clipboard* clipboard, rdpContext* context) { /* Attempt to load FreeRDP support for the CLIPRDR channel */ - if (guac_freerdp_channels_load_plugin(context->channels, context->settings, "cliprdr", NULL)) { + if (guac_freerdp_channels_load_plugin(context, "cliprdr", NULL)) { guac_client_log(clipboard->client, GUAC_LOG_WARNING, "Support for the CLIPRDR channel (clipboard redirection) " "could not be loaded. This support normally takes the form of " diff --git a/src/protocols/rdp/channels/common-svc.c b/src/protocols/rdp/channels/common-svc.c index 20254ad7..b73dd6e1 100644 --- a/src/protocols/rdp/channels/common-svc.c +++ b/src/protocols/rdp/channels/common-svc.c @@ -59,10 +59,8 @@ int guac_rdp_common_svc_load_plugin(rdpContext* context, "characters and will be truncated to \"%s\".", name, GUAC_RDP_SVC_MAX_LENGTH - 1, svc->name); - int result = guac_freerdp_channels_load_plugin(context->channels, - context->settings, "guac-common-svc", svc); - /* Attempt to load the common SVC plugin for new static channel */ + int result = guac_freerdp_channels_load_plugin(context, "guac-common-svc", svc); if (result) { guac_client_log(client, GUAC_LOG_WARNING, "Cannot create static " "channel \"%s\": failed to load \"guac-common-svc\" plugin " diff --git a/src/protocols/rdp/channels/rail.c b/src/protocols/rdp/channels/rail.c index eb645a8f..07b0babb 100644 --- a/src/protocols/rdp/channels/rail.c +++ b/src/protocols/rdp/channels/rail.c @@ -177,7 +177,7 @@ void guac_rdp_rail_load_plugin(rdpContext* context) { guac_client* client = ((rdp_freerdp_context*) context)->client; /* Attempt to load FreeRDP support for the RAIL channel */ - if (guac_freerdp_channels_load_plugin(context->channels, context->settings, "rail", context->settings)) { + if (guac_freerdp_channels_load_plugin(context, "rail", context->settings)) { guac_client_log(client, GUAC_LOG_WARNING, "Support for the RAIL channel (RemoteApp) could not be " "loaded. This support normally takes the form of a plugin " diff --git a/src/protocols/rdp/plugins/channels.c b/src/protocols/rdp/plugins/channels.c index a183b667..0048b891 100644 --- a/src/protocols/rdp/plugins/channels.c +++ b/src/protocols/rdp/plugins/channels.c @@ -18,6 +18,7 @@ */ #include "plugins/channels.h" +#include "rdp.h" #include #include @@ -36,12 +37,17 @@ PVIRTUALCHANNELENTRYEX guac_rdp_wrapped_entry_ex[GUAC_RDP_MAX_CHANNELS] = { NULL PVIRTUALCHANNELENTRY guac_rdp_wrapped_entry[GUAC_RDP_MAX_CHANNELS] = { NULL }; -PVIRTUALCHANNELENTRYEX guac_rdp_plugin_wrap_entry_ex(PVIRTUALCHANNELENTRYEX entry_ex) { +PVIRTUALCHANNELENTRYEX guac_rdp_plugin_wrap_entry_ex(guac_client* client, + PVIRTUALCHANNELENTRYEX entry_ex) { /* Do not wrap if there is insufficient space to store the wrapped * function */ - if (guac_rdp_wrapped_entry_ex_count == GUAC_RDP_MAX_CHANNELS) + if (guac_rdp_wrapped_entry_ex_count == GUAC_RDP_MAX_CHANNELS) { + guac_client_log(client, GUAC_LOG_WARNING, "Maximum number of static " + "channels has been reached. Further FreeRDP plugins and " + "channel support may fail to load."); return entry_ex; + } /* Generate wrapped version of provided entry point */ PVIRTUALCHANNELENTRYEX wrapper = guac_rdp_entry_ex_wrappers[guac_rdp_wrapped_entry_ex_count]; @@ -52,12 +58,17 @@ PVIRTUALCHANNELENTRYEX guac_rdp_plugin_wrap_entry_ex(PVIRTUALCHANNELENTRYEX entr } -PVIRTUALCHANNELENTRY guac_rdp_plugin_wrap_entry(PVIRTUALCHANNELENTRY entry) { +PVIRTUALCHANNELENTRY guac_rdp_plugin_wrap_entry(guac_client* client, + PVIRTUALCHANNELENTRY entry) { /* Do not wrap if there is insufficient space to store the wrapped * function */ - if (guac_rdp_wrapped_entry_count == GUAC_RDP_MAX_CHANNELS) + if (guac_rdp_wrapped_entry_count == GUAC_RDP_MAX_CHANNELS) { + guac_client_log(client, GUAC_LOG_WARNING, "Maximum number of static " + "channels has been reached. Further FreeRDP plugins and " + "channel support may fail to load."); return entry; + } /* Generate wrapped version of provided entry point */ PVIRTUALCHANNELENTRY wrapper = guac_rdp_entry_wrappers[guac_rdp_wrapped_entry_count]; @@ -68,16 +79,18 @@ PVIRTUALCHANNELENTRY guac_rdp_plugin_wrap_entry(PVIRTUALCHANNELENTRY entry) { } -int guac_freerdp_channels_load_plugin(rdpChannels* channels, - rdpSettings* settings, const char* name, void* data) { +int guac_freerdp_channels_load_plugin(rdpContext* context, + const char* name, void* data) { + + guac_client* client = ((rdp_freerdp_context*) context)->client; /* Load plugin using "ex" version of the channel plugin entry point, if it exists */ PVIRTUALCHANNELENTRYEX entry_ex = (PVIRTUALCHANNELENTRYEX) (void*) freerdp_load_channel_addin_entry(name, NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC | FREERDP_ADDIN_CHANNEL_ENTRYEX); if (entry_ex != NULL) { - entry_ex = guac_rdp_plugin_wrap_entry_ex(entry_ex); - return freerdp_channels_client_load_ex(channels, settings, entry_ex, data); + entry_ex = guac_rdp_plugin_wrap_entry_ex(client, entry_ex); + return freerdp_channels_client_load_ex(context->channels, context->settings, entry_ex, data); } /* Lacking the "ex" entry point, attempt to load using the non-ex version */ @@ -85,8 +98,8 @@ int guac_freerdp_channels_load_plugin(rdpChannels* channels, NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC); if (entry != NULL) { - entry = guac_rdp_plugin_wrap_entry(entry); - return freerdp_channels_client_load(channels, settings, entry, data); + entry = guac_rdp_plugin_wrap_entry(client, entry); + return freerdp_channels_client_load(context->channels, context->settings, entry, data); } /* The plugin does not exist / cannot be loaded */ diff --git a/src/protocols/rdp/plugins/channels.h b/src/protocols/rdp/plugins/channels.h index 59d6c829..b1207e2a 100644 --- a/src/protocols/rdp/plugins/channels.h +++ b/src/protocols/rdp/plugins/channels.h @@ -23,6 +23,7 @@ #include #include #include +#include #include /** @@ -41,25 +42,20 @@ #error "GUAC_RDP_MAX_CHANNELS must not be less than CHANNEL_MAX_COUNT" #endif -/** - * Loads the FreeRDP plugin having the given name. This function is a drop-in - * replacement for freerdp_channels_load_plugin() which additionally loads - * plugins implementing the PVIRTUALCHANNELENTRYEX version of the channel - * plugin entry point. The freerdp_channels_load_plugin() function which is - * part of FreeRDP can load only plugins which implement the - * PVIRTUALCHANNELENTRY version of the entry point. +/** Loads the FreeRDP plugin having the given name. With the exception that + * this function requires the rdpContext rather than rdpChannels and + * rdpSettings, this function is essentially a drop-in replacement for + * freerdp_channels_load_plugin() which additionally loads plugins implementing + * the PVIRTUALCHANNELENTRYEX version of the channel plugin entry point. The + * freerdp_channels_load_plugin() function which is part of FreeRDP can load + * only plugins which implement the PVIRTUALCHANNELENTRY version of the entry + * point. * * This MUST be called within the PreConnect callback of the freerdp instance * for the referenced plugin to be loaded correctly. * - * @param channels - * The rdpChannels structure with which the plugin should be registered - * once loaded. This structure should be retrieved directly from the - * relevant FreeRDP instance. - * - * @param settings - * The rdpSettings structure associated with the FreeRDP instance, already - * populated with any settings applicable to the plugin being loaded. + * @param context + * The rdpContext associated with the active RDP session. * * @param name * The name of the plugin to load. If the plugin is not statically built @@ -78,8 +74,8 @@ * Zero if the plugin was loaded successfully, non-zero if the plugin could * not be loaded. */ -int guac_freerdp_channels_load_plugin(rdpChannels* channels, - rdpSettings* settings, const char* name, void* data); +int guac_freerdp_channels_load_plugin(rdpContext* context, + const char* name, void* data); /** * Schedules loading of the FreeRDP dynamic virtual channel plugin having the @@ -150,6 +146,9 @@ extern PVIRTUALCHANNELENTRYEX guac_rdp_entry_ex_wrappers[GUAC_RDP_MAX_CHANNELS]; * load a plugin if its entry point is already loaded, this allows a single * FreeRDP plugin to be loaded multiple times. * + * @param client + * The guac_client associated with the relevant RDP session. + * * @param entry_ex * The entry point function to wrap. * @@ -158,7 +157,8 @@ extern PVIRTUALCHANNELENTRYEX guac_rdp_entry_ex_wrappers[GUAC_RDP_MAX_CHANNELS]; * point if there is insufficient space remaining within * guac_rdp_entry_ex_wrappers to wrap the entry point. */ -PVIRTUALCHANNELENTRYEX guac_rdp_plugin_wrap_entry_ex(PVIRTUALCHANNELENTRYEX entry_ex); +PVIRTUALCHANNELENTRYEX guac_rdp_plugin_wrap_entry_ex(guac_client* client, + PVIRTUALCHANNELENTRYEX entry_ex); /** * The number of wrapped channel entry points currently stored within @@ -189,6 +189,9 @@ extern PVIRTUALCHANNELENTRY guac_rdp_entry_wrappers[GUAC_RDP_MAX_CHANNELS]; * load a plugin if its entry point is already loaded, this allows a single * FreeRDP plugin to be loaded multiple times. * + * @param client + * The guac_client associated with the relevant RDP session. + * * @param entry * The entry point function to wrap. * @@ -197,7 +200,8 @@ extern PVIRTUALCHANNELENTRY guac_rdp_entry_wrappers[GUAC_RDP_MAX_CHANNELS]; * point if there is insufficient space remaining within * guac_rdp_entry_wrappers to wrap the entry point. */ -PVIRTUALCHANNELENTRY guac_rdp_plugin_wrap_entry(PVIRTUALCHANNELENTRY entry); +PVIRTUALCHANNELENTRY guac_rdp_plugin_wrap_entry(guac_client* client, + PVIRTUALCHANNELENTRY entry); #endif diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index c6435e10..07475c56 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -77,7 +77,6 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { rdpContext* context = instance->context; - rdpChannels* channels = context->channels; rdpGraphics* graphics = context->graphics; guac_client* client = ((rdp_freerdp_context*) context)->client; @@ -127,8 +126,8 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { /* Load plugin providing Dynamic Virtual Channel support, if required */ if (instance->settings->SupportDynamicChannels && - guac_freerdp_channels_load_plugin(channels, instance->settings, - "drdynvc", instance->settings)) { + guac_freerdp_channels_load_plugin(context, "drdynvc", + instance->settings)) { guac_client_log(client, GUAC_LOG_WARNING, "Failed to load drdynvc plugin. Display update and audio " "input support will be disabled."); From f805a80bc1a7e0e6daa3b299b80cd470d8332c5a Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 11 Jan 2020 20:14:14 -0800 Subject: [PATCH 094/109] GUACAMOLE-249: Switch return type of guac_rdp_cache_bitmap() back to void - it doesn't fail, and isn't dictated by the FreeRDP API. --- src/protocols/rdp/bitmap.c | 4 +--- src/protocols/rdp/bitmap.h | 5 +---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/protocols/rdp/bitmap.c b/src/protocols/rdp/bitmap.c index 61621f2e..db293162 100644 --- a/src/protocols/rdp/bitmap.c +++ b/src/protocols/rdp/bitmap.c @@ -31,7 +31,7 @@ #include #include -BOOL guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap) { +void guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; @@ -59,8 +59,6 @@ BOOL guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap) { /* Store buffer reference in bitmap */ ((guac_rdp_bitmap*) bitmap)->layer = buffer; - return TRUE; - } BOOL guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap) { diff --git a/src/protocols/rdp/bitmap.h b/src/protocols/rdp/bitmap.h index ef3e5476..297230c5 100644 --- a/src/protocols/rdp/bitmap.h +++ b/src/protocols/rdp/bitmap.h @@ -61,11 +61,8 @@ typedef struct guac_rdp_bitmap { * * @param bitmap * The bitmap to cache. - * - * @return - * TRUE if successful, FALSE otherwise. */ -BOOL guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap); +void guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap); /** * Initializes the given newly-created rdpBitmap. From a3d9a685e835b260eb8532493b1adb50bb27e17b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 11 Jan 2020 20:18:27 -0800 Subject: [PATCH 095/109] GUACAMOLE-249: Handle failure to send either response required for monitor ready. --- src/protocols/rdp/channels/cliprdr.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/protocols/rdp/channels/cliprdr.c b/src/protocols/rdp/channels/cliprdr.c index 3ca41ce2..5841cf18 100644 --- a/src/protocols/rdp/channels/cliprdr.c +++ b/src/protocols/rdp/channels/cliprdr.c @@ -138,8 +138,12 @@ static UINT guac_rdp_cliprdr_monitor_ready(CliprdrClientContext* cliprdr, guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received " "monitor ready."); - /* Respond with capabilities and supported format list */ - guac_rdp_cliprdr_send_capabilities(cliprdr); + /* Respond with capabilities ... */ + int status = guac_rdp_cliprdr_send_capabilities(cliprdr); + if (status != CHANNEL_RC_OK) + return status; + + /* ... and supported format list */ return guac_rdp_cliprdr_send_format_list(cliprdr); } From e9670df145916cb57f22006bf4bdc66b4491f5ed Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 11 Jan 2020 20:19:51 -0800 Subject: [PATCH 096/109] GUACAMOLE-249: Correct typo: "updating" should be "update". --- src/common/surface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/surface.c b/src/common/surface.c index 98d234dc..c86ca806 100644 --- a/src/common/surface.c +++ b/src/common/surface.c @@ -267,7 +267,7 @@ static int __guac_common_surface_is_opaque(guac_common_surface* surface, * The surface being updated. * * @param rect - * The bounding rectangle of the updating being made to the surface. + * The bounding rectangle of the update being made to the surface. * * @param rect_only * Non-zero if this update, by its nature, contains only metainformation From 92d97a3244df460b6762710a46888e0bae274777 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 11 Jan 2020 20:21:00 -0800 Subject: [PATCH 097/109] GUACAMOLE-249: Correct typo: "indicating" should be "indicates". --- src/protocols/rdp/channels/cliprdr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/protocols/rdp/channels/cliprdr.c b/src/protocols/rdp/channels/cliprdr.c index 5841cf18..a03ffe93 100644 --- a/src/protocols/rdp/channels/cliprdr.c +++ b/src/protocols/rdp/channels/cliprdr.c @@ -151,8 +151,8 @@ static UINT guac_rdp_cliprdr_monitor_ready(CliprdrClientContext* cliprdr, /** * Sends a Format Data Request PDU to the RDP server, requesting that available * clipboard data be sent to the client in the specified format. This PDU is - * sent when the server indicating that clipboard data is available via a - * Format List PDU. + * sent when the server indicates that clipboard data is available via a Format + * List PDU. * * @param client * The guac_client associated with the current RDP session. From 01c731e2410b839ad844b69ee2d04e4875685f32 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 11 Jan 2020 20:22:23 -0800 Subject: [PATCH 098/109] GUACAMOLE-249: Clean up documentation for arbitrary pipe SVC. No need to say "automatically" everywhere. --- src/protocols/rdp/channels/pipe-svc.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/protocols/rdp/channels/pipe-svc.h b/src/protocols/rdp/channels/pipe-svc.h index 6878f3a0..242d4e50 100644 --- a/src/protocols/rdp/channels/pipe-svc.h +++ b/src/protocols/rdp/channels/pipe-svc.h @@ -152,17 +152,17 @@ guac_rdp_pipe_svc* guac_rdp_pipe_svc_get(guac_client* client, const char* name); guac_rdp_pipe_svc* guac_rdp_pipe_svc_remove(guac_client* client, const char* name); /** - * Handler for "blob" instructions which automatically writes received data to - * the associated SVC using guac_rdp_pipe_svc_write(). + * Handler for "blob" instructions which writes received data to the associated + * SVC using guac_rdp_pipe_svc_write(). */ guac_user_blob_handler guac_rdp_pipe_svc_blob_handler; /** - * Handler for "pipe" instructions which automatically prepares received pipe - * streams to automatically write received blobs to the SVC having the same - * name as the pipe stream. Received pipe streams are associated with the - * relevant guac_rdp_pipe_svc instance and the SVC-specific "blob" instruction - * handler (guac_rdp_pipe_svc_blob_handler). + * Handler for "pipe" instructions which prepares received pipe streams to + * write received blobs to the SVC having the same name as the pipe stream. + * Received pipe streams are associated with the relevant guac_rdp_pipe_svc + * instance and the SVC-specific "blob" instruction handler + * (guac_rdp_pipe_svc_blob_handler). */ guac_user_pipe_handler guac_rdp_pipe_svc_pipe_handler; From 5e9c7cdb42191decddd78e881548f9f872d46d10 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 11 Jan 2020 20:24:12 -0800 Subject: [PATCH 099/109] GUACAMOLE-249: Correct typo: "of common RDPDR header" should be "of the common RDPDR header". --- .../rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h | 6 +++--- .../rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h | 6 +++--- src/protocols/rdp/channels/rdpdr/rdpdr.h | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h index fb49ce93..2f259e91 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h @@ -43,9 +43,9 @@ * * @param device * The guac_rdpdr_device of the relevant device, as dictated by the - * deviceId field of common RDPDR header within the received PDU. Within - * the guac_rdpdr_iorequest structure, the deviceId field is stored within - * device_id. + * deviceId field of the common RDPDR header within the received PDU. + * Within the guac_rdpdr_iorequest structure, the deviceId field is stored + * within device_id. * * @param iorequest * The contents of the common RDPDR Device I/O Request header shared by all diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h index 25f13cee..f7a8784f 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h @@ -41,9 +41,9 @@ * * @param device * The guac_rdpdr_device of the relevant device, as dictated by the - * deviceId field of common RDPDR header within the received PDU. Within - * the guac_rdpdr_iorequest structure, the deviceId field is stored within - * device_id. + * deviceId field of the common RDPDR header within the received PDU. + * Within the guac_rdpdr_iorequest structure, the deviceId field is stored + * within device_id. * * @param iorequest * The contents of the common RDPDR Device I/O Request header shared by all diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr.h b/src/protocols/rdp/channels/rdpdr/rdpdr.h index a5f5798d..b6f9da31 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr.h +++ b/src/protocols/rdp/channels/rdpdr/rdpdr.h @@ -87,9 +87,9 @@ typedef struct guac_rdpdr_iorequest { * * @param device * The guac_rdpdr_device of the relevant device, as dictated by the - * deviceId field of common RDPDR header within the received PDU. Within - * the guac_rdpdr_iorequest structure, the deviceId field is stored within - * device_id. + * deviceId field of the common RDPDR header within the received PDU. + * Within the guac_rdpdr_iorequest structure, the deviceId field is stored + * within device_id. * * @param iorequest * The contents of the common RDPDR Device I/O Request header shared by all From 4b1243fbf8a3fc1c59f186d13466b31ad59d56d6 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 12 Jan 2020 14:06:31 -0800 Subject: [PATCH 100/109] GUACAMOLE-249: Ensure CLIPRDR message handlers are accepted by compiler regardless of whether const is required. Without a typecast, errors like the following are generated by the compiler: channels/cliprdr.c: In function 'guac_rdp_cliprdr_channel_connected': channels/cliprdr.c:477:27: error: assignment from incompatible pointer type [-Werror] cliprdr->MonitorReady = guac_rdp_cliprdr_monitor_ready; ^ channels/cliprdr.c:478:31: error: assignment from incompatible pointer type [-Werror] cliprdr->ServerFormatList = guac_rdp_cliprdr_format_list; ^ channels/cliprdr.c:479:38: error: assignment from incompatible pointer type [-Werror] cliprdr->ServerFormatDataRequest = guac_rdp_cliprdr_format_data_request; ^ channels/cliprdr.c:480:39: error: assignment from incompatible pointer type [-Werror] cliprdr->ServerFormatDataResponse = guac_rdp_cliprdr_format_data_response; ^ cc1: all warnings being treated as errors This is because FreeRDP commit 65812bd added const to the pointer argument of each of these handlers, wheras older versions of FreeRDP lack const here. Our implementations of these functions declare const and thus do not match the older prototype, though they are compatible with it. --- src/protocols/rdp/channels/cliprdr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/protocols/rdp/channels/cliprdr.c b/src/protocols/rdp/channels/cliprdr.c index a03ffe93..4332d35f 100644 --- a/src/protocols/rdp/channels/cliprdr.c +++ b/src/protocols/rdp/channels/cliprdr.c @@ -474,10 +474,10 @@ static void guac_rdp_cliprdr_channel_connected(rdpContext* context, cliprdr->custom = clipboard; clipboard->cliprdr = cliprdr; - cliprdr->MonitorReady = guac_rdp_cliprdr_monitor_ready; - cliprdr->ServerFormatList = guac_rdp_cliprdr_format_list; - cliprdr->ServerFormatDataRequest = guac_rdp_cliprdr_format_data_request; - cliprdr->ServerFormatDataResponse = guac_rdp_cliprdr_format_data_response; + cliprdr->MonitorReady = (pcCliprdrMonitorReady) guac_rdp_cliprdr_monitor_ready; + cliprdr->ServerFormatList = (pcCliprdrServerFormatList) guac_rdp_cliprdr_format_list; + cliprdr->ServerFormatDataRequest = (pcCliprdrServerFormatDataRequest) guac_rdp_cliprdr_format_data_request; + cliprdr->ServerFormatDataResponse = (pcCliprdrServerFormatDataResponse) guac_rdp_cliprdr_format_data_response; guac_client_log(client, GUAC_LOG_DEBUG, "CLIPRDR (clipboard redirection) " "channel connected."); From e9846945c7cfc33b052241eab2b356a38261835c Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 12 Jan 2020 14:10:07 -0800 Subject: [PATCH 101/109] GUACAMOLE-249: Test endianness of platform without violating strict aliasing rules. Dereferencing a uint8_t array as uint32_t causes a build failure with some compilers as it breaks strict aliasing rules. --- src/protocols/rdp/color.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/protocols/rdp/color.c b/src/protocols/rdp/color.c index 9befcfb3..ee7b7ce9 100644 --- a/src/protocols/rdp/color.c +++ b/src/protocols/rdp/color.c @@ -25,14 +25,18 @@ #include #include +#include UINT32 guac_rdp_get_native_pixel_format(BOOL alpha) { - uint8_t color[] = { 0x0A, 0x0B, 0x0C, 0x0D }; + uint32_t int_value; + uint8_t raw_bytes[4] = { 0x0A, 0x0B, 0x0C, 0x0D }; + + memcpy(&int_value, raw_bytes, sizeof(raw_bytes)); /* Local platform stores bytes in decreasing order of significance * (big-endian) */ - if (*((uint32_t*) color) == 0x0A0B0C0D) + if (int_value == 0x0A0B0C0D) return alpha ? PIXEL_FORMAT_ARGB32 : PIXEL_FORMAT_XRGB32; /* Local platform stores bytes in increasing order of significance From 4282da662fb6f260684b24fecfc3604473de91d5 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 12 Jan 2020 21:55:58 -0800 Subject: [PATCH 102/109] GUACAMOLE-249: Restructure audio input such that audio buffer can be separately linked. On some platforms, the libguacai-client.so plugin for FreeRDP reports an unlinked symbol: undefined symbol: guac_freerdp_dynamic_channel_collection_add (/usr/local/lib/freerdp2/libguacai-client.so) This symbol is actually unused within the plugin, but may be referenced due to being defined within a function in a common piece of source shared between the plugin and the RDP support. Separating the actual common components such that they can be included by both the RDP support and the libguacai-client.so plugin removes the potential for unused pieces being flagged as missing. --- src/protocols/rdp/Makefile.am | 14 +- .../audio-buffer.c} | 165 +-------------- .../audio-buffer.h} | 31 +-- .../rdp/channels/audio-input/audio-input.c | 195 ++++++++++++++++++ .../rdp/channels/audio-input/audio-input.h | 53 +++++ src/protocols/rdp/client.c | 2 +- .../rdp/plugins/guacai/guacai-messages.c | 2 +- .../rdp/plugins/guacai/guacai-messages.h | 2 +- src/protocols/rdp/plugins/guacai/guacai.c | 2 +- src/protocols/rdp/rdp.c | 3 +- src/protocols/rdp/rdp.h | 2 +- src/protocols/rdp/user.c | 2 +- 12 files changed, 267 insertions(+), 206 deletions(-) rename src/protocols/rdp/channels/{audio-input.c => audio-input/audio-buffer.c} (69%) rename src/protocols/rdp/channels/{audio-input.h => audio-input/audio-buffer.h} (90%) create mode 100644 src/protocols/rdp/channels/audio-input/audio-input.c create mode 100644 src/protocols/rdp/channels/audio-input/audio-input.h diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index 8766b76a..d20d79cb 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -39,7 +39,8 @@ nodist_libguac_client_rdp_la_SOURCES = \ libguac_client_rdp_la_SOURCES = \ bitmap.c \ - channels/audio-input.c \ + channels/audio-input/audio-buffer.c \ + channels/audio-input/audio-input.c \ channels/cliprdr.c \ channels/common-svc.c \ channels/disp.c \ @@ -81,7 +82,8 @@ libguac_client_rdp_la_SOURCES = \ noinst_HEADERS = \ bitmap.h \ - channels/audio-input.h \ + channels/audio-input/audio-buffer.h \ + channels/audio-input/audio-input.h \ channels/cliprdr.h \ channels/common-svc.h \ channels/disp.h \ @@ -173,10 +175,10 @@ libguac_common_svc_client_la_LIBADD = \ # Audio Input # -libguacai_client_la_SOURCES = \ - channels/audio-input.c \ - plugins/guacai/guacai-messages.c \ - plugins/guacai/guacai.c \ +libguacai_client_la_SOURCES = \ + channels/audio-input/audio-buffer.c \ + plugins/guacai/guacai-messages.c \ + plugins/guacai/guacai.c \ plugins/ptr-string.c libguacai_client_la_CFLAGS = \ diff --git a/src/protocols/rdp/channels/audio-input.c b/src/protocols/rdp/channels/audio-input/audio-buffer.c similarity index 69% rename from src/protocols/rdp/channels/audio-input.c rename to src/protocols/rdp/channels/audio-input/audio-buffer.c index 29b48169..30513419 100644 --- a/src/protocols/rdp/channels/audio-input.c +++ b/src/protocols/rdp/channels/audio-input/audio-buffer.c @@ -17,12 +17,9 @@ * under the License. */ -#include "channels/audio-input.h" -#include "plugins/channels.h" -#include "plugins/ptr-string.h" +#include "channels/audio-input/audio-buffer.h" #include "rdp.h" -#include #include #include #include @@ -30,169 +27,9 @@ #include #include -#include #include #include #include -#include - -/** - * Parses the given raw audio mimetype, producing the corresponding rate, - * number of channels, and bytes per sample. - * - * @param mimetype - * The raw auduio mimetype to parse. - * - * @param rate - * A pointer to an int where the sample rate for the PCM format described - * by the given mimetype should be stored. - * - * @param channels - * A pointer to an int where the number of channels used by the PCM format - * described by the given mimetype should be stored. - * - * @param bps - * A pointer to an int where the number of bytes used the PCM format for - * each sample (independent of number of channels) described by the given - * mimetype should be stored. - * - * @return - * Zero if the given mimetype is a raw audio mimetype and has been parsed - * successfully, non-zero otherwise. - */ -static int guac_rdp_audio_parse_mimetype(const char* mimetype, - int* rate, int* channels, int* bps) { - - int parsed_rate = -1; - int parsed_channels = 1; - int parsed_bps; - - /* PCM audio with one byte per sample */ - if (strncmp(mimetype, "audio/L8;", 9) == 0) { - mimetype += 8; /* Advance to semicolon ONLY */ - parsed_bps = 1; - } - - /* PCM audio with two bytes per sample */ - else if (strncmp(mimetype, "audio/L16;", 10) == 0) { - mimetype += 9; /* Advance to semicolon ONLY */ - parsed_bps = 2; - } - - /* Unsupported mimetype */ - else - return 1; - - /* Parse each parameter name/value pair within the mimetype */ - do { - - /* Advance to first character of parameter (current is either a - * semicolon or a comma) */ - mimetype++; - - /* Parse number of channels */ - if (strncmp(mimetype, "channels=", 9) == 0) { - - mimetype += 9; - parsed_channels = strtol(mimetype, (char**) &mimetype, 10); - - /* Fail if value invalid / out of range */ - if (errno == EINVAL || errno == ERANGE) - return 1; - - } - - /* Parse number of rate */ - else if (strncmp(mimetype, "rate=", 5) == 0) { - - mimetype += 5; - parsed_rate = strtol(mimetype, (char**) &mimetype, 10); - - /* Fail if value invalid / out of range */ - if (errno == EINVAL || errno == ERANGE) - return 1; - - } - - /* Advance to next parameter */ - mimetype = strchr(mimetype, ','); - - } while (mimetype != NULL); - - /* Mimetype is invalid if rate was not specified */ - if (parsed_rate == -1) - return 1; - - /* Parse success */ - *rate = parsed_rate; - *channels = parsed_channels; - *bps = parsed_bps; - - return 0; - -} - -int guac_rdp_audio_handler(guac_user* user, guac_stream* stream, - char* mimetype) { - - guac_client* client = user->client; - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - - int rate; - int channels; - int bps; - - /* Parse mimetype, abort on parse error */ - if (guac_rdp_audio_parse_mimetype(mimetype, &rate, &channels, &bps)) { - guac_user_log(user, GUAC_LOG_WARNING, "Denying user audio stream with " - "unsupported mimetype: \"%s\"", mimetype); - guac_protocol_send_ack(user->socket, stream, "Unsupported audio " - "mimetype", GUAC_PROTOCOL_STATUS_CLIENT_BAD_TYPE); - return 0; - } - - /* Init stream data */ - stream->blob_handler = guac_rdp_audio_blob_handler; - stream->end_handler = guac_rdp_audio_end_handler; - - /* Associate stream with audio buffer */ - guac_rdp_audio_buffer_set_stream(rdp_client->audio_input, user, stream, - rate, channels, bps); - - return 0; - -} - -int guac_rdp_audio_blob_handler(guac_user* user, guac_stream* stream, - void* data, int length) { - - guac_client* client = user->client; - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; - - /* Write blob to audio stream, buffering if necessary */ - guac_rdp_audio_buffer_write(rdp_client->audio_input, data, length); - - return 0; - -} - -int guac_rdp_audio_end_handler(guac_user* user, guac_stream* stream) { - - /* Ignore - the AUDIO_INPUT channel will simply not receive anything */ - return 0; - -} - -void guac_rdp_audio_load_plugin(rdpContext* context) { - - guac_client* client = ((rdp_freerdp_context*) context)->client; - char client_ref[GUAC_RDP_PTR_STRING_LENGTH]; - - /* Add "AUDIO_INPUT" channel */ - guac_rdp_ptr_to_string(client, client_ref); - guac_freerdp_dynamic_channel_collection_add(context->settings, "guacai", client_ref, NULL); - -} guac_rdp_audio_buffer* guac_rdp_audio_buffer_alloc() { guac_rdp_audio_buffer* buffer = calloc(1, sizeof(guac_rdp_audio_buffer)); diff --git a/src/protocols/rdp/channels/audio-input.h b/src/protocols/rdp/channels/audio-input/audio-buffer.h similarity index 90% rename from src/protocols/rdp/channels/audio-input.h rename to src/protocols/rdp/channels/audio-input/audio-buffer.h index 1ff76d58..32f7def8 100644 --- a/src/protocols/rdp/channels/audio-input.h +++ b/src/protocols/rdp/channels/audio-input/audio-buffer.h @@ -17,10 +17,9 @@ * under the License. */ -#ifndef GUAC_RDP_CHANNELS_AUDIO_INPUT_H -#define GUAC_RDP_CHANNELS_AUDIO_INPUT_H +#ifndef GUAC_RDP_CHANNELS_AUDIO_INPUT_AUDIO_BUFFER_H +#define GUAC_RDP_CHANNELS_AUDIO_INPUT_AUDIO_BUFFER_H -#include #include #include #include @@ -274,31 +273,5 @@ void guac_rdp_audio_buffer_end(guac_rdp_audio_buffer* audio_buffer); */ void guac_rdp_audio_buffer_free(guac_rdp_audio_buffer* audio_buffer); -/** - * Handler for inbound audio data (audio input). - */ -guac_user_audio_handler guac_rdp_audio_handler; - -/** - * Handler for stream data related to audio input. - */ -guac_user_blob_handler guac_rdp_audio_blob_handler; - -/** - * Handler for end-of-stream related to audio input. - */ -guac_user_end_handler guac_rdp_audio_end_handler; - -/** - * Adds Guacamole's "guacai" plugin to the list of dynamic virtual channel - * plugins to be loaded by FreeRDP's "drdynvc" plugin. The plugin will only - * be loaded once the "drdynvc" plugin is loaded. The "guacai" plugin - * ultimately adds support for the "AUDIO_INPUT" dynamic virtual channel. - * - * @param context - * The rdpContext associated with the active RDP session. - */ -void guac_rdp_audio_load_plugin(rdpContext* context); - #endif diff --git a/src/protocols/rdp/channels/audio-input/audio-input.c b/src/protocols/rdp/channels/audio-input/audio-input.c new file mode 100644 index 00000000..51fa1188 --- /dev/null +++ b/src/protocols/rdp/channels/audio-input/audio-input.c @@ -0,0 +1,195 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#include "channels/audio-input/audio-buffer.h" +#include "channels/audio-input/audio-input.h" +#include "plugins/channels.h" +#include "plugins/ptr-string.h" +#include "rdp.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/** + * Parses the given raw audio mimetype, producing the corresponding rate, + * number of channels, and bytes per sample. + * + * @param mimetype + * The raw auduio mimetype to parse. + * + * @param rate + * A pointer to an int where the sample rate for the PCM format described + * by the given mimetype should be stored. + * + * @param channels + * A pointer to an int where the number of channels used by the PCM format + * described by the given mimetype should be stored. + * + * @param bps + * A pointer to an int where the number of bytes used the PCM format for + * each sample (independent of number of channels) described by the given + * mimetype should be stored. + * + * @return + * Zero if the given mimetype is a raw audio mimetype and has been parsed + * successfully, non-zero otherwise. + */ +static int guac_rdp_audio_parse_mimetype(const char* mimetype, + int* rate, int* channels, int* bps) { + + int parsed_rate = -1; + int parsed_channels = 1; + int parsed_bps; + + /* PCM audio with one byte per sample */ + if (strncmp(mimetype, "audio/L8;", 9) == 0) { + mimetype += 8; /* Advance to semicolon ONLY */ + parsed_bps = 1; + } + + /* PCM audio with two bytes per sample */ + else if (strncmp(mimetype, "audio/L16;", 10) == 0) { + mimetype += 9; /* Advance to semicolon ONLY */ + parsed_bps = 2; + } + + /* Unsupported mimetype */ + else + return 1; + + /* Parse each parameter name/value pair within the mimetype */ + do { + + /* Advance to first character of parameter (current is either a + * semicolon or a comma) */ + mimetype++; + + /* Parse number of channels */ + if (strncmp(mimetype, "channels=", 9) == 0) { + + mimetype += 9; + parsed_channels = strtol(mimetype, (char**) &mimetype, 10); + + /* Fail if value invalid / out of range */ + if (errno == EINVAL || errno == ERANGE) + return 1; + + } + + /* Parse number of rate */ + else if (strncmp(mimetype, "rate=", 5) == 0) { + + mimetype += 5; + parsed_rate = strtol(mimetype, (char**) &mimetype, 10); + + /* Fail if value invalid / out of range */ + if (errno == EINVAL || errno == ERANGE) + return 1; + + } + + /* Advance to next parameter */ + mimetype = strchr(mimetype, ','); + + } while (mimetype != NULL); + + /* Mimetype is invalid if rate was not specified */ + if (parsed_rate == -1) + return 1; + + /* Parse success */ + *rate = parsed_rate; + *channels = parsed_channels; + *bps = parsed_bps; + + return 0; + +} + +int guac_rdp_audio_handler(guac_user* user, guac_stream* stream, + char* mimetype) { + + guac_client* client = user->client; + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + + int rate; + int channels; + int bps; + + /* Parse mimetype, abort on parse error */ + if (guac_rdp_audio_parse_mimetype(mimetype, &rate, &channels, &bps)) { + guac_user_log(user, GUAC_LOG_WARNING, "Denying user audio stream with " + "unsupported mimetype: \"%s\"", mimetype); + guac_protocol_send_ack(user->socket, stream, "Unsupported audio " + "mimetype", GUAC_PROTOCOL_STATUS_CLIENT_BAD_TYPE); + return 0; + } + + /* Init stream data */ + stream->blob_handler = guac_rdp_audio_blob_handler; + stream->end_handler = guac_rdp_audio_end_handler; + + /* Associate stream with audio buffer */ + guac_rdp_audio_buffer_set_stream(rdp_client->audio_input, user, stream, + rate, channels, bps); + + return 0; + +} + +int guac_rdp_audio_blob_handler(guac_user* user, guac_stream* stream, + void* data, int length) { + + guac_client* client = user->client; + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + + /* Write blob to audio stream, buffering if necessary */ + guac_rdp_audio_buffer_write(rdp_client->audio_input, data, length); + + return 0; + +} + +int guac_rdp_audio_end_handler(guac_user* user, guac_stream* stream) { + + /* Ignore - the AUDIO_INPUT channel will simply not receive anything */ + return 0; + +} + +void guac_rdp_audio_load_plugin(rdpContext* context) { + + guac_client* client = ((rdp_freerdp_context*) context)->client; + char client_ref[GUAC_RDP_PTR_STRING_LENGTH]; + + /* Add "AUDIO_INPUT" channel */ + guac_rdp_ptr_to_string(client, client_ref); + guac_freerdp_dynamic_channel_collection_add(context->settings, "guacai", client_ref, NULL); + +} + diff --git a/src/protocols/rdp/channels/audio-input/audio-input.h b/src/protocols/rdp/channels/audio-input/audio-input.h new file mode 100644 index 00000000..a3b705f7 --- /dev/null +++ b/src/protocols/rdp/channels/audio-input/audio-input.h @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#ifndef GUAC_RDP_CHANNELS_AUDIO_INPUT_H +#define GUAC_RDP_CHANNELS_AUDIO_INPUT_H + +#include +#include + +/** + * Handler for inbound audio data (audio input). + */ +guac_user_audio_handler guac_rdp_audio_handler; + +/** + * Handler for stream data related to audio input. + */ +guac_user_blob_handler guac_rdp_audio_blob_handler; + +/** + * Handler for end-of-stream related to audio input. + */ +guac_user_end_handler guac_rdp_audio_end_handler; + +/** + * Adds Guacamole's "guacai" plugin to the list of dynamic virtual channel + * plugins to be loaded by FreeRDP's "drdynvc" plugin. The plugin will only + * be loaded once the "drdynvc" plugin is loaded. The "guacai" plugin + * ultimately adds support for the "AUDIO_INPUT" dynamic virtual channel. + * + * @param context + * The rdpContext associated with the active RDP session. + */ +void guac_rdp_audio_load_plugin(rdpContext* context); + +#endif + diff --git a/src/protocols/rdp/client.c b/src/protocols/rdp/client.c index 8cbc1635..c79e59d8 100644 --- a/src/protocols/rdp/client.c +++ b/src/protocols/rdp/client.c @@ -18,7 +18,7 @@ */ #include "client.h" -#include "channels/audio-input.h" +#include "channels/audio-input/audio-buffer.h" #include "channels/cliprdr.h" #include "channels/disp.h" #include "common/recording.h" diff --git a/src/protocols/rdp/plugins/guacai/guacai-messages.c b/src/protocols/rdp/plugins/guacai/guacai-messages.c index 9e4b4142..38f7a7c4 100644 --- a/src/protocols/rdp/plugins/guacai/guacai-messages.c +++ b/src/protocols/rdp/plugins/guacai/guacai-messages.c @@ -17,7 +17,7 @@ * under the License. */ -#include "channels/audio-input.h" +#include "channels/audio-input/audio-buffer.h" #include "plugins/guacai/guacai-messages.h" #include "rdp.h" diff --git a/src/protocols/rdp/plugins/guacai/guacai-messages.h b/src/protocols/rdp/plugins/guacai/guacai-messages.h index 49fbd1cb..6a2333fc 100644 --- a/src/protocols/rdp/plugins/guacai/guacai-messages.h +++ b/src/protocols/rdp/plugins/guacai/guacai-messages.h @@ -20,7 +20,7 @@ #ifndef GUAC_RDP_PLUGINS_GUACAI_MESSAGES_H #define GUAC_RDP_PLUGINS_GUACAI_MESSAGES_H -#include "channels/audio-input.h" +#include "channels/audio-input/audio-buffer.h" #include #include diff --git a/src/protocols/rdp/plugins/guacai/guacai.c b/src/protocols/rdp/plugins/guacai/guacai.c index 80dd87f3..15de8655 100644 --- a/src/protocols/rdp/plugins/guacai/guacai.c +++ b/src/protocols/rdp/plugins/guacai/guacai.c @@ -17,7 +17,7 @@ * under the License. */ -#include "channels/audio-input.h" +#include "channels/audio-input/audio-buffer.h" #include "plugins/guacai/guacai.h" #include "plugins/guacai/guacai-messages.h" #include "plugins/ptr-string.h" diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 07475c56..5cf651ad 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -18,7 +18,8 @@ */ #include "bitmap.h" -#include "channels/audio-input.h" +#include "channels/audio-input/audio-buffer.h" +#include "channels/audio-input/audio-input.h" #include "channels/cliprdr.h" #include "channels/disp.h" #include "channels/pipe-svc.h" diff --git a/src/protocols/rdp/rdp.h b/src/protocols/rdp/rdp.h index 43f6dc2d..32f72df7 100644 --- a/src/protocols/rdp/rdp.h +++ b/src/protocols/rdp/rdp.h @@ -20,7 +20,7 @@ #ifndef GUAC_RDP_H #define GUAC_RDP_H -#include "channels/audio-input.h" +#include "channels/audio-input/audio-buffer.h" #include "channels/cliprdr.h" #include "channels/disp.h" #include "common/clipboard.h" diff --git a/src/protocols/rdp/user.c b/src/protocols/rdp/user.c index 2e96b9a2..38f2623b 100644 --- a/src/protocols/rdp/user.c +++ b/src/protocols/rdp/user.c @@ -17,7 +17,7 @@ * under the License. */ -#include "channels/audio-input.h" +#include "channels/audio-input/audio-input.h" #include "channels/cliprdr.h" #include "channels/pipe-svc.h" #include "common/cursor.h" From eaae203e94563953883aeeed609affdb18022edb Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 12 Jan 2020 22:32:48 -0800 Subject: [PATCH 103/109] GUACAMOLE-249: Ensure RAIL message handlers are accepted by compiler regardless of whether const is required. --- src/protocols/rdp/channels/rail.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/protocols/rdp/channels/rail.c b/src/protocols/rdp/channels/rail.c index 07b0babb..60ead636 100644 --- a/src/protocols/rdp/channels/rail.c +++ b/src/protocols/rdp/channels/rail.c @@ -164,8 +164,8 @@ static void guac_rdp_rail_channel_connected(rdpContext* context, /* Init FreeRDP RAIL context, ensuring the guac_client can be accessed from * within any RAIL-specific callbacks */ rail->custom = client; - rail->ServerHandshake = guac_rdp_rail_handshake; - rail->ServerHandshakeEx = guac_rdp_rail_handshake_ex; + rail->ServerHandshake = (pcRailServerHandshake) guac_rdp_rail_handshake; + rail->ServerHandshakeEx = (pcRailServerHandshakeEx) guac_rdp_rail_handshake_ex; guac_client_log(client, GUAC_LOG_DEBUG, "RAIL (RemoteApp) channel " "connected."); From 9a34caf40f41cf57a98af7391c42d78f09b4fe4b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 13 Jan 2020 15:42:27 -0800 Subject: [PATCH 104/109] GUACAMOLE-249: The FreeRDPConvertColor() function is also known as ConvertColor(), but was only available as ConvertColor() in older FreeRDP 2.0.0 release candidates. --- configure.ac | 16 +++++++++++++++- src/protocols/rdp/color.c | 5 +++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 928c4363..2f833244 100644 --- a/configure.ac +++ b/configure.ac @@ -541,7 +541,8 @@ AC_ARG_WITH([rdp], if test "x$with_rdp" != "xno" then have_freerdp2=yes - PKG_CHECK_MODULES([RDP], [freerdp2 freerdp-client2 winpr2],, + PKG_CHECK_MODULES([RDP], [freerdp2 freerdp-client2 winpr2], + [CPPFLAGS="${RDP_CFLAGS} $CPPFLAGS"], [AC_MSG_WARN([ -------------------------------------------- Unable to find FreeRDP (libfreerdp2 / libfreerdp-client2 / libwinpr2) @@ -550,6 +551,19 @@ then have_freerdp2=no]) fi +# Available color conversion functions +if test "x$have_freerdp2" = "xyes" +then + + # FreeRDP 2.0.0-rc3 and older referred to FreeRDPConvertColor() as + # ConvertColor() + AC_CHECK_DECL([FreeRDPConvertColor], + [AC_DEFINE([HAVE_FREERDPCONVERTCOLOR],, + [Whether FreeRDPConvertColor() is defined])],, + [#include ]) + +fi + AM_CONDITIONAL([ENABLE_RDP], [test "x${have_freerdp2}" = "xyes"]) # diff --git a/src/protocols/rdp/color.c b/src/protocols/rdp/color.c index ee7b7ce9..964310af 100644 --- a/src/protocols/rdp/color.c +++ b/src/protocols/rdp/color.c @@ -17,6 +17,7 @@ * under the License. */ +#include "config.h" #include "settings.h" #include @@ -59,8 +60,12 @@ UINT32 guac_rdp_convert_color(rdpContext* context, UINT32 color) { /* Convert color from RDP source format to the native format used by Cairo, * still maintaining intermediate representation */ +#ifdef HAVE_FREERDPCONVERTCOLOR intermed = FreeRDPConvertColor(intermed, src_format, dst_format, &gdi->palette); +#else + intermed = ConvertColor(intermed, src_format, dst_format, &gdi->palette); +#endif /* Convert color from intermediate representation to the actual desired * format */ From 308d7a09a8adec2efbca44eceac61395cb7fbbaf Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 13 Jan 2020 16:09:44 -0800 Subject: [PATCH 105/109] GUACAMOLE-249: Support rdpGlyph callback format used in FreeRDP 2.0.0-rc3 and older (used UINT32 instead of INT32). --- configure.ac | 33 +++++++++++++++++++++++++++++++++ src/protocols/rdp/glyph.c | 17 +++++++++++------ src/protocols/rdp/glyph.h | 33 +++++++++++++++++++++++++++------ 3 files changed, 71 insertions(+), 12 deletions(-) diff --git a/configure.ac b/configure.ac index 2f833244..e37b4dbf 100644 --- a/configure.ac +++ b/configure.ac @@ -564,6 +564,39 @@ then fi +# Glyph callback variants +if test "x${have_freerdp2}" = "xyes" +then + + # FreeRDP 2.0.0-rc3 and older used UINT32 for integer parameters to all + # rdpGlyph callbacks + AC_MSG_CHECKING([whether rdpGlyph callbacks accept INT32 integer parameters]) + AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ + + #include + #include + #include + + BOOL test_begindraw(rdpContext* context, INT32 x, INT32 y, + INT32 width, INT32 height, UINT32 fgcolor, UINT32 bgcolor, + BOOL redundant); + + rdpGlyph glyph = { + .BeginDraw = test_begindraw + }; + + int main() { + return (int) glyph.BeginDraw(NULL, 0, 0, 0, 0, 0, 0, FALSE); + } + + ]])], + [AC_MSG_RESULT([yes])] + [AC_DEFINE([FREERDP_GLYPH_CALLBACKS_ACCEPT_INT32],, + [Whether rdpGlyph callbacks accept INT32 integer parameters])], + [AC_MSG_RESULT([no])]) + +fi + AM_CONDITIONAL([ENABLE_RDP], [test "x${have_freerdp2}" = "xyes"]) # diff --git a/src/protocols/rdp/glyph.c b/src/protocols/rdp/glyph.c index cecaa8d9..d8413841 100644 --- a/src/protocols/rdp/glyph.c +++ b/src/protocols/rdp/glyph.c @@ -91,7 +91,9 @@ BOOL guac_rdp_glyph_new(rdpContext* context, const rdpGlyph* glyph) { } BOOL guac_rdp_glyph_draw(rdpContext* context, const rdpGlyph* glyph, - INT32 x, INT32 y, INT32 w, INT32 h, INT32 sx, INT32 sy, + GLYPH_CALLBACK_INT32 x, GLYPH_CALLBACK_INT32 y, + GLYPH_CALLBACK_INT32 w, GLYPH_CALLBACK_INT32 h, + GLYPH_CALLBACK_INT32 sx, GLYPH_CALLBACK_INT32 sy, BOOL redundant) { guac_client* client = ((rdp_freerdp_context*) context)->client; @@ -127,9 +129,10 @@ void guac_rdp_glyph_free(rdpContext* context, rdpGlyph* glyph) { } -BOOL guac_rdp_glyph_begindraw(rdpContext* context, INT32 x, INT32 y, - INT32 width, INT32 height, UINT32 fgcolor, UINT32 bgcolor, - BOOL redundant) { +BOOL guac_rdp_glyph_begindraw(rdpContext* context, + GLYPH_CALLBACK_INT32 x, GLYPH_CALLBACK_INT32 y, + GLYPH_CALLBACK_INT32 width, GLYPH_CALLBACK_INT32 height, + UINT32 fgcolor, UINT32 bgcolor, BOOL redundant) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_rdp_client* rdp_client = @@ -157,8 +160,10 @@ BOOL guac_rdp_glyph_begindraw(rdpContext* context, INT32 x, INT32 y, } -BOOL guac_rdp_glyph_enddraw(rdpContext* context, INT32 x, INT32 y, - INT32 width, INT32 height, UINT32 fgcolor, UINT32 bgcolor) { +BOOL guac_rdp_glyph_enddraw(rdpContext* context, + GLYPH_CALLBACK_INT32 x, GLYPH_CALLBACK_INT32 y, + GLYPH_CALLBACK_INT32 width, GLYPH_CALLBACK_INT32 height, + UINT32 fgcolor, UINT32 bgcolor) { /* IGNORE */ return TRUE; } diff --git a/src/protocols/rdp/glyph.h b/src/protocols/rdp/glyph.h index 1e9b389b..85f2080d 100644 --- a/src/protocols/rdp/glyph.h +++ b/src/protocols/rdp/glyph.h @@ -20,11 +20,27 @@ #ifndef GUAC_RDP_GLYPH_H #define GUAC_RDP_GLYPH_H +#include "config.h" + #include #include #include #include +#ifdef FREERDP_GLYPH_CALLBACKS_ACCEPT_INT32 +/** + * FreeRDP 2.0.0-rc4 and newer requires INT32 for all integer arguments of + * glyph callbacks. + */ +#define GLYPH_CALLBACK_INT32 INT32 +#else +/** + * FreeRDP 2.0.0-rc3 and older requires UINT32 for all integer arguments of + * glyph callbacks. + */ +#define GLYPH_CALLBACK_INT32 UINT32 +#endif + /** * Guacamole-specific rdpGlyph data. */ @@ -94,7 +110,9 @@ BOOL guac_rdp_glyph_new(rdpContext* context, const rdpGlyph* glyph); * TRUE if successful, FALSE otherwise. */ BOOL guac_rdp_glyph_draw(rdpContext* context, const rdpGlyph* glyph, - INT32 x, INT32 y, INT32 w, INT32 h, INT32 sx, INT32 sy, + GLYPH_CALLBACK_INT32 x, GLYPH_CALLBACK_INT32 y, + GLYPH_CALLBACK_INT32 w, GLYPH_CALLBACK_INT32 h, + GLYPH_CALLBACK_INT32 sx, GLYPH_CALLBACK_INT32 sy, BOOL redundant); /** @@ -150,9 +168,10 @@ void guac_rdp_glyph_free(rdpContext* context, rdpGlyph* glyph); * @return * TRUE if successful, FALSE otherwise. */ -BOOL guac_rdp_glyph_begindraw(rdpContext* context, INT32 x, INT32 y, - INT32 width, INT32 height, UINT32 fgcolor, UINT32 bgcolor, - BOOL redundant); +BOOL guac_rdp_glyph_begindraw(rdpContext* context, + GLYPH_CALLBACK_INT32 x, GLYPH_CALLBACK_INT32 y, + GLYPH_CALLBACK_INT32 width, GLYPH_CALLBACK_INT32 height, + UINT32 fgcolor, UINT32 bgcolor, BOOL redundant); /** * Called immediately after rendering a series of glyphs. Unlike @@ -191,7 +210,9 @@ BOOL guac_rdp_glyph_begindraw(rdpContext* context, INT32 x, INT32 y, * @return * TRUE if successful, FALSE otherwise. */ -BOOL guac_rdp_glyph_enddraw(rdpContext* context, INT32 x, INT32 y, - INT32 width, INT32 height, UINT32 fgcolor, UINT32 bgcolor); +BOOL guac_rdp_glyph_enddraw(rdpContext* context, + GLYPH_CALLBACK_INT32 x, GLYPH_CALLBACK_INT32 y, + GLYPH_CALLBACK_INT32 width, GLYPH_CALLBACK_INT32 height, + UINT32 fgcolor, UINT32 bgcolor); #endif From e5fdda1286cf01321f289b383a3308e3db8b571a Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 13 Jan 2020 16:22:50 -0800 Subject: [PATCH 106/109] GUACAMOLE-249: Remove CLIPRDR callback typecasts, relying instead on configure tests to check need for const. --- configure.ac | 30 +++++++++++++++++++++++++++ src/protocols/rdp/channels/cliprdr.c | 31 +++++++++++++++++++++------- 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/configure.ac b/configure.ac index e37b4dbf..f245da3a 100644 --- a/configure.ac +++ b/configure.ac @@ -597,6 +597,36 @@ then fi +# CLIPRDR callback variants +if test "x${have_freerdp2}" = "xyes" +then + + # FreeRDP 2.0.0-rc3 and older did not use const for CLIPRDR callbacks + AC_MSG_CHECKING([whether CLIPRDR callbacks require const for their final parameter]) + AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ + + #include + #include + + UINT test_monitor_ready(CliprdrClientContext* cliprdr, + const CLIPRDR_MONITOR_READY* monitor_ready); + + CliprdrClientContext context = { + .MonitorReady = test_monitor_ready + }; + + int main() { + return (int) context.MonitorReady(NULL, NULL); + } + + ]])], + [AC_MSG_RESULT([yes])] + [AC_DEFINE([FREERDP_CLIPRDR_CALLBACKS_REQUIRE_CONST],, + [Whether CLIPRDR callbacks require const for the final parameter])], + [AC_MSG_RESULT([no])]) + +fi + AM_CONDITIONAL([ENABLE_RDP], [test "x${have_freerdp2}" = "xyes"]) # diff --git a/src/protocols/rdp/channels/cliprdr.c b/src/protocols/rdp/channels/cliprdr.c index 4332d35f..6911c197 100644 --- a/src/protocols/rdp/channels/cliprdr.c +++ b/src/protocols/rdp/channels/cliprdr.c @@ -21,6 +21,7 @@ #include "client.h" #include "common/clipboard.h" #include "common/iconv.h" +#include "config.h" #include "plugins/channels.h" #include "rdp.h" @@ -37,6 +38,20 @@ #include #include +#ifdef FREERDP_CLIPRDR_CALLBACKS_REQUIRE_CONST +/** + * FreeRDP 2.0.0-rc4 and newer requires the final argument for all CLIPRDR + * callbacks to be const. + */ +#define CLIPRDR_CONST const +#else +/** + * FreeRDP 2.0.0-rc3 and older requires the final argument for all CLIPRDR + * callbacks to NOT be const. + */ +#define CLIPRDR_CONST +#endif + /** * Sends a Format List PDU to the RDP server containing the formats of * clipboard data supported. This PDU is used both to indicate the general @@ -127,7 +142,7 @@ static UINT guac_rdp_cliprdr_send_capabilities(CliprdrClientContext* cliprdr) { * (non-zero) otherwise. */ static UINT guac_rdp_cliprdr_monitor_ready(CliprdrClientContext* cliprdr, - const CLIPRDR_MONITOR_READY* monitor_ready) { + CLIPRDR_CONST CLIPRDR_MONITOR_READY* monitor_ready) { /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not * callable, until after the relevant guac_rdp_clipboard structure is @@ -241,7 +256,7 @@ static int guac_rdp_cliprdr_format_supported(const CLIPRDR_FORMAT_LIST* format_l * (non-zero) otherwise. */ static UINT guac_rdp_cliprdr_format_list(CliprdrClientContext* cliprdr, - const CLIPRDR_FORMAT_LIST* format_list) { + CLIPRDR_CONST CLIPRDR_FORMAT_LIST* format_list) { /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not * callable, until after the relevant guac_rdp_clipboard structure is @@ -296,7 +311,7 @@ static UINT guac_rdp_cliprdr_format_list(CliprdrClientContext* cliprdr, * (non-zero) otherwise. */ static UINT guac_rdp_cliprdr_format_data_request(CliprdrClientContext* cliprdr, - const CLIPRDR_FORMAT_DATA_REQUEST* format_data_request) { + CLIPRDR_CONST CLIPRDR_FORMAT_DATA_REQUEST* format_data_request) { /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not * callable, until after the relevant guac_rdp_clipboard structure is @@ -373,7 +388,7 @@ static UINT guac_rdp_cliprdr_format_data_request(CliprdrClientContext* cliprdr, * (non-zero) otherwise. */ static UINT guac_rdp_cliprdr_format_data_response(CliprdrClientContext* cliprdr, - const CLIPRDR_FORMAT_DATA_RESPONSE* format_data_response) { + CLIPRDR_CONST CLIPRDR_FORMAT_DATA_RESPONSE* format_data_response) { /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not * callable, until after the relevant guac_rdp_clipboard structure is @@ -474,10 +489,10 @@ static void guac_rdp_cliprdr_channel_connected(rdpContext* context, cliprdr->custom = clipboard; clipboard->cliprdr = cliprdr; - cliprdr->MonitorReady = (pcCliprdrMonitorReady) guac_rdp_cliprdr_monitor_ready; - cliprdr->ServerFormatList = (pcCliprdrServerFormatList) guac_rdp_cliprdr_format_list; - cliprdr->ServerFormatDataRequest = (pcCliprdrServerFormatDataRequest) guac_rdp_cliprdr_format_data_request; - cliprdr->ServerFormatDataResponse = (pcCliprdrServerFormatDataResponse) guac_rdp_cliprdr_format_data_response; + cliprdr->MonitorReady = guac_rdp_cliprdr_monitor_ready; + cliprdr->ServerFormatList = guac_rdp_cliprdr_format_list; + cliprdr->ServerFormatDataRequest = guac_rdp_cliprdr_format_data_request; + cliprdr->ServerFormatDataResponse = guac_rdp_cliprdr_format_data_response; guac_client_log(client, GUAC_LOG_DEBUG, "CLIPRDR (clipboard redirection) " "channel connected."); From 3dfd2467c34c2a6bb71abddab4110047cf58c987 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 13 Jan 2020 16:32:38 -0800 Subject: [PATCH 107/109] GUACAMOLE-249: Remove RAIL callback typecasts, relying instead on configure tests to check need for const. --- configure.ac | 30 ++++++++++++++++++++++++++++++ src/protocols/rdp/channels/rail.c | 22 ++++++++++++++++++---- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index f245da3a..ef8f6619 100644 --- a/configure.ac +++ b/configure.ac @@ -627,6 +627,36 @@ then fi +# RAIL callback variants +if test "x${have_freerdp2}" = "xyes" +then + + # FreeRDP 2.0.0-rc3 and older did not use const for RAIL callbacks + AC_MSG_CHECKING([whether RAIL callbacks require const for their final parameter]) + AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ + + #include + #include + + UINT test_server_handshake(RailClientContext* rail, + const RAIL_HANDSHAKE_ORDER* handshake); + + RailClientContext context = { + .ServerHandshake = test_server_handshake + }; + + int main() { + return (int) context.ServerHandshake(NULL, NULL); + } + + ]])], + [AC_MSG_RESULT([yes])] + [AC_DEFINE([FREERDP_RAIL_CALLBACKS_REQUIRE_CONST],, + [Whether RAIL callbacks require const for the final parameter])], + [AC_MSG_RESULT([no])]) + +fi + AM_CONDITIONAL([ENABLE_RDP], [test "x${have_freerdp2}" = "xyes"]) # diff --git a/src/protocols/rdp/channels/rail.c b/src/protocols/rdp/channels/rail.c index 60ead636..3e800075 100644 --- a/src/protocols/rdp/channels/rail.c +++ b/src/protocols/rdp/channels/rail.c @@ -33,6 +33,20 @@ #include #include +#ifdef FREERDP_RAIL_CALLBACKS_REQUIRE_CONST +/** + * FreeRDP 2.0.0-rc4 and newer requires the final argument for all RAIL + * callbacks to be const. + */ +#define RAIL_CONST const +#else +/** + * FreeRDP 2.0.0-rc3 and older requires the final argument for all RAIL + * callbacks to NOT be const. + */ +#define RAIL_CONST +#endif + /** * Completes initialization of the RemoteApp session, sending client system * parameters and executing the desired RemoteApp command using the Client @@ -102,7 +116,7 @@ static UINT guac_rdp_rail_complete_handshake(RailClientContext* rail) { * (non-zero) otherwise. */ static UINT guac_rdp_rail_handshake(RailClientContext* rail, - const RAIL_HANDSHAKE_ORDER* handshake) { + RAIL_CONST RAIL_HANDSHAKE_ORDER* handshake) { return guac_rdp_rail_complete_handshake(rail); } @@ -126,7 +140,7 @@ static UINT guac_rdp_rail_handshake(RailClientContext* rail, * (non-zero) otherwise. */ static UINT guac_rdp_rail_handshake_ex(RailClientContext* rail, - const RAIL_HANDSHAKE_EX_ORDER* handshake_ex) { + RAIL_CONST RAIL_HANDSHAKE_EX_ORDER* handshake_ex) { return guac_rdp_rail_complete_handshake(rail); } @@ -164,8 +178,8 @@ static void guac_rdp_rail_channel_connected(rdpContext* context, /* Init FreeRDP RAIL context, ensuring the guac_client can be accessed from * within any RAIL-specific callbacks */ rail->custom = client; - rail->ServerHandshake = (pcRailServerHandshake) guac_rdp_rail_handshake; - rail->ServerHandshakeEx = (pcRailServerHandshakeEx) guac_rdp_rail_handshake_ex; + rail->ServerHandshake = guac_rdp_rail_handshake; + rail->ServerHandshakeEx = guac_rdp_rail_handshake_ex; guac_client_log(client, GUAC_LOG_DEBUG, "RAIL (RemoteApp) channel " "connected."); From de3300ed89e036516349bd532d305ca2879ed33f Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 13 Jan 2020 18:17:32 -0800 Subject: [PATCH 108/109] GUACAMOLE-249: Preserve CPPFLAGS such that modifications needed for FreeRDP tests affect only FreeRDP tests. --- configure.ac | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/configure.ac b/configure.ac index ef8f6619..cdd75666 100644 --- a/configure.ac +++ b/configure.ac @@ -538,6 +538,10 @@ AC_ARG_WITH([rdp], [], [with_rdp=check]) +# Preserve CPPFLAGS so it can be restored later, following the addition of +# options specific to FreeRDP tests +OLDCPPFLAGS="$CPPFLAGS" + if test "x$with_rdp" != "xno" then have_freerdp2=yes @@ -657,6 +661,9 @@ then fi +# Restore CPPFLAGS, removing FreeRDP-specific options needed for testing +CPPFLAGS="$OLDCPPFLAGS" + AM_CONDITIONAL([ENABLE_RDP], [test "x${have_freerdp2}" = "xyes"]) # From 99b00a8cc0fff05c1ce62ce03ccd3a0c35e61cc9 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 13 Jan 2020 18:17:56 -0800 Subject: [PATCH 109/109] GUACAMOLE-249: Add -Werror to CPPFLAGS for FreeRDP tests to ensure tests fail when pointers are incompatible. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index cdd75666..eb182feb 100644 --- a/configure.ac +++ b/configure.ac @@ -546,7 +546,7 @@ if test "x$with_rdp" != "xno" then have_freerdp2=yes PKG_CHECK_MODULES([RDP], [freerdp2 freerdp-client2 winpr2], - [CPPFLAGS="${RDP_CFLAGS} $CPPFLAGS"], + [CPPFLAGS="${RDP_CFLAGS} -Werror $CPPFLAGS"], [AC_MSG_WARN([ -------------------------------------------- Unable to find FreeRDP (libfreerdp2 / libfreerdp-client2 / libwinpr2)