Merge staging/1.2.0 changes back to master.

This commit is contained in:
Nick Couchman 2020-02-24 22:50:10 -05:00
commit 811d2f70e4
6 changed files with 161 additions and 6 deletions

View File

@ -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"

View File

@ -586,7 +586,6 @@ static int guac_common_ssh_sftp_ls_ack_handler(guac_user* user,
guac_stream* stream, char* message, guac_protocol_status status) { guac_stream* stream, char* message, guac_protocol_status status) {
int bytes_read; int bytes_read;
int blob_written = 0;
char filename[GUAC_COMMON_SSH_SFTP_MAX_PATH]; char filename[GUAC_COMMON_SSH_SFTP_MAX_PATH];
LIBSSH2_SFTP_ATTRIBUTES attributes; LIBSSH2_SFTP_ATTRIBUTES attributes;
@ -608,8 +607,7 @@ static int guac_common_ssh_sftp_ls_ack_handler(guac_user* user,
/* While directory entries remain */ /* While directory entries remain */
while ((bytes_read = libssh2_sftp_readdir(list_state->directory, while ((bytes_read = libssh2_sftp_readdir(list_state->directory,
filename, sizeof(filename), &attributes)) > 0 filename, sizeof(filename), &attributes)) > 0) {
&& !blob_written) {
char absolute_path[GUAC_COMMON_SSH_SFTP_MAX_PATH]; char absolute_path[GUAC_COMMON_SSH_SFTP_MAX_PATH];
@ -639,9 +637,10 @@ static int guac_common_ssh_sftp_ls_ack_handler(guac_user* user,
else else
mimetype = "application/octet-stream"; mimetype = "application/octet-stream";
/* Write entry */ /* Write entry, waiting for next ack if a blob is written */
blob_written |= guac_common_json_write_property(user, stream, if (guac_common_json_write_property(user, stream,
&list_state->json_state, absolute_path, mimetype); &list_state->json_state, absolute_path, mimetype))
break;
} }

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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
} }