summaryrefslogtreecommitdiffstats
path: root/libxrdp
diff options
context:
space:
mode:
Diffstat (limited to 'libxrdp')
-rw-r--r--libxrdp/Makefile.am5
-rw-r--r--libxrdp/libxrdp.c152
-rw-r--r--libxrdp/libxrdp.h14
-rw-r--r--libxrdp/libxrdpinc.h40
-rw-r--r--libxrdp/xrdp_channel.c16
-rw-r--r--libxrdp/xrdp_fastpath.c6
-rw-r--r--libxrdp/xrdp_jpeg_compress.c18
-rw-r--r--libxrdp/xrdp_mcs.c27
-rw-r--r--libxrdp/xrdp_orders.c266
-rw-r--r--libxrdp/xrdp_orders_rail.c625
-rw-r--r--libxrdp/xrdp_orders_rail.h50
-rw-r--r--libxrdp/xrdp_rdp.c323
-rw-r--r--libxrdp/xrdp_sec.c19
13 files changed, 1460 insertions, 101 deletions
diff --git a/libxrdp/Makefile.am b/libxrdp/Makefile.am
index 08fb7130..11d1d836 100644
--- a/libxrdp/Makefile.am
+++ b/libxrdp/Makefile.am
@@ -50,11 +50,12 @@ libxrdp_la_SOURCES = \
xrdp_sec.c \
xrdp_tcp.c \
xrdp_bitmap_compress.c \
- xrdp_jpeg_compress.c
+ xrdp_jpeg_compress.c \
+ xrdp_orders_rail.c
libxrdp_la_LDFLAGS = \
$(EXTRA_FLAGS)
libxrdp_la_LIBADD = \
- $(top_srcdir)/common/libcommon.la \
+ $(top_builddir)/common/libcommon.la \
$(EXTRA_LIBS)
diff --git a/libxrdp/libxrdp.c b/libxrdp/libxrdp.c
index 05e67eb7..3f8307c2 100644
--- a/libxrdp/libxrdp.c
+++ b/libxrdp/libxrdp.c
@@ -75,10 +75,12 @@ libxrdp_process_data(struct xrdp_session* session)
int rv;
int code;
int term;
+ int dead_lock_counter;
term = 0;
cont = 1;
rv = 0;
+ dead_lock_counter = 0;
while ((cont || !session->up_and_running) && !term)
{
if (session->is_term != 0)
@@ -89,7 +91,8 @@ libxrdp_process_data(struct xrdp_session* session)
}
}
code = 0;
- if (xrdp_rdp_recv((struct xrdp_rdp*)session->rdp, session->s, &code) != 0)
+ if (xrdp_rdp_recv((struct xrdp_rdp*)(session->rdp),
+ session->s, &code) != 0)
{
rv = 1;
break;
@@ -102,6 +105,7 @@ libxrdp_process_data(struct xrdp_session* session)
session->up_and_running = 0;
break;
case 0:
+ dead_lock_counter++;
break;
case RDP_PDU_CONFIRM_ACTIVE: /* 3 */
xrdp_rdp_process_confirm_active((struct xrdp_rdp*)session->rdp,
@@ -118,8 +122,17 @@ libxrdp_process_data(struct xrdp_session* session)
break;
default:
g_writeln("unknown in libxrdp_process_data");
+ dead_lock_counter++;
break;
}
+ if (dead_lock_counter > 100000)
+ {
+ /*This situation can happen and this is a workaround*/
+ cont = 0;
+ g_writeln("Serious programming error we were locked in a deadly loop") ;
+ g_writeln("remaining :%d",session->s->end-session->s->next_packet);
+ session->s->next_packet = 0;
+ }
if (cont)
{
cont = (session->s->next_packet != 0) &&
@@ -616,7 +629,10 @@ libxrdp_reset(struct xrdp_session* session,
}
/* process till up and running */
session->up_and_running = 0;
- libxrdp_process_data(session);
+ if (libxrdp_process_data(session) != 0)
+ {
+ g_writeln("non handled error from libxrdp_process_data");
+ }
return 0;
}
@@ -635,11 +651,22 @@ libxrdp_orders_send_raw_bitmap2(struct xrdp_session* session,
int EXPORT_CC
libxrdp_orders_send_bitmap2(struct xrdp_session* session,
int width, int height, int bpp, char* data,
- int cache_id, int cache_idx)
+ int cache_id, int cache_idx, int hints)
{
return xrdp_orders_send_bitmap2((struct xrdp_orders*)session->orders,
width, height, bpp, data,
- cache_id, cache_idx);
+ cache_id, cache_idx, hints);
+}
+
+/*****************************************************************************/
+int EXPORT_CC
+libxrdp_orders_send_bitmap3(struct xrdp_session* session,
+ int width, int height, int bpp, char* data,
+ int cache_id, int cache_idx, int hints)
+{
+ return xrdp_orders_send_bitmap3((struct xrdp_orders*)session->orders,
+ width, height, bpp, data,
+ cache_id, cache_idx, hints);
}
/*****************************************************************************/
@@ -658,6 +685,11 @@ libxrdp_query_channel(struct xrdp_session* session, int index,
rdp = (struct xrdp_rdp*)session->rdp;
mcs = rdp->sec_layer->mcs_layer;
+ if (mcs->channel_list == NULL)
+ {
+ g_writeln("libxrdp_query_channel - No channel initialized");
+ return 1 ;
+ }
count = mcs->channel_list->count;
if (index < 0 || index >= count)
{
@@ -668,6 +700,7 @@ libxrdp_query_channel(struct xrdp_session* session, int index,
if (channel_item == 0)
{
/* this should not happen */
+ g_writeln("libxrdp_query_channel - channel item is 0");
return 1;
}
if (channel_name != 0)
@@ -695,6 +728,11 @@ libxrdp_get_channel_id(struct xrdp_session* session, char* name)
rdp = (struct xrdp_rdp*)session->rdp;
mcs = rdp->sec_layer->mcs_layer;
+ if (mcs->channel_list == NULL)
+ {
+ g_writeln("libxrdp_get_channel_id No channel initialized");
+ return -1 ;
+ }
count = mcs->channel_list->count;
for (index = 0; index < count; index++)
{
@@ -737,6 +775,7 @@ libxrdp_send_to_channel(struct xrdp_session* session, int channel_id,
s_mark_end(s);
if (xrdp_channel_send(chan, s, channel_id, total_data_len, flags) != 0)
{
+ g_writeln("Debug - data NOT sent to channel");
free_stream(s);
return 1;
}
@@ -754,3 +793,108 @@ libxrdp_orders_send_brush(struct xrdp_session* session,
width, height, bpp, type, size, data,
cache_id);
}
+
+/*****************************************************************************/
+int EXPORT_CC
+libxrdp_orders_send_create_os_surface(struct xrdp_session* session, int id,
+ int width, int height,
+ struct list* del_list)
+{
+ return xrdp_orders_send_create_os_surface
+ ((struct xrdp_orders*)(session->orders), id,
+ width, height, del_list);
+}
+
+/*****************************************************************************/
+int EXPORT_CC
+libxrdp_orders_send_switch_os_surface(struct xrdp_session* session, int id)
+{
+ return xrdp_orders_send_switch_os_surface
+ ((struct xrdp_orders*)(session->orders), id);
+}
+
+/*****************************************************************************/
+int EXPORT_CC
+libxrdp_window_new_update(struct xrdp_session* session, int window_id,
+ struct rail_window_state_order* window_state,
+ int flags)
+{
+ struct xrdp_orders* orders;
+
+ orders = (struct xrdp_orders*)(session->orders);
+ return xrdp_orders_send_window_new_update(orders, window_id,
+ window_state, flags);
+}
+
+/*****************************************************************************/
+int EXPORT_CC
+libxrdp_window_delete(struct xrdp_session* session, int window_id)
+{
+ struct xrdp_orders* orders;
+
+ orders = (struct xrdp_orders*)(session->orders);
+ return xrdp_orders_send_window_delete(orders, window_id);
+}
+
+/*****************************************************************************/
+int EXPORT_CC
+libxrdp_window_icon(struct xrdp_session* session, int window_id,
+ int cache_entry, int cache_id,
+ struct rail_icon_info* icon_info, int flags)
+{
+ struct xrdp_orders* orders;
+
+ orders = (struct xrdp_orders*)(session->orders);
+ return xrdp_orders_send_window_icon(orders, window_id, cache_entry,
+ cache_id, icon_info, flags);
+}
+
+/*****************************************************************************/
+int EXPORT_CC
+libxrdp_window_cached_icon(struct xrdp_session* session, int window_id,
+ int cache_entry, int cache_id,
+ int flags)
+{
+ struct xrdp_orders* orders;
+
+ orders = (struct xrdp_orders*)(session->orders);
+ return xrdp_orders_send_window_cached_icon(orders, window_id, cache_entry,
+ cache_id, flags);
+}
+
+/*****************************************************************************/
+int EXPORT_CC
+libxrdp_notify_new_update(struct xrdp_session* session,
+ int window_id, int notify_id,
+ struct rail_notify_state_order* notify_state,
+ int flags)
+{
+ struct xrdp_orders* orders;
+
+ orders = (struct xrdp_orders*)(session->orders);
+ return xrdp_orders_send_notify_new_update(orders, window_id, notify_id,
+ notify_state, flags);
+}
+
+/*****************************************************************************/
+int DEFAULT_CC
+libxrdp_notify_delete(struct xrdp_session* session,
+ int window_id, int notify_id)
+{
+ struct xrdp_orders* orders;
+
+ orders = (struct xrdp_orders*)(session->orders);
+ return xrdp_orders_send_notify_delete(orders, window_id, notify_id);
+}
+
+/*****************************************************************************/
+int DEFAULT_CC
+libxrdp_monitored_desktop(struct xrdp_session* session,
+ struct rail_monitored_desktop_order* mdo,
+ int flags)
+{
+ struct xrdp_orders* orders;
+
+ orders = (struct xrdp_orders*)(session->orders);
+ return xrdp_orders_send_monitored_desktop(orders, mdo, flags);
+}
diff --git a/libxrdp/libxrdp.h b/libxrdp/libxrdp.h
index 35a38190..b066db95 100644
--- a/libxrdp/libxrdp.h
+++ b/libxrdp/libxrdp.h
@@ -119,6 +119,7 @@ struct xrdp_rdp
int mcs_channel;
struct xrdp_client_info client_info;
void* mppc_enc;
+ void* rfx_enc;
};
/* state */
@@ -325,6 +326,8 @@ xrdp_orders_send(struct xrdp_orders* self);
int APP_CC
xrdp_orders_force_send(struct xrdp_orders* self);
int APP_CC
+xrdp_orders_check(struct xrdp_orders* self, int max_size);
+int APP_CC
xrdp_orders_rect(struct xrdp_orders* self, int x, int y, int cx, int cy,
int color, struct xrdp_rect* rect);
int APP_CC
@@ -383,13 +386,18 @@ xrdp_orders_send_raw_bitmap2(struct xrdp_orders* self,
int APP_CC
xrdp_orders_send_bitmap2(struct xrdp_orders* self,
int width, int height, int bpp, char* data,
- int cache_id, int cache_idx);
+ int cache_id, int cache_idx, int hints);
+int APP_CC
+xrdp_orders_send_bitmap3(struct xrdp_orders* self,
+ int width, int height, int bpp, char* data,
+ int cache_id, int cache_idx, int hints);
int APP_CC
xrdp_orders_send_brush(struct xrdp_orders* self, int width, int height,
int bpp, int type, int size, char* data, int cache_id);
int APP_CC
xrdp_orders_send_create_os_surface(struct xrdp_orders* self, int id,
- int width, int height);
+ int width, int height,
+ struct list* del_list);
int APP_CC
xrdp_orders_send_switch_os_surface(struct xrdp_orders* self, int id);
@@ -403,7 +411,7 @@ int APP_CC
xrdp_jpeg_compress(char* in_data, int width, int height,
struct stream* s, int bpp, int byte_limit,
int start_line, struct stream* temp_s,
- int e);
+ int e, int quality);
/* xrdp_channel.c */
struct xrdp_channel* APP_CC
diff --git a/libxrdp/libxrdpinc.h b/libxrdp/libxrdpinc.h
index 82ac9ad0..4f3504e6 100644
--- a/libxrdp/libxrdpinc.h
+++ b/libxrdp/libxrdpinc.h
@@ -23,6 +23,8 @@
#ifndef LIBXRDPINC_H
#define LIBXRDPINC_H
+#include "xrdp_rail.h"
+
/* struct xrdp_client_info moved to xrdp_client_info.h */
struct xrdp_brush
@@ -162,7 +164,11 @@ libxrdp_orders_send_raw_bitmap2(struct xrdp_session* session,
int DEFAULT_CC
libxrdp_orders_send_bitmap2(struct xrdp_session* session,
int width, int height, int bpp, char* data,
- int cache_id, int cache_idx);
+ int cache_id, int cache_idx, int hints);
+int DEFAULT_CC
+libxrdp_orders_send_bitmap3(struct xrdp_session* session,
+ int width, int height, int bpp, char* data,
+ int cache_id, int cache_idx, int hints);
int DEFAULT_CC
libxrdp_query_channel(struct xrdp_session* session, int index,
char* channel_name, int* channel_flags);
@@ -176,5 +182,37 @@ int DEFAULT_CC
libxrdp_orders_send_brush(struct xrdp_session* session,
int width, int height, int bpp, int type,
int size, char* data, int cache_id);
+int DEFAULT_CC
+libxrdp_orders_send_create_os_surface(struct xrdp_session* session, int id,
+ int width, int height,
+ struct list* del_list);
+int DEFAULT_CC
+libxrdp_orders_send_switch_os_surface(struct xrdp_session* session, int id);
+int DEFAULT_CC
+libxrdp_window_new_update(struct xrdp_session* session, int window_id,
+ struct rail_window_state_order* window_state,
+ int flags);
+int DEFAULT_CC
+libxrdp_window_delete(struct xrdp_session* session, int window_id);
+int DEFAULT_CC
+libxrdp_window_icon(struct xrdp_session* session, int window_id,
+ int cache_entry, int cache_id,
+ struct rail_icon_info* icon_info, int flags);
+int DEFAULT_CC
+libxrdp_window_cached_icon(struct xrdp_session* session, int window_id,
+ int cache_entry, int cache_id,
+ int flags);
+int DEFAULT_CC
+libxrdp_notify_new_update(struct xrdp_session* session,
+ int window_id, int notify_id,
+ struct rail_notify_state_order* notify_state,
+ int flags);
+int DEFAULT_CC
+libxrdp_notify_delete(struct xrdp_session* session,
+ int window_id, int notify_id);
+int DEFAULT_CC
+libxrdp_monitored_desktop(struct xrdp_session* session,
+ struct rail_monitored_desktop_order* mdo,
+ int flags);
#endif
diff --git a/libxrdp/xrdp_channel.c b/libxrdp/xrdp_channel.c
index 00497c35..2b3d23a5 100644
--- a/libxrdp/xrdp_channel.c
+++ b/libxrdp/xrdp_channel.c
@@ -35,7 +35,11 @@ static struct mcs_channel_item* APP_CC
xrdp_channel_get_item(struct xrdp_channel* self, int channel_id)
{
struct mcs_channel_item* channel;
-
+ if(self->mcs_layer->channel_list==NULL)
+ {
+ g_writeln("xrdp_channel_get_item - No channel initialized");
+ return NULL ;
+ }
channel = (struct mcs_channel_item*)
list_get_item(self->mcs_layer->channel_list, channel_id);
return channel;
@@ -62,6 +66,7 @@ xrdp_channel_delete(struct xrdp_channel* self)
{
return;
}
+ g_memset(self,0,sizeof(struct xrdp_channel));
g_free(self);
}
@@ -88,19 +93,21 @@ xrdp_channel_send(struct xrdp_channel* self, struct stream* s, int channel_id,
struct mcs_channel_item* channel;
channel = xrdp_channel_get_item(self, channel_id);
- if (channel == 0)
+ if (channel == NULL)
{
+ g_writeln("xrdp_channel_send - no such channel");
return 1;
}
s_pop_layer(s, channel_hdr);
out_uint32_le(s, total_data_len);
- if (channel->flags & CHANNEL_OPTION_SHOW_PROTOCOL)
+ if (channel->flags & XR_CHANNEL_OPTION_SHOW_PROTOCOL)
{
flags |= CHANNEL_FLAG_SHOW_PROTOCOL;
}
out_uint32_le(s, flags);
if (xrdp_sec_send(self->sec_layer, s, channel->chanid) != 0)
{
+ g_writeln("xrdp_channel_send - failure sending data");
return 1;
}
return 0;
@@ -159,13 +166,14 @@ xrdp_channel_process(struct xrdp_channel* self, struct stream* s,
int channel_id;
struct mcs_channel_item* channel;
+
/* this assumes that the channels are in order of chanid(mcs channel id)
but they should be, see xrdp_sec_process_mcs_data_channels
the first channel should be MCS_GLOBAL_CHANNEL + 1, second
one should be MCS_GLOBAL_CHANNEL + 2, and so on */
channel_id = (chanid - MCS_GLOBAL_CHANNEL) - 1;
channel = xrdp_channel_get_item(self, channel_id);
- if (channel == 0)
+ if (channel == NULL)
{
g_writeln("xrdp_channel_process, channel not found");
return 1;
diff --git a/libxrdp/xrdp_fastpath.c b/libxrdp/xrdp_fastpath.c
index 5ce07861..9a147b1b 100644
--- a/libxrdp/xrdp_fastpath.c
+++ b/libxrdp/xrdp_fastpath.c
@@ -76,7 +76,7 @@ xrdp_fastpath_send_update_pdu(struct xrdp_fastpath* self, tui8 updateCode,
compression = 0;
s_send = self->out_s;
- maxLen = FASTPATH_MAX_PACKET_SIZE - 6 ; /* 6 bytes for header */
+ maxLen = FASTPATH_MAX_PACKET_SIZE - 6; /* 6 bytes for header */
payloadLeft = (s->end - s->data);
for (i = 0; payloadLeft > 0; i++)
{
@@ -143,7 +143,7 @@ xrdp_fastpath_process_update(struct xrdp_fastpath* self, tui8 updateCode,
}
return 0;
-}
+}
/*****************************************************************************/
int APP_CC
@@ -192,5 +192,5 @@ xrdp_fastpath_process_data(struct xrdp_fastpath* self, struct stream* s,
return 1;
}
in_uint16_le(s, size);
- return xrdp_fastpath_process_update(self, updateCode, size, s);
+ return xrdp_fastpath_process_update(self, updateCode, size, s);
}
diff --git a/libxrdp/xrdp_jpeg_compress.c b/libxrdp/xrdp_jpeg_compress.c
index 48f12359..8561982f 100644
--- a/libxrdp/xrdp_jpeg_compress.c
+++ b/libxrdp/xrdp_jpeg_compress.c
@@ -148,9 +148,8 @@ jp_do_compress(char* data, int width, int height, int bpp, int quality,
/*****************************************************************************/
static int APP_CC
jpeg_compress(char* in_data, int width, int height,
- struct stream* s, int bpp, int byte_limit,
- int start_line, struct stream* temp_s,
- int e)
+ struct stream* s, struct stream* temp_s, int bpp,
+ int byte_limit, int e, int quality)
{
char* data;
tui32* src32;
@@ -164,7 +163,7 @@ jpeg_compress(char* in_data, int width, int height,
int i;
int cdata_bytes;
- data = g_malloc((width + e) * height * 3, 0);
+ data = temp_s->data;
dst8 = data;
if (bpp == 24)
{
@@ -192,9 +191,8 @@ jpeg_compress(char* in_data, int width, int height,
g_writeln("bpp wrong %d", bpp);
}
cdata_bytes = byte_limit;
- jp_do_compress(data, width + e, height, 24, JP_QUALITY, s->p, &cdata_bytes);
+ jp_do_compress(data, width + e, height, 24, quality, s->p, &cdata_bytes);
s->p += cdata_bytes;
- g_free(data);
return cdata_bytes;
}
@@ -203,10 +201,10 @@ int APP_CC
xrdp_jpeg_compress(char* in_data, int width, int height,
struct stream* s, int bpp, int byte_limit,
int start_line, struct stream* temp_s,
- int e)
+ int e, int quality)
{
- jpeg_compress(in_data, width, height, s, bpp, byte_limit,
- start_line, temp_s, e);
+ jpeg_compress(in_data, width, height, s, temp_s, bpp, byte_limit,
+ e, quality);
return height;
}
@@ -217,7 +215,7 @@ int APP_CC
xrdp_jpeg_compress(char* in_data, int width, int height,
struct stream* s, int bpp, int byte_limit,
int start_line, struct stream* temp_s,
- int e)
+ int e, int quality)
{
return height;
}
diff --git a/libxrdp/xrdp_mcs.c b/libxrdp/xrdp_mcs.c
index af65faf2..618a3433 100644
--- a/libxrdp/xrdp_mcs.c
+++ b/libxrdp/xrdp_mcs.c
@@ -65,11 +65,15 @@ xrdp_mcs_delete(struct xrdp_mcs* self)
}
list_delete(self->channel_list);
xrdp_iso_delete(self->iso_layer);
+ /* make sure we get null pointer exception if struct is used again. */
+ DEBUG(("xrdp_mcs_delete processed"))
+ g_memset(self,0,sizeof(struct xrdp_mcs)) ;
g_free(self);
}
/*****************************************************************************/
-/* returns error */
+/* This function sends channel join confirm*/
+/* returns error = 1 ok = 0*/
static int APP_CC
xrdp_mcs_send_cjcf(struct xrdp_mcs* self, int userid, int chanid)
{
@@ -87,7 +91,7 @@ xrdp_mcs_send_cjcf(struct xrdp_mcs* self, int userid, int chanid)
out_uint8(s, (MCS_CJCF << 2) | 2);
out_uint8(s, 0);
out_uint16_be(s, userid);
- out_uint16_be(s, chanid);
+ out_uint16_be(s, chanid); /* TODO Explain why we send this two times */
out_uint16_be(s, chanid);
s_mark_end(s);
if (xrdp_iso_send(self->iso_layer, s) != 0)
@@ -122,20 +126,33 @@ xrdp_mcs_recv(struct xrdp_mcs* self, struct stream* s, int* chan)
}
in_uint8(s, opcode);
appid = opcode >> 2;
- if (appid == MCS_DPUM)
+ if (appid == MCS_DPUM) /* Disconnect Provider Ultimatum */
{
+ g_writeln("received Disconnect Provider Ultimatum");
DEBUG((" out xrdp_mcs_recv appid != MCS_DPUM"));
return 1;
}
/* this is channels getting added from the client */
if (appid == MCS_CJRQ)
{
+ g_writeln("channel join request received");
in_uint16_be(s, userid);
in_uint16_be(s, chanid);
- DEBUG((" adding channel %4.4x", chanid));
- xrdp_mcs_send_cjcf(self, userid, chanid);
+ DEBUG(("xrdp_mcs_recv adding channel %4.4x", chanid));
+ if(xrdp_mcs_send_cjcf(self, userid, chanid)!=0)
+ {
+ g_writeln("Non handled error from xrdp_mcs_send_cjcf") ;
+ }
continue;
}
+ if(appid==MCS_SDRQ || appid==MCS_SDIN)
+ {
+ break ;
+ }
+ else
+ {
+ g_writeln("Recieved an unhandled appid:%d",appid);
+ }
break;
}
if (appid != MCS_SDRQ)
diff --git a/libxrdp/xrdp_orders.c b/libxrdp/xrdp_orders.c
index 925c52aa..e7739e3e 100644
--- a/libxrdp/xrdp_orders.c
+++ b/libxrdp/xrdp_orders.c
@@ -22,6 +22,20 @@
#include "libxrdp.h"
+#if defined(XRDP_FREERDP1)
+#include <freerdp/codec/rfx.h>
+#endif
+
+#define LLOG_LEVEL 2
+#define LLOGLN(_log_level, _params) \
+{ \
+ if (_log_level < LLOG_LEVEL) \
+ { \
+ g_write("xrdp_orders.c [%10.10u]: ", g_time3()); \
+ g_writeln _params ; \
+ } \
+}
+
/*****************************************************************************/
struct xrdp_orders* APP_CC
xrdp_orders_create(struct xrdp_session* session, struct xrdp_rdp* rdp_layer)
@@ -152,7 +166,7 @@ xrdp_orders_force_send(struct xrdp_orders* self)
/* check if the current order will fit in packet size of 16384, if not */
/* send what we got and init a new one */
/* returns error */
-static int APP_CC
+int APP_CC
xrdp_orders_check(struct xrdp_orders* self, int max_size)
{
int size;
@@ -1829,32 +1843,12 @@ xrdp_orders_send_raw_bitmap2(struct xrdp_orders* self,
}
/*****************************************************************************/
-static int
-xrdp_orders_send_as_jpeg(struct xrdp_orders* self,
- int width, int height, int bpp)
-{
- if (bpp != 24)
- {
- return 0;
- }
- if (self->rdp_layer->client_info.jpeg == 0)
- {
- return 0;
- }
- if (width * height < 64)
- {
- return 0;
- }
- return 1;
-}
-
-/*****************************************************************************/
/* returns error */
/* max size width * height * Bpp + 14 */
int APP_CC
xrdp_orders_send_bitmap2(struct xrdp_orders* self,
int width, int height, int bpp, char* data,
- int cache_id, int cache_idx)
+ int cache_id, int cache_idx, int hints)
{
int order_flags = 0;
int len = 0;
@@ -1863,7 +1857,6 @@ xrdp_orders_send_bitmap2(struct xrdp_orders* self,
int i = 0;
int lines_sending = 0;
int e = 0;
- int is_jpeg;
struct stream* s = NULL;
struct stream* temp_s = NULL;
char* p = NULL;
@@ -1889,18 +1882,8 @@ xrdp_orders_send_bitmap2(struct xrdp_orders* self,
init_stream(temp_s, 16384);
p = s->p;
i = height;
- is_jpeg = 0;
- if (xrdp_orders_send_as_jpeg(self, width, height, bpp))
- {
- lines_sending = xrdp_jpeg_compress(data, width, height, s, bpp, 16384,
- i - 1, temp_s, e);
- is_jpeg = 1;
- }
- else
- {
- lines_sending = xrdp_bitmap_compress(data, width, height, s, bpp, 16384,
+ lines_sending = xrdp_bitmap_compress(data, width, height, s, bpp, 16384,
i - 1, temp_s, e);
- }
if (lines_sending != height)
{
free_stream(s);
@@ -1919,10 +1902,6 @@ height(%d)", lines_sending, height);
out_uint16_le(self->out_s, len);
i = (((Bpp + 2) << 3) & 0x38) | (cache_id & 7);
i = i | (0x08 << 7); /* CBR2_NO_BITMAP_COMPRESSION_HDR */
- if (is_jpeg)
- {
- i = i | (0x80 << 7); /* unsed flag, jpeg hack */
- }
out_uint16_le(self->out_s, i); /* flags */
out_uint8(self->out_s, RDP_ORDER_BMPCACHE2); /* type */
out_uint8(self->out_s, width + e);
@@ -1939,6 +1918,182 @@ height(%d)", lines_sending, height);
}
/*****************************************************************************/
+static int
+xrdp_orders_send_as_jpeg(struct xrdp_orders* self,
+ int width, int height, int bpp, int hints)
+{
+ if (hints & 1)
+ {
+ return 0;
+ }
+ if (bpp != 24)
+ {
+ return 0;
+ }
+ if (width * height < 64)
+ {
+ return 0;
+ }
+ return 1;
+}
+
+#if defined(XRDP_FREERDP1)
+/*****************************************************************************/
+/* secondary drawing order (bitmap v3) using remotefx compression */
+static int APP_CC
+xrdp_orders_send_as_rfx(struct xrdp_orders* self,
+ int width, int height, int bpp,
+ int hints)
+{
+ if (hints & 1)
+ {
+ return 0;
+ }
+ if (bpp != 24)
+ {
+ return 0;
+ }
+ if (width * height < 64)
+ {
+ return 0;
+ }
+ return 1;
+}
+#endif
+
+/*****************************************************************************/
+static int APP_CC
+xrdp_orders_out_v3(struct xrdp_orders* self, int cache_id, int cache_idx,
+ char* buf, int bufsize, int width, int height, int bpp,
+ int codec_id)
+{
+ int Bpp;
+ int order_flags;
+ int len;
+ int i;
+
+ Bpp = (bpp + 7) / 8;
+ xrdp_orders_check(self, bufsize + 30);
+ self->order_count++;
+ order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY;
+ out_uint8(self->out_s, order_flags);
+ len = (bufsize + 22) - 7; /* length after type minus 7 */
+ out_uint16_le(self->out_s, len);
+ i = (((Bpp + 2) << 3) & 0x38) | (cache_id & 7);
+ out_uint16_le(self->out_s, i); /* flags */
+ out_uint8(self->out_s, RDP_ORDER_BMPCACHE3); /* type */
+ /* cache index */
+ out_uint16_le(self->out_s, cache_idx);
+ /* persistant cache key 1/2 */
+ out_uint32_le(self->out_s, 0);
+ out_uint32_le(self->out_s, 0);
+ /* bitmap data */
+ out_uint8(self->out_s, bpp);
+ out_uint8(self->out_s, 0); /* reserved */
+ out_uint8(self->out_s, 0); /* reserved */
+ out_uint8(self->out_s, codec_id);
+ out_uint16_le(self->out_s, width);
+ out_uint16_le(self->out_s, height);
+ out_uint32_le(self->out_s, bufsize);
+ out_uint8a(self->out_s, buf, bufsize);
+ return 0;
+}
+
+/*****************************************************************************/
+/* secondary drawing order (bitmap v3) using remotefx compression */
+int APP_CC
+xrdp_orders_send_bitmap3(struct xrdp_orders* self,
+ int width, int height, int bpp, char* data,
+ int cache_id, int cache_idx, int hints)
+{
+ int e;
+ int bufsize;
+ int quality;
+ struct stream* xr_s; /* xrdp stream */
+ struct stream* temp_s; /* xrdp stream */
+ struct xrdp_client_info* ci;
+#if defined(XRDP_FREERDP1)
+ STREAM* fr_s; /* FreeRDP stream */
+ RFX_CONTEXT* context;
+ RFX_RECT rect;
+#endif
+
+ ci = &(self->rdp_layer->client_info);
+ if (ci->v3_codec_id == 0)
+ {
+ return 2;
+ }
+ if (ci->v3_codec_id == ci->rfx_codec_id)
+ {
+#if defined(XRDP_FREERDP1)
+ if (!xrdp_orders_send_as_rfx(self, width, height, bpp, hints))
+ {
+ return 2;
+ }
+ LLOGLN(10, ("xrdp_orders_send_bitmap3: rfx"));
+ context = (RFX_CONTEXT*)(self->rdp_layer->rfx_enc);
+ make_stream(xr_s);
+ init_stream(xr_s, 16384);
+ fr_s = stream_new(0);
+ stream_attach(fr_s, (tui8*)(xr_s->data), 16384);
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = width;
+ rect.height = height;
+ rfx_compose_message(context, fr_s, &rect, 1, (tui8*)data, width,
+ height, width * 4);
+ bufsize = stream_get_length(fr_s);
+ xrdp_orders_out_v3(self, cache_id, cache_idx, (char*)(fr_s->data), bufsize,
+ width, height, bpp,ci->v3_codec_id);
+ stream_detach(fr_s);
+ stream_free(fr_s);
+ free_stream(xr_s);
+ return 0;
+#else
+ return 2;
+#endif
+ }
+ else if (ci->v3_codec_id == ci->jpeg_codec_id)
+ {
+#if defined(XRDP_JPEG)
+ if (!xrdp_orders_send_as_jpeg(self, width, height, bpp, hints))
+ {
+ LLOGLN(10, ("xrdp_orders_send_bitmap3: jpeg skipped"));
+ return 2;
+ }
+ LLOGLN(10, ("xrdp_orders_send_bitmap3: jpeg"));
+ e = width % 4;
+ if (e != 0)
+ {
+ e = 4 - e;
+ }
+ make_stream(xr_s);
+ init_stream(xr_s, 16384);
+ make_stream(temp_s);
+ init_stream(temp_s, 16384);
+ quality = ci->jpeg_prop[0];
+ xrdp_jpeg_compress(data, width, height, xr_s, bpp, 16384,
+ height - 1, temp_s, e, quality);
+ s_mark_end(xr_s);
+ bufsize = (int)(xr_s->end - xr_s->data);
+ xrdp_orders_out_v3(self, cache_id, cache_idx, (char*)(xr_s->data), bufsize,
+ width + e, height, bpp,ci->v3_codec_id);
+ free_stream(xr_s);
+ free_stream(temp_s);
+ return 0;
+#else
+ return 2;
+#endif
+ }
+ else
+ {
+ g_writeln("xrdp_orders_send_bitmap3: todo unknown codec");
+ return 1;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
/* returns error */
/* send a brush cache entry */
int APP_CC
@@ -1971,21 +2126,47 @@ xrdp_orders_send_brush(struct xrdp_orders* self, int width, int height,
/* send an off screen bitmap entry */
int APP_CC
xrdp_orders_send_create_os_surface(struct xrdp_orders* self, int id,
- int width, int height)
+ int width, int height,
+ struct list* del_list)
{
int order_flags;
int cache_id;
+ int flags;
+ int index;
+ int bytes;
+ int num_del_list;
- g_writeln("xrdp_orders_send_create_os_surface:");
- xrdp_orders_check(self, 7);
+ bytes = 7;
+ num_del_list = del_list->count;
+ if (num_del_list > 0)
+ {
+ bytes += 2;
+ bytes += num_del_list * 2;
+ }
+ xrdp_orders_check(self, bytes);
self->order_count++;
order_flags = RDP_ORDER_SECONDARY;
order_flags |= 1 << 2; /* type RDP_ORDER_ALTSEC_CREATE_OFFSCR_BITMAP */
out_uint8(self->out_s, order_flags);
cache_id = id & 0x7fff;
- out_uint16_le(self->out_s, cache_id);
+ flags = cache_id;
+ if (num_del_list > 0)
+ {
+ flags |= 0x8000;
+ }
+ out_uint16_le(self->out_s, flags);
out_uint16_le(self->out_s, width);
out_uint16_le(self->out_s, height);
+ if (num_del_list > 0)
+ {
+ /* delete list */
+ out_uint16_le(self->out_s, num_del_list);
+ for (index = 0; index < num_del_list; index++)
+ {
+ cache_id = list_get_item(del_list, index) & 0x7fff;
+ out_uint16_le(self->out_s, cache_id);
+ }
+ }
return 0;
}
@@ -1997,7 +2178,6 @@ xrdp_orders_send_switch_os_surface(struct xrdp_orders* self, int id)
int order_flags;
int cache_id;
- g_writeln("xrdp_orders_send_switch_os_surface:");
xrdp_orders_check(self, 3);
self->order_count++;
order_flags = RDP_ORDER_SECONDARY;
diff --git a/libxrdp/xrdp_orders_rail.c b/libxrdp/xrdp_orders_rail.c
new file mode 100644
index 00000000..62f9b8ea
--- /dev/null
+++ b/libxrdp/xrdp_orders_rail.c
@@ -0,0 +1,625 @@
+/**
+ * xrdp: A Remote Desktop Protocol server.
+ *
+ * Copyright (C) Jay Sorg 2012
+ *
+ * Licensed 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 "libxrdp.h"
+#include "xrdp_rail.h"
+
+/* [MS-RDPERP]: Remote Desktop Protocol:
+ Remote Programs Virtual Channel Extension
+ http://msdn.microsoft.com/en-us/library/cc242568(v=prot.10) */
+
+/*****************************************************************************/
+/* RAIL */
+/* returns error */
+int APP_CC
+xrdp_orders_send_window_delete(struct xrdp_orders* self, int window_id)
+{
+ int order_size;
+ int order_flags;
+ int field_present_flags;
+
+ order_size = 11;
+ xrdp_orders_check(self, order_size);
+ self->order_count++;
+ order_flags = RDP_ORDER_SECONDARY;
+ order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
+ out_uint8(self->out_s, order_flags);
+ /* orderSize (2 bytes) */
+ out_uint16_le(self->out_s, order_size);
+ /* FieldsPresentFlags (4 bytes) */
+ field_present_flags = WINDOW_ORDER_TYPE_WINDOW | WINDOW_ORDER_STATE_DELETED;
+ out_uint32_le(self->out_s, field_present_flags);
+ /* windowId (4 bytes) */
+ out_uint32_le(self->out_s, window_id);
+ return 0;
+}
+
+/*****************************************************************************/
+/* RAIL */
+/* returns error */
+/* flags can contain WINDOW_ORDER_STATE_NEW and/or
+ WINDOW_ORDER_FIELD_ICON_BIG */
+int APP_CC
+xrdp_orders_send_window_cached_icon(struct xrdp_orders* self,
+ int window_id, int cache_entry,
+ int cache_id, int flags)
+{
+ int order_size;
+ int order_flags;
+ int field_present_flags;
+
+ order_size = 14;
+ xrdp_orders_check(self, order_size);
+ self->order_count++;
+ order_flags = RDP_ORDER_SECONDARY;
+ order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
+ out_uint8(self->out_s, order_flags);
+ /* orderSize (2 bytes) */
+ out_uint16_le(self->out_s, order_size);
+ /* FieldsPresentFlags (4 bytes) */
+ field_present_flags = flags | WINDOW_ORDER_TYPE_WINDOW |
+ WINDOW_ORDER_CACHED_ICON;
+ out_uint32_le(self->out_s, field_present_flags);
+ /* windowId (4 bytes) */
+ out_uint32_le(self->out_s, window_id);
+ /* CacheEntry (2 bytes) */
+ out_uint16_le(self->out_s, cache_entry);
+ /* CacheId (1 byte) */
+ out_uint8(self->out_s, cache_id);
+ return 0;
+}
+
+/*****************************************************************************/
+/* RAIL */
+/* returns error */
+static int APP_CC
+xrdp_orders_send_ts_icon(struct stream* s, int cache_entry, int cache_id,
+ struct rail_icon_info* icon_info)
+{
+ int use_cmap;
+
+ use_cmap = 0;
+ if ((icon_info->bpp == 1) || (icon_info->bpp == 2) || (icon_info->bpp == 4))
+ {
+ use_cmap = 1;
+ }
+
+ /* TS_ICON_INFO */
+ out_uint16_le(s, cache_entry);
+ out_uint8(s, cache_id);
+ out_uint8(s, icon_info->bpp);
+ out_uint16_le(s, icon_info->width);
+ out_uint16_le(s, icon_info->height);
+ if (use_cmap)
+ {
+ out_uint16_le(s, icon_info->cmap_bytes);
+ }
+ out_uint16_le(s, icon_info->mask_bytes);
+ out_uint16_le(s, icon_info->data_bytes);
+ out_uint8p(s, icon_info->mask, icon_info->mask_bytes);
+ if (use_cmap)
+ {
+ out_uint8p(s, icon_info->cmap, icon_info->cmap_bytes);
+ }
+ out_uint8p(s, icon_info->data, icon_info->data_bytes);
+ return 0;
+}
+
+/*****************************************************************************/
+/* RAIL */
+/* returns error */
+/* flags can contain WINDOW_ORDER_STATE_NEW and/or
+ WINDOW_ORDER_FIELD_ICON_BIG */
+int APP_CC
+xrdp_orders_send_window_icon(struct xrdp_orders* self,
+ int window_id, int cache_entry, int cache_id,
+ struct rail_icon_info* icon_info,
+ int flags)
+{
+ int order_size;
+ int order_flags;
+ int field_present_flags;
+ int use_cmap;
+
+ use_cmap = 0;
+ if ((icon_info->bpp == 1) || (icon_info->bpp == 2) || (icon_info->bpp == 4))
+ {
+ use_cmap = 1;
+ }
+ order_size = 23 + icon_info->mask_bytes + icon_info->data_bytes;
+ if (use_cmap)
+ {
+ order_size += icon_info->cmap_bytes + 2;
+ }
+ xrdp_orders_check(self, order_size);
+ self->order_count++;
+ order_flags = RDP_ORDER_SECONDARY;
+ order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
+ out_uint8(self->out_s, order_flags);
+ /* orderSize (2 bytes) */
+ out_uint16_le(self->out_s, order_size);
+ /* FieldsPresentFlags (4 bytes) */
+ field_present_flags = flags | WINDOW_ORDER_TYPE_WINDOW |
+ WINDOW_ORDER_ICON;
+ out_uint32_le(self->out_s, field_present_flags);
+ /* windowId (4 bytes) */
+ out_uint32_le(self->out_s, window_id);
+
+ xrdp_orders_send_ts_icon(self->out_s, cache_entry, cache_id, icon_info);
+
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+static int APP_CC
+xrdp_orders_send_as_unicode(struct stream* s, const char* text)
+{
+ int str_chars;
+ int index;
+ int i32;
+ twchar wdst[256];
+
+ str_chars = g_mbstowcs(wdst, text, 255);
+ if (str_chars > 0)
+ {
+ i32 = str_chars * 2;
+ out_uint16_le(s, i32);
+ for (index = 0; index < str_chars; index++)
+ {
+ i32 = wdst[index];
+ out_uint16_le(s, i32);
+ }
+ }
+ else
+ {
+ out_uint16_le(s, 0);
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* RAIL */
+/* returns error */
+/* flags can contain WINDOW_ORDER_STATE_NEW */
+int APP_CC
+xrdp_orders_send_window_new_update(struct xrdp_orders* self, int window_id,
+ struct rail_window_state_order* window_state,
+ int flags)
+{
+ int order_size;
+ int order_flags;
+ int field_present_flags;
+ int num_chars;
+ int index;
+
+ order_size = 11;
+ field_present_flags = flags | WINDOW_ORDER_TYPE_WINDOW;
+ if (field_present_flags & WINDOW_ORDER_FIELD_OWNER)
+ {
+ /* ownerWindowId (4 bytes) */
+ order_size += 4;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_STYLE)
+ {
+ /* style (4 bytes) */
+ order_size += 4;
+ /* extendedStyle (4 bytes) */
+ order_size += 4;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_SHOW)
+ {
+ /* showState (1 byte) */
+ order_size += 1;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_TITLE)
+ {
+ /* titleInfo */
+ num_chars = g_mbstowcs(0, window_state->title_info, 0);
+ order_size += 2 * num_chars + 2;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET)
+ {
+ /* clientOffsetX (4 bytes) */
+ order_size += 4;
+ /* clientOffsetY (4 bytes) */
+ order_size += 4;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE)
+ {
+ /* clientAreaWidth (4 bytes) */
+ order_size += 4;
+ /* clientAreaHeight (4 bytes) */
+ order_size += 4;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_RP_CONTENT)
+ {
+ /* RPContent (1 byte) */
+ order_size += 1;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_ROOT_PARENT)
+ {
+ /* rootParentHandle (4 bytes) */
+ order_size += 4;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_WND_OFFSET)
+ {
+ /* windowOffsetX (4 bytes) */
+ order_size += 4;
+ /* windowOffsetY (4 bytes) */
+ order_size += 4;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA)
+ {
+ /* windowClientDeltaX (4 bytes) */
+ order_size += 4;
+ /* windowClientDeltaY (4 bytes) */
+ order_size += 4;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_WND_SIZE)
+ {
+ /* windowWidth (4 bytes) */
+ order_size += 4;
+ /* windowHeight (4 bytes) */
+ order_size += 4;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_WND_RECTS)
+ {
+ /* numWindowRects (2 bytes) */
+ order_size += 2;
+ order_size += 8 * window_state->num_window_rects;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_VIS_OFFSET)
+ {
+ /* visibleOffsetX (4 bytes) */
+ order_size += 4;
+ /* visibleOffsetY (4 bytes) */
+ order_size += 4;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_VISIBILITY)
+ {
+ /* numVisibilityRects (2 bytes) */
+ order_size += 2;
+ order_size += 8 * window_state->num_visibility_rects;
+ }
+
+ xrdp_orders_check(self, order_size);
+ self->order_count++;
+ order_flags = RDP_ORDER_SECONDARY;
+ order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
+ out_uint8(self->out_s, order_flags);
+ /* orderSize (2 bytes) */
+ out_uint16_le(self->out_s, order_size);
+ /* FieldsPresentFlags (4 bytes) */
+ out_uint32_le(self->out_s, field_present_flags);
+ /* windowId (4 bytes) */
+ out_uint32_le(self->out_s, window_id);
+
+ if (field_present_flags & WINDOW_ORDER_FIELD_OWNER)
+ {
+ /* ownerWindowId (4 bytes) */
+ out_uint32_le(self->out_s, window_state->owner_window_id);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_STYLE)
+ {
+ /* style (4 bytes) */
+ out_uint32_le(self->out_s, window_state->style);
+ /* extendedStyle (4 bytes) */
+ out_uint32_le(self->out_s, window_state->extended_style);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_SHOW)
+ {
+ /* showState (1 byte) */
+ out_uint8(self->out_s, window_state->show_state);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_TITLE)
+ {
+ /* titleInfo */
+ xrdp_orders_send_as_unicode(self->out_s, window_state->title_info);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET)
+ {
+ /* clientOffsetX (4 bytes) */
+ out_uint32_le(self->out_s, window_state->client_offset_x);
+ /* clientOffsetY (4 bytes) */
+ out_uint32_le(self->out_s, window_state->client_offset_y);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE)
+ {
+ /* clientAreaWidth (4 bytes) */
+ out_uint32_le(self->out_s, window_state->client_area_width);
+ /* clientAreaHeight (4 bytes) */
+ out_uint32_le(self->out_s, window_state->client_area_height);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_RP_CONTENT)
+ {
+ /* RPContent (1 byte) */
+ out_uint8(self->out_s, window_state->rp_content);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_ROOT_PARENT)
+ {
+ /* rootParentHandle (4 bytes) */
+ out_uint32_le(self->out_s, window_state->root_parent_handle);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_WND_OFFSET)
+ {
+ /* windowOffsetX (4 bytes) */
+ out_uint32_le(self->out_s, window_state->window_offset_x);
+ /* windowOffsetY (4 bytes) */
+ out_uint32_le(self->out_s, window_state->window_offset_y);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA)
+ {
+ /* windowClientDeltaX (4 bytes) */
+ out_uint32_le(self->out_s, window_state->window_client_delta_x);
+ /* windowClientDeltaY (4 bytes) */
+ out_uint32_le(self->out_s, window_state->window_client_delta_y);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_WND_SIZE)
+ {
+ /* windowWidth (4 bytes) */
+ out_uint32_le(self->out_s, window_state->window_width);
+ /* windowHeight (4 bytes) */
+ out_uint32_le(self->out_s, window_state->window_height);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_WND_RECTS)
+ {
+ /* numWindowRects (2 bytes) */
+ out_uint16_le(self->out_s, window_state->num_window_rects);
+ for (index = 0; index < window_state->num_window_rects; index++)
+ {
+ out_uint16_le(self->out_s, window_state->window_rects[index].left);
+ out_uint16_le(self->out_s, window_state->window_rects[index].top);
+ out_uint16_le(self->out_s, window_state->window_rects[index].right);
+ out_uint16_le(self->out_s, window_state->window_rects[index].bottom);
+ }
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_VIS_OFFSET)
+ {
+ /* visibleOffsetX (4 bytes) */
+ out_uint32_le(self->out_s, window_state->visible_offset_x);
+ /* visibleOffsetY (4 bytes) */
+ out_uint32_le(self->out_s, window_state->visible_offset_y);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_VISIBILITY)
+ {
+ /* numVisibilityRects (2 bytes) */
+ out_uint16_le(self->out_s, window_state->num_visibility_rects);
+ for (index = 0; index < window_state->num_visibility_rects; index++)
+ {
+ out_uint16_le(self->out_s, window_state->visibility_rects[index].left);
+ out_uint16_le(self->out_s, window_state->visibility_rects[index].top);
+ out_uint16_le(self->out_s, window_state->visibility_rects[index].right);
+ out_uint16_le(self->out_s, window_state->visibility_rects[index].bottom);
+ }
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+/* RAIL */
+/* returns error */
+int APP_CC
+xrdp_orders_send_notify_delete(struct xrdp_orders* self, int window_id,
+ int notify_id)
+{
+ int order_size;
+ int order_flags;
+ int field_present_flags;
+
+ order_size = 15;
+ xrdp_orders_check(self, order_size);
+ self->order_count++;
+ order_flags = RDP_ORDER_SECONDARY;
+ order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
+ out_uint8(self->out_s, order_flags);
+ /* orderSize (2 bytes) */
+ out_uint16_le(self->out_s, order_size);
+ /* FieldsPresentFlags (4 bytes) */
+ field_present_flags = WINDOW_ORDER_TYPE_NOTIFY | WINDOW_ORDER_STATE_DELETED;
+ out_uint32_le(self->out_s, field_present_flags);
+ /* windowId (4 bytes) */
+ out_uint32_le(self->out_s, window_id);
+ /* notifyIconId (4 bytes) */
+ out_uint32_le(self->out_s, notify_id);
+ return 0;
+}
+
+/*****************************************************************************/
+/* RAIL */
+/* returns error */
+/* flags can contain WINDOW_ORDER_STATE_NEW */
+int APP_CC
+xrdp_orders_send_notify_new_update(struct xrdp_orders* self,
+ int window_id, int notify_id,
+ struct rail_notify_state_order* notify_state,
+ int flags)
+{
+ int order_size;
+ int order_flags;
+ int field_present_flags;
+ int num_chars;
+ int use_cmap;
+
+ order_size = 15;
+ field_present_flags = flags | WINDOW_ORDER_TYPE_NOTIFY;
+ if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_VERSION)
+ {
+ /* Version (4 bytes) */
+ order_size += 4;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_TIP)
+ {
+ /* ToolTip (variable) UNICODE_STRING */
+ num_chars = g_mbstowcs(0, notify_state->tool_tip, 0);
+ order_size += 2 * num_chars + 2;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP)
+ {
+ /* InfoTip (variable) TS_NOTIFY_ICON_INFOTIP */
+ /* UNICODE_STRING */
+ num_chars = g_mbstowcs(0, notify_state->infotip.title, 0);
+ order_size += 2 * num_chars + 2;
+ /* UNICODE_STRING */
+ num_chars = g_mbstowcs(0, notify_state->infotip.text, 0);
+ order_size += 2 * num_chars + 2;
+ /* Timeout (4 bytes) */
+ /* InfoFlags (4 bytes) */
+ order_size += 8;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_STATE)
+ {
+ /* State (4 bytes) */
+ order_size += 4;
+ }
+ if (field_present_flags & WINDOW_ORDER_ICON)
+ {
+ /* Icon (variable) */
+ use_cmap = 0;
+ if ((notify_state->icon_info.bpp == 1) || (notify_state->icon_info.bpp == 2) ||
+ (notify_state->icon_info.bpp == 4))
+ {
+ use_cmap = 1;
+ }
+ order_size += 12 + notify_state->icon_info.mask_bytes +
+ notify_state->icon_info.data_bytes;
+ if (use_cmap)
+ {
+ order_size += notify_state->icon_info.cmap_bytes + 2;
+ }
+ }
+ if (field_present_flags & WINDOW_ORDER_CACHED_ICON)
+ {
+ /* CachedIcon (3 bytes) */
+ order_size += 3;
+ }
+
+ xrdp_orders_check(self, order_size);
+ self->order_count++;
+ order_flags = RDP_ORDER_SECONDARY;
+ order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
+ out_uint8(self->out_s, order_flags);
+ /* orderSize (2 bytes) */
+ out_uint16_le(self->out_s, order_size);
+ /* FieldsPresentFlags (4 bytes) */
+ out_uint32_le(self->out_s, field_present_flags);
+ /* windowId (4 bytes) */
+ out_uint32_le(self->out_s, window_id);
+ /* notifyIconId (4 bytes) */
+ out_uint32_le(self->out_s, notify_id);
+
+ if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_VERSION)
+ {
+ /* Version (4 bytes) */
+ out_uint32_le(self->out_s, notify_state->version);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_TIP)
+ {
+ /* ToolTip (variable) UNICODE_STRING */
+ xrdp_orders_send_as_unicode(self->out_s, notify_state->tool_tip);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP)
+ {
+ /* InfoTip (variable) TS_NOTIFY_ICON_INFOTIP */
+ out_uint32_le(self->out_s, notify_state->infotip.timeout);
+ out_uint32_le(self->out_s, notify_state->infotip.flags);
+ xrdp_orders_send_as_unicode(self->out_s, notify_state->infotip.text);
+ xrdp_orders_send_as_unicode(self->out_s, notify_state->infotip.title);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_STATE)
+ {
+ /* State (4 bytes) */
+ out_uint32_le(self->out_s, notify_state->state);
+ }
+ if (field_present_flags & WINDOW_ORDER_ICON)
+ {
+ /* Icon (variable) */
+ xrdp_orders_send_ts_icon(self->out_s, notify_state->icon_cache_entry,
+ notify_state->icon_cache_id,
+ &notify_state->icon_info);
+ }
+ if (field_present_flags & WINDOW_ORDER_CACHED_ICON)
+ {
+ /* CacheEntry (2 bytes) */
+ out_uint16_le(self->out_s, notify_state->icon_cache_entry);
+ /* CacheId (1 byte) */
+ out_uint8(self->out_s, notify_state->icon_cache_id);
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+/* RAIL */
+/* returns error */
+/* used for both Non-Monitored Desktop and Actively Monitored Desktop */
+int APP_CC
+xrdp_orders_send_monitored_desktop(struct xrdp_orders* self,
+ struct rail_monitored_desktop_order* mdo,
+ int flags)
+{
+ int order_size;
+ int order_flags;
+ int field_present_flags;
+ int index;
+
+ order_size = 7;
+ field_present_flags = flags | WINDOW_ORDER_TYPE_DESKTOP;
+
+ if (field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND)
+ {
+ /* ActiveWindowId (4 bytes) */
+ order_size += 4;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER)
+ {
+ /* NumWindowIds (1 byte) */
+ order_size += 1;
+ /* WindowIds (variable) */
+ order_size += mdo->num_window_ids * 4;
+ }
+
+ xrdp_orders_check(self, order_size);
+ self->order_count++;
+ order_flags = RDP_ORDER_SECONDARY;
+ order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
+ out_uint8(self->out_s, order_flags);
+ /* orderSize (2 bytes) */
+ out_uint16_le(self->out_s, order_size);
+ /* FieldsPresentFlags (4 bytes) */
+ out_uint32_le(self->out_s, field_present_flags);
+
+ if (field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND)
+ {
+ /* ActiveWindowId (4 bytes) */
+ out_uint32_le(self->out_s, mdo->active_window_id);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER)
+ {
+ /* NumWindowIds (1 byte) */
+ out_uint8(self->out_s, mdo->num_window_ids);
+ /* WindowIds (variable) */
+ for (index = 0; index < mdo->num_window_ids; index++)
+ {
+ out_uint32_le(self->out_s, mdo->window_ids[index]);
+ }
+ }
+
+ return 0;
+}
diff --git a/libxrdp/xrdp_orders_rail.h b/libxrdp/xrdp_orders_rail.h
new file mode 100644
index 00000000..8f5b402f
--- /dev/null
+++ b/libxrdp/xrdp_orders_rail.h
@@ -0,0 +1,50 @@
+/**
+ * xrdp: A Remote Desktop Protocol server.
+ *
+ * Copyright (C) Jay Sorg 2012
+ *
+ * Licensed 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.
+ */
+
+#if !defined(_XRDP_ORDERS_RAIL_H)
+#define _XRDP_ORDERS_RAIL_H
+
+int APP_CC
+xrdp_orders_send_window_delete(struct xrdp_orders* self, int window_id);
+int APP_CC
+xrdp_orders_send_window_cached_icon(struct xrdp_orders* self,
+ int window_id, int cache_entry,
+ int cache_id, int flags);
+int APP_CC
+xrdp_orders_send_window_icon(struct xrdp_orders* self,
+ int window_id, int cache_entry, int cache_id,
+ struct rail_icon_info* icon_info,
+ int flags);
+int APP_CC
+xrdp_orders_send_window_new_update(struct xrdp_orders* self, int window_id,
+ struct rail_window_state_order* window_state,
+ int flags);
+int APP_CC
+xrdp_orders_send_notify_delete(struct xrdp_orders* self, int window_id,
+ int notify_id);
+int APP_CC
+xrdp_orders_send_notify_new_update(struct xrdp_orders* self,
+ int window_id, int notify_id,
+ struct rail_notify_state_order* notify_state,
+ int flags);
+int APP_CC
+xrdp_orders_send_monitored_desktop(struct xrdp_orders* self,
+ struct rail_monitored_desktop_order* mdo,
+ int flags);
+
+#endif
diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c
index bdbeed48..53e3ddc2 100644
--- a/libxrdp/xrdp_rdp.c
+++ b/libxrdp/xrdp_rdp.c
@@ -24,6 +24,7 @@
#if defined(XRDP_FREERDP1)
#include <freerdp/codec/mppc_enc.h>
+#include <freerdp/codec/rfx.h>
#endif
/* some compilers need unsigned char to avoid warnings */
@@ -113,13 +114,25 @@ xrdp_rdp_read_config(struct xrdp_client_info* client_info)
{
client_info->crypt_level = 3;
}
+ else
+ {
+ g_writeln("Warning: Your configured crypt level is"
+ "undefined 'high' will be used");
+ client_info->crypt_level = 3;
+ }
}
else if (g_strcasecmp(item, "channel_code") == 0)
{
- if (g_strcasecmp(value, "1") == 0)
+ if ((g_strcasecmp(value, "yes") == 0) ||
+ (g_strcasecmp(value, "1") == 0) ||
+ (g_strcasecmp(value, "true") == 0))
{
client_info->channel_code = 1;
}
+ else
+ {
+ g_writeln("Info: All channels are disabled");
+ }
}
else if (g_strcasecmp(item, "max_bpp") == 0)
{
@@ -131,11 +144,66 @@ xrdp_rdp_read_config(struct xrdp_client_info* client_info)
return 0;
}
+#if defined(XRDP_FREERDP1)
+/*****************************************************************************/
+static void
+cpuid(tui32 info, tui32* eax, tui32* ebx, tui32* ecx, tui32* edx)
+{
+#ifdef __GNUC__
+#if defined(__i386__) || defined(__x86_64__)
+ __asm volatile
+ (
+ /* The EBX (or RBX register on x86_64) is used for the PIC base address
+ and must not be corrupted by our inline assembly. */
+#if defined(__i386__)
+ "mov %%ebx, %%esi;"
+ "cpuid;"
+ "xchg %%ebx, %%esi;"
+#else
+ "mov %%rbx, %%rsi;"
+ "cpuid;"
+ "xchg %%rbx, %%rsi;"
+#endif
+ : "=a" (*eax), "=S" (*ebx), "=c" (*ecx), "=d" (*edx)
+ : "0" (info)
+ );
+#endif
+#endif
+}
+
+/*****************************************************************************/
+static tui32
+xrdp_rdp_detect_cpu(void)
+{
+ tui32 eax;
+ tui32 ebx;
+ tui32 ecx;
+ tui32 edx;
+ tui32 cpu_opt;
+
+ eax = 0;
+ ebx = 0;
+ ecx = 0;
+ edx = 0;
+ cpu_opt = 0;
+ cpuid(1, &eax, &ebx, &ecx, &edx);
+
+ if (edx & (1 << 26))
+ {
+ DEBUG("SSE2 detected");
+ cpu_opt |= CPU_SSE2;
+ }
+
+ return cpu_opt;
+}
+#endif
+
/*****************************************************************************/
struct xrdp_rdp* APP_CC
xrdp_rdp_create(struct xrdp_session* session, struct trans* trans)
{
struct xrdp_rdp* self = (struct xrdp_rdp *)NULL;
+ int bytes;
DEBUG(("in xrdp_rdp_create"));
self = (struct xrdp_rdp*)g_malloc(sizeof(struct xrdp_rdp), 1);
@@ -153,9 +221,13 @@ xrdp_rdp_create(struct xrdp_session* session, struct trans* trans)
self->client_info.cache2_size = 1024;
self->client_info.cache3_entries = 262;
self->client_info.cache3_size = 4096;
- g_write_ip_address(trans->sck, self->client_info.client_ip); /* load client ip info */
+ /* load client ip info */
+ bytes = sizeof(self->client_info.client_ip) - 1;
+ g_write_ip_address(trans->sck, self->client_info.client_ip, bytes);
#if defined(XRDP_FREERDP1)
self->mppc_enc = mppc_enc_new(PROTO_RDP_50);
+ self->rfx_enc = rfx_context_new();
+ rfx_context_set_cpu_opt(self->rfx_enc, xrdp_rdp_detect_cpu());
#endif
self->client_info.size = sizeof(self->client_info);
DEBUG(("out xrdp_rdp_create"));
@@ -173,6 +245,7 @@ xrdp_rdp_delete(struct xrdp_rdp* self)
xrdp_sec_delete(self->sec_layer);
#if defined(XRDP_FREERDP1)
mppc_enc_free((struct rdp_mppc_enc*)(self->mppc_enc));
+ rfx_context_free((RFX_CONTEXT*)(self->rfx_enc));
#endif
g_free(self);
}
@@ -220,7 +293,7 @@ xrdp_rdp_recv(struct xrdp_rdp* self, struct stream* s, int* code)
{
s->next_packet = 0;
*code = -1;
- DEBUG(("out xrdp_rdp_recv"));
+ DEBUG(("out (1) xrdp_rdp_recv"));
return 0;
}
if (error != 0)
@@ -232,35 +305,47 @@ xrdp_rdp_recv(struct xrdp_rdp* self, struct stream* s, int* code)
{
if (chan > MCS_GLOBAL_CHANNEL)
{
- xrdp_channel_process(self->sec_layer->chan_layer, s, chan);
+ if(xrdp_channel_process(self->sec_layer->chan_layer, s, chan)!=0)
+ {
+ g_writeln("xrdp_channel_process returned unhandled error") ;
+ }
+ }
+ else
+ {
+ g_writeln("Wrong channel Id to be handled by xrdp_channel_process %d",chan);
}
s->next_packet = 0;
*code = 0;
- DEBUG(("out xrdp_rdp_recv"));
+ DEBUG(("out (2) xrdp_rdp_recv"));
return 0;
}
s->next_packet = s->p;
}
else
{
+ DEBUG(("xrdp_rdp_recv stream not touched"))
s->p = s->next_packet;
}
if (!s_check_rem(s, 6))
{
s->next_packet = 0;
*code = 0;
- DEBUG(("out xrdp_rdp_recv"));
+ DEBUG(("out (3) xrdp_rdp_recv"));
len = (int)(s->end - s->p);
g_writeln("xrdp_rdp_recv: bad RDP packet, length [%d]", len);
return 0;
}
- in_uint16_le(s, len);
- in_uint16_le(s, pdu_code);
- *code = pdu_code & 0xf;
- in_uint8s(s, 2); /* mcs user id */
- s->next_packet += len;
- DEBUG(("out xrdp_rdp_recv"));
- return 0;
+ else
+ {
+ in_uint16_le(s, len);
+ /*g_writeln("New len received : %d next packet: %d s_end: %d",len,s->next_packet,s->end); */
+ in_uint16_le(s, pdu_code);
+ *code = pdu_code & 0xf;
+ in_uint8s(s, 2); /* mcs user id */
+ s->next_packet += len;
+ DEBUG(("out (4) xrdp_rdp_recv"));
+ return 0;
+ }
}
/*****************************************************************************/
@@ -318,7 +403,7 @@ xrdp_rdp_send_data(struct xrdp_rdp* self, struct stream* s,
if (self->client_info.rdp_compression && self->session->up_and_running)
{
mppc_enc = (struct rdp_mppc_enc*)(self->mppc_enc);
- if (compress_rdp(mppc_enc, s->p + 18, tocomplen))
+ if (compress_rdp(mppc_enc, (tui8*)(s->p + 18), tocomplen))
{
DEBUG(("mppc_encode ok flags 0x%x bytes_in_opb %d historyOffset %d "
"tocomplen %d", mppc_enc->flags, mppc_enc->bytes_in_opb,
@@ -474,9 +559,13 @@ xrdp_rdp_send_demand_active(struct xrdp_rdp* self)
struct stream* s;
int caps_count;
int caps_size;
+ int codec_caps_count;
+ int codec_caps_size;
char* caps_count_ptr;
char* caps_size_ptr;
char* caps_ptr;
+ char* codec_caps_count_ptr;
+ char* codec_caps_size_ptr;
make_stream(s);
init_stream(s, 8192);
@@ -589,12 +678,48 @@ xrdp_rdp_send_demand_active(struct xrdp_rdp* self)
out_uint8(s, 0); /* unused */
out_uint8(s, 0); /* unused */
out_uint16_le(s, 0x6a1);
- out_uint8s(s, 2); /* ? */
+ /* declare support of bitmap cache rev3 */
+ out_uint16_le(s, XR_ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT);
out_uint32_le(s, 0x0f4240); /* desk save */
out_uint32_le(s, 0x0f4240); /* desk save */
out_uint32_le(s, 1); /* ? */
out_uint32_le(s, 0); /* ? */
+ /* Output bmpcodecs capability set */
+ caps_count++;
+ out_uint16_le(s, RDP_CAPSET_BMPCODECS);
+ codec_caps_size_ptr = s->p;
+ out_uint8s(s, 2); /* cap len set later */
+ codec_caps_count = 0;
+ codec_caps_count_ptr = s->p;
+ out_uint8s(s, 1); /* bitmapCodecCount set later */
+ /* nscodec */
+ codec_caps_count++;
+ out_uint8a(s, XR_CODEC_GUID_NSCODEC, 16);
+ out_uint8(s, 1); /* codec id, must be 1 */
+ out_uint16_le(s, 3);
+ out_uint8(s, 0x01); /* fAllowDynamicFidelity */
+ out_uint8(s, 0x01); /* fAllowSubsampling */
+ out_uint8(s, 0x03); /* colorLossLevel */
+ /* remotefx */
+ codec_caps_count++;
+ out_uint8a(s, XR_CODEC_GUID_REMOTEFX, 16);
+ out_uint8(s, 0); /* codec id, client sets */
+ out_uint16_le(s, 256);
+ out_uint8s(s, 256);
+ /* jpeg */
+ codec_caps_count++;
+ out_uint8a(s, XR_CODEC_GUID_JPEG, 16);
+ out_uint8(s, 0); /* codec id, client sets */
+ out_uint16_le(s, 1); /* ext length */
+ out_uint8(s, 75);
+ /* calculate and set size and count */
+ codec_caps_size = (int)(s->p - codec_caps_size_ptr);
+ codec_caps_size += 2; /* 2 bytes for RDP_CAPSET_BMPCODECS above */
+ codec_caps_size_ptr[0] = codec_caps_size;
+ codec_caps_size_ptr[1] = codec_caps_size >> 8;
+ codec_caps_count_ptr[0] = codec_caps_count;
+
/* Output color cache capability set */
caps_count++;
out_uint16_le(s, RDP_CAPSET_COLCACHE);
@@ -617,6 +742,27 @@ xrdp_rdp_send_demand_active(struct xrdp_rdp* self)
out_uint8(s, 1);
out_uint8s(s, 83);
+ /* Remote Programs Capability Set */
+ caps_count++;
+ out_uint16_le(s, 0x0017); /* CAPSETTYPE_RAIL */
+ out_uint16_le(s, 8);
+ out_uint32_le(s, 3); /* TS_RAIL_LEVEL_SUPPORTED
+ TS_RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED */
+
+ /* Window List Capability Set */
+ caps_count++;
+ out_uint16_le(s, 0x0018); /* CAPSETTYPE_WINDOW */
+ out_uint16_le(s, 11);
+ out_uint32_le(s, 2); /* TS_WINDOW_LEVEL_SUPPORTED_EX */
+ out_uint8(s, 3); /* NumIconCaches */
+ out_uint16_le(s, 12); /* NumIconCacheEntries */
+
+ /* 6 - bitmap cache v3 codecid */
+ caps_count++;
+ out_uint16_le(s, 0x0006);
+ out_uint16_le(s, 5);
+ out_uint8(s, 0); /* client sets */
+
out_uint8s(s, 4); /* pad */
s_mark_end(s);
@@ -664,6 +810,7 @@ xrdp_process_capset_order(struct xrdp_rdp* self, struct stream* s,
{
int i;
char order_caps[32];
+ int ex_flags;
DEBUG(("order capabilities"));
in_uint8s(s, 20); /* Terminal desc, pad */
@@ -694,7 +841,15 @@ xrdp_process_capset_order(struct xrdp_rdp* self, struct stream* s,
g_hexdump(order_caps, 32);
#endif
in_uint8s(s, 2); /* Text capability flags */
- in_uint8s(s, 6); /* Pad */
+ /* read extended order support flags */
+ in_uint16_le(s, ex_flags); /* Ex flags */
+ if (ex_flags & XR_ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT)
+ {
+ g_writeln("xrdp_process_capset_order: bitmap cache v3 supported");
+ self->client_info.bitmap_cache_version |= 4;
+ }
+ in_uint8s(s, 4); /* Pad */
+
in_uint32_le(s, i); /* desktop cache size, usually 0x38400 */
self->client_info.desktop_cache = i;
DEBUG(("desktop cache size %d", i));
@@ -709,6 +864,7 @@ static int APP_CC
xrdp_process_capset_bmpcache(struct xrdp_rdp* self, struct stream* s,
int len)
{
+ self->client_info.bitmap_cache_version |= 1;
in_uint8s(s, 24);
in_uint16_le(s, self->client_info.cache1_entries);
in_uint16_le(s, self->client_info.cache1_size);
@@ -734,16 +890,9 @@ xrdp_process_capset_bmpcache2(struct xrdp_rdp* self, struct stream* s,
int Bpp = 0;
int i = 0;
- self->client_info.bitmap_cache_version = 2;
+ self->client_info.bitmap_cache_version |= 2;
Bpp = (self->client_info.bpp + 7) / 8;
in_uint16_le(s, i); /* cache flags */
-#if defined(XRDP_JPEG)
- if (i & 0x80)
- {
- g_writeln("xrdp_process_capset_bmpcache2: client supports jpeg");
- self->client_info.jpeg = 1;
- }
-#endif
self->client_info.bitmap_cache_persist_enable = i;
in_uint8s(s, 2); /* number of caches in set, 3 */
in_uint32_le(s, i);
@@ -769,6 +918,20 @@ xrdp_process_capset_bmpcache2(struct xrdp_rdp* self, struct stream* s,
}
/*****************************************************************************/
+static int
+xrdp_process_capset_cache_v3_codec_id(struct xrdp_rdp* self, struct stream* s,
+ int len)
+{
+ int codec_id;
+
+ in_uint8(s, codec_id);
+ g_writeln("xrdp_process_capset_cache_v3_codec_id: cache_v3_codec_id %d",
+ codec_id);
+ self->client_info.v3_codec_id = codec_id;
+ return 0;
+}
+
+/*****************************************************************************/
/* get the number of client cursor cache */
static int APP_CC
xrdp_process_capset_pointercache(struct xrdp_rdp* self, struct stream* s,
@@ -823,6 +986,106 @@ xrdp_process_offscreen_bmpcache(struct xrdp_rdp* self, struct stream* s,
}
/*****************************************************************************/
+static int APP_CC
+xrdp_process_capset_rail(struct xrdp_rdp* self, struct stream* s, int len)
+{
+ int i32;
+
+ if (len - 4 < 4)
+ {
+ g_writeln("xrdp_process_capset_rail: bad len");
+ return 1;
+ }
+ in_uint32_le(s, i32);
+ self->client_info.rail_support_level = i32;
+ g_writeln("xrdp_process_capset_rail: rail_support_level %d",
+ self->client_info.rail_support_level);
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+xrdp_process_capset_window(struct xrdp_rdp* self, struct stream* s, int len)
+{
+ int i32;
+
+ if (len - 4 < 7)
+ {
+ g_writeln("xrdp_process_capset_window: bad len");
+ return 1;
+ }
+ in_uint32_le(s, i32);
+ self->client_info.wnd_support_level = i32;
+ in_uint8(s, i32);
+ self->client_info.wnd_num_icon_caches = i32;
+ in_uint16_le(s, i32);
+ self->client_info.wnd_num_icon_cache_entries = i32;
+ g_writeln("xrdp_process_capset_window wnd_support_level %d "
+ "wnd_num_icon_caches %d wnd_num_icon_cache_entries %d",
+ self->client_info.wnd_support_level,
+ self->client_info.wnd_num_icon_caches,
+ self->client_info.wnd_num_icon_cache_entries);
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+xrdp_process_capset_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;
+
+ in_uint8(s, codec_count);
+ for (index = 0; index < codec_count; index++)
+ {
+ codec_guid = s->p;
+ in_uint8s(s, 16);
+ in_uint8(s, codec_id);
+ in_uint16_le(s, codec_properties_length);
+ next_guid = s->p + codec_properties_length;
+ if (g_memcmp(codec_guid, XR_CODEC_GUID_NSCODEC, 16) == 0)
+ {
+ g_writeln("xrdp_process_capset_codecs: nscodec codec id %d prop len %d",
+ codec_id, codec_properties_length);
+ self->client_info.ns_codec_id = codec_id;
+ i1 = MIN(64, codec_properties_length);
+ g_memcpy(self->client_info.ns_prop, s->p, i1);
+ self->client_info.ns_prop_len = i1;
+ }
+ else if (g_memcmp(codec_guid, XR_CODEC_GUID_REMOTEFX, 16) == 0)
+ {
+ g_writeln("xrdp_process_capset_codecs: rfx codec id %d prop len %d",
+ codec_id, codec_properties_length);
+ self->client_info.rfx_codec_id = codec_id;
+ i1 = MIN(64, codec_properties_length);
+ g_memcpy(self->client_info.rfx_prop, s->p, i1);
+ self->client_info.rfx_prop_len = i1;
+ }
+ else if (g_memcmp(codec_guid, XR_CODEC_GUID_JPEG, 16) == 0)
+ {
+ g_writeln("xrdp_process_capset_codecs: jpeg codec id %d prop len %d",
+ codec_id, codec_properties_length);
+ self->client_info.jpeg_codec_id = codec_id;
+ i1 = MIN(64, codec_properties_length);
+ g_memcpy(self->client_info.jpeg_prop, s->p, i1);
+ self->client_info.jpeg_prop_len = i1;
+ g_writeln(" jpeg quality %d", self->client_info.jpeg_prop[0]);
+ }
+ else
+ {
+ g_writeln("xrdp_process_capset_codecs: unknown codec id %d", codec_id);
+ }
+ s->p = next_guid;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
int APP_CC
xrdp_rdp_process_confirm_active(struct xrdp_rdp* self, struct stream* s)
{
@@ -867,6 +1130,9 @@ xrdp_rdp_process_confirm_active(struct xrdp_rdp* self, struct stream* s)
case RDP_CAPSET_CONTROL: /* 5 */
DEBUG(("RDP_CAPSET_CONTROL"));
break;
+ case 6:
+ xrdp_process_capset_cache_v3_codec_id(self, s, len);
+ break;
case RDP_CAPSET_ACTIVATE: /* 7 */
DEBUG(("RDP_CAPSET_ACTIVATE"));
break;
@@ -912,9 +1178,18 @@ xrdp_rdp_process_confirm_active(struct xrdp_rdp* self, struct stream* s)
case 22: /* 22 */
DEBUG(("--22"));
break;
+ case 0x0017: /* 23 CAPSETTYPE_RAIL */
+ xrdp_process_capset_rail(self, s, len);
+ break;
+ case 0x0018: /* 24 CAPSETTYPE_WINDOW */
+ xrdp_process_capset_window(self, s, len);
+ break;
case 26: /* 26 */
DEBUG(("--26"));
break;
+ case RDP_CAPSET_BMPCODECS: /* 0x1d(29) */
+ xrdp_process_capset_codecs(self, s, len);
+ break;
default:
g_writeln("unknown in xrdp_rdp_process_confirm_active %d", type);
break;
diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c
index 952ff12f..381e8435 100644
--- a/libxrdp/xrdp_sec.c
+++ b/libxrdp/xrdp_sec.c
@@ -148,9 +148,20 @@ xrdp_sec_create(struct xrdp_rdp* owner, struct trans* trans, int crypt_level,
self->rc4_key_size = 2;
self->crypt_level = 3;
break;
+ default:
+ g_writeln("Fatal : Illegal crypt_level");
+ break ;
}
self->channel_code = channel_code;
+ if(self->decrypt_rc4_info!=NULL)
+ {
+ g_writeln("xrdp_sec_create - decrypt_rc4_info already created !!!");
+ }
self->decrypt_rc4_info = ssl_rc4_info_create();
+ if(self->encrypt_rc4_info!=NULL)
+ {
+ g_writeln("xrdp_sec_create - encrypt_rc4_info already created !!!");
+ }
self->encrypt_rc4_info = ssl_rc4_info_create();
self->mcs_layer = xrdp_mcs_create(self, trans, &self->client_mcs_data,
&self->server_mcs_data);
@@ -165,14 +176,17 @@ xrdp_sec_delete(struct xrdp_sec* self)
{
if (self == 0)
{
+ g_writeln("xrdp_sec_delete: indata is null");
return;
}
xrdp_channel_delete(self->chan_layer);
xrdp_mcs_delete(self->mcs_layer);
- ssl_rc4_info_delete(self->decrypt_rc4_info);
- ssl_rc4_info_delete(self->encrypt_rc4_info);
+ ssl_rc4_info_delete(self->decrypt_rc4_info); /* TODO clear all data */
+ ssl_rc4_info_delete(self->encrypt_rc4_info); /* TODO clear all data */
g_free(self->client_mcs_data.data);
g_free(self->server_mcs_data.data);
+ /* Crypto information must always be cleared */
+ g_memset(self,0,sizeof(struct xrdp_sec));
g_free(self);
}
@@ -722,6 +736,7 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec* self, struct stream* s)
/* this is an option set in xrdp.ini */
if (self->channel_code != 1) /* are channels on? */
{
+ g_writeln("Processing channel data from client - The channel is off");
return 0;
}
in_uint32_le(s, num_channels);