From b52bf1b838c35c61479ff4d8ba139c29daaeb6cd Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Thu, 14 Jun 2012 14:37:02 -0700 Subject: [PATCH] libxrdp: started adding RAIL support --- common/rail.h | 147 +++++++++ libxrdp/Makefile.am | 3 +- libxrdp/libxrdp.h | 2 + libxrdp/xrdp_orders.c | 2 +- libxrdp/xrdp_orders_rail.c | 625 +++++++++++++++++++++++++++++++++++++ libxrdp/xrdp_orders_rail.h | 50 +++ 6 files changed, 827 insertions(+), 2 deletions(-) create mode 100644 common/rail.h create mode 100644 libxrdp/xrdp_orders_rail.c create mode 100644 libxrdp/xrdp_orders_rail.h 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, + ¬ify_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