/* TODO: validate for allowed monitors in terminal server (maybe by config?) */ for (i = 0; i < description->monitorCount; i++)
{
out_uint32_le(s, description->minfo[i].left);
out_uint32_le(s, description->minfo[i].top);
out_uint32_le(s, description->minfo[i].right);
out_uint32_le(s, description->minfo[i].bottom);
out_uint32_le(s, description->minfo[i].is_primary);
}
s_mark_end(s);
// [MS-RDPBCGR] // - 2.2.12.1 - ...the pduSource field MUST be set to zero. // - 3.3.5.12.1 - The contents of this PDU SHOULD NOT be compressed
rv = xrdp_rdp_send_data_from_channel(self, s,
PDUTYPE2_MONITOR_LAYOUT_PDU, 0, 0);
free_stream(s); return rv;
}
/*****************************************************************************/ staticint
xrdp_caps_process_general(struct xrdp_rdp *self, struct stream *s, int len)
{ int extraFlags; int client_does_fastpath_output;
if (len < 10 + 2)
{
LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: " "len 12, remaining %d", len); return1;
}
self->client_info.op1 = extraFlags & NO_BITMAP_COMPRESSION_HDR; /* use_compact_packets is pretty much 'use rdp5' */
self->client_info.use_compact_packets = (extraFlags != 0); /* op2 is a boolean to use compact bitmap headers in bitmap cache */ /* set it to same as 'use rdp5' boolean */
self->client_info.op2 = self->client_info.use_compact_packets; /* FASTPATH_OUTPUT_SUPPORTED 0x0001 */
client_does_fastpath_output = extraFlags & FASTPATH_OUTPUT_SUPPORTED; if ((self->client_info.use_fast_path & 1) && !client_does_fastpath_output)
{ /* server supports fast path output and client does not, turn it off */
self->client_info.use_fast_path &= ~1;
} return0;
}
/*****************************************************************************/ staticint
xrdp_caps_process_bitmap(struct xrdp_rdp *self, struct stream *s, int len)
{ /* [MS-RDPBCGR] 2.2.7.1.2 */ int desktopResizeFlag; if (len < 14 + 2)
{
LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: " "len 16, remaining %d", len); return1;
}
/* Work out what kind of client resizing we can do from the server */ int early_cap_flags = self->client_info.mcs_early_capability_flags; if (desktopResizeFlag == 0)
{
self->client_info.client_resize_mode = CRMODE_NONE;
LOG(LOG_LEVEL_INFO, "Client cannot be resized by xrdp");
} elseif ((early_cap_flags & RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU) == 0)
{
self->client_info.client_resize_mode = CRMODE_SINGLE_SCREEN;
LOG(LOG_LEVEL_INFO, "Client supports single-screen resizes by xrdp");
} else
{
self->client_info.client_resize_mode = CRMODE_MULTI_SCREEN;
LOG(LOG_LEVEL_INFO, "Client supports multi-screen resizes by xrdp");
}
return0;
}
/*****************************************************************************/ /* *Process[MS-RDPBCGR]TS_ORDER_CAPABILITYSET(2.2.7.1.3)message.
*/ staticint
xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s, int len)
{ int i; char order_caps[32]; int ex_flags; int cap_flags;
if (len < 20 + 2 + 2 + 2 + 2 + 2 + 2 + 32 + 2 + 2 + 4 + 4 + 4 + 4)
{
LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: " "len 84, remaining %d", len); return1;
}
in_uint8s(s, 20); /* Terminal desc, pad */
in_uint8s(s, 2); /* Cache X granularity */
in_uint8s(s, 2); /* Cache Y granularity */
in_uint8s(s, 2); /* Pad */
in_uint8s(s, 2); /* Max order level */
in_uint8s(s, 2); /* Number of fonts */
in_uint16_le(s, cap_flags); /* Capability flags */
in_uint8a(s, order_caps, 32); /* Orders supported */
g_memcpy(self->client_info.orders, order_caps, 32);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: terminalDescriptor (ignored as per protocol spec)");
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: desktopSaveXGranularity (ignored as per protocol spec)");
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: desktopSaveYGranularity (ignored as per protocol spec)");
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: maximumOrderLevel (ignored as per protocol spec)");
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: numberFonts (ignored as per protocol spec)");
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderFlags 0x%4.4x", cap_flags);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 0: DstBlt %d", order_caps[0]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 1: PatBlt %d", order_caps[1]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 2: ScrBlt %d", order_caps[2]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 3,13: MemBlt %d %d", order_caps[3], order_caps[13]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 4,14: Mem3Blt %d %d", order_caps[4], order_caps[14]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 5-6: unused index");
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 7: DrawNineGrid %d", order_caps[7]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 8: LineTo %d", order_caps[8]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 9: MultiDrawNineGrid %d", order_caps[9]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 10: unused index");
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 11: SaveBitmap %d", order_caps[11]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 12-14: unused index");
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 15: MultiDstBlt %d", order_caps[15]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 16: MultiPatBlt %d", order_caps[16]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 17: MultiScrBlt %d", order_caps[17]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 18: MultiOpaqueRect %d", order_caps[18]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 19: FastIndex %d", order_caps[19]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 20: PolygonSC %d", order_caps[20]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 21: PolygonCB %d", order_caps[21]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 22: Polyline %d", order_caps[22]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 23: unused index");
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 24: FastGlyph %d", order_caps[24]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 25: EllipseSC %d", order_caps[25]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 26: EllipseCB %d", order_caps[26]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 27: GlyphIndex %d", order_caps[27]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 28-31: unused index");
LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: order_caps", order_caps, 32);
in_uint8s(s, 2); /* Text capability flags */
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: textFlags (ignored as per protocol spec)"); /* read extended order support flags */
in_uint16_le(s, ex_flags); /* Ex flags */
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupportExFlags 0x%4.4x", ex_flags);
in_uint32_le(s, i); /* desktop cache size, usually 0x38400 */
self->client_info.desktop_cache = i;
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: desktopSaveSize %d", i);
in_uint8s(s, 4); /* Pad */
in_uint8s(s, 4); /* Pad */
/* check if libpainter should be used for drawing, instead of orders */ if (!(order_caps[TS_NEG_DSTBLT_INDEX] && order_caps[TS_NEG_PATBLT_INDEX] &&
order_caps[TS_NEG_SCRBLT_INDEX] && order_caps[TS_NEG_MEMBLT_INDEX]))
{
LOG_DEVEL(LOG_LEVEL_INFO, "Client Capability: not enough orders supported by client, using painter.");
self->client_info.no_orders_supported = 1;
}
return0;
}
/*****************************************************************************/ /* get the bitmap cache size */ staticint
xrdp_caps_process_bmpcache(struct xrdp_rdp *self, struct stream *s, int len)
{ int i;
/*****************************************************************************/ /* get the bitmap cache size */ staticint
xrdp_caps_process_bmpcache2(struct xrdp_rdp *self, struct stream *s, int len)
{ int Bpp = 0; int i = 0;
/*****************************************************************************/ /* get the number of client cursor cache */ staticint
xrdp_caps_process_pointer(struct xrdp_rdp *self, struct stream *s, int len)
{ int i; int colorPointerFlag; int no_new_cursor;
if (len < 2 + 2 + 2)
{
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_pointer: error"); return1;
}
no_new_cursor = self->client_info.pointer_flags & 2;
in_uint16_le(s, colorPointerFlag);
self->client_info.pointer_flags = colorPointerFlag;
in_uint16_le(s, i);
i = MIN(i, 32);
self->client_info.pointer_cache_entries = i; if (colorPointerFlag & 1)
{
LOG(LOG_LEVEL_INFO, "xrdp_caps_process_pointer: client supports " "new(color) cursor");
in_uint16_le(s, i);
i = MIN(i, 32);
self->client_info.pointer_cache_entries = i;
} else
{
LOG(LOG_LEVEL_INFO, "xrdp_caps_process_pointer: client does not support " "new(color) cursor");
} if (no_new_cursor)
{
LOG(LOG_LEVEL_INFO, "xrdp_caps_process_pointer: new(color) cursor is " "disabled by config");
self->client_info.pointer_flags = 0;
} return0;
}
/*****************************************************************************/ staticint
xrdp_caps_process_input(struct xrdp_rdp *self, struct stream *s, int len)
{ int inputFlags; int client_does_fastpath_input;
/*****************************************************************************/ /* get the type of client brush cache */ int
xrdp_caps_process_brushcache(struct xrdp_rdp *self, struct stream *s, int len)
{ int code;
if (glyph_support_level == GLYPH_SUPPORT_ENCODE)
{
self->client_info.use_cache_glyph_v2 = 1;
}
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_process_glyphcache: support level %d ",
glyph_support_level); return0;
}
/*****************************************************************************/ int
xrdp_caps_process_offscreen_bmpcache(struct xrdp_rdp *self, struct stream *s, int len)
{ int i32;
/*****************************************************************************/ int
xrdp_caps_process_rail(struct xrdp_rdp *self, struct stream *s, int len)
{ int i32;
/*****************************************************************************/ staticint
xrdp_caps_process_codecs(struct xrdp_rdp *self, struct stream *s, int len)
{ int codec_id; int codec_count; int index; int codec_properties_length; int i1; char *codec_guid; char *next_guid; struct guid guid; char codec_guid_str[GUID_STR_SIZE];
/*****************************************************************************/ staticint
xrdp_caps_process_frame_ack(struct xrdp_rdp *self, struct stream *s, int len)
{ int max_count;
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_process_frame_ack:"); if (len < 4)
{
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_frame_ack: missing data"); return1;
}
self->client_info.use_frame_acks = 1;
in_uint32_le(s, max_count); if (max_count < 0)
{
LOG(LOG_LEVEL_WARNING, " invalid max_unacknowledged_frame_count value (%d), setting to 0",
max_count);
max_count = 0;
}
LOG_DEVEL(LOG_LEVEL_TRACE, " max_unacknowledged_frame_count %d", max_count);
self->client_info.max_unacknowledged_frame_count = max_count; return0;
}
/*****************************************************************************/ staticint
xrdp_caps_process_surface_cmds(struct xrdp_rdp *self, struct stream *s, int len)
{ int cmdFlags; #ifndef USE_DEVEL_LOGGING /* TODO: remove UNUSED_VAR once the `cmdFlags` variable is used for more than
logging in debug mode */
UNUSED_VAR(cmdFlags); #endif // Check the data is there, whether or not we are logging it if (len < 8)
{
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_surface_cmds: missing data"); return1;
}
/*****************************************************************************/ /* *Processa[MS-RDPBCGR]TS_CONFIRM_ACTIVE_PDU(2.2.1.13.2.1)message.
*/ int
xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
{ int cap_len; int source_len; int num_caps; int index; int type; int len; char *p;
if (self->client_info.no_orders_supported &&
(self->client_info.offscreen_support_level != 0))
{
LOG(LOG_LEVEL_WARNING, "Client Capability: not enough orders " "supported by client, client wants off screen bitmap but " "offscreen bitmaps disabled");
self->client_info.offscreen_support_level = 0;
self->client_info.offscreen_cache_size = 0;
self->client_info.offscreen_cache_entries = 0;
}
if (self->client_info.use_fast_path)
{ if ((self->client_info.large_pointer_support_flags & LARGE_POINTER_FLAG_96x96) &&
(self->client_info.max_fastpath_frag_bytes < 38055))
{
LOG(LOG_LEVEL_WARNING, "Client Capability: client requested " "LARGE_POINTER_FLAG_96x96 but max_fastpath_frag_bytes(%d) is less then " "the required size of 38055, 96x96 large cursor support disabled",
self->client_info.max_fastpath_frag_bytes);
self->client_info.large_pointer_support_flags &= ~LARGE_POINTER_FLAG_96x96;
} if ((self->client_info.large_pointer_support_flags & LARGE_POINTER_FLAG_384x384) &&
(self->client_info.max_fastpath_frag_bytes < 608299))
{
LOG(LOG_LEVEL_WARNING, "Client Capability: client requested " "LARGE_POINTER_FLAG_384x384 but max_fastpath_frag_bytes(%d) is less then " "the required size of 608299, 384x384 large cursor support disabled",
self->client_info.max_fastpath_frag_bytes);
self->client_info.large_pointer_support_flags &= ~LARGE_POINTER_FLAG_384x384;
}
} else
{ if (self->client_info.large_pointer_support_flags != 0)
{
LOG(LOG_LEVEL_WARNING, "Client Capability: client requested " "large pointers but use_fast_path is false, " "all large cursor support disabled");
self->client_info.large_pointer_support_flags = 0;
}
} if (self->client_info.large_pointer_support_flags & LARGE_POINTER_FLAG_96x96)
{
LOG(LOG_LEVEL_INFO, "Client Capability: LARGE_POINTER_FLAG_96x96 supported");
} if (self->client_info.large_pointer_support_flags & LARGE_POINTER_FLAG_384x384)
{
LOG(LOG_LEVEL_INFO, "Client Capability: LARGE_POINTER_FLAG_384x384 supported");
}
LOG_DEVEL(LOG_LEVEL_TRACE, "Completed processing received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU"); return0;
}
/**************************************************************************//**
* Calculate the multifragmentupdate len we advertised to the client
* for fastpath updates
*
* See [MS-RDPBCGR] 2.2.7.2.6
*
* The basic logic is taken from freerdp 2.4. We try to use the highest
* useful request size that will allow us to pack a complete screen
* update into a single fast path PDU using any of the supported codecs.
* For RemoteFX, the client MUST use at least this value
*
* A backstop on the maximum advertised size is implemented to prevent
* extreme memory usage for large screen configurations. RDP supports a
* maximum desktop size of 32768x32768, which would cause overflow for
* 32-bit integers using a simple calculation.
*
* The codecs have to deal with the value returned by the client after
* we advertise our own value, and must not assume a complete update
* will fit in a single PDU
*/ static unsignedint calculate_multifragmentupdate_len(conststruct xrdp_rdp *self)
{ unsignedint result = MAX_MULTIFRAGMENTUPDATE_SIZE;
/* Check for overflow on calculation if bad parameters are supplied */ if ((x_tiles * y_tiles + 1) < (UINT_MAX / 16384))
{
result = x_tiles * y_tiles * 16384; /* and add room for headers, regions, frame markers, etc. */
result += 16384;
}
return result;
}
/*****************************************************************************/ int
xrdp_caps_send_demand_active(struct xrdp_rdp *self)
{ struct stream *s; int caps_count; int caps_size; int codec_caps_count; int codec_caps_size; int flags; char *caps_count_ptr; char *caps_size_ptr; char *caps_ptr; char *codec_caps_count_ptr; char *codec_caps_size_ptr;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.