diff --git a/Makefile.am b/Makefile.am
index 1b6a513..84e90a4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -10,4 +10,5 @@ SUBDIRS = \
   sesman \
   keygen \
   docs \
-  instfiles
+  instfiles \
+  dmx
diff --git a/common/defines.h b/common/defines.h
index 050eb5a..5fb1a42 100644
--- a/common/defines.h
+++ b/common/defines.h
@@ -89,5 +89,5 @@
   ((((f)->height * (((f)->width + 7) / 8)) + 3) & ~3);
 /* use crc for bitmap cache lookups */
 #define USE_CRC
-
+#define MAX_SESSIONS_LIMIT 128
 #endif
diff --git a/common/file.c b/common/file.c
index cf6f1e6..86aa3b8 100644
--- a/common/file.c
+++ b/common/file.c
@@ -86,7 +86,7 @@ l_file_read_sections(int fd, int max_file_size, struct list* names)
 }
 
 /*****************************************************************************/
-static int APP_CC
+int APP_CC
 file_read_line(struct stream* s, char* text)
 {
   int i;
@@ -155,7 +155,7 @@ file_read_line(struct stream* s, char* text)
 
 /*****************************************************************************/
 /* returns error */
-static int APP_CC
+int APP_CC
 file_split_name_value(char* text, char* name, char* value)
 {
   int len;
diff --git a/common/file.h b/common/file.h
index 9482a79..6c45db8 100644
--- a/common/file.h
+++ b/common/file.h
@@ -26,8 +26,13 @@
 #define FILE_H
 
 #include "arch.h"
+#include "parse.h"
 
 int APP_CC
+file_read_line(struct stream* s, char* text);
+int APP_CC
+file_split_name_value(char* text, char* name, char* value);
+int APP_CC
 file_read_sections(int fd, struct list* names);
 int APP_CC
 file_by_name_read_sections(const char* file_name, struct list* names);
diff --git a/common/os_calls.c b/common/os_calls.c
index b3a8043..e6ceace 100644
--- a/common/os_calls.c
+++ b/common/os_calls.c
@@ -60,6 +60,7 @@
 #include <string.h>
 #include <stdarg.h>
 #include <stdio.h>
+#include <dirent.h>
 #include <locale.h>
 
 #include "os_calls.h"
@@ -1626,6 +1627,13 @@ g_load_library(char* in)
 #if defined(_WIN32)
   return (long)LoadLibraryA(in);
 #else
+  char file[512];
+  void *handle;
+  g_snprintf(file, sizeof (file), XRDP_LIB_PATH "/%s", in);
+  file[sizeof (file) - 1] = '\0';
+  handle = dlopen(file, RTLD_LOCAL | RTLD_LAZY);
+  if (handle)
+    return (long) handle;
   return (long)dlopen(in, RTLD_LOCAL | RTLD_LAZY);
 #endif
 }
@@ -2030,3 +2038,54 @@ g_time2(void)
   return (int)(num_ticks * 10);
 #endif
 }
+
+/*****************************************************************************/
+/* returns 0 on error, else return handle */
+unsigned int APP_CC
+g_dir_open(const char * dir_name)
+{
+#if defined(_WIN32)
+  return 0;
+#else
+  return (unsigned int) opendir (dir_name);
+#endif
+}
+
+/*****************************************************************************/
+void APP_CC
+g_dir_close(unsigned int handle)
+{
+#if defined(_WIN32)
+#else
+  closedir ((DIR *) handle);
+#endif
+}
+
+/*****************************************************************************/
+const char* APP_CC
+g_dir_read_name(unsigned int handle)
+{
+#if defined(_WIN32)
+  return 0;
+#else
+  struct dirent *ent;
+
+  ent = readdir ((DIR *) handle);
+  if (!ent)
+    return 0;
+
+  return ent->d_name;
+#endif
+}
+
+/*****************************************************************************/
+/* returns -1 on error, else 0 is returned */
+int APP_CC
+g_gethostname(char *name, unsigned int len)
+{
+#if defined(_WIN32)
+  return -1;
+#else
+  return gethostname (name, len);
+#endif
+}
diff --git a/common/os_calls.h b/common/os_calls.h
index c9707ca..e4477a5 100644
--- a/common/os_calls.h
+++ b/common/os_calls.h
@@ -237,5 +237,13 @@ int APP_CC
 g_time1(void);
 int APP_CC
 g_time2(void);
+unsigned int APP_CC
+g_dir_open(const char * dir_name);
+void APP_CC
+g_dir_close(unsigned int handle);
+const char* APP_CC
+g_dir_read_name(unsigned int handle);
+int APP_CC
+g_gethostname(char *name, unsigned int len);
 
 #endif
diff --git a/common/xrdp_constants.h b/common/xrdp_constants.h
index f61c320..9532e77 100644
--- a/common/xrdp_constants.h
+++ b/common/xrdp_constants.h
@@ -430,6 +430,7 @@
 #define WND_TYPE_COMBO   7
 #define WND_TYPE_SPECIAL 8
 #define WND_TYPE_LISTBOX 9
+#define WND_TYPE_TILE    10
 
 /* button states */
 #define BUTTON_STATE_UP   0
diff --git a/configure.ac b/configure.ac
index 788c8a0..2de6359 100644
--- a/configure.ac
+++ b/configure.ac
@@ -19,19 +19,23 @@ AC_ARG_ENABLE(pamuserpass, AS_HELP_STRING([--enable-pamuserpass],
               [Build pam userpass support (default: no)]),
               [pamuserpass=true], [pamuserpass=false])
 AM_CONDITIONAL(SESMAN_PAMUSERPASS, [test x$pamuserpass = xtrue])
+PKG_CHECK_MODULES(DBUS, dbus-1)
+PKG_CHECK_MODULES(XAU, xau)
+PKG_CHECK_MODULES(XCB, xcb)
 libdir="${libdir}/xrdp/";
+AC_DEFINE_UNQUOTED([XRDP_LIB_PATH], ["${libdir}"], [xrdp lib dir])
 if test "x${prefix}" = "xNONE" ; then
 sysconfdir="/etc/";
 else
-AC_DEFINE_UNQUOTED([XRDP_CFG_PATH], ["${prefix}/etc/xrdp"], [xrdp config dir])
-AC_DEFINE_UNQUOTED([XRDP_CFG_FILE], ["${prefix}/etc/xrdp/xrdp.ini"], [xrdp config file])
-AC_DEFINE_UNQUOTED([XRDP_KEY_FILE], ["${prefix}/etc/xrdp/rsakeys.ini"], [xrdp key file])
-AC_DEFINE_UNQUOTED([XRDP_KEYMAP_FILE], ["${prefix}/etc/xrdp/km-%4.4x.ini"], [xrdp keymap file])
-AC_DEFINE_UNQUOTED([XRDP_PID_FILE], ["${prefix}/var/run/xrdp.pid"], [xrdp pid file])
+AC_DEFINE_UNQUOTED([XRDP_CFG_PATH], ["${sysconfdir}/xrdp"], [xrdp config dir])
+AC_DEFINE_UNQUOTED([XRDP_CFG_FILE], ["${sysconfdir}/xrdp/xrdp.ini"], [xrdp config file])
+AC_DEFINE_UNQUOTED([XRDP_KEY_FILE], ["${sysconfdir}/xrdp/rsakeys.ini"], [xrdp key file])
+AC_DEFINE_UNQUOTED([XRDP_KEYMAP_FILE], ["${sysconfdir}/xrdp/km-%4.4x.ini"], [xrdp keymap file])
+AC_DEFINE_UNQUOTED([XRDP_PID_FILE], ["${localstatedir}/run/xrdp.pid"], [xrdp pid file])
 AC_DEFINE_UNQUOTED([XRDP_SBIN_PATH], ["${prefix}/sbin"], [xrdp sbin dir])
 AC_DEFINE_UNQUOTED([XRDP_SHARE_PATH], ["${prefix}/share/xrdp"], [xrdp share dir])
-AC_DEFINE_UNQUOTED([SESMAN_PID_FILE], ["${prefix}/var/run/sesman.pid"], [sesman pid file])
-AC_DEFINE_UNQUOTED([SESMAN_CFG_FILE], ["${prefix}/etc/xrdp/sesman.ini"], [sesman config file])
+AC_DEFINE_UNQUOTED([SESMAN_PID_FILE], ["${localstatedir}/run/sesman.pid"], [sesman pid file])
+AC_DEFINE_UNQUOTED([SESMAN_CFG_FILE], ["${sysconfdir}/xrdp/sesman.ini"], [sesman config file])
 fi
 AC_CONFIG_FILES([Makefile
                  common/Makefile
@@ -49,6 +53,7 @@ AC_CONFIG_FILES([Makefile
                  docs/man/Makefile
                  instfiles/Makefile
                  instfiles/pam.d/Makefile
+                 dmx/Makefile
 ])
 #                 fontdump/Makefile
 #                 xrdp/cursors/Makefile
diff --git a/dmx/Makefile.am b/dmx/Makefile.am
new file mode 100644
index 0000000..d2cf026
--- /dev/null
+++ b/dmx/Makefile.am
@@ -0,0 +1,17 @@
+INCLUDES = \
+  -I$(top_srcdir)/common \
+  -I$(top_srcdir)/xrdp \
+  -I$(top_srcdir)/libxrdp \
+  $(DBUS_CFLAGS) \
+  $(XAU_CFLAGS)
+
+
+lib_LTLIBRARIES = \
+  libdmx.la
+
+libdmx_la_SOURCES = dmx.c
+
+libdmx_la_LIBADD = \
+  $(top_srcdir)/common/libcommon.la \
+  $(DBUS_LIBS) \
+  $(XAU_LIBS)
diff --git a/dmx/Makefile.osx b/dmx/Makefile.osx
new file mode 100644
index 0000000..fc77c1c
--- /dev/null
+++ b/dmx/Makefile.osx
@@ -0,0 +1,35 @@
+# libdmx makefile
+
+DMXOBJ = os_calls.o dmx.o
+
+DESTDIR = /usr/local/xrdp
+CFGDIR = /etc/xrdp
+PIDDIR = /var/run
+MANDIR = /usr/local/man
+DOCDIR = /usr/doc/xrdp
+
+DEFINES =
+
+LIBDMX = libdmx.dylib
+
+CFLAGS = -Wall -O2 -I../common `pkg-config --cflags dbus-1` -fPIC $(DEFINES)
+#CFLAGS += -DXRDP_DEBUG
+C_OS_FLAGS = $(CFLAGS) -c
+LDFLAGS = -dynamiclib -Wl,-flat_namespace -Wl,-undefined -Wl,suppress
+LIBS = `pkg-config --libs dbus-1` -ldl
+CC = gcc
+
+all: $(LIBDMX)
+
+$(LIBDMX): $(DMXOBJ)
+	$(CC) $(LDFLAGS) -o $(LIBDMX) $(DMXOBJ) $(LIBS)
+
+clean:
+	rm -f $(DMXOBJ) $(LIBDMX)
+
+os_calls.o: ../common/os_calls.c
+	$(CC) $(C_OS_FLAGS) ../common/os_calls.c
+
+install:
+	install $(LIBDMX) $(DESTDIR)/$(LIBDMX)
+
diff --git a/dmx/dmx.c b/dmx/dmx.c
new file mode 100644
index 0000000..b5836fa
--- /dev/null
+++ b/dmx/dmx.c
@@ -0,0 +1,1658 @@
+/*
+   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-2008
+   Copyright (C) Novell, Inc. 2008
+
+   libdmx main file
+
+*/
+
+#include "dmx.h"
+#include "libxrdpinc.h"
+#include "xrdp_types.h"
+#include "list.h"
+#include <stdlib.h>
+#include <dbus/dbus.h>
+#ifndef _WIN32
+#include <sys/un.h>
+#include <sys/socket.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <signal.h>
+#include <X11/Xauth.h>
+#endif
+#ifndef X_UNIX_PATH
+#  ifdef __hpux
+#    define X_UNIX_PATH "/var/spool/sockets/X11/%u"
+#  else
+#    define X_UNIX_PATH "/tmp/.X11-unix/X%u"
+#  endif
+#endif /* X_UNIX_PATH */
+#define _PATH_UNIX_X X_UNIX_PATH
+
+#define DMX_ERROR_INVALID_SCREEN "org.x.config.dmx.InvalidScreen"
+#define DMX_ERROR_SCREEN_IN_USE  "org.x.config.dmx.ScreenInUse"
+
+#define RDPX11_CHANNEL_RBUF (16 * 1024)
+
+#define RDPX11_OPEN_REQUEST      1
+#define RDPX11_OPEN_CONFIRMATION 2
+#define RDPX11_OPEN_FAILURE      3
+
+/******************************************************************************/
+/* returns error */
+int DEFAULT_CC
+lib_recv(struct mod* mod, char* data, int len)
+{
+  int rcvd;
+
+  if (mod->sck_closed)
+  {
+    return 1;
+  }
+  while (len > 0)
+  {
+    rcvd = g_tcp_recv(mod->sck, data, len, 0);
+    if (rcvd == -1)
+    {
+      if (g_tcp_last_error_would_block(mod->sck))
+      {
+        if (mod->server_is_term(mod))
+        {
+          return 1;
+        }
+        g_tcp_can_recv(mod->sck, 10);
+      }
+      else
+      {
+        return 1;
+      }
+    }
+    else if (rcvd == 0)
+    {
+      mod->sck_closed = 1;
+      return 1;
+    }
+    else
+    {
+      data += rcvd;
+      len -= rcvd;
+    }
+  }
+  return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int DEFAULT_CC
+lib_send(struct mod* mod, char* data, int len)
+{
+  int sent;
+
+  if (mod->sck_closed)
+  {
+    return 1;
+  }
+  while (len > 0)
+  {
+    sent = g_tcp_send(mod->sck, data, len, 0);
+    if (sent == -1)
+    {
+      if (g_tcp_last_error_would_block(mod->sck))
+      {
+        if (mod->server_is_term(mod))
+        {
+          return 1;
+        }
+        g_tcp_can_send(mod->sck, 10);
+      }
+      else
+      {
+        return 1;
+      }
+    }
+    else if (sent == 0)
+    {
+      mod->sck_closed = 1;
+      return 1;
+    }
+    else
+    {
+      data += sent;
+      len -= sent;
+    }
+  }
+  return 0;
+}
+
+/******************************************************************************/
+/* return error */
+int DEFAULT_CC
+lib_mod_start(struct mod* mod, int w, int h, int bpp)
+{
+  LIB_DEBUG(mod, "in lib_mod_start");
+  mod->width = w;
+  mod->height = h;
+  mod->bpp = bpp;
+  mod->xpid = 0;
+  LIB_DEBUG(mod, "out lib_mod_start");
+  return 0;
+}
+
+/******************************************************************************/
+static int DEFAULT_CC
+dmx_connect(DBusConnection* c,
+	    char*           display,
+	    char*           name,
+	    char*           proto,
+	    int             proto_len,
+	    char*           data,
+	    int             data_len,
+	    int             dmxdisplay,
+	    dbus_uint32_t   window,
+	    DBusError       *err)
+{
+    DBusMessage     *message;
+    DBusMessage     *reply;
+    DBusMessageIter iter, subiter;
+    dbus_uint32_t   screen = 0;
+    dbus_bool_t     core = TRUE;
+    char            dest[256];
+    char            path[256];
+    int		    i;
+    
+    g_sprintf (dest, "org.x.config.display%d", dmxdisplay);
+    g_sprintf (path, "/org/x/config/dmx/%d", dmxdisplay);
+
+    do
+    {
+	message = dbus_message_new_method_call (dest,
+						path,
+						"org.x.config.dmx",
+						"attachScreen");
+	if (!message)
+	{
+	    dbus_set_error (err, DBUS_ERROR_NO_MEMORY, "Not enough memory");
+	    break;
+	}
+
+	dbus_message_iter_init_append (message, &iter);
+
+	dbus_message_iter_append_basic (&iter,
+					DBUS_TYPE_UINT32,
+					&screen);
+	dbus_message_iter_append_basic (&iter,
+					DBUS_TYPE_STRING,
+					&display);
+	dbus_message_iter_append_basic (&iter,
+					DBUS_TYPE_STRING,
+					&name);
+	dbus_message_iter_append_basic (&iter,
+					DBUS_TYPE_UINT32,
+					&window);
+	dbus_message_iter_open_container (&iter,
+					  DBUS_TYPE_ARRAY,
+					  DBUS_TYPE_BYTE_AS_STRING,
+					  &subiter);
+	for (i = 0; i < proto_len; i++)
+	    dbus_message_iter_append_basic (&subiter,
+					    DBUS_TYPE_BYTE,
+					    &proto[i]);
+	dbus_message_iter_close_container (&iter, &subiter);
+	dbus_message_iter_open_container (&iter,
+					  DBUS_TYPE_ARRAY,
+					  DBUS_TYPE_BYTE_AS_STRING,
+					  &subiter);
+	for (i = 0; i < data_len; i++)
+	    dbus_message_iter_append_basic (&subiter,
+					    DBUS_TYPE_BYTE,
+					    &data[i]);
+	dbus_message_iter_close_container (&iter, &subiter);
+    
+	reply = dbus_connection_send_with_reply_and_block (c,
+							   message,
+							   -1,
+							   err);
+
+	dbus_message_unref (message);
+
+	if (dbus_error_is_set (err))
+	{
+	    if (g_strcmp (err->name, DMX_ERROR_SCREEN_IN_USE) == 0)
+	    {
+		dbus_error_free (err);
+		dbus_error_init (err);
+
+		screen++; /* try next screen */
+	    }
+	    else
+	    {
+		if (g_strcmp (err->name, DMX_ERROR_INVALID_SCREEN) == 0)
+		{
+		    dbus_error_free (err);
+		    dbus_error_init (err);
+
+		    dbus_set_error (err,
+				    DMX_ERROR_SCREEN_IN_USE,
+				    "No available screens on display %d",
+				    dmxdisplay);
+		}
+
+		break;
+	    }
+	}
+    } while (!reply);
+
+    if (dbus_error_is_set (err))
+	return 1;
+
+    dbus_message_unref (reply);
+
+    message = dbus_message_new_method_call (dest,
+					    path,
+					    "org.x.config.dmx",
+					    "addInput");
+    if (!message)
+    	return 0;
+
+    dbus_message_iter_init_append (message, &iter);
+
+    dbus_message_iter_append_basic (&iter,
+				    DBUS_TYPE_UINT32,
+				    &screen);
+
+    dbus_message_iter_append_basic (&iter,
+				    DBUS_TYPE_BOOLEAN,
+				    &core);
+
+    reply = dbus_connection_send_with_reply_and_block (c,
+						       message,
+						       -1,
+						       err);
+
+    dbus_message_unref (message);
+
+    if (dbus_error_is_set (err))
+	return 1;
+
+    dbus_message_unref (reply);
+
+    message = dbus_message_new_method_call (dest,
+					    path,
+					    "org.x.config.dmx",
+					    "enableScreen");
+    if (!message)
+    {
+	dbus_set_error (err, DBUS_ERROR_NO_MEMORY, "Not enough memory");
+	return 1;
+    }
+
+    dbus_message_iter_init_append (message, &iter);
+
+    dbus_message_iter_append_basic (&iter,
+				    DBUS_TYPE_UINT32,
+				    &screen);
+
+    if (!dbus_connection_send (c, message, NULL))
+    {
+	dbus_set_error (err, DBUS_ERROR_NO_MEMORY, "Not enough memory");
+	dbus_message_unref (message);
+	return 1;
+    }
+
+    dbus_message_unref (message);
+
+    dbus_connection_flush (c);
+
+    return 0;
+}
+
+#ifndef _WIN32
+static int received_usr1;
+
+static void
+sig_usr1_waiting (int sig)
+{
+    g_signal (sig, sig_usr1_waiting);
+    received_usr1++;
+}
+
+#define AUTH_DATA_LEN 16 /* bytes of authorization data */
+
+static int
+lib_mod_setup_auth (struct mod* mod,
+		    char*       display,
+		    char*       auth_data,
+		    int         auth_fd)
+{
+    Xauth   auth;
+    int	    random_fd, i;
+    ssize_t bytes, size;
+    char    auth_host[256];
+    FILE    *file;
+
+    auth.family = FamilyLocal;
+
+    gethostname (auth_host, sizeof (auth_host));
+
+    auth.address	= auth_host;
+    auth.address_length = strlen (auth_host);
+
+    auth.number        = display;
+    auth.number_length = strlen (auth.number);
+
+    auth.name	     = "MIT-MAGIC-COOKIE-1";
+    auth.name_length = strlen (auth.name);
+
+    random_fd = open ("/dev/urandom", O_RDONLY);
+    if (random_fd == -1)
+    {
+	mod->server_msg(mod, "error - can't open /dev/urandom", 0);
+	return 1;
+    }
+
+    bytes = 0;
+    do {
+	size = read (random_fd, auth_data + bytes, AUTH_DATA_LEN - bytes);
+	if (size <= 0)
+	    break;
+
+	bytes += size;
+    } while (bytes != AUTH_DATA_LEN);
+
+    close (random_fd);
+
+    if (bytes != AUTH_DATA_LEN)
+    {
+	mod->server_msg(mod, "error - failed when reading bytes from "
+			"/dev/urandom", 0);
+	return 1;
+    }
+
+    auth.data	     = auth_data;
+    auth.data_length = AUTH_DATA_LEN;
+
+    file = fdopen (auth_fd, "w");
+    if (!file)
+    {
+	close (auth_fd);
+	return 1;
+    }
+
+    XauWriteAuth (file, &auth);
+    fclose (file);
+
+    return 0;
+}
+#endif
+
+/* return error */
+static int DEFAULT_CC
+lib_mod_connect_rdp(struct mod* mod)
+{
+  int error = 0;
+  int len;
+  int i;
+  int pid;
+  struct stream* s;
+  char con_port[256];
+  char** pp1;
+  struct list* xserver_params=0;
+  char screen[256];
+  char geometry[256];
+  char depth[256];
+  char port[256];
+  char name[512];
+  struct xrdp_wm* wm = (struct xrdp_wm *) mod->wm;
+
+#ifndef _WIN32
+  char auth_file[256];
+  const char *auth_templ = "/tmp/.Xdmx-auth-XXXXXX";
+  char auth_data[AUTH_DATA_LEN];
+  int auth_fd;
+  int mask;
+#endif
+
+  g_sprintf(screen, ":%d", mod->display);
+  g_sprintf(geometry, "%dx%d", mod->width, mod->height);
+  g_sprintf(depth, "%d", mod->bpp);
+  g_sprintf(port, "%d", atoi (mod->port) - 6000);
+  g_sprintf(name, "%s@%s", mod->username, mod->hostname);
+
+#ifndef _WIN32
+  received_usr1 = 0;
+  g_signal (SIGUSR1, sig_usr1_waiting);
+
+  strcpy (auth_file, auth_templ);
+  mask = umask (0077);
+  auth_fd = mkstemp (auth_file);
+  umask (mask);
+
+  if (auth_fd == -1)
+  {
+      mod->server_msg(mod, "error - generating unique authorization file", 0);
+      return 1;
+  }
+
+  if (lib_mod_setup_auth (mod, screen + 1, auth_data, auth_fd))
+      return 1;
+#endif
+
+  mod->xpid = g_fork();
+  if (mod->xpid == -1)
+  {
+  }
+  else if (mod->xpid == 0)
+  {
+
+#ifndef _WIN32
+      g_signal (SIGUSR1, SIG_IGN);
+#endif
+
+      xserver_params = list_create();
+      xserver_params->auto_free = 1;
+      list_add_item(xserver_params, (long)g_strdup("X11rdp"));
+      list_add_item(xserver_params, (long)g_strdup(screen));
+      list_add_item(xserver_params, (long)g_strdup("-geometry"));
+      list_add_item(xserver_params, (long)g_strdup(geometry));
+      list_add_item(xserver_params, (long)g_strdup("-depth"));
+      list_add_item(xserver_params, (long)g_strdup(depth));
+      list_add_item(xserver_params, (long)g_strdup("-nolisten"));
+      list_add_item(xserver_params, (long)g_strdup("tcp"));
+#ifdef _WIN32
+      list_add_item(xserver_params, (long)g_strdup("-ac"));
+#else
+      list_add_item(xserver_params, (long)g_strdup("-auth"));
+      list_add_item(xserver_params, (long)g_strdup(auth_file));
+#endif
+      list_add_item(xserver_params, (long)g_strdup("-br"));
+      list_add_item(xserver_params, (long)g_strdup("-terminate"));
+
+      /* make sure it ends with a zero */
+      list_add_item(xserver_params, 0);
+      pp1 = (char**)xserver_params->items;
+      g_execvp("X11rdp", pp1);
+      exit (1);
+  }
+  else
+  {
+      DBusConnection *c;
+      int            time = 0;
+      DBusError      err;
+
+      dbus_error_init (&err);
+
+      c = dbus_bus_get_private (DBUS_BUS_SYSTEM, &err);
+      if (dbus_error_is_set (&err))
+      {
+	  mod->server_msg(mod, (char *) err.message, 0);
+	  dbus_error_free (&err);
+	  g_sigterm(mod->xpid);
+	  mod->xpid = 0;
+	  return 1;
+      }
+
+#ifdef _WIN32
+      g_sleep (5000);
+#else
+      /* wait for X11rdp to start */
+      while (time < 5000)
+      {
+	  if (received_usr1)
+	      break;
+
+	  time += 50;
+	  g_sleep(time);
+      }
+
+      if (!received_usr1)
+      {
+	  mod->server_msg(mod, "error - starting X11 RDP server", 0);
+	  g_sigterm(mod->xpid);
+	  mod->xpid = 0;
+	  return 1;
+      }
+#endif
+
+      mod->server_msg(mod, "X11 RDP server started", 0);
+
+      if (dmx_connect (c,
+		       screen,
+		       name,
+		       "MIT-MAGIC-COOKIE-1",
+		       strlen ("MIT-MAGIC-COOKIE-1"),
+		       auth_data,
+		       AUTH_DATA_LEN,
+		       atoi (mod->port) - 6000,
+		       0,
+		       &err))
+      {
+	  if (dbus_error_is_set (&err))
+	  {
+	      mod->server_msg(mod, (char *) err.message, 0);
+	      dbus_error_free (&err);
+	  }
+
+	  dbus_connection_close (c);
+	  g_sigterm(mod->xpid);
+	  mod->xpid = 0;
+	  return 1;
+      }
+
+      dbus_connection_close (c);
+
+      g_sprintf(con_port, "62%2.2d", mod->display);
+      mod->server_msg(mod, "DMX connection established", 0);
+      make_stream(s);
+
+      mod->sck = g_tcp_socket();
+      mod->sck_obj = g_create_wait_obj_from_socket(mod->sck, 0);
+      mod->sck_closed = 0;
+      error = g_tcp_connect(mod->sck, mod->ip, con_port);
+      if (error == 0)
+      {
+	  g_tcp_set_non_blocking(mod->sck);
+	  g_tcp_set_no_delay(mod->sck);
+      }
+      if (error == 0)
+      {
+	  init_stream(s, 8192);
+	  s_push_layer(s, iso_hdr, 4);
+	  out_uint16_le(s, 103);
+	  out_uint32_le(s, 200);
+	  /* x and y */
+	  i = 0;
+	  out_uint32_le(s, i);
+	  /* width and height */
+	  i = ((mod->width & 0xffff) << 16) | mod->height;
+	  out_uint32_le(s, i);
+	  out_uint32_le(s, 0);
+	  out_uint32_le(s, 0);
+	  s_mark_end(s);
+	  len = (int)(s->end - s->data);
+	  s_pop_layer(s, iso_hdr);
+	  out_uint32_le(s, len);
+	  lib_send(mod, s->data, len);
+      }
+      else
+      {
+          mod->server_msg(mod,
+                          "error - couldn't connect to X11 RDP server",
+                          0); 
+      }
+      free_stream(s);
+  }
+
+  return error;
+}
+
+/* return 0 if there isn't a display running, nonzero otherwise */
+static int DEFAULT_CC
+x_server_running(int display)
+{
+    char text[256];
+    int x_running;
+
+    g_sprintf(text, "/tmp/.X11-unix/X%d", display);
+    x_running = g_file_exist(text);
+    if (!x_running)
+    {
+        g_sprintf(text, "/tmp/.X%d-lock", display);
+	x_running = g_file_exist(text);
+    }
+    return x_running;
+}
+
+/* return error */
+int DEFAULT_CC
+lib_mod_connect(struct mod* mod)
+{
+  int error = 0;
+
+  LIB_DEBUG(mod, "in lib_mod_connect");
+  /* clear screen */
+  mod->server_begin_update(mod);
+  mod->server_set_fgcolor(mod, 0);
+  mod->server_fill_rect(mod, 0, 0, mod->width, mod->height);
+  mod->server_end_update(mod);
+  mod->server_msg(mod, "started connecting", 0);
+  /* only support 8, 16 and 24 bpp connections from rdp client */
+  if (mod->bpp != 8 && mod->bpp != 16 && mod->bpp != 24)
+  {
+    mod->server_msg(mod,
+      "error - only supporting 8, 16 and 24 bpp rdp connections", 0);
+    LIB_DEBUG(mod, "out lib_mod_connect error");
+    return 1;
+  }
+  if (g_strcmp(mod->ip, "") == 0)
+  {
+    mod->server_msg(mod, "error - no ip set", 0);
+    LIB_DEBUG(mod, "out lib_mod_connect error");
+    return 1;
+  }
+  if (g_strcmp(mod->ip, "127.0.0.1") != 0)
+  {
+    mod->server_msg(mod, "error - dmx ip is not 127.0.0.1", 0);
+    LIB_DEBUG(mod, "out lib_mod_connect error");
+    return 1;
+  }
+
+  mod->display = atoi (mod->port) + (MAX_SESSIONS_LIMIT * 2) - 6000;
+
+  while (mod->display <= (MAX_SESSIONS_LIMIT * 4))
+  {
+      if (!x_server_running (mod->display))
+	  break;
+      
+      mod->display++;
+  }
+
+  if (mod->display > (MAX_SESSIONS_LIMIT * 4))
+  {
+    mod->server_msg(mod, "error - no available display offset", 0);
+    LIB_DEBUG(mod, "out lib_mod_connect error");
+    return 1;
+  }
+  
+  mod->xpid = 0;
+  mod->sck = 0;
+  mod->sck_obj = 0;
+  mod->sck_closed = 1;
+  mod->x11_client_sck = 0;
+  mod->x11_client_sck_obj = 0;
+  mod->x11_client_sck_closed = 1;
+  mod->pipefd = 0;
+
+  mod->x11_chanid = mod->server_get_channel_id(mod, "rdpx11");
+  if (mod->x11_chanid >= 0)
+  {
+      char init_data[4] = { RDPX11_OPEN_REQUEST, 0, 0, 0 };
+
+      mod->server_msg(mod, "rdpx11 channel is present", 0);
+      mod->server_send_to_channel(mod, mod->x11_chanid, init_data, 4);
+      mod->server_set_login_mode(mod, 4);
+  }
+  else
+  {
+      mod->server_msg(mod, "rdpx11 channel is not present", 0);
+      error = lib_mod_connect_rdp(mod);
+  }
+
+  LIB_DEBUG(mod, "out lib_mod_connect");
+  return error;
+}
+
+/******************************************************************************/
+/* return error */
+static int DEFAULT_CC
+lib_mod_rdpx11_channel_send(struct mod* mod)
+{
+    char stack_buf[RDPX11_CHANNEL_RBUF];
+    char *buf = stack_buf;
+    int  buf_avail;
+    int  size = sizeof (stack_buf);
+    int  buf_offset = 0;
+    int  len;
+    int  rv = 0;
+
+    do
+    {
+	buf_avail = size - buf_offset;
+
+#ifndef _WIN32
+	len = read (mod->x11_client_sck, buf + buf_offset, buf_avail);
+	if (len == -1)
+	{
+	    if (errno == EINTR || errno == EAGAIN ||
+		errno == EWOULDBLOCK)
+	    {
+		len = 0;
+	    }
+	    else
+	    {
+		rv = 1;
+		break;
+	    }
+	}
+#else	
+	len = g_tcp_recv(mod->x11_client_sck, buf + buf_offset, buf_avail, 0);
+	if (len == -1)
+	{
+	    if (g_tcp_last_error_would_block(mod->x11_client_sck))
+	    {
+		len = 0;
+	    }
+	    else
+	    {
+		rv = 1;
+		break;
+	    }
+	}
+#endif
+
+	else if (len == 0)
+	{
+	    /* wait for error message from pipe */
+	    if (mod->pipefd)
+	    {
+		g_delete_wait_obj_from_socket(mod->x11_client_sck_obj);
+		mod->x11_client_sck_obj = 0;
+	    }
+	    else
+	    {
+		rv = 1;
+		break;
+	    }
+	}
+
+	buf_avail -= len;
+	
+	if (mod->deflate_level)
+	{
+	    char out_buf[RDPX11_CHANNEL_RBUF];
+	    int  out_len;
+	    int  status;
+
+	    if (buf_avail == 0)
+	    {
+		char *data;
+
+#ifndef _WIN32
+		if (buf != stack_buf)
+		{
+		    data = realloc(buf, size * 2);
+		}
+		else
+#endif
+
+		{
+		    data = g_malloc(size * 2, 0);
+		    if (data && buf == stack_buf)
+			g_memcpy(data, buf, size);
+		}
+
+		if (data)
+		{
+		    buf_offset += len;
+		    buf = data;
+		    size *= 2;
+		    continue;
+		}
+	    }
+
+	    mod->outgoing_stream.next_in  = buf;
+	    mod->outgoing_stream.avail_in = size - buf_avail;
+
+	    do {
+		mod->outgoing_stream.next_out  = out_buf;
+		mod->outgoing_stream.avail_out = sizeof(out_buf);
+
+		status = deflate(&mod->outgoing_stream, Z_SYNC_FLUSH);
+		switch (status) {
+		case Z_OK:
+		    out_len = sizeof(out_buf) - mod->outgoing_stream.avail_out;
+		    if (out_len)
+			mod->server_send_to_channel(mod,
+						    mod->x11_chanid,
+						    out_buf,
+						    out_len);
+		    break;
+		default:
+		    g_writeln("[dmx] deflate returned %d", status);
+		}
+	    } while (mod->outgoing_stream.avail_out == 0);
+	}
+	else if (len)
+	{
+	    mod->server_send_to_channel(mod, mod->x11_chanid, buf, len);
+	}	    
+    } while (buf_avail == 0);
+
+    if (buf != stack_buf)
+	g_free (buf);
+
+    return rv;
+}
+
+static int APP_CC
+lib_mod_force_write(int socket, char *buf, int size)
+{
+    int total = 0;
+    int sent;
+
+    while (total < size)
+    {
+
+#ifndef _WIN32
+	sent = write(socket, buf + total, size - total);
+	if (sent == -1)
+	{
+	    if (errno == EINTR || errno == EAGAIN ||
+		errno == EWOULDBLOCK)
+	    {
+		fd_set         rfds;
+		struct timeval time;
+
+		time.tv_sec = 0;
+		time.tv_usec = 10000;
+
+		FD_ZERO(&rfds);
+		FD_SET(socket, &rfds);
+
+		select(socket + 1, &rfds, 0, 0, &time);
+	    }
+	    else
+	    {
+		return -1;
+	    }
+	}
+#else	
+	sent = g_tcp_send(socket, buf + total, size - total, 0);
+	if (sent == -1)
+	{
+	    if (g_tcp_last_error_would_block(socket))
+		g_tcp_can_send(socket, 10);
+	    else
+		return -1;
+	}
+#endif
+
+	else if (sent == 0)
+	{
+	    return 0;
+	}
+	else
+	{
+	    total = total + sent;
+	}
+    }
+
+    return total;
+}
+
+#ifndef _WIN32
+/* return error */
+static int DEFAULT_CC
+lib_mod_process_pipe_data(struct mod* mod)
+{
+    char msg[257];
+    int  len;
+    int  n = 0;
+
+    msg[256] = '\0';
+
+    do
+    {
+	len = read (mod->pipefd, &msg[n++], 1);
+	if (len == -1)
+	{
+	    return 1;
+	}
+	else if (len == 0)
+	{
+	    close(mod->pipefd);
+	    mod->pipefd = 0;
+	    mod->server_set_login_mode(mod, 10);
+	    return 0;
+	}
+	msg[n - 1] = tolower (msg[n - 1]);
+    } while (n < 256);
+
+    switch (msg[0]) {
+    case 0: /* connection error */
+	mod->server_msg(mod, &msg[1], 0);
+	close(mod->pipefd);
+	mod->pipefd = 0;
+	mod->server_msg(mod, "rdpx11 connection failed", 0);
+	if (lib_mod_connect_rdp(mod) == 0)
+	    mod->server_set_login_mode(mod, 10);
+	else
+	    mod->server_set_login_mode(mod, 11);
+	break;
+    case 1: /* connection established */
+	mod->server_msg(mod, "rdpx11 connection established", 0);
+	break;
+    case 2: /* connection message */
+	mod->server_msg(mod, &msg[1], 0);
+	break;
+    }
+
+    return 0;
+}
+#endif
+
+static void
+send_error_response(void *addr)
+{
+    char data[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+    int  sck;
+    
+#ifndef _WIN32
+    sck = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (connect(sck, (struct sockaddr *) addr, sizeof(struct sockaddr_un)) == 0)
+	write (sck, data, sizeof (data));
+    close(sck);
+#else
+    const char *host = "127.0.0.1";
+
+    sck = g_tcp_socket();
+    if (g_tcp_connect(sck, host, (const char *) addr) == 0)
+	g_tcp_send (sck, data, sizeof (data), 0);
+    close (sck);
+#endif
+}
+
+/* return error */
+static int DEFAULT_CC
+lib_process_channel_data(struct mod* mod, int chanid, int size, struct stream* s)
+{
+  if (chanid == mod->x11_chanid)
+  {
+      if (mod->x11_output)
+      {
+	  if (mod->x11_client_sck)
+	  {
+	      int rv = 0;
+
+	      if (mod->inflate_level)
+	      {
+		  char buf[RDPX11_CHANNEL_RBUF];
+		  int  status;
+		  int  len;
+
+		  mod->incoming_stream.next_in  = s->p;
+		  mod->incoming_stream.avail_in = size;
+
+		  do
+		  {
+		      mod->incoming_stream.next_out  = buf;
+		      mod->incoming_stream.avail_out = sizeof(buf);
+
+		      status = inflate(&mod->incoming_stream, Z_SYNC_FLUSH);
+		      switch (status) {
+		      case Z_OK:
+			  len = sizeof(buf) - mod->incoming_stream.avail_out;
+			  rv = lib_mod_force_write (mod->x11_client_sck, buf,
+						    len);
+			  break;
+		      case Z_BUF_ERROR:
+			  break;
+		      default:
+			  g_writeln("[dmx] inflate returned %d", status);
+		      }
+		  } while (rv && status == Z_OK);
+	      }
+	      else
+	      {
+		  rv = lib_mod_force_write (mod->x11_client_sck, s->p, size);
+	      }
+
+	      if (rv == 0)
+	      {
+		  /* wait for error message from pipe */
+		  if (mod->pipefd)
+		  {
+		      g_delete_wait_obj_from_socket(mod->x11_client_sck_obj);
+		      mod->x11_client_sck_obj = 0;
+		  }
+		  else
+		  {
+		      return 1;
+		  }
+	      }
+	  }
+      }
+      else
+      {
+	  struct xrdp_wm*    wm = (struct xrdp_wm *) mod->wm;
+	  char               name[512];
+	  char               screen[256];
+	  char               *proto;
+	  char               *data;
+	  int		     proto_len;
+	  int		     data_len;
+	  int                type;
+	  int                pid;
+	  int                sck;
+	  int                error;
+	  int                len;
+
+#ifndef _WIN32
+	  struct sockaddr_un local, remote;
+	  int                flag;
+	  int                gid;
+	  int                uid;
+	  int                pipefd[2];
+
+	  g_sprintf(screen, ":%d.0", mod->display);
+#else
+	  char               con_port[256];
+    
+	  g_sprintf(screen, "localhost:%d.0", mod->display);
+#endif
+	  g_sprintf(name, "%s@%s", mod->username, mod->hostname);
+
+	  in_uint32_le(s, type);
+
+	  switch (type) {
+	  case RDPX11_OPEN_CONFIRMATION:
+	      in_uint32_le(s, mod->x11_output);
+	      in_uint16_le(s, mod->deflate_level);
+	      in_uint16_le(s, mod->inflate_level);
+	      in_uint32_le(s, proto_len);
+	      in_uint32_le(s, data_len);
+	      in_uint8p(s, proto, proto_len);
+	      in_uint8p(s, data, data_len);
+
+	      if (mod->deflate_level)
+		  deflateInit (&mod->outgoing_stream, mod->deflate_level);
+
+	      if (mod->inflate_level)
+		  inflateInit (&mod->incoming_stream);
+
+#ifndef _WIN32
+	      sck = socket(AF_UNIX, SOCK_STREAM, 0);
+
+	      local.sun_family = AF_UNIX;
+	      g_snprintf(local.sun_path, sizeof local.sun_path, _PATH_UNIX_X,
+			 mod->display);
+	      len = strlen(local.sun_path) + sizeof(local.sun_family);
+	      unlink(local.sun_path);
+
+	      error = bind(sck, (struct sockaddr *) &local, len);
+	      if (error != 0)
+	      {
+		  close(sck);
+		  g_writeln("[dmx] bind() error: %d", error);
+		  return 1;
+	      }
+
+	      if (g_getuser_info (mod->username, &gid, &uid, 0, 0, 0) == 0)
+		  chown (local.sun_path, uid, gid);
+
+	      error = listen(sck, 1);
+	      if (error != 0)
+	      {
+		  close(sck);
+		  unlink(local.sun_path);
+		  g_writeln("[dmx] listen() error: %d", error);
+		  return 1;
+	      }
+
+	      if (pipe(pipefd) == -1)
+	      {
+		  close(sck);
+		  unlink(local.sun_path);
+		  g_writeln("[dmx] pipe() error: %d", error);
+		  return 1;
+	      }
+#else
+	      g_sprintf(con_port, "%d", 6000 + mod->display);
+  
+	      sck = g_tcp_socket();
+	      error = g_tcp_bind(sck, con_port);
+	      if (error != 0)
+	      {
+		  g_tcp_close(sck);
+		  g_writeln("[dmx] bind() error: %d", error);
+		  return 1;
+	      }
+	      error = g_tcp_listen(sck);
+	      if (error != 0)
+	      {
+		  g_tcp_close(sck);
+		  g_writeln("[dmx] listen() error: %d", error);
+		  return 1;
+	      }
+#endif
+
+	      pid = g_fork();
+	      if (pid == -1)
+	      {
+	      }
+	      else if (pid == 0)
+	      {
+		  DBusConnection *c;
+		  DBusError      err;
+		  char           msg[256];
+
+		  g_memset (msg, 0, sizeof (msg));
+
+#ifndef _WIN32
+		  close(pipefd[0]);
+#endif
+    
+		  dbus_error_init (&err);
+
+		  c = dbus_bus_get_private (DBUS_BUS_SYSTEM, &err);
+		  if (dbus_error_is_set (&err))
+		  {
+#ifndef _WIN32
+		      msg[0] = 0; /* connection error */
+		      g_snprintf (&msg[1], sizeof (msg) - 1, "error - %s",
+				  err.message);
+		      write (pipefd[1], msg, sizeof (msg));
+		      close (pipefd[1]);
+		      send_error_response(&local);
+#else
+		      send_error_response(con_port);
+#endif
+		      dbus_error_free (&err);
+		      exit (1);
+		  }
+
+		  if (dmx_connect (c,
+				   screen,
+				   name,
+				   proto,
+				   proto_len,
+				   data,
+				   data_len,
+				   atoi (mod->port) - 6000,
+				   mod->x11_output,
+				   &err))
+		  {
+#ifndef _WIN32
+		      msg[0] = 0; /* connection error */
+		      g_snprintf (&msg[1], sizeof (msg) - 1, "error - %s",
+				  err.message);
+		      write (pipefd[1], msg, sizeof (msg));
+		      close (pipefd[1]);
+		      send_error_response(&local);
+#else
+		      send_error_response(con_port);
+#endif
+		      dbus_error_free (&err);
+		      dbus_connection_close (c);
+		      exit (1);
+		  }
+
+#ifndef _WIN32
+		  msg[0] = 1; /* connection established */
+		  write (pipefd[1], msg, sizeof (msg));
+
+		  close(pipefd[1]); /* connection ready */
+#endif
+		  dbus_connection_close (c);
+		  exit (1);
+	      }
+	      else
+	      {
+		  int  x11_client_sck;
+                  char buf[1024];
+
+#ifndef _WIN32
+		  close(pipefd[1]);
+		  mod->pipefd = pipefd[0];
+
+                  len = sizeof(remote);
+		  x11_client_sck = accept(sck, (struct sockaddr *) &remote, &len);
+		  len = read(x11_client_sck, buf, sizeof (buf));
+		  close(sck);
+		  unlink(local.sun_path);
+
+		  if (len < 0 || buf[0] == 0)
+                  {
+		      close(x11_client_sck);
+		      lib_mod_process_pipe_data(mod);
+		      mod->server_set_login_mode(mod, 11);
+                      return 0;
+                  }
+
+		  if ((flag = fcntl(x11_client_sck, F_GETFL)) != -1)
+		      fcntl(x11_client_sck, F_SETFL, flag | O_NONBLOCK);
+#else
+		  x11_client_sck = g_tcp_accept(sck);
+		  len = g_tcp_recv(x11_client_sck, buf, sizeof (buf), 0);
+		  g_tcp_close(sck);
+
+		  if (len < 0 || buf[0] == 0)
+                  {
+		      g_tcp_close(x11_client_sck);
+		      mod->server_msg(mod, "error - rdpx11 connection failed", 0);
+		      mod->server_set_login_mode(mod, 11);
+                      return 0;
+                  }
+
+		  g_tcp_set_non_blocking(x11_client_sck);
+		  g_tcp_set_no_delay(x11_client_sck);
+
+		  mod->server_set_login_mode(mod, 10);
+#endif
+
+		  if (mod->deflate_level)
+		  {
+		      char out_buf[RDPX11_CHANNEL_RBUF];
+		      int  out_len;
+		      int  status;
+
+		      mod->outgoing_stream.next_in  = buf;
+		      mod->outgoing_stream.avail_in = len;
+
+		      do {
+			  mod->outgoing_stream.next_out  = out_buf;
+			  mod->outgoing_stream.avail_out = sizeof(out_buf);
+
+			  status = deflate(&mod->outgoing_stream,
+					   Z_SYNC_FLUSH);
+			  switch (status) {
+			  case Z_OK:
+			      out_len = sizeof(out_buf) -
+				  mod->outgoing_stream.avail_out;
+			      if (out_len)
+				  mod->server_send_to_channel(mod,
+							      mod->x11_chanid,
+							      out_buf,
+							      out_len);
+			      break;
+			  default:
+			      g_writeln("[dmx] deflate returned %d", status);
+			  }
+		      } while (mod->outgoing_stream.avail_out == 0);
+		  }
+		  else
+		  {
+		      mod->server_send_to_channel(mod,
+						  mod->x11_chanid,
+						  buf,
+						  len);
+		  }	    
+
+		  mod->server_msg(mod, "rdpx11 connection initiated", 0);
+
+		  mod->x11_client_sck = x11_client_sck;
+		  mod->x11_client_sck_obj =
+		      g_create_wait_obj_from_socket(mod->x11_client_sck, 0);
+	      }
+	      break;
+	  case RDPX11_OPEN_FAILURE:
+	      in_uint8s(s, 16);
+	      mod->server_msg(mod, "error - rdpx11 open request failed", 0);
+	      mod->server_set_login_mode(mod, 11);
+	      break;
+	  }
+      }
+  }
+
+  return 0;
+}
+
+/* return error */
+int DEFAULT_CC
+lib_mod_event(struct mod* mod, int msg, tbus param1, tbus param2,
+              tbus param3, tbus param4)
+{
+  struct stream* s;
+  int len;
+  int rv;
+  int size;
+  int chanid;
+  char* data;
+
+  LIB_DEBUG(mod, "in lib_mod_event");
+  make_stream(s);
+  if (msg == 0x5555) /* channel data */
+  {
+    chanid = (int)param1;
+    size = (int)param2;
+    data = (char*)param3;
+    if ((size >= 0) && (size <= (32 * 1024)) && (data != 0))
+    {
+      init_stream(s, size);
+      out_uint8a(s, data, size);
+      s_mark_end(s);
+      s->p = s->data;
+      rv = lib_process_channel_data(mod, chanid, size, s);
+    }
+    else
+    {
+      rv = 1;
+    }
+  }
+  else
+  {
+    init_stream(s, 8192);
+    s_push_layer(s, iso_hdr, 4);
+    out_uint16_le(s, 103);
+    out_uint32_le(s, msg);
+    out_uint32_le(s, param1);
+    out_uint32_le(s, param2);
+    out_uint32_le(s, param3);
+    out_uint32_le(s, param4);
+    s_mark_end(s);
+    len = (int)(s->end - s->data);
+    s_pop_layer(s, iso_hdr);
+    out_uint32_le(s, len);
+    rv = lib_send(mod, s->data, len);
+  }
+  free_stream(s);
+  LIB_DEBUG(mod, "out lib_mod_event");
+  return rv;
+}
+
+/******************************************************************************/
+/* return error */
+int DEFAULT_CC
+lib_mod_signal(struct mod* mod)
+{
+  struct stream* s;
+  int num_orders;
+  int index;
+  int rv;
+  int len;
+  int type;
+  int x;
+  int y;
+  int cx;
+  int cy;
+  int fgcolor;
+  int opcode;
+  int width;
+  int height;
+  int srcx;
+  int srcy;
+  int len_bmpdata;
+  int style;
+  int x1;
+  int y1;
+  int x2;
+  int y2;
+  char* bmpdata;
+  char cur_data[32 * (32 * 3)];
+  char cur_mask[32 * (32 / 8)];
+
+  LIB_DEBUG(mod, "in lib_mod_signal");
+  make_stream(s);
+  init_stream(s, 8192);
+  rv = lib_recv(mod, s->data, 8);
+  if (rv == 0)
+  {
+    in_uint16_le(s, type);
+    in_uint16_le(s, num_orders);
+    in_uint32_le(s, len);
+    if (type == 1)
+    {
+      init_stream(s, len);
+      rv = lib_recv(mod, s->data, len);
+      if (rv == 0)
+      {
+        for (index = 0; index < num_orders; index++)
+        {
+          in_uint16_le(s, type);
+          switch (type)
+          {
+            case 1: /* server_begin_update */
+              rv = mod->server_begin_update(mod);
+              break;
+            case 2: /* server_end_update */
+              rv = mod->server_end_update(mod);
+              break;
+            case 3: /* server_fill_rect */
+              in_sint16_le(s, x);
+              in_sint16_le(s, y);
+              in_uint16_le(s, cx);
+              in_uint16_le(s, cy);
+              rv = mod->server_fill_rect(mod, x, y, cx, cy);
+              break;
+            case 4: /* server_screen_blt */
+              in_sint16_le(s, x);
+              in_sint16_le(s, y);
+              in_uint16_le(s, cx);
+              in_uint16_le(s, cy);
+              in_sint16_le(s, srcx);
+              in_sint16_le(s, srcy);
+              rv = mod->server_screen_blt(mod, x, y, cx, cy, srcx, srcy);
+              break;
+            case 5: /* server_paint_rect */
+              in_sint16_le(s, x);
+              in_sint16_le(s, y);
+              in_uint16_le(s, cx);
+              in_uint16_le(s, cy);
+              in_uint32_le(s, len_bmpdata);
+              in_uint8p(s, bmpdata, len_bmpdata);
+              in_uint16_le(s, width);
+              in_uint16_le(s, height);
+              in_sint16_le(s, srcx);
+              in_sint16_le(s, srcy);
+              rv = mod->server_paint_rect(mod, x, y, cx, cy,
+                                          bmpdata, width, height,
+                                          srcx, srcy);
+              break;
+            case 10: /* server_set_clip */
+              in_sint16_le(s, x);
+              in_sint16_le(s, y);
+              in_uint16_le(s, cx);
+              in_uint16_le(s, cy);
+              rv = mod->server_set_clip(mod, x, y, cx, cy);
+              break;
+            case 11: /* server_reset_clip */
+              rv = mod->server_reset_clip(mod);
+              break;
+            case 12: /* server_set_fgcolor */
+              in_uint32_le(s, fgcolor);
+              rv = mod->server_set_fgcolor(mod, fgcolor);
+              break;
+            case 14:
+              in_uint16_le(s, opcode);
+              rv = mod->server_set_opcode(mod, opcode);
+              break;
+            case 17:
+              in_uint16_le(s, style);
+              in_uint16_le(s, width);
+              rv = mod->server_set_pen(mod, style, width);
+              break;
+            case 18:
+              in_sint16_le(s, x1);
+              in_sint16_le(s, y1);
+              in_sint16_le(s, x2);
+              in_sint16_le(s, y2);
+              rv = mod->server_draw_line(mod, x1, y1, x2, y2);
+              break;
+            case 19:
+              in_sint16_le(s, x);
+              in_sint16_le(s, y);
+              in_uint8a(s, cur_data, 32 * (32 * 3));
+              in_uint8a(s, cur_mask, 32 * (32 / 8));
+              rv = mod->server_set_cursor(mod, x, y, cur_data, cur_mask);
+              break;
+            default:
+              rv = 1;
+              break;
+          }
+          if (rv != 0)
+          {
+            break;
+          }
+        }
+      }
+    }
+  }
+  free_stream(s);
+  LIB_DEBUG(mod, "out lib_mod_signal");
+  return rv;
+}
+
+/******************************************************************************/
+/* return error */
+int DEFAULT_CC
+lib_mod_end(struct mod* mod)
+{
+  return 0;
+}
+
+/******************************************************************************/
+/* return error */
+int DEFAULT_CC
+lib_mod_set_param(struct mod* mod, char* name, char* value)
+{
+  if (g_strcasecmp(name, "username") == 0)
+  {
+    g_strncpy(mod->username, value, 255);
+  }
+  else if (g_strcasecmp(name, "password") == 0)
+  {
+    g_strncpy(mod->password, value, 255);
+  }
+  else if (g_strcasecmp(name, "ip") == 0)
+  {
+    g_strncpy(mod->ip, value, 255);
+  }
+  else if (g_strcasecmp(name, "port") == 0)
+  {
+    g_strncpy(mod->port, value, 255);
+  }
+  else if (g_strcasecmp(name, "hostname") == 0)
+  {
+    g_strncpy(mod->hostname, value, 255);
+  }
+  return 0;
+}
+
+/******************************************************************************/
+/* return error */
+int DEFAULT_CC
+lib_mod_get_wait_objs(struct mod* mod, tbus* read_objs, int* rcount,
+                      tbus* write_objs, int* wcount, int* timeout)
+{
+  int i;
+
+  i = *rcount;
+  if (mod != 0)
+  {
+    if (mod->sck_obj != 0)
+    {
+      read_objs[i++] = mod->sck_obj;
+    }
+    if (mod->x11_client_sck_obj != 0)
+    {
+      read_objs[i++] = mod->x11_client_sck_obj;
+    }
+    if (mod->pipefd != 0)
+    {
+      read_objs[i++] = mod->pipefd;
+    }
+  }
+  *rcount = i;
+  return 0;
+}
+
+/******************************************************************************/
+/* return error */
+int DEFAULT_CC
+lib_mod_check_wait_objs(struct mod* mod)
+{
+  int rv;
+
+  rv = 0;
+  if (mod != 0)
+  {
+    if (mod->sck_obj != 0)
+    {
+      if (g_is_wait_obj_set(mod->sck_obj))
+      {
+        rv = lib_mod_signal(mod);
+      }
+    }
+    if (mod->x11_client_sck_obj != 0)
+    {
+      if (g_is_wait_obj_set(mod->x11_client_sck_obj))
+      {
+	rv = lib_mod_rdpx11_channel_send(mod);
+      }
+    }
+#ifndef _WIN32
+    if (mod->pipefd != 0)
+    {
+      fd_set         rfds;
+      struct timeval time = { 0, 0 };
+
+      FD_ZERO(&rfds);
+      FD_SET(mod->pipefd, &rfds);
+
+      rv = select(mod->pipefd + 1, &rfds, 0, 0, &time);
+      if (rv < 0)
+	  return 1;
+
+      if (rv > 0)
+	rv = lib_mod_process_pipe_data(mod);
+
+      FD_ZERO(&rfds);
+    }
+#endif
+  }
+  return rv;
+}
+
+/******************************************************************************/
+struct mod* EXPORT_CC
+mod_init(void)
+{
+  struct mod* mod;
+
+  mod = (struct mod*)g_malloc(sizeof(struct mod), 1);
+  mod->size = sizeof(struct mod);
+  mod->handle = (tbus)mod;
+  mod->mod_connect = lib_mod_connect;
+  mod->mod_start = lib_mod_start;
+  mod->mod_event = lib_mod_event;
+  mod->mod_signal = lib_mod_signal;
+  mod->mod_end = lib_mod_end;
+  mod->mod_set_param = lib_mod_set_param;
+  mod->mod_get_wait_objs = lib_mod_get_wait_objs;
+  mod->mod_check_wait_objs = lib_mod_check_wait_objs;
+  mod->deflate_level = 0;
+  mod->inflate_level = 0;
+
+  return mod;
+}
+
+/******************************************************************************/
+int EXPORT_CC
+mod_exit(struct mod* mod)
+{
+  if (mod == 0)
+  {
+    return 0;
+  }
+#ifndef _WIN32
+  if (mod->pipefd != 0)
+      close (mod->pipefd);
+#endif
+  if (mod->deflate_level)
+      deflateEnd (&mod->outgoing_stream);
+  if (mod->inflate_level)
+      inflateEnd (&mod->incoming_stream);
+  if (mod->x11_client_sck_obj != 0)
+      g_delete_wait_obj_from_socket(mod->x11_client_sck_obj);
+  if (mod->x11_client_sck != 0)
+#ifndef _WIN32
+      close(mod->x11_client_sck);
+#else
+      g_tcp_close(mod->x11_client_sck);
+#endif
+  if (mod->sck_obj != 0)
+      g_delete_wait_obj_from_socket(mod->sck_obj);
+  if (mod->sck != 0)
+      g_tcp_close(mod->sck);
+  if (mod->xpid > 0)
+    g_sigterm(mod->xpid);
+  g_free(mod);
+  return 0;
+}
diff --git a/dmx/dmx.h b/dmx/dmx.h
new file mode 100644
index 0000000..7edf580
--- /dev/null
+++ b/dmx/dmx.h
@@ -0,0 +1,119 @@
+/*
+   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-2008
+   Copyright (C) Novell, Inc. 2008
+
+   libdmx main header file
+
+*/
+
+/* include other h files */
+#include "arch.h"
+#include "parse.h"
+#include "os_calls.h"
+#include "defines.h"
+#include <zlib.h>
+
+struct mod
+{
+  int size; /* size of this struct */
+  int version; /* internal version */
+  /* client functions */
+  int (*mod_start)(struct mod* v, int w, int h, int bpp);
+  int (*mod_connect)(struct mod* v);
+  int (*mod_event)(struct mod* v, int msg, tbus param1, tbus param2,
+                   tbus param3, tbus param4);
+  int (*mod_signal)(struct mod* v);
+  int (*mod_end)(struct mod* v);
+  int (*mod_set_param)(struct mod* v, char* name, char* value);
+  int (*mod_session_change)(struct mod* v, int, int);
+  int (*mod_get_wait_objs)(struct mod* v, tbus* read_objs, int* rcount,
+                           tbus* write_objs, int* wcount, int* timeout);
+  int (*mod_check_wait_objs)(struct mod* v);
+  tbus mod_dumby[100 - 9]; /* align, 100 minus the number of mod
+                              functions above */
+  /* server functions */
+  int (*server_begin_update)(struct mod* v);
+  int (*server_end_update)(struct mod* v);
+  int (*server_fill_rect)(struct mod* v, int x, int y, int cx, int cy);
+  int (*server_screen_blt)(struct mod* v, int x, int y, int cx, int cy,
+                           int srcx, int srcy);
+  int (*server_paint_rect)(struct mod* v, int x, int y, int cx, int cy,
+                           char* data, int width, int height, int srcx, int srcy);
+  int (*server_set_cursor)(struct mod* v, int x, int y, char* data, char* mask);
+  int (*server_palette)(struct mod* v, int* palette);
+  int (*server_msg)(struct mod* v, char* msg, int code);
+  int (*server_is_term)(struct mod* v);
+  int (*server_set_clip)(struct mod* v, int x, int y, int cx, int cy);
+  int (*server_reset_clip)(struct mod* v);
+  int (*server_set_fgcolor)(struct mod* v, int fgcolor);
+  int (*server_set_bgcolor)(struct mod* v, int bgcolor);
+  int (*server_set_opcode)(struct mod* v, int opcode);
+  int (*server_set_mixmode)(struct mod* v, int mixmode);
+  int (*server_set_brush)(struct mod* v, int x_orgin, int y_orgin,
+                          int style, char* pattern);
+  int (*server_set_pen)(struct mod* v, int style,
+                        int width);
+  int (*server_draw_line)(struct mod* v, int x1, int y1, int x2, int y2);
+  int (*server_add_char)(struct mod* v, int font, int charactor,
+                         int offset, int baseline,
+                         int width, int height, char* data);
+  int (*server_draw_text)(struct mod* v, int font,
+                          int flags, int mixmode, int clip_left, int clip_top,
+                          int clip_right, int clip_bottom,
+                          int box_left, int box_top,
+                          int box_right, int box_bottom,
+                          int x, int y, char* data, int data_len);
+  int (*server_reset)(struct mod* v, int width, int height, int bpp);
+  int (*server_query_channel)(struct mod* v, int index,
+                              char* channel_name,
+                              int* channel_flags);
+  int (*server_get_channel_id)(struct mod* v, char* name);
+  int (*server_send_to_channel)(struct mod* v, int channel_id,
+                                char* data, int data_len);
+  int (*server_set_login_mode)(struct mod* v, int login_mode);
+  long server_dumby[100 - 25]; /* align, 100 minus the number of server
+                                  functions above */
+  /* common */
+  tbus handle; /* pointer to self as long */
+  tbus wm;
+  tbus painter;
+  int sck;
+  /* mod data */
+  int width;
+  int height;
+  int bpp;
+  int display;
+  int xpid;
+  int sck_closed;
+  char username[256];
+  char password[256];
+  char ip[256];
+  char port[256];
+  char hostname[256];
+  tbus sck_obj;
+  int x11_chanid;
+  unsigned int x11_output;
+  int x11_client_sck;
+  tbus x11_client_sck_obj;
+  int x11_client_sck_closed;
+  int pipefd;
+  unsigned int inflate_level;
+  unsigned int deflate_level;
+  z_stream incoming_stream;
+  z_stream outgoing_stream;
+};
diff --git a/instfiles/Makefile.am b/instfiles/Makefile.am
index 8f8616c..05eeb88 100644
--- a/instfiles/Makefile.am
+++ b/instfiles/Makefile.am
@@ -10,6 +10,6 @@ startscript_DATA = \
 # must be tab below
 install-data-hook:
 	chmod 755 $(DESTDIR)$(sysconfdir)/xrdp/xrdp.sh
-	if [ -w /etc/init.d ]; then rm -f /etc/init.d/xrdp.sh; fi
-	if [ -w /etc/init.d ]; then $(LN_S) $(DESTDIR)$(sysconfdir)/xrdp/xrdp.sh /etc/init.d/xrdp.sh; fi
-	$(DESTDIR)$(bindir)/xrdp-keygen xrdp $(DESTDIR)$(sysconfdir)/xrdp/rsakeys.ini
+	mkdir -p $(DESTDIR)/etc/init.d
+	$(LN_S) $(sysconfdir)/xrdp/xrdp.sh $(DESTDIR)/etc/init.d/xrdp
+#	$(DESTDIR)$(bindir)/xrdp-keygen xrdp $(DESTDIR)$(sysconfdir)/xrdp/rsakeys.ini
diff --git a/instfiles/xrdp.sh b/instfiles/xrdp.sh
index 3671004..870118e 100755
--- a/instfiles/xrdp.sh
+++ b/instfiles/xrdp.sh
@@ -4,8 +4,19 @@
 # maintaned by Jay Sorg
 # chkconfig: 2345 11 89
 # description: starts xrdp
+#
+### BEGIN INIT INFO
+# Provides:          xrdp
+# Required-Start:    $remote_fs
+# Should-Start:      ypbind $syslog firstboot resmgr winbind acpid
+# Should-Stop:       $null
+# Required-Stop:     $null
+# Default-Start:     5
+# Default-Stop:
+# Description:       Start the xrdp daemon
+### END INIT INFO    
 
-SBINDIR=/usr/local/sbin
+SBINDIR=/usr/sbin
 LOG=/dev/null
 CFGDIR=/etc/xrdp
 
@@ -27,26 +38,25 @@ fi
 
 xrdp_start()
 {
-  echo -n "Starting: xrdp and sesman . . "
-  $SBINDIR/xrdp >> $LOG
+  echo "Starting sesman daemon"
   $SBINDIR/xrdp-sesman >> $LOG
-  echo "."
-  sleep 1
+  echo "Starting xrdp daemon"
+  $SBINDIR/xrdp >> $LOG
   return 0;
 }
 
 xrdp_stop()
 {
-  echo -n "Stopping: xrdp and sesman . . "
-  $SBINDIR/xrdp-sesman --kill >> $LOG
+  echo "Stopping xrdp daemon"
   $SBINDIR/xrdp --kill >> $LOG
-  echo "."
+  echo "Stopping sesman daemon"
+  $SBINDIR/xrdp-sesman --kill >> $LOG
   return 0;
 }
 
 is_xrdp_running()
 {
-  ps u --noheading -C xrdp | grep -q -i xrdp
+  ps u --noheading -C xrdp | grep -q -i $SBINDIR/xrdp
   if test $? -eq 0
   then
     return 1;
@@ -57,7 +67,7 @@ is_xrdp_running()
 
 is_sesman_running()
 {
-  ps u --noheading -C xrdp-sesman | grep -q -i xrdp-sesman
+  ps u --noheading -C xrdp-sesman | grep -q -i $SBINDIR/xrdp-sesman
   if test $? -eq 0
   then
     return 1;
@@ -122,7 +132,6 @@ case "$1" in
     ;;
   force-reload|restart)
     check_up
-    echo "Restarting xrdp ..."
     xrdp_stop
     is_xrdp_running
     while ! test $? -eq 0
diff --git a/rdp/rdp_lic.c b/rdp/rdp_lic.c
index 0de448c..5d355bb 100644
--- a/rdp/rdp_lic.c
+++ b/rdp/rdp_lic.c
@@ -293,7 +293,7 @@ static void APP_CC
 rdp_lic_process_issue(struct rdp_lic* self, struct stream* s)
 {
   void* crypt_key;
-  int length;
+  tui32 length;
   int check;
   int i;
 
@@ -320,7 +320,7 @@ rdp_lic_process_issue(struct rdp_lic* self, struct stream* s)
   {
     in_uint8s(s, length);
     in_uint32_le(s, length);
-    if (!s_check_rem(s, length))
+    if (!s_check(s) || length > (tui32) (s->end - s->p))
     {
       return;
     }
diff --git a/rdp/rdp_orders.c b/rdp/rdp_orders.c
index 4bc4d05..853bbd3 100644
--- a/rdp/rdp_orders.c
+++ b/rdp/rdp_orders.c
@@ -433,6 +433,8 @@ rdp_orders_process_secondary_order(struct rdp_orders* self, struct stream* s)
   in_uint16_le(s, length);
   in_uint16_le(s, flags);
   in_uint8(s, type);
+  if (!s_check_rem (s, length + 7))
+      return 0;
   next_order = s->p + length + 7;
   switch (type)
   {
diff --git a/rdp/rdp_rdp.c b/rdp/rdp_rdp.c
index db8bb30..9e08272 100644
--- a/rdp/rdp_rdp.c
+++ b/rdp/rdp_rdp.c
@@ -411,8 +411,27 @@ rdp_rdp_process_color_pointer_pdu(struct rdp_rdp* self, struct stream* s)
   in_uint16_le(s, cursor->height);
   in_uint16_le(s, mlen); /* mask length */
   in_uint16_le(s, dlen); /* data length */
-  in_uint8a(s, cursor->data, dlen);
-  in_uint8a(s, cursor->mask, mlen);
+
+  g_memset (cursor->data, 0, sizeof (cursor->data));
+  if (dlen <= sizeof (cursor->data))
+  {
+    in_uint8a(s, cursor->data, dlen);
+  }
+  else
+  {
+    in_uint8s(s, dlen);
+  }
+
+  g_memset (cursor->mask, 0, sizeof (cursor->mask));
+  if (mlen <= sizeof (cursor->mask))
+  {
+    in_uint8a(s, cursor->mask, mlen);
+  }
+  else
+  {
+    in_uint8s(s, mlen);
+  }
+
   self->mod->server_set_cursor(self->mod, cursor->x, cursor->y,
                                cursor->data, cursor->mask);
 }
@@ -514,6 +533,8 @@ rdp_rdp_process_bitmap_updates(struct rdp_rdp* self, struct stream* s)
   in_uint16_le(s, num_updates);
   for (i = 0; i < num_updates; i++)
   {
+    if (!s_check_rem (s, 18))
+      return;
     in_uint16_le(s, left);
     in_uint16_le(s, top);
     in_uint16_le(s, right);
@@ -526,6 +547,8 @@ rdp_rdp_process_bitmap_updates(struct rdp_rdp* self, struct stream* s)
     in_uint16_le(s, bufsize);
     cx = (right - left) + 1;
     cy = (bottom - top) + 1;
+    if (width > 8192 || height > 8192 || bpp > 32)
+	return;
     bmpdata0 = (char*)g_malloc(width * height * Bpp, 0);
     if (compress)
     {
@@ -535,10 +558,14 @@ rdp_rdp_process_bitmap_updates(struct rdp_rdp* self, struct stream* s)
       }
       else
       {
+        if (!s_check_rem (s, 8))
+	  return;
         in_uint8s(s, 2); /* pad */
         in_uint16_le(s, size);
         in_uint8s(s, 4); /* line_size, final_size */
       }
+      if (!s_check_rem (s, size))
+	  return;
       in_uint8p(s, data, size);
       rdp_bitmap_decompress(bmpdata0, width, height, data, size, Bpp);
       bmpdata1 = rdp_orders_convert_bitmap(bpp, self->mod->xrdp_bpp,
@@ -549,6 +576,8 @@ rdp_rdp_process_bitmap_updates(struct rdp_rdp* self, struct stream* s)
     }
     else /* not compressed */
     {
+      if (!s_check_rem (s, width * height * Bpp))
+	return;
       for (y = 0; y < height; y++)
       {
         data = bmpdata0 + ((height - y) - 1) * (width * Bpp);
diff --git a/sesman/Makefile.am b/sesman/Makefile.am
index 22736e6..41dce1b 100644
--- a/sesman/Makefile.am
+++ b/sesman/Makefile.am
@@ -1,6 +1,9 @@
 INCLUDES = \
   -I$(top_srcdir)/common \
-  -I$(top_srcdir)/sesman/libscp
+  -I$(top_srcdir)/sesman/libscp \
+  $(DBUS_CFLAGS) \
+  $(XAU_CFLAGS) \
+  $(XCB_CFLAGS)
 
 if SESMAN_NOPAM
 AUTH_C = verify_user.c
@@ -44,7 +47,10 @@ xrdp_sessvc_SOURCES = \
 xrdp_sesman_LDADD = \
   $(top_srcdir)/common/libcommon.la \
   $(top_srcdir)/sesman/libscp/libscp.la \
-  $(AUTH_LIB)
+  $(AUTH_LIB) \
+  $(DBUS_LIBS) \
+  $(XAU_LIBS) \
+  $(XCB_LIBS)
 
 xrdp_sessvc_LDADD = \
   $(top_srcdir)/common/libcommon.la
diff --git a/sesman/config.c b/sesman/config.c
index 4af7b69..b48ca29 100644
--- a/sesman/config.c
+++ b/sesman/config.c
@@ -29,6 +29,7 @@
 #include "list.h"
 #include "file.h"
 #include "sesman.h"
+#include "defines.h"
 
 extern struct config_sesman* g_cfg;
 
@@ -88,9 +89,10 @@ config_read(struct config_sesman* cfg)
   /* read global config */
   config_read_globals(fd, cfg, param_n, param_v);
 
-  /* read Xvnc/X11rdp parameter list */
+  /* read Xvnc/X11rdp/Xdmx parameter list */
   config_read_vnc_params(fd, cfg, param_n, param_v);
   config_read_rdp_params(fd, cfg, param_n, param_v);
+  config_read_dmx_params(fd, cfg, param_n, param_v);
 
   /* read logging config */
   config_read_logging(fd, &(cfg->log), param_n, param_v);
@@ -340,6 +342,10 @@ config_read_sessions(int file, struct config_sessions* se, struct list* param_n,
     if (0 == g_strcasecmp(buf, SESMAN_CFG_SESS_MAX))
     {
       se->max_sessions = g_atoi((char*)list_get_item(param_v, i));
+      if (se->max_sessions > MAX_SESSIONS_LIMIT)
+	  se->max_sessions = MAX_SESSIONS_LIMIT;
+      else if (se->max_sessions < 1)
+	  se->max_sessions = 1;
     }
     if (0 == g_strcasecmp(buf, SESMAN_CFG_SESS_KILL_DISC))
     {
@@ -421,3 +427,30 @@ config_read_vnc_params(int file, struct config_sesman* cs, struct list* param_n,
   return 0;
 }
 
+/******************************************************************************/
+int DEFAULT_CC
+config_read_dmx_params(int file, struct config_sesman* cs, struct list* param_n,
+                       struct list* param_v)
+{
+  int i;
+
+  list_clear(param_v);
+  list_clear(param_n);
+
+  cs->dmx_params=list_create();
+
+  file_read_section(file, SESMAN_CFG_DMX_PARAMS, param_n, param_v);
+  for (i = 0; i < param_n->count; i++)
+  {
+    list_add_item(cs->dmx_params, (long)g_strdup((char*)list_get_item(param_v, i)));
+  }
+
+  /* printing security config */
+  g_printf("Xdmx parameters:\r\n");
+  for (i = 0; i < cs->dmx_params->count; i++)
+  {
+    g_printf("\tParameter %02d                   %s\r\n", i, (char*)list_get_item(cs->dmx_params, i));
+  }
+
+  return 0;
+}
diff --git a/sesman/config.h b/sesman/config.h
index 11b3e58..312c48e 100644
--- a/sesman/config.h
+++ b/sesman/config.h
@@ -53,6 +53,7 @@
 
 #define SESMAN_CFG_RDP_PARAMS        "X11rdp"
 #define SESMAN_CFG_VNC_PARAMS        "Xvnc"
+#define SESMAN_CFG_DMX_PARAMS        "Xdmx"
 
 #define SESMAN_CFG_LOGGING           "Logging"
 #define SESMAN_CFG_LOG_FILE          "LogFile"
@@ -187,6 +188,11 @@ struct config_sesman
    */
   struct list* rdp_params;
   /**
+   * @var dmx_params
+   * @brief Xdmx additional parameter list
+   */
+  struct list* dmx_params;
+  /**
    * @var log
    * @brief Log configuration struct
    */
@@ -298,5 +304,20 @@ int DEFAULT_CC
 config_read_vnc_params(int file, struct config_sesman* cs, struct list* param_n,
                        struct list* param_v);
 
+
+/**
+ *
+ * @brief Reads sesman [Xdmx] configuration section
+ * @param file configuration file descriptor
+ * @param cs pointer to a config_sesman struct
+ * @param param_n parameter name list
+ * @param param_v parameter value list
+ * @return 0 on success, 1 on failure
+ *
+ */
+int DEFAULT_CC
+config_read_dmx_params(int file, struct config_sesman* cs, struct list* param_n,
+                       struct list* param_v);
+
 #endif
 
diff --git a/sesman/env.c b/sesman/env.c
index 066277d..a8ba865 100644
--- a/sesman/env.c
+++ b/sesman/env.c
@@ -60,7 +60,7 @@ env_check_password_file(char* filename, char* password)
 
 /******************************************************************************/
 int DEFAULT_CC
-env_set_user(char* username, char* passwd_file, int display)
+env_set_user(char* username, char* passwd_file, int display, char* auth_file)
 {
   int error;
   int pw_uid;
@@ -97,6 +97,7 @@ env_set_user(char* username, char* passwd_file, int display)
       g_set_current_dir(pw_dir);
       g_sprintf(text, ":%d.0", display);
       g_setenv("DISPLAY", text, 1);
+      g_setenv("XAUTHORITY", auth_file, 1);
       if (passwd_file != 0)
       {
         if (0 == g_cfg->auth_file_path)
diff --git a/sesman/env.h b/sesman/env.h
index 77deb08..63544f8 100644
--- a/sesman/env.h
+++ b/sesman/env.h
@@ -45,11 +45,12 @@ env_check_password_file(char* filename, char* password);
  * @param username Username 
  * @param passwd_file VNC password file
  * @param display The session display
+ * @param auth_File The session authorization file
  * @return 0 on success, g_getuser_info() error codes on error
  *
  */
 int DEFAULT_CC
-env_set_user(char* username, char* passwd_file, int display);
+env_set_user(char* username, char* passwd_file, int display, char* auth_file);
 
 #endif
 
diff --git a/sesman/libscp/libscp_session.c b/sesman/libscp/libscp_session.c
index 6f86e20..fabc093 100644
--- a/sesman/libscp/libscp_session.c
+++ b/sesman/libscp/libscp_session.c
@@ -48,9 +48,11 @@ scp_session_create()
 
   s->username = 0;
   s->password = 0;
+  s->wm = 0;
   s->hostname = 0;
   s->errstr = 0;
   s->locale[0]='\0';
+  s->layout = 0x409;
 
   return s;
 }
@@ -67,6 +69,9 @@ scp_session_set_type(struct SCP_SESSION* s, tui8 type)
     case SCP_SESSION_TYPE_XRDP:
       s->type = SCP_SESSION_TYPE_XRDP;
       break;
+    case SCP_SESSION_TYPE_XDMX:
+      s->type = SCP_SESSION_TYPE_XDMX;
+      break;
     case SCP_SESSION_TYPE_MANAGE:
       s->type = SCP_SESSION_TYPE_MANAGE;
       break;
@@ -204,6 +209,28 @@ scp_session_set_password(struct SCP_SESSION* s, char* str)
 
 /*******************************************************************/
 int
+scp_session_set_wm(struct SCP_SESSION* s, char* str)
+{
+  if (0 == str)
+  {
+    log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_wm: null wm", __LINE__);
+    return 1;
+  }
+  if (0 != s->wm)
+  {
+    g_free(s->wm);
+  }
+  s->wm = g_strdup(str);
+  if (0 == s->wm)
+  {
+    log_message(s_log, LOG_LEVEL_WARNING, "[session:%d] set_wm: strdup error", __LINE__);
+    return 1;
+  }
+  return 0;
+}
+
+/*******************************************************************/
+int
 scp_session_set_hostname(struct SCP_SESSION* s, char* str)
 {
   if (0 == str)
@@ -305,6 +332,14 @@ scp_session_set_addr(struct SCP_SESSION* s, int type, void* addr)
 }
 
 /*******************************************************************/
+int
+scp_session_set_layout(struct SCP_SESSION* s, tui16 layout)
+{
+  s->layout = layout;
+  return 0;
+}
+
+/*******************************************************************/
 void
 scp_session_destroy(struct SCP_SESSION* s)
 {
diff --git a/sesman/libscp/libscp_session.h b/sesman/libscp/libscp_session.h
index aefeb20..eacc109 100644
--- a/sesman/libscp/libscp_session.h
+++ b/sesman/libscp/libscp_session.h
@@ -69,6 +69,9 @@ int
 scp_session_set_password(struct SCP_SESSION* s, char* str);
 
 int
+scp_session_set_wm(struct SCP_SESSION* s, char* str);
+
+int
 scp_session_set_hostname(struct SCP_SESSION* s, char* str);
 
 int
@@ -80,6 +83,9 @@ scp_session_set_display(struct SCP_SESSION* s, SCP_DISPLAY display);
 int
 scp_session_set_errstr(struct SCP_SESSION* s, char* str);
 
+int
+scp_session_set_layout(struct SCP_SESSION* s, tui16 layout);
+
 /**
  *
  * @brief destroys a session object
diff --git a/sesman/libscp/libscp_types.h b/sesman/libscp/libscp_types.h
index b8b5d6b..04350aa 100644
--- a/sesman/libscp/libscp_types.h
+++ b/sesman/libscp/libscp_types.h
@@ -41,7 +41,8 @@
 
 #define SCP_SESSION_TYPE_XVNC    0x00
 #define SCP_SESSION_TYPE_XRDP    0x01
-#define SCP_SESSION_TYPE_MANAGE  0x02
+#define SCP_SESSION_TYPE_XDMX    0x02
+#define SCP_SESSION_TYPE_MANAGE  0x03
 
 #define SCP_ADDRESS_TYPE_IPV4 0x00
 #define SCP_ADDRESS_TYPE_IPV6 0x01
@@ -77,11 +78,13 @@ struct SCP_SESSION
   char* username;
   char* password;
   char* hostname;
+  char* wm;
   tui8  addr_type;
   tui32 ipv4addr;
   tui8  ipv6addr[16];
   tui16 display;
   char* errstr;
+  tui16 layout;
 };
 
 struct SCP_DISCONNECTED_SESSION
diff --git a/sesman/libscp/libscp_v0.c b/sesman/libscp/libscp_v0.c
index bd94146..7ccf745 100644
--- a/sesman/libscp/libscp_v0.c
+++ b/sesman/libscp/libscp_v0.c
@@ -56,6 +56,10 @@ enum SCP_CLIENT_STATES_E scp_v0c_connect(struct SCP_CONNECTION* c, struct SCP_SE
   {
     out_uint16_be(c->out_s, 10);
   }
+  else if (s->type == SCP_SESSION_TYPE_XDMX)
+  {
+    out_uint16_be(c->out_s, 20);
+  }
   else
   {
     log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__);
@@ -68,6 +72,9 @@ enum SCP_CLIENT_STATES_E scp_v0c_connect(struct SCP_CONNECTION* c, struct SCP_SE
   sz = g_strlen(s->password);
   out_uint16_be(c->out_s,sz);
   out_uint8a(c->out_s, s->password, sz);
+  sz = g_strlen(s->wm);
+  out_uint16_be(c->out_s,sz);
+  out_uint8a(c->out_s, s->wm, sz);
   out_uint16_be(c->out_s, s->width);
   out_uint16_be(c->out_s, s->height);
   out_uint16_be(c->out_s, s->bpp);
@@ -168,6 +175,11 @@ enum SCP_SERVER_STATES_E scp_v0s_accept(struct SCP_CONNECTION* c, struct SCP_SES
   }
 
   in_uint32_be(c->in_s, size);
+  if (size < 24 || size > 8196)
+  {
+    log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: size error", __LINE__);
+    return SCP_SERVER_STATE_SIZE_ERR;
+  }
 
   init_stream(c->in_s, 8196);
   if (0!=scp_tcp_force_recv(c->in_sck, c->in_s->data, size-8))
@@ -176,9 +188,11 @@ enum SCP_SERVER_STATES_E scp_v0s_accept(struct SCP_CONNECTION* c, struct SCP_SES
     return SCP_SERVER_STATE_NETWORK_ERR;
   }
 
+  size -= 24;
+
   in_uint16_be(c->in_s, code);
 
-  if (code == 0 || code == 10)
+  if (code == 0 || code == 10 || code == 20)
   {
 	session = scp_session_create();
     if (0 == session)
@@ -192,13 +206,24 @@ enum SCP_SERVER_STATES_E scp_v0s_accept(struct SCP_CONNECTION* c, struct SCP_SES
     {
       scp_session_set_type(session, SCP_SESSION_TYPE_XVNC);
     }
-    else
+    else if (code == 10)
     {
       scp_session_set_type(session, SCP_SESSION_TYPE_XRDP);
     }
+    else
+    {
+      scp_session_set_type(session, SCP_SESSION_TYPE_XDMX);
+    }
 
     /* reading username */
     in_uint16_be(c->in_s, sz);
+    if (sz >= sizeof (buf) || sz > size)
+    {
+      scp_session_destroy(session);
+      log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: size error", __LINE__);
+      return SCP_SERVER_STATE_SIZE_ERR;
+    }
+    size -= sz;
     buf[sz]='\0';
     in_uint8a(c->in_s, buf, sz);
     if (0 != scp_session_set_username(session, buf))
@@ -210,6 +235,13 @@ enum SCP_SERVER_STATES_E scp_v0s_accept(struct SCP_CONNECTION* c, struct SCP_SES
 
     /* reading password */
     in_uint16_be(c->in_s, sz);
+    if (sz >= sizeof (buf) || sz > size)
+    {
+      scp_session_destroy(session);
+      log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: size error", __LINE__);
+      return SCP_SERVER_STATE_SIZE_ERR;
+    }
+    size -= sz;
     buf[sz]='\0';
     in_uint8a(c->in_s, buf, sz);
     if (0 != scp_session_set_password(session, buf))
@@ -219,6 +251,24 @@ enum SCP_SERVER_STATES_E scp_v0s_accept(struct SCP_CONNECTION* c, struct SCP_SES
       return SCP_SERVER_STATE_INTERNAL_ERR;
     }
 
+    /* reading wm */
+    in_uint16_be(c->in_s, sz);
+    if (sz >= sizeof (buf) || sz > size)
+    {
+      scp_session_destroy(session);
+      log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: size error", __LINE__);
+      return SCP_SERVER_STATE_SIZE_ERR;
+    }
+    size -= sz;
+    buf[sz]='\0';
+    in_uint8a(c->in_s, buf, sz);
+    if (0 != scp_session_set_wm(session, buf))
+    {
+      scp_session_destroy(session);
+      log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: error setting wm", __LINE__);
+      return SCP_SERVER_STATE_INTERNAL_ERR;
+    }
+
     /* width */
     in_uint16_be(c->in_s, sz);
     scp_session_set_width(session, sz);
@@ -228,6 +278,9 @@ enum SCP_SERVER_STATES_E scp_v0s_accept(struct SCP_CONNECTION* c, struct SCP_SES
     /* bpp */
     in_uint16_be(c->in_s, sz);
     scp_session_set_bpp(session, (tui8)sz);
+    /* layout */
+    in_uint16_be(c->in_s, sz);
+    scp_session_set_layout(session, (tui16)sz);
   }
   else
   {
diff --git a/sesman/libscp/libscp_v1s.c b/sesman/libscp/libscp_v1s.c
index 74ce187..4f5009c 100644
--- a/sesman/libscp/libscp_v1s.c
+++ b/sesman/libscp/libscp_v1s.c
@@ -67,19 +67,21 @@ 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)
+  if (size < 40 || size > 8196)
   {
     log_message(s_log, 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);
+  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, "[v1s:%d] connection aborted: network error", __LINE__);
     return SCP_SERVER_STATE_NETWORK_ERR;
   }
 
+  size -= 40;
+
   /* reading command set */
   in_uint16_be(c->in_s, cmdset);
 
@@ -114,7 +116,9 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES
   scp_session_set_version(session, 1);
 
   in_uint8(c->in_s, sz);
-  if ((sz != SCP_SESSION_TYPE_XVNC) && (sz != SCP_SESSION_TYPE_XRDP))
+  if ((sz != SCP_SESSION_TYPE_XVNC) &&
+      (sz != SCP_SESSION_TYPE_XRDP) &&
+      (sz != SCP_SESSION_TYPE_XDMX))
   {
     scp_session_destroy(session);
     log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: unknown session type", __LINE__);
@@ -135,20 +139,40 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES
   scp_session_set_locale(session, buf);
 
   in_uint8(c->in_s, sz);
-  if (sz == SCP_ADDRESS_TYPE_IPV4)
+  if (sz == SCP_ADDRESS_TYPE_IPV6)
+      sz = 16;
+  else
+      sz = 4;
+
+  if (sz > size)
   {
-    in_uint32_be(c->in_s, size);
-    scp_session_set_addr(session, SCP_ADDRESS_TYPE_IPV4_BIN, &size);
+    scp_session_destroy(session);
+    log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: size error", __LINE__);
+    return SCP_SERVER_STATE_SIZE_ERR;
   }
-  else if (sz == SCP_ADDRESS_TYPE_IPV6)
+  size -= sz;
+
+  if (sz == 4)
+  {
+    tui32 addr;
+    in_uint32_be(c->in_s, addr);
+    scp_session_set_addr(session, SCP_ADDRESS_TYPE_IPV4_BIN, &addr);
+  }
+  else
   {
     in_uint8a(c->in_s, buf, 16);
     scp_session_set_addr(session, SCP_ADDRESS_TYPE_IPV6_BIN, buf);
   }
 
-  buf[256] = '\0';
   /* reading hostname */
   in_uint8(c->in_s, sz);
+  if (sz > size)
+  {
+    scp_session_destroy(session);
+    log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: size error", __LINE__);
+    return SCP_SERVER_STATE_SIZE_ERR;
+  }
+  size -= sz;
   buf[sz]='\0';
   in_uint8a(c->in_s, buf, sz);
   if (0 != scp_session_set_hostname(session, buf))
@@ -160,6 +184,13 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES
 
   /* reading username */
   in_uint8(c->in_s, sz);
+  if (sz > size)
+  {
+    scp_session_destroy(session);
+    log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: size error", __LINE__);
+    return SCP_SERVER_STATE_SIZE_ERR;
+  }
+  size -= sz;
   buf[sz]='\0';
   in_uint8a(c->in_s, buf, sz);
   if (0 != scp_session_set_username(session, buf))
@@ -171,6 +202,13 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES
 
   /* reading password */
   in_uint8(c->in_s, sz);
+  if (sz > size)
+  {
+    scp_session_destroy(session);
+    log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: size error", __LINE__);
+    return SCP_SERVER_STATE_SIZE_ERR;
+  }
+  size -= sz;
   buf[sz]='\0';
   in_uint8a(c->in_s, buf, sz);
   if (0 != scp_session_set_password(session, buf))
@@ -229,14 +267,14 @@ scp_v1s_request_password(struct SCP_CONNECTION* c, struct SCP_SESSION* s, char*
   int rlen;
   char buf[257];
 
-  init_stream(c->in_s, c->in_s->size);
-  init_stream(c->out_s, c->out_s->size);
+  init_stream(c->in_s, 8);
+  init_stream(c->out_s, 14 + 4096);
 
-  /* forcing message not to exceed 64k */
+  /* forcing message not to exceed 4k */
   rlen = g_strlen(reason);
-  if (rlen > 65535)
+  if (rlen > 4096)
   {
-    rlen = 65535;
+    rlen = 4096;
   }
 
   /* send password request */
@@ -274,18 +312,19 @@ scp_v1s_request_password(struct SCP_CONNECTION* c, struct SCP_SESSION* s, char*
   }
 
   in_uint32_be(c->in_s, size);
-  if (size<12)
+  if (size<12 || size > 8192)
   {
     log_message(s_log, 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);
+  init_stream(c->in_s, size-8);
   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__);
     return SCP_SERVER_STATE_NETWORK_ERR;
   }
+  size -= 14;
 
   in_uint16_be(c->in_s, cmdset);
   if (cmdset != SCP_COMMAND_SET_DEFAULT)
@@ -301,25 +340,34 @@ scp_v1s_request_password(struct SCP_CONNECTION* c, struct SCP_SESSION* s, char*
     return SCP_SERVER_STATE_SEQUENCE_ERR;
   }
 
-  buf[256] = '\0';
   /* reading username */
   in_uint8(c->in_s, sz);
+  if (sz > size)
+  {
+    log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: size error", __LINE__);
+    return SCP_SERVER_STATE_SIZE_ERR;
+  }
+  size -= sz;
   buf[sz] = '\0';
   in_uint8a(c->in_s, buf, sz);
   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__);
     return SCP_SERVER_STATE_INTERNAL_ERR;
   }
 
   /* reading password */
   in_uint8(c->in_s, sz);
+  if (sz > size)
+  {
+    log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: size error", __LINE__);
+    return SCP_SERVER_STATE_SIZE_ERR;
+  }
+  size -= sz;
   buf[sz]='\0';
   in_uint8a(c->in_s, buf, sz);
   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__);
     return SCP_SERVER_STATE_INTERNAL_ERR;
   }
@@ -390,7 +438,7 @@ scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNEC
   struct SCP_DISCONNECTED_SESSION* cds;
 
   /* first we send a notice that we have some disconnected sessions */
-  init_stream(c->out_s, c->out_s->size);
+  init_stream(c->out_s, 12);
 
   out_uint32_be(c->out_s, version);                 /* version */
   out_uint32_be(c->out_s, size);                    /* size    */
@@ -406,7 +454,7 @@ scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNEC
   /* then we wait for client ack */
 #warning maybe this message could say if the session should be resized on
 #warning server side or client side
-  init_stream(c->in_s, c->in_s->size);
+  init_stream(c->in_s, 8192);
   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__);
@@ -421,14 +469,14 @@ scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNEC
   }
 
   in_uint32_be(c->in_s, size);
-  if (size<12)
+  if (size !=12)
   {
     log_message(s_log, 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)))
+  init_stream(c->in_s, 4);
+  if (0!=scp_tcp_force_recv(c->in_sck, c->in_s->data, 4))
   {
     log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
     return SCP_SERVER_STATE_NETWORK_ERR;
@@ -458,7 +506,7 @@ scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNEC
   for (idx=0; idx<pktcnt; idx++)
   {
     /* ok, we send session session list */
-    init_stream(c->out_s, c->out_s->size);
+    init_stream(c->out_s, 8192);
 
     /* size: ver+size+cmdset+cmd+sescnt+continue+count */
     size=4+4+2+2+4+1+1;
@@ -537,7 +585,7 @@ scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNEC
   }
 
   /* we get the response */
-  init_stream(c->in_s, c->in_s->size);
+  init_stream(c->in_s, 8);
   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__);
@@ -552,14 +600,14 @@ scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNEC
   }
 
   in_uint32_be(c->in_s, size);
-  if (size < 12)
+  if (size < 12 || size > 16)
   {
     log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__);
     return SCP_SERVER_STATE_SIZE_ERR;
   }
 
   /* rest of the packet */
-  init_stream(c->in_s, c->in_s->size);
+  init_stream(c->in_s, size-8);
   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__);
@@ -576,6 +624,12 @@ scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNEC
   in_uint16_be(c->in_s, cmd);
   if (cmd == 43)
   {
+    if (size < 16)
+    {
+      log_message(s_log, LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__);
+      return SCP_SERVER_STATE_SIZE_ERR;
+    }
+	
     /* select session */
     in_uint32_be(c->in_s, (*sid));
 
@@ -624,7 +678,7 @@ scp_v1s_reconnect_session(struct SCP_CONNECTION* c, SCP_DISPLAY d)
   tui16 cmd = 46;
 
   /* ok, we send session data and display */
-  init_stream(c->out_s, c->out_s->size);
+  init_stream(c->out_s, size);
 
   /* header */
   out_uint32_be(c->out_s, version);
diff --git a/sesman/scp_v0.c b/sesman/scp_v0.c
index e006ad3..c3ba11d 100644
--- a/sesman/scp_v0.c
+++ b/sesman/scp_v0.c
@@ -57,14 +57,20 @@ scp_v0_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s)
         if (SCP_SESSION_TYPE_XVNC == s->type)
         {
           log_message(&(g_cfg->log), LOG_LEVEL_INFO, "starting Xvnc session...");
-          display = session_start(s->width, s->height, s->bpp, s->username, s->password,
-                                  data, SESMAN_SESSION_TYPE_XVNC);
+          display = session_start(s->width, s->height, s->bpp, s->layout, s->username, s->password,
+                                  s->wm, data, SESMAN_SESSION_TYPE_XVNC);
         }
-        else
+        else if (SCP_SESSION_TYPE_XRDP == s->type)
         {
           log_message(&(g_cfg->log), LOG_LEVEL_INFO, "starting X11rdp session...");
-          display = session_start(s->width, s->height, s->bpp, s->username, s->password,
-                                  data, SESMAN_SESSION_TYPE_XRDP);
+          display = session_start(s->width, s->height, s->bpp, s->layout, s->username, s->password,
+                                  s->wm, data, SESMAN_SESSION_TYPE_XRDP);
+        }
+	else
+        {
+          log_message(&(g_cfg->log), LOG_LEVEL_INFO, "starting Xdmx session...");
+          display = session_start(s->width, s->height, s->bpp, s->layout, s->username, s->password,
+                                  s->wm, data, SESMAN_SESSION_TYPE_XDMX);
         }
       }
       else
diff --git a/sesman/scp_v1.c b/sesman/scp_v1.c
index c5ff2d4..7315fae 100644
--- a/sesman/scp_v1.c
+++ b/sesman/scp_v1.c
@@ -111,14 +111,20 @@ scp_v1_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s)
     if (SCP_SESSION_TYPE_XVNC == s->type)
     {
       log_message(&(g_cfg->log), LOG_LEVEL_INFO, "starting Xvnc session...");
-      display = session_start(s->width, s->height, s->bpp, s->username,
-                              s->password, data, SESMAN_SESSION_TYPE_XVNC);
+      display = session_start(s->width, s->height, s->bpp, s->layout, s->username,
+                              s->password, s->wm, data, SESMAN_SESSION_TYPE_XVNC);
     }
-    else
+    else if (SCP_SESSION_TYPE_XRDP == s->type)
     {
       log_message(&(g_cfg->log), LOG_LEVEL_INFO, "starting X11rdp session...");
-      display = session_start(s->width, s->height, s->bpp, s->username,
-                              s->password, data, SESMAN_SESSION_TYPE_XRDP);
+      display = session_start(s->width, s->height, s->bpp, s->layout, s->username,
+                              s->password, s->wm, data, SESMAN_SESSION_TYPE_XRDP);
+    }
+    else
+    {
+      log_message(&(g_cfg->log), LOG_LEVEL_INFO, "starting Xdmx session...");
+      display = session_start(s->width, s->height, s->bpp, s->layout, s->username,
+                              s->password, s->wm, data, SESMAN_SESSION_TYPE_XDMX);
     }
 
     e = scp_v1s_connect_new_session(c, display);
diff --git a/sesman/sesman.c b/sesman/sesman.c
index c7522c7..10e5393 100644
--- a/sesman/sesman.c
+++ b/sesman/sesman.c
@@ -273,13 +273,6 @@ main(int argc, char** argv)
   /* start program main loop */
   log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "starting sesman with pid %d", g_pid);
 
-  /* make sure the /tmp/.X11-unix directory exist */
-  if (!g_directory_exist("/tmp/.X11-unix"))
-  {
-    g_create_dir("/tmp/.X11-unix");
-    g_chmod_hex("/tmp/.X11-unix", 0x1777);
-  }
-
   sesman_main_loop();
 
   if (!daemon)
diff --git a/sesman/sesman.ini b/sesman/sesman.ini
index fd240e7..a8de2bd 100644
--- a/sesman/sesman.ini
+++ b/sesman/sesman.ini
@@ -25,8 +25,14 @@ SyslogLevel=DEBUG
 
 [X11rdp]
 param1=-bs
-param2=-ac
 
 [Xvnc]
 param1=-bs
-param2=-ac
+
+[Xdmx]
+param1=-br
+param2=-noreset
+param3=-nolisten
+param4=tcp
+param5=--
+param6=/usr/bin/Xfake
diff --git a/sesman/session.c b/sesman/session.c
index 54e02ad..1eab77d 100644
--- a/sesman/session.c
+++ b/sesman/session.c
@@ -29,12 +29,24 @@
 #include "libscp_types.h"
 
 #include <errno.h>
-//#include <time.h>
+#include <stdio.h>
+#ifndef _WIN32
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <X11/Xauth.h>
+#include <xcb/xcb.h>
+#endif
+#include <dbus/dbus.h>
 
 extern unsigned char g_fixedkey[8];
 extern struct config_sesman* g_cfg; /* config.h */
-struct session_chain* g_sessions;
-int g_session_count;
+struct session_chain* g_sessions = NULL;
+int g_session_count = 0;
 
 /******************************************************************************/
 struct session_item* DEFAULT_CC
@@ -49,14 +61,23 @@ session_get_bydata(char* name, int width, int height, int bpp)
 
   while (tmp != 0)
   {
-    if (g_strncmp(name, tmp->item->name, 255) == 0 &&
-        tmp->item->width == width &&
-        tmp->item->height == height &&
-        tmp->item->bpp == bpp)
+    if (g_strncmp(name, tmp->item->name, 255) == 0)
     {
-      /*THREAD-FIX release chain lock */
-      lock_chain_release();
-      return tmp->item;
+      if (tmp->item->type == SESMAN_SESSION_TYPE_XDMX)
+      {
+	/*THREAD-FIX release chain lock */
+        lock_chain_release();
+        return tmp->item;
+      }
+
+      if (tmp->item->bpp == bpp &&
+	  tmp->item->width == width &&
+	  tmp->item->height == height)
+      {
+        /*THREAD-FIX release chain lock */
+        lock_chain_release();
+        return tmp->item;
+      }
     }
     tmp = tmp->next;
   }
@@ -67,52 +88,6 @@ session_get_bydata(char* name, int width, int height, int bpp)
 }
 
 /******************************************************************************/
-/**
- *
- * @brief checks if there's a server running on a display
- * @param display the display to check
- * @return 0 if there isn't a display running, nonzero otherwise
- *
- */
-static int DEFAULT_CC
-x_server_running(int display)
-{
-  char text[256];
-  int x_running;
-  int sck;
-
-  g_sprintf(text, "/tmp/.X11-unix/X%d", display);
-  x_running = g_file_exist(text);
-  if (!x_running)
-  {
-    g_sprintf(text, "/tmp/.X%d-lock", display);
-    x_running = g_file_exist(text);
-  }
-  if (!x_running) /* check 59xx */
-  {
-    sck = g_tcp_socket();
-    g_sprintf(text, "59%2.2d", display);
-    x_running = g_tcp_bind(sck, text);
-    g_tcp_close(sck);
-  }
-  if (!x_running) /* check 60xx */
-  {
-    sck = g_tcp_socket();
-    g_sprintf(text, "60%2.2d", display);
-    x_running = g_tcp_bind(sck, text);
-    g_tcp_close(sck);
-  }
-  if (!x_running) /* check 62xx */
-  {
-    sck = g_tcp_socket();
-    g_sprintf(text, "62%2.2d", display);
-    x_running = g_tcp_bind(sck, text);
-    g_tcp_close(sck);
-  }
-  return x_running;
-}
-
-/******************************************************************************/
 static void DEFAULT_CC
 session_start_sessvc(int xpid, int wmpid, long data)
 {
@@ -171,12 +146,340 @@ session_start_sessvc(int xpid, int wmpid, long data)
 }
 
 /******************************************************************************/
+static dbus_bool_t
+add_param_basic (DBusMessageIter *iter_array,
+                 const char      *name,
+                 int              type,
+                 const void      *value)
+{
+    DBusMessageIter iter_struct;
+    DBusMessageIter iter_variant;
+    const char     *container_type;
+
+    switch (type) {
+    case DBUS_TYPE_STRING:
+	container_type = DBUS_TYPE_STRING_AS_STRING;
+	break;
+    case DBUS_TYPE_BOOLEAN:
+	container_type = DBUS_TYPE_BOOLEAN_AS_STRING;
+	break;
+    case DBUS_TYPE_INT32:
+	container_type = DBUS_TYPE_INT32_AS_STRING;
+	break;
+    default:
+	goto oom;
+	break;
+    }
+
+    if (! dbus_message_iter_open_container (iter_array,
+					    DBUS_TYPE_STRUCT,
+					    NULL,
+					    &iter_struct)) {
+	goto oom;
+    }
+
+    if (! dbus_message_iter_append_basic (&iter_struct,
+					  DBUS_TYPE_STRING,
+					  &name)) {
+	goto oom;
+    }
+
+    if (! dbus_message_iter_open_container (&iter_struct,
+					    DBUS_TYPE_VARIANT,
+					    container_type,
+					    &iter_variant)) {
+	goto oom;
+    }
+
+    if (! dbus_message_iter_append_basic (&iter_variant,
+					  type,
+					  value)) {
+	goto oom;
+    }
+
+    if (! dbus_message_iter_close_container (&iter_struct,
+					     &iter_variant)) {
+	goto oom;
+    }
+
+    if (! dbus_message_iter_close_container (iter_array,
+					     &iter_struct)) {
+	goto oom;
+    }
+
+    return TRUE;
+oom:
+    return FALSE;
+}
+
+static char *
+session_ck_open_session (DBusConnection *connection,
+			 const char     *username,
+			 int            display)
+{
+    DBusError       error;
+    DBusMessage     *message;
+    DBusMessage     *reply;
+    DBusMessageIter iter;
+    DBusMessageIter iter_array;
+    dbus_bool_t     res;
+    char            *ret;
+    char            *cookie;
+    dbus_bool_t     is_local = FALSE;
+    dbus_bool_t     active = TRUE;
+    int             uid;
+    char            display_str[256];
+    const char      *x11_display = display_str;
+    const char      *session_type = "rdp";
+
+    reply = NULL;
+    message = NULL;
+    ret = NULL;
+
+    g_sprintf(display_str, ":%d", display);
+
+    if (g_getuser_info(username, 0, &uid, 0, 0, 0))
+	goto out;
+
+    message =
+	dbus_message_new_method_call ("org.freedesktop.ConsoleKit",
+				      "/org/freedesktop/ConsoleKit/Manager",
+				      "org.freedesktop.ConsoleKit.Manager",
+				      "OpenSessionWithParameters");
+    if (message == NULL) {
+	goto out;
+    }
+
+    dbus_message_iter_init_append (message, &iter);
+    if (! dbus_message_iter_open_container (&iter,
+					    DBUS_TYPE_ARRAY,
+					    "(sv)",
+					    &iter_array)) {
+	goto out;
+    }
+
+    if (!add_param_basic (&iter_array,
+			  "unix-user",
+			  DBUS_TYPE_INT32,
+			  &uid) ||
+	!add_param_basic (&iter_array,
+			  "x11-display",
+			  DBUS_TYPE_STRING,
+			  &x11_display) ||
+	!add_param_basic (&iter_array,
+			  "is-local",
+			  DBUS_TYPE_BOOLEAN,
+			  &is_local) ||
+	!add_param_basic (&iter_array,
+			  "active",
+			  DBUS_TYPE_BOOLEAN,
+			  &active) ||
+	!add_param_basic (&iter_array,
+			  "session-type",
+			  DBUS_TYPE_STRING,
+			  &session_type)) {
+	log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS,
+		    "Error adding ck session parameter");
+	goto out;
+    }
+
+    if (! dbus_message_iter_close_container (&iter, &iter_array)) {
+	goto out;
+    }
+
+    dbus_error_init (&error);
+    reply = dbus_connection_send_with_reply_and_block (connection,
+						       message,
+						       -1,
+						       &error);
+    if (reply == NULL) {
+	if (dbus_error_is_set (&error)) {
+	    log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS,
+			"Unable to open session: %s",
+			error.message);
+	    dbus_error_free (&error);
+	    goto out;
+	}
+    }
+
+    dbus_error_init (&error);
+    if (! dbus_message_get_args (reply,
+				 &error,
+				 DBUS_TYPE_STRING, &cookie,
+				 DBUS_TYPE_INVALID)) {
+	if (dbus_error_is_set (&error)) {
+	    log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS,
+			"Unable to open session: %s",
+			error.message);
+	    dbus_error_free (&error);
+	    goto out;
+	}
+    }
+
+    ret = g_strdup (cookie);
+
+out:
+    if (reply != NULL) {
+	dbus_message_unref (reply);
+    }
+
+    if (message != NULL) {
+	dbus_message_unref (message);
+    }
+
+    return ret;
+}
+
+static void
+session_ck_close_session (DBusConnection *connection,
+			  char           *cookie)
+{
+    DBusError   error;
+    DBusMessage *message;
+    DBusMessage *reply;
+
+    reply = NULL;
+    message = NULL;
+
+    if (cookie == NULL) {
+	goto out;
+    }
+
+    message =
+	dbus_message_new_method_call ("org.freedesktop.ConsoleKit",
+				      "/org/freedesktop/ConsoleKit/Manager",
+				      "org.freedesktop.ConsoleKit.Manager",
+				      "CloseSession");
+    if (message == NULL) {
+	goto out;
+    }
+
+    if (! dbus_message_append_args (message,
+				    DBUS_TYPE_STRING, &cookie,
+				    DBUS_TYPE_INVALID)) {
+	goto out;
+    }
+
+    dbus_error_init (&error);
+    reply = dbus_connection_send_with_reply_and_block (connection,
+						       message,
+						       -1,
+						       &error);
+    if (reply == NULL) {
+	if (dbus_error_is_set (&error)) {
+	    g_printf("\n[sessvc] Unable to close session: %s",
+		     error.message);
+	    dbus_error_free (&error);
+	    goto out;
+	}
+    }
+
+out:
+    if (reply != NULL) {
+	dbus_message_unref (reply);
+    }
+
+    if (message != NULL) {
+	dbus_message_unref (message);
+    }
+}
+
+/******************************************************************************/
+#ifndef _WIN32
+static int     received_usr1;
+static jmp_buf jumpbuf;
+
+static void
+sig_usr1_waiting (int sig)
+{
+    signal (sig, sig_usr1_waiting);
+    received_usr1++;
+}
+
+static void
+sig_usr1_jump (int sig)
+{
+    sigset_t set;
+
+    signal (sig, sig_usr1_waiting);
+
+    sigemptyset (&set);
+    sigaddset (&set, SIGUSR1);
+    sigprocmask (SIG_UNBLOCK, &set, NULL);
+
+    longjmp (jumpbuf, 1);
+}
+
+#define AUTH_DATA_LEN 16 /* bytes of authorization data */
+
+static int
+session_setup_auth (char* display,
+		    char* auth_data,
+		    int   auth_fd)
+{
+    Xauth   auth;
+    int	    random_fd, i;
+    ssize_t bytes, size;
+    char    auth_host[256];
+    FILE    *file;
+
+    auth.family = FamilyLocal;
+
+    gethostname (auth_host, sizeof (auth_host));
+
+    auth.address	= auth_host;
+    auth.address_length = strlen (auth_host);
+
+    auth.number        = display;
+    auth.number_length = strlen (auth.number);
+
+    auth.name	     = "MIT-MAGIC-COOKIE-1";
+    auth.name_length = strlen (auth.name);
+
+    random_fd = open ("/dev/urandom", O_RDONLY);
+    if (random_fd == -1)
+	return 1;
+
+    bytes = 0;
+    do {
+	size = read (random_fd, auth_data + bytes, AUTH_DATA_LEN - bytes);
+	if (size <= 0)
+	    break;
+
+	bytes += size;
+    } while (bytes != AUTH_DATA_LEN);
+
+    close (random_fd);
+
+    if (bytes != AUTH_DATA_LEN)
+	return 1;
+
+    auth.data	     = auth_data;
+    auth.data_length = AUTH_DATA_LEN;
+
+    file = fdopen (auth_fd, "w");
+    if (!file)
+    {
+	close (auth_fd);
+	return 1;
+    }
+
+    XauWriteAuth (file, &auth);
+    fclose (file);
+
+    return 0;
+}
+#endif
+
+/******************************************************************************/
 int DEFAULT_CC
-session_start(int width, int height, int bpp, char* username, char* password,
-              long data, unsigned char type)
+session_start(int width, int height, int bpp, int layout,
+	      char* username, char* password,
+              char* wm, long data, unsigned char type)
 {
   int display;
   int pid;
+  int xkbpid;
   int wmpid;
   int xpid;
   int i;
@@ -190,6 +493,10 @@ session_start(int width, int height, int bpp, char* username, char* password,
   struct list* xserver_params=0;
   time_t ltime;
   struct tm stime;
+  char *ck_cookie;
+  DBusConnection *connection;
+  DBusError error;
+  int pipefd[2];
 
   /*THREAD-FIX lock to control g_session_count*/
   lock_chain_acquire();
@@ -203,6 +510,8 @@ for user %s denied", username);
     return 0;
   }
 
+  display = 10 + g_session_count;
+
   /*THREAD-FIX unlock chain*/
   lock_chain_release();
 
@@ -222,193 +531,481 @@ for user %s denied", username);
     return 0;
   }
 
-  display = 10;
+  dbus_error_init (&error);
+  connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+  if (connection == NULL) {
+      if (dbus_error_is_set (&error)) {
+	  log_message(&(g_cfg->log), LOG_LEVEL_INFO, "dbus_bus_get: %s",
+		      error.message);
+	  dbus_error_free (&error);
+      }
+      g_free(temp->item);
+      g_free(temp);
+      return 0;
+  }
 
-  /*while (x_server_running(display) && display < 50)*/
-  /* we search for a free display up to max_sessions */
-  /* we should need no more displays than this       */
+  dbus_connection_set_exit_on_disconnect (connection, FALSE);
 
-  /* block all the threads running to enable forking */
-  scp_lock_fork_request();
-  while (x_server_running(display))
+#ifndef _WIN32
+  if (pipe(pipefd) == -1)
   {
-    display++;
-    if (((display - 10) > g_cfg->sess.max_sessions) || (display >= 50))
-    {
+      log_message(&(g_cfg->log), LOG_LEVEL_INFO, "pipe failed");
+      g_free(temp->item);
+      g_free(temp);
       return 0;
-    }
   }
-  wmpid = 0;
+#endif
+
+  /* block all the threads running to enable forking */
+  scp_lock_fork_request();
+
+  ck_cookie = session_ck_open_session (connection, username, display);
+
   pid = g_fork();
   if (pid == -1)
   {
   }
   else if (pid == 0) /* child sesman */
   {
+
+#ifndef _WIN32
+    char       auth_file[256];
+    const char *auth_templ = "/tmp/.xrdp-auth-XXXXXX";
+    char       auth_data[AUTH_DATA_LEN];
+    int        auth_fd;
+    int        mask;
+
+    close(pipefd[0]);
+#endif
+
     g_unset_signals();
     auth_start_session(data, display);
+
+#ifndef _WIN32
+    strcpy (auth_file, auth_templ);
+    mask = umask (0077);
+    auth_fd = mkstemp (auth_file);
+    umask (mask);
+
+    if (auth_fd == -1)
+    {
+      log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS,
+		  "error - generating unique authorization file");
+      g_exit(1);
+    }
+
+    if (session_setup_auth (screen + 1, auth_data, auth_fd))
+    {
+      g_exit(1);
+    }
+#endif
+    
+    if (env_set_user(username, passwd_file, display, auth_file) != 0)
+    {
+      log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "error - set user failed");
+      g_exit(1);
+    }
+
+    env_check_password_file(passwd_file, password);
     g_sprintf(geometry, "%dx%d", width, height);
     g_sprintf(depth, "%d", bpp);
     g_sprintf(screen, ":%d", display);
-    wmpid = g_fork();
-    if (wmpid == -1)
+
+#ifndef _WIN32
+    g_signal (SIGUSR1, sig_usr1_waiting);
+#endif
+
+    xpid = g_fork();
+    if (xpid == -1)
     {
     }
-    else if (wmpid == 0) /* child (child sesman) xserver */
+    else if (xpid == 0) /* child (child sesman) xserver */
     {
-      /* give X a bit to start */
-      g_sleep(1000);
-      env_set_user(username, 0, display);
-      if (x_server_running(display))
-      {
-        auth_set_env(data);
-        /* try to execute user window manager if enabled */
-        if (g_cfg->enable_user_wm)
-        {
-          g_sprintf(text,"%s/%s", g_getenv("HOME"), g_cfg->user_wm);
-          if (g_file_exist(text))
-          {
-            g_execlp3(text, g_cfg->user_wm, 0);
-            log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS,"error starting user wm for user %s - pid %d",
-                        username, g_getpid());
-            /* 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", 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", text);
-            log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, "        argv[1] = %s", g_cfg->user_wm);
-          }
-        }
-        /* if we're here something happened to g_execlp3
-           so we try running the default window manager */
-        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 wm for user %s - pid %d",
-                    username, g_getpid());
-        /* 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", 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", text);
-        log_message(&(g_cfg->log), 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 for user %s - pid %d",
-                    username, g_getpid());
-        /* 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", errno, g_get_strerror());
-      }
-      else
-      {
-        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...");
-      g_exit(0);
-    }
-    else /* parent (child sesman) */
-    {
-      xpid = g_fork();
-      if (xpid == -1)
+#ifndef _WIN32
+      close(pipefd[1]);
+      g_signal (SIGUSR1, SIG_IGN);
+#endif
+
+      if (type == SESMAN_SESSION_TYPE_XVNC)
       {
+        xserver_params = list_create();
+	xserver_params->auto_free = 1;
+	/* these are the must have parameters */
+	list_add_item(xserver_params, (long)g_strdup("Xvnc"));
+	list_add_item(xserver_params, (long)g_strdup(screen));
+	list_add_item(xserver_params, (long)g_strdup("-geometry"));
+	list_add_item(xserver_params, (long)g_strdup(geometry));
+	list_add_item(xserver_params, (long)g_strdup("-depth"));
+	list_add_item(xserver_params, (long)g_strdup(depth));
+	list_add_item(xserver_params, (long)g_strdup("-rfbauth"));
+	list_add_item(xserver_params, (long)g_strdup(passwd_file));
+
+#ifndef _WIN32
+	list_add_item(xserver_params, (long)g_strdup("-auth"));
+	list_add_item(xserver_params, (long)g_strdup(auth_file));
+#endif
+
+
+	/* additional parameters from sesman.ini file */
+	//config_read_xserver_params(SESMAN_SESSION_TYPE_XVNC,
+	//                           xserver_params);
+	list_append_list_strdup(g_cfg->vnc_params, xserver_params, 0);
+
+	/* make sure it ends with a zero */
+	list_add_item(xserver_params, 0);
+	pp1 = (char**)xserver_params->items;
+	g_execvp("Xvnc", pp1);
       }
-      else if (xpid == 0) /* child */
+      else if (type == SESMAN_SESSION_TYPE_XRDP)
       {
-        env_set_user(username, passwd_file, display);
-        env_check_password_file(passwd_file, password);
-        if (type == SESMAN_SESSION_TYPE_XVNC)
-        {
-          xserver_params = list_create();
+	  xserver_params = list_create();
           xserver_params->auto_free = 1;
           /* these are the must have parameters */
-          list_add_item(xserver_params, (long)g_strdup("Xvnc"));
+          list_add_item(xserver_params, (long)g_strdup("X11rdp"));
           list_add_item(xserver_params, (long)g_strdup(screen));
           list_add_item(xserver_params, (long)g_strdup("-geometry"));
           list_add_item(xserver_params, (long)g_strdup(geometry));
           list_add_item(xserver_params, (long)g_strdup("-depth"));
           list_add_item(xserver_params, (long)g_strdup(depth));
-          list_add_item(xserver_params, (long)g_strdup("-rfbauth"));
-          list_add_item(xserver_params, (long)g_strdup(passwd_file));
+
+#ifndef _WIN32
+	  list_add_item(xserver_params, (long)g_strdup("-auth"));
+	  list_add_item(xserver_params, (long)g_strdup(auth_file));
+#endif
 
           /* additional parameters from sesman.ini file */
-          //config_read_xserver_params(SESMAN_SESSION_TYPE_XVNC,
+          //config_read_xserver_params(SESMAN_SESSION_TYPE_XRDP,
           //                           xserver_params);
-          list_append_list_strdup(g_cfg->vnc_params, xserver_params, 0);
+	  list_append_list_strdup(g_cfg->rdp_params, xserver_params, 0);
 
           /* make sure it ends with a zero */
           list_add_item(xserver_params, 0);
           pp1 = (char**)xserver_params->items;
-          g_execvp("Xvnc", pp1);
-        }
-        else if (type == SESMAN_SESSION_TYPE_XRDP)
-        {
-          xserver_params = list_create();
+	  g_execvp("X11rdp", pp1);
+      }
+      else if (type == SESMAN_SESSION_TYPE_XDMX)
+      {
+	  xserver_params = list_create();
           xserver_params->auto_free = 1;
           /* these are the must have parameters */
-          list_add_item(xserver_params, (long)g_strdup("X11rdp"));
+          list_add_item(xserver_params, (long)g_strdup("Xdmx"));
           list_add_item(xserver_params, (long)g_strdup(screen));
-          list_add_item(xserver_params, (long)g_strdup("-geometry"));
-          list_add_item(xserver_params, (long)g_strdup(geometry));
-          list_add_item(xserver_params, (long)g_strdup("-depth"));
-          list_add_item(xserver_params, (long)g_strdup(depth));
+
+#ifndef _WIN32
+	  list_add_item(xserver_params, (long)g_strdup("-auth"));
+	  list_add_item(xserver_params, (long)g_strdup(auth_file));
+#endif
 
           /* additional parameters from sesman.ini file */
-          //config_read_xserver_params(SESMAN_SESSION_TYPE_XRDP,
-          //                           xserver_params);
-	  list_append_list_strdup(g_cfg->rdp_params, xserver_params, 0);
+          list_append_list_strdup(g_cfg->dmx_params, xserver_params, 0);
 
-          /* make sure it ends with a zero */
-          list_add_item(xserver_params, 0);
+	  /* make sure it ends with a zero */
+	  list_add_item(xserver_params, 0);
           pp1 = (char**)xserver_params->items;
-          g_execvp("X11rdp", pp1);
-        }
-        else
-        {
-          log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "bad session type - user %s - pid %d",
-                      username, g_getpid());
+          g_execvp("Xdmx", pp1);
+      }
+      else
+      {
+	log_message(&(g_cfg->log), 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 - user %s - pid %d",
+		  username, g_getpid());
+
+      /* 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", errno, g_get_strerror());
+      log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, "execve parameter list: %d", (xserver_params)->count);
+
+      for (i=0; i<(xserver_params->count); i++)
+      {
+	log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, "        argv[%d] = %s", i, (char*)list_get_item(xserver_params, i));
+      }
+      list_delete(xserver_params);
+      g_exit(1);
+    }
+    else /* parent (child sesman) */
+    {
+
+#ifdef _WIN32
+      g_sleep (5000);
+#else
+      xcb_connection_t *c;
+
+      received_usr1 = 0;
+
+      for (;;)
+      {
+	g_signal (SIGUSR1, sig_usr1_waiting);
+	if (setjmp (jumpbuf))
+	  break;
+
+	g_signal (SIGUSR1, sig_usr1_jump);
+	if (received_usr1)
+	  break;
+
+	if (g_waitpid (xpid) != -1)
+	{
+	  log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS,
+		      "error X server died - user %s - pid %d",
+		      username, xpid);
+	  g_exit(1);
+	}
+      }
+
+      c = xcb_connect (screen, NULL);
+      if (!c || xcb_connection_has_error (c))
+      {
+          log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS,
+                      "error X server connection failed - user %s - pid %d",
+                      username, xpid);
           g_exit(1);
-        }
+      }
+#endif
 
-        /* should not get here */
-        log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "error starting X server - user %s - pid %d",
-                    username, g_getpid());
+      log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS,
+		  "X server running - user %s - pid %d",
+		  username, xpid);
+
+      g_unset_signals();
 
-        /* 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", errno, g_get_strerror());
-        log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, "execve parameter list: %d", (xserver_params)->count);
-
-        for (i=0; i<(xserver_params->count); i++)
-        {
-          log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, "        argv[%d] = %s", i, (char*)list_get_item(xserver_params, i));
-        }
-        list_delete(xserver_params);
-        g_exit(1);
+      wmpid = g_fork();
+      if (wmpid == -1)
+      {
       }
-      else /* parent (child sesman)*/
+      else if (wmpid == 0) /* child */
       {
-        /* new style waiting for clients */
-        session_start_sessvc(xpid, wmpid, data);
+
+#ifndef _WIN32
+	close(pipefd[1]);
+#endif
+
+	if (ck_cookie)
+	  g_setenv("XDG_SESSION_COOKIE", ck_cookie, 1);
+
+	auth_set_env(data);
+
+	/* for XDMX sessions, we adjust screen size using xrandr once
+	   the X server is up */
+	if (type == SESMAN_SESSION_TYPE_XDMX)
+	{
+	    if (g_fork() == 0)
+	    {
+		struct list* xrandr_params=0;
+
+		xrandr_params = list_create();
+		xrandr_params->auto_free = 1;
+		list_add_item(xrandr_params, (long)g_strdup("xrandr"));
+		list_add_item(xrandr_params, (long)g_strdup("--fb"));
+		list_add_item(xrandr_params, (long)g_strdup(geometry));
+
+		/* make sure it ends with a zero */
+		list_add_item(xrandr_params, 0);
+		pp1 = (char**)xrandr_params->items;
+		g_execvp("xrandr", pp1);
+
+		/* should not get here */
+		log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS,
+			    "error running xrandr - user %s",
+			    username);
+
+		/* logging parameters */
+		log_message(&(g_cfg->log), LOG_LEVEL_DEBUG,
+			    "errno: %d, description: %s",
+			    errno, g_get_strerror());
+		log_message(&(g_cfg->log), LOG_LEVEL_DEBUG,
+			    "execve parameter list: %d",
+			    (xrandr_params)->count);
+
+		for (i=0; i<(xrandr_params->count); i++)
+		{
+		    log_message(&(g_cfg->log), LOG_LEVEL_DEBUG,
+				"        argv[%d] = %s", i,
+				(char*)list_get_item(xrandr_params, i));
+		}
+		list_delete(xrandr_params);
+		g_exit(1);
+	    }
+	}
+
+	/* set XKB map */
+        xkbpid = g_fork();
+	if (xkbpid == 0)
+	{
+	    struct list* setxkbmap_params=0;
+
+	    setxkbmap_params = list_create();
+	    setxkbmap_params->auto_free = 1;
+	    list_add_item(setxkbmap_params, (long)g_strdup("setxkbmap"));
+	    switch (layout)
+	    {
+	    case 0x40c: /* france */
+		list_add_item(setxkbmap_params, (long)g_strdup("fr"));
+		break;
+	    case 0x809: /* en-uk or en-gb */
+		list_add_item(setxkbmap_params, (long)g_strdup("gb"));
+		break;
+	    case 0x407: /* german */
+		list_add_item(setxkbmap_params, (long)g_strdup("de"));
+		break;
+	    case 0x416: /* Portuguese (Brazil) */
+		list_add_item(setxkbmap_params, (long)g_strdup("pt"));
+		break;
+	    case 0x410: /* italy */
+		list_add_item(setxkbmap_params, (long)g_strdup("it"));
+		break;
+	    case 0x41d: /* swedish */
+		list_add_item(setxkbmap_params, (long)g_strdup("se"));
+		break;
+	    case 0x405: /* czech */
+		list_add_item(setxkbmap_params, (long)g_strdup("cz"));
+		break;
+	    case 0x419: /* russian */
+		list_add_item(setxkbmap_params, (long)g_strdup("ru"));
+		break;
+	    default: /* default 0x409 us en */
+		list_add_item(setxkbmap_params, (long)g_strdup("us"));
+		break;
+	    }
+
+            log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS,
+                        "using keyboard layout: 0x%x (%s)",
+                        layout,
+                        list_get_item(setxkbmap_params, 1));
+
+	    /* make sure it ends with a zero */
+	    list_add_item(setxkbmap_params, 0);
+	    pp1 = (char**)setxkbmap_params->items;
+	    g_execvp("setxkbmap", pp1);
+
+	    /* should not get here */
+	    log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS,
+			"error running setxkbmap - user %s",
+			username);
+
+	    /* logging parameters */
+	    log_message(&(g_cfg->log), LOG_LEVEL_DEBUG,
+			"errno: %d, description: %s",
+			errno, g_get_strerror());
+	    log_message(&(g_cfg->log), LOG_LEVEL_DEBUG,
+			"execve parameter list: %d",
+			(setxkbmap_params)->count);
+
+	    for (i=0; i<(setxkbmap_params->count); i++)
+	    {
+		log_message(&(g_cfg->log), LOG_LEVEL_DEBUG,
+			    "        argv[%d] = %s", i,
+			    (char*)list_get_item(setxkbmap_params, i));
+	    }
+	    list_delete(setxkbmap_params);
+	    g_exit(1);
+	}
+
+        g_waitpid(xkbpid);
+
+	/* try to execute session window manager */
+	if (*wm != '\0')
+	  g_execlp3("/etc/X11/xdm/Xsession", "Xsession", wm);
+
+          /* try to execute user window manager if enabled */
+	if (g_cfg->enable_user_wm)
+	{
+          g_sprintf(text,"%s/%s", g_getenv("HOME"), g_cfg->user_wm);
+	  if (g_file_exist(text))
+	  {
+            g_execlp3(text, g_cfg->user_wm, 0);
+	    log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS,"error starting user wm for user %s - pid %d",
+			username, g_getpid());
+	    /* 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", 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", text);
+	    log_message(&(g_cfg->log), LOG_LEVEL_DEBUG, "        argv[1] = %s", g_cfg->user_wm);
+	  }
+	}
+        /* if we're here something happened to g_execlp3
+	   so we try running the default window manager */
+	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 wm for user %s - pid %d",
+                    username, g_getpid());
+	/* 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", 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", text);
+	log_message(&(g_cfg->log), 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 for user %s - pid %d",
+		    username, g_getpid());
+	/* 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", errno, g_get_strerror());
+      }
+      else /* parent (child sesman) */
+      {
+
+#ifndef _WIN32
+	char status = 1;
+
+	write(pipefd[1], &status, 1);
+	close(pipefd[1]);
+
+        fcntl (xcb_get_file_descriptor (c), F_SETFD, 0);
+#endif
+	/* new style waiting for clients */
+	session_start_sessvc(xpid, wmpid, data);
       }
     }
   }
   else /* parent sesman process */
   {
+    char status = 0;
+    int  len;
+
     /* let the other threads go on */
     scp_lock_fork_release();
 
+#ifdef _WIN32
+    /* wait for X server to start */
+    g_sleep (5000);
+    status = 1;
+#else
+    close(pipefd[1]);
+
+    do {
+	len = read(pipefd[0], &status, 1);
+    } while (len == -1);
+
+    close(pipefd[0]);
+#endif
+
+    if (status == 0)
+    {
+	g_free(temp->item);
+	g_free(temp);
+	return 0;
+    }
+
     temp->item->pid = pid;
     temp->item->display = display;
     temp->item->width = width;
     temp->item->height = height;
     temp->item->bpp = bpp;
     temp->item->data = data;
+    temp->item->ck_cookie = ck_cookie;
     g_strncpy(temp->item->name, username, 255);
 
     ltime = g_time1();
@@ -431,8 +1028,6 @@ for user %s denied", username);
     g_session_count++;
     /*THERAD-FIX free the chain*/
     lock_chain_release();
-
-    g_sleep(5000);
   }
   return display;
 }
@@ -472,6 +1067,7 @@ struct session_chain
   struct session_chain* next;
   struct session_item* item;
 };
+
 */
 
 /******************************************************************************/
@@ -513,6 +1109,12 @@ session_kill(int pid)
       /* deleting the session */
       log_message(&(g_cfg->log), LOG_LEVEL_INFO, "session %d - user %s - terminated",
                   tmp->item->pid, tmp->item->name);
+      if (tmp->item->ck_cookie)
+      {
+	  session_ck_close_session (dbus_bus_get(DBUS_BUS_SYSTEM, 0),
+				    tmp->item->ck_cookie);
+	g_free(tmp->item->ck_cookie);
+      }
       g_free(tmp->item);
       if (prev == 0)
       {
diff --git a/sesman/session.h b/sesman/session.h
index e6c6563..8b9638f 100644
--- a/sesman/session.h
+++ b/sesman/session.h
@@ -33,6 +33,7 @@
 
 #define SESMAN_SESSION_TYPE_XRDP  1
 #define SESMAN_SESSION_TYPE_XVNC  2
+#define SESMAN_SESSION_TYPE_XDMX  3
 
 #define SESMAN_SESSION_STATUS_ACTIVE        1
 #define SESMAN_SESSION_STATUS_IDLE          2
@@ -64,6 +65,7 @@ struct session_item
   int width;
   int height;
   int bpp;
+  int layout;
   long data;
 
   /* status info */
@@ -74,6 +76,9 @@ struct session_item
   struct session_date connect_time;
   struct session_date disconnect_time;
   struct session_date idle_time;
+
+  /* console kit */
+  char *ck_cookie;
 };
 
 struct session_chain
@@ -101,8 +106,9 @@ session_get_bydata(char* name, int width, int height, int bpp);
  *
  */
 int DEFAULT_CC
-session_start(int width, int height, int bpp, char* username, char* password,
-              long data, unsigned char type);
+session_start(int width, int height, int bpp, int layout,
+	      char* username, char* password,
+              char* wm, long data, unsigned char type);
 
 /**
  *
diff --git a/sesman/startwm.sh b/sesman/startwm.sh
index 3445c49..077304e 100755
--- a/sesman/startwm.sh
+++ b/sesman/startwm.sh
@@ -1,48 +1,14 @@
-#!/bin/sh
+#!/bin/bash
+#
+# startwm.sh for SuSE Linux
+#
 
-# edit this file to run whatever window manager you want
-# defaults to running kde
+. /etc/sysconfig/windowmanager
 
-# for kde
-if [ -d /opt/kde3/bin ]; then
-  export PATH=/opt/kde3/bin:$PATH
-fi
-if [ -d /opt/kde/bin ]; then
-  export PATH=/opt/kde/bin:$PATH
-fi
-which startkde
-if [ $? -eq 0 ]; then
-  startkde
-  exit 0
-fi
-which kde
-if [ $? -eq 0 ]; then
-  kde
-  exit 0
-fi
+test -z "$DEFAULT_WM" && DEFAULT_WM=twm
+WINDOWMANAGER="`type -p ${DEFAULT_WM##*/}`"
+unset DEFAULT_WM
 
-# gnome
-which gnome-session
-if [ $? -eq 0 ]; then
-  gnome-session
-  exit 0
-fi
+exec /etc/X11/xdm/Xsession $WINDOWMANAGER
 
-# blackbox
-#if [ "'which blackbox'" != "" ]; then
-#  blackbox
-#  exit 0
-#fi
-
-# fvwm95
-#if [ "'which fvwm95'" != "" ]; then
-#  fvwm95
-#  exit 0
-#fi
-
-# fall back on xterm
-which xterm
-if [ $? -eq 0 ]; then
-  xterm
-  exit 0
-fi
+exit 1
diff --git a/sesman/tools/sesrun.c b/sesman/tools/sesrun.c
index ef280c4..4af08ff 100644
--- a/sesman/tools/sesrun.c
+++ b/sesman/tools/sesrun.c
@@ -44,11 +44,13 @@ main(int argc, char** argv)
   int width;
   int height;
   int bpp;
+  int keylayout;
   int display;
   struct stream* in_s;
   struct stream* out_s;
   char* username;
   char* password;
+  char* exec;
   long data;
 
   if (0 != config_read(&g_cfg))
@@ -60,17 +62,19 @@ main(int argc, char** argv)
   g_pid = g_getpid();
   if (argc == 1)
   {
-    g_printf("xrdp session starter v0.1\n");
+    g_printf("xrdp session starter v0.2\n");
     g_printf("\nusage:\n");
-    g_printf("sesrun <server> <username> <password> <width> <height> <bpp>\n");
+    g_printf("sesrun <server> <username> <password> <exec> <width> <height> <bpp> <keylayout>\n");
   }
-  else if (argc == 7)
+  else if (argc == 9)
   {
     username = argv[2];
     password = argv[3];
-    width = g_atoi(argv[4]);
-    height = g_atoi(argv[5]);
-    bpp = g_atoi(argv[6]);
+    exec = argv[4];
+    width = g_atoi(argv[5]);
+    height = g_atoi(argv[6]);
+    bpp = g_atoi(argv[7]);
+    keylayout = g_atoi(argv[8]);
     make_stream(in_s);
     init_stream(in_s, 8192);
     make_stream(out_s);
@@ -79,16 +83,20 @@ main(int argc, char** argv)
     if (g_tcp_connect(sck, argv[1], "3350") == 0)
     {
       s_push_layer(out_s, channel_hdr, 8);
-      out_uint16_be(out_s, 0); /* code */
+      out_uint16_be(out_s, 20); /* code */
       i = g_strlen(username);
       out_uint16_be(out_s, i);
       out_uint8a(out_s, username, i);
       i = g_strlen(password);
       out_uint16_be(out_s, i);
       out_uint8a(out_s, password, i);
+      i = g_strlen(exec);
+      out_uint16_be(out_s, i);
+      out_uint8a(out_s, exec, i);
       out_uint16_be(out_s, width);
       out_uint16_be(out_s, height);
       out_uint16_be(out_s, bpp);
+      out_uint16_be(out_s, keylayout);
       s_mark_end(out_s);
       s_pop_layer(out_s, channel_hdr);
       out_uint32_be(out_s, 0); /* version */
diff --git a/sesman/tools/sestest.c b/sesman/tools/sestest.c
index 03cd1a1..a95130e 100644
--- a/sesman/tools/sestest.c
+++ b/sesman/tools/sestest.c
@@ -161,8 +161,13 @@ int inputSession(struct SCP_SESSION* s)
   g_printf("session type:\n");
   g_printf("0: Xvnc\n", SCP_SESSION_TYPE_XVNC);
   g_printf("1: x11rdp\n", SCP_SESSION_TYPE_XRDP);
+  g_printf("2: Xdmx\n", SCP_SESSION_TYPE_XDMX);
   integer=menuSelect(1);
-  if (integer==1)
+  if (integer==2)
+  {
+    s->type=SCP_SESSION_TYPE_XDMX;
+  }
+  else if (integer==1)
   {
     s->type=SCP_SESSION_TYPE_XRDP;
   }
diff --git a/vnc/vnc.c b/vnc/vnc.c
index 5f9c9ba..0a34884 100644
--- a/vnc/vnc.c
+++ b/vnc/vnc.c
@@ -874,6 +874,8 @@ lib_framebuffer_update(struct vnc* v)
       in_uint16_be(s, cx);
       in_uint16_be(s, cy);
       in_uint32_be(s, encoding);
+      if (cx > 8192 || cy > 8192)
+        return 1;
       if (encoding == 0) /* raw */
       {
         need_size = cx * cy * Bpp;
@@ -977,7 +979,8 @@ lib_clip_data(struct vnc* v)
   int size;
   int error;
 
-  g_free(v->clip_data);
+  if (v->clip_data)
+    g_free(v->clip_data);
   v->clip_data = 0;
   v->clip_data_size = 0;
   make_stream(s);
@@ -987,9 +990,14 @@ lib_clip_data(struct vnc* v)
   {
     in_uint8s(s, 3);
     in_uint32_be(s, size);
-    v->clip_data = (char*)g_malloc(size, 0);
-    v->clip_data_size = size;
-    error = lib_recv(v, v->clip_data, size);
+    if (size <= 0 || size > 65536)
+	error = 1;
+    if (error == 0)
+    {
+      v->clip_data = (char*)g_malloc(size, 0);
+      v->clip_data_size = size;
+      error = lib_recv(v, v->clip_data, size);
+    }
   }
   if (error == 0)
   {
@@ -1037,7 +1045,7 @@ lib_palette_update(struct vnc* v)
     in_uint8s(s, 1);
     in_uint16_be(s, first_color);
     in_uint16_be(s, num_colors);
-    init_stream(s, 8192);
+    init_stream(s, num_colors * 6);
     error = lib_recv(v, s->data, num_colors * 6);
   }
   if (error == 0)
diff --git a/xrdp/Makefile.am b/xrdp/Makefile.am
index 32dd412..b71f2c0 100644
--- a/xrdp/Makefile.am
+++ b/xrdp/Makefile.am
@@ -33,7 +33,11 @@ xrdpsysconf_DATA = \
 pkgdata_DATA = \
   ad256.bmp \
   xrdp256.bmp \
+  tile256.bmp \
+  opensuse256.bmp \
+  rdc256.bmp \
   sans-10.fv1 \
+  tahoma-10.fv1 \
   cursor0.cur \
   cursor1.cur
 
diff --git a/xrdp/funcs.c b/xrdp/funcs.c
index e2ebdb6..e946660 100644
--- a/xrdp/funcs.c
+++ b/xrdp/funcs.c
@@ -217,7 +217,8 @@ set_string(char** in_str, const char* in)
   {
     return 0;
   }
-  g_free(*in_str);
+  if (*in_str)
+    g_free(*in_str);
   *in_str = g_strdup(in);
   return 0;
 }
diff --git a/xrdp/opensuse256.bmp b/xrdp/opensuse256.bmp
new file mode 100644
index 0000000..e3daee6
--- /dev/null
+++ b/xrdp/opensuse256.bmp
@@ -0,0 +1,8 @@
+BM¶6(„ ­­­àâá«««©©©§§§¥¥¥£££¢£¢¡¡¡$%% ¡ ÔÖÕŸŸŸ"##���ÑÒÒ›››™™™———•••�‘����Ž�Ž‰‰‰‡‡‡
+º¼»………€�€}}}{{{tutqqqmmmlmlkkkgggcccaaa]]]\]\YYYWWWSSSPQPNONþþþüüüIIIúúúGGGøøøöööCCCAAAòòòqrr;;;999êêê777èèè555æææ333äää111///ààà+++*+*)))ÚÚÚ'''ØØØ&'&%%%ÖÖÖYZZ###UVVÐÐÐÎÎÎÍÎÍÌÌÌÊÊÊþÿÿÈÈÈIJJÄÄÄGHHÂÂÂÀÀÀôõõBDC



òóó½¾½¼¼¼			ºººîïï¸¸¸ìíí¶¶¶³´³344äåå®®®­®­/00àááªªª©ª©¨¨¨§¨§¦¦¦¤¤¤'((   #$$žžž!""�ž�œœœÏÑÐššš˜˜˜•–•ÉËÊ”””’’’���ŒŒŒ¼½½	
+
+„„„ƒ„ƒ€€€~~~|||zzzxxxvvvtttqrqppplllklkjjjhhhfffddd```^^^]^]\\\ZZZXXXVVVTTTRRR„……NNNÿÿÿýýýûûû±´³ùùù÷÷÷õõõCDCóóó?@?ïïïíííëëënoo787666çççjkk444222000ced...`aaÜÝÜ***)*)(((ÙÙÙ'('&&&$$$"""   ÏÏÏËËËÈÉÈûüüÅÅÅÄÅÄÃÃÃ÷øø¿¿¿ACBñòò¼½¼
+
+
+»»»º»º¹¹¹µµµçèèæèçs{ý{õòs{ý{õòs{ý{õòs{ý{õòûý{ø{š}ûý{ø{}ûý{ø{}ûý{ø{}ýifo}h¾.ýifo}ýifo}ýifo}ûîis}¹¼ªûîis}ûîis}ûîis}ýûúûýû/¼%ýûúûýûøxýýûúûýûøxýýûúûýûøxýx,¼¨ýxîkxýxîkxýxîkxýÚLLLŽø²¼¨TÕäÞLLL
+{àžXøiiødLÕÕÕLLÕLLÕsøLLLLLLLÒiiøÛLÕLLÕÕLLLÜoLLLLLÐAAÐÕLÕïKR¼¼¼¼¼“ãû¶¼¤…¼¼a–ûøúr¼¼¼¼¼A™¼�aLuu´½¼¼¼¼¼¼¼¼¼¼¼�Ùæ8¼¼¼¼¼¼¼¼D§u—¼¼¼¼¼¼¼¼¼¼¼w§¡Ïm¼¼¼¼¼¼¼¼¼¼¼¼ÂÏk\úýð¼÷å¼‰0¼Á’Ç¼2îk¼Wè¼Ly¼Eý¼¼¼¼¼¼¼¼¼¼¼¼¼ÿiæ¼¼¼¼¼¼¼¼¼¼¼¼
Û¼¼¼¼¼¼¼¼¼¼¼¼¼¼ºª¼¼¼¼¼¼¼¼¼¼¼¼¼¼ªáC×Õú4Æ{îÀ]¹¼Ÿ#¼!ëî_¼Œ¼Ly¼E¬3¼¼¼¼¼¼¼¼¼¼¼¼¼¦¼¼¼¼¼¼¼¼¼¼¼¼¼¼nûÔ¼¼¼¼¼¼¼¼¼¼¼¼¼ífª¼¼¼¼¼¼¼¼¼¼¼¼¼ÀñàEJHxý¼ÈÂ]¹¼ªª¼¤õø]¼Ýý¼Ly¼EQÎEEEEË>?Cµ4¼¼v{þ¼¼çÉEEEEE>‡¼¼¼˜pEË>?CEÎEÎÎ¼¼¼7ª¼¼¼:EÎEEEEÎÎEà^Õuýûõõ¼ÈÂ]¹¼ªª¼¥ý]¼˜5õú¼Ly¼Eýß¼¼jûè¼¼¼†Æ¼¼ýý¹¼¼¼±ª¼¼¼èýýxië¼ÈÂ]¹¼ª%¼¥]¼¼¼¼¼¼¼6\ò¼Ly¼Ej¼¼jxá¼¼¼I¼¼¹¼¼¼°ª¼¼¼èúîk¼ÈÂ]¹¼%ª¼¥]¼Ïèdèèc¼Ëø¼Ly¼EûR¼¼jú^¼¼¼I¼¼ý·¼¼¼+ª¼¼¼èý}}ý¼ÈÂYuû¹¼%%¼¥]¼Vì¼J¼Lûö¼ËÅ•‹â¼¼¼ü}o¼¼¼ûõuûI¼¼ýs«ˆÈ¼¼¼5ª¼¼¼9ÂÂÂÂÂÂFÑý@8Gõõõ1½[îø¹¼vèõso~¼«ýô¼-õõõPB½ø¼¢õõsÖ�¼J«¼¼¼¼¼¼¼¼¼¼¼¼¼'õ¼¼¼øiîøI¼¼¼¼¼¼¼¼¼¼¼¼¼¼Ìòª¼¼¼¼¼¼¼¼¼¼¼Mý!¼¼¼¼¼¼¼=iø¹¼Ø@¼¼¼¼ób»4¼¼¼¼¼¼¼_À¼¼¼¼gu„4¼¼¼¼¼¼¼¼¼¼¼¼ûõ¼¼¼øiiøI¼¼�¼¼¼¼¼¼¼¼¼¼¼¼Çeª¼¼¼¼¼¼¼¼¼¼¼t.yyyŠUøx}NƒbkÍù‘„Ã
yyy‚«xS›£|ù `}¼¼¼ê&­)¯¯¯¯¯Ês¼¼¼}øx}I¼¼{Â¼¼6¯¯¯¯¯))¶ë%¼¼¼¨(­®¯¯)°ë{uúsfîûý¼¼Âfîûýs¼¼¼I¼¼s¼¼¼ýª¼¼¼èsfîûýýýõfî}ýý¼¼Èõfî}ýõ¼¼¼I¼¼ýõ¼¼¼ýýª¼¼¼èýõfî}ý}{ûûux}{û¼¼9`ux}{ûõ¼¼¼I¼¼û¼¼¼•}{ûª¼¼¼dûuxúòòxýúòòx"¼¼¼”©sòòxs¼¼¼I¼¼z¼¼4Š��˜G%¼¼¼	™€ýuffuýuffuãq¼¼¼¼¼¼¼¼¼¼¼¼*ffuõ¼¼¼I¼¼ý ¼¼¼¼¼¼¼¼¼¼¼¼Ìúª¼¼¼¼¼¼¼¼¼¼¼¼¼F{ss{ûý{ss{ûý;Â¼¼¼¼¼¼¼¼¼¼¼$ss{x<¼¼œûýO¼¼}¿¼¼¼¼¼¼¼¼¼¼¼Äõ®¼¼¼¼¼¼¼¼¼¼¼¼¼Çý}ý{oòûýýý}ý{oòûPjjjjjjjjj‰iý}³jZ{oòû7ðüTýý¸jjjjjjjìlÓýoééìjjjjjjjjjSýýõèëxýõèëxýõèëxýõèëxxkò}ýýxkò}ýýxkò}ýýxkò}ýýû}ýøsøû}ýøsøû}ýøsøû}ýøsøý}ïfïý}ïfïý}ïfïý}ïfïýýòiõýýòiõýýòiõýýòiõxýý}}ýý}usxýý}}ýý}usxýý}}ýý}usxýý}}ýý}uskxýýýúofkxýýýúofkxýýýúofkxýýýúof
\ No newline at end of file
diff --git a/xrdp/rdc256.bmp b/xrdp/rdc256.bmp
new file mode 100644
index 0000000..7fe8438
--- /dev/null
+++ b/xrdp/rdc256.bmp
@@ -0,0 +1,9 @@
+BM¶¿6(�x¢ ›IH= ž™žœ—àäáœš•CB7ÝàÞš˜“ÛÞÜ˜–‘—”�•’Ž“�ŒÑÔÒüÿþÇÊÈ€~y~|w{xtyvrwtpurnëïísplOODîìæqnjíêåolhëèãéæáljejhcáåãEE:hfaäâÜãàÛfd_áÞÙdb]@?5ßÜ×b`[==2×ÛÙÚØÒ[XT×ÔÏÕÒÍXVQVTOÎÌÆÍÊÅËÈÃÉÆÁLJEDB=À¾¸¿¼·½ºµ»¸³°®¨¯¬§­ª¥«¨£©¦¡ÝÛÖ_]YÛÙÔ][WÑÏÊSQMQOKOMI‘Ž‰IGCÅÃ¾�Œ‡GEAÃÁ¼�Š…EC?hg\‹ˆƒ‰†�A?;‡„?=9…‚}`_Túýû·µ°øûù]]Qµ³®öù÷³±¬ZYN}zu±¯ªó÷ôXWLòõóVUJðóñTSHîñïQQEèëé¥£žLK@æéç£¡œJI>¡ŸšŸ�˜�›–Þáß›™”ÜßÝ™—’–“�”‘�Ô×ÕÐÓÑüùô}xôøözwsöóîxuqôñìvsotqmPPEïíçrokNNCpminkgmkfkidGF<FF;igbåãÝDD9ge`âßÚec^àÝØca\?>4>>3ÖÚØÙ×ÑØÕÐZWSÖÓÎYWRÔÑÌWUPUSNÌÐÎÏÍÇÌÉÄÊÇÂMKFÈÅÀKIDÁ¿¹¾»¶¼¹´ðîéº·²æäß®«¦¬©¤ª§¢¨¥ `^ZÜÚÕ^\X\ZVÒÐËÐÎÉRPLPNJNLHÆÄ¿��ˆHFBÄÂ½Ž‹†FD@jj^ÂÀ»Œ‰„Š‡‚edYˆ…€†ƒ~><8„�|¸¶±ùüú^^R¶´¯÷úø\\P[ZO²°«YXMWVKñôòUTIïòðíðîêîëéìê¦¤ŸMLAçêè¤¢�KJ?åèæÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌKÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌKÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌKÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌšššššššššššššššššššššššššššššš«šššššššššššššššššššššššššššššššššššššššššš«šššššššššššššššššššššššššš«šššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššššYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW”””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””Ê¸””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””G"””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””#¾‘”””””””””””””””””””--””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””¶”””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::¡
+8q^^n6¹:::::::::::::::Ê¸::::::,:o9SÝÏ¢E,::,:,:MeØØ?Á,:SÝÏ¢E:::‹­aÛ³::SÝÏ¢E�Ý,:€,:MeØØ?Á:,ÂÏ.):::::�1^nÄ:MeØØ?Á,::,:,::,SÝÏ¢E‹<Ò‰
:,:,:MeØØ?Á,::,:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::'¿\5�:::::::::::::ÌÌ::::::,¹^X:
f
+Z`á,::,:,:eL
ne,:
f
+Z`á:::>‰
Oã::
f
+Z`°\µÛ,,^²:,:eL
ne:,»Xº.S:::’^ºÎÑ:eL
ne,::,:,::,
f
+Z`áÎ“È²,:,:eL
ne,::,:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::P³Ï`«:::::::::::ÊE::::::,N S:NŽ::,:,:Ø::‚Ø,:N¾::f‚::::NkZ¦ã,��P:,:Ø::‚Ø:,¤:4£:::7QS::Ž€SØ::‚Ø,:S,:,:S,N‡:S©Á,:,:Ø::‚Ø,:S,::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””m~.Ö””””””””””ÌÌ””””””,^{”bã™,h™s��”T”Ø””Ú,”bã™,h#””Ø””””bã™,h1´Ô,œN#”,”Ø””Ú”,i”gc”””�Œ””””””Ø””Ú,âp[”,âp[bã™,h�”#kp,”,”Ø””Ú,âp[””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””Œã×”””””””””ÊE””””””,'^‹’\ÕÇãe,³´ºX8"”?Ý

Ü?È‡’\ÕÇãe”””`à

””’\ÕÇãefá³,$\X”È‡?Ý

Ü?”,ºÊºy#”””a�””””””?Ý

Ü?,e´\¾”,e´\¾’\ÕÇãe°È?‚È‡,”?Ý

Ü?,e´\¾”””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””´aÛ.­=Â¥ãÏ�Á””””””””››””””””,”âE”ãa®9,~a§Ï„”ejje˜·”ãa®9”””ß>al=”””ãa®9OjÛÃ,”Aƒ£˜·ejje”,Î^.—””””¦°#””USejje,¦Òt””,¦Òt””ãa®9¾¬ÒqÀ”˜·,”ejje,¦Òt”””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””‘¼�””””””””p�v}´””””””””ÊE””””””,¬fâ””””””””””””””””””””””,””””””””””””””,””””””””””””,””””,””””””””””””””””””�^¨`\e””””””””””””””””””””””””””””””””,”KÈ””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””';\^¶”””””””››””””””,lX”””””””””””””””””””””””,””””””””””””””,””””””””””””,””””,”””””””””””””””””””œ^ã‘””””””””””””””””””””””””””””””””,”,”””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS�l®SSSSSSSÊESSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS¡{7nÛÞ'S´a¾SSSSSS››SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSd§\jNtr6Ïº´XSSSSSSÊ¶SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS######################################################################�U&2Í#####ÔÎ`######ÌÌ#####################################################################################################################################################################################################################################################################################################################################################################################R~‡#âD³m###d~######Ê¶#####################################################################################################################################################################################################################################################################################################################################################################################¨X‘#�¦FÈª“I########šš####################################################################################################################################################################################################################################################################################################################################################################################pm###R(©###¬²##Cl######V¶#################################################################################################################################0..#############################################################################################0..###########################################################################SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSÂ
+SÄ™M&SÄ“"SSSSSSššSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS¶SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS¶SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSNS
¬yS�¢SSSSSSV¶SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS¶SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS¶SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSÀœÁß3®²S®ÕSSSSSSššSSSSSSSA\–SSS!5§’SSSA\–SSSSSSSS¢¶S¶SSS¶SSSMBÛ(
S¬"«S4ØoSSSSS¶SSS¶SSS¶SSS,Æjw{ÄS¶SS¶Z(j<¹SS¶SSS¶SS�¥^ÛBMSS,Æjw{ÄSSSSSS\Ü¿SSSSSS,Æjw{ÄSS�¥^ÛBM¶SSZS¶SSSIÕÜã9SS¶Z(j<¹SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSÁ¦H€­yJE^ÍSSSSSSV¶SSSSSSM/dS!�SM/dSSSSSSS¢¶S¶SSS¶SSS?SI¯uS>.MSSSSS¶SSS¶SSS¶SSŒ�°Ä¶SS¶…ES¶SSS¶S£Ø@SŒ�°ÄSSSSSSSSSŒ�°Ä£Ø@¶S¹ØªÄS¶SS3ãž©S¶…ESSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘â �µmkœf‹‘‘‘‘‘‘YY‘‘‘‘‘‘È^ÈÉ>}‘7Fœ§‘È^ÈÉ>}‘‘†___‹‘‘‘‘‘†__g¶‘¶‘‘‘¶‘‘�²âÔ¢‘‘X^T‘‘‘‘‘‘†___‹¶‘‘‘¶‘‘‘¶‘âNcÈÏd¶‘‘¶Ž�Œ¨‘¶‘‘‘¶‘R\ãi€jâNcÈÏd‘‘‘‘‘†ÉÍ †‘‘âNcÈÏdR\ãi€j¶&‘‘¶‘‘Q"Žlµ‘¶Ž�Œ¨‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Ý`‘‘‘‘‘‘‘V¶‘‘‘‘‘‘€e
‘‘•^‘j‘‘‡j‘€e
‘‘•^‘‘¶‘‘‘‘‘‘‘‘‘¶‘‘‘¶‘¶‘‘‘¶‘‘Ôg‘‘‘‘‘>u‘‘‘‘‘‘‘¶‘‘‘‘¶‘‘‘¶‘‘‘¶‘Ú‹‘‘‘‘‘‘¶‘‘¶Œ‘‘‘Š\‹¶‘‘‘¶‘‘‘�Å¬…Ú‹‘‘‘‘‘‘‘‘‘‘‘¶‘‘s¢¦‘‘Ú‹‘‘‘‘‘‘‘‘�Å¬…¶áØ¶‘‘‘¶‘‹ÏŠ‘‘‘Rq‘¶Œ‘‘‘Š\‹‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘«P‘‘‘‘‘‘‘‹€=hÒG‘‘‘‘‘‘‘**‘‘‘‘‘‘‘‘‘‘�@¯‘,‘‘,‘‘‘‘‘�@¯‘‘¶‘‘‘‘‘‘‘‘‘¶‘‘‘¶‘¶P‘‘™‘‘¶P‘‘™‘‘‘mÒã‘‘‘‘‘‘‘¶‘‘‘‘¶P‘‘™‘‘‘¶‘§¶‘‘¶«‘‘‘p¸¶‘‘‘¶‘‘y^Ç§‘‘‘‘‘¶‘‘‘†^«‘§‘y^Ç¶^
‘‘‘‘¶‘E«‘‘‘'‘¶«‘‘‘p¸‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•{¿fâ‘‘‘mr¥Òt‘‘‘‘‘‘‘‘È¶‘‘‘‘‘‘‘‘0µqu‘¶‘‘¶‘‘‘0µqu‘‘G‘‘‘‘‘¶‘‘‘¶‘¶0‘‘^‘‘¶‘‘‘¶‘‘‘O‡‘‘‘‘‘‘‘G¶0‘‘^‘‘‘¶‘N¶K‘¶‘‘‘Š¶K‘‘¶‘¾h¥Ö‘N‘‘‘‘‘¶‘‘‘¾G‘N¾h¥Ö‘¶µy‹‘‘‘¶‘¾Ï‘‘‘Oã‘¶‘‘‘Š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄP¿ÈÂ"ºMÄÄÄÄÄÄÄÄ**ÄÄÄÄÄÄÄ�jvPÄ¶ÄÄ¶ÄÄ�jvPÄÄGÄÄÄÄÄ¶ÄÄÄ¶Ä¶Q¤JÂ±ÄÄ¶ÄÄÄ¶ÄÄ4Ú7%«ÄÄÄÄÄÄG¶Q¤JÂ±ÄÄÄ¶Ä•fZ¾Á'2O¶P¶"ŒM"6Ä¶PÄ¶Ä¹GË;=•fZ¾Á'2OÄÄÄÄÄ¶ÄÄÄ¾¹Ä•fZ¾Á'2O¹GË;=¶«(bÄÄÄ¶ÄÄÆ"�«ÚoÄ¶"ŒM"6ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ‹œIÄÄÄÄÄÄÄÄÄÈ¶ÄÄÄÄÄÄÁÝœË©ÄÄÄ¶ÄÄ¶ÄÁÝœË©ÄÄÄÄ¶ÄÄÄÄÄÄÄÄÄ¶ÄÄÄ¶Ä¶uÄÄ¶ÄÄÄ¶ÄÄ=6«±ÄÄÄÄÄÄ¶ÄÄÄÄ¶uÄK^^|Äu6Á¶"¶^Ú™Ä¶"Ä¶ÄP+§Äu6ÁÄÄÄÄÄ¶ÄÄÄ„^«ÄÄu6ÁP+§¶Ä�\K^^|Ä3/‹Ä¶^Ú™ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄK§~¤ÄÄÄÄÄÄÄÄÄÄ**ÄÄÄÄÄÄ¹mÄJÊÊÄ¶ÄÄ¶Ä¹mÄJÊÊÄÄ¶ÄÄÄÄÄÄÄÄÄ¶ÄÄÄ¶Ä¶X"àtPÄÄ¶ÄÄÄ¶Ä^™ÄÒ¶ÄÄÄÄÄ¶ÄÄÄÄ¶X"àtPÄK{ÄÄd»fÏyx«Ä¶]à¶‡/ÏÚ;¸ÄÄ¶]àÄ¶ÄÄ¹7Òj]JÄÄd»fÏyx«ÄÄÄÄÄÄ¶ÄÄ« 7ÄÄÄÄd»fÏyx«ÄÄ¹7Òj]J¶ÄÄÞ…,{ÄÄIÕÝá‹ÄÄ¶‡/ÏÚ;¸ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄPÒ^´«ÄÄÄÄÄÄÄÄÄÄÄÈ¶ÄÄÄÄÄÄ¾^u'eÜÄ¶ÄÄ¶Ä¾^u'eÜÄÄ†GGG¾ÄÄÄÄÄ¶ÄÄÄP©©ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ†GGG¾ÄÄÄÄÄÄÄÄÄÄÄÄ¶ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄP©©ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ†'ZžŠÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¶ÄÄÄÄÄÄÄ¶ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ�������������������������������������������������������������������Ð®Ò^¬É�������������WW�������Cx�¶��¶��Cx��€�����¶���¶������������������������������������€������������¶���������������������������������¶�����������������������z��������������������¶�������¶���������������������������������������������������������������������������������������������������������������������������������������������������������������kÃ<.Ú\Úy¬
g���������������È,��������
+"\±
��¶��¶���
+"\±
���€�����¶���¶������������������������������������€������������¶���������������������������������¶�����������������������^"<���������������������¶�������¶�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������**���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPË¶PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssâssssssssssssssssssssssssssssssssssssssssssssssssssssssss«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««Æ«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««™4«¦¹™«©!«£««3«™Ÿ«««—„¼««—Ö««$««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««¥v.«Üv ŽÕbL«³'«ª¾q^«;�d½‰^—\«««««««««««««««««ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââZ{â»â»â{Z¨BµÅA$â¨âm×××.Æ_×ÓyNâm××g%®�××kââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââZxâ2ââvÍ8 †=²7âExtt°$‡ââÂ»â¶xtlb�=²B¡ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ3¿NAâQ?7£7¨|B8ÃâÚ22Â'$‡ââÂ»ß"l22Q™�.2¢�âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââiÃââââ$‡ââÂ»¹Êââââ��âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ+�		Hi•ŠââQ5â%h		»kŽ"		¢•€ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââk
tt
ââßââ)�âÙ|ttLâßttt£ââââââââââââââââ99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹ˆˆmmkk¤Ùi£gÖ¡cÔ0¹Ó¹GÐ¸EE¶¶,,,™)—''••$$’!!!��  ŽŽ���ŒŒŒŠŠŠŠŠ‡‡‡‡‡††††††††††††††††††††‡‡‡‡‡‡ŠŠŠŠŒŒŒŒ���ŽŽ   �!!!’$$$•''——)™,,¶¶EE¸¸ÐG¹Ó¹0Ôc¡g£iÙ¤kk¼mmˆˆ‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹
\ No newline at end of file
diff --git a/xrdp/tahoma-10.fv1 b/xrdp/tahoma-10.fv1
new file mode 100755
index 0000000..537bab6
--- /dev/null
+++ b/xrdp/tahoma-10.fv1
@@ -0,0 +1,22 @@
+FNT1Tahoma
+ðÿüÿðÿüÿðÿüÿðÿüÿ	  ð@@à@€€ðÿüÿÀ
+
+€@@€ðÿüÿ�� LR’’ðÿüÿ	€@@€  ``�ðÿüÿðÿüÿ€€ðÿüÿðÿüÿ@€@ðÿüÿàðÿüÿðÿüÿðÿüÿðÿüÿ€€ðÿüÿ€@@@@@@@€ðÿüÿÀðÿüÿ€@@@€Àðÿüÿ€@@@€@@@€ðÿüÿ€€€€€À€€€ðÿüÿÀ€@@@@€ðÿüÿ€€@@@@€ðÿüÿÀ@€€ðÿüÿ€@@@€@@@€ðÿüÿ€@@@@À@€ðÿüÿðÿüÿðÿüÿ	`€€`ðÿüÿ	ðððÿüÿ	À0Àðÿüÿ€€ðÿüÿðô				üððÿüÿ€€@@À  ðÿüÿ€€€€@@@€ðÿüÿÀ  Àðÿüÿ€@     @€ðÿüÿÀÀÀðÿüÿÀÀðÿüÿÀ à  àðÿüÿ    à    ðÿüÿðÿüÿðÿüÿ@€	
+
+	€@ðÿüÿ€ðÿüÿ
+
+(
+(	H	Hˆˆðÿüÿ  
+ 
+ 	   ``ðÿüÿ	À  Àðÿüÿ€@@@€ðÿüÿ	À  À€pðÿüÿ€@@@€	€@ ðÿüÿÀ À   Àðÿüÿàðÿüÿ       @€ðÿüÿ   @@€€ðÿüÿBB¢¢¤ðÿüÿ @€€€€@ ðÿüÿ @@€ðÿüÿÀ@€Àðÿüÿðÿüÿ€€ðÿüÿðÿüÿ	À ðÿüÿàðÿüÿ€ðÿüÿ€@@À@À@ðÿüÿ€@@@@@€ðÿüÿ€€ðÿüÿ@@@À@@@@À@ðÿüÿ€@@À@€ðÿüÿ€ðÿüÿÀ@@@@À@@@€ðÿüÿ€@@@@@@ðÿüÿðÿüÿðÿüÿ€	
+
+	€ðÿüÿðÿüÿ˜dDDDDDðÿüÿ€@@@@@@ðÿüÿ€@@@@@€ðÿüÿ€@@@@@€ðÿüÿÀ@@@@À@@@@ðÿüÿðÿüÿ€€€ðÿüÿðÿüÿ@@@@@À@ðÿüÿ€€ðÿüÿ
+ˆˆPPP  ðÿüÿ€€ðÿüÿ€€ðÿüÿ€€€ðÿüÿ€€ðÿüÿðÿüÿ€ðÿüÿ	�`ðÿüÿ
ÿÿðÿüÿÀÀÀÀðÿüÿ
ÿÿðÿüÿðÿüÿàÀðÿüÿ€€€	ðÿüÿDDðÿüÿÀðÿüÿÀÀðÿüÿ€ ðÿüÿ�� L`R�’�’�`ðÿüÿ@€À À   Àðÿüÿðÿüÿ
ÿ   ?   ÿðÿüÿ
ÿÿðÿüÿ€À@€Àðÿüÿ
ÿÿðÿüÿ
ÿÿðÿüÿðÿüÿðÿüÿ			€ðÿüÿ€€€	ðÿüÿ€€ðÿüÿàðÿüÿÿðÿüÿ@€ðÿüÿDlTDðÿüÿ€€€€ðÿüÿðÿüÿ¼BB~@B¼ðÿüÿ
ÿÿðÿüÿ€€€€ðÿüÿ@ @@€ðÿüÿðÿüÿðÿüÿÀÀðÿüÿÀ Ààðÿüÿ@€€€€@ðÿüÿ @€€Àðÿüÿðÿüÿ€@€@@€@@€ðÿüÿ@ðÿüÿðä					äððÿüÿ€€€€€ðÿüÿ@€		€@ðÿüÿ	ððÿüÿðÿüÿðä			â	"	ððÿüÿàðÿüÿ€€€ðÿüÿààðÿüÿ€€€ðÿüÿ€€€ðÿüÿ€ðÿüÿ@@@@@À@ðÿüÿÀ@@@@@@@@@@ðÿüÿðÿüÿ€€ðÿüÿ€ðÿüÿ€€€€ðÿüÿ	€@@€	ðÿüÿ
"&J’Ÿðÿüÿ
 &IA‚„ðÿüÿ
ˆ’–*R_‚ðÿüÿ€ðÿüÿ€€@@À  ðÿüÿ€€€@@À  ðÿüÿ€@€€@@À  ðÿüÿ@€€€@@À  ðÿüÿ@€€@@À  ðÿüÿ€€€€@@À  ðÿüÿþ   >à  >ðÿüÿÀ  À@@€ðÿüÿÀÀÀðÿüÿ€ÀÀÀðÿüÿ€ÀÀÀðÿüÿ€ÀÀÀðÿüÿðÿüÿðÿüÿ	ðÿüÿ
+ðÿüÿ	À  Àðÿüÿ@€  
+ 
+ 	   ``ðÿüÿ	€À  Àðÿüÿ	€À  Àðÿüÿ	€@À  Àðÿüÿ	 ÀÀ  Àðÿüÿ	@À  Àðÿüÿ	 @€@ ðÿüÿ	Ð P�		
+ Àðÿüÿ       @€ðÿüÿ€       @€ðÿüÿ€@       @€ðÿüÿ@       @€ðÿüÿ€ @@€ðÿüÿ€@@@€ðÿüÿ€€€€@@€ðÿüÿ€@@À@À@ðÿüÿ€€@@À@À@ðÿüÿ€€@@À@À@ðÿüÿ@€€@@À@À@ðÿüÿ€€@@À@À@ðÿüÿ€€€@@À@À@ðÿüÿ0È„ü€Ä8ðÿüÿ€€ðÿüÿ€@@À@€ðÿüÿ€@@À@€ðÿüÿ€€@@À@€ðÿüÿ€€@@À@€ðÿüÿðÿüÿðÿüÿ
+ðÿüÿ
+ðÿüÿ€€@À@@@€ðÿüÿ@€€@@@@@@ðÿüÿ€@@@@@€ðÿüÿ€€@@@@@€ðÿüÿ€€@@@@@€ðÿüÿ@€€@@@@@€ðÿüÿ€€@@@@@€ðÿüÿ	àðÿüÿ@€€	@
+@
+@€ðÿüÿ@@@@@À@ðÿüÿ@@@@@À@ðÿüÿ€@@@@@À@ðÿüÿ€@@@@@À@ðÿüÿ€€ðÿüÿ€@@@@@€ðÿüÿ€€€
\ No newline at end of file
diff --git a/xrdp/tile256.bmp b/xrdp/tile256.bmp
new file mode 100644
index 0000000..84838b0
--- /dev/null
+++ b/xrdp/tile256.bmp
@@ -0,0 +1,1508 @@
+BM6%6(„@


			
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	
+
+
+
+
+
+
+	
+
+
+
+
+
+
+	
+
+
+
+
+
+
+	
+
+	
+
+
+
+
+	
+
+
+
+
+	
+
+
+
+
+	
+
+
+
+
+
+
+
+
	
+
+
+
+
+
+
+
+
	
+
+
+
+
+
+
+
+
	
+
+
+
+
+
+
+
+
	
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+

+
+
+
+
+
+

+
+
+
+
+
+

+
+
+
+
+
+		
+
+
+
+
+
+
+
+
+		
+
+
+
+
+
+
+
+
+		
+
+
+
+
+
+
+
+
+		
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+		
+
+
+
+
+
+
+
+
+		
+
+
+
+
+
+
+
+
+		
+
+
+
+
+
+
+
+
+		
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+

+
+
+
+
	
+
+
+
+
	
+
+
+
+
	
+
+
+
+
	
+
+	
+
+
+
+
+
+
+
+
+	
+
+
+
+
+
+
+
+
+	
+
+
+
+
+
+
+
+
+	
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	
+
+
+
+
+	
+
+
+
+
+	
+
+
+
+
+	
+
+
+
+
+
+
+
+	
+	
+	
+	
+
+
+	
+
+
+
+
+
+	
+
+
+
+
+
+	
+
+
+
+
+
+	
+
+
+
+
+
+
+
+
+
+	
+
+
+
+
+
+	
+
+
+
+
+
+	
+
+
+
+
+
+	
+
+
+
+
+
+
+
+
+
+
+		
+	
+
+
+		
+	
+
+
+		
+	
+
+
+		
+	
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	
+
+
+
+
+
+
+	
+
+
+
+
+
+
+	
+
+
+
+
+
+
+	
+
+	
+
+
+
+
+	
+
+
+
+
+	
+
+
+
+
+	
+
+
+
+
+
+
+
+
	
+
+
+
+
+
+
+
+
	
+
+
+
+
+
+
+
+
	
+
+
+
+
+
+
+
+
	
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+

+
+
+
+
+
+

+
+
+
+
+
+

+
+
+
+
+
+		
+
+
+
+
+
+
+
+
+		
+
+
+
+
+
+
+
+
+		
+
+
+
+
+
+
+
+
+		
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+		
+
+
+
+
+
+
+
+
+		
+
+
+
+
+
+
+
+
+		
+
+
+
+
+
+
+
+
+		
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+

+
+
+
+
	
+
+
+
+
	
+
+
+
+
	
+
+
+
+
	
+
+	
+
+
+
+
+
+
+
+
+	
+
+
+
+
+
+
+
+
+	
+
+
+
+
+
+
+
+
+	
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	
+
+
+
+
+	
+
+
+
+
+	
+
+
+
+
+	
+
+
+
+
+
+
+
+	
+	
+	
+	
+
+
+	
+
+
+
+
+
+	
+
+
+
+
+
+	
+
+
+
+
+
+	
+
+
+
+
+
+
+
+
+
+	
+
+
+
+
+
+	
+
+
+
+
+
+	
+
+
+
+
+
+	
+
+
+
+
+
+
+
+
+
+
+		
+	
+
+
+		
+	
+
+
+		
+	
+
+
+		
+	
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/xrdp/xrdp.c b/xrdp/xrdp.c
index 344a80b..b876344 100644
--- a/xrdp/xrdp.c
+++ b/xrdp/xrdp.c
@@ -22,6 +22,10 @@
 
 #if defined(_WIN32)
 #include <windows.h>
+#else
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 #endif
 #include "xrdp.h"
 
@@ -139,6 +143,21 @@ pipe_sig(int sig_num)
 }
 
 /*****************************************************************************/
+void DEFAULT_CC
+child_sig(int sig_num)
+{
+  int pid;
+
+  g_writeln("got SIGCHLD(%d)", sig_num);
+
+  pid = g_waitchild();
+  if (pid > 0)
+  {
+    g_writeln("child %d exited", pid);
+  }
+}
+
+/*****************************************************************************/
 void APP_CC
 g_loop(void)
 {
@@ -501,19 +520,12 @@ main(int argc, char** argv)
   if (!no_daemon)
   {
     /* make sure we can write to pid file */
-    fd = g_file_open(XRDP_PID_FILE); /* xrdp.pid */
+    fd = open (XRDP_PID_FILE, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
     if (fd == -1)
     {
       g_writeln("running in daemon mode with no access to pid files, quitting");
       g_exit(0);
     }
-    if (g_file_write(fd, "0", 1) == -1)
-    {
-      g_writeln("running in daemon mode with no access to pid files, quitting");
-      g_exit(0);
-    }
-    g_file_close(fd);
-    g_file_delete(XRDP_PID_FILE);
   }
   if (!no_daemon)
   {
@@ -522,6 +534,8 @@ main(int argc, char** argv)
     if (pid == -1)
     {
       g_writeln("problem forking");
+      close (fd);
+      g_file_delete(XRDP_PID_FILE);
       g_exit(1);
     }
     if (0 != pid)
@@ -543,20 +557,10 @@ main(int argc, char** argv)
   {
     /* write the pid to file */
     pid = g_getpid();
-    fd = g_file_open(XRDP_PID_FILE); /* xrdp.pid */
-    if (fd == -1)
-    {
-      g_writeln("trying to write process id to xrdp.pid");
-      g_writeln("problem opening xrdp.pid");
-      g_writeln("maybe no rights");
-    }
-    else
-    {
-      g_set_file_rights(XRDP_PID_FILE, 1, 1); /* xrdp.pid */
-      g_sprintf(text, "%d", pid);
-      g_file_write(fd, text, g_strlen(text));
-      g_file_close(fd);
-    }
+    g_set_file_rights(XRDP_PID_FILE, 1, 1); /* xrdp.pid */
+    g_sprintf(text, "%d", pid);
+    g_file_write(fd, text, g_strlen(text));
+    close (fd);
   }
 #endif
   g_threadid = tc_get_threadid();
@@ -565,6 +569,7 @@ main(int argc, char** argv)
   g_signal(9, xrdp_shutdown); /* SIGKILL */
   g_signal(13, pipe_sig); /* sig pipe */
   g_signal(15, xrdp_shutdown); /* SIGTERM */
+  g_signal_child_stop(child_sig); /* SIGCHLD */
   g_sync_mutex = tc_mutex_create();
   g_sync1_mutex = tc_mutex_create();
   g_term_event = g_create_wait_obj("xrdp_main_term");
diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h
index 94e6ed5..8d8a442 100644
--- a/xrdp/xrdp.h
+++ b/xrdp/xrdp.h
@@ -92,6 +92,10 @@ xrdp_wm_load_static_colors(struct xrdp_wm* self);
 int APP_CC
 xrdp_wm_load_static_pointers(struct xrdp_wm* self);
 int APP_CC
+xrdp_wm_load_sections(struct xrdp_wm* self,
+		      struct list* string_list,
+		      struct list* data_list);
+int APP_CC
 xrdp_wm_init(struct xrdp_wm* self);
 int APP_CC
 xrdp_wm_send_bitmap(struct xrdp_wm* self, struct xrdp_bitmap* bitmap,
@@ -395,3 +399,5 @@ server_get_channel_id(struct xrdp_mod* mod, char* name);
 int DEFAULT_CC
 server_send_to_channel(struct xrdp_mod* mod, int channel_id,
                        char* data, int data_len);
+int DEFAULT_CC
+server_set_login_mode(struct xrdp_mod* mod, int login_mode);
diff --git a/xrdp/xrdp.ini b/xrdp/xrdp.ini
index 5b635dd..a91fad0 100644
--- a/xrdp/xrdp.ini
+++ b/xrdp/xrdp.ini
@@ -6,47 +6,18 @@ port=3389
 crypt_level=low
 channel_code=1
 
-[xrdp1]
-name=sesman-Xvnc
-lib=libvnc.so
+[xsessions]
+path=/usr/share/xsessions
+lib=libdmx.so
 username=ask
 password=ask
 ip=127.0.0.1
 port=-1
 
-[xrdp2]
-name=console
+[failsafe]
+name=Failsafe Terminal
+exec=xterm
 lib=libvnc.so
-ip=127.0.0.1
-port=5900
-username=na
-password=ask
-
-[xrdp3]
-name=vnc-any
-lib=libvnc.so
-ip=ask
-port=ask5900
-username=na
-password=ask
-
-[xrdp4]
-name=sesman-any
-lib=libvnc.so
-ip=ask
-port=-1
-username=ask
-password=ask
-
-[xrdp5]
-name=rdp-any
-lib=librdp.so
-ip=ask
-port=ask3389
-
-[xrdp6]
-name=sesman-X11rdp
-lib=libxup.so
 username=ask
 password=ask
 ip=127.0.0.1
diff --git a/xrdp/xrdp_bitmap.c b/xrdp/xrdp_bitmap.c
index b3d7162..ecb3716 100644
--- a/xrdp/xrdp_bitmap.c
+++ b/xrdp/xrdp_bitmap.c
@@ -98,7 +98,9 @@ xrdp_bitmap_create(int width, int height, int bpp,
     case 15: Bpp = 2; break;
     case 16: Bpp = 2; break;
   }
-  if (self->type == WND_TYPE_BITMAP || self->type == WND_TYPE_IMAGE)
+  if (self->type == WND_TYPE_BITMAP ||
+      self->type == WND_TYPE_IMAGE ||
+      self->type == WND_TYPE_TILE)
   {
     self->data = (char*)g_malloc(width * height * Bpp, 0);
   }
@@ -107,6 +109,8 @@ xrdp_bitmap_create(int width, int height, int bpp,
     self->child_list = list_create();
   }
   self->line_size = width * Bpp;
+  self->line_width = width;
+  self->lines = height;
   if (self->type == WND_TYPE_COMBO)
   {
     self->string_list = list_create();
@@ -132,6 +136,8 @@ xrdp_bitmap_create_with_data(int width, int height,
   self->height = height;
   self->bpp = bpp;
   self->data = data;
+  self->line_width = width;
+  self->lines = height;
   self->do_not_free_data = 1;
   self->wm = wm;
   return self;
@@ -260,21 +266,25 @@ xrdp_bitmap_set_focus(struct xrdp_bitmap* self, int focused)
   painter = xrdp_painter_create(self->wm, self->wm->session);
   xrdp_painter_font_needed(painter);
   xrdp_painter_begin_update(painter);
+
+  /* bottom dark gray line */
+  painter->fg_color = self->wm->dark_grey;
+  xrdp_painter_fill_rect(painter, self, 2, 22, self->width - 4, 1); 
   if (focused)
   {
     /* active title bar */
-    painter->fg_color = self->wm->blue;
-    xrdp_painter_fill_rect(painter, self, 3, 3, self->width - 5, 18);
+    painter->fg_color = self->wm->dark_blue;
+    xrdp_painter_fill_rect(painter, self, 2, 2, self->width - 4, 20);
     painter->fg_color = self->wm->white;
   }
   else
   {
     /* inactive title bar */
     painter->fg_color = self->wm->dark_grey;
-    xrdp_painter_fill_rect(painter, self, 3, 3, self->width - 5, 18);
+    xrdp_painter_fill_rect(painter, self, 2, 2, self->width - 4, 20);
     painter->fg_color = self->wm->black;
   }
-  xrdp_painter_draw_text(painter, self, 4, 4, self->caption1);
+  xrdp_painter_draw_text(painter, self, 8, 4, self->caption1);
   xrdp_painter_end_update(painter);
   xrdp_painter_delete(painter);
   return 0;
@@ -303,8 +313,16 @@ int APP_CC
 xrdp_bitmap_resize(struct xrdp_bitmap* self, int width, int height)
 {
   int Bpp;
-
-  if ((width == self->width) && (height == self->height))
+  
+  Bpp = 4;
+  switch (self->bpp)
+  {
+    case 8: Bpp = 1; break;
+    case 15: Bpp = 2; break;
+    case 16: Bpp = 2; break;
+  }
+ 
+  if ((width * Bpp == self->line_size) && (height == self->lines))
   {
     return 0;
   }
@@ -312,18 +330,16 @@ xrdp_bitmap_resize(struct xrdp_bitmap* self, int width, int height)
   {
     return 1;
   }
-  self->width = width;
-  self->height = height;
-  Bpp = 4;
-  switch (self->bpp)
+  if (self->type == WND_TYPE_IMAGE)
   {
-    case 8: Bpp = 1; break;
-    case 15: Bpp = 2; break;
-    case 16: Bpp = 2; break;
+    self->width = width;
+    self->height = height;
   }
   g_free(self->data);
   self->data = (char*)g_malloc(width * height * Bpp, 0);
   self->line_size = width * Bpp;
+  self->line_width = width;
+  self->lines = height;
   return 0;
 }
 
@@ -413,9 +429,9 @@ xrdp_bitmap_load(struct xrdp_bitmap* self, const char* filename, int* palette)
       {
         g_file_read(fd, data + i * header.image_width, header.image_width);
       }
-      for (i = 0; i < self->height; i++)
+      for (i = 0; i < self->lines; i++)
       {
-        for (j = 0; j < self->width; j++)
+        for (j = 0; j < self->line_width; j++)
         {
           k = (unsigned char)data[i * header.image_width + j];
           color = palette1[k];
@@ -464,19 +480,19 @@ xrdp_bitmap_get_pixel(struct xrdp_bitmap* self, int x, int y)
   {
     return 0;
   }
-  if (x >= 0 && x < self->width && y >= 0 && y < self->height)
+  if (x >= 0 && x < self->line_width && y >= 0 && y < self->lines)
   {
     if (self->bpp == 8)
     {
-      return GETPIXEL8(self->data, x, y, self->width);
+      return GETPIXEL8(self->data, x, y, self->line_width);
     }
     else if (self->bpp == 15 || self->bpp == 16)
     {
-      return GETPIXEL16(self->data, x, y, self->width);
+      return GETPIXEL16(self->data, x, y, self->line_width);
     }
     else if (self->bpp == 24)
     {
-      return GETPIXEL32(self->data, x, y, self->width);
+      return GETPIXEL32(self->data, x, y, self->line_width);
     }
   }
   return 0;
@@ -494,19 +510,19 @@ xrdp_bitmap_set_pixel(struct xrdp_bitmap* self, int x, int y, int pixel)
   {
     return 0;
   }
-  if (x >= 0 && x < self->width && y >= 0 && y < self->height)
+  if (x >= 0 && x < self->line_width && y >= 0 && y < self->lines)
   {
     if (self->bpp == 8)
     {
-      SETPIXEL8(self->data, x, y, self->width, pixel);
+      SETPIXEL8(self->data, x, y, self->line_width, pixel);
     }
     else if (self->bpp == 15 || self->bpp == 16)
     {
-      SETPIXEL16(self->data, x, y, self->width, pixel);
+      SETPIXEL16(self->data, x, y, self->line_width, pixel);
     }
     else if (self->bpp == 24)
     {
-      SETPIXEL32(self->data, x, y, self->width, pixel);
+      SETPIXEL32(self->data, x, y, self->line_width, pixel);
     }
   }
   return 0;
@@ -534,11 +550,15 @@ xrdp_bitmap_copy_box(struct xrdp_bitmap* self,
   {
     return 1;
   }
-  if (self->type != WND_TYPE_BITMAP && self->type != WND_TYPE_IMAGE)
+  if (self->type != WND_TYPE_BITMAP &&
+      self->type != WND_TYPE_IMAGE &&
+      self->type != WND_TYPE_TILE)
   {
     return 1;
   }
-  if (dest->type != WND_TYPE_BITMAP && dest->type != WND_TYPE_IMAGE)
+  if (dest->type != WND_TYPE_BITMAP &&
+      dest->type != WND_TYPE_IMAGE &&
+      dest->type != WND_TYPE_TILE)
   {
     return 1;
   }
@@ -562,8 +582,8 @@ xrdp_bitmap_copy_box(struct xrdp_bitmap* self,
     {
       for (j = 0; j < cx; j++)
       {
-        pixel = GETPIXEL32(self->data, j + x, i + y, self->width);
-        SETPIXEL32(dest->data, j + destx, i + desty, dest->width, pixel);
+        pixel = GETPIXEL32(self->data, j + x, i + y, self->line_width);
+        SETPIXEL32(dest->data, j + destx, i + desty, dest->line_width, pixel);
       }
     }
   }
@@ -573,8 +593,8 @@ xrdp_bitmap_copy_box(struct xrdp_bitmap* self,
     {
       for (j = 0; j < cx; j++)
       {
-        pixel = GETPIXEL16(self->data, j + x, i + y, self->width);
-        SETPIXEL16(dest->data, j + destx, i + desty, dest->width, pixel);
+        pixel = GETPIXEL16(self->data, j + x, i + y, self->line_width);
+        SETPIXEL16(dest->data, j + destx, i + desty, dest->line_width, pixel);
       }
     }
   }
@@ -584,8 +604,8 @@ xrdp_bitmap_copy_box(struct xrdp_bitmap* self,
     {
       for (j = 0; j < cx; j++)
       {
-        pixel = GETPIXEL8(self->data, j + x, i + y, self->width);
-        SETPIXEL8(dest->data, j + destx, i + desty, dest->width, pixel);
+        pixel = GETPIXEL8(self->data, j + x, i + y, self->line_width);
+        SETPIXEL8(dest->data, j + destx, i + desty, dest->line_width, pixel);
       }
     }
   }
@@ -625,11 +645,15 @@ xrdp_bitmap_copy_box_with_crc(struct xrdp_bitmap* self,
   {
     return 1;
   }
-  if (self->type != WND_TYPE_BITMAP && self->type != WND_TYPE_IMAGE)
+  if (self->type != WND_TYPE_BITMAP &&
+      self->type != WND_TYPE_IMAGE &&
+      self->type != WND_TYPE_TILE)
   {
     return 1;
   }
-  if (dest->type != WND_TYPE_BITMAP && dest->type != WND_TYPE_IMAGE)
+  if (dest->type != WND_TYPE_BITMAP &&
+      dest->type != WND_TYPE_IMAGE &&
+      dest->type != WND_TYPE_TILE)
   {
     return 1;
   }
@@ -655,20 +679,20 @@ xrdp_bitmap_copy_box_with_crc(struct xrdp_bitmap* self,
     {
       for (j = 0; j < cx; j++)
       {
-        pixel = GETPIXEL32(self->data, j + x, i + y, self->width);
+        pixel = GETPIXEL32(self->data, j + x, i + y, self->line_width);
         CRC_PASS(pixel, crc);
         CRC_PASS(pixel >> 8, crc);
         CRC_PASS(pixel >> 16, crc);
-        SETPIXEL32(dest->data, j + destx, i + desty, dest->width, pixel);
+        SETPIXEL32(dest->data, j + destx, i + desty, dest->line_width, pixel);
       }
     }
   }
   else if (self->bpp == 15 || self->bpp == 16)
   {
-    s16 = ((unsigned short*)(self->data)) + (self->width * y + x);
-    d16 = ((unsigned short*)(dest->data)) + (dest->width * desty + destx);
-    incs = self->width - cx;
-    incd = dest->width - cx;
+    s16 = ((unsigned short*)(self->data)) + (self->line_width * y + x);
+    d16 = ((unsigned short*)(dest->data)) + (dest->line_width * desty + destx);
+    incs = self->line_width - cx;
+    incd = dest->line_width - cx;
     for (i = 0; i < cy; i++)
     {
       for (j = 0; j < cx; j++)
@@ -686,10 +710,10 @@ xrdp_bitmap_copy_box_with_crc(struct xrdp_bitmap* self,
   }
   else if (self->bpp == 8)
   {
-    s8 = ((unsigned char*)(self->data)) + (self->width * y + x);
-    d8 = ((unsigned char*)(dest->data)) + (dest->width * desty + destx);
-    incs = self->width - cx;
-    incd = dest->width - cx;
+    s8 = ((unsigned char*)(self->data)) + (self->line_width * y + x);
+    d8 = ((unsigned char*)(dest->data)) + (dest->line_width * desty + destx);
+    incs = self->line_width - cx;
+    incd = dest->line_width - cx;
     for (i = 0; i < cy; i++)
     {
       for (j = 0; j < cx; j++)
@@ -731,15 +755,15 @@ xrdp_bitmap_compare(struct xrdp_bitmap* self,
   {
     return 0;
   }
-  if (self->width != b->width)
+  if (self->line_width != b->line_width)
   {
     return 0;
   }
-  if (self->height != b->height)
+  if (self->lines != b->lines)
   {
     return 0;
   }
-  if (g_memcmp(self->data, b->data, b->height * b->line_size) == 0)
+  if (g_memcmp(self->data, b->data, b->lines * b->line_size) == 0)
   {
     return 1;
   }
@@ -764,11 +788,11 @@ xrdp_bitmap_compare_with_crc(struct xrdp_bitmap* self,
   {
     return 0;
   }
-  if (self->width != b->width)
+  if (self->line_width != b->line_width)
   {
     return 0;
   }
-  if (self->height != b->height)
+  if (self->lines != b->lines)
   {
     return 0;
   }
@@ -826,32 +850,32 @@ xrdp_bitmap_draw_button(struct xrdp_bitmap* self,
 {
   if (down)
   {
-    /* gray box */
-    painter->fg_color = self->wm->grey;
+    /* medium gray box */
+    painter->fg_color = self->wm->med_grey;
     xrdp_painter_fill_rect(painter, self, x, y, w, h);
-    /* black top line */
-    painter->fg_color = self->wm->black;
-    xrdp_painter_fill_rect(painter, self, x, y, w, 1);
-    /* black left line */
-    painter->fg_color = self->wm->black;
-    xrdp_painter_fill_rect(painter, self, x, y, 1, h);
     /* dark grey top line */
     painter->fg_color = self->wm->dark_grey;
-    xrdp_painter_fill_rect(painter, self, x + 1, y + 1, w - 2, 1);
+    xrdp_painter_fill_rect(painter, self, x, y, w, 1);
     /* dark grey left line */
     painter->fg_color = self->wm->dark_grey;
+    xrdp_painter_fill_rect(painter, self, x, y, 1, h);
+    /* medium grey top line */
+    painter->fg_color = self->wm->med_grey;
+    xrdp_painter_fill_rect(painter, self, x + 1, y + 1, w - 2, 1);
+    /* medium grey left line */
+    painter->fg_color = self->wm->med_grey;
     xrdp_painter_fill_rect(painter, self, x + 1, y + 1, 1, h - 2);
+    /* white bottom line */
+    painter->fg_color = self->wm->white;
+    xrdp_painter_fill_rect(painter, self, x + 1, y + (h - 2), w - 1, 1);
+    /* white right line */
+    painter->fg_color = self->wm->white;
+    xrdp_painter_fill_rect(painter, self, x + (w - 2), y + 1, 1, h - 1);
     /* dark grey bottom line */
     painter->fg_color = self->wm->dark_grey;
-    xrdp_painter_fill_rect(painter, self, x + 1, y + (h - 2), w - 1, 1);
+    xrdp_painter_fill_rect(painter, self, x, y + (h - 1), w, 1);
     /* dark grey right line */
     painter->fg_color = self->wm->dark_grey;
-    xrdp_painter_fill_rect(painter, self, x + (w - 2), y + 1, 1, h - 1);
-    /* black bottom line */
-    painter->fg_color = self->wm->black;
-    xrdp_painter_fill_rect(painter, self, x, y + (h - 1), w, 1);
-    /* black right line */
-    painter->fg_color = self->wm->black;
     xrdp_painter_fill_rect(painter, self, x + (w - 1), y, 1, h);
   }
   else
@@ -859,23 +883,29 @@ xrdp_bitmap_draw_button(struct xrdp_bitmap* self,
     /* gray box */
     painter->fg_color = self->wm->grey;
     xrdp_painter_fill_rect(painter, self, x, y, w, h);
+    /* dark grey top line */
+    painter->fg_color = self->wm->dark_grey;
+    xrdp_painter_fill_rect(painter, self, x, y, w, 1);
+    /* dark grey left line */
+    painter->fg_color = self->wm->dark_grey;
+    xrdp_painter_fill_rect(painter, self, x, y, 1, h);
     /* white top line */
     painter->fg_color = self->wm->white;
-    xrdp_painter_fill_rect(painter, self, x, y, w, 1);
+    xrdp_painter_fill_rect(painter, self, x + 1, y + 1, w - 2, 1);
     /* white left line */
     painter->fg_color = self->wm->white;
-    xrdp_painter_fill_rect(painter, self, x, y, 1, h);
+    xrdp_painter_fill_rect(painter, self, x + 1, y + 1, 1, h - 2);
+    /* medium grey bottom line */
+    painter->fg_color = self->wm->med_grey;
+    xrdp_painter_fill_rect(painter, self, x + 1, y + (h - 2), w - 1, 1);
+    /* medium grey right line */
+    painter->fg_color = self->wm->med_grey;
+    xrdp_painter_fill_rect(painter, self, x + (w - 2), y + 1, 1, h - 1);
     /* dark grey bottom line */
     painter->fg_color = self->wm->dark_grey;
-    xrdp_painter_fill_rect(painter, self, x + 1, y + (h - 2), w - 1, 1);
+    xrdp_painter_fill_rect(painter, self, x, y + (h - 1), w, 1);
     /* dark grey right line */
     painter->fg_color = self->wm->dark_grey;
-    xrdp_painter_fill_rect(painter, self, (x + w) - 2, y + 1, 1, h - 1);
-    /* black bottom line */
-    painter->fg_color = self->wm->black;
-    xrdp_painter_fill_rect(painter, self, x, y + (h - 1), w, 1);
-    /* black right line */
-    painter->fg_color = self->wm->black;
     xrdp_painter_fill_rect(painter, self, x + (w - 1), y, 1, h);
   }
   return 0;
@@ -931,43 +961,55 @@ xrdp_bitmap_invalidate(struct xrdp_bitmap* self, struct xrdp_rect* rect)
     /* draw grey background */
     painter->fg_color = self->bg_color;
     xrdp_painter_fill_rect(painter, self, 0, 0, self->width, self->height);
+    /* top grey line */
+    painter->fg_color = self->wm->white;
+    xrdp_painter_fill_rect(painter, self, 0, 0, self->width, 1);
+    /* left grey line */
+    painter->fg_color = self->wm->white;
+    xrdp_painter_fill_rect(painter, self, 0, 0, 1, self->height);
+
     /* top white line */
     painter->fg_color = self->wm->white;
     xrdp_painter_fill_rect(painter, self, 1, 1, self->width - 2, 1);
     /* left white line */
     painter->fg_color = self->wm->white;
     xrdp_painter_fill_rect(painter, self, 1, 1, 1, self->height - 2);
-    /* bottom dark grey line */
-    painter->fg_color = self->wm->dark_grey;
+
+    /* bottom medium grey line */
+    painter->fg_color = self->wm->med_grey;
     xrdp_painter_fill_rect(painter, self, 1, self->height - 2,
                            self->width - 2, 1);
-    /* right dark grey line */
-    painter->fg_color = self->wm->dark_grey;
+    /* right medium grey line */
+    painter->fg_color = self->wm->med_grey;
     xrdp_painter_fill_rect(painter, self, self->width - 2, 1, 1,
                            self->height - 2);
-    /* bottom black line */
-    painter->fg_color = self->wm->black;
+    /* bottom dark grey line */
+    painter->fg_color = self->wm->dark_grey;
     xrdp_painter_fill_rect(painter, self, 0, self->height - 1,
                            self->width, 1);
-    /* right black line */
-    painter->fg_color = self->wm->black;
+    /* right dark grey line */
+    painter->fg_color = self->wm->dark_grey;
     xrdp_painter_fill_rect(painter, self, self->width - 1, 0,
                            1, self->height);
+
+    /* bottom dark gray line */
+    painter->fg_color = self->wm->dark_grey;
+    xrdp_painter_fill_rect(painter, self, 2, 22, self->width - 4, 1); 
     if (self->wm->focused_window == self)
     {
       /* active title bar */
-      painter->fg_color = self->wm->blue;
-      xrdp_painter_fill_rect(painter, self, 3, 3, self->width - 5, 18);
+      painter->fg_color = self->wm->dark_blue;
+      xrdp_painter_fill_rect(painter, self, 2, 2, self->width - 4, 20);
       painter->fg_color = self->wm->white;
     }
     else
     {
       /* inactive title bar */
       painter->fg_color = self->wm->dark_grey;
-      xrdp_painter_fill_rect(painter, self, 3, 3, self->width - 5, 18);
+      xrdp_painter_fill_rect(painter, self, 2, 2, self->width - 4, 20);
       painter->fg_color = self->wm->black;
     }
-    xrdp_painter_draw_text(painter, self, 4, 4, self->caption1);
+    xrdp_painter_draw_text(painter, self, 8, 4, self->caption1);
   }
   else if (self->type == WND_TYPE_SCREEN) /* 2 */
   {
@@ -1052,65 +1094,78 @@ xrdp_bitmap_invalidate(struct xrdp_bitmap* self, struct xrdp_rect* rect)
   }
   else if (self->type == WND_TYPE_EDIT) /* 5 */
   {
-    /* draw gray box */
-    painter->fg_color = self->wm->grey;
+    /* draw dark gray box */
+    painter->fg_color = self->wm->dark_grey;
     xrdp_painter_fill_rect(painter, self, 0, 0, self->width, self->height);
     /* main white background */
     painter->fg_color = self->wm->white;
-    xrdp_painter_fill_rect(painter, self, 1, 1, self->width - 3,
-                           self->height - 3);
-    /* dark grey top line */
-    painter->fg_color = self->wm->dark_grey;
-    xrdp_painter_fill_rect(painter, self, 0, 0, self->width, 1);
-    /* dark grey left line */
-    painter->fg_color = self->wm->dark_grey;
-    xrdp_painter_fill_rect(painter, self, 0, 0, 1, self->height);
+    xrdp_painter_fill_rect(painter, self, 2, 2, self->width - 4,
+                           self->height - 4);
+    /* medium grey top line */
+    painter->fg_color = self->wm->med_grey;
+    xrdp_painter_fill_rect(painter, self, 1, 1, self->width - 2, 1);
+    /* medium grey left line */
+    painter->fg_color = self->wm->med_grey;
+    xrdp_painter_fill_rect(painter, self, 1, 1, 1, self->height - 2);
     /* white bottom line */
     painter->fg_color = self->wm->white;
-    xrdp_painter_fill_rect(painter, self, 0, self->height- 1, self->width, 1);
+    xrdp_painter_fill_rect(painter, self, 1, self->height- 2, self->width - 2, 1);
     /* white right line */
     painter->fg_color = self->wm->white;
-    xrdp_painter_fill_rect(painter, self, self->width - 1, 0, 1, self->height);
-    /* black left line */
-    painter->fg_color = self->wm->black;
-    xrdp_painter_fill_rect(painter, self, 1, 1, 1, self->height - 2);
-    /* black top line */
-    painter->fg_color = self->wm->black;
-    xrdp_painter_fill_rect(painter, self, 1, 1, self->width - 2, 1);
+    xrdp_painter_fill_rect(painter, self, self->width - 2, 1, 1, self->height - 2);
     /* draw text */
     painter->fg_color = self->wm->black;
     if (self->password_char != 0)
     {
-      i = g_mbstowcs(0, self->caption1, 0);
+      i = MIN (g_mbstowcs(0, self->caption1, 0), 255);
       g_memset(text, self->password_char, i);
       text[i] = 0;
       xrdp_painter_draw_text(painter, self, 4, 2, text);
     }
     else
     {
-      xrdp_painter_draw_text(painter, self, 4, 2, self->caption1);
+      char *cap = self->caption1;
+      int  pos;
+
+      i = 2;
+      for (;;)
+      {
+        for (pos = 0; cap[pos] != '\0' && cap[pos] != '\n'; pos++);
+
+        if (cap[pos] == '\0')
+        {
+          xrdp_painter_draw_text(painter, self, 4, i, cap);
+          break;
+        }
+        cap[pos] = '\0';
+        xrdp_painter_draw_text(painter, self, 4, i, cap);
+        cap[pos] = '\n';
+        cap += (pos + 1);
+        i += 15;
+      }
     }
     /* draw xor box(cursor) */
     if (self->parent != 0)
     {
       if (self->parent->focused_control == self)
       {
+	i = MIN (self->edit_pos, 255);
         if (self->password_char != 0)
         {
-          wchar_repeat(wtext, 255, self->password_char, self->edit_pos);
-          wtext[self->edit_pos] = 0;
-          g_wcstombs(text, wtext, 255);
+          wchar_repeat(wtext, 255, self->password_char, i);
+          wtext[i] = 0;
+          g_wcstombs(text, wtext, i);
         }
         else
         {
           g_mbstowcs(wtext, self->caption1, 255);
-          wtext[self->edit_pos] = 0;
+          wtext[i] = 0;
           g_wcstombs(text, wtext, 255);
         }
         w = xrdp_painter_text_width(painter, text);
         painter->fg_color = self->wm->white;
         painter->rop = 0x5a;
-        xrdp_painter_fill_rect(painter, self, 4 + w, 3, 2, self->height - 6);
+        xrdp_painter_fill_rect(painter, self, 4 + w, 3, 2, 14);
       }
     }
     /* reset rop back */
@@ -1123,37 +1178,32 @@ xrdp_bitmap_invalidate(struct xrdp_bitmap* self, struct xrdp_rect* rect)
   }
   else if (self->type == WND_TYPE_COMBO) /* 7 combo box */
   {
-    /* draw gray box */
-    painter->fg_color = self->wm->grey;
+    /* draw dark gray box */
+    painter->fg_color = self->wm->dark_grey;
     xrdp_painter_fill_rect(painter, self, 0, 0, self->width, self->height);
-    /* white background */
+    /* main white background */
     painter->fg_color = self->wm->white;
-    xrdp_painter_fill_rect(painter, self, 1, 1, self->width - 3,
-                           self->height - 3);
-    if (self->parent->focused_control == self)
-    {
-      painter->fg_color = self->wm->dark_blue;
-      xrdp_painter_fill_rect(painter, self, 3, 3, (self->width - 6) - 18,
-                             self->height - 5);
-    }
-    /* dark grey top line */
-    painter->fg_color = self->wm->dark_grey;
-    xrdp_painter_fill_rect(painter, self, 0, 0, self->width, 1);
-    /* dark grey left line */
-    painter->fg_color = self->wm->dark_grey;
-    xrdp_painter_fill_rect(painter, self, 0, 0, 1, self->height);
+    xrdp_painter_fill_rect(painter, self, 2, 2, self->width - 4,
+                           self->height - 4);
+    /* medium grey top line */
+    painter->fg_color = self->wm->med_grey;
+    xrdp_painter_fill_rect(painter, self, 1, 1, self->width - 2, 1);
+    /* medium grey left line */
+    painter->fg_color = self->wm->med_grey;
+    xrdp_painter_fill_rect(painter, self, 1, 1, 1, self->height - 2);
     /* white bottom line */
     painter->fg_color = self->wm->white;
-    xrdp_painter_fill_rect(painter, self, 0, self->height- 1, self->width, 1);
+    xrdp_painter_fill_rect(painter, self, 1, self->height- 2, self->width - 2, 1);
     /* white right line */
     painter->fg_color = self->wm->white;
-    xrdp_painter_fill_rect(painter, self, self->width - 1, 0, 1, self->height);
-    /* black left line */
-    painter->fg_color = self->wm->black;
-    xrdp_painter_fill_rect(painter, self, 1, 1, 1, self->height - 2);
-    /* black top line */
-    painter->fg_color = self->wm->black;
-    xrdp_painter_fill_rect(painter, self, 1, 1, self->width - 2, 1);
+    xrdp_painter_fill_rect(painter, self, self->width - 2, 1, 1, self->height - 2);
+
+    if (self->parent->focused_control == self)
+    {
+      painter->fg_color = self->wm->dark_blue;
+      xrdp_painter_fill_rect(painter, self, 2, 2, (self->width - 4) - 19,
+                             self->height - 4);
+    }
     /* draw text */
     if (self->parent->focused_control == self)
     {
@@ -1178,6 +1228,13 @@ xrdp_bitmap_invalidate(struct xrdp_bitmap* self, struct xrdp_rect* rect)
     {
       xrdp_bitmap_draw_button(self, painter, x, y, w, h, 1);
     }
+    /* black arrow */
+    painter->fg_color = self->wm->black;
+    xrdp_painter_fill_rect(painter, self, x + 5, y + 6, w - 10, 1);
+    xrdp_painter_fill_rect(painter, self, x + 6, y + 7, w - 12, 1);
+    xrdp_painter_fill_rect(painter, self, x + 7, y + 8, w - 14, 1);
+    xrdp_painter_fill_rect(painter, self, x + 8, y + 9, w - 16, 1);
+
   }
   else if (self->type == WND_TYPE_SPECIAL) /* 8 special */
   {
@@ -1207,6 +1264,22 @@ xrdp_bitmap_invalidate(struct xrdp_bitmap* self, struct xrdp_rect* rect)
       }
     }
   }
+  else if (self->type == WND_TYPE_TILE) /* 10 tile */
+  {
+      y = self->top;
+      while (y < self->height)
+      {
+          x = self->left;
+	  while (x < self->width)
+	  {
+	      xrdp_painter_copy(painter, self, self, x, y,
+				self->line_width, self->lines, 0, 0);
+              x += self->line_width;
+	  }
+          y += self->lines;
+      }
+  }
+
   /* notify */
   if (self->notify != 0)
   {
diff --git a/xrdp/xrdp_login_wnd.c b/xrdp/xrdp_login_wnd.c
index 784c06f..b38f93c 100644
--- a/xrdp/xrdp_login_wnd.c
+++ b/xrdp/xrdp_login_wnd.c
@@ -205,7 +205,12 @@ xrdp_wm_ok_clicked(struct xrdp_bitmap* wnd)
       edit = xrdp_bitmap_get_child_by_id(wnd, i + 1);
       while (label != 0 && edit != 0)
       {
-        set_mod_data_item(mod_data, label->caption1, edit->caption1);
+	if (g_strcmp (label->caption1, "User name:") == 0)
+          set_mod_data_item(mod_data, "username", edit->caption1);
+	else if (g_strcmp (label->caption1, "Password:") == 0)
+          set_mod_data_item(mod_data, "password", edit->caption1);
+	else
+          set_mod_data_item(mod_data, label->caption1, edit->caption1);
         i += 2;
         label = xrdp_bitmap_get_child_by_id(wnd, i);
         edit = xrdp_bitmap_get_child_by_id(wnd, i + 1);
@@ -268,21 +273,24 @@ xrdp_wm_show_edits(struct xrdp_wm* self, struct xrdp_bitmap* combo)
         insert_index++;
         b->parent = self->login_window;
         b->owner = self->login_window;
-        b->left = 155;
-        b->top = 60 + 25 * count;
+        b->left = 16;
+        b->top = 159 + 25 * count;
         b->id = 100 + 2 * count;
         name = (char*)list_get_item(mod->names, index);
-        set_string(&b->caption1, name);
+        if (g_strcmp (name, "username") == 0)
+          set_string(&b->caption1, "User name:");
+        else
+          set_string(&b->caption1, "Password:");
         /* edit */
-        b = xrdp_bitmap_create(140, 20, self->screen->bpp,
+        b = xrdp_bitmap_create(self->login_window->width - 200, 20, self->screen->bpp,
                                WND_TYPE_EDIT, self);
         list_insert_item(self->login_window->child_list, insert_index,
                               (long)b);
         insert_index++;
         b->parent = self->login_window;
         b->owner = self->login_window;
-        b->left = 230;
-        b->top = 60 + 25 * count;
+        b->left = 100;
+        b->top = 159 + 25 * count;
         b->id = 100 + 2 * count + 1;
         b->pointer = 1;
         b->tab_stop = 1;
@@ -370,7 +378,6 @@ xrdp_wm_login_notify(struct xrdp_bitmap* wnd,
   }
   else if (msg == CB_ITEMCHANGE) /* combo box change */
   {
-    xrdp_wm_show_edits(wnd->wm, sender);
     xrdp_bitmap_invalidate(wnd, 0); /* invalidate the whole dialog for now */
   }
   return 0;
@@ -380,62 +387,7 @@ xrdp_wm_login_notify(struct xrdp_bitmap* wnd,
 static int APP_CC
 xrdp_wm_login_fill_in_combo(struct xrdp_wm* self, struct xrdp_bitmap* b)
 {
-  struct list* sections;
-  struct list* section_names;
-  struct list* section_values;
-  int fd;
-  int i;
-  int j;
-  char* p;
-  char* q;
-  char* r;
-  char name[256];
-  struct xrdp_mod_data* mod_data;
-
-  sections = list_create();
-  sections->auto_free = 1;
-  section_names = list_create();
-  section_names->auto_free = 1;
-  section_values = list_create();
-  section_values->auto_free = 1;
-  fd = g_file_open(XRDP_CFG_FILE); /* xrdp.ini */
-  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)
-    {
-    }
-    else
-    {
-      g_strncpy(name, p, 255);
-      mod_data = (struct xrdp_mod_data*)
-                     g_malloc(sizeof(struct xrdp_mod_data), 1);
-      mod_data->names = list_create();
-      mod_data->names->auto_free = 1;
-      mod_data->values = list_create();
-      mod_data->values->auto_free = 1;
-      for (j = 0; j < section_names->count; j++)
-      {
-        q = (char*)list_get_item(section_names, j);
-        r = (char*)list_get_item(section_values, j);
-        if (g_strncmp("name", q, 255) == 0)
-        {
-          g_strncpy(name, r, 255);
-        }
-        list_add_item(mod_data->names, (long)g_strdup(q));
-        list_add_item(mod_data->values, (long)g_strdup(r));
-      }
-      list_add_item(b->string_list, (long)g_strdup(name));
-      list_add_item(b->data_list, (long)mod_data);
-    }
-  }
-  g_file_close(fd);
-  list_delete(sections);
-  list_delete(section_names);
-  list_delete(section_values);
-  return 0;
+  return xrdp_wm_load_sections(self, b->string_list, b->data_list);
 }
 
 /******************************************************************************/
@@ -445,11 +397,19 @@ xrdp_login_wnd_create(struct xrdp_wm* self)
   struct xrdp_bitmap* but;
   struct xrdp_bitmap* combo;
   char file_path[256];
+  char hostname[256];
+  char title[288];
+  int i;
+
+  g_strncpy(hostname, "xrdp", 255);
+  g_gethostname(hostname, 255);
+  hostname[255] = '\0';
+  g_snprintf(title, 287, "Log On to %s", hostname);
 
   /* draw login window */
-  self->login_window = xrdp_bitmap_create(400, 200, self->screen->bpp,
+  self->login_window = xrdp_bitmap_create(404, 278, self->screen->bpp,
                                           WND_TYPE_WND, self);
-  list_add_item(self->screen->child_list, (long)self->login_window);
+  list_insert_item(self->screen->child_list, 0, (long)self->login_window);
   self->login_window->parent = self->screen;
   self->login_window->owner = self->screen;
   self->login_window->bg_color = self->grey;
@@ -458,26 +418,16 @@ xrdp_login_wnd_create(struct xrdp_wm* self)
   self->login_window->top = self->screen->height / 2 -
                             self->login_window->height / 2;
   self->login_window->notify = xrdp_wm_login_notify;
-  set_string(&self->login_window->caption1, "Login to xrdp");
+  set_string(&self->login_window->caption1, title);
 
   /* image */
   but = xrdp_bitmap_create(4, 4, self->screen->bpp, WND_TYPE_IMAGE, self);
-  g_snprintf(file_path, 255, "%s/xrdp256.bmp", XRDP_SHARE_PATH);
-  xrdp_bitmap_load(but, file_path, self->palette);
-  but->parent = self->screen;
-  but->owner = self->screen;
-  but->left = self->screen->width - but->width;
-  but->top = self->screen->height - but->height;
-  list_add_item(self->screen->child_list, (long)but);
-
-  /* image */
-  but = xrdp_bitmap_create(4, 4, self->screen->bpp, WND_TYPE_IMAGE, self);
-  g_snprintf(file_path, 255, "%s/ad256.bmp", XRDP_SHARE_PATH);
+  g_snprintf(file_path, 255, "%s/rdc256.bmp", XRDP_SHARE_PATH);
   xrdp_bitmap_load(but, file_path, self->palette);
   but->parent = self->login_window;
   but->owner = self->login_window;
-  but->left = 10;
-  but->top = 30;
+  but->left = 2;
+  but->top = 23;
   list_add_item(self->login_window->child_list, (long)but);
 
   /* label */
@@ -485,28 +435,38 @@ xrdp_login_wnd_create(struct xrdp_wm* self)
   list_add_item(self->login_window->child_list, (long)but);
   but->parent = self->login_window;
   but->owner = self->login_window;
-  but->left = 155;
-  but->top = 35;
-  set_string(&but->caption1, "Module");
+  but->left = 16;
+  but->top = 209;
+  set_string(&but->caption1, "Session:");
 
   /* combo */
-  combo = xrdp_bitmap_create(140, 20, self->screen->bpp, WND_TYPE_COMBO, self);
+  combo = xrdp_bitmap_create(self->login_window->width - 200, 20, self->screen->bpp, WND_TYPE_COMBO, self);
   list_add_item(self->login_window->child_list, (long)combo);
   combo->parent = self->login_window;
   combo->owner = self->login_window;
-  combo->left = 230;
-  combo->top = 35;
+  combo->left = 100;
+  combo->top = 209;
   combo->id = 6;
   combo->tab_stop = 1;
   xrdp_wm_login_fill_in_combo(self, combo);
+  for (i = 0; i < combo->string_list->count; i++)
+  {
+    char *p;
+    p = (char*)list_get_item(combo->string_list, i);
+    if (g_strncmp(p, self->client_info->program, 255) == 0)
+    {
+      combo->item_index = i;
+      break;
+    }
+  }
 
   /* button */
   but = xrdp_bitmap_create(60, 25, self->screen->bpp, WND_TYPE_BUTTON, self);
   list_add_item(self->login_window->child_list, (long)but);
   but->parent = self->login_window;
   but->owner = self->login_window;
-  but->left = 180;
-  but->top = 160;
+  but->left = self->login_window->width - 75;
+  but->top = self->login_window->height - 38;
   but->id = 3;
   set_string(&but->caption1, "OK");
   but->tab_stop = 1;
@@ -517,14 +477,14 @@ xrdp_login_wnd_create(struct xrdp_wm* self)
   list_add_item(self->login_window->child_list, (long)but);
   but->parent = self->login_window;
   but->owner = self->login_window;
-  but->left = 250;
-  but->top = 160;
+  but->left = self->login_window->width - 145;
+  but->top = self->login_window->height - 38;
   but->id = 2;
   set_string(&but->caption1, "Cancel");
   but->tab_stop = 1;
   self->login_window->esc_button = but;
 
-  /* button */
+  /* button
   but = xrdp_bitmap_create(60, 25, self->screen->bpp, WND_TYPE_BUTTON, self);
   list_add_item(self->login_window->child_list, (long)but);
   but->parent = self->login_window;
@@ -533,7 +493,7 @@ xrdp_login_wnd_create(struct xrdp_wm* self)
   but->top = 160;
   but->id = 1;
   set_string(&but->caption1, "Help");
-  but->tab_stop = 1;
+  but->tab_stop = 1; */
 
   /* labels and edits */
   xrdp_wm_show_edits(self, combo);
diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c
index cec7177..70fa02a 100644
--- a/xrdp/xrdp_mm.c
+++ b/xrdp/xrdp_mm.c
@@ -200,12 +200,14 @@ xrdp_mm_send_login(struct xrdp_mm* self)
   int count;
   char* username;
   char* password;
+  char* exec;
   char* name;
   char* value;
 
   xrdp_wm_log_msg(self->wm, "sending login info to sesman");
   username = 0;
   password = 0;
+  exec = "";
   self->code = 0;
   count = self->login_names->count;
   for (index = 0; index < count; index++)
@@ -220,9 +222,18 @@ xrdp_mm_send_login(struct xrdp_mm* self)
     {
       password = value;
     }
+    else if (g_strcasecmp(name, "exec") == 0)
+    {
+      exec = value;
+    }
     else if (g_strcasecmp(name, "lib") == 0)
     {
-      if ((g_strcasecmp(value, "libxup.so") == 0) ||
+      if ((g_strcasecmp(value, "libdmx.so") == 0) ||
+          (g_strcasecmp(value, "dmx.dll") == 0))
+      {
+        self->code = 20;
+      }
+      else if ((g_strcasecmp(value, "libxup.so") == 0) ||
           (g_strcasecmp(value, "xup.dll") == 0))
       {
         self->code = 10;
@@ -245,15 +256,19 @@ xrdp_mm_send_login(struct xrdp_mm* self)
   index = g_strlen(password);
   out_uint16_be(s, index);
   out_uint8a(s, password, index);
+  index = g_strlen(exec);
+  out_uint16_be(s, index);
+  out_uint8a(s, exec, index);
   out_uint16_be(s, self->wm->screen->width);
   out_uint16_be(s, self->wm->screen->height);
   out_uint16_be(s, self->wm->screen->bpp);
+  out_uint16_be(s, self->wm->session->client_info->keylayout);
   s_mark_end(s);
   s_pop_layer(s, channel_hdr);
   out_uint32_be(s, 0); /* version */
   index = s->end - s->data;
   out_uint32_be(s, index); /* size */
-  rv = xrdp_mm_send(self, s->data, index);
+  rv = xrdp_mm_send(self, s->data, s->end - s->data);
   free_stream(s);
   return rv;
 }
@@ -382,6 +397,7 @@ 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_set_login_mode = server_set_login_mode;
     }
   }
   /* id self->mod is null, there must be a problem */
@@ -428,6 +444,10 @@ xrdp_mm_setup_mod2(struct xrdp_mm* self)
       {
         g_snprintf(text, 255, "%d", 6200 + self->display);
       }
+      else if (self->code == 20) /* Xdmx */
+      {
+        g_snprintf(text, 255, "%d", 6000 + self->display);
+      }
       else
       {
         g_set_wait_obj(self->wm->pro_layer->self_term_event); /* kill session */
@@ -511,7 +531,8 @@ xrdp_mm_process_login_response(struct xrdp_mm* self, struct stream* s)
     {
       if (xrdp_mm_setup_mod2(self) == 0)
       {
-        xrdp_wm_set_login_mode(self->wm, 10);
+	if (self->wm->login_mode == 3)
+	  xrdp_wm_set_login_mode(self->wm, 10);
         self->wm->dragging = 0;
       }
     }
@@ -526,7 +547,7 @@ xrdp_mm_process_login_response(struct xrdp_mm* self, struct stream* s)
   g_tcp_close(self->sck);
   self->sck = 0;
   self->connected_state = 0;
-  if (self->wm->login_mode != 10)
+  if (self->wm->login_mode < 4)
   {
     xrdp_wm_set_login_mode(self->wm, 11);
     xrdp_mm_module_cleanup(self);
@@ -634,10 +655,11 @@ xrdp_mm_connect(struct xrdp_mm* self)
     {
       if (xrdp_mm_setup_mod2(self) == 0)
       {
-        xrdp_wm_set_login_mode(self->wm, 10);
+	if (self->wm->login_mode == 3)
+	  xrdp_wm_set_login_mode(self->wm, 10);
       }
     }
-    if (self->wm->login_mode != 10)
+    if (self->wm->login_mode < 4)
     {
       xrdp_wm_set_login_mode(self->wm, 11);
       xrdp_mm_module_cleanup(self);
@@ -1028,3 +1050,13 @@ server_send_to_channel(struct xrdp_mod* mod, int channel_id,
   wm = (struct xrdp_wm*)mod->wm;
   return libxrdp_send_to_channel(wm->session, channel_id, data, data_len);
 }
+
+/*****************************************************************************/
+int DEFAULT_CC
+server_set_login_mode(struct xrdp_mod* mod, int login_mode)
+{
+  struct xrdp_wm* wm;
+
+  wm = (struct xrdp_wm*)mod->wm;
+  return xrdp_wm_set_login_mode (wm, login_mode);
+}
diff --git a/xrdp/xrdp_painter.c b/xrdp/xrdp_painter.c
index 451f530..0593dd3 100644
--- a/xrdp/xrdp_painter.c
+++ b/xrdp/xrdp_painter.c
@@ -602,13 +602,13 @@ xrdp_painter_copy(struct xrdp_painter* self,
     y += dy;
     palette_id = 0;
     j = srcy;
-    while (j < src->height)
+    while (j < src->lines)
     {
       i = srcx;
-      while (i < src->width)
+      while (i < src->line_width)
       {
-        w = MIN(64, src->width - i);
-        h = MIN(64, src->height - j);
+        w = MIN(64, src->line_width - i);
+        h = MIN(64, src->lines - 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);
diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h
index 7d2b2b7..0852899 100644
--- a/xrdp/xrdp_types.h
+++ b/xrdp/xrdp_types.h
@@ -78,7 +78,8 @@ struct xrdp_mod
   int (*server_get_channel_id)(struct xrdp_mod* v, char* name);
   int (*server_send_to_channel)(struct xrdp_mod* v, int channel_id,
                                 char* data, int data_len);
-  long server_dumby[100 - 24]; /* align, 100 minus the number of server 
+  int (*server_set_login_mode)(struct xrdp_mod* v, int login_mode);
+  long server_dumby[100 - 25]; /* align, 100 minus the number of server 
                                   functions above */
   /* common */
   long handle; /* pointer to self as int */
@@ -209,6 +210,7 @@ struct xrdp_wm
   /* generic colors */
   int black;
   int grey;
+  int med_grey;
   int dark_grey;
   int blue;
   int dark_blue;
@@ -247,6 +249,7 @@ struct xrdp_wm
   /* session log */
   struct list* log;
   struct xrdp_bitmap* log_wnd;
+  struct xrdp_bitmap* log_edit;
   int login_mode;
   tbus login_mode_event;
   struct xrdp_mm* mm;
@@ -318,6 +321,8 @@ struct xrdp_bitmap
   /* for bitmap */
   int bpp;
   int line_size; /* in bytes */
+  int line_width;
+  int lines;
   int do_not_free_data;
   char* data;
   /* for all but bitmap */
@@ -356,7 +361,7 @@ struct xrdp_bitmap
 };
 
 #define NUM_FONTS 0x4e00
-#define DEFAULT_FONT_NAME "sans-10.fv1"
+#define DEFAULT_FONT_NAME "tahoma-10.fv1"
 
 /* font */
 struct xrdp_font
diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c
index 1d09cf6..d14c3d8 100644
--- a/xrdp/xrdp_wm.c
+++ b/xrdp/xrdp_wm.c
@@ -290,10 +290,11 @@ xrdp_wm_load_static_colors(struct xrdp_wm* self)
       }
     }
     self->black     = COLOR8(0, 0, 0);
-    self->grey      = COLOR8(0xc0, 0xc0, 0xc0);
-    self->dark_grey = COLOR8(0x80, 0x80, 0x80);
-    self->blue      = COLOR8(0x00, 0x00, 0xff);
-    self->dark_blue = COLOR8(0x00, 0x00, 0x7f);
+    self->grey      = COLOR8(0xfb, 0xfb, 0xfb);
+    self->med_grey  = COLOR8(0xed, 0xed, 0xed);
+    self->dark_grey = COLOR8(0xb0, 0xb0, 0xb0);
+    self->blue      = COLOR8(0x7e, 0xa4, 0xd4);
+    self->dark_blue = COLOR8(0x4e, 0x76, 0xa8);
     self->white     = COLOR8(0xff, 0xff, 0xff);
     self->red       = COLOR8(0xff, 0x00, 0x00);
     self->green     = COLOR8(0x00, 0xff, 0x00);
@@ -302,10 +303,11 @@ xrdp_wm_load_static_colors(struct xrdp_wm* self)
   else if (self->screen->bpp == 15)
   {
     self->black     = COLOR15(0, 0, 0);
-    self->grey      = COLOR15(0xc0, 0xc0, 0xc0);
-    self->dark_grey = COLOR15(0x80, 0x80, 0x80);
-    self->blue      = COLOR15(0x00, 0x00, 0xff);
-    self->dark_blue = COLOR15(0x00, 0x00, 0x7f);
+    self->grey      = COLOR15(0xfb, 0xfb, 0xfb);
+    self->med_grey  = COLOR15(0xed, 0xed, 0xed);
+    self->dark_grey = COLOR15(0xb0, 0xb0, 0xb0);
+    self->blue      = COLOR15(0x7e, 0xa4, 0xd4);
+    self->dark_blue = COLOR15(0x4e, 0x76, 0xa8);
     self->white     = COLOR15(0xff, 0xff, 0xff);
     self->red       = COLOR15(0xff, 0x00, 0x00);
     self->green     = COLOR15(0x00, 0xff, 0x00);
@@ -313,10 +315,11 @@ xrdp_wm_load_static_colors(struct xrdp_wm* self)
   else if (self->screen->bpp == 16)
   {
     self->black     = COLOR16(0, 0, 0);
-    self->grey      = COLOR16(0xc0, 0xc0, 0xc0);
-    self->dark_grey = COLOR16(0x80, 0x80, 0x80);
-    self->blue      = COLOR16(0x00, 0x00, 0xff);
-    self->dark_blue = COLOR16(0x00, 0x00, 0x7f);
+    self->grey      = COLOR16(0xfb, 0xfb, 0xfb);
+    self->med_grey  = COLOR16(0xed, 0xed, 0xed);
+    self->dark_grey = COLOR16(0xb0, 0xb0, 0xb0);
+    self->blue      = COLOR16(0x7e, 0xa4, 0xd4);
+    self->dark_blue = COLOR16(0x4e, 0x76, 0xa8);
     self->white     = COLOR16(0xff, 0xff, 0xff);
     self->red       = COLOR16(0xff, 0x00, 0x00);
     self->green     = COLOR16(0x00, 0xff, 0x00);
@@ -324,10 +327,11 @@ xrdp_wm_load_static_colors(struct xrdp_wm* self)
   else if (self->screen->bpp == 24)
   {
     self->black     = COLOR24BGR(0, 0, 0);
-    self->grey      = COLOR24BGR(0xc0, 0xc0, 0xc0);
-    self->dark_grey = COLOR24BGR(0x80, 0x80, 0x80);
-    self->blue      = COLOR24BGR(0x00, 0x00, 0xff);
-    self->dark_blue = COLOR24BGR(0x00, 0x00, 0x7f);
+    self->grey      = COLOR24BGR(0xfb, 0xfb, 0xfb);
+    self->med_grey  = COLOR24BGR(0xed, 0xed, 0xed);
+    self->dark_grey = COLOR24BGR(0xb0, 0xb0, 0xb0);
+    self->blue      = COLOR24BGR(0x7e, 0xa4, 0xd4);
+    self->dark_blue = COLOR24BGR(0x4e, 0x76, 0xa8);
     self->white     = COLOR24BGR(0xff, 0xff, 0xff);
     self->red       = COLOR24BGR(0xff, 0x00, 0x00);
     self->green     = COLOR24BGR(0x00, 0xff, 0x00);
@@ -360,12 +364,236 @@ xrdp_wm_load_static_pointers(struct xrdp_wm* self)
 
 /*****************************************************************************/
 int APP_CC
-xrdp_wm_init(struct xrdp_wm* self)
+xrdp_wm_load_sections(struct xrdp_wm* self,
+		      struct list* string_list,
+		      struct list* data_list)
 {
+  struct list* sections;
+  struct list* section_names;
+  struct list* section_values;
   int fd;
+  int i;
+  int j;
+  char* p;
+  char* q;
+  char* r;
+  char name[256];
+  struct xrdp_mod_data* mod_data;
+
+  sections = list_create();
+  sections->auto_free = 1;
+  section_names = list_create();
+  section_names->auto_free = 1;
+  section_values = list_create();
+  section_values->auto_free = 1;
+  fd = g_file_open(XRDP_CFG_FILE); /* xrdp.ini */
+  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)
+    {
+    }
+    else if (g_strncmp(p, "xsessions", 255) == 0)
+    {
+      unsigned int dir;
+      char         path[256];
+
+      g_strncpy(path, ".", 255);
+      for (j = 0; j < section_names->count; j++)
+      {
+        q = (char*)list_get_item(section_names, j);
+        r = (char*)list_get_item(section_values, j);
+	if (g_strncmp("path", q, 255) == 0)
+        {
+	  g_strncpy(path, r, 255);
+	  break;
+        }
+      }
+
+      if (g_directory_exist (path) && (dir = g_dir_open (path)))
+      {
+	const char*  file;
+	struct list* entry_names;
+	struct list* entry_values;
+
+	struct stream* s;
+	char stext[512];
+	char sname[512];
+	char svalue[512];
+	int wm_fd, len;
+	char *default_wm;
+
+	entry_names = list_create();
+	entry_names->auto_free = 1;
+	entry_values = list_create();
+	entry_values->auto_free = 1;
+
+	default_wm = g_strdup("twm");
+	g_memset(stext, 0, 512);
+	make_stream(s);
+	init_stream(s, 32 * 1024);
+	wm_fd = g_file_open("/etc/sysconfig/windowmanager");
+	len = g_file_read(wm_fd, s->data, 32 * 1024);
+	if (len > 0)
+	{
+	  s->end = s->p + len;
+	  while (file_read_line(s, stext) == 0)
+	  {
+	    if (g_strlen(stext) > 0)
+	    {
+	      file_split_name_value(stext, sname, svalue);
+	      if (g_strcmp (sname, "DEFAULT_WM") == 0)
+	      {
+		default_wm = g_strdup(svalue);
+		break;
+	      }
+	    }
+	  }
+	}
+	g_file_close(wm_fd);
+	free_stream(s);
+
+	while ((file = g_dir_read_name (dir)))
+	{
+	  int de_fd;
+	  int prepend = 0;
+
+	  if (g_pos ((char *) file, ".desktop") == -1)
+	    continue;
+
+	  g_strncpy(name, file, 255);
+	  mod_data = (struct xrdp_mod_data*)
+	      g_malloc(sizeof(struct xrdp_mod_data), 1);
+	  mod_data->names = list_create();
+	  mod_data->names->auto_free = 1;
+	  mod_data->values = list_create();
+	  mod_data->values->auto_free = 1;
+
+	  g_snprintf(name, 255, "%s/%s", path, file);
+	  de_fd = g_file_open(name);
+
+	  g_strncpy(name, file, 255);
+	  file_read_section(de_fd, "Desktop Entry", entry_names, entry_values);
+	  for (j = 0; j < entry_names->count; j++)
+	  {
+	    q = (char*)list_get_item(entry_names, j);
+	    r = (char*)list_get_item(entry_values, j);
+	    if (g_strncmp("Name", q, 255) == 0)
+	    {
+	      g_strncpy(name, r, 255);
+	    }
+	    else if (g_strncmp("Exec", q, 255) == 0)
+	    {
+	      list_add_item(mod_data->names, (long)g_strdup("exec"));
+	      list_add_item(mod_data->values, (long)g_strdup(r));
+
+	      if (default_wm && g_pos (default_wm, r) != -1)
+		prepend = 1;
+	    }
+	  }
+
+	  for (j = 0; j < section_names->count; j++)
+	  {
+	    q = (char*)list_get_item(section_names, j);
+	    r = (char*)list_get_item(section_values, j);
+	    list_add_item(mod_data->names, (long)g_strdup(q));
+	    list_add_item(mod_data->values, (long)g_strdup(r));
+	  }
+
+	  if (prepend)
+	  {
+	    list_insert_item(string_list, 0, (long)g_strdup(name));
+	    list_insert_item(data_list, 0, (long)mod_data);
+	  }
+	  else
+	  {
+	    list_add_item(string_list, (long)g_strdup(name));
+	    list_add_item(data_list, (long)mod_data);
+	  }
+	  
+	  g_file_close(de_fd);
+	}
+
+	list_delete(entry_names);
+	list_delete(entry_values);
+
+	if (default_wm)
+	  g_free (default_wm);
+
+	g_dir_close (dir);
+      }
+    }
+    else
+    {
+      g_strncpy(name, p, 255);
+      mod_data = (struct xrdp_mod_data*)
+                     g_malloc(sizeof(struct xrdp_mod_data), 1);
+      mod_data->names = list_create();
+      mod_data->names->auto_free = 1;
+      mod_data->values = list_create();
+      mod_data->values->auto_free = 1;
+      for (j = 0; j < section_names->count; j++)
+      {
+        q = (char*)list_get_item(section_names, j);
+        r = (char*)list_get_item(section_values, j);
+        if (g_strncmp("name", q, 255) == 0)
+        {
+          g_strncpy(name, r, 255);
+        }
+        list_add_item(mod_data->names, (long)g_strdup(q));
+        list_add_item(mod_data->values, (long)g_strdup(r));
+      }
+      list_add_item(string_list, (long)g_strdup(name));
+      list_add_item(data_list, (long)mod_data);
+    }
+  }
+  g_file_close(fd);
+  list_delete(sections);
+  list_delete(section_names);
+  list_delete(section_values);
+  return 0;
+}
+
+/******************************************************************************/
+static void APP_CC
+xrdp_wm_background_create(struct xrdp_wm* self)
+{
+  struct xrdp_bitmap* b;
+  char file_path[256];
+
+  /* image */
+  b = xrdp_bitmap_create(4, 4, self->screen->bpp, WND_TYPE_IMAGE, self);
+  g_snprintf(file_path, 255, "%s/opensuse256.bmp", XRDP_SHARE_PATH);
+  xrdp_bitmap_load(b, file_path, self->palette);
+  b->parent = self->screen;
+  b->owner = self->screen;
+  b->left = 0;
+  b->top = 0;
+  list_add_item(self->screen->child_list, (long)b);
+
+  /* tile */
+  b = xrdp_bitmap_create(4, 4, self->screen->bpp, WND_TYPE_TILE, self);
+  g_snprintf(file_path, 255, "%s/tile256.bmp", XRDP_SHARE_PATH);
+  xrdp_bitmap_load(b, file_path, self->palette);
+  b->parent = self->screen;
+  b->owner = self->screen;
+  b->left = 0;
+  b->top = 0;
+  b->width = self->screen->width;
+  b->height = self->screen->height;
+  list_add_item(self->screen->child_list, (long)b);
+}
+
+/*****************************************************************************/
+int APP_CC
+xrdp_wm_init(struct xrdp_wm* self)
+{
+  struct xrdp_mod_data* mod_data;
   int index;
-  struct list* names;
-  struct list* values;
+  struct list* string_list;
+  struct list* data_list;
   char* q;
   char* r;
   char section_name[256];
@@ -375,63 +603,71 @@ xrdp_wm_init(struct xrdp_wm* self)
   self->screen->bg_color = self->black;
   if (self->session->client_info->rdp_autologin)
   {
-    fd = g_file_open(XRDP_CFG_FILE); /* xrdp.ini */
-    if (fd > 0)
+    string_list = list_create();
+    string_list->auto_free = 1;
+    data_list = list_create();
+    data_list->auto_free = 1;
+    xrdp_wm_load_sections (self, string_list, data_list);
+    g_strncpy(section_name, self->session->client_info->program, 255);
+    index = 0;
+    if (section_name[0] != 0)
     {
-      names = list_create();
-      names->auto_free = 1;
-      values = list_create();
-      values->auto_free = 1;
-      g_strncpy(section_name, self->session->client_info->domain, 255);
-      if (section_name[0] == 0)
+      int i;
+
+      for (i = 0; i < string_list->count; i++)
       {
-        /* if no doamin is passed, use the first item in the xrdp.ini
-           file thats not named 'globals' */
-        file_read_sections(fd, names);
-        for (index = 0; index < names->count; index++)
-        {
-          q = (char*)list_get_item(names, index);
-          if (g_strncasecmp("globals", q, 8) != 0)
-          {
-            g_strncpy(section_name, q, 255);
-            break;
-          }
-        }
+        q = (char*)list_get_item(string_list, i);
+	if (g_strcasecmp(section_name, q) == 0)
+	{
+	  index = i;
+          break;
+	}
       }
-      list_clear(names);
-      if (file_read_section(fd, section_name, names, values) == 0)
+    }
+    mod_data = (struct xrdp_mod_data*) list_get_item(data_list, index);
+    if (mod_data != 0)
+    {
+      for (index = 0; index < mod_data->names->count; index++)
       {
-        for (index = 0; index < names->count; index++)
+        q = (char*)list_get_item(mod_data->names, index);
+	r = (char*)list_get_item(mod_data->values, index);
+	if (g_strncmp("password", q, 255) == 0)
         {
-          q = (char*)list_get_item(names, index);
-          r = (char*)list_get_item(values, index);
-          if (g_strncmp("password", q, 255) == 0)
-          {
-            list_add_item(self->mm->login_names, (long)g_strdup("password"));
-            list_add_item(self->mm->login_values,
-                   (long)g_strdup(self->session->client_info->password));
-          }
-          else if (g_strncmp("username", q, 255) == 0)
-          {
-            list_add_item(self->mm->login_names, (long)g_strdup("username"));
-            list_add_item(self->mm->login_values,
-                   (long)g_strdup(self->session->client_info->username));
-          }
-          else
-          {
-            list_add_item(self->mm->login_names, (long)g_strdup(q));
-            list_add_item(self->mm->login_values, (long)g_strdup(r));
-          }
-        }
-        xrdp_wm_set_login_mode(self, 2);
+          list_add_item(self->mm->login_names, (long)g_strdup("password"));
+	  list_add_item(self->mm->login_values,
+			(long)g_strdup(self->session->client_info->password));
+	}
+	else if (g_strncmp("username", q, 255) == 0)
+	{
+          list_add_item(self->mm->login_names, (long)g_strdup("username"));
+	  list_add_item(self->mm->login_values,
+			(long)g_strdup(self->session->client_info->username));
+	}
+	else
+	{
+          list_add_item(self->mm->login_names, (long)g_strdup(q));
+	  list_add_item(self->mm->login_values, (long)g_strdup(r));
+	}
       }
-      list_delete(names);
-      list_delete(values);
-      g_file_close(fd);
     }
+
+    xrdp_wm_set_login_mode(self, 2);
+
+    for (index = 0; index < data_list->count; index++)
+    {
+      mod_data = (struct xrdp_mod_data*)list_get_item(data_list, index);
+      if (mod_data != 0)
+      {
+        list_delete(mod_data->names);
+	list_delete(mod_data->values);
+      }
+    }
+    list_delete(string_list);
+    list_delete(data_list);
   }
   else
   {
+    xrdp_wm_background_create(self);
     xrdp_login_wnd_create(self);
     /* clear screen */
     xrdp_bitmap_invalidate(self->screen, 0);
@@ -1255,8 +1491,8 @@ xrdp_wm_process_channel_data(struct xrdp_wm* self, int channel_id,
   {
     if (self->mm->mod->mod_event != 0)
     {
-      self->mm->mod->mod_event(self->mm->mod, 0x5555, channel_id, (long)data,
-                               data_len, 0);
+      return self->mm->mod->mod_event(self->mm->mod, 0x5555, channel_id,
+				      (long)data, data_len, 0);
     }
   }
   return 0;
@@ -1329,44 +1565,26 @@ xrdp_wm_login_mode_changed(struct xrdp_wm* self)
   {
     xrdp_wm_set_login_mode(self, 3); /* put the wm in connected mode */
     xrdp_wm_delete_all_childs(self);
+    xrdp_wm_background_create(self);
+    xrdp_bitmap_invalidate(self->screen, 0);
     self->dragging = 0;
     xrdp_mm_connect(self->mm);
   }
+  else if (self->login_mode == 4)
+  {
+    /* intermediate state used by dmx module */
+    xrdp_wm_set_login_mode(self, 5);
+  }
   else if (self->login_mode == 10)
   {
     xrdp_wm_delete_all_childs(self);
+    xrdp_bitmap_invalidate(self->screen, 0);
     self->dragging = 0;
     xrdp_wm_set_login_mode(self, 11);
   }
-  return 0;
-}
-
-/******************************************************************************/
-/* returns error */
-int APP_CC
-xrdp_wm_app_sck_signal(struct xrdp_wm* self, int app_sck)
-{
-  if (self->login_mode == 3)
-  {
-    if (xrdp_mm_signal(self->mm) != 0)
-    {
-      return 1;
-    }
-  }
-  else if (self->login_mode > 9)
+  else if (self->login_mode == 20)
   {
-    if (self->mm->mod == 0)
-    {
-      return 1;
-    }
-    if (self->mm->mod->mod_signal == 0)
-    {
-      return 1;
-    }
-    if (self->mm->mod->mod_signal(self->mm->mod) != 0)
-    {
-      return 1;
-    }
+    return 1; /* end session */
   }
   return 0;
 }
@@ -1401,30 +1619,7 @@ xrdp_wm_log_wnd_notify(struct xrdp_bitmap* wnd,
   {
     if (sender->id == 1) /* ok button */
     {
-      /* close the log window */
-      MAKERECT(rect, wnd->left, wnd->top, wnd->width, wnd->height);
-      xrdp_bitmap_delete(wnd);
-      xrdp_bitmap_invalidate(wm->screen, &rect);
-      /* if module is gone, reset the session when ok is clicked */
-      if (wm->mm->mod_handle == 0)
-      {
-        /* make sure autologin is off */
-        wm->session->client_info->rdp_autologin = 0;
-        xrdp_wm_set_login_mode(wm, 0); /* reset session */
-      }
-    }
-  }
-  else if (msg == WM_PAINT) /* 3 */
-  {
-    painter = (struct xrdp_painter*)param1;
-    if (painter != 0)
-    {
-      painter->fg_color = wnd->wm->black;
-      for (index = 0; index < wnd->wm->log->count; index++)
-      {
-        text = (char*)list_get_item(wnd->wm->log, index);
-        xrdp_painter_draw_text(painter, wnd, 10, 30 + index * 15, text);
-      }
+      xrdp_wm_set_login_mode(wm, 20); /* end session */
     }
   }
   return 0;
@@ -1440,22 +1635,39 @@ xrdp_wm_log_msg(struct xrdp_wm* self, char* msg)
   if (self->log_wnd == 0)
   {
     /* log window */
-    self->log_wnd = xrdp_bitmap_create(400, 400, self->screen->bpp,
+    self->log_wnd = xrdp_bitmap_create(620, 430, self->screen->bpp,
                                        WND_TYPE_WND, self);
-    list_add_item(self->screen->child_list, (long)self->log_wnd);
+    list_insert_item(self->screen->child_list, 0, (long)self->log_wnd);
     self->log_wnd->parent = self->screen;
     self->log_wnd->owner = self->screen;
     self->log_wnd->bg_color = self->grey;
     self->log_wnd->left = 10;
-    self->log_wnd->top = 10;
+    self->log_wnd->top = 40;
     set_string(&(self->log_wnd->caption1), "Connection Log");
+
+    /* edit */
+    self->log_edit = xrdp_bitmap_create(self->log_wnd->width - 18,
+					self->log_wnd->height - 72,
+					self->screen->bpp,
+					WND_TYPE_EDIT, self);
+    list_insert_item(self->log_wnd->child_list, 0, (long)self->log_edit);
+    self->log_edit->parent = self->log_wnd;
+    self->log_edit->owner = self->log_wnd;
+    self->log_edit->left = 9;
+    self->log_edit->top = 30;
+    self->log_edit->id = 2;
+    self->log_edit->pointer = 0;
+    self->log_edit->tab_stop = 0;
+    self->log_edit->edit_pos = 0;
+    set_string(&(self->log_edit->caption1), msg);
+
     /* ok button */
     but = xrdp_bitmap_create(60, 25, self->screen->bpp, WND_TYPE_BUTTON, self);
     list_insert_item(self->log_wnd->child_list, 0, (long)but);
     but->parent = self->log_wnd;
     but->owner = self->log_wnd;
-    but->left = (400 - 60) - 10;
-    but->top = (400 - 25) - 10;
+    but->left = (self->log_wnd->width - 60) - 10;
+    but->top = (self->log_wnd->height - 25) - 10;
     but->id = 1;
     but->tab_stop = 1;
     set_string(&but->caption1, "OK");
@@ -1463,6 +1675,27 @@ xrdp_wm_log_msg(struct xrdp_wm* self, char* msg)
     /* set notify function */
     self->log_wnd->notify = xrdp_wm_log_wnd_notify;
   }
+  else if (self->log_edit->caption1)
+  {
+    char buf[8192];
+    int  pos;
+    int  len;
+    int  index;
+
+    msg = (char *)list_get_item(self->log, 0);
+    len = g_strlen(msg);
+    g_sprintf(buf, "%s", msg);
+    pos = len;
+    for (index = 1; index < self->log->count; index++)
+    {
+      msg = (char *)list_get_item(self->log, index);
+      len = g_strlen(msg) + 1;
+      if (pos + len + 1 < sizeof(buf))
+	g_sprintf(buf + pos, "\n%s", msg);
+      pos += len;
+    }
+    set_string(&self->log_edit->caption1, buf);
+  }
   xrdp_wm_set_focused(self, self->log_wnd);
   xrdp_bitmap_invalidate(self->log_wnd, 0);
   g_sleep(100);
@@ -1545,15 +1778,18 @@ xrdp_wm_check_wait_objs(struct xrdp_wm* self)
   if (g_is_wait_obj_set(self->login_mode_event))
   {
     g_reset_wait_obj(self->login_mode_event);
-    xrdp_wm_login_mode_changed(self);
+    rv = xrdp_wm_login_mode_changed(self);
   }
-  if (self->mm != 0)
+  if (rv == 0)
   {
-    if (self->mm->sck_obj != 0)
+    if (self->mm != 0)
     {
-      if (g_is_wait_obj_set(self->mm->sck_obj))
+      if (self->mm->sck_obj != 0)
       {
-        rv = xrdp_mm_signal(self->mm); 
+        if (g_is_wait_obj_set(self->mm->sck_obj))
+        {
+          rv = xrdp_mm_signal(self->mm); 
+        }
       }
     }
   }
