summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xrdp/Makefile9
-rw-r--r--xrdp/constants.h27
-rw-r--r--xrdp/os_calls.c205
-rw-r--r--xrdp/parse.h6
-rw-r--r--xrdp/xrdp.c2
-rw-r--r--xrdp/xrdp.h140
-rw-r--r--xrdp/xrdp_bitmap.c479
-rw-r--r--xrdp/xrdp_cache.c145
-rw-r--r--xrdp/xrdp_iso.c4
-rw-r--r--xrdp/xrdp_list.c149
-rw-r--r--xrdp/xrdp_listen.c23
-rw-r--r--xrdp/xrdp_mcs.c31
-rw-r--r--xrdp/xrdp_orders.c976
-rw-r--r--xrdp/xrdp_painter.c333
-rw-r--r--xrdp/xrdp_process.c32
-rw-r--r--xrdp/xrdp_rdp.c83
-rw-r--r--xrdp/xrdp_region.c286
-rw-r--r--xrdp/xrdp_sec.c76
-rw-r--r--xrdp/xrdp_tcp.c7
-rw-r--r--xrdp/xrdp_types.h259
-rw-r--r--xrdp/xrdp_wm.c886
21 files changed, 4073 insertions, 85 deletions
diff --git a/xrdp/Makefile b/xrdp/Makefile
index 3f79fb6a..d39fad86 100644
--- a/xrdp/Makefile
+++ b/xrdp/Makefile
@@ -1,9 +1,10 @@
XRDPOBJ = xrdp.o os_calls.o xrdp_tcp.o xrdp_iso.o xrdp_mcs.o xrdp_sec.o xrdp_rdp.o \
- xrdp_process.o xrdp_listen.o
-CFLAGS = -Wall -O2 -DXRDP_DEBUG
-#CFLAGS = -Wall -O2
-CC = g++
+ xrdp_process.o xrdp_listen.o xrdp_orders.o xrdp_bitmap.o xrdp_wm.o \
+ xrdp_painter.o xrdp_list.o xrdp_region.o xrdp_cache.o
+#CFLAGS = -Wall -O2 -DXRDP_DEBUG
+CFLAGS = -Wall -O2
+CC = gcc
all: xrdp
diff --git a/xrdp/constants.h b/xrdp/constants.h
index 473262bd..ec531273 100644
--- a/xrdp/constants.h
+++ b/xrdp/constants.h
@@ -370,3 +370,30 @@
#define exDiscReasonLicenseErrClientEncryption 0x0108
#define exDiscReasonLicenseCantUpgradeLicense 0x0109
#define exDiscReasonLicenseNoRemoteConnections 0x010a
+
+#define RDP_ORDER_STANDARD 0x01
+#define RDP_ORDER_SECONDARY 0x02
+#define RDP_ORDER_BOUNDS 0x04
+#define RDP_ORDER_CHANGE 0x08
+#define RDP_ORDER_DELTA 0x10
+#define RDP_ORDER_LASTBOUNDS 0x20
+#define RDP_ORDER_SMALL 0x40
+#define RDP_ORDER_TINY 0x80
+
+#define RDP_ORDER_DESTBLT 0
+#define RDP_ORDER_PATBLT 1
+#define RDP_ORDER_SCREENBLT 2
+#define RDP_ORDER_LINE 9
+#define RDP_ORDER_RECT 10
+#define RDP_ORDER_DESKSAVE 11
+#define RDP_ORDER_MEMBLT 13
+#define RDP_ORDER_TRIBLT 14
+#define RDP_ORDER_POLYLINE 22
+#define RDP_ORDER_TEXT2 27
+
+#define RDP_ORDER_RAW_BMPCACHE 0
+#define RDP_ORDER_COLCACHE 1
+#define RDP_ORDER_BMPCACHE 2
+#define RDP_ORDER_FONTCACHE 3
+#define RDP_ORDER_RAW_BMPCACHE2 4
+#define RDP_ORDER_BMPCACHE2 5
diff --git a/xrdp/os_calls.c b/xrdp/os_calls.c
index afa1e8b7..f6d8e48a 100644
--- a/xrdp/os_calls.c
+++ b/xrdp/os_calls.c
@@ -28,6 +28,7 @@
#include <stdio.h>
#include <fcntl.h>
#include <netinet/in.h>
+#include <netinet/tcp.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <openssl/rc4.h>
@@ -35,11 +36,121 @@
#include <openssl/sha.h>
#include <openssl/bn.h>
+#include "xrdp.h"
+
+//#define MEMLEAK
+
static pthread_mutex_t g_term_mutex = PTHREAD_MUTEX_INITIALIZER;
static int g_term = 0;
+#ifdef MEMLEAK
+int g_memsize = 0;
+int g_memid = 0;
+struct xrdp_list* g_memlist = 0;
+#endif
+
+/*****************************************************************************/
+int g_init_system(void)
+{
+#ifdef MEMLEAK
+ g_memlist = xrdp_list_create();
+#endif
+ return 0;
+}
+
+/*****************************************************************************/
+int g_exit_system(void)
+{
+#ifdef MEMLEAK
+ int i;
+ struct xrdp_mem* p;
+
+ for (i = 0; i < g_memlist->count; i++)
+ {
+ p = (struct xrdp_mem*)xrdp_list_get_item(g_memlist, i);
+ g_printf("leak size %d id %d\n\r", p->size, p->id);
+ }
+ g_printf("mem %d\n\r", g_memsize);
+ xrdp_list_delete(g_memlist);
+ g_memlist = 0;
+#endif
+ return 0;
+}
+
+/*****************************************************************************/
+void* g_malloc(int size, int zero)
+{
+#ifdef MEMLEAK
+ char* rv;
+ struct xrdp_mem* p;
+
+ rv = (char*)malloc(size + sizeof(struct xrdp_mem));
+ if (zero)
+ memset(rv, 0, size + sizeof(struct xrdp_mem));
+ g_memsize += size;
+ p = (struct xrdp_mem*)rv;
+ p->size = size;
+ p->id = g_memid;
+ if (g_memlist != 0)
+ xrdp_list_add_item(g_memlist, (int)p);
+ g_memid++;
+ return rv + sizeof(struct xrdp_mem);
+#else
+ char* rv;
+
+ rv = (char*)malloc(size);
+ if (zero)
+ memset(rv, 0, size);
+ return rv;
+#endif
+}
+
+/*****************************************************************************/
+void* g_malloc1(int size, int zero)
+{
+ char* rv;
+
+ rv = (char*)malloc(size);
+ if (zero)
+ memset(rv, 0, size);
+ return rv;
+}
+
+/*****************************************************************************/
+void g_free(void* ptr)
+{
+#ifdef MEMLEAK
+ struct xrdp_mem* p;
+ int i;
+
+ if (ptr != 0)
+ {
+ p = (struct xrdp_mem*)(((char*)ptr) - sizeof(struct xrdp_mem));
+ g_memsize -= p->size;
+ i = xrdp_list_index_of(g_memlist, (int)p);
+ if (i >= 0)
+ xrdp_list_remove_item(g_memlist, i);
+ free(p);
+ }
+#else
+ if (ptr != 0)
+ {
+ free(ptr);
+ }
+#endif
+}
+
/*****************************************************************************/
-void g_printf(char *format, ...)
+void g_free1(void* ptr)
+{
+ if (ptr != 0)
+ {
+ free(ptr);
+ }
+}
+
+/*****************************************************************************/
+void g_printf(char* format, ...)
{
va_list ap;
@@ -78,24 +189,6 @@ void g_hexdump(char* p, int len)
}
/*****************************************************************************/
-void* g_malloc(int size, int zero)
-{
- void* rv;
-
- rv = malloc(size);
- if (zero)
- memset(rv, 0, size);
- return rv;
-}
-
-/*****************************************************************************/
-void g_free(void* ptr)
-{
- if (ptr != 0)
- free(ptr);
-}
-
-/*****************************************************************************/
void g_memset(void* ptr, int val, int size)
{
memset(ptr, val, size);
@@ -116,7 +209,13 @@ int g_getchar(void)
/*****************************************************************************/
int g_tcp_socket(void)
{
- return socket(PF_INET, SOCK_STREAM, 0);
+ int rv;
+ int i;
+
+ i = 1;
+ rv = socket(PF_INET, SOCK_STREAM, 0);
+ setsockopt(rv, IPPROTO_TCP, TCP_NODELAY, (void*)&i, sizeof(i));
+ return rv;
}
/*****************************************************************************/
@@ -187,10 +286,13 @@ int g_tcp_last_error_would_block(int sck)
int g_tcp_select(int sck)
{
fd_set rfds;
+ struct timeval time;
+ time.tv_sec = 0;
+ time.tv_usec = 0;
FD_ZERO(&rfds);
FD_SET(sck, &rfds);
- return select(sck + 1, &rfds, 0, 0, 0);
+ return select(sck + 1, &rfds, 0, 0, &time);
}
/*****************************************************************************/
@@ -359,3 +461,64 @@ void g_random(char* data, int len)
close(fd);
}
}
+
+/*****************************************************************************/
+int g_abs(int i)
+{
+ return abs(i);
+}
+
+/*****************************************************************************/
+int g_memcmp(void* s1, void* s2, int len)
+{
+ return memcmp(s1, s2, len);
+}
+
+/*****************************************************************************/
+int g_file_open(char* file_name)
+{
+ return open(file_name, O_RDWR | O_CREAT);
+}
+
+/*****************************************************************************/
+int g_file_close(int fd)
+{
+ close(fd);
+ return 0;
+}
+
+/*****************************************************************************/
+/* read from file*/
+int g_file_read(int fd, char* ptr, int len)
+{
+ return read(fd, ptr, len);
+}
+
+/*****************************************************************************/
+/* write to file */
+int g_file_write(int fd, char* ptr, int len)
+{
+ return write(fd, ptr, len);
+}
+
+/*****************************************************************************/
+/* move file pointer */
+int g_file_seek(int fd, int offset)
+{
+ return lseek(fd, offset, SEEK_SET);
+}
+
+/*****************************************************************************/
+/* do a write lock on a file */
+int g_file_lock(int fd, int start, int len)
+{
+ struct flock lock;
+
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = start;
+ lock.l_len = len;
+ if (fcntl(fd, F_SETLK, &lock) == -1)
+ return 0;
+ return 1;
+}
diff --git a/xrdp/parse.h b/xrdp/parse.h
index 28c2d49c..605486b6 100644
--- a/xrdp/parse.h
+++ b/xrdp/parse.h
@@ -77,6 +77,12 @@ struct stream
s->p++; \
}
+#define in_sint16_le(s, v) \
+{ \
+ v = *((signed short*)(s->p)); \
+ s->p += 2; \
+}
+
#define in_uint16_le(s, v) \
{ \
v = *((unsigned short*)(s->p)); \
diff --git a/xrdp/xrdp.c b/xrdp/xrdp.c
index ba91216a..ad486782 100644
--- a/xrdp/xrdp.c
+++ b/xrdp/xrdp.c
@@ -39,6 +39,7 @@ int main(int argc, char** argv)
{
int rv;
+ g_init_system();
rv = 0;
g_listen = xrdp_listen_create();
if (g_thread_create(xrdp_listen_run, 0) == 0)
@@ -51,5 +52,6 @@ int main(int argc, char** argv)
else
rv = 1;
xrdp_listen_delete(g_listen);
+ g_exit_system();
return rv;
}
diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h
index 989fda0b..e67ec280 100644
--- a/xrdp/xrdp.h
+++ b/xrdp/xrdp.h
@@ -29,11 +29,21 @@
#define DEBUG(args)
#endif
+#define MIN(x, x1, x2) x = (x1) < (x2) ? (x1) : (x2)
+#define MAX(x, x1, x2) x = (x1) > (x2) ? (x1) : (x2)
+#define HIWORD(out, in) out = ((in) & 0xffff0000) >> 16
+#define LOWORD(out, in) out = (in) & 0x0000ffff
+#define MAKELONG(out, hi, lo) out = (((hi) << 16) || (lo))
+
/* os_calls.c */
+int g_init_system(void);
+int g_exit_system(void);
void g_printf(char *format, ...);
void g_hexdump(char* p, int len);
void* g_malloc(int size, int zero);
+void* g_malloc1(int size, int zero);
void g_free(void* ptr);
+void g_free1(void* ptr);
void g_memset(void* ptr, int val, int size);
void g_memcpy(void* d_ptr, const void* s_ptr, int size);
int g_getchar(void);
@@ -67,6 +77,14 @@ void g_md5_transform(void* md5_info, char* data, int len);
void g_md5_complete(void* md5_info, char* data);
int g_mod_exp(char* out, char* in, char* mod, char* exp);
void g_random(char* data, int len);
+int g_abs(int i);
+int g_memcmp(void* s1, void* s2, int len);
+int g_file_open(char* file_name);
+int g_file_close(int fd);
+int g_file_read(int fd, char* ptr, int len);
+int g_file_write(int fd, char* ptr, int len);
+int g_file_seek(int fd, int offset);
+int g_file_lock(int fd, int start, int len);
/* xrdp_tcp.c */
struct xrdp_tcp* xrdp_tcp_create(struct xrdp_iso* owner);
@@ -87,18 +105,20 @@ int xrdp_iso_incoming(struct xrdp_iso* self);
struct xrdp_mcs* xrdp_mcs_create(struct xrdp_sec* owner);
void xrdp_mcs_delete(struct xrdp_mcs* self);
int xrdp_mcs_init(struct xrdp_mcs* self, int len);
-int xrdp_mcs_recv(struct xrdp_mcs* self);
+int xrdp_mcs_recv(struct xrdp_mcs* self, int* chan);
int xrdp_mcs_send(struct xrdp_mcs* self);
int xrdp_mcs_incoming(struct xrdp_mcs* self);
+int xrdp_mcs_disconnect(struct xrdp_mcs* self);
/* xrdp_sec.c */
struct xrdp_sec* xrdp_sec_create(struct xrdp_rdp* owner);
void xrdp_sec_delete(struct xrdp_sec* self);
int xrdp_sec_init(struct xrdp_sec* self, int len);
-int xrdp_sec_recv(struct xrdp_sec* self);
+int xrdp_sec_recv(struct xrdp_sec* self, int* chan);
int xrdp_sec_send(struct xrdp_sec* self, int flags);
int xrdp_rdp_send_data(struct xrdp_rdp* self, int data_pdu_type);
int xrdp_sec_incoming(struct xrdp_sec* self);
+int xrdp_sec_disconnect(struct xrdp_sec* self);
/* xrdp_rdp.c */
struct xrdp_rdp* xrdp_rdp_create(struct xrdp_process* owner);
@@ -111,6 +131,68 @@ int xrdp_rdp_incoming(struct xrdp_rdp* self);
int xrdp_rdp_send_demand_active(struct xrdp_rdp* self);
int xrdp_rdp_process_confirm_active(struct xrdp_rdp* self);
int xrdp_rdp_process_data(struct xrdp_rdp* self);
+int xrdp_rdp_disconnect(struct xrdp_rdp* self);
+
+/* xrdp_orders.c */
+struct xrdp_orders* xrdp_orders_create(struct xrdp_process* owner);
+void xrdp_orders_delete(struct xrdp_orders* self);
+int xrdp_orders_init(struct xrdp_orders* self);
+int xrdp_orders_send(struct xrdp_orders* self);
+int xrdp_orders_rect(struct xrdp_orders* self, int x, int y, int cx, int cy,
+ int color, struct xrdp_rect* rect);
+int 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 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 xrdp_orders_dest_blt(struct xrdp_orders* self, int x, int y,
+ int cx, int cy, int rop,
+ struct xrdp_rect* rect);
+int 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 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 xrdp_orders_send_palette(struct xrdp_orders* self, int* palette,
+ int cache_id);
+int xrdp_orders_send_raw_bitmap(struct xrdp_orders* self,
+ struct xrdp_bitmap* bitmap,
+ int cache_id, int cache_idx);
+
+/* xrdp_cache.c */
+struct xrdp_cache* xrdp_cache_create(struct xrdp_wm* owner,
+ struct xrdp_orders* orders);
+void xrdp_cache_delete(struct xrdp_cache* self);
+int xrdp_cache_add_bitmap(struct xrdp_cache* self, struct xrdp_bitmap* bitmap);
+int xrdp_cache_add_palette(struct xrdp_cache* self, int* palette);
+
+/* xrdp_wm.c */
+struct xrdp_wm* xrdp_wm_create(struct xrdp_process* owner);
+void xrdp_wm_delete(struct xrdp_wm* self);
+int xrdp_wm_send_palette(struct xrdp_wm* self);
+int xrdp_wm_init(struct xrdp_wm* self);
+int xrdp_wm_send_bitmap(struct xrdp_wm* self, struct xrdp_bitmap* bitmap,
+ int x, int y, int cx, int cy);
+int xrdp_wm_get_vis_region(struct xrdp_wm* self, struct xrdp_bitmap* bitmap,
+ int x, int y, int cx, int cy,
+ struct xrdp_region* region);
+int xrdp_wm_mouse_move(struct xrdp_wm* self, int x, int y);
+int xrdp_wm_mouse_click(struct xrdp_wm* self, int x, int y, int but, int down);
+int xrdp_wm_rect(struct xrdp_rect* r, int x, int y, int cx, int cy);
+int xrdp_wm_rect_is_empty(struct xrdp_rect* in);
+int xrdp_wm_rect_contains_pt(struct xrdp_rect* in, int x, int y);
+int xrdp_wm_rect_intersect(struct xrdp_rect* in1, struct xrdp_rect* in2,
+ struct xrdp_rect* out);
+int xrdp_wm_rect_offset(struct xrdp_rect* in, int dx, int dy);
+int xrdp_wm_color15(int r, int g, int b);
+int xrdp_wm_color16(int r, int g, int b);
+int xrdp_wm_color24(int r, int g, int b);
/* xrdp_process.c */
struct xrdp_process* xrdp_process_create(struct xrdp_listen* owner);
@@ -120,4 +202,58 @@ int xrdp_process_main_loop(struct xrdp_process* self);
/* xrdp_listen.c */
struct xrdp_listen* xrdp_listen_create(void);
void xrdp_listen_delete(struct xrdp_listen* self);
+int xrdp_listen_delete_pro(struct xrdp_listen* self, struct xrdp_process* pro);
int xrdp_listen_main_loop(struct xrdp_listen* self);
+
+/* xrdp_region.c */
+struct xrdp_region* xrdp_region_create(struct xrdp_wm* wm);
+void xrdp_region_delete(struct xrdp_region* self);
+int xrdp_region_add_rect(struct xrdp_region* self, struct xrdp_rect* rect);
+int xrdp_region_insert_rect(struct xrdp_region* self, int i, int left,
+ int top, int right, int bottom);
+int xrdp_region_subtract_rect(struct xrdp_region* self,
+ struct xrdp_rect* rect);
+int xrdp_region_get_rect(struct xrdp_region* self, int index,
+ struct xrdp_rect* rect);
+
+/* xrdp_bitmap.c */
+struct xrdp_bitmap* xrdp_bitmap_create(int width, int height, int bpp,
+ int type);
+void xrdp_bitmap_delete(struct xrdp_bitmap* self);
+int xrdp_bitmap_set_focus(struct xrdp_bitmap* self, int focused);
+int xrdp_bitmap_load(struct xrdp_bitmap* self, char* filename, int* palette);
+int xrdp_bitmap_get_pixel(struct xrdp_bitmap* self, int x, int y);
+int xrdp_bitmap_set_pixel(struct xrdp_bitmap* self, int x, int y, int pixel);
+int xrdp_bitmap_copy_box(struct xrdp_bitmap* self, struct xrdp_bitmap* dest,
+ int x, int y, int cx, int cy);
+int xrdp_bitmap_compare(struct xrdp_bitmap* self, struct xrdp_bitmap* b);
+int xrdp_bitmap_invalidate(struct xrdp_bitmap* self, struct xrdp_rect* rect);
+
+/* xrdp_painter.c */
+struct xrdp_painter* xrdp_painter_create(struct xrdp_wm* wn);
+void xrdp_painter_delete(struct xrdp_painter* self);
+int xrdp_painter_begin_update(struct xrdp_painter* self);
+int xrdp_painter_end_update(struct xrdp_painter* self);
+int xrdp_painter_set_clip(struct xrdp_painter* self,
+ int x, int y, int cx, int cy);
+int xrdp_painter_clr_clip(struct xrdp_painter* self);
+int xrdp_painter_fill_rect(struct xrdp_painter* self,
+ struct xrdp_bitmap* bitmap,
+ int x, int y, int cx, int cy);
+int xrdp_painter_fill_rect2(struct xrdp_painter* self,
+ struct xrdp_bitmap* bitmap,
+ int x, int y, int cx, int cy);
+int xrdp_painter_draw_bitmap(struct xrdp_painter* self,
+ struct xrdp_bitmap* bitmap,
+ struct xrdp_bitmap* to_draw,
+ int x, int y, int cx, int cy);
+
+/* xrdp_list.c */
+struct xrdp_list* xrdp_list_create(void);
+void xrdp_list_delete(struct xrdp_list* self);
+void xrdp_list_add_item(struct xrdp_list* self, int item);
+int xrdp_list_get_item(struct xrdp_list* self, int index);
+void xrdp_list_clear(struct xrdp_list* self);
+int xrdp_list_index_of(struct xrdp_list* self, int item);
+void xrdp_list_remove_item(struct xrdp_list* self, int index);
+void xrdp_list_insert_item(struct xrdp_list* self, int index, int item);
diff --git a/xrdp/xrdp_bitmap.c b/xrdp/xrdp_bitmap.c
new file mode 100644
index 00000000..2f965a2f
--- /dev/null
+++ b/xrdp/xrdp_bitmap.c
@@ -0,0 +1,479 @@
+
+/*
+ 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.
+
+ Copyright (C) Jay Sorg 2004
+
+ bitmap, drawable
+
+*/
+
+#include "xrdp.h"
+
+/*****************************************************************************/
+struct xrdp_bitmap* xrdp_bitmap_create(int width, int height, int bpp,
+ int type)
+{
+ struct xrdp_bitmap* self;
+ int Bpp;
+
+ self = (struct xrdp_bitmap*)g_malloc(sizeof(struct xrdp_bitmap), 1);
+ self->type = type;
+ self->width = width;
+ self->height = height;
+ self->bpp = bpp;
+ Bpp = 4;
+ switch (bpp)
+ {
+ case 8: Bpp = 1; break;
+ case 15: Bpp = 2; break;
+ case 16: Bpp = 2; break;
+ }
+ self->data = (char*)g_malloc(width * height * Bpp, 1);
+ self->child_list = xrdp_list_create();
+ self->line_size = ((width + 3) & ~3) * Bpp;
+ return self;
+}
+
+/*****************************************************************************/
+void xrdp_bitmap_delete(struct xrdp_bitmap* self)
+{
+ int i;
+
+ if (self == 0)
+ return;
+ if (self->wm != 0)
+ {
+ if (self->wm->focused_window == self)
+ self->wm->focused_window = 0;
+ if (self->wm->dragging_window == self)
+ self->wm->dragging_window = 0;
+ if (self->wm->button_down == self)
+ self->wm->button_down = 0;
+ }
+ for (i = 0; i < self->child_list->count; i++)
+ xrdp_bitmap_delete((struct xrdp_bitmap*)self->child_list->items[i]);
+ xrdp_list_delete(self->child_list);
+ g_free(self->data);
+ g_free(self);
+}
+
+/*****************************************************************************/
+int xrdp_bitmap_set_focus(struct xrdp_bitmap* self, int focused)
+{
+ struct xrdp_painter* painter;
+
+ if (self == 0)
+ return 0;
+ if (self->type != 1)
+ return 0;
+ self->focused = focused;
+ painter = xrdp_painter_create(self->wm);
+ xrdp_painter_begin_update(painter);
+ if (focused)
+ {
+ /* active title bar */
+ painter->fg_color = self->wm->blue;
+ xrdp_painter_fill_rect(painter, self, 3, 3, self->width - 5, 18);
+ }
+ else
+ {
+ /* inactive title bar */
+ painter->fg_color = self->wm->dark_grey;
+ xrdp_painter_fill_rect(painter, self, 3, 3, self->width - 5, 18);
+ }
+ DEBUG(("1\n\r"));
+ xrdp_painter_end_update(painter);
+ DEBUG(("2\n\r"));
+ xrdp_painter_delete(painter);
+ DEBUG(("3\n\r"));
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_bitmap_get_index(struct xrdp_bitmap* self, int* palette, int color)
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ {
+ if (color == palette[i])
+ return i;
+ }
+ for (i = 1; i < 256; i++)
+ {
+ if (palette[i] == 0)
+ {
+ palette[i] = color;
+ return i;
+ }
+ }
+ g_printf("color %8.8x not found\n", color);
+ return 255;
+}
+
+/*****************************************************************************/
+int xrdp_bitmap_resize(struct xrdp_bitmap* self, int width, int height)
+{
+ int Bpp;
+
+ g_free(self->data);
+ self->width = width;
+ self->height = height;
+ Bpp = 4;
+ switch (self->bpp)
+ {
+ case 8: Bpp = 1; break;
+ case 15: Bpp = 2; break;
+ case 16: Bpp = 2; break;
+ }
+ self->data = (char*)g_malloc(width * height * Bpp, 1);
+ self->line_size = ((width + 3) & ~3) * Bpp;
+ return 0;
+}
+
+/*****************************************************************************/
+/* load a bmp file */
+/* return 0 ok */
+/* return 1 error */
+int xrdp_bitmap_load(struct xrdp_bitmap* self, char* filename, int* palette)
+{
+ int fd;
+ int i;
+ int j;
+ int k;
+ int color;
+ int size;
+ int palette1[256];
+ char type1[3];
+ char* data;
+ struct xrdp_bmp_header header;
+
+ fd = g_file_open(filename);
+ if (fd != -1)
+ {
+ /* read file type */
+ if (g_file_read(fd, type1, 2) != 2)
+ {
+ g_file_close(fd);
+ return 1;
+ }
+ if (type1[0] != 'B' || type1[1] != 'M')
+ {
+ g_file_close(fd);
+ return 1;
+ }
+ /* read file size */
+ size = 0;
+ g_file_read(fd, (char*)&size, 4);
+ /* read bmp header */
+ g_file_seek(fd, 14);
+ g_file_read(fd, (char*)&header, sizeof(header));
+ if (header.bit_count != 8 && header.bit_count != 24)
+ {
+ g_file_close(fd);
+ return 1;
+ }
+ if (header.bit_count == 24) /* 24 bit bitmap */
+ {
+ g_file_seek(fd, 14 + header.size);
+ }
+ if (header.bit_count == 8) /* 8 bit bitmap */
+ {
+ /* read palette */
+ g_file_seek(fd, 14 + header.size);
+ g_file_read(fd, (char*)palette1, 256 * sizeof(int));
+ /* read data */
+ xrdp_bitmap_resize(self, header.image_width, header.image_height);
+ data = (char*)g_malloc(header.image_width * header.image_height, 1);
+ for (i = header.image_height - 1; i >= 0; i--)
+ g_file_read(fd, data + i * header.image_width, header.image_width);
+ for (i = 0; i < self->height; i++)
+ {
+ for (j = 0; j < self->width; j++)
+ {
+ k = (unsigned char)data[i * header.image_width + j];
+ color = palette1[k];
+ if (self->bpp == 8)
+ color = xrdp_bitmap_get_index(self, palette, color);
+ else if (self->bpp == 15)
+ color = xrdp_wm_color15((color & 0xff0000) >> 16,
+ (color & 0x00ff00) >> 8,
+ (color & 0x0000ff) >> 0);
+ else if (self->bpp == 16)
+ color = xrdp_wm_color16((color & 0xff0000) >> 16,
+ (color & 0x00ff00) >> 8,
+ (color & 0x0000ff) >> 0);
+ else if (self->bpp == 24)
+ color = xrdp_wm_color24((color & 0xff0000) >> 16,
+ (color & 0x00ff00) >> 8,
+ (color & 0x0000ff) >> 0);
+ xrdp_bitmap_set_pixel(self, j, i, color);
+ }
+ }
+ g_free(data);
+ }
+ g_file_close(fd);
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_bitmap_get_pixel(struct xrdp_bitmap* self, int x, int y)
+{
+ if (self == 0)
+ return 0;
+ if (self->data == 0)
+ return 0;
+ if (x >= 0 && x < self->width && y >= 0 && y < self->height)
+ {
+ if (self->bpp == 8)
+ return self->data[y * self->width + x];
+ else if (self->bpp == 15 || self->bpp == 16)
+ return ((short*)self->data)[y * self->width + x];
+ else if (self->bpp == 24)
+ return ((int*)self->data)[y * self->width + x];
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_bitmap_set_pixel(struct xrdp_bitmap* self, int x, int y, int pixel)
+{
+ if (x >= 0 && x < self->width && y >= 0 && y < self->height)
+ {
+ if (self->bpp == 8)
+ self->data[y * self->width + x] = pixel;
+ else if (self->bpp == 15 || self->bpp == 16)
+ ((short*)(self->data))[y * self->width + x] = pixel;
+ else if (self->bpp == 24)
+ ((int*)(self->data))[y * self->width + x] = pixel;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_bitmap_copy_box(struct xrdp_bitmap* self, struct xrdp_bitmap* dest,
+ int x, int y, int cx, int cy)
+{
+ int i;
+ int j;
+
+ if (self == 0)
+ return 0;
+ if (dest == 0)
+ return 0;
+ if (self->bpp != dest->bpp)
+ return 0;
+ for (i = 0; i < cy; i++)
+ {
+ for (j = 0; j < cx; j++)
+ {
+ xrdp_bitmap_set_pixel(dest, j, i,
+ xrdp_bitmap_get_pixel(self, j + x, i + y));
+ }
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_bitmap_compare(struct xrdp_bitmap* self, struct xrdp_bitmap* b)
+{
+ if (self == 0)
+ return 0;
+ if (b == 0)
+ return 0;
+ if (self->bpp != b->bpp)
+ return 0;
+ if (self->width != b->width)
+ return 0;
+ if (self->height != b->height)
+ return 0;
+ if (g_memcmp(self->data, b->data, b->height * b->line_size) == 0)
+ return 1;
+ return 0;
+}
+
+/*****************************************************************************/
+/* nil for rect means the whole thing */
+int xrdp_bitmap_invalidate(struct xrdp_bitmap* self, struct xrdp_rect* rect)
+{
+ int i;
+ struct xrdp_bitmap* b;
+ struct xrdp_rect r1;
+ struct xrdp_rect r2;
+ struct xrdp_painter* painter;
+
+ if (self == 0) /* if no bitmap */
+ return 0;
+ if (self->type == 0) /* if bitmap, leave */
+ return 0;
+ painter = xrdp_painter_create(self->wm);
+ painter->rop = 0xcc; /* copy */
+ if (rect == 0)
+ painter->use_clip = 0;
+ else
+ {
+ if (xrdp_wm_rect_is_empty(rect))
+ {
+ xrdp_painter_delete(painter);
+ return 0;
+ }
+ painter->clip = *rect;
+ painter->use_clip = 1;
+ }
+ xrdp_painter_begin_update(painter);
+ if (self->type == 1) /* normal window */
+ {
+ /* draw grey background */
+ painter->fg_color = self->bg_color;
+ xrdp_painter_fill_rect(painter, self, 0, 0, self->width, self->height);
+ /* top white line */
+ painter->fg_color = self->wm->white;
+ xrdp_painter_fill_rect(painter, self, 1, 1, self->width - 2, 1);
+ /* left white line */
+ painter->fg_color = self->wm->white;
+ xrdp_painter_fill_rect(painter, self, 1, 1, 1, self->height - 2);
+ /* bottom dark grey line */
+ painter->fg_color = self->wm->dark_grey;
+ xrdp_painter_fill_rect(painter, self, 1, self->height - 2,
+ self->width - 2, 1);
+ /* right dark grey line */
+ painter->fg_color = self->wm->dark_grey;
+ xrdp_painter_fill_rect(painter, self, self->width - 2, 1, 1,
+ self->height - 2);
+ /* bottom black line */
+ painter->fg_color = self->wm->black;
+ xrdp_painter_fill_rect(painter, self, 0, self->height - 1,
+ self->width, 1);
+ /* right black line */
+ painter->fg_color = self->wm->black;
+ xrdp_painter_fill_rect(painter, self, self->width - 1, 0,
+ 1, self->height);
+ if (self->focused)
+ {
+ /* active title bar */
+ painter->fg_color = self->wm->blue;
+ xrdp_painter_fill_rect(painter, self, 3, 3, self->width - 5, 18);
+ }
+ else
+ {
+ /* inactive title bar */
+ painter->fg_color = self->wm->dark_grey;
+ xrdp_painter_fill_rect(painter, self, 3, 3, self->width - 5, 18);
+ }
+ }
+ else if (self->type == 2) /* screen */
+ {
+ painter->fg_color = self->bg_color;
+ xrdp_painter_fill_rect(painter, self, 0, 0, self->width, self->height);
+ }
+ else if (self->type == 3) /* button */
+ {
+ if (self->state == 0) /* button up */
+ {
+ /* gray box */
+ painter->fg_color = self->wm->grey;
+ xrdp_painter_fill_rect(painter, self, 0, 0, self->width, self->height);
+ /* white top line */
+ painter->fg_color = self->wm->white;
+ xrdp_painter_fill_rect(painter, self, 0, 0, self->width, 1);
+ /* white left line */
+ painter->fg_color = self->wm->white;
+ xrdp_painter_fill_rect(painter, self, 0, 0, 1, self->height);
+ /* dark grey bottom line */
+ painter->fg_color = self->wm->dark_grey;
+ xrdp_painter_fill_rect(painter, self, 1, self->height - 2,
+ self->width - 1, 1);
+ /* dark grey right line */
+ painter->fg_color = self->wm->dark_grey;
+ xrdp_painter_fill_rect(painter, self, self->width - 2, 1,
+ 1, self->height - 1);
+ /* black bottom line */
+ painter->fg_color = self->wm->black;
+ xrdp_painter_fill_rect(painter, self, 0, self->height - 1, self->width, 1);
+ /* black right line */
+ painter->fg_color = self->wm->black;
+ xrdp_painter_fill_rect(painter, self, self->width - 1, 0, 1, self->height);
+ }
+ else if (self->state == 1) /* button down */
+ {
+ /* black top line */
+ painter->fg_color = self->wm->black;
+ xrdp_painter_fill_rect(painter, self, 0, 0, self->width, 1);
+ /* black left line */
+ painter->fg_color = self->wm->black;
+ xrdp_painter_fill_rect(painter, self, 0, 0, 1, self->height);
+ /* dark grey top line */
+ painter->fg_color = self->wm->dark_grey;
+ xrdp_painter_fill_rect(painter, self, 1, 1, self->width - 2, 1);
+ /* dark grey left line */
+ painter->fg_color = self->wm->dark_grey;
+ xrdp_painter_fill_rect(painter, self, 1, 1, 1, self->height - 2);
+ }
+ }
+ else if (self->type == 4) /* image */
+ {
+ xrdp_painter_draw_bitmap(painter, self, self, 0, 0, self->width,
+ self->height);
+ }
+ else if (self->type == 5) /* edit */
+ {
+ /* draw gray box */
+ painter->fg_color = self->wm->grey;
+ xrdp_painter_fill_rect(painter, self, 0, 0, self->width, self->height);
+ /* main white background */
+ painter->fg_color = self->wm->white;
+ xrdp_painter_fill_rect(painter, self, 1, 1, self->width - 3,
+ self->height - 3);
+ /* dark grey top line */
+ painter->fg_color = self->wm->dark_grey;
+ xrdp_painter_fill_rect(painter, self, 0, 0, self->width, 1);
+ /* dark grey left line */
+ painter->fg_color = self->wm->dark_grey;
+ xrdp_painter_fill_rect(painter, self, 0, 0, 1, self->height);
+ /* white bottom line */
+ painter->fg_color = self->wm->white;
+ xrdp_painter_fill_rect(painter, self, 0, self->height- 1, self->width, 1);
+ /* white right line */
+ painter->fg_color = self->wm->white;
+ xrdp_painter_fill_rect(painter, self, self->width - 1, 0, 1, self->height);
+ /* black left line */
+ painter->fg_color = self->wm->black;
+ xrdp_painter_fill_rect(painter, self, 1, 1, 1, self->height - 2);
+ /* black top line */
+ painter->fg_color = self->wm->black;
+ xrdp_painter_fill_rect(painter, self, 1, 1, self->width - 2, 1);
+ }
+ /* draw any child windows in the area */
+ for (i = 0; i < self->child_list->count; i++)
+ {
+ b = (struct xrdp_bitmap*)xrdp_list_get_item(self->child_list, i);
+ if (rect == 0)
+ xrdp_bitmap_invalidate(b, 0);
+ else
+ {
+ xrdp_wm_rect(&r1, b->left, b->top, b->width, b->height);
+ if (xrdp_wm_rect_intersect(rect, &r1, &r2))
+ {
+ xrdp_wm_rect_offset(&r2, -(b->left), -(b->top));
+ xrdp_bitmap_invalidate(b, &r2);
+ }
+ }
+ }
+ xrdp_painter_end_update(painter);
+ xrdp_painter_delete(painter);
+ return 0;
+}
diff --git a/xrdp/xrdp_cache.c b/xrdp/xrdp_cache.c
new file mode 100644
index 00000000..a62ae6f2
--- /dev/null
+++ b/xrdp/xrdp_cache.c
@@ -0,0 +1,145 @@
+
+/*
+ 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.
+
+ Copyright (C) Jay Sorg 2004
+
+ cache
+
+*/
+
+#include "xrdp.h"
+
+/*****************************************************************************/
+struct xrdp_cache* xrdp_cache_create(struct xrdp_wm* owner,
+ struct xrdp_orders* orders)
+{
+ struct xrdp_cache* self;
+
+ self = (struct xrdp_cache*)g_malloc(sizeof(struct xrdp_cache), 1);
+ self->wm = owner;
+ self->orders = orders;
+ return self;
+}
+
+/*****************************************************************************/
+void xrdp_cache_delete(struct xrdp_cache* self)
+{
+ int i;
+ int j;
+
+ if (self == 0)
+ return;
+ /* free all the cached bitmaps */
+ for (i = 0; i < 3; i++)
+ for (j = 0; j < 600; j++)
+ xrdp_bitmap_delete(self->bitmap_items[i][j].bitmap);
+ g_free(self);
+}
+
+/*****************************************************************************/
+/* returns cache id */
+int xrdp_cache_add_bitmap(struct xrdp_cache* self, struct xrdp_bitmap* bitmap)
+{
+ int i;
+ int j;
+ int min_use;
+ int min_use_index1;
+ int min_use_index2;
+ struct xrdp_bitmap* b;
+
+ /* look for match */
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 0; j < 600; j++)
+ {
+ if (xrdp_bitmap_compare(self->bitmap_items[i][j].bitmap, bitmap))
+ {
+ self->bitmap_items[i][j].use_count++;
+ DEBUG(("found bitmap at %d %d\n", i, j));
+ return (i << 16) | j;
+ }
+ }
+ }
+ /* look for least used */
+ min_use_index1 = 0;
+ min_use_index2 = 0;
+ min_use = 999999;
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 0; j < 600; j++)
+ {
+ if (self->bitmap_items[i][j].use_count < min_use)
+ {
+ min_use = self->bitmap_items[i][j].use_count;
+ min_use_index1 = i;
+ min_use_index2 = j;
+ }
+ }
+ }
+ DEBUG(("adding bitmap at %d %d\n", min_use_index1, min_use_index2));
+ /* set, send bitmap and return */
+ xrdp_bitmap_delete(self->bitmap_items[min_use_index1]
+ [min_use_index2].bitmap);
+ b = xrdp_bitmap_create(bitmap->width, bitmap->height, bitmap->bpp, 0);
+ xrdp_bitmap_copy_box(bitmap, b, 0, 0, bitmap->width, bitmap->height);
+ self->bitmap_items[min_use_index1][min_use_index2].bitmap = b;
+ self->bitmap_items[min_use_index1][min_use_index2].use_count++;
+ xrdp_orders_send_raw_bitmap(self->orders, b, min_use_index1,
+ min_use_index2);
+ return (min_use_index1 << 16) | min_use_index2;
+}
+
+/*****************************************************************************/
+int xrdp_cache_add_palette(struct xrdp_cache* self, int* palette)
+{
+ int i;
+ int min_use;
+ int min_use_index;
+
+ if (self == 0)
+ return 0;
+ if (palette == 0)
+ return 0;
+ if (self->wm->screen->bpp > 8)
+ return 0;
+ /* look for match */
+ for (i = 0; i < 6; i++)
+ {
+ if (g_memcmp(palette, self->palette_items[i].palette,
+ 256 * sizeof(int)) == 0)
+ {
+ self->palette_items[i].use_count++;
+ return i;
+ }
+ }
+ /* look for least used */
+ min_use_index = 0;
+ min_use = 999999;
+ for (i = 0; i < 6; i++)
+ {
+ if (self->palette_items[i].use_count < min_use)
+ {
+ min_use = self->palette_items[i].use_count;
+ min_use_index = i;
+ }
+ }
+ /* set, send palette and return */
+ g_memcpy(self->palette_items[min_use_index].palette, palette,
+ 256 * sizeof(int));
+ self->palette_items[min_use_index].use_count++;
+ xrdp_orders_send_palette(self->orders, palette, min_use_index);
+ return min_use_index;
+}
diff --git a/xrdp/xrdp_iso.c b/xrdp/xrdp_iso.c
index 8bbbcbdc..985e5aac 100644
--- a/xrdp/xrdp_iso.c
+++ b/xrdp/xrdp_iso.c
@@ -37,6 +37,8 @@ struct xrdp_iso* xrdp_iso_create(struct xrdp_mcs* owner)
/*****************************************************************************/
void xrdp_iso_delete(struct xrdp_iso* self)
{
+ if (self == 0)
+ return;
xrdp_tcp_delete(self->tcp_layer);
g_free(self);
}
@@ -137,6 +139,7 @@ int xrdp_iso_send(struct xrdp_iso* self)
{
int len;
+ DEBUG((" in xrdp_iso_send\n\r"));
s_pop_layer(self->out_s, iso_hdr);
len = self->out_s->end - self->out_s->p;
out_uint8(self->out_s, 3);
@@ -147,5 +150,6 @@ int xrdp_iso_send(struct xrdp_iso* self)
out_uint8(self->out_s, 0x80);
if (xrdp_tcp_send(self->tcp_layer) != 0)
return 1;
+ DEBUG((" out xrdp_iso_send\n\r"));
return 0;
}
diff --git a/xrdp/xrdp_list.c b/xrdp/xrdp_list.c
new file mode 100644
index 00000000..6a3cd12d
--- /dev/null
+++ b/xrdp/xrdp_list.c
@@ -0,0 +1,149 @@
+/*
+ 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.
+
+ Copyright (C) Jay Sorg 2004
+
+ simple list
+
+ this list is used to track mem leaks so g_malloc1 and
+ g_free1 should be used for internal allocs but not
+ for auto_free items
+
+*/
+
+#include "xrdp.h"
+
+/*****************************************************************************/
+struct xrdp_list* xrdp_list_create(void)
+{
+ struct xrdp_list* self;
+
+ self = (struct xrdp_list*)g_malloc1(sizeof(struct xrdp_list), 1);
+ self->grow_by = 10;
+ self->alloc_size = 10;
+ self->items = (int*)g_malloc1(sizeof(int) * 10, 1);
+ return self;
+}
+
+/*****************************************************************************/
+void xrdp_list_delete(struct xrdp_list* self)
+{
+ int i;
+
+ if (self == 0)
+ return;
+ if (self->auto_free)
+ for (i = 0; i < self->count; i++)
+ g_free((void*)self->items[i]);
+ g_free1(self->items);
+ g_free1(self);
+}
+
+/*****************************************************************************/
+void xrdp_list_add_item(struct xrdp_list* self, int item)
+{
+ int* p;
+ int i;
+
+ if (self->count >= self->alloc_size)
+ {
+ i = self->alloc_size;
+ self->alloc_size += self->grow_by;
+ p = (int*)g_malloc1(sizeof(int) * self->alloc_size, 1);
+ g_memcpy(p, self->items, sizeof(int) * i);
+ g_free1(self->items);
+ self->items = p;
+ }
+ self->items[self->count] = item;
+ self->count++;
+}
+
+/*****************************************************************************/
+int xrdp_list_get_item(struct xrdp_list* self, int index)
+{
+ if (index < 0 || index >= self->count)
+ return 0;
+ return self->items[index];
+}
+
+/*****************************************************************************/
+void xrdp_list_clear(struct xrdp_list* self)
+{
+ int i;
+
+ if (self->auto_free)
+ for (i = 0; i < self->count; i++)
+ g_free((void*)self->items[i]);
+ g_free1(self->items);
+ self->count = 0;
+ self->grow_by = 10;
+ self->alloc_size = 10;
+ self->items = (int*)g_malloc1(sizeof(int) * 10, 1);
+}
+
+/*****************************************************************************/
+int xrdp_list_index_of(struct xrdp_list* self, int item)
+{
+ int i;
+
+ for (i = 0; i < self->count; i++)
+ if (self->items[i] == item)
+ return i;
+ return -1;
+}
+
+/*****************************************************************************/
+void xrdp_list_remove_item(struct xrdp_list* self, int index)
+{
+ int i;
+
+ if (index >= 0 && index < self->count)
+ {
+ if (self->auto_free)
+ g_free((void*)self->items[index]);
+ for (i = index; i < (self->count - 1); i++)
+ self->items[i] = self->items[i + 1];
+ self->count--;
+ }
+}
+
+/*****************************************************************************/
+void xrdp_list_insert_item(struct xrdp_list* self, int index, int item)
+{
+ int* p;
+ int i;
+
+ if (index == self->count)
+ {
+ xrdp_list_add_item(self, item);
+ return;
+ }
+ if (index >= 0 && index < self->count)
+ {
+ self->count++;
+ if (self->count > self->alloc_size)
+ {
+ i = self->alloc_size;
+ self->alloc_size += self->grow_by;
+ p = (int*)g_malloc1(sizeof(int) * self->alloc_size, 1);
+ g_memcpy(p, self->items, sizeof(int) * i);
+ g_free1(self->items);
+ self->items = p;
+ }
+ for (i = (self->count - 2); i >= index; i--)
+ self->items[i + 1] = self->items[i];
+ self->items[index] = item;
+ }
+}
diff --git a/xrdp/xrdp_listen.c b/xrdp/xrdp_listen.c
index 2112a7ef..1d1a5f7f 100644
--- a/xrdp/xrdp_listen.c
+++ b/xrdp/xrdp_listen.c
@@ -76,6 +76,7 @@ int xrdp_listen_add_pro(struct xrdp_listen* self)
return 0;
}
/* add process in unused slot */
+ /* this shouldn't happen */
if (self->process_list[i]->status <= 0)
{
xrdp_process_delete(self->process_list[i]);
@@ -87,6 +88,24 @@ int xrdp_listen_add_pro(struct xrdp_listen* self)
}
/*****************************************************************************/
+int xrdp_listen_delete_pro(struct xrdp_listen* self, struct xrdp_process* pro)
+{
+ int i;
+
+ for (i = 0; i < self->process_list_max; i++)
+ {
+ if (self->process_list[i] == pro)
+ {
+ DEBUG(("process deleted\n\r"));
+ xrdp_process_delete(pro);
+ self->process_list[i] = 0;
+ return 0;
+ }
+ }
+ return 0;
+}
+
+/*****************************************************************************/
/* i can't get stupid in_val to work, hum using global var for now */
void* xrdp_process_run(void* in_val)
{
@@ -131,6 +150,10 @@ int xrdp_listen_main_loop(struct xrdp_listen* self)
}
}
}
+ else
+ {
+ DEBUG(("error, listener done\n\r"));
+ }
xrdp_listen_term_processes(self);
g_tcp_close(self->sck);
self->status = -1;
diff --git a/xrdp/xrdp_mcs.c b/xrdp/xrdp_mcs.c
index 4cc24b89..0d26bb3c 100644
--- a/xrdp/xrdp_mcs.c
+++ b/xrdp/xrdp_mcs.c
@@ -41,6 +41,8 @@ struct xrdp_mcs* xrdp_mcs_create(struct xrdp_sec* owner)
/*****************************************************************************/
void xrdp_mcs_delete(struct xrdp_mcs* self)
{
+ if (self == 0)
+ return;
xrdp_iso_delete(self->iso_layer);
g_free(self);
}
@@ -64,7 +66,7 @@ int xrdp_mcs_send_cjcf(struct xrdp_mcs* self, int chanid)
/*****************************************************************************/
/* returns error */
-int xrdp_mcs_recv(struct xrdp_mcs* self)
+int xrdp_mcs_recv(struct xrdp_mcs* self, int* chan)
{
int appid;
int opcode;
@@ -91,7 +93,9 @@ int xrdp_mcs_recv(struct xrdp_mcs* self)
DEBUG((" out xrdp_mcs_recv err got 0x%x need MCS_SDRQ\n\r", appid));
return 1;
}
- in_uint8s(self->in_s, 5);
+ in_uint8s(self->in_s, 2);
+ in_uint16_be(self->in_s, *chan);
+ in_uint8s(self->in_s, 1);
in_uint8(self->in_s, len);
if (len & 0x80)
in_uint8s(self->in_s, 1);
@@ -407,6 +411,7 @@ int xrdp_mcs_send(struct xrdp_mcs* self)
{
int len;
+ DEBUG((" in xrdp_mcs_send\n\r"));
s_pop_layer(self->out_s, mcs_hdr);
len = (self->out_s->end - self->out_s->p) - 8;
len = len | 0x8000;
@@ -417,5 +422,27 @@ int xrdp_mcs_send(struct xrdp_mcs* self)
out_uint16_be(self->out_s, len);
if (xrdp_iso_send(self->iso_layer) != 0)
return 1;
+ DEBUG((" out xrdp_mcs_send\n\r"));
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int xrdp_mcs_disconnect(struct xrdp_mcs* self)
+{
+ int len;
+
+ xrdp_mcs_init(self, 100);
+ s_mark_end(self->out_s);
+ s_pop_layer(self->out_s, mcs_hdr);
+ len = (self->out_s->end - self->out_s->p) - 8;
+ len = len | 0x8000;
+ out_uint8(self->out_s, MCS_DPUM << 2);
+ out_uint16_be(self->out_s, self->userid);
+ out_uint16_be(self->out_s, MCS_GLOBAL_CHANNEL);
+ out_uint8(self->out_s, 0x70);
+ out_uint16_be(self->out_s, len);
+ if (xrdp_iso_send(self->iso_layer) != 0)
+ return 1;
return 0;
}
diff --git a/xrdp/xrdp_orders.c b/xrdp/xrdp_orders.c
new file mode 100644
index 00000000..c7644726
--- /dev/null
+++ b/xrdp/xrdp_orders.c
@@ -0,0 +1,976 @@
+
+/*
+ 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.
+
+ Copyright (C) Jay Sorg 2004
+
+ orders
+
+*/
+
+#include "xrdp.h"
+
+/*****************************************************************************/
+struct xrdp_orders* xrdp_orders_create(struct xrdp_process* owner)
+{
+ struct xrdp_orders* self;
+
+ self = (struct xrdp_orders*)g_malloc(sizeof(struct xrdp_orders), 1);
+ self->pro_layer = owner;
+ self->rdp_layer = owner->rdp_layer;
+ self->out_s = &owner->out_s;
+ return self;
+}
+
+/*****************************************************************************/
+void xrdp_orders_delete(struct xrdp_orders* self)
+{
+ g_free(self);
+}
+
+/*****************************************************************************/
+/* returns error */
+int xrdp_orders_init(struct xrdp_orders* self)
+{
+ self->order_level++;
+ if (self->order_level == 1)
+ {
+ self->order_count = 0;
+ if (xrdp_rdp_init_data(self->rdp_layer, 8192) != 0) /* is this big enough */
+ 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 xrdp_orders_send(struct xrdp_orders* self)
+{
+ int rv;
+
+ rv = 0;
+ if (self->order_level > 0)
+ {
+ self->order_level--;
+ if (self->order_level == 0)
+ {
+ s_mark_end(self->out_s);
+ *((short*)self->order_count_ptr) = self->order_count;
+ if (xrdp_rdp_send_data(self->rdp_layer, RDP_DATA_PDU_UPDATE) != 0)
+ rv = 1;
+ }
+ }
+ return rv;
+}
+
+/*****************************************************************************/
+/* returns error */
+int xrdp_orders_force_send(struct xrdp_orders* self)
+{
+ if (self->order_count > 0)
+ {
+ s_mark_end(self->out_s);
+ *((short*)self->order_count_ptr) = self->order_count;
+ if (xrdp_rdp_send_data(self->rdp_layer, RDP_DATA_PDU_UPDATE) != 0)
+ return 1;
+ }
+ self->order_count = 0;
+ self->order_level = 0;
+ return 0;
+}
+
+/*****************************************************************************/
+int 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;
+}
+
+/*****************************************************************************/
+/* returns boolean */
+int 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;
+}
+
+/*****************************************************************************/
+/* returns boolean */
+int 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 */
+int 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 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 = present;
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+/* send a screen blt order */
+/* max size 25 */
+int 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 = present;
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+/* send a pat blt order */
+/* max size 39 */
+int 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);
+ }
+ *((short*)present_ptr) = present;
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+/* send a dest blt order */
+/* max size 21 */
+int 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 |= 0x0010;
+ out_uint8(self->out_s, rop);
+ self->dest_blt_rop = rop;
+ }
+ *present_ptr = present;
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+/* send a line order */
+/* max size 32 */
+int 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;
+ }
+ *((short*)present_ptr) = present;
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+/* send a mem blt order */
+/* max size 30 */
+int 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;
+ }
+ *((short*)present_ptr) = present;
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+/* when a palette gets sent, send the main palette too */
+/* don't need max size here */
+int xrdp_orders_send_palette(struct xrdp_orders* self, int* palette,
+ int cache_id)
+{
+ int order_flags;
+ int len;
+ int i;
+
+ /* gota clear any build up orders and send the main palette */
+ xrdp_orders_force_send(self);
+ xrdp_wm_send_palette(self->pro_layer->wm);
+ xrdp_orders_init(self);
+ 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 xrdp_orders_send_raw_bitmap(struct xrdp_orders* self,
+ struct xrdp_bitmap* bitmap,
+ int cache_id, int cache_idx)
+{
+ int order_flags;
+ int len;
+ int bufsize;
+ int Bpp;
+ int i;
+ int j;
+ int pixel;
+
+ Bpp = (bitmap->bpp + 7) / 8;
+ bufsize = bitmap->width * bitmap->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;
+ 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, bitmap->width);
+ out_uint8(self->out_s, bitmap->height);
+ out_uint8(self->out_s, bitmap->bpp);
+ out_uint16_le(self->out_s, bufsize);
+ out_uint16_le(self->out_s, cache_idx);
+ for (i = bitmap->height - 1; i >= 0; i--)
+ for (j = 0; j < bitmap->width; j++)
+ {
+ pixel = xrdp_bitmap_get_pixel(bitmap, j, i);
+ if (Bpp == 3)
+ {
+ out_uint8(self->out_s, pixel >> 16);
+ out_uint8(self->out_s, pixel >> 8);
+ out_uint8(self->out_s, pixel);
+ }
+ else if (Bpp == 2)
+ {
+ out_uint8(self->out_s, pixel);
+ out_uint8(self->out_s, pixel >> 8);
+ }
+ else if (Bpp == 1)
+ out_uint8(self->out_s, pixel);
+ }
+ return 0;
+}
diff --git a/xrdp/xrdp_painter.c b/xrdp/xrdp_painter.c
new file mode 100644
index 00000000..b09df176
--- /dev/null
+++ b/xrdp/xrdp_painter.c
@@ -0,0 +1,333 @@
+
+/*
+ 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.
+
+ Copyright (C) Jay Sorg 2004
+
+ painter, gc
+
+*/
+
+#include "xrdp.h"
+
+/*****************************************************************************/
+struct xrdp_painter* xrdp_painter_create(struct xrdp_wm* wm)
+{
+ struct xrdp_painter* self;
+
+ self = (struct xrdp_painter*)g_malloc(sizeof(struct xrdp_painter), 1);
+ self->wm = wm;
+ self->orders = wm->orders;
+ self->rop = 0xcc; /* copy */
+ return self;
+}
+
+/*****************************************************************************/
+void xrdp_painter_delete(struct xrdp_painter* self)
+{
+ if (self == 0)
+ return;
+ g_free(self);
+}
+
+/*****************************************************************************/
+int xrdp_painter_begin_update(struct xrdp_painter* self)
+{
+ xrdp_orders_init(self->orders);
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_painter_end_update(struct xrdp_painter* self)
+{
+ xrdp_orders_send(self->orders);
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_painter_clip_adj(struct xrdp_painter* self, int* x, int* y,
+ int* cx, int* cy)
+{
+ int dx;
+ int dy;
+
+ if (!self->use_clip)
+ return 1;
+ if (self->clip.left > *x)
+ dx = self->clip.left - *x;
+ else
+ dx = 0;
+ if (self->clip.top > *y)
+ dy = self->clip.top - *y;
+ else
+ dy = 0;
+ if (*x + *cx > self->clip.right)
+ *cx = *cx - ((*x + *cx) - self->clip.right);
+ if (*y + *cy > self->clip.bottom)
+ *cy = *cy - ((*y + *cy) - self->clip.bottom);
+ *cx = *cx - dx;
+ *cy = *cy - dy;
+ if (*cx <= 0)
+ return 0;
+ if (*cy <= 0)
+ return 0;
+ *x = *x + dx;
+ *y = *y + dy;
+ return 1;
+}
+
+/*****************************************************************************/
+int xrdp_painter_set_clip(struct xrdp_painter* self,
+ int x, int y, int cx, int cy)
+{
+ self->use_clip = 1;
+ self->clip.left = x;
+ self->clip.top = y;
+ self->clip.right = x + cx;
+ self->clip.bottom = y + cy;
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_painter_clr_clip(struct xrdp_painter* self)
+{
+ self->use_clip = 0;
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_painter_rop(int rop, int src, int dst)
+{
+ switch (rop & 0x0f)
+ {
+ case 0x0: return 0;
+ case 0x1: return ~(src | dst);
+ case 0x2: return (~src) & dst;
+ case 0x3: return ~src;
+ case 0x4: return src & (~dst);
+ case 0x5: return ~(dst);
+ case 0x6: return src ^ dst;
+ case 0x7: return ~(src & dst);
+ case 0x8: return src & dst;
+ case 0x9: return ~(src) ^ dst;
+ case 0xa: return dst;
+ case 0xb: return (~src) | dst;
+ case 0xc: return src;
+ case 0xd: return src | (~dst);
+ case 0xe: return src | dst;
+ case 0xf: return ~0;
+ }
+ return dst;
+}
+
+/*****************************************************************************/
+/* fill in an area of the screen with one color */
+int xrdp_painter_fill_rect(struct xrdp_painter* self,
+ struct xrdp_bitmap* bitmap,
+ int x, int y, int cx, int cy)
+{
+ int i;
+ struct xrdp_region* region;
+ struct xrdp_rect rect;
+
+ if (x >= bitmap->width) return 0;
+ if (y >= bitmap->height) return 0;
+ if (x < 0) { cx += x; x = 0; }
+ if (y < 0) { cy += y; y = 0; }
+ if (cx <= 0) return 0;
+ if (cy <= 0) return 0;
+ if (x + cx > bitmap->width) cx = bitmap->width - x;
+ if (y + cy > bitmap->height) cy = bitmap->height - y;
+
+ if (!xrdp_painter_clip_adj(self, &x, &y, &cx, &cy))
+ return 0;
+
+ if (bitmap->type == 0)
+ return 0;
+ region = xrdp_region_create(self->wm);
+ xrdp_wm_get_vis_region(self->wm, bitmap, x, y, cx, cy, region);
+ i = 0;
+ while (xrdp_region_get_rect(region, i, &rect) == 0)
+ {
+ DEBUG(("sending rect order %d %d %d %d\n\r", rect.left, rect.top,
+ rect.right, rect.bottom));
+ xrdp_orders_rect(self->orders, rect.left, rect.top,
+ rect.right - rect.left,
+ rect.bottom - rect.top,
+ self->fg_color, 0);
+ i++;
+ }
+ xrdp_region_delete(region);
+ return 0;
+}
+
+/*****************************************************************************/
+/* fill in an area of the screen with opcodes and patterns */
+/* todo, this needs work */
+int xrdp_painter_fill_rect2(struct xrdp_painter* self,
+ struct xrdp_bitmap* bitmap,
+ int x, int y, int cx, int cy)
+{
+ int i;
+ struct xrdp_region* region;
+ struct xrdp_rect rect;
+
+ if (x >= bitmap->width) return 0;
+ if (y >= bitmap->height) return 0;
+ if (x < 0) { cx += x; x = 0; }
+ if (y < 0) { cy += y; y = 0; }
+ if (cx <= 0) return 0;
+ if (cy <= 0) return 0;
+ if (x + cx > bitmap->width) cx = bitmap->width - x;
+ if (y + cy > bitmap->height) cy = bitmap->height - y;
+
+ if (!xrdp_painter_clip_adj(self, &x, &y, &cx, &cy))
+ return 0;
+
+ if (bitmap->type == 0) /* bitmap */
+ return 0;
+ region = xrdp_region_create(self->wm);
+ xrdp_wm_get_vis_region(self->wm, bitmap, x, y, cx, cy, region);
+ i = 0;
+ while (xrdp_region_get_rect(region, i, &rect) == 0)
+ {
+ DEBUG(("sending rect order %d %d %d %d\n\r", rect.left, rect.top,
+ rect.right, rect.bottom));
+ xrdp_orders_pat_blt(self->orders, rect.left, rect.top,
+ rect.right - rect.left,
+ rect.bottom - rect.top,
+ self->rop, self->bg_color, self->fg_color,
+ &self->brush, 0);
+ i++;
+ }
+ xrdp_region_delete(region);
+
+ return 0;
+}
+
+#define SS 16
+
+/*****************************************************************************/
+int xrdp_painter_draw_bitmap(struct xrdp_painter* self,
+ struct xrdp_bitmap* bitmap,
+ struct xrdp_bitmap* to_draw,
+ int x, int y, int cx, int cy)
+{
+ int i;
+ int j;
+ int k;
+ int w;
+ int h;
+ int x1;
+ int y1;
+ int ok;
+ int srcx;
+ int srcy;
+ int bitmap_id;
+ int cache_id;
+ int cache_idx;
+ int palette_id;
+ struct xrdp_region* region;
+ struct xrdp_rect rect;
+ struct xrdp_rect rect1;
+ struct xrdp_rect rect2;
+ struct xrdp_bitmap* b;
+
+ /* todo data */
+
+ if (bitmap->type == 0)
+ return 0;
+ region = xrdp_region_create(self->wm);
+ xrdp_wm_get_vis_region(self->wm, bitmap, x, y, cx, cy, region);
+ b = bitmap;
+ while (b != 0)
+ {
+ x = x + b->left;
+ y = y + b->top;
+ b = b->parent;
+ }
+ palette_id = xrdp_cache_add_palette(self->wm->cache, self->wm->palette);
+ i = 0;
+ while (i < to_draw->width)
+ {
+ j = 0;
+ while (j < to_draw->height)
+ {
+ x1 = x + i;
+ y1 = y + j;
+ MIN(w, SS, to_draw->width - i);
+ MIN(h, SS, to_draw->height - j);
+ b = xrdp_bitmap_create(w, h, self->wm->screen->bpp, 0);
+ xrdp_bitmap_copy_box(to_draw, b, i, j, w, h);
+ bitmap_id = xrdp_cache_add_bitmap(self->wm->cache, b);
+ HIWORD(cache_id, bitmap_id);
+ LOWORD(cache_idx, bitmap_id);
+ k = 0;
+ while (xrdp_region_get_rect(region, k, &rect) == 0)
+ {
+ xrdp_wm_rect(&rect1, x1, y1, w, h);
+ if (xrdp_wm_rect_intersect(&rect, &rect1, &rect2))
+ {
+ ok = 1;
+ if (self->use_clip)
+ {
+ rect = self->clip;
+ xrdp_wm_rect_offset(&rect, x, y);
+ if (!xrdp_wm_rect_intersect(&rect2, &rect, &rect1))
+ ok = 0;
+ }
+ else
+ rect1 = rect2;
+ if (ok)
+ {
+ rect1.right--;
+ rect1.bottom--;
+ /* check these so ms client don't crash */
+ if (x1 + w >= self->wm->screen->width)
+ w = self->wm->screen->width - x1;
+ if (y1 + h >= self->wm->screen->height)
+ h = self->wm->screen->height - y1;
+ if (w > 0 && h > 0 && x1 + w > 0 && y1 + h > 0)
+ {
+ srcx = 0;
+ srcy = 0;
+ if (x1 < 0)
+ {
+ w = w + x1;
+ srcx = srcx - x1;
+ x1 = 0;
+ }
+ if (y1 < 0)
+ {
+ h = h + y1;
+ srcy = srcy - y1;
+ y1 = 0;
+ }
+ xrdp_orders_mem_blt(self->orders, cache_id, palette_id,
+ x1, y1, w, h, self->rop, srcx, srcy,
+ cache_idx, &rect1);
+ }
+ }
+ }
+ k++;
+ }
+ xrdp_bitmap_delete(b);
+ j += SS;
+ }
+ i += SS;
+ }
+ xrdp_region_delete(region);
+ return 0;
+}
diff --git a/xrdp/xrdp_process.c b/xrdp/xrdp_process.c
index 875829e6..ba1d2300 100644
--- a/xrdp/xrdp_process.c
+++ b/xrdp/xrdp_process.c
@@ -28,14 +28,17 @@ struct xrdp_process* xrdp_process_create(struct xrdp_listen* owner)
self = (struct xrdp_process*)g_malloc(sizeof(struct xrdp_process), 1);
self->lis_layer = owner;
- self->rdp_layer = xrdp_rdp_create(self);
return self;
}
/*****************************************************************************/
void xrdp_process_delete(struct xrdp_process* self)
{
+ if (self == 0)
+ return;
xrdp_rdp_delete(self->rdp_layer);
+ xrdp_orders_delete(self->orders);
+ xrdp_wm_delete(self->wm);
g_free(self->in_s.data);
g_free(self->out_s.data);
g_free(self);
@@ -63,7 +66,7 @@ int xrdp_process_main_loop(struct xrdp_process* self)
{
if (xrdp_rdp_recv(self->rdp_layer, &code) != 0)
break;
- DEBUG(("xrdp_process_main_loop code %d\n", code));
+ DEBUG(("xrdp_process_main_loop code %d\n\r", code));
switch (code)
{
case -1:
@@ -75,23 +78,42 @@ int xrdp_process_main_loop(struct xrdp_process* self)
xrdp_rdp_process_confirm_active(self->rdp_layer); /* 3 */
break;
case RDP_PDU_DATA:
- xrdp_rdp_process_data(self->rdp_layer); /* 7 */
+ if (xrdp_rdp_process_data(self->rdp_layer) != 0) /* 7 */
+ {
+ DEBUG(("xrdp_rdp_process_data returned non zero\n\r"));
+ cont = 0;
+ self->term = 1;
+ }
break;
default:
- g_printf("unknown in xrdp_process_main_loop\n");
+ g_printf("unknown in xrdp_process_main_loop\n\r");
break;
}
- cont = self->rdp_layer->next_packet < self->rdp_layer->in_s->end;
+ if (cont)
+ cont = self->rdp_layer->next_packet < self->rdp_layer->in_s->end;
}
if (cont) /* we must have errored out */
break;
+ if (self->rdp_layer->up_and_running && self->wm == 0)
+ {
+ /* only do this once */
+ DEBUG(("xrdp_process_main_loop up and running\n\r"));
+ self->orders = xrdp_orders_create(self);
+ self->wm = xrdp_wm_create(self);
+ xrdp_wm_init(self->wm);
+ }
}
+ else if (i == 0)
+ g_sleep(10);
else
break;
}
}
+ xrdp_rdp_disconnect(self->rdp_layer);
xrdp_rdp_delete(self->rdp_layer);
+ self->rdp_layer = 0;
g_tcp_close(self->sck);
self->status = -1;
+ xrdp_listen_delete_pro(self->lis_layer, self);
return 0;
}
diff --git a/xrdp/xrdp_rdp.c b/xrdp/xrdp_rdp.c
index b8eadccb..005f4d58 100644
--- a/xrdp/xrdp_rdp.c
+++ b/xrdp/xrdp_rdp.c
@@ -63,6 +63,8 @@ struct xrdp_rdp* xrdp_rdp_create(struct xrdp_process* owner)
/*****************************************************************************/
void xrdp_rdp_delete(struct xrdp_rdp* self)
{
+ if (self == 0)
+ return;
xrdp_sec_delete(self->sec_layer);
g_free(self);
}
@@ -91,16 +93,24 @@ int xrdp_rdp_recv(struct xrdp_rdp* self, int* code)
int error;
int len;
int pdu_code;
+ int chan;
if (self->next_packet == 0 || self->next_packet >= self->in_s->end)
{
- error = xrdp_sec_recv(self->sec_layer);
+ chan = 0;
+ error = xrdp_sec_recv(self->sec_layer, &chan);
if (error == -1) /* special code for send demand active */
{
self->next_packet = 0;
*code = -1;
return 0;
}
+ if (chan != MCS_GLOBAL_CHANNEL && chan > 0)
+ {
+ self->next_packet = 0;
+ *code = 0;
+ return 0;
+ }
if (error != 0)
return 1;
self->next_packet = self->in_s->p;
@@ -126,6 +136,7 @@ int xrdp_rdp_send(struct xrdp_rdp* self, int pdu_type)
{
int len;
+ DEBUG(("in xrdp_rdp_send\n\r"));
s_pop_layer(self->out_s, rdp_hdr);
len = self->out_s->end - self->out_s->p;
out_uint16_le(self->out_s, len);
@@ -133,6 +144,7 @@ int xrdp_rdp_send(struct xrdp_rdp* self, int pdu_type)
out_uint16_le(self->out_s, self->mcs_channel);
if (xrdp_sec_send(self->sec_layer, 0) != 0)
return 1;
+ DEBUG(("out xrdp_rdp_send\n\r"));
return 0;
}
@@ -141,6 +153,7 @@ int xrdp_rdp_send_data(struct xrdp_rdp* self, int data_pdu_type)
{
int len;
+ DEBUG(("in xrdp_rdp_send_data\n\r"));
s_pop_layer(self->out_s, rdp_hdr);
len = self->out_s->end - self->out_s->p;
out_uint16_le(self->out_s, len);
@@ -155,6 +168,7 @@ int xrdp_rdp_send_data(struct xrdp_rdp* self, int data_pdu_type)
out_uint16_le(self->out_s, 0);
if (xrdp_sec_send(self->sec_layer, 0) != 0)
return 1;
+ DEBUG(("out xrdp_rdp_send_data\n\r"));
return 0;
}
@@ -350,14 +364,20 @@ int xrdp_rdp_process_data_pointer(struct xrdp_rdp* self)
int xrdp_rdp_process_input_sync(struct xrdp_rdp* self, int device_flags,
int key_flags)
{
+ DEBUG(("sync event flags %d key %d\n\r", device_flags, key_flags))
+ if (!self->up_and_running)
+ return 0;
return 0;
}
/*****************************************************************************/
/* RDP_INPUT_SCANCODE */
int xrdp_rdp_process_input_scancode(struct xrdp_rdp* self, int device_flags,
- int ext_flags, int scan_code)
+ int scan_code)
{
+ DEBUG(("key event flags %d scan_code %d\n\r", device_flags, scan_code))
+ if (!self->up_and_running)
+ return 0;
return 0;
}
@@ -366,6 +386,25 @@ int xrdp_rdp_process_input_scancode(struct xrdp_rdp* self, int device_flags,
int xrdp_rdp_process_input_mouse(struct xrdp_rdp* self, int device_flags,
int x, int y)
{
+ DEBUG(("mouse event flags %4.4x x - %d y - %d\n\r", device_flags, x, y));
+ if (!self->up_and_running)
+ return 0;
+ if (device_flags & MOUSE_FLAG_MOVE) /* 0x0800 */
+ xrdp_wm_mouse_move(self->pro_layer->wm, x, y);
+ if (device_flags & MOUSE_FLAG_BUTTON1) /* 0x1000 */
+ {
+ if (device_flags & MOUSE_FLAG_DOWN) /* 0x8000 */
+ xrdp_wm_mouse_click(self->pro_layer->wm, x, y, 1, 1);
+ else
+ xrdp_wm_mouse_click(self->pro_layer->wm, x, y, 1, 0);
+ }
+ if (device_flags & MOUSE_FLAG_BUTTON2) /* 0x2000 */
+ {
+ if (device_flags & MOUSE_FLAG_DOWN) /* 0x8000 */
+ xrdp_wm_mouse_click(self->pro_layer->wm, x, y, 2, 1);
+ else
+ xrdp_wm_mouse_click(self->pro_layer->wm, x, y, 2, 0);
+ }
return 0;
}
@@ -382,26 +421,27 @@ int xrdp_rdp_process_data_input(struct xrdp_rdp* self)
in_uint16_le(self->in_s, num_events);
in_uint8s(self->in_s, 2); /* pad */
+ DEBUG(("xrdp_rdp_process_data_input %d events\n\r", num_events))
for (index = 0; index < num_events; index++)
{
in_uint8s(self->in_s, 4); /* time */
in_uint16_le(self->in_s, msg_type);
in_uint16_le(self->in_s, device_flags);
- in_uint16_le(self->in_s, param1);
- in_uint16_le(self->in_s, param2);
+ in_sint16_le(self->in_s, param1);
+ in_sint16_le(self->in_s, param2);
switch (msg_type)
{
case RDP_INPUT_SYNCHRONIZE: /* 0 */
xrdp_rdp_process_input_sync(self, device_flags, param1);
break;
case RDP_INPUT_SCANCODE: /* 4 */
- xrdp_rdp_process_input_scancode(self, device_flags, param1, param2);
+ xrdp_rdp_process_input_scancode(self, device_flags, param1);
break;
case RDP_INPUT_MOUSE: /* 8001 */
xrdp_rdp_process_input_mouse(self, device_flags, param1, param2);
break;
default:
- g_printf("unknown in xrdp_rdp_process_data_input\n");
+ g_printf("unknown in xrdp_rdp_process_data_input\n\r");
break;
}
}
@@ -461,6 +501,21 @@ int xrdp_rdp_process_data_sync(struct xrdp_rdp* self)
/*****************************************************************************/
int xrdp_rdp_process_screen_update(struct xrdp_rdp* self)
{
+ int op;
+ int left;
+ int top;
+ int right;
+ int bottom;
+ struct xrdp_rect rect;
+
+ in_uint32_le(self->in_s, op);
+ in_uint16_le(self->in_s, left);
+ in_uint16_le(self->in_s, top);
+ in_uint16_le(self->in_s, right);
+ in_uint16_le(self->in_s, bottom);
+ xrdp_wm_rect(&rect, left, top, (right - left) + 1, (bottom - top) + 1);
+ if (self->up_and_running && self->pro_layer->wm != 0)
+ xrdp_bitmap_invalidate(self->pro_layer->wm->screen, &rect);
return 0;
}
@@ -489,6 +544,7 @@ int xrdp_rdp_process_data_font(struct xrdp_rdp* self)
if (seq == 2 || seq == 3) /* after second font message, we are up and */
{ /* running */
xrdp_rdp_send_unknown1(self);
+ self->up_and_running = 1;
}
return 0;
}
@@ -507,7 +563,7 @@ int xrdp_rdp_process_data(struct xrdp_rdp* self)
in_uint8(self->in_s, data_type);
in_uint8(self->in_s, ctype);
in_uint16_le(self->in_s, clen);
- DEBUG(("xrdp_rdp_process_data code %d\n", data_type));
+ DEBUG(("xrdp_rdp_process_data code %d\n\r", data_type));
switch (data_type)
{
case RDP_DATA_PDU_POINTER: /* 27 */
@@ -525,15 +581,24 @@ int xrdp_rdp_process_data(struct xrdp_rdp* self)
case 33: /* 33 ?? */
xrdp_rdp_process_screen_update(self);
break;
- case 36: /* 36 ?? */
+
+ //case 35: /* 35 ?? this comes when minimuzing a full screen mstsc.exe 2600 */
+
+ case 36: /* 36 ?? disconnect? */
return 1;
break;
case RDP_DATA_PDU_FONT2: /* 39 */
xrdp_rdp_process_data_font(self);
break;
default:
- g_printf("unknown in xrdp_rdp_process_data\n");
+ g_printf("unknown in xrdp_rdp_process_data %d\n\r", data_type);
break;
}
return 0;
}
+
+/*****************************************************************************/
+int xrdp_rdp_disconnect(struct xrdp_rdp* self)
+{
+ return xrdp_sec_disconnect(self->sec_layer);
+}
diff --git a/xrdp/xrdp_region.c b/xrdp/xrdp_region.c
new file mode 100644
index 00000000..63627b6d
--- /dev/null
+++ b/xrdp/xrdp_region.c
@@ -0,0 +1,286 @@
+
+/*
+ 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.
+
+ Copyright (C) Jay Sorg 2004
+
+ region
+
+*/
+
+#include "xrdp.h"
+
+/*****************************************************************************/
+struct xrdp_region* xrdp_region_create(struct xrdp_wm* wm)
+{
+ struct xrdp_region* self;
+
+ self = (struct xrdp_region*)g_malloc(sizeof(struct xrdp_region), 1);
+ self->wm = wm;
+ self->rects = xrdp_list_create();
+ self->rects->auto_free = 1;
+ return self;
+}
+
+/*****************************************************************************/
+void xrdp_region_delete(struct xrdp_region* self)
+{
+ if (self == 0)
+ return;
+ xrdp_list_delete(self->rects);
+ g_free(self);
+}
+
+/*****************************************************************************/
+int xrdp_region_add_rect(struct xrdp_region* self, struct xrdp_rect* rect)
+{
+ struct xrdp_rect* r;
+
+ r = (struct xrdp_rect*)g_malloc(sizeof(struct xrdp_rect), 1);
+ *r = *rect;
+ xrdp_list_add_item(self->rects, (int)r);
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_region_insert_rect(struct xrdp_region* self, int i, int left,
+ int top, int right, int bottom)
+{
+ struct xrdp_rect* r;
+
+ r = (struct xrdp_rect*)g_malloc(sizeof(struct xrdp_rect), 1);
+ r->left = left;
+ r->top = top;
+ r->right = right;
+ r->bottom = bottom;
+ xrdp_list_insert_item(self->rects, i, (int)r);
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_region_subtract_rect(struct xrdp_region* self,
+ struct xrdp_rect* rect)
+{
+ struct xrdp_rect* r;
+ struct xrdp_rect rect1;
+ int i;
+
+ for (i = self->rects->count - 1; i >= 0; i--)
+ {
+ r = (struct xrdp_rect*)xrdp_list_get_item(self->rects, i);
+ rect1 = *r;
+ r = &rect1;
+ //g_printf("r is %d %d %d %d\n", r->left, r->top, r->right, r->bottom);
+ if (rect->left <= r->left &&
+ rect->top <= r->top &&
+ rect->right >= r->right &&
+ rect->bottom >= r->bottom)
+ { /* rect is not visible */
+ xrdp_list_remove_item(self->rects, i);
+ }
+ else if (rect->right < r->left ||
+ rect->bottom < r->top ||
+ rect->top > r->bottom ||
+ rect->left > r->right)
+ { /* rect are not related */
+ }
+ else if (rect->left <= r->left &&
+ rect->right >= r->right &&
+ rect->bottom < r->bottom &&
+ rect->top <= r->top)
+ { /* partially covered(whole top) */
+ xrdp_list_remove_item(self->rects, i);
+ xrdp_region_insert_rect(self, i, r->left, rect->bottom,
+ r->right, r->bottom);
+ }
+ else if (rect->top <= r->top &&
+ rect->bottom >= r->bottom &&
+ rect->right < r->right &&
+ rect->left <= r->left)
+ { /* partially covered(left) */
+ xrdp_list_remove_item(self->rects, i);
+ xrdp_region_insert_rect(self, i, rect->right, r->top,
+ r->right, r->bottom);
+ }
+ else if (rect->left <= r->left &&
+ rect->right >= r->right &&
+ rect->top > r->top &&
+ rect->bottom >= r->bottom)
+ { /* partially covered(bottom) */
+ xrdp_list_remove_item(self->rects, i);
+ xrdp_region_insert_rect(self, i, r->left, r->top,
+ r->right, rect->top);
+ }
+ else if (rect->top <= r->top &&
+ rect->bottom >= r->bottom &&
+ rect->left > r->left &&
+ rect->right >= r->right)
+ { /* partially covered(right) */
+ xrdp_list_remove_item(self->rects, i);
+ xrdp_region_insert_rect(self, i, r->left, r->top,
+ rect->left, r->bottom);
+ }
+ else if (rect->left <= r->left &&
+ rect->top <= r->top &&
+ rect->right < r->right &&
+ rect->bottom < r->bottom)
+ { /* partially covered(top left) */
+ xrdp_list_remove_item(self->rects, i);
+ xrdp_region_insert_rect(self, i, rect->right, r->top,
+ r->right, rect->bottom);
+ xrdp_region_insert_rect(self, i, r->left, rect->bottom,
+ r->right, r->bottom);
+ }
+ else if (rect->left <= r->left &&
+ rect->bottom >= r->bottom &&
+ rect->right < r->right &&
+ rect->top > r->top)
+ { /* partially covered(bottom left) */
+ xrdp_list_remove_item(self->rects, i);
+ xrdp_region_insert_rect(self, i, r->left, r->top,
+ r->right, rect->top);
+ xrdp_region_insert_rect(self, i, rect->right, rect->top,
+ r->right, r->bottom);
+ }
+ else if (rect->left > r->left &&
+ rect->right >= r->right &&
+ rect->top <= r->top &&
+ rect->bottom < r->bottom)
+ { /* partially covered(top right) */
+ xrdp_list_remove_item(self->rects, i);
+ xrdp_region_insert_rect(self, i, r->left, r->top,
+ rect->left, r->bottom);
+ xrdp_region_insert_rect(self, i, rect->left, rect->bottom,
+ r->right, r->bottom);
+ }
+ else if (rect->left > r->left &&
+ rect->right >= r->right &&
+ rect->top > r->top &&
+ rect->bottom >= r->bottom)
+ { /* partially covered(bottom right) */
+ xrdp_list_remove_item(self->rects, i);
+ xrdp_region_insert_rect(self, i, r->left, r->top,
+ r->right, rect->top);
+ xrdp_region_insert_rect(self, i, r->left, rect->top,
+ rect->left, r->bottom);
+ }
+ else if (rect->left > r->left &&
+ rect->top <= r->top &&
+ rect->right < r->right &&
+ rect->bottom >= r->bottom)
+ { /* 2 rects, one on each end */
+ xrdp_list_remove_item(self->rects, i);
+ xrdp_region_insert_rect(self, i, r->left, r->top,
+ rect->left, r->bottom);
+ xrdp_region_insert_rect(self, i, rect->right, r->top,
+ r->right, r->bottom);
+ }
+ else if (rect->left <= r->left &&
+ rect->top > r->top &&
+ rect->right >= r->right &&
+ rect->bottom < r->bottom)
+ { /* 2 rects, one on each end */
+ xrdp_list_remove_item(self->rects, i);
+ xrdp_region_insert_rect(self, i, r->left, r->top,
+ r->right, rect->top);
+ xrdp_region_insert_rect(self, i, r->left, rect->bottom,
+ r->right, r->bottom);
+ }
+ else if (rect->left > r->left &&
+ rect->right < r->right &&
+ rect->top <= r->top &&
+ rect->bottom < r->bottom)
+ { /* partially covered(top) */
+ xrdp_list_remove_item(self->rects, i);
+ xrdp_region_insert_rect(self, i, r->left, r->top,
+ rect->left, r->bottom);
+ xrdp_region_insert_rect(self, i, rect->left, rect->bottom,
+ rect->right, r->bottom);
+ xrdp_region_insert_rect(self, i, rect->right, r->top,
+ r->right, r->bottom);
+ }
+ else if (rect->top > r->top &&
+ rect->bottom < r->bottom &&
+ rect->left <= r->left &&
+ rect->right < r->right)
+ { /* partially covered(left) */
+ xrdp_list_remove_item(self->rects, i);
+ xrdp_region_insert_rect(self, i, r->left, r->top,
+ r->right, rect->top);
+ xrdp_region_insert_rect(self, i, rect->right, rect->top,
+ r->right, rect->bottom);
+ xrdp_region_insert_rect(self, i, r->left, rect->bottom,
+ r->right, r->bottom);
+ }
+ else if (rect->left > r->left &&
+ rect->right < r->right &&
+ rect->bottom >= r->bottom &&
+ rect->top > r->top)
+ { /* partially covered(bottom) */
+ xrdp_list_remove_item(self->rects, i);
+ xrdp_region_insert_rect(self, i, r->left, r->top,
+ rect->left, r->bottom);
+ xrdp_region_insert_rect(self, i, rect->left, r->top,
+ rect->right, rect->top);
+ xrdp_region_insert_rect(self, i, rect->right, r->top,
+ r->right, r->bottom);
+ }
+ else if (rect->top > r->top &&
+ rect->bottom < r->bottom &&
+ rect->right >= r->right &&
+ rect->left > r->left)
+ { /* partially covered(right) */
+ xrdp_list_remove_item(self->rects, i);
+ xrdp_region_insert_rect(self, i, r->left, r->top,
+ r->right, rect->top);
+ xrdp_region_insert_rect(self, i, r->left, rect->top,
+ rect->left, rect->bottom);
+ xrdp_region_insert_rect(self, i, r->left, rect->bottom,
+ r->right, r->bottom);
+ }
+ else if (rect->left > r->left &&
+ rect->top > r->top &&
+ rect->right < r->right &&
+ rect->bottom < r->bottom)
+ { /* totally contained, 4 rects */
+ xrdp_list_remove_item(self->rects, i);
+ xrdp_region_insert_rect(self, i, r->left, r->top,
+ r->right, rect->top);
+ xrdp_region_insert_rect(self, i, r->left, rect->top,
+ rect->left, rect->bottom);
+ xrdp_region_insert_rect(self, i, r->left, rect->bottom,
+ r->right, r->bottom);
+ xrdp_region_insert_rect(self, i, rect->right, rect->top,
+ r->right, rect->bottom);
+ }
+ else
+ g_printf("error in xrdp_region_subtract_rect\n\r");
+
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_region_get_rect(struct xrdp_region* self, int index,
+ struct xrdp_rect* rect)
+{
+ struct xrdp_rect* r;
+
+ r = (struct xrdp_rect*)xrdp_list_get_item(self->rects, index);
+ if (r == 0)
+ return 1;
+ *rect = *r;
+ return 0;
+}
diff --git a/xrdp/xrdp_sec.c b/xrdp/xrdp_sec.c
index d92f923a..0a139d3d 100644
--- a/xrdp/xrdp_sec.c
+++ b/xrdp/xrdp_sec.c
@@ -131,6 +131,8 @@ struct xrdp_sec* xrdp_sec_create(struct xrdp_rdp* owner)
/*****************************************************************************/
void 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);
@@ -386,48 +388,48 @@ void xrdp_sec_establish_keys(struct xrdp_sec* self)
/*****************************************************************************/
/* returns error */
-int xrdp_sec_recv(struct xrdp_sec* self)
+int xrdp_sec_recv(struct xrdp_sec* self, int* chan)
{
int flags;
int len;
DEBUG((" in xrdp_sec_recv\n\r"));
- while (xrdp_mcs_recv(self->mcs_layer) == 0)
+ if (xrdp_mcs_recv(self->mcs_layer, chan) != 0)
+ return 1;
+ in_uint32_le(self->in_s, flags);
+ DEBUG((" in xrdp_sec_recv flags $%x\n\r", flags));
+ if (flags & SEC_ENCRYPT) /* 0x08 */
+ {
+ in_uint8s(self->in_s, 8); /* signature */
+ xrdp_sec_decrypt(self, self->in_s->p, self->in_s->end - self->in_s->p);
+ }
+ if (flags & SEC_CLIENT_RANDOM) /* 0x01 */
+ {
+ in_uint32_le(self->in_s, len);
+ in_uint8a(self->in_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 */
{
- in_uint32_le(self->in_s, flags);
- DEBUG((" in xrdp_sec_recv flags $%x\n\r", flags));
- if (flags & SEC_ENCRYPT) /* 0x08 */
- {
- in_uint8s(self->in_s, 8); /* signature */
- xrdp_sec_decrypt(self, self->in_s->p, self->in_s->end - self->in_s->p);
- }
- if (flags & SEC_CLIENT_RANDOM) /* 0x01 */
- {
- in_uint32_le(self->in_s, len);
- in_uint8a(self->in_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);
- continue;
- }
- if (flags & SEC_LOGON_INFO) /* 0x40 */
- {
- if (xrdp_sec_process_logon_info(self) != 0)
- return 1;
- if (xrdp_sec_send_lic_initial(self) != 0)
- return 1;
- continue;
- }
- 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 */
- }
+ if (xrdp_sec_process_logon_info(self) != 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 1;
+ return 0;
}
/*****************************************************************************/
@@ -435,10 +437,12 @@ int xrdp_sec_recv(struct xrdp_sec* self)
/* TODO needs outgoing encryption */
int xrdp_sec_send(struct xrdp_sec* self, int flags)
{
+ DEBUG((" in xrdp_sec_send\n\r"));
s_pop_layer(self->out_s, sec_hdr);
out_uint32_le(self->out_s, flags);
if (xrdp_mcs_send(self->mcs_layer) != 0)
return 1;
+ DEBUG((" out xrdp_sec_send\n\r"));
return 0;
}
@@ -528,3 +532,9 @@ int xrdp_sec_incoming(struct xrdp_sec* self)
DEBUG(("out xrdp_sec_incoming\n\r"));
return 0;
}
+
+/*****************************************************************************/
+int xrdp_sec_disconnect(struct xrdp_sec* self)
+{
+ return xrdp_mcs_disconnect(self->mcs_layer);
+}
diff --git a/xrdp/xrdp_tcp.c b/xrdp/xrdp_tcp.c
index 1a9961c3..1f57db5f 100644
--- a/xrdp/xrdp_tcp.c
+++ b/xrdp/xrdp_tcp.c
@@ -96,7 +96,7 @@ int xrdp_tcp_send(struct xrdp_tcp* self)
int sent;
len = self->out_s->end - self->out_s->data;
- DEBUG((" in xrdp_tcp_send, gota send %d bytes\n", len))
+ DEBUG((" in xrdp_tcp_send, gota send %d bytes\n\r", len))
total = 0;
while (total < len)
{
@@ -109,17 +109,18 @@ int xrdp_tcp_send(struct xrdp_tcp* self)
g_sleep(1);
else
{
- DEBUG((" error = -1 in xrdp_tcp_send socket %d\n", self->sck))
+ DEBUG((" error = -1 in xrdp_tcp_send socket %d\n\r", self->sck))
return 1;
}
}
else if (sent == 0)
{
- DEBUG((" error = 0 in xrdp_tcp_send socket %d\n", self->sck))
+ 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;
}
diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h
index 30cf16a4..a429c5a0 100644
--- a/xrdp/xrdp_types.h
+++ b/xrdp/xrdp_types.h
@@ -19,13 +19,81 @@
*/
+/* for memory debugging */
+struct xrdp_mem
+{
+ int size;
+ int id;
+};
+
+/* header for bmp file */
+struct xrdp_bmp_header
+{
+ long size;
+ long image_width;
+ long image_height;
+ short planes;
+ short bit_count;
+ long compression;
+ long image_size;
+ long x_pels_per_meter;
+ long y_pels_per_meter;
+ long clr_used;
+ long clr_important;
+};
+
+/* list */
+struct xrdp_list
+{
+ int* items;
+ int count;
+ int alloc_size;
+ int grow_by;
+ int auto_free;
+};
+
+/* rect */
+struct xrdp_rect
+{
+ int left;
+ int top;
+ int right;
+ int bottom;
+};
+
+/* bounds */
+struct xrdp_bounds
+{
+ int x;
+ int y;
+ int cx;
+ int cy;
+};
+
+/* brush */
+struct xrdp_brush
+{
+ int x_orgin;
+ int y_orgin;
+ int style;
+ char pattern[8];
+};
+
+/* pen */
+struct xrdp_pen
+{
+ int style;
+ int width;
+ int color;
+};
+
/* tcp */
struct xrdp_tcp
{
int sck;
struct stream* in_s;
struct stream* out_s;
- struct xrdp_iso* iso_layer;
+ struct xrdp_iso* iso_layer; /* owner */
};
/* iso */
@@ -33,7 +101,7 @@ struct xrdp_iso
{
struct stream* in_s;
struct stream* out_s;
- struct xrdp_mcs* mcs_layer;
+ struct xrdp_mcs* mcs_layer; /* owner */
struct xrdp_tcp* tcp_layer;
};
@@ -42,7 +110,7 @@ struct xrdp_mcs
{
struct stream* in_s;
struct stream* out_s;
- struct xrdp_sec* sec_layer;
+ struct xrdp_sec* sec_layer; /* owner */
struct xrdp_iso* iso_layer;
int userid;
int chanid;
@@ -55,7 +123,7 @@ struct xrdp_sec
{
struct stream* in_s;
struct stream* out_s;
- struct xrdp_rdp* rdp_layer;
+ struct xrdp_rdp* rdp_layer; /* owner */
struct xrdp_mcs* mcs_layer;
char server_random[32];
char client_random[64];
@@ -80,7 +148,7 @@ struct xrdp_rdp
{
struct stream* in_s;
struct stream* out_s;
- struct xrdp_process* pro_layer;
+ struct xrdp_process* pro_layer; /* owner */
struct xrdp_sec* sec_layer;
char* next_packet;
int share_id;
@@ -88,6 +156,137 @@ struct xrdp_rdp
int bpp;
int width;
int height;
+ int up_and_running;
+};
+
+/* orders */
+struct xrdp_orders
+{
+ struct stream* out_s;
+ struct xrdp_rdp* rdp_layer;
+ struct xrdp_process* pro_layer; /* owner */
+
+ 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;
+
+ 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;
+
+ struct xrdp_pen line_pen;
+
+};
+
+struct xrdp_palette_item
+{
+ int use_count;
+ int palette[256];
+};
+
+struct xrdp_bitmap_item
+{
+ int use_count;
+ struct xrdp_bitmap* bitmap;
+};
+
+/* differnce caches */
+struct xrdp_cache
+{
+ struct xrdp_wm* wm; /* owner */
+ struct xrdp_orders* orders;
+ struct xrdp_palette_item palette_items[6];
+ struct xrdp_bitmap_item bitmap_items[3][600];
+};
+
+/* the window manager */
+struct xrdp_wm
+{
+ struct xrdp_process* pro_layer; /* owner */
+ struct xrdp_bitmap* screen;
+ struct xrdp_orders* orders;
+ struct xrdp_painter* painter;
+ struct stream* out_s;
+ struct xrdp_rdp* rdp_layer;
+ struct xrdp_cache* cache;
+ int palette[256];
+ struct xrdp_bitmap* login_window;
+ /* generic colors */
+ int black;
+ int grey;
+ int dark_grey;
+ int blue;
+ int white;
+ int red;
+ int green;
+ /* dragging info */
+ int dragging;
+ int draggingx;
+ int draggingy;
+ int draggingcx;
+ int draggingcy;
+ int draggingdx;
+ int draggingdy;
+ int draggingorgx;
+ int draggingorgy;
+ struct xrdp_bitmap* dragging_window;
+ /* the down(clicked) button */
+ struct xrdp_bitmap* button_down;
+ /* focused window */
+ struct xrdp_bitmap* focused_window;
+ /* cursor */
+ int current_cursor;
};
/* rdp process */
@@ -98,8 +297,11 @@ struct xrdp_process
int term;
struct stream in_s;
struct stream out_s;
- struct xrdp_listen* lis_layer;
+ struct xrdp_listen* lis_layer; /* owner */
struct xrdp_rdp* rdp_layer;
+ /* create these when up and running */
+ struct xrdp_orders* orders;
+ struct xrdp_wm* wm;
};
/* rdp listener */
@@ -112,3 +314,48 @@ struct xrdp_listen
int process_list_count;
int process_list_max;
};
+
+/* region */
+struct xrdp_region
+{
+ struct xrdp_wm* wm; /* owner */
+ struct xrdp_list* rects;
+};
+
+/* painter */
+struct xrdp_painter
+{
+ int rop;
+ int use_clip;
+ struct xrdp_rect clip;
+ int bg_color;
+ int fg_color;
+ struct xrdp_brush brush;
+ struct xrdp_orders* orders;
+ struct xrdp_wm* wm; /* owner */
+};
+
+/* window or bitmap */
+struct xrdp_bitmap
+{
+ int type; /* 0 = bitmap 1 = window 2 = screen 3 = button 4 = image 5 = edit */
+ int state; /* for button 0 = normal 1 = down */
+ int id;
+ char* data;
+ int width;
+ int height;
+ int bpp;
+ int left;
+ int top;
+ int bg_color;
+ int line_size; /* in bytes */
+ int focused;
+ struct xrdp_bitmap* modal_dialog;
+ struct xrdp_bitmap* owner; /* window that created us */
+ struct xrdp_bitmap* parent; /* window contained in */
+ struct xrdp_list* child_list;
+ struct xrdp_wm* wm;
+ int cursor;
+ int (*notify)(struct xrdp_bitmap* wnd, struct xrdp_bitmap* sender,
+ int msg, int param1, int param2);
+};
diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c
new file mode 100644
index 00000000..2bff2f1b
--- /dev/null
+++ b/xrdp/xrdp_wm.c
@@ -0,0 +1,886 @@
+
+/*
+ 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.
+
+ Copyright (C) Jay Sorg 2004
+
+ simple window manager
+
+*/
+
+#include "xrdp.h"
+
+/*****************************************************************************/
+struct xrdp_wm* xrdp_wm_create(struct xrdp_process* owner)
+{
+ struct xrdp_wm* self;
+
+ self = (struct xrdp_wm*)g_malloc(sizeof(struct xrdp_wm), 1);
+ self->screen = xrdp_bitmap_create(owner->rdp_layer->width,
+ owner->rdp_layer->height,
+ owner->rdp_layer->bpp, 2);
+ self->screen->wm = self;
+ self->pro_layer = owner;
+ self->orders = owner->orders;
+ self->painter = xrdp_painter_create(self);
+ self->out_s = &owner->out_s;
+ self->rdp_layer = owner->rdp_layer;
+ self->cache = xrdp_cache_create(self, self->orders);
+ return self;
+}
+
+/*****************************************************************************/
+void xrdp_wm_delete(struct xrdp_wm* self)
+{
+ if (self == 0)
+ return;
+ xrdp_cache_delete(self->cache);
+ xrdp_painter_delete(self->painter);
+ xrdp_bitmap_delete(self->screen);
+ g_free(self);
+}
+
+/*****************************************************************************/
+int xrdp_wm_send_palette(struct xrdp_wm* self)
+{
+ int i;
+ int color;
+
+ xrdp_rdp_init_data(self->rdp_layer, 776);
+ out_uint16_le(self->out_s, RDP_UPDATE_PALETTE);
+ out_uint16_le(self->out_s, 0);
+ out_uint16_le(self->out_s, 256); /* # of colors */
+ out_uint16_le(self->out_s, 0);
+ for (i = 0; i < 256; i++)
+ {
+ color = self->palette[i];
+ out_uint8(self->out_s, color >> 16);
+ out_uint8(self->out_s, color >> 8);
+ out_uint8(self->out_s, color);
+ }
+ s_mark_end(self->out_s);
+ xrdp_rdp_send_data(self->rdp_layer, RDP_DATA_PDU_UPDATE);
+ return 0;
+}
+
+/*****************************************************************************/
+/* todo */
+int xrdp_wm_send_bitmap(struct xrdp_wm* self, struct xrdp_bitmap* bitmap,
+ int x, int y, int cx, int cy)
+{
+ int data_size;
+ int line_size;
+ int i;
+ int total_lines;
+ int lines_sending;
+ char* p;
+
+ data_size = bitmap->width * bitmap->height * ((bitmap->bpp + 7) / 8);
+ line_size = bitmap->width * ((bitmap->bpp + 7) / 8);
+ total_lines = data_size / line_size;
+ i = 0;
+ p = bitmap->data;
+ lines_sending = 4096 / line_size;
+ if (lines_sending > total_lines)
+ lines_sending = total_lines;
+ while (i < total_lines)
+ {
+ xrdp_rdp_init_data(self->rdp_layer, 8192);
+ out_uint16_le(self->out_s, RDP_UPDATE_BITMAP);
+ out_uint16_le(self->out_s, 1); /* num updates */
+ out_uint16_le(self->out_s, x);
+ out_uint16_le(self->out_s, y + i);
+ out_uint16_le(self->out_s, (x + cx) - 1);
+ out_uint16_le(self->out_s, (y + i + cy) - 1);
+ out_uint16_le(self->out_s, bitmap->width);
+ out_uint16_le(self->out_s, lines_sending);
+ out_uint16_le(self->out_s, bitmap->bpp); /* bpp */
+ out_uint16_le(self->out_s, 0); /* compress */
+ out_uint16_le(self->out_s, line_size * lines_sending); /* bufsize */
+ out_uint8a(self->out_s, p, line_size * lines_sending);
+ s_mark_end(self->out_s);
+ xrdp_rdp_send_data(self->rdp_layer, RDP_DATA_PDU_UPDATE);
+ p = p + line_size * lines_sending;
+ i = i + lines_sending;
+ if (i + lines_sending > total_lines)
+ lines_sending = total_lines - i;
+ if (lines_sending <= 0)
+ break;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_wm_color15(int r, int g, int b)
+{
+ r = r >> 3;
+ g = g >> 3;
+ b = b >> 3;
+ return (r << 10) | (g << 5) | b;
+}
+
+/*****************************************************************************/
+int xrdp_wm_color16(int r, int g, int b)
+{
+ r = r >> 3;
+ g = g >> 2;
+ b = b >> 3;
+ return (r << 11) | (g << 5) | b;
+}
+
+/*****************************************************************************/
+int xrdp_wm_color24(int r, int g, int b)
+{
+ return r | (g << 8) | (b << 16);
+}
+
+/*****************************************************************************/
+/* all login help screen events go here */
+int xrdp_wm_login_help_notify(struct xrdp_bitmap* wnd,
+ struct xrdp_bitmap* sender,
+ int msg, int param1, int param2)
+{
+ if (wnd == 0)
+ return 0;
+ if (sender == 0)
+ return 0;
+ if (wnd->owner == 0)
+ return 0;
+ if (msg == 1) /* click */
+ {
+ if (sender->id == 1) /* ok button */
+ {
+ if (sender->owner->notify != 0)
+ {
+ wnd->owner->notify(wnd->owner, wnd, 100, 1, 0); /* ok */
+ }
+ }
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_wm_set_focused(struct xrdp_wm* self, struct xrdp_bitmap* wnd)
+{
+ if (self == 0)
+ return 0;
+ if (self->focused_window == wnd)
+ return 0;
+ if (self->focused_window != 0)
+ {
+ xrdp_bitmap_set_focus(self->focused_window, 0);
+ }
+ self->focused_window = wnd;
+ if (self->focused_window != 0)
+ {
+ xrdp_bitmap_set_focus(self->focused_window, 1);
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* all login screen events go here */
+int xrdp_wm_login_notify(struct xrdp_bitmap* wnd,
+ struct xrdp_bitmap* sender,
+ int msg, int param1, int param2)
+{
+ struct xrdp_bitmap* help;
+ struct xrdp_bitmap* but;
+ struct xrdp_bitmap* b;
+ struct xrdp_rect rect;
+ int i;
+
+ if (msg == 1) /* click */
+ {
+ if (sender->id == 1) /* help button */
+ {
+ /* create help screen */
+ help = xrdp_bitmap_create(300, 300, wnd->wm->screen->bpp, 1);
+ xrdp_list_insert_item(wnd->wm->screen->child_list, 0, (int)help);
+ help->parent = wnd->wm->screen;
+ help->owner = wnd;
+ wnd->modal_dialog = help;
+ help->wm = wnd->wm;
+ help->bg_color = wnd->wm->grey;
+ help->left = wnd->wm->screen->width / 2 - help->width / 2;
+ help->top = wnd->wm->screen->height / 2 - help->height / 2;
+ help->notify = xrdp_wm_login_help_notify;
+ /* ok button */
+ but = xrdp_bitmap_create(60, 25, wnd->wm->screen->bpp, 3);
+ xrdp_list_insert_item(help->child_list, 0, (int)but);
+ but->parent = help;
+ but->owner = help;
+ but->wm = wnd->wm;
+ but->left = 120;
+ but->top = 260;
+ but->id = 1;
+ /* draw it */
+ xrdp_bitmap_invalidate(help, 0);
+ xrdp_wm_set_focused(wnd->wm, help);
+ }
+ else if (sender->id == 2) /* cancel button */
+ {
+ /*if (wnd != 0)
+ if (wnd->wm != 0)
+ if (wnd->wm->pro_layer != 0)
+ wnd->wm->pro_layer->term = 1;*/
+ }
+ }
+ else if (msg == 2) /* mouse move */
+ {
+ }
+ else if (msg == 100) /* modal result is done */
+ {
+ i = xrdp_list_index_of(wnd->wm->screen->child_list, (int)sender);
+ if (i >= 0)
+ {
+ b = (struct xrdp_bitmap*)
+ xrdp_list_get_item(wnd->wm->screen->child_list, i);
+ xrdp_list_remove_item(sender->wm->screen->child_list, i);
+ xrdp_wm_rect(&rect, b->left, b->top, b->width, b->height);
+ xrdp_bitmap_invalidate(wnd->wm->screen, &rect);
+ xrdp_bitmap_delete(sender);
+ wnd->modal_dialog = 0;
+ xrdp_wm_set_focused(wnd->wm, wnd);
+ }
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_set_cursor(struct xrdp_wm* self, int cache_idx)
+{
+ xrdp_rdp_init_data(self->rdp_layer, 8000);
+ out_uint16_le(self->out_s, RDP_POINTER_CACHED);
+ out_uint16_le(self->out_s, 0); /* pad */
+ out_uint16_le(self->out_s, cache_idx); /* cache_idx */
+ s_mark_end(self->out_s);
+ xrdp_rdp_send_data(self->rdp_layer, RDP_DATA_PDU_POINTER);
+ return 0;
+}
+
+/*****************************************************************************/
+/* send a cursor from a file */
+int xrdp_send_cursor(struct xrdp_wm* self, char* file_name, int cache_idx)
+{
+ int v;
+ int fd;
+ int w;
+ int h;
+ struct stream* s;
+
+ s = (struct stream*)g_malloc(sizeof(struct stream), 1);
+ init_stream(s, 8001);
+ fd = g_file_open(file_name);
+ g_file_read(fd, s->data, 8000);
+ g_file_close(fd);
+ xrdp_rdp_init_data(self->rdp_layer, 8000);
+ out_uint16_le(self->out_s, RDP_POINTER_COLOR);
+ out_uint16_le(self->out_s, 0); /* pad */
+ out_uint16_le(self->out_s, cache_idx); /* cache_idx */
+ in_uint32_le(s, v);
+ out_uint16_le(self->out_s, v); /* x */
+ in_uint32_le(s, v);
+ out_uint16_le(self->out_s, v); /* y */
+ in_uint32_le(s, w);
+ out_uint16_le(self->out_s, w); /* width */
+ in_uint32_le(s, h);
+ out_uint16_le(self->out_s, h); /* height */
+ v = (w * h) / 8;
+ out_uint16_le(self->out_s, v); /* mask len */
+ v = (w * h) * 3;
+ out_uint16_le(self->out_s, v); /* data len */
+ v = ((w * h) / 8) + ((w * h) * 3);
+ out_uint8a(self->out_s, s->p, v);
+ s_mark_end(self->out_s);
+ xrdp_rdp_send_data(self->rdp_layer, RDP_DATA_PDU_POINTER);
+ g_free(s->data);
+ g_free(s);
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_wm_init(struct xrdp_wm* self)
+{
+ struct xrdp_bitmap* but;
+
+ if (self->screen->bpp == 8)
+ {
+ /* rgb */
+ self->palette[250] = 0x00ff0000;
+ self->palette[251] = 0x0000ff00;
+ self->palette[252] = 0x00c0c0c0;
+ self->palette[253] = 0x00808080;
+ self->palette[254] = 0x000000ff;
+ self->palette[255] = 0x00ffffff;
+ self->black = 0;
+ self->grey = 252;
+ self->dark_grey = 253;
+ self->blue = 254;
+ self->white = 255;
+ self->red = 250;
+ self->green = 251;
+ xrdp_wm_send_palette(self);
+
+ }
+ else if (self->screen->bpp == 15)
+ {
+ self->black = xrdp_wm_color15(0, 0, 0);
+ self->grey = xrdp_wm_color15(0xc0, 0xc0, 0xc0);
+ self->dark_grey = xrdp_wm_color15(0x80, 0x80, 0x80);
+ self->blue = xrdp_wm_color15(0x00, 0x00, 0xff);
+ self->white = xrdp_wm_color15(0xff, 0xff, 0xff);
+ self->red = xrdp_wm_color15(0xff, 0x00, 0x00);
+ self->green = xrdp_wm_color15(0x00, 0xff, 0x00);
+ }
+ else if (self->screen->bpp == 16)
+ {
+ self->black = xrdp_wm_color16(0, 0, 0);
+ self->grey = xrdp_wm_color16(0xc0, 0xc0, 0xc0);
+ self->dark_grey = xrdp_wm_color16(0x80, 0x80, 0x80);
+ self->blue = xrdp_wm_color16(0x00, 0x00, 0xff);
+ self->white = xrdp_wm_color16(0xff, 0xff, 0xff);
+ self->red = xrdp_wm_color16(0xff, 0x00, 0x00);
+ self->green = xrdp_wm_color16(0x00, 0xff, 0x00);
+ }
+ else if (self->screen->bpp == 24)
+ {
+ self->black = xrdp_wm_color24(0, 0, 0);
+ self->grey = xrdp_wm_color24(0xc0, 0xc0, 0xc0);
+ self->dark_grey = xrdp_wm_color24(0x80, 0x80, 0x80);
+ self->blue = xrdp_wm_color24(0x00, 0x00, 0xff);
+ self->white = xrdp_wm_color24(0xff, 0xff, 0xff);
+ self->red = xrdp_wm_color24(0xff, 0x00, 0x00);
+ self->green = xrdp_wm_color24(0x00, 0xff, 0x00);
+ }
+ /* draw login window */
+ self->login_window = xrdp_bitmap_create(400, 200, self->screen->bpp, 1);
+ xrdp_list_add_item(self->screen->child_list, (int)self->login_window);
+ self->login_window->parent = self->screen;
+ self->login_window->owner = self->screen;
+ self->login_window->wm = self;
+ self->login_window->bg_color = self->grey;
+ self->login_window->left = self->screen->width / 2 -
+ self->login_window->width / 2;
+ self->login_window->top = self->screen->height / 2 -
+ self->login_window->height / 2;
+ self->login_window->notify = xrdp_wm_login_notify;
+
+ /* image */
+ but = xrdp_bitmap_create(4, 4, self->screen->bpp, 4);
+ xrdp_bitmap_load(but, "xrdp256.bmp", self->palette);
+ but->parent = self->screen;
+ but->owner = self->screen;
+ but->wm = self;
+ but->left = self->screen->width - but->width;
+ but->top = self->screen->height - but->height;
+ xrdp_list_add_item(self->screen->child_list, (int)but);
+
+ /* image */
+ but = xrdp_bitmap_create(4, 4, self->screen->bpp, 4);
+ xrdp_bitmap_load(but, "ad256.bmp", self->palette);
+ but->parent = self->login_window;
+ but->owner = self->login_window;
+ but->wm = self;
+ but->left = 10;
+ but->top = 30;
+ xrdp_list_add_item(self->login_window->child_list, (int)but);
+
+ but = xrdp_bitmap_create(60, 25, self->screen->bpp, 3);
+ xrdp_list_add_item(self->login_window->child_list, (int)but);
+ but->parent = self->login_window;
+ but->owner = self->login_window;
+ but->wm = self;
+ but->left = 320;
+ but->top = 160;
+ but->id = 1;
+
+ but = xrdp_bitmap_create(60, 25, self->screen->bpp, 3);
+ xrdp_list_add_item(self->login_window->child_list, (int)but);
+ but->parent = self->login_window;
+ but->owner = self->login_window;
+ but->wm = self;
+ but->left = 250;
+ but->top = 160;
+ but->id = 2;
+
+ but = xrdp_bitmap_create(60, 25, self->screen->bpp, 3);
+ xrdp_list_add_item(self->login_window->child_list, (int)but);
+ but->parent = self->login_window;
+ but->owner = self->login_window;
+ but->wm = self;
+ but->left = 180;
+ but->top = 160;
+ but->id = 3;
+
+ but = xrdp_bitmap_create(140, 20, self->screen->bpp, 5);
+ xrdp_list_add_item(self->login_window->child_list, (int)but);
+ but->parent = self->login_window;
+ but->owner = self->login_window;
+ but->wm = self;
+ but->left = 220;
+ but->top = 50;
+ but->id = 4;
+ but->cursor = 1;
+
+ but = xrdp_bitmap_create(140, 20, self->screen->bpp, 5);
+ xrdp_list_add_item(self->login_window->child_list, (int)but);
+ but->parent = self->login_window;
+ but->owner = self->login_window;
+ but->wm = self;
+ but->left = 220;
+ but->top = 80;
+ but->id = 5;
+ but->cursor = 1;
+
+ /* clear screen */
+ self->screen->bg_color = self->black;
+ xrdp_bitmap_invalidate(self->screen, 0);
+
+ xrdp_wm_set_focused(self, self->login_window);
+
+ xrdp_send_cursor(self, "cursor1.cur", 1);
+ xrdp_send_cursor(self, "cursor0.cur", 0);
+
+ //xrdp_set_cursor(self, 1);
+
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns the number for rects visible for an area relative to a drawable */
+/* putting the rects in region */
+int xrdp_wm_get_vis_region(struct xrdp_wm* self, struct xrdp_bitmap* bitmap,
+ int x, int y, int cx, int cy,
+ struct xrdp_region* region)
+{
+ int i;
+ struct xrdp_bitmap* p;
+ struct xrdp_rect a;
+ struct xrdp_rect b;
+
+ /* area we are drawing */
+ xrdp_wm_rect(&a, bitmap->left + x, bitmap->top + y, cx, cy);
+
+ p = bitmap->parent;
+ while (p != 0)
+ {
+ xrdp_wm_rect_offset(&a, p->left, p->top);
+ p = p->parent;
+ }
+
+ xrdp_region_add_rect(region, &a);
+
+ if (bitmap == self->screen)
+ return 0;
+
+ /* loop through all windows in z order */
+ for (i = 0; i < self->screen->child_list->count; i++)
+ {
+ p = (struct xrdp_bitmap*)xrdp_list_get_item(self->screen->child_list, i);
+ if (p == bitmap || p == bitmap->parent)
+ return 0;
+ xrdp_wm_rect(&b, p->left, p->top, p->width, p->height);
+ xrdp_region_subtract_rect(region, &b);
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+/* return the window at x, y on the screen */
+struct xrdp_bitmap* xrdp_wm_at_pos(struct xrdp_bitmap* wnd, int x, int y,
+ struct xrdp_bitmap** wnd1)
+{
+ int i;
+ struct xrdp_bitmap* p;
+ struct xrdp_bitmap* q;
+
+ /* loop through all windows in z order */
+ for (i = 0; i < wnd->child_list->count; i++)
+ {
+ p = (struct xrdp_bitmap*)xrdp_list_get_item(wnd->child_list, i);
+ if (x >= p->left && y >= p->top && x < p->left + p->width &&
+ y < p->top + p->height)
+ {
+ if (wnd1 != 0)
+ *wnd1 = p;
+ q = xrdp_wm_at_pos(p, x - p->left, y - p->top, 0);
+ if (q == 0)
+ return p;
+ else
+ return q;
+ }
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_wm_xor_pat(struct xrdp_wm* self, int x, int y, int cx, int cy)
+{
+ self->painter->rop = 0x5a;
+ xrdp_painter_begin_update(self->painter);
+ self->painter->use_clip = 0;
+ self->painter->brush.pattern[0] = 0xaa;
+ self->painter->brush.pattern[1] = 0x55;
+ self->painter->brush.pattern[2] = 0xaa;
+ self->painter->brush.pattern[3] = 0x55;
+ self->painter->brush.pattern[4] = 0xaa;
+ self->painter->brush.pattern[5] = 0x55;
+ self->painter->brush.pattern[6] = 0xaa;
+ self->painter->brush.pattern[7] = 0x55;
+ self->painter->brush.x_orgin = 0;
+ self->painter->brush.x_orgin = 0;
+ self->painter->brush.style = 3;
+ self->painter->bg_color = self->black;
+ self->painter->fg_color = self->white;
+ /* top */
+ xrdp_painter_fill_rect2(self->painter, self->screen, x, y, cx, 5);
+ /* bottom */
+ xrdp_painter_fill_rect2(self->painter, self->screen, x, y + (cy - 5), cx, 5);
+ /* left */
+ xrdp_painter_fill_rect2(self->painter, self->screen, x, y + 5, 5, cy - 10);
+ /* right */
+ xrdp_painter_fill_rect2(self->painter, self->screen, x + (cx - 5), y + 5, 5,
+ cy - 10);
+ xrdp_painter_end_update(self->painter);
+ self->painter->rop = 0xcc;
+ return 0;
+}
+
+/*****************************************************************************/
+/* this don't are about nothing, just copy the bits */
+/* no clipping rects, no windows in the way, nothing */
+int xrdp_wm_bitblt(struct xrdp_wm* self,
+ struct xrdp_bitmap* dst, int dx, int dy,
+ struct xrdp_bitmap* src, int sx, int sy,
+ int sw, int sh, int rop)
+{
+// int i;
+// int line_size;
+// int Bpp;
+// char* s;
+// char* d;
+
+// if (sw <= 0 || sh <= 0)
+// return 0;
+ if (self->screen == dst && self->screen == src)
+ { /* send a screen blt */
+// Bpp = (dst->bpp + 7) / 8;
+// line_size = sw * Bpp;
+// s = src->data + (sy * src->width + sx) * Bpp;
+// d = dst->data + (dy * dst->width + dx) * Bpp;
+// for (i = 0; i < sh; i++)
+// {
+// //g_memcpy(d, s, line_size);
+// s += src->width * Bpp;
+// d += dst->width * Bpp;
+// }
+ xrdp_orders_init(self->orders);
+ xrdp_orders_screen_blt(self->orders, dx, dy, sw, sh, sx, sy, rop, 0);
+ xrdp_orders_send(self->orders);
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* return true is rect is totaly exposed going in reverse z order */
+/* from wnd up */
+int xrdp_wm_is_rect_vis(struct xrdp_wm* self, struct xrdp_bitmap* wnd,
+ struct xrdp_rect* rect)
+{
+ struct xrdp_rect rect1;
+ struct xrdp_rect rect2;
+ struct xrdp_bitmap* b;
+ int i;;
+
+ /* if rect is part off screen */
+ if (rect->left < 0)
+ return 0;
+ if (rect->top < 0)
+ return 0;
+ if (rect->right >= self->screen->width)
+ return 0;
+ if (rect->bottom >= self->screen->height)
+ return 0;
+
+ i = xrdp_list_index_of(self->screen->child_list, (int)wnd);
+ i--;
+ while (i >= 0)
+ {
+ b = (struct xrdp_bitmap*)xrdp_list_get_item(self->screen->child_list, i);
+ xrdp_wm_rect(&rect1, b->left, b->top, b->width, b->height);
+ if (xrdp_wm_rect_intersect(rect, &rect1, &rect2))
+ return 0;
+ i--;
+ }
+ return 1;
+}
+
+/*****************************************************************************/
+int xrdp_wm_move_window(struct xrdp_wm* self, struct xrdp_bitmap* wnd,
+ int dx, int dy)
+{
+ struct xrdp_rect rect1;
+ struct xrdp_rect rect2;
+ struct xrdp_region* r;
+ int i;
+
+ xrdp_wm_rect(&rect1, wnd->left, wnd->top, wnd->width, wnd->height);
+ if (xrdp_wm_is_rect_vis(self, wnd, &rect1))
+ {
+ rect2 = rect1;
+ xrdp_wm_rect_offset(&rect2, dx, dy);
+ if (xrdp_wm_is_rect_vis(self, wnd, &rect2))
+ { /* if both src and dst are unobscured, we can do a bitblt move */
+ xrdp_wm_bitblt(self, self->screen, wnd->left + dx, wnd->top + dy,
+ self->screen, wnd->left, wnd->top,
+ wnd->width, wnd->height, 0xcc);
+ wnd->left += dx;
+ wnd->top += dy;
+ r = xrdp_region_create(self);
+ xrdp_region_add_rect(r, &rect1);
+ xrdp_region_subtract_rect(r, &rect2);
+ i = 0;
+ while (xrdp_region_get_rect(r, i, &rect1) == 0)
+ {
+ xrdp_bitmap_invalidate(self->screen, &rect1);
+ i++;
+ }
+ xrdp_region_delete(r);
+ return 0;
+ }
+ }
+ wnd->left += dx;
+ wnd->top += dy;
+ xrdp_bitmap_invalidate(self->screen, &rect1);
+ xrdp_bitmap_invalidate(wnd, 0);
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_wm_rect(struct xrdp_rect* r, int x, int y, int cx, int cy)
+{
+ r->left = x;
+ r->top = y;
+ r->right = x + cx;
+ r->bottom = y + cy;
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_wm_rect_is_empty(struct xrdp_rect* in)
+{
+ return (in->right <= in->left) || (in->bottom <= in->top);
+}
+
+/*****************************************************************************/
+int xrdp_wm_rect_contains_pt(struct xrdp_rect* in, int x, int y)
+{
+ if (x < in->left)
+ return 0;
+ if (y < in->top)
+ return 0;
+ if (x >= in->right)
+ return 0;
+ if (y >= in->bottom)
+ return 0;
+ return 1;
+}
+
+/*****************************************************************************/
+int xrdp_wm_rect_intersect(struct xrdp_rect* in1, struct xrdp_rect* in2,
+ struct xrdp_rect* out)
+{
+ int rv;
+
+ *out = *in1;
+ if (in2->left > in1->left)
+ out->left = in2->left;
+ if (in2->top > in1->top)
+ out->top = in2->top;
+ if (in2->right < in1->right)
+ out->right = in2->right;
+ if (in2->bottom < in1->bottom)
+ out->bottom = in2->bottom;
+ rv = !xrdp_wm_rect_is_empty(out);
+ if (!rv)
+ g_memset(out, 0, sizeof(struct xrdp_rect));
+ return rv;
+}
+
+/*****************************************************************************/
+int xrdp_wm_rect_offset(struct xrdp_rect* in, int dx, int dy)
+{
+ in->left += dx;
+ in->right += dx;
+ in->top += dy;
+ in->bottom += dy;
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_wm_mouse_move(struct xrdp_wm* self, int x, int y)
+{
+ struct xrdp_bitmap* b;
+ int boxx;
+ int boxy;
+
+ DEBUG(("in mouse move\n\r"));
+ if (self == 0)
+ return 0;
+ if (x < 0)
+ x = 0;
+ if (y < 0)
+ y = 0;
+ if (x >= self->screen->width)
+ x = self->screen->width;
+ if (y >= self->screen->height)
+ y = self->screen->height;
+ if (self->dragging)
+ {
+ xrdp_painter_begin_update(self->painter);
+ boxx = self->draggingx - self->draggingdx;
+ boxy = self->draggingy - self->draggingdy;
+ xrdp_wm_xor_pat(self, boxx, boxy, self->draggingcx, self->draggingcy);
+ self->draggingx = x;
+ self->draggingy = y;
+ boxx = self->draggingx - self->draggingdx;
+ boxy = self->draggingy - self->draggingdy;
+ xrdp_wm_xor_pat(self, boxx, boxy, self->draggingcx, self->draggingcy);
+ xrdp_painter_end_update(self->painter);
+ }
+ b = xrdp_wm_at_pos(self->screen, x, y, 0);
+ if (self->button_down != 0)
+ {
+ if (b == self->button_down && self->button_down->state == 0)
+ {
+ self->button_down->state = 1;
+ xrdp_bitmap_invalidate(self->button_down, 0);
+ }
+ else if (b != self->button_down)
+ {
+ self->button_down->state = 0;
+ xrdp_bitmap_invalidate(self->button_down, 0);
+ }
+ }
+ if (b != 0)
+ {
+ if (!self->dragging)
+ {
+ if (b->cursor != self->current_cursor)
+ {
+ xrdp_set_cursor(self, b->cursor);
+ self->current_cursor = b->cursor;
+ }
+ if (self->button_down == 0)
+ if (b->notify != 0)
+ b->notify(b->owner, b, 2, x, y);
+ }
+ }
+ DEBUG(("out mouse move\n\r"));
+ return 0;
+}
+
+/*****************************************************************************/
+int xrdp_wm_mouse_click(struct xrdp_wm* self, int x, int y, int but, int down)
+{
+ struct xrdp_bitmap* b;
+ struct xrdp_bitmap* b1;
+ int newx;
+ int newy;
+ int oldx;
+ int oldy;
+
+ if (self == 0)
+ return 0;
+ if (x < 0)
+ x = 0;
+ if (y < 0)
+ y = 0;
+ if (x >= self->screen->width)
+ x = self->screen->width;
+ if (y >= self->screen->height)
+ y = self->screen->height;
+ if (self->dragging && but == 1 && !down && self->dragging_window != 0)
+ { /* if done dragging */
+ self->draggingx = x;
+ self->draggingy = y;
+ newx = self->draggingx - self->draggingdx;
+ newy = self->draggingy - self->draggingdy;
+ oldx = self->dragging_window->left;
+ oldy = self->dragging_window->top;
+ /* draw xor box one more time */
+ xrdp_wm_xor_pat(self, newx, newy, self->draggingcx, self->draggingcy);
+ /* move screen to new location */
+ xrdp_wm_move_window(self, self->dragging_window, newx - oldx, newy - oldy);
+ self->dragging_window = 0;
+ self->dragging = 0;
+ }
+ b = xrdp_wm_at_pos(self->screen, x, y, &b1);
+ if (b != 0)
+ {
+ if (b->type == 3 && but == 1 && !down && self->button_down == b)
+ { /* if clicking up on a button that was clicked down */
+ self->button_down = 0;
+ b->state = 0;
+ xrdp_bitmap_invalidate(b, 0);
+ if (b->parent != 0)
+ if (b->parent->notify != 0)
+ /* b can be invalid after this */
+ b->parent->notify(b->owner, b, 1, x, y);
+ }
+ else if (b->type == 3 && but == 1 && down)
+ { /* if clicking down on a button */
+ self->button_down = b;
+ b->state = 1;
+ xrdp_bitmap_invalidate(b, 0);
+ }
+ else if (but == 1 && down)
+ {
+ xrdp_wm_set_focused(self, b1);
+ if (b->type == 1 && y < (b->top + 21))
+ { /* if dragging */
+ if (self->dragging) /* rarely happens */
+ {
+ newx = self->draggingx - self->draggingdx;
+ newy = self->draggingy - self->draggingdy;
+ xrdp_wm_xor_pat(self, newx, newy, self->draggingcx,
+ self->draggingcy);
+ }
+ self->dragging = 1;
+ self->dragging_window = b;
+ self->draggingorgx = b->left;
+ self->draggingorgy = b->top;
+ self->draggingx = x;
+ self->draggingy = y;
+ self->draggingdx = x - b->left;
+ self->draggingdy = y - b->top;
+ self->draggingcx = b->width;
+ self->draggingcy = b->height;
+ newx = self->draggingx - self->draggingdx;
+ newy = self->draggingy - self->draggingdy;
+ xrdp_wm_xor_pat(self, newx, newy, self->draggingcx, self->draggingcy);
+ }
+ }
+ }
+ else
+ xrdp_wm_set_focused(self, 0);
+
+ /* no matter what, mouse is up, reset button_down */
+ if (but == 1 && !down && self->button_down != 0)
+ self->button_down = 0;
+ return 0;
+}