summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/rail.h147
-rw-r--r--libxrdp/Makefile.am3
-rw-r--r--libxrdp/libxrdp.h2
-rw-r--r--libxrdp/xrdp_orders.c2
-rw-r--r--libxrdp/xrdp_orders_rail.c625
-rw-r--r--libxrdp/xrdp_orders_rail.h50
6 files changed, 827 insertions, 2 deletions
diff --git a/common/rail.h b/common/rail.h
new file mode 100644
index 00000000..deed3a9e
--- /dev/null
+++ b/common/rail.h
@@ -0,0 +1,147 @@
+/**
+ * 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(_RAIL_H)
+#define _RAIL_H
+
+/*
+ ORDER_TYPE_WINDOW
+ WINDOW_ORDER_TYPE_WINDOW
+ WINDOW_ORDER_ICON
+ WINDOW_ORDER_CACHED_ICON
+ WINDOW_ORDER_STATE_DELETED
+ WINDOW_ORDER_STATE_NEW on
+ WINDOW_ORDER_STATE_NEW off
+ WINDOW_ORDER_TYPE_NOTIFY
+ WINDOW_ORDER_STATE_DELETED
+ WINDOW_ORDER_STATE_NEW on
+ WINDOW_ORDER_STATE_NEW off
+ WINDOW_ORDER_TYPE_DESKTOP
+ WINDOW_ORDER_FIELD_DESKTOP_NONE on
+ WINDOW_ORDER_FIELD_DESKTOP_NONE off
+*/
+
+/* Window Order Header Flags */
+#define WINDOW_ORDER_TYPE_WINDOW 0x01000000
+#define WINDOW_ORDER_TYPE_NOTIFY 0x02000000
+#define WINDOW_ORDER_TYPE_DESKTOP 0x04000000
+#define WINDOW_ORDER_STATE_NEW 0x10000000
+#define WINDOW_ORDER_STATE_DELETED 0x20000000
+#define WINDOW_ORDER_FIELD_OWNER 0x00000002
+#define WINDOW_ORDER_FIELD_STYLE 0x00000008
+#define WINDOW_ORDER_FIELD_SHOW 0x00000010
+#define WINDOW_ORDER_FIELD_TITLE 0x00000004
+#define WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET 0x00004000
+#define WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE 0x00010000
+#define WINDOW_ORDER_FIELD_RP_CONTENT 0x00020000
+#define WINDOW_ORDER_FIELD_ROOT_PARENT 0x00040000
+#define WINDOW_ORDER_FIELD_WND_OFFSET 0x00000800
+#define WINDOW_ORDER_FIELD_WND_CLIENT_DELTA 0x00008000
+#define WINDOW_ORDER_FIELD_WND_SIZE 0x00000400
+#define WINDOW_ORDER_FIELD_WND_RECTS 0x00000100
+#define WINDOW_ORDER_FIELD_VIS_OFFSET 0x00001000
+#define WINDOW_ORDER_FIELD_VISIBILITY 0x00000200
+#define WINDOW_ORDER_FIELD_ICON_BIG 0x00002000
+#define WINDOW_ORDER_ICON 0x40000000
+#define WINDOW_ORDER_CACHED_ICON 0x80000000
+#define WINDOW_ORDER_FIELD_NOTIFY_VERSION 0x00000008
+#define WINDOW_ORDER_FIELD_NOTIFY_TIP 0x00000001
+#define WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP 0x00000002
+#define WINDOW_ORDER_FIELD_NOTIFY_STATE 0x00000004
+#define WINDOW_ORDER_FIELD_DESKTOP_NONE 0x00000001
+#define WINDOW_ORDER_FIELD_DESKTOP_HOOKED 0x00000002
+#define WINDOW_ORDER_FIELD_DESKTOP_ARC_COMPLETED 0x00000004
+#define WINDOW_ORDER_FIELD_DESKTOP_ARC_BEGAN 0x00000008
+#define WINDOW_ORDER_FIELD_DESKTOP_ZORDER 0x00000010
+#define WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND 0x00000020
+
+struct rail_icon_info
+{
+ int bpp;
+ int width;
+ int height;
+ int cmap_bytes;
+ int mask_bytes;
+ int data_bytes;
+ char* mask;
+ char* cmap;
+ char* data;
+};
+
+struct rail_window_rect
+{
+ short left;
+ short top;
+ short right;
+ short bottom;
+};
+
+struct rail_notify_icon_infotip
+{
+ int timeout;
+ int flags;
+ char* text;
+ char* title;
+};
+
+struct rail_window_state_order
+{
+ int owner_window_id;
+ int style;
+ int extended_style;
+ int show_state;
+ char* title_info;
+ int client_offset_x;
+ int client_offset_y;
+ int client_area_width;
+ int client_area_height;
+ int rp_content;
+ int root_parent_handle;
+ int window_offset_x;
+ int window_offset_y;
+ int window_client_delta_x;
+ int window_client_delta_y;
+ int window_width;
+ int window_height;
+ int num_window_rects;
+ struct rail_window_rect* window_rects;
+ int visible_offset_x;
+ int visible_offset_y;
+ int num_visibility_rects;
+ struct rail_window_rect* visibility_rects;
+};
+
+struct rail_notify_state_order
+{
+ int version;
+ char* tool_tip;
+ struct rail_notify_icon_infotip infotip;
+ int state;
+ int icon_cache_entry;
+ int icon_cache_id;
+ struct rail_icon_info icon_info;
+};
+
+struct rail_monitored_desktop_order
+{
+ int active_window_id;
+ int num_window_ids;
+ int* window_ids;
+};
+
+#endif
diff --git a/libxrdp/Makefile.am b/libxrdp/Makefile.am
index 08fb7130..ad891bd8 100644
--- a/libxrdp/Makefile.am
+++ b/libxrdp/Makefile.am
@@ -50,7 +50,8 @@ 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)
diff --git a/libxrdp/libxrdp.h b/libxrdp/libxrdp.h
index 7aae38b5..7792d157 100644
--- a/libxrdp/libxrdp.h
+++ b/libxrdp/libxrdp.h
@@ -325,6 +325,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
diff --git a/libxrdp/xrdp_orders.c b/libxrdp/xrdp_orders.c
index cff1324a..d068c39a 100644
--- a/libxrdp/xrdp_orders.c
+++ b/libxrdp/xrdp_orders.c
@@ -152,7 +152,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;
diff --git a/libxrdp/xrdp_orders_rail.c b/libxrdp/xrdp_orders_rail.c
new file mode 100644
index 00000000..087cf42e
--- /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 "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