GUACAMOLE-962: Merge allow misbehaving RDP servers to use OpaqueRect and PatBlt.
This commit is contained in:
commit
d2ee11f15a
15
configure.ac
15
configure.ac
@ -722,6 +722,21 @@ then
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Support for receiving unannounced orders from the RDP server
|
||||||
|
if test "x${have_freerdp2}" = "xyes"
|
||||||
|
then
|
||||||
|
AC_CHECK_MEMBERS([rdpSettings.AllowUnanouncedOrdersFromServer],,
|
||||||
|
[AC_MSG_WARN([
|
||||||
|
--------------------------------------------
|
||||||
|
This version of FreeRDP does not support relaxed order checks. RDP servers
|
||||||
|
that send orders that the client did not announce as supported (such as the
|
||||||
|
VirtualBox RDP server) will likely not be usable.
|
||||||
|
|
||||||
|
See: https://issues.apache.org/jira/browse/GUACAMOLE-962
|
||||||
|
--------------------------------------------])],
|
||||||
|
[[#include <freerdp/freerdp.h>]])
|
||||||
|
fi
|
||||||
|
|
||||||
# Restore CPPFLAGS, removing FreeRDP-specific options needed for testing
|
# Restore CPPFLAGS, removing FreeRDP-specific options needed for testing
|
||||||
CPPFLAGS="$OLDCPPFLAGS"
|
CPPFLAGS="$OLDCPPFLAGS"
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "bitmap.h"
|
#include "bitmap.h"
|
||||||
|
#include "color.h"
|
||||||
#include "common/display.h"
|
#include "common/display.h"
|
||||||
#include "common/surface.h"
|
#include "common/surface.h"
|
||||||
#include "rdp.h"
|
#include "rdp.h"
|
||||||
@ -139,6 +140,76 @@ 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) {
|
BOOL guac_rdp_gdi_scrblt(rdpContext* context, const SCRBLT_ORDER* scrblt) {
|
||||||
|
|
||||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||||
@ -256,6 +327,30 @@ 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) {
|
BOOL guac_rdp_gdi_set_bounds(rdpContext* context, const rdpBounds* bounds) {
|
||||||
|
|
||||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||||
|
@ -62,6 +62,25 @@ guac_composite_mode guac_rdp_rop3_transfer_function(guac_client* client,
|
|||||||
*/
|
*/
|
||||||
BOOL guac_rdp_gdi_dstblt(rdpContext* context, const DSTBLT_ORDER* dstblt);
|
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
|
* Handler for the ScrBlt Primary Drawing Order. A ScrBlt Primary Drawing Order
|
||||||
* paints a rectangle of image data using a raster operation which considers
|
* paints a rectangle of image data using a raster operation which considers
|
||||||
@ -98,6 +117,26 @@ BOOL guac_rdp_gdi_scrblt(rdpContext* context, const SCRBLT_ORDER* scrblt);
|
|||||||
*/
|
*/
|
||||||
BOOL guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt);
|
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
|
* 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
|
* those updates are clipped by a bounding rectangle. This is not a true RDP
|
||||||
|
@ -179,8 +179,10 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) {
|
|||||||
|
|
||||||
rdpPrimaryUpdate* primary = instance->update->primary;
|
rdpPrimaryUpdate* primary = instance->update->primary;
|
||||||
primary->DstBlt = guac_rdp_gdi_dstblt;
|
primary->DstBlt = guac_rdp_gdi_dstblt;
|
||||||
|
primary->PatBlt = guac_rdp_gdi_patblt;
|
||||||
primary->ScrBlt = guac_rdp_gdi_scrblt;
|
primary->ScrBlt = guac_rdp_gdi_scrblt;
|
||||||
primary->MemBlt = guac_rdp_gdi_memblt;
|
primary->MemBlt = guac_rdp_gdi_memblt;
|
||||||
|
primary->OpaqueRect = guac_rdp_gdi_opaquerect;
|
||||||
|
|
||||||
pointer_cache_register_callbacks(instance->update);
|
pointer_cache_register_callbacks(instance->update);
|
||||||
glyph_cache_register_callbacks(instance->update);
|
glyph_cache_register_callbacks(instance->update);
|
||||||
|
@ -1356,5 +1356,10 @@ void guac_rdp_push_settings(guac_client* client,
|
|||||||
rdp_settings->OrderSupport[NEG_FAST_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;
|
rdp_settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = !guac_settings->disable_glyph_caching;
|
||||||
|
|
||||||
|
#ifdef HAVE_RDPSETTINGS_ALLOWUNANOUNCEDORDERSFROMSERVER
|
||||||
|
/* Do not consider server use of unannounced orders to be a fatal error */
|
||||||
|
rdp_settings->AllowUnanouncedOrdersFromServer = TRUE;
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user