From e856dc67abedd0a38b766d2f0ecdde9a75424e27 Mon Sep 17 00:00:00 2001 From: jsorg71 Date: Sat, 11 Sep 2004 21:27:39 +0000 Subject: [PATCH] major work and login screen --- xrdp/Makefile | 9 +- xrdp/constants.h | 27 ++ xrdp/os_calls.c | 205 +++++++++- xrdp/parse.h | 6 + xrdp/xrdp.c | 2 + xrdp/xrdp.h | 140 ++++++- xrdp/xrdp_bitmap.c | 479 ++++++++++++++++++++++ xrdp/xrdp_cache.c | 145 +++++++ xrdp/xrdp_iso.c | 4 + xrdp/xrdp_list.c | 149 +++++++ xrdp/xrdp_listen.c | 23 ++ xrdp/xrdp_mcs.c | 31 +- xrdp/xrdp_orders.c | 976 ++++++++++++++++++++++++++++++++++++++++++++ xrdp/xrdp_painter.c | 333 +++++++++++++++ xrdp/xrdp_process.c | 32 +- xrdp/xrdp_rdp.c | 83 +++- xrdp/xrdp_region.c | 286 +++++++++++++ xrdp/xrdp_sec.c | 76 ++-- xrdp/xrdp_tcp.c | 7 +- xrdp/xrdp_types.h | 259 +++++++++++- xrdp/xrdp_wm.c | 886 ++++++++++++++++++++++++++++++++++++++++ 21 files changed, 4073 insertions(+), 85 deletions(-) create mode 100644 xrdp/xrdp_bitmap.c create mode 100644 xrdp/xrdp_cache.c create mode 100644 xrdp/xrdp_list.c create mode 100644 xrdp/xrdp_orders.c create mode 100644 xrdp/xrdp_painter.c create mode 100644 xrdp/xrdp_region.c create mode 100644 xrdp/xrdp_wm.c 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 #include #include +#include #include #include #include @@ -35,11 +36,121 @@ #include #include +#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; @@ -77,24 +188,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) { @@ -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]); @@ -86,6 +87,24 @@ int xrdp_listen_add_pro(struct xrdp_listen* self) return 1; } +/*****************************************************************************/ +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; @@ -415,6 +420,28 @@ int xrdp_mcs_send(struct xrdp_mcs* self) 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; + 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; +}