summaryrefslogtreecommitdiffstats
path: root/rdp/rdp_rdp.c
diff options
context:
space:
mode:
authorjsorg71 <jsorg71>2005-11-03 02:01:50 +0000
committerjsorg71 <jsorg71>2005-11-03 02:01:50 +0000
commit523ea69fa574dbcbe9e261c8664c8e93f18eb09d (patch)
tree180fed20bd3e54ca7af1d0c02115769b54a0857b /rdp/rdp_rdp.c
parent05ec6aa2d59efcf4c489bd3d7decd83be384157c (diff)
downloadxrdp-proprietary-523ea69fa574dbcbe9e261c8664c8e93f18eb09d.tar.gz
xrdp-proprietary-523ea69fa574dbcbe9e261c8664c8e93f18eb09d.zip
early rdp module work
Diffstat (limited to 'rdp/rdp_rdp.c')
-rw-r--r--rdp/rdp_rdp.c974
1 files changed, 974 insertions, 0 deletions
diff --git a/rdp/rdp_rdp.c b/rdp/rdp_rdp.c
new file mode 100644
index 00000000..972db54e
--- /dev/null
+++ b/rdp/rdp_rdp.c
@@ -0,0 +1,974 @@
+/*
+ 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 2005
+
+ librdp rdp layer
+
+*/
+
+#include "rdp.h"
+
+/*****************************************************************************/
+struct rdp_rdp* APP_CC
+rdp_rdp_create(struct mod* owner)
+{
+ struct rdp_rdp* self;
+
+ self = (struct rdp_rdp*)g_malloc(sizeof(struct rdp_rdp), 1);
+ self->mod = owner;
+ self->sec_layer = rdp_sec_create(self);
+ self->bitmap_compression = 1;
+ self->bitmap_cache = 1;
+ self->desktop_save = 0;
+ self->orders = rdp_orders_create(self);
+ return self;
+}
+
+/*****************************************************************************/
+void APP_CC
+rdp_rdp_delete(struct rdp_rdp* self)
+{
+ if (self == 0)
+ {
+ return;
+ }
+ rdp_orders_delete(self->orders);
+ rdp_sec_delete(self->sec_layer);
+ g_free(self);
+}
+
+/******************************************************************************/
+/* Initialise an RDP packet */
+int APP_CC
+rdp_rdp_init(struct rdp_rdp* self, struct stream* s)
+{
+ if (rdp_sec_init(self->sec_layer, s, SEC_ENCRYPT) != 0)
+ {
+ return 1;
+ }
+ s_push_layer(s, rdp_hdr, 6);
+ return 0;
+}
+
+/******************************************************************************/
+/* Send an RDP packet */
+int APP_CC
+rdp_rdp_send(struct rdp_rdp* self, struct stream* s, int pdu_type)
+{
+ int len;
+ int sec_flags;
+
+ s_pop_layer(s, rdp_hdr);
+ len = s->end - s->p;
+ out_uint16_le(s, len);
+ out_uint16_le(s, pdu_type | 0x10);
+ out_uint16_le(s, self->sec_layer->mcs_layer->userid);
+ sec_flags = SEC_ENCRYPT;
+ if (rdp_sec_send(self->sec_layer, s, sec_flags) != 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/* Initialise an RDP data packet */
+int APP_CC
+rdp_rdp_init_data(struct rdp_rdp* self, struct stream* s)
+{
+ if (rdp_sec_init(self->sec_layer, s, SEC_ENCRYPT) != 0)
+ {
+ return 1;
+ }
+ s_push_layer(s, rdp_hdr, 18);
+ return 0;
+}
+
+/******************************************************************************/
+/* Send an RDP data packet */
+int APP_CC
+rdp_rdp_send_data(struct rdp_rdp* self, struct stream* s, int pdu_data_type)
+{
+ int len;
+ int sec_flags;
+
+ s_pop_layer(s, rdp_hdr);
+ len = s->end - s->p;
+ out_uint16_le(s, len);
+ out_uint16_le(s, RDP_PDU_DATA | 0x10);
+ out_uint16_le(s, self->sec_layer->mcs_layer->userid);
+ out_uint32_le(s, self->share_id);
+ out_uint8(s, 0);
+ out_uint8(s, 1);
+ out_uint16_le(s, len - 14);
+ out_uint8(s, pdu_data_type);
+ out_uint8(s, 0); /* compress type */
+ out_uint16_le(s, 0); /* compress len */
+ sec_flags = SEC_ENCRYPT;
+ if (rdp_sec_send(self->sec_layer, s, sec_flags) != 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/* Output general capability set */
+static int APP_CC
+rdp_rdp_out_general_caps(struct rdp_rdp* self, struct stream* s)
+{
+ out_uint16_le(s, RDP_CAPSET_GENERAL);
+ out_uint16_le(s, RDP_CAPLEN_GENERAL);
+ 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, self->use_rdp5 ? 0x40d : 0);
+ 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 */
+ return 0;
+}
+
+/******************************************************************************/
+/* Output bitmap capability set */
+static int APP_CC
+rdp_rdp_out_bitmap_caps(struct rdp_rdp* self, struct stream* s)
+{
+ out_uint16_le(s, RDP_CAPSET_BITMAP);
+ out_uint16_le(s, RDP_CAPLEN_BITMAP);
+ out_uint16_le(s, self->mod->rdp_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, 800); /* Desktop width */
+ out_uint16_le(s, 600); /* Desktop height */
+ out_uint16_le(s, 0); /* Pad */
+ out_uint16_le(s, 1); /* Allow resize */
+ out_uint16_le(s, self->bitmap_compression); /* Support compression */
+ out_uint16_le(s, 0); /* Unknown */
+ out_uint16_le(s, 1); /* Unknown */
+ out_uint16_le(s, 0); /* Pad */
+ return 0;
+}
+
+/******************************************************************************/
+/* Output order capability set */
+static int APP_CC
+rdp_rdp_out_order_caps(struct rdp_rdp* self, struct stream* s)
+{
+ char order_caps[32];
+
+ g_memset(order_caps, 0, 32);
+ order_caps[0] = 1; /* dest blt */
+ order_caps[1] = 1; /* pat blt */
+ order_caps[2] = 1; /* screen blt */
+ order_caps[3] = self->bitmap_cache; /* memblt */
+ order_caps[4] = 0; /* triblt */
+ order_caps[8] = 1; /* line */
+ order_caps[9] = 1; /* line */
+ order_caps[10] = 1; /* rect */
+ order_caps[11] = self->desktop_save; /* desksave */
+ order_caps[13] = 1; /* memblt another above */
+ order_caps[14] = 1; /* triblt another above */
+ order_caps[20] = self->polygon_ellipse_orders; /* polygon */
+ order_caps[21] = self->polygon_ellipse_orders; /* polygon2 */
+ order_caps[22] = 0; /* todo polyline */
+ order_caps[25] = self->polygon_ellipse_orders; /* ellipse */
+ order_caps[26] = self->polygon_ellipse_orders; /* ellipse2 */
+ order_caps[27] = 1; /* text2 */
+ out_uint16_le(s, RDP_CAPSET_ORDER);
+ out_uint16_le(s, RDP_CAPLEN_ORDER);
+ out_uint8s(s, 20); /* Terminal desc, pad */
+ 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, 0x147); /* Number of fonts */
+ out_uint16_le(s, 0x2a); /* Capability flags */
+ out_uint8p(s, order_caps, 32); /* Orders supported */
+ out_uint16_le(s, 0x6a1); /* Text capability flags */
+ out_uint8s(s, 6); /* Pad */
+ out_uint32_le(s, self->desktop_save * 0x38400); /* Desktop cache size */
+ out_uint32_le(s, 0); /* Unknown */
+ out_uint32_le(s, 0x4e4); /* Unknown */
+ return 0;
+}
+
+/******************************************************************************/
+/* Output bitmap cache capability set */
+static int APP_CC
+rdp_rdp_out_bmpcache_caps(struct rdp_rdp* self, struct stream* s)
+{
+ int Bpp;
+
+ out_uint16_le(s, RDP_CAPSET_BMPCACHE);
+ out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
+ Bpp = (self->mod->rdp_bpp + 7) / 8;
+ out_uint8s(s, 24); /* unused */
+ out_uint16_le(s, 0x258); /* entries */
+ out_uint16_le(s, 0x100 * Bpp); /* max cell size */
+ out_uint16_le(s, 0x12c); /* entries */
+ out_uint16_le(s, 0x400 * Bpp); /* max cell size */
+ out_uint16_le(s, 0x106); /* entries */
+ out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
+ return 0;
+}
+
+/******************************************************************************/
+/* Output control capability set */
+static int APP_CC
+rdp_rdp_out_control_caps(struct rdp_rdp* self, struct stream* s)
+{
+ out_uint16_le(s, RDP_CAPSET_CONTROL);
+ out_uint16_le(s, RDP_CAPLEN_CONTROL);
+ out_uint16_le(s, 0); /* Control capabilities */
+ out_uint16_le(s, 0); /* Remote detach */
+ out_uint16_le(s, 2); /* Control interest */
+ out_uint16_le(s, 2); /* Detach interest */
+ return 0;
+}
+
+/******************************************************************************/
+/* Output activation capability set */
+static int APP_CC
+rdp_rdp_out_activate_caps(struct rdp_rdp* self, struct stream* s)
+{
+ out_uint16_le(s, RDP_CAPSET_ACTIVATE);
+ out_uint16_le(s, RDP_CAPLEN_ACTIVATE);
+ out_uint16_le(s, 0); /* Help key */
+ out_uint16_le(s, 0); /* Help index key */
+ out_uint16_le(s, 0); /* Extended help key */
+ out_uint16_le(s, 0); /* Window activate */
+ return 0;
+}
+
+/******************************************************************************/
+/* Output pointer capability set */
+static int APP_CC
+rdp_rdp_out_pointer_caps(struct rdp_rdp* self, struct stream* s)
+{
+ out_uint16_le(s, RDP_CAPSET_POINTER);
+ out_uint16_le(s, RDP_CAPLEN_POINTER);
+ out_uint16_le(s, 0); /* Color pointer */
+ out_uint16_le(s, 20); /* Cache size */
+ return 0;
+}
+
+/******************************************************************************/
+/* Output share capability set */
+static int APP_CC
+rdp_rdp_out_share_caps(struct rdp_rdp* self, struct stream* s)
+{
+ out_uint16_le(s, RDP_CAPSET_SHARE);
+ out_uint16_le(s, RDP_CAPLEN_SHARE);
+ out_uint16_le(s, 0); /* userid */
+ out_uint16_le(s, 0); /* pad */
+ return 0;
+}
+
+/******************************************************************************/
+/* Output color cache capability set */
+static int APP_CC
+rdp_rdp_out_colcache_caps(struct rdp_rdp* self, struct stream* s)
+{
+ 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 */
+ return 0;
+}
+
+static char caps_0x0d[] = {
+0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00
+};
+
+static char caps_0x0c[] = { 0x01, 0x00, 0x00, 0x00 };
+
+static char caps_0x0e[] = { 0x01, 0x00, 0x00, 0x00 };
+
+static char caps_0x10[] = {
+0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00,
+0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00,
+0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00,
+0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00,
+0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08,
+0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00
+};
+
+/******************************************************************************/
+/* Output unknown capability sets */
+static int APP_CC
+rdp_rdp_out_unknown_caps(struct rdp_rdp* self, struct stream* s, int id,
+ int length, char* caps)
+{
+ out_uint16_le(s, id);
+ out_uint16_le(s, length);
+ out_uint8p(s, caps, length - 4);
+ return 0;
+}
+
+#define RDP5_FLAG 0x0030
+
+/******************************************************************************/
+/* Send a confirm active PDU */
+static int APP_CC
+rdp_rdp_send_confirm_active(struct rdp_rdp* self, struct stream* s)
+{
+ int sec_flags;
+ int caplen;
+
+ sec_flags = SEC_ENCRYPT;
+ //sec_flags = RDP5_FLAG | SEC_ENCRYPT;
+ caplen = RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
+ RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
+ RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
+ RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE +
+ 0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */ +
+ 4 /* w2k fix, why? */ ;
+ if (rdp_sec_init(self->sec_layer, s, sec_flags) != 0)
+ {
+ return 1;
+ }
+ out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE));
+ out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10)); /* Version 1 */
+ out_uint16_le(s, (self->sec_layer->mcs_layer->userid + 1001));
+ out_uint32_le(s, self->share_id);
+ out_uint16_le(s, 0x3ea); /* userid */
+ out_uint16_le(s, sizeof(RDP_SOURCE));
+ out_uint16_le(s, caplen);
+ out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
+ out_uint16_le(s, 0xd); /* num_caps */
+ out_uint8s(s, 2); /* pad */
+ rdp_rdp_out_general_caps(self, s);
+ rdp_rdp_out_bitmap_caps(self, s);
+ rdp_rdp_out_order_caps(self, s);
+ rdp_rdp_out_bmpcache_caps(self, s);
+ rdp_rdp_out_colcache_caps(self, s);
+ rdp_rdp_out_activate_caps(self, s);
+ rdp_rdp_out_control_caps(self, s);
+ rdp_rdp_out_pointer_caps(self, s);
+ rdp_rdp_out_share_caps(self, s);
+ rdp_rdp_out_unknown_caps(self, s, 0x0d, 0x58, caps_0x0d); /* international? */
+ rdp_rdp_out_unknown_caps(self, s, 0x0c, 0x08, caps_0x0c);
+ rdp_rdp_out_unknown_caps(self, s, 0x0e, 0x08, caps_0x0e);
+ rdp_rdp_out_unknown_caps(self, s, 0x10, 0x34, caps_0x10); /* glyph cache? */
+ s_mark_end(s);
+ if (rdp_sec_send(self->sec_layer, s, sec_flags) != 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/* Process a color pointer PDU */
+static void APP_CC
+rdp_rdp_process_color_pointer_pdu(struct rdp_rdp* self, struct stream* s)
+{
+ int cache_idx;
+ int dlen;
+ int mlen;
+ struct rdp_cursor* cursor;
+
+ in_uint16_le(s, cache_idx);
+ cursor = self->cursors + cache_idx;
+ in_uint16_le(s, cursor->x);
+ in_uint16_le(s, cursor->y);
+ in_uint16_le(s, cursor->width);
+ in_uint16_le(s, cursor->height);
+ in_uint16_le(s, mlen); /* mask length */
+ in_uint16_le(s, dlen); /* data length */
+ in_uint8a(s, cursor->data, dlen);
+ in_uint8a(s, cursor->mask, mlen);
+ self->mod->server_set_cursor(self->mod, cursor->x, cursor->y,
+ cursor->data, cursor->mask);
+}
+
+/******************************************************************************/
+/* Process a cached pointer PDU */
+static void APP_CC
+rdp_rdp_process_cached_pointer_pdu(struct rdp_rdp* self, struct stream* s)
+{
+ int cache_idx;
+ struct rdp_cursor* cursor;
+
+ in_uint16_le(s, cache_idx);
+ cursor = self->cursors + cache_idx;
+ self->mod->server_set_cursor(self->mod, cursor->x, cursor->y,
+ cursor->data, cursor->mask);
+}
+
+/******************************************************************************/
+/* Process a system pointer PDU */
+static void APP_CC
+rdp_rdp_process_system_pointer_pdu(struct rdp_rdp* self, struct stream* s)
+{
+ int system_pointer_type;
+ struct rdp_cursor* cursor;
+
+ in_uint16_le(s, system_pointer_type);
+ switch (system_pointer_type)
+ {
+ case RDP_NULL_POINTER:
+ cursor = (struct rdp_cursor*)g_malloc(sizeof(struct rdp_cursor), 1);
+ g_memset(cursor->mask, 0xff, sizeof(cursor->mask));
+ self->mod->server_set_cursor(self->mod, cursor->x, cursor->y,
+ cursor->data, cursor->mask);
+ g_free(cursor);
+ break;
+ default:
+ break;
+ }
+}
+
+/******************************************************************************/
+/* Process a pointer PDU */
+static void APP_CC
+rdp_rdp_process_pointer_pdu(struct rdp_rdp* self, struct stream* s)
+{
+ int message_type;
+ int x;
+ int y;
+
+ in_uint16_le(s, message_type);
+ in_uint8s(s, 2); /* pad */
+ switch (message_type)
+ {
+ case RDP_POINTER_MOVE:
+ in_uint16_le(s, x);
+ in_uint16_le(s, y);
+ break;
+ case RDP_POINTER_COLOR:
+ rdp_rdp_process_color_pointer_pdu(self, s);
+ break;
+ case RDP_POINTER_CACHED:
+ rdp_rdp_process_cached_pointer_pdu(self, s);
+ break;
+ case RDP_POINTER_SYSTEM:
+ rdp_rdp_process_system_pointer_pdu(self, s);
+ break;
+ default:
+ break;
+ }
+}
+
+/******************************************************************************/
+/* Process bitmap updates */
+static void APP_CC
+rdp_rdp_process_bitmap_updates(struct rdp_rdp* self, struct stream* s)
+{
+ int num_updates;
+ int left;
+ int top;
+ int right;
+ int bottom;
+ int width;
+ int height;
+ int cx;
+ int cy;
+ int bpp;
+ int Bpp;
+ int compress;
+ int bufsize;
+ int size;
+ int i;
+ int y;
+ char* data;
+ char* bmpdata;
+
+ in_uint16_le(s, num_updates);
+ for (i = 0; i < num_updates; i++)
+ {
+ in_uint16_le(s, left);
+ in_uint16_le(s, top);
+ in_uint16_le(s, right);
+ in_uint16_le(s, bottom);
+ in_uint16_le(s, width);
+ in_uint16_le(s, height);
+ in_uint16_le(s, bpp);
+ Bpp = (bpp + 7) / 8;
+ in_uint16_le(s, compress);
+ in_uint16_le(s, bufsize);
+ cx = (right - left) + 1;
+ cy = (bottom - top) + 1;
+ bmpdata = (char*)g_malloc(width * height * Bpp, 0);
+ if (compress)
+ {
+ if (compress & 0x400)
+ {
+ size = bufsize;
+ }
+ else
+ {
+ in_uint8s(s, 2); /* pad */
+ in_uint16_le(s, size);
+ in_uint8s(s, 4); /* line_size, final_size */
+ }
+ in_uint8p(s, data, size);
+ rdp_bitmap_decompress(bmpdata, width, height, data, size, Bpp);
+ self->mod->server_paint_rect(self->mod, left, top, cx, cy, bmpdata,
+ width, height, 0, 0);
+ }
+ else
+ {
+ for (y = 0; y < height; y++)
+ {
+ data = bmpdata + ((height - y) - 1) * (width * Bpp);
+ in_uint8a(s, data, width * Bpp);
+ }
+ self->mod->server_paint_rect(self->mod, left, top, cx, cy, bmpdata,
+ width, height, 0, 0);
+ }
+ g_free(bmpdata);
+ }
+}
+
+/******************************************************************************/
+/* Process a palette update */
+static void APP_CC
+rdp_rdp_process_palette(struct rdp_rdp* self, struct stream* s)
+{
+ int i;
+ int r;
+ int g;
+ int b;
+
+ in_uint8s(s, 2); /* pad */
+ in_uint16_le(s, self->colormap.ncolors);
+ in_uint8s(s, 2); /* pad */
+ for (i = 0; i < self->colormap.ncolors; i++)
+ {
+ in_uint8(s, r);
+ in_uint8(s, g);
+ in_uint8(s, b);
+ self->colormap.colors[i] = (r << 16) | (g << 8) | b;
+ }
+ //ui_set_colormap(hmap);
+}
+
+/******************************************************************************/
+/* Process an update PDU */
+static void APP_CC
+rdp_rdp_process_update_pdu(struct rdp_rdp* self, struct stream* s)
+{
+ int update_type;
+ int count;
+
+ in_uint16_le(s, update_type);
+ self->mod->server_begin_update(self->mod);
+ switch (update_type)
+ {
+ case RDP_UPDATE_ORDERS:
+ in_uint8s(s, 2); /* pad */
+ in_uint16_le(s, count);
+ in_uint8s(s, 2); /* pad */
+ rdp_orders_process_orders(self->orders, s, count);
+ break;
+ case RDP_UPDATE_BITMAP:
+ rdp_rdp_process_bitmap_updates(self, s);
+ break;
+ case RDP_UPDATE_PALETTE:
+ rdp_rdp_process_palette(self, s);
+ break;
+ case RDP_UPDATE_SYNCHRONIZE:
+ break;
+ default:
+ break;
+ }
+ self->mod->server_end_update(self->mod);
+}
+
+
+/******************************************************************************/
+void APP_CC
+rdp_rdp_out_unistr(struct stream* s, char* text)
+{
+ int i;
+
+ i = 0;
+ while (text[i] != 0)
+ {
+ out_uint8(s, text[i]);
+ out_uint8(s, 0);
+ i++;
+ }
+ out_uint8(s, 0);
+ out_uint8(s, 0);
+}
+
+/******************************************************************************/
+int APP_CC
+rdp_rdp_send_login_info(struct rdp_rdp* self, int flags)
+{
+ int len_domain;
+ int len_username;
+ int len_password;
+ int len_program;
+ int len_directory;
+ int sec_flags;
+ struct stream* s;
+
+ DEBUG(("in rdp_rdp_send_login_info\r\n"));
+ make_stream(s);
+ init_stream(s, 8192);
+ len_domain = 2 * g_strlen(self->mod->domain);
+ len_username = 2 * g_strlen(self->mod->username);
+ len_password = 2 * g_strlen(self->mod->password);
+ len_program = 2 * g_strlen(self->mod->program);
+ len_directory = 2 * g_strlen(self->mod->directory);
+ sec_flags = SEC_LOGON_INFO | SEC_ENCRYPT;
+ if (rdp_sec_init(self->sec_layer, s, sec_flags) != 0)
+ {
+ free_stream(s);
+ DEBUG(("out rdp_rdp_send_login_info error 1\r\n"));
+ return 1;
+ }
+ out_uint32_le(s, 0);
+ out_uint32_le(s, flags);
+ out_uint16_le(s, len_domain);
+ out_uint16_le(s, len_username);
+ out_uint16_le(s, len_password);
+ out_uint16_le(s, len_program);
+ out_uint16_le(s, len_directory);
+ rdp_rdp_out_unistr(s, self->mod->domain);
+ rdp_rdp_out_unistr(s, self->mod->username);
+ rdp_rdp_out_unistr(s, self->mod->password);
+ rdp_rdp_out_unistr(s, self->mod->program);
+ rdp_rdp_out_unistr(s, self->mod->directory);
+ s_mark_end(s);
+ if (rdp_sec_send(self->sec_layer, s, sec_flags) != 0)
+ {
+ free_stream(s);
+ DEBUG(("out rdp_rdp_send_login_info error 2\r\n"));
+ return 1;
+ }
+ free_stream(s);
+ DEBUG(("out rdp_rdp_send_login_info\r\n"));
+ return 0;
+}
+
+/******************************************************************************/
+int APP_CC
+rdp_rdp_connect(struct rdp_rdp* self, char* ip, char* port)
+{
+ int flags;
+
+ DEBUG(("in rdp_rdp_connect\r\n"));
+ flags = RDP_LOGON_NORMAL;
+ if (g_strlen(self->mod->password) > 0)
+ {
+ flags |= RDP_LOGON_AUTO;
+ }
+ if (rdp_sec_connect(self->sec_layer, ip, port) != 0)
+ {
+ DEBUG(("out rdp_rdp_connect error rdp_sec_connect failed\r\n"));
+ return 1;
+ }
+ if (rdp_rdp_send_login_info(self, flags) != 0)
+ {
+ DEBUG(("out rdp_rdp_connect error rdp_rdp_send_login_info failed\r\n"));
+ return 1;
+ }
+ DEBUG(("out rdp_rdp_connect\r\n"));
+ return 0;
+}
+
+/******************************************************************************/
+int APP_CC
+rdp_rdp_send_input(struct rdp_rdp* self, struct stream* s,
+ int time, int message_type,
+ int device_flags, int param1, int param2)
+{
+ if (rdp_rdp_init_data(self, s) != 0)
+ {
+ return 1;
+ }
+ out_uint16_le(s, 1); /* number of events */
+ out_uint16_le(s, 0);
+ out_uint32_le(s, time);
+ out_uint16_le(s, message_type);
+ out_uint16_le(s, device_flags);
+ out_uint16_le(s, param1);
+ out_uint16_le(s, param2);
+ s_mark_end(s);
+ if (rdp_rdp_send_data(self, s, RDP_DATA_PDU_INPUT) != 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+int APP_CC
+rdp_rdp_send_invalidate(struct rdp_rdp* self, struct stream* s,
+ int left, int top, int width, int height)
+{
+ if (rdp_rdp_init_data(self, s) != 0)
+ {
+ return 1;
+ }
+ out_uint32_le(s, 1);
+ out_uint16_le(s, left);
+ out_uint16_le(s, top);
+ out_uint16_le(s, (left + width) - 1);
+ out_uint16_le(s, (top + height) - 1);
+ s_mark_end(s);
+ if (rdp_rdp_send_data(self, s, 33) != 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+int APP_CC
+rdp_rdp_recv(struct rdp_rdp* self, struct stream* s, int* type)
+{
+ int len;
+ int pdu_type;
+ int chan;
+
+ chan = 0;
+ DEBUG(("in rdp_rdp_recv\r\n"));
+ if (s->next_packet >= s->end || s->next_packet == 0)
+ {
+ if (rdp_sec_recv(self->sec_layer, s, &chan) != 0)
+ {
+ DEBUG(("error in rdp_rdp_recv, rdp_sec_recv failed\r\n"));
+ return 1;
+ }
+ s->next_packet = s->p;
+ }
+ else
+ {
+ chan = MCS_GLOBAL_CHANNEL;
+ s->p = s->next_packet;
+ }
+ if (chan == MCS_GLOBAL_CHANNEL)
+ {
+ in_uint16_le(s, len);
+ DEBUG(("rdp_rdp_recv got %d len\r\n", len));
+ if (len == 0x8000)
+ {
+ s->next_packet += 8;
+ DEBUG(("out rdp_rdp_recv\r\n"));
+ return 0;
+ }
+ in_uint16_le(s, pdu_type);
+ in_uint8s(s, 2);
+ *type = pdu_type & 0xf;
+ s->next_packet += len;
+ }
+ else
+ {
+ /* todo, process channel data */
+ DEBUG(("got channel data channel %d\r\n", chan));
+ s->next_packet = s->end;
+ }
+ DEBUG(("out rdp_rdp_recv\r\n"));
+ return 0;
+}
+
+
+/******************************************************************************/
+static int APP_CC
+rdp_rdp_process_disconnect_pdu(struct rdp_rdp* self, struct stream* s)
+{
+ return 0;
+}
+
+/******************************************************************************/
+int APP_CC
+rdp_rdp_process_data_pdu(struct rdp_rdp* self, struct stream* s)
+{
+ int data_pdu_type;
+ int ctype;
+ int clen;
+ int len;
+
+ in_uint8s(s, 6); /* shareid, pad, streamid */
+ in_uint16_le(s, len);
+ in_uint8(s, data_pdu_type);
+ in_uint8(s, ctype);
+ in_uint16_le(s, clen);
+ clen -= 18;
+ switch (data_pdu_type)
+ {
+ case RDP_DATA_PDU_UPDATE:
+ rdp_rdp_process_update_pdu(self, s);
+ break;
+ case RDP_DATA_PDU_CONTROL:
+ break;
+ case RDP_DATA_PDU_SYNCHRONISE:
+ break;
+ case RDP_DATA_PDU_POINTER:
+ rdp_rdp_process_pointer_pdu(self, s);
+ break;
+ case RDP_DATA_PDU_BELL:
+ break;
+ case RDP_DATA_PDU_LOGON:
+ break;
+ case RDP_DATA_PDU_DISCONNECT:
+ rdp_rdp_process_disconnect_pdu(self, s);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/* Process server capabilities */
+static int APP_CC
+rdp_rdp_process_server_caps(struct rdp_rdp* self, struct stream* s, int len)
+{
+ int n;
+ int ncapsets;
+ int capset_type;
+ int capset_length;
+ char* next;
+ char* start;
+
+ start = s->p;
+ in_uint16_le(s, ncapsets);
+ in_uint8s(s, 2); /* pad */
+ for (n = 0; n < ncapsets; n++)
+ {
+ if (s->p > start + len)
+ {
+ return 0;
+ }
+ in_uint16_le(s, capset_type);
+ in_uint16_le(s, capset_length);
+ next = (s->p + capset_length) - 4;
+ switch (capset_type)
+ {
+ case RDP_CAPSET_GENERAL:
+ //rdp_process_general_caps(s);
+ break;
+ case RDP_CAPSET_BITMAP:
+ //rdp_process_bitmap_caps(s);
+ break;
+ }
+ s->p = next;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/* Send a control PDU */
+/* returns error */
+static int APP_CC
+rdp_rdp_send_control(struct rdp_rdp* self, struct stream* s, int action)
+{
+ if (rdp_rdp_init_data(self, s) != 0)
+ {
+ return 1;
+ }
+ out_uint16_le(s, action);
+ out_uint16_le(s, 0); /* userid */
+ out_uint32_le(s, 0); /* control id */
+ s_mark_end(s);
+ if (rdp_rdp_send_data(self, s, RDP_DATA_PDU_CONTROL) != 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/* Send a synchronisation PDU */
+/* returns error */
+static int APP_CC
+rdp_rdp_send_synchronise(struct rdp_rdp* self, struct stream* s)
+{
+ if (rdp_rdp_init_data(self, s) != 0)
+ {
+ return 1;
+ }
+ out_uint16_le(s, 1); /* type */
+ out_uint16_le(s, 1002);
+ s_mark_end(s);
+ if (rdp_rdp_send_data(self, s, RDP_DATA_PDU_SYNCHRONISE) != 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/* Send an (empty) font information PDU */
+static int APP_CC
+rdp_rdp_send_fonts(struct rdp_rdp* self, struct stream* s, int seq)
+{
+ if (rdp_rdp_init_data(self, s) != 0)
+ {
+ return 1;
+ }
+ out_uint16_le(s, 0); /* number of fonts */
+ out_uint16_le(s, 0); /* pad? */
+ out_uint16_le(s, seq); /* unknown */
+ out_uint16_le(s, 0x32); /* entry size */
+ s_mark_end(s);
+ if (rdp_rdp_send_data(self, s, RDP_DATA_PDU_FONT2) != 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/* Respond to a demand active PDU */
+int APP_CC
+rdp_rdp_process_demand_active(struct rdp_rdp* self, struct stream* s)
+{
+ int type;
+ int len_src_descriptor;
+ int len_combined_caps;
+
+ in_uint32_le(s, self->share_id);
+ in_uint16_le(s, len_src_descriptor);
+ in_uint16_le(s, len_combined_caps);
+ in_uint8s(s, len_src_descriptor);
+ rdp_rdp_process_server_caps(self, s, len_combined_caps);
+ rdp_rdp_send_confirm_active(self, s);
+ rdp_rdp_send_synchronise(self, s);
+ rdp_rdp_send_control(self, s, RDP_CTL_COOPERATE);
+ rdp_rdp_send_control(self, s, RDP_CTL_REQUEST_CONTROL);
+ rdp_rdp_recv(self, s, &type); /* RDP_PDU_SYNCHRONIZE */
+ rdp_rdp_recv(self, s, &type); /* RDP_CTL_COOPERATE */
+ rdp_rdp_recv(self, s, &type); /* RDP_CTL_GRANT_CONTROL */
+ rdp_rdp_send_input(self, s, 0, RDP_INPUT_SYNCHRONIZE, 0, 0, 0);
+ rdp_rdp_send_fonts(self, s, 1);
+ rdp_rdp_send_fonts(self, s, 2);
+ rdp_rdp_recv(self, s, &type); /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */
+ rdp_orders_reset_state(self->orders);
+ return 0;
+}