diff options
160 files changed, 15173 insertions, 3133 deletions
diff --git a/Makefile.am b/Makefile.am index 9e0e42bd..98979bba 100644 --- a/Makefile.am +++ b/Makefile.am @@ -20,4 +20,5 @@ SUBDIRS = \ keygen \ docs \ instfiles \ - genkeymap + genkeymap \ + xrdpapi diff --git a/common/Makefile.am b/common/Makefile.am index 1bc5eeb6..33cfc1e5 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -5,7 +5,8 @@ AM_CFLAGS = \ -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \ -DXRDP_SBIN_PATH=\"${sbindir}\" \ -DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \ - -DXRDP_PID_PATH=\"${localstatedir}/run\" + -DXRDP_PID_PATH=\"${localstatedir}/run\" \ + -DXRDP_LOG_PATH=\"${localstatedir}/log\" lib_LTLIBRARIES = \ libcommon.la diff --git a/common/list.c b/common/list.c index 9df7f6a1..f67a08ab 100644 --- a/common/list.c +++ b/common/list.c @@ -205,7 +205,6 @@ void APP_CC list_dump_items(struct list* self) { int index; - tbus item; if (self->count == 0) { diff --git a/common/log.c b/common/log.c index 7bbdfc06..390b2bff 100644 --- a/common/log.c +++ b/common/log.c @@ -1,20 +1,24 @@ /* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - xrdp: A Remote Desktop Protocol server. - Copyright (C) Jay Sorg 2005-2010 + Copyright (c) 2005-2012 Jay Sorg + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + 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 + AUTHORS OR COPYRIGHT HOLDERS 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 <sys/types.h> @@ -24,23 +28,41 @@ #include <stdarg.h> #include <stdio.h> #include <time.h> - +#include "list.h" +#include "file.h" #include "os_calls.h" +#include "thread_calls.h" +/* Add a define here so that the log.h will hold more information + * when compiled from this C file. + * When compiled normally the log.h file only contain the public parts + * of the operators in this file. */ +#define LOGINTERNALSTUFF #include "log.h" +/* Here we store the current state and configuration of the log */ +static struct log_config* staticLogConfig = NULL; + +/* This file first start with all private functions. + In the end of the file the public functions is defined */ + /** * * @brief Opens log file * @param fname log file name * @return see open(2) return values - * + * */ -static int DEFAULT_CC -log_file_open(const char* fname) +int DEFAULT_CC +internal_log_file_open(const char* fname) { - return open(fname, O_WRONLY | O_CREAT | O_APPEND | O_SYNC, S_IRUSR | - S_IWUSR); + int ret = -1; + if (fname != NULL) + { + ret = open(fname, O_WRONLY | O_CREAT | O_APPEND | O_SYNC, + S_IRUSR | S_IWUSR); + } + return ret; } /** @@ -50,8 +72,8 @@ log_file_open(const char* fname) * @return syslog equivalent logging level * */ -static int DEFAULT_CC -log_xrdp2syslog(const int lvl) +int DEFAULT_CC +internal_log_xrdp2syslog(const enum logLevels lvl) { switch (lvl) { @@ -63,22 +85,23 @@ log_xrdp2syslog(const int lvl) return LOG_WARNING; case LOG_LEVEL_INFO: return LOG_INFO; - /* case LOG_LEVEL_DEBUG: */ + case LOG_LEVEL_DEBUG: + return LOG_DEBUG; default: + g_writeln("Undefined log level - programming error"); return LOG_DEBUG; } } /** - *ring - * @brief Converts xrdp log level to syslog logging level + * @brief Converts xrdp log levels to textual logging levels * @param lvl logging level - * @param str pointer to a st - * @return syslog equivalent logging level + * @param str pointer to a string, must be allocated before + * @return The log string in str pointer. * */ -static void DEFAULT_CC -log_lvl2str(int lvl, char* str) +void DEFAULT_CC +internal_log_lvl2str(const enum logLevels lvl, char* str) { switch (lvl) { @@ -94,115 +117,42 @@ log_lvl2str(int lvl, char* str) case LOG_LEVEL_INFO: snprintf(str, 9, "%s", "[INFO ] "); break; - /* case LOG_LEVEL_DEBUG: */ - default: + case LOG_LEVEL_DEBUG: snprintf(str, 9, "%s", "[DEBUG] "); break; + default: + snprintf(str, 9, "%s", "PRG ERR!"); + g_writeln("Programming error - undefined log level!!!"); } } /******************************************************************************/ -int DEFAULT_CC -log_message(struct log_config* l_cfg, const unsigned int lvl, const char* msg, ...) -{ - char buff[LOG_BUFFER_SIZE + 31]; /* 19 (datetime) 4 (space+cr+lf+\0) */ - va_list ap; - int len = 0; - int rv; - time_t now_t; - struct tm* now; - - rv = 0; - if (0 == l_cfg) - { - return LOG_ERROR_NO_CFG; - } - - if (0 > l_cfg->fd) - { - return LOG_ERROR_FILE_NOT_OPEN; - } - - now_t = time(&now_t); - now = localtime(&now_t); - - snprintf(buff, 21, "[%.4d%.2d%.2d-%.2d:%.2d:%.2d] ", (now->tm_year) + 1900, - (now->tm_mon) + 1, now->tm_mday, now->tm_hour, now->tm_min, - now->tm_sec); - - log_lvl2str(lvl, buff + 20); - - va_start(ap, msg); - len = vsnprintf(buff + 28, LOG_BUFFER_SIZE, msg, ap); - va_end(ap); - - /* checking for truncated messages */ - if (len > LOG_BUFFER_SIZE) - { - log_message(l_cfg, LOG_LEVEL_WARNING, "next message will be truncated"); - } - - /* forcing the end of message string */ - #ifdef _WIN32 - buff[len + 28] = '\r'; - buff[len + 29] = '\n'; - buff[len + 30] = '\0'; - #else - #ifdef _MACOS - buff[len + 28] = '\r'; - buff[len + 29] = '\0'; - #else - buff[len + 28] = '\n'; - buff[len + 29] = '\0'; - #endif - #endif - - if (l_cfg->enable_syslog && (lvl <= l_cfg->log_level)) - { - /* log to syslog */ - syslog(log_xrdp2syslog(lvl), buff + 20); - } - - if (lvl <= l_cfg->log_level) - { - /* log to console */ - g_printf((char*)buff); - - /* log to application logfile */ -#ifdef LOG_ENABLE_THREAD - pthread_mutex_lock(&(l_cfg->log_lock)); -#endif - rv = g_file_write(l_cfg->fd, (char*)buff, g_strlen((char*)buff)); -#ifdef LOG_ENABLE_THREAD - pthread_mutex_unlock(&(l_cfg->log_lock)); -#endif - } - return rv; -} - -/******************************************************************************/ -int DEFAULT_CC -log_start(struct log_config* l_cfg) +enum logReturns DEFAULT_CC +internal_log_start(struct log_config* l_cfg) { + enum logReturns ret = LOG_GENERAL_ERROR; if (0 == l_cfg) { - return LOG_ERROR_MALLOC; + ret = LOG_ERROR_MALLOC; + return ret; } - /* if logfile is NULL, we use a default logfile */ + /* if logfile is NULL, we return error */ if (0 == l_cfg->log_file) { - l_cfg->log_file = g_strdup("./myprogram.log"); + g_writeln("log_file not properly assigned"); + return ret; } - /* if progname is NULL, we use a default name */ + /* if progname is NULL, we ureturn error */ if (0 == l_cfg->program_name) { - l_cfg->program_name = g_strdup("myprogram"); + g_writeln("program_name not properly assigned"); + return ret; } /* open file */ - l_cfg->fd = log_file_open(l_cfg->log_file); + l_cfg->fd = internal_log_file_open(l_cfg->log_file); if (-1 == l_cfg->fd) { @@ -224,30 +174,25 @@ log_start(struct log_config* l_cfg) } /******************************************************************************/ -void DEFAULT_CC -log_end(struct log_config* l_cfg) +enum logReturns DEFAULT_CC +internal_log_end(struct log_config* l_cfg) { + enum logReturns ret = LOG_GENERAL_ERROR; /* if log is closed, quit silently */ if (0 == l_cfg) { - return; + return ret; } /* closing log file */ - log_message(l_cfg, LOG_LEVEL_ALWAYS, "shutting down log subsystem..."); + log_message(LOG_LEVEL_ALWAYS, "shutting down log subsystem..."); if (0 > l_cfg->fd) { - /* if syslog is enabled, close it */ - if (l_cfg->enable_syslog) - { - closelog(); - } + /* closing logfile... */ + g_file_close(l_cfg->fd); } - /* closing logfile... */ - g_file_close(l_cfg->fd); - /* if syslog is enabled, close it */ if (l_cfg->enable_syslog) { @@ -265,11 +210,17 @@ log_end(struct log_config* l_cfg) g_free(l_cfg->program_name); l_cfg->program_name = 0; } + ret = LOG_STARTUP_OK; + return ret; } -/******************************************************************************/ -int DEFAULT_CC -log_text2level(char* buf) +/** + * Converts a string representing th log level to a value + * @param buf + * @return + */ +enum logLevels DEFAULT_CC +internal_log_text2level(char* buf) { if (0 == g_strcasecmp(buf, "0") || 0 == g_strcasecmp(buf, "core")) @@ -292,5 +243,387 @@ log_text2level(char* buf) { return LOG_LEVEL_INFO; } + else if (0 == g_strcasecmp(buf, "4") || + 0 == g_strcasecmp(buf, "debug")) + { + return LOG_LEVEL_DEBUG; + } + g_writeln("Your configured log level is corrupt - we use debug log level"); return LOG_LEVEL_DEBUG; } + +enum logReturns DEFAULT_CC +internalReadConfiguration(const char* inFilename, const char* applicationName) +{ + int fd; + enum logReturns ret = LOG_GENERAL_ERROR; + struct list* sec; + struct list* param_n; + struct list* param_v; + + if (inFilename == NULL) + { + g_writeln("The inifile is null to readConfiguration!"); + return ret; + } + fd = g_file_open(inFilename); + if (-1 == fd) + { + ret = LOG_ERROR_NO_CFG; + g_writeln("We could not open the configuration file to read log parameters"); + return ret; + } + /* we initialize the memory for the configuration and set all content + to zero. */ + ret = internalInitAndAllocStruct(); + if (ret != LOG_STARTUP_OK) + { + return ret; + } + + sec = list_create(); + sec->auto_free = 1; + file_read_sections(fd, sec); + param_n = list_create(); + param_n->auto_free = 1; + param_v = list_create(); + param_v->auto_free = 1; + + /* read logging config */ + ret = internal_config_read_logging(fd, staticLogConfig, param_n, + param_v, applicationName); + if (ret != LOG_STARTUP_OK) + { + return ret; + } + /* cleanup */ + list_delete(sec); + list_delete(param_v); + list_delete(param_n); + g_file_close(fd); + return ret; +} + +/******************************************************************************/ +enum logReturns DEFAULT_CC +internal_config_read_logging(int file, struct log_config* lc, + struct list* param_n, + struct list* param_v, + const char* applicationName) +{ + int i; + char* buf; + char* temp_buf; + + list_clear(param_v); + list_clear(param_n); + + /* setting defaults */ + lc->program_name = g_strdup(applicationName); + lc->log_file = 0; + lc->fd = 0; + lc->log_level = LOG_LEVEL_DEBUG; + lc->enable_syslog = 0; + lc->syslog_level = LOG_LEVEL_DEBUG; + + file_read_section(file, SESMAN_CFG_LOGGING, param_n, param_v); + for (i = 0; i < param_n->count; i++) + { + buf = (char*)list_get_item(param_n, i); + if (0 == g_strcasecmp(buf, SESMAN_CFG_LOG_FILE)) + { + lc->log_file = g_strdup((char*)list_get_item(param_v, i)); + if (lc->log_file != NULL) + { + if (lc->log_file[0] != '/') + { + temp_buf = (char*)g_malloc(512, 0); + g_snprintf(temp_buf, 511, "%s/%s", XRDP_LOG_PATH, lc->log_file); + g_free(lc->log_file); + lc->log_file = temp_buf; + } + } + } + if (0 == g_strcasecmp(buf, SESMAN_CFG_LOG_LEVEL)) + { + lc->log_level = internal_log_text2level((char*)list_get_item(param_v, i)); + } + if (0 == g_strcasecmp(buf, SESMAN_CFG_LOG_ENABLE_SYSLOG)) + { + lc->enable_syslog = text2bool((char*)list_get_item(param_v, i)); + } + if (0 == g_strcasecmp(buf, SESMAN_CFG_LOG_SYSLOG_LEVEL)) + { + lc->syslog_level = internal_log_text2level((char*)list_get_item(param_v, i)); + } + } + + if (0 == lc->log_file) + { + lc->log_file = g_strdup("./sesman.log"); + } + + /* try to create path if not exist */ + g_create_path(lc->log_file); + + g_printf("logging configuration:\r\n"); + g_printf("\tLogFile: %s\r\n", lc->log_file); + g_printf("\tLogLevel: %i\r\n", lc->log_level); + g_printf("\tEnableSyslog: %i\r\n", lc->enable_syslog); + g_printf("\tSyslogLevel: %i\r\n", lc->syslog_level); + return LOG_STARTUP_OK; +} + +enum logReturns DEFAULT_CC +internalInitAndAllocStruct(void) +{ + enum logReturns ret = LOG_GENERAL_ERROR; + staticLogConfig = g_malloc(sizeof(struct log_config), 1); + if (staticLogConfig != NULL) + { + staticLogConfig->fd = -1; + staticLogConfig->enable_syslog = 0; + ret = LOG_STARTUP_OK; + } + else + { + g_writeln("could not allocate memory for log struct"); + ret = LOG_ERROR_MALLOC; + } + return ret; +} + +/* + * Here below the public functions + */ + + +/** + * + * @brief Reads sesman configuration + * @param s translates the strings "1", "true" and "yes" in 1 (true) and other strings in 0 + * @return 0 on false, 1 on 1,true, yes + * + */ +int APP_CC +text2bool(char* s) +{ + if (0 == g_strcasecmp(s, "1") || + 0 == g_strcasecmp(s, "true") || + 0 == g_strcasecmp(s, "yes")) + { + return 1; + } + return 0; +} + +enum logReturns DEFAULT_CC +log_start_from_param(const struct log_config* iniParams) +{ + enum logReturns ret = LOG_GENERAL_ERROR; + if (staticLogConfig != NULL) + { + log_message(LOG_LEVEL_ALWAYS, "Log already initialized"); + return ret; + } + if (iniParams == NULL) + { + g_writeln("inparam to log_start_from_param is NULL"); + return ret; + } + else + { + /*Copy the struct information*/ + ret = internalInitAndAllocStruct(); + if (ret != LOG_STARTUP_OK) + { + g_writeln("internalInitAndAllocStruct failed"); + return ret; + } + staticLogConfig->enable_syslog = iniParams->enable_syslog; + staticLogConfig->fd = iniParams->fd; + staticLogConfig->log_file = g_strdup(iniParams->log_file); + staticLogConfig->log_level = iniParams->log_level; + staticLogConfig->log_lock = iniParams->log_lock; + staticLogConfig->log_lock_attr = iniParams->log_lock_attr; + staticLogConfig->program_name = g_strdup(iniParams->program_name); + staticLogConfig->syslog_level = iniParams->syslog_level; + ret = internal_log_start(staticLogConfig); + if (ret != LOG_STARTUP_OK) + { + g_writeln("Could not start log"); + if (staticLogConfig != NULL) + { + g_free(staticLogConfig); + staticLogConfig = NULL; + } + } + } + return ret; +} + +/** + * This function initialize the log facilities according to the configuration + * file, that is described by the in parameter. + * @param iniFile + * @param applicationName, the name that is used in the log for the running application + * @return 0 on success + */ +enum logReturns DEFAULT_CC +log_start(const char* iniFile, const char* applicationName) +{ + enum logReturns ret = LOG_GENERAL_ERROR; + if (applicationName == NULL) + { + g_writeln("Programming error your application name cannot be null"); + return ret; + } + ret = internalReadConfiguration(iniFile, applicationName); + if (ret == LOG_STARTUP_OK) + { + ret = internal_log_start(staticLogConfig); + if (ret != LOG_STARTUP_OK) + { + g_writeln("Could not start log"); + if (staticLogConfig != NULL) + { + g_free(staticLogConfig); + staticLogConfig = NULL; + } + } + } + else + { + g_writeln("Error reading configuration for log based on config: %s", + iniFile); + } + return ret; +} + +/** + * Function that terminates all logging + * @return + */ +enum logReturns DEFAULT_CC +log_end(void) +{ + enum logReturns ret = LOG_GENERAL_ERROR; + ret = internal_log_end(staticLogConfig); + if (staticLogConfig != NULL) + { + g_free(staticLogConfig); + staticLogConfig = NULL; + } + return ret; +} + +enum logReturns DEFAULT_CC +log_message(const enum logLevels lvl, const char* msg, ...) +{ + char buff[LOG_BUFFER_SIZE + 31]; /* 19 (datetime) 4 (space+cr+lf+\0) */ + va_list ap; + int len = 0; + enum logReturns rv = LOG_STARTUP_OK; + int writereply = 0; + time_t now_t; + struct tm* now; + if (staticLogConfig == NULL) + { + g_writeln("The log reference is NULL - log not initialized properly"); + return LOG_ERROR_NO_CFG; + } + if (0 > staticLogConfig->fd && staticLogConfig->enable_syslog == 0) + { + return LOG_ERROR_FILE_NOT_OPEN; + } + + now_t = time(&now_t); + now = localtime(&now_t); + + snprintf(buff, 21, "[%.4d%.2d%.2d-%.2d:%.2d:%.2d] ", now->tm_year + 1900, + now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, + now->tm_sec); + + internal_log_lvl2str(lvl, buff + 20); + + va_start(ap, msg); + len = vsnprintf(buff + 28, LOG_BUFFER_SIZE, msg, ap); + va_end(ap); + + /* checking for truncated messages */ + if (len > LOG_BUFFER_SIZE) + { + log_message(LOG_LEVEL_WARNING, "next message will be truncated"); + } + + /* forcing the end of message string */ +#ifdef _WIN32 + buff[len + 28] = '\r'; + buff[len + 29] = '\n'; + buff[len + 30] = '\0'; +#else +#ifdef _MACOS + buff[len + 28] = '\r'; + buff[len + 29] = '\0'; +#else + buff[len + 28] = '\n'; + buff[len + 29] = '\0'; +#endif +#endif + + if (staticLogConfig->enable_syslog && (lvl <= staticLogConfig->syslog_level)) + { + /* log to syslog*/ + /* %s fix compiler warning 'not a string literal' */ + syslog(internal_log_xrdp2syslog(lvl), "(%d)(%ld)%s", g_getpid(), + tc_get_threadid(), buff + 20); + } + + if (lvl <= staticLogConfig->log_level) + { + /* log to console */ + g_printf(buff); + + /* log to application logfile */ +#ifdef LOG_ENABLE_THREAD + pthread_mutex_lock(&(staticLogConfig->log_lock)); +#endif + if (staticLogConfig->fd > 0) + { + writereply = g_file_write(staticLogConfig->fd, buff, g_strlen(buff)); + if (writereply <= 0) + { + rv = LOG_ERROR_NULL_FILE; + } + } +#ifdef LOG_ENABLE_THREAD + pthread_mutex_unlock(&(staticLogConfig->log_lock)); +#endif + } + return rv; +} + +/** + * Return the configured log file name + * @return + */ +char* DEFAULT_CC +getLogFile(char* replybuf, int bufsize) +{ + if (staticLogConfig) + { + if (staticLogConfig->log_file) + { + g_strncpy(replybuf, staticLogConfig->log_file, bufsize); + } + else + { + g_sprintf(replybuf, "The log_file name is NULL"); + } + } + else + { + g_snprintf(replybuf, bufsize, "The log is not properly started"); + } + return replybuf; +} diff --git a/common/log.h b/common/log.h index acb10fea..cc355b18 100644 --- a/common/log.h +++ b/common/log.h @@ -1,20 +1,24 @@ /* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - xrdp: A Remote Desktop Protocol server. - Copyright (C) Jay Sorg 2005-2010 + Copyright (c) 2005-2012 Jay Sorg + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + 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 + AUTHORS OR COPYRIGHT HOLDERS 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 LOG_H @@ -28,27 +32,40 @@ #define LOG_BUFFER_SIZE 1024 /* logging levels */ -#define LOG_LEVEL_ALWAYS 0 -#define LOG_LEVEL_ERROR 1 -#define LOG_LEVEL_WARNING 2 -#define LOG_LEVEL_INFO 3 -#define LOG_LEVEL_DEBUG 4 +enum logLevels +{ + LOG_LEVEL_ALWAYS = 0, + LOG_LEVEL_ERROR, + LOG_LEVEL_WARNING, + LOG_LEVEL_INFO, + LOG_LEVEL_DEBUG +}; /* startup return values */ -#define LOG_STARTUP_OK 0 -#define LOG_ERROR_MALLOC 1 -#define LOG_ERROR_NULL_FILE 2 -#define LOG_ERROR_FILE_OPEN 3 -#define LOG_ERROR_NO_CFG 4 -#define LOG_ERROR_FILE_NOT_OPEN 5 +enum logReturns +{ + LOG_STARTUP_OK = 0, + LOG_ERROR_MALLOC, + LOG_ERROR_NULL_FILE, + LOG_ERROR_FILE_OPEN, + LOG_ERROR_NO_CFG, + LOG_ERROR_FILE_NOT_OPEN, + LOG_GENERAL_ERROR +}; + +#define SESMAN_CFG_LOGGING "Logging" +#define SESMAN_CFG_LOG_FILE "LogFile" +#define SESMAN_CFG_LOG_LEVEL "LogLevel" +#define SESMAN_CFG_LOG_ENABLE_SYSLOG "EnableSyslog" +#define SESMAN_CFG_LOG_SYSLOG_LEVEL "SyslogLevel" /* enable threading */ /*#define LOG_ENABLE_THREAD*/ #ifdef DEBUG - #define LOG_DBG(lcfg,args...) log_message((lcfg), LOG_LEVEL_DEBUG, args); +#define LOG_DBG(args...) log_message(LOG_LEVEL_DEBUG, args); #else - #define LOG_DBG(lcfg,args...) +#define LOG_DBG(args...) #endif struct log_config @@ -63,16 +80,8 @@ struct log_config pthread_mutexattr_t log_lock_attr; }; -/** - * - * @brief Logs a message. Optionally logs the same message on syslog - * @param lvl The level of the logged message - * @param msg The message to be logged - * @return - * - */ -int DEFAULT_CC -log_message(struct log_config* l_cfg, const unsigned int lvl, const char* msg, ...); +/* internal functions, only used in log.c if this ifdef is defined.*/ +#ifdef LOGINTERNALSTUFF /** * @@ -81,8 +90,8 @@ log_message(struct log_config* l_cfg, const unsigned int lvl, const char* msg, . * @return * */ -int DEFAULT_CC -log_start(struct log_config* l_cfg); +enum logReturns DEFAULT_CC +internal_log_start(struct log_config* l_cfg); /** * @@ -90,8 +99,16 @@ log_start(struct log_config* l_cfg); * @param l_cfg pointer to the logging subsystem to stop * */ +enum logReturns DEFAULT_CC +internal_log_end(struct log_config* l_cfg); + +/** + * Converts a log level to a string + * @param lvl, the loglevel + * @param str pointer where the string will be stored. + */ void DEFAULT_CC -log_end(struct log_config* l_cfg); +internal_log_lvl2str(const enum logLevels lvl, char* str); /** * @@ -100,8 +117,82 @@ log_end(struct log_config* l_cfg); * @return The corresponding level or LOG_LEVEL_DEBUG if error * */ -int DEFAULT_CC -log_text2level(char* s); +enum logLevels DEFAULT_CC +internal_log_text2level(char* s); + +/** + * A function that init our struct that holds all state and + * also init its content. + * @return LOG_STARTUP_OK or LOG_ERROR_MALLOC + */ +enum logReturns DEFAULT_CC +internalInitAndAllocStruct(void); +/** + * Read configuration from a file and store the values in lists. + * @param file + * @param lc + * @param param_n + * @param param_v + * @param applicationName, the application name used in the log events. + * @return + */ +enum logReturns DEFAULT_CC +internal_config_read_logging(int file, struct log_config* lc, + struct list* param_n, + struct list* param_v, + const char *applicationName); +/*End of internal functions*/ #endif +/** + * This function initialize the log facilities according to the configuration + * file, that is described by the in parameter. + * @param iniFile + * @param applicationName, the name that is used in the log for the running application + * @return LOG_STARTUP_OK on success + */ +enum logReturns DEFAULT_CC +log_start(const char* iniFile, const char* applicationName); +/** + * An alternative log_start where the caller gives the params directly. + * @param iniParams + * @return + */ +enum logReturns DEFAULT_CC +log_start_from_param(const struct log_config *iniParams); +/** + * Function that terminates all logging + * @return + */ +enum logReturns DEFAULT_CC +log_end(void); + +/** + * the log function that all files use to log an event. + * @param lvl, the loglevel + * @param msg, the logtext. + * @param ... + * @return + */ +enum logReturns DEFAULT_CC +log_message(const enum logLevels lvl, const char* msg, ...); + +/** + * + * @brief Reads configuration + * @param s translates the strings "1", "true" and "yes" in 1 (true) and + * other strings in 0 + * @return 0 on success, 1 on failure + * + */ +int APP_CC text2bool(char* s); + +/** + * This function returns the configured file name for the logfile + * @param replybuf the buffer where the reply is stored + * @param bufsize how big is the reply buffer. + * @return + */ +char *getLogFile(char *replybuf, int bufsize); +#endif diff --git a/common/os_calls.c b/common/os_calls.c index 692dc015..6b55f2f7 100644 --- a/common/os_calls.c +++ b/common/os_calls.c @@ -71,6 +71,10 @@ extern char** environ; #endif +#if defined(__linux__) +#include <linux/unistd.h> +#endif + /* for solaris */ #if !defined(PF_LOCAL) #define PF_LOCAL AF_UNIX @@ -321,9 +325,11 @@ g_getchar(void) } /*****************************************************************************/ +/*Returns 0 on success*/ int APP_CC g_tcp_set_no_delay(int sck) { + int ret = 1; /* error */ #if defined(_WIN32) int option_value; int option_len; @@ -341,11 +347,63 @@ g_tcp_set_no_delay(int sck) { option_value = 1; option_len = sizeof(option_value); - setsockopt(sck, IPPROTO_TCP, TCP_NODELAY, (char*)&option_value, - option_len); + if (setsockopt(sck, IPPROTO_TCP, TCP_NODELAY, (char*)&option_value, + option_len) == 0) + { + ret = 0; /* success */ + } + else + { + g_writeln("Error setting tcp_nodelay"); + } } } - return 0; + else + { + g_writeln("Error getting tcp_nodelay"); + } + return ret; +} + +/*****************************************************************************/ +/*Returns 0 on success*/ +int APP_CC +g_tcp_set_keepalive(int sck) +{ + int ret = 1; /* error */ +#if defined(_WIN32) + int option_value; + int option_len; +#else + int option_value; + unsigned int option_len; +#endif + + option_len = sizeof(option_value); + /* SOL_TCP IPPROTO_TCP */ + if (getsockopt(sck, SOL_SOCKET, SO_KEEPALIVE, (char*)&option_value, + &option_len) == 0) + { + if (option_value == 0) + { + option_value = 1; + option_len = sizeof(option_value); + if (setsockopt(sck, SOL_SOCKET, SO_KEEPALIVE, (char*)&option_value, + option_len) == 0) + { + ret = 0; /* success */ + } + else + { + g_writeln("Error setting tcp_keepalive"); + } + } + } + else + { + g_writeln("Error getting tcp_keepalive"); + } + return ret; } /*****************************************************************************/ @@ -415,7 +473,6 @@ g_tcp_close(int sck) { return; } - shutdown(sck, 2); #if defined(_WIN32) closesocket(sck); #else @@ -563,31 +620,37 @@ g_tcp_accept(int sck) /*****************************************************************************/ void APP_CC -g_write_ip_address(int rcv_sck, char* ip_address) +g_write_ip_address(int rcv_sck, char* ip_address, int bytes) { struct sockaddr_in s; struct in_addr in; +#if defined(_WIN32) int len; +#else + unsigned int len; +#endif int ip_port; + int ok; - memset(&s,0,sizeof(&s)); + ok = 0; + memset(&s, 0, sizeof(s)); len = sizeof(s); - getpeername(rcv_sck,(struct sockaddr*)&s, &len); - - memset(&in,0,sizeof(in)); - in.s_addr = s.sin_addr.s_addr; - - ip_port = ntohs(s.sin_port); - - if (ip_port != 0) + if (getpeername(rcv_sck,(struct sockaddr*)&s, &len) == 0) { - sprintf(ip_address, "%s:%d - socket: %d", inet_ntoa(in), ip_port, rcv_sck); + memset(&in, 0, sizeof(in)); + in.s_addr = s.sin_addr.s_addr; + ip_port = ntohs(s.sin_port); + if (ip_port != 0) + { + ok = 1; + snprintf(ip_address, bytes, "%s:%d - socket: %d", inet_ntoa(in), + ip_port, rcv_sck); + } } - else + if (!ok) { - sprintf(ip_address, "NULL:NULL - socket: %d", rcv_sck); + snprintf(ip_address, bytes, "NULL:NULL - socket: %d", rcv_sck); } - } /*****************************************************************************/ @@ -998,6 +1061,19 @@ g_delete_wait_obj(tbus obj) /*****************************************************************************/ /* returns error */ +/* close but do not delete the wait obj, used after fork */ +int APP_CC +g_close_wait_obj(tbus obj) +{ +#ifdef _WIN32 +#else + close((int)obj); +#endif + return 0; +} + +/*****************************************************************************/ +/* returns error */ int APP_CC g_obj_wait(tbus* read_objs, int rcount, tbus* write_objs, int wcount, int mstimeout) @@ -1056,28 +1132,47 @@ g_obj_wait(tbus* read_objs, int rcount, tbus* write_objs, int wcount, } FD_ZERO(&rfds); FD_ZERO(&wfds); - for (i = 0; i < rcount; i++) + /* Find the highest descriptor number in read_obj */ + if (read_objs!=NULL) { - sck = (int)(read_objs[i]); - if (sck > 0) { - FD_SET(sck, &rfds); - if (sck > max) + for (i = 0; i < rcount; i++) + { + sck = (int)(read_objs[i]); + if (sck > 0) { - max = sck; + FD_SET(sck, &rfds); + if (sck > max) + { + max = sck; /* max holds the highest socket/descriptor number */ + } } } } - for (i = 0; i < wcount; i++) + else if (rcount>0) + { + g_writeln("Programming error read_objs is null"); + return 1; /* error */ + } + if (write_objs!=NULL) { - sck = (int)(write_objs[i]); - if (sck > 0) { - FD_SET(sck, &wfds); - if (sck > max) + for (i = 0; i < wcount; i++) + { + sck = (int)(write_objs[i]); + if (sck > 0) { - max = sck; + FD_SET(sck, &wfds); + if (sck > max) + { + max = sck; /* max holds the highest socket/descriptor number */ + } } } } + else if (wcount > 0) + { + g_writeln("Programming error write_objs is null"); + return 1; /* error */ + } res = select(max + 1, &rfds, &wfds, 0, ptime); if (res < 0) { @@ -1089,7 +1184,7 @@ g_obj_wait(tbus* read_objs, int rcount, tbus* write_objs, int wcount, { return 0; } - return 1; + return 1; /* error */ } return 0; #endif @@ -1309,7 +1404,7 @@ g_mkdir(const char* dirname) /*****************************************************************************/ /* gets the current working directory and puts up to maxlen chars in - dirname + dirname always returns 0 */ char* APP_CC g_get_current_dir(char* dirname, int maxlen) @@ -1391,6 +1486,44 @@ g_create_dir(const char* dirname) } /*****************************************************************************/ +/* will try to create directories up to last / in name + example /tmp/a/b/c/readme.txt will try to create /tmp/a/b/c + returns boolean */ +int APP_CC +g_create_path(const char* path) +{ + char* pp; + char* sp; + char* copypath; + int status; + + status = 1; + copypath = g_strdup(path); + pp = copypath; + sp = strchr(pp, '/'); + while (sp != 0) + { + if (sp != pp) + { + *sp = 0; + if (!g_directory_exist(copypath)) + { + if (!g_create_dir(copypath)) + { + status = 0; + break; + } + } + *sp = '/'; + } + pp = sp + 1; + sp = strchr(pp, '/'); + } + g_free(copypath); + return status; +} + +/*****************************************************************************/ /* returns boolean */ int APP_CC g_remove_dir(const char* dirname) @@ -1511,12 +1644,38 @@ g_strdup(const char* in) } len = g_strlen(in); p = (char*)g_malloc(len + 1, 0); - if (p != NULL) { + if (p != NULL) + { g_strcpy(p, in); } return p; } +/*****************************************************************************/ +/* if in = 0, return 0 else return newly alloced copy of input string + * if the input string is larger than maxlen the returned string will be + * truncated. All strings returned will include null termination*/ +char* APP_CC +g_strndup(const char* in, const unsigned int maxlen) +{ + int len; + char* p; + if (in == 0) + { + return 0; + } + len = g_strlen(in); + if (len>maxlen) + { + len = maxlen - 1; + } + p = (char*)g_malloc(len + 2, 0); + if (p != NULL) + { + g_strncpy(p, in,len+1); + } + return p; +} /*****************************************************************************/ int APP_CC g_strcmp(const char* c1, const char* c2) diff --git a/common/os_calls.h b/common/os_calls.h index 5c7d848e..41b221bf 100644 --- a/common/os_calls.h +++ b/common/os_calls.h @@ -64,6 +64,8 @@ g_getchar(void); int APP_CC g_tcp_set_no_delay(int sck); int APP_CC +g_tcp_set_keepalive(int sck); +int APP_CC g_tcp_socket(void); int APP_CC g_tcp_local_socket(void); @@ -104,7 +106,7 @@ g_tcp_can_recv(int sck, int millis); int APP_CC g_tcp_select(int sck1, int sck2); void APP_CC -g_write_ip_address(int rcv_sck, char* ip_address); +g_write_ip_address(int rcv_sck, char* ip_address, int bytes); void APP_CC g_sleep(int msecs); tbus APP_CC @@ -122,6 +124,8 @@ g_is_wait_obj_set(tbus obj); int APP_CC g_delete_wait_obj(tbus obj); int APP_CC +g_close_wait_obj(tbus obj); +int APP_CC g_obj_wait(tbus* read_objs, int rcount, tbus* write_objs, int wcount, int mstimeout); void APP_CC @@ -159,6 +163,8 @@ g_directory_exist(const char* dirname); int APP_CC g_create_dir(const char* dirname); int APP_CC +g_create_path(const char* path); +int APP_CC g_remove_dir(const char* dirname); int APP_CC g_file_delete(const char* filename); @@ -174,6 +180,8 @@ char* APP_CC g_strcat(char* dest, const char* src); char* APP_CC g_strdup(const char* in); +char* APP_CC +g_strndup(const char* in, const unsigned int maxlen); int APP_CC g_strcmp(const char* c1, const char* c2); int APP_CC diff --git a/common/rail.h b/common/rail.h new file mode 100644 index 00000000..deed3a9e --- /dev/null +++ b/common/rail.h @@ -0,0 +1,147 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2012 + * + * 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. + */ + +#if !defined(_RAIL_H) +#define _RAIL_H + +/* + ORDER_TYPE_WINDOW + WINDOW_ORDER_TYPE_WINDOW + WINDOW_ORDER_ICON + WINDOW_ORDER_CACHED_ICON + WINDOW_ORDER_STATE_DELETED + WINDOW_ORDER_STATE_NEW on + WINDOW_ORDER_STATE_NEW off + WINDOW_ORDER_TYPE_NOTIFY + WINDOW_ORDER_STATE_DELETED + WINDOW_ORDER_STATE_NEW on + WINDOW_ORDER_STATE_NEW off + WINDOW_ORDER_TYPE_DESKTOP + WINDOW_ORDER_FIELD_DESKTOP_NONE on + WINDOW_ORDER_FIELD_DESKTOP_NONE off +*/ + +/* Window Order Header Flags */ +#define WINDOW_ORDER_TYPE_WINDOW 0x01000000 +#define WINDOW_ORDER_TYPE_NOTIFY 0x02000000 +#define WINDOW_ORDER_TYPE_DESKTOP 0x04000000 +#define WINDOW_ORDER_STATE_NEW 0x10000000 +#define WINDOW_ORDER_STATE_DELETED 0x20000000 +#define WINDOW_ORDER_FIELD_OWNER 0x00000002 +#define WINDOW_ORDER_FIELD_STYLE 0x00000008 +#define WINDOW_ORDER_FIELD_SHOW 0x00000010 +#define WINDOW_ORDER_FIELD_TITLE 0x00000004 +#define WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET 0x00004000 +#define WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE 0x00010000 +#define WINDOW_ORDER_FIELD_RP_CONTENT 0x00020000 +#define WINDOW_ORDER_FIELD_ROOT_PARENT 0x00040000 +#define WINDOW_ORDER_FIELD_WND_OFFSET 0x00000800 +#define WINDOW_ORDER_FIELD_WND_CLIENT_DELTA 0x00008000 +#define WINDOW_ORDER_FIELD_WND_SIZE 0x00000400 +#define WINDOW_ORDER_FIELD_WND_RECTS 0x00000100 +#define WINDOW_ORDER_FIELD_VIS_OFFSET 0x00001000 +#define WINDOW_ORDER_FIELD_VISIBILITY 0x00000200 +#define WINDOW_ORDER_FIELD_ICON_BIG 0x00002000 +#define WINDOW_ORDER_ICON 0x40000000 +#define WINDOW_ORDER_CACHED_ICON 0x80000000 +#define WINDOW_ORDER_FIELD_NOTIFY_VERSION 0x00000008 +#define WINDOW_ORDER_FIELD_NOTIFY_TIP 0x00000001 +#define WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP 0x00000002 +#define WINDOW_ORDER_FIELD_NOTIFY_STATE 0x00000004 +#define WINDOW_ORDER_FIELD_DESKTOP_NONE 0x00000001 +#define WINDOW_ORDER_FIELD_DESKTOP_HOOKED 0x00000002 +#define WINDOW_ORDER_FIELD_DESKTOP_ARC_COMPLETED 0x00000004 +#define WINDOW_ORDER_FIELD_DESKTOP_ARC_BEGAN 0x00000008 +#define WINDOW_ORDER_FIELD_DESKTOP_ZORDER 0x00000010 +#define WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND 0x00000020 + +struct rail_icon_info +{ + int bpp; + int width; + int height; + int cmap_bytes; + int mask_bytes; + int data_bytes; + char* mask; + char* cmap; + char* data; +}; + +struct rail_window_rect +{ + short left; + short top; + short right; + short bottom; +}; + +struct rail_notify_icon_infotip +{ + int timeout; + int flags; + char* text; + char* title; +}; + +struct rail_window_state_order +{ + int owner_window_id; + int style; + int extended_style; + int show_state; + char* title_info; + int client_offset_x; + int client_offset_y; + int client_area_width; + int client_area_height; + int rp_content; + int root_parent_handle; + int window_offset_x; + int window_offset_y; + int window_client_delta_x; + int window_client_delta_y; + int window_width; + int window_height; + int num_window_rects; + struct rail_window_rect* window_rects; + int visible_offset_x; + int visible_offset_y; + int num_visibility_rects; + struct rail_window_rect* visibility_rects; +}; + +struct rail_notify_state_order +{ + int version; + char* tool_tip; + struct rail_notify_icon_infotip infotip; + int state; + int icon_cache_entry; + int icon_cache_id; + struct rail_icon_info icon_info; +}; + +struct rail_monitored_desktop_order +{ + int active_window_id; + int num_window_ids; + int* window_ids; +}; + +#endif diff --git a/common/trans.c b/common/trans.c index f5549f06..4e1f0da6 100644 --- a/common/trans.c +++ b/common/trans.c @@ -69,7 +69,7 @@ trans_delete(struct trans* self) /*****************************************************************************/ int APP_CC -trans_get_wait_objs(struct trans* self, tbus* objs, int* count, int* timeout) +trans_get_wait_objs(struct trans* self, tbus* objs, int* count) { if (self == 0) { diff --git a/common/trans.h b/common/trans.h index bb0f42c0..8e8d942a 100644 --- a/common/trans.h +++ b/common/trans.h @@ -64,7 +64,7 @@ trans_create(int mode, int in_size, int out_size); void APP_CC trans_delete(struct trans* self); int APP_CC -trans_get_wait_objs(struct trans* self, tbus* objs, int* count, int* timeout); +trans_get_wait_objs(struct trans* self, tbus* objs, int* count); int APP_CC trans_check_wait_objs(struct trans* self); int APP_CC diff --git a/common/xrdp_client_info.h b/common/xrdp_client_info.h index 7fe93c26..f95543a3 100644 --- a/common/xrdp_client_info.h +++ b/common/xrdp_client_info.h @@ -40,7 +40,7 @@ struct xrdp_client_info int cache3_entries; int cache3_size; int bitmap_cache_persist_enable; /* 0 or 2 */ - int bitmap_cache_version; /* 0 = original version, 2 = v2 */ + int bitmap_cache_version; /* ored 1 = original version, 2 = v2, 4 = v3 */ /* pointer info */ int pointer_cache_entries; /* other */ @@ -74,6 +74,23 @@ struct xrdp_client_info int offscreen_cache_size; int offscreen_cache_entries; int rfx; + /* CAPSETTYPE_RAIL */ + int rail_support_level; + /* CAPSETTYPE_WINDOW */ + int wnd_support_level; + int wnd_num_icon_caches; + int wnd_num_icon_cache_entries; + /* codecs */ + int rfx_codec_id; + int rfx_prop_len; + char rfx_prop[64]; + int ns_codec_id; + int ns_prop_len; + char ns_prop[64]; + int jpeg_codec_id; + int jpeg_prop_len; + char jpeg_prop[64]; + int v3_codec_id; }; #endif diff --git a/common/xrdp_constants.h b/common/xrdp_constants.h index 1faeea33..1aa18eb5 100644 --- a/common/xrdp_constants.h +++ b/common/xrdp_constants.h @@ -323,16 +323,22 @@ #define CF_GDIOBJLAST 1023 /* Sound format constants */ -#define WAVE_FORMAT_PCM 1 +#define WAVE_FORMAT_PCM 1 #define WAVE_FORMAT_ADPCM 2 #define WAVE_FORMAT_ALAW 6 #define WAVE_FORMAT_MULAW 7 /* Virtual channel options */ -#define CHANNEL_OPTION_INITIALIZED 0x80000000 -#define CHANNEL_OPTION_ENCRYPT_RDP 0x40000000 -#define CHANNEL_OPTION_COMPRESS_RDP 0x00800000 -#define CHANNEL_OPTION_SHOW_PROTOCOL 0x00200000 +#define XR_CHANNEL_OPTION_SHOW_PROTOCOL 0x00200000 +#define XR_CHANNEL_OPTION_COMPRESS 0x00400000 +#define XR_CHANNEL_OPTION_COMPRESS_RDP 0x00800000 +#define XR_CHANNEL_OPTION_PRI_LOW 0x02000000 +#define XR_CHANNEL_OPTION_PRI_MED 0x04000000 +#define XR_CHANNEL_OPTION_PRI_HIGH 0x08000000 +#define XR_CHANNEL_OPTION_ENCRYPT_CS 0x10000000 +#define XR_CHANNEL_OPTION_ENCRYPT_SC 0x20000000 +#define XR_CHANNEL_OPTION_ENCRYPT_RDP 0x40000000 +#define XR_CHANNEL_OPTION_INITIALIZED 0x80000000 /* NT status codes for RDPDR */ #define STATUS_SUCCESS 0x00000000 @@ -417,6 +423,12 @@ #define RDP_ORDER_RAW_BMPCACHE2 4 #define RDP_ORDER_BMPCACHE2 5 #define RDP_ORDER_BRUSHCACHE 7 +#define RDP_ORDER_BMPCACHE3 8 + +/* orderSupportExFlags (2 bytes): A 16-bit, unsigned integer. + Extended order support flags. */ +#define XR_ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT 0x0002 +#define XR_ORDERFLAGS_EX_ALTSEC_FRAME_MARKER_SUPPORT 0x0004 /* drawable types */ #define WND_TYPE_BITMAP 0 @@ -429,6 +441,7 @@ #define WND_TYPE_COMBO 7 #define WND_TYPE_SPECIAL 8 #define WND_TYPE_LISTBOX 9 +#define WND_TYPE_OFFSCREEN 10 /* button states */ #define BUTTON_STATE_UP 0 @@ -495,10 +508,18 @@ #define SURCMDS_FRAMEMARKER 0x00000010 #define SURCMDS_STREAMSUFRACEBITS 0x00000040 +/* CODEC_GUID_NSCODEC 0xCA8D1BB9000F154F589FAE2D1A87E2D6 */ +#define XR_CODEC_GUID_NSCODEC \ + "\xb9\x1b\x8d\xca\x0f\x00\x4f\x15\x58\x9f\xae\x2d\x1a\x87\xe2\xd6" + /* CODEC_GUID_REMOTEFX 0x76772F12BD724463AFB3B73C9C6F7886 */ -#define CODEC_GUID_REMOTEFX \ +#define XR_CODEC_GUID_REMOTEFX \ "\x12\x2F\x77\x76\x72\xBD\x63\x44\xAF\xB3\xB7\x3C\x9C\x6F\x78\x86" +/* CODEC_GUID_JPEG 0x430C9EED1BAF4CE6869ACB8B37B66237*/ +#define XR_CODEC_GUID_JPEG \ + "\xE6\x4C\xAF\x1B\xED\x9E\x0C\x43\x86\x9A\xCB\x8B\x37\xB6\x62\x37" + #define RDP_CAPSET_SURFCMDS 0x1c #define RDP_CAPLEN_SURFCMDS 0x0c #define RDP_CAPSET_BMPCODECS 0x1d diff --git a/common/xrdp_rail.h b/common/xrdp_rail.h new file mode 100644 index 00000000..deed3a9e --- /dev/null +++ b/common/xrdp_rail.h @@ -0,0 +1,147 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2012 + * + * 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. + */ + +#if !defined(_RAIL_H) +#define _RAIL_H + +/* + ORDER_TYPE_WINDOW + WINDOW_ORDER_TYPE_WINDOW + WINDOW_ORDER_ICON + WINDOW_ORDER_CACHED_ICON + WINDOW_ORDER_STATE_DELETED + WINDOW_ORDER_STATE_NEW on + WINDOW_ORDER_STATE_NEW off + WINDOW_ORDER_TYPE_NOTIFY + WINDOW_ORDER_STATE_DELETED + WINDOW_ORDER_STATE_NEW on + WINDOW_ORDER_STATE_NEW off + WINDOW_ORDER_TYPE_DESKTOP + WINDOW_ORDER_FIELD_DESKTOP_NONE on + WINDOW_ORDER_FIELD_DESKTOP_NONE off +*/ + +/* Window Order Header Flags */ +#define WINDOW_ORDER_TYPE_WINDOW 0x01000000 +#define WINDOW_ORDER_TYPE_NOTIFY 0x02000000 +#define WINDOW_ORDER_TYPE_DESKTOP 0x04000000 +#define WINDOW_ORDER_STATE_NEW 0x10000000 +#define WINDOW_ORDER_STATE_DELETED 0x20000000 +#define WINDOW_ORDER_FIELD_OWNER 0x00000002 +#define WINDOW_ORDER_FIELD_STYLE 0x00000008 +#define WINDOW_ORDER_FIELD_SHOW 0x00000010 +#define WINDOW_ORDER_FIELD_TITLE 0x00000004 +#define WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET 0x00004000 +#define WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE 0x00010000 +#define WINDOW_ORDER_FIELD_RP_CONTENT 0x00020000 +#define WINDOW_ORDER_FIELD_ROOT_PARENT 0x00040000 +#define WINDOW_ORDER_FIELD_WND_OFFSET 0x00000800 +#define WINDOW_ORDER_FIELD_WND_CLIENT_DELTA 0x00008000 +#define WINDOW_ORDER_FIELD_WND_SIZE 0x00000400 +#define WINDOW_ORDER_FIELD_WND_RECTS 0x00000100 +#define WINDOW_ORDER_FIELD_VIS_OFFSET 0x00001000 +#define WINDOW_ORDER_FIELD_VISIBILITY 0x00000200 +#define WINDOW_ORDER_FIELD_ICON_BIG 0x00002000 +#define WINDOW_ORDER_ICON 0x40000000 +#define WINDOW_ORDER_CACHED_ICON 0x80000000 +#define WINDOW_ORDER_FIELD_NOTIFY_VERSION 0x00000008 +#define WINDOW_ORDER_FIELD_NOTIFY_TIP 0x00000001 +#define WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP 0x00000002 +#define WINDOW_ORDER_FIELD_NOTIFY_STATE 0x00000004 +#define WINDOW_ORDER_FIELD_DESKTOP_NONE 0x00000001 +#define WINDOW_ORDER_FIELD_DESKTOP_HOOKED 0x00000002 +#define WINDOW_ORDER_FIELD_DESKTOP_ARC_COMPLETED 0x00000004 +#define WINDOW_ORDER_FIELD_DESKTOP_ARC_BEGAN 0x00000008 +#define WINDOW_ORDER_FIELD_DESKTOP_ZORDER 0x00000010 +#define WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND 0x00000020 + +struct rail_icon_info +{ + int bpp; + int width; + int height; + int cmap_bytes; + int mask_bytes; + int data_bytes; + char* mask; + char* cmap; + char* data; +}; + +struct rail_window_rect +{ + short left; + short top; + short right; + short bottom; +}; + +struct rail_notify_icon_infotip +{ + int timeout; + int flags; + char* text; + char* title; +}; + +struct rail_window_state_order +{ + int owner_window_id; + int style; + int extended_style; + int show_state; + char* title_info; + int client_offset_x; + int client_offset_y; + int client_area_width; + int client_area_height; + int rp_content; + int root_parent_handle; + int window_offset_x; + int window_offset_y; + int window_client_delta_x; + int window_client_delta_y; + int window_width; + int window_height; + int num_window_rects; + struct rail_window_rect* window_rects; + int visible_offset_x; + int visible_offset_y; + int num_visibility_rects; + struct rail_window_rect* visibility_rects; +}; + +struct rail_notify_state_order +{ + int version; + char* tool_tip; + struct rail_notify_icon_infotip infotip; + int state; + int icon_cache_entry; + int icon_cache_id; + struct rail_icon_info icon_info; +}; + +struct rail_monitored_desktop_order +{ + int active_window_id; + int num_window_ids; + int* window_ids; +}; + +#endif diff --git a/configure.ac b/configure.ac index 73a472ad..191f3624 100644 --- a/configure.ac +++ b/configure.ac @@ -7,6 +7,14 @@ AM_INIT_AUTOMAKE([1.6 foreign]) AC_PROG_CC AC_C_CONST AC_PROG_LIBTOOL +AC_ARG_WITH([systemdsystemunitdir], + AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]), + [], [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)]) +if test "x$with_systemdsystemunitdir" != xno; then + AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir]) +fi +AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ]) + AC_ARG_ENABLE(nopam, AS_HELP_STRING([--enable-nopam], [Build no PAM support (default: no)]), [nopam=true], [nopam=false]) @@ -31,6 +39,10 @@ AC_ARG_ENABLE(jpeg, AS_HELP_STRING([--enable-jpeg], [Build jpeg module (default: no)]), [jpeg=true], [jpeg=false]) AM_CONDITIONAL(XRDP_JPEG, [test x$jpeg = xtrue]) +AC_ARG_ENABLE(simplesound, AS_HELP_STRING([--enable-simplesound], + [Build simple pulse audio interface (default: no)]), + [simplesound=true], [simplesound=false]) +AM_CONDITIONAL(XRDP_SIMPLESOUND, [test x$simplesound = xtrue]) AM_CONDITIONAL(GOT_PREFIX, test "x${prefix}" != "xNONE"]) @@ -51,13 +63,20 @@ fi AS_IF( [test "x$enable_freerdp1" = "xyes"] , [PKG_CHECK_MODULES(FREERDP, freerdp >= 1.0.0)] ) -# checking for libjpeg +# checking for libjpeg if ! test -z "$enable_jpeg" then AC_CHECK_HEADER([jpeglib.h], [], [AC_MSG_ERROR([please install libjpeg-dev or libjpeg-devel])]) fi +# checking for libpulse libpulse-simple +if ! test -z "$enable_simplesound" +then + AC_CHECK_HEADER([pulse/simple.h], [], + [AC_MSG_ERROR([please install libpulse-dev or libpulse-devel])]) +fi + # checking for Xlib, Xfixes AC_CHECK_HEADER([X11/Xlib.h], [], [AC_MSG_ERROR([please install libx11-dev or libX11-devel])]) @@ -91,6 +110,7 @@ AC_CONFIG_FILES([Makefile instfiles/Makefile instfiles/pam.d/Makefile genkeymap/Makefile + xrdpapi/Makefile ]) # fontdump/Makefile # xrdp/cursors/Makefile diff --git a/freerdp/Makefile.am b/freerdp/Makefile.am index afb4f85c..21f78741 100644 --- a/freerdp/Makefile.am +++ b/freerdp/Makefile.am @@ -16,5 +16,5 @@ lib_LTLIBRARIES = \ libxrdpfreerdp_la_SOURCES = xrdp-freerdp.c xrdp-color.c libxrdpfreerdp_la_LIBADD = \ - $(top_srcdir)/common/libcommon.la \ + $(top_builddir)/common/libcommon.la \ $(FREERDP_LIBS) diff --git a/freerdp1/Makefile.am b/freerdp1/Makefile.am index cb5e02a9..494e5c04 100644 --- a/freerdp1/Makefile.am +++ b/freerdp1/Makefile.am @@ -16,5 +16,5 @@ lib_LTLIBRARIES = \ libxrdpfreerdp1_la_SOURCES = xrdp-freerdp.c xrdp-color.c libxrdpfreerdp1_la_LIBADD = \ - $(top_srcdir)/common/libcommon.la \ + $(top_builddir)/common/libcommon.la \ $(FREERDP_LIBS) diff --git a/freerdp1/xrdp-freerdp.c b/freerdp1/xrdp-freerdp.c index 8e7aa3db..524dcf2e 100644 --- a/freerdp1/xrdp-freerdp.c +++ b/freerdp1/xrdp-freerdp.c @@ -19,6 +19,7 @@ #include "xrdp-freerdp.h" #include "xrdp-color.h" +#include "xrdp_rail.h" #define LOG_LEVEL 1 #define LLOG(_level, _args) \ @@ -87,34 +88,41 @@ lxrdp_connect(struct mod* mod) switch (connectErrorCode) { case PREECONNECTERROR: - snprintf(buf, 128, "The error code from connect is PREECONNECTERROR"); + snprintf(buf, 128, "The error code from connect is " + "PREECONNECTERROR"); break; case UNDEFINEDCONNECTERROR: - snprintf(buf, 128, "The error code from connect is UNDEFINEDCONNECTERROR"); + snprintf(buf, 128, "The error code from connect is " + "UNDEFINEDCONNECTERROR"); break; case POSTCONNECTERROR: - snprintf(buf, 128, "The error code from connect is POSTCONNECTERROR"); + snprintf(buf, 128, "The error code from connect is " + "POSTCONNECTERROR"); break; case DNSERROR: snprintf(buf, 128, "The DNS system generated an error"); break; case DNSNAMENOTFOUND: - snprintf(buf, 128, "The DNS system could not find the specified name"); + snprintf(buf, 128, "The DNS system could not find the " + "specified name"); break; case CONNECTERROR: snprintf(buf, 128, "A general connect error was returned"); break; case MCSCONNECTINITIALERROR: - snprintf(buf, 128, "The error code from connect is MCSCONNECTINITIALERROR"); + snprintf(buf, 128, "The error code from connect is " + "MCSCONNECTINITIALERROR"); break; case TLSCONNECTERROR: snprintf(buf, 128, "Error in TLS handshake"); break; case AUTHENTICATIONERROR: - snprintf(buf, 128, "Authentication error check your password and username"); + snprintf(buf, 128, "Authentication error check your password " + "and username"); break; default: - snprintf(buf, 128, "Unhandled Errorcode from connect : %d", connectErrorCode); + snprintf(buf, 128, "Unhandled Errorcode from connect : %d", + connectErrorCode); break; } } @@ -213,6 +221,49 @@ lxrdp_event(struct mod* mod, int msg, long param1, long param2, mod->inst->input->MouseEvent(mod->inst->input, flags, 0, 0); case 110: break; + case 200: + LLOGLN(10, ("Invalidate request sent from client")); + RECTANGLE_16 *rectangle = (RECTANGLE_16 *) g_malloc(sizeof(RECTANGLE_16), 0); + /* The parameters are coded as follows param1 = MAKELONG(y, x), param2 =MAKELONG(h, w) + * #define MAKELONG(lo, hi) ((((hi) & 0xffff) << 16) | ((lo) & 0xffff)) + */ + rectangle->left = (param1 >> 16) & 0xffff; + rectangle->top = param1 & 0xffff; + rectangle->right = (((param2 >> 16) & 0xffff) + rectangle->left) - 1; + rectangle->bottom = ((param2 & 0xffff) + rectangle->top) - 1; + if (mod->inst->settings->refresh_rect) + { + if (mod->inst->update != NULL) + { + if (mod->inst->update->RefreshRect != NULL) + { + if (mod->inst->context != NULL) + { + LLOGLN(0, ("update rectangle left: %d top: %d bottom: %d right: %d", + rectangle->left, rectangle->top, rectangle->bottom, rectangle->right)); + mod->inst->update->RefreshRect(mod->inst->context, 1, rectangle); + } + else + { + LLOGLN(0, ("Invalidate request -The context is null")); + } + } + else + { + LLOGLN(0, ("Invalidate request - RefreshRect is Null")); + } + } + else + { + LLOGLN(0, ("Invalidate request -the update pointer is null")); + } + } + else + { + LLOGLN(0, ("Invalidate request - warning - update rectangle is disabled")); + } + g_free(rectangle); + break; case 0x5555: chanid = LOWORD(param1); flags = HIWORD(param1); @@ -229,13 +280,14 @@ lxrdp_event(struct mod* mod, int msg, long param1, long param2, switch (flags & 3) { case 3: - mod->inst->SendChannelData(mod->inst, lchid, data, total_size); + mod->inst->SendChannelData(mod->inst, lchid, (tui8*)data, total_size); break; case 2: /* end */ g_memcpy(mod->chan_buf + mod->chan_buf_valid, data, size); mod->chan_buf_valid += size; - mod->inst->SendChannelData(mod->inst, lchid, mod->chan_buf, total_size); + mod->inst->SendChannelData(mod->inst, lchid, (tui8*)(mod->chan_buf), + total_size); g_free(mod->chan_buf); mod->chan_buf = 0; mod->chan_buf_bytes = 0; @@ -339,6 +391,12 @@ lxrdp_set_param(struct mod* mod, char* name, char* value) { g_strncpy(mod->password, value, 255); } + else if (g_strcmp(name, "client_info") == 0) + { + g_memcpy(&(mod->client_info), value, sizeof(mod->client_info)); + /* This is a Struct and cannot be printed in next else*/ + LLOGLN(10, ("Client_info struct ignored")); + } else { LLOGLN(0, ("lxrdp_set_param: unknown name [%s] value [%s]", name, value)); @@ -454,10 +512,10 @@ lfreerdp_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmap) int j; int line_bytes; BITMAP_DATA* bd; - tui8* dst_data; - tui8* dst_data1; - tui8* src; - tui8* dst; + char* dst_data; + char* dst_data1; + char* src; + char* dst; mod = ((struct mod_context*)context)->modi; LLOGLN(10, ("lfreerdp_bitmap_update: %d %d", bitmap->number, bitmap->count)); @@ -472,15 +530,15 @@ lfreerdp_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmap) cx = (bd->destRight - bd->destLeft) + 1; cy = (bd->destBottom - bd->destTop) + 1; line_bytes = server_Bpp * bd->width; - dst_data = (tui8*)g_malloc(bd->height * line_bytes + 16, 0); + dst_data = (char*)g_malloc(bd->height * line_bytes + 16, 0); if (bd->compressed) { - bitmap_decompress(bd->bitmapDataStream, dst_data, bd->width, + bitmap_decompress(bd->bitmapDataStream, (tui8*)dst_data, bd->width, bd->height, bd->bitmapLength, server_bpp, server_bpp); } else { /* bitmap is upside down */ - src = bd->bitmapDataStream; + src = (char*)(bd->bitmapDataStream); dst = dst_data + bd->height * line_bytes; for (j = 0; j < bd->height; j++) { @@ -559,7 +617,8 @@ lfreerdp_pat_blt(rdpContext* context, PATBLT_ORDER* patblt) else { mod->server_set_brush(mod, patblt->brush.x, patblt->brush.y, - patblt->brush.style, patblt->brush.p8x8); + patblt->brush.style, + (char*)(patblt->brush.p8x8)); } mod->server_fill_rect(mod, patblt->nLeftRect, patblt->nTopRect, patblt->nWidth, patblt->nHeight); @@ -673,7 +732,7 @@ lfreerdp_glyph_index(rdpContext* context, GLYPH_INDEX_ORDER* glyph_index) glyph_index->opLeft, glyph_index->opTop, glyph_index->opRight, glyph_index->opBottom, glyph_index->x, glyph_index->y, - glyph_index->data, glyph_index->cbData); + (char*)(glyph_index->data), glyph_index->cbData); } /******************************************************************************/ @@ -711,6 +770,32 @@ lfreerdp_cache_bitmap(rdpContext* context, CACHE_BITMAP_ORDER* cache_bitmap_orde } /******************************************************************************/ +/* Turn the bitmap upside down*/ +static void DEFAULT_CC +lfreerdp_upsidedown(uint8* destination, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2_order, int server_Bpp) +{ + tui8* src; + tui8* dst; + int line_bytes; + int j; + + if (destination == NULL) + { + LLOGLN(0, ("lfreerdp_upsidedown: destination pointer is NULL !!!")); + return; + } + line_bytes = server_Bpp * cache_bitmap_v2_order->bitmapWidth; + src = cache_bitmap_v2_order->bitmapDataStream; + dst = destination + ((cache_bitmap_v2_order->bitmapHeight) * line_bytes); + for (j = 0; j < cache_bitmap_v2_order->bitmapHeight; j++) + { + dst -= line_bytes; + g_memcpy(dst, src, line_bytes); + src += line_bytes; + } +} + +/******************************************************************************/ static void DEFAULT_CC lfreerdp_cache_bitmapV2(rdpContext* context, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2_order) @@ -764,14 +849,15 @@ lfreerdp_cache_bitmapV2(rdpContext* context, if (cache_bitmap_v2_order->compressed) { bitmap_decompress(cache_bitmap_v2_order->bitmapDataStream, - dst_data, width, height, + (tui8*)dst_data, width, height, cache_bitmap_v2_order->bitmapLength, server_bpp, server_bpp); } else { - g_memcpy(dst_data, cache_bitmap_v2_order->bitmapDataStream, - width * height * server_Bpp); + /* Uncompressed bitmaps are upside down */ + lfreerdp_upsidedown((tui8*)dst_data, cache_bitmap_v2_order, server_Bpp); + LLOGLN(10, ("lfreerdp_cache_bitmapV2: upside down progressed")); } dst_data1 = convert_bitmap(server_bpp, client_bpp, dst_data, width, height, mod->colormap); @@ -801,7 +887,7 @@ lfreerdp_cache_glyph(rdpContext* context, CACHE_GLYPH_ORDER* cache_glyph_order) LLOGLN(10, (" %d %d %d %d %d", gd->cacheIndex, gd->x, gd->y, gd->cx, gd->cy)); mod->server_add_char(mod, cache_glyph_order->cacheId, gd->cacheIndex, - gd->x, gd->y, gd->cx, gd->cy, gd->aj); + gd->x, gd->y, gd->cx, gd->cy, (char*)(gd->aj)); xfree(gd->aj); gd->aj = 0; xfree(gd); @@ -880,7 +966,7 @@ static void DEFAULT_CC lfreerdp_pointer_system(rdpContext* context, POINTER_SYSTEM_UPDATE* pointer_system) { - LLOGLN(0, ("lfreerdp_pointer_system:")); + LLOGLN(0, ("lfreerdp_pointer_system: - no code here")); } /******************************************************************************/ @@ -1007,14 +1093,14 @@ lfreerdp_pointer_new(rdpContext* context, mod->pointer_cache[index].hotx = pointer_new->colorPtrAttr.xPos; mod->pointer_cache[index].hoty = pointer_new->colorPtrAttr.yPos; - dst = mod->pointer_cache[index].data; + dst = (tui8*)(mod->pointer_cache[index].data); dst += 32 * 32 * 3 - 32 * 3; src = pointer_new->colorPtrAttr.xorMaskData; lfreerdp_convert_color_image(dst, 32, 32, 24, 32 * -3, src, 32, 32, 1, 32 / 8); - dst = mod->pointer_cache[index].mask; - dst += 32 * 32 / 8 - 32 / 8; + dst = (tui8*)(mod->pointer_cache[index].mask); + dst +=( 32 * 32 / 8) - (32 / 8); src = pointer_new->colorPtrAttr.andMaskData; lfreerdp_convert_color_image(dst, 32, 32, 1, 32 / -8, src, 32, 32, 1, 32 / 8); @@ -1048,7 +1134,7 @@ lfreerdp_pointer_cached(rdpContext* context, struct mod* mod; int index; - LLOGLN(0, ("lfreerdp_pointer_cached:")); + LLOGLN(10, ("lfreerdp_pointer_cached:")); mod = ((struct mod_context*)context)->modi; index = pointer_cached->cacheIndex; mod->server_set_cursor(mod, mod->pointer_cache[index].hotx, @@ -1123,6 +1209,14 @@ lfreerdp_pre_connect(freerdp* instance) instance->settings->username = g_strdup(mod->username); instance->settings->password = g_strdup(mod->password); + if (mod->client_info.rail_support_level > 0) + { + instance->settings->remote_app = true; + instance->settings->rail_langbar_supported = true; + instance->settings->workarea = true; + instance->settings->performance_flags = PERF_DISABLE_WALLPAPER | PERF_DISABLE_FULLWINDOWDRAG; + } + // here //instance->settings->rdp_version = 4; @@ -1163,6 +1257,263 @@ lfreerdp_pre_connect(freerdp* instance) return true; } +/*****************************************************************************/ +void DEFAULT_CC +lrail_WindowCreate(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, + WINDOW_STATE_ORDER* window_state) +{ + int index; + struct mod* mod; + struct rail_window_state_order wso; + UNICONV* uniconv; + + LLOGLN(0, ("llrail_WindowCreate:")); + uniconv = freerdp_uniconv_new(); + mod = ((struct mod_context*)context)->modi; + memset(&wso, 0, sizeof(wso)); + /* copy the window state order */ + wso.owner_window_id = window_state->ownerWindowId; + wso.style = window_state->style; + wso.extended_style = window_state->extendedStyle; + wso.show_state = window_state->showState; + if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TITLE) + { + wso.title_info = freerdp_uniconv_in(uniconv, + window_state->titleInfo.string, window_state->titleInfo.length); + } + LLOGLN(0, ("lrail_WindowCreate: %s", wso.title_info)); + wso.client_offset_x = window_state->clientOffsetX; + wso.client_offset_y = window_state->clientOffsetY; + wso.client_area_width = window_state->clientAreaWidth; + wso.client_area_height = window_state->clientAreaHeight; + wso.rp_content = window_state->RPContent; + wso.root_parent_handle = window_state->rootParentHandle; + wso.window_offset_x = window_state->windowOffsetX; + wso.window_offset_y = window_state->windowOffsetY; + wso.window_client_delta_x = window_state->windowClientDeltaX; + wso.window_client_delta_y = window_state->windowClientDeltaY; + wso.window_width = window_state->windowWidth; + wso.window_height = window_state->windowHeight; + wso.num_window_rects = window_state->numWindowRects; + if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) + { + wso.window_rects = (struct rail_window_rect*) + g_malloc(sizeof(struct rail_window_rect) * wso.num_window_rects, 0); + for (index = 0; index < wso.num_window_rects; index++) + { + wso.window_rects[index].left = window_state->windowRects[index].left; + wso.window_rects[index].top = window_state->windowRects[index].top; + wso.window_rects[index].right = window_state->windowRects[index].right; + wso.window_rects[index].bottom = window_state->windowRects[index].bottom; + } + } + wso.visible_offset_x = window_state->visibleOffsetX; + wso.visible_offset_y = window_state->visibleOffsetY; + wso.num_visibility_rects = window_state->numVisibilityRects; + if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY) + { + wso.visibility_rects = (struct rail_window_rect*) + g_malloc(sizeof(struct rail_window_rect) * wso.num_visibility_rects, 0); + for (index = 0; index < wso.num_visibility_rects; index++) + { + wso.visibility_rects[index].left = window_state->visibilityRects[index].left; + wso.visibility_rects[index].top = window_state->visibilityRects[index].top; + wso.visibility_rects[index].right = window_state->visibilityRects[index].right; + wso.visibility_rects[index].bottom = window_state->visibilityRects[index].bottom; + } + } + + mod->server_window_new_update(mod, orderInfo->windowId, &wso, + orderInfo->fieldFlags); + + xfree(wso.title_info); + g_free(wso.window_rects); + g_free(wso.visibility_rects); + freerdp_uniconv_free(uniconv); +} + +/*****************************************************************************/ +void DEFAULT_CC +lrail_WindowUpdate(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, + WINDOW_STATE_ORDER* window_state) +{ + LLOGLN(0, ("lrail_WindowUpdate:")); + lrail_WindowCreate(context, orderInfo, window_state); +} + +/*****************************************************************************/ +void DEFAULT_CC +lrail_WindowDelete(rdpContext* context, WINDOW_ORDER_INFO* orderInfo) +{ + struct mod* mod; + + LLOGLN(0, ("lrail_WindowDelete:")); + mod = ((struct mod_context*)context)->modi; + mod->server_window_delete(mod, orderInfo->windowId); +} + +/*****************************************************************************/ +void DEFAULT_CC +lrail_WindowIcon(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, + WINDOW_ICON_ORDER* window_icon) +{ + struct mod* mod; + struct rail_icon_info rii; + + LLOGLN(0, ("lrail_WindowIcon:")); + mod = ((struct mod_context*)context)->modi; + memset(&rii, 0, sizeof(rii)); + rii.bpp = window_icon->iconInfo->bpp; + rii.width = window_icon->iconInfo->width; + rii.height = window_icon->iconInfo->height; + rii.cmap_bytes = window_icon->iconInfo->cbColorTable; + rii.mask_bytes = window_icon->iconInfo->cbBitsMask; + rii.data_bytes = window_icon->iconInfo->cbBitsColor; + rii.mask = (char*)(window_icon->iconInfo->bitsMask); + rii.cmap = (char*)(window_icon->iconInfo->colorTable); + rii.data = (char*)(window_icon->iconInfo->bitsColor); + mod->server_window_icon(mod, orderInfo->windowId, + window_icon->iconInfo->cacheEntry, + window_icon->iconInfo->cacheId, &rii, + orderInfo->fieldFlags); +} + +/*****************************************************************************/ +void DEFAULT_CC +lrail_WindowCachedIcon(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, + WINDOW_CACHED_ICON_ORDER* window_cached_icon) +{ + struct mod* mod; + + LLOGLN(0, ("lrail_WindowCachedIcon:")); + mod = ((struct mod_context*)context)->modi; + mod->server_window_cached_icon(mod, orderInfo->windowId, + window_cached_icon->cachedIcon.cacheEntry, + window_cached_icon->cachedIcon.cacheId, + orderInfo->fieldFlags); +} + +/*****************************************************************************/ +void DEFAULT_CC +lrail_NotifyIconCreate(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, + NOTIFY_ICON_STATE_ORDER* notify_icon_state) +{ + struct mod* mod; + struct rail_notify_state_order rnso; + UNICONV* uniconv; + + + LLOGLN(0, ("lrail_NotifyIconCreate:")); + uniconv = freerdp_uniconv_new(); + + mod = ((struct mod_context*)context)->modi; + + memset(&rnso, 0, sizeof(rnso)); + rnso.version = notify_icon_state->version; + if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_TIP) + { + rnso.tool_tip = freerdp_uniconv_in(uniconv, + notify_icon_state->toolTip.string, notify_icon_state->toolTip.length); + } + if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP) + { + rnso.infotip.timeout = notify_icon_state->infoTip.timeout; + rnso.infotip.flags = notify_icon_state->infoTip.flags; + rnso.infotip.text = freerdp_uniconv_in(uniconv, + notify_icon_state->infoTip.text.string, + notify_icon_state->infoTip.text.length); + rnso.infotip.title = freerdp_uniconv_in(uniconv, + notify_icon_state->infoTip.title.string, + notify_icon_state->infoTip.title.length); + } + rnso.state = notify_icon_state->state; + rnso.icon_cache_entry = notify_icon_state->icon.cacheEntry; + rnso.icon_cache_id = notify_icon_state->icon.cacheId; + + rnso.icon_info.bpp = notify_icon_state->icon.bpp; + rnso.icon_info.width = notify_icon_state->icon.width; + rnso.icon_info.height = notify_icon_state->icon.height; + rnso.icon_info.cmap_bytes = notify_icon_state->icon.cbColorTable; + rnso.icon_info.mask_bytes = notify_icon_state->icon.cbBitsMask; + rnso.icon_info.data_bytes = notify_icon_state->icon.cbBitsColor; + rnso.icon_info.mask = (char*)(notify_icon_state->icon.bitsMask); + rnso.icon_info.cmap = (char*)(notify_icon_state->icon.colorTable); + rnso.icon_info.data = (char*)(notify_icon_state->icon.bitsColor); + + mod->server_notify_new_update(mod, orderInfo->windowId, + orderInfo->notifyIconId, + &rnso, orderInfo->fieldFlags); + + xfree(rnso.tool_tip); + xfree(rnso.infotip.text); + xfree(rnso.infotip.title); + freerdp_uniconv_free(uniconv); + +} + +/*****************************************************************************/ +void DEFAULT_CC +lrail_NotifyIconUpdate(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, + NOTIFY_ICON_STATE_ORDER* notify_icon_state) +{ + LLOGLN(0, ("lrail_NotifyIconUpdate:")); + lrail_NotifyIconCreate(context, orderInfo, notify_icon_state); +} + +/*****************************************************************************/ +void DEFAULT_CC +lrail_NotifyIconDelete(rdpContext* context, WINDOW_ORDER_INFO* orderInfo) +{ + struct mod* mod; + + LLOGLN(0, ("lrail_NotifyIconDelete:")); + mod = ((struct mod_context*)context)->modi; + mod->server_notify_delete(mod, orderInfo->windowId, + orderInfo->notifyIconId); +} + +/*****************************************************************************/ +void DEFAULT_CC +lrail_MonitoredDesktop(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, + MONITORED_DESKTOP_ORDER* monitored_desktop) +{ + int index; + struct mod* mod; + struct rail_monitored_desktop_order rmdo; + + LLOGLN(0, ("lrail_MonitoredDesktop:")); + mod = ((struct mod_context*)context)->modi; + memset(&rmdo, 0, sizeof(rmdo)); + rmdo.active_window_id = monitored_desktop->activeWindowId; + rmdo.num_window_ids = monitored_desktop->numWindowIds; + if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER) + { + if (rmdo.num_window_ids > 0) + { + rmdo.window_ids = (int*)g_malloc(sizeof(int) * rmdo.num_window_ids, 0); + for (index = 0; index < rmdo.num_window_ids; index++) + { + rmdo.window_ids[index] = monitored_desktop->windowIds[index]; + } + } + } + mod->server_monitored_desktop(mod, &rmdo, orderInfo->fieldFlags); + g_free(rmdo.window_ids); +} + +/*****************************************************************************/ +void DEFAULT_CC +lrail_NonMonitoredDesktop(rdpContext* context, WINDOW_ORDER_INFO* orderInfo) +{ + struct mod* mod; + struct rail_monitored_desktop_order rmdo; + + LLOGLN(0, ("lrail_NonMonitoredDesktop:")); + mod = ((struct mod_context*)context)->modi; + memset(&rmdo, 0, sizeof(rmdo)); + mod->server_monitored_desktop(mod, &rmdo, orderInfo->fieldFlags); +} + /******************************************************************************/ static boolean DEFAULT_CC lfreerdp_post_connect(freerdp* instance) @@ -1172,6 +1523,18 @@ lfreerdp_post_connect(freerdp* instance) LLOGLN(0, ("lfreerdp_post_connect:")); mod = ((struct mod_context*)(instance->context))->modi; g_memset(mod->password, 0, sizeof(mod->password)); + + mod->inst->update->window->WindowCreate = lrail_WindowCreate; + mod->inst->update->window->WindowUpdate = lrail_WindowUpdate; + mod->inst->update->window->WindowDelete = lrail_WindowDelete; + mod->inst->update->window->WindowIcon = lrail_WindowIcon; + mod->inst->update->window->WindowCachedIcon = lrail_WindowCachedIcon; + mod->inst->update->window->NotifyIconCreate = lrail_NotifyIconCreate; + mod->inst->update->window->NotifyIconUpdate = lrail_NotifyIconUpdate; + mod->inst->update->window->NotifyIconDelete = lrail_NotifyIconDelete; + mod->inst->update->window->MonitoredDesktop = lrail_MonitoredDesktop; + mod->inst->update->window->NonMonitoredDesktop = lrail_NonMonitoredDesktop; + return true; } @@ -1212,7 +1575,7 @@ lfreerdp_receive_channel_data(freerdp* instance, int channelId, uint8* data, if (lchid >= 0) { LLOGLN(10, ("lfreerdp_receive_channel_data: server to client")); - error = mod->server_send_to_channel(mod, lchid, data, size, + error = mod->server_send_to_channel(mod, lchid, (char*)data, size, total_size, flags); if (error != 0) { @@ -1297,7 +1660,13 @@ mod_exit(struct mod* mod) { return 0; } - + if (mod->inst == NULL) + { + LLOGLN(0, ("mod_exit - null pointer for inst:")); + g_free(mod); + return 0 ; + } + freerdp_disconnect(mod->inst); if ((mod->vmaj == 1) && (mod->vmin == 0) && (mod->vrev == 1)) { /* this version has a bug with double free in freerdp_free */ diff --git a/freerdp1/xrdp-freerdp.h b/freerdp1/xrdp-freerdp.h index 1ecbb5ee..9ea0bcb0 100644 --- a/freerdp1/xrdp-freerdp.h +++ b/freerdp1/xrdp-freerdp.h @@ -22,9 +22,15 @@ #include "parse.h" #include "os_calls.h" #include "defines.h" +#include "xrdp_rail.h" +#include "xrdp_client_info.h" /* this is the freerdp main header */ #include <freerdp/freerdp.h> +#include <freerdp/rail.h> +#include <freerdp/rail/rail.h> +#include <freerdp/codec/bitmap.h> +#include <freerdp/utils/memory.h> //#include "/home/jay/git/jsorg71/staging/include/freerdp/freerdp.h" struct bitmap_item @@ -112,7 +118,38 @@ struct mod char* data, int data_len, int total_data_len, int flags); int (*server_bell_trigger)(struct mod* v); - long server_dumby[100 - 25]; /* align, 100 minus the number of server + /* off screen bitmaps */ + int (*server_create_os_surface)(struct mod* v, int rdpindex, + int width, int height); + int (*server_switch_os_surface)(struct mod* v, int rdpindex); + int (*server_delete_os_surface)(struct mod* v, int rdpindex); + int (*server_paint_rect_os)(struct mod* mod, int x, int y, + int cx, int cy, + int rdpindex, int srcx, int srcy); + int (*server_set_hints)(struct mod* mod, int hints, int mask); + /* rail */ + int (*server_window_new_update)(struct mod* mod, int window_id, + struct rail_window_state_order* window_state, + int flags); + int (*server_window_delete)(struct mod* mod, int window_id); + int (*server_window_icon)(struct mod* mod, + int window_id, int cache_entry, int cache_id, + struct rail_icon_info* icon_info, + int flags); + int (*server_window_cached_icon)(struct mod* mod, + int window_id, int cache_entry, + int cache_id, int flags); + int (*server_notify_new_update)(struct mod* mod, + int window_id, int notify_id, + struct rail_notify_state_order* notify_state, + int flags); + int (*server_notify_delete)(struct mod* mod, int window_id, + int notify_id); + int (*server_monitored_desktop)(struct mod* mod, + struct rail_monitored_desktop_order* mdo, + int flags); + + long server_dumby[100 - 37]; /* align, 100 minus the number of server functions above */ /* common */ tbus handle; /* pointer to self as long */ @@ -133,6 +170,8 @@ struct mod char username[256]; char password[256]; + struct xrdp_client_info client_info; + struct rdp_freerdp* inst; struct bitmap_item bitmap_cache[4][4096]; struct brush_item brush_cache[64]; diff --git a/instfiles/Makefile.am b/instfiles/Makefile.am index d6d86140..4cabd942 100644 --- a/instfiles/Makefile.am +++ b/instfiles/Makefile.am @@ -1,8 +1,16 @@ -EXTRA_DIST = xrdp.sh km-0407.ini km-0409.ini km-040c.ini km-0410.ini km-0419.ini km-041d.ini +EXTRA_DIST = xrdp.sh km-0407.ini km-0409.ini km-040c.ini km-0410.ini km-0419.ini km-041d.ini \ +xrdp-sesman.service \ +xrdp.service SUBDIRS = \ pam.d +if HAVE_SYSTEMD +systemdsystemunit_DATA = \ + xrdp-sesman.service \ + xrdp.service +endif + startscriptdir=$(sysconfdir)/xrdp startscript_DATA = \ diff --git a/instfiles/xrdp-sesman.service b/instfiles/xrdp-sesman.service new file mode 100644 index 00000000..d40150cd --- /dev/null +++ b/instfiles/xrdp-sesman.service @@ -0,0 +1,14 @@ +[Unit] +Description=xrdp session manager +After=syslog.target network.target +StopWhenUnneeded=true + +[Service] +Type=forking +PIDFile=/var/run/xrdp-sesman.pid +EnvironmentFile=/etc/sysconfig/xrdp +ExecStart=/usr/sbin/xrdp-sesman $SESMAN_OPTIONS +ExecStop=/usr/sbin/xrdp-sesman $SESMAN_OPTIONS --kill + +[Install] +WantedBy=multi-user.target diff --git a/instfiles/xrdp.service b/instfiles/xrdp.service new file mode 100644 index 00000000..7bb076d1 --- /dev/null +++ b/instfiles/xrdp.service @@ -0,0 +1,14 @@ +[Unit] +Description=xrdp daemon +Requires=xrdp-sesman.service +After=syslog.target network.target xrdp-sesman.service + +[Service] +Type=forking +PIDFile=/var/run/xrdp.pid +EnvironmentFile=/etc/sysconfig/xrdp +ExecStart=/usr/sbin/xrdp $XRDP_OPTIONS +ExecStop=/usr/sbin/xrdp $XRDP_OPTIONS --kill + +[Install] +WantedBy=multi-user.target diff --git a/keygen/Makefile.am b/keygen/Makefile.am index 53147317..c28c063d 100644 --- a/keygen/Makefile.am +++ b/keygen/Makefile.am @@ -14,4 +14,4 @@ bin_PROGRAMS = \ xrdp_keygen_SOURCES = keygen.c xrdp_keygen_LDADD = \ - $(top_srcdir)/common/libcommon.la + $(top_builddir)/common/libcommon.la diff --git a/libxrdp/Makefile.am b/libxrdp/Makefile.am index 08fb7130..11d1d836 100644 --- a/libxrdp/Makefile.am +++ b/libxrdp/Makefile.am @@ -50,11 +50,12 @@ libxrdp_la_SOURCES = \ xrdp_sec.c \ xrdp_tcp.c \ xrdp_bitmap_compress.c \ - xrdp_jpeg_compress.c + xrdp_jpeg_compress.c \ + xrdp_orders_rail.c libxrdp_la_LDFLAGS = \ $(EXTRA_FLAGS) libxrdp_la_LIBADD = \ - $(top_srcdir)/common/libcommon.la \ + $(top_builddir)/common/libcommon.la \ $(EXTRA_LIBS) diff --git a/libxrdp/libxrdp.c b/libxrdp/libxrdp.c index 05e67eb7..3f8307c2 100644 --- a/libxrdp/libxrdp.c +++ b/libxrdp/libxrdp.c @@ -75,10 +75,12 @@ libxrdp_process_data(struct xrdp_session* session) int rv; int code; int term; + int dead_lock_counter; term = 0; cont = 1; rv = 0; + dead_lock_counter = 0; while ((cont || !session->up_and_running) && !term) { if (session->is_term != 0) @@ -89,7 +91,8 @@ 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((struct xrdp_rdp*)(session->rdp), + session->s, &code) != 0) { rv = 1; break; @@ -102,6 +105,7 @@ libxrdp_process_data(struct xrdp_session* session) session->up_and_running = 0; break; case 0: + dead_lock_counter++; break; case RDP_PDU_CONFIRM_ACTIVE: /* 3 */ xrdp_rdp_process_confirm_active((struct xrdp_rdp*)session->rdp, @@ -118,8 +122,17 @@ libxrdp_process_data(struct xrdp_session* session) break; default: g_writeln("unknown in libxrdp_process_data"); + dead_lock_counter++; break; } + if (dead_lock_counter > 100000) + { + /*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; + } if (cont) { cont = (session->s->next_packet != 0) && @@ -616,7 +629,10 @@ libxrdp_reset(struct xrdp_session* session, } /* process till up and running */ session->up_and_running = 0; - libxrdp_process_data(session); + if (libxrdp_process_data(session) != 0) + { + g_writeln("non handled error from libxrdp_process_data"); + } return 0; } @@ -635,11 +651,22 @@ libxrdp_orders_send_raw_bitmap2(struct xrdp_session* session, int EXPORT_CC libxrdp_orders_send_bitmap2(struct xrdp_session* session, int width, int height, int bpp, char* data, - int cache_id, int cache_idx) + int cache_id, int cache_idx, int hints) { return xrdp_orders_send_bitmap2((struct xrdp_orders*)session->orders, width, height, bpp, data, - cache_id, cache_idx); + cache_id, cache_idx, hints); +} + +/*****************************************************************************/ +int EXPORT_CC +libxrdp_orders_send_bitmap3(struct xrdp_session* session, + int width, int height, int bpp, char* data, + int cache_id, int cache_idx, int hints) +{ + return xrdp_orders_send_bitmap3((struct xrdp_orders*)session->orders, + width, height, bpp, data, + cache_id, cache_idx, hints); } /*****************************************************************************/ @@ -658,6 +685,11 @@ libxrdp_query_channel(struct xrdp_session* session, int index, rdp = (struct xrdp_rdp*)session->rdp; mcs = rdp->sec_layer->mcs_layer; + if (mcs->channel_list == NULL) + { + g_writeln("libxrdp_query_channel - No channel initialized"); + return 1 ; + } count = mcs->channel_list->count; if (index < 0 || index >= count) { @@ -668,6 +700,7 @@ libxrdp_query_channel(struct xrdp_session* session, int index, if (channel_item == 0) { /* this should not happen */ + g_writeln("libxrdp_query_channel - channel item is 0"); return 1; } if (channel_name != 0) @@ -695,6 +728,11 @@ libxrdp_get_channel_id(struct xrdp_session* session, char* name) rdp = (struct xrdp_rdp*)session->rdp; mcs = rdp->sec_layer->mcs_layer; + if (mcs->channel_list == NULL) + { + g_writeln("libxrdp_get_channel_id No channel initialized"); + return -1 ; + } count = mcs->channel_list->count; for (index = 0; index < count; index++) { @@ -737,6 +775,7 @@ libxrdp_send_to_channel(struct xrdp_session* session, int channel_id, s_mark_end(s); if (xrdp_channel_send(chan, s, channel_id, total_data_len, flags) != 0) { + g_writeln("Debug - data NOT sent to channel"); free_stream(s); return 1; } @@ -754,3 +793,108 @@ libxrdp_orders_send_brush(struct xrdp_session* session, width, height, bpp, type, size, data, cache_id); } + +/*****************************************************************************/ +int EXPORT_CC +libxrdp_orders_send_create_os_surface(struct xrdp_session* session, int id, + int width, int height, + struct list* del_list) +{ + return xrdp_orders_send_create_os_surface + ((struct xrdp_orders*)(session->orders), id, + width, height, del_list); +} + +/*****************************************************************************/ +int EXPORT_CC +libxrdp_orders_send_switch_os_surface(struct xrdp_session* session, int id) +{ + return xrdp_orders_send_switch_os_surface + ((struct xrdp_orders*)(session->orders), id); +} + +/*****************************************************************************/ +int EXPORT_CC +libxrdp_window_new_update(struct xrdp_session* session, int window_id, + struct rail_window_state_order* window_state, + int flags) +{ + struct xrdp_orders* orders; + + orders = (struct xrdp_orders*)(session->orders); + return xrdp_orders_send_window_new_update(orders, window_id, + window_state, flags); +} + +/*****************************************************************************/ +int EXPORT_CC +libxrdp_window_delete(struct xrdp_session* session, int window_id) +{ + struct xrdp_orders* orders; + + orders = (struct xrdp_orders*)(session->orders); + return xrdp_orders_send_window_delete(orders, window_id); +} + +/*****************************************************************************/ +int EXPORT_CC +libxrdp_window_icon(struct xrdp_session* session, int window_id, + int cache_entry, int cache_id, + struct rail_icon_info* icon_info, int flags) +{ + struct xrdp_orders* orders; + + orders = (struct xrdp_orders*)(session->orders); + return xrdp_orders_send_window_icon(orders, window_id, cache_entry, + cache_id, icon_info, flags); +} + +/*****************************************************************************/ +int EXPORT_CC +libxrdp_window_cached_icon(struct xrdp_session* session, int window_id, + int cache_entry, int cache_id, + int flags) +{ + struct xrdp_orders* orders; + + orders = (struct xrdp_orders*)(session->orders); + return xrdp_orders_send_window_cached_icon(orders, window_id, cache_entry, + cache_id, flags); +} + +/*****************************************************************************/ +int EXPORT_CC +libxrdp_notify_new_update(struct xrdp_session* session, + int window_id, int notify_id, + struct rail_notify_state_order* notify_state, + int flags) +{ + struct xrdp_orders* orders; + + orders = (struct xrdp_orders*)(session->orders); + return xrdp_orders_send_notify_new_update(orders, window_id, notify_id, + notify_state, flags); +} + +/*****************************************************************************/ +int DEFAULT_CC +libxrdp_notify_delete(struct xrdp_session* session, + int window_id, int notify_id) +{ + struct xrdp_orders* orders; + + orders = (struct xrdp_orders*)(session->orders); + return xrdp_orders_send_notify_delete(orders, window_id, notify_id); +} + +/*****************************************************************************/ +int DEFAULT_CC +libxrdp_monitored_desktop(struct xrdp_session* session, + struct rail_monitored_desktop_order* mdo, + int flags) +{ + struct xrdp_orders* orders; + + orders = (struct xrdp_orders*)(session->orders); + return xrdp_orders_send_monitored_desktop(orders, mdo, flags); +} diff --git a/libxrdp/libxrdp.h b/libxrdp/libxrdp.h index 35a38190..b066db95 100644 --- a/libxrdp/libxrdp.h +++ b/libxrdp/libxrdp.h @@ -119,6 +119,7 @@ struct xrdp_rdp int mcs_channel; struct xrdp_client_info client_info; void* mppc_enc; + void* rfx_enc; }; /* state */ @@ -325,6 +326,8 @@ xrdp_orders_send(struct xrdp_orders* self); int APP_CC xrdp_orders_force_send(struct xrdp_orders* self); int APP_CC +xrdp_orders_check(struct xrdp_orders* self, int max_size); +int APP_CC xrdp_orders_rect(struct xrdp_orders* self, int x, int y, int cx, int cy, int color, struct xrdp_rect* rect); int APP_CC @@ -383,13 +386,18 @@ xrdp_orders_send_raw_bitmap2(struct xrdp_orders* self, int APP_CC xrdp_orders_send_bitmap2(struct xrdp_orders* self, int width, int height, int bpp, char* data, - int cache_id, int cache_idx); + int cache_id, int cache_idx, int hints); +int APP_CC +xrdp_orders_send_bitmap3(struct xrdp_orders* self, + int width, int height, int bpp, char* data, + int cache_id, int cache_idx, int hints); int APP_CC xrdp_orders_send_brush(struct xrdp_orders* self, int width, int height, int bpp, int type, int size, char* data, int cache_id); int APP_CC xrdp_orders_send_create_os_surface(struct xrdp_orders* self, int id, - int width, int height); + int width, int height, + struct list* del_list); int APP_CC xrdp_orders_send_switch_os_surface(struct xrdp_orders* self, int id); @@ -403,7 +411,7 @@ int APP_CC xrdp_jpeg_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 e, int quality); /* xrdp_channel.c */ struct xrdp_channel* APP_CC diff --git a/libxrdp/libxrdpinc.h b/libxrdp/libxrdpinc.h index 82ac9ad0..4f3504e6 100644 --- a/libxrdp/libxrdpinc.h +++ b/libxrdp/libxrdpinc.h @@ -23,6 +23,8 @@ #ifndef LIBXRDPINC_H #define LIBXRDPINC_H +#include "xrdp_rail.h" + /* struct xrdp_client_info moved to xrdp_client_info.h */ struct xrdp_brush @@ -162,7 +164,11 @@ libxrdp_orders_send_raw_bitmap2(struct xrdp_session* session, int DEFAULT_CC libxrdp_orders_send_bitmap2(struct xrdp_session* session, int width, int height, int bpp, char* data, - int cache_id, int cache_idx); + int cache_id, int cache_idx, int hints); +int DEFAULT_CC +libxrdp_orders_send_bitmap3(struct xrdp_session* session, + int width, int height, int bpp, char* data, + int cache_id, int cache_idx, int hints); int DEFAULT_CC libxrdp_query_channel(struct xrdp_session* session, int index, char* channel_name, int* channel_flags); @@ -176,5 +182,37 @@ int DEFAULT_CC libxrdp_orders_send_brush(struct xrdp_session* session, int width, int height, int bpp, int type, int size, char* data, int cache_id); +int DEFAULT_CC +libxrdp_orders_send_create_os_surface(struct xrdp_session* session, int id, + int width, int height, + struct list* del_list); +int DEFAULT_CC +libxrdp_orders_send_switch_os_surface(struct xrdp_session* session, int id); +int DEFAULT_CC +libxrdp_window_new_update(struct xrdp_session* session, int window_id, + struct rail_window_state_order* window_state, + int flags); +int DEFAULT_CC +libxrdp_window_delete(struct xrdp_session* session, int window_id); +int DEFAULT_CC +libxrdp_window_icon(struct xrdp_session* session, int window_id, + int cache_entry, int cache_id, + struct rail_icon_info* icon_info, int flags); +int DEFAULT_CC +libxrdp_window_cached_icon(struct xrdp_session* session, int window_id, + int cache_entry, int cache_id, + int flags); +int DEFAULT_CC +libxrdp_notify_new_update(struct xrdp_session* session, + int window_id, int notify_id, + struct rail_notify_state_order* notify_state, + int flags); +int DEFAULT_CC +libxrdp_notify_delete(struct xrdp_session* session, + int window_id, int notify_id); +int DEFAULT_CC +libxrdp_monitored_desktop(struct xrdp_session* session, + struct rail_monitored_desktop_order* mdo, + int flags); #endif diff --git a/libxrdp/xrdp_channel.c b/libxrdp/xrdp_channel.c index 00497c35..2b3d23a5 100644 --- a/libxrdp/xrdp_channel.c +++ b/libxrdp/xrdp_channel.c @@ -35,7 +35,11 @@ static struct mcs_channel_item* APP_CC xrdp_channel_get_item(struct xrdp_channel* self, int channel_id) { struct mcs_channel_item* channel; - + if(self->mcs_layer->channel_list==NULL) + { + g_writeln("xrdp_channel_get_item - No channel initialized"); + return NULL ; + } channel = (struct mcs_channel_item*) list_get_item(self->mcs_layer->channel_list, channel_id); return channel; @@ -62,6 +66,7 @@ xrdp_channel_delete(struct xrdp_channel* self) { return; } + g_memset(self,0,sizeof(struct xrdp_channel)); g_free(self); } @@ -88,19 +93,21 @@ xrdp_channel_send(struct xrdp_channel* self, struct stream* s, int channel_id, struct mcs_channel_item* channel; channel = xrdp_channel_get_item(self, channel_id); - if (channel == 0) + if (channel == NULL) { + g_writeln("xrdp_channel_send - no such channel"); return 1; } s_pop_layer(s, channel_hdr); out_uint32_le(s, total_data_len); - if (channel->flags & CHANNEL_OPTION_SHOW_PROTOCOL) + if (channel->flags & XR_CHANNEL_OPTION_SHOW_PROTOCOL) { flags |= CHANNEL_FLAG_SHOW_PROTOCOL; } out_uint32_le(s, flags); if (xrdp_sec_send(self->sec_layer, s, channel->chanid) != 0) { + g_writeln("xrdp_channel_send - failure sending data"); return 1; } return 0; @@ -159,13 +166,14 @@ xrdp_channel_process(struct xrdp_channel* self, struct stream* s, int channel_id; struct mcs_channel_item* channel; + /* this assumes that the channels are in order of chanid(mcs channel id) but they should be, see xrdp_sec_process_mcs_data_channels the first channel should be MCS_GLOBAL_CHANNEL + 1, second one should be MCS_GLOBAL_CHANNEL + 2, and so on */ channel_id = (chanid - MCS_GLOBAL_CHANNEL) - 1; channel = xrdp_channel_get_item(self, channel_id); - if (channel == 0) + if (channel == NULL) { g_writeln("xrdp_channel_process, channel not found"); return 1; diff --git a/libxrdp/xrdp_fastpath.c b/libxrdp/xrdp_fastpath.c index 5ce07861..9a147b1b 100644 --- a/libxrdp/xrdp_fastpath.c +++ b/libxrdp/xrdp_fastpath.c @@ -76,7 +76,7 @@ xrdp_fastpath_send_update_pdu(struct xrdp_fastpath* self, tui8 updateCode, compression = 0; s_send = self->out_s; - maxLen = FASTPATH_MAX_PACKET_SIZE - 6 ; /* 6 bytes for header */ + maxLen = FASTPATH_MAX_PACKET_SIZE - 6; /* 6 bytes for header */ payloadLeft = (s->end - s->data); for (i = 0; payloadLeft > 0; i++) { @@ -143,7 +143,7 @@ xrdp_fastpath_process_update(struct xrdp_fastpath* self, tui8 updateCode, } return 0; -} +} /*****************************************************************************/ int APP_CC @@ -192,5 +192,5 @@ xrdp_fastpath_process_data(struct xrdp_fastpath* self, struct stream* s, return 1; } in_uint16_le(s, size); - return xrdp_fastpath_process_update(self, updateCode, size, s); + return xrdp_fastpath_process_update(self, updateCode, size, s); } diff --git a/libxrdp/xrdp_jpeg_compress.c b/libxrdp/xrdp_jpeg_compress.c index 48f12359..8561982f 100644 --- a/libxrdp/xrdp_jpeg_compress.c +++ b/libxrdp/xrdp_jpeg_compress.c @@ -148,9 +148,8 @@ jp_do_compress(char* data, int width, int height, int bpp, int quality, /*****************************************************************************/ static int APP_CC jpeg_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) + struct stream* s, struct stream* temp_s, int bpp, + int byte_limit, int e, int quality) { char* data; tui32* src32; @@ -164,7 +163,7 @@ jpeg_compress(char* in_data, int width, int height, int i; int cdata_bytes; - data = g_malloc((width + e) * height * 3, 0); + data = temp_s->data; dst8 = data; if (bpp == 24) { @@ -192,9 +191,8 @@ jpeg_compress(char* in_data, int width, int height, g_writeln("bpp wrong %d", bpp); } cdata_bytes = byte_limit; - jp_do_compress(data, width + e, height, 24, JP_QUALITY, s->p, &cdata_bytes); + jp_do_compress(data, width + e, height, 24, quality, s->p, &cdata_bytes); s->p += cdata_bytes; - g_free(data); return cdata_bytes; } @@ -203,10 +201,10 @@ int APP_CC xrdp_jpeg_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 e, int quality) { - jpeg_compress(in_data, width, height, s, bpp, byte_limit, - start_line, temp_s, e); + jpeg_compress(in_data, width, height, s, temp_s, bpp, byte_limit, + e, quality); return height; } @@ -217,7 +215,7 @@ int APP_CC xrdp_jpeg_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 e, int quality) { return height; } diff --git a/libxrdp/xrdp_mcs.c b/libxrdp/xrdp_mcs.c index af65faf2..618a3433 100644 --- a/libxrdp/xrdp_mcs.c +++ b/libxrdp/xrdp_mcs.c @@ -65,11 +65,15 @@ xrdp_mcs_delete(struct xrdp_mcs* self) } list_delete(self->channel_list); xrdp_iso_delete(self->iso_layer); + /* make sure we get null pointer exception if struct is used again. */ + DEBUG(("xrdp_mcs_delete processed")) + g_memset(self,0,sizeof(struct xrdp_mcs)) ; g_free(self); } /*****************************************************************************/ -/* returns error */ +/* 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) { @@ -87,7 +91,7 @@ xrdp_mcs_send_cjcf(struct xrdp_mcs* self, int userid, int chanid) out_uint8(s, (MCS_CJCF << 2) | 2); out_uint8(s, 0); out_uint16_be(s, userid); - out_uint16_be(s, chanid); + out_uint16_be(s, chanid); /* TODO Explain why we send this two times */ out_uint16_be(s, chanid); s_mark_end(s); if (xrdp_iso_send(self->iso_layer, s) != 0) @@ -122,20 +126,33 @@ xrdp_mcs_recv(struct xrdp_mcs* self, struct stream* s, int* chan) } in_uint8(s, opcode); appid = opcode >> 2; - if (appid == MCS_DPUM) + if (appid == MCS_DPUM) /* Disconnect Provider Ultimatum */ { + g_writeln("received Disconnect Provider Ultimatum"); DEBUG((" out xrdp_mcs_recv appid != MCS_DPUM")); return 1; } /* this is channels getting added from the client */ if (appid == MCS_CJRQ) { + g_writeln("channel join request received"); in_uint16_be(s, userid); in_uint16_be(s, chanid); - DEBUG((" adding channel %4.4x", chanid)); - xrdp_mcs_send_cjcf(self, userid, chanid); + DEBUG(("xrdp_mcs_recv adding channel %4.4x", chanid)); + if(xrdp_mcs_send_cjcf(self, userid, chanid)!=0) + { + g_writeln("Non handled error from xrdp_mcs_send_cjcf") ; + } continue; } + if(appid==MCS_SDRQ || appid==MCS_SDIN) + { + break ; + } + else + { + g_writeln("Recieved an unhandled appid:%d",appid); + } break; } if (appid != MCS_SDRQ) diff --git a/libxrdp/xrdp_orders.c b/libxrdp/xrdp_orders.c index 925c52aa..e7739e3e 100644 --- a/libxrdp/xrdp_orders.c +++ b/libxrdp/xrdp_orders.c @@ -22,6 +22,20 @@ #include "libxrdp.h" +#if defined(XRDP_FREERDP1) +#include <freerdp/codec/rfx.h> +#endif + +#define LLOG_LEVEL 2 +#define LLOGLN(_log_level, _params) \ +{ \ + if (_log_level < LLOG_LEVEL) \ + { \ + g_write("xrdp_orders.c [%10.10u]: ", g_time3()); \ + g_writeln _params ; \ + } \ +} + /*****************************************************************************/ struct xrdp_orders* APP_CC xrdp_orders_create(struct xrdp_session* session, struct xrdp_rdp* rdp_layer) @@ -152,7 +166,7 @@ xrdp_orders_force_send(struct xrdp_orders* self) /* check if the current order will fit in packet size of 16384, if not */ /* send what we got and init a new one */ /* returns error */ -static int APP_CC +int APP_CC xrdp_orders_check(struct xrdp_orders* self, int max_size) { int size; @@ -1829,32 +1843,12 @@ xrdp_orders_send_raw_bitmap2(struct xrdp_orders* self, } /*****************************************************************************/ -static int -xrdp_orders_send_as_jpeg(struct xrdp_orders* self, - int width, int height, int bpp) -{ - if (bpp != 24) - { - return 0; - } - if (self->rdp_layer->client_info.jpeg == 0) - { - return 0; - } - if (width * height < 64) - { - return 0; - } - return 1; -} - -/*****************************************************************************/ /* returns error */ /* max size width * height * Bpp + 14 */ int APP_CC xrdp_orders_send_bitmap2(struct xrdp_orders* self, int width, int height, int bpp, char* data, - int cache_id, int cache_idx) + int cache_id, int cache_idx, int hints) { int order_flags = 0; int len = 0; @@ -1863,7 +1857,6 @@ xrdp_orders_send_bitmap2(struct xrdp_orders* self, int i = 0; int lines_sending = 0; int e = 0; - int is_jpeg; struct stream* s = NULL; struct stream* temp_s = NULL; char* p = NULL; @@ -1889,18 +1882,8 @@ xrdp_orders_send_bitmap2(struct xrdp_orders* self, init_stream(temp_s, 16384); p = s->p; i = height; - is_jpeg = 0; - if (xrdp_orders_send_as_jpeg(self, width, height, bpp)) - { - lines_sending = xrdp_jpeg_compress(data, width, height, s, bpp, 16384, - i - 1, temp_s, e); - is_jpeg = 1; - } - else - { - lines_sending = xrdp_bitmap_compress(data, width, height, s, bpp, 16384, + lines_sending = xrdp_bitmap_compress(data, width, height, s, bpp, 16384, i - 1, temp_s, e); - } if (lines_sending != height) { free_stream(s); @@ -1919,10 +1902,6 @@ height(%d)", lines_sending, height); out_uint16_le(self->out_s, len); i = (((Bpp + 2) << 3) & 0x38) | (cache_id & 7); i = i | (0x08 << 7); /* CBR2_NO_BITMAP_COMPRESSION_HDR */ - if (is_jpeg) - { - i = i | (0x80 << 7); /* unsed flag, jpeg hack */ - } out_uint16_le(self->out_s, i); /* flags */ out_uint8(self->out_s, RDP_ORDER_BMPCACHE2); /* type */ out_uint8(self->out_s, width + e); @@ -1939,6 +1918,182 @@ height(%d)", lines_sending, height); } /*****************************************************************************/ +static int +xrdp_orders_send_as_jpeg(struct xrdp_orders* self, + int width, int height, int bpp, int hints) +{ + if (hints & 1) + { + return 0; + } + if (bpp != 24) + { + return 0; + } + if (width * height < 64) + { + return 0; + } + return 1; +} + +#if defined(XRDP_FREERDP1) +/*****************************************************************************/ +/* secondary drawing order (bitmap v3) using remotefx compression */ +static int APP_CC +xrdp_orders_send_as_rfx(struct xrdp_orders* self, + int width, int height, int bpp, + int hints) +{ + if (hints & 1) + { + return 0; + } + if (bpp != 24) + { + return 0; + } + if (width * height < 64) + { + return 0; + } + return 1; +} +#endif + +/*****************************************************************************/ +static int APP_CC +xrdp_orders_out_v3(struct xrdp_orders* self, int cache_id, int cache_idx, + char* buf, int bufsize, int width, int height, int bpp, + int codec_id) +{ + int Bpp; + int order_flags; + int len; + int i; + + Bpp = (bpp + 7) / 8; + xrdp_orders_check(self, bufsize + 30); + self->order_count++; + order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY; + out_uint8(self->out_s, order_flags); + len = (bufsize + 22) - 7; /* length after type minus 7 */ + out_uint16_le(self->out_s, len); + i = (((Bpp + 2) << 3) & 0x38) | (cache_id & 7); + out_uint16_le(self->out_s, i); /* flags */ + out_uint8(self->out_s, RDP_ORDER_BMPCACHE3); /* type */ + /* cache index */ + out_uint16_le(self->out_s, cache_idx); + /* persistant cache key 1/2 */ + out_uint32_le(self->out_s, 0); + out_uint32_le(self->out_s, 0); + /* bitmap data */ + out_uint8(self->out_s, bpp); + out_uint8(self->out_s, 0); /* reserved */ + out_uint8(self->out_s, 0); /* reserved */ + out_uint8(self->out_s, codec_id); + out_uint16_le(self->out_s, width); + out_uint16_le(self->out_s, height); + out_uint32_le(self->out_s, bufsize); + out_uint8a(self->out_s, buf, bufsize); + return 0; +} + +/*****************************************************************************/ +/* secondary drawing order (bitmap v3) using remotefx compression */ +int APP_CC +xrdp_orders_send_bitmap3(struct xrdp_orders* self, + int width, int height, int bpp, char* data, + int cache_id, int cache_idx, int hints) +{ + int e; + int bufsize; + int quality; + struct stream* xr_s; /* xrdp stream */ + struct stream* temp_s; /* xrdp stream */ + struct xrdp_client_info* ci; +#if defined(XRDP_FREERDP1) + STREAM* fr_s; /* FreeRDP stream */ + RFX_CONTEXT* context; + RFX_RECT rect; +#endif + + ci = &(self->rdp_layer->client_info); + if (ci->v3_codec_id == 0) + { + return 2; + } + if (ci->v3_codec_id == ci->rfx_codec_id) + { +#if defined(XRDP_FREERDP1) + if (!xrdp_orders_send_as_rfx(self, width, height, bpp, hints)) + { + return 2; + } + LLOGLN(10, ("xrdp_orders_send_bitmap3: rfx")); + context = (RFX_CONTEXT*)(self->rdp_layer->rfx_enc); + make_stream(xr_s); + init_stream(xr_s, 16384); + fr_s = stream_new(0); + stream_attach(fr_s, (tui8*)(xr_s->data), 16384); + rect.x = 0; + rect.y = 0; + rect.width = width; + rect.height = height; + rfx_compose_message(context, fr_s, &rect, 1, (tui8*)data, width, + height, width * 4); + bufsize = stream_get_length(fr_s); + xrdp_orders_out_v3(self, cache_id, cache_idx, (char*)(fr_s->data), bufsize, + width, height, bpp,ci->v3_codec_id); + stream_detach(fr_s); + stream_free(fr_s); + free_stream(xr_s); + return 0; +#else + return 2; +#endif + } + else if (ci->v3_codec_id == ci->jpeg_codec_id) + { +#if defined(XRDP_JPEG) + if (!xrdp_orders_send_as_jpeg(self, width, height, bpp, hints)) + { + LLOGLN(10, ("xrdp_orders_send_bitmap3: jpeg skipped")); + return 2; + } + LLOGLN(10, ("xrdp_orders_send_bitmap3: jpeg")); + e = width % 4; + if (e != 0) + { + e = 4 - e; + } + make_stream(xr_s); + init_stream(xr_s, 16384); + make_stream(temp_s); + init_stream(temp_s, 16384); + quality = ci->jpeg_prop[0]; + xrdp_jpeg_compress(data, width, height, xr_s, bpp, 16384, + height - 1, temp_s, e, quality); + s_mark_end(xr_s); + bufsize = (int)(xr_s->end - xr_s->data); + xrdp_orders_out_v3(self, cache_id, cache_idx, (char*)(xr_s->data), bufsize, + width + e, height, bpp,ci->v3_codec_id); + free_stream(xr_s); + free_stream(temp_s); + return 0; +#else + return 2; +#endif + } + else + { + g_writeln("xrdp_orders_send_bitmap3: todo unknown codec"); + return 1; + } + return 0; +} + +/*****************************************************************************/ /* returns error */ /* send a brush cache entry */ int APP_CC @@ -1971,21 +2126,47 @@ xrdp_orders_send_brush(struct xrdp_orders* self, int width, int height, /* send an off screen bitmap entry */ int APP_CC xrdp_orders_send_create_os_surface(struct xrdp_orders* self, int id, - int width, int height) + int width, int height, + struct list* del_list) { int order_flags; int cache_id; + int flags; + int index; + int bytes; + int num_del_list; - g_writeln("xrdp_orders_send_create_os_surface:"); - xrdp_orders_check(self, 7); + bytes = 7; + num_del_list = del_list->count; + if (num_del_list > 0) + { + bytes += 2; + bytes += num_del_list * 2; + } + xrdp_orders_check(self, bytes); self->order_count++; order_flags = RDP_ORDER_SECONDARY; order_flags |= 1 << 2; /* type RDP_ORDER_ALTSEC_CREATE_OFFSCR_BITMAP */ out_uint8(self->out_s, order_flags); cache_id = id & 0x7fff; - out_uint16_le(self->out_s, cache_id); + flags = cache_id; + if (num_del_list > 0) + { + flags |= 0x8000; + } + out_uint16_le(self->out_s, flags); out_uint16_le(self->out_s, width); out_uint16_le(self->out_s, height); + if (num_del_list > 0) + { + /* delete list */ + out_uint16_le(self->out_s, num_del_list); + for (index = 0; index < num_del_list; index++) + { + cache_id = list_get_item(del_list, index) & 0x7fff; + out_uint16_le(self->out_s, cache_id); + } + } return 0; } @@ -1997,7 +2178,6 @@ xrdp_orders_send_switch_os_surface(struct xrdp_orders* self, int id) int order_flags; int cache_id; - g_writeln("xrdp_orders_send_switch_os_surface:"); xrdp_orders_check(self, 3); self->order_count++; order_flags = RDP_ORDER_SECONDARY; diff --git a/libxrdp/xrdp_orders_rail.c b/libxrdp/xrdp_orders_rail.c new file mode 100644 index 00000000..62f9b8ea --- /dev/null +++ b/libxrdp/xrdp_orders_rail.c @@ -0,0 +1,625 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2012 + * + * 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. + */ + +#include "libxrdp.h" +#include "xrdp_rail.h" + +/* [MS-RDPERP]: Remote Desktop Protocol: + Remote Programs Virtual Channel Extension + http://msdn.microsoft.com/en-us/library/cc242568(v=prot.10) */ + +/*****************************************************************************/ +/* RAIL */ +/* returns error */ +int APP_CC +xrdp_orders_send_window_delete(struct xrdp_orders* self, int window_id) +{ + int order_size; + int order_flags; + int field_present_flags; + + order_size = 11; + xrdp_orders_check(self, order_size); + self->order_count++; + order_flags = RDP_ORDER_SECONDARY; + order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */ + out_uint8(self->out_s, order_flags); + /* orderSize (2 bytes) */ + out_uint16_le(self->out_s, order_size); + /* FieldsPresentFlags (4 bytes) */ + field_present_flags = WINDOW_ORDER_TYPE_WINDOW | WINDOW_ORDER_STATE_DELETED; + out_uint32_le(self->out_s, field_present_flags); + /* windowId (4 bytes) */ + out_uint32_le(self->out_s, window_id); + return 0; +} + +/*****************************************************************************/ +/* RAIL */ +/* returns error */ +/* flags can contain WINDOW_ORDER_STATE_NEW and/or + WINDOW_ORDER_FIELD_ICON_BIG */ +int APP_CC +xrdp_orders_send_window_cached_icon(struct xrdp_orders* self, + int window_id, int cache_entry, + int cache_id, int flags) +{ + int order_size; + int order_flags; + int field_present_flags; + + order_size = 14; + xrdp_orders_check(self, order_size); + self->order_count++; + order_flags = RDP_ORDER_SECONDARY; + order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */ + out_uint8(self->out_s, order_flags); + /* orderSize (2 bytes) */ + out_uint16_le(self->out_s, order_size); + /* FieldsPresentFlags (4 bytes) */ + field_present_flags = flags | WINDOW_ORDER_TYPE_WINDOW | + WINDOW_ORDER_CACHED_ICON; + out_uint32_le(self->out_s, field_present_flags); + /* windowId (4 bytes) */ + out_uint32_le(self->out_s, window_id); + /* CacheEntry (2 bytes) */ + out_uint16_le(self->out_s, cache_entry); + /* CacheId (1 byte) */ + out_uint8(self->out_s, cache_id); + return 0; +} + +/*****************************************************************************/ +/* RAIL */ +/* returns error */ +static int APP_CC +xrdp_orders_send_ts_icon(struct stream* s, int cache_entry, int cache_id, + struct rail_icon_info* icon_info) +{ + int use_cmap; + + use_cmap = 0; + if ((icon_info->bpp == 1) || (icon_info->bpp == 2) || (icon_info->bpp == 4)) + { + use_cmap = 1; + } + + /* TS_ICON_INFO */ + out_uint16_le(s, cache_entry); + out_uint8(s, cache_id); + out_uint8(s, icon_info->bpp); + out_uint16_le(s, icon_info->width); + out_uint16_le(s, icon_info->height); + if (use_cmap) + { + out_uint16_le(s, icon_info->cmap_bytes); + } + out_uint16_le(s, icon_info->mask_bytes); + out_uint16_le(s, icon_info->data_bytes); + out_uint8p(s, icon_info->mask, icon_info->mask_bytes); + if (use_cmap) + { + out_uint8p(s, icon_info->cmap, icon_info->cmap_bytes); + } + out_uint8p(s, icon_info->data, icon_info->data_bytes); + return 0; +} + +/*****************************************************************************/ +/* RAIL */ +/* returns error */ +/* flags can contain WINDOW_ORDER_STATE_NEW and/or + WINDOW_ORDER_FIELD_ICON_BIG */ +int APP_CC +xrdp_orders_send_window_icon(struct xrdp_orders* self, + int window_id, int cache_entry, int cache_id, + struct rail_icon_info* icon_info, + int flags) +{ + int order_size; + int order_flags; + int field_present_flags; + int use_cmap; + + use_cmap = 0; + if ((icon_info->bpp == 1) || (icon_info->bpp == 2) || (icon_info->bpp == 4)) + { + use_cmap = 1; + } + order_size = 23 + icon_info->mask_bytes + icon_info->data_bytes; + if (use_cmap) + { + order_size += icon_info->cmap_bytes + 2; + } + xrdp_orders_check(self, order_size); + self->order_count++; + order_flags = RDP_ORDER_SECONDARY; + order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */ + out_uint8(self->out_s, order_flags); + /* orderSize (2 bytes) */ + out_uint16_le(self->out_s, order_size); + /* FieldsPresentFlags (4 bytes) */ + field_present_flags = flags | WINDOW_ORDER_TYPE_WINDOW | + WINDOW_ORDER_ICON; + out_uint32_le(self->out_s, field_present_flags); + /* windowId (4 bytes) */ + out_uint32_le(self->out_s, window_id); + + xrdp_orders_send_ts_icon(self->out_s, cache_entry, cache_id, icon_info); + + return 0; +} + +/*****************************************************************************/ +/* returns error */ +static int APP_CC +xrdp_orders_send_as_unicode(struct stream* s, const char* text) +{ + int str_chars; + int index; + int i32; + twchar wdst[256]; + + str_chars = g_mbstowcs(wdst, text, 255); + if (str_chars > 0) + { + i32 = str_chars * 2; + out_uint16_le(s, i32); + for (index = 0; index < str_chars; index++) + { + i32 = wdst[index]; + out_uint16_le(s, i32); + } + } + else + { + out_uint16_le(s, 0); + } + return 0; +} + +/*****************************************************************************/ +/* RAIL */ +/* returns error */ +/* flags can contain WINDOW_ORDER_STATE_NEW */ +int APP_CC +xrdp_orders_send_window_new_update(struct xrdp_orders* self, int window_id, + struct rail_window_state_order* window_state, + int flags) +{ + int order_size; + int order_flags; + int field_present_flags; + int num_chars; + int index; + + order_size = 11; + field_present_flags = flags | WINDOW_ORDER_TYPE_WINDOW; + if (field_present_flags & WINDOW_ORDER_FIELD_OWNER) + { + /* ownerWindowId (4 bytes) */ + order_size += 4; + } + if (field_present_flags & WINDOW_ORDER_FIELD_STYLE) + { + /* style (4 bytes) */ + order_size += 4; + /* extendedStyle (4 bytes) */ + order_size += 4; + } + if (field_present_flags & WINDOW_ORDER_FIELD_SHOW) + { + /* showState (1 byte) */ + order_size += 1; + } + if (field_present_flags & WINDOW_ORDER_FIELD_TITLE) + { + /* titleInfo */ + num_chars = g_mbstowcs(0, window_state->title_info, 0); + order_size += 2 * num_chars + 2; + } + if (field_present_flags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) + { + /* clientOffsetX (4 bytes) */ + order_size += 4; + /* clientOffsetY (4 bytes) */ + order_size += 4; + } + if (field_present_flags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) + { + /* clientAreaWidth (4 bytes) */ + order_size += 4; + /* clientAreaHeight (4 bytes) */ + order_size += 4; + } + if (field_present_flags & WINDOW_ORDER_FIELD_RP_CONTENT) + { + /* RPContent (1 byte) */ + order_size += 1; + } + if (field_present_flags & WINDOW_ORDER_FIELD_ROOT_PARENT) + { + /* rootParentHandle (4 bytes) */ + order_size += 4; + } + if (field_present_flags & WINDOW_ORDER_FIELD_WND_OFFSET) + { + /* windowOffsetX (4 bytes) */ + order_size += 4; + /* windowOffsetY (4 bytes) */ + order_size += 4; + } + if (field_present_flags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) + { + /* windowClientDeltaX (4 bytes) */ + order_size += 4; + /* windowClientDeltaY (4 bytes) */ + order_size += 4; + } + if (field_present_flags & WINDOW_ORDER_FIELD_WND_SIZE) + { + /* windowWidth (4 bytes) */ + order_size += 4; + /* windowHeight (4 bytes) */ + order_size += 4; + } + if (field_present_flags & WINDOW_ORDER_FIELD_WND_RECTS) + { + /* numWindowRects (2 bytes) */ + order_size += 2; + order_size += 8 * window_state->num_window_rects; + } + if (field_present_flags & WINDOW_ORDER_FIELD_VIS_OFFSET) + { + /* visibleOffsetX (4 bytes) */ + order_size += 4; + /* visibleOffsetY (4 bytes) */ + order_size += 4; + } + if (field_present_flags & WINDOW_ORDER_FIELD_VISIBILITY) + { + /* numVisibilityRects (2 bytes) */ + order_size += 2; + order_size += 8 * window_state->num_visibility_rects; + } + + xrdp_orders_check(self, order_size); + self->order_count++; + order_flags = RDP_ORDER_SECONDARY; + order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */ + out_uint8(self->out_s, order_flags); + /* orderSize (2 bytes) */ + out_uint16_le(self->out_s, order_size); + /* FieldsPresentFlags (4 bytes) */ + out_uint32_le(self->out_s, field_present_flags); + /* windowId (4 bytes) */ + out_uint32_le(self->out_s, window_id); + + if (field_present_flags & WINDOW_ORDER_FIELD_OWNER) + { + /* ownerWindowId (4 bytes) */ + out_uint32_le(self->out_s, window_state->owner_window_id); + } + if (field_present_flags & WINDOW_ORDER_FIELD_STYLE) + { + /* style (4 bytes) */ + out_uint32_le(self->out_s, window_state->style); + /* extendedStyle (4 bytes) */ + out_uint32_le(self->out_s, window_state->extended_style); + } + if (field_present_flags & WINDOW_ORDER_FIELD_SHOW) + { + /* showState (1 byte) */ + out_uint8(self->out_s, window_state->show_state); + } + if (field_present_flags & WINDOW_ORDER_FIELD_TITLE) + { + /* titleInfo */ + xrdp_orders_send_as_unicode(self->out_s, window_state->title_info); + } + if (field_present_flags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) + { + /* clientOffsetX (4 bytes) */ + out_uint32_le(self->out_s, window_state->client_offset_x); + /* clientOffsetY (4 bytes) */ + out_uint32_le(self->out_s, window_state->client_offset_y); + } + if (field_present_flags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) + { + /* clientAreaWidth (4 bytes) */ + out_uint32_le(self->out_s, window_state->client_area_width); + /* clientAreaHeight (4 bytes) */ + out_uint32_le(self->out_s, window_state->client_area_height); + } + if (field_present_flags & WINDOW_ORDER_FIELD_RP_CONTENT) + { + /* RPContent (1 byte) */ + out_uint8(self->out_s, window_state->rp_content); + } + if (field_present_flags & WINDOW_ORDER_FIELD_ROOT_PARENT) + { + /* rootParentHandle (4 bytes) */ + out_uint32_le(self->out_s, window_state->root_parent_handle); + } + if (field_present_flags & WINDOW_ORDER_FIELD_WND_OFFSET) + { + /* windowOffsetX (4 bytes) */ + out_uint32_le(self->out_s, window_state->window_offset_x); + /* windowOffsetY (4 bytes) */ + out_uint32_le(self->out_s, window_state->window_offset_y); + } + if (field_present_flags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) + { + /* windowClientDeltaX (4 bytes) */ + out_uint32_le(self->out_s, window_state->window_client_delta_x); + /* windowClientDeltaY (4 bytes) */ + out_uint32_le(self->out_s, window_state->window_client_delta_y); + } + if (field_present_flags & WINDOW_ORDER_FIELD_WND_SIZE) + { + /* windowWidth (4 bytes) */ + out_uint32_le(self->out_s, window_state->window_width); + /* windowHeight (4 bytes) */ + out_uint32_le(self->out_s, window_state->window_height); + } + if (field_present_flags & WINDOW_ORDER_FIELD_WND_RECTS) + { + /* numWindowRects (2 bytes) */ + out_uint16_le(self->out_s, window_state->num_window_rects); + for (index = 0; index < window_state->num_window_rects; index++) + { + out_uint16_le(self->out_s, window_state->window_rects[index].left); + out_uint16_le(self->out_s, window_state->window_rects[index].top); + out_uint16_le(self->out_s, window_state->window_rects[index].right); + out_uint16_le(self->out_s, window_state->window_rects[index].bottom); + } + } + if (field_present_flags & WINDOW_ORDER_FIELD_VIS_OFFSET) + { + /* visibleOffsetX (4 bytes) */ + out_uint32_le(self->out_s, window_state->visible_offset_x); + /* visibleOffsetY (4 bytes) */ + out_uint32_le(self->out_s, window_state->visible_offset_y); + } + if (field_present_flags & WINDOW_ORDER_FIELD_VISIBILITY) + { + /* numVisibilityRects (2 bytes) */ + out_uint16_le(self->out_s, window_state->num_visibility_rects); + for (index = 0; index < window_state->num_visibility_rects; index++) + { + out_uint16_le(self->out_s, window_state->visibility_rects[index].left); + out_uint16_le(self->out_s, window_state->visibility_rects[index].top); + out_uint16_le(self->out_s, window_state->visibility_rects[index].right); + out_uint16_le(self->out_s, window_state->visibility_rects[index].bottom); + } + } + + return 0; +} + +/*****************************************************************************/ +/* RAIL */ +/* returns error */ +int APP_CC +xrdp_orders_send_notify_delete(struct xrdp_orders* self, int window_id, + int notify_id) +{ + int order_size; + int order_flags; + int field_present_flags; + + order_size = 15; + xrdp_orders_check(self, order_size); + self->order_count++; + order_flags = RDP_ORDER_SECONDARY; + order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */ + out_uint8(self->out_s, order_flags); + /* orderSize (2 bytes) */ + out_uint16_le(self->out_s, order_size); + /* FieldsPresentFlags (4 bytes) */ + field_present_flags = WINDOW_ORDER_TYPE_NOTIFY | WINDOW_ORDER_STATE_DELETED; + out_uint32_le(self->out_s, field_present_flags); + /* windowId (4 bytes) */ + out_uint32_le(self->out_s, window_id); + /* notifyIconId (4 bytes) */ + out_uint32_le(self->out_s, notify_id); + return 0; +} + +/*****************************************************************************/ +/* RAIL */ +/* returns error */ +/* flags can contain WINDOW_ORDER_STATE_NEW */ +int APP_CC +xrdp_orders_send_notify_new_update(struct xrdp_orders* self, + int window_id, int notify_id, + struct rail_notify_state_order* notify_state, + int flags) +{ + int order_size; + int order_flags; + int field_present_flags; + int num_chars; + int use_cmap; + + order_size = 15; + field_present_flags = flags | WINDOW_ORDER_TYPE_NOTIFY; + if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_VERSION) + { + /* Version (4 bytes) */ + order_size += 4; + } + if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_TIP) + { + /* ToolTip (variable) UNICODE_STRING */ + num_chars = g_mbstowcs(0, notify_state->tool_tip, 0); + order_size += 2 * num_chars + 2; + } + if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP) + { + /* InfoTip (variable) TS_NOTIFY_ICON_INFOTIP */ + /* UNICODE_STRING */ + num_chars = g_mbstowcs(0, notify_state->infotip.title, 0); + order_size += 2 * num_chars + 2; + /* UNICODE_STRING */ + num_chars = g_mbstowcs(0, notify_state->infotip.text, 0); + order_size += 2 * num_chars + 2; + /* Timeout (4 bytes) */ + /* InfoFlags (4 bytes) */ + order_size += 8; + } + if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_STATE) + { + /* State (4 bytes) */ + order_size += 4; + } + if (field_present_flags & WINDOW_ORDER_ICON) + { + /* Icon (variable) */ + use_cmap = 0; + if ((notify_state->icon_info.bpp == 1) || (notify_state->icon_info.bpp == 2) || + (notify_state->icon_info.bpp == 4)) + { + use_cmap = 1; + } + order_size += 12 + notify_state->icon_info.mask_bytes + + notify_state->icon_info.data_bytes; + if (use_cmap) + { + order_size += notify_state->icon_info.cmap_bytes + 2; + } + } + if (field_present_flags & WINDOW_ORDER_CACHED_ICON) + { + /* CachedIcon (3 bytes) */ + order_size += 3; + } + + xrdp_orders_check(self, order_size); + self->order_count++; + order_flags = RDP_ORDER_SECONDARY; + order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */ + out_uint8(self->out_s, order_flags); + /* orderSize (2 bytes) */ + out_uint16_le(self->out_s, order_size); + /* FieldsPresentFlags (4 bytes) */ + out_uint32_le(self->out_s, field_present_flags); + /* windowId (4 bytes) */ + out_uint32_le(self->out_s, window_id); + /* notifyIconId (4 bytes) */ + out_uint32_le(self->out_s, notify_id); + + if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_VERSION) + { + /* Version (4 bytes) */ + out_uint32_le(self->out_s, notify_state->version); + } + if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_TIP) + { + /* ToolTip (variable) UNICODE_STRING */ + xrdp_orders_send_as_unicode(self->out_s, notify_state->tool_tip); + } + if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP) + { + /* InfoTip (variable) TS_NOTIFY_ICON_INFOTIP */ + out_uint32_le(self->out_s, notify_state->infotip.timeout); + out_uint32_le(self->out_s, notify_state->infotip.flags); + xrdp_orders_send_as_unicode(self->out_s, notify_state->infotip.text); + xrdp_orders_send_as_unicode(self->out_s, notify_state->infotip.title); + } + if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_STATE) + { + /* State (4 bytes) */ + out_uint32_le(self->out_s, notify_state->state); + } + if (field_present_flags & WINDOW_ORDER_ICON) + { + /* Icon (variable) */ + xrdp_orders_send_ts_icon(self->out_s, notify_state->icon_cache_entry, + notify_state->icon_cache_id, + ¬ify_state->icon_info); + } + if (field_present_flags & WINDOW_ORDER_CACHED_ICON) + { + /* CacheEntry (2 bytes) */ + out_uint16_le(self->out_s, notify_state->icon_cache_entry); + /* CacheId (1 byte) */ + out_uint8(self->out_s, notify_state->icon_cache_id); + } + + return 0; +} + +/*****************************************************************************/ +/* RAIL */ +/* returns error */ +/* used for both Non-Monitored Desktop and Actively Monitored Desktop */ +int APP_CC +xrdp_orders_send_monitored_desktop(struct xrdp_orders* self, + struct rail_monitored_desktop_order* mdo, + int flags) +{ + int order_size; + int order_flags; + int field_present_flags; + int index; + + order_size = 7; + field_present_flags = flags | WINDOW_ORDER_TYPE_DESKTOP; + + if (field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND) + { + /* ActiveWindowId (4 bytes) */ + order_size += 4; + } + if (field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER) + { + /* NumWindowIds (1 byte) */ + order_size += 1; + /* WindowIds (variable) */ + order_size += mdo->num_window_ids * 4; + } + + xrdp_orders_check(self, order_size); + self->order_count++; + order_flags = RDP_ORDER_SECONDARY; + order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */ + out_uint8(self->out_s, order_flags); + /* orderSize (2 bytes) */ + out_uint16_le(self->out_s, order_size); + /* FieldsPresentFlags (4 bytes) */ + out_uint32_le(self->out_s, field_present_flags); + + if (field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND) + { + /* ActiveWindowId (4 bytes) */ + out_uint32_le(self->out_s, mdo->active_window_id); + } + if (field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER) + { + /* NumWindowIds (1 byte) */ + out_uint8(self->out_s, mdo->num_window_ids); + /* WindowIds (variable) */ + for (index = 0; index < mdo->num_window_ids; index++) + { + out_uint32_le(self->out_s, mdo->window_ids[index]); + } + } + + return 0; +} diff --git a/libxrdp/xrdp_orders_rail.h b/libxrdp/xrdp_orders_rail.h new file mode 100644 index 00000000..8f5b402f --- /dev/null +++ b/libxrdp/xrdp_orders_rail.h @@ -0,0 +1,50 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2012 + * + * 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. + */ + +#if !defined(_XRDP_ORDERS_RAIL_H) +#define _XRDP_ORDERS_RAIL_H + +int APP_CC +xrdp_orders_send_window_delete(struct xrdp_orders* self, int window_id); +int APP_CC +xrdp_orders_send_window_cached_icon(struct xrdp_orders* self, + int window_id, int cache_entry, + int cache_id, int flags); +int APP_CC +xrdp_orders_send_window_icon(struct xrdp_orders* self, + int window_id, int cache_entry, int cache_id, + struct rail_icon_info* icon_info, + int flags); +int APP_CC +xrdp_orders_send_window_new_update(struct xrdp_orders* self, int window_id, + struct rail_window_state_order* window_state, + int flags); +int APP_CC +xrdp_orders_send_notify_delete(struct xrdp_orders* self, int window_id, + int notify_id); +int APP_CC +xrdp_orders_send_notify_new_update(struct xrdp_orders* self, + int window_id, int notify_id, + struct rail_notify_state_order* notify_state, + int flags); +int APP_CC +xrdp_orders_send_monitored_desktop(struct xrdp_orders* self, + struct rail_monitored_desktop_order* mdo, + int flags); + +#endif diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index bdbeed48..53e3ddc2 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -24,6 +24,7 @@ #if defined(XRDP_FREERDP1) #include <freerdp/codec/mppc_enc.h> +#include <freerdp/codec/rfx.h> #endif /* some compilers need unsigned char to avoid warnings */ @@ -113,13 +114,25 @@ xrdp_rdp_read_config(struct xrdp_client_info* client_info) { client_info->crypt_level = 3; } + else + { + g_writeln("Warning: Your configured crypt level is" + "undefined 'high' will be used"); + client_info->crypt_level = 3; + } } else if (g_strcasecmp(item, "channel_code") == 0) { - if (g_strcasecmp(value, "1") == 0) + if ((g_strcasecmp(value, "yes") == 0) || + (g_strcasecmp(value, "1") == 0) || + (g_strcasecmp(value, "true") == 0)) { client_info->channel_code = 1; } + else + { + g_writeln("Info: All channels are disabled"); + } } else if (g_strcasecmp(item, "max_bpp") == 0) { @@ -131,11 +144,66 @@ xrdp_rdp_read_config(struct xrdp_client_info* client_info) return 0; } +#if defined(XRDP_FREERDP1) +/*****************************************************************************/ +static void +cpuid(tui32 info, tui32* eax, tui32* ebx, tui32* ecx, tui32* edx) +{ +#ifdef __GNUC__ +#if defined(__i386__) || defined(__x86_64__) + __asm volatile + ( + /* The EBX (or RBX register on x86_64) is used for the PIC base address + and must not be corrupted by our inline assembly. */ +#if defined(__i386__) + "mov %%ebx, %%esi;" + "cpuid;" + "xchg %%ebx, %%esi;" +#else + "mov %%rbx, %%rsi;" + "cpuid;" + "xchg %%rbx, %%rsi;" +#endif + : "=a" (*eax), "=S" (*ebx), "=c" (*ecx), "=d" (*edx) + : "0" (info) + ); +#endif +#endif +} + +/*****************************************************************************/ +static tui32 +xrdp_rdp_detect_cpu(void) +{ + tui32 eax; + tui32 ebx; + tui32 ecx; + tui32 edx; + tui32 cpu_opt; + + eax = 0; + ebx = 0; + ecx = 0; + edx = 0; + cpu_opt = 0; + cpuid(1, &eax, &ebx, &ecx, &edx); + + if (edx & (1 << 26)) + { + DEBUG("SSE2 detected"); + cpu_opt |= CPU_SSE2; + } + + return cpu_opt; +} +#endif + /*****************************************************************************/ struct xrdp_rdp* APP_CC xrdp_rdp_create(struct xrdp_session* session, struct trans* trans) { struct xrdp_rdp* self = (struct xrdp_rdp *)NULL; + int bytes; DEBUG(("in xrdp_rdp_create")); self = (struct xrdp_rdp*)g_malloc(sizeof(struct xrdp_rdp), 1); @@ -153,9 +221,13 @@ xrdp_rdp_create(struct xrdp_session* session, struct trans* trans) self->client_info.cache2_size = 1024; self->client_info.cache3_entries = 262; self->client_info.cache3_size = 4096; - g_write_ip_address(trans->sck, self->client_info.client_ip); /* load client ip info */ + /* load client ip info */ + bytes = sizeof(self->client_info.client_ip) - 1; + g_write_ip_address(trans->sck, self->client_info.client_ip, bytes); #if defined(XRDP_FREERDP1) self->mppc_enc = mppc_enc_new(PROTO_RDP_50); + self->rfx_enc = rfx_context_new(); + rfx_context_set_cpu_opt(self->rfx_enc, xrdp_rdp_detect_cpu()); #endif self->client_info.size = sizeof(self->client_info); DEBUG(("out xrdp_rdp_create")); @@ -173,6 +245,7 @@ xrdp_rdp_delete(struct xrdp_rdp* self) xrdp_sec_delete(self->sec_layer); #if defined(XRDP_FREERDP1) mppc_enc_free((struct rdp_mppc_enc*)(self->mppc_enc)); + rfx_context_free((RFX_CONTEXT*)(self->rfx_enc)); #endif g_free(self); } @@ -220,7 +293,7 @@ xrdp_rdp_recv(struct xrdp_rdp* self, struct stream* s, int* code) { s->next_packet = 0; *code = -1; - DEBUG(("out xrdp_rdp_recv")); + DEBUG(("out (1) xrdp_rdp_recv")); return 0; } if (error != 0) @@ -232,35 +305,47 @@ xrdp_rdp_recv(struct xrdp_rdp* self, struct stream* s, int* code) { if (chan > MCS_GLOBAL_CHANNEL) { - xrdp_channel_process(self->sec_layer->chan_layer, s, chan); + if(xrdp_channel_process(self->sec_layer->chan_layer, s, chan)!=0) + { + g_writeln("xrdp_channel_process returned unhandled error") ; + } + } + else + { + g_writeln("Wrong channel Id to be handled by xrdp_channel_process %d",chan); } s->next_packet = 0; *code = 0; - DEBUG(("out xrdp_rdp_recv")); + DEBUG(("out (2) xrdp_rdp_recv")); return 0; } s->next_packet = s->p; } else { + DEBUG(("xrdp_rdp_recv stream not touched")) s->p = s->next_packet; } if (!s_check_rem(s, 6)) { s->next_packet = 0; *code = 0; - DEBUG(("out xrdp_rdp_recv")); + DEBUG(("out (3) xrdp_rdp_recv")); len = (int)(s->end - s->p); g_writeln("xrdp_rdp_recv: bad RDP packet, length [%d]", len); return 0; } - in_uint16_le(s, len); - in_uint16_le(s, pdu_code); - *code = pdu_code & 0xf; - in_uint8s(s, 2); /* mcs user id */ - s->next_packet += len; - DEBUG(("out xrdp_rdp_recv")); - return 0; + else + { + in_uint16_le(s, len); + /*g_writeln("New len received : %d next packet: %d s_end: %d",len,s->next_packet,s->end); */ + in_uint16_le(s, pdu_code); + *code = pdu_code & 0xf; + in_uint8s(s, 2); /* mcs user id */ + s->next_packet += len; + DEBUG(("out (4) xrdp_rdp_recv")); + return 0; + } } /*****************************************************************************/ @@ -318,7 +403,7 @@ xrdp_rdp_send_data(struct xrdp_rdp* self, struct stream* s, if (self->client_info.rdp_compression && self->session->up_and_running) { mppc_enc = (struct rdp_mppc_enc*)(self->mppc_enc); - if (compress_rdp(mppc_enc, s->p + 18, tocomplen)) + if (compress_rdp(mppc_enc, (tui8*)(s->p + 18), tocomplen)) { DEBUG(("mppc_encode ok flags 0x%x bytes_in_opb %d historyOffset %d " "tocomplen %d", mppc_enc->flags, mppc_enc->bytes_in_opb, @@ -474,9 +559,13 @@ xrdp_rdp_send_demand_active(struct xrdp_rdp* self) struct stream* s; int caps_count; int caps_size; + int codec_caps_count; + int codec_caps_size; char* caps_count_ptr; char* caps_size_ptr; char* caps_ptr; + char* codec_caps_count_ptr; + char* codec_caps_size_ptr; make_stream(s); init_stream(s, 8192); @@ -589,12 +678,48 @@ xrdp_rdp_send_demand_active(struct xrdp_rdp* self) out_uint8(s, 0); /* unused */ out_uint8(s, 0); /* unused */ out_uint16_le(s, 0x6a1); - out_uint8s(s, 2); /* ? */ + /* declare support of bitmap cache rev3 */ + out_uint16_le(s, XR_ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT); out_uint32_le(s, 0x0f4240); /* desk save */ out_uint32_le(s, 0x0f4240); /* desk save */ out_uint32_le(s, 1); /* ? */ out_uint32_le(s, 0); /* ? */ + /* Output bmpcodecs capability set */ + caps_count++; + out_uint16_le(s, RDP_CAPSET_BMPCODECS); + codec_caps_size_ptr = s->p; + out_uint8s(s, 2); /* cap len set later */ + codec_caps_count = 0; + codec_caps_count_ptr = s->p; + out_uint8s(s, 1); /* bitmapCodecCount set later */ + /* nscodec */ + codec_caps_count++; + out_uint8a(s, XR_CODEC_GUID_NSCODEC, 16); + out_uint8(s, 1); /* codec id, must be 1 */ + out_uint16_le(s, 3); + out_uint8(s, 0x01); /* fAllowDynamicFidelity */ + out_uint8(s, 0x01); /* fAllowSubsampling */ + out_uint8(s, 0x03); /* colorLossLevel */ + /* remotefx */ + codec_caps_count++; + out_uint8a(s, XR_CODEC_GUID_REMOTEFX, 16); + out_uint8(s, 0); /* codec id, client sets */ + out_uint16_le(s, 256); + out_uint8s(s, 256); + /* jpeg */ + codec_caps_count++; + out_uint8a(s, XR_CODEC_GUID_JPEG, 16); + out_uint8(s, 0); /* codec id, client sets */ + out_uint16_le(s, 1); /* ext length */ + out_uint8(s, 75); + /* calculate and set size and count */ + codec_caps_size = (int)(s->p - codec_caps_size_ptr); + codec_caps_size += 2; /* 2 bytes for RDP_CAPSET_BMPCODECS above */ + codec_caps_size_ptr[0] = codec_caps_size; + codec_caps_size_ptr[1] = codec_caps_size >> 8; + codec_caps_count_ptr[0] = codec_caps_count; + /* Output color cache capability set */ caps_count++; out_uint16_le(s, RDP_CAPSET_COLCACHE); @@ -617,6 +742,27 @@ xrdp_rdp_send_demand_active(struct xrdp_rdp* self) out_uint8(s, 1); out_uint8s(s, 83); + /* Remote Programs Capability Set */ + caps_count++; + out_uint16_le(s, 0x0017); /* CAPSETTYPE_RAIL */ + out_uint16_le(s, 8); + out_uint32_le(s, 3); /* TS_RAIL_LEVEL_SUPPORTED + TS_RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED */ + + /* Window List Capability Set */ + caps_count++; + out_uint16_le(s, 0x0018); /* CAPSETTYPE_WINDOW */ + out_uint16_le(s, 11); + out_uint32_le(s, 2); /* TS_WINDOW_LEVEL_SUPPORTED_EX */ + out_uint8(s, 3); /* NumIconCaches */ + out_uint16_le(s, 12); /* NumIconCacheEntries */ + + /* 6 - bitmap cache v3 codecid */ + caps_count++; + out_uint16_le(s, 0x0006); + out_uint16_le(s, 5); + out_uint8(s, 0); /* client sets */ + out_uint8s(s, 4); /* pad */ s_mark_end(s); @@ -664,6 +810,7 @@ xrdp_process_capset_order(struct xrdp_rdp* self, struct stream* s, { int i; char order_caps[32]; + int ex_flags; DEBUG(("order capabilities")); in_uint8s(s, 20); /* Terminal desc, pad */ @@ -694,7 +841,15 @@ xrdp_process_capset_order(struct xrdp_rdp* self, struct stream* s, g_hexdump(order_caps, 32); #endif in_uint8s(s, 2); /* Text capability flags */ - in_uint8s(s, 6); /* Pad */ + /* read extended order support flags */ + in_uint16_le(s, ex_flags); /* Ex flags */ + if (ex_flags & XR_ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT) + { + g_writeln("xrdp_process_capset_order: bitmap cache v3 supported"); + self->client_info.bitmap_cache_version |= 4; + } + in_uint8s(s, 4); /* Pad */ + in_uint32_le(s, i); /* desktop cache size, usually 0x38400 */ self->client_info.desktop_cache = i; DEBUG(("desktop cache size %d", i)); @@ -709,6 +864,7 @@ static int APP_CC xrdp_process_capset_bmpcache(struct xrdp_rdp* self, struct stream* s, int len) { + self->client_info.bitmap_cache_version |= 1; in_uint8s(s, 24); in_uint16_le(s, self->client_info.cache1_entries); in_uint16_le(s, self->client_info.cache1_size); @@ -734,16 +890,9 @@ xrdp_process_capset_bmpcache2(struct xrdp_rdp* self, struct stream* s, int Bpp = 0; int i = 0; - self->client_info.bitmap_cache_version = 2; + self->client_info.bitmap_cache_version |= 2; Bpp = (self->client_info.bpp + 7) / 8; in_uint16_le(s, i); /* cache flags */ -#if defined(XRDP_JPEG) - if (i & 0x80) - { - g_writeln("xrdp_process_capset_bmpcache2: client supports jpeg"); - self->client_info.jpeg = 1; - } -#endif self->client_info.bitmap_cache_persist_enable = i; in_uint8s(s, 2); /* number of caches in set, 3 */ in_uint32_le(s, i); @@ -769,6 +918,20 @@ xrdp_process_capset_bmpcache2(struct xrdp_rdp* self, struct stream* s, } /*****************************************************************************/ +static int +xrdp_process_capset_cache_v3_codec_id(struct xrdp_rdp* self, struct stream* s, + int len) +{ + int codec_id; + + in_uint8(s, codec_id); + g_writeln("xrdp_process_capset_cache_v3_codec_id: cache_v3_codec_id %d", + codec_id); + self->client_info.v3_codec_id = codec_id; + return 0; +} + +/*****************************************************************************/ /* get the number of client cursor cache */ static int APP_CC xrdp_process_capset_pointercache(struct xrdp_rdp* self, struct stream* s, @@ -823,6 +986,106 @@ xrdp_process_offscreen_bmpcache(struct xrdp_rdp* self, struct stream* s, } /*****************************************************************************/ +static int APP_CC +xrdp_process_capset_rail(struct xrdp_rdp* self, struct stream* s, int len) +{ + int i32; + + if (len - 4 < 4) + { + g_writeln("xrdp_process_capset_rail: bad len"); + return 1; + } + in_uint32_le(s, i32); + self->client_info.rail_support_level = i32; + g_writeln("xrdp_process_capset_rail: rail_support_level %d", + self->client_info.rail_support_level); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +xrdp_process_capset_window(struct xrdp_rdp* self, struct stream* s, int len) +{ + int i32; + + if (len - 4 < 7) + { + g_writeln("xrdp_process_capset_window: bad len"); + return 1; + } + in_uint32_le(s, i32); + self->client_info.wnd_support_level = i32; + in_uint8(s, i32); + self->client_info.wnd_num_icon_caches = i32; + in_uint16_le(s, i32); + self->client_info.wnd_num_icon_cache_entries = i32; + g_writeln("xrdp_process_capset_window wnd_support_level %d " + "wnd_num_icon_caches %d wnd_num_icon_cache_entries %d", + self->client_info.wnd_support_level, + self->client_info.wnd_num_icon_caches, + self->client_info.wnd_num_icon_cache_entries); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +xrdp_process_capset_codecs(struct xrdp_rdp* self, struct stream* s, int len) +{ + int codec_id; + int codec_count; + int index; + int codec_properties_length; + int i1; + char* codec_guid; + char* next_guid; + + in_uint8(s, codec_count); + for (index = 0; index < codec_count; index++) + { + codec_guid = s->p; + in_uint8s(s, 16); + in_uint8(s, codec_id); + in_uint16_le(s, codec_properties_length); + next_guid = s->p + codec_properties_length; + if (g_memcmp(codec_guid, XR_CODEC_GUID_NSCODEC, 16) == 0) + { + g_writeln("xrdp_process_capset_codecs: nscodec codec id %d prop len %d", + codec_id, codec_properties_length); + self->client_info.ns_codec_id = codec_id; + i1 = MIN(64, codec_properties_length); + g_memcpy(self->client_info.ns_prop, s->p, i1); + self->client_info.ns_prop_len = i1; + } + else if (g_memcmp(codec_guid, XR_CODEC_GUID_REMOTEFX, 16) == 0) + { + g_writeln("xrdp_process_capset_codecs: rfx codec id %d prop len %d", + codec_id, codec_properties_length); + self->client_info.rfx_codec_id = codec_id; + i1 = MIN(64, codec_properties_length); + g_memcpy(self->client_info.rfx_prop, s->p, i1); + self->client_info.rfx_prop_len = i1; + } + else if (g_memcmp(codec_guid, XR_CODEC_GUID_JPEG, 16) == 0) + { + g_writeln("xrdp_process_capset_codecs: jpeg codec id %d prop len %d", + codec_id, codec_properties_length); + self->client_info.jpeg_codec_id = codec_id; + i1 = MIN(64, codec_properties_length); + g_memcpy(self->client_info.jpeg_prop, s->p, i1); + self->client_info.jpeg_prop_len = i1; + g_writeln(" jpeg quality %d", self->client_info.jpeg_prop[0]); + } + else + { + g_writeln("xrdp_process_capset_codecs: unknown codec id %d", codec_id); + } + s->p = next_guid; + } + return 0; +} + +/*****************************************************************************/ int APP_CC xrdp_rdp_process_confirm_active(struct xrdp_rdp* self, struct stream* s) { @@ -867,6 +1130,9 @@ xrdp_rdp_process_confirm_active(struct xrdp_rdp* self, struct stream* s) case RDP_CAPSET_CONTROL: /* 5 */ DEBUG(("RDP_CAPSET_CONTROL")); break; + case 6: + xrdp_process_capset_cache_v3_codec_id(self, s, len); + break; case RDP_CAPSET_ACTIVATE: /* 7 */ DEBUG(("RDP_CAPSET_ACTIVATE")); break; @@ -912,9 +1178,18 @@ xrdp_rdp_process_confirm_active(struct xrdp_rdp* self, struct stream* s) case 22: /* 22 */ DEBUG(("--22")); break; + case 0x0017: /* 23 CAPSETTYPE_RAIL */ + xrdp_process_capset_rail(self, s, len); + break; + case 0x0018: /* 24 CAPSETTYPE_WINDOW */ + xrdp_process_capset_window(self, s, len); + break; case 26: /* 26 */ DEBUG(("--26")); break; + case RDP_CAPSET_BMPCODECS: /* 0x1d(29) */ + xrdp_process_capset_codecs(self, s, len); + break; default: g_writeln("unknown in xrdp_rdp_process_confirm_active %d", type); break; diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index 952ff12f..381e8435 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -148,9 +148,20 @@ xrdp_sec_create(struct xrdp_rdp* owner, struct trans* trans, int crypt_level, self->rc4_key_size = 2; self->crypt_level = 3; break; + default: + g_writeln("Fatal : Illegal crypt_level"); + break ; } self->channel_code = channel_code; + if(self->decrypt_rc4_info!=NULL) + { + g_writeln("xrdp_sec_create - decrypt_rc4_info already created !!!"); + } self->decrypt_rc4_info = ssl_rc4_info_create(); + if(self->encrypt_rc4_info!=NULL) + { + g_writeln("xrdp_sec_create - encrypt_rc4_info already created !!!"); + } self->encrypt_rc4_info = ssl_rc4_info_create(); self->mcs_layer = xrdp_mcs_create(self, trans, &self->client_mcs_data, &self->server_mcs_data); @@ -165,14 +176,17 @@ xrdp_sec_delete(struct xrdp_sec* self) { if (self == 0) { + g_writeln("xrdp_sec_delete: indata is null"); return; } xrdp_channel_delete(self->chan_layer); xrdp_mcs_delete(self->mcs_layer); - ssl_rc4_info_delete(self->decrypt_rc4_info); - ssl_rc4_info_delete(self->encrypt_rc4_info); + ssl_rc4_info_delete(self->decrypt_rc4_info); /* TODO clear all data */ + ssl_rc4_info_delete(self->encrypt_rc4_info); /* TODO clear all data */ g_free(self->client_mcs_data.data); g_free(self->server_mcs_data.data); + /* Crypto information must always be cleared */ + g_memset(self,0,sizeof(struct xrdp_sec)); g_free(self); } @@ -722,6 +736,7 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec* self, struct stream* s) /* this is an option set in xrdp.ini */ if (self->channel_code != 1) /* are channels on? */ { + g_writeln("Processing channel data from client - The channel is off"); return 0; } in_uint32_le(s, num_channels); diff --git a/mc/Makefile.am b/mc/Makefile.am index 5d1cb0fa..eb000085 100644 --- a/mc/Makefile.am +++ b/mc/Makefile.am @@ -15,4 +15,4 @@ lib_LTLIBRARIES = \ libmc_la_SOURCES = mc.c libmc_la_LIBADD = \ - $(top_srcdir)/common/libcommon.la + $(top_builddir)/common/libcommon.la diff --git a/rdp/Makefile.am b/rdp/Makefile.am index 4565838d..6f698d29 100644 --- a/rdp/Makefile.am +++ b/rdp/Makefile.am @@ -24,4 +24,4 @@ librdp_la_SOURCES = \ rdp_tcp.c librdp_la_LIBADD = \ - $(top_srcdir)/common/libcommon.la + $(top_builddir)/common/libcommon.la diff --git a/rdp/rdp_sec.c b/rdp/rdp_sec.c index e57c188d..5efab76e 100644 --- a/rdp/rdp_sec.c +++ b/rdp/rdp_sec.c @@ -46,7 +46,15 @@ rdp_sec_create(struct rdp_rdp* owner) init_stream(self->server_mcs_data, 8192); self->mcs_layer = rdp_mcs_create(self, self->client_mcs_data, self->server_mcs_data); + if(self->decrypt_rc4_info!=NULL) + { + g_writeln("rdp_sec_create - decrypt_rc4_info already created !!!"); + } self->decrypt_rc4_info = ssl_rc4_info_create(); + if(self->encrypt_rc4_info!=NULL) + { + g_writeln("rdp_sec_create - encrypt_rc4_info already created !!!"); + } self->encrypt_rc4_info = ssl_rc4_info_create(); self->lic_layer = rdp_lic_create(self); return self; @@ -1,9 +1,9 @@ -xrdp 0.6.0 +xrdp 0.7.0 Credits - This project is very much dependent on rdesktop and the work of Matt Chapman - and the rdesktop team members, of which I'm a member + This project is very much dependent on FreeRDP(was rdesktop), the work of + Matt Chapman and the FreeRDP team members, of which I'm a member. Mark from up 19.9 was the first to work with rdp server code. diff --git a/sesman/access.c b/sesman/access.c index f4bfd30a..0037de3f 100644 --- a/sesman/access.c +++ b/sesman/access.c @@ -38,33 +38,33 @@ access_login_allowed(char* user) if ((0 == g_strncmp(user, "root", 5)) && (0 == g_cfg->sec.allow_root)) { - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, + log_message(LOG_LEVEL_WARNING, "ROOT login attempted, but root login is disabled"); return 0; } if (0 == g_cfg->sec.ts_users_enable) { - LOG_DBG(&(g_cfg->log), "Terminal Server Users group is disabled, allowing authentication", + LOG_DBG("Terminal Server Users group is disabled, allowing authentication", 1); return 1; } if (0 != g_getuser_info(user, &gid, 0, 0, 0, 0)) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "Cannot read user info! - login denied"); + log_message(LOG_LEVEL_ERROR, "Cannot read user info! - login denied"); return 0; } if (g_cfg->sec.ts_users == gid) { - LOG_DBG(&(g_cfg->log), "ts_users is user's primary group"); + LOG_DBG("ts_users is user's primary group"); return 1; } if (0 != g_check_user_in_group(user, g_cfg->sec.ts_users, &ok)) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "Cannot read group info! - login denied"); + log_message(LOG_LEVEL_ERROR, "Cannot read group info! - login denied"); return 0; } @@ -73,7 +73,7 @@ access_login_allowed(char* user) return 1; } - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "login denied for user %s", user); + log_message(LOG_LEVEL_INFO, "login denied for user %s", user); return 0; } @@ -87,33 +87,33 @@ access_login_mng_allowed(char* user) if ((0 == g_strncmp(user, "root", 5)) && (0 == g_cfg->sec.allow_root)) { - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, + log_message(LOG_LEVEL_WARNING, "[MNG] ROOT login attempted, but root login is disabled"); return 0; } if (0 == g_cfg->sec.ts_admins_enable) { - LOG_DBG(&(g_cfg->log), "[MNG] Terminal Server Admin group is disabled, allowing authentication", - 1); + LOG_DBG("[MNG] Terminal Server Admin group is disabled," + "allowing authentication",1); return 1; } if (0 != g_getuser_info(user, &gid, 0, 0, 0, 0)) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "[MNG] Cannot read user info! - login denied"); + log_message(LOG_LEVEL_ERROR, "[MNG] Cannot read user info! - login denied"); return 0; } if (g_cfg->sec.ts_admins == gid) { - LOG_DBG(&(g_cfg->log), "[MNG] ts_users is user's primary group"); + LOG_DBG("[MNG] ts_users is user's primary group"); return 1; } if (0 != g_check_user_in_group(user, g_cfg->sec.ts_admins, &ok)) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "[MNG] Cannot read group info! - login denied"); + log_message(LOG_LEVEL_ERROR, "[MNG] Cannot read group info! - login denied"); return 0; } @@ -122,7 +122,7 @@ access_login_mng_allowed(char* user) return 1; } - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "[MNG] login denied for user %s", user); + log_message(LOG_LEVEL_INFO, "[MNG] login denied for user %s", user); return 0; } diff --git a/sesman/chansrv/Makefile.am b/sesman/chansrv/Makefile.am index 486d49a8..9d52d950 100644 --- a/sesman/chansrv/Makefile.am +++ b/sesman/chansrv/Makefile.am @@ -1,10 +1,21 @@ EXTRA_DIST = chansrv.h clipboard.h devredir.h sound.h +EXTRA_DEFINES = +EXTRA_INCLUDES = +EXTRA_LIBS = +EXTRA_FLAGS = + +if XRDP_SIMPLESOUND +EXTRA_DEFINES += -DXRDP_SIMPLESOUND +EXTRA_LIBS += -lpthread -lpulse -lpulse-simple +endif + AM_CFLAGS = \ -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \ -DXRDP_SBIN_PATH=\"${sbindir}\" \ -DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \ - -DXRDP_PID_PATH=\"${localstatedir}/run\" + -DXRDP_PID_PATH=\"${localstatedir}/run\" \ + $(EXTRA_DEFINES) INCLUDES = \ -I$(top_srcdir)/common \ @@ -17,7 +28,12 @@ xrdp_chansrv_SOURCES = \ chansrv.c \ sound.c \ clipboard.c \ - devredir.c + devredir.c \ + rail.c \ + xcommon.c + +xrdp_chansrv_LDFLAGS = \ + $(EXTRA_FLAGS) xrdp_chansrv_LDADD = \ -L/usr/X11R6/lib \ diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index eb892100..c7917d03 100644 --- a/sesman/chansrv/chansrv.c +++ b/sesman/chansrv/chansrv.c @@ -1,21 +1,20 @@ -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - xrdp: A Remote Desktop Protocol server. - Copyright (C) Jay Sorg 2009-2010 -*/ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2009-2012 + * + * 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. + */ #include "arch.h" #include "os_calls.h" @@ -29,16 +28,22 @@ #include "list.h" #include "file.h" #include "file_loc.h" +#include "log.h" +#include "rail.h" +#include "xcommon.h" #include "libraptorsmiface.h" static struct trans* g_lis_trans = 0; static struct trans* g_con_trans = 0; +static struct trans* g_api_lis_trans = 0; +static struct trans* g_api_con_trans = 0; static struct chan_item g_chan_items[32]; static int g_num_chan_items = 0; static int g_cliprdr_index = -1; static int g_rdpsnd_index = -1; static int g_rdpdr_index = -1; +static int g_rail_index = -1; static tbus g_term_event = 0; static tbus g_thread_done_event = 0; @@ -49,6 +54,21 @@ int g_display_num = 0; int g_cliprdr_chan_id = -1; /* cliprdr */ int g_rdpsnd_chan_id = -1; /* rdpsnd */ int g_rdpdr_chan_id = -1; /* rdpdr */ +int g_rail_chan_id = -1; /* rail */ + +char* g_exec_name; +tbus g_exec_event; +tbus g_exec_mutex; +tbus g_exec_sem; +int g_exec_pid = 0; + +/* data in struct trans::callback_data */ +struct xrdp_api_data +{ + int chan_id; + char header[64]; + int flags; +}; //#if 0 #include <stdio.h> @@ -77,55 +97,132 @@ void dprint(const char *fmt, ...) //#endif /*****************************************************************************/ +/* add data to chan_item, on its way to the client */ /* returns error */ -int APP_CC -send_channel_data(int chan_id, char* data, int size) +static int APP_CC +add_data_to_chan_item(struct chan_item* chan_item, char* data, int size) { - struct stream * s = (struct stream *)NULL; - int chan_flags = 0; - int total_size = 0; - int sent = 0; - int rv = 0; + struct stream* s; + struct chan_out_data* cod; + make_stream(s); + init_stream(s, size); + g_memcpy(s->data, data, size); + s->end = s->data + size; + cod = (struct chan_out_data*)g_malloc(sizeof(struct chan_out_data), 1); + cod->s = s; + if (chan_item->tail == 0) + { + chan_item->tail = cod; + chan_item->head = cod; + } + else + { + chan_item->tail->next = cod; + chan_item->tail = cod; + } + return 0; +} + +/*****************************************************************************/ +/* returns error */ +static int APP_CC +send_data_from_chan_item(struct chan_item* chan_item) +{ + struct stream* s; + struct chan_out_data* cod; + int bytes_left; + int size; + int chan_flags; + int error; + + if (chan_item->head == 0) + { + return 0; + } + cod = chan_item->head; + bytes_left = (int)(cod->s->end - cod->s->p); + size = MIN(1600, bytes_left); + chan_flags = 0; + if (cod->s->p == cod->s->data) + { + chan_flags |= 1; /* first */ + } + if (cod->s->p + size >= cod->s->end) + { + chan_flags |= 2; /* last */ + } s = trans_get_out_s(g_con_trans, 8192); - if (s == 0) + out_uint32_le(s, 0); /* version */ + out_uint32_le(s, 8 + 8 + 2 + 2 + 2 + 4 + size); /* size */ + out_uint32_le(s, 8); /* msg id */ + out_uint32_le(s, 8 + 2 + 2 + 2 + 4 + size); /* size */ + out_uint16_le(s, chan_item->id); + out_uint16_le(s, chan_flags); + out_uint16_le(s, size); + out_uint32_le(s, cod->s->size); + out_uint8a(s, cod->s->p, size); + s_mark_end(s); + LOGM((LOG_LEVEL_DEBUG, "chansrv::send_channel_data: -- " + "size %d chan_flags 0x%8.8x", size, chan_flags)); + error = trans_force_write(g_con_trans); + if (error != 0) { return 1; } - rv = 0; - sent = 0; - total_size = size; - while (sent < total_size) + cod->s->p += size; + if (cod->s->p >= cod->s->end) { - size = MIN(1600, total_size - sent); - chan_flags = 0; - if (sent == 0) + free_stream(cod->s); + chan_item->head = chan_item->head->next; + if (chan_item->head == 0) { - chan_flags |= 1; /* first */ + chan_item->tail = 0; } - if (size + sent == total_size) + g_free(cod); + } + return 0; +} + +/*****************************************************************************/ +/* returns error */ +static int APP_CC +check_chan_items(void) +{ + int index; + + for (index = 0; index < g_num_chan_items; index++) + { + if (g_chan_items[index].head != 0) { - chan_flags |= 2; /* last */ + send_data_from_chan_item(g_chan_items + index); } - out_uint32_le(s, 0); /* version */ - out_uint32_le(s, 8 + 8 + 2 + 2 + 2 + 4 + size); /* size */ - out_uint32_le(s, 8); /* msg id */ - out_uint32_le(s, 8 + 2 + 2 + 2 + 4 + size); /* size */ - out_uint16_le(s, chan_id); - out_uint16_le(s, chan_flags); - out_uint16_le(s, size); - out_uint32_le(s, total_size); - out_uint8a(s, data + sent, size); - s_mark_end(s); - rv = trans_force_write(g_con_trans); - if (rv != 0) + } + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int APP_CC +send_channel_data(int chan_id, char* data, int size) +{ + int index; + + LOGM((LOG_LEVEL_DEBUG, "chansrv::send_channel_data: size %d", size)); + if (chan_id == -1) + { + return 1; + } + for (index = 0; index < g_num_chan_items; index++) + { + if (g_chan_items[index].id == chan_id) { - break; + add_data_to_chan_item(g_chan_items + index, data, size); + check_chan_items(); + return 0; } - sent += size; - s = trans_get_out_s(g_con_trans, 8192); } - return rv; + return 1; } /*****************************************************************************/ @@ -135,7 +232,7 @@ send_init_response_message(void) { struct stream * s = (struct stream *)NULL; - LOG(1, ("send_init_response_message:")); + LOGM((LOG_LEVEL_INFO, "send_init_response_message:")); s = trans_get_out_s(g_con_trans, 8192); if (s == 0) { @@ -157,7 +254,7 @@ send_channel_setup_response_message(void) { struct stream * s = (struct stream *)NULL; - LOG(10, ("send_channel_setup_response_message:")); + LOGM((LOG_LEVEL_DEBUG, "send_channel_setup_response_message:")); s = trans_get_out_s(g_con_trans, 8192); if (s == 0) { @@ -178,7 +275,7 @@ send_channel_data_response_message(void) { struct stream * s = (struct stream *)NULL; - LOG(10, ("send_channel_data_response_message:")); + LOGM((LOG_LEVEL_DEBUG, "send_channel_data_response_message:")); s = trans_get_out_s(g_con_trans, 8192); if (s == 0) { @@ -197,7 +294,7 @@ send_channel_data_response_message(void) static int APP_CC process_message_init(struct stream* s) { - LOG(10, ("process_message_init:")); + LOGM((LOG_LEVEL_DEBUG, "process_message_init:")); return send_init_response_message(); } @@ -206,21 +303,24 @@ process_message_init(struct stream* s) static int APP_CC process_message_channel_setup(struct stream* s) { - int num_chans = 0; - int index = 0; - int rv = 0; - struct chan_item* ci = (struct chan_item *)NULL; + int num_chans; + int index; + int rv; + struct chan_item* ci; g_num_chan_items = 0; g_cliprdr_index = -1; g_rdpsnd_index = -1; g_rdpdr_index = -1; + g_rail_index = -1; g_cliprdr_chan_id = -1; g_rdpsnd_chan_id = -1; g_rdpdr_chan_id = -1; - LOG(10, ("process_message_channel_setup:")); + g_rail_chan_id = -1; + LOGM((LOG_LEVEL_DEBUG, "process_message_channel_setup:")); in_uint16_le(s, num_chans); - LOG(10, ("process_message_channel_setup: num_chans %d", num_chans)); + LOGM((LOG_LEVEL_DEBUG, "process_message_channel_setup: num_chans %d", + num_chans)); for (index = 0; index < num_chans; index++) { ci = &(g_chan_items[g_num_chan_items]); @@ -228,8 +328,8 @@ process_message_channel_setup(struct stream* s) in_uint8a(s, ci->name, 8); in_uint16_le(s, ci->id); in_uint16_le(s, ci->flags); - LOG(10, ("process_message_channel_setup: chan name '%s' " - "id %d flags %8.8x", ci->name, ci->id, ci->flags)); + LOGM((LOG_LEVEL_DEBUG, "process_message_channel_setup: chan name '%s' " + "id %d flags %8.8x", ci->name, ci->id, ci->flags)); if (g_strcasecmp(ci->name, "cliprdr") == 0) { g_cliprdr_index = g_num_chan_items; @@ -245,6 +345,15 @@ process_message_channel_setup(struct stream* s) g_rdpdr_index = g_num_chan_items; g_rdpdr_chan_id = ci->id; } + else if (g_strcasecmp(ci->name, "rail") == 0) + { + g_rail_index = g_num_chan_items; + g_rail_chan_id = ci->id; + } + else + { + LOG(10, ("other %s", ci->name)); + } g_num_chan_items++; } rv = send_channel_setup_response_message(); @@ -275,13 +384,15 @@ process_message_channel_data(struct stream* s) int rv = 0; int length = 0; int total_length = 0; + struct stream* ls; in_uint16_le(s, chan_id); in_uint16_le(s, chan_flags); in_uint16_le(s, length); in_uint32_le(s, total_length); - LOG(10, ("process_message_channel_data: chan_id %d " - "chan_flags %d", chan_id, chan_flags)); + LOGM((LOG_LEVEL_DEBUG,"process_message_channel_data: chan_id %d " + "chan_flags %d", chan_id, chan_flags)); + LOG(10, ("process_message_channel_data")); rv = send_channel_data_response_message(); if (rv == 0) { @@ -297,6 +408,27 @@ process_message_channel_data(struct stream* s) { rv = dev_redir_data_in(s, chan_id, chan_flags, length, total_length); } + else if (chan_id == g_rail_chan_id) + { + rv = rail_data_in(s, chan_id, chan_flags, length, total_length); + } + else if (chan_id == ((struct xrdp_api_data*) + (g_api_con_trans->callback_data))->chan_id) + { + LOG(10, ("process_message_channel_data length %d total_length %d " + "chan_flags 0x%8.8x", length, total_length, chan_flags)); + ls = g_api_con_trans->out_s; + if (chan_flags & 1) /* first */ + { + init_stream(ls, total_length); + } + out_uint8a(ls, s->p, length); + if (chan_flags & 2) /* last */ + { + s_mark_end(ls); + trans_force_write(g_api_con_trans); + } + } } return rv; } @@ -307,6 +439,7 @@ static int APP_CC process_message_channel_data_response(struct stream* s) { LOG(10, ("process_message_channel_data_response:")); + check_chan_items(); return 0; } @@ -352,8 +485,8 @@ process_message(void) rv = process_message_channel_data_response(s); break; default: - LOG(0, ("process_message: error in process_message " - "unknown msg %d", id)); + LOGM((LOG_LEVEL_ERROR, "process_message: error in process_message ", + "unknown msg %d", id)); break; } if (rv != 0) @@ -361,9 +494,7 @@ process_message(void) LOG(0, ("process_message: error in process_message: rv %d", rv)); break; } - else { - s->p = next_msg; - } + s->p = next_msg; } return rv; } @@ -386,7 +517,7 @@ my_trans_data_in(struct trans* trans) { return 1; } - LOG(10, ("my_trans_data_in:")); + LOGM((LOG_LEVEL_DEBUG, "my_trans_data_in:")); s = trans_get_in_s(trans); in_uint32_le(s, id); in_uint32_le(s, size); @@ -400,6 +531,44 @@ my_trans_data_in(struct trans* trans) } /*****************************************************************************/ +/* returns error */ +int DEFAULT_CC +my_api_trans_data_in(struct trans* trans) +{ + struct stream* s; + int error; + struct xrdp_api_data* ad; + + LOG(10, ("my_api_trans_data_in:")); + if (trans == 0) + { + return 0; + } + if (trans != g_api_con_trans) + { + return 1; + } + LOGM((LOG_LEVEL_DEBUG, "my_api_trans_data_in:")); + s = trans_get_in_s(trans); + error = g_tcp_recv(trans->sck, s->data, 8192, 0); + if (error > 0) + { + LOG(10, ("my_api_trans_data_in: got data %d", error)); + ad = (struct xrdp_api_data*)(trans->callback_data); + if (send_channel_data(ad->chan_id, s->data, error) != 0) + { + LOG(0, ("my_api_trans_data_in: send_channel_data failed")); + } + } + else + { + LOG(10, ("my_api_trans_data_in: g_tcp_recv failed, or disconnected")); + return 1; + } + return 0; +} + +/*****************************************************************************/ int DEFAULT_CC my_trans_conn_in(struct trans* trans, struct trans* new_trans) { @@ -419,7 +588,7 @@ my_trans_conn_in(struct trans* trans, struct trans* new_trans) { return 1; } - LOG(10, ("my_trans_conn_in:")); + LOGM((LOG_LEVEL_DEBUG, "my_trans_conn_in:")); g_con_trans = new_trans; g_con_trans->trans_data_in = my_trans_data_in; g_con_trans->header_size = 8; @@ -430,6 +599,84 @@ my_trans_conn_in(struct trans* trans, struct trans* new_trans) } /*****************************************************************************/ +int DEFAULT_CC +my_api_trans_conn_in(struct trans* trans, struct trans* new_trans) +{ + struct xrdp_api_data* ad; + int error; + int index; + int found; + struct stream* s; + + if (trans == 0) + { + return 1; + } + if (trans != g_api_lis_trans) + { + return 1; + } + if (new_trans == 0) + { + return 1; + } + LOGM((LOG_LEVEL_DEBUG, "my_api_trans_conn_in:")); + + LOG(10, ("my_api_trans_conn_in: got incoming")); + + s = trans_get_in_s(new_trans); + s->end = s->data; + error = trans_force_read(new_trans, 64); + if (error != 0) + { + LOG(0, ("my_api_trans_conn_in: trans_force_read failed")); + trans_delete(new_trans); + } + s->end = s->data; + + ad = (struct xrdp_api_data*)g_malloc(sizeof(struct xrdp_api_data), 1); + + g_memcpy(ad->header, s->data, 64); + + ad->flags = GGET_UINT32(ad->header, 16); + + found = 0; + if (ad->flags | 1) /* WTS_CHANNEL_OPTION_DYNAMIC */ + { + /* TODO */ + found = 0; + } + else + { + for (index = 0; index < g_num_chan_items; index++) + { + LOG(10, (" %s %s", ad->header, g_chan_items[index].name)); + if (g_strcasecmp(ad->header, g_chan_items[index].name) == 0) + { + LOG(10, ("my_api_trans_conn_in: found it at %d", index)); + ad->chan_id = g_chan_items[index].id; + found = 1; + break; + } + } + } + LOG(10, ("my_api_trans_conn_in: found %d", found)); + if (!found) + { + ad->chan_id = -1; + } + + new_trans->callback_data = ad; + + trans_delete(g_api_con_trans); + g_api_con_trans = new_trans; + g_api_con_trans->trans_data_in = my_api_trans_data_in; + g_api_con_trans->header_size = 0; + + return 0; +} + +/*****************************************************************************/ static int APP_CC setup_listen(void) { @@ -443,7 +690,8 @@ setup_listen(void) if (g_use_unix_socket) { g_lis_trans = trans_create(2, 8192, 8192); - g_snprintf(port, 255, "/tmp/.xrdp/xrdp_chansrv_socket_%d", 7200 + g_display_num); + g_snprintf(port, 255, "/tmp/.xrdp/xrdp_chansrv_socket_%d", + 7200 + g_display_num); } else { @@ -454,7 +702,28 @@ setup_listen(void) error = trans_listen(g_lis_trans, port); if (error != 0) { - LOG(0, ("setup_listen: trans_listen failed for port %s", port)); + LOGM((LOG_LEVEL_ERROR, "setup_listen: trans_listen failed for port %s", + port)); + return 1; + } + return 0; +} + +/*****************************************************************************/ +static int APP_CC +setup_api_listen(void) +{ + char port[256]; + int error = 0; + + g_api_lis_trans = trans_create(2, 8192, 8192); + g_snprintf(port, 255, "/tmp/.xrdp/xrdpapi_%d", g_display_num); + g_api_lis_trans->trans_conn_in = my_api_trans_conn_in; + error = trans_listen(g_api_lis_trans, port); + if (error != 0) + { + LOGM((LOG_LEVEL_ERROR, "setup_api_listen: trans_listen failed for port %s", + port)); return 1; } return 0; @@ -465,13 +734,14 @@ THREAD_RV THREAD_CC channel_thread_loop(void* in_val) { tbus objs[32]; - int num_objs = 0; - int timeout = 0; - int error = 0; - THREAD_RV rv = 0; + int num_objs; + int timeout; + int error; + THREAD_RV rv; - LOG(1, ("channel_thread_loop: thread start")); + LOGM((LOG_LEVEL_INFO, "channel_thread_loop: thread start")); rv = 0; + setup_api_listen(); error = setup_listen(); if (error == 0) { @@ -479,33 +749,37 @@ channel_thread_loop(void* in_val) num_objs = 0; objs[num_objs] = g_term_event; num_objs++; - trans_get_wait_objs(g_lis_trans, objs, &num_objs, &timeout); + trans_get_wait_objs(g_lis_trans, objs, &num_objs); + trans_get_wait_objs(g_api_lis_trans, objs, &num_objs); while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0) { if (g_is_wait_obj_set(g_term_event)) { - LOG(0, ("channel_thread_loop: g_term_event set")); + LOGM((LOG_LEVEL_INFO, "channel_thread_loop: g_term_event set")); clipboard_deinit(); sound_deinit(); dev_redir_deinit(); + rail_deinit(); break; } if (g_lis_trans != 0) { if (trans_check_wait_objs(g_lis_trans) != 0) { - LOG(0, ("channel_thread_loop: trans_check_wait_objs error")); + LOGM((LOG_LEVEL_INFO, "channel_thread_loop: " + "trans_check_wait_objs error")); } } if (g_con_trans != 0) { if (trans_check_wait_objs(g_con_trans) != 0) { - LOG(0, ("channel_thread_loop: " - "trans_check_wait_objs error resetting")); + LOGM((LOG_LEVEL_INFO, "channel_thread_loop: " + "trans_check_wait_objs error resetting")); clipboard_deinit(); sound_deinit(); dev_redir_deinit(); + rail_deinit(); /* delete g_con_trans */ trans_delete(g_con_trans); g_con_trans = 0; @@ -519,16 +793,40 @@ channel_thread_loop(void* in_val) } } } - clipboard_check_wait_objs(); + if (g_api_lis_trans != 0) + { + if (trans_check_wait_objs(g_api_lis_trans) != 0) + { + LOG(0, ("channel_thread_loop: trans_check_wait_objs failed")); + } + } + + LOG(10, ("0 %p", g_api_con_trans)); + if (g_api_con_trans != 0) + { + LOG(10, ("1 %p %d", g_api_con_trans, g_tcp_can_recv(g_api_con_trans->sck, 0))); + if (trans_check_wait_objs(g_api_con_trans) != 0) + { + LOG(10, ("channel_thread_loop: trans_check_wait_objs failed, " + "or disconnected")); + g_free(g_api_con_trans->callback_data); + trans_delete(g_api_con_trans); + g_api_con_trans = 0; + } + } + + xcommon_check_wait_objs(); sound_check_wait_objs(); dev_redir_check_wait_objs(); timeout = -1; num_objs = 0; objs[num_objs] = g_term_event; num_objs++; - trans_get_wait_objs(g_lis_trans, objs, &num_objs, &timeout); - trans_get_wait_objs(g_con_trans, objs, &num_objs, &timeout); - clipboard_get_wait_objs(objs, &num_objs, &timeout); + trans_get_wait_objs(g_lis_trans, objs, &num_objs); + trans_get_wait_objs(g_con_trans, objs, &num_objs); + trans_get_wait_objs(g_api_lis_trans, objs, &num_objs); + trans_get_wait_objs(g_api_con_trans, objs, &num_objs); + xcommon_get_wait_objs(objs, &num_objs, &timeout); sound_get_wait_objs(objs, &num_objs, &timeout); dev_redir_get_wait_objs(objs, &num_objs, &timeout); } @@ -537,7 +835,11 @@ channel_thread_loop(void* in_val) g_lis_trans = 0; trans_delete(g_con_trans); g_con_trans = 0; - LOG(0, ("channel_thread_loop: thread stop")); + trans_delete(g_api_lis_trans); + g_api_lis_trans = 0; + trans_delete(g_api_con_trans); + g_api_con_trans = 0; + LOGM((LOG_LEVEL_INFO, "channel_thread_loop: thread stop")); g_set_wait_obj(g_thread_done_event); return rv; } @@ -546,7 +848,7 @@ channel_thread_loop(void* in_val) void DEFAULT_CC term_signal_handler(int sig) { - LOG(1, ("term_signal_handler: got signal %d", sig)); + LOGM((LOG_LEVEL_INFO, "term_signal_handler: got signal %d", sig)); g_set_wait_obj(g_term_event); } @@ -554,26 +856,44 @@ term_signal_handler(int sig) void DEFAULT_CC nil_signal_handler(int sig) { - LOG(1, ("nil_signal_handler: got signal %d", sig)); - g_set_wait_obj(g_term_event); + LOGM((LOG_LEVEL_INFO, "nil_signal_handler: got signal %d", sig)); +} + +/*****************************************************************************/ +void DEFAULT_CC +child_signal_handler(int sig) +{ + int i1; + + LOG(10, ("child_signal_handler:")); + do + { + i1 = g_waitchild(); + if (i1 == g_exec_pid) + { + LOG(0, ("child_signal_handler: found pid %d", i1)); + //shutdownx(); + } + LOG(10, (" %d", i1)); + } while (i1 >= 0); } /*****************************************************************************/ static int APP_CC -get_display_num_from_display(char * display_text) +get_display_num_from_display(char* display_text) { - int index = 0; - int mode = 0; - int host_index = 0; - int disp_index = 0; - int scre_index = 0; - char host[256] = ""; - char disp[256] = ""; - char scre[256] = ""; - - g_memset(host,0,256); - g_memset(disp,0,256); - g_memset(scre,0,256); + int index; + int mode; + int host_index; + int disp_index; + int scre_index; + char host[256]; + char disp[256]; + char scre[256]; + + g_memset(host, 0, 256); + g_memset(disp, 0, 256); + g_memset(scre, 0, 256); index = 0; host_index = 0; @@ -620,6 +940,8 @@ main_cleanup(void) { g_delete_wait_obj(g_term_event); g_delete_wait_obj(g_thread_done_event); + g_delete_wait_obj(g_exec_event); + tc_mutex_delete(g_exec_mutex); g_deinit(); /* os_calls */ return 0; } @@ -628,15 +950,14 @@ main_cleanup(void) static int APP_CC read_ini(void) { - char filename[256] = ""; - struct list* names = (struct list *)NULL; - struct list* values = (struct list *)NULL; - char* name = (char *)NULL; - char* value = (char *)NULL; - int index = 0; - - g_memset(filename,0,(sizeof(char)*256)); + char filename[256]; + struct list* names; + struct list* values; + char* name; + char* value; + int index; + g_memset(filename,0,(sizeof(char) * 256)); names = list_create(); names->auto_free = 1; values = list_create(); @@ -666,51 +987,140 @@ read_ini(void) } /*****************************************************************************/ +static int APP_CC +run_exec(void) +{ + int pid; + + LOG(10, ("run_exec:")); + pid = g_fork(); + if (pid == 0) + { + trans_delete(g_con_trans); + g_close_wait_obj(g_term_event); + g_close_wait_obj(g_thread_done_event); + g_close_wait_obj(g_exec_event); + tc_mutex_delete(g_exec_mutex); + tc_sem_delete(g_exec_sem); + g_execlp3(g_exec_name, g_exec_name, 0); + g_exit(0); + } + g_exec_pid = pid; + tc_sem_inc(g_exec_sem); + + return 0; +} + +/*****************************************************************************/ int DEFAULT_CC main(int argc, char** argv) { + tbus waiters[4]; int pid = 0; - char text[256] = ""; - char* display_text = (char *)NULL; + char text[256]; + char* home_text; + char* display_text; + char log_file[256]; + enum logReturns error; + struct log_config logconfig; g_init("xrdp-chansrv"); /* os_calls */ + + home_text = g_getenv("HOME"); + if (home_text == 0) + { + g_writeln("error reading HOME environment variable"); + g_deinit(); + return 1; + } + read_ini(); pid = g_getpid(); - LOG(1, ("main: app started pid %d(0x%8.8x)", pid, pid)); + /* starting logging subsystem */ + g_memset(&logconfig, 0, sizeof(struct log_config)); + logconfig.program_name = "XRDP-Chansrv"; + g_snprintf(log_file, 255, "%s/xrdp-chansrv.log", home_text); + g_writeln("chansrv::main: using log file [%s]", log_file); + if (g_file_exist(log_file)) + { + g_file_delete(log_file); + } + logconfig.log_file = log_file; + logconfig.fd = -1; + logconfig.log_level = LOG_LEVEL_ERROR; + logconfig.enable_syslog = 0; + logconfig.syslog_level = 0; + error = log_start_from_param(&logconfig); + if (error != LOG_STARTUP_OK) + { + switch (error) + { + case LOG_ERROR_MALLOC: + g_writeln("error on malloc. cannot start logging. quitting."); + break; + case LOG_ERROR_FILE_OPEN: + g_writeln("error opening log file [%s]. quitting.", + getLogFile(text, 255)); + break; + default: + g_writeln("log_start error"); + break; + } + g_deinit(); + return 1; + } + LOGM((LOG_LEVEL_ALWAYS, "main: app started pid %d(0x%8.8x)", pid, pid)); /* set up signal handler */ g_signal_kill(term_signal_handler); /* SIGKILL */ g_signal_terminate(term_signal_handler); /* SIGTERM */ g_signal_user_interrupt(term_signal_handler); /* SIGINT */ g_signal_pipe(nil_signal_handler); /* SIGPIPE */ + g_signal_child_stop(child_signal_handler); /* SIGCHLD */ display_text = g_getenv("DISPLAY"); - LOG(1, ("main: DISPLAY env var set to %s", display_text)); + LOGM((LOG_LEVEL_INFO, "main: DISPLAY env var set to %s", display_text)); get_display_num_from_display(display_text); if (g_display_num == 0) { - LOG(0, ("main: error, display is zero")); + LOGM((LOG_LEVEL_ERROR, "main: error, display is zero")); + g_deinit(); return 1; } - LOG(1, ("main: using DISPLAY %d", g_display_num)); + LOGM((LOG_LEVEL_INFO, "main: using DISPLAY %d", g_display_num)); g_snprintf(text, 255, "xrdp_chansrv_%8.8x_main_term", pid); g_term_event = g_create_wait_obj(text); g_snprintf(text, 255, "xrdp_chansrv_%8.8x_thread_done", pid); g_thread_done_event = g_create_wait_obj(text); + g_snprintf(text, 255, "xrdp_chansrv_%8.8x_exec", pid); + g_exec_event = g_create_wait_obj(text); + g_exec_mutex = tc_mutex_create(); + g_exec_sem = tc_sem_create(0); tc_thread_create(channel_thread_loop, 0); while (g_term_event > 0 && !g_is_wait_obj_set(g_term_event)) { - if (g_obj_wait(&g_term_event, 1, 0, 0, 0) != 0) + waiters[0] = g_term_event; + waiters[1] = g_exec_event; + if (g_obj_wait(waiters, 2, 0, 0, 0) != 0) + { + LOGM((LOG_LEVEL_ERROR, "main: error, g_obj_wait failed")); + break; + } + if (g_is_wait_obj_set(g_term_event)) { - LOG(0, ("main: error, g_obj_wait failed")); break; } + if (g_is_wait_obj_set(g_exec_event)) + { + g_reset_wait_obj(g_exec_event); + run_exec(); + } } while (g_thread_done_event > 0 && !g_is_wait_obj_set(g_thread_done_event)) { /* wait for thread to exit */ if (g_obj_wait(&g_thread_done_event, 1, 0, 0, 0) != 0) { - LOG(0, ("main: error, g_obj_wait failed")); + LOGM((LOG_LEVEL_ERROR, "main: error, g_obj_wait failed")); break; } } @@ -718,7 +1128,7 @@ main(int argc, char** argv) raptor_sm_set_session_state(g_display_num, SM_STATUS_RUNNING); /* cleanup */ main_cleanup(); - LOG(1, ("main: app exiting pid %d(0x%8.8x)", pid, pid)); + LOGM((LOG_LEVEL_INFO, "main: app exiting pid %d(0x%8.8x)", pid, pid)); g_deinit(); return 0; } diff --git a/sesman/chansrv/chansrv.h b/sesman/chansrv/chansrv.h index b265458f..ba593461 100644 --- a/sesman/chansrv/chansrv.h +++ b/sesman/chansrv/chansrv.h @@ -1,15 +1,41 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2009-2012 + * + * 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. + */ #if !defined(CHANSRV_H) #define CHANSRV_H #include "arch.h" #include "parse.h" +#include "log.h" + +struct chan_out_data +{ + struct stream* s; + struct chan_out_data* next; +}; struct chan_item { int id; int flags; char name[16]; + struct chan_out_data* head; + struct chan_out_data* tail; }; int APP_CC @@ -28,4 +54,25 @@ main_cleanup(void); } \ } +#define LOGM(_args) do { log_message _args ; } while (0) + +#ifndef GSET_UINT8 +#define GSET_UINT8(_ptr, _offset, _data) \ + *((unsigned char*) (((unsigned char*)(_ptr)) + (_offset))) = (unsigned char)(_data) +#define GGET_UINT8(_ptr, _offset) \ + (*((unsigned char*) (((unsigned char*)(_ptr)) + (_offset)))) +#define GSET_UINT16(_ptr, _offset, _data) \ + GSET_UINT8(_ptr, _offset, _data); \ + GSET_UINT8(_ptr, (_offset) + 1, (_data) >> 8) +#define GGET_UINT16(_ptr, _offset) \ + (GGET_UINT8(_ptr, _offset)) | \ + ((GGET_UINT8(_ptr, (_offset) + 1)) << 8) +#define GSET_UINT32(_ptr, _offset, _data) \ + GSET_UINT16(_ptr, _offset, _data); \ + GSET_UINT16(_ptr, (_offset) + 2, (_data) >> 16) +#define GGET_UINT32(_ptr, _offset) \ + (GGET_UINT16(_ptr, _offset)) | \ + ((GGET_UINT16(_ptr, (_offset) + 2)) << 16) +#endif + #endif diff --git a/sesman/chansrv/clipboard.c b/sesman/chansrv/clipboard.c index cf601a8e..3bea9704 100644 --- a/sesman/chansrv/clipboard.c +++ b/sesman/chansrv/clipboard.c @@ -1,25 +1,30 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2009-2012 + * Copyright (C) Laxmikant Rashinkar 2012 + * + * 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. + */ /* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - xrdp: A Remote Desktop Protocol server. - Copyright (C) Jay Sorg 2009-2010 - for help see http://tronche.com/gui/x/icccm/sec-2.html#s-2 .../kde/kdebase/workspace/klipper/clipboardpoll.cpp + Revision: + Aug 05, 2012: + Laxmikant Rashinkar (LK dot Rashinkar at gmail.com) + added clipboard support for BMP images */ #include <X11/Xlib.h> @@ -29,6 +34,29 @@ #include "parse.h" #include "os_calls.h" #include "chansrv.h" +#include "clipboard.h" +#include "xcommon.h" + +static char g_bmp_image_header[] = +{ + /* this is known to work */ + //0x42, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + + /* THIS IS BEING SENT BY WIN2008 */ + 0x42, 0x4d, 0x16, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00 +}; + +extern int g_cliprdr_chan_id; /* in chansrv.c */ + +extern Display* g_display; /* in xcommon.c */ +extern int g_x_socket; /* in xcommon.c */ +extern tbus g_x_wait_obj; /* in xcommon.c */ +extern Screen* g_screen; /* in xcommon.c */ +extern int g_screen_num; /* in xcommon.c */ + +int g_clip_up = 0; +int g_waiting_for_data_response = 0; +int g_waiting_for_data_response_time = 0; static Atom g_clipboard_atom = 0; static Atom g_clip_property_atom = 0; @@ -39,12 +67,9 @@ static Atom g_primary_atom = 0; static Atom g_secondary_atom = 0; static Atom g_get_time_atom = 0; static Atom g_utf8_atom = 0; -static int g_x_socket = 0; -static tbus g_x_wait_obj = 0; -static int g_clip_up = 0; +static Atom g_image_bmp_atom = 0; + static Window g_wnd = 0; -static Screen* g_screen = 0; -static int g_screen_num = 0; static int g_xfixes_event_base = 0; static int g_last_clip_size = 0; @@ -64,35 +89,20 @@ static int g_data_in_size = 0; static int g_data_in_time = 0; static int g_data_in_up_to_date = 0; static int g_got_format_announce = 0; -static int g_waiting_for_data_response = 0; -static int g_waiting_for_data_response_time = 0; -static Display* g_display = 0; +/* for image data */ +static int g_want_image_data = 0; +static XSelectionRequestEvent g_saved_selection_req_event; -extern int g_cliprdr_chan_id; /* in chansrv.c */ +/* for clipboard INCR transfers */ +static Atom g_incr_atom; +static Atom g_incr_atom_type; +static Atom g_incr_atom_target; +static char* g_incr_data = 0; +static int g_incr_data_size = 0; +static int g_incr_in_progress = 0; -/*****************************************************************************/ -int DEFAULT_CC -clipboard_error_handler(Display* dis, XErrorEvent* xer) -{ - char text[256]; - - XGetErrorText(dis, xer->error_code, text, 255); - LOG(1, ("error [%s]", text)); - return 0; -} - -/*****************************************************************************/ -/* The X server had an internal error. This is the last function called. - Do any cleanup that needs to be done on exit, like removing temporary files. - Don't worry about memory leaks */ -int DEFAULT_CC -clipboard_fatal_handler(Display* dis) -{ - LOG(1, ("fatal error, exiting")); - main_cleanup(); - return 0; -} +static int clipboard_format_id = CB_FORMAT_UNICODETEXT; /*****************************************************************************/ /* this is one way to get the current time from the x server */ @@ -100,10 +110,12 @@ static Time APP_CC clipboard_get_server_time(void) { XEvent xevent; + unsigned char no_text[4]; /* append nothing */ + no_text[0] = 0; XChangeProperty(g_display, g_wnd, g_get_time_atom, XA_STRING, 8, - PropModeAppend, "", 0); + PropModeAppend, no_text, 0); /* wait for PropertyNotify */ do { @@ -137,39 +149,20 @@ clipboard_init(void) int ver_min; Status st; - LOG(5, ("xrdp-chansrv: in clipboard_init")); + LOGM((LOG_LEVEL_DEBUG, "xrdp-chansrv: in clipboard_init")); if (g_clip_up) { return 0; } + xcommon_init(); clipboard_deinit(); rv = 0; - /* setting the error handlers can cause problem when shutting down - chansrv on some xlibs */ - //XSetErrorHandler(clipboard_error_handler); - //XSetIOErrorHandler(clipboard_fatal_handler); - g_display = XOpenDisplay(0); - if (g_display == 0) - { - LOG(0, ("clipboard_init: XOpenDisplay failed")); - rv = 1; - } - if (rv == 0) - { - g_x_socket = XConnectionNumber(g_display); - if (g_x_socket == 0) - { - LOG(0, ("clipboard_init: XConnectionNumber failed")); - rv = 2; - } - g_x_wait_obj = g_create_wait_obj_from_socket(g_x_socket, 0); - } if (rv == 0) { g_clipboard_atom = XInternAtom(g_display, "CLIPBOARD", False); if (g_clipboard_atom == None) { - LOG(0, ("clipboard_init: XInternAtom failed")); + LOGM((LOG_LEVEL_ERROR, "clipboard_init: XInternAtom failed")); rv = 3; } } @@ -177,17 +170,17 @@ clipboard_init(void) { if (!XFixesQueryExtension(g_display, &g_xfixes_event_base, &dummy)) { - LOG(0, ("clipboard_init: no xfixes")); + LOGM((LOG_LEVEL_ERROR, "clipboard_init: no xfixes")); rv = 5; } } if (rv == 0) { - LOG(0, ("clipboard_init: g_xfixes_event_base %d", g_xfixes_event_base)); + LOGM((LOG_LEVEL_DEBUG, "clipboard_init: g_xfixes_event_base %d", + g_xfixes_event_base)); st = XFixesQueryVersion(g_display, &ver_maj, &ver_min); - LOG(0, ("clipboard_init st %d, maj %d min %d", st, ver_maj, ver_min)); - g_screen_num = DefaultScreen(g_display); - g_screen = ScreenOfDisplay(g_display, g_screen_num); + LOGM((LOG_LEVEL_DEBUG, "clipboard_init st %d, maj %d min %d", st, + ver_maj, ver_min)); g_clip_property_atom = XInternAtom(g_display, "XRDP_CLIP_PROPERTY_ATOM", False); g_get_time_atom = XInternAtom(g_display, "XRDP_GET_TIME_ATOM", @@ -198,6 +191,15 @@ clipboard_init(void) g_primary_atom = XInternAtom(g_display, "PRIMARY", False); g_secondary_atom = XInternAtom(g_display, "SECONDARY", False); g_utf8_atom = XInternAtom(g_display, "UTF8_STRING", False); + + g_image_bmp_atom = XInternAtom(g_display, "image/bmp", False); + g_incr_atom = XInternAtom(g_display, "INCR", False); + if (g_image_bmp_atom == None) + { + LOGM((LOG_LEVEL_ERROR, "clipboard_init: g_image_bmp_atom was " + "not allocated")); + } + g_wnd = XCreateSimpleWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, 4, 4, 0, 0, 0); input_mask = StructureNotifyMask | PropertyChangeMask; @@ -219,13 +221,13 @@ clipboard_init(void) out_uint32_le(s, 0); /* extra 4 bytes ? */ s_mark_end(s); size = (int)(s->end - s->data); - LOG(5, ("clipboard_init: data out, sending " - "CLIPRDR_CONNECT (clip_msg_id = 1)")); + LOGM((LOG_LEVEL_DEBUG, "clipboard_init: data out, sending " + "CLIPRDR_CONNECT (clip_msg_id = 1)")); rv = send_channel_data(g_cliprdr_chan_id, s->data, size); if (rv != 0) { - LOG(0, ("clipboard_init: send_channel_data failed " - "rv = %d", rv)); + LOGM((LOG_LEVEL_ERROR, "clipboard_init: send_channel_data failed " + "rv = %d", rv)); rv = 4; } free_stream(s); @@ -238,7 +240,7 @@ clipboard_init(void) } else { - LOG(0, ("xrdp-chansrv: clipboard_init: error on exit")); + LOGM((LOG_LEVEL_ERROR, "xrdp-chansrv: clipboard_init: error on exit")); } return rv; } @@ -247,27 +249,16 @@ clipboard_init(void) int APP_CC clipboard_deinit(void) { - if (g_x_wait_obj != 0) - { - g_delete_wait_obj_from_socket(g_x_wait_obj); - g_x_wait_obj = 0; - } if (g_wnd != 0) { XDestroyWindow(g_display, g_wnd); g_wnd = 0; } - g_x_socket = 0; g_free(g_last_clip_data); g_last_clip_data = 0; g_last_clip_size = 0; free_stream(g_ins); g_ins = 0; - if (g_display != 0) - { - XCloseDisplay(g_display); - g_display = 0; - } g_clip_up = 0; return 0; } @@ -279,12 +270,12 @@ clipboard_send_data_request(void) struct stream* s; int size; int rv; - int num_chars; - LOG(5, ("clipboard_send_data_request:")); + LOGM((LOG_LEVEL_DEBUG, "clipboard_send_data_request:")); if (!g_got_format_announce) { - LOG(0, ("clipboard_send_data_request: error, no format announce")); + LOGM((LOG_LEVEL_ERROR, "clipboard_send_data_request: error, " + "no format announce")); return 0; } g_got_format_announce = 0; @@ -293,11 +284,11 @@ clipboard_send_data_request(void) out_uint16_le(s, 4); /* CLIPRDR_DATA_REQUEST */ out_uint16_le(s, 0); /* status */ out_uint32_le(s, 4); /* length */ - out_uint32_le(s, 0x0d); + out_uint32_le(s, clipboard_format_id); s_mark_end(s); size = (int)(s->end - s->data); - LOG(5, ("clipboard_send_data_request: data out, sending " - "CLIPRDR_DATA_REQUEST (clip_msg_id = 4)")); + LOGM((LOG_LEVEL_DEBUG,"clipboard_send_data_request: data out, sending " + "CLIPRDR_DATA_REQUEST (clip_msg_id = 4)")); rv = send_channel_data(g_cliprdr_chan_id, s->data, size); free_stream(s); return rv; @@ -319,16 +310,24 @@ clipboard_send_format_ack(void) out_uint32_le(s, 0); /* extra 4 bytes ? */ s_mark_end(s); size = (int)(s->end - s->data); - LOG(5, ("clipboard_send_format_ack: data out, sending " - "CLIPRDR_FORMAT_ACK (clip_msg_id = 3)")); + LOGM((LOG_LEVEL_DEBUG,"clipboard_send_format_ack: data out, sending " + "CLIPRDR_FORMAT_ACK (clip_msg_id = 3)")); rv = send_channel_data(g_cliprdr_chan_id, s->data, size); free_stream(s); return rv; } +static char windows_native_format[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + /*****************************************************************************/ static int APP_CC -clipboard_send_format_announce(void) +clipboard_send_format_announce(tui32 format_id, char* format_name) { struct stream* s; int size; @@ -338,13 +337,13 @@ clipboard_send_format_announce(void) init_stream(s, 8192); out_uint16_le(s, 2); /* CLIPRDR_FORMAT_ANNOUNCE */ out_uint16_le(s, 0); /* status */ - out_uint32_le(s, 0x90); /* length */ - out_uint32_le(s, 0x0d); /* extra 4 bytes ? */ - out_uint8s(s, 0x90); + out_uint32_le(s, 4 + sizeof(windows_native_format)); /* length */ + out_uint32_le(s, format_id); + out_uint8p(s, windows_native_format, sizeof(windows_native_format)); s_mark_end(s); size = (int)(s->end - s->data); - LOG(5, ("clipboard_send_format_announce: data out, sending " - "CLIPRDR_FORMAT_ANNOUNCE (clip_msg_id = 2)")); + LOGM((LOG_LEVEL_DEBUG,"clipboard_send_format_announce: data out, sending " + "CLIPRDR_FORMAT_ANNOUNCE (clip_msg_id = 2)")); rv = send_channel_data(g_cliprdr_chan_id, s->data, size); free_stream(s); return rv; @@ -382,6 +381,39 @@ clipboard_out_unicode(struct stream* s, char* text, int num_chars) /*****************************************************************************/ static int APP_CC +clipboard_send_data_response_for_image(void) +{ + struct stream* s; + int size; + int rv; + + LOG(10, ("clipboard_send_data_response_for_image: g_last_clip_size %d\n", + g_last_clip_size)); + make_stream(s); + init_stream(s, 64 + g_last_clip_size); + out_uint16_le(s, 5); /* CLIPRDR_DATA_RESPONSE */ + out_uint16_le(s, 1); /* status */ + out_uint32_le(s, g_last_clip_size); /* length */ + /* insert image data */ + if (g_last_clip_type == g_image_bmp_atom) + { + /* do not insert first header */ + out_uint8p(s, g_last_clip_data + 14, g_last_clip_size - 14); + } + out_uint16_le(s, 0); /* nil for string */ + out_uint32_le(s, 0); + out_uint32_le(s, 0); + out_uint32_le(s, 0); + s_mark_end(s); + size = (int)(s->end - s->data); + /* HANGING HERE WHEN IMAGE DATA IS TOO BIG!!!! */ + rv = send_channel_data(g_cliprdr_chan_id, s->data, size); + free_stream(s); + return rv; +} + +/*****************************************************************************/ +static int APP_CC clipboard_send_data_response(void) { struct stream* s; @@ -393,12 +425,16 @@ clipboard_send_data_response(void) num_chars = 0; if (g_last_clip_data != 0) { + if (g_last_clip_type == g_image_bmp_atom) + { + return clipboard_send_data_response_for_image(); + } if ((g_last_clip_type == XA_STRING) || (g_last_clip_type == g_utf8_atom)) { num_chars = g_mbstowcs(0, g_last_clip_data, 0); if (num_chars < 0) { - LOG(0, ("clipboard_send_data_response: bad string")); + LOGM((LOG_LEVEL_ERROR, "clipboard_send_data_response: bad string")); num_chars = 0; } } @@ -412,16 +448,16 @@ clipboard_send_data_response(void) out_uint32_le(s, num_chars * 2 + 2); /* length */ if (clipboard_out_unicode(s, g_last_clip_data, num_chars) != num_chars * 2) { - LOG(0, ("clipboard_send_data_response: error " - "clipboard_out_unicode didn't write right number of bytes")); + LOGM((LOG_LEVEL_ERROR,"clipboard_send_data_response: error " + "clipboard_out_unicode didn't write right number of bytes")); } out_uint16_le(s, 0); /* nil for string */ out_uint32_le(s, 0); s_mark_end(s); size = (int)(s->end - s->data); - LOG(5, ("clipboard_send_data_response: data out, sending " - "CLIPRDR_DATA_RESPONSE (clip_msg_id = 5) size %d num_chars %d", - size, num_chars)); + LOGM((LOG_LEVEL_DEBUG,"clipboard_send_data_response: data out, sending " + "CLIPRDR_DATA_RESPONSE (clip_msg_id = 5) size %d num_chars %d", + size, num_chars)); rv = send_channel_data(g_cliprdr_chan_id, s->data, size); free_stream(s); return rv; @@ -487,60 +523,134 @@ clipboard_refuse_selection(XSelectionRequestEvent* req) } /*****************************************************************************/ +/* sent by client or server when its local system clipboard is + updated with new clipboard data; contains Clipboard Format ID + and name pairs of new Clipboard Formats on the clipboard. */ static int APP_CC clipboard_process_format_announce(struct stream* s, int clip_msg_status, int clip_msg_len) { - Window owner; - - LOG(5, ("clipboard_process_format_announce: CLIPRDR_FORMAT_ANNOUNCE")); + LOGM((LOG_LEVEL_DEBUG, "clipboard_process_format_announce: " + "CLIPRDR_FORMAT_ANNOUNCE")); //g_hexdump(s->p, s->end - s->p); clipboard_send_format_ack(); g_got_format_announce = 1; g_data_in_up_to_date = 0; if (clipboard_set_selection_owner() != 0) { - LOG(0, ("clipboard_process_format_announce: XSetSelectionOwner failed")); + LOGM((LOG_LEVEL_ERROR, "clipboard_process_format_announce: " + "XSetSelectionOwner failed")); } return 0; } /*****************************************************************************/ +/* response to CB_FORMAT_LIST; used to indicate whether + processing of the Format List PDU was successful */ static int APP_CC clipboard_prcoess_format_ack(struct stream* s, int clip_msg_status, int clip_msg_len) { - LOG(5, ("clipboard_prcoess_format_ack: CLIPRDR_FORMAT_ACK")); + LOGM((LOG_LEVEL_DEBUG,"clipboard_prcoess_format_ack: CLIPRDR_FORMAT_ACK")); //g_hexdump(s->p, s->end - s->p); return 0; } /*****************************************************************************/ +/* sent by recipient of CB_FORMAT_LIST; used to request data for one + of the formats that was listed in CB_FORMAT_LIST */ static int APP_CC clipboard_process_data_request(struct stream* s, int clip_msg_status, int clip_msg_len) { - LOG(5, ("clipboard_process_data_request: CLIPRDR_DATA_REQUEST")); + LOGM((LOG_LEVEL_DEBUG,"clipboard_process_data_request: " + "CLIPRDR_DATA_REQUEST")); //g_hexdump(s->p, s->end - s->p); clipboard_send_data_response(); return 0; } /*****************************************************************************/ +/* sent as a reply to CB_FORMAT_DATA_REQUEST; used to indicate whether + processing of the CB_FORMAT_DATA_REQUEST was successful; if processing + was successful, CB_FORMAT_DATA_RESPONSE includes contents of requested + clipboard data. */ +static int APP_CC +clipboard_process_data_response_for_image(struct stream * s, + int clip_msg_status, + int clip_msg_len) +{ + XSelectionRequestEvent* lxev = &g_saved_selection_req_event; + char* cptr; + char cdata; + int len; + int index; + + LOGM((LOG_LEVEL_DEBUG, "clipboard_process_data_response_for_image: " + "CLIPRDR_DATA_RESPONSE_FOR_IMAGE")); + g_waiting_for_data_response = 0; + len = (int)(s->end - s->p); + if (len < 1) + { + return 0; + } + if (g_last_clip_type == g_image_bmp_atom) + { + /* space for inserting bmp image header */ + len += 14; + cptr = (char*)g_malloc(len, 0); + if (cptr == 0) + { + return 0; + } + g_memcpy(cptr, g_bmp_image_header, 14); + index = 14; + } + else + { + return 0; + } + while (s_check(s)) + { + in_uint8(s, cdata); + cptr[index++] = cdata; + } + if (len >= 0) + { + g_data_in = cptr; + g_data_in_size = len; + g_data_in_time = clipboard_get_local_time(); + g_data_in_up_to_date = 1; + } + clipboard_provide_selection(lxev, lxev->target, 8, cptr, len); + return 0; +} + +/*****************************************************************************/ +/* sent as a reply to CB_FORMAT_DATA_REQUEST; used to indicate whether + processing of the CB_FORMAT_DATA_REQUEST was successful; if processing was + successful, CB_FORMAT_DATA_RESPONSE includes contents of requested + clipboard data. */ +/*****************************************************************************/ static int APP_CC clipboard_process_data_response(struct stream* s, int clip_msg_status, int clip_msg_len) { - XEvent xev; XSelectionRequestEvent* lxev; twchar* wtext; twchar wchr; int len; int index; - int wtext_size; int data_in_len; - LOG(5, ("clipboard_process_data_response: CLIPRDR_DATA_RESPONSE")); + if (g_want_image_data) + { + g_want_image_data = 0; + clipboard_process_data_response_for_image(s, clip_msg_status, clip_msg_len); + return 0; + } + LOGM((LOG_LEVEL_DEBUG,"clipboard_process_data_response: " + "CLIPRDR_DATA_RESPONSE")); g_waiting_for_data_response = 0; len = (int)(s->end - s->p); if (len < 1) @@ -580,7 +690,7 @@ clipboard_process_data_response(struct stream* s, int clip_msg_status, } g_data_in_size = len; g_wcstombs(g_data_in, wtext, len + 1); - g_data_in_time = clipboard_get_local_time(); + g_data_in_time = xcommon_get_local_time(); g_data_in_up_to_date = 1; } if (g_data_in != 0) @@ -591,8 +701,8 @@ clipboard_process_data_response(struct stream* s, int clip_msg_status, lxev = &(g_selection_request_event[index]); clipboard_provide_selection(lxev, lxev->target, 8, g_data_in, data_in_len); - LOG(5, ("clipboard_process_data_response: requestor %d data_in_len %d", - lxev->requestor, data_in_len)); + LOGM((LOG_LEVEL_DEBUG,"clipboard_process_data_response: requestor %d " + "data_in_len %d", lxev->requestor, data_in_len)); } } g_selection_request_event_count = 0; @@ -641,24 +751,37 @@ clipboard_data_in(struct stream* s, int chan_id, int chan_flags, int length, rv = 0; switch (clip_msg_id) { - case 2: /* CLIPRDR_FORMAT_ANNOUNCE */ + /* sent by client or server when its local system clipboard is */ + /* updated with new clipboard data; contains Clipboard Format ID */ + /* and name pairs of new Clipboard Formats on the clipboard. */ + case CB_FORMAT_LIST: /* CLIPRDR_FORMAT_ANNOUNCE */ rv = clipboard_process_format_announce(ls, clip_msg_status, clip_msg_len); break; - case 3: /* CLIPRDR_FORMAT_ACK */ + /* response to CB_FORMAT_LIST; used to indicate whether */ + /* processing of the Format List PDU was successful */ + case CB_FORMAT_LIST_RESPONSE: /* CLIPRDR_FORMAT_ACK */ rv = clipboard_prcoess_format_ack(ls, clip_msg_status, clip_msg_len); break; - case 4: /* CLIPRDR_DATA_REQUEST */ + /* sent by recipient of CB_FORMAT_LIST; used to request data for one */ + /* of the formats that was listed in CB_FORMAT_LIST */ + case CB_FORMAT_DATA_REQUEST: /* CLIPRDR_DATA_REQUEST */ rv = clipboard_process_data_request(ls, clip_msg_status, clip_msg_len); break; - case 5: /* CLIPRDR_DATA_RESPONSE */ + /* sent as a reply to CB_FORMAT_DATA_REQUEST; used to indicate */ + /* whether processing of the CB_FORMAT_DATA_REQUEST was */ + /* successful; if processing was successful, */ + /* CB_FORMAT_DATA_RESPONSE includes contents of requested */ + /* clipboard data. */ + case CB_FORMAT_DATA_RESPONSE: /* CLIPRDR_DATA_RESPONSE */ rv = clipboard_process_data_response(ls, clip_msg_status, clip_msg_len); break; default: - LOG(0, ("clipboard_data_in: unknown clip_msg_id %d", clip_msg_id)); + LOGM((LOG_LEVEL_ERROR, "clipboard_data_in: unknown clip_msg_id %d", + clip_msg_id)); break; } XFlush(g_display); @@ -668,7 +791,8 @@ clipboard_data_in(struct stream* s, int chan_id, int chan_flags, int length, /*****************************************************************************/ /* this happens when a new app copies something to the clipboard 'CLIPBOARD' Atom - typedef struct { + typedef struct + { int type; unsigned long serial; Bool send_event; @@ -679,20 +803,20 @@ clipboard_data_in(struct stream* s, int chan_id, int chan_flags, int length, Atom selection; Time timestamp; Time selection_timestamp; -} XFixesSelectionNotifyEvent; */ + } XFixesSelectionNotifyEvent; */ static int APP_CC clipboard_event_selection_owner_notify(XEvent* xevent) { XFixesSelectionNotifyEvent* lxevent; lxevent = (XFixesSelectionNotifyEvent*)xevent; - LOG(5, ("clipboard_event_selection_owner_notify: " - "window %d subtype %d owner %d g_wnd %d", - lxevent->window, lxevent->subtype, lxevent->owner, g_wnd)); + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_owner_notify: " + "window %d subtype %d owner %d g_wnd %d", + lxevent->window, lxevent->subtype, lxevent->owner, g_wnd)); if (lxevent->owner == g_wnd) { - LOG(5, ("clipboard_event_selection_owner_notify: skipping, " - "onwer == g_wnd")); + LOGM((LOG_LEVEL_DEBUG,"clipboard_event_selection_owner_notify: skipping, " + "onwer == g_wnd")); g_got_selection = 1; return 0; } @@ -721,12 +845,28 @@ clipboard_get_window_property(Window wnd, Atom prop, Atom* type, int* fmt, XGetWindowProperty(g_display, g_wnd, prop, 0, 0, 0, AnyPropertyType, <ype, &lfmt, &ln_items, &llen_after, &lxdata); - XFree(lxdata); + if (lxdata != 0) + { + XFree(lxdata); + } if (ltype == 0) { /* XGetWindowProperty failed */ return 1; } + + if (ltype == g_incr_atom) + { + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_property_notify: INCR start")); + g_incr_in_progress = 1; + g_incr_atom_type = prop; + g_incr_data_size = 0; + g_free(g_incr_data); + g_incr_data = 0; + XDeleteProperty(g_display, g_wnd, prop); + return 0; + } + if (llen_after < 1) { /* no data, ok */ @@ -740,20 +880,29 @@ clipboard_get_window_property(Window wnd, Atom prop, Atom* type, int* fmt, if (ltype == 0) { /* XGetWindowProperty failed */ - XFree(lxdata); + if (lxdata != 0) + { + XFree(lxdata); + } return 1; } lxdata_size = (lfmt / 8) * ln_items; if (lxdata_size < 1) { /* should not happen */ - XFree(lxdata); + if (lxdata != 0) + { + XFree(lxdata); + } return 2; } if (llen_after > 0) { /* should not happen */ - XFree(lxdata); + if (lxdata != 0) + { + XFree(lxdata); + } return 3; } if (xdata != 0) @@ -761,7 +910,10 @@ clipboard_get_window_property(Window wnd, Atom prop, Atom* type, int* fmt, *xdata = (char*)g_malloc(lxdata_size, 0); g_memcpy(*xdata, lxdata, lxdata_size); } - XFree(lxdata); + if (lxdata != 0) + { + XFree(lxdata); + } if (xdata_size != 0) { *xdata_size = lxdata_size; @@ -807,34 +959,50 @@ clipboard_event_selection_notify(XEvent* xevent) int index; int convert_to_string; int convert_to_utf8; + int convert_to_bmp_image; int send_format_announce; int atom; - int* atoms; + Atom* atoms; Atom type; + tui32 format_id; + char format_name[32]; - LOG(5, ("clipboard_event_selection_notify:")); + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_notify:")); + data_size = 0; + n_items = 0; + fmt = 0; convert_to_string = 0; convert_to_utf8 = 0; + convert_to_bmp_image = 0; send_format_announce = 0; + format_id = 0; rv = 0; data = 0; type = 0; lxevent = (XSelectionEvent*)xevent; + g_memset(format_name, 0, 32); if (lxevent->property == None) { - LOG(0, ("clipboard_event_selection_notify: clip could " - "not be converted")); + LOGM((LOG_LEVEL_ERROR, "clipboard_event_selection_notify: clip could " + "not be converted")); rv = 1; } if (rv == 0) { + /* we need this if the call below turns out to be a + clipboard INCR operation */ + if (!g_incr_in_progress) + { + g_incr_atom_target = lxevent->target; + } + rv = clipboard_get_window_property(lxevent->requestor, lxevent->property, &type, &fmt, &n_items, &data, &data_size); if (rv != 0) { - LOG(0, ("clipboard_event_selection_notify: " - "clipboard_get_window_property failed error %d", rv)); + LOGM((LOG_LEVEL_ERROR, "clipboard_event_selection_notify: " + "clipboard_get_window_property failed error %d", rv)); } XDeleteProperty(g_display, lxevent->requestor, lxevent->property); } @@ -844,14 +1012,15 @@ clipboard_event_selection_notify(XEvent* xevent) { if (lxevent->target == g_targets_atom) { + /* on a 64 bit machine, actual_format_return of 32 implies long */ if ((type == XA_ATOM) && (fmt == 32)) { - atoms = (int*)data; + atoms = (Atom*)data; for (index = 0; index < n_items; index++) { atom = atoms[index]; - LOG(5, ("clipboard_event_selection_notify: %d %s %d", atom, - XGetAtomName(g_display, atom), XA_STRING)); + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_notify: %d %s %d", + atom, XGetAtomName(g_display, atom), XA_STRING)); if (atom == g_utf8_atom) { convert_to_utf8 = 1; @@ -860,47 +1029,71 @@ clipboard_event_selection_notify(XEvent* xevent) { convert_to_string = 1; } + else if (atom == g_image_bmp_atom) + { + convert_to_bmp_image = 1; + } } } else { - LOG(0, ("clipboard_event_selection_notify: error, target is " - "'TARGETS' and type[%d] or fmt[%d] not right, should be " - "type[%d], fmt[%d]", type, fmt, XA_ATOM, 32)); + LOGM((LOG_LEVEL_ERROR, "clipboard_event_selection_notify: error, " + "target is 'TARGETS' and type[%d] or fmt[%d] not right, " + "should be type[%d], fmt[%d]", type, fmt, XA_ATOM, 32)); } } else if (lxevent->target == g_utf8_atom) { - LOG(5, ("clipboard_event_selection_notify: UTF8_STRING data_size %d", - data_size)); + LOGM((LOG_LEVEL_DEBUG,"clipboard_event_selection_notify: UTF8_STRING " + "data_size %d", data_size)); g_free(g_last_clip_data); + g_last_clip_data = 0; g_last_clip_size = data_size; g_last_clip_data = g_malloc(g_last_clip_size + 1, 0); g_last_clip_type = g_utf8_atom; g_memcpy(g_last_clip_data, data, g_last_clip_size); g_last_clip_data[g_last_clip_size] = 0; send_format_announce = 1; + format_id = CB_FORMAT_UNICODETEXT; } else if (lxevent->target == XA_STRING) { - LOG(5, ("clipboard_event_selection_notify: XA_STRING data_size %d", - data_size)); + LOGM((LOG_LEVEL_DEBUG,"clipboard_event_selection_notify: XA_STRING " + "data_size %d", data_size)); g_free(g_last_clip_data); + g_last_clip_data = 0; g_last_clip_size = data_size; g_last_clip_data = g_malloc(g_last_clip_size + 1, 0); g_last_clip_type = XA_STRING; g_memcpy(g_last_clip_data, data, g_last_clip_size); g_last_clip_data[g_last_clip_size] = 0; send_format_announce = 1; + format_id = CB_FORMAT_UNICODETEXT; + } + else if (lxevent->target == g_image_bmp_atom) + { + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_notify: image/bmp " + "data_size %d", data_size)); + g_free(g_last_clip_data); + g_last_clip_data = 0; + g_last_clip_size = data_size; + g_last_clip_data = g_malloc(data_size, 0); + g_last_clip_type = g_image_bmp_atom; + g_memcpy(g_last_clip_data, data, data_size); + send_format_announce = 1; + format_id = CB_FORMAT_DIB; + g_strcpy(format_name, "image/bmp"); } else { - LOG(0, ("clipboard_event_selection_notify: unknown target")); + LOGM((LOG_LEVEL_ERROR, "clipboard_event_selection_notify: " + "unknown target")); } } else { - LOG(0, ("clipboard_event_selection_notify: unknown selection")); + LOGM((LOG_LEVEL_ERROR,"clipboard_event_selection_notify: " + "unknown selection")); } } if (convert_to_utf8) @@ -913,9 +1106,14 @@ clipboard_event_selection_notify(XEvent* xevent) XConvertSelection(g_display, g_clipboard_atom, XA_STRING, g_clip_property_atom, g_wnd, lxevent->time); } + else if (convert_to_bmp_image) + { + XConvertSelection(g_display, g_clipboard_atom, g_image_bmp_atom, + g_clip_property_atom, g_wnd, lxevent->time); + } if (send_format_announce) { - if (clipboard_send_format_announce() != 0) + if (clipboard_send_format_announce(format_id, format_name) != 0) { rv = 4; } @@ -939,12 +1137,17 @@ clipboard_event_selection_notify(XEvent* xevent) Atom property; Time time; } XSelectionRequestEvent; */ +/* + * When XGetWindowProperty and XChangeProperty talk about "format 32" it + * doesn't mean a 32bit value, but actually a long. So 32 means 4 bytes on + * a 32bit machine and 8 bytes on a 64 machine + */ static int APP_CC clipboard_event_selection_request(XEvent* xevent) { - XEvent xev; XSelectionRequestEvent* lxev; - tui32 ui32[8]; + XEvent xev; + Atom atom_buf[10]; Atom type; int fmt; int n_items; @@ -952,52 +1155,58 @@ clipboard_event_selection_request(XEvent* xevent) char* xdata; lxev = (XSelectionRequestEvent*)xevent; - LOG(5, ("clipboard_event_selection_request: g_wnd %d, " - ".requestor %d .owner %d .selection %d '%s' .target %d .property %d", - g_wnd, lxev->requestor, lxev->owner, lxev->selection, - XGetAtomName(g_display, lxev->selection), - lxev->target, lxev->property)); + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: g_wnd %d, " + ".requestor %d .owner %d .selection %d '%s' .target %d .property %d", + g_wnd, lxev->requestor, lxev->owner, lxev->selection, + XGetAtomName(g_display, lxev->selection), + lxev->target, lxev->property)); if (lxev->property == None) { - LOG(5, ("clipboard_event_selection_request: lxev->property is None")); + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: " + "lxev->property is None")); } else if (lxev->target == g_targets_atom) { /* requestor is asking what the selection can be converted to */ - LOG(5, ("clipboard_event_selection_request: g_targets_atom")); - ui32[0] = g_targets_atom; - ui32[1] = g_timestamp_atom; - ui32[2] = g_multiple_atom; - ui32[3] = XA_STRING; - ui32[4] = g_utf8_atom; - return clipboard_provide_selection(lxev, XA_ATOM, 32, (char*)ui32, 5); + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: " + "g_targets_atom")); + atom_buf[0] = g_targets_atom; + atom_buf[1] = g_timestamp_atom; + atom_buf[2] = g_multiple_atom; + atom_buf[3] = XA_STRING; + atom_buf[4] = g_utf8_atom; + atom_buf[5] = g_image_bmp_atom; + return clipboard_provide_selection(lxev, XA_ATOM, 32, (char*)atom_buf, 6); } else if (lxev->target == g_timestamp_atom) { /* requestor is asking the time I got the selection */ - LOG(5, ("clipboard_event_selection_request: g_timestamp_atom")); - ui32[0] = g_selection_time; - return clipboard_provide_selection(lxev, XA_INTEGER, 32, (char*)ui32, 1); + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: " + "g_timestamp_atom")); + atom_buf[0] = g_selection_time; + return clipboard_provide_selection(lxev, XA_INTEGER, 32, (char*)atom_buf, 1); } else if (lxev->target == g_multiple_atom) { /* target, property pairs */ - LOG(5, ("clipboard_event_selection_request: g_multiple_atom")); + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: " + "g_multiple_atom")); if (clipboard_get_window_property(xev.xselection.requestor, xev.xselection.property, &type, &fmt, &n_items, &xdata, &xdata_size) == 0) { - LOG(5, ("clipboard_event_selection_request: g_multiple_atom " - "n_items %d", n_items)); + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: g_multiple_atom " + "n_items %d", n_items)); /* todo */ g_free(xdata); } } else if ((lxev->target == XA_STRING) || (lxev->target == g_utf8_atom)) { - LOG(5, ("clipboard_event_selection_request: %s", - XGetAtomName(g_display, lxev->target))); + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_request: %s", + XGetAtomName(g_display, lxev->target))); + clipboard_format_id = CB_FORMAT_UNICODETEXT; if (g_data_in_up_to_date) { return clipboard_provide_selection(lxev, lxev->target, 8, @@ -1005,7 +1214,8 @@ clipboard_event_selection_request(XEvent* xevent) } if (g_selection_request_event_count > 10) { - LOG(0, ("clipboard_event_selection_request: error, too many requests")); + LOGM((LOG_LEVEL_ERROR, "clipboard_event_selection_request: error, " + "too many requests")); } else { @@ -1015,16 +1225,28 @@ clipboard_event_selection_request(XEvent* xevent) { clipboard_send_data_request(); g_waiting_for_data_response = 1; - g_waiting_for_data_response_time = clipboard_get_local_time(); + g_waiting_for_data_response_time = xcommon_get_local_time(); } g_selection_request_event_count++; return 0; } } + else if (lxev->target == g_image_bmp_atom) + { + g_memcpy(&g_saved_selection_req_event, lxev, + sizeof(g_saved_selection_req_event)); + g_last_clip_type = g_image_bmp_atom; + g_want_image_data = 1; + clipboard_format_id = CB_FORMAT_DIB; + clipboard_send_data_request(); + g_waiting_for_data_response = 1; + g_waiting_for_data_response_time = clipboard_get_local_time(); + return 0; + } else { - LOG(0, ("clipboard_event_selection_request: unknown " - "target %s", XGetAtomName(g_display, lxev->target))); + LOGM((LOG_LEVEL_ERROR,"clipboard_event_selection_request: unknown " + "target %s", XGetAtomName(g_display, lxev->target))); } clipboard_refuse_selection(lxev); return 0; @@ -1045,7 +1267,7 @@ clipboard_event_selection_request(XEvent* xevent) static int APP_CC clipboard_event_selection_clear(XEvent* xevent) { - LOG(5, ("clipboard_event_selection_clear:")); + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_clear:")); return 0; } @@ -1064,92 +1286,132 @@ clipboard_event_selection_clear(XEvent* xevent) static int APP_CC clipboard_event_property_notify(XEvent* xevent) { + Atom actual_type_return; + int actual_format_return; + unsigned long nitems_returned; + unsigned long bytes_left; + unsigned char* data; + int rv; + int format_in_bytes; + int new_data_len; + char* cptr; + char format_name[32]; + LOG(10, ("clipboard_check_wait_objs: PropertyNotify .window %d " ".state %d .atom %d", xevent->xproperty.window, xevent->xproperty.state, xevent->xproperty.atom)); - return 0; -} - -/*****************************************************************************/ -/* returns error - this is called to get any wait objects for the main loop - timeout can be nil */ -int APP_CC -clipboard_get_wait_objs(tbus* objs, int* count, int* timeout) -{ - int lcount; - - if ((!g_clip_up) || (objs == 0) || (count == 0)) + if (g_incr_in_progress && + (xevent->xproperty.atom == g_incr_atom_type) && + (xevent->xproperty.state == PropertyNewValue)) { - return 0; + rv = XGetWindowProperty(g_display, g_wnd, g_incr_atom_type, 0, 0, 0, + AnyPropertyType, &actual_type_return, &actual_format_return, + &nitems_returned, &bytes_left, (unsigned char **) &data); + if (data != 0) + { + XFree(data); + data = 0; + } + if (bytes_left <= 0) + { + LOGM((LOG_LEVEL_DEBUG, "clipboard_event_property_notify: INCR done")); + g_memset(format_name, 0, 32); + /* clipboard INCR cycle has completed */ + g_incr_in_progress = 0; + g_last_clip_size = g_incr_data_size; + g_last_clip_data = g_incr_data; + g_incr_data = 0; + g_last_clip_type = g_incr_atom_target; + if (g_incr_atom_target == g_image_bmp_atom) + { + g_snprintf(format_name, 31, "image/bmp"); + clipboard_send_format_announce(CB_FORMAT_DIB, format_name); + } + XDeleteProperty(g_display, g_wnd, g_incr_atom_type); + } + else + { + rv = XGetWindowProperty(g_display, g_wnd, g_incr_atom_type, 0, bytes_left, 0, + AnyPropertyType, &actual_type_return, &actual_format_return, + &nitems_returned, &bytes_left, (unsigned char **) &data); + + format_in_bytes = actual_format_return / 8; + if ((actual_format_return == 32) && (sizeof(long) == 8)) + { + /* on a 64 bit machine, actual_format_return of 32 implies long */ + format_in_bytes = 8; + } + new_data_len = nitems_returned * format_in_bytes; + cptr = (char*)g_malloc(g_incr_data_size + new_data_len, 0); + g_memcpy(cptr, g_incr_data, g_incr_data_size); + g_free(g_incr_data); + if (cptr == NULL) + { + g_incr_data = 0; + /* cannot add any more data */ + if (data != 0) + { + XFree(data); + } + XDeleteProperty(g_display, g_wnd, g_incr_atom_type); + return 0; + } + g_incr_data = cptr; + g_memcpy(g_incr_data + g_incr_data_size, data, new_data_len); + g_incr_data_size += new_data_len; + if (data) + { + XFree(data); + } + XDeleteProperty(g_display, g_wnd, g_incr_atom_type); + } } - lcount = *count; - objs[lcount] = g_x_wait_obj; - lcount++; - *count = lcount; return 0; } /*****************************************************************************/ +/* returns 0, event handled, 1 unhandled */ int APP_CC -clipboard_check_wait_objs(void) +clipboard_xevent(void* xevent) { - XEvent xevent; - int time_diff; + XEvent* lxevent; if (!g_clip_up) { - return 0; + return 1; } - if (g_is_wait_obj_set(g_x_wait_obj)) + lxevent = (XEvent*)xevent; + switch (lxevent->type) { - if (XPending(g_display) < 1) - { - /* something is wrong, should not get here */ - LOG(0, ("clipboard_check_wait_objs: sck closed")); - return 0; - } - if (g_waiting_for_data_response) - { - time_diff = clipboard_get_local_time() - - g_waiting_for_data_response_time; - if (time_diff > 1000) - { - LOG(0, ("clipboard_check_wait_objs: warning, waiting for " - "data response too long")); - } - } - while (XPending(g_display) > 0) - { - XNextEvent(g_display, &xevent); - switch (xevent.type) + case SelectionNotify: + clipboard_event_selection_notify(lxevent); + break; + case SelectionRequest: + clipboard_event_selection_request(lxevent); + break; + case SelectionClear: + clipboard_event_selection_clear(lxevent); + break; + case MappingNotify: + break; + case PropertyNotify: + clipboard_event_property_notify(lxevent); + break; + case UnmapNotify: + LOG(0, ("chansrv::clipboard_xevent: got UnmapNotify")); + break; + case ClientMessage: + LOG(0, ("chansrv::clipboard_xevent: got ClientMessage")); + break; + default: + if (lxevent->type == g_xfixes_event_base + + XFixesSetSelectionOwnerNotify) { - case SelectionNotify: - clipboard_event_selection_notify(&xevent); - break; - case SelectionRequest: - clipboard_event_selection_request(&xevent); - break; - case SelectionClear: - clipboard_event_selection_clear(&xevent); - break; - case MappingNotify: - break; - case PropertyNotify: - clipboard_event_property_notify(&xevent); - break; - default: - if (xevent.type == g_xfixes_event_base + - XFixesSetSelectionOwnerNotify) - { - clipboard_event_selection_owner_notify(&xevent); - break; - } - LOG(0, ("clipboard_check_wait_objs unknown type %d", - xevent.type)); - break; + clipboard_event_selection_owner_notify(lxevent); + break; } - } + /* we didn't handle this message */ + return 1; } return 0; } diff --git a/sesman/chansrv/clipboard.h b/sesman/chansrv/clipboard.h index d6c74403..2fe1d194 100644 --- a/sesman/chansrv/clipboard.h +++ b/sesman/chansrv/clipboard.h @@ -1,3 +1,21 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2009-2012 + * Copyright (C) Laxmikant Rashinkar 2012 + * + * 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. + */ #if !defined(CLIPBOARD_H) #define CLIPBOARD_H @@ -5,6 +23,22 @@ #include "arch.h" #include "parse.h" +#define CB_FORMAT_LIST 2 +#define CB_FORMAT_LIST_RESPONSE 3 +#define CB_FORMAT_DATA_REQUEST 4 +#define CB_FORMAT_DATA_RESPONSE 5 + +/* Clipboard Formats */ + +#define CB_FORMAT_RAW 0x0000 +#define CB_FORMAT_TEXT 0x0001 +#define CB_FORMAT_DIB 0x0008 +#define CB_FORMAT_UNICODETEXT 0x000D +#define CB_FORMAT_HTML 0xD010 +#define CB_FORMAT_PNG 0xD011 +#define CB_FORMAT_JPEG 0xD012 +#define CB_FORMAT_GIF 0xD013 + int APP_CC clipboard_init(void); int APP_CC @@ -13,8 +47,6 @@ int APP_CC clipboard_data_in(struct stream* s, int chan_id, int chan_flags, int length, int total_length); int APP_CC -clipboard_get_wait_objs(tbus* objs, int* count, int* timeout); -int APP_CC -clipboard_check_wait_objs(void); +clipboard_xevent(void* xevent); #endif diff --git a/sesman/chansrv/devredir.c b/sesman/chansrv/devredir.c index 8e660a49..dd244572 100644 --- a/sesman/chansrv/devredir.c +++ b/sesman/chansrv/devredir.c @@ -1,21 +1,20 @@ -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - xrdp: A Remote Desktop Protocol server. - Copyright (C) Jay Sorg 2009-2010 -*/ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2009-2012 + * + * 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. + */ #include "arch.h" #include "parse.h" diff --git a/sesman/chansrv/devredir.h b/sesman/chansrv/devredir.h index e0279093..3ec08a51 100644 --- a/sesman/chansrv/devredir.h +++ b/sesman/chansrv/devredir.h @@ -1,3 +1,20 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2009-2012 + * + * 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. + */ #if !defined(DEVREDIR_H) #define DEVREDIR_H diff --git a/sesman/chansrv/rail.c b/sesman/chansrv/rail.c new file mode 100644 index 00000000..6b47f867 --- /dev/null +++ b/sesman/chansrv/rail.c @@ -0,0 +1,677 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2012 + * + * 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. + */ + +/* + window manager info + http://www.freedesktop.org/wiki/Specifications/wm-spec +*/ + +#include <X11/Xlib.h> +#include "chansrv.h" +#include "rail.h" +#include "xcommon.h" +#include "log.h" +#include "os_calls.h" +#include "thread_calls.h" + +extern int g_rail_chan_id; /* in chansrv.c */ +extern int g_display_num; /* in chansrv.c */ +extern char* g_exec_name; /* in chansrv.c */ +extern tbus g_exec_event; /* in chansrv.c */ +extern tbus g_exec_mutex; /* in chansrv.c */ +extern tbus g_exec_sem; /* in chansrv.c */ + +extern Display* g_display; /* in xcommon.c */ +extern Screen* g_screen; /* in xcommon.c */ +extern Window g_root_window; /* in xcommon.c */ +extern Atom g_wm_delete_window_atom; /* in xcommon.c */ +extern Atom g_wm_protocols_atom; /* in xcommon.c */ + +int g_rail_up = 0; + +/* for rail_is_another_wm_running */ +static int g_rail_running = 1; + +/* Indicates a Client Execute PDU from client to server. */ +#define TS_RAIL_ORDER_EXEC 0x0001 +/* Indicates a Client Activate PDU from client to server. */ +#define TS_RAIL_ORDER_ACTIVATE 0x0002 +/* Indicates a Client System Parameters Update PDU from client + to server or a Server System Parameters Update PDU + from server to client. */ +#define TS_RAIL_ORDER_SYSPARAM 0x0003 +/* Indicates a Client System Command PDU from client to server. */ +#define TS_RAIL_ORDER_SYSCOMMAND 0x0004 +/* Indicates a bi-directional Handshake PDU. */ +#define TS_RAIL_ORDER_HANDSHAKE 0x0005 +/* Indicates a Client Notify Event PDU from client to server. */ +#define TS_RAIL_ORDER_NOTIFY_EVENT 0x0006 +/* Indicates a Client Window Move PDU from client to server. */ +#define TS_RAIL_ORDER_WINDOWMOVE 0x0008 +/* Indicates a Server Move/Size Start PDU and a Server Move/Size + End PDU from server to client. */ +#define TS_RAIL_ORDER_LOCALMOVESIZE 0x0009 +/* Indicates a Server Min Max Info PDU from server to client. */ +#define TS_RAIL_ORDER_MINMAXINFO 0x000a +/* Indicates a Client Information PDU from client to server. */ +#define TS_RAIL_ORDER_CLIENTSTATUS 0x000b +/* Indicates a Client System Menu PDU from client to server. */ +#define TS_RAIL_ORDER_SYSMENU 0x000c +/* Indicates a Server Language Bar Information PDU from server to + client, or a Client Language Bar Information PDU from client to server. */ +#define TS_RAIL_ORDER_LANGBARINFO 0x000d +/* Indicates a Server Execute Result PDU from server to client. */ +#define TS_RAIL_ORDER_EXEC_RESULT 0x0080 +/* Indicates a Client Get Application ID PDU from client to server. */ +#define TS_RAIL_ORDER_GET_APPID_REQ 0x000E +/* Indicates a Server Get Application ID Response PDU from + server to client. */ +#define TS_RAIL_ORDER_GET_APPID_RESP 0x000F + +/* Resize the window. */ +#define SC_SIZE 0xF000 +/* Move the window. */ +#define SC_MOVE 0xF010 +/* Minimize the window. */ +#define SC_MINIMIZE 0xF020 +/* Maximize the window. */ +#define SC_MAXIMIZE 0xF030 +/* Close the window. */ +#define SC_CLOSE 0xF060 +/* The ALT + SPACE key combination was pressed; display + the window's system menu. */ +#define SC_KEYMENU 0xF100 +/* Restore the window to its original shape and size. */ +#define SC_RESTORE 0xF120 +/* Perform the default action of the window's system menu. */ +#define SC_DEFAULT 0xF160 + +/******************************************************************************/ +static int APP_CC +is_window_valid_child_of_root(unsigned int window_id) +{ + int found; + unsigned int i; + unsigned int nchild; + Window r; + Window p; + Window* children; + + found = 0; + XQueryTree(g_display, g_root_window, &r, &p, &children, &nchild); + for (i = 0; i < nchild; i++) + { + if (window_id == children[i]) + { + found = 1; + break; + } + } + XFree(children); + return found; +} + +/*****************************************************************************/ +static int APP_CC +rail_send_init(void) +{ + struct stream* s; + int bytes; + char* size_ptr; + + LOG(10, ("chansrv::rail_send_init:")); + make_stream(s); + init_stream(s, 8182); + out_uint16_le(s, TS_RAIL_ORDER_HANDSHAKE); + size_ptr = s->p; + out_uint16_le(s, 0); /* size, set later */ + out_uint32_le(s, 1); /* build number */ + s_mark_end(s); + bytes = (int)((s->end - s->data) - 4); + size_ptr[0] = bytes; + size_ptr[1] = bytes >> 8; + bytes = (int)(s->end - s->data); + send_channel_data(g_rail_chan_id, s->data, bytes); + free_stream(s); + return 0; +} + +/******************************************************************************/ +static int DEFAULT_CC +anotherWMRunning(Display* display, XErrorEvent* xe) +{ + g_rail_running = 0; + return -1; +} + +/******************************************************************************/ +static int APP_CC +rail_is_another_wm_running(void) +{ + XErrorHandler old; + + g_rail_running = 1; + old = XSetErrorHandler((XErrorHandler)anotherWMRunning); + XSelectInput(g_display, g_root_window, + PropertyChangeMask | StructureNotifyMask | + SubstructureRedirectMask | ButtonPressMask | + SubstructureNotifyMask | FocusChangeMask | + EnterWindowMask | LeaveWindowMask); + XSync(g_display, 0); + XSetErrorHandler((XErrorHandler)old); + g_rail_up = g_rail_running; + if (!g_rail_up) + { + return 1; + } + return 0; +} + +/*****************************************************************************/ +int APP_CC +rail_init(void) +{ + 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"); + } + rail_send_init(); + g_rail_up = 1; + return 0; +} + +/*****************************************************************************/ +int APP_CC +rail_deinit(void) +{ + if (g_rail_up) + { + /* no longer window manager */ + XSelectInput(g_display, g_root_window, 0); + g_rail_up = 0; + } + return 0; +} + +/*****************************************************************************/ +static char* APP_CC +read_uni(struct stream* s, int num_chars) +{ + twchar* rchrs; + char* rv; + int index; + int lchars; + + rchrs = 0; + rv = 0; + if (num_chars > 0) + { + rchrs = (twchar*)g_malloc((num_chars + 1) * sizeof(twchar), 0); + for (index = 0; index < num_chars; index++) + { + in_uint16_le(s, rchrs[index]); + } + rchrs[num_chars] = 0; + lchars = g_wcstombs(0, rchrs, 0); + if (lchars > 0) + { + rv = (char*)g_malloc((lchars + 1) * 4, 0); + g_wcstombs(rv, rchrs, lchars); + rv[lchars] = 0; + } + } + g_free(rchrs); + return rv; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_exec(struct stream* s, int size) +{ + int pid; + int flags; + int ExeOrFileLength; + int WorkingDirLength; + int ArgumentsLen; + char* ExeOrFile; + char* WorkingDir; + char* Arguments; + + LOG(0, ("chansrv::rail_process_exec:")); + in_uint16_le(s, flags); + in_uint16_le(s, ExeOrFileLength); + in_uint16_le(s, WorkingDirLength); + in_uint16_le(s, ArgumentsLen); + ExeOrFile = read_uni(s, ExeOrFileLength); + WorkingDir = read_uni(s, WorkingDirLength); + Arguments = read_uni(s, ArgumentsLen); + LOG(10, (" flags 0x%8.8x ExeOrFileLength %d WorkingDirLength %d " + "ArgumentsLen %d ExeOrFile [%s] WorkingDir [%s] " + "Arguments [%s]", flags, ExeOrFileLength, WorkingDirLength, + ArgumentsLen, ExeOrFile, WorkingDir, Arguments)); + if (g_strlen(ExeOrFile) > 0) + { + LOG(10, ("rail_process_exec: pre")); + /* ask main thread to fork */ + tc_mutex_lock(g_exec_mutex); + g_exec_name = ExeOrFile; + g_set_wait_obj(g_exec_event); + tc_sem_dec(g_exec_sem); + tc_mutex_unlock(g_exec_mutex); + LOG(10, ("rail_process_exec: post")); + } + g_free(ExeOrFile); + g_free(WorkingDir); + g_free(Arguments); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_activate(struct stream* s, int size) +{ + int window_id; + int enabled; + + LOG(10, ("chansrv::rail_process_activate:")); + in_uint32_le(s, window_id); + in_uint8(s, enabled); + LOG(10, (" window_id 0x%8.8x enabled %d", window_id, enabled)); + if (enabled) + { + LOG(10, ("chansrv::rail_process_activate: calling XRaiseWindow 0x%8.8x", 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; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_system_param(struct stream* s, int size) +{ + int system_param; + + LOG(10, ("chansrv::rail_process_system_param:")); + in_uint32_le(s, system_param); + LOG(10, (" system_param 0x%8.8x", system_param)); + return 0; +} + +/******************************************************************************/ +static int APP_CC +rail_close_window(int window_id) +{ + XEvent ce; + + LOG(0, ("chansrv::rail_close_window:")); + g_memset(&ce, 0, sizeof(ce)); + ce.xclient.type = ClientMessage; + ce.xclient.message_type = g_wm_protocols_atom; + ce.xclient.display = g_display; + ce.xclient.window = window_id; + ce.xclient.format = 32; + ce.xclient.data.l[0] = g_wm_delete_window_atom; + ce.xclient.data.l[1] = CurrentTime; + XSendEvent(g_display, window_id, False, NoEventMask, &ce); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_system_command(struct stream* s, int size) +{ + int window_id; + int command; + + LOG(10, ("chansrv::rail_process_system_command:")); + in_uint32_le(s, window_id); + in_uint16_le(s, command); + switch (command) + { + case SC_SIZE: + LOG(10, (" window_id 0x%8.8x SC_SIZE", window_id)); + break; + case SC_MOVE: + LOG(10, (" window_id 0x%8.8x SC_MOVE", window_id)); + break; + case SC_MINIMIZE: + LOG(10, (" window_id 0x%8.8x SC_MINIMIZE", window_id)); + break; + case SC_MAXIMIZE: + LOG(10, (" window_id 0x%8.8x SC_MAXIMIZE", window_id)); + break; + case SC_CLOSE: + LOG(10, (" window_id 0x%8.8x SC_CLOSE", window_id)); + rail_close_window(window_id); + break; + case SC_KEYMENU: + LOG(10, (" window_id 0x%8.8x SC_KEYMENU", window_id)); + break; + case SC_RESTORE: + LOG(10, (" window_id 0x%8.8x SC_RESTORE", window_id)); + break; + case SC_DEFAULT: + LOG(10, (" window_id 0x%8.8x SC_DEFAULT", window_id)); + break; + default: + LOG(10, (" window_id 0x%8.8x unknown command command %d", + window_id, command)); + break; + } + return 0; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_handshake(struct stream* s, int size) +{ + int build_number; + + LOG(10, ("chansrv::rail_process_handshake:")); + in_uint32_le(s, build_number); + LOG(10, (" build_number 0x%8.8x", build_number)); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_notify_event(struct stream* s, int size) +{ + int window_id; + int notify_id; + int message; + + LOG(10, ("chansrv::rail_process_notify_event:")); + in_uint32_le(s, window_id); + in_uint32_le(s, notify_id); + in_uint32_le(s, message); + LOG(10, (" window_id 0x%8.8x notify_id 0x%8.8x message 0x%8.8x", + window_id, notify_id, message)); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_window_move(struct stream* s, int size) +{ + int window_id; + int left; + int top; + int right; + int bottom; + + LOG(10, ("chansrv::rail_process_window_move:")); + in_uint32_le(s, window_id); + in_uint16_le(s, left); + in_uint16_le(s, top); + in_uint16_le(s, right); + in_uint16_le(s, bottom); + LOG(10, (" window_id 0x%8.8x left %d top %d right %d bottom %d width %d height %d", + window_id, left, top, right, bottom, right - left, bottom - top)); + XMoveResizeWindow(g_display, window_id, left, top, right - left, bottom - top); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_local_move_size(struct stream* s, int size) +{ + int window_id; + int is_move_size_start; + int move_size_type; + int pos_x; + int pos_y; + + LOG(10, ("chansrv::rail_process_local_move_size:")); + in_uint32_le(s, window_id); + in_uint16_le(s, is_move_size_start); + in_uint16_le(s, move_size_type); + in_uint16_le(s, pos_x); + in_uint16_le(s, pos_y); + LOG(10, (" window_id 0x%8.8x is_move_size_start %d move_size_type %d " + "pos_x %d pos_y %d", window_id, is_move_size_start, move_size_type, + pos_x, pos_y)); + return 0; +} + +/*****************************************************************************/ +/* server to client only */ +static int APP_CC +rail_process_min_max_info(struct stream* s, int size) +{ + LOG(10, ("chansrv::rail_process_min_max_info:")); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_client_status(struct stream* s, int size) +{ + int flags; + + LOG(10, ("chansrv::rail_process_client_status:")); + in_uint32_le(s, flags); + LOG(10, (" flags 0x%8.8x", flags)); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_sys_menu(struct stream* s, int size) +{ + int window_id; + int left; + int top; + + LOG(10, ("chansrv::rail_process_sys_menu:")); + in_uint32_le(s, window_id); + in_uint16_le(s, left); + in_uint16_le(s, top); + LOG(10, (" window_id 0x%8.8x left %d top %d", window_id, left, top)); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_lang_bar_info(struct stream* s, int size) +{ + int language_bar_status; + + LOG(10, ("chansrv::rail_process_lang_bar_info:")); + in_uint32_le(s, language_bar_status); + LOG(10, (" language_bar_status 0x%8.8x", language_bar_status)); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_appid_req(struct stream* s, int size) +{ + LOG(10, ("chansrv::rail_process_appid_req:")); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +rail_process_appid_resp(struct stream* s, int size) +{ + LOG(10, ("chansrv::rail_process_appid_resp:")); + return 0; +} + +/*****************************************************************************/ +/* server to client only */ +static int APP_CC +rail_process_exec_result(struct stream* s, int size) +{ + LOG(10, ("chansrv::rail_process_exec_result:")); + return 0; +} + +/*****************************************************************************/ +/* data in from client ( client -> xrdp -> chansrv ) */ +int APP_CC +rail_data_in(struct stream* s, int chan_id, int chan_flags, int length, + int total_length) +{ + int code; + int size; + + LOG(10, ("chansrv::rail_data_in:")); + in_uint8(s, code); + in_uint8s(s, 1); + in_uint16_le(s, size); + switch (code) + { + case TS_RAIL_ORDER_EXEC: /* 1 */ + rail_process_exec(s, size); + break; + case TS_RAIL_ORDER_ACTIVATE: /* 2 */ + rail_process_activate(s, size); + break; + case TS_RAIL_ORDER_SYSPARAM: /* 3 */ + rail_process_system_param(s, size); + break; + case TS_RAIL_ORDER_SYSCOMMAND: /* 4 */ + rail_process_system_command(s, size); + break; + case TS_RAIL_ORDER_HANDSHAKE: /* 5 */ + rail_process_handshake(s, size); + break; + case TS_RAIL_ORDER_NOTIFY_EVENT: /* 6 */ + rail_process_notify_event(s, size); + break; + case TS_RAIL_ORDER_WINDOWMOVE: /* 8 */ + rail_process_window_move(s, size); + break; + case TS_RAIL_ORDER_LOCALMOVESIZE: /* 9 */ + rail_process_local_move_size(s, size); + break; + case TS_RAIL_ORDER_MINMAXINFO: /* 10 */ + rail_process_min_max_info(s, size); + break; + case TS_RAIL_ORDER_CLIENTSTATUS: /* 11 */ + rail_process_client_status(s, size); + break; + case TS_RAIL_ORDER_SYSMENU: /* 12 */ + rail_process_sys_menu(s, size); + break; + case TS_RAIL_ORDER_LANGBARINFO: /* 13 */ + rail_process_lang_bar_info(s, size); + break; + case TS_RAIL_ORDER_GET_APPID_REQ: /* 14 */ + rail_process_appid_req(s, size); + break; + case TS_RAIL_ORDER_GET_APPID_RESP: /* 15 */ + rail_process_appid_resp(s, size); + break; + case TS_RAIL_ORDER_EXEC_RESULT: /* 128 */ + rail_process_exec_result(s, size); + break; + default: + LOG(10, ("rail_data_in: unknown code %d size %d", code, size)); + break; + } + XFlush(g_display); + return 0; +} + +/*****************************************************************************/ +/* returns 0, event handled, 1 unhandled */ +int APP_CC +rail_xevent(void* xevent) +{ + XEvent* lxevent; + XWindowChanges xwc; + int rv; + int nchildren_return = 0; + Window root_return; + Window parent_return; + Window *children_return; + Window wreturn; + int revert_to; + XWindowAttributes wnd_attributes; + + LOG(10, ("chansrv::rail_xevent:")); + if (!g_rail_up) + { + return 1; + } + rv = 1; + lxevent = (XEvent*)xevent; + switch (lxevent->type) + { + case ConfigureRequest: + LOG(10, (" got ConfigureRequest window_id 0x%8.8x", lxevent->xconfigurerequest.window)); + g_memset(&xwc, 0, sizeof(xwc)); + xwc.x = lxevent->xconfigurerequest.x; + xwc.y = lxevent->xconfigurerequest.y; + xwc.width = lxevent->xconfigurerequest.width; + xwc.height = lxevent->xconfigurerequest.height; + xwc.border_width = lxevent->xconfigurerequest.border_width; + xwc.sibling = lxevent->xconfigurerequest.above; + xwc.stack_mode = lxevent->xconfigurerequest.detail; + XConfigureWindow(g_display, + lxevent->xconfigurerequest.window, + lxevent->xconfigurerequest.value_mask, + &xwc); + rv = 0; + break; + + case MapRequest: + LOG(10, (" got MapRequest")); + XMapWindow(g_display, lxevent->xmaprequest.window); + rv = 0; + break; + + case MapNotify: + LOG(10, (" got MapNotify")); + break; + + case UnmapNotify: + LOG(10, (" got UnmapNotify")); + break; + + case ConfigureNotify: + LOG(10, (" got ConfigureNotify")); + break; + + case FocusIn: + LOG(10, (" got FocusIn")); + break; + + case ButtonPress: + LOG(10, (" got ButtonPress")); + break; + + case EnterNotify: + LOG(10, (" got EnterNotify")); + break; + + case LeaveNotify: + LOG(10, (" got LeaveNotify")); + break; + + } + return rv; +} diff --git a/sesman/chansrv/rail.h b/sesman/chansrv/rail.h new file mode 100644 index 00000000..7dbcbc5a --- /dev/null +++ b/sesman/chansrv/rail.h @@ -0,0 +1,35 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2012 + * + * 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. + */ + +#ifndef _RAIL_H_ +#define _RAIL_H_ + +#include "arch.h" +#include "parse.h" + +int APP_CC +rail_init(void); +int APP_CC +rail_deinit(void); +int APP_CC +rail_data_in(struct stream* s, int chan_id, int chan_flags, + int length, int total_length); +int APP_CC +rail_xevent(void* xevent); + +#endif diff --git a/sesman/chansrv/sound.c b/sesman/chansrv/sound.c index 8cca641d..e4d54bb0 100644 --- a/sesman/chansrv/sound.c +++ b/sesman/chansrv/sound.c @@ -1,32 +1,346 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2009-2012 + * + * 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. + */ + +#include "sound.h" +#include "thread_calls.h" + +extern int g_rdpsnd_chan_id; /* in chansrv.c */ +extern int g_display_num; /* in chansrv.c */ + +static struct trans *g_audio_l_trans = 0; // listener +static struct trans *g_audio_c_trans = 0; // connection +static int g_training_sent_time = 0; +static int g_cBlockNo = 0; + +#if defined(XRDP_SIMPLESOUND) +static void* DEFAULT_CC +read_raw_audio_data(void* arg); +#endif + +/*****************************************************************************/ +static int APP_CC +sound_send_server_formats(void) +{ + struct stream* s; + int bytes; + char* size_ptr; + + print_got_here(); + + make_stream(s); + init_stream(s, 8182); + out_uint16_le(s, SNDC_FORMATS); + size_ptr = s->p; + out_uint16_le(s, 0); /* size, set later */ + out_uint32_le(s, 0); /* dwFlags */ + out_uint32_le(s, 0); /* dwVolume */ + out_uint32_le(s, 0); /* dwPitch */ + out_uint16_le(s, 0); /* wDGramPort */ + out_uint16_le(s, 1); /* wNumberOfFormats */ + out_uint8(s, g_cBlockNo); /* cLastBlockConfirmed */ + out_uint16_le(s, 2); /* wVersion */ + out_uint8(s, 0); /* bPad */ + + /* sndFormats */ + /* + wFormatTag 2 byte offset 0 + nChannels 2 byte offset 2 + nSamplesPerSec 4 byte offset 4 + nAvgBytesPerSec 4 byte offset 8 + nBlockAlign 2 byte offset 12 + wBitsPerSample 2 byte offset 14 + cbSize 2 byte offset 16 + data variable offset 18 + */ + + /* examples + 01 00 02 00 44 ac 00 00 10 b1 02 00 04 00 10 00 ....D........... + 00 00 + 01 00 02 00 22 56 00 00 88 58 01 00 04 00 10 00 ...."V...X...... + 00 00 + */ + + out_uint16_le(s, 1); // wFormatTag - WAVE_FORMAT_PCM + out_uint16_le(s, 2); // num of channels + out_uint32_le(s, 44100); // samples per sec + out_uint32_le(s, 176400); // avg bytes per sec + out_uint16_le(s, 4); // block align + out_uint16_le(s, 16); // bits per sample + out_uint16_le(s, 0); // size + + s_mark_end(s); + bytes = (int)((s->end - s->data) - 4); + size_ptr[0] = bytes; + size_ptr[1] = bytes >> 8; + bytes = (int)(s->end - s->data); + send_channel_data(g_rdpsnd_chan_id, s->data, bytes); + free_stream(s); + return 0; +} + +/*****************************************************************************/ +static int +sound_send_training(void) +{ + struct stream* s; + int bytes; + int time; + char* size_ptr; + + print_got_here(); + + make_stream(s); + init_stream(s, 8182); + out_uint16_le(s, SNDC_TRAINING); + size_ptr = s->p; + out_uint16_le(s, 0); /* size, set later */ + time = g_time2(); + g_training_sent_time = time; + out_uint16_le(s, time); + out_uint16_le(s, 1024); + out_uint8s(s, (1024 - 4)); + s_mark_end(s); + bytes = (int)((s->end - s->data) - 4); + size_ptr[0] = bytes; + size_ptr[1] = bytes >> 8; + bytes = (int)(s->end - s->data); + send_channel_data(g_rdpsnd_chan_id, s->data, bytes); + free_stream(s); + return 0; +} + +/*****************************************************************************/ /* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - xrdp: A Remote Desktop Protocol server. - Copyright (C) Jay Sorg 2009-2010 + 0000 07 02 26 00 03 00 80 00 ff ff ff ff 00 00 00 00 ..&............. + 0010 00 00 01 00 00 02 00 00 01 00 02 00 44 ac 00 00 ............D... + 0020 10 b1 02 00 04 00 10 00 00 00 */ -#include "arch.h" -#include "parse.h" -#include "os_calls.h" +static int APP_CC +sound_process_formats(struct stream* s, int size) +{ + int num_formats; + + print_got_here(); + + LOG(0, ("sound_process_formats:")); + if (size < 16) + { + return 1; + } + in_uint8s(s, 14); + in_uint16_le(s, num_formats); + if (num_formats > 0) + { + sound_send_training(); + } + return 0; +} + +/*****************************************************************************/ +static int +sound_send_wave_data(char* data, int data_bytes) +{ + struct stream* s; + int bytes; + int time; + char* size_ptr; + + print_got_here(); + + if ((data_bytes < 4) || (data_bytes > 32 * 1024)) + { + LOG(0, ("sound_send_wave_data: bad data_bytes %d", data_bytes)); + } + + /* part one of 2 PDU wave info */ + + LOG(10, ("sound_send_wave_data: sending %d bytes", data_bytes)); + + make_stream(s); + init_stream(s, data_bytes); + out_uint16_le(s, SNDC_WAVE); + size_ptr = s->p; + out_uint16_le(s, 0); /* size, set later */ + time = g_time2(); + out_uint16_le(s, time); + out_uint16_le(s, 0); /* wFormatNo */ + g_cBlockNo++; + out_uint8(s, g_cBlockNo); + + LOG(10, ("sound_send_wave_data: sending time %d, g_cBlockNo %d", + time & 0xffff, g_cBlockNo & 0xff)); + + out_uint8s(s, 3); + out_uint8a(s, data, 4); + s_mark_end(s); + bytes = (int)((s->end - s->data) - 4); + bytes += data_bytes; + bytes -= 4; + size_ptr[0] = bytes; + size_ptr[1] = bytes >> 8; + bytes = (int)(s->end - s->data); + send_channel_data(g_rdpsnd_chan_id, s->data, bytes); + + /* part two of 2 PDU wave info */ + init_stream(s, data_bytes); + out_uint32_le(s, 0); + out_uint8a(s, data + 4, data_bytes - 4); + s_mark_end(s); + bytes = (int)(s->end - s->data); + send_channel_data(g_rdpsnd_chan_id, s->data, bytes); + free_stream(s); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +sound_process_training(struct stream* s, int size) +{ + int time_diff; + + print_got_here(); + + time_diff = g_time2() - g_training_sent_time; + LOG(0, ("sound_process_training: round trip time %u", time_diff)); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +sound_process_wave_confirm(struct stream* s, int size) +{ + int wTimeStamp; + int cConfirmedBlockNo; + + print_got_here(); -extern int g_rdpsnd_chan_id; /* in chansrv.c */ + in_uint16_le(s, wTimeStamp); + in_uint8(s, cConfirmedBlockNo); + + LOG(10, ("sound_process_wave_confirm: wTimeStamp %d, cConfirmedBlockNo %d", + wTimeStamp, cConfirmedBlockNo)); + + return 0; +} + +/*****************************************************************************/ +static int APP_CC +process_pcm_message(int id, int size, struct stream* s) +{ + print_got_here(); + + sound_send_wave_data(s->p, size); + return 0; +} + +/*****************************************************************************/ +/* data coming in from audio source, eg pulse, alsa */ +static int DEFAULT_CC +sound_trans_audio_data_in(struct trans* trans) +{ + struct stream *s; + int id; + int size; + int error; + + if (trans == 0) + { + return 0; + } + if (trans != g_audio_c_trans) + { + return 1; + } + s = trans_get_in_s(trans); + in_uint32_le(s, id); + in_uint32_le(s, size); + if ((id != 0) || (size > 32 * 1024 + 8) || (size < 1)) + { + LOG(0, ("sound_trans_audio_data_in: bad message id %d size %d", id, size)); + return 1; + } + error = trans_force_read(trans, size - 8); + if (error == 0) + { + /* here, the entire message block is read in, process it */ + error = process_pcm_message(id, size - 8, s); + } + return error; +} + +/*****************************************************************************/ +static int DEFAULT_CC +sound_trans_audio_conn_in(struct trans *trans, struct trans *new_trans) +{ + print_got_here(); + + if (trans == 0) + { + return 1; + } + if (trans != g_audio_l_trans) + { + return 1; + } + if (g_audio_c_trans != 0) /* if already set, error */ + { + return 1; + } + if (new_trans == 0) + { + return 1; + } + g_audio_c_trans = new_trans; + g_audio_c_trans->trans_data_in = sound_trans_audio_data_in; + g_audio_c_trans->header_size = 8; + trans_delete(g_audio_l_trans); + g_audio_l_trans = 0; + return 0; +} /*****************************************************************************/ int APP_CC sound_init(void) { + char port[256]; + int error; + + print_got_here(); + LOG(0, ("sound_init:")); + + sound_send_server_formats(); + g_audio_l_trans = trans_create(2, 33 * 1024, 8192); + g_snprintf(port, 255, "/tmp/xrdp_chansrv_audio_socket_%d", g_display_num); + g_audio_l_trans->trans_conn_in = sound_trans_audio_conn_in; + error = trans_listen(g_audio_l_trans, port); + if (error != 0) + { + LOG(0, ("sound_init: trans_listen failed")); + } + +#if defined(XRDP_SIMPLESOUND) + + /* start thread to read raw audio data from pulseaudio device */ + tc_thread_create(read_raw_audio_data, 0); + +#endif + return 0; } @@ -34,14 +348,54 @@ sound_init(void) int APP_CC sound_deinit(void) { + print_got_here(); + + if (g_audio_l_trans != 0) + { + trans_delete(g_audio_l_trans); + g_audio_l_trans = 0; + } + if (g_audio_c_trans != 0) + { + trans_delete(g_audio_c_trans); + g_audio_l_trans = 0; + } + return 0; } /*****************************************************************************/ +/* data in from client ( clinet -> xrdp -> chansrv ) */ int APP_CC sound_data_in(struct stream* s, int chan_id, int chan_flags, int length, int total_length) { + int code; + int size; + + print_got_here(); + + in_uint8(s, code); + in_uint8s(s, 1); + in_uint16_le(s, size); + switch (code) + { + case SNDC_WAVECONFIRM: + sound_process_wave_confirm(s, size); + break; + + case SNDC_TRAINING: + sound_process_training(s, size); + break; + + case SNDC_FORMATS: + sound_process_formats(s, size); + break; + + default: + LOG(0, ("sound_data_in: unknown code %d size %d", code, size)); + break; + } return 0; } @@ -49,6 +403,20 @@ sound_data_in(struct stream* s, int chan_id, int chan_flags, int length, int APP_CC sound_get_wait_objs(tbus* objs, int* count, int* timeout) { + int lcount; + + lcount = *count; + if (g_audio_l_trans != 0) + { + objs[lcount] = g_audio_l_trans->sck; + lcount++; + } + if (g_audio_c_trans != 0) + { + objs[lcount] = g_audio_c_trans->sck; + lcount++; + } + *count = lcount; return 0; } @@ -56,5 +424,130 @@ sound_get_wait_objs(tbus* objs, int* count, int* timeout) int APP_CC sound_check_wait_objs(void) { + if (g_audio_l_trans != 0) + { + trans_check_wait_objs(g_audio_l_trans); + } + + if (g_audio_c_trans != 0) + { + trans_check_wait_objs(g_audio_c_trans); + } + + return 0; +} + +#if defined(XRDP_SIMPLESOUND) + +static int DEFAULT_CC +sttrans_data_in(struct trans* self) +{ + LOG(0, ("sttrans_data_in:\n")); return 0; } + +/** + * read raw audio data from pulseaudio device and write it + * to a unix domain socket on which trans server is listening + */ + +static void* DEFAULT_CC +read_raw_audio_data(void* arg) +{ + pa_sample_spec samp_spec; + pa_simple* simple = NULL; + uint32_t bytes_read; + char* cptr; + int i; + int error; + struct trans* strans; + char path[256]; + struct stream* outs; + + strans = trans_create(TRANS_MODE_UNIX, 8192, 8192); + if (strans == 0) + { + LOG(0, ("read_raw_audio_data: trans_create failed\n")); + return 0; + } + strans->trans_data_in = sttrans_data_in; + g_snprintf(path, 255, "/tmp/xrdp_chansrv_audio_socket_%d", g_display_num); + if (trans_connect(strans, "", path, 100) != 0) + { + LOG(0, ("read_raw_audio_data: trans_connect failed\n")); + trans_delete(strans); + return 0; + } + + /* setup audio format */ + samp_spec.format = PA_SAMPLE_S16LE; + samp_spec.rate = 44100; + samp_spec.channels = 2; + + /* if we are root, then for first 8 seconds connection to pulseaudo server + fails; if we are non-root, then connection succeeds on first attempt; + for now we have changed code to be non-root, but this may change in the + future - so pretend we are root and try connecting to pulseaudio server + for upto one minute */ + for (i = 0; i < 60; i++) + { + simple = pa_simple_new(NULL, "xrdp", PA_STREAM_RECORD, NULL, + "record", &samp_spec, NULL, NULL, &error); + if (simple) + { + /* connected to pulseaudio server */ + LOG(0, ("read_raw_audio_data: connected to pulseaudio server\n")); + break; + } + LOG(0, ("read_raw_audio_data: ERROR creating PulseAudio async interface\n")); + LOG(0, ("read_raw_audio_data: %s\n", pa_strerror(error))); + g_sleep(1000); + } + + if (i == 60) + { + /* failed to connect to audio server */ + trans_delete(strans); + return NULL; + } + + /* insert header just once */ + outs = trans_get_out_s(strans, 8192); + out_uint32_le(outs, 0); + out_uint32_le(outs, AUDIO_BUF_SIZE + 8); + cptr = outs->p; + out_uint8s(outs, AUDIO_BUF_SIZE); + s_mark_end(outs); + + while (1) + { + /* read a block of raw audio data... */ + g_memset(cptr, 0, 4); + bytes_read = pa_simple_read(simple, cptr, AUDIO_BUF_SIZE, &error); + if (bytes_read < 0) + { + LOG(0, ("read_raw_audio_data: ERROR reading from pulseaudio stream\n")); + LOG(0, ("read_raw_audio_data: %s\n", pa_strerror(error))); + break; + } + /* bug workaround: + even when there is no audio data, pulseaudio is returning without + errors but the data itself is zero; we use this zero data to + determine that there is no audio data present */ + if (*cptr == 0 && *(cptr + 1) == 0 && *(cptr + 2) == 0 && *(cptr + 3) == 0) + { + g_sleep(10); + continue; + } + if (trans_force_write_s(strans, outs) != 0) + { + LOG(0, ("read_raw_audio_data: ERROR writing audio data to server\n")); + break; + } + } + pa_simple_free(simple); + trans_delete(strans); + return NULL; +} + +#endif diff --git a/sesman/chansrv/sound.h b/sesman/chansrv/sound.h index 45448a5a..8171680d 100644 --- a/sesman/chansrv/sound.h +++ b/sesman/chansrv/sound.h @@ -1,20 +1,70 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2009-2012 + * + * 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. + */ -#if !defined(SOUND_H) -#define SOUND_H +#ifndef _SOUND_H_ +#define _SOUND_H_ + +#if defined(XRDP_SIMPLESOUND) +#include <pulse/simple.h> +#include <pulse/error.h> +#endif #include "arch.h" #include "parse.h" +#include "os_calls.h" +#include "chansrv.h" +#include "trans.h" + +#define _DEBUG_RDPSND + +#ifdef DEBUG_RDPSND +#include <stdio.h> +#define print_got_here() printf("****** got here: %s : %s : %d\n", \ + __FILE__, __func__, __LINE__); +#else +#define print_got_here() +#endif + +#define AUDIO_BUF_SIZE 2048 + +#define SNDC_CLOSE 0x01 +#define SNDC_WAVE 0x02 +#define SNDC_SETVOLUME 0x03 +#define SNDC_SETPITCH 0x04 +#define SNDC_WAVECONFIRM 0x05 +#define SNDC_TRAINING 0x06 +#define SNDC_FORMATS 0x07 +#define SNDC_CRYPTKEY 0x08 +#define SNDC_WAVEENCRYPT 0x09 +#define SNDC_UDPWAVE 0x0A +#define SNDC_UDPWAVELAST 0x0B +#define SNDC_QUALITYMODE 0x0C int APP_CC sound_init(void); int APP_CC sound_deinit(void); int APP_CC -sound_data_in(struct stream* s, int chan_id, int chan_flags, int length, - int total_length); -int APP_CC sound_get_wait_objs(tbus* objs, int* count, int* timeout); int APP_CC sound_check_wait_objs(void); +int APP_CC +sound_data_in(struct stream* s, int chan_id, int chan_flags, + int length, int total_length); #endif diff --git a/sesman/chansrv/xcommon.c b/sesman/chansrv/xcommon.c new file mode 100644 index 00000000..70b52694 --- /dev/null +++ b/sesman/chansrv/xcommon.c @@ -0,0 +1,187 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2012 + * + * 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. + */ + +#include <X11/Xlib.h> +#include "arch.h" +#include "parse.h" +#include "os_calls.h" +#include "chansrv.h" +#include "log.h" +#include "clipboard.h" +#include "rail.h" + +extern int g_clip_up; /* in clipboard.c */ +extern int g_waiting_for_data_response; /* in clipboard.c */ +extern int g_waiting_for_data_response_time; /* in clipboard.c */ + +extern int g_rail_up; /* in rail.c */ + +Display* g_display = 0; +int g_x_socket = 0; +tbus g_x_wait_obj = 0; +Screen* g_screen = 0; +int g_screen_num = 0; +Window g_root_window = 0; +Atom g_wm_delete_window_atom = 0; +Atom g_wm_protocols_atom = 0; + +/*****************************************************************************/ +static int DEFAULT_CC +xcommon_error_handler(Display* dis, XErrorEvent* xer) +{ + char text[256]; + + XGetErrorText(dis, xer->error_code, text, 255); + LOGM((LOG_LEVEL_ERROR, "X error [%s](%d) opcodes %d/%d " + "resource 0x%lx", text, xer->error_code, + xer->request_code, xer->minor_code, xer->resourceid)); + return 0; +} + +/*****************************************************************************/ +/* The X server had an internal error. This is the last function called. + Do any cleanup that needs to be done on exit, like removing temporary files. + Don't worry about memory leaks */ +static int DEFAULT_CC +xcommon_fatal_handler(Display* dis) +{ + return 0; +} + +/*****************************************************************************/ +/* returns time in miliseconds + this is like g_time2 in os_calls, but not miliseconds since machine was + up, something else + this is a time value similar to what the xserver uses */ +int APP_CC +xcommon_get_local_time(void) +{ + return g_time3(); +} + +/******************************************************************************/ +/* this should be called first */ +int APP_CC +xcommon_init(void) +{ + if (g_display != 0) + { + LOG(10, ("xcommon_init: xcommon_init already called")); + return 0; + } + g_display = XOpenDisplay(0); + if (g_display == 0) + { + LOGM((LOG_LEVEL_ERROR, "xcommon_init: error, XOpenDisplay failed")); + return 1; + } + + LOG(0, ("xcommon_init: connected to display ok")); + + /* setting the error handlers can cause problem when shutting down + chansrv on some xlibs */ + XSetErrorHandler(xcommon_error_handler); + //XSetIOErrorHandler(xcommon_fatal_handler); + + g_x_socket = XConnectionNumber(g_display); + if (g_x_socket == 0) + { + LOGM((LOG_LEVEL_ERROR, "xcommon_init: XConnectionNumber failed")); + return 1; + } + + g_x_wait_obj = g_create_wait_obj_from_socket(g_x_socket, 0); + g_screen_num = DefaultScreen(g_display); + g_screen = ScreenOfDisplay(g_display, g_screen_num); + + g_root_window = RootWindowOfScreen(g_screen); + + g_wm_delete_window_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", 0); + g_wm_protocols_atom = XInternAtom(g_display, "WM_PROTOCOLS", 0); + + return 0; +} + +/*****************************************************************************/ +/* returns error + this is called to get any wait objects for the main loop + timeout can be nil */ +int APP_CC +xcommon_get_wait_objs(tbus* objs, int* count, int* timeout) +{ + int lcount; + + if (((!g_clip_up) && (!g_rail_up)) || (objs == 0) || (count == 0)) + { + LOG(10, ("xcommon_get_wait_objs: nothing to do")); + return 0; + } + lcount = *count; + objs[lcount] = g_x_wait_obj; + lcount++; + *count = lcount; + return 0; +} + +/*****************************************************************************/ +int APP_CC +xcommon_check_wait_objs(void) +{ + XEvent xevent; + int time_diff; + int clip_rv; + int rail_rv; + + if ((!g_clip_up) && (!g_rail_up)) + { + LOG(10, ("xcommon_check_wait_objs: nothing to do")); + return 0; + } + if (g_is_wait_obj_set(g_x_wait_obj)) + { + if (XPending(g_display) < 1) + { + /* something is wrong, should not get here */ + LOGM((LOG_LEVEL_ERROR, "xcommon_check_wait_objs: sck closed")); + return 0; + } + if (g_waiting_for_data_response) + { + time_diff = xcommon_get_local_time() - + g_waiting_for_data_response_time; + if (time_diff > 10000) + { + LOGM((LOG_LEVEL_ERROR, "xcommon_check_wait_objs: warning, " + "waiting for data response too long")); + } + } + while (XPending(g_display) > 0) + { + g_memset(&xevent, 0, sizeof(xevent)); + XNextEvent(g_display, &xevent); + + clip_rv = clipboard_xevent(&xevent); + rail_rv = rail_xevent(&xevent); + if ((clip_rv == 1) && (rail_rv == 1)) + { + LOG(10, ("xcommon_check_wait_objs unknown xevent type %d", xevent.type)); + } + } + } + return 0; +} diff --git a/sesman/chansrv/xcommon.h b/sesman/chansrv/xcommon.h new file mode 100644 index 00000000..d5aa7e46 --- /dev/null +++ b/sesman/chansrv/xcommon.h @@ -0,0 +1,34 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2012 + * + * 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. + */ + +#if !defined(XCOMMON_H) +#define XCOMMON_H + +#include "arch.h" +#include "parse.h" + +int APP_CC +xcommon_get_local_time(void); +int APP_CC +xcommon_init(void); +int APP_CC +xcommon_get_wait_objs(tbus* objs, int* count, int* timeout); +int APP_CC +xcommon_check_wait_objs(void); + +#endif diff --git a/sesman/config.c b/sesman/config.c index d81f7968..a4342676 100644 --- a/sesman/config.c +++ b/sesman/config.c @@ -29,28 +29,11 @@ #include "list.h" #include "file.h" #include "sesman.h" +#include "log.h" extern struct config_sesman* g_cfg; /* in sesman.c */ -/******************************************************************************/ -/** - * - * @brief Reads sesman configuration - * @param s translates the strings "1", "true" and "yes" in 1 (true) and other strings in 0 - * @return 0 on success, 1 on failure - * - */ -static int APP_CC -text2bool(char* s) -{ - if (0 == g_strcasecmp(s, "1") || - 0 == g_strcasecmp(s, "true") || - 0 == g_strcasecmp(s, "yes")) - { - return 1; - } - return 0; -} + /******************************************************************************/ int DEFAULT_CC @@ -66,16 +49,16 @@ config_read(struct config_sesman* cfg) fd = g_file_open(cfg_file); if (-1 == fd) { - if (g_cfg->log.fd >= 0) - { + //if (g_cfg->log.fd >= 0) + //{ /* logging is already active */ - log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "error opening %s in \ + log_message(LOG_LEVEL_ALWAYS, "error opening %s in \ config_read", cfg_file); - } - else - { + //} + //else + //{ g_printf("error opening %s in config_read", cfg_file); - } + //} return 1; } g_memset(cfg, 0, sizeof(struct config_sesman)); @@ -95,7 +78,7 @@ config_read(struct config_sesman* cfg) config_read_rdp_params(fd, cfg, param_n, param_v); /* read logging config */ - config_read_logging(fd, &(cfg->log), param_n, param_v); + // config_read_logging(fd, &(cfg->log), param_n, param_v); /* read security config */ config_read_security(fd, &(cfg->sec), param_n, param_v); @@ -190,7 +173,7 @@ config_read_globals(int file, struct config_sesman* cf, struct list* param_n, return 0; } -/******************************************************************************/ +/****************************************************************************** int DEFAULT_CC config_read_logging(int file, struct log_config* lc, struct list* param_n, struct list* param_v) @@ -201,7 +184,7 @@ config_read_logging(int file, struct log_config* lc, struct list* param_n, list_clear(param_v); list_clear(param_n); - /* setting defaults */ + // setting defaults lc->program_name = g_strdup("sesman"); lc->log_file = 0; lc->fd = 0; @@ -244,7 +227,7 @@ config_read_logging(int file, struct log_config* lc, struct list* param_n, return 0; } - +*/ /******************************************************************************/ int DEFAULT_CC config_read_security(int file, struct config_security* sc, diff --git a/sesman/config.h b/sesman/config.h index 2a4ebd28..73fab38f 100644 --- a/sesman/config.h +++ b/sesman/config.h @@ -45,12 +45,13 @@ #define SESMAN_CFG_RDP_PARAMS "X11rdp" #define SESMAN_CFG_VNC_PARAMS "Xvnc" +/* #define SESMAN_CFG_LOGGING "Logging" #define SESMAN_CFG_LOG_FILE "LogFile" #define SESMAN_CFG_LOG_LEVEL "LogLevel" #define SESMAN_CFG_LOG_ENABLE_SYSLOG "EnableSyslog" #define SESMAN_CFG_LOG_SYSLOG_LEVEL "SyslogLevel" - +*/ #define SESMAN_CFG_SECURITY "Security" #define SESMAN_CFG_SEC_LOGIN_RETRY "MaxLoginRetry" #define SESMAN_CFG_SEC_ALLOW_ROOT "AllowRootLogin" @@ -186,7 +187,7 @@ struct config_sesman * @var log * @brief Log configuration struct */ - struct log_config log; + //struct log_config log; /** * @var sec * @brief Security configuration options struct diff --git a/sesman/env.c b/sesman/env.c index 4bcb22e8..f7abe120 100644 --- a/sesman/env.c +++ b/sesman/env.c @@ -47,7 +47,7 @@ env_check_password_file(char* filename, char* password) fd = g_file_open(filename); if (fd == -1) { - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, + log_message(LOG_LEVEL_WARNING, "can't read vnc password file - %s", filename); return 1; @@ -112,13 +112,13 @@ env_set_user(char* username, char* passwd_file, int display) /* we use auth_file_path as requested */ g_sprintf(passwd_file, g_cfg->auth_file_path, username); } - LOG_DBG(&(g_cfg->log), "pass file: %s", passwd_file); + LOG_DBG("pass file: %s", passwd_file); } } } else { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, + log_message(LOG_LEVEL_ERROR, "error getting user info for user %s", username); } return error; diff --git a/sesman/libscp/Makefile.am b/sesman/libscp/Makefile.am index de8513f8..eaf518a8 100644 --- a/sesman/libscp/Makefile.am +++ b/sesman/libscp/Makefile.am @@ -1,5 +1,5 @@ EXTRA_DIST = libscp_connection.h libscp_commands.h libscp.h libscp_session.h libscp_types_mng.h libscp_v1c_mng.h libscp_vX.h libscp_commands_mng.h libscp_init.h libscp_tcp.h libscp_v0.h libscp_v1s.h libscp_lock.h \ -libscp_types.h libscp_v1c.h libscp_v1s_mng.h +libscp_types.h libscp_v1c.h libscp_v1s_mng.h AM_CFLAGS = \ -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \ @@ -27,5 +27,5 @@ libscp_la_SOURCES = \ libscp_vX.c libscp_la_LIBADD = \ - $(top_srcdir)/common/libcommon.la \ + $(top_builddir)/common/libcommon.la \ -lpthread diff --git a/sesman/libscp/libscp_connection.c b/sesman/libscp/libscp_connection.c index 0b09852e..bf49fb84 100644 --- a/sesman/libscp/libscp_connection.c +++ b/sesman/libscp/libscp_connection.c @@ -27,7 +27,7 @@ #include "libscp_connection.h" -extern struct log_config* s_log; +//extern struct log_config* s_log; struct SCP_CONNECTION* scp_connection_create(int sck) @@ -38,7 +38,7 @@ scp_connection_create(int sck) if (0 == conn) { - log_message(s_log, LOG_LEVEL_WARNING, "[connection:%d] connection create: malloc error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[connection:%d] connection create: malloc error", __LINE__); return 0; } diff --git a/sesman/libscp/libscp_init.c b/sesman/libscp/libscp_init.c index 22497ac2..4c48fb1f 100644 --- a/sesman/libscp/libscp_init.c +++ b/sesman/libscp/libscp_init.c @@ -27,22 +27,24 @@ #include "libscp_init.h" -struct log_config* s_log; +//struct log_config* s_log; /* server API */ int DEFAULT_CC -scp_init(struct log_config* log) +scp_init() { +/* if (0 == log) { return 1; } +*/ - s_log = log; + //s_log = log; scp_lock_init(); - log_message(s_log, LOG_LEVEL_WARNING, "[init:%d] libscp initialized", __LINE__); + log_message(LOG_LEVEL_WARNING, "[init:%d] libscp initialized", __LINE__); return 0; } diff --git a/sesman/libscp/libscp_init.h b/sesman/libscp/libscp_init.h index 5ac0ba02..92dbc659 100644 --- a/sesman/libscp/libscp_init.h +++ b/sesman/libscp/libscp_init.h @@ -42,7 +42,7 @@ * */ int DEFAULT_CC -scp_init(struct log_config* log); +scp_init(); #endif diff --git a/sesman/libscp/libscp_session.c b/sesman/libscp/libscp_session.c index 8ac94d25..3ed5070a 100644 --- a/sesman/libscp/libscp_session.c +++ b/sesman/libscp/libscp_session.c @@ -31,7 +31,7 @@ #include <sys/socket.h> #include <arpa/inet.h> -extern struct log_config* s_log; +//extern struct log_config* s_log; /*******************************************************************/ struct SCP_SESSION* @@ -42,7 +42,7 @@ scp_session_create() s = (struct SCP_SESSION*)g_malloc(sizeof(struct SCP_SESSION), 1); if (0 == s) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] session create: malloc error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] session create: malloc error", __LINE__); return 0; } return s; @@ -60,17 +60,20 @@ scp_session_set_type(struct SCP_SESSION* s, tui8 type) case SCP_SESSION_TYPE_XRDP: s->type = SCP_SESSION_TYPE_XRDP; break; + case SCP_GW_AUTHENTICATION: + s->type = SCP_GW_AUTHENTICATION; + break; case SCP_SESSION_TYPE_MANAGE: s->type = SCP_SESSION_TYPE_MANAGE; s->mng = (struct SCP_MNG_DATA*)g_malloc(sizeof(struct SCP_MNG_DATA), 1); if (NULL == s->mng) { - log_message(s_log, LOG_LEVEL_ERROR, "[session:%d] set_type: internal error", __LINE__); + log_message(LOG_LEVEL_ERROR, "[session:%d] set_type: internal error", __LINE__); return 1; } break; default: - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_type: unknown type", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_type: unknown type", __LINE__); return 1; } return 0; @@ -89,7 +92,7 @@ scp_session_set_version(struct SCP_SESSION* s, tui32 version) s->version = 1; break; default: - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_version: unknown version", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_version: unknown version", __LINE__); return 1; } return 0; @@ -149,7 +152,7 @@ scp_session_set_locale(struct SCP_SESSION* s, char* str) { if (0 == str) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_locale: null locale", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_locale: null locale", __LINE__); s->locale[0]='\0'; return 1; } @@ -164,7 +167,7 @@ scp_session_set_username(struct SCP_SESSION* s, char* str) { if (0 == str) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_username: null username", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_username: null username", __LINE__); return 1; } if (0 != s->username) @@ -174,7 +177,7 @@ scp_session_set_username(struct SCP_SESSION* s, char* str) s->username = g_strdup(str); if (0 == s->username) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_username: strdup error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_username: strdup error", __LINE__); return 1; } return 0; @@ -186,7 +189,7 @@ scp_session_set_password(struct SCP_SESSION* s, char* str) { if (0 == str) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_password: null password", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_password: null password", __LINE__); return 1; } if (0 != s->password) @@ -196,7 +199,7 @@ scp_session_set_password(struct SCP_SESSION* s, char* str) s->password = g_strdup(str); if (0 == s->password) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_password: strdup error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_password: strdup error", __LINE__); return 1; } return 0; @@ -208,7 +211,7 @@ scp_session_set_domain(struct SCP_SESSION* s, char* str) { if (0 == str) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_domain: null domain", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_domain: null domain", __LINE__); return 1; } if (0 != s->domain) @@ -218,7 +221,7 @@ scp_session_set_domain(struct SCP_SESSION* s, char* str) s->domain = g_strdup(str); if (0 == s->domain) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_domain: strdup error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_domain: strdup error", __LINE__); return 1; } return 0; @@ -230,7 +233,7 @@ scp_session_set_program(struct SCP_SESSION* s, char* str) { if (0 == str) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_program: null program", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_program: null program", __LINE__); return 1; } if (0 != s->program) @@ -240,7 +243,7 @@ scp_session_set_program(struct SCP_SESSION* s, char* str) s->program = g_strdup(str); if (0 == s->program) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_program: strdup error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_program: strdup error", __LINE__); return 1; } return 0; @@ -252,7 +255,7 @@ scp_session_set_directory(struct SCP_SESSION* s, char* str) { if (0 == str) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_directory: null directory", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_directory: null directory", __LINE__); return 1; } if (0 != s->directory) @@ -262,7 +265,7 @@ scp_session_set_directory(struct SCP_SESSION* s, char* str) s->directory = g_strdup(str); if (0 == s->directory) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_directory: strdup error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_directory: strdup error", __LINE__); return 1; } return 0; @@ -274,7 +277,7 @@ scp_session_set_client_ip(struct SCP_SESSION* s, char* str) { if (0 == str) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_client_ip: null ip", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_client_ip: null ip", __LINE__); return 1; } if (0 != s->client_ip) @@ -284,7 +287,7 @@ scp_session_set_client_ip(struct SCP_SESSION* s, char* str) s->client_ip = g_strdup(str); if (0 == s->client_ip) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_client_ip: strdup error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_client_ip: strdup error", __LINE__); return 1; } return 0; @@ -296,7 +299,7 @@ scp_session_set_hostname(struct SCP_SESSION* s, char* str) { if (0 == str) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_hostname: null hostname", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_hostname: null hostname", __LINE__); return 1; } if (0 != s->hostname) @@ -306,7 +309,7 @@ scp_session_set_hostname(struct SCP_SESSION* s, char* str) s->hostname = g_strdup(str); if (0 == s->hostname) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_hostname: strdup error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_hostname: strdup error", __LINE__); return 1; } return 0; @@ -318,7 +321,7 @@ scp_session_set_errstr(struct SCP_SESSION* s, char* str) { if (0 == str) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_errstr: null string", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_errstr: null string", __LINE__); return 1; } if (0 != s->errstr) @@ -328,7 +331,7 @@ scp_session_set_errstr(struct SCP_SESSION* s, char* str) s->errstr = g_strdup(str); if (0 == s->errstr) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_errstr: strdup error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_errstr: strdup error", __LINE__); return 1; } return 0; @@ -359,7 +362,7 @@ scp_session_set_addr(struct SCP_SESSION* s, int type, void* addr) ret = inet_pton(AF_INET, addr, &ip4); if (ret == 0) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_addr: invalid address", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_addr: invalid address", __LINE__); inet_pton(AF_INET, "127.0.0.1", &ip4); g_memcpy(&(s->ipv4addr), &(ip4.s_addr), 4); return 1; @@ -375,7 +378,7 @@ scp_session_set_addr(struct SCP_SESSION* s, int type, void* addr) ret = inet_pton(AF_INET6, addr, &ip6); if (ret == 0) { - log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_addr: invalid address", __LINE__); + log_message(LOG_LEVEL_WARNING, "[session:%d] set_addr: invalid address", __LINE__); inet_pton(AF_INET, "::1", &ip6); g_memcpy(s->ipv6addr, &(ip6.s6_addr), 16); return 1; diff --git a/sesman/libscp/libscp_tcp.c b/sesman/libscp/libscp_tcp.c index 6ffa4693..459992fe 100644 --- a/sesman/libscp/libscp_tcp.c +++ b/sesman/libscp/libscp_tcp.c @@ -42,7 +42,7 @@ scp_tcp_force_recv(int sck, char* data, int len) int rcvd; int block; - LOG_DBG(s_log, "scp_tcp_force_recv()"); + LOG_DBG("scp_tcp_force_recv()"); block = scp_lock_fork_critical_section_start(); while (len > 0) @@ -84,7 +84,7 @@ scp_tcp_force_send(int sck, char* data, int len) int sent; int block; - LOG_DBG(s_log, "scp_tcp_force_send()"); + LOG_DBG("scp_tcp_force_send()"); block = scp_lock_fork_critical_section_start(); while (len > 0) diff --git a/sesman/libscp/libscp_types.h b/sesman/libscp/libscp_types.h index 7a54545a..e6521741 100644 --- a/sesman/libscp/libscp_types.h +++ b/sesman/libscp/libscp_types.h @@ -42,6 +42,10 @@ #define SCP_SESSION_TYPE_XVNC 0x00 #define SCP_SESSION_TYPE_XRDP 0x01 #define SCP_SESSION_TYPE_MANAGE 0x02 +/* SCP_GW_AUTHENTICATION can be used when XRDP + sesman act as a gateway + * XRDP sends this command to let sesman verify if the user is allowed + * to use the gateway */ +#define SCP_GW_AUTHENTICATION 0x04 #define SCP_ADDRESS_TYPE_IPV4 0x00 #define SCP_ADDRESS_TYPE_IPV6 0x01 diff --git a/sesman/libscp/libscp_v0.c b/sesman/libscp/libscp_v0.c index d46d6afa..f8b5a9d6 100644 --- a/sesman/libscp/libscp_v0.c +++ b/sesman/libscp/libscp_v0.c @@ -43,7 +43,7 @@ scp_v0c_connect(struct SCP_CONNECTION* c, struct SCP_SESSION* s) init_stream(c->in_s, c->in_s->size); init_stream(c->out_s, c->in_s->size); - LOG_DBG(s_log, "[v0:%d] starting connection", __LINE__); + LOG_DBG("[v0:%d] starting connection", __LINE__); g_tcp_set_non_blocking(c->in_sck); g_tcp_set_no_delay(c->in_sck); s_push_layer(c->out_s, channel_hdr, 8); @@ -59,7 +59,7 @@ scp_v0c_connect(struct SCP_CONNECTION* c, struct SCP_SESSION* s) } else { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); return SCP_CLIENT_STATE_INTERNAL_ERR; } sz = g_strlen(s->username); @@ -83,27 +83,27 @@ scp_v0c_connect(struct SCP_CONNECTION* c, struct SCP_SESSION* s) if (0!=scp_tcp_force_send(c->in_sck, c->out_s->data, c->out_s->end - c->out_s->data)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); return SCP_CLIENT_STATE_NETWORK_ERR; } if (0!=scp_tcp_force_recv(c->in_sck, c->in_s->data, 8)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); return SCP_CLIENT_STATE_NETWORK_ERR; } in_uint32_be(c->in_s, version); if (0 != version) { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: version error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: version error", __LINE__); return SCP_CLIENT_STATE_VERSION_ERR; } in_uint32_be(c->in_s, size); if (size < 14) { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: packet size error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: packet size error", __LINE__); return SCP_CLIENT_STATE_SIZE_ERR; } @@ -111,7 +111,7 @@ scp_v0c_connect(struct SCP_CONNECTION* c, struct SCP_SESSION* s) init_stream(c->in_s, c->in_s->size); if (0!=scp_tcp_force_recv(c->in_sck, c->in_s->data, size - 8)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); return SCP_CLIENT_STATE_NETWORK_ERR; } @@ -119,7 +119,7 @@ scp_v0c_connect(struct SCP_CONNECTION* c, struct SCP_SESSION* s) in_uint16_be(c->in_s, sz); if (3 != sz) { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: sequence error", __LINE__); return SCP_CLIENT_STATE_SEQUENCE_ERR; } @@ -127,14 +127,14 @@ scp_v0c_connect(struct SCP_CONNECTION* c, struct SCP_SESSION* s) in_uint16_be(c->in_s, sz); if (1 != sz) { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: connection denied", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: connection denied", __LINE__); return SCP_CLIENT_STATE_CONNECTION_DENIED; } in_uint16_be(c->in_s, sz); s->display = sz; - LOG_DBG(s_log, "[v0:%d] connection terminated", __LINE__); + LOG_DBG("[v0:%d] connection terminated", __LINE__); return SCP_CLIENT_STATE_END; } @@ -152,20 +152,20 @@ scp_v0s_accept(struct SCP_CONNECTION* c, struct SCP_SESSION** s, int skipVchk) if (!skipVchk) { - LOG_DBG(s_log, "[v0:%d] starting connection", __LINE__); + LOG_DBG("[v0:%d] starting connection", __LINE__); if (0 == scp_tcp_force_recv(c->in_sck, c->in_s->data, 8)) { c->in_s->end = c->in_s->data + 8; in_uint32_be(c->in_s, version); if (version != 0) { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: version error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: version error", __LINE__); return SCP_SERVER_STATE_VERSION_ERR; } } else { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } } @@ -175,7 +175,7 @@ scp_v0s_accept(struct SCP_CONNECTION* c, struct SCP_SESSION** s, int skipVchk) init_stream(c->in_s, 8196); if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, size - 8)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } c->in_s->end = c->in_s->data + (size - 8); @@ -187,7 +187,7 @@ scp_v0s_accept(struct SCP_CONNECTION* c, struct SCP_SESSION** s, int skipVchk) session = scp_session_create(); if (0 == session) { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_INTERNAL_ERR; } @@ -208,7 +208,7 @@ scp_v0s_accept(struct SCP_CONNECTION* c, struct SCP_SESSION** s, int skipVchk) if (0 != scp_session_set_username(session, buf)) { scp_session_destroy(session); - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: error setting username", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: error setting username", __LINE__); return SCP_SERVER_STATE_INTERNAL_ERR; } @@ -219,7 +219,7 @@ scp_v0s_accept(struct SCP_CONNECTION* c, struct SCP_SESSION** s, int skipVchk) if (0 != scp_session_set_password(session, buf)) { scp_session_destroy(session); - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: error setting password", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: error setting password", __LINE__); return SCP_SERVER_STATE_INTERNAL_ERR; } @@ -277,9 +277,45 @@ scp_v0s_accept(struct SCP_CONNECTION* c, struct SCP_SESSION** s, int skipVchk) } } } + else if (code == SCP_GW_AUTHENTICATION) + { + /* g_writeln("Command is SCP_GW_AUTHENTICATION"); */ + session = scp_session_create(); + if (0 == session) + { + /* until syslog merge log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__);*/ + return SCP_SERVER_STATE_INTERNAL_ERR; + } + + scp_session_set_version(session, version); + scp_session_set_type(session, SCP_GW_AUTHENTICATION); + /* reading username */ + in_uint16_be(c->in_s, sz); + buf[sz]='\0'; + in_uint8a(c->in_s, buf, sz); + /* g_writeln("Received user name: %s",buf); */ + if (0 != scp_session_set_username(session, buf)) + { + scp_session_destroy(session); + /* until syslog merge log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: error setting username", __LINE__);*/ + return SCP_SERVER_STATE_INTERNAL_ERR; + } + + /* reading password */ + in_uint16_be(c->in_s, sz); + buf[sz] = '\0'; + in_uint8a(c->in_s, buf, sz); + /* g_writeln("Received password: %s",buf); */ + if (0 != scp_session_set_password(session, buf)) + { + scp_session_destroy(session); + /* until syslog merge log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: error setting password", __LINE__); */ + return SCP_SERVER_STATE_INTERNAL_ERR; + } + } else { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: sequence error", __LINE__); return SCP_SERVER_STATE_SEQUENCE_ERR; } @@ -300,11 +336,11 @@ scp_v0s_allow_connection(struct SCP_CONNECTION* c, SCP_DISPLAY d) if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, c->out_s->end - c->out_s->data)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } - LOG_DBG(s_log, "[v0:%d] connection terminated (allowed)", __LINE__); + LOG_DBG("[v0:%d] connection terminated (allowed)", __LINE__); return SCP_SERVER_STATE_OK; } @@ -315,16 +351,39 @@ scp_v0s_deny_connection(struct SCP_CONNECTION* c) out_uint32_be(c->out_s, 0); /* version */ out_uint32_be(c->out_s, 14); /* size */ out_uint16_be(c->out_s, 3); /* cmd */ - out_uint16_be(c->out_s, 0); /* data */ - out_uint16_be(c->out_s, 0); /* data */ + out_uint16_be(c->out_s, 0); /* data = 0 - means NOT ok*/ + out_uint16_be(c->out_s, 0); /* reserved for display number*/ + s_mark_end(c->out_s); + + if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, c->out_s->end - c->out_s->data)) + { + log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); + return SCP_SERVER_STATE_NETWORK_ERR; + } + + LOG_DBG("[v0:%d] connection terminated (denied)", __LINE__); + return SCP_SERVER_STATE_OK; +} + +/******************************************************************************/ +enum SCP_SERVER_STATES_E +scp_v0s_replyauthentication(struct SCP_CONNECTION* c, unsigned short int value) +{ + out_uint32_be(c->out_s, 0); /* version */ + out_uint32_be(c->out_s, 14); /* size */ + /* cmd SCP_GW_AUTHENTICATION means authentication reply */ + out_uint16_be(c->out_s, SCP_GW_AUTHENTICATION); + out_uint16_be(c->out_s, value); /* reply code */ + out_uint16_be(c->out_s, 0); /* dummy data */ s_mark_end(c->out_s); + /* g_writeln("Total number of bytes that will be sent %d",c->out_s->end - c->out_s->data);*/ if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, c->out_s->end - c->out_s->data)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); + /* until syslog merge log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); */ return SCP_SERVER_STATE_NETWORK_ERR; } - LOG_DBG(s_log, "[v0:%d] connection terminated (denied)", __LINE__); + /* until syslog merge LOG_DBG(s_log, "[v0:%d] connection terminated (scp_v0s_deny_authentication)", __LINE__);*/ return SCP_SERVER_STATE_OK; } diff --git a/sesman/libscp/libscp_v0.h b/sesman/libscp/libscp_v0.h index 7c6fd4b2..92b835f0 100644 --- a/sesman/libscp/libscp_v0.h +++ b/sesman/libscp/libscp_v0.h @@ -73,5 +73,14 @@ scp_v0s_allow_connection(struct SCP_CONNECTION* c, SCP_DISPLAY d); enum SCP_SERVER_STATES_E scp_v0s_deny_connection(struct SCP_CONNECTION* c); +/** + * @brief send reply to an authentication request + * @param c connection descriptor + * @param value the reply code 0 means ok + * @return + */ +enum SCP_SERVER_STATES_E +scp_v0s_replyauthentication(struct SCP_CONNECTION* c, unsigned short int value); + #endif diff --git a/sesman/libscp/libscp_v1c_mng.c b/sesman/libscp/libscp_v1c_mng.c index bb54bc79..88f86f4f 100644 --- a/sesman/libscp/libscp_v1c_mng.c +++ b/sesman/libscp/libscp_v1c_mng.c @@ -30,7 +30,7 @@ #include <stdlib.h> #include <stdio.h> -extern struct log_config* s_log; +//extern struct log_config* s_log; static enum SCP_CLIENT_STATES_E _scp_v1c_mng_check_response(struct SCP_CONNECTION* c, struct SCP_SESSION* s); @@ -91,7 +91,7 @@ scp_v1c_mng_connect(struct SCP_CONNECTION* c, struct SCP_SESSION* s) if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, size)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); return SCP_CLIENT_STATE_NETWORK_ERR; } @@ -127,7 +127,7 @@ scp_v1c_mng_get_session_list(struct SCP_CONNECTION* c, int* scount, if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, size)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); return SCP_CLIENT_STATE_NETWORK_ERR; } @@ -137,42 +137,42 @@ scp_v1c_mng_get_session_list(struct SCP_CONNECTION* c, int* scount, init_stream(c->in_s, c->in_s->size); if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, 8)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); return SCP_CLIENT_STATE_NETWORK_ERR; } in_uint32_be(c->in_s, version); if (version != 1) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: version error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: version error", __LINE__); return SCP_CLIENT_STATE_VERSION_ERR; } in_uint32_be(c->in_s, size); if (size < 12) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: size error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: size error", __LINE__); return SCP_CLIENT_STATE_SIZE_ERR; } init_stream(c->in_s, c->in_s->size); if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, size - 8)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); return SCP_CLIENT_STATE_NETWORK_ERR; } in_uint16_be(c->in_s, cmd); if (cmd != SCP_COMMAND_SET_MANAGE) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: sequence error", __LINE__); return SCP_CLIENT_STATE_SEQUENCE_ERR; } in_uint16_be(c->in_s, cmd); if (cmd != SCP_CMD_MNG_LIST) /* session list */ { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: sequence error", __LINE__); return SCP_CLIENT_STATE_SEQUENCE_ERR; } @@ -188,14 +188,14 @@ scp_v1c_mng_get_session_list(struct SCP_CONNECTION* c, int* scount, (*scount) = sescnt; (*s) = NULL; - LOG_DBG(s_log, "[v1c_mng] end list - no session on TS"); + LOG_DBG("[v1c_mng] end list - no session on TS"); return SCP_CLIENT_STATE_LIST_OK; } ds = g_malloc(sizeof(struct SCP_DISCONNECTED_SESSION) * sescnt, 0); if (ds == 0) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: internal error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: internal error", __LINE__); return SCP_CLIENT_STATE_INTERNAL_ERR; } } @@ -240,7 +240,7 @@ scp_v1c_mng_get_session_list(struct SCP_CONNECTION* c, int* scount, (*scount) = sescnt; (*s) = ds; - LOG_DBG(s_log, "[v1c_mng] end list"); + LOG_DBG("[v1c_mng] end list"); return SCP_CLIENT_STATE_LIST_OK; } @@ -350,14 +350,14 @@ _scp_v1c_mng_check_response(struct SCP_CONNECTION* c, struct SCP_SESSION* s) init_stream(c->in_s, c->in_s->size); if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, 8)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); return SCP_CLIENT_STATE_NETWORK_ERR; } in_uint32_be(c->in_s, version); if (version != 1) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: version error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: version error", __LINE__); return SCP_CLIENT_STATE_VERSION_ERR; } @@ -367,21 +367,21 @@ _scp_v1c_mng_check_response(struct SCP_CONNECTION* c, struct SCP_SESSION* s) /* read the rest of the packet */ if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, size - 8)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); return SCP_CLIENT_STATE_NETWORK_ERR; } in_uint16_be(c->in_s, cmd); if (cmd != SCP_COMMAND_SET_MANAGE) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: sequence error", __LINE__); return SCP_CLIENT_STATE_SEQUENCE_ERR; } in_uint16_be(c->in_s, cmd); if (cmd == SCP_CMD_MNG_LOGIN_ALLOW) /* connection ok */ { - log_message(s_log, LOG_LEVEL_INFO, "[v1c_mng:%d] connection ok", __LINE__); + log_message(LOG_LEVEL_INFO, "[v1c_mng:%d] connection ok", __LINE__); return SCP_CLIENT_STATE_OK; } else if (cmd == SCP_CMD_MNG_LOGIN_DENY) /* connection denied */ @@ -391,10 +391,10 @@ _scp_v1c_mng_check_response(struct SCP_CONNECTION* c, struct SCP_SESSION* s) in_uint8a(c->in_s, buf, dim); scp_session_set_errstr(s, buf); - log_message(s_log, LOG_LEVEL_INFO, "[v1c_mng:%d] connection denied: %s", __LINE__ , s->errstr); + log_message(LOG_LEVEL_INFO, "[v1c_mng:%d] connection denied: %s", __LINE__ , s->errstr); return SCP_CLIENT_STATE_CONNECTION_DENIED; } - log_message(s_log, LOG_LEVEL_WARNING, "[v1c-mng:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1c-mng:%d] connection aborted: sequence error", __LINE__); return SCP_CLIENT_STATE_SEQUENCE_ERR; } diff --git a/sesman/libscp/libscp_v1s.c b/sesman/libscp/libscp_v1s.c index e57a907e..e10af26c 100644 --- a/sesman/libscp/libscp_v1s.c +++ b/sesman/libscp/libscp_v1s.c @@ -30,7 +30,7 @@ #include "libscp_v1s.h" -extern struct log_config* s_log; +//extern struct log_config* s_log; /* server API */ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SESSION** s, int skipVchk) @@ -46,18 +46,18 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES if (!skipVchk) { - if (0==scp_tcp_force_recv(c->in_sck, c->in_s->data, 8)) + if (0 == scp_tcp_force_recv(c->in_sck, c->in_s->data, 8)) { in_uint32_be(c->in_s, version); if (version != 1) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: version error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: version error", __LINE__); return SCP_SERVER_STATE_VERSION_ERR; } } else { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } } @@ -65,14 +65,14 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES in_uint32_be(c->in_s, size); if (size < 12) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__); return SCP_SERVER_STATE_SIZE_ERR; } init_stream(c->in_s, c->in_s->size); if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, (size-8))) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } @@ -82,7 +82,7 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES /* if we are starting a management session */ if (cmdset == SCP_COMMAND_SET_MANAGE) { - log_message(s_log, LOG_LEVEL_DEBUG, "[v1s:%d] requested management connection", __LINE__); + log_message(LOG_LEVEL_DEBUG, "[v1s:%d] requested management connection", __LINE__); /* should return SCP_SERVER_STATE_START_MANAGE */ return scp_v1s_mng_accept(c, s); } @@ -90,7 +90,7 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES /* if we started with resource sharing... */ if (cmdset == SCP_COMMAND_SET_RSR) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); return SCP_SERVER_STATE_SEQUENCE_ERR; } @@ -98,14 +98,14 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES in_uint16_be(c->in_s, cmd); if (cmd != 1) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); return SCP_SERVER_STATE_SEQUENCE_ERR; } session = scp_session_create(); if (0 == session) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error (malloc returned NULL)", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error (malloc returned NULL)", __LINE__); return SCP_SERVER_STATE_INTERNAL_ERR; } scp_session_set_version(session, 1); @@ -114,7 +114,7 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES if ((sz != SCP_SESSION_TYPE_XVNC) && (sz != SCP_SESSION_TYPE_XRDP)) { scp_session_destroy(session); - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: unknown session type", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: unknown session type", __LINE__); return SCP_SERVER_STATE_SESSION_TYPE_ERR; } scp_session_set_type(session, sz); @@ -151,7 +151,7 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES if (0 != scp_session_set_hostname(session, buf)) { scp_session_destroy(session); - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__); return SCP_SERVER_STATE_INTERNAL_ERR; } @@ -162,7 +162,7 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES if (0 != scp_session_set_username(session, buf)) { scp_session_destroy(session); - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__); return SCP_SERVER_STATE_INTERNAL_ERR; } @@ -173,7 +173,7 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES if (0 != scp_session_set_password(session, buf)) { scp_session_destroy(session); - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__); return SCP_SERVER_STATE_INTERNAL_ERR; } @@ -208,7 +208,7 @@ scp_v1s_deny_connection(struct SCP_CONNECTION* c, char* reason) if (0!=scp_tcp_force_send(c->in_sck, c->out_s->data, rlen+14)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } @@ -250,49 +250,49 @@ scp_v1s_request_password(struct SCP_CONNECTION* c, struct SCP_SESSION* s, char* if (0!=scp_tcp_force_send(c->in_sck, c->out_s->data, 14+rlen)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } /* receive password & username */ if (0!=scp_tcp_force_recv(c->in_sck, c->in_s->data, 8)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } in_uint32_be(c->in_s, version); if (version!=1) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: version error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: version error", __LINE__); return SCP_SERVER_STATE_VERSION_ERR; } in_uint32_be(c->in_s, size); if (size<12) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__); return SCP_SERVER_STATE_SIZE_ERR; } init_stream(c->in_s, c->in_s->size); if (0!=scp_tcp_force_recv(c->in_sck, c->in_s->data, (size-8))) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } in_uint16_be(c->in_s, cmdset); if (cmdset != SCP_COMMAND_SET_DEFAULT) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); return SCP_SERVER_STATE_SEQUENCE_ERR; } in_uint16_be(c->in_s, cmd); if (cmd != 4) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); return SCP_SERVER_STATE_SEQUENCE_ERR; } @@ -304,7 +304,7 @@ scp_v1s_request_password(struct SCP_CONNECTION* c, struct SCP_SESSION* s, char* if (0 != scp_session_set_username(s, buf)) { scp_session_destroy(s); - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__); return SCP_SERVER_STATE_INTERNAL_ERR; } @@ -315,7 +315,7 @@ scp_v1s_request_password(struct SCP_CONNECTION* c, struct SCP_SESSION* s, char* if (0 != scp_session_set_password(s, buf)) { scp_session_destroy(s); - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__); return SCP_SERVER_STATE_INTERNAL_ERR; } @@ -356,7 +356,7 @@ scp_v1s_connect_new_session(struct SCP_CONNECTION* c, SCP_DISPLAY d) if (0!=scp_tcp_force_send(c->in_sck, c->out_s->data, 14)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } @@ -410,7 +410,7 @@ scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNEC if (0!=scp_tcp_force_send(c->in_sck, c->out_s->data, size)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } @@ -420,42 +420,42 @@ scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNEC init_stream(c->in_s, c->in_s->size); if (0!=scp_tcp_force_recv(c->in_sck, c->in_s->data, 8)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } in_uint32_be(c->in_s, version); if (version!=1) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: version error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: version error", __LINE__); return SCP_SERVER_STATE_VERSION_ERR; } in_uint32_be(c->in_s, size); if (size<12) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__); return SCP_SERVER_STATE_SIZE_ERR; } init_stream(c->in_s, c->in_s->size); if (0!=scp_tcp_force_recv(c->in_sck, c->in_s->data, (size-8))) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } in_uint16_be(c->in_s, cmd); if (cmd != SCP_COMMAND_SET_DEFAULT) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); return SCP_SERVER_STATE_SEQUENCE_ERR; } in_uint16_be(c->in_s, cmd); if (cmd != 41) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); return SCP_SERVER_STATE_SEQUENCE_ERR; } @@ -542,7 +542,7 @@ scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNEC if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, size)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } } @@ -551,21 +551,21 @@ scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNEC init_stream(c->in_s, c->in_s->size); if (0!=scp_tcp_force_recv(c->in_sck, c->in_s->data, (8))) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } in_uint32_be(c->in_s, version); if (version != 1) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: version error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: version error", __LINE__); return SCP_SERVER_STATE_VERSION_ERR; } in_uint32_be(c->in_s, size); if (size < 12) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__); return SCP_SERVER_STATE_SIZE_ERR; } @@ -573,14 +573,14 @@ scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNEC init_stream(c->in_s, c->in_s->size); if (0!=scp_tcp_force_recv(c->in_sck, c->in_s->data, (size-8))) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } in_uint16_be(c->in_s, cmd); if (cmd != SCP_COMMAND_SET_DEFAULT) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); return SCP_SERVER_STATE_SEQUENCE_ERR; } @@ -603,7 +603,7 @@ scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNEC /* if we got here, the requested sid wasn't one from the list we sent */ /* we should kill the connection */ - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error (no such session in list)", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error (no such session in list)", __LINE__); return SCP_CLIENT_STATE_INTERNAL_ERR; } else if (cmd == 44) @@ -619,7 +619,7 @@ scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNEC else { /* wrong response */ - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); return SCP_SERVER_STATE_SEQUENCE_ERR; } @@ -656,7 +656,7 @@ scp_v1s_reconnect_session(struct SCP_CONNECTION* c, SCP_DISPLAY d) if (0!=scp_tcp_force_send(c->in_sck, c->out_s->data, size)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } diff --git a/sesman/libscp/libscp_v1s_mng.c b/sesman/libscp/libscp_v1s_mng.c index 266c9962..599545ab 100644 --- a/sesman/libscp/libscp_v1s_mng.c +++ b/sesman/libscp/libscp_v1s_mng.c @@ -30,7 +30,7 @@ #include "libscp_v1s_mng.h" -extern struct log_config* s_log; +//extern struct log_config* s_log; static enum SCP_SERVER_STATES_E _scp_v1s_mng_check_response(struct SCP_CONNECTION* c, struct SCP_SESSION* s); @@ -259,7 +259,7 @@ scp_v1s_mng_list_sessions(struct SCP_CONNECTION* c, struct SCP_SESSION* s, if (0!=scp_tcp_force_send(c->in_sck, c->out_s->data, size)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } } @@ -279,14 +279,14 @@ _scp_v1s_mng_check_response(struct SCP_CONNECTION* c, struct SCP_SESSION* s) init_stream(c->in_s, c->in_s->size); if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, 8)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } in_uint32_be(c->in_s, version); if (version != 1) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: version error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: version error", __LINE__); return SCP_SERVER_STATE_VERSION_ERR; } @@ -296,21 +296,21 @@ _scp_v1s_mng_check_response(struct SCP_CONNECTION* c, struct SCP_SESSION* s) /* read the rest of the packet */ if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, size - 8)) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: network error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } in_uint16_be(c->in_s, cmd); if (cmd != SCP_COMMAND_SET_MANAGE) { - log_message(s_log, LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: sequence error", __LINE__); return SCP_SERVER_STATE_SEQUENCE_ERR; } in_uint16_be(c->in_s, cmd); if (cmd == SCP_CMD_MNG_LIST_REQ) /* request session list */ { - log_message(s_log, LOG_LEVEL_INFO, "[v1s_mng:%d] request session list", __LINE__); + log_message(LOG_LEVEL_INFO, "[v1s_mng:%d] request session list", __LINE__); return SCP_SERVER_STATE_MNG_LISTREQ; } else if (cmd == SCP_CMD_MNG_ACTION) /* execute an action */ @@ -320,7 +320,7 @@ _scp_v1s_mng_check_response(struct SCP_CONNECTION* c, struct SCP_SESSION* s) in_uint8a(c->in_s, buf, dim); scp_session_set_errstr(s, buf);*/ - log_message(s_log, LOG_LEVEL_INFO, "[v1s_mng:%d] action request", __LINE__); + log_message(LOG_LEVEL_INFO, "[v1s_mng:%d] action request", __LINE__); return SCP_SERVER_STATE_MNG_ACTION; } /* else if (cmd == 20) / * password change * / @@ -334,7 +334,7 @@ _scp_v1s_mng_check_response(struct SCP_CONNECTION* c, struct SCP_SESSION* s) return SCP_SERVER_STATE_SESSION_LIST; }*/ - log_message(s_log, LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: sequence error", __LINE__); + log_message(LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: sequence error", __LINE__); return SCP_SERVER_STATE_SEQUENCE_ERR; } diff --git a/sesman/lock.c b/sesman/lock.c index d5a91af6..83023cba 100644 --- a/sesman/lock.c +++ b/sesman/lock.c @@ -55,7 +55,7 @@ void APP_CC lock_chain_acquire(void) { /* lock the chain */ - LOG_DBG(&(g_cfg->log), "lock_chain_acquire()"); + LOG_DBG("lock_chain_acquire()"); tc_mutex_lock(g_lock_chain); } @@ -64,7 +64,7 @@ void APP_CC lock_chain_release(void) { /* unlock the chain */ - LOG_DBG(&(g_cfg->log), "lock_chain_release()"); + LOG_DBG("lock_chain_release()"); tc_mutex_unlock(g_lock_chain); } @@ -73,7 +73,7 @@ void APP_CC lock_socket_acquire(void) { /* lock socket variable */ - LOG_DBG(&(g_cfg->log), "lock_socket_acquire()"); + LOG_DBG("lock_socket_acquire()"); tc_sem_dec(g_lock_socket); } @@ -82,7 +82,7 @@ void APP_CC lock_socket_release(void) { /* unlock socket variable */ - LOG_DBG(&(g_cfg->log), "lock_socket_release()"); + LOG_DBG("lock_socket_release()"); tc_sem_inc(g_lock_socket); } @@ -91,7 +91,7 @@ void APP_CC lock_sync_acquire(void) { /* lock sync variable */ - LOG_DBG(&(g_cfg->log), "lock_sync_acquire()"); + LOG_DBG("lock_sync_acquire()"); tc_mutex_lock(g_sync_mutex); } @@ -100,7 +100,7 @@ void APP_CC lock_sync_release(void) { /* unlock socket variable */ - LOG_DBG(&(g_cfg->log), "lock_sync_release()"); + LOG_DBG("lock_sync_release()"); tc_mutex_unlock(g_sync_mutex); } @@ -109,7 +109,7 @@ void APP_CC lock_sync_sem_acquire(void) { /* dec sem */ - LOG_DBG(&(g_cfg->log), "lock_sync_sem_acquire()"); + LOG_DBG("lock_sync_sem_acquire()"); tc_sem_dec(g_sync_sem); } @@ -118,6 +118,6 @@ void APP_CC lock_sync_sem_release(void) { /* inc sem */ - LOG_DBG(&(g_cfg->log), "lock_sync_sem_release()"); + LOG_DBG("lock_sync_sem_release()"); tc_sem_inc(g_sync_sem); } diff --git a/sesman/scp.c b/sesman/scp.c index 439c046c..bbe495ea 100644 --- a/sesman/scp.c +++ b/sesman/scp.c @@ -43,7 +43,7 @@ scp_process_start(void* sck) /* making a local copy of the socket (it's on the stack) */ /* probably this is just paranoia */ scon.in_sck = g_thread_sck; - LOG_DBG(&(g_cfg->log), "started scp thread on socket %d", scon.in_sck); + LOG_DBG("started scp thread on socket %d", scon.in_sck); /* unlocking g_thread_sck */ lock_socket_release(); @@ -60,40 +60,40 @@ scp_process_start(void* sck) if (sdata->version == 0) { /* starts processing an scp v0 connection */ - LOG_DBG(&(g_cfg->log), "accept ok, go on with scp v0\n",0); + LOG_DBG("accept ok, go on with scp v0\n",0); scp_v0_process(&scon, sdata); } else { - LOG_DBG(&(g_cfg->log), "accept ok, go on with scp v1\n",0); - /*LOG_DBG(&(g_cfg->log), "user: %s\npass: %s",sdata->username, sdata->password);*/ + LOG_DBG("accept ok, go on with scp v1\n",0); + /*LOG_DBG("user: %s\npass: %s",sdata->username, sdata->password);*/ scp_v1_process(&scon, sdata); } break; case SCP_SERVER_STATE_START_MANAGE: /* starting a management session */ - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, + log_message(LOG_LEVEL_WARNING, "starting a sesman management session..."); scp_v1_mng_process(&scon, sdata); break; case SCP_SERVER_STATE_VERSION_ERR: /* an unknown scp version was requested, so we shut down the */ /* connection (and log the fact) */ - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, + log_message(LOG_LEVEL_WARNING, "unknown protocol version specified. connection refused."); break; case SCP_SERVER_STATE_NETWORK_ERR: - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, "libscp network error."); + log_message(LOG_LEVEL_WARNING, "libscp network error."); break; case SCP_SERVER_STATE_SEQUENCE_ERR: - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, "libscp sequence error."); + log_message(LOG_LEVEL_WARNING, "libscp sequence error."); break; case SCP_SERVER_STATE_INTERNAL_ERR: /* internal error occurred (eg. malloc() error, ecc.) */ - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "libscp internal error occurred."); + log_message(LOG_LEVEL_ERROR, "libscp internal error occurred."); break; default: - log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "unknown return from scp_vXs_accept()"); + log_message(LOG_LEVEL_ALWAYS, "unknown return from scp_vXs_accept()"); } g_tcp_close(scon.in_sck); free_stream(scon.in_s); diff --git a/sesman/scp_v0.c b/sesman/scp_v0.c index 886aaa29..092585cf 100644 --- a/sesman/scp_v0.c +++ b/sesman/scp_v0.c @@ -40,8 +40,7 @@ scp_v0_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) struct session_item* s_item; data = auth_userpass(s->username, s->password); - - if (data) + if (s->type == SCP_GW_AUTHENTICATION) { s_item = session_get_bydata(s->username, s->width, s->height, s->bpp, s->type); @@ -60,42 +59,51 @@ scp_v0_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) display = s_item->display; if (0 != s->client_ip) { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "++ reconnected session: username %s, display :%d.0, session_pid %d, ip %s", s->username, display, s_item->pid, s->client_ip); + log_message( LOG_LEVEL_INFO, "++ reconnected session: username %s, " + "display :%d.0, session_pid %d, ip %s", + s->username, display, s_item->pid, s->client_ip); } else { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "++ reconnected session: username %s, display :%d.0, session_pid %d", s->username, display, s_item->pid); + log_message(LOG_LEVEL_INFO, "++ reconnected session: username %s, " + "display :%d.0, session_pid %d", s->username, display, + s_item->pid); } + session_reconnect(display, s->username); auth_end(data); /* don't set data to null here */ } else { - LOG_DBG(&(g_cfg->log), "pre auth"); + LOG_DBG("pre auth"); if (1 == access_login_allowed(s->username)) { if (0 != s->client_ip) { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "++ created session (access granted): username %s, ip %s", s->username, s->client_ip); + log_message(LOG_LEVEL_INFO, "++ created session (access granted): " + "username %s, ip %s", s->username, s->client_ip); } else { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "++ created session (access granted): username %s", s->username); + log_message(LOG_LEVEL_INFO, "++ created session (access granted): " + "username %s", s->username); } if (SCP_SESSION_TYPE_XVNC == s->type) { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "starting Xvnc session..."); + log_message( LOG_LEVEL_INFO, "starting Xvnc session..."); display = session_start(s->width, s->height, s->bpp, s->username, s->password, data, SESMAN_SESSION_TYPE_XVNC, - s->domain, s->program, s->directory, s->client_ip); + s->domain, s->program, s->directory, + s->client_ip); } else { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "starting X11rdp session..."); + log_message(LOG_LEVEL_INFO, "starting X11rdp session..."); display = session_start(s->width, s->height, s->bpp, s->username, s->password, data, SESMAN_SESSION_TYPE_XRDP, - s->domain, s->program, s->directory, s->client_ip); + s->domain, s->program, s->directory, + s->client_ip); } } else @@ -118,4 +126,3 @@ scp_v0_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) scp_v0s_deny_connection(c); } } - diff --git a/sesman/scp_v1.c b/sesman/scp_v1.c index beb1c36b..d83dd7bc 100644 --- a/sesman/scp_v1.c +++ b/sesman/scp_v1.c @@ -58,9 +58,11 @@ scp_v1_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) while ((!data) && ((retries == 0) || (current_try > 0))) { - LOG_DBG(&(g_cfg->log), "data %d - retry %d - currenttry %d - expr %d", data, retries, current_try, ((!data) && ((retries==0) || (current_try>0)))); + LOG_DBG("data %d - retry %d - currenttry %d - expr %d", + data, retries, current_try, + ((!data) && ((retries == 0) || (current_try > 0)))); - e=scp_v1s_request_password(c,s,"Wrong username and/or password"); + e = scp_v1s_request_password(c, s, "Wrong username and/or password"); switch (e) { @@ -85,7 +87,7 @@ scp_v1_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) if (!data) { scp_v1s_deny_connection(c, "Login failed"); - log_message(&(g_cfg->log), LOG_LEVEL_INFO, + log_message( LOG_LEVEL_INFO, "Login failed for user %s. Connection terminated", s->username); scp_session_destroy(s); return; @@ -95,7 +97,7 @@ scp_v1_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) if (0 == access_login_allowed(s->username)) { scp_v1s_deny_connection(c, "Access to Terminal Server not allowed."); - log_message(&(g_cfg->log), LOG_LEVEL_INFO, + log_message(LOG_LEVEL_INFO, "User %s not allowed on TS. Connection terminated", s->username); scp_session_destroy(s); return; @@ -116,24 +118,26 @@ scp_v1_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) if (scount == 0) { /* no disconnected sessions - start a new one */ + log_message(LOG_LEVEL_DEBUG,"No disconnected sessions for this user" + "- we create a new one"); if (0 != s->client_ip) { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "++ created session (access granted): username %s, ip %s", s->username, s->client_ip); + log_message(LOG_LEVEL_INFO, "++ created session (access granted): username %s, ip %s", s->username, s->client_ip); } else { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "++ created session (access granted): username %s", s->username); + log_message(LOG_LEVEL_INFO, "++ created session (access granted): username %s", s->username); } if (SCP_SESSION_TYPE_XVNC == s->type) { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "starting Xvnc session..."); + log_message(LOG_LEVEL_INFO, "starting Xvnc session..."); display = session_start(s->width, s->height, s->bpp, s->username, s->password, data, SESMAN_SESSION_TYPE_XVNC, s->domain, s->program, s->directory, s->client_ip); } else { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "starting X11rdp session..."); + log_message(LOG_LEVEL_INFO, "starting X11rdp session..."); display = session_start(s->width, s->height, s->bpp, s->username, s->password, data, SESMAN_SESSION_TYPE_XRDP, s->domain, s->program, s->directory, s->client_ip); @@ -161,28 +165,28 @@ scp_v1_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) /*case SCP_SERVER_STATE_FORCE_NEW:*/ /* we should check for MaxSessions */ case SCP_SERVER_STATE_SELECTION_CANCEL: - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "Connection cancelled after session listing"); + log_message( LOG_LEVEL_INFO, "Connection cancelled after session listing"); break; case SCP_SERVER_STATE_OK: /* ok, reconnecting... */ sitem=session_get_bypid(sid); - if (0==sitem) + if (0 == sitem) { - e=scp_v1s_connection_error(c, "Internal error"); - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "Cannot find session item on the chain"); + e = scp_v1s_connection_error(c, "Internal error"); + log_message(LOG_LEVEL_INFO, "Cannot find session item on the chain"); } else { - display=sitem->display; + display = sitem->display; /*e=scp_v1s_reconnect_session(c, sitem, display);*/ e=scp_v1s_reconnect_session(c, display); if (0 != s->client_ip) { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "++ reconnected session: username %s, display :%d.0, session_pid %d, ip %s", s->username, display, sitem->pid, s->client_ip); + log_message(LOG_LEVEL_INFO, "++ reconnected session: username %s, display :%d.0, session_pid %d, ip %s", s->username, display, sitem->pid, s->client_ip); } else { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "++ reconnected session: username %s, display :%d.0, session_pid %d", s->username, display, sitem->pid); + log_message(LOG_LEVEL_INFO, "++ reconnected session: username %s, display :%d.0, session_pid %d", s->username, display, sitem->pid); } g_free(sitem); } @@ -211,27 +215,27 @@ static void parseCommonStates(enum SCP_SERVER_STATES_E e, char* f) switch (e) { case SCP_SERVER_STATE_VERSION_ERR: - LOG_DBG(&(g_cfg->log), "version error") + LOG_DBG("version error") case SCP_SERVER_STATE_SIZE_ERR: /* an unknown scp version was requested, so we shut down the */ /* connection (and log the fact) */ - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, + log_message(LOG_LEVEL_WARNING, "protocol violation. connection closed."); break; case SCP_SERVER_STATE_NETWORK_ERR: - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, "libscp network error."); + log_message(LOG_LEVEL_WARNING, "libscp network error."); break; case SCP_SERVER_STATE_SEQUENCE_ERR: - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, "libscp sequence error."); + log_message(LOG_LEVEL_WARNING, "libscp sequence error."); break; case SCP_SERVER_STATE_INTERNAL_ERR: /* internal error occurred (eg. malloc() error, ecc.) */ - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "libscp internal error occurred."); + log_message(LOG_LEVEL_ERROR, "libscp internal error occurred."); break; default: /* dummy: scp_v1s_request_password won't generate any other */ /* error other than the ones before */ - log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "unknown return from %s", f); + log_message(LOG_LEVEL_ALWAYS, "unknown return from %s", f); break; } } diff --git a/sesman/scp_v1_mng.c b/sesman/scp_v1_mng.c index a1773225..e4d97b77 100644 --- a/sesman/scp_v1_mng.c +++ b/sesman/scp_v1_mng.c @@ -49,7 +49,7 @@ scp_v1_mng_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) if (!data) { scp_v1s_mng_deny_connection(c, "Login failed"); - log_message(&(g_cfg->log), LOG_LEVEL_INFO, + log_message(LOG_LEVEL_INFO, "[MNG] Login failed for user %s. Connection terminated", s->username); scp_session_destroy(s); auth_end(data); @@ -60,7 +60,7 @@ scp_v1_mng_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) if (0 == access_login_mng_allowed(s->username)) { scp_v1s_mng_deny_connection(c, "Access to Terminal Server not allowed."); - log_message(&(g_cfg->log), LOG_LEVEL_INFO, + log_message(LOG_LEVEL_INFO, "[MNG] User %s not allowed on TS. Connection terminated", s->username); scp_session_destroy(s); auth_end(data); @@ -75,18 +75,18 @@ scp_v1_mng_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) switch (e) { case SCP_SERVER_STATE_MNG_ACTION: - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "Connection cancelled after session listing"); + log_message(LOG_LEVEL_INFO, "Connection cancelled after session listing"); break; case SCP_SERVER_STATE_MNG_LISTREQ: /* list disconnected sessions */ slist = session_get_byuser(NULL, &scount, SESMAN_SESSION_STATUS_ALL); - LOG_DBG(&(g_cfg->log), "sessions on TS: %d (slist: %x)", scount, slist); + LOG_DBG("sessions on TS: %d (slist: %x)", scount, slist); if (0 == slist) { // e=scp_v1s_connection_error(c, "Internal error"); - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "No sessions on Terminal Server"); + log_message(LOG_LEVEL_INFO, "No sessions on Terminal Server"); end = 0; } else @@ -114,27 +114,27 @@ static void parseCommonStates(enum SCP_SERVER_STATES_E e, char* f) switch (e) { case SCP_SERVER_STATE_VERSION_ERR: - LOG_DBG(&(g_cfg->log), "version error") + LOG_DBG("version error") case SCP_SERVER_STATE_SIZE_ERR: /* an unknown scp version was requested, so we shut down the */ /* connection (and log the fact) */ - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, + log_message(LOG_LEVEL_WARNING, "protocol violation. connection closed."); break; case SCP_SERVER_STATE_NETWORK_ERR: - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, "libscp network error."); + log_message(LOG_LEVEL_WARNING, "libscp network error."); break; case SCP_SERVER_STATE_SEQUENCE_ERR: - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, "libscp sequence error."); + log_message(LOG_LEVEL_WARNING, "libscp sequence error."); break; case SCP_SERVER_STATE_INTERNAL_ERR: /* internal error occurred (eg. malloc() error, ecc.) */ - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "libscp internal error occurred."); + log_message(LOG_LEVEL_ERROR, "libscp internal error occurred."); break; default: /* dummy: scp_v1s_request_password won't generate any other */ /* error other than the ones before */ - log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "unknown return from %s", f); + log_message(LOG_LEVEL_ALWAYS, "unknown return from %s", f); break; } } diff --git a/sesman/sesman.c b/sesman/sesman.c index 5a230417..b882c49d 100644 --- a/sesman/sesman.c +++ b/sesman/sesman.c @@ -54,7 +54,7 @@ sesman_main_loop(void) tbus robjs[8]; /*main program loop*/ - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "listening..."); + log_message(LOG_LEVEL_INFO, "listening..."); g_sck = g_tcp_socket(); g_tcp_set_non_blocking(g_sck); error = scp_tcp_bind(g_sck, g_cfg->listen_address, g_cfg->listen_port); @@ -103,7 +103,7 @@ sesman_main_loop(void) else { /* we've got a connection, so we pass it to scp code */ - LOG_DBG(&(g_cfg->log), "new connection"); + LOG_DBG("new connection"); thread_scp_start(in_sck); /* todo, do we have to wait here ? */ } @@ -113,13 +113,13 @@ sesman_main_loop(void) } else { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "listen error %d (%s)", + log_message(LOG_LEVEL_ERROR, "listen error %d (%s)", g_get_errno(), g_get_strerror()); } } else { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "bind error on " + log_message(LOG_LEVEL_ERROR, "bind error on " "port '%s': %d (%s)", g_cfg->listen_port, g_get_errno(), g_get_strerror()); } @@ -131,12 +131,13 @@ int DEFAULT_CC main(int argc, char** argv) { int fd; - int error; + enum logReturns error; int daemon = 1; int pid; char pid_s[8]; char text[256]; char pid_file[256]; + char cfg_file[256]; g_init("xrdp-sesman"); g_snprintf(pid_file, 255, "%s/xrdp-sesman.pid", XRDP_PID_PATH); @@ -242,7 +243,7 @@ main(int argc, char** argv) g_deinit(); g_exit(1); } - g_cfg->log.fd = -1; /* don't use logging before reading its config */ + //g_cfg->log.fd = -1; /* don't use logging before reading its config */ if (0 != config_read(g_cfg)) { g_printf("error reading config: %s\nquitting.\n", g_get_strerror()); @@ -250,18 +251,21 @@ main(int argc, char** argv) g_exit(1); } + g_snprintf(cfg_file,255,"%s/sesman.ini",XRDP_CFG_PATH); + /* starting logging subsystem */ - error = log_start(&(g_cfg->log)); + error = log_start(cfg_file,"XRDP-sesman"); if (error != LOG_STARTUP_OK) { switch (error) { case LOG_ERROR_MALLOC: - g_printf("error on malloc. cannot start logging. quitting.\n"); + g_writeln("error on malloc. cannot start logging. quitting."); break; case LOG_ERROR_FILE_OPEN: - g_printf("error opening log file [%s]. quitting.\n", g_cfg->log.log_file); + g_writeln("error opening log file [%s]. quitting.", + getLogFile(text, 255)); break; } g_deinit(); @@ -269,7 +273,7 @@ main(int argc, char** argv) } /* libscp initialization */ - scp_init(&(g_cfg->log)); + scp_init(); if (daemon) { @@ -317,10 +321,10 @@ main(int argc, char** argv) fd = g_file_open(pid_file); if (-1 == fd) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, + log_message(LOG_LEVEL_ERROR, "error opening pid file[%s]: %s", pid_file, g_get_strerror()); - log_end(&(g_cfg->log)); + log_end(); g_deinit(); g_exit(1); } @@ -330,7 +334,7 @@ main(int argc, char** argv) } /* start program main loop */ - log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, + log_message(LOG_LEVEL_ALWAYS, "starting sesman with pid %d", g_pid); /* make sure the /tmp/.X11-unix directory exist */ @@ -358,10 +362,9 @@ main(int argc, char** argv) if (!daemon) { - log_end(&(g_cfg->log)); + log_end(); } g_deinit(); return 0; } - diff --git a/sesman/sesman.ini b/sesman/sesman.ini index 1d1d16bf..7f194074 100644 --- a/sesman/sesman.ini +++ b/sesman/sesman.ini @@ -19,9 +19,9 @@ IdleTimeLimit=0 DisconnectedTimeLimit=0 [Logging] -LogFile=/var/log/xrdp-sesman.log +LogFile=xrdp-sesman.log LogLevel=DEBUG -EnableSyslog=0 +EnableSyslog=1 SyslogLevel=DEBUG #[X11rdp] diff --git a/sesman/session.c b/sesman/session.c index 81484b80..46037187 100644 --- a/sesman/session.c +++ b/sesman/session.c @@ -60,6 +60,40 @@ static char* g_sync_client_ip; static tbus g_sync_data; static tui8 g_sync_type; static int g_sync_result; +static int g_sync_cmd; + +/** + * Creates a string consisting of all parameters that is hosted in the param list + * @param self + * @param outstr, allocate this buffer before you use this function + * @param len the allocated len for outstr + * @return + */ +char* APP_CC +dumpItemsToString(struct list* self, char *outstr, int len) +{ + g_memset(outstr,0,len); + int index; + tbus item; + int totalLen= 0; + + if (self->count == 0) + { + g_writeln("List is empty"); + } + for (index = 0; index < self->count; index++) + { + /* +1 = one space*/ + totalLen = totalLen + g_strlen((char*)list_get_item(self, index))+1; + if(len>totalLen) + { + g_strcat(outstr,(char*)list_get_item(self, index)); + g_strcat(outstr," "); + } + } + return outstr ; +} + /******************************************************************************/ struct session_item* DEFAULT_CC @@ -267,7 +301,7 @@ x_server_running(int display) /******************************************************************************/ static void DEFAULT_CC -session_start_sessvc(int xpid, int wmpid, long data) +session_start_sessvc(int xpid, int wmpid, long data, char* username, int display) { struct list * sessvc_params = (struct list *)NULL; char wmpid_str[25]; @@ -283,7 +317,7 @@ session_start_sessvc(int xpid, int wmpid, long data) /* new style waiting for clients */ g_sprintf(wmpid_str, "%d", wmpid); g_sprintf(xpid_str, "%d", xpid); - log_message(&(g_cfg->log), LOG_LEVEL_INFO, + log_message(LOG_LEVEL_INFO, "starting xrdp-sessvc - xpid=%s - wmpid=%s", xpid_str, wmpid_str); @@ -298,23 +332,25 @@ session_start_sessvc(int xpid, int wmpid, long data) list_add_item(sessvc_params, (long)g_strdup(wmpid_str)); list_add_item(sessvc_params, 0); /* mandatory */ + env_set_user(username, 0, display); + /* executing sessvc */ g_execvp(exe_path, ((char**)sessvc_params->items)); /* should not get here */ - log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, + log_message(LOG_LEVEL_ALWAYS, "error starting xrdp-sessvc - pid %d - xpid=%s - wmpid=%s", g_getpid(), xpid_str, wmpid_str); /* logging parameters */ /* no problem calling strerror for thread safety: other threads are blocked */ - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, "errno: %d, description: %s", + log_message(LOG_LEVEL_DEBUG, "errno: %d, description: %s", errno, g_get_strerror()); - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, "execve parameter list:"); + log_message(LOG_LEVEL_DEBUG, "execve parameter list:"); for (i = 0; i < (sessvc_params->count); i++) { - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, " argv[%d] = %s", i, + log_message(LOG_LEVEL_DEBUG, " argv[%d] = %s", i, (char*)list_get_item(sessvc_params, i)); } list_delete(sessvc_params); @@ -372,7 +408,7 @@ session_get_aval_display_from_chain(void) display++; } lock_chain_release(); - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "X server -- no display in range is available"); + log_message(LOG_LEVEL_ERROR, "X server -- no display in range is available"); return 0; } @@ -391,7 +427,7 @@ wait_for_xserver(int display) i++; if (i > 60) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, + log_message(LOG_LEVEL_ERROR, "X server for display %d startup timeout", display); break; @@ -474,6 +510,7 @@ session_start_fork(int width, int height, int bpp, char* username, struct list * xserver_params = (struct list *)NULL; time_t ltime; struct tm stime; + char execvpparams[2048]; /* initialize (zero out) local variables: */ g_memset(<ime,0,sizeof(time_t)); @@ -489,7 +526,7 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 260.0] In session_star /* check to limit concurrent sessions */ if (g_session_count >= g_cfg->sess.max_sessions) { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "max concurrent session limit " + log_message(LOG_LEVEL_INFO, "max concurrent session limit " "exceeded. login for user %s denied", username); return 0; } @@ -497,7 +534,7 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 260.0] In session_star temp = (struct session_chain*)g_malloc(sizeof(struct session_chain), 0); if (temp == 0) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "cannot create new chain " + log_message(LOG_LEVEL_ERROR, "cannot create new chain " "element - user %s", username); return 0; } @@ -505,7 +542,7 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 260.0] In session_star if (temp->item == 0) { g_free(temp); - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "cannot create new session " + log_message(LOG_LEVEL_ERROR, "cannot create new session " "item - user %s", username); return 0; } @@ -599,7 +636,7 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 260.0] In session_star if (program[0] != 0) { g_execlp3(program, program, 0); - log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, + log_message(LOG_LEVEL_ALWAYS, "error starting program %s for user %s - pid %d", program, username, g_getpid()); } @@ -611,16 +648,16 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 260.0] In session_star if (g_file_exist(text)) { g_execlp3(text, g_cfg->user_wm, 0); - log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS,"error starting user " + log_message(LOG_LEVEL_ALWAYS,"error starting user " "wm for user %s - pid %d", username, g_getpid()); /* logging parameters */ - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, "errno: %d, " + log_message(LOG_LEVEL_DEBUG, "errno: %d, " "description: %s", errno, g_get_strerror()); - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG,"execlp3 parameter " + log_message(LOG_LEVEL_DEBUG,"execlp3 parameter " "list:"); - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, " argv[0] = %s", + log_message(LOG_LEVEL_DEBUG, " argv[0] = %s", text); - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, " argv[1] = %s", + log_message(LOG_LEVEL_DEBUG, " argv[1] = %s", g_cfg->user_wm); } } @@ -629,25 +666,25 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 260.0] In session_star g_sprintf(text, "%s/%s", XRDP_CFG_PATH, g_cfg->default_wm); g_execlp3(text, g_cfg->default_wm, 0); - log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS,"error starting default " + log_message( LOG_LEVEL_ALWAYS,"error starting default " "wm for user %s - pid %d", username, g_getpid()); /* logging parameters */ - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, "errno: %d, description: " + log_message( LOG_LEVEL_DEBUG, "errno: %d, description: " "%s", errno, g_get_strerror()); - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG,"execlp3 parameter list:"); - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, " argv[0] = %s", + log_message(LOG_LEVEL_DEBUG,"execlp3 parameter list:"); + log_message(LOG_LEVEL_DEBUG, " argv[0] = %s", text); - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, " argv[1] = %s", + log_message(LOG_LEVEL_DEBUG, " argv[1] = %s", g_cfg->default_wm); /* still a problem starting window manager just start xterm */ g_execlp3("xterm", "xterm", 0); /* should not get here */ - log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS,"error starting xterm " + log_message(LOG_LEVEL_ALWAYS,"error starting xterm " "for user %s - pid %d", username, g_getpid()); /* logging parameters */ - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, "errno: %d, description: " + log_message(LOG_LEVEL_DEBUG, "errno: %d, description: " "%s", errno, g_get_strerror()); } else @@ -656,7 +693,7 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 260.0] In session_star log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "another Xserver is " "already active on display %d", display); } - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG,"aborting connection..."); + log_message(LOG_LEVEL_DEBUG,"aborting connection..."); g_exit(0); } else /* parent (child sesman) */ @@ -691,6 +728,7 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 260.0] In session_star /* make sure it ends with a zero */ list_add_item(xserver_params, 0); pp1 = (char**)xserver_params->items; + log_message(LOG_LEVEL_INFO,"Xvnc start:%s",dumpItemsToString(xserver_params, execvpparams, 2048)); g_execvp("Xvnc", pp1); } else if (type == SESMAN_SESSION_TYPE_XRDP) @@ -743,24 +781,24 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 260.0] In session_star } else { - log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "bad session type - " + log_message(LOG_LEVEL_ALWAYS, "bad session type - " "user %s - pid %d", username, g_getpid()); g_exit(1); } /* should not get here */ - log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "error starting X server " + log_message(LOG_LEVEL_ALWAYS, "error starting X server " "- user %s - pid %d", username, g_getpid()); /* logging parameters */ - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, "errno: %d, description: " + log_message(LOG_LEVEL_DEBUG, "errno: %d, description: " "%s", errno, g_get_strerror()); - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, "execve parameter list: " + log_message(LOG_LEVEL_DEBUG, "execve parameter list size: " "%d", (xserver_params)->count); for (i=0; i<(xserver_params->count); i++) { - log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, " argv[%d] = %s", + log_message(LOG_LEVEL_DEBUG, " argv[%d] = %s", i, (char*)list_get_item(xserver_params, i)); } list_delete(xserver_params); @@ -777,7 +815,7 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 260.0] In session_star g_snprintf(text, 255, ":%d.0", display); g_setenv("DISPLAY", text, 1); /* new style waiting for clients */ - session_start_sessvc(xpid, wmpid, data); + session_start_sessvc(xpid, wmpid, data, username, display); } } } @@ -813,6 +851,31 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 260.0] In session_star } /******************************************************************************/ +/* called with the main thread */ +static int APP_CC +session_reconnect_fork(int display, char* username) +{ + int pid; + char text[256]; + + pid = g_fork(); + if (pid == -1) + { + } + else if (pid == 0) + { + env_set_user(username, 0, display); + g_snprintf(text, 255, "%s/%s", XRDP_CFG_PATH, "reconnectwm.sh"); + if (g_file_exist(text)) + { + g_execlp3(text, g_cfg->default_wm, 0); + } + g_exit(0); + } + return display; +} + +/******************************************************************************/ /* called by a worker thread, ask the main thread to call session_sync_start and wait till done */ int DEFAULT_CC @@ -826,6 +889,7 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 258.0] In session_star /* lock mutex */ lock_sync_acquire(); /* set shared vars */ + g_sync_cmd = 0; g_sync_width = width; g_sync_height = height; g_sync_bpp = bpp; @@ -849,6 +913,27 @@ log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "[RAJA DEBUG 258.0] In session_star } /******************************************************************************/ +/* called by a worker thread, ask the main thread to call session_sync_start + and wait till done */ +int DEFAULT_CC +session_reconnect(int display, char* username) +{ + /* lock mutex */ + lock_sync_acquire(); + /* set shared vars */ + g_sync_cmd = 1; + g_sync_width = display; + g_sync_username = username; + /* set event for main thread to see */ + g_set_wait_obj(g_sync_event); + /* wait for main thread to get done */ + lock_sync_sem_acquire(); + /* unlock mutex */ + lock_sync_release(); + return 0; +} + +/******************************************************************************/ /* called with the main thread */ int APP_CC session_sync_start(void) @@ -879,7 +964,7 @@ session_kill(int pid) { if (tmp->item == 0) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "session descriptor for " + log_message(LOG_LEVEL_ERROR, "session descriptor for " "pid %d is null!", pid); if (prev == 0) { @@ -899,7 +984,7 @@ session_kill(int pid) if (tmp->item->pid == pid) { /* deleting the session */ - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "++ terminated session: username %s, display :%d.0, session_pid %d, ip %s", tmp->item->name, tmp->item->display, tmp->item->pid, tmp->item->client_ip); + log_message(LOG_LEVEL_INFO, "++ terminated session: username %s, display :%d.0, session_pid %d, ip %s", tmp->item->name, tmp->item->display, tmp->item->pid, tmp->item->client_ip); g_free(tmp->item); if (prev == 0) { @@ -943,7 +1028,7 @@ session_sigkill_all() { if (tmp->item == 0) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "found null session " + log_message(LOG_LEVEL_ERROR, "found null session " "descriptor!"); } else @@ -969,7 +1054,7 @@ session_get_bypid(int pid) dummy = g_malloc(sizeof(struct session_item), 1); if (0 == dummy) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "internal error", pid); + log_message(LOG_LEVEL_ERROR, "internal error", pid); return 0; } @@ -981,7 +1066,7 @@ session_get_bypid(int pid) { if (tmp->item == 0) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "session descriptor for " + log_message(LOG_LEVEL_ERROR, "session descriptor for " "pid %d is null!", pid); /*THREAD-FIX release chain lock */ lock_chain_release(); @@ -1015,7 +1100,7 @@ session_get_byuser(char* user, int* cnt, unsigned char flags) int count; int index; - count=0; + count = 0; /*THREAD-FIX require chain lock */ lock_chain_acquire(); @@ -1023,10 +1108,10 @@ session_get_byuser(char* user, int* cnt, unsigned char flags) tmp = g_sessions; while (tmp != 0) { - LOG_DBG(&(g_cfg->log), "user: %s", user); + LOG_DBG("user: %s", user); if ((NULL == user) || (!g_strncasecmp(user, tmp->item->name, 256))) { - LOG_DBG(&(g_cfg->log), "session_get_byuser: status=%d, flags=%d, " + LOG_DBG("session_get_byuser: status=%d, flags=%d, " "result=%d", (tmp->item->status), flags, ((tmp->item->status) & flags)); if ((tmp->item->status) & flags) @@ -1039,9 +1124,9 @@ session_get_byuser(char* user, int* cnt, unsigned char flags) tmp=tmp->next; } - if (count==0) + if (count == 0) { - (*cnt)=0; + (*cnt) = 0; /*THREAD-FIX release chain lock */ lock_chain_release(); return 0; @@ -1049,9 +1134,9 @@ session_get_byuser(char* user, int* cnt, unsigned char flags) /* malloc() an array of disconnected sessions */ sess=g_malloc(count * sizeof(struct SCP_DISCONNECTED_SESSION),1); - if (sess==0) + if (sess == 0) { - (*cnt)=0; + (*cnt) = 0; /*THREAD-FIX release chain lock */ lock_chain_release(); return 0; diff --git a/sesman/session.h b/sesman/session.h index 23aed823..a8de90d5 100644 --- a/sesman/session.h +++ b/sesman/session.h @@ -107,6 +107,9 @@ session_start(int width, int height, int bpp, char* username, char* password, long data, tui8 type, char* domain, char* program, char* directory, char* client_ip); +int DEFAULT_CC +session_reconnect(int display, char* username); + /** * * @brief starts a session @@ -156,4 +159,3 @@ struct SCP_DISCONNECTED_SESSION* session_get_byuser(char* user, int* cnt, unsigned char flags); #endif - diff --git a/sesman/sessvc/Makefile.am b/sesman/sessvc/Makefile.am index 67740781..8ba24abd 100644 --- a/sesman/sessvc/Makefile.am +++ b/sesman/sessvc/Makefile.am @@ -15,4 +15,4 @@ xrdp_sessvc_SOURCES = \ sessvc.c xrdp_sessvc_LDADD = \ - $(top_srcdir)/common/libcommon.la + $(top_builddir)/common/libcommon.la diff --git a/sesman/sig.c b/sesman/sig.c index 24f2e81c..151c0c57 100644 --- a/sesman/sig.c +++ b/sesman/sig.c @@ -40,15 +40,15 @@ sig_sesman_shutdown(int sig) { char pid_file[256]; - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "shutting down sesman %d", 1); + log_message(LOG_LEVEL_INFO, "shutting down sesman %d", 1); if (g_getpid() != g_pid) { - LOG_DBG(&(g_cfg->log), "g_getpid() [%d] differs from g_pid [%d]", (g_getpid()), g_pid); + LOG_DBG("g_getpid() [%d] differs from g_pid [%d]", (g_getpid()), g_pid); return; } - LOG_DBG(&(g_cfg->log), " - getting signal %d pid %d", sig, g_getpid()); + LOG_DBG(" - getting signal %d pid %d", sig, g_getpid()); g_set_wait_obj(g_term_event); @@ -66,51 +66,55 @@ sig_sesman_reload_cfg(int sig) { int error; struct config_sesman *cfg; + char cfg_file[256]; - log_message(&(g_cfg->log), LOG_LEVEL_WARNING, "receiving SIGHUP %d", 1); + log_message(LOG_LEVEL_WARNING, "receiving SIGHUP %d", 1); if (g_getpid() != g_pid) { - LOG_DBG(&(g_cfg->log), "g_getpid() [%d] differs from g_pid [%d]", g_getpid(), g_pid); + LOG_DBG("g_getpid() [%d] differs from g_pid [%d]", g_getpid(), g_pid); return; } cfg = g_malloc(sizeof(struct config_sesman), 1); if (0 == cfg) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "error creating new config: - keeping old cfg"); + log_message(LOG_LEVEL_ERROR, "error creating new config: - keeping old cfg"); return; } if (config_read(cfg) != 0) { - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "error reading config - keeping old cfg"); + log_message(LOG_LEVEL_ERROR, "error reading config - keeping old cfg"); return; } /* stop logging subsystem */ - log_end(&(g_cfg->log)); + log_end(); /* replace old config with new readed one */ g_cfg = cfg; + + g_snprintf(cfg_file, 255, "%s/sesman.ini", XRDP_CFG_PATH); /* start again logging subsystem */ - error = log_start(&(g_cfg->log)); + error = log_start(cfg_file,"XRDP-sesman"); if (error != LOG_STARTUP_OK) { + char buf[256]; switch (error) { case LOG_ERROR_MALLOC: g_printf("error on malloc. cannot restart logging. log stops here, sorry.\n"); break; case LOG_ERROR_FILE_OPEN: - g_printf("error reopening log file [%s]. log stops here, sorry.\n", g_cfg->log.log_file); + g_printf("error reopening log file [%s]. log stops here, sorry.\n", getLogFile(buf,255)); break; } } - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "configuration reloaded, log subsystem restarted"); + log_message(LOG_LEVEL_INFO, "configuration reloaded, log subsystem restarted"); } /******************************************************************************/ @@ -166,27 +170,27 @@ sig_handler_thread(void* arg) case SIGHUP: //reload cfg //we must stop & restart logging, or copy logging cfg!!!! - LOG_DBG(&(g_cfg->log), "sesman received SIGHUP", 0); + LOG_DBG("sesman received SIGHUP", 0); //return 0; break; case SIGCHLD: /* a session died */ - LOG_DBG(&(g_cfg->log), "sesman received SIGCHLD", 0); + LOG_DBG("sesman received SIGCHLD", 0); sig_sesman_session_end(SIGCHLD); break; case SIGINT: /* we die */ - LOG_DBG(&(g_cfg->log), "sesman received SIGINT", 0); + LOG_DBG("sesman received SIGINT", 0); sig_sesman_shutdown(recv_signal); break; case SIGKILL: /* we die */ - LOG_DBG(&(g_cfg->log), "sesman received SIGKILL", 0); + LOG_DBG("sesman received SIGKILL", 0); sig_sesman_shutdown(recv_signal); break; case SIGTERM: /* we die */ - LOG_DBG(&(g_cfg->log), "sesman received SIGTERM", 0); + LOG_DBG("sesman received SIGTERM", 0); sig_sesman_shutdown(recv_signal); break; } diff --git a/sesman/thread.c b/sesman/thread.c index 986a5d27..98a92533 100644 --- a/sesman/thread.c +++ b/sesman/thread.c @@ -22,7 +22,7 @@ * @file thread.c * @brief thread stuff... * @author Simone Fedele - * + * */ #include "sesman.h" @@ -62,14 +62,14 @@ thread_sighandler_start(void) sigaddset(&waitmask, SIGFPE); pthread_sigmask(SIG_UNBLOCK, &waitmask, NULL); - log_message(&(g_cfg->log), LOG_LEVEL_INFO,"starting signal handling thread..."); + log_message(LOG_LEVEL_INFO,"starting signal handling thread..."); ret = pthread_create(&g_thread_sighandler, NULL, sig_handler_thread, ""); pthread_detach(g_thread_sighandler); if (ret == 0) { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "signal handler thread started successfully"); + log_message(LOG_LEVEL_INFO, "signal handler thread started successfully"); return 0; } @@ -77,16 +77,16 @@ thread_sighandler_start(void) switch (ret) { case EINVAL: - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "invalid attributes for signal handling thread (creation returned EINVAL)"); + log_message(LOG_LEVEL_ERROR, "invalid attributes for signal handling thread (creation returned EINVAL)"); break; case EAGAIN: - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "not enough resources to start signal handling thread (creation returned EAGAIN)"); + log_message(LOG_LEVEL_ERROR, "not enough resources to start signal handling thread (creation returned EAGAIN)"); break; case EPERM: - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "invalid permissions for signal handling thread (creation returned EPERM)"); + log_message(LOG_LEVEL_ERROR, "invalid permissions for signal handling thread (creation returned EPERM)"); break; default: - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "unknown error starting signal handling thread"); + log_message(LOG_LEVEL_ERROR, "unknown error starting signal handling thread"); } return 1; @@ -100,13 +100,13 @@ thread_session_update_start(void) int ret; //starts the session update thread //that checks for idle time, destroys sessions, ecc... - -#warning this thread should always request lock_fork before read or write + +#warning this thread should always request lock_fork before read or write #warning (so we can Fork() In Peace) ret = pthread_create(&g_thread_updater, NULL, , ""); pthread_detach(g_thread_updater); - if (ret==0) + if (ret == 0) { log_message(&(g_cfg->log), LOG_LEVEL_INFO, "session update thread started successfully"); return 0; @@ -116,16 +116,16 @@ thread_session_update_start(void) switch (ret) { case EINVAL: - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "invalid attributes for session update thread (creation returned EINVAL)"); + log_message(LOG_LEVEL_ERROR, "invalid attributes for session update thread (creation returned EINVAL)"); break; case EAGAIN: - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "not enough resources to start session update thread (creation returned EAGAIN)"); + log_message(LOG_LEVEL_ERROR, "not enough resources to start session update thread (creation returned EAGAIN)"); break; case EPERM: - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "invalid permissions for session update thread (creation returned EPERM)"); + log_message(LOG_LEVEL_ERROR, "invalid permissions for session update thread (creation returned EPERM)"); break; default: - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "unknown error starting session update thread"); + log_message(LOG_LEVEL_ERROR, "unknown error starting session update thread"); } return 1; @@ -148,9 +148,9 @@ thread_scp_start(int skt) //ret = pthread_create(&th, NULL, scp_process_start, (void*) (&g_thread_sck)); pthread_detach(th); - if (ret == 0) + if (ret == 0) { - log_message(&(g_cfg->log), LOG_LEVEL_INFO, "scp thread on sck %d started successfully", skt); + log_message(LOG_LEVEL_INFO, "scp thread on sck %d started successfully", skt); return 0; } @@ -158,18 +158,17 @@ thread_scp_start(int skt) switch (ret) { case EINVAL: - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "invalid attributes for scp thread on sck %d (creation returned EINVAL)", skt); + log_message(LOG_LEVEL_ERROR, "invalid attributes for scp thread on sck %d (creation returned EINVAL)", skt); break; case EAGAIN: - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "not enough resources to start scp thread on sck %d (creation returned EAGAIN)", skt); + log_message(LOG_LEVEL_ERROR, "not enough resources to start scp thread on sck %d (creation returned EAGAIN)", skt); break; case EPERM: - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "invalid permissions for scp thread on sck %d (creation returned EPERM)", skt); + log_message(LOG_LEVEL_ERROR, "invalid permissions for scp thread on sck %d (creation returned EPERM)", skt); break; default: - log_message(&(g_cfg->log), LOG_LEVEL_ERROR, "unknown error starting scp thread on sck %d"); + log_message(LOG_LEVEL_ERROR, "unknown error starting scp thread on sck %d"); } return 1; } - diff --git a/sesman/tools/Makefile.am b/sesman/tools/Makefile.am index a48b0f11..ab3612d0 100644 --- a/sesman/tools/Makefile.am +++ b/sesman/tools/Makefile.am @@ -15,7 +15,8 @@ bin_PROGRAMS = \ xrdp-sesrun \ xrdp-sestest \ xrdp-sesadmin \ - xrdp-dis + xrdp-dis \ + xrdp-xcon xrdp_sesrun_SOURCES = \ sesrun.c \ @@ -31,14 +32,20 @@ xrdp_sesadmin_SOURCES = \ xrdp_dis_SOURCES = \ dis.c +xrdp_xcon_SOURCES = \ + xcon.c + xrdp_sesrun_LDADD = \ - $(top_srcdir)/common/libcommon.la + $(top_builddir)/common/libcommon.la xrdp_sestest_LDADD = \ - $(top_srcdir)/common/libcommon.la \ - $(top_srcdir)/sesman/libscp/libscp.la + $(top_builddir)/common/libcommon.la \ + $(top_builddir)/sesman/libscp/libscp.la xrdp_sesadmin_LDADD = \ - $(top_srcdir)/common/libcommon.la \ - $(top_srcdir)/sesman/libscp/libscp.la + $(top_builddir)/common/libcommon.la \ + $(top_builddir)/sesman/libscp/libscp.la +xrdp_xcon_LDADD = \ + -L/usr/X11R6/lib \ + -lX11 diff --git a/sesman/tools/sesadmin.c b/sesman/tools/sesadmin.c index 4c612316..22f20c23 100644 --- a/sesman/tools/sesadmin.c +++ b/sesman/tools/sesadmin.c @@ -50,7 +50,7 @@ int main(int argc, char** argv) logging.log_file = g_strdup("xrdp-sesadmin.log"); logging.log_level = LOG_LEVEL_DEBUG; logging.enable_syslog = 0; - log_start(&logging); + log_start_from_param(&logging); for (idx = 0; idx < argc; idx++) { @@ -110,11 +110,11 @@ int main(int argc, char** argv) s = scp_session_create(); c = scp_connection_create(sock); - LOG_DBG(&logging, "Connecting to %s:%s with user %s (%s)\n", serv, port, user, pass); + LOG_DBG("Connecting to %s:%s with user %s (%s)\n", serv, port, user, pass); if (0 != g_tcp_connect(sock, serv, port)) { - LOG_DBG(&logging, "g_tcp_connect() error\n"); + LOG_DBG("g_tcp_connect() error\n"); return 1; } @@ -127,7 +127,7 @@ int main(int argc, char** argv) if (SCP_CLIENT_STATE_OK != e) { - LOG_DBG(&logging, "libscp error connecting: %s %d\n", s->errstr, (int)e); + LOG_DBG("libscp error connecting: %s %d\n", s->errstr, (int)e); } if (0 == g_strncmp(cmnd, "list", 5)) @@ -142,7 +142,7 @@ int main(int argc, char** argv) g_tcp_close(sock); scp_session_destroy(s); scp_connection_destroy(c); - log_end(&logging); + log_end(); return 0; } diff --git a/sesman/tools/sestest.c b/sesman/tools/sestest.c index 4382e160..c0784ba3 100644 --- a/sesman/tools/sestest.c +++ b/sesman/tools/sestest.c @@ -34,7 +34,7 @@ int main(int argc, char** argv) log.log_level=99; log.program_name=g_strdup("sestest"); log.log_file=g_strdup("sestest.log"); - log_start(&log); + log_start_from_param(&log); scp_init(&log); sock=g_tcp_socket(); @@ -206,7 +206,7 @@ menuSelect(tui32 choices) ret = scanf("%u", &sel); - while ((ret==0) || (sel > choices)) + while ((ret == 0) || (sel > choices)) { g_printf("invalid choice."); ret = scanf("%u", &sel); diff --git a/sesman/tools/xcon.c b/sesman/tools/xcon.c new file mode 100644 index 00000000..7a45a1cd --- /dev/null +++ b/sesman/tools/xcon.c @@ -0,0 +1,35 @@ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <X11/Xlib.h> + +Display* g_display = 0; +int g_x_socket = 0; + +int main(int argc, char** argv) +{ + fd_set rfds; + int i1; + XEvent xevent; + + g_display = XOpenDisplay(0); + if (g_display == 0) + { + printf("XOpenDisplay failed\n"); + return 0; + } + g_x_socket = XConnectionNumber(g_display); + while (1) + { + FD_ZERO(&rfds); + FD_SET(g_x_socket, &rfds); + i1 = select(g_x_socket + 1, &rfds, 0, 0, 0); + if (i1 < 0) + { + break; + } + XNextEvent(g_display, &xevent); + } + return 0; +} diff --git a/sesman/verify_user.c b/sesman/verify_user.c index cdc60b47..aaa1515c 100644 --- a/sesman/verify_user.c +++ b/sesman/verify_user.c @@ -302,21 +302,21 @@ auth_account_disabled(struct spwd* stp) { int today; - if (0==stp) + if (0 == stp) { /* if an invalid struct was passed we assume a disabled account */ return 1; } - today=g_time1()/SECS_PER_DAY; + today = g_time1() / SECS_PER_DAY; - LOG_DBG(&(g_cfg->log), "last %d",stp->sp_lstchg); - LOG_DBG(&(g_cfg->log), "min %d",stp->sp_min); - LOG_DBG(&(g_cfg->log), "max %d",stp->sp_max); - LOG_DBG(&(g_cfg->log), "inact %d",stp->sp_inact); - LOG_DBG(&(g_cfg->log), "warn %d",stp->sp_warn); - LOG_DBG(&(g_cfg->log), "expire %d",stp->sp_expire); - LOG_DBG(&(g_cfg->log), "today %d",today); + LOG_DBG("last %d",stp->sp_lstchg); + LOG_DBG("min %d",stp->sp_min); + LOG_DBG("max %d",stp->sp_max); + LOG_DBG("inact %d",stp->sp_inact); + LOG_DBG("warn %d",stp->sp_warn); + LOG_DBG("expire %d",stp->sp_expire); + LOG_DBG("today %d",today); if ((stp->sp_expire != -1) && (today >= stp->sp_expire)) { diff --git a/vnc/Makefile.am b/vnc/Makefile.am index 81f44c38..24835011 100644 --- a/vnc/Makefile.am +++ b/vnc/Makefile.am @@ -15,4 +15,4 @@ lib_LTLIBRARIES = \ libvnc_la_SOURCES = vnc.c libvnc_la_LIBADD = \ - $(top_srcdir)/common/libcommon.la + $(top_builddir)/common/libcommon.la @@ -21,6 +21,7 @@ */ #include "vnc.h" +#include "log.h" /******************************************************************************/ /* taken from vncauth.c */ @@ -63,6 +64,7 @@ lib_recv(struct vnc* v, char* data, int len) } else { + log_message(LOG_LEVEL_DEBUG, "VNC lib_recv return 1"); return 1; } } @@ -199,12 +201,16 @@ lib_process_channel_data(struct vnc* v, int chanid, int flags, int size, length, 3); free_stream(out_s); break; + default:{ + log_message(LOG_LEVEL_DEBUG, "VNC clip information unhandled"); + break; + } } } else { - g_writeln("lib_process_channel_data: unknown chanid %d v->clip_chanid %d", - chanid, v->clip_chanid); + log_message(LOG_LEVEL_DEBUG, "lib_process_channel_data: unknown chanid:", + "%d :(v->clip_chanid) %d",chanid,v->clip_chanid); } return 0; } @@ -381,7 +387,7 @@ get_pixel_safe(char* data, int x, int y, int width, int height, int bpp) } else { - g_writeln("error in get_pixel_safe bpp %d", bpp); + log_message(LOG_LEVEL_ERROR, "error in get_pixel_safe bpp %d", bpp); } return 0; } @@ -436,7 +442,7 @@ set_pixel_safe(char* data, int x, int y, int width, int height, int bpp, } else { - g_writeln("error in set_pixel_safe bpp %d", bpp); + log_message(LOG_LEVEL_ERROR, "error in set_pixel_safe bpp %d", bpp); } } @@ -473,7 +479,7 @@ split_color(int pixel, int* r, int* g, int* b, int bpp, int* palette) } else { - g_writeln("error in split_color bpp %d", bpp); + log_message(LOG_LEVEL_ERROR, "error in split_color bpp %d", bpp); } return 0; } @@ -488,7 +494,7 @@ make_color(int r, int g, int b, int bpp) } else { - g_writeln("error in make_color bpp %d", bpp); + log_message(LOG_LEVEL_ERROR, "error in make_color bpp %d", bpp); } return 0; } @@ -629,7 +635,7 @@ lib_framebuffer_update(struct vnc* v) } else { - g_sprintf(text, "error in lib_framebuffer_update encoding = %8.8x", + g_sprintf(text, "VNC error in lib_framebuffer_update encoding = %8.8x", encoding); v->server_msg(v, text, 1); } @@ -784,18 +790,18 @@ lib_mod_signal(struct vnc* v) { error = lib_palette_update(v); } - else if (type == 2) /* bell */ + else if (type == 2) /* bell */ { error = lib_bell_trigger(v); } else if (type == 3) /* clipboard */ { - g_writeln("got clip data"); + log_message(LOG_LEVEL_DEBUG, "VNC got clip data"); error = lib_clip_data(v); } else { - g_sprintf(text, "unknown in lib_mod_signal %d", type); + g_sprintf(text, "VNC unknown in lib_mod_signal %d", type); v->server_msg(v, text, 1); } } @@ -847,19 +853,19 @@ lib_mod_connect(struct vnc* v) int i; int check_sec_result; - v->server_msg(v, "started connecting", 0); + v->server_msg(v, "VNC started connecting", 0); check_sec_result = 1; /* only support 8 and 16 bpp connections from rdp client */ if ((v->server_bpp != 8) && (v->server_bpp != 15) && (v->server_bpp != 16) && (v->server_bpp != 24)) { - v->server_msg(v, "error - only supporting 8, 15, 16 and 24 bpp rdp \ -connections", 0); + v->server_msg(v, "VNC error - only supporting 8, 15, 16 and 24 bpp rdp " + "connections", 0); return 1; } if (g_strcmp(v->ip, "") == 0) { - v->server_msg(v, "error - no ip set", 0); + v->server_msg(v, "VNC error - no ip set", 0); return 1; } make_stream(s); @@ -868,12 +874,12 @@ connections", 0); v->sck = g_tcp_socket(); v->sck_obj = g_create_wait_obj_from_socket(v->sck, 0); v->sck_closed = 0; - g_sprintf(text, "connecting to %s %s", v->ip, con_port); + g_sprintf(text, "VNC connecting to %s %s", v->ip, con_port); v->server_msg(v, text, 0); error = g_tcp_connect(v->sck, v->ip, con_port); if (error == 0) { - v->server_msg(v, "tcp connected", 0); + v->server_msg(v, "VNC tcp connected", 0); g_tcp_set_non_blocking(v->sck); g_tcp_set_no_delay(v->sck); /* protocal version */ @@ -892,7 +898,7 @@ connections", 0); if (error == 0) { in_uint32_be(s, i); - g_sprintf(text, "security level is %d (1 = none, 2 = standard)", i); + g_sprintf(text, "VNC security level is %d (1 = none, 2 = standard)", i); v->server_msg(v, text, 0); if (i == 1) /* none */ { @@ -906,14 +912,25 @@ connections", 0); { rfbEncryptBytes(s->data, v->password); error = lib_send(v, s->data, 16); + check_sec_result = 1; // not needed } } + else if (i == 0) + { + log_message(LOG_LEVEL_DEBUG, "VNC Server will disconnect"); + error = 1; + } else { + log_message(LOG_LEVEL_DEBUG, "VNC unsupported security level"); error = 1; } } } + if (error!=0) + { + log_message(LOG_LEVEL_DEBUG, "VNC Error after security negotiation"); + } if (error == 0 && check_sec_result) { /* sec result */ @@ -924,42 +941,58 @@ connections", 0); in_uint32_be(s, i); if (i != 0) { - v->server_msg(v, "password failed", 0); + v->server_msg(v, "VNC password failed", 0); error = 2; } else { - v->server_msg(v, "password ok", 0); + v->server_msg(v, "VNC password ok", 0); } } } if (error == 0) { - v->server_msg(v, "sending share flag", 0); + v->server_msg(v, "VNC sending share flag", 0); init_stream(s, 8192); s->data[0] = 1; error = lib_send(v, s->data, 1); /* share flag */ } + else + { + log_message(LOG_LEVEL_DEBUG, "VNC error before sending share flag"); + } if (error == 0) { - v->server_msg(v, "receiving server init", 0); + v->server_msg(v, "VNC receiving server init", 0); error = lib_recv(v, s->data, 4); /* server init */ } + else + { + log_message(LOG_LEVEL_DEBUG, "VNC error before receiving server init"); + } if (error == 0) { in_uint16_be(s, v->mod_width); in_uint16_be(s, v->mod_height); init_stream(pixel_format, 8192); - v->server_msg(v, "receiving pixel format", 0); + v->server_msg(v, "VNC receiving pixel format", 0); error = lib_recv(v, pixel_format->data, 16); } + else + { + log_message(LOG_LEVEL_DEBUG, "VNC error before receiving pixel format"); + } if (error == 0) { v->mod_bpp = v->server_bpp; init_stream(s, 8192); - v->server_msg(v, "receiving name length", 0); + v->server_msg(v, "VNC receiving name length", 0); error = lib_recv(v, s->data, 4); /* name len */ } + else + { + log_message(LOG_LEVEL_DEBUG, "VNC error before receiving name length"); + } if (error == 0) { in_uint32_be(s, i); @@ -969,11 +1002,15 @@ connections", 0); } else { - v->server_msg(v, "receiving name", 0); + v->server_msg(v, "VNC receiving name", 0); error = lib_recv(v, v->mod_name, i); v->mod_name[i] = 0; } } + else + { + log_message(LOG_LEVEL_DEBUG, "VNC error before receiving name"); + } /* should be connected */ if (error == 0) { @@ -1057,7 +1094,7 @@ connections", 0); out_uint8s(pixel_format, 3); /* pad */ } out_uint8a(s, pixel_format->data, 16); - v->server_msg(v, "sending pixel format", 0); + v->server_msg(v, "VNC sending pixel format", 0); error = lib_send(v, s->data, 20); } if (error == 0) @@ -1071,7 +1108,7 @@ connections", 0); out_uint32_be(s, 1); /* copy rect */ out_uint32_be(s, 0xffffff11); /* cursor */ out_uint32_be(s, 0xffffff21); /* desktop size */ - v->server_msg(v, "sending encodings", 0); + v->server_msg(v, "VNC sending encodings", 0); error = lib_send(v, s->data, 4 + 4 * 4); } if (error == 0) @@ -1088,14 +1125,14 @@ connections", 0); out_uint16_be(s, 0); out_uint16_be(s, v->mod_width); out_uint16_be(s, v->mod_height); - v->server_msg(v, "sending framebuffer update request", 0); + v->server_msg(v, "VNC sending framebuffer update request", 0); error = lib_send(v, s->data, 10); } if (error == 0) { if (v->server_bpp != v->mod_bpp) { - v->server_msg(v, "error - server bpp and client bpp do not match", 0); + v->server_msg(v, "VNC error - server bpp and client bpp do not match", 0); error = 1; } } @@ -1107,19 +1144,19 @@ connections", 0); g_memset(cursor_data + (32 * (32 * 3) - 2 * 32 * 3), 0xff, 9); g_memset(cursor_data + (32 * (32 * 3) - 3 * 32 * 3), 0xff, 9); g_memset(cursor_mask, 0xff, 32 * (32 / 8)); - v->server_msg(v, "sending cursor", 0); + v->server_msg(v, "VNC sending cursor", 0); error = v->server_set_cursor(v, 3, 3, cursor_data, cursor_mask); } free_stream(s); free_stream(pixel_format); if (error == 0) { - v->server_msg(v, "connection complete, connected ok", 0); + v->server_msg(v, "VNC connection complete, connected ok", 0); lib_open_clip_channel(v); } else { - v->server_msg(v, "error - problem connecting", 0); + v->server_msg(v, "VNC error - problem connecting", 0); } return error; } @@ -1231,6 +1268,7 @@ mod_init(void) int EXPORT_CC mod_exit(struct vnc* v) { + log_message(LOG_LEVEL_DEBUG, "VNC mod_exit"); if (v == 0) { return 0; diff --git a/xorg/X11R7.6/buildx.sh b/xorg/X11R7.6/buildx.sh index 77203aed..279f72cb 100755 --- a/xorg/X11R7.6/buildx.sh +++ b/xorg/X11R7.6/buildx.sh @@ -6,27 +6,31 @@ # Authors # Jay Sorg Jay.Sorg@gmail.com # Laxmikant Rashinkar LK.Rashinkar@gmail.com -# +# # 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. -# flex bison libxml2-dev intltool -# xsltproc -# xutils-dev python-libxml2 +# debian packages needed +# flex bison libxml2-dev intltool xsltproc xutils-dev python-libxml2 g++ xutils download_file() { file=$1 + # if we already have the file, don't re-download it + if [ -r downloads/$file ]; then + return 0 + fi + cd downloads echo "downloading file $file" @@ -145,24 +149,16 @@ remove_modules() cd .. } -make_it() +extract_it() { mod_file=$1 mod_name=$2 mod_args=$3 - count=`expr $count + 1` - - # if a cookie with $mod_name exists... - if [ -e cookies/$mod_name ]; then - # ...package has already been built + if [ -e cookies/$mod_name.extracted ]; then return 0 fi - echo "" - echo "*** processing module $mod_name ($count of $num_modules) ***" - echo "" - # download file download_file $mod_file if [ $? -ne 0 ]; then @@ -202,17 +198,51 @@ make_it() exit 1 fi - # make module - make + cd ../.. + + touch cookies/$mod_name.extracted +} + +make_it() +{ + mod_file=$1 + mod_name=$2 + mod_args=$3 + + count=`expr $count + 1` + + # if a cookie with $mod_name exists... + if [ -e cookies/$mod_name.installed ]; then + # ...package has already been installed + return 0 + fi + + echo "" + echo "*** processing module $mod_name ($count of $num_modules) ***" + echo "" + + extract_it $mod_file $mod_name "$mod_args" if [ $? -ne 0 ]; then echo "" - echo "make failed for module $mod_name" + echo "extract failed for module $mod_name" echo "" exit 1 fi + # make module + if [ ! -e cookies/$mod_name.made ]; then + (cd build_dir/$mod_name ; make) + if [ $? -ne 0 ]; then + echo "" + echo "make failed for module $mod_name" + echo "" + exit 1 + fi + touch cookies/$mod_name.made + fi + # install module - make install + (cd build_dir/$mod_name ; make install) if [ $? -ne 0 ]; then echo "" echo "make install failed for module $mod_name" @@ -224,12 +254,11 @@ make_it() # so Mesa builds using this python version case "$mod_name" in *Python-2*) - ln -s python $PREFIX_DIR/bin/python2 + (cd build_dir/$mod_name ; ln -s python $PREFIX_DIR/bin/python2) ;; esac - cd ../.. - touch cookies/$mod_name + touch cookies/$mod_name.installed return 0 } @@ -281,11 +310,9 @@ fi echo "using $PREFIX_DIR" export PKG_CONFIG_PATH=$PREFIX_DIR/lib/pkgconfig:$PREFIX_DIR/share/pkgconfig - export PATH=$PREFIX_DIR/bin:$PATH - -# really only needed for x84 -export CFLAGS=-fPIC +export LDFLAGS=-Wl,-rpath=$PREFIX_DIR/lib +export CFLAGS="-I$PREFIX_DIR/include -fPIC -O2" # prefix dir must exist... if [ ! -d $PREFIX_DIR ]; then @@ -347,6 +374,10 @@ export X11RDPBASE cd rdp make +if [ $? -ne 0 ]; then + echo "error building rdp" + exit 1 +fi # this will copy the build X server with the other X server binaries strip X11rdp diff --git a/xorg/X11R7.6/rdp/Makefile b/xorg/X11R7.6/rdp/Makefile index 91961151..7373f51a 100644 --- a/xorg/X11R7.6/rdp/Makefile +++ b/xorg/X11R7.6/rdp/Makefile @@ -7,6 +7,12 @@ LIBBASE = $(X11RDPBASE)/lib XSRCBASE = ../build_dir/xorg-server-1.9.3 OBJS = rdpmain.o rdpdraw.o rdpinput.o rdpmisc.o rdpup.o rdprandr.o \ +rdpCopyArea.o rdpPolyFillRect.o rdpPutImage.o rdpPolyRectangle.o \ +rdpPolylines.o rdpPolySegment.o rdpFillSpans.o rdpSetSpans.o \ +rdpCopyPlane.o rdpPolyPoint.o rdpPolyArc.o rdpFillPolygon.o \ +rdpPolyFillArc.o rdpPolyText8.o rdpPolyText16.o \ +rdpImageText8.o rdpImageText16.o rdpImageGlyphBlt.o rdpPolyGlyphBlt.o \ +rdpPushPixels.o \ miinitext.o \ fbcmap_mi.o @@ -51,6 +57,7 @@ CFLAGS = -O2 -Wall -fno-strength-reduce \ -I../../render \ -I../xfree86/common \ -I../xfree86/os-support \ + -I../../../common \ -D_POSIX_C_SOURCE=199309L -D_SVID_SOURCE -D_REENTRANT \ -DGLX_USE_MESA -DXRECORD -D_GNU_SOURCE -DXAPPGROUP \ -DTOGCUP -DSINGLEDEPTH -DXFree86Server \ diff --git a/xorg/X11R7.6/rdp/gcops.h b/xorg/X11R7.6/rdp/gcops.h index 52889b82..8d7b5d48 100644 --- a/xorg/X11R7.6/rdp/gcops.h +++ b/xorg/X11R7.6/rdp/gcops.h @@ -33,66 +33,3 @@ static void rdpDestroyClip(GCPtr pGC); static void rdpCopyClip(GCPtr dst, GCPtr src); -static void -rdpFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit, - DDXPointPtr pptInit, int * pwidthInit, int fSorted); -static void -rdpSetSpans(DrawablePtr pDrawable, GCPtr pGC, char * psrc, - DDXPointPtr ppt, int * pwidth, int nspans, int fSorted); -static void -rdpPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, - int w, int h, int leftPad, int format, char * pBits); -static RegionPtr -rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, - int srcx, int srcy, int w, int h, int dstx, int dsty); -static RegionPtr -rdpCopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, - GCPtr pGC, int srcx, int srcy, int width, int height, - int dstx, int dsty, unsigned long bitPlane); -static void -rdpPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, - int npt, DDXPointPtr pptInit); -static void -rdpPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode, - int npt, DDXPointPtr pptInit); -static void -rdpPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pSegs); -static void -rdpPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects, - xRectangle * pRects); -static void -rdpPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * parcs); -static void -rdpFillPolygon(DrawablePtr pDrawable, GCPtr pGC, - int shape, int mode, int count, - DDXPointPtr pPts); -static void -rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, - xRectangle * prectInit); -static void -rdpPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * parcs); -static int -rdpPolyText8(DrawablePtr pDrawable, GCPtr pGC, - int x, int y, int count, char * chars); -static int -rdpPolyText16(DrawablePtr pDrawable, GCPtr pGC, - int x, int y, int count, unsigned short * chars); -static void -rdpImageText8(DrawablePtr pDrawable, GCPtr pGC, - int x, int y, int count, char * chars); -static void -rdpImageText16(DrawablePtr pDrawable, GCPtr pGC, - int x, int y, int count, - unsigned short * chars); -static void -rdpImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, - int x, int y, unsigned int nglyph, - CharInfoPtr * ppci, pointer pglyphBase); -static void -rdpPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, - int x, int y, unsigned int nglyph, - CharInfoPtr * ppci, - pointer pglyphBase); -static void -rdpPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst, - int w, int h, int x, int y); diff --git a/xorg/X11R7.6/rdp/rdp.h b/xorg/X11R7.6/rdp/rdp.h index 98c0c067..695a2bde 100644 --- a/xorg/X11R7.6/rdp/rdp.h +++ b/xorg/X11R7.6/rdp/rdp.h @@ -70,7 +70,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "exevents.h" #include "xserver-properties.h" #include "xkbsrv.h" -#include "../../../common/xrdp_client_info.h" +/* in xrdp/common */ +#include "xrdp_client_info.h" +#include "xrdp_constants.h" //#include "colormapst.h" @@ -93,6 +95,16 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define PixelDPI 100 #define PixelToMM(_size) (((_size) * 254 + (PixelDPI) * 5) / ((PixelDPI) * 10)) +struct image_data +{ + int width; + int height; + int bpp; + int Bpp; + int lineBytes; + char* pixels; +}; + /* Per-screen (framebuffer) structure. There is only one of these, since we don't allow the X server to have multiple screens. */ struct _rdpScreenInfoRec @@ -118,6 +130,11 @@ struct _rdpScreenInfoRec /* Window Procedures */ CreateWindowProcPtr CreateWindow; DestroyWindowProcPtr DestroyWindow; + PositionWindowProcPtr PositionWindow; + RealizeWindowProcPtr RealizeWindow; + UnrealizeWindowProcPtr UnrealizeWindow; + ChangeWindowAttributesProcPtr ChangeWindowAttributes; + WindowExposuresProcPtr WindowExposures; CreateColormapProcPtr CreateColormap; DestroyColormapProcPtr DestroyColormap; @@ -126,6 +143,7 @@ struct _rdpScreenInfoRec ClearToBackgroundProcPtr ClearToBackground; ScreenWakeupHandlerProcPtr WakeupHandler; CompositeProcPtr Composite; + GlyphsProcPtr Glyphs; /* Backing store procedures */ RestoreAreasProcPtr RestoreAreas; @@ -159,15 +177,87 @@ typedef rdpWindowRec* rdpWindowPtr; #define GETWINPRIV(_pWindow) \ (rdpWindowPtr)dixGetPrivateAddr(&(_pWindow->devPrivates), &g_rdpWindowIndex) +#define XR_IS_ROOT(_pWindow) ((_pWindow)->drawable.pScreen->root == (_pWindow)) + +/* for tooltips */ +#define XR_STYLE_TOOLTIP (0x80000000) +#define XR_EXT_STYLE_TOOLTIP (0x00000080 | 0x00000008) + +/* for normal desktop windows */ +/* WS_TILEDWINDOW (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | + WS_MINIMIZEBOX | WS_MAXIMIZEBOX) */ +#define XR_STYLE_NORMAL (0x00C00000 | 0x00080000 | 0x00040000 | 0x00010000 | 0x00020000) +#define XR_EXT_STYLE_NORMAL (0x00040000) + +/* for dialogs */ +#define XR_STYLE_DIALOG (0x80000000) +#define XR_EXT_STYLE_DIALOG (0x00040000) + +#define RDI_FILL 1 +#define RDI_IMGLL 2 /* lossless */ +#define RDI_IMGLY 3 /* lossy */ +#define RDI_LINE 4 + +struct urdp_draw_item_fill +{ + int opcode; + int fg_color; + int bg_color; + int pad0; +}; + +struct urdp_draw_item_img +{ + int opcode; + int pad0; +}; + +struct urdp_draw_item_line +{ + int opcode; + int fg_color; + int bg_color; + int width; + xSegment* segs; + int nseg; + int flags; +}; + +union urdp_draw_item +{ + struct urdp_draw_item_fill fill; + struct urdp_draw_item_img img; + struct urdp_draw_item_line line; +}; + +struct rdp_draw_item +{ + int type; + int flags; + struct rdp_draw_item* prev; + struct rdp_draw_item* next; + RegionPtr reg; + union urdp_draw_item u; +}; + struct _rdpPixmapRec { int status; + int rdpindex; + int allocBytes; + int con_number; + int is_dirty; + int pad0; + struct rdp_draw_item* draw_item_head; + struct rdp_draw_item* draw_item_tail; }; typedef struct _rdpPixmapRec rdpPixmapRec; typedef rdpPixmapRec* rdpPixmapPtr; #define GETPIXPRIV(_pPixmap) \ (rdpPixmapPtr)dixGetPrivateAddr(&(_pPixmap->devPrivates), &g_rdpPixmapIndex) +#define XRDP_IS_OS(_priv) (_priv->status != 0) + /* rdpmisc.c */ void rdpLog(char *format, ...); @@ -221,11 +311,34 @@ int g_chmod_hex(const char* filename, int flags); void hexdump(unsigned char *p, unsigned int len); +void +RegionAroundSegs(RegionPtr reg, xSegment* segs, int nseg); /* rdpdraw.c */ Bool rdpCloseScreen(int i, ScreenPtr pScreen); + +int +draw_item_add(rdpPixmapRec* priv, struct rdp_draw_item* di); +int +draw_item_remove(rdpPixmapRec* priv, struct rdp_draw_item* di); +int +draw_item_remove_all(rdpPixmapRec* priv); +int +draw_item_pack(rdpPixmapRec* priv); +int +draw_item_add_img_region(rdpPixmapRec* priv, RegionPtr reg, int opcode, + int type); +int +draw_item_add_fill_region(rdpPixmapRec* priv, RegionPtr reg, int color, + int opcode); +int +draw_item_add_line_region(rdpPixmapRec* priv, RegionPtr reg, int color, + int opcode, int width, xSegment* segs, int nsegs, + int is_segment); + + PixmapPtr rdpCreatePixmap(ScreenPtr pScreen, int width, int height, int depth, unsigned usage_hint); @@ -236,6 +349,16 @@ Bool rdpCreateWindow(WindowPtr pWindow); Bool rdpDestroyWindow(WindowPtr pWindow); +Bool +rdpPositionWindow(WindowPtr pWindow, int x, int y); +Bool +rdpRealizeWindow(WindowPtr pWindow); +Bool +rdpUnrealizeWindow(WindowPtr pWindow); +Bool +rdpChangeWindowAttributes(WindowPtr pWindow, unsigned long mask); +void +rdpWindowExposures(WindowPtr pWindow, RegionPtr pRegion, RegionPtr pBSRegion); Bool rdpCreateGC(GCPtr pGC); @@ -276,6 +399,11 @@ void rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height); +void +rdpGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, INT16 ySrc, int nlists, GlyphListPtr lists, + GlyphPtr* glyphs); /* rdpinput.c */ @@ -315,6 +443,14 @@ KbdSync(int param1); /* rdpup.c */ int +rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv); +int +rdpup_remove_os_bitmap(int rdpindex); +void +rdpup_get_screen_image_rect(struct image_data* id); +void +rdpup_get_pixmap_image_rect(PixmapPtr pPixmap, struct image_data* id); +int rdpup_init(void); int rdpup_check(void); @@ -345,9 +481,27 @@ rdpup_set_pen(int style, int width); int rdpup_draw_line(short x1, short y1, short x2, short y2); void -rdpup_send_area(int x, int y, int w, int h); +rdpup_send_area(struct image_data* id, int x, int y, int w, int h); int rdpup_set_cursor(short x, short y, char* cur_data, char* cur_mask); +int +rdpup_create_os_surface(int rdpindexd, int width, int height); +int +rdpup_switch_os_surface(int rdpindex); +int +rdpup_delete_os_surface(int rdpindex); + +void +rdpup_paint_rect_os(int x, int y, int cx, int cy, + int rdpindex, int srcx, int srcy); +void +rdpup_set_hints(int hints, int mask); +void +rdpup_create_window(WindowPtr pWindow, rdpWindowRec* priv); +void +rdpup_delete_window(WindowPtr pWindow, rdpWindowRec* priv); +int +rdpup_check_dirty(PixmapPtr pDirtyPixmap, rdpPixmapRec* pDirtyPriv); #if defined(X_BYTE_ORDER) # if X_BYTE_ORDER == X_LITTLE_ENDIAN diff --git a/xorg/X11R7.6/rdp/rdpCopyArea.c b/xorg/X11R7.6/rdp/rdpCopyArea.c new file mode 100644 index 00000000..4b35d9fb --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpCopyArea.c @@ -0,0 +1,549 @@ +/* +Copyright 2005-2012 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 "rdp.h" +#include "rdpdraw.h" + +#define LDEBUG 0 + +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpGCIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpWindowIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */ +extern int g_Bpp; /* from rdpmain.c */ +extern ScreenPtr g_pScreen; /* from rdpmain.c */ +extern Bool g_wrapPixmap; /* from rdpmain.c */ +extern int g_can_do_pix_to_pix; /* from rdpmain.c */ +extern int g_do_dirty_os; /* in rdpmain.c */ + +extern GCOps g_rdpGCOps; /* from rdpdraw.c */ + +extern int g_con_number; /* in rdpup.c */ + +/******************************************************************************/ +static RegionPtr +rdpCopyAreaOrg(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + int srcx, int srcy, int w, int h, int dstx, int dsty) +{ + rdpGCPtr priv; + GCFuncs* oldFuncs; + RegionPtr rv; + + GC_OP_PROLOGUE(pGC); + rv = pGC->ops->CopyArea(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); + GC_OP_EPILOGUE(pGC); + return rv; +} + +/******************************************************************************/ +static RegionPtr +rdpCopyAreaWndToWnd(WindowPtr pSrcWnd, WindowPtr pDstWnd, GCPtr pGC, + int srcx, int srcy, int w, int h, + int dstx, int dsty) +{ + int cd; + int lsrcx; + int lsrcy; + int ldstx; + int ldsty; + int num_clips; + int dx; + int dy; + int j; + BoxRec box; + RegionPtr rv; + RegionRec clip_reg; + + LLOGLN(10, ("rdpCopyAreaWndToWnd:")); + + rv = rdpCopyAreaOrg(&(pSrcWnd->drawable), &(pDstWnd->drawable), + pGC, srcx, srcy, w, h, dstx, dsty); + RegionInit(&clip_reg, NullBox, 0); + cd = rdp_get_clip(&clip_reg, &(pDstWnd->drawable), pGC); + lsrcx = pSrcWnd->drawable.x + srcx; + lsrcy = pSrcWnd->drawable.y + srcy; + ldstx = pDstWnd->drawable.x + dstx; + ldsty = pDstWnd->drawable.y + dsty; + if (cd == 1) + { + rdpup_begin_update(); + rdpup_screen_blt(ldstx, ldsty, w, h, lsrcx, lsrcy); + rdpup_end_update(); + } + else if (cd == 2) + { + num_clips = REGION_NUM_RECTS(&clip_reg); + if (num_clips > 0) + { + rdpup_begin_update(); + dx = dstx - srcx; + dy = dsty - srcy; + if ((dy < 0) || ((dy == 0) && (dx < 0))) + { + for (j = 0; j < num_clips; j++) + { + box = REGION_RECTS(&clip_reg)[j]; + rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + rdpup_screen_blt(ldstx, ldsty, w, h, lsrcx, lsrcy); + } + } + else + { + for (j = num_clips - 1; j >= 0; j--) + { + box = REGION_RECTS(&clip_reg)[j]; + rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + rdpup_screen_blt(ldstx, ldsty, w, h, lsrcx, lsrcy); + } + } + rdpup_reset_clip(); + rdpup_end_update(); + } + } + RegionUninit(&clip_reg); + return rv; +} + +/******************************************************************************/ +static RegionPtr +rdpCopyAreaWndToPixmap(WindowPtr pSrcWnd, + PixmapPtr pDstPixmap, rdpPixmapRec* pDstPriv, + GCPtr pGC, int srcx, int srcy, int w, int h, + int dstx, int dsty) +{ + int cd; + int lsrcx; + int lsrcy; + int ldstx; + int ldsty; + int num_clips; + int dx; + int dy; + int j; + BoxRec box; + RegionPtr rv; + RegionRec clip_reg; + + LLOGLN(10, ("rdpCopyAreaWndToPixmap:")); + + rv = rdpCopyAreaOrg(&(pSrcWnd->drawable), &(pDstPixmap->drawable), + pGC, srcx, srcy, w, h, dstx, dsty); + RegionInit(&clip_reg, NullBox, 0); + cd = rdp_get_clip(&clip_reg, &(pDstPixmap->drawable), pGC); + lsrcx = pSrcWnd->drawable.x + srcx; + lsrcy = pSrcWnd->drawable.y + srcy; + ldstx = pDstPixmap->drawable.x + dstx; + ldsty = pDstPixmap->drawable.y + dsty; + if (cd == 1) + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + rdpup_begin_update(); + rdpup_screen_blt(ldstx, ldsty, w, h, lsrcx, lsrcy); + rdpup_end_update(); + rdpup_switch_os_surface(-1); + } + else if (cd == 2) + { + num_clips = REGION_NUM_RECTS(&clip_reg); + if (num_clips > 0) + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + rdpup_begin_update(); + dx = dstx - srcx; + dy = dsty - srcy; + if ((dy < 0) || ((dy == 0) && (dx < 0))) + { + for (j = 0; j < num_clips; j++) + { + box = REGION_RECTS(&clip_reg)[j]; + rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + rdpup_screen_blt(ldstx, ldsty, w, h, lsrcx, lsrcy); + } + } + else + { + for (j = num_clips - 1; j >= 0; j--) + { + box = REGION_RECTS(&clip_reg)[j]; + rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + rdpup_screen_blt(ldstx, ldsty, w, h, lsrcx, lsrcy); + } + } + rdpup_reset_clip(); + rdpup_end_update(); + rdpup_switch_os_surface(-1); + } + } + RegionUninit(&clip_reg); + return rv; +} + +/******************************************************************************/ +/* draw from an off screen pixmap to a visible window */ +static RegionPtr +rdpCopyAreaPixmapToWnd(PixmapPtr pSrcPixmap, rdpPixmapRec* pSrcPriv, + WindowPtr pDstWnd, GCPtr pGC, + int srcx, int srcy, int w, int h, + int dstx, int dsty) +{ + int lsrcx; + int lsrcy; + int ldstx; + int ldsty; + int cd; + int j; + int num_clips; + RegionPtr rv; + RegionRec clip_reg; + BoxRec box; + + LLOGLN(10, ("rdpCopyAreaPixmapToWnd:")); + + rv = rdpCopyAreaOrg(&(pSrcPixmap->drawable), &(pDstWnd->drawable), + pGC, srcx, srcy, w, h, dstx, dsty); + RegionInit(&clip_reg, NullBox, 0); + cd = rdp_get_clip(&clip_reg, &(pDstWnd->drawable), pGC); + ldstx = pDstWnd->drawable.x + dstx; + ldsty = pDstWnd->drawable.y + dsty; + lsrcx = pSrcPixmap->drawable.x + srcx; + lsrcy = pSrcPixmap->drawable.y + srcy; + if (cd == 1) + { + rdpup_begin_update(); + rdpup_paint_rect_os(ldstx, ldsty, w, h, pSrcPriv->rdpindex, lsrcx, lsrcy); + rdpup_end_update(); + } + else if (cd == 2) + { + num_clips = REGION_NUM_RECTS(&clip_reg); + if (num_clips > 0) + { + rdpup_begin_update(); + LLOGLN(10, ("rdpCopyAreaPixmapToWnd: num_clips %d", num_clips)); + for (j = 0; j < num_clips; j++) + { + box = REGION_RECTS(&clip_reg)[j]; + LLOGLN(10, ("rdpCopyAreaPixmapToWnd: %d %d %d %d", box.x1, box.y1, box.x2, box.y2)); + rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + LLOGLN(10, ("rdpCopyAreaPixmapToWnd: %d %d", w, h)); + rdpup_paint_rect_os(ldstx, ldsty, w, h, pSrcPriv->rdpindex, lsrcx, lsrcy); + } + rdpup_reset_clip(); + rdpup_end_update(); + } + } + RegionUninit(&clip_reg); + return rv; +} + +/******************************************************************************/ +/* draw from an off screen pixmap to an off screen pixmap */ +static RegionPtr +rdpCopyAreaPixmapToPixmap(PixmapPtr pSrcPixmap, rdpPixmapRec* pSrcPriv, + PixmapPtr pDstPixmap, rdpPixmapRec* pDstPriv, + GCPtr pGC, int srcx, int srcy, int w, int h, + int dstx, int dsty) +{ + int lsrcx; + int lsrcy; + int ldstx; + int ldsty; + int cd; + int j; + int num_clips; + RegionPtr rv; + RegionRec clip_reg; + BoxRec box; + + LLOGLN(10, ("rdpCopyAreaPixmapToPixmap:")); + + rv = rdpCopyAreaOrg(&(pSrcPixmap->drawable), &(pDstPixmap->drawable), + pGC, srcx, srcy, w, h, dstx, dsty); + RegionInit(&clip_reg, NullBox, 0); + cd = rdp_get_clip(&clip_reg, &(pDstPixmap->drawable), pGC); + LLOGLN(10, ("rdpCopyAreaPixmapToPixmap: cd %d", cd)); + ldstx = pDstPixmap->drawable.x + dstx; + ldsty = pDstPixmap->drawable.y + dsty; + lsrcx = pSrcPixmap->drawable.x + srcx; + lsrcy = pSrcPixmap->drawable.y + srcy; + if (cd == 1) + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + rdpup_begin_update(); + rdpup_paint_rect_os(ldstx, ldsty, w, h, pSrcPriv->rdpindex, lsrcx, lsrcy); + LLOGLN(10, ("%d %d %d %d %d %d", ldstx, ldsty, w, h, lsrcx, lsrcy)); + rdpup_end_update(); + rdpup_switch_os_surface(-1); + } + else if (cd == 2) + { + num_clips = REGION_NUM_RECTS(&clip_reg); + if (num_clips > 0) + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + rdpup_begin_update(); + LLOGLN(10, ("rdpCopyAreaPixmapToPixmap: num_clips %d", num_clips)); + for (j = 0; j < num_clips; j++) + { + box = REGION_RECTS(&clip_reg)[j]; + rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + rdpup_paint_rect_os(ldstx, ldsty, w, h, pSrcPriv->rdpindex, lsrcx, lsrcy); + LLOGLN(10, ("%d %d %d %d %d %d", ldstx, ldsty, w, h, lsrcx, lsrcy)); + } + rdpup_reset_clip(); + rdpup_end_update(); + rdpup_switch_os_surface(-1); + } + } + RegionUninit(&clip_reg); + return rv; +} + +/******************************************************************************/ +RegionPtr +rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + int srcx, int srcy, int w, int h, int dstx, int dsty) +{ + RegionPtr rv; + RegionRec clip_reg; + RegionRec box_reg; + RegionRec reg1; + int num_clips; + int cd; + int j; + int can_do_screen_blt; + int got_id; + int dirty_type; + int post_process; + int reset_surface; + struct image_data id; + BoxRec box; + BoxPtr pbox; + PixmapPtr pSrcPixmap; + PixmapPtr pDstPixmap; + rdpPixmapRec* pSrcPriv; + rdpPixmapRec* pDstPriv; + rdpPixmapRec* pDirtyPriv; + WindowPtr pDstWnd; + WindowPtr pSrcWnd; + + LLOGLN(10, ("rdpCopyArea:")); + + if (pSrc->type == DRAWABLE_WINDOW) + { + pSrcWnd = (WindowPtr)pSrc; + if (pSrcWnd->viewable) + { + if (pDst->type == DRAWABLE_WINDOW) + { + pDstWnd = (WindowPtr)pDst; + if (pDstWnd->viewable) + { + can_do_screen_blt = pGC->alu == GXcopy; + if (can_do_screen_blt) + { + return rdpCopyAreaWndToWnd(pSrcWnd, pDstWnd, pGC, + srcx, srcy, w, h, dstx, dsty); + } + } + } + else if (pDst->type == DRAWABLE_PIXMAP) + { + pDstPixmap = (PixmapPtr)pDst; + pDstPriv = GETPIXPRIV(pDstPixmap); + if (XRDP_IS_OS(pDstPriv)) + { + can_do_screen_blt = pGC->alu == GXcopy; + if (can_do_screen_blt) + { + rdpup_check_dirty(pDstPixmap, pDstPriv); + return rdpCopyAreaWndToPixmap(pSrcWnd, pDstPixmap, pDstPriv, pGC, + srcx, srcy, w, h, dstx, dsty); + } + } + } + } + } + if (pSrc->type == DRAWABLE_PIXMAP) + { + pSrcPixmap = (PixmapPtr)pSrc; + pSrcPriv = GETPIXPRIV(pSrcPixmap); + if (XRDP_IS_OS(pSrcPriv)) + { + if (pDst->type == DRAWABLE_WINDOW) + { + pDstWnd = (WindowPtr)pDst; + if (pDstWnd->viewable) + { + rdpup_check_dirty(pSrcPixmap, pSrcPriv); + return rdpCopyAreaPixmapToWnd(pSrcPixmap, pSrcPriv, pDstWnd, pGC, + srcx, srcy, w, h, dstx, dsty); + } + } + else if (pDst->type == DRAWABLE_PIXMAP) + { + pDstPixmap = (PixmapPtr)pDst; + pDstPriv = GETPIXPRIV(pDstPixmap); + if (XRDP_IS_OS(pDstPriv)) + { + if (g_can_do_pix_to_pix) + { + rdpup_check_dirty(pSrcPixmap, pSrcPriv); + rdpup_check_dirty(pDstPixmap, pDstPriv); + return rdpCopyAreaPixmapToPixmap(pSrcPixmap, pSrcPriv, + pDstPixmap, pDstPriv, + pGC, srcx, srcy, w, h, + dstx, dsty); + } + } + } + } + } + + /* do original call */ + rv = rdpCopyAreaOrg(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); + + dirty_type = 0; + pDirtyPriv = 0; + post_process = 0; + reset_surface = 0; + got_id = 0; + if (pDst->type == DRAWABLE_PIXMAP) + { + pDstPixmap = (PixmapPtr)pDst; + pDstPriv = GETPIXPRIV(pDstPixmap); + if (XRDP_IS_OS(pDstPriv)) + { + post_process = 1; + if (g_do_dirty_os) + { + LLOGLN(10, ("rdpCopyArea: gettig dirty")); + pDstPriv->is_dirty = 1; + pDirtyPriv = pDstPriv; + dirty_type = RDI_IMGLL; + } + else + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + reset_surface = 1; + rdpup_get_pixmap_image_rect(pDstPixmap, &id); + got_id = 1; + } + } + } + else + { + if (pDst->type == DRAWABLE_WINDOW) + { + pDstWnd = (WindowPtr)pDst; + if (pDstWnd->viewable) + { + post_process = 1; + rdpup_get_screen_image_rect(&id); + got_id = 1; + } + } + } + if (!post_process) + { + return rv; + } + + RegionInit(&clip_reg, NullBox, 0); + cd = rdp_get_clip(&clip_reg, pDst, pGC); + if (cd == 1) + { + if (dirty_type != 0) + { + box.x1 = pDst->x + dstx; + box.y1 = pDst->y + dsty; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + RegionInit(®1, &box, 0); + draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type); + RegionUninit(®1); + } + else if (got_id) + { + rdpup_begin_update(); + rdpup_send_area(&id, pDst->x + dstx, pDst->y + dsty, w, h); + rdpup_end_update(); + } + } + else if (cd == 2) + { + num_clips = REGION_NUM_RECTS(&clip_reg); + if (num_clips > 0) + { + if (dirty_type != 0) + { + box.x1 = pDst->x + dstx; + box.y1 = pDst->y + dsty; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + RegionInit(&box_reg, &box, 0); + RegionIntersect(&clip_reg, &clip_reg, &box_reg); + draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type); + RegionUninit(&box_reg); + } + else if (got_id) + { + rdpup_begin_update(); + box.x1 = pDst->x + dstx; + box.y1 = pDst->y + dsty; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + RegionInit(&box_reg, &box, 0); + RegionIntersect(&clip_reg, &clip_reg, &box_reg); + num_clips = REGION_NUM_RECTS(&clip_reg); + if (num_clips < 10) + { + for (j = num_clips - 1; j >= 0; j--) + { + box = REGION_RECTS(&clip_reg)[j]; + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, + box.y2 - box.y1); + } + } + else + { + pbox = RegionExtents(&clip_reg); + rdpup_send_area(&id, pbox->x1, pbox->y1, pbox->x2 - pbox->x1, + pbox->y2 - pbox->y1); + } + RegionUninit(&box_reg); + rdpup_end_update(); + } + } + } + RegionUninit(&clip_reg); + if (reset_surface) + { + rdpup_switch_os_surface(-1); + } + return rv; +} diff --git a/xorg/X11R7.6/rdp/rdpCopyArea.h b/xorg/X11R7.6/rdp/rdpCopyArea.h new file mode 100644 index 00000000..d5d7c27b --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpCopyArea.h @@ -0,0 +1,29 @@ +/* +Copyright 2005-2012 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 __RDPCOPYAREA_H +#define __RDPCOPYAREA_H + +RegionPtr +rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + int srcx, int srcy, int w, int h, int dstx, int dsty); + +#endif diff --git a/xorg/X11R7.6/rdp/rdpCopyPlane.c b/xorg/X11R7.6/rdp/rdpCopyPlane.c new file mode 100644 index 00000000..389dc6e1 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpCopyPlane.c @@ -0,0 +1,216 @@ +/* +Copyright 2005-2012 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 "rdp.h" +#include "rdpdraw.h" + +#define LDEBUG 0 + +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpGCIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpWindowIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */ +extern int g_Bpp; /* from rdpmain.c */ +extern ScreenPtr g_pScreen; /* from rdpmain.c */ +extern Bool g_wrapPixmap; /* from rdpmain.c */ +extern int g_do_dirty_os; /* in rdpmain.c */ + +extern GCOps g_rdpGCOps; /* from rdpdraw.c */ + +extern int g_con_number; /* in rdpup.c */ + +/******************************************************************************/ +RegionPtr +rdpCopyPlaneOrg(DrawablePtr pSrc, DrawablePtr pDst, + GCPtr pGC, int srcx, int srcy, int w, int h, + int dstx, int dsty, unsigned long bitPlane) +{ + RegionPtr rv; + rdpGCPtr priv; + GCFuncs* oldFuncs; + + GC_OP_PROLOGUE(pGC); + rv = pGC->ops->CopyPlane(pSrc, pDst, pGC, srcx, srcy, + w, h, dstx, dsty, bitPlane); + GC_OP_EPILOGUE(pGC); + return rv; +} + +/******************************************************************************/ +RegionPtr +rdpCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, + GCPtr pGC, int srcx, int srcy, int w, int h, + int dstx, int dsty, unsigned long bitPlane) +{ + RegionPtr rv; + RegionRec clip_reg; + RegionRec box_reg; + RegionRec reg1; + RegionRec reg2; + int cd; + int num_clips; + int j; + int got_id; + int dirty_type; + int post_process; + int reset_surface; + BoxRec box; + BoxPtr pbox; + struct image_data id; + WindowPtr pDstWnd; + PixmapPtr pDstPixmap; + rdpPixmapRec* pDstPriv; + rdpPixmapRec* pDirtyPriv; + + LLOGLN(10, ("rdpCopyPlane:")); + + /* do original call */ + rv = rdpCopyPlaneOrg(pSrc, pDst, pGC, srcx, srcy, w, h, + dstx, dsty, bitPlane); + + dirty_type = 0; + pDirtyPriv = 0; + post_process = 0; + reset_surface = 0; + got_id = 0; + if (pDst->type == DRAWABLE_PIXMAP) + { + pDstPixmap = (PixmapPtr)pDst; + pDstPriv = GETPIXPRIV(pDstPixmap); + if (XRDP_IS_OS(pDstPriv)) + { + post_process = 1; + if (g_do_dirty_os) + { + LLOGLN(10, ("rdpCopyPlane: gettig dirty")); + pDstPriv->is_dirty = 1; + pDirtyPriv = pDstPriv; + dirty_type = RDI_IMGLL; + } + else + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + reset_surface = 1; + rdpup_get_pixmap_image_rect(pDstPixmap, &id); + got_id = 1; + } + } + } + else + { + if (pDst->type == DRAWABLE_WINDOW) + { + pDstWnd = (WindowPtr)pDst; + if (pDstWnd->viewable) + { + post_process = 1; + rdpup_get_screen_image_rect(&id); + got_id = 1; + } + } + } + if (!post_process) + { + return rv; + } + + RegionInit(&clip_reg, NullBox, 0); + cd = rdp_get_clip(&clip_reg, pDst, pGC); + if (cd == 1) + { + if (dirty_type != 0) + { + box.x1 = pDst->x + dstx; + box.y1 = pDst->y + dsty; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + RegionInit(®1, &box, 0); + draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type); + RegionUninit(®1); + } + else if (got_id) + { + rdpup_begin_update(); + rdpup_send_area(&id, pDst->x + dstx, pDst->y + dsty, w, h); + rdpup_end_update(); + } + } + else if (cd == 2) + { + num_clips = REGION_NUM_RECTS(&clip_reg); + if (num_clips > 0) + { + if (dirty_type != 0) + { + box.x1 = pDst->x + dstx; + box.y1 = pDst->y + dsty; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + RegionInit(®1, &box, 0); + RegionInit(®2, NullBox, 0); + RegionCopy(®2, &clip_reg); + RegionIntersect(®1, ®1, ®2); + draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type); + RegionUninit(®1); + RegionUninit(®2); + } + else if (got_id) + { + rdpup_begin_update(); + box.x1 = pDst->x + dstx; + box.y1 = pDst->y + dsty; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + RegionInit(&box_reg, &box, 0); + RegionIntersect(&clip_reg, &clip_reg, &box_reg); + num_clips = REGION_NUM_RECTS(&clip_reg); + if (num_clips < 10) + { + for (j = num_clips - 1; j >= 0; j--) + { + box = REGION_RECTS(&clip_reg)[j]; + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + } + } + else + { + pbox = RegionExtents(&clip_reg); + rdpup_send_area(&id, pbox->x1, pbox->y1, pbox->x2 - pbox->x1, + pbox->y2 - pbox->y1); + } + RegionUninit(&box_reg); + rdpup_end_update(); + } + } + } + RegionUninit(&clip_reg); + if (reset_surface) + { + rdpup_switch_os_surface(-1); + } + return rv; +} diff --git a/xorg/X11R7.6/rdp/rdpCopyPlane.h b/xorg/X11R7.6/rdp/rdpCopyPlane.h new file mode 100644 index 00000000..ae87edc7 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpCopyPlane.h @@ -0,0 +1,30 @@ +/* +Copyright 2005-2012 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 __RDPCOPYPLANE_H +#define __RDPCOPYPLANE_H + +RegionPtr +rdpCopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, + GCPtr pGC, int srcx, int srcy, int width, int height, + int dstx, int dsty, unsigned long bitPlane); + +#endif diff --git a/xorg/X11R7.6/rdp/rdpFillPolygon.c b/xorg/X11R7.6/rdp/rdpFillPolygon.c new file mode 100644 index 00000000..bf71c094 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpFillPolygon.c @@ -0,0 +1,220 @@ +/* +Copyright 2005-2012 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 "rdp.h" +#include "rdpdraw.h" + +#define LDEBUG 0 + +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpGCIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpWindowIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */ +extern int g_Bpp; /* from rdpmain.c */ +extern ScreenPtr g_pScreen; /* from rdpmain.c */ +extern Bool g_wrapPixmap; /* from rdpmain.c */ +extern int g_do_dirty_os; /* in rdpmain.c */ + +extern GCOps g_rdpGCOps; /* from rdpdraw.c */ + +extern int g_con_number; /* in rdpup.c */ + +/******************************************************************************/ +void +rdpFillPolygonOrg(DrawablePtr pDrawable, GCPtr pGC, + int shape, int mode, int count, + DDXPointPtr pPts) +{ + rdpGCPtr priv; + GCFuncs* oldFuncs; + + GC_OP_PROLOGUE(pGC); + pGC->ops->FillPolygon(pDrawable, pGC, shape, mode, count, pPts); + GC_OP_EPILOGUE(pGC); +} + +/******************************************************************************/ +void +rdpFillPolygon(DrawablePtr pDrawable, GCPtr pGC, + int shape, int mode, int count, + DDXPointPtr pPts) +{ + RegionRec clip_reg; + RegionRec box_reg; + RegionRec reg1; + int num_clips; + int cd; + int maxx; + int maxy; + int minx; + int miny; + int i; + int j; + int got_id; + int dirty_type; + int post_process; + int reset_surface; + BoxRec box; + struct image_data id; + WindowPtr pDstWnd; + PixmapPtr pDstPixmap; + rdpPixmapRec* pDstPriv; + rdpPixmapRec* pDirtyPriv; + + LLOGLN(10, ("rdpFillPolygon:")); + + 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 (i = 1; i < count; i++) + { + if (pPts[i].x > maxx) + { + maxx = pPts[i].x; + } + if (pPts[i].x < minx) + { + minx = pPts[i].x; + } + if (pPts[i].y > maxy) + { + maxy = pPts[i].y; + } + if (pPts[i].y < miny) + { + miny = pPts[i].y; + } + } + box.x1 = pDrawable->x + minx; + box.y1 = pDrawable->y + miny; + box.x2 = pDrawable->x + maxx + 1; + box.y2 = pDrawable->y + maxy + 1; + } + + /* do original call */ + rdpFillPolygonOrg(pDrawable, pGC, shape, mode, count, pPts); + + dirty_type = 0; + pDirtyPriv = 0; + post_process = 0; + reset_surface = 0; + got_id = 0; + if (pDrawable->type == DRAWABLE_PIXMAP) + { + pDstPixmap = (PixmapPtr)pDrawable; + pDstPriv = GETPIXPRIV(pDstPixmap); + if (XRDP_IS_OS(pDstPriv)) + { + post_process = 1; + if (g_do_dirty_os) + { + LLOGLN(10, ("rdpFillPolygon: gettig dirty")); + pDstPriv->is_dirty = 1; + pDirtyPriv = pDstPriv; + dirty_type = RDI_IMGLL; + } + else + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + reset_surface = 1; + rdpup_get_pixmap_image_rect(pDstPixmap, &id); + got_id = 1; + } + } + } + else + { + if (pDrawable->type == DRAWABLE_WINDOW) + { + pDstWnd = (WindowPtr)pDrawable; + if (pDstWnd->viewable) + { + post_process = 1; + rdpup_get_screen_image_rect(&id); + got_id = 1; + } + } + } + if (!post_process) + { + return; + } + + RegionInit(&clip_reg, NullBox, 0); + cd = rdp_get_clip(&clip_reg, pDrawable, pGC); + if (cd == 1) + { + if (dirty_type != 0) + { + RegionInit(®1, &box, 0); + draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type); + RegionUninit(®1); + } + else if (got_id) + { + rdpup_begin_update(); + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + rdpup_end_update(); + } + } + else if (cd == 2) + { + RegionInit(&box_reg, &box, 0); + RegionIntersect(&clip_reg, &clip_reg, &box_reg); + num_clips = REGION_NUM_RECTS(&clip_reg); + if (num_clips > 0) + { + if (dirty_type != 0) + { + draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type); + } + else if (got_id) + { + rdpup_begin_update(); + for (j = num_clips - 1; j >= 0; j--) + { + box = REGION_RECTS(&clip_reg)[j]; + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + } + rdpup_end_update(); + } + } + RegionUninit(&box_reg); + } + RegionUninit(&clip_reg); + if (reset_surface) + { + rdpup_switch_os_surface(-1); + } +} diff --git a/xorg/X11R7.6/rdp/rdpFillPolygon.h b/xorg/X11R7.6/rdp/rdpFillPolygon.h new file mode 100644 index 00000000..bb01c379 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpFillPolygon.h @@ -0,0 +1,30 @@ +/* +Copyright 2005-2012 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 __RDPFILLPOLYGON_H +#define __RDPFILLPOLYGON_H + +void +rdpFillPolygon(DrawablePtr pDrawable, GCPtr pGC, + int shape, int mode, int count, + DDXPointPtr pPts); + +#endif diff --git a/xorg/X11R7.6/rdp/rdpFillSpans.c b/xorg/X11R7.6/rdp/rdpFillSpans.c new file mode 100644 index 00000000..5c3dcc67 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpFillSpans.c @@ -0,0 +1,114 @@ +/* +Copyright 2005-2012 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 "rdp.h" +#include "rdpdraw.h" + +#define LDEBUG 0 + +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpGCIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpWindowIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */ +extern int g_Bpp; /* from rdpmain.c */ +extern ScreenPtr g_pScreen; /* from rdpmain.c */ +extern Bool g_wrapPixmap; /* from rdpmain.c */ + +extern GCOps g_rdpGCOps; /* from rdpdraw.c */ + +extern int g_con_number; /* in rdpup.c */ + +/******************************************************************************/ +static void +rdpFillSpansOrg(DrawablePtr pDrawable, GCPtr pGC, int nInit, + DDXPointPtr pptInit, int* pwidthInit, int fSorted) +{ + rdpGCPtr priv; + GCFuncs* oldFuncs; + + GC_OP_PROLOGUE(pGC); + pGC->ops->FillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted); + GC_OP_EPILOGUE(pGC); +} + +/******************************************************************************/ +void +rdpFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit, + DDXPointPtr pptInit, int* pwidthInit, int fSorted) +{ + RegionRec clip_reg; + int cd; + int got_id; + struct image_data id; + WindowPtr pDstWnd; + PixmapPtr pDstPixmap; + rdpPixmapRec* pDstPriv; + + LLOGLN(10, ("rdpFillSpans: todo")); + + /* do original call */ + rdpFillSpansOrg(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted); + + got_id = 0; + if (pDrawable->type == DRAWABLE_PIXMAP) + { + pDstPixmap = (PixmapPtr)pDrawable; + pDstPriv = GETPIXPRIV(pDstPixmap); + if (XRDP_IS_OS(pDstPriv)) + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + rdpup_get_pixmap_image_rect(pDstPixmap, &id); + got_id = 1; + } + } + else + { + if (pDrawable->type == DRAWABLE_WINDOW) + { + pDstWnd = (WindowPtr)pDrawable; + if (pDstWnd->viewable) + { + rdpup_get_screen_image_rect(&id); + got_id = 1; + } + } + } + if (!got_id) + { + return; + } + RegionInit(&clip_reg, NullBox, 0); + cd = rdp_get_clip(&clip_reg, pDrawable, pGC); + if (cd == 1) + { + } + else if (cd == 2) + { + } + RegionUninit(&clip_reg); + rdpup_switch_os_surface(-1); +} diff --git a/xorg/X11R7.6/rdp/rdpFillSpans.h b/xorg/X11R7.6/rdp/rdpFillSpans.h new file mode 100644 index 00000000..744f0f17 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpFillSpans.h @@ -0,0 +1,29 @@ +/* +Copyright 2005-2012 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 __RDPFILLSPANS_H +#define __RDPFILLSPANS_H + +void +rdpFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit, + DDXPointPtr pptInit, int* pwidthInit, int fSorted); + +#endif diff --git a/xorg/X11R7.6/rdp/rdpImageGlyphBlt.c b/xorg/X11R7.6/rdp/rdpImageGlyphBlt.c new file mode 100644 index 00000000..25d23a51 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpImageGlyphBlt.c @@ -0,0 +1,192 @@ +/* +Copyright 2005-2012 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 "rdp.h" +#include "rdpdraw.h" + +#define LDEBUG 0 + +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpGCIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpWindowIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */ +extern int g_Bpp; /* from rdpmain.c */ +extern ScreenPtr g_pScreen; /* from rdpmain.c */ +extern Bool g_wrapPixmap; /* from rdpmain.c */ +extern int g_do_dirty_os; /* in rdpmain.c */ + +extern GCOps g_rdpGCOps; /* from rdpdraw.c */ + +extern int g_con_number; /* in rdpup.c */ + +/******************************************************************************/ +void +rdpImageGlyphBltOrg(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, unsigned int nglyph, + CharInfoPtr* ppci, pointer pglyphBase) +{ + rdpGCPtr priv; + GCFuncs* oldFuncs; + + GC_OP_PROLOGUE(pGC); + pGC->ops->ImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + GC_OP_EPILOGUE(pGC); +} + +/******************************************************************************/ +void +rdpImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, unsigned int nglyph, + CharInfoPtr* ppci, pointer pglyphBase) +{ + RegionRec reg; + RegionRec reg1; + int num_clips; + int cd; + int j; + int got_id; + int dirty_type; + int post_process; + int reset_surface; + BoxRec box; + struct image_data id; + WindowPtr pDstWnd; + PixmapPtr pDstPixmap; + rdpPixmapRec* pDstPriv; + rdpPixmapRec* pDirtyPriv; + + LLOGLN(10, ("rdpImageGlyphBlt:")); + + if (nglyph != 0) + { + GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box); + } + + /* do original call */ + rdpImageGlyphBltOrg(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + + dirty_type = 0; + pDirtyPriv = 0; + post_process = 0; + reset_surface = 0; + got_id = 0; + if (pDrawable->type == DRAWABLE_PIXMAP) + { + pDstPixmap = (PixmapPtr)pDrawable; + pDstPriv = GETPIXPRIV(pDstPixmap); + if (XRDP_IS_OS(pDstPriv)) + { + post_process = 1; + if (g_do_dirty_os) + { + LLOGLN(10, ("rdpImageGlyphBlt: gettig dirty")); + pDstPriv->is_dirty = 1; + pDirtyPriv = pDstPriv; + dirty_type = RDI_IMGLL; + } + else + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + reset_surface = 1; + rdpup_get_pixmap_image_rect(pDstPixmap, &id); + got_id = 1; + } + } + } + else + { + if (pDrawable->type == DRAWABLE_WINDOW) + { + pDstWnd = (WindowPtr)pDrawable; + if (pDstWnd->viewable) + { + post_process = 1; + rdpup_get_screen_image_rect(&id); + got_id = 1; + } + } + } + if (!post_process) + { + return; + } + + RegionInit(®, NullBox, 0); + if (nglyph == 0) + { + cd = 0; + } + else + { + cd = rdp_get_clip(®, pDrawable, pGC); + } + if (cd == 1) + { + if (dirty_type != 0) + { + RegionInit(®1, &box, 0); + draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type); + RegionUninit(®1); + } + else if (got_id) + { + rdpup_begin_update(); + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + rdpup_end_update(); + } + } + else if (cd == 2) + { + RegionInit(®1, &box, 0); + RegionIntersect(®, ®, ®1); + num_clips = REGION_NUM_RECTS(®); + if (num_clips > 0) + { + if (dirty_type != 0) + { + draw_item_add_img_region(pDirtyPriv, ®, GXcopy, dirty_type); + } + else if (got_id) + { + rdpup_begin_update(); + for (j = num_clips - 1; j >= 0; j--) + { + box = REGION_RECTS(®)[j]; + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + } + rdpup_end_update(); + } + } + RegionUninit(®1); + } + RegionUninit(®); + if (reset_surface) + { + rdpup_switch_os_surface(-1); + } + return; +} diff --git a/xorg/X11R7.6/rdp/rdpImageGlyphBlt.h b/xorg/X11R7.6/rdp/rdpImageGlyphBlt.h new file mode 100644 index 00000000..47fca1b3 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpImageGlyphBlt.h @@ -0,0 +1,30 @@ +/* +Copyright 2005-2012 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 __RDPIMAGEGLYPHBLT_H +#define __RDPIMAGEGLYPHBLT_H + +void +rdpImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, unsigned int nglyph, + CharInfoPtr* ppci, pointer pglyphBase); + +#endif diff --git a/xorg/X11R7.6/rdp/rdpImageText16.c b/xorg/X11R7.6/rdp/rdpImageText16.c new file mode 100644 index 00000000..103344c6 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpImageText16.c @@ -0,0 +1,191 @@ +/* +Copyright 2005-2012 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 "rdp.h" +#include "rdpdraw.h" + +#define LDEBUG 0 + +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpGCIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpWindowIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */ +extern int g_Bpp; /* from rdpmain.c */ +extern ScreenPtr g_pScreen; /* from rdpmain.c */ +extern Bool g_wrapPixmap; /* from rdpmain.c */ +extern int g_do_dirty_os; /* in rdpmain.c */ + +extern GCOps g_rdpGCOps; /* from rdpdraw.c */ + +extern int g_con_number; /* in rdpup.c */ + +/******************************************************************************/ +void +rdpImageText16Org(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, int count, unsigned short* chars) +{ + rdpGCPtr priv; + GCFuncs* oldFuncs; + + GC_OP_PROLOGUE(pGC); + pGC->ops->ImageText16(pDrawable, pGC, x, y, count, chars); + GC_OP_EPILOGUE(pGC); +} + +/******************************************************************************/ +void +rdpImageText16(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, int count, unsigned short* chars) +{ + RegionRec reg; + RegionRec reg1; + int num_clips; + int cd; + int j; + int got_id; + int dirty_type; + int post_process; + int reset_surface; + BoxRec box; + struct image_data id; + WindowPtr pDstWnd; + PixmapPtr pDstPixmap; + rdpPixmapRec* pDstPriv; + rdpPixmapRec* pDirtyPriv; + + LLOGLN(10, ("rdpImageText16:")); + + if (count != 0) + { + GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); + } + + /* do original call */ + rdpImageText16Org(pDrawable, pGC, x, y, count, chars); + + dirty_type = 0; + pDirtyPriv = 0; + post_process = 0; + reset_surface = 0; + got_id = 0; + if (pDrawable->type == DRAWABLE_PIXMAP) + { + pDstPixmap = (PixmapPtr)pDrawable; + pDstPriv = GETPIXPRIV(pDstPixmap); + if (XRDP_IS_OS(pDstPriv)) + { + post_process = 1; + if (g_do_dirty_os) + { + LLOGLN(10, ("rdpImageText16: gettig dirty")); + pDstPriv->is_dirty = 1; + pDirtyPriv = pDstPriv; + dirty_type = RDI_IMGLY; + } + else + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + reset_surface = 1; + rdpup_get_pixmap_image_rect(pDstPixmap, &id); + got_id = 1; + } + } + } + else + { + if (pDrawable->type == DRAWABLE_WINDOW) + { + pDstWnd = (WindowPtr)pDrawable; + if (pDstWnd->viewable) + { + post_process = 1; + rdpup_get_screen_image_rect(&id); + got_id = 1; + } + } + } + if (!post_process) + { + return; + } + + RegionInit(®, NullBox, 0); + if (count == 0) + { + cd = 0; + } + else + { + cd = rdp_get_clip(®, pDrawable, pGC); + } + if (cd == 1) + { + if (dirty_type != 0) + { + RegionInit(®1, &box, 0); + draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type); + RegionUninit(®1); + } + else if (got_id) + { + rdpup_begin_update(); + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + rdpup_end_update(); + } + } + else if (cd == 2) + { + RegionInit(®1, &box, 0); + RegionIntersect(®, ®, ®1); + num_clips = REGION_NUM_RECTS(®); + if (num_clips > 0) + { + if (dirty_type != 0) + { + draw_item_add_img_region(pDirtyPriv, ®, GXcopy, dirty_type); + } + else if (got_id) + { + rdpup_begin_update(); + for (j = num_clips - 1; j >= 0; j--) + { + box = REGION_RECTS(®)[j]; + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, + box.y2 - box.y1); + } + rdpup_end_update(); + } + } + RegionUninit(®1); + } + RegionUninit(®); + if (reset_surface) + { + rdpup_switch_os_surface(-1); + } + return; +} diff --git a/xorg/X11R7.6/rdp/rdpImageText16.h b/xorg/X11R7.6/rdp/rdpImageText16.h new file mode 100644 index 00000000..3fe4f205 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpImageText16.h @@ -0,0 +1,29 @@ +/* +Copyright 2005-2012 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 __RDPIMAGETEXT16_H +#define __RDPIMAGETEXT16_H + +void +rdpImageText16(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, int count, unsigned short* chars); + +#endif diff --git a/xorg/X11R7.6/rdp/rdpImageText8.c b/xorg/X11R7.6/rdp/rdpImageText8.c new file mode 100644 index 00000000..ba958a21 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpImageText8.c @@ -0,0 +1,191 @@ +/* +Copyright 2005-2012 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 "rdp.h" +#include "rdpdraw.h" + +#define LDEBUG 0 + +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpGCIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpWindowIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */ +extern int g_Bpp; /* from rdpmain.c */ +extern ScreenPtr g_pScreen; /* from rdpmain.c */ +extern Bool g_wrapPixmap; /* from rdpmain.c */ +extern int g_do_dirty_os; /* in rdpmain.c */ + +extern GCOps g_rdpGCOps; /* from rdpdraw.c */ + +extern int g_con_number; /* in rdpup.c */ + +/******************************************************************************/ +void +rdpImageText8Org(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, int count, char* chars) +{ + rdpGCPtr priv; + GCFuncs* oldFuncs; + + GC_OP_PROLOGUE(pGC); + pGC->ops->ImageText8(pDrawable, pGC, x, y, count, chars); + GC_OP_EPILOGUE(pGC); +} + +/******************************************************************************/ +void +rdpImageText8(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, int count, char* chars) +{ + RegionRec reg; + RegionRec reg1; + int num_clips; + int cd; + int j; + int got_id; + int dirty_type; + int post_process; + int reset_surface; + BoxRec box; + struct image_data id; + WindowPtr pDstWnd; + PixmapPtr pDstPixmap; + rdpPixmapRec* pDstPriv; + rdpPixmapRec* pDirtyPriv; + + LLOGLN(10, ("rdpImageText8:")); + + if (count != 0) + { + GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); + } + + /* do original call */ + rdpImageText8Org(pDrawable, pGC, x, y, count, chars); + + dirty_type = 0; + pDirtyPriv = 0; + post_process = 0; + reset_surface = 0; + got_id = 0; + if (pDrawable->type == DRAWABLE_PIXMAP) + { + pDstPixmap = (PixmapPtr)pDrawable; + pDstPriv = GETPIXPRIV(pDstPixmap); + if (XRDP_IS_OS(pDstPriv)) + { + post_process = 1; + if (g_do_dirty_os) + { + LLOGLN(10, ("rdpImageText8: gettig dirty")); + pDstPriv->is_dirty = 1; + pDirtyPriv = pDstPriv; + dirty_type = RDI_IMGLL; + } + else + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + reset_surface = 1; + rdpup_get_pixmap_image_rect(pDstPixmap, &id); + got_id = 1; + } + } + } + else + { + if (pDrawable->type == DRAWABLE_WINDOW) + { + pDstWnd = (WindowPtr)pDrawable; + if (pDstWnd->viewable) + { + post_process = 1; + rdpup_get_screen_image_rect(&id); + got_id = 1; + } + } + } + if (!post_process) + { + return; + } + + RegionInit(®, NullBox, 0); + if (count == 0) + { + cd = 0; + } + else + { + cd = rdp_get_clip(®, pDrawable, pGC); + } + if (cd == 1) + { + if (dirty_type != 0) + { + RegionInit(®1, &box, 0); + draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type); + RegionUninit(®1); + } + else if (got_id) + { + rdpup_begin_update(); + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + rdpup_end_update(); + } + } + else if (cd == 2) + { + RegionInit(®1, &box, 0); + RegionIntersect(®, ®, ®1); + num_clips = REGION_NUM_RECTS(®); + if (num_clips > 0) + { + if (dirty_type != 0) + { + draw_item_add_img_region(pDirtyPriv, ®, GXcopy, dirty_type); + } + else if (got_id) + { + rdpup_begin_update(); + for (j = num_clips - 1; j >= 0; j--) + { + box = REGION_RECTS(®)[j]; + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, + box.y2 - box.y1); + } + rdpup_end_update(); + } + } + RegionUninit(®1); + } + RegionUninit(®); + if (reset_surface) + { + rdpup_switch_os_surface(-1); + } + return; +} diff --git a/xorg/X11R7.6/rdp/rdpImageText8.h b/xorg/X11R7.6/rdp/rdpImageText8.h new file mode 100644 index 00000000..1a81b271 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpImageText8.h @@ -0,0 +1,29 @@ +/* +Copyright 2005-2012 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 __RDPIMAGETEXT8_H +#define __RDPIMAGETEXT8_H + +void +rdpImageText8(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, int count, char* chars); + +#endif diff --git a/xorg/X11R7.6/rdp/rdpPolyArc.c b/xorg/X11R7.6/rdp/rdpPolyArc.c new file mode 100644 index 00000000..ba890f0c --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpPolyArc.c @@ -0,0 +1,215 @@ +/* +Copyright 2005-2012 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 "rdp.h" +#include "rdpdraw.h" + +#define LDEBUG 0 + +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpGCIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpWindowIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */ +extern int g_Bpp; /* from rdpmain.c */ +extern ScreenPtr g_pScreen; /* from rdpmain.c */ +extern Bool g_wrapPixmap; /* from rdpmain.c */ +extern int g_do_dirty_os; /* in rdpmain.c */ + +extern GCOps g_rdpGCOps; /* from rdpdraw.c */ + +extern int g_con_number; /* in rdpup.c */ + +/******************************************************************************/ +void +rdpPolyArcOrg(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc* parcs) +{ + rdpGCPtr priv; + GCFuncs* oldFuncs; + + GC_OP_PROLOGUE(pGC); + pGC->ops->PolyArc(pDrawable, pGC, narcs, parcs); + GC_OP_EPILOGUE(pGC); +} + +/******************************************************************************/ +void +rdpPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc* parcs) +{ + RegionRec clip_reg; + RegionPtr tmpRegion; + int cd; + int lw; + int extra; + int i; + int num_clips; + int got_id; + int dirty_type; + int post_process; + int reset_surface; + xRectangle* rects; + BoxRec box; + struct image_data id; + WindowPtr pDstWnd; + PixmapPtr pDstPixmap; + rdpPixmapRec* pDstPriv; + rdpPixmapRec* pDirtyPriv; + + LLOGLN(10, ("rdpPolyArc:")); + + rects = 0; + if (narcs > 0) + { + rects = (xRectangle*)g_malloc(narcs * sizeof(xRectangle), 0); + lw = pGC->lineWidth; + if (lw == 0) + { + lw = 1; + } + extra = lw / 2; + for (i = 0; i < narcs; i++) + { + rects[i].x = (parcs[i].x - extra) + pDrawable->x; + rects[i].y = (parcs[i].y - extra) + pDrawable->y; + rects[i].width = parcs[i].width + lw; + rects[i].height = parcs[i].height + lw; + } + } + + /* do original call */ + rdpPolyArcOrg(pDrawable, pGC, narcs, parcs); + + dirty_type = 0; + pDirtyPriv = 0; + post_process = 0; + reset_surface = 0; + got_id = 0; + if (pDrawable->type == DRAWABLE_PIXMAP) + { + pDstPixmap = (PixmapPtr)pDrawable; + pDstPriv = GETPIXPRIV(pDstPixmap); + if (XRDP_IS_OS(pDstPriv)) + { + post_process = 1; + if (g_do_dirty_os) + { + LLOGLN(10, ("rdpPolyArc: gettig dirty")); + pDstPriv->is_dirty = 1; + pDirtyPriv = pDstPriv; + dirty_type = RDI_IMGLL; + } + else + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + reset_surface = 1; + rdpup_get_pixmap_image_rect(pDstPixmap, &id); + got_id = 1; + } + } + } + else + { + if (pDrawable->type == DRAWABLE_WINDOW) + { + pDstWnd = (WindowPtr)pDrawable; + if (pDstWnd->viewable) + { + post_process = 1; + rdpup_get_screen_image_rect(&id); + got_id = 1; + } + } + } + if (!post_process) + { + g_free(rects); + return; + } + + RegionInit(&clip_reg, NullBox, 0); + cd = rdp_get_clip(&clip_reg, pDrawable, pGC); + if (cd == 1) + { + if (rects != 0) + { + tmpRegion = RegionFromRects(narcs, rects, CT_NONE); + num_clips = REGION_NUM_RECTS(tmpRegion); + if (num_clips > 0) + { + if (dirty_type != 0) + { + draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type); + } + else if (got_id) + { + rdpup_begin_update(); + for (i = num_clips - 1; i >= 0; i--) + { + box = REGION_RECTS(tmpRegion)[i]; + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, + box.y2 - box.y1); + } + rdpup_end_update(); + } + } + RegionDestroy(tmpRegion); + } + } + else if (cd == 2) + { + if (rects != 0) + { + tmpRegion = RegionFromRects(narcs, rects, CT_NONE); + RegionIntersect(tmpRegion, tmpRegion, &clip_reg); + num_clips = REGION_NUM_RECTS(tmpRegion); + if (num_clips > 0) + { + if (dirty_type != 0) + { + draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type); + } + else if (got_id) + { + rdpup_begin_update(); + for (i = num_clips - 1; i >= 0; i--) + { + box = REGION_RECTS(tmpRegion)[i]; + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, + box.y2 - box.y1); + } + rdpup_end_update(); + } + } + RegionDestroy(tmpRegion); + } + } + RegionUninit(&clip_reg); + g_free(rects); + if (reset_surface) + { + rdpup_switch_os_surface(-1); + } +} diff --git a/xorg/X11R7.6/rdp/rdpPolyArc.h b/xorg/X11R7.6/rdp/rdpPolyArc.h new file mode 100644 index 00000000..8db9a017 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpPolyArc.h @@ -0,0 +1,28 @@ +/* +Copyright 2005-2012 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 __RDPPOLYARC_H +#define __RDPPOLYARC_H + +void +rdpPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc* parcs); + +#endif diff --git a/xorg/X11R7.6/rdp/rdpPolyFillArc.c b/xorg/X11R7.6/rdp/rdpPolyFillArc.c new file mode 100644 index 00000000..cb8f2801 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpPolyFillArc.c @@ -0,0 +1,215 @@ +/* +Copyright 2005-2012 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 "rdp.h" +#include "rdpdraw.h" + +#define LDEBUG 0 + +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpGCIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpWindowIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */ +extern int g_Bpp; /* from rdpmain.c */ +extern ScreenPtr g_pScreen; /* from rdpmain.c */ +extern Bool g_wrapPixmap; /* from rdpmain.c */ +extern int g_do_dirty_os; /* in rdpmain.c */ + +extern GCOps g_rdpGCOps; /* from rdpdraw.c */ + +extern int g_con_number; /* in rdpup.c */ + +/******************************************************************************/ +void +rdpPolyFillArcOrg(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc* parcs) +{ + rdpGCPtr priv; + GCFuncs* oldFuncs; + + GC_OP_PROLOGUE(pGC); + pGC->ops->PolyFillArc(pDrawable, pGC, narcs, parcs); + GC_OP_EPILOGUE(pGC); +} + +/******************************************************************************/ +void +rdpPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc* parcs) +{ + RegionRec clip_reg; + RegionPtr tmpRegion; + int cd; + int lw; + int extra; + int i; + int num_clips; + int got_id; + int dirty_type; + int post_process; + int reset_surface; + xRectangle* rects; + BoxRec box; + struct image_data id; + WindowPtr pDstWnd; + PixmapPtr pDstPixmap; + rdpPixmapRec* pDstPriv; + rdpPixmapRec* pDirtyPriv; + + LLOGLN(10, ("rdpPolyFillArc:")); + + rects = 0; + if (narcs > 0) + { + rects = (xRectangle*)g_malloc(narcs * sizeof(xRectangle), 0); + lw = pGC->lineWidth; + if (lw == 0) + { + lw = 1; + } + extra = lw / 2; + for (i = 0; i < narcs; i++) + { + rects[i].x = (parcs[i].x - extra) + pDrawable->x; + rects[i].y = (parcs[i].y - extra) + pDrawable->y; + rects[i].width = parcs[i].width + lw; + rects[i].height = parcs[i].height + lw; + } + } + + /* do original call */ + rdpPolyFillArcOrg(pDrawable, pGC, narcs, parcs); + + dirty_type = 0; + pDirtyPriv = 0; + post_process = 0; + reset_surface = 0; + got_id = 0; + if (pDrawable->type == DRAWABLE_PIXMAP) + { + pDstPixmap = (PixmapPtr)pDrawable; + pDstPriv = GETPIXPRIV(pDstPixmap); + if (XRDP_IS_OS(pDstPriv)) + { + post_process = 1; + if (g_do_dirty_os) + { + LLOGLN(10, ("rdpPolyFillArc: gettig dirty")); + pDstPriv->is_dirty = 1; + pDirtyPriv = pDstPriv; + dirty_type = RDI_IMGLY; + } + else + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + reset_surface = 1; + rdpup_get_pixmap_image_rect(pDstPixmap, &id); + got_id = 1; + } + } + } + else + { + if (pDrawable->type == DRAWABLE_WINDOW) + { + pDstWnd = (WindowPtr)pDrawable; + if (pDstWnd->viewable) + { + post_process = 1; + rdpup_get_screen_image_rect(&id); + got_id = 1; + } + } + } + if (!post_process) + { + g_free(rects); + return; + } + + RegionInit(&clip_reg, NullBox, 0); + cd = rdp_get_clip(&clip_reg, pDrawable, pGC); + if (cd == 1) + { + if (rects != 0) + { + tmpRegion = RegionFromRects(narcs, rects, CT_NONE); + num_clips = REGION_NUM_RECTS(tmpRegion); + if (num_clips > 0) + { + if (dirty_type != 0) + { + draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type); + } + else if (got_id) + { + rdpup_begin_update(); + for (i = num_clips - 1; i >= 0; i--) + { + box = REGION_RECTS(tmpRegion)[i]; + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, + box.y2 - box.y1); + } + rdpup_end_update(); + } + } + RegionDestroy(tmpRegion); + } + } + else if (cd == 2) + { + if (rects != 0) + { + tmpRegion = RegionFromRects(narcs, rects, CT_NONE); + RegionIntersect(tmpRegion, tmpRegion, &clip_reg); + num_clips = REGION_NUM_RECTS(tmpRegion); + if (num_clips > 0) + { + if (dirty_type != 0) + { + draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type); + } + else if (got_id) + { + rdpup_begin_update(); + for (i = num_clips - 1; i >= 0; i--) + { + box = REGION_RECTS(tmpRegion)[i]; + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, + box.y2 - box.y1); + } + rdpup_end_update(); + } + } + RegionDestroy(tmpRegion); + } + } + RegionUninit(&clip_reg); + g_free(rects); + if (reset_surface) + { + rdpup_switch_os_surface(-1); + } +} diff --git a/xorg/X11R7.6/rdp/rdpPolyFillArc.h b/xorg/X11R7.6/rdp/rdpPolyFillArc.h new file mode 100644 index 00000000..6d5a9bda --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpPolyFillArc.h @@ -0,0 +1,28 @@ +/* +Copyright 2005-2012 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 __RDPPOLYFILLARC_H +#define __RDPPOLYFILLARC_H + +void +rdpPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc* parcs); + +#endif diff --git a/xorg/X11R7.6/rdp/rdpPolyFillRect.c b/xorg/X11R7.6/rdp/rdpPolyFillRect.c new file mode 100644 index 00000000..5dda6b7e --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpPolyFillRect.c @@ -0,0 +1,255 @@ +/* +Copyright 2005-2012 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 "rdp.h" +#include "rdpdraw.h" + +#define LDEBUG 0 + +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpGCIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpWindowIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */ +extern int g_Bpp; /* from rdpmain.c */ +extern ScreenPtr g_pScreen; /* from rdpmain.c */ +extern Bool g_wrapPixmap; /* from rdpmain.c */ +extern int g_do_dirty_os; /* in rdpmain.c */ + +extern GCOps g_rdpGCOps; /* from rdpdraw.c */ + +extern int g_con_number; /* in rdpup.c */ + +/******************************************************************************/ +static void +rdpPolyFillRectOrg(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, + xRectangle* prectInit) +{ + rdpGCPtr priv; + GCFuncs* oldFuncs; + + GC_OP_PROLOGUE(pGC); + pGC->ops->PolyFillRect(pDrawable, pGC, nrectFill, prectInit); + GC_OP_EPILOGUE(pGC); +} + +/******************************************************************************/ +void +rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, + xRectangle* prectInit) +{ + int j; + int cd; + int num_clips; + RegionRec clip_reg; + RegionPtr fill_reg; + BoxRec box; + + int got_id; + int dirty_type; + int post_process; + int reset_surface; + + struct image_data id; + WindowPtr pDstWnd; + PixmapPtr pDstPixmap; + rdpPixmapRec* pDstPriv; + rdpPixmapRec* pDirtyPriv; + + LLOGLN(10, ("rdpPolyFillRect:")); + + /* make a copy of rects */ + fill_reg = RegionFromRects(nrectFill, prectInit, CT_NONE); + + /* do original call */ + rdpPolyFillRectOrg(pDrawable, pGC, nrectFill, prectInit); + + dirty_type = 0; + pDirtyPriv = 0; + post_process = 0; + reset_surface = 0; + if (pDrawable->type == DRAWABLE_PIXMAP) + { + pDstPixmap = (PixmapPtr)pDrawable; + pDstPriv = GETPIXPRIV(pDstPixmap); + if (XRDP_IS_OS(pDstPriv)) + { + post_process = 1; + if (g_do_dirty_os) + { + pDstPriv->is_dirty = 1; + pDirtyPriv = pDstPriv; + dirty_type = RDI_FILL; + } + else + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + reset_surface = 1; + rdpup_get_pixmap_image_rect(pDstPixmap, &id); + got_id = 1; + } + } + } + else + { + if (pDrawable->type == DRAWABLE_WINDOW) + { + pDstWnd = (WindowPtr)pDrawable; + if (pDstWnd->viewable) + { + post_process = 1; + rdpup_get_screen_image_rect(&id); + got_id = 1; + } + } + } + if (!post_process) + { + RegionDestroy(fill_reg); + return; + } + RegionTranslate(fill_reg, pDrawable->x, pDrawable->y); + RegionInit(&clip_reg, NullBox, 0); + cd = rdp_get_clip(&clip_reg, pDrawable, pGC); + if (cd == 1) /* no clip */ + { + if (dirty_type != 0) + { + if (pGC->fillStyle == 0 && /* solid fill */ + (pGC->alu == GXclear || + pGC->alu == GXset || + pGC->alu == GXinvert || + pGC->alu == GXnoop || + pGC->alu == GXand || + pGC->alu == GXcopy /*|| + pGC->alu == GXxor*/)) /* todo, why dosen't xor work? */ + { + draw_item_add_fill_region(pDirtyPriv, fill_reg, pGC->fgPixel, + pGC->alu); + } + else + { + draw_item_add_img_region(pDirtyPriv, fill_reg, GXcopy, RDI_IMGLL); + } + } + else if (got_id) + { + rdpup_begin_update(); + if (pGC->fillStyle == 0 && /* solid fill */ + (pGC->alu == GXclear || + pGC->alu == GXset || + pGC->alu == GXinvert || + pGC->alu == GXnoop || + pGC->alu == GXand || + pGC->alu == GXcopy /*|| + pGC->alu == GXxor*/)) /* todo, why dosen't xor work? */ + { + rdpup_set_fgcolor(pGC->fgPixel); + rdpup_set_opcode(pGC->alu); + for (j = REGION_NUM_RECTS(fill_reg) - 1; j >= 0; j--) + { + box = REGION_RECTS(fill_reg)[j]; + rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + } + rdpup_set_opcode(GXcopy); + } + else /* non solid fill */ + { + for (j = REGION_NUM_RECTS(fill_reg) - 1; j >= 0; j--) + { + box = REGION_RECTS(fill_reg)[j]; + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, + box.y2 - box.y1); + } + } + rdpup_end_update(); + } + } + else if (cd == 2) /* clip */ + { + RegionIntersect(&clip_reg, &clip_reg, fill_reg); + num_clips = REGION_NUM_RECTS(&clip_reg); + if (num_clips > 0) + { + if (dirty_type != 0) + { + if (pGC->fillStyle == 0 && /* solid fill */ + (pGC->alu == GXclear || + pGC->alu == GXset || + pGC->alu == GXinvert || + pGC->alu == GXnoop || + pGC->alu == GXand || + pGC->alu == GXcopy /*|| + pGC->alu == GXxor*/)) /* todo, why dosen't xor work? */ + { + draw_item_add_fill_region(pDirtyPriv, &clip_reg, pGC->fgPixel, + pGC->alu); + } + else + { + draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, RDI_IMGLL); + } + } + else if (got_id) + { + rdpup_begin_update(); + if (pGC->fillStyle == 0 && /* solid fill */ + (pGC->alu == GXclear || + pGC->alu == GXset || + pGC->alu == GXinvert || + pGC->alu == GXnoop || + pGC->alu == GXand || + pGC->alu == GXcopy /*|| + pGC->alu == GXxor*/)) /* todo, why dosen't xor work? */ + { + rdpup_set_fgcolor(pGC->fgPixel); + rdpup_set_opcode(pGC->alu); + for (j = num_clips - 1; j >= 0; j--) + { + box = REGION_RECTS(&clip_reg)[j]; + rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + } + rdpup_set_opcode(GXcopy); + } + else /* non solid fill */ + { + for (j = num_clips - 1; j >= 0; j--) + { + box = REGION_RECTS(&clip_reg)[j]; + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + } + } + rdpup_end_update(); + } + } + } + RegionUninit(&clip_reg); + RegionDestroy(fill_reg); + if (reset_surface) + { + rdpup_switch_os_surface(-1); + } +} diff --git a/xorg/X11R7.6/rdp/rdpPolyFillRect.h b/xorg/X11R7.6/rdp/rdpPolyFillRect.h new file mode 100644 index 00000000..cca9efa2 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpPolyFillRect.h @@ -0,0 +1,29 @@ +/* +Copyright 2005-2012 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 __RDPPOLYFILLRECT_H +#define __RDPPOLYFILLRECT_H + +void +rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, + xRectangle* prectInit); + +#endif diff --git a/xorg/X11R7.6/rdp/rdpPolyGlyphBlt.c b/xorg/X11R7.6/rdp/rdpPolyGlyphBlt.c new file mode 100644 index 00000000..89ae85b4 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpPolyGlyphBlt.c @@ -0,0 +1,193 @@ +/* +Copyright 2005-2012 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 "rdp.h" +#include "rdpdraw.h" + +#define LDEBUG 0 + +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpGCIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpWindowIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */ +extern int g_Bpp; /* from rdpmain.c */ +extern ScreenPtr g_pScreen; /* from rdpmain.c */ +extern Bool g_wrapPixmap; /* from rdpmain.c */ +extern int g_do_dirty_os; /* in rdpmain.c */ + +extern GCOps g_rdpGCOps; /* from rdpdraw.c */ + +extern int g_con_number; /* in rdpup.c */ + +/******************************************************************************/ +void +rdpPolyGlyphBltOrg(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, unsigned int nglyph, + CharInfoPtr* ppci, pointer pglyphBase) +{ + rdpGCPtr priv; + GCFuncs* oldFuncs; + + GC_OP_PROLOGUE(pGC); + pGC->ops->PolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + GC_OP_EPILOGUE(pGC); +} + +/******************************************************************************/ +void +rdpPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, unsigned int nglyph, + CharInfoPtr* ppci, pointer pglyphBase) +{ + RegionRec reg; + RegionRec reg1; + int num_clips; + int cd; + int j; + int got_id; + int dirty_type; + int post_process; + int reset_surface; + BoxRec box; + struct image_data id; + WindowPtr pDstWnd; + PixmapPtr pDstPixmap; + rdpPixmapRec* pDstPriv; + rdpPixmapRec* pDirtyPriv; + + LLOGLN(10, ("rdpPolyGlyphBlt:")); + + if (nglyph != 0) + { + GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box); + } + + /* do original call */ + rdpPolyGlyphBltOrg(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + + dirty_type = 0; + pDirtyPriv = 0; + post_process = 0; + reset_surface = 0; + got_id = 0; + if (pDrawable->type == DRAWABLE_PIXMAP) + { + pDstPixmap = (PixmapPtr)pDrawable; + pDstPriv = GETPIXPRIV(pDstPixmap); + if (XRDP_IS_OS(pDstPriv)) + { + post_process = 1; + if (g_do_dirty_os) + { + LLOGLN(10, ("rdpPolyGlyphBlt: gettig dirty")); + pDstPriv->is_dirty = 1; + pDirtyPriv = pDstPriv; + dirty_type = RDI_IMGLY; + } + else + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + reset_surface = 1; + rdpup_get_pixmap_image_rect(pDstPixmap, &id); + got_id = 1; + } + } + } + else + { + if (pDrawable->type == DRAWABLE_WINDOW) + { + pDstWnd = (WindowPtr)pDrawable; + if (pDstWnd->viewable) + { + post_process = 1; + rdpup_get_screen_image_rect(&id); + got_id = 1; + } + } + } + if (!post_process) + { + return; + } + + RegionInit(®, NullBox, 0); + if (nglyph == 0) + { + cd = 0; + } + else + { + cd = rdp_get_clip(®, pDrawable, pGC); + } + if (cd == 1) + { + if (dirty_type != 0) + { + RegionInit(®1, &box, 0); + draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type); + RegionUninit(®1); + } + else if (got_id) + { + rdpup_begin_update(); + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + rdpup_end_update(); + } + } + else if (cd == 2) + { + RegionInit(®1, &box, 0); + RegionIntersect(®, ®, ®1); + num_clips = REGION_NUM_RECTS(®); + if (num_clips > 0) + { + if (dirty_type != 0) + { + draw_item_add_img_region(pDirtyPriv, ®, GXcopy, dirty_type); + } + else if (got_id) + { + rdpup_begin_update(); + for (j = num_clips - 1; j >= 0; j--) + { + box = REGION_RECTS(®)[j]; + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, + box.y2 - box.y1); + } + rdpup_end_update(); + } + } + RegionUninit(®1); + } + RegionUninit(®); + if (reset_surface) + { + rdpup_switch_os_surface(-1); + } + return; +} diff --git a/xorg/X11R7.6/rdp/rdpPolyGlyphBlt.h b/xorg/X11R7.6/rdp/rdpPolyGlyphBlt.h new file mode 100644 index 00000000..4098c1ec --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpPolyGlyphBlt.h @@ -0,0 +1,30 @@ +/* +Copyright 2005-2012 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 __RDPPOLYGLYPHBLT_H +#define __RDPPOLYGLYPHBLT_H + +void +rdpPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, unsigned int nglyph, + CharInfoPtr* ppci, pointer pglyphBase); + +#endif diff --git a/xorg/X11R7.6/rdp/rdpPolyPoint.c b/xorg/X11R7.6/rdp/rdpPolyPoint.c new file mode 100644 index 00000000..cbbc4a98 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpPolyPoint.c @@ -0,0 +1,269 @@ +/* +Copyright 2005-2012 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 "rdp.h" +#include "rdpdraw.h" + +#define LDEBUG 0 + +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpGCIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpWindowIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */ +extern int g_Bpp; /* from rdpmain.c */ +extern ScreenPtr g_pScreen; /* from rdpmain.c */ +extern Bool g_wrapPixmap; /* from rdpmain.c */ +extern int g_do_dirty_os; /* in rdpmain.c */ + +extern GCOps g_rdpGCOps; /* from rdpdraw.c */ + +extern int g_con_number; /* in rdpup.c */ + +/******************************************************************************/ +void +rdpPolyPointOrg(DrawablePtr pDrawable, GCPtr pGC, int mode, + int npt, DDXPointPtr in_pts) +{ + rdpGCPtr priv; + GCFuncs* oldFuncs; + + GC_OP_PROLOGUE(pGC); + pGC->ops->PolyPoint(pDrawable, pGC, mode, npt, in_pts); + GC_OP_EPILOGUE(pGC); +} + +/******************************************************************************/ +void +rdpPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, + int npt, DDXPointPtr in_pts) +{ + RegionRec clip_reg; + RegionRec reg1; + RegionRec reg2; + int num_clips; + int cd; + int x; + int y; + int i; + int j; + int got_id; + int dirty_type; + int post_process; + int reset_surface; + BoxRec box; + BoxRec total_box; + DDXPointPtr pts; + DDXPointRec stack_pts[32]; + struct image_data id; + WindowPtr pDstWnd; + PixmapPtr pDstPixmap; + rdpPixmapRec* pDstPriv; + rdpPixmapRec* pDirtyPriv; + + LLOGLN(10, ("rdpPolyPoint:")); + LLOGLN(10, ("rdpPolyPoint: npt %d", npt)); + + if (npt > 32) + { + pts = (DDXPointPtr)g_malloc(sizeof(DDXPointRec) * npt, 0); + } + else + { + pts = stack_pts; + } + for (i = 0; i < npt; i++) + { + pts[i].x = pDrawable->x + in_pts[i].x; + pts[i].y = pDrawable->y + in_pts[i].y; + if (i == 0) + { + total_box.x1 = pts[0].x; + total_box.y1 = pts[0].y; + total_box.x2 = pts[0].x; + total_box.y2 = pts[0].y; + } + else + { + if (pts[i].x < total_box.x1) + { + total_box.x1 = pts[i].x; + } + if (pts[i].y < total_box.y1) + { + total_box.y1 = pts[i].y; + } + if (pts[i].x > total_box.x2) + { + total_box.x2 = pts[i].x; + } + if (pts[i].y > total_box.y2) + { + total_box.y2 = pts[i].y; + } + } + /* todo, use this total_box */ + } + + /* do original call */ + rdpPolyPointOrg(pDrawable, pGC, mode, npt, in_pts); + + dirty_type = 0; + pDirtyPriv = 0; + post_process = 0; + reset_surface = 0; + got_id = 0; + if (pDrawable->type == DRAWABLE_PIXMAP) + { + pDstPixmap = (PixmapPtr)pDrawable; + pDstPriv = GETPIXPRIV(pDstPixmap); + if (XRDP_IS_OS(pDstPriv)) + { + post_process = 1; + if (g_do_dirty_os) + { + LLOGLN(10, ("rdpPolyPoint: gettig dirty")); + pDstPriv->is_dirty = 1; + pDirtyPriv = pDstPriv; + dirty_type = RDI_IMGLL; + } + else + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + reset_surface = 1; + rdpup_get_pixmap_image_rect(pDstPixmap, &id); + got_id = 1; + } + } + } + else + { + if (pDrawable->type == DRAWABLE_WINDOW) + { + pDstWnd = (WindowPtr)pDrawable; + if (pDstWnd->viewable) + { + post_process = 1; + rdpup_get_screen_image_rect(&id); + got_id = 1; + } + } + } + if (!post_process) + { + return; + } + + RegionInit(&clip_reg, NullBox, 0); + cd = rdp_get_clip(&clip_reg, pDrawable, pGC); + if (cd == 1) + { + if (npt > 0) + { + if (dirty_type != 0) + { + RegionInit(®1, NullBox, 0); + for (i = 0; i < npt; i++) + { + box.x1 = pts[i].x; + box.y1 = pts[i].y; + box.x2 = box.x1 + 1; + box.y2 = box.y1 + 1; + RegionInit(®2, &box, 0); + RegionUnion(®1, ®1, ®2); + RegionUninit(®2); + } + draw_item_add_fill_region(pDirtyPriv, ®1, pGC->fgPixel, + pGC->alu); + RegionUninit(®1); + } + else if (got_id) + { + rdpup_begin_update(); + rdpup_set_fgcolor(pGC->fgPixel); + for (i = 0; i < npt; i++) + { + x = pts[i].x; + y = pts[i].y; + rdpup_fill_rect(x, y, 1, 1); + } + rdpup_end_update(); + } + } + } + else if (cd == 2) + { + num_clips = REGION_NUM_RECTS(&clip_reg); + if (npt > 0 && num_clips > 0) + { + if (dirty_type != 0) + { + RegionInit(®1, NullBox, 0); + for (i = 0; i < npt; i++) + { + box.x1 = pts[i].x; + box.y1 = pts[i].y; + box.x2 = box.x1 + 1; + box.y2 = box.y1 + 1; + RegionInit(®2, &box, 0); + RegionUnion(®1, ®1, ®2); + RegionUninit(®2); + } + RegionIntersect(®1, ®1, &clip_reg); + draw_item_add_fill_region(pDirtyPriv, ®1, pGC->fgPixel, + pGC->alu); + RegionUninit(®1); + } + else if (got_id) + { + rdpup_begin_update(); + rdpup_set_fgcolor(pGC->fgPixel); + for (j = num_clips - 1; j >= 0; j--) + { + box = REGION_RECTS(&clip_reg)[j]; + rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + for (i = 0; i < npt; i++) + { + x = pts[i].x; + y = pts[i].y; + rdpup_fill_rect(x, y, 1, 1); + } + } + rdpup_reset_clip(); + rdpup_end_update(); + } + } + } + RegionUninit(&clip_reg); + if (pts != stack_pts) + { + g_free(pts); + } + if (reset_surface) + { + rdpup_switch_os_surface(-1); + } +} diff --git a/xorg/X11R7.6/rdp/rdpPolyPoint.h b/xorg/X11R7.6/rdp/rdpPolyPoint.h new file mode 100644 index 00000000..6bb7222b --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpPolyPoint.h @@ -0,0 +1,29 @@ +/* +Copyright 2005-2012 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 __RDPPOLYPOINT_H +#define __RDPPOLYPOINT_H + +void +rdpPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, + int npt, DDXPointPtr in_pts); + +#endif diff --git a/xorg/X11R7.6/rdp/rdpPolyRectangle.c b/xorg/X11R7.6/rdp/rdpPolyRectangle.c new file mode 100644 index 00000000..e2b38394 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpPolyRectangle.c @@ -0,0 +1,285 @@ +/* +Copyright 2005-2012 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 "rdp.h" +#include "rdpdraw.h" + +#define LDEBUG 0 + +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpGCIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpWindowIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */ +extern int g_Bpp; /* from rdpmain.c */ +extern ScreenPtr g_pScreen; /* from rdpmain.c */ +extern Bool g_wrapPixmap; /* from rdpmain.c */ +extern int g_do_dirty_os; /* in rdpmain.c */ + +extern GCOps g_rdpGCOps; /* from rdpdraw.c */ + +extern int g_con_number; /* in rdpup.c */ + +/******************************************************************************/ +static void +rdpPolyRectangleOrg(DrawablePtr pDrawable, GCPtr pGC, int nrects, + xRectangle* rects) +{ + rdpGCPtr priv; + GCFuncs* oldFuncs; + + GC_OP_PROLOGUE(pGC); + pGC->ops->PolyRectangle(pDrawable, pGC, nrects, rects); + GC_OP_EPILOGUE(pGC); +} + +/******************************************************************************/ +/* tested with pGC->lineWidth = 0, 1, 2, 4 and opcodes 3 and 6 */ +void +rdpPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects, + xRectangle* rects) +{ + RegionRec clip_reg; + RegionPtr fill_reg; + int num_clips; + int cd; + int lw; + int i; + int j; + int up; + int down; + int got_id; + int dirty_type; + int post_process; + int reset_surface; + xRectangle* regRects; + xRectangle* r; + xRectangle* rect1; + BoxRec box; + struct image_data id; + + WindowPtr pDstWnd; + PixmapPtr pDstPixmap; + rdpPixmapRec* pDstPriv; + rdpPixmapRec* pDirtyPriv; + + LLOGLN(10, ("rdpPolyRectangle:")); + + /* make a copy of rects */ + rect1 = (xRectangle*)g_malloc(sizeof(xRectangle) * nrects, 0); + for (i = 0; i < nrects; i++) + { + rect1[i] = rects[i]; + } + + /* do original call */ + rdpPolyRectangleOrg(pDrawable, pGC, nrects, rects); + + dirty_type = 0; + pDirtyPriv = 0; + post_process = 0; + reset_surface = 0; + got_id = 0; + if (pDrawable->type == DRAWABLE_PIXMAP) + { + pDstPixmap = (PixmapPtr)pDrawable; + pDstPriv = GETPIXPRIV(pDstPixmap); + if (XRDP_IS_OS(pDstPriv)) + { + post_process = 1; + if (g_do_dirty_os) + { + LLOGLN(10, ("rdpPolyRectangle: gettig dirty")); + pDstPriv->is_dirty = 1; + pDirtyPriv = pDstPriv; + dirty_type = RDI_IMGLL; + } + else + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + reset_surface = 1; + rdpup_get_pixmap_image_rect(pDstPixmap, &id); + got_id = 1; + } + } + } + else + { + if (pDrawable->type == DRAWABLE_WINDOW) + { + pDstWnd = (WindowPtr)pDrawable; + if (pDstWnd->viewable) + { + post_process = 1; + rdpup_get_screen_image_rect(&id); + got_id = 1; + } + } + } + if (!post_process) + { + g_free(rect1); + return; + } + + RegionInit(&clip_reg, NullBox, 0); + cd = rdp_get_clip(&clip_reg, pDrawable, pGC); + regRects = 0; + if ((cd != 0) && (nrects > 0)) + { + regRects = (xRectangle*)g_malloc(nrects * 4 * sizeof(xRectangle), 0); + lw = pGC->lineWidth; + if (lw < 1) + { + lw = 1; + } + up = lw / 2; + down = 1 + (lw - 1) / 2; + for (i = 0; i < nrects; i++) + { + r = regRects + i * 4; + r->x = (rect1[i].x + pDrawable->x) - up; + r->y = (rect1[i].y + pDrawable->y) - up; + r->width = rect1[i].width + up + down; + r->height = lw; + r++; + r->x = (rect1[i].x + pDrawable->x) - up; + r->y = (rect1[i].y + pDrawable->y) + down; + r->width = lw; + r->height = MAX(rect1[i].height - (up + down), 0); + r++; + r->x = ((rect1[i].x + rect1[i].width) + pDrawable->x) - up; + r->y = (rect1[i].y + pDrawable->y) + down; + r->width = lw; + r->height = MAX(rect1[i].height - (up + down), 0); + r++; + r->x = (rect1[i].x + pDrawable->x) - up; + r->y = ((rect1[i].y + rect1[i].height) + pDrawable->y) - up; + r->width = rect1[i].width + up + down; + r->height = lw; + } + } + if (cd == 1) + { + if (regRects != 0) + { + if (dirty_type != 0) + { + fill_reg = RegionFromRects(nrects * 4, regRects, CT_NONE); + if (pGC->lineStyle == LineSolid) + { + draw_item_add_fill_region(pDirtyPriv, fill_reg, pGC->fgPixel, + pGC->alu); + } + else + { + draw_item_add_img_region(pDirtyPriv, fill_reg, GXcopy, dirty_type); + } + RegionDestroy(fill_reg); + } + else if (got_id) + { + rdpup_begin_update(); + if (pGC->lineStyle == LineSolid) + { + rdpup_set_fgcolor(pGC->fgPixel); + rdpup_set_opcode(pGC->alu); + for (i = 0; i < nrects * 4; i++) + { + r = regRects + i; + rdpup_fill_rect(r->x, r->y, r->width, r->height); + } + rdpup_set_opcode(GXcopy); + } + else + { + for (i = 0; i < nrects * 4; i++) + { + r = regRects + i; + rdpup_send_area(&id, r->x, r->y, r->width, r->height); + } + } + rdpup_end_update(); + } + } + } + else if (cd == 2) + { + if (regRects != 0) + { + fill_reg = RegionFromRects(nrects * 4, regRects, CT_NONE); + RegionIntersect(&clip_reg, &clip_reg, fill_reg); + num_clips = REGION_NUM_RECTS(&clip_reg); + if (num_clips > 0) + { + if (dirty_type != 0) + { + if (pGC->lineStyle == LineSolid) + { + draw_item_add_fill_region(pDirtyPriv, &clip_reg, pGC->fgPixel, + pGC->alu); + } + else + { + draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type); + } + } + else if (got_id) + { + rdpup_begin_update(); + if (pGC->lineStyle == LineSolid) + { + rdpup_set_fgcolor(pGC->fgPixel); + rdpup_set_opcode(pGC->alu); + for (j = num_clips - 1; j >= 0; j--) + { + box = REGION_RECTS(&clip_reg)[j]; + rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + } + rdpup_set_opcode(GXcopy); + } + else + { + for (j = num_clips - 1; j >= 0; j--) + { + box = REGION_RECTS(&clip_reg)[j]; + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + } + } + rdpup_end_update(); + } + } + RegionDestroy(fill_reg); + } + } + RegionUninit(&clip_reg); + g_free(regRects); + g_free(rect1); + if (reset_surface) + { + rdpup_switch_os_surface(-1); + } +} diff --git a/xorg/X11R7.6/rdp/rdpPolyRectangle.h b/xorg/X11R7.6/rdp/rdpPolyRectangle.h new file mode 100644 index 00000000..4bc6600e --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpPolyRectangle.h @@ -0,0 +1,29 @@ +/* +Copyright 2005-2012 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 __RDPPOLYRECTANGLE_H +#define __RDPPOLYRECTANGLE_H + +void +rdpPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects, + xRectangle* rects); + +#endif diff --git a/xorg/X11R7.6/rdp/rdpPolySegment.c b/xorg/X11R7.6/rdp/rdpPolySegment.c new file mode 100644 index 00000000..efab3cc0 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpPolySegment.c @@ -0,0 +1,212 @@ +/* +Copyright 2005-2012 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 "rdp.h" +#include "rdpdraw.h" + +#define LDEBUG 0 + +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpGCIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpWindowIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */ +extern int g_Bpp; /* from rdpmain.c */ +extern ScreenPtr g_pScreen; /* from rdpmain.c */ +extern Bool g_wrapPixmap; /* from rdpmain.c */ +extern int g_do_dirty_os; /* in rdpmain.c */ + +extern GCOps g_rdpGCOps; /* from rdpdraw.c */ + +extern int g_con_number; /* in rdpup.c */ + +/******************************************************************************/ +void +rdpPolySegmentOrg(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment* pSegs) +{ + rdpGCPtr priv; + GCFuncs* oldFuncs; + + GC_OP_PROLOGUE(pGC); + pGC->ops->PolySegment(pDrawable, pGC, nseg, pSegs); + GC_OP_EPILOGUE(pGC); +} + +/******************************************************************************/ +void +rdpPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment* pSegs) +{ + RegionRec clip_reg; + int cd; + int i; + int j; + int got_id; + int dirty_type; + int post_process; + int reset_surface; + xSegment* segs; + BoxRec box; + struct image_data id; + WindowPtr pDstWnd; + PixmapPtr pDstPixmap; + rdpPixmapRec* pDstPriv; + rdpPixmapRec* pDirtyPriv; + + LLOGLN(10, ("rdpPolySegment:")); + LLOGLN(10, (" nseg %d", nseg)); + + segs = 0; + if (nseg) /* get the rects */ + { + segs = (xSegment*)g_malloc(nseg * sizeof(xSegment), 0); + for (i = 0; i < nseg; i++) + { + segs[i].x1 = pSegs[i].x1 + pDrawable->x; + segs[i].y1 = pSegs[i].y1 + pDrawable->y; + segs[i].x2 = pSegs[i].x2 + pDrawable->x; + segs[i].y2 = pSegs[i].y2 + pDrawable->y; + } + } + + /* do original call */ + rdpPolySegmentOrg(pDrawable, pGC, nseg, pSegs); + + dirty_type = 0; + pDirtyPriv = 0; + post_process = 0; + reset_surface = 0; + got_id = 0; + if (pDrawable->type == DRAWABLE_PIXMAP) + { + pDstPixmap = (PixmapPtr)pDrawable; + pDstPriv = GETPIXPRIV(pDstPixmap); + if (XRDP_IS_OS(pDstPriv)) + { + post_process = 1; + if (g_do_dirty_os) + { + LLOGLN(10, ("rdpPolySegment: gettig dirty")); + pDstPriv->is_dirty = 1; + pDirtyPriv = pDstPriv; + dirty_type = RDI_IMGLL; + } + else + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + reset_surface = 1; + rdpup_get_pixmap_image_rect(pDstPixmap, &id); + got_id = 1; + } + } + } + else + { + if (pDrawable->type == DRAWABLE_WINDOW) + { + pDstWnd = (WindowPtr)pDrawable; + if (pDstWnd->viewable) + { + post_process = 1; + rdpup_get_screen_image_rect(&id); + got_id = 1; + } + } + } + if (!post_process) + { + g_free(segs); + return; + } + + RegionInit(&clip_reg, NullBox, 0); + cd = rdp_get_clip(&clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpPolySegment: cd %d", cd)); + if (cd == 1) /* no clip */ + { + if (segs != 0) + { + if (dirty_type != 0) + { + RegionUninit(&clip_reg); + RegionInit(&clip_reg, NullBox, 0); + RegionAroundSegs(&clip_reg, segs, nseg); + draw_item_add_line_region(pDirtyPriv, &clip_reg, pGC->fgPixel, + pGC->alu, pGC->lineWidth, segs, nseg, 1); + } + else if (got_id) + { + rdpup_begin_update(); + rdpup_set_fgcolor(pGC->fgPixel); + rdpup_set_opcode(pGC->alu); + rdpup_set_pen(0, pGC->lineWidth); + for (i = 0; i < nseg; i++) + { + rdpup_draw_line(segs[i].x1, segs[i].y1, segs[i].x2, segs[i].y2); + } + rdpup_set_opcode(GXcopy); + rdpup_end_update(); + } + } + } + else if (cd == 2) /* clip */ + { + if (segs != 0) + { + if (dirty_type != 0) + { + draw_item_add_line_region(pDirtyPriv, &clip_reg, pGC->fgPixel, + pGC->alu, pGC->lineWidth, segs, nseg, 1); + } + else if (got_id) + { + rdpup_begin_update(); + rdpup_set_fgcolor(pGC->fgPixel); + rdpup_set_opcode(pGC->alu); + rdpup_set_pen(0, pGC->lineWidth); + for (j = REGION_NUM_RECTS(&clip_reg) - 1; j >= 0; j--) + { + box = REGION_RECTS(&clip_reg)[j]; + rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + for (i = 0; i < nseg; i++) + { + rdpup_draw_line(segs[i].x1, segs[i].y1, segs[i].x2, segs[i].y2); + LLOGLN(10, (" %d %d %d %d", segs[i].x1, segs[i].y1, + segs[i].x2, segs[i].y2)); + } + } + rdpup_reset_clip(); + rdpup_set_opcode(GXcopy); + rdpup_end_update(); + } + } + } + g_free(segs); + RegionUninit(&clip_reg); + if (reset_surface) + { + rdpup_switch_os_surface(-1); + } +} diff --git a/xorg/X11R7.6/rdp/rdpPolySegment.h b/xorg/X11R7.6/rdp/rdpPolySegment.h new file mode 100644 index 00000000..17bf0547 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpPolySegment.h @@ -0,0 +1,28 @@ +/* +Copyright 2005-2012 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 __RDPPOLYSEGMENT_H +#define __RDPPOLYSEGMENT_H + +void +rdpPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment* pSegs); + +#endif diff --git a/xorg/X11R7.6/rdp/rdpPolyText16.c b/xorg/X11R7.6/rdp/rdpPolyText16.c new file mode 100644 index 00000000..aaea2434 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpPolyText16.c @@ -0,0 +1,193 @@ +/* +Copyright 2005-2012 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 "rdp.h" +#include "rdpdraw.h" + +#define LDEBUG 0 + +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpGCIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpWindowIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */ +extern int g_Bpp; /* from rdpmain.c */ +extern ScreenPtr g_pScreen; /* from rdpmain.c */ +extern Bool g_wrapPixmap; /* from rdpmain.c */ +extern int g_do_dirty_os; /* in rdpmain.c */ + +extern GCOps g_rdpGCOps; /* from rdpdraw.c */ + +extern int g_con_number; /* in rdpup.c */ + +/******************************************************************************/ +int +rdpPolyText16Org(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, int count, unsigned short* chars) +{ + int rv; + rdpGCPtr priv; + GCFuncs* oldFuncs; + + GC_OP_PROLOGUE(pGC); + rv = pGC->ops->PolyText16(pDrawable, pGC, x, y, count, chars); + GC_OP_EPILOGUE(pGC); + return rv; +} + +/******************************************************************************/ +int +rdpPolyText16(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, int count, unsigned short* chars) +{ + RegionRec reg; + RegionRec reg1; + int num_clips; + int cd; + int j; + int rv; + int got_id; + int dirty_type; + int post_process; + int reset_surface; + BoxRec box; + struct image_data id; + WindowPtr pDstWnd; + PixmapPtr pDstPixmap; + rdpPixmapRec* pDstPriv; + rdpPixmapRec* pDirtyPriv; + + LLOGLN(10, ("rdpPolyText16:")); + + if (count != 0) + { + GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); + } + + /* do original call */ + rv = rdpPolyText16Org(pDrawable, pGC, x, y, count, chars); + + dirty_type = 0; + pDirtyPriv = 0; + post_process = 0; + reset_surface = 0; + got_id = 0; + if (pDrawable->type == DRAWABLE_PIXMAP) + { + pDstPixmap = (PixmapPtr)pDrawable; + pDstPriv = GETPIXPRIV(pDstPixmap); + if (XRDP_IS_OS(pDstPriv)) + { + post_process = 1; + if (g_do_dirty_os) + { + LLOGLN(10, ("rdpPolyText16: gettig dirty")); + pDstPriv->is_dirty = 1; + pDirtyPriv = pDstPriv; + dirty_type = RDI_IMGLY; + } + else + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + reset_surface = 1; + rdpup_get_pixmap_image_rect(pDstPixmap, &id); + got_id = 1; + } + } + } + else + { + if (pDrawable->type == DRAWABLE_WINDOW) + { + pDstWnd = (WindowPtr)pDrawable; + if (pDstWnd->viewable) + { + post_process = 1; + rdpup_get_screen_image_rect(&id); + got_id = 1; + } + } + } + if (!post_process) + { + return rv; + } + + RegionInit(®, NullBox, 0); + if (count == 0) + { + cd = 0; + } + else + { + cd = rdp_get_clip(®, pDrawable, pGC); + } + if (cd == 1) + { + if (dirty_type != 0) + { + RegionInit(®1, &box, 0); + draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type); + RegionUninit(®1); + } + else if (got_id) + { + rdpup_begin_update(); + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + rdpup_end_update(); + } + } + else if (cd == 2) + { + RegionInit(®1, &box, 0); + RegionIntersect(®, ®, ®1); + num_clips = REGION_NUM_RECTS(®); + if (num_clips > 0) + { + if (dirty_type != 0) + { + draw_item_add_img_region(pDirtyPriv, ®, GXcopy, dirty_type); + } + else if (got_id) + { + rdpup_begin_update(); + for (j = num_clips - 1; j >= 0; j--) + { + box = REGION_RECTS(®)[j]; + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + } + rdpup_end_update(); + } + } + RegionUninit(®1); + } + RegionUninit(®); + if (reset_surface) + { + rdpup_switch_os_surface(-1); + } + return rv; +} diff --git a/xorg/X11R7.6/rdp/rdpPolyText16.h b/xorg/X11R7.6/rdp/rdpPolyText16.h new file mode 100644 index 00000000..87e58f13 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpPolyText16.h @@ -0,0 +1,29 @@ +/* +Copyright 2005-2012 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 __RDPPOLYTEXT16_H +#define __RDPPOLYTEXT16_H + +int +rdpPolyText16(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, int count, unsigned short* chars); + +#endif diff --git a/xorg/X11R7.6/rdp/rdpPolyText8.c b/xorg/X11R7.6/rdp/rdpPolyText8.c new file mode 100644 index 00000000..0b16cf26 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpPolyText8.c @@ -0,0 +1,193 @@ +/* +Copyright 2005-2012 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 "rdp.h" +#include "rdpdraw.h" + +#define LDEBUG 0 + +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpGCIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpWindowIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */ +extern int g_Bpp; /* from rdpmain.c */ +extern ScreenPtr g_pScreen; /* from rdpmain.c */ +extern Bool g_wrapPixmap; /* from rdpmain.c */ +extern int g_do_dirty_os; /* in rdpmain.c */ + +extern GCOps g_rdpGCOps; /* from rdpdraw.c */ + +extern int g_con_number; /* in rdpup.c */ + +/******************************************************************************/ +int +rdpPolyText8Org(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, int count, char* chars) +{ + int rv; + rdpGCPtr priv; + GCFuncs* oldFuncs; + + GC_OP_PROLOGUE(pGC); + rv = pGC->ops->PolyText8(pDrawable, pGC, x, y, count, chars); + GC_OP_EPILOGUE(pGC); + return rv; +} + +/******************************************************************************/ +int +rdpPolyText8(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, int count, char* chars) +{ + RegionRec reg; + RegionRec reg1; + int num_clips; + int cd; + int j; + int rv; + int got_id; + int dirty_type; + int post_process; + int reset_surface; + BoxRec box; + struct image_data id; + WindowPtr pDstWnd; + PixmapPtr pDstPixmap; + rdpPixmapRec* pDstPriv; + rdpPixmapRec* pDirtyPriv; + + LLOGLN(10, ("rdpPolyText8:")); + + if (count != 0) + { + GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); + } + + /* do original call */ + rv = rdpPolyText8Org(pDrawable, pGC, x, y, count, chars); + + dirty_type = 0; + pDirtyPriv = 0; + post_process = 0; + reset_surface = 0; + got_id = 0; + if (pDrawable->type == DRAWABLE_PIXMAP) + { + pDstPixmap = (PixmapPtr)pDrawable; + pDstPriv = GETPIXPRIV(pDstPixmap); + if (XRDP_IS_OS(pDstPriv)) + { + post_process = 1; + if (g_do_dirty_os) + { + LLOGLN(10, ("rdpPolyText8: gettig dirty")); + pDstPriv->is_dirty = 1; + pDirtyPriv = pDstPriv; + dirty_type = RDI_IMGLY; + } + else + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + reset_surface = 1; + rdpup_get_pixmap_image_rect(pDstPixmap, &id); + got_id = 1; + } + } + } + else + { + if (pDrawable->type == DRAWABLE_WINDOW) + { + pDstWnd = (WindowPtr)pDrawable; + if (pDstWnd->viewable) + { + post_process = 1; + rdpup_get_screen_image_rect(&id); + got_id = 1; + } + } + } + if (!post_process) + { + return rv; + } + + RegionInit(®, NullBox, 0); + if (count == 0) + { + cd = 0; + } + else + { + cd = rdp_get_clip(®, pDrawable, pGC); + } + if (cd == 1) + { + if (dirty_type != 0) + { + RegionInit(®1, &box, 0); + draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type); + RegionUninit(®1); + } + else if (got_id) + { + rdpup_begin_update(); + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + rdpup_end_update(); + } + } + else if (cd == 2) + { + RegionInit(®1, &box, 0); + RegionIntersect(®, ®, ®1); + num_clips = REGION_NUM_RECTS(®); + if (num_clips > 0) + { + if (dirty_type != 0) + { + draw_item_add_img_region(pDirtyPriv, ®, GXcopy, dirty_type); + } + else if (got_id) + { + rdpup_begin_update(); + for (j = num_clips - 1; j >= 0; j--) + { + box = REGION_RECTS(®)[j]; + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + } + rdpup_end_update(); + } + } + RegionUninit(®1); + } + RegionUninit(®); + if (reset_surface) + { + rdpup_switch_os_surface(-1); + } + return rv; +} diff --git a/xorg/X11R7.6/rdp/rdpPolyText8.h b/xorg/X11R7.6/rdp/rdpPolyText8.h new file mode 100644 index 00000000..fb68649c --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpPolyText8.h @@ -0,0 +1,29 @@ +/* +Copyright 2005-2012 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 __RDPPOLYTEXT8_H +#define __RDPPOLYTEXT8_H + +int +rdpPolyText8(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, int count, char* chars); + +#endif diff --git a/xorg/X11R7.6/rdp/rdpPolylines.c b/xorg/X11R7.6/rdp/rdpPolylines.c new file mode 100644 index 00000000..cbaf9c3e --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpPolylines.c @@ -0,0 +1,254 @@ +/* +Copyright 2005-2012 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 "rdp.h" +#include "rdpdraw.h" + +#define LDEBUG 0 + +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpGCIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpWindowIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */ +extern int g_Bpp; /* from rdpmain.c */ +extern ScreenPtr g_pScreen; /* from rdpmain.c */ +extern Bool g_wrapPixmap; /* from rdpmain.c */ +extern int g_do_dirty_os; /* in rdpmain.c */ + +extern GCOps g_rdpGCOps; /* from rdpdraw.c */ + +extern int g_con_number; /* in rdpup.c */ + +/******************************************************************************/ +static void +rdpPolylinesOrg(DrawablePtr pDrawable, GCPtr pGC, int mode, + int npt, DDXPointPtr pptInit) +{ + rdpGCPtr priv; + GCFuncs* oldFuncs; + + GC_OP_PROLOGUE(pGC); + pGC->ops->Polylines(pDrawable, pGC, mode, npt, pptInit); + GC_OP_EPILOGUE(pGC); +} + +/******************************************************************************/ +void +rdpPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode, + int npt, DDXPointPtr pptInit) +{ + RegionRec clip_reg; + int num_clips; + int cd; + int i; + int j; + int got_id; + int dirty_type; + int post_process; + int reset_surface; + BoxRec box; + xSegment* segs; + int nseg; + struct image_data id; + WindowPtr pDstWnd; + PixmapPtr pDstPixmap; + rdpPixmapRec* pDstPriv; + rdpPixmapRec* pDirtyPriv; + + LLOGLN(10, ("rdpPolylines:")); + LLOGLN(10, (" npt %d mode %d x %d y %d", npt, mode, + pDrawable->x, pDrawable->y)); +#if 0 + LLOGLN(0, (" points")); + for (i = 0; i < npt; i++) + { + LLOGLN(0, (" %d %d", pptInit[i].x, pptInit[i].y)); + } +#endif + /* convert lines to line segments */ + nseg = npt - 1; + segs = 0; + if (npt > 1) + { + segs = (xSegment*)g_malloc(sizeof(xSegment) * nseg, 0); + segs[0].x1 = pptInit[0].x + pDrawable->x; + segs[0].y1 = pptInit[0].y + pDrawable->y; + if (mode == CoordModeOrigin) + { + segs[0].x2 = pptInit[1].x + pDrawable->x; + segs[0].y2 = pptInit[1].y + pDrawable->y; + for (i = 2; i < npt; i++) + { + segs[i - 1].x1 = segs[i - 2].x2; + segs[i - 1].y1 = segs[i - 2].y2; + segs[i - 1].x2 = pptInit[i].x + pDrawable->x; + segs[i - 1].y2 = pptInit[i].y + pDrawable->y; + } + } + else + { + segs[0].x2 = segs[0].x1 + pptInit[1].x; + segs[0].y2 = segs[0].y1 + pptInit[1].y; + for (i = 2; i < npt; i++) + { + segs[i - 1].x1 = segs[i - 2].x2; + segs[i - 1].y1 = segs[i - 2].y2; + segs[i - 1].x2 = segs[i - 1].x1 + pptInit[i].x; + segs[i - 1].y2 = segs[i - 1].y1 + pptInit[i].y; + } + } + } + else + { + LLOGLN(0, ("rdpPolylines: weird npt [%d]", npt)); + } +#if 0 + LLOGLN(0, (" segments")); + for (i = 0; i < nseg; i++) + { + LLOGLN(0, (" %d %d %d %d", segs[i].x1, segs[i].y1, + segs[i].x2, segs[i].y2)); + } +#endif + + /* do original call */ + rdpPolylinesOrg(pDrawable, pGC, mode, npt, pptInit); + + dirty_type = 0; + pDirtyPriv = 0; + post_process = 0; + reset_surface = 0; + got_id = 0; + if (pDrawable->type == DRAWABLE_PIXMAP) + { + pDstPixmap = (PixmapPtr)pDrawable; + pDstPriv = GETPIXPRIV(pDstPixmap); + if (XRDP_IS_OS(pDstPriv)) + { + post_process = 1; + if (g_do_dirty_os) + { + LLOGLN(10, ("rdpPolylines: gettig dirty")); + pDstPriv->is_dirty = 1; + pDirtyPriv = pDstPriv; + dirty_type = RDI_IMGLL; + } + else + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + reset_surface = 1; + rdpup_get_pixmap_image_rect(pDstPixmap, &id); + got_id = 1; + } + } + } + else + { + if (pDrawable->type == DRAWABLE_WINDOW) + { + pDstWnd = (WindowPtr)pDrawable; + if (pDstWnd->viewable) + { + post_process = 1; + rdpup_get_screen_image_rect(&id); + got_id = 1; + } + } + } + if (!post_process) + { + g_free(segs); + return; + } + + RegionInit(&clip_reg, NullBox, 0); + cd = rdp_get_clip(&clip_reg, pDrawable, pGC); + if (cd == 1) + { + if (segs != 0) + { + if (dirty_type != 0) + { + RegionUninit(&clip_reg); + RegionInit(&clip_reg, NullBox, 0); + RegionAroundSegs(&clip_reg, segs, nseg); + draw_item_add_line_region(pDirtyPriv, &clip_reg, pGC->fgPixel, + pGC->alu, pGC->lineWidth, segs, nseg, 0); + } + else if (got_id) + { + rdpup_begin_update(); + rdpup_set_fgcolor(pGC->fgPixel); + rdpup_set_opcode(pGC->alu); + rdpup_set_pen(0, pGC->lineWidth); + for (i = 0; i < nseg; i++) + { + rdpup_draw_line(segs[i].x1, segs[i].y1, segs[i].x2, segs[i].y2); + } + rdpup_set_opcode(GXcopy); + rdpup_end_update(); + } + } + } + else if (cd == 2) + { + num_clips = REGION_NUM_RECTS(&clip_reg); + if (nseg != 0 && num_clips > 0) + { + if (dirty_type != 0) + { + draw_item_add_line_region(pDirtyPriv, &clip_reg, pGC->fgPixel, + pGC->alu, pGC->lineWidth, segs, nseg, 0); + } + else if (got_id) + { + rdpup_begin_update(); + rdpup_set_fgcolor(pGC->fgPixel); + rdpup_set_opcode(pGC->alu); + rdpup_set_pen(0, pGC->lineWidth); + for (j = num_clips - 1; j >= 0; j--) + { + box = REGION_RECTS(&clip_reg)[j]; + rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + for (i = 0; i < nseg; i++) + { + rdpup_draw_line(segs[i].x1, segs[i].y1, segs[i].x2, segs[i].y2); + } + } + rdpup_reset_clip(); + rdpup_set_opcode(GXcopy); + rdpup_end_update(); + } + } + } + g_free(segs); + RegionUninit(&clip_reg); + if (reset_surface) + { + rdpup_switch_os_surface(-1); + } +} diff --git a/xorg/X11R7.6/rdp/rdpPolylines.h b/xorg/X11R7.6/rdp/rdpPolylines.h new file mode 100644 index 00000000..fd98439a --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpPolylines.h @@ -0,0 +1,29 @@ +/* +Copyright 2005-2012 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 __RDPPOLYLINES_H +#define __RDPPOLYLINES_H + +void +rdpPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode, + int npt, DDXPointPtr pptInit); + +#endif diff --git a/xorg/X11R7.6/rdp/rdpPushPixels.c b/xorg/X11R7.6/rdp/rdpPushPixels.c new file mode 100644 index 00000000..06c5ba9f --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpPushPixels.c @@ -0,0 +1,189 @@ +/* +Copyright 2005-2012 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 "rdp.h" +#include "rdpdraw.h" + +#define LDEBUG 0 + +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpGCIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpWindowIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */ +extern int g_Bpp; /* from rdpmain.c */ +extern ScreenPtr g_pScreen; /* from rdpmain.c */ +extern Bool g_wrapPixmap; /* from rdpmain.c */ +extern int g_do_dirty_os; /* in rdpmain.c */ + +extern GCOps g_rdpGCOps; /* from rdpdraw.c */ + +extern int g_con_number; /* in rdpup.c */ + +/******************************************************************************/ +void +rdpPushPixelsOrg(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst, + int w, int h, int x, int y) +{ + rdpGCPtr priv; + GCFuncs* oldFuncs; + + GC_OP_PROLOGUE(pGC); + pGC->ops->PushPixels(pGC, pBitMap, pDst, w, h, x, y); + GC_OP_EPILOGUE(pGC); +} + +/******************************************************************************/ +void +rdpPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst, + int w, int h, int x, int y) +{ + RegionRec clip_reg; + RegionRec box_reg; + RegionRec reg1; + int num_clips; + int cd; + int j; + int got_id; + int dirty_type; + int post_process; + int reset_surface; + BoxRec box; + struct image_data id; + WindowPtr pDstWnd; + PixmapPtr pDstPixmap; + rdpPixmapRec* pDstPriv; + rdpPixmapRec* pDirtyPriv; + + LLOGLN(10, ("rdpPushPixels:")); + + /* do original call */ + rdpPushPixelsOrg(pGC, pBitMap, pDst, w, h, x, y); + + dirty_type = 0; + pDirtyPriv = 0; + post_process = 0; + reset_surface = 0; + got_id = 0; + if (pDst->type == DRAWABLE_PIXMAP) + { + pDstPixmap = (PixmapPtr)pDst; + pDstPriv = GETPIXPRIV(pDstPixmap); + if (XRDP_IS_OS(pDstPriv)) + { + post_process = 1; + if (g_do_dirty_os) + { + LLOGLN(10, ("rdpPutImage: gettig dirty")); + pDstPriv->is_dirty = 1; + pDirtyPriv = pDstPriv; + dirty_type = RDI_IMGLY; + } + else + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + reset_surface = 1; + rdpup_get_pixmap_image_rect(pDstPixmap, &id); + got_id = 1; + } + } + } + else + { + if (pDst->type == DRAWABLE_WINDOW) + { + pDstWnd = (WindowPtr)pDst; + if (pDstWnd->viewable) + { + post_process = 1; + rdpup_get_screen_image_rect(&id); + got_id = 1; + } + } + } + if (!post_process) + { + return; + } + + memset(&box, 0, sizeof(box)); + RegionInit(&clip_reg, NullBox, 0); + cd = rdp_get_clip(&clip_reg, pDst, pGC); + if (cd == 1) + { + if (dirty_type != 0) + { + box.x1 = pDst->x + x; + box.y1 = pDst->y + y; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + RegionInit(®1, &box, 0); + draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type); + RegionUninit(®1); + } + else if (got_id) + { + rdpup_begin_update(); + rdpup_send_area(0, pDst->x + x, pDst->y + y, w, h); + rdpup_end_update(); + } + } + else if (cd == 2) + { + box.x1 = pDst->x + x; + box.y1 = pDst->y + y; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + RegionInit(&box_reg, &box, 0); + RegionIntersect(&clip_reg, &clip_reg, &box_reg); + num_clips = REGION_NUM_RECTS(&clip_reg); + if (num_clips > 0) + { + if (dirty_type != 0) + { + RegionInit(®1, &box, 0); + draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type); + RegionUninit(®1); + } + else if (got_id) + { + rdpup_begin_update(); + for (j = num_clips - 1; j >= 0; j--) + { + box = REGION_RECTS(&clip_reg)[j]; + rdpup_send_area(0, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + } + rdpup_end_update(); + } + } + RegionUninit(&box_reg); + } + RegionUninit(&clip_reg); + if (reset_surface) + { + rdpup_switch_os_surface(-1); + } +} diff --git a/xorg/X11R7.6/rdp/rdpPushPixels.h b/xorg/X11R7.6/rdp/rdpPushPixels.h new file mode 100644 index 00000000..249da583 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpPushPixels.h @@ -0,0 +1,29 @@ +/* +Copyright 2005-2012 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 __RDPPUSHPIXELS_H +#define __RDPPUSHPIXELS_H + +void +rdpPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst, + int w, int h, int x, int y); + +#endif diff --git a/xorg/X11R7.6/rdp/rdpPutImage.c b/xorg/X11R7.6/rdp/rdpPutImage.c new file mode 100644 index 00000000..798016f3 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpPutImage.c @@ -0,0 +1,188 @@ +/* +Copyright 2005-2012 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 "rdp.h" +#include "rdpdraw.h" + +#define LDEBUG 0 + +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpGCIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpWindowIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */ +extern int g_Bpp; /* from rdpmain.c */ +extern ScreenPtr g_pScreen; /* from rdpmain.c */ +extern Bool g_wrapPixmap; /* from rdpmain.c */ +extern int g_do_dirty_os; /* in rdpmain.c */ + +extern GCOps g_rdpGCOps; /* from rdpdraw.c */ + +extern int g_con_number; /* in rdpup.c */ + +/******************************************************************************/ +static void +rdpPutImageOrg(DrawablePtr pDst, GCPtr pGC, int depth, int x, int y, + int w, int h, int leftPad, int format, char* pBits) +{ + rdpGCPtr priv; + GCFuncs* oldFuncs; + + GC_OP_PROLOGUE(pGC); + pGC->ops->PutImage(pDst, pGC, depth, x, y, w, h, leftPad, + format, pBits); + GC_OP_EPILOGUE(pGC); +} + +/******************************************************************************/ +void +rdpPutImage(DrawablePtr pDst, GCPtr pGC, int depth, int x, int y, + int w, int h, int leftPad, int format, char* pBits) +{ + RegionRec clip_reg; + int cd; + int j; + int reset_surface; + int post_process; + int got_id; + int dirty_type; + BoxRec box; + struct image_data id; + + WindowPtr pDstWnd; + PixmapPtr pDstPixmap; + rdpPixmapRec* pDstPriv; + rdpPixmapRec* pDirtyPriv; + RegionRec reg1; + RegionRec reg2; + + LLOGLN(10, ("rdpPutImage:")); + LLOGLN(10, ("rdpPutImage: drawable id 0x%x", (int)(pDst->id))); + + /* do original call */ + rdpPutImageOrg(pDst, pGC, depth, x, y, w, h, leftPad, format, pBits); + + dirty_type = 0; + pDirtyPriv = 0; + post_process = 0; + reset_surface = 0; + got_id = 0; + if (pDst->type == DRAWABLE_PIXMAP) + { + pDstPixmap = (PixmapPtr)pDst; + pDstPriv = GETPIXPRIV(pDstPixmap); + if (XRDP_IS_OS(pDstPriv)) + { + post_process = 1; + if (g_do_dirty_os) + { + LLOGLN(10, ("rdpPutImage: gettig dirty")); + pDstPriv->is_dirty = 1; + pDirtyPriv = pDstPriv; + dirty_type = RDI_IMGLY; + } + else + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + reset_surface = 1; + rdpup_get_pixmap_image_rect(pDstPixmap, &id); + got_id = 1; + } + } + } + else + { + if (pDst->type == DRAWABLE_WINDOW) + { + pDstWnd = (WindowPtr)pDst; + if (pDstWnd->viewable) + { + post_process = 1; + rdpup_get_screen_image_rect(&id); + got_id = 1; + } + } + } + if (!post_process) + { + return; + } + RegionInit(&clip_reg, NullBox, 0); + cd = rdp_get_clip(&clip_reg, pDst, pGC); + if (cd == 1) + { + if (dirty_type != 0) + { + box.x1 = pDst->x + x; + box.y1 = pDst->y + y; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + RegionInit(®1, &box, 0); + draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type); + RegionUninit(®1); + } + else if (got_id) + { + rdpup_begin_update(); + rdpup_send_area(&id, pDst->x + x, pDst->y + y, w, h); + rdpup_end_update(); + } + } + else if (cd == 2) + { + if (dirty_type != 0) + { + box.x1 = pDst->x + x; + box.y1 = pDst->y + y; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + RegionInit(®1, &box, 0); + RegionInit(®2, NullBox, 0); + RegionCopy(®2, &clip_reg); + RegionIntersect(®1, ®1, ®2); + draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type); + RegionUninit(®1); + RegionUninit(®2); + } + else if (got_id) + { + rdpup_begin_update(); + for (j = REGION_NUM_RECTS(&clip_reg) - 1; j >= 0; j--) + { + box = REGION_RECTS(&clip_reg)[j]; + rdpup_set_clip(box.x1, box.y1, (box.x2 - box.x1), (box.y2 - box.y1)); + rdpup_send_area(&id, pDst->x + x, pDst->y + y, w, h); + } + rdpup_reset_clip(); + rdpup_end_update(); + } + } + RegionUninit(&clip_reg); + if (reset_surface) + { + rdpup_switch_os_surface(-1); + } +} diff --git a/xorg/X11R7.6/rdp/rdpPutImage.h b/xorg/X11R7.6/rdp/rdpPutImage.h new file mode 100644 index 00000000..94119a81 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpPutImage.h @@ -0,0 +1,29 @@ +/* +Copyright 2005-2012 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 __RDPPUTIMAGE_H +#define __RDPPUTIMAGE_H + +void +rdpPutImage(DrawablePtr pDst, GCPtr pGC, int depth, int x, int y, + int w, int h, int leftPad, int format, char* pBits); + +#endif diff --git a/xorg/X11R7.6/rdp/rdpSetSpans.c b/xorg/X11R7.6/rdp/rdpSetSpans.c new file mode 100644 index 00000000..aab36f88 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpSetSpans.c @@ -0,0 +1,151 @@ +/* +Copyright 2005-2012 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 "rdp.h" +#include "rdpdraw.h" + +#define LDEBUG 0 + +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpGCIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpWindowIndex; /* from rdpmain.c */ +extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */ +extern int g_Bpp; /* from rdpmain.c */ +extern ScreenPtr g_pScreen; /* from rdpmain.c */ +extern Bool g_wrapPixmap; /* from rdpmain.c */ +extern int g_do_dirty_os; /* in rdpmain.c */ + +extern GCOps g_rdpGCOps; /* from rdpdraw.c */ + +extern int g_con_number; /* in rdpup.c */ + +/******************************************************************************/ +void +rdpSetSpansOrg(DrawablePtr pDrawable, GCPtr pGC, char* psrc, + DDXPointPtr ppt, int* pwidth, int nspans, int fSorted) +{ + rdpGCPtr priv; + GCFuncs* oldFuncs; + + GC_OP_PROLOGUE(pGC); + pGC->ops->SetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); + GC_OP_EPILOGUE(pGC); +} + +/******************************************************************************/ +void +rdpSetSpans(DrawablePtr pDrawable, GCPtr pGC, char* psrc, + DDXPointPtr ppt, int* pwidth, int nspans, int fSorted) +{ + RegionRec clip_reg; + int cd; + int got_id; + int dirty_type; + int post_process; + int reset_surface; + struct image_data id; + WindowPtr pDstWnd; + PixmapPtr pDstPixmap; + rdpPixmapRec* pDstPriv; + rdpPixmapRec* pDirtyPriv; + + LLOGLN(10, ("rdpSetSpans: todo")); + + /* do original call */ + rdpSetSpansOrg(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); + + dirty_type = 0; + pDirtyPriv = 0; + post_process = 0; + reset_surface = 0; + got_id = 0; + if (pDrawable->type == DRAWABLE_PIXMAP) + { + pDstPixmap = (PixmapPtr)pDrawable; + pDstPriv = GETPIXPRIV(pDstPixmap); + if (XRDP_IS_OS(pDstPriv)) + { + post_process = 1; + if (g_do_dirty_os) + { + LLOGLN(10, ("rdpSetSpans: gettig dirty")); + pDstPriv->is_dirty = 1; + pDirtyPriv = pDstPriv; + dirty_type = RDI_IMGLY; + } + else + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + reset_surface = 1; + rdpup_get_pixmap_image_rect(pDstPixmap, &id); + got_id = 1; + } + } + } + else + { + if (pDrawable->type == DRAWABLE_WINDOW) + { + pDstWnd = (WindowPtr)pDrawable; + if (pDstWnd->viewable) + { + post_process = 1; + rdpup_get_screen_image_rect(&id); + got_id = 1; + } + } + } + if (!post_process) + { + return; + } + RegionInit(&clip_reg, NullBox, 0); + cd = rdp_get_clip(&clip_reg, pDrawable, pGC); + if (cd == 1) + { + if (dirty_type != 0) + { + } + else if (got_id) + { + } + } + else if (cd == 2) + { + if (dirty_type != 0) + { + } + else if (got_id) + { + } + } + RegionUninit(&clip_reg); + if (reset_surface) + { + rdpup_switch_os_surface(-1); + } +} diff --git a/xorg/X11R7.6/rdp/rdpSetSpans.h b/xorg/X11R7.6/rdp/rdpSetSpans.h new file mode 100644 index 00000000..3346f00e --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpSetSpans.h @@ -0,0 +1,29 @@ +/* +Copyright 2005-2012 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 __RDPSETSPANS_H +#define __RDPSETSPANS_H + +void +rdpSetSpans(DrawablePtr pDrawable, GCPtr pGC, char* psrc, + DDXPointPtr ppt, int* pwidth, int nspans, int fSorted); + +#endif diff --git a/xorg/X11R7.6/rdp/rdpdraw.c b/xorg/X11R7.6/rdp/rdpdraw.c index 9dba7c02..78b2aa3d 100644 --- a/xorg/X11R7.6/rdp/rdpdraw.c +++ b/xorg/X11R7.6/rdp/rdpdraw.c @@ -23,14 +23,34 @@ Xserver drawing ops and funcs #include "rdp.h" #include "gcops.h" - -#if 1 -#define DEBUG_OUT_FUNCS(arg) -#define DEBUG_OUT_OPS(arg) -#else -#define DEBUG_OUT_FUNCS(arg) ErrorF arg -#define DEBUG_OUT_OPS(arg) ErrorF arg -#endif +#include "rdpdraw.h" + +#include "rdpCopyArea.h" +#include "rdpPolyFillRect.h" +#include "rdpPutImage.h" +#include "rdpPolyRectangle.h" +#include "rdpPolylines.h" +#include "rdpPolySegment.h" +#include "rdpFillSpans.h" +#include "rdpSetSpans.h" +#include "rdpCopyPlane.h" +#include "rdpPolyPoint.h" +#include "rdpPolyArc.h" +#include "rdpFillPolygon.h" +#include "rdpPolyFillArc.h" +#include "rdpPolyText8.h" +#include "rdpPolyText16.h" +#include "rdpImageText8.h" +#include "rdpImageText16.h" +#include "rdpImageGlyphBlt.h" +#include "rdpPolyGlyphBlt.h" +#include "rdpPushPixels.h" + +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ extern DevPrivateKeyRec g_rdpGCIndex; /* from rdpmain.c */ @@ -38,16 +58,22 @@ extern DevPrivateKeyRec g_rdpWindowIndex; /* from rdpmain.c */ extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */ extern int g_Bpp; /* from rdpmain.c */ extern ScreenPtr g_pScreen; /* from rdpmain.c */ +extern Bool g_wrapPixmap; /* from rdpmain.c */ +extern WindowPtr g_invalidate_window; /* in rdpmain.c */ +extern int g_use_rail; /* in rdpmain.c */ +extern int g_do_dirty_os; /* in rdpmain.c */ ColormapPtr g_rdpInstalledColormap; -static GCFuncs g_rdpGCFuncs = +static int g_doing_font = 0; + +GCFuncs g_rdpGCFuncs = { rdpValidateGC, rdpChangeGC, rdpCopyGC, rdpDestroyGC, rdpChangeClip, rdpDestroyClip, rdpCopyClip }; -static GCOps g_rdpGCOps = +GCOps g_rdpGCOps = { rdpFillSpans, rdpSetSpans, rdpPutImage, rdpCopyArea, rdpCopyPlane, rdpPolyPoint, rdpPolylines, rdpPolySegment, rdpPolyRectangle, @@ -60,7 +86,7 @@ static GCOps g_rdpGCOps = /* return 0, draw nothing */ /* return 1, draw with no clip */ /* return 2, draw using clip */ -static int +int rdp_get_clip(RegionPtr pRegion, DrawablePtr pDrawable, GCPtr pGC) { WindowPtr pWindow; @@ -69,7 +95,34 @@ rdp_get_clip(RegionPtr pRegion, DrawablePtr pDrawable, GCPtr pGC) int rv; rv = 0; - if (pDrawable->type == DRAWABLE_WINDOW) + if (pDrawable->type == DRAWABLE_PIXMAP) + { + switch (pGC->clientClipType) + { + case CT_NONE: + rv = 1; + break; + case CT_REGION: + rv = 2; + RegionCopy(pRegion, pGC->clientClip); + break; + default: + rdpLog("unimp clip type %d\n", pGC->clientClipType); + break; + } + if (rv == 2) /* check if the clip is the entire pixmap */ + { + box.x1 = 0; + box.y1 = 0; + box.x2 = pDrawable->width; + box.y2 = pDrawable->height; + if (RegionContainsRect(pRegion, &box) == rgnIN) + { + rv = 1; + } + } + } + else if (pDrawable->type == DRAWABLE_WINDOW) { pWindow = (WindowPtr)pDrawable; if (pWindow->viewable) @@ -120,7 +173,7 @@ rdp_get_clip(RegionPtr pRegion, DrawablePtr pDrawable, GCPtr pGC) } /******************************************************************************/ -static void +void GetTextBoundingBox(DrawablePtr pDrawable, FontPtr font, int x, int y, int n, BoxPtr pbox) { @@ -191,27 +244,34 @@ static void rdpValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr d) { rdpGCRec* priv; - int viewable; + int wrap; RegionPtr pRegion; - DEBUG_OUT_FUNCS(("in rdpValidateGC\n")); + LLOGLN(10, ("rdpValidateGC:")); GC_FUNC_PROLOGUE(pGC); pGC->funcs->ValidateGC(pGC, changes, d); - viewable = d->type == DRAWABLE_WINDOW && ((WindowPtr)d)->viewable; - if (viewable) + if (g_wrapPixmap) { - if (pGC->subWindowMode == IncludeInferiors) - { - pRegion = &(((WindowPtr)d)->borderClip); - } - else + wrap = 1; + } + else + { + wrap = (d->type == DRAWABLE_WINDOW) && ((WindowPtr)d)->viewable; + if (wrap) { - pRegion = &(((WindowPtr)d)->clipList); + if (pGC->subWindowMode == IncludeInferiors) + { + pRegion = &(((WindowPtr)d)->borderClip); + } + else + { + pRegion = &(((WindowPtr)d)->clipList); + } + wrap = RegionNotEmpty(pRegion); } - viewable = RegionNotEmpty(pRegion); } priv->ops = 0; - if (viewable) + if (wrap) { priv->ops = pGC->ops; } @@ -224,7 +284,7 @@ rdpChangeGC(GCPtr pGC, unsigned long mask) { rdpGCRec* priv; - DEBUG_OUT_FUNCS(("in rdpChangeGC\n")); + LLOGLN(10, ("in rdpChangeGC")); GC_FUNC_PROLOGUE(pGC); pGC->funcs->ChangeGC(pGC, mask); GC_FUNC_EPILOGUE(pGC); @@ -236,7 +296,7 @@ rdpCopyGC(GCPtr src, unsigned long mask, GCPtr dst) { rdpGCRec* priv; - DEBUG_OUT_FUNCS(("in rdpCopyGC\n")); + LLOGLN(10, ("in rdpCopyGC")); GC_FUNC_PROLOGUE(dst); dst->funcs->CopyGC(src, mask, dst); GC_FUNC_EPILOGUE(dst); @@ -248,7 +308,7 @@ rdpDestroyGC(GCPtr pGC) { rdpGCRec* priv; - DEBUG_OUT_FUNCS(("in rdpDestroyGC\n")); + LLOGLN(10, ("in rdpDestroyGC")); GC_FUNC_PROLOGUE(pGC); pGC->funcs->DestroyGC(pGC); GC_FUNC_EPILOGUE(pGC); @@ -260,7 +320,7 @@ rdpChangeClip(GCPtr pGC, int type, pointer pValue, int nrects) { rdpGCRec* priv; - DEBUG_OUT_FUNCS(("in rdpChangeClip\n")); + LLOGLN(10, ("in rdpChangeClip")); GC_FUNC_PROLOGUE(pGC); pGC->funcs->ChangeClip(pGC, type, pValue, nrects); GC_FUNC_EPILOGUE(pGC); @@ -272,7 +332,7 @@ rdpDestroyClip(GCPtr pGC) { rdpGCRec* priv; - DEBUG_OUT_FUNCS(("in rdpDestroyClip\n")); + LLOGLN(10, ("in rdpDestroyClip")); GC_FUNC_PROLOGUE(pGC); pGC->funcs->DestroyClip(pGC); GC_FUNC_EPILOGUE(pGC); @@ -284,7 +344,7 @@ rdpCopyClip(GCPtr dst, GCPtr src) { rdpGCRec* priv; - DEBUG_OUT_FUNCS(("in rdpCopyClip\n")); + LLOGLN(0, ("in rdpCopyClip")); GC_FUNC_PROLOGUE(dst); dst->funcs->CopyClip(dst, src); GC_FUNC_EPILOGUE(dst); @@ -308,1566 +368,463 @@ rdpCopyClip(GCPtr dst, GCPtr src) } /******************************************************************************/ -static void -rdpFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit, - DDXPointPtr pptInit, int* pwidthInit, int fSorted) -{ - rdpGCPtr priv; - RegionRec clip_reg; - int cd; - int j; - GCFuncs* oldFuncs; - BoxRec box; - - DEBUG_OUT_OPS(("in rdpFillSpans\n")); - GC_OP_PROLOGUE(pGC) - pGC->ops->FillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted); - RegionInit(&clip_reg, NullBox, 0); - cd = rdp_get_clip(&clip_reg, pDrawable, pGC); - if (cd == 1) - { - rdpup_begin_update(); - RegionCopy(&clip_reg, &(((WindowPtr)pDrawable)->borderClip)); - for (j = REGION_NUM_RECTS(&clip_reg) - 1; j >= 0; j--) - { - box = REGION_RECTS(&clip_reg)[j]; - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - } - rdpup_end_update(); - } - else if (cd == 2) - { - rdpup_begin_update(); - RegionIntersect(&clip_reg, &clip_reg, - &(((WindowPtr)pDrawable)->borderClip)); - for (j = REGION_NUM_RECTS(&clip_reg) - 1; j >= 0; j--) - { - box = REGION_RECTS(&clip_reg)[j]; - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - } - rdpup_end_update(); - } - RegionUninit(&clip_reg); - GC_OP_EPILOGUE(pGC); -} - -/******************************************************************************/ -static void -rdpSetSpans(DrawablePtr pDrawable, GCPtr pGC, char* psrc, - DDXPointPtr ppt, int* pwidth, int nspans, int fSorted) -{ - rdpGCPtr priv; - RegionRec clip_reg; - int cd; - int j; - GCFuncs* oldFuncs; - BoxRec box; - - DEBUG_OUT_OPS(("in rdpSetSpans\n")); - GC_OP_PROLOGUE(pGC); - pGC->ops->SetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); - RegionInit(&clip_reg, NullBox, 0); - cd = rdp_get_clip(&clip_reg, pDrawable, pGC); - if (cd == 1) - { - rdpup_begin_update(); - RegionCopy(&clip_reg, &(((WindowPtr)pDrawable)->borderClip)); - for (j = REGION_NUM_RECTS(&clip_reg) - 1; j >= 0; j--) - { - box = REGION_RECTS(&clip_reg)[j]; - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - } - rdpup_end_update(); - } - else if (cd == 2) - { - rdpup_begin_update(); - RegionIntersect(&clip_reg, &clip_reg, - &((WindowPtr)pDrawable)->borderClip); - for (j = REGION_NUM_RECTS(&clip_reg) - 1; j >= 0; j--) - { - box = REGION_RECTS(&clip_reg)[j]; - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - } - rdpup_end_update(); - } - RegionUninit(&clip_reg); - GC_OP_EPILOGUE(pGC); -} - -/******************************************************************************/ -static void -rdpPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, - int w, int h, int leftPad, int format, char* pBits) -{ - rdpGCPtr priv; - RegionRec clip_reg; - int cd; - int j; - GCFuncs* oldFuncs; - BoxRec box; - - DEBUG_OUT_OPS(("in rdpPutImage\n")); - GC_OP_PROLOGUE(pGC); - pGC->ops->PutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, - format, pBits); - RegionInit(&clip_reg, NullBox, 0); - cd = rdp_get_clip(&clip_reg, pDrawable, pGC); - if (cd == 1) - { - rdpup_begin_update(); - rdpup_send_area(pDrawable->x + x, pDrawable->y + y, w, h); - rdpup_end_update(); - } - else if (cd == 2) - { - rdpup_begin_update(); - for (j = REGION_NUM_RECTS(&clip_reg) - 1; j >= 0; j--) - { - box = REGION_RECTS(&clip_reg)[j]; - rdpup_set_clip(box.x1, box.y1, (box.x2 - box.x1), (box.y2 - box.y1)); - rdpup_send_area(pDrawable->x + x, pDrawable->y + y, w, h); - } - rdpup_reset_clip(); - rdpup_end_update(); - } - RegionUninit(&clip_reg); - GC_OP_EPILOGUE(pGC); -} - -/******************************************************************************/ -static RegionPtr -rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, - int srcx, int srcy, int w, int h, int dstx, int dsty) +Bool +rdpCloseScreen(int i, ScreenPtr pScreen) { - rdpGCPtr priv; - RegionPtr rv; - RegionRec clip_reg; - RegionRec box_reg; - int num_clips; - int cd; - int j; - int can_do_screen_blt; - int dx; - int dy; - BoxRec box; - BoxPtr pbox; - GCFuncs* oldFuncs; - - DEBUG_OUT_OPS(("in rdpCopyArea\n")); - GC_OP_PROLOGUE(pGC); - rv = pGC->ops->CopyArea(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); - RegionInit(&clip_reg, NullBox, 0); - cd = rdp_get_clip(&clip_reg, pDst, pGC); - can_do_screen_blt = pSrc->type == DRAWABLE_WINDOW && - ((WindowPtr)pSrc)->viewable && - pGC->alu == GXcopy; - if (cd == 1) - { - rdpup_begin_update(); - if (can_do_screen_blt) - { - rdpup_screen_blt(pDst->x + dstx, pDst->y + dsty, w, h, - pSrc->x + srcx, pSrc->y + srcy); - } - else - { - rdpup_send_area(pDst->x + dstx, pDst->y + dsty, w, h); - } - rdpup_end_update(); - } - else if (cd == 2) - { - num_clips = REGION_NUM_RECTS(&clip_reg); - if (num_clips > 0) - { - rdpup_begin_update(); - if (can_do_screen_blt) - { - dx = dstx - srcx; - dy = dsty - srcy; - if (dy < 0 || (dy == 0 && dx < 0)) - { - for (j = 0; j < num_clips; j++) - { - box = REGION_RECTS(&clip_reg)[j]; - rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - rdpup_screen_blt(pDst->x + dstx, pDst->y + dsty, w, h, - pSrc->x + srcx, pSrc->y + srcy); - } - } - else - { - for (j = num_clips - 1; j >= 0; j--) - { - box = REGION_RECTS(&clip_reg)[j]; - rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - rdpup_screen_blt(pDst->x + dstx, pDst->y + dsty, w, h, - pSrc->x + srcx, pSrc->y + srcy); - } - } - rdpup_reset_clip(); - } - else - { - box.x1 = pDst->x + dstx; - box.y1 = pDst->y + dsty; - box.x2 = box.x1 + w; - box.y2 = box.y1 + h; - RegionInit(&box_reg, &box, 0); - RegionIntersect(&clip_reg, &clip_reg, &box_reg); - num_clips = REGION_NUM_RECTS(&clip_reg); - if (num_clips < 10) - { - for (j = num_clips - 1; j >= 0; j--) - { - box = REGION_RECTS(&clip_reg)[j]; - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - } - } - else - { - pbox = RegionExtents(&clip_reg); - rdpup_send_area(pbox->x1, pbox->y1, pbox->x2 - pbox->x1, - pbox->y2 - pbox->y1); - } - RegionUninit(&box_reg); - } - rdpup_end_update(); - } - } - RegionUninit(&clip_reg); - GC_OP_EPILOGUE(pGC); - return rv; + LLOGLN(10, ("in rdpCloseScreen")); + pScreen->CloseScreen = g_rdpScreen.CloseScreen; + pScreen->CreateGC = g_rdpScreen.CreateGC; + //pScreen->PaintWindowBackground = g_rdpScreen.PaintWindowBackground; + //pScreen->PaintWindowBorder = g_rdpScreen.PaintWindowBorder; + pScreen->CopyWindow = g_rdpScreen.CopyWindow; + pScreen->ClearToBackground = g_rdpScreen.ClearToBackground; + pScreen->RestoreAreas = g_rdpScreen.RestoreAreas; + return 1; } /******************************************************************************/ -static RegionPtr -rdpCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, - GCPtr pGC, int srcx, int srcy, int w, int h, - int dstx, int dsty, unsigned long bitPlane) +int +draw_item_add(rdpPixmapRec* priv, struct rdp_draw_item* di) { - rdpGCPtr priv; - RegionPtr rv; - RegionRec clip_reg; - RegionRec box_reg; - int cd; - int num_clips; - int j; - GCFuncs* oldFuncs; - BoxRec box; - BoxPtr pbox; - - DEBUG_OUT_OPS(("in rdpCopyPlane\n")); - GC_OP_PROLOGUE(pGC); - rv = pGC->ops->CopyPlane(pSrc, pDst, pGC, srcx, srcy, - w, h, dstx, dsty, bitPlane); - RegionInit(&clip_reg, NullBox, 0); - cd = rdp_get_clip(&clip_reg, pDst, pGC); - if (cd == 1) + if (priv->draw_item_tail == 0) { - rdpup_begin_update(); - rdpup_send_area(pDst->x + dstx, pDst->y + dsty, w, h); - rdpup_end_update(); + priv->draw_item_tail = di; + priv->draw_item_head = di; } - else if (cd == 2) + else { - num_clips = REGION_NUM_RECTS(&clip_reg); - if (num_clips > 0) - { - rdpup_begin_update(); - box.x1 = pDst->x + dstx; - box.y1 = pDst->y + dsty; - box.x2 = box.x1 + w; - box.y2 = box.y1 + h; - RegionInit(&box_reg, &box, 0); - RegionIntersect(&clip_reg, &clip_reg, &box_reg); - num_clips = REGION_NUM_RECTS(&clip_reg); - if (num_clips < 10) - { - for (j = num_clips - 1; j >= 0; j--) - { - box = REGION_RECTS(&clip_reg)[j]; - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - } - } - else - { - pbox = RegionExtents(&clip_reg); - rdpup_send_area(pbox->x1, pbox->y1, pbox->x2 - pbox->x1, - pbox->y2 - pbox->y1); - } - RegionUninit(&box_reg); - rdpup_end_update(); - } + di->prev = priv->draw_item_tail; + priv->draw_item_tail->next = di; + priv->draw_item_tail = di; } - RegionUninit(&clip_reg); - GC_OP_EPILOGUE(pGC); - return rv; + return 0; } /******************************************************************************/ -static void -rdpPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, - int npt, DDXPointPtr in_pts) +int +draw_item_remove(rdpPixmapRec* priv, struct rdp_draw_item* di) { - rdpGCPtr priv; - RegionRec clip_reg; - int num_clips; - int cd; - int x; - int y; - int i; - int j; - GCFuncs* oldFuncs; - BoxRec box; - BoxRec total_box; - DDXPointPtr pts; - DDXPointRec stack_pts[32]; - - DEBUG_OUT_OPS(("in rdpPolyPoint\n")); - GC_OP_PROLOGUE(pGC); - if (npt > 32) + if (di->prev != 0) { - pts = (DDXPointPtr)g_malloc(sizeof(DDXPointRec) * npt, 0); + di->prev->next = di->next; } - else + if (di->next != 0) { - pts = stack_pts; + di->next->prev = di->prev; } - for (i = 0; i < npt; i++) + if (priv->draw_item_head == di) { - pts[i].x = pDrawable->x + in_pts[i].x; - pts[i].y = pDrawable->y + in_pts[i].y; - if (i == 0) - { - total_box.x1 = pts[0].x; - total_box.y1 = pts[0].y; - total_box.x2 = pts[0].x; - total_box.y2 = pts[0].y; - } - else - { - if (pts[i].x < total_box.x1) - { - total_box.x1 = pts[i].x; - } - if (pts[i].y < total_box.y1) - { - total_box.y1 = pts[i].y; - } - if (pts[i].x > total_box.x2) - { - total_box.x2 = pts[i].x; - } - if (pts[i].y > total_box.y2) - { - total_box.y2 = pts[i].y; - } - } - /* todo, use this total_box */ + priv->draw_item_head = di->next; } - pGC->ops->PolyPoint(pDrawable, pGC, mode, npt, in_pts); - RegionInit(&clip_reg, NullBox, 0); - cd = rdp_get_clip(&clip_reg, pDrawable, pGC); - if (cd == 1) + if (priv->draw_item_tail == di) { - if (npt > 0) - { - rdpup_begin_update(); - rdpup_set_fgcolor(pGC->fgPixel); - for (i = 0; i < npt; i++) - { - x = pts[i].x; - y = pts[i].y; - rdpup_fill_rect(x, y, 1, 1); - } - rdpup_end_update(); - } + priv->draw_item_tail = di->prev; } - else if (cd == 2) + if (di->type == RDI_LINE) { - num_clips = REGION_NUM_RECTS(&clip_reg); - if (npt > 0 && num_clips > 0) + if (di->u.line.segs != 0) { - rdpup_begin_update(); - rdpup_set_fgcolor(pGC->fgPixel); - for (j = num_clips - 1; j >= 0; j--) - { - box = REGION_RECTS(&clip_reg)[j]; - rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - for (i = 0; i < npt; i++) - { - x = pts[i].x; - y = pts[i].y; - rdpup_fill_rect(x, y, 1, 1); - } - } - rdpup_reset_clip(); - rdpup_end_update(); + g_free(di->u.line.segs); } } - RegionUninit(&clip_reg); - if (pts != stack_pts) - { - g_free(pts); - } - GC_OP_EPILOGUE(pGC); + RegionDestroy(di->reg); + g_free(di); + return 0; } /******************************************************************************/ -static void -rdpPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode, - int npt, DDXPointPtr pptInit) +int +draw_item_remove_all(rdpPixmapRec* priv) { - rdpGCPtr priv; - RegionRec clip_reg; - int num_clips; - int cd; - int i; - int j; - int x1; - int y1; - int x2; - int y2; - GCFuncs* oldFuncs; - BoxRec box; - DDXPointPtr ppts; + struct rdp_draw_item* di; - DEBUG_OUT_OPS(("in rdpPolylines\n")); - GC_OP_PROLOGUE(pGC); - ppts = 0; - if (npt > 0) + di = priv->draw_item_head; + while (di != 0) { - ppts = (DDXPointPtr)g_malloc(sizeof(DDXPointRec) * npt, 0); - for (i = 0; i < npt; i++) - { - ppts[i] = pptInit[i]; - } + draw_item_remove(priv, di); + di = priv->draw_item_head; } - pGC->ops->Polylines(pDrawable, pGC, mode, npt, pptInit); - RegionInit(&clip_reg, NullBox, 0); - cd = rdp_get_clip(&clip_reg, pDrawable, pGC); - if (cd == 1) - { - if (ppts != 0) - { - rdpup_begin_update(); - rdpup_set_fgcolor(pGC->fgPixel); - rdpup_set_opcode(pGC->alu); - rdpup_set_pen(0, pGC->lineWidth); - x1 = ppts[0].x + pDrawable->x; - y1 = ppts[0].y + pDrawable->y; - for (i = 1; i < npt; i++) - { - if (mode == CoordModeOrigin) - { - x2 = pDrawable->x + ppts[i].x; - y2 = pDrawable->y + ppts[i].y; - } - else - { - x2 = x1 + ppts[i].x; - y2 = y1 + ppts[i].y; - } - rdpup_draw_line(x1, y1, x2, y2); - x1 = x2; - y1 = y2; - } - rdpup_set_opcode(GXcopy); - rdpup_end_update(); - } - } - else if (cd == 2) - { - num_clips = REGION_NUM_RECTS(&clip_reg); - if (ppts != 0 && num_clips > 0) - { - rdpup_begin_update(); - rdpup_set_fgcolor(pGC->fgPixel); - rdpup_set_opcode(pGC->alu); - rdpup_set_pen(0, pGC->lineWidth); - for (j = num_clips - 1; j >= 0; j--) - { - box = REGION_RECTS(&clip_reg)[j]; - rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - x1 = ppts[0].x + pDrawable->x; - y1 = ppts[0].y + pDrawable->y; - for (i = 1; i < npt; i++) - { - if (mode == CoordModeOrigin) - { - x2 = pDrawable->x + ppts[i].x; - y2 = pDrawable->y + ppts[i].y; - } - else - { - x2 = x1 + ppts[i].x; - y2 = y1 + ppts[i].y; - } - rdpup_draw_line(x1, y1, x2, y2); - x1 = x2; - y1 = y2; - } - } - rdpup_reset_clip(); - rdpup_set_opcode(GXcopy); - rdpup_end_update(); - } - } - RegionUninit(&clip_reg); - g_free(ppts); - GC_OP_EPILOGUE(pGC); + return 0; } /******************************************************************************/ -static void -rdpPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment* pSegs) +int +draw_item_pack(rdpPixmapRec* priv) { - rdpGCPtr priv; - RegionRec clip_reg; - int cd; - int i; - int j; - GCFuncs* oldFuncs; - xSegment* segs; - BoxRec box; + struct rdp_draw_item* di; + struct rdp_draw_item* di_prev; - DEBUG_OUT_OPS(("in rdpPolySegment\n")); - GC_OP_PROLOGUE(pGC); - segs = 0; - if (nseg) /* get the rects */ - { - segs = (xSegment*)g_malloc(nseg * sizeof(xSegment), 0); - for (i = 0; i < nseg; i++) - { - segs[i].x1 = pSegs[i].x1 + pDrawable->x; - segs[i].y1 = pSegs[i].y1 + pDrawable->y; - segs[i].x2 = pSegs[i].x2 + pDrawable->x; - segs[i].y2 = pSegs[i].y2 + pDrawable->y; - } - } - pGC->ops->PolySegment(pDrawable, pGC, nseg, pSegs); - RegionInit(&clip_reg, NullBox, 0); - cd = rdp_get_clip(&clip_reg, pDrawable, pGC); - if (cd == 1) /* no clip */ - { - if (segs != 0) - { - rdpup_begin_update(); - rdpup_set_fgcolor(pGC->fgPixel); - rdpup_set_opcode(pGC->alu); - rdpup_set_pen(0, pGC->lineWidth); - for (i = 0; i < nseg; i++) - { - rdpup_draw_line(segs[i].x1, segs[i].y1, segs[i].x2, segs[i].y2); - } - rdpup_set_opcode(GXcopy); - rdpup_end_update(); - } - } - else if (cd == 2) /* clip */ +#if 1 + /* look for repeating draw types */ + if (priv->draw_item_head != 0) { - if (segs != 0) + if (priv->draw_item_head->next != 0) { - rdpup_begin_update(); - rdpup_set_fgcolor(pGC->fgPixel); - rdpup_set_opcode(pGC->alu); - rdpup_set_pen(0, pGC->lineWidth); - for (j = REGION_NUM_RECTS(&clip_reg) - 1; j >= 0; j--) + di_prev = priv->draw_item_head; + di = priv->draw_item_head->next; + while (di != 0) { - box = REGION_RECTS(&clip_reg)[j]; - rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - for (i = 0; i < nseg; i++) + if ((di_prev->type == RDI_IMGLL) && (di->type == RDI_IMGLL)) { - rdpup_draw_line(segs[i].x1, segs[i].y1, segs[i].x2, segs[i].y2); + LLOGLN(10, ("draw_item_pack: packing RDI_IMGLL")); + RegionUnion(di_prev->reg, di_prev->reg, di->reg); + draw_item_remove(priv, di); + di = di_prev->next; } - } - rdpup_reset_clip(); - rdpup_set_opcode(GXcopy); - rdpup_end_update(); - } - } - g_free(segs); - RegionUninit(&clip_reg); - GC_OP_EPILOGUE(pGC); -} - -/******************************************************************************/ -/* tested with pGC->lineWidth = 0, 1, 2, 4 and opcodes 3 and 6 */ -static void -rdpPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects, - xRectangle* rects) -{ - rdpGCPtr priv; - RegionRec clip_reg; - RegionPtr fill_reg; - int num_clips; - int cd; - int lw; - int i; - int j; - int up; - int down; - GCFuncs* oldFuncs; - xRectangle* regRects; - xRectangle* r; - xRectangle* rect1; - BoxRec box; - - DEBUG_OUT_OPS(("in rdpPolyRectangle\n")); - GC_OP_PROLOGUE(pGC); - /* make a copy of rects */ - rect1 = (xRectangle*)g_malloc(sizeof(xRectangle) * nrects, 0); - for (i = 0; i < nrects; i++) - { - rect1[i] = rects[i]; - } - pGC->ops->PolyRectangle(pDrawable, pGC, nrects, rects); - RegionInit(&clip_reg, NullBox, 0); - cd = rdp_get_clip(&clip_reg, pDrawable, pGC); - regRects = 0; - if (cd != 0 && nrects > 0) - { - regRects = (xRectangle*)g_malloc(nrects * 4 * sizeof(xRectangle), 0); - lw = pGC->lineWidth; - if (lw < 1) - { - lw = 1; - } - up = lw / 2; - down = 1 + (lw - 1) / 2; - for (i = 0; i < nrects; i++) - { - r = regRects + i * 4; - r->x = (rect1[i].x + pDrawable->x) - up; - r->y = (rect1[i].y + pDrawable->y) - up; - r->width = rect1[i].width + up + down; - r->height = lw; - r++; - r->x = (rect1[i].x + pDrawable->x) - up; - r->y = (rect1[i].y + pDrawable->y) + down; - r->width = lw; - r->height = MAX(rect1[i].height - (up + down), 0); - r++; - r->x = ((rect1[i].x + rect1[i].width) + pDrawable->x) - up; - r->y = (rect1[i].y + pDrawable->y) + down; - r->width = lw; - r->height = MAX(rect1[i].height - (up + down), 0); - r++; - r->x = (rect1[i].x + pDrawable->x) - up; - r->y = ((rect1[i].y + rect1[i].height) + pDrawable->y) - up; - r->width = rect1[i].width + up + down; - r->height = lw; - } - } - if (cd == 1) - { - if (regRects != 0) - { - rdpup_begin_update(); - if (pGC->lineStyle == LineSolid) - { - rdpup_set_fgcolor(pGC->fgPixel); - rdpup_set_opcode(pGC->alu); - for (i = 0; i < nrects * 4; i++) + else if ((di_prev->type == RDI_IMGLY) && (di->type == RDI_IMGLY)) { - r = regRects + i; - rdpup_fill_rect(r->x, r->y, r->width, r->height); + LLOGLN(10, ("draw_item_pack: packing RDI_IMGLY")); + RegionUnion(di_prev->reg, di_prev->reg, di->reg); + draw_item_remove(priv, di); + di = di_prev->next; } - rdpup_set_opcode(GXcopy); - } - else - { - for (i = 0; i < nrects * 4; i++) + else { - r = regRects + i; - rdpup_send_area(r->x, r->y, r->width, r->height); + di_prev = di; + di = di_prev->next; } } - rdpup_end_update(); } } - else if (cd == 2) +#endif +#if 1 + /* subtract regions */ + if (priv->draw_item_tail != 0) { - if (regRects != 0) + if (priv->draw_item_tail->prev != 0) { - fill_reg = RegionFromRects(nrects * 4, regRects, CT_NONE); - RegionIntersect(&clip_reg, &clip_reg, fill_reg); - num_clips = REGION_NUM_RECTS(&clip_reg); - if (num_clips > 0) + di = priv->draw_item_tail; + while (di->prev != 0) { - rdpup_begin_update(); - if (pGC->lineStyle == LineSolid) - { - rdpup_set_fgcolor(pGC->fgPixel); - rdpup_set_opcode(pGC->alu); - for (j = num_clips - 1; j >= 0; j--) - { - box = REGION_RECTS(&clip_reg)[j]; - rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - } - rdpup_set_opcode(GXcopy); - } - else + /* skip subtract flag + * draw items like line can't be used to clear(subtract) previous + * draw items since they are not opaque + * eg they can not be the 'S' in 'D = M - S' + * the region for line draw items is the clip region */ + if ((di->flags & 1) == 0) { - for (j = num_clips - 1; j >= 0; j--) + di_prev = di->prev; + while (di_prev != 0) { - box = REGION_RECTS(&clip_reg)[j]; - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + /* D = M - S */ + RegionSubtract(di_prev->reg, di_prev->reg, di->reg); + di_prev = di_prev->prev; } } - rdpup_end_update(); + di = di->prev; } - RegionDestroy(fill_reg); } } - RegionUninit(&clip_reg); - g_free(regRects); - g_free(rect1); - GC_OP_EPILOGUE(pGC); -} - -/******************************************************************************/ -static void -rdpPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc* parcs) -{ - rdpGCPtr priv; - RegionRec clip_reg; - RegionPtr tmpRegion; - int cd; - int lw; - int extra; - int i; - int num_clips; - GCFuncs* oldFuncs; - xRectangle* rects; - BoxRec box; - - DEBUG_OUT_OPS(("in rdpPolyArc\n")); - GC_OP_PROLOGUE(pGC); - rects = 0; - if (narcs > 0) - { - rects = (xRectangle*)g_malloc(narcs * sizeof(xRectangle), 0); - lw = pGC->lineWidth; - if (lw == 0) - { - lw = 1; - } - extra = lw / 2; - for (i = 0; i < narcs; i++) - { - rects[i].x = (parcs[i].x - extra) + pDrawable->x; - rects[i].y = (parcs[i].y - extra) + pDrawable->y; - rects[i].width = parcs[i].width + lw; - rects[i].height = parcs[i].height + lw; - } - } - pGC->ops->PolyArc(pDrawable, pGC, narcs, parcs); - RegionInit(&clip_reg, NullBox, 0); - cd = rdp_get_clip(&clip_reg, pDrawable, pGC); - if (cd == 1) +#endif +#if 1 + /* remove draw items with empty regions */ + di = priv->draw_item_head; + di_prev = 0; + while (di != 0) { - if (rects != 0) + if (!RegionNotEmpty(di->reg)) { - tmpRegion = RegionFromRects(narcs, rects, CT_NONE); - num_clips = REGION_NUM_RECTS(tmpRegion); - if (num_clips > 0) - { - rdpup_begin_update(); - for (i = num_clips - 1; i >= 0; i--) - { - box = REGION_RECTS(tmpRegion)[i]; - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - } - rdpup_end_update(); - } - RegionDestroy(tmpRegion); + LLOGLN(10, ("draw_item_pack: removing empty item type %d", di->type)); + draw_item_remove(priv, di); + di = di_prev == 0 ? priv->draw_item_head : di_prev->next; } - } - else if (cd == 2) - { - if (rects != 0) + else { - tmpRegion = RegionFromRects(narcs, rects, CT_NONE); - RegionIntersect(tmpRegion, tmpRegion, &clip_reg); - num_clips = REGION_NUM_RECTS(tmpRegion); - if (num_clips > 0) - { - rdpup_begin_update(); - for (i = num_clips - 1; i >= 0; i--) - { - box = REGION_RECTS(tmpRegion)[i]; - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - } - rdpup_end_update(); - } - RegionDestroy(tmpRegion); + di_prev = di; + di = di->next; } } - RegionUninit(&clip_reg); - g_free(rects); - GC_OP_EPILOGUE(pGC); +#endif + return 0; } /******************************************************************************/ -static void -rdpFillPolygon(DrawablePtr pDrawable, GCPtr pGC, - int shape, int mode, int count, - DDXPointPtr pPts) +int +draw_item_add_img_region(rdpPixmapRec* priv, RegionPtr reg, int opcode, + int type) { - rdpGCPtr priv; - RegionRec clip_reg; - RegionRec box_reg; - int num_clips; - int cd; - int maxx; - int maxy; - int minx; - int miny; - int i; - int j; - GCFuncs* oldFuncs; - BoxRec box; - - DEBUG_OUT_OPS(("in rdpFillPolygon\n")); - GC_OP_PROLOGUE(pGC); - pGC->ops->FillPolygon(pDrawable, pGC, shape, mode, count, pPts); - RegionInit(&clip_reg, NullBox, 0); - cd = rdp_get_clip(&clip_reg, pDrawable, pGC); - if (cd != 0) - { - 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 (i = 1; i < count; i++) - { - if (pPts[i].x > maxx) - { - maxx = pPts[i].x; - } - if (pPts[i].x < minx) - { - minx = pPts[i].x; - } - if (pPts[i].y > maxy) - { - maxy = pPts[i].y; - } - if (pPts[i].y < miny) - { - miny = pPts[i].y; - } - box.x1 = pDrawable->x + minx; - box.y1 = pDrawable->y + miny; - box.x2 = pDrawable->x + maxx + 1; - box.y2 = pDrawable->y + maxy + 1; - } - } - } - if (cd == 1) - { - rdpup_begin_update(); - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - rdpup_end_update(); - } - else if (cd == 2) - { - RegionInit(&box_reg, &box, 0); - RegionIntersect(&clip_reg, &clip_reg, &box_reg); - num_clips = REGION_NUM_RECTS(&clip_reg); - if (num_clips > 0) - { - rdpup_begin_update(); - for (j = num_clips - 1; j >= 0; j--) - { - box = REGION_RECTS(&clip_reg)[j]; - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - } - rdpup_end_update(); - } - RegionUninit(&box_reg); - } - RegionUninit(&clip_reg); - GC_OP_EPILOGUE(pGC); + struct rdp_draw_item* di; + + di = (struct rdp_draw_item*)g_malloc(sizeof(struct rdp_draw_item), 1); + di->type = type; + di->reg = RegionCreate(NullBox, 0); + RegionCopy(di->reg, reg); + di->u.img.opcode = opcode; + draw_item_add(priv, di); + return 0; } /******************************************************************************/ -static void -rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, - xRectangle* prectInit) +int +draw_item_add_fill_region(rdpPixmapRec* priv, RegionPtr reg, int color, + int opcode) { - int i; - int j; - int cd; - int num_clips; - xRectangle* copy_of_rects; - rdpGCPtr priv; - RegionRec clip_reg; - RegionPtr fill_reg; - BoxRec box; - GCFuncs* oldFuncs; - - DEBUG_OUT_OPS(("in rdpPolyFillRect\n")); - GC_OP_PROLOGUE(pGC); - /* make a copy of rects */ - copy_of_rects = (xRectangle*)g_malloc(sizeof(xRectangle) * nrectFill, 0); - for (i = 0; i < nrectFill; i++) - { - copy_of_rects[i] = prectInit[i]; - } - fill_reg = RegionFromRects(nrectFill, copy_of_rects, CT_NONE); - g_free(copy_of_rects); - RegionTranslate(fill_reg, pDrawable->x, pDrawable->y); - pGC->ops->PolyFillRect(pDrawable, pGC, nrectFill, prectInit); - RegionInit(&clip_reg, NullBox, 0); - cd = rdp_get_clip(&clip_reg, pDrawable, pGC); - if (cd == 1) /* no clip */ - { - rdpup_begin_update(); - if (pGC->fillStyle == 0 && /* solid fill */ - (pGC->alu == GXclear || - pGC->alu == GXset || - pGC->alu == GXinvert || - pGC->alu == GXnoop || - pGC->alu == GXand || - pGC->alu == GXcopy /*|| - pGC->alu == GXxor*/)) /* todo, why dosen't xor work? */ - { - rdpup_set_fgcolor(pGC->fgPixel); - rdpup_set_opcode(pGC->alu); - for (j = REGION_NUM_RECTS(fill_reg) - 1; j >= 0; j--) - { - box = REGION_RECTS(fill_reg)[j]; - rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - } - rdpup_set_opcode(GXcopy); - } - else /* non solid fill */ - { - for (j = REGION_NUM_RECTS(fill_reg) - 1; j >= 0; j--) - { - box = REGION_RECTS(fill_reg)[j]; - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - } - } - rdpup_end_update(); - } - else if (cd == 2) /* clip */ - { - RegionIntersect(&clip_reg, &clip_reg, fill_reg); - num_clips = REGION_NUM_RECTS(&clip_reg); - if (num_clips > 0) - { - rdpup_begin_update(); - if (pGC->fillStyle == 0 && /* solid fill */ - (pGC->alu == GXclear || - pGC->alu == GXset || - pGC->alu == GXinvert || - pGC->alu == GXnoop || - pGC->alu == GXand || - pGC->alu == GXcopy /*|| - pGC->alu == GXxor*/)) /* todo, why dosen't xor work? */ - { - rdpup_set_fgcolor(pGC->fgPixel); - rdpup_set_opcode(pGC->alu); - for (j = num_clips - 1; j >= 0; j--) - { - box = REGION_RECTS(&clip_reg)[j]; - rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - } - rdpup_set_opcode(GXcopy); - } - else /* non solid fill */ - { - for (j = num_clips - 1; j >= 0; j--) - { - box = REGION_RECTS(&clip_reg)[j]; - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - } - } - rdpup_end_update(); - } - } - RegionUninit(&clip_reg); - RegionDestroy(fill_reg); - GC_OP_EPILOGUE(pGC); + struct rdp_draw_item* di; + + di = (struct rdp_draw_item*)g_malloc(sizeof(struct rdp_draw_item), 1); + di->type = RDI_FILL; + di->u.fill.fg_color = color; + di->u.fill.opcode = opcode; + di->reg = RegionCreate(NullBox, 0); + RegionCopy(di->reg, reg); + draw_item_add(priv, di); + return 0; } /******************************************************************************/ -static void -rdpPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc* parcs) +int +draw_item_add_line_region(rdpPixmapRec* priv, RegionPtr reg, int color, + int opcode, int width, xSegment* segs, int nseg, + int is_segment) { - rdpGCPtr priv; - RegionRec clip_reg; - RegionPtr tmpRegion; - int cd; - int lw; - int extra; - int i; - int num_clips; - GCFuncs* oldFuncs; - xRectangle* rects; - BoxRec box; - - DEBUG_OUT_OPS(("in rdpPolyFillArc\n")); - GC_OP_PROLOGUE(pGC); - rects = 0; - if (narcs > 0) - { - rects = (xRectangle*)g_malloc(narcs * sizeof(xRectangle), 0); - lw = pGC->lineWidth; - if (lw == 0) - { - lw = 1; - } - extra = lw / 2; - for (i = 0; i < narcs; i++) - { - rects[i].x = (parcs[i].x - extra) + pDrawable->x; - rects[i].y = (parcs[i].y - extra) + pDrawable->y; - rects[i].width = parcs[i].width + lw; - rects[i].height = parcs[i].height + lw; - } - } - pGC->ops->PolyFillArc(pDrawable, pGC, narcs, parcs); - RegionInit(&clip_reg, NullBox, 0); - cd = rdp_get_clip(&clip_reg, pDrawable, pGC); - if (cd == 1) - { - if (rects != 0) - { - tmpRegion = RegionFromRects(narcs, rects, CT_NONE); - num_clips = REGION_NUM_RECTS(tmpRegion); - if (num_clips > 0) - { - rdpup_begin_update(); - for (i = num_clips - 1; i >= 0; i--) - { - box = REGION_RECTS(tmpRegion)[i]; - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - } - rdpup_end_update(); - } - RegionDestroy(tmpRegion); - } - } - else if (cd == 2) - { - if (rects != 0) - { - tmpRegion = RegionFromRects(narcs, rects, CT_NONE); - RegionIntersect(tmpRegion, tmpRegion, &clip_reg); - num_clips = REGION_NUM_RECTS(tmpRegion); - if (num_clips > 0) - { - rdpup_begin_update(); - for (i = num_clips - 1; i >= 0; i--) - { - box = REGION_RECTS(tmpRegion)[i]; - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - } - rdpup_end_update(); - } - RegionDestroy(tmpRegion); - } - } - RegionUninit(&clip_reg); - g_free(rects); - GC_OP_EPILOGUE(pGC); + struct rdp_draw_item* di; + + LLOGLN(10, ("draw_item_add_line_region:")); + di = (struct rdp_draw_item*)g_malloc(sizeof(struct rdp_draw_item), 1); + di->type = RDI_LINE; + di->u.line.fg_color = color; + di->u.line.opcode = opcode; + di->u.line.width = width; + di->u.line.segs = (xSegment*)g_malloc(sizeof(xSegment) * nseg, 1); + memcpy(di->u.line.segs, segs, sizeof(xSegment) * nseg); + di->u.line.nseg = nseg; + if (is_segment) + { + di->u.line.flags = 1; + } + di->reg = RegionCreate(NullBox, 0); + di->flags |= 1; + RegionCopy(di->reg, reg); + draw_item_add(priv, di); + return 0; } /******************************************************************************/ -static int -rdpPolyText8(DrawablePtr pDrawable, GCPtr pGC, - int x, int y, int count, char* chars) +PixmapPtr +rdpCreatePixmap(ScreenPtr pScreen, int width, int height, int depth, + unsigned usage_hint) { - rdpGCPtr priv; - RegionRec reg; - RegionRec reg1; - int num_clips; - int cd; - int j; - int rv; - GCFuncs* oldFuncs; - BoxRec box; + PixmapPtr rv; + rdpPixmapRec* priv; + int org_width; - DEBUG_OUT_OPS(("in rdpPolyText8\n")); - GC_OP_PROLOGUE(pGC); - if (count != 0) - { - GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); - } - rv = pGC->ops->PolyText8(pDrawable, pGC, x, y, count, chars); - RegionInit(®, NullBox, 0); - if (count == 0) - { - cd = 0; - } - else - { - cd = rdp_get_clip(®, pDrawable, pGC); - } - if (cd == 1) - { - rdpup_begin_update(); - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - rdpup_end_update(); - } - else if (cd == 2) + org_width = width; + /* width must be a multiple of 4 in rdp */ + width = (width + 3) & ~3; + LLOGLN(10, ("rdpCreatePixmap: width %d org_width %d depth %d screen depth %d", + width, org_width, depth, g_rdpScreen.depth)); + pScreen->CreatePixmap = g_rdpScreen.CreatePixmap; + rv = pScreen->CreatePixmap(pScreen, width, height, depth, usage_hint); + priv = GETPIXPRIV(rv); + priv->rdpindex = -1; + if ((rv->drawable.depth >= g_rdpScreen.depth) && + (org_width > 1) && (height > 1)) { - RegionInit(®1, &box, 0); - RegionIntersect(®, ®, ®1); - num_clips = REGION_NUM_RECTS(®); - if (num_clips > 0) + priv->allocBytes = width * height * g_Bpp; + priv->rdpindex = rdpup_add_os_bitmap(rv, priv); + if (priv->rdpindex >= 0) { - rdpup_begin_update(); - for (j = num_clips - 1; j >= 0; j--) - { - box = REGION_RECTS(®)[j]; - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - } - rdpup_end_update(); + priv->status = 1; + rdpup_create_os_surface(priv->rdpindex, width, height); } - RegionUninit(®1); } - RegionUninit(®); - GC_OP_EPILOGUE(pGC); + pScreen->ModifyPixmapHeader(rv, org_width, 0, 0, 0, 0, 0); + pScreen->CreatePixmap = rdpCreatePixmap; return rv; } +extern struct rdpup_os_bitmap* g_os_bitmaps; + /******************************************************************************/ -static int -rdpPolyText16(DrawablePtr pDrawable, GCPtr pGC, - int x, int y, int count, unsigned short* chars) +Bool +rdpDestroyPixmap(PixmapPtr pPixmap) { - rdpGCPtr priv; - RegionRec reg; - RegionRec reg1; - int num_clips; - int cd; - int j; - int rv; - GCFuncs* oldFuncs; - BoxRec box; + Bool rv; + ScreenPtr pScreen; + rdpPixmapRec* priv; - DEBUG_OUT_OPS(("in rdpPolyText16\n")); - GC_OP_PROLOGUE(pGC); - if (count != 0) - { - GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); - } - rv = pGC->ops->PolyText16(pDrawable, pGC, x, y, count, chars); - RegionInit(®, NullBox, 0); - if (count == 0) - { - cd = 0; - } - else - { - cd = rdp_get_clip(®, pDrawable, pGC); - } - if (cd == 1) - { - rdpup_begin_update(); - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - rdpup_end_update(); - } - else if (cd == 2) + LLOGLN(10, ("rdpDestroyPixmap:")); + priv = GETPIXPRIV(pPixmap); + LLOGLN(10, ("status %d refcnt %d", priv->status, pPixmap->refcnt)); + if (pPixmap->refcnt < 2) { - RegionInit(®1, &box, 0); - RegionIntersect(®, ®, ®1); - num_clips = REGION_NUM_RECTS(®); - if (num_clips > 0) + if (XRDP_IS_OS(priv)) { - rdpup_begin_update(); - for (j = num_clips - 1; j >= 0; j--) - { - box = REGION_RECTS(®)[j]; - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - } - rdpup_end_update(); + rdpup_remove_os_bitmap(priv->rdpindex); + rdpup_delete_os_surface(priv->rdpindex); + draw_item_remove_all(priv); } - RegionUninit(®1); } - RegionUninit(®); - GC_OP_EPILOGUE(pGC); + pScreen = pPixmap->drawable.pScreen; + pScreen->DestroyPixmap = g_rdpScreen.DestroyPixmap; + rv = pScreen->DestroyPixmap(pPixmap); + pScreen->DestroyPixmap = rdpDestroyPixmap; return rv; } /******************************************************************************/ -static void -rdpImageText8(DrawablePtr pDrawable, GCPtr pGC, - int x, int y, int count, char* chars) +Bool +rdpCreateWindow(WindowPtr pWindow) { - rdpGCPtr priv; - RegionRec clip_reg; - RegionRec box_reg; - int num_clips; - int cd; - int j; - GCFuncs* oldFuncs; - BoxRec box; + ScreenPtr pScreen; + rdpWindowRec* priv; + Bool rv; - DEBUG_OUT_OPS(("in rdpImageText8\n")); - GC_OP_PROLOGUE(pGC); - if (count != 0) - { - GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); - } - pGC->ops->ImageText8(pDrawable, pGC, x, y, count, chars); - RegionInit(&clip_reg, NullBox, 0); - if (count == 0) - { - cd = 0; - } - else - { - cd = rdp_get_clip(&clip_reg, pDrawable, pGC); - } - if (cd == 1) + LLOGLN(10, ("rdpCreateWindow:")); + priv = GETWINPRIV(pWindow); + LLOGLN(10, (" %p status %d", priv, priv->status)); + pScreen = pWindow->drawable.pScreen; + pScreen->CreateWindow = g_rdpScreen.CreateWindow; + rv = pScreen->CreateWindow(pWindow); + pScreen->CreateWindow = rdpCreateWindow; + if (g_use_rail) { - rdpup_begin_update(); - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - rdpup_end_update(); } - else if (cd == 2) - { - RegionInit(&box_reg, &box, 0); - RegionIntersect(&clip_reg, &clip_reg, &box_reg); - num_clips = REGION_NUM_RECTS(&clip_reg); - if (num_clips > 0) - { - rdpup_begin_update(); - for (j = num_clips - 1; j >= 0; j--) - { - box = REGION_RECTS(&clip_reg)[j]; - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - } - rdpup_end_update(); - } - RegionUninit(&box_reg); - } - RegionUninit(&clip_reg); - GC_OP_EPILOGUE(pGC); + return rv; } /******************************************************************************/ -static void -rdpImageText16(DrawablePtr pDrawable, GCPtr pGC, - int x, int y, int count, - unsigned short* chars) +Bool +rdpDestroyWindow(WindowPtr pWindow) { - rdpGCPtr priv; - RegionRec clip_reg; - RegionRec box_reg; - int num_clips; - int cd; - int j; - GCFuncs* oldFuncs; - BoxRec box; + ScreenPtr pScreen; + rdpWindowRec* priv; + Bool rv; - DEBUG_OUT_OPS(("in rdpImageText16\n")); - GC_OP_PROLOGUE(pGC); - if (count != 0) - { - GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); - } - pGC->ops->ImageText16(pDrawable, pGC, x, y, count, chars); - RegionInit(&clip_reg, NullBox, 0); - if (count == 0) - { - cd = 0; - } - else - { - cd = rdp_get_clip(&clip_reg, pDrawable, pGC); - } - if (cd == 1) + LLOGLN(10, ("rdpDestroyWindow:")); + priv = GETWINPRIV(pWindow); + pScreen = pWindow->drawable.pScreen; + pScreen->DestroyWindow = g_rdpScreen.DestroyWindow; + rv = pScreen->DestroyWindow(pWindow); + pScreen->DestroyWindow = rdpDestroyWindow; + if (g_use_rail) { - rdpup_begin_update(); - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - rdpup_end_update(); } - else if (cd == 2) - { - RegionInit(&box_reg, &box, 0); - RegionIntersect(&clip_reg, &clip_reg, &box_reg); - num_clips = REGION_NUM_RECTS(&clip_reg); - if (num_clips > 0) - { - rdpup_begin_update(); - for (j = num_clips - 1; j >= 0; j--) - { - box = REGION_RECTS(&clip_reg)[j]; - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - } - rdpup_end_update(); - } - RegionUninit(&box_reg); - } - RegionUninit(&clip_reg); - GC_OP_EPILOGUE(pGC); + return rv; } /******************************************************************************/ -static void -rdpImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, - int x, int y, unsigned int nglyph, - CharInfoPtr* ppci, pointer pglyphBase) +Bool +rdpPositionWindow(WindowPtr pWindow, int x, int y) { - rdpGCPtr priv; - RegionRec reg; - RegionRec box_reg; - int num_clips; - int cd; - int j; - GCFuncs* oldFuncs; - BoxRec box; + ScreenPtr pScreen; + rdpWindowRec* priv; + Bool rv; - DEBUG_OUT_OPS(("in rdpImageGlyphBlt\n")); - GC_OP_PROLOGUE(pGC); - if (nglyph != 0) - { - GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box); - } - pGC->ops->ImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); - RegionInit(®, NullBox, 0); - if (nglyph == 0) - { - cd = 0; - } - else - { - cd = rdp_get_clip(®, pDrawable, pGC); - } - if (cd == 1) - { - rdpup_begin_update(); - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - rdpup_end_update(); - } - else if (cd == 2) + LLOGLN(10, ("rdpPositionWindow:")); + priv = GETWINPRIV(pWindow); + pScreen = pWindow->drawable.pScreen; + pScreen->PositionWindow = g_rdpScreen.PositionWindow; + rv = pScreen->PositionWindow(pWindow, x, y); + pScreen->PositionWindow = rdpPositionWindow; + if (g_use_rail) { - RegionInit(&box_reg, &box, 0); - RegionIntersect(®, ®, &box_reg); - num_clips = REGION_NUM_RECTS(®); - if (num_clips > 0) + if (priv->status == 1) { - rdpup_begin_update(); - for (j = num_clips - 1; j >= 0; j--) - { - box = REGION_RECTS(®)[j]; - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - } - rdpup_end_update(); + LLOGLN(10, ("rdpPositionWindow:")); + LLOGLN(10, (" x %d y %d", x, y)); } - RegionUninit(&box_reg); } - RegionUninit(®); - GC_OP_EPILOGUE(pGC); + return rv; } /******************************************************************************/ -static void -rdpPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, - int x, int y, unsigned int nglyph, - CharInfoPtr* ppci, - pointer pglyphBase) +Bool +rdpRealizeWindow(WindowPtr pWindow) { - rdpGCPtr priv; - RegionRec reg; - RegionRec box_reg; - int num_clips; - int cd; - int j; - GCFuncs* oldFuncs; - BoxRec box; + ScreenPtr pScreen; + rdpWindowRec* priv; + Bool rv; - DEBUG_OUT_OPS(("in rdpPolyGlyphBlt\n")); - GC_OP_PROLOGUE(pGC); - memset(&box, 0, sizeof(box)); - if (nglyph != 0) - { - GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box); - } - pGC->ops->PolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); - RegionInit(®, NullBox, 0); - if (nglyph == 0) - { - cd = 0; - } - else - { - cd = rdp_get_clip(®, pDrawable, pGC); - } - if (cd == 1) - { - rdpup_begin_update(); - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - rdpup_end_update(); - } - else if (cd == 2) + LLOGLN(10, ("rdpRealizeWindow:")); + priv = GETWINPRIV(pWindow); + pScreen = pWindow->drawable.pScreen; + pScreen->RealizeWindow = g_rdpScreen.RealizeWindow; + rv = pScreen->RealizeWindow(pWindow); + pScreen->RealizeWindow = rdpRealizeWindow; + if (g_use_rail) { - RegionInit(&box_reg, &box, 0); - RegionIntersect(®, ®, &box_reg); - num_clips = REGION_NUM_RECTS(®); - if (num_clips > 0) + if ((pWindow != g_invalidate_window) && (pWindow->parent != 0)) { - rdpup_begin_update(); - for (j = num_clips - 1; j >= 0; j--) + if (XR_IS_ROOT(pWindow->parent)) { - box = REGION_RECTS(®)[j]; - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + LLOGLN(10, ("rdpRealizeWindow:")); + LLOGLN(10, (" pWindow %p id 0x%x pWindow->parent %p id 0x%x x %d " + "y %d width %d height %d", + pWindow, pWindow->drawable.id, + pWindow->parent, pWindow->parent->drawable.id, + pWindow->drawable.x, pWindow->drawable.y, + pWindow->drawable.width, pWindow->drawable.height)); + priv->status = 1; + rdpup_create_window(pWindow, priv); } - rdpup_end_update(); } - RegionUninit(&box_reg); } - RegionUninit(®); - GC_OP_EPILOGUE(pGC); + return rv; } /******************************************************************************/ -static void -rdpPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst, - int w, int h, int x, int y) +Bool +rdpUnrealizeWindow(WindowPtr pWindow) { - rdpGCPtr priv; - RegionRec clip_reg; - RegionRec box_reg; - int num_clips; - int cd; - int j; - GCFuncs* oldFuncs; - BoxRec box; + ScreenPtr pScreen; + rdpWindowRec* priv; + Bool rv; - DEBUG_OUT_OPS(("in rdpPushPixels\n")); - GC_OP_PROLOGUE(pGC); - memset(&box, 0, sizeof(box)); - pGC->ops->PushPixels(pGC, pBitMap, pDst, w, h, x, y); - RegionInit(&clip_reg, NullBox, 0); - cd = rdp_get_clip(&clip_reg, pDst, pGC); - if (cd == 1) - { - rdpup_begin_update(); - rdpup_send_area(x, y, w, h); - rdpup_end_update(); - } - else if (cd == 2) + LLOGLN(10, ("rdpUnrealizeWindow:")); + priv = GETWINPRIV(pWindow); + pScreen = pWindow->drawable.pScreen; + pScreen->UnrealizeWindow = g_rdpScreen.UnrealizeWindow; + rv = pScreen->UnrealizeWindow(pWindow); + pScreen->UnrealizeWindow = rdpUnrealizeWindow; + if (g_use_rail) { - RegionInit(&box_reg, &box, 0); - RegionIntersect(&clip_reg, &clip_reg, &box_reg); - num_clips = REGION_NUM_RECTS(&clip_reg); - if (num_clips > 0) + if (priv->status == 1) { - rdpup_begin_update(); - for (j = num_clips - 1; j >= 0; j--) - { - box = REGION_RECTS(&clip_reg)[j]; - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); - } - rdpup_end_update(); + LLOGLN(10, ("rdpUnrealizeWindow:")); + priv->status = 0; + rdpup_delete_window(pWindow, priv); } - RegionUninit(&box_reg); } - RegionUninit(&clip_reg); - GC_OP_EPILOGUE(pGC); -} - -/******************************************************************************/ -Bool -rdpCloseScreen(int i, ScreenPtr pScreen) -{ - DEBUG_OUT_OPS(("in rdpCloseScreen\n")); - pScreen->CloseScreen = g_rdpScreen.CloseScreen; - pScreen->CreateGC = g_rdpScreen.CreateGC; - //pScreen->PaintWindowBackground = g_rdpScreen.PaintWindowBackground; - //pScreen->PaintWindowBorder = g_rdpScreen.PaintWindowBorder; - pScreen->CopyWindow = g_rdpScreen.CopyWindow; - pScreen->ClearToBackground = g_rdpScreen.ClearToBackground; - pScreen->RestoreAreas = g_rdpScreen.RestoreAreas; - return 1; -} - -/******************************************************************************/ -PixmapPtr -rdpCreatePixmap(ScreenPtr pScreen, int width, int height, int depth, - unsigned usage_hint) -{ - PixmapPtr rv; - rdpPixmapRec* priv; - - //ErrorF("rdpCreatePixmap:\n"); - //ErrorF(" in width %d height %d depth %d\n", width, height, depth); - pScreen->CreatePixmap = g_rdpScreen.CreatePixmap; - rv = pScreen->CreatePixmap(pScreen, width, height, depth, usage_hint); - priv = GETPIXPRIV(rv); - pScreen->CreatePixmap = rdpCreatePixmap; - //ErrorF(" out width %d height %d depth %d\n", rv->drawable.width, - // rv->drawable.height, rv->drawable.depth); return rv; } /******************************************************************************/ Bool -rdpDestroyPixmap(PixmapPtr pPixmap) -{ - Bool rv; - ScreenPtr pScreen; - rdpPixmapRec* priv; - - //ErrorF("rdpDestroyPixmap:\n"); - priv = GETPIXPRIV(pPixmap); - //ErrorF(" refcnt %d\n", pPixmap->refcnt); - pScreen = pPixmap->drawable.pScreen; - pScreen->DestroyPixmap = g_rdpScreen.DestroyPixmap; - rv = pScreen->DestroyPixmap(pPixmap); - pScreen->DestroyPixmap = rdpDestroyPixmap; - return rv; -} - -/******************************************************************************/ -Bool -rdpCreateWindow(WindowPtr pWindow) +rdpChangeWindowAttributes(WindowPtr pWindow, unsigned long mask) { ScreenPtr pScreen; rdpWindowRec* priv; Bool rv; - //ErrorF("rdpCreateWindow:\n"); + LLOGLN(10, ("rdpChangeWindowAttributes:")); priv = GETWINPRIV(pWindow); - //ErrorF(" %p status %d\n", priv, priv->status); pScreen = pWindow->drawable.pScreen; - pScreen->CreateWindow = g_rdpScreen.CreateWindow; - rv = pScreen->CreateWindow(pWindow); - pScreen->CreateWindow = rdpCreateWindow; + pScreen->ChangeWindowAttributes = g_rdpScreen.ChangeWindowAttributes; + rv = pScreen->ChangeWindowAttributes(pWindow, mask); + pScreen->ChangeWindowAttributes = rdpChangeWindowAttributes; + if (g_use_rail) + { + } return rv; } /******************************************************************************/ -Bool -rdpDestroyWindow(WindowPtr pWindow) +void +rdpWindowExposures(WindowPtr pWindow, RegionPtr pRegion, RegionPtr pBSRegion) { ScreenPtr pScreen; rdpWindowRec* priv; - Bool rv; - //ErrorF("rdpDestroyWindow:\n"); + LLOGLN(10, ("rdpWindowExposures:")); priv = GETWINPRIV(pWindow); pScreen = pWindow->drawable.pScreen; - pScreen->DestroyWindow = g_rdpScreen.DestroyWindow; - rv = pScreen->DestroyWindow(pWindow); - pScreen->DestroyWindow = rdpDestroyWindow; - return rv; + pScreen->WindowExposures = g_rdpScreen.WindowExposures; + pScreen->WindowExposures(pWindow, pRegion, pBSRegion); + if (g_use_rail) + { + } + pScreen->WindowExposures = rdpWindowExposures; } /******************************************************************************/ @@ -1877,7 +834,7 @@ rdpCreateGC(GCPtr pGC) rdpGCRec* priv; Bool rv; - DEBUG_OUT_OPS(("in rdpCreateGC\n")); + LLOGLN(10, ("in rdpCreateGC\n")); priv = GETGCPRIV(pGC); g_pScreen->CreateGC = g_rdpScreen.CreateGC; rv = g_pScreen->CreateGC(pGC); @@ -1910,7 +867,7 @@ rdpCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion) BoxRec box1; BoxRec box2; - DEBUG_OUT_OPS(("in rdpCopyWindow\n")); + LLOGLN(10, ("in rdpCopyWindow")); RegionInit(®, NullBox, 0); RegionCopy(®, pOldRegion); g_pScreen->CopyWindow = g_rdpScreen.CopyWindow; @@ -1969,7 +926,7 @@ rdpClearToBackground(WindowPtr pWin, int x, int y, int w, int h, BoxRec box; RegionRec reg; - DEBUG_OUT_OPS(("in rdpClearToBackground\n")); + LLOGLN(10, ("in rdpClearToBackground")); g_pScreen->ClearToBackground = g_rdpScreen.ClearToBackground; g_pScreen->ClearToBackground(pWin, x, y, w, h, generateExposures); if (!generateExposures) @@ -1994,7 +951,7 @@ rdpClearToBackground(WindowPtr pWin, int x, int y, int w, int h, for (j = REGION_NUM_RECTS(®) - 1; j >= 0; j--) { box = REGION_RECTS(®)[j]; - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + rdpup_send_area(0, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } rdpup_end_update(); RegionUninit(®); @@ -2011,7 +968,7 @@ rdpRestoreAreas(WindowPtr pWin, RegionPtr prgnExposed) int j; BoxRec box; - DEBUG_OUT_OPS(("in rdpRestoreAreas\n")); + LLOGLN(10, ("in rdpRestoreAreas")); RegionInit(®, NullBox, 0); RegionCopy(®, prgnExposed); g_pScreen->RestoreAreas = g_rdpScreen.RestoreAreas; @@ -2020,7 +977,7 @@ rdpRestoreAreas(WindowPtr pWin, RegionPtr prgnExposed) for (j = REGION_NUM_RECTS(®) - 1; j >= 0; j--) { box = REGION_RECTS(®)[j]; - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + rdpup_send_area(0, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } rdpup_end_update(); RegionUninit(®); @@ -2100,29 +1057,97 @@ rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, RegionRec reg1; RegionRec reg2; DrawablePtr p; + int dirty_type; int j; int num_clips; - - DEBUG_OUT_OPS(("in rdpComposite\n")); + int post_process; + int reset_surface; + int got_id; + int lx; + int ly; + WindowPtr pDstWnd; + PixmapPtr pDstPixmap; + rdpPixmapRec* pDstPriv; + rdpPixmapRec* pDirtyPriv; + struct image_data id; + + LLOGLN(10, ("rdpComposite:")); ps = GetPictureScreen(g_pScreen); ps->Composite = g_rdpScreen.Composite; ps->Composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); + ps->Composite = rdpComposite; + p = pDst->pDrawable; - if (p->type == DRAWABLE_WINDOW) + + dirty_type = 0; + pDirtyPriv = 0; + post_process = 0; + reset_surface = 0; + got_id = 0; + if (p->type == DRAWABLE_PIXMAP) { - if (pDst->clientClipType == CT_REGION) + pDstPixmap = (PixmapPtr)p; + pDstPriv = GETPIXPRIV(pDstPixmap); + if (XRDP_IS_OS(pDstPriv)) + { + post_process = 1; + if (g_do_dirty_os) + { + LLOGLN(10, ("rdpComposite: gettig dirty")); + pDstPriv->is_dirty = 1; + dirty_type = g_doing_font ? RDI_IMGLL : RDI_IMGLY; + pDirtyPriv = pDstPriv; + + } + else + { + rdpup_switch_os_surface(pDstPriv->rdpindex); + reset_surface = 1; + rdpup_get_pixmap_image_rect(pDstPixmap, &id); + got_id = 1; + LLOGLN(10, ("rdpComposite: offscreen")); + } + } + } + else + { + if (p->type == DRAWABLE_WINDOW) + { + pDstWnd = (WindowPtr)p; + if (pDstWnd->viewable) + { + post_process = 1; + rdpup_get_screen_image_rect(&id); + got_id = 1; + LLOGLN(10, ("rdpComposite: screen")); + } + } + } + if (!post_process) + { + return; + } + + if (pDst->clientClipType == CT_REGION) + { + box.x1 = p->x + xDst; + box.y1 = p->y + yDst; + box.x2 = box.x1 + width; + box.y2 = box.y1 + height; + RegionInit(®1, &box, 0); + RegionInit(®2, NullBox, 0); + RegionCopy(®2, pDst->clientClip); + lx = p->x + pDst->clipOrigin.x; + ly = p->y + pDst->clipOrigin.y; + RegionTranslate(®2, lx, ly); + RegionIntersect(®1, ®1, ®2); + if (dirty_type != 0) + { + draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type); + } + else if (got_id) { - box.x1 = p->x + xDst; - box.y1 = p->y + yDst; - box.x2 = box.x1 + width; - box.y2 = box.y1 + height; - RegionInit(®1, &box, 0); - RegionInit(®2, NullBox, 0); - RegionCopy(®2, pDst->clientClip); - RegionTranslate(®2, p->x + pDst->clipOrigin.x, - p->y + pDst->clipOrigin.y); - RegionIntersect(®1, ®1, ®2); num_clips = REGION_NUM_RECTS(®1); if (num_clips > 0) { @@ -2130,23 +1155,65 @@ rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, for (j = num_clips - 1; j >= 0; j--) { box = REGION_RECTS(®1)[j]; - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } rdpup_end_update(); } + } + RegionUninit(®1); + RegionUninit(®2); + } + else + { + box.x1 = p->x + xDst; + box.y1 = p->y + yDst; + box.x2 = box.x1 + width; + box.y2 = box.y1 + height; + if (dirty_type != 0) + { + RegionInit(®1, &box, 0); + draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type); RegionUninit(®1); - RegionUninit(®2); } - else + else if (got_id) { - box.x1 = p->x + xDst; - box.y1 = p->y + yDst; - box.x2 = box.x1 + width; - box.y2 = box.y1 + height; rdpup_begin_update(); - rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_end_update(); } } - ps->Composite = rdpComposite; + if (reset_surface) + { + rdpup_switch_os_surface(-1); + } +} + +/******************************************************************************/ +void +rdpGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, INT16 ySrc, int nlists, GlyphListPtr lists, + GlyphPtr* glyphs) +{ + PictureScreenPtr ps; + int index; + + LLOGLN(10, ("rdpGlyphs:")); + LLOGLN(10, ("rdpGlyphs: nlists %d len %d", nlists, lists->len)); + rdpup_set_hints(1, 1); + g_doing_font = 1; + for (index = 0; index < lists->len; index++) + { + LLOGLN(10, (" index %d size %d refcnt %d width %d height %d", + index, (int)(glyphs[index]->size), (int)(glyphs[index]->refcnt), + glyphs[index]->info.width, glyphs[index]->info.height)); + } + ps = GetPictureScreen(g_pScreen); + ps->Glyphs = g_rdpScreen.Glyphs; + ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, + nlists, lists, glyphs); + ps->Glyphs = rdpGlyphs; + rdpup_set_hints(0, 1); + g_doing_font = 0; + LLOGLN(10, ("rdpGlyphs: out")); } diff --git a/xorg/X11R7.6/rdp/rdpdraw.h b/xorg/X11R7.6/rdp/rdpdraw.h new file mode 100644 index 00000000..38d46ecc --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpdraw.h @@ -0,0 +1,48 @@ +/* +Copyright 2005-2012 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 __RDPDRAW_H +#define __RDPDRAW_H + +/******************************************************************************/ +#define GC_OP_PROLOGUE(_pGC) \ +{ \ + priv = (rdpGCPtr)dixGetPrivateAddr(&(pGC->devPrivates), &g_rdpGCIndex); \ + oldFuncs = _pGC->funcs; \ + (_pGC)->funcs = priv->funcs; \ + (_pGC)->ops = priv->ops; \ +} + +/******************************************************************************/ +#define GC_OP_EPILOGUE(_pGC) \ +{ \ + priv->ops = (_pGC)->ops; \ + (_pGC)->funcs = oldFuncs; \ + (_pGC)->ops = &g_rdpGCOps; \ +} + +int +rdp_get_clip(RegionPtr pRegion, DrawablePtr pDrawable, GCPtr pGC); +void +GetTextBoundingBox(DrawablePtr pDrawable, FontPtr font, int x, int y, + int n, BoxPtr pbox); + +#endif diff --git a/xorg/X11R7.6/rdp/rdpinput.c b/xorg/X11R7.6/rdp/rdpinput.c index 4d11ad11..3ebb9e7a 100644 --- a/xorg/X11R7.6/rdp/rdpinput.c +++ b/xorg/X11R7.6/rdp/rdpinput.c @@ -797,6 +797,25 @@ check_keysa(void) /******************************************************************************/ void +sendDownUpKeyEvent(int type, int x_scancode) +{ + /* if type is keydown, send keydown + keyup */ + /* this allows us to ignore keyup events */ + if (type == KeyPress) + { + rdpEnqueueKey(KeyPress, x_scancode); + rdpEnqueueKey(KeyRelease, x_scancode); + } +} + +/** + * @param down - true for KeyDown events, false otherwise + * @param param1 - ASCII code of pressed key + * @param param2 - + * @param param3 - scancode of pressed key + * @param param4 - + ******************************************************************************/ +void KbdAddEvent(int down, int param1, int param2, int param3, int param4) { int rdp_scancode; @@ -805,63 +824,75 @@ KbdAddEvent(int down, int param1, int param2, int param3, int param4) int is_spe; int type; +#if 0 + fprintf(stderr, "down=0x%x param1=0x%x param2=0x%x param3=0x%x " + "param4=0x%x\n", down, param1, param2, param3, param4); +#endif + type = down ? KeyPress : KeyRelease; rdp_scancode = param3; is_ext = param4 & 256; /* 0x100 */ is_spe = param4 & 512; /* 0x200 */ x_scancode = 0; + switch (rdp_scancode) { + case 58: /* caps lock */ + case 42: /* left shift */ + case 54: /* right shift */ + case 70: /* scroll lock */ + x_scancode = rdp_scancode + MIN_KEY_CODE; + if (x_scancode > 0) + { + rdpEnqueueKey(type, x_scancode); + } + + break; + + case 56: /* left - right alt button */ + if (is_ext) + { + x_scancode = 113; /* right alt button */ + } + else + { + x_scancode = 64; /* left alt button */ + } + + rdpEnqueueKey(type, x_scancode); + break; + case 15: /* tab */ if (!down && !g_tab_down) { - check_keysa(); - /* leave x_scancode 0 here, we don't want the tab key up */ + check_keysa(); /* leave x_scancode 0 here, we don't want the tab key up */ } else { - x_scancode = 23; + sendDownUpKeyEvent(type, 23); } + g_tab_down = down; break; - case 28: /* Enter or Return */ - x_scancode = is_ext ? 108 : 36; - break; + case 29: /* left or right ctrl */ - /* this is to handle special case with pause key sending - control first */ + /* this is to handle special case with pause key sending control first */ if (is_spe) { if (down) { - g_pause_spe = 1; + g_pause_spe = 1; + /* leave x_scancode 0 here, we don't want the control key down */ } - /* leave x_scancode 0 here, we don't want the control key down */ } else { x_scancode = is_ext ? 109 : 37; g_ctrl_down = down ? x_scancode : 0; + rdpEnqueueKey(type, x_scancode); } break; - case 42: /* left shift */ - x_scancode = 50; - g_shift_down = down ? x_scancode : 0; - break; - case 53: /* / */ - x_scancode = is_ext ? 112 : 61; - break; - case 54: /* right shift */ - x_scancode = 62; - g_shift_down = down ? x_scancode : 0; - break; - case 55: /* * on KP or Print Screen */ - x_scancode = is_ext ? 111 : 63; - break; - case 56: /* left or right alt */ - x_scancode = is_ext ? 113 : 64; - g_alt_down = down ? x_scancode : 0; - break; + case 69: /* Pause or Num Lock */ if (g_pause_spe) { @@ -873,63 +904,96 @@ KbdAddEvent(int down, int param1, int param2, int param3, int param4) } else { - x_scancode = g_ctrl_down ? 110 : 77; + x_scancode = g_ctrl_down ? 110 : 77; } + sendDownUpKeyEvent(type, x_scancode); break; - case 70: /* scroll lock */ - x_scancode = 78; - if (!down) - { - g_scroll_lock_down = !g_scroll_lock_down; - } + + case 28: /* Enter or Return */ + x_scancode = is_ext ? 108 : 36; + sendDownUpKeyEvent(type, x_scancode); break; + + case 53: /* / */ + x_scancode = is_ext ? 112 : 61; + sendDownUpKeyEvent(type, x_scancode); + break; + + case 55: /* * on KP or Print Screen */ + x_scancode = is_ext ? 111 : 63; + sendDownUpKeyEvent(type, x_scancode); + break; + case 71: /* 7 or Home */ x_scancode = is_ext ? 97 : 79; + sendDownUpKeyEvent(type, x_scancode); break; + case 72: /* 8 or Up */ x_scancode = is_ext ? 98 : 80; + sendDownUpKeyEvent(type, x_scancode); break; + case 73: /* 9 or PgUp */ x_scancode = is_ext ? 99 : 81; + sendDownUpKeyEvent(type, x_scancode); break; + case 75: /* 4 or Left */ x_scancode = is_ext ? 100 : 83; + sendDownUpKeyEvent(type, x_scancode); break; + case 77: /* 6 or Right */ x_scancode = is_ext ? 102 : 85; + sendDownUpKeyEvent(type, x_scancode); break; + case 79: /* 1 or End */ x_scancode = is_ext ? 103 : 87; + sendDownUpKeyEvent(type, x_scancode); break; + case 80: /* 2 or Down */ x_scancode = is_ext ? 104 : 88; + sendDownUpKeyEvent(type, x_scancode); break; + case 81: /* 3 or PgDn */ x_scancode = is_ext ? 105 : 89; + sendDownUpKeyEvent(type, x_scancode); break; + case 82: /* 0 or Insert */ x_scancode = is_ext ? 106 : 90; + sendDownUpKeyEvent(type, x_scancode); break; + case 83: /* . or Delete */ x_scancode = is_ext ? 107 : 91; + sendDownUpKeyEvent(type, x_scancode); break; + case 91: /* left win key */ - x_scancode = 115; + rdpEnqueueKey(type, 115); break; + case 92: /* right win key */ - x_scancode = 116; + rdpEnqueueKey(type, 116); break; + case 93: /* menu key */ - x_scancode = 117; + rdpEnqueueKey(type, 117); break; + default: x_scancode = rdp_scancode + MIN_KEY_CODE; + if (x_scancode > 0) + { + sendDownUpKeyEvent(type, x_scancode); + } break; } - if (x_scancode > 0) - { - rdpEnqueueKey(type, x_scancode); - } } /******************************************************************************/ diff --git a/xorg/X11R7.6/rdp/rdpmain.c b/xorg/X11R7.6/rdp/rdpmain.c index 8e9117fb..48f5a2e9 100644 --- a/xorg/X11R7.6/rdp/rdpmain.c +++ b/xorg/X11R7.6/rdp/rdpmain.c @@ -42,8 +42,15 @@ DevPrivateKeyRec g_rdpPixmapIndex; DeviceIntPtr g_pointer = 0; DeviceIntPtr g_keyboard = 0; -Bool g_wrapWindow = 0; -Bool g_wrapPixmap = 0; +int g_can_do_pix_to_pix = 1; +int g_do_dirty_os = 1; /* delay remoting off screen bitmaps */ +Bool g_wrapWindow = 1; +Bool g_wrapPixmap = 1; + +/* if true, running in RemoteApp / RAIL mode */ +int g_use_rail = 0; + +WindowPtr g_invalidate_window = 0; /* if true, use a unix domain socket instead of a tcp socket */ int g_use_uds = 0; @@ -347,6 +354,11 @@ rdpScreenInit(int index, ScreenPtr pScreen, int argc, char** argv) /* Window Procedures */ g_rdpScreen.CreateWindow = pScreen->CreateWindow; g_rdpScreen.DestroyWindow = pScreen->DestroyWindow; + g_rdpScreen.ChangeWindowAttributes = pScreen->ChangeWindowAttributes; + g_rdpScreen.RealizeWindow = pScreen->RealizeWindow; + g_rdpScreen.UnrealizeWindow = pScreen->UnrealizeWindow; + g_rdpScreen.PositionWindow = pScreen->PositionWindow; + g_rdpScreen.WindowExposures = pScreen->WindowExposures; g_rdpScreen.CopyWindow = pScreen->CopyWindow; g_rdpScreen.ClearToBackground = pScreen->ClearToBackground; @@ -361,6 +373,8 @@ rdpScreenInit(int index, ScreenPtr pScreen, int argc, char** argv) if (ps) { g_rdpScreen.Composite = ps->Composite; + g_rdpScreen.Glyphs = ps->Glyphs; + } pScreen->blackPixel = g_rdpScreen.blackPixel; pScreen->whitePixel = g_rdpScreen.whitePixel; @@ -370,6 +384,7 @@ rdpScreenInit(int index, ScreenPtr pScreen, int argc, char** argv) if (ps) { ps->Composite = rdpComposite; + ps->Glyphs = rdpGlyphs; } pScreen->SaveScreen = rdpSaveScreen; /* GC procedures */ @@ -387,6 +402,11 @@ rdpScreenInit(int index, ScreenPtr pScreen, int argc, char** argv) /* Window Procedures */ pScreen->CreateWindow = rdpCreateWindow; pScreen->DestroyWindow = rdpDestroyWindow; + pScreen->ChangeWindowAttributes = rdpChangeWindowAttributes; + pScreen->RealizeWindow = rdpRealizeWindow; + pScreen->UnrealizeWindow = rdpUnrealizeWindow; + pScreen->PositionWindow = rdpPositionWindow; + pScreen->WindowExposures = rdpWindowExposures; } pScreen->CopyWindow = rdpCopyWindow; diff --git a/xorg/X11R7.6/rdp/rdpmisc.c b/xorg/X11R7.6/rdp/rdpmisc.c index 5c43654a..d3defe27 100644 --- a/xorg/X11R7.6/rdp/rdpmisc.c +++ b/xorg/X11R7.6/rdp/rdpmisc.c @@ -530,3 +530,43 @@ void FontCacheExtensionInit(INITARGS) { } + +/******************************************************************************/ +void +RegionAroundSegs(RegionPtr reg, xSegment* segs, int nseg) +{ + int index; + BoxRec box; + RegionRec treg; + + index = 0; + while (index < nseg) + { + if (segs[index].x1 < segs[index].x2) + { + box.x1 = segs[index].x1; + box.x2 = segs[index].x2; + } + else + { + box.x1 = segs[index].x2; + box.x2 = segs[index].x1; + } + box.x2++; + if (segs[index].y1 < segs[index].y2) + { + box.y1 = segs[index].y1; + box.y2 = segs[index].y2; + } + else + { + box.y1 = segs[index].y2; + box.y2 = segs[index].y1; + } + box.y2++; + RegionInit(&treg, &box, 0); + RegionUnion(reg, reg, &treg); + RegionUninit(&treg); + index++; + } +} diff --git a/xorg/X11R7.6/rdp/rdprandr.c b/xorg/X11R7.6/rdp/rdprandr.c index 29f1c6e3..ec011e8f 100644 --- a/xorg/X11R7.6/rdp/rdprandr.c +++ b/xorg/X11R7.6/rdp/rdprandr.c @@ -34,6 +34,7 @@ extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ extern DeviceIntPtr g_pointer; /* in rdpmain.c */ extern DeviceIntPtr g_keyboard; /* in rdpmain.c */ extern ScreenPtr g_pScreen; /* in rdpmain.c */ +extern WindowPtr g_invalidate_window; /* in rdpmain.c */ static XID g_wid = 0; @@ -108,8 +109,10 @@ rdpInvalidateArea(ScreenPtr pScreen, int x, int y, int cx, int cy) wVisual(pScreen->root), &result); if (result == 0) { + g_invalidate_window = pWin; MapWindow(pWin, serverClient); DeleteWindow(pWin, None); + g_invalidate_window = pWin; } return 0; } @@ -123,7 +126,7 @@ rdpRRScreenSetSize(ScreenPtr pScreen, CARD16 width, CARD16 height, BoxRec box; ErrorF("rdpRRScreenSetSize: width %d height %d mmWidth %d mmHeight %d\n", - width, height, mmWidth, mmHeight); + width, height, (int)mmWidth, (int)mmHeight); if ((width < 1) || (height < 1)) { diff --git a/xorg/X11R7.6/rdp/rdpup.c b/xorg/X11R7.6/rdp/rdpup.c index 4154ac9c..81165a3a 100644 --- a/xorg/X11R7.6/rdp/rdpup.c +++ b/xorg/X11R7.6/rdp/rdpup.c @@ -20,18 +20,20 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "rdp.h" +#include "xrdp_rail.h" -#if 1 -#define DEBUG_OUT_UP(arg) -#else -#define DEBUG_OUT_UP(arg) ErrorF arg -#endif +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +int g_con_number = 0; /* increments for each connection */ static int g_listen_sck = 0; static int g_sck = 0; static int g_sck_closed = 0; static int g_connected = 0; - static int g_dis_listen_sck = 0; //static int g_dis_sck = 0; //static int g_dis_sck_closed = 0; @@ -46,15 +48,33 @@ static int g_cursor_y = 0; static OsTimerPtr g_timer = 0; static int g_scheduled = 0; static int g_count = 0; +static int g_rdpindex = -1; + extern ScreenPtr g_pScreen; /* from rdpmain.c */ extern int g_Bpp; /* from rdpmain.c */ extern int g_Bpp_mask; /* from rdpmain.c */ extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ +extern int g_use_rail; /* from rdpmain.c */ /* true is to use unix domain socket */ extern int g_use_uds; /* in rdpmain.c */ extern char g_uds_data[]; /* in rdpmain.c */ +struct rdpup_os_bitmap +{ + int used; + PixmapPtr pixmap; + rdpPixmapPtr priv; + int stamp; +}; + +static struct rdpup_os_bitmap* g_os_bitmaps = 0; +static int g_max_os_bitmaps = 0; +static int g_os_bitmap_stamp = 0; + +static int g_pixmap_byte_total = 0; +static int g_pixmap_num_used = 0; + /* 0 GXclear, 0 1 GXnor, DPon @@ -95,13 +115,135 @@ static int g_rdp_opcodes[16] = }; /*****************************************************************************/ +static int +rdpup_disconnect(void) +{ + int index; + + RemoveEnabledDevice(g_sck); + g_connected = 0; + g_tcp_close(g_sck); + g_sck = 0; + g_sck_closed = 1; + g_pixmap_byte_total = 0; + g_pixmap_num_used = 0; + if (g_max_os_bitmaps > 0) + { + for (index = 0; index < g_max_os_bitmaps; index++) + { + if (g_os_bitmaps[index].used) + { + if (g_os_bitmaps[index].priv != 0) + { + g_os_bitmaps[index].priv->status = 0; + } + } + } + } + g_max_os_bitmaps = 0; + g_free(g_os_bitmaps); + g_os_bitmaps = 0; + g_use_rail = 0; + return 0; +} + +/*****************************************************************************/ +int +rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv) +{ + int index; + int rv; + int oldest; + int oldest_index; + + if (!g_connected) + { + return -1; + } + if (g_os_bitmaps == 0) + { + return -1; + } + rv = -1; + index = 0; + while (index < g_max_os_bitmaps) + { + if (g_os_bitmaps[index].used == 0) + { + g_os_bitmaps[index].used = 1; + g_os_bitmaps[index].pixmap = pixmap; + g_os_bitmaps[index].priv = priv; + g_os_bitmaps[index].stamp = g_os_bitmap_stamp; + g_os_bitmap_stamp++; + g_pixmap_num_used++; + rv = index; + break; + } + index++; + } + if (rv == -1) + { + /* find oldest */ + oldest = 0x7fffffff; + oldest_index = 0; + index = 0; + while (index < g_max_os_bitmaps) + { + if (g_os_bitmaps[index].stamp < oldest) + { + oldest = g_os_bitmaps[index].stamp; + oldest_index = index; + } + index++; + } + LLOGLN(10, ("rdpup_add_os_bitmap: evicting old, oldest_index %d", oldest_index)); + /* evict old */ + g_os_bitmaps[oldest_index].priv->status = 0; + /* set new */ + g_os_bitmaps[oldest_index].pixmap = pixmap; + g_os_bitmaps[oldest_index].priv = priv; + g_os_bitmaps[oldest_index].stamp = g_os_bitmap_stamp; + g_os_bitmap_stamp++; + rv = oldest_index; + } + LLOGLN(10, ("rdpup_add_os_bitmap: new bitmap index %d", rv)); + LLOGLN(10, (" g_pixmap_num_used %d", g_pixmap_num_used)); + return rv; +} + +/*****************************************************************************/ +int +rdpup_remove_os_bitmap(int rdpindex) +{ + LLOGLN(10, ("rdpup_remove_os_bitmap: index %d stamp %d", + rdpindex, g_os_bitmaps[rdpindex].stamp)); + if (g_os_bitmaps == 0) + { + return 1; + } + if ((rdpindex < 0) && (rdpindex >= g_max_os_bitmaps)) + { + return 1; + } + if (g_os_bitmaps[rdpindex].used) + { + g_os_bitmaps[rdpindex].used = 0; + g_os_bitmaps[rdpindex].pixmap = 0; + g_os_bitmaps[rdpindex].priv = 0; + g_pixmap_num_used--; + } + LLOGLN(10, (" g_pixmap_num_used %d", g_pixmap_num_used)); + return 0; +} + +/*****************************************************************************/ /* returns error */ static int rdpup_send(char* data, int len) { int sent; - DEBUG_OUT_UP(("rdpup_send - sending %d bytes\n", len)); + LLOGLN(10, ("rdpup_send - sending %d bytes", len)); if (g_sck_closed) { return 1; @@ -117,21 +259,13 @@ rdpup_send(char* data, int len) } else { - RemoveEnabledDevice(g_sck); - g_connected = 0; - g_tcp_close(g_sck); - g_sck = 0; - g_sck_closed = 1; + rdpup_disconnect(); return 1; } } else if (sent == 0) { - RemoveEnabledDevice(g_sck); - g_connected = 0; - g_tcp_close(g_sck); - g_sck = 0; - g_sck_closed = 1; + rdpup_disconnect(); return 1; } else @@ -172,19 +306,28 @@ rdpup_send_msg(struct stream* s) } /******************************************************************************/ -static CARD32 -rdpDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg) +static int +rdpup_send_pending(void) { if (g_connected && g_begin) { - DEBUG_OUT_UP(("end %d\n", g_count)); + LLOGLN(10, ("end %d", g_count)); out_uint16_le(g_out_s, 2); + out_uint16_le(g_out_s, 4); g_count++; s_mark_end(g_out_s); rdpup_send_msg(g_out_s); } g_count = 0; g_begin = 0; + return 0; +} + +/******************************************************************************/ +static CARD32 +rdpDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg) +{ + rdpup_send_pending(); g_scheduled = 0; return 0; } @@ -222,21 +365,13 @@ rdpup_recv(char* data, int len) } else { - RemoveEnabledDevice(g_sck); - g_connected = 0; - g_tcp_close(g_sck); - g_sck = 0; - g_sck_closed = 1; + rdpup_disconnect(); return 1; } } else if (rcvd == 0) { - RemoveEnabledDevice(g_sck); - g_connected = 0; - g_tcp_close(g_sck); - g_sck = 0; - g_sck_closed = 1; + rdpup_disconnect(); return 1; } else @@ -291,8 +426,8 @@ process_screen_size_msg(int width, int height, int bpp) int mmheight; Bool ok; - ErrorF("process_screen_size_msg: set width %d height %d bpp %d\n", - width, height, bpp); + LLOGLN(0, ("process_screen_size_msg: set width %d height %d bpp %d", + width, height, bpp)); g_rdpScreen.rdp_width = width; g_rdpScreen.rdp_height = height; g_rdpScreen.rdp_bpp = bpp; @@ -323,9 +458,9 @@ process_screen_size_msg(int width, int height, int bpp) RRSetCurrentConfig(g_pScreen, RR_Rotate_0, 0, pSize); if ((g_rdpScreen.width != width) || (g_rdpScreen.height != height)) { - ErrorF(" calling RRScreenSizeSet\n"); + LLOGLN(0, (" calling RRScreenSizeSet")); ok = RRScreenSizeSet(g_pScreen, width, height, mmwidth, mmheight); - ErrorF(" RRScreenSizeSet ok=[%d]\n", ok); + LLOGLN(0, (" RRScreenSizeSet ok=[%d]", ok)); } return 0; } @@ -384,7 +519,7 @@ rdpup_send_caps(void) rv = rdpup_send(ls->data, len); if (rv != 0) { - ErrorF("rdpup_send_caps: rdpup_send failed\n"); + LLOGLN(0, ("rdpup_send_caps: rdpup_send failed")); } free_stream(ls); return rv; @@ -394,8 +529,8 @@ rdpup_send_caps(void) static int process_version_msg(int param1, int param2, int param3, int param4) { - ErrorF("process_version_msg: version %d %d %d %d\n", param1, param2, - param3, param4); + LLOGLN(0, ("process_version_msg: version %d %d %d %d", param1, param2, + param3, param4)); if ((param1 > 0) || (param2 > 0) || (param3 > 0) || (param4 > 0)) { rdpup_send_caps(); @@ -414,6 +549,7 @@ rdpup_process_msg(struct stream* s) int param3; int param4; int bytes; + int i1; in_uint16_le(s, msg_type); if (msg_type == 103) @@ -423,8 +559,8 @@ rdpup_process_msg(struct stream* s) in_uint32_le(s, param2); in_uint32_le(s, param3); in_uint32_le(s, param4); - DEBUG_OUT_UP(("rdpup_process_msg - msg %d param1 %d param2 %d param3 %d \ -param4 %d\n", msg, param1, param2, param3, param4)); + LLOGLN(10, ("rdpup_process_msg - msg %d param1 %d param2 %d param3 %d " + "param4 %d", msg, param1, param2, param3, param4)); switch (msg) { case 15: /* key down */ @@ -483,7 +619,7 @@ param4 %d\n", msg, param1, param2, param3, param4)); break; case 200: rdpup_begin_update(); - rdpup_send_area((param1 >> 16) & 0xffff, param1 & 0xffff, + rdpup_send_area(0, (param1 >> 16) & 0xffff, param1 & 0xffff, (param2 >> 16) & 0xffff, param2 & 0xffff); rdpup_end_update(); break; @@ -504,15 +640,28 @@ param4 %d\n", msg, param1, param2, param3, param4)); } memcpy(&(g_rdpScreen.client_info), s->p - 4, bytes); g_rdpScreen.client_info.size = bytes; - ErrorF("rdpup_process_msg: got client info bytes %d\n", bytes); - ErrorF(" jpeg support %d\n", - g_rdpScreen.client_info.jpeg); - ErrorF(" offscreen support %d\n", - g_rdpScreen.client_info.offscreen_support_level); - ErrorF(" offscreen size %d\n", - g_rdpScreen.client_info.offscreen_cache_size); - ErrorF(" offscreen entries %d\n", - g_rdpScreen.client_info.offscreen_cache_entries); + LLOGLN(0, ("rdpup_process_msg: got client info bytes %d", bytes)); + LLOGLN(0, (" jpeg support %d", g_rdpScreen.client_info.jpeg)); + i1 = g_rdpScreen.client_info.offscreen_support_level; + LLOGLN(0, (" offscreen support %d", i1)); + i1 = g_rdpScreen.client_info.offscreen_cache_size; + LLOGLN(0, (" offscreen size %d", i1)); + i1 = g_rdpScreen.client_info.offscreen_cache_entries; + LLOGLN(0, (" offscreen entries %d", i1)); + if (g_rdpScreen.client_info.offscreen_support_level > 0) + { + if (g_rdpScreen.client_info.offscreen_cache_entries > 0) + { + g_max_os_bitmaps = g_rdpScreen.client_info.offscreen_cache_entries; + g_free(g_os_bitmaps); + g_os_bitmaps = (struct rdpup_os_bitmap*) + g_malloc(sizeof(struct rdpup_os_bitmap) * g_max_os_bitmaps, 1); + } + } + if (g_rdpScreen.client_info.rail_support_level > 0) + { + g_use_rail = 1; + } } else { @@ -522,6 +671,30 @@ param4 %d\n", msg, param1, param2, param3, param4)); } /******************************************************************************/ +void +rdpup_get_screen_image_rect(struct image_data* id) +{ + id->width = g_rdpScreen.width; + id->height = g_rdpScreen.height; + id->bpp = g_rdpScreen.rdp_bpp; + id->Bpp = g_rdpScreen.rdp_Bpp; + id->lineBytes = g_rdpScreen.paddedWidthInBytes; + id->pixels = g_rdpScreen.pfbMemory; +} + +/******************************************************************************/ +void +rdpup_get_pixmap_image_rect(PixmapPtr pPixmap, struct image_data* id) +{ + id->width = pPixmap->drawable.width; + id->height = pPixmap->drawable.height; + id->bpp = g_rdpScreen.rdp_bpp; + id->Bpp = g_rdpScreen.rdp_Bpp; + id->lineBytes = pPixmap->devKind; + id->pixels = (char*)(pPixmap->devPrivate.ptr); +} + +/******************************************************************************/ int rdpup_init(void) { @@ -532,7 +705,7 @@ rdpup_init(void) { if (!g_create_dir("/tmp/.xrdp")) { - ErrorF("rdpup_init: g_create_dir failed\n"); + LLOGLN(0, ("rdpup_init: g_create_dir failed")); return 0; } g_chmod_hex("/tmp/.xrdp", 0x1777); @@ -560,7 +733,7 @@ rdpup_init(void) g_listen_sck = g_tcp_local_socket_stream(); if (g_tcp_local_bind(g_listen_sck, g_uds_data) != 0) { - ErrorF("rdpup_init: g_tcp_local_bind failed\n"); + LLOGLN(0, ("rdpup_init: g_tcp_local_bind failed")); return 0; } g_tcp_listen(g_listen_sck); @@ -618,11 +791,7 @@ rdpup_check(void) { /* should maybe ask is user wants to allow here with timeout */ rdpLog("replacing connection, already got a connection\n"); - RemoveEnabledDevice(g_sck); - g_connected = 0; - g_tcp_close(g_sck); - g_sck = 0; - g_sck_closed = 1; + rdpup_disconnect(); } rdpLog("got a connection\n"); g_sck = new_sck; @@ -631,6 +800,7 @@ rdpup_check(void) g_connected = 1; g_sck_closed = 0; g_begin = 0; + g_con_number++; AddEnabledDevice(g_sck); } } @@ -648,11 +818,7 @@ rdpup_check(void) if (g_sck != 0) { rdpLog("disconnecting session via user request\n"); - RemoveEnabledDevice(g_sck); - g_connected = 0; - g_tcp_close(g_sck); - g_sck = 0; - g_sck_closed = 1; + rdpup_disconnect(); } } } @@ -673,7 +839,7 @@ rdpup_begin_update(void) s_push_layer(g_out_s, iso_hdr, 8); out_uint16_le(g_out_s, 1); /* begin update */ out_uint16_le(g_out_s, 4); /* size */ - DEBUG_OUT_UP(("begin %d\n", g_count)); + LLOGLN(10, ("begin %d", g_count)); g_begin = 1; g_count = 1; } @@ -716,7 +882,7 @@ rdpup_fill_rect(short x, short y, int cx, int cy) { if (g_connected) { - DEBUG_OUT_UP((" rdpup_fill_rect\n")); + LLOGLN(10, (" rdpup_fill_rect")); rdpup_pre_check(12); out_uint16_le(g_out_s, 3); /* fill rect */ out_uint16_le(g_out_s, 12); /* size */ @@ -735,7 +901,7 @@ rdpup_screen_blt(short x, short y, int cx, int cy, short srcx, short srcy) { if (g_connected) { - DEBUG_OUT_UP((" rdpup_screen_blt\n")); + LLOGLN(10, (" rdpup_screen_blt")); rdpup_pre_check(16); out_uint16_le(g_out_s, 4); /* screen blt */ out_uint16_le(g_out_s, 16); /* size */ @@ -756,7 +922,7 @@ rdpup_set_clip(short x, short y, int cx, int cy) { if (g_connected) { - DEBUG_OUT_UP((" rdpup_set_clip\n")); + LLOGLN(10, (" rdpup_set_clip")); rdpup_pre_check(12); out_uint16_le(g_out_s, 10); /* set clip */ out_uint16_le(g_out_s, 12); /* size */ @@ -775,7 +941,7 @@ rdpup_reset_clip(void) { if (g_connected) { - DEBUG_OUT_UP((" rdpup_reset_clip\n")); + LLOGLN(10, (" rdpup_reset_clip")); rdpup_pre_check(4); out_uint16_le(g_out_s, 11); /* reset clip */ out_uint16_le(g_out_s, 4); /* size */ @@ -923,7 +1089,7 @@ rdpup_set_fgcolor(int fgcolor) { if (g_connected) { - DEBUG_OUT_UP((" rdpup_set_fgcolor\n")); + LLOGLN(10, (" rdpup_set_fgcolor")); rdpup_pre_check(8); out_uint16_le(g_out_s, 12); /* set fgcolor */ out_uint16_le(g_out_s, 8); /* size */ @@ -941,7 +1107,7 @@ rdpup_set_bgcolor(int bgcolor) { if (g_connected) { - DEBUG_OUT_UP((" rdpup_set_bgcolor\n")); + LLOGLN(10, (" rdpup_set_bgcolor")); rdpup_pre_check(8); out_uint16_le(g_out_s, 13); /* set bg color */ out_uint16_le(g_out_s, 8); /* size */ @@ -959,7 +1125,7 @@ rdpup_set_opcode(int opcode) { if (g_connected) { - DEBUG_OUT_UP((" rdpup_set_opcode\n")); + LLOGLN(10, (" rdpup_set_opcode")); rdpup_pre_check(6); out_uint16_le(g_out_s, 14); /* set opcode */ out_uint16_le(g_out_s, 6); /* size */ @@ -975,7 +1141,7 @@ rdpup_set_pen(int style, int width) { if (g_connected) { - DEBUG_OUT_UP((" rdpup_set_pen\n")); + LLOGLN(10, (" rdpup_set_pen")); rdpup_pre_check(8); out_uint16_le(g_out_s, 17); /* set pen */ out_uint16_le(g_out_s, 8); /* size */ @@ -992,7 +1158,7 @@ rdpup_draw_line(short x1, short y1, short x2, short y2) { if (g_connected) { - DEBUG_OUT_UP((" rdpup_draw_line\n")); + LLOGLN(10, (" rdpup_draw_line")); rdpup_pre_check(12); out_uint16_le(g_out_s, 18); /* draw line */ out_uint16_le(g_out_s, 12); /* size */ @@ -1013,7 +1179,7 @@ rdpup_set_cursor(short x, short y, char* cur_data, char* cur_mask) if (g_connected) { - DEBUG_OUT_UP((" rdpup_set_cursor\n")); + LLOGLN(10, (" rdpup_set_cursor")); size = 8 + 32 * (32 * 3) + 32 * (32 / 8); rdpup_pre_check(size); out_uint16_le(g_out_s, 19); /* set cursor */ @@ -1032,8 +1198,67 @@ rdpup_set_cursor(short x, short y, char* cur_data, char* cur_mask) } /******************************************************************************/ +int +rdpup_create_os_surface(int rdpindex, int width, int height) +{ + LLOGLN(10, ("rdpup_create_os_surface:")); + if (g_connected) + { + LLOGLN(10, (" rdpup_create_os_surface width %d height %d", width, height)); + rdpup_pre_check(12); + out_uint16_le(g_out_s, 20); + out_uint16_le(g_out_s, 12); + g_count++; + out_uint32_le(g_out_s, rdpindex); + out_uint16_le(g_out_s, width); + out_uint16_le(g_out_s, height); + } + return 0; +} + +/******************************************************************************/ +int +rdpup_switch_os_surface(int rdpindex) +{ + LLOGLN(10, ("rdpup_switch_os_surface:")); + if (g_connected) + { + if (g_rdpindex == rdpindex) + { + return 0; + } + g_rdpindex = rdpindex; + LLOGLN(10, ("rdpup_switch_os_surface: rdpindex %d", rdpindex)); + /* switch surface */ + rdpup_pre_check(8); + out_uint16_le(g_out_s, 21); + out_uint16_le(g_out_s, 8); + out_uint32_le(g_out_s, rdpindex); + g_count++; + } + return 0; +} + +/******************************************************************************/ +int +rdpup_delete_os_surface(int rdpindex) +{ + LLOGLN(10, ("rdpup_delete_os_surface: rdpindex %d", rdpindex)); + if (g_connected) + { + LLOGLN(10, ("rdpup_delete_os_surface: rdpindex %d", rdpindex)); + rdpup_pre_check(8); + out_uint16_le(g_out_s, 22); + out_uint16_le(g_out_s, 8); + g_count++; + out_uint32_le(g_out_s, rdpindex); + } + return 0; +} + +/******************************************************************************/ static int -get_single_color(int x, int y, int w, int h) +get_single_color(struct image_data* id, int x, int y, int w, int h) { int rv; int i; @@ -1049,8 +1274,8 @@ get_single_color(int x, int y, int w, int h) { for (i = 0; i < h; i++) { - i8 = (unsigned char*)(g_rdpScreen.pfbMemory + - ((y + i) * g_rdpScreen.paddedWidthInBytes) + (x * g_Bpp)); + i8 = (unsigned char*)(id->pixels + + ((y + i) * id->lineBytes) + (x * g_Bpp)); if (i == 0) { p = *i8; @@ -1069,8 +1294,8 @@ get_single_color(int x, int y, int w, int h) { for (i = 0; i < h; i++) { - i16 = (unsigned short*)(g_rdpScreen.pfbMemory + - ((y + i) * g_rdpScreen.paddedWidthInBytes) + (x * g_Bpp)); + i16 = (unsigned short*)(id->pixels + + ((y + i) * id->lineBytes) + (x * g_Bpp)); if (i == 0) { p = *i16; @@ -1089,8 +1314,8 @@ get_single_color(int x, int y, int w, int h) { for (i = 0; i < h; i++) { - i32 = (unsigned int*)(g_rdpScreen.pfbMemory + - ((y + i) * g_rdpScreen.paddedWidthInBytes) + (x * g_Bpp)); + i32 = (unsigned int*)(id->pixels + + ((y + i) * id->lineBytes) + (x * g_Bpp)); if (i == 0) { p = *i32; @@ -1111,7 +1336,7 @@ get_single_color(int x, int y, int w, int h) /******************************************************************************/ /* split the bitmap up into 64 x 64 pixel areas */ void -rdpup_send_area(int x, int y, int w, int h) +rdpup_send_area(struct image_data* id, int x, int y, int w, int h) { char* s; int i; @@ -1121,12 +1346,20 @@ rdpup_send_area(int x, int y, int w, int h) int lh; int lw; int size; + struct image_data lid; + + LLOGLN(10, ("rdpup_send_area: id %p x %d y %d w %d h %d", id, x, y, w, h)); + if (id == 0) + { + rdpup_get_screen_image_rect(&lid); + id = &lid; + } - if (x >= g_rdpScreen.width) + if (x >= id->width) { return; } - if (y >= g_rdpScreen.height) + if (y >= id->height) { return; } @@ -1148,18 +1381,18 @@ rdpup_send_area(int x, int y, int w, int h) { return; } - if (x + w > g_rdpScreen.width) + if (x + w > id->width) { - w = g_rdpScreen.width - x; + w = id->width - x; } - if (y + h > g_rdpScreen.height) + if (y + h > id->height) { - h = g_rdpScreen.height - y; + h = id->height - y; } - DEBUG_OUT_UP(("%d\n", w * h)); + LLOGLN(10, ("%d", w * h)); if (g_connected && g_begin) { - DEBUG_OUT_UP((" rdpup_send_area\n")); + LLOGLN(10, (" rdpup_send_area")); ly = y; while (ly < y + h) { @@ -1168,16 +1401,16 @@ rdpup_send_area(int x, int y, int w, int h) { lw = MIN(64, (x + w) - lx); lh = MIN(64, (y + h) - ly); - single_color = get_single_color(lx, ly, lw, lh); + single_color = get_single_color(id, lx, ly, lw, lh); if (single_color != -1) { - DEBUG_OUT_UP(("%d sending single color\n", g_count)); + LLOGLN(10, ("%d sending single color", g_count)); rdpup_set_fgcolor(single_color); rdpup_fill_rect(lx, ly, lw, lh); } else { - size = lw * lh * g_rdpScreen.rdp_Bpp + 24; + size = lw * lh * id->Bpp + 24; rdpup_pre_check(size); out_uint16_le(g_out_s, 5); out_uint16_le(g_out_s, size); @@ -1186,13 +1419,13 @@ rdpup_send_area(int x, int y, int w, int h) out_uint16_le(g_out_s, ly); out_uint16_le(g_out_s, lw); out_uint16_le(g_out_s, lh); - out_uint32_le(g_out_s, lw * lh * g_rdpScreen.rdp_Bpp); + out_uint32_le(g_out_s, lw * lh * id->Bpp); for (i = 0; i < lh; i++) { - s = (g_rdpScreen.pfbMemory + - ((ly + i) * g_rdpScreen.paddedWidthInBytes) + (lx * g_Bpp)); + s = (id->pixels + + ((ly + i) * id->lineBytes) + (lx * g_Bpp)); convert_pixels(s, g_out_s->p, lw); - g_out_s->p += lw * g_rdpScreen.rdp_Bpp; + g_out_s->p += lw * id->Bpp; } out_uint16_le(g_out_s, lw); out_uint16_le(g_out_s, lh); @@ -1205,3 +1438,268 @@ rdpup_send_area(int x, int y, int w, int h) } } } + +/******************************************************************************/ +void +rdpup_paint_rect_os(int x, int y, int cx, int cy, + int rdpindex, int srcx, int srcy) +{ + if (g_connected) + { + rdpup_pre_check(20); + out_uint16_le(g_out_s, 23); + out_uint16_le(g_out_s, 20); + g_count++; + out_uint16_le(g_out_s, x); + out_uint16_le(g_out_s, y); + out_uint16_le(g_out_s, cx); + out_uint16_le(g_out_s, cy); + out_uint32_le(g_out_s, rdpindex); + out_uint16_le(g_out_s, srcx); + out_uint16_le(g_out_s, srcy); + } +} + +/******************************************************************************/ +void +rdpup_set_hints(int hints, int mask) +{ + if (g_connected) + { + rdpup_pre_check(12); + out_uint16_le(g_out_s, 24); + out_uint16_le(g_out_s, 12); + g_count++; + out_uint32_le(g_out_s, hints); + out_uint32_le(g_out_s, mask); + } +} + +/******************************************************************************/ +void +rdpup_create_window(WindowPtr pWindow, rdpWindowRec* priv) +{ + int bytes; + int index; + int flags; + int num_window_rects; + int num_visibility_rects; + int title_bytes; + int style; + int ext_style; + int root_id; + char title[256]; + + LLOGLN(10, ("rdpup_create_window: id 0x%8.8x", pWindow->drawable.id)); + if (g_connected) + { + root_id = pWindow->drawable.pScreen->root->drawable.id; + + if (pWindow->overrideRedirect) + { + style = XR_STYLE_TOOLTIP; + ext_style = XR_EXT_STYLE_TOOLTIP; + } + else + { + style = XR_STYLE_NORMAL; + ext_style = XR_EXT_STYLE_NORMAL; + } + + flags = WINDOW_ORDER_TYPE_WINDOW | WINDOW_ORDER_STATE_NEW; + strcpy(title, "title"); + title_bytes = strlen(title); + + num_window_rects = 1; + num_visibility_rects = 1; + + /* calculate bytes */ + bytes = (2 + 2) + (5 * 4) + (2 + title_bytes) + (12 * 4) + + (2 + num_window_rects * 8) + (4 + 4) + + (2 + num_visibility_rects * 8) + 4; + + rdpup_pre_check(bytes); + out_uint16_le(g_out_s, 25); + out_uint16_le(g_out_s, bytes); + g_count++; + out_uint32_le(g_out_s, pWindow->drawable.id); /* window_id */ + out_uint32_le(g_out_s, pWindow->parent->drawable.id); /* owner_window_id */ + flags |= WINDOW_ORDER_FIELD_OWNER; + out_uint32_le(g_out_s, style); /* style */ + out_uint32_le(g_out_s, ext_style); /* extended_style */ + flags |= WINDOW_ORDER_FIELD_STYLE; + out_uint32_le(g_out_s, 0); /* show_state */ + flags |= WINDOW_ORDER_FIELD_SHOW; + out_uint16_le(g_out_s, title_bytes); /* title_info */ + out_uint8a(g_out_s, title, title_bytes); + flags |= WINDOW_ORDER_FIELD_TITLE; + out_uint32_le(g_out_s, 0); /* client_offset_x */ + out_uint32_le(g_out_s, 0); /* client_offset_y */ + flags |= WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET; + out_uint32_le(g_out_s, pWindow->drawable.width); /* client_area_width */ + out_uint32_le(g_out_s, pWindow->drawable.height); /* client_area_height */ + flags |= WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE; + out_uint32_le(g_out_s, 0); /* rp_content */ + out_uint32_le(g_out_s, root_id); /* root_parent_handle */ + flags |= WINDOW_ORDER_FIELD_ROOT_PARENT; + out_uint32_le(g_out_s, pWindow->drawable.x); /* window_offset_x */ + out_uint32_le(g_out_s, pWindow->drawable.y); /* window_offset_y */ + flags |= WINDOW_ORDER_FIELD_WND_OFFSET; + out_uint32_le(g_out_s, 0); /* window_client_delta_x */ + out_uint32_le(g_out_s, 0); /* window_client_delta_y */ + flags |= WINDOW_ORDER_FIELD_WND_CLIENT_DELTA; + out_uint32_le(g_out_s, pWindow->drawable.width); /* window_width */ + out_uint32_le(g_out_s, pWindow->drawable.height); /* window_height */ + flags |= WINDOW_ORDER_FIELD_WND_SIZE; + out_uint16_le(g_out_s, num_window_rects); /* num_window_rects */ + for (index = 0; index < num_window_rects; index++) + { + out_uint16_le(g_out_s, 0); /* left */ + out_uint16_le(g_out_s, 0); /* top */ + out_uint16_le(g_out_s, pWindow->drawable.width); /* right */ + out_uint16_le(g_out_s, pWindow->drawable.height); /* bottom */ + } + flags |= WINDOW_ORDER_FIELD_WND_RECTS; + out_uint32_le(g_out_s, 0); /* visible_offset_x */ + out_uint32_le(g_out_s, 0); /* visible_offset_y */ + flags |= WINDOW_ORDER_FIELD_VIS_OFFSET; + out_uint16_le(g_out_s, num_visibility_rects); /* num_visibility_rects */ + for (index = 0; index < num_visibility_rects; index++) + { + out_uint16_le(g_out_s, 0); /* left */ + out_uint16_le(g_out_s, 0); /* top */ + out_uint16_le(g_out_s, pWindow->drawable.width); /* right */ + out_uint16_le(g_out_s, pWindow->drawable.height); /* bottom */ + } + flags |= WINDOW_ORDER_FIELD_VISIBILITY; + + out_uint32_le(g_out_s, flags); /* flags */ + } +} + +/******************************************************************************/ +void +rdpup_delete_window(WindowPtr pWindow, rdpWindowRec* priv) +{ + LLOGLN(10, ("rdpup_delete_window: id 0x%8.8x", pWindow->drawable.id)); + if (g_connected) + { + rdpup_pre_check(8); + out_uint16_le(g_out_s, 26); + out_uint16_le(g_out_s, 8); + g_count++; + out_uint32_le(g_out_s, pWindow->drawable.id); /* window_id */ + } +} + +/******************************************************************************/ +int +rdpup_check_dirty(PixmapPtr pDirtyPixmap, rdpPixmapRec* pDirtyPriv) +{ + int index; + int clip_index; + int count; + int num_clips; + BoxRec box; + xSegment* seg; + struct image_data id; + struct rdp_draw_item* di; + + if (pDirtyPriv == 0) + { + return 0; + } + if (pDirtyPriv->is_dirty == 0) + { + return 0; + } + + /* update use time / count */ + g_os_bitmaps[pDirtyPriv->rdpindex].stamp = g_os_bitmap_stamp; + g_os_bitmap_stamp++; + + LLOGLN(10, ("-----------------got dirty")); + rdpup_switch_os_surface(pDirtyPriv->rdpindex); + rdpup_get_pixmap_image_rect(pDirtyPixmap, &id); + rdpup_begin_update(); + draw_item_pack(pDirtyPriv); + di = pDirtyPriv->draw_item_head; + while (di != 0) + { + LLOGLN(10, ("rdpup_check_dirty: type %d", di->type)); + switch (di->type) + { + case RDI_FILL: + rdpup_set_fgcolor(di->u.fill.fg_color); + rdpup_set_opcode(di->u.fill.opcode); + count = REGION_NUM_RECTS(di->reg); + for (index = 0; index < count; index++) + { + box = REGION_RECTS(di->reg)[index]; + LLOGLN(10, (" RDI_FILL %d %d %d %d", box.x1, box.y1, + box.x2, box.y2)); + rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + } + rdpup_set_opcode(GXcopy); + break; + case RDI_IMGLL: + rdpup_set_hints(1, 1); + rdpup_set_opcode(di->u.img.opcode); + count = REGION_NUM_RECTS(di->reg); + for (index = 0; index < count; index++) + { + box = REGION_RECTS(di->reg)[index]; + LLOGLN(10, (" RDI_IMGLL %d %d %d %d", box.x1, box.y1, + box.x2, box.y2)); + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, + box.y2 - box.y1); + } + rdpup_set_opcode(GXcopy); + rdpup_set_hints(0, 1); + break; + case RDI_IMGLY: + rdpup_set_opcode(di->u.img.opcode); + count = REGION_NUM_RECTS(di->reg); + for (index = 0; index < count; index++) + { + box = REGION_RECTS(di->reg)[index]; + LLOGLN(10, (" RDI_IMGLY %d %d %d %d", box.x1, box.y1, + box.x2, box.y2)); + rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, + box.y2 - box.y1); + } + rdpup_set_opcode(GXcopy); + break; + case RDI_LINE: + LLOGLN(10, (" RDI_LINE")); + num_clips = REGION_NUM_RECTS(di->reg); + if (num_clips > 0) + { + rdpup_set_fgcolor(di->u.line.fg_color); + rdpup_set_opcode(di->u.line.opcode); + rdpup_set_pen(0, di->u.line.width); + for (clip_index = num_clips - 1; clip_index >= 0; clip_index--) + { + box = REGION_RECTS(di->reg)[clip_index]; + rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + for (index = 0; index < di->u.line.nseg; index++) + { + seg = di->u.line.segs + index; + LLOGLN(10, (" RDI_LINE %d %d %d %d", seg->x1, seg->y1, + seg->x2, seg->y2)); + rdpup_draw_line(seg->x1, seg->y1, seg->x2, seg->y2); + } + } + } + rdpup_reset_clip(); + rdpup_set_opcode(GXcopy); + break; + } + di = di->next; + } + draw_item_remove_all(pDirtyPriv); + rdpup_end_update(); + pDirtyPriv->is_dirty = 0; + rdpup_switch_os_surface(-1); + return 0; +} diff --git a/xorg/X11R7.6/x11_file_list.txt b/xorg/X11R7.6/x11_file_list.txt index bb518d3d..cf08c62c 100644 --- a/xorg/X11R7.6/x11_file_list.txt +++ b/xorg/X11R7.6/x11_file_list.txt @@ -1,41 +1,5 @@ Python-2.7.tar.bz2 : Python-2.7 : util-macros-1.11.0.tar.bz2 : util-macros-1.11.0 : -font-adobe-75dpi-1.0.3.tar.bz2 : font-adobe-75dpi-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-adobe-100dpi-1.0.3.tar.bz2 : font-adobe-100dpi-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-adobe-utopia-75dpi-1.0.4.tar.bz2 : font-adobe-utopia-75dpi-1.0.4 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-adobe-utopia-100dpi-1.0.4.tar.bz2 : font-adobe-utopia-100dpi-1.0.4 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-adobe-utopia-type1-1.0.4.tar.bz2 : font-adobe-utopia-type1-1.0.4 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-alias-1.0.3.tar.bz2 : font-alias-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-arabic-misc-1.0.3.tar.bz2 : font-arabic-misc-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-bh-75dpi-1.0.3.tar.bz2 : font-bh-75dpi-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-bh-100dpi-1.0.3.tar.bz2 : font-bh-100dpi-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-bh-lucidatypewriter-75dpi-1.0.3.tar.bz2 : font-bh-lucidatypewriter-75dpi-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-bh-lucidatypewriter-100dpi-1.0.3.tar.bz2 : font-bh-lucidatypewriter-100dpi-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-bh-ttf-1.0.3.tar.bz2 : font-bh-ttf-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-bh-type1-1.0.3.tar.bz2 : font-bh-type1-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-bitstream-75dpi-1.0.3.tar.bz2 : font-bitstream-75dpi-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-bitstream-100dpi-1.0.3.tar.bz2 : font-bitstream-100dpi-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-bitstream-type1-1.0.3.tar.bz2 : font-bitstream-type1-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-cronyx-cyrillic-1.0.3.tar.bz2 : font-cronyx-cyrillic-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-cursor-misc-1.0.3.tar.bz2 : font-cursor-misc-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-daewoo-misc-1.0.3.tar.bz2 : font-daewoo-misc-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-dec-misc-1.0.3.tar.bz2 : font-dec-misc-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-ibm-type1-1.0.3.tar.bz2 : font-ibm-type1-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-isas-misc-1.0.3.tar.bz2 : font-isas-misc-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-jis-misc-1.0.3.tar.bz2 : font-jis-misc-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-micro-misc-1.0.3.tar.bz2 : font-micro-misc-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-misc-cyrillic-1.0.3.tar.bz2 : font-misc-cyrillic-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-misc-ethiopic-1.0.3.tar.bz2 : font-misc-ethiopic-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-misc-meltho-1.0.3.tar.bz2 : font-misc-meltho-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-misc-misc-1.1.2.tar.bz2 : font-misc-misc-1.1.2 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-mutt-misc-1.0.3.tar.bz2 : font-mutt-misc-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-schumacher-misc-1.1.2.tar.bz2 : font-schumacher-misc-1.1.2 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-screen-cyrillic-1.0.4.tar.bz2 : font-screen-cyrillic-1.0.4 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-sony-misc-1.0.3.tar.bz2 : font-sony-misc-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-sun-misc-1.0.3.tar.bz2 : font-sun-misc-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-util-1.2.0.tar.bz2 : font-util-1.2.0 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-winitzki-cyrillic-1.0.3.tar.bz2 : font-winitzki-cyrillic-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 -font-xfree86-type1-1.0.4.tar.bz2 : font-xfree86-type1-1.0.4 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 xf86driproto-2.1.0.tar.bz2 : xf86driproto-2.1.0 : dri2proto-2.3.tar.bz2 : dri2proto-2.3 : glproto-1.4.12.tar.bz2 : glproto-1.4.12 : @@ -43,7 +7,6 @@ libpciaccess-0.12.0.tar.bz2 : libpciaccess-0.12.0 libpthread-stubs-0.3.tar.bz2 : libpthread-stubs-0.3 : libdrm-2.4.26.tar.bz2 : libdrm-2.4.26 : damageproto-1.2.1.tar.bz2 : damageproto-1.2.1 : -libXdamage-1.1.3.tar.bz2 : libXdamage-1.1.3 : makedepend-1.0.3.tar.bz2 : makedepend-1.0.3 : libxml2-sources-2.7.8.tar.gz : libxml2-2.7.8 : libpng-1.2.46.tar.gz : libpng-1.2.46 : @@ -62,6 +25,8 @@ libXext-1.2.0.tar.bz2 : libXext-1.2.0 libICE-1.0.7.tar.bz2 : libICE-1.0.7 : libSM-1.2.0.tar.bz2 : libSM-1.2.0 : libXt-1.0.9.tar.bz2 : libXt-1.0.9 : +libXdamage-1.1.3.tar.bz2 : libXdamage-1.1.3 : +libXfixes-4.0.5.tar.bz2 : libXfixes-4.0.5 : MesaLib-7.10.3.tar.bz2 : Mesa-7.10.3 : --with-expat=$PREFIX_DIR --disable-gallium randrproto-1.3.2.tar.bz2 : randrproto-1.3.2 : renderproto-0.11.1.tar.bz2 : renderproto-0.11.1 : @@ -91,9 +56,46 @@ libXxf86vm-1.1.1.tar.bz2 : libXxf86vm-1.1.1 libXpm-3.5.9.tar.bz2 : libXpm-3.5.9 : libXaw-1.0.8.tar.bz2 : libXaw-1.0.8 : mkfontdir-1.0.6.tar.bz2 : mkfontdir-1.0.6 : +mkfontscale-1.0.8.tar.bz2 : mkfontscale-1.0.8 : xkbcomp-1.2.0.tar.bz2 : xkbcomp-1.2.0 : xorg-server-1.9.3.tar.bz2 : xorg-server-1.9.3 : --with-sha1=libcrypto applewmproto-1.4.1.tar.bz2 : applewmproto-1.4.1 : bdftopcf-1.0.3.tar.bz2 : bdftopcf-1.0.3 : intltool-0.41.1.tar.gz : intltool-0.41.1 : xkeyboard-config-2.0.tar.bz2 : xkeyboard-config-2.0 : +font-adobe-75dpi-1.0.3.tar.bz2 : font-adobe-75dpi-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-adobe-100dpi-1.0.3.tar.bz2 : font-adobe-100dpi-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-adobe-utopia-75dpi-1.0.4.tar.bz2 : font-adobe-utopia-75dpi-1.0.4 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-adobe-utopia-100dpi-1.0.4.tar.bz2 : font-adobe-utopia-100dpi-1.0.4 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-adobe-utopia-type1-1.0.4.tar.bz2 : font-adobe-utopia-type1-1.0.4 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-alias-1.0.3.tar.bz2 : font-alias-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-arabic-misc-1.0.3.tar.bz2 : font-arabic-misc-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-bh-75dpi-1.0.3.tar.bz2 : font-bh-75dpi-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-bh-100dpi-1.0.3.tar.bz2 : font-bh-100dpi-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-bh-lucidatypewriter-75dpi-1.0.3.tar.bz2 : font-bh-lucidatypewriter-75dpi-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-bh-lucidatypewriter-100dpi-1.0.3.tar.bz2 : font-bh-lucidatypewriter-100dpi-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-bh-ttf-1.0.3.tar.bz2 : font-bh-ttf-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-bh-type1-1.0.3.tar.bz2 : font-bh-type1-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-bitstream-75dpi-1.0.3.tar.bz2 : font-bitstream-75dpi-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-bitstream-100dpi-1.0.3.tar.bz2 : font-bitstream-100dpi-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-bitstream-type1-1.0.3.tar.bz2 : font-bitstream-type1-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-cronyx-cyrillic-1.0.3.tar.bz2 : font-cronyx-cyrillic-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-cursor-misc-1.0.3.tar.bz2 : font-cursor-misc-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-daewoo-misc-1.0.3.tar.bz2 : font-daewoo-misc-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-dec-misc-1.0.3.tar.bz2 : font-dec-misc-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-ibm-type1-1.0.3.tar.bz2 : font-ibm-type1-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-isas-misc-1.0.3.tar.bz2 : font-isas-misc-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-jis-misc-1.0.3.tar.bz2 : font-jis-misc-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-micro-misc-1.0.3.tar.bz2 : font-micro-misc-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-misc-cyrillic-1.0.3.tar.bz2 : font-misc-cyrillic-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-misc-ethiopic-1.0.3.tar.bz2 : font-misc-ethiopic-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-misc-meltho-1.0.3.tar.bz2 : font-misc-meltho-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-misc-misc-1.1.2.tar.bz2 : font-misc-misc-1.1.2 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-mutt-misc-1.0.3.tar.bz2 : font-mutt-misc-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-schumacher-misc-1.1.2.tar.bz2 : font-schumacher-misc-1.1.2 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-screen-cyrillic-1.0.4.tar.bz2 : font-screen-cyrillic-1.0.4 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-sony-misc-1.0.3.tar.bz2 : font-sony-misc-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-sun-misc-1.0.3.tar.bz2 : font-sun-misc-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-util-1.2.0.tar.bz2 : font-util-1.2.0 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-winitzki-cyrillic-1.0.3.tar.bz2 : font-winitzki-cyrillic-1.0.3 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 +font-xfree86-type1-1.0.4.tar.bz2 : font-xfree86-type1-1.0.4 : --with-fontrootdir=$PREFIX_DIR/share/fonts/X11 diff --git a/xrdp/lang.c b/xrdp/lang.c index 6bcf7ebe..1c13839f 100644 --- a/xrdp/lang.c +++ b/xrdp/lang.c @@ -22,6 +22,7 @@ */ #include "xrdp.h" +#include "log.h" /* map for rdp to x11 scancodes code1 is regular scancode, code2 is extended scancode */ @@ -232,13 +233,18 @@ get_keymaps(int keylayout, struct xrdp_keymap* keymap) km_read_section(fd, "shiftcapslock", keymap->keys_shiftcapslock); if (g_memcmp(lkeymap, keymap, sizeof(struct xrdp_keymap)) != 0) { - g_writeln("local keymap file for 0x%4.4x found and dosen't match " + log_message(LOG_LEVEL_WARNING, + "local keymap file for 0x%4.4x found and dosen't match " "built in keymap, using local keymap file", keylayout); } g_free(lkeymap); g_file_close(fd); } } + else + { + log_message(LOG_LEVEL_WARNING,"File does not exist: %s",filename); + } g_free(filename); return 0; } diff --git a/xrdp/xrdp.c b/xrdp/xrdp.c index fb8dfbc0..4af8c4d7 100644 --- a/xrdp/xrdp.c +++ b/xrdp/xrdp.c @@ -21,6 +21,9 @@ */ #include "xrdp.h" +#include "log.h" + +#define THREAD_WAITING 100 static struct xrdp_listen* g_listen = 0; static long g_threadid = 0; /* main threadid */ @@ -37,6 +40,9 @@ static long g_sync_param2 = 0; static long (*g_sync_func)(long param1, long param2); /*****************************************************************************/ +/* This function is used to run a function from the main thread. + Sync_func is the function pointer that will run from main thread + The function can have two long in parameters and must return long */ long APP_CC g_xrdp_sync(long (*sync_func)(long param1, long param2), long sync_param1, long sync_param2) @@ -44,31 +50,46 @@ g_xrdp_sync(long (*sync_func)(long param1, long param2), long sync_param1, long sync_result; int sync_command; + /* If the function is called from the main thread, the function can + * be called directly. g_threadid= main thread ID*/ if (tc_threadid_equal(tc_get_threadid(), g_threadid)) { /* this is the main thread, call the function directly */ + /* in fork mode, this always happens too */ sync_result = sync_func(sync_param1, sync_param2); + /*g_writeln("g_xrdp_sync processed IN main thread -> continue");*/ } else { + /* All threads have to wait here until the main thread + * process the function. g_process_waiting_function() is called + * from the listening thread. g_process_waiting_function() process the function*/ tc_mutex_lock(g_sync1_mutex); tc_mutex_lock(g_sync_mutex); g_sync_param1 = sync_param1; g_sync_param2 = sync_param2; g_sync_func = sync_func; - g_sync_command = 100; + /* set a value THREAD_WAITING so the g_process_waiting_function function + * know if any function must be processed */ + g_sync_command = THREAD_WAITING; tc_mutex_unlock(g_sync_mutex); + /* set this event so that the main thread know if + * g_process_waiting_function() must be called */ g_set_wait_obj(g_sync_event); do { g_sleep(100); tc_mutex_lock(g_sync_mutex); + /* load new value from global to see if the g_process_waiting_function() + * function has processed the function */ sync_command = g_sync_command; sync_result = g_sync_result; tc_mutex_unlock(g_sync_mutex); } - while (sync_command != 0); + while (sync_command != 0); /* loop until g_process_waiting_function() + * has processed the request */ tc_mutex_unlock(g_sync1_mutex); + /*g_writeln("g_xrdp_sync processed BY main thread -> continue");*/ } return sync_result; } @@ -89,6 +110,32 @@ xrdp_shutdown(int sig) } /*****************************************************************************/ +void DEFAULT_CC +xrdp_child(int sig) +{ + g_waitchild(); +} + +/*****************************************************************************/ +/* called in child just after fork */ +int APP_CC +xrdp_child_fork(void) +{ + int pid; + char text[256]; + + /* close, don't delete these */ + g_close_wait_obj(g_term_event); + g_close_wait_obj(g_sync_event); + pid = g_getpid(); + g_snprintf(text, 255, "xrdp_%8.8x_main_term", pid); + g_term_event = g_create_wait_obj(text); + g_snprintf(text, 255, "xrdp_%8.8x_main_sync", pid); + g_sync_event = g_create_wait_obj(text); + return 0; +} + +/*****************************************************************************/ int APP_CC g_is_term(void) { @@ -132,15 +179,17 @@ pipe_sig(int sig_num) } /*****************************************************************************/ +/*Some function must be called from the main thread. + if g_sync_command==THREAD_WAITING a function is waiting to be processed*/ void APP_CC -g_loop(void) +g_process_waiting_function(void) { tc_mutex_lock(g_sync_mutex); if (g_sync_command != 0) { if (g_sync_func != 0) { - if (g_sync_command == 100) + if (g_sync_command == THREAD_WAITING) { g_sync_result = g_sync_func(g_sync_param1, g_sync_param2); } @@ -213,6 +262,12 @@ xrdp_process_params(int argc, char** argv, startup_params->port); } } + else if ((g_strncasecmp(option, "-f", 255) == 0) || + (g_strncasecmp(option, "--fork", 255) == 0)) + { + startup_params->fork = 1; + g_writeln("--fork parameter found, ini override"); + } else { return 1; @@ -228,6 +283,8 @@ main(int argc, char** argv) { int test; int host_be; + char cfg_file[256]; + enum logReturns error; struct xrdp_startup_params* startup_params; int pid; int fd; @@ -271,6 +328,29 @@ main(int argc, char** argv) g_writeln("unusable tui64 size, must be 8"); return 0; } + g_snprintf(cfg_file, 255, "%s/xrdp.ini", XRDP_CFG_PATH); + + /* starting logging subsystem */ + error = log_start(cfg_file, "XRDP"); + + if (error != LOG_STARTUP_OK) + { + switch (error) + { + case LOG_ERROR_MALLOC: + g_writeln("error on malloc. cannot start logging. quitting."); + break; + case LOG_ERROR_FILE_OPEN: + g_writeln("error opening log file [%s]. quitting.", + getLogFile(text, 255)); + break; + default: + g_writeln("log_start error"); + break; + } + g_deinit(); + g_exit(1); + } startup_params = (struct xrdp_startup_params*) g_malloc(sizeof(struct xrdp_startup_params), 1); @@ -297,7 +377,7 @@ main(int argc, char** argv) } if (fd == -1) { - g_writeln("problem opening to xrdp.pid"); + g_writeln("problem opening to xrdp.pid [%s]", pid_file); g_writeln("maybe its not running"); } else @@ -327,9 +407,11 @@ main(int argc, char** argv) g_writeln("See http://xrdp.sourceforge.net for more information."); g_writeln(""); g_writeln("Usage: xrdp [options]"); - g_writeln(" -h: show help"); - g_writeln(" -nodaemon: don't fork into background"); - g_writeln(" -kill: shut down xrdp"); + g_writeln(" --help: show help"); + g_writeln(" --nodaemon: don't fork into background"); + g_writeln(" --kill: shut down xrdp"); + g_writeln(" --port: tcp listen port"); + g_writeln(" --fork: fork on new connection"); g_writeln(""); g_deinit(); g_exit(0); @@ -354,6 +436,10 @@ main(int argc, char** argv) } if (!no_daemon) { + + /* make sure containing directory exists */ + g_create_path(pid_file); + /* make sure we can write to pid file */ fd = g_file_open(pid_file); /* xrdp.pid */ if (fd == -1) @@ -389,16 +475,6 @@ main(int argc, char** argv) g_exit(0); } g_sleep(1000); - g_file_close(0); - g_file_close(1); - g_file_close(2); - g_file_open("/dev/null"); - g_file_open("/dev/null"); - g_file_open("/dev/null"); - /* end of daemonizing code */ - } - if (!no_daemon) - { /* write the pid to file */ pid = g_getpid(); fd = g_file_open(pid_file); /* xrdp.pid */ @@ -414,6 +490,14 @@ main(int argc, char** argv) g_file_write(fd, text, g_strlen(text)); g_file_close(fd); } + g_sleep(1000); + g_file_close(0); + g_file_close(1); + g_file_close(2); + g_file_open("/dev/null"); + g_file_open("/dev/null"); + g_file_open("/dev/null"); + /* end of daemonizing code */ } g_threadid = tc_get_threadid(); g_listen = xrdp_listen_create(); @@ -421,25 +505,35 @@ main(int argc, char** argv) g_signal_kill(xrdp_shutdown); /* SIGKILL */ g_signal_pipe(pipe_sig); /* SIGPIPE */ g_signal_terminate(xrdp_shutdown); /* SIGTERM */ + g_signal_child_stop(xrdp_child); /* SIGCHLD */ g_sync_mutex = tc_mutex_create(); g_sync1_mutex = tc_mutex_create(); pid = g_getpid(); g_snprintf(text, 255, "xrdp_%8.8x_main_term", pid); g_term_event = g_create_wait_obj(text); - g_snprintf(text, 255, "xrdp_%8.8x_main_sync", pid); - g_sync_event = g_create_wait_obj(text); if (g_term_event == 0) { g_writeln("error creating g_term_event"); } - xrdp_listen_main_loop(g_listen, startup_params); + g_snprintf(text, 255, "xrdp_%8.8x_main_sync", pid); + g_sync_event = g_create_wait_obj(text); + if (g_sync_event == 0) + { + g_writeln("error creating g_sync_event"); + } + g_listen->startup_params = startup_params; + xrdp_listen_main_loop(g_listen); xrdp_listen_delete(g_listen); tc_mutex_delete(g_sync_mutex); tc_mutex_delete(g_sync1_mutex); g_delete_wait_obj(g_term_event); g_delete_wait_obj(g_sync_event); - /* delete the xrdp.pid file */ - g_file_delete(pid_file); + /* only main process should delete pid file */ + if ((!no_daemon) && (pid == g_getpid())) + { + /* delete the xrdp.pid file */ + g_file_delete(pid_file); + } g_free(startup_params); g_deinit(); return 0; diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h index 14be3767..2f4e7eb6 100644 --- a/xrdp/xrdp.h +++ b/xrdp/xrdp.h @@ -27,6 +27,7 @@ #include "arch.h" #include "parse.h" #include "trans.h" +#include "list.h" #include "libxrdpinc.h" #include "xrdp_types.h" #include "xrdp_constants.h" @@ -34,7 +35,6 @@ #include "os_calls.h" #include "ssl_calls.h" #include "thread_calls.h" -#include "list.h" #include "file.h" #include "file_loc.h" #include "xrdp_client_info.h" @@ -52,7 +52,7 @@ g_get_term_event(void); tbus APP_CC g_get_sync_event(void); void APP_CC -g_loop(void); +g_process_waiting_function(void); /* xrdp_cache.c */ struct xrdp_cache* APP_CC @@ -64,7 +64,8 @@ int APP_CC xrdp_cache_reset(struct xrdp_cache* self, struct xrdp_client_info* client_info); int APP_CC -xrdp_cache_add_bitmap(struct xrdp_cache* self, struct xrdp_bitmap* bitmap); +xrdp_cache_add_bitmap(struct xrdp_cache* self, struct xrdp_bitmap* bitmap, + int hints); int APP_CC xrdp_cache_add_palette(struct xrdp_cache* self, int* palette); int APP_CC @@ -82,11 +83,11 @@ xrdp_cache_add_brush(struct xrdp_cache* self, char* brush_item_data); int APP_CC xrdp_cache_add_os_bitmap(struct xrdp_cache* self, struct xrdp_bitmap* bitmap, - int id); + int rdpindex); int APP_CC -xrdp_cache_remove_os_bitmap(struct xrdp_cache* self, int id); +xrdp_cache_remove_os_bitmap(struct xrdp_cache* self, int rdpindex); struct xrdp_os_bitmap_item* APP_CC -xrdp_cache_get_os_bitmap(struct xrdp_cache* self, int id); +xrdp_cache_get_os_bitmap(struct xrdp_cache* self, int rdpindex); /* xrdp_wm.c */ struct xrdp_wm* APP_CC @@ -158,8 +159,7 @@ xrdp_listen_create(void); void APP_CC xrdp_listen_delete(struct xrdp_listen* self); int APP_CC -xrdp_listen_main_loop(struct xrdp_listen* self, - struct xrdp_startup_params* startup_param); +xrdp_listen_main_loop(struct xrdp_listen* self); /* xrdp_region.c */ struct xrdp_region* APP_CC @@ -239,6 +239,8 @@ xrdp_painter_create(struct xrdp_wm* wm, struct xrdp_session* session); void APP_CC xrdp_painter_delete(struct xrdp_painter* self); int APP_CC +wm_painter_set_target(struct xrdp_painter* self); +int APP_CC xrdp_painter_begin_update(struct xrdp_painter* self); int APP_CC xrdp_painter_end_update(struct xrdp_painter* self); @@ -381,6 +383,8 @@ int DEFAULT_CC server_msg(struct xrdp_mod* mod, char* msg, int code); int DEFAULT_CC server_is_term(struct xrdp_mod* mod); +int APP_CC +xrdp_child_fork(void); int DEFAULT_CC server_set_clip(struct xrdp_mod* mod, int x, int y, int cx, int cy); int DEFAULT_CC @@ -414,6 +418,8 @@ server_draw_text(struct xrdp_mod* mod, int font, int DEFAULT_CC server_reset(struct xrdp_mod* mod, int width, int height, int bpp); int DEFAULT_CC +is_channel_allowed(struct xrdp_wm* wm, int channel_id); +int DEFAULT_CC server_query_channel(struct xrdp_mod* mod, int index, char* channel_name, int* channel_flags); int DEFAULT_CC @@ -422,3 +428,41 @@ int DEFAULT_CC server_send_to_channel(struct xrdp_mod* mod, int channel_id, char* data, int data_len, int total_data_len, int flags); +int DEFAULT_CC +server_create_os_surface(struct xrdp_mod* mod, int id, + int width, int height); +int DEFAULT_CC +server_switch_os_surface(struct xrdp_mod* mod, int id); +int DEFAULT_CC +server_delete_os_surface(struct xrdp_mod* mod, int id); +int DEFAULT_CC +server_paint_rect_os(struct xrdp_mod* mod, int x, int y, int cx, int cy, + int id, int srcx, int srcy); +int DEFAULT_CC +server_set_hints(struct xrdp_mod* mod, int hints, int mask); +int DEFAULT_CC +server_window_new_update(struct xrdp_mod* mod, int window_id, + struct rail_window_state_order* window_state, + int flags); +int DEFAULT_CC +server_window_delete(struct xrdp_mod* mod, int window_id); +int DEFAULT_CC +server_window_icon(struct xrdp_mod* mod, int window_id, int cache_entry, + int cache_id, struct rail_icon_info* icon_info, + int flags); +int DEFAULT_CC +server_window_cached_icon(struct xrdp_mod* mod, + int window_id, int cache_entry, + int cache_id, int flags); +int DEFAULT_CC +server_notify_new_update(struct xrdp_mod* mod, + int window_id, int notify_id, + struct rail_notify_state_order* notify_state, + int flags); +int DEFAULT_CC +server_notify_delete(struct xrdp_mod* mod, int window_id, + int notify_id); +int DEFAULT_CC +server_monitored_desktop(struct xrdp_mod* mod, + struct rail_monitored_desktop_order* mdo, + int flags); diff --git a/xrdp/xrdp.ini b/xrdp/xrdp.ini index cfcdcc18..871e8d47 100644 --- a/xrdp/xrdp.ini +++ b/xrdp/xrdp.ini @@ -6,6 +6,13 @@ port=3389 crypt_level=low channel_code=1 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 #black=000000 #grey=d6d3ce #dark_grey=808080 @@ -18,6 +25,24 @@ max_bpp=24 #autorun=xrdp7 #hidelogwindow=yes +[Logging] +LogFile=xrdp.log +LogLevel=DEBUG +EnableSyslog=1 +SyslogLevel=DEBUG +# LogLevel and SysLogLevel could by any of: core, error, warning, info or debug + +[channels] +# Channel names not listed here will be blocket by XRDP. +# You can block any channel by setting its value to false. +# IMPORTANT! All channels are not supported in all use +# cases even if you set all values to true. +rdpdr=true +rdpsnd=true +drdynvc=true +cliprdr=true +rail=true + [xrdp1] name=sesman-X11rdp lib=libxup.so diff --git a/xrdp/xrdp_bitmap.c b/xrdp/xrdp_bitmap.c index cee6f40b..828c5139 100644 --- a/xrdp/xrdp_bitmap.c +++ b/xrdp/xrdp_bitmap.c @@ -24,6 +24,7 @@ */ #include "xrdp.h" +#include "log.h" static int g_crc_seed = 0xffffffff; static int g_crc_table[256] = @@ -351,8 +352,8 @@ xrdp_bitmap_load(struct xrdp_bitmap* self, const char* filename, int* palette) if (!g_file_exist(filename)) { - g_writeln("xrdp_bitmap_load: error bitmap file [%s] does not exist", - filename); + log_message(LOG_LEVEL_ERROR, "xrdp_bitmap_load: error bitmap file [%s] " + "does not exist", filename); return 1; } s = (struct stream *)NULL; @@ -362,15 +363,15 @@ xrdp_bitmap_load(struct xrdp_bitmap* self, const char* filename, int* palette) /* read file type */ if (g_file_read(fd, type1, 2) != 2) { - g_writeln("xrdp_bitmap_load: error bitmap file [%s] read error", - filename); + log_message(LOG_LEVEL_ERROR, "xrdp_bitmap_load: error bitmap file [%s] " + "read error", filename); g_file_close(fd); return 1; } if ((type1[0] != 'B') || (type1[1] != 'M')) { - g_writeln("xrdp_bitmap_load: error bitmap file [%s] not BMP file", - filename); + log_message(LOG_LEVEL_ERROR, "xrdp_bitmap_load: error bitmap file [%s] " + "not BMP file", filename); g_file_close(fd); return 1; } @@ -397,8 +398,8 @@ xrdp_bitmap_load(struct xrdp_bitmap* self, const char* filename, int* palette) if ((header.bit_count != 4) && (header.bit_count != 8) && (header.bit_count != 24)) { - g_writeln("xrdp_bitmap_load: error bitmap file [%s] bad bpp %d", - filename, header.bit_count); + log_message(LOG_LEVEL_ERROR, "xrdp_bitmap_load: error bitmap file [%s] " + "bad bpp %d", filename, header.bit_count); free_stream(s); g_file_close(fd); return 1; @@ -416,8 +417,8 @@ xrdp_bitmap_load(struct xrdp_bitmap* self, const char* filename, int* palette) k = g_file_read(fd, s->data + i * size, size); if (k != size) { - g_writeln("xrdp_bitmap_load: error bitmap file [%s] read", - filename); + log_message(LOG_LEVEL_ERROR, "xrdp_bitmap_load: error bitmap " + "file [%s] read", filename); } } for (i = 0; i < self->height; i++) @@ -470,8 +471,8 @@ xrdp_bitmap_load(struct xrdp_bitmap* self, const char* filename, int* palette) k = g_file_read(fd, s->data + i * size, size); if (k != size) { - g_writeln("xrdp_bitmap_load: error bitmap file [%s] read", - filename); + log_message(LOG_LEVEL_ERROR, "xrdp_bitmap_load: error bitmap " + "file [%s] read", filename); } } for (i = 0; i < self->height; i++) @@ -520,8 +521,8 @@ xrdp_bitmap_load(struct xrdp_bitmap* self, const char* filename, int* palette) k = g_file_read(fd, s->data + i * size, size); if (k != size) { - g_writeln("xrdp_bitmap_load: error bitmap file [%s] read", - filename); + log_message(LOG_LEVEL_ERROR, "xrdp_bitmap_load: error bitmap " + "file [%s] read", filename); } } for (i = 0; i < self->height; i++) @@ -563,8 +564,8 @@ xrdp_bitmap_load(struct xrdp_bitmap* self, const char* filename, int* palette) } else { - g_writeln("xrdp_bitmap_load: error loading bitmap from file [%s]", - filename); + log_message(LOG_LEVEL_ERROR, "xrdp_bitmap_load: error loading bitmap " + "from file [%s]", filename); return 1; } return 0; @@ -1304,7 +1305,7 @@ xrdp_bitmap_invalidate(struct xrdp_bitmap* self, struct xrdp_rect* rect) h = (h / 2) + 2; y = y + (h / 2) + 1; painter->fg_color = self->wm->black; - for (i=w; i>0; i=i-2) + for (i=w; i>0; i=i-2) { xrdp_painter_fill_rect(painter, self, x, y, i, 1); y++; diff --git a/xrdp/xrdp_cache.c b/xrdp/xrdp_cache.c index 88180491..17316633 100644 --- a/xrdp/xrdp_cache.c +++ b/xrdp/xrdp_cache.c @@ -43,6 +43,7 @@ xrdp_cache_create(struct xrdp_wm* owner, self->bitmap_cache_persist_enable = client_info->bitmap_cache_persist_enable; self->bitmap_cache_version = client_info->bitmap_cache_version; self->pointer_cache_entries = client_info->pointer_cache_entries; + self->xrdp_os_del_list = list_create(); return self; } @@ -73,10 +74,12 @@ xrdp_cache_delete(struct xrdp_cache* self) g_free(self->char_items[i][j].font_item.data); } } + /* free all the off screen bitmaps */ for (i = 0; i < 2000; i++) { xrdp_bitmap_delete(self->os_bitmap_items[i].bitmap); } + list_delete(self->xrdp_os_del_list); g_free(self); } @@ -131,7 +134,8 @@ xrdp_cache_reset(struct xrdp_cache* self, /*****************************************************************************/ /* returns cache id */ int APP_CC -xrdp_cache_add_bitmap(struct xrdp_cache* self, struct xrdp_bitmap* bitmap) +xrdp_cache_add_bitmap(struct xrdp_cache* self, struct xrdp_bitmap* bitmap, + int hints) { int i = 0; int j = 0; @@ -257,35 +261,46 @@ xrdp_cache_add_bitmap(struct xrdp_cache* self, struct xrdp_bitmap* bitmap) xrdp_bitmap_delete(self->bitmap_items[cache_id][cache_idx].bitmap); self->bitmap_items[cache_id][cache_idx].bitmap = bitmap; self->bitmap_items[cache_id][cache_idx].stamp = self->bitmap_stamp; - if (self->bitmap_cache_version == 0) /* orginal version */ + if (self->use_bitmap_comp) { - if (self->use_bitmap_comp) + if (self->bitmap_cache_version & 4) + { + if (libxrdp_orders_send_bitmap3(self->session, bitmap->width, + bitmap->height, bitmap->bpp, + bitmap->data, cache_id, cache_idx, + hints) == 0) + { + return MAKELONG(cache_idx, cache_id); + } + } + if (self->bitmap_cache_version & 2) + { + libxrdp_orders_send_bitmap2(self->session, bitmap->width, + bitmap->height, bitmap->bpp, + bitmap->data, cache_id, cache_idx, + hints); + } + else if (self->bitmap_cache_version & 1) { libxrdp_orders_send_bitmap(self->session, bitmap->width, bitmap->height, bitmap->bpp, bitmap->data, cache_id, cache_idx); } - else - { - libxrdp_orders_send_raw_bitmap(self->session, bitmap->width, - bitmap->height, bitmap->bpp, - bitmap->data, cache_id, cache_idx); - } } else { - if (self->use_bitmap_comp) - { - libxrdp_orders_send_bitmap2(self->session, bitmap->width, - bitmap->height, bitmap->bpp, - bitmap->data, cache_id, cache_idx); - } - else + if (self->bitmap_cache_version & 2) { libxrdp_orders_send_raw_bitmap2(self->session, bitmap->width, bitmap->height, bitmap->bpp, bitmap->data, cache_id, cache_idx); } + else if (self->bitmap_cache_version & 1) + { + libxrdp_orders_send_raw_bitmap(self->session, bitmap->width, + bitmap->height, bitmap->bpp, + bitmap->data, cache_id, cache_idx); + } } return MAKELONG(cache_idx, cache_id); } @@ -539,76 +554,58 @@ xrdp_cache_add_brush(struct xrdp_cache* self, } /*****************************************************************************/ -/* returns index */ +/* returns error */ int APP_CC xrdp_cache_add_os_bitmap(struct xrdp_cache* self, struct xrdp_bitmap* bitmap, - int id) + int rdpindex) { - int index; struct xrdp_os_bitmap_item* bi; - if (id < 1) + if ((rdpindex < 0) || (rdpindex >= 2000)) { - return -1; - } - index = 0; - for (index = 0; index < 2000; index++) - { - bi = self->os_bitmap_items + index; - if (bi->bitmap == 0) - { - bi->id = id; - bi->bitmap = bitmap; - //g_writeln("xrdp_cache_add_os_bitmap: bitmap id 0x%x added at index %d", id, index); - return index; - } + return 1; } - g_writeln("xrdp_cache_add_os_bitmap: bitmap id 0x%x not added, full", id); - return -1; + bi = self->os_bitmap_items + rdpindex; + bi->bitmap = bitmap; + return 0; } /*****************************************************************************/ -/* returns index */ +/* returns error */ int APP_CC -xrdp_cache_remove_os_bitmap(struct xrdp_cache* self, int id) +xrdp_cache_remove_os_bitmap(struct xrdp_cache* self, int rdpindex) { - int index; struct xrdp_os_bitmap_item* bi; + int index; - if (id < 1) + if ((rdpindex < 0) || (rdpindex >= 2000)) { - return -1; + return 1; } - for (index = 0; index < 2000; index++) + bi = self->os_bitmap_items + rdpindex; + if (bi->bitmap->tab_stop) { - bi = self->os_bitmap_items + index; - if (bi->id == id) + index = list_index_of(self->xrdp_os_del_list, rdpindex); + if (index == -1) { - xrdp_bitmap_delete(bi->bitmap); - g_memset(bi, 0, sizeof(struct xrdp_os_bitmap_item)); - //g_writeln("xrdp_cache_remove_os_bitmap: bitmap id 0x%x removed from index %d", id, index); - return index; + list_add_item(self->xrdp_os_del_list, rdpindex); } } - return -1; + xrdp_bitmap_delete(bi->bitmap); + g_memset(bi, 0, sizeof(struct xrdp_os_bitmap_item)); + return 0; } /*****************************************************************************/ struct xrdp_os_bitmap_item* APP_CC -xrdp_cache_get_os_bitmap(struct xrdp_cache* self, int id) +xrdp_cache_get_os_bitmap(struct xrdp_cache* self, int rdpindex) { - int index; struct xrdp_os_bitmap_item* bi; - for (index = 0; index < 2000; index++) + if ((rdpindex < 0) || (rdpindex >= 2000)) { - bi = self->os_bitmap_items + index; - if (bi->id == id) - { - //g_writeln("xrdp_cache_get_os_bitmap: bitmap id 0x%x found at index %d", id, index); - return bi; - } + return 0; } - g_writeln("xrdp_cache_get_os_bitmap: bitmap id 0x%x not found", id); - return 0; + bi = self->os_bitmap_items + rdpindex; + return bi; } diff --git a/xrdp/xrdp_listen.c b/xrdp/xrdp_listen.c index 23f532a8..82bade84 100644 --- a/xrdp/xrdp_listen.c +++ b/xrdp/xrdp_listen.c @@ -28,17 +28,30 @@ static tbus g_process_sem = 0; static struct xrdp_process* g_process = 0; /*****************************************************************************/ -struct xrdp_listen* APP_CC -xrdp_listen_create(void) +static int +xrdp_listen_create_pro_done(struct xrdp_listen* self) { - struct xrdp_listen* self; int pid; char text[256]; pid = g_getpid(); - self = (struct xrdp_listen*)g_malloc(sizeof(struct xrdp_listen), 1); g_snprintf(text, 255, "xrdp_%8.8x_listen_pro_done_event", pid); self->pro_done_event = g_create_wait_obj(text); + if(self->pro_done_event == 0) + { + g_writeln("Failure creating pro_done_event"); + } + return 0; +} + +/*****************************************************************************/ +struct xrdp_listen* APP_CC +xrdp_listen_create(void) +{ + struct xrdp_listen* self; + + self = (struct xrdp_listen*)g_malloc(sizeof(struct xrdp_listen), 1); + xrdp_listen_create_pro_done(self); self->process_list = list_create(); if (g_process_sem == 0) { @@ -121,6 +134,7 @@ xrdp_process_run(void* in_val) static int xrdp_listen_get_port_address(char* port, int port_bytes, char* address, int address_bytes, + int *tcp_nodelay, int *tcp_keepalive, struct xrdp_startup_params* startup_param) { int fd; @@ -138,6 +152,8 @@ xrdp_listen_get_port_address(char* port, int port_bytes, /* see if port or address is in xrdp.ini file */ g_snprintf(cfg_file, 255, "%s/xrdp.ini", XRDP_CFG_PATH); fd = g_file_open(cfg_file); + *tcp_nodelay = 0 ; + *tcp_keepalive = 0 ; if (fd > 0) { names = list_create(); @@ -165,6 +181,39 @@ xrdp_listen_get_port_address(char* port, int port_bytes, val = (char*)list_get_item(values, index); g_strncpy(address, val, address_bytes - 1); } + if (g_strcasecmp(val, "fork") == 0) + { + val = (char*)list_get_item(values, index); + if ((g_strcasecmp(val, "yes") == 0) || + (g_strcasecmp(val, "on") == 0) || + (g_strcasecmp(val, "true") == 0) || + (g_atoi(val) != 0)) + { + startup_param->fork = 1; + } + } + if (g_strcasecmp(val, "tcp_nodelay") == 0) + { + val = (char*)list_get_item(values, index); + if ((g_strcasecmp(val, "yes") == 0) || + (g_strcasecmp(val, "on") == 0) || + (g_strcasecmp(val, "true") == 0) || + (g_atoi(val) != 0)) + { + *tcp_nodelay = 1 ; + } + } + if (g_strcasecmp(val, "tcp_keepalive") == 0) + { + val = (char*)list_get_item(values, index); + if ((g_strcasecmp(val, "yes") == 0) || + (g_strcasecmp(val, "on") == 0) || + (g_strcasecmp(val, "true") == 0) || + (g_atoi(val) != 0)) + { + *tcp_keepalive = 1 ; + } + } } } } @@ -181,6 +230,41 @@ xrdp_listen_get_port_address(char* port, int port_bytes, } /*****************************************************************************/ +static int APP_CC +xrdp_listen_fork(struct xrdp_listen* self, struct trans* server_trans) +{ + int pid; + struct xrdp_process* process; + + pid = g_fork(); + if (pid == 0) + { + /* child */ + /* recreate some main globals */ + xrdp_child_fork(); + /* recreate the process done wait object, not used in fork mode */ + /* close, don't delete this */ + g_close_wait_obj(self->pro_done_event); + xrdp_listen_create_pro_done(self); + /* delete listener, child need not listen */ + trans_delete(self->listen_trans); + self->listen_trans = 0; + /* new connect instance */ + process = xrdp_process_create(self, 0); + process->server_trans = server_trans; + g_process = process; + xrdp_process_run(0); + xrdp_process_delete(process); + /* mark this process to exit */ + g_set_term(1); + return 0; + } + /* parent */ + trans_delete(server_trans); + return 0; +} + +/*****************************************************************************/ /* a new connection is coming in */ int DEFAULT_CC xrdp_listen_conn_in(struct trans* self, struct trans* new_self) @@ -189,6 +273,10 @@ xrdp_listen_conn_in(struct trans* self, struct trans* new_self) struct xrdp_listen* lis; lis = (struct xrdp_listen*)(self->callback_data); + if (lis->startup_params->fork) + { + return xrdp_listen_fork(lis, new_self); + } process = xrdp_process_create(lis, lis->pro_done_event); if (xrdp_listen_add_pro(lis, process) == 0) { @@ -208,8 +296,7 @@ xrdp_listen_conn_in(struct trans* self, struct trans* new_self) /*****************************************************************************/ /* wait for incoming connections */ int APP_CC -xrdp_listen_main_loop(struct xrdp_listen* self, - struct xrdp_startup_params* startup_param) +xrdp_listen_main_loop(struct xrdp_listen* self) { int error; int robjs_count; @@ -220,24 +307,41 @@ xrdp_listen_main_loop(struct xrdp_listen* self, tbus robjs[8]; tbus term_obj; tbus sync_obj; - tbus sck_obj; tbus done_obj; + int tcp_nodelay; + int tcp_keepalive; self->status = 1; if (xrdp_listen_get_port_address(port, sizeof(port), address, sizeof(address), - startup_param) != 0) + &tcp_nodelay, &tcp_keepalive, + self->startup_params) != 0) { g_writeln("xrdp_listen_main_loop: xrdp_listen_get_port failed"); self->status = -1; return 1; } + /*Create socket*/ error = trans_listen_address(self->listen_trans, port, address); if (error == 0) { + if(tcp_nodelay) + { + if(g_tcp_set_no_delay(self->listen_trans->sck)) + { + g_writeln("Error setting tcp_nodelay"); + } + } + if(tcp_keepalive) + { + if(g_tcp_set_keepalive(self->listen_trans->sck)) + { + g_writeln("Error setting tcp_keepalive"); + } + } self->listen_trans->trans_conn_in = xrdp_listen_conn_in; self->listen_trans->callback_data = self; - term_obj = g_get_term_event(); + term_obj = g_get_term_event(); /*Global termination event */ sync_obj = g_get_sync_event(); done_obj = self->pro_done_event; cont = 1; @@ -249,34 +353,36 @@ xrdp_listen_main_loop(struct xrdp_listen* self, robjs[robjs_count++] = sync_obj; robjs[robjs_count++] = done_obj; timeout = -1; - if (trans_get_wait_objs(self->listen_trans, robjs, &robjs_count, - &timeout) != 0) + if (trans_get_wait_objs(self->listen_trans, robjs, &robjs_count) != 0) { + g_writeln("Listening socket is in wrong state we terminate listener") ; break; } - /* wait */ + /* wait - timeout -1 means wait indefinitely*/ if (g_obj_wait(robjs, robjs_count, 0, 0, timeout) != 0) { /* error, should not get here */ g_sleep(100); } - if (g_is_wait_obj_set(term_obj)) /* term */ + if (g_is_wait_obj_set(term_obj)) /* termination called */ { break; } - if (g_is_wait_obj_set(sync_obj)) /* sync */ + if (g_is_wait_obj_set(sync_obj)) /* some function must be processed by this thread */ { g_reset_wait_obj(sync_obj); - g_loop(); + g_process_waiting_function(); /* run the function */ } if (g_is_wait_obj_set(done_obj)) /* pro_done_event */ { g_reset_wait_obj(done_obj); + /* a process has died remove it from lists*/ xrdp_listen_delete_done_pro(self); } + /* Run the callback when accept() returns a new socket*/ if (trans_check_wait_objs(self->listen_trans) != 0) { - break; + break; } } /* stop listening */ @@ -290,20 +396,21 @@ xrdp_listen_main_loop(struct xrdp_listen* self, { break; } + timeout = -1; /* build the wait obj list */ robjs_count = 0; robjs[robjs_count++] = sync_obj; robjs[robjs_count++] = done_obj; - /* wait */ - if (g_obj_wait(robjs, robjs_count, 0, 0, -1) != 0) + /* wait - timeout -1 means wait indefinitely*/ + if (g_obj_wait(robjs, robjs_count, 0, 0, timeout) != 0) { /* error, should not get here */ g_sleep(100); } - if (g_is_wait_obj_set(sync_obj)) /* sync */ + if (g_is_wait_obj_set(sync_obj)) /* some function must be processed by this thread */ { g_reset_wait_obj(sync_obj); - g_loop(); + g_process_waiting_function(); /* run the function that is waiting*/ } if (g_is_wait_obj_set(done_obj)) /* pro_done_event */ { diff --git a/xrdp/xrdp_login_wnd.c b/xrdp/xrdp_login_wnd.c index b4f25699..34a929b8 100644 --- a/xrdp/xrdp_login_wnd.c +++ b/xrdp/xrdp_login_wnd.c @@ -21,6 +21,8 @@ */ #include "xrdp.h" +#define ACCESS +#include "log.h" /*****************************************************************************/ /* all login help screen events go here */ @@ -222,6 +224,10 @@ xrdp_wm_ok_clicked(struct xrdp_bitmap* wnd) xrdp_wm_set_login_mode(wm, 2); } } + else + { + log_message(LOG_LEVEL_ERROR,"Combo is 0 - potential programming error"); + } return 0; } @@ -261,7 +267,7 @@ xrdp_wm_show_edits(struct xrdp_wm* self, struct xrdp_bitmap* combo) if (g_strncmp("ask", value, 3) == 0) { /* label */ - b = xrdp_bitmap_create(70, DEFAULT_EDIT_H, self->screen->bpp, + b = xrdp_bitmap_create(95, DEFAULT_EDIT_H, self->screen->bpp, WND_TYPE_LABEL, self); list_insert_item(self->login_window->child_list, insert_index, (long)b); @@ -302,7 +308,11 @@ xrdp_wm_show_edits(struct xrdp_wm* self, struct xrdp_bitmap* combo) username_set = 1; } } +#ifdef ACCESS + if ((g_strncmp(name, "password", 255) == 0) || (g_strncmp(name, "pampassword", 255) == 0)) +#else if (g_strncmp(name, "password", 255) == 0) +#endif { b->password_char = '*'; if (username_set) @@ -403,14 +413,16 @@ xrdp_wm_login_fill_in_combo(struct xrdp_wm* self, struct xrdp_bitmap* b) fd = g_file_open(cfg_file); /* xrdp.ini */ if (fd < 1) { - g_writeln("Could not read xrdp ini file %s", cfg_file); + log_message(LOG_LEVEL_ERROR,"Could not read xrdp ini file %s", cfg_file); } file_read_sections(fd, sections); for (i = 0; i < sections->count; i++) { p = (char*)list_get_item(sections, i); file_read_section(fd, p, section_names, section_values); - if (g_strncmp(p, "globals", 255) == 0) + if ((g_strncmp(p, "globals", 255) == 0) + ||(g_strncmp(p, "channels", 255) == 0) + ||(g_strncmp(p, "Logging", 255) == 0)) { } else diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index 4001677f..66f3b1d9 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -21,6 +21,8 @@ */ #include "xrdp.h" +#include "log.h" +#define ACCESS #include "libraptorsmiface.h" @@ -65,6 +67,7 @@ xrdp_mm_sync_load(long param1, long param2) static void APP_CC xrdp_mm_module_cleanup(struct xrdp_mm* self) { + g_writeln("xrdp_mm_module_cleanup"); if (self->mod != 0) { if (self->mod_exit != 0) @@ -75,7 +78,7 @@ xrdp_mm_module_cleanup(struct xrdp_mm* self) } if (self->mod_handle != 0) { - /* main thread unload */ + /* Let the main thread unload the module.*/ g_xrdp_sync(xrdp_mm_sync_unload, self->mod_handle, 0); } trans_delete(self->chan_trans); @@ -106,6 +109,7 @@ xrdp_mm_delete(struct xrdp_mm* self) } /*****************************************************************************/ +/* Send login information to sesman */ static int APP_CC xrdp_mm_send_login(struct xrdp_mm* self) { @@ -204,6 +208,7 @@ xrdp_mm_send_login(struct xrdp_mm* self) s_mark_end(s); s_pop_layer(s, channel_hdr); + /* Version 0 of the protocol to sesman is currently used by XRDP */ out_uint32_be(s, 0); /* version */ index = (int)(s->end - s->data); out_uint32_be(s, index); /* size */ @@ -284,6 +289,7 @@ xrdp_mm_setup_mod1(struct xrdp_mm* self) } if (self->mod_handle == 0) { + /* Let the main thread load the lib,*/ self->mod_handle = g_xrdp_sync(xrdp_mm_sync_load, (long)lib, 0); if (self->mod_handle != 0) { @@ -319,6 +325,8 @@ xrdp_mm_setup_mod1(struct xrdp_mm* self) g_writeln("loaded module '%s' ok, interface size %d, version %d", lib, self->mod->size, self->mod->version); } + }else{ + g_writeln("no mod_init or mod_exit address found"); } } else @@ -326,6 +334,7 @@ xrdp_mm_setup_mod1(struct xrdp_mm* self) g_snprintf(text, 255, "error loading %s specified in xrdp.ini, please " "add a valid entry like lib=libxrdp-vnc.so or similar", lib); xrdp_wm_log_msg(self->wm, text); + return 1; } if (self->mod != 0) { @@ -355,6 +364,18 @@ xrdp_mm_setup_mod1(struct xrdp_mm* self) self->mod->server_query_channel = server_query_channel; self->mod->server_get_channel_id = server_get_channel_id; self->mod->server_send_to_channel = server_send_to_channel; + self->mod->server_create_os_surface = server_create_os_surface; + self->mod->server_switch_os_surface = server_switch_os_surface; + self->mod->server_delete_os_surface = server_delete_os_surface; + self->mod->server_paint_rect_os = server_paint_rect_os; + self->mod->server_set_hints = server_set_hints; + self->mod->server_window_new_update = server_window_new_update; + self->mod->server_window_delete = server_window_delete; + self->mod->server_window_icon = server_window_icon; + self->mod->server_window_cached_icon = server_window_cached_icon; + self->mod->server_notify_new_update = server_notify_new_update; + self->mod->server_notify_delete = server_notify_delete; + self->mod->server_monitored_desktop = server_monitored_desktop; } } /* id self->mod is null, there must be a problem */ @@ -778,6 +799,17 @@ xrdp_mm_connect_chansrv(struct xrdp_mm* self, char* ip, char* port) return 0; } +static void cleanup_sesman_connection(struct xrdp_mm* self) +{ + self->delete_sesman_trans = 1; + self->connected_state = 0; + if (self->wm->login_mode != 10) + { + xrdp_wm_set_login_mode(self->wm, 11); + xrdp_mm_module_cleanup(self); + } +} + /*****************************************************************************/ static int APP_CC xrdp_mm_process_login_response(struct xrdp_mm* self, struct stream* s) @@ -785,8 +817,6 @@ xrdp_mm_process_login_response(struct xrdp_mm* self, struct stream* s) int ok; int display; int rv; - int uid; - int gid; char text[256]; char ip[256]; char port[256]; @@ -828,14 +858,7 @@ xrdp_mm_process_login_response(struct xrdp_mm* self, struct stream* s) xrdp_wm_log_msg(self->wm, "xrdp_mm_process_login_response: " "login failed"); } - self->delete_sesman_trans = 1; - self->connected_state = 0; - if (self->wm->login_mode != 10) - { - xrdp_wm_set_login_mode(self->wm, 11); - xrdp_mm_module_cleanup(self); - } - + cleanup_sesman_connection(self); return rv; } @@ -940,6 +963,7 @@ xrdp_mm_process_channel_data(struct xrdp_mm* self, tbus param1, tbus param2, } /*****************************************************************************/ +/* This is the callback registered for sesman communication replies. */ static int APP_CC xrdp_mm_sesman_data_in(struct trans* trans) { @@ -968,11 +992,14 @@ xrdp_mm_sesman_data_in(struct trans* trans) in_uint16_be(s, code); switch (code) { + /* even when the request is denied the reply will hold 3 as the command. */ case 3: error = xrdp_mm_process_login_response(self, s); break; default: - g_writeln("xrdp_mm_sesman_data_in: unknown code %d", code); + xrdp_wm_log_msg(self->wm, "An undefined reply code was received from sesman"); + g_writeln("Fatal xrdp_mm_sesman_data_in: unknown cmd code %d", code); + cleanup_sesman_connection(self); break; } } @@ -980,6 +1007,133 @@ xrdp_mm_sesman_data_in(struct trans* trans) return error; } +#ifdef ACCESS +/*********************************************************************/ +/* return 0 on success */ +int access_control(char *username, char *password, char *srv) +{ + int reply; + int rec = 1; // failure + struct stream* in_s; + struct stream* out_s; + unsigned long version; + unsigned short int dummy; + unsigned short int ok; + unsigned short int code; + unsigned long size; + int index; + int socket = g_tcp_socket(); + if (socket > 0) + { + /* we use a blocking socket here */ + reply = g_tcp_connect(socket, srv, "3350"); + if (reply == 0) + { + make_stream(in_s); + init_stream(in_s, 500); + make_stream(out_s); + init_stream(out_s, 500); + s_push_layer(out_s, channel_hdr, 8); + out_uint16_be(out_s, 4); /*0x04 means SCP_GW_AUTHENTICATION*/ + index = g_strlen(username); + out_uint16_be(out_s, index); + out_uint8a(out_s, username, index); + + index = g_strlen(password); + out_uint16_be(out_s, index); + out_uint8a(out_s, password, index); + s_mark_end(out_s); + s_pop_layer(out_s, channel_hdr); + out_uint32_be(out_s, 0); /* version */ + index = (int)(out_s->end - out_s->data); + out_uint32_be(out_s, index); /* size */ + /* g_writeln("Number of data to send : %d",index); */ + reply = g_tcp_send(socket, out_s->data, index, 0); + free_stream(out_s); + if (reply > 0) + { + /* We wait in 5 sec for a reply from sesman*/ + if (g_tcp_can_recv(socket, 5000)) + { + reply = g_tcp_recv(socket, in_s->end, 500, 0); + if (reply > 0) + { + in_s->end = in_s->end + reply; + in_uint32_be(in_s, version); + /*g_writeln("Version number in reply from sesman: %d",version) ; */ + in_uint32_be(in_s, size); + if ((size == 14) && (version == 0)) + { + in_uint16_be(in_s, code); + in_uint16_be(in_s, ok); + in_uint16_be(in_s, dummy); + if (code != 4) + { + log_message(LOG_LEVEL_ERROR, "Returned cmd code from " + "sesman is corrupt"); + } + else + { + rec = ok; /* here we read the reply from the access control */ + } + } + else + { + log_message(LOG_LEVEL_ERROR, "Corrupt reply size or " + "version from sesman: %d", size); + } + } + else + { + log_message(LOG_LEVEL_ERROR, "No data received from sesman"); + } + } + else + { + log_message(LOG_LEVEL_ERROR, "Timeout when waiting for sesman"); + } + } + else + { + log_message(LOG_LEVEL_ERROR, "No success sending to sesman"); + } + free_stream(in_s); + g_tcp_close(socket); + } + else + { + log_message(LOG_LEVEL_ERROR, "Failure connecting to socket sesman"); + } + } + else + { + log_message(LOG_LEVEL_ERROR, "Failure creating socket - for access control"); + } + return rec; +} +#endif + +/*****************************************************************************/ +/* This routine clears all states to make sure that our next login will be + * as expected. If the user does not press ok on the log window and try to + * connect again we must make sure that no previous information is stored.*/ +void cleanup_states(struct xrdp_mm* self) +{ + if (self != NULL) + { + self-> connected_state = 0; /* true if connected to sesman else false */ + self-> sesman_trans = NULL; /* connection to sesman */ + self-> sesman_trans_up = 0; /* true once connected to sesman */ + self-> delete_sesman_trans = 0; /* boolean set when done with sesman connection */ + self-> display = 0; /* 10 for :10.0, 11 for :11.0, etc */ + self-> code = 0; /* 0 Xvnc session 10 X11rdp session */ + self-> sesman_controlled = 0; /* true if this is a sesman session */ + self-> chan_trans = NULL; /* connection to chansrv */ + self-> chan_trans_up = 0; /* true once connected to chansrv */ + self-> delete_chan_trans = 0; /* boolean set when done with channel connection */ + self-> usechansrv = 0; /* true if chansrvport is set in xrdp.ini or using sesman */ + } +} /*****************************************************************************/ int APP_CC xrdp_mm_connect(struct xrdp_mm* self) @@ -988,7 +1142,6 @@ xrdp_mm_connect(struct xrdp_mm* self) struct list* values; int index; int count; - int use_sesman; int ok; int rv; char* name; @@ -998,14 +1151,24 @@ xrdp_mm_connect(struct xrdp_mm* self) char text[256]; char port[8]; char chansrvport[256]; - +#ifdef ACCESS + int use_pam_auth = 0; + char pam_auth_sessionIP[256]; + char pam_auth_password[256]; + char pam_auth_username[256]; + char username[256]; + char password[256]; + username[0] = 0; + password[0] = 0; +#endif + /* make sure we start in correct state */ + cleanup_states(self); g_memset(ip, 0, sizeof(ip)); g_memset(errstr, 0, sizeof(errstr)); g_memset(text, 0, sizeof(text)); g_memset(port, 0, sizeof(port)); g_memset(chansrvport, 0, sizeof(chansrvport)); rv = 0; /* success */ - use_sesman = 0; names = self->login_names; values = self->login_values; count = names->count; @@ -1021,25 +1184,84 @@ xrdp_mm_connect(struct xrdp_mm* self) { if (g_strcasecmp(value, "-1") == 0) { - use_sesman = 1; + self->sesman_controlled = 1; } } +#ifdef ACCESS + else if (g_strcasecmp(name, "pamusername") == 0) + { + use_pam_auth = 1; + g_strncpy(pam_auth_username, value, 255); + } + else if (g_strcasecmp(name, "pamsessionmng") == 0) + { + g_strncpy(pam_auth_sessionIP, value, 255); + } + else if (g_strcasecmp(name, "pampassword") == 0) + { + g_strncpy(pam_auth_password, value, 255); + } + else if (g_strcasecmp(name, "password") == 0) + { + g_strncpy(password, value, 255); + } + else if (g_strcasecmp(name, "username") == 0) + { + g_strncpy(username, value, 255); + } +#endif else if (g_strcasecmp(name, "chansrvport") == 0) { g_strncpy(chansrvport, value, 255); self->usechansrv = 1; } } - if (use_sesman) +#ifdef ACCESS + if (use_pam_auth) + { + int reply; + char replytxt[80]; + char replymessage[4][80] = {"Ok","Sesman connect failure","User or password error","Privilege group error"}; + xrdp_wm_log_msg(self->wm, "Please wait, we now perform access control..."); + /* g_writeln("we use pam modules to check if we can approve this user"); */ + if (!g_strncmp(pam_auth_username, "same", 255)) + { + log_message(LOG_LEVEL_DEBUG, "pamusername copied from username - same: %s", username); + g_strncpy(pam_auth_username,username, 255); + } + if (!g_strncmp(pam_auth_password, "same", 255)) + { + log_message(LOG_LEVEL_DEBUG,"pam_auth_password copied from username - same: %s", password); + g_strncpy(pam_auth_password, password, 255); + } + /* access_control return 0 on success */ + reply = access_control(pam_auth_username, pam_auth_password, pam_auth_sessionIP); + if (reply >= 0 && reply < 4) + { + g_sprintf(replytxt,"Reply from access control: %s", replymessage[reply]); + } + else + { + g_sprintf(replytxt,"Reply from access control undefined"); + } + xrdp_wm_log_msg(self->wm,replytxt); + log_message(LOG_LEVEL_INFO,replytxt); + if (reply != 0) + { + rv = 1; + return rv; + } + } +#endif + if (self->sesman_controlled) { ok = 0; - errstr[0] = 0; trans_delete(self->sesman_trans); self->sesman_trans = trans_create(TRANS_MODE_TCP, 8192, 8192); xrdp_mm_get_sesman_port(port, sizeof(port)); g_snprintf(text, 255, "connecting to sesman ip %s port %s", ip, port); xrdp_wm_log_msg(self->wm, text); - + /* xrdp_mm_sesman_data_in is the callback that is called when data arrives */ self->sesman_trans->trans_data_in = xrdp_mm_sesman_data_in; self->sesman_trans->header_size = 8; self->sesman_trans->callback_data = self; @@ -1065,6 +1287,8 @@ xrdp_mm_connect(struct xrdp_mm* self) } else { + g_snprintf(errstr, 255, "Failure to connect to sesman: %s port: %s", + ip, port); xrdp_wm_log_msg(self->wm, errstr); trans_delete(self->sesman_trans); self->sesman_trans = 0; @@ -1079,23 +1303,27 @@ xrdp_mm_connect(struct xrdp_mm* self) if (xrdp_mm_setup_mod2(self) == 0) { xrdp_wm_set_login_mode(self->wm, 10); + rv = 0; /*sucess*/ } else { /* connect error */ - g_snprintf(errstr, 255, "Failure to connect to: %s port: %s", - ip, port); + g_snprintf(errstr, 255, "Failure to connect to: %s", ip); xrdp_wm_log_msg(self->wm, errstr); - rv = 1 ; /* failure */ + rv = 1; /* failure */ } } + else + { + g_writeln("Failure setting up module"); + } if (self->wm->login_mode != 10) { xrdp_wm_set_login_mode(self->wm, 11); xrdp_mm_module_cleanup(self); + rv = 1; /* failure */ } } - self->sesman_controlled = use_sesman; if ((self->wm->login_mode == 10) && (self->sesman_controlled == 0) && (self->usechansrv != 0)) @@ -1103,6 +1331,7 @@ xrdp_mm_connect(struct xrdp_mm* self) /* if sesman controlled, this will connect later */ xrdp_mm_connect_chansrv(self, "", chansrvport); } + g_writeln("returnvalue from xrdp_mm_connect %d", rv); return rv; } @@ -1122,11 +1351,11 @@ xrdp_mm_get_wait_objs(struct xrdp_mm* self, rv = 0; if ((self->sesman_trans != 0) && self->sesman_trans_up) { - trans_get_wait_objs(self->sesman_trans, read_objs, rcount, timeout); + trans_get_wait_objs(self->sesman_trans, read_objs, rcount); } if ((self->chan_trans != 0) && self->chan_trans_up) { - trans_get_wait_objs(self->chan_trans, read_objs, rcount, timeout); + trans_get_wait_objs(self->chan_trans, read_objs, rcount); } if (self->mod != 0) { @@ -1266,7 +1495,7 @@ server_fill_rect(struct xrdp_mod* mod, int x, int y, int cx, int cy) return 0; } wm = (struct xrdp_wm*)(mod->wm); - xrdp_painter_fill_rect(p, wm->screen, x, y, cx, cy); + xrdp_painter_fill_rect(p, wm->target_surface, x, y, cx, cy); return 0; } @@ -1285,7 +1514,7 @@ server_screen_blt(struct xrdp_mod* mod, int x, int y, int cx, int cy, } wm = (struct xrdp_wm*)(mod->wm); p->rop = 0xcc; - xrdp_painter_copy(p, wm->screen, wm->screen, x, y, cx, cy, srcx, srcy); + xrdp_painter_copy(p, wm->screen, wm->target_surface, x, y, cx, cy, srcx, srcy); return 0; } @@ -1305,7 +1534,7 @@ server_paint_rect(struct xrdp_mod* mod, int x, int y, int cx, int cy, } wm = (struct xrdp_wm*)(mod->wm); b = xrdp_bitmap_create_with_data(width, height, wm->screen->bpp, data, wm); - xrdp_painter_copy(p, b, wm->screen, x, y, cx, cy, srcx, srcy); + xrdp_painter_copy(p, b, wm->target_surface, x, y, cx, cy, srcx, srcy); xrdp_bitmap_delete(b); return 0; } @@ -1496,7 +1725,7 @@ server_draw_line(struct xrdp_mod* mod, int x1, int y1, int x2, int y2) return 0; } wm = (struct xrdp_wm*)(mod->wm); - return xrdp_painter_line(p, wm->screen, x1, y1, x2, y2); + return xrdp_painter_line(p, wm->target_surface, x1, y1, x2, y2); } /*****************************************************************************/ @@ -1535,7 +1764,7 @@ server_draw_text(struct xrdp_mod* mod, int font, return 0; } wm = (struct xrdp_wm*)(mod->wm); - return xrdp_painter_draw_text2(p, wm->screen, font, flags, + return xrdp_painter_draw_text2(p, wm->target_surface, font, flags, mixmode, clip_left, clip_top, clip_right, clip_bottom, box_left, box_top, @@ -1581,8 +1810,164 @@ server_reset(struct xrdp_mod* mod, int width, int height, int bpp) xrdp_wm_load_static_pointers(wm); return 0; } +/* read the channel section of the ini file into lists + * return 1 on success 0 on failure */ +int read_allowed_channel_names(struct list* names, struct list* values) +{ + int fd; + int ret = 0; + char cfg_file[256]; + int pos; + g_snprintf(cfg_file, 255, "%s/xrdp.ini", XRDP_CFG_PATH); + fd = g_file_open(cfg_file); + if (fd > 0) + { + names->auto_free = 1; + values->auto_free = 1; + pos = 0; + /* all values in this section can be valid channel names */ + if (file_read_section(fd, "channels", names, values) == 0) + { + ret = 1; + } + else + { + g_writeln("Failure reading channel section of configuration"); + } + g_file_close(fd); + return ret; + } +} +/* internal function return 1 if name is in list of channels + * and if the value is allowed */ +int DEFAULT_CC +is_name_in_lists(char* inName, struct list* names, struct list* values) +{ + int reply = 0; /*means not in the list*/ + int index; + char* val; + char* name; + for (index = 0; index < names->count; index++) + { + name = (char*)list_get_item(names, index); + if (name != 0) + { + /* ex rdpdr ;rdpsnd ; drdynvc ; cliprdr */ + if (!g_strncmp(name, inName, MAX_CHANNEL_NAME)) + { + val = (char*)list_get_item(values, index); + if ((g_strcasecmp(val, "yes") == 0) || + (g_strcasecmp(val, "on") == 0) || + (g_strcasecmp(val, "true") == 0) || + (g_atoi(val) != 0)) + { + reply = 1; + } + else + { + g_writeln("This channel is disabled: %s", name); + } + break; /* stop loop - item found*/ + } + } + } + return reply; +} +/* internal function only used once per session + * creates the list of allowed channels and store the information + * in wm struct */ +void init_channel_allowed(struct xrdp_wm* wm) +{ + int error; + int i; + char channelname[MAX_CHANNEL_NAME]; + int index = 0; + int allowindex = 0; + struct list* names; + struct list* values; + /* first reset allowedchannels */ + for (i = 0; i < MAX_NR_CHANNELS; i++) + { + /* 0 is a valid channel so we use -1 to mark the index as unused */ + wm->allowedchannels[i] = -1; + } + names = list_create(); + values = list_create(); + if (read_allowed_channel_names(names, values)) + { + do + { + /* libxrdp_query_channel return 1 on error*/ + error = libxrdp_query_channel(wm->session, index, channelname,NULL); + if (error == 0) + { + /* examples of channel names: rdpdr ; rdpsnd ; drdynvc ; cliprdr */ + if (is_name_in_lists(channelname, names, values)) + { + g_writeln("The following channel is allowed: %s", channelname); + wm->allowedchannels[allowindex] = index; + allowindex++; + if (allowindex >= MAX_NR_CHANNELS) + { + g_writeln("Programming error in is_channel_allowed"); + error = 1; /* end loop */ + } + } + else + { + g_writeln("The following channel is not allowed: %s",channelname); + } + index++; + } + } while ((error == 0) && (index < MAX_NR_CHANNELS)); + } + else + { + g_writeln("Error reading channel section in inifile"); + } + list_delete(names); + list_delete(values); +} + +/*****************************************************************************/ +/* This function returns 1 if the channelID is allowed by rule set + * returns 0 if not allowed */ +int DEFAULT_CC is_channel_allowed(struct xrdp_wm* wm, int channel_id) +{ + int i; + int reply = 0; /* not allowed */ + /* The first time each client is using this function we have to + * define the list of allowed channels */ + if (wm->allowedinitialized == 0) + { + init_channel_allowed(wm); + g_writeln("allow channel list initialized"); + wm->allowedinitialized = 1; + } + for(i = 0; i < MAX_NR_CHANNELS; i++) + { + if (channel_id == wm->allowedchannels[i]) + { + /*g_writeln("Channel allowed: %d",channel_id);*/ + reply = 1; /*channel allowed*/ + break; + } + else if (wm->allowedchannels[i] == -1) + { + /* We are in the unused space of the allowedchannels list + * We can end the loop */ + break; + } + } + /*if (reply == 0) + { + g_writeln("This channel is NOT allowed: %d",channel_id) ; + }*/ + return reply; +} /*****************************************************************************/ +/*return 0 if the index is not found*/ int DEFAULT_CC server_query_channel(struct xrdp_mod* mod, int index, char* channel_name, int* channel_flags) @@ -1622,10 +2007,244 @@ server_send_to_channel(struct xrdp_mod* mod, int channel_id, struct xrdp_wm* wm; wm = (struct xrdp_wm*)(mod->wm); - if (wm->mm->usechansrv) + if (is_channel_allowed(wm, channel_id)) + { + if (wm->mm->usechansrv) + { + return 1; + } + return libxrdp_send_to_channel(wm->session, channel_id, data, data_len, + total_data_len, flags); + } + else + { + return 1; + } +} + +/*****************************************************************************/ +int DEFAULT_CC +server_create_os_surface(struct xrdp_mod* mod, int rdpindex, + int width, int height) +{ + struct xrdp_wm* wm; + struct xrdp_bitmap* bitmap; + int error; + + wm = (struct xrdp_wm*)(mod->wm); + bitmap = xrdp_bitmap_create(width, height, wm->screen->bpp, + WND_TYPE_OFFSCREEN, wm); + error = xrdp_cache_add_os_bitmap(wm->cache, bitmap, rdpindex); + if (error != 0) { + g_writeln("server_create_os_surface: xrdp_cache_add_os_bitmap failed"); return 1; } - return libxrdp_send_to_channel(wm->session, channel_id, data, data_len, - total_data_len, flags); + bitmap->item_index = rdpindex; + bitmap->id = rdpindex; + return 0; +} + +/*****************************************************************************/ +int DEFAULT_CC +server_switch_os_surface(struct xrdp_mod* mod, int rdpindex) +{ + struct xrdp_wm* wm; + struct xrdp_os_bitmap_item* bi; + struct xrdp_painter* p; + + //g_writeln("server_switch_os_surface: id 0x%x", id); + wm = (struct xrdp_wm*)(mod->wm); + if (rdpindex == -1) + { + //g_writeln("server_switch_os_surface: setting target_surface to screen"); + wm->target_surface = wm->screen; + p = (struct xrdp_painter*)(mod->painter); + if (p != 0) + { + //g_writeln("setting target"); + wm_painter_set_target(p); + } + return 0; + } + bi = xrdp_cache_get_os_bitmap(wm->cache, rdpindex); + if (bi != 0) + { + //g_writeln("server_switch_os_surface: setting target_surface to rdpid %d", id); + wm->target_surface = bi->bitmap; + p = (struct xrdp_painter*)(mod->painter); + if (p != 0) + { + //g_writeln("setting target"); + wm_painter_set_target(p); + } + } + else + { + g_writeln("server_switch_os_surface: error finding id %d", rdpindex); + } + return 0; +} + +/*****************************************************************************/ +int DEFAULT_CC +server_delete_os_surface(struct xrdp_mod* mod, int rdpindex) +{ + struct xrdp_wm* wm; + struct xrdp_painter* p; + + //g_writeln("server_delete_os_surface: id 0x%x", id); + wm = (struct xrdp_wm*)(mod->wm); + if (wm->target_surface->type == WND_TYPE_OFFSCREEN) + { + if (wm->target_surface->id == rdpindex) + { + g_writeln("server_delete_os_surface: setting target_surface to screen"); + wm->target_surface = wm->screen; + p = (struct xrdp_painter*)(mod->painter); + if (p != 0) + { + //g_writeln("setting target"); + wm_painter_set_target(p); + } + } + } + xrdp_cache_remove_os_bitmap(wm->cache, rdpindex); + return 0; +} + +/*****************************************************************************/ +int DEFAULT_CC +server_paint_rect_os(struct xrdp_mod* mod, int x, int y, int cx, int cy, + int rdpindex, int srcx, int srcy) +{ + struct xrdp_wm* wm; + struct xrdp_bitmap* b; + struct xrdp_painter* p; + struct xrdp_os_bitmap_item* bi; + + p = (struct xrdp_painter*)(mod->painter); + if (p == 0) + { + return 0; + } + wm = (struct xrdp_wm*)(mod->wm); + bi = xrdp_cache_get_os_bitmap(wm->cache, rdpindex); + if (bi != 0) + { + b = bi->bitmap; + xrdp_painter_copy(p, b, wm->target_surface, x, y, cx, cy, srcx, srcy); + } + else + { + g_writeln("server_paint_rect_os: error finding id %d", rdpindex); + } + return 0; +} + +/*****************************************************************************/ +int DEFAULT_CC +server_set_hints(struct xrdp_mod* mod, int hints, int mask) +{ + struct xrdp_wm* wm; + + wm = (struct xrdp_wm*)(mod->wm); + if (mask & 1) + { + if (hints & 1) + { + wm->hints |= 1; + } + else + { + wm->hints &= ~1; + } + } + return 0; +} + +/*****************************************************************************/ +int DEFAULT_CC +server_window_new_update(struct xrdp_mod* mod, int window_id, + struct rail_window_state_order* window_state, + int flags) +{ + struct xrdp_wm* wm; + + wm = (struct xrdp_wm*)(mod->wm); + return libxrdp_window_new_update(wm->session, window_id, + window_state, flags); +} + +/*****************************************************************************/ +int DEFAULT_CC +server_window_delete(struct xrdp_mod* mod, int window_id) +{ + struct xrdp_wm* wm; + + wm = (struct xrdp_wm*)(mod->wm); + return libxrdp_window_delete(wm->session, window_id); +} + +/*****************************************************************************/ +int DEFAULT_CC +server_window_icon(struct xrdp_mod* mod, int window_id, int cache_entry, + int cache_id, struct rail_icon_info* icon_info, + int flags) +{ + struct xrdp_wm* wm; + + wm = (struct xrdp_wm*)(mod->wm); + return libxrdp_window_icon(wm->session, window_id, cache_entry, cache_id, + icon_info, flags); +} + +/*****************************************************************************/ +int DEFAULT_CC +server_window_cached_icon(struct xrdp_mod* mod, + int window_id, int cache_entry, + int cache_id, int flags) +{ + struct xrdp_wm* wm; + + wm = (struct xrdp_wm*)(mod->wm); + return libxrdp_window_cached_icon(wm->session, window_id, cache_entry, + cache_id, flags); +} + +/*****************************************************************************/ +int DEFAULT_CC +server_notify_new_update(struct xrdp_mod* mod, + int window_id, int notify_id, + struct rail_notify_state_order* notify_state, + int flags) +{ + struct xrdp_wm* wm; + + wm = (struct xrdp_wm*)(mod->wm); + return libxrdp_notify_new_update(wm->session, window_id, notify_id, + notify_state, flags); +} + +/*****************************************************************************/ +int DEFAULT_CC +server_notify_delete(struct xrdp_mod* mod, int window_id, + int notify_id) +{ + struct xrdp_wm* wm; + + wm = (struct xrdp_wm*)(mod->wm); + return libxrdp_notify_delete(wm->session, window_id, notify_id); +} + +/*****************************************************************************/ +int DEFAULT_CC +server_monitored_desktop(struct xrdp_mod* mod, + struct rail_monitored_desktop_order* mdo, + int flags) +{ + struct xrdp_wm* wm; + + wm = (struct xrdp_wm*)(mod->wm); + return libxrdp_monitored_desktop(wm->session, mdo, flags); } diff --git a/xrdp/xrdp_painter.c b/xrdp/xrdp_painter.c index 38644ae1..b91be16d 100644 --- a/xrdp/xrdp_painter.c +++ b/xrdp/xrdp_painter.c @@ -14,7 +14,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. xrdp: A Remote Desktop Protocol server. - Copyright (C) Jay Sorg 2004-2010 + Copyright (C) Jay Sorg 2004-2012 painter, gc @@ -49,6 +49,50 @@ xrdp_painter_delete(struct xrdp_painter* self) /*****************************************************************************/ int APP_CC +wm_painter_set_target(struct xrdp_painter* self) +{ + int surface_index; + int index; + struct list* del_list; + + if (self->wm->target_surface->type == WND_TYPE_SCREEN) + { + if (self->wm->current_surface_index != 0xffff) + { + libxrdp_orders_send_switch_os_surface(self->session, 0xffff); + self->wm->current_surface_index = 0xffff; + } + } + else if (self->wm->target_surface->type == WND_TYPE_OFFSCREEN) + { + surface_index = self->wm->target_surface->item_index; + if (surface_index != self->wm->current_surface_index) + { + if (self->wm->target_surface->tab_stop == 0) /* tab_stop is hack */ + { + del_list = self->wm->cache->xrdp_os_del_list; + index = list_index_of(del_list, surface_index); + list_remove_item(del_list, index); + libxrdp_orders_send_create_os_surface(self->session, surface_index, + self->wm->target_surface->width, + self->wm->target_surface->height, + del_list); + self->wm->target_surface->tab_stop = 1; + list_clear(del_list); + } + libxrdp_orders_send_switch_os_surface(self->session, surface_index); + self->wm->current_surface_index = surface_index; + } + } + else + { + g_writeln("xrdp_painter_begin_update: bad target_surface"); + } + return 0; +} + +/*****************************************************************************/ +int APP_CC xrdp_painter_begin_update(struct xrdp_painter* self) { if (self == 0) @@ -56,6 +100,7 @@ xrdp_painter_begin_update(struct xrdp_painter* self) return 0; } libxrdp_orders_init(self->session); + wm_painter_set_target(self); return 0; } @@ -82,6 +127,7 @@ xrdp_painter_font_needed(struct xrdp_painter* self) return 0; } +#if 0 /*****************************************************************************/ /* returns boolean, true if there is something to draw */ static int APP_CC @@ -133,6 +179,7 @@ xrdp_painter_clip_adj(struct xrdp_painter* self, int* x, int* y, *y = *y + dy; return 1; } +#endif /*****************************************************************************/ int APP_CC @@ -155,6 +202,7 @@ xrdp_painter_clr_clip(struct xrdp_painter* self) return 0; } +#if 0 /*****************************************************************************/ static int APP_CC xrdp_painter_rop(int rop, int src, int dst) @@ -180,6 +228,7 @@ xrdp_painter_rop(int rop, int src, int dst) } return dst; } +#endif /*****************************************************************************/ int APP_CC @@ -271,7 +320,7 @@ xrdp_painter_setup_brush(struct xrdp_painter* self, /* fill in an area of the screen with one color */ int APP_CC xrdp_painter_fill_rect(struct xrdp_painter* self, - struct xrdp_bitmap* bitmap, + struct xrdp_bitmap* dst, int x, int y, int cx, int cy) { struct xrdp_rect clip_rect; @@ -291,14 +340,21 @@ xrdp_painter_fill_rect(struct xrdp_painter* self, /* todo data */ - if (bitmap->type == WND_TYPE_BITMAP) /* 0 */ + if (dst->type == WND_TYPE_BITMAP) /* 0 */ { return 0; } - xrdp_bitmap_get_screen_clip(bitmap, self, &clip_rect, &dx, &dy); + xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy); region = xrdp_region_create(self->wm); - xrdp_wm_get_vis_region(self->wm, bitmap, x, y, cx, cy, region, - self->clip_children); + if (dst->type != WND_TYPE_OFFSCREEN) + { + xrdp_wm_get_vis_region(self->wm, dst, x, y, cx, cy, region, + self->clip_children); + } + else + { + xrdp_region_add_rect(region, &clip_rect); + } x += dx; y += dy; if (self->mix_mode == 0 && self->rop == 0xcc) @@ -372,7 +428,7 @@ xrdp_painter_fill_rect(struct xrdp_painter* self, /*****************************************************************************/ int APP_CC xrdp_painter_draw_text(struct xrdp_painter* self, - struct xrdp_bitmap* bitmap, + struct xrdp_bitmap* dst, int x, int y, const char* text) { int i; @@ -409,7 +465,7 @@ xrdp_painter_draw_text(struct xrdp_painter* self, /* todo data */ - if (bitmap->type == 0) + if (dst->type == 0) { return 0; } @@ -439,10 +495,17 @@ xrdp_painter_draw_text(struct xrdp_painter* self, total_width += k; total_height = MAX(total_height, font_item->height); } - xrdp_bitmap_get_screen_clip(bitmap, self, &clip_rect, &dx, &dy); + xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy); region = xrdp_region_create(self->wm); - xrdp_wm_get_vis_region(self->wm, bitmap, x, y, total_width, total_height, - region, self->clip_children); + if (dst->type != WND_TYPE_OFFSCREEN) + { + xrdp_wm_get_vis_region(self->wm, dst, x, y, total_width, total_height, + region, self->clip_children); + } + else + { + xrdp_region_add_rect(region, &clip_rect); + } x += dx; y += dy; k = 0; @@ -470,7 +533,7 @@ xrdp_painter_draw_text(struct xrdp_painter* self, /*****************************************************************************/ int APP_CC xrdp_painter_draw_text2(struct xrdp_painter* self, - struct xrdp_bitmap* bitmap, + struct xrdp_bitmap* dst, int font, int flags, int mixmode, int clip_left, int clip_top, int clip_right, int clip_bottom, @@ -493,24 +556,32 @@ xrdp_painter_draw_text2(struct xrdp_painter* self, /* todo data */ - if (bitmap->type == WND_TYPE_BITMAP) + if (dst->type == WND_TYPE_BITMAP) { return 0; } - xrdp_bitmap_get_screen_clip(bitmap, self, &clip_rect, &dx, &dy); + xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy); region = xrdp_region_create(self->wm); - if (box_right - box_left > 1) + if (dst->type != WND_TYPE_OFFSCREEN) { - xrdp_wm_get_vis_region(self->wm, bitmap, box_left, box_top, - box_right - box_left, box_bottom - box_top, - region, self->clip_children); + if (box_right - box_left > 1) + { + xrdp_wm_get_vis_region(self->wm, dst, box_left, box_top, + box_right - box_left, box_bottom - box_top, + region, self->clip_children); + } + else + { + xrdp_wm_get_vis_region(self->wm, dst, clip_left, clip_top, + clip_right - clip_left, clip_bottom - clip_top, + region, self->clip_children); + } } else { - xrdp_wm_get_vis_region(self->wm, bitmap, clip_left, clip_top, - clip_right - clip_left, clip_bottom - clip_top, - region, self->clip_children); + xrdp_region_add_rect(region, &clip_rect); } + clip_left += dx; clip_top += dy; clip_right += dx; @@ -577,12 +648,19 @@ xrdp_painter_copy(struct xrdp_painter* self, { return 0; } - if (src == dst && src->wm->screen == src) + if (src->type == WND_TYPE_SCREEN) { xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy); region = xrdp_region_create(self->wm); - xrdp_wm_get_vis_region(self->wm, dst, x, y, cx, cy, - region, self->clip_children); + if (dst->type != WND_TYPE_OFFSCREEN) + { + xrdp_wm_get_vis_region(self->wm, dst, x, y, cx, cy, + region, self->clip_children); + } + else + { + xrdp_region_add_rect(region, &clip_rect); + } x += dx; y += dy; srcx += dx; @@ -599,13 +677,61 @@ xrdp_painter_copy(struct xrdp_painter* self, } xrdp_region_delete(region); } + else if (src->type == WND_TYPE_OFFSCREEN) + { + //g_writeln("xrdp_painter_copy: todo"); + + xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy); + region = xrdp_region_create(self->wm); + if (dst->type != WND_TYPE_OFFSCREEN) + { + //g_writeln("off screen to screen"); + xrdp_wm_get_vis_region(self->wm, dst, x, y, cx, cy, + region, self->clip_children); + } + else + { + //g_writeln("off screen to off screen"); + xrdp_region_add_rect(region, &clip_rect); + } + x += dx; + y += dy; + + palette_id = 0; + cache_id = 255; // todo + cache_idx = src->item_index; // todo + + k = 0; + while (xrdp_region_get_rect(region, k, &rect1) == 0) + { + if (rect_intersect(&rect1, &clip_rect, &rect2)) + { + MAKERECT(rect1, x, y, cx, cy); + if (rect_intersect(&rect2, &rect1, &draw_rect)) + { + libxrdp_orders_mem_blt(self->session, cache_id, palette_id, + x, y, cx, cy, self->rop, srcx, srcy, + cache_idx, &draw_rect); + } + } + k++; + } + xrdp_region_delete(region); + } else if (src->data != 0) /* todo, the non bitmap cache part is gone, it should be put back */ { xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy); region = xrdp_region_create(self->wm); - xrdp_wm_get_vis_region(self->wm, dst, x, y, cx, cy, - region, self->clip_children); + if (dst->type != WND_TYPE_OFFSCREEN) + { + xrdp_wm_get_vis_region(self->wm, dst, x, y, cx, cy, + region, self->clip_children); + } + else + { + xrdp_region_add_rect(region, &clip_rect); + } x += dx; y += dy; palette_id = 0; @@ -615,11 +741,11 @@ xrdp_painter_copy(struct xrdp_painter* self, i = srcx; while (i < (srcx + cx)) { - w = MIN(64, (srcx + cx) - i); - h = MIN(64, (srcy + cy) - j); + w = MIN(64, ((srcx + cx) - i)); + h = MIN(64, ((srcy + cy) - j)); b = xrdp_bitmap_create(w, h, self->wm->screen->bpp, 0, self->wm); xrdp_bitmap_copy_box_with_crc(src, b, i, j, w, h); - bitmap_id = xrdp_cache_add_bitmap(self->wm->cache, b); + bitmap_id = xrdp_cache_add_bitmap(self->wm->cache, b, self->wm->hints); cache_id = HIWORD(bitmap_id); cache_idx = LOWORD(bitmap_id); dstx = (x + i) - srcx; @@ -651,7 +777,7 @@ xrdp_painter_copy(struct xrdp_painter* self, /*****************************************************************************/ int APP_CC xrdp_painter_line(struct xrdp_painter* self, - struct xrdp_bitmap* bitmap, + struct xrdp_bitmap* dst, int x1, int y1, int x2, int y2) { struct xrdp_rect clip_rect; @@ -670,15 +796,22 @@ xrdp_painter_line(struct xrdp_painter* self, /* todo data */ - if (bitmap->type == WND_TYPE_BITMAP) + if (dst->type == WND_TYPE_BITMAP) { return 0; } - xrdp_bitmap_get_screen_clip(bitmap, self, &clip_rect, &dx, &dy); + xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy); region = xrdp_region_create(self->wm); - xrdp_wm_get_vis_region(self->wm, bitmap, MIN(x1, x2), MIN(y1, y2), - g_abs(x1 - x2) + 1, g_abs(y1 - y2) + 1, - region, self->clip_children); + if (dst->type != WND_TYPE_OFFSCREEN) + { + xrdp_wm_get_vis_region(self->wm, dst, MIN(x1, x2), MIN(y1, y2), + g_abs(x1 - x2) + 1, g_abs(y1 - y2) + 1, + region, self->clip_children); + } + else + { + xrdp_region_add_rect(region, &clip_rect); + } x1 += dx; y1 += dy; x2 += dx; diff --git a/xrdp/xrdp_process.c b/xrdp/xrdp_process.c index 905db928..7a88d524 100644 --- a/xrdp/xrdp_process.c +++ b/xrdp/xrdp_process.c @@ -161,7 +161,7 @@ xrdp_process_main_loop(struct xrdp_process* self) robjs[robjs_count++] = self->self_term_event; xrdp_wm_get_wait_objs(self->wm, robjs, &robjs_count, wobjs, &wobjs_count, &timeout); - trans_get_wait_objs(self->server_trans, robjs, &robjs_count, &timeout); + trans_get_wait_objs(self->server_trans, robjs, &robjs_count); /* wait */ if (g_obj_wait(robjs, robjs_count, wobjs, wobjs_count, timeout) != 0) { @@ -187,6 +187,10 @@ xrdp_process_main_loop(struct xrdp_process* self) } libxrdp_disconnect(self->session); } + else + { + g_writeln("xrdp_process_main_loop: libxrdp_process_incomming failed"); + } xrdp_process_mod_end(self); libxrdp_exit(self->session); self->session = 0; diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h index da9a062b..bf698dff 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -19,7 +19,13 @@ types */ +#define DEFAULT_STRING_LEN 255 +#define LOG_WINDOW_CHAR_PER_LINE 60 +#include "xrdp_rail.h" + +#define MAX_NR_CHANNELS 16 +#define MAX_CHANNEL_NAME 16 /* lib */ struct xrdp_mod { @@ -37,7 +43,7 @@ struct xrdp_mod int (*mod_get_wait_objs)(struct xrdp_mod* v, tbus* read_objs, int* rcount, tbus* write_objs, int* wcount, int* timeout); int (*mod_check_wait_objs)(struct xrdp_mod* v); - long mod_dumby[100 - 9]; /* align, 100 minus the number of mod + long mod_dumby[100 - 9]; /* align, 100 minus the number of mod functions above */ /* server functions */ int (*server_begin_update)(struct xrdp_mod* v); @@ -80,7 +86,38 @@ struct xrdp_mod char* data, int data_len, int total_data_len, int flags); int (*server_bell_trigger)(struct xrdp_mod* v); - long server_dumby[100 - 25]; /* align, 100 minus the number of server + /* off screen bitmaps */ + int (*server_create_os_surface)(struct xrdp_mod* v, int rdpindex, + int width, int height); + int (*server_switch_os_surface)(struct xrdp_mod* v, int rdpindex); + int (*server_delete_os_surface)(struct xrdp_mod* v, int rdpindex); + int (*server_paint_rect_os)(struct xrdp_mod* mod, int x, int y, + int cx, int cy, + int rdpindex, int srcx, int srcy); + int (*server_set_hints)(struct xrdp_mod* mod, int hints, int mask); + /* rail */ + int (*server_window_new_update)(struct xrdp_mod* mod, int window_id, + struct rail_window_state_order* window_state, + int flags); + int (*server_window_delete)(struct xrdp_mod* mod, int window_id); + int (*server_window_icon)(struct xrdp_mod* mod, + int window_id, int cache_entry, int cache_id, + struct rail_icon_info* icon_info, + int flags); + int (*server_window_cached_icon)(struct xrdp_mod* mod, + int window_id, int cache_entry, + int cache_id, int flags); + int (*server_notify_new_update)(struct xrdp_mod* mod, + int window_id, int notify_id, + struct rail_notify_state_order* notify_state, + int flags); + int (*server_notify_delete)(struct xrdp_mod* mod, int window_id, + int notify_id); + int (*server_monitored_desktop)(struct xrdp_mod* mod, + struct rail_monitored_desktop_order* mdo, + int flags); + + long server_dumby[100 - 37]; /* align, 100 minus the number of server functions above */ /* common */ long handle; /* pointer to self as int */ @@ -176,6 +213,7 @@ struct xrdp_cache int brush_stamp; struct xrdp_brush_item brush_items[64]; struct xrdp_os_bitmap_item os_bitmap_items[2000]; + struct list* xrdp_os_del_list; }; struct xrdp_mm @@ -275,6 +313,11 @@ struct xrdp_wm struct xrdp_font* default_font; struct xrdp_keymap keymap; int hide_log_window; + struct xrdp_bitmap* target_surface; /* either screen or os surface */ + int current_surface_index; + int hints; + int allowedchannels[MAX_NR_CHANNELS]; + int allowedinitialized ; }; /* rdp process */ @@ -299,6 +342,7 @@ struct xrdp_listen struct trans* listen_trans; /* in tcp listen mode */ struct list* process_list; tbus pro_done_event; + struct xrdp_startup_params* startup_params; }; /* region */ @@ -384,12 +428,12 @@ struct xrdp_bitmap #define DEFAULT_ELEMENT_TOP 35 #define DEFAULT_BUTTON_W 60 #define DEFAULT_BUTTON_H 23 -#define DEFAULT_COMBO_W 140 +#define DEFAULT_COMBO_W 210 #define DEFAULT_COMBO_H 21 -#define DEFAULT_EDIT_W 140 +#define DEFAULT_EDIT_W 210 #define DEFAULT_EDIT_H 21 -#define DEFAULT_WND_LOGIN_W 400 -#define DEFAULT_WND_LOGIN_H 200 +#define DEFAULT_WND_LOGIN_W 500 +#define DEFAULT_WND_LOGIN_H 250 #define DEFAULT_WND_HELP_W 340 #define DEFAULT_WND_HELP_H 300 #define DEFAULT_WND_LOG_W 400 @@ -420,4 +464,5 @@ struct xrdp_startup_params int no_daemon; int help; int version; + int fork; }; diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c index 7d15c3d0..7883d33e 100644 --- a/xrdp/xrdp_wm.c +++ b/xrdp/xrdp_wm.c @@ -56,6 +56,8 @@ xrdp_wm_create(struct xrdp_process* owner, /* this will use built in keymap or load from file */ get_keymaps(self->session->client_info->keylayout, &(self->keymap)); xrdp_wm_set_login_mode(self, 0); + self->target_surface = self->screen; + self->current_surface_index = 0xffff; /* screen */ return self; } @@ -1389,21 +1391,25 @@ xrdp_wm_process_channel_data(struct xrdp_wm* self, tbus param3, tbus param4) { int rv; - + int chanid ; rv = 1; if (self->mm->mod != 0) - { - if (self->mm->usechansrv) + { + chanid = LOWORD(param1); + if(is_channel_allowed(self, chanid)) { - rv = xrdp_mm_process_channel_data(self->mm, param1, param2, + if (self->mm->usechansrv) + { + rv = xrdp_mm_process_channel_data(self->mm, param1, param2, param3, param4); - } - else - { - if (self->mm->mod->mod_event != 0) + } + else { - rv = self->mm->mod->mod_event(self->mm->mod, 0x5555, param1, param2, + if (self->mm->mod->mod_event != 0) + { + rv = self->mm->mod->mod_event(self->mm->mod, 0x5555, param1, param2, param3, param4); + } } } } @@ -1554,6 +1560,21 @@ xrdp_wm_log_wnd_notify(struct xrdp_bitmap* wnd, return 0; } + void add_string_to_logwindow(char *msg,struct list* log) + { + + char *new_part_message; + char *current_pointer = msg ; + int processedlen = 0; + do{ + new_part_message = g_strndup(current_pointer,LOG_WINDOW_CHAR_PER_LINE) ; + g_writeln(new_part_message); + list_add_item(log, (long)new_part_message); + processedlen = processedlen + g_strlen(new_part_message); + current_pointer = current_pointer + g_strlen(new_part_message) ; + }while((processedlen<g_strlen(msg)) && (processedlen<DEFAULT_STRING_LEN)); + } + /*****************************************************************************/ int APP_CC xrdp_wm_log_msg(struct xrdp_wm* self, char* msg) @@ -1568,7 +1589,7 @@ xrdp_wm_log_msg(struct xrdp_wm* self, char* msg) { return 0; } - list_add_item(self->log, (long)g_strdup(msg)); + add_string_to_logwindow(msg,self->log); if (self->log_wnd == 0) { w = DEFAULT_WND_LOG_W; diff --git a/xrdp/xrdpwin.c b/xrdp/xrdpwin.c index d2c2d0f3..849f7112 100644 --- a/xrdp/xrdpwin.c +++ b/xrdp/xrdpwin.c @@ -140,7 +140,7 @@ pipe_sig(int sig_num) /*****************************************************************************/ void APP_CC -g_loop(void) +g_process_waiting_function(void) { tc_mutex_lock(g_sync_mutex); if (g_sync_command != 0) diff --git a/xrdpapi/Makefile.am b/xrdpapi/Makefile.am new file mode 100644 index 00000000..88ef100e --- /dev/null +++ b/xrdpapi/Makefile.am @@ -0,0 +1,24 @@ +EXTRA_DIST = xrdpapi.h + +EXTRA_DEFINES = +EXTRA_INCLUDES = +EXTRA_LIBS = +EXTRA_FLAGS = + +AM_CFLAGS = \ + $(EXTRA_DEFINES) + +INCLUDES = \ + $(EXTRA_INCLUDES) + +lib_LTLIBRARIES = \ + libxrdpapi.la + +libxrdpapi_la_SOURCES = \ + xrdpapi.c + +libxrdpapi_la_LDFLAGS = \ + $(EXTRA_FLAGS) + +libxrdpapi_la_LIBADD = \ + $(EXTRA_LIBS) diff --git a/xrdpapi/simple.c b/xrdpapi/simple.c new file mode 100644 index 00000000..a2c0f875 --- /dev/null +++ b/xrdpapi/simple.c @@ -0,0 +1,94 @@ + + +// xrdp_chan_test.cpp : Basic test for virtual channel use. + +// These headers are required for the windows terminal services calls. +#include "xrdpapi.h" +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +#define DSIZE (1024 * 4) + +int main() +{ + + // Initialize the data for send/receive + void* hFile; + char* data; + char* data1; + data = (char*)malloc(DSIZE); + data1 = (char*)malloc(DSIZE); + int ret; + void* vcFileHandlePtr = NULL; + memset(data, 0xca, DSIZE); + memset(data1, 0, DSIZE); + unsigned int written = 0; + + // Open the skel channel in current session + + //void* channel = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, "skel", 0); + void* channel = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, "TSMF", WTS_CHANNEL_OPTION_DYNAMIC); + ret = WTSVirtualChannelQuery(channel, WTSVirtualFileHandle, vcFileHandlePtr, &written); + + // Write the data to the channel + ret = WTSVirtualChannelWrite(channel, data, DSIZE, &written); + if (!ret) + { + + long err = errno; + printf("error 1 0x%8.8x\n", err); + usleep(100000); + return 1; + } + else + { + printf("Sent bytes!\n"); + } + if (written != DSIZE) + { + long err = errno; + printf("error 2 0x%8.8x\n", err); + usleep(100000); + return 1; + } + else + { + printf("Read bytes!\n"); + } + ret = WTSVirtualChannelRead(channel, 100, data1, DSIZE, &written); + if (!ret) + { + long err = errno; + printf("error 3 0x%8.8x\n", err); + usleep(100000); + return 1; + } + if (written != DSIZE) + { + long err = errno; + printf("error 4 0x%8.8x\n", err); + usleep(100000); + return 1; + } + else + { + printf("Read bytes!\n"); + } + ret = WTSVirtualChannelClose(channel); + if (memcmp(data, data1, DSIZE) == 0) + { + } + else + { + printf("error data no match\n"); + return 1; + } + + printf("Done!\n"); + + usleep(100000); + return 0; +} diff --git a/xrdpapi/xrdpapi.c b/xrdpapi/xrdpapi.c new file mode 100644 index 00000000..694b3800 --- /dev/null +++ b/xrdpapi/xrdpapi.c @@ -0,0 +1,383 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Thomas Goddard 2012 + * Copyright (C) Jay Sorg 2012 + * + * 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. + */ + +/* do not use os_calls in here */ + +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { printf _args ; printf("\n"); } } while (0) + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/un.h> + +#include "xrdpapi.h" + +struct wts_obj +{ + int fd; + int status; + char name[8]; + char dname[128]; + int display_num; + int flags; +}; + +/*****************************************************************************/ +static int +get_display_num_from_display(char* display_text) +{ + int index; + int mode; + int host_index; + int disp_index; + int scre_index; + char host[256]; + char disp[256]; + char scre[256]; + + index = 0; + host_index = 0; + disp_index = 0; + scre_index = 0; + mode = 0; + while (display_text[index] != 0) + { + if (display_text[index] == ':') + { + mode = 1; + } + else if (display_text[index] == '.') + { + mode = 2; + } + else if (mode == 0) + { + host[host_index] = display_text[index]; + host_index++; + } + else if (mode == 1) + { + disp[disp_index] = display_text[index]; + disp_index++; + } + else if (mode == 2) + { + scre[scre_index] = display_text[index]; + scre_index++; + } + index++; + } + host[host_index] = 0; + disp[disp_index] = 0; + scre[scre_index] = 0; + return atoi(disp); +} + +/*****************************************************************************/ +void* +WTSVirtualChannelOpen(void* hServer, unsigned int SessionId, + const char* pVirtualName) +{ + if (hServer != WTS_CURRENT_SERVER_HANDLE) + { + return 0; + } + return WTSVirtualChannelOpenEx(SessionId, pVirtualName, 0); +} + +/*****************************************************************************/ +static int +can_send(int sck, int millis) +{ + struct timeval time; + fd_set wfds; + int select_rv; + + FD_ZERO(&wfds); + FD_SET(sck, &wfds); + time.tv_sec = millis / 1000; + time.tv_usec = (millis * 1000) % 1000000; + select_rv = select(sck + 1, 0, &wfds, 0, &time); + if (select_rv > 0) + { + return 1; + } + return 0; +} + +/*****************************************************************************/ +static int +can_recv(int sck, int millis) +{ + struct timeval time; + fd_set rfds; + int select_rv; + + FD_ZERO(&rfds); + FD_SET(sck, &rfds); + time.tv_sec = millis / 1000; + time.tv_usec = (millis * 1000) % 1000000; + select_rv = select(sck + 1, &rfds, 0, 0, &time); + if (select_rv > 0) + { + return 1; + } + return 0; +} + +/*****************************************************************************/ +static int +send_init(struct wts_obj* wts) +{ + char initmsg[64]; + + memset(initmsg, 0, 64); + strncpy(initmsg, wts->name, 8); + initmsg[16] = (wts->flags >> 0) & 0xff; + initmsg[17] = (wts->flags >> 8) & 0xff; + initmsg[18] = (wts->flags >> 16) & 0xff; + initmsg[19] = (wts->flags >> 24) & 0xff; + LLOGLN(10, ("send_init: sending %s", initmsg)); + if (!can_send(wts->fd, 500)) + { + return 1; + } + if (send(wts->fd, initmsg, 64, 0) != 64) + { + return 1; + } + LLOGLN(10, ("send_init: send ok!")); + return 0; +} + +/*****************************************************************************/ +void* +WTSVirtualChannelOpenEx(unsigned int SessionId, + const char* pVirtualName, + unsigned int flags) +{ + struct wts_obj* wts; + char* display_text; + struct sockaddr_un s; + int bytes; + unsigned long llong; + + if (SessionId != WTS_CURRENT_SESSION) + { + LLOGLN(0, ("WTSVirtualChannelOpenEx: SessionId bad")); + return 0; + } + wts = (struct wts_obj*)malloc(sizeof(struct wts_obj)); + memset(wts, 0, sizeof(struct wts_obj)); + wts->fd = -1; + wts->flags = flags; + display_text = getenv("DISPLAY"); + if (display_text != 0) + { + wts->display_num = get_display_num_from_display(display_text); + } + if (wts->display_num > 0) + { + wts->fd = socket(AF_UNIX, SOCK_STREAM, 0); + /* set non blocking */ + llong = fcntl(wts->fd, F_GETFL); + llong = llong | O_NONBLOCK; + fcntl(wts->fd, F_SETFL, llong); + /* connect to session chansrv */ + memset(&s, 0, sizeof(struct sockaddr_un)); + s.sun_family = AF_UNIX; + bytes = sizeof(s.sun_path); + snprintf(s.sun_path, bytes - 1, "/tmp/.xrdp/xrdpapi_%d", wts->display_num); + s.sun_path[bytes - 1] = 0; + bytes = sizeof(struct sockaddr_un); + if (connect(wts->fd, (struct sockaddr*)&s, bytes) == 0) + { + LLOGLN(10, ("WTSVirtualChannelOpenEx: connected ok, name %s", pVirtualName)); + strncpy(wts->name, pVirtualName, 8); + /* wait for connection to complete and send init */ + if (send_init(wts) == 0) + { + /* all ok */ + wts->status = 1; + } + } + } + else + { + LLOGLN(0, ("WTSVirtualChannelOpenEx: display is 0")); + } + return wts; +} + +/*****************************************************************************/ +int +WTSVirtualChannelWrite(void* hChannelHandle, const char* Buffer, + unsigned int Length, unsigned int* pBytesWritten) +{ + struct wts_obj* wts; + int error; + int lerrno; + + wts = (struct wts_obj*)hChannelHandle; + if (wts == 0) + { + return 0; + } + if (wts->status != 1) + { + return 0; + } + if (can_send(wts->fd, 0)) + { + error = send(wts->fd, Buffer, Length, 0); + if (error == -1) + { + lerrno = errno; + if ((lerrno == EWOULDBLOCK) || (lerrno == EAGAIN) || + (lerrno == EINPROGRESS)) + { + *pBytesWritten = 0; + return 1; + } + return 0; + } + else if (error == 0) + { + return 0; + } + else if (error > 0) + { + *pBytesWritten = error; + return 1; + } + } + *pBytesWritten = 0; + return 1; +} + +/*****************************************************************************/ +int +WTSVirtualChannelRead(void* hChannelHandle, unsigned int TimeOut, + char* Buffer, unsigned int BufferSize, + unsigned int* pBytesRead) +{ + struct wts_obj* wts; + int error; + int lerrno; + + wts = (struct wts_obj*)hChannelHandle; + if (wts == 0) + { + return 0; + } + if (wts->status != 1) + { + return 0; + } + if (can_recv(wts->fd, TimeOut)) + { + error = recv(wts->fd, Buffer, BufferSize, 0); + if (error == -1) + { + lerrno = errno; + if ((lerrno == EWOULDBLOCK) || (lerrno == EAGAIN) || + (lerrno == EINPROGRESS)) + { + *pBytesRead = 0; + return 1; + } + return 0; + } + else if (error == 0) + { + return 0; + } + else if (error > 0) + { + *pBytesRead = error; + return 1; + } + } + *pBytesRead = 0; + return 1; +} + +/*****************************************************************************/ +int +WTSVirtualChannelClose(void* hChannelHandle) +{ + struct wts_obj* wts; + + wts = (struct wts_obj*)hChannelHandle; + if (wts == 0) + { + return 0; + } + if (wts->fd != -1) + { + close(wts->fd); + } + free(wts); + return 1; +} + +/*****************************************************************************/ +int +WTSVirtualChannelQuery(void* hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, + void** ppBuffer, unsigned int* pBytesReturned) +{ + struct wts_obj* wts; + + wts = (struct wts_obj*)hChannelHandle; + if (wts == 0) + { + return 0; + } + if (wts->status != 1) + { + return 0; + } + if (WtsVirtualClass == WTSVirtualFileHandle) + { + *pBytesReturned = 4; + *ppBuffer = malloc(4); + memcpy(*ppBuffer, &(wts->fd), 4); + } + return 1; +} + +/*****************************************************************************/ +void +WTSFreeMemory(void* pMemory) +{ + if (pMemory != 0) + { + free(pMemory); + } +} diff --git a/xrdpapi/xrdpapi.h b/xrdpapi/xrdpapi.h new file mode 100644 index 00000000..65b6db42 --- /dev/null +++ b/xrdpapi/xrdpapi.h @@ -0,0 +1,76 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Thomas Goddard 2012 + * Copyright (C) Jay Sorg 2012 + * + * 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. + */ +/* + xrdpapi header, do not use os_calls.h, arch.h or any xrdp internal headers + this file is included in 3rd party apps +*/ + +#if !defined(XRDPAPI_H_) +#define XRDPAPI_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define WTS_CURRENT_SERVER_HANDLE 0 +#define WTS_CURRENT_SESSION 0xffffffff +#define WTS_CHANNEL_OPTION_DYNAMIC 0x00000001 +#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_LOW 0x00000000 +#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_MED 0x00000002 +#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_HIGH 0x00000004 +#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_REAL 0x00000006 +#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_COMPRESS 0x00000008 + +typedef enum _WTS_VIRTUAL_CLASS +{ + WTSVirtualClientData, + WTSVirtualFileHandle +} WTS_VIRTUAL_CLASS; + +/* + Reference: + http://msdn.microsoft.com/en-us/library/windows/desktop/aa383464(v=vs.85).aspx +*/ +void* +WTSVirtualChannelOpen(void* hServer, unsigned int SessionId, + const char* pVirtualName); +void* +WTSVirtualChannelOpenEx(unsigned int SessionId, + const char* pVirtualName, + unsigned int flags); +int +WTSVirtualChannelWrite(void* hChannelHandle, const char* Buffer, + unsigned int Length, unsigned int* pBytesWritten); +int +WTSVirtualChannelRead(void* hChannelHandle, unsigned int TimeOut, + char* Buffer, unsigned int BufferSize, + unsigned int* pBytesRead); +int +WTSVirtualChannelClose(void* hChannelHandle); +int +WTSVirtualChannelQuery(void* hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, + void** ppBuffer, unsigned int* pBytesReturned); +void +WTSFreeMemory(void* pMemory); + +#ifdef __cplusplus +} +#endif + +#endif /* XRDPAPI_H_ */ diff --git a/xup/Makefile.am b/xup/Makefile.am index 41d7e3f5..544c957a 100644 --- a/xup/Makefile.am +++ b/xup/Makefile.am @@ -15,4 +15,4 @@ lib_LTLIBRARIES = \ libxup_la_SOURCES = xup.c libxup_la_LIBADD = \ - $(top_srcdir)/common/libcommon.la + $(top_builddir)/common/libcommon.la @@ -279,9 +279,9 @@ lib_mod_connect(struct mod* mod) else { mod->sck = g_tcp_socket(); + g_tcp_set_non_blocking(mod->sck); + g_tcp_set_no_delay(mod->sck); } - g_tcp_set_non_blocking(mod->sck); - g_tcp_set_no_delay(mod->sck); mod->server_msg(mod, "connecting...", 0); if (use_uds) { @@ -467,6 +467,95 @@ lib_mod_event(struct mod* mod, int msg, tbus param1, tbus param2, /******************************************************************************/ /* return error */ +static int APP_CC +process_server_window_new_update(struct mod* mod, struct stream* s) +{ + int flags; + int window_id; + int title_bytes; + int index; + int bytes; + int rv; + struct rail_window_state_order rwso; + + g_memset(&rwso, 0, sizeof(rwso)); + in_uint32_le(s, window_id); + in_uint32_le(s, rwso.owner_window_id); + in_uint32_le(s, rwso.style); + in_uint32_le(s, rwso.extended_style); + in_uint32_le(s, rwso.show_state); + in_uint16_le(s, title_bytes); + if (title_bytes > 0) + { + rwso.title_info = g_malloc(title_bytes + 1, 0); + in_uint8a(s, rwso.title_info, title_bytes); + rwso.title_info[title_bytes] = 0; + } + in_uint32_le(s, rwso.client_offset_x); + in_uint32_le(s, rwso.client_offset_y); + in_uint32_le(s, rwso.client_area_width); + in_uint32_le(s, rwso.client_area_height); + in_uint32_le(s, rwso.rp_content); + in_uint32_le(s, rwso.root_parent_handle); + in_uint32_le(s, rwso.window_offset_x); + in_uint32_le(s, rwso.window_offset_y); + in_uint32_le(s, rwso.window_client_delta_x); + in_uint32_le(s, rwso.window_client_delta_y); + in_uint32_le(s, rwso.window_width); + in_uint32_le(s, rwso.window_height); + in_uint16_le(s, rwso.num_window_rects); + if (rwso.num_window_rects > 0) + { + bytes = sizeof(struct rail_window_rect) * rwso.num_window_rects; + rwso.window_rects = (struct rail_window_rect*)g_malloc(bytes, 0); + for (index = 0; index < rwso.num_window_rects; index++) + { + in_uint16_le(s, rwso.window_rects[index].left); + in_uint16_le(s, rwso.window_rects[index].top); + in_uint16_le(s, rwso.window_rects[index].right); + in_uint16_le(s, rwso.window_rects[index].bottom); + } + } + in_uint32_le(s, rwso.visible_offset_x); + in_uint32_le(s, rwso.visible_offset_y); + in_uint16_le(s, rwso.num_visibility_rects); + if (rwso.num_visibility_rects > 0) + { + bytes = sizeof(struct rail_window_rect) * rwso.num_visibility_rects; + rwso.visibility_rects = (struct rail_window_rect*)g_malloc(bytes, 0); + for (index = 0; index < rwso.num_visibility_rects; index++) + { + in_uint16_le(s, rwso.visibility_rects[index].left); + in_uint16_le(s, rwso.visibility_rects[index].top); + in_uint16_le(s, rwso.visibility_rects[index].right); + in_uint16_le(s, rwso.visibility_rects[index].bottom); + } + } + in_uint32_le(s, flags); + mod->server_window_new_update(mod, window_id, &rwso, flags); + rv = 0; + g_free(rwso.title_info); + g_free(rwso.window_rects); + g_free(rwso.visibility_rects); + 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 lib_mod_process_orders(struct mod* mod, int type, struct stream* s) { @@ -483,6 +572,9 @@ lib_mod_process_orders(struct mod* mod, int type, struct stream* s) int y1; int x2; int y2; + int rdpid; + int hints; + int mask; int width; int height; int fgcolor; @@ -568,6 +660,42 @@ lib_mod_process_orders(struct mod* mod, int type, struct stream* s) in_uint8a(s, cur_mask, 32 * (32 / 8)); rv = mod->server_set_cursor(mod, x, y, cur_data, cur_mask); 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); + break; + case 21: + in_uint32_le(s, rdpid); + rv = mod->server_switch_os_surface(mod, rdpid); + break; + case 22: + in_uint32_le(s, rdpid); + rv = mod->server_delete_os_surface(mod, rdpid); + 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); + break; + case 24: /* server_set_hints */ + in_uint32_le(s, hints); + in_uint32_le(s, mask); + rv = mod->server_set_hints(mod, hints, mask); + break; + case 25: /* server_window_new_update */ + rv = process_server_window_new_update(mod, s); + break; + case 26: /* server_window_delete */ + rv = process_server_window_delete(mod, s); + break; default: g_writeln("lib_mod_process_orders: unknown order type %d", type); rv = 0; @@ -26,6 +26,7 @@ #include "os_calls.h" #include "defines.h" #include "xrdp_client_info.h" +#include "xrdp_rail.h" #define CURRENT_MOD_VER 2 @@ -88,7 +89,37 @@ struct mod char* data, int data_len, int total_data_len, int flags); int (*server_bell_trigger)(struct mod* v); - tbus server_dumby[100 - 25]; /* align, 100 minus the number of server + /* off screen bitmaps */ + int (*server_create_os_surface)(struct mod* v, int rdpindex, + int width, int height); + int (*server_switch_os_surface)(struct mod* v, int rdpindex); + int (*server_delete_os_surface)(struct mod* v, int rdpindex); + int (*server_paint_rect_os)(struct mod* v, int x, int y, + int cx, int cy, + int rdpindex, int srcx, int srcy); + int (*server_set_hints)(struct mod* v, int hints, int mask); + /* rail */ + int (*server_window_new_update)(struct mod* v, int window_id, + struct rail_window_state_order* window_state, + int flags); + int (*server_window_delete)(struct mod* v, int window_id); + int (*server_window_icon)(struct mod* v, + int window_id, int cache_entry, int cache_id, + struct rail_icon_info* icon_info, + int flags); + int (*server_window_cached_icon)(struct mod* v, + int window_id, int cache_entry, + int cache_id, int flags); + int (*server_notify_new_update)(struct mod* v, + int window_id, int notify_id, + struct rail_notify_state_order* notify_state, + int flags); + int (*server_notify_delete)(struct mod* v, int window_id, + int notify_id); + int (*server_monitored_desktop)(struct mod* v, + struct rail_monitored_desktop_order* mdo, + int flags); + tbus server_dumby[100 - 37]; /* align, 100 minus the number of server functions above */ /* common */ tbus handle; /* pointer to self as long */ |