summaryrefslogtreecommitdiffstats
path: root/libxrdp
diff options
context:
space:
mode:
authorjsorg71 <jsorg71>2005-06-28 03:11:35 +0000
committerjsorg71 <jsorg71>2005-06-28 03:11:35 +0000
commit992dbfa7b3fa568ee480aa3fe3242084d33c518f (patch)
treec46af888c75e214fa2c1f18606c4d21ef83526e5 /libxrdp
parent41df89c7f2da57650948967a78afa352a3dfc4b6 (diff)
downloadxrdp-proprietary-992dbfa7b3fa568ee480aa3fe3242084d33c518f.tar.gz
xrdp-proprietary-992dbfa7b3fa568ee480aa3fe3242084d33c518f.zip
moved a bunch of files around
Diffstat (limited to 'libxrdp')
-rw-r--r--libxrdp/Makefile25
-rw-r--r--libxrdp/libxrdp.c530
-rw-r--r--libxrdp/libxrdp.h342
-rw-r--r--libxrdp/libxrdpinc.h170
-rwxr-xr-xlibxrdp/makefile_win3242
-rw-r--r--libxrdp/xrdp_bitmap_compress.c1002
-rw-r--r--libxrdp/xrdp_iso.c195
-rw-r--r--libxrdp/xrdp_mcs.c629
-rw-r--r--libxrdp/xrdp_orders.c1553
-rw-r--r--libxrdp/xrdp_rdp.c847
-rw-r--r--libxrdp/xrdp_sec.c606
-rw-r--r--libxrdp/xrdp_tcp.c146
12 files changed, 6087 insertions, 0 deletions
diff --git a/libxrdp/Makefile b/libxrdp/Makefile
new file mode 100644
index 00000000..e19b0c80
--- /dev/null
+++ b/libxrdp/Makefile
@@ -0,0 +1,25 @@
+
+LIBXRDPOBJ = libxrdp.o xrdp_tcp.o xrdp_iso.o xrdp_mcs.o \
+ xrdp_sec.o xrdp_rdp.o xrdp_orders.o \
+ xrdp_bitmap_compress.o \
+ ../common/os_calls.o \
+ ../common/ssl_calls.o
+
+CFLAGS = -Wall -O2 -I../common -fPIC
+LDFLAGS = -shared
+LIBS = -ldl -lcrypto
+CC = gcc
+
+all: libxrdp
+
+static: $(LIBXRDPOBJ)
+ $(AR) rvu libxrdp.a $(LIBXRDPOBJ)
+ ranlib libxrdp.a
+
+libxrdp: $(LIBXRDPOBJ)
+ $(CC) $(LDFLAGS) -o libxrdp.so $(LIBXRDPOBJ) $(LIBS)
+ strip libxrdp.so
+
+clean:
+ rm -f $(LIBXRDPOBJ) libxrdp.a libxrdp.so
+
diff --git a/libxrdp/libxrdp.c b/libxrdp/libxrdp.c
new file mode 100644
index 00000000..263a99ae
--- /dev/null
+++ b/libxrdp/libxrdp.c
@@ -0,0 +1,530 @@
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ xrdp: A Remote Desktop Protocol server.
+ Copyright (C) Jay Sorg 2004-2005
+
+ this is the interface to libxrdp
+
+*/
+
+#include "libxrdp.h"
+
+/******************************************************************************/
+struct xrdp_session* EXPORT_CC
+libxrdp_init(long id, int sck)
+{
+ struct xrdp_session* session;
+
+ session = (struct xrdp_session*)g_malloc(sizeof(struct xrdp_session), 1);
+ session->id = id;
+ session->rdp = xrdp_rdp_create(session, sck);
+ session->orders = xrdp_orders_create(session, (struct xrdp_rdp*)session->rdp);
+ session->client_info = &(((struct xrdp_rdp*)session->rdp)->client_info);
+ return session;
+}
+
+/******************************************************************************/
+int EXPORT_CC
+libxrdp_exit(struct xrdp_session* session)
+{
+ if (session == 0)
+ {
+ return 0;
+ }
+ xrdp_orders_delete((struct xrdp_orders*)session->orders);
+ xrdp_rdp_delete((struct xrdp_rdp*)session->rdp);
+ g_free(session);
+ return 0;
+}
+
+/******************************************************************************/
+int EXPORT_CC
+libxrdp_disconnect(struct xrdp_session* session)
+{
+ return xrdp_rdp_disconnect((struct xrdp_rdp*)session->rdp);
+}
+
+/******************************************************************************/
+int EXPORT_CC
+libxrdp_process_incomming(struct xrdp_session* session)
+{
+ return xrdp_rdp_incoming((struct xrdp_rdp*)session->rdp);
+}
+
+/******************************************************************************/
+int EXPORT_CC
+libxrdp_process_data(struct xrdp_session* session)
+{
+ struct stream* s;
+ int cont;
+ int rv;
+ int code;
+
+ cont = 1;
+ rv = 0;
+ make_stream(s);
+ init_stream(s, 8192);
+ while (cont && !session->term)
+ {
+ code = 0;
+ if (xrdp_rdp_recv((struct xrdp_rdp*)session->rdp, s, &code) != 0)
+ {
+ rv = 1;
+ break;
+ }
+ DEBUG(("libxrdp_process_data code %d\n\r", code));
+ switch (code)
+ {
+ case -1:
+ xrdp_rdp_send_demand_active((struct xrdp_rdp*)session->rdp);
+ break;
+ case 0:
+ break;
+ case RDP_PDU_CONFIRM_ACTIVE: /* 3 */
+ xrdp_rdp_process_confirm_active((struct xrdp_rdp*)session->rdp, s);
+ break;
+ case RDP_PDU_DATA: /* 7 */
+ if (xrdp_rdp_process_data((struct xrdp_rdp*)session->rdp, s) != 0)
+ {
+ DEBUG(("libxrdp_process_data returned non zero\n\r"));
+ cont = 0;
+ session->term = 1;
+ }
+ break;
+ default:
+ g_printf("unknown in libxrdp_process_data\n\r");
+ break;
+ }
+ if (cont)
+ {
+ cont = s->next_packet < s->end;
+ }
+ }
+ free_stream(s);
+ return rv;
+}
+
+/******************************************************************************/
+int EXPORT_CC
+libxrdp_send_palette(struct xrdp_session* session, int* palette)
+{
+ int i;
+ int color;
+ struct stream* s;
+
+ if (session->client_info->bpp > 8)
+ {
+ return 0;
+ }
+ /* clear orders */
+ libxrdp_orders_force_send(session);
+ make_stream(s);
+ init_stream(s, 8192);
+ xrdp_rdp_init_data((struct xrdp_rdp*)session->rdp, s);
+ out_uint16_le(s, RDP_UPDATE_PALETTE);
+ out_uint16_le(s, 0);
+ out_uint16_le(s, 256); /* # of colors */
+ out_uint16_le(s, 0);
+ for (i = 0; i < 256; i++)
+ {
+ color = palette[i];
+ out_uint8(s, color >> 16);
+ out_uint8(s, color >> 8);
+ out_uint8(s, color);
+ }
+ s_mark_end(s);
+ xrdp_rdp_send_data((struct xrdp_rdp*)session->rdp, s, RDP_DATA_PDU_UPDATE);
+ free_stream(s);
+ /* send the orders palette too */
+ libxrdp_orders_init(session);
+ libxrdp_orders_send_palette(session, palette, 0);
+ libxrdp_orders_send(session);
+ return 0;
+}
+
+/*****************************************************************************/
+int EXPORT_CC
+libxrdp_send_bitmap(struct xrdp_session* session, int width, int height,
+ int bpp, char* data, int x, int y, int cx, int cy)
+{
+ int data_size;
+ int line_size;
+ int i;
+ int j;
+ int total_lines;
+ int lines_sending;
+ int Bpp;
+ int e;
+ int bufsize;
+ int total_bufsize;
+ int num_updates;
+ char* p_num_updates;
+ char* p;
+ char* q;
+ struct stream* s;
+ struct stream* temp_s;
+
+ Bpp = (bpp + 7) / 8;
+ e = width % 4;
+ if (e != 0)
+ {
+ e = 4 - e;
+ }
+ line_size = width * Bpp;
+ make_stream(s);
+ init_stream(s, 8192);
+ if (session->client_info->use_bitmap_comp)
+ {
+ make_stream(temp_s);
+ init_stream(temp_s, 65536);
+ i = 0;
+ if (cy <= height)
+ {
+ i = cy;
+ }
+ while (i > 0)
+ {
+ total_bufsize = 0;
+ num_updates = 0;
+ xrdp_rdp_init_data((struct xrdp_rdp*)session->rdp, s);
+ out_uint16_le(s, RDP_UPDATE_BITMAP);
+ p_num_updates = s->p;
+ out_uint8s(s, 2); /* num_updates set later */
+ do
+ {
+ if (session->client_info->op1)
+ {
+ s_push_layer(s, channel_hdr, 18);
+ }
+ else
+ {
+ s_push_layer(s, channel_hdr, 26);
+ }
+ p = s->p;
+ lines_sending = xrdp_bitmap_compress(data, width, height,
+ s, bpp,
+ 4096 - total_bufsize,
+ i - 1, temp_s, e);
+ if (lines_sending == 0)
+ {
+ break;
+ }
+ num_updates++;
+ bufsize = s->p - p;
+ total_bufsize += bufsize;
+ i = i - lines_sending;
+ s_mark_end(s);
+ s_pop_layer(s, channel_hdr);
+ out_uint16_le(s, x); /* left */
+ out_uint16_le(s, y + i); /* top */
+ out_uint16_le(s, (x + cx) - 1); /* right */
+ out_uint16_le(s, (y + i + lines_sending) - 1); /* bottom */
+ out_uint16_le(s, width + e); /* width */
+ out_uint16_le(s, lines_sending); /* height */
+ out_uint16_le(s, bpp); /* bpp */
+ if (session->client_info->op1)
+ {
+ out_uint16_le(s, 0x401); /* compress */
+ out_uint16_le(s, bufsize); /* compressed size */
+ j = (width + e) * Bpp;
+ j = j * lines_sending;
+ }
+ else
+ {
+ out_uint16_le(s, 0x1); /* compress */
+ out_uint16_le(s, bufsize + 8);
+ out_uint8s(s, 2); /* pad */
+ out_uint16_le(s, bufsize); /* compressed size */
+ j = (width + e) * Bpp;
+ out_uint16_le(s, j); /* line size */
+ j = j * lines_sending;
+ out_uint16_le(s, j); /* final size */
+ }
+ if (j > 32768)
+ {
+ g_printf("error, decompressed size too big, its %d\n\r", j);
+ }
+ if (bufsize > 8192)
+ {
+ g_printf("error, compressed size too big, its %d\n\r", bufsize);
+ }
+ s->p = s->end;
+ } while (total_bufsize < 4096 && i > 0);
+ p_num_updates[0] = num_updates;
+ p_num_updates[1] = num_updates >> 8;
+ xrdp_rdp_send_data((struct xrdp_rdp*)session->rdp, s,
+ RDP_DATA_PDU_UPDATE);
+ if (total_bufsize > 8192)
+ {
+ g_printf("error, total compressed size too big, its %d\n\r",
+ total_bufsize);
+ }
+ }
+ free_stream(temp_s);
+ }
+ else
+ {
+ lines_sending = 0;
+ data_size = width * height * Bpp;
+ total_lines = height;
+ i = 0;
+ p = data;
+ if (line_size > 0 && total_lines > 0)
+ {
+ while (i < total_lines)
+ {
+ lines_sending = 4096 / (line_size + e * Bpp);
+ if (i + lines_sending > total_lines)
+ {
+ lines_sending = total_lines - i;
+ }
+ p = p + line_size * lines_sending;
+ xrdp_rdp_init_data((struct xrdp_rdp*)session->rdp, s);
+ out_uint16_le(s, RDP_UPDATE_BITMAP);
+ out_uint16_le(s, 1); /* num updates */
+ out_uint16_le(s, x);
+ out_uint16_le(s, y + i);
+ out_uint16_le(s, (x + cx) - 1);
+ out_uint16_le(s, (y + i + lines_sending) - 1);
+ out_uint16_le(s, width + e);
+ out_uint16_le(s, lines_sending);
+ out_uint16_le(s, bpp); /* bpp */
+ out_uint16_le(s, 0); /* compress */
+ out_uint16_le(s, (line_size + e * Bpp) * lines_sending); /* bufsize */
+ q = p;
+ for (j = 0; j < lines_sending; j++)
+ {
+ q = q - line_size;
+ out_uint8a(s, q, line_size)
+ out_uint8s(s, e * Bpp);
+ }
+ s_mark_end(s);
+ xrdp_rdp_send_data((struct xrdp_rdp*)session->rdp, s,
+ RDP_DATA_PDU_UPDATE);
+ i = i + lines_sending;
+ }
+ }
+ }
+ free_stream(s);
+ return 0;
+}
+
+/*****************************************************************************/
+int EXPORT_CC
+libxrdp_send_pointer(struct xrdp_session* session, int cache_idx,
+ char* data, char* mask, int x, int y)
+{
+ struct stream* s;
+ char* p;
+ int i;
+ int j;
+
+ make_stream(s);
+ init_stream(s, 8192);
+ xrdp_rdp_init_data((struct xrdp_rdp*)session->rdp, s);
+ out_uint16_le(s, RDP_POINTER_COLOR);
+ out_uint16_le(s, 0); /* pad */
+ out_uint16_le(s, cache_idx); /* cache_idx */
+ out_uint16_le(s, x);
+ out_uint16_le(s, y);
+ out_uint16_le(s, 32);
+ out_uint16_le(s, 32);
+ out_uint16_le(s, 128);
+ out_uint16_le(s, 3072);
+ p = data;
+ for (i = 0; i < 32; i++)
+ {
+ for (j = 0; j < 32; j++)
+ {
+ out_uint8(s, *p);
+ p++;
+ out_uint8(s, *p);
+ p++;
+ out_uint8(s, *p);
+ p++;
+ }
+ }
+ out_uint8a(s, mask, 128); /* mask */
+ s_mark_end(s);
+ xrdp_rdp_send_data((struct xrdp_rdp*)session->rdp, s, RDP_DATA_PDU_POINTER);
+ free_stream(s);
+ return 0;
+}
+
+/*****************************************************************************/
+int EXPORT_CC
+libxrdp_set_pointer(struct xrdp_session* session, int cache_idx)
+{
+ struct stream* s;
+
+ make_stream(s);
+ init_stream(s, 8192);
+ xrdp_rdp_init_data((struct xrdp_rdp*)session->rdp, s);
+ out_uint16_le(s, RDP_POINTER_CACHED);
+ out_uint16_le(s, 0); /* pad */
+ out_uint16_le(s, cache_idx); /* cache_idx */
+ s_mark_end(s);
+ xrdp_rdp_send_data((struct xrdp_rdp*)session->rdp, s, RDP_DATA_PDU_POINTER);
+ free_stream(s);
+ return 0;
+}
+
+/******************************************************************************/
+int EXPORT_CC
+libxrdp_orders_init(struct xrdp_session* session)
+{
+ return xrdp_orders_init((struct xrdp_orders*)session->orders);
+}
+
+/******************************************************************************/
+int EXPORT_CC
+libxrdp_orders_send(struct xrdp_session* session)
+{
+ return xrdp_orders_send((struct xrdp_orders*)session->orders);
+}
+
+/******************************************************************************/
+int EXPORT_CC
+libxrdp_orders_force_send(struct xrdp_session* session)
+{
+ return xrdp_orders_force_send((struct xrdp_orders*)session->orders);
+}
+
+/******************************************************************************/
+int EXPORT_CC
+libxrdp_orders_rect(struct xrdp_session* session, int x, int y,
+ int cx, int cy, int color, struct xrdp_rect* rect)
+{
+ return xrdp_orders_rect((struct xrdp_orders*)session->orders,
+ x, y, cx, cy, color, rect);
+}
+
+/******************************************************************************/
+int EXPORT_CC
+libxrdp_orders_screen_blt(struct xrdp_session* session, int x, int y,
+ int cx, int cy, int srcx, int srcy,
+ int rop, struct xrdp_rect* rect)
+{
+ return xrdp_orders_screen_blt((struct xrdp_orders*)session->orders,
+ x, y, cx, cy, srcx, srcy, rop, rect);
+}
+
+/******************************************************************************/
+int EXPORT_CC
+libxrdp_orders_pat_blt(struct xrdp_session* session, int x, int y,
+ int cx, int cy, int rop, int bg_color,
+ int fg_color, struct xrdp_brush* brush,
+ struct xrdp_rect* rect)
+{
+ return xrdp_orders_pat_blt((struct xrdp_orders*)session->orders,
+ x, y, cx, cy, rop, bg_color, fg_color,
+ brush, rect);
+}
+
+/******************************************************************************/
+int EXPORT_CC
+libxrdp_orders_dest_blt(struct xrdp_session* session, int x, int y,
+ int cx, int cy, int rop,
+ struct xrdp_rect* rect)
+{
+ return xrdp_orders_dest_blt((struct xrdp_orders*)session->orders,
+ x, y, cx, cy, rop, rect);
+}
+
+/******************************************************************************/
+int EXPORT_CC
+libxrdp_orders_line(struct xrdp_session* session, int mix_mode,
+ int startx, int starty,
+ int endx, int endy, int rop, int bg_color,
+ struct xrdp_pen* pen,
+ struct xrdp_rect* rect)
+{
+ return xrdp_orders_line((struct xrdp_orders*)session->orders,
+ mix_mode, startx, starty, endx, endy,
+ rop, bg_color, pen, rect);
+}
+
+/******************************************************************************/
+int EXPORT_CC
+libxrdp_orders_mem_blt(struct xrdp_session* session, int cache_id,
+ int color_table, int x, int y, int cx, int cy,
+ int rop, int srcx, int srcy,
+ int cache_idx, struct xrdp_rect* rect)
+{
+ return xrdp_orders_mem_blt((struct xrdp_orders*)session->orders,
+ cache_id, color_table, x, y, cx, cy, rop,
+ srcx, srcy, cache_idx, rect);
+}
+
+/******************************************************************************/
+int EXPORT_CC
+libxrdp_orders_text(struct xrdp_session* session,
+ int font, int flags, int mixmode,
+ int fg_color, int bg_color,
+ int clip_left, int clip_top,
+ int clip_right, int clip_bottom,
+ int box_left, int box_top,
+ int box_right, int box_bottom,
+ int x, int y, char* data, int data_len,
+ struct xrdp_rect* rect)
+{
+ return xrdp_orders_text((struct xrdp_orders*)session->orders,
+ font, flags, mixmode, fg_color, bg_color,
+ clip_left, clip_top, clip_right, clip_bottom,
+ box_left, box_top, box_right, box_bottom,
+ x, y, data, data_len, rect);
+}
+
+/******************************************************************************/
+int EXPORT_CC
+libxrdp_orders_send_palette(struct xrdp_session* session, int* palette,
+ int cache_id)
+{
+ return xrdp_orders_send_palette((struct xrdp_orders*)session->orders,
+ palette, cache_id);
+}
+
+/*****************************************************************************/
+int EXPORT_CC
+libxrdp_orders_send_raw_bitmap(struct xrdp_session* session,
+ int width, int height, int bpp, char* data,
+ int cache_id, int cache_idx)
+{
+ return xrdp_orders_send_raw_bitmap((struct xrdp_orders*)session->orders,
+ width, height, bpp, data,
+ cache_id, cache_idx);
+}
+
+/*****************************************************************************/
+int EXPORT_CC
+libxrdp_orders_send_bitmap(struct xrdp_session* session,
+ int width, int height, int bpp, char* data,
+ int cache_id, int cache_idx)
+{
+ return xrdp_orders_send_bitmap((struct xrdp_orders*)session->orders,
+ width, height, bpp, data,
+ cache_id, cache_idx);
+}
+
+/*****************************************************************************/
+int EXPORT_CC
+libxrdp_orders_send_font(struct xrdp_session* session,
+ struct xrdp_font_char* font_char,
+ int font_index, int char_index)
+{
+ return xrdp_orders_send_font((struct xrdp_orders*)session->orders,
+ font_char, font_index, char_index);
+}
diff --git a/libxrdp/libxrdp.h b/libxrdp/libxrdp.h
new file mode 100644
index 00000000..29c2bdb6
--- /dev/null
+++ b/libxrdp/libxrdp.h
@@ -0,0 +1,342 @@
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ xrdp: A Remote Desktop Protocol server.
+ Copyright (C) Jay Sorg 2004-2005
+
+ libxrdp header
+
+*/
+
+#if !defined(LIBXRDP_H)
+#define LIBXRDP_H
+
+#include "arch.h"
+#include "parse.h"
+#include "xrdp_constants.h"
+#include "defines.h"
+#include "os_calls.h"
+#include "ssl_calls.h"
+#include "list.h"
+#include "file.h"
+#include "libxrdpinc.h"
+
+/* tcp */
+struct xrdp_tcp
+{
+ int sck;
+ int sck_closed;
+ struct xrdp_iso* iso_layer; /* owner */
+};
+
+/* iso */
+struct xrdp_iso
+{
+ struct xrdp_mcs* mcs_layer; /* owner */
+ struct xrdp_tcp* tcp_layer;
+};
+
+/* mcs */
+struct xrdp_mcs
+{
+ struct xrdp_sec* sec_layer; /* owner */
+ struct xrdp_iso* iso_layer;
+ int userid;
+ int chanid;
+ struct stream* client_mcs_data;
+ struct stream* server_mcs_data;
+};
+
+/* sec */
+struct xrdp_sec
+{
+ struct xrdp_rdp* rdp_layer; /* owner */
+ struct xrdp_mcs* mcs_layer;
+ char server_random[32];
+ char client_random[64];
+ char client_crypt_random[72];
+ struct stream client_mcs_data;
+ struct stream server_mcs_data;
+ int decrypt_use_count;
+ int encrypt_use_count;
+ char decrypt_key[16];
+ char encrypt_key[16];
+ char decrypt_update_key[16];
+ char encrypt_update_key[16];
+ int rc4_key_size;
+ int rc4_key_len;
+ char sign_key[16];
+ void* decrypt_rc4_info;
+ void* encrypt_rc4_info;
+};
+
+/* rdp */
+struct xrdp_rdp
+{
+ struct xrdp_session* session;
+ struct xrdp_sec* sec_layer;
+ int share_id;
+ int mcs_channel;
+ struct xrdp_client_info client_info;
+};
+
+/* orders */
+struct xrdp_orders
+{
+ struct stream* out_s;
+ struct xrdp_rdp* rdp_layer;
+ struct xrdp_session* session;
+ struct xrdp_wm* wm;
+
+ char* order_count_ptr; /* pointer to count, set when sending */
+ int order_count;
+ int order_level; /* inc for every call to xrdp_orders_init */
+
+ int last_order; /* last order sent */
+
+ int clip_left; /* RDP_ORDER_BOUNDS, RDP_ORDER_LASTBOUNDS */
+ int clip_top;
+ int clip_right;
+ int clip_bottom;
+
+ int rect_x; /* RDP_ORDER_RECT */
+ int rect_y;
+ int rect_cx;
+ int rect_cy;
+ int rect_color;
+
+ int scr_blt_x; /* RDP_ORDER_SCREENBLT */
+ int scr_blt_y;
+ int scr_blt_cx;
+ int scr_blt_cy;
+ int scr_blt_rop;
+ int scr_blt_srcx;
+ int scr_blt_srcy;
+
+ int pat_blt_x; /* RDP_ORDER_PATBLT */
+ int pat_blt_y;
+ int pat_blt_cx;
+ int pat_blt_cy;
+ int pat_blt_rop;
+ int pat_blt_bg_color;
+ int pat_blt_fg_color;
+ struct xrdp_brush pat_blt_brush;
+
+ int dest_blt_x; /* RDP_ORDER_DESTBLT */
+ int dest_blt_y;
+ int dest_blt_cx;
+ int dest_blt_cy;
+ int dest_blt_rop;
+
+ int line_mix_mode; /* RDP_ORDER_LINE */
+ int line_startx;
+ int line_starty;
+ int line_endx;
+ int line_endy;
+ int line_bg_color;
+ int line_rop;
+ struct xrdp_pen line_pen;
+
+ int mem_blt_color_table; /* RDP_ORDER_MEMBLT */
+ int mem_blt_cache_id;
+ int mem_blt_x;
+ int mem_blt_y;
+ int mem_blt_cx;
+ int mem_blt_cy;
+ int mem_blt_rop;
+ int mem_blt_srcx;
+ int mem_blt_srcy;
+ int mem_blt_cache_idx;
+
+ int text_font; /* RDP_ORDER_TEXT2 */
+ int text_flags;
+ int text_unknown;
+ int text_mixmode;
+ int text_fg_color;
+ int text_bg_color;
+ int text_clip_left;
+ int text_clip_top;
+ int text_clip_right;
+ int text_clip_bottom;
+ int text_box_left;
+ int text_box_top;
+ int text_box_right;
+ int text_box_bottom;
+ int text_x;
+ int text_y;
+ int text_len;
+ char* text_data;
+};
+
+/* xrdp_tcp.c */
+struct xrdp_tcp* APP_CC
+xrdp_tcp_create(struct xrdp_iso* owner, int sck);
+void APP_CC
+xrdp_tcp_delete(struct xrdp_tcp* self);
+int APP_CC
+xrdp_tcp_init(struct xrdp_tcp* self, struct stream* s);
+int APP_CC
+xrdp_tcp_recv(struct xrdp_tcp* self, struct stream* s, int len);
+int APP_CC
+xrdp_tcp_send(struct xrdp_tcp* self, struct stream* s);
+
+/* xrdp_iso.c */
+struct xrdp_iso* APP_CC
+xrdp_iso_create(struct xrdp_mcs* owner, int sck);
+void APP_CC
+xrdp_iso_delete(struct xrdp_iso* self);
+int APP_CC
+xrdp_iso_init(struct xrdp_iso* self, struct stream* s);
+int APP_CC
+xrdp_iso_recv(struct xrdp_iso* self, struct stream* s);
+int APP_CC
+xrdp_iso_send(struct xrdp_iso* self, struct stream* s);
+int APP_CC
+xrdp_iso_incoming(struct xrdp_iso* self);
+
+/* xrdp_mcs.c */
+struct xrdp_mcs* APP_CC
+xrdp_mcs_create(struct xrdp_sec* owner, int sck,
+ struct stream* client_mcs_data,
+ struct stream* server_mcs_data);
+void APP_CC
+xrdp_mcs_delete(struct xrdp_mcs* self);
+int APP_CC
+xrdp_mcs_init(struct xrdp_mcs* self, struct stream* s);
+int APP_CC
+xrdp_mcs_recv(struct xrdp_mcs* self, struct stream* s, int* chan);
+int APP_CC
+xrdp_mcs_send(struct xrdp_mcs* self, struct stream* s);
+int APP_CC
+xrdp_mcs_incoming(struct xrdp_mcs* self);
+int APP_CC
+xrdp_mcs_disconnect(struct xrdp_mcs* self);
+
+/* xrdp_sec.c */
+struct xrdp_sec* APP_CC
+xrdp_sec_create(struct xrdp_rdp* owner, int sck);
+void APP_CC
+xrdp_sec_delete(struct xrdp_sec* self);
+int APP_CC
+xrdp_sec_init(struct xrdp_sec* self, struct stream* s);
+int APP_CC
+xrdp_sec_recv(struct xrdp_sec* self, struct stream* s, int* chan);
+int APP_CC
+xrdp_sec_send(struct xrdp_sec* self, struct stream* s, int flags);
+int APP_CC
+xrdp_sec_incoming(struct xrdp_sec* self);
+int APP_CC
+xrdp_sec_disconnect(struct xrdp_sec* self);
+
+/* xrdp_rdp.c */
+struct xrdp_rdp* APP_CC
+xrdp_rdp_create(struct xrdp_session* session, int sck);
+void APP_CC
+xrdp_rdp_delete(struct xrdp_rdp* self);
+int APP_CC
+xrdp_rdp_init(struct xrdp_rdp* self, struct stream* s);
+int APP_CC
+xrdp_rdp_init_data(struct xrdp_rdp* self, struct stream* s);
+int APP_CC
+xrdp_rdp_recv(struct xrdp_rdp* self, struct stream* s, int* code);
+int APP_CC
+xrdp_rdp_send(struct xrdp_rdp* self, struct stream* s, int pdu_type);
+int APP_CC
+xrdp_rdp_send_data(struct xrdp_rdp* self, struct stream* s,
+ int data_pdu_type);
+int APP_CC
+xrdp_rdp_incoming(struct xrdp_rdp* self);
+int APP_CC
+xrdp_rdp_send_demand_active(struct xrdp_rdp* self);
+int APP_CC
+xrdp_rdp_process_confirm_active(struct xrdp_rdp* self, struct stream* s);
+int APP_CC
+xrdp_rdp_process_data(struct xrdp_rdp* self, struct stream* s);
+int APP_CC
+xrdp_rdp_disconnect(struct xrdp_rdp* self);
+
+/* xrdp_orders.c */
+struct xrdp_orders* APP_CC
+xrdp_orders_create(struct xrdp_session* session,
+ struct xrdp_rdp* rdp_layer);
+void APP_CC
+xrdp_orders_delete(struct xrdp_orders* self);
+int APP_CC
+xrdp_orders_init(struct xrdp_orders* self);
+int APP_CC
+xrdp_orders_send(struct xrdp_orders* self);
+int APP_CC
+xrdp_orders_force_send(struct xrdp_orders* self);
+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
+xrdp_orders_screen_blt(struct xrdp_orders* self, int x, int y,
+ int cx, int cy, int srcx, int srcy,
+ int rop, struct xrdp_rect* rect);
+int APP_CC
+xrdp_orders_pat_blt(struct xrdp_orders* self, int x, int y,
+ int cx, int cy, int rop, int bg_color,
+ int fg_color, struct xrdp_brush* brush,
+ struct xrdp_rect* rect);
+int APP_CC
+xrdp_orders_dest_blt(struct xrdp_orders* self, int x, int y,
+ int cx, int cy, int rop,
+ struct xrdp_rect* rect);
+int APP_CC
+xrdp_orders_line(struct xrdp_orders* self, int mix_mode,
+ int startx, int starty,
+ int endx, int endy, int rop, int bg_color,
+ struct xrdp_pen* pen,
+ struct xrdp_rect* rect);
+int APP_CC
+xrdp_orders_mem_blt(struct xrdp_orders* self, int cache_id,
+ int color_table, int x, int y, int cx, int cy,
+ int rop, int srcx, int srcy,
+ int cache_idx, struct xrdp_rect* rect);
+int APP_CC
+xrdp_orders_text(struct xrdp_orders* self,
+ int font, int flags, int mixmode,
+ int fg_color, int bg_color,
+ int clip_left, int clip_top,
+ int clip_right, int clip_bottom,
+ int box_left, int box_top,
+ int box_right, int box_bottom,
+ int x, int y, char* data, int data_len,
+ struct xrdp_rect* rect);
+int APP_CC
+xrdp_orders_send_palette(struct xrdp_orders* self, int* palette,
+ int cache_id);
+int APP_CC
+xrdp_orders_send_raw_bitmap(struct xrdp_orders* self,
+ int width, int height, int bpp, char* data,
+ int cache_id, int cache_idx);
+int APP_CC
+xrdp_orders_send_bitmap(struct xrdp_orders* self,
+ int width, int height, int bpp, char* data,
+ int cache_id, int cache_idx);
+int APP_CC
+xrdp_orders_send_font(struct xrdp_orders* self,
+ struct xrdp_font_char* font_char,
+ int font_index, int char_index);
+
+/* xrdp_bitmap_compress.c */
+int APP_CC
+xrdp_bitmap_compress(char* in_data, int width, int height,
+ struct stream* s, int bpp, int byte_limit,
+ int start_line, struct stream* temp,
+ int e);
+
+#endif
diff --git a/libxrdp/libxrdpinc.h b/libxrdp/libxrdpinc.h
new file mode 100644
index 00000000..38857208
--- /dev/null
+++ b/libxrdp/libxrdpinc.h
@@ -0,0 +1,170 @@
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ xrdp: A Remote Desktop Protocol server.
+ Copyright (C) Jay Sorg 2004-2005
+
+ header file for use with libxrdp.so / xrdp.dll
+
+*/
+
+#if !defined(LIBXRDPINC_H)
+#define LIBXRDPINC_H
+
+struct xrdp_client_info
+{
+ int bpp;
+ int width;
+ int height;
+ int cache1_entries;
+ int cache1_size;
+ int cache2_entries;
+ int cache2_size;
+ int cache3_entries;
+ int cache3_size;
+ int pointer_cache_entries;
+ int use_bitmap_comp;
+ int use_bitmap_cache;
+ int op1; /* use smaller bitmap header, todo */
+ int desktop_cache;
+ int use_compact_packets; /* rdp5 smaller packets */
+};
+
+struct xrdp_brush
+{
+ int x_orgin;
+ int y_orgin;
+ int style;
+ char pattern[8];
+};
+
+struct xrdp_pen
+{
+ int style;
+ int width;
+ int color;
+};
+
+struct xrdp_font_char
+{
+ int offset;
+ int baseline;
+ int width;
+ int height;
+ int incby;
+ char* data;
+};
+
+struct xrdp_rect
+{
+ int left;
+ int top;
+ int right;
+ int bottom;
+};
+
+struct xrdp_session
+{
+ long id;
+ int sck;
+ int term; /* do we need this */
+ int (*callback)(long id, int msg, long param1, long param2, long param3,
+ long param4);
+ void* rdp;
+ void* orders;
+ struct xrdp_client_info* client_info;
+ int up_and_running;
+};
+
+struct xrdp_session*
+libxrdp_init(long id, int sck);
+int
+libxrdp_exit(struct xrdp_session* session);
+int
+libxrdp_disconnect(struct xrdp_session* session);
+int
+libxrdp_process_incomming(struct xrdp_session* session);
+int
+libxrdp_process_data(struct xrdp_session* session);
+int
+libxrdp_send_palette(struct xrdp_session* session, int* palette);
+int
+libxrdp_send_bitmap(struct xrdp_session* session, int width, int height,
+ int bpp, char* data, int x, int y, int cx, int cy);
+int
+libxrdp_send_pointer(struct xrdp_session* session, int cache_idx,
+ char* data, char* mask, int x, int y);
+int
+libxrdp_set_pointer(struct xrdp_session* session, int cache_idx);
+int
+libxrdp_orders_init(struct xrdp_session* session);
+int
+libxrdp_orders_send(struct xrdp_session* session);
+int
+libxrdp_orders_force_send(struct xrdp_session* session);
+int
+libxrdp_orders_rect(struct xrdp_session* session, int x, int y,
+ int cx, int cy, int color, struct xrdp_rect* rect);
+int
+libxrdp_orders_screen_blt(struct xrdp_session* session, int x, int y,
+ int cx, int cy, int srcx, int srcy,
+ int rop, struct xrdp_rect* rect);
+int
+libxrdp_orders_pat_blt(struct xrdp_session* session, int x, int y,
+ int cx, int cy, int rop, int bg_color,
+ int fg_color, struct xrdp_brush* brush,
+ struct xrdp_rect* rect);
+int
+libxrdp_orders_dest_blt(struct xrdp_session* session, int x, int y,
+ int cx, int cy, int rop,
+ struct xrdp_rect* rect);
+int
+libxrdp_orders_line(struct xrdp_session* session, int mix_mode,
+ int startx, int starty,
+ int endx, int endy, int rop, int bg_color,
+ struct xrdp_pen* pen,
+ struct xrdp_rect* rect);
+int
+libxrdp_orders_mem_blt(struct xrdp_session* session, int cache_id,
+ int color_table, int x, int y, int cx, int cy,
+ int rop, int srcx, int srcy,
+ int cache_idx, struct xrdp_rect* rect);
+int
+libxrdp_orders_text(struct xrdp_session* session,
+ int font, int flags, int mixmode,
+ int fg_color, int bg_color,
+ int clip_left, int clip_top,
+ int clip_right, int clip_bottom,
+ int box_left, int box_top,
+ int box_right, int box_bottom,
+ int x, int y, char* data, int data_len,
+ struct xrdp_rect* rect);
+int
+libxrdp_orders_send_palette(struct xrdp_session* session, int* palette,
+ int cache_id);
+int
+libxrdp_orders_send_raw_bitmap(struct xrdp_session* session,
+ int width, int height, int bpp, char* data,
+ int cache_id, int cache_idx);
+int
+libxrdp_orders_send_bitmap(struct xrdp_session* session,
+ int width, int height, int bpp, char* data,
+ int cache_id, int cache_idx);
+int
+libxrdp_orders_send_font(struct xrdp_session* session,
+ struct xrdp_font_char* font_char,
+ int font_index, int char_index);
+
+#endif
diff --git a/libxrdp/makefile_win32 b/libxrdp/makefile_win32
new file mode 100755
index 00000000..4ab297ef
--- /dev/null
+++ b/libxrdp/makefile_win32
@@ -0,0 +1,42 @@
+# borland windows makefile
+#
+# this assumes openssl and borland free command line tools are installed
+# this assumes c:\windows is windows directory
+#
+# run 'set PATH=c:\borland\bcc55\bin' and run 'make -f makefile_win32 all'
+#
+
+XRDPOBJ = libxrdp.obj xrdp_tcp.obj xrdp_iso.obj xrdp_mcs.obj \
+ xrdp_sec.obj xrdp_rdp.obj xrdp_orders.obj \
+ xrdp_bitmap_compress.obj \
+ list.obj \
+ file.obj \
+ os_calls.obj \
+ ssl_calls.obj
+
+CFLAGS = -w- -O2 -I../common -Ic:/borland/bcc55/include -Ic:/openssl/include
+LDFLAGS = -Lc:/borland/bcc55/lib
+
+xrdp: $(XRDPOBJ)
+ $(CC) $(LDFLAGS) -WD -exrdp.dll libeay32.lib $(XRDPOBJ)
+
+all: lib xrdp
+
+clean:
+ del $(XRDPOBJ) xrdp.dll
+
+lib:
+ implib -a -w libeay32.lib c:/windows/system32/libeay32.dll
+
+list.obj:
+ $(CC) $(CFLAGS) -c ../common/list.c
+
+file.obj:
+ $(CC) $(CFLAGS) -c ../common/file.c
+
+os_calls.obj:
+ $(CC) $(CFLAGS) -c ../common/os_calls.c
+
+ssl_calls.obj:
+ $(CC) $(CFLAGS) -c ../common/ssl_calls.c
+
diff --git a/libxrdp/xrdp_bitmap_compress.c b/libxrdp/xrdp_bitmap_compress.c
new file mode 100644
index 00000000..b85162f2
--- /dev/null
+++ b/libxrdp/xrdp_bitmap_compress.c
@@ -0,0 +1,1002 @@
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ xrdp: A Remote Desktop Protocol server.
+ Copyright (C) Jay Sorg 2004-2005
+
+ bitmap compressor
+
+*/
+
+#include "libxrdp.h"
+
+/*****************************************************************************/
+#define IN_PIXEL8(in_ptr, in_x, in_y, in_w, in_last_pixel, in_pixel); \
+{ \
+ if (in_ptr == 0) \
+ { \
+ in_pixel = 0; \
+ } \
+ else if (in_x < in_w) \
+ { \
+ in_pixel = GETPIXEL8(in_ptr, in_x, in_y, in_w); \
+ } \
+ else \
+ { \
+ in_pixel = in_last_pixel; \
+ } \
+}
+
+/*****************************************************************************/
+#define IN_PIXEL16(in_ptr, in_x, in_y, in_w, in_last_pixel, in_pixel); \
+{ \
+ if (in_ptr == 0) \
+ { \
+ in_pixel = 0; \
+ } \
+ else if (in_x < in_w) \
+ { \
+ in_pixel = GETPIXEL16(in_ptr, in_x, in_y, in_w); \
+ } \
+ else \
+ { \
+ in_pixel = in_last_pixel; \
+ } \
+}
+
+/*****************************************************************************/
+/* color */
+#define OUT_COLOR_COUNT1(in_count, in_s, in_data) \
+{ \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ temp = (0x3 << 5) | in_count; \
+ out_uint8(in_s, temp); \
+ out_uint8(in_s, in_data); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ out_uint8(in_s, 0x60); \
+ temp = in_count - 32; \
+ out_uint8(in_s, temp); \
+ out_uint8(in_s, in_data); \
+ } \
+ else \
+ { \
+ out_uint8(in_s, 0xf3); \
+ out_uint16_le(in_s, in_count); \
+ out_uint8(in_s, in_data); \
+ } \
+ } \
+ in_count = 0; \
+}
+
+/*****************************************************************************/
+/* color */
+#define OUT_COLOR_COUNT2(in_count, in_s, in_data) \
+{ \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ temp = (0x3 << 5) | in_count; \
+ out_uint8(in_s, temp); \
+ out_uint16_le(in_s, in_data); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ out_uint8(in_s, 0x60); \
+ temp = in_count - 32; \
+ out_uint8(in_s, temp); \
+ out_uint16_le(in_s, in_data); \
+ } \
+ else \
+ { \
+ out_uint8(in_s, 0xf3); \
+ out_uint16_le(in_s, in_count); \
+ out_uint16_le(in_s, in_data); \
+ } \
+ } \
+ in_count = 0; \
+}
+
+/*****************************************************************************/
+/* copy */
+#define OUT_COPY_COUNT1(in_count, in_s, in_data) \
+{ \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ temp = (0x4 << 5) | in_count; \
+ out_uint8(in_s, temp); \
+ out_uint8a(in_s, in_data->data, in_count); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ out_uint8(in_s, 0x80); \
+ temp = in_count - 32; \
+ out_uint8(in_s, temp); \
+ out_uint8a(in_s, in_data->data, in_count); \
+ } \
+ else \
+ { \
+ out_uint8(in_s, 0xf4); \
+ out_uint16_le(in_s, in_count); \
+ out_uint8a(in_s, in_data->data, in_count); \
+ } \
+ } \
+ in_count = 0; \
+ init_stream(in_data, 0); \
+}
+
+/*****************************************************************************/
+/* copy */
+#define OUT_COPY_COUNT2(in_count, in_s, in_data) \
+{ \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ temp = (0x4 << 5) | in_count; \
+ out_uint8(in_s, temp); \
+ temp = in_count * 2; \
+ out_uint8a(in_s, in_data->data, temp); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ out_uint8(in_s, 0x80); \
+ temp = in_count - 32; \
+ out_uint8(in_s, temp); \
+ temp = in_count * 2; \
+ out_uint8a(in_s, in_data->data, temp); \
+ } \
+ else \
+ { \
+ out_uint8(in_s, 0xf4); \
+ out_uint16_le(in_s, in_count); \
+ temp = in_count * 2; \
+ out_uint8a(in_s, in_data->data, temp); \
+ } \
+ } \
+ in_count = 0; \
+ init_stream(in_data, 0); \
+}
+
+/*****************************************************************************/
+/* bicolor */
+#define OUT_BICOLOR_COUNT1(in_count, in_s, in_color1, in_color2) \
+{ \
+ if (in_count > 0) \
+ { \
+ if (in_count / 2 < 16) \
+ { \
+ temp = (0xe << 4) | (in_count / 2); \
+ out_uint8(in_s, temp); \
+ out_uint8(in_s, in_color1); \
+ out_uint8(in_s, in_color2); \
+ } \
+ else if (in_count / 2 < 256 + 16) \
+ { \
+ out_uint8(in_s, 0xe0); \
+ temp = in_count / 2 - 16; \
+ out_uint8(in_s, temp); \
+ out_uint8(in_s, in_color1); \
+ out_uint8(in_s, in_color2); \
+ } \
+ else \
+ { \
+ out_uint8(in_s, 0xf8); \
+ temp = in_count / 2; \
+ out_uint16_le(in_s, temp); \
+ out_uint8(in_s, in_color1); \
+ out_uint8(in_s, in_color2); \
+ } \
+ } \
+ in_count = 0; \
+}
+
+/*****************************************************************************/
+/* bicolor */
+#define OUT_BICOLOR_COUNT2(in_count, in_s, in_color1, in_color2) \
+{ \
+ if (in_count > 0) \
+ { \
+ if (in_count / 2 < 16) \
+ { \
+ temp = (0xe << 4) | (in_count / 2); \
+ out_uint8(in_s, temp); \
+ out_uint16_le(in_s, in_color1); \
+ out_uint16_le(in_s, in_color2); \
+ } \
+ else if (in_count / 2 < 256 + 16) \
+ { \
+ out_uint8(in_s, 0xe0); \
+ temp = in_count / 2 - 16; \
+ out_uint8(in_s, temp); \
+ out_uint16_le(in_s, in_color1); \
+ out_uint16_le(in_s, in_color2); \
+ } \
+ else \
+ { \
+ out_uint8(in_s, 0xf8); \
+ temp = in_count / 2; \
+ out_uint16_le(in_s, temp); \
+ out_uint16_le(in_s, in_color1); \
+ out_uint16_le(in_s, in_color2); \
+ } \
+ } \
+ in_count = 0; \
+}
+
+/*****************************************************************************/
+/* fill */
+#define OUT_FILL_COUNT1(in_count, in_s) \
+{ \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ out_uint8(in_s, in_count); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ out_uint8(in_s, 0x0); \
+ temp = in_count - 32; \
+ out_uint8(in_s, temp); \
+ } \
+ else \
+ { \
+ out_uint8(in_s, 0xf0); \
+ out_uint16_le(in_s, in_count); \
+ } \
+ } \
+ in_count = 0; \
+}
+
+/*****************************************************************************/
+/* fill */
+#define OUT_FILL_COUNT2(in_count, in_s) \
+{ \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ out_uint8(in_s, in_count); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ out_uint8(in_s, 0x0); \
+ temp = in_count - 32; \
+ out_uint8(in_s, temp); \
+ } \
+ else \
+ { \
+ out_uint8(in_s, 0xf0); \
+ out_uint16_le(in_s, in_count); \
+ } \
+ } \
+ in_count = 0; \
+}
+
+/*****************************************************************************/
+/* mix */
+#define OUT_MIX_COUNT1(in_count, in_s) \
+{ \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ temp = (0x1 << 5) | in_count; \
+ out_uint8(in_s, temp); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ out_uint8(in_s, 0x20); \
+ temp = in_count - 32; \
+ out_uint8(in_s, temp); \
+ } \
+ else \
+ { \
+ out_uint8(in_s, 0xf1); \
+ out_uint16_le(in_s, in_count); \
+ } \
+ } \
+ in_count = 0; \
+}
+
+/*****************************************************************************/
+/* mix */
+#define OUT_MIX_COUNT2(in_count, in_s) \
+{ \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ temp = (0x1 << 5) | in_count; \
+ out_uint8(in_s, temp); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ out_uint8(in_s, 0x20); \
+ temp = in_count - 32; \
+ out_uint8(in_s, temp); \
+ } \
+ else \
+ { \
+ out_uint8(in_s, 0xf1); \
+ out_uint16_le(in_s, in_count); \
+ } \
+ } \
+ in_count = 0; \
+}
+
+/*****************************************************************************/
+/* fom */
+#define OUT_FOM_COUNT1(in_count, in_s, in_mask, in_mask_len) \
+{ \
+ if (in_count > 0) \
+ { \
+ if ((in_count % 8) == 0 && in_count < 249) \
+ { \
+ temp = (0x2 << 5) | (in_count / 8); \
+ out_uint8(in_s, temp); \
+ out_uint8a(in_s, in_mask, in_mask_len); \
+ } \
+ else if (in_count < 256) \
+ { \
+ out_uint8(in_s, 0x40); \
+ temp = in_count - 1; \
+ out_uint8(in_s, temp); \
+ out_uint8a(in_s, in_mask, in_mask_len); \
+ } \
+ else \
+ { \
+ out_uint8(in_s, 0xf2); \
+ out_uint16_le(in_s, in_count); \
+ out_uint8a(in_s, in_mask, in_mask_len); \
+ } \
+ } \
+ in_count = 0; \
+}
+
+/*****************************************************************************/
+/* fom */
+#define OUT_FOM_COUNT2(in_count, in_s, in_mask, in_mask_len) \
+{ \
+ if (in_count > 0) \
+ { \
+ if ((in_count % 8) == 0 && in_count < 249) \
+ { \
+ temp = (0x2 << 5) | (in_count / 8); \
+ out_uint8(in_s, temp); \
+ out_uint8a(in_s, in_mask, in_mask_len); \
+ } \
+ else if (in_count < 256) \
+ { \
+ out_uint8(in_s, 0x40); \
+ temp = in_count - 1; \
+ out_uint8(in_s, temp); \
+ out_uint8a(in_s, in_mask, in_mask_len); \
+ } \
+ else \
+ { \
+ out_uint8(in_s, 0xf2); \
+ out_uint16_le(in_s, in_count); \
+ out_uint8a(in_s, in_mask, in_mask_len); \
+ } \
+ } \
+ in_count = 0; \
+}
+
+/*****************************************************************************/
+#define TEST_FILL \
+((last_line == 0 && pixel == 0) || \
+ (last_line != 0 && pixel == ypixel))
+#define TEST_MIX \
+((last_line == 0 && pixel == mix) || \
+ (last_line != 0 && pixel == (ypixel ^ mix)))
+#define TEST_FOM (TEST_FILL || TEST_MIX)
+#define TEST_COLOR (pixel == last_pixel)
+#define TEST_BICOLOR \
+( \
+ (pixel != last_pixel) && \
+ ( \
+ (!bicolor_spin && pixel == bicolor1 && last_pixel == bicolor2) || \
+ (bicolor_spin && pixel == bicolor2 && last_pixel == bicolor1) \
+ ) \
+)
+#define RESET_COUNTS \
+{ \
+ bicolor_count = 0; \
+ fill_count = 0; \
+ color_count = 0; \
+ mix_count = 0; \
+ fom_count = 0; \
+ fom_mask_len = 0; \
+ bicolor_spin = 0; \
+}
+
+/*****************************************************************************/
+int APP_CC
+xrdp_bitmap_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)
+{
+ char* line;
+ char* last_line;
+ char fom_mask[8192];
+ int lines_sent;
+ int pixel;
+ int count;
+ int color_count;
+ int last_pixel;
+ int bicolor_count;
+ int bicolor1;
+ int bicolor2;
+ int bicolor_spin;
+ int end;
+ int i;
+ int out_count;
+ int ypixel;
+ int last_ypixel;
+ int fill_count;
+ int mix_count;
+ int mix;
+ int fom_count;
+ int fom_mask_len;
+ int temp; /* used in macros */
+
+ init_stream(temp_s, 0);
+ fom_mask_len = 0;
+ last_line = 0;
+ lines_sent = 0;
+ end = width + e;
+ count = 0;
+ color_count = 0;
+ last_pixel = 0;
+ last_ypixel = 0;
+ bicolor_count = 0;
+ bicolor1 = 0;
+ bicolor2 = 0;
+ bicolor_spin = 0;
+ fill_count = 0;
+ mix_count = 0;
+ fom_count = 0;
+ if (bpp == 8)
+ {
+ mix = 0xff;
+ out_count = end;
+ line = in_data + width * start_line;
+ while (start_line >= 0 && out_count < 32768)
+ {
+ i = (s->p - s->data) + count;
+ if (i - color_count >= byte_limit &&
+ i - bicolor_count >= byte_limit &&
+ i - fill_count >= byte_limit &&
+ i - mix_count >= byte_limit &&
+ i - fom_count >= byte_limit)
+ {
+ break;
+ }
+ out_count += end;
+ for (i = 0; i < end; i++)
+ {
+ /* read next pixel */
+ IN_PIXEL8(line, i, 0, width, last_pixel, pixel);
+ IN_PIXEL8(last_line, i, 0, width, last_ypixel, ypixel);
+ if (!TEST_FILL)
+ {
+ if (fill_count > 3 &&
+ fill_count >= color_count &&
+ fill_count >= bicolor_count &&
+ fill_count >= mix_count &&
+ fill_count >= fom_count)
+ {
+ count -= fill_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_FILL_COUNT1(fill_count, s);
+ RESET_COUNTS;
+ }
+ fill_count = 0;
+ }
+ if (!TEST_MIX)
+ {
+ if (mix_count > 3 &&
+ mix_count >= fill_count &&
+ mix_count >= bicolor_count &&
+ mix_count >= color_count &&
+ mix_count >= fom_count)
+ {
+ count -= mix_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_MIX_COUNT1(mix_count, s);
+ RESET_COUNTS;
+ }
+ mix_count = 0;
+ }
+ if (!TEST_COLOR)
+ {
+ if (color_count > 3 &&
+ color_count >= fill_count &&
+ color_count >= bicolor_count &&
+ color_count >= mix_count &&
+ color_count >= fom_count)
+ {
+ count -= color_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_COLOR_COUNT1(color_count, s, last_pixel);
+ RESET_COUNTS;
+ }
+ color_count = 0;
+ }
+ if (!TEST_BICOLOR)
+ {
+ if (bicolor_count > 3 &&
+ bicolor_count >= fill_count &&
+ bicolor_count >= color_count &&
+ bicolor_count >= mix_count &&
+ bicolor_count >= fom_count)
+ {
+ if ((bicolor_count % 2) == 0)
+ {
+ count -= bicolor_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_BICOLOR_COUNT1(bicolor_count, s, bicolor1, bicolor2);
+ }
+ else
+ {
+ bicolor_count--;
+ count -= bicolor_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_BICOLOR_COUNT1(bicolor_count, s, bicolor2, bicolor1);
+ }
+ RESET_COUNTS;
+ }
+ bicolor_count = 0;
+ bicolor1 = last_pixel;
+ bicolor2 = pixel;
+ bicolor_spin = 0;
+ }
+ if (!TEST_FOM)
+ {
+ if (fom_count > 3 &&
+ fom_count >= fill_count &&
+ fom_count >= color_count &&
+ fom_count >= mix_count &&
+ fom_count >= bicolor_count)
+ {
+ count -= fom_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_FOM_COUNT1(fom_count, s, fom_mask, fom_mask_len);
+ RESET_COUNTS;
+ }
+ fom_count = 0;
+ fom_mask_len = 0;
+ }
+ if (TEST_FILL)
+ {
+ fill_count++;
+ }
+ if (TEST_MIX)
+ {
+ mix_count++;
+ }
+ if (TEST_COLOR)
+ {
+ color_count++;
+ }
+ if (TEST_BICOLOR)
+ {
+ bicolor_spin = !bicolor_spin;
+ bicolor_count++;
+ }
+ if (TEST_FOM)
+ {
+ if ((fom_count % 8) == 0)
+ {
+ fom_mask[fom_mask_len] = 0;
+ fom_mask_len++;
+ }
+ if (pixel == (ypixel ^ mix))
+ {
+ fom_mask[fom_mask_len - 1] |= (1 << (fom_count % 8));
+ }
+ fom_count++;
+ }
+ out_uint8(temp_s, pixel);
+ count++;
+ last_pixel = pixel;
+ last_ypixel = ypixel;
+ }
+ /* can't take fix, mix, or fom past first line */
+ if (last_line == 0)
+ {
+ if (fill_count > 3 &&
+ fill_count >= color_count &&
+ fill_count >= bicolor_count &&
+ fill_count >= mix_count &&
+ fill_count >= fom_count)
+ {
+ count -= fill_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_FILL_COUNT1(fill_count, s);
+ RESET_COUNTS;
+ }
+ fill_count = 0;
+ if (mix_count > 3 &&
+ mix_count >= fill_count &&
+ mix_count >= bicolor_count &&
+ mix_count >= color_count &&
+ mix_count >= fom_count)
+ {
+ count -= mix_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_MIX_COUNT1(mix_count, s);
+ RESET_COUNTS;
+ }
+ mix_count = 0;
+ if (fom_count > 3 &&
+ fom_count >= fill_count &&
+ fom_count >= color_count &&
+ fom_count >= mix_count &&
+ fom_count >= bicolor_count)
+ {
+ count -= fom_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_FOM_COUNT1(fom_count, s, fom_mask, fom_mask_len);
+ RESET_COUNTS;
+ }
+ fom_count = 0;
+ fom_mask_len = 0;
+ }
+ last_line = line;
+ line = line - width;
+ start_line--;
+ lines_sent++;
+ }
+ if (fill_count > 3 &&
+ fill_count >= color_count &&
+ fill_count >= bicolor_count &&
+ fill_count >= mix_count &&
+ fill_count >= fom_count)
+ {
+ count -= fill_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_FILL_COUNT1(fill_count, s);
+ }
+ else if (mix_count > 3 &&
+ mix_count >= color_count &&
+ mix_count >= bicolor_count &&
+ mix_count >= fill_count &&
+ mix_count >= fom_count)
+ {
+ count -= mix_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_MIX_COUNT1(mix_count, s);
+ }
+ else if (color_count > 3 &&
+ color_count >= mix_count &&
+ color_count >= bicolor_count &&
+ color_count >= fill_count &&
+ color_count >= fom_count)
+ {
+ count -= color_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_COLOR_COUNT1(color_count, s, last_pixel);
+ }
+ else if (bicolor_count > 3 &&
+ bicolor_count >= mix_count &&
+ bicolor_count >= color_count &&
+ bicolor_count >= fill_count &&
+ bicolor_count >= fom_count)
+ {
+ if ((bicolor_count % 2) == 0)
+ {
+ count -= bicolor_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_BICOLOR_COUNT1(bicolor_count, s, bicolor1, bicolor2);
+ }
+ else
+ {
+ bicolor_count--;
+ count -= bicolor_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_BICOLOR_COUNT1(bicolor_count, s, bicolor2, bicolor1);
+ }
+ count -= bicolor_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_BICOLOR_COUNT1(bicolor_count, s, bicolor1, bicolor2);
+ }
+ else if (fom_count > 3 &&
+ fom_count >= mix_count &&
+ fom_count >= color_count &&
+ fom_count >= fill_count &&
+ fom_count >= bicolor_count)
+ {
+ count -= fom_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_FOM_COUNT1(fom_count, s, fom_mask, fom_mask_len);
+ }
+ else
+ {
+ OUT_COPY_COUNT1(count, s, temp_s);
+ }
+ }
+ else if (bpp == 16)
+ {
+ mix = 0xffff;
+ out_count = end * 2;
+ line = in_data + width * start_line * 2;
+ while (start_line >= 0 && out_count < 32768)
+ {
+ i = (s->p - s->data) + count * 2;
+ if (i - (color_count * 2) >= byte_limit &&
+ i - (bicolor_count * 2) >= byte_limit &&
+ i - (fill_count * 2) >= byte_limit &&
+ i - (mix_count * 2) >= byte_limit &&
+ i - (fom_count * 2) >= byte_limit)
+ {
+ break;
+ }
+ out_count += end * 2;
+ for (i = 0; i < end; i++)
+ {
+ /* read next pixel */
+ IN_PIXEL16(line, i, 0, width, last_pixel, pixel);
+ IN_PIXEL16(last_line, i, 0, width, last_ypixel, ypixel);
+ if (!TEST_FILL)
+ {
+ if (fill_count > 3 &&
+ fill_count >= color_count &&
+ fill_count >= bicolor_count &&
+ fill_count >= mix_count &&
+ fill_count >= fom_count)
+ {
+ count -= fill_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_FILL_COUNT2(fill_count, s);
+ RESET_COUNTS;
+ }
+ fill_count = 0;
+ }
+ if (!TEST_MIX)
+ {
+ if (mix_count > 3 &&
+ mix_count >= fill_count &&
+ mix_count >= bicolor_count &&
+ mix_count >= color_count &&
+ mix_count >= fom_count)
+ {
+ count -= mix_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_MIX_COUNT2(mix_count, s);
+ RESET_COUNTS;
+ }
+ mix_count = 0;
+ }
+ if (!TEST_COLOR)
+ {
+ if (color_count > 3 &&
+ color_count >= fill_count &&
+ color_count >= bicolor_count &&
+ color_count >= mix_count &&
+ color_count >= fom_count)
+ {
+ count -= color_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_COLOR_COUNT2(color_count, s, last_pixel);
+ RESET_COUNTS;
+ }
+ color_count = 0;
+ }
+ if (!TEST_BICOLOR)
+ {
+ if (bicolor_count > 3 &&
+ bicolor_count >= fill_count &&
+ bicolor_count >= color_count &&
+ bicolor_count >= mix_count &&
+ bicolor_count >= fom_count)
+ {
+ if ((bicolor_count % 2) == 0)
+ {
+ count -= bicolor_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_BICOLOR_COUNT2(bicolor_count, s, bicolor1, bicolor2);
+ }
+ else
+ {
+ bicolor_count--;
+ count -= bicolor_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_BICOLOR_COUNT2(bicolor_count, s, bicolor2, bicolor1);
+ }
+ RESET_COUNTS;
+ }
+ bicolor_count = 0;
+ bicolor1 = last_pixel;
+ bicolor2 = pixel;
+ bicolor_spin = 0;
+ }
+ if (!TEST_FOM)
+ {
+ if (fom_count > 3 &&
+ fom_count >= fill_count &&
+ fom_count >= color_count &&
+ fom_count >= mix_count &&
+ fom_count >= bicolor_count)
+ {
+ count -= fom_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_FOM_COUNT2(fom_count, s, fom_mask, fom_mask_len);
+ RESET_COUNTS;
+ }
+ fom_count = 0;
+ fom_mask_len = 0;
+ }
+ if (TEST_FILL)
+ {
+ fill_count++;
+ }
+ if (TEST_MIX)
+ {
+ mix_count++;
+ }
+ if (TEST_COLOR)
+ {
+ color_count++;
+ }
+ if (TEST_BICOLOR)
+ {
+ bicolor_spin = !bicolor_spin;
+ bicolor_count++;
+ }
+ if (TEST_FOM)
+ {
+ if ((fom_count % 8) == 0)
+ {
+ fom_mask[fom_mask_len] = 0;
+ fom_mask_len++;
+ }
+ if (pixel == (ypixel ^ mix))
+ {
+ fom_mask[fom_mask_len - 1] |= (1 << (fom_count % 8));
+ }
+ fom_count++;
+ }
+ out_uint16_le(temp_s, pixel);
+ count++;
+ last_pixel = pixel;
+ last_ypixel = ypixel;
+ }
+ /* can't take fix, mix, or fom past first line */
+ if (last_line == 0)
+ {
+ if (fill_count > 3 &&
+ fill_count >= color_count &&
+ fill_count >= bicolor_count &&
+ fill_count >= mix_count &&
+ fill_count >= fom_count)
+ {
+ count -= fill_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_FILL_COUNT2(fill_count, s);
+ RESET_COUNTS;
+ }
+ fill_count = 0;
+ if (mix_count > 3 &&
+ mix_count >= fill_count &&
+ mix_count >= bicolor_count &&
+ mix_count >= color_count &&
+ mix_count >= fom_count)
+ {
+ count -= mix_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_MIX_COUNT2(mix_count, s);
+ RESET_COUNTS;
+ }
+ mix_count = 0;
+ if (fom_count > 3 &&
+ fom_count >= fill_count &&
+ fom_count >= color_count &&
+ fom_count >= mix_count &&
+ fom_count >= bicolor_count)
+ {
+ count -= fom_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_FOM_COUNT2(fom_count, s, fom_mask, fom_mask_len);
+ RESET_COUNTS;
+ }
+ fom_count = 0;
+ fom_mask_len = 0;
+ }
+ last_line = line;
+ line = line - width * 2;
+ start_line--;
+ lines_sent++;
+ }
+ if (fill_count > 3 &&
+ fill_count >= color_count &&
+ fill_count >= bicolor_count &&
+ fill_count >= mix_count &&
+ fill_count >= fom_count)
+ {
+ count -= fill_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_FILL_COUNT2(fill_count, s);
+ }
+ else if (mix_count > 3 &&
+ mix_count >= color_count &&
+ mix_count >= bicolor_count &&
+ mix_count >= fill_count &&
+ mix_count >= fom_count)
+ {
+ count -= mix_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_MIX_COUNT2(mix_count, s);
+ }
+ else if (color_count > 3 &&
+ color_count >= mix_count &&
+ color_count >= bicolor_count &&
+ color_count >= fill_count &&
+ color_count >= fom_count)
+ {
+ count -= color_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_COLOR_COUNT2(color_count, s, last_pixel);
+ }
+ else if (bicolor_count > 3 &&
+ bicolor_count >= mix_count &&
+ bicolor_count >= color_count &&
+ bicolor_count >= fill_count &&
+ bicolor_count >= fom_count)
+ {
+ if ((bicolor_count % 2) == 0)
+ {
+ count -= bicolor_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_BICOLOR_COUNT2(bicolor_count, s, bicolor1, bicolor2);
+ }
+ else
+ {
+ bicolor_count--;
+ count -= bicolor_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_BICOLOR_COUNT2(bicolor_count, s, bicolor2, bicolor1);
+ }
+ count -= bicolor_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_BICOLOR_COUNT2(bicolor_count, s, bicolor1, bicolor2);
+ }
+ else if (fom_count > 3 &&
+ fom_count >= mix_count &&
+ fom_count >= color_count &&
+ fom_count >= fill_count &&
+ fom_count >= bicolor_count)
+ {
+ count -= fom_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_FOM_COUNT2(fom_count, s, fom_mask, fom_mask_len);
+ }
+ else
+ {
+ OUT_COPY_COUNT2(count, s, temp_s);
+ }
+ }
+ return lines_sent;
+}
diff --git a/libxrdp/xrdp_iso.c b/libxrdp/xrdp_iso.c
new file mode 100644
index 00000000..7cd56bf9
--- /dev/null
+++ b/libxrdp/xrdp_iso.c
@@ -0,0 +1,195 @@
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ xrdp: A Remote Desktop Protocol server.
+ Copyright (C) Jay Sorg 2004-2005
+
+ iso layer
+
+*/
+
+#include "libxrdp.h"
+
+/*****************************************************************************/
+struct xrdp_iso* APP_CC
+xrdp_iso_create(struct xrdp_mcs* owner, int sck)
+{
+ struct xrdp_iso* self;
+
+ self = (struct xrdp_iso*)g_malloc(sizeof(struct xrdp_iso), 1);
+ self->mcs_layer = owner;
+ self->tcp_layer = xrdp_tcp_create(self, sck);
+ return self;
+}
+
+/*****************************************************************************/
+void APP_CC
+xrdp_iso_delete(struct xrdp_iso* self)
+{
+ if (self == 0)
+ {
+ return;
+ }
+ xrdp_tcp_delete(self->tcp_layer);
+ g_free(self);
+}
+
+/*****************************************************************************/
+/* returns error */
+static int APP_CC
+xrdp_iso_recv_msg(struct xrdp_iso* self, struct stream* s, int* code)
+{
+ int ver;
+ int len;
+
+ *code = 0;
+ if (xrdp_tcp_recv(self->tcp_layer, s, 4) != 0)
+ {
+ return 1;
+ }
+ in_uint8(s, ver);
+ if (ver != 3)
+ {
+ return 1;
+ }
+ in_uint8s(s, 1);
+ in_uint16_be(s, len);
+ if (xrdp_tcp_recv(self->tcp_layer, s, len - 4) != 0)
+ {
+ return 1;
+ }
+ in_uint8s(s, 1);
+ in_uint8(s, *code);
+ if (*code == ISO_PDU_DT)
+ {
+ in_uint8s(s, 1);
+ }
+ else
+ {
+ in_uint8s(s, 5);
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+xrdp_iso_recv(struct xrdp_iso* self, struct stream* s)
+{
+ int code;
+
+ DEBUG((" in xrdp_iso_recv\n\r"));
+ if (xrdp_iso_recv_msg(self, s, &code) != 0)
+ {
+ DEBUG((" out xrdp_iso_recv xrdp_iso_recv_msg return non zero\n\r"));
+ return 1;
+ }
+ if (code != ISO_PDU_DT)
+ {
+ DEBUG((" out xrdp_iso_recv code != ISO_PDU_DT\n\r"));
+ return 1;
+ }
+ DEBUG((" out xrdp_iso_recv\n\r"));
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+xrdp_iso_send_msg(struct xrdp_iso* self, struct stream* s, int code)
+{
+ if (xrdp_tcp_init(self->tcp_layer, s) != 0)
+ {
+ return 1;
+ }
+ out_uint8(s, 3);
+ out_uint8(s, 0);
+ out_uint16_be(s, 11); /* length */
+ out_uint8(s, 8);
+ out_uint8(s, code);
+ out_uint16_le(s, 0);
+ out_uint16_le(s, 0);
+ out_uint8(s, 0);
+ s_mark_end(s);
+ if (xrdp_tcp_send(self->tcp_layer, s) != 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+xrdp_iso_incoming(struct xrdp_iso* self)
+{
+ int code;
+ struct stream* s;
+
+ make_stream(s);
+ init_stream(s, 8192);
+ DEBUG((" in xrdp_iso_incoming\n\r"));
+ if (xrdp_iso_recv_msg(self, s, &code) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ if (code != ISO_PDU_CR)
+ {
+ free_stream(s);
+ return 1;
+ }
+ if (xrdp_iso_send_msg(self, s, ISO_PDU_CC) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ DEBUG((" out xrdp_iso_incoming\n\r"));
+ free_stream(s);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+xrdp_iso_init(struct xrdp_iso* self, struct stream* s)
+{
+ xrdp_tcp_init(self->tcp_layer, s);
+ s_push_layer(s, iso_hdr, 7);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+xrdp_iso_send(struct xrdp_iso* self, struct stream* s)
+{
+ int len;
+
+ DEBUG((" in xrdp_iso_send\n\r"));
+ s_pop_layer(s, iso_hdr);
+ len = s->end - s->p;
+ out_uint8(s, 3);
+ out_uint8(s, 0);
+ out_uint16_be(s, len);
+ out_uint8(s, 2);
+ out_uint8(s, ISO_PDU_DT);
+ out_uint8(s, 0x80);
+ if (xrdp_tcp_send(self->tcp_layer, s) != 0)
+ {
+ return 1;
+ }
+ DEBUG((" out xrdp_iso_send\n\r"));
+ return 0;
+}
diff --git a/libxrdp/xrdp_mcs.c b/libxrdp/xrdp_mcs.c
new file mode 100644
index 00000000..3fed1a0b
--- /dev/null
+++ b/libxrdp/xrdp_mcs.c
@@ -0,0 +1,629 @@
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ xrdp: A Remote Desktop Protocol server.
+ Copyright (C) Jay Sorg 2004-2005
+
+ mcs layer
+
+*/
+
+#include "libxrdp.h"
+
+/*****************************************************************************/
+struct xrdp_mcs* APP_CC
+xrdp_mcs_create(struct xrdp_sec* owner, int sck,
+ struct stream* client_mcs_data,
+ struct stream* server_mcs_data)
+{
+ struct xrdp_mcs* self;
+
+ self = (struct xrdp_mcs*)g_malloc(sizeof(struct xrdp_mcs), 1);
+ self->sec_layer = owner;
+ self->userid = 1;
+ self->chanid = 1001;
+ self->client_mcs_data = client_mcs_data;
+ self->server_mcs_data = server_mcs_data;
+ self->iso_layer = xrdp_iso_create(self, sck);
+ return self;
+}
+
+/*****************************************************************************/
+void APP_CC
+xrdp_mcs_delete(struct xrdp_mcs* self)
+{
+ if (self == 0)
+ {
+ return;
+ }
+ xrdp_iso_delete(self->iso_layer);
+ g_free(self);
+}
+
+/*****************************************************************************/
+/* returns error */
+static int APP_CC
+xrdp_mcs_send_cjcf(struct xrdp_mcs* self, int chanid)
+{
+ struct stream* s;
+
+ make_stream(s);
+ init_stream(s, 8192);
+ if (xrdp_iso_init(self->iso_layer, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ out_uint8(s, (MCS_CJCF << 2) | 2);
+ out_uint8(s, 0);
+ out_uint16_be(s, self->userid);
+ out_uint16_be(s, chanid);
+ out_uint16_be(s, chanid);
+ s_mark_end(s);
+ if (xrdp_iso_send(self->iso_layer, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ free_stream(s);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+xrdp_mcs_recv(struct xrdp_mcs* self, struct stream* s, int* chan)
+{
+ int appid;
+ int opcode;
+ int len;
+
+ DEBUG((" in xrdp_mcs_recv\n\r"));
+ while (1)
+ {
+ if (xrdp_iso_recv(self->iso_layer, s) != 0)
+ {
+ DEBUG((" out xrdp_mcs_recv xrdp_iso_recv returned non zero\n\r"));
+ return 1;
+ }
+ in_uint8(s, opcode);
+ appid = opcode >> 2;
+ if (appid == MCS_DPUM)
+ {
+ DEBUG((" out xrdp_mcs_recv appid != MCS_DPUM\n\r"));
+ return 1;
+ }
+ if (appid == MCS_CJRQ)
+ {
+ xrdp_mcs_send_cjcf(self, self->userid + MCS_USERCHANNEL_BASE);
+ continue;
+ }
+ break;
+ }
+ if (appid != MCS_SDRQ)
+ {
+ DEBUG((" out xrdp_mcs_recv err got 0x%x need MCS_SDRQ\n\r", appid));
+ return 1;
+ }
+ in_uint8s(s, 2);
+ in_uint16_be(s, *chan);
+ in_uint8s(s, 1);
+ in_uint8(s, len);
+ if (len & 0x80)
+ {
+ in_uint8s(s, 1);
+ }
+ DEBUG((" out xrdp_mcs_recv\n\r"));
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+static int APP_CC
+xrdp_mcs_ber_parse_header(struct xrdp_mcs* self, struct stream* s,
+ int tag_val, int* len)
+{
+ int tag;
+ int l;
+ int i;
+
+ if (tag_val > 0xff)
+ {
+ in_uint16_be(s, tag);
+ }
+ else
+ {
+ in_uint8(s, tag);
+ }
+ if (tag != tag_val)
+ {
+ return 1;
+ }
+ in_uint8(s, l);
+ if (l & 0x80)
+ {
+ l = l & ~0x80;
+ *len = 0;
+ while (l > 0)
+ {
+ in_uint8(s, i);
+ *len = (*len << 8) | i;
+ l--;
+ }
+ }
+ else
+ {
+ *len = l;
+ }
+ if (s_check(s))
+ {
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+/*****************************************************************************/
+/* returns error */
+static int APP_CC
+xrdp_mcs_parse_domain_params(struct xrdp_mcs* self, struct stream* s)
+{
+ int len;
+
+ if (xrdp_mcs_ber_parse_header(self, s, MCS_TAG_DOMAIN_PARAMS, &len) != 0)
+ {
+ return 1;
+ }
+ in_uint8s(s, len);
+ if (s_check(s))
+ {
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+/*****************************************************************************/
+/* returns error */
+static int APP_CC
+xrdp_mcs_recv_connect_initial(struct xrdp_mcs* self)
+{
+ int len;
+ struct stream* s;
+
+ make_stream(s);
+ init_stream(s, 8192);
+ if (xrdp_iso_recv(self->iso_layer, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ if (xrdp_mcs_ber_parse_header(self, s, MCS_CONNECT_INITIAL, &len) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ in_uint8s(s, len);
+ if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ in_uint8s(s, len);
+ if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_BOOLEAN, &len) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ in_uint8s(s, len);
+ if (xrdp_mcs_parse_domain_params(self, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ if (xrdp_mcs_parse_domain_params(self, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ if (xrdp_mcs_parse_domain_params(self, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ /* make a copy of client mcs data */
+ init_stream(self->client_mcs_data, len);
+ out_uint8a(self->client_mcs_data, s->p, len);
+ in_uint8s(s, len);
+ s_mark_end(self->client_mcs_data);
+ if (s_check_end(s))
+ {
+ free_stream(s);
+ return 0;
+ }
+ else
+ {
+ free_stream(s);
+ return 1;
+ }
+}
+
+/*****************************************************************************/
+/* returns error */
+static int APP_CC
+xrdp_mcs_recv_edrq(struct xrdp_mcs* self)
+{
+ int opcode;
+ struct stream* s;
+
+ make_stream(s);
+ init_stream(s, 8192);
+ if (xrdp_iso_recv(self->iso_layer, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ in_uint8(s, opcode);
+ if ((opcode >> 2) != MCS_EDRQ)
+ {
+ free_stream(s);
+ return 1;
+ }
+ in_uint8s(s, 2);
+ in_uint8s(s, 2);
+ if (opcode & 2)
+ {
+ in_uint16_be(s, self->userid);
+ }
+ if (!(s_check_end(s)))
+ {
+ free_stream(s);
+ return 1;
+ }
+ free_stream(s);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+static int APP_CC
+xrdp_mcs_recv_aurq(struct xrdp_mcs* self)
+{
+ int opcode;
+ struct stream* s;
+
+ make_stream(s);
+ init_stream(s, 8192);
+ if (xrdp_iso_recv(self->iso_layer, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ in_uint8(s, opcode);
+ if ((opcode >> 2) != MCS_AURQ)
+ {
+ free_stream(s);
+ return 1;
+ }
+ if (opcode & 2)
+ {
+ in_uint16_be(s, self->userid);
+ }
+ if (!(s_check_end(s)))
+ {
+ free_stream(s);
+ return 1;
+ }
+ free_stream(s);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+static int APP_CC
+xrdp_mcs_send_aucf(struct xrdp_mcs* self)
+{
+ struct stream* s;
+
+ make_stream(s);
+ init_stream(s, 8192);
+ if (xrdp_iso_init(self->iso_layer, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ out_uint8(s, ((MCS_AUCF << 2) | 2));
+ out_uint8s(s, 1);
+ out_uint16_be(s, self->userid);
+ s_mark_end(s);
+ if (xrdp_iso_send(self->iso_layer, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ free_stream(s);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+static int APP_CC
+xrdp_mcs_recv_cjrq(struct xrdp_mcs* self)
+{
+ int opcode;
+ struct stream* s;
+
+ make_stream(s);
+ init_stream(s, 8192);
+ if (xrdp_iso_recv(self->iso_layer, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ in_uint8(s, opcode);
+ if ((opcode >> 2) != MCS_CJRQ)
+ {
+ free_stream(s);
+ return 1;
+ }
+ in_uint8s(s, 4);
+ if (opcode & 2)
+ {
+ in_uint8s(s, 2);
+ }
+ if (!(s_check_end(s)))
+ {
+ free_stream(s);
+ return 1;
+ }
+ free_stream(s);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+static int APP_CC
+xrdp_mcs_ber_out_header(struct xrdp_mcs* self, struct stream* s,
+ int tag_val, int len)
+{
+ if (tag_val > 0xff)
+ {
+ out_uint16_be(s, tag_val);
+ }
+ else
+ {
+ out_uint8(s, tag_val);
+ }
+ if (len >= 0x80)
+ {
+ out_uint8(s, 0x82);
+ out_uint16_be(s, len);
+ }
+ else
+ {
+ out_uint8(s, len);
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+static int APP_CC
+xrdp_mcs_ber_out_int8(struct xrdp_mcs* self, struct stream* s, int value)
+{
+ xrdp_mcs_ber_out_header(self, s, BER_TAG_INTEGER, 1);
+ out_uint8(s, value);
+ return 0;
+}
+
+#if 0 /* not used */
+/*****************************************************************************/
+/* returns error */
+static int APP_CC
+xrdp_mcs_ber_out_int16(struct xrdp_mcs* self, struct stream* s, int value)
+{
+ xrdp_mcs_ber_out_header(self, s, BER_TAG_INTEGER, 2);
+ out_uint8(s, (value >> 8));
+ out_uint8(s, value);
+ return 0;
+}
+#endif
+
+/*****************************************************************************/
+/* returns error */
+static int APP_CC
+xrdp_mcs_ber_out_int24(struct xrdp_mcs* self, struct stream* s, int value)
+{
+ xrdp_mcs_ber_out_header(self, s, BER_TAG_INTEGER, 3);
+ out_uint8(s, (value >> 16));
+ out_uint8(s, (value >> 8));
+ out_uint8(s, value);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+static int APP_CC
+xrdp_mcs_out_domain_params(struct xrdp_mcs* self, struct stream* s,
+ int max_channels,
+ int max_users, int max_tokens,
+ int max_pdu_size)
+{
+ xrdp_mcs_ber_out_header(self, s, MCS_TAG_DOMAIN_PARAMS, 26);
+ xrdp_mcs_ber_out_int8(self, s, max_channels);
+ xrdp_mcs_ber_out_int8(self, s, max_users);
+ xrdp_mcs_ber_out_int8(self, s, max_tokens);
+ xrdp_mcs_ber_out_int8(self, s, 1);
+ xrdp_mcs_ber_out_int8(self, s, 0);
+ xrdp_mcs_ber_out_int8(self, s, 1);
+ xrdp_mcs_ber_out_int24(self, s, max_pdu_size);
+ xrdp_mcs_ber_out_int8(self, s, 2);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+static int APP_CC
+xrdp_mcs_send_connect_response(struct xrdp_mcs* self)
+{
+ int data_len;
+ struct stream* s;
+
+ make_stream(s);
+ init_stream(s, 8192);
+ data_len = self->server_mcs_data->end - self->server_mcs_data->data;
+ xrdp_iso_init(self->iso_layer, s);
+ xrdp_mcs_ber_out_header(self, s, MCS_CONNECT_RESPONSE, 313);
+ xrdp_mcs_ber_out_header(self, s, BER_TAG_RESULT, 1);
+ out_uint8(s, 0);
+ xrdp_mcs_ber_out_header(self, s, BER_TAG_INTEGER, 1);
+ out_uint8(s, 0);
+ xrdp_mcs_out_domain_params(self, s, 2, 2, 0, 0xffff);
+ xrdp_mcs_ber_out_header(self, s, BER_TAG_OCTET_STRING, data_len);
+ /* mcs data */
+ out_uint8a(s, self->server_mcs_data->data, data_len);
+ s_mark_end(s);
+ if (xrdp_iso_send(self->iso_layer, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ free_stream(s);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+xrdp_mcs_incoming(struct xrdp_mcs* self)
+{
+ DEBUG((" in xrdp_mcs_incoming\n\r"));
+ if (xrdp_iso_incoming(self->iso_layer) != 0)
+ {
+ return 1;
+ }
+ if (xrdp_mcs_recv_connect_initial(self) != 0)
+ {
+ return 1;
+ }
+ if (xrdp_mcs_send_connect_response(self) != 0)
+ {
+ return 1;
+ }
+ if (xrdp_mcs_recv_edrq(self) != 0)
+ {
+ return 1;
+ }
+ if (xrdp_mcs_recv_aurq(self) != 0)
+ {
+ return 1;
+ }
+ if (xrdp_mcs_send_aucf(self) != 0)
+ {
+ return 1;
+ }
+ if (xrdp_mcs_recv_cjrq(self) != 0)
+ {
+ return 1;
+ }
+ if (xrdp_mcs_send_cjcf(self, self->userid + MCS_USERCHANNEL_BASE) != 0)
+ {
+ return 1;
+ }
+ if (xrdp_mcs_recv_cjrq(self) != 0)
+ {
+ return 1;
+ }
+ if (xrdp_mcs_send_cjcf(self, MCS_GLOBAL_CHANNEL) != 0)
+ {
+ return 1;
+ }
+ DEBUG((" out xrdp_mcs_incoming\n\r"));
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+xrdp_mcs_init(struct xrdp_mcs* self, struct stream* s)
+{
+ xrdp_iso_init(self->iso_layer, s);
+ s_push_layer(s, mcs_hdr, 8);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+xrdp_mcs_send(struct xrdp_mcs* self, struct stream* s)
+{
+ int len;
+
+ DEBUG((" in xrdp_mcs_send\n\r"));
+ s_pop_layer(s, mcs_hdr);
+ len = (s->end - s->p) - 8;
+ len = len | 0x8000;
+ out_uint8(s, MCS_SDIN << 2);
+ out_uint16_be(s, self->userid);
+ out_uint16_be(s, MCS_GLOBAL_CHANNEL);
+ out_uint8(s, 0x70);
+ out_uint16_be(s, len);
+ if (xrdp_iso_send(self->iso_layer, s) != 0)
+ {
+ return 1;
+ }
+ DEBUG((" out xrdp_mcs_send\n\r"));
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+xrdp_mcs_disconnect(struct xrdp_mcs* self)
+{
+ struct stream* s;
+
+ make_stream(s);
+ init_stream(s, 8192);
+ if (xrdp_iso_init(self->iso_layer, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ out_uint8(s, (MCS_DPUM << 2) | 1);
+ out_uint8(s, 0x80);
+ s_mark_end(s);
+ if (xrdp_iso_send(self->iso_layer, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ free_stream(s);
+ return 0;
+}
diff --git a/libxrdp/xrdp_orders.c b/libxrdp/xrdp_orders.c
new file mode 100644
index 00000000..4ee7cae0
--- /dev/null
+++ b/libxrdp/xrdp_orders.c
@@ -0,0 +1,1553 @@
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ xrdp: A Remote Desktop Protocol server.
+ Copyright (C) Jay Sorg 2004-2005
+
+ orders
+
+*/
+
+#include "libxrdp.h"
+
+/*****************************************************************************/
+struct xrdp_orders* APP_CC
+xrdp_orders_create(struct xrdp_session* session, struct xrdp_rdp* rdp_layer)
+{
+ struct xrdp_orders* self;
+
+ self = (struct xrdp_orders*)g_malloc(sizeof(struct xrdp_orders), 1);
+ self->session = session;
+ self->rdp_layer = rdp_layer;
+ make_stream(self->out_s);
+ init_stream(self->out_s, 8192);
+ return self;
+}
+
+/*****************************************************************************/
+void APP_CC
+xrdp_orders_delete(struct xrdp_orders* self)
+{
+ if (self == 0)
+ {
+ return;
+ }
+ free_stream(self->out_s);
+ g_free(self);
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+xrdp_orders_init(struct xrdp_orders* self)
+{
+ self->order_level++;
+ if (self->order_level == 1)
+ {
+ self->order_count = 0;
+ /* is this big enough */
+ if (xrdp_rdp_init_data(self->rdp_layer, self->out_s) != 0)
+ {
+ return 1;
+ }
+ out_uint16_le(self->out_s, RDP_UPDATE_ORDERS);
+ out_uint8s(self->out_s, 2); /* pad */
+ self->order_count_ptr = self->out_s->p;
+ out_uint8s(self->out_s, 2); /* number of orders, set later */
+ out_uint8s(self->out_s, 2); /* pad */
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+xrdp_orders_send(struct xrdp_orders* self)
+{
+ int rv;
+
+ rv = 0;
+ if (self->order_level > 0)
+ {
+ self->order_level--;
+ if (self->order_level == 0 && self->order_count > 0)
+ {
+ s_mark_end(self->out_s);
+ DEBUG(("xrdp_orders_send sending %d orders\n\r", self->order_count));
+ self->order_count_ptr[0] = self->order_count;
+ self->order_count_ptr[1] = self->order_count >> 8;
+ if (xrdp_rdp_send_data(self->rdp_layer, self->out_s,
+ RDP_DATA_PDU_UPDATE) != 0)
+ {
+ rv = 1;
+ }
+ }
+ }
+ return rv;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+xrdp_orders_force_send(struct xrdp_orders* self)
+{
+ if (self->order_count > 0)
+ {
+ s_mark_end(self->out_s);
+ DEBUG(("xrdp_orders_force_send sending %d orders\n\r", self->order_count));
+ self->order_count_ptr[0] = self->order_count;
+ self->order_count_ptr[1] = self->order_count >> 8;
+ if (xrdp_rdp_send_data(self->rdp_layer, self->out_s,
+ RDP_DATA_PDU_UPDATE) != 0)
+ {
+ return 1;
+ }
+ }
+ self->order_count = 0;
+ self->order_level = 0;
+ return 0;
+}
+
+/*****************************************************************************/
+/* check if the current order will fix in packet size of 8192, if not */
+/* send what we got and init a new one */
+/* returns error */
+static int APP_CC
+xrdp_orders_check(struct xrdp_orders* self, int max_size)
+{
+ int size;
+
+ if (self->order_level < 1)
+ {
+ if (max_size > 8000)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ size = self->out_s->p - self->order_count_ptr;
+ if (size < 0 || size > 8192)
+ {
+ return 1;
+ }
+ if (size + max_size + 100 > 8000)
+ {
+ xrdp_orders_force_send(self);
+ xrdp_orders_init(self);
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* check if rect is the same as the last one sent */
+/* returns boolean */
+static int APP_CC
+xrdp_orders_last_bounds(struct xrdp_orders* self, struct xrdp_rect* rect)
+{
+ if (rect == 0)
+ {
+ return 0;
+ }
+ if (rect->left == self->clip_left &&
+ rect->top == self->clip_top &&
+ rect->right == self->clip_right &&
+ rect->bottom == self->clip_bottom)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* check if all coords are withing 256 bytes */
+/* returns boolean */
+static int APP_CC
+xrdp_orders_send_delta(struct xrdp_orders* self, int* vals, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i += 2)
+ {
+ if (g_abs(vals[i] - vals[i + 1]) >= 128)
+ {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*****************************************************************************/
+/* returns error */
+static int APP_CC
+xrdp_orders_out_bounds(struct xrdp_orders* self, struct xrdp_rect* rect)
+{
+ char* bounds_flags_ptr;
+ int bounds_flags;
+
+ bounds_flags = 0;
+ bounds_flags_ptr = self->out_s->p;
+ out_uint8s(self->out_s, 1);
+ /* left */
+ if (rect->left == self->clip_left)
+ {
+ }
+ else if (g_abs(rect->left - self->clip_left) < 128)
+ {
+ bounds_flags |= 0x10;
+ }
+ else
+ {
+ bounds_flags |= 0x01;
+ }
+ /* top */
+ if (rect->top == self->clip_top)
+ {
+ }
+ else if (g_abs(rect->top - self->clip_top) < 128)
+ {
+ bounds_flags |= 0x20;
+ }
+ else
+ {
+ bounds_flags |= 0x02;
+ }
+ /* right */
+ if (rect->right == self->clip_right)
+ {
+ }
+ else if (g_abs(rect->right - self->clip_right) < 128)
+ {
+ bounds_flags |= 0x40;
+ }
+ else
+ {
+ bounds_flags |= 0x04;
+ }
+ /* bottom */
+ if (rect->bottom == self->clip_bottom)
+ {
+ }
+ else if (g_abs(rect->bottom - self->clip_bottom) < 128)
+ {
+ bounds_flags |= 0x80;
+ }
+ else
+ {
+ bounds_flags |= 0x08;
+ }
+ /* left */
+ if (bounds_flags & 0x01)
+ {
+ out_uint16_le(self->out_s, rect->left);
+ }
+ else if (bounds_flags & 0x10)
+ {
+ out_uint8(self->out_s, rect->left - self->clip_left);
+ }
+ self->clip_left = rect->left;
+ /* top */
+ if (bounds_flags & 0x02)
+ {
+ out_uint16_le(self->out_s, rect->top);
+ }
+ else if (bounds_flags & 0x20)
+ {
+ out_uint8(self->out_s, rect->top - self->clip_top);
+ }
+ self->clip_top = rect->top;
+ /* right */
+ if (bounds_flags & 0x04)
+ {
+ out_uint16_le(self->out_s, rect->right);
+ }
+ else if (bounds_flags & 0x40)
+ {
+ out_uint8(self->out_s, rect->right - self->clip_right);
+ }
+ self->clip_right = rect->right;
+ /* bottom */
+ if (bounds_flags & 0x08)
+ {
+ out_uint16_le(self->out_s, rect->bottom);
+ }
+ else if (bounds_flags & 0x80)
+ {
+ out_uint8(self->out_s, rect->bottom - self->clip_bottom);
+ }
+ self->clip_bottom = rect->bottom;
+ /* set flags */
+ *bounds_flags_ptr = bounds_flags;
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+/* send a solid rect to client */
+/* max size 23 */
+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 order_flags;
+ int vals[8];
+ int present;
+ char* present_ptr;
+
+ xrdp_orders_check(self, 23);
+ self->order_count++;
+ order_flags = RDP_ORDER_STANDARD;
+ if (self->last_order != RDP_ORDER_RECT)
+ {
+ order_flags |= RDP_ORDER_CHANGE;
+ }
+ self->last_order = RDP_ORDER_RECT;
+ if (rect != 0)
+ {
+ order_flags |= RDP_ORDER_BOUNDS;
+ if (xrdp_orders_last_bounds(self, rect))
+ {
+ order_flags |= RDP_ORDER_LASTBOUNDS;
+ }
+ }
+ vals[0] = x;
+ vals[1] = self->rect_x;
+ vals[2] = y;
+ vals[3] = self->rect_y;
+ vals[4] = cx;
+ vals[5] = self->rect_cx;
+ vals[6] = cy;
+ vals[7] = self->rect_cy;
+ if (xrdp_orders_send_delta(self, vals, 8))
+ {
+ order_flags |= RDP_ORDER_DELTA;
+ }
+ out_uint8(self->out_s, order_flags)
+ if (order_flags & RDP_ORDER_CHANGE)
+ {
+ out_uint8(self->out_s, self->last_order);
+ }
+ present = 0;
+ present_ptr = self->out_s->p; /* hold 1 byte present pointer */
+ out_uint8s(self->out_s, 1)
+ if ((order_flags & RDP_ORDER_BOUNDS) &&
+ !(order_flags & RDP_ORDER_LASTBOUNDS))
+ {
+ xrdp_orders_out_bounds(self, rect);
+ }
+ if (x != self->rect_x)
+ {
+ present |= 0x01;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, x - self->rect_x);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, x);
+ }
+ self->rect_x = x;
+ }
+ if (y != self->rect_y)
+ {
+ present |= 0x02;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, y - self->rect_y);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, y);
+ }
+ self->rect_y = y;
+ }
+ if (cx != self->rect_cx)
+ {
+ present |= 0x04;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, cx - self->rect_cx);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, cx);
+ }
+ self->rect_cx = cx;
+ }
+ if (cy != self->rect_cy)
+ {
+ present |= 0x08;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, cy - self->rect_cy);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, cy);
+ }
+ self->rect_cy = cy;
+ }
+ if ((color & 0xff) != (self->rect_color & 0xff))
+ {
+ present |= 0x10;
+ self->rect_color = (self->rect_color & 0xffff00) | (color & 0xff);
+ out_uint8(self->out_s, color);
+ }
+ if ((color & 0xff00) != (self->rect_color & 0xff00))
+ {
+ present |= 0x20;
+ self->rect_color = (self->rect_color & 0xff00ff) | (color & 0xff00);
+ out_uint8(self->out_s, color >> 8);
+ }
+ if ((color & 0xff0000) != (self->rect_color & 0xff0000))
+ {
+ present |= 0x40;
+ self->rect_color = (self->rect_color & 0x00ffff) | (color & 0xff0000);
+ out_uint8(self->out_s, color >> 16);
+ }
+ present_ptr[0] = present;
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+/* send a screen blt order */
+/* max size 25 */
+int APP_CC
+xrdp_orders_screen_blt(struct xrdp_orders* self, int x, int y,
+ int cx, int cy, int srcx, int srcy,
+ int rop, struct xrdp_rect* rect)
+{
+ int order_flags;
+ int vals[12];
+ int present;
+ char* present_ptr;
+
+ xrdp_orders_check(self, 25);
+ self->order_count++;
+ order_flags = RDP_ORDER_STANDARD;
+ if (self->last_order != RDP_ORDER_SCREENBLT)
+ {
+ order_flags |= RDP_ORDER_CHANGE;
+ }
+ self->last_order = RDP_ORDER_SCREENBLT;
+ if (rect != 0)
+ {
+ order_flags |= RDP_ORDER_BOUNDS;
+ if (xrdp_orders_last_bounds(self, rect))
+ {
+ order_flags |= RDP_ORDER_LASTBOUNDS;
+ }
+ }
+ vals[0] = x;
+ vals[1] = self->scr_blt_x;
+ vals[2] = y;
+ vals[3] = self->scr_blt_y;
+ vals[4] = cx;
+ vals[5] = self->scr_blt_cx;
+ vals[6] = cy;
+ vals[7] = self->scr_blt_cy;
+ vals[8] = srcx;
+ vals[9] = self->scr_blt_srcx;
+ vals[10] = srcy;
+ vals[11] = self->scr_blt_srcy;
+ if (xrdp_orders_send_delta(self, vals, 12))
+ {
+ order_flags |= RDP_ORDER_DELTA;
+ }
+ out_uint8(self->out_s, order_flags);
+ if (order_flags & RDP_ORDER_CHANGE)
+ {
+ out_uint8(self->out_s, self->last_order);
+ }
+ present = 0;
+ present_ptr = self->out_s->p; /* hold 1 byte present pointer */
+ out_uint8s(self->out_s, 1)
+ if ((order_flags & RDP_ORDER_BOUNDS) &&
+ !(order_flags & RDP_ORDER_LASTBOUNDS))
+ {
+ xrdp_orders_out_bounds(self, rect);
+ }
+ if (x != self->scr_blt_x)
+ {
+ present |= 0x01;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, x - self->scr_blt_x);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, x);
+ }
+ self->scr_blt_x = x;
+ }
+ if (y != self->scr_blt_y)
+ {
+ present |= 0x02;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, y - self->scr_blt_y);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, y);
+ }
+ self->scr_blt_y = y;
+ }
+ if (cx != self->scr_blt_cx)
+ {
+ present |= 0x04;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, cx - self->scr_blt_cx);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, cx);
+ }
+ self->scr_blt_cx = cx;
+ }
+ if (cy != self->scr_blt_cy)
+ {
+ present |= 0x08;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, cy - self->scr_blt_cy);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, cy);
+ }
+ self->scr_blt_cy = cy;
+ }
+ if (rop != self->scr_blt_rop)
+ {
+ present |= 0x10;
+ out_uint8(self->out_s, rop);
+ self->scr_blt_rop = rop;
+ }
+ if (srcx != self->scr_blt_srcx)
+ {
+ present |= 0x20;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, srcx - self->scr_blt_srcx);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, srcx);
+ }
+ self->scr_blt_srcx = srcx;
+ }
+ if (srcy != self->scr_blt_srcy)
+ {
+ present |= 0x40;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, srcy - self->scr_blt_srcy)
+ }
+ else
+ {
+ out_uint16_le(self->out_s, srcy)
+ }
+ self->scr_blt_srcy = srcy;
+ }
+ present_ptr[0] = present;
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+/* send a pat blt order */
+/* max size 39 */
+int APP_CC
+xrdp_orders_pat_blt(struct xrdp_orders* self, int x, int y,
+ int cx, int cy, int rop, int bg_color,
+ int fg_color, struct xrdp_brush* brush,
+ struct xrdp_rect* rect)
+{
+ int order_flags;
+ int vals[8];
+ int present;
+ char* present_ptr;
+ struct xrdp_brush blank_brush;
+
+ xrdp_orders_check(self, 39);
+ self->order_count++;
+ order_flags = RDP_ORDER_STANDARD;
+ if (self->last_order != RDP_ORDER_PATBLT)
+ {
+ order_flags |= RDP_ORDER_CHANGE;
+ }
+ self->last_order = RDP_ORDER_PATBLT;
+ if (rect != 0)
+ {
+ order_flags |= RDP_ORDER_BOUNDS;
+ if (xrdp_orders_last_bounds(self, rect))
+ {
+ order_flags |= RDP_ORDER_LASTBOUNDS;
+ }
+ }
+ vals[0] = x;
+ vals[1] = self->pat_blt_x;
+ vals[2] = y;
+ vals[3] = self->pat_blt_y;
+ vals[4] = cx;
+ vals[5] = self->pat_blt_cx;
+ vals[6] = cy;
+ vals[7] = self->pat_blt_cy;
+ if (xrdp_orders_send_delta(self, vals, 8))
+ {
+ order_flags |= RDP_ORDER_DELTA;
+ }
+ out_uint8(self->out_s, order_flags);
+ if (order_flags & RDP_ORDER_CHANGE)
+ {
+ out_uint8(self->out_s, self->last_order);
+ }
+ present = 0;
+ present_ptr = self->out_s->p; /* hold 2 byte present pointer, todo */
+ out_uint8s(self->out_s, 2) /* this can be smaller, */
+ /* see RDP_ORDER_SMALL and RDP_ORDER_TINY */
+ if ((order_flags & RDP_ORDER_BOUNDS) &&
+ !(order_flags & RDP_ORDER_LASTBOUNDS))
+ {
+ xrdp_orders_out_bounds(self, rect);
+ }
+ if (x != self->pat_blt_x)
+ {
+ present |= 0x0001;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, x - self->pat_blt_x);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, x);
+ }
+ self->pat_blt_x = x;
+ }
+ if (y != self->pat_blt_y)
+ {
+ present |= 0x0002;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, y - self->pat_blt_y);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, y);
+ }
+ self->pat_blt_y = y;
+ }
+ if (cx != self->pat_blt_cx)
+ {
+ present |= 0x0004;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, cx - self->pat_blt_cx);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, cx);
+ }
+ self->pat_blt_cx = cx;
+ }
+ if (cy != self->pat_blt_cy)
+ {
+ present |= 0x0008;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, cy - self->pat_blt_cy);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, cy);
+ }
+ self->pat_blt_cy = cy;
+ }
+ if (rop != self->pat_blt_rop)
+ {
+ present |= 0x0010;
+ /* PATCOPY PATPAINT PATINVERT DSTINVERT BLACKNESS WHITENESS */
+ out_uint8(self->out_s, rop);
+ self->pat_blt_rop = rop;
+ }
+ if (bg_color != self->pat_blt_bg_color)
+ {
+ present |= 0x0020;
+ out_uint8(self->out_s, bg_color);
+ out_uint8(self->out_s, bg_color >> 8);
+ out_uint8(self->out_s, bg_color >> 16);
+ self->pat_blt_bg_color = bg_color;
+ }
+ if (fg_color != self->pat_blt_fg_color)
+ {
+ present |= 0x0040;
+ out_uint8(self->out_s, fg_color);
+ out_uint8(self->out_s, fg_color >> 8);
+ out_uint8(self->out_s, fg_color >> 16);
+ self->pat_blt_fg_color = fg_color;
+ }
+ if (brush == 0) /* if nil use blank one */
+ { /* todo can we just set style to zero */
+ g_memset(&blank_brush, 0, sizeof(struct xrdp_brush));
+ brush = &blank_brush;
+ }
+ if (brush->x_orgin != self->pat_blt_brush.x_orgin)
+ {
+ present |= 0x0080;
+ out_uint8(self->out_s, brush->x_orgin);
+ self->pat_blt_brush.x_orgin = brush->x_orgin;
+ }
+ if (brush->y_orgin != self->pat_blt_brush.y_orgin)
+ {
+ present |= 0x0100;
+ out_uint8(self->out_s, brush->y_orgin);
+ self->pat_blt_brush.y_orgin = brush->y_orgin;
+ }
+ if (brush->style != self->pat_blt_brush.style)
+ {
+ present |= 0x0200;
+ out_uint8(self->out_s, brush->style);
+ self->pat_blt_brush.style = brush->style;
+ }
+ if (brush->pattern[0] != self->pat_blt_brush.pattern[0])
+ {
+ present |= 0x0400;
+ out_uint8(self->out_s, brush->pattern[0]);
+ self->pat_blt_brush.pattern[0] = brush->pattern[0];
+ }
+ if (g_memcmp(brush->pattern + 1, self->pat_blt_brush.pattern + 1, 7) != 0)
+ {
+ present |= 0x0800;
+ out_uint8a(self->out_s, brush->pattern + 1, 7);
+ g_memcpy(self->pat_blt_brush.pattern + 1, brush->pattern + 1, 7);
+ }
+ present_ptr[0] = present;
+ present_ptr[1] = present >> 8;
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+/* send a dest blt order */
+/* max size 21 */
+int APP_CC
+xrdp_orders_dest_blt(struct xrdp_orders* self, int x, int y,
+ int cx, int cy, int rop,
+ struct xrdp_rect* rect)
+{
+ int order_flags;
+ int vals[8];
+ int present;
+ char* present_ptr;
+
+ xrdp_orders_check(self, 21);
+ self->order_count++;
+ order_flags = RDP_ORDER_STANDARD;
+ if (self->last_order != RDP_ORDER_DESTBLT)
+ {
+ order_flags |= RDP_ORDER_CHANGE;
+ }
+ self->last_order = RDP_ORDER_DESTBLT;
+ if (rect != 0)
+ {
+ order_flags |= RDP_ORDER_BOUNDS;
+ if (xrdp_orders_last_bounds(self, rect))
+ {
+ order_flags |= RDP_ORDER_LASTBOUNDS;
+ }
+ }
+ vals[0] = x;
+ vals[1] = self->dest_blt_x;
+ vals[2] = y;
+ vals[3] = self->dest_blt_y;
+ vals[4] = cx;
+ vals[5] = self->dest_blt_cx;
+ vals[6] = cy;
+ vals[7] = self->dest_blt_cy;
+ if (xrdp_orders_send_delta(self, vals, 8))
+ {
+ order_flags |= RDP_ORDER_DELTA;
+ }
+ out_uint8(self->out_s, order_flags);
+ if (order_flags & RDP_ORDER_CHANGE)
+ {
+ out_uint8(self->out_s, self->last_order)
+ }
+ present = 0;
+ present_ptr = self->out_s->p; /* hold 1 byte present pointer */
+ out_uint8s(self->out_s, 1)
+ if ((order_flags & RDP_ORDER_BOUNDS) &&
+ !(order_flags & RDP_ORDER_LASTBOUNDS))
+ {
+ xrdp_orders_out_bounds(self, rect);
+ }
+ if (x != self->dest_blt_x)
+ {
+ present |= 0x01;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, x - self->dest_blt_x);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, x);
+ }
+ self->dest_blt_x = x;
+ }
+ if (y != self->dest_blt_y)
+ {
+ present |= 0x02;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, y - self->dest_blt_y);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, y);
+ }
+ self->dest_blt_y = y;
+ }
+ if (cx != self->dest_blt_cx)
+ {
+ present |= 0x04;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, cx - self->dest_blt_cx);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, cx);
+ }
+ self->dest_blt_cx = cx;
+ }
+ if (cy != self->dest_blt_cy)
+ {
+ present |= 0x08;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, cy - self->dest_blt_cy);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, cy);
+ }
+ self->dest_blt_cy = cy;
+ }
+ if (rop != self->dest_blt_rop)
+ {
+ present |= 0x10;
+ out_uint8(self->out_s, rop);
+ self->dest_blt_rop = rop;
+ }
+ present_ptr[0] = present;
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+/* send a line order */
+/* max size 32 */
+int APP_CC
+xrdp_orders_line(struct xrdp_orders* self, int mix_mode,
+ int startx, int starty,
+ int endx, int endy, int rop, int bg_color,
+ struct xrdp_pen* pen,
+ struct xrdp_rect* rect)
+{
+ int order_flags;
+ int vals[8];
+ int present;
+ char* present_ptr;
+ struct xrdp_pen blank_pen;
+
+ xrdp_orders_check(self, 32);
+ self->order_count++;
+ order_flags = RDP_ORDER_STANDARD;
+ if (self->last_order != RDP_ORDER_LINE)
+ {
+ order_flags |= RDP_ORDER_CHANGE;
+ }
+ self->last_order = RDP_ORDER_LINE;
+ if (rect != 0)
+ {
+ order_flags |= RDP_ORDER_BOUNDS;
+ if (xrdp_orders_last_bounds(self, rect))
+ {
+ order_flags |= RDP_ORDER_LASTBOUNDS;
+ }
+ }
+ vals[0] = startx;
+ vals[1] = self->line_startx;
+ vals[2] = starty;
+ vals[3] = self->line_starty;
+ vals[4] = endx;
+ vals[5] = self->line_endx;
+ vals[6] = endy;
+ vals[7] = self->line_endy;
+ if (xrdp_orders_send_delta(self, vals, 8))
+ {
+ order_flags |= RDP_ORDER_DELTA;
+ }
+ out_uint8(self->out_s, order_flags);
+ if (order_flags & RDP_ORDER_CHANGE)
+ {
+ out_uint8(self->out_s, self->last_order);
+ }
+ present = 0;
+ present_ptr = self->out_s->p; /* hold 2 byte present pointer */
+ out_uint8s(self->out_s, 2)
+ if ((order_flags & RDP_ORDER_BOUNDS) &&
+ !(order_flags & RDP_ORDER_LASTBOUNDS))
+ {
+ xrdp_orders_out_bounds(self, rect);
+ }
+ if (mix_mode != self->line_mix_mode)
+ {
+ present |= 0x0001;
+ out_uint16_le(self->out_s, mix_mode)
+ self->line_mix_mode = mix_mode;
+ }
+ if (startx != self->line_startx)
+ {
+ present |= 0x0002;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, startx - self->line_startx);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, startx);
+ }
+ self->line_startx = startx;
+ }
+ if (starty != self->line_starty)
+ {
+ present |= 0x0004;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, starty - self->line_starty);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, starty);
+ }
+ self->line_starty = starty;
+ }
+ if (endx != self->line_endx)
+ {
+ present |= 0x0008;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, endx - self->line_endx);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, endx);
+ }
+ self->line_endx = endx;
+ }
+ if (endy != self->line_endy)
+ {
+ present |= 0x0010;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, endy - self->line_endy);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, endy);
+ }
+ self->line_endy = endy;
+ }
+ if (bg_color != self->line_bg_color)
+ {
+ present |= 0x0020;
+ out_uint8(self->out_s, bg_color)
+ out_uint8(self->out_s, bg_color >> 8)
+ out_uint8(self->out_s, bg_color >> 16)
+ self->line_bg_color = bg_color;
+ }
+ if (rop != self->line_rop)
+ {
+ present |= 0x0040;
+ out_uint8(self->out_s, rop)
+ self->line_rop = rop;
+ }
+ if (pen == 0)
+ {
+ g_memset(&blank_pen, 0, sizeof(struct xrdp_pen));
+ pen = &blank_pen;
+ }
+ if (pen->style != self->line_pen.style)
+ {
+ present |= 0x0080;
+ out_uint8(self->out_s, pen->style)
+ self->line_pen.style = pen->style;
+ }
+ if (pen->width != self->line_pen.width)
+ {
+ present |= 0x0100;
+ out_uint8(self->out_s, pen->width)
+ self->line_pen.width = pen->width;
+ }
+ if (pen->color != self->line_pen.color)
+ {
+ present |= 0x0200;
+ out_uint8(self->out_s, pen->color)
+ out_uint8(self->out_s, pen->color >> 8)
+ out_uint8(self->out_s, pen->color >> 16)
+ self->line_pen.color = pen->color;
+ }
+ present_ptr[0] = present;
+ present_ptr[1] = present >> 8;
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+/* send a mem blt order */
+/* max size 30 */
+int APP_CC
+xrdp_orders_mem_blt(struct xrdp_orders* self, int cache_id,
+ int color_table, int x, int y, int cx, int cy,
+ int rop, int srcx, int srcy,
+ int cache_idx, struct xrdp_rect* rect)
+{
+ int order_flags;
+ int vals[12];
+ int present;
+ char* present_ptr;
+
+ xrdp_orders_check(self, 30);
+ self->order_count++;
+ order_flags = RDP_ORDER_STANDARD;
+ if (self->last_order != RDP_ORDER_MEMBLT)
+ {
+ order_flags |= RDP_ORDER_CHANGE;
+ }
+ self->last_order = RDP_ORDER_MEMBLT;
+ if (rect != 0)
+ {
+ order_flags |= RDP_ORDER_BOUNDS;
+ if (xrdp_orders_last_bounds(self, rect))
+ {
+ order_flags |= RDP_ORDER_LASTBOUNDS;
+ }
+ }
+ vals[0] = x;
+ vals[1] = self->mem_blt_x;
+ vals[2] = y;
+ vals[3] = self->mem_blt_y;
+ vals[4] = cx;
+ vals[5] = self->mem_blt_cx;
+ vals[6] = cy;
+ vals[7] = self->mem_blt_cy;
+ vals[8] = srcx;
+ vals[9] = self->mem_blt_srcx;
+ vals[10] = srcy;
+ vals[11] = self->mem_blt_srcy;
+ if (xrdp_orders_send_delta(self, vals, 12))
+ {
+ order_flags |= RDP_ORDER_DELTA;
+ }
+ out_uint8(self->out_s, order_flags);
+ if (order_flags & RDP_ORDER_CHANGE)
+ {
+ out_uint8(self->out_s, self->last_order)
+ }
+ present = 0;
+ present_ptr = self->out_s->p; /* hold 2 byte present pointer, todo */
+ out_uint8s(self->out_s, 2) /* this can be smaller, */
+ /* see RDP_ORDER_SMALL and RDP_ORDER_TINY */
+ if ((order_flags & RDP_ORDER_BOUNDS) &&
+ !(order_flags & RDP_ORDER_LASTBOUNDS))
+ {
+ xrdp_orders_out_bounds(self, rect);
+ }
+ if (cache_id != self->mem_blt_cache_id ||
+ color_table != self->mem_blt_color_table)
+ {
+ present |= 0x0001;
+ out_uint8(self->out_s, cache_id);
+ out_uint8(self->out_s, color_table);
+ self->mem_blt_cache_id = cache_id;
+ self->mem_blt_color_table = color_table;
+ }
+ if (x != self->mem_blt_x)
+ {
+ present |= 0x0002;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, x - self->mem_blt_x);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, x);
+ }
+ self->mem_blt_x = x;
+ }
+ if (y != self->mem_blt_y)
+ {
+ present |= 0x0004;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, y - self->mem_blt_y);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, y);
+ }
+ self->mem_blt_y = y;
+ }
+ if (cx != self->mem_blt_cx)
+ {
+ present |= 0x0008;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, cx - self->mem_blt_cx);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, cx);
+ }
+ self->mem_blt_cx = cx;
+ }
+ if (cy != self->mem_blt_cy)
+ {
+ present |= 0x0010;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, cy - self->mem_blt_cy);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, cy);
+ }
+ self->mem_blt_cy = cy;
+ }
+ if (rop != self->mem_blt_rop)
+ {
+ present |= 0x0020;
+ out_uint8(self->out_s, rop);
+ self->mem_blt_rop = rop;
+ }
+ if (srcx != self->mem_blt_srcx)
+ {
+ present |= 0x0040;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, srcx - self->mem_blt_srcx);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, srcx);
+ }
+ self->mem_blt_srcx = srcx;
+ }
+ if (srcy != self->mem_blt_srcy)
+ {
+ present |= 0x0080;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, srcy - self->mem_blt_srcy);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, srcy);
+ }
+ self->mem_blt_srcy = srcy;
+ }
+ if (cache_idx != self->mem_blt_cache_idx)
+ {
+ present |= 0x0100;
+ out_uint16_le(self->out_s, cache_idx);
+ self->mem_blt_cache_idx = cache_idx;
+ }
+ present_ptr[0] = present;
+ present_ptr[1] = present >> 8;
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+xrdp_orders_text(struct xrdp_orders* self,
+ int font, int flags, int mixmode,
+ int fg_color, int bg_color,
+ int clip_left, int clip_top,
+ int clip_right, int clip_bottom,
+ int box_left, int box_top,
+ int box_right, int box_bottom,
+ int x, int y, char* data, int data_len,
+ struct xrdp_rect* rect)
+{
+ int order_flags;
+ int present;
+ char* present_ptr;
+
+ xrdp_orders_check(self, 100);
+ self->order_count++;
+ order_flags = RDP_ORDER_STANDARD;
+ if (self->last_order != RDP_ORDER_TEXT2)
+ {
+ order_flags |= RDP_ORDER_CHANGE;
+ }
+ self->last_order = RDP_ORDER_TEXT2;
+ if (rect != 0)
+ {
+ order_flags |= RDP_ORDER_BOUNDS;
+ if (xrdp_orders_last_bounds(self, rect))
+ {
+ order_flags |= RDP_ORDER_LASTBOUNDS;
+ }
+ }
+ out_uint8(self->out_s, order_flags);
+ if (order_flags & RDP_ORDER_CHANGE)
+ {
+ out_uint8(self->out_s, self->last_order);
+ }
+ present = 0;
+ present_ptr = self->out_s->p; /* hold 3 byte present pointer, todo */
+ out_uint8s(self->out_s, 3) /* this can be smaller, */
+ /* see RDP_ORDER_SMALL and RDP_ORDER_TINY */
+ if ((order_flags & RDP_ORDER_BOUNDS) &&
+ !(order_flags & RDP_ORDER_LASTBOUNDS))
+ {
+ xrdp_orders_out_bounds(self, rect);
+ }
+ if (font != self->text_font)
+ {
+ present |= 0x000001;
+ out_uint8(self->out_s, font);
+ self->text_font = font;
+ }
+ if (flags != self->text_flags)
+ {
+ present |= 0x000002;
+ out_uint8(self->out_s, flags);
+ self->text_flags = flags;
+ }
+ /* unknown */
+ if (mixmode != self->text_mixmode)
+ {
+ present |= 0x000008;
+ out_uint8(self->out_s, mixmode);
+ self->text_mixmode = mixmode;
+ }
+ if (fg_color != self->text_fg_color)
+ {
+ present |= 0x000010;
+ out_uint8(self->out_s, fg_color)
+ out_uint8(self->out_s, fg_color >> 8)
+ out_uint8(self->out_s, fg_color >> 16)
+ self->text_fg_color = fg_color;
+ }
+ if (bg_color != self->text_bg_color)
+ {
+ present |= 0x000020;
+ out_uint8(self->out_s, bg_color)
+ out_uint8(self->out_s, bg_color >> 8)
+ out_uint8(self->out_s, bg_color >> 16)
+ self->text_bg_color = bg_color;
+ }
+ if (clip_left != self->text_clip_left)
+ {
+ present |= 0x000040;
+ out_uint16_le(self->out_s, clip_left);
+ self->text_clip_left = clip_left;
+ }
+ if (clip_top != self->text_clip_top)
+ {
+ present |= 0x000080;
+ out_uint16_le(self->out_s, clip_top);
+ self->text_clip_top = clip_top;
+ }
+ if (clip_right != self->text_clip_right)
+ {
+ present |= 0x000100;
+ out_uint16_le(self->out_s, clip_right);
+ self->text_clip_right = clip_right;
+ }
+ if (clip_bottom != self->text_clip_bottom)
+ {
+ present |= 0x000200;
+ out_uint16_le(self->out_s, clip_bottom);
+ self->text_clip_bottom = clip_bottom;
+ }
+ if (box_left != self->text_box_left)
+ {
+ present |= 0x000400;
+ out_uint16_le(self->out_s, box_left);
+ self->text_box_left = box_left;
+ }
+ if (box_top != self->text_box_top)
+ {
+ present |= 0x000800;
+ out_uint16_le(self->out_s, box_top);
+ self->text_box_top = box_top;
+ }
+ if (box_right != self->text_box_right)
+ {
+ present |= 0x001000;
+ out_uint16_le(self->out_s, box_right);
+ self->text_box_right = box_right;
+ }
+ if (box_bottom != self->text_box_bottom)
+ {
+ present |= 0x002000;
+ out_uint16_le(self->out_s, box_bottom);
+ self->text_box_bottom = box_bottom;
+ }
+ if (x != self->text_x)
+ {
+ present |= 0x080000;
+ out_uint16_le(self->out_s, x);
+ self->text_x = x;
+ }
+ if (y != self->text_y)
+ {
+ present |= 0x100000;
+ out_uint16_le(self->out_s, y);
+ self->text_y = y;
+ }
+ {
+ /* always send text */
+ present |= 0x200000;
+ out_uint8(self->out_s, data_len);
+ out_uint8a(self->out_s, data, data_len);
+ }
+ /* send 3 byte present */
+ present_ptr[0] = present;
+ present_ptr[1] = present >> 8;
+ present_ptr[2] = present >> 16;
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+/* when a palette gets sent, send the main palette too */
+int APP_CC
+xrdp_orders_send_palette(struct xrdp_orders* self, int* palette,
+ int cache_id)
+{
+ int order_flags;
+ int len;
+ int i;
+
+ xrdp_orders_check(self, 2000);
+ self->order_count++;
+ order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY;
+ out_uint8(self->out_s, order_flags);
+ len = 1027 - 7; /* length after type minus 7 */
+ out_uint16_le(self->out_s, len);
+ out_uint16_le(self->out_s, 0); /* flags */
+ out_uint8(self->out_s, RDP_ORDER_COLCACHE); /* type */
+ out_uint8(self->out_s, cache_id);
+ out_uint16_le(self->out_s, 256); /* num colors */
+ for (i = 0; i < 256; i++)
+ {
+ out_uint8(self->out_s, palette[i]);
+ out_uint8(self->out_s, palette[i] >> 8);
+ out_uint8(self->out_s, palette[i] >> 16);
+ out_uint8(self->out_s, 0);
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+/* max size width * height * Bpp + 16 */
+int APP_CC
+xrdp_orders_send_raw_bitmap(struct xrdp_orders* self,
+ int width, int height, int bpp, char* data,
+ int cache_id, int cache_idx)
+{
+ int order_flags;
+ int len;
+ int bufsize;
+ int Bpp;
+ int i;
+ int j;
+ int pixel;
+ int e;
+
+ e = width % 4;
+ if (e != 0)
+ {
+ e = 4 - e;
+ }
+ Bpp = (bpp + 7) / 8;
+ bufsize = (width + e) * height * Bpp;
+ xrdp_orders_check(self, bufsize + 16);
+ self->order_count++;
+ order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY;
+ out_uint8(self->out_s, order_flags);
+ len = (bufsize + 9) - 7; /* length after type minus 7 */
+ out_uint16_le(self->out_s, len);
+ out_uint16_le(self->out_s, 8); /* flags */
+ out_uint8(self->out_s, RDP_ORDER_RAW_BMPCACHE); /* type */
+ out_uint8(self->out_s, cache_id);
+ out_uint8s(self->out_s, 1); /* pad */
+ out_uint8(self->out_s, width + e);
+ out_uint8(self->out_s, height);
+ out_uint8(self->out_s, bpp);
+ out_uint16_le(self->out_s, bufsize);
+ out_uint16_le(self->out_s, cache_idx);
+ for (i = height - 1; i >= 0; i--)
+ {
+ for (j = 0; j < width; j++)
+ {
+ if (Bpp == 3)
+ {
+ pixel = GETPIXEL32(data, j, i, width);
+ out_uint8(self->out_s, pixel >> 16);
+ out_uint8(self->out_s, pixel >> 8);
+ out_uint8(self->out_s, pixel);
+ }
+ else if (Bpp == 2)
+ {
+ pixel = GETPIXEL16(data, j, i, width);
+ out_uint8(self->out_s, pixel);
+ out_uint8(self->out_s, pixel >> 8);
+ }
+ else if (Bpp == 1)
+ {
+ pixel = GETPIXEL8(data, j, i, width);
+ out_uint8(self->out_s, pixel);
+ }
+ }
+ for (j = 0; j < e; j++)
+ {
+ out_uint8s(self->out_s, Bpp);
+ }
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+/* max size width * height * Bpp + 16 */
+int APP_CC
+xrdp_orders_send_bitmap(struct xrdp_orders* self,
+ int width, int height, int bpp, char* data,
+ int cache_id, int cache_idx)
+{
+ int order_flags;
+ int len;
+ int bufsize;
+ int Bpp;
+ int i;
+ int lines_sending;
+ int e;
+ struct stream* s;
+ struct stream* temp_s;
+ char* p;
+
+ if (width > 64)
+ {
+ g_printf("error, width > 64\n\r");
+ return 1;
+ }
+ if (height > 64)
+ {
+ g_printf("error, height > 64\n\r");
+ return 1;
+ }
+ e = width % 4;
+ if (e != 0)
+ {
+ e = 4 - e;
+ }
+ make_stream(s);
+ init_stream(s, 8192);
+ make_stream(temp_s);
+ init_stream(temp_s, 8192);
+ p = s->p;
+ i = height;
+ lines_sending = xrdp_bitmap_compress(data, width, height, s, bpp, 8192,
+ i - 1, temp_s, e);
+ if (lines_sending != height)
+ {
+ free_stream(s);
+ free_stream(temp_s);
+ g_printf("error in xrdp_orders_send_bitmap, lines_sending(%d) != \
+height(%d)\n\r", lines_sending, height);
+ return 1;
+ }
+ bufsize = s->p - p;
+ Bpp = (bpp + 7) / 8;
+ xrdp_orders_check(self, bufsize + 16);
+ self->order_count++;
+ order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY;
+ out_uint8(self->out_s, order_flags);
+ len = (bufsize + 9 + 8) - 7; /* length after type minus 7 */
+ out_uint16_le(self->out_s, len);
+ out_uint16_le(self->out_s, 8); /* flags */
+ out_uint8(self->out_s, RDP_ORDER_BMPCACHE); /* type */
+ out_uint8(self->out_s, cache_id);
+ out_uint8s(self->out_s, 1); /* pad */
+ out_uint8(self->out_s, width + e);
+ out_uint8(self->out_s, height);
+ out_uint8(self->out_s, bpp);
+ out_uint16_le(self->out_s, bufsize + 8);
+ out_uint16_le(self->out_s, cache_idx);
+ out_uint8s(self->out_s, 2); /* pad */
+ out_uint16_le(self->out_s, bufsize);
+ out_uint16_le(self->out_s, (width + e) * Bpp); /* line size */
+ out_uint16_le(self->out_s, (width + e) *
+ Bpp * height); /* final size */
+ out_uint8a(self->out_s, s->data, bufsize);
+ free_stream(s);
+ free_stream(temp_s);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+/* max size datasize + 18*/
+/* todo, only sends one for now */
+int APP_CC
+xrdp_orders_send_font(struct xrdp_orders* self,
+ struct xrdp_font_char* font_char,
+ int font_index, int char_index)
+{
+ int order_flags;
+ int datasize;
+ int len;
+
+ datasize = FONT_DATASIZE(font_char);
+ xrdp_orders_check(self, datasize + 18);
+ self->order_count++;
+ order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY;
+ out_uint8(self->out_s, order_flags);
+ len = (datasize + 12) - 7; /* length after type minus 7 */
+ out_uint16_le(self->out_s, len);
+ out_uint16_le(self->out_s, 8); /* flags */
+ out_uint8(self->out_s, RDP_ORDER_FONTCACHE); /* type */
+ out_uint8(self->out_s, font_index);
+ out_uint8(self->out_s, 1); /* num of chars */
+ out_uint16_le(self->out_s, char_index);
+ out_uint16_le(self->out_s, font_char->offset);
+ out_uint16_le(self->out_s, font_char->baseline);
+ out_uint16_le(self->out_s, font_char->width);
+ out_uint16_le(self->out_s, font_char->height);
+ out_uint8a(self->out_s, font_char->data, datasize);
+ return 0;
+}
diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c
new file mode 100644
index 00000000..155e109c
--- /dev/null
+++ b/libxrdp/xrdp_rdp.c
@@ -0,0 +1,847 @@
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ xrdp: A Remote Desktop Protocol server.
+ Copyright (C) Jay Sorg 2004-2005
+
+ rdp layer
+
+*/
+
+#include "libxrdp.h"
+
+static char unknown1[172] =
+{ 0xff, 0x02, 0xb6, 0x00, 0x28, 0x00, 0x00, 0x00,
+ 0x27, 0x00, 0x27, 0x00, 0x03, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x26, 0x00, 0x01, 0x00, 0x1e, 0x00,
+ 0x02, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x1d, 0x00,
+ 0x04, 0x00, 0x27, 0x00, 0x05, 0x00, 0x0b, 0x00,
+ 0x06, 0x00, 0x28, 0x00, 0x08, 0x00, 0x21, 0x00,
+ 0x09, 0x00, 0x20, 0x00, 0x0a, 0x00, 0x22, 0x00,
+ 0x0b, 0x00, 0x25, 0x00, 0x0c, 0x00, 0x24, 0x00,
+ 0x0d, 0x00, 0x23, 0x00, 0x0e, 0x00, 0x19, 0x00,
+ 0x0f, 0x00, 0x16, 0x00, 0x10, 0x00, 0x15, 0x00,
+ 0x11, 0x00, 0x1c, 0x00, 0x12, 0x00, 0x1b, 0x00,
+ 0x13, 0x00, 0x1a, 0x00, 0x14, 0x00, 0x17, 0x00,
+ 0x15, 0x00, 0x18, 0x00, 0x16, 0x00, 0x0e, 0x00,
+ 0x18, 0x00, 0x0c, 0x00, 0x19, 0x00, 0x0d, 0x00,
+ 0x1a, 0x00, 0x12, 0x00, 0x1b, 0x00, 0x14, 0x00,
+ 0x1f, 0x00, 0x13, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x21, 0x00, 0x0a, 0x00, 0x22, 0x00, 0x06, 0x00,
+ 0x23, 0x00, 0x07, 0x00, 0x24, 0x00, 0x08, 0x00,
+ 0x25, 0x00, 0x09, 0x00, 0x26, 0x00, 0x04, 0x00,
+ 0x27, 0x00, 0x03, 0x00, 0x28, 0x00, 0x02, 0x00,
+ 0x29, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x05, 0x00,
+ 0x2b, 0x00, 0x2a, 0x00 };
+
+/*****************************************************************************/
+static int APP_CC
+xrdp_rdp_read_config(struct xrdp_client_info* client_info)
+{
+ int fd;
+ int index;
+ struct list* items;
+ struct list* values;
+ char* item;
+ char* value;
+
+ fd = g_file_open("xrdp.ini");
+ if (fd > 0)
+ {
+ items = list_create();
+ items->auto_free = 1;
+ values = list_create();
+ values->auto_free = 1;
+ file_read_section(fd, "globals", items, values);
+ for (index = 0; index < items->count; index++)
+ {
+ item = (char*)list_get_item(items, index);
+ value = (char*)list_get_item(values, index);
+ if (g_strcmp(item, "bitmap_cache") == 0)
+ {
+ if (g_strcmp(value, "yes") == 0)
+ {
+ client_info->use_bitmap_cache = 1;
+ }
+ }
+ else if (g_strcmp(item, "bitmap_compression") == 0)
+ {
+ if (g_strcmp(value, "yes") == 0)
+ {
+ client_info->use_bitmap_comp = 1;
+ }
+ }
+ }
+ list_delete(items);
+ list_delete(values);
+ g_file_close(fd);
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+struct xrdp_rdp* APP_CC
+xrdp_rdp_create(struct xrdp_session* session, int sck)
+{
+ struct xrdp_rdp* self;
+
+ self = (struct xrdp_rdp*)g_malloc(sizeof(struct xrdp_rdp), 1);
+ self->session = session;
+ self->share_id = 66538;
+ self->sec_layer = xrdp_sec_create(self, sck);
+ /* read ini settings */
+ xrdp_rdp_read_config(&self->client_info);
+ return self;
+}
+
+/*****************************************************************************/
+void APP_CC
+xrdp_rdp_delete(struct xrdp_rdp* self)
+{
+ if (self == 0)
+ {
+ return;
+ }
+ xrdp_sec_delete(self->sec_layer);
+ g_free(self);
+}
+
+/*****************************************************************************/
+int APP_CC
+xrdp_rdp_init(struct xrdp_rdp* self, struct stream* s)
+{
+ if (xrdp_sec_init(self->sec_layer, s) != 0)
+ {
+ return 1;
+ }
+ s_push_layer(s, rdp_hdr, 6);
+ return 0;
+}
+
+/*****************************************************************************/
+int APP_CC
+xrdp_rdp_init_data(struct xrdp_rdp* self, struct stream* s)
+{
+ if (xrdp_sec_init(self->sec_layer, s) != 0)
+ {
+ return 1;
+ }
+ s_push_layer(s, rdp_hdr, 18);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns erros */
+int APP_CC
+xrdp_rdp_recv(struct xrdp_rdp* self, struct stream* s, int* code)
+{
+ int error;
+ int len;
+ int pdu_code;
+ int chan;
+
+ DEBUG(("in xrdp_rdp_recv\n\r"));
+ if (s->next_packet == 0 || s->next_packet >= s->end)
+ {
+ chan = 0;
+ error = xrdp_sec_recv(self->sec_layer, s, &chan);
+ if (error == -1) /* special code for send demand active */
+ {
+ s->next_packet = 0;
+ *code = -1;
+ DEBUG(("out xrdp_rdp_recv\n\r"));
+ return 0;
+ }
+ if (error != 0)
+ {
+ DEBUG(("out xrdp_rdp_recv error\n\r"));
+ return 1;
+ }
+ if (chan != MCS_GLOBAL_CHANNEL && chan > 0)
+ {
+ s->next_packet = 0;
+ *code = 0;
+ DEBUG(("out xrdp_rdp_recv\n\r"));
+ return 0;
+ }
+ s->next_packet = s->p;
+ }
+ else
+ {
+ s->p = s->next_packet;
+ }
+ in_uint16_le(s, len);
+ if (len == 0x8000)
+ {
+ s->next_packet += 8;
+ *code = 0;
+ DEBUG(("out xrdp_rdp_recv\n\r"));
+ return 0;
+ }
+ 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\n\r"));
+ return 0;
+}
+
+/*****************************************************************************/
+int APP_CC
+xrdp_rdp_send(struct xrdp_rdp* self, struct stream* s, int pdu_type)
+{
+ int len;
+
+ DEBUG(("in xrdp_rdp_send\n\r"));
+ s_pop_layer(s, rdp_hdr);
+ len = s->end - s->p;
+ out_uint16_le(s, len);
+ out_uint16_le(s, 0x10 | pdu_type);
+ out_uint16_le(s, self->mcs_channel);
+ if (xrdp_sec_send(self->sec_layer, s, 0) != 0)
+ {
+ DEBUG(("out xrdp_rdp_send error\n\r"));
+ return 1;
+ }
+ DEBUG(("out xrdp_rdp_send\n\r"));
+ return 0;
+}
+
+/*****************************************************************************/
+int APP_CC
+xrdp_rdp_send_data(struct xrdp_rdp* self, struct stream* s,
+ int data_pdu_type)
+{
+ int len;
+
+ DEBUG(("in xrdp_rdp_send_data\n\r"));
+ s_pop_layer(s, rdp_hdr);
+ len = s->end - s->p;
+ out_uint16_le(s, len);
+ out_uint16_le(s, 0x10 | RDP_PDU_DATA);
+ out_uint16_le(s, self->mcs_channel);
+ out_uint32_le(s, self->share_id);
+ out_uint8(s, 0);
+ out_uint8(s, 1);
+ out_uint16_le(s, len - 14);
+ out_uint8(s, data_pdu_type);
+ out_uint8(s, 0);
+ out_uint16_le(s, 0);
+ if (xrdp_sec_send(self->sec_layer, s, 0) != 0)
+ {
+ DEBUG(("out xrdp_rdp_send_data error\n\r"));
+ return 1;
+ }
+ DEBUG(("out xrdp_rdp_send_data\n\r"));
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+xrdp_rdp_parse_client_mcs_data(struct xrdp_rdp* self)
+{
+ struct stream* p;
+ int i;
+
+ p = &self->sec_layer->client_mcs_data;
+ p->p = p->data;
+ in_uint8s(p, 31);
+ in_uint16_le(p, self->client_info.width);
+ in_uint16_le(p, self->client_info.height);
+ in_uint8s(p, 120);
+ self->client_info.bpp = 8;
+ in_uint16_le(p, i);
+ switch (i)
+ {
+ case 0xca01:
+ in_uint8s(p, 6);
+ in_uint8(p, i);
+ if (i > 8)
+ {
+ self->client_info.bpp = i;
+ }
+ break;
+ case 0xca02:
+ self->client_info.bpp = 15;
+ break;
+ case 0xca03:
+ self->client_info.bpp = 16;
+ break;
+ case 0xca04:
+ self->client_info.bpp = 24;
+ break;
+ }
+ p->p = p->data;
+ DEBUG(("client width %d, client height %d bpp %d\n\r",
+ self->client_info.width, self->client_info.height,
+ self->client_info.bpp));
+ return 0;
+}
+
+/*****************************************************************************/
+int APP_CC
+xrdp_rdp_incoming(struct xrdp_rdp* self)
+{
+ DEBUG(("in xrdp_rdp_incoming\n\r"));
+ if (xrdp_sec_incoming(self->sec_layer) != 0)
+ {
+ return 1;
+ }
+ self->mcs_channel = self->sec_layer->mcs_layer->userid +
+ MCS_USERCHANNEL_BASE;
+ xrdp_rdp_parse_client_mcs_data(self);
+ DEBUG(("out xrdp_rdp_incoming mcs channel %d\n\r", self->mcs_channel));
+ return 0;
+}
+
+/*****************************************************************************/
+int APP_CC
+xrdp_rdp_send_demand_active(struct xrdp_rdp* self)
+{
+ struct stream* s;
+
+ make_stream(s);
+ init_stream(s, 8192);
+ if (xrdp_rdp_init(self, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+
+ out_uint32_le(s, self->share_id);
+ out_uint32_be(s, 0x04000401);
+ out_uint32_be(s, 0x524e5300);
+ out_uint32_be(s, 0x08000000);
+ out_uint32_be(s, 0x09000800);
+ out_uint16_le(s, self->mcs_channel);
+ out_uint16_be(s, 0xb5e2);
+
+ /* Output general capability set */
+ out_uint16_le(s, RDP_CAPSET_GENERAL); /* 1 */
+ out_uint16_le(s, RDP_CAPLEN_GENERAL); /* 24(0x18) */
+ out_uint16_le(s, 1); /* OS major type */
+ out_uint16_le(s, 3); /* OS minor type */
+ out_uint16_le(s, 0x200); /* Protocol version */
+ out_uint16_le(s, 0); /* pad */
+ out_uint16_le(s, 0); /* Compression types */
+ out_uint16_le(s, 0); /* pad */
+ out_uint16_le(s, 0); /* Update capability */
+ out_uint16_le(s, 0); /* Remote unshare capability */
+ out_uint16_le(s, 0); /* Compression level */
+ out_uint16_le(s, 0); /* Pad */
+
+ /* Output bitmap capability set */
+ out_uint16_le(s, RDP_CAPSET_BITMAP); /* 2 */
+ out_uint16_le(s, RDP_CAPLEN_BITMAP); /* 28(0x1c) */
+ out_uint16_le(s, self->client_info.bpp); /* Preferred BPP */
+ out_uint16_le(s, 1); /* Receive 1 BPP */
+ out_uint16_le(s, 1); /* Receive 4 BPP */
+ out_uint16_le(s, 1); /* Receive 8 BPP */
+ out_uint16_le(s, self->client_info.width); /* width */
+ out_uint16_le(s, self->client_info.height); /* height */
+ out_uint16_le(s, 0); /* Pad */
+ out_uint16_le(s, 1); /* Allow resize */
+ out_uint16_le(s, 1); /* bitmap compression */
+ out_uint16_le(s, 0); /* unknown */
+ out_uint16_le(s, 0); /* unknown */
+ out_uint16_le(s, 0); /* pad */
+
+ /* Output ? */
+ out_uint16_le(s, 14);
+ out_uint16_le(s, 4);
+
+ /* Output order capability set */
+ out_uint16_le(s, RDP_CAPSET_ORDER); /* 3 */
+ out_uint16_le(s, RDP_CAPLEN_ORDER); /* 88(0x58) */
+ out_uint8s(s, 16);
+ out_uint32_be(s, 0x40420f00);
+ out_uint16_le(s, 1); /* Cache X granularity */
+ out_uint16_le(s, 20); /* Cache Y granularity */
+ out_uint16_le(s, 0); /* Pad */
+ out_uint16_le(s, 1); /* Max order level */
+ out_uint16_le(s, 0x2f); /* Number of fonts */
+ out_uint16_le(s, 0x22); /* Capability flags */
+ /* caps */
+ out_uint8(s, 1); /* dest blt */
+ out_uint8(s, 1); /* pat blt */
+ out_uint8(s, 1); /* screen blt */
+ out_uint8(s, 1); /* memblt */
+ out_uint8(s, 1);
+ out_uint8(s, 1);
+ out_uint8(s, 1);
+ out_uint8(s, 1);
+ out_uint8(s, 1);
+ out_uint8(s, 1);
+ out_uint8(s, 1);
+ out_uint8(s, 1);
+ out_uint8(s, 1);
+ out_uint8(s, 0);
+ out_uint8(s, 0);
+ out_uint8(s, 1);
+ out_uint8(s, 1);
+ out_uint8(s, 1);
+ out_uint8(s, 1);
+ out_uint8(s, 1);
+ out_uint8(s, 1);
+ out_uint8(s, 1);
+ out_uint8(s, 1);
+ out_uint8(s, 1);
+ out_uint8(s, 1);
+ out_uint8(s, 1);
+ out_uint8(s, 1);
+ out_uint8(s, 1);
+ out_uint8(s, 1);
+ out_uint8(s, 0);
+ out_uint8(s, 0);
+ out_uint8(s, 0);
+ out_uint16_le(s, 0x6a1);
+ out_uint8s(s, 6); /* ? */
+ out_uint32_le(s, 0x0f4240); /* desk save */
+ out_uint32_le(s, 0); /* ? */
+ out_uint32_le(s, 0); /* ? */
+
+ /* Output color cache capability set */
+ out_uint16_le(s, RDP_CAPSET_COLCACHE);
+ out_uint16_le(s, RDP_CAPLEN_COLCACHE);
+ out_uint16_le(s, 6); /* cache size */
+ out_uint16_le(s, 0); /* pad */
+
+ /* Output pointer capability set */
+ out_uint16_le(s, RDP_CAPSET_POINTER);
+ out_uint16_le(s, RDP_CAPLEN_POINTER);
+ out_uint16_le(s, 1); /* Colour pointer */
+ out_uint16_le(s, 0x19); /* Cache size */
+
+ /* Output ? */
+ out_uint16_le(s, 0xd);
+ out_uint16_le(s, 0x58); /* 88 */
+ out_uint8(s, 1);
+ out_uint8s(s, 83);
+
+ s_mark_end(s);
+
+ if (xrdp_rdp_send(self, s, RDP_PDU_DEMAND_ACTIVE) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+
+ free_stream(s);
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+xrdp_process_capset_general(struct xrdp_rdp* self, struct stream* s,
+ int len)
+{
+ int i;
+
+ in_uint8s(s, 10);
+ in_uint16_le(s, i);
+ self->client_info.use_compact_packets = (i != 0);
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+xrdp_process_capset_order(struct xrdp_rdp* self, struct stream* s,
+ int len)
+{
+ int i;
+
+ in_uint8s(s, 72);
+ in_uint32_le(s, i); /* desktop cache size, usually 0x38400 */
+ self->client_info.desktop_cache = i;
+ return 0;
+}
+
+/*****************************************************************************/
+/* get the bitmap cache size */
+static int APP_CC
+xrdp_process_capset_bmpcache(struct xrdp_rdp* self, struct stream* s,
+ int len)
+{
+ in_uint8s(s, 24);
+ in_uint16_le(s, self->client_info.cache1_entries);
+ in_uint16_le(s, self->client_info.cache1_size);
+ in_uint16_le(s, self->client_info.cache2_entries);
+ in_uint16_le(s, self->client_info.cache2_size);
+ in_uint16_le(s, self->client_info.cache3_entries);
+ in_uint16_le(s, self->client_info.cache3_size);
+ return 0;
+}
+
+/*****************************************************************************/
+/* get the number of client cursor cache */
+static int APP_CC
+xrdp_process_capset_pointercache(struct xrdp_rdp* self, struct stream* s,
+ int len)
+{
+ int i;
+
+ in_uint8s(s, 2); /* color pointer */
+ in_uint16_le(s, i);
+ i = MIN(i, 32);
+ self->client_info.pointer_cache_entries = i;
+ return 0;
+}
+
+/*****************************************************************************/
+int APP_CC
+xrdp_rdp_process_confirm_active(struct xrdp_rdp* self, struct stream* s)
+{
+ int cap_len;
+ int source_len;
+ int num_caps;
+ int index;
+ int type;
+ int len;
+ char* p;
+
+ in_uint8s(s, 4); /* rdp_shareid */
+ in_uint8s(s, 2); /* userid */
+ in_uint16_le(s, source_len); /* sizeof RDP_SOURCE */
+ in_uint16_le(s, cap_len);
+ in_uint8s(s, source_len);
+ in_uint16_le(s, num_caps);
+ in_uint8s(s, 2); /* pad */
+ for (index = 0; index < num_caps; index++)
+ {
+ p = s->p;
+ in_uint16_le(s, type);
+ in_uint16_le(s, len);
+ switch (type)
+ {
+ case RDP_CAPSET_GENERAL: /* 1 */
+ xrdp_process_capset_general(self, s, len);
+ break;
+ case RDP_CAPSET_ORDER: /* 3 */
+ xrdp_process_capset_order(self, s, len);
+ break;
+ case RDP_CAPSET_BMPCACHE: /* 4 */
+ xrdp_process_capset_bmpcache(self, s, len);
+ break;
+ case RDP_CAPSET_POINTER: /* 8 */
+ xrdp_process_capset_pointercache(self, s, len);
+ break;
+ }
+ s->p = p + len;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+xrdp_rdp_process_data_pointer(struct xrdp_rdp* self, struct stream* s)
+{
+ return 0;
+}
+
+/*****************************************************************************/
+/* RDP_DATA_PDU_INPUT */
+static int APP_CC
+xrdp_rdp_process_data_input(struct xrdp_rdp* self, struct stream* s)
+{
+ int num_events;
+ int index;
+ int msg_type;
+ int device_flags;
+ int param1;
+ int param2;
+ int time;
+
+ in_uint16_le(s, num_events);
+ in_uint8s(s, 2); /* pad */
+ DEBUG(("xrdp_rdp_process_data_input %d events\n\r", num_events));
+ for (index = 0; index < num_events; index++)
+ {
+ in_uint32_le(s, time);
+ in_uint16_le(s, msg_type);
+ in_uint16_le(s, device_flags);
+ in_sint16_le(s, param1);
+ in_sint16_le(s, param2);
+ DEBUG(("xrdp_rdp_process_data_input event %4.4x flags %4.4x param1 %d \
+param2 %d time %d\n\r", msg_type, device_flags, param1, param2, time));
+ if (self->session->callback != 0)
+ {
+ /* msg_type can be
+ RDP_INPUT_SYNCHRONIZE - 0
+ RDP_INPUT_SCANCODE - 4
+ RDP_INPUT_MOUSE - 0x8001 */
+ self->session->callback(self->session->id, msg_type, param1, param2,
+ device_flags, time);
+ }
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+xrdp_rdp_send_synchronise(struct xrdp_rdp* self)
+{
+ struct stream* s;
+
+ make_stream(s);
+ init_stream(s, 8192);
+ if (xrdp_rdp_init_data(self, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ out_uint16_le(s, 1);
+ out_uint16_le(s, 1002);
+ s_mark_end(s);
+ if (xrdp_rdp_send_data(self, s, RDP_DATA_PDU_SYNCHRONISE) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ free_stream(s);
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+xrdp_rdp_send_control(struct xrdp_rdp* self, int action)
+{
+ struct stream* s;
+
+ make_stream(s);
+ init_stream(s, 8192);
+ if (xrdp_rdp_init_data(self, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ out_uint16_le(s, action);
+ out_uint16_le(s, 0); /* userid */
+ out_uint32_le(s, 1002); /* control id */
+ s_mark_end(s);
+ if (xrdp_rdp_send_data(self, s, RDP_DATA_PDU_CONTROL) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ free_stream(s);
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+xrdp_rdp_process_data_control(struct xrdp_rdp* self, struct stream* s)
+{
+ int action;
+
+ in_uint16_le(s, action);
+ in_uint8s(s, 2); /* user id */
+ in_uint8s(s, 4); /* control id */
+ if (action == RDP_CTL_REQUEST_CONTROL)
+ {
+ xrdp_rdp_send_synchronise(self);
+ xrdp_rdp_send_control(self, RDP_CTL_COOPERATE);
+ xrdp_rdp_send_control(self, RDP_CTL_GRANT_CONTROL);
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+xrdp_rdp_process_data_sync(struct xrdp_rdp* self)
+{
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+xrdp_rdp_process_screen_update(struct xrdp_rdp* self, struct stream* s)
+{
+ int op;
+ int left;
+ int top;
+ int right;
+ int bottom;
+ int cx;
+ int cy;
+
+ in_uint32_le(s, op);
+ in_uint16_le(s, left);
+ in_uint16_le(s, top);
+ in_uint16_le(s, right);
+ in_uint16_le(s, bottom);
+ cx = (right - left) + 1;
+ cy = (bottom - top) + 1;
+ if (self->session->callback != 0)
+ {
+ self->session->callback(self->session->id, 0x4444, left, top, cx, cy);
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+xrdp_rdp_send_unknown1(struct xrdp_rdp* self)
+{
+ struct stream* s;
+
+ make_stream(s);
+ init_stream(s, 8192);
+ if (xrdp_rdp_init_data(self, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ out_uint8a(s, unknown1, 172);
+ s_mark_end(s);
+ if (xrdp_rdp_send_data(self, s, 0x28) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ free_stream(s);
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+xrdp_rdp_process_data_font(struct xrdp_rdp* self, struct stream* s)
+{
+ int seq;
+
+ in_uint8s(s, 2); /* num of fonts */
+ in_uint8s(s, 2); /* unknown */
+ in_uint16_le(s, seq);
+ /* 419 client sends Seq 1, then 2 */
+ /* 2600 clients sends only Seq 3 */
+ if (seq == 2 || seq == 3) /* after second font message, we are up and */
+ { /* running */
+ xrdp_rdp_send_unknown1(self);
+ self->session->up_and_running = 1;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* sent 37 pdu */
+static int APP_CC
+xrdp_rdp_send_disconnect_query_response(struct xrdp_rdp* self)
+{
+ struct stream* s;
+
+ make_stream(s);
+ init_stream(s, 8192);
+ if (xrdp_rdp_init_data(self, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ s_mark_end(s);
+ if (xrdp_rdp_send_data(self, s, 37) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ free_stream(s);
+ return 0;
+}
+
+#if 0 /* not used */
+/*****************************************************************************/
+/* sent RDP_DATA_PDU_DISCONNECT 47 pdu */
+static int APP_CC
+xrdp_rdp_send_disconnect_reason(struct xrdp_rdp* self, int reason)
+{
+ struct stream* s;
+
+ make_stream(s);
+ init_stream(s, 8192);
+ if (xrdp_rdp_init_data(self, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ out_uint32_le(s, reason);
+ s_mark_end(s);
+ if (xrdp_rdp_send_data(self, s, RDP_DATA_PDU_DISCONNECT) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ free_stream(s);
+ return 0;
+}
+#endif
+
+/*****************************************************************************/
+/* RDP_PDU_DATA */
+int APP_CC
+xrdp_rdp_process_data(struct xrdp_rdp* self, struct stream* s)
+{
+ int len;
+ int data_type;
+ int ctype;
+ int clen;
+
+ in_uint8s(s, 6);
+ in_uint16_le(s, len);
+ in_uint8(s, data_type);
+ in_uint8(s, ctype);
+ in_uint16_le(s, clen);
+ DEBUG(("xrdp_rdp_process_data code %d\n\r", data_type));
+ switch (data_type)
+ {
+ case RDP_DATA_PDU_POINTER: /* 27 */
+ xrdp_rdp_process_data_pointer(self, s);
+ break;
+ case RDP_DATA_PDU_INPUT: /* 28 */
+ xrdp_rdp_process_data_input(self, s);
+ break;
+ case RDP_DATA_PDU_CONTROL: /* 20 */
+ xrdp_rdp_process_data_control(self, s);
+ break;
+ case RDP_DATA_PDU_SYNCHRONISE: /* 31 */
+ xrdp_rdp_process_data_sync(self);
+ break;
+ case 33: /* 33 ?? Invalidate an area I think */
+ xrdp_rdp_process_screen_update(self, s);
+ break;
+ case 35:
+ /* 35 ?? this comes when minimuzing a full screen mstsc.exe 2600 */
+ /* I think this is saying the client no longer wants screen */
+ /* updates and it will issue a 33 above to catch up */
+ /* so minimized apps don't take bandwidth */
+ break;
+ case 36: /* 36 ?? disconnect query? */
+ /* when this message comes, send a 37 back so the client */
+ /* is sure the connection is alive and it can ask if user */
+ /* really wants to disconnect */
+ xrdp_rdp_send_disconnect_query_response(self); /* send a 37 back */
+ break;
+ case RDP_DATA_PDU_FONT2: /* 39 */
+ xrdp_rdp_process_data_font(self, s);
+ break;
+ default:
+ g_printf("unknown in xrdp_rdp_process_data %d\n\r", data_type);
+ break;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+int APP_CC
+xrdp_rdp_disconnect(struct xrdp_rdp* self)
+{
+ return xrdp_sec_disconnect(self->sec_layer);
+}
diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c
new file mode 100644
index 00000000..0616b656
--- /dev/null
+++ b/libxrdp/xrdp_sec.c
@@ -0,0 +1,606 @@
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ xrdp: A Remote Desktop Protocol server.
+ Copyright (C) Jay Sorg 2004-2005
+
+ secure layer
+
+*/
+
+#include "libxrdp.h"
+
+static char pad_54[40] =
+{ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
+ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
+ 54, 54, 54, 54, 54, 54, 54, 54 };
+
+static char pad_92[48] =
+{ 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92 };
+
+static char pub_exp[4] = { 0x01, 0x00, 0x01, 0x00 };
+
+static char pub_mod[64] =
+{ 0x67, 0xab, 0x0e, 0x6a, 0x9f, 0xd6, 0x2b, 0xa3,
+ 0x32, 0x2f, 0x41, 0xd1, 0xce, 0xee, 0x61, 0xc3,
+ 0x76, 0x0b, 0x26, 0x11, 0x70, 0x48, 0x8a, 0x8d,
+ 0x23, 0x81, 0x95, 0xa0, 0x39, 0xf7, 0x5b, 0xaa,
+ 0x3e, 0xf1, 0xed, 0xb8, 0xc4, 0xee, 0xce, 0x5f,
+ 0x6a, 0xf5, 0x43, 0xce, 0x5f, 0x60, 0xca, 0x6c,
+ 0x06, 0x75, 0xae, 0xc0, 0xd6, 0xa4, 0x0c, 0x92,
+ 0xa4, 0xc6, 0x75, 0xea, 0x64, 0xb2, 0x50, 0x5b };
+
+static char pub_sig[64] =
+{ 0x6a, 0x41, 0xb1, 0x43, 0xcf, 0x47, 0x6f, 0xf1,
+ 0xe6, 0xcc, 0xa1, 0x72, 0x97, 0xd9, 0xe1, 0x85,
+ 0x15, 0xb3, 0xc2, 0x39, 0xa0, 0xa6, 0x26, 0x1a,
+ 0xb6, 0x49, 0x01, 0xfa, 0xa6, 0xda, 0x60, 0xd7,
+ 0x45, 0xf7, 0x2c, 0xee, 0xe4, 0x8e, 0x64, 0x2e,
+ 0x37, 0x49, 0xf0, 0x4c, 0x94, 0x6f, 0x08, 0xf5,
+ 0x63, 0x4c, 0x56, 0x29, 0x55, 0x5a, 0x63, 0x41,
+ 0x2c, 0x20, 0x65, 0x95, 0x99, 0xb1, 0x15, 0x7c };
+
+static char pri_exp[64] =
+{ 0x41, 0x93, 0x05, 0xB1, 0xF4, 0x38, 0xFC, 0x47,
+ 0x88, 0xC4, 0x7F, 0x83, 0x8C, 0xEC, 0x90, 0xDA,
+ 0x0C, 0x8A, 0xB5, 0xAE, 0x61, 0x32, 0x72, 0xF5,
+ 0x2B, 0xD1, 0x7B, 0x5F, 0x44, 0xC0, 0x7C, 0xBD,
+ 0x8A, 0x35, 0xFA, 0xAE, 0x30, 0xF6, 0xC4, 0x6B,
+ 0x55, 0xA7, 0x65, 0xEF, 0xF4, 0xB2, 0xAB, 0x18,
+ 0x4E, 0xAA, 0xE6, 0xDC, 0x71, 0x17, 0x3B, 0x4C,
+ 0xC2, 0x15, 0x4C, 0xF7, 0x81, 0xBB, 0xF0, 0x03 };
+
+static char lic1[322] =
+{ 0x80, 0x00, 0x3e, 0x01, 0x01, 0x02, 0x3e, 0x01,
+ 0x7b, 0x3c, 0x31, 0xa6, 0xae, 0xe8, 0x74, 0xf6,
+ 0xb4, 0xa5, 0x03, 0x90, 0xe7, 0xc2, 0xc7, 0x39,
+ 0xba, 0x53, 0x1c, 0x30, 0x54, 0x6e, 0x90, 0x05,
+ 0xd0, 0x05, 0xce, 0x44, 0x18, 0x91, 0x83, 0x81,
+ 0x00, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x00, 0x00,
+ 0x4d, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00,
+ 0x6f, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x66, 0x00,
+ 0x74, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6f, 0x00,
+ 0x72, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x72, 0x00,
+ 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00,
+ 0x6e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x32, 0x00, 0x33, 0x00, 0x36, 0x00, 0x00, 0x00,
+ 0x0d, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0xb8, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x5c, 0x00, 0x52, 0x53, 0x41, 0x31,
+ 0x48, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x3f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0xc7, 0xc9, 0xf7, 0x8e, 0x5a, 0x38, 0xe4,
+ 0x29, 0xc3, 0x00, 0x95, 0x2d, 0xdd, 0x4c, 0x3e,
+ 0x50, 0x45, 0x0b, 0x0d, 0x9e, 0x2a, 0x5d, 0x18,
+ 0x63, 0x64, 0xc4, 0x2c, 0xf7, 0x8f, 0x29, 0xd5,
+ 0x3f, 0xc5, 0x35, 0x22, 0x34, 0xff, 0xad, 0x3a,
+ 0xe6, 0xe3, 0x95, 0x06, 0xae, 0x55, 0x82, 0xe3,
+ 0xc8, 0xc7, 0xb4, 0xa8, 0x47, 0xc8, 0x50, 0x71,
+ 0x74, 0x29, 0x53, 0x89, 0x6d, 0x9c, 0xed, 0x70,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x48, 0x00, 0xa8, 0xf4, 0x31, 0xb9,
+ 0xab, 0x4b, 0xe6, 0xb4, 0xf4, 0x39, 0x89, 0xd6,
+ 0xb1, 0xda, 0xf6, 0x1e, 0xec, 0xb1, 0xf0, 0x54,
+ 0x3b, 0x5e, 0x3e, 0x6a, 0x71, 0xb4, 0xf7, 0x75,
+ 0xc8, 0x16, 0x2f, 0x24, 0x00, 0xde, 0xe9, 0x82,
+ 0x99, 0x5f, 0x33, 0x0b, 0xa9, 0xa6, 0x94, 0xaf,
+ 0xcb, 0x11, 0xc3, 0xf2, 0xdb, 0x09, 0x42, 0x68,
+ 0x29, 0x56, 0x58, 0x01, 0x56, 0xdb, 0x59, 0x03,
+ 0x69, 0xdb, 0x7d, 0x37, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x0e, 0x00, 0x0e, 0x00, 0x6d, 0x69, 0x63, 0x72,
+ 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x2e, 0x63, 0x6f,
+ 0x6d, 0x00 };
+
+static char lic2[20] =
+{ 0x80, 0x00, 0x10, 0x00, 0xff, 0x02, 0x10, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x28, 0x14, 0x00, 0x00 };
+
+/*****************************************************************************/
+struct xrdp_sec* APP_CC
+xrdp_sec_create(struct xrdp_rdp* owner, int sck)
+{
+ struct xrdp_sec* self;
+
+ self = (struct xrdp_sec*)g_malloc(sizeof(struct xrdp_sec), 1);
+ self->rdp_layer = owner;
+ self->rc4_key_size = 1;
+ self->decrypt_rc4_info = g_rc4_info_create();
+ self->encrypt_rc4_info = g_rc4_info_create();
+ g_random(self->server_random, 32);
+ self->mcs_layer = xrdp_mcs_create(self, sck, &self->client_mcs_data,
+ &self->server_mcs_data);
+ return self;
+}
+
+/*****************************************************************************/
+void APP_CC
+xrdp_sec_delete(struct xrdp_sec* self)
+{
+ if (self == 0)
+ {
+ return;
+ }
+ xrdp_mcs_delete(self->mcs_layer);
+ g_rc4_info_delete(self->decrypt_rc4_info);
+ g_rc4_info_delete(self->encrypt_rc4_info);
+ g_free(self->client_mcs_data.data);
+ g_free(self->server_mcs_data.data);
+ g_free(self);
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+xrdp_sec_init(struct xrdp_sec* self, struct stream* s)
+{
+ if (xrdp_mcs_init(self->mcs_layer, s) != 0)
+ {
+ return 1;
+ }
+ s_push_layer(s, sec_hdr, 4);
+ return 0;
+}
+
+/*****************************************************************************/
+/* Reduce key entropy from 64 to 40 bits */
+static void APP_CC
+xrdp_sec_make_40bit(char* key)
+{
+ key[0] = 0xd1;
+ key[1] = 0x26;
+ key[2] = 0x9e;
+}
+
+/*****************************************************************************/
+/* returns error */
+/* update an encryption key */
+static int APP_CC
+xrdp_sec_update(char* key, char* update_key, int key_len)
+{
+ char shasig[20];
+ void* sha1_info;
+ void* md5_info;
+ void* rc4_info;
+
+ sha1_info = g_sha1_info_create();
+ md5_info = g_md5_info_create();
+ rc4_info = g_rc4_info_create();
+ g_sha1_clear(sha1_info);
+ g_sha1_transform(sha1_info, update_key, key_len);
+ g_sha1_transform(sha1_info, pad_54, 40);
+ g_sha1_transform(sha1_info, key, key_len);
+ g_sha1_complete(sha1_info, shasig);
+ g_md5_clear(md5_info);
+ g_md5_transform(md5_info, update_key, key_len);
+ g_md5_transform(md5_info, pad_92, 48);
+ g_md5_transform(md5_info, shasig, 20);
+ g_md5_complete(md5_info, key);
+ g_rc4_set_key(rc4_info, key, key_len);
+ g_rc4_crypt(rc4_info, key, key_len);
+ if (key_len == 8)
+ {
+ xrdp_sec_make_40bit(key);
+ }
+ g_sha1_info_delete(sha1_info);
+ g_md5_info_delete(md5_info);
+ g_rc4_info_delete(rc4_info);
+ return 0;
+}
+
+/*****************************************************************************/
+static void APP_CC
+xrdp_sec_decrypt(struct xrdp_sec* self, char* data, int len)
+{
+ if (self->decrypt_use_count == 4096)
+ {
+ xrdp_sec_update(self->decrypt_key, self->decrypt_update_key,
+ self->rc4_key_len);
+ g_rc4_set_key(self->decrypt_rc4_info, self->decrypt_key,
+ self->rc4_key_len);
+ self->decrypt_use_count = 0;
+ }
+ g_rc4_crypt(self->decrypt_rc4_info, data, len);
+ self->decrypt_use_count++;
+}
+
+/*****************************************************************************/
+/* returns error */
+static int APP_CC
+xrdp_sec_process_logon_info(struct xrdp_sec* self, struct stream* s)
+{
+ int flags;
+ int len_domain;
+ int len_user;
+ int len_password;
+ int len_program;
+ int len_directory;
+
+ in_uint8s(s, 4);
+ in_uint32_le(s, flags);
+ DEBUG(("in xrdp_sec_process_logon_info flags $%x\n\r", flags));
+ /* this is the first test that the decrypt is working */
+ if ((flags & RDP_LOGON_NORMAL) != RDP_LOGON_NORMAL) /* 0x33 */
+ { /* must be or error */
+ return 1;
+ }
+ if (flags & RDP_LOGON_AUTO)
+ {
+ }
+ if (flags & RDP_COMPRESSION)
+ {
+ }
+ in_uint16_le(s, len_domain);
+ in_uint16_le(s, len_user);
+ in_uint16_le(s, len_password);
+ in_uint16_le(s, len_program);
+ in_uint16_le(s, len_directory);
+ in_uint8s(s, len_domain + 2);
+ in_uint8s(s, len_user + 2);
+ in_uint8s(s, len_password + 2);
+ in_uint8s(s, len_program + 2);
+ in_uint8s(s, len_directory + 2);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+static int APP_CC
+xrdp_sec_send_lic_initial(struct xrdp_sec* self)
+{
+ struct stream* s;
+
+ make_stream(s);
+ init_stream(s, 8192);
+ if (xrdp_mcs_init(self->mcs_layer, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ out_uint8a(s, lic1, 322);
+ s_mark_end(s);
+ if (xrdp_mcs_send(self->mcs_layer, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ free_stream(s);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+static int APP_CC
+xrdp_sec_send_lic_response(struct xrdp_sec* self)
+{
+ struct stream* s;
+
+ make_stream(s);
+ init_stream(s, 8192);
+ if (xrdp_mcs_init(self->mcs_layer, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ out_uint8a(s, lic2, 20);
+ s_mark_end(s);
+ if (xrdp_mcs_send(self->mcs_layer, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ free_stream(s);
+ return 0;
+}
+
+/*****************************************************************************/
+static void APP_CC
+xrdp_sec_reverse(char* p, int len)
+{
+ int i;
+ int j;
+ char temp;
+
+ i = 0;
+ j = len - 1;
+ while (i < j)
+ {
+ temp = p[i];
+ p[i] = p[j];
+ p[j] = temp;
+ i++;
+ j--;
+ }
+}
+
+/*****************************************************************************/
+static void APP_CC
+xrdp_sec_rsa_op(char* out, char* in, char* mod, char* exp)
+{
+ char lexp[64];
+ char lmod[64];
+ char lin[64];
+ char lout[64];
+ int len;
+
+ g_memcpy(lexp, exp, 64);
+ g_memcpy(lmod, mod, 64);
+ g_memcpy(lin, in, 64);
+ xrdp_sec_reverse(lexp, 64);
+ xrdp_sec_reverse(lmod, 64);
+ xrdp_sec_reverse(lin, 64);
+ g_memset(lout, 0, 64);
+ len = g_mod_exp(lout, lin, lmod, lexp);
+ xrdp_sec_reverse(lout, len);
+ g_memcpy(out, lout, 64);
+}
+
+/*****************************************************************************/
+static void APP_CC
+xrdp_sec_hash_48(char* out, char* in, char* salt1, char* salt2, int salt)
+{
+ int i;
+ void* sha1_info;
+ void* md5_info;
+ char pad[4];
+ char sha1_sig[20];
+ char md5_sig[16];
+
+ sha1_info = g_sha1_info_create();
+ md5_info = g_md5_info_create();
+ for (i = 0; i < 3; i++)
+ {
+ g_memset(pad, salt + i, 4);
+ g_sha1_clear(sha1_info);
+ g_sha1_transform(sha1_info, pad, i + 1);
+ g_sha1_transform(sha1_info, in, 48);
+ g_sha1_transform(sha1_info, salt1, 32);
+ g_sha1_transform(sha1_info, salt2, 32);
+ g_sha1_complete(sha1_info, sha1_sig);
+ g_md5_clear(md5_info);
+ g_md5_transform(md5_info, in, 48);
+ g_md5_transform(md5_info, sha1_sig, 20);
+ g_md5_complete(md5_info, md5_sig);
+ g_memcpy(out + i * 16, md5_sig, 16);
+ }
+ g_sha1_info_delete(sha1_info);
+ g_md5_info_delete(md5_info);
+}
+
+/*****************************************************************************/
+static void APP_CC
+xrdp_sec_hash_16(char* out, char* in, char* salt1, char* salt2)
+{
+ void* md5_info;
+
+ md5_info = g_md5_info_create();
+ g_md5_clear(md5_info);
+ g_md5_transform(md5_info, in, 16);
+ g_md5_transform(md5_info, salt1, 32);
+ g_md5_transform(md5_info, salt2, 32);
+ g_md5_complete(md5_info, out);
+ g_md5_info_delete(md5_info);
+}
+
+/*****************************************************************************/
+static void APP_CC
+xrdp_sec_establish_keys(struct xrdp_sec* self)
+{
+ char session_key[48];
+ char temp_hash[48];
+ char input[48];
+
+ g_memcpy(input, self->client_random, 24);
+ g_memcpy(input + 24, self->server_random, 24);
+ xrdp_sec_hash_48(temp_hash, input, self->client_random,
+ self->server_random, 65);
+ xrdp_sec_hash_48(session_key, temp_hash, self->client_random,
+ self->server_random, 88);
+ g_memcpy(self->sign_key, session_key, 16);
+ xrdp_sec_hash_16(self->encrypt_key, session_key + 16, self->client_random,
+ self->server_random);
+ xrdp_sec_hash_16(self->decrypt_key, session_key + 32, self->client_random,
+ self->server_random);
+ if (self->rc4_key_size == 1)
+ {
+ xrdp_sec_make_40bit(self->sign_key);
+ xrdp_sec_make_40bit(self->encrypt_key);
+ xrdp_sec_make_40bit(self->decrypt_key);
+ self->rc4_key_len = 8;
+ }
+ else
+ {
+ self->rc4_key_len = 16;
+ }
+ g_memcpy(self->decrypt_update_key, self->decrypt_key, 16);
+ g_memcpy(self->encrypt_update_key, self->encrypt_key, 16);
+ g_rc4_set_key(self->decrypt_rc4_info, self->decrypt_key, self->rc4_key_len);
+ g_rc4_set_key(self->encrypt_rc4_info, self->encrypt_key, self->rc4_key_len);
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+xrdp_sec_recv(struct xrdp_sec* self, struct stream* s, int* chan)
+{
+ int flags;
+ int len;
+
+ DEBUG((" in xrdp_sec_recv\n\r"));
+ if (xrdp_mcs_recv(self->mcs_layer, s, chan) != 0)
+ {
+ DEBUG((" out xrdp_sec_recv error\n\r"));
+ return 1;
+ }
+ in_uint32_le(s, flags);
+ DEBUG((" in xrdp_sec_recv flags $%x\n\r", flags));
+ if (flags & SEC_ENCRYPT) /* 0x08 */
+ {
+ in_uint8s(s, 8); /* signature */
+ xrdp_sec_decrypt(self, s->p, s->end - s->p);
+ }
+ if (flags & SEC_CLIENT_RANDOM) /* 0x01 */
+ {
+ in_uint32_le(s, len);
+ in_uint8a(s, self->client_crypt_random, 64);
+ xrdp_sec_rsa_op(self->client_random, self->client_crypt_random,
+ pub_mod, pri_exp);
+ xrdp_sec_establish_keys(self);
+ *chan = 1; /* just set a non existing channel and exit */
+ return 0;
+ }
+ if (flags & SEC_LOGON_INFO) /* 0x40 */
+ {
+ if (xrdp_sec_process_logon_info(self, s) != 0)
+ {
+ return 1;
+ }
+ if (xrdp_sec_send_lic_initial(self) != 0)
+ {
+ return 1;
+ }
+ *chan = 1; /* just set a non existing channel and exit */
+ return 0;
+ }
+ if (flags & SEC_LICENCE_NEG) /* 0x80 */
+ {
+ if (xrdp_sec_send_lic_response(self) != 0)
+ {
+ return 1;
+ }
+ return -1; /* special error that means send demand active */
+ }
+ DEBUG((" out xrdp_sec_recv error\n\r"));
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+/* TODO needs outgoing encryption */
+int APP_CC
+xrdp_sec_send(struct xrdp_sec* self, struct stream* s, int flags)
+{
+ DEBUG((" in xrdp_sec_send\n\r"));
+ s_pop_layer(s, sec_hdr);
+ out_uint32_le(s, flags);
+ if (xrdp_mcs_send(self->mcs_layer, s) != 0)
+ {
+ return 1;
+ }
+ DEBUG((" out xrdp_sec_send\n\r"));
+ return 0;
+}
+
+/*****************************************************************************/
+/* prepare server mcs data to send in mcs layer */
+static void APP_CC
+xrdp_sec_out_mcs_data(struct xrdp_sec* self)
+{
+ struct stream* p;
+
+ p = &self->server_mcs_data;
+ init_stream(p, 512);
+ out_uint16_be(p, 5);
+ out_uint16_be(p, 0x14);
+ out_uint8(p, 0x7c);
+ out_uint16_be(p, 1);
+ out_uint8(p, 0x2a);
+ out_uint8(p, 0x14);
+ out_uint8(p, 0x76);
+ out_uint8(p, 0x0a);
+ out_uint8(p, 1);
+ out_uint8(p, 1);
+ out_uint8(p, 0);
+ out_uint16_le(p, 0xc001);
+ out_uint8(p, 0);
+ out_uint8(p, 0x4d); /* M */
+ out_uint8(p, 0x63); /* c */
+ out_uint8(p, 0x44); /* D */
+ out_uint8(p, 0x6e); /* n */
+ out_uint16_be(p, 0x80fc);
+ out_uint16_le(p, SEC_TAG_SRV_INFO);
+ out_uint16_le(p, 8); /* len */
+ out_uint8(p, 4); /* 4 = rdp5 1 = rdp4 */
+ out_uint8(p, 0);
+ out_uint8(p, 8);
+ out_uint8(p, 0);
+ out_uint16_le(p, SEC_TAG_SRV_CHANNELS);
+ out_uint16_le(p, 8); /* len */
+ out_uint8(p, 0xeb);
+ out_uint8(p, 3);
+ out_uint8(p, 0);
+ out_uint8(p, 0);
+ out_uint16_le(p, SEC_TAG_SRV_CRYPT);
+ out_uint16_le(p, 0x00ec); /* len is 236 */
+ out_uint32_le(p, 1); /* key len 1 = 40 bit 2 = 128 bit */
+ out_uint32_le(p, 1); /* crypt level 1 = low 2 = medium 3 = high */
+ out_uint32_le(p, 32); /* 32 bytes random len */
+ out_uint32_le(p, 0xb8); /* 184 bytes rsa info(certificate) len */
+ out_uint8a(p, self->server_random, 32);
+ /* here to end is certificate */
+ /* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ */
+ /* TermService\Parameters\Certificate */
+ out_uint32_le(p, 1);
+ out_uint32_le(p, 1);
+ out_uint32_le(p, 1);
+ out_uint16_le(p, SEC_TAG_PUBKEY);
+ out_uint16_le(p, 0x005c); /* 92 bytes length of SEC_TAG_PUBKEY */
+ out_uint32_le(p, SEC_RSA_MAGIC);
+ out_uint32_le(p, 0x48); /* 72 bytes modulus len */
+ out_uint32_be(p, 0x00020000);
+ out_uint32_be(p, 0x3f000000);
+ out_uint8a(p, pub_exp, 4); /* pub exp */
+ out_uint8a(p, pub_mod, 64); /* pub mod */
+ out_uint8s(p, 8); /* pad */
+ out_uint16_le(p, SEC_TAG_KEYSIG);
+ out_uint16_le(p, 72); /* len */
+ out_uint8a(p, pub_sig, 64); /* pub sig */
+ out_uint8s(p, 8); /* pad */
+ /* end certificate */
+ s_mark_end(p);
+}
+
+/*****************************************************************************/
+int APP_CC
+xrdp_sec_incoming(struct xrdp_sec* self)
+{
+ DEBUG(("in xrdp_sec_incoming\n\r"));
+ xrdp_sec_out_mcs_data(self);
+ if (xrdp_mcs_incoming(self->mcs_layer) != 0)
+ {
+ return 1;
+ }
+#ifdef XRDP_DEBUG
+ g_printf("client mcs data received\n\r");
+ g_hexdump(self->client_mcs_data.data,
+ self->client_mcs_data.end - self->client_mcs_data.data);
+ g_printf("server mcs data sent\n\r");
+ g_hexdump(self->server_mcs_data.data,
+ self->server_mcs_data.end - self->server_mcs_data.data);
+#endif
+ DEBUG(("out xrdp_sec_incoming\n\r"));
+ return 0;
+}
+
+/*****************************************************************************/
+int APP_CC
+xrdp_sec_disconnect(struct xrdp_sec* self)
+{
+ return xrdp_mcs_disconnect(self->mcs_layer);
+}
diff --git a/libxrdp/xrdp_tcp.c b/libxrdp/xrdp_tcp.c
new file mode 100644
index 00000000..59d4a615
--- /dev/null
+++ b/libxrdp/xrdp_tcp.c
@@ -0,0 +1,146 @@
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ xrdp: A Remote Desktop Protocol server.
+ Copyright (C) Jay Sorg 2004-2005
+
+ tcp layer
+
+*/
+
+#include "libxrdp.h"
+
+/*****************************************************************************/
+struct xrdp_tcp* APP_CC
+xrdp_tcp_create(struct xrdp_iso* owner, int sck)
+{
+ struct xrdp_tcp* self;
+
+ self = (struct xrdp_tcp*)g_malloc(sizeof(struct xrdp_tcp), 1);
+ self->iso_layer = owner;
+ self->sck = sck;
+ return self;
+}
+
+/*****************************************************************************/
+void APP_CC
+xrdp_tcp_delete(struct xrdp_tcp* self)
+{
+ g_free(self);
+}
+
+/*****************************************************************************/
+/* get out stream ready for data */
+/* returns error */
+int APP_CC
+xrdp_tcp_init(struct xrdp_tcp* self, struct stream* s)
+{
+ init_stream(s, 8192);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+xrdp_tcp_recv(struct xrdp_tcp* self, struct stream* s, int len)
+{
+ int rcvd;
+
+ if (self->sck_closed)
+ {
+ DEBUG((" in xrdp_tcp_recv, sck closed\n\r"));
+ return 1;
+ }
+ DEBUG((" in xrdp_tcp_recv, gota get %d bytes\n\r", len));
+ init_stream(s, len);
+ while (len > 0)
+ {
+ rcvd = g_tcp_recv(self->sck, s->end, len, 0);
+ if (rcvd == -1)
+ {
+ if (g_tcp_last_error_would_block(self->sck))
+ {
+ g_sleep(1);
+ }
+ else
+ {
+ self->sck_closed = 1;
+ DEBUG((" error = -1 in xrdp_tcp_recv socket %d\n\r", self->sck));
+ return 1;
+ }
+ }
+ else if (rcvd == 0)
+ {
+ self->sck_closed = 1;
+ DEBUG((" error = 0 in xrdp_tcp_recv socket %d\n\r", self->sck));
+ return 1;
+ }
+ else
+ {
+ s->end += rcvd;
+ len -= rcvd;
+ }
+ }
+ DEBUG((" out xrdp_tcp_recv\n\r"));
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+xrdp_tcp_send(struct xrdp_tcp* self, struct stream* s)
+{
+ int len;
+ int total;
+ int sent;
+
+ if (self->sck_closed)
+ {
+ DEBUG((" in xrdp_tcp_send, sck closed\n\r"));
+ return 1;
+ }
+ len = s->end - s->data;
+ DEBUG((" in xrdp_tcp_send, gota send %d bytes\n\r", len));
+ total = 0;
+ while (total < len)
+ {
+ sent = g_tcp_send(self->sck, s->data + total, len - total, 0);
+ if (sent == -1)
+ {
+ if (g_tcp_last_error_would_block(self->sck))
+ {
+ g_sleep(1);
+ }
+ else
+ {
+ self->sck_closed = 1;
+ DEBUG((" error = -1 in xrdp_tcp_send socket %d\n\r", self->sck));
+ return 1;
+ }
+ }
+ else if (sent == 0)
+ {
+ self->sck_closed = 1;
+ DEBUG((" error = 0 in xrdp_tcp_send socket %d\n\r", self->sck));
+ return 1;
+ }
+ else
+ {
+ total = total + sent;
+ }
+ }
+ DEBUG((" out xrdp_tcp_send, sent %d bytes ok\n\r", len));
+ return 0;
+}