diff --git a/common/os_calls.c b/common/os_calls.c index 2d5b4280..80b2d235 100644 --- a/common/os_calls.c +++ b/common/os_calls.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,11 @@ * put all the os / arch define in here you want */ +/* To test for Windows (64 bit or 32 bit) use _WIN32 and _WIN64 in addition + for 64 bit windows. _WIN32 is defined for both. + To test for Linux use __linux__. + To test for BSD use BSD */ + #if defined(HAVE_CONFIG_H) #include "config_ac.h" #endif @@ -42,6 +47,8 @@ #include #include #include +#include +#include #include #include #include @@ -58,6 +65,13 @@ #include #include +/* this is so we can use #ifdef BSD later */ +/* This is the recommended way of detecting BSD in the + FreeBSD Porter's Handbook. */ +#if (defined(__unix__) || defined(unix)) && !defined(USG) +#include +#endif + #include "os_calls.h" #include "arch.h" #include "log.h" @@ -594,10 +608,16 @@ g_tcp_local_socket(void) } /*****************************************************************************/ +/* returns error */ int APP_CC g_sck_get_peer_cred(int sck, int *pid, int *uid, int *gid) { +#if defined(SO_PEERCRED) +#if defined(_WIN32) int ucred_length; +#else + unsigned int ucred_length; +#endif struct myucred { pid_t pid; @@ -623,6 +643,9 @@ g_sck_get_peer_cred(int sck, int *pid, int *uid, int *gid) *gid = credentials.gid; } return 0; +#else + return 1; +#endif } /*****************************************************************************/ @@ -3118,3 +3141,35 @@ g_text2bool(const char *s) } return 0; } + +/*****************************************************************************/ +/* returns pointer or nil on error */ +void * APP_CC +g_shmat(int shmid) +{ +#if defined(_WIN32) + return 0; +#else + return shmat(shmid, 0, 0); +#endif +} + +/*****************************************************************************/ +/* returns -1 on error 0 on success */ +int APP_CC +g_shmdt(const void *shmaddr) +{ +#if defined(_WIN32) + return -1; +#else + return shmdt(shmaddr); +#endif +} + +/*****************************************************************************/ +/* returns -1 on error 0 on success */ +int APP_CC +g_gethostname(char *name, int len) +{ + return gethostname(name, len); +} diff --git a/common/os_calls.h b/common/os_calls.h index b6e1c91a..06ce8494 100644 --- a/common/os_calls.h +++ b/common/os_calls.h @@ -161,5 +161,8 @@ int APP_CC g_time1(void); int APP_CC g_time2(void); int APP_CC g_time3(void); int APP_CC g_text2bool(const char *s); +void * APP_CC g_shmat(int shmid); +int APP_CC g_shmdt(const void *shmaddr); +int APP_CC g_gethostname(char *name, int len); #endif diff --git a/common/ssl_calls.c b/common/ssl_calls.c index 4cb706f3..a187edc9 100644 --- a/common/ssl_calls.c +++ b/common/ssl_calls.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2012 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -157,6 +158,151 @@ ssl_md5_complete(void *md5_info, char *data) MD5_Final((tui8 *)data, (MD5_CTX *)md5_info); } +/* FIPS stuff */ + +/*****************************************************************************/ +void *APP_CC +ssl_des3_encrypt_info_create(const char *key, const char* ivec) +{ + EVP_CIPHER_CTX *des3_ctx; + const tui8 *lkey; + const tui8 *livec; + + des3_ctx = (EVP_CIPHER_CTX *) g_malloc(sizeof(EVP_CIPHER_CTX), 1); + EVP_CIPHER_CTX_init(des3_ctx); + lkey = (const tui8 *) key; + livec = (const tui8 *) ivec; + EVP_EncryptInit_ex(des3_ctx, EVP_des_ede3_cbc(), NULL, lkey, livec); + EVP_CIPHER_CTX_set_padding(des3_ctx, 0); + return des3_ctx; +} + +/*****************************************************************************/ +void *APP_CC +ssl_des3_decrypt_info_create(const char *key, const char* ivec) +{ + EVP_CIPHER_CTX *des3_ctx; + const tui8 *lkey; + const tui8 *livec; + + des3_ctx = g_malloc(sizeof(EVP_CIPHER_CTX), 1); + EVP_CIPHER_CTX_init(des3_ctx); + lkey = (const tui8 *) key; + livec = (const tui8 *) ivec; + EVP_DecryptInit_ex(des3_ctx, EVP_des_ede3_cbc(), NULL, lkey, livec); + EVP_CIPHER_CTX_set_padding(des3_ctx, 0); + return des3_ctx; +} + +/*****************************************************************************/ +void APP_CC +ssl_des3_info_delete(void *des3) +{ + EVP_CIPHER_CTX *des3_ctx; + + des3_ctx = (EVP_CIPHER_CTX *) des3; + if (des3_ctx != 0) + { + EVP_CIPHER_CTX_cleanup(des3_ctx); + g_free(des3_ctx); + } +} + +/*****************************************************************************/ +int APP_CC +ssl_des3_encrypt(void *des3, int length, const char *in_data, char *out_data) +{ + EVP_CIPHER_CTX *des3_ctx; + int len; + const tui8 *lin_data; + tui8 *lout_data; + + des3_ctx = (EVP_CIPHER_CTX *) des3; + lin_data = (const tui8 *) in_data; + lout_data = (tui8 *) out_data; + len = 0; + EVP_EncryptUpdate(des3_ctx, lout_data, &len, lin_data, length); + return 0; +} + +/*****************************************************************************/ +int APP_CC +ssl_des3_decrypt(void *des3, int length, const char *in_data, char *out_data) +{ + EVP_CIPHER_CTX *des3_ctx; + int len; + const tui8 *lin_data; + tui8 *lout_data; + + des3_ctx = (EVP_CIPHER_CTX *) des3; + lin_data = (const tui8 *) in_data; + lout_data = (tui8 *) out_data; + len = 0; + EVP_DecryptUpdate(des3_ctx, lout_data, &len, lin_data, length); + return 0; +} + +/*****************************************************************************/ +void * APP_CC +ssl_hmac_info_create(void) +{ + HMAC_CTX *hmac_ctx; + + hmac_ctx = (HMAC_CTX *) g_malloc(sizeof(HMAC_CTX), 1); + HMAC_CTX_init(hmac_ctx); + return hmac_ctx; +} + +/*****************************************************************************/ +void APP_CC +ssl_hmac_info_delete(void *hmac) +{ + HMAC_CTX *hmac_ctx; + + hmac_ctx = (HMAC_CTX *) hmac; + if (hmac_ctx != 0) + { + HMAC_CTX_cleanup(hmac_ctx); + g_free(hmac_ctx); + } +} + +/*****************************************************************************/ +void APP_CC +ssl_hmac_sha1_init(void *hmac, const char *data, int len) +{ + HMAC_CTX *hmac_ctx; + + hmac_ctx = (HMAC_CTX *) hmac; + HMAC_Init_ex(hmac_ctx, data, len, EVP_sha1(), NULL); +} + +/*****************************************************************************/ +void APP_CC +ssl_hmac_transform(void *hmac, const char *data, int len) +{ + HMAC_CTX *hmac_ctx; + const tui8 *ldata; + + hmac_ctx = (HMAC_CTX *) hmac; + ldata = (const tui8*) data; + HMAC_Update(hmac_ctx, ldata, len); +} + +/*****************************************************************************/ +void APP_CC +ssl_hmac_complete(void *hmac, char *data, int len) +{ + HMAC_CTX *hmac_ctx; + tui8* ldata; + tui32 llen; + + hmac_ctx = (HMAC_CTX *) hmac; + ldata = (tui8 *) data; + llen = len; + HMAC_Final(hmac_ctx, ldata, &llen); +} + /*****************************************************************************/ static void APP_CC ssl_reverse_it(char *p, int len) diff --git a/common/ssl_calls.h b/common/ssl_calls.h index 3b59537a..40acfb5b 100644 --- a/common/ssl_calls.h +++ b/common/ssl_calls.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -53,6 +53,26 @@ void APP_CC ssl_md5_transform(void* md5_info, char* data, int len); void APP_CC ssl_md5_complete(void* md5_info, char* data); +void *APP_CC +ssl_des3_encrypt_info_create(const char *key, const char* ivec); +void *APP_CC +ssl_des3_decrypt_info_create(const char *key, const char* ivec); +void APP_CC +ssl_des3_info_delete(void *des3); +int APP_CC +ssl_des3_encrypt(void *des3, int length, const char *in_data, char *out_data); +int APP_CC +ssl_des3_decrypt(void *des3, int length, const char *in_data, char *out_data); +void * APP_CC +ssl_hmac_info_create(void); +void APP_CC +ssl_hmac_info_delete(void *hmac); +void APP_CC +ssl_hmac_sha1_init(void *hmac, const char *data, int len); +void APP_CC +ssl_hmac_transform(void *hmac, const char *data, int len); +void APP_CC +ssl_hmac_complete(void *hmac, char *data, int len); int APP_CC ssl_mod_exp(char* out, int out_len, char* in, int in_len, char* mod, int mod_len, char* exp, int exp_len); diff --git a/common/trans.c b/common/trans.c index c418877e..aced0667 100644 --- a/common/trans.c +++ b/common/trans.c @@ -282,7 +282,10 @@ trans_check_wait_objs(struct trans *self) if (self->trans_data_in != 0) { rv = self->trans_data_in(self); - init_stream(self->in_s, 0); + if (self->no_stream_init_on_data_in == 0) + { + init_stream(self->in_s, 0); + } } } } diff --git a/common/trans.h b/common/trans.h index 31c90721..c2e5e0df 100644 --- a/common/trans.h +++ b/common/trans.h @@ -57,6 +57,8 @@ struct trans struct stream* wait_s; char addr[256]; char port[256]; + int no_stream_init_on_data_in; + int extra_flags; /* user defined */ }; struct trans* APP_CC diff --git a/common/xrdp_client_info.h b/common/xrdp_client_info.h index 1d7242bd..50c9f143 100644 --- a/common/xrdp_client_info.h +++ b/common/xrdp_client_info.h @@ -113,6 +113,14 @@ struct xrdp_client_info int keyboard_type; int keyboard_subtype; + + int png_codec_id; + int png_prop_len; + char png_prop[64]; + int vendor_flags[4]; + int mcs_connection_type; + int mcs_early_capability_flags; + }; #endif diff --git a/configure.ac b/configure.ac index 07d61cd2..d4807bcc 100644 --- a/configure.ac +++ b/configure.ac @@ -54,10 +54,10 @@ AC_ARG_ENABLE(fuse, AS_HELP_STRING([--enable-fuse], [fuse=true], [fuse=false]) AM_CONDITIONAL(XRDP_FUSE, [test x$fuse = xtrue]) -AC_ARG_ENABLE(load_pulse_modules, AS_HELP_STRING([--enable-load_pulse_modules], +AC_ARG_ENABLE(loadpulsemodules, AS_HELP_STRING([--enable-loadpulsemodules], [Build code to load pulse audio modules (default: no)]), - [load_pulse_modules=true], [load_pulse_modules=false]) -AM_CONDITIONAL(XRDP_LOAD_PULSE_MODULES, [test x$load_pulse_modules = xtrue]) + [loadpulsemodules=true], [loadpulsemodules=false]) +AM_CONDITIONAL(XRDP_LOAD_PULSE_MODULES, [test x$loadpulsemodules = xtrue]) AC_ARG_ENABLE(xrdpvr, AS_HELP_STRING([--enable-xrdpvr], [Build xrdpvr module (default: no)]), @@ -114,7 +114,7 @@ then fi # checking for libpulse -if ! test -z "$enable_load_pulse_modules" +if ! test -z "$enable_loadpulsemodules" then AC_CHECK_HEADER([pulse/util.h], [], [AC_MSG_ERROR([please install libpulse-dev or libpulse-devel])]) diff --git a/libxrdp/Makefile.am b/libxrdp/Makefile.am index 3fdc963d..7fe5d1b2 100644 --- a/libxrdp/Makefile.am +++ b/libxrdp/Makefile.am @@ -55,8 +55,8 @@ libxrdp_la_SOURCES = \ xrdp_orders.c \ xrdp_rdp.c \ xrdp_sec.c \ - xrdp_tcp.c \ xrdp_bitmap_compress.c \ + xrdp_bitmap32_compress.c \ xrdp_jpeg_compress.c \ xrdp_orders_rail.c \ xrdp_mppc_enc.c \ diff --git a/libxrdp/libxrdp.c b/libxrdp/libxrdp.c index 5e7e72a1..ae2690f2 100644 --- a/libxrdp/libxrdp.c +++ b/libxrdp/libxrdp.c @@ -32,8 +32,6 @@ libxrdp_init(tbus id, struct trans *trans) session->rdp = xrdp_rdp_create(session, trans); session->orders = xrdp_orders_create(session, (struct xrdp_rdp *)session->rdp); session->client_info = &(((struct xrdp_rdp *)session->rdp)->client_info); - make_stream(session->s); - init_stream(session->s, 8192 * 2); return session; } @@ -48,7 +46,6 @@ libxrdp_exit(struct xrdp_session *session) xrdp_orders_delete((struct xrdp_orders *)session->orders); xrdp_rdp_delete((struct xrdp_rdp *)session->rdp); - free_stream(session->s); g_free(session); return 0; } @@ -69,19 +66,38 @@ libxrdp_process_incomming(struct xrdp_session *session) /******************************************************************************/ int EXPORT_CC -libxrdp_process_data(struct xrdp_session *session) +libxrdp_process_data(struct xrdp_session *session, struct stream *s) { int cont; int rv; int code; int term; int dead_lock_counter; + struct xrdp_rdp *rdp; + struct stream *ls; + + if (session->in_process_data != 0) + { + g_writeln("libxrdp_process_data: error reentry"); + return 1; + } + session->in_process_data++; + + ls = 0; + if (s == 0) + { + make_stream(ls); + init_stream(ls, 8192 * 4); + s = ls; + } term = 0; cont = 1; rv = 0; dead_lock_counter = 0; + rdp = (struct xrdp_rdp *) (session->rdp); + while ((cont || !session->up_and_running) && !term) { if (session->is_term != 0) @@ -94,8 +110,7 @@ libxrdp_process_data(struct xrdp_session *session) code = 0; - if (xrdp_rdp_recv((struct xrdp_rdp *)(session->rdp), - session->s, &code) != 0) + if (xrdp_rdp_recv(rdp, s, &code) != 0) { rv = 1; break; @@ -106,13 +121,14 @@ libxrdp_process_data(struct xrdp_session *session) switch (code) { case -1: - xrdp_rdp_send_demand_active((struct xrdp_rdp *)session->rdp); + xrdp_rdp_send_demand_active(rdp); - // send Monitor Layout PDU for multimon - if (session->client_info->monitorCount > 0 && session->client_info->multimon == 1) + /* send Monitor Layout PDU for multimon */ + if (session->client_info->monitorCount > 0 && + session->client_info->multimon == 1) { DEBUG(("sending monitor layout pdu")); - if (xrdp_rdp_send_monitorlayout((struct xrdp_rdp *)session->rdp) != 0) + if (xrdp_rdp_send_monitorlayout(rdp) != 0) { g_writeln("xrdp_rdp_send_monitorlayout: error"); } @@ -124,28 +140,24 @@ libxrdp_process_data(struct xrdp_session *session) dead_lock_counter++; break; case RDP_PDU_CONFIRM_ACTIVE: /* 3 */ - xrdp_rdp_process_confirm_active((struct xrdp_rdp *)session->rdp, - session->s); + xrdp_rdp_process_confirm_active(rdp, s); break; case RDP_PDU_DATA: /* 7 */ - if (xrdp_rdp_process_data((struct xrdp_rdp *)session->rdp, - session->s) != 0) + if (xrdp_rdp_process_data(rdp, s) != 0) { DEBUG(("libxrdp_process_data returned non zero")); cont = 0; term = 1; } - break; case 2: /* FASTPATH_INPUT_EVENT */ - if (xrdp_rdp_process_fastpath_data_input((struct xrdp_rdp *)session->rdp, - session->s) != 0) - { - DEBUG(("libxrdp_process_data returned non zero")); - cont = 0; - term = 1; - } - break; + if (xrdp_rdp_process_fastpath_data_input(rdp, s) != 0) + { + DEBUG(("libxrdp_process_data returned non zero")); + cont = 0; + term = 1; + } + break; default: g_writeln("unknown in libxrdp_process_data: code= %d", code); dead_lock_counter++; @@ -157,17 +169,24 @@ libxrdp_process_data(struct xrdp_session *session) /*This situation can happen and this is a workaround*/ cont = 0; g_writeln("Serious programming error we were locked in a deadly loop") ; - g_writeln("remaining :%d", session->s->end - session->s->next_packet); - session->s->next_packet = 0; + g_writeln("remaining :%d", s->end - s->next_packet); + s->next_packet = 0; } if (cont) { - cont = (session->s->next_packet != 0) && - (session->s->next_packet < session->s->end); + cont = (s->next_packet != 0) && + (s->next_packet < s->end); } } + if (s == ls) + { + free_stream(s); + } + + session->in_process_data--; + return rv; } @@ -777,7 +796,7 @@ libxrdp_reset(struct xrdp_session *session, /* process till up and running */ session->up_and_running = 0; - if (libxrdp_process_data(session) != 0) + if (libxrdp_process_data(session, 0) != 0) { g_writeln("non handled error from libxrdp_process_data"); } diff --git a/libxrdp/libxrdp.h b/libxrdp/libxrdp.h index 91f21974..2843089b 100644 --- a/libxrdp/libxrdp.h +++ b/libxrdp/libxrdp.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,22 +37,14 @@ #include "file_loc.h" #include "xrdp_client_info.h" -/* tcp */ -struct xrdp_tcp -{ - struct trans* trans; - struct xrdp_iso* iso_layer; /* owner */ - struct xrdp_fastpath* fastpath_layer; /* owner */ - -}; /* iso */ struct xrdp_iso { struct xrdp_mcs* mcs_layer; /* owner */ - struct xrdp_tcp* tcp_layer; int requestedProtocol; int selectedProtocol; + struct trans* trans; }; /* used in mcs */ @@ -79,11 +71,26 @@ struct xrdp_mcs struct xrdp_fastpath { struct xrdp_sec* sec_layer; /* owner */ - struct xrdp_tcp* tcp_layer; + struct trans* trans; int numEvents; int secFlags; }; +/* Encryption Methods */ +#define CRYPT_METHOD_NONE 0x00000000 +#define CRYPT_METHOD_40BIT 0x00000001 +#define CRYPT_METHOD_128BIT 0x00000002 +#define CRYPT_METHOD_56BIT 0x00000008 +#define CRYPT_METHOD_FIPS 0x00000010 + +/* Encryption Levels */ +#define CRYPT_LEVEL_NONE 0x00000000 +#define CRYPT_LEVEL_LOW 0x00000001 +#define CRYPT_LEVEL_CLIENT_COMPATIBLE 0x00000002 +#define CRYPT_LEVEL_HIGH 0x00000003 +#define CRYPT_LEVEL_FIPS 0x00000004 + + /* sec */ struct xrdp_sec { @@ -102,9 +109,9 @@ struct xrdp_sec char encrypt_key[16]; char decrypt_update_key[16]; char encrypt_update_key[16]; - int rc4_key_size; /* 1 = 40 bit, 2 = 128 bit */ + int crypt_method; int rc4_key_len; /* 8 = 40 bit, 16 = 128 bit */ - int crypt_level; /* 1, 2, 3 = low, meduim, high */ + int crypt_level; char sign_key[16]; void* decrypt_rc4_info; void* encrypt_rc4_info; @@ -114,6 +121,12 @@ struct xrdp_sec char pri_exp[64]; int channel_code; int multimon; + char fips_encrypt_key[24]; + char fips_decrypt_key[24]; + char fips_sign_key[20]; + void* encrypt_fips_info; + void* decrypt_fips_info; + void* sign_fips_info; }; /* channel */ @@ -233,7 +246,7 @@ struct xrdp_orders_state int com_blt_width; /* 2 */ int com_blt_height; /* 2 */ int com_blt_dstformat; /* 2 */ - + }; /* orders */ @@ -485,10 +498,33 @@ xrdp_bitmap_compress(char* in_data, int width, int height, int start_line, struct stream* temp_s, int e); int APP_CC +xrdp_bitmap32_compress(char* in_data, int width, int height, + struct stream* s, int bpp, int byte_limit, + int start_line, struct stream* temp_s, + int e); +int APP_CC xrdp_jpeg_compress(void *handle, char* in_data, int width, int height, struct stream* s, int bpp, int byte_limit, int start_line, struct stream* temp_s, int e, int quality); + +int APP_CC +xrdp_codec_jpeg_compress(void *handle, + int format, /* input data format */ + char *inp_data, /* input data */ + int width, /* width of inp_data */ + int height, /* height of inp_data */ + int stride, /* inp_data stride, in bytes*/ + int x, /* x loc in inp_data */ + int y, /* y loc in inp_data */ + int cx, /* width of area to compress */ + int cy, /* height of area to compress */ + int quality, /* higher numbers compress less */ + char *out_data, /* dest for jpg image */ + int *io_len /* length of out_data and on return */ + /* len of compressed data */ + ); + void *APP_CC xrdp_jpeg_init(void); int APP_CC diff --git a/libxrdp/libxrdpinc.h b/libxrdp/libxrdpinc.h index e5f52a05..d322eafa 100644 --- a/libxrdp/libxrdpinc.h +++ b/libxrdp/libxrdpinc.h @@ -70,8 +70,8 @@ struct xrdp_session void* orders; struct xrdp_client_info* client_info; int up_and_running; - struct stream* s; int (*is_term)(void); + int in_process_data; /* inc / dec libxrdp_process_data calls */ }; struct xrdp_session* DEFAULT_CC @@ -83,7 +83,7 @@ libxrdp_disconnect(struct xrdp_session* session); int DEFAULT_CC libxrdp_process_incomming(struct xrdp_session* session); int DEFAULT_CC -libxrdp_process_data(struct xrdp_session* session); +libxrdp_process_data(struct xrdp_session* session, struct stream *s); int DEFAULT_CC libxrdp_send_palette(struct xrdp_session* session, int* palette); int DEFAULT_CC diff --git a/libxrdp/xrdp_bitmap32_compress.c b/libxrdp/xrdp_bitmap32_compress.c new file mode 100644 index 00000000..b681d040 --- /dev/null +++ b/libxrdp/xrdp_bitmap32_compress.c @@ -0,0 +1,32 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2014 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * planar bitmap compressor + * 32 bpp compression + */ + +#include "libxrdp.h" + +/*****************************************************************************/ +int APP_CC +xrdp_bitmap32_compress(char *in_data, int width, int height, + struct stream *s, int bpp, int byte_limit, + int start_line, struct stream *temp_s, + int e) +{ + return 0; +} diff --git a/libxrdp/xrdp_bitmap_compress.c b/libxrdp/xrdp_bitmap_compress.c index 28a08e77..03c56f10 100644 --- a/libxrdp/xrdp_bitmap_compress.c +++ b/libxrdp/xrdp_bitmap_compress.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,13 +16,15 @@ * limitations under the License. * * bitmap compressor + * This is the original RDP bitmap compression algorithm. Pixel based. + * This does not do 32 bpp compression, nscodec, rfx, etc */ #include "libxrdp.h" /*****************************************************************************/ #define IN_PIXEL8(in_ptr, in_x, in_y, in_w, in_last_pixel, in_pixel); \ - { \ + do { \ if (in_ptr == 0) \ { \ in_pixel = 0; \ @@ -35,11 +37,11 @@ { \ in_pixel = in_last_pixel; \ } \ - } + } while (0) /*****************************************************************************/ #define IN_PIXEL16(in_ptr, in_x, in_y, in_w, in_last_pixel, in_pixel); \ - { \ + do { \ if (in_ptr == 0) \ { \ in_pixel = 0; \ @@ -52,11 +54,11 @@ { \ in_pixel = in_last_pixel; \ } \ - } + } while (0) /*****************************************************************************/ #define IN_PIXEL32(in_ptr, in_x, in_y, in_w, in_last_pixel, in_pixel); \ - { \ + do { \ if (in_ptr == 0) \ { \ in_pixel = 0; \ @@ -69,12 +71,12 @@ { \ in_pixel = in_last_pixel; \ } \ - } + } while (0) /*****************************************************************************/ /* color */ #define OUT_COLOR_COUNT1(in_count, in_s, in_data) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count < 32) \ @@ -98,12 +100,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* color */ #define OUT_COLOR_COUNT2(in_count, in_s, in_data) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count < 32) \ @@ -127,12 +129,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* color */ #define OUT_COLOR_COUNT3(in_count, in_s, in_data) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count < 32) \ @@ -162,12 +164,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* copy */ #define OUT_COPY_COUNT1(in_count, in_s, in_data) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count < 32) \ @@ -192,12 +194,12 @@ } \ in_count = 0; \ init_stream(in_data, 0); \ - } + } while (0) /*****************************************************************************/ /* copy */ #define OUT_COPY_COUNT2(in_count, in_s, in_data) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count < 32) \ @@ -225,12 +227,12 @@ } \ in_count = 0; \ init_stream(in_data, 0); \ - } + } while (0) /*****************************************************************************/ /* copy */ #define OUT_COPY_COUNT3(in_count, in_s, in_data) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count < 32) \ @@ -258,12 +260,12 @@ } \ in_count = 0; \ init_stream(in_data, 0); \ - } + } while (0) /*****************************************************************************/ /* bicolor */ #define OUT_BICOLOR_COUNT1(in_count, in_s, in_color1, in_color2) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count / 2 < 16) \ @@ -291,12 +293,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* bicolor */ #define OUT_BICOLOR_COUNT2(in_count, in_s, in_color1, in_color2) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count / 2 < 16) \ @@ -324,12 +326,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* bicolor */ #define OUT_BICOLOR_COUNT3(in_count, in_s, in_color1, in_color2) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count / 2 < 16) \ @@ -369,12 +371,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* fill */ #define OUT_FILL_COUNT1(in_count, in_s) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count < 32) \ @@ -394,12 +396,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* fill */ #define OUT_FILL_COUNT2(in_count, in_s) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count < 32) \ @@ -419,12 +421,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* fill */ #define OUT_FILL_COUNT3(in_count, in_s) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count < 32) \ @@ -444,12 +446,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* mix */ #define OUT_MIX_COUNT1(in_count, in_s) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count < 32) \ @@ -470,12 +472,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* mix */ #define OUT_MIX_COUNT2(in_count, in_s) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count < 32) \ @@ -496,12 +498,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* mix */ #define OUT_MIX_COUNT3(in_count, in_s) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count < 32) \ @@ -522,12 +524,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* fom */ #define OUT_FOM_COUNT1(in_count, in_s, in_mask, in_mask_len) \ - { \ + do { \ if (in_count > 0) \ { \ if ((in_count % 8) == 0 && in_count < 249) \ @@ -551,12 +553,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* fom */ #define OUT_FOM_COUNT2(in_count, in_s, in_mask, in_mask_len) \ - { \ + do { \ if (in_count > 0) \ { \ if ((in_count % 8) == 0 && in_count < 249) \ @@ -580,12 +582,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* fill or mix (fom) */ #define OUT_FOM_COUNT3(in_count, in_s, in_mask, in_mask_len) \ - { \ + do { \ if (in_count > 0) \ { \ if ((in_count % 8) == 0 && in_count < 249) \ @@ -609,7 +611,7 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ #define TEST_FILL \ @@ -629,7 +631,7 @@ ) \ ) #define RESET_COUNTS \ - { \ + do { \ bicolor_count = 0; \ fill_count = 0; \ color_count = 0; \ @@ -637,7 +639,7 @@ fom_count = 0; \ fom_mask_len = 0; \ bicolor_spin = 0; \ - } + } while (0) /*****************************************************************************/ int APP_CC diff --git a/libxrdp/xrdp_fastpath.c b/libxrdp/xrdp_fastpath.c index fcd7ac72..bc6f49d2 100644 --- a/libxrdp/xrdp_fastpath.c +++ b/libxrdp/xrdp_fastpath.c @@ -28,7 +28,7 @@ xrdp_fastpath_create(struct xrdp_sec *owner, struct trans *trans) DEBUG((" in xrdp_fastpath_create")); self = (struct xrdp_fastpath *)g_malloc(sizeof(struct xrdp_fastpath), 1); self->sec_layer = owner; - self->tcp_layer = owner->mcs_layer->iso_layer->tcp_layer; + self->trans = trans; DEBUG((" out xrdp_fastpath_create")); return self; } @@ -69,7 +69,7 @@ xrdp_fastpath_recv(struct xrdp_fastpath *self, struct stream *s) self->secFlags = (fp_hdr & 0xC0) >> 6; // receive fastpath first length packet - if (xrdp_tcp_recv(self->tcp_layer, s, 1) != 0) + if (trans_force_read_s(self->trans, s, 1) != 0) { return 1; } diff --git a/libxrdp/xrdp_iso.c b/libxrdp/xrdp_iso.c index 1f546b0b..df00f52b 100644 --- a/libxrdp/xrdp_iso.c +++ b/libxrdp/xrdp_iso.c @@ -30,7 +30,7 @@ xrdp_iso_create(struct xrdp_mcs *owner, struct trans *trans) DEBUG((" in xrdp_iso_create")); self = (struct xrdp_iso *)g_malloc(sizeof(struct xrdp_iso), 1); self->mcs_layer = owner; - self->tcp_layer = xrdp_tcp_create(self, trans); + self->trans = trans; DEBUG((" out xrdp_iso_create")); return self; } @@ -44,7 +44,6 @@ xrdp_iso_delete(struct xrdp_iso *self) return; } - xrdp_tcp_delete(self->tcp_layer); g_free(self); } @@ -89,94 +88,30 @@ xrdp_iso_recv_rdpnegreq(struct xrdp_iso *self, struct stream *s) static int APP_CC xrdp_iso_recv_msg(struct xrdp_iso *self, struct stream *s, int *code, int *len) { - int plen; // PacketLength + int ver; // TPKT Version + int plen; // TPKT PacketLength + int do_read; *code = 0; // X.224 Packet Type *len = 0; // X.224 Length Indicator - plen = xrdp_iso_recv_tpkt_header(self, s); + /* early in connection sequence, iso needs to do a force read */ + do_read = s != self->trans->in_s; - if (plen == 2) + if (do_read) { - DEBUG(("xrdp_iso_recv_msg: non-TPKT header detected, we try fastpath")); - return plen; + init_stream(s, 4); + if (trans_force_read_s(self->trans, s, 4) != 0) + { + return 1; + } } - if (plen == 1) { - return 1; - } - - // receive the left bytes - if (xrdp_tcp_recv(self->tcp_layer, s, plen - 4) != 0) - { - return 1; - } - - xrdp_iso_read_x224_header(s, code, len); - - return 0; -} -/*****************************************************************************/ -/* returns error */ -int APP_CC -xrdp_iso_recv(struct xrdp_iso *self, struct stream *s) -{ - int code; - int len; - int iso_msg; - - DEBUG((" in xrdp_iso_recv")); - - iso_msg = xrdp_iso_recv_msg(self, s, &code, &len); - - if (iso_msg == 2) // non-TPKT header - { - DEBUG((" out xrdp_iso_recv xrdp_iso_recv_msg return 2, non-TPKT header detected")); - return iso_msg; - } - - if (iso_msg == 1) // error - { - DEBUG((" out xrdp_iso_recv xrdp_iso_recv_msg return non zero")); - return 1; - } - - if (code != ISO_PDU_DT || len != 2) - { - DEBUG((" out xrdp_iso_recv code != ISO_PDU_DT or length != 2")); - return 1; - } - - DEBUG((" out xrdp_iso_recv")); - return 0; -} -/*****************************************************************************/ -/* returns packet length or error (1) */ -int APP_CC -xrdp_iso_recv_tpkt_header(struct xrdp_iso *self, struct stream *s) -{ - int plen; - int ver; - - if (xrdp_tcp_recv(self->tcp_layer, s, 1) != 0) - { - return 1; - } - - in_uint8_peek(s, ver); // Peek only so we can use it later in fastpath layer, if needed + in_uint8(s, ver); if (ver != 3) { - /* - * special error code that means we got non-TPKT header, - * so we gonna try fastpath input. - */ - return 2; - } - - if (xrdp_tcp_recv(self->tcp_layer, s, 3) != 0) - { - return 1; + return 2; // special code for fastpath } in_uint8s(s, 1); @@ -184,32 +119,25 @@ xrdp_iso_recv_tpkt_header(struct xrdp_iso *self, struct stream *s) if (plen < 4) { - return 1; // tpkt must be >= 4 bytes length + return 1; + } + + if (do_read) + { + init_stream(s, plen - 4); + if (trans_force_read_s(self->trans, s, plen - 4) != 0) + { + return 1; + } } - return plen; -} -/*****************************************************************************/ -void APP_CC -xrdp_iso_write_tpkt_header(struct stream *s, int len) -{ - /* TPKT HEADER - 4 bytes */ - out_uint8(s, 3); /* version */ - out_uint8(s, 0); /* RESERVED */ - out_uint16_be(s, len); /* length */ -} -/*****************************************************************************/ -/* returns error */ -int APP_CC -xrdp_iso_read_x224_header(struct stream *s, int *code, int *len) -{ if (!s_check_rem(s, 2)) { return 1; } - in_uint8(s, *len); /* length */ - in_uint8(s, *code); /* code */ + in_uint8(s, *len); + in_uint8(s, *code); if (*code == ISO_PDU_DT) { @@ -230,55 +158,63 @@ xrdp_iso_read_x224_header(struct stream *s, int *code, int *len) return 0; } -/*****************************************************************************/ -void APP_CC -xrdp_iso_write_x224_header(struct stream *s, int len, int code) -{ - /* ISO LAYER - X.224 - 7 bytes*/ - out_uint8(s, len); /* length */ - out_uint8(s, code); /* code */ - if (code == ISO_PDU_DT) - { - out_uint8(s, 0x80); - } else { - out_uint16_be(s, 0); - out_uint16_be(s, 0x1234); - out_uint8(s, 0); - } -} /*****************************************************************************/ -static int APP_CC -xrdp_iso_send_rdpnegrsp(struct xrdp_iso *self, struct stream *s) +/* returns error */ +int APP_CC +xrdp_iso_recv(struct xrdp_iso *self, struct stream *s) { - if (xrdp_tcp_init(self->tcp_layer, s) != 0) + int code; + int len; + + DEBUG((" in xrdp_iso_recv")); + + if (xrdp_iso_recv_msg(self, s, &code, &len) != 0) { + DEBUG((" out xrdp_iso_recv xrdp_iso_recv_msg return non zero")); return 1; } - // Write TPKT Header + if (code != ISO_PDU_DT || len != 2) + { + DEBUG((" out xrdp_iso_recv code != ISO_PDU_DT or length != 2")); + return 1; + } + + DEBUG((" out xrdp_iso_recv")); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +xrdp_iso_send_rdpnegrsp(struct xrdp_iso *self, struct stream *s, int code) +{ + init_stream(s, 8192 * 4); /* 32 KB */ + + /* TPKT HEADER - 4 bytes */ + out_uint8(s, 3); /* version */ + out_uint8(s, 0); /* RESERVED */ if (self->selectedProtocol != -1) { - //rdp negotiation happens. - xrdp_iso_write_tpkt_header(s, 19); + out_uint16_be(s, 19); /* length */ //rdp negotiation happens. } else { - //rdp negotiation doesn't happen. - xrdp_iso_write_tpkt_header(s, 11); + out_uint16_be(s, 11); /* length */ //rdp negotiation doesn't happen. } - - // Write x224 header + /* ISO LAYER - X.224 - 7 bytes*/ if (self->selectedProtocol != -1) { - xrdp_iso_write_x224_header(s, 14, ISO_PDU_CC); + out_uint8(s, 14); /* length */ } else { - xrdp_iso_write_x224_header(s, 6, ISO_PDU_CC); + out_uint8(s, 6); /* length */ } - - /* RDP_NEG */ + out_uint8(s, code); /* SHOULD BE 0xD for CC */ + out_uint16_be(s, 0); + out_uint16_be(s, 0x1234); + out_uint8(s, 0); if (self->selectedProtocol != -1) { /* RDP_NEG_RSP - 8 bytes*/ @@ -290,7 +226,7 @@ xrdp_iso_send_rdpnegrsp(struct xrdp_iso *self, struct stream *s) s_mark_end(s); - if (xrdp_tcp_send(self->tcp_layer, s) != 0) + if (trans_force_write_s(self->trans, s) != 0) { return 1; } @@ -299,17 +235,20 @@ xrdp_iso_send_rdpnegrsp(struct xrdp_iso *self, struct stream *s) } /*****************************************************************************/ static int APP_CC -xrdp_iso_send_rdpnegfailure(struct xrdp_iso *self, struct stream *s, int failureCode) +xrdp_iso_send_rdpnegfailure(struct xrdp_iso *self, struct stream *s, int code, int failureCode) { - if (xrdp_tcp_init(self->tcp_layer, s) != 0) - { - return 1; - } - - xrdp_iso_write_tpkt_header(s, 19); - - xrdp_iso_write_x224_header(s, 14, ISO_PDU_CC); + init_stream(s, 8192 * 4); /* 32 KB */ + /* TPKT HEADER - 4 bytes */ + out_uint8(s, 3); /* version */ + out_uint8(s, 0); /* RESERVED */ + out_uint16_be(s, 19); /* length */ + /* ISO LAYER - X.224 - 7 bytes*/ + out_uint8(s, 14); /* length */ + out_uint8(s, code); /* SHOULD BE 0xD for CC */ + out_uint16_be(s, 0); + out_uint16_be(s, 0x1234); + out_uint8(s, 0); /* RDP_NEG_FAILURE - 8 bytes*/ out_uint8(s, RDP_NEG_FAILURE); out_uint8(s, 0); /* no flags available */ @@ -317,7 +256,7 @@ xrdp_iso_send_rdpnegfailure(struct xrdp_iso *self, struct stream *s, int failure out_uint32_le(s, failureCode); /* failure code */ s_mark_end(s); - if (xrdp_tcp_send(self->tcp_layer, s) != 0) + if (trans_force_write_s(self->trans, s) != 0) { return 1; } @@ -338,7 +277,8 @@ xrdp_iso_send_nego(struct xrdp_iso *self) if (self->requestedProtocol != PROTOCOL_RDP) { // Send RDP_NEG_FAILURE back to client - if (xrdp_iso_send_rdpnegfailure(self, s, SSL_NOT_ALLOWED_BY_SERVER) != 0) + if (xrdp_iso_send_rdpnegfailure(self, s, ISO_PDU_CC, + SSL_NOT_ALLOWED_BY_SERVER) != 0) { free_stream(s); return 1; @@ -348,7 +288,7 @@ xrdp_iso_send_nego(struct xrdp_iso *self) { self->selectedProtocol = PROTOCOL_RDP; // Send RDP_NEG_RSP back to client - if (xrdp_iso_send_rdpnegrsp(self, s) != 0) + if (xrdp_iso_send_rdpnegrsp(self, s, ISO_PDU_CC) != 0) { free_stream(s); return 1; @@ -384,7 +324,6 @@ xrdp_iso_incoming(struct xrdp_iso *self) if ((code != ISO_PDU_CR) || (len < 6)) { - DEBUG((" in xrdp_iso_recv_msg error: non iso_pdu_cr msg")); free_stream(s); return 1; } @@ -446,7 +385,7 @@ xrdp_iso_incoming(struct xrdp_iso *self) int APP_CC xrdp_iso_init(struct xrdp_iso *self, struct stream *s) { - xrdp_tcp_init(self->tcp_layer, s); + init_stream(s, 8192 * 4); /* 32 KB */ s_push_layer(s, iso_hdr, 7); return 0; } @@ -461,11 +400,14 @@ xrdp_iso_send(struct xrdp_iso *self, struct stream *s) DEBUG((" in xrdp_iso_send")); s_pop_layer(s, iso_hdr); len = (int)(s->end - s->p); + out_uint8(s, 3); + out_uint8(s, 0); + out_uint16_be(s, len); + out_uint8(s, 2); + out_uint8(s, ISO_PDU_DT); + out_uint8(s, 0x80); - xrdp_iso_write_tpkt_header(s, len); - xrdp_iso_write_x224_header(s, 2, ISO_PDU_DT); - - if (xrdp_tcp_send(self->tcp_layer, s) != 0) + if (trans_force_write_s(self->trans, s) != 0) { return 1; } diff --git a/libxrdp/xrdp_jpeg_compress.c b/libxrdp/xrdp_jpeg_compress.c index a41bd1cf..334cc2e3 100644 --- a/libxrdp/xrdp_jpeg_compress.c +++ b/libxrdp/xrdp_jpeg_compress.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -98,6 +98,67 @@ xrdp_jpeg_compress(void *handle, char *in_data, int width, int height, return height; } +/** + * Compress a rectangular area (aka inner rectangle) inside our + * frame buffer (inp_data) + *****************************************************************************/ + +int APP_CC +xrdp_codec_jpeg_compress(void *handle, + int format, /* input data format */ + char *inp_data, /* input data */ + int width, /* width of inp_data */ + int height, /* height of inp_data */ + int stride, /* inp_data stride, in bytes*/ + int x, /* x loc in inp_data */ + int y, /* y loc in inp_data */ + int cx, /* width of area to compress */ + int cy, /* height of area to compress */ + int quality, /* higher numbers compress less */ + char *out_data, /* dest for jpg image */ + int *io_len /* length of out_data and on return */ + /* len of compressed data */ + ) +{ + tjhandle tj_han; + int error; + int bpp; + char *src_ptr; + + /* + * note: for now we assume that format is always XBGR and ignore format + */ + + if (handle == 0) + { + g_writeln("xrdp_codec_jpeg_compress: handle is nil"); + return height; + } + + tj_han = (tjhandle) handle; + + /* get bytes per pixel */ + bpp = stride / width; + + /* start of inner rect in inp_data */ + src_ptr = inp_data + (y * stride + x * bpp); + + /* compress inner rect */ + error = tjCompress(tj_han, /* opaque handle */ + src_ptr, /* source buf */ + cx, /* width of area to compress */ + stride, /* pitch */ + cy, /* height of area to compress */ + TJPF_XBGR, /* pixel size */ + out_data, /* dest buf */ + io_len, /* inner_buf length & compressed_size */ + TJSAMP_420, /* jpeg sub sample */ + quality, /* jpeg quality */ + 0 /* flags */ + ); + return height; +} + /*****************************************************************************/ void *APP_CC xrdp_jpeg_init(void) diff --git a/libxrdp/xrdp_mcs.c b/libxrdp/xrdp_mcs.c index 2c643373..526587d5 100644 --- a/libxrdp/xrdp_mcs.c +++ b/libxrdp/xrdp_mcs.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -75,8 +75,8 @@ xrdp_mcs_delete(struct xrdp_mcs *self) } /*****************************************************************************/ -/* This function sends channel join confirm*/ -/* returns error = 1 ok = 0*/ +/* This function sends channel join confirm */ +/* returns error = 1 ok = 0 */ static int APP_CC xrdp_mcs_send_cjcf(struct xrdp_mcs *self, int userid, int chanid) { @@ -160,6 +160,12 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan) /* this is channels getting added from the client */ if (appid == MCS_CJRQ) { + if (s == self->iso_layer->trans->in_s) + { + /* this should not happen */ + g_writeln("xrdp_mcs_recv: error, MCS_CJRQ at wrong time"); + return 1; + } if (!s_check_rem(s, 4)) { return 1; @@ -174,13 +180,12 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan) { log_message(LOG_LEVEL_ERROR,"Non handled error from xrdp_mcs_send_cjcf") ; } - continue; } if (appid == MCS_SDRQ || appid == MCS_SDIN) { - break ; + break; } else { @@ -955,16 +960,17 @@ xrdp_mcs_send(struct xrdp_mcs *self, struct stream *s, int chan) * Internal help function to close the socket * @param self */ -void close_rdp_socket(struct xrdp_mcs *self) +void APP_CC +close_rdp_socket(struct xrdp_mcs *self) { - if(self->iso_layer->tcp_layer) + if (self->iso_layer != 0) { - if(self->iso_layer->tcp_layer->trans) + if (self->iso_layer->trans != 0) { - g_tcp_close(self->iso_layer->tcp_layer->trans->sck); - self->iso_layer->tcp_layer->trans->sck = 0 ; + g_tcp_close(self->iso_layer->trans->sck); + self->iso_layer->trans->sck = 0 ; g_writeln("xrdp_mcs_disconnect - socket closed"); - return ; + return; } } g_writeln("Failed to close socket"); diff --git a/libxrdp/xrdp_orders.c b/libxrdp/xrdp_orders.c index 0e2d90d2..317e1135 100644 --- a/libxrdp/xrdp_orders.c +++ b/libxrdp/xrdp_orders.c @@ -2570,8 +2570,16 @@ xrdp_orders_send_bitmap2(struct xrdp_orders *self, init_stream(temp_s, 16384); p = s->p; i = height; - lines_sending = xrdp_bitmap_compress(data, width, height, s, bpp, 16384, - i - 1, temp_s, e); + if (bpp > 24) + { + lines_sending = xrdp_bitmap32_compress(data, width, height, s, bpp, 16384, + i - 1, temp_s, e); + } + else + { + lines_sending = xrdp_bitmap_compress(data, width, height, s, bpp, 16384, + i - 1, temp_s, e); + } if (lines_sending != height) { diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index a98d507e..85ca15d7 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ #if defined(XRDP_NEUTRINORDP) #include +#include #endif /*****************************************************************************/ @@ -79,6 +80,10 @@ xrdp_rdp_read_config(struct xrdp_client_info *client_info) { client_info->crypt_level = 3; } + else if (g_strcasecmp(value, "fips") == 0) + { + client_info->crypt_level = 4; + } else { log_message(LOG_LEVEL_ALWAYS,"Warning: Your configured crypt level is" @@ -218,8 +223,10 @@ xrdp_rdp_create(struct xrdp_session *session, struct trans *trans) /* read ini settings */ xrdp_rdp_read_config(&self->client_info); /* create sec layer */ - self->sec_layer = xrdp_sec_create(self, trans, self->client_info.crypt_level, - self->client_info.channel_code, self->client_info.multimon); + self->sec_layer = xrdp_sec_create(self, trans, + self->client_info.crypt_level, + self->client_info.channel_code, + self->client_info.multimon); /* default 8 bit v1 color bitmap cache entries and size */ self->client_info.cache1_entries = 600; self->client_info.cache1_size = 256; @@ -331,7 +338,10 @@ xrdp_rdp_recv(struct xrdp_rdp *self, struct stream *s, int *code) } else { - g_writeln("Wrong channel Id to be handled by xrdp_channel_process %d", chan); + if (chan != 1) + { + g_writeln("Wrong channel Id to be handled by xrdp_channel_process %d", chan); + } } s->next_packet = 0; @@ -511,69 +521,6 @@ xrdp_rdp_send_data_update_sync(struct xrdp_rdp *self) return 0; } -/*****************************************************************************/ -static int APP_CC -xrdp_rdp_parse_client_mcs_data(struct xrdp_rdp *self) -{ - struct stream *p = (struct stream *)NULL; - int i = 0; - - p = &(self->sec_layer->client_mcs_data); - p->p = p->data; - if (!s_check_rem(p, 31 + 2 + 2 + 120 + 2)) - { - g_writeln("xrdp_rdp_parse_client_mcs_data: error"); - return 1; - } - in_uint8s(p, 31); - in_uint16_le(p, self->client_info.width); - in_uint16_le(p, self->client_info.height); - in_uint8s(p, 120); - self->client_info.bpp = 8; - in_uint16_le(p, i); - - switch (i) - { - case 0xca01: - if (!s_check_rem(p, 6 + 1)) - { - return 1; - } - in_uint8s(p, 6); - in_uint8(p, i); - - if (i > 8) - { - self->client_info.bpp = i; - } - - break; - case 0xca02: - self->client_info.bpp = 15; - break; - case 0xca03: - self->client_info.bpp = 16; - break; - case 0xca04: - self->client_info.bpp = 24; - break; - } - - if (self->client_info.max_bpp > 0) - { - if (self->client_info.bpp > self->client_info.max_bpp) - { - self->client_info.bpp = self->client_info.max_bpp; - } - } - - p->p = p->data; - DEBUG(("client width %d, client height %d bpp %d", - self->client_info.width, self->client_info.height, - self->client_info.bpp)); - return 0; -} - /*****************************************************************************/ int APP_CC xrdp_rdp_incoming(struct xrdp_rdp *self) @@ -584,19 +531,15 @@ xrdp_rdp_incoming(struct xrdp_rdp *self) { return 1; } - self->mcs_channel = self->sec_layer->mcs_layer->userid + MCS_USERCHANNEL_BASE; - xrdp_rdp_parse_client_mcs_data(self); DEBUG(("out xrdp_rdp_incoming mcs channel %d", self->mcs_channel)); - g_strncpy(self->client_info.client_addr, - self->sec_layer->mcs_layer->iso_layer->tcp_layer->trans->addr, + self->sec_layer->mcs_layer->iso_layer->trans->addr, sizeof(self->client_info.client_addr) - 1); g_strncpy(self->client_info.client_port, - self->sec_layer->mcs_layer->iso_layer->tcp_layer->trans->port, + self->sec_layer->mcs_layer->iso_layer->trans->port, sizeof(self->client_info.client_port) - 1); - return 0; } @@ -1657,6 +1600,7 @@ xrdp_rdp_process_data_font(struct xrdp_rdp *self, struct stream *s) xrdp_rdp_send_fontmap(self); self->session->up_and_running = 1; + g_writeln("yeah, up_and_running"); DEBUG(("up_and_running set")); xrdp_rdp_send_data_update_sync(self); } diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index 37209772..ec9b5711 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,12 @@ #include "libxrdp.h" #include "log.h" +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { g_write _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { g_writeln _args ; } } while (0) + /* some compilers need unsigned char to avoid warnings */ static tui8 g_pad_54[40] = { @@ -100,6 +106,83 @@ static tui8 g_lic3[20] = 0xf3, 0x99, 0x00, 0x00 }; +static const tui8 g_fips_reverse_table[256] = +{ + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff +}; + +static const tui8 g_fips_oddparity_table[256] = +{ + 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x07, 0x07, + 0x08, 0x08, 0x0b, 0x0b, 0x0d, 0x0d, 0x0e, 0x0e, + 0x10, 0x10, 0x13, 0x13, 0x15, 0x15, 0x16, 0x16, + 0x19, 0x19, 0x1a, 0x1a, 0x1c, 0x1c, 0x1f, 0x1f, + 0x20, 0x20, 0x23, 0x23, 0x25, 0x25, 0x26, 0x26, + 0x29, 0x29, 0x2a, 0x2a, 0x2c, 0x2c, 0x2f, 0x2f, + 0x31, 0x31, 0x32, 0x32, 0x34, 0x34, 0x37, 0x37, + 0x38, 0x38, 0x3b, 0x3b, 0x3d, 0x3d, 0x3e, 0x3e, + 0x40, 0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46, + 0x49, 0x49, 0x4a, 0x4a, 0x4c, 0x4c, 0x4f, 0x4f, + 0x51, 0x51, 0x52, 0x52, 0x54, 0x54, 0x57, 0x57, + 0x58, 0x58, 0x5b, 0x5b, 0x5d, 0x5d, 0x5e, 0x5e, + 0x61, 0x61, 0x62, 0x62, 0x64, 0x64, 0x67, 0x67, + 0x68, 0x68, 0x6b, 0x6b, 0x6d, 0x6d, 0x6e, 0x6e, + 0x70, 0x70, 0x73, 0x73, 0x75, 0x75, 0x76, 0x76, + 0x79, 0x79, 0x7a, 0x7a, 0x7c, 0x7c, 0x7f, 0x7f, + 0x80, 0x80, 0x83, 0x83, 0x85, 0x85, 0x86, 0x86, + 0x89, 0x89, 0x8a, 0x8a, 0x8c, 0x8c, 0x8f, 0x8f, + 0x91, 0x91, 0x92, 0x92, 0x94, 0x94, 0x97, 0x97, + 0x98, 0x98, 0x9b, 0x9b, 0x9d, 0x9d, 0x9e, 0x9e, + 0xa1, 0xa1, 0xa2, 0xa2, 0xa4, 0xa4, 0xa7, 0xa7, + 0xa8, 0xa8, 0xab, 0xab, 0xad, 0xad, 0xae, 0xae, + 0xb0, 0xb0, 0xb3, 0xb3, 0xb5, 0xb5, 0xb6, 0xb6, + 0xb9, 0xb9, 0xba, 0xba, 0xbc, 0xbc, 0xbf, 0xbf, + 0xc1, 0xc1, 0xc2, 0xc2, 0xc4, 0xc4, 0xc7, 0xc7, + 0xc8, 0xc8, 0xcb, 0xcb, 0xcd, 0xcd, 0xce, 0xce, + 0xd0, 0xd0, 0xd3, 0xd3, 0xd5, 0xd5, 0xd6, 0xd6, + 0xd9, 0xd9, 0xda, 0xda, 0xdc, 0xdc, 0xdf, 0xdf, + 0xe0, 0xe0, 0xe3, 0xe3, 0xe5, 0xe5, 0xe6, 0xe6, + 0xe9, 0xe9, 0xea, 0xea, 0xec, 0xec, 0xef, 0xef, + 0xf1, 0xf1, 0xf2, 0xf2, 0xf4, 0xf4, 0xf7, 0xf7, + 0xf8, 0xf8, 0xfb, 0xfb, 0xfd, 0xfd, 0xfe, 0xfe +}; + +static const tui8 g_fips_ivec[8] = +{ + 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF +}; + /*****************************************************************************/ static void APP_CC hex_str_to_bin(char *in, char *out, int out_len) @@ -145,22 +228,25 @@ xrdp_sec_create(struct xrdp_rdp *owner, struct trans *trans, int crypt_level, DEBUG((" in xrdp_sec_create")); self = (struct xrdp_sec *)g_malloc(sizeof(struct xrdp_sec), 1); self->rdp_layer = owner; - self->rc4_key_size = 1; /* 1 = 40 bit, 2 = 128 bit */ - self->crypt_level = 1; /* 1, 2, 3 = low, medium, high */ - + self->crypt_method = CRYPT_METHOD_NONE; + self->crypt_level = CRYPT_LEVEL_NONE; switch (crypt_level) { - case 1: - self->rc4_key_size = 1; - self->crypt_level = 1; + case 1: /* low */ + self->crypt_method = CRYPT_METHOD_40BIT; + self->crypt_level = CRYPT_LEVEL_LOW; break; - case 2: - self->rc4_key_size = 1; - self->crypt_level = 2; + case 2: /* medium */ + self->crypt_method = CRYPT_METHOD_40BIT; + self->crypt_level = CRYPT_LEVEL_CLIENT_COMPATIBLE; break; - case 3: - self->rc4_key_size = 2; - self->crypt_level = 3; + case 3: /* high */ + self->crypt_method = CRYPT_METHOD_128BIT; + self->crypt_level = CRYPT_LEVEL_HIGH; + break; + case 4: /* fips */ + self->crypt_method = CRYPT_METHOD_FIPS; + self->crypt_level = CRYPT_LEVEL_FIPS; break; default: g_writeln("Fatal : Illegal crypt_level"); @@ -206,6 +292,9 @@ xrdp_sec_delete(struct xrdp_sec *self) xrdp_fastpath_delete(self->fastpath_layer); ssl_rc4_info_delete(self->decrypt_rc4_info); /* TODO clear all data */ ssl_rc4_info_delete(self->encrypt_rc4_info); /* TODO clear all data */ + ssl_des3_info_delete(self->decrypt_fips_info); + ssl_des3_info_delete(self->encrypt_fips_info); + ssl_hmac_info_delete(self->sign_fips_info); g_free(self->client_mcs_data.data); g_free(self->server_mcs_data.data); /* Crypto information must always be cleared */ @@ -223,7 +312,11 @@ xrdp_sec_init(struct xrdp_sec *self, struct stream *s) return 1; } - if (self->crypt_level > 1) + if (self->crypt_level == CRYPT_LEVEL_FIPS) + { + s_push_layer(s, sec_hdr, 4 + 4 + 8); + } + else if (self->crypt_level > CRYPT_LEVEL_LOW) { s_push_layer(s, sec_hdr, 4 + 8); } @@ -283,10 +376,20 @@ xrdp_sec_update(char *key, char *update_key, int key_len) return 0; } +/*****************************************************************************/ +static void APP_CC +xrdp_sec_fips_decrypt(struct xrdp_sec *self, char *data, int len) +{ + LLOGLN(10, ("xrdp_sec_fips_decrypt:")); + ssl_des3_decrypt(self->decrypt_fips_info, len, data, data); + self->decrypt_use_count++; +} + /*****************************************************************************/ static void APP_CC xrdp_sec_decrypt(struct xrdp_sec *self, char *data, int len) { + LLOGLN(10, ("xrdp_sec_decrypt:")); if (self->decrypt_use_count == 4096) { xrdp_sec_update(self->decrypt_key, self->decrypt_update_key, @@ -295,15 +398,24 @@ xrdp_sec_decrypt(struct xrdp_sec *self, char *data, int len) self->rc4_key_len); self->decrypt_use_count = 0; } - ssl_rc4_crypt(self->decrypt_rc4_info, data, len); self->decrypt_use_count++; } +/*****************************************************************************/ +static void APP_CC +xrdp_sec_fips_encrypt(struct xrdp_sec *self, char *data, int len) +{ + LLOGLN(10, ("xrdp_sec_fips_encrypt:")); + ssl_des3_encrypt(self->encrypt_fips_info, len, data, data); + self->encrypt_use_count++; +} + /*****************************************************************************/ static void APP_CC xrdp_sec_encrypt(struct xrdp_sec *self, char *data, int len) { + LLOGLN(10, ("xrdp_sec_encrypt:")); if (self->encrypt_use_count == 4096) { xrdp_sec_update(self->encrypt_key, self->encrypt_update_key, @@ -383,6 +495,8 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) { /* must be or error */ DEBUG(("xrdp_sec_process_logon_info: flags wrong, major error")); + LLOGLN(0, ("xrdp_sec_process_logon_info: flags wrong, likely decrypt " + "not working")); return 1; } @@ -559,8 +673,9 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) static int APP_CC xrdp_sec_send_lic_initial(struct xrdp_sec *self) { - struct stream *s = (struct stream *)NULL; + struct stream *s; + LLOGLN(10, ("xrdp_sec_send_lic_initial:")); make_stream(s); init_stream(s, 8192); @@ -699,12 +814,103 @@ xrdp_sec_hash_16(char *out, char *in, char *salt1, char *salt2) /*****************************************************************************/ static void APP_CC +fips_expand_key_bits(const char *in, char *out) +{ + tui8 buf[32]; + tui8 c; + int i; + int b; + int p; + int r; + + /* reverse every byte in the key */ + for (i = 0; i < 21; i++) + { + c = in[i]; + buf[i] = g_fips_reverse_table[c]; + } + /* insert a zero-bit after every 7th bit */ + for (i = 0, b = 0; i < 24; i++, b += 7) + { + p = b / 8; + r = b % 8; + if (r == 0) + { + out[i] = buf[p] & 0xfe; + } + else + { + /* c is accumulator */ + c = buf[p] << r; + c |= buf[p + 1] >> (8 - r); + out[i] = c & 0xfe; + } + } + /* reverse every byte */ + /* alter lsb so the byte has odd parity */ + for (i = 0; i < 24; i++) + { + c = out[i]; + c = g_fips_reverse_table[c]; + out[i] = g_fips_oddparity_table[c]; + } +} + +/****************************************************************************/ +static void APP_CC +xrdp_sec_fips_establish_keys(struct xrdp_sec *self) +{ + char server_encrypt_key[32]; + char server_decrypt_key[32]; + const char *fips_ivec; + void *sha1; + + LLOGLN(0, ("xrdp_sec_fips_establish_keys:")); + + sha1 = ssl_sha1_info_create(); + ssl_sha1_clear(sha1); + ssl_sha1_transform(sha1, self->client_random + 16, 16); + ssl_sha1_transform(sha1, self->server_random + 16, 16); + ssl_sha1_complete(sha1, server_decrypt_key); + + server_decrypt_key[20] = server_decrypt_key[0]; + fips_expand_key_bits(server_decrypt_key, self->fips_decrypt_key); + ssl_sha1_info_delete(sha1); + + sha1 = ssl_sha1_info_create(); + ssl_sha1_clear(sha1); + ssl_sha1_transform(sha1, self->client_random, 16); + ssl_sha1_transform(sha1, self->server_random, 16); + ssl_sha1_complete(sha1, server_encrypt_key); + server_encrypt_key[20] = server_encrypt_key[0]; + fips_expand_key_bits(server_encrypt_key, self->fips_encrypt_key); + ssl_sha1_info_delete(sha1); + + sha1 = ssl_sha1_info_create(); + ssl_sha1_clear(sha1); + ssl_sha1_transform(sha1, server_encrypt_key, 20); + ssl_sha1_transform(sha1, server_decrypt_key, 20); + ssl_sha1_complete(sha1, self->fips_sign_key); + ssl_sha1_info_delete(sha1); + + fips_ivec = (const char *) g_fips_ivec; + self->encrypt_fips_info = + ssl_des3_encrypt_info_create(self->fips_encrypt_key, fips_ivec); + self->decrypt_fips_info = + ssl_des3_decrypt_info_create(self->fips_decrypt_key, fips_ivec); + self->sign_fips_info = ssl_hmac_info_create(); +} + +/****************************************************************************/ +static void APP_CC xrdp_sec_establish_keys(struct xrdp_sec *self) { char session_key[48]; char temp_hash[48]; char input[48]; + LLOGLN(0, ("xrdp_sec_establish_keys:")); + g_memcpy(input, self->client_random, 24); g_memcpy(input + 24, self->server_random, 24); xrdp_sec_hash_48(temp_hash, input, self->client_random, @@ -717,7 +923,7 @@ xrdp_sec_establish_keys(struct xrdp_sec *self) xrdp_sec_hash_16(self->decrypt_key, session_key + 32, self->client_random, self->server_random); - if (self->rc4_key_size == 1) + if (self->crypt_method == CRYPT_METHOD_40BIT) { xrdp_sec_make_40bit(self->sign_key); xrdp_sec_make_40bit(self->encrypt_key); @@ -767,6 +973,9 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) int flags; int len; int mcs_msg; + int ver; + int pad; + DEBUG((" in xrdp_sec_recv")); @@ -794,12 +1003,34 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) if (flags & SEC_ENCRYPT) /* 0x08 */ { - if (!s_check_rem(s, 8)) + if (self->crypt_level == CRYPT_LEVEL_FIPS) { - return 1; + if (!s_check_rem(s, 12)) + { + return 1; + } + in_uint16_le(s, len); + in_uint8(s, ver); + if ((len != 16) || (ver != 1)) + { + return 1; + } + in_uint8(s, pad); + LLOGLN(10, ("xrdp_sec_recv: len %d ver %d pad %d", len, ver, pad)); + in_uint8s(s, 8); /* signature(8) */ + LLOGLN(10, ("xrdp_sec_recv: data len %d", (int)(s->end - s->p))); + xrdp_sec_fips_decrypt(self, s->p, (int)(s->end - s->p)); + s->end -= pad; + } + else + { + if (!s_check_rem(s, 8)) + { + return 1; + } + in_uint8s(s, 8); /* signature(8) */ + xrdp_sec_decrypt(self, s->p, (int)(s->end - s->p)); } - in_uint8s(s, 8); /* signature */ - xrdp_sec_decrypt(self, s->p, (int)(s->end - s->p)); } if (flags & SEC_CLIENT_RANDOM) /* 0x01 */ @@ -812,7 +1043,14 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) in_uint8a(s, self->client_crypt_random, 64); xrdp_sec_rsa_op(self->client_random, self->client_crypt_random, self->pub_mod, self->pri_exp); - xrdp_sec_establish_keys(self); + if (self->crypt_level == CRYPT_LEVEL_FIPS) + { + xrdp_sec_fips_establish_keys(self); + } + else + { + xrdp_sec_establish_keys(self); + } *chan = 1; /* just set a non existing channel and exit */ DEBUG((" out xrdp_sec_recv")); return 0; @@ -876,6 +1114,23 @@ buf_out_uint32(char *buffer, int value) buffer[3] = (value >> 24) & 0xff; } +/*****************************************************************************/ +/* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */ +static void APP_CC +xrdp_sec_fips_sign(struct xrdp_sec *self, char *out, int out_len, + char *data, int data_len) +{ + char buf[20]; + char lenhdr[4]; + + buf_out_uint32(lenhdr, self->encrypt_use_count); + ssl_hmac_sha1_init(self->sign_fips_info, self->fips_sign_key, 20); + ssl_hmac_transform(self->sign_fips_info, data, data_len); + ssl_hmac_transform(self->sign_fips_info, lenhdr, 4); + ssl_hmac_complete(self->sign_fips_info, buf, 20); + g_memcpy(out, buf, out_len); +} + /*****************************************************************************/ /* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */ static void APP_CC @@ -913,11 +1168,27 @@ int APP_CC xrdp_sec_send(struct xrdp_sec *self, struct stream *s, int chan) { int datalen; + int pad; + LLOGLN(10, ("xrdp_sec_send:")); DEBUG((" in xrdp_sec_send")); s_pop_layer(s, sec_hdr); - if (self->crypt_level > 1) + if (self->crypt_level == CRYPT_LEVEL_FIPS) + { + LLOGLN(10, ("xrdp_sec_send: fips")); + out_uint32_le(s, SEC_ENCRYPT); + datalen = (int)((s->end - s->p) - 12); + out_uint16_le(s, 16); /* crypto header size */ + out_uint8(s, 1); /* fips version */ + pad = (8 - (datalen % 8)) & 7; + g_memset(s->end, 0, pad); + s->end += pad; + out_uint8(s, pad); /* fips pad */ + xrdp_sec_fips_sign(self, s->p, 8, s->p + 8, datalen); + xrdp_sec_fips_encrypt(self, s->p + 8, datalen + pad); + } + else if (self->crypt_level > CRYPT_LEVEL_LOW) { out_uint32_le(s, SEC_ENCRYPT); datalen = (int)((s->end - s->p) - 8); @@ -938,38 +1209,234 @@ xrdp_sec_send(struct xrdp_sec *self, struct stream *s, int chan) return 0; } /*****************************************************************************/ -/* returns error */ +/* http://msdn.microsoft.com/en-us/library/cc240510.aspx + 2.2.1.3.2 Client Core Data (TS_UD_CS_CORE) */ static int APP_CC -xrdp_sec_process_mcs_cli_info(struct xrdp_sec *self, struct stream *s) +xrdp_sec_process_mcs_data_CS_CORE(struct xrdp_sec* self, struct stream* s) { - in_uint8s(s, 4); /* RDP client version */ - in_uint8s(s, 2); /* desktopWidth */ - in_uint8s(s, 2); /* desktopHeight */ - in_uint8s(s, 2); /* colorDepth */ - in_uint8s(s, 2); - in_uint8s(s, 4); - in_uint8s(s, 4); - in_uint8s(s, 32); - in_uint8s(s, 4); - in_uint8s(s, 4); - in_uint8s(s, 64); - in_uint8s(s, 2); - in_uint8s(s, 2); - in_uint8s(s, 4); - in_uint8s(s, 2); - in_uint8s(s, 2); - in_uint8s(s, 2); /* earlyCapabilityFlags */ - in_uint8s(s, 64); - in_uint8s(s, 1); - in_uint8s(s, 1); /* pad1octet */ - in_uint8s(s, 4); - in_uint8s(s, 4); - in_uint8s(s, 4); - in_uint8s(s, 2); - in_uint8s(s, 4); - in_uint8s(s, 4); + int colorDepth; + int postBeta2ColorDepth; + int highColorDepth; + int supportedColorDepths; + int earlyCapabilityFlags; + in_uint8s(s, 4); /* version */ + in_uint16_le(s, self->rdp_layer->client_info.width); + in_uint16_le(s, self->rdp_layer->client_info.height); + in_uint16_le(s, colorDepth); + g_writeln("colorDepth 0x%4.4x (0xca00 4bpp 0xca01 8bpp)", colorDepth); + switch (colorDepth) + { + case 0xca00: /* RNS_UD_COLOR_4BPP */ + self->rdp_layer->client_info.bpp = 4; + break; + case 0xca01: /* RNS_UD_COLOR_8BPP */ + self->rdp_layer->client_info.bpp = 8; + break; + } + in_uint8s(s, 2); /* SASSequence */ + in_uint8s(s, 4); /* keyboardLayout */ + in_uint8s(s, 4); /* clientBuild */ + in_uint8s(s, 32); /* clientName */ + in_uint8s(s, 4); /* keyboardType */ + in_uint8s(s, 4); /* keyboardSubType */ + in_uint8s(s, 4); /* keyboardFunctionKey */ + in_uint8s(s, 64); /* imeFileName */ + in_uint16_le(s, postBeta2ColorDepth); + g_writeln("postBeta2ColorDepth 0x%4.4x (0xca00 4bpp 0xca01 8bpp " + "0xca02 15bpp 0xca03 16bpp 0xca04 24bpp)", postBeta2ColorDepth); + + switch (postBeta2ColorDepth) + { + case 0xca00: /* RNS_UD_COLOR_4BPP */ + self->rdp_layer->client_info.bpp = 4; + break; + case 0xca01: /* RNS_UD_COLOR_8BPP */ + self->rdp_layer->client_info.bpp = 8; + break; + case 0xca02: /* RNS_UD_COLOR_16BPP_555 */ + self->rdp_layer->client_info.bpp = 15; + break; + case 0xca03: /* RNS_UD_COLOR_16BPP_565 */ + self->rdp_layer->client_info.bpp = 16; + break; + case 0xca04: /* RNS_UD_COLOR_24BPP */ + self->rdp_layer->client_info.bpp = 24; + break; + } + if (!s_check_rem(s, 2)) + { + return 0; + } + in_uint8s(s, 2); /* clientProductId */ + + if (!s_check_rem(s, 4)) + { + return 0; + } + in_uint8s(s, 4); /* serialNumber */ + + if (!s_check_rem(s, 2)) + { + return 0; + } + in_uint16_le(s, highColorDepth); + g_writeln("highColorDepth 0x%4.4x (0x0004 4bpp 0x0008 8bpp 0x000f 15bpp " + "0x0010 16 bpp 0x0018 24bpp)", highColorDepth); + self->rdp_layer->client_info.bpp = highColorDepth; + + if (!s_check_rem(s, 2)) + { + return 0; + } + in_uint16_le(s, supportedColorDepths); + g_writeln("supportedColorDepths 0x%4.4x (0x0001 24bpp 0x0002 16bpp " + "0x0004 15bpp 0x0008 32bpp)", supportedColorDepths); + + if (!s_check_rem(s, 2)) + { + return 0; + } + in_uint16_le(s, earlyCapabilityFlags); + self->rdp_layer->client_info.mcs_early_capability_flags = earlyCapabilityFlags; + g_writeln("earlyCapabilityFlags 0x%4.4x (0x0002 want32)", + earlyCapabilityFlags); + if ((earlyCapabilityFlags & 0x0002) && (supportedColorDepths & 0x0008)) + { + self->rdp_layer->client_info.bpp = 32; + } + + if (!s_check_rem(s, 64)) + { + return 0; + } + in_uint8s(s, 64); /* clientDigProductId */ + + if (!s_check_rem(s, 1)) + { + return 0; + } + in_uint8(s, self->rdp_layer->client_info.mcs_connection_type); /* connectionType */ + g_writeln("got client client connection type 0x%8.8x", + self->rdp_layer->client_info.mcs_connection_type); + + if (!s_check_rem(s, 1)) + { + return 0; + } + in_uint8s(s, 1); /* pad1octet */ + + if (!s_check_rem(s, 4)) + { + return 0; + } + in_uint8s(s, 4); /* serverSelectedProtocol */ + + if (!s_check_rem(s, 4)) + { + return 0; + } + in_uint8s(s, 4); /* desktopPhysicalWidth */ + + if (!s_check_rem(s, 4)) + { + return 0; + } + in_uint8s(s, 4); /* desktopPhysicalHeight */ + + if (!s_check_rem(s, 2)) + { + return 0; + } + in_uint8s(s, 2); /* reserved */ + + return 0; } + +/*****************************************************************************/ +static int APP_CC +xrdp_sec_process_mcs_data_CS_SECURITY(struct xrdp_sec *self, struct stream* s) +{ + int crypt_method; + int found; + + g_writeln("xrdp_sec_process_mcs_data_CS_SECURITY:"); + in_uint32_le(s, crypt_method); + if (crypt_method & CRYPT_METHOD_40BIT) + { + g_writeln(" client supports 40 bit encryption"); + } + if (crypt_method & CRYPT_METHOD_128BIT) + { + g_writeln(" client supports 128 bit encryption"); + } + if (crypt_method & CRYPT_METHOD_56BIT) + { + g_writeln(" client supports 56 bit encryption"); + } + if (crypt_method & CRYPT_METHOD_FIPS) + { + g_writeln(" client supports fips encryption"); + } + found = 0; + if ((found == 0) && + (self->crypt_method & CRYPT_METHOD_FIPS) && + (self->crypt_level == CRYPT_LEVEL_FIPS)) + { + if (crypt_method & CRYPT_METHOD_FIPS) + { + g_writeln(" client and server support fips, using fips"); + self->crypt_method = CRYPT_METHOD_FIPS; + self->crypt_level = CRYPT_LEVEL_FIPS; + found = 1; + } + } + if ((found == 0) && + (self->crypt_method & CRYPT_METHOD_128BIT) && + (self->crypt_level == CRYPT_LEVEL_HIGH)) + { + if (crypt_method & CRYPT_METHOD_128BIT) + { + g_writeln(" client and server support high crypt, using " + "high crypt"); + self->crypt_method = CRYPT_METHOD_128BIT; + self->crypt_level = CRYPT_LEVEL_HIGH; + found = 1; + } + } + if ((found == 0) && + (self->crypt_method & CRYPT_METHOD_40BIT) && + (self->crypt_level == CRYPT_LEVEL_CLIENT_COMPATIBLE)) + { + if (crypt_method & CRYPT_METHOD_40BIT) + { + g_writeln(" client and server support medium crypt, using " + "medium crypt"); + self->crypt_method = CRYPT_METHOD_40BIT; + self->crypt_level = CRYPT_LEVEL_CLIENT_COMPATIBLE; + found = 1; + } + } + if ((found == 0) && + (self->crypt_method & CRYPT_METHOD_40BIT) && + (self->crypt_level == CRYPT_LEVEL_LOW)) + { + if (crypt_method & CRYPT_METHOD_40BIT) + { + g_writeln(" client and server support low crypt, using " + "low crypt"); + self->crypt_method = CRYPT_METHOD_40BIT; + self->crypt_level = CRYPT_LEVEL_LOW; + found = 1; + } + } + if (found == 0) + { + g_writeln(" no security"); + } + return 0; +} + /*****************************************************************************/ /* this adds the mcs channels in the list of channels to be used when creating the server mcs data */ @@ -1019,6 +1486,7 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s) return 0; } + /*****************************************************************************/ /* reads the client monitors data */ static int APP_CC @@ -1074,6 +1542,7 @@ xrdp_sec_process_mcs_data_monitors(struct xrdp_sec *self, struct stream *s) } return 0; } + /*****************************************************************************/ /* process client mcs data, we need some things in here to create the server mcs data */ @@ -1101,46 +1570,73 @@ xrdp_sec_process_mcs_data(struct xrdp_sec *self) in_uint16_le(s, tag); in_uint16_le(s, size); - if (size < 4 || !s_check_rem(s, size - 4)) + if ((size < 4) || (!s_check_rem(s, size - 4))) { - g_writeln("error in xrdp_sec_process_mcs_data tag %d size %d", - tag, size); + LLOGLN(0, ("error in xrdp_sec_process_mcs_data tag %d size %d", + tag, size)); break; } + LLOGLN(10, ("xrdp_sec_process_mcs_data: 0x%8.8x", tag)); switch (tag) { - case SEC_TAG_CLI_INFO: -// if (xrdp_sec_process_mcs_cli_info(self, s) != 0) -// { -// return 1; -// } + case SEC_TAG_CLI_INFO: /* CS_CORE 0xC001 */ + if (xrdp_sec_process_mcs_data_CS_CORE(self, s) != 0) + { + return 1; + } break; - case SEC_TAG_CLI_CRYPT: + case SEC_TAG_CLI_CRYPT: /* CS_SECURITY 0xC002 */ + if (xrdp_sec_process_mcs_data_CS_SECURITY(self, s) != 0) + { + return 1; + } break; - case SEC_TAG_CLI_CHANNELS: + case SEC_TAG_CLI_CHANNELS: /* CS_NET 0xC003 */ if (xrdp_sec_process_mcs_data_channels(self, s) != 0) { return 1; } break; - case SEC_TAG_CLI_4: + case SEC_TAG_CLI_4: /* CS_CLUSTER 0xC004 */ break; - case SEC_TAG_CLI_MONITOR: + case SEC_TAG_CLI_MONITOR: /* CS_MONITOR 0xC005 */ if (xrdp_sec_process_mcs_data_monitors(self, s) != 0) { return 1; } break; + /* CS_MCS_MSGCHANNEL 0xC006 + CS_MONITOR_EX 0xC008 + CS_MULTITRANSPORT 0xC00A + SC_CORE 0x0C01 + SC_SECURITY 0x0C02 + SC_NET 0x0C03 + SC_MCS_MSGCHANNEL 0x0C04 + SC_MULTITRANSPORT 0x0C08 */ default: - g_writeln("error unknown xrdp_sec_process_mcs_data tag %d size %d", - tag, size); + LLOGLN(0, ("error unknown xrdp_sec_process_mcs_data " + "tag 0x%4.4x size %d", tag, size)); break; } s->p = hold_p + size; } + if (self->rdp_layer->client_info.max_bpp > 0) + { + if (self->rdp_layer->client_info.bpp > + self->rdp_layer->client_info.max_bpp) + { + LLOGLN(0, ("xrdp_rdp_parse_client_mcs_data: client asked " + "for %dbpp connection but configuration is limited " + "to %dbpp", self->rdp_layer->client_info.bpp, + self->rdp_layer->client_info.max_bpp)); + self->rdp_layer->client_info.bpp = + self->rdp_layer->client_info.max_bpp; + } + } + /* set p to beginning */ s->p = s->data; return 0; @@ -1224,9 +1720,8 @@ xrdp_sec_out_mcs_data(struct xrdp_sec *self) out_uint16_le(s, SEC_TAG_SRV_CRYPT); out_uint16_le(s, 0x00ec); /* len is 236 */ - out_uint32_le(s, self->rc4_key_size); /* key len 1 = 40 bit 2 = 128 bit */ - out_uint32_le(s, self->crypt_level); /* crypt level 1 = low 2 = medium */ - /* 3 = high */ + out_uint32_le(s, self->crypt_method); + out_uint32_le(s, self->crypt_level); out_uint32_le(s, 32); /* 32 bytes random len */ out_uint32_le(s, 0xb8); /* 184 bytes rsa info(certificate) len */ out_uint8a(s, self->server_random, 32); @@ -1328,8 +1823,8 @@ xrdp_sec_incoming(struct xrdp_sec *self) char *value = NULL; char key_file[256]; + LLOGLN(10, ("xrdp_sec_incoming:")); g_memset(key_file, 0, sizeof(char) * 256); - DEBUG((" in xrdp_sec_incoming")); g_random(self->server_random, 32); items = list_create(); @@ -1392,6 +1887,7 @@ xrdp_sec_incoming(struct xrdp_sec *self) { return 1; } + LLOGLN(10, ("xrdp_sec_incoming: out")); return 0; } diff --git a/libxrdp/xrdp_tcp.c b/libxrdp/xrdp_tcp.c deleted file mode 100644 index 384556ba..00000000 --- a/libxrdp/xrdp_tcp.c +++ /dev/null @@ -1,89 +0,0 @@ -/** - * xrdp: A Remote Desktop Protocol server. - * - * Copyright (C) Jay Sorg 2004-2013 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * tcp layer - */ - -#include "libxrdp.h" - -/*****************************************************************************/ -struct xrdp_tcp *APP_CC -xrdp_tcp_create(struct xrdp_iso *owner, struct trans *trans) -{ - struct xrdp_tcp *self; - - DEBUG((" in xrdp_tcp_create")); - self = (struct xrdp_tcp *)g_malloc(sizeof(struct xrdp_tcp), 1); - self->iso_layer = owner; - self->trans = trans; - DEBUG((" out xrdp_tcp_create")); - return self; -} - -/*****************************************************************************/ -void APP_CC -xrdp_tcp_delete(struct xrdp_tcp *self) -{ - g_free(self); -} - -/*****************************************************************************/ -/* get out stream ready for data */ -/* returns error */ -int APP_CC -xrdp_tcp_init(struct xrdp_tcp *self, struct stream *s) -{ - init_stream(s, 8192); - return 0; -} - -/*****************************************************************************/ -/* returns error */ -int APP_CC -xrdp_tcp_recv(struct xrdp_tcp *self, struct stream *s, int len) -{ - DEBUG((" in xrdp_tcp_recv, gota get %d bytes", len)); - init_stream(s, len); - - if (trans_force_read_s(self->trans, s, len) != 0) - { - DEBUG((" error in trans_force_read_s")); - return 1; - } - - DEBUG((" out xrdp_tcp_recv")); - return 0; -} - -/*****************************************************************************/ -/* returns error */ -int APP_CC -xrdp_tcp_send(struct xrdp_tcp *self, struct stream *s) -{ - int len; - len = s->end - s->data; - DEBUG((" in xrdp_tcp_send, gota send %d bytes", len)); - - if (trans_force_write_s(self->trans, s) != 0) - { - DEBUG((" error in trans_force_write_s")); - return 1; - } - - DEBUG((" out xrdp_tcp_send, sent %d bytes ok", len)); - return 0; -} diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index 9c79f670..a89957ba 100644 --- a/sesman/chansrv/chansrv.c +++ b/sesman/chansrv/chansrv.c @@ -547,7 +547,7 @@ process_message_channel_setup(struct stream *s) g_rdpdr_chan_id = ci->id; } /* disabled for now */ - else if (g_strcasecmp(ci->name, "notrail") == 0) + else if (g_strcasecmp(ci->name, "rail") == 0) { g_rail_index = g_num_chan_items; g_rail_chan_id = ci->id; diff --git a/sesman/chansrv/rail.c b/sesman/chansrv/rail.c index fb1075c6..4bfeef7e 100644 --- a/sesman/chansrv/rail.c +++ b/sesman/chansrv/rail.c @@ -230,7 +230,7 @@ static struct rail_window_data* APP_CC rail_get_window_data_safe(Window window) { struct rail_window_data* rv; - + rv = rail_get_window_data(window); if (rv != 0) { @@ -330,20 +330,43 @@ rail_is_another_wm_running(void) /*****************************************************************************/ int APP_CC rail_init(void) +{ + LOG(10, ("chansrv::rail_init:")); + xcommon_init(); + + return 0; +} + +/*****************************************************************************/ +int APP_CC +rail_deinit(void) +{ + if (g_rail_up) + { + list_delete(g_window_list); + g_window_list = 0; + /* no longer window manager */ + XSelectInput(g_display, g_root_window, 0); + g_rail_up = 0; + } + + return 0; +} + +int APP_CC +rail_startup() { int dummy; int ver_maj; int ver_min; Status st; - - LOG(10, ("chansrv::rail_init:")); - xcommon_init(); if (rail_is_another_wm_running()) { log_message(LOG_LEVEL_ERROR, "rail_init: another window manager " "is running"); } + list_delete(g_window_list); g_window_list = list_create(); rail_send_init(); @@ -372,21 +395,6 @@ rail_init(void) g_default_cursor = XCreateFontCursor(g_display, XC_left_ptr); XDefineCursor(g_display, g_root_window, g_default_cursor); } - return 0; -} - -/*****************************************************************************/ -int APP_CC -rail_deinit(void) -{ - if (g_rail_up) - { - list_delete(g_window_list); - g_window_list = 0; - /* no longer window manager */ - XSelectInput(g_display, g_root_window, 0); - g_rail_up = 0; - } return 0; } @@ -454,6 +462,8 @@ rail_process_exec(struct stream *s, int size) if (g_strlen(ExeOrFile) > 0) { + rail_startup(); + LOG(10, ("rail_process_exec: pre")); /* ask main thread to fork */ tc_mutex_lock(g_exec_mutex); @@ -481,13 +491,13 @@ rail_win_popdown(void) Window p; Window* children; XWindowAttributes window_attributes; - + /* * Check the tree of current existing X windows and dismiss * the managed rail popups by simulating a esc key, so * that the requested window can be closed properly. */ - + XQueryTree(g_display, g_root_window, &r, &p, &children, &nchild); for (i = nchild - 1; i >= 0; i--) { @@ -501,7 +511,7 @@ rail_win_popdown(void) rv = 1; } } - + XFree(children); return rv; } @@ -511,11 +521,11 @@ static int APP_CC rail_close_window(int window_id) { XEvent ce; - + LOG(0, ("chansrv::rail_close_window:")); - + rail_win_popdown(); - + g_memset(&ce, 0, sizeof(ce)); ce.xclient.type = ClientMessage; ce.xclient.message_type = g_wm_protocols_atom; @@ -562,13 +572,13 @@ rail_process_activate(struct stream *s, int size) window_id)); return 0; } - + g_focus_counter++; g_got_focus = enabled; LOG(10, (" window_id 0x%8.8x enabled %d", window_id, enabled)); XGetWindowAttributes(g_display, window_id, &window_attributes); - + if (enabled) { if (g_focus_win == window_id) @@ -619,7 +629,7 @@ rail_restore_windows(void) Window r; Window p; Window* children; - + XQueryTree(g_display, g_root_window, &r, &p, &children, &nchild); for (i = 0; i < nchild; i++) { @@ -671,7 +681,7 @@ rail_get_property(Display* display, Window target, Atom type, Atom property, int size; unsigned long nitems, bytes_left; char* prop_name; - + int ret = XGetWindowProperty(display, target, property, 0l, 1l, False, type, &atom_return, &size, @@ -683,7 +693,7 @@ rail_get_property(Display* display, Window target, Atom type, Atom property, XFree(prop_name); return 1; } - + if (bytes_left != 0) { XFree(*data); @@ -697,7 +707,7 @@ rail_get_property(Display* display, Window target, Atom type, Atom property, return 1; } } - + *count = nitems; return 0; } @@ -709,18 +719,18 @@ rail_win_get_state(Window win) unsigned long nitems = 0; int rv = -1; char* data = 0; - + rail_get_property(g_display, win, g_wm_state, g_wm_state, (unsigned char **)&data, &nitems); - + if (data || nitems > 0) { rv = *(unsigned long *)data; XFree(data); LOG(10, (" rail_win_get_state: %d", rv)); } - + return rv; } @@ -730,7 +740,7 @@ rail_win_set_state(Window win, unsigned long state) { int old_state; unsigned long data[2] = { state, None }; - + LOG(10, (" rail_win_set_state: %d", state)); /* check whether WM_STATE exists */ old_state = rail_win_get_state(win); @@ -756,7 +766,7 @@ rail_win_get_text(Window win, char **data) int ret = 0; int i = 0; unsigned long nitems = 0; - + ret = rail_get_property(g_display, win, g_utf8_string, g_net_wm_name, (unsigned char **)data, &nitems); if (ret != 0) @@ -764,7 +774,7 @@ rail_win_get_text(Window win, char **data) /* _NET_WM_NAME isn't set, use WM_NAME (XFetchName) instead */ XFetchName(g_display, win, data); } - + if (data) { char *ptr = *data; @@ -776,7 +786,7 @@ rail_win_get_text(Window win, char **data) } } } - + return i; } @@ -787,7 +797,7 @@ rail_minmax_window(int window_id, int max) LOG(10, ("chansrv::rail_minmax_window 0x%8.8x:", window_id)); if (max) { - + } else { XUnmapWindow(g_display, window_id); /* change window state to IconicState (3) */ @@ -804,7 +814,7 @@ static int APP_CC rail_restore_window(int window_id) { XWindowAttributes window_attributes; - + LOG(10, ("chansrv::rail_restore_window 0x%8.8x:", window_id)); XGetWindowAttributes(g_display, window_id, &window_attributes); if (window_attributes.map_state != IsViewable) @@ -815,7 +825,7 @@ rail_restore_window(int window_id) XRaiseWindow(g_display, window_id); LOG(10, ("chansrv::rail_process_activate: calling XSetInputFocus 0x%8.8x", window_id)); XSetInputFocus(g_display, window_id, RevertToParent, CurrentTime); - + return 0; } @@ -838,7 +848,7 @@ rail_process_system_command(struct stream *s, int size) window_id)); return 0; } - + switch (command) { case SC_SIZE: @@ -1196,7 +1206,7 @@ rail_win_send_text(Window win) int flags; int crc; struct rail_window_data* rwd; - + len = rail_win_get_text(win, &data); rwd = rail_get_window_data_safe(win); if (rwd != 0) @@ -1254,7 +1264,7 @@ static int APP_CC rail_destroy_window(Window window_id) { struct stream *s; - + LOG(10, ("chansrv::rail_destroy_window 0x%8.8x", window_id)); make_stream(s); init_stream(s, 1024); @@ -1348,7 +1358,7 @@ rail_create_window(Window window_id, Window owner_id) title_size = rail_win_get_text(window_id, &title_bytes); XGetTransientForHint(g_display, window_id, &transient_for); - + if (attributes.override_redirect) { style = RAIL_STYLE_TOOLTIP; @@ -1368,7 +1378,7 @@ rail_create_window(Window window_id, Window owner_id) make_stream(s); init_stream(s, 1024); - + out_uint32_le(s, 2); /* create_window */ out_uint32_le(s, window_id); /* window_id */ out_uint32_le(s, owner_id); /* owner_window_id */ @@ -1459,9 +1469,9 @@ rail_configure_request_window(XConfigureRequestEvent* config) int mask; int resized = 0; struct rail_window_data* rwd; - + struct stream* s; - + window_id = config->window; mask = config->value_mask; LOG(10, ("chansrv::rail_configure_request_window: mask %d", mask)); @@ -1580,13 +1590,13 @@ rail_configure_request_window(XConfigureRequestEvent* config) XFree(rwd); return 0; } - + LOG(10, ("chansrv::rail_configure_request_window: 0x%8.8x", window_id)); - - + + LOG(10, (" x %d y %d width %d height %d border_width %d", config->x, config->y, config->width, config->height, config->border_width)); - + index = list_index_of(g_window_list, window_id); if (index == -1) { @@ -1594,15 +1604,15 @@ rail_configure_request_window(XConfigureRequestEvent* config) LOG(0, ("chansrv::rail_configure_request_window: window not mapped")); return 0; } - + flags = WINDOW_ORDER_TYPE_WINDOW; - + make_stream(s); init_stream(s, 1024); - + out_uint32_le(s, 10); /* configure_window */ out_uint32_le(s, window_id); /* window_id */ - + out_uint32_le(s, 0); /* client_offset_x */ out_uint32_le(s, 0); /* client_offset_y */ flags |= WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET; @@ -1643,7 +1653,7 @@ rail_configure_request_window(XConfigureRequestEvent* config) } flags |= WINDOW_ORDER_FIELD_VISIBILITY; out_uint32_le(s, flags); /*flags*/ - + s_mark_end(s); send_rail_drawing_orders(s->data, (int)(s->end - s->data)); free_stream(s); @@ -1661,32 +1671,32 @@ rail_configure_window(XConfigureEvent *config) int flags; int index; int window_id; - + struct stream* s; - + window_id = config->window; - + LOG(10, ("chansrv::rail_configure_window 0x%8.8x", window_id)); - - + + LOG(10, (" x %d y %d width %d height %d border_width %d", config->x, config->y, config->width, config->height, config->border_width)); - + index = list_index_of(g_window_list, window_id); if (index == -1) { /* window isn't mapped yet */ return 0; } - + flags = WINDOW_ORDER_TYPE_WINDOW; - + make_stream(s); init_stream(s, 1024); - + out_uint32_le(s, 10); /* configure_window */ out_uint32_le(s, window_id); /* window_id */ - + out_uint32_le(s, 0); /* client_offset_x */ out_uint32_le(s, 0); /* client_offset_y */ flags |= WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET; @@ -1727,7 +1737,7 @@ rail_configure_window(XConfigureEvent *config) } flags |= WINDOW_ORDER_FIELD_VISIBILITY; out_uint32_le(s, flags); /*flags*/ - + s_mark_end(s); send_rail_drawing_orders(s->data, (int)(s->end - s->data)); free_stream(s); @@ -1772,7 +1782,7 @@ rail_xevent(void *xevent) LOG(10, (" got PropertyNotify window_id 0x%8.8x %s state new %d", lxevent->xproperty.window, prop_name, lxevent->xproperty.state == PropertyNewValue)); - + if (list_index_of(g_window_list, lxevent->xproperty.window) < 0) { break; @@ -1790,7 +1800,7 @@ rail_xevent(void *xevent) } XFree(prop_name); break; - + case ConfigureRequest: LOG(10, (" got ConfigureRequest window_id 0x%8.8x", lxevent->xconfigurerequest.window)); g_memset(&xwc, 0, sizeof(xwc)); @@ -1833,7 +1843,7 @@ rail_xevent(void *xevent) } rv = 0; break; - + case MapRequest: LOG(10, (" got MapRequest window 0x%8.8x", lxevent->xmaprequest.window)); XMapWindow(g_display, lxevent->xmaprequest.window); @@ -1916,7 +1926,7 @@ rail_xevent(void *xevent) case FocusOut: LOG(10, (" got FocusOut")); break; - + case ButtonPress: LOG(10, (" got ButtonPress")); break; @@ -1951,7 +1961,7 @@ rail_xevent(void *xevent) } rv = 0; break; - + default: if (g_xrr_event_base > 0) { diff --git a/sesman/chansrv/sound.c b/sesman/chansrv/sound.c index 5669aea8..eb299ecc 100644 --- a/sesman/chansrv/sound.c +++ b/sesman/chansrv/sound.c @@ -54,6 +54,7 @@ static struct stream *g_stream_inp = NULL; char g_buffer[BBUF_SIZE]; int g_buf_index = 0; int g_sent_time[256]; +int g_sent_flag[256]; #if defined(XRDP_SIMPLESOUND) static void *DEFAULT_CC @@ -367,6 +368,16 @@ sound_send_wave_data_chunk(char *data, int data_bytes) return 0; } + if (g_sent_flag[(g_cBlockNo + 1) & 0xff] & 1) + { + LOG(10, ("sound_send_wave_data_chunk: no room")); + return 0; + } + else + { + LOG(10, ("sound_send_wave_data_chunk: got room")); + } + /* part one of 2 PDU wave info */ LOG(10, ("sound_send_wave_data_chunk: sending %d bytes", data_bytes)); @@ -382,6 +393,7 @@ sound_send_wave_data_chunk(char *data, int data_bytes) g_cBlockNo++; out_uint8(s, g_cBlockNo); g_sent_time[g_cBlockNo & 0xff] = time; + g_sent_flag[g_cBlockNo & 0xff] = 1; LOG(10, ("sound_send_wave_data_chunk: sending time %d, g_cBlockNo %d", time & 0xffff, g_cBlockNo & 0xff)); @@ -498,7 +510,8 @@ sound_process_wave_confirm(struct stream *s, int size) time = g_time2(); in_uint16_le(s, wTimeStamp); in_uint8(s, cConfirmedBlockNo); - time_diff = time - g_sent_time[cConfirmedBlockNo]; + time_diff = time - g_sent_time[cConfirmedBlockNo & 0xff]; + g_sent_flag[cConfirmedBlockNo & 0xff] &= ~1; LOG(10, ("sound_process_wave_confirm: wTimeStamp %d, " "cConfirmedBlockNo %d time diff %d", @@ -637,6 +650,7 @@ sound_init(void) LOG(0, ("sound_init:")); + g_memset(g_sent_flag, 0, sizeof(g_sent_flag)); #ifdef XRDP_LOAD_PULSE_MODULES if (load_pulse_modules()) diff --git a/sesman/session.c b/sesman/session.c index a5932736..32b2e6be 100644 --- a/sesman/session.c +++ b/sesman/session.c @@ -551,6 +551,7 @@ session_start_fork(int width, int height, int bpp, char *username, { g_waitpid(pampid); auth_stop_session(data); + g_deinit(); g_exit(0); } } diff --git a/tests/tcp_proxy/Makefile b/tests/tcp_proxy/Makefile index d19b4818..8f5821d3 100644 --- a/tests/tcp_proxy/Makefile +++ b/tests/tcp_proxy/Makefile @@ -1,6 +1,7 @@ -CFLAGS = -O2 -Wall -I../../common -LDFLAGS = -Wl -OBJS = main.o ../../common/os_calls.o + +CFLAGS = -O2 -Wall +LDFLAGS = +OBJS = main.o LIBS = -ldl all: tcp_proxy diff --git a/tests/tcp_proxy/main.c b/tests/tcp_proxy/main.c index 53458a57..2d283ed9 100644 --- a/tests/tcp_proxy/main.c +++ b/tests/tcp_proxy/main.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,20 @@ * limitations under the License. */ -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include int g_loc_io_count = 0; // bytes read from local port int g_rem_io_count = 0; // bytes read from remote port @@ -24,6 +37,394 @@ int g_rem_io_count = 0; // bytes read from remote port static int g_terminated = 0; static char g_buf[1024 * 32]; +#define DEFAULT_CC +#define APP_CC + +typedef unsigned short tui16; + +/*****************************************************************************/ +static void APP_CC +g_memset(void *ptr, int val, int size) +{ + memset(ptr, val, size); +} + +/*****************************************************************************/ +static void DEFAULT_CC +g_printf(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vfprintf(stdout, format, ap); + va_end(ap); +} + +/*****************************************************************************/ +static void DEFAULT_CC +g_writeln(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vfprintf(stdout, format, ap); + va_end(ap); + g_printf("\n"); +} + +/*****************************************************************************/ +static void APP_CC +g_hexdump(char *p, int len) +{ + unsigned char *line; + int i; + int thisline; + int offset; + + line = (unsigned char *)p; + offset = 0; + + while (offset < len) + { + g_printf("%04x ", offset); + thisline = len - offset; + + if (thisline > 16) + { + thisline = 16; + } + + for (i = 0; i < thisline; i++) + { + g_printf("%02x ", line[i]); + } + + for (; i < 16; i++) + { + g_printf(" "); + } + + for (i = 0; i < thisline; i++) + { + g_printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.'); + } + + g_writeln(""); + offset += thisline; + line += thisline; + } +} + +/*****************************************************************************/ +static int APP_CC +g_tcp_socket(void) +{ + int rv; + int option_value; + unsigned int option_len; + + rv = (int)socket(AF_INET, SOCK_STREAM, 0); + if (rv < 0) + { + return -1; + } + option_len = sizeof(option_value); + if (getsockopt(rv, SOL_SOCKET, SO_REUSEADDR, (char *)&option_value, + &option_len) == 0) + { + if (option_value == 0) + { + option_value = 1; + option_len = sizeof(option_value); + setsockopt(rv, SOL_SOCKET, SO_REUSEADDR, (char *)&option_value, + option_len); + } + } + + option_len = sizeof(option_value); + + if (getsockopt(rv, SOL_SOCKET, SO_SNDBUF, (char *)&option_value, + &option_len) == 0) + { + if (option_value < (1024 * 32)) + { + option_value = 1024 * 32; + option_len = sizeof(option_value); + setsockopt(rv, SOL_SOCKET, SO_SNDBUF, (char *)&option_value, + option_len); + } + } + + return rv; +} + +/*****************************************************************************/ +static int APP_CC +g_tcp_set_non_blocking(int sck) +{ + unsigned long i; + + i = fcntl(sck, F_GETFL); + i = i | O_NONBLOCK; + fcntl(sck, F_SETFL, i); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +g_tcp_bind(int sck, const char* port) +{ + struct sockaddr_in s; + + memset(&s, 0, sizeof(struct sockaddr_in)); + s.sin_family = AF_INET; + s.sin_port = htons((tui16)atoi(port)); + s.sin_addr.s_addr = INADDR_ANY; + return bind(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in)); +} + +/*****************************************************************************/ +static int APP_CC +g_tcp_listen(int sck) +{ + return listen(sck, 2); +} + +/*****************************************************************************/ +static int APP_CC +g_tcp_select(int sck1, int sck2) +{ + fd_set rfds; + struct timeval time; + int max = 0; + int rv = 0; + + g_memset(&rfds, 0, sizeof(fd_set)); + g_memset(&time, 0, sizeof(struct timeval)); + + time.tv_sec = 0; + time.tv_usec = 0; + FD_ZERO(&rfds); + + if (sck1 > 0) + { + FD_SET(((unsigned int)sck1), &rfds); + } + + if (sck2 > 0) + { + FD_SET(((unsigned int)sck2), &rfds); + } + + max = sck1; + + if (sck2 > max) + { + max = sck2; + } + + rv = select(max + 1, &rfds, 0, 0, &time); + + if (rv > 0) + { + rv = 0; + + if (FD_ISSET(((unsigned int)sck1), &rfds)) + { + rv = rv | 1; + } + + if (FD_ISSET(((unsigned int)sck2), &rfds)) + { + rv = rv | 2; + } + } + else + { + rv = 0; + } + + return rv; +} + +/*****************************************************************************/ +static int APP_CC +g_tcp_recv(int sck, void *ptr, int len, int flags) +{ + return recv(sck, ptr, len, flags); +} + +/*****************************************************************************/ +static void APP_CC +g_tcp_close(int sck) +{ + if (sck == 0) + { + return; + } + close(sck); +} + +/*****************************************************************************/ +static int APP_CC +g_tcp_send(int sck, const void *ptr, int len, int flags) +{ + return send(sck, ptr, len, flags); +} + +/*****************************************************************************/ +void APP_CC +g_sleep(int msecs) +{ + usleep(msecs * 1000); +} + +/*****************************************************************************/ +static int APP_CC +g_tcp_last_error_would_block(int sck) +{ + return (errno == EWOULDBLOCK) || (errno == EAGAIN) || (errno == EINPROGRESS); +} + +/*****************************************************************************/ +static int APP_CC +g_tcp_accept(int sck) +{ + int ret ; + struct sockaddr_in s; + unsigned int i; + + i = sizeof(struct sockaddr_in); + memset(&s, 0, i); + ret = accept(sck, (struct sockaddr *)&s, &i); + return ret ; +} + +/*****************************************************************************/ +static int APP_CC +g_tcp_connect(int sck, const char* address, const char* port) +{ + struct sockaddr_in s; + struct hostent* h; + + g_memset(&s, 0, sizeof(struct sockaddr_in)); + s.sin_family = AF_INET; + s.sin_port = htons((tui16)atoi(port)); + s.sin_addr.s_addr = inet_addr(address); + if (s.sin_addr.s_addr == INADDR_NONE) + { + h = gethostbyname(address); + if (h != 0) + { + if (h->h_name != 0) + { + if (h->h_addr_list != 0) + { + if ((*(h->h_addr_list)) != 0) + { + s.sin_addr.s_addr = *((int*)(*(h->h_addr_list))); + } + } + } + } + } + return connect(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in)); +} + +/*****************************************************************************/ +static int APP_CC +g_tcp_socket_ok(int sck) +{ + int opt; + unsigned int opt_len; + + opt_len = sizeof(opt); + + if (getsockopt(sck, SOL_SOCKET, SO_ERROR, (char *)(&opt), &opt_len) == 0) + { + if (opt == 0) + { + return 1; + } + } + + return 0; +} + +/*****************************************************************************/ +static void APP_CC +g_init(const char *app_name) +{ + setlocale(LC_CTYPE, ""); +} + +/*****************************************************************************/ +static void APP_CC +g_deinit(void) +{ +} + +/*****************************************************************************/ +static int APP_CC +g_tcp_can_send(int sck, int millis) +{ + fd_set wfds; + struct timeval time; + int rv; + + time.tv_sec = millis / 1000; + time.tv_usec = (millis * 1000) % 1000000; + FD_ZERO(&wfds); + + if (sck > 0) + { + FD_SET(((unsigned int)sck), &wfds); + rv = select(sck + 1, 0, &wfds, 0, &time); + + if (rv > 0) + { + return g_tcp_socket_ok(sck); + } + } + + return 0; +} + +/*****************************************************************************/ +static void APP_CC +g_signal_user_interrupt(void (*func)(int)) +{ + signal(SIGINT, func); +} + +/*****************************************************************************/ +static void APP_CC +g_signal_kill(void (*func)(int)) +{ + signal(SIGKILL, func); +} + +/*****************************************************************************/ +static void APP_CC +g_signal_terminate(void (*func)(int)) +{ + signal(SIGTERM, func); +} + +/*****************************************************************************/ +static void APP_CC +g_signal_usr1(void (*func)(int)) +{ + signal(SIGUSR1, func); +} + +/*****************************************************************************/ +static int APP_CC +g_strcasecmp(const char *c1, const char *c2) +{ + return strcasecmp(c1, c2); +} + /*****************************************************************************/ static int main_loop(char *local_port, char *remote_ip, char *remote_port, int hexdump) diff --git a/xorg/X11R7.6/rdp/rdpmain.c b/xorg/X11R7.6/rdp/rdpmain.c index c68700fc..884b8a3a 100644 --- a/xorg/X11R7.6/rdp/rdpmain.c +++ b/xorg/X11R7.6/rdp/rdpmain.c @@ -32,6 +32,27 @@ Sets up the functions #define DEBUG_OUT(arg) ErrorF arg #endif +#ifndef XRDP_DISABLE_LINUX_ABSTRACT +#ifdef __linux__ +#define XRDP_DISABLE_LINUX_ABSTRACT 1 +#else +#define XRDP_DISABLE_LINUX_ABSTRACT 0 +#endif +#endif + +#if XRDP_DISABLE_LINUX_ABSTRACT +/* because including in problematic + * we dup a small struct + * we need to set flags to zero to turn off abstract sockets */ +struct _MyXtransport +{ + char *TransName; + int flags; +}; +/* in xtrans-1.2.6/Xtranssock.c */ +extern struct _MyXtransport _XSERVTransSocketLocalFuncs; +#endif + rdpScreenInfoRec g_rdpScreen; /* the one screen */ ScreenPtr g_pScreen = 0; @@ -233,6 +254,16 @@ rdpDestroyColormap(ColormapPtr pColormap) } #endif +/******************************************************************************/ +void +rdpSetUDSRights(void) +{ + char unixSocketName[128]; + + sprintf(unixSocketName, "/tmp/.X11-unix/X%s", display); + chmod(unixSocketName, 0700); +} + /******************************************************************************/ /* returns boolean, true if everything is ok */ static Bool @@ -548,6 +579,8 @@ rdpScreenInit(int index, ScreenPtr pScreen, int argc, char **argv) rdpGlyphInit(); //rdpXvInit(pScreen); + + rdpSetUDSRights(); ErrorF("rdpScreenInit: ret %d\n", ret); @@ -620,6 +653,11 @@ ddxProcessArgument(int argc, char **argv, int i) void OsVendorInit(void) { +#if XRDP_DISABLE_LINUX_ABSTRACT + /* turn off the Linux abstract unix doamin sockets TRANS_ABSTRACT */ + /* TRANS_NOLISTEN = 1 << 3 */ + _XSERVTransSocketLocalFuncs.flags = 0; +#endif } /******************************************************************************/ diff --git a/xorg/server/module/Makefile b/xorg/server/module/Makefile index 91f38679..9003de4d 100644 --- a/xorg/server/module/Makefile +++ b/xorg/server/module/Makefile @@ -5,7 +5,8 @@ rdpPolyRectangle.o rdpPolyArc.o rdpFillPolygon.o rdpPolyFillRect.o \ rdpPolyFillArc.o rdpPolyText8.o rdpPolyText16.o rdpImageText8.o \ rdpImageText16.o rdpImageGlyphBlt.o rdpPolyGlyphBlt.o rdpPushPixels.o \ rdpCursor.o rdpMain.o rdpRandR.o rdpMisc.o rdpReg.o \ -rdpComposite.o rdpGlyphs.o rdpPixmap.o rdpInput.o rdpClientCon.o +rdpComposite.o rdpGlyphs.o rdpPixmap.o rdpInput.o rdpClientCon.o rdpCapture.o \ +rdpTrapezoids.o CFLAGS = -g -O2 -Wall -fPIC -I/usr/include/xorg -I/usr/include/pixman-1 \ -I../../../common diff --git a/xorg/server/module/rdp.h b/xorg/server/module/rdp.h index b912b4b8..ba1bcfd0 100644 --- a/xorg/server/module/rdp.h +++ b/xorg/server/module/rdp.h @@ -30,6 +30,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdpPri.h" +/* PIXMAN_a8r8g8b8 */ +#define XRDP_a8r8g8b8 \ +((32 << 24) | (2 << 16) | (8 << 12) | (8 << 8) | (8 << 4) | 8) + #define PixelDPI 100 #define PixelToMM(_size) (((_size) * 254 + (PixelDPI) * 5) / ((PixelDPI) * 10)) @@ -38,6 +42,30 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define RDPCLAMP(_val, _lo, _hi) \ (_val) < (_lo) ? (_lo) : (_val) > (_hi) ? (_hi) : (_val) +#define XRDP_CD_NODRAW 0 +#define XRDP_CD_NOCLIP 1 +#define XRDP_CD_CLIP 2 + +#if 0 +#define RegionCopy DONOTUSE +#define RegionTranslate DONOTUSE +#define RegionNotEmpty DONOTUSE +#define RegionIntersect DONOTUSE +#define RegionContainsRect DONOTUSE +#define RegionInit DONOTUSE +#define RegionUninit DONOTUSE +#define RegionFromRects DONOTUSE +#define RegionDestroy DONOTUSE +#define RegionCreate DONOTUSE +#define RegionUnion DONOTUSE +#define RegionSubtract DONOTUSE +#define RegionInverse DONOTUSE +#define RegionExtents DONOTUSE +#define RegionReset DONOTUSE +#define RegionBreak DONOTUSE +#define RegionUnionRect DONOTUSE +#endif + struct image_data { int width; @@ -101,6 +129,34 @@ typedef struct _rdpPixmapRec * rdpPixmapPtr; #define GETPIXPRIV(_dev, _pPixmap) (rdpPixmapPtr) \ rdpGetPixmapPrivate(&((_pPixmap)->devPrivates), (_dev)->privateKeyRecPixmap) +struct _rdpCounts +{ + CARD32 rdpFillSpansCallCount; /* 1 */ + CARD32 rdpSetSpansCallCount; + CARD32 rdpPutImageCallCount; + CARD32 rdpCopyAreaCallCount; + CARD32 rdpCopyPlaneCallCount; + CARD32 rdpPolyPointCallCount; + CARD32 rdpPolylinesCallCount; + CARD32 rdpPolySegmentCallCount; + CARD32 rdpPolyRectangleCallCount; + CARD32 rdpPolyArcCallCount; /* 10 */ + CARD32 rdpFillPolygonCallCount; + CARD32 rdpPolyFillRectCallCount; + CARD32 rdpPolyFillArcCallCount; + CARD32 rdpPolyText8CallCount; + CARD32 rdpPolyText16CallCount; + CARD32 rdpImageText8CallCount; + CARD32 rdpImageText16CallCount; + CARD32 rdpImageGlyphBltCallCount; + CARD32 rdpPolyGlyphBltCallCount; + CARD32 rdpPushPixelsCallCount; /* 20 */ + CARD32 rdpCompositeCallCount; + CARD32 rdpCopyWindowCallCount; /* 22 */ + CARD32 rdpTrapezoidsCallCount; + CARD32 callCount[64 - 23]; +}; + /* move this to common header */ struct _rdpRec { @@ -126,6 +182,7 @@ struct _rdpRec CloseScreenProcPtr CloseScreen; CompositeProcPtr Composite; GlyphsProcPtr Glyphs; + TrapezoidsProcPtr Trapezoids; /* keyboard and mouse */ miPointerScreenFuncPtr pCursorFuncs; @@ -169,6 +226,8 @@ struct _rdpRec int conNumber; + struct _rdpCounts counts; + }; typedef struct _rdpRec rdpRec; typedef struct _rdpRec * rdpPtr; diff --git a/xorg/server/module/rdpCapture.c b/xorg/server/module/rdpCapture.c new file mode 100644 index 00000000..8819713a --- /dev/null +++ b/xorg/server/module/rdpCapture.c @@ -0,0 +1,154 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Laxmikant Rashinkar 2014 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Routines to copy regions from framebuffer to shared memory + */ + +#include +#include +#include + +/* this should be before all X11 .h files */ +#include + +/* all driver need this */ +#include +#include + +#include "rdp.h" +#include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" + +#define LOG_LEVEL 1 +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +/******************************************************************************/ +static Bool +rdpCapture0(RegionPtr in_reg, RegionPtr out_reg, + void *src, int src_width, int src_height, + int src_stride, int src_format, + void *dst, int dst_width, int dst_height, + int dst_stride, int dst_format, int max_rects) +{ + BoxPtr prects; + BoxRec rect; + RegionRec reg; + char *src_rect; + char *dst_rect; + int num_regions; + int bytespp; + int width; + int height; + int src_offset; + int dst_offset; + int bytes; + int i; + int j; + Bool rv; + + LLOGLN(10, ("rdpCapture0:")); + + rv = TRUE; + + rect.x1 = 0; + rect.y1 = 0; + rect.x2 = min(dst_width, src_width); + rect.y2 = min(dst_height, src_height); + rdpRegionInit(®, &rect, 0); + rdpRegionIntersect(®, in_reg, ®); + + num_regions = REGION_NUM_RECTS(®); + + if (num_regions > max_rects) + { + num_regions = 1; + prects = rdpRegionExtents(®); + rdpRegionUninit(out_reg); + rdpRegionInit(out_reg, prects, 0); + } + else + { + prects = REGION_RECTS(®); + rdpRegionCopy(out_reg, ®); + } + + if ((src_format == XRDP_a8r8g8b8) && (dst_format == XRDP_a8r8g8b8)) + { + bytespp = 4; + + for (i = 0; i < num_regions; i++) + { + /* get rect to copy */ + rect = prects[i]; + + /* get rect dimensions */ + width = rect.x2 - rect.x1; + height = rect.y2 - rect.y1; + + /* point to start of each rect in respective memory */ + src_offset = rect.y1 * src_stride + rect.x1 * bytespp; + dst_offset = rect.y1 * dst_stride + rect.x1 * bytespp; + src_rect = src + src_offset; + dst_rect = dst + dst_offset; + + /* bytes per line */ + bytes = width * bytespp; + + /* copy one line at a time */ + for (j = 0; j < height; j++) + { + memcpy(dst_rect, src_rect, bytes); + src_rect += src_stride; + dst_rect += dst_stride; + } + } + } + else + { + LLOGLN(0, ("rdpCapture0: unimp color conversion")); + } + rdpRegionUninit(®); + return rv; +} + +/** + * Copy an array of rectangles from one memory area to another + *****************************************************************************/ +Bool +rdpCapture(RegionPtr in_reg, RegionPtr out_reg, + void *src, int src_width, int src_height, + int src_stride, int src_format, + void *dst, int dst_width, int dst_height, + int dst_stride, int dst_format, int mode) +{ + LLOGLN(10, ("rdpCapture:")); + switch (mode) + { + case 0: + return rdpCapture0(in_reg, out_reg, + src, src_width, src_height, + src_stride, src_format, + dst, dst_width, dst_height, + dst_stride, dst_format, 15); + default: + LLOGLN(0, ("rdpCapture: unimp mode")); + break; + } + return TRUE; +} diff --git a/xorg/server/module/rdpCapture.h b/xorg/server/module/rdpCapture.h new file mode 100644 index 00000000..f92508c4 --- /dev/null +++ b/xorg/server/module/rdpCapture.h @@ -0,0 +1,27 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Laxmikant Rashinkar 2014 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Routines to copy regions from framebuffer to shared memory + */ + +Bool +rdpCapture(RegionPtr in_reg, RegionPtr out_reg, + void *src, int src_width, int src_height, + int src_stride, int src_format, + void *dst, int dst_width, int dst_height, + int dst_stride, int dst_format, + int mode); diff --git a/xorg/server/module/rdpClientCon.c b/xorg/server/module/rdpClientCon.c index 73b08500..3c9cdad5 100644 --- a/xorg/server/module/rdpClientCon.c +++ b/xorg/server/module/rdpClientCon.c @@ -42,6 +42,7 @@ Client connection to xrdp #include "rdpMisc.h" #include "rdpInput.h" #include "rdpReg.h" +#include "rdpCapture.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -115,6 +116,9 @@ rdpClientConGotConnection(ScreenPtr pScreen, rdpPtr dev) LLOGLN(0, ("rdpClientConGotConnection:")); clientCon = (rdpClientCon *) g_malloc(sizeof(rdpClientCon), 1); + clientCon->dev = dev; + dev->do_dirty_ons = 1; + make_stream(clientCon->in_s); init_stream(clientCon->in_s, 8192); make_stream(clientCon->out_s); @@ -154,6 +158,7 @@ rdpClientConGotConnection(ScreenPtr pScreen, rdpPtr dev) } clientCon->dirtyRegion = rdpRegionCreate(NullBox, 0); + clientCon->shmRegion = rdpRegionCreate(NullBox, 0); return 0; } @@ -260,12 +265,15 @@ rdpClientConDisconnect(rdpPtr dev, rdpClientCon *clientCon) dev->clientConTail = plcli; } } + LLOGLN(0, ("rdpClientConDisconnect: clientCon removed from " + "dev list")); break; } plcli = pcli; pcli = pcli->next; } rdpRegionDestroy(clientCon->dirtyRegion); + rdpRegionDestroy(clientCon->shmRegion); g_free(clientCon); return 0; } @@ -568,46 +576,36 @@ rdpClientConProcessScreenSizeMsg(rdpPtr dev, rdpClientCon *clientCon, clientCon->rdp_Bpp_mask = 0xffffff; } -// todo -#if 0 - if (g_use_shmem) + if (clientCon->shmemptr != 0) { - if (g_shmemptr != 0) - { - shmdt(g_shmemptr); - } - bytes = g_rdpScreen.rdp_width * g_rdpScreen.rdp_height * - g_rdpScreen.rdp_Bpp; - g_shmemid = shmget(IPC_PRIVATE, bytes, IPC_CREAT | 0777); - g_shmemptr = shmat(g_shmemid, 0, 0); - shmctl(g_shmemid, IPC_RMID, NULL); - LLOGLN(0, ("rdpClientConProcessScreenSizeMsg: g_shmemid %d g_shmemptr %p", - g_shmemid, g_shmemptr)); - g_shmem_lineBytes = g_rdpScreen.rdp_Bpp * g_rdpScreen.rdp_width; - - if (g_shm_reg != 0) - { - RegionDestroy(g_shm_reg); - } - g_shm_reg = RegionCreate(NullBox, 0); + shmdt(clientCon->shmemptr); } -#endif + bytes = clientCon->rdp_width * clientCon->rdp_height * + clientCon->rdp_Bpp; + clientCon->shmemid = shmget(IPC_PRIVATE, bytes, IPC_CREAT | 0777); + clientCon->shmemptr = shmat(clientCon->shmemid, 0, 0); + shmctl(clientCon->shmemid, IPC_RMID, NULL); + LLOGLN(0, ("rdpClientConProcessScreenSizeMsg: shmemid %d shmemptr %p", + clientCon->shmemid, clientCon->shmemptr)); + clientCon->shmem_lineBytes = clientCon->rdp_Bpp * clientCon->rdp_width; + + if (clientCon->shmRegion != 0) + { + rdpRegionDestroy(clientCon->shmRegion); + } + clientCon->shmRegion = rdpRegionCreate(NullBox, 0); mmwidth = PixelToMM(width); mmheight = PixelToMM(height); -// todo -#if 0 - pSize = RRRegisterSize(g_pScreen, width, height, mmwidth, mmheight); - RRSetCurrentConfig(g_pScreen, RR_Rotate_0, 0, pSize); + pSize = RRRegisterSize(dev->pScreen, width, height, mmwidth, mmheight); + RRSetCurrentConfig(dev->pScreen, RR_Rotate_0, 0, pSize); - if ((g_rdpScreen.width != width) || (g_rdpScreen.height != height)) + if ((dev->width != width) || (dev->height != height)) { - LLOGLN(0, (" calling RRScreenSizeSet")); - ok = RRScreenSizeSet(g_pScreen, width, height, mmwidth, mmheight); - LLOGLN(0, (" RRScreenSizeSet ok=[%d]", ok)); + ok = RRScreenSizeSet(dev->pScreen, width, height, mmwidth, mmheight); + LLOGLN(0, ("rdpClientConProcessScreenSizeMsg: RRScreenSizeSet ok=[%d]", ok)); } -#endif return 0; } @@ -622,6 +620,10 @@ rdpClientConProcessMsgClientInput(rdpPtr dev, rdpClientCon *clientCon) int param2; int param3; int param4; + int x; + int y; + int cx; + int cy; s = clientCon->in_s; in_uint32_le(s, msg); @@ -643,10 +645,13 @@ rdpClientConProcessMsgClientInput(rdpPtr dev, rdpClientCon *clientCon) } else if (msg == 200) /* invalidate */ { - rdpClientConBeginUpdate(dev, clientCon); - rdpClientConSetFgcolor(dev, clientCon, 0x00ff0000); - rdpClientConFillRect(dev, clientCon, 0, 0, dev->width, dev->height); - rdpClientConEndUpdate(dev, clientCon); + x = (param1 >> 16) & 0xffff; + y = param1 & 0xffff; + cx = (param2 >> 16) & 0xffff; + cy = param2 & 0xffff; + LLOGLN(0, ("rdpClientConProcessMsgClientInput: invalidate x %d y %d " + "cx %d cy %d", x, y, cx, cy)); + rdpClientConAddDirtyScreen(dev, clientCon, x, y, cx, cy); } else if (msg == 300) /* resize desktop */ { @@ -761,10 +766,57 @@ static int rdpClientConProcessMsgClientRegion(rdpPtr dev, rdpClientCon *clientCon) { struct stream *s; + int flags; + int x; + int y; + int cx; + int cy; + RegionRec reg; + BoxRec box; - LLOGLN(0, ("rdpClientConProcessMsgClientRegion:")); + LLOGLN(10, ("rdpClientConProcessMsgClientRegion:")); s = clientCon->in_s; - g_hexdump(s->p, s->end - s->p); + + in_uint32_le(s, flags); + in_uint32_le(s, clientCon->rect_id_ack); + in_uint32_le(s, x); + in_uint32_le(s, y); + in_uint32_le(s, cx); + in_uint32_le(s, cy); + LLOGLN(10, ("rdpClientConProcessMsgClientRegion: %d %d %d %d flags 0x%8.8x", + x, y, cx, cy, flags)); + LLOGLN(10, ("rdpClientConProcessMsgClientRegion: rect_id %d rect_id_ack %d", + clientCon->rect_id, clientCon->rect_id_ack)); + + box.x1 = x; + box.y1 = y; + box.x2 = box.x1 + cx; + box.y2 = box.y1 + cy; + + rdpRegionInit(®, &box, 0); + LLOGLN(10, ("rdpClientConProcessMsgClientRegion: %d %d %d %d", + box.x1, box.y1, box.x2, box.y2)); + rdpRegionSubtract(clientCon->shmRegion, clientCon->shmRegion, ®); + rdpRegionUninit(®); + + return 0; +} + +/******************************************************************************/ +static int +rdpClientConProcessMsgClientRegionEx(rdpPtr dev, rdpClientCon *clientCon) +{ + struct stream *s; + int flags; + + LLOGLN(10, ("rdpClientConProcessMsgClientRegionEx:")); + s = clientCon->in_s; + + in_uint32_le(s, flags); + in_uint32_le(s, clientCon->rect_id_ack); + LLOGLN(10, ("rdpClientConProcessMsgClientRegionEx: flags 0x%8.8x", flags)); + LLOGLN(10, ("rdpClientConProcessMsgClientRegionEx: rect_id %d " + "rect_id_ack %d", clientCon->rect_id, clientCon->rect_id_ack)); return 0; } @@ -790,6 +842,9 @@ rdpClientConProcessMsg(rdpPtr dev, rdpClientCon *clientCon) case 105: /* client region */ rdpClientConProcessMsgClientRegion(dev, clientCon); break; + case 106: /* client region ex */ + rdpClientConProcessMsgClientRegionEx(dev, clientCon); + break; default: break; } @@ -1819,12 +1874,149 @@ rdpClientConCheckDirtyScreen(rdpPtr dev, rdpClientCon *clientCon) return 0; } +/******************************************************************************/ +static int +rdpClientConSendPaintRectShmEx(rdpPtr dev, rdpClientCon *clientCon, + struct image_data *id, + RegionPtr dirtyReg, RegionPtr copyReg) +{ + int index; + int size; + int num_rects_d; + int num_rects_c; + struct stream *s; + BoxRec box; + + rdpClientConBeginUpdate(dev, clientCon); + + num_rects_d = REGION_NUM_RECTS(dirtyReg); + num_rects_c = REGION_NUM_RECTS(copyReg); + size = 2 + 2 + 2 + num_rects_d * 8 + 2 + num_rects_c * 8; + size += 4 + 4 + 4 + 4 + 2 + 2; + rdpClientConPreCheck(dev, clientCon, size); + + s = clientCon->out_s; + out_uint16_le(s, 61); + out_uint16_le(s, size); + clientCon->count++; + + out_uint16_le(s, num_rects_d); + for (index = 0; index < num_rects_d; index++) + { + box = REGION_RECTS(dirtyReg)[index]; + out_uint16_le(s, box.x1); + out_uint16_le(s, box.y1); + out_uint16_le(s, box.x2 - box.x1); + out_uint16_le(s, box.y2 - box.y1); + } + + out_uint16_le(s, num_rects_c); + for (index = 0; index < num_rects_c; index++) + { + box = REGION_RECTS(copyReg)[index]; + out_uint16_le(s, box.x1); + out_uint16_le(s, box.y1); + out_uint16_le(s, box.x2 - box.x1); + out_uint16_le(s, box.y2 - box.y1); + } + + out_uint32_le(s, 0); + clientCon->rect_id++; + out_uint32_le(s, clientCon->rect_id); + out_uint32_le(s, id->shmem_id); + out_uint32_le(s, id->shmem_offset); + out_uint16_le(s, clientCon->rdp_width); + out_uint16_le(s, clientCon->rdp_height); + + rdpClientConEndUpdate(dev, clientCon); + + return 0; +} + +/******************************************************************************/ +static CARD32 +rdpDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg) +{ + rdpClientCon *clientCon; + RegionRec reg; + struct image_data id; + + LLOGLN(10, ("rdpDeferredUpdateCallback:")); + clientCon = (rdpClientCon *) arg; + + if (clientCon->rect_id != clientCon->rect_id_ack) + { + LLOGLN(0, ("rdpDeferredUpdateCallback: reschedual")); + clientCon->updateTimer = TimerSet(clientCon->updateTimer, 0, 40, + rdpDeferredUpdateCallback, clientCon); + return 0; + } + else + { + LLOGLN(10, ("rdpDeferredUpdateCallback: sending")); + } + rdpClientConGetScreenImageRect(clientCon->dev, clientCon, &id); + LLOGLN(10, ("rdpDeferredUpdateCallback: rdp_width %d rdp_height %d " + "rdp_Bpp %d screen width %d screen height %d", + clientCon->rdp_width, clientCon->rdp_height, clientCon->rdp_Bpp, + id.width, id.height)); + clientCon->updateSchedualed = FALSE; + rdpRegionInit(®, NullBox, 0); + rdpCapture(clientCon->dirtyRegion, ®, + id.pixels, id.width, id.height, + id.lineBytes, XRDP_a8r8g8b8, + id.shmem_pixels, clientCon->rdp_width, clientCon->rdp_height, + clientCon->rdp_width * clientCon->rdp_Bpp , XRDP_a8r8g8b8, 0); + rdpClientConSendPaintRectShmEx(clientCon->dev, clientCon, &id, + clientCon->dirtyRegion, ®); + rdpRegionDestroy(clientCon->dirtyRegion); + clientCon->dirtyRegion = rdpRegionCreate(NullBox, 0); + rdpRegionUninit(®); + return 0; +} + /******************************************************************************/ int rdpClientConAddDirtyScreenReg(rdpPtr dev, rdpClientCon *clientCon, RegionPtr reg) { + LLOGLN(10, ("rdpClientConAddDirtyScreenReg:")); + rdpRegionUnion(clientCon->dirtyRegion, clientCon->dirtyRegion, reg); + if (clientCon->updateSchedualed == FALSE) + { + clientCon->updateTimer = TimerSet(clientCon->updateTimer, 0, 40, + rdpDeferredUpdateCallback, clientCon); + clientCon->updateSchedualed = TRUE; + } + return 0; +} + +/******************************************************************************/ +int +rdpClientConAddDirtyScreenBox(rdpPtr dev, rdpClientCon *clientCon, + BoxPtr box) +{ + RegionPtr reg; + + reg = rdpRegionCreate(box, 0); + rdpClientConAddDirtyScreenReg(dev, clientCon, reg); + rdpRegionDestroy(reg); + return 0; +} + +/******************************************************************************/ +int +rdpClientConAddDirtyScreen(rdpPtr dev, rdpClientCon *clientCon, + int x, int y, int cx, int cy) +{ + BoxRec box; + + box.x1 = x; + box.y1 = y; + box.x2 = box.x1 + cx; + box.y2 = box.y1 + cy; + rdpClientConAddDirtyScreenBox(dev, clientCon, &box); return 0; } @@ -1839,10 +2031,10 @@ rdpClientConGetScreenImageRect(rdpPtr dev, rdpClientCon *clientCon, id->Bpp = clientCon->rdp_Bpp; id->lineBytes = dev->paddedWidthInBytes; id->pixels = dev->pfbMemory; - id->shmem_pixels = g_shmemptr; - id->shmem_id = g_shmemid; + id->shmem_pixels = clientCon->shmemptr; + id->shmem_id = clientCon->shmemid; id->shmem_offset = 0; - id->shmem_lineBytes = g_shmem_lineBytes; + id->shmem_lineBytes = clientCon->shmem_lineBytes; } /******************************************************************************/ @@ -1852,8 +2044,8 @@ rdpClientConGetPixmapImageRect(rdpPtr dev, rdpClientCon *clientCon, { id->width = pPixmap->drawable.width; id->height = pPixmap->drawable.height; - id->bpp = g_rdpScreen.rdp_bpp; - id->Bpp = g_rdpScreen.rdp_Bpp; + id->bpp = clientCon->rdp_bpp; + id->Bpp = clientCon->rdp_Bpp; id->lineBytes = pPixmap->devKind; id->pixels = (char *)(pPixmap->devPrivate.ptr); id->shmem_pixels = 0; @@ -1864,15 +2056,22 @@ rdpClientConGetPixmapImageRect(rdpPtr dev, rdpClientCon *clientCon, /******************************************************************************/ void -rdpClientConSendArea(struct image_data *id, int x, int y, int w, int h) +rdpClientConSendArea(rdpPtr dev, rdpClientCon *clientCon, + struct image_data *id, int x, int y, int w, int h) { struct image_data lid; + BoxRec box; + int ly; + int size; + char *src; + char *dst; + struct stream *s; LLOGLN(10, ("rdpClientConSendArea: id %p x %d y %d w %d h %d", id, x, y, w, h)); - if (id == 0) + if (id == NULL) { - rdpup_get_screen_image_rect(&lid); + rdpClientConGetScreenImageRect(dev, clientCon, &lid); id = &lid; } @@ -1886,4 +2085,125 @@ rdpClientConSendArea(struct image_data *id, int x, int y, int w, int h) return; } + if (x < 0) + { + w += x; + x = 0; + } + + if (y < 0) + { + h += y; + y = 0; + } + + if (w <= 0) + { + return; + } + + if (h <= 0) + { + return; + } + + if (x + w > id->width) + { + w = id->width - x; + } + + if (y + h > id->height) + { + h = id->height - y; + } + + if (clientCon->connected && clientCon->begin) + { + if (id->shmem_pixels != 0) + { + LLOGLN(10, ("rdpClientConSendArea: using shmem")); + box.x1 = x; + box.y1 = y; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + src = id->pixels; + src += y * id->lineBytes; + src += x * dev->Bpp; + dst = id->shmem_pixels + id->shmem_offset; + dst += y * id->shmem_lineBytes; + dst += x * clientCon->rdp_Bpp; + ly = y; + while (ly < y + h) + { + rdpClientConConvertPixels(dev, clientCon, src, dst, w); + src += id->lineBytes; + dst += id->shmem_lineBytes; + ly += 1; + } + size = 36; + rdpClientConPreCheck(dev, clientCon, size); + s = clientCon->out_s; + out_uint16_le(s, 60); + out_uint16_le(s, size); + clientCon->count++; + LLOGLN(10, ("rdpClientConSendArea: 2 x %d y %d w %d h %d", x, y, w, h)); + out_uint16_le(s, x); + out_uint16_le(s, y); + out_uint16_le(s, w); + out_uint16_le(s, h); + out_uint32_le(s, 0); + clientCon->rect_id++; + out_uint32_le(s, clientCon->rect_id); + out_uint32_le(s, id->shmem_id); + out_uint32_le(s, id->shmem_offset); + out_uint16_le(s, id->width); + out_uint16_le(s, id->height); + out_uint16_le(s, x); + out_uint16_le(s, y); + rdpRegionUnionRect(clientCon->shmRegion, &box); + return; + } + } +} + +/******************************************************************************/ +int +rdpClientConAddAllReg(rdpPtr dev, RegionPtr reg, DrawablePtr pDrawable) +{ + rdpClientCon *clientCon; + Bool drw_is_vis; + + drw_is_vis = XRDP_DRAWABLE_IS_VISIBLE(dev, pDrawable); + if (!drw_is_vis) + { + return 0; + } + clientCon = dev->clientConHead; + while (clientCon != NULL) + { + rdpClientConAddDirtyScreenReg(dev, clientCon, reg); + clientCon = clientCon->next; + } + return 0; +} + +/******************************************************************************/ +int +rdpClientConAddAllBox(rdpPtr dev, BoxPtr box, DrawablePtr pDrawable) +{ + rdpClientCon *clientCon; + Bool drw_is_vis; + + drw_is_vis = XRDP_DRAWABLE_IS_VISIBLE(dev, pDrawable); + if (!drw_is_vis) + { + return 0; + } + clientCon = dev->clientConHead; + while (clientCon != NULL) + { + rdpClientConAddDirtyScreenBox(dev, clientCon, box); + clientCon = clientCon->next; + } + return 0; } diff --git a/xorg/server/module/rdpClientCon.h b/xorg/server/module/rdpClientCon.h index 2551a4ed..9cbe493a 100644 --- a/xorg/server/module/rdpClientCon.h +++ b/xorg/server/module/rdpClientCon.h @@ -50,6 +50,8 @@ struct rdpup_os_bitmap /* one of these for each client */ struct _rdpClientCon { + rdpPtr dev; + int sck; int sckControlListener; int sckControl; @@ -90,6 +92,16 @@ struct _rdpClientCon struct xrdp_client_info client_info; + char *shmemptr; + int shmemid; + int shmem_lineBytes; + RegionPtr shmRegion; + int rect_id; + int rect_id_ack; + + OsTimerPtr updateTimer; + int updateSchedualed; /* boolean */ + struct _rdpClientCon *next; }; @@ -99,6 +111,9 @@ int rdpClientConEndUpdate(rdpPtr dev, rdpClientCon *clientCon); int rdpClientConSetFgcolor(rdpPtr dev, rdpClientCon *clientCon, int fgcolor); +void +rdpClientConSendArea(rdpPtr dev, rdpClientCon *clientCon, + struct image_data *id, int x, int y, int w, int h); int rdpClientConFillRect(rdpPtr dev, rdpClientCon *clientCon, short x, short y, int cx, int cy); @@ -122,6 +137,25 @@ rdpClientConCheckDirtyScreen(rdpPtr dev, rdpClientCon *clientCon); int rdpClientConAddDirtyScreenReg(rdpPtr dev, rdpClientCon *clientCon, RegionPtr reg); - +int +rdpClientConAddDirtyScreenBox(rdpPtr dev, rdpClientCon *clientCon, + BoxPtr box); +int +rdpClientConAddDirtyScreen(rdpPtr dev, rdpClientCon *clientCon, + int x, int y, int cx, int cy); +void +rdpClientConGetScreenImageRect(rdpPtr dev, rdpClientCon *clientCon, + struct image_data *id); +int +rdpClientConAddAllReg(rdpPtr dev, RegionPtr reg, DrawablePtr pDrawable); +int +rdpClientConAddAllBox(rdpPtr dev, BoxPtr box, DrawablePtr pDrawable); +int +rdpClientConSetCursor(rdpPtr dev, rdpClientCon *clientCon, + short x, short y, char *cur_data, char *cur_mask); +int +rdpClientConSetCursorEx(rdpPtr dev, rdpClientCon *clientCon, + short x, short y, char *cur_data, + char *cur_mask, int bpp); #endif diff --git a/xorg/server/module/rdpComposite.c b/xorg/server/module/rdpComposite.c index 87a9364f..7535d6c3 100644 --- a/xorg/server/module/rdpComposite.c +++ b/xorg/server/module/rdpComposite.c @@ -32,11 +32,14 @@ composite(alpha blending) calls #include #include +#include "mipict.h" #include #include "rdp.h" -#include "rdpComposite.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" +#include "rdpComposite.h" /******************************************************************************/ #define LOG_LEVEL 1 @@ -65,11 +68,26 @@ rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, ScreenPtr pScreen; rdpPtr dev; PictureScreenPtr ps; + BoxRec box; + RegionRec reg; LLOGLN(10, ("rdpComposite:")); - pScreen = pSrc->pDrawable->pScreen; + pScreen = pDst->pDrawable->pScreen; dev = rdpGetDevFromScreen(pScreen); + dev->counts.rdpCompositeCallCount++; + box.x1 = xDst + pDst->pDrawable->x; + box.y1 = yDst + pDst->pDrawable->y; + box.x2 = box.x1 + width; + box.y2 = box.y1 + height; + rdpRegionInit(®, &box, 0); + if (pDst->pCompositeClip != NULL) + { + rdpRegionIntersect(®, pDst->pCompositeClip, ®); + } ps = GetPictureScreen(pScreen); + /* do original call */ rdpCompositeOrg(ps, dev, op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); + rdpClientConAddAllReg(dev, ®, pDst->pDrawable); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpCopyArea.c b/xorg/server/module/rdpCopyArea.c index 77ad43ad..708891f6 100644 --- a/xorg/server/module/rdpCopyArea.c +++ b/xorg/server/module/rdpCopyArea.c @@ -32,6 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -56,10 +58,35 @@ RegionPtr rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty) { + rdpPtr dev; RegionPtr rv; + RegionRec clip_reg; + RegionRec reg; + int cd; + BoxRec box; LLOGLN(10, ("rdpCopyArea:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpCopyAreaCallCount++; + box.x1 = dstx + pDst->x; + box.y1 = dsty + pDst->y; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + rdpRegionInit(®, &box, 0); + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDst, pGC); + LLOGLN(10, ("rdpCopyArea: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rv = rdpCopyAreaOrg(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDst); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); return rv; } diff --git a/xorg/server/module/rdpCopyPlane.c b/xorg/server/module/rdpCopyPlane.c index 5dae9f09..9ccf4c0a 100644 --- a/xorg/server/module/rdpCopyPlane.c +++ b/xorg/server/module/rdpCopyPlane.c @@ -32,6 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -60,10 +62,35 @@ rdpCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, int dstx, int dsty, unsigned long bitPlane) { RegionPtr rv; + rdpPtr dev; + RegionRec clip_reg; + RegionRec reg; + int cd; + BoxRec box; LLOGLN(10, ("rdpCopyPlane:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpCopyPlaneCallCount++; + box.x1 = pDst->x + dstx; + box.y1 = pDst->y + dsty; + box.x2 = box.x1 + w; + box.y2 = box.x1 + h; + rdpRegionInit(®, &box, 0); + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDst, pGC); + LLOGLN(10, ("rdpCopyPlane: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rv = rdpCopyPlaneOrg(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, bitPlane); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDst); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); return rv; } diff --git a/xorg/server/module/rdpCursor.c b/xorg/server/module/rdpCursor.c index 21b9c47c..3859e8e7 100644 --- a/xorg/server/module/rdpCursor.c +++ b/xorg/server/module/rdpCursor.c @@ -36,9 +36,50 @@ cursor #include #include #include +#include +#include #include "rdp.h" #include "rdpMain.h" +#include "rdpDraw.h" +#include "rdpClientCon.h" + +/* Copied from Xvnc/lib/font/util/utilbitmap.c */ +static unsigned char g_reverse_byte[0x100] = +{ + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff +}; /******************************************************************************/ #define LOG_LEVEL 1 @@ -49,7 +90,7 @@ cursor Bool rdpSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScr, CursorPtr pCurs) { - LLOGLN(0, ("rdpSpriteRealizeCursor:")); + LLOGLN(10, ("rdpSpriteRealizeCursor:")); return TRUE; } @@ -57,30 +98,244 @@ rdpSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScr, CursorPtr pCurs) Bool rdpSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScr, CursorPtr pCurs) { - LLOGLN(0, ("rdpSpriteUnrealizeCursor:")); + LLOGLN(10, ("rdpSpriteUnrealizeCursor:")); return TRUE; } +/******************************************************************************/ +static int +get_pixel_safe(char *data, int x, int y, int width, int height, int bpp) +{ + int start; + int shift; + int c; + unsigned int *src32; + + if (x < 0) + { + return 0; + } + + if (y < 0) + { + return 0; + } + + if (x >= width) + { + return 0; + } + + if (y >= height) + { + return 0; + } + + if (bpp == 1) + { + width = (width + 7) / 8; + start = (y * width) + x / 8; + shift = x % 8; + c = (unsigned char)(data[start]); +#if (X_BYTE_ORDER == X_LITTLE_ENDIAN) + return (g_reverse_byte[c] & (0x80 >> shift)) != 0; +#else + return (c & (0x80 >> shift)) != 0; +#endif + } + else if (bpp == 32) + { + src32 = (unsigned int*)data; + return src32[y * width + x]; + } + + return 0; +} + +/******************************************************************************/ +static void +set_pixel_safe(char *data, int x, int y, int width, int height, int bpp, + int pixel) +{ + int start; + int shift; + unsigned int *dst32; + + if (x < 0) + { + return; + } + + if (y < 0) + { + return; + } + + if (x >= width) + { + return; + } + + if (y >= height) + { + return; + } + + if (bpp == 1) + { + width = (width + 7) / 8; + start = (y * width) + x / 8; + shift = x % 8; + + if (pixel & 1) + { + data[start] = data[start] | (0x80 >> shift); + } + else + { + data[start] = data[start] & ~(0x80 >> shift); + } + } + else if (bpp == 24) + { + *(data + (3 * (y * width + x)) + 0) = pixel >> 0; + *(data + (3 * (y * width + x)) + 1) = pixel >> 8; + *(data + (3 * (y * width + x)) + 2) = pixel >> 16; + } + else if (bpp == 32) + { + dst32 = (unsigned int*)data; + dst32[y * width + x] = pixel; + } +} + +/******************************************************************************/ +void +rdpSpriteSetCursorCon(rdpClientCon *clientCon, + DeviceIntPtr pDev, ScreenPtr pScr, CursorPtr pCurs, + int x, int y) +{ + char cur_data[32 * (32 * 4)]; + char cur_mask[32 * (32 / 8)]; + char *mask; + char *data; + int i; + int j; + int w; + int h; + int p; + int xhot; + int yhot; + int paddedRowBytes; + int fgcolor; + int bgcolor; + int bpp; + + LLOGLN(10, ("rdpSpriteSetCursorCon:")); + + w = pCurs->bits->width; + h = pCurs->bits->height; + if ((pCurs->bits->argb != 0) && + (clientCon->client_info.pointer_flags & 1)) + { + bpp = 32; + paddedRowBytes = PixmapBytePad(w, 32); + xhot = pCurs->bits->xhot; + yhot = pCurs->bits->yhot; + data = (char *)(pCurs->bits->argb); + memset(cur_data, 0, sizeof(cur_data)); + memset(cur_mask, 0, sizeof(cur_mask)); + + for (j = 0; j < 32; j++) + { + for (i = 0; i < 32; i++) + { + p = get_pixel_safe(data, i, j, paddedRowBytes / 4, h, 32); + set_pixel_safe(cur_data, i, 31 - j, 32, 32, 32, p); + } + } + } + else + { + bpp = 0; + paddedRowBytes = PixmapBytePad(w, 1); + xhot = pCurs->bits->xhot; + yhot = pCurs->bits->yhot; + data = (char *)(pCurs->bits->source); + mask = (char *)(pCurs->bits->mask); + fgcolor = (((pCurs->foreRed >> 8) & 0xff) << 16) | + (((pCurs->foreGreen >> 8) & 0xff) << 8) | + ((pCurs->foreBlue >> 8) & 0xff); + bgcolor = (((pCurs->backRed >> 8) & 0xff) << 16) | + (((pCurs->backGreen >> 8) & 0xff) << 8) | + ((pCurs->backBlue >> 8) & 0xff); + memset(cur_data, 0, sizeof(cur_data)); + memset(cur_mask, 0, sizeof(cur_mask)); + + for (j = 0; j < 32; j++) + { + for (i = 0; i < 32; i++) + { + p = get_pixel_safe(mask, i, j, paddedRowBytes * 8, h, 1); + set_pixel_safe(cur_mask, i, 31 - j, 32, 32, 1, !p); + + if (p != 0) + { + p = get_pixel_safe(data, i, j, paddedRowBytes * 8, h, 1); + p = p ? fgcolor : bgcolor; + set_pixel_safe(cur_data, i, 31 - j, 32, 32, 24, p); + } + } + } + } + + rdpClientConBeginUpdate(clientCon->dev, clientCon); + rdpClientConSetCursorEx(clientCon->dev, clientCon, xhot, yhot, + cur_data, cur_mask, bpp); + rdpClientConEndUpdate(clientCon->dev, clientCon); + +} + /******************************************************************************/ void rdpSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScr, CursorPtr pCurs, int x, int y) { - LLOGLN(0, ("rdpSpriteSetCursor:")); + rdpPtr dev; + rdpClientCon *clientCon; + + LLOGLN(10, ("rdpSpriteSetCursor:")); + if (pCurs == 0) + { + return; + } + + if (pCurs->bits == 0) + { + return; + } + + dev = rdpGetDevFromScreen(pScr); + clientCon = dev->clientConHead; + while (clientCon != NULL) + { + rdpSpriteSetCursorCon(clientCon, pDev, pScr, pCurs, x, y); + clientCon = clientCon->next; + } } /******************************************************************************/ void rdpSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScr, int x, int y) { - LLOGLN(0, ("rdpSpriteMoveCursor:")); + LLOGLN(10, ("rdpSpriteMoveCursor:")); } /******************************************************************************/ Bool rdpSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScr) { - LLOGLN(0, ("rdpSpriteDeviceCursorInitialize:")); + LLOGLN(10, ("rdpSpriteDeviceCursorInitialize:")); return TRUE; } @@ -88,6 +343,6 @@ rdpSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScr) void rdpSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScr) { - LLOGLN(0, ("rdpSpriteDeviceCursorCleanup:")); + LLOGLN(10, ("rdpSpriteDeviceCursorCleanup:")); xorgxrdpDownDown(pScr); } diff --git a/xorg/server/module/rdpDraw.c b/xorg/server/module/rdpDraw.c index a731ee98..b4e689af 100644 --- a/xorg/server/module/rdpDraw.c +++ b/xorg/server/module/rdpDraw.c @@ -27,6 +27,7 @@ misc draw calls /* this should be before all X11 .h files */ #include +#include /* all driver need this */ #include @@ -36,6 +37,7 @@ misc draw calls #include #include #include +#include #include "rdp.h" #include "rdpDraw.h" @@ -107,7 +109,7 @@ rdpDrawGetClip(rdpPtr dev, RegionPtr pRegion, DrawablePtr pDrawable, GCPtr pGC) temp = &pWindow->clipList; } - if (RegionNotEmpty(temp)) + if (rdpRegionNotEmpty(temp)) { switch (pGC->clientClipType) { @@ -148,6 +150,54 @@ rdpDrawGetClip(rdpPtr dev, RegionPtr pRegion, DrawablePtr pDrawable, GCPtr pGC) return rv; } +/******************************************************************************/ +void +GetTextBoundingBox(DrawablePtr pDrawable, FontPtr font, int x, int y, + int n, BoxPtr pbox) +{ + int maxAscent; + int maxDescent; + int maxCharWidth; + + if (FONTASCENT(font) > FONTMAXBOUNDS(font, ascent)) + { + maxAscent = FONTASCENT(font); + } + else + { + maxAscent = FONTMAXBOUNDS(font, ascent); + } + + if (FONTDESCENT(font) > FONTMAXBOUNDS(font, descent)) + { + maxDescent = FONTDESCENT(font); + } + else + { + maxDescent = FONTMAXBOUNDS(font, descent); + } + + if (FONTMAXBOUNDS(font, rightSideBearing) > + FONTMAXBOUNDS(font, characterWidth)) + { + maxCharWidth = FONTMAXBOUNDS(font, rightSideBearing); + } + else + { + maxCharWidth = FONTMAXBOUNDS(font, characterWidth); + } + + pbox->x1 = pDrawable->x + x; + pbox->y1 = pDrawable->y + y - maxAscent; + pbox->x2 = pbox->x1 + maxCharWidth * n; + pbox->y2 = pbox->y1 + maxAscent + maxDescent; + + if (FONTMINBOUNDS(font, leftSideBearing) < 0) + { + pbox->x1 += FONTMINBOUNDS(font, leftSideBearing); + } +} + /******************************************************************************/ int rdpDrawItemAdd(rdpPtr dev, rdpPixmapRec *priv, struct rdp_draw_item *di) @@ -239,14 +289,63 @@ rdpCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion) { ScreenPtr pScreen; rdpPtr dev; + RegionRec reg; + RegionRec clip; + int dx; + int dy; + int num_clip_rects; + int num_reg_rects; + BoxPtr box; + BoxRec box1; + LLOGLN(10, ("rdpCopyWindow:")); pScreen = pWin->drawable.pScreen; dev = rdpGetDevFromScreen(pScreen); + dev->counts.rdpCopyWindowCallCount++; + + rdpRegionInit(®, NullBox, 0); + rdpRegionCopy(®, pOldRegion); + rdpRegionInit(&clip, NullBox, 0); + rdpRegionCopy(&clip, &pWin->borderClip); + dx = pWin->drawable.x - ptOldOrg.x; + dy = pWin->drawable.y - ptOldOrg.y; + dev->pScreen->CopyWindow = dev->CopyWindow; dev->pScreen->CopyWindow(pWin, ptOldOrg, pOldRegion); dev->pScreen->CopyWindow = rdpCopyWindow; + + num_clip_rects = REGION_NUM_RECTS(&clip); + num_reg_rects = REGION_NUM_RECTS(®); + + if ((num_clip_rects == 0) || (num_reg_rects == 0)) + { + } + else + { + if ((num_clip_rects > 16) || (num_reg_rects > 16)) + { + LLOGLN(10, ("rdpCopyWindow: big list")); + box = rdpRegionExtents(®); + box1 = *box; + box1.x1 += dx; + box1.y1 += dy; + box1.x2 += dx; + box1.y2 += dy; + rdpClientConAddAllBox(dev, &box1, &(pWin->drawable)); + } + else + { + rdpRegionTranslate(®, dx, dy); + rdpRegionIntersect(®, ®, &clip); + rdpClientConAddAllReg(dev, ®, &(pWin->drawable)); + } + } + rdpRegionUninit(®); + rdpRegionUninit(&clip); } +#if XRDP_CLOSESCR == 1 /* before v1.13 */ + /*****************************************************************************/ Bool rdpCloseScreen(int index, ScreenPtr pScreen) @@ -262,11 +361,30 @@ rdpCloseScreen(int index, ScreenPtr pScreen) return rv; } +#else + +/*****************************************************************************/ +Bool +rdpCloseScreen(ScreenPtr pScreen) +{ + rdpPtr dev; + Bool rv; + + LLOGLN(0, ("rdpCloseScreen:")); + dev = rdpGetDevFromScreen(pScreen); + dev->pScreen->CloseScreen = dev->CloseScreen; + rv = dev->pScreen->CloseScreen(pScreen); + dev->pScreen->CloseScreen = rdpCloseScreen; + return rv; +} + +#endif + /******************************************************************************/ WindowPtr rdpGetRootWindowPtr(ScreenPtr pScreen) { -#if XORG_VERSION_CURRENT < (((1) * 10000000) + ((9) * 100000) + ((0) * 1000) + 0) +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 9, 0, 0, 0) return WindowTable[pScreen->myNum]; /* in globals.c */ #else return pScreen->root; diff --git a/xorg/server/module/rdpDraw.h b/xorg/server/module/rdpDraw.h index eaebddb2..af65b46c 100644 --- a/xorg/server/module/rdpDraw.h +++ b/xorg/server/module/rdpDraw.h @@ -25,8 +25,23 @@ misc draw calls #define __RDPDRAW_H #include +#include #include +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 13, 0, 0, 0) +/* 1.1, 1.2, 1.3, 1.4 1.5, 1.6, 1.7, 1.8, 1.9, 1.10, 1.11, 1.12 */ +#define XRDP_CLOSESCR 1 +#else +/* 1.13 */ +#define XRDP_CLOSESCR 2 +#endif + +/* true if drawable is window or pixmap is screen */ +#define XRDP_DRAWABLE_IS_VISIBLE(_dev, _drw) \ +(((_drw)->type == DRAWABLE_WINDOW && ((WindowPtr)(_drw))->viewable) || \ + ((_drw)->type == DRAWABLE_PIXMAP && \ + ((PixmapPtr)(_drw))->devPrivate.ptr == (_dev)->pfbMemory)) + /******************************************************************************/ #define GC_OP_VARS rdpPtr dev; rdpGCPtr priv; GCFuncs *oldFuncs @@ -52,6 +67,9 @@ extern GCOps g_rdpGCOps; /* in rdpGC.c */ int rdpDrawGetClip(rdpPtr dev, RegionPtr pRegion, DrawablePtr pDrawable, GCPtr pGC); +void +GetTextBoundingBox(DrawablePtr pDrawable, FontPtr font, int x, int y, + int n, BoxPtr pbox); int rdpDrawItemAdd(rdpPtr dev, rdpPixmapRec *priv, struct rdp_draw_item *di); int @@ -60,8 +78,13 @@ int rdpDrawItemRemoveAll(rdpPtr dev, rdpPixmapRec *priv); void rdpCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion); +#if XRDP_CLOSESCR == 1 Bool rdpCloseScreen(int index, ScreenPtr pScreen); +#else +Bool +rdpCloseScreen(ScreenPtr pScreen); +#endif WindowPtr rdpGetRootWindowPtr(ScreenPtr pScreen); rdpPtr diff --git a/xorg/server/module/rdpFillPolygon.c b/xorg/server/module/rdpFillPolygon.c index 475dc3d5..34fe4096 100644 --- a/xorg/server/module/rdpFillPolygon.c +++ b/xorg/server/module/rdpFillPolygon.c @@ -32,6 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -56,7 +58,60 @@ rdpFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape, int mode, int count, DDXPointPtr pPts) { + rdpPtr dev; + RegionRec clip_reg; + RegionRec reg; + int cd; + int maxx; + int maxy; + int minx; + int miny; + int index; + int x; + int y; + BoxRec box; + LLOGLN(10, ("rdpFillPolygon:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpFillPolygonCallCount++; + box.x1 = 0; + box.y1 = 0; + box.x2 = 0; + box.y2 = 0; + if (count > 0) + { + maxx = pPts[0].x; + maxy = pPts[0].y; + minx = maxx; + miny = maxy; + for (index = 1; index < count; index++) + { + x = pPts[index].x; + y = pPts[index].y; + maxx = RDPMAX(x, maxx); + minx = RDPMIN(x, minx); + maxy = RDPMAX(y, maxy); + miny = RDPMIN(y, miny); + } + box.x1 = pDrawable->x + minx; + box.y1 = pDrawable->y + miny; + box.x2 = pDrawable->x + maxx + 1; + box.y2 = pDrawable->y + maxy + 1; + } + rdpRegionInit(®, &box, 0); + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpFillPolygon: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rdpFillPolygonOrg(pDrawable, pGC, shape, mode, count, pPts); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpGlyphs.c b/xorg/server/module/rdpGlyphs.c index a4e93e47..e6fcbb30 100644 --- a/xorg/server/module/rdpGlyphs.c +++ b/xorg/server/module/rdpGlyphs.c @@ -96,7 +96,7 @@ rdpGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictureScreenPtr ps; LLOGLN(10, ("rdpGlyphs:")); - pScreen = pSrc->pDrawable->pScreen; + pScreen = pDst->pDrawable->pScreen; dev = rdpGetDevFromScreen(pScreen); ps = GetPictureScreen(pScreen); rdpGlyphsOrg(ps, dev, op, pSrc, pDst, maskFormat, xSrc, ySrc, diff --git a/xorg/server/module/rdpImageGlyphBlt.c b/xorg/server/module/rdpImageGlyphBlt.c index e09ce256..74693fd9 100644 --- a/xorg/server/module/rdpImageGlyphBlt.c +++ b/xorg/server/module/rdpImageGlyphBlt.c @@ -32,13 +32,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) /******************************************************************************/ -void +static void rdpImageGlyphBltOrg(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase) @@ -56,7 +58,30 @@ rdpImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase) { - LLOGLN(10, ("rdpImageGlyphBlt:")); + rdpPtr dev; + RegionRec clip_reg; + RegionRec reg; + int cd; + BoxRec box; + + LLOGLN(0, ("rdpImageGlyphBlt:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpImageGlyphBltCallCount++; + GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box); + rdpRegionInit(®, &box, 0); + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpImageGlyphBlt: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rdpImageGlyphBltOrg(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpImageText16.c b/xorg/server/module/rdpImageText16.c index 984b7759..7ad8012b 100644 --- a/xorg/server/module/rdpImageText16.c +++ b/xorg/server/module/rdpImageText16.c @@ -32,13 +32,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) /******************************************************************************/ -void +static void rdpImageText16Org(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, unsigned short *chars) { @@ -54,7 +56,30 @@ void rdpImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, unsigned short *chars) { + rdpPtr dev; + RegionRec clip_reg; + RegionRec reg; + int cd; + BoxRec box; + LLOGLN(10, ("rdpImageText16:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpImageText16CallCount++; + GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); + rdpRegionInit(®, &box, 0); + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpImageText16: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rdpImageText16Org(pDrawable, pGC, x, y, count, chars); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpImageText8.c b/xorg/server/module/rdpImageText8.c index f4d62977..abcfbff0 100644 --- a/xorg/server/module/rdpImageText8.c +++ b/xorg/server/module/rdpImageText8.c @@ -32,13 +32,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) /******************************************************************************/ -void +static void rdpImageText8Org(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, char *chars) { @@ -54,8 +56,30 @@ void rdpImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, char *chars) { + rdpPtr dev; + RegionRec clip_reg; + RegionRec reg; + int cd; + BoxRec box; + LLOGLN(10, ("rdpImageText8:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpImageText8CallCount++; + GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); + rdpRegionInit(®, &box, 0); + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpImageText8: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rdpImageText8Org(pDrawable, pGC, x, y, count, chars); - return; + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpMisc.c b/xorg/server/module/rdpMisc.c index 1f0c4c51..653342fe 100644 --- a/xorg/server/module/rdpMisc.c +++ b/xorg/server/module/rdpMisc.c @@ -65,6 +65,34 @@ rdpBitsPerPixel(int depth) /* the g_ functions from os_calls.c */ +/*****************************************************************************/ +/* wait 'millis' milliseconds for the socket to be able to receive */ +/* returns boolean */ +int +g_sck_can_recv(int sck, int millis) +{ + fd_set rfds; + struct timeval time; + int rv; + + time.tv_sec = millis / 1000; + time.tv_usec = (millis * 1000) % 1000000; + FD_ZERO(&rfds); + + if (sck > 0) + { + FD_SET(((unsigned int)sck), &rfds); + rv = select(sck + 1, &rfds, 0, 0, &time); + + if (rv > 0) + { + return 1; + } + } + + return 0; +} + /*****************************************************************************/ int g_sck_recv(int sck, void *ptr, int len, int flags) diff --git a/xorg/server/module/rdpMisc.h b/xorg/server/module/rdpMisc.h index 976f26c8..58f6bd31 100644 --- a/xorg/server/module/rdpMisc.h +++ b/xorg/server/module/rdpMisc.h @@ -29,6 +29,8 @@ the rest int rdpBitsPerPixel(int depth); int +g_sck_can_recv(int sck, int millis); +int g_sck_recv(int sck, void *ptr, int len, int flags); void g_sck_close(int sck); diff --git a/xorg/server/module/rdpPixmap.h b/xorg/server/module/rdpPixmap.h index 0ab10a3f..7fce3186 100644 --- a/xorg/server/module/rdpPixmap.h +++ b/xorg/server/module/rdpPixmap.h @@ -24,13 +24,8 @@ pixmap calls #ifndef __RDPPIXMAP_H #define __RDPPIXAMP_H -#ifndef XORG_VERSION_NUMERIC -#warning XORG_VERSION_NUMERIC not defined, need #include -#endif - -#ifndef XORG_VERSION_CURRENT -#warning XORG_VERSION_CURRENT not defined -#endif +#include +#include #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 5, 0, 0, 0) /* 1.1, 1.2, 1.3, 1.4 */ diff --git a/xorg/server/module/rdpPolyArc.c b/xorg/server/module/rdpPolyArc.c index c669c650..9a701dd8 100644 --- a/xorg/server/module/rdpPolyArc.c +++ b/xorg/server/module/rdpPolyArc.c @@ -32,13 +32,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) /******************************************************************************/ -void +static void rdpPolyArcOrg(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs) { GC_OP_VARS; @@ -52,7 +54,49 @@ rdpPolyArcOrg(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs) void rdpPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs) { - LLOGLN(10, ("rdpPolyArc:")); + rdpPtr dev; + BoxRec box; + int index; + int cd; + int lw; + int extra; + RegionRec clip_reg; + RegionRec reg; + + LLOGLN(0, ("rdpPolyArc:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpPolyArcCallCount++; + rdpRegionInit(®, NullBox, 0); + if (narcs > 0) + { + lw = pGC->lineWidth; + if (lw == 0) + { + lw = 1; + } + extra = lw / 2; + for (index = 0; index < narcs; index++) + { + box.x1 = (parcs[index].x - extra) + pDrawable->x; + box.y1 = (parcs[index].y - extra) + pDrawable->y; + box.x2 = box.x1 + parcs[index].width + lw; + box.y2 = box.y1 + parcs[index].height + lw; + rdpRegionUnionRect(®, &box); + } + } + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpPolyArc: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rdpPolyArcOrg(pDrawable, pGC, narcs, parcs); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpPolyFillArc.c b/xorg/server/module/rdpPolyFillArc.c index 62d16675..437929ae 100644 --- a/xorg/server/module/rdpPolyFillArc.c +++ b/xorg/server/module/rdpPolyFillArc.c @@ -32,13 +32,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) /******************************************************************************/ -void +static void rdpPolyFillArcOrg(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs) { GC_OP_VARS; @@ -52,7 +54,49 @@ rdpPolyFillArcOrg(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs) void rdpPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs) { + rdpPtr dev; + BoxRec box; + int index; + int cd; + int lw; + int extra; + RegionRec clip_reg; + RegionRec reg; + LLOGLN(10, ("rdpPolyFillArc:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpPolyFillArcCallCount++; + rdpRegionInit(®, NullBox, 0); + if (narcs > 0) + { + lw = pGC->lineWidth; + if (lw == 0) + { + lw = 1; + } + extra = lw / 2; + for (index = 0; index < narcs; index++) + { + box.x1 = (parcs[index].x - extra) + pDrawable->x; + box.y1 = (parcs[index].y - extra) + pDrawable->y; + box.x2 = box.x1 + parcs[index].width + lw; + box.y2 = box.y1 + parcs[index].height + lw; + rdpRegionUnionRect(®, &box); + } + } + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpPolyFillArc: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rdpPolyFillArcOrg(pDrawable, pGC, narcs, parcs); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpPolyFillRect.c b/xorg/server/module/rdpPolyFillRect.c index afcdf3cc..f61202b2 100644 --- a/xorg/server/module/rdpPolyFillRect.c +++ b/xorg/server/module/rdpPolyFillRect.c @@ -39,14 +39,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) -/******************************************************************************/ -static void -rdpPolyFillRectPre(rdpPtr dev, rdpClientCon *clientCon, - int cd, RegionPtr clip_reg, - DrawablePtr pDrawable, GCPtr pGC, RegionPtr fill_reg) -{ -} - /******************************************************************************/ static void rdpPolyFillRectOrg(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, @@ -59,72 +51,35 @@ rdpPolyFillRectOrg(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, GC_OP_EPILOGUE(pGC); } -/******************************************************************************/ -static void -rdpPolyFillRectPost(rdpPtr dev, rdpClientCon *clientCon, - int cd, RegionPtr clip_reg, - DrawablePtr pDrawable, GCPtr pGC, RegionPtr fill_reg) -{ - BoxRec box; - WindowPtr pDstWnd; - - if (cd == 0) - { - return; - } - if (pDrawable->type != DRAWABLE_WINDOW) - { - return; - } - pDstWnd = (WindowPtr) pDrawable; - if (pDstWnd->viewable == FALSE) - { - return; - } - if (cd == 2) - { - rdpRegionIntersect(fill_reg, clip_reg, fill_reg); - } - rdpClientConAddDirtyScreenReg(dev, clientCon, fill_reg); -} - /******************************************************************************/ void rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, xRectangle *prectInit) { rdpPtr dev; - rdpClientCon *clientCon; RegionRec clip_reg; - RegionPtr fill_reg; + RegionPtr reg; int cd; LLOGLN(10, ("rdpPolyFillRect:")); dev = rdpGetDevFromScreen(pGC->pScreen); - + dev->counts.rdpPolyFillRectCallCount++; /* make a copy of rects */ - fill_reg = rdpRegionFromRects(nrectFill, prectInit, CT_NONE); - rdpRegionTranslate(fill_reg, pDrawable->x, pDrawable->y); - + reg = rdpRegionFromRects(nrectFill, prectInit, CT_NONE); + rdpRegionTranslate(reg, pDrawable->x, pDrawable->y); rdpRegionInit(&clip_reg, NullBox, 0); cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); - LLOGLN(0, ("rdpPolyFillRect: cd %d", cd)); - clientCon = dev->clientConHead; - while (clientCon != NULL) + LLOGLN(10, ("rdpPolyFillRect: cd %d", cd)); + if (cd == XRDP_CD_CLIP) { - rdpPolyFillRectPre(dev, clientCon, cd, &clip_reg, pDrawable, - pGC, fill_reg); - clientCon = clientCon->next; + rdpRegionIntersect(reg, &clip_reg, reg); } /* do original call */ rdpPolyFillRectOrg(pDrawable, pGC, nrectFill, prectInit); - clientCon = dev->clientConHead; - while (clientCon != NULL) + if (cd != XRDP_CD_NODRAW) { - rdpPolyFillRectPost(dev, clientCon, cd, &clip_reg, pDrawable, - pGC, fill_reg); - clientCon = clientCon->next; + rdpClientConAddAllReg(dev, reg, pDrawable); } - RegionUninit(&clip_reg); - rdpRegionDestroy(fill_reg); + rdpRegionUninit(&clip_reg); + rdpRegionDestroy(reg); } diff --git a/xorg/server/module/rdpPolyGlyphBlt.c b/xorg/server/module/rdpPolyGlyphBlt.c index f1fae911..e43e676b 100644 --- a/xorg/server/module/rdpPolyGlyphBlt.c +++ b/xorg/server/module/rdpPolyGlyphBlt.c @@ -32,6 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -56,7 +58,30 @@ rdpPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase) { - LLOGLN(10, ("rdpPolyGlyphBlt:")); + rdpPtr dev; + RegionRec clip_reg; + RegionRec reg; + int cd; + BoxRec box; + + LLOGLN(0, ("rdpPolyGlyphBlt:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpPolyGlyphBltCallCount++; + GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box); + rdpRegionInit(®, &box, 0); + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpPolyGlyphBlt: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rdpPolyGlyphBltOrg(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpPolyPoint.c b/xorg/server/module/rdpPolyPoint.c index eb6f55dd..5dfac5ef 100644 --- a/xorg/server/module/rdpPolyPoint.c +++ b/xorg/server/module/rdpPolyPoint.c @@ -32,13 +32,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) /******************************************************************************/ -void +static void rdpPolyPointOrg(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr in_pts) { @@ -54,7 +56,38 @@ void rdpPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr in_pts) { + rdpPtr dev; + RegionRec clip_reg; + RegionRec reg; + int cd; + int index; + BoxRec box; + LLOGLN(10, ("rdpPolyPoint:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpPolyPointCallCount++; + rdpRegionInit(®, NullBox, 0); + for (index = 0; index < npt; index++) + { + box.x1 = in_pts[index].x + pDrawable->x; + box.y1 = in_pts[index].y + pDrawable->y; + box.x2 = box.x1 + 1; + box.y2 = box.y1 + 1; + rdpRegionUnionRect(®, &box); + } + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpPolyPoint: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rdpPolyPointOrg(pDrawable, pGC, mode, npt, in_pts); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpPolyRectangle.c b/xorg/server/module/rdpPolyRectangle.c index b6f56daa..18311907 100644 --- a/xorg/server/module/rdpPolyRectangle.c +++ b/xorg/server/module/rdpPolyRectangle.c @@ -32,6 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -50,12 +52,81 @@ rdpPolyRectangleOrg(DrawablePtr pDrawable, GCPtr pGC, int nrects, } /******************************************************************************/ -/* tested with pGC->lineWidth = 0, 1, 2, 4 and opcodes 3 and 6 */ void rdpPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects, xRectangle *rects) { + rdpPtr dev; + BoxRec box; + int index; + int up; + int down; + int lw; + int cd; + int x1; + int y1; + int x2; + int y2; + RegionRec clip_reg; + RegionRec reg; + LLOGLN(10, ("rdpPolyRectangle:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpPolyRectangleCallCount++; + rdpRegionInit(®, NullBox, 0); + lw = pGC->lineWidth; + if (lw < 1) + { + lw = 1; + } + up = lw / 2; + down = 1 + (lw - 1) / 2; + index = 0; + while (index < nrects) + { + x1 = rects[index].x + pDrawable->x; + y1 = rects[index].y + pDrawable->y; + x2 = x1 + rects[index].width; + y2 = y1 + rects[index].height; + /* top */ + box.x1 = x1 - up; + box.y1 = y1 - up; + box.x2 = x2 + down; + box.y2 = y1 + down; + rdpRegionUnionRect(®, &box); + /* left */ + box.x1 = x1 - up; + box.y1 = y1 - up; + box.x2 = x1 + down; + box.y2 = y2 + down; + rdpRegionUnionRect(®, &box); + /* right */ + box.x1 = x2 - up; + box.y1 = y1 - up; + box.x2 = x2 + down; + box.y2 = y2 + down; + rdpRegionUnionRect(®, &box); + /* bottom */ + box.x1 = x1 - up; + box.y1 = y2 - up; + box.x2 = x2 + down; + box.y2 = y2 + down; + rdpRegionUnionRect(®, &box); + index++; + } + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpPolyRectangle: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rdpPolyRectangleOrg(pDrawable, pGC, nrects, rects); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpPolySegment.c b/xorg/server/module/rdpPolySegment.c index 0e388f08..98e4eb1f 100644 --- a/xorg/server/module/rdpPolySegment.c +++ b/xorg/server/module/rdpPolySegment.c @@ -32,6 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -52,7 +54,46 @@ rdpPolySegmentOrg(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment *pSegs) void rdpPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment *pSegs) { + rdpPtr dev; + RegionRec clip_reg; + RegionRec reg; + int cd; + int index; + int x1; + int y1; + int x2; + int y2; + BoxRec box; + LLOGLN(10, ("rdpPolySegment:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpPolySegmentCallCount++; + rdpRegionInit(®, NullBox, 0); + for (index = 0; index < nseg; index++) + { + x1 = pSegs[index].x1 + pDrawable->x; + y1 = pSegs[index].y1 + pDrawable->y; + x2 = pSegs[index].x2 + pDrawable->x; + y2 = pSegs[index].y2 + pDrawable->y; + box.x1 = RDPMIN(x1, x2); + box.y1 = RDPMIN(y1, y2); + box.x2 = RDPMAX(x1, x2) + 1; + box.y2 = RDPMAX(y1, y2) + 1; + rdpRegionUnionRect(®, &box); + } + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpPolySegment: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rdpPolySegmentOrg(pDrawable, pGC, nseg, pSegs); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpPolyText16.c b/xorg/server/module/rdpPolyText16.c index 7617bef8..90d68a8c 100644 --- a/xorg/server/module/rdpPolyText16.c +++ b/xorg/server/module/rdpPolyText16.c @@ -32,13 +32,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) /******************************************************************************/ -int +static int rdpPolyText16Org(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, unsigned short *chars) { @@ -57,9 +59,31 @@ rdpPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, unsigned short *chars) { int rv; + rdpPtr dev; + RegionRec clip_reg; + RegionRec reg; + int cd; + BoxRec box; LLOGLN(10, ("rdpPolyText16:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpPolyText16CallCount++; + GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); + rdpRegionInit(®, &box, 0); + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpPolyText16: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rv = rdpPolyText16Org(pDrawable, pGC, x, y, count, chars); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); return rv; } diff --git a/xorg/server/module/rdpPolyText8.c b/xorg/server/module/rdpPolyText8.c index 6592e811..630bc04e 100644 --- a/xorg/server/module/rdpPolyText8.c +++ b/xorg/server/module/rdpPolyText8.c @@ -32,13 +32,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) /******************************************************************************/ -int +static int rdpPolyText8Org(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, char *chars) { @@ -57,9 +59,31 @@ rdpPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, char *chars) { int rv; + rdpPtr dev; + RegionRec clip_reg; + RegionRec reg; + int cd; + BoxRec box; LLOGLN(10, ("rdpPolyText8:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpPolyText8CallCount++; + GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); + rdpRegionInit(®, &box, 0); + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpPolyText8: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rv = rdpPolyText8Org(pDrawable, pGC, x, y, count, chars); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); return rv; } diff --git a/xorg/server/module/rdpPolylines.c b/xorg/server/module/rdpPolylines.c index 015aa26a..da979e9f 100644 --- a/xorg/server/module/rdpPolylines.c +++ b/xorg/server/module/rdpPolylines.c @@ -32,6 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -54,7 +56,46 @@ void rdpPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr pptInit) { + rdpPtr dev; + RegionRec clip_reg; + RegionRec reg; + int cd; + int index; + int x1; + int y1; + int x2; + int y2; + BoxRec box; + LLOGLN(10, ("rdpPolylines:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpPolylinesCallCount++; + rdpRegionInit(®, NullBox, 0); + for (index = 1; index < npt; index++) + { + x1 = pptInit[index - 1].x + pDrawable->x; + y1 = pptInit[index - 1].y + pDrawable->y; + x2 = pptInit[index].x + pDrawable->x; + y2 = pptInit[index].y + pDrawable->y; + box.x1 = RDPMIN(x1, x2); + box.y1 = RDPMIN(y1, y2); + box.x2 = RDPMAX(x1, x2) + 1; + box.y2 = RDPMAX(y1, y2) + 1; + rdpRegionUnionRect(®, &box); + } + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpPolylines: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rdpPolylinesOrg(pDrawable, pGC, mode, npt, pptInit); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpPri.h b/xorg/server/module/rdpPri.h index 625947a3..97e570f5 100644 --- a/xorg/server/module/rdpPri.h +++ b/xorg/server/module/rdpPri.h @@ -1,5 +1,5 @@ /* -Copyright 2013 Jay Sorg +Copyright 2013-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpPushPixels.c b/xorg/server/module/rdpPushPixels.c index aa392578..8ab046b8 100644 --- a/xorg/server/module/rdpPushPixels.c +++ b/xorg/server/module/rdpPushPixels.c @@ -54,7 +54,7 @@ void rdpPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst, int w, int h, int x, int y) { - LLOGLN(10, ("rdpPushPixels:")); + LLOGLN(0, ("rdpPushPixels:")); /* do original call */ rdpPushPixelsOrg(pGC, pBitMap, pDst, w, h, x, y); } diff --git a/xorg/server/module/rdpPutImage.c b/xorg/server/module/rdpPutImage.c index 9a7d49b2..b7134479 100644 --- a/xorg/server/module/rdpPutImage.c +++ b/xorg/server/module/rdpPutImage.c @@ -32,6 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -55,7 +57,33 @@ void rdpPutImage(DrawablePtr pDst, GCPtr pGC, int depth, int x, int y, int w, int h, int leftPad, int format, char *pBits) { + rdpPtr dev; + RegionRec clip_reg; + RegionRec reg; + int cd; + BoxRec box; + LLOGLN(10, ("rdpPutImage:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpPutImageCallCount++; + box.x1 = x + pDst->x; + box.y1 = y + pDst->y; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + rdpRegionInit(®, &box, 0); + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDst, pGC); + LLOGLN(10, ("rdpPutImage: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rdpPutImageOrg(pDst, pGC, depth, x, y, w, h, leftPad, format, pBits); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDst); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpRandR.c b/xorg/server/module/rdpRandR.c index c90c0303..37577645 100644 --- a/xorg/server/module/rdpRandR.c +++ b/xorg/server/module/rdpRandR.c @@ -27,6 +27,7 @@ RandR draw calls /* this should be before all X11 .h files */ #include +#include /* all driver need this */ #include @@ -141,8 +142,13 @@ rdpRRScreenSetSize(ScreenPtr pScreen, CARD16 width, CARD16 height, RRGetInfo(pScreen, 1); LLOGLN(0, (" screen resized to %dx%d", pScreen->width, pScreen->height)); RRScreenSizeNotify(pScreen); +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 13, 0, 0, 0) xf86EnableDisableFBAccess(pScreen->myNum, FALSE); xf86EnableDisableFBAccess(pScreen->myNum, TRUE); +#else + xf86EnableDisableFBAccess(xf86Screens[pScreen->myNum], FALSE); + xf86EnableDisableFBAccess(xf86Screens[pScreen->myNum], TRUE); +#endif return TRUE; } diff --git a/xorg/server/module/rdpReg.c b/xorg/server/module/rdpReg.c index 437b7969..8ff7d79d 100644 --- a/xorg/server/module/rdpReg.c +++ b/xorg/server/module/rdpReg.c @@ -233,3 +233,33 @@ rdpRegionBreak(RegionPtr pReg) return RegionBreak(pReg); #endif } + +/*****************************************************************************/ +void +rdpRegionUnionRect(RegionPtr pReg, BoxPtr prect) +{ + RegionRec reg; + + rdpRegionInit(®, prect, 0); + rdpRegionUnion(pReg, pReg, ®); + rdpRegionUninit(®); +} + +/*****************************************************************************/ +int +rdpRegionPixelCount(RegionPtr pReg) +{ + int index; + int count; + int rv; + BoxRec box; + + rv = 0; + count = REGION_NUM_RECTS(pReg); + for (index = 0; index < count; index++) + { + box = REGION_RECTS(pReg)[index]; + rv += (box.x2 - box.x1) * (box.y2 - box.y1); + } + return rv; +} diff --git a/xorg/server/module/rdpReg.h b/xorg/server/module/rdpReg.h index 2d640c00..a5cd73bf 100644 --- a/xorg/server/module/rdpReg.h +++ b/xorg/server/module/rdpReg.h @@ -56,5 +56,9 @@ void rdpRegionReset(RegionPtr pReg, BoxPtr pBox); Bool rdpRegionBreak(RegionPtr pReg); +void +rdpRegionUnionRect(RegionPtr pReg, BoxPtr prect); +int +rdpRegionPixelCount(RegionPtr pReg); #endif diff --git a/xorg/server/module/rdpTrapezoids.c b/xorg/server/module/rdpTrapezoids.c new file mode 100644 index 00000000..212780ce --- /dev/null +++ b/xorg/server/module/rdpTrapezoids.c @@ -0,0 +1,87 @@ +/* +Copyright 2014 Jay Sorg + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + +#include +#include +#include + +/* this should be before all X11 .h files */ +#include + +/* all driver need this */ +#include +#include + +#include +#include + +#include "rdp.h" +#include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" +#include "rdpTrapezoids.h" + +/******************************************************************************/ +#define LOG_LEVEL 1 +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +/******************************************************************************/ +static void +rdpTrapezoidsOrg(PictureScreenPtr ps, rdpPtr dev, + CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int ntrap, xTrapezoid *traps) +{ + ps->Trapezoids = dev->Trapezoids; + ps->Trapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps); + ps->Trapezoids = rdpTrapezoids; +} + +/******************************************************************************/ +void +rdpTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int ntrap, xTrapezoid *traps) +{ + ScreenPtr pScreen; + rdpPtr dev; + PictureScreenPtr ps; + BoxRec box; + RegionRec reg; + + LLOGLN(10, ("rdpTrapezoids:")); + pScreen = pDst->pDrawable->pScreen; + dev = rdpGetDevFromScreen(pScreen); + dev->counts.rdpTrapezoidsCallCount++; + miTrapezoidBounds(ntrap, traps, &box); + box.x1 += pDst->pDrawable->x; + box.y1 += pDst->pDrawable->y; + box.x2 += pDst->pDrawable->x; + box.y2 += pDst->pDrawable->y; + rdpRegionInit(®, &box, 0); + ps = GetPictureScreen(pScreen); + /* do original call */ + rdpTrapezoidsOrg(ps, dev, op, pSrc, pDst, maskFormat, xSrc, ySrc, + ntrap, traps); + rdpClientConAddAllReg(dev, ®, pDst->pDrawable); + rdpRegionUninit(®); +} diff --git a/xorg/server/module/rdpTrapezoids.h b/xorg/server/module/rdpTrapezoids.h new file mode 100644 index 00000000..77738dc4 --- /dev/null +++ b/xorg/server/module/rdpTrapezoids.h @@ -0,0 +1,30 @@ +/* +Copyright 2014 Jay Sorg + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + +#ifndef _RDPTRAPEZOIDS_H +#define _RDPTRAPEZOIDS_H + +void +rdpTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int ntrap, xTrapezoid *traps); + +#endif diff --git a/xorg/server/readme.txt b/xorg/server/readme.txt index dce66306..28bbc692 100644 --- a/xorg/server/readme.txt +++ b/xorg/server/readme.txt @@ -1,7 +1,16 @@ -Notes for building xrdpdev_drv.so and libxorgxrdp.so +------------------------------------------------------ + Notes for building xrdpdev_drv.so and libxorgxrdp.so +------------------------------------------------------ +Pre-requisites: + o sudo apt-get install xserver-xorg-dev +quick and easy way to build and run the driver + o cd xorg/server + o ./test-in-home.sh + + o see /etc/X11/xrdp/xorg.conf to see how things are configured to run it create /etc/X11/xrdp diff --git a/xorg/server/xrdpdev/xrdpdev.c b/xorg/server/xrdpdev/xrdpdev.c index 6c8f54d7..7e5959ba 100644 --- a/xorg/server/xrdpdev/xrdpdev.c +++ b/xorg/server/xrdpdev/xrdpdev.c @@ -47,6 +47,7 @@ This is the main driver file #include "rdpRandR.h" #include "rdpMisc.h" #include "rdpComposite.h" +#include "rdpTrapezoids.h" #include "rdpGlyphs.h" #include "rdpPixmap.h" #include "rdpClientCon.h" @@ -410,7 +411,11 @@ rdpWakeupHandler1(pointer blockData, int result, pointer pReadmask) /*****************************************************************************/ static Bool +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 13, 0, 0, 0) rdpScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) +#else +rdpScreenInit(ScreenPtr pScreen, int argc, char **argv) +#endif { ScrnInfoPtr pScrn; rdpPtr dev; @@ -418,7 +423,7 @@ rdpScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) Bool vis_found; PictureScreenPtr ps; - pScrn = xf86Screens[scrnIndex]; + pScrn = xf86Screens[pScreen->myNum]; dev = XRDPPTR(pScrn); dev->pScreen = pScreen; @@ -531,6 +536,9 @@ rdpScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) /* glyphs */ dev->Glyphs = ps->Glyphs; ps->Glyphs = rdpGlyphs; + /* trapezoids */ + dev->Trapezoids = ps->Trapezoids; + ps->Trapezoids = rdpTrapezoids; } RegisterBlockAndWakeupHandlers(rdpBlockHandler1, rdpWakeupHandler1, pScreen); @@ -552,7 +560,11 @@ rdpScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) /*****************************************************************************/ static Bool +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 13, 0, 0, 0) rdpSwitchMode(int a, DisplayModePtr b, int c) +#else +rdpSwitchMode(ScrnInfoPtr a, DisplayModePtr b) +#endif { LLOGLN(0, ("rdpSwitchMode:")); return TRUE; @@ -560,14 +572,22 @@ rdpSwitchMode(int a, DisplayModePtr b, int c) /*****************************************************************************/ static void +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 13, 0, 0, 0) rdpAdjustFrame(int a, int b, int c, int d) +#else +rdpAdjustFrame(ScrnInfoPtr a, int b, int c) +#endif { LLOGLN(10, ("rdpAdjustFrame:")); } /*****************************************************************************/ static Bool +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 13, 0, 0, 0) rdpEnterVT(int a, int b) +#else +rdpEnterVT(ScrnInfoPtr a) +#endif { LLOGLN(0, ("rdpEnterVT:")); return TRUE; @@ -575,14 +595,22 @@ rdpEnterVT(int a, int b) /*****************************************************************************/ static void +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 13, 0, 0, 0) rdpLeaveVT(int a, int b) +#else +rdpLeaveVT(ScrnInfoPtr a) +#endif { LLOGLN(0, ("rdpLeaveVT:")); } /*****************************************************************************/ static ModeStatus +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 13, 0, 0, 0) rdpValidMode(int a, DisplayModePtr b, Bool c, int d) +#else +rdpValidMode(ScrnInfoPtr a, DisplayModePtr b, Bool c, int d) +#endif { LLOGLN(0, ("rdpValidMode:")); return 0; diff --git a/xorg/server/xrdpmouse/rdpMouse.c b/xorg/server/xrdpmouse/rdpMouse.c index a2092d46..2d8213cd 100644 --- a/xorg/server/xrdpmouse/rdpMouse.c +++ b/xorg/server/xrdpmouse/rdpMouse.c @@ -98,18 +98,16 @@ l_bound_by(int val, int low, int high) static void rdpEnqueueMotion(DeviceIntPtr device, int x, int y) { - int valuators[2]; - - valuators[0] = x; - valuators[1] = y; - xf86PostMotionEvent(device, TRUE, 0, 2, valuators); + LLOGLN(10, ("rdpEnqueueMotion:")); + xf86PostMotionEvent(device, TRUE, 0, 2, x, y); } /******************************************************************************/ static void rdpEnqueueButton(DeviceIntPtr device, int type, int buttons) { - xf86PostButtonEvent(device, FALSE, buttons, type, 0, 0); + LLOGLN(10, ("rdpEnqueueButton:")); + xf86PostButtonEvent(device, FALSE, buttons, type == ButtonPress, 0, 0); } /******************************************************************************/ @@ -122,6 +120,8 @@ PtrAddEvent(rdpPointer *pointer) rdpEnqueueMotion(pointer->device, pointer->cursor_x, pointer->cursor_y); + LLOGLN(10, ("PtrAddEvent: x %d y %d", pointer->cursor_x, pointer->cursor_y)); + for (i = 0; i < 5; i++) { if ((pointer->button_mask ^ pointer->old_button_mask) & (1 << i)) @@ -152,7 +152,8 @@ rdpInputMouse(rdpPtr dev, int msg, { rdpPointer *pointer; - LLOGLN(10, ("rdpInputMouse:")); + LLOGLN(10, ("rdpInputMouse: msg %d param1 %ld param2 %ld param3 %ld param4 %ld", + msg, param1, param2, param3, param4)); pointer = &(dev->pointer); switch (msg) { diff --git a/xrdp/Makefile.am b/xrdp/Makefile.am index 83d04a6c..71d84a33 100644 --- a/xrdp/Makefile.am +++ b/xrdp/Makefile.am @@ -1,4 +1,4 @@ -EXTRA_DIST = xrdp.ini ad24b.bmp ad256.bmp xrdp24b.bmp xrdp256.bmp sans-10.fv1 cursor0.cur cursor1.cur xrdp.h xrdp_types.h +EXTRA_DIST = xrdp.ini ad24b.bmp ad256.bmp xrdp24b.bmp xrdp256.bmp xrdp_logo.bmp sans-10.fv1 cursor0.cur cursor1.cur xrdp.h xrdp_types.h EXTRA_INCLUDES = EXTRA_LIBS = @@ -66,6 +66,7 @@ xrdppkgdata_DATA = \ ad256.bmp \ xrdp24b.bmp \ xrdp256.bmp \ + xrdp_logo.bmp \ sans-10.fv1 \ cursor0.cur \ cursor1.cur diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h index 172d417a..a778058f 100644 --- a/xrdp/xrdp.h +++ b/xrdp/xrdp.h @@ -108,6 +108,8 @@ xrdp_wm_send_bitmap(struct xrdp_wm* self, struct xrdp_bitmap* bitmap, int x, int y, int cx, int cy); int APP_CC xrdp_wm_set_pointer(struct xrdp_wm* self, int cache_idx); +unsigned int APP_CC +xrdp_wm_htoi (const char *ptr); int APP_CC xrdp_wm_set_focused(struct xrdp_wm* self, struct xrdp_bitmap* wnd); int APP_CC @@ -349,6 +351,8 @@ get_keymaps(int keylayout, struct xrdp_keymap* keymap); /* xrdp_login_wnd.c */ int APP_CC xrdp_login_wnd_create(struct xrdp_wm* self); +int APP_CC +load_xrdp_config(struct xrdp_config *config, int bpp); /* xrdp_bitmap_compress.c */ int APP_CC @@ -398,6 +402,10 @@ server_composite(struct xrdp_mod* mod, int srcidx, int srcformat, int srcwidth, int srcx, int srcy, int mskx, int msky, int dstx, int dsty, int width, int height, int dstformat); int DEFAULT_CC +server_paint_rects(struct xrdp_mod* mod, int num_drects, short *drects, + int num_crects, short *crects, + char *data, int width, int height, int flags); +int DEFAULT_CC server_set_pointer(struct xrdp_mod* mod, int x, int y, char* data, char* mask); int DEFAULT_CC diff --git a/xrdp/xrdp.ini b/xrdp/xrdp.ini index f89e78d9..56357794 100644 --- a/xrdp/xrdp.ini +++ b/xrdp/xrdp.ini @@ -1,5 +1,7 @@ - [globals] +# xrdp.ini file version number +ini_version=1 + bitmap_cache=yes bitmap_compression=yes port=3389 @@ -7,16 +9,25 @@ crypt_level=high allow_channels=true max_bpp=24 fork=yes + # regulate if the listening socket use socket option tcp_nodelay # no buffering will be performed in the TCP stack tcp_nodelay=yes + # regulate if the listening socket use socket option keepalive # if the network connection disappear without close messages the connection will be closed tcp_keepalive=yes + #tcp_send_buffer_bytes=32768 #tcp_recv_buffer_bytes=32768 + +# +# colors used by windows in RGB format +# + +blue=009cb5 +grey=dedede #black=000000 -#grey=d6d3ce #dark_grey=808080 #blue=08246b #dark_blue=08246b @@ -31,6 +42,7 @@ tcp_keepalive=yes # require_credentials=yes #bulk_compression=yes + # You can set the PAM error text in a gateway setup (MAX 256 chars) #pamerrortxt=change your password according to policy at http://url #new_cursors=no @@ -39,6 +51,47 @@ allow_multimon=true # fastpath - can be set to input / output / both / none use_fastpath=input +# +# configure login screen +# + +# top level window background color in RGB format +ls_top_window_bg_color=009cb5 + +# width and height of login screen +ls_width=350 +ls_height=430 + +# login screen background color in RGB format +ls_bg_color=dedede + +# logo +ls_logo_filename= +ls_logo_x_pos=55 +ls_logo_y_pos=50 + +# for positioning labels such as username, password etc +ls_label_x_pos=30 +ls_label_width=60 + +# for positioning text and combo boxes next to above labels +ls_input_x_pos=110 +ls_input_width=210 + +# y pos for first label and combo box +ls_input_y_pos=220 + +# OK button +ls_btn_ok_x_pos=142 +ls_btn_ok_y_pos=370 +ls_btn_ok_width=85 +ls_btn_ok_height=30 + +# Cancel button +ls_btn_cancel_x_pos=237 +ls_btn_cancel_y_pos=370 +ls_btn_cancel_width=85 +ls_btn_cancel_height=30 [Logging] LogFile=xrdp.log @@ -125,6 +178,7 @@ ip=ask port=ask3389 username=ask password=ask + # You can override the common channel settings for each session type #channel.rdpdr=true #channel.rdpsnd=true diff --git a/xrdp/xrdp_bitmap.c b/xrdp/xrdp_bitmap.c index b3faea41..c3eef7a1 100644 --- a/xrdp/xrdp_bitmap.c +++ b/xrdp/xrdp_bitmap.c @@ -115,7 +115,7 @@ xrdp_bitmap_create(int width, int height, int bpp, self->child_list = list_create(); } - self->line_size = width *Bpp; + self->line_size = width * Bpp; if (self->type == WND_TYPE_COMBO) { diff --git a/xrdp/xrdp_login_wnd.c b/xrdp/xrdp_login_wnd.c index e7066798..2e53fca5 100644 --- a/xrdp/xrdp_login_wnd.c +++ b/xrdp/xrdp_login_wnd.c @@ -254,6 +254,9 @@ xrdp_wm_show_edits(struct xrdp_wm *self, struct xrdp_bitmap *combo) char *value; struct xrdp_mod_data *mod; struct xrdp_bitmap *b; + struct xrdp_cfg_globals *globals; + + globals = &self->xrdp_config->cfg_globals; username_set = 0; @@ -289,11 +292,13 @@ xrdp_wm_show_edits(struct xrdp_wm *self, struct xrdp_bitmap *combo) insert_index++; b->parent = self->login_window; b->owner = self->login_window; - b->left = self->login_window->width >= DEFAULT_WND_LOGIN_W ? 155 : 5; - b->top = DEFAULT_ELEMENT_TOP + DEFAULT_COMBO_H + 5 + (DEFAULT_EDIT_H + 5) * count; + b->left = globals->ls_label_x_pos; + + b->top = globals->ls_input_y_pos + DEFAULT_COMBO_H + 5 + (DEFAULT_EDIT_H + 5) * count; b->id = 100 + 2 * count; name = (char *)list_get_item(mod->names, index); set_string(&b->caption1, name); + /* edit */ b = xrdp_bitmap_create(DEFAULT_EDIT_W, DEFAULT_EDIT_H, self->screen->bpp, WND_TYPE_EDIT, self); @@ -302,8 +307,10 @@ xrdp_wm_show_edits(struct xrdp_wm *self, struct xrdp_bitmap *combo) insert_index++; b->parent = self->login_window; b->owner = self->login_window; - b->left = self->login_window->width >= DEFAULT_WND_LOGIN_W ? DEFAULT_WND_LOGIN_W - DEFAULT_EDIT_W - 30 : 70; - b->top = DEFAULT_ELEMENT_TOP + DEFAULT_COMBO_H + 5 + (DEFAULT_EDIT_H + 5) * count; + b->left = globals->ls_input_x_pos; + + b->top = globals->ls_input_y_pos + DEFAULT_COMBO_H + 5 + (DEFAULT_EDIT_H + 5) * count; + b->id = 100 + 2 * count + 1; b->pointer = 1; b->tab_stop = 1; @@ -506,15 +513,20 @@ xrdp_wm_login_fill_in_combo(struct xrdp_wm *self, struct xrdp_bitmap *b) int APP_CC xrdp_login_wnd_create(struct xrdp_wm *self) { - struct xrdp_bitmap *but; - struct xrdp_bitmap *combo; - char file_path[256]; + struct xrdp_bitmap *but; + struct xrdp_bitmap *combo; + struct xrdp_cfg_globals *globals; + + char buf[256]; + char buf1[256]; int log_width; int log_height; int regular; - log_width = DEFAULT_WND_LOGIN_W; - log_height = DEFAULT_WND_LOGIN_H; + globals = &self->xrdp_config->cfg_globals; + + log_width = globals->ls_width; + log_height = globals->ls_height; regular = 1; if (self->screen->width < log_width) @@ -537,115 +549,393 @@ xrdp_login_wnd_create(struct xrdp_wm *self) list_add_item(self->screen->child_list, (long)self->login_window); self->login_window->parent = self->screen; self->login_window->owner = self->screen; - self->login_window->bg_color = self->grey; + self->login_window->bg_color = globals->ls_bg_color; + 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; - set_string(&self->login_window->caption1, "Login to xrdp"); + + g_gethostname(buf1, 256); + g_sprintf(buf, "Login to %s", buf1); + set_string(&self->login_window->caption1, buf); if (regular) { - /* image */ + /* if logo image not specified, use default */ + if (globals->ls_logo_filename[0] == 0) + g_snprintf(globals->ls_logo_filename, 255, "%s/xrdp_logo.bmp", XRDP_SHARE_PATH); + + /* logo image */ but = xrdp_bitmap_create(4, 4, self->screen->bpp, WND_TYPE_IMAGE, self); - if (self->screen->bpp > 8) - { - g_snprintf(file_path, 255, "%s/xrdp24b.bmp", XRDP_SHARE_PATH); - } - else - { - g_snprintf(file_path, 255, "%s/xrdp256.bmp", XRDP_SHARE_PATH); - } + if (self->screen->bpp <= 8) + g_snprintf(globals->ls_logo_filename, 255, "%s/ad256.bmp", XRDP_SHARE_PATH); - xrdp_bitmap_load(but, file_path, self->palette); - but->parent = self->screen; - but->owner = self->screen; - but->left = self->screen->width - but->width; - but->top = self->screen->height - but->height; - list_add_item(self->screen->child_list, (long)but); - - /* image */ - but = xrdp_bitmap_create(4, 4, self->screen->bpp, WND_TYPE_IMAGE, self); - - if (self->screen->bpp > 8) - { - g_snprintf(file_path, 255, "%s/ad24b.bmp", XRDP_SHARE_PATH); - } - else - { - g_snprintf(file_path, 255, "%s/ad256.bmp", XRDP_SHARE_PATH); - } - - xrdp_bitmap_load(but, file_path, self->palette); + xrdp_bitmap_load(but, globals->ls_logo_filename, self->palette); but->parent = self->login_window; but->owner = self->login_window; - but->left = 10; - but->top = 30; + but->left = globals->ls_logo_x_pos; + but->top = globals->ls_logo_y_pos; list_add_item(self->login_window->child_list, (long)but); } /* label */ - but = xrdp_bitmap_create(60, DEFAULT_EDIT_H, self->screen->bpp, WND_TYPE_LABEL, self); + but = xrdp_bitmap_create(globals->ls_label_width, DEFAULT_EDIT_H, self->screen->bpp, WND_TYPE_LABEL, self); list_add_item(self->login_window->child_list, (long)but); but->parent = self->login_window; but->owner = self->login_window; - but->left = regular ? 155 : 5; - but->top = DEFAULT_ELEMENT_TOP; - set_string(&but->caption1, "Module"); + but->left = globals->ls_label_x_pos; + but->top = globals->ls_input_y_pos; + set_string(&but->caption1, "Session"); /* combo */ - combo = xrdp_bitmap_create(DEFAULT_COMBO_W, DEFAULT_COMBO_H, self->screen->bpp, WND_TYPE_COMBO, self); + combo = xrdp_bitmap_create(globals->ls_input_width, DEFAULT_COMBO_H, + self->screen->bpp, WND_TYPE_COMBO, self); list_add_item(self->login_window->child_list, (long)combo); combo->parent = self->login_window; combo->owner = self->login_window; - combo->left = regular ? DEFAULT_WND_LOGIN_W - DEFAULT_COMBO_W - 30 : 70; - combo->top = DEFAULT_ELEMENT_TOP; + combo->left = globals->ls_input_x_pos; + combo->top = globals->ls_input_y_pos; combo->id = 6; combo->tab_stop = 1; xrdp_wm_login_fill_in_combo(self, combo); - /* button */ - but = xrdp_bitmap_create(DEFAULT_BUTTON_W, DEFAULT_BUTTON_H, self->screen->bpp, WND_TYPE_BUTTON, self); + /* OK button */ + but = xrdp_bitmap_create(globals->ls_btn_ok_width, globals->ls_btn_ok_height, + self->screen->bpp, WND_TYPE_BUTTON, self); list_add_item(self->login_window->child_list, (long)but); but->parent = self->login_window; but->owner = self->login_window; - but->left = regular ? DEFAULT_WND_LOGIN_W - ((DEFAULT_BUTTON_W + 10) * 3) - 10 : 30; - but->top = DEFAULT_WND_LOGIN_H - DEFAULT_BUTTON_H - 15; + but->left = globals->ls_btn_ok_x_pos; + but->top = globals->ls_btn_ok_y_pos; but->id = 3; set_string(&but->caption1, "OK"); but->tab_stop = 1; self->login_window->default_button = but; - /* button */ - but = xrdp_bitmap_create(DEFAULT_BUTTON_W, DEFAULT_BUTTON_H, self->screen->bpp, WND_TYPE_BUTTON, self); + /* Cancel button */ + but = xrdp_bitmap_create(globals->ls_btn_cancel_width, + globals->ls_btn_cancel_height, self->screen->bpp, + WND_TYPE_BUTTON, self); list_add_item(self->login_window->child_list, (long)but); but->parent = self->login_window; but->owner = self->login_window; - but->left = regular ? DEFAULT_WND_LOGIN_W - ((DEFAULT_BUTTON_W + 10) * 2) - 10 : ((log_width - 30) - DEFAULT_BUTTON_W); - but->top = DEFAULT_WND_LOGIN_H - DEFAULT_BUTTON_H - 15; + but->left = globals->ls_btn_cancel_x_pos; + but->top = globals->ls_btn_cancel_y_pos; but->id = 2; set_string(&but->caption1, "Cancel"); but->tab_stop = 1; self->login_window->esc_button = but; - if (regular) - { - /* button */ - but = xrdp_bitmap_create(DEFAULT_BUTTON_W, DEFAULT_BUTTON_H, self->screen->bpp, WND_TYPE_BUTTON, self); - list_add_item(self->login_window->child_list, (long)but); - but->parent = self->login_window; - but->owner = self->login_window; - but->left = DEFAULT_WND_LOGIN_W - (DEFAULT_BUTTON_W + 10) - 10; - but->top = DEFAULT_WND_LOGIN_H - DEFAULT_BUTTON_H - 15; - but->id = 1; - set_string(&but->caption1, "Help"); - but->tab_stop = 1; - } - /* labels and edits */ xrdp_wm_show_edits(self, combo); return 0; } + +/** + * Load configuration from xrdp.ini file + * + * @return 0 on success, -1 on failure + *****************************************************************************/ +int APP_CC +load_xrdp_config(struct xrdp_config *config, int bpp) +{ + struct xrdp_cfg_globals *globals; + + struct list *names; + struct list *values; + + char *n; + char *v; + char buf[256]; + int fd; + int i; + + if (!config) + return -1; + + globals = &config->cfg_globals; + + /* set default values incase we can't get them from xrdp.ini file */ + globals->ini_version = 1; + globals->ls_top_window_bg_color = HCOLOR(bpp, xrdp_wm_htoi("009cb5")); + globals->ls_bg_color = HCOLOR(bpp, xrdp_wm_htoi("dedede")); + globals->ls_width = 350; + globals->ls_height = 350; + globals->ls_bg_color = 0xdedede; + globals->ls_logo_x_pos = 63; + globals->ls_logo_y_pos = 50; + globals->ls_label_x_pos = 30; + globals->ls_label_width = 60; + globals->ls_input_x_pos = 110; + globals->ls_input_width = 210; + globals->ls_input_y_pos = 150; + globals->ls_btn_ok_x_pos = 150; + globals->ls_btn_ok_y_pos = 300; + globals->ls_btn_ok_width = 85; + globals->ls_btn_ok_height =30; + globals->ls_btn_cancel_x_pos = 245; + globals->ls_btn_cancel_y_pos = 300; + globals->ls_btn_cancel_width = 85; + globals->ls_btn_cancel_height = 30; + + /* open xrdp.ini file */ + g_snprintf(buf, 255, "%s/xrdp.ini", XRDP_CFG_PATH); + if ((fd = g_file_open(buf)) < 0) + { + log_message(LOG_LEVEL_ERROR,"load_config: Could not read " + "xrdp.ini file %s", buf); + return -1; + + } + + names = list_create(); + values = list_create(); + names->auto_free = 1; + values->auto_free = 1; + + if (file_read_section(fd, "globals", names, values) != 0) + { + list_delete(names); + list_delete(values); + g_file_close(fd); + log_message(LOG_LEVEL_ERROR,"load_config: Could not read globals " + "section from xrdp.ini file %s", buf); + return -1; + } + + for (i = 0; i < names->count; i++) + { + n = (char *) list_get_item(names, i); + v = (char *) list_get_item(values, i); + + /* + * parse globals section + */ + + if (g_strncmp(n, "ini_version", 64) == 0) + globals->ini_version = g_atoi(v); + + else if (g_strncmp(n, "bitmap_cache", 64) == 0) + globals->use_bitmap_cache = g_text2bool(v); + + else if (g_strncmp(n, "bitmap_compression", 64) == 0) + globals->use_bitmap_compression = g_text2bool(v); + + else if (g_strncmp(n, "port", 64) == 0) + globals->port = g_atoi(v); + + else if (g_strncmp(n, "crypt_level", 64) == 0) + { + if (g_strcmp(v, "low") == 0) + globals->crypt_level = 1; + else if (g_strcmp(v, "medium") == 0) + globals->crypt_level = 2; + else + globals->crypt_level = 3; + } + + else if (g_strncmp(n, "allow_channels", 64) == 0) + globals->allow_channels = g_text2bool(v); + + else if (g_strncmp(n, "max_bpp", 64) == 0) + globals->max_bpp = g_atoi(v); + + else if (g_strncmp(n, "fork", 64) == 0) + globals->fork = g_text2bool(v); + + else if (g_strncmp(n, "tcp_nodelay", 64) == 0) + globals->tcp_nodelay = g_text2bool(v); + + else if (g_strncmp(n, "tcp_keepalive", 64) == 0) + globals->tcp_keepalive = g_text2bool(v); + + else if (g_strncmp(n, "tcp_send_buffer_bytes", 64) == 0) + globals->tcp_send_buffer_bytes = g_atoi(v); + + else if (g_strncmp(n, "tcp_recv_buffer_bytes", 64) == 0) + globals->tcp_recv_buffer_bytes = g_atoi(v); + + /* colors */ + + else if (g_strncmp(n, "grey", 64) == 0) + globals->grey = xrdp_wm_htoi(v); + + else if (g_strncmp(n, "black", 64) == 0) + globals->black = xrdp_wm_htoi(v); + + else if (g_strncmp(n, "dark_grey", 64) == 0) + globals->dark_grey = xrdp_wm_htoi(v); + + else if (g_strncmp(n, "blue", 64) == 0) + globals->blue = xrdp_wm_htoi(v); + + else if (g_strncmp(n, "dark_blue", 64) == 0) + globals->dark_blue = xrdp_wm_htoi(v); + + else if (g_strncmp(n, "white", 64) == 0) + globals->white = xrdp_wm_htoi(v); + + else if (g_strncmp(n, "red", 64) == 0) + globals->red = xrdp_wm_htoi(v); + + else if (g_strncmp(n, "green", 64) == 0) + globals->green = xrdp_wm_htoi(v); + + else if (g_strncmp(n, "background", 64) == 0) + globals->background = xrdp_wm_htoi(v); + + /* misc stuff */ + + else if (g_strncmp(n, "autorun", 255) == 0) + g_strncpy(globals->autorun, v, 255); + + else if (g_strncmp(n, "hidelogwindow", 64) == 0) + globals->hidelogwindow = g_text2bool(v); + + else if (g_strncmp(n, "require_credentials", 64) == 0) + globals->require_credentials = g_text2bool(v); + + else if (g_strncmp(n, "bulk_compression", 64) == 0) + globals->bulk_compression = g_text2bool(v); + + else if (g_strncmp(n, "new_cursors", 64) == 0) + globals->new_cursors = g_text2bool(v); + + else if (g_strncmp(n, "nego_sec_layer", 64) == 0) + globals->nego_sec_layer = g_atoi(v); + + else if (g_strncmp(n, "allow_multimon", 64) == 0) + globals->allow_multimon = g_text2bool(v); + + /* login screen values */ + else if (g_strncmp(n, "ls_top_window_bg_color", 64) == 0) + globals->ls_top_window_bg_color = HCOLOR(bpp, xrdp_wm_htoi(v)); + + else if (g_strncmp(n, "ls_width", 64) == 0) + globals->ls_width = g_atoi(v); + + else if (g_strncmp(n, "ls_height", 64) == 0) + globals->ls_height = g_atoi(v); + + else if (g_strncmp(n, "ls_bg_color", 64) == 0) + globals->ls_bg_color = HCOLOR(bpp, xrdp_wm_htoi(v)); + + else if (g_strncmp(n, "ls_logo_filename", 255) == 0) + { + g_strncpy(globals->ls_logo_filename, v, 255); + globals->ls_logo_filename[255] = 0; + } + + else if (g_strncmp(n, "ls_logo_x_pos", 64) == 0) + globals->ls_logo_x_pos = g_atoi(v); + + else if (g_strncmp(n, "ls_logo_y_pos", 64) == 0) + globals->ls_logo_y_pos = g_atoi(v); + + else if (g_strncmp(n, "ls_label_x_pos", 64) == 0) + globals->ls_label_x_pos = g_atoi(v); + + else if (g_strncmp(n, "ls_label_width", 64) == 0) + globals->ls_label_width = g_atoi(v); + + else if (g_strncmp(n, "ls_input_x_pos", 64) == 0) + globals->ls_input_x_pos = g_atoi(v); + + else if (g_strncmp(n, "ls_input_width", 64) == 0) + globals->ls_input_width = g_atoi(v); + + else if (g_strncmp(n, "ls_input_y_pos", 64) == 0) + globals->ls_input_y_pos = g_atoi(v); + + else if (g_strncmp(n, "ls_btn_ok_x_pos", 64) == 0) + globals->ls_btn_ok_x_pos = g_atoi(v); + + else if (g_strncmp(n, "ls_btn_ok_y_pos", 64) == 0) + globals->ls_btn_ok_y_pos = g_atoi(v); + + else if (g_strncmp(n, "ls_btn_ok_width", 64) == 0) + globals->ls_btn_ok_width = g_atoi(v); + + else if (g_strncmp(n, "ls_btn_ok_height", 64) == 0) + globals->ls_btn_ok_height = g_atoi(v); + + else if (g_strncmp(n, "ls_btn_cancel_x_pos", 64) == 0) + globals->ls_btn_cancel_x_pos = g_atoi(v); + + else if (g_strncmp(n, "ls_btn_cancel_y_pos", 64) == 0) + globals->ls_btn_cancel_y_pos = g_atoi(v); + + else if (g_strncmp(n, "ls_btn_cancel_width", 64) == 0) + globals->ls_btn_cancel_width = g_atoi(v); + + else if (g_strncmp(n, "ls_btn_cancel_height", 64) == 0) + globals->ls_btn_cancel_height = g_atoi(v); + } + +#if 0 + g_writeln("ini_version: %d", globals->ini_version); + g_writeln("use_bitmap_cache: %d", globals->use_bitmap_cache); + g_writeln("use_bitmap_compression: %d", globals->use_bitmap_compression); + g_writeln("port: %d", globals->port); + g_writeln("crypt_level: %d", globals->crypt_level); + g_writeln("allow_channels: %d", globals->allow_channels); + g_writeln("max_bpp: %d", globals->max_bpp); + g_writeln("fork: %d", globals->fork); + g_writeln("tcp_nodelay: %d", globals->tcp_nodelay); + g_writeln("tcp_keepalive: %d", globals->tcp_keepalive); + g_writeln("tcp_send_buffer_bytes: %d", globals->tcp_send_buffer_bytes); + g_writeln("tcp_recv_buffer_bytes: %d", globals->tcp_recv_buffer_bytes); + g_writeln("new_cursors: %d", globals->new_cursors); + g_writeln("allow_multimon: %d", globals->allow_multimon); + + g_writeln("grey: %d", globals->grey); + g_writeln("black: %d", globals->black); + g_writeln("dark_grey: %d", globals->dark_grey); + g_writeln("blue: %d", globals->blue); + g_writeln("dark_blue: %d", globals->dark_blue); + g_writeln("white: %d", globals->white); + g_writeln("red: %d", globals->red); + g_writeln("green: %d", globals->green); + g_writeln("background: %d", globals->background); + + g_writeln("autorun: %s", globals->autorun); + g_writeln("hidelogwindow: %d", globals->hidelogwindow); + g_writeln("require_credentials: %d", globals->require_credentials); + g_writeln("bulk_compression: %d", globals->bulk_compression); + g_writeln("new_cursors: %d", globals->new_cursors); + g_writeln("nego_sec_layer: %d", globals->nego_sec_layer); + g_writeln("allow_multimon: %d", globals->allow_multimon); + + g_writeln("ls_top_window_bg_color: %x", globals->ls_top_window_bg_color); + g_writeln("ls_width: %d", globals->ls_width); + g_writeln("ls_height: %d", globals->ls_height); + g_writeln("ls_bg_color: %x", globals->ls_bg_color); + g_writeln("ls_logo_filename: %s", globals->ls_logo_filename); + g_writeln("ls_logo_x_pos: %d", globals->ls_logo_x_pos); + g_writeln("ls_logo_y_pos: %d", globals->ls_logo_y_pos); + g_writeln("ls_label_x_pos: %d", globals->ls_label_x_pos); + g_writeln("ls_label_width: %d", globals->ls_label_width); + g_writeln("ls_input_x_pos: %d", globals->ls_input_x_pos); + g_writeln("ls_input_width: %d", globals->ls_input_width); + g_writeln("ls_input_y_pos: %d", globals->ls_input_y_pos); + g_writeln("ls_btn_ok_x_pos: %d", globals->ls_btn_ok_x_pos); + g_writeln("ls_btn_ok_y_pos: %d", globals->ls_btn_ok_y_pos); + g_writeln("ls_btn_ok_width: %d", globals->ls_btn_ok_width); + g_writeln("ls_btn_ok_height: %d", globals->ls_btn_ok_height); + g_writeln("ls_btn_cancel_x_pos: %d", globals->ls_btn_cancel_x_pos); + g_writeln("ls_btn_cancel_y_pos: %d", globals->ls_btn_cancel_y_pos); + g_writeln("ls_btn_cancel_width: %d", globals->ls_btn_cancel_width); + g_writeln("ls_btn_cancel_height: %d", globals->ls_btn_cancel_height); +#endif + + list_delete(names); + list_delete(values); + g_file_close(fd); + return 0; +} diff --git a/xrdp/xrdp_logo.bmp b/xrdp/xrdp_logo.bmp new file mode 100644 index 00000000..58ce50ff Binary files /dev/null and b/xrdp/xrdp_logo.bmp differ diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index 560ebedb..494d79d3 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -238,7 +238,7 @@ xrdp_mm_send_login(struct xrdp_mm *self) /*****************************************************************************/ /* returns error */ /* this goes through the login_names looking for one called 'aname' - then it copies the corisponding login_values item into 'dest' + then it copies the corresponding login_values item into 'dest' 'dest' must be at least 'dest_len' + 1 bytes in size */ static int APP_CC xrdp_mm_get_value(struct xrdp_mm *self, char *aname, char *dest, int dest_len) @@ -417,6 +417,7 @@ xrdp_mm_setup_mod1(struct xrdp_mm *self) self->mod->server_create_os_surface_bpp = server_create_os_surface_bpp; self->mod->server_paint_rect_bpp = server_paint_rect_bpp; self->mod->server_composite = server_composite; + self->mod->server_paint_rects = server_paint_rects; } } @@ -692,12 +693,12 @@ xrdp_mm_process_rail_create_window(struct xrdp_mm* self, struct stream* s) int bytes; int rv; struct rail_window_state_order rwso; - + g_memset(&rwso, 0, sizeof(rwso)); in_uint32_le(s, window_id); - + g_writeln("xrdp_mm_process_rail_create_window: 0x%8.8x", window_id); - + in_uint32_le(s, rwso.owner_window_id); in_uint32_le(s, rwso.style); in_uint32_le(s, rwso.extended_style); @@ -771,12 +772,12 @@ xrdp_mm_process_rail_configure_window(struct xrdp_mm* self, struct stream* s) int bytes; int rv; struct rail_window_state_order rwso; - + g_memset(&rwso, 0, sizeof(rwso)); in_uint32_le(s, window_id); - + g_writeln("xrdp_mm_process_rail_configure_window: 0x%8.8x", window_id); - + in_uint32_le(s, rwso.client_offset_x); in_uint32_le(s, rwso.client_offset_y); in_uint32_le(s, rwso.client_area_width); @@ -834,7 +835,7 @@ xrdp_mm_process_rail_destroy_window(struct xrdp_mm* self, struct stream* s) { int window_id; int rv; - + in_uint32_le(s, window_id); g_writeln("xrdp_mm_process_rail_destroy_window 0x%8.8x", window_id); rv = libxrdp_orders_init(self->wm->session); @@ -853,7 +854,7 @@ xrdp_mm_process_rail_show_window(struct xrdp_mm* self, struct stream* s) int rv; int flags; struct rail_window_state_order rwso; - + g_memset(&rwso, 0, sizeof(rwso)); in_uint32_le(s, window_id); in_uint32_le(s, flags); @@ -877,13 +878,13 @@ xrdp_mm_process_rail_update_window_text(struct xrdp_mm* self, struct stream* s) int rv = 0; int window_id; struct rail_window_state_order rwso; - + g_writeln("xrdp_mm_process_rail_update_window_text:"); - + in_uint32_le(s, window_id); in_uint32_le(s, flags); g_writeln(" update window title info: 0x%8.8x", window_id); - + g_memset(&rwso, 0, sizeof(rwso)); in_uint32_le(s, size); /* title size */ rwso.title_info = g_malloc(size + 1, 0); @@ -894,7 +895,7 @@ xrdp_mm_process_rail_update_window_text(struct xrdp_mm* self, struct stream* s) rv = libxrdp_window_new_update(self->wm->session, window_id, &rwso, flags); rv = libxrdp_orders_send(self->wm->session); g_writeln(" set window title %s %d", rwso.title_info, rv); - + g_free(rwso.title_info); return rv; @@ -909,14 +910,14 @@ xrdp_mm_process_rail_drawing_orders(struct xrdp_mm* self, struct trans* trans) struct stream* s; int order_type; int rv = 0; - + s = trans_get_in_s(trans); if (s == 0) { return 1; } in_uint32_le(s, order_type); - + switch(order_type) { case 2: /* create_window */ @@ -934,7 +935,7 @@ xrdp_mm_process_rail_drawing_orders(struct xrdp_mm* self, struct trans* trans) default: break; } - + return rv; } @@ -1511,7 +1512,7 @@ getPAMError(const int pamError, char *text, int text_bytes) case PAM_USER_UNKNOWN: return "User not known to the underlying authentication module"; case PAM_MAXTRIES: - return "Have exhasted maximum number of retries for service."; + return "Have exhausted maximum number of retries for service."; case PAM_NEW_AUTHTOK_REQD: return "Authentication token is no longer valid; new one required."; case PAM_ACCT_EXPIRED: @@ -2072,7 +2073,7 @@ server_paint_rect_bpp(struct xrdp_mod* mod, int x, int y, int cx, int cy, struct xrdp_wm* wm; struct xrdp_bitmap* b; struct xrdp_painter* p; - + p = (struct xrdp_painter*)(mod->painter); if (p == 0) { @@ -2099,7 +2100,7 @@ server_composite(struct xrdp_mod* mod, int srcidx, int srcformat, struct xrdp_bitmap* msk; struct xrdp_painter* p; struct xrdp_os_bitmap_item* bi; - + p = (struct xrdp_painter*)(mod->painter); if (p == 0) { @@ -2136,6 +2137,38 @@ server_composite(struct xrdp_mod* mod, int srcidx, int srcformat, return 0; } +/*****************************************************************************/ +int DEFAULT_CC +server_paint_rects(struct xrdp_mod* mod, int num_drects, short *drects, + int num_crects, short *crects, + char *data, int width, int height, int flags) +{ + struct xrdp_wm* wm; + struct xrdp_painter* p; + struct xrdp_bitmap *b; + short *s; + int index; + + //g_writeln("server_paint_rects:"); + wm = (struct xrdp_wm*)(mod->wm); + p = (struct xrdp_painter*)(mod->painter); + if (p == 0) + { + return 0; + } + b = xrdp_bitmap_create_with_data(width, height, wm->screen->bpp, + data, wm); + s = crects; + for (index = 0; index < num_crects; index++) + { + xrdp_painter_copy(p, b, wm->target_surface, s[0], s[1], s[2], s[3], + s[0], s[1]); + s += 4; + } + xrdp_bitmap_delete(b); + return 0; +} + /*****************************************************************************/ int DEFAULT_CC server_set_pointer(struct xrdp_mod *mod, int x, int y, @@ -2493,7 +2526,7 @@ find_name_in_lists(char *inName, struct list *names) for (index = 0; index < names->count; index++) { name = (char *)list_get_item(names, index); - if ( (name != 0) && (g_strncmp(name, inName, MAX_CHANNEL_NAME) == 0) ) + if ( (name != 0) && (g_strncasecmp(name, inName, MAX_CHANNEL_NAME) == 0) ) { reply = index; break; /* stop loop - item found*/ @@ -2759,7 +2792,7 @@ server_create_os_surface_bpp(struct xrdp_mod* mod, int rdpindex, struct xrdp_wm* wm; struct xrdp_bitmap* bitmap; int error; - + wm = (struct xrdp_wm*)(mod->wm); bitmap = xrdp_bitmap_create(width, height, bpp, WND_TYPE_OFFSCREEN, wm); diff --git a/xrdp/xrdp_process.c b/xrdp/xrdp_process.c index 4c52eaac..78576f1f 100644 --- a/xrdp/xrdp_process.c +++ b/xrdp/xrdp_process.c @@ -61,7 +61,7 @@ xrdp_process_delete(struct xrdp_process *self) /*****************************************************************************/ static int APP_CC -xrdp_process_loop(struct xrdp_process *self) +xrdp_process_loop(struct xrdp_process *self, struct stream *s) { int rv; @@ -69,7 +69,7 @@ xrdp_process_loop(struct xrdp_process *self) if (self->session != 0) { - rv = libxrdp_process_data(self->session); + rv = libxrdp_process_data(self->session, s); } if ((self->wm == 0) && (self->session->up_and_running) && (rv == 0)) @@ -114,18 +114,117 @@ xrdp_process_mod_end(struct xrdp_process *self) return 0; } +/*****************************************************************************/ +static int APP_CC +xrdp_process_get_pdu_bytes(const char *aheader) +{ + int rv; + const tui8 *header; + + rv = -1; + header = (const tui8 *) aheader; + if (header[0] == 0x03) + { + /* TPKT */ + rv = (header[2] << 8) | header[3]; + } + else if (header[0] == 0x30) + { + /* TSRequest (NLA) */ + if (header[1] & 0x80) + { + if ((header[1] & ~(0x80)) == 1) + { + rv = header[2]; + rv += 3; + } + else if ((header[1] & ~(0x80)) == 2) + { + rv = (header[2] << 8) | header[3]; + rv += 4; + } + else + { + g_writeln("xrdp_process_get_packet_bytes: error TSRequest!"); + return -1; + } + } + else + { + rv = header[1]; + rv += 2; + } + } + else + { + /* Fast-Path */ + if (header[1] & 0x80) + { + rv = ((header[1] & 0x7F) << 8) | header[2]; + } + else + { + rv = header[1]; + } + } + return rv; +} + /*****************************************************************************/ static int DEFAULT_CC xrdp_process_data_in(struct trans *self) { struct xrdp_process *pro; + struct stream *s; + int len; DEBUG(("xrdp_process_data_in")); pro = (struct xrdp_process *)(self->callback_data); - if (xrdp_process_loop(pro) != 0) + s = pro->server_trans->in_s; + switch (pro->server_trans->extra_flags) { - return 1; + case 0: + /* early in connection sequence, we're in this mode */ + if (xrdp_process_loop(pro, 0) != 0) + { + g_writeln("xrdp_process_data_in: " + "xrdp_process_loop failed"); + return 1; + } + if (pro->session->up_and_running) + { + pro->server_trans->extra_flags = 1; + pro->server_trans->header_size = 4; + } + break; + + case 1: + /* we have enough now to get the PDU bytes */ + len = xrdp_process_get_pdu_bytes(s->p); + if (len == -1) + { + g_writeln("xrdp_process_data_in: " + "xrdp_process_get_packet_bytes failed"); + return 1; + } + pro->server_trans->header_size = len; + pro->server_trans->extra_flags = 2; + break; + + case 2: + /* the whole PDU is read in now process */ + s->p = s->data; + if (xrdp_process_loop(pro, s) != 0) + { + g_writeln("xrdp_process_data_in: " + "xrdp_process_loop failed"); + return 1; + } + init_stream(s, 0); + pro->server_trans->header_size = 4; + pro->server_trans->extra_flags = 1; + break; } return 0; @@ -145,8 +244,12 @@ xrdp_process_main_loop(struct xrdp_process *self) DEBUG(("xrdp_process_main_loop")); self->status = 1; + self->server_trans->extra_flags = 0; + self->server_trans->header_size = 0; + self->server_trans->no_stream_init_on_data_in = 1; self->server_trans->trans_data_in = xrdp_process_data_in; self->server_trans->callback_data = self; + init_stream(self->server_trans->in_s, 8192 * 4); self->session = libxrdp_init((tbus)self, self->server_trans); /* this callback function is in xrdp_wm.c */ self->session->callback = callback; diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h index 3811b16b..7d7eb72c 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -18,6 +18,9 @@ * types */ +#ifndef _XRDP_TYPES_H_ +#define _XRDP_TYPES_H_ + #define DEFAULT_STRING_LEN 255 #define LOG_WINDOW_CHAR_PER_LINE 60 @@ -136,7 +139,11 @@ struct xrdp_mod int srcx, int srcy, int mskx, int msky, int dstx, int dsty, int width, int height, int dstformat); - long server_dumby[100 - 42]; /* align, 100 minus the number of server + int (*server_paint_rects)(struct xrdp_mod* v, + int num_drects, short *drects, + int num_crects, short *crects, + char *data, int width, int height, int flags); + long server_dumby[100 - 43]; /* align, 100 minus the number of server functions above */ /* common */ long handle; /* pointer to self as int */ @@ -342,6 +349,9 @@ struct xrdp_wm int allowedchannels[MAX_NR_CHANNELS]; int allowedinitialized ; char pamerrortxt[256]; + + /* configuration derived from xrdp.ini */ + struct xrdp_config *xrdp_config; }; /* rdp process */ @@ -456,8 +466,8 @@ struct xrdp_bitmap #define DEFAULT_COMBO_H 21 #define DEFAULT_EDIT_W 210 #define DEFAULT_EDIT_H 21 -#define DEFAULT_WND_LOGIN_W 500 -#define DEFAULT_WND_LOGIN_H 250 +#define DEFAULT_WND_LOGIN_W 425 +#define DEFAULT_WND_LOGIN_H 475 #define DEFAULT_WND_HELP_W 340 #define DEFAULT_WND_HELP_H 300 #define DEFAULT_WND_LOG_W 400 @@ -492,3 +502,83 @@ struct xrdp_startup_params int send_buffer_bytes; int recv_buffer_bytes; }; + +/* + * For storing xrdp.ini configuration settings + */ + +struct xrdp_cfg_globals +{ + int ini_version; /* xrdp.ini file version number */ + int use_bitmap_cache; + int use_bitmap_compression; + int port; + int crypt_level; /* low=1, medium=2, high=3 */ + int allow_channels; + int max_bpp; + int fork; + int tcp_nodelay; + int tcp_keepalive; + int tcp_send_buffer_bytes; + int tcp_recv_buffer_bytes; + char autorun[256]; + int hidelogwindow; + int require_credentials; + int bulk_compression; + int new_cursors; + int nego_sec_layer; + int allow_multimon; + + /* colors */ + + int grey; + int black; + int dark_grey; + int blue; + int dark_blue; + int white; + int red; + int green; + int background; + + /* login screen */ + int ls_top_window_bg_color; /* top level window background color */ + int ls_width; /* window width */ + int ls_height; /* window height */ + int ls_bg_color; /* background color */ + char ls_logo_filename[256]; /* logo filename */ + int ls_logo_x_pos; /* logo x co-ordinate */ + int ls_logo_y_pos; /* logo y co-ordinate */ + int ls_label_x_pos; /* x pos of labels */ + int ls_label_width; /* width of labels */ + int ls_input_x_pos; /* x pos of text and combo boxes */ + int ls_input_width; /* width of input and combo boxes */ + int ls_input_y_pos; /* y pos for for first label and combo box */ + int ls_btn_ok_x_pos; /* x pos for OK button */ + int ls_btn_ok_y_pos; /* y pos for OK button */ + int ls_btn_ok_width; /* width of OK button */ + int ls_btn_ok_height; /* height of OK button */ + int ls_btn_cancel_x_pos; /* x pos for Cancel button */ + int ls_btn_cancel_y_pos; /* y pos for Cancel button */ + int ls_btn_cancel_width; /* width of Cancel button */ + int ls_btn_cancel_height; /* height of Cancel button */ +}; + +struct xrdp_cfg_logging +{ + +}; + +struct xrdp_cfg_channels +{ + +}; + +struct xrdp_config +{ + struct xrdp_cfg_globals cfg_globals; + struct xrdp_cfg_logging cfg_logging; + struct xrdp_cfg_channels cfg_channels; +}; + +#endif diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c index bba25c34..ffc6d3a2 100644 --- a/xrdp/xrdp_wm.c +++ b/xrdp/xrdp_wm.c @@ -58,6 +58,10 @@ xrdp_wm_create(struct xrdp_process *owner, xrdp_wm_set_login_mode(self, 0); self->target_surface = self->screen; self->current_surface_index = 0xffff; /* screen */ + + /* to store configuration from xrdp.ini */ + self->xrdp_config = g_malloc(sizeof(struct xrdp_config), 1); + return self; } @@ -79,6 +83,10 @@ xrdp_wm_delete(struct xrdp_wm *self) /* free default font */ xrdp_font_delete(self->default_font); g_delete_wait_obj(self->login_mode_event); + + if (self->xrdp_config) + g_free(self->xrdp_config); + /* free self */ g_free(self); } @@ -315,7 +323,8 @@ xrdp_wm_set_pointer(struct xrdp_wm *self, int cache_idx) /*****************************************************************************/ /* convert hex string to int */ -unsigned int xrdp_wm_htoi (const char *ptr) +unsigned int APP_CC +xrdp_wm_htoi (const char *ptr) { unsigned int value = 0; char ch = *ptr; @@ -535,12 +544,18 @@ xrdp_wm_init(struct xrdp_wm *self) char cfg_file[256]; char autorun_name[256]; + load_xrdp_config(self->xrdp_config, self->screen->bpp); + xrdp_wm_load_static_colors_plus(self, autorun_name); xrdp_wm_load_static_pointers(self); - self->screen->bg_color = self->background; + self->screen->bg_color = self->xrdp_config->cfg_globals.ls_top_window_bg_color; if (self->session->client_info->rdp_autologin || (autorun_name[0] != 0)) { + /* + * NOTE: this should eventually be accessed from self->xrdp_config + */ + g_snprintf(cfg_file, 255, "%s/xrdp.ini", XRDP_CFG_PATH); fd = g_file_open(cfg_file); /* xrdp.ini */ @@ -561,7 +576,7 @@ xrdp_wm_init(struct xrdp_wm *self) { if (autorun_name[0] == 0) { - /* if no doamin is passed, and no autorun in xrdp.ini, + /* if no domain is passed, and no autorun in xrdp.ini, use the first item in the xrdp.ini file thats not named 'globals' or 'Logging' or 'channels' */ @@ -1028,7 +1043,7 @@ xrdp_wm_mouse_move(struct xrdp_wm *self, int x, int y) b = xrdp_wm_at_pos(self->screen, x, y, 0); - if (b == 0) /* if b is null, the movment must be over the screen */ + if (b == 0) /* if b is null, the movement must be over the screen */ { if (self->screen->pointer != self->current_pointer) { @@ -1036,7 +1051,7 @@ xrdp_wm_mouse_move(struct xrdp_wm *self, int x, int y) self->current_pointer = self->screen->pointer; } - if (self->mm->mod != 0) /* if screen is mod controled */ + if (self->mm->mod != 0) /* if screen is mod controlled */ { if (self->mm->mod->mod_event != 0) { @@ -1175,7 +1190,7 @@ xrdp_wm_mouse_click(struct xrdp_wm *self, int x, int y, int but, int down) if (control == 0) { - if (self->mm->mod != 0) /* if screen is mod controled */ + if (self->mm->mod != 0) /* if screen is mod controlled */ { if (self->mm->mod->mod_event != 0) { @@ -1724,7 +1739,7 @@ xrdp_wm_login_mode_changed(struct xrdp_wm *self) } /*****************************************************************************/ -/* this is the log windows nofity function */ +/* this is the log windows notify function */ static int DEFAULT_CC xrdp_wm_log_wnd_notify(struct xrdp_bitmap *wnd, struct xrdp_bitmap *sender, diff --git a/xup/xup.c b/xup/xup.c index 7ff5e5e8..12c570af 100644 --- a/xup/xup.c +++ b/xup/xup.c @@ -21,9 +21,6 @@ #include "xup.h" #include "log.h" -#include -#include - #define LOG_LEVEL 1 #define LLOG(_level, _args) \ do { if (_level < LOG_LEVEL) { g_write _args ; } } while (0) @@ -435,6 +432,287 @@ lib_mod_event(struct mod *mod, int msg, tbus param1, tbus param2, return rv; } +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_fill_rect(struct mod *mod, struct stream *s) +{ + int rv; + int x; + int y; + int cx; + int cy; + + in_sint16_le(s, x); + in_sint16_le(s, y); + in_uint16_le(s, cx); + in_uint16_le(s, cy); + rv = mod->server_fill_rect(mod, x, y, cx, cy); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_screen_blt(struct mod *mod, struct stream *s) +{ + int rv; + int x; + int y; + int cx; + int cy; + int srcx; + int srcy; + + in_sint16_le(s, x); + in_sint16_le(s, y); + in_uint16_le(s, cx); + in_uint16_le(s, cy); + in_sint16_le(s, srcx); + in_sint16_le(s, srcy); + rv = mod->server_screen_blt(mod, x, y, cx, cy, srcx, srcy); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_paint_rect(struct mod *mod, struct stream *s) +{ + int rv; + int x; + int y; + int cx; + int cy; + int len_bmpdata; + char *bmpdata; + int width; + int height; + int srcx; + int srcy; + + in_sint16_le(s, x); + in_sint16_le(s, y); + in_uint16_le(s, cx); + in_uint16_le(s, cy); + in_uint32_le(s, len_bmpdata); + in_uint8p(s, bmpdata, len_bmpdata); + in_uint16_le(s, width); + in_uint16_le(s, height); + in_sint16_le(s, srcx); + in_sint16_le(s, srcy); + rv = mod->server_paint_rect(mod, x, y, cx, cy, + bmpdata, width, height, + srcx, srcy); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_set_clip(struct mod *mod, struct stream *s) +{ + int rv; + int x; + int y; + int cx; + int cy; + + in_sint16_le(s, x); + in_sint16_le(s, y); + in_uint16_le(s, cx); + in_uint16_le(s, cy); + rv = mod->server_set_clip(mod, x, y, cx, cy); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_reset_clip(struct mod *mod, struct stream *s) +{ + int rv; + + rv = mod->server_reset_clip(mod); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_set_fgcolor(struct mod *mod, struct stream *s) +{ + int rv; + int fgcolor; + + in_uint32_le(s, fgcolor); + rv = mod->server_set_fgcolor(mod, fgcolor); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_set_bgcolor(struct mod *mod, struct stream *s) +{ + int rv; + int bgcolor; + + in_uint32_le(s, bgcolor); + rv = mod->server_set_bgcolor(mod, bgcolor); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_set_opcode(struct mod *mod, struct stream *s) +{ + int rv; + int opcode; + + in_uint16_le(s, opcode); + rv = mod->server_set_opcode(mod, opcode); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_set_pen(struct mod *mod, struct stream *s) +{ + int rv; + int style; + int width; + + in_uint16_le(s, style); + in_uint16_le(s, width); + rv = mod->server_set_pen(mod, style, width); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_draw_line(struct mod *mod, struct stream *s) +{ + int rv; + int x1; + int y1; + int x2; + int y2; + + in_sint16_le(s, x1); + in_sint16_le(s, y1); + in_sint16_le(s, x2); + in_sint16_le(s, y2); + rv = mod->server_draw_line(mod, x1, y1, x2, y2); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_set_cursor(struct mod *mod, struct stream *s) +{ + int rv; + int x; + int y; + char cur_data[32 * (32 * 3)]; + char cur_mask[32 * (32 / 8)]; + + in_sint16_le(s, x); + in_sint16_le(s, y); + in_uint8a(s, cur_data, 32 * (32 * 3)); + in_uint8a(s, cur_mask, 32 * (32 / 8)); + rv = mod->server_set_cursor(mod, x, y, cur_data, cur_mask); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_create_os_surface(struct mod *mod, struct stream *s) +{ + int rv; + int rdpid; + int width; + int height; + + in_uint32_le(s, rdpid); + in_uint16_le(s, width); + in_uint16_le(s, height); + rv = mod->server_create_os_surface(mod, rdpid, width, height); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_switch_os_surface(struct mod *mod, struct stream *s) +{ + int rv; + int rdpid; + + in_uint32_le(s, rdpid); + rv = mod->server_switch_os_surface(mod, rdpid); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_delete_os_surface(struct mod *mod, struct stream *s) +{ + int rv; + int rdpid; + + in_uint32_le(s, rdpid); + rv = mod->server_delete_os_surface(mod, rdpid); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_paint_rect_os(struct mod *mod, struct stream *s) +{ + int rv; + int x; + int y; + int cx; + int cy; + int rdpid; + int srcx; + int srcy; + + in_sint16_le(s, x); + in_sint16_le(s, y); + in_uint16_le(s, cx); + in_uint16_le(s, cy); + in_uint32_le(s, rdpid); + in_sint16_le(s, srcx); + in_sint16_le(s, srcy); + rv = mod->server_paint_rect_os(mod, x, y, cx, cy, + rdpid, srcx, srcy); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_set_hints(struct mod *mod, struct stream *s) +{ + int rv; + int hints; + int mask; + + in_uint32_le(s, hints); + in_uint32_le(s, mask); + rv = mod->server_set_hints(mod, hints, mask); + return rv; +} + /******************************************************************************/ /* return error */ static int APP_CC @@ -518,6 +796,20 @@ process_server_window_new_update(struct mod *mod, struct stream *s) return rv; } +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_window_delete(struct mod *mod, struct stream *s) +{ + int window_id; + int rv; + + in_uint32_le(s, window_id); + mod->server_window_delete(mod, window_id); + rv = 0; + return rv; +} + /******************************************************************************/ /* return error */ static int APP_CC @@ -527,7 +819,7 @@ process_server_window_show(struct mod* mod, struct stream* s) int rv; int flags; struct rail_window_state_order rwso; - + g_memset(&rwso, 0, sizeof(rwso)); in_uint32_le(s, window_id); in_uint32_le(s, flags); @@ -540,14 +832,209 @@ process_server_window_show(struct mod* mod, struct stream* s) /******************************************************************************/ /* return error */ static int APP_CC -process_server_window_delete(struct mod *mod, struct stream *s) +process_server_add_char(struct mod *mod, struct stream *s) { - int window_id; int rv; + int font; + int charactor; + int x; + int y; + int cx; + int cy; + int len_bmpdata; + char *bmpdata; - in_uint32_le(s, window_id); - mod->server_window_delete(mod, window_id); - rv = 0; + in_uint16_le(s, font); + in_uint16_le(s, charactor); + in_sint16_le(s, x); + in_sint16_le(s, y); + in_uint16_le(s, cx); + in_uint16_le(s, cy); + in_uint16_le(s, len_bmpdata); + in_uint8p(s, bmpdata, len_bmpdata); + rv = mod->server_add_char(mod, font, charactor, x, y, cx, cy, bmpdata); + return rv; +} + + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_add_char_alpha(struct mod *mod, struct stream *s) +{ + int rv; + int font; + int charactor; + int x; + int y; + int cx; + int cy; + int len_bmpdata; + char *bmpdata; + + in_uint16_le(s, font); + in_uint16_le(s, charactor); + in_sint16_le(s, x); + in_sint16_le(s, y); + in_uint16_le(s, cx); + in_uint16_le(s, cy); + in_uint16_le(s, len_bmpdata); + in_uint8p(s, bmpdata, len_bmpdata); + rv = mod->server_add_char_alpha(mod, font, charactor, x, y, cx, cy, + bmpdata); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_draw_text(struct mod *mod, struct stream *s) +{ + int rv; + int font; + int flags; + int mixmode; + int clip_left; + int clip_top; + int clip_right; + int clip_bottom; + int box_left; + int box_top; + int box_right; + int box_bottom; + int x; + int y; + int len_bmpdata; + char *bmpdata; + + in_uint16_le(s, font); + in_uint16_le(s, flags); + in_uint16_le(s, mixmode); + in_sint16_le(s, clip_left); + in_sint16_le(s, clip_top); + in_sint16_le(s, clip_right); + in_sint16_le(s, clip_bottom); + in_sint16_le(s, box_left); + in_sint16_le(s, box_top); + in_sint16_le(s, box_right); + in_sint16_le(s, box_bottom); + in_sint16_le(s, x); + in_sint16_le(s, y); + in_uint16_le(s, len_bmpdata); + in_uint8p(s, bmpdata, len_bmpdata); + rv = mod->server_draw_text(mod, font, flags, mixmode, clip_left, clip_top, + clip_right, clip_bottom, box_left, box_top, + box_right, box_bottom, x, y, bmpdata, len_bmpdata); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_create_os_surface_bpp(struct mod *mod, struct stream *s) +{ + int rv; + int rdpid; + int width; + int height; + int bpp; + + in_uint32_le(s, rdpid); + in_uint16_le(s, width); + in_uint16_le(s, height); + in_uint8(s, bpp); + rv = mod->server_create_os_surface_bpp(mod, rdpid, width, height, bpp); + return rv; +} + + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_paint_rect_bpp(struct mod *mod, struct stream *s) +{ + int rv; + int x; + int y; + int cx; + int cy; + int len_bmpdata; + char *bmpdata; + int width; + int height; + int srcx; + int srcy; + int bpp; + + in_sint16_le(s, x); + in_sint16_le(s, y); + in_uint16_le(s, cx); + in_uint16_le(s, cy); + in_uint32_le(s, len_bmpdata); + in_uint8p(s, bmpdata, len_bmpdata); + in_uint16_le(s, width); + in_uint16_le(s, height); + in_sint16_le(s, srcx); + in_sint16_le(s, srcy); + in_uint8(s, bpp); + rv = mod->server_paint_rect_bpp(mod, x, y, cx, cy, + bmpdata, width, height, + srcx, srcy, bpp); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_composite(struct mod *mod, struct stream *s) +{ + int rv; + int srcidx; + int srcformat; + int srcwidth; + int srcrepeat; + int transform[10]; + int mskflags; + int mskidx; + int mskformat; + int mskwidth; + int mskrepeat; + int op; + int srcx; + int srcy; + int mskx; + int msky; + int dstx; + int dsty; + int width; + int height; + int dstformat; + + in_uint16_le(s, srcidx); + in_uint32_le(s, srcformat); + in_uint16_le(s, srcwidth); + in_uint8(s, srcrepeat); + g_memcpy(transform, s->p, 40); + in_uint8s(s, 40); + in_uint8(s, mskflags); + in_uint16_le(s, mskidx); + in_uint32_le(s, mskformat); + in_uint16_le(s, mskwidth); + in_uint8(s, mskrepeat); + in_uint8(s, op); + in_sint16_le(s, srcx); + in_sint16_le(s, srcy); + in_sint16_le(s, mskx); + in_sint16_le(s, msky); + in_sint16_le(s, dstx); + in_sint16_le(s, dsty); + in_uint16_le(s, width); + in_uint16_le(s, height); + in_uint32_le(s, dstformat); + rv = mod->server_composite(mod, srcidx, srcformat, srcwidth, srcrepeat, + transform, mskflags, mskidx, mskformat, + mskwidth, mskrepeat, op, srcx, srcy, mskx, msky, + dstx, dsty, width, height, dstformat); return rv; } @@ -605,67 +1092,185 @@ send_paint_rect_ack(struct mod *mod, int flags, int x, int y, int cx, int cy, /******************************************************************************/ /* return error */ static int APP_CC -lib_mod_process_orders(struct mod *mod, int type, struct stream *s) +process_server_paint_rect_shmem(struct mod *mod, struct stream *s) { int rv; int x; int y; int cx; int cy; - int srcx; - int srcy; - int mskx; - int msky; - int dstx; - int dsty; - int len_bmpdata; - int style; - int x1; - int y1; - int x2; - int y2; - int bpp; - int rdpid; - int hints; - int mask; - int width; - int height; - int fgcolor; - int bgcolor; - int opcode; int flags; + int frame_id; int shmem_id; int shmem_offset; - int frame_id; - int charactor; - int font; - int mixmode; - int clip_left; - int clip_top; - int clip_right; - int clip_bottom; - int box_left; - int box_top; - int box_right; - int box_bottom; - int srcrepeat; - int srcidx; - int srcformat; - int srcwidth; - int mskflags; - int mskidx; - int mskformat; - int mskwidth; - int mskrepeat; - int dstformat; - int op; - int transform[10]; + int width; + int height; + int srcx; + int srcy; char *bmpdata; - char cur_data[32 * (32 * 3)]; - char cur_mask[32 * (32 / 8)]; + + in_sint16_le(s, x); + in_sint16_le(s, y); + in_uint16_le(s, cx); + in_uint16_le(s, cy); + in_uint32_le(s, flags); + in_uint32_le(s, frame_id); + in_uint32_le(s, shmem_id); + in_uint32_le(s, shmem_offset); + in_uint16_le(s, width); + in_uint16_le(s, height); + in_sint16_le(s, srcx); + in_sint16_le(s, srcy); + bmpdata = 0; + if (flags == 0) /* screen */ + { + if (mod->screen_shmem_id == 0) + { + mod->screen_shmem_id = shmem_id; + mod->screen_shmem_pixels = g_shmat(mod->screen_shmem_id); + } + if (mod->screen_shmem_pixels != 0) + { + bmpdata = mod->screen_shmem_pixels + shmem_offset; + } + } + if (bmpdata != 0) + { + rv = mod->server_paint_rect(mod, x, y, cx, cy, + bmpdata, width, height, + srcx, srcy); + } + else + { + rv = 1; + } + send_paint_rect_ack(mod, flags, x, y, cx, cy, frame_id); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +send_paint_rect_ex_ack(struct mod *mod, int flags, int frame_id) +{ + int len; + struct stream *s; + + make_stream(s); + init_stream(s, 8192); + s_push_layer(s, iso_hdr, 4); + out_uint16_le(s, 106); + out_uint32_le(s, flags); + out_uint32_le(s, frame_id); + s_mark_end(s); + len = (int)(s->end - s->data); + s_pop_layer(s, iso_hdr); + out_uint32_le(s, len); + lib_send(mod, s->data, len); + free_stream(s); + return 0; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_paint_rect_shmem_ex(struct mod *amod, struct stream *s) +{ + int num_drects; + int num_crects; + int flags; + int frame_id; + int shmem_id; + int shmem_offset; + int width; + int height; + int x; + int y; + int cx; + int cy; + int index; + int rv; + tsi16 *ldrects; + tsi16 *ldrects1; + tsi16 *lcrects; + tsi16 *lcrects1; + char *bmpdata; + + /* dirty pixels */ + in_uint16_le(s, num_drects); + ldrects = (tsi16 *) g_malloc(2 * 4 * num_drects, 0); + ldrects1 = ldrects; + for (index = 0; index < num_drects; index++) + { + in_sint16_le(s, ldrects1[0]); + in_sint16_le(s, ldrects1[1]); + in_sint16_le(s, ldrects1[2]); + in_sint16_le(s, ldrects1[3]); + ldrects1 += 4; + } + + /* copied pixels */ + in_uint16_le(s, num_crects); + lcrects = (tsi16 *) g_malloc(2 * 4 * num_crects, 0); + lcrects1 = lcrects; + for (index = 0; index < num_crects; index++) + { + in_sint16_le(s, lcrects1[0]); + in_sint16_le(s, lcrects1[1]); + in_sint16_le(s, lcrects1[2]); + in_sint16_le(s, lcrects1[3]); + lcrects1 += 4; + } + + in_uint32_le(s, flags); + in_uint32_le(s, frame_id); + in_uint32_le(s, shmem_id); + in_uint32_le(s, shmem_offset); + + in_uint16_le(s, width); + in_uint16_le(s, height); + + bmpdata = 0; + if (flags == 0) /* screen */ + { + if (amod->screen_shmem_id == 0) + { + amod->screen_shmem_id = shmem_id; + amod->screen_shmem_pixels = g_shmat(amod->screen_shmem_id); + } + if (amod->screen_shmem_pixels != 0) + { + bmpdata = amod->screen_shmem_pixels + shmem_offset; + } + } + if (bmpdata != 0) + { + + rv = amod->server_paint_rects(amod, num_drects, ldrects, + num_crects, lcrects, + bmpdata, width, height, 0); + } + else + { + rv = 1; + } + + send_paint_rect_ex_ack(amod, flags, frame_id); + + g_free(lcrects); + g_free(ldrects); + + return 0; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +lib_mod_process_orders(struct mod *mod, int type, struct stream *s) +{ + int rv; rv = 0; - switch (type) { case 1: /* server_begin_update */ @@ -675,106 +1280,52 @@ lib_mod_process_orders(struct mod *mod, int type, struct stream *s) rv = mod->server_end_update(mod); break; case 3: /* server_fill_rect */ - in_sint16_le(s, x); - in_sint16_le(s, y); - in_uint16_le(s, cx); - in_uint16_le(s, cy); - rv = mod->server_fill_rect(mod, x, y, cx, cy); + rv = process_server_fill_rect(mod, s); break; case 4: /* server_screen_blt */ - in_sint16_le(s, x); - in_sint16_le(s, y); - in_uint16_le(s, cx); - in_uint16_le(s, cy); - in_sint16_le(s, srcx); - in_sint16_le(s, srcy); - rv = mod->server_screen_blt(mod, x, y, cx, cy, srcx, srcy); + rv = process_server_screen_blt(mod, s); break; case 5: /* server_paint_rect */ - in_sint16_le(s, x); - in_sint16_le(s, y); - in_uint16_le(s, cx); - in_uint16_le(s, cy); - in_uint32_le(s, len_bmpdata); - in_uint8p(s, bmpdata, len_bmpdata); - in_uint16_le(s, width); - in_uint16_le(s, height); - in_sint16_le(s, srcx); - in_sint16_le(s, srcy); - rv = mod->server_paint_rect(mod, x, y, cx, cy, - bmpdata, width, height, - srcx, srcy); + rv = process_server_paint_rect(mod, s); break; case 10: /* server_set_clip */ - in_sint16_le(s, x); - in_sint16_le(s, y); - in_uint16_le(s, cx); - in_uint16_le(s, cy); - rv = mod->server_set_clip(mod, x, y, cx, cy); + rv = process_server_set_clip(mod, s); break; case 11: /* server_reset_clip */ - rv = mod->server_reset_clip(mod); + rv = process_server_reset_clip(mod, s); break; case 12: /* server_set_fgcolor */ - in_uint32_le(s, fgcolor); - rv = mod->server_set_fgcolor(mod, fgcolor); + rv = process_server_set_fgcolor(mod, s); break; case 13: /* server_set_bgcolor */ - in_uint32_le(s, bgcolor); - rv = mod->server_set_bgcolor(mod, bgcolor); + rv = process_server_set_bgcolor(mod, s); break; - case 14: - in_uint16_le(s, opcode); - rv = mod->server_set_opcode(mod, opcode); + case 14: /* server_set_opcode */ + rv = process_server_set_opcode(mod, s); break; - case 17: - in_uint16_le(s, style); - in_uint16_le(s, width); - rv = mod->server_set_pen(mod, style, width); + case 17: /* server_set_pen */ + rv = process_server_set_pen(mod, s); break; - case 18: - in_sint16_le(s, x1); - in_sint16_le(s, y1); - in_sint16_le(s, x2); - in_sint16_le(s, y2); - rv = mod->server_draw_line(mod, x1, y1, x2, y2); + case 18: /* server_draw_line */ + rv = process_server_draw_line(mod, s); break; - case 19: - in_sint16_le(s, x); - in_sint16_le(s, y); - in_uint8a(s, cur_data, 32 * (32 * 3)); - in_uint8a(s, cur_mask, 32 * (32 / 8)); - rv = mod->server_set_cursor(mod, x, y, cur_data, cur_mask); + case 19: /* server_set_cursor */ + rv = process_server_set_cursor(mod, s); break; - case 20: - in_uint32_le(s, rdpid); - in_uint16_le(s, width); - in_uint16_le(s, height); - rv = mod->server_create_os_surface(mod, rdpid, width, height); + case 20: /* server_create_os_surface */ + rv = process_server_create_os_surface(mod, s); break; - case 21: - in_uint32_le(s, rdpid); - rv = mod->server_switch_os_surface(mod, rdpid); + case 21: /* server_switch_os_surface */ + rv = process_server_switch_os_surface(mod, s); break; - case 22: - in_uint32_le(s, rdpid); - rv = mod->server_delete_os_surface(mod, rdpid); + case 22: /* server_delete_os_surface */ + rv = process_server_delete_os_surface(mod, s); break; case 23: /* server_paint_rect_os */ - in_sint16_le(s, x); - in_sint16_le(s, y); - in_uint16_le(s, cx); - in_uint16_le(s, cy); - in_uint32_le(s, rdpid); - in_sint16_le(s, srcx); - in_sint16_le(s, srcy); - rv = mod->server_paint_rect_os(mod, x, y, cx, cy, - rdpid, srcx, srcy); + rv = process_server_paint_rect_os(mod, s); break; case 24: /* server_set_hints */ - in_uint32_le(s, hints); - in_uint32_le(s, mask); - rv = mod->server_set_hints(mod, hints, mask); + rv = process_server_set_hints(mod, s); break; case 25: /* server_window_new_update */ rv = process_server_window_new_update(mod, s); @@ -786,149 +1337,40 @@ lib_mod_process_orders(struct mod *mod, int type, struct stream *s) rv = process_server_window_show(mod, s); break; case 28: /* server_add_char */ - in_uint16_le(s, font); - in_uint16_le(s, charactor); - in_sint16_le(s, x); - in_sint16_le(s, y); - in_uint16_le(s, cx); - in_uint16_le(s, cy); - in_uint16_le(s, len_bmpdata); - in_uint8p(s, bmpdata, len_bmpdata); - rv = mod->server_add_char(mod, font, charactor, x, y, cx, cy, bmpdata); + rv = process_server_add_char(mod, s); break; case 29: /* server_add_char_alpha */ - in_uint16_le(s, font); - in_uint16_le(s, charactor); - in_sint16_le(s, x); - in_sint16_le(s, y); - in_uint16_le(s, cx); - in_uint16_le(s, cy); - in_uint16_le(s, len_bmpdata); - in_uint8p(s, bmpdata, len_bmpdata); - rv = mod->server_add_char_alpha(mod, font, charactor, x, y, cx, cy, bmpdata); + rv = process_server_add_char_alpha(mod, s); break; case 30: /* server_draw_text */ - in_uint16_le(s, font); - in_uint16_le(s, flags); - in_uint16_le(s, mixmode); - in_sint16_le(s, clip_left); - in_sint16_le(s, clip_top); - in_sint16_le(s, clip_right); - in_sint16_le(s, clip_bottom); - in_sint16_le(s, box_left); - in_sint16_le(s, box_top); - in_sint16_le(s, box_right); - in_sint16_le(s, box_bottom); - in_sint16_le(s, x); - in_sint16_le(s, y); - in_uint16_le(s, len_bmpdata); - in_uint8p(s, bmpdata, len_bmpdata); - rv = mod->server_draw_text(mod, font, flags, mixmode, clip_left, clip_top, - clip_right, clip_bottom, box_left, box_top, - box_right, box_bottom, x, y, bmpdata, len_bmpdata); + rv = process_server_draw_text(mod, s); break; case 31: /* server_create_os_surface_bpp */ - in_uint32_le(s, rdpid); - in_uint16_le(s, width); - in_uint16_le(s, height); - in_uint8(s, bpp); - rv = mod->server_create_os_surface_bpp(mod, rdpid, width, height, bpp); + rv = process_server_create_os_surface_bpp(mod, s); break; case 32: /* server_paint_rect_bpp */ - in_sint16_le(s, x); - in_sint16_le(s, y); - in_uint16_le(s, cx); - in_uint16_le(s, cy); - in_uint32_le(s, len_bmpdata); - in_uint8p(s, bmpdata, len_bmpdata); - in_uint16_le(s, width); - in_uint16_le(s, height); - in_sint16_le(s, srcx); - in_sint16_le(s, srcy); - in_uint8(s, bpp); - rv = mod->server_paint_rect_bpp(mod, x, y, cx, cy, - bmpdata, width, height, - srcx, srcy, bpp); + rv = process_server_paint_rect_bpp(mod, s); break; - case 33: - in_uint16_le(s, srcidx); - in_uint32_le(s, srcformat); - in_uint16_le(s, srcwidth); - in_uint8(s, srcrepeat); - g_memcpy(transform, s->p, 40); - in_uint8s(s, 40); - in_uint8(s, mskflags); - in_uint16_le(s, mskidx); - in_uint32_le(s, mskformat); - in_uint16_le(s, mskwidth); - in_uint8(s, mskrepeat); - in_uint8(s, op); - in_sint16_le(s, srcx); - in_sint16_le(s, srcy); - in_sint16_le(s, mskx); - in_sint16_le(s, msky); - in_sint16_le(s, dstx); - in_sint16_le(s, dsty); - in_uint16_le(s, width); - in_uint16_le(s, height); - in_uint32_le(s, dstformat); - rv = mod->server_composite(mod, srcidx, srcformat, srcwidth, srcrepeat, - transform, mskflags, mskidx, mskformat, - mskwidth, mskrepeat, op, srcx, srcy, mskx, msky, - dstx, dsty, width, height, dstformat); + case 33: /* server_composite */ + rv = process_server_composite(mod, s); break; case 51: /* server_set_pointer_ex */ rv = process_server_set_pointer_ex(mod, s); break; case 60: /* server_paint_rect_shmem */ - in_sint16_le(s, x); - in_sint16_le(s, y); - in_uint16_le(s, cx); - in_uint16_le(s, cy); - in_uint32_le(s, flags); - in_uint32_le(s, frame_id); - in_uint32_le(s, shmem_id); - in_uint32_le(s, shmem_offset); - in_uint16_le(s, width); - in_uint16_le(s, height); - in_sint16_le(s, srcx); - in_sint16_le(s, srcy); - bmpdata = 0; - if (flags == 0) /* screen */ - { - if (mod->screen_shmem_id == 0) - { - mod->screen_shmem_id = shmem_id; - mod->screen_shmem_pixels = shmat(mod->screen_shmem_id, 0, 0); - } - if (mod->screen_shmem_pixels != 0) - { - bmpdata = mod->screen_shmem_pixels + shmem_offset; - } - } - if (bmpdata != 0) - { - rv = mod->server_paint_rect(mod, x, y, cx, cy, - bmpdata, width, height, - srcx, srcy); - } - else - { - rv = 1; - } - send_paint_rect_ack(mod, flags, x, y, cx, cy, frame_id); + rv = process_server_paint_rect_shmem(mod, s); + break; + case 61: /* server_paint_rect_shmem_ex */ + rv = process_server_paint_rect_shmem_ex(mod, s); break; - default: g_writeln("lib_mod_process_orders: unknown order type %d", type); rv = 0; break; } - return rv; } - /******************************************************************************/ /* return error */ static int APP_CC @@ -1062,6 +1504,11 @@ lib_mod_signal(struct mod *mod) int DEFAULT_CC lib_mod_end(struct mod *mod) { + if (mod->screen_shmem_pixels != 0) + { + g_shmdt(mod->screen_shmem_pixels); + mod->screen_shmem_pixels = 0; + } return 0; } diff --git a/xup/xup.h b/xup/xup.h index 9ae4f920..d8214f08 100644 --- a/xup/xup.h +++ b/xup/xup.h @@ -133,8 +133,12 @@ struct mod int mskformat, int mskwidth, int mskrepeat, int op, int srcx, int srcy, int mskx, int msky, int dstx, int dsty, int width, int height, int dstformat); + int (*server_paint_rects)(struct mod* v, + int num_drects, short *drects, + int num_crects, short *crects, + char *data, int width, int height, int flags); - tbus server_dumby[100 - 42]; /* align, 100 minus the number of server + tbus server_dumby[100 - 43]; /* align, 100 minus the number of server functions above */ /* common */ tbus handle; /* pointer to self as long */