summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am7
-rw-r--r--common/arch.h2
-rw-r--r--common/log.c24
-rw-r--r--common/os_calls.c183
-rw-r--r--common/os_calls.h9
-rw-r--r--common/parse.h32
-rw-r--r--common/trans.c163
-rw-r--r--common/trans.h7
-rw-r--r--common/xrdp_client_info.h17
-rw-r--r--common/xrdp_constants.h38
-rw-r--r--configure.ac22
-rw-r--r--docs/man/sesman.ini.56
-rw-r--r--freerdp/Makefile.am20
-rw-r--r--freerdp/xrdp-color.c314
-rw-r--r--freerdp/xrdp-freerdp.c1049
-rw-r--r--freerdp/xrdp-freerdp.h105
-rw-r--r--freerdp1/Makefile.am28
-rw-r--r--freerdp1/xrdp-color.c313
-rw-r--r--freerdp1/xrdp-color.h29
-rw-r--r--freerdp1/xrdp-freerdp.c1858
-rw-r--r--freerdp1/xrdp-freerdp.h180
-rw-r--r--libxrdp/Makefile.am11
-rw-r--r--libxrdp/libxrdp.c19
-rw-r--r--libxrdp/libxrdp.h44
-rw-r--r--libxrdp/libxrdpinc.h20
-rw-r--r--libxrdp/xrdp_iso.c237
-rw-r--r--libxrdp/xrdp_jpeg_compress.c139
-rw-r--r--libxrdp/xrdp_mcs.c124
-rw-r--r--libxrdp/xrdp_mppc_enc.c29
-rw-r--r--libxrdp/xrdp_orders.c471
-rw-r--r--libxrdp/xrdp_orders_rail.c35
-rw-r--r--libxrdp/xrdp_rdp.c305
-rw-r--r--libxrdp/xrdp_sec.c241
-rw-r--r--sesman/auth.h10
-rw-r--r--sesman/chansrv/Makefile.am8
-rw-r--r--sesman/chansrv/chansrv.c270
-rw-r--r--sesman/chansrv/chansrv.h9
-rw-r--r--sesman/chansrv/chansrv_fuse.c218
-rw-r--r--sesman/chansrv/clipboard.c65
-rw-r--r--sesman/chansrv/devredir.c23
-rw-r--r--sesman/chansrv/fifo.c255
-rw-r--r--sesman/chansrv/fifo.h (renamed from freerdp/xrdp-color.h)25
-rw-r--r--sesman/chansrv/irp.h1
-rw-r--r--sesman/chansrv/mlog.h112
-rw-r--r--sesman/chansrv/pcsc/Makefile12
-rw-r--r--sesman/chansrv/pcsc/xrdp_pcsc.c1157
-rw-r--r--sesman/chansrv/rail.c1354
-rw-r--r--sesman/chansrv/rail.h2
-rw-r--r--sesman/chansrv/smartcard.c2333
-rw-r--r--sesman/chansrv/smartcard.h138
-rw-r--r--sesman/chansrv/smartcard_pcsc.c1126
-rw-r--r--sesman/chansrv/smartcard_pcsc.h69
-rw-r--r--sesman/chansrv/sound.c3
-rw-r--r--sesman/chansrv/xcommon.c10
-rw-r--r--sesman/config.c10
-rw-r--r--sesman/sesman.ini5
-rw-r--r--sesman/session.c154
-rw-r--r--sesman/verify_user_kerberos.c8
-rw-r--r--sesman/verify_user_pam.c20
-rw-r--r--sesman/verify_user_pam_userpass.c8
-rw-r--r--tcutils/README.txt29
-rw-r--r--tcutils/main.cpp11
-rw-r--r--tcutils/mainwindow.cpp234
-rw-r--r--tcutils/mainwindow.h57
-rw-r--r--tcutils/mainwindow.ui100
-rw-r--r--tcutils/moc_mainwindow.cpp104
-rw-r--r--tcutils/qrc_resources.cpp1191
-rw-r--r--tcutils/resources.qrc5
-rw-r--r--tcutils/resources/images/tools.gifbin0 -> 17765 bytes
-rwxr-xr-xtcutils/tcutilsbin0 -> 63109 bytes
-rw-r--r--tcutils/tcutils.pro30
-rw-r--r--tcutils/tcutils.pro.user365
-rw-r--r--tcutils/ui_mainwindow.h105
-rw-r--r--tcutils/utils.cpp217
-rw-r--r--tcutils/utils.h150
-rw-r--r--tests/memtest/libmem.c10
-rw-r--r--tests/memtest/libmem.h2
-rwxr-xr-xxorg/X11R7.6/cleanx.sh102
-rw-r--r--xorg/X11R7.6/rdp/Makefile4
-rw-r--r--xorg/X11R7.6/rdp/rdp.h104
-rw-r--r--xorg/X11R7.6/rdp/rdpComposite.c846
-rw-r--r--xorg/X11R7.6/rdp/rdpCopyArea.c20
-rw-r--r--xorg/X11R7.6/rdp/rdpCopyPlane.c8
-rw-r--r--xorg/X11R7.6/rdp/rdpFillPolygon.c8
-rw-r--r--xorg/X11R7.6/rdp/rdpImageGlyphBlt.c8
-rw-r--r--xorg/X11R7.6/rdp/rdpImageText16.c8
-rw-r--r--xorg/X11R7.6/rdp/rdpImageText8.c8
-rw-r--r--xorg/X11R7.6/rdp/rdpPolyArc.c8
-rw-r--r--xorg/X11R7.6/rdp/rdpPolyFillArc.c8
-rw-r--r--xorg/X11R7.6/rdp/rdpPolyFillRect.c33
-rw-r--r--xorg/X11R7.6/rdp/rdpPolyGlyphBlt.c8
-rw-r--r--xorg/X11R7.6/rdp/rdpPolyPoint.c4
-rw-r--r--xorg/X11R7.6/rdp/rdpPolyRectangle.c8
-rw-r--r--xorg/X11R7.6/rdp/rdpPolySegment.c4
-rw-r--r--xorg/X11R7.6/rdp/rdpPolyText16.c8
-rw-r--r--xorg/X11R7.6/rdp/rdpPolyText8.c8
-rw-r--r--xorg/X11R7.6/rdp/rdpPolylines.c4
-rw-r--r--xorg/X11R7.6/rdp/rdpPushPixels.c8
-rw-r--r--xorg/X11R7.6/rdp/rdpPutImage.c10
-rw-r--r--xorg/X11R7.6/rdp/rdpSetSpans.c18
-rw-r--r--xorg/X11R7.6/rdp/rdpdraw.c549
-rw-r--r--xorg/X11R7.6/rdp/rdpglyph.c862
-rw-r--r--xorg/X11R7.6/rdp/rdpglyph.h64
-rw-r--r--xorg/X11R7.6/rdp/rdpinput.c152
-rw-r--r--xorg/X11R7.6/rdp/rdpmain.c14
-rw-r--r--xorg/X11R7.6/rdp/rdpmisc.c69
-rw-r--r--xorg/X11R7.6/rdp/rdprandr.c7
-rw-r--r--xorg/X11R7.6/rdp/rdpup.c957
-rw-r--r--xrdp/Makefile.am15
-rw-r--r--xrdp/xrdp.c2
-rw-r--r--xrdp/xrdp.h35
-rw-r--r--xrdp/xrdp.ini8
-rw-r--r--xrdp/xrdp_bitmap.c57
-rw-r--r--xrdp/xrdp_cache.c63
-rw-r--r--xrdp/xrdp_listen.c71
-rw-r--r--xrdp/xrdp_mm.c392
-rw-r--r--xrdp/xrdp_painter.c82
-rw-r--r--xrdp/xrdp_process.c3
-rw-r--r--xrdp/xrdp_types.h32
-rw-r--r--xrdp/xrdp_wm.c67
-rw-r--r--xrdpvr/xrdpvr.c118
-rw-r--r--xrdpvr/xrdpvr_internal.h2
-rw-r--r--xup/xup.c260
-rw-r--r--xup/xup.h20
124 files changed, 16057 insertions, 5185 deletions
diff --git a/Makefile.am b/Makefile.am
index 26dcb8aa..e8905c98 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,11 +1,5 @@
EXTRA_DIST = bootstrap COPYING design.txt faq-compile.txt faq-general.txt file-loc.txt install.txt prog_std.txt readme.txt
-if XRDP_FREERDP1
-FREERDPDIR = freerdp1
-else
-FREERDPDIR =
-endif
-
if XRDP_NEUTRINORDP
NEUTRINORDPDIR = neutrinordp
else
@@ -24,7 +18,6 @@ SUBDIRS = \
rdp \
xup \
mc \
- $(FREERDPDIR) \
$(NEUTRINORDPDIR) \
libxrdp \
xrdp \
diff --git a/common/arch.h b/common/arch.h
index b8780926..6a29b0a9 100644
--- a/common/arch.h
+++ b/common/arch.h
@@ -1,7 +1,7 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
- * Copyright (C) Jay Sorg 2004-2012
+ * Copyright (C) Jay Sorg 2004-2013
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/common/log.c b/common/log.c
index ce0000aa..55353a8f 100644
--- a/common/log.c
+++ b/common/log.c
@@ -363,7 +363,7 @@ internal_config_read_logging(int file, struct log_config *lc,
if (0 == g_strcasecmp(buf, SESMAN_CFG_LOG_ENABLE_SYSLOG))
{
- lc->enable_syslog = text2bool((char *)list_get_item(param_v, i));
+ lc->enable_syslog = g_text2bool((char *)list_get_item(param_v, i));
}
if (0 == g_strcasecmp(buf, SESMAN_CFG_LOG_SYSLOG_LEVEL))
@@ -413,28 +413,6 @@ internalInitAndAllocStruct(void)
* Here below the public functions
*/
-
-/**
- *
- * @brief Reads sesman configuration
- * @param s translates the strings "1", "true" and "yes" in 1 (true) and other strings in 0
- * @return 0 on false, 1 on 1,true, yes
- *
- */
-int APP_CC
-text2bool(char *s)
-{
- if ( (g_atoi(s) != 0) ||
- (0 == g_strcasecmp(s, "true")) ||
- (0 == g_strcasecmp(s, "on")) ||
- (0 == g_strcasecmp(s, "yes")))
- {
- return 1;
- }
-
- return 0;
-}
-
enum logReturns DEFAULT_CC
log_start_from_param(const struct log_config *iniParams)
{
diff --git a/common/os_calls.c b/common/os_calls.c
index f5f5cd60..2d5b4280 100644
--- a/common/os_calls.c
+++ b/common/os_calls.c
@@ -493,6 +493,96 @@ g_tcp_socket(void)
}
/*****************************************************************************/
+/* returns error */
+int APP_CC
+g_sck_set_send_buffer_bytes(int sck, int bytes)
+{
+ int option_value;
+#if defined(_WIN32)
+ int option_len;
+#else
+ unsigned int option_len;
+#endif
+
+ option_value = bytes;
+ option_len = sizeof(option_value);
+ if (setsockopt(sck, SOL_SOCKET, SO_SNDBUF, (char *)&option_value,
+ option_len) != 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+g_sck_get_send_buffer_bytes(int sck, int *bytes)
+{
+ int option_value;
+#if defined(_WIN32)
+ int option_len;
+#else
+ unsigned int option_len;
+#endif
+
+ option_value = 0;
+ option_len = sizeof(option_value);
+ if (getsockopt(sck, SOL_SOCKET, SO_SNDBUF, (char *)&option_value,
+ &option_len) != 0)
+ {
+ return 1;
+ }
+ *bytes = option_value;
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+g_sck_set_recv_buffer_bytes(int sck, int bytes)
+{
+ int option_value;
+#if defined(_WIN32)
+ int option_len;
+#else
+ unsigned int option_len;
+#endif
+
+ option_value = bytes;
+ option_len = sizeof(option_value);
+ if (setsockopt(sck, SOL_SOCKET, SO_RCVBUF, (char *)&option_value,
+ option_len) != 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+g_sck_get_recv_buffer_bytes(int sck, int *bytes)
+{
+ int option_value;
+#if defined(_WIN32)
+ int option_len;
+#else
+ unsigned int option_len;
+#endif
+
+ option_value = 0;
+ option_len = sizeof(option_value);
+ if (getsockopt(sck, SOL_SOCKET, SO_RCVBUF, (char *)&option_value,
+ &option_len) != 0)
+ {
+ return 1;
+ }
+ *bytes = option_value;
+ return 0;
+}
+
+/*****************************************************************************/
int APP_CC
g_tcp_local_socket(void)
{
@@ -504,6 +594,38 @@ g_tcp_local_socket(void)
}
/*****************************************************************************/
+int APP_CC
+g_sck_get_peer_cred(int sck, int *pid, int *uid, int *gid)
+{
+ int ucred_length;
+ struct myucred
+ {
+ pid_t pid;
+ uid_t uid;
+ gid_t gid;
+ } credentials;
+
+ ucred_length = sizeof(credentials);
+ if (getsockopt(sck, SOL_SOCKET, SO_PEERCRED, &credentials, &ucred_length))
+ {
+ return 1;
+ }
+ if (pid != 0)
+ {
+ *pid = credentials.pid;
+ }
+ if (uid != 0)
+ {
+ *uid = credentials.uid;
+ }
+ if (gid != 0)
+ {
+ *gid = credentials.gid;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
void APP_CC
g_tcp_close(int sck)
{
@@ -848,6 +970,41 @@ g_tcp_accept(int sck)
}
/*****************************************************************************/
+int APP_CC
+g_sck_accept(int sck, char *addr, int addr_bytes, char *port, int port_bytes)
+{
+ int ret;
+ char ipAddr[256];
+ struct sockaddr_in s;
+#if defined(_WIN32)
+ signed int i;
+#else
+ unsigned int i;
+#endif
+
+ i = sizeof(struct sockaddr_in);
+ memset(&s, 0, i);
+ ret = accept(sck, (struct sockaddr *)&s, &i);
+ if (ret > 0)
+ {
+ g_snprintf(ipAddr, 255, "A connection received from: %s port %d",
+ inet_ntoa(s.sin_addr), ntohs(s.sin_port));
+ log_message(LOG_LEVEL_INFO,ipAddr);
+ if (s.sin_family == AF_INET)
+ {
+ g_snprintf(addr, addr_bytes, "%s", inet_ntoa(s.sin_addr));
+ g_snprintf(port, port_bytes, "%d", ntohs(s.sin_port));
+ }
+ if (s.sin_family == AF_UNIX)
+ {
+ g_strncpy(addr, "", addr_bytes - 1);
+ g_strncpy(port, "", port_bytes - 1);
+ }
+ }
+ return ret;
+}
+
+/*****************************************************************************/
void APP_CC
g_write_ip_address(int rcv_sck, char *ip_address, int bytes)
{
@@ -2501,6 +2658,17 @@ g_signal_child_stop(void (*func)(int))
}
/*****************************************************************************/
+
+void APP_CC
+g_signal_segfault(void (*func)(int))
+{
+#if defined(_WIN32)
+#else
+ signal(SIGSEGV, func);
+#endif
+}
+
+/*****************************************************************************/
/* does not work in win32 */
void APP_CC
g_signal_hang_up(void (*func)(int))
@@ -2935,3 +3103,18 @@ g_time3(void)
return (tp.tv_sec * 1000) + (tp.tv_usec / 1000);
#endif
}
+
+/*****************************************************************************/
+/* returns boolean */
+int APP_CC
+g_text2bool(const char *s)
+{
+ if ( (g_atoi(s) != 0) ||
+ (0 == g_strcasecmp(s, "true")) ||
+ (0 == g_strcasecmp(s, "on")) ||
+ (0 == g_strcasecmp(s, "yes")))
+ {
+ return 1;
+ }
+ return 0;
+}
diff --git a/common/os_calls.h b/common/os_calls.h
index cba37588..b6e1c91a 100644
--- a/common/os_calls.h
+++ b/common/os_calls.h
@@ -45,7 +45,12 @@ int APP_CC g_getchar(void);
int APP_CC g_tcp_set_no_delay(int sck);
int APP_CC g_tcp_set_keepalive(int sck);
int APP_CC g_tcp_socket(void);
+int APP_CC g_sck_set_send_buffer_bytes(int sck, int bytes);
+int APP_CC g_sck_get_send_buffer_bytes(int sck, int *bytes);
+int APP_CC g_sck_set_recv_buffer_bytes(int sck, int bytes);
+int APP_CC g_sck_get_recv_buffer_bytes(int sck, int *bytes);
int APP_CC g_tcp_local_socket(void);
+int APP_CC g_sck_get_peer_cred(int sck, int *pid, int *uid, int *gid);
void APP_CC g_tcp_close(int sck);
int APP_CC g_tcp_connect(int sck, const char* address, const char* port);
int APP_CC g_tcp_local_connect(int sck, const char* port);
@@ -57,6 +62,8 @@ int APP_CC g_tcp_local_bind(int sck, const char* port);
int APP_CC g_tcp_bind_address(int sck, const char* port, const char* address);
int APP_CC g_tcp_listen(int sck);
int APP_CC g_tcp_accept(int sck);
+int APP_CC g_sck_accept(int sck, char *addr, int addr_bytes,
+ char *port, int port_bytes);
int APP_CC g_tcp_recv(int sck, void* ptr, int len, int flags);
int APP_CC g_tcp_send(int sck, const void* ptr, int len, int flags);
int APP_CC g_tcp_last_error_would_block(int sck);
@@ -125,6 +132,7 @@ int APP_CC g_get_errno(void);
int APP_CC g_execvp(const char* p1, char* args[]);
int APP_CC g_execlp3(const char* a1, const char* a2, const char* a3);
void APP_CC g_signal_child_stop(void (*func)(int));
+void APP_CC g_signal_segfault(void (*func)(int));
void APP_CC g_signal_hang_up(void (*func)(int));
void APP_CC g_signal_user_interrupt(void (*func)(int));
void APP_CC g_signal_kill(void (*func)(int));
@@ -152,5 +160,6 @@ int APP_CC g_check_user_in_group(const char* username, int gid, int* ok);
int APP_CC g_time1(void);
int APP_CC g_time2(void);
int APP_CC g_time3(void);
+int APP_CC g_text2bool(const char *s);
#endif
diff --git a/common/parse.h b/common/parse.h
index f92e76de..69a57ff8 100644
--- a/common/parse.h
+++ b/common/parse.h
@@ -56,6 +56,9 @@ struct stream
#define s_check_rem(s, n) ((s)->p + (n) <= (s)->end)
/******************************************************************************/
+#define s_check_rem_out(s, n) ((s)->p + (n) <= (s)->data + (s)->size)
+
+/******************************************************************************/
#define s_check_end(s) ((s)->p == (s)->end)
/******************************************************************************/
@@ -279,6 +282,35 @@ struct stream
#endif
/******************************************************************************/
+#if defined(B_ENDIAN) || defined(NEED_ALIGN)
+#define out_uint64_le(s, v) do \
+{ \
+ *((s)->p) = (unsigned char)((v) >> 0); \
+ (s)->p++; \
+ *((s)->p) = (unsigned char)((v) >> 8); \
+ (s)->p++; \
+ *((s)->p) = (unsigned char)((v) >> 16); \
+ (s)->p++; \
+ *((s)->p) = (unsigned char)((v) >> 24); \
+ (s)->p++; \
+ *((s)->p) = (unsigned char)((v) >> 32); \
+ (s)->p++; \
+ *((s)->p) = (unsigned char)((v) >> 40); \
+ (s)->p++; \
+ *((s)->p) = (unsigned char)((v) >> 48); \
+ (s)->p++; \
+ *((s)->p) = (unsigned char)((v) >> 56); \
+ (s)->p++; \
+} while (0)
+#else
+#define out_uint64_le(s, v) do \
+{ \
+ *((tui64*)((s)->p)) = (v); \
+ (s)->p += 8; \
+} while (0)
+#endif
+
+/******************************************************************************/
#define out_uint32_be(s, v) do \
{ \
*((s)->p) = (unsigned char)((v) >> 24); \
diff --git a/common/trans.c b/common/trans.c
index e862249e..bb349298 100644
--- a/common/trans.c
+++ b/common/trans.c
@@ -92,6 +92,86 @@ trans_get_wait_objs(struct trans *self, tbus *objs, int *count)
/*****************************************************************************/
int APP_CC
+trans_get_wait_objs_rw(struct trans *self,
+ tbus *robjs, int *rcount,
+ tbus *wobjs, int *wcount)
+{
+ if (self == 0)
+ {
+ return 1;
+ }
+
+ if (self->status != TRANS_STATUS_UP)
+ {
+ return 1;
+ }
+
+ robjs[*rcount] = self->sck;
+ (*rcount)++;
+
+ if (self->wait_s != 0)
+ {
+ wobjs[*wcount] = self->sck;
+ (*wcount)++;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+int APP_CC
+send_waiting(struct trans *self, int block)
+{
+ struct stream *temp_s;
+ int bytes;
+ int sent;
+ int timeout;
+ int cont;
+
+ timeout = block ? 100 : 0;
+ cont = 1;
+ while (cont)
+ {
+ if (self->wait_s != 0)
+ {
+ temp_s = self->wait_s;
+ if (g_tcp_can_send(self->sck, timeout))
+ {
+ bytes = (int) (temp_s->end - temp_s->p);
+ sent = g_tcp_send(self->sck, temp_s->p, bytes, 0);
+ if (sent > 0)
+ {
+ temp_s->p += sent;
+ if (temp_s->p >= temp_s->end)
+ {
+ self->wait_s = (struct stream *) (temp_s->next_packet);
+ free_stream(temp_s);
+ }
+ }
+ else if (sent == 0)
+ {
+ return 1;
+ }
+ else
+ {
+ if (!g_tcp_last_error_would_block(self->sck))
+ {
+ return 1;
+ }
+ }
+ }
+ }
+ else
+ {
+ break;
+ }
+ cont = block;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+int APP_CC
trans_check_wait_objs(struct trans *self)
{
tbus in_sck = (tbus)0;
@@ -117,7 +197,8 @@ trans_check_wait_objs(struct trans *self)
{
if (g_tcp_can_recv(self->sck, 0))
{
- in_sck = g_tcp_accept(self->sck);
+ in_sck = g_sck_accept(self->sck, self->addr, sizeof(self->addr),
+ self->port, sizeof(self->port));
if (in_sck == -1)
{
@@ -142,6 +223,9 @@ trans_check_wait_objs(struct trans *self)
in_trans->sck = in_sck;
in_trans->type1 = TRANS_TYPE_SERVER;
in_trans->status = TRANS_STATUS_UP;
+ in_trans->is_term = self->is_term;
+ g_strncpy(in_trans->addr, self->addr, sizeof(self->addr) - 1);
+ g_strncpy(in_trans->port, self->port, sizeof(self->port) - 1);
if (self->trans_conn_in(self, in_trans) != 0)
{
@@ -202,6 +286,12 @@ trans_check_wait_objs(struct trans *self)
}
}
}
+ if (send_waiting(self, 0) != 0)
+ {
+ /* error */
+ self->status = TRANS_STATUS_DOWN;
+ return 1;
+ }
}
return rv;
@@ -220,15 +310,28 @@ trans_force_read_s(struct trans *self, struct stream *in_s, int size)
while (size > 0)
{
+ /* make sure stream has room */
+ if ((in_s->end + size) > (in_s->data + in_s->size))
+ {
+ return 1;
+ }
rcvd = g_tcp_recv(self->sck, in_s->end, size, 0);
-
if (rcvd == -1)
{
if (g_tcp_last_error_would_block(self->sck))
{
- if (!g_tcp_can_recv(self->sck, 10))
+ if (!g_tcp_can_recv(self->sck, 100))
{
/* check for term here */
+ if (self->is_term != 0)
+ {
+ if (self->is_term())
+ {
+ /* term */
+ self->status = TRANS_STATUS_DOWN;
+ return 1;
+ }
+ }
}
}
else
@@ -277,6 +380,12 @@ trans_force_write_s(struct trans *self, struct stream *out_s)
size = (int)(out_s->end - out_s->data);
total = 0;
+ if (send_waiting(self, 1) != 0)
+ {
+ self->status = TRANS_STATUS_DOWN;
+ return 1;
+ }
+
while (total < size)
{
sent = g_tcp_send(self->sck, out_s->data + total, size - total, 0);
@@ -285,9 +394,18 @@ trans_force_write_s(struct trans *self, struct stream *out_s)
{
if (g_tcp_last_error_would_block(self->sck))
{
- if (!g_tcp_can_send(self->sck, 10))
+ if (!g_tcp_can_send(self->sck, 100))
{
/* check for term here */
+ if (self->is_term != 0)
+ {
+ if (self->is_term())
+ {
+ /* term */
+ self->status = TRANS_STATUS_DOWN;
+ return 1;
+ }
+ }
}
}
else
@@ -321,6 +439,43 @@ trans_force_write(struct trans *self)
/*****************************************************************************/
int APP_CC
+trans_write_copy(struct trans *self)
+{
+ int size;
+ struct stream *out_s;
+ struct stream *wait_s;
+ struct stream *temp_s;
+
+ if (self->status != TRANS_STATUS_UP)
+ {
+ return 1;
+ }
+
+ out_s = self->out_s;
+ size = (int)(out_s->end - out_s->data);
+ make_stream(wait_s);
+ init_stream(wait_s, size);
+ out_uint8a(wait_s, out_s->data, size);
+ s_mark_end(wait_s);
+ wait_s->p = wait_s->data;
+ if (self->wait_s == 0)
+ {
+ self->wait_s = wait_s;
+ }
+ else
+ {
+ temp_s = self->wait_s;
+ while (temp_s->next_packet != 0)
+ {
+ temp_s = (struct stream *) (temp_s->next_packet);
+ }
+ temp_s->next_packet = (char *) wait_s;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+int APP_CC
trans_connect(struct trans *self, const char *server, const char *port,
int timeout)
{
diff --git a/common/trans.h b/common/trans.h
index 8daa980a..350f05cc 100644
--- a/common/trans.h
+++ b/common/trans.h
@@ -38,6 +38,7 @@ struct trans; /* forward declaration */
typedef int (*ttrans_data_in)(struct trans* self);
typedef int (*ttrans_conn_in)(struct trans* self, struct trans* new_self);
+typedef int (*tis_term)(void);
struct trans
{
@@ -52,6 +53,10 @@ struct trans
struct stream* in_s;
struct stream* out_s;
char* listen_filename;
+ tis_term is_term; /* used to test for exit */
+ struct stream* wait_s;
+ char addr[256];
+ char port[256];
};
struct trans* APP_CC
@@ -71,6 +76,8 @@ trans_force_read(struct trans* self, int size);
int APP_CC
trans_force_write(struct trans* self);
int APP_CC
+trans_write_copy(struct trans* self);
+int APP_CC
trans_connect(struct trans* self, const char* server, const char* port,
int timeout);
int APP_CC
diff --git a/common/xrdp_client_info.h b/common/xrdp_client_info.h
index 43ff3f82..acd145e6 100644
--- a/common/xrdp_client_info.h
+++ b/common/xrdp_client_info.h
@@ -21,6 +21,15 @@
#if !defined(XRDP_CLIENT_INFO_H)
#define XRDP_CLIENT_INFO_H
+struct monitor_info
+{
+ int left;
+ int top;
+ int right;
+ int bottom;
+ int is_primary;
+};
+
struct xrdp_client_info
{
int size; /* bytes for this structure */
@@ -69,6 +78,7 @@ struct xrdp_client_info
int offscreen_cache_size;
int offscreen_cache_entries;
int rfx;
+
/* CAPSETTYPE_RAIL */
int rail_support_level;
/* CAPSETTYPE_WINDOW */
@@ -93,6 +103,13 @@ struct xrdp_client_info
int pointer_flags; /* 0 color, 1 new, 2 no new */
int use_fast_path;
int require_credentials; /* when true, credentials *must* be passed on cmd line */
+ char client_addr[256];
+ char client_port[256];
+
+ int nego_sec_layer; /* 0, 1, 2 = RDP security layer, TLS , Negotiate */
+ int multimon; /* 0 = deny , 1 = allow */
+ int monitorCount; /* number of monitors detected (max = 16) */
+ struct monitor_info minfo[16]; /* client monitor data */
};
#endif
diff --git a/common/xrdp_constants.h b/common/xrdp_constants.h
index b978d2de..ed74fd01 100644
--- a/common/xrdp_constants.h
+++ b/common/xrdp_constants.h
@@ -25,12 +25,36 @@
/* TCP port for Remote Desktop Protocol */
#define TCP_PORT_RDP 3389
-#define ISO_PDU_CR 0xE0 /* Connection Request */
-#define ISO_PDU_CC 0xD0 /* Connection Confirm */
+#define ISO_PDU_CR 0xE0 /* X.224 Connection Request */
+#define ISO_PDU_CC 0xD0 /* X.224 Connection Confirm */
#define ISO_PDU_DR 0x80 /* Disconnect Request */
#define ISO_PDU_DT 0xF0 /* Data */
#define ISO_PDU_ER 0x70 /* Error */
+
+/* RDP Security Negotiation codes */
+#define RDP_NEG_REQ 0x01
+#define RDP_NEG_RSP 0x02
+#define RDP_NEG_FAILURE 0x03
+#define RDP_CORRELATION_INFO 0x06
+/* Protocol types codes */
+#define PROTOCOL_RDP 0x0
+#define PROTOCOL_SSL 0x1
+#define PROTOCOL_HYBRID 0x2
+#define PROTOCOL_HYBRID_EX 0x8
+/* Negotiation packet flags */
+#define EXTENDED_CLIENT_DATA_SUPPORTED 0x1
+#define DYNVC_GFX_PROTOCOL_SUPPORTED 0x2
+#define RDP_NEGRSP_RESERVED 0x4
+/* Failure Codes */
+#define SSL_REQUIRED_BY_SERVER 0x1
+#define SSL_NOT_ALLOWED_BY_SERVER 0x2
+#define SSL_CERT_NOT_ON_SERVER 0x3
+#define INCONSISTENT_FLAGS 0x4
+#define HYBRID_REQUIRED_BY_SERVER 0x5
+#define SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER 0x6
+
+
/* MCS PDU codes */
#define MCS_EDRQ 1 /* Erect Domain Request */
#define MCS_DPUM 8 /* Disconnect Provider Ultimatum */
@@ -72,6 +96,7 @@
#define SEC_TAG_CLI_CRYPT 0xc002
#define SEC_TAG_CLI_CHANNELS 0xc003
#define SEC_TAG_CLI_4 0xc004
+#define SEC_TAG_CLI_MONITOR 0xc005
#define SEC_TAG_PUBKEY 0x0006
#define SEC_TAG_KEYSIG 0x0008
@@ -416,6 +441,7 @@
#define RDP_ORDER_TRIBLT 14
#define RDP_ORDER_POLYLINE 22
#define RDP_ORDER_TEXT2 27
+#define RDP_ORDER_COMPOSITE 37 /* 0x25 */
#define RDP_ORDER_RAW_BMPCACHE 0
#define RDP_ORDER_COLCACHE 1
@@ -463,6 +489,10 @@
#define WM_BUTTON4DOWN 108
#define WM_BUTTON5UP 109
#define WM_BUTTON5DOWN 110
+#define WM_BUTTON6UP 111
+#define WM_BUTTON6DOWN 112
+#define WM_BUTTON7UP 113
+#define WM_BUTTON7DOWN 114
#define WM_INVALIDATE 200
#define CB_ITEMCHANGE 300
@@ -559,4 +589,8 @@
#define CMDTYPE_FRAME_MARKER 0x0004
#define CMDTYPE_STREAM_SURFACE_BITS 0x0006
+#define XRDP_MAX_BITMAP_CACHE_ID 3
+#define XRDP_MAX_BITMAP_CACHE_IDX 2000
+#define XRDP_BITMAP_CACHE_ENTRIES 2048
+
#endif
diff --git a/configure.ac b/configure.ac
index a2a80aa2..6c0134e6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
# Process this file with autoconf to produce a configure script
AC_PREREQ(2.59)
-AC_INIT([xrdp], [0.6.0], [xrdp-devel@lists.sourceforge.net])
+AC_INIT([xrdp], [0.7.0], [xrdp-devel@lists.sourceforge.net])
AC_CONFIG_HEADERS(config_ac.h:config_ac-h.in)
AM_INIT_AUTOMAKE([1.6 foreign])
AC_PROG_CC
@@ -31,10 +31,6 @@ AC_ARG_ENABLE(xrdpdebug, AS_HELP_STRING([--enable-xrdpdebug],
[Build debug (default: no)]),
[xrdpdebug=true], [xrdpdebug=false])
AM_CONDITIONAL(XRDP_DEBUG, [test x$xrdpdebug = xtrue])
-AC_ARG_ENABLE(freerdp1, AS_HELP_STRING([--enable-freerdp1],
- [Build freerdp1 module (default: no)]),
- [freerdp1=true], [freerdp1=false])
-AM_CONDITIONAL(XRDP_FREERDP1, [test x$freerdp1 = xtrue])
AC_ARG_ENABLE(neutrinordp, AS_HELP_STRING([--enable-neutrinordp],
[Build neutrinordp module (default: no)]),
[neutrinordp=true], [neutrinordp=false])
@@ -43,6 +39,10 @@ AC_ARG_ENABLE(jpeg, AS_HELP_STRING([--enable-jpeg],
[Build jpeg module (default: no)]),
[jpeg=true], [jpeg=false])
AM_CONDITIONAL(XRDP_JPEG, [test x$jpeg = xtrue])
+AC_ARG_ENABLE(tjpeg, AS_HELP_STRING([--enable-tjpeg],
+ [Build turbo jpeg module(assumes /opt/libjpeg-turbo) (default: no)]),
+ [tjpeg=true], [tjpeg=false])
+AM_CONDITIONAL(XRDP_TJPEG, [test x$tjpeg = xtrue])
AC_ARG_ENABLE(simplesound, AS_HELP_STRING([--enable-simplesound],
[Build simple pulse audio interface (default: no)]),
[simplesound=true], [simplesound=false])
@@ -83,8 +83,6 @@ then
AC_DEFINE([USE_NOPAM],1,[Disable PAM])
fi
-AS_IF( [test "x$enable_freerdp1" = "xyes"] , [PKG_CHECK_MODULES(FREERDP, freerdp >= 1.0.0)] )
-
AS_IF( [test "x$enable_neutrinordp" = "xyes"] , [PKG_CHECK_MODULES(FREERDP, freerdp >= 1.0.0)] )
# checking for libjpeg
@@ -94,6 +92,11 @@ then
[AC_MSG_ERROR([please install libjpeg-dev or libjpeg-devel])])
fi
+if ! test -z "$enable_xrdpdebug"
+then
+ CFLAGS="-g -O0"
+fi
+
# checking for fuse
if ! test -z "$enable_fuse"
then
@@ -128,7 +131,6 @@ AC_CONFIG_FILES([Makefile
libxrdp/Makefile
xup/Makefile
mc/Makefile
- freerdp1/Makefile
neutrinordp/Makefile
xrdp/Makefile
sesman/Makefile
@@ -141,8 +143,8 @@ AC_CONFIG_FILES([Makefile
docs/man/Makefile
instfiles/Makefile
instfiles/pam.d/Makefile
- instfiles/init.d/Makefile
- instfiles/default/Makefile
+ instfiles/init.d/Makefile
+ instfiles/default/Makefile
genkeymap/Makefile
xrdpapi/Makefile
xrdpvr/Makefile
diff --git a/docs/man/sesman.ini.5 b/docs/man/sesman.ini.5
index 2bf69297..84beafb4 100644
--- a/docs/man/sesman.ini.5
+++ b/docs/man/sesman.ini.5
@@ -98,9 +98,8 @@ If unset or set to \fI0\fR, unlimited session are allowed.
.TP
\fBKillDisconnected\fR=\fI[0|1]\fR
-If set to \fB1\fR, \fBtrue\fR or \fByes\fR, every session will be killed when the user disconnects.
+If set to \fB1\fR, \fBtrue\fR or \fByes\fR, every session will be killed within 60 seconds when the user disconnects.
.br
-\fI\-this option is currently ignored!\-\fR
.TP
\fBIdleTimeLimit\fR=\fI<number>\fR
@@ -112,11 +111,10 @@ If set to \fI0\fR, automatic disconnection is disabled.
.TP
\fBDisconnectedTimeLimit\fR=\fI<number>\fR
-Sets the the time limit before a disconnected session is killed.
+Sets the time(in seconds) limit before a disconnected session is killed.
.br
If set to \fI0\fR, automatic killing is disabled.
.br
-\fI\-this option is currently ignored!\-\fR
.SH "SECURITY"
The following parameters can be used in the \fB[Sessions]\fR section:
diff --git a/freerdp/Makefile.am b/freerdp/Makefile.am
deleted file mode 100644
index 21f78741..00000000
--- a/freerdp/Makefile.am
+++ /dev/null
@@ -1,20 +0,0 @@
-EXTRA_DIST = xrdp-freerdp.h
-
-AM_CFLAGS = \
- -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \
- -DXRDP_SBIN_PATH=\"${sbindir}\" \
- -DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \
- -DXRDP_PID_PATH=\"${localstatedir}/run\"
-
-INCLUDES = \
- -I$(top_srcdir)/common \
- $(FREERDP_CFLAGS)
-
-lib_LTLIBRARIES = \
- libxrdpfreerdp.la
-
-libxrdpfreerdp_la_SOURCES = xrdp-freerdp.c xrdp-color.c
-
-libxrdpfreerdp_la_LIBADD = \
- $(top_builddir)/common/libcommon.la \
- $(FREERDP_LIBS)
diff --git a/freerdp/xrdp-color.c b/freerdp/xrdp-color.c
deleted file mode 100644
index 0ecf4dbf..00000000
--- a/freerdp/xrdp-color.c
+++ /dev/null
@@ -1,314 +0,0 @@
-/**
- * xrdp: A Remote Desktop Protocol server.
- *
- * Copyright (C) Jay Sorg 2004-2012
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * freerdp wrapper
- */
-
-#include "xrdp-freerdp.h"
-
-char *APP_CC
-convert_bitmap(int in_bpp, int out_bpp, char *bmpdata,
- int width, int height, int *palette)
-{
- char *out;
- char *src;
- char *dst;
- int i;
- int j;
- int red;
- int green;
- int blue;
- int pixel;
-
- if ((in_bpp == 8) && (out_bpp == 8))
- {
- out = (char *)g_malloc(width * height, 0);
- src = bmpdata;
- dst = out;
-
- for (i = 0; i < height; i++)
- {
- for (j = 0; j < width; j++)
- {
- pixel = *((tui8 *)src);
- pixel = palette[pixel];
- SPLITCOLOR32(red, green, blue, pixel);
- pixel = COLOR8(red, green, blue);
- *dst = pixel;
- src++;
- dst++;
- }
- }
-
- return out;
- }
-
- if ((in_bpp == 8) && (out_bpp == 16))
- {
- out = (char *)g_malloc(width * height * 2, 0);
- src = bmpdata;
- dst = out;
-
- for (i = 0; i < height; i++)
- {
- for (j = 0; j < width; j++)
- {
- pixel = *((tui8 *)src);
- pixel = palette[pixel];
- SPLITCOLOR32(red, green, blue, pixel);
- pixel = COLOR16(red, green, blue);
- *((tui16 *)dst) = pixel;
- src++;
- dst += 2;
- }
- }
-
- return out;
- }
-
- if ((in_bpp == 8) && (out_bpp == 24))
- {
- out = (char *)g_malloc(width * height * 4, 0);
- src = bmpdata;
- dst = out;
-
- for (i = 0; i < height; i++)
- {
- for (j = 0; j < width; j++)
- {
- pixel = *((tui8 *)src);
- pixel = palette[pixel];
- SPLITCOLOR32(red, green, blue, pixel);
- pixel = COLOR24RGB(red, green, blue);
- *((tui32 *)dst) = pixel;
- src++;
- dst += 4;
- }
- }
-
- return out;
- }
-
- if ((in_bpp == 15) && (out_bpp == 16))
- {
- out = (char *)g_malloc(width * height * 2, 0);
- src = bmpdata;
- dst = out;
-
- for (i = 0; i < height; i++)
- {
- for (j = 0; j < width; j++)
- {
- pixel = *((tui16 *)src);
- SPLITCOLOR15(red, green, blue, pixel);
- pixel = COLOR16(red, green, blue);
- *((tui16 *)dst) = pixel;
- src += 2;
- dst += 2;
- }
- }
-
- return out;
- }
-
- if ((in_bpp == 15) && (out_bpp == 24))
- {
- out = (char *)g_malloc(width * height * 4, 0);
- src = bmpdata;
- dst = out;
-
- for (i = 0; i < height; i++)
- {
- for (j = 0; j < width; j++)
- {
- pixel = *((tui16 *)src);
- SPLITCOLOR15(red, green, blue, pixel);
- pixel = COLOR24RGB(red, green, blue);
- *((tui32 *)dst) = pixel;
- src += 2;
- dst += 4;
- }
- }
-
- return out;
- }
-
- if ((in_bpp == 16) && (out_bpp == 16))
- {
- return bmpdata;
- }
-
- if ((in_bpp == 16) && (out_bpp == 24))
- {
- out = (char *)g_malloc(width * height * 4, 0);
- src = bmpdata;
- dst = out;
-
- for (i = 0; i < height; i++)
- {
- for (j = 0; j < width; j++)
- {
- pixel = *((tui16 *)src);
- SPLITCOLOR16(red, green, blue, pixel);
- pixel = COLOR24RGB(red, green, blue);
- *((tui32 *)dst) = pixel;
- src += 2;
- dst += 4;
- }
- }
-
- return out;
- }
-
- if ((in_bpp == 24) && (out_bpp == 24))
- {
- out = (char *)g_malloc(width * height * 4, 0);
- src = bmpdata;
- dst = out;
-
- for (i = 0; i < height; i++)
- {
- for (j = 0; j < width; j++)
- {
- blue = *((tui8 *)src);
- src++;
- green = *((tui8 *)src);
- src++;
- red = *((tui8 *)src);
- src++;
- pixel = COLOR24RGB(red, green, blue);
- *((tui32 *)dst) = pixel;
- dst += 4;
- }
- }
-
- return out;
- }
-
- if ((in_bpp == 32) && (out_bpp == 24))
- {
- return bmpdata;
- }
-
- if ((in_bpp == 32) && (out_bpp == 32))
- {
- return bmpdata;
- }
-
- if ((in_bpp == 15) && (out_bpp == 15))
- {
- return bmpdata;
- }
-
- g_writeln("convert_bitmap: error unknown conversion from %d to %d",
- in_bpp, out_bpp);
- return 0;
-}
-
-/*****************************************************************************/
-/* returns color or 0 */
-int APP_CC
-convert_color(int in_bpp, int out_bpp, int in_color, int *palette)
-{
- int pixel;
- int red;
- int green;
- int blue;
-
- if ((in_bpp == 1) && (out_bpp == 24))
- {
- pixel = in_color == 0 ? 0 : 0xffffff;
- return pixel;
- }
-
- if ((in_bpp == 8) && (out_bpp == 8))
- {
- pixel = palette[in_color];
- SPLITCOLOR32(red, green, blue, pixel);
- pixel = COLOR8(red, green, blue);
- return pixel;
- }
-
- if ((in_bpp == 8) && (out_bpp == 16))
- {
- pixel = palette[in_color];
- SPLITCOLOR32(red, green, blue, pixel);
- pixel = COLOR16(red, green, blue);
- return pixel;
- }
-
- if ((in_bpp == 8) && (out_bpp == 24))
- {
- pixel = palette[in_color];
- SPLITCOLOR32(red, green, blue, pixel);
- pixel = COLOR24BGR(red, green, blue);
- return pixel;
- }
-
- if ((in_bpp == 15) && (out_bpp == 16))
- {
- pixel = in_color;
- SPLITCOLOR15(red, green, blue, pixel);
- pixel = COLOR16(red, green, blue);
- return pixel;
- }
-
- if ((in_bpp == 15) && (out_bpp == 24))
- {
- pixel = in_color;
- SPLITCOLOR15(red, green, blue, pixel);
- pixel = COLOR24BGR(red, green, blue);
- return pixel;
- }
-
- if ((in_bpp == 16) && (out_bpp == 16))
- {
- return in_color;
- }
-
- if ((in_bpp == 16) && (out_bpp == 24))
- {
- pixel = in_color;
- SPLITCOLOR16(red, green, blue, pixel);
- pixel = COLOR24BGR(red, green, blue);
- return pixel;
- }
-
- if ((in_bpp == 24) && (out_bpp == 24))
- {
- return in_color;
- }
-
- if ((in_bpp == 32) && (out_bpp == 24))
- {
- return in_color;
- }
-
- if ((in_bpp == 32) && (out_bpp == 32))
- {
- return in_color;
- }
-
- if ((in_bpp == 15) && (out_bpp == 15))
- {
- return in_color;
- }
-
- g_writeln("convert_color: error unknown conversion from %d to %d",
- in_bpp, out_bpp);
- return 0;
-}
diff --git a/freerdp/xrdp-freerdp.c b/freerdp/xrdp-freerdp.c
deleted file mode 100644
index 5ee58800..00000000
--- a/freerdp/xrdp-freerdp.c
+++ /dev/null
@@ -1,1049 +0,0 @@
-/**
- * xrdp: A Remote Desktop Protocol server.
- *
- * Copyright (C) Jay Sorg 2004-2012
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * freerdp wrapper
- */
-
-#include "xrdp-freerdp.h"
-#include "xrdp-color.h"
-
-#define GET_MOD(_inst) ((struct mod*)((_inst)->param1))
-#define SET_MOD(_inst, _mod) ((_inst)->param1) = _mod
-
-struct my_bitmap
-{
- char *data;
- int width;
- int height;
- int bpp;
-};
-
-struct my_cursor
-{
- char *andmask;
- int andbpp;
- char *xormask;
- int xorbpp;
- int width;
- int height;
- int hotx;
- int hoty;
-};
-
-/*****************************************************************************/
-/* return error */
-static int DEFAULT_CC
-lib_mod_start(struct mod *mod, int w, int h, int bpp)
-{
- LIB_DEBUG(mod, "in lib_mod_start");
- g_writeln("lib_mod_start: w %d h %d bpp %d", w, h, bpp);
- mod->width = w;
- mod->height = h;
- mod->bpp = bpp;
-
- if (bpp == 24)
- {
- mod->settings->server_depth = 32;
- }
- else
- {
- mod->settings->server_depth = mod->bpp;
- }
-
- mod->settings->width = mod->width;
- mod->settings->height = mod->height;
- LIB_DEBUG(mod, "out lib_mod_start");
- return 0;
-}
-
-/******************************************************************************/
-/* return error */
-static int DEFAULT_CC
-lib_mod_connect(struct mod *mod)
-{
- int code;
-
- LIB_DEBUG(mod, "in lib_mod_connect");
- code = mod->inst->rdp_connect(mod->inst);
- g_writeln("lib_mod_connect: code %d", code);
- LIB_DEBUG(mod, "out lib_mod_connect");
- return code;
-}
-
-/******************************************************************************/
-/* return error */
-static int DEFAULT_CC
-lib_mod_event(struct mod *mod, int msg, long param1, long param2,
- long param3, long param4)
-{
- LIB_DEBUG(mod, "in lib_mod_event");
- int ext;
-
- //g_writeln("%d %d %d %d %d", msg, param1, param2, param3, param4);
- switch (msg)
- {
- case 15:
- ext = param4 & 0x100 ? 1 : 0;
- mod->inst->rdp_send_input_scancode(mod->inst, 0, ext, param3);
- break;
- case 16:
- ext = param4 & 0x100 ? 1 : 0;
- mod->inst->rdp_send_input_scancode(mod->inst, 1, ext, param3);
- break;
- case 17:
- mod->inst->rdp_sync_input(mod->inst, param4);
- break;
- case 100:
- mod->inst->rdp_send_input_mouse(mod->inst, PTRFLAGS_MOVE,
- param1, param2);
- break;
- case 101:
- mod->inst->rdp_send_input_mouse(mod->inst, PTRFLAGS_BUTTON1,
- param1, param2);
- break;
- case 102:
- mod->inst->rdp_send_input_mouse(mod->inst,
- PTRFLAGS_BUTTON1 | PTRFLAGS_DOWN,
- param1, param2);
- break;
- case 103:
- mod->inst->rdp_send_input_mouse(mod->inst,
- PTRFLAGS_BUTTON2, param1, param2);
- break;
- case 104:
- mod->inst->rdp_send_input_mouse(mod->inst,
- PTRFLAGS_BUTTON2 | PTRFLAGS_DOWN,
- param1, param2);
- break;
- case 105:
- mod->inst->rdp_send_input_mouse(mod->inst,
- PTRFLAGS_BUTTON3, param1, param2);
- break;
- case 106:
- mod->inst->rdp_send_input_mouse(mod->inst,
- PTRFLAGS_BUTTON3 | PTRFLAGS_DOWN,
- param1, param2);
- break;
- case 107:
- mod->inst->rdp_send_input_mouse(mod->inst,
- PTRFLAGS_WHEEL | 0x0078, 0, 0);
- break;
- case 108:
- break;
- case 109:
- mod->inst->rdp_send_input_mouse(mod->inst,
- PTRFLAGS_WHEEL |
- PTRFLAGS_WHEEL_NEGATIVE | 0x0088, 0, 0);
- break;
- case 110:
- break;
- }
-
- LIB_DEBUG(mod, "out lib_mod_event");
- return 0;
-}
-
-/******************************************************************************/
-/* return error */
-static int DEFAULT_CC
-lib_mod_signal(struct mod *mod)
-{
- LIB_DEBUG(mod, "in lib_mod_signal");
- g_writeln("lib_mod_signal:");
- LIB_DEBUG(mod, "out lib_mod_signal");
- return 0;
-}
-
-/******************************************************************************/
-/* return error */
-static int DEFAULT_CC
-lib_mod_end(struct mod *mod)
-{
- g_writeln("lib_mod_end:");
- return 0;
-}
-
-/******************************************************************************/
-/* return error */
-static int DEFAULT_CC
-lib_mod_set_param(struct mod *mod, char *name, char *value)
-{
- g_writeln("lib_mod_set_param: name [%s] value [%s]", name, value);
-
- if (g_strcmp(name, "hostname") == 0)
- {
- g_strncpy(mod->settings->hostname, value, sizeof(mod->settings->hostname));
- }
- else if (g_strcmp(name, "ip") == 0)
- {
- g_strncpy(mod->settings->server, value, sizeof(mod->settings->server));
- }
- else if (g_strcmp(name, "port") == 0)
- {
- mod->settings->tcp_port_rdp = g_atoi(value);
- }
- else if (g_strcmp(name, "keylayout") == 0)
- {
- mod->settings->keyboard_layout = g_atoi(value);
- }
- else if (g_strcmp(name, "name") == 0)
- {
- }
- else if (g_strcmp(name, "lib") == 0)
- {
- }
- else
- {
- g_writeln("lib_mod_set_param: unknown name [%s] value [%s]", name, value);
- }
-
- return 0;
-}
-
-/******************************************************************************/
-static int DEFAULT_CC
-mod_session_change(struct mod *v, int a, int b)
-{
- g_writeln("mod_session_change:");
- return 0;
-}
-
-/******************************************************************************/
-static int DEFAULT_CC
-mod_get_wait_objs(struct mod *v, tbus *read_objs, int *rcount,
- tbus *write_objs, int *wcount, int *timeout)
-{
- void **rfds;
- void **wfds;
-
- rfds = (void **)read_objs;
- wfds = (void **)write_objs;
- return v->inst->rdp_get_fds(v->inst, rfds, rcount, wfds, wcount);
-}
-
-/******************************************************************************/
-static int DEFAULT_CC
-mod_check_wait_objs(struct mod *v)
-{
- return v->inst->rdp_check_fds(v->inst);
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_error(rdpInst *inst, const char *text)
-{
- g_writeln("ui_error: %s", text);
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_warning(rdpInst *inst, const char *text)
-{
- g_writeln("ui_warning: %s", text);
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_unimpl(rdpInst *inst, const char *text)
-{
- g_writeln("ui_unimpl: %s", text);
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_begin_update(rdpInst *inst)
-{
- struct mod *mod;
-
- mod = GET_MOD(inst);
- mod->server_begin_update(mod);
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_end_update(rdpInst *inst)
-{
- struct mod *mod;
-
- mod = GET_MOD(inst);
- mod->server_end_update(mod);
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_desktop_save(rdpInst *inst, int offset, int x, int y,
- int cx, int cy)
-{
- g_writeln("ui_desktop_save:");
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_desktop_restore(rdpInst *inst, int offset, int x, int y,
- int cx, int cy)
-{
- g_writeln("ui_desktop_restore:");
-}
-
-/******************************************************************************/
-static RD_HBITMAP DEFAULT_CC
-ui_create_bitmap(rdpInst *inst, int width, int height, uint8 *data)
-{
- struct my_bitmap *bm;
- struct mod *mod;
- int size;
- int bpp;
- char *bmpdata;
-
- mod = GET_MOD(inst);
- bpp = mod->bpp == 24 ? 32 : mod->bpp;
- bm = (struct my_bitmap *)g_malloc(sizeof(struct my_bitmap), 1);
- bm->width = width;
- bm->height = height;
- bm->bpp = bpp;
- bmpdata = convert_bitmap(mod->settings->server_depth, bpp,
- data, width, height, mod->cmap);
-
- if (bmpdata == (char *)data)
- {
- size = width * height * ((bpp + 7) / 8);
- bm->data = (char *)g_malloc(size, 0);
- g_memcpy(bm->data, bmpdata, size);
- }
- else
- {
- bm->data = bmpdata;
- }
-
- return bm;
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_paint_bitmap(rdpInst *inst, int x, int y, int cx, int cy, int width,
- int height, uint8 *data)
-{
- struct mod *mod;
- char *bmpdata;
-
- mod = GET_MOD(inst);
- bmpdata = convert_bitmap(mod->settings->server_depth, mod->bpp,
- data, width, height, mod->cmap);
-
- if (bmpdata != 0)
- {
- mod->server_paint_rect(mod, x, y, cx, cy, bmpdata, width, height, 0, 0);
- }
-
- if (bmpdata != (char *)data)
- {
- g_free(bmpdata);
- }
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_destroy_bitmap(rdpInst *inst, RD_HBITMAP bmp)
-{
- struct my_bitmap *bm;
-
- bm = (struct my_bitmap *)bmp;
- g_free(bm->data);
- g_free(bm);
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_line(rdpInst *inst, uint8 opcode, int startx, int starty, int endx,
- int endy, RD_PEN *pen)
-{
- g_writeln("ui_line:");
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_rect(rdpInst *inst, int x, int y, int cx, int cy, uint32 color)
-{
- struct mod *mod;
-
- mod = GET_MOD(inst);
- color = convert_color(mod->settings->server_depth, mod->bpp,
- color, mod->cmap);
- mod->server_set_fgcolor(mod, color);
- mod->server_fill_rect(mod, x, y, cx, cy);
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_polygon(rdpInst *inst, uint8 opcode, uint8 fillmode, RD_POINT *point,
- int npoints, RD_BRUSH *brush, uint32 bgcolor, uint32 fgcolor)
-{
- g_writeln("ui_polygon:");
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_polyline(rdpInst *inst, uint8 opcode, RD_POINT *points, int npoints,
- RD_PEN *pen)
-{
- g_writeln("ui_polyline:");
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_ellipse(rdpInst *inst, uint8 opcode, uint8 fillmode, int x, int y,
- int cx, int cy, RD_BRUSH *brush, uint32 bgcolor, uint32 fgcolor)
-{
- g_writeln("ui_ellipse:");
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_add_char(rdpInst *inst, uint8 font, uint16 character, sint16 offset,
- sint16 baseline, uint16 width, uint16 height, uint8 *data)
-{
- struct mod *mod;
-
- //g_writeln("ui_add_char:");
- mod = GET_MOD(inst);
- mod->server_add_char(mod, font, character, offset, baseline,
- width, height, (char *)data);
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_draw_text(rdpInst *inst, uint8 font, uint8 flags,
- uint8 opcode, int mixmode,
- int x, int y, int clipx, int clipy, int clipcx, int clipcy,
- int boxx, int boxy, int boxcx, int boxcy, RD_BRUSH *brush,
- uint32 bgcolor, uint32 fgcolor, uint8 *text, uint8 length)
-{
- struct mod *mod;
-
- //g_writeln("ui_draw_text: flags %d mixmode %d x %d y %d", flags, mixmode, x, y);
- //g_writeln("%d %d %d %d %d %d %d %d", clipx, clipy, clipcx, clipcy, boxx, boxy, boxcx, boxcy);
- mod = GET_MOD(inst);
- fgcolor = convert_color(mod->settings->server_depth, mod->bpp,
- fgcolor, mod->cmap);
- mod->server_set_fgcolor(mod, fgcolor);
- bgcolor = convert_color(mod->settings->server_depth, mod->bpp,
- bgcolor, mod->cmap);
- mod->server_set_bgcolor(mod, bgcolor);
- mod->server_draw_text(mod, font, flags, mixmode,
- clipx, clipy, clipx + clipcx, clipy + clipcy,
- boxx, boxy, boxx + boxcx, boxy + boxcy, x, y,
- (char *)text, length);
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_start_draw_glyphs(rdpInst *inst, uint32 bgcolor, uint32 fgcolor)
-{
- g_writeln("ui_start_draw_glyphs:");
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_draw_glyph(rdpInst *inst, int x, int y, int cx, int cy,
- RD_HGLYPH glyph)
-{
- g_writeln("ui_draw_glyph:");
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_end_draw_glyphs(rdpInst *inst, int x, int y, int cx, int cy)
-{
- g_writeln("ui_end_draw_glyphs:");
-}
-
-/******************************************************************************/
-static uint32 DEFAULT_CC
-ui_get_toggle_keys_state(rdpInst *inst)
-{
- g_writeln("ui_get_toggle_keys_state:");
- return 0;
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_bell(rdpInst *inst)
-{
- g_writeln("ui_bell:");
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_destblt(rdpInst *inst, uint8 opcode, int x, int y, int cx, int cy)
-{
- struct mod *mod;
-
- g_writeln("ui_destblt:");
- mod = GET_MOD(inst);
- mod->server_set_opcode(mod, opcode);
- mod->server_fill_rect(mod, x, y, cx, cy);
- mod->server_set_opcode(mod, 0xcc);
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_patblt(rdpInst *inst, uint8 opcode, int x, int y, int cx, int cy,
- RD_BRUSH *brush, uint32 bgcolor, uint32 fgcolor)
-{
- struct mod *mod;
- uint8 idata[8];
- int index;
-
- mod = GET_MOD(inst);
- mod->server_set_opcode(mod, opcode);
- fgcolor = convert_color(mod->settings->server_depth, mod->bpp,
- fgcolor, mod->cmap);
- mod->server_set_fgcolor(mod, fgcolor);
- bgcolor = convert_color(mod->settings->server_depth, mod->bpp,
- bgcolor, mod->cmap);
- mod->server_set_bgcolor(mod, bgcolor);
- mod->server_set_mixmode(mod, 1);
-
- if (brush->bd != 0)
- {
- if (brush->bd->color_code == 1) /* 8x8 1 bpp */
- {
- for (index = 0; index < 8; index++)
- {
- idata[index] = ~(brush->bd->data[index]);
- }
-
- mod->server_set_brush(mod, brush->xorigin, brush->yorigin,
- brush->style, idata);
- }
- else
- {
- g_writeln("ui_patblt: error color_code %d", brush->bd->color_code);
- }
- }
- else
- {
- for (index = 0; index < 8; index++)
- {
- idata[index] = ~(brush->pattern[index]);
- }
-
- mod->server_set_brush(mod, brush->xorigin, brush->yorigin,
- brush->style, idata);
- }
-
- mod->server_fill_rect(mod, x, y, cx, cy);
- mod->server_set_opcode(mod, 0xcc);
- mod->server_set_mixmode(mod, 0);
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_screenblt(rdpInst *inst, uint8 opcode, int x, int y, int cx, int cy,
- int srcx, int srcy)
-{
- struct mod *mod;
-
- mod = GET_MOD(inst);
- mod->server_set_opcode(mod, opcode);
- mod->server_screen_blt(mod, x, y, cx, cy, srcx, srcy);
- mod->server_set_opcode(mod, 0xcc);
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_memblt(rdpInst *inst, uint8 opcode, int x, int y, int cx, int cy,
- RD_HBITMAP src, int srcx, int srcy)
-{
- struct my_bitmap *bitmap;
- struct mod *mod;
- char *bmpdata;
-
- mod = GET_MOD(inst);
- bitmap = (struct my_bitmap *)src;
- mod->server_set_opcode(mod, opcode);
- mod->server_paint_rect(mod, x, y, cx, cy, bitmap->data,
- bitmap->width, bitmap->height, srcx, srcy);
- mod->server_set_opcode(mod, 0xcc);
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_triblt(rdpInst *inst, uint8 opcode, int x, int y, int cx, int cy,
- RD_HBITMAP src, int srcx, int srcy, RD_BRUSH *brush,
- uint32 bgcolor, uint32 fgcolor)
-{
- g_writeln("ui_triblt:");
-}
-
-/******************************************************************************/
-static RD_HGLYPH DEFAULT_CC
-ui_create_glyph(rdpInst *inst, int width, int height, uint8 *data)
-{
- g_writeln("ui_create_glyph:");
- return 0;
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_destroy_glyph(rdpInst *inst, RD_HGLYPH glyph)
-{
- g_writeln("ui_destroy_glyph:");
-}
-
-/******************************************************************************/
-static int DEFAULT_CC
-ui_select(rdpInst *inst, int rdp_socket)
-{
- return 1;
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_set_clip(rdpInst *inst, int x, int y, int cx, int cy)
-{
- struct mod *mod;
-
- mod = GET_MOD(inst);
- mod->server_set_clip(mod, x, y, cx, cy);
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_reset_clip(rdpInst *inst)
-{
- struct mod *mod;
-
- mod = GET_MOD(inst);
- mod->server_reset_clip(mod);
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_resize_window(rdpInst *inst)
-{
- g_writeln("ui_resize_window:");
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_set_cursor(rdpInst *inst, RD_HCURSOR cursor)
-{
- struct mod *mod;
- struct my_cursor *cur;
-
- //g_writeln("ui_set_cursor:");
- mod = GET_MOD(inst);
- cur = (struct my_cursor *)cursor;
-
- if (cur != 0)
- {
- mod->server_set_cursor(mod, cur->hotx, cur->hoty,
- cur->xormask, cur->andmask);
- }
- else
- {
- g_writeln("ui_set_cursor: nil cursor");
- }
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_destroy_cursor(rdpInst *inst, RD_HCURSOR cursor)
-{
- struct my_cursor *cur;
-
- //g_writeln("ui_destroy_cursor:");
- cur = (struct my_cursor *)cursor;
-
- if (cur != 0)
- {
- g_free(cur->andmask);
- g_free(cur->xormask);
- }
-
- g_free(cur);
-}
-
-#define RGB24(_r, _g, _b) \
- (_r << 16) | (_g << 8) | _b;
-
-/******************************************************************************/
-static int
-l_get_pixel(tui8 *data, int x, int y, int width, int height, int bpp)
-{
- int start;
- int shift;
- tui16 *src16;
- tui32 *src32;
- int red, green, blue;
-
- switch (bpp)
- {
- case 1:
- width = (width + 7) / 8;
- start = (y * width) + x / 8;
- shift = x % 8;
- return (data[start] & (0x80 >> shift)) != 0;
- case 8:
- return data[y * width + x];
- case 15:
- case 16:
- src16 = (uint16 *) data;
- return src16[y * width + x];
- case 24:
- data += y * width * 3;
- data += x * 3;
- red = data[0];
- green = data[1];
- blue = data[2];
- return RGB24(red, green, blue);
- case 32:
- src32 = (uint32 *) data;
- return src32[y * width + x];
- default:
- g_writeln("l_get_pixel: unknown bpp %d", bpp);
- break;
- }
-
- return 0;
-}
-
-/******************************************************************************/
-static void
-l_set_pixel(tui8 *data, int x, int y, int width, int height,
- int bpp, int pixel)
-{
- int start;
- int shift;
- int *dst32;
- tui8 *dst8;
-
- if (bpp == 1)
- {
- width = (width + 7) / 8;
- start = (y * width) + x / 8;
- shift = x % 8;
-
- if (pixel)
- {
- data[start] = data[start] | (0x80 >> shift);
- }
- else
- {
- data[start] = data[start] & ~(0x80 >> shift);
- }
- }
- else if (bpp == 24)
- {
- dst8 = data + (y * width + x) * 3;
- *(dst8++) = (pixel >> 16) & 0xff;
- *(dst8++) = (pixel >> 8) & 0xff;
- *(dst8++) = (pixel >> 0) & 0xff;
- }
- else if (bpp == 32)
- {
- dst32 = (int *) data;
- dst32[y * width + x] = pixel;
- }
- else
- {
- g_writeln("l_set_pixel: unknown bpp %d", bpp);
- }
-}
-
-
-/******************************************************************************/
-/* andmask = mask = 32 * 32 / 8
- xormask = data = 32 * 32 * 3 */
-static RD_HCURSOR DEFAULT_CC
-ui_create_cursor(rdpInst *inst, unsigned int x, unsigned int y,
- int width, int height, uint8 *andmask,
- uint8 *xormask, int bpp)
-{
- struct mod *mod;
- struct my_cursor *cur;
- int i;
- int j;
- int jj;
- int apixel;
- int xpixel;
- char *dst;
-
- mod = GET_MOD(inst);
- g_writeln("ui_create_cursor: x %d y %d width %d height %d bpp %d",
- x, y, width, height, bpp);
- cur = (struct my_cursor *)g_malloc(sizeof(struct my_cursor), 1);
- cur->width = width;
- cur->height = height;
- cur->hotx = x;
- cur->hoty = y;
- cur->andmask = g_malloc(32 * 32 * 4, 1);
- cur->xormask = g_malloc(32 * 32 * 4, 1);
-
- for (j = 0; j < height; j++)
- {
- jj = (bpp != 1) ? j : (height - 1) - j;
-
- for (i = 0; i < width; i++)
- {
- apixel = l_get_pixel(andmask, i, jj, width, height, 1);
- xpixel = l_get_pixel(xormask, i, jj, width, height, bpp);
- xpixel = convert_color(bpp, 24, xpixel, mod->cmap);
- l_set_pixel(cur->andmask, i, j, width, height, 1, apixel);
- l_set_pixel(cur->xormask, i, j, width, height, 24, xpixel);
- }
- }
-
- return (RD_HCURSOR)cur;
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_set_null_cursor(rdpInst *inst)
-{
- g_writeln("ui_set_null_cursor:");
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_set_default_cursor(rdpInst *inst)
-{
- g_writeln("ui_set_default_cursor:");
-}
-
-/******************************************************************************/
-static RD_HPALETTE DEFAULT_CC
-ui_create_palette(rdpInst *inst, RD_PALETTE *colors)
-{
- struct mod *mod;
- int index;
- int red;
- int green;
- int blue;
- int pixel;
- int count;
- int *cmap;
-
- mod = GET_MOD(inst);
- g_writeln("ui_create_palette:");
- count = 256;
-
- if (count > colors->count)
- {
- count = colors->count;
- }
-
- cmap = (int *)g_malloc(256 * 4, 1);
-
- for (index = 0; index < count; index++)
- {
- red = colors->entries[index].red;
- green = colors->entries[index].green;
- blue = colors->entries[index].blue;
- pixel = COLOR24RGB(red, green, blue);
- cmap[index] = pixel;
- }
-
- return (RD_HPALETTE)cmap;
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_move_pointer(rdpInst *inst, int x, int y)
-{
- g_writeln("ui_move_pointer:");
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_set_palette(rdpInst *inst, RD_HPALETTE map)
-{
- struct mod *mod;
-
- mod = GET_MOD(inst);
- g_writeln("ui_set_palette:");
- g_memcpy(mod->cmap, map, 256 * 4);
- g_free(map);
-}
-
-/******************************************************************************/
-static RD_HBITMAP DEFAULT_CC
-ui_create_surface(rdpInst *inst, int width, int height, RD_HBITMAP old)
-{
- g_writeln("ui_create_surface:");
- return 0;
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_set_surface(rdpInst *inst, RD_HBITMAP surface)
-{
- g_writeln("ui_set_surface:");
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_destroy_surface(rdpInst *inst, RD_HBITMAP surface)
-{
- g_writeln("ui_destroy_surface:");
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-ui_channel_data(rdpInst *inst, int chan_id, char *data, int data_size,
- int flags, int total_size)
-{
- g_writeln("ui_channel_data:");
-}
-
-/******************************************************************************/
-static RD_BOOL DEFAULT_CC
-ui_authenticate(rdpInst *inst)
-{
- return 1;
-}
-
-/******************************************************************************/
-static int DEFAULT_CC
-ui_decode(rdpInst *inst, uint8 *data, int data_size)
-{
- return 0;
-}
-
-/******************************************************************************/
-static RD_BOOL DEFAULT_CC
-ui_check_certificate(rdpInst *inst, const char *fingerprint,
- const char *subject, const char *issuer, RD_BOOL verified)
-{
- return 1;
-}
-
-/******************************************************************************/
-struct mod *EXPORT_CC
-mod_init(void)
-{
- struct mod *mod;
-
- //g_writeln("1");
- //freerdp_global_init();
- //g_writeln("2");
- mod = (struct mod *)g_malloc(sizeof(struct mod), 1);
- mod->size = sizeof(struct mod);
- mod->version = CURRENT_MOD_VER;
- 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_session_change = mod_session_change;
- mod->mod_get_wait_objs = mod_get_wait_objs;
- mod->mod_check_wait_objs = mod_check_wait_objs;
- mod->settings = (struct rdp_set *)g_malloc(sizeof(struct rdp_set), 1);
-
- mod->settings->width = 1280;
- mod->settings->height = 1024;
- mod->settings->encryption = 1;
- mod->settings->rdp_security = 1;
- mod->settings->tls_security = 1;
- mod->settings->server_depth = 16;
- mod->settings->bitmap_cache = 1;
- mod->settings->bitmap_compression = 1;
- mod->settings->performanceflags =
- PERF_DISABLE_WALLPAPER | PERF_DISABLE_FULLWINDOWDRAG | PERF_DISABLE_MENUANIMATIONS;
- mod->settings->new_cursors = 1;
- mod->settings->rdp_version = 5;
- mod->settings->text_flags = 1;
-
- mod->inst = freerdp_new(mod->settings);
-
- if (mod->inst == 0)
- {
- return 0;
- }
-
- SET_MOD(mod->inst, mod);
- mod->inst->ui_error = ui_error;
- mod->inst->ui_warning = ui_warning;
- mod->inst->ui_unimpl = ui_unimpl;
- mod->inst->ui_begin_update = ui_begin_update;
- mod->inst->ui_end_update = ui_end_update;
- mod->inst->ui_desktop_save = ui_desktop_save;
- mod->inst->ui_desktop_restore = ui_desktop_restore;
- mod->inst->ui_create_bitmap = ui_create_bitmap;
- mod->inst->ui_paint_bitmap = ui_paint_bitmap;
- mod->inst->ui_destroy_bitmap = ui_destroy_bitmap;
- mod->inst->ui_line = ui_line;
- mod->inst->ui_rect = ui_rect;
- mod->inst->ui_polygon = ui_polygon;
- mod->inst->ui_polyline = ui_polyline;
- mod->inst->ui_ellipse = ui_ellipse;
- mod->inst->ui_add_char = ui_add_char;
- mod->inst->ui_draw_text = ui_draw_text;
- mod->inst->ui_start_draw_glyphs = ui_start_draw_glyphs;
- mod->inst->ui_draw_glyph = ui_draw_glyph;
- mod->inst->ui_end_draw_glyphs = ui_end_draw_glyphs;
- mod->inst->ui_get_toggle_keys_state = ui_get_toggle_keys_state;
- mod->inst->ui_bell = ui_bell;
- mod->inst->ui_destblt = ui_destblt;
- mod->inst->ui_patblt = ui_patblt;
- mod->inst->ui_screenblt = ui_screenblt;
- mod->inst->ui_memblt = ui_memblt;
- mod->inst->ui_triblt = ui_triblt;
- mod->inst->ui_create_glyph = ui_create_glyph;
- mod->inst->ui_destroy_glyph = ui_destroy_glyph;
- mod->inst->ui_select = ui_select;
- mod->inst->ui_set_clip = ui_set_clip;
- mod->inst->ui_reset_clip = ui_reset_clip;
- mod->inst->ui_resize_window = ui_resize_window;
- mod->inst->ui_set_cursor = ui_set_cursor;
- mod->inst->ui_destroy_cursor = ui_destroy_cursor;
- mod->inst->ui_create_cursor = ui_create_cursor;
- mod->inst->ui_set_null_cursor = ui_set_null_cursor;
- mod->inst->ui_set_default_cursor = ui_set_default_cursor;
- mod->inst->ui_create_palette = ui_create_palette;
- mod->inst->ui_move_pointer = ui_move_pointer;
- mod->inst->ui_set_palette = ui_set_palette;
- mod->inst->ui_create_surface = ui_create_surface;
- mod->inst->ui_set_surface = ui_set_surface;
- mod->inst->ui_destroy_surface = ui_destroy_surface;
- mod->inst->ui_channel_data = ui_channel_data;
-
- mod->inst->ui_authenticate = ui_authenticate;
- mod->inst->ui_decode = ui_decode;
- mod->inst->ui_check_certificate = ui_check_certificate;
-
- return mod;
-}
-
-/******************************************************************************/
-int EXPORT_CC
-mod_exit(struct mod *mod)
-{
- if (mod == 0)
- {
- return 0;
- }
-
- freerdp_free(mod->inst);
- g_free(mod->settings);
- g_free(mod);
- //freerdp_global_finish();
- return 0;
-}
diff --git a/freerdp/xrdp-freerdp.h b/freerdp/xrdp-freerdp.h
deleted file mode 100644
index b62c8206..00000000
--- a/freerdp/xrdp-freerdp.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/**
- * xrdp: A Remote Desktop Protocol server.
- *
- * Copyright (C) Jay Sorg 2004-2012
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * freerdp wrapper
- */
-
-/* include other h files */
-#include "arch.h"
-#include "parse.h"
-#include "os_calls.h"
-#include "defines.h"
-
-/* this is the freerdp main header */
-#include <freerdp/freerdp.h>
-
-#define CURRENT_MOD_VER 2
-
-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, long param1, long param2,
- long param3, long 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);
- long 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 total_data_len, int flags);
- int (*server_bell_trigger)(struct mod* v);
- 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;
- struct rdp_set* settings;
- struct rdp_inst* inst;
- int cmap[256];
-};
diff --git a/freerdp1/Makefile.am b/freerdp1/Makefile.am
deleted file mode 100644
index d1d49440..00000000
--- a/freerdp1/Makefile.am
+++ /dev/null
@@ -1,28 +0,0 @@
-EXTRA_DIST = xrdp-freerdp.h
-EXTRA_DEFINES =
-
-if XRDP_DEBUG
-EXTRA_DEFINES += -DXRDP_DEBUG
-else
-EXTRA_DEFINES += -DXRDP_NODEBUG
-endif
-
-AM_CFLAGS = \
- -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \
- -DXRDP_SBIN_PATH=\"${sbindir}\" \
- -DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \
- -DXRDP_PID_PATH=\"${localstatedir}/run\" \
- $(EXTRA_DEFINES)
-
-INCLUDES = \
- -I$(top_srcdir)/common \
- $(FREERDP_CFLAGS)
-
-lib_LTLIBRARIES = \
- libxrdpfreerdp1.la
-
-libxrdpfreerdp1_la_SOURCES = xrdp-freerdp.c xrdp-color.c
-
-libxrdpfreerdp1_la_LIBADD = \
- $(top_builddir)/common/libcommon.la \
- $(FREERDP_LIBS)
diff --git a/freerdp1/xrdp-color.c b/freerdp1/xrdp-color.c
deleted file mode 100644
index 6b99140a..00000000
--- a/freerdp1/xrdp-color.c
+++ /dev/null
@@ -1,313 +0,0 @@
-/**
- * FreeRDP: A Remote Desktop Protocol Server
- * freerdp wrapper
- *
- * Copyright 2011-2012 Jay Sorg
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "xrdp-freerdp.h"
-
-char *APP_CC
-convert_bitmap(int in_bpp, int out_bpp, char *bmpdata,
- int width, int height, int *palette)
-{
- char *out;
- char *src;
- char *dst;
- int i;
- int j;
- int red;
- int green;
- int blue;
- int pixel;
-
- if ((in_bpp == 8) && (out_bpp == 8))
- {
- out = (char *)g_malloc(width * height, 0);
- src = bmpdata;
- dst = out;
-
- for (i = 0; i < height; i++)
- {
- for (j = 0; j < width; j++)
- {
- pixel = *((tui8 *)src);
- pixel = palette[pixel];
- SPLITCOLOR32(red, green, blue, pixel);
- pixel = COLOR8(red, green, blue);
- *dst = pixel;
- src++;
- dst++;
- }
- }
-
- return out;
- }
-
- if ((in_bpp == 8) && (out_bpp == 16))
- {
- out = (char *)g_malloc(width * height * 2, 0);
- src = bmpdata;
- dst = out;
-
- for (i = 0; i < height; i++)
- {
- for (j = 0; j < width; j++)
- {
- pixel = *((tui8 *)src);
- pixel = palette[pixel];
- SPLITCOLOR32(red, green, blue, pixel);
- pixel = COLOR16(red, green, blue);
- *((tui16 *)dst) = pixel;
- src++;
- dst += 2;
- }
- }
-
- return out;
- }
-
- if ((in_bpp == 8) && (out_bpp == 24))
- {
- out = (char *)g_malloc(width * height * 4, 0);
- src = bmpdata;
- dst = out;
-
- for (i = 0; i < height; i++)
- {
- for (j = 0; j < width; j++)
- {
- pixel = *((tui8 *)src);
- pixel = palette[pixel];
- SPLITCOLOR32(red, green, blue, pixel);
- pixel = COLOR24RGB(red, green, blue);
- *((tui32 *)dst) = pixel;
- src++;
- dst += 4;
- }
- }
-
- return out;
- }
-
- if ((in_bpp == 15) && (out_bpp == 16))
- {
- out = (char *)g_malloc(width * height * 2, 0);
- src = bmpdata;
- dst = out;
-
- for (i = 0; i < height; i++)
- {
- for (j = 0; j < width; j++)
- {
- pixel = *((tui16 *)src);
- SPLITCOLOR15(red, green, blue, pixel);
- pixel = COLOR16(red, green, blue);
- *((tui16 *)dst) = pixel;
- src += 2;
- dst += 2;
- }
- }
-
- return out;
- }
-
- if ((in_bpp == 15) && (out_bpp == 24))
- {
- out = (char *)g_malloc(width * height * 4, 0);
- src = bmpdata;
- dst = out;
-
- for (i = 0; i < height; i++)
- {
- for (j = 0; j < width; j++)
- {
- pixel = *((tui16 *)src);
- SPLITCOLOR15(red, green, blue, pixel);
- pixel = COLOR24RGB(red, green, blue);
- *((tui32 *)dst) = pixel;
- src += 2;
- dst += 4;
- }
- }
-
- return out;
- }
-
- if ((in_bpp == 15) && (out_bpp == 15))
- {
- return bmpdata;
- }
-
- if ((in_bpp == 16) && (out_bpp == 16))
- {
- return bmpdata;
- }
-
- if ((in_bpp == 16) && (out_bpp == 24))
- {
- out = (char *)g_malloc(width * height * 4, 0);
- src = bmpdata;
- dst = out;
-
- for (i = 0; i < height; i++)
- {
- for (j = 0; j < width; j++)
- {
- pixel = *((tui16 *)src);
- SPLITCOLOR16(red, green, blue, pixel);
- pixel = COLOR24RGB(red, green, blue);
- *((tui32 *)dst) = pixel;
- src += 2;
- dst += 4;
- }
- }
-
- return out;
- }
-
- if ((in_bpp == 24) && (out_bpp == 24))
- {
- out = (char *)g_malloc(width * height * 4, 0);
- src = bmpdata;
- dst = out;
-
- for (i = 0; i < height; i++)
- {
- for (j = 0; j < width; j++)
- {
- blue = *((tui8 *)src);
- src++;
- green = *((tui8 *)src);
- src++;
- red = *((tui8 *)src);
- src++;
- pixel = COLOR24RGB(red, green, blue);
- *((tui32 *)dst) = pixel;
- dst += 4;
- }
- }
-
- return out;
- }
-
- if ((in_bpp == 32) && (out_bpp == 24))
- {
- return bmpdata;
- }
-
- if ((in_bpp == 32) && (out_bpp == 32))
- {
- return bmpdata;
- }
-
- g_writeln("convert_bitmap: error unknown conversion from %d to %d",
- in_bpp, out_bpp);
- return 0;
-}
-
-/*****************************************************************************/
-/* returns color or 0 */
-int APP_CC
-convert_color(int in_bpp, int out_bpp, int in_color, int *palette)
-{
- int pixel;
- int red;
- int green;
- int blue;
-
- if ((in_bpp == 1) && (out_bpp == 24))
- {
- pixel = in_color == 0 ? 0 : 0xffffff;
- return pixel;
- }
-
- if ((in_bpp == 8) && (out_bpp == 8))
- {
- pixel = palette[in_color];
- SPLITCOLOR32(red, green, blue, pixel);
- pixel = COLOR8(red, green, blue);
- return pixel;
- }
-
- if ((in_bpp == 8) && (out_bpp == 16))
- {
- pixel = palette[in_color];
- SPLITCOLOR32(red, green, blue, pixel);
- pixel = COLOR16(red, green, blue);
- return pixel;
- }
-
- if ((in_bpp == 8) && (out_bpp == 24))
- {
- pixel = palette[in_color];
- SPLITCOLOR32(red, green, blue, pixel);
- pixel = COLOR24BGR(red, green, blue);
- return pixel;
- }
-
- if ((in_bpp == 15) && (out_bpp == 16))
- {
- pixel = in_color;
- SPLITCOLOR15(red, green, blue, pixel);
- pixel = COLOR16(red, green, blue);
- return pixel;
- }
-
- if ((in_bpp == 15) && (out_bpp == 24))
- {
- pixel = in_color;
- SPLITCOLOR15(red, green, blue, pixel);
- pixel = COLOR24BGR(red, green, blue);
- return pixel;
- }
-
- if ((in_bpp == 15) && (out_bpp == 15))
- {
- return in_color;
- }
-
- if ((in_bpp == 16) && (out_bpp == 16))
- {
- return in_color;
- }
-
- if ((in_bpp == 16) && (out_bpp == 24))
- {
- pixel = in_color;
- SPLITCOLOR16(red, green, blue, pixel);
- pixel = COLOR24BGR(red, green, blue);
- return pixel;
- }
-
- if ((in_bpp == 24) && (out_bpp == 24))
- {
- return in_color;
- }
-
- if ((in_bpp == 32) && (out_bpp == 24))
- {
- return in_color;
- }
-
- if ((in_bpp == 32) && (out_bpp == 32))
- {
- return in_color;
- }
-
- g_writeln("convert_color: error unknown conversion from %d to %d",
- in_bpp, out_bpp);
- return 0;
-}
diff --git a/freerdp1/xrdp-color.h b/freerdp1/xrdp-color.h
deleted file mode 100644
index 6a3f7362..00000000
--- a/freerdp1/xrdp-color.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * FreeRDP: A Remote Desktop Protocol Server
- * freerdp wrapper
- *
- * Copyright 2011-2012 Jay Sorg
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __XRDP_COLOR_H
-#define __XRDP_COLOR_H
-
-char* APP_CC
-convert_bitmap(int in_bpp, int out_bpp, char* bmpdata,
- int width, int height, int* palette);
-int APP_CC
-convert_color(int in_bpp, int out_bpp, int in_color, int* palette);
-
-#endif
diff --git a/freerdp1/xrdp-freerdp.c b/freerdp1/xrdp-freerdp.c
deleted file mode 100644
index ca4fe31f..00000000
--- a/freerdp1/xrdp-freerdp.c
+++ /dev/null
@@ -1,1858 +0,0 @@
-/**
- * FreeRDP: A Remote Desktop Protocol Server
- * freerdp wrapper
- *
- * Copyright 2011-2012 Jay Sorg
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <freerdp/settings.h>
-#include <X11/Xlib.h>
-#include "xrdp-freerdp.h"
-#include "xrdp-color.h"
-#include "xrdp_rail.h"
-#include "log.h"
-
-#ifdef XRDP_DEBUG
-#define LOG_LEVEL 99
-#else
-#define LOG_LEVEL 0
-#endif
-
-#define LLOG(_level, _args) \
- do { if (_level < LOG_LEVEL) { g_write _args ; } } while (0)
-#define LLOGLN(_level, _args) \
- do { if (_level < LOG_LEVEL) { g_writeln _args ; } } while (0)
-
-struct mod_context
-{
- rdpContext _p;
- struct mod *modi;
-};
-typedef struct mod_context modContext;
-
-void verifyColorMap(struct mod *mod)
-{
- int i ;
- for( i = 0 ;i<255 ; i++)
- {
- if(mod->colormap[i]!=0)
- {
- return ;
- }
- }
- LLOGLN(0, ("The colormap is all NULL\n"));
-}
-/*****************************************************************************/
-/* return error */
-static int DEFAULT_CC
-lxrdp_start(struct mod *mod, int w, int h, int bpp)
-{
- rdpSettings *settings;
-
- LLOGLN(10, ("lxrdp_start: w %d h %d bpp %d", w, h, bpp));
- settings = mod->inst->settings;
- settings->DesktopWidth = w;
- settings->DesktopHeight = h;
- settings->ColorDepth = bpp;
- mod->bpp = bpp;
- // TODO what does this really become
- settings->DisableEncryption = 1; // settings->encryption = 1;
- settings->TlsSecurity = 1;
- settings->NlaSecurity = 0;
- settings->RdpSecurity = 1;
-
- return 0;
-}
-
-/******************************************************************************/
-/* return error */
-static int DEFAULT_CC
-lxrdp_connect(struct mod *mod)
-{
- BOOL ok;
-
- LLOGLN(10, ("lxrdp_connect:"));
-
- ok = freerdp_connect(mod->inst);
- LLOGLN(0, ("lxrdp_connect: freerdp_connect returned %d", ok));
-
- if (!ok)
- {
- LLOGLN(0, ("Failure to connect"));
-#ifdef ERRORSTART
-
- if (connectErrorCode != 0)
- {
- char buf[128];
-
- if (connectErrorCode < ERRORSTART)
- {
- if (strerror_r(connectErrorCode, buf, 128) != 0)
- {
- g_snprintf(buf, 128, "Errorcode from connect : %d", connectErrorCode);
- }
- }
- else
- {
- switch (connectErrorCode)
- {
- case PREECONNECTERROR:
- g_snprintf(buf, 128, "The error code from connect is "
- "PREECONNECTERROR");
- break;
- case UNDEFINEDCONNECTERROR:
- g_snprintf(buf, 128, "The error code from connect is "
- "UNDEFINEDCONNECTERROR");
- break;
- case POSTCONNECTERROR:
- g_snprintf(buf, 128, "The error code from connect is "
- "POSTCONNECTERROR");
- break;
- case DNSERROR:
- g_snprintf(buf, 128, "The DNS system generated an error");
- break;
- case DNSNAMENOTFOUND:
- g_snprintf(buf, 128, "The DNS system could not find the "
- "specified name");
- break;
- case CONNECTERROR:
- g_snprintf(buf, 128, "A general connect error was returned");
- break;
- case MCSCONNECTINITIALERROR:
- g_snprintf(buf, 128, "The error code from connect is "
- "MCSCONNECTINITIALERROR");
- break;
- case TLSCONNECTERROR:
- g_snprintf(buf, 128, "Error in TLS handshake");
- break;
- case AUTHENTICATIONERROR:
- g_snprintf(buf, 128, "Authentication error check your password "
- "and username");
- break;
- default:
- g_snprintf(buf, 128, "Unhandled Errorcode from connect : %d",
- connectErrorCode);
- break;
- }
- }
- log_message(LOG_LEVEL_INFO,buf);
- mod->server_msg(mod, buf, 0);
- }
-
-#endif
- log_message(LOG_LEVEL_INFO,"freerdp_connect Failed to destination :%s:%d",mod->inst->settings->ServerHostname,mod->inst->settings->ServerPort);
- return 1;
- }
- else
- {
- log_message(LOG_LEVEL_INFO,"freerdp_connect returned Success to destination :%s:%d",mod->inst->settings->ServerHostname,mod->inst->settings->ServerPort);
- }
-
- return 0;
-}
-
-/******************************************************************************/
-/* return error */
-static int DEFAULT_CC
-lxrdp_event(struct mod *mod, int msg, long param1, long param2,
- long param3, long param4)
-{
- int x;
- int y;
- int flags;
- int size;
- int total_size;
- int chanid;
- int lchid;
- char *data;
-
- LLOGLN(12, ("lxrdp_event: msg %d", msg));
-
- switch (msg)
- {
- case 15: /* key down */
- mod->inst->input->KeyboardEvent(mod->inst->input, param4, param3);
- break;
- case 16: /* key up */
- mod->inst->input->KeyboardEvent(mod->inst->input, param4, param3);
- break;
- case 17: /*Synchronize*/
- LLOGLN(11, ("Synchronized event handled"));
- mod->inst->input->SynchronizeEvent(mod->inst->input, 0);
- break;
- case 100: /* mouse move */
- LLOGLN(12, ("mouse move %d %d", param1, param2));
- x = param1;
- y = param2;
- flags = PTR_FLAGS_MOVE;
- mod->inst->input->MouseEvent(mod->inst->input, flags, x, y);
- break;
- case 101: /* left button up */
- LLOGLN(12, ("left button up %d %d", param1, param2));
- x = param1;
- y = param2;
- flags = PTR_FLAGS_BUTTON1;
- mod->inst->input->MouseEvent(mod->inst->input, flags, x, y);
- break;
- case 102: /* left button down */
- LLOGLN(12, ("left button down %d %d", param1, param2));
- x = param1;
- y = param2;
- flags = PTR_FLAGS_BUTTON1 | PTR_FLAGS_DOWN;
- mod->inst->input->MouseEvent(mod->inst->input, flags, x, y);
- break;
- case 103: /* right button up */
- LLOGLN(12, ("right button up %d %d", param1, param2));
- x = param1;
- y = param2;
- flags = PTR_FLAGS_BUTTON2;
- mod->inst->input->MouseEvent(mod->inst->input, flags, x, y);
- break;
- case 104: /* right button down */
- LLOGLN(12, ("right button down %d %d", param1, param2));
- x = param1;
- y = param2;
- flags = PTR_FLAGS_BUTTON2 | PTR_FLAGS_DOWN;
- mod->inst->input->MouseEvent(mod->inst->input, flags, x, y);
- break;
- case 105: /* middle button up */
- LLOGLN(12, ("middle button up %d %d", param1, param2));
- x = param1;
- y = param2;
- flags = PTR_FLAGS_BUTTON3;
- mod->inst->input->MouseEvent(mod->inst->input, flags, x, y);
- break;
- case 106: /* middle button down */
- LLOGLN(12, ("middle button down %d %d", param1, param2));
- x = param1;
- y = param2;
- flags = PTR_FLAGS_BUTTON3 | PTR_FLAGS_DOWN;
- mod->inst->input->MouseEvent(mod->inst->input, flags, x, y);
- break;
- case 107: /* wheel up */
- flags = PTR_FLAGS_WHEEL | 0x0078;
- mod->inst->input->MouseEvent(mod->inst->input, flags, 0, 0);
- case 108:
- break;
- case 109: /* wheel down */
- flags = PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x0088;
- mod->inst->input->MouseEvent(mod->inst->input, flags, 0, 0);
- case 110:
- break;
- case 200:
- LLOGLN(12, ("Invalidate request sent from client"));
- RECTANGLE_16 *rectangle = (RECTANGLE_16 *) g_malloc(sizeof(RECTANGLE_16), 0);
- /* The parameters are coded as follows param1 = MAKELONG(y, x), param2 =MAKELONG(h, w)
- * #define MAKELONG(lo, hi) ((((hi) & 0xffff) << 16) | ((lo) & 0xffff))
- */
- rectangle->left = (param1 >> 16) & 0xffff;
- rectangle->top = param1 & 0xffff;
- rectangle->right = (((param2 >> 16) & 0xffff) + rectangle->left) - 1;
- rectangle->bottom = ((param2 & 0xffff) + rectangle->top) - 1;
-
- if (mod->inst->settings->RefreshRect)
- {
- if (mod->inst->update != NULL)
- {
- if (mod->inst->update->RefreshRect != NULL)
- {
- if (mod->inst->context != NULL)
- {
- LLOGLN(0, ("update rectangle left: %d top: %d bottom: %d right: %d",
- rectangle->left, rectangle->top, rectangle->bottom, rectangle->right));
- mod->inst->update->RefreshRect(mod->inst->context, 1, rectangle);
- }
- else
- {
- LLOGLN(0, ("Invalidate request -The context is null"));
- }
- }
- else
- {
- LLOGLN(0, ("Invalidate request - RefreshRect is Null"));
- }
- }
- else
- {
- LLOGLN(0, ("Invalidate request -the update pointer is null"));
- }
- }
- else
- {
- LLOGLN(0, ("Invalidate request - warning - update rectangle is disabled"));
- }
-
- g_free(rectangle);
- break;
- case 0x5555:
- chanid = LOWORD(param1);
- flags = HIWORD(param1);
- size = (int)param2;
- data = (char *)param3;
- total_size = (int)param4;
- LLOGLN(12, ("lxrdp_event: client to server flags %d", flags));
-
- if ((chanid < 0) || (chanid >= mod->inst->settings->ChannelDefArraySize))
- {
- LLOGLN(0, ("lxrdp_event: error chanid %d", chanid));
- break;
- }
-
- lchid = mod->inst->settings->ChannelDefArray[chanid].ChannelId;
-
- switch (flags & 3)
- {
- case 3:
- mod->inst->SendChannelData(mod->inst, lchid, (tui8 *)data, total_size);
- break;
- case 2:
- /* end */
- g_memcpy(mod->chan_buf + mod->chan_buf_valid, data, size);
- mod->chan_buf_valid += size;
- mod->inst->SendChannelData(mod->inst, lchid, (tui8 *)(mod->chan_buf),
- total_size);
- g_free(mod->chan_buf);
- mod->chan_buf = 0;
- mod->chan_buf_bytes = 0;
- mod->chan_buf_valid = 0;
- break;
- case 1:
- /* start */
- g_free(mod->chan_buf);
- mod->chan_buf = (char *)g_malloc(total_size, 0);
- mod->chan_buf_bytes = total_size;
- mod->chan_buf_valid = 0;
- g_memcpy(mod->chan_buf + mod->chan_buf_valid, data, size);
- mod->chan_buf_valid += size;
- break;
- default:
- /* middle */
- g_memcpy(mod->chan_buf + mod->chan_buf_valid, data, size);
- mod->chan_buf_valid += size;
- break;
- }
-
- break;
- default:
- LLOGLN(0, ("Unhandled message type in eventhandler %d", msg));
- break;
- }
-
- return 0;
-}
-
-/******************************************************************************/
-/* return error */
-static int DEFAULT_CC
-lxrdp_signal(struct mod *mod)
-{
- LLOGLN(10, ("lxrdp_signal:"));
- return 0;
-}
-
-/******************************************************************************/
-/* return error */
-static int DEFAULT_CC
-lxrdp_end(struct mod *mod)
-{
- int i;
- int j;
-
- for (j = 0; j < 4; j++)
- {
- for (i = 0; i < 4096; i++)
- {
- g_free(mod->bitmap_cache[j][i].data);
- }
- }
-
- for (i = 0; i < 64; i++)
- {
- if (mod->brush_cache[i].data != mod->brush_cache[i].b8x8)
- {
- g_free(mod->brush_cache[i].data);
- }
- }
-
- LLOGLN(10, ("lxrdp_end:"));
- return 0;
-}
-
-/******************************************************************************/
-/* return error */
-static int DEFAULT_CC
-lxrdp_set_param(struct mod *mod, char *name, char *value)
-{
- rdpSettings *settings;
-
- LLOGLN(10, ("lxrdp_set_param: name [%s] value [%s]", name, value));
- settings = mod->inst->settings;
-
- LLOGLN(10, ("%p %d", settings->ServerHostname, settings->DisableEncryption));
-
- if (g_strcmp(name, "hostname") == 0)
- {
- }
- else if (g_strcmp(name, "ip") == 0)
- {
- settings->ServerHostname = g_strdup(value);
- }
- else if (g_strcmp(name, "port") == 0)
- {
- settings->ServerPort = g_atoi(value);
- }
- else if (g_strcmp(name, "keylayout") == 0)
- {
- }
- else if (g_strcmp(name, "name") == 0)
- {
- }
- else if (g_strcmp(name, "lib") == 0)
- {
- }
- else if (g_strcmp(name, "username") == 0)
- {
- g_strncpy(mod->username, value, 255);
- }
- else if (g_strcmp(name, "password") == 0)
- {
- g_strncpy(mod->password, value, 255);
- }
- else if (g_strcmp(name, "client_info") == 0)
- {
- g_memcpy(&(mod->client_info), value, sizeof(mod->client_info));
- /* This is a Struct and cannot be printed in next else*/
- LLOGLN(10, ("Client_info struct ignored"));
- }
- else
- {
- LLOGLN(0, ("lxrdp_set_param: unknown name [%s] value [%s]", name, value));
- }
-
- return 0;
-}
-
-/******************************************************************************/
-static int DEFAULT_CC
-lxrdp_session_change(struct mod *mod, int a, int b)
-{
- LLOGLN(0, ("lxrdp_session_change: - no code here"));
- return 0;
-}
-
-/******************************************************************************/
-static int DEFAULT_CC
-lxrdp_get_wait_objs(struct mod *mod, tbus *read_objs, int *rcount,
- tbus *write_objs, int *wcount, int *timeout)
-{
- void **rfds;
- void **wfds;
- BOOL ok;
-
- LLOGLN(12, ("lxrdp_get_wait_objs:"));
- rfds = (void **)read_objs;
- wfds = (void **)write_objs;
- ok = freerdp_get_fds(mod->inst, rfds, rcount, wfds, wcount);
-
- if (!ok)
- {
- LLOGLN(0, ("lxrdp_get_wait_objs: freerdp_get_fds failed"));
- return 1;
- }
-
- return 0;
-}
-
-/******************************************************************************/
-static int DEFAULT_CC
-lxrdp_check_wait_objs(struct mod *mod)
-{
- BOOL ok;
-
- LLOGLN(12, ("lxrdp_check_wait_objs:"));
- ok = freerdp_check_fds(mod->inst);
-
- if (!ok)
- {
- LLOGLN(0, ("lxrdp_check_wait_objs: freerdp_check_fds failed"));
- return 1;
- }
-
- return 0;
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-lfreerdp_begin_paint(rdpContext *context)
-{
- struct mod *mod;
-
- LLOGLN(10, ("lfreerdp_begin_paint:"));
- mod = ((struct mod_context *)context)->modi;
- mod->server_begin_update(mod);
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-lfreerdp_end_paint(rdpContext *context)
-{
- struct mod *mod;
-
- LLOGLN(10, ("lfreerdp_end_paint:"));
- mod = ((struct mod_context *)context)->modi;
- mod->server_end_update(mod);
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-lfreerdp_set_bounds(rdpContext *context, rdpBounds *bounds)
-{
- struct mod *mod;
- int x;
- int y;
- int cx;
- int cy;
-
- LLOGLN(10, ("lfreerdp_set_bounds: %p", bounds));
- mod = ((struct mod_context *)context)->modi;
-
- if (bounds != 0)
- {
- x = bounds->left;
- y = bounds->top;
- cx = (bounds->right - bounds->left) + 1;
- cy = (bounds->bottom - bounds->top) + 1;
- mod->server_set_clip(mod, x, y, cx, cy);
- }
- else
- {
- mod->server_reset_clip(mod);
- }
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-lfreerdp_bitmap_update(rdpContext *context, BITMAP_UPDATE *bitmap)
-{
- struct mod *mod;
- int index;
- int cx;
- int cy;
- int server_bpp;
- int server_Bpp;
- int client_bpp;
- int j;
- int line_bytes;
- BITMAP_DATA *bd;
- char *dst_data;
- char *dst_data1;
- char *src;
- char *dst;
-
- mod = ((struct mod_context *)context)->modi;
- LLOGLN(10, ("lfreerdp_bitmap_update: %d %d", bitmap->number, bitmap->count));
-
- server_bpp = mod->inst->settings->ColorDepth;
- server_Bpp = (server_bpp + 7) / 8;
- client_bpp = mod->bpp;
-
- for (index = 0; index < bitmap->number; index++)
- {
- bd = &bitmap->rectangles[index];
- cx = (bd->destRight - bd->destLeft) + 1;
- cy = (bd->destBottom - bd->destTop) + 1;
- line_bytes = server_Bpp * bd->width;
- dst_data = (char *)g_malloc(bd->height * line_bytes + 16, 0);
-
- if (bd->compressed)
- {
- LLOGLN(20,("decompress size : %d",bd->bitmapLength));
- if(!bitmap_decompress(bd->bitmapDataStream, (tui8 *)dst_data, bd->width,
- bd->height, bd->bitmapLength, server_bpp, server_bpp)){
- LLOGLN(0,("Failure to decompress the bitmap"));
- }
- }
- else
- {
- /* bitmap is upside down */
- LLOGLN(10,("bitmap upside down"));
- src = (char *)(bd->bitmapDataStream);
- dst = dst_data + bd->height * line_bytes;
-
- for (j = 0; j < bd->height; j++)
- {
- dst -= line_bytes;
- g_memcpy(dst, src, line_bytes);
- src += line_bytes;
- }
- }
-
- dst_data1 = convert_bitmap(server_bpp, client_bpp, dst_data,
- bd->width, bd->height, mod->colormap);
- mod->server_paint_rect(mod, bd->destLeft, bd->destTop, cx, cy,
- dst_data1, bd->width, bd->height, 0, 0);
-
- if (dst_data1 != dst_data)
- {
- g_free(dst_data1);
- }
-
- g_free(dst_data);
- }
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-lfreerdp_dst_blt(rdpContext *context, DSTBLT_ORDER *dstblt)
-{
- struct mod *mod;
-
- mod = ((struct mod_context *)context)->modi;
- LLOGLN(10, ("lfreerdp_dst_blt:"));
- mod->server_set_opcode(mod, dstblt->bRop);
- mod->server_fill_rect(mod, dstblt->nLeftRect, dstblt->nTopRect,
- dstblt->nWidth, dstblt->nHeight);
- mod->server_set_opcode(mod, 0xcc);
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-lfreerdp_pat_blt(rdpContext *context, PATBLT_ORDER *patblt)
-{
- struct mod *mod;
- int idx;
- int fgcolor;
- int bgcolor;
- int server_bpp;
- int client_bpp;
- struct brush_item *bi;
-
- mod = ((struct mod_context *)context)->modi;
- LLOGLN(10, ("lfreerdp_pat_blt:"));
-
- server_bpp = mod->inst->settings->ColorDepth;
- client_bpp = mod->bpp;
- LLOGLN(0, ("lfreerdp_pat_blt: bpp %d %d", server_bpp, client_bpp));
-
- fgcolor = convert_color(server_bpp, client_bpp,
- patblt->foreColor, mod->colormap);
- bgcolor = convert_color(server_bpp, client_bpp,
- patblt->backColor, mod->colormap);
-
- if(fgcolor==bgcolor)
- {
- LLOGLN(0, ("Warning same color on both bg and fg"));
- }
- mod->server_set_mixmode(mod, 1);
- mod->server_set_opcode(mod, patblt->bRop);
- mod->server_set_fgcolor(mod, fgcolor);
- mod->server_set_bgcolor(mod, bgcolor);
-
- if (patblt->brush.style & 0x80)
- {
- idx = patblt->brush.hatch;
-
- if ((idx < 0) || (idx >= 64))
- {
- LLOGLN(0, ("lfreerdp_pat_blt: error"));
- return;
- }
-
- bi = mod->brush_cache + idx;
- mod->server_set_brush(mod, patblt->brush.x, patblt->brush.y,
- 3, bi->b8x8);
- }
- else
- {
- mod->server_set_brush(mod, patblt->brush.x, patblt->brush.y,
- patblt->brush.style,
- (char *)(patblt->brush.p8x8));
- }
-
- mod->server_fill_rect(mod, patblt->nLeftRect, patblt->nTopRect,
- patblt->nWidth, patblt->nHeight);
- mod->server_set_opcode(mod, 0xcc);
- mod->server_set_mixmode(mod, 0);
-
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-lfreerdp_scr_blt(rdpContext *context, SCRBLT_ORDER *scrblt)
-{
- struct mod *mod;
-
- mod = ((struct mod_context *)context)->modi;
- LLOGLN(10, ("lfreerdp_scr_blt:"));
- mod->server_set_opcode(mod, scrblt->bRop);
- mod->server_screen_blt(mod, scrblt->nLeftRect, scrblt->nTopRect,
- scrblt->nWidth, scrblt->nHeight,
- scrblt->nXSrc, scrblt->nYSrc);
- mod->server_set_opcode(mod, 0xcc);
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-lfreerdp_opaque_rect(rdpContext *context, OPAQUE_RECT_ORDER *opaque_rect)
-{
- struct mod *mod;
- int server_bpp;
- int client_bpp;
- int fgcolor;
-
- mod = ((struct mod_context *)context)->modi;
- LLOGLN(10, ("lfreerdp_opaque_rect:"));
- server_bpp = mod->inst->settings->ColorDepth;
- client_bpp = mod->bpp;
- fgcolor = convert_color(server_bpp, client_bpp,
- opaque_rect->color, mod->colormap);
- mod->server_set_fgcolor(mod, fgcolor);
- mod->server_fill_rect(mod, opaque_rect->nLeftRect, opaque_rect->nTopRect,
- opaque_rect->nWidth, opaque_rect->nHeight);
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-lfreerdp_mem_blt(rdpContext *context, MEMBLT_ORDER *memblt)
-{
- int id;
- int idx;
- struct mod *mod;
- struct bitmap_item *bi;
-
- mod = ((struct mod_context *)context)->modi;
- LLOGLN(10, ("lfreerdp_mem_blt: cacheId %d cacheIndex %d",
- memblt->cacheId, memblt->cacheIndex));
-
- id = memblt->cacheId;
- idx = memblt->cacheIndex;
-
- if (idx == 32767) /* BITMAPCACHE_WAITING_LIST_INDEX */
- {
- idx = 4096 - 1;
- }
-
- if ((id < 0) || (id >= 4))
- {
- LLOGLN(0, ("lfreerdp_mem_blt: bad id [%d]", id));
- return;
- }
-
- if ((idx < 0) || (idx >= 4096))
- {
- LLOGLN(0, ("lfreerdp_mem_blt: bad idx [%d]", idx));
- return;
- }
-
- bi = &(mod->bitmap_cache[id][idx]);
-
- mod->server_set_opcode(mod, memblt->bRop);
- mod->server_paint_rect(mod, memblt->nLeftRect, memblt->nTopRect,
- memblt->nWidth, memblt->nHeight,
- bi->data, bi->width, bi->height,
- memblt->nXSrc, memblt->nYSrc);
- mod->server_set_opcode(mod, 0xcc);
-
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-lfreerdp_glyph_index(rdpContext *context, GLYPH_INDEX_ORDER *glyph_index)
-{
- struct mod *mod;
- int server_bpp;
- int client_bpp;
- int fgcolor;
- int bgcolor;
-
- mod = ((struct mod_context *)context)->modi;
- LLOGLN(10, ("lfreerdp_glyph_index:"));
- server_bpp = mod->inst->settings->ColorDepth;
- client_bpp = mod->bpp;
- fgcolor = convert_color(server_bpp, client_bpp,
- glyph_index->foreColor, mod->colormap);
- bgcolor = convert_color(server_bpp, client_bpp,
- glyph_index->backColor, mod->colormap);
- mod->server_set_bgcolor(mod, fgcolor);
- mod->server_set_fgcolor(mod, bgcolor);
- mod->server_draw_text(mod, glyph_index->cacheId, glyph_index->flAccel,
- glyph_index->fOpRedundant,
- glyph_index->bkLeft, glyph_index->bkTop,
- glyph_index->bkRight, glyph_index->bkBottom,
- glyph_index->opLeft, glyph_index->opTop,
- glyph_index->opRight, glyph_index->opBottom,
- glyph_index->x, glyph_index->y,
- (char *)(glyph_index->data), glyph_index->cbData);
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-lfreerdp_line_to(rdpContext *context, LINE_TO_ORDER *line_to)
-{
- struct mod *mod;
- int server_bpp;
- int client_bpp;
- int fgcolor;
- int bgcolor;
-
- mod = ((struct mod_context *)context)->modi;
- LLOGLN(10, ("lfreerdp_line_to:"));
- mod->server_set_opcode(mod, line_to->bRop2);
- server_bpp = mod->inst->settings->ColorDepth;
- client_bpp = mod->bpp;
- fgcolor = convert_color(server_bpp, client_bpp,
- line_to->penColor, mod->colormap);
- bgcolor = convert_color(server_bpp, client_bpp,
- line_to->backColor, mod->colormap);
- mod->server_set_fgcolor(mod, fgcolor);
- mod->server_set_bgcolor(mod, bgcolor);
- mod->server_set_pen(mod, line_to->penStyle, line_to->penWidth);
- mod->server_draw_line(mod, line_to->nXStart, line_to->nYStart,
- line_to->nXEnd, line_to->nYEnd);
- mod->server_set_opcode(mod, 0xcc);
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-lfreerdp_cache_bitmap(rdpContext *context, CACHE_BITMAP_ORDER *cache_bitmap_order)
-{
- LLOGLN(0, ("lfreerdp_cache_bitmap: - no code here"));
-}
-
-/******************************************************************************/
-/* Turn the bitmap upside down*/
-static void DEFAULT_CC
-lfreerdp_upsidedown(UINT8 *destination, CACHE_BITMAP_V2_ORDER *cache_bitmap_v2_order, int server_Bpp)
-{
- tui8 *src;
- tui8 *dst;
- int line_bytes;
- int j;
-
- if (destination == NULL)
- {
- LLOGLN(0, ("lfreerdp_upsidedown: destination pointer is NULL !!!"));
- return;
- }
-
- line_bytes = server_Bpp * cache_bitmap_v2_order->bitmapWidth;
- src = cache_bitmap_v2_order->bitmapDataStream;
- dst = destination + ((cache_bitmap_v2_order->bitmapHeight) * line_bytes);
-
- for (j = 0; j < cache_bitmap_v2_order->bitmapHeight; j++)
- {
- dst -= line_bytes;
- g_memcpy(dst, src, line_bytes);
- src += line_bytes;
- }
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-lfreerdp_cache_bitmapV2(rdpContext *context,
- CACHE_BITMAP_V2_ORDER *cache_bitmap_v2_order)
-{
- char *dst_data;
- char *dst_data1;
- int bytes;
- int width;
- int height;
- int id;
- int idx;
- int flags;
- int server_bpp;
- int server_Bpp;
- int client_bpp;
- struct mod *mod;
-
- LLOGLN(10, ("lfreerdp_cache_bitmapV2: %d %d 0x%8.8x compressed %d",
- cache_bitmap_v2_order->cacheId,
- cache_bitmap_v2_order->cacheIndex,
- cache_bitmap_v2_order->flags,
- cache_bitmap_v2_order->compressed));
-
- mod = ((struct mod_context *)context)->modi;
- id = cache_bitmap_v2_order->cacheId;
- idx = cache_bitmap_v2_order->cacheIndex;
- flags = cache_bitmap_v2_order->flags;
-
- if (flags & 0x10) /* CBR2_DO_NOT_CACHE */
- {
- LLOGLN(0, ("lfreerdp_cache_bitmapV2: CBR2_DO_NOT_CACHE"));
- idx = 4096 - 1;
- }
-
- if ((id < 0) || (id >= 4))
- {
- LLOGLN(0, ("lfreerdp_cache_bitmapV2: bad id [%d]", id));
- return;
- }
-
- if ((idx < 0) || (idx >= 4096))
- {
- LLOGLN(0, ("lfreerdp_cache_bitmapV2: bad idx [%d]", idx));
- return;
- }
-
- server_bpp = mod->inst->settings->ColorDepth;
- server_Bpp = (server_bpp + 7) / 8;
- client_bpp = mod->bpp;
-
- width = cache_bitmap_v2_order->bitmapWidth;
- height = cache_bitmap_v2_order->bitmapHeight;
- bytes = width * height * server_Bpp + 16;
- dst_data = (char *)g_malloc(bytes, 0);
-
- if (cache_bitmap_v2_order->compressed)
- {
- bitmap_decompress(cache_bitmap_v2_order->bitmapDataStream,
- (tui8 *)dst_data, width, height,
- cache_bitmap_v2_order->bitmapLength,
- server_bpp, server_bpp);
- }
- else
- {
- /* Uncompressed bitmaps are upside down */
- lfreerdp_upsidedown((tui8 *)dst_data, cache_bitmap_v2_order, server_Bpp);
- LLOGLN(10, ("lfreerdp_cache_bitmapV2: upside down progressed"));
- }
-
- dst_data1 = convert_bitmap(server_bpp, client_bpp, dst_data,
- width, height, mod->colormap);
- g_free(mod->bitmap_cache[id][idx].data);
- mod->bitmap_cache[id][idx].width = width;
- mod->bitmap_cache[id][idx].height = height;
- mod->bitmap_cache[id][idx].data = dst_data1;
-
- if (dst_data != dst_data1)
- {
- g_free(dst_data);
- }
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-lfreerdp_cache_glyph(rdpContext *context, CACHE_GLYPH_ORDER *cache_glyph_order)
-{
- int index;
- GLYPH_DATA *gd;
- struct mod *mod;
-
- mod = ((struct mod_context *)context)->modi;
- LLOGLN(10, ("lfreerdp_cache_glyph: %d", cache_glyph_order->cGlyphs));
-
- for (index = 0; index < cache_glyph_order->cGlyphs; index++)
- {
- gd = cache_glyph_order->glyphData[index];
- LLOGLN(10, (" %d %d %d %d %d", gd->cacheIndex, gd->x, gd->y,
- gd->cx, gd->cy));
- mod->server_add_char(mod, cache_glyph_order->cacheId, gd->cacheIndex,
- gd->x, gd->y, gd->cx, gd->cy, (char *)(gd->aj));
- free(gd->aj);
- gd->aj = 0;
- free(gd);
- cache_glyph_order->glyphData[index] = 0;
- }
-
- free(cache_glyph_order->unicodeCharacters);
- cache_glyph_order->unicodeCharacters = 0;
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-lfreerdp_cache_brush(rdpContext *context, CACHE_BRUSH_ORDER *cache_brush_order)
-{
- int idx;
- int bytes;
- int bpp;
- int cx;
- int cy;
- struct mod *mod;
-
- mod = ((struct mod_context *)context)->modi;
- bpp = cache_brush_order->bpp;
- cx = cache_brush_order->cx;
- cy = cache_brush_order->cy;
- idx = cache_brush_order->index;
- bytes = cache_brush_order->length;
- LLOGLN(10, ("lfreerdp_cache_brush: bpp %d cx %d cy %d idx %d bytes %d",
- bpp, cx, cy, idx, bytes));
-
- if ((idx < 0) || (idx >= 64))
- {
- LLOGLN(0, ("lfreerdp_cache_brush: error idx %d", idx));
- return;
- }
-
- if ((bpp != 1) || (cx != 8) || (cy != 8))
- {
- LLOGLN(0, ("lfreerdp_cache_brush: error unsupported brush "
- "bpp %d cx %d cy %d", bpp, cx, cy));
- return;
- }
-
- mod->brush_cache[idx].bpp = bpp;
- mod->brush_cache[idx].width = cx;
- mod->brush_cache[idx].height = cy;
- mod->brush_cache[idx].data = mod->brush_cache[idx].b8x8;
-
- if (bytes > 8)
- {
- bytes = 8;
- }
-
- g_memset(mod->brush_cache[idx].data, 0, 8);
-
- if (bytes > 0)
- {
- if (bytes > 8)
- {
- LLOGLN(0, ("lfreerdp_cache_brush: bytes to big %d", bytes));
- bytes = 8;
- }
-
- g_memcpy(mod->brush_cache[idx].data, cache_brush_order->data, bytes);
- }
-
- LLOGLN(10, ("lfreerdp_cache_brush: out bpp %d cx %d cy %d idx %d bytes %d",
- bpp, cx, cy, idx, bytes));
-
- free(cache_brush_order->data);
- cache_brush_order->data = 0;
-
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-lfreerdp_pointer_position(rdpContext *context,
- POINTER_POSITION_UPDATE *pointer_position)
-{
- LLOGLN(0, ("lfreerdp_pointer_position: - no code here"));
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-lfreerdp_pointer_system(rdpContext *context,
- POINTER_SYSTEM_UPDATE *pointer_system)
-{
- LLOGLN(0, ("lfreerdp_pointer_system: - no code here type value = %d",pointer_system->type));
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-lfreerdp_pointer_color(rdpContext *context,
- POINTER_COLOR_UPDATE *pointer_color)
-{
- LLOGLN(0, ("lfreerdp_pointer_color: - no code here"));
-}
-
-/******************************************************************************/
-static int APP_CC
-lfreerdp_get_pixel(void *bits, int width, int height, int bpp,
- int delta, int x, int y)
-{
- int start;
- int shift;
- int pixel;
- tui8 *src8;
-
- if (bpp == 1)
- {
- src8 = (tui8 *)bits;
- start = (y * delta) + x / 8;
- shift = x % 8;
- pixel = (src8[start] & (0x80 >> shift)) != 0;
- return pixel ? 0xffffff : 0;
- }
- else
- {
- LLOGLN(0, ("lfreerdp_get_pixel: unknown bpp %d", bpp));
- }
-
- return 0;
-}
-
-/******************************************************************************/
-static int APP_CC
-lfreerdp_set_pixel(int pixel, void *bits, int width, int height, int bpp,
- int delta, int x, int y)
-{
- tui8 *dst8;
- int start;
- int shift;
-
- if (bpp == 1)
- {
- dst8 = (tui8 *)bits;
- start = (y * delta) + x / 8;
- shift = x % 8;
-
- if (pixel)
- {
- dst8[start] = dst8[start] | (0x80 >> shift);
- }
- else
- {
- dst8[start] = dst8[start] & ~(0x80 >> shift);
- }
- }
- else if (bpp == 24)
- {
- dst8 = (tui8 *)bits;
- dst8 += y * delta + x * 3;
- dst8[0] = (pixel >> 0) & 0xff;
- dst8[1] = (pixel >> 8) & 0xff;
- dst8[2] = (pixel >> 16) & 0xff;
- }
- else
- {
- LLOGLN(0, ("lfreerdp_set_pixel: unknown bpp %d", bpp));
- }
-
- return 0;
-}
-
-/******************************************************************************/
-static int APP_CC
-lfreerdp_convert_color_image(void *dst, int dst_width, int dst_height,
- int dst_bpp, int dst_delta,
- void *src, int src_width, int src_height,
- int src_bpp, int src_delta)
-{
- int i;
- int j;
- int pixel;
-
- for (j = 0; j < dst_height; j++)
- {
- for (i = 0; i < dst_width; i++)
- {
- pixel = lfreerdp_get_pixel(src, src_width, src_height, src_bpp,
- src_delta, i, j);
- lfreerdp_set_pixel(pixel, dst, dst_width, dst_height, dst_bpp,
- dst_delta, i, j);
- }
- }
-
- return 0;
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-lfreerdp_pointer_new(rdpContext *context,
- POINTER_NEW_UPDATE *pointer_new)
-{
- struct mod *mod;
- int index;
- tui8 *dst;
- tui8 *src;
-
- mod = ((struct mod_context *)context)->modi;
- LLOGLN(20, ("lfreerdp_pointer_new:"));
- LLOGLN(20, (" bpp %d", pointer_new->xorBpp));
- LLOGLN(20, (" width %d height %d", pointer_new->colorPtrAttr.width,
- pointer_new->colorPtrAttr.height));
-
- LLOGLN(20, (" lengthXorMask %d lengthAndMask %d",
- pointer_new->colorPtrAttr.lengthXorMask,
- pointer_new->colorPtrAttr.lengthAndMask));
-
- index = pointer_new->colorPtrAttr.cacheIndex;
- if(index>=32)
- {
- LLOGLN(0,("pointer index too big"));
- return ;
- }
- // In this fix we remove the xorBpp check, even if
- // the mouse pointers are not correct we can use them.
- // Configure your destination not to use windows Aero as pointer scheme
- else if ( // pointer_new->xorBpp == 1 &&
- pointer_new->colorPtrAttr.width == 32 &&
- pointer_new->colorPtrAttr.height == 32 &&
- index < 32)
- {
- mod->pointer_cache[index].hotx = pointer_new->colorPtrAttr.xPos;
- mod->pointer_cache[index].hoty = pointer_new->colorPtrAttr.yPos;
-
- dst = (tui8 *)(mod->pointer_cache[index].data);
- dst += 32 * 32 * 3 - 32 * 3;
- src = pointer_new->colorPtrAttr.xorMaskData;
- lfreerdp_convert_color_image(dst, 32, 32, 24, 32 * -3,
- src, 32, 32, 1, 32 / 8);
-
- dst = (tui8 *)(mod->pointer_cache[index].mask);
- dst += ( 32 * 32 / 8) - (32 / 8);
- src = pointer_new->colorPtrAttr.andMaskData;
- lfreerdp_convert_color_image(dst, 32, 32, 1, 32 / -8,
- src, 32, 32, 1, 32 / 8);
-
- //memcpy(mod->pointer_cache[index].mask,
- // pointer_new->colorPtrAttr.andMaskData, 32 * 32 / 8);
-
- mod->server_set_pointer(mod, mod->pointer_cache[index].hotx,
- mod->pointer_cache[index].hoty, mod->pointer_cache[index].data,
- mod->pointer_cache[index].mask);
- }
- else
- {
- LLOGLN(0, ("lfreerdp_pointer_new: error bpp %d width %d height %d index: %d",
- pointer_new->xorBpp, pointer_new->colorPtrAttr.width,
- pointer_new->colorPtrAttr.height,index));
- }
-
- free(pointer_new->colorPtrAttr.xorMaskData);
- pointer_new->colorPtrAttr.xorMaskData = 0;
- free(pointer_new->colorPtrAttr.andMaskData);
- pointer_new->colorPtrAttr.andMaskData = 0;
-
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-lfreerdp_pointer_cached(rdpContext *context,
- POINTER_CACHED_UPDATE *pointer_cached)
-{
- struct mod *mod;
- int index;
-
- mod = ((struct mod_context *)context)->modi;
- index = pointer_cached->cacheIndex;
- LLOGLN(10, ("lfreerdp_pointer_cached:%d", index));
- mod->server_set_pointer(mod, mod->pointer_cache[index].hotx,
- mod->pointer_cache[index].hoty, mod->pointer_cache[index].data,
- mod->pointer_cache[index].mask);
-}
-
-static void DEFAULT_CC lfreerdp_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb)
-{
- LLOGLN(0, ("lfreerdp_polygon_sc called:- not supported!!!!!!!!!!!!!!!!!!!!"));
-}
-
-static void DEFAULT_CC lfreerdp_polygon_sc(rdpContext* context, POLYGON_SC_ORDER* polygon_sc)
-{
- struct mod *mod;
- int i, npoints;
- XPoint points[4];
- int fgcolor;
- int server_bpp, client_bpp;
-
- mod = ((struct mod_context *)context)->modi;
- LLOGLN(10, ("lfreerdp_polygon_sc :%d(points) %d(color) %d(fillmode) %d(bRop) %d(cbData) %d(x) %d(y)", polygon_sc->numPoints,polygon_sc->brushColor,polygon_sc->fillMode,polygon_sc->bRop2,polygon_sc->cbData,polygon_sc->xStart,polygon_sc->yStart));
- if(polygon_sc->numPoints==3)
- {
- server_bpp = mod->inst->settings->ColorDepth;
- client_bpp = mod->bpp;
-
- points[0].x = polygon_sc->xStart;
- points[0].y = polygon_sc->yStart;
-
- for (i = 0; i < polygon_sc->numPoints; i++)
- {
- points[i + 1].x = polygon_sc->points[i].x;
- points[i + 1].y = polygon_sc->points[i].y;
- }
- fgcolor = convert_color(server_bpp, client_bpp,
- polygon_sc->brushColor, mod->colormap);
-
- mod->server_set_opcode(mod, polygon_sc->bRop2);
- mod->server_set_bgcolor(mod, 255);
- mod->server_set_fgcolor(mod, fgcolor);
- mod->server_set_pen(mod, 1, 1); // style, width
- // TODO replace with correct brush; this is a workaround
- // This workaround handles the text cursor in microsoft word.
- mod->server_draw_line(mod,polygon_sc->xStart,polygon_sc->yStart,polygon_sc->xStart,polygon_sc->yStart+points[2].y);
-// mod->server_fill_rect(mod, points[0].x, points[0].y,
-// points[0].x-points[3].x, points[0].y-points[2].y);
-// mod->server_set_brush(mod,); // howto use this on our indata??
- mod->server_set_opcode(mod, 0xcc);
- }
- else
- {
- LLOGLN(0, ("Not handled number of points in lfreerdp_polygon_sc"));
- }
-}
-
-static void DEFAULT_CC lfreerdp_syncronize(rdpContext* context)
-{
- struct mod *mod;
- mod = ((struct mod_context *)context)->modi;
- LLOGLN(0, ("lfreerdp_synchronize received - not handled"));
-}
-
-/******************************************************************************/
-static BOOL DEFAULT_CC
-lfreerdp_pre_connect(freerdp *instance)
-{
- struct mod *mod;
- int index;
- int error;
- int num_chans;
- int ch_flags;
- char ch_name[256];
- char *dst_ch_name;
-
- LLOGLN(0, ("lfreerdp_pre_connect:"));
- mod = ((struct mod_context *)(instance->context))->modi;
- verifyColorMap(mod);
- num_chans = 0;
- index = 0;
- error = mod->server_query_channel(mod, index, ch_name, &ch_flags);
-
- while (error == 0)
- {
- num_chans++;
- LLOGLN(10, ("lfreerdp_pre_connect: got channel [%s], flags [0x%8.8x]",
- ch_name, ch_flags));
- dst_ch_name = instance->settings->ChannelDefArray[index].Name;
- g_memset(dst_ch_name, 0, 8);
- g_snprintf(dst_ch_name, 8, "%s", ch_name);
- instance->settings->ChannelDefArray[index].options = ch_flags;
- index++;
- error = mod->server_query_channel(mod, index, ch_name, &ch_flags);
- }
-
- instance->settings->ChannelCount = num_chans;
-
- // TODO
- // instance->settings->offscreen_bitmap_cache = false;
- instance->settings->OffscreenSupportLevel = 0;
- instance->settings->DrawNineGridEnabled = 0 ;
-
- // TODO
- //instance->settings->glyph_cache = true;
- instance->settings->GlyphSupportLevel = GLYPH_SUPPORT_FULL;
- instance->settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = TRUE;
- instance->settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = FALSE;
- instance->settings->OrderSupport[NEG_FAST_INDEX_INDEX] = FALSE;
- instance->settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE;
- instance->settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE;
-
- instance->settings->BitmapCacheEnabled = TRUE;
- instance->settings->OrderSupport[NEG_MEMBLT_INDEX] = TRUE;
- instance->settings->OrderSupport[NEG_MEMBLT_V2_INDEX] = TRUE;
- instance->settings->OrderSupport[NEG_MEM3BLT_INDEX] = FALSE;
- instance->settings->OrderSupport[NEG_MEM3BLT_V2_INDEX] = FALSE;
- instance->settings->BitmapCacheV2NumCells = 3; // 5;
- instance->settings->BitmapCacheV2CellInfo[0].numEntries = 0x78; // 600;
- instance->settings->BitmapCacheV2CellInfo[0].persistent = FALSE;
- instance->settings->BitmapCacheV2CellInfo[1].numEntries = 0x78; // 600;
- instance->settings->BitmapCacheV2CellInfo[1].persistent = FALSE;
- instance->settings->BitmapCacheV2CellInfo[2].numEntries = 0x150; // 2048;
- instance->settings->BitmapCacheV2CellInfo[2].persistent = FALSE;
- instance->settings->BitmapCacheV2CellInfo[3].numEntries = 0; // 4096;
- instance->settings->BitmapCacheV2CellInfo[3].persistent = FALSE;
- instance->settings->BitmapCacheV2CellInfo[4].numEntries = 0; // 2048;
- instance->settings->BitmapCacheV2CellInfo[4].persistent = FALSE;
-
- // instance->settings->BitmapCacheV3Enabled = FALSE;
- instance->settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE;
- instance->settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE;
- instance->settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE;
- instance->settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = FALSE;
- instance->settings->OrderSupport[NEG_POLYLINE_INDEX] = FALSE;
-
- instance->settings->Username = g_strdup(mod->username);
- instance->settings->Password = g_strdup(mod->password);
-
- if (mod->client_info.rail_support_level > 0)
- {
- LLOGLN(0, ("Railsupport !!!!!!!!!!!!!!!!!!"));
- instance->settings->RemoteApplicationMode = TRUE;
- instance->settings->RemoteAppLanguageBarSupported = TRUE;
- instance->settings->Workarea = TRUE;
- instance->settings->PerformanceFlags = PERF_DISABLE_WALLPAPER | PERF_DISABLE_FULLWINDOWDRAG;
- }
- else
- {
- LLOGLN(10, ("Special PerformanceFlags changed"));
- instance->settings->PerformanceFlags = PERF_DISABLE_WALLPAPER | PERF_DISABLE_FULLWINDOWDRAG | PERF_DISABLE_MENUANIMATIONS | PERF_DISABLE_THEMING ; // | PERF_DISABLE_CURSOR_SHADOW | PERF_DISABLE_CURSORSETTINGS ;
- }
- instance->settings->CompressionEnabled = FALSE ;
- instance->settings->IgnoreCertificate = TRUE ;
-
- // here
- //instance->settings->RdpVersion = 4;
-
- instance->update->BeginPaint = lfreerdp_begin_paint;
- instance->update->EndPaint = lfreerdp_end_paint;
- instance->update->SetBounds = lfreerdp_set_bounds;
- instance->update->BitmapUpdate = lfreerdp_bitmap_update;
- instance->update->Synchronize = lfreerdp_syncronize ;
- instance->update->primary->DstBlt = lfreerdp_dst_blt;
- instance->update->primary->PatBlt = lfreerdp_pat_blt;
- instance->update->primary->ScrBlt = lfreerdp_scr_blt;
- instance->update->primary->OpaqueRect = lfreerdp_opaque_rect;
- instance->update->primary->MemBlt = lfreerdp_mem_blt;
- instance->update->primary->GlyphIndex = lfreerdp_glyph_index;
- instance->update->primary->LineTo = lfreerdp_line_to;
- instance->update->primary->PolygonSC = lfreerdp_polygon_sc ;
- instance->update->primary->PolygonCB = lfreerdp_polygon_cb;
- instance->update->secondary->CacheBitmap = lfreerdp_cache_bitmap;
- instance->update->secondary->CacheBitmapV2 = lfreerdp_cache_bitmapV2;
- instance->update->secondary->CacheGlyph = lfreerdp_cache_glyph;
- instance->update->secondary->CacheBrush = lfreerdp_cache_brush;
-
- instance->update->pointer->PointerPosition = lfreerdp_pointer_position;
- instance->update->pointer->PointerSystem = lfreerdp_pointer_system;
- instance->update->pointer->PointerColor = lfreerdp_pointer_color;
- instance->update->pointer->PointerNew = lfreerdp_pointer_new;
- instance->update->pointer->PointerCached = lfreerdp_pointer_cached;
-
- if ((mod->username[0] != 0) && (mod->password[0] != 0))
- {
- /* since we have username and password, we can try nla */
- instance->settings->NlaSecurity = 1;
- }
- else
- {
- instance->settings->NlaSecurity = 0;
- }
-
- return TRUE;
-}
-
-/*****************************************************************************/
-void DEFAULT_CC
-lrail_WindowCreate(rdpContext *context, WINDOW_ORDER_INFO *orderInfo,
- WINDOW_STATE_ORDER *window_state)
-{
- int index;
- struct mod *mod;
- struct rail_window_state_order wso;
-
- LLOGLN(0, ("llrail_WindowCreate:"));
- mod = ((struct mod_context *)context)->modi;
- memset(&wso, 0, sizeof(wso));
- /* copy the window state order */
- wso.owner_window_id = window_state->ownerWindowId;
- wso.style = window_state->style;
- wso.extended_style = window_state->extendedStyle;
- wso.show_state = window_state->showState;
-
- if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TITLE)
- {
- freerdp_UnicodeToAsciiAlloc(window_state->titleInfo.string, &wso.title_info, window_state->titleInfo.length / 2);
- }
-
- LLOGLN(0, ("lrail_WindowCreate: %s", wso.title_info));
- wso.client_offset_x = window_state->clientOffsetX;
- wso.client_offset_y = window_state->clientOffsetY;
- wso.client_area_width = window_state->clientAreaWidth;
- wso.client_area_height = window_state->clientAreaHeight;
- wso.rp_content = window_state->RPContent;
- wso.root_parent_handle = window_state->rootParentHandle;
- wso.window_offset_x = window_state->windowOffsetX;
- wso.window_offset_y = window_state->windowOffsetY;
- wso.window_client_delta_x = window_state->windowClientDeltaX;
- wso.window_client_delta_y = window_state->windowClientDeltaY;
- wso.window_width = window_state->windowWidth;
- wso.window_height = window_state->windowHeight;
- wso.num_window_rects = window_state->numWindowRects;
-
- if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS)
- {
- wso.window_rects = (struct rail_window_rect *)
- g_malloc(sizeof(struct rail_window_rect) * wso.num_window_rects, 0);
-
- for (index = 0; index < wso.num_window_rects; index++)
- {
- wso.window_rects[index].left = window_state->windowRects[index].left;
- wso.window_rects[index].top = window_state->windowRects[index].top;
- wso.window_rects[index].right = window_state->windowRects[index].right;
- wso.window_rects[index].bottom = window_state->windowRects[index].bottom;
- }
- }
-
- wso.visible_offset_x = window_state->visibleOffsetX;
- wso.visible_offset_y = window_state->visibleOffsetY;
- wso.num_visibility_rects = window_state->numVisibilityRects;
-
- if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY)
- {
- wso.visibility_rects = (struct rail_window_rect *)
- g_malloc(sizeof(struct rail_window_rect) * wso.num_visibility_rects, 0);
-
- for (index = 0; index < wso.num_visibility_rects; index++)
- {
- wso.visibility_rects[index].left = window_state->visibilityRects[index].left;
- wso.visibility_rects[index].top = window_state->visibilityRects[index].top;
- wso.visibility_rects[index].right = window_state->visibilityRects[index].right;
- wso.visibility_rects[index].bottom = window_state->visibilityRects[index].bottom;
- }
- }
-
- mod->server_window_new_update(mod, orderInfo->windowId, &wso,
- orderInfo->fieldFlags);
-
- free(wso.title_info);
- g_free(wso.window_rects);
- g_free(wso.visibility_rects);
-}
-
-/*****************************************************************************/
-void DEFAULT_CC
-lrail_WindowUpdate(rdpContext *context, WINDOW_ORDER_INFO *orderInfo,
- WINDOW_STATE_ORDER *window_state)
-{
- LLOGLN(0, ("lrail_WindowUpdate:"));
- lrail_WindowCreate(context, orderInfo, window_state);
-}
-
-/*****************************************************************************/
-void DEFAULT_CC
-lrail_WindowDelete(rdpContext *context, WINDOW_ORDER_INFO *orderInfo)
-{
- struct mod *mod;
-
- LLOGLN(0, ("lrail_WindowDelete:"));
- mod = ((struct mod_context *)context)->modi;
- mod->server_window_delete(mod, orderInfo->windowId);
-}
-
-/*****************************************************************************/
-void DEFAULT_CC
-lrail_WindowIcon(rdpContext *context, WINDOW_ORDER_INFO *orderInfo,
- WINDOW_ICON_ORDER *window_icon)
-{
- struct mod *mod;
- struct rail_icon_info rii;
-
- LLOGLN(0, ("lrail_WindowIcon:"));
- mod = ((struct mod_context *)context)->modi;
- memset(&rii, 0, sizeof(rii));
- rii.bpp = window_icon->iconInfo->bpp;
- rii.width = window_icon->iconInfo->width;
- rii.height = window_icon->iconInfo->height;
- rii.cmap_bytes = window_icon->iconInfo->cbColorTable;
- rii.mask_bytes = window_icon->iconInfo->cbBitsMask;
- rii.data_bytes = window_icon->iconInfo->cbBitsColor;
- rii.mask = (char *)(window_icon->iconInfo->bitsMask);
- rii.cmap = (char *)(window_icon->iconInfo->colorTable);
- rii.data = (char *)(window_icon->iconInfo->bitsColor);
- mod->server_window_icon(mod, orderInfo->windowId,
- window_icon->iconInfo->cacheEntry,
- window_icon->iconInfo->cacheId, &rii,
- orderInfo->fieldFlags);
-}
-
-/*****************************************************************************/
-void DEFAULT_CC
-lrail_WindowCachedIcon(rdpContext *context, WINDOW_ORDER_INFO *orderInfo,
- WINDOW_CACHED_ICON_ORDER *window_cached_icon)
-{
- struct mod *mod;
-
- LLOGLN(0, ("lrail_WindowCachedIcon:"));
- mod = ((struct mod_context *)context)->modi;
- mod->server_window_cached_icon(mod, orderInfo->windowId,
- window_cached_icon->cachedIcon.cacheEntry,
- window_cached_icon->cachedIcon.cacheId,
- orderInfo->fieldFlags);
-}
-
-/*****************************************************************************/
-void DEFAULT_CC
-lrail_NotifyIconCreate(rdpContext *context, WINDOW_ORDER_INFO *orderInfo,
- NOTIFY_ICON_STATE_ORDER *notify_icon_state)
-{
- struct mod *mod;
- struct rail_notify_state_order rnso;
-
- LLOGLN(0, ("lrail_NotifyIconCreate:"));
-
- mod = ((struct mod_context *)context)->modi;
-
- memset(&rnso, 0, sizeof(rnso));
- rnso.version = notify_icon_state->version;
-
- if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_TIP)
- {
- freerdp_UnicodeToAsciiAlloc(notify_icon_state->toolTip.string,
- &rnso.tool_tip, notify_icon_state->toolTip.length / 2);
- }
-
- if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP)
- {
- rnso.infotip.timeout = notify_icon_state->infoTip.timeout;
- rnso.infotip.flags = notify_icon_state->infoTip.flags;
- freerdp_UnicodeToAsciiAlloc(notify_icon_state->infoTip.text.string,
- &rnso.infotip.text, notify_icon_state->infoTip.text.length / 2);
- freerdp_UnicodeToAsciiAlloc(notify_icon_state->infoTip.title.string,
- &rnso.infotip.title, notify_icon_state->infoTip.title.length / 2);
- }
-
- rnso.state = notify_icon_state->state;
- rnso.icon_cache_entry = notify_icon_state->icon.cacheEntry;
- rnso.icon_cache_id = notify_icon_state->icon.cacheId;
-
- rnso.icon_info.bpp = notify_icon_state->icon.bpp;
- rnso.icon_info.width = notify_icon_state->icon.width;
- rnso.icon_info.height = notify_icon_state->icon.height;
- rnso.icon_info.cmap_bytes = notify_icon_state->icon.cbColorTable;
- rnso.icon_info.mask_bytes = notify_icon_state->icon.cbBitsMask;
- rnso.icon_info.data_bytes = notify_icon_state->icon.cbBitsColor;
- rnso.icon_info.mask = (char *)(notify_icon_state->icon.bitsMask);
- rnso.icon_info.cmap = (char *)(notify_icon_state->icon.colorTable);
- rnso.icon_info.data = (char *)(notify_icon_state->icon.bitsColor);
-
- mod->server_notify_new_update(mod, orderInfo->windowId,
- orderInfo->notifyIconId,
- &rnso, orderInfo->fieldFlags);
-
- free(rnso.tool_tip);
- free(rnso.infotip.text);
- free(rnso.infotip.title);
-}
-
-/*****************************************************************************/
-void DEFAULT_CC
-lrail_NotifyIconUpdate(rdpContext *context, WINDOW_ORDER_INFO *orderInfo,
- NOTIFY_ICON_STATE_ORDER *notify_icon_state)
-{
- LLOGLN(0, ("lrail_NotifyIconUpdate:"));
- lrail_NotifyIconCreate(context, orderInfo, notify_icon_state);
-}
-
-/*****************************************************************************/
-void DEFAULT_CC
-lrail_NotifyIconDelete(rdpContext *context, WINDOW_ORDER_INFO *orderInfo)
-{
- struct mod *mod;
-
- LLOGLN(0, ("lrail_NotifyIconDelete:"));
- mod = ((struct mod_context *)context)->modi;
- mod->server_notify_delete(mod, orderInfo->windowId,
- orderInfo->notifyIconId);
-}
-
-/*****************************************************************************/
-void DEFAULT_CC
-lrail_MonitoredDesktop(rdpContext *context, WINDOW_ORDER_INFO *orderInfo,
- MONITORED_DESKTOP_ORDER *monitored_desktop)
-{
- int index;
- struct mod *mod;
- struct rail_monitored_desktop_order rmdo;
-
- LLOGLN(0, ("lrail_MonitoredDesktop:"));
- mod = ((struct mod_context *)context)->modi;
- memset(&rmdo, 0, sizeof(rmdo));
- rmdo.active_window_id = monitored_desktop->activeWindowId;
- rmdo.num_window_ids = monitored_desktop->numWindowIds;
-
- if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER)
- {
- if (rmdo.num_window_ids > 0)
- {
- rmdo.window_ids = (int *)g_malloc(sizeof(int) * rmdo.num_window_ids, 0);
-
- for (index = 0; index < rmdo.num_window_ids; index++)
- {
- rmdo.window_ids[index] = monitored_desktop->windowIds[index];
- }
- }
- }
-
- mod->server_monitored_desktop(mod, &rmdo, orderInfo->fieldFlags);
- g_free(rmdo.window_ids);
-}
-
-/*****************************************************************************/
-void DEFAULT_CC
-lrail_NonMonitoredDesktop(rdpContext *context, WINDOW_ORDER_INFO *orderInfo)
-{
- struct mod *mod;
- struct rail_monitored_desktop_order rmdo;
-
- LLOGLN(0, ("lrail_NonMonitoredDesktop:"));
- mod = ((struct mod_context *)context)->modi;
- memset(&rmdo, 0, sizeof(rmdo));
- mod->server_monitored_desktop(mod, &rmdo, orderInfo->fieldFlags);
-}
-
-/******************************************************************************/
-static BOOL DEFAULT_CC
-lfreerdp_post_connect(freerdp *instance)
-{
- struct mod *mod;
-
- LLOGLN(0, ("lfreerdp_post_connect:"));
- mod = ((struct mod_context *)(instance->context))->modi;
- g_memset(mod->password, 0, sizeof(mod->password));
-
- mod->inst->update->window->WindowCreate = lrail_WindowCreate;
- mod->inst->update->window->WindowUpdate = lrail_WindowUpdate;
- mod->inst->update->window->WindowDelete = lrail_WindowDelete;
- mod->inst->update->window->WindowIcon = lrail_WindowIcon;
- mod->inst->update->window->WindowCachedIcon = lrail_WindowCachedIcon;
- mod->inst->update->window->NotifyIconCreate = lrail_NotifyIconCreate;
- mod->inst->update->window->NotifyIconUpdate = lrail_NotifyIconUpdate;
- mod->inst->update->window->NotifyIconDelete = lrail_NotifyIconDelete;
- mod->inst->update->window->MonitoredDesktop = lrail_MonitoredDesktop;
- mod->inst->update->window->NonMonitoredDesktop = lrail_NonMonitoredDesktop;
-
- return TRUE;
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-lfreerdp_context_new(freerdp *instance, rdpContext *context)
-{
- LLOGLN(0, ("lfreerdp_context_new: %p", context));
-}
-
-/******************************************************************************/
-static void DEFAULT_CC
-lfreerdp_context_free(freerdp *instance, rdpContext *context)
-{
- LLOGLN(0, ("lfreerdp_context_free: - no code here"));
-}
-
-/******************************************************************************/
-static int DEFAULT_CC
-lfreerdp_receive_channel_data(freerdp *instance, int channelId, UINT8 *data,
- int size, int flags, int total_size)
-{
- struct mod *mod;
- int lchid;
- int index;
- int error;
-
- mod = ((struct mod_context *)(instance->context))->modi;
- lchid = -1;
-
- for (index = 0; index < instance->settings->ChannelDefArraySize; index++)
- {
- if (instance->settings->ChannelDefArray[index].ChannelId == channelId)
- {
- lchid = index;
- break;
- }
- }
-
- if (lchid >= 0)
- {
- LLOGLN(10, ("lfreerdp_receive_channel_data: server to client"));
- error = mod->server_send_to_channel(mod, lchid, (char *)data, size,
- total_size, flags);
-
- if (error != 0)
- {
- LLOGLN(0, ("lfreerdp_receive_channel_data: error %d", error));
- }
- }
- else
- {
- LLOGLN(0, ("lfreerdp_receive_channel_data: bad lchid"));
- }
-
- return 0;
-}
-
-/******************************************************************************/
-static BOOL DEFAULT_CC
-lfreerdp_authenticate(freerdp *instance, char **username,
- char **password, char **domain)
-{
- LLOGLN(0, ("lfreerdp_authenticate: - no code here"));
- return TRUE;
-}
-
-/******************************************************************************/
-static BOOL DEFAULT_CC
-lfreerdp_verify_certificate(freerdp *instance, char *subject, char *issuer,
- char *fingerprint)
-{
- LLOGLN(0, ("lfreerdp_verify_certificate: - no code here"));
- return TRUE;
-}
-
-/******************************************************************************/
-struct mod *EXPORT_CC
-mod_init(void)
-{
- struct mod *mod;
- modContext *lcon;
-
- LLOGLN(0, ("mod_init:"));
- mod = (struct mod *)g_malloc(sizeof(struct mod), 1);
- freerdp_get_version(&(mod->vmaj), &(mod->vmin), &(mod->vrev));
- LLOGLN(0, (" FreeRDP version major %d minor %d revision %d",
- mod->vmaj, mod->vmin, mod->vrev));
- mod->size = sizeof(struct mod);
- mod->version = CURRENT_MOD_VER;
- mod->handle = (tbus)mod;
- mod->mod_connect = lxrdp_connect;
- mod->mod_start = lxrdp_start;
- mod->mod_event = lxrdp_event;
- mod->mod_signal = lxrdp_signal;
- mod->mod_end = lxrdp_end;
- mod->mod_set_param = lxrdp_set_param;
- mod->mod_session_change = lxrdp_session_change;
- mod->mod_get_wait_objs = lxrdp_get_wait_objs;
- mod->mod_check_wait_objs = lxrdp_check_wait_objs;
-
- mod->inst = freerdp_new();
- mod->inst->PreConnect = lfreerdp_pre_connect;
- mod->inst->PostConnect = lfreerdp_post_connect;
- mod->inst->context_size = sizeof(modContext);
- mod->inst->ContextNew = lfreerdp_context_new;
- mod->inst->ContextFree = lfreerdp_context_free;
- mod->inst->ReceiveChannelData = lfreerdp_receive_channel_data;
- mod->inst->Authenticate = lfreerdp_authenticate;
- mod->inst->VerifyCertificate = lfreerdp_verify_certificate;
-
- freerdp_context_new(mod->inst);
-
- lcon = (modContext *)(mod->inst->context);
- lcon->modi = mod;
- LLOGLN(10, ("mod_init: mod %p", mod));
-
- return mod;
-}
-
-/******************************************************************************/
-int EXPORT_CC
-mod_exit(struct mod *mod)
-{
- LLOGLN(0, ("mod_exit:"));
-
- if (mod == 0)
- {
- return 0;
- }
-
- if (mod->inst == NULL)
- {
- LLOGLN(0, ("mod_exit - null pointer for inst:"));
- g_free(mod);
- return 0 ;
- }
-
- freerdp_disconnect(mod->inst);
-
- if ((mod->vmaj == 1) && (mod->vmin == 0) && (mod->vrev == 1))
- {
- /* this version has a bug with double free in freerdp_free */
- }
- else
- {
- freerdp_context_free(mod->inst);
- }
-
- freerdp_free(mod->inst);
- g_free(mod);
- return 0;
-}
diff --git a/freerdp1/xrdp-freerdp.h b/freerdp1/xrdp-freerdp.h
deleted file mode 100644
index c2956b4d..00000000
--- a/freerdp1/xrdp-freerdp.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/**
- * FreeRDP: A Remote Desktop Protocol Server
- * freerdp wrapper
- *
- * Copyright 2011-2012 Jay Sorg
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* include other h files */
-#include "arch.h"
-#include "parse.h"
-#include "os_calls.h"
-#include "defines.h"
-#include "xrdp_rail.h"
-#include "xrdp_client_info.h"
-
-/* this is the freerdp main header */
-#include <freerdp/freerdp.h>
-#include <freerdp/rail.h>
-#include <freerdp/rail/rail.h>
-#include <freerdp/codec/bitmap.h>
-//#include <freerdp/utils/memory.h>
-//#include "/home/jay/git/jsorg71/staging/include/freerdp/freerdp.h"
-
-struct bitmap_item
-{
- int width;
- int height;
- char* data;
-};
-
-struct brush_item
-{
- int bpp;
- int width;
- int height;
- char* data;
- char b8x8[8];
-};
-
-struct pointer_item
-{
- int hotx;
- int hoty;
- char data[32 * 32 * 3];
- char mask[32 * 32 / 8];
-};
-
-#define CURRENT_MOD_VER 2
-
-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, long param1, long param2,
- long param3, long 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);
- long 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_pointer)(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 total_data_len, int flags);
- int (*server_bell_trigger)(struct mod* v);
- /* off screen bitmaps */
- int (*server_create_os_surface)(struct mod* v, int rdpindex,
- int width, int height);
- int (*server_switch_os_surface)(struct mod* v, int rdpindex);
- int (*server_delete_os_surface)(struct mod* v, int rdpindex);
- int (*server_paint_rect_os)(struct mod* mod, int x, int y,
- int cx, int cy,
- int rdpindex, int srcx, int srcy);
- int (*server_set_hints)(struct mod* mod, int hints, int mask);
- /* rail */
- int (*server_window_new_update)(struct mod* mod, int window_id,
- struct rail_window_state_order* window_state,
- int flags);
- int (*server_window_delete)(struct mod* mod, int window_id);
- int (*server_window_icon)(struct mod* mod,
- int window_id, int cache_entry, int cache_id,
- struct rail_icon_info* icon_info,
- int flags);
- int (*server_window_cached_icon)(struct mod* mod,
- int window_id, int cache_entry,
- int cache_id, int flags);
- int (*server_notify_new_update)(struct mod* mod,
- int window_id, int notify_id,
- struct rail_notify_state_order* notify_state,
- int flags);
- int (*server_notify_delete)(struct mod* mod, int window_id,
- int notify_id);
- int (*server_monitored_desktop)(struct mod* mod,
- struct rail_monitored_desktop_order* mdo,
- int flags);
-
- long server_dumby[100 - 37]; /* align, 100 minus the number of server
- functions above */
- /* common */
- tbus handle; /* pointer to self as long */
- tbus wm;
- tbus painter;
- int sck;
- /* mod data */
- int width;
- int height;
- int bpp;
- int colormap[256];
- char* chan_buf;
- int chan_buf_valid;
- int chan_buf_bytes;
- int vmaj;
- int vmin;
- int vrev;
- char username[256];
- char password[256];
-
- struct xrdp_client_info client_info;
-
- struct rdp_freerdp* inst;
- struct bitmap_item bitmap_cache[4][4096];
- struct brush_item brush_cache[64];
- struct pointer_item pointer_cache[32];
-
-};
diff --git a/libxrdp/Makefile.am b/libxrdp/Makefile.am
index 4aba9e7e..6564da36 100644
--- a/libxrdp/Makefile.am
+++ b/libxrdp/Makefile.am
@@ -11,15 +11,22 @@ else
EXTRA_DEFINES += -DXRDP_NODEBUG
endif
-if XRDP_FREERDP1
-EXTRA_DEFINES += -DXRDP_FREERDP1
+if XRDP_NEUTRINORDP
+EXTRA_DEFINES += -DXRDP_NEUTRINORDP
EXTRA_LIBS += $(FREERDP_LIBS)
endif
+if XRDP_TJPEG
+EXTRA_DEFINES += -DXRDP_JPEG -DXRDP_TJPEG
+EXTRA_INCLUDES += -I/opt/libjpeg-turbo/include
+EXTRA_FLAGS += -L/opt/libjpeg-turbo/lib -Wl,-rpath -Wl,/opt/libjpeg-turbo/lib
+EXTRA_LIBS += -lturbojpeg
+else
if XRDP_JPEG
EXTRA_DEFINES += -DXRDP_JPEG
EXTRA_LIBS += -ljpeg
endif
+endif
if GOT_PREFIX
EXTRA_INCLUDES += -I$(prefix)/include
diff --git a/libxrdp/libxrdp.c b/libxrdp/libxrdp.c
index 15e34e91..e72fa1d0 100644
--- a/libxrdp/libxrdp.c
+++ b/libxrdp/libxrdp.c
@@ -629,6 +629,25 @@ libxrdp_orders_mem_blt(struct xrdp_session *session, int cache_id,
}
/******************************************************************************/
+int DEFAULT_CC
+libxrdp_orders_composite_blt(struct xrdp_session* session, int srcidx,
+ int srcformat, int srcwidth, int srcrepeat,
+ int* srctransform, int mskflags,
+ int mskidx, int mskformat, int mskwidth,
+ int mskrepeat, int op, int srcx, int srcy,
+ int mskx, int msky, int dstx, int dsty,
+ int width, int height, int dstformat,
+ struct xrdp_rect* rect)
+{
+ return xrdp_orders_composite_blt((struct xrdp_orders*)session->orders,
+ srcidx, srcformat, srcwidth, srcrepeat,
+ srctransform, mskflags,
+ mskidx, mskformat, mskwidth, mskrepeat,
+ op, srcx, srcy, mskx, msky, dstx, dsty,
+ width, height, dstformat, rect);
+}
+
+/******************************************************************************/
int EXPORT_CC
libxrdp_orders_text(struct xrdp_session *session,
int font, int flags, int mixmode,
diff --git a/libxrdp/libxrdp.h b/libxrdp/libxrdp.h
index d31edbb4..5bf627b5 100644
--- a/libxrdp/libxrdp.h
+++ b/libxrdp/libxrdp.h
@@ -49,6 +49,8 @@ struct xrdp_iso
{
struct xrdp_mcs* mcs_layer; /* owner */
struct xrdp_tcp* tcp_layer;
+ int requestedProtocol;
+ int selectedProtocol;
};
/* used in mcs */
@@ -99,6 +101,7 @@ struct xrdp_sec
char pub_sig[64];
char pri_exp[64];
int channel_code;
+ int multimon;
};
/* channel */
@@ -197,6 +200,28 @@ struct xrdp_orders_state
int text_y;
int text_len;
char* text_data;
+
+ int com_blt_srcidx; /* RDP_ORDER_COMPOSITE */ /* 2 */
+ int com_blt_srcformat; /* 2 */
+ int com_blt_srcwidth; /* 2 */
+ int com_blt_srcrepeat; /* 1 */
+ int com_blt_srctransform[10]; /* 40 */
+ int com_blt_mskflags; /* 1 */
+ int com_blt_mskidx; /* 2 */
+ int com_blt_mskformat; /* 2 */
+ int com_blt_mskwidth; /* 2 */
+ int com_blt_mskrepeat; /* 1 */
+ int com_blt_op; /* 1 */
+ int com_blt_srcx; /* 2 */
+ int com_blt_srcy; /* 2 */
+ int com_blt_mskx; /* 2 */
+ int com_blt_msky; /* 2 */
+ int com_blt_dstx; /* 2 */
+ int com_blt_dsty; /* 2 */
+ int com_blt_width; /* 2 */
+ int com_blt_height; /* 2 */
+ int com_blt_dstformat; /* 2 */
+
};
/* orders */
@@ -211,6 +236,8 @@ struct xrdp_orders
int order_count;
int order_level; /* inc for every call to xrdp_orders_init */
struct xrdp_orders_state orders_state;
+ void* jpeg_han;
+ int rfx_min_pixel;
};
#define PROTO_RDP_40 1
@@ -285,7 +312,7 @@ xrdp_mcs_disconnect(struct xrdp_mcs* self);
/* xrdp_sec.c */
struct xrdp_sec* APP_CC
xrdp_sec_create(struct xrdp_rdp* owner, struct trans* trans, int crypt_level,
- int channel_code);
+ int channel_code, int multimon);
void APP_CC
xrdp_sec_delete(struct xrdp_sec* self);
int APP_CC
@@ -378,6 +405,15 @@ xrdp_orders_mem_blt(struct xrdp_orders* self, int cache_id,
int rop, int srcx, int srcy,
int cache_idx, struct xrdp_rect* rect);
int APP_CC
+xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx,
+ int srcformat, int srcwidth,
+ int srcrepeat, int* srctransform, int mskflags,
+ int mskidx, int mskformat, int mskwidth,
+ int mskrepeat, int op, int srcx, int srcy,
+ int mskx, int msky, int dstx, int dsty,
+ int width, int height, int dstformat,
+ struct xrdp_rect* rect);
+int APP_CC
xrdp_orders_text(struct xrdp_orders* self,
int font, int flags, int mixmode,
int fg_color, int bg_color,
@@ -431,10 +467,14 @@ xrdp_bitmap_compress(char* in_data, int width, int height,
int start_line, struct stream* temp_s,
int e);
int APP_CC
-xrdp_jpeg_compress(char* in_data, int width, int height,
+xrdp_jpeg_compress(void *handle, char* in_data, int width, int height,
struct stream* s, int bpp, int byte_limit,
int start_line, struct stream* temp_s,
int e, int quality);
+void *APP_CC
+xrdp_jpeg_init(void);
+int APP_CC
+xrdp_jpeg_deinit(void *handle);
/* xrdp_channel.c */
struct xrdp_channel* APP_CC
diff --git a/libxrdp/libxrdpinc.h b/libxrdp/libxrdpinc.h
index b971204e..e5f52a05 100644
--- a/libxrdp/libxrdpinc.h
+++ b/libxrdp/libxrdpinc.h
@@ -40,13 +40,15 @@ struct xrdp_pen
int color;
};
+/* 2.2.2.2.1.2.5.1 Cache Glyph Data (TS_CACHE_GLYPH_DATA) */
struct xrdp_font_char
{
- int offset;
- int baseline;
- int width;
- int height;
+ int offset; /* x */
+ int baseline; /* y */
+ int width; /* cx */
+ int height; /* cy */
int incby;
+ int bpp;
char* data;
};
@@ -128,6 +130,16 @@ libxrdp_orders_mem_blt(struct xrdp_session* session, int cache_id,
int rop, int srcx, int srcy,
int cache_idx, struct xrdp_rect* rect);
int DEFAULT_CC
+libxrdp_orders_composite_blt(struct xrdp_session* session, int srcidx,
+ int srcformat, int srcwidth, int srcrepeat,
+ int* srctransform, int mskflags,
+ int mskidx, int mskformat, int mskwidth,
+ int mskrepeat, int op, int srcx, int srcy,
+ int mskx, int msky, int dstx, int dsty,
+ int width, int height, int dstformat,
+ struct xrdp_rect* rect);
+
+int DEFAULT_CC
libxrdp_orders_text(struct xrdp_session* session,
int font, int flags, int mixmode,
int fg_color, int bg_color,
diff --git a/libxrdp/xrdp_iso.c b/libxrdp/xrdp_iso.c
index d851c1bb..69c242d3 100644
--- a/libxrdp/xrdp_iso.c
+++ b/libxrdp/xrdp_iso.c
@@ -2,6 +2,7 @@
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2004-2013
+ * Copyright (C) Idan Freiberg 2013
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -50,12 +51,49 @@ xrdp_iso_delete(struct xrdp_iso *self)
/*****************************************************************************/
/* returns error */
static int APP_CC
-xrdp_iso_recv_msg(struct xrdp_iso *self, struct stream *s, int *code)
+xrdp_iso_recv_rdpnegreq(struct xrdp_iso *self, struct stream *s)
{
- int ver;
+ int flags;
int len;
- *code = 0;
+ DEBUG((" in xrdp_iso_recv_rdpnegreq"));
+
+ in_uint8(s, flags);
+ if (flags != 0x0)
+ {
+ DEBUG((" xrdp_iso_recv_rdpnegreq: flags: %x",flags));
+ return 1;
+ }
+
+ in_uint16_le(s, len);
+ if (len != 8) // fixed length
+ {
+ DEBUG((" xrdp_iso_recv_rdpnegreq: length: %x",len));
+ return 1;
+ }
+
+ in_uint32_le(s, self->requestedProtocol);
+
+ //TODO: think of protocol verification logic
+// if (requestedProtocol != PROTOCOL_RDP || PROTOCOL_SSL || PROTOCOL_HYBRID || PROTOCOL_HYBRID_EX)
+// {
+// DEBUG((" xrdp_iso_recv_rdpnegreq: wrong requestedProtocol: %x",requestedProtocol));
+// return 1;
+// }
+
+ DEBUG((" out xrdp_iso_recv_rdpnegreq"));
+ return 0;
+}
+/*****************************************************************************/
+/* returns error */
+static int APP_CC
+xrdp_iso_recv_msg(struct xrdp_iso *self, struct stream *s, int *code, int *len)
+{
+ int ver; // TPKT Version
+ int plen; // TPKT PacketLength
+
+ *code = 0; // X.224 Packet Type
+ *len = 0; // X.224 Length Indicator
if (xrdp_tcp_recv(self->tcp_layer, s, 4) != 0)
{
@@ -70,46 +108,64 @@ xrdp_iso_recv_msg(struct xrdp_iso *self, struct stream *s, int *code)
}
in_uint8s(s, 1);
- in_uint16_be(s, len);
+ in_uint16_be(s, plen);
- if (xrdp_tcp_recv(self->tcp_layer, s, len - 4) != 0)
+ if (plen < 4)
{
return 1;
}
- in_uint8s(s, 1);
+ if (xrdp_tcp_recv(self->tcp_layer, s, plen - 4) != 0)
+ {
+ return 1;
+ }
+
+ if (!s_check_rem(s, 2))
+ {
+ return 1;
+ }
+
+ in_uint8(s, *len);
in_uint8(s, *code);
if (*code == ISO_PDU_DT)
{
+ if (!s_check_rem(s, 1))
+ {
+ return 1;
+ }
in_uint8s(s, 1);
}
else
{
+ if (!s_check_rem(s, 5))
+ {
+ return 1;
+ }
in_uint8s(s, 5);
}
return 0;
}
-
/*****************************************************************************/
/* returns error */
int APP_CC
xrdp_iso_recv(struct xrdp_iso *self, struct stream *s)
{
int code;
+ int len;
DEBUG((" in xrdp_iso_recv"));
- if (xrdp_iso_recv_msg(self, s, &code) != 0)
+ if (xrdp_iso_recv_msg(self, s, &code, &len) != 0)
{
DEBUG((" out xrdp_iso_recv xrdp_iso_recv_msg return non zero"));
return 1;
}
- if (code != ISO_PDU_DT)
+ if (code != ISO_PDU_DT || len != 2)
{
- DEBUG((" out xrdp_iso_recv code != ISO_PDU_DT"));
+ DEBUG((" out xrdp_iso_recv code != ISO_PDU_DT or length != 2"));
return 1;
}
@@ -119,21 +175,79 @@ xrdp_iso_recv(struct xrdp_iso *self, struct stream *s)
/*****************************************************************************/
static int APP_CC
-xrdp_iso_send_msg(struct xrdp_iso *self, struct stream *s, int code)
+xrdp_iso_send_rdpnegrsp(struct xrdp_iso *self, struct stream *s, int code)
{
if (xrdp_tcp_init(self->tcp_layer, s) != 0)
{
return 1;
}
- out_uint8(s, 3);
+ /* TPKT HEADER - 4 bytes */
+ out_uint8(s, 3); /* version */
+ out_uint8(s, 0); /* RESERVED */
+ if (self->selectedProtocol != -1)
+ {
+ out_uint16_be(s, 19); /* length */ //rdp negotiation happens.
+ }
+ else
+ {
+ out_uint16_be(s, 11); /* length */ //rdp negotiation doesn't happen.
+ }
+ /* ISO LAYER - X.224 - 7 bytes*/
+ if (self->selectedProtocol != -1)
+ {
+ out_uint8(s, 14); /* length */
+ }
+ else
+ {
+ out_uint8(s, 6); /* length */
+ }
+ out_uint8(s, code); /* SHOULD BE 0xD for CC */
+ out_uint16_be(s, 0);
+ out_uint16_be(s, 0x1234);
out_uint8(s, 0);
- out_uint16_be(s, 11); /* length */
- out_uint8(s, 6);
- out_uint8(s, code);
- out_uint16_le(s, 0);
- out_uint16_le(s, 0);
+ if (self->selectedProtocol != -1)
+ {
+ /* RDP_NEG_RSP - 8 bytes*/
+ out_uint8(s, RDP_NEG_RSP);
+ out_uint8(s, EXTENDED_CLIENT_DATA_SUPPORTED); /* flags */
+ out_uint16_le(s, 8); /* fixed length */
+ out_uint32_le(s, self->selectedProtocol); /* selected protocol */
+ }
+
+ s_mark_end(s);
+
+ if (xrdp_tcp_send(self->tcp_layer, s) != 0)
+ {
+ return 1;
+ }
+
+ return 0;
+}
+/*****************************************************************************/
+static int APP_CC
+xrdp_iso_send_rdpnegfailure(struct xrdp_iso *self, struct stream *s, int code, int failureCode)
+{
+ if (xrdp_tcp_init(self->tcp_layer, s) != 0)
+ {
+ return 1;
+ }
+
+ /* TPKT HEADER - 4 bytes */
+ out_uint8(s, 3); /* version */
+ out_uint8(s, 0); /* RESERVED */
+ out_uint16_be(s, 19); /* length */
+ /* ISO LAYER - X.224 - 7 bytes*/
+ out_uint8(s, 14); /* length */
+ out_uint8(s, code); /* SHOULD BE 0xD for CC */
+ out_uint16_be(s, 0);
+ out_uint16_be(s, 0x1234);
out_uint8(s, 0);
+ /* RDP_NEG_FAILURE - 8 bytes*/
+ out_uint8(s, RDP_NEG_FAILURE);
+ out_uint8(s, 0); /* no flags available */
+ out_uint16_le(s, 8); /* fixed length */
+ out_uint32_le(s, failureCode); /* failure code */
s_mark_end(s);
if (xrdp_tcp_send(self->tcp_layer, s) != 0)
@@ -145,30 +259,111 @@ xrdp_iso_send_msg(struct xrdp_iso *self, struct stream *s, int code)
}
/*****************************************************************************/
+static int APP_CC
+xrdp_iso_send_nego(struct xrdp_iso *self)
+{
+ struct stream *s;
+
+ make_stream(s);
+ init_stream(s, 8192);
+
+ //TODO: negotiation logic here.
+ if (self->requestedProtocol != PROTOCOL_RDP)
+ {
+ // Send RDP_NEG_FAILURE back to client
+ if (xrdp_iso_send_rdpnegfailure(self, s, ISO_PDU_CC,
+ SSL_NOT_ALLOWED_BY_SERVER) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ }
+ else
+ {
+ self->selectedProtocol = PROTOCOL_RDP;
+ // Send RDP_NEG_RSP back to client
+ if (xrdp_iso_send_rdpnegrsp(self, s, ISO_PDU_CC) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ }
+ free_stream(s);
+ return 0;
+}
+
+/*****************************************************************************/
/* returns error */
int APP_CC
xrdp_iso_incoming(struct xrdp_iso *self)
{
int code;
+ int len;
+ int cookie_index;
+ int cc_type;
+ char text[256];
+ char *pend;
struct stream *s;
make_stream(s);
init_stream(s, 8192);
DEBUG((" in xrdp_iso_incoming"));
- if (xrdp_iso_recv_msg(self, s, &code) != 0)
+ if (xrdp_iso_recv_msg(self, s, &code, &len) != 0)
{
+ DEBUG((" in xrdp_iso_recv_msg error!!"));
free_stream(s);
return 1;
}
- if (code != ISO_PDU_CR)
+ if ((code != ISO_PDU_CR) || (len < 6))
{
free_stream(s);
return 1;
}
- if (xrdp_iso_send_msg(self, s, ISO_PDU_CC) != 0)
+ self->selectedProtocol = -1;
+ self->requestedProtocol = PROTOCOL_RDP;
+
+ pend = s->p + (len - 6);
+ cookie_index = 0;
+ while (s->p < pend)
+ {
+ in_uint8(s, cc_type);
+ switch (cc_type)
+ {
+ default:
+ break;
+ case RDP_NEG_REQ: /* rdpNegReq 1 */
+ if (xrdp_iso_recv_rdpnegreq(self, s) != 0)
+ {
+ free_stream(s);
+ return 1;
+ }
+ break;
+ case RDP_CORRELATION_INFO: /* rdpCorrelationInfo 6 */
+ // TODO
+ in_uint8s(s, 1 + 2 + 16 + 16);
+ break;
+ case 'C': /* Cookie routingToken */
+ while (s->p < pend)
+ {
+ text[cookie_index] = cc_type;
+ cookie_index++;
+ if ((s->p[0] == 0x0D) && (s->p[1] == 0x0A))
+ {
+ in_uint8s(s, 2);
+ text[cookie_index] = 0;
+ cookie_index = 0;
+ break;
+ }
+ in_uint8(s, cc_type);
+ }
+ break;
+ }
+ }
+
+ if (xrdp_iso_send_nego(self) != 0)
{
free_stream(s);
return 1;
@@ -198,7 +393,7 @@ xrdp_iso_send(struct xrdp_iso *self, struct stream *s)
DEBUG((" in xrdp_iso_send"));
s_pop_layer(s, iso_hdr);
- len = s->end - s->p;
+ len = (int)(s->end - s->p);
out_uint8(s, 3);
out_uint8(s, 0);
out_uint16_be(s, len);
diff --git a/libxrdp/xrdp_jpeg_compress.c b/libxrdp/xrdp_jpeg_compress.c
index 82a816a0..a41bd1cf 100644
--- a/libxrdp/xrdp_jpeg_compress.c
+++ b/libxrdp/xrdp_jpeg_compress.c
@@ -20,7 +20,112 @@
#include "libxrdp.h"
-#if defined(XRDP_JPEG)
+#if defined(XRDP_TJPEG)
+
+/* turbo jpeg */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <turbojpeg.h>
+
+/*****************************************************************************/
+int APP_CC
+xrdp_jpeg_compress(void *handle, char *in_data, int width, int height,
+ struct stream *s, int bpp, int byte_limit,
+ int start_line, struct stream *temp_s,
+ int e, int quality)
+{
+ int error;
+ int i;
+ int j;
+ unsigned int pixel;
+ unsigned int *src32;
+ unsigned int *dst32;
+ unsigned long cdata_bytes;
+ unsigned char *src_buf;
+ unsigned char *dst_buf;
+ char *temp_buf;
+ tjhandle tj_han;
+
+ if (bpp != 24)
+ {
+ g_writeln("xrdp_jpeg_compress: bpp wrong %d", bpp);
+ return height;
+ }
+ if (handle == 0)
+ {
+ g_writeln("xrdp_jpeg_compress: handle is nil");
+ return height;
+ }
+ tj_han = (tjhandle) handle;
+ cdata_bytes = byte_limit;
+ src_buf = (unsigned char *) in_data;
+ dst_buf = (unsigned char *) (s->p);
+ temp_buf = 0;
+ if (e == 0)
+ {
+ src_buf = (unsigned char*)in_data;
+ }
+ else
+ {
+ temp_buf = (char *) g_malloc((width + e) * height * 4, 0);
+ dst32 = (unsigned int *) temp_buf;
+ src32 = (unsigned int *) in_data;
+ for (j = 0; j < height; j++)
+ {
+ for (i = 0; i < width; i++)
+ {
+ pixel = *src32;
+ src32++;
+ *dst32 = pixel;
+ dst32++;
+ }
+ for (i = 0; i < e; i++)
+ {
+ *dst32 = pixel;
+ dst32++;
+ }
+ }
+ src_buf = (unsigned char *) temp_buf;
+ }
+ dst_buf = (unsigned char*)(s->p);
+ error = tjCompress(tj_han, src_buf, width + e, (width + e) * 4, height,
+ TJPF_XBGR, dst_buf, &cdata_bytes,
+ TJSAMP_420, quality, 0);
+ s->p += cdata_bytes;
+ g_free(temp_buf);
+ return height;
+}
+
+/*****************************************************************************/
+void *APP_CC
+xrdp_jpeg_init(void)
+{
+ tjhandle tj_han;
+
+ tj_han = tjInitCompress();
+ return tj_han;
+}
+
+/*****************************************************************************/
+int APP_CC
+xrdp_jpeg_deinit(void *handle)
+{
+ tjhandle tj_han;
+
+ if (handle == 0)
+ {
+ return 0;
+ }
+ tj_han = (tjhandle) handle;
+ tjDestroy(tj_han);
+ return 0;
+}
+
+#elif defined(XRDP_JPEG)
+
+/* libjpeg */
#include <stdio.h>
#include <stdlib.h>
@@ -205,7 +310,7 @@ jpeg_compress(char *in_data, int width, int height,
/*****************************************************************************/
int APP_CC
-xrdp_jpeg_compress(char *in_data, int width, int height,
+xrdp_jpeg_compress(void *handle, char *in_data, int width, int height,
struct stream *s, int bpp, int byte_limit,
int start_line, struct stream *temp_s,
int e, int quality)
@@ -215,11 +320,25 @@ xrdp_jpeg_compress(char *in_data, int width, int height,
return height;
}
+/*****************************************************************************/
+void *APP_CC
+xrdp_jpeg_init(void)
+{
+ return 0;
+}
+
+/*****************************************************************************/
+int APP_CC
+xrdp_jpeg_deinit(void *handle)
+{
+ return 0;
+}
+
#else
/*****************************************************************************/
int APP_CC
-xrdp_jpeg_compress(char *in_data, int width, int height,
+xrdp_jpeg_compress(void *handle, char *in_data, int width, int height,
struct stream *s, int bpp, int byte_limit,
int start_line, struct stream *temp_s,
int e, int quality)
@@ -227,4 +346,18 @@ xrdp_jpeg_compress(char *in_data, int width, int height,
return height;
}
+/*****************************************************************************/
+void *APP_CC
+xrdp_jpeg_init(void)
+{
+ return 0;
+}
+
+/*****************************************************************************/
+int APP_CC
+xrdp_jpeg_deinit(void *handle)
+{
+ return 0;
+}
+
#endif
diff --git a/libxrdp/xrdp_mcs.c b/libxrdp/xrdp_mcs.c
index 4bf3d025..c145158c 100644
--- a/libxrdp/xrdp_mcs.c
+++ b/libxrdp/xrdp_mcs.c
@@ -66,6 +66,7 @@ xrdp_mcs_delete(struct xrdp_mcs *self)
}
list_delete(self->channel_list);
+
xrdp_iso_delete(self->iso_layer);
/* make sure we get null pointer exception if struct is used again. */
DEBUG(("xrdp_mcs_delete processed"))
@@ -132,6 +133,11 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan)
return 1;
}
+ if (!s_check_rem(s, 1))
+ {
+ return 1;
+ }
+
in_uint8(s, opcode);
appid = opcode >> 2;
@@ -145,6 +151,11 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan)
/* this is channels getting added from the client */
if (appid == MCS_CJRQ)
{
+ if (!s_check_rem(s, 4))
+ {
+ return 1;
+ }
+
in_uint16_be(s, userid);
in_uint16_be(s, chanid);
log_message(LOG_LEVEL_DEBUG,"MCS_CJRQ - channel join request received");
@@ -176,6 +187,11 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan)
return 1;
}
+ if (!s_check_rem(s, 6))
+ {
+ return 1;
+ }
+
in_uint8s(s, 2);
in_uint16_be(s, *chan);
in_uint8s(s, 1);
@@ -183,6 +199,10 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan)
if (len & 0x80)
{
+ if (!s_check_rem(s, 1))
+ {
+ return 1;
+ }
in_uint8s(s, 1);
}
@@ -202,10 +222,18 @@ xrdp_mcs_ber_parse_header(struct xrdp_mcs *self, struct stream *s,
if (tag_val > 0xff)
{
+ if (!s_check_rem(s, 2))
+ {
+ return 1;
+ }
in_uint16_be(s, tag);
}
else
{
+ if (!s_check_rem(s, 1))
+ {
+ return 1;
+ }
in_uint8(s, tag);
}
@@ -214,6 +242,11 @@ xrdp_mcs_ber_parse_header(struct xrdp_mcs *self, struct stream *s,
return 1;
}
+ if (!s_check_rem(s, 1))
+ {
+ return 1;
+ }
+
in_uint8(s, l);
if (l & 0x80)
@@ -223,6 +256,10 @@ xrdp_mcs_ber_parse_header(struct xrdp_mcs *self, struct stream *s,
while (l > 0)
{
+ if (!s_check_rem(s, 1))
+ {
+ return 1;
+ }
in_uint8(s, i);
*len = (*len << 8) | i;
l--;
@@ -255,6 +292,11 @@ xrdp_mcs_parse_domain_params(struct xrdp_mcs *self, struct stream *s)
return 1;
}
+ if ((len < 0) || !s_check_rem(s, len))
+ {
+ return 1;
+ }
+
in_uint8s(s, len);
if (s_check(s))
@@ -276,7 +318,7 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self)
struct stream *s;
make_stream(s);
- init_stream(s, 8192);
+ init_stream(s, 16 * 1024);
if (xrdp_iso_recv(self->iso_layer, s) != 0)
{
@@ -296,6 +338,12 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self)
return 1;
}
+ if ((len < 0) || !s_check_rem(s, len))
+ {
+ free_stream(s);
+ return 1;
+ }
+
in_uint8s(s, len);
if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0)
@@ -304,6 +352,12 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self)
return 1;
}
+ if ((len < 0) || !s_check_rem(s, len))
+ {
+ free_stream(s);
+ return 1;
+ }
+
in_uint8s(s, len);
if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_BOOLEAN, &len) != 0)
@@ -312,6 +366,12 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self)
return 1;
}
+ if ((len < 0) || !s_check_rem(s, len))
+ {
+ free_stream(s);
+ return 1;
+ }
+
in_uint8s(s, len);
if (xrdp_mcs_parse_domain_params(self, s) != 0)
@@ -338,6 +398,19 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self)
return 1;
}
+ /* mcs data can not be zero length */
+ if ((len <= 0) || (len > 16 * 1024))
+ {
+ free_stream(s);
+ return 1;
+ }
+
+ if (!s_check_rem(s, len))
+ {
+ free_stream(s);
+ return 1;
+ }
+
/* make a copy of client mcs data */
init_stream(self->client_mcs_data, len);
out_uint8a(self->client_mcs_data, s->p, len);
@@ -364,6 +437,7 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self)
int opcode;
struct stream *s;
+ DEBUG((" in xrdp_mcs_recv_edrq"));
make_stream(s);
init_stream(s, 8192);
@@ -372,6 +446,12 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self)
free_stream(s);
return 1;
}
+
+ if (!s_check_rem(s, 1))
+ {
+ free_stream(s);
+ return 1;
+ }
in_uint8(s, opcode);
@@ -381,11 +461,22 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self)
return 1;
}
+ if (!s_check_rem(s, 4))
+ {
+ free_stream(s);
+ return 1;
+ }
+
in_uint8s(s, 2);
in_uint8s(s, 2);
if (opcode & 2)
{
+ if (!s_check_rem(s, 2))
+ {
+ free_stream(s);
+ return 1;
+ }
in_uint16_be(s, self->userid);
}
@@ -396,6 +487,7 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self)
}
free_stream(s);
+ DEBUG((" out xrdp_mcs_recv_edrq"));
return 0;
}
@@ -407,6 +499,7 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self)
int opcode;
struct stream *s;
+ DEBUG((" in xrdp_mcs_recv_aurq"));
make_stream(s);
init_stream(s, 8192);
@@ -416,6 +509,12 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self)
return 1;
}
+ if (!s_check_rem(s, 1))
+ {
+ free_stream(s);
+ return 1;
+ }
+
in_uint8(s, opcode);
if ((opcode >> 2) != MCS_AURQ)
@@ -426,6 +525,11 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self)
if (opcode & 2)
{
+ if (!s_check_rem(s, 2))
+ {
+ free_stream(s);
+ return 1;
+ }
in_uint16_be(s, self->userid);
}
@@ -436,6 +540,7 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self)
}
free_stream(s);
+ DEBUG((" out xrdp_mcs_recv_aurq"));
return 0;
}
@@ -491,6 +596,12 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self)
return 1;
}
+ if (!s_check_rem(s, 1))
+ {
+ free_stream(s);
+ return 1;
+ }
+
in_uint8(s, opcode);
if ((opcode >> 2) != MCS_CJRQ)
@@ -499,10 +610,21 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self)
return 1;
}
+ if (!s_check_rem(s, 4))
+ {
+ free_stream(s);
+ return 1;
+ }
+
in_uint8s(s, 4);
if (opcode & 2)
{
+ if (!s_check_rem(s, 2))
+ {
+ free_stream(s);
+ return 1;
+ }
in_uint8s(s, 2);
}
diff --git a/libxrdp/xrdp_mppc_enc.c b/libxrdp/xrdp_mppc_enc.c
index 05aa6bb6..15125d54 100644
--- a/libxrdp/xrdp_mppc_enc.c
+++ b/libxrdp/xrdp_mppc_enc.c
@@ -573,18 +573,21 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len)
outputBuffer = enc->outputBuffer;
g_memset(outputBuffer, 0, len);
enc->flags = PACKET_COMPR_TYPE_64K;
+
if (enc->first_pkt)
{
enc->first_pkt = 0;
enc->flagsHold |= PACKET_AT_FRONT;
}
- if ((enc->historyOffset + len) > enc->buf_len)
+ if ((enc->historyOffset + len) >= enc->buf_len)
{
/* historyBuffer cannot hold srcData - rewind it */
enc->historyOffset = 0;
- enc->flagsHold |= PACKET_AT_FRONT;
g_memset(hash_table, 0, enc->buf_len * 2);
+ g_memset(enc->historyBuffer, 0, enc->buf_len); // added
+ enc->first_pkt = 0;
+ enc->flagsHold |= PACKET_AT_FRONT;
}
/* point to next free byte in historyBuffer */
@@ -602,7 +605,7 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len)
/* first 2 bytes,because minimum LoM is 3 */
if (historyOffset == 0)
{
- /* encode first two bytes are literals */
+ /* encode first two bytes as literals */
for (x = 0; x < 2; x++)
{
data = *(historyPointer + x);
@@ -974,8 +977,14 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len)
/* give up */
enc->historyOffset = 0;
g_memset(hash_table, 0, enc->buf_len * 2);
+ g_memset(enc->historyBuffer, 0, enc->buf_len);
enc->flagsHold |= PACKET_FLUSHED;
enc->first_pkt = 1;
+
+ g_memcpy(enc->outputBuffer, srcData, len);
+ enc->bytes_in_opb = len;
+ enc->flags = 0x81;
+
return 1;
}
else if (opb_index + 1 > len)
@@ -984,8 +993,14 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len)
/* give up */
enc->historyOffset = 0;
g_memset(hash_table, 0, enc->buf_len * 2);
+ g_memset(enc->historyBuffer, 0, enc->buf_len);
enc->flagsHold |= PACKET_FLUSHED;
enc->first_pkt = 1;
+
+ g_memcpy(enc->outputBuffer, srcData, len);
+ enc->bytes_in_opb = len;
+ enc->flags = 0x81;
+
return 1;
}
@@ -1000,8 +1015,14 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len)
/* give up */
enc->historyOffset = 0;
g_memset(hash_table, 0, enc->buf_len * 2);
+ g_memset(enc->historyBuffer, 0, enc->buf_len);
enc->flagsHold |= PACKET_FLUSHED;
enc->first_pkt = 1;
+
+ g_memcpy(enc->outputBuffer, srcData, len);
+ enc->bytes_in_opb = len;
+ enc->flags = 0x81;
+
return 1;
}
enc->flags |= PACKET_COMPRESSED;
@@ -1011,6 +1032,8 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len)
enc->flagsHold = 0;
DLOG(("\n"));
+ //g_writeln("compression ratio: %f", (float) len / (float) enc->bytes_in_opb);
+
return 1;
}
diff --git a/libxrdp/xrdp_orders.c b/libxrdp/xrdp_orders.c
index 29234173..0e2d90d2 100644
--- a/libxrdp/xrdp_orders.c
+++ b/libxrdp/xrdp_orders.c
@@ -20,7 +20,7 @@
#include "libxrdp.h"
-#if defined(XRDP_FREERDP1)
+#if defined(XRDP_NEUTRINORDP)
#include <freerdp/codec/rfx.h>
#endif
@@ -47,6 +47,12 @@ xrdp_orders_create(struct xrdp_session *session, struct xrdp_rdp *rdp_layer)
init_stream(self->out_s, 16384);
self->orders_state.clip_right = 1; /* silly rdp right clip */
self->orders_state.clip_bottom = 1; /* silly rdp bottom clip */
+ self->jpeg_han = xrdp_jpeg_init();
+ self->rfx_min_pixel = rdp_layer->client_info.rfx_min_pixel;
+ if (self->rfx_min_pixel == 0)
+ {
+ self->rfx_min_pixel = 64 * 32;
+ }
return self;
}
@@ -59,6 +65,7 @@ xrdp_orders_delete(struct xrdp_orders *self)
return;
}
+ xrdp_jpeg_deinit(self->jpeg_han);
free_stream(self->out_s);
g_free(self->orders_state.text_data);
g_free(self);
@@ -200,6 +207,7 @@ xrdp_orders_check(struct xrdp_orders *self, int max_size)
}
else
{
+ xrdp_orders_init(self);
return 0;
}
}
@@ -462,7 +470,10 @@ xrdp_orders_rect(struct xrdp_orders *self, int x, int y, int cx, int cy,
char *present_ptr;
char *order_flags_ptr;
- xrdp_orders_check(self, 23);
+ if (xrdp_orders_check(self, 23) != 0)
+ {
+ return 1;
+ }
self->order_count++;
order_flags = RDP_ORDER_STANDARD;
@@ -630,7 +641,10 @@ xrdp_orders_screen_blt(struct xrdp_orders *self, int x, int y,
char *present_ptr = (char *)NULL;
char *order_flags_ptr = (char *)NULL;
- xrdp_orders_check(self, 25);
+ if (xrdp_orders_check(self, 25) != 0)
+ {
+ return 1;
+ }
self->order_count++;
order_flags = RDP_ORDER_STANDARD;
@@ -819,7 +833,10 @@ xrdp_orders_pat_blt(struct xrdp_orders *self, int x, int y,
char *order_flags_ptr;
struct xrdp_brush blank_brush;
- xrdp_orders_check(self, 39);
+ if (xrdp_orders_check(self, 39) != 0)
+ {
+ return 1;
+ }
self->order_count++;
order_flags = RDP_ORDER_STANDARD;
@@ -1033,7 +1050,10 @@ xrdp_orders_dest_blt(struct xrdp_orders *self, int x, int y,
char *present_ptr;
char *order_flags_ptr;
- xrdp_orders_check(self, 21);
+ if (xrdp_orders_check(self, 21) != 0)
+ {
+ return 1;
+ }
self->order_count++;
order_flags = RDP_ORDER_STANDARD;
@@ -1201,7 +1221,10 @@ xrdp_orders_line(struct xrdp_orders *self, int mix_mode,
rop = 0x0d; /* R2_COPYPEN */
}
- xrdp_orders_check(self, 32);
+ if (xrdp_orders_check(self, 32) != 0)
+ {
+ return 1;
+ }
self->order_count++;
order_flags = RDP_ORDER_STANDARD;
@@ -1400,7 +1423,10 @@ xrdp_orders_mem_blt(struct xrdp_orders *self, int cache_id,
char *present_ptr = (char *)NULL;
char *order_flags_ptr = (char *)NULL;
- xrdp_orders_check(self, 30);
+ if (xrdp_orders_check(self, 30) != 0)
+ {
+ return 1;
+ }
self->order_count++;
order_flags = RDP_ORDER_STANDARD;
@@ -1592,6 +1618,335 @@ xrdp_orders_mem_blt(struct xrdp_orders *self, int cache_id,
/*****************************************************************************/
/* returns error */
int APP_CC
+xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat,
+ int srcwidth, int srcrepeat, int* srctransform,
+ int mskflags, int mskidx, int mskformat,
+ int mskwidth, int mskrepeat, int op,
+ int srcx, int srcy, int mskx, int msky,
+ int dstx, int dsty, int width, int height,
+ int dstformat,
+ struct xrdp_rect* rect)
+{
+ int order_flags;
+ int vals[20];
+ int present;
+ char* present_ptr;
+ char* order_flags_ptr;
+
+ if (xrdp_orders_check(self, 80) != 0)
+ {
+ return 1;
+ }
+ self->order_count++;
+ order_flags = RDP_ORDER_STANDARD;
+ if (self->orders_state.last_order != RDP_ORDER_COMPOSITE)
+ {
+ order_flags |= RDP_ORDER_CHANGE;
+ }
+ self->orders_state.last_order = RDP_ORDER_COMPOSITE;
+ if (rect != 0)
+ {
+ /* if clip is present, still check if its needed */
+ if (dstx < rect->left || dsty < rect->top ||
+ dstx + width > rect->right || dsty + height > rect->bottom)
+ {
+ order_flags |= RDP_ORDER_BOUNDS;
+ if (xrdp_orders_last_bounds(self, rect))
+ {
+
+ order_flags |= RDP_ORDER_LASTBOUNDS;
+
+ }
+ }
+ }
+ vals[0] = srcx;
+ vals[1] = self->orders_state.com_blt_srcx;
+ vals[2] = srcy;
+ vals[3] = self->orders_state.com_blt_srcy;
+ vals[4] = mskx;
+ vals[5] = self->orders_state.com_blt_mskx;
+ vals[6] = msky;
+ vals[7] = self->orders_state.com_blt_msky;
+ vals[8] = dstx;
+ vals[9] = self->orders_state.com_blt_dstx;
+ vals[10] = dsty;
+ vals[11] = self->orders_state.com_blt_dsty;
+ vals[12] = width;
+ vals[13] = self->orders_state.com_blt_width;
+ vals[14] = height;
+ vals[15] = self->orders_state.com_blt_height;
+ vals[16] = srcwidth;
+ vals[17] = self->orders_state.com_blt_srcwidth;
+ vals[18] = mskwidth;
+ vals[19] = self->orders_state.com_blt_mskwidth;
+ if (xrdp_orders_send_delta(self, vals, 20))
+ {
+ order_flags |= RDP_ORDER_DELTA;
+ }
+ /* order_flags, set later, 1 byte */
+ order_flags_ptr = self->out_s->p;
+ out_uint8s(self->out_s, 1);
+ if (order_flags & RDP_ORDER_CHANGE)
+ {
+ out_uint8(self->out_s, self->orders_state.last_order);
+ }
+ present = 0;
+ /* present, set later, 3 bytes */
+ present_ptr = self->out_s->p;
+ out_uint8s(self->out_s, 3);
+ if ((order_flags & RDP_ORDER_BOUNDS) &&
+ !(order_flags & RDP_ORDER_LASTBOUNDS))
+ {
+ xrdp_orders_out_bounds(self, rect);
+ }
+
+ if (srcidx != self->orders_state.com_blt_srcidx)
+ {
+ present |= 0x000001;
+ out_uint16_le(self->out_s, srcidx);
+ self->orders_state.com_blt_srcidx = srcidx;
+ }
+
+ if (srcformat != self->orders_state.com_blt_srcformat)
+ {
+ present |= 0x000002;
+ out_uint32_le(self->out_s, srcformat);
+ self->orders_state.com_blt_srcformat = srcformat;
+ }
+
+ if (srcwidth != self->orders_state.com_blt_srcwidth)
+ {
+ present |= 0x000004;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, srcwidth - self->orders_state.com_blt_srcwidth);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, srcwidth);
+ }
+ self->orders_state.com_blt_srcwidth = srcwidth;
+ }
+
+ if (srcrepeat != self->orders_state.com_blt_srcrepeat)
+ {
+ present |= 0x000008;
+ out_uint8(self->out_s, srcrepeat);
+ self->orders_state.com_blt_srcrepeat = srcrepeat;
+ }
+
+ if (srctransform != 0)
+ {
+ if (srctransform[0] != self->orders_state.com_blt_srctransform[0])
+ {
+ present |= 0x000010;
+ out_uint32_le(self->out_s, srctransform[0]);
+ self->orders_state.com_blt_srctransform[0] = srctransform[0];
+ }
+ if (g_memcmp(&(srctransform[1]),
+ &(self->orders_state.com_blt_srctransform[1]),
+ 36) != 0)
+ {
+ present |= 0x000020;
+ out_uint32_le(self->out_s, srctransform[1]);
+ out_uint32_le(self->out_s, srctransform[2]);
+ out_uint32_le(self->out_s, srctransform[3]);
+ out_uint32_le(self->out_s, srctransform[4]);
+ out_uint32_le(self->out_s, srctransform[5]);
+ out_uint32_le(self->out_s, srctransform[6]);
+ out_uint32_le(self->out_s, srctransform[7]);
+ out_uint32_le(self->out_s, srctransform[8]);
+ out_uint32_le(self->out_s, srctransform[9]);
+ }
+ }
+ else
+ {
+ if (self->orders_state.com_blt_srctransform[0] != 0)
+ {
+ present |= 0x000010;
+ out_uint32_le(self->out_s, 0);
+ self->orders_state.com_blt_srctransform[0] = 0;
+ }
+ }
+
+ if (mskflags != self->orders_state.com_blt_mskflags)
+ {
+ present |= 0x000040;
+ out_uint8(self->out_s, mskflags);
+ self->orders_state.com_blt_mskflags = mskflags;
+ }
+
+ if (mskidx != self->orders_state.com_blt_mskidx)
+ {
+ present |= 0x000080;
+ out_uint16_le(self->out_s, mskidx);
+ self->orders_state.com_blt_mskidx = mskidx;
+ }
+
+ if (mskformat != self->orders_state.com_blt_mskformat)
+ {
+ present |= 0x000100;
+ out_uint32_le(self->out_s, mskformat);
+ self->orders_state.com_blt_mskformat = mskformat;
+ }
+
+ if (mskwidth != self->orders_state.com_blt_mskwidth)
+ {
+ present |= 0x000200;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, mskwidth - self->orders_state.com_blt_mskwidth);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, mskwidth);
+ }
+ self->orders_state.com_blt_mskwidth = mskwidth;
+ }
+
+ if (mskrepeat != self->orders_state.com_blt_mskrepeat)
+ {
+ present |= 0x000400;
+ out_uint8(self->out_s, mskrepeat);
+ self->orders_state.com_blt_mskrepeat = mskrepeat;
+ }
+
+ if (op != self->orders_state.com_blt_op)
+ {
+ present |= 0x000800;
+ out_uint8(self->out_s, op);
+ self->orders_state.com_blt_op = op;
+ }
+
+ if (srcx != self->orders_state.com_blt_srcx)
+ {
+ present |= 0x001000;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, srcx - self->orders_state.com_blt_srcx);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, srcx);
+ }
+ self->orders_state.com_blt_srcx = srcx;
+ }
+
+ if (srcy != self->orders_state.com_blt_srcy)
+ {
+ present |= 0x002000;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, srcy - self->orders_state.com_blt_srcy);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, srcy);
+ }
+ self->orders_state.com_blt_srcy = srcy;
+ }
+
+ if (mskx != self->orders_state.com_blt_mskx)
+ {
+ present |= 0x004000;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, mskx - self->orders_state.com_blt_mskx);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, mskx);
+ }
+ self->orders_state.com_blt_mskx = mskx;
+ }
+
+ if (msky != self->orders_state.com_blt_msky)
+ {
+ present |= 0x008000;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, msky - self->orders_state.com_blt_msky);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, msky);
+ }
+ self->orders_state.com_blt_msky = msky;
+ }
+
+ if (dstx != self->orders_state.com_blt_dstx)
+ {
+ present |= 0x010000;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, dstx - self->orders_state.com_blt_dstx);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, dstx);
+ }
+ self->orders_state.com_blt_dstx = dstx;
+ }
+
+ if (dsty != self->orders_state.com_blt_dsty)
+ {
+ present |= 0x020000;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, dsty - self->orders_state.com_blt_dsty);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, dsty);
+ }
+ self->orders_state.com_blt_dsty = dsty;
+ }
+
+ if (width != self->orders_state.com_blt_width)
+ {
+ present |= 0x040000;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, width - self->orders_state.com_blt_width);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, width);
+ }
+ self->orders_state.com_blt_width = width;
+ }
+
+ if (height != self->orders_state.com_blt_height)
+ {
+ present |= 0x080000;
+ if (order_flags & RDP_ORDER_DELTA)
+ {
+ out_uint8(self->out_s, height - self->orders_state.com_blt_height);
+ }
+ else
+ {
+ out_uint16_le(self->out_s, height);
+ }
+ self->orders_state.com_blt_height = height;
+ }
+
+ if (dstformat != self->orders_state.com_blt_dstformat)
+ {
+ present |= 0x100000;
+ out_uint32_le(self->out_s, dstformat);
+ self->orders_state.com_blt_dstformat = dstformat;
+ }
+
+ xrdp_order_pack_small_or_tiny(self, order_flags_ptr, order_flags,
+
+ present_ptr, present, 3);
+
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
xrdp_orders_text(struct xrdp_orders *self,
int font, int flags, int mixmode,
int fg_color, int bg_color,
@@ -1607,8 +1962,10 @@ xrdp_orders_text(struct xrdp_orders *self,
char *present_ptr = (char *)NULL;
char *order_flags_ptr = (char *)NULL;
- //xrdp_orders_check(self, 100);
- xrdp_orders_check(self, 44+data_len);
+ if (xrdp_orders_check(self, 44 + data_len) != 0)
+ {
+ return 1;
+ }
self->order_count++;
order_flags = RDP_ORDER_STANDARD;
@@ -1794,7 +2151,10 @@ xrdp_orders_send_palette(struct xrdp_orders *self, int *palette,
int len;
int i;
- xrdp_orders_check(self, 2000);
+ if (xrdp_orders_check(self, 2000) != 0)
+ {
+ return 1;
+ }
self->order_count++;
order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY;
out_uint8(self->out_s, order_flags);
@@ -1854,7 +2214,10 @@ xrdp_orders_send_raw_bitmap(struct xrdp_orders *self,
Bpp = (bpp + 7) / 8;
bufsize = (width + e) * height * Bpp;
- xrdp_orders_check(self, bufsize + 16);
+ if (xrdp_orders_check(self, bufsize + 16) != 0)
+ {
+ return 1;
+ }
self->order_count++;
order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY;
out_uint8(self->out_s, order_flags);
@@ -1961,7 +2324,10 @@ height(%d)", lines_sending, height);
bufsize = (int)(s->p - p);
Bpp = (bpp + 7) / 8;
- xrdp_orders_check(self, bufsize + 16);
+ if (xrdp_orders_check(self, bufsize + 16) != 0)
+ {
+ return 1;
+ }
self->order_count++;
order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY;
out_uint8(self->out_s, order_flags);
@@ -2015,15 +2381,28 @@ xrdp_orders_send_font(struct xrdp_orders *self,
int order_flags = 0;
int datasize = 0;
int len = 0;
+ int flags;
- datasize = FONT_DATASIZE(font_char);
- xrdp_orders_check(self, datasize + 18);
+ if (font_char->bpp == 8) /* alpha font */
+ {
+ datasize = ((font_char->width + 3) & ~3) * font_char->height;
+ flags = 8 | 0x4000;
+ }
+ else
+ {
+ datasize = FONT_DATASIZE(font_char);
+ flags = 8;
+ }
+ if (xrdp_orders_check(self, datasize + 18) != 0)
+ {
+ return 1;
+ }
self->order_count++;
order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY;
out_uint8(self->out_s, order_flags);
len = (datasize + 12) - 7; /* length after type minus 7 */
out_uint16_le(self->out_s, len);
- out_uint16_le(self->out_s, 8); /* flags */
+ out_uint16_le(self->out_s, flags);
out_uint8(self->out_s, RDP_ORDER_FONTCACHE); /* type */
out_uint8(self->out_s, font_index);
out_uint8(self->out_s, 1); /* num of chars */
@@ -2074,7 +2453,10 @@ xrdp_orders_send_raw_bitmap2(struct xrdp_orders *self,
Bpp = (bpp + 7) / 8;
bufsize = (width + e) * height * Bpp;
- xrdp_orders_check(self, bufsize + 14);
+ if (xrdp_orders_check(self, bufsize + 14) != 0)
+ {
+ return 1;
+ }
self->order_count++;
order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY;
out_uint8(self->out_s, order_flags);
@@ -2091,6 +2473,25 @@ xrdp_orders_send_raw_bitmap2(struct xrdp_orders *self,
i = cache_idx & 0xff;
out_uint8(self->out_s, i);
+ if (1 && Bpp == 3)
+ {
+ for (i = height - 1; i >= 0; i--)
+ {
+ for (j = 0; j < width; j++)
+ {
+ pixel = GETPIXEL32(data, j, i, width);
+ out_uint8(self->out_s, pixel);
+ out_uint8(self->out_s, pixel >> 8);
+ out_uint8(self->out_s, pixel >> 16);
+ }
+ for (j = 0; j < e; j++)
+ {
+ out_uint8s(self->out_s, Bpp);
+ }
+ }
+ }
+ else
+ {
for (i = height - 1; i >= 0; i--)
{
for (j = 0; j < width; j++)
@@ -2120,6 +2521,7 @@ xrdp_orders_send_raw_bitmap2(struct xrdp_orders *self,
out_uint8s(self->out_s, Bpp);
}
}
+ }
return 0;
}
@@ -2182,7 +2584,10 @@ height(%d)", lines_sending, height);
bufsize = (int)(s->p - p);
Bpp = (bpp + 7) / 8;
- xrdp_orders_check(self, bufsize + 14);
+ if (xrdp_orders_check(self, bufsize + 14) != 0)
+ {
+ return 1;
+ }
self->order_count++;
order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY;
out_uint8(self->out_s, order_flags);
@@ -2228,7 +2633,7 @@ xrdp_orders_send_as_jpeg(struct xrdp_orders *self,
return 1;
}
-#if defined(XRDP_FREERDP1)
+#if defined(XRDP_NEUTRINORDP)
/*****************************************************************************/
/* secondary drawing order (bitmap v3) using remotefx compression */
static int APP_CC
@@ -2246,7 +2651,9 @@ xrdp_orders_send_as_rfx(struct xrdp_orders *self,
return 0;
}
- if (width * height < 64)
+ LLOGLN(10, ("width %d height %d rfx_min_pixel %d", width, height,
+ self->rfx_min_pixel));
+ if (width * height < self->rfx_min_pixel)
{
return 0;
}
@@ -2267,7 +2674,10 @@ xrdp_orders_out_v3(struct xrdp_orders *self, int cache_id, int cache_idx,
int i;
Bpp = (bpp + 7) / 8;
- xrdp_orders_check(self, bufsize + 30);
+ if (xrdp_orders_check(self, bufsize + 30) != 0)
+ {
+ return 1;
+ }
self->order_count++;
order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY;
out_uint8(self->out_s, order_flags);
@@ -2306,7 +2716,7 @@ xrdp_orders_send_bitmap3(struct xrdp_orders *self,
struct stream *xr_s; /* xrdp stream */
struct stream *temp_s; /* xrdp stream */
struct xrdp_client_info *ci;
-#if defined(XRDP_FREERDP1)
+#if defined(XRDP_NEUTRINORDP)
STREAM *fr_s; /* FreeRDP stream */
RFX_CONTEXT *context;
RFX_RECT rect;
@@ -2321,7 +2731,7 @@ xrdp_orders_send_bitmap3(struct xrdp_orders *self,
if (ci->v3_codec_id == ci->rfx_codec_id)
{
-#if defined(XRDP_FREERDP1)
+#if defined(XRDP_NEUTRINORDP)
if (!xrdp_orders_send_as_rfx(self, width, height, bpp, hints))
{
@@ -2374,7 +2784,7 @@ xrdp_orders_send_bitmap3(struct xrdp_orders *self,
make_stream(temp_s);
init_stream(temp_s, 16384);
quality = ci->jpeg_prop[0];
- xrdp_jpeg_compress(data, width, height, xr_s, bpp, 16384,
+ xrdp_jpeg_compress(self->jpeg_han, data, width, height, xr_s, bpp, 16384,
height - 1, temp_s, e, quality);
s_mark_end(xr_s);
bufsize = (int)(xr_s->end - xr_s->data);
@@ -2406,7 +2816,10 @@ xrdp_orders_send_brush(struct xrdp_orders *self, int width, int height,
int order_flags = 0;
int len = 0;
- xrdp_orders_check(self, size + 12);
+ if (xrdp_orders_check(self, size + 12) != 0)
+ {
+ return 1;
+ }
self->order_count++;
order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY;
out_uint8(self->out_s, order_flags);
@@ -2448,7 +2861,10 @@ xrdp_orders_send_create_os_surface(struct xrdp_orders *self, int id,
bytes += num_del_list * 2;
}
- xrdp_orders_check(self, bytes);
+ if (xrdp_orders_check(self, bytes) != 0)
+ {
+ return 1;
+ }
self->order_count++;
order_flags = RDP_ORDER_SECONDARY;
order_flags |= 1 << 2; /* type RDP_ORDER_ALTSEC_CREATE_OFFSCR_BITMAP */
@@ -2489,7 +2905,10 @@ xrdp_orders_send_switch_os_surface(struct xrdp_orders *self, int id)
int order_flags;
int cache_id;
- xrdp_orders_check(self, 3);
+ if (xrdp_orders_check(self, 3) != 0)
+ {
+ return 1;
+ }
self->order_count++;
order_flags = RDP_ORDER_SECONDARY;
order_flags |= 0 << 2; /* type RDP_ORDER_ALTSEC_SWITCH_SURFACE */
diff --git a/libxrdp/xrdp_orders_rail.c b/libxrdp/xrdp_orders_rail.c
index bd91b543..91d4b607 100644
--- a/libxrdp/xrdp_orders_rail.c
+++ b/libxrdp/xrdp_orders_rail.c
@@ -34,7 +34,10 @@ xrdp_orders_send_window_delete(struct xrdp_orders *self, int window_id)
int field_present_flags;
order_size = 11;
- xrdp_orders_check(self, order_size);
+ if (xrdp_orders_check(self, order_size) != 0)
+ {
+ return 1;
+ }
self->order_count++;
order_flags = RDP_ORDER_SECONDARY;
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
@@ -64,7 +67,10 @@ xrdp_orders_send_window_cached_icon(struct xrdp_orders *self,
int field_present_flags;
order_size = 14;
- xrdp_orders_check(self, order_size);
+ if (xrdp_orders_check(self, order_size) != 0)
+ {
+ return 1;
+ }
self->order_count++;
order_flags = RDP_ORDER_SECONDARY;
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
@@ -155,7 +161,10 @@ xrdp_orders_send_window_icon(struct xrdp_orders *self,
order_size += icon_info->cmap_bytes + 2;
}
- xrdp_orders_check(self, order_size);
+ if (xrdp_orders_check(self, order_size) != 0)
+ {
+ return 1;
+ }
self->order_count++;
order_flags = RDP_ORDER_SECONDARY;
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
@@ -324,7 +333,10 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
order_size += 8 * window_state->num_visibility_rects;
}
- xrdp_orders_check(self, order_size);
+ if (xrdp_orders_check(self, order_size) != 0)
+ {
+ return 1;
+ }
self->order_count++;
order_flags = RDP_ORDER_SECONDARY;
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
@@ -465,7 +477,10 @@ xrdp_orders_send_notify_delete(struct xrdp_orders *self, int window_id,
int field_present_flags;
order_size = 15;
- xrdp_orders_check(self, order_size);
+ if (xrdp_orders_check(self, order_size) != 0)
+ {
+ return 1;
+ }
self->order_count++;
order_flags = RDP_ORDER_SECONDARY;
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
@@ -560,7 +575,10 @@ xrdp_orders_send_notify_new_update(struct xrdp_orders *self,
order_size += 3;
}
- xrdp_orders_check(self, order_size);
+ if (xrdp_orders_check(self, order_size) != 0)
+ {
+ return 1;
+ }
self->order_count++;
order_flags = RDP_ORDER_SECONDARY;
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
@@ -651,7 +669,10 @@ xrdp_orders_send_monitored_desktop(struct xrdp_orders *self,
order_size += mdo->num_window_ids * 4;
}
- xrdp_orders_check(self, order_size);
+ if (xrdp_orders_check(self, order_size) != 0)
+ {
+ return 1;
+ }
self->order_count++;
order_flags = RDP_ORDER_SECONDARY;
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c
index 93219968..9147287e 100644
--- a/libxrdp/xrdp_rdp.c
+++ b/libxrdp/xrdp_rdp.c
@@ -21,7 +21,7 @@
#include "libxrdp.h"
#include "log.h"
-#if defined(XRDP_FREERDP1)
+#if defined(XRDP_NEUTRINORDP)
#include <freerdp/codec/rfx.h>
#endif
@@ -88,15 +88,15 @@ xrdp_rdp_read_config(struct xrdp_client_info *client_info)
if (g_strcasecmp(item, "bitmap_cache") == 0)
{
- client_info->use_bitmap_cache = text2bool(value);
+ client_info->use_bitmap_cache = g_text2bool(value);
}
else if (g_strcasecmp(item, "bitmap_compression") == 0)
{
- client_info->use_bitmap_comp = text2bool(value);
+ client_info->use_bitmap_comp = g_text2bool(value);
}
else if (g_strcasecmp(item, "bulk_compression") == 0)
{
- client_info->use_bulk_comp = text2bool(value);
+ client_info->use_bulk_comp = g_text2bool(value);
}
else if (g_strcasecmp(item, "crypt_level") == 0)
{
@@ -121,23 +121,35 @@ xrdp_rdp_read_config(struct xrdp_client_info *client_info)
}
else if (g_strcasecmp(item, "allow_channels") == 0)
{
- client_info->channel_code = text2bool(value);
+ client_info->channel_code = g_text2bool(value);
if (client_info->channel_code == 0)
{
log_message(LOG_LEVEL_DEBUG,"Info - All channels are disabled");
}
}
+ else if (g_strcasecmp(item, "allow_multimon") == 0)
+ {
+ client_info->multimon = g_text2bool(value);
+ if (client_info->multimon == 0)
+ {
+ log_message(LOG_LEVEL_DEBUG,"Info - Multi monitor server support disabled");
+ }
+ }
else if (g_strcasecmp(item, "max_bpp") == 0)
{
client_info->max_bpp = g_atoi(value);
}
+ else if (g_strcasecmp(item, "rfx_min_pixel") == 0)
+ {
+ client_info->rfx_min_pixel = g_atoi(value);
+ }
else if (g_strcasecmp(item, "new_cursors") == 0)
{
- client_info->pointer_flags = text2bool(value) == 0 ? 2 : 0;
+ client_info->pointer_flags = g_text2bool(value) == 0 ? 2 : 0;
}
else if (g_strcasecmp(item, "require_credentials") == 0)
{
- client_info->require_credentials = text2bool(value);
+ client_info->require_credentials = g_text2bool(value);
}
}
@@ -146,7 +158,7 @@ xrdp_rdp_read_config(struct xrdp_client_info *client_info)
return 0;
}
-#if defined(XRDP_FREERDP1)
+#if defined(XRDP_NEUTRINORDP)
/*****************************************************************************/
static void
cpuid(tui32 info, tui32 *eax, tui32 *ebx, tui32 *ecx, tui32 *edx)
@@ -215,7 +227,7 @@ xrdp_rdp_create(struct xrdp_session *session, struct trans *trans)
xrdp_rdp_read_config(&self->client_info);
/* create sec layer */
self->sec_layer = xrdp_sec_create(self, trans, self->client_info.crypt_level,
- self->client_info.channel_code);
+ self->client_info.channel_code, self->client_info.multimon);
/* default 8 bit v1 color bitmap cache entries and size */
self->client_info.cache1_entries = 600;
self->client_info.cache1_size = 256;
@@ -227,7 +239,7 @@ xrdp_rdp_create(struct xrdp_session *session, struct trans *trans)
bytes = sizeof(self->client_info.client_ip) - 1;
g_write_ip_address(trans->sck, self->client_info.client_ip, bytes);
self->mppc_enc = mppc_enc_new(PROTO_RDP_50);
-#if defined(XRDP_FREERDP1)
+#if defined(XRDP_NEUTRINORDP)
self->rfx_enc = rfx_context_new();
rfx_context_set_cpu_opt(self->rfx_enc, xrdp_rdp_detect_cpu());
#endif
@@ -247,7 +259,7 @@ xrdp_rdp_delete(struct xrdp_rdp *self)
xrdp_sec_delete(self->sec_layer);
mppc_enc_free(self->mppc_enc);
-#if defined(XRDP_FREERDP1)
+#if defined(XRDP_NEUTRINORDP)
rfx_context_free((RFX_CONTEXT *)(self->rfx_enc));
#endif
g_free(self);
@@ -421,29 +433,26 @@ xrdp_rdp_send_data(struct xrdp_rdp *self, struct stream *s,
"tocomplen %d", mppc_enc->flags, mppc_enc->bytes_in_opb,
mppc_enc->historyOffset, tocomplen));
- if (mppc_enc->flags & RDP_MPPC_COMPRESSED)
- {
- clen = mppc_enc->bytes_in_opb + 18;
- pdulen = clen;
- ctype = mppc_enc->flags;
- iso_offset = (int)(s->iso_hdr - s->data);
- mcs_offset = (int)(s->mcs_hdr - s->data);
- sec_offset = (int)(s->sec_hdr - s->data);
- rdp_offset = (int)(s->rdp_hdr - s->data);
-
- /* outputBuffer has 64 bytes preceding it */
- ls.data = mppc_enc->outputBuffer - (rdp_offset + 18);
- ls.p = ls.data + rdp_offset;
- ls.end = ls.p + clen;
- ls.size = clen;
- ls.iso_hdr = ls.data + iso_offset;
- ls.mcs_hdr = ls.data + mcs_offset;
- ls.sec_hdr = ls.data + sec_offset;
- ls.rdp_hdr = ls.data + rdp_offset;
- ls.channel_hdr = 0;
- ls.next_packet = 0;
- s = &ls;
- }
+ clen = mppc_enc->bytes_in_opb + 18;
+ pdulen = clen;
+ ctype = mppc_enc->flags;
+ iso_offset = (int)(s->iso_hdr - s->data);
+ mcs_offset = (int)(s->mcs_hdr - s->data);
+ sec_offset = (int)(s->sec_hdr - s->data);
+ rdp_offset = (int)(s->rdp_hdr - s->data);
+
+ /* outputBuffer has 64 bytes preceding it */
+ ls.data = mppc_enc->outputBuffer - (rdp_offset + 18);
+ ls.p = ls.data + rdp_offset;
+ ls.end = ls.p + clen;
+ ls.size = clen;
+ ls.iso_hdr = ls.data + iso_offset;
+ ls.mcs_hdr = ls.data + mcs_offset;
+ ls.sec_hdr = ls.data + sec_offset;
+ ls.rdp_hdr = ls.data + rdp_offset;
+ ls.channel_hdr = 0;
+ ls.next_packet = 0;
+ s = &ls;
}
else
{
@@ -514,6 +523,11 @@ xrdp_rdp_parse_client_mcs_data(struct xrdp_rdp *self)
p = &(self->sec_layer->client_mcs_data);
p->p = p->data;
+ if (!s_check_rem(p, 31 + 2 + 2 + 120 + 2))
+ {
+ g_writeln("xrdp_rdp_parse_client_mcs_data: error");
+ return 1;
+ }
in_uint8s(p, 31);
in_uint16_le(p, self->client_info.width);
in_uint16_le(p, self->client_info.height);
@@ -524,6 +538,10 @@ xrdp_rdp_parse_client_mcs_data(struct xrdp_rdp *self)
switch (i)
{
case 0xca01:
+ if (!s_check_rem(p, 6 + 1))
+ {
+ return 1;
+ }
in_uint8s(p, 6);
in_uint8(p, i);
@@ -574,6 +592,14 @@ xrdp_rdp_incoming(struct xrdp_rdp *self)
MCS_USERCHANNEL_BASE;
xrdp_rdp_parse_client_mcs_data(self);
DEBUG(("out xrdp_rdp_incoming mcs channel %d", self->mcs_channel));
+
+ g_strncpy(self->client_info.client_addr,
+ self->sec_layer->mcs_layer->iso_layer->tcp_layer->trans->addr,
+ sizeof(self->client_info.client_addr) - 1);
+ g_strncpy(self->client_info.client_port,
+ self->sec_layer->mcs_layer->iso_layer->tcp_layer->trans->port,
+ sizeof(self->client_info.client_port) - 1);
+
return 0;
}
@@ -586,6 +612,7 @@ xrdp_rdp_send_demand_active(struct xrdp_rdp *self)
int caps_size;
int codec_caps_count;
int codec_caps_size;
+ int flags;
char *caps_count_ptr;
char *caps_size_ptr;
char *caps_ptr;
@@ -679,38 +706,38 @@ xrdp_rdp_send_demand_active(struct xrdp_rdp *self)
out_uint16_le(s, 0x2f); /* Number of fonts */
out_uint16_le(s, 0x22); /* Capability flags */
/* caps */
- out_uint8(s, 1); /* dest blt */
- out_uint8(s, 1); /* pat blt */
- out_uint8(s, 1); /* screen blt */
- out_uint8(s, 1); /* mem blt */
- out_uint8(s, 0); /* tri blt */
- out_uint8(s, 0); /* unused */
- out_uint8(s, 0); /* unused */
- out_uint8(s, 0); /* nine grid */
- out_uint8(s, 1); /* line to */
- out_uint8(s, 0); /* multi nine grid */
- out_uint8(s, 1); /* rect */
- out_uint8(s, 0); /* desk save */
- out_uint8(s, 0); /* unused */
- out_uint8(s, 0); /* unused */
- out_uint8(s, 0); /* unused */
- out_uint8(s, 0); /* multi dest blt */
- out_uint8(s, 0); /* multi pat blt */
- out_uint8(s, 0); /* multi screen blt */
- out_uint8(s, 1); /* multi rect */
- out_uint8(s, 0); /* fast index */
- out_uint8(s, 0); /* polygonSC ([MS-RDPEGDI], 2.2.2.2.1.1.2.16) */
- out_uint8(s, 0); /* polygonCB ([MS-RDPEGDI], 2.2.2.2.1.1.2.17) */
- out_uint8(s, 0); /* polyline */
- out_uint8(s, 0); /* unused */
- out_uint8(s, 0); /* fast glyph */
- out_uint8(s, 0); /* ellipse */
- out_uint8(s, 0); /* ellipse */
- out_uint8(s, 0); /* ? */
- out_uint8(s, 0); /* unused */
- out_uint8(s, 0); /* unused */
- out_uint8(s, 0); /* unused */
- out_uint8(s, 0); /* unused */
+ out_uint8(s, 1); /* NEG_DSTBLT_INDEX 0x00 0 */
+ out_uint8(s, 1); /* NEG_PATBLT_INDEX 0x01 1 */
+ out_uint8(s, 1); /* NEG_SCRBLT_INDEX 0x02 2 */
+ out_uint8(s, 1); /* NEG_MEMBLT_INDEX 0x03 3 */
+ out_uint8(s, 0); /* NEG_MEM3BLT_INDEX 0x04 4 */
+ out_uint8(s, 0); /* NEG_ATEXTOUT_INDEX 0x05 5 */
+ out_uint8(s, 0); /* NEG_AEXTTEXTOUT_INDEX 0x06 6 */
+ out_uint8(s, 0); /* NEG_DRAWNINEGRID_INDEX 0x07 7 */
+ out_uint8(s, 1); /* NEG_LINETO_INDEX 0x08 8 */
+ out_uint8(s, 0); /* NEG_MULTI_DRAWNINEGRID_INDEX 0x09 9 */
+ out_uint8(s, 1); /* NEG_OPAQUE_RECT_INDEX 0x0A 10 */
+ out_uint8(s, 0); /* NEG_SAVEBITMAP_INDEX 0x0B 11 */
+ out_uint8(s, 0); /* NEG_WTEXTOUT_INDEX 0x0C 12 */
+ out_uint8(s, 0); /* NEG_MEMBLT_V2_INDEX 0x0D 13 */
+ out_uint8(s, 0); /* NEG_MEM3BLT_V2_INDEX 0x0E 14 */
+ out_uint8(s, 0); /* NEG_MULTIDSTBLT_INDEX 0x0F 15 */
+ out_uint8(s, 0); /* NEG_MULTIPATBLT_INDEX 0x10 16 */
+ out_uint8(s, 0); /* NEG_MULTISCRBLT_INDEX 0x11 17 */
+ out_uint8(s, 1); /* NEG_MULTIOPAQUERECT_INDEX 0x12 18 */
+ out_uint8(s, 0); /* NEG_FAST_INDEX_INDEX 0x13 19 */
+ out_uint8(s, 0); /* NEG_POLYGON_SC_INDEX 0x14 20 */
+ out_uint8(s, 0); /* NEG_POLYGON_CB_INDEX 0x15 21 */
+ out_uint8(s, 0); /* NEG_POLYLINE_INDEX 0x16 22 */
+ out_uint8(s, 0); /* unused 0x17 23 */
+ out_uint8(s, 0); /* NEG_FAST_GLYPH_INDEX 0x18 24 */
+ out_uint8(s, 0); /* NEG_ELLIPSE_SC_INDEX 0x19 25 */
+ out_uint8(s, 0); /* NEG_ELLIPSE_CB_INDEX 0x1A 26 */
+ out_uint8(s, 1); /* NEG_GLYPH_INDEX_INDEX 0x1B 27 */
+ out_uint8(s, 0); /* NEG_GLYPH_WEXTTEXTOUT_INDEX 0x1C 28 */
+ out_uint8(s, 0); /* NEG_GLYPH_WLONGTEXTOUT_INDEX 0x1D 29 */
+ out_uint8(s, 0); /* NEG_GLYPH_WLONGEXTTEXTOUT_INDEX 0x1E 30 */
+ out_uint8(s, 0); /* unused 0x1F 31 */
out_uint16_le(s, 0x6a1);
/* declare support of bitmap cache rev3 */
out_uint16_le(s, XR_ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT);
@@ -773,18 +800,16 @@ xrdp_rdp_send_demand_active(struct xrdp_rdp *self)
caps_count++;
out_uint16_le(s, RDP_CAPSET_INPUT); /* 13(0xd) */
out_uint16_le(s, RDP_CAPLEN_INPUT); /* 88(0x58) */
+
+ /* INPUT_FLAG_SCANCODES 0x0001
+ INPUT_FLAG_MOUSEX 0x0004
+ INPUT_FLAG_FASTPATH_INPUT 0x0008
+ INPUT_FLAG_FASTPATH_INPUT2 0x0020 */
+ flags = 0x0001 | 0x0004;
if (self->client_info.use_fast_path & 2)
- {
- /* INPUT_FLAG_SCANCODES 0x0001
- INPUT_FLAG_FASTPATH_INPUT 0x0008
- INPUT_FLAG_FASTPATH_INPUT2 0x0020 */
- out_uint8(s, 1 | 8 | 0x20);
- }
- else
- {
- out_uint8(s, 1);
- }
- out_uint8s(s, 83);
+ flags |= 0x0008 | 0x0020;
+ out_uint16_le(s, flags);
+ out_uint8s(s, 82);
/* Remote Programs Capability Set */
caps_count++;
@@ -837,6 +862,11 @@ xrdp_process_capset_general(struct xrdp_rdp *self, struct stream *s,
{
int i;
+ if (len < 10 + 2)
+ {
+ g_writeln("xrdp_process_capset_general: error");
+ return 1;
+ }
in_uint8s(s, 10);
in_uint16_le(s, i);
/* use_compact_packets is pretty much 'use rdp5' */
@@ -858,6 +888,11 @@ xrdp_process_capset_order(struct xrdp_rdp *self, struct stream *s,
int cap_flags;
DEBUG(("order capabilities"));
+ if (len < 20 + 2 + 2 + 2 + 2 + 2 + 2 + 32 + 2 + 2 + 4 + 4 + 4 + 4)
+ {
+ g_writeln("xrdp_process_capset_order: error");
+ return 1;
+ }
in_uint8s(s, 20); /* Terminal desc, pad */
in_uint8s(s, 2); /* Cache X granularity */
in_uint8s(s, 2); /* Cache Y granularity */
@@ -915,13 +950,32 @@ static int APP_CC
xrdp_process_capset_bmpcache(struct xrdp_rdp *self, struct stream *s,
int len)
{
+ int i;
+
+ if (len < 24 + 2 + 2 + 2 + 2 + 2 + 2)
+ {
+ g_writeln("xrdp_process_capset_bmpcache: error");
+ return 1;
+ }
self->client_info.bitmap_cache_version |= 1;
in_uint8s(s, 24);
- in_uint16_le(s, self->client_info.cache1_entries);
+ /* cache 1 */
+ in_uint16_le(s, i);
+ i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX);
+ i = MAX(i, 0);
+ self->client_info.cache1_entries = i;
in_uint16_le(s, self->client_info.cache1_size);
- in_uint16_le(s, self->client_info.cache2_entries);
+ /* cache 2 */
+ in_uint16_le(s, i);
+ i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX);
+ i = MAX(i, 0);
+ self->client_info.cache2_entries = i;
in_uint16_le(s, self->client_info.cache2_size);
- in_uint16_le(s, self->client_info.cache3_entries);
+ /* caceh 3 */
+ in_uint16_le(s, i);
+ i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX);
+ i = MAX(i, 0);
+ self->client_info.cache3_entries = i;
in_uint16_le(s, self->client_info.cache3_size);
DEBUG(("cache1 entries %d size %d", self->client_info.cache1_entries,
self->client_info.cache1_size));
@@ -941,22 +995,30 @@ xrdp_process_capset_bmpcache2(struct xrdp_rdp *self, struct stream *s,
int Bpp = 0;
int i = 0;
+ if (len < 2 + 2 + 4 + 4 + 4)
+ {
+ g_writeln("xrdp_process_capset_bmpcache2: error");
+ return 1;
+ }
self->client_info.bitmap_cache_version |= 2;
Bpp = (self->client_info.bpp + 7) / 8;
in_uint16_le(s, i); /* cache flags */
self->client_info.bitmap_cache_persist_enable = i;
in_uint8s(s, 2); /* number of caches in set, 3 */
in_uint32_le(s, i);
- i = MIN(i, 2000);
+ i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX);
+ i = MAX(i, 0);
self->client_info.cache1_entries = i;
self->client_info.cache1_size = 256 * Bpp;
in_uint32_le(s, i);
- i = MIN(i, 2000);
+ i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX);
+ i = MAX(i, 0);
self->client_info.cache2_entries = i;
self->client_info.cache2_size = 1024 * Bpp;
in_uint32_le(s, i);
i = i & 0x7fffffff;
- i = MIN(i, 2000);
+ i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX);
+ i = MAX(i, 0);
self->client_info.cache3_entries = i;
self->client_info.cache3_size = 4096 * Bpp;
DEBUG(("cache1 entries %d size %d", self->client_info.cache1_entries,
@@ -975,6 +1037,11 @@ xrdp_process_capset_cache_v3_codec_id(struct xrdp_rdp *self, struct stream *s,
{
int codec_id;
+ if (len < 1)
+ {
+ g_writeln("xrdp_process_capset_cache_v3_codec_id: error");
+ return 1;
+ }
in_uint8(s, codec_id);
g_writeln("xrdp_process_capset_cache_v3_codec_id: cache_v3_codec_id %d",
codec_id);
@@ -992,6 +1059,11 @@ xrdp_process_capset_pointercache(struct xrdp_rdp *self, struct stream *s,
int colorPointerFlag;
int no_new_cursor;
+ if (len < 2 + 2 + 2)
+ {
+ g_writeln("xrdp_process_capset_pointercache: error");
+ return 1;
+ }
no_new_cursor = self->client_info.pointer_flags & 2;
in_uint16_le(s, colorPointerFlag);
self->client_info.pointer_flags = colorPointerFlag;
@@ -1028,6 +1100,11 @@ xrdp_process_capset_brushcache(struct xrdp_rdp *self, struct stream *s,
{
int code;
+ if (len < 4)
+ {
+ g_writeln("xrdp_process_capset_brushcache: error");
+ return 1;
+ }
in_uint32_le(s, code);
self->client_info.brush_cache_code = code;
return 0;
@@ -1040,12 +1117,11 @@ xrdp_process_offscreen_bmpcache(struct xrdp_rdp *self, struct stream *s,
{
int i32;
- if (len - 4 < 8)
+ if (len < 4 + 2 + 2)
{
- g_writeln("xrdp_process_offscreen_bmpcache: bad len");
+ g_writeln("xrdp_process_offscreen_bmpcache: error");
return 1;
}
-
in_uint32_le(s, i32);
self->client_info.offscreen_support_level = i32;
in_uint16_le(s, i32);
@@ -1066,12 +1142,11 @@ xrdp_process_capset_rail(struct xrdp_rdp *self, struct stream *s, int len)
{
int i32;
- if (len - 4 < 4)
+ if (len < 4)
{
- g_writeln("xrdp_process_capset_rail: bad len");
+ g_writeln("xrdp_process_capset_rail: error");
return 1;
}
-
in_uint32_le(s, i32);
self->client_info.rail_support_level = i32;
g_writeln("xrdp_process_capset_rail: rail_support_level %d",
@@ -1085,12 +1160,11 @@ xrdp_process_capset_window(struct xrdp_rdp *self, struct stream *s, int len)
{
int i32;
- if (len - 4 < 7)
+ if (len < 4 + 1 + 2)
{
- g_writeln("xrdp_process_capset_window: bad len");
+ g_writeln("xrdp_process_capset_window: error");
return 1;
}
-
in_uint32_le(s, i32);
self->client_info.wnd_support_level = i32;
in_uint8(s, i32);
@@ -1117,14 +1191,32 @@ xrdp_process_capset_codecs(struct xrdp_rdp *self, struct stream *s, int len)
char *codec_guid;
char *next_guid;
+ if (len < 1)
+ {
+ g_writeln("xrdp_process_capset_codecs: error");
+ return 1;
+ }
in_uint8(s, codec_count);
+ len--;
for (index = 0; index < codec_count; index++)
{
codec_guid = s->p;
+ if (len < 16 + 1 + 2)
+ {
+ g_writeln("xrdp_process_capset_codecs: error");
+ return 1;
+ }
in_uint8s(s, 16);
in_uint8(s, codec_id);
in_uint16_le(s, codec_properties_length);
+ len -= 16 + 1 + 2;
+ if (len < codec_properties_length)
+ {
+ g_writeln("xrdp_process_capset_codecs: error");
+ return 1;
+ }
+ len -= codec_properties_length;
next_guid = s->p + codec_properties_length;
if (g_memcmp(codec_guid, XR_CODEC_GUID_NSCODEC, 16) == 0)
@@ -1190,9 +1282,19 @@ xrdp_rdp_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
for (index = 0; index < num_caps; index++)
{
p = s->p;
+ if (!s_check_rem(s, 4))
+ {
+ g_writeln("xrdp_rdp_process_confirm_active: error 1");
+ return 1;
+ }
in_uint16_le(s, type);
in_uint16_le(s, len);
-
+ if ((len < 4) || !s_check_rem(s, len - 4))
+ {
+ g_writeln("xrdp_rdp_process_confirm_active: error len %d", len, s->end - s->p);
+ return 1;
+ }
+ len -= 4;
switch (type)
{
case RDP_CAPSET_GENERAL: /* 1 */
@@ -1278,7 +1380,7 @@ xrdp_rdp_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
break;
}
- s->p = p + len;
+ s->p = p + len + 4;
}
DEBUG(("out xrdp_rdp_process_confirm_active"));
@@ -1305,26 +1407,35 @@ xrdp_rdp_process_data_input(struct xrdp_rdp *self, struct stream *s)
int param2;
int time;
+ if (!s_check_rem(s, 4))
+ {
+ return 1;
+ }
in_uint16_le(s, num_events);
in_uint8s(s, 2); /* pad */
DEBUG(("in xrdp_rdp_process_data_input %d events", num_events));
for (index = 0; index < num_events; index++)
{
+ if (!s_check_rem(s, 12))
+ {
+ return 1;
+ }
in_uint32_le(s, time);
in_uint16_le(s, msg_type);
in_uint16_le(s, device_flags);
in_sint16_le(s, param1);
in_sint16_le(s, param2);
- DEBUG(("xrdp_rdp_process_data_input event %4.4x flags %4.4x param1 %d \
-param2 %d time %d", msg_type, device_flags, param1, param2, time));
+ DEBUG(("xrdp_rdp_process_data_input event %4.4x flags %4.4x param1 %d "
+ "param2 %d time %d", msg_type, device_flags, param1, param2, time));
if (self->session->callback != 0)
{
/* msg_type can be
RDP_INPUT_SYNCHRONIZE - 0
RDP_INPUT_SCANCODE - 4
- RDP_INPUT_MOUSE - 0x8001 */
+ RDP_INPUT_MOUSE - 0x8001
+ RDP_INPUT_MOUSEX - 0x8002 */
/* call to xrdp_wm.c : callback */
self->session->callback(self->session->id, msg_type, param1, param2,
device_flags, time);
diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c
index 726fcde4..f52a080d 100644
--- a/libxrdp/xrdp_sec.c
+++ b/libxrdp/xrdp_sec.c
@@ -138,7 +138,7 @@ hex_str_to_bin(char *in, char *out, int out_len)
/*****************************************************************************/
struct xrdp_sec *APP_CC
xrdp_sec_create(struct xrdp_rdp *owner, struct trans *trans, int crypt_level,
- int channel_code)
+ int channel_code, int multimon)
{
struct xrdp_sec *self;
@@ -168,6 +168,7 @@ xrdp_sec_create(struct xrdp_rdp *owner, struct trans *trans, int crypt_level,
}
self->channel_code = channel_code;
+ self->multimon = multimon;
if (self->decrypt_rc4_info != NULL)
{
@@ -331,12 +332,20 @@ unicode_in(struct stream *s, int uni_len, char *dst, int dst_len)
break;
}
+ if (!s_check_rem(s, 2))
+ {
+ return 1;
+ }
in_uint8(s, dst[dst_index]);
in_uint8s(s, 1);
dst_index++;
src_index += 2;
}
+ if (!s_check_rem(s, 2))
+ {
+ return 1;
+ }
in_uint8s(s, 2);
return 0;
}
@@ -359,6 +368,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s)
/* initialize (zero out) local variables */
g_memset(tmpdata, 0, sizeof(char) * 256);
+ if (!s_check_rem(s, 8))
+ {
+ return 1;
+ }
in_uint8s(s, 4);
in_uint32_le(s, flags);
DEBUG(("in xrdp_sec_process_logon_info flags $%x", flags));
@@ -398,6 +411,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s)
}
}
+ if (!s_check_rem(s, 2))
+ {
+ return 1;
+ }
in_uint16_le(s, len_domain);
if (len_domain > 511)
@@ -406,6 +423,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s)
return 1;
}
+ if (!s_check_rem(s, 2))
+ {
+ return 1;
+ }
in_uint16_le(s, len_user);
if (len_user > 511)
@@ -414,6 +435,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s)
return 1;
}
+ if (!s_check_rem(s, 2))
+ {
+ return 1;
+ }
in_uint16_le(s, len_password);
if (len_password > 511)
@@ -422,6 +447,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s)
return 1;
}
+ if (!s_check_rem(s, 2))
+ {
+ return 1;
+ }
in_uint16_le(s, len_program);
if (len_program > 511)
@@ -430,6 +459,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s)
return 1;
}
+ if (!s_check_rem(s, 2))
+ {
+ return 1;
+ }
in_uint16_le(s, len_directory);
if (len_directory > 511)
@@ -438,36 +471,76 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s)
return 1;
}
- unicode_in(s, len_domain, self->rdp_layer->client_info.domain, 255);
+ if (unicode_in(s, len_domain, self->rdp_layer->client_info.domain, 255) != 0)
+ {
+ return 1;
+ }
DEBUG(("domain %s", self->rdp_layer->client_info.domain));
- unicode_in(s, len_user, self->rdp_layer->client_info.username, 255);
+ if (unicode_in(s, len_user, self->rdp_layer->client_info.username, 255) != 0)
+ {
+ return 1;
+ }
DEBUG(("username %s", self->rdp_layer->client_info.username));
if (flags & RDP_LOGON_AUTO)
{
- unicode_in(s, len_password, self->rdp_layer->client_info.password, 255);
+ if (unicode_in(s, len_password, self->rdp_layer->client_info.password, 255) != 0)
+ {
+ return 1;
+ }
DEBUG(("flag RDP_LOGON_AUTO found"));
}
else
{
+ if (!s_check_rem(s, len_password + 2))
+ {
+ return 1;
+ }
in_uint8s(s, len_password + 2);
if (self->rdp_layer->client_info.require_credentials)
+ {
+ g_writeln("xrdp_sec_process_logon_info: credentials on cmd line is mandatory");
return 1; /* credentials on cmd line is mandatory */
+ }
}
- unicode_in(s, len_program, self->rdp_layer->client_info.program, 255);
+ if (unicode_in(s, len_program, self->rdp_layer->client_info.program, 255) != 0)
+ {
+ return 1;
+ }
DEBUG(("program %s", self->rdp_layer->client_info.program));
- unicode_in(s, len_directory, self->rdp_layer->client_info.directory, 255);
+ if (unicode_in(s, len_directory, self->rdp_layer->client_info.directory, 255) != 0)
+ {
+ return 1;
+ }
DEBUG(("directory %s", self->rdp_layer->client_info.directory));
if (flags & RDP_LOGON_BLOB)
{
+ if (!s_check_rem(s, 4))
+ {
+ return 1;
+ }
in_uint8s(s, 2); /* unknown */
in_uint16_le(s, len_ip);
- unicode_in(s, len_ip - 2, tmpdata, 255);
+ if (unicode_in(s, len_ip - 2, tmpdata, 255) != 0)
+ {
+ return 1;
+ }
+ if (!s_check_rem(s, 2))
+ {
+ return 1;
+ }
in_uint16_le(s, len_dll);
- unicode_in(s, len_dll - 2, tmpdata, 255);
- in_uint32_le(s, tzone); /* len of timetone */
+ if (unicode_in(s, len_dll - 2, tmpdata, 255) != 0)
+ {
+ return 1;
+ }
+ if (!s_check_rem(s, 4 + 62 + 22 + 62 + 26 + 4))
+ {
+ return 1;
+ }
+ in_uint32_le(s, tzone); /* len of timezone */
in_uint8s(s, 62); /* skip */
in_uint8s(s, 22); /* skip misc. */
in_uint8s(s, 62); /* skip */
@@ -676,17 +749,29 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan)
return 1;
}
+ if (!s_check_rem(s, 4))
+ {
+ return 1;
+ }
in_uint32_le(s, flags);
DEBUG((" in xrdp_sec_recv flags $%x", flags));
if (flags & SEC_ENCRYPT) /* 0x08 */
{
+ if (!s_check_rem(s, 8))
+ {
+ return 1;
+ }
in_uint8s(s, 8); /* signature */
xrdp_sec_decrypt(self, s->p, (int)(s->end - s->p));
}
if (flags & SEC_CLIENT_RANDOM) /* 0x01 */
{
+ if (!s_check_rem(s, 4 + 64))
+ {
+ return 1;
+ }
in_uint32_le(s, len);
in_uint8a(s, self->client_crypt_random, 64);
xrdp_sec_rsa_op(self->client_random, self->client_crypt_random,
@@ -836,23 +921,91 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s)
return 0;
}
+ if (!s_check_rem(s, 4))
+ {
+ return 1;
+ }
+
in_uint32_le(s, num_channels);
+ if (num_channels > 31)
+ {
+ return 1;
+ }
+
for (index = 0; index < num_channels; index++)
{
channel_item = (struct mcs_channel_item *)
g_malloc(sizeof(struct mcs_channel_item), 1);
+ if (!s_check_rem(s, 12))
+ {
+ return 1;
+ }
in_uint8a(s, channel_item->name, 8);
in_uint32_le(s, channel_item->flags);
channel_item->chanid = MCS_GLOBAL_CHANNEL + (index + 1);
- list_add_item(self->mcs_layer->channel_list, (long)channel_item);
+ list_add_item(self->mcs_layer->channel_list, (tintptr)channel_item);
DEBUG(("got channel flags %8.8x name %s", channel_item->flags,
channel_item->name));
}
return 0;
}
+/*****************************************************************************/
+/* reads the client monitors data */
+static int APP_CC
+xrdp_sec_process_mcs_data_monitors(struct xrdp_sec *self, struct stream *s)
+{
+ int index;
+ int monitorCount;
+ int flags;
+ struct xrdp_client_info *client_info = (struct xrdp_client_info *)NULL;
+
+ client_info = &(self->rdp_layer->client_info);
+ DEBUG(("processing monitors data, allow_multimon is %d", self->multimon));
+ /* this is an option set in xrdp.ini */
+ if (self->multimon != 1) /* are multi-monitors allowed ? */
+ {
+ DEBUG(("[INFO] xrdp_sec_process_mcs_data_monitors: multimon is not "
+ "allowed, skipping"));
+ return 0;
+ }
+ in_uint32_le(s, flags); /* flags */
+ //verify flags - must be 0x0
+ if (flags != 0)
+ {
+ DEBUG(("[ERROR] xrdp_sec_process_mcs_data_monitors: flags MUST be "
+ "zero, detected: %d", flags));
+ return 1;
+ }
+ in_uint32_le(s, monitorCount);
+ //verify monitorCount - max 16
+ if (monitorCount > 16)
+ {
+ DEBUG(("[ERROR] xrdp_sec_process_mcs_data_monitors: max allowed "
+ "monitors is 16, detected: %d", monitorCount));
+ return 1;
+ }
+
+ g_writeln("monitorCount= %d", monitorCount); // for debugging only
+
+ client_info->monitorCount = monitorCount;
+
+ /* Add client_monitor_data to client_info struct, will later pass to X11rdp */
+ for (index = 0; index < monitorCount; index++)
+ {
+ in_uint32_le(s, client_info->minfo[index].left);
+ in_uint32_le(s, client_info->minfo[index].top);
+ in_uint32_le(s, client_info->minfo[index].right);
+ in_uint32_le(s, client_info->minfo[index].bottom);
+ in_uint32_le(s, client_info->minfo[index].is_primary);
+
+ g_writeln("got a monitor: left= %d, top= %d, right= %d, bottom= %d, is_primary?= %d", client_info->minfo[index].left,
+ client_info->minfo[index].top, client_info->minfo[index].right, client_info->minfo[index].bottom, client_info->minfo[index].is_primary);
+ }
+ return 0;
+}
/*****************************************************************************/
/* process client mcs data, we need some things in here to create the server
mcs data */
@@ -864,10 +1017,14 @@ xrdp_sec_process_mcs_data(struct xrdp_sec *self)
int tag = 0;
int size = 0;
- s = &self->client_mcs_data;
+ s = &(self->client_mcs_data);
/* set p to beginning */
s->p = s->data;
/* skip header */
+ if (!s_check_rem(s, 23))
+ {
+ return 1;
+ }
in_uint8s(s, 23);
while (s_check_rem(s, 4))
@@ -890,10 +1047,19 @@ xrdp_sec_process_mcs_data(struct xrdp_sec *self)
case SEC_TAG_CLI_CRYPT:
break;
case SEC_TAG_CLI_CHANNELS:
- xrdp_sec_process_mcs_data_channels(self, s);
+ if (xrdp_sec_process_mcs_data_channels(self, s) != 0)
+ {
+ return 1;
+ }
break;
case SEC_TAG_CLI_4:
break;
+ case SEC_TAG_CLI_MONITOR:
+ if (xrdp_sec_process_mcs_data_monitors(self, s) != 0)
+ {
+ return 1;
+ }
+ break;
default:
g_writeln("error unknown xrdp_sec_process_mcs_data tag %d size %d",
tag, size);
@@ -940,13 +1106,32 @@ xrdp_sec_out_mcs_data(struct xrdp_sec *self)
out_uint8(s, 0x63); /* c */
out_uint8(s, 0x44); /* D */
out_uint8(s, 0x6e); /* n */
- out_uint16_be(s, 0x80fc + (num_channels_even * 2));
+ if (self->mcs_layer->iso_layer->selectedProtocol != -1)
+ { // Check for RDPNEGDATA availability
+ out_uint16_be(s, 0x80fc + (num_channels_even * 2) + 4);
+ }
+ else
+ {
+ out_uint16_be(s, 0x80fc + (num_channels_even * 2));
+ }
out_uint16_le(s, SEC_TAG_SRV_INFO);
- out_uint16_le(s, 8); /* len */
+ if (self->mcs_layer->iso_layer->selectedProtocol != -1)
+ {
+ out_uint16_le(s, 12); /* len */
+ }
+ else
+ {
+ out_uint16_le(s, 8); /* len */
+ }
out_uint8(s, 4); /* 4 = rdp5 1 = rdp4 */
out_uint8(s, 0);
out_uint8(s, 8);
out_uint8(s, 0);
+ if (self->mcs_layer->iso_layer->selectedProtocol != -1)
+ {
+ /* clientReqeustedProtocol */
+ out_uint32_le(s, self->mcs_layer->iso_layer->selectedProtocol);
+ }
out_uint16_le(s, SEC_TAG_SRV_CHANNELS);
out_uint16_le(s, 8 + (num_channels_even * 2)); /* len */
out_uint16_le(s, MCS_GLOBAL_CHANNEL); /* 1003, 0x03eb main channel */
@@ -999,7 +1184,7 @@ xrdp_sec_out_mcs_data(struct xrdp_sec *self)
/*****************************************************************************/
/* process the mcs client data we received from the mcs layer */
-static void APP_CC
+static int APP_CC
xrdp_sec_in_mcs_data(struct xrdp_sec *self)
{
struct stream *s = (struct stream *)NULL;
@@ -1011,6 +1196,10 @@ xrdp_sec_in_mcs_data(struct xrdp_sec *self)
s = &(self->client_mcs_data);
/* get hostname, its unicode */
s->p = s->data;
+ if (!s_check_rem(s, 47))
+ {
+ return 1;
+ }
in_uint8s(s, 47);
g_memset(client_info->hostname, 0, 32);
c = 1;
@@ -1018,21 +1207,33 @@ xrdp_sec_in_mcs_data(struct xrdp_sec *self)
while (index < 16 && c != 0)
{
+ if (!s_check_rem(s, 2))
+ {
+ return 1;
+ }
in_uint8(s, c);
in_uint8s(s, 1);
client_info->hostname[index] = c;
index++;
}
-
/* get build */
s->p = s->data;
+ if (!s_check_rem(s, 43 + 4))
+ {
+ return 1;
+ }
in_uint8s(s, 43);
in_uint32_le(s, client_info->build);
/* get keylayout */
s->p = s->data;
+ if (!s_check_rem(s, 39 + 4))
+ {
+ return 1;
+ }
in_uint8s(s, 39);
in_uint32_le(s, client_info->keylayout);
s->p = s->data;
+ return 0;
}
/*****************************************************************************/
@@ -1059,7 +1260,8 @@ xrdp_sec_incoming(struct xrdp_sec *self)
if (file_by_name_read_section(key_file, "keys", items, values) != 0)
{
/* this is a show stopper */
- log_message(LOG_LEVEL_ALWAYS,"XRDP cannot read file: %s (check permissions)", key_file);
+ log_message(LOG_LEVEL_ALWAYS, "XRDP cannot read file: %s "
+ "(check permissions)", key_file);
list_delete(items);
list_delete(values);
return 1;
@@ -1105,7 +1307,10 @@ xrdp_sec_incoming(struct xrdp_sec *self)
(int)(self->server_mcs_data.end - self->server_mcs_data.data));
#endif
DEBUG((" out xrdp_sec_incoming"));
- xrdp_sec_in_mcs_data(self);
+ if (xrdp_sec_in_mcs_data(self) != 0)
+ {
+ return 1;
+ }
return 0;
}
diff --git a/sesman/auth.h b/sesman/auth.h
index 39acc0b8..e06b9eb3 100644
--- a/sesman/auth.h
+++ b/sesman/auth.h
@@ -57,6 +57,16 @@ auth_start_session(long in_val, int in_display);
*
*/
int DEFAULT_CC
+auth_stop_session(long in_val);
+
+/**
+ *
+ * @brief FIXME
+ * @param in_val
+ * @return 0 on success, 1 on failure
+ *
+ */
+int DEFAULT_CC
auth_end(long in_val);
/**
diff --git a/sesman/chansrv/Makefile.am b/sesman/chansrv/Makefile.am
index 7cecdb1e..2d73f05c 100644
--- a/sesman/chansrv/Makefile.am
+++ b/sesman/chansrv/Makefile.am
@@ -8,7 +8,8 @@ EXTRA_DIST = \
drdynvc.h \
rail.h \
sound.h \
- xcommon.h
+ xcommon.h \
+ mlog.h
EXTRA_DEFINES =
EXTRA_INCLUDES =
@@ -51,7 +52,8 @@ xrdp_chansrv_SOURCES = \
xcommon.c \
drdynvc.c \
chansrv_fuse.c \
- irp.c
+ irp.c \
+ fifo.c
xrdp_chansrv_LDFLAGS = \
$(EXTRA_FLAGS)
@@ -59,5 +61,5 @@ xrdp_chansrv_LDFLAGS = \
xrdp_chansrv_LDADD = \
-L/usr/X11R6/lib \
$(top_builddir)/common/libcommon.la \
- -lX11 -lXfixes \
+ -lX11 -lXfixes -lXrandr \
$(EXTRA_LIBS)
diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c
index 388d0273..01c6a43d 100644
--- a/sesman/chansrv/chansrv.c
+++ b/sesman/chansrv/chansrv.c
@@ -72,10 +72,156 @@ tbus g_exec_mutex;
tbus g_exec_sem;
int g_exec_pid = 0;
+#define ARRAYSIZE(x) (sizeof(x)/sizeof(*(x)))
+
/* each time we create a DVC we need a unique DVC channel id */
/* this variable gets bumped up once per DVC we create */
tui32 g_dvc_chan_id = 100;
+struct timeout_obj
+{
+ tui32 mstime;
+ void *data;
+ void (*callback)(void *data);
+ struct timeout_obj *next;
+};
+
+static struct timeout_obj *g_timeout_head = 0;
+static struct timeout_obj *g_timeout_tail = 0;
+
+/*****************************************************************************/
+int APP_CC
+add_timeout(int msoffset, void (*callback)(void *data), void *data)
+{
+ struct timeout_obj *tobj;
+ tui32 now;
+
+ LOG(10, ("add_timeout:"));
+ now = g_time3();
+ tobj = g_malloc(sizeof(struct timeout_obj), 1);
+ tobj->mstime = now + msoffset;
+ tobj->callback = callback;
+ tobj->data = data;
+ if (g_timeout_tail == 0)
+ {
+ g_timeout_head = tobj;
+ g_timeout_tail = tobj;
+ }
+ else
+ {
+ g_timeout_tail->next = tobj;
+ g_timeout_tail = tobj;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+get_timeout(int *timeout)
+{
+ struct timeout_obj *tobj;
+ tui32 now;
+ int ltimeout;
+
+ LOG(10, ("get_timeout:"));
+ ltimeout = *timeout;
+ if (ltimeout < 1)
+ {
+ ltimeout = 0;
+ }
+ tobj = g_timeout_head;
+ if (tobj != 0)
+ {
+ now = g_time3();
+ while (tobj != 0)
+ {
+ LOG(10, (" now %u tobj->mstime %u", now, tobj->mstime));
+ if (now < tobj->mstime)
+ {
+ ltimeout = tobj->mstime - now;
+ }
+ tobj = tobj->next;
+ }
+ }
+ if (ltimeout > 0)
+ {
+ LOG(10, (" ltimeout %d", ltimeout));
+ if (*timeout < 1)
+ {
+ *timeout = ltimeout;
+ }
+ else
+ {
+ if (*timeout > ltimeout)
+ {
+ *timeout = ltimeout;
+ }
+ }
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+check_timeout(void)
+{
+ struct timeout_obj *tobj;
+ struct timeout_obj *last_tobj;
+ struct timeout_obj *temp_tobj;
+ int count;
+ tui32 now;
+
+ LOG(10, ("check_timeout:"));
+ count = 0;
+ tobj = g_timeout_head;
+ if (tobj != 0)
+ {
+ last_tobj = 0;
+ while (tobj != 0)
+ {
+ count++;
+ now = g_time3();
+ if (now >= tobj->mstime)
+ {
+ tobj->callback(tobj->data);
+ if (last_tobj == 0)
+ {
+ g_timeout_head = tobj->next;
+ if (g_timeout_head == 0)
+ {
+ g_timeout_tail = 0;
+ }
+ }
+ else
+ {
+ last_tobj->next = tobj->next;
+ if (g_timeout_tail == tobj)
+ {
+ g_timeout_tail = last_tobj;
+ }
+ }
+ temp_tobj = tobj;
+ tobj = tobj->next;
+ g_free(temp_tobj);
+ }
+ else
+ {
+ last_tobj = tobj;
+ tobj = tobj->next;
+ }
+ }
+ }
+ LOG(10, (" count %d", count));
+ return 0;
+}
+
+/*****************************************************************************/
+int DEFAULT_CC
+g_is_term(void)
+{
+ return g_is_wait_obj_set(g_term_event);
+}
+
/*****************************************************************************/
/* add data to chan_item, on its way to the client */
/* returns error */
@@ -149,11 +295,11 @@ send_data_from_chan_item(struct chan_item *chan_item)
out_uint32_le(s, cod->s->size);
out_uint8a(s, cod->s->p, size);
s_mark_end(s);
- LOGM((LOG_LEVEL_DEBUG, "chansrv::send_channel_data: -- "
+ LOGM((LOG_LEVEL_DEBUG, "chansrv::send_data_from_chan_item: -- "
"size %d chan_flags 0x%8.8x", size, chan_flags));
g_sent = 1;
- error = trans_force_write(g_con_trans);
+ error = trans_write_copy(g_con_trans);
if (error != 0)
{
return 1;
@@ -230,6 +376,31 @@ send_channel_data(int chan_id, char *data, int size)
/*****************************************************************************/
/* returns error */
+int APP_CC
+send_rail_drawing_orders(char* data, int size)
+{
+ LOGM((LOG_LEVEL_DEBUG, "chansrv::send_rail_drawing_orders: size %d", size));
+
+ struct stream* s;
+ int error;
+
+ s = trans_get_out_s(g_con_trans, 8192);
+ out_uint32_le(s, 0); /* version */
+ out_uint32_le(s, 8 + 8 + size); /* size */
+ out_uint32_le(s, 10); /* msg id */
+ out_uint32_le(s, 8 + size); /* size */
+ out_uint8a(s, data, size);
+ s_mark_end(s);
+ error = trans_force_write(g_con_trans);
+ if (error != 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
static int APP_CC
send_init_response_message(void)
{
@@ -248,7 +419,7 @@ send_init_response_message(void)
out_uint32_le(s, 2); /* msg id */
out_uint32_le(s, 8); /* size */
s_mark_end(s);
- return trans_force_write(g_con_trans);
+ return trans_write_copy(g_con_trans);
}
/*****************************************************************************/
@@ -271,7 +442,7 @@ send_channel_setup_response_message(void)
out_uint32_le(s, 4); /* msg id */
out_uint32_le(s, 8); /* size */
s_mark_end(s);
- return trans_force_write(g_con_trans);
+ return trans_write_copy(g_con_trans);
}
/*****************************************************************************/
@@ -294,7 +465,7 @@ send_channel_data_response_message(void)
out_uint32_le(s, 6); /* msg id */
out_uint32_le(s, 8); /* size */
s_mark_end(s);
- return trans_force_write(g_con_trans);
+ return trans_write_copy(g_con_trans);
}
/*****************************************************************************/
@@ -493,7 +664,7 @@ process_message_channel_data(struct stream *s)
if (chan_flags & 2) /* last */
{
s_mark_end(ls);
- trans_force_write(g_api_con_trans);
+ trans_write_copy(g_api_con_trans);
}
}
}
@@ -844,13 +1015,15 @@ setup_listen(void)
if (g_use_unix_socket)
{
- g_lis_trans = trans_create(2, 8192, 8192);
+ g_lis_trans = trans_create(TRANS_MODE_UNIX, 8192, 8192);
+ g_lis_trans->is_term = g_is_term;
g_snprintf(port, 255, "/tmp/.xrdp/xrdp_chansrv_socket_%d",
7200 + g_display_num);
}
else
{
- g_lis_trans = trans_create(1, 8192, 8192);
+ g_lis_trans = trans_create(TRANS_MODE_TCP, 8192, 8192);
+ g_lis_trans->is_term = g_is_term;
g_snprintf(port, 255, "%d", 7200 + g_display_num);
}
@@ -875,6 +1048,7 @@ setup_api_listen(void)
int error = 0;
g_api_lis_trans = trans_create(TRANS_MODE_UNIX, 8192 * 4, 8192 * 4);
+ g_api_lis_trans->is_term = g_is_term;
g_snprintf(port, 255, "/tmp/.xrdp/xrdpapi_%d", g_display_num);
g_api_lis_trans->trans_conn_in = my_api_trans_conn_in;
error = trans_listen(g_api_lis_trans, port);
@@ -894,7 +1068,9 @@ THREAD_RV THREAD_CC
channel_thread_loop(void *in_val)
{
tbus objs[32];
+ tbus wobjs[32];
int num_objs;
+ int num_wobjs;
int timeout;
int error;
THREAD_RV rv;
@@ -908,13 +1084,15 @@ channel_thread_loop(void *in_val)
{
timeout = -1;
num_objs = 0;
+ num_wobjs = 0;
objs[num_objs] = g_term_event;
num_objs++;
trans_get_wait_objs(g_lis_trans, objs, &num_objs);
trans_get_wait_objs(g_api_lis_trans, objs, &num_objs);
- while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0)
+ while (g_obj_wait(objs, num_objs, wobjs, num_wobjs, timeout) == 0)
{
+ check_timeout();
if (g_is_wait_obj_set(g_term_event))
{
LOGM((LOG_LEVEL_INFO, "channel_thread_loop: g_term_event set"));
@@ -987,16 +1165,19 @@ channel_thread_loop(void *in_val)
xfuse_check_wait_objs();
timeout = -1;
num_objs = 0;
+ num_wobjs = 0;
objs[num_objs] = g_term_event;
num_objs++;
trans_get_wait_objs(g_lis_trans, objs, &num_objs);
- trans_get_wait_objs(g_con_trans, objs, &num_objs);
+ trans_get_wait_objs_rw(g_con_trans, objs, &num_objs,
+ wobjs, &num_wobjs);
trans_get_wait_objs(g_api_lis_trans, objs, &num_objs);
trans_get_wait_objs(g_api_con_trans, objs, &num_objs);
xcommon_get_wait_objs(objs, &num_objs, &timeout);
sound_get_wait_objs(objs, &num_objs, &timeout);
dev_redir_get_wait_objs(objs, &num_objs, &timeout);
xfuse_get_wait_objs(objs, &num_objs, &timeout);
+ get_timeout(&timeout);
} /* end while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0) */
}
@@ -1034,7 +1215,7 @@ child_signal_handler(int sig)
{
int i1;
- LOG(10, ("child_signal_handler:"));
+ LOG(0, ("child_signal_handler:"));
do
{
@@ -1051,6 +1232,14 @@ child_signal_handler(int sig)
while (i1 >= 0);
}
+void DEFAULT_CC
+segfault_signal_handler(int sig)
+{
+ LOG(0, ("segfault_signal_handler: entered......."));
+ xfuse_deinit();
+ exit(0);
+}
+
/*****************************************************************************/
static int APP_CC
get_display_num_from_display(char *display_text)
@@ -1164,6 +1353,47 @@ read_ini(void)
}
/*****************************************************************************/
+static char* APP_CC
+get_log_path()
+{
+ char* log_path = 0;
+
+ log_path = g_getenv("CHANSRV_LOG_PATH");
+ if (log_path == 0)
+ {
+ log_path = g_getenv("HOME");
+ }
+ return log_path;
+}
+
+/*****************************************************************************/
+static unsigned int APP_CC
+get_log_level(const char* level_str, unsigned int default_level)
+{
+ static const char* levels[] = {
+ "LOG_LEVEL_ALWAYS",
+ "LOG_LEVEL_ERROR",
+ "LOG_LEVEL_WARNING",
+ "LOG_LEVEL_INFO",
+ "LOG_LEVEL_DEBUG"
+ };
+ unsigned int i;
+
+ if (level_str == NULL || level_str[0] == 0)
+ {
+ return default_level;
+ }
+ for (i = 0; i < ARRAYSIZE(levels); ++i)
+ {
+ if (g_strcasecmp(levels[i], level_str) == 0)
+ {
+ return i;
+ }
+ }
+ return default_level;
+}
+
+/*****************************************************************************/
static int APP_CC
run_exec(void)
{
@@ -1197,19 +1427,19 @@ main(int argc, char **argv)
tbus waiters[4];
int pid = 0;
char text[256];
- char *home_text;
+ char* log_path;
char *display_text;
char log_file[256];
enum logReturns error;
struct log_config logconfig;
+ unsigned int log_level;
g_init("xrdp-chansrv"); /* os_calls */
- home_text = g_getenv("HOME");
-
- if (home_text == 0)
+ log_path = get_log_path();
+ if (log_path == 0)
{
- g_writeln("error reading HOME environment variable");
+ g_writeln("error reading CHANSRV_LOG_PATH and HOME environment variable");
g_deinit();
return 1;
}
@@ -1217,10 +1447,12 @@ main(int argc, char **argv)
read_ini();
pid = g_getpid();
+ log_level = get_log_level(g_getenv("CHANSRV_LOG_LEVEL"), LOG_LEVEL_ERROR);
+
/* starting logging subsystem */
g_memset(&logconfig, 0, sizeof(struct log_config));
logconfig.program_name = "XRDP-Chansrv";
- g_snprintf(log_file, 255, "%s/xrdp-chansrv.log", home_text);
+ g_snprintf(log_file, 255, "%s/xrdp-chansrv.log", log_path);
g_writeln("chansrv::main: using log file [%s]", log_file);
if (g_file_exist(log_file))
@@ -1230,7 +1462,7 @@ main(int argc, char **argv)
logconfig.log_file = log_file;
logconfig.fd = -1;
- logconfig.log_level = LOG_LEVEL_ERROR;
+ logconfig.log_level = log_level;
logconfig.enable_syslog = 0;
logconfig.syslog_level = 0;
error = log_start_from_param(&logconfig);
@@ -1262,6 +1494,8 @@ main(int argc, char **argv)
g_signal_user_interrupt(term_signal_handler); /* SIGINT */
g_signal_pipe(nil_signal_handler); /* SIGPIPE */
g_signal_child_stop(child_signal_handler); /* SIGCHLD */
+ g_signal_segfault(segfault_signal_handler);
+
display_text = g_getenv("DISPLAY");
LOGM((LOG_LEVEL_INFO, "main: DISPLAY env var set to %s", display_text));
get_display_num_from_display(display_text);
diff --git a/sesman/chansrv/chansrv.h b/sesman/chansrv/chansrv.h
index bca30ca4..a3e8ed51 100644
--- a/sesman/chansrv/chansrv.h
+++ b/sesman/chansrv/chansrv.h
@@ -1,8 +1,8 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
- * Copyright (C) Jay Sorg 2009-2012
- * Copyright (C) Laxmikant Rashinkar 2009-2012
+ * Copyright (C) Jay Sorg 2009-2013
+ * Copyright (C) Laxmikant Rashinkar 2009-2013
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -54,8 +54,13 @@ struct xrdp_api_data
int is_connected;
};
+int DEFAULT_CC
+g_is_term(void);
+
int APP_CC send_channel_data(int chan_id, char *data, int size);
+int APP_CC send_rail_drawing_orders(char* data, int size);
int APP_CC main_cleanup(void);
+int APP_CC add_timeout(int msoffset, void (*callback)(void* data), void* data);
int APP_CC find_empty_slot_in_dvc_channels();
struct xrdp_api_data * APP_CC struct_from_dvc_chan_id(tui32 dvc_chan_id);
int remove_struct_with_chan_id(tui32 dvc_chan_id);
diff --git a/sesman/chansrv/chansrv_fuse.c b/sesman/chansrv/chansrv_fuse.c
index 572679eb..2eb78ea0 100644
--- a/sesman/chansrv/chansrv_fuse.c
+++ b/sesman/chansrv/chansrv_fuse.c
@@ -102,6 +102,7 @@ void xfuse_devredir_cb_file_close(void *vp) {}
#include "os_calls.h"
#include "chansrv_fuse.h"
#include "list.h"
+#include "fifo.h"
#define min(x, y) ((x) < (y) ? (x) : (y))
@@ -223,6 +224,16 @@ struct dir_info
int index;
};
+/* queue FUSE opendir commands so we run only one at a time */
+struct opendir_req
+{
+ fuse_req_t req;
+ fuse_ino_t ino;
+ struct fuse_file_info *fi;
+};
+
+FIFO g_fifo_opendir;
+
static struct list *g_req_list = 0;
static struct xrdp_fs g_xrdp_fs; /* an inst of xrdp file system */
static char *g_mount_point = 0; /* our FUSE mount point */
@@ -338,19 +349,22 @@ static void xfuse_cb_create(fuse_req_t req, fuse_ino_t parent,
static void xfuse_cb_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,
struct fuse_file_info *fi);
-/* clipboard calls */
-int clipboard_request_file_data(int stream_id, int lindex, int offset,
- int request_bytes);
-
static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
int to_set, struct fuse_file_info *fi);
static void xfuse_cb_opendir(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi);
+static int xfuse_proc_opendir_req(fuse_req_t req, fuse_ino_t ino,
+ struct fuse_file_info *fi);
+
static void xfuse_cb_releasedir(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi);
+/* clipboard calls */
+int clipboard_request_file_data(int stream_id, int lindex, int offset,
+ int request_bytes);
+
/* misc calls */
static void xfuse_mark_as_stale(int pinode);
static void xfuse_delete_stale_entries(int pinode);
@@ -403,6 +417,9 @@ int xfuse_init()
if (xfuse_init_xrdp_fs())
return -1;
+ /* setup FIFOs */
+ fifo_init(&g_fifo_opendir, 30);
+
/* setup FUSE callbacks */
g_memset(&g_xfuse_ops, 0, sizeof(g_xfuse_ops));
g_xfuse_ops.lookup = xfuse_cb_lookup;
@@ -424,6 +441,8 @@ int xfuse_init()
fuse_opt_add_arg(&args, "xrdp-chansrv");
fuse_opt_add_arg(&args, g_fuse_root_path);
+ //fuse_opt_add_arg(&args, "-s"); /* single threaded mode */
+ //fuse_opt_add_arg(&args, "-d"); /* debug mode */
if (xfuse_init_lib(&args))
{
@@ -444,6 +463,7 @@ int xfuse_init()
int xfuse_deinit()
{
xfuse_deinit_xrdp_fs();
+ fifo_deinit(&g_fifo_opendir);
if (g_ch != 0)
{
@@ -901,12 +921,11 @@ static int xfuse_deinit_xrdp_fs()
static int xfuse_is_inode_valid(int ino)
{
- /* our lowest ino is FIRST_INODE */
- if (ino < FIRST_INODE)
+ /* is ino present in our table? */
+ if ((ino < FIRST_INODE) || (ino >= g_xrdp_fs.next_node))
return 0;
- /* is ino present in our table? */
- if (ino >= g_xrdp_fs.next_node)
+ if (g_xrdp_fs.inode_table[ino] == NULL)
return 0;
return 1;
@@ -989,6 +1008,11 @@ static void xfuse_dump_fs()
log_debug("found %d entries", g_xrdp_fs.num_entries - FIRST_INODE);
+#if 0
+ log_debug("not dumping xrdp fs");
+ return;
+#endif
+
for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++)
{
if ((xinode = g_xrdp_fs.inode_table[i]) == NULL)
@@ -1229,6 +1253,9 @@ static int xfuse_delete_file_with_xinode(XRDP_INODE *xinode)
if ((xinode == NULL) || (xinode->mode & S_IFDIR))
return -1;
+ log_always("deleting: inode=%d name=%s", xinode->inode, xinode->name);
+ log_debug("deleting: inode=%d name=%s", xinode->inode, xinode->name);
+
g_xrdp_fs.inode_table[xinode->parent_inode]->nentries--;
g_xrdp_fs.inode_table[xinode->inode] = NULL;
free(xinode);
@@ -1281,6 +1308,12 @@ static int xfuse_recursive_delete_dir_with_xinode(XRDP_INODE *xinode)
if ((xinode == NULL) || (xinode->mode & S_IFREG))
return -1;
+ log_always("recursively deleting dir with inode=%d name=%s",
+ xinode->inode, xinode->name);
+
+ log_debug("recursively deleting dir with inode=%d name=%s",
+ xinode->inode, xinode->name);
+
for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++)
{
if ((xip = g_xrdp_fs.inode_table[i]) == NULL)
@@ -1342,60 +1375,6 @@ static void xfuse_update_xrdpfs_size()
g_xrdp_fs.inode_table = vp;
}
-/* LK_TODO do we still need this function */
-#if 0
-static void xfuse_enum_dir(fuse_req_t req, fuse_ino_t ino, size_t size,
- off_t off, struct fuse_file_info *fi)
-{
- XRDP_INODE *xinode;
- XRDP_INODE *xinode1;
- struct dirbuf b;
- int first_time = 1;
- int i;
-
- memset(&b, 0, sizeof(struct dirbuf));
-
- for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++)
- {
- if ((xinode = g_xrdp_fs.inode_table[i]) == NULL)
- continue;
-
- /* match parent inode */
- if (xinode->parent_inode != ino)
- continue;
-
- if (first_time)
- {
- first_time = 0;
- if (ino == 1)
- {
- xfuse_dirbuf_add(req, &b, ".", 1);
- xfuse_dirbuf_add(req, &b, "..", 1);
- }
- else
- {
- xinode1 = g_xrdp_fs.inode_table[ino];
- xfuse_dirbuf_add(req, &b, ".", ino);
- xfuse_dirbuf_add(req, &b, "..", xinode1->parent_inode);
- }
- }
-
- xfuse_dirbuf_add(req, &b, xinode->name, xinode->inode);
- }
-
- if (!first_time)
- {
- if (off < b.size)
- fuse_reply_buf(req, b.p + off, min(b.size - off, size));
- else
- fuse_reply_buf(req, NULL, 0);
- }
-
- if (b.p)
- free(b.p);
-}
-#endif
-
/******************************************************************************
** **
** callbacks for devredir **
@@ -1464,8 +1443,9 @@ void xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode)
void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus)
{
- XFUSE_INFO *fip;
- struct dir_info *di;
+ XFUSE_INFO *fip;
+ struct dir_info *di;
+ struct opendir_req *odreq;
log_debug("vp=%p IoStatus=0x%x", vp, IoStatus);
@@ -1473,7 +1453,7 @@ void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus)
if (fip == NULL)
{
log_debug("fip is NULL");
- return;
+ goto done;
}
if (IoStatus != 0)
@@ -1506,6 +1486,22 @@ done:
if (fip)
free(fip);
+
+ /* remove current request */
+ g_free(fifo_remove(&g_fifo_opendir));
+
+ while (1)
+ {
+ /* process next request */
+ odreq = fifo_peek(&g_fifo_opendir);
+ if (!odreq)
+ return;
+
+ if (xfuse_proc_opendir_req(odreq->req, odreq->ino, odreq->fi))
+ g_free(fifo_remove(&g_fifo_opendir)); /* req failed */
+ else
+ break; /* req has been queued */
+ }
}
void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId,
@@ -1903,15 +1899,19 @@ static void xfuse_cb_getattr(fuse_req_t req, fuse_ino_t ino,
}
xino = g_xrdp_fs.inode_table[ino];
+ if (!xino)
+ {
+ log_debug("****** invalid ino=%d", (int) ino);
+ fuse_reply_err(req, EBADF);
+ return;
+ }
memset(&stbuf, 0, sizeof(stbuf));
stbuf.st_ino = ino;
stbuf.st_mode = xino->mode;
stbuf.st_nlink = xino->nlink;
stbuf.st_size = xino->size;
-
fuse_reply_attr(req, &stbuf, 1.0);
- log_debug("exiting");
}
/**
@@ -1977,8 +1977,7 @@ static void xfuse_cb_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
int i;
int first_time;
- log_debug("req=%p inode=%d name=%s size=%d offset=%d", req, ino,
- g_xrdp_fs.inode_table[ino]->name, size, off);
+ log_debug("req=%p inode=%d size=%d offset=%d", req, ino, size, off);
/* do we have a valid inode? */
if (!xfuse_is_inode_valid(ino))
@@ -2014,6 +2013,12 @@ static void xfuse_cb_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
{
first_time = 0;
ti = g_xrdp_fs.inode_table[ino];
+ if (!ti)
+ {
+ log_debug("****** g_xrdp_fs.inode_table[%d] is NULL", ino);
+ fuse_reply_buf(req, NULL, 0);
+ return;
+ }
xfuse_dirbuf_add1(req, &b, ".", ino);
xfuse_dirbuf_add1(req, &b, "..", ti->parent_inode);
}
@@ -2451,6 +2456,12 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino,
/* if ino points to a dir, fail the open request */
xinode = g_xrdp_fs.inode_table[ino];
+ if (!xinode)
+ {
+ log_debug("****** g_xrdp_fs.inode_table[%d] is NULL", ino);
+ fuse_reply_err(req, EBADF);
+ return;
+ }
if (xinode->mode & S_IFDIR)
{
log_debug("reading a dir not allowed!");
@@ -2491,8 +2502,6 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino,
fip->name[1023] = 0;
fip->reply_type = RT_FUSE_REPLY_OPEN;
- /* LK_TODO need to handle open permissions */
-
/* we want path minus 'root node of the share' */
if ((cptr = strchr(full_path, '/')) == NULL)
{
@@ -2532,6 +2541,12 @@ static void xfuse_cb_release(fuse_req_t req, fuse_ino_t ino, struct
}
XRDP_INODE *xinode = g_xrdp_fs.inode_table[ino];
+ if (!xinode)
+ {
+ log_debug("****** g_xrdp_fs.inode_table[%d] is NULL", ino);
+ fuse_reply_err(req, 0);
+ return;
+ }
if (xinode->is_loc_resource)
{
/* specified file is a local resource */
@@ -2748,7 +2763,12 @@ static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
return;
}
- xinode = g_xrdp_fs.inode_table[ino];
+ if ((xinode = g_xrdp_fs.inode_table[ino]) == NULL)
+ {
+ log_debug("g_xrdp_fs.inode_table[%d] is NULL", ino);
+ fuse_reply_err(req, EBADF);
+ return;
+ }
if (to_set & FUSE_SET_ATTR_MODE)
{
@@ -2813,9 +2833,40 @@ static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
fuse_reply_attr(req, &st, 1.0); /* LK_TODO just faking for now */
}
+/**
+ * Get dir listing
+ *****************************************************************************/
static void xfuse_cb_opendir(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi)
{
+ struct opendir_req *odreq;
+
+ /* save request */
+ odreq = malloc(sizeof(struct opendir_req));
+ odreq->req = req;
+ odreq->ino = ino;
+ odreq->fi = fi;
+
+ if (fifo_is_empty(&g_fifo_opendir))
+ {
+ fifo_insert(&g_fifo_opendir, odreq);
+ xfuse_proc_opendir_req(req, ino, fi);
+ }
+ else
+ {
+ /* place req in FIFO; xfuse_devredir_cb_enum_dir_done() will handle it */
+ fifo_insert(&g_fifo_opendir, odreq);
+ }
+}
+
+/**
+ * Process the next opendir req
+ *
+ * @return 0 of the request was sent for remote lookup, -1 otherwise
+ *****************************************************************************/
+static int xfuse_proc_opendir_req(fuse_req_t req, fuse_ino_t ino,
+ struct fuse_file_info *fi)
+{
struct dir_info *di;
XRDP_INODE *xinode;
XFUSE_INFO *fip;
@@ -2823,19 +2874,26 @@ static void xfuse_cb_opendir(fuse_req_t req, fuse_ino_t ino,
char full_path[4096];
char *cptr;
- log_debug("inode=%d name=%s", ino, g_xrdp_fs.inode_table[ino]->name);
+ log_debug("inode=%d", ino);
if (!xfuse_is_inode_valid(ino))
{
log_error("inode %d is not valid", ino);
fuse_reply_err(req, EBADF);
- return;
+ g_free(fifo_remove(&g_fifo_opendir));
+ return -1;
}
if (ino == 1)
goto done; /* special case; enumerate top level dir */
- xinode = g_xrdp_fs.inode_table[ino];
+ if ((xinode = g_xrdp_fs.inode_table[ino]) == NULL)
+ {
+ log_debug("g_xrdp_fs.inode_table[%d] is NULL", ino);
+ fuse_reply_err(req, EBADF);
+ g_free(fifo_remove(&g_fifo_opendir));
+ return -1;
+ }
if (xinode->is_loc_resource)
goto done;
@@ -2846,7 +2904,8 @@ static void xfuse_cb_opendir(fuse_req_t req, fuse_ino_t ino,
if (xinode->is_synced)
{
xfuse_enum_dir(req, ino, size, off, fi);
- return;
+ g_free(fifo_remove(&g_fifo_opendir));
+ return -1;
}
else
{
@@ -2867,7 +2926,8 @@ do_remote_lookup:
{
log_error("system out of memory");
fuse_reply_err(req, ENOMEM);
- return;
+ g_free(fifo_remove(&g_fifo_opendir));
+ return -1;
}
fip->req = req;
@@ -2900,7 +2960,7 @@ do_remote_lookup:
}
}
- return;
+ return 0;
done:
@@ -2908,6 +2968,8 @@ done:
di->index = FIRST_INODE;
fi->fh = (long) di;
fuse_reply_open(req, fi);
+ g_free(fifo_remove(&g_fifo_opendir));
+ return -1;
}
/**
diff --git a/sesman/chansrv/clipboard.c b/sesman/chansrv/clipboard.c
index c2062605..25775f3b 100644
--- a/sesman/chansrv/clipboard.c
+++ b/sesman/chansrv/clipboard.c
@@ -277,6 +277,39 @@ static int g_num_formatIds = 0;
static int g_file_format_id = -1;
+static char g_last_atom_name[256] = "";
+
+/*****************************************************************************/
+static char* APP_CC
+get_atom_text(Atom atom)
+{
+ char* name;
+ int failed;
+
+ failed = 0;
+ /* sanity check */
+ if ((atom < 1) || (atom > 512))
+ {
+ failed = 1;
+ }
+ if (!failed)
+ {
+ name = XGetAtomName(g_display, atom);
+ if (name == 0)
+ {
+ failed = 1;
+ }
+ }
+ if (failed)
+ {
+ g_snprintf(g_last_atom_name, 255, "unknown atom 0x%8.8x", (int)atom);
+ return g_last_atom_name;
+ }
+ g_strncpy(g_last_atom_name, name, 255);
+ XFree(name);
+ return g_last_atom_name;
+}
+
/*****************************************************************************/
/* this is one way to get the current time from the x server */
static Time APP_CC
@@ -895,8 +928,8 @@ clipboard_provide_selection_c2s(XSelectionRequestEvent *req, Atom type)
g_clip_c2s.property = req->property;
g_clip_c2s.window = req->requestor;
log_debug("clipboard_provide_selection_c2s: start INCR property %s "
- "type %s", XGetAtomName(g_display, req->property),
- XGetAtomName(g_display, type));
+ "type %s", get_atom_text(req->property),
+ get_atom_text(type));
val1[0] = g_clip_c2s.total_bytes;
val1[1] = 0;
XChangeProperty(g_display, req->requestor, req->property,
@@ -1697,7 +1730,7 @@ clipboard_get_window_property(Window wnd, Atom prop, Atom *type, int *fmt,
Atom ltype;
log_debug("clipboard_get_window_property:");
- log_debug(" prop %d name %s", prop, XGetAtomName(g_display, prop));
+ log_debug(" prop %d name %s", prop, get_atom_text(prop));
lxdata = 0;
ltype = 0;
XGetWindowProperty(g_display, wnd, prop, 0, 0, 0,
@@ -1837,7 +1870,7 @@ clipboard_event_selection_notify(XEvent *xevent)
{
log_debug("clipboard_event_selection_notify: wnd %p prop %s",
lxevent->requestor,
- XGetAtomName(g_display, lxevent->property));
+ get_atom_text(lxevent->property));
rv = clipboard_get_window_property(lxevent->requestor, lxevent->property,
&type, &fmt,
&n_items, &data, &data_size);
@@ -1855,8 +1888,8 @@ clipboard_event_selection_notify(XEvent *xevent)
PropertyNotify */
log_debug("clipboard_event_selection_notify: type is INCR "
"data_size %d property name %s type %s", data_size,
- XGetAtomName(g_display, lxevent->property),
- XGetAtomName(g_display, lxevent->type));
+ get_atom_text(lxevent->property),
+ get_atom_text(lxevent->type));
g_clip_s2c.incr_in_progress = 1;
g_clip_s2c.property = lxevent->property;
g_clip_s2c.type = lxevent->target;
@@ -1882,10 +1915,10 @@ clipboard_event_selection_notify(XEvent *xevent)
for (index = 0; index < n_items; index++)
{
atom = atoms[index];
- log_debug("clipboard_event_selection_notify: %d %s %d",
- atom, XGetAtomName(g_display, atom), XA_STRING);
+ LOGM((LOG_LEVEL_DEBUG, "clipboard_event_selection_notify: %d %s %d",
+ atom, get_atom_text(atom), XA_STRING));
log_debug("clipboard_event_selection_notify: 0x%x %s",
- atom, XGetAtomName(g_display, atom));
+ atom, get_atom_text(atom));
if (atom == g_utf8_atom)
{
got_utf8 = 1;
@@ -2091,7 +2124,6 @@ static int APP_CC
clipboard_event_selection_request(XEvent *xevent)
{
XSelectionRequestEvent *lxev;
- XEvent xev;
Atom atom_buf[10];
Atom type;
int atom_count;
@@ -2105,7 +2137,7 @@ clipboard_event_selection_request(XEvent *xevent)
log_debug("clipboard_event_selection_request: g_wnd %d, "
".requestor %d .owner %d .selection %d '%s' .target %d .property %d",
g_wnd, lxev->requestor, lxev->owner, lxev->selection,
- XGetAtomName(g_display, lxev->selection),
+ get_atom_text(lxev->selection),
lxev->target, lxev->property);
if (lxev->property == None)
@@ -2164,8 +2196,7 @@ clipboard_event_selection_request(XEvent *xevent)
"g_multiple_atom");
xdata = 0;
- if (clipboard_get_window_property(xev.xselection.requestor,
- xev.xselection.property,
+ if (clipboard_get_window_property(lxev->requestor, lxev->property,
&type, &fmt, &n_items, &xdata,
&xdata_size) == 0)
{
@@ -2235,9 +2266,9 @@ clipboard_event_selection_request(XEvent *xevent)
else
{
log_debug("clipboard_event_selection_request: unknown "
- "target %s", XGetAtomName(g_display, lxev->target));
- log_error("clipboard_event_selection_request: unknown "
- "target %s", XGetAtomName(g_display, lxev->target));
+ "target %s", get_atom_text(lxev->target));
+ LOGM((LOG_LEVEL_ERROR, "clipboard_event_selection_request: unknown "
+ "target %s", get_atom_text(lxev->target)));
}
clipboard_refuse_selection(lxev);
@@ -2293,7 +2324,7 @@ clipboard_event_property_notify(XEvent *xevent)
log_debug("clipboard_event_property_notify: PropertyNotify .window %d "
".state %d .atom %d %s", xevent->xproperty.window,
xevent->xproperty.state, xevent->xproperty.atom,
- XGetAtomName(g_display, xevent->xproperty.atom));
+ get_atom_text(xevent->xproperty.atom));
if (g_clip_c2s.incr_in_progress &&
(xevent->xproperty.window == g_clip_c2s.window) &&
diff --git a/sesman/chansrv/devredir.c b/sesman/chansrv/devredir.c
index 418c29e7..cdcc9e94 100644
--- a/sesman/chansrv/devredir.c
+++ b/sesman/chansrv/devredir.c
@@ -68,7 +68,7 @@
#define log_info(_params...) \
{ \
- if (LOG_INFO <= LOG_LEVEL) \
+ if (LOG_INFO <= LOG_LEVEL) \
{ \
g_write("[%10.10u]: DEV_REDIR %s: %d : ", \
g_time3(), __func__, __LINE__); \
@@ -78,7 +78,7 @@
#define log_debug(_params...) \
{ \
- if (LOG_DEBUG <= LOG_LEVEL) \
+ if (LOG_DEBUG <= LOG_LEVEL) \
{ \
g_write("[%10.10u]: DEV_REDIR %s: %d : ", \
g_time3(), __func__, __LINE__); \
@@ -587,53 +587,50 @@ void dev_redir_proc_client_core_cap_resp(struct stream *s)
tui16 cap_type;
tui16 cap_len;
tui32 cap_version;
+ char* holdp;
xstream_rd_u16_le(s, num_caps);
xstream_seek(s, 2); /* padding */
for (i = 0; i < num_caps; i++)
{
+ holdp = s->p;
xstream_rd_u16_le(s, cap_type);
xstream_rd_u16_le(s, cap_len);
xstream_rd_u32_le(s, cap_version);
- /* remove header length and version */
- cap_len -= 8;
-
switch (cap_type)
{
case CAP_GENERAL_TYPE:
log_debug("got CAP_GENERAL_TYPE");
- xstream_seek(s, cap_len);
break;
case CAP_PRINTER_TYPE:
log_debug("got CAP_PRINTER_TYPE");
g_is_printer_redir_supported = 1;
- xstream_seek(s, cap_len);
break;
case CAP_PORT_TYPE:
log_debug("got CAP_PORT_TYPE");
g_is_port_redir_supported = 1;
- xstream_seek(s, cap_len);
break;
case CAP_DRIVE_TYPE:
log_debug("got CAP_DRIVE_TYPE");
g_is_drive_redir_supported = 1;
if (cap_version == 2)
+ {
g_drive_redir_version = 2;
- xstream_seek(s, cap_len);
+ }
break;
case CAP_SMARTCARD_TYPE:
log_debug("got CAP_SMARTCARD_TYPE");
g_is_smartcard_redir_supported = 1;
scard_init();
- xstream_seek(s, cap_len);
break;
}
+ s->p = holdp + cap_len;
}
}
@@ -1101,7 +1098,11 @@ dev_redir_file_open(void *fusep, tui32 device_id, char *path,
#if 1
/* without the 0x00000010 rdesktop opens files in */
/* O_RDONLY instead of O_RDWR mode */
- DesiredAccess = DA_FILE_READ_DATA | DA_FILE_WRITE_DATA | DA_SYNCHRONIZE | 0x00000010;
+ if (mode & O_RDWR)
+ DesiredAccess = DA_FILE_READ_DATA | DA_FILE_WRITE_DATA | DA_SYNCHRONIZE | 0x00000010;
+ else
+ DesiredAccess = DA_FILE_READ_DATA | DA_SYNCHRONIZE;
+
CreateOptions = CO_FILE_SYNCHRONOUS_IO_NONALERT;
CreateDisposition = CD_FILE_OPEN; // WAS 1
#else
diff --git a/sesman/chansrv/fifo.c b/sesman/chansrv/fifo.c
new file mode 100644
index 00000000..630df3cd
--- /dev/null
+++ b/sesman/chansrv/fifo.c
@@ -0,0 +1,255 @@
+/**
+ * xrdp: A Remote Desktop Protocol server.
+ *
+ * Copyright (C) Laxmikant Rashinkar 2013 LK.Rashinkar@gmail.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ /* FIFO implementation to store a pointer to a user struct */
+
+/* module based logging */
+#define MODULE_NAME "FIFO "
+#define LOCAL_DEBUG
+
+#include "fifo.h"
+#include "mlog.h"
+
+/**
+ * Initialize a FIFO that grows as required
+ *
+ * @param fp pointer to a FIFO
+ * @param num_entries initial size
+ *
+ * @return 0 on success, -1 on failure
+ *****************************************************************************/
+int
+fifo_init(FIFO* fp, int num_entries)
+{
+ log_debug_high("entered");
+
+ /* validate params */
+ if (!fp)
+ {
+ log_debug_high("invalid parameters");
+ return -1;
+ }
+
+ if (num_entries < 1)
+ num_entries = 10;
+
+ fp->rd_ptr = 0;
+ fp->wr_ptr = 0;
+ fp->user_data = (long *) g_malloc(sizeof(long) * num_entries);
+
+ if (fp->user_data)
+ {
+ fp->entries = num_entries;
+ log_debug_low("FIFO created; rd_ptr=%d wr_ptr=%d entries=%d",
+ fp->rd_ptr, fp->wr_ptr, fp->entries);
+ return 0;
+ }
+ else
+ {
+ log_error("FIFO create error; system out of memory");
+ fp->entries = 0;
+ return -1;
+ }
+}
+
+/**
+ * Deinit FIFO and release resources
+ *
+ * @param fp FIFO to deinit
+ *
+ * @return 0 on success, -1 on error
+ *****************************************************************************/
+int
+fifo_deinit(FIFO* fp)
+{
+ log_debug_high("entered");
+
+ if (!fp)
+ {
+ log_debug_high("FIFO is null");
+ return -1;
+ }
+
+ if (fp->user_data)
+ {
+ g_free(fp->user_data);
+ fp->user_data = 0;
+ }
+
+ fp->rd_ptr = 0;
+ fp->wr_ptr = 0;
+ fp->entries = 0;
+}
+
+/**
+ * Check if FIFO is empty
+ *
+ * @param fp FIFO
+ *
+ * @return 1 if FIFO is empty, 0 otherwise
+ *****************************************************************************/
+int
+fifo_is_empty(FIFO* fp)
+{
+ log_debug_high("entered");
+
+ if (!fp)
+ {
+ log_debug_high("FIFO is null");
+ return 0;
+ }
+
+ return (fp->rd_ptr == fp->wr_ptr) ? 1 : 0;
+}
+
+/**
+ * Insert an item at the end
+ *
+ * @param fp FIFO
+ * @param data data to insert into FIFO
+ *
+ * @param 0 on success, -1 on error
+ *****************************************************************************/
+
+int
+fifo_insert(FIFO* fp, void* data)
+{
+ long* lp;
+ int next_val; /* next value for wr_ptr */
+ int i;
+
+ log_debug_high("entered");
+
+ if (!fp)
+ {
+ log_debug_high("FIFO is null");
+ return -1;
+ }
+
+ next_val = fp->wr_ptr + 1;
+ if (next_val >= fp->entries)
+ next_val = 0;
+
+ if (next_val == fp->rd_ptr)
+ {
+ /* FIFO is full, expand it by 10 entries */
+ lp = (long *) g_malloc(sizeof(long) * (fp->entries + 10));
+ if (!lp)
+ {
+ log_debug_low("FIFO full; cannot expand, no memory");
+ return -1;
+ }
+
+ log_debug_low("FIFO full, expanding by 10 entries");
+
+ /* copy old data new location */
+ for (i = 0; i < (fp->entries - 1); i++)
+ {
+ lp[i] = fp->user_data[fp->rd_ptr++];
+ if (fp->rd_ptr >= fp->entries)
+ fp->rd_ptr = 0;
+ }
+
+ /* update pointers */
+ fp->rd_ptr = 0;
+ fp->wr_ptr = fp->entries - 1;
+ next_val = fp->entries;
+ fp->entries += 10;
+
+ /* free old data */
+ g_free(fp->user_data);
+ fp->user_data = lp;
+ }
+
+ log_debug_low("inserting data at index %d", fp->wr_ptr);
+
+ fp->user_data[fp->wr_ptr] = (long) data;
+ fp->wr_ptr = next_val;
+
+ return 0;
+}
+
+/**
+ * Remove an item from the head
+ *
+ * @param fp FIFO
+ *
+ * @param data on success, NULL on error
+ *****************************************************************************/
+void*
+fifo_remove(FIFO* fp)
+{
+ long data;
+
+ log_debug_high("entered");
+
+ if (!fp)
+ {
+ log_debug_high("FIFO is null");
+ return 0;
+ }
+
+ if (fp->rd_ptr == fp->wr_ptr)
+ {
+ log_debug_high("FIFO is empty");
+ return 0;
+ }
+
+ log_debug_low("removing data at index %d", fp->rd_ptr);
+
+ data = fp->user_data[fp->rd_ptr++];
+
+ if (fp->rd_ptr >= fp->entries)
+ {
+ log_debug_high("FIFO rd_ptr wrapped around");
+ fp->rd_ptr = 0;
+ }
+
+ return (void *) data;
+}
+
+/**
+ * Return item from head, but do not remove it
+ *
+ * @param fp FIFO
+ *
+ * @param data on success, NULL on error
+ *****************************************************************************/
+void*
+fifo_peek(FIFO* fp)
+{
+ long data;
+
+ log_debug_high("entered\n");
+
+ if (!fp)
+ {
+ log_debug_high("FIFO is null\n");
+ return 0;
+ }
+
+ if (fp->rd_ptr == fp->wr_ptr)
+ {
+ log_debug_high("FIFO is empty\n");
+ return 0;
+ }
+
+ log_debug_low("peeking data at index %d\n", fp->rd_ptr);
+
+ return (void *) fp->user_data[fp->rd_ptr];
+}
diff --git a/freerdp/xrdp-color.h b/sesman/chansrv/fifo.h
index 3c58c032..0a23592c 100644
--- a/freerdp/xrdp-color.h
+++ b/sesman/chansrv/fifo.h
@@ -1,7 +1,7 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
- * Copyright (C) Jay Sorg 2004-2012
+ * Copyright (C) Laxmikant Rashinkar 2013 LK.Rashinkar@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,13 +16,20 @@
* limitations under the License.
*/
-#ifndef __XRDP_COLOR_H
-#define __XRDP_COLOR_H
+ /* FIFO implementation to store a pointer to a user struct */
-char* APP_CC
-convert_bitmap(int in_bpp, int out_bpp, char* bmpdata,
- int width, int height, int* palette);
-int APP_CC
-convert_color(int in_bpp, int out_bpp, int in_color, int* palette);
+typedef struct fifo
+{
+ long* user_data;
+ int rd_ptr;
+ int wr_ptr;
+ int entries;
+} FIFO;
+
+int fifo_init(FIFO* fp, int num_entries);
+int fifo_deinit(FIFO* fp);
+int fifo_is_empty(FIFO* fp);
+int fifo_insert(FIFO* fp, void* data);
+void* fifo_remove(FIFO* fp);
+void* fifo_peek(FIFO* fp);
-#endif
diff --git a/sesman/chansrv/irp.h b/sesman/chansrv/irp.h
index e1a65d83..a13ea8e5 100644
--- a/sesman/chansrv/irp.h
+++ b/sesman/chansrv/irp.h
@@ -52,6 +52,7 @@ struct irp
void (*callback)(struct stream *s, IRP *irp, tui32 DeviceId,
tui32 CompletionId, tui32 IoStatus);
+ void *user_data;
};
IRP * APP_CC devredir_irp_new(void);
diff --git a/sesman/chansrv/mlog.h b/sesman/chansrv/mlog.h
new file mode 100644
index 00000000..866c9692
--- /dev/null
+++ b/sesman/chansrv/mlog.h
@@ -0,0 +1,112 @@
+/**
+ * xrdp: A Remote Desktop Protocol server.
+ *
+ * Copyright (C) Laxmikant Rashinkar 2013 LK.Rashinkar@gmail.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ /* module based logging */
+
+#ifndef _MLOG_H
+#define _MLOG_H
+
+/*
+ * Note1: to enable debug messages, in your .c file, #define LOCAL_DEBUG
+ * BEFORE including this file
+ *
+ * Note2: in your .c file, #define MODULE_NAME, 8 chars long, to print each
+ * log entry with your module name
+ */
+
+#define LOG_ERROR 0
+#define LOG_INFO 1
+#define LOG_DEBUG_LOW 2
+#define LOG_DEBUG_HIGH 3
+#define LOG_LEVEL LOG_ERROR
+
+/*
+ * print always
+ */
+
+#define log_error(_params...) \
+do \
+{ \
+ g_write("[%10.10u]: %s %s: %d: ERROR: ", g_time3(), \
+ MODULE_NAME, __func__, __LINE__); \
+ g_writeln (_params); \
+} \
+while(0)
+
+#define log_always(_params...) \
+do \
+{ \
+ g_write("[%10.10u]: %s %s: %d: ALWAYS: ", g_time3(), \
+ MODULE_NAME, __func__, __LINE__); \
+ g_writeln (_params); \
+} \
+while(0)
+
+/*
+ * print conditionally
+ */
+
+#ifdef LOCAL_DEBUG
+#define log_info(_params...) \
+do \
+{ \
+ if (LOG_INFO <= LOG_LEVEL) \
+ { \
+ g_write("[%10.10u]: %s %s: %d: INFO: ", g_time3(), \
+ MODULE_NAME, __func__, __LINE__); \
+ g_writeln (_params); \
+ } \
+} \
+while(0)
+#else
+#define log_info(_params...)
+#endif
+
+#ifdef LOCAL_DEBUG
+#define log_debug_low(_params...) \
+do \
+{ \
+ if (LOG_DEBUG_LOW <= LOG_LEVEL) \
+ { \
+ g_write("[%10.10u]: %s %s: %d: DEBUG: ", g_time3(), \
+ MODULE_NAME, __func__, __LINE__); \
+ g_writeln (_params); \
+ } \
+} \
+while(0)
+#else
+#define log_debug_low(_params...)
+#endif
+
+#ifdef LOCAL_DEBUG
+#define log_debug_high(_params...) \
+do \
+{ \
+ if (LOG_DEBUG_HIGH <= LOG_LEVEL) \
+ { \
+ g_write("[%10.10u]: %s %s: %d: DEBUG: ", g_time3(), \
+ MODULE_NAME, __func__, __LINE__); \
+ g_writeln (_params); \
+ } \
+} \
+while(0)
+#else
+#define log_debug_high(_params...)
+#endif
+
+#endif /* #ifndef _MLOG_H */
diff --git a/sesman/chansrv/pcsc/Makefile b/sesman/chansrv/pcsc/Makefile
new file mode 100644
index 00000000..483151f2
--- /dev/null
+++ b/sesman/chansrv/pcsc/Makefile
@@ -0,0 +1,12 @@
+
+OBJS = xrdp_pcsc.o
+
+CFLAGS = -Wall -O2 -fPIC
+
+all: libpcsclite.so
+
+libpcsclite.so: $(OBJS)
+ $(CC) $(LDFLAGS) -shared -o libpcsclite.so $(OBJS)
+
+clean:
+ rm -f $(OBJS) libpcsclite.so
diff --git a/sesman/chansrv/pcsc/xrdp_pcsc.c b/sesman/chansrv/pcsc/xrdp_pcsc.c
new file mode 100644
index 00000000..502d3096
--- /dev/null
+++ b/sesman/chansrv/pcsc/xrdp_pcsc.c
@@ -0,0 +1,1157 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+
+#define PCSC_API
+
+typedef unsigned char BYTE;
+typedef BYTE *LPBYTE;
+typedef unsigned int LONG;
+typedef unsigned int DWORD;
+typedef DWORD *LPDWORD;
+typedef const void *LPCVOID;
+typedef const char *LPCSTR;
+typedef char *LPSTR;
+typedef void *LPVOID;
+typedef const BYTE *LPCBYTE;
+
+typedef LONG SCARDCONTEXT;
+typedef SCARDCONTEXT *LPSCARDCONTEXT;
+
+typedef LONG SCARDHANDLE;
+typedef SCARDHANDLE *LPSCARDHANDLE;
+
+#define MAX_ATR_SIZE 33
+
+typedef struct _SCARD_READERSTATE
+{
+ const char *szReader;
+ void *pvUserData;
+ DWORD dwCurrentState;
+ DWORD dwEventState;
+ DWORD cbAtr;
+ unsigned char rgbAtr[MAX_ATR_SIZE];
+} SCARD_READERSTATE, *LPSCARD_READERSTATE;
+
+typedef struct _SCARD_IO_REQUEST
+{
+ unsigned long dwProtocol;
+ unsigned long cbPciLength;
+} SCARD_IO_REQUEST, *PSCARD_IO_REQUEST, *LPSCARD_IO_REQUEST;
+
+#define SCARD_PROTOCOL_T0 0x0001 /**< T=0 active protocol. */
+#define SCARD_PROTOCOL_T1 0x0002 /**< T=1 active protocol. */
+#define SCARD_PROTOCOL_RAW 0x0004 /**< Raw active protocol. */
+
+PCSC_API SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_T0, 8 };
+PCSC_API SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, 8 };
+PCSC_API SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_RAW, 8 };
+
+#define LLOG_LEVEL 5
+#define LLOGLN(_level, _args) \
+ do { if (_level < LLOG_LEVEL) { printf _args ; printf("\n"); } } while (0)
+
+#define SCARD_ESTABLISH_CONTEXT 0x01
+#define SCARD_RELEASE_CONTEXT 0x02
+#define SCARD_LIST_READERS 0x03
+#define SCARD_CONNECT 0x04
+#define SCARD_RECONNECT 0x05
+#define SCARD_DISCONNECT 0x06
+#define SCARD_BEGIN_TRANSACTION 0x07
+#define SCARD_END_TRANSACTION 0x08
+#define SCARD_TRANSMIT 0x09
+#define SCARD_CONTROL 0x0A
+#define SCARD_STATUS 0x0B
+#define SCARD_GET_STATUS_CHANGE 0x0C
+#define SCARD_CANCEL 0x0D
+#define SCARD_CANCEL_TRANSACTION 0x0E
+#define SCARD_GET_ATTRIB 0x0F
+#define SCARD_SET_ATTRIB 0x10
+
+#define SCARD_S_SUCCESS 0x00000000
+#define SCARD_F_INTERNAL_ERROR ((LONG)0x80100001)
+
+#define SET_UINT32(_data, _offset, _val) do { \
+ (((BYTE*)(_data)) + (_offset))[0] = ((_val) >> 0) & 0xff; \
+ (((BYTE*)(_data)) + (_offset))[1] = ((_val) >> 8) & 0xff; \
+ (((BYTE*)(_data)) + (_offset))[2] = ((_val) >> 16) & 0xff; \
+ (((BYTE*)(_data)) + (_offset))[3] = ((_val) >> 24) & 0xff; } while (0)
+
+#define GET_UINT32(_data, _offset) \
+ ((((BYTE*)(_data)) + (_offset))[0] << 0) | \
+ ((((BYTE*)(_data)) + (_offset))[1] << 8) | \
+ ((((BYTE*)(_data)) + (_offset))[2] << 16) | \
+ ((((BYTE*)(_data)) + (_offset))[3] << 24)
+
+#define LMIN(_val1, _val2) (_val1) < (_val2) ? (_val1) : (_val2)
+#define LMAX(_val1, _val2) (_val1) > (_val2) ? (_val1) : (_val2)
+
+static int g_sck = -1; /* unix domain socket */
+
+static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/* for pcsc_stringify_error */
+static char g_error_str[512];
+
+/*****************************************************************************/
+static int
+get_display_num_from_display(const char *display_text)
+{
+ int rv;
+ int index;
+ int mode;
+ int host_index;
+ int disp_index;
+ int scre_index;
+ char host[256];
+ char disp[256];
+ char scre[256];
+
+ memset(host, 0, 256);
+ memset(disp, 0, 256);
+ memset(scre, 0, 256);
+
+ index = 0;
+ host_index = 0;
+ disp_index = 0;
+ scre_index = 0;
+ mode = 0;
+
+ while (display_text[index] != 0)
+ {
+ if (display_text[index] == ':')
+ {
+ mode = 1;
+ }
+ else if (display_text[index] == '.')
+ {
+ mode = 2;
+ }
+ else if (mode == 0)
+ {
+ host[host_index] = display_text[index];
+ host_index++;
+ }
+ else if (mode == 1)
+ {
+ disp[disp_index] = display_text[index];
+ disp_index++;
+ }
+ else if (mode == 2)
+ {
+ scre[scre_index] = display_text[index];
+ scre_index++;
+ }
+ index++;
+ }
+ host[host_index] = 0;
+ disp[disp_index] = 0;
+ scre[scre_index] = 0;
+ LLOGLN(0, ("get_display_num_from_display: host [%s] disp [%s] scre [%s]",
+ host, disp, scre));
+ rv = atoi(disp);
+ return rv;
+}
+
+/*****************************************************************************/
+static int
+connect_to_chansrv(void)
+{
+ int bytes;
+ int dis;
+ int error;
+ char *xrdp_session;
+ char *xrdp_display;
+ char *home_str;
+ struct sockaddr_un saddr;
+ struct sockaddr *psaddr;
+
+ if (g_sck != -1)
+ {
+ /* already connected */
+ return 0;
+ }
+ xrdp_session = getenv("XRDP_SESSION");
+ if (xrdp_session == NULL)
+ {
+ /* XRDP_SESSION must be set */
+ LLOGLN(0, ("connect_to_chansrv: error, not xrdp session"));
+ return 1;
+ }
+ xrdp_display = getenv("DISPLAY");
+ if (xrdp_display == NULL)
+ {
+ /* DISPLAY must be set */
+ LLOGLN(0, ("connect_to_chansrv: error, display not set"));
+ return 1;
+ }
+ home_str = getenv("HOME");
+ if (home_str == NULL)
+ {
+ /* HOME must be set */
+ LLOGLN(0, ("connect_to_chansrv: error, home not set"));
+ return 1;
+ }
+ dis = get_display_num_from_display(xrdp_display);
+ if (dis < 10)
+ {
+ /* DISPLAY must be > 9 */
+ LLOGLN(0, ("connect_to_chansrv: error, display not > 9 %d", dis));
+ return 1;
+ }
+ g_sck = socket(PF_LOCAL, SOCK_STREAM, 0);
+ if (g_sck == -1)
+ {
+ LLOGLN(0, ("connect_to_chansrv: error, socket failed"));
+ return 1;
+ }
+ memset(&saddr, 0, sizeof(struct sockaddr_un));
+ saddr.sun_family = AF_UNIX;
+ bytes = sizeof(saddr.sun_path);
+ snprintf(saddr.sun_path, bytes, "%s/.pcsc%d/pcscd.comm", home_str, dis);
+ saddr.sun_path[bytes - 1] = 0;
+ LLOGLN(0, ("connect_to_chansrv: connecting to %s", saddr.sun_path));
+ psaddr = (struct sockaddr *) &saddr;
+ bytes = sizeof(struct sockaddr_un);
+ error = connect(g_sck, psaddr, bytes);
+ if (error == 0)
+ {
+ }
+ else
+ {
+ perror("connect_to_chansrv");
+ close(g_sck);
+ g_sck = -1;
+ LLOGLN(0, ("connect_to_chansrv: error, open %s", saddr.sun_path));
+ return 1;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+static int
+send_message(int code, char *data, int bytes)
+{
+ char header[8];
+
+ SET_UINT32(header, 0, bytes);
+ SET_UINT32(header, 4, code);
+ if (send(g_sck, header, 8, 0) != 8)
+ {
+ return 1;
+ }
+ if (send(g_sck, data, bytes, 0) != bytes)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+static int
+get_message(int *code, char *data, int *bytes)
+{
+ char header[8];
+ int max_bytes;
+
+ if (recv(g_sck, header, 8, 0) != 8)
+ {
+ return 1;
+ }
+ max_bytes = *bytes;
+ *bytes = GET_UINT32(header, 0);
+ *code = GET_UINT32(header, 4);
+ if (*bytes > max_bytes)
+ {
+ return 1;
+ }
+ if (recv(g_sck, data, *bytes, 0) != *bytes)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+PCSC_API LONG
+SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2,
+ LPSCARDCONTEXT phContext)
+{
+ char msg[256];
+ DWORD context;
+ int code;
+ int bytes;
+ int status;
+
+ LLOGLN(10, ("SCardEstablishContext:"));
+ if (g_sck == -1)
+ {
+ if (connect_to_chansrv() != 0)
+ {
+ LLOGLN(0, ("SCardEstablishContext: error, can not connect "
+ "to chansrv"));
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ }
+ pthread_mutex_lock(&g_mutex);
+ SET_UINT32(msg, 0, dwScope);
+ if (send_message(SCARD_ESTABLISH_CONTEXT, msg, 4) != 0)
+ {
+ LLOGLN(0, ("SCardEstablishContext: error, send_message"));
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ bytes = 256;
+ if (get_message(&code, msg, &bytes) != 0)
+ {
+ LLOGLN(0, ("SCardEstablishContext: error, get_message"));
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ if ((code != SCARD_ESTABLISH_CONTEXT) || (bytes != 8))
+ {
+ LLOGLN(0, ("SCardEstablishContext: error, bad code"));
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ pthread_mutex_unlock(&g_mutex);
+ context = GET_UINT32(msg, 0);
+ status = GET_UINT32(msg, 4);
+ LLOGLN(10, ("SCardEstablishContext: got context 0x%8.8x", context));
+ *phContext = context;
+ return status;
+}
+
+/*****************************************************************************/
+PCSC_API LONG
+SCardReleaseContext(SCARDCONTEXT hContext)
+{
+ char msg[256];
+ int code;
+ int bytes;
+ int status;
+
+ LLOGLN(10, ("SCardReleaseContext:"));
+ if (g_sck == -1)
+ {
+ LLOGLN(0, ("SCardReleaseContext: error, not connected"));
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ pthread_mutex_lock(&g_mutex);
+ SET_UINT32(msg, 0, hContext);
+ if (send_message(SCARD_RELEASE_CONTEXT, msg, 4) != 0)
+ {
+ LLOGLN(0, ("SCardReleaseContext: error, send_message"));
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ bytes = 256;
+ if (get_message(&code, msg, &bytes) != 0)
+ {
+ LLOGLN(0, ("SCardReleaseContext: error, get_message"));
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ if ((code != SCARD_RELEASE_CONTEXT) || (bytes != 4))
+ {
+ LLOGLN(0, ("SCardReleaseContext: error, bad code"));
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ pthread_mutex_unlock(&g_mutex);
+ status = GET_UINT32(msg, 0);
+ LLOGLN(10, ("SCardReleaseContext: got status 0x%8.8x", status));
+ return status;
+}
+
+/*****************************************************************************/
+PCSC_API LONG
+SCardIsValidContext(SCARDCONTEXT hContext)
+{
+ LLOGLN(10, ("SCardIsValidContext:"));
+ if (g_sck == -1)
+ {
+ LLOGLN(0, ("SCardIsValidContext: error, not connected"));
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ pthread_mutex_lock(&g_mutex);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_S_SUCCESS;
+}
+
+/*****************************************************************************/
+PCSC_API LONG
+SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode,
+ DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
+ LPDWORD pdwActiveProtocol)
+{
+ char msg[256];
+ int code;
+ int bytes;
+ int status;
+ int offset;
+
+ LLOGLN(10, ("SCardConnect:"));
+ LLOGLN(10, ("SCardConnect: hContext %p szReader %s dwShareMode %d "
+ "dwPreferredProtocols %d",
+ (void*)hContext, szReader, dwShareMode, dwPreferredProtocols));
+ if (g_sck == -1)
+ {
+ LLOGLN(0, ("SCardConnect: error, not connected"));
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ offset = 0;
+ SET_UINT32(msg, offset, hContext);
+ offset += 4;
+ bytes = strlen(szReader);
+ if (bytes > 99)
+ {
+ LLOGLN(0, ("SCardConnect: error, name too long"));
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ memcpy(msg + offset, szReader, bytes);
+ memset(msg + offset + bytes, 0, 100 - bytes);
+ offset += 100;
+ SET_UINT32(msg, offset, dwShareMode);
+ offset += 4;
+ SET_UINT32(msg, offset, dwPreferredProtocols);
+ offset += 4;
+ pthread_mutex_lock(&g_mutex);
+ if (send_message(SCARD_CONNECT, msg, offset) != 0)
+ {
+ LLOGLN(0, ("SCardConnect: error, send_message"));
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ bytes = 256;
+ if (get_message(&code, msg, &bytes) != 0)
+ {
+ LLOGLN(0, ("SCardConnect: error, get_message"));
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ if (code != SCARD_CONNECT)
+ {
+ LLOGLN(0, ("SCardConnect: error, bad code"));
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ pthread_mutex_unlock(&g_mutex);
+ *phCard = GET_UINT32(msg, 0);
+ *pdwActiveProtocol = GET_UINT32(msg, 4);
+ status = GET_UINT32(msg, 8);
+ LLOGLN(10, ("SCardReleaseContext: got status 0x%8.8x", status));
+ return status;
+}
+
+/*****************************************************************************/
+PCSC_API LONG
+SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
+ DWORD dwPreferredProtocols, DWORD dwInitialization,
+ LPDWORD pdwActiveProtocol)
+{
+ LLOGLN(0, ("SCardReconnect:"));
+ if (g_sck == -1)
+ {
+ LLOGLN(0, ("SCardReconnect: error, not connected"));
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ pthread_mutex_lock(&g_mutex);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_S_SUCCESS;
+}
+
+/*****************************************************************************/
+PCSC_API LONG
+SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
+{
+ char msg[256];
+ int code;
+ int bytes;
+ int status;
+
+ LLOGLN(10, ("SCardDisconnect:"));
+ if (g_sck == -1)
+ {
+ LLOGLN(0, ("SCardDisconnect: error, not connected"));
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ pthread_mutex_lock(&g_mutex);
+ SET_UINT32(msg, 0, hCard);
+ SET_UINT32(msg, 4, dwDisposition);
+ if (send_message(SCARD_DISCONNECT, msg, 8) != 0)
+ {
+ LLOGLN(0, ("SCardDisconnect: error, send_message"));
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ bytes = 256;
+ if (get_message(&code, msg, &bytes) != 0)
+ {
+ LLOGLN(0, ("SCardDisconnect: error, get_message"));
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ if ((code != SCARD_DISCONNECT) || (bytes != 4))
+ {
+ LLOGLN(0, ("SCardDisconnect: error, bad code"));
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ pthread_mutex_unlock(&g_mutex);
+ status = GET_UINT32(msg, 0);
+ LLOGLN(10, ("SCardDisconnect: got status 0x%8.8x", status));
+ return status;
+}
+
+/*****************************************************************************/
+PCSC_API LONG
+SCardBeginTransaction(SCARDHANDLE hCard)
+{
+ char msg[256];
+ int code;
+ int bytes;
+ int status;
+
+ LLOGLN(10, ("SCardBeginTransaction:"));
+ if (g_sck == -1)
+ {
+ LLOGLN(0, ("SCardBeginTransaction: error, not connected"));
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ pthread_mutex_lock(&g_mutex);
+ SET_UINT32(msg, 0, hCard);
+ if (send_message(SCARD_BEGIN_TRANSACTION, msg, 4) != 0)
+ {
+ LLOGLN(0, ("SCardBeginTransaction: error, send_message"));
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ bytes = 256;
+ if (get_message(&code, msg, &bytes) != 0)
+ {
+ LLOGLN(0, ("SCardBeginTransaction: error, get_message"));
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ if ((code != SCARD_BEGIN_TRANSACTION) || (bytes != 4))
+ {
+ LLOGLN(0, ("SCardBeginTransaction: error, bad code"));
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ pthread_mutex_unlock(&g_mutex);
+ status = GET_UINT32(msg, 0);
+ LLOGLN(10, ("SCardBeginTransaction: got status 0x%8.8x", status));
+ return status;
+}
+
+/*****************************************************************************/
+PCSC_API LONG
+SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
+{
+ char msg[256];
+ int code;
+ int bytes;
+ int status;
+
+ LLOGLN(10, ("SCardEndTransaction:"));
+ if (g_sck == -1)
+ {
+ LLOGLN(0, ("SCardEndTransaction: error, not connected"));
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ pthread_mutex_lock(&g_mutex);
+ SET_UINT32(msg, 0, hCard);
+ SET_UINT32(msg, 4, dwDisposition);
+ if (send_message(SCARD_END_TRANSACTION, msg, 8) != 0)
+ {
+ LLOGLN(0, ("SCardEndTransaction: error, send_message"));
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ bytes = 256;
+ if (get_message(&code, msg, &bytes) != 0)
+ {
+ LLOGLN(0, ("SCardEndTransaction: error, get_message"));
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ if ((code != SCARD_END_TRANSACTION) || (bytes != 4))
+ {
+ LLOGLN(0, ("SCardEndTransaction: error, bad code"));
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ pthread_mutex_unlock(&g_mutex);
+ status = GET_UINT32(msg, 0);
+ LLOGLN(10, ("SCardEndTransaction: got status 0x%8.8x", status));
+ return status;
+}
+
+/*****************************************************************************/
+PCSC_API LONG
+SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName, LPDWORD pcchReaderLen,
+ LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr,
+ LPDWORD pcbAtrLen)
+{
+ char *msg;
+ int code;
+ int bytes;
+ int status;
+ int offset;
+ int cchReaderLen;
+ int to_copy;
+
+ LLOGLN(10, ("SCardStatus:"));
+ if (g_sck == -1)
+ {
+ LLOGLN(0, ("SCardStatus: error, not connected"));
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ cchReaderLen = *pcchReaderLen;
+ msg = (char *) malloc(8192);
+ SET_UINT32(msg, 0, hCard);
+ SET_UINT32(msg, 4, cchReaderLen);
+ SET_UINT32(msg, 8, *pcbAtrLen);
+ pthread_mutex_lock(&g_mutex);
+ if (send_message(SCARD_STATUS, msg, 12) != 0)
+ {
+ LLOGLN(0, ("SCardStatus: error, send_message"));
+ free(msg);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ bytes = 8192;
+ if (get_message(&code, msg, &bytes) != 0)
+ {
+ LLOGLN(0, ("SCardStatus: error, get_message"));
+ free(msg);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ if (code != SCARD_STATUS)
+ {
+ LLOGLN(0, ("SCardStatus: error, bad code"));
+ free(msg);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ pthread_mutex_unlock(&g_mutex);
+
+ LLOGLN(10, ("SCardStatus: cchReaderLen %d", *pcchReaderLen));
+ offset = 0;
+ *pcchReaderLen = GET_UINT32(msg, offset);
+ LLOGLN(10, ("SCardStatus: cchReaderLen %d", *pcchReaderLen));
+ offset += 4;
+ if (cchReaderLen > 0)
+ {
+ to_copy = cchReaderLen - 1;
+ if (*pcchReaderLen < to_copy)
+ {
+ to_copy = *pcchReaderLen;
+ }
+ memcpy(mszReaderName, msg + offset, to_copy);
+ mszReaderName[to_copy] = 0;
+ }
+ LLOGLN(10, ("SCardStatus: mszReaderName %s", mszReaderName));
+ offset += *pcchReaderLen;
+ *pdwState = GET_UINT32(msg, offset);
+ LLOGLN(10, ("SCardStatus: dwState %d", *pdwState));
+ offset += 4;
+ *pdwProtocol = GET_UINT32(msg, offset);
+ LLOGLN(10, ("SCardStatus: dwProtocol %d", *pdwProtocol));
+ offset += 4;
+ *pcbAtrLen = GET_UINT32(msg, offset);
+ offset += 4;
+ LLOGLN(10, ("SCardStatus: cbAtrLen %d", *pcbAtrLen));
+ memcpy(pbAtr, msg + offset, *pcbAtrLen);
+ offset += *pcbAtrLen;
+ status = GET_UINT32(msg, offset);
+ LLOGLN(10, ("SCardStatus: status %d", status));
+ offset += 4;
+ free(msg);
+ return status;
+}
+
+/*****************************************************************************/
+PCSC_API LONG
+SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout,
+ LPSCARD_READERSTATE rgReaderStates, DWORD cReaders)
+{
+ char *msg;
+ int bytes;
+ int code;
+ int index;
+ int offset;
+ int str_len;
+ int status;
+
+ LLOGLN(10, ("SCardGetStatusChange:"));
+ LLOGLN(10, (" dwTimeout %d cReaders %d", dwTimeout, cReaders));
+ if (g_sck == -1)
+ {
+ LLOGLN(0, ("SCardGetStatusChange: error, not connected"));
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ msg = (char *) malloc(8192);
+ SET_UINT32(msg, 0, hContext);
+ SET_UINT32(msg, 4, dwTimeout);
+ SET_UINT32(msg, 8, cReaders);
+ offset = 12;
+ for (index = 0; index < cReaders; index++)
+ {
+ str_len = strlen(rgReaderStates[index].szReader);
+ str_len = LMIN(str_len, 99);
+ memset(msg + offset, 0, 100);
+ memcpy(msg + offset, rgReaderStates[index].szReader, str_len);
+ offset += 100;
+ LLOGLN(10, (" in dwCurrentState %d", rgReaderStates[index].dwCurrentState));
+ SET_UINT32(msg, offset, rgReaderStates[index].dwCurrentState);
+ offset += 4;
+ LLOGLN(10, (" in dwEventState %d", rgReaderStates[index].dwEventState));
+ SET_UINT32(msg, offset, rgReaderStates[index].dwEventState);
+ offset += 4;
+ LLOGLN(10, (" in cbAtr %d", rgReaderStates[index].cbAtr));
+ SET_UINT32(msg, offset, rgReaderStates[index].cbAtr);
+ offset += 4;
+ memset(msg + offset, 0, 36);
+ memcpy(msg + offset, rgReaderStates[index].rgbAtr, 33);
+ offset += 36;
+ }
+ pthread_mutex_lock(&g_mutex);
+ if (send_message(SCARD_GET_STATUS_CHANGE, msg, offset) != 0)
+ {
+ LLOGLN(0, ("SCardGetStatusChange: error, send_message"));
+ free(msg);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ bytes = 8192;
+ if (get_message(&code, msg, &bytes) != 0)
+ {
+ LLOGLN(0, ("SCardGetStatusChange: error, get_message"));
+ free(msg);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ if (code != SCARD_GET_STATUS_CHANGE)
+ {
+ LLOGLN(0, ("SCardGetStatusChange: error, bad code"));
+ free(msg);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ pthread_mutex_unlock(&g_mutex);
+ cReaders = GET_UINT32(msg, 0);
+ offset = 4;
+ LLOGLN(10, ("SCardGetStatusChange: got back cReaders %d", cReaders));
+ for (index = 0; index < cReaders; index++)
+ {
+ rgReaderStates[index].dwCurrentState = GET_UINT32(msg, offset);
+ offset += 4;
+ LLOGLN(10, (" out dwCurrentState %d", rgReaderStates[index].dwCurrentState));
+ rgReaderStates[index].dwEventState = GET_UINT32(msg, offset);
+ offset += 4;
+ LLOGLN(10, (" out dwEventState %d", rgReaderStates[index].dwEventState));
+ rgReaderStates[index].cbAtr = GET_UINT32(msg, offset);
+ offset += 4;
+ LLOGLN(10, (" out cbAtr %d", rgReaderStates[index].cbAtr));
+ memcpy(rgReaderStates[index].rgbAtr, msg + offset, 33);
+ offset += 36;
+ }
+ status = GET_UINT32(msg, offset);
+ offset += 4;
+ free(msg);
+ return status;
+}
+
+/*****************************************************************************/
+PCSC_API LONG
+SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
+ DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
+ LPDWORD lpBytesReturned)
+{
+ char *msg;
+ int bytes;
+ int code;
+ int offset;
+ int status = 0;
+
+ LLOGLN(10, ("SCardControl:"));
+ if (g_sck == -1)
+ {
+ LLOGLN(0, ("SCardControl: error, not connected"));
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ LLOGLN(10, ("SCardControl: dwControlCode 0x%8.8x", dwControlCode));
+ LLOGLN(10, ("SCardControl: cbSendLength %d", cbSendLength));
+ LLOGLN(10, ("SCardControl: cbRecvLength %d", cbRecvLength));
+
+ /* #define SCARD_CTL_CODE(code) (0x42000000 + (code))
+ control_code = (control_code & 0x3ffc) >> 2;
+ control_code = SCARD_CTL_CODE(control_code); */
+
+ /* PCSC to Windows control code conversion */
+ dwControlCode = dwControlCode - 0x42000000;
+ dwControlCode = dwControlCode << 2;
+ dwControlCode = dwControlCode | (49 << 16);
+ LLOGLN(10, ("SCardControl: dwControlCode 0x%8.8x", dwControlCode));
+
+ msg = (char *) malloc(8192);
+ offset = 0;
+ SET_UINT32(msg, offset, hCard);
+ offset += 4;
+ SET_UINT32(msg, offset, dwControlCode);
+ offset += 4;
+ SET_UINT32(msg, offset, cbSendLength);
+ offset += 4;
+ memcpy(msg + offset, pbSendBuffer, cbSendLength);
+ offset += cbSendLength;
+ SET_UINT32(msg, offset, cbRecvLength);
+ offset += 4;
+ pthread_mutex_lock(&g_mutex);
+ if (send_message(SCARD_CONTROL, msg, offset) != 0)
+ {
+ LLOGLN(0, ("SCardControl: error, send_message"));
+ free(msg);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ bytes = 8192;
+ if (get_message(&code, msg, &bytes) != 0)
+ {
+ LLOGLN(0, ("SCardControl: error, get_message"));
+ free(msg);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ if (code != SCARD_CONTROL)
+ {
+ LLOGLN(0, ("SCardControl: error, bad code"));
+ free(msg);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ pthread_mutex_unlock(&g_mutex);
+ offset = 0;
+ *lpBytesReturned = GET_UINT32(msg, offset);
+ offset += 4;
+ memcpy(pbRecvBuffer, msg + offset, *lpBytesReturned);
+ offset += *lpBytesReturned;
+ status = GET_UINT32(msg, offset);
+ free(msg);
+ return status;
+}
+
+/*****************************************************************************/
+PCSC_API LONG
+SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
+ LPCBYTE pbSendBuffer, DWORD cbSendLength,
+ SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer,
+ LPDWORD pcbRecvLength)
+{
+ char *msg;
+ int bytes;
+ int code;
+ int offset;
+ int status;
+ int extra_len;
+
+ LLOGLN(10, ("SCardTransmit:"));
+ if (g_sck == -1)
+ {
+ LLOGLN(0, ("SCardTransmit: error, not connected"));
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ LLOGLN(10, ("SCardTransmit: cbSendLength %d", cbSendLength));
+ LLOGLN(10, ("SCardTransmit: pioRecvPci %p", pioRecvPci));
+ if (pioRecvPci != 0)
+ {
+ LLOGLN(10, ("SCardTransmit: pioRecvPci->dwProtocol %d",
+ (int)pioRecvPci->dwProtocol));
+ LLOGLN(10, ("SCardTransmit: pioRecvPci->cbPciLength %d",
+ (int)pioRecvPci->cbPciLength));
+ }
+ msg = (char *) malloc(8192);
+ offset = 0;
+ SET_UINT32(msg, offset, hCard);
+ offset += 4;
+ SET_UINT32(msg, offset, pioSendPci->dwProtocol);
+ offset += 4;
+ SET_UINT32(msg, offset, pioSendPci->cbPciLength);
+ offset += 4;
+ extra_len = pioSendPci->cbPciLength - 8;
+ SET_UINT32(msg, offset, extra_len);
+ offset += 4;
+ memcpy(msg + offset, pioSendPci + 1, extra_len);
+ offset += extra_len;
+ SET_UINT32(msg, offset, cbSendLength);
+ offset += 4;
+ memcpy(msg + offset, pbSendBuffer, cbSendLength);
+ offset += cbSendLength;
+ if ((pioRecvPci == 0) || (pioRecvPci->cbPciLength < 8))
+ {
+ SET_UINT32(msg, offset, 0); /* dwProtocol */
+ offset += 4;
+ SET_UINT32(msg, offset, 0); /* cbPciLength */
+ offset += 4;
+ SET_UINT32(msg, offset, 0); /* extra_len */
+ offset += 4;
+ }
+ else
+ {
+ SET_UINT32(msg, offset, pioRecvPci->dwProtocol);
+ offset += 4;
+ SET_UINT32(msg, offset, pioRecvPci->cbPciLength);
+ offset += 4;
+ extra_len = pioRecvPci->cbPciLength - 8;
+ SET_UINT32(msg, offset, extra_len);
+ offset += 4;
+ memcpy(msg + offset, pioRecvPci + 1, extra_len);
+ offset += extra_len;
+ }
+ SET_UINT32(msg, offset, *pcbRecvLength);
+ offset += 4;
+ pthread_mutex_lock(&g_mutex);
+ if (send_message(SCARD_TRANSMIT, msg, offset) != 0)
+ {
+ LLOGLN(0, ("SCardTransmit: error, send_message"));
+ free(msg);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ bytes = 8192;
+ if (get_message(&code, msg, &bytes) != 0)
+ {
+ LLOGLN(0, ("SCardTransmit: error, get_message"));
+ free(msg);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ if (code != SCARD_TRANSMIT)
+ {
+ LLOGLN(0, ("SCardTransmit: error, bad code"));
+ free(msg);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ pthread_mutex_unlock(&g_mutex);
+ offset = 0;
+ if (pioRecvPci == 0)
+ {
+ offset += 8;
+ extra_len = GET_UINT32(msg, offset);
+ offset += 4;
+ offset += extra_len;
+ }
+ else
+ {
+ pioRecvPci->dwProtocol = GET_UINT32(msg, offset);
+ offset += 4;
+ pioRecvPci->cbPciLength = GET_UINT32(msg, offset);
+ offset += 4;
+ extra_len = GET_UINT32(msg, offset);
+ offset += 4;
+ offset += extra_len;
+ }
+ *pcbRecvLength = GET_UINT32(msg, offset);
+ offset += 4;
+ LLOGLN(10, ("SCardTransmit: cbRecvLength %d", *pcbRecvLength));
+ memcpy(pbRecvBuffer, msg + offset, *pcbRecvLength);
+ offset += *pcbRecvLength;
+ status = GET_UINT32(msg, offset);
+ free(msg);
+ return status;
+}
+
+/*****************************************************************************/
+PCSC_API LONG
+SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups,
+ LPDWORD pcchGroups)
+{
+ LLOGLN(10, ("SCardListReaderGroups:"));
+ if (g_sck == -1)
+ {
+ LLOGLN(0, ("SCardListReaderGroups: error, not connected"));
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ pthread_mutex_lock(&g_mutex);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_S_SUCCESS;
+}
+
+/*****************************************************************************/
+PCSC_API LONG
+SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders,
+ LPDWORD pcchReaders)
+{
+ char* msg;
+ char* reader_names;
+ int reader_names_index;
+ int code;
+ int bytes;
+ int num_readers;
+ int status;
+ int offset;
+ int index;
+ char reader[100];
+
+ LLOGLN(10, ("SCardListReaders:"));
+ if (g_sck == -1)
+ {
+ LLOGLN(0, ("SCardListReaders: error, not connected"));
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ msg = (char *) malloc(8192);
+ pthread_mutex_lock(&g_mutex);
+ SET_UINT32(msg, 0, hContext);
+ if (send_message(SCARD_LIST_READERS, msg, 4) != 0)
+ {
+ LLOGLN(0, ("SCardListReaders: error, send_message"));
+ free(msg);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ bytes = 8192;
+ if (get_message(&code, msg, &bytes) != 0)
+ {
+ LLOGLN(0, ("SCardListReaders: error, get_message"));
+ free(msg);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ if (code != SCARD_LIST_READERS)
+ {
+ LLOGLN(0, ("SCardListReaders: error, bad code"));
+ free(msg);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ pthread_mutex_unlock(&g_mutex);
+ offset = 0;
+ num_readers = GET_UINT32(msg, offset);
+ offset += 4;
+ LLOGLN(10, ("SCardListReaders: mszReaders %p pcchReaders %p num_readers %d",
+ mszReaders, pcchReaders, num_readers));
+ reader_names = (char *) malloc(8192);
+ reader_names_index = 0;
+ for (index = 0; index < num_readers; index++)
+ {
+ memcpy(reader, msg + offset, 100);
+ bytes = strlen(reader);
+ memcpy(reader_names + reader_names_index, reader, bytes);
+ reader_names_index += bytes;
+ reader_names[reader_names_index] = 0;
+ reader_names_index++;
+ offset += 100;
+ LLOGLN(10, ("SCardListReaders: readername %s", reader));
+ }
+ reader_names[reader_names_index] = 0;
+ reader_names_index++;
+ status = GET_UINT32(msg, offset);
+ offset += 4;
+ if (pcchReaders != 0)
+ {
+ *pcchReaders = reader_names_index;
+ }
+ if (mszReaders != 0)
+ {
+ memcpy(mszReaders, reader_names, reader_names_index);
+ }
+ free(msg);
+ free(reader_names);
+ return status;
+}
+
+/*****************************************************************************/
+PCSC_API LONG
+SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
+{
+ LLOGLN(0, ("SCardFreeMemory:"));
+ if (g_sck == -1)
+ {
+ LLOGLN(0, ("SCardFreeMemory: error, not connected"));
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ pthread_mutex_lock(&g_mutex);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_S_SUCCESS;
+}
+
+/*****************************************************************************/
+PCSC_API LONG
+SCardCancel(SCARDCONTEXT hContext)
+{
+ LLOGLN(0, ("SCardCancel:"));
+ if (g_sck == -1)
+ {
+ LLOGLN(0, ("SCardCancel: error, not connected"));
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ pthread_mutex_lock(&g_mutex);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_S_SUCCESS;
+}
+
+/*****************************************************************************/
+PCSC_API LONG
+SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
+ LPDWORD pcbAttrLen)
+{
+ LLOGLN(0, ("SCardGetAttrib:"));
+ if (g_sck == -1)
+ {
+ LLOGLN(0, ("SCardGetAttrib: error, not connected"));
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ pthread_mutex_lock(&g_mutex);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_S_SUCCESS;
+}
+
+/*****************************************************************************/
+PCSC_API LONG
+SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
+ DWORD cbAttrLen)
+{
+ LLOGLN(0, ("SCardSetAttrib:"));
+ if (g_sck == -1)
+ {
+ LLOGLN(0, ("SCardSetAttrib: error, not connected"));
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ pthread_mutex_lock(&g_mutex);
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_S_SUCCESS;
+}
+
+/*****************************************************************************/
+PCSC_API char *
+pcsc_stringify_error(const long code)
+{
+ LLOGLN(10, ("pcsc_stringify_error: %d", (int)code));
+ switch (code)
+ {
+ case SCARD_S_SUCCESS:
+ snprintf(g_error_str, 511, "Command successful.");
+ break;
+ case SCARD_F_INTERNAL_ERROR:
+ snprintf(g_error_str, 511, "Internal error.");
+ break;
+ default:
+ snprintf(g_error_str, 511, "error 0x%8.8x", (int)code);
+ break;
+ }
+ g_error_str[511] = 0;
+ return g_error_str;
+}
diff --git a/sesman/chansrv/rail.c b/sesman/chansrv/rail.c
index cfa3c5de..fb1075c6 100644
--- a/sesman/chansrv/rail.c
+++ b/sesman/chansrv/rail.c
@@ -19,15 +19,24 @@
/*
window manager info
http://www.freedesktop.org/wiki/Specifications/wm-spec
+
+ rail
+ [MS-RDPERP]: Remote Desktop Protocol:
+ Remote Programs Virtual Channel Extension
+ http://msdn.microsoft.com/en-us/library/cc242568(v=prot.20).aspx
*/
#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/Xrandr.h>
+#include <X11/cursorfont.h>
#include "chansrv.h"
#include "rail.h"
#include "xcommon.h"
#include "log.h"
#include "os_calls.h"
#include "thread_calls.h"
+#include "list.h"
extern int g_rail_chan_id; /* in chansrv.c */
extern int g_display_num; /* in chansrv.c */
@@ -41,11 +50,43 @@ extern Screen *g_screen; /* in xcommon.c */
extern Window g_root_window; /* in xcommon.c */
extern Atom g_wm_delete_window_atom; /* in xcommon.c */
extern Atom g_wm_protocols_atom; /* in xcommon.c */
+extern Atom g_utf8_string; /* in xcommon.c */
+extern Atom g_net_wm_name; /* in xcommon.c */
+extern Atom g_wm_state; /* in xcommon.c */
+
+static Atom g_rwd_atom = 0;
int g_rail_up = 0;
/* for rail_is_another_wm_running */
static int g_rail_running = 1;
+/* list of valid rail windows */
+static struct list* g_window_list = 0;
+
+static int g_got_focus = 0;
+static int g_focus_counter = 0;
+static Window g_focus_win = 0;
+
+static int g_xrr_event_base = 0; /* non zero means we got extension */
+
+static Cursor g_default_cursor = 0;
+
+/* used in valid field of struct rail_window_data */
+#define RWD_X (1 << 0)
+#define RWD_Y (1 << 1)
+#define RWD_WIDTH (1 << 2)
+#define RWD_HEIGHT (1 << 3)
+#define RWD_TITLE (1 << 4)
+
+struct rail_window_data
+{
+ int valid; /* bits for which fields are valid */
+ int x;
+ int y;
+ int width;
+ int height;
+ int title_crc; /* crc of title for compare */
+};
/* Indicates a Client Execute PDU from client to server. */
#define TS_RAIL_ORDER_EXEC 0x0001
@@ -101,6 +142,133 @@ static int g_rail_running = 1;
/* Perform the default action of the window's system menu. */
#define SC_DEFAULT 0xF160
+/* for tooltips */
+#define RAIL_STYLE_TOOLTIP (0x80000000)
+#define RAIL_EXT_STYLE_TOOLTIP (0x00000080 | 0x00000008)
+
+/* for normal desktop windows */
+#define RAIL_STYLE_NORMAL (0x00C00000 | 0x00080000 | 0x00040000 | 0x00010000 | 0x00020000)
+#define RAIL_EXT_STYLE_NORMAL (0x00040000)
+
+/* for dialogs */
+#define RAIL_STYLE_DIALOG (0x80000000)
+#define RAIL_EXT_STYLE_DIALOG (0x00040000)
+
+static int APP_CC rail_win_get_state(Window win);
+static int APP_CC rail_create_window(Window window_id, Window owner_id);
+static int APP_CC rail_win_set_state(Window win, unsigned long state);
+static int APP_CC rail_show_window(Window window_id, int show_state);
+static int APP_CC rail_win_send_text(Window win);
+
+/*****************************************************************************/
+static int APP_CC
+rail_send_key_esc(int window_id)
+{
+ XEvent event;
+
+ g_memset(&event, 0, sizeof(event));
+ event.type = KeyPress;
+ event.xkey.same_screen = True;
+ event.xkey.root = g_root_window;
+ event.xkey.window = window_id;
+ event.xkey.keycode = 9;
+ XSendEvent(g_display, window_id, True, 0xfff, &event);
+ event.type = KeyRelease;
+ XSendEvent(g_display, window_id, True, 0xfff, &event);
+ return 0;
+}
+
+/*****************************************************************************/
+static struct rail_window_data* APP_CC
+rail_get_window_data(Window window)
+{
+ int bytes;
+ Atom actual_type_return;
+ int actual_format_return;
+ unsigned long nitems_return;
+ unsigned long bytes_after_return;
+ unsigned char* prop_return;
+ struct rail_window_data* rv;
+
+ LOG(10, ("chansrv::rail_get_window_data:"));
+ rv = 0;
+ actual_type_return = 0;
+ actual_format_return = 0;
+ nitems_return = 0;
+ prop_return = 0;
+ bytes = sizeof(struct rail_window_data);
+ XGetWindowProperty(g_display, window, g_rwd_atom, 0, bytes, 0,
+ XA_STRING, &actual_type_return,
+ &actual_format_return, &nitems_return,
+ &bytes_after_return, &prop_return);
+ if (prop_return == 0)
+ {
+ return 0;
+ }
+ if (nitems_return == bytes)
+ {
+ rv = (struct rail_window_data*)prop_return;
+ }
+ return rv;
+}
+
+/*****************************************************************************/
+static int APP_CC
+rail_set_window_data(Window window, struct rail_window_data* rwd)
+{
+ int bytes;
+
+ bytes = sizeof(struct rail_window_data);
+ XChangeProperty(g_display, window, g_rwd_atom, XA_STRING, 8,
+ PropModeReplace, (unsigned char*)rwd, bytes);
+ return 0;
+}
+
+/*****************************************************************************/
+/* get the rail window data, if not exist, try to create it and return */
+static struct rail_window_data* APP_CC
+rail_get_window_data_safe(Window window)
+{
+ struct rail_window_data* rv;
+
+ rv = rail_get_window_data(window);
+ if (rv != 0)
+ {
+ return rv;
+ }
+ rv = g_malloc(sizeof(struct rail_window_data), 1);
+ rail_set_window_data(window, rv);
+ g_free(rv);
+ return rail_get_window_data(window);
+}
+
+/******************************************************************************/
+static int APP_CC
+is_window_valid_child_of_root(unsigned int window_id)
+{
+ int found;
+ unsigned int i;
+ unsigned int nchild;
+ Window r;
+ Window p;
+ Window *children;
+
+ found = 0;
+ XQueryTree(g_display, g_root_window, &r, &p, &children, &nchild);
+
+ for (i = 0; i < nchild; i++)
+ {
+ if (window_id == children[i])
+ {
+ found = 1;
+ break;
+ }
+ }
+
+ XFree(children);
+ return found;
+}
+
/*****************************************************************************/
static int APP_CC
rail_send_init(void)
@@ -163,6 +331,11 @@ rail_is_another_wm_running(void)
int APP_CC
rail_init(void)
{
+ int dummy;
+ int ver_maj;
+ int ver_min;
+ Status st;
+
LOG(10, ("chansrv::rail_init:"));
xcommon_init();
@@ -171,9 +344,34 @@ rail_init(void)
log_message(LOG_LEVEL_ERROR, "rail_init: another window manager "
"is running");
}
-
+ list_delete(g_window_list);
+ g_window_list = list_create();
rail_send_init();
g_rail_up = 1;
+ g_rwd_atom = XInternAtom(g_display, "XRDP_RAIL_WINDOW_DATA", 0);
+
+ if (!XRRQueryExtension(g_display, &g_xrr_event_base, &dummy))
+ {
+ g_xrr_event_base = 0;
+ log_message(LOG_LEVEL_ERROR, "rail_init: RandR extension not found");
+ }
+
+ if (g_xrr_event_base > 0)
+ {
+ LOG(0, ("rail_init: found RandR entension"));
+ st = XRRQueryVersion(g_display, &ver_maj, &ver_min);
+ if (st)
+ {
+ LOG(0, ("rail_init: RandR version major %d minor %d", ver_maj, ver_min));
+ }
+ XRRSelectInput(g_display, g_root_window, RRScreenChangeNotifyMask);
+ }
+
+ if (g_default_cursor == 0)
+ {
+ g_default_cursor = XCreateFontCursor(g_display, XC_left_ptr);
+ XDefineCursor(g_display, g_root_window, g_default_cursor);
+ }
return 0;
}
@@ -183,6 +381,8 @@ rail_deinit(void)
{
if (g_rail_up)
{
+ list_delete(g_window_list);
+ g_window_list = 0;
/* no longer window manager */
XSelectInput(g_display, g_root_window, 0);
g_rail_up = 0;
@@ -270,26 +470,173 @@ rail_process_exec(struct stream *s, int size)
return 0;
}
+/******************************************************************************/
+static int APP_CC
+rail_win_popdown(void)
+{
+ int rv = 0;
+ int i;
+ unsigned int nchild;
+ Window r;
+ Window p;
+ Window* children;
+ XWindowAttributes window_attributes;
+
+ /*
+ * Check the tree of current existing X windows and dismiss
+ * the managed rail popups by simulating a esc key, so
+ * that the requested window can be closed properly.
+ */
+
+ XQueryTree(g_display, g_root_window, &r, &p, &children, &nchild);
+ for (i = nchild - 1; i >= 0; i--)
+ {
+ XGetWindowAttributes(g_display, children[i], &window_attributes);
+ if (window_attributes.override_redirect &&
+ window_attributes.map_state == IsViewable &&
+ list_index_of(g_window_list, children[i]) >= 0)
+ {
+ LOG(10, (" dismiss pop up 0x%8.8x", children[i]));
+ rail_send_key_esc(children[i]);
+ rv = 1;
+ }
+ }
+
+ XFree(children);
+ return rv;
+}
+
+/******************************************************************************/
+static int APP_CC
+rail_close_window(int window_id)
+{
+ XEvent ce;
+
+ LOG(0, ("chansrv::rail_close_window:"));
+
+ rail_win_popdown();
+
+ g_memset(&ce, 0, sizeof(ce));
+ ce.xclient.type = ClientMessage;
+ ce.xclient.message_type = g_wm_protocols_atom;
+ ce.xclient.display = g_display;
+ ce.xclient.window = window_id;
+ ce.xclient.format = 32;
+ ce.xclient.data.l[0] = g_wm_delete_window_atom;
+ ce.xclient.data.l[1] = CurrentTime;
+ XSendEvent(g_display, window_id, False, NoEventMask, &ce);
+
+ return 0;
+}
+
+/*****************************************************************************/
+void DEFAULT_CC
+my_timoeut(void* data)
+{
+ LOG(10, ("my_timoeut: g_got_focus %d", g_got_focus));
+ if (g_focus_counter == (int)(long)data)
+ {
+ LOG(10, ("my_timoeut: g_focus_counter %d", g_focus_counter));
+ rail_win_popdown();
+ }
+}
+
/*****************************************************************************/
static int APP_CC
rail_process_activate(struct stream *s, int size)
{
int window_id;
int enabled;
+ int index;
+ XWindowAttributes window_attributes;
+ Window transient_for = 0;
LOG(10, ("chansrv::rail_process_activate:"));
in_uint32_le(s, window_id);
in_uint8(s, enabled);
+
+ index = list_index_of(g_window_list, window_id);
+ if (index < 0)
+ {
+ LOG(10, ("chansrv::rail_process_activate: window 0x%8.8x not in list",
+ window_id));
+ return 0;
+ }
+
+ g_focus_counter++;
+ g_got_focus = enabled;
LOG(10, (" window_id 0x%8.8x enabled %d", window_id, enabled));
+ XGetWindowAttributes(g_display, window_id, &window_attributes);
+
if (enabled)
{
+ if (g_focus_win == window_id)
+ {
+ /* In case that window is unmapped upon minimization and not yet mapped*/
+ XMapWindow(g_display, window_id);
+ }
+ else
+ {
+ rail_win_popdown();
+ if (window_attributes.map_state != IsViewable)
+ {
+ /* In case that window is unmapped upon minimization and not yet mapped */
+ XMapWindow(g_display, window_id);
+ }
+ XGetTransientForHint(g_display, window_id, &transient_for);
+ if (transient_for > 0)
+ {
+ /* Owner window should be raised up as well */
+ XRaiseWindow(g_display, transient_for);
+ }
+ LOG(10, ("chansrv::rail_process_activate: calling XRaiseWindow 0x%8.8x", window_id));
+ XRaiseWindow(g_display, window_id);
+ LOG(10, ("chansrv::rail_process_activate: calling XSetInputFocus 0x%8.8x", window_id));
+ XSetInputFocus(g_display, window_id, RevertToParent, CurrentTime);
+ }
LOG(10, ("chansrv::rail_process_activate: calling XRaiseWindow 0x%8.8x", window_id));
XRaiseWindow(g_display, window_id);
LOG(10, ("chansrv::rail_process_activate: calling XSetInputFocus 0x%8.8x", window_id));
XSetInputFocus(g_display, window_id, RevertToParent, CurrentTime);
+ } else {
+ XWindowAttributes window_attributes;
+ XGetWindowAttributes(g_display, window_id, &window_attributes);
+
+ LOG(10, (" window attributes: override_redirect %d",
+ window_attributes.override_redirect));
+ add_timeout(200, my_timoeut, (void*)(long)g_focus_counter);
}
+ return 0;
+}
+/*****************************************************************************/
+static int APP_CC
+rail_restore_windows(void)
+{
+ unsigned int i;
+ unsigned int nchild;
+ Window r;
+ Window p;
+ Window* children;
+
+ XQueryTree(g_display, g_root_window, &r, &p, &children, &nchild);
+ for (i = 0; i < nchild; i++)
+ {
+ XWindowAttributes window_attributes;
+ XGetWindowAttributes(g_display, children[i], &window_attributes);
+ if (!window_attributes.override_redirect)
+ {
+ if (window_attributes.map_state == IsViewable)
+ {
+ rail_win_set_state(children[i], 0x0); /* WithdrawnState */
+ rail_create_window(children[i], g_root_window);
+ rail_win_set_state(children[i], 0x1); /* NormalState */
+ rail_win_send_text(children[i]);
+ }
+ }
+ }
+ XFree(children);
return 0;
}
@@ -302,25 +649,173 @@ rail_process_system_param(struct stream *s, int size)
LOG(10, ("chansrv::rail_process_system_param:"));
in_uint32_le(s, system_param);
LOG(10, (" system_param 0x%8.8x", system_param));
+ /*
+ * Ask client to re-create the existing rail windows. This is supposed
+ * to be done after handshake and client is initialised properly, we
+ * consider client is ready when it sends "SET_WORKAREA" sysparam.
+ */
+ if (system_param == 0x0000002F) /*SPI_SET_WORK_AREA*/
+ {
+ LOG(10, (" restore rail windows"));
+ rail_restore_windows();
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+rail_get_property(Display* display, Window target, Atom type, Atom property,
+ unsigned char** data, unsigned long* count)
+{
+ Atom atom_return;
+ int size;
+ unsigned long nitems, bytes_left;
+ char* prop_name;
+
+ int ret = XGetWindowProperty(display, target, property,
+ 0l, 1l, False,
+ type, &atom_return, &size,
+ &nitems, &bytes_left, data);
+ if ((ret != Success || nitems < 1) && atom_return == None)
+ {
+ prop_name = XGetAtomName(g_display, property);
+ LOG(10, (" rail_get_property %s: failed", prop_name));
+ XFree(prop_name);
+ return 1;
+ }
+
+ if (bytes_left != 0)
+ {
+ XFree(*data);
+ unsigned long remain = ((size / 8) * nitems) + bytes_left;
+ ret = XGetWindowProperty(g_display, target,
+ property, 0l, remain, False,
+ atom_return, &atom_return, &size,
+ &nitems, &bytes_left, data);
+ if (ret != Success)
+ {
+ return 1;
+ }
+ }
+
+ *count = nitems;
return 0;
}
+/*****************************************************************************/
+static int APP_CC
+rail_win_get_state(Window win)
+{
+ unsigned long nitems = 0;
+ int rv = -1;
+ char* data = 0;
+
+ rail_get_property(g_display, win, g_wm_state, g_wm_state,
+ (unsigned char **)&data,
+ &nitems);
+
+ if (data || nitems > 0)
+ {
+ rv = *(unsigned long *)data;
+ XFree(data);
+ LOG(10, (" rail_win_get_state: %d", rv));
+ }
+
+ return rv;
+}
+
+/*****************************************************************************/
+static int APP_CC
+rail_win_set_state(Window win, unsigned long state)
+{
+ int old_state;
+ unsigned long data[2] = { state, None };
+
+ LOG(10, (" rail_win_set_state: %d", state));
+ /* check whether WM_STATE exists */
+ old_state = rail_win_get_state(win);
+ if (old_state == -1)
+ {
+ /* create WM_STATE property */
+ XChangeProperty(g_display, win, g_wm_state, g_wm_state, 32, PropModeAppend,
+ (unsigned char *)data, 2);
+ LOG(10, (" rail_win_set_state: create WM_STATE property"));
+ }
+ else
+ {
+ XChangeProperty(g_display, win, g_wm_state, g_wm_state, 32, PropModeReplace,
+ (unsigned char *)data, 2);
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+rail_win_get_text(Window win, char **data)
+{
+ int ret = 0;
+ int i = 0;
+ unsigned long nitems = 0;
+
+ ret = rail_get_property(g_display, win, g_utf8_string, g_net_wm_name,
+ (unsigned char **)data, &nitems);
+ if (ret != 0)
+ {
+ /* _NET_WM_NAME isn't set, use WM_NAME (XFetchName) instead */
+ XFetchName(g_display, win, data);
+ }
+
+ if (data)
+ {
+ char *ptr = *data;
+ for (; ptr != NULL; i++)
+ {
+ if (ptr[i] == '\0')
+ {
+ break;
+ }
+ }
+ }
+
+ return i;
+}
+
/******************************************************************************/
static int APP_CC
-rail_close_window(int window_id)
+rail_minmax_window(int window_id, int max)
{
- XEvent ce;
+ LOG(10, ("chansrv::rail_minmax_window 0x%8.8x:", window_id));
+ if (max)
+ {
+
+ } else {
+ XUnmapWindow(g_display, window_id);
+ /* change window state to IconicState (3) */
+ rail_win_set_state(window_id, 0x3);
+ /*
+ * TODO dismiss popups opened so far
+ */
+ }
+ return 0;
+}
- LOG(0, ("chansrv::rail_close_window:"));
- g_memset(&ce, 0, sizeof(ce));
- ce.xclient.type = ClientMessage;
- ce.xclient.message_type = g_wm_protocols_atom;
- ce.xclient.display = g_display;
- ce.xclient.window = window_id;
- ce.xclient.format = 32;
- ce.xclient.data.l[0] = g_wm_delete_window_atom;
- ce.xclient.data.l[1] = CurrentTime;
- XSendEvent(g_display, window_id, False, NoEventMask, &ce);
+/*****************************************************************************/
+static int APP_CC
+rail_restore_window(int window_id)
+{
+ XWindowAttributes window_attributes;
+
+ LOG(10, ("chansrv::rail_restore_window 0x%8.8x:", window_id));
+ XGetWindowAttributes(g_display, window_id, &window_attributes);
+ if (window_attributes.map_state != IsViewable)
+ {
+ XMapWindow(g_display, window_id);
+ }
+ LOG(10, ("chansrv::rail_process_activate: calling XRaiseWindow 0x%8.8x", window_id));
+ XRaiseWindow(g_display, window_id);
+ LOG(10, ("chansrv::rail_process_activate: calling XSetInputFocus 0x%8.8x", window_id));
+ XSetInputFocus(g_display, window_id, RevertToParent, CurrentTime);
+
return 0;
}
@@ -330,11 +825,20 @@ rail_process_system_command(struct stream *s, int size)
{
int window_id;
int command;
+ int index;
LOG(10, ("chansrv::rail_process_system_command:"));
in_uint32_le(s, window_id);
in_uint16_le(s, command);
+ index = list_index_of(g_window_list, window_id);
+ if (index < 0)
+ {
+ LOG(10, ("chansrv::rail_process_system_command: window 0x%8.8x not in list",
+ window_id));
+ return 0;
+ }
+
switch (command)
{
case SC_SIZE:
@@ -345,6 +849,7 @@ rail_process_system_command(struct stream *s, int size)
break;
case SC_MINIMIZE:
LOG(10, (" window_id 0x%8.8x SC_MINIMIZE", window_id));
+ rail_minmax_window(window_id, 0);
break;
case SC_MAXIMIZE:
LOG(10, (" window_id 0x%8.8x SC_MAXIMIZE", window_id));
@@ -358,6 +863,7 @@ rail_process_system_command(struct stream *s, int size)
break;
case SC_RESTORE:
LOG(10, (" window_id 0x%8.8x SC_RESTORE", window_id));
+ rail_restore_window(window_id);
break;
case SC_DEFAULT:
LOG(10, (" window_id 0x%8.8x SC_DEFAULT", window_id));
@@ -409,16 +915,30 @@ rail_process_window_move(struct stream *s, int size)
int top;
int right;
int bottom;
+ tsi16 si16;
+ struct rail_window_data* rwd;
LOG(10, ("chansrv::rail_process_window_move:"));
in_uint32_le(s, window_id);
- in_uint16_le(s, left);
- in_uint16_le(s, top);
- in_uint16_le(s, right);
- in_uint16_le(s, bottom);
+ in_uint16_le(s, si16);
+ left = si16;
+ in_uint16_le(s, si16);
+ top = si16;
+ in_uint16_le(s, si16);
+ right = si16;
+ in_uint16_le(s, si16);
+ bottom = si16;
LOG(10, (" window_id 0x%8.8x left %d top %d right %d bottom %d width %d height %d",
window_id, left, top, right, bottom, right - left, bottom - top));
XMoveResizeWindow(g_display, window_id, left, top, right - left, bottom - top);
+ rwd = (struct rail_window_data*)
+ g_malloc(sizeof(struct rail_window_data), 1);
+ rwd->x = left;
+ rwd->y = top;
+ rwd->width = right - left;
+ rwd->height = bottom - top;
+ rail_set_window_data(window_id, rwd);
+ g_free(rwd);
return 0;
}
@@ -431,13 +951,16 @@ rail_process_local_move_size(struct stream *s, int size)
int move_size_type;
int pos_x;
int pos_y;
+ tsi16 si16;
LOG(10, ("chansrv::rail_process_local_move_size:"));
in_uint32_le(s, window_id);
in_uint16_le(s, is_move_size_start);
in_uint16_le(s, move_size_type);
- in_uint16_le(s, pos_x);
- in_uint16_le(s, pos_y);
+ in_uint16_le(s, si16);
+ pos_x = si16;
+ in_uint16_le(s, si16);
+ pos_y = si16;
LOG(10, (" window_id 0x%8.8x is_move_size_start %d move_size_type %d "
"pos_x %d pos_y %d", window_id, is_move_size_start, move_size_type,
pos_x, pos_y));
@@ -472,11 +995,14 @@ rail_process_sys_menu(struct stream *s, int size)
int window_id;
int left;
int top;
+ tsi16 si16;
LOG(10, ("chansrv::rail_process_sys_menu:"));
in_uint32_le(s, window_id);
- in_uint16_le(s, left);
- in_uint16_le(s, top);
+ in_uint16_le(s, si16);
+ left = si16;
+ in_uint16_le(s, si16);
+ top = si16;
LOG(10, (" window_id 0x%8.8x left %d top %d", window_id, left, top));
return 0;
}
@@ -588,14 +1114,646 @@ rail_data_in(struct stream *s, int chan_id, int chan_flags, int length,
return 0;
}
+static int g_crc_seed = 0xffffffff;
+static int g_crc_table[256] =
+{
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+ 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+ 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+ 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+ 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+ 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+ 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+ 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+ 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+ 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+ 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+ 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+ 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+ 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+ 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+ 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+ 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+ 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+#define CRC_START(in_crc) (in_crc) = g_crc_seed
+#define CRC_PASS(in_pixel, in_crc) \
+ (in_crc) = g_crc_table[((in_crc) ^ (in_pixel)) & 0xff] ^ ((in_crc) >> 8)
+#define CRC_END(in_crc) (in_crc) = ((in_crc) ^ g_crc_seed)
+
+/*****************************************************************************/
+static int
+get_string_crc(const char* text)
+{
+ int index;
+ int crc;
+
+ CRC_START(crc);
+ index = 0;
+ while (text[index] != 0)
+ {
+ CRC_PASS(text[index], crc);
+ index++;
+ }
+ CRC_END(crc);
+ return crc;
+}
+
+/*****************************************************************************/
+/* returns 0, event handled, 1 unhandled */
+static int APP_CC
+rail_win_send_text(Window win)
+{
+ char* data = 0;
+ struct stream* s;
+ int len = 0;
+ int flags;
+ int crc;
+ struct rail_window_data* rwd;
+
+ len = rail_win_get_text(win, &data);
+ rwd = rail_get_window_data_safe(win);
+ if (rwd != 0)
+ {
+ if (data != 0)
+ {
+ if (rwd->valid & RWD_TITLE)
+ {
+ crc = get_string_crc(data);
+ if (rwd->title_crc == crc)
+ {
+ LOG(10, ("chansrv::rail_win_send_text: skipping, title not changed"));
+ XFree(data);
+ XFree(rwd);
+ return 0;
+ }
+ }
+ }
+ }
+ else
+ {
+ LOG(0, ("chansrv::rail_win_send_text: error rail_get_window_data_safe failed"));
+ return 1;
+ }
+ if (data && len > 0) {
+ LOG(10, ("chansrv::rail_win_send_text: 0x%8.8x text %s length %d",
+ win, data, len));
+ make_stream(s);
+ init_stream(s, 1024);
+ flags = WINDOW_ORDER_TYPE_WINDOW | WINDOW_ORDER_FIELD_TITLE;
+ out_uint32_le(s, 8); /* update title info */
+ out_uint32_le(s, win); /* window id */
+ out_uint32_le(s, flags); /* flags */
+ out_uint32_le(s, len); /* title size */
+ out_uint8a(s, data, len); /* title */
+ s_mark_end(s);
+ send_rail_drawing_orders(s->data, (int)(s->end - s->data));
+ free_stream(s);
+ /* update rail window data */
+ rwd->valid |= RWD_TITLE;
+ crc = get_string_crc(data);
+ rwd->title_crc = crc;
+ rail_set_window_data(win, rwd);
+ }
+ if (data != 0)
+ {
+ XFree(data);
+ }
+ XFree(rwd);
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+rail_destroy_window(Window window_id)
+{
+ struct stream *s;
+
+ LOG(10, ("chansrv::rail_destroy_window 0x%8.8x", window_id));
+ make_stream(s);
+ init_stream(s, 1024);
+
+ out_uint32_le(s, 4); /* destroy_window */
+ out_uint32_le(s, window_id);
+ s_mark_end(s);
+ send_rail_drawing_orders(s->data, (int)(s->end - s->data));
+ free_stream(s);
+
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+rail_show_window(Window window_id, int show_state)
+{
+ int flags;
+ struct stream* s;
+
+ LOG(10, ("chansrv::rail_show_window 0x%8.8x 0x%x", window_id, show_state));
+ make_stream(s);
+ init_stream(s, 1024);
+
+ flags = WINDOW_ORDER_TYPE_WINDOW | WINDOW_ORDER_FIELD_SHOW;
+ out_uint32_le(s, 6); /* show_window */
+ out_uint32_le(s, window_id); /* window_id */
+ out_uint32_le(s, flags); /* flags */
+ out_uint32_le(s, show_state); /* show_state */
+ s_mark_end(s);
+ send_rail_drawing_orders(s->data, (int)(s->end - s->data));
+ free_stream(s);
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+rail_create_window(Window window_id, Window owner_id)
+{
+ int x;
+ int y;
+ tui32 width;
+ tui32 height;
+ tui32 border;
+ Window root;
+ tui32 depth;
+ char* title_bytes = 0;
+ int title_size = 0;
+ XWindowAttributes attributes;
+ int style;
+ int ext_style;
+ int num_window_rects = 1;
+ int num_visibility_rects = 1;
+ int i = 0;
+
+ int flags;
+ int index;
+ int crc;
+ Window transient_for = 0;
+ struct rail_window_data* rwd;
+ struct stream* s;
+
+ LOG(10, ("chansrv::rail_create_window 0x%8.8x", window_id));
+
+ rwd = rail_get_window_data_safe(window_id);
+ if (rwd == 0)
+ {
+ LOG(0, ("chansrv::rail_create_window: error rail_get_window_data_safe failed"));
+ return 0;
+ }
+ XGetGeometry(g_display, window_id, &root, &x, &y, &width, &height,
+ &border, &depth);
+ XGetWindowAttributes(g_display, window_id, &attributes);
+
+ LOG(10, (" x %d y %d width %d height %d border_width %d", x, y, width,
+ height, border));
+
+ index = list_index_of(g_window_list, window_id);
+ if (index == -1)
+ {
+ LOG(10, (" create new window"));
+ flags = WINDOW_ORDER_TYPE_WINDOW | WINDOW_ORDER_STATE_NEW;
+ list_add_item(g_window_list, window_id);
+ }
+ else
+ {
+ LOG(10, (" update existing window"));
+ flags = WINDOW_ORDER_TYPE_WINDOW;
+ }
+
+ title_size = rail_win_get_text(window_id, &title_bytes);
+
+ XGetTransientForHint(g_display, window_id, &transient_for);
+
+ if (attributes.override_redirect)
+ {
+ style = RAIL_STYLE_TOOLTIP;
+ ext_style = RAIL_EXT_STYLE_TOOLTIP;
+ }
+ else if (transient_for > 0)
+ {
+ style = RAIL_STYLE_DIALOG;
+ ext_style = RAIL_EXT_STYLE_DIALOG;
+ owner_id = transient_for;
+ }
+ else
+ {
+ style = RAIL_STYLE_NORMAL;
+ ext_style = RAIL_EXT_STYLE_NORMAL;
+ }
+
+ make_stream(s);
+ init_stream(s, 1024);
+
+ out_uint32_le(s, 2); /* create_window */
+ out_uint32_le(s, window_id); /* window_id */
+ out_uint32_le(s, owner_id); /* owner_window_id */
+ flags |= WINDOW_ORDER_FIELD_OWNER;
+ out_uint32_le(s, style); /* style */
+ out_uint32_le(s, ext_style); /* extended_style */
+ flags |= WINDOW_ORDER_FIELD_STYLE;
+ out_uint32_le(s, 0x05); /* show_state */
+ flags |= WINDOW_ORDER_FIELD_SHOW;
+ if (title_size > 0)
+ {
+ out_uint16_le(s, title_size); /* title_size */
+ out_uint8a(s, title_bytes, title_size); /* title */
+ rwd->valid |= RWD_TITLE;
+ crc = get_string_crc(title_bytes);
+ rwd->title_crc = crc;
+ }
+ else
+ {
+ out_uint16_le(s, 5); /* title_size */
+ out_uint8a(s, "title", 5); /* title */
+ rwd->valid |= RWD_TITLE;
+ rwd->title_crc = 0;
+ }
+ LOG(10, (" set title info %d", title_size));
+ flags |= WINDOW_ORDER_FIELD_TITLE;
+ out_uint32_le(s, 0); /* client_offset_x */
+ out_uint32_le(s, 0); /* client_offset_y */
+ flags |= WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET;
+ out_uint32_le(s, width); /* client_area_width */
+ out_uint32_le(s, height); /* client_area_height */
+ flags |= WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE;
+ out_uint32_le(s, 0); /* rp_content */
+ out_uint32_le(s, g_root_window); /* root_parent_handle */
+ flags |= WINDOW_ORDER_FIELD_ROOT_PARENT;
+ out_uint32_le(s, x); /* window_offset_x */
+ out_uint32_le(s, y); /* window_offset_y */
+ flags |= WINDOW_ORDER_FIELD_WND_OFFSET;
+ out_uint32_le(s, 0); /* window_client_delta_x */
+ out_uint32_le(s, 0); /* window_client_delta_y */
+ flags |= WINDOW_ORDER_FIELD_WND_CLIENT_DELTA;
+ out_uint32_le(s, width); /* window_width */
+ out_uint32_le(s, height); /* window_height */
+ flags |= WINDOW_ORDER_FIELD_WND_SIZE;
+ out_uint16_le(s, num_window_rects); /* num_window_rects */
+ for (i = 0; i < num_window_rects; i++)
+ {
+ out_uint16_le(s, 0); /* left */
+ out_uint16_le(s, 0); /* top */
+ out_uint16_le(s, width); /* right */
+ out_uint16_le(s, height); /* bottom */
+ }
+ flags |= WINDOW_ORDER_FIELD_WND_RECTS;
+ out_uint32_le(s, x); /* visible_offset_x */
+ out_uint32_le(s, y); /* visible_offset_y */
+ flags |= WINDOW_ORDER_FIELD_VIS_OFFSET;
+ out_uint16_le(s, num_visibility_rects); /* num_visibility_rects */
+ for (i = 0; i < num_visibility_rects; i++)
+ {
+ out_uint16_le(s, 0); /* left */
+ out_uint16_le(s, 0); /* top */
+ out_uint16_le(s, width); /* right */
+ out_uint16_le(s, height); /* bottom */
+ }
+ flags |= WINDOW_ORDER_FIELD_VISIBILITY;
+ out_uint32_le(s, flags); /*flags*/
+
+ s_mark_end(s);
+ send_rail_drawing_orders(s->data, (int)(s->end - s->data));
+ free_stream(s);
+ XFree(title_bytes);
+ rail_set_window_data(window_id, rwd);
+ XFree(rwd);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns 0, event handled, 1 unhandled */
+int APP_CC
+rail_configure_request_window(XConfigureRequestEvent* config)
+{
+ int num_window_rects = 1;
+ int num_visibility_rects = 1;
+ int i = 0;
+ int flags;
+ int index;
+ int window_id;
+ int mask;
+ int resized = 0;
+ struct rail_window_data* rwd;
+
+ struct stream* s;
+
+ window_id = config->window;
+ mask = config->value_mask;
+ LOG(10, ("chansrv::rail_configure_request_window: mask %d", mask));
+ if (mask & CWStackMode)
+ {
+ LOG(10, ("chansrv::rail_configure_request_window: CWStackMode "
+ "detail 0x%8.8x above 0x%8.8x", config->detail, config->above));
+ if (config->detail == Above)
+ {
+ LOG(10, ("chansrv::rail_configure_request_window: bring to front "
+ "window_id 0x%8.8x", window_id));
+ /* 0x05 - Show the window in its current size and position. */
+ rail_show_window(window_id, 5);
+ }
+ }
+ rwd = rail_get_window_data(window_id);
+ if (rwd == 0)
+ {
+ rwd = (struct rail_window_data*)g_malloc(sizeof(struct rail_window_data), 1);
+ rwd->x = config->x;
+ rwd->y = config->y;
+ rwd->width = config->width;
+ rwd->height = config->height;
+ rwd->valid |= RWD_X | RWD_Y | RWD_WIDTH | RWD_HEIGHT;
+ rail_set_window_data(window_id, rwd);
+ g_free(rwd);
+ return 0;
+ }
+ if (!resized)
+ {
+ if (mask & CWX)
+ {
+ if (rwd->valid & RWD_X)
+ {
+ if (rwd->x != config->x)
+ {
+ resized = 1;
+ rwd->x = config->x;
+ }
+ }
+ else
+ {
+ resized = 1;
+ rwd->x = config->x;
+ rwd->valid |= RWD_X;
+ }
+ }
+ }
+ if (!resized)
+ {
+ if (mask & CWY)
+ {
+ if (rwd->valid & RWD_Y)
+ {
+ if (rwd->y != config->y)
+ {
+ resized = 1;
+ rwd->y = config->y;
+ }
+ }
+ else
+ {
+ resized = 1;
+ rwd->y = config->y;
+ rwd->valid |= RWD_Y;
+ }
+ }
+ }
+ if (!resized)
+ {
+ if (mask & CWWidth)
+ {
+ if (rwd->valid & RWD_WIDTH)
+ {
+ if (rwd->width != config->width)
+ {
+ resized = 1;
+ rwd->width = config->width;
+ }
+ }
+ else
+ {
+ resized = 1;
+ rwd->width = config->width;
+ rwd->valid |= RWD_WIDTH;
+ }
+ }
+ }
+ if (!resized)
+ {
+ if (mask & CWHeight)
+ {
+ if (rwd->valid & RWD_HEIGHT)
+ {
+ if (rwd->height != config->height)
+ {
+ resized = 1;
+ rwd->height = config->height;
+ }
+ }
+ else
+ {
+ resized = 1;
+ rwd->height = config->height;
+ rwd->valid |= RWD_HEIGHT;
+ }
+ }
+ }
+ if (resized)
+ {
+ rail_set_window_data(window_id, rwd);
+ XFree(rwd);
+ }
+ else
+ {
+ XFree(rwd);
+ return 0;
+ }
+
+ LOG(10, ("chansrv::rail_configure_request_window: 0x%8.8x", window_id));
+
+
+ LOG(10, (" x %d y %d width %d height %d border_width %d", config->x,
+ config->y, config->width, config->height, config->border_width));
+
+ index = list_index_of(g_window_list, window_id);
+ if (index == -1)
+ {
+ /* window isn't mapped yet */
+ LOG(0, ("chansrv::rail_configure_request_window: window not mapped"));
+ return 0;
+ }
+
+ flags = WINDOW_ORDER_TYPE_WINDOW;
+
+ make_stream(s);
+ init_stream(s, 1024);
+
+ out_uint32_le(s, 10); /* configure_window */
+ out_uint32_le(s, window_id); /* window_id */
+
+ out_uint32_le(s, 0); /* client_offset_x */
+ out_uint32_le(s, 0); /* client_offset_y */
+ flags |= WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET;
+ out_uint32_le(s, config->width); /* client_area_width */
+ out_uint32_le(s, config->height); /* client_area_height */
+ flags |= WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE;
+ out_uint32_le(s, 0); /* rp_content */
+ out_uint32_le(s, g_root_window); /* root_parent_handle */
+ flags |= WINDOW_ORDER_FIELD_ROOT_PARENT;
+ out_uint32_le(s, config->x); /* window_offset_x */
+ out_uint32_le(s, config->y); /* window_offset_y */
+ flags |= WINDOW_ORDER_FIELD_WND_OFFSET;
+ out_uint32_le(s, 0); /* window_client_delta_x */
+ out_uint32_le(s, 0); /* window_client_delta_y */
+ flags |= WINDOW_ORDER_FIELD_WND_CLIENT_DELTA;
+ out_uint32_le(s, config->width); /* window_width */
+ out_uint32_le(s, config->height); /* window_height */
+ flags |= WINDOW_ORDER_FIELD_WND_SIZE;
+ out_uint16_le(s, num_window_rects); /* num_window_rects */
+ for (i = 0; i < num_window_rects; i++)
+ {
+ out_uint16_le(s, 0); /* left */
+ out_uint16_le(s, 0); /* top */
+ out_uint16_le(s, config->width); /* right */
+ out_uint16_le(s, config->height); /* bottom */
+ }
+ flags |= WINDOW_ORDER_FIELD_WND_RECTS;
+ out_uint32_le(s, config->x); /* visible_offset_x */
+ out_uint32_le(s, config->y); /* visible_offset_y */
+ flags |= WINDOW_ORDER_FIELD_VIS_OFFSET;
+ out_uint16_le(s, num_visibility_rects); /* num_visibility_rects */
+ for (i = 0; i < num_visibility_rects; i++)
+ {
+ out_uint16_le(s, 0); /* left */
+ out_uint16_le(s, 0); /* top */
+ out_uint16_le(s, config->width); /* right */
+ out_uint16_le(s, config->height); /* bottom */
+ }
+ flags |= WINDOW_ORDER_FIELD_VISIBILITY;
+ out_uint32_le(s, flags); /*flags*/
+
+ s_mark_end(s);
+ send_rail_drawing_orders(s->data, (int)(s->end - s->data));
+ free_stream(s);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns 0, event handled, 1 unhandled */
+int APP_CC
+rail_configure_window(XConfigureEvent *config)
+{
+ int num_window_rects = 1;
+ int num_visibility_rects = 1;
+ int i = 0;
+ int flags;
+ int index;
+ int window_id;
+
+ struct stream* s;
+
+ window_id = config->window;
+
+ LOG(10, ("chansrv::rail_configure_window 0x%8.8x", window_id));
+
+
+ LOG(10, (" x %d y %d width %d height %d border_width %d", config->x,
+ config->y, config->width, config->height, config->border_width));
+
+ index = list_index_of(g_window_list, window_id);
+ if (index == -1)
+ {
+ /* window isn't mapped yet */
+ return 0;
+ }
+
+ flags = WINDOW_ORDER_TYPE_WINDOW;
+
+ make_stream(s);
+ init_stream(s, 1024);
+
+ out_uint32_le(s, 10); /* configure_window */
+ out_uint32_le(s, window_id); /* window_id */
+
+ out_uint32_le(s, 0); /* client_offset_x */
+ out_uint32_le(s, 0); /* client_offset_y */
+ flags |= WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET;
+ out_uint32_le(s, config->width); /* client_area_width */
+ out_uint32_le(s, config->height); /* client_area_height */
+ flags |= WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE;
+ out_uint32_le(s, 0); /* rp_content */
+ out_uint32_le(s, g_root_window); /* root_parent_handle */
+ flags |= WINDOW_ORDER_FIELD_ROOT_PARENT;
+ out_uint32_le(s, config->x); /* window_offset_x */
+ out_uint32_le(s, config->y); /* window_offset_y */
+ flags |= WINDOW_ORDER_FIELD_WND_OFFSET;
+ out_uint32_le(s, 0); /* window_client_delta_x */
+ out_uint32_le(s, 0); /* window_client_delta_y */
+ flags |= WINDOW_ORDER_FIELD_WND_CLIENT_DELTA;
+ out_uint32_le(s, config->width); /* window_width */
+ out_uint32_le(s, config->height); /* window_height */
+ flags |= WINDOW_ORDER_FIELD_WND_SIZE;
+ out_uint16_le(s, num_window_rects); /* num_window_rects */
+ for (i = 0; i < num_window_rects; i++)
+ {
+ out_uint16_le(s, 0); /* left */
+ out_uint16_le(s, 0); /* top */
+ out_uint16_le(s, config->width); /* right */
+ out_uint16_le(s, config->height); /* bottom */
+ }
+ flags |= WINDOW_ORDER_FIELD_WND_RECTS;
+ out_uint32_le(s, config->x); /* visible_offset_x */
+ out_uint32_le(s, config->y); /* visible_offset_y */
+ flags |= WINDOW_ORDER_FIELD_VIS_OFFSET;
+ out_uint16_le(s, num_visibility_rects); /* num_visibility_rects */
+ for (i = 0; i < num_visibility_rects; i++)
+ {
+ out_uint16_le(s, 0); /* left */
+ out_uint16_le(s, 0); /* top */
+ out_uint16_le(s, config->width); /* right */
+ out_uint16_le(s, config->height); /* bottom */
+ }
+ flags |= WINDOW_ORDER_FIELD_VISIBILITY;
+ out_uint32_le(s, flags); /*flags*/
+
+ s_mark_end(s);
+ send_rail_drawing_orders(s->data, (int)(s->end - s->data));
+ free_stream(s);
+ return 0;
+}
+
+/*****************************************************************************/
+static int
+rail_desktop_resize(lxevent)
+{
+ LOG(0, ("rail_desktop_resize:"));
+ return 0;
+}
+
/*****************************************************************************/
/* returns 0, event handled, 1 unhandled */
int APP_CC
rail_xevent(void *xevent)
{
XEvent *lxevent;
+ XEvent lastevent;
XWindowChanges xwc;
int rv;
+ int index;
+ XWindowAttributes wnd_attributes;
+ char* prop_name;
LOG(10, ("chansrv::rail_xevent:"));
@@ -609,6 +1767,30 @@ rail_xevent(void *xevent)
switch (lxevent->type)
{
+ case PropertyNotify:
+ prop_name = XGetAtomName(g_display, lxevent->xproperty.atom);
+ LOG(10, (" got PropertyNotify window_id 0x%8.8x %s state new %d",
+ lxevent->xproperty.window, prop_name,
+ lxevent->xproperty.state == PropertyNewValue));
+
+ if (list_index_of(g_window_list, lxevent->xproperty.window) < 0)
+ {
+ break;
+ }
+
+ if (g_strcmp(prop_name, "WM_NAME") == 0 ||
+ g_strcmp(prop_name, "_NET_WM_NAME") == 0)
+ {
+ XGetWindowAttributes(g_display, lxevent->xproperty.window, &wnd_attributes);
+ if (wnd_attributes.map_state == IsViewable)
+ {
+ rail_win_send_text(lxevent->xproperty.window);
+ rv = 0;
+ }
+ }
+ XFree(prop_name);
+ break;
+
case ConfigureRequest:
LOG(10, (" got ConfigureRequest window_id 0x%8.8x", lxevent->xconfigurerequest.window));
g_memset(&xwc, 0, sizeof(xwc));
@@ -623,31 +1805,118 @@ rail_xevent(void *xevent)
lxevent->xconfigurerequest.window,
lxevent->xconfigurerequest.value_mask,
&xwc);
+ rail_configure_request_window(&(lxevent->xconfigurerequest));
rv = 0;
break;
+ case CreateNotify:
+ LOG(10, (" got CreateNotify window 0x%8.8x parent 0x%8.8x",
+ lxevent->xcreatewindow.window, lxevent->xcreatewindow.parent));
+ XSelectInput(g_display, lxevent->xcreatewindow.window,
+ PropertyChangeMask | StructureNotifyMask |
+ SubstructureNotifyMask | FocusChangeMask |
+ EnterWindowMask | LeaveWindowMask);
+ break;
+
+ case DestroyNotify:
+ LOG(10, (" got DestroyNotify window 0x%8.8x event 0x%8.8x",
+ lxevent->xdestroywindow.window, lxevent->xdestroywindow.event));
+ if (lxevent->xdestroywindow.window != lxevent->xdestroywindow.event)
+ {
+ break;
+ }
+ index = list_index_of(g_window_list, lxevent->xdestroywindow.window);
+ if (index >= 0)
+ {
+ rail_destroy_window(lxevent->xdestroywindow.window);
+ list_remove_item(g_window_list, index);
+ }
+ rv = 0;
+ break;
+
case MapRequest:
- LOG(10, (" got MapRequest"));
+ LOG(10, (" got MapRequest window 0x%8.8x", lxevent->xmaprequest.window));
XMapWindow(g_display, lxevent->xmaprequest.window);
- rv = 0;
break;
case MapNotify:
- LOG(10, (" got MapNotify"));
+ LOG(10, (" got MapNotify window 0x%8.8x event 0x%8.8x",
+ lxevent->xmap.window, lxevent->xmap.event));
+ if (lxevent->xmap.window != lxevent->xmap.event)
+ {
+ break;
+ }
+
+ if (!is_window_valid_child_of_root(lxevent->xmap.window))
+ {
+ break;
+ }
+
+ XGetWindowAttributes(g_display, lxevent->xmap.window, &wnd_attributes);
+ if (wnd_attributes.map_state == IsViewable)
+ {
+ rail_create_window(lxevent->xmap.window, lxevent->xmap.event);
+ if (!wnd_attributes.override_redirect)
+ {
+ rail_win_set_state(lxevent->xmap.window, 0x1); /* NormalState */
+ rail_win_send_text(lxevent->xmap.window);
+ }
+ rv = 0;
+ }
break;
case UnmapNotify:
- LOG(10, (" got UnmapNotify"));
+ LOG(10, (" got UnmapNotify 0x%8.8x", lxevent->xunmap.event));
+ if (lxevent->xunmap.window != lxevent->xunmap.event)
+ {
+ break;
+ }
+ if (is_window_valid_child_of_root(lxevent->xunmap.window))
+ {
+ index = list_index_of(g_window_list, lxevent->xunmap.window);
+ LOG(10, (" window 0x%8.8x is unmapped", lxevent->xunmap.window));
+ if (index >= 0)
+ {
+ rail_show_window(lxevent->xunmap.window, 0x0);
+ rv = 0;
+ }
+ }
break;
case ConfigureNotify:
- LOG(10, (" got ConfigureNotify"));
+ LOG(10, (" got ConfigureNotify 0x%8.8x event 0x%8.8x", lxevent->xconfigure.window,
+ lxevent->xconfigure.event));
+ rv = 0;
+ if (lxevent->xconfigure.event != lxevent->xconfigure.window ||
+ lxevent->xconfigure.override_redirect)
+ {
+ break;
+ }
+ /* skip dup ConfigureNotify */
+ while (XCheckTypedWindowEvent(g_display,
+ lxevent->xconfigure.window,
+ ConfigureNotify, &lastevent))
+ {
+ if (lastevent.xconfigure.event == lastevent.xconfigure.window &&
+ lxevent->xconfigure.override_redirect == 0)
+ {
+ lxevent = &lastevent;
+ }
+ }
+#if 0
+ rail_configure_window(&(lxevent->xconfigure));
+#endif
break;
case FocusIn:
LOG(10, (" got FocusIn"));
+ g_focus_win = lxevent->xfocus.window;
break;
+ case FocusOut:
+ LOG(10, (" got FocusOut"));
+ break;
+
case ButtonPress:
LOG(10, (" got ButtonPress"));
break;
@@ -660,6 +1929,39 @@ rail_xevent(void *xevent)
LOG(10, (" got LeaveNotify"));
break;
+ case ReparentNotify:
+ LOG(10, (" got ReparentNotify window 0x%8.8x parent 0x%8.8x "
+ "event 0x%8.8x x %d y %d overrider redirect %d",
+ lxevent->xreparent.window, lxevent->xreparent.parent,
+ lxevent->xreparent.event, lxevent->xreparent.x,
+ lxevent->xreparent.y, lxevent->xreparent.override_redirect));
+
+ if (lxevent->xreparent.window != lxevent->xreparent.event)
+ {
+ break;
+ }
+ if (lxevent->xreparent.parent != g_root_window)
+ {
+ index = list_index_of(g_window_list, lxevent->xreparent.window);
+ if (index >= 0)
+ {
+ rail_destroy_window(lxevent->xreparent.window);
+ list_remove_item(g_window_list, index);
+ }
+ }
+ rv = 0;
+ break;
+
+ default:
+ if (g_xrr_event_base > 0)
+ {
+ if (lxevent->type == g_xrr_event_base + RRScreenChangeNotify)
+ {
+ rail_desktop_resize(lxevent);
+ rv = 0;
+ break;
+ }
+ }
}
return rv;
diff --git a/sesman/chansrv/rail.h b/sesman/chansrv/rail.h
index 7dbcbc5a..3be3a15d 100644
--- a/sesman/chansrv/rail.h
+++ b/sesman/chansrv/rail.h
@@ -19,6 +19,7 @@
#ifndef _RAIL_H_
#define _RAIL_H_
+#include "../../common/rail.h"
#include "arch.h"
#include "parse.h"
@@ -31,5 +32,6 @@ rail_data_in(struct stream* s, int chan_id, int chan_flags,
int length, int total_length);
int APP_CC
rail_xevent(void* xevent);
+int APP_CC rail_request_title(int window_id);
#endif
diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c
index c370479e..29406d62 100644
--- a/sesman/chansrv/smartcard.c
+++ b/sesman/chansrv/smartcard.c
@@ -21,6 +21,7 @@
* smartcard redirection support
*/
+#include <string.h>
#include "os_calls.h"
#include "smartcard.h"
#include "log.h"
@@ -31,6 +32,8 @@
/*
* TODO
*
+ * o ensure that all wide calls are handled correctly
+ *
* o need to query client for build number and determine whether we should use
* SCREDIR_VERSION_XP or SCREDIR_VERSION_LONGHORN
*
@@ -56,17 +59,19 @@
#define LOG_DEBUG 2
#ifndef LOG_LEVEL
-#define LOG_LEVEL LOG_DEBUG
+#define LOG_LEVEL LOG_INFO
#endif
#define log_error(_params...) \
+do \
{ \
g_write("[%10.10u]: SMART_CARD %s: %d : ERROR: ", \
g_time3(), __func__, __LINE__); \
g_writeln (_params); \
-}
+} while (0)
#define log_info(_params...) \
+do \
{ \
if (LOG_INFO <= LOG_LEVEL) \
{ \
@@ -74,9 +79,10 @@
g_time3(), __func__, __LINE__); \
g_writeln (_params); \
} \
-}
+} while (0)
#define log_debug(_params...) \
+do \
{ \
if (LOG_DEBUG <= LOG_LEVEL) \
{ \
@@ -84,7 +90,7 @@
g_time3(), __func__, __LINE__); \
g_writeln (_params); \
} \
-}
+} while (0)
/* [MS-RDPESC] 3.1.4 */
#define SCARD_IOCTL_ESTABLISH_CONTEXT 0x00090014 /* EstablishContext */
@@ -98,16 +104,19 @@
#define SCARD_IOCTL_INTRODUCE_READER 0x00090060 /* IntroduceReader */
#define SCARD_IOCTL_FORGET_READER 0x00090068 /* IntroduceReader */
#define SCARD_IOCTL_ADD_READER_TO_GROUP 0x00090070 /* AddReaderToGroup */
-#define SCARD_IOCTL_REMOVE_READER_FROM_GROUP 0x00090078 /* RemoveReaderFromGroup */
-#define SCARD_IOCTL_GET_STATUS_CHANGE 0x000900A0 /* GetStatusChangeA */
+#define SCARD_IOCTL_REMOVE_READER_FROM_GROUP 0x00090078 /* RemoveReaderFromGroup*/
+#define SCARD_IOCTL_GET_STATUS_CHANGE_A 0x000900A0 /* GetStatusChangeA */
+#define SCARD_IOCTL_GET_STATUS_CHANGE_W 0x000900A4 /* GetStatusChangeW */
#define SCARD_IOCTL_CANCEL 0x000900A8 /* Cancel */
-#define SCARD_IOCTL_CONNECT 0x000900AC /* ConnectA */
+#define SCARD_IOCTL_CONNECT_A 0x000900AC /* ConnectA */
+#define SCARD_IOCTL_CONNECT_W 0x000900B0 /* ConnectW */
#define SCARD_IOCTL_RECONNECT 0x000900B4 /* Reconnect */
#define SCARD_IOCTL_DISCONNECT 0x000900B8 /* Disconnect */
#define SCARD_IOCTL_BEGIN_TRANSACTION 0x000900BC /* BeginTransaction */
#define SCARD_IOCTL_END_TRANSACTION 0x000900C0 /* EndTransaction */
#define SCARD_IOCTL_STATE 0x000900C4 /* State */
-#define SCARD_IOCTL_STATUS 0x000900C8 /* StatusA */
+#define SCARD_IOCTL_STATUS_A 0x000900C8 /* StatusA */
+#define SCARD_IOCTL_STATUS_W 0x000900CC /* StatusW */
#define SCARD_IOCTL_TRANSMIT 0x000900D0 /* Transmit */
#define SCARD_IOCTL_CONTROL 0x000900D4 /* Control */
#define SCARD_IOCTL_GETATTRIB 0x000900D8 /* GetAttrib */
@@ -120,191 +129,818 @@
#define SCARD_SCOPE_TERMINAL 0x00000001
#define SCARD_SCOPE_SYSTEM 0x00000002
+/* disposition - action to take on card */
+#define SCARD_LEAVE_CARD 0x00000000
+#define SCARD_RESET_CARD 0x00000001
+#define SCARD_UNPOWER_CARD 0x00000002
+#define SCARD_EJECT_CARD 0x00000003
+
#define MAX_SMARTCARDS 16
/* stores info about a smart card */
typedef struct smartcard
{
tui32 DeviceId;
- char Context[16]; /* opaque context; save as passed to us */
- int Context_len; /* Context len in bytes */
} SMARTCARD;
-SMARTCARD *smartcards[MAX_SMARTCARDS];
-int g_smartcards_inited = 0;
+/* globals */
+SMARTCARD* smartcards[MAX_SMARTCARDS];
+int g_smartcards_inited = 0;
+static tui32 g_device_id = 0;
+static int g_scard_index = 0;
+/* externs */
extern tui32 g_completion_id;
-extern int g_rdpdr_chan_id; /* in chansrv.c */
+extern int g_rdpdr_chan_id; /* in chansrv.c */
+
+
+/******************************************************************************
+** static functions local to this file **
+******************************************************************************/
+static struct stream * APP_CC scard_make_new_ioctl(IRP *irp, tui32 ioctl);
+static int APP_CC scard_add_new_device(tui32 device_id);
+static int APP_CC scard_get_free_slot(void);
+#if 0
+static void APP_CC scard_release_resources(void);
+#endif
+static void APP_CC scard_send_EstablishContext(IRP* irp, int scope);
+static void APP_CC scard_send_ReleaseContext(IRP* irp, tui32 context);
+static void APP_CC scard_send_IsContextValid(IRP* irp, tui32 context);
+static void APP_CC scard_send_ListReaders(IRP* irp, tui32 context, int wide);
+static void APP_CC scard_send_GetStatusChange(IRP* irp, tui32 context, int wide,
+ tui32 timeout, tui32 num_readers,
+ READER_STATE* rsa);
+static void APP_CC scard_send_Connect(IRP* irp, tui32 context, int wide,
+ READER_STATE* rs);
+static void APP_CC scard_send_Reconnect(IRP* irp, tui32 context,
+ tui32 sc_handle, READER_STATE* rs);
+static void APP_CC scard_send_BeginTransaction(IRP* irp, tui32 sc_handle);
+static void APP_CC scard_send_EndTransaction(IRP* irp, tui32 sc_handle,
+ tui32 dwDisposition);
+static void APP_CC scard_send_Status(IRP* irp, int wide, tui32 sc_handle,
+ int cchReaderLen, int cbAtrLen);
+static void APP_CC scard_send_Disconnect(IRP* irp, tui32 context,
+ tui32 sc_handle, int dwDisposition);
+static int APP_CC scard_send_Transmit(IRP* irp, tui32 sc_handle,
+ char *send_data, int send_bytes,
+ int recv_bytes,
+ struct xrdp_scard_io_request *send_ior,
+ struct xrdp_scard_io_request *recv_ior);
+static int APP_CC scard_send_Control(IRP* irp, tui32 context, tui32 sc_handle,
+ char *send_data, int send_bytes,
+ int recv_bytes, int control_code);
+static int APP_CC scard_send_Cancel(IRP* irp, tui32 context);
+static int APP_CC scard_send_GetAttrib(IRP* irp, tui32 sc_handle,
+ READER_STATE* rs);
+
+/******************************************************************************
+** local callbacks into this module **
+******************************************************************************/
+
+static void APP_CC scard_handle_EstablishContext_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId, tui32 CompletionId,
+ tui32 IoStatus);
+
+static void APP_CC scard_handle_ReleaseContext_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId, tui32 CompletionId,
+ tui32 IoStatus);
+
+
+static void APP_CC scard_handle_IsContextValid_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId, tui32 CompletionId,
+ tui32 IoStatus);
+
+static void APP_CC scard_handle_ListReaders_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId, tui32 CompletionId,
+ tui32 IoStatus);
+
+static void APP_CC scard_handle_GetStatusChange_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId, tui32 CompletionId,
+ tui32 IoStatus);
+
+static void APP_CC scard_handle_Connect_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId, tui32 CompletionId,
+ tui32 IoStatus);
-/* forward declarations specific to this file */
-static void scard_send_EstablishContext(IRP *irp);
-static void scard_send_ListReaders(IRP *irp, int wide);
-static struct stream *scard_make_new_ioctl(IRP *irp, tui32 ioctl);
-static int scard_add_new_device(tui32 device_id);
-static int scard_get_free_slot(void);
-static void scard_release_resources(void);
+static void APP_CC scard_handle_Reconnect_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId, tui32 CompletionId,
+ tui32 IoStatus);
+
+static void APP_CC scard_handle_BeginTransaction_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId, tui32 CompletionId,
+ tui32 IoStatus);
+
+static void APP_CC scard_handle_EndTransaction_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId,
+ tui32 CompletionId,
+ tui32 IoStatus);
+
+static void APP_CC scard_handle_Status_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId, tui32 CompletionId,
+ tui32 IoStatus);
+
+static void APP_CC scard_handle_Disconnect_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId, tui32 CompletionId,
+ tui32 IoStatus);
+
+
+static void APP_CC scard_handle_Transmit_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId,
+ tui32 CompletionId,
+ tui32 IoStatus);
+
+static void APP_CC scard_handle_Control_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId,
+ tui32 CompletionId,
+ tui32 IoStatus);
+
+static void APP_CC scard_handle_Cancel_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId,
+ tui32 CompletionId,
+ tui32 IoStatus);
+
+static void APP_CC scard_handle_GetAttrib_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId,
+ tui32 CompletionId,
+ tui32 IoStatus);
/******************************************************************************
-** non static functions **
+** **
+** externally accessible functions, defined in smartcard.h **
+** **
******************************************************************************/
+/**
+ *****************************************************************************/
void APP_CC
scard_device_announce(tui32 device_id)
{
+ log_debug("entered: device_id=%d", device_id);
+
+ if (g_smartcards_inited)
+ return;
+
+ g_memset(&smartcards, 0, sizeof(smartcards));
+ g_smartcards_inited = 1;
+ g_device_id = device_id;
+ g_scard_index = scard_add_new_device(device_id);
+
+ if (g_scard_index < 0)
+ log_debug("scard_add_new_device failed with DeviceId=%d", g_device_id);
+ else
+ log_debug("added smartcard with DeviceId=%d to list", g_device_id);
+}
+
+/**
+ *
+ *****************************************************************************/
+int APP_CC
+scard_get_wait_objs(tbus *objs, int *count, int *timeout)
+{
+ return scard_pcsc_get_wait_objs(objs, count, timeout);
+}
+
+/**
+ *
+ *****************************************************************************/
+int APP_CC
+scard_check_wait_objs(void)
+{
+ return scard_pcsc_check_wait_objs();
+}
+
+/**
+ *
+ *****************************************************************************/
+int APP_CC
+scard_init(void)
+{
+ log_debug("init");
+ return scard_pcsc_init();
+}
+
+/**
+ *
+ *****************************************************************************/
+int APP_CC
+scard_deinit(void)
+{
+ log_debug("deinit");
+ return scard_pcsc_deinit();
+}
+
+/**
+ *
+ *****************************************************************************/
+int APP_CC
+scard_send_establish_context(struct trans *con, int scope)
+{
IRP *irp;
- log_debug("entered: device_id=%d", device_id);
+ /* setup up IRP */
+ if ((irp = devredir_irp_new()) == NULL)
+ {
+ log_error("system out of memory");
+ return 1;
+ }
+
+ irp->scard_index = g_scard_index;
+ irp->CompletionId = g_completion_id++;
+ irp->DeviceId = g_device_id;
+ irp->callback = scard_handle_EstablishContext_Return;
+ irp->user_data = con;
+
+ /* send IRP to client */
+ scard_send_EstablishContext(irp, scope);
- if (!g_smartcards_inited)
+ return 0;
+}
+
+/**
+ * Release a previously established Smart Card context
+ *****************************************************************************/
+int APP_CC
+scard_send_release_context(struct trans *con, tui32 context)
+{
+ IRP *irp;
+
+ /* setup up IRP */
+ if ((irp = devredir_irp_new()) == NULL)
{
- g_memset(&smartcards, 0, sizeof(smartcards));
- g_smartcards_inited = 1;
+ log_error("system out of memory");
+ return 1;
}
+ irp->scard_index = g_scard_index;
+ irp->CompletionId = g_completion_id++;
+ irp->DeviceId = g_device_id;
+ irp->callback = scard_handle_ReleaseContext_Return;
+ irp->user_data = con;
+
+ /* send IRP to client */
+ scard_send_ReleaseContext(irp, context);
+
+ return 0;
+}
+
+/**
+ * Checks if a previously established context is still valid
+ *****************************************************************************/
+int APP_CC
+scard_send_is_valid_context(struct trans *con, tui32 context)
+{
+ IRP *irp;
+
+ /* setup up IRP */
if ((irp = devredir_irp_new()) == NULL)
{
log_error("system out of memory");
- return;
+ return 1;
}
- irp->scard_index = scard_add_new_device(device_id);
- if (irp->scard_index < 0)
+ irp->scard_index = g_scard_index;
+ irp->CompletionId = g_completion_id++;
+ irp->DeviceId = g_device_id;
+ irp->callback = scard_handle_IsContextValid_Return;
+ irp->user_data = con;
+
+ /* send IRP to client */
+ scard_send_IsContextValid(irp, context);
+
+ return 0;
+}
+
+/**
+ *
+ *****************************************************************************/
+int APP_CC
+scard_send_list_readers(struct trans *con, tui32 context, int wide)
+{
+ IRP *irp;
+
+ /* setup up IRP */
+ if ((irp = devredir_irp_new()) == NULL)
{
- log_debug("NOT adding smartcard with DeviceId=%d to list", device_id);
- devredir_irp_delete(irp);
- return;
+ log_error("system out of memory");
+ return 1;
}
+ irp->scard_index = g_scard_index;
+ irp->CompletionId = g_completion_id++;
+ irp->DeviceId = g_device_id;
+ irp->callback = scard_handle_ListReaders_Return;
+ irp->user_data = con;
- log_debug("added smartcard with DeviceId=%d to list", device_id);
+ /* send IRP to client */
+ scard_send_ListReaders(irp, context, wide);
+ return 0;
+}
+
+/**
+ * Send get change in status command
+ *
+ * @param con connection to client
+ * @param wide TRUE if unicode string
+ * @param timeout timeout in milliseconds, -1 for infinity
+ * @param num_readers number of entries in rsa
+ * @param rsa array of READER_STATEs
+ *****************************************************************************/
+int APP_CC
+scard_send_get_status_change(struct trans *con, tui32 context, int wide,
+ tui32 timeout, tui32 num_readers,
+ READER_STATE* rsa)
+{
+ IRP *irp;
+
+ /* setup up IRP */
+ if ((irp = devredir_irp_new()) == NULL)
+ {
+ log_error("system out of memory");
+ return 1;
+ }
+
+ irp->scard_index = g_scard_index;
irp->CompletionId = g_completion_id++;
- irp->DeviceId = device_id;
- irp->callback = scard_handle_EstablishContext_Return;
+ irp->DeviceId = g_device_id;
+ irp->callback = scard_handle_GetStatusChange_Return;
+ irp->user_data = con;
- scard_send_EstablishContext(irp);
- log_debug("leaving");
+ /* send IRP to client */
+ scard_send_GetStatusChange(irp, context, wide, timeout, num_readers, rsa);
+
+ return 0;
}
-/******************************************************************************
-** callbacks into this module **
-******************************************************************************/
+/**
+ * Open a connection to the smart card located in the reader
+ *
+ * @param con connection to client
+ * @param wide TRUE if unicode string
+ *****************************************************************************/
+int APP_CC
+scard_send_connect(struct trans *con, tui32 context, int wide,
+ READER_STATE* rs)
+{
+ IRP *irp;
-void APP_CC
-scard_handle_EstablishContext_Return(struct stream *s, IRP *irp,
- tui32 DeviceId, tui32 CompletionId,
- tui32 IoStatus)
+ /* setup up IRP */
+ if ((irp = devredir_irp_new()) == NULL)
+ {
+ log_error("system out of memory");
+ return 1;
+ }
+
+ irp->scard_index = g_scard_index;
+ irp->CompletionId = g_completion_id++;
+ irp->DeviceId = g_device_id;
+ irp->callback = scard_handle_Connect_Return;
+ irp->user_data = con;
+
+ /* send IRP to client */
+ scard_send_Connect(irp, context, wide, rs);
+
+ return 0;
+}
+
+/**
+ * The reconnect method re-establishes a smart card reader handle. On success,
+ * the handle is valid once again.
+ *
+ * @param con connection to client
+ * @param sc_handle handle to device
+ * @param rs reader state where following fields are set
+ * rs.shared_mode_flag
+ * rs.preferred_protocol
+ * rs.init_type
+ *****************************************************************************/
+int APP_CC
+scard_send_reconnect(struct trans *con, tui32 context, tui32 sc_handle,
+ READER_STATE* rs)
{
- tui32 len;
- int tmp;
- SMARTCARD *sc;
+ IRP *irp;
- log_debug("entered");
+ /* setup up IRP */
+ if ((irp = devredir_irp_new()) == NULL)
+ {
+ log_error("system out of memory");
+ return 1;
+ }
- /* sanity check */
- if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId))
+ irp->scard_index = g_scard_index;
+ irp->CompletionId = g_completion_id++;
+ irp->DeviceId = g_device_id;
+ irp->callback = scard_handle_Reconnect_Return;
+ irp->user_data = con;
+
+ /* send IRP to client */
+ scard_send_Reconnect(irp, context, sc_handle, rs);
+
+ return 0;
+}
+
+/**
+ * Lock smart card reader for exclusive access for specified smart
+ * card reader handle.
+ *
+ * @param con connection to client
+ *****************************************************************************/
+int APP_CC
+scard_send_begin_transaction(struct trans *con, tui32 sc_handle)
+{
+ IRP *irp;
+
+ /* setup up IRP */
+ if ((irp = devredir_irp_new()) == NULL)
{
- log_error("DeviceId/CompletionId do not match those in IRP");
- return;
+ log_error("system out of memory");
+ return 1;
}
- if (IoStatus != 0)
+ irp->scard_index = g_scard_index;
+ irp->CompletionId = g_completion_id++;
+ irp->DeviceId = g_device_id;
+ irp->callback = scard_handle_BeginTransaction_Return;
+ irp->user_data = con;
+
+ /* send IRP to client */
+ scard_send_BeginTransaction(irp, sc_handle);
+
+ return 0;
+}
+
+/**
+ * Release a smart card reader after being locked by a previously
+ * successful call to Begin Transaction
+ *
+ * @param con connection to client
+ * @param sc_handle handle to smartcard
+ *****************************************************************************/
+int APP_CC
+scard_send_end_transaction(struct trans *con, tui32 sc_handle,
+ tui32 dwDisposition)
+{
+ IRP *irp;
+
+ /* setup up IRP */
+ if ((irp = devredir_irp_new()) == NULL)
{
- log_error("failed to establish context - device not usable");
- /* LK_TODO delete irp and smartcard entry */
- return;
+ log_error("system out of memory");
+ return 1;
}
- sc = smartcards[irp->scard_index];
+ irp->scard_index = g_scard_index;
+ irp->CompletionId = g_completion_id++;
+ irp->DeviceId = g_device_id;
+ irp->callback = scard_handle_EndTransaction_Return;
+ irp->user_data = con;
- /* get OutputBufferLen */
- xstream_rd_u32_le(s, len);
+ /* send IRP to client */
+ scard_send_EndTransaction(irp, sc_handle, dwDisposition);
- /* LK_TODO */
- g_hexdump(s->p, len);
+ return 0;
+}
- xstream_rd_u32_le(s, tmp); /* should be len 8, LE, V1 */
- xstream_rd_u32_le(s, tmp); /* marshalling flag */
- xstream_rd_u32_le(s, tmp); /* ?? */
- xstream_rd_u32_le(s, tmp); /* ?? */
- xstream_rd_u32_le(s, tmp); /* ?? */
- xstream_rd_u32_le(s, tmp); /* ?? */
- xstream_rd_u32_le(s, tmp); /* ?? */
- xstream_rd_u32_le(s, len); /* len of context in bytes */
- sc->Context_len = len;
- xstream_copyout(sc->Context, s, len);
+/**
+ * Get the status of a connection for a valid smart card reader handle
+ *
+ * @param con connection to client
+ * @param wide TRUE if unicode string
+ *****************************************************************************/
+int APP_CC
+scard_send_status(struct trans *con, int wide, tui32 sc_handle,
+ int cchReaderLen, int cbAtrLen)
+{
+ IRP *irp;
- if (LOG_LEVEL == LOG_DEBUG)
+ /* setup up IRP */
+ if ((irp = devredir_irp_new()) == NULL)
{
- log_debug("dumping context (%d bytes)", sc->Context_len);
- g_hexdump(sc->Context, sc->Context_len);
+ log_error("system out of memory");
+ return 1;
}
- irp->callback = scard_handle_ListReaders_Return;
- scard_send_ListReaders(irp, 1);
+ irp->scard_index = g_scard_index;
+ irp->CompletionId = g_completion_id++;
+ irp->DeviceId = g_device_id;
+ irp->callback = scard_handle_Status_Return;
+ irp->user_data = con;
- /* LK_TODO need to delete IRP */
- log_debug("leaving");
+ /* send IRP to client */
+ scard_send_Status(irp, wide, sc_handle, cchReaderLen, cbAtrLen);
+
+ return 0;
}
-void APP_CC
-scard_handle_ListReaders_Return(struct stream *s, IRP *irp,
- tui32 DeviceId, tui32 CompletionId,
- tui32 IoStatus)
+/**
+ * Release a smart card reader handle that was acquired in ConnectA/ConnectW
+ *
+ * @param con connection to client
+ * @param sc_handle handle to smartcard
+ *****************************************************************************/
+int APP_CC
+scard_send_disconnect(struct trans *con, tui32 context, tui32 sc_handle,
+ int dwDisposition)
{
- tui32 len;
+ IRP *irp;
- log_debug("entered");
+ /* setup up IRP */
+ if ((irp = devredir_irp_new()) == NULL)
+ {
+ log_error("system out of memory");
+ return 1;
+ }
- /* sanity check */
- if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId))
+ irp->scard_index = g_scard_index;
+ irp->CompletionId = g_completion_id++;
+ irp->DeviceId = g_device_id;
+ irp->callback = scard_handle_Disconnect_Return;
+ irp->user_data = con;
+
+ /* send IRP to client */
+ scard_send_Disconnect(irp, context, sc_handle, dwDisposition);
+
+ return 0;
+}
+
+/**
+ * The Transmit_Call structure is used to send data to the smart card
+ * associated with a valid context.
+ *****************************************************************************/
+int APP_CC
+scard_send_transmit(struct trans *con, tui32 sc_handle,
+ char *send_data, int send_bytes, int recv_bytes,
+ struct xrdp_scard_io_request *send_ior,
+ struct xrdp_scard_io_request *recv_ior)
+{
+ IRP *irp;
+
+ /* setup up IRP */
+ if ((irp = devredir_irp_new()) == NULL)
{
- log_error("DeviceId/CompletionId do not match those in IRP");
- return;
+ log_error("system out of memory");
+ return 1;
}
- if (IoStatus != 0)
+ irp->scard_index = g_scard_index;
+ irp->CompletionId = g_completion_id++;
+ irp->DeviceId = g_device_id;
+ irp->callback = scard_handle_Transmit_Return;
+ irp->user_data = con;
+
+ /* send IRP to client */
+ scard_send_Transmit(irp, sc_handle, send_data, send_bytes, recv_bytes,
+ send_ior, recv_ior);
+
+ return 0;
+}
+
+/**
+ * Communicate directly with the smart card reader
+ *****************************************************************************/
+int APP_CC
+scard_send_control(struct trans *con, tui32 context, tui32 sc_handle,
+ char *send_data, int send_bytes,
+ int recv_bytes, int control_code)
+{
+ IRP *irp;
+
+ /* setup up IRP */
+ if ((irp = devredir_irp_new()) == NULL)
{
- log_error("failed to list readers - device not usable");
- /* LK_TODO delete irp and smartcard entry */
- return;
+ log_error("system out of memory");
+ return 1;
}
- /* get OutputBufferLen */
- xstream_rd_u32_le(s, len);
+ irp->scard_index = g_scard_index;
+ irp->CompletionId = g_completion_id++;
+ irp->DeviceId = g_device_id;
+ irp->callback = scard_handle_Control_Return;
+ irp->user_data = con;
- /* LK_TODO */
- log_debug("dumping %d bytes", len);
- g_hexdump(s->p, len);
+ /* send IRP to client */
+ scard_send_Control(irp, context, sc_handle, send_data,
+ send_bytes, recv_bytes, control_code);
- log_debug("leaving");
+ return 0;
+}
+
+/**
+ * Cancel any outstanding calls
+ *****************************************************************************/
+int APP_CC
+scard_send_cancel(struct trans *con, tui32 context)
+{
+ IRP *irp;
+
+ /* setup up IRP */
+ if ((irp = devredir_irp_new()) == NULL)
+ {
+ log_error("system out of memory");
+ return 1;
+ }
+
+ irp->scard_index = g_scard_index;
+ irp->CompletionId = g_completion_id++;
+ irp->DeviceId = g_device_id;
+ irp->callback = scard_handle_Cancel_Return;
+ irp->user_data = con;
+
+ /* send IRP to client */
+ scard_send_Cancel(irp, context);
+
+ return 0;
+}
+
+/**
+ * Get reader attributes
+ *****************************************************************************/
+int APP_CC
+scard_send_get_attrib(struct trans *con, tui32 sc_handle, READER_STATE* rs)
+{
+ IRP *irp;
+
+ /* setup up IRP */
+ if ((irp = devredir_irp_new()) == NULL)
+ {
+ log_error("system out of memory");
+ return 1;
+ }
+
+ irp->scard_index = g_scard_index;
+ irp->CompletionId = g_completion_id++;
+ irp->DeviceId = g_device_id;
+ irp->callback = scard_handle_GetAttrib_Return;
+ irp->user_data = con;
+
+ /* send IRP to client */
+ scard_send_GetAttrib(irp, sc_handle, rs);
+
+ return 0;
}
/******************************************************************************
+** **
** static functions local to this file **
+** **
******************************************************************************/
/**
+ * Crate a new stream and insert specified IOCTL
+ *
+ * @param irp information about the I/O
+ * @param ioctl the IOCTL code
*
+ * @return stream with IOCTL inserted in it, NULL on error
*****************************************************************************/
+static struct stream * APP_CC
+scard_make_new_ioctl(IRP *irp, tui32 ioctl)
+{
+ /*
+ * format of device control request
+ *
+ * DeviceIoRequest
+ * u16 RDPDR_CTYP_CORE
+ * u16 PAKID_CORE_DEVICE_IOREQUEST
+ * u32 DeviceId
+ * u32 FileId
+ * u32 CompletionId
+ * u32 MajorFunction
+ * u32 MinorFunction
+ *
+ * u32 OutputBufferLength SHOULD be 2048
+ * u32 InputBufferLength
+ * u32 IoControlCode
+ * 20 bytes padding
+ * xx bytes InputBuffer (variable)
+ */
+
+ struct stream *s;
+
+ xstream_new(s, 1024 * 4);
+ if (s == NULL)
+ {
+ log_error("system out of memory");
+ return s;
+ }
+
+ devredir_insert_DeviceIoRequest(s,
+ irp->DeviceId,
+ irp->FileId,
+ irp->CompletionId,
+ IRP_MJ_DEVICE_CONTROL,
+ 0);
+
+ xstream_wr_u32_le(s, 2048); /* OutputBufferLength */
+ xstream_wr_u32_le(s, 0); /* InputBufferLength - insert later */
+ xstream_wr_u32_le(s, ioctl); /* Ioctl Code */
+ xstream_seek(s, 20); /* padding */
+
+ /* [MS-RPCE] 2.2.6.1 */
+ xstream_wr_u32_le(s, 0x00081001); /* len 8, LE, v1 */
+ xstream_wr_u32_le(s, 0xcccccccc); /* filler */
+
+ return s;
+}
+
+/**
+ * Create a new smart card device entry and insert it into smartcards[]
+ *
+ * @param device_id DeviceId of new card
+ *
+ * @return index into smartcards[] on success, -1 on failure
+ *****************************************************************************/
+static int APP_CC
+scard_add_new_device(tui32 device_id)
+{
+ int index;
+ SMARTCARD *sc;
+
+ if ((index = scard_get_free_slot()) < 0)
+ {
+ log_error("scard_get_free_slot failed");
+ return -1;
+ }
+
+ if ((sc = g_malloc(sizeof(SMARTCARD), 1)) == NULL)
+ {
+ log_error("system out of memory");
+ return -1;
+ }
+
+ sc->DeviceId = device_id;
+ smartcards[index] = sc;
+
+ return index;
+}
+
+/**
+ * Find first unused entry in smartcards
+ *
+ * @return index of first unused entry in smartcards or -1 if smartcards
+ * is full
+ *****************************************************************************/
+static int APP_CC
+scard_get_free_slot(void)
+{
+ int i;
+
+ for (i = 0; i < MAX_SMARTCARDS; i++)
+ {
+ if (smartcards[i] == NULL)
+ {
+ log_debug("found free slot at index %d", i);
+ return i;
+ }
+ }
+
+ log_error("too many smart card devices; rejecting this one");
+ return -1;
+}
+
+#if 0
+/**
+ * Release resources prior to shutting down
+ *****************************************************************************/
+static void APP_CC
+scard_release_resources(void)
+{
+ int i;
+
+ for (i = 0; i < MAX_SMARTCARDS; i++)
+ {
+ if (smartcards[i] != NULL)
+ {
+ g_free(smartcards[i]);
+ smartcards[i] = NULL;
+ }
+ }
+}
+#endif
+/**
+ *
+ *****************************************************************************/
static void APP_CC
-scard_send_EstablishContext(IRP *irp)
+scard_send_EstablishContext(IRP *irp, int scope)
{
struct stream *s;
int bytes;
if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_ESTABLISH_CONTEXT)) == NULL)
+ {
+ log_error("scard_make_new_ioctl failed");
return;
+ }
- xstream_wr_u32_le(s, 0x08); /* len */
- xstream_wr_u32_le(s, 0); /* unused */
- xstream_wr_u32_le(s, SCARD_SCOPE_SYSTEM); /* Ioctl specific data */
- xstream_wr_u32_le(s, 0); /* don't know what this is, */
- /* but Win7 is sending it */
+ xstream_wr_u32_le(s, 0x08); /* len */
+ xstream_wr_u32_le(s, 0); /* unused */
+ xstream_wr_u32_le(s, scope); /* Ioctl specific data */
+ xstream_wr_u32_le(s, 0); /* don't know what this is, */
+ /* but Win7 is sending it */
/* get stream len */
bytes = xstream_len(s);
- /* InputBufferLength is number of bytes AFTER 20 byte padding */
+ /* InputBufferLength is number of bytes AFTER 20 byte padding */
*(s->data + 28) = bytes - 56;
/* send to client */
@@ -313,11 +949,112 @@ scard_send_EstablishContext(IRP *irp)
}
/**
- *
+ * Release a previously established Smart Card context
*****************************************************************************/
+static void APP_CC
+scard_send_ReleaseContext(IRP* irp, tui32 context)
+{
+ /* see [MS-RDPESC] 3.1.4.2 */
+
+ SMARTCARD* sc;
+ struct stream* s;
+ int bytes;
+
+ if ((sc = smartcards[irp->scard_index]) == NULL)
+ {
+ log_error("smartcards[%d] is NULL", irp->scard_index);
+ return;
+ }
+ if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_RELEASE_CONTEXT)) == NULL)
+ return;
+
+ /*
+ * command format
+ *
+ * ......
+ * 20 bytes padding
+ * u32 4 bytes len 8, LE, v1
+ * u32 4 bytes filler
+ * 4 bytes len - don't know what this is, zero for now
+ * 12 bytes unused
+ * u32 4 bytes context len
+ * 4 bytes context
+ */
+
+ xstream_wr_u32_le(s, 0);
+ xstream_seek(s, 12);
+
+ /* insert context */
+ xstream_wr_u32_le(s, 4);
+ xstream_wr_u32_le(s, context);
+
+ /* get stream len */
+ bytes = xstream_len(s);
+
+ /* InputBufferLength is number of bytes AFTER 20 byte padding */
+ *(s->data + 28) = bytes - 56;
+
+ /* send to client */
+ send_channel_data(g_rdpdr_chan_id, s->data, bytes);
+ xstream_free(s);
+}
+
+/**
+ * Checks if a previously established context is still valid
+ *****************************************************************************/
static void APP_CC
-scard_send_ListReaders(IRP *irp, int wide)
+scard_send_IsContextValid(IRP* irp, tui32 context)
+{
+ /* see [MS-RDPESC] 3.1.4.3 */
+
+ SMARTCARD* sc;
+ struct stream* s;
+ int bytes;
+
+ if ((sc = smartcards[irp->scard_index]) == NULL)
+ {
+ log_error("smartcards[%d] is NULL", irp->scard_index);
+ return;
+ }
+
+ if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_IS_VALID_CONTEXT)) == NULL)
+ return;
+
+ /*
+ * command format
+ *
+ * ......
+ * 20 bytes padding
+ * u32 4 bytes len 8, LE, v1
+ * u32 4 bytes filler
+ * 16 bytes unused (s->p currently pointed here at unused[0])
+ * u32 4 bytes context len
+ * u32 4 bytes context
+ */
+
+ xstream_wr_u32_le(s, 16);
+
+ /* insert context */
+ xstream_wr_u32_le(s, 4);
+ xstream_wr_u32_le(s, context);
+
+ /* get stream len */
+ bytes = xstream_len(s);
+
+ /* InputBufferLength is number of bytes AFTER 20 byte padding */
+ *(s->data + 28) = bytes - 56;
+
+ /* send to client */
+ send_channel_data(g_rdpdr_chan_id, s->data, bytes);
+ xstream_free(s);
+}
+
+/**
+ *
+ *****************************************************************************/
+static void APP_CC
+scard_send_ListReaders(IRP *irp, tui32 context, int wide)
{
/* see [MS-RDPESC] 2.2.2.4 */
@@ -332,18 +1069,18 @@ scard_send_ListReaders(IRP *irp, int wide)
return;
}
- ioctl = (wide > 0) ? SCARD_IOCTL_LIST_READERS_W :
- SCARD_IOCTL_LIST_READERS_A;
+ ioctl = (wide) ? SCARD_IOCTL_LIST_READERS_W :
+ SCARD_IOCTL_LIST_READERS_A;
if ((s = scard_make_new_ioctl(irp, ioctl)) == NULL)
return;
xstream_wr_u32_le(s, 72); /* number of bytes to follow */
- xstream_seek(s, 0x1c); /* freerdp does not use this */
+ xstream_seek(s, 28); /* freerdp does not use this */
/* insert context */
- xstream_wr_u32_le(s, sc->Context_len);
- xstream_copyin(s, sc->Context, sc->Context_len);
+ xstream_wr_u32_le(s, 4);
+ xstream_wr_u32_le(s, context);
xstream_wr_u32_le(s, 36); /* length of mszGroups */
xstream_wr_u16_le(s, 0x0053);
@@ -389,185 +1126,1361 @@ scard_send_ListReaders(IRP *irp, int wide)
*/
/*
- scard_device_control: dumping 120 bytes of data
- 0000 00 08 00 00 80 00 00 00 14 00 09 00 00 00 00 00 ................
- 0010 2e 2e 00 00 00 00 00 00 02 00 00 00 00 00 00 00 ................
- 0020 01 10 08 00 cc cc cc cc 48 00 00 00 00 00 00 00 ........H.......
- 0030 02 00 00 00 00 00 00 00 72 64 00 00 00 00 00 00 ........rd......
- 0040 81 27 00 00 00 00 00 00 04 00 00 00 84 b3 03 01 .'..............
- 0050 24 00 00 00 53 00 43 00 61 00 72 00 64 00 24 00 $...S.C.a.r.d.$.
- 0060 41 00 6c 00 6c 00 52 00 65 00 61 00 64 00 65 00 A.l.l.R.e.a.d.e.
- 0070 72 00 73 00 00 00 00 00 r.s.....
- scard_device_control: output_len=2048 input_len=128 ioctl_code=0x90014
+ scard_device_control: dumping 120 bytes of data
+ 0000 00 08 00 00 80 00 00 00 14 00 09 00 00 00 00 00 ................
+ 0010 2e 2e 00 00 00 00 00 00 02 00 00 00 00 00 00 00 ................
+ 0020 01 10 08 00 cc cc cc cc 48 00 00 00 00 00 00 00 ........H.......
+ 0030 02 00 00 00 00 00 00 00 72 64 00 00 00 00 00 00 ........rd......
+ 0040 81 27 00 00 00 00 00 00 04 00 00 00 84 b3 03 01 .'..............
+ 0050 24 00 00 00 53 00 43 00 61 00 72 00 64 00 24 00 $...S.C.a.r.d.$.
+ 0060 41 00 6c 00 6c 00 52 00 65 00 61 00 64 00 65 00 A.l.l.R.e.a.d.e.
+ 0070 72 00 73 00 00 00 00 00 r.s.....
+ scard_device_control: output_len=2048 input_len=128 ioctl_code=0x90014
*/
}
+/*****************************************************************************/
+static int
+align_s(struct stream *s, int bytes)
+{
+ int i32;
+
+ i32 = (int) (s->p - s->data);
+ while ((i32 % bytes) != 0)
+ {
+ out_uint8s(s, 1);
+ i32 = (int) (s->p - s->data);
+ }
+ return 0;
+}
+
/**
- * Crate a new stream and insert specified IOCTL
- *
- * @param irp information about the I/O
- * @param ioctl the IOCTL code
+ * Get change in status
*
- * @return stream with IOCTL inserted in it, NULL on error
+ * @param irp I/O resource pkt
+ * @param wide TRUE if unicode string
+ * @param timeout timeout in milliseconds, -1 for infinity
+ * @param num_readers number of entries in rsa
+ * @param rsa array of READER_STATEs
*****************************************************************************/
+static void APP_CC
+scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, tui32 timeout,
+ tui32 num_readers, READER_STATE* rsa)
+{
+ /* see [MS-RDPESC] 2.2.2.11 for ASCII */
+ /* see [MS-RDPESC] 2.2.2.12 for Wide char */
-static struct stream * APP_CC
-scard_make_new_ioctl(IRP *irp, tui32 ioctl)
+ SMARTCARD* sc;
+ READER_STATE* rs;
+ struct stream* s;
+ tui32 ioctl;
+ int bytes;
+ int i;
+ int num_chars;
+ int index;
+ twchar w_reader_name[100];
+
+ if ((sc = smartcards[irp->scard_index]) == NULL)
+ {
+ log_error("smartcards[%d] is NULL", irp->scard_index);
+ return;
+ }
+
+ ioctl = (wide) ? SCARD_IOCTL_GET_STATUS_CHANGE_W :
+ SCARD_IOCTL_GET_STATUS_CHANGE_A;
+
+ if ((s = scard_make_new_ioctl(irp, ioctl)) == NULL)
+ return;
+
+ xstream_seek(s, 16); /* unused */
+ xstream_wr_u32_le(s, timeout);
+ xstream_wr_u32_le(s, num_readers);
+ xstream_wr_u32_le(s, 0); /* unused */
+
+ /* insert context */
+ xstream_wr_u32_le(s, 4);
+ xstream_wr_u32_le(s, context);
+
+ xstream_wr_u32_le(s, 0); /* unused */
+
+ /* insert card reader state */
+ for (i = 0; i < num_readers; i++)
+ {
+ rs = &rsa[i];
+ xstream_wr_u32_le(s, 0); /* unused */
+ xstream_wr_u32_le(s, rs->current_state);
+ xstream_wr_u32_le(s, rs->event_state);
+ xstream_wr_u32_le(s, rs->atr_len);
+ xstream_copyin(s, rs->atr, 33);
+ out_uint8s(s, 3);
+ }
+
+ if (wide)
+ {
+ /* insert card reader names */
+ for (i = 0; i < num_readers; i++)
+ {
+ rs = &rsa[i];
+ num_chars = g_mbstowcs(w_reader_name, rs->reader_name, 99);
+ xstream_wr_u32_le(s, 0); /* unused */
+ xstream_wr_u32_le(s, 0); /* unused */
+ xstream_wr_u32_le(s, num_chars);
+ for (index = 0; index < num_chars; index++)
+ {
+ xstream_wr_u16_le(s, w_reader_name[index]);
+ }
+ align_s(s, 4);
+ }
+ }
+ else
+ {
+ /* insert card reader names */
+ for (i = 0; i < num_readers; i++)
+ {
+ rs = &rsa[i];
+ num_chars = g_mbstowcs(w_reader_name, rs->reader_name, 99);
+ xstream_wr_u32_le(s, 0); /* unused */
+ xstream_wr_u32_le(s, 0); /* unused */
+ xstream_wr_u32_le(s, num_chars);
+ for (index = 0; index < num_chars; index++)
+ {
+ xstream_wr_u8(s, w_reader_name[index]);
+ }
+ align_s(s, 4);
+ }
+ }
+
+ /* get stream len */
+ bytes = xstream_len(s);
+
+ /* InputBufferLength is number of bytes AFTER 20 byte padding */
+ *(s->data + 28) = bytes - 56;
+
+ /* send to client */
+ send_channel_data(g_rdpdr_chan_id, s->data, bytes);
+ xstream_free(s);
+}
+
+/**
+ * Send connect command
+ *
+ * @param irp I/O resource pkt
+ * @param wide TRUE if unicode string
+ * @param rs reader state
+ *****************************************************************************/
+static void APP_CC
+scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs)
{
+ /* see [MS-RDPESC] 2.2.2.13 for ASCII */
+ /* see [MS-RDPESC] 2.2.2.14 for Wide char */
+
+ SMARTCARD* sc;
+ struct stream* s;
+ tui32 ioctl;
+ int bytes;
+ int num_chars;
+ int index;
+ twchar w_reader_name[100];
+
+ if ((sc = smartcards[irp->scard_index]) == NULL)
+ {
+ log_error("smartcards[%d] is NULL", irp->scard_index);
+ return;
+ }
+
+ ioctl = (wide) ? SCARD_IOCTL_CONNECT_W :
+ SCARD_IOCTL_CONNECT_A;
+
+ if ((s = scard_make_new_ioctl(irp, ioctl)) == NULL)
+ return;
+
/*
- * format of device control request
+ * command format
*
- * DeviceIoRequest
- * u16 RDPDR_CTYP_CORE
- * u16 PAKID_CORE_DEVICE_IOREQUEST
- * u32 DeviceId
- * u32 FileId
- * u32 CompletionId
- * u32 MajorFunction
- * u32 MinorFunction
+ * ......
+ * 20 bytes padding
+ * u32 4 bytes len 8, LE, v1
+ * u32 4 bytes filler
+ * 20 bytes unused (s->p currently pointed here at unused[0])
+ * u32 4 bytes dwShareMode
+ * u32 4 bytes dwPreferredProtocols
+ * xx bytes reader name
+ * u32 4 bytes context length (len)
+ * len bytes context
+ */
+
+ xstream_seek(s, 20);
+ xstream_wr_u32_le(s, rs->dwShareMode);
+ xstream_wr_u32_le(s, rs->dwPreferredProtocols);
+
+ /* insert reader name */
+ num_chars = g_mbstowcs(w_reader_name, rs->reader_name, 99);
+ xstream_wr_u32_le(s, 0);
+ xstream_wr_u32_le(s, 0);
+ xstream_wr_u32_le(s, num_chars);
+ if (wide)
+ {
+ for (index = 0; index < num_chars; index++)
+ {
+ xstream_wr_u16_le(s, w_reader_name[index]);
+ }
+ }
+ else
+ {
+ for (index = 0; index < num_chars; index++)
+ {
+ xstream_wr_u8(s, w_reader_name[index]);
+ }
+ }
+ align_s(s, 4);
+
+ /* insert context */
+ xstream_wr_u32_le(s, 4);
+ xstream_wr_u32_le(s, context);
+
+ /* get stream len */
+ bytes = xstream_len(s);
+
+ /* InputBufferLength is number of bytes AFTER 20 byte padding */
+ *(s->data + 28) = bytes - 56;
+
+ /* send to client */
+ send_channel_data(g_rdpdr_chan_id, s->data, bytes);
+ xstream_free(s);
+}
+
+/**
+ * The reconnect method re-establishes a smart card reader handle. On success,
+ * the handle is valid once again.
+ *
+ * @param con connection to client
+ * @param sc_handle handle to device
+ * @param rs reader state where following fields are set
+ * rs.shared_mode_flag
+ * rs.preferred_protocol
+ * rs.init_type
+ *****************************************************************************/
+static void APP_CC
+scard_send_Reconnect(IRP* irp, tui32 context, tui32 sc_handle, READER_STATE* rs)
+{
+ /* see [MS-RDPESC] 2.2.2.15 */
+ /* see [MS-RDPESC] 3.1.4.36 */
+
+ SMARTCARD* sc;
+ struct stream* s;
+ int bytes;
+
+ if ((sc = smartcards[irp->scard_index]) == NULL)
+ {
+ log_error("smartcards[%d] is NULL", irp->scard_index);
+ return;
+ }
+
+ if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_RECONNECT)) == NULL)
+ return;
+
+ /*
+ * command format
*
- * u32 OutputBufferLength SHOULD be 2048
- * u32 InputBufferLength
- * u32 IoControlCode
- * 20 bytes padding
- * xx bytes InputBuffer (variable)
+ * ......
+ * 20 bytes padding
+ * u32 4 bytes len 8, LE, v1
+ * u32 4 bytes filler
+ * 24 bytes unused (s->p currently pointed here at unused[0])
+ * u32 4 bytes dwShareMode
+ * u32 4 bytes dwPreferredProtocols
+ * u32 4 bytes dwInitialization
+ * u32 4 bytes context length
+ * u32 4 bytes context
+ * u32 4 bytes handle length
+ * u32 4 bytes handle
*/
+ xstream_seek(s, 24);
+ xstream_wr_u32_le(s, rs->dwShareMode);
+ xstream_wr_u32_le(s, rs->dwPreferredProtocols);
+ xstream_wr_u32_le(s, rs->init_type);
+ xstream_wr_u32_le(s, 4);
+ xstream_wr_u32_le(s, context);
+ xstream_wr_u32_le(s, 4);
+ xstream_wr_u32_le(s, sc_handle);
+
+ /* get stream len */
+ bytes = xstream_len(s);
+
+ /* InputBufferLength is number of bytes AFTER 20 byte padding */
+ *(s->data + 28) = bytes - 56;
+
+ /* send to client */
+ send_channel_data(g_rdpdr_chan_id, s->data, bytes);
+ xstream_free(s);
+}
+
+/**
+ * Lock smart card reader for exclusive access for specified smart
+ * card reader handle.
+ *
+ * @param con connection to client
+ *****************************************************************************/
+static void APP_CC
+scard_send_BeginTransaction(IRP *irp, tui32 sc_handle)
+{
+ /* see [MS-RDPESC] 4.9 */
+
+ SMARTCARD *sc;
struct stream *s;
+ int bytes;
- xstream_new(s, 1024 * 3);
- if (s == NULL)
+ if ((sc = smartcards[irp->scard_index]) == NULL)
{
- log_error("system out of memory");
- return s;
+ log_error("smartcards[%d] is NULL", irp->scard_index);
+ return;
}
- devredir_insert_DeviceIoRequest(s,
- irp->DeviceId,
- irp->FileId,
- irp->CompletionId,
- IRP_MJ_DEVICE_CONTROL,
- 0);
+ if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_BEGIN_TRANSACTION)) == NULL)
+ return;
- xstream_wr_u32_le(s, 2048); /* OutputBufferLength */
- xstream_wr_u32_le(s, 0); /* InputBufferLength - insert later */
- xstream_wr_u32_le(s, ioctl); /* Ioctl Code */
- xstream_seek(s, 20); /* padding */
+ /*
+ * command format
+ *
+ * ......
+ * 20 bytes padding
+ * u32 4 bytes len 8, LE, v1
+ * u32 4 bytes filler
+ * 36 bytes unused (s->p currently pointed here at unused[0])
+ * u32 4 bytes len of sc_handle
+ * 4 bytes sc_handle
+ */
- /* [MS-RPCE] 2.2.6.1 */
- xstream_wr_u32_le(s, 0x00081001); /* len 8, LE, v1 */
- xstream_wr_u32_le(s, 0xcccccccc); /* filler */
+ xstream_seek(s, 36);
- return s;
+ /* insert handle */
+ xstream_wr_u32_le(s, 4);
+ xstream_wr_u32_le(s, sc_handle);
+
+ /* get stream len */
+ bytes = xstream_len(s);
+
+ /* InputBufferLength is number of bytes AFTER 20 byte padding */
+ *(s->data + 28) = bytes - 56;
+
+ /* send to client */
+ send_channel_data(g_rdpdr_chan_id, s->data, bytes);
+ xstream_free(s);
}
/**
- * Create a new smart card device entry and insert it into smartcards[]
+ * Release a smart card reader after being locked by a previously
+ * successful call to Begin Transaction
*
- * @param device_id DeviceId of new card
- *
- * @return index into smartcards[] on success, -1 on failure
+ * @param con connection to client
+ * @param sc_handle handle to smartcard
*****************************************************************************/
+static void APP_CC
+scard_send_EndTransaction(IRP *irp, tui32 sc_handle, tui32 dwDisposition)
+{
+ /* see [MS-RDPESC] 3.1.4.32 */
-static int APP_CC
-scard_add_new_device(tui32 device_id)
+ SMARTCARD *sc;
+ struct stream *s;
+ int bytes;
+
+ if ((sc = smartcards[irp->scard_index]) == NULL)
+ {
+ log_error("smartcards[%d] is NULL", irp->scard_index);
+ return;
+ }
+
+ if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_END_TRANSACTION)) == NULL)
+ return;
+
+ /*
+ * command format
+ *
+ * ......
+ * 20 bytes padding
+ * u32 4 bytes len 8, LE, v1
+ * u32 4 bytes filler
+ * 24 bytes unused (s->p currently pointed here at unused[0])
+ * u32 4 bytes disposition
+ * 8 unused
+ * u32 4 bytes length of sc_handle
+ * 4 bytes sc_handle
+ */
+
+ xstream_seek(s, 24);
+ xstream_wr_u32_le(s, dwDisposition);
+ xstream_seek(s, 8);
+
+ /* insert handle */
+ xstream_wr_u32_le(s, 4);
+ xstream_wr_u32_le(s, sc_handle);
+
+ /* get stream len */
+ bytes = xstream_len(s);
+
+ /* InputBufferLength is number of bytes AFTER 20 byte padding */
+ *(s->data + 28) = bytes - 56;
+
+ /* send to client */
+ send_channel_data(g_rdpdr_chan_id, s->data, bytes);
+ xstream_free(s);
+}
+
+/**
+ * Get the status of a connection for a valid smart card reader handle
+ *
+ * @param con connection to client
+ * @param wide TRUE if unicode string
+ *****************************************************************************/
+static void APP_CC
+scard_send_Status(IRP *irp, int wide, tui32 sc_handle,
+ int cchReaderLen, int cbAtrLen)
{
- int index;
- SMARTCARD *sc;
+ /* see [MS-RDPESC] 2.2.2.18 */
- if ((index = scard_get_free_slot()) < 0)
- return -1;
+ SMARTCARD *sc;
+ struct stream *s;
+ int bytes;
+ tui32 ioctl;
- if ((sc = g_malloc(sizeof(SMARTCARD), 1)) == NULL)
+ if ((sc = smartcards[irp->scard_index]) == NULL)
{
- log_error("system out of memory");
- return -1;
+ log_error("smartcards[%d] is NULL", irp->scard_index);
+ return;
}
- sc->DeviceId = device_id;
- smartcards[index] = sc;
+ ioctl = wide ? SCARD_IOCTL_STATUS_W : SCARD_IOCTL_STATUS_A;
+ if ((s = scard_make_new_ioctl(irp, ioctl)) == NULL)
+ {
+ log_error("scard_make_new_ioctl");
+ return;
+ }
- return index;
+ /*
+ * command format
+ *
+ * ......
+ * 20 bytes padding
+ * u32 4 bytes len 8, LE, v1
+ * u32 4 bytes filler
+ * 28 bytes unused (s->p currently pointed here at unused[0])
+ * u32 4 bytes reader len
+ * u32 4 bytes ATR len
+ * 8 bytes unused
+ * u32 4 bytes len of sc_handle
+ * 4 bytes sc_handle
+ * 4 bytes unused
+ */
+
+ xstream_seek(s, 28);
+ xstream_wr_u32_le(s, cchReaderLen); /* readerLen, see [MS-RDPESC] 4.11 */
+ xstream_wr_u32_le(s, cbAtrLen); /* atrLen, see [MS-RDPESC] 4.11 */
+ xstream_seek(s, 8);
+
+ /* insert sc_handle */
+ xstream_wr_u32_le(s, 4);
+ xstream_wr_u32_le(s, sc_handle);
+
+ xstream_wr_u32_le(s, 0);
+
+ /* get stream len */
+ bytes = xstream_len(s);
+
+ /* InputBufferLength is number of bytes AFTER 20 byte padding */
+ *(s->data + 28) = bytes - 56;
+
+ /* send to client */
+ send_channel_data(g_rdpdr_chan_id, s->data, bytes);
+ xstream_free(s);
}
/**
- * Find first unused entry in smartcards
+ * Release a smart card reader handle that was acquired in ConnectA/ConnectW
*
- * @return index of first unused entry in smartcards or -1 if smartcards
- * is full
+ * @param con connection to client
+ * @param sc_handle handle to smartcard
*****************************************************************************/
+static void APP_CC
+scard_send_Disconnect(IRP *irp, tui32 context, tui32 sc_handle,
+ int dwDisposition)
+{
+ /* see [MS-RDPESC] 3.1.4.30 */
+ SMARTCARD* sc;
+ struct stream* s;
+ int bytes;
+
+ if ((sc = smartcards[irp->scard_index]) == NULL)
+ {
+ log_error("smartcards[%d] is NULL", irp->scard_index);
+ return;
+ }
+
+ if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_DISCONNECT)) == NULL)
+ return;
+
+ /*
+ * command format
+ *
+ * ......
+ * 20 bytes padding
+ * u32 4 bytes len 8, LE, v1
+ * u32 4 bytes filler
+ * 24 bytes unused (s->p currently pointed here at unused[0])
+ * u32 4 bytes disposition
+ * u32 4 bytes context len
+ * 4 bytes context
+ * u32 4 bytes length of sc_handle
+ * 4 bytes sc_handle
+ */
+
+ xstream_seek(s, 24);
+ xstream_wr_u32_le(s, dwDisposition);
+
+ /* insert context */
+ xstream_wr_u32_le(s, 4);
+ xstream_wr_u32_le(s, context);
+
+ /* insert handle */
+ xstream_wr_u32_le(s, 4);
+ xstream_wr_u32_le(s, sc_handle);
+
+ /* get stream len */
+ bytes = xstream_len(s);
+
+ /* InputBufferLength is number of bytes AFTER 20 byte padding */
+ *(s->data + 28) = bytes - 56;
+
+ /* send to client */
+ send_channel_data(g_rdpdr_chan_id, s->data, bytes);
+ xstream_free(s);
+}
+
+/**
+ * The Transmit_Call structure is used to send data to the smart card
+ * associated with a valid context.
+ *****************************************************************************/
static int APP_CC
-scard_get_free_slot(void)
+scard_send_Transmit(IRP* irp, tui32 sc_handle, char *send_data,
+ int send_bytes, int recv_bytes,
+ struct xrdp_scard_io_request *send_ior,
+ struct xrdp_scard_io_request *recv_ior)
{
- int i;
+ /* see [MS-RDPESC] 2.2.2.19 */
- for (i = 0; i < MAX_SMARTCARDS; i++)
+ SMARTCARD* sc;
+ struct stream* s;
+ int bytes;
+ int val;
+
+ if ((sc = smartcards[irp->scard_index]) == NULL)
{
- if (smartcards[i] == NULL)
+ log_error("smartcards[%d] is NULL", irp->scard_index);
+ return 1;
+ }
+
+ if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_TRANSMIT)) == NULL)
+ {
+ log_error("scard_make_new_ioctl");
+ return 1;
+ }
+
+ log_debug("send_bytes %d recv_bytes %d send dwProtocol %d cbPciLength %d "
+ "extra_bytes %d recv dwProtocol %d cbPciLength %d", send_bytes,
+ recv_bytes, send_ior->dwProtocol, send_ior->cbPciLength,
+ send_ior->extra_bytes, recv_ior->dwProtocol, recv_ior->cbPciLength,
+ recv_ior->extra_bytes);
+
+ /*
+ * command format
+ *
+ * ......
+ * 20 bytes padding
+ * u32 4 bytes len 8, LE, v1
+ * u32 4 bytes filler
+ * 12 bytes unused (s->p currently pointed here at unused[0])
+ * u32 4 bytes map0
+ * 4 bytes unused
+ * u32 4 bytes map1
+ * u32 4 bytes dwProtocol
+ * u32 4 bytes cbPciLength
+ * u32 4 bytes map2
+ * u32 4 byts cbSendLength
+ * u32 4 bytes map3
+ * u32 4 bytes map4
+ * u32 4 bytes map5
+ * u32 4 bytes map6
+ * u32 4 bytes cbRecvLength
+ * u32 4 bytes len of sc_handle
+ * u32 4 bytes sc_handle
+ */
+
+ xstream_seek(s, 12);
+ xstream_wr_u32_le(s, 0); // map0
+ xstream_seek(s, 4);
+ xstream_wr_u32_le(s, 0); // map1
+ xstream_wr_u32_le(s, send_ior->dwProtocol);
+ xstream_wr_u32_le(s, send_ior->cbPciLength);
+ val = send_ior->extra_bytes > 0 ? 1 : 0;
+ xstream_wr_u32_le(s, val); // map2
+ xstream_wr_u32_le(s, send_bytes);
+ val = send_bytes > 0 ? 1 : 0;
+ xstream_wr_u32_le(s, val); // map3
+ val = recv_ior->cbPciLength > 0 ? 1 : 0;
+ xstream_wr_u32_le(s, val); // map 4
+ xstream_wr_u32_le(s, 0); // map5
+ xstream_wr_u32_le(s, recv_bytes);
+ xstream_wr_u32_le(s, 4);
+ xstream_wr_u32_le(s, sc_handle);
+
+ if (send_ior->extra_bytes > 0)
+ {
+ xstream_wr_u32_le(s, send_ior->extra_bytes);
+ out_uint8a(s, send_ior->extra_data, send_ior->extra_bytes);
+ }
+
+ if (send_bytes > 0)
+ {
+ xstream_wr_u32_le(s, send_bytes);
+ out_uint8a(s, send_data, send_bytes);
+ }
+
+ if (recv_ior->cbPciLength > 0)
+ {
+ xstream_wr_u32_le(s, recv_ior->dwProtocol);
+ xstream_wr_u32_le(s, recv_ior->cbPciLength);
+ val = recv_ior->extra_bytes > 0 ? 1 : 0;
+ xstream_wr_u32_le(s, val);
+ if (val)
{
- log_debug("found free slot at index %d", i);
- return i;
+ xstream_wr_u32_le(s, recv_ior->extra_bytes);
+ out_uint8a(s, recv_ior->extra_data, recv_ior->extra_bytes);
}
}
- log_error("too many smart card devices; rejecting this one");
- return -1;
+ /* get stream len */
+ bytes = xstream_len(s);
+
+ /* InputBufferLength is number of bytes AFTER 20 byte padding */
+ *(s->data + 28) = bytes - 56;
+
+ /* send to client */
+ send_channel_data(g_rdpdr_chan_id, s->data, bytes);
+ xstream_free(s);
+ return 0;
}
/**
- * Release resources prior to shutting down
+ * Communicate directly with the smart card reader
*****************************************************************************/
+static int APP_CC
+scard_send_Control(IRP* irp, tui32 context, tui32 sc_handle, char *send_data,
+ int send_bytes, int recv_bytes, int control_code)
+{
+ /* see [MS-RDPESC] 2.2.2.19 */
+
+ SMARTCARD* sc;
+ struct stream* s;
+ int bytes;
+ int val;
+
+ if ((sc = smartcards[irp->scard_index]) == NULL)
+ {
+ log_error("smartcards[%d] is NULL", irp->scard_index);
+ return 1;
+ }
+
+ if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_CONTROL)) == NULL)
+ {
+ log_error("scard_make_new_ioctl");
+ return 1;
+ }
+
+ /*
+ * command format
+ *
+ * ......
+ * 20 bytes padding
+ * u32 4 bytes len 8, LE, v1
+ * u32 4 bytes filler
+ * 12 bytes unused (s->p currently pointed here at unused[0])
+ * u32 4 bytes map0
+ * 4 bytes unused
+ * u32 4 bytes map1
+ * u32 4 bytes dwControlCode
+ * u32 4 bytes cbRecvLength
+ * u32 4 bytes map2
+ * 4 bytes unused
+ * u32 4 bytes cbOutBufferSize
+ * u32 4 bytes context len
+ * u32 4 bytes context
+ * u32 4 bytes handle len
+ * u32 4 bytes handle
+ */
+
+ xstream_seek(s, 12);
+ xstream_wr_u32_le(s, 0); // map0
+ xstream_seek(s, 4);
+ xstream_wr_u32_le(s, 0); // map1
+
+ xstream_wr_u32_le(s, control_code);
+
+ xstream_wr_u32_le(s, send_bytes);
+
+ val = send_bytes > 0 ? 1 : 0;
+ xstream_wr_u32_le(s, val); // map2
+
+ xstream_wr_u32_le(s, 0);
+ xstream_wr_u32_le(s, recv_bytes);
+ xstream_wr_u32_le(s, 4);
+ xstream_wr_u32_le(s, context);
+ xstream_wr_u32_le(s, 4);
+ xstream_wr_u32_le(s, sc_handle);
+
+ if (send_bytes > 0)
+ {
+ xstream_wr_u32_le(s, send_bytes);
+ out_uint8a(s, send_data, send_bytes);
+ }
+
+ /* get stream len */
+ bytes = xstream_len(s);
+
+ /* InputBufferLength is number of bytes AFTER 20 byte padding */
+ *(s->data + 28) = bytes - 56;
+
+ /* send to client */
+ send_channel_data(g_rdpdr_chan_id, s->data, bytes);
+ xstream_free(s);
+ return 0;
+}
+
+/**
+ * Cancel any outstanding calls
+ *****************************************************************************/
+static int APP_CC
+scard_send_Cancel(IRP* irp, tui32 context)
+{
+ /* see [MS-RDPESC] 3.1.4.27 */
+
+ SMARTCARD* sc;
+ struct stream* s;
+ int bytes;
+
+ if ((sc = smartcards[irp->scard_index]) == NULL)
+ {
+ log_error("smartcards[%d] is NULL", irp->scard_index);
+ return 1;
+ }
+
+ if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_CANCEL)) == NULL)
+ {
+ log_error("scard_make_new_ioctl");
+ return 1;
+ }
+
+ /*
+ * command format
+ *
+ * ......
+ * 20 bytes padding
+ * u32 4 bytes len 8, LE, v1
+ * u32 4 bytes filler
+ * 16 bytes unused (s->p currently pointed here at unused[0])
+ * u32 4 bytes context len
+ * u32 4 bytes context
+ */
+
+ xstream_seek(s, 16);
+ xstream_wr_u32_le(s, 4);
+ xstream_wr_u32_le(s, context);
+
+ /* get stream len */
+ bytes = xstream_len(s);
+
+ /* InputBufferLength is number of bytes AFTER 20 byte padding */
+ *(s->data + 28) = bytes - 56;
+
+ /* send to client */
+ send_channel_data(g_rdpdr_chan_id, s->data, bytes);
+ xstream_free(s);
+ return 0;
+}
+
+/**
+ * Get reader attributes
+ *****************************************************************************/
+static int APP_CC
+scard_send_GetAttrib(IRP* irp, tui32 sc_handle, READER_STATE* rs)
+{
+ /* see [MS-RDPESC] 2.2.2.21 */
+ SMARTCARD* sc;
+ struct stream* s;
+ int bytes;
+
+ if ((sc = smartcards[irp->scard_index]) == NULL)
+ {
+ log_error("smartcards[%d] is NULL", irp->scard_index);
+ return 1;
+ }
+
+ if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_GETATTRIB)) == NULL)
+ {
+ log_error("scard_make_new_ioctl");
+ return 1;
+ }
+
+ /*
+ * command format
+ *
+ * ......
+ * 20 bytes padding
+ * u32 4 bytes len 8, LE, v1
+ * u32 4 bytes filler
+ * 24 bytes unused (s->p currently pointed here at unused[0])
+ * u32 4 bytes dwAttribId
+ * 4 bytes unused
+ * u32 4 bytes dwAttrLen
+ * 8 bytes unused
+ * u32 4 bytes handle len
+ * u32 4 bytes handle
+ */
+
+ xstream_seek(s, 24);
+ xstream_wr_u32_le(s, rs->dwAttribId);
+ xstream_wr_u32_le(s, 0);
+ xstream_wr_u32_le(s, rs->dwAttrLen);
+ xstream_seek(s, 8);
+ xstream_wr_u32_le(s, 4);
+ xstream_wr_u32_le(s, sc_handle);
+
+ /* get stream len */
+ bytes = xstream_len(s);
+
+ /* InputBufferLength is number of bytes AFTER 20 byte padding */
+ *(s->data + 28) = bytes - 56;
+
+ /* send to client */
+ send_channel_data(g_rdpdr_chan_id, s->data, bytes);
+ xstream_free(s);
+ return 0;
+}
+
+/******************************************************************************
+** **
+** local callbacks into this module **
+** **
+******************************************************************************/
+
+/**
+ *
+ *****************************************************************************/
static void APP_CC
-scard_release_resources(void)
+scard_handle_EstablishContext_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId, tui32 CompletionId,
+ tui32 IoStatus)
{
- int i;
+ tui32 len;
+ struct trans *con;
- for (i = 0; i < MAX_SMARTCARDS; i++)
+ log_debug("entered");
+ /* sanity check */
+ if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId))
{
- if (smartcards[i] != NULL)
- {
- g_free(smartcards[i]);
- smartcards[i] = NULL;
- }
+ log_error("DeviceId/CompletionId do not match those in IRP");
+ return;
}
+ if (IoStatus != 0)
+ {
+ log_error("failed to establish context - device not usable");
+ /* LK_TODO delete irp and smartcard entry */
+ return;
+ }
+ /* get OutputBufferLen */
+ xstream_rd_u32_le(s, len);
+ con = (struct trans *) (irp->user_data);
+ scard_function_establish_context_return(con, s, len);
+ devredir_irp_delete(irp);
+ log_debug("leaving");
}
/**
*
*****************************************************************************/
-int APP_CC
-scard_get_wait_objs(tbus *objs, int *count, int *timeout)
+static void
+scard_handle_ReleaseContext_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId, tui32 CompletionId,
+ tui32 IoStatus)
{
- return scard_pcsc_get_wait_objs(objs, count, timeout);
+ tui32 len;
+ struct trans *con;
+
+ log_debug("entered");
+ /* sanity check */
+ if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId))
+ {
+ log_error("DeviceId/CompletionId do not match those in IRP");
+ return;
+ }
+ if (IoStatus != 0)
+ {
+ log_error("ReleaseContext failed");
+ /* LK_TODO delete irp and smartcard entry */
+ return;
+ }
+ /* get OutputBufferLen */
+ xstream_rd_u32_le(s, len);
+ con = (struct trans *) (irp->user_data);
+ scard_function_release_context_return(con, s, len);
+ devredir_irp_delete(irp);
+ log_debug("leaving");
}
/**
*
*****************************************************************************/
-int APP_CC
-scard_check_wait_objs(void)
+static void
+APP_CC scard_handle_IsContextValid_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId, tui32 CompletionId,
+ tui32 IoStatus)
{
- return scard_pcsc_check_wait_objs();
+ tui32 len;
+ struct trans *con;
+
+ log_debug("entered");
+
+ /* sanity check */
+ if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId))
+ {
+ log_error("DeviceId/CompletionId do not match those in IRP");
+ return;
+ }
+
+ if (IoStatus != 0)
+ {
+ log_error("Error checking context validity");
+ /* LK_TODO delete irp and smartcard entry */
+ return;
+ }
+
+ /* get OutputBufferLen */
+ xstream_rd_u32_le(s, len);
+ con = (struct trans *) (irp->user_data);
+ scard_function_is_context_valid_return(con, s, len);
+ devredir_irp_delete(irp);
+ log_debug("leaving");
}
/**
*
*****************************************************************************/
-int APP_CC
-scard_init(void)
+static void APP_CC
+scard_handle_ListReaders_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId, tui32 CompletionId,
+ tui32 IoStatus)
{
- log_debug("init")
- return scard_pcsc_init();
+ tui32 len;
+ struct trans *con;
+
+ log_debug("entered");
+ /* sanity check */
+ if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId))
+ {
+ log_error("DeviceId/CompletionId do not match those in IRP");
+ return;
+ }
+ if (IoStatus != 0)
+ {
+ log_error("failed to list readers");
+ /* LK_TODO delete irp and smartcard entry */
+ return;
+ }
+ /* get OutputBufferLen */
+ xstream_rd_u32_le(s, len);
+ con = (struct trans *) (irp->user_data);
+ scard_function_list_readers_return(con, s, len);
+ devredir_irp_delete(irp);
+ log_debug("leaving");
}
/**
*
*****************************************************************************/
-int APP_CC
-scard_deinit(void)
+static void
+scard_handle_GetStatusChange_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId, tui32 CompletionId,
+ tui32 IoStatus)
{
- log_debug("deinit")
- return scard_pcsc_deinit();
+ tui32 len;
+ struct trans *con;
+
+ log_debug("entered");
+ /* sanity check */
+ if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId))
+ {
+ log_error("DeviceId/CompletionId do not match those in IRP");
+ return;
+ }
+ if (IoStatus != 0)
+ {
+ log_error("failed to get status change");
+ /* LK_TODO delete irp and smartcard entry */
+ return;
+ }
+ /* get OutputBufferLen */
+ xstream_rd_u32_le(s, len);
+ con = (struct trans *) (irp->user_data);
+ scard_function_get_status_change_return(con, s, len);
+ devredir_irp_delete(irp);
+ log_debug("leaving");
+}
+
+/**
+ *
+ *****************************************************************************/
+static void
+scard_handle_Connect_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId, tui32 CompletionId,
+ tui32 IoStatus)
+{
+ tui32 len;
+ struct trans *con;
+
+ log_debug("entered");
+
+ /* sanity check */
+ if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId))
+ {
+ log_error("DeviceId/CompletionId do not match those in IRP");
+ return;
+ }
+
+ if (IoStatus != 0)
+ {
+ log_error("failed to connect");
+ /* LK_TODO delete irp and smartcard entry */
+ return;
+ }
+
+ /* get OutputBufferLen */
+ xstream_rd_u32_le(s, len);
+
+ con = (struct trans *) (irp->user_data);
+ scard_function_connect_return(con, s, len);
+ devredir_irp_delete(irp);
+
+ log_debug("leaving");
+}
+
+/**
+ *
+ *****************************************************************************/
+static void APP_CC
+scard_handle_Reconnect_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId, tui32 CompletionId,
+ tui32 IoStatus)
+{
+ tui32 len;
+ struct trans *con;
+
+ log_debug("entered");
+
+ /* sanity check */
+ if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId))
+ {
+ log_error("DeviceId/CompletionId do not match those in IRP");
+ return;
+ }
+
+ if (IoStatus != 0)
+ {
+ log_error("failed to reconnect");
+ /* LK_TODO delete irp and smartcard entry */
+ return;
+ }
+
+ /* get OutputBufferLen */
+ xstream_rd_u32_le(s, len);
+ con = (struct trans *) (irp->user_data);
+ scard_function_reconnect_return(con, s, len);
+ devredir_irp_delete(irp);
+ log_debug("leaving");
+}
+
+/**
+ *
+ *****************************************************************************/
+static void
+scard_handle_BeginTransaction_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId, tui32 CompletionId,
+ tui32 IoStatus)
+{
+ tui32 len;
+ struct trans *con;
+
+ log_debug("entered");
+
+ /* sanity check */
+ if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId))
+ {
+ log_error("DeviceId/CompletionId do not match those in IRP");
+ return;
+ }
+
+ if (IoStatus != 0)
+ {
+ log_error("BeginTransaction failed");
+ /* LK_TODO delete irp and smartcard entry */
+ return;
+ }
+
+ /* get OutputBufferLen */
+ xstream_rd_u32_le(s, len);
+ con = (struct trans *) (irp->user_data);
+ scard_function_begin_transaction_return(con, s, len);
+ devredir_irp_delete(irp);
+ log_debug("leaving");
+}
+
+/**
+ *
+ *****************************************************************************/
+static void
+scard_handle_EndTransaction_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId, tui32 CompletionId,
+ tui32 IoStatus)
+{
+ tui32 len;
+ struct trans *con;
+
+ log_debug("entered");
+
+ /* sanity check */
+ if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId))
+ {
+ log_error("DeviceId/CompletionId do not match those in IRP");
+ return;
+ }
+
+ if (IoStatus != 0)
+ {
+ log_error("EndTransaction failed");
+ /* LK_TODO delete irp and smartcard entry */
+ return;
+ }
+
+ /* get OutputBufferLen */
+ xstream_rd_u32_le(s, len);
+ con = (struct trans *) (irp->user_data);
+ scard_function_end_transaction_return(con, s, len);
+ devredir_irp_delete(irp);
+ log_debug("leaving");
+}
+
+/**
+ *
+ *****************************************************************************/
+static void
+scard_handle_Status_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId, tui32 CompletionId,
+ tui32 IoStatus)
+{
+ tui32 len;
+ struct trans *con;
+
+ log_debug("entered");
+
+ /* sanity check */
+ if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId))
+ {
+ log_error("DeviceId/CompletionId do not match those in IRP");
+ return;
+ }
+
+ if (IoStatus != 0)
+ {
+ log_error("StatusCall failed");
+ /* LK_TODO delete irp and smartcard entry */
+ return;
+ }
+
+ /* get OutputBufferLen */
+ xstream_rd_u32_le(s, len);
+ con = (struct trans *) (irp->user_data);
+ scard_function_status_return(con, s, len);
+ devredir_irp_delete(irp);
+ log_debug("leaving");
+}
+
+/**
+ *
+ *****************************************************************************/
+static void
+scard_handle_Disconnect_Return(struct stream *s, IRP *irp,
+ tui32 DeviceId, tui32 CompletionId,
+ tui32 IoStatus)
+{
+ tui32 len;
+ struct trans *con;
+
+ log_debug("entered");
+
+ /* sanity check */
+ if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId))
+ {
+ log_error("DeviceId/CompletionId do not match those in IRP");
+ return;
+ }
+
+ if (IoStatus != 0)
+ {
+ log_error("Disconnect failed");
+ /* LK_TODO delete irp and smartcard entry */
+ return;
+ }
+
+ /* get OutputBufferLen */
+ xstream_rd_u32_le(s, len);
+ con = (struct trans *) (irp->user_data);
+ scard_function_disconnect_return(con, s, len);
+ devredir_irp_delete(irp);
+ log_debug("leaving");
+}
+
+/**
+ *
+ *****************************************************************************/
+static void APP_CC
+scard_handle_Transmit_Return(struct stream *s, IRP *irp, tui32 DeviceId,
+ tui32 CompletionId, tui32 IoStatus)
+{
+ tui32 len;
+ struct trans *con;
+
+ log_debug("entered");
+
+ /* sanity check */
+ if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId))
+ {
+ log_error("DeviceId/CompletionId do not match those in IRP");
+ return;
+ }
+
+ if (IoStatus != 0)
+ {
+ log_error("Transmit failed");
+ /* LK_TODO delete irp and smartcard entry */
+ return;
+ }
+
+ /* get OutputBufferLen */
+ xstream_rd_u32_le(s, len);
+ con = (struct trans *) (irp->user_data);
+ scard_function_transmit_return(con, s, len);
+ devredir_irp_delete(irp);
+ log_debug("leaving");
+}
+
+/**
+ *
+ *****************************************************************************/
+static void APP_CC
+scard_handle_Control_Return(struct stream *s, IRP *irp, tui32 DeviceId,
+ tui32 CompletionId,tui32 IoStatus)
+{
+ tui32 len;
+ struct trans *con;
+
+ log_debug("entered");
+
+ /* sanity check */
+ if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId))
+ {
+ log_error("DeviceId/CompletionId do not match those in IRP");
+ return;
+ }
+
+ if (IoStatus != 0)
+ {
+ log_error("Control failed");
+ /* LK_TODO delete irp and smartcard entry */
+ return;
+ }
+
+ /* get OutputBufferLen */
+ xstream_rd_u32_le(s, len);
+ con = (struct trans *) (irp->user_data);
+ scard_function_control_return(con, s, len);
+ devredir_irp_delete(irp);
+ log_debug("leaving");
+}
+
+/**
+ *
+ *****************************************************************************/
+static void APP_CC
+scard_handle_Cancel_Return(struct stream *s, IRP *irp, tui32 DeviceId,
+ tui32 CompletionId, tui32 IoStatus)
+{
+ tui32 len;
+ struct trans *con;
+
+ log_debug("entered");
+
+ /* sanity check */
+ if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId))
+ {
+ log_error("DeviceId/CompletionId do not match those in IRP");
+ return;
+ }
+
+ if (IoStatus != 0)
+ {
+ log_error("Cancel_call failed");
+ /* LK_TODO delete irp and smartcard entry */
+ return;
+ }
+
+ /* get OutputBufferLen */
+ xstream_rd_u32_le(s, len);
+ con = (struct trans *) (irp->user_data);
+ scard_function_cancel_return(con, s, len);
+ devredir_irp_delete(irp);
+ log_debug("leaving");
+}
+
+/**
+ *
+ *****************************************************************************/
+static void APP_CC
+scard_handle_GetAttrib_Return(struct stream *s, IRP *irp, tui32 DeviceId,
+ tui32 CompletionId, tui32 IoStatus)
+{
+ tui32 len;
+ struct trans *con;
+
+ log_debug("entered");
+
+ /* sanity check */
+ if ((DeviceId != irp->DeviceId) || (CompletionId != irp->CompletionId))
+ {
+ log_error("DeviceId/CompletionId do not match those in IRP");
+ return;
+ }
+
+ if (IoStatus != 0)
+ {
+ log_error("GetAttrib_call failed");
+ /* LK_TODO delete irp and smartcard entry */
+ return;
+ }
+
+ /* get OutputBufferLen */
+ xstream_rd_u32_le(s, len);
+ con = (struct trans *) (irp->user_data);
+ scard_function_get_attrib_return(con, s, len);
+ devredir_irp_delete(irp);
+ log_debug("leaving");
}
diff --git a/sesman/chansrv/smartcard.h b/sesman/chansrv/smartcard.h
index a85b9f5f..88f4cdf6 100644
--- a/sesman/chansrv/smartcard.h
+++ b/sesman/chansrv/smartcard.h
@@ -26,26 +26,132 @@
#include "parse.h"
#include "irp.h"
+#include "trans.h"
+
+#define SCARD_SHARE_EXCLUSIVE 0x00000001
+#define SCARD_SHARE_SHARED 0x00000002
+#define SCARD_SHARE_DIRECT 0x00000003
+
+/* see [MS-RDPESC] 2.2.5 protocol identifier - Table A */
+#define SCARD_PROTOCOL_UNDEFINED 0x00000000
+#define SCARD_PROTOCOL_T0 0x00000001
+#define SCARD_PROTOCOL_T1 0x00000002
+#define SCARD_PROTOCOL_Tx 0x00000003
+#define SCARD_PROTOCOL_RAW 0x00010000
+
+/* see [MS-RDPESC] 2.2.5 protocol identifier - Table B */
+#define SCARD_PROTOCOL_DEFAULT 0x80000000
+#define SCARD_PROTOCOL_OPTIMAL 0x00000000
+
+/* initialization type */
+#define SCARD_LEAVE_CARD 0x00000000 /* do not do anything */
+#define SCARD_RESET_CARD 0x00000001 /* reset smart card */
+#define SCARD_UNPOWER_CARD 0x00000002 /* turn off and reset card */
+
+struct xrdp_scard_io_request
+{
+ tui32 dwProtocol;
+ tui32 cbPciLength;
+ int extra_bytes;
+ char *extra_data;
+};
+
+typedef struct reader_state
+{
+ char reader_name[128];
+ tui32 current_state;
+ tui32 event_state;
+ tui32 atr_len; /* number of bytes in atr[] */
+ tui8 atr[36];
+
+ /*
+ * share mode flag, can be one of:
+ * SCARD_SHARE_EXCLUSIVE app not willing to share smartcard with other apps
+ * SCARD_SHARE_SHARED app willing to share smartcard with other apps
+ * SCARD_SHARE_DIRECT app demands direct control of smart card, hence
+ * it is not available to other readers
+ */
+ tui32 dwShareMode;
+
+ /*
+ * This field MUST have a value from Table A which is logically
+ * OR'ed with a value from Table B.
+ */
+ tui32 dwPreferredProtocols;
+
+ /*
+ * initialization type, must be one of the initialization type
+ * defined above
+ */
+ tui32 init_type;
+
+ /* required by scard_send_transmit(), scard_send_control() */
+ tui32 map0;
+ tui32 map1;
+ tui32 map2;
+ tui32 map3;
+ tui32 map4;
+ tui32 map5;
+ tui32 map6;
+
+ tui32 dwProtocol;
+ tui32 cbPciLength;
+ tui32 cbSendLength;
+ tui32 cbRecvLength;
+ tui32 dwControlCode;
+ tui32 cbOutBufferSize;
+ tui32 dwAttribId;
+ tui32 dwAttrLen;
+
+} READER_STATE;
-/* forward declarations */
void scard_device_announce(tui32 device_id);
+int APP_CC scard_get_wait_objs(tbus *objs, int *count, int *timeout);
+int APP_CC scard_check_wait_objs(void);
+int APP_CC scard_init(void);
+int APP_CC scard_deinit(void);
+int APP_CC scard_send_establish_context(struct trans *con, int scope);
+int APP_CC scard_send_release_context(struct trans *con, tui32 context);
+int APP_CC scard_send_is_valid_context(struct trans *con, tui32 context);
+int APP_CC scard_send_list_readers(struct trans *con, tui32 context, int wide);
+
+int APP_CC scard_send_get_status_change(struct trans *con, tui32 context,
+ int wide, tui32 timeout,
+ tui32 num_readers, READER_STATE* rsa);
+
+int APP_CC scard_send_connect(struct trans *con, tui32 context, int wide,
+ READER_STATE* rs);
+
+int APP_CC scard_send_reconnect(struct trans *con, tui32 context,
+ tui32 sc_handle, READER_STATE* rs);
-/* callbacks into this module */
-void scard_handle_EstablishContext_Return(struct stream *s, IRP *irp,
- tui32 DeviceId, tui32 CompletionId,
- tui32 IoStatus);
+int APP_CC scard_send_begin_transaction(struct trans *con, tui32 sc_handle);
+int APP_CC scard_send_end_transaction(struct trans *con, tui32 sc_handle,
+ tui32 dwDisposition);
+int APP_CC scard_send_status(struct trans *con, int wide, tui32 sc_handle,
+ int cchReaderLen, int cbAtrLen);
+int APP_CC scard_send_disconnect(struct trans *con, tui32 context,
+ tui32 sc_handle, int dwDisposition);
-void scard_handle_ListReaders_Return(struct stream *s, IRP *irp,
- tui32 DeviceId, tui32 CompletionId,
- tui32 IoStatus);
+int APP_CC scard_send_transmit(struct trans *con, tui32 sc_handle,
+ char *send_data, int send_bytes, int recv_bytes,
+ struct xrdp_scard_io_request *send_ior,
+ struct xrdp_scard_io_request *recv_ior);
-int APP_CC
-scard_get_wait_objs(tbus *objs, int *count, int *timeout);
-int APP_CC
-scard_check_wait_objs(void);
-int APP_CC
-scard_init(void);
-int APP_CC
-scard_deinit(void);
+int APP_CC scard_send_control(struct trans *con, tui32 context, tui32 sc_handle,
+ char *send_data, int send_bytes,
+ int recv_bytes, int control_code);
+int APP_CC scard_send_cancel(struct trans *con, tui32 context);
+
+int APP_CC scard_send_get_attrib(struct trans *con, tui32 sc_handle,
+ READER_STATE* rs);
+
+/*
+ * Notes:
+ * SCardTransmit - partially done
+ * SCardControl - partially done
+ * SCardListReaderGroups - not supported
+ * SCardSetAttrib - not supported
+ */
#endif /* end #ifndef _SMARTCARD_C */
diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c
index a3a269d7..29f60c8d 100644
--- a/sesman/chansrv/smartcard_pcsc.c
+++ b/sesman/chansrv/smartcard_pcsc.c
@@ -20,8 +20,12 @@
/*
* smartcard redirection support, PCSC daemon standin
* this will act like pcsc daemon
+ * pcsc lib and daemon write struct on unix domain socket for communication
*/
+#define JAY_TODO_CONTEXT 0
+#define JAY_TODO_WIDE 1
+
#define PCSC_STANDIN 1
#include "os_calls.h"
@@ -30,77 +34,37 @@
#include "irp.h"
#include "devredir.h"
#include "trans.h"
+#include "chansrv.h"
#if PCSC_STANDIN
-/* module based logging */
-#define LOG_ERROR 0
-#define LOG_INFO 1
-#define LOG_DEBUG 2
-#define LOG_LEVEL LOG_ERROR
-
-#define log_error(_params...) \
-{ \
- g_write("[%10.10u]: PCSC %s: %d : ERROR: ", \
- g_time3(), __func__, __LINE__); \
- g_writeln (_params); \
-}
-
-#define log_always(_params...) \
-{ \
- g_write("[%10.10u]: PCSC %s: %d : ALWAYS: ", \
- g_time3(), __func__, __LINE__); \
- g_writeln (_params); \
-}
-
-#define log_info(_params...) \
-{ \
- if (LOG_INFO <= LOG_LEVEL) \
- { \
- g_write("[%10.10u]: PCSC %s: %d : ", \
- g_time3(), __func__, __LINE__); \
- g_writeln (_params); \
- } \
-}
-
-#define log_debug(_params...) \
-{ \
- if (LOG_DEBUG <= LOG_LEVEL) \
- { \
- g_write("[%10.10u]: PCSC %s: %d : ", \
- g_time3(), __func__, __LINE__); \
- g_writeln (_params); \
- } \
-}
-
-#define PCSCLITE_MSG_KEY_LEN 16
-#define PCSCLITE_MAX_MESSAGE_SIZE 2048
-
-struct version_struct
-{
- tsi32 major; /**< IPC major \ref PROTOCOL_VERSION_MAJOR */
- tsi32 minor; /**< IPC minor \ref PROTOCOL_VERSION_MINOR */
- tui32 rv;
-};
-typedef struct version_struct version_struct;
+#define LLOG_LEVEL 1
+#define LLOGLN(_level, _args) \
+ do \
+ { \
+ if (_level < LLOG_LEVEL) \
+ { \
+ g_write("chansrv:smartcard_pcsc [%10.10u]: ", g_time3()); \
+ g_writeln _args ; \
+ } \
+ } \
+ while (0)
-struct rxSharedSegment
-{
- tui32 mtype; /** one of the \c pcsc_adm_commands */
- tui32 user_id;
- tui32 group_id;
- tui32 command; /** one of the \c pcsc_msg_commands */
- tui64 date;
- tui8 key[PCSCLITE_MSG_KEY_LEN]; /* 16 bytes */
- union _u
- {
- tui8 data[PCSCLITE_MAX_MESSAGE_SIZE];
- struct version_struct veStr;
- } u;
-};
-typedef struct rxSharedSegment sharedSegmentMsg, *psharedSegmentMsg;
+#define XRDP_PCSC_STATE_NONE 0
+#define XRDP_PCSC_STATE_GOT_EC (1 << 0) /* establish context */
+#define XRDP_PCSC_STATE_GOT_LR (1 << 1) /* list readers */
+#define XRDP_PCSC_STATE_GOT_RC (1 << 2) /* release context */
+#define XRDP_PCSC_STATE_GOT_GSC (1 << 3) /* get status change */
+#define XRDP_PCSC_STATE_GOT_C (1 << 4) /* connect */
+#define XRDP_PCSC_STATE_GOT_BT (1 << 5) /* begin transaction */
+#define XRDP_PCSC_STATE_GOT_ET (1 << 6) /* end transaction */
+#define XRDP_PCSC_STATE_GOT_TR (1 << 7) /* transmit */
+#define XRDP_PCSC_STATE_GOT_CO (1 << 8) /* control */
+#define XRDP_PCSC_STATE_GOT_D (1 << 9) /* disconnect */
+#define XRDP_PCSC_STATE_GOT_ST (1 << 10) /* get status */
-#define RXSHAREDSEGMENT_BYTES 2088
+/* TODO: put this in con */
+static int g_xrdp_pcsc_state = XRDP_PCSC_STATE_NONE;
extern int g_display_num; /* in chansrv.c */
@@ -110,20 +74,21 @@ struct pcsc_client
struct trans *con;
};
+#if 0
static struct pcsc_client *g_head = 0;
static struct pcsc_client *g_tail = 0;
+#endif
static struct trans *g_lis = 0;
static struct trans *g_con = 0; /* todo, remove this */
-
-static char g_pcsc_directory[256] = "";
+static char g_pcsclite_ipc_dir[256] = "";
+static int g_pub_file_fd = 0;
/*****************************************************************************/
int APP_CC
scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout)
{
- log_debug("scard_pcsc_get_wait_objs");
-
+ LLOGLN(10, ("scard_pcsc_get_wait_objs"));
if (g_lis != 0)
{
trans_get_wait_objs(g_lis, objs, count);
@@ -139,8 +104,7 @@ scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout)
int APP_CC
scard_pcsc_check_wait_objs(void)
{
- log_debug("scard_pcsc_check_wait_objs");
-
+ LLOGLN(10, ("scard_pcsc_check_wait_objs"));
if (g_lis != 0)
{
trans_check_wait_objs(g_lis);
@@ -155,34 +119,955 @@ scard_pcsc_check_wait_objs(void)
/*****************************************************************************/
/* returns error */
int APP_CC
-scard_process_version(psharedSegmentMsg msg)
+scard_process_establish_context(struct trans *con, struct stream *in_s)
{
+ int dwScope;
+
+ LLOGLN(10, ("scard_process_establish_context:"));
+ if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_EC)
+ {
+ LLOGLN(0, ("scard_process_establish_context: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_EC;
+ in_uint32_le(in_s, dwScope);
+ LLOGLN(10, ("scard_process_establish_context: dwScope 0x%8.8x", dwScope));
+ scard_send_establish_context(con, dwScope);
return 0;
}
/*****************************************************************************/
/* returns error */
int APP_CC
-scard_process_msg(struct stream *s)
+scard_function_establish_context_return(struct trans *con,
+ struct stream *in_s,
+ int len)
{
- sharedSegmentMsg msg;
- int rv;
+ int bytes;
+ tui32 context;
+ tui32 context_len;
+ struct stream *out_s;
- g_memset(&msg, 0, sizeof(msg));
- in_uint32_le(s, msg.mtype);
- in_uint32_le(s, msg.user_id);
- in_uint32_le(s, msg.group_id);
- in_uint32_le(s, msg.command);
- in_uint64_le(s, msg.date);
+ LLOGLN(10, ("scard_function_establish_context_return:"));
+ if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_EC) == 0)
+ {
+ LLOGLN(0, ("scard_function_establish_context_return: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_EC;
+ in_uint8s(in_s, 28);
+ in_uint32_le(in_s, context_len);
+ if (context_len != 4)
+ {
+ LLOGLN(0, ("scard_function_establish_context_return: opps"));
+ return 1;
+ }
+ in_uint32_le(in_s, context);
+ LLOGLN(10, ("scard_function_establish_context_return: context 0x%8.8x", context));
+ out_s = trans_get_out_s(con, 8192);
+ s_push_layer(out_s, iso_hdr, 8);
+ out_uint32_le(out_s, context);
+ out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */
+ s_mark_end(out_s);
+ bytes = (int) (out_s->end - out_s->data);
+ s_pop_layer(out_s, iso_hdr);
+ out_uint32_le(out_s, bytes - 8);
+ out_uint32_le(out_s, 0x01); /* SCARD_ESTABLISH_CONTEXT 0x01 */
+ return trans_force_write(con);
+}
- log_debug("scard_process_msg: mtype 0x%2.2x command 0x%2.2x",
- msg.mtype, msg.command);
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_process_release_context(struct trans *con, struct stream *in_s)
+{
+ int hContext;
+
+ LLOGLN(10, ("scard_process_release_context:"));
+ if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_RC)
+ {
+ LLOGLN(0, ("scard_process_establish_context: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_RC;
+ in_uint32_le(in_s, hContext);
+ LLOGLN(10, ("scard_process_release_context: hContext 0x%8.8x", hContext));
+ scard_send_release_context(con, hContext);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_function_release_context_return(struct trans *con,
+ struct stream *in_s,
+ int len)
+{
+ int bytes;
+ struct stream *out_s;
+
+ LLOGLN(10, ("scard_function_release_context_return:"));
+ if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_RC) == 0)
+ {
+ LLOGLN(0, ("scard_function_release_context_return: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_RC;
+ out_s = trans_get_out_s(con, 8192);
+ s_push_layer(out_s, iso_hdr, 8);
+ out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */
+ s_mark_end(out_s);
+ bytes = (int) (out_s->end - out_s->data);
+ s_pop_layer(out_s, iso_hdr);
+ out_uint32_le(out_s, bytes - 8);
+ out_uint32_le(out_s, 0x02); /* SCARD_RELEASE_CONTEXT 0x02 */
+ return trans_force_write(con);
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_process_list_readers(struct trans *con, struct stream *in_s)
+{
+ int hContext;
+
+ LLOGLN(10, ("scard_process_list_readers:"));
+ if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_LR)
+ {
+ LLOGLN(0, ("scard_process_list_readers: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_LR;
+ in_uint32_le(in_s, hContext);
+ LLOGLN(10, ("scard_process_list_readers: dwScope 0x%8.8x", hContext));
+ scard_send_list_readers(con, hContext, 1);
+ return 0;
+}
+
+/*****************************************************************************/
+int APP_CC
+scard_function_list_readers_return(struct trans *con,
+ struct stream *in_s,
+ int len)
+{
+ struct stream *out_s;
+ int chr;
+ int readers;
+ int rn_index;
+ int index;
+ int bytes;
+ twchar reader_name[100];
+ char lreader_name[16][100];
+
+ LLOGLN(10, ("scard_function_list_readers_return:"));
+ //g_hexdump(in_s->p, len);
+ if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_LR) == 0)
+ {
+ LLOGLN(0, ("scard_function_list_readers_return: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_LR;
+
+ g_memset(reader_name, 0, sizeof(reader_name));
+ g_memset(lreader_name, 0, sizeof(lreader_name));
+ in_uint8s(in_s, 28);
+ len -= 28;
+ in_uint32_le(in_s, len);
+ //g_writeln("len %d", len);
+ rn_index = 0;
+ readers = 0;
+ while (len > 0)
+ {
+ in_uint16_le(in_s, chr);
+ len -= 2;
+ if (chr == 0)
+ {
+ if (reader_name[0] != 0)
+ {
+ g_wcstombs(lreader_name[readers], reader_name, 99);
+ //g_writeln("1 %s", lreader_name[readers]);
+ g_memset(reader_name, 0, sizeof(reader_name));
+ readers++;
+ }
+ reader_name[0] = 0;
+ rn_index = 0;
+ }
+ else
+ {
+ reader_name[rn_index] = chr;
+ rn_index++;
+ }
+ }
+ if (rn_index > 0)
+ {
+ if (reader_name[0] != 0)
+ {
+ g_wcstombs(lreader_name[readers], reader_name, 99);
+ //g_writeln("2 %s", lreader_name[readers]);
+ g_memset(reader_name, 0, sizeof(reader_name));
+ readers++;
+ }
+ }
+
+ out_s = trans_get_out_s(con, 8192);
+ s_push_layer(out_s, iso_hdr, 8);
+ out_uint32_le(out_s, readers);
+ for (index = 0; index < readers; index++)
+ {
+ //g_writeln("3 - %s", lreader_name[index]);
+ out_uint8a(out_s, lreader_name[index], 100);
+ }
+ out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */
+ s_mark_end(out_s);
+ bytes = (int) (out_s->end - out_s->data);
+ s_pop_layer(out_s, iso_hdr);
+ out_uint32_le(out_s, bytes - 8);
+ out_uint32_le(out_s, 0x03); /* SCARD_LIST_READERS 0x03 */
+ return trans_force_write(con);
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_process_connect(struct trans *con, struct stream *in_s)
+{
+ int hContext;
+ READER_STATE rs;
+ LLOGLN(10, ("scard_process_connect:"));
+ if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_C)
+ {
+ LLOGLN(0, ("scard_process_connect: opps"));
+ return 1;
+ }
+ g_memset(&rs, 0, sizeof(rs));
+ g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_C;
+ in_uint32_le(in_s, hContext);
+ in_uint8a(in_s, rs.reader_name, 100);
+ in_uint32_le(in_s, rs.dwShareMode);
+ in_uint32_le(in_s, rs.dwPreferredProtocols);
+ LLOGLN(10, ("scard_process_connect: rs.reader_name %s dwShareMode 0x%8.8x "
+ "dwPreferredProtocols 0x%8.8x", rs.reader_name, rs.dwShareMode,
+ rs.dwPreferredProtocols));
+ scard_send_connect(con, hContext, 1, &rs);
+ return 0;
+}
+
+/*****************************************************************************/
+int APP_CC
+scard_function_connect_return(struct trans *con,
+ struct stream *in_s,
+ int len)
+{
+ int dwActiveProtocol;
+ int hCard;
+ int bytes;
+ struct stream *out_s;
+
+ //g_hexdump(in_s->p, len);
+ if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_C) == 0)
+ {
+ LLOGLN(0, ("scard_function_connect_return: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_C;
+ in_uint8s(in_s, 36);
+ in_uint32_le(in_s, dwActiveProtocol);
+ in_uint8s(in_s, 4);
+ in_uint32_le(in_s, hCard);
+ LLOGLN(10, ("scard_function_connect_return: hCard %d dwActiveProtocol %d", hCard, dwActiveProtocol));
+ out_s = trans_get_out_s(con, 8192);
+ s_push_layer(out_s, iso_hdr, 8);
+ out_uint32_le(out_s, hCard);
+ out_uint32_le(out_s, dwActiveProtocol);
+ out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */
+ s_mark_end(out_s);
+ bytes = (int) (out_s->end - out_s->data);
+ s_pop_layer(out_s, iso_hdr);
+ out_uint32_le(out_s, bytes - 8);
+ out_uint32_le(out_s, 0x04); /* SCARD_CONNECT 0x04 */
+ return trans_force_write(con);
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_process_disconnect(struct trans *con, struct stream *in_s)
+{
+ int hContext;
+ int hCard;
+ int dwDisposition;
+
+ LLOGLN(10, ("scard_process_disconnect:"));
+ if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_D)
+ {
+ LLOGLN(0, ("scard_process_disconnect: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_D;
+ in_uint32_le(in_s, hCard);
+ in_uint32_le(in_s, dwDisposition);
+
+ hContext = 1;
+
+ scard_send_disconnect(con, hContext, hCard, dwDisposition);
+
+ return 0;
+}
+
+/*****************************************************************************/
+int APP_CC
+scard_function_disconnect_return(struct trans *con,
+ struct stream *in_s,
+ int len)
+{
+ int dwActiveProtocol;
+ int hCard;
+ int bytes;
+ struct stream *out_s;
+
+ //g_hexdump(in_s->p, len);
+ if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_D) == 0)
+ {
+ LLOGLN(0, ("scard_function_connect_return: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_D;
+ in_uint8s(in_s, 36);
+ in_uint32_le(in_s, dwActiveProtocol);
+ in_uint8s(in_s, 4);
+ in_uint32_le(in_s, hCard);
+ LLOGLN(10, ("scard_function_connect_return: hCard %d dwActiveProtocol %d", hCard, dwActiveProtocol));
+ out_s = trans_get_out_s(con, 8192);
+ s_push_layer(out_s, iso_hdr, 8);
+ out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */
+ s_mark_end(out_s);
+ bytes = (int) (out_s->end - out_s->data);
+ s_pop_layer(out_s, iso_hdr);
+ out_uint32_le(out_s, bytes - 8);
+ out_uint32_le(out_s, 0x06); /* SCARD_DISCONNECT 0x06 */
+ return trans_force_write(con);
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_process_begin_transaction(struct trans *con, struct stream *in_s)
+{
+ int hCard;
+
+ LLOGLN(10, ("scard_process_begin_transaction:"));
+ if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_BT)
+ {
+ LLOGLN(0, ("scard_process_begin_transaction: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_BT;
+ in_uint32_le(in_s, hCard);
+ LLOGLN(10, ("scard_process_begin_transaction: hCard 0x%8.8x", hCard));
+ scard_send_begin_transaction(con, hCard);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_function_begin_transaction_return(struct trans *con,
+ struct stream *in_s,
+ int len)
+{
+ struct stream *out_s;
+ int bytes;
+
+ //g_hexdump(in_s->p, len);
+ if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_BT) == 0)
+ {
+ LLOGLN(0, ("scard_function_begin_transaction_return: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_BT;
+
+ out_s = trans_get_out_s(con, 8192);
+ s_push_layer(out_s, iso_hdr, 8);
+ out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */
+ s_mark_end(out_s);
+ bytes = (int) (out_s->end - out_s->data);
+ s_pop_layer(out_s, iso_hdr);
+ out_uint32_le(out_s, bytes - 8);
+ out_uint32_le(out_s, 0x07); /* SCARD_BEGIN_TRANSACTION 0x07 */
+ return trans_force_write(con);
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_process_end_transaction(struct trans *con, struct stream *in_s)
+{
+ int hCard;
+ int dwDisposition;
+
+ LLOGLN(10, ("scard_process_end_transaction:"));
+ if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_ET)
+ {
+ LLOGLN(0, ("scard_process_end_transaction: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_ET;
+ in_uint32_le(in_s, hCard);
+ in_uint32_le(in_s, dwDisposition);
+ LLOGLN(10, ("scard_process_end_transaction: hCard 0x%8.8x", hCard));
+ scard_send_end_transaction(con, hCard, dwDisposition);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_function_end_transaction_return(struct trans *con,
+ struct stream *in_s,
+ int len)
+{
+ struct stream *out_s;
+ int bytes;
+
+ //g_hexdump(in_s->p, len);
+ if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_ET) == 0)
+ {
+ LLOGLN(0, ("scard_function_end_transaction_return: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_ET;
+
+ out_s = trans_get_out_s(con, 8192);
+ s_push_layer(out_s, iso_hdr, 8);
+ out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */
+ s_mark_end(out_s);
+ bytes = (int) (out_s->end - out_s->data);
+ s_pop_layer(out_s, iso_hdr);
+ out_uint32_le(out_s, bytes - 8);
+ out_uint32_le(out_s, 0x08); /* SCARD_END_TRANSACTION 0x08 */
+ return trans_force_write(con);
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_function_cancel_return(struct trans *con,
+ struct stream *in_s,
+ int len)
+{
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_function_get_attrib_return(struct trans *con,
+ struct stream *in_s,
+ int len)
+{
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_process_transmit(struct trans *con, struct stream *in_s)
+{
+ int hCard;
+ int recv_bytes;
+ int send_bytes;
+ char *send_data;
+ struct xrdp_scard_io_request send_ior;
+ struct xrdp_scard_io_request recv_ior;
+
+ LLOGLN(10, ("scard_process_transmit:"));
+ if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_TR)
+ {
+ LLOGLN(0, ("scard_process_transmit: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_TR;
+ LLOGLN(10, ("scard_process_transmit:"));
+ in_uint32_le(in_s, hCard);
+ in_uint32_le(in_s, send_ior.dwProtocol);
+ in_uint32_le(in_s, send_ior.cbPciLength);
+ in_uint32_le(in_s, send_ior.extra_bytes);
+ in_uint8p(in_s, send_ior.extra_data, send_ior.extra_bytes);
+ in_uint32_le(in_s, send_bytes);
+ in_uint8p(in_s, send_data, send_bytes);
+ in_uint32_le(in_s, recv_ior.dwProtocol);
+ in_uint32_le(in_s, recv_ior.cbPciLength);
+ in_uint32_le(in_s, recv_ior.extra_bytes);
+ in_uint8p(in_s, recv_ior.extra_data, recv_ior.extra_bytes);
+ in_uint32_le(in_s, recv_bytes);
+ LLOGLN(10, ("scard_process_transmit: send dwProtocol %d cbPciLength %d "
+ "recv dwProtocol %d cbPciLength %d send_bytes %d ",
+ send_ior.dwProtocol, send_ior.cbPciLength, recv_ior.dwProtocol,
+ recv_ior.cbPciLength, send_bytes));
+ //g_hexdump(in_s->p, send_bytes);
+ LLOGLN(10, ("scard_process_transmit: recv_bytes %d", recv_bytes));
+ scard_send_transmit(con, hCard, send_data, send_bytes, recv_bytes,
+ &send_ior, &recv_ior);
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_function_transmit_return(struct trans *con,
+ struct stream *in_s,
+ int len)
+{
+ struct stream *out_s;
+ int bytes;
+ int val;
+ int cbRecvLength;
+ struct xrdp_scard_io_request recv_ior;
+ char *recvBuf;
+
+ LLOGLN(10, ("scard_function_transmit_return:"));
+ //g_hexdump(in_s->p, len);
+ if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_TR) == 0)
+ {
+ LLOGLN(0, ("scard_function_transmit_return: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_TR;
+
+ in_uint8s(in_s, 20);
+ in_uint32_le(in_s, val);
+ g_memset(&recv_ior, 0, sizeof(recv_ior));
+ if (val != 0)
+ {
+ /* pioRecvPci */
+ LLOGLN(0, ("scard_function_transmit_return: pioRecvPci not zero!"));
+ }
+ in_uint8s(in_s, 4);
+ in_uint32_le(in_s, val);
+ cbRecvLength = 0;
+ recvBuf = 0;
+ if (val != 0)
+ {
+ in_uint32_le(in_s, cbRecvLength);
+ in_uint8p(in_s, recvBuf, cbRecvLength);
+ }
+ LLOGLN(10, ("scard_function_transmit_return: cbRecvLength %d", cbRecvLength));
+ out_s = trans_get_out_s(con, 8192);
+ s_push_layer(out_s, iso_hdr, 8);
+ out_uint32_le(out_s, recv_ior.dwProtocol);
+ out_uint32_le(out_s, recv_ior.cbPciLength);
+ out_uint32_le(out_s, recv_ior.extra_bytes);
+ out_uint8a(out_s, recv_ior.extra_data, recv_ior.extra_bytes);
+ out_uint32_le(out_s, cbRecvLength);
+ out_uint8a(out_s, recvBuf, cbRecvLength);
+ out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */
+ s_mark_end(out_s);
+ bytes = (int) (out_s->end - out_s->data);
+ s_pop_layer(out_s, iso_hdr);
+ out_uint32_le(out_s, bytes - 8);
+ out_uint32_le(out_s, 0x09); /* SCARD_TRANSMIT 0x09 */
+ return trans_force_write(con);
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_process_control(struct trans *con, struct stream *in_s)
+{
+ tui32 context;
+ int hCard;
+ int send_bytes;
+ int recv_bytes;
+ int control_code;
+ char *send_data;
+
+ LLOGLN(10, ("scard_process_control:"));
+ if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_CO)
+ {
+ LLOGLN(0, ("scard_process_control: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_CO;
+ LLOGLN(10, ("scard_process_control:"));
+
+ in_uint32_le(in_s, hCard);
+ in_uint32_le(in_s, control_code);
+ in_uint32_le(in_s, send_bytes);
+ in_uint8p(in_s, send_data, send_bytes);
+ in_uint32_le(in_s, recv_bytes);
+
+ context = 1;
+
+ scard_send_control(con, context, hCard, send_data, send_bytes, recv_bytes,
+ control_code);
+
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_function_control_return(struct trans *con,
+ struct stream *in_s,
+ int len)
+{
+ struct stream *out_s;
+ int bytes;
+ int cbRecvLength;
+ char *recvBuf;
+
+ //g_hexdump(in_s->p, len);
+ if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_CO) == 0)
+ {
+ LLOGLN(0, ("scard_function_control_return: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_CO;
+
+ in_uint8s(in_s, 28);
+ in_uint32_le(in_s, cbRecvLength);
+ in_uint8p(in_s, recvBuf, cbRecvLength);
+
+ LLOGLN(10, ("scard_function_control_return: cbRecvLength %d", cbRecvLength));
+ out_s = trans_get_out_s(con, 8192);
+ s_push_layer(out_s, iso_hdr, 8);
+ out_uint32_le(out_s, cbRecvLength);
+ out_uint8a(out_s, recvBuf, cbRecvLength);
+ out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */
+ s_mark_end(out_s);
+ bytes = (int) (out_s->end - out_s->data);
+ s_pop_layer(out_s, iso_hdr);
+ out_uint32_le(out_s, bytes - 8);
+ out_uint32_le(out_s, 0x0A); /* SCARD_CONTROL 0x0A */
+ return trans_force_write(con);
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_process_status(struct trans *con, struct stream *in_s)
+{
+ int hCard;
+ int cchReaderLen;
+ int cbAtrLen;
+
+ LLOGLN(10, ("scard_process_status:"));
+ if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_ST)
+ {
+ LLOGLN(0, ("scard_process_status: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_ST;
+
+ in_uint32_le(in_s, hCard);
+ in_uint32_le(in_s, cchReaderLen);
+ in_uint32_le(in_s, cbAtrLen);
+
+ scard_send_status(con, 1, hCard, cchReaderLen, cbAtrLen);
+
+ return 0;
+}
+
+#define MS_SCARD_UNKNOWN 0
+#define MS_SCARD_ABSENT 1
+#define MS_SCARD_PRESENT 2
+#define MS_SCARD_SWALLOWED 3
+#define MS_SCARD_POWERED 4
+#define MS_SCARD_NEGOTIABLE 5
+#define MS_SCARD_SPECIFIC 6
+
+#define PC_SCARD_UNKNOWN 0x0001 /**< Unknown state */
+#define PC_SCARD_ABSENT 0x0002 /**< Card is absent */
+#define PC_SCARD_PRESENT 0x0004 /**< Card is present */
+#define PC_SCARD_SWALLOWED 0x0008 /**< Card not powered */
+#define PC_SCARD_POWERED 0x0010 /**< Card is powered */
+#define PC_SCARD_NEGOTIABLE 0x0020 /**< Ready for PTS */
+#define PC_SCARD_SPECIFIC 0x0040 /**< PTS has been set */
+
+static int g_ms2pc[] = { PC_SCARD_UNKNOWN, PC_SCARD_ABSENT,
+ PC_SCARD_PRESENT, PC_SCARD_SWALLOWED,
+ PC_SCARD_POWERED, PC_SCARD_NEGOTIABLE,
+ PC_SCARD_SPECIFIC };
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_function_status_return(struct trans *con,
+ struct stream *in_s,
+ int len)
+{
+ struct stream *out_s;
+ int index;
+ int bytes;
+ int dwReaderLen;
+ int dwState;
+ int dwProtocol;
+ int dwAtrLen;
+ char attr[32];
+ twchar reader_name[100];
+ char lreader_name[100];
+
+ //g_hexdump(in_s->p, len);
+ if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_ST) == 0)
+ {
+ LLOGLN(0, ("scard_function_status_return: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_ST;
+ in_uint8s(in_s, 20);
+ in_uint32_le(in_s, dwReaderLen);
+ in_uint8s(in_s, 4);
+ in_uint32_le(in_s, dwState);
+ dwState = g_ms2pc[dwState % 6];
+ in_uint32_le(in_s, dwProtocol);
+ in_uint8a(in_s, attr, 32);
+ in_uint32_le(in_s, dwAtrLen);
+ in_uint32_le(in_s, dwReaderLen);
+ dwReaderLen /= 2;
+ g_memset(reader_name, 0, sizeof(reader_name));
+ g_memset(lreader_name, 0, sizeof(lreader_name));
+ for (index = 0; index < dwReaderLen; index++)
+ {
+ in_uint16_le(in_s, reader_name[index]);
+ }
+ g_wcstombs(lreader_name, reader_name, 99);
+ LLOGLN(10, ("scard_function_status_return: dwAtrLen %d dwReaderLen %d "
+ "dwProtocol %d dwState %d name %s",
+ dwAtrLen, dwReaderLen, dwProtocol, dwState, lreader_name));
+ out_s = trans_get_out_s(con, 8192);
+ s_push_layer(out_s, iso_hdr, 8);
+ dwReaderLen = g_strlen(lreader_name);
+ out_uint32_le(out_s, dwReaderLen);
+ out_uint8a(out_s, lreader_name, dwReaderLen);
+ out_uint32_le(out_s, dwState);
+ out_uint32_le(out_s, dwProtocol);
+ out_uint32_le(out_s, dwAtrLen);
+ out_uint8a(out_s, attr, dwAtrLen);
+ out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */
+ s_mark_end(out_s);
+ bytes = (int) (out_s->end - out_s->data);
+ s_pop_layer(out_s, iso_hdr);
+ out_uint32_le(out_s, bytes - 8);
+ out_uint32_le(out_s, 0x0B); /* SCARD_STATUS 0x0B */
+ return trans_force_write(con);
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_process_get_status_change(struct trans *con, struct stream *in_s)
+{
+ int index;
+ int hContext;
+ int dwTimeout;
+ int cReaders;
+ READER_STATE *rsa;
+
+ LLOGLN(10, ("scard_process_get_status_change:"));
+ if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_GSC)
+ {
+ LLOGLN(0, ("scard_process_get_status_change: opps"));
+ return 1;
+ }
+ in_uint32_le(in_s, hContext);
+ in_uint32_le(in_s, dwTimeout);
+ in_uint32_le(in_s, cReaders);
+ if ((cReaders < 0) || (cReaders > 16))
+ {
+ LLOGLN(0, ("scard_process_get_status_change: bad cReaders %d", cReaders));
+ return 1;
+ }
+ rsa = (READER_STATE *) g_malloc(sizeof(READER_STATE) * cReaders, 1);
+
+ for (index = 0; index < cReaders; index++)
+ {
+ in_uint8a(in_s, rsa[index].reader_name, 100);
+ LLOGLN(10, ("scard_process_get_status_change: reader_name %s",
+ rsa[index].reader_name));
+ in_uint32_le(in_s, rsa[index].current_state);
+ LLOGLN(10, ("scard_process_get_status_change: current_state %d",
+ rsa[index].current_state));
+ in_uint32_le(in_s, rsa[index].event_state);
+ LLOGLN(10, ("scard_process_get_status_change: event_state %d",
+ rsa[index].event_state));
+ in_uint32_le(in_s, rsa[index].atr_len);
+ LLOGLN(10, ("scard_process_get_status_change: atr_len %d",
+ rsa[index].atr_len));
+ in_uint8a(in_s, rsa[index].atr, 36);
+ }
+
+ LLOGLN(10, ("scard_process_get_status_change: hContext 0x%8.8x dwTimeout "
+ "%d cReaders %d", hContext, dwTimeout, cReaders));
+
+ g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_GSC;
+
+ scard_send_get_status_change(con, hContext, 1, dwTimeout, cReaders, rsa);
+
+ g_free(rsa);
+
+ return 0;
+}
+
+/*****************************************************************************/
+int APP_CC
+scard_function_get_status_change_return(struct trans *con,
+ struct stream *in_s,
+ int len)
+{
+ int bytes;
+ int index;
+ int cReaders;
+ tui32 current_state;
+ tui32 event_state;
+ tui32 atr_len; /* number of bytes in atr[] */
+ tui8 atr[36];
+ struct stream *out_s;
+
+ LLOGLN(10, ("scard_function_get_status_change_return:"));
+ //g_hexdump(in_s->p, len);
+ if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_GSC) == 0)
+ {
+ LLOGLN(0, ("scard_function_establish_context_return: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_GSC;
+ in_uint8s(in_s, 28);
+ in_uint32_le(in_s, cReaders);
+ if (cReaders > 0)
+ {
+ out_s = trans_get_out_s(con, 8192);
+ s_push_layer(out_s, iso_hdr, 8);
+ out_uint32_le(out_s, cReaders);
+ for (index = 0; index < cReaders; index++)
+ {
+ in_uint32_le(in_s, current_state);
+ out_uint32_le(out_s, current_state);
+ in_uint32_le(in_s, event_state);
+ out_uint32_le(out_s, event_state);
+ in_uint32_le(in_s, atr_len);
+ out_uint32_le(out_s, atr_len);
+ in_uint8a(in_s, atr, 36);
+ out_uint8a(out_s, atr, 36);
+ }
+ out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */
+ s_mark_end(out_s);
+ bytes = (int) (out_s->end - out_s->data);
+ s_pop_layer(out_s, iso_hdr);
+ out_uint32_le(out_s, bytes - 8);
+ out_uint32_le(out_s, 0x0C); /* SCARD_ESTABLISH_CONTEXT 0x0C */
+ return trans_force_write(con);
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_function_is_context_valid_return(struct trans *con,
+ struct stream *in_s,
+ int len)
+{
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC scard_function_reconnect_return(struct trans *con,
+ struct stream *in_s,
+ int len)
+{
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_process_msg(struct trans *con, struct stream *in_s, int command)
+{
+ int rv;
+
+ LLOGLN(10, ("scard_process_msg: command 0x%4.4x", command));
rv = 0;
- switch (msg.mtype)
+ switch (command)
{
- case 0xF8: /* CMD_VERSION */
- rv = scard_process_version(&msg);
+ case 0x01: /* SCARD_ESTABLISH_CONTEXT */
+ LLOGLN(10, ("scard_process_msg: SCARD_ESTABLISH_CONTEXT"));
+ rv = scard_process_establish_context(con, in_s);
+ break;
+ case 0x02: /* SCARD_RELEASE_CONTEXT */
+ LLOGLN(10, ("scard_process_msg: SCARD_RELEASE_CONTEXT"));
+ rv = scard_process_release_context(con, in_s);
+ break;
+
+ case 0x03: /* SCARD_LIST_READERS */
+ LLOGLN(10, ("scard_process_msg: SCARD_LIST_READERS"));
+ rv = scard_process_list_readers(con, in_s);
+ break;
+
+ case 0x04: /* SCARD_CONNECT */
+ LLOGLN(10, ("scard_process_msg: SCARD_CONNECT"));
+ rv = scard_process_connect(con, in_s);
+ break;
+
+ case 0x05: /* SCARD_RECONNECT */
+ LLOGLN(0, ("scard_process_msg: SCARD_RECONNECT"));
+ break;
+
+ case 0x06: /* SCARD_DISCONNECT */
+ LLOGLN(10, ("scard_process_msg: SCARD_DISCONNECT"));
+ rv = scard_process_disconnect(con, in_s);
+ break;
+
+ case 0x07: /* SCARD_BEGIN_TRANSACTION */
+ LLOGLN(10, ("scard_process_msg: SCARD_BEGIN_TRANSACTION"));
+ rv = scard_process_begin_transaction(con, in_s);
+ break;
+
+ case 0x08: /* SCARD_END_TRANSACTION */
+ LLOGLN(10, ("scard_process_msg: SCARD_END_TRANSACTION"));
+ rv = scard_process_end_transaction(con, in_s);
+ break;
+
+ case 0x09: /* SCARD_TRANSMIT */
+ LLOGLN(10, ("scard_process_msg: SCARD_TRANSMIT"));
+ rv = scard_process_transmit(con, in_s);
+ break;
+
+ case 0x0A: /* SCARD_CONTROL */
+ LLOGLN(10, ("scard_process_msg: SCARD_CONTROL"));
+ rv = scard_process_control(con, in_s);
+ break;
+
+ case 0x0B: /* SCARD_STATUS */
+ LLOGLN(10, ("scard_process_msg: SCARD_STATUS"));
+ rv = scard_process_status(con, in_s);
+ break;
+
+ case 0x0C: /* SCARD_GET_STATUS_CHANGE */
+ LLOGLN(10, ("scard_process_msg: SCARD_GET_STATUS_CHANGE"));
+ rv = scard_process_get_status_change(con, in_s);
+ break;
+
+ case 0x0D: /* SCARD_CANCEL */
+ LLOGLN(0, ("scard_process_msg: SCARD_CANCEL"));
+ break;
+
+ case 0x0E: /* SCARD_CANCEL_TRANSACTION */
+ LLOGLN(0, ("scard_process_msg: SCARD_CANCEL_TRANSACTION"));
+ break;
+
+ case 0x0F: /* SCARD_GET_ATTRIB */
+ LLOGLN(0, ("scard_process_msg: SCARD_GET_ATTRIB"));
+ break;
+
+ case 0x10: /* SCARD_SET_ATTRIB */
+ LLOGLN(0, ("scard_process_msg: SCARD_SET_ATTRIB"));
+ break;
+
+ default:
+ LLOGLN(0, ("scard_process_msg: unknown mtype 0x%4.4x", command));
+ rv = 1;
break;
}
return rv;
@@ -194,24 +1079,28 @@ int DEFAULT_CC
my_pcsc_trans_data_in(struct trans *trans)
{
struct stream *s;
- int id;
int size;
+ int command;
int error;
- log_debug("my_pcsc_trans_data_in:");
-
+ LLOGLN(10, ("my_pcsc_trans_data_in:"));
if (trans == 0)
{
return 0;
}
-
if (trans != g_con)
{
return 1;
}
s = trans_get_in_s(trans);
- g_hexdump(s->p, 64);
- error = scard_process_msg(s);
+ in_uint32_le(s, size);
+ in_uint32_le(s, command);
+ LLOGLN(10, ("my_pcsc_trans_data_in: size %d command %d", size, command));
+ error = trans_force_read(trans, size);
+ if (error == 0)
+ {
+ error = scard_process_msg(g_con, s, command);
+ }
return error;
}
@@ -220,7 +1109,7 @@ my_pcsc_trans_data_in(struct trans *trans)
int DEFAULT_CC
my_pcsc_trans_conn_in(struct trans *trans, struct trans *new_trans)
{
- log_debug("my_pcsc_trans_conn_in:");
+ LLOGLN(10, ("my_pcsc_trans_conn_in:"));
if (trans == 0)
{
@@ -239,11 +1128,7 @@ my_pcsc_trans_conn_in(struct trans *trans, struct trans *new_trans)
g_con = new_trans;
g_con->trans_data_in = my_pcsc_trans_data_in;
- g_con->header_size = RXSHAREDSEGMENT_BYTES;
-
- log_debug("my_pcsc_trans_conn_in: sizeof sharedSegmentMsg is %d",
- sizeof(sharedSegmentMsg));
-
+ g_con->header_size = 8;
return 0;
}
@@ -252,33 +1137,39 @@ int APP_CC
scard_pcsc_init(void)
{
char port[256];
+ char *home;
+ int disp;
int error;
- log_debug("scard_pcsc_init:");
-
+ LLOGLN(0, ("scard_pcsc_init:"));
if (g_lis == 0)
{
g_lis = trans_create(2, 8192, 8192);
- g_snprintf(g_pcsc_directory, 255, "/tmp/.xrdp/pcsc%d", g_display_num);
- if (g_directory_exist(g_pcsc_directory))
+
+ //g_snprintf(g_pcsclite_ipc_dir, 255, "/tmp/.xrdp/pcsc%d", g_display_num);
+ home = g_getenv("HOME");
+ disp = g_display_num;
+ g_snprintf(g_pcsclite_ipc_dir, 255, "%s/.pcsc%d", home, disp);
+
+ if (g_directory_exist(g_pcsclite_ipc_dir))
{
- if (g_remove_dir(g_pcsc_directory) != 0)
+ if (g_remove_dir(g_pcsclite_ipc_dir) != 0)
{
- log_error("scard_pcsc_init: g_remove_dir failed");
+ LLOGLN(0, ("scard_pcsc_init: g_remove_dir failed"));
}
}
- if (g_create_dir(g_pcsc_directory) != 0)
+ if (!g_create_dir(g_pcsclite_ipc_dir))
{
- log_error("scard_pcsc_init: g_create_dir failed");
+ LLOGLN(0, ("scard_pcsc_init: g_create_dir failed"));
}
- g_chmod_hex(g_pcsc_directory, 0x1777);
- g_snprintf(port, 255, "%s/pcscd.comm", g_pcsc_directory);
+ g_chmod_hex(g_pcsclite_ipc_dir, 0x1777);
+ g_snprintf(port, 255, "%s/pcscd.comm", g_pcsclite_ipc_dir);
g_lis->trans_conn_in = my_pcsc_trans_conn_in;
error = trans_listen(g_lis, port);
if (error != 0)
{
- log_error("scard_pcsc_init: trans_listen failed for port %s",
- port);
+ LLOGLN(0, ("scard_pcsc_init: trans_listen failed for port %s",
+ port));
return 1;
}
}
@@ -289,17 +1180,20 @@ scard_pcsc_init(void)
int APP_CC
scard_pcsc_deinit(void)
{
- log_debug("scard_pcsc_deinit:");
-
+ LLOGLN(0, ("scard_pcsc_deinit:"));
if (g_lis != 0)
{
trans_delete(g_lis);
g_lis = 0;
- if (g_remove_dir(g_pcsc_directory) != 0)
+
+ g_file_close(g_pub_file_fd);
+ g_pub_file_fd = 0;
+
+ if (g_remove_dir(g_pcsclite_ipc_dir) != 0)
{
- log_error("scard_pcsc_deinit: g_remove_dir failed");
+ LLOGLN(0, ("scard_pcsc_deinit: g_remove_dir failed"));
}
- g_pcsc_directory[0] = 0;
+ g_pcsclite_ipc_dir[0] = 0;
}
return 0;
}
diff --git a/sesman/chansrv/smartcard_pcsc.h b/sesman/chansrv/smartcard_pcsc.h
index a97a70d3..bd5b9090 100644
--- a/sesman/chansrv/smartcard_pcsc.h
+++ b/sesman/chansrv/smartcard_pcsc.h
@@ -24,13 +24,66 @@
#ifndef _SMARTCARD_PCSC_H
#define _SMARTCARD_PCSC_H
-int APP_CC
-scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout);
-int APP_CC
-scard_pcsc_check_wait_objs(void);
-int APP_CC
-scard_pcsc_init(void);
-int APP_CC
-scard_pcsc_deinit(void);
+int APP_CC scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout);
+int APP_CC scard_pcsc_check_wait_objs(void);
+int APP_CC scard_pcsc_init(void);
+int APP_CC scard_pcsc_deinit(void);
+int APP_CC scard_function_establish_context_return(struct trans *con,
+ struct stream *in_s,
+ int len);
+int APP_CC scard_function_release_context_return(struct trans *con,
+ struct stream *in_s,
+ int len);
+int APP_CC scard_function_list_readers_return(struct trans *con,
+ struct stream *in_s,
+ int len);
+
+int APP_CC scard_function_transmit_return(struct trans *con,
+ struct stream *in_s,
+ int len);
+
+int APP_CC scard_function_control_return(struct trans *con,
+ struct stream *in_s,
+ int len);
+
+int APP_CC scard_function_get_status_change_return(struct trans *con,
+ struct stream *in_s,
+ int len);
+
+int APP_CC scard_function_connect_return(struct trans *con,
+ struct stream *in_s,
+ int len);
+
+int APP_CC scard_function_status_return(struct trans *con,
+ struct stream *in_s,
+ int len);
+
+int APP_CC scard_function_begin_transaction_return(struct trans *con,
+ struct stream *in_s,
+ int len);
+
+int APP_CC scard_function_end_transaction_return(struct trans *con,
+ struct stream *in_s,
+ int len);
+
+int APP_CC scard_function_is_context_valid_return(struct trans *con,
+ struct stream *in_s,
+ int len);
+
+int APP_CC scard_function_reconnect_return(struct trans *con,
+ struct stream *in_s,
+ int len);
+
+int APP_CC scard_function_disconnect_return(struct trans *con,
+ struct stream *in_s,
+ int len);
+
+int APP_CC scard_function_cancel_return(struct trans *con,
+ struct stream *in_s,
+ int len);
+
+int APP_CC scard_function_get_attrib_return(struct trans *con,
+ struct stream *in_s,
+ int len);
#endif /* end #ifndef _SMARTCARD_PCSC_H */
diff --git a/sesman/chansrv/sound.c b/sesman/chansrv/sound.c
index 9ee3c8c3..2e85f1f2 100644
--- a/sesman/chansrv/sound.c
+++ b/sesman/chansrv/sound.c
@@ -551,7 +551,8 @@ sound_init(void)
LOG(0, ("sound_init:"));
sound_send_server_formats();
- g_audio_l_trans = trans_create(2, 128 * 1024, 8192);
+ g_audio_l_trans = trans_create(TRANS_MODE_UNIX, 128 * 1024, 8192);
+ g_audio_l_trans->is_term = g_is_term;
g_snprintf(port, 255, CHANSRV_PORT_STR, g_display_num);
g_audio_l_trans->trans_conn_in = sound_trans_audio_conn_in;
error = trans_listen(g_audio_l_trans, port);
diff --git a/sesman/chansrv/xcommon.c b/sesman/chansrv/xcommon.c
index c5a91cae..919bc41b 100644
--- a/sesman/chansrv/xcommon.c
+++ b/sesman/chansrv/xcommon.c
@@ -25,8 +25,10 @@
#include "clipboard.h"
#include "rail.h"
+/*
#undef LOG_LEVEL
#define LOG_LEVEL 11
+*/
extern int g_clip_up; /* in clipboard.c */
@@ -40,6 +42,9 @@ int g_screen_num = 0;
Window g_root_window = 0;
Atom g_wm_delete_window_atom = 0;
Atom g_wm_protocols_atom = 0;
+Atom g_utf8_string = 0;
+Atom g_net_wm_name = 0;
+Atom g_wm_state = 0;
/*****************************************************************************/
static int DEFAULT_CC
@@ -117,7 +122,10 @@ xcommon_init(void)
g_wm_delete_window_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", 0);
g_wm_protocols_atom = XInternAtom(g_display, "WM_PROTOCOLS", 0);
-
+ g_utf8_string = XInternAtom(g_display, "UTF8_STRING", 0);
+ g_net_wm_name = XInternAtom(g_display, "_NET_WM_NAME", 0);
+ g_wm_state = XInternAtom(g_display, "WM_STATE", 0);
+
return 0;
}
diff --git a/sesman/config.c b/sesman/config.c
index c7c3de24..877a949c 100644
--- a/sesman/config.c
+++ b/sesman/config.c
@@ -130,7 +130,7 @@ config_read_globals(int file, struct config_sesman *cf, struct list *param_n,
}
else if (0 == g_strcasecmp(buf, SESMAN_CFG_ENABLE_USERWM))
{
- cf->enable_user_wm = text2bool((char *)list_get_item(param_v, i));
+ cf->enable_user_wm = g_text2bool((char *)list_get_item(param_v, i));
}
else if (0 == g_strcasecmp(buf, SESMAN_CFG_PORT))
{
@@ -212,7 +212,7 @@ config_read_logging(int file, struct log_config* lc, struct list* param_n,
}
if (0 == g_strcasecmp(buf, SESMAN_CFG_LOG_ENABLE_SYSLOG))
{
- lc->enable_syslog = text2bool((char*)list_get_item(param_v, i));
+ lc->enable_syslog = g_text2bool((char*)list_get_item(param_v, i));
}
if (0 == g_strcasecmp(buf, SESMAN_CFG_LOG_SYSLOG_LEVEL))
{
@@ -261,7 +261,7 @@ config_read_security(int file, struct config_security *sc,
if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_ALLOW_ROOT))
{
- sc->allow_root = text2bool((char *)list_get_item(param_v, i));
+ sc->allow_root = g_text2bool((char *)list_get_item(param_v, i));
}
if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_LOGIN_RETRY))
@@ -288,7 +288,7 @@ config_read_security(int file, struct config_security *sc,
}
if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_ALWAYSGROUPCHECK))
{
- sc->ts_always_group_check = text2bool((char *)list_get_item(param_v, i));
+ sc->ts_always_group_check = g_text2bool((char *)list_get_item(param_v, i));
}
}
@@ -355,7 +355,7 @@ config_read_sessions(int file, struct config_sessions *se, struct list *param_n,
if (0 == g_strcasecmp(buf, SESMAN_CFG_SESS_KILL_DISC))
{
- se->kill_disconnected = text2bool((char *)list_get_item(param_v, i));
+ se->kill_disconnected = g_text2bool((char *)list_get_item(param_v, i));
}
if (0 == g_strcasecmp(buf, SESMAN_CFG_SESS_IDLE_LIMIT))
diff --git a/sesman/sesman.ini b/sesman/sesman.ini
index 571e063b..02fef5ba 100644
--- a/sesman/sesman.ini
+++ b/sesman/sesman.ini
@@ -17,8 +17,13 @@ AlwaysGroupCheck = false
[Sessions]
X11DisplayOffset=10
MaxSessions=10
+# if 1, true, or yes, kill session after 60 seconds
KillDisconnected=0
+# if not zero, the seconds without mouse or keyboard input before disconnect
+# not complete yet
IdleTimeLimit=0
+# if not zero, the seconds before a disconnected session is killed
+# min 60 seconds
DisconnectedTimeLimit=0
[Logging]
diff --git a/sesman/session.c b/sesman/session.c
index 888604da..a5932736 100644
--- a/sesman/session.c
+++ b/sesman/session.c
@@ -62,11 +62,11 @@ static int g_sync_cmd;
char *APP_CC
dumpItemsToString(struct list *self, char *outstr, int len)
{
- g_memset(outstr, 0, len);
int index;
tbus item;
int totalLen = 0;
+ g_memset(outstr, 0, len);
if (self->count == 0)
{
g_writeln("List is empty");
@@ -385,6 +385,7 @@ session_start_fork(int width, int height, int bpp, char *username,
int display = 0;
int pid = 0;
int wmpid = 0;
+ int pampid = 0;
int xpid = 0;
int i = 0;
char geometry[32];
@@ -453,99 +454,105 @@ session_start_fork(int width, int height, int bpp, char *username,
{
g_tcp_close(g_sck);
g_tcp_close(g_thread_sck);
- auth_start_session(data, display);
g_sprintf(geometry, "%dx%d", width, height);
g_sprintf(depth, "%d", bpp);
g_sprintf(screen, ":%d", display);
wmpid = g_fork();
-
if (wmpid == -1)
{
}
else if (wmpid == 0) /* child (child sesman) xserver */
{
wait_for_xserver(display);
- env_set_user(username, 0, display);
-
- if (x_server_running(display))
+ auth_start_session(data, display);
+ pampid = g_fork();
+ if (pampid == -1)
{
- auth_set_env(data);
-
- if (directory != 0)
+ }
+ else if (pampid == 0) /* child: X11/client */
+ {
+ env_set_user(username, 0, display);
+ if (x_server_running(display))
{
- if (directory[0] != 0)
+ auth_set_env(data);
+ if (directory != 0)
{
- g_set_current_dir(directory);
+ if (directory[0] != 0)
+ {
+ g_set_current_dir(directory);
+ }
}
- }
-
- if (program != 0)
- {
- if (program[0] != 0)
+ if (program != 0)
{
- g_execlp3(program, program, 0);
- log_message(LOG_LEVEL_ALWAYS,
- "error starting program %s for user %s - pid %d",
- program, username, g_getpid());
+ if (program[0] != 0)
+ {
+ g_execlp3(program, program, 0);
+ log_message(LOG_LEVEL_ALWAYS,
+ "error starting program %s for user %s - pid %d",
+ program, username, g_getpid());
+ }
}
- }
-
- /* 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))
+ /* try to execute user window manager if enabled */
+ if (g_cfg->enable_user_wm)
{
- g_execlp3(text, g_cfg->user_wm, 0);
- log_message(LOG_LEVEL_ALWAYS, "error starting user "
- "wm for user %s - pid %d", username, g_getpid());
- /* logging parameters */
- log_message(LOG_LEVEL_DEBUG, "errno: %d, "
- "description: %s", errno, g_get_strerror());
- log_message(LOG_LEVEL_DEBUG, "execlp3 parameter "
- "list:");
- log_message(LOG_LEVEL_DEBUG, " argv[0] = %s",
- text);
- log_message(LOG_LEVEL_DEBUG, " argv[1] = %s",
- g_cfg->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(LOG_LEVEL_ALWAYS, "error starting user "
+ "wm for user %s - pid %d", username, g_getpid());
+ /* logging parameters */
+ log_message(LOG_LEVEL_DEBUG, "errno: %d, "
+ "description: %s", errno, g_get_strerror());
+ log_message(LOG_LEVEL_DEBUG, "execlp3 parameter "
+ "list:");
+ log_message(LOG_LEVEL_DEBUG, " argv[0] = %s",
+ text);
+ log_message(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(LOG_LEVEL_ALWAYS, "error starting default "
+ "wm for user %s - pid %d", username, g_getpid());
+ /* logging parameters */
+ log_message(LOG_LEVEL_DEBUG, "errno: %d, description: "
+ "%s", errno, g_get_strerror());
+ log_message(LOG_LEVEL_DEBUG, "execlp3 parameter list:");
+ log_message(LOG_LEVEL_DEBUG, " argv[0] = %s",
+ text);
+ log_message(LOG_LEVEL_DEBUG, " argv[1] = %s",
+ g_cfg->default_wm);
+
+ /* still a problem starting window manager just start xterm */
+ g_execlp3("xterm", "xterm", 0);
+
+ /* should not get here */
+ log_message(LOG_LEVEL_ALWAYS, "error starting xterm "
+ "for user %s - pid %d", username, g_getpid());
+ /* logging parameters */
+ log_message(LOG_LEVEL_DEBUG, "errno: %d, description: "
+ "%s", errno, g_get_strerror());
+ }
+ else
+ {
+ log_message(LOG_LEVEL_ERROR, "another Xserver might "
+ "already be active on display %d - see log", display);
}
- /* 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( LOG_LEVEL_ALWAYS, "error starting default "
- "wm for user %s - pid %d", username, g_getpid());
- /* logging parameters */
- log_message( LOG_LEVEL_DEBUG, "errno: %d, description: "
- "%s", errno, g_get_strerror());
- log_message(LOG_LEVEL_DEBUG, "execlp3 parameter list:");
- log_message(LOG_LEVEL_DEBUG, " argv[0] = %s",
- text);
- log_message(LOG_LEVEL_DEBUG, " argv[1] = %s",
- g_cfg->default_wm);
-
- /* still a problem starting window manager just start xterm */
- g_execlp3("xterm", "xterm", 0);
-
- /* should not get here */
- log_message(LOG_LEVEL_ALWAYS, "error starting xterm "
- "for user %s - pid %d", username, g_getpid());
- /* logging parameters */
- log_message(LOG_LEVEL_DEBUG, "errno: %d, description: "
- "%s", errno, g_get_strerror());
+ log_message(LOG_LEVEL_DEBUG, "aborting connection...");
+ g_exit(0);
}
else
{
- log_message(LOG_LEVEL_ERROR, "another Xserver might "
- "already be active on display %d - see log", display);
+ g_waitpid(pampid);
+ auth_stop_session(data);
+ g_exit(0);
}
-
- log_message(LOG_LEVEL_DEBUG, "aborting connection...");
- g_exit(0);
}
else /* parent (child sesman) */
{
@@ -559,6 +566,13 @@ session_start_fork(int width, int height, int bpp, char *username,
env_set_user(username, passwd_file, display);
env_check_password_file(passwd_file, password);
+ g_snprintf(text, 255, "%d", g_cfg->sess.max_idle_time);
+ g_setenv("XRDP_SESMAN_MAX_IDLE_TIME", text, 1);
+ g_snprintf(text, 255, "%d", g_cfg->sess.max_disc_time);
+ g_setenv("XRDP_SESMAN_MAX_DISC_TIME", text, 1);
+ g_snprintf(text, 255, "%d", g_cfg->sess.kill_disconnected);
+ g_setenv("XRDP_SESMAN_KILL_DISCONNECTED", text, 1);
+
if (type == SESMAN_SESSION_TYPE_XVNC)
{
xserver_params = list_create();
diff --git a/sesman/verify_user_kerberos.c b/sesman/verify_user_kerberos.c
index a6480f56..bb7ba3d2 100644
--- a/sesman/verify_user_kerberos.c
+++ b/sesman/verify_user_kerberos.c
@@ -431,6 +431,14 @@ auth_start_session(void)
}
/******************************************************************************/
+/* returns error */
+int DEFAULT_CC
+auth_stop_session(long in_val)
+{
+ return 0;
+}
+
+/******************************************************************************/
int DEFAULT_CC
auth_end(void)
{
diff --git a/sesman/verify_user_pam.c b/sesman/verify_user_pam.c
index e53f72d5..4d73f85d 100644
--- a/sesman/verify_user_pam.c
+++ b/sesman/verify_user_pam.c
@@ -203,6 +203,26 @@ auth_start_session(long in_val, int in_display)
/******************************************************************************/
/* returns error */
+int DEFAULT_CC
+auth_stop_session(long in_val)
+{
+ struct t_auth_info *auth_info;
+ int error;
+
+ auth_info = (struct t_auth_info *)in_val;
+ error = pam_close_session(auth_info->ph, 0);
+ if (error != PAM_SUCCESS)
+ {
+ g_printf("pam_close_session failed: %s\r\n",
+ pam_strerror(auth_info->ph, error));
+ return 1;
+ }
+ auth_info->session_opened = 0;
+ return 0;
+}
+
+/******************************************************************************/
+/* returns error */
/* cleanup */
int DEFAULT_CC
auth_end(long in_val)
diff --git a/sesman/verify_user_pam_userpass.c b/sesman/verify_user_pam_userpass.c
index 7f31176e..b3d4de73 100644
--- a/sesman/verify_user_pam_userpass.c
+++ b/sesman/verify_user_pam_userpass.c
@@ -91,6 +91,14 @@ auth_start_session(void)
}
/******************************************************************************/
+/* returns error */
+int DEFAULT_CC
+auth_stop_session(long in_val)
+{
+ return 0;
+}
+
+/******************************************************************************/
int DEFAULT_CC
auth_end(void)
{
diff --git a/tcutils/README.txt b/tcutils/README.txt
new file mode 100644
index 00000000..de75f1b2
--- /dev/null
+++ b/tcutils/README.txt
@@ -0,0 +1,29 @@
+A QT based utility program for thinclients using xrdp and NeutrinoRDP
+
+This program sends commands to NeutrinoRDP to do something
+useful on the client end (such as unmounting a USB drive,
+or powering down the client)
+
+Required packages to build tcutils:
+-----------------------------------
+libqt4-gui
+qt4-dev-tools
+
+to build tcutils:
+-----------------
+qmake
+make
+
+To run tcutils:
+---------------
+include xrdpapi/.libs in your LD_LIBRARY_PATH
+
+Example:
+--------
+export LD_LIBRARY_PATH=../xrdpapi/.libs
+run tcutils inside the xfreerdp session
+
+this is how we run xfreerdp:
+----------------------------
+./xfreerdp --sec rdp --plugin tcutils 192.168.2.149
+
diff --git a/tcutils/main.cpp b/tcutils/main.cpp
new file mode 100644
index 00000000..d951345f
--- /dev/null
+++ b/tcutils/main.cpp
@@ -0,0 +1,11 @@
+#include <QtGui/QApplication>
+#include "mainwindow.h"
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+ MainWindow w;
+ w.show();
+
+ return a.exec();
+}
diff --git a/tcutils/mainwindow.cpp b/tcutils/mainwindow.cpp
new file mode 100644
index 00000000..8cc0a988
--- /dev/null
+++ b/tcutils/mainwindow.cpp
@@ -0,0 +1,234 @@
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+
+MainWindow::MainWindow(QWidget *parent) :
+ QMainWindow(parent),
+ ui(new Ui::MainWindow)
+{
+ ui->setupUi(this);
+
+ wtsChannel = NULL;
+ okToQuit = false;
+ savedGeometry = this->geometry();
+
+ /* setup tab to unmount drives */
+ ui->tabWidget->setTabText(0, "Unmount drives");
+ connect(ui->btnRefresh, SIGNAL(clicked()), this, SLOT(onBtnRefreshClicked()));
+ connect(ui->btnUnmount, SIGNAL(clicked()), this, SLOT(onBtnUnmountClicked()));
+
+ ui->tabWidget->setTabText(1, "");
+ if (initWtsChannel())
+ {
+ okToQuit = true;
+ QTimer::singleShot(10, qApp, SLOT(quit()));
+ return;
+ }
+ setupSystemTray();
+
+ /* set up status bar to display messages */
+ statusBar = new QStatusBar;
+ this->setStatusBar(statusBar);
+ setStatusMsg("Connected to client");
+}
+
+MainWindow::~MainWindow()
+{
+ delete ui;
+}
+
+void MainWindow::setupSystemTray()
+{
+ trayMenu = new QMenu(this);
+ trayMenu->addAction("Launch Thinclient Utils", this, SLOT(onActionLaunch()));
+ trayMenu->addSeparator();
+ trayMenu->addAction("Quit", this, SLOT(onActionQuit()));
+
+ trayIcon = new QSystemTrayIcon;
+ trayIcon->setContextMenu(trayMenu);
+ trayIcon->setIcon(QIcon(":/images/resources/images/tools.gif"));
+
+ trayIcon->show();
+
+ trayIcon->showMessage("TCutils", "Click on the tcutils icon to launch tcutils",
+ QSystemTrayIcon::Information, 3000);
+
+ connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
+ this, SLOT(onSystemTrayClicked(QSystemTrayIcon::ActivationReason)));
+}
+
+/**
+ *
+ *****************************************************************************/
+
+int MainWindow::initWtsChannel()
+{
+ /* init the channel just once */
+ if (wtsChannel)
+ return 0;
+
+ /* open a WTS channel and connect to remote client */
+ wtsChannel = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, "tcutils", 0);
+ if (wtsChannel == NULL)
+ {
+ QMessageBox::information(this, "Open virtual channel", "Error "
+ "connecting to remote client. This program "
+ "can only be used when connected via "
+ "NeutrinoRDP.\n\nClick ok to close this "
+ "application");
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ *
+ *****************************************************************************/
+
+int MainWindow::deinitWtsChannel()
+{
+ if (!wtsChannel)
+ return -1;
+
+ WTSVirtualChannelClose(wtsChannel);
+ return 0;
+}
+
+/**
+ * Display a msg on the status bar
+ *
+ * @param msg message to display in status bar
+ *****************************************************************************/
+
+void MainWindow::setStatusMsg(QString msg)
+{
+ statusBar->showMessage(msg, 30000);
+}
+
+/**
+ *
+ *****************************************************************************/
+
+void MainWindow::closeEvent(QCloseEvent *event)
+{
+ if (!okToQuit)
+ {
+ savedGeometry = this->geometry();
+ this->hide();
+ event->ignore();
+ return;
+ }
+
+ if (wtsChannel)
+ deinitWtsChannel();
+
+ event->accept();
+}
+
+/******************************************************************************
+** **
+** slots go here **
+** **
+******************************************************************************/
+#if 1
+void MainWindow::onBtnRefreshClicked()
+{
+ int i;
+
+ /* clear drive list */
+ if (itemList.count())
+ {
+ for (i = 0; i < itemList.count(); i++)
+ ui->listWidget->removeItemWidget(itemList.at(i));
+
+ itemList.clear();
+ }
+ ui->listWidget->clear();
+
+ if (Utils::getMountList(wtsChannel, &itemList))
+ {
+ QMessageBox::information(this, "Get device list", "\nError getting "
+ "device list from client");
+ return;
+ }
+
+ if (itemList.count() == 0)
+ {
+ QMessageBox::information(this, "Get device list",
+ "\nNo devices found!");
+ return;
+ }
+
+ /* add mount point to list widget */
+ for (i = 0; i < itemList.count(); i++)
+ ui->listWidget->insertItem(i, itemList.at(i));
+}
+#else
+void MainWindow::onBtnRefreshClicked()
+{
+ QListWidgetItem *item;
+ int i;
+ int j;
+
+ /* clear drive list */
+ if (itemList.count())
+ {
+ for (i = 0; i < itemList.count(); i++)
+ ui->listWidget->removeItemWidget(itemList.at(i));
+
+ itemList.clear();
+ }
+ ui->listWidget->clear();
+
+ QDir dir(QDir::homePath() + "/xrdp_client");
+ QStringList sl = dir.entryList();
+
+ for (i = 0, j = 0; i < sl.count(); i++)
+ {
+ /* skip files starting with . */
+ if (sl.at(i).startsWith("."))
+ continue;
+
+ /* add mount point to list widget */
+ item = new QListWidgetItem;
+ item->setText(sl.at(i));
+ ui->listWidget->insertItem(j++, item);
+ itemList.append(item);
+ }
+}
+#endif
+
+void MainWindow::onBtnUnmountClicked()
+{
+ QListWidgetItem *item = ui->listWidget->currentItem();
+
+ if (!item)
+ {
+ QMessageBox::information(this, "Unmount device", "\nNo device selected. "
+ "You must select a device to unmount");
+ return;
+ }
+
+ if (Utils::unmountDevice(wtsChannel, item->text(), statusBar) == 0)
+ {
+ delete ui->listWidget->takeItem(itemList.indexOf(item));
+ itemList.removeOne(item);
+ }
+}
+
+void MainWindow::onActionQuit()
+{
+ okToQuit = true;
+ this->close();
+}
+
+void MainWindow::onActionLaunch()
+{
+ this->show();
+ this->setGeometry(savedGeometry);
+}
+
+void MainWindow::onSystemTrayClicked(QSystemTrayIcon::ActivationReason)
+{
+ trayMenu->popup(QCursor::pos());
+}
diff --git a/tcutils/mainwindow.h b/tcutils/mainwindow.h
new file mode 100644
index 00000000..1639522f
--- /dev/null
+++ b/tcutils/mainwindow.h
@@ -0,0 +1,57 @@
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QMainWindow>
+#include <xrdpapi.h>
+#include <QSystemTrayIcon>
+#include <QMenu>
+#include <QCloseEvent>
+#include <QFileDialog>
+#include <QDir>
+#include <QListWidgetItem>
+#include <QList>
+#include <QMessageBox>
+#include <QTimer>
+#include <QStatusBar>
+//#include <QDebug>
+
+#include "utils.h"
+
+namespace Ui {
+class MainWindow;
+}
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindow(QWidget *parent = 0);
+ ~MainWindow();
+
+private:
+ Ui::MainWindow *ui;
+ void *wtsChannel;
+ QSystemTrayIcon *trayIcon;
+ QMenu *trayMenu;
+ bool okToQuit;
+ QRect savedGeometry;
+ QStatusBar *statusBar;
+
+ QList<QListWidgetItem *> itemList;
+
+ void setupSystemTray();
+ int initWtsChannel();
+ int deinitWtsChannel();
+ void setStatusMsg(QString msg);
+ void closeEvent(QCloseEvent * event);
+
+private slots:
+ void onBtnRefreshClicked();
+ void onBtnUnmountClicked();
+ void onActionQuit();
+ void onActionLaunch();
+ void onSystemTrayClicked(QSystemTrayIcon::ActivationReason);
+};
+
+#endif // MAINWINDOW_H
diff --git a/tcutils/mainwindow.ui b/tcutils/mainwindow.ui
new file mode 100644
index 00000000..802d01a3
--- /dev/null
+++ b/tcutils/mainwindow.ui
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>541</width>
+ <height>355</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>TC Utils</string>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>511</width>
+ <height>291</height>
+ </rect>
+ </property>
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tabUnmount">
+ <attribute name="title">
+ <string>Tab 1</string>
+ </attribute>
+ <widget class="QListWidget" name="listWidget">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>321</width>
+ <height>221</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QPushButton" name="btnUnmount">
+ <property name="geometry">
+ <rect>
+ <x>350</x>
+ <y>60</y>
+ <width>141</width>
+ <height>27</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Unmount device</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" name="btnRefresh">
+ <property name="geometry">
+ <rect>
+ <x>350</x>
+ <y>10</y>
+ <width>141</width>
+ <height>27</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Get device list</string>
+ </property>
+ </widget>
+ </widget>
+ <widget class="QWidget" name="tab_2">
+ <attribute name="title">
+ <string>Tab 2</string>
+ </attribute>
+ </widget>
+ </widget>
+ </widget>
+ <widget class="QMenuBar" name="menuBar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>541</width>
+ <height>25</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QToolBar" name="mainToolBar">
+ <attribute name="toolBarArea">
+ <enum>TopToolBarArea</enum>
+ </attribute>
+ <attribute name="toolBarBreak">
+ <bool>false</bool>
+ </attribute>
+ </widget>
+ <widget class="QStatusBar" name="statusBar"/>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tcutils/moc_mainwindow.cpp b/tcutils/moc_mainwindow.cpp
new file mode 100644
index 00000000..85806598
--- /dev/null
+++ b/tcutils/moc_mainwindow.cpp
@@ -0,0 +1,104 @@
+/****************************************************************************
+** Meta object code from reading C++ file 'mainwindow.h'
+**
+** Created: Sun Aug 25 15:11:44 2013
+** by: The Qt Meta Object Compiler version 63 (Qt 4.8.1)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#include "mainwindow.h"
+#if !defined(Q_MOC_OUTPUT_REVISION)
+#error "The header file 'mainwindow.h' doesn't include <QObject>."
+#elif Q_MOC_OUTPUT_REVISION != 63
+#error "This file was generated using the moc from 4.8.1. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+QT_BEGIN_MOC_NAMESPACE
+static const uint qt_meta_data_MainWindow[] = {
+
+ // content:
+ 6, // revision
+ 0, // classname
+ 0, 0, // classinfo
+ 5, 14, // methods
+ 0, 0, // properties
+ 0, 0, // enums/sets
+ 0, 0, // constructors
+ 0, // flags
+ 0, // signalCount
+
+ // slots: signature, parameters, type, tag, flags
+ 12, 11, 11, 11, 0x08,
+ 34, 11, 11, 11, 0x08,
+ 56, 11, 11, 11, 0x08,
+ 71, 11, 11, 11, 0x08,
+ 88, 11, 11, 11, 0x08,
+
+ 0 // eod
+};
+
+static const char qt_meta_stringdata_MainWindow[] = {
+ "MainWindow\0\0onBtnRefreshClicked()\0"
+ "onBtnUnmountClicked()\0onActionQuit()\0"
+ "onActionLaunch()\0"
+ "onSystemTrayClicked(QSystemTrayIcon::ActivationReason)\0"
+};
+
+void MainWindow::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
+{
+ if (_c == QMetaObject::InvokeMetaMethod) {
+ Q_ASSERT(staticMetaObject.cast(_o));
+ MainWindow *_t = static_cast<MainWindow *>(_o);
+ switch (_id) {
+ case 0: _t->onBtnRefreshClicked(); break;
+ case 1: _t->onBtnUnmountClicked(); break;
+ case 2: _t->onActionQuit(); break;
+ case 3: _t->onActionLaunch(); break;
+ case 4: _t->onSystemTrayClicked((*reinterpret_cast< QSystemTrayIcon::ActivationReason(*)>(_a[1]))); break;
+ default: ;
+ }
+ }
+}
+
+const QMetaObjectExtraData MainWindow::staticMetaObjectExtraData = {
+ 0, qt_static_metacall
+};
+
+const QMetaObject MainWindow::staticMetaObject = {
+ { &QMainWindow::staticMetaObject, qt_meta_stringdata_MainWindow,
+ qt_meta_data_MainWindow, &staticMetaObjectExtraData }
+};
+
+#ifdef Q_NO_DATA_RELOCATION
+const QMetaObject &MainWindow::getStaticMetaObject() { return staticMetaObject; }
+#endif //Q_NO_DATA_RELOCATION
+
+const QMetaObject *MainWindow::metaObject() const
+{
+ return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
+}
+
+void *MainWindow::qt_metacast(const char *_clname)
+{
+ if (!_clname) return 0;
+ if (!strcmp(_clname, qt_meta_stringdata_MainWindow))
+ return static_cast<void*>(const_cast< MainWindow*>(this));
+ return QMainWindow::qt_metacast(_clname);
+}
+
+int MainWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+ _id = QMainWindow::qt_metacall(_c, _id, _a);
+ if (_id < 0)
+ return _id;
+ if (_c == QMetaObject::InvokeMetaMethod) {
+ if (_id < 5)
+ qt_static_metacall(this, _c, _id, _a);
+ _id -= 5;
+ }
+ return _id;
+}
+QT_END_MOC_NAMESPACE
diff --git a/tcutils/qrc_resources.cpp b/tcutils/qrc_resources.cpp
new file mode 100644
index 00000000..3f2366cb
--- /dev/null
+++ b/tcutils/qrc_resources.cpp
@@ -0,0 +1,1191 @@
+/****************************************************************************
+** Resource object code
+**
+** Created: Sun Aug 25 15:11:45 2013
+** by: The Resource Compiler for Qt version 4.8.1
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#include <QtCore/qglobal.h>
+
+static const unsigned char qt_resource_data[] = {
+ // /home/lk/projects/jtech/nlabs_xrdp_tcutils/tcutils/resources/images/tools.gif
+ 0x0,0x0,0x45,0x65,
+ 0x47,
+ 0x49,0x46,0x38,0x39,0x61,0xab,0x0,0xb7,0x0,0xe7,0xff,0x0,0x22,0x26,0x9a,0x18,
+ 0x2a,0x95,0x24,0x29,0x8f,0x1d,0x2e,0x92,0x1d,0x32,0x71,0x23,0x33,0x64,0x15,0x37,
+ 0x6c,0x16,0x34,0x96,0x22,0x31,0x96,0x1f,0x37,0x65,0x25,0x3b,0x5a,0x28,0x35,0x93,
+ 0x1d,0x38,0x9a,0x2c,0x38,0x70,0x1f,0x39,0x95,0x24,0x3a,0x87,0x14,0x3d,0x9f,0x15,
+ 0x3e,0x99,0x2a,0x40,0x65,0x24,0x3f,0x81,0x1f,0x41,0x7d,0x21,0x42,0x6e,0x25,0x3d,
+ 0x99,0x29,0x40,0x70,0x2c,0x3e,0x7b,0x1b,0x41,0x9c,0x24,0x42,0x78,0xd,0x46,0x99,
+ 0x10,0x46,0xa0,0x29,0x40,0x97,0x1f,0x43,0x9e,0x1f,0x44,0x99,0x2b,0x40,0x9e,0x1e,
+ 0x45,0x93,0x24,0x44,0x8c,0x21,0x43,0xa6,0x1e,0x49,0x84,0x23,0x45,0xa1,0x16,0x49,
+ 0xa3,0x29,0x43,0xab,0x2a,0x48,0x77,0x22,0x49,0x8a,0x19,0x4b,0x99,0x26,0x47,0x9d,
+ 0x30,0x45,0x95,0x2b,0x49,0x7f,0x1a,0x4b,0x9f,0x1c,0x4a,0xac,0x3d,0x47,0x6f,0x28,
+ 0x48,0xa4,0x31,0x48,0x8a,0x28,0x49,0x9f,0x2e,0x4a,0x87,0x1c,0x4e,0x95,0x1d,0x4c,
+ 0xa7,0x29,0x4a,0x98,0x27,0x4e,0x79,0x1e,0x4d,0xa1,0x2a,0x4a,0xa0,0x1d,0x50,0x90,
+ 0x11,0x51,0xab,0x25,0x4f,0x84,0x37,0x4a,0x82,0x2c,0x4f,0x73,0x2c,0x4a,0xa7,0x12,
+ 0x52,0xa5,0x11,0x53,0x9f,0x21,0x4e,0xa3,0x20,0x4f,0x9d,0x2a,0x4d,0x95,0x2a,0x4e,
+ 0x90,0x22,0x4f,0xa4,0x33,0x4e,0x7d,0x2d,0x4d,0x9c,0x29,0x50,0x8c,0x32,0x4f,0x86,
+ 0x23,0x51,0x9f,0x25,0x50,0xa5,0x30,0x4c,0xb1,0x16,0x56,0x9c,0x30,0x4e,0xa4,0x18,
+ 0x55,0xa8,0x30,0x4f,0x9f,0x26,0x50,0xb3,0x26,0x52,0xa1,0x1a,0x54,0xb5,0x1a,0x56,
+ 0xa3,0x28,0x51,0xad,0x1a,0x55,0xaf,0x26,0x54,0x9b,0x9,0x5b,0xad,0x25,0x55,0x96,
+ 0x31,0x51,0x9b,0x28,0x53,0xa2,0x29,0x53,0xa8,0x29,0x54,0xa3,0x38,0x53,0x83,0x1e,
+ 0x57,0xab,0x34,0x53,0x96,0x2a,0x55,0xa4,0x31,0x55,0x91,0x1e,0x59,0xa6,0x1e,0x5a,
+ 0xa0,0x2c,0x55,0xab,0x3c,0x56,0x75,0x1e,0x5b,0x9c,0x2c,0x56,0xa5,0x2a,0x58,0x9a,
+ 0x22,0x58,0xb3,0x32,0x58,0x84,0x22,0x59,0xad,0x3c,0x55,0x8d,0x2c,0x58,0xa0,0x30,
+ 0x55,0xb2,0x2e,0x57,0xa6,0x2a,0x5a,0x95,0x22,0x5b,0xa8,0x32,0x59,0x8f,0x46,0x55,
+ 0x7d,0x3a,0x54,0xac,0x47,0x53,0x9a,0x3c,0x59,0x7f,0x2e,0x5b,0x9d,0x32,0x59,0xaf,
+ 0x3a,0x58,0xa3,0x2b,0x5a,0xbe,0x3a,0x59,0x9c,0x41,0x59,0x89,0x46,0x55,0xa6,0x38,
+ 0x5b,0x98,0x26,0x60,0xa7,0x33,0x5d,0xa5,0x2a,0x60,0xaf,0x2c,0x5f,0xb4,0x39,0x5c,
+ 0xba,0x30,0x63,0xa1,0x37,0x62,0xa5,0x40,0x61,0x9f,0x3e,0x60,0xb0,0x32,0x63,0xb8,
+ 0x40,0x63,0x90,0x40,0x62,0x9a,0x48,0x62,0x83,0x46,0x63,0x89,0x44,0x61,0xa5,0x49,
+ 0x62,0x92,0x50,0x61,0x94,0x40,0x66,0xb0,0x37,0x69,0xb2,0x53,0x63,0x9e,0x3a,0x6a,
+ 0xb9,0x50,0x6d,0x85,0x52,0x6e,0x9d,0x58,0x71,0x99,0x58,0x73,0x94,0x54,0x72,0xab,
+ 0x5e,0x71,0xa6,0x65,0x7c,0x95,0x61,0x7b,0xac,0x63,0x7d,0xa5,0x6b,0x7a,0xad,0x64,
+ 0x7f,0xa1,0x60,0x80,0xbf,0x68,0x7d,0xd4,0x78,0x86,0xbb,0x6f,0x89,0xb9,0x71,0x8a,
+ 0xb3,0x73,0x8b,0xae,0x75,0x8d,0xa8,0x82,0x8f,0xc1,0x82,0x95,0xc5,0x7c,0x99,0xb8,
+ 0x7c,0x99,0xc4,0x78,0x99,0xd9,0x7c,0x99,0xce,0x88,0x98,0xba,0x8c,0xa7,0xb8,0x8e,
+ 0xa4,0xd2,0x8e,0xa6,0xc7,0x9c,0xa5,0xc9,0x96,0xb2,0xe4,0x9a,0xb3,0xcf,0xa4,0xb1,
+ 0xd0,0x94,0xb5,0xda,0x9f,0xb4,0xdb,0xa5,0xb3,0xe0,0xa4,0xb4,0xf0,0xa5,0xbf,0xf3,
+ 0xb0,0xc1,0xd4,0xb1,0xbf,0xeb,0xb7,0xbe,0xed,0xab,0xc3,0xeb,0xad,0xc4,0xe1,0xb9,
+ 0xc7,0xd4,0xb6,0xcd,0xf6,0xbb,0xd0,0xf0,0xc0,0xce,0xfd,0xb8,0xd7,0xed,0xcd,0xd3,
+ 0xeb,0xc3,0xd6,0xf0,0xbf,0xd8,0xff,0xc5,0xde,0xfd,0xcd,0xdc,0xfe,0xb7,0xe3,0xff,
+ 0xd4,0xe4,0xfe,0xdd,0xe5,0xeb,0xd1,0xeb,0xff,0xdd,0xea,0xff,0xf1,0xed,0xe4,0xcb,
+ 0xf6,0xfe,0xf0,0xec,0xff,0xe4,0xf0,0xfe,0xdd,0xf3,0xff,0xeb,0xef,0xff,0xf1,0xef,
+ 0xf7,0xe6,0xf3,0xf4,0xf0,0xf2,0xef,0xed,0xf4,0xe9,0xe9,0xf5,0xef,0xf8,0xf1,0xf0,
+ 0xf1,0xf5,0xe4,0xef,0xf4,0xf7,0xed,0xf5,0xfe,0xe7,0xf8,0xff,0xff,0xf1,0xfe,0xf5,
+ 0xf5,0xff,0xe2,0xfb,0xff,0xfb,0xf4,0xff,0xdf,0xfd,0xfa,0xdb,0xfe,0xff,0xf9,0xf8,
+ 0xee,0xf0,0xf9,0xff,0xf9,0xf7,0xfb,0xff,0xf7,0xf0,0xee,0xfb,0xfc,0xf7,0xf9,0xf6,
+ 0xff,0xf6,0xfd,0xed,0xfd,0xf0,0xfe,0xf8,0xf6,0xf5,0xfa,0xfd,0xff,0xfa,0xea,0xec,
+ 0xff,0xf8,0xea,0xff,0xfe,0xfa,0xfe,0xe6,0xf4,0xfe,0xf9,0xf9,0xfe,0xed,0xfd,0xfb,
+ 0xff,0xf7,0xfe,0xf3,0xf1,0xff,0xff,0xff,0xfc,0xfa,0xf9,0xfe,0xff,0xfc,0xfe,0xfb,
+ 0xff,0xfe,0xf5,0xff,0xfd,0xff,0xfe,0xff,0xfc,0xff,0xff,0xff,0x21,0xfe,0x11,0x43,
+ 0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,
+ 0x0,0x21,0xf9,0x4,0x1,0xa,0x0,0xff,0x0,0x2c,0x0,0x0,0x0,0x0,0xab,0x0,
+ 0xb7,0x0,0x0,0x8,0xfe,0x0,0xbb,0x78,0x19,0xe8,0x25,0x48,0x97,0x2e,0x63,0xbe,
+ 0x28,0x5c,0xc8,0xb0,0xe1,0x98,0x87,0x10,0x23,0x4a,0x9c,0x48,0xb1,0xa2,0x45,0x88,
+ 0xd,0x33,0x6a,0xdc,0xc8,0xb1,0x21,0x93,0x8f,0x20,0x43,0x8a,0x64,0x42,0xa4,0xa4,
+ 0xc9,0x92,0x39,0x52,0xaa,0x74,0xc1,0xd2,0xc5,0x8c,0x15,0x33,0x5e,0xae,0xe0,0x40,
+ 0xb3,0xa6,0x4d,0xf,0x1e,0x32,0xe8,0xd4,0xe9,0x80,0x81,0xc0,0x81,0x41,0xbe,0x1c,
+ 0x4c,0xd8,0x91,0xe1,0xc5,0xa3,0x48,0x93,0x5e,0x2c,0xca,0x94,0xe3,0xc8,0xa7,0x20,
+ 0x4f,0x9e,0x1c,0x32,0x44,0x65,0xe,0x96,0x29,0x63,0x6a,0x9d,0x61,0xb3,0x2b,0x4d,
+ 0x9c,0x3b,0x4b,0x58,0x80,0x40,0x30,0x4a,0xd0,0x83,0x4d,0x17,0x2a,0x5d,0xcb,0xf6,
+ 0x68,0xda,0xb7,0xb,0xa1,0x42,0x95,0x6a,0x92,0x6a,0xd5,0x94,0x58,0x73,0xe8,0x98,
+ 0xa1,0x63,0xef,0xc,0x13,0x26,0xbc,0xde,0x4,0x6b,0x1,0x84,0x87,0xb2,0x6,0xd1,
+ 0xbe,0x6d,0xcb,0xb8,0xf1,0x43,0xb8,0x70,0xe5,0x3e,0xa5,0x5b,0xf2,0x88,0x5d,0xab,
+ 0x29,0xfb,0x6a,0xfe,0xb,0x58,0x70,0x4d,0x9c,0x1e,0x20,0x80,0xc8,0x50,0xf6,0x8b,
+ 0x15,0x2e,0x59,0xe0,0x3a,0x5e,0x4d,0x51,0x8d,0xeb,0xd7,0xae,0x21,0xbf,0x95,0x3c,
+ 0x92,0x32,0x91,0x23,0x96,0xa9,0x62,0xd6,0xac,0x19,0x70,0x67,0xcf,0x1c,0x70,0x1a,
+ 0x26,0x3d,0x30,0x8a,0xe9,0x2c,0xa9,0x17,0xb3,0x5e,0xfe,0x10,0x36,0x6c,0xd9,0x69,
+ 0x69,0x8b,0xb4,0x8d,0x3b,0xf7,0x6e,0xde,0x3a,0x7c,0x7,0x6,0x2e,0xbc,0x4,0x87,
+ 0x33,0x67,0xbc,0xfe,0x3c,0xb4,0x92,0xc5,0xca,0x46,0xe6,0xe8,0xd3,0x4b,0x3c,0x4f,
+ 0x71,0x63,0x6d,0x22,0x50,0xed,0x5e,0x56,0x89,0x3d,0xbb,0x76,0xee,0xa0,0x3f,0x84,
+ 0xf,0xf3,0xd8,0x8a,0x7f,0x8d,0xea,0x5,0x88,0x1e,0x7b,0x13,0x6d,0xd4,0x45,0x6d,
+ 0xf1,0xc9,0x77,0x57,0x66,0xd8,0x69,0xb7,0x9d,0x60,0xa0,0x79,0xf0,0x81,0x17,0xfc,
+ 0x99,0xe6,0xdf,0x7f,0x19,0x9,0xa8,0xe1,0x6a,0x4,0xae,0xa7,0xd1,0x41,0xd2,0x7d,
+ 0xa4,0xe0,0x82,0x7a,0x35,0xe8,0xa0,0x67,0x11,0x76,0xf0,0x98,0x85,0xfe,0x6d,0xe8,
+ 0xe2,0x80,0x0,0xb6,0xf7,0x21,0x88,0xd2,0x8d,0x68,0x55,0x7d,0x36,0x38,0xf8,0xe0,
+ 0x60,0x1d,0xf4,0xa8,0x10,0x86,0xa,0xbd,0x28,0x24,0x87,0x31,0x16,0x38,0x23,0x8d,
+ 0x92,0xd9,0x48,0x1f,0x76,0x36,0x34,0x79,0x62,0x57,0x1e,0x74,0xf0,0xc1,0x7,0x19,
+ 0x5c,0x68,0x9e,0x15,0x43,0x66,0xd9,0x58,0x87,0x11,0x19,0x78,0x10,0x92,0x9,0xca,
+ 0x77,0x23,0x93,0x4d,0xe6,0xe8,0x9b,0x57,0x51,0x4e,0x99,0x41,0x79,0x17,0x8e,0xc1,
+ 0x9f,0x73,0xaf,0x69,0x29,0xa7,0x87,0x19,0xca,0x98,0xd1,0x97,0x5f,0x26,0xa9,0xe0,
+ 0x98,0xbc,0x95,0x69,0xe6,0x6f,0x37,0x7d,0xc0,0x2,0xb,0x55,0x5a,0x9,0x11,0x9c,
+ 0xae,0x31,0x67,0xe5,0x85,0xb0,0x85,0xe1,0xe8,0xa3,0x88,0x46,0x3a,0x86,0xa1,0x10,
+ 0x61,0xe9,0x5c,0x45,0x5c,0x62,0xa4,0x11,0x41,0x78,0xca,0xb5,0xe7,0x8d,0x7a,0x69,
+ 0x85,0x5d,0x4c,0x3b,0x7e,0x35,0x25,0x95,0x6d,0x3a,0x16,0x29,0xa2,0x65,0xc0,0x61,
+ 0x86,0x19,0xfe,0x65,0xc4,0x2a,0xc7,0xa3,0x61,0xb0,0x61,0x6b,0x1c,0xb6,0x82,0xa7,
+ 0xeb,0xae,0xbc,0x86,0xd1,0x2a,0x1c,0xc0,0xc6,0x5a,0xc6,0x6b,0xb4,0x86,0xa1,0xc6,
+ 0x5a,0x6f,0x45,0x31,0x50,0x13,0x5e,0x1c,0x84,0xdc,0xb3,0x59,0x7c,0x54,0x59,0x75,
+ 0x47,0x34,0x61,0xad,0xb5,0x96,0x59,0x15,0xd3,0xa,0xdc,0x76,0xeb,0x6d,0x4d,0xa7,
+ 0x96,0xc0,0xdc,0xaa,0x70,0xc6,0xa,0xab,0xb0,0xb3,0x3e,0x6a,0xeb,0xba,0x67,0x14,
+ 0xeb,0xee,0xa3,0x72,0x58,0x1,0xac,0x19,0xc1,0x96,0xe1,0x9f,0x6b,0xb4,0x1e,0xab,
+ 0x54,0xb2,0xcb,0x36,0xdb,0x5,0xb4,0xc8,0x49,0xb,0x1f,0x13,0xd4,0x5e,0xdb,0x44,
+ 0x6e,0x43,0xdc,0x70,0x43,0x4b,0x2d,0x79,0xcb,0xad,0x60,0xe3,0x92,0x2b,0xb1,0x1a,
+ 0x72,0x54,0x6c,0xb1,0xc5,0x70,0xac,0xa1,0xf1,0xc6,0x1c,0x73,0x4c,0xaf,0x7f,0x70,
+ 0xc8,0x6b,0x85,0xbd,0x58,0x12,0xd9,0x94,0xb2,0x9c,0xfe,0xb,0x2d,0x48,0x54,0x95,
+ 0x24,0x5,0x11,0x52,0x8c,0x94,0xc4,0xcc,0xa,0x33,0xcc,0x92,0xc3,0x33,0x79,0x15,
+ 0xf1,0xc4,0xae,0xf1,0x8a,0xe8,0x85,0x19,0x77,0x2c,0x34,0xc7,0x21,0xab,0xb1,0xe8,
+ 0xd1,0x2d,0x22,0x9b,0x96,0xb2,0xcc,0xfa,0xfb,0xaf,0x48,0xb9,0x9d,0xf4,0x72,0xcc,
+ 0x53,0x27,0x71,0x12,0x5e,0xd,0x3b,0xc,0xf1,0x72,0x3c,0xe3,0xeb,0x45,0x78,0xe0,
+ 0x1d,0x2a,0x2f,0xb0,0x1a,0xc3,0x41,0x71,0x18,0xb3,0xa6,0x8d,0xf6,0xda,0x69,0xcb,
+ 0xe1,0x1c,0xc8,0x70,0x0,0xc,0x7,0x5b,0xfc,0xa6,0x8c,0x64,0x75,0x2d,0x4b,0x65,
+ 0xf5,0xfe,0xde,0x52,0xad,0x74,0xb3,0xd6,0x3a,0x73,0xdd,0x75,0x18,0x5f,0x83,0x27,
+ 0x9e,0x14,0x63,0x18,0xd,0x6c,0xc6,0xc0,0x3a,0xda,0xee,0xe3,0x61,0x40,0xe,0x39,
+ 0xad,0x15,0x1b,0x3d,0x36,0xb4,0x73,0x2b,0x9d,0x56,0x10,0x76,0x1f,0xc8,0xc4,0xc1,
+ 0xb8,0xd9,0x30,0xc4,0x11,0x52,0x94,0x6e,0xfa,0xcc,0x49,0x48,0x81,0xfa,0xd,0x39,
+ 0x24,0xe1,0xb7,0x4c,0xdd,0x6e,0xcd,0x5a,0xd7,0x14,0xeb,0x7a,0xec,0xed,0x6f,0xab,
+ 0x21,0xac,0xee,0xbc,0xf,0xeb,0x7b,0xef,0x91,0x53,0xee,0xf6,0x78,0x63,0x87,0xac,
+ 0x39,0x74,0x2,0x61,0xb,0x5,0x14,0x7e,0xe2,0x36,0xa2,0x6e,0x39,0x2c,0xe8,0x3a,
+ 0x5e,0xdb,0xc6,0x1e,0xf8,0xec,0xb4,0xc3,0x76,0xb1,0xc5,0x94,0xb,0xeb,0xfd,0xf7,
+ 0xde,0xbf,0xeb,0x76,0xc9,0x94,0xee,0xb,0x9d,0x42,0xcb,0x36,0xb1,0x3c,0xf3,0x7e,
+ 0x5e,0xd1,0x24,0xf3,0x43,0xbc,0xef,0xa7,0xd,0x3a,0x4c,0x7f,0x55,0xf5,0xf,0x5f,
+ 0x9f,0x54,0xf6,0xac,0xc2,0x21,0x8,0xb0,0x56,0xa0,0x3,0x21,0xe8,0x50,0x8,0x37,
+ 0xb8,0x61,0x5d,0x71,0xe0,0x81,0xaf,0xe8,0xc0,0xc0,0x58,0x5,0x90,0xe,0x8b,0x4a,
+ 0x97,0xbb,0xa,0xc1,0xc0,0x2b,0x95,0x21,0x5e,0xcb,0xd9,0x88,0x7f,0xe,0x12,0x4,
+ 0xce,0x79,0xc1,0x5a,0x4,0x39,0x82,0xe,0x6c,0x70,0x85,0x2a,0x5c,0xe1,0x84,0x36,
+ 0xa0,0x49,0x1c,0x52,0x68,0x82,0x32,0x5d,0x21,0x7,0x52,0x60,0x49,0xe9,0xb8,0x55,
+ 0x3d,0xd9,0xed,0x8f,0x7f,0xce,0x29,0xc3,0x13,0x9e,0x20,0x88,0x1e,0x6e,0x30,0x8,
+ 0xfe,0x6e,0x28,0x4,0x1b,0x6c,0x0,0x84,0x2b,0xb0,0x61,0xf,0x95,0x1b,0x3,0x88,
+ 0x2c,0xa6,0xc4,0x2f,0xc9,0xc1,0x7b,0xc,0x84,0xa0,0x15,0xe4,0xa0,0x85,0x2a,0x76,
+ 0x50,0x5f,0x26,0x6b,0xc8,0x6,0xbb,0xd0,0x41,0x82,0x84,0x27,0x7,0x47,0x90,0x83,
+ 0x14,0x36,0x80,0xc2,0xf7,0x7d,0x6d,0x42,0x50,0xc8,0x80,0x7,0xae,0x10,0x87,0x12,
+ 0xd4,0xf,0x2b,0x2e,0xf8,0xc0,0x11,0x6a,0xa8,0x3f,0xa4,0xe0,0x30,0x87,0x82,0x48,
+ 0xc3,0x13,0xcc,0xd0,0xc3,0x28,0x76,0x1,0x8c,0x67,0xd8,0x3,0x1b,0xae,0xa0,0x3,
+ 0x2f,0xec,0xa1,0x10,0x88,0xdc,0xc3,0x19,0x98,0x15,0x48,0x44,0x16,0x42,0x11,0x59,
+ 0xd0,0x98,0x1e,0xf4,0x40,0x2f,0x38,0x8,0x90,0xe,0x61,0xe8,0xa0,0x16,0x8,0x81,
+ 0x45,0xc7,0x68,0xd0,0x3c,0xb,0xe9,0xa0,0x1b,0xbc,0x10,0xb3,0x1b,0x84,0x80,0x8,
+ 0x72,0x70,0x41,0xe,0x48,0x29,0x5,0x2e,0x70,0xa1,0x8,0xaf,0xbc,0x81,0x18,0x37,
+ 0xe0,0x82,0x3d,0xac,0x80,0x96,0x78,0x59,0x81,0x5f,0xf2,0xd7,0x15,0xb6,0xdc,0x11,
+ 0x36,0x65,0x10,0x84,0x19,0xf6,0xf8,0xaa,0x2c,0xd4,0x20,0xb,0x8b,0x23,0x49,0x17,
+ 0xe0,0xe0,0x7,0x31,0xc8,0x40,0x6,0x13,0x90,0x81,0x11,0xc4,0xe0,0x87,0x6a,0x8a,
+ 0xc1,0x8,0xd0,0xa4,0x80,0x12,0x7a,0x50,0x87,0x3a,0xcc,0x81,0xc,0x5b,0xd8,0x81,
+ 0x1e,0x42,0xc6,0x40,0x2d,0x84,0x21,0xa,0x9d,0xdc,0x52,0x46,0x2e,0xc4,0x90,0xe,
+ 0x9e,0x21,0x75,0x7c,0x18,0x44,0xdc,0x8e,0x99,0x5,0x23,0xa4,0x60,0x2,0x18,0xfe,
+ 0xa0,0x81,0xf,0xf4,0x89,0x81,0x9,0x4c,0xc0,0x8,0x59,0xe0,0x82,0xea,0xae,0xa2,
+ 0xca,0x1c,0x68,0x85,0x97,0x36,0xf1,0xe5,0x2f,0x5d,0x53,0x6,0x21,0x94,0x81,0xe,
+ 0x65,0xc8,0x82,0x19,0x26,0xb9,0x86,0x40,0x4,0x62,0x9,0x2d,0x68,0xc1,0x1b,0x22,
+ 0xa1,0x9,0x54,0xd4,0x62,0x18,0xcf,0xa0,0xc6,0x37,0xa8,0x21,0xf,0x79,0x88,0x83,
+ 0x1a,0xcf,0x48,0xc6,0x30,0x86,0xb1,0x8a,0x53,0x64,0x22,0xf,0x48,0x40,0x2,0x37,
+ 0x95,0xb0,0x6,0x44,0xc0,0xa1,0x6,0x44,0xa0,0x83,0x25,0x4a,0x96,0xc5,0x85,0x58,
+ 0x29,0x94,0x6,0x91,0x3,0x1f,0x6a,0x90,0x2,0x23,0x90,0x81,0xc,0x4b,0xb8,0x0,
+ 0xa,0x22,0xa1,0x8a,0x5e,0x28,0x83,0x19,0xf8,0x98,0xc6,0x33,0x98,0x91,0xb,0x4c,
+ 0x5c,0x80,0x2,0x2,0x2d,0xdd,0x7,0x5c,0xd0,0x84,0x5d,0xe6,0xac,0x97,0x6b,0x59,
+ 0xa8,0x6b,0xe4,0xe0,0x6,0x47,0x95,0x61,0x10,0x7a,0x58,0xc3,0x36,0x51,0x80,0x84,
+ 0x47,0x98,0xe2,0x16,0xc9,0xf8,0x6,0x3e,0xf4,0x41,0x57,0x7c,0xd8,0xf5,0x1d,0x78,
+ 0xb5,0xeb,0x5d,0xe5,0x6a,0xd7,0x6f,0x24,0x43,0x16,0x9f,0x60,0x44,0xf,0x7a,0x40,
+ 0x86,0x35,0xc8,0xf3,0xb,0x4c,0x60,0x8e,0x46,0x16,0xa5,0x90,0xa0,0xa8,0x41,0x5,
+ 0x45,0xa8,0xa8,0x12,0x48,0x0,0x86,0x4c,0xd4,0x82,0x1a,0x76,0xf5,0xc6,0x3b,0xf4,
+ 0x11,0x8e,0x77,0x54,0xe3,0x19,0x76,0x1d,0x6,0x26,0x44,0xf0,0x1,0x29,0x0,0x22,
+ 0x8e,0x2f,0xa1,0x23,0x58,0x95,0x22,0x56,0x35,0xd4,0xa,0xb,0x7b,0x50,0xfe,0x4,
+ 0x21,0x88,0xba,0x4,0x4c,0xb0,0x22,0x19,0xf2,0xd0,0xab,0x3e,0xba,0x81,0xe,0x74,
+ 0xd8,0xe3,0xb7,0xbd,0xfd,0xad,0x70,0xfd,0x41,0xdc,0x73,0x6c,0x56,0x1f,0x76,0x35,
+ 0xa9,0x30,0x5c,0xd1,0x88,0xa2,0xe,0x62,0x10,0x3c,0xed,0xe9,0x8f,0x7e,0xba,0x10,
+ 0x39,0x30,0x73,0xd,0x24,0xe8,0x81,0x2b,0x9c,0x61,0xd7,0x73,0x78,0x83,0xb7,0xee,
+ 0x8,0x6f,0x3e,0xf4,0x81,0xd7,0x73,0xe0,0x43,0x1e,0xa2,0x18,0x63,0xe9,0x36,0x30,
+ 0x25,0xd5,0x26,0x34,0xac,0xac,0xda,0x1d,0xc5,0xb6,0xf7,0x1a,0x39,0xec,0x41,0x3c,
+ 0x70,0x48,0x41,0xb,0x4a,0x21,0xc,0xbd,0xaa,0xc3,0x1b,0xea,0x98,0x2b,0x71,0xc3,
+ 0x1b,0x5e,0x7b,0x10,0xf8,0xc0,0xc4,0xa5,0x6b,0x79,0xbd,0xf1,0x8d,0x6f,0x88,0x43,
+ 0x1e,0xe4,0x20,0x86,0x28,0xec,0x9,0xdd,0xc,0xae,0x13,0x94,0xa,0x71,0x96,0x11,
+ 0x76,0xa0,0x1,0x30,0xc4,0x82,0xa4,0xd,0x9e,0xab,0x3e,0x8,0xec,0xf,0x7e,0xa4,
+ 0x23,0x1d,0xc4,0x55,0xc7,0x35,0xbe,0x21,0x8f,0x56,0x88,0xa0,0x8,0x49,0xf8,0x80,
+ 0xe,0xae,0x0,0x18,0x9c,0xe5,0xac,0x22,0xb4,0xfb,0x15,0xbd,0x2e,0xe8,0xa8,0x2,
+ 0x46,0x81,0x82,0x1,0xbc,0x20,0x1f,0x68,0x60,0x87,0x55,0x4c,0x43,0x1f,0xe7,0x10,
+ 0xae,0x3d,0xf4,0xe1,0xf,0x7a,0xd0,0x23,0xc0,0x78,0x55,0x32,0x3b,0xa6,0xfc,0xdb,
+ 0x75,0xac,0x83,0xae,0x75,0xd5,0xab,0x49,0xa9,0x51,0xe,0x72,0x94,0xc3,0x15,0x84,
+ 0x35,0x1b,0x9c,0xe8,0xf6,0xa1,0x30,0xb8,0x21,0x25,0x84,0x10,0x41,0xfe,0x23,0x90,
+ 0x90,0x7,0x54,0x40,0xd5,0xb3,0xe8,0xc0,0x7,0x3d,0xc8,0xfb,0x5b,0x76,0x18,0x38,
+ 0x1d,0xe6,0xe0,0x7,0x3f,0xe8,0xa1,0x8d,0x6,0xcb,0xc3,0x13,0x3e,0xb8,0x81,0xe,
+ 0xe2,0x70,0x80,0x17,0x0,0xc1,0x6,0x2e,0x50,0x98,0xc2,0x56,0x50,0x2,0x71,0xb5,
+ 0xa6,0x6b,0xad,0x7a,0x15,0x8f,0x1d,0xf5,0x81,0x1f,0x77,0x81,0x10,0x82,0xa8,0x1,
+ 0x22,0x44,0x40,0x6,0x56,0x70,0xf7,0x1a,0xd8,0xe0,0x87,0x3b,0xd0,0x61,0x67,0x7b,
+ 0xf8,0xe3,0x1e,0xf4,0x10,0xb1,0x3f,0xc,0x4c,0x65,0x7b,0xa0,0x23,0x1c,0x9d,0xed,
+ 0x2b,0x33,0x7a,0x11,0xb,0x53,0x64,0x2,0x13,0x91,0xf8,0xc3,0x1f,0x1a,0xb1,0x9,
+ 0x51,0x4,0x82,0x4,0x6b,0x10,0xf3,0xa5,0x8e,0xa7,0x16,0x20,0x82,0x31,0xc,0x44,
+ 0xd0,0x83,0x1,0xf2,0x50,0x8b,0xb9,0x86,0xc3,0x1a,0x76,0x76,0x32,0x9d,0xed,0x31,
+ 0xe5,0x6d,0xb8,0x43,0xcf,0x4d,0xee,0x2b,0x3e,0x90,0x81,0x4,0xd2,0x42,0xe0,0x5,
+ 0x2f,0x68,0x52,0xa2,0x15,0xfd,0x81,0x46,0xe3,0x18,0xd2,0x92,0x2e,0x3,0xad,0xa,
+ 0x41,0x8,0x22,0xa0,0xd5,0x8,0x81,0xd0,0x80,0x2b,0x70,0xfb,0x8d,0x6b,0x94,0x18,
+ 0x1a,0xee,0xa0,0x76,0xa9,0x89,0xeb,0x6a,0xdf,0xfa,0xc3,0x1d,0xc4,0xbd,0x32,0x72,
+ 0xf1,0x41,0xd,0x5c,0x98,0xe2,0xf,0xfb,0xa4,0x0,0x5,0x68,0xf0,0x86,0x66,0xfa,
+ 0x21,0xb,0x45,0x18,0x4,0x1f,0xe2,0x29,0x29,0x62,0x7,0xc9,0xb,0xd5,0xa,0xc3,
+ 0xd,0xe0,0x40,0x2,0x46,0xc,0x43,0xae,0xef,0xf0,0xad,0x81,0xfe,0x4b,0xbc,0x8f,
+ 0x3a,0xb3,0x3,0x1d,0xd7,0xe6,0xc7,0x3a,0xb0,0xd1,0x8d,0x73,0xa8,0x43,0xa4,0xf2,
+ 0x70,0x85,0x8,0xf6,0x50,0x82,0x29,0x34,0x69,0x6,0x2c,0x21,0xb7,0xb9,0x1f,0xcd,
+ 0xb3,0x5f,0xc5,0xca,0xcc,0x3d,0xb6,0xc2,0x20,0xc4,0x30,0x87,0x1e,0xfc,0x41,0x18,
+ 0x25,0xb5,0x2b,0x3d,0xb2,0x71,0x8f,0x7f,0x2b,0xf9,0xe9,0xbf,0x5,0xb8,0x3f,0xf0,
+ 0x11,0x60,0x6a,0x0,0xe3,0x13,0x60,0x50,0x82,0x1e,0xc4,0x20,0x6,0x2e,0x4c,0x9c,
+ 0xf,0xc3,0xab,0xd8,0x7,0x1d,0x95,0x3,0xb7,0x8d,0xd9,0xe2,0x5f,0x18,0x43,0x13,
+ 0x72,0xe0,0x86,0x2f,0x14,0x41,0xc,0x91,0x40,0x6,0xd5,0xcf,0xc1,0x64,0x7f,0xa0,
+ 0x63,0x1b,0xd8,0xce,0x77,0xd4,0xb7,0x41,0x5c,0x7f,0x60,0x59,0x1d,0xf2,0x70,0x46,
+ 0x29,0xde,0xf0,0x0,0x2f,0x44,0xc0,0x7d,0x3a,0x68,0xc9,0xd,0xb8,0x55,0x6e,0x47,
+ 0x4f,0x24,0x7b,0x3f,0x37,0xb3,0x1,0xc3,0xc0,0x4,0x4a,0x90,0xa1,0xe,0x60,0x30,
+ 0x5,0x66,0xa9,0xae,0xe,0x27,0xdf,0xe3,0x1e,0xda,0xd0,0x7,0xd4,0x9f,0x8e,0xe,
+ 0xe4,0x9a,0xb4,0x16,0x8f,0x40,0xc1,0x1c,0x10,0x41,0x7,0x15,0x54,0x4c,0x89,0x1f,
+ 0x4,0x61,0xe1,0x78,0x50,0x88,0x45,0xb8,0xc1,0xec,0xc3,0x36,0x5f,0x43,0xc2,0x60,
+ 0x2,0x36,0x9c,0x81,0x8,0x46,0x78,0xc3,0x2f,0xf0,0xf1,0xc,0xba,0xaf,0x1a,0x1b,
+ 0xd8,0x58,0x87,0x9e,0xd3,0xa1,0xf7,0x91,0xfb,0xe3,0x1d,0xc6,0x7d,0xc7,0x33,0x90,
+ 0x91,0x89,0x16,0x50,0xa0,0x8,0x63,0x58,0xc1,0x22,0x3e,0xfe,0x90,0x92,0x9a,0x31,
+ 0xba,0xd1,0x3b,0x7f,0x7c,0x8e,0x2b,0x26,0x79,0x2d,0x4,0x73,0xd,0x3d,0x68,0x3,
+ 0x2e,0xe6,0xba,0x59,0xcf,0xd7,0xa3,0x1e,0xa8,0x16,0xfd,0xd3,0xd9,0xe1,0x8e,0x6d,
+ 0x6c,0x63,0xc9,0xf8,0x60,0xc6,0x2d,0x70,0xd0,0x83,0x39,0xac,0xa1,0x6,0x2a,0x70,
+ 0x69,0xb7,0x67,0x40,0x4,0x58,0x56,0x3d,0x26,0x79,0x68,0x83,0x28,0x64,0xb6,0x7b,
+ 0x3c,0x40,0x4a,0x62,0x40,0x3,0xc3,0xb7,0x59,0xae,0xb6,0xd,0x56,0x46,0x5c,0xcb,
+ 0xd7,0x7c,0x9b,0xf5,0xe,0x0,0xf6,0xd,0xc2,0x0,0xa,0x6,0x40,0x1,0x46,0x0,
+ 0x7,0x44,0x30,0x4,0x53,0x82,0x6c,0x26,0xe1,0x2,0x2b,0x0,0x2,0x20,0x0,0x7e,
+ 0xe7,0xd6,0x35,0x12,0x14,0x6,0x10,0x65,0x6,0x87,0xa0,0x1,0x98,0x90,0xc,0xf8,
+ 0x50,0xd,0xa2,0xa7,0x7c,0xfc,0xf0,0x79,0xa8,0xe6,0x77,0xf2,0xa7,0x64,0x27,0xb6,
+ 0x64,0xcf,0x80,0xb,0x9e,0x30,0x1,0x83,0x0,0x41,0xbe,0x52,0x6,0xb0,0x62,0x5,
+ 0x66,0xc0,0x40,0x82,0xd0,0x40,0xae,0xc2,0x47,0x52,0x8,0x7,0xc3,0x72,0x76,0xba,
+ 0xc7,0x10,0xb5,0x92,0x3,0x4c,0xf0,0x6,0xa0,0x30,0x57,0xd6,0x60,0x60,0x52,0x57,
+ 0x81,0x7a,0x56,0x60,0x79,0x35,0xd,0x54,0x7,0xc,0x91,0x50,0x0,0x13,0x0,0x9,
+ 0xb1,0xa4,0x6,0x1f,0x50,0x8,0x41,0xa0,0x2,0x44,0x50,0x4,0x44,0xb0,0x30,0x25,
+ 0x30,0x2,0x23,0xc0,0x82,0x3c,0x37,0x31,0xea,0x86,0x36,0x15,0xa3,0x84,0xd8,0x55,
+ 0xa,0xdc,0x75,0xe,0xe8,0xe0,0xf,0xe9,0xc0,0xf,0xfe,0xe6,0x90,0x67,0xfc,0xd0,
+ 0x64,0x73,0x86,0x65,0xc2,0x25,0x75,0xfa,0xf0,0xc,0xa6,0xb0,0x4,0x45,0x70,0x6,
+ 0x46,0xc4,0x6,0x8e,0x42,0x7,0xaf,0x92,0x47,0xaf,0xb2,0x43,0xaf,0x92,0x6,0x87,
+ 0xa0,0x31,0x3b,0x90,0x6,0x69,0xa0,0x7,0x55,0x98,0x7b,0x49,0x1,0x20,0x8a,0x54,
+ 0x4,0x2d,0x40,0xd,0x38,0x8,0x86,0xe1,0xb5,0xe,0xc4,0x45,0xf,0xfe,0x50,0x72,
+ 0x79,0x75,0x5e,0xe2,0x80,0x7a,0x15,0xd0,0x2,0x7e,0xc0,0x5,0x2c,0x70,0x3,0x6e,
+ 0x70,0x4,0x2e,0xe0,0x5,0xf,0x10,0x4,0x44,0x50,0x3,0x35,0x40,0x87,0x33,0x70,
+ 0x87,0x79,0x18,0x7e,0x12,0x91,0x63,0x61,0x60,0x9,0xa6,0x41,0x8,0x4f,0x90,0x6,
+ 0x24,0xc0,0xa,0x98,0xa5,0x59,0x29,0xc7,0x7c,0x52,0xe7,0x83,0x4d,0xd6,0x77,0xfb,
+ 0xe0,0xe,0xeb,0x60,0x57,0xbc,0x90,0x7,0x2d,0x20,0x6,0x61,0x10,0x7,0x55,0xb0,
+ 0x8e,0x98,0x8,0x88,0x6b,0x60,0x6,0x6b,0x90,0x6,0xf1,0x48,0x8a,0xf4,0x98,0x6,
+ 0x73,0x70,0x8f,0xc1,0x46,0x3b,0xe7,0xa6,0x29,0x63,0xe0,0x5,0x5f,0x60,0x4,0xb4,
+ 0x80,0xf,0xde,0x80,0x72,0x7,0x6,0x70,0x4e,0x46,0xf,0xfb,0x30,0x70,0xf2,0x40,
+ 0xd,0xab,0xf0,0x3,0xfc,0xa7,0x4,0x35,0x20,0x5,0x65,0xc2,0x3,0x65,0x92,0x3,
+ 0x41,0x20,0x4,0xc8,0x88,0x53,0xcb,0x88,0x87,0x7a,0x28,0x7e,0x3d,0x27,0x7,0x2,
+ 0x4,0x7,0x3b,0x40,0x6,0x3d,0xe0,0x69,0xf2,0xe0,0xd,0xde,0x50,0x62,0x87,0x58,
+ 0x60,0xbf,0x85,0x65,0x4e,0x96,0xd,0x4d,0x66,0xfe,0x65,0xfa,0x20,0xf,0xb2,0x80,
+ 0x3,0x38,0xd0,0x8,0x82,0x50,0x2b,0x6c,0x50,0x5,0xb6,0xe2,0x2b,0xf3,0x12,0x85,
+ 0xaf,0xf2,0x2a,0x43,0x43,0x2f,0xfa,0xf8,0x68,0xfc,0x48,0x4,0x70,0x50,0x7,0x50,
+ 0xd5,0xd,0x86,0xc8,0x8d,0xe1,0xc5,0x88,0xf4,0xd0,0xd,0xde,0x80,0xf,0xc9,0xc0,
+ 0xa,0x6d,0x50,0x1,0x3d,0xa0,0x4,0x5b,0x10,0x2d,0x3c,0x0,0x6e,0x36,0x40,0x91,
+ 0x4d,0x62,0x91,0xc7,0x88,0x8c,0x44,0xb0,0x91,0xcd,0xe8,0x78,0xcf,0x8,0x69,0x56,
+ 0xc0,0x4,0x70,0x80,0x8,0x64,0xd0,0x2,0xd8,0x98,0x59,0x4c,0x76,0x62,0xa2,0xf6,
+ 0x74,0x74,0x45,0xf,0x3c,0xf8,0x64,0x91,0xc8,0xa,0x73,0xa0,0x4,0x87,0xb0,0x5,
+ 0x35,0x20,0x40,0xe6,0xe4,0x28,0xc3,0x33,0x5f,0x95,0x3,0x27,0x8c,0x62,0x5,0xd9,
+ 0xb3,0x8f,0x2b,0xf2,0x5,0x5c,0x60,0x4,0xac,0x40,0x75,0xca,0x77,0x62,0xee,0x60,
+ 0x67,0x6,0x49,0x8b,0xfa,0xf0,0xd,0x9d,0x0,0x53,0x4a,0x90,0x2,0xcf,0xf2,0x39,
+ 0x57,0xe0,0x95,0xf3,0x93,0x3,0x73,0x48,0x96,0x2e,0xc0,0x8c,0x1d,0x99,0x96,0x5d,
+ 0x43,0x1e,0x5b,0x30,0x7,0x8c,0x10,0xa,0x98,0x35,0xd,0xe7,0x30,0x60,0xd8,0xc0,
+ 0x8d,0x50,0x47,0x5c,0xd9,0xe0,0x64,0x7d,0x75,0xa,0x29,0x20,0x4,0x94,0x40,0x9,
+ 0x35,0xf0,0x4,0xc0,0x19,0x2c,0xae,0xc5,0x2b,0xe0,0xe1,0x2e,0xc6,0x89,0x7b,0x13,
+ 0xc3,0x98,0x44,0x91,0x5,0x7e,0xa0,0x1,0xcc,0x90,0x5b,0xf7,0x50,0xf,0x75,0xb9,
+ 0x6f,0x9f,0x47,0xf,0xd7,0x80,0xf,0x97,0xfe,0x80,0x4,0x24,0xe0,0x7,0x1f,0xd1,
+ 0x41,0x41,0xd0,0x4,0x3c,0xe0,0x3e,0x3c,0x10,0x3f,0x65,0xa2,0x3,0x37,0x30,0x87,
+ 0x74,0x78,0x9a,0x1c,0xe9,0x8c,0x11,0x91,0x63,0x6d,0x79,0x79,0x99,0x20,0xe,0xf8,
+ 0x40,0x77,0xfb,0xe0,0xf,0x2b,0x17,0x70,0xfc,0xa6,0x64,0xb3,0x38,0x67,0x66,0xf8,
+ 0xa,0x60,0xf0,0x4,0x10,0x15,0x40,0xc2,0x84,0x4c,0xc4,0x19,0x39,0xc7,0x49,0x2b,
+ 0xba,0x12,0x3c,0x8e,0x93,0x80,0x5d,0xc3,0x9c,0xa,0x91,0x5,0x34,0x80,0x9,0xb,
+ 0xa9,0xf,0xd3,0x59,0x9d,0xbf,0x55,0x62,0xf7,0xc0,0xf,0xd8,0xe0,0xd,0xc0,0x80,
+ 0x4,0x62,0x70,0x3,0x7b,0xc0,0x3,0x24,0x8a,0x2d,0x96,0x31,0x33,0x7a,0x51,0x26,
+ 0x33,0x90,0x9e,0x45,0xb0,0x30,0x26,0x50,0x2,0x2f,0x90,0x9a,0xef,0x9,0x69,0x82,
+ 0xb0,0x3,0x75,0xd0,0x6,0xce,0xf0,0xd,0xfa,0x50,0x88,0xe6,0x80,0x67,0x2,0xa7,
+ 0xf,0xf4,0xb0,0x88,0x4a,0x26,0x8e,0xd9,0xa6,0xe,0xbf,0x0,0x6,0x21,0x28,0x8,
+ 0xfe,0x1,0x41,0xee,0x66,0x39,0xdf,0x33,0x5f,0x14,0x63,0x98,0x17,0x3,0x2f,0x45,
+ 0x29,0x7e,0x9a,0x92,0x5,0x1a,0x80,0xb,0xb9,0x45,0xf,0xf0,0x67,0xe,0xcd,0xf7,
+ 0x5b,0xfc,0x50,0xf,0xdc,0xe0,0x77,0xdf,0x80,0x9,0x7e,0xb0,0x2,0x24,0x74,0x5,
+ 0x3c,0x70,0x30,0xaa,0x63,0x12,0x29,0xa,0x4,0x40,0x80,0x73,0x8a,0x86,0x82,0xe0,
+ 0xe7,0x9e,0x87,0x2,0x69,0xd5,0xd8,0x3,0xc8,0x20,0xf,0xfa,0x60,0xd,0x88,0x8,
+ 0xd,0x26,0xe6,0x77,0xe6,0xf5,0x79,0xfe,0x42,0xa,0x86,0xb2,0xa8,0xf,0xd3,0xf0,
+ 0xd,0x91,0x20,0x3,0x19,0x73,0x8,0x4f,0x90,0x5,0x4,0x74,0x6,0x50,0x70,0x7,
+ 0xed,0xf2,0x44,0x66,0x40,0x8a,0x42,0x13,0x94,0x9a,0xea,0x3d,0x55,0x9a,0x96,0x57,
+ 0xfa,0x7,0xcf,0x20,0x57,0x5c,0xfa,0x79,0xc2,0x55,0x6a,0x61,0x4a,0x9d,0x48,0x96,
+ 0xb,0x13,0xb0,0x2,0x71,0xf0,0x2,0x26,0x34,0x4,0x49,0x50,0x4,0xb2,0x9a,0x8c,
+ 0x49,0xa0,0x3,0x40,0x10,0x3,0xb8,0xba,0xa2,0x8a,0xb6,0x2,0x2f,0x2a,0xa3,0x77,
+ 0xfa,0x1a,0xb1,0x12,0x29,0x70,0x10,0x6f,0xb7,0x40,0x9f,0x29,0x99,0xe,0xf0,0x0,
+ 0xf,0x26,0x76,0x65,0x9b,0x75,0x9d,0xab,0x6,0x86,0xe9,0x90,0x90,0xf8,0x20,0xc,
+ 0x14,0x30,0x9,0x72,0x70,0x8,0x73,0x90,0x6,0x66,0xa0,0x98,0x8a,0x44,0xa9,0x68,
+ 0xa3,0x84,0x98,0x3a,0x94,0xef,0xa8,0xa9,0xb0,0x92,0x3d,0xd1,0xf5,0x10,0x95,0x83,
+ 0x25,0xfe,0x21,0x6,0x9e,0xa0,0x57,0xed,0x0,0x7f,0xfc,0x0,0x75,0xfc,0x0,0xf,
+ 0xf3,0x0,0xf,0x64,0xfa,0x6,0x52,0x0,0x4,0xe0,0x6,0x4,0x3a,0x20,0xab,0x46,
+ 0x60,0x4,0xb2,0x2a,0x68,0x44,0x4,0xa7,0xe8,0xe9,0x7d,0xbc,0xa,0x7e,0x91,0xf2,
+ 0x3d,0x21,0x43,0x1e,0xc0,0xc2,0x26,0x56,0xb0,0x5,0x48,0x10,0xa,0xdf,0x60,0x5c,
+ 0x4c,0xa6,0x83,0x63,0xa8,0x77,0x7a,0xf6,0x83,0x6,0x96,0x67,0xc8,0x55,0xb,0x2d,
+ 0xc0,0x7,0x44,0x0,0x8f,0xef,0x18,0x6c,0xc0,0xe2,0xa4,0xde,0x3,0x94,0x8b,0x93,
+ 0xb2,0x8b,0x13,0xac,0x2e,0x68,0xfe,0x2c,0xc4,0x93,0x38,0x66,0xa6,0x5,0x10,0xc5,
+ 0x4c,0x24,0x20,0xc,0x66,0x88,0xf,0x4c,0xf7,0x79,0xeb,0xa0,0x77,0x27,0x77,0x6d,
+ 0xef,0xc7,0xf,0x9,0x59,0xb,0x22,0xe0,0x3e,0x57,0xe0,0x4,0x40,0xc0,0x5,0x7e,
+ 0x20,0x2,0x65,0x70,0x3,0x2c,0xb0,0x2,0x65,0xd4,0x4,0x67,0xb0,0x1,0x21,0x50,
+ 0xab,0xba,0x4,0x4,0x8,0x1b,0x5f,0xb1,0x92,0xb2,0x6,0xba,0x38,0x56,0xa0,0x4,
+ 0x30,0x60,0xc,0xfa,0x80,0x83,0xfa,0x20,0x8b,0x25,0x26,0x6a,0x2c,0x99,0x60,0xd3,
+ 0xa6,0xa1,0x53,0x27,0xb,0x60,0x0,0x7,0xf1,0x2,0x94,0xf0,0x8,0x8f,0x2b,0x7b,
+ 0x41,0x4f,0x4,0x3e,0x76,0xcb,0xb2,0x3c,0x93,0x2e,0x93,0x72,0x28,0x8e,0xe2,0x6,
+ 0x4c,0x30,0x8,0x6b,0xb0,0x5,0x8c,0xf0,0xc,0xc7,0x45,0xa8,0x56,0xf6,0x74,0xf9,
+ 0xe0,0xf,0xf0,0x50,0xf,0xc9,0xea,0xf,0xe2,0x40,0x6,0x39,0x60,0x2,0x2f,0x70,
+ 0x2,0x40,0xf0,0x62,0x44,0xf0,0x5,0x52,0x0,0x5,0x3a,0xc0,0x1,0x36,0x80,0x89,
+ 0x4d,0xb0,0x1,0x30,0xf3,0x0,0x2c,0xd0,0x55,0x19,0x70,0xb5,0xe5,0x22,0x2c,0x0,
+ 0x4,0x32,0xf6,0xf2,0x50,0x6a,0x90,0x2,0x99,0x40,0x5e,0x74,0xa7,0xf,0xd8,0x60,
+ 0x81,0xff,0xd6,0x7c,0x68,0xfb,0xe,0x19,0xba,0x83,0xa9,0xf6,0xa1,0xac,0xf7,0x2b,
+ 0x51,0xe8,0x2a,0x29,0xeb,0x3b,0x77,0x3b,0xbc,0xb4,0xa3,0xb7,0x3c,0xe5,0x5a,0xe7,
+ 0x24,0x2f,0x7a,0x90,0x2,0x91,0x79,0xa1,0x88,0xb8,0xe,0xa3,0x47,0xa4,0x8a,0xb,
+ 0xf,0xd8,0xa0,0xe,0xac,0xfe,0x20,0x2,0x5e,0xf0,0x2,0x23,0x70,0x7,0x1d,0x70,
+ 0x3,0x63,0x40,0x4,0x1f,0x30,0x3,0x5e,0x80,0x5,0x3c,0xc0,0x12,0x44,0xf0,0x4a,
+ 0xae,0x24,0x5,0x1f,0x10,0x1,0x6d,0xd4,0x68,0x9,0x8b,0xba,0xf5,0xd2,0x40,0x2,
+ 0xd4,0xba,0xc0,0xa0,0xf,0xde,0xa0,0x60,0xf8,0xd9,0x77,0x5f,0x7a,0xbb,0xb9,0xcb,
+ 0xf,0xda,0x40,0x70,0x28,0x80,0x8,0x23,0x3,0xbf,0x2a,0x4b,0x85,0xc3,0x7b,0xc0,
+ 0xc5,0xeb,0x28,0xcf,0xe8,0x28,0x41,0x40,0x8d,0xbf,0x36,0xc,0xfa,0xc0,0xb8,0x63,
+ 0x58,0x67,0x4a,0x96,0xb8,0x53,0xf7,0xe,0x7a,0x66,0xf,0xef,0x20,0xe,0x3d,0x60,
+ 0x89,0x32,0x36,0x42,0x61,0xe0,0x2,0x67,0x90,0x42,0x1c,0x90,0x3,0x7,0x51,0x3,
+ 0x5b,0x60,0x4,0xfe,0xf4,0x0,0x80,0x0,0x5,0x1c,0xd0,0xab,0x9,0x6b,0xc0,0xdf,
+ 0x23,0xbf,0x84,0x20,0x7,0x3b,0x40,0xd,0xb0,0x86,0xbf,0xb3,0x5b,0xbb,0xfc,0xe9,
+ 0x83,0xb8,0x6b,0x6a,0x79,0x46,0xf,0x53,0x89,0x9,0x4a,0x90,0x5,0x74,0xbb,0x3d,
+ 0x27,0x3b,0xb7,0x7,0xcc,0xa9,0x2d,0x9b,0x4e,0xae,0x65,0x10,0x82,0xa0,0x56,0x98,
+ 0xf0,0xd,0xb0,0xa8,0x64,0xc1,0x55,0x8b,0xe6,0x90,0xd,0xff,0x8b,0xf,0xa1,0x76,
+ 0x72,0xf8,0x70,0xa,0x22,0x10,0x7,0x39,0xb0,0x1,0xfa,0xa,0x46,0x1c,0x80,0x5,
+ 0x67,0x30,0x4,0x48,0x29,0x6,0x14,0x90,0x51,0x9b,0xa0,0xb,0x7e,0x10,0x2,0x13,
+ 0x2,0xc3,0xa7,0x2b,0xc3,0xb2,0x2,0x92,0x20,0x19,0x45,0x81,0xf0,0xd,0x9b,0xd5,
+ 0xd,0x63,0x4b,0xb6,0xfe,0x3c,0xfc,0x88,0x3e,0x88,0x65,0x25,0x66,0xe,0xcf,0x87,
+ 0xf,0xbf,0xa0,0x1,0x6b,0x60,0x5,0xef,0x92,0x80,0xbe,0x5b,0x2f,0x4b,0x8c,0xb7,
+ 0x7c,0x98,0x28,0x8f,0x91,0x38,0x6e,0xe0,0x2,0xd4,0xd8,0x8,0x2d,0x10,0xb,0xf8,
+ 0x30,0xe,0xa5,0x36,0x65,0xbd,0x15,0x70,0x7,0x89,0x5c,0xe2,0x20,0xe,0xfa,0x70,
+ 0x7f,0xec,0xf0,0xe,0xdf,0x90,0x2,0x2e,0x90,0x5,0x44,0xd0,0xaa,0xdf,0x71,0x6,
+ 0x1f,0xb0,0x1,0x6c,0xc9,0x61,0x17,0x90,0x9,0xbf,0x50,0x52,0xa2,0x20,0x2,0x72,
+ 0xf0,0x1,0x74,0x9c,0x43,0x46,0xa3,0x3b,0x47,0x9c,0x2e,0xc,0xf4,0x5,0x84,0xd0,
+ 0x8,0x3a,0xba,0x5b,0xf8,0x9,0xc8,0x5f,0x9a,0xa1,0x58,0x56,0x77,0x2a,0xe7,0x77,
+ 0x4,0x87,0x9,0x64,0x0,0x7,0x8d,0xfc,0xad,0x2a,0x1b,0xc9,0xf2,0xd5,0x73,0x94,
+ 0x1c,0x24,0x66,0x36,0x6,0x74,0xb0,0x6,0x75,0xf0,0x7,0x50,0x35,0xe,0xe0,0x50,
+ 0x6a,0xe8,0xb0,0xe,0x9f,0xd7,0xe,0xed,0xa0,0x57,0xcf,0xa0,0xc,0xa5,0xf0,0x9,
+ 0xcf,0xf0,0x85,0xdb,0x80,0xd,0xf8,0x50,0xa,0x22,0xf0,0x4,0x4c,0x70,0x42,0x1c,
+ 0xe0,0x5,0x2e,0x80,0x94,0x6b,0xa0,0x1,0x15,0xf0,0x9,0xc3,0x80,0xf,0x7e,0x46,
+ 0xb,0x4,0xc0,0x4,0x1b,0xf0,0xcb,0x88,0x39,0x56,0x16,0xa3,0x5,0x41,0x0,0x83,
+ 0xd,0x45,0x8,0x9b,0x80,0xf,0xef,0xe0,0xc7,0xfe,0x30,0xbb,0x64,0x3b,0x7a,0x4b,
+ 0x46,0xc8,0xb5,0x88,0x9f,0xa4,0x2c,0xb,0x28,0xe0,0x7,0x67,0xd3,0x2e,0x98,0xf8,
+ 0x28,0x91,0x46,0xfe,0xb2,0xda,0x2c,0xc9,0x12,0xe3,0x3b,0x58,0x82,0x3e,0x8e,0x32,
+ 0x5b,0x8d,0xa0,0x1,0x9f,0x20,0x90,0xf6,0x0,0xe,0xe0,0xd0,0x92,0x4e,0xd6,0xe,
+ 0xf1,0xd0,0x57,0xc3,0x0,0xa,0x1a,0xa0,0x4,0x6,0xf0,0xa,0xf6,0x60,0xd,0xe1,
+ 0x15,0xe,0xca,0xd0,0x3,0x3b,0x90,0x5,0x39,0xb0,0x48,0x37,0xf0,0x98,0x6d,0x5c,
+ 0xa,0x36,0x68,0xd1,0xe1,0x50,0xd,0xf9,0xd7,0x0,0x59,0xb0,0x78,0xee,0x1b,0x29,
+ 0x8a,0x79,0x36,0x31,0xdd,0xc0,0x84,0x20,0x4,0xfe,0x83,0xcc,0x1,0x77,0x9f,0x80,
+ 0xcc,0xd1,0xcf,0xac,0x9f,0xdb,0x90,0x57,0xdf,0xf0,0x9,0x4a,0x50,0x4,0x1,0x14,
+ 0x6,0x6c,0x77,0xd2,0x68,0xe3,0x2a,0xef,0x68,0xc7,0x4b,0x9c,0x63,0xe,0x44,0x14,
+ 0x40,0x41,0x4,0x7e,0xd0,0x8,0x15,0x60,0xb,0x73,0x65,0xf,0xf7,0x47,0x5e,0x33,
+ 0x9,0x61,0x10,0x56,0xb,0x98,0x40,0x3,0x83,0x62,0x4,0x4b,0x0,0xaa,0x84,0xed,
+ 0x6a,0xdf,0x10,0xa,0x10,0x99,0x5,0x2a,0x10,0x2,0x7c,0x80,0x1,0x6f,0x90,0xa,
+ 0x72,0x57,0x9f,0xc0,0x65,0xd,0x91,0xb8,0x4,0x62,0x10,0x2,0x7,0x8b,0x28,0xb8,
+ 0xa7,0x36,0x99,0x24,0x40,0x44,0xd0,0x43,0x29,0xf0,0x7,0xcd,0x70,0x9f,0x7d,0x57,
+ 0x81,0xcf,0xa,0x75,0x69,0xdd,0x77,0xf7,0xe7,0x72,0x54,0xd9,0x3,0x89,0x20,0x6,
+ 0x35,0xa0,0x6,0x8a,0x90,0x3,0x8b,0x70,0xd2,0xd6,0x15,0xb7,0x78,0x8d,0xc0,0x90,
+ 0xb6,0xd7,0xfd,0x38,0x10,0x43,0x50,0x6,0x8e,0x9d,0x9,0xcf,0x40,0x57,0xd9,0xb0,
+ 0x67,0xfa,0xfe,0x10,0x60,0x25,0x25,0xf,0xb0,0x70,0x9,0x79,0xf0,0x6,0x13,0x70,
+ 0x7,0xa3,0xd0,0xa,0x3d,0x80,0x4,0xb3,0x10,0xd9,0xec,0xa0,0xf,0xc5,0x60,0x0,
+ 0x8d,0xa0,0x4,0x4a,0x20,0x3,0x6f,0x10,0xb,0xca,0x60,0x57,0xd5,0x10,0xe,0xf6,
+ 0x60,0x62,0x95,0x69,0xbf,0x48,0x7a,0x3,0x7f,0x51,0x2,0xa6,0x5d,0x5f,0xc5,0x62,
+ 0x9,0x4c,0x10,0x49,0x15,0x85,0x2,0xc1,0x90,0x7c,0xc9,0x47,0x5c,0xb0,0x8d,0xd6,
+ 0x75,0xa7,0xbf,0xbf,0xa5,0x81,0xe7,0xf5,0xb,0x2d,0x50,0x7,0x89,0xe0,0xca,0x96,
+ 0xd0,0x4,0xf0,0x62,0xd7,0x3b,0xb6,0xd2,0x7a,0x6d,0x2f,0xf,0x41,0x10,0x39,0x0,
+ 0xb8,0x6,0x30,0xb,0x73,0xb5,0xe,0xef,0x47,0xf,0x7e,0x46,0xd,0xb2,0xf0,0x3,
+ 0x68,0x80,0x6,0x12,0x80,0x4,0xf3,0xb6,0x90,0x91,0x80,0x2,0x76,0xf0,0x6c,0xd4,
+ 0xb6,0xe,0xf2,0xa0,0x9,0xe9,0xd7,0x6,0xb1,0x30,0xd,0x62,0x1b,0xe,0xbe,0x65,
+ 0x62,0x80,0x6a,0xf,0xe1,0xe0,0xd,0x3e,0x10,0xa2,0xf7,0x9d,0xdf,0x6a,0xd0,0x2e,
+ 0xf0,0x2,0x41,0x19,0xb3,0x5,0x4a,0xf0,0x6,0x76,0x30,0xd,0x1,0x7,0xc8,0xfb,
+ 0x49,0xdb,0x7d,0x37,0x60,0x4a,0xf6,0xe,0x80,0x27,0xf,0xbf,0xb0,0x54,0x64,0x90,
+ 0x5,0x8a,0x70,0x4,0x46,0x3e,0xdc,0xaf,0x52,0xdc,0xc4,0x7b,0xdc,0x18,0x4e,0x10,
+ 0x1f,0x34,0x8,0x64,0x0,0x6,0xcc,0xf0,0xe,0xeb,0x60,0xe,0xf3,0xc0,0xd,0x76,
+ 0xf5,0xc,0xa9,0xf0,0x6,0x3e,0xf0,0x7,0x12,0x80,0x6,0xb0,0x80,0x59,0x23,0x45,
+ 0x93,0xfe,0x17,0x70,0x1,0xb6,0xa0,0xf,0xe3,0x60,0xf,0x57,0x56,0xc,0xcc,0x86,
+ 0x59,0xd5,0x60,0xf,0xe3,0xf0,0x85,0x82,0x9e,0xac,0x41,0x58,0xd,0xcc,0xa0,0x1,
+ 0x5c,0xb0,0x78,0x2f,0x4a,0xe4,0x46,0x4e,0x98,0x74,0x20,0x4,0x88,0xb0,0x5,0x8d,
+ 0x50,0x7,0x59,0x2a,0x7a,0x4f,0x39,0xe5,0xa0,0xbe,0x9f,0x7,0x1e,0xe5,0x76,0x36,
+ 0x70,0x72,0x5,0xc,0x12,0xa0,0xdb,0x70,0xf0,0x5,0xf0,0x12,0x69,0x15,0xae,0xcd,
+ 0x39,0xd6,0x26,0x66,0x3e,0x6,0x45,0xa0,0x4,0xac,0xa0,0xe,0xe7,0x90,0x72,0x76,
+ 0x35,0xb,0x4,0x20,0x3,0x22,0x20,0x3,0x92,0x50,0xb,0xf4,0x99,0x5b,0xc8,0x35,
+ 0x52,0x76,0x80,0x4,0x76,0x80,0xf,0xf0,0xed,0xf,0xff,0x4b,0x52,0x37,0xf8,0x74,
+ 0x6d,0xae,0x88,0xee,0xb0,0x59,0xaa,0x2a,0x68,0x80,0x81,0xdf,0x70,0xe2,0x36,0x95,
+ 0x8e,0xd2,0x59,0xb0,0x3,0x73,0x90,0x54,0xa9,0xa0,0xec,0xf6,0xc7,0x77,0x1f,0x1d,
+ 0xea,0xa2,0xe,0xea,0xfa,0x96,0xa1,0x73,0x66,0xd0,0xf8,0x0,0xc,0x15,0xf0,0x6,
+ 0x46,0x40,0x7,0xe9,0xf2,0x44,0x76,0x2d,0xe6,0x77,0x1b,0xeb,0x2d,0x32,0x10,0x58,
+ 0x20,0x1e,0x45,0xf0,0x6,0xcc,0xa0,0xe,0x65,0xeb,0xf,0xde,0x30,0xd,0x92,0x20,
+ 0x3,0x80,0x30,0x9,0xba,0x90,0x5b,0x72,0x46,0xa8,0x51,0x89,0xf,0xab,0x50,0x1,
+ 0x28,0xd0,0xb,0x3b,0x2a,0x8e,0xa9,0xc6,0xa7,0xd4,0x86,0x60,0xba,0x9b,0x90,0xc8,
+ 0xc5,0x9,0x45,0xd0,0x1,0x57,0x10,0x3,0x93,0x9e,0xed,0x9,0xa,0x2f,0x5d,0x20,
+ 0xfe,0x8,0x29,0x10,0x8,0x2d,0x80,0x9,0x50,0xa5,0xb1,0xae,0x66,0x6a,0x53,0x8e,
+ 0x6d,0x2d,0xd9,0x64,0x8b,0xf8,0x6f,0xad,0xa6,0xce,0xed,0x10,0x60,0x72,0x35,0xc,
+ 0x1a,0x10,0x8,0x66,0x43,0x98,0x3a,0x66,0xef,0x76,0x8b,0xef,0x58,0xa2,0xef,0xcd,
+ 0x92,0x5,0xad,0x20,0xf,0xdf,0x50,0x62,0xf0,0xb0,0xf,0xc6,0x45,0xa,0x18,0x80,
+ 0x7,0xba,0x10,0x60,0x9d,0xb7,0xa1,0xa2,0x96,0xb8,0xf8,0xe0,0xc,0x38,0xe0,0x7,
+ 0x92,0xe0,0xd,0xf0,0xbd,0xd,0xf0,0xa7,0xcc,0x94,0x49,0xe0,0xda,0x30,0x67,0x1,
+ 0x36,0xad,0x34,0x90,0x4,0x30,0xa,0xf2,0xd8,0xee,0x1c,0x2f,0x88,0x36,0xf2,0x12,
+ 0x8,0x9e,0x60,0x95,0xb0,0xa9,0xe,0x9c,0x15,0x75,0xe1,0x25,0x72,0x1d,0xdd,0x77,
+ 0xf2,0x37,0xea,0x4e,0xe7,0x5b,0xf7,0xa9,0xbb,0x74,0xc5,0x62,0xbf,0x20,0xda,0x63,
+ 0xa0,0x2b,0xd6,0xa5,0x31,0x95,0x54,0xc0,0x90,0xcc,0xc4,0xda,0x43,0x31,0x59,0x5b,
+ 0xb2,0x55,0x48,0x38,0xf,0x91,0x5,0x81,0x40,0x9f,0xef,0x80,0x77,0xf0,0xb0,0xd,
+ 0xf6,0xcb,0xc,0x3e,0x80,0x1,0x95,0xf0,0x5f,0x4c,0xd6,0xa3,0xa2,0xc6,0x77,0xe7,
+ 0x65,0xa,0xfa,0x74,0xc,0x39,0x8,0x7f,0xb4,0x78,0x81,0xe9,0xa0,0x7c,0x7,0x69,
+ 0xd0,0x7f,0x36,0x1,0x1f,0xa0,0xbd,0x6a,0x8f,0x28,0x66,0x46,0xbe,0x6e,0x40,0x4,
+ 0x90,0x40,0x3,0x48,0x90,0xa3,0xff,0xd5,0x59,0xa2,0x67,0xd6,0xe4,0x5e,0xd4,0xae,
+ 0xd6,0x59,0xd0,0x97,0x81,0xa,0xf6,0xcc,0x60,0x68,0x81,0x84,0xba,0x88,0x48,0xfe,
+ 0x86,0xf,0xbd,0x80,0x1,0xf9,0xa,0x4,0x71,0x10,0x5,0x35,0x0,0x8a,0xe3,0x4a,
+ 0xae,0xc1,0x7b,0x41,0x59,0x1b,0xf9,0x8e,0xe3,0x36,0x64,0xf3,0x8e,0xb5,0x52,0x8,
+ 0x51,0x0,0xd0,0x45,0xb7,0xa7,0xe2,0x3e,0x86,0xf6,0x8b,0xf,0xae,0x40,0x3,0x14,
+ 0x80,0xc,0x38,0x1e,0xe8,0xd6,0x16,0x5e,0x99,0x79,0xf5,0x17,0x60,0x7,0xa1,0xa0,
+ 0xf0,0xf1,0xd0,0xe,0x3d,0x58,0x7f,0xe1,0x85,0x67,0x0,0xc1,0x8f,0x9e,0x3c,0x71,
+ 0xf2,0x62,0xd1,0x8,0x31,0xe5,0xc4,0x89,0x11,0x26,0x4a,0xa8,0x81,0x18,0x51,0x4d,
+ 0x98,0x42,0x3c,0xa,0xd,0xe1,0x23,0x6,0x8c,0xad,0x69,0xde,0xd6,0x7d,0x5c,0xe7,
+ 0xce,0x1f,0x3f,0x73,0xeb,0xfc,0x85,0xb4,0x67,0x4f,0xdf,0x3b,0x96,0xf8,0x5c,0x4e,
+ 0xc3,0xd7,0x52,0xdf,0xca,0x99,0x1f,0x4f,0x9a,0xf4,0x37,0x92,0x9f,0xbf,0x6e,0xfa,
+ 0xa6,0xf9,0x92,0x1,0x8,0xc8,0x95,0x42,0x82,0x52,0x1c,0x5a,0x3,0xc7,0xcc,0x52,
+ 0x33,0x6b,0x9a,0xc2,0x81,0x5a,0xa6,0x8c,0x1c,0xa9,0x70,0xa4,0x4e,0xc,0x13,0xe6,
+ 0x8c,0x1c,0x35,0x4a,0xd7,0xa4,0x31,0xb3,0xc8,0x46,0xa1,0x20,0x70,0xf4,0xd4,0xa9,
+ 0x20,0x8b,0x5a,0x4c,0x7d,0xee,0xf8,0xf1,0x73,0xa7,0xf2,0x1b,0xb2,0x1e,0x4b,0x3c,
+ 0xc5,0xb4,0xc7,0x2e,0x65,0x5c,0x7d,0xdf,0xf0,0x7d,0xf3,0xe4,0x23,0xc1,0x30,0x79,
+ 0xf2,0xe2,0xdd,0xbb,0xe7,0x2f,0xa5,0x3d,0x77,0x22,0xfd,0x69,0x53,0xe7,0xb7,0x16,
+ 0x98,0x14,0x52,0x46,0x20,0x38,0x11,0xc3,0xa1,0xc4,0x88,0x72,0xc2,0x10,0xfe,0x62,
+ 0x42,0xc7,0x8f,0x6,0x56,0xf8,0xce,0xbd,0x5b,0xb7,0xaf,0xb1,0xbb,0x7c,0xeb,0x76,
+ 0xfa,0x7b,0x37,0xd3,0x9b,0x3e,0x7c,0xcc,0x6c,0xa1,0xa,0x75,0x4a,0x96,0xad,0x61,
+ 0x7e,0x5d,0x7a,0x8b,0xad,0x2f,0xa7,0x3f,0x74,0x8b,0xf7,0xe5,0x5c,0x17,0x1b,0xdf,
+ 0x2e,0xc,0x62,0xf8,0x30,0x51,0x21,0xa8,0x6,0x54,0xa8,0x4b,0x95,0x52,0xb7,0xaa,
+ 0x46,0xea,0xf6,0x32,0x10,0xe5,0x78,0xfe,0x5e,0x46,0xa9,0x19,0x38,0x61,0xd8,0xe4,
+ 0x20,0x82,0x68,0x4e,0x8f,0x50,0xe2,0x5c,0xbe,0xf3,0xe7,0xd6,0x1c,0x3c,0x7e,0xfa,
+ 0xa8,0xc9,0xb,0x85,0xa3,0xc2,0xb0,0x98,0xe7,0xf4,0x75,0x8b,0xed,0x1b,0x79,0x70,
+ 0xa9,0x84,0xb,0x40,0x8,0xc8,0xc5,0x25,0xc4,0xf8,0xc9,0x8b,0x1d,0x76,0xb6,0xf1,
+ 0x7,0x9b,0x9e,0x5c,0xc2,0x25,0x92,0x6,0x8a,0x90,0xc2,0x84,0x17,0x5e,0xd0,0xec,
+ 0x21,0xce,0xb4,0x93,0x4a,0x10,0x23,0x1a,0xc1,0x64,0xad,0x95,0x4c,0xda,0x67,0x9b,
+ 0x6d,0xf6,0x31,0xe9,0xbf,0x99,0xde,0xa1,0xf0,0x11,0x1c,0xc0,0x0,0x3,0x5,0x14,
+ 0x5a,0x68,0xc1,0x8e,0x4c,0x6c,0x79,0x46,0x1d,0x7c,0x66,0x12,0x6e,0x31,0x21,0xed,
+ 0x81,0xd,0x46,0x7c,0x7e,0xb9,0x20,0x90,0x1a,0x6e,0xd8,0x23,0xc,0xaa,0xaa,0xc2,
+ 0x8e,0x3a,0xee,0xb8,0xeb,0xec,0x3b,0xaa,0x40,0x94,0x23,0x8a,0x30,0xe8,0xc8,0x62,
+ 0x87,0x3a,0x18,0x59,0x8b,0xad,0x93,0x46,0x82,0xa7,0x9e,0x7b,0x7c,0x2c,0x46,0x1,
+ 0x34,0x56,0x91,0xc7,0x19,0x7c,0xe4,0xf1,0x51,0x1e,0x5e,0x1c,0xb9,0xfe,0xc0,0x8f,
+ 0x7,0x58,0x10,0x85,0x99,0xd8,0xde,0x8a,0xcb,0x41,0x22,0xb1,0x99,0xe9,0x9c,0x69,
+ 0x7a,0xf1,0xa1,0x39,0x2e,0x1e,0x70,0xe1,0x8c,0xf,0x4c,0xd8,0xec,0x43,0xf1,0xb6,
+ 0xd8,0xa2,0xe,0x30,0x9c,0xf1,0x4b,0x1f,0x7b,0x70,0x72,0x67,0x1b,0xc7,0x92,0xd3,
+ 0xe7,0x99,0x37,0x4d,0x89,0x64,0x89,0x3a,0x2,0x21,0x63,0xb,0x3d,0x6,0xe1,0xc2,
+ 0x8f,0x37,0xc0,0xc8,0x43,0x16,0x97,0x56,0x7a,0x27,0x25,0x3f,0xed,0x41,0x7,0x9d,
+ 0x9c,0xe8,0xc1,0xc7,0x47,0x5e,0x2a,0x20,0x83,0x8f,0x2b,0xae,0xd8,0xca,0x4a,0x2b,
+ 0xb9,0xc3,0x8e,0x2b,0x88,0xa6,0xfc,0x2e,0x2b,0x65,0x8f,0x20,0x24,0x8b,0x35,0xea,
+ 0x40,0x81,0x9a,0x6f,0xd4,0x89,0xed,0x26,0x7b,0xf6,0xa9,0xa7,0x1e,0x6e,0x70,0xc5,
+ 0xa7,0x13,0x34,0x24,0x70,0x86,0x1c,0x71,0xc9,0x81,0x5,0x8d,0xa,0x68,0xf4,0x81,
+ 0x14,0x65,0x58,0x1a,0xd2,0x4f,0x7a,0xb4,0xd1,0xc7,0x1b,0x75,0xa6,0x21,0x65,0x82,
+ 0x3b,0x59,0xb8,0x21,0x84,0x10,0x44,0x50,0x61,0x86,0x46,0x39,0xb3,0x62,0xd,0x25,
+ 0xa0,0xfd,0xc5,0xbd,0xd8,0x18,0x6b,0x8c,0x56,0x91,0x0,0xa5,0xed,0x4d,0x56,0x7a,
+ 0x50,0x62,0x8d,0x53,0x7,0x29,0xa3,0x8b,0x26,0x86,0x90,0xc3,0xf,0x25,0x34,0xc8,
+ 0x63,0x15,0x13,0x63,0xb5,0x67,0x1c,0x91,0x85,0x1c,0xe9,0x9e,0x77,0xf1,0x29,0x6,
+ 0x5,0x31,0x62,0x88,0xe3,0xc,0x65,0x5f,0x76,0x52,0x3b,0xea,0xac,0x0,0xf,0xc4,
+ 0xed,0x3c,0x33,0x8f,0xd,0x9d,0xe5,0x80,0xc3,0x88,0x55,0x9f,0xfe,0xf9,0xe6,0x45,
+ 0xc6,0x70,0xda,0x87,0x9f,0x7a,0xde,0x4a,0xee,0x18,0x5,0x18,0x71,0xa5,0x9c,0x65,
+ 0x68,0x79,0x44,0x1,0x47,0x7e,0x40,0xc2,0x14,0x66,0xf0,0xf1,0xa6,0x1a,0x69,0x86,
+ 0x5c,0xec,0xcd,0xfb,0x7e,0xa9,0x44,0x84,0x7,0x74,0x0,0xc2,0x83,0x19,0xa4,0x28,
+ 0x42,0x84,0x22,0x5c,0xf8,0x57,0x22,0x38,0x94,0x88,0xa4,0x8d,0x55,0xf0,0x99,0x66,
+ 0xa6,0xf8,0x12,0xde,0xeb,0x2d,0x7f,0xfa,0xc2,0x7,0x97,0xb,0xc8,0xd0,0x3,0x8e,
+ 0x2e,0x82,0xd0,0xf2,0x8c,0x33,0xbc,0x8,0x82,0x88,0x41,0x10,0x59,0x55,0x96,0xab,
+ 0x2d,0x45,0x67,0x1b,0x7b,0x24,0x37,0xee,0x9e,0x6c,0xef,0xd1,0x6,0x1f,0x61,0x30,
+ 0x0,0xe4,0xe,0x97,0x61,0x56,0x96,0x2a,0xec,0x26,0xe2,0x6a,0xca,0x32,0xb2,0x62,
+ 0x23,0x8e,0x2a,0xd8,0xa0,0x23,0x85,0x46,0xc0,0x40,0xe6,0x47,0x4b,0x73,0x72,0xe7,
+ 0x38,0x9a,0x86,0xb3,0x27,0x1c,0x7d,0x1e,0x41,0xa1,0x8e,0x56,0x94,0x68,0x1,0x9,
+ 0x14,0xd0,0x80,0xc5,0x3d,0x6a,0x2d,0xb5,0x87,0x1f,0x78,0xe6,0x39,0x7a,0x6f,0x7c,
+ 0xa,0x72,0xc6,0x94,0x16,0x64,0x60,0x61,0x6,0x10,0x40,0x0,0x2,0xa,0x29,0xb8,
+ 0xa8,0x61,0xed,0xb6,0x23,0x82,0x23,0x10,0x30,0x34,0x9,0xf3,0x1a,0x7f,0xf6,0xc9,
+ 0xc7,0x9d,0xe2,0x52,0x5a,0x27,0x1d,0xb8,0xde,0x39,0xe7,0x19,0x14,0xde,0x40,0x44,
+ 0x70,0x37,0xa,0x29,0x84,0x8d,0x42,0xb2,0x72,0x83,0x2a,0x2b,0x6a,0x48,0x84,0x1,
+ 0x62,0xf1,0xb1,0xa2,0xed,0x24,0x25,0xe8,0x10,0x89,0xd1,0xfe,0xea,0x41,0xf,0x1f,
+ 0xf5,0x42,0x6,0x52,0x18,0x83,0x1a,0x3c,0xe3,0x32,0x36,0xbc,0x4c,0x3c,0x4f,0xc1,
+ 0xca,0x93,0x6e,0x86,0xba,0x38,0xb4,0x2c,0xb,0x75,0x40,0x82,0x30,0xb0,0x86,0x40,
+ 0xb7,0xc0,0x65,0x6f,0xca,0x41,0x9e,0x5e,0xaa,0x1,0xc,0x14,0x90,0x60,0x7,0x5b,
+ 0x20,0x1,0x18,0x72,0xe1,0xd,0x7c,0xc4,0xe3,0x1a,0xfa,0xa8,0x55,0xf2,0xe6,0xb1,
+ 0xc3,0x5,0xba,0x44,0x1e,0xd4,0x58,0x5,0xa,0x34,0x20,0x6,0x11,0xac,0x40,0x7,
+ 0x71,0x0,0x41,0x9,0x80,0xf0,0x81,0x1b,0x70,0xe1,0x6,0xfe,0xf2,0x10,0x67,0xe0,
+ 0xf0,0x86,0x48,0x50,0x4a,0x1d,0xfa,0xa0,0xc7,0x4e,0xe2,0x22,0x24,0x77,0xb8,0x4f,
+ 0x72,0xfa,0x78,0x5,0x12,0x96,0x20,0x6,0x2b,0x28,0x4b,0x67,0x6e,0x60,0xca,0xe9,
+ 0x9c,0x34,0x6,0x48,0x90,0x26,0x68,0xf4,0xe0,0x46,0x3d,0xe8,0xb3,0xe,0x92,0x19,
+ 0xed,0x1e,0xfa,0xf0,0x91,0x2f,0x68,0xe0,0x87,0x1a,0x58,0x81,0x10,0x61,0x70,0xc1,
+ 0xfd,0x42,0xe7,0x95,0x35,0x64,0x90,0x3b,0x74,0xa0,0x3,0x21,0xba,0x90,0xa8,0x33,
+ 0x8c,0x81,0x2,0x98,0xe0,0xf,0x3e,0xc2,0x91,0x40,0xbd,0xed,0xad,0x61,0x3f,0x12,
+ 0xd2,0x3b,0x1e,0x71,0x81,0x16,0x70,0x62,0x17,0x31,0x41,0x7,0x3d,0xcc,0xf4,0x91,
+ 0xc6,0x28,0xf0,0x1e,0xf1,0x78,0x53,0x31,0x58,0x21,0x46,0x25,0x18,0xa1,0x8,0x45,
+ 0xb8,0x81,0xe,0x74,0x60,0x3,0x1b,0xcc,0xc0,0x96,0xb6,0x5c,0xc1,0xf7,0x20,0x2,
+ 0x7,0x1a,0xfc,0xc2,0x37,0xda,0x20,0x9,0x5c,0x86,0xfe,0xe4,0x96,0x74,0xb8,0x43,
+ 0x77,0xca,0x40,0x41,0x23,0xe0,0x80,0x15,0x9d,0x39,0x29,0xd,0x87,0x0,0x8b,0x1b,
+ 0xcc,0x73,0x86,0x1b,0x24,0x2,0x5,0x73,0xc3,0x87,0xe5,0xb2,0xb5,0x8f,0x3,0xa6,
+ 0xc4,0x1f,0xf7,0xd8,0x89,0x7f,0x6,0xd5,0x82,0x44,0x18,0x21,0xb,0x72,0x50,0xc4,
+ 0x6,0xf2,0x97,0x15,0x9e,0x35,0x65,0xd,0x34,0x73,0x52,0x78,0xe4,0x20,0x4,0x2b,
+ 0x10,0x81,0xe,0x83,0xe8,0x82,0x1c,0x8c,0x80,0x89,0x63,0xe4,0xea,0x1c,0x8c,0x79,
+ 0x4b,0x25,0x67,0xe2,0x92,0x1f,0xdd,0x2d,0x25,0xcc,0x78,0xc5,0x2f,0xde,0x53,0x9c,
+ 0xe1,0xc,0x87,0x45,0xd,0xa3,0x6,0x2f,0x34,0xf1,0x3,0x1c,0x18,0x81,0x8,0x44,
+ 0x28,0xc2,0x45,0x89,0x70,0x83,0x1b,0xb8,0x40,0x7,0x33,0xb0,0x41,0xc,0x4a,0xa0,
+ 0x19,0x5d,0x76,0xc5,0xf,0x6e,0x9a,0x16,0x1c,0xf9,0x34,0xcc,0x74,0xa4,0x43,0x2f,
+ 0x7f,0xf1,0x84,0x12,0xe0,0x80,0xb3,0xcf,0xc1,0x21,0xd,0x73,0x0,0x8b,0x16,0x74,
+ 0xc6,0x6,0x37,0x14,0x61,0x9,0x38,0x80,0x85,0x4b,0x44,0x59,0x8f,0x9c,0x70,0x11,
+ 0x27,0x34,0x39,0x92,0x6,0xea,0x90,0x88,0x1a,0xa8,0x40,0x11,0x4d,0x18,0xa4,0x3b,
+ 0x97,0x69,0x25,0x65,0x31,0xc1,0x12,0x83,0x10,0x81,0x1e,0x2,0xa1,0x4,0x4c,0x30,
+ 0xa3,0x52,0xc2,0xf1,0x7,0x34,0x2,0x9a,0x13,0x20,0xb9,0x44,0x27,0x7a,0xd3,0x87,
+ 0x7f,0xde,0xa1,0xbb,0x94,0x8c,0x43,0x25,0x40,0xa2,0x8d,0x3a,0x90,0xa1,0x8a,0x46,
+ 0xb4,0xa0,0x7,0x6d,0x98,0x43,0x12,0x6c,0xa0,0xfe,0x83,0x1c,0x24,0x1,0xa3,0xaf,
+ 0xdc,0xe8,0xc,0x80,0x10,0x83,0x11,0x8c,0xa0,0x43,0x1f,0x52,0xc3,0x18,0xfc,0xf0,
+ 0x8d,0x69,0xa9,0x3,0x9c,0x6f,0x19,0x66,0x7c,0xb6,0x81,0x8e,0x70,0xbc,0xa9,0x11,
+ 0x5b,0x80,0x67,0x56,0x76,0x79,0xd3,0x34,0x94,0x41,0xb,0xe6,0xa1,0x48,0x16,0xc8,
+ 0xd0,0x86,0x1f,0xa0,0xa2,0x1c,0xf8,0xa0,0x7,0x3d,0x70,0xc7,0x45,0xe4,0x74,0xc3,
+ 0x25,0xbf,0xa8,0xc0,0x1f,0x94,0x50,0x3,0x39,0x4,0xe1,0x73,0xed,0x7c,0x8a,0x55,
+ 0xd4,0xc8,0x4e,0x22,0x84,0x4f,0x52,0x9f,0xb8,0xda,0x6c,0x56,0x72,0x9c,0x80,0xbe,
+ 0x6,0x48,0xa9,0x5,0x27,0x3c,0x94,0x4b,0x12,0x6c,0x1c,0x27,0x27,0xc,0xb,0x47,
+ 0x35,0x68,0xf8,0x8d,0x61,0xc4,0x42,0x12,0x32,0x10,0x1,0x17,0x98,0x20,0x82,0x14,
+ 0x30,0xc1,0x6,0x2f,0xb0,0x1,0x14,0xfc,0x5a,0x84,0xee,0x5,0x76,0xb0,0x85,0x2d,
+ 0x41,0x49,0xd5,0x70,0x3,0x5d,0xc8,0x3,0x1f,0xd7,0xc8,0x86,0xd1,0x14,0xa3,0x17,
+ 0x6f,0xc6,0x87,0x1d,0xe1,0x38,0x87,0x38,0x68,0x41,0x1,0x41,0x4c,0x85,0x9d,0x5d,
+ 0xc1,0xce,0x54,0x3c,0xa3,0x5,0x2e,0xed,0xa0,0x11,0x3d,0xc0,0x1,0x2b,0xdc,0x3,
+ 0x2b,0xda,0x2d,0x66,0x7d,0x64,0xf5,0xb,0x30,0x62,0x9b,0x88,0x2c,0x74,0x21,0x74,
+ 0x17,0x5c,0x83,0x53,0xac,0x92,0xb3,0x33,0xe4,0x80,0xf,0x46,0x0,0x61,0x28,0xfc,
+ 0xe2,0x8d,0x9c,0xd8,0xca,0x26,0xd,0xb5,0x64,0x4e,0x8a,0x5b,0x5c,0x73,0xec,0x84,
+ 0x61,0xbf,0x61,0xc6,0x2e,0x48,0x91,0x8,0xfe,0x19,0x4c,0xe0,0x95,0x45,0xb0,0x98,
+ 0x9,0x6c,0xd0,0x87,0xd,0x1,0xc1,0x6,0x43,0x18,0x6f,0x46,0x3b,0x6a,0x3,0x20,
+ 0x70,0xe8,0xb0,0x1f,0x1a,0x83,0x14,0xc4,0x20,0xc,0xf7,0xc0,0x91,0xa8,0xd,0xaa,
+ 0x6f,0x71,0xfa,0x12,0x8b,0x16,0x20,0x42,0x8,0x5a,0x90,0x66,0x18,0xc4,0x3,0x87,
+ 0x2c,0x24,0x59,0xa,0xc7,0xa,0xd1,0x13,0x4,0xb1,0x85,0x35,0x88,0xc1,0x8,0xae,
+ 0xa0,0xc6,0x8b,0x54,0x6b,0x92,0x2d,0x7a,0x73,0x27,0x7c,0x63,0x61,0x1d,0x8c,0x30,
+ 0x8,0x9c,0x89,0xce,0x9d,0x4e,0x39,0x5d,0xea,0xe2,0x50,0x88,0x2e,0x24,0xe2,0x2,
+ 0xa7,0xf8,0xcb,0x3b,0x8e,0xe3,0xe,0x9c,0x8c,0x69,0x38,0x40,0xca,0x47,0x25,0x1b,
+ 0xda,0xd2,0x74,0xac,0x83,0x36,0xf2,0x48,0x46,0x2c,0x3c,0xf1,0x6,0xec,0x72,0x54,
+ 0xa,0x6e,0x50,0x84,0xa2,0x22,0xd0,0x41,0x8,0xbc,0xc0,0xc7,0x36,0xc8,0x1,0x90,
+ 0x93,0xc0,0x51,0x17,0x78,0x94,0x51,0xa7,0x8e,0xa2,0x44,0xc6,0x70,0x7,0x11,0xfc,
+ 0xa1,0x16,0xf8,0x68,0x7,0x62,0xfa,0x44,0xdf,0x9c,0xbc,0xc3,0x53,0xb2,0x40,0x81,
+ 0x12,0x28,0x61,0x5,0x37,0xf4,0x5a,0xb,0xe2,0x59,0x43,0x16,0xee,0x30,0x94,0x33,
+ 0xa8,0xa1,0x29,0x69,0x78,0xe6,0x13,0xe8,0x10,0x6,0x1b,0x18,0x82,0x5,0xb1,0x60,
+ 0x86,0xdd,0xb2,0x25,0x4c,0xe3,0xbc,0x85,0x36,0x6b,0xf9,0x85,0x6,0x2,0x31,0x8,
+ 0x43,0x42,0xe5,0x2b,0x60,0xc9,0x73,0x15,0xe2,0xb0,0x7,0x3e,0x8,0xf0,0x55,0x23,
+ 0x71,0x1f,0x3f,0xd6,0x81,0xd,0x7f,0xfe,0xa8,0x96,0xac,0x40,0x5a,0x4d,0x4a,0x80,
+ 0xb4,0x18,0xbd,0x78,0xa3,0x16,0x8c,0xa8,0x3,0xd,0x52,0x90,0x2,0x23,0x6c,0xe1,
+ 0x9,0x65,0xc4,0xc2,0x86,0xfa,0x10,0x7,0x26,0xca,0x41,0x7,0x50,0x8,0x2f,0x14,
+ 0x14,0xe,0x5,0xbe,0xf2,0x35,0x7,0x2e,0xe8,0x28,0x14,0x11,0xab,0x6,0x2f,0xe0,
+ 0x81,0x2,0x76,0xe0,0x45,0xae,0x66,0x32,0xcc,0xbe,0xc8,0x83,0x15,0x28,0x0,0x9c,
+ 0x10,0x8,0xe1,0xeb,0xaa,0xf8,0x81,0xb,0x57,0x98,0xc2,0x15,0xbc,0xd0,0x95,0x6f,
+ 0x8b,0x99,0xe,0x5e,0x30,0xc4,0x14,0xee,0x40,0x80,0x58,0xf8,0x85,0x1e,0x96,0x33,
+ 0x20,0xc9,0x4e,0xf2,0x23,0xbf,0xfc,0xa2,0x5,0x46,0x18,0x83,0xe1,0xb6,0x2,0x87,
+ 0x6f,0x27,0x25,0xc,0xaa,0x9b,0x42,0x1c,0xa4,0x30,0x1,0x5a,0xc8,0xc3,0xe6,0xf7,
+ 0x68,0x31,0x49,0x6e,0xd5,0xee,0xd4,0xe,0x27,0x1f,0x6,0x55,0xc9,0xab,0x74,0x87,
+ 0x50,0x24,0x68,0x1b,0xe,0x4c,0xe0,0xc3,0x20,0xb2,0xe0,0x6f,0x2b,0xc,0xe1,0xbb,
+ 0x4e,0x18,0x1,0x10,0xb6,0x27,0x82,0x24,0xe4,0x20,0x7,0xb,0xa7,0xa5,0x2c,0x75,
+ 0x50,0x6a,0x88,0xbb,0x0,0x8a,0x63,0xc0,0x7b,0x95,0xe4,0x10,0x2,0x31,0xd0,0x0,
+ 0x5,0xae,0x32,0xd,0x4b,0xe8,0x28,0x6f,0x79,0xb4,0xc2,0x9c,0x35,0xc8,0x2,0x21,
+ 0xe8,0x10,0x1e,0x28,0x59,0x41,0xd,0x2e,0x13,0x5d,0x80,0xfd,0xcb,0xce,0x9,0x28,
+ 0x18,0xb5,0x2b,0x3d,0xe0,0x40,0xfd,0x61,0x8e,0xbd,0x9d,0x3,0x1f,0xbd,0xa0,0x81,
+ 0x14,0x80,0x90,0x74,0x37,0xd4,0xfe,0xa0,0x11,0x87,0x38,0x44,0x16,0xbc,0xd0,0x7,
+ 0x27,0x38,0xe1,0x4,0x71,0x10,0x41,0x2e,0xdc,0x3,0xeb,0x58,0xa3,0x98,0xea,0xa9,
+ 0x55,0xb4,0xf2,0xc4,0xea,0xf,0x98,0x14,0x86,0x1a,0xb1,0x78,0x43,0xa,0xb8,0xc0,
+ 0x87,0x2f,0xc8,0x81,0x9,0xc7,0xef,0xc2,0xf1,0x99,0x70,0x84,0x23,0x34,0x81,0xf9,
+ 0x47,0x18,0xc2,0x45,0x93,0x30,0x84,0x21,0xb8,0x3d,0x7,0x72,0x9f,0xfb,0x2d,0xed,
+ 0xbe,0x82,0x12,0x94,0x0,0xef,0x11,0xf4,0x8e,0x1c,0xec,0xc9,0x87,0x2c,0x88,0xe1,
+ 0xd,0xa6,0x8,0xd3,0x8f,0xba,0x91,0x92,0x73,0xb4,0x2,0x34,0x8a,0xb7,0x2,0x1d,
+ 0xac,0x60,0x3a,0xfa,0xd7,0x7f,0x3b,0x4d,0xb0,0x84,0x12,0x58,0x21,0xf,0xe1,0x34,
+ 0x86,0xbe,0xe8,0x8,0xe,0x9d,0x80,0xd,0x9f,0x0,0xa,0x45,0x18,0x8a,0x42,0xa0,
+ 0x84,0x1d,0x38,0x84,0x1d,0xb0,0x82,0x3d,0x40,0xb9,0x11,0xb8,0x83,0x9,0xc8,0x5,
+ 0xdf,0x88,0x35,0x93,0x51,0x8c,0xbd,0x51,0x31,0xc4,0x78,0xac,0xd7,0x8,0x28,0x9,
+ 0xc9,0x15,0x79,0xd8,0x85,0x39,0x10,0x83,0x22,0x90,0x83,0x3d,0x38,0x82,0xf0,0x6a,
+ 0x82,0x2e,0x50,0x41,0xe5,0x63,0xc1,0x16,0xa4,0xbe,0x17,0xac,0xbe,0x87,0xb3,0xbb,
+ 0x19,0xc0,0xbe,0xee,0xf3,0xbe,0xbc,0xb,0xbf,0x31,0x50,0x84,0x1b,0x50,0x81,0x49,
+ 0x20,0x83,0x1e,0x30,0x85,0x36,0xf9,0x8b,0x1f,0xa9,0x86,0x57,0x48,0x1,0x7b,0x22,
+ 0x4,0x2b,0x88,0x3f,0xfb,0x63,0x42,0xd3,0x69,0x96,0x1f,0x7c,0x5,0x50,0x12,0x89,
+ 0x2d,0x9a,0x37,0xe7,0xb2,0xfe,0xa4,0xe5,0x68,0xe,0x3e,0xb8,0x28,0x41,0xc8,0x2,
+ 0x4a,0x90,0xe,0x33,0xd0,0x18,0x14,0x88,0x24,0x75,0x58,0xb3,0xf5,0x21,0x12,0xdb,
+ 0x43,0x43,0x6c,0x68,0x11,0x1,0x31,0x5,0x88,0xc9,0x82,0x65,0xba,0x18,0x28,0x18,
+ 0x82,0x14,0x5c,0xc1,0x16,0xb4,0x43,0x18,0xa4,0x3e,0xb7,0x2b,0x35,0x5b,0xaa,0xc1,
+ 0xee,0xfb,0xbe,0x2a,0x9,0x82,0x5e,0x93,0x3,0x3a,0x78,0x1b,0x14,0x78,0x4,0x72,
+ 0x28,0x8c,0xc2,0x38,0x85,0xb,0x10,0x3,0x42,0x0,0xd,0x22,0x88,0x3f,0x3a,0x68,
+ 0xc2,0x49,0x84,0x83,0x31,0xdb,0x2,0x32,0x68,0x1,0x55,0xf8,0x6,0x96,0x10,0x40,
+ 0x95,0x18,0x12,0x9e,0xa0,0xa1,0x23,0x49,0x92,0x2c,0x60,0x2,0x37,0x68,0x2,0x17,
+ 0x48,0x8f,0x46,0x68,0x3,0x34,0x28,0x6,0x79,0x20,0x7,0xd4,0x9a,0x2f,0x5a,0x43,
+ 0x43,0xdc,0x29,0xaa,0xb7,0x52,0x87,0x67,0xc8,0x4,0x14,0x58,0x82,0xa4,0xb0,0x82,
+ 0x2f,0x8,0x83,0x3d,0x68,0x82,0x15,0xa0,0xc3,0xe4,0xb3,0x43,0x17,0xc4,0x43,0x3d,
+ 0x9c,0xc1,0x3e,0xbc,0x41,0xf0,0x93,0x20,0x39,0x58,0x84,0x40,0x5c,0x84,0x23,0x20,
+ 0x2,0x3d,0x98,0x83,0x36,0xc8,0x84,0x5b,0x48,0x6,0x64,0x88,0x84,0x16,0x8,0x84,
+ 0x2c,0x90,0x3f,0x48,0x2c,0x3,0x25,0x9c,0xc4,0x26,0x34,0x83,0x34,0xd8,0x82,0x1a,
+ 0x40,0x15,0x19,0xd0,0xc4,0x1f,0xc1,0x39,0x59,0x39,0x20,0x5b,0xd9,0x7,0x7a,0xc0,
+ 0x23,0x7c,0xd8,0x95,0x40,0x98,0x84,0x2b,0x78,0x1,0x43,0x68,0x82,0x41,0xa8,0xc6,
+ 0x65,0x28,0x7,0x44,0xfe,0x7c,0xaf,0xe2,0x0,0x7,0x70,0xa0,0x2f,0xae,0x31,0xc8,
+ 0xbd,0x89,0x8c,0x64,0x40,0x82,0x4,0x68,0x84,0x35,0x28,0xaf,0x2e,0xf0,0x2,0xe7,
+ 0x1b,0x46,0x62,0x2c,0x46,0xe5,0xc3,0xc3,0x18,0xdc,0x43,0x1a,0x94,0x3b,0x1b,0xfc,
+ 0xc3,0xf0,0x5b,0x4,0x2f,0xe0,0x81,0x33,0x28,0x4,0x37,0x30,0x8b,0x39,0xa8,0x83,
+ 0x1e,0xa8,0x83,0x39,0x28,0xa7,0xaf,0x93,0x8a,0x25,0x5c,0xc2,0x71,0xb4,0x3f,0x33,
+ 0x58,0x40,0x38,0x20,0x2,0x39,0x28,0x82,0x14,0x18,0x20,0xd4,0x2,0xa7,0x7c,0x60,
+ 0x7,0xb7,0xaa,0x23,0x93,0xc9,0x1c,0x5e,0x50,0x19,0x20,0xe8,0x83,0x13,0x58,0x84,
+ 0x2e,0x78,0x24,0x34,0x40,0x85,0x62,0x28,0x7,0x79,0xf8,0x27,0x76,0x20,0xc8,0xc6,
+ 0x50,0xc,0x83,0x5c,0xc,0xb2,0x9a,0x6,0x6a,0x10,0x6,0x14,0x40,0x82,0x46,0x48,
+ 0x1,0x74,0xac,0xa7,0xe5,0xb,0xb5,0x31,0x60,0x2,0x15,0xa4,0xc8,0x8a,0x64,0x82,
+ 0x8b,0x44,0x46,0x3e,0xdc,0x48,0x3f,0xc4,0xc1,0x66,0x54,0x81,0xfb,0x39,0x3,0x69,
+ 0xea,0x2,0x33,0x40,0x4,0x12,0xb8,0xac,0x14,0xc8,0x2,0x4b,0xd8,0x80,0x41,0x44,
+ 0x24,0x71,0x94,0x44,0x98,0xac,0x3f,0xa5,0xa0,0x4,0x22,0x70,0x83,0x3d,0xb8,0x1,
+ 0x3f,0x68,0x1,0x59,0x70,0x93,0xfe,0xd3,0x8b,0x82,0x24,0x12,0xc4,0x30,0x93,0xcc,
+ 0xf9,0x5,0xce,0x89,0x3,0xd6,0xbb,0x2,0x39,0xd8,0x82,0x43,0xe8,0x81,0x16,0x88,
+ 0x84,0x5d,0xf8,0x86,0x73,0xd8,0x1a,0xe5,0x79,0x8d,0xa9,0xe4,0x1a,0x4b,0xb2,0x8f,
+ 0x5d,0xd0,0x80,0xfe,0x25,0x48,0x4,0x31,0x78,0xc3,0x2e,0xb8,0xa8,0x60,0x91,0x82,
+ 0x1b,0x18,0xcb,0x3a,0x34,0xcb,0xb3,0x3c,0x46,0x19,0x54,0x4b,0x59,0xe2,0xc8,0xb6,
+ 0xfc,0xe,0x42,0x20,0x82,0x1c,0x38,0x9c,0x30,0x70,0x83,0xff,0x81,0xa6,0x35,0xa0,
+ 0xb3,0x21,0xf0,0x2,0x39,0x98,0xbf,0x70,0x94,0x44,0x22,0x0,0x4c,0xfb,0xb3,0x82,
+ 0x2e,0x18,0x49,0x37,0xa0,0x83,0x1a,0x98,0x83,0x4,0x90,0x85,0x5,0x5b,0x8d,0xf8,
+ 0x58,0x9f,0xab,0xd3,0xa6,0x76,0x68,0x20,0x19,0x10,0x2c,0x27,0xb8,0x3,0x29,0xc8,
+ 0x2,0x74,0xe4,0x3,0x39,0x10,0x81,0x4a,0xf0,0x85,0x1f,0x31,0x9a,0xd1,0x24,0xcd,
+ 0xaa,0x2c,0x2b,0x5a,0x30,0x82,0x14,0xd0,0x3,0xf2,0xa2,0x3,0x22,0xf0,0xc5,0x28,
+ 0x8,0x82,0x2e,0x18,0x83,0xef,0x20,0xcb,0xb2,0xac,0x48,0xb4,0xc4,0x4d,0x8d,0xd4,
+ 0x4d,0xb6,0xfc,0x3e,0xbc,0x53,0x42,0x78,0x32,0x9c,0x30,0xe8,0xa,0xeb,0xc8,0x33,
+ 0x36,0xd0,0xa0,0xe7,0x6c,0x42,0xcf,0xa8,0x20,0xaa,0x58,0x8a,0x35,0x68,0x4,0x3,
+ 0x60,0x85,0xa0,0x41,0xa0,0xb1,0xa2,0x15,0x37,0x43,0x8c,0x21,0xd4,0x23,0x19,0xb8,
+ 0x81,0x22,0x90,0x1,0x23,0xe0,0x2,0x29,0x80,0x2,0x20,0x30,0x84,0x8,0x34,0x85,
+ 0x82,0x68,0x87,0xd4,0x72,0x37,0xac,0x53,0x9,0x18,0xf9,0x6,0x5e,0xa8,0x3,0x2e,
+ 0xc8,0x82,0x2c,0xe8,0x45,0xbc,0xfb,0x82,0x2f,0x8,0x82,0xfe,0xc,0x50,0xb2,0xac,
+ 0xcd,0xe3,0x7b,0x41,0xeb,0xa3,0x3b,0x17,0x58,0x81,0x15,0x98,0x81,0x26,0xe5,0x3e,
+ 0x4,0x4d,0xfe,0xd0,0x31,0x80,0x8a,0xc4,0xf2,0x2,0xc3,0x51,0x4e,0xeb,0x98,0x88,
+ 0x9d,0xa1,0xd0,0x71,0x3c,0xba,0x38,0xd0,0xb2,0x72,0x5c,0x8a,0x2c,0x40,0x4,0x1a,
+ 0x50,0x85,0x82,0x52,0x20,0x7f,0xc8,0x87,0x1c,0x7a,0x4c,0x81,0x98,0x8d,0x41,0xf9,
+ 0x84,0x58,0xf8,0x5,0x5c,0x28,0x85,0x46,0x10,0x83,0x10,0xd8,0x3,0x1b,0x38,0x3,
+ 0x2e,0xa8,0x83,0x3c,0x68,0x45,0xf7,0xd2,0x7,0x93,0x30,0x89,0x6d,0x58,0xd3,0xb4,
+ 0x72,0x89,0x60,0x40,0x83,0x2d,0x8,0x52,0xbc,0xd3,0x92,0x30,0x88,0x2,0xfe,0x24,
+ 0xd2,0x22,0x15,0xd0,0x62,0x4c,0x52,0x64,0x2c,0xb5,0x26,0x7d,0xd2,0x26,0xdd,0xcd,
+ 0x29,0xb5,0x2,0x2e,0xc3,0x3b,0x2f,0xb8,0x52,0x0,0x8b,0xa,0xad,0xd8,0x8a,0x2e,
+ 0x9d,0xc4,0x30,0x10,0x37,0x2d,0x43,0x36,0xb0,0x20,0x84,0x26,0x52,0x47,0xa1,0x32,
+ 0x93,0x5a,0xdc,0xb,0x9c,0x8,0x8e,0xe0,0x78,0x93,0x37,0x1,0x86,0x52,0x20,0x1,
+ 0x3f,0xe8,0xd1,0x2d,0x68,0x84,0xa,0xb8,0x5,0x79,0xb8,0x6,0xf5,0x33,0x34,0xd8,
+ 0xc8,0x95,0x62,0xb8,0x4,0x14,0xc8,0x82,0x47,0xc5,0x3b,0x65,0x79,0xd4,0x21,0xd,
+ 0x82,0x2f,0x90,0xd4,0x23,0xb5,0xcd,0x18,0x94,0xc1,0x4b,0x75,0x52,0x28,0xdd,0xd4,
+ 0x4,0xed,0xd4,0x2c,0xf8,0x2,0x29,0x38,0x9c,0x62,0xeb,0x54,0xa5,0x98,0xa,0xc3,
+ 0xb1,0x19,0x53,0xad,0x3f,0x39,0x68,0xa6,0x72,0x4,0xb7,0x42,0x38,0x82,0xed,0x69,
+ 0x81,0x57,0x70,0xaf,0x1a,0x8d,0x4f,0x7b,0xb8,0xba,0xf3,0x11,0x34,0x33,0x41,0xc,
+ 0x54,0xfe,0x7a,0x1e,0x60,0x60,0x84,0x1e,0x8,0x84,0x35,0x30,0x82,0xba,0x64,0x13,
+ 0xf7,0x2a,0xa8,0x2b,0xc4,0x87,0x64,0x68,0x3,0xbc,0xea,0xb2,0x30,0x18,0x3,0x87,
+ 0x75,0xd8,0x28,0x10,0x52,0x68,0x8d,0x54,0xda,0x34,0xcb,0x4a,0xbd,0x56,0x26,0xcd,
+ 0x56,0x4d,0x95,0xd2,0x4,0x85,0x8a,0xa0,0x3b,0x3,0x2c,0x30,0xd7,0x0,0xd3,0x2c,
+ 0x74,0xad,0xd0,0x27,0x31,0x3,0xa9,0x90,0x3,0x37,0x8,0x82,0x1b,0x18,0x4,0xe0,
+ 0xb1,0xbc,0x17,0x91,0x55,0x5a,0x61,0xa8,0x91,0xa8,0x87,0x79,0x88,0x23,0x70,0x42,
+ 0xc8,0x6f,0x58,0x85,0xa,0x68,0x84,0x2c,0x70,0xd9,0x1e,0xf8,0x4,0x71,0xf0,0x8d,
+ 0x17,0x71,0x89,0x64,0xf8,0x83,0x25,0x30,0x2,0x38,0x50,0xc2,0x31,0xb0,0x82,0x31,
+ 0xf8,0x82,0x28,0x18,0x3,0x8a,0x5,0x55,0xc4,0x9,0x50,0x6a,0xc5,0xd8,0x25,0xc5,
+ 0x54,0x6d,0xed,0xd8,0xef,0x73,0x3c,0xc3,0xd9,0xa9,0x62,0xab,0x8e,0xd,0x73,0x50,
+ 0x93,0xb5,0xbf,0xf1,0x20,0xdb,0xac,0x20,0x84,0x2f,0x18,0x84,0x1a,0x58,0x83,0x1d,
+ 0x20,0x81,0x1,0x52,0xb3,0xf3,0x41,0x89,0x10,0xd5,0x89,0x69,0x7b,0xb,0x35,0xdc,
+ 0x9b,0x61,0x5,0x6,0x24,0x40,0x84,0x1b,0xe8,0x2,0xc4,0x8c,0x4,0xa7,0x93,0x1d,
+ 0x3c,0x62,0x6,0x46,0x20,0x1,0x38,0xc8,0x81,0x26,0x70,0xda,0x5,0xfd,0xd1,0x20,
+ 0x1d,0x52,0x50,0x7d,0xd4,0x61,0xc4,0xda,0x3c,0xb4,0x54,0x8d,0xcd,0xd4,0x28,0x5d,
+ 0xc6,0x29,0x95,0xa0,0x33,0xd0,0xb3,0x38,0xa8,0xa0,0xb,0x4a,0x59,0xcf,0x30,0xdb,
+ 0xfe,0x98,0x9c,0x83,0x39,0x30,0x3,0x75,0xed,0x20,0x36,0xe8,0x2,0x4a,0x20,0x33,
+ 0x87,0x24,0x4,0x11,0x80,0x36,0xbb,0xc1,0x39,0xca,0x71,0x33,0xce,0x43,0x1e,0xd6,
+ 0xea,0x86,0x6f,0x70,0x86,0x48,0x48,0x81,0x41,0xe0,0x3,0x55,0x41,0x82,0x64,0x20,
+ 0x28,0xba,0xc9,0x83,0x25,0x18,0x84,0x15,0xe8,0x83,0x29,0x8,0x3,0xa6,0x75,0x5c,
+ 0x69,0xed,0x2,0x21,0x7d,0x54,0x2f,0x88,0x2,0xca,0x3d,0xd2,0xac,0xa5,0xbb,0xad,
+ 0xe5,0xd8,0xcd,0x4d,0x50,0x9,0xd2,0x8a,0x9d,0xca,0x8a,0xaa,0x50,0xd9,0x9,0x2d,
+ 0x5d,0xee,0x30,0x83,0xd3,0x4d,0x5d,0x36,0x48,0x55,0x22,0x78,0x2,0xa4,0x30,0x3,
+ 0x41,0x8,0x2,0x42,0xa0,0x80,0x9c,0x14,0xe,0xbd,0xd1,0x39,0xc5,0x40,0x9e,0x71,
+ 0xa0,0x2f,0xa9,0xc4,0x23,0x67,0x28,0x5,0xa,0x20,0x41,0x23,0x58,0x82,0x3f,0x20,
+ 0xc,0x82,0x70,0x4,0x24,0x8,0x4,0x26,0x60,0x83,0x29,0x78,0x1,0x2f,0x70,0x5c,
+ 0x25,0x84,0xde,0x20,0x8d,0xda,0x28,0x88,0x48,0x23,0xbd,0x5e,0xcb,0xcd,0x58,0x28,
+ 0xe5,0x5a,0xee,0xfd,0xbe,0x45,0xc5,0x8a,0x78,0x42,0x96,0xf2,0xd,0xcc,0xaf,0x18,
+ 0x5d,0x76,0x12,0x5d,0xa6,0x30,0x3,0x3d,0x20,0x81,0xfd,0xdb,0xc4,0xfb,0x4d,0x31,
+ 0xaa,0x34,0x89,0x77,0xe8,0x89,0x22,0x9c,0x0,0x3e,0x28,0x2,0x23,0x50,0x82,0x25,
+ 0xf0,0xc7,0x3a,0xa8,0x3,0x32,0xa8,0x30,0x2f,0xb8,0x2,0x2c,0x88,0x2,0x49,0xfd,
+ 0x2,0xa8,0xd,0xd2,0xc1,0x19,0xd2,0x26,0x50,0xe2,0xe7,0xa3,0x3e,0x26,0xb6,0xfe,
+ 0x5c,0x6b,0xcd,0xd8,0x25,0xd5,0xd8,0x6d,0x4d,0x50,0x9,0xee,0xc8,0x89,0x13,0x61,
+ 0xd3,0x19,0x8f,0xa5,0xd0,0xe2,0x2d,0x5e,0x8a,0x43,0x50,0x2,0x52,0xc0,0x9a,0xaa,
+ 0x14,0x28,0xb0,0x9a,0x45,0xe4,0xc8,0x89,0x69,0x70,0x85,0x9,0x80,0x4,0x81,0x45,
+ 0x84,0x35,0x10,0x85,0x27,0xe0,0xb2,0x5e,0xc,0x2,0xc4,0x89,0x56,0x9,0xb6,0x62,
+ 0x9,0x36,0x52,0x25,0x76,0x3e,0xe6,0x6b,0x62,0x3f,0xc6,0x60,0xeb,0x8b,0x62,0x29,
+ 0x76,0x1,0x2a,0xee,0xe0,0x45,0x6d,0x4b,0xc4,0xca,0xe2,0x29,0xf1,0xe2,0xb3,0x55,
+ 0x8a,0x27,0xd8,0x1,0x3f,0x30,0xd3,0x77,0xa8,0x6,0x22,0x29,0x63,0x33,0xb6,0xbd,
+ 0x13,0x6b,0x11,0x67,0xa0,0x85,0x16,0x20,0x81,0x40,0x60,0xcd,0x2f,0x80,0x8,0xbc,
+ 0xeb,0x82,0x5,0xc5,0x63,0x3c,0x36,0x62,0xe8,0x4d,0x3e,0x3e,0x76,0x62,0x27,0x86,
+ 0x62,0x25,0x25,0xe4,0x25,0x35,0x64,0x20,0x45,0x64,0x66,0x54,0xe4,0x45,0xde,0x8e,
+ 0x46,0x1e,0x5f,0xc6,0xab,0x8a,0x27,0xd8,0x82,0x2c,0xf0,0x3,0xc,0x78,0x85,0xff,
+ 0x18,0xab,0x33,0x46,0xb1,0x42,0x5b,0x7,0xd7,0x92,0x7,0x59,0x68,0x3,0x25,0x40,
+ 0x4,0x88,0xc4,0x82,0x68,0xf6,0x82,0x2f,0xb0,0x82,0x1e,0x8d,0xde,0x53,0x2e,0x62,
+ 0x3d,0x5e,0x41,0x56,0x6,0x64,0x57,0x16,0x64,0x58,0x8e,0xe5,0x52,0x9b,0xe5,0x54,
+ 0xbe,0xe2,0x5b,0xc6,0xe5,0x13,0xd6,0x2d,0xd0,0x79,0x12,0x38,0x38,0x4,0x3d,0xe0,
+ 0x2,0x2e,0x10,0x83,0x3f,0xf8,0x86,0xa1,0x62,0x90,0xfa,0x9a,0x45,0x9c,0xfe,0x28,
+ 0xb4,0x99,0xf0,0xb,0x5b,0x0,0x3,0x31,0xf0,0xae,0x2a,0x10,0x37,0x2c,0xf8,0x82,
+ 0x2c,0x30,0xc7,0x5e,0xc4,0xe6,0x54,0xde,0xe3,0x25,0xee,0x66,0x40,0x7e,0xe5,0xcb,
+ 0x8d,0xe5,0x71,0xb6,0xe2,0x44,0x76,0x94,0x73,0xc6,0x30,0xf2,0x98,0xbc,0x97,0x31,
+ 0x16,0x38,0xd8,0x82,0x1d,0x90,0x83,0xed,0xf1,0x84,0x79,0xde,0xa1,0x7a,0xb6,0xe7,
+ 0x4c,0x46,0x8e,0x13,0x33,0x7,0x7a,0x80,0x11,0x5c,0x68,0x81,0x41,0xf0,0x82,0xe,
+ 0x12,0xd9,0x81,0x2e,0x68,0x6c,0xce,0xe6,0x23,0xde,0x66,0x85,0x86,0xbe,0x21,0xf0,
+ 0xe6,0x6f,0x1e,0x64,0x29,0x86,0xe8,0x5a,0x9e,0x38,0x30,0x3b,0x67,0xaf,0xb0,0xe8,
+ 0x64,0xc1,0x68,0x35,0x8,0x98,0x1e,0x68,0x84,0xf,0xd8,0x83,0x7,0xf0,0x4,0x79,
+ 0xc8,0x86,0x90,0x76,0x61,0x63,0x1e,0xe,0xfa,0xd8,0x9b,0x6f,0x38,0x8,0x15,0xb8,
+ 0x52,0x2c,0x8,0x83,0x81,0x7e,0x82,0x27,0xb8,0xe6,0x53,0x46,0xe8,0x9a,0xee,0xe3,
+ 0x9b,0xce,0xe9,0x6f,0xe,0x67,0xba,0xeb,0xe9,0x22,0x96,0x68,0xce,0xa0,0x68,0x74,
+ 0xbe,0xe8,0x98,0x1,0x30,0x32,0xa0,0x85,0x4d,0x50,0x84,0xc,0x90,0x82,0x4d,0x28,
+ 0x87,0x78,0xd8,0xa1,0xf8,0x94,0xea,0x92,0xce,0x9,0xe5,0x82,0xd,0x75,0x90,0x87,
+ 0x52,0x20,0x3,0x32,0x7a,0x5a,0x69,0x85,0x60,0x99,0xe,0xeb,0x55,0xb6,0xe9,0x3f,
+ 0xbe,0xe9,0x86,0xde,0x69,0x59,0xee,0xda,0x29,0xa5,0xec,0xca,0x6e,0xeb,0xea,0x48,
+ 0xd9,0xc9,0x3b,0x2,0xf1,0xcb,0x82,0x41,0x48,0x1,0xb9,0x26,0x87,0xfe,0x52,0x10,
+ 0x3d,0x28,0x50,0x82,0xbc,0x66,0x1e,0x77,0xd0,0x5f,0xb7,0xea,0x6b,0x14,0xab,0x24,
+ 0xcf,0x13,0x7,0x56,0xa8,0x80,0x3a,0x30,0xce,0x2f,0xb8,0xd2,0x26,0xb8,0xe3,0x53,
+ 0xbe,0x5a,0xe5,0x7b,0xbe,0xdd,0x7e,0xec,0xdb,0x3c,0x6b,0x8d,0xdd,0xde,0xca,0x16,
+ 0xee,0xe1,0xbe,0x6c,0x29,0xf1,0xaf,0xef,0xe8,0x54,0x3f,0x20,0x83,0x37,0xa0,0x5,
+ 0x6a,0x10,0x7,0x5c,0xe0,0x2,0x28,0xd8,0x83,0x14,0x28,0x6,0x72,0x68,0x87,0x7a,
+ 0xe8,0x13,0xd5,0x5e,0xed,0xe1,0xd8,0xce,0x77,0xf0,0xb,0x20,0x8a,0xed,0x1d,0x28,
+ 0x83,0x3d,0x28,0x81,0x38,0x98,0x66,0x6c,0xce,0xed,0xe3,0xe3,0x6d,0x57,0xf6,0xed,
+ 0xb3,0xd6,0xe0,0x71,0x1e,0x6e,0xcb,0x2e,0xee,0x5d,0x2e,0x83,0x1e,0xd,0x84,0x46,
+ 0x40,0x82,0x5f,0x70,0xaf,0x6f,0x60,0x6,0x1a,0xf8,0xcf,0x1a,0x38,0x5,0xf7,0xba,
+ 0x87,0x2d,0xd2,0x8b,0xed,0xae,0xc5,0xc8,0xc9,0x89,0xcc,0x79,0x9e,0x4e,0x90,0x80,
+ 0x3a,0xc8,0x82,0x1c,0xf8,0x95,0xf3,0xc6,0x6d,0xb,0x56,0xef,0xf5,0xee,0x6d,0x18,
+ 0x74,0x68,0x29,0x7e,0xef,0xc9,0x8e,0x6f,0xf9,0x6e,0xeb,0x9b,0xe9,0xe,0x2e,0xb,
+ 0x84,0x3a,0xb0,0x83,0xd8,0x1,0xe,0x18,0x91,0x4,0x31,0xe0,0x99,0x36,0x70,0x93,
+ 0x77,0x58,0x9f,0x2,0x37,0x70,0xe2,0x98,0x1c,0x15,0x3b,0x19,0x79,0xe8,0x4,0x90,
+ 0xe3,0x83,0xf,0x38,0x1c,0x99,0x4e,0xef,0xe5,0xb3,0xf0,0x8b,0xb4,0xdc,0xdf,0xde,
+ 0x70,0xe,0xee,0x70,0xf,0xff,0xf0,0xf0,0xe8,0x54,0xd,0xb5,0xfe,0x3,0x65,0xc0,
+ 0x9a,0x83,0xf1,0x86,0x83,0x80,0x83,0x41,0x58,0x61,0xfe,0x1b,0x12,0xf8,0x30,0xf0,
+ 0x6a,0x71,0xd,0xb4,0x12,0x90,0x4c,0xe8,0x1,0x31,0x18,0x4,0xfd,0xe4,0x71,0xa,
+ 0xf7,0xf1,0xf5,0x6,0x72,0x8c,0x74,0xef,0xd,0x2e,0xf2,0x22,0xff,0x70,0x1,0xb,
+ 0xf,0xa2,0x23,0x3,0x24,0x58,0x8b,0xd9,0xc8,0x89,0x7c,0xb0,0x86,0x69,0x78,0x3,
+ 0x52,0xac,0x81,0x37,0x48,0x6,0x4b,0x49,0x18,0xd8,0x30,0x70,0xb8,0x52,0x31,0x3,
+ 0xb2,0x86,0x37,0xc1,0xb7,0x1d,0xf0,0xd1,0x30,0xb7,0x58,0xb,0xbf,0xf0,0x4a,0x15,
+ 0x72,0x34,0x4f,0xf3,0xf8,0x6e,0x6b,0xef,0x5,0x61,0xa2,0x6b,0x84,0xa6,0xfc,0x11,
+ 0xd7,0x68,0x31,0x7b,0xc0,0x7,0x56,0x10,0x3,0x48,0x4c,0x81,0x52,0x60,0x6,0x84,
+ 0x49,0xb1,0xed,0x6e,0x18,0x77,0xe3,0x87,0x62,0xd2,0x8b,0xbe,0x20,0x87,0x7f,0x9d,
+ 0x3,0x6f,0x45,0x6f,0x31,0x57,0xf4,0x32,0xcf,0x70,0xad,0x75,0xf4,0x47,0x17,0x6e,
+ 0xa,0x8d,0x8a,0x26,0xec,0xb6,0x35,0x98,0x3,0x30,0x28,0xc,0xac,0xc9,0x9,0xf7,
+ 0x49,0x7,0x7b,0x38,0x7,0x6a,0x50,0xa6,0x24,0x18,0x4,0xa,0xc0,0x85,0x6f,0xb8,
+ 0x6,0xce,0x8b,0xf1,0x2b,0xd4,0x7,0x16,0x89,0xb7,0xdc,0xf1,0x8b,0x64,0x70,0x4,
+ 0x1c,0xc0,0x2c,0x25,0xb4,0x66,0x8b,0xe1,0xe3,0x20,0x50,0x3e,0x29,0xf8,0x71,0x20,
+ 0x77,0xbb,0xb9,0xcb,0x3e,0xbb,0x63,0x52,0xe0,0xd6,0x5c,0x5b,0x57,0x77,0x5b,0x8e,
+ 0x8,0x28,0x31,0xee,0xf8,0x8b,0xbf,0xb5,0xed,0x2,0x8a,0xfe,0x8b,0x2,0x3a,0x10,
+ 0x83,0x1e,0x40,0x2,0x11,0x93,0x9d,0x86,0xca,0x7,0xc9,0x41,0x7,0x7d,0xc8,0x5,
+ 0xc,0xe0,0x82,0x81,0xc6,0x81,0xea,0x8e,0x7,0xb8,0x70,0x8c,0x9b,0x40,0x43,0xb8,
+ 0x2,0x92,0x86,0x9a,0x1c,0x22,0xa1,0x89,0x66,0x40,0x3,0x32,0x68,0xdb,0x2d,0x98,
+ 0x83,0x5f,0xee,0x82,0xef,0xda,0x10,0x1b,0x60,0x2,0x48,0x99,0xbe,0x32,0x7f,0x65,
+ 0x59,0xda,0xab,0x5a,0x32,0x1,0x7f,0xc9,0xa5,0x15,0xe0,0x0,0x94,0xe7,0x0,0xf8,
+ 0x5e,0x77,0xca,0x9e,0xb8,0x75,0xa6,0x8e,0x94,0x15,0x84,0x6f,0x64,0x2,0x35,0x88,
+ 0x82,0x42,0x20,0x4,0xeb,0xac,0x80,0x50,0x38,0xb7,0xd5,0x1a,0x92,0x6a,0x48,0x5,
+ 0x2,0x18,0x4,0x41,0xa8,0xc6,0x68,0x28,0x87,0xfe,0x3b,0xb1,0xf3,0x49,0x78,0xd3,
+ 0xb4,0x1b,0x34,0x14,0xd4,0x86,0xa,0x86,0x1e,0x38,0x4,0x8b,0xbf,0xf8,0x2c,0x70,
+ 0x81,0xb3,0x3,0x2f,0x26,0x18,0xbb,0x8f,0x97,0x75,0x41,0xa6,0x25,0x5a,0x3a,0xb5,
+ 0xb0,0x37,0x1,0xe,0x20,0xfb,0x95,0xe7,0xf0,0x96,0x77,0xf9,0xf,0x91,0x83,0x6,
+ 0x15,0x5d,0xb0,0x78,0x82,0x2c,0x28,0x3,0x3a,0xc0,0x1f,0x7,0xae,0x81,0x40,0x20,
+ 0xd,0x79,0xa8,0x1b,0x4c,0xe6,0x1a,0xdd,0x79,0x6,0x49,0xa0,0x1,0x31,0x50,0xf,
+ 0x46,0xc0,0x7b,0x5b,0x41,0x31,0x9d,0x63,0xf8,0x7b,0x6e,0x28,0x93,0xc0,0x87,0x5b,
+ 0x68,0x81,0x46,0x20,0x81,0x5f,0xfe,0x0,0x2f,0xf8,0x7a,0x1b,0x60,0xbe,0xe3,0xe3,
+ 0x7a,0x71,0xf7,0xfa,0xaf,0x17,0x7b,0x46,0x29,0x7b,0xfe,0xb2,0x67,0x79,0xb4,0x2f,
+ 0xe7,0x88,0x8,0x83,0x68,0x1e,0xba,0x63,0x5b,0x40,0x65,0x73,0x83,0x33,0xb0,0x1,
+ 0x17,0x80,0x83,0x39,0x48,0x4c,0x71,0xf0,0x91,0x6e,0xb0,0xbd,0x94,0xc0,0x86,0xc5,
+ 0x88,0x8d,0xbe,0xa5,0x81,0x49,0x8,0x81,0x1b,0xd8,0x84,0x98,0x80,0x8f,0xd7,0xd8,
+ 0x22,0x33,0x1c,0xe,0x7a,0x35,0xe6,0xe3,0x38,0x7,0x79,0xb8,0x85,0x4,0x20,0x83,
+ 0x22,0x48,0x82,0x23,0x80,0x2,0xde,0x6e,0x2,0x1e,0xe0,0x81,0x50,0x3,0xf9,0x6f,
+ 0xd6,0xfc,0xcd,0xef,0x7c,0xcf,0x3f,0x7b,0xd0,0xf,0x7d,0x88,0xf8,0x52,0xad,0x2e,
+ 0x3,0x76,0x45,0x36,0x41,0x10,0x84,0x31,0x0,0x62,0x39,0x50,0x2,0x1c,0x8,0xd6,
+ 0xf7,0x40,0xc3,0x33,0x94,0x71,0x7f,0xa0,0x21,0x59,0x40,0x82,0x22,0x50,0x88,0x19,
+ 0x10,0x5,0x1f,0xd1,0x86,0xc4,0x50,0x8c,0xe2,0x28,0xc8,0xc,0x84,0x4f,0xa7,0x7,
+ 0x8,0x7f,0x2,0xdf,0x7d,0x93,0xc7,0x8a,0x2,0x17,0x28,0x86,0x6c,0x1c,0x61,0x22,
+ 0x44,0x8,0x13,0x1e,0x2f,0x5e,0x40,0x19,0x62,0xf1,0x22,0xc6,0x1c,0x1a,0x35,0xda,
+ 0x30,0xe1,0xf1,0x23,0x87,0x90,0x22,0x45,0x96,0x28,0x39,0xe6,0x24,0xca,0x94,0x2a,
+ 0x57,0xb2,0x4c,0xa9,0xe6,0x25,0x4c,0x35,0x61,0xae,0x5c,0xf1,0xe2,0x65,0xc,0x1c,
+ 0x33,0x69,0xb6,0xac,0x11,0x94,0x85,0x8e,0xa5,0x23,0x45,0xc0,0xd4,0x12,0x87,0xf,
+ 0x9f,0xbe,0x6b,0x2,0xf9,0x9,0xf4,0x67,0x4f,0x5f,0x53,0x7f,0x50,0xd7,0xe9,0xfb,
+ 0xa6,0x4a,0x6,0x10,0x27,0x4e,0x1e,0x94,0x92,0xfe,0x7,0x15,0x9b,0x53,0x74,0xf6,
+ 0xc6,0xda,0x6b,0xca,0x8f,0x69,0xd4,0xb4,0xfe,0xf6,0x35,0xdd,0xa7,0xef,0x9d,0x37,
+ 0x7c,0xa0,0x26,0xb0,0xb8,0xe3,0xc5,0x61,0x96,0x2c,0x4d,0xae,0x4c,0xb4,0x81,0xf1,
+ 0xef,0x90,0x8d,0x1a,0x3f,0x82,0x1c,0x69,0xb8,0x64,0x89,0x96,0x8a,0x17,0xab,0x8c,
+ 0x9,0x33,0x8c,0xcd,0x33,0x5e,0x5e,0x5a,0xa9,0xc,0x7,0x4e,0x8d,0xcb,0x22,0x2,
+ 0xfd,0xfa,0x76,0xb4,0x1b,0xbe,0xa5,0x68,0x9d,0xea,0xd3,0xb7,0x4e,0x20,0xb6,0xd3,
+ 0xa5,0xf1,0x71,0xaa,0x3b,0x83,0xf,0x99,0x53,0xd3,0xf4,0x79,0xeb,0x6,0x55,0x2d,
+ 0xee,0xb4,0xeb,0x4e,0xb,0xdc,0x2d,0x50,0xdf,0x39,0x7c,0x95,0xc4,0x24,0x91,0x82,
+ 0xd7,0xca,0xde,0xbe,0x80,0x33,0xa,0x26,0x6c,0xc2,0x30,0x74,0xc4,0x8c,0xa7,0x2b,
+ 0x76,0xc,0xf3,0xa4,0x1a,0x2f,0x67,0xb6,0x9f,0x9,0xd3,0x5,0x4e,0x16,0x32,0x3d,
+ 0x1a,0x9,0xc3,0xa7,0xe,0xe9,0xd4,0xb3,0xa3,0xa5,0x9a,0xf6,0x77,0x9a,0xad,0xbf,
+ 0x77,0xef,0xd4,0x71,0x9a,0x0,0xa9,0x48,0x8a,0x16,0xaf,0xbc,0xd1,0x2e,0xed,0x4f,
+ 0xfd,0x59,0xec,0xdd,0x96,0x9b,0x7b,0xbc,0xe5,0xe3,0xe,0x3b,0xe8,0xc0,0x55,0x9f,
+ 0x18,0x35,0x30,0xc1,0x44,0x10,0x7b,0x55,0x61,0x43,0x45,0xcb,0x59,0x24,0x58,0xe,
+ 0xce,0x41,0x37,0x92,0x7,0xd2,0xb1,0xf4,0x5,0x88,0x21,0x82,0x68,0xdd,0x4b,0xd4,
+ 0x9d,0x64,0xc5,0x13,0x4f,0x94,0x11,0xc6,0x19,0x6c,0xf4,0x51,0x45,0x1c,0x7b,0x14,
+ 0xb1,0x6,0x12,0x8c,0x24,0x23,0xf,0x7a,0xfe,0x66,0xa9,0xf7,0x5b,0x69,0x3,0xa,
+ 0x44,0x56,0x38,0xfa,0x38,0x73,0x49,0x1b,0x3d,0x3c,0x31,0x8,0x5,0xa4,0x78,0x16,
+ 0xd7,0x3d,0xf5,0xcc,0x53,0xf,0x3c,0x68,0xd9,0x23,0x16,0x81,0x69,0xe5,0xc3,0xce,
+ 0x38,0xf6,0xbc,0x83,0xf,0x33,0x99,0x18,0xa0,0x47,0x8,0x1f,0xb0,0xf1,0x9c,0x17,
+ 0x47,0x98,0x79,0xc4,0x45,0x18,0x62,0x48,0xd8,0x86,0x22,0x79,0xf0,0xe6,0x9b,0x2d,
+ 0x89,0x28,0x22,0x89,0x6a,0x98,0x38,0x86,0x15,0x3b,0x65,0xf1,0x85,0x17,0x71,0xf4,
+ 0x31,0x5,0x10,0x2b,0x40,0xd2,0x42,0x1e,0xce,0x18,0xe5,0x23,0x80,0x4d,0xf5,0xe8,
+ 0xa3,0x53,0x63,0xf9,0xa3,0xd,0x3d,0xe4,0x5c,0xc2,0xc8,0x13,0x61,0x70,0x31,0x1,
+ 0x28,0x9e,0x5d,0x93,0x8d,0x93,0x4f,0x32,0x15,0x4e,0x96,0x65,0x55,0xd9,0x14,0x59,
+ 0x53,0x82,0x56,0x4c,0x26,0x34,0x14,0xb1,0x87,0xd,0x7b,0xe4,0x10,0xc2,0x17,0x52,
+ 0x98,0x99,0xa6,0x9a,0x1b,0xb1,0xd9,0x26,0x7,0x70,0xc6,0xf9,0xe1,0x9c,0x20,0xde,
+ 0xd9,0x52,0x9e,0x73,0x3c,0x61,0x85,0x17,0x7c,0x1,0x1,0x84,0x22,0x13,0x60,0xe2,
+ 0xc,0x35,0xf8,0xd0,0x33,0xaa,0x80,0x8c,0xea,0x33,0xd6,0x3a,0xf7,0xcc,0x13,0x4f,
+ 0x39,0x9a,0x98,0xc1,0x3,0x14,0x52,0xc8,0xe0,0x9,0x8e,0xf8,0xb4,0xe3,0x24,0x37,
+ 0xe6,0xac,0x13,0xe,0x59,0xd0,0xfe,0x98,0x25,0x3a,0x6c,0xe9,0x83,0x8f,0x33,0x60,
+ 0xf8,0xf1,0xc1,0x1e,0x2b,0x7c,0x31,0x48,0x11,0xb2,0xa2,0x79,0x61,0xad,0x83,0x15,
+ 0xd6,0xa6,0xae,0x1e,0xc8,0xd9,0xeb,0xfe,0x17,0xbf,0xb2,0x64,0xc5,0x16,0x87,0xc,
+ 0x62,0xc5,0x11,0x5e,0xdc,0x71,0xc6,0xa5,0x98,0x7c,0xa3,0x8e,0x3a,0xf4,0xdc,0x3,
+ 0x6d,0x8f,0x69,0x2d,0xba,0x4f,0x3d,0xf5,0xb4,0x23,0x4f,0x34,0x94,0x70,0x10,0x47,
+ 0x4,0x93,0x28,0xd1,0x46,0xb8,0x16,0x33,0xe5,0x4e,0xa9,0xea,0x3a,0xc5,0xee,0x7f,
+ 0xf7,0x9c,0x97,0xcc,0x1b,0x32,0xdc,0x20,0xc7,0xd,0x44,0x64,0xa1,0x2f,0xad,0xfd,
+ 0xde,0xa,0xb0,0xae,0x3,0xf7,0x6a,0xf0,0xc1,0x84,0xd0,0x41,0x44,0x17,0x74,0xc0,
+ 0xe1,0xc7,0x12,0x9e,0x9c,0xe7,0xcd,0x3a,0xfc,0x98,0xa3,0xd6,0xa2,0xfe,0x51,0xbd,
+ 0xa8,0x3f,0xe6,0xdc,0x83,0x8f,0x38,0xc8,0x6c,0xd1,0x84,0xd,0x6c,0xa8,0x1,0x47,
+ 0xf,0x79,0x34,0x7b,0x1e,0x54,0x7,0xa6,0xab,0xee,0xb4,0xd6,0x8,0x74,0xf,0x53,
+ 0xe7,0x31,0x13,0x49,0xcd,0x5c,0x74,0x71,0xc3,0x99,0x3d,0xd7,0xfa,0xf3,0x86,0x1,
+ 0xb,0x4d,0xf0,0xd0,0x26,0x86,0xc1,0x3,0x1b,0x77,0xd,0xb2,0x46,0xb,0x28,0x9c,
+ 0x62,0xde,0x3b,0x65,0xa5,0xc3,0x54,0x3e,0x4f,0x91,0x55,0x35,0x6e,0x19,0x67,0xed,
+ 0x4f,0x38,0xde,0x8,0xa3,0x41,0xa,0x74,0x34,0xb1,0x48,0x14,0x56,0xe8,0x51,0xc7,
+ 0x1f,0xcc,0x1c,0x15,0xe,0x3a,0xfe,0xb8,0x93,0x8e,0xcb,0x3c,0xda,0xb6,0x1b,0x3f,
+ 0xbb,0x81,0xf6,0x4d,0x26,0x14,0xe4,0x5b,0xd1,0xac,0xfc,0xba,0xb0,0x3b,0xef,0xbb,
+ 0xf3,0xd,0x9d,0xdf,0xbc,0x2,0x1e,0x38,0x75,0x61,0x4c,0x31,0xc5,0x15,0x72,0xe8,
+ 0xd1,0x43,0x1b,0xa8,0xc8,0x73,0xfe,0xde,0x3b,0x7,0xba,0xc3,0x72,0xa9,0xd3,0x52,
+ 0x1e,0x95,0x3b,0x52,0x39,0x7b,0xcf,0x3d,0xf4,0xbc,0xe5,0xb,0x6,0x7e,0xe8,0xb1,
+ 0x3,0x21,0x2e,0x10,0xa2,0x2,0x17,0x62,0xd0,0x20,0x89,0x32,0xef,0xe8,0x13,0xce,
+ 0x7f,0xf0,0xd4,0xd3,0xba,0x3f,0xde,0xbf,0xa5,0x3a,0x36,0x52,0xbf,0x4b,0x4d,0x29,
+ 0x13,0x44,0x10,0x7,0x14,0x72,0x17,0x98,0x1c,0xf4,0xae,0x77,0xbf,0x33,0x4c,0xf0,
+ 0x84,0x37,0x3c,0x10,0x55,0xc6,0xa,0x63,0x88,0x89,0x65,0x2e,0xf3,0xc0,0x16,0xf5,
+ 0xa1,0xf,0x3c,0xc8,0x82,0x12,0x70,0xb0,0x8a,0x70,0x75,0x3,0x1d,0xd3,0x9b,0xde,
+ 0xe4,0xaa,0x66,0xb9,0x7c,0xfc,0x87,0x1f,0x4f,0xd1,0x7,0x3d,0x52,0x28,0x1f,0x62,
+ 0x88,0x81,0xb,0x5c,0xe8,0x89,0x15,0xb4,0x10,0x84,0x30,0x44,0xe1,0xb,0x45,0x90,
+ 0xc1,0x1b,0x88,0x81,0x8f,0xc6,0xf1,0x3,0x1e,0x51,0xd2,0x98,0x8,0xfd,0x41,0xc2,
+ 0x14,0xaa,0x63,0x5a,0xa9,0x33,0x87,0xd6,0x8e,0x62,0x95,0x9,0xe4,0x4c,0xa,0x39,
+ 0xd0,0x81,0xd,0x6c,0xa0,0x91,0x9c,0x11,0x81,0x8,0x2e,0x98,0x41,0xc,0x62,0x70,
+ 0x40,0xe,0xc1,0x29,0x3,0x5d,0xf8,0x22,0x18,0xbb,0x50,0x30,0x96,0x90,0xc8,0xa,
+ 0x62,0x10,0x3,0x9f,0x6c,0xe2,0x5,0x2b,0xd4,0x20,0xd,0x3b,0x21,0x44,0x21,0xaa,
+ 0x70,0x3c,0xf,0xc8,0x21,0x10,0x38,0xa8,0x5,0x3e,0xf8,0x53,0x2a,0x51,0x89,0x70,
+ 0x40,0x8b,0xb2,0x47,0x3e,0xce,0x62,0xae,0xf8,0xac,0xe6,0x17,0x8d,0x90,0xc1,0x20,
+ 0xc6,0x50,0x86,0x20,0xa0,0xfe,0x24,0xc,0x34,0xec,0x42,0x16,0x52,0xf0,0x86,0xf2,
+ 0x4c,0xe3,0x1c,0xa6,0x31,0xc7,0x59,0x54,0xe3,0xbe,0x3f,0x2,0x92,0x84,0x3c,0xf2,
+ 0xa4,0x7b,0x7a,0xf4,0xe,0x5e,0x28,0xe0,0xd,0x45,0xd0,0x41,0xc,0x46,0xe0,0x84,
+ 0x17,0xe4,0x80,0x8,0x35,0xd8,0x81,0x11,0x6e,0x50,0x82,0x13,0x9c,0x20,0x6,0x88,
+ 0xb9,0x25,0x62,0xba,0x98,0x81,0x5d,0x5a,0x20,0x8c,0x61,0x6c,0x49,0x19,0xb7,0xb0,
+ 0x5,0x3e,0x61,0x1,0xb,0x67,0x18,0x83,0x19,0x76,0x90,0x86,0x43,0x94,0xa1,0x9,
+ 0x72,0x4c,0x9e,0x11,0x90,0x80,0x47,0x7c,0x58,0x63,0x8f,0x81,0x64,0x8a,0xe5,0xa2,
+ 0xd2,0xa3,0xb1,0x4,0xd2,0x87,0xfe,0x40,0x47,0x90,0xf0,0x81,0xc,0x4c,0x50,0x0,
+ 0x11,0x84,0x80,0x50,0x10,0x7c,0x35,0x6,0x47,0x8e,0xe1,0xb,0x70,0x20,0x43,0xb,
+ 0x7e,0x61,0x1e,0x4b,0x66,0x6d,0x6a,0xeb,0x70,0x9f,0x6d,0xb6,0xc9,0x4d,0x50,0x46,
+ 0xc5,0x37,0xee,0x11,0x88,0x31,0xec,0x40,0x17,0x43,0x38,0xe1,0x4,0x53,0xe0,0x80,
+ 0x2b,0x61,0x29,0x4b,0x5a,0x8e,0x0,0x97,0xb8,0xd4,0xa5,0x5,0x22,0xea,0x4b,0x30,
+ 0xde,0xc9,0x8c,0x68,0x54,0x63,0x77,0xac,0x20,0x8,0x33,0xd4,0xc0,0xa,0x84,0xd8,
+ 0x83,0xb,0xe0,0x40,0x2,0x24,0x0,0xe3,0x28,0xea,0x10,0x22,0x59,0x48,0x18,0x20,
+ 0x45,0xf9,0xa7,0x6a,0x80,0xcc,0x5a,0x26,0xe5,0x83,0xf,0x65,0x60,0xa2,0x5,0x34,
+ 0xa8,0x1,0x1d,0xe4,0xb0,0x1,0x3a,0xa8,0x13,0x32,0x61,0x18,0x83,0xa,0xc4,0x50,
+ 0x87,0x4,0xe0,0xe2,0xfe,0x28,0xee,0xeb,0x8d,0x6a,0x38,0xb9,0xb6,0x2a,0xa5,0x26,
+ 0x3e,0xcc,0xc0,0xc4,0x4,0x42,0x0,0x84,0x17,0x80,0xa0,0xa,0xad,0x2c,0x42,0x11,
+ 0x6e,0xd0,0x81,0x11,0x9c,0xc0,0xa1,0xf,0x7d,0x13,0x2f,0x25,0x3a,0xd1,0x2e,0xdc,
+ 0xe9,0xb,0x59,0x18,0xd6,0x3a,0x6d,0x12,0x86,0x20,0x10,0xa1,0xc,0x82,0x10,0x82,
+ 0x8,0xe0,0x80,0x88,0x16,0xfc,0x61,0x18,0xf8,0xf8,0x86,0xca,0x4,0xe2,0xe,0x95,
+ 0xf2,0xe3,0x62,0x2c,0x2d,0x8d,0xe4,0xf2,0x21,0x58,0xd1,0x50,0xe5,0xae,0xdf,0xc0,
+ 0x84,0x1,0x2,0x81,0x8,0x11,0x8,0xe1,0x68,0x3c,0xb5,0x2,0x88,0x7c,0x1a,0x85,
+ 0x2e,0xd4,0x40,0x9,0x43,0x7d,0x85,0x79,0xf8,0x73,0xbf,0x7f,0xa,0x51,0xb0,0x91,
+ 0xb3,0x1a,0x6e,0xf6,0xc1,0x1b,0xf7,0x74,0xe3,0x3c,0xa5,0xc0,0x80,0x14,0xa0,0x0,
+ 0x4,0x8,0xd8,0x40,0x7,0x37,0x78,0xed,0xa,0x3a,0xe0,0xd5,0xaf,0x7a,0x20,0xac,
+ 0xbd,0x1c,0xeb,0xdf,0x42,0xd4,0x5,0x2b,0x64,0xa1,0x81,0x69,0x65,0xc3,0x7,0xc2,
+ 0x40,0x8,0x11,0xec,0x60,0xe,0x28,0xc8,0x84,0x32,0x8e,0x82,0xf,0xb8,0x61,0x52,
+ 0x75,0x9e,0xec,0x6b,0xf7,0x78,0x64,0x4d,0xd1,0xf0,0x3,0x1b,0xef,0x9a,0x86,0x3c,
+ 0x18,0xd1,0x83,0x39,0xec,0x20,0xb,0x82,0xb0,0x2,0x11,0x8,0x41,0x84,0xca,0x44,
+ 0xd6,0xa7,0x44,0x0,0x4f,0xa,0x1a,0x91,0x80,0x52,0x68,0x4a,0xb3,0x60,0xa9,0x1c,
+ 0xa3,0x9a,0x92,0x9a,0x75,0xc0,0x87,0x3d,0xd3,0xc0,0x7,0x2e,0x30,0x20,0x2,0xd5,
+ 0x1e,0xcb,0x6,0xfe,0x33,0x70,0xc1,0x6b,0x37,0xb0,0x82,0xd9,0x96,0x4,0xa2,0x62,
+ 0x9d,0x68,0x6e,0x43,0xd4,0xc0,0xcb,0x58,0x81,0x45,0x36,0x30,0x4,0xf,0x36,0x80,
+ 0x88,0x3a,0xe0,0xe0,0x11,0xc9,0xb8,0x2f,0x7f,0xfc,0x1,0xd,0x7e,0x80,0x70,0x2c,
+ 0xb7,0xb1,0xd8,0x6f,0xf6,0x68,0x8f,0xec,0xa9,0x87,0x2a,0xfa,0xc0,0xee,0x23,0x7a,
+ 0xa0,0x4,0x3d,0xc0,0x21,0xbc,0x74,0x50,0x41,0x19,0x98,0x90,0x97,0x31,0x42,0xc6,
+ 0xb,0x43,0x38,0x2f,0x1c,0x52,0x90,0x8,0x1a,0x94,0xc2,0x19,0x38,0xda,0xec,0xe3,
+ 0x76,0xf4,0x9b,0xdc,0xc0,0x87,0xbe,0xa2,0xed,0xd1,0x7d,0x85,0xf1,0x87,0x9,0x24,
+ 0x61,0x5,0x5a,0x34,0xc1,0xa,0x6e,0xa0,0x2,0x15,0xc,0x98,0xc0,0x6,0xbe,0x2d,
+ 0x82,0x15,0xa8,0xdb,0x93,0xe4,0xe4,0x9,0x70,0x18,0xc3,0x19,0x1e,0x7c,0x5,0x45,
+ 0x24,0xa2,0x2,0x97,0x70,0x6,0x52,0xac,0x81,0xba,0xbd,0x6e,0x43,0xc4,0xfe,0xf1,
+ 0xeb,0xb4,0x44,0x5c,0x42,0x7e,0x94,0x26,0x2e,0x99,0x40,0xc1,0x1c,0xd6,0xa0,0x2,
+ 0x42,0x84,0x81,0x8,0x74,0xb0,0x42,0x11,0xc0,0xb3,0xa7,0x93,0x38,0x52,0x32,0x8b,
+ 0x70,0x1,0x13,0x26,0x21,0x2,0x2e,0x50,0xe0,0x13,0x68,0xfe,0xc6,0x3b,0xa8,0xbb,
+ 0x52,0xa9,0x10,0x48,0xb4,0x6a,0xe9,0x86,0xfb,0x66,0xa,0xa,0x2,0x88,0x60,0x5,
+ 0x2b,0x80,0xb2,0x94,0xa9,0x4c,0xe0,0x12,0x5c,0x79,0xac,0x64,0xd5,0x72,0x88,0xbc,
+ 0x10,0x6,0x2b,0x98,0x61,0xd,0xc3,0xea,0x13,0x10,0xf6,0xc0,0x5,0x3,0x84,0x22,
+ 0x1a,0x5e,0xfe,0x41,0xd7,0x58,0x10,0xe4,0xe6,0x37,0xff,0x48,0xc4,0xa2,0x62,0x8a,
+ 0x72,0x43,0x81,0xe7,0x1d,0x78,0x74,0x3,0x41,0x60,0xab,0xd2,0x66,0x4c,0x63,0x9b,
+ 0xb8,0xe1,0x8,0x7b,0x8,0x83,0xb,0xe4,0xc0,0x4,0x38,0x24,0x40,0x13,0x76,0xc5,
+ 0x47,0x38,0xe,0x94,0xa8,0x21,0xe7,0xc6,0x37,0xeb,0x68,0xaa,0xa3,0xba,0x11,0x17,
+ 0x6a,0x98,0xa2,0x5,0x36,0xe3,0x9d,0xa,0x6e,0x50,0xe5,0x5b,0x76,0xa8,0xc0,0x60,
+ 0xcd,0x40,0x44,0xb1,0x2c,0x46,0x5f,0x2d,0xb0,0x57,0x47,0x70,0x3,0x8a,0x5c,0x3d,
+ 0x8,0x37,0xdc,0xc1,0x6,0x80,0x90,0xc1,0x27,0xe4,0x21,0xf0,0x38,0x53,0x6f,0xc4,
+ 0xd9,0x3,0x61,0x69,0x22,0xfd,0x2c,0x94,0x92,0x85,0x1d,0x64,0x1,0xcb,0x96,0xc4,
+ 0x61,0xa,0x14,0x34,0x42,0xf,0x8d,0x75,0xa4,0x23,0xcd,0x9a,0x17,0xbb,0xcd,0x3b,
+ 0xa,0x18,0x95,0x8c,0x1a,0xbf,0x30,0x87,0xa,0xd8,0x8,0x29,0x63,0xd9,0x86,0x90,
+ 0x39,0xab,0x2e,0xb2,0x64,0x2f,0x85,0x47,0xb1,0xc5,0x5,0x68,0x20,0x2,0x29,0x7c,
+ 0x60,0x5,0x19,0xe0,0x0,0x6d,0xdf,0xbd,0x4b,0x78,0x1f,0x78,0xde,0xf5,0x26,0x98,
+ 0xaa,0x85,0x60,0x6,0x33,0x6c,0x21,0xb,0x4c,0x90,0x82,0x22,0x8a,0xb0,0x9,0x71,
+ 0x8,0xdc,0x62,0x83,0xf4,0xc7,0x36,0xb2,0x37,0x67,0xf7,0xbc,0xb7,0x29,0x91,0x1b,
+ 0x8b,0xc3,0xc5,0x82,0x8e,0xb7,0xe0,0x83,0xdc,0x60,0xa8,0x83,0xab,0x1b,0x5c,0x4c,
+ 0x47,0xf2,0x76,0xe3,0x5f,0xc,0x51,0x14,0x3c,0x6e,0x93,0x62,0x16,0x33,0x8,0x35,
+ 0xa8,0xfe,0x43,0x1d,0x2a,0x90,0x5c,0x6f,0x88,0x65,0x1b,0xbd,0xa1,0x5f,0xaf,0x47,
+ 0x1c,0x33,0x7a,0xdc,0x15,0x18,0x48,0xa0,0xc1,0x3,0xce,0x40,0x6a,0x87,0xea,0x6a,
+ 0xe7,0x3b,0x8f,0xb7,0x2f,0x7f,0x4e,0xb0,0x66,0x7f,0x7,0xe,0x4f,0xc8,0x8b,0x1f,
+ 0x26,0x90,0x8a,0x89,0x21,0xa5,0x49,0xf5,0xb8,0xc7,0xd4,0x4,0x82,0x49,0x6e,0x70,
+ 0xe3,0x49,0x97,0x5f,0xcf,0xd5,0xc7,0x52,0xcd,0xb7,0x54,0xe5,0x1b,0xac,0xd0,0x40,
+ 0xf,0x12,0x91,0x19,0x39,0xb8,0x0,0xb,0x18,0x2f,0x7b,0x16,0xc0,0x8,0xa2,0x8e,
+ 0xab,0xdd,0xb,0xc5,0xf4,0x2,0x11,0xd6,0x90,0x82,0x3a,0x5c,0x0,0x19,0xfc,0x89,
+ 0x74,0x54,0x16,0xee,0xb2,0x52,0xb9,0x83,0x1f,0x1d,0xbb,0x47,0x55,0x92,0x81,0x4,
+ 0x19,0x7c,0x20,0xe,0x10,0xc8,0xb9,0xe1,0xf,0xdf,0xf3,0xb3,0x2b,0x5e,0x44,0x6b,
+ 0xa5,0x43,0x19,0x74,0xe6,0x7,0x44,0x50,0xc0,0x69,0x48,0xe9,0x46,0xcc,0xda,0xe1,
+ 0xbd,0x77,0x74,0xa3,0x1b,0x51,0xeb,0x94,0xe7,0x2f,0x56,0x9a,0xc1,0x1e,0xdc,0xc3,
+ 0xfa,0x78,0x6,0x3e,0x64,0xd1,0x82,0x1d,0x1c,0x62,0xd,0x35,0x58,0xe4,0x10,0x54,
+ 0x1d,0x86,0x2f,0xc0,0xbe,0xb,0xc7,0x9e,0xfd,0x6e,0x9d,0x9d,0xda,0x61,0x81,0x17,
+ 0x6c,0xc0,0x20,0x64,0x81,0x11,0xbc,0xc1,0x5,0x94,0x7,0x7a,0xc,0xc8,0x7a,0x8c,
+ 0x4a,0xcb,0x9c,0xc5,0xe5,0x65,0xc3,0xbb,0x8,0x83,0xf,0xdc,0x80,0x3,0x34,0x54,
+ 0x2e,0xe9,0x5c,0xf4,0xf1,0x9c,0x5,0x3c,0xc8,0x44,0x55,0x1f,0x88,0x1c,0x9b,0x1b,
+ 0xfe,0x74,0x1,0x11,0xf0,0x81,0x18,0xbc,0xc1,0x1f,0xc8,0xc3,0x7d,0x5,0x49,0xf6,
+ 0x68,0x83,0x49,0x1d,0x5,0x6d,0x58,0x4c,0xc7,0x78,0x9e,0x54,0x70,0xd3,0xd4,0xad,
+ 0x83,0x6d,0x14,0x84,0x2c,0x80,0xc1,0xe,0x50,0x42,0xd,0x34,0x16,0x13,0xdc,0x9b,
+ 0x17,0xd4,0xd0,0x17,0xf1,0x16,0xb1,0x78,0x41,0x3a,0xed,0x56,0x5e,0xf4,0xd6,0x17,
+ 0x5,0x41,0x17,0xa8,0xd1,0x6,0xc8,0x1,0x7e,0x2c,0xc1,0x2,0x1e,0xc5,0x6c,0xe8,
+ 0x43,0xfe,0xe0,0x5d,0x53,0x7c,0x50,0x9,0xd1,0x83,0x67,0xfc,0x2,0x1,0x48,0xc1,
+ 0xe0,0x91,0x5a,0x6d,0x75,0xa0,0xe1,0xc5,0xdb,0x83,0x30,0x41,0xe2,0x55,0xdf,0x17,
+ 0x35,0x4c,0xe,0x78,0x81,0x1c,0xe4,0xc7,0x2f,0x9c,0x87,0xf9,0xb5,0x19,0x3a,0x1c,
+ 0x5,0x35,0xc,0x43,0x2e,0xf4,0x82,0xe9,0xbc,0x8b,0x36,0x30,0xd7,0x3a,0xec,0x51,
+ 0x9,0x45,0x49,0x61,0xc9,0x3,0x2e,0x54,0xc0,0x12,0x98,0xc1,0x8b,0xc9,0x81,0x1c,
+ 0x4,0x81,0x22,0xa8,0xdd,0x11,0x36,0x50,0xc8,0x41,0x52,0x13,0xe6,0x85,0x15,0x3c,
+ 0x61,0x10,0xb0,0x1,0xf,0x7c,0x80,0x1c,0xb8,0x52,0x20,0x20,0x41,0x51,0xe5,0x91,
+ 0x69,0x4c,0x9a,0xba,0x70,0x4f,0xa3,0xe4,0xda,0x69,0x94,0x96,0x5c,0x3c,0x80,0xe,
+ 0x74,0x8,0x7,0xa2,0x61,0x4,0xa8,0xe1,0x1a,0x86,0x91,0x8,0x6,0xa0,0x17,0xb4,
+ 0x8a,0x1a,0x28,0xb,0xd3,0xe9,0x83,0xd4,0xb8,0x3,0x38,0xd8,0xc3,0x37,0x98,0xc2,
+ 0x5,0x60,0x80,0xc,0x4c,0x0,0xd,0x80,0x82,0x32,0x94,0x6,0xfc,0xd8,0x3,0xfe,
+ 0xae,0xa5,0x4b,0xf,0xc1,0xc3,0xc5,0x7c,0xc3,0x1e,0x4a,0x40,0x1d,0x4,0x2,0x11,
+ 0x84,0x81,0x1b,0xb8,0x41,0xe,0x4,0x1,0xce,0x84,0x51,0x3,0x45,0xa1,0x4d,0x40,
+ 0x61,0x5e,0x88,0x81,0x30,0x35,0xe1,0x17,0x81,0xd,0x1b,0x5c,0x81,0x27,0xbe,0x90,
+ 0x6,0x30,0x82,0x5d,0x65,0xd8,0x86,0xb5,0x8e,0xf1,0xd5,0x83,0xf7,0xd8,0x3,0x3b,
+ 0x38,0xdc,0x36,0xb8,0x85,0x37,0xa8,0x3,0x31,0x10,0xc0,0xd,0x7c,0x80,0x2e,0xa1,
+ 0x61,0x6,0x44,0xc0,0x2c,0x46,0xd4,0x1a,0xb2,0xa1,0x2d,0x56,0x9f,0x3,0xb9,0x41,
+ 0x13,0xec,0x1,0x11,0x28,0x1,0x2b,0x98,0x47,0x73,0x55,0x53,0x35,0xd8,0xc1,0x1b,
+ 0x88,0xc1,0xd,0x48,0x1,0x20,0xb0,0x0,0x6,0x80,0xc1,0x30,0x0,0x87,0x58,0x38,
+ 0x5c,0x4a,0x4d,0xdd,0x79,0x0,0x43,0x5,0xf4,0x0,0x19,0x64,0x81,0x1b,0x44,0x41,
+ 0x18,0xe4,0x80,0x23,0x4d,0xe1,0x44,0x65,0xa2,0x1a,0x41,0x61,0x17,0x70,0xc1,0x25,
+ 0xe6,0xc5,0x83,0x34,0x41,0x1c,0x44,0x51,0xe,0x1c,0x81,0xd,0x21,0xc2,0x1b,0x80,
+ 0x1,0x32,0xe0,0xc3,0x34,0x2c,0x85,0x5a,0x48,0x8e,0xa3,0x98,0x45,0xc7,0xdc,0x63,
+ 0x3e,0x3a,0x5c,0xb5,0xbc,0x8b,0x32,0x10,0x0,0xb,0x74,0x40,0x2c,0xee,0x9c,0x41,
+ 0x66,0x65,0xbc,0x9d,0x9,0x57,0x1e,0x81,0xa9,0x1,0x4e,0x16,0xe0,0x54,0x19,0x94,
+ 0x81,0x1e,0xa0,0x40,0x32,0xbc,0xc3,0x3e,0x44,0x89,0x3d,0x9c,0xc3,0x37,0x6c,0x2,
+ 0xd,0x88,0x81,0x14,0xa4,0x56,0xb7,0x88,0xc1,0x12,0xd8,0x41,0xb3,0x84,0xfe,0x3,
+ 0x49,0xa6,0xce,0x6e,0x9c,0x6,0x55,0x78,0x6,0x30,0xb4,0x1,0x9,0x20,0x42,0x8b,
+ 0x85,0xc8,0xb1,0xb5,0xa1,0x3a,0x5,0x81,0x1a,0x35,0xc1,0x17,0x25,0x64,0x42,0x1e,
+ 0x1,0xf,0x5c,0x1,0xf,0x34,0x41,0x13,0x98,0x9,0x11,0xdc,0x50,0x25,0xc0,0x9f,
+ 0x7c,0xf4,0xd3,0x40,0x6c,0x12,0x60,0xa9,0x4e,0xfd,0x74,0xcf,0x3e,0xe0,0x63,0x3e,
+ 0xfa,0x3,0x37,0x78,0x8c,0x3c,0x20,0xc3,0x3,0x38,0xc0,0x40,0xc6,0x1b,0x6b,0xc6,
+ 0x1b,0x4,0xbc,0x66,0x57,0x9e,0x89,0xa9,0x99,0x1a,0x26,0xb2,0xda,0x21,0x30,0x2,
+ 0x35,0xf8,0x22,0x3c,0x68,0xcf,0x2e,0x18,0x1,0x17,0x48,0x41,0x13,0x40,0x1,0x4d,
+ 0x78,0x41,0x78,0xa0,0x0,0x1e,0x4d,0x8b,0xc3,0x15,0x88,0x54,0xd8,0xc6,0x7d,0xfd,
+ 0x65,0x1d,0x20,0x82,0xa,0xb8,0xc1,0x5a,0xcd,0xe6,0x44,0x25,0xa6,0x64,0x4a,0x66,
+ 0x6c,0xc6,0xe6,0x75,0x1e,0x41,0x13,0x78,0x4b,0x25,0x18,0x65,0x69,0x7c,0x1b,0x6f,
+ 0x58,0xcf,0x1f,0x35,0x45,0xa,0xad,0xc,0x3e,0xda,0x83,0xd6,0x74,0x8f,0x3c,0xfc,
+ 0xc2,0x3,0x58,0x40,0x17,0x81,0x40,0x6b,0xce,0xe7,0x6b,0x42,0x40,0x76,0x7a,0x25,
+ 0x75,0xfa,0x52,0x16,0xc0,0x81,0x10,0x58,0x41,0x19,0xa4,0x1,0x26,0x20,0x45,0x3a,
+ 0xc0,0x43,0x3a,0xd8,0x3,0x3e,0xf4,0x4f,0xec,0x15,0x4b,0x15,0x54,0x1,0x16,0x74,
+ 0xc1,0x16,0xa0,0x80,0x26,0x14,0x51,0xae,0x15,0x48,0x69,0x9c,0xc3,0x79,0xc,0x43,
+ 0x1e,0xe0,0x99,0x18,0xd0,0x81,0xb,0xb8,0x81,0x4d,0xe6,0xe7,0x17,0xfe,0x59,0xe7,
+ 0x76,0x66,0xe7,0x10,0x9c,0x9,0x13,0x60,0x67,0x13,0xdc,0x80,0x8,0xf0,0x98,0x51,
+ 0x46,0x9a,0x68,0xf9,0x53,0xb4,0x88,0x8a,0x3f,0xa0,0x62,0x68,0x3a,0x4a,0x5f,0x1d,
+ 0x85,0x3c,0x80,0x1,0x17,0x58,0xe5,0x19,0xca,0xe7,0x7c,0xb2,0x66,0x7d,0xde,0x27,
+ 0x88,0x86,0xd1,0x79,0x8d,0x97,0x15,0xac,0x41,0x80,0x76,0xc3,0xe3,0xa4,0x43,0x38,
+ 0xe0,0x3,0x26,0x28,0xc1,0x9e,0x60,0xc1,0x15,0x2c,0xe8,0x15,0x44,0x81,0x50,0xe5,
+ 0x81,0x38,0xbc,0x85,0xc1,0xb9,0x4b,0x5c,0xa8,0x43,0x32,0xe4,0x1,0xe,0x2c,0x41,
+ 0x20,0x14,0x1,0x13,0x1c,0x9a,0x17,0xc,0x69,0x88,0x5e,0xa7,0x9a,0xde,0xe7,0x11,
+ 0xc4,0xe5,0x1a,0x72,0xa7,0x9,0x9c,0xc1,0xd,0x88,0x81,0xf,0x4c,0xe4,0x51,0xf6,
+ 0xc6,0x7b,0x8d,0x56,0x54,0xd4,0x63,0x2a,0x16,0x1f,0x3f,0xe4,0x11,0x3e,0xa8,0xc2,
+ 0x4,0x88,0xc0,0x7,0xa4,0xe1,0x8f,0x2,0x29,0x3,0x30,0xc0,0x7d,0x32,0x66,0x2d,
+ 0x8e,0x15,0x11,0x7c,0x22,0x88,0x88,0x1,0x23,0xc8,0x83,0x37,0xa0,0x5c,0x3a,0x6c,
+ 0x9d,0x26,0xf4,0xc0,0x16,0x84,0x41,0x31,0x1d,0x4f,0x15,0x10,0x67,0x1d,0x60,0xe9,
+ 0xe,0xfd,0xd3,0x58,0x8c,0x9b,0x38,0x64,0x68,0x1d,0x74,0x57,0x17,0xe4,0xc0,0x19,
+ 0xe8,0xc0,0x99,0xa2,0xa9,0x9a,0x62,0x27,0x9b,0x4a,0x41,0x15,0xad,0xa1,0x64,0x5e,
+ 0x81,0x7f,0x89,0x80,0x2,0xca,0x93,0x35,0x50,0xcf,0xb7,0xad,0x5,0x6e,0xf0,0x29,
+ 0x34,0xc2,0x20,0x3e,0xe8,0xc2,0x3,0xf0,0xc1,0x3,0x68,0x95,0xfe,0xf4,0x1d,0x6a,
+ 0x44,0x25,0xaa,0xa2,0x66,0x27,0xa3,0x82,0xe0,0x44,0xb1,0xa1,0x1a,0x94,0xe8,0x77,
+ 0x44,0x82,0x57,0xac,0xe,0x3f,0xb8,0xf,0x2a,0x54,0xc0,0x16,0x88,0x9d,0x1c,0x7d,
+ 0x6a,0x16,0xb4,0x40,0x26,0x9c,0xc7,0x5a,0x30,0xc5,0x5a,0x56,0xc5,0xa9,0x6e,0xd7,
+ 0xe,0xc0,0x41,0x8,0x48,0xc1,0x1e,0xd0,0xb,0x9a,0xa6,0xe3,0x9a,0xce,0x2a,0xad,
+ 0x12,0x81,0xad,0xf2,0xa4,0x3,0x74,0x8b,0x8,0x90,0x1,0x12,0x24,0x83,0x11,0x8d,
+ 0x45,0x53,0x5,0x6b,0xc7,0xd4,0xa8,0x3d,0xa4,0xd0,0xbb,0xe4,0xc2,0x3,0x74,0x40,
+ 0x7,0xdc,0x40,0x8,0x74,0xc0,0xb2,0xfe,0xa8,0x3,0x38,0x80,0xb3,0x2e,0x6a,0xb4,
+ 0x8e,0x15,0x13,0xa8,0x41,0x14,0xb6,0x69,0x16,0x2c,0xc1,0x33,0x4c,0x8b,0xd4,0xe9,
+ 0x3,0x2f,0xa0,0x41,0x1d,0xc,0xcb,0x4c,0xd0,0x84,0x14,0x88,0x81,0x71,0x22,0x5,
+ 0x3d,0x9c,0x85,0x75,0x79,0x83,0x37,0xc8,0x43,0x1e,0xd4,0x1,0x19,0xd4,0xc0,0x24,
+ 0xdc,0x40,0x13,0xb4,0xea,0x1e,0xb4,0xe9,0xbc,0xd6,0x2b,0x9a,0x64,0xe7,0xbd,0x12,
+ 0x1,0x4e,0x9e,0x28,0xd8,0xbc,0xc0,0x15,0xf0,0xab,0x12,0x44,0xc2,0xc7,0x5a,0x83,
+ 0x58,0xec,0x15,0x52,0xee,0x69,0xc1,0xee,0xc3,0x26,0xdd,0x55,0x2f,0x2c,0x6c,0x6,
+ 0x38,0x80,0xb,0x3c,0x6c,0xc4,0xb6,0xe6,0xc4,0x52,0x6c,0xa2,0x5a,0x6c,0xb4,0x32,
+ 0xaa,0x14,0x7c,0xc1,0xd,0x84,0xc1,0x64,0x16,0x41,0x3,0x10,0x83,0xfb,0x0,0xdf,
+ 0x96,0x74,0x42,0x1b,0xcc,0xc1,0xb7,0xda,0x84,0x14,0x70,0xfe,0x81,0xf,0xfc,0xc1,
+ 0x7d,0xbd,0xc3,0x8e,0x54,0x43,0xd7,0x65,0x82,0x4a,0x3e,0x1,0x1d,0x30,0x41,0x21,
+ 0x84,0x19,0x14,0xac,0xc0,0xc,0x48,0x1,0xc6,0x46,0x6b,0xbd,0x5a,0x4,0xd0,0x56,
+ 0x11,0x17,0xd4,0x80,0xd1,0x71,0xe7,0xb,0x1c,0x4f,0x9,0x9c,0xa9,0x8,0xe8,0x47,
+ 0x35,0xbc,0xf,0xc1,0x4d,0x9d,0x8e,0xfc,0x86,0x72,0xf5,0x2,0x6,0x3c,0x40,0x9,
+ 0x44,0x14,0x7,0xcc,0x80,0xa1,0x4a,0xec,0xc4,0x3a,0xab,0x85,0x84,0x6d,0xb4,0x8e,
+ 0x6d,0x1c,0x9e,0xc1,0xc,0x84,0x0,0x24,0x28,0x89,0x3e,0x58,0xc3,0xda,0x12,0xc4,
+ 0x23,0x14,0x9,0x19,0xf8,0x81,0x1f,0xc8,0x0,0xd,0xd8,0xc1,0x32,0x96,0xe2,0x6e,
+ 0x6e,0x9,0x35,0x64,0x42,0x2,0x4,0x42,0xd,0x10,0x1,0x62,0x3e,0xe6,0xd1,0x6,
+ 0x90,0x71,0xa8,0x2e,0x63,0xb2,0x69,0x6c,0xc6,0x65,0x12,0x8,0xad,0x83,0x9c,0xa8,
+ 0xd,0x4c,0xc4,0xb,0x48,0x11,0x11,0xd0,0x80,0x4,0xbc,0x82,0xfb,0x4,0x9,0x3a,
+ 0x9c,0x46,0xca,0x7d,0x93,0x3d,0x60,0x3,0x3d,0x9c,0xc7,0x37,0xfc,0x2,0x6,0x54,
+ 0xe5,0xce,0x81,0x0,0x8,0x94,0x6e,0x44,0x75,0xad,0xfc,0xa2,0xee,0x72,0x38,0x6f,
+ 0xb4,0xde,0x40,0xe,0x4,0xe7,0xc,0x14,0xc1,0x1b,0xa8,0xc3,0xc7,0x7a,0x83,0xfb,
+ 0x58,0x83,0x3a,0x88,0xc3,0x2a,0xe0,0x0,0xa,0xb4,0x80,0x6,0xfc,0x81,0x29,0x3c,
+ 0x83,0x37,0x58,0x52,0xd4,0x98,0xd0,0x5d,0x7d,0xc2,0xd7,0x4d,0x40,0x22,0x15,0x13,
+ 0x4d,0x2c,0x6f,0x9b,0xda,0x6f,0x63,0x42,0x6f,0x57,0xfe,0xe,0xc1,0xbd,0xd6,0x0,
+ 0x17,0xc,0xe1,0xf5,0xf6,0x45,0xe,0xdc,0x80,0x11,0x5c,0x0,0xc,0xc4,0x23,0x7f,
+ 0xe8,0xa9,0xa2,0xd8,0x83,0x35,0xa0,0x10,0x35,0xa,0x3,0x5d,0x74,0xc0,0x7,0xd4,
+ 0x70,0x6,0xb8,0x2f,0xfc,0xca,0xef,0xfc,0x26,0x6a,0xea,0x6a,0xf0,0x1a,0x12,0x81,
+ 0x13,0xcd,0x80,0xe,0xa4,0xe8,0x4,0xc4,0x82,0x67,0x64,0xa1,0x82,0xe0,0x83,0x3c,
+ 0xec,0x21,0x2e,0x10,0x3,0x3,0x3,0x16,0xf8,0xa9,0xc6,0x33,0x94,0xc2,0x5,0x2c,
+ 0x81,0xfd,0x65,0x87,0x5,0x1f,0xad,0x64,0xba,0xa9,0xf,0xf,0x21,0x7,0x73,0xa5,
+ 0x7,0xdf,0x2b,0x17,0x10,0xc1,0x11,0x8c,0x70,0xf6,0x6a,0x44,0x15,0x22,0x1,0x33,
+ 0xa8,0x3,0x5c,0xac,0xc5,0x3e,0xbc,0xf1,0x1b,0x37,0xce,0xe5,0x36,0xc3,0x51,0xa8,
+ 0xef,0x3,0xec,0xd2,0x7,0x84,0x40,0x98,0xb8,0xef,0xfb,0xda,0x96,0x5,0xe8,0x70,
+ 0xd7,0x26,0xea,0x1,0xf4,0x70,0x17,0x13,0x1,0x9f,0xcc,0x80,0x9,0x74,0x4b,0x11,
+ 0x50,0x40,0x32,0x18,0x55,0x8f,0xf4,0x23,0x52,0x70,0x26,0xd3,0xf6,0x88,0x9a,0x1d,
+ 0xa8,0x6,0x90,0x81,0xfd,0x95,0x8f,0x17,0xf0,0x0,0x27,0x5f,0x67,0x17,0x6f,0x70,
+ 0x6c,0x2e,0x47,0xe,0xb4,0x56,0xe,0x4c,0x2f,0x11,0x24,0xc1,0x10,0xd8,0xc0,0x54,
+ 0x1,0x81,0x14,0xb5,0x12,0x17,0x18,0x1,0x5,0xfc,0x1,0x78,0xca,0x7,0x1c,0x1b,
+ 0xac,0x96,0x6c,0xc9,0x2f,0x18,0x0,0xb,0x58,0x0,0x8,0x78,0xc0,0x6,0xe8,0xf1,
+ 0x7,0x80,0xc0,0x9,0x40,0xc0,0x2e,0x1d,0x64,0xfe,0xfc,0x2,0xb2,0x3,0x1c,0x80,
+ 0x32,0x13,0xb2,0xf,0x8f,0x97,0x8d,0x99,0x80,0xab,0xf2,0x81,0xb2,0x84,0x8b,0x37,
+ 0x94,0x5,0x6d,0xd0,0xee,0xfb,0x58,0x83,0xdb,0x50,0xc5,0x39,0x60,0x98,0x2a,0x90,
+ 0xc0,0x16,0xd4,0x40,0x11,0x98,0xe0,0x43,0xc6,0x6a,0x10,0x7c,0xf2,0x9b,0x92,0x28,
+ 0x60,0x8c,0x32,0x29,0xe7,0xc,0xfe,0x42,0x51,0x14,0xb5,0xf2,0xd,0x6c,0x80,0x8a,
+ 0xd2,0x40,0x80,0xe2,0x43,0x35,0x34,0xce,0x7,0x1,0xc9,0x96,0xf4,0x2,0x55,0x96,
+ 0x0,0x4,0xbc,0x89,0x1e,0x87,0x89,0x5,0x40,0x80,0x5,0x14,0xa4,0x31,0xff,0x31,
+ 0x32,0x2b,0xf3,0x20,0xd7,0xef,0x27,0x5b,0x1,0x13,0xc,0x1,0x14,0x44,0x91,0x6b,
+ 0xc9,0x40,0xb,0x4,0xdc,0x37,0xcc,0x6e,0xf9,0x42,0x45,0xba,0x44,0x8d,0x54,0xb0,
+ 0x25,0x35,0xe4,0x82,0x1,0x88,0x40,0x19,0xa8,0xc0,0x83,0x6c,0x0,0x37,0x5e,0xe7,
+ 0x87,0xa2,0xb3,0x17,0x87,0xf2,0x72,0xf4,0x57,0x9,0x13,0xc1,0xd,0x24,0x1,0x14,
+ 0xb1,0xb2,0xe,0x94,0xf0,0xd,0x70,0x80,0x9,0x7c,0x40,0x11,0x68,0x80,0x2a,0x44,
+ 0x72,0xae,0x55,0xcf,0x34,0xf8,0x73,0x7,0xc4,0xc1,0x0,0xbc,0x40,0x9,0xe4,0x31,
+ 0x30,0x43,0x6c,0x56,0x26,0x34,0x32,0x27,0xf3,0x32,0x3b,0x74,0x17,0x57,0x46,0x44,
+ 0xc7,0xf3,0xa,0x30,0x1a,0xa,0x84,0x2,0x35,0x34,0x83,0x3d,0xd8,0x1d,0x8c,0xaa,
+ 0x7,0x3d,0x5c,0xc3,0x5d,0xb1,0x82,0xf,0x18,0x1,0x1d,0x18,0xdb,0x18,0xb8,0x80,
+ 0x4d,0x6c,0x80,0x27,0xef,0x56,0x65,0x54,0xfe,0x11,0x5c,0xc3,0x75,0xd8,0xde,0x67,
+ 0xbf,0xf4,0x85,0x6b,0x55,0xd1,0xd,0xe8,0x80,0xe,0xd8,0xf4,0x6b,0xdd,0xc0,0x82,
+ 0x46,0x40,0x8,0xf8,0x41,0x1,0xd8,0x2,0x0,0xfb,0x1a,0x3e,0xf0,0x42,0x3,0xb0,
+ 0xc0,0x9,0x4,0xc0,0x30,0x2b,0x75,0x98,0xd4,0xf0,0x7,0x34,0x35,0x6b,0x3e,0x35,
+ 0x43,0xe7,0x40,0x60,0x5c,0xb6,0x65,0xa3,0xf3,0x78,0xbd,0xa4,0x9,0xd8,0x80,0x5d,
+ 0x10,0x81,0x1f,0x28,0xc1,0x5,0xe4,0xc1,0x30,0x58,0x92,0x7c,0x6c,0x92,0x4c,0xe1,
+ 0xa8,0x33,0x7c,0x42,0xb,0xa4,0x40,0x16,0x4,0x1,0x37,0x6e,0xc0,0x19,0x34,0xc1,
+ 0x6,0xec,0x41,0x18,0xaf,0x21,0x44,0xc7,0x75,0x5c,0xcf,0x75,0x76,0xd6,0xca,0x5e,
+ 0x67,0xaf,0x6b,0xf5,0xb5,0x5e,0xf,0xf7,0x6b,0xe5,0x40,0x15,0xbc,0x0,0x16,0xdc,
+ 0xc0,0x4,0x2c,0x41,0x2,0xd8,0xc2,0x69,0xbf,0x3,0x3a,0x44,0xf7,0x3b,0xd4,0x82,
+ 0x4,0xc8,0x80,0x5,0x30,0x36,0x2,0x8c,0xc0,0x2f,0x6f,0x0,0x64,0xd7,0xb0,0x64,
+ 0xc7,0x1b,0x32,0x2f,0x0,0x43,0xdf,0x34,0x79,0x5f,0xb6,0x85,0x58,0x48,0x15,0xf1,
+ 0xcb,0x4d,0x97,0x70,0x11,0x64,0x81,0x8,0x4c,0x80,0x28,0xec,0x82,0xc0,0x29,0x97,
+ 0xc0,0x9,0x1c,0x32,0x94,0x42,0x1d,0x90,0x40,0xa,0x74,0x57,0x4b,0x7f,0xf1,0x79,
+ 0x2f,0xc7,0x7d,0x8a,0x32,0x45,0xff,0x17,0xef,0xc,0xf7,0xc,0x10,0xb8,0xb,0x74,
+ 0x44,0x94,0x89,0x80,0xc,0xf0,0xae,0x2b,0x34,0x8b,0x51,0x3d,0x83,0x2a,0x50,0x0,
+ 0xa1,0xde,0x70,0x2f,0xd7,0x56,0xa1,0xfe,0x16,0xf3,0x77,0x1f,0xb3,0xfc,0x2e,0x80,
+ 0x87,0x8b,0x37,0x2,0x20,0xc0,0x70,0xf,0xb7,0x65,0xff,0xb7,0x89,0x5f,0xc4,0x19,
+ 0xc,0x41,0x13,0xb8,0xc1,0x19,0x70,0xb7,0x8,0x44,0xc2,0x27,0xc4,0x82,0x30,0x20,
+ 0x83,0x30,0xd0,0x82,0x2b,0x34,0x42,0x20,0x18,0x41,0xa,0x38,0x2e,0x1c,0x40,0xf4,
+ 0x17,0xe7,0xcd,0x89,0x5f,0x44,0x80,0x2f,0xc7,0x15,0x1d,0xb8,0x91,0xb,0xb1,0xe,
+ 0x1c,0xb8,0xa7,0x2d,0xb9,0xa7,0xb9,0x0,0xb,0xa8,0xa8,0x8,0x3c,0x0,0x24,0xb4,
+ 0x2,0x31,0x10,0x43,0x2a,0x48,0x2,0x1,0x8,0x64,0xc0,0x9c,0x21,0x56,0x46,0x94,
+ 0x41,0x4e,0xb6,0xe,0x7f,0xf8,0x2,0x84,0xb8,0x88,0x8f,0xb8,0x5e,0x7,0xf9,0x89,
+ 0xdb,0x4,0x9a,0x34,0x81,0x4d,0x14,0x81,0x12,0x20,0xc1,0x1,0x6b,0x80,0x6,0xd0,
+ 0x40,0xa,0x50,0xc0,0x8e,0x3b,0x2e,0x5c,0xff,0x38,0x90,0xa3,0xf9,0x90,0x3,0x46,
+ 0x91,0x1f,0x39,0xa0,0x33,0xf9,0x47,0x2c,0x39,0xb,0xb0,0x80,0x8,0x44,0xf9,0x31,
+ 0x12,0x80,0x31,0x6a,0x79,0xc0,0xc0,0xef,0x7c,0x2,0xb2,0x98,0x93,0xf9,0x81,0x9b,
+ 0xb9,0x46,0xa0,0xf9,0x79,0x6f,0xc0,0x11,0x80,0x9c,0x76,0x7c,0x41,0xa,0xd0,0x80,
+ 0xa7,0x9f,0x51,0xb,0xc1,0x1,0x1f,0xa8,0x1,0x13,0xdc,0x80,0xb,0xfc,0xa4,0x9e,
+ 0xb,0x90,0xa5,0xaf,0x73,0xad,0x0,0xba,0xab,0x33,0xf9,0xba,0x95,0x4,0x64,0x3f,
+ 0x40,0xa1,0x1b,0xfa,0xa1,0x3f,0x40,0x86,0x13,0x64,0x42,0x73,0x2d,0xa4,0x7f,0xb8,
+ 0xa4,0x4f,0x3a,0x89,0x97,0xf8,0xfe,0xaa,0xff,0x45,0x13,0x58,0xb6,0xaa,0x79,0x41,
+ 0xd6,0xf2,0x81,0xb,0x61,0xd5,0x6b,0xc5,0xa5,0x46,0xe8,0x80,0x70,0xd6,0x44,0x89,
+ 0xea,0xf9,0xb0,0x8b,0x72,0xab,0xbb,0xba,0x92,0xc3,0xfa,0x80,0x8d,0x0,0xb7,0xbb,
+ 0x9b,0xe,0x30,0x6c,0xd,0xe3,0x7a,0x6c,0x11,0xa4,0x7,0x9a,0x6e,0x87,0x7f,0xb8,
+ 0x32,0x87,0xf8,0x0,0x10,0x2e,0xb0,0xeb,0xb5,0xb0,0x57,0xbb,0x45,0xb8,0xc1,0x10,
+ 0x6c,0x80,0xb,0xb0,0xb9,0x76,0x7c,0xc0,0x6,0x14,0x87,0x14,0xd8,0xd8,0xc,0x4,
+ 0xa7,0xd,0x5c,0x30,0xae,0x4e,0xfb,0x8f,0xc3,0xfb,0x5f,0xd4,0xca,0x9f,0x7,0xba,
+ 0xb6,0x6f,0x3b,0xb7,0x8f,0x0,0x9c,0x94,0x0,0x42,0x1b,0x24,0xc3,0xea,0xfa,0xae,
+ 0x83,0x79,0x98,0xa3,0xfb,0x1,0xc,0x0,0xc6,0x7b,0x9a,0x91,0x7,0x7b,0xbf,0xa8,
+ 0x89,0x85,0x9c,0x3a,0x9b,0x37,0xc1,0xee,0xe8,0xc0,0x76,0x94,0x89,0x99,0x77,0x44,
+ 0x14,0xd1,0x4,0xee,0x50,0xbb,0xa5,0xf7,0x4b,0x1,0xf1,0xe,0xb6,0xcf,0x40,0xc2,
+ 0xc7,0x7a,0xbb,0x39,0x7c,0x9,0x0,0xc1,0x2e,0xd9,0x52,0x4,0x10,0x24,0xaf,0x3f,
+ 0xb5,0x3,0x78,0x38,0x43,0x33,0x34,0xc6,0xaf,0xbb,0xc6,0x23,0xf9,0x7a,0x77,0x3c,
+ 0x86,0x58,0xc8,0x4f,0x36,0x41,0x89,0x62,0x67,0x3c,0x73,0x32,0x4d,0x34,0xc1,0xa,
+ 0xe8,0x35,0x14,0x54,0x3d,0x14,0xa0,0x3a,0xcb,0xa3,0xb9,0xcb,0xbf,0xfc,0xc1,0x1f,
+ 0xf9,0xcc,0xaf,0xc0,0x7,0x3c,0x94,0xd,0xec,0x7c,0x49,0x14,0xa4,0xd,0xf0,0x3c,
+ 0xc5,0x3f,0x35,0xd0,0x7,0xfe,0xfd,0xc5,0x63,0x7c,0xcc,0x23,0xbd,0xc7,0x5b,0xba,
+ 0x3a,0x5b,0x44,0x12,0xd4,0x7d,0xa5,0x13,0xbc,0xde,0x8,0x6,0xd7,0xef,0x7d,0x91,
+ 0x7f,0x3d,0xd8,0x77,0x37,0xe0,0x77,0x37,0x2,0x45,0x9f,0x56,0x82,0xb7,0xcf,0xaf,
+ 0x3d,0xdb,0xb7,0xfd,0x0,0xbc,0x3d,0xdc,0xb,0xc6,0xaa,0xbb,0xf4,0x8d,0x99,0x32,
+ 0x5c,0xa3,0x32,0xde,0xf,0x90,0x9a,0xf0,0x3d,0xd7,0xcb,0xfc,0xd7,0x77,0xf7,0x2f,
+ 0xf,0x74,0x98,0x84,0xc0,0x6,0x70,0x37,0x64,0x87,0x4,0x97,0x6b,0xb8,0x53,0x1f,
+ 0xbe,0x78,0x27,0xbe,0xe2,0xcf,0x7c,0xcc,0x63,0xbb,0xb,0xe0,0xbd,0x6e,0x57,0x66,
+ 0x11,0xd4,0x80,0x38,0x53,0x3e,0xde,0xbb,0x3c,0xb6,0xfb,0xfd,0xe6,0x43,0xf6,0x2f,
+ 0x8b,0x80,0xe7,0xf,0x74,0xe8,0xb,0xbe,0xe1,0x7d,0x79,0xda,0x57,0x3c,0xe2,0xb,
+ 0xfd,0xd0,0x13,0xbd,0xb6,0xb7,0x3e,0xb6,0x37,0x7e,0xbf,0xc4,0xbe,0xec,0x63,0x55,
+ 0x56,0x39,0x3f,0xf5,0x6f,0x44,0xd7,0x1b,0xb9,0xee,0x6b,0x7b,0xe0,0x77,0xbe,0xe7,
+ 0x7,0x3e,0x64,0xf,0x3f,0xf1,0x73,0x78,0x78,0x5b,0x7c,0xd0,0x27,0xbf,0xf2,0xc3,
+ 0xba,0x99,0xa7,0xff,0x88,0xcf,0x40,0xf5,0xab,0x49,0x5f,0xf7,0x75,0x15,0x61,0x95,
+ 0x4c,0xb7,0x3f,0xf5,0x5f,0x91,0xfa,0xc7,0x7c,0xc2,0x7b,0x3f,0xbe,0xeb,0x3f,0x64,
+ 0x47,0x3c,0xf8,0x17,0x3f,0x40,0x38,0x70,0xb0,0x80,0x60,0xc1,0x5,0x7,0x10,0x26,
+ 0x1c,0xb0,0x90,0xe1,0x80,0x15,0xf,0x21,0x3e,0x9c,0x31,0x91,0x62,0x45,0x8b,0x2b,
+ 0x5c,0xe4,0xd0,0xb8,0xfe,0x91,0x63,0x47,0x17,0x33,0x74,0x80,0x74,0x31,0xd2,0xc5,
+ 0xd,0x93,0x27,0x6f,0x74,0x54,0xb9,0x52,0x25,0x49,0x97,0x1f,0x75,0xc4,0x94,0xa9,
+ 0x23,0x62,0xcd,0x88,0x1f,0x70,0xe6,0xd4,0xb9,0x13,0x67,0x87,0xe,0x19,0x80,0x66,
+ 0xb0,0x30,0xd4,0x42,0x4,0xa3,0x11,0x86,0xa,0x54,0xaa,0xd4,0xa0,0xc1,0x84,0xa,
+ 0x1b,0x2e,0xb4,0x29,0xd1,0x62,0x55,0x8a,0x18,0x59,0xb6,0xc,0x69,0x63,0x86,0x8d,
+ 0x99,0x19,0xb3,0x86,0xd,0xfb,0x92,0x24,0xc8,0x99,0x31,0xa7,0xda,0xe4,0xb9,0x33,
+ 0x68,0x50,0xa2,0x16,0x20,0xc4,0x95,0x5b,0xf4,0xed,0x52,0xa6,0x4d,0xf,0x3e,0x3d,
+ 0x10,0xb5,0x61,0xc4,0x91,0x37,0x3e,0xce,0x58,0x21,0x98,0xf0,0x60,0xc3,0x82,0x57,
+ 0xe8,0xc8,0xa1,0x98,0xf1,0x62,0xc7,0x8c,0x43,0xce,0x88,0xd1,0xb5,0xeb,0xd9,0x99,
+ 0x1a,0x33,0x66,0xce,0xa1,0x99,0xf3,0x63,0xc7,0x33,0x3e,0x86,0x6,0x1d,0x13,0x64,
+ 0x69,0x9a,0x69,0x6f,0xae,0x58,0x8b,0xb3,0x2d,0x8,0x10,0x6f,0xe5,0xce,0xad,0x6b,
+ 0x77,0x60,0xd3,0x3,0x79,0x11,0xe,0xd8,0xcb,0x77,0x21,0x88,0x12,0x25,0x3e,0x6c,
+ 0x50,0x21,0x42,0xc5,0x60,0x13,0x33,0x8e,0x27,0x47,0xbe,0xfc,0xb8,0x57,0xe7,0x3a,
+ 0x9e,0x47,0x27,0x3d,0x31,0x64,0xf5,0x98,0x8e,0x31,0x8b,0xd6,0xe,0x9a,0xbb,0x8b,
+ 0x98,0xd2,0x95,0x2b,0x2f,0xb1,0x62,0x7c,0x79,0xf2,0x1f,0x80,0xa7,0x47,0xbf,0x5e,
+ 0xbd,0x87,0xe,0xee,0xe1,0x7b,0x68,0x3b,0x5f,0xe8,0x5b,0xb8,0x72,0x19,0xe4,0xd7,
+ 0xbf,0xff,0x29,0xfe,0x82,0x3,0xfe,0x75,0xe3,0x6d,0x80,0x5,0x6,0x10,0xc0,0x37,
+ 0xf,0x3e,0x60,0x21,0x4,0x15,0x42,0x58,0xc1,0x84,0x7,0x21,0x8c,0x50,0x42,0x1b,
+ 0x28,0xac,0xd0,0xc2,0xb,0xa7,0xb3,0xc8,0xb2,0xc,0xad,0xaa,0xea,0xc2,0xa,0x25,
+ 0x84,0xf0,0xb7,0x11,0x49,0x2c,0xd1,0x44,0x12,0x3d,0x48,0x51,0xc5,0x14,0xe9,0x6b,
+ 0xeb,0x28,0xa3,0xe0,0xda,0x4f,0x46,0xfe,0xfe,0x43,0xc0,0x46,0x4,0x4,0x2c,0x90,
+ 0xa1,0x0,0x74,0x7a,0xe8,0x3,0x7,0x43,0xc,0x52,0xc8,0x21,0x27,0x9a,0xaa,0x43,
+ 0xd4,0xa6,0x1a,0x32,0xc8,0x13,0x99,0x6c,0x72,0xc5,0x15,0x5b,0xcc,0xe0,0x45,0x18,
+ 0x2d,0x98,0xd1,0xca,0x84,0x6e,0xc4,0x31,0x47,0x1,0xb8,0xc,0x20,0x80,0x1b,0x36,
+ 0xf8,0xb1,0x44,0x25,0xc9,0x24,0x12,0xb1,0x9a,0x8e,0x44,0xb2,0xa6,0x32,0x23,0x6c,
+ 0xf2,0xc4,0x27,0x55,0x8c,0x92,0xbe,0x29,0xa9,0xac,0xd2,0x4a,0x1a,0x11,0xba,0x31,
+ 0xc7,0x2,0x5,0xf0,0xd2,0x4b,0x6,0x37,0xe0,0xa0,0x84,0x11,0x4e,0xf0,0x8d,0x83,
+ 0x43,0x11,0x4d,0x54,0x51,0x36,0x1f,0x2c,0xd2,0xa6,0x34,0xd5,0x84,0x48,0x48,0x45,
+ 0x11,0x75,0xd3,0x44,0x39,0x5b,0xb4,0x4f,0xd3,0xba,0xee,0xd4,0x4f,0x2f,0x1b,0xb7,
+ 0xe4,0xb2,0x4f,0x0,0x0,0x8,0x40,0x85,0xd,0x56,0xe0,0x60,0x4,0x10,0xa,0x2d,
+ 0x81,0xd2,0x57,0xf,0x65,0xd4,0x84,0x48,0x69,0x4d,0x6b,0xd2,0x57,0x2d,0x2d,0x11,
+ 0x53,0xfa,0x36,0xdd,0x54,0xa0,0x4e,0x19,0xd0,0x6b,0x37,0x1,0x45,0xed,0x92,0xd4,
+ 0x0,0x46,0x6f,0x12,0x74,0x84,0x55,0xd,0x85,0x95,0x52,0x59,0x6b,0x8d,0x36,0xa2,
+ 0x5b,0x29,0xcd,0x95,0xc4,0x5d,0xe7,0xeb,0xd5,0x3e,0xa5,0xee,0x14,0x36,0xb7,0x50,
+ 0x45,0xf5,0x33,0x0,0x41,0x5f,0x28,0xc1,0x3,0xd7,0x2c,0x70,0xd5,0xd9,0x45,0x19,
+ 0x95,0xd6,0x5d,0x6a,0x15,0x65,0x12,0x4e,0x16,0xb1,0x75,0x4b,0x5b,0xa2,0xb8,0x9d,
+ 0xd1,0xdb,0x6f,0x79,0x2b,0xb6,0x58,0x2f,0x5f,0x78,0x61,0x4,0x73,0x33,0xf0,0xe9,
+ 0x83,0x75,0x11,0x8e,0x35,0x44,0x77,0xa5,0x4d,0x38,0x51,0x79,0xe7,0xad,0xd7,0xde,
+ 0xa4,0x94,0xb2,0x80,0x36,0x7,0x3c,0xdd,0xf7,0xa9,0x7e,0xfd,0x15,0x75,0xa1,0x0,
+ 0x2,0x2,0x0,0x3b,
+
+};
+
+static const unsigned char qt_resource_name[] = {
+ // images
+ 0x0,0x6,
+ 0x7,0x3,0x7d,0xc3,
+ 0x0,0x69,
+ 0x0,0x6d,0x0,0x61,0x0,0x67,0x0,0x65,0x0,0x73,
+ // resources
+ 0x0,0x9,
+ 0xa,0x6c,0x78,0x43,
+ 0x0,0x72,
+ 0x0,0x65,0x0,0x73,0x0,0x6f,0x0,0x75,0x0,0x72,0x0,0x63,0x0,0x65,0x0,0x73,
+ // tools.gif
+ 0x0,0x9,
+ 0x6,0x36,0xbb,0x36,
+ 0x0,0x74,
+ 0x0,0x6f,0x0,0x6f,0x0,0x6c,0x0,0x73,0x0,0x2e,0x0,0x67,0x0,0x69,0x0,0x66,
+
+};
+
+static const unsigned char qt_resource_struct[] = {
+ // :
+ 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1,
+ // :/images
+ 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x2,
+ // :/images/resources
+ 0x0,0x0,0x0,0x12,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x3,
+ // :/images/resources/images
+ 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x4,
+ // :/images/resources/images/tools.gif
+ 0x0,0x0,0x0,0x2a,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,
+
+};
+
+QT_BEGIN_NAMESPACE
+
+extern Q_CORE_EXPORT bool qRegisterResourceData
+ (int, const unsigned char *, const unsigned char *, const unsigned char *);
+
+extern Q_CORE_EXPORT bool qUnregisterResourceData
+ (int, const unsigned char *, const unsigned char *, const unsigned char *);
+
+QT_END_NAMESPACE
+
+
+int QT_MANGLE_NAMESPACE(qInitResources_resources)()
+{
+ QT_PREPEND_NAMESPACE(qRegisterResourceData)
+ (0x01, qt_resource_struct, qt_resource_name, qt_resource_data);
+ return 1;
+}
+
+Q_CONSTRUCTOR_FUNCTION(QT_MANGLE_NAMESPACE(qInitResources_resources))
+
+int QT_MANGLE_NAMESPACE(qCleanupResources_resources)()
+{
+ QT_PREPEND_NAMESPACE(qUnregisterResourceData)
+ (0x01, qt_resource_struct, qt_resource_name, qt_resource_data);
+ return 1;
+}
+
+Q_DESTRUCTOR_FUNCTION(QT_MANGLE_NAMESPACE(qCleanupResources_resources))
+
diff --git a/tcutils/resources.qrc b/tcutils/resources.qrc
new file mode 100644
index 00000000..76a1f852
--- /dev/null
+++ b/tcutils/resources.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/images">
+ <file>resources/images/tools.gif</file>
+ </qresource>
+</RCC>
diff --git a/tcutils/resources/images/tools.gif b/tcutils/resources/images/tools.gif
new file mode 100644
index 00000000..c6596cc4
--- /dev/null
+++ b/tcutils/resources/images/tools.gif
Binary files differ
diff --git a/tcutils/tcutils b/tcutils/tcutils
new file mode 100755
index 00000000..73aa979a
--- /dev/null
+++ b/tcutils/tcutils
Binary files differ
diff --git a/tcutils/tcutils.pro b/tcutils/tcutils.pro
new file mode 100644
index 00000000..a24029e8
--- /dev/null
+++ b/tcutils/tcutils.pro
@@ -0,0 +1,30 @@
+#-------------------------------------------------
+#
+# Project created by QtCreator 2013-08-18T13:54:44
+#
+#-------------------------------------------------
+
+QT += core gui
+
+TARGET = tcutils
+TEMPLATE = app
+
+
+SOURCES += main.cpp\
+ mainwindow.cpp \
+ utils.cpp
+
+HEADERS += mainwindow.h \
+ utils.h
+
+FORMS += mainwindow.ui
+
+# added by LK Rashinkar
+INCLUDEPATH += ../xrdpapi
+
+LIBS += -Wl,-rpath
+LIBS += -Wl,/usr/local/lib/xrdp
+LIBS += -L../xrdpapi/.libs -lxrdpapi
+
+RESOURCES += \
+ resources.qrc
diff --git a/tcutils/tcutils.pro.user b/tcutils/tcutils.pro.user
new file mode 100644
index 00000000..50311334
--- /dev/null
+++ b/tcutils/tcutils.pro.user
@@ -0,0 +1,365 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE QtCreatorProject>
+<!-- Written by Qt Creator 2.4.1, 2013-08-25T13:35:29. -->
+<qtcreator>
+ <data>
+ <variable>ProjectExplorer.Project.ActiveTarget</variable>
+ <value type="int">0</value>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.EditorSettings</variable>
+ <valuemap type="QVariantMap">
+ <value type="bool" key="EditorConfiguration.AutoIndent">true</value>
+ <value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
+ <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
+ <value type="QString" key="language">Cpp</value>
+ <valuemap type="QVariantMap" key="value">
+ <value type="QString" key="CurrentPreferences">CppGlobal</value>
+ </valuemap>
+ </valuemap>
+ <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
+ <value type="QString" key="language">QmlJS</value>
+ <valuemap type="QVariantMap" key="value">
+ <value type="QString" key="CurrentPreferences">QmlJSGlobal</value>
+ </valuemap>
+ </valuemap>
+ <value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
+ <value type="QByteArray" key="EditorConfiguration.Codec">System</value>
+ <value type="bool" key="EditorConfiguration.ConstrainTooltips">true</value>
+ <value type="int" key="EditorConfiguration.IndentSize">4</value>
+ <value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
+ <value type="int" key="EditorConfiguration.PaddingMode">1</value>
+ <value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
+ <value type="int" key="EditorConfiguration.SmartBackspaceBehavior">2</value>
+ <value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
+ <value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
+ <value type="int" key="EditorConfiguration.TabSize">8</value>
+ <value type="bool" key="EditorConfiguration.UseGlobal">true</value>
+ <value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
+ <value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
+ <value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
+ <value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
+ <value type="bool" key="EditorConfiguration.inEntireDocument">true</value>
+ </valuemap>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.PluginSettings</variable>
+ <valuemap type="QVariantMap"/>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.Target.0</variable>
+ <valuemap type="QVariantMap">
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Target.DesktopTarget</value>
+ <value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
+ <value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
+ <value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
+ <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
+ <value type="QString" key="ProjectExplorer.BuildCOnfiguration.ToolChain">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-32bit./usr/bin/gdb</value>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
+ <value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+ <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+ <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
+ <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
+ <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Qt 4.8.1 in PATH (System) Release</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
+ <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
+ <value type="QString" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory">/home/lk/projects/jtech/nlabs_xrdp_tcutils/tcutils-build-desktop-Qt_4_8_1_in_PATH__System__Release</value>
+ <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId">1</value>
+ <value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
+ <value type="QString" key="ProjectExplorer.BuildCOnfiguration.ToolChain">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-32bit./usr/bin/gdb</value>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
+ <value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+ <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+ <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
+ <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
+ <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Qt 4.8.1 in PATH (System) Debug</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
+ <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
+ <value type="QString" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory">/home/lk/projects/jtech/nlabs_xrdp_tcutils/tcutils-build-desktop-Qt_4_8_1_in_PATH__System__Debug</value>
+ <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId">1</value>
+ <value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
+ <value type="QString" key="ProjectExplorer.BuildCOnfiguration.ToolChain">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-32bit./usr/bin/gdb</value>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
+ <value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+ <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+ <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
+ <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
+ <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Qt 4.8.1 (System) Release</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
+ <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
+ <value type="QString" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory">/home/lk/projects/jtech/nlabs_xrdp_tcutils/tcutils-build-desktop-Qt_4_8_1__System__Release</value>
+ <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId">2</value>
+ <value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.3">
+ <value type="QString" key="ProjectExplorer.BuildCOnfiguration.ToolChain">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-32bit./usr/bin/gdb</value>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
+ <value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+ <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+ <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
+ <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
+ <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Qt 4.8.1 (System) Debug</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
+ <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
+ <value type="QString" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory">/home/lk/projects/jtech/nlabs_xrdp_tcutils/tcutils-build-desktop-Qt_4_8_1__System__Debug</value>
+ <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId">2</value>
+ <value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">4</value>
+ <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+ <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">No deployment</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
+ <valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
+ <value type="bool" key="Analyzer.Project.UseGlobal">true</value>
+ <value type="bool" key="Analyzer.Project.UseGlobal">true</value>
+ <valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
+ <valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
+ <value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
+ <value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
+ <value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
+ <value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
+ <value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
+ <value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
+ <value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
+ <value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
+ <valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
+ <valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
+ <value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
+ <value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
+ <value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
+ <value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
+ <valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
+ <value type="int">0</value>
+ <value type="int">1</value>
+ <value type="int">2</value>
+ <value type="int">3</value>
+ <value type="int">4</value>
+ <value type="int">5</value>
+ <value type="int">6</value>
+ <value type="int">7</value>
+ <value type="int">8</value>
+ <value type="int">9</value>
+ <value type="int">10</value>
+ <value type="int">11</value>
+ <value type="int">12</value>
+ <value type="int">13</value>
+ <value type="int">14</value>
+ </valuelist>
+ <valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
+ <value type="int">0</value>
+ <value type="int">1</value>
+ <value type="int">2</value>
+ <value type="int">3</value>
+ <value type="int">4</value>
+ <value type="int">5</value>
+ <value type="int">6</value>
+ <value type="int">7</value>
+ <value type="int">8</value>
+ <value type="int">9</value>
+ <value type="int">10</value>
+ <value type="int">11</value>
+ <value type="int">12</value>
+ <value type="int">13</value>
+ <value type="int">14</value>
+ </valuelist>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">tcutils</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration</value>
+ <value type="int" key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase">2</value>
+ <value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"></value>
+ <value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">tcutils.pro</value>
+ <value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix">false</value>
+ <value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal">false</value>
+ <valuelist type="QVariantList" key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges"/>
+ <value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory"></value>
+ <value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
+ <value type="bool" key="RunConfiguration.UseCppDebugger">true</value>
+ <value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
+ <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">false</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
+ </valuemap>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.TargetCount</variable>
+ <value type="int">1</value>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.Updater.EnvironmentId</variable>
+ <value type="QString">{9a0d9632-2baf-44e0-864a-a12692180779}</value>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.Updater.FileVersion</variable>
+ <value type="int">10</value>
+ </data>
+</qtcreator>
diff --git a/tcutils/ui_mainwindow.h b/tcutils/ui_mainwindow.h
new file mode 100644
index 00000000..4c47aefa
--- /dev/null
+++ b/tcutils/ui_mainwindow.h
@@ -0,0 +1,105 @@
+/********************************************************************************
+** Form generated from reading UI file 'mainwindow.ui'
+**
+** Created: Sun Aug 25 15:11:42 2013
+** by: Qt User Interface Compiler version 4.8.1
+**
+** WARNING! All changes made in this file will be lost when recompiling UI file!
+********************************************************************************/
+
+#ifndef UI_MAINWINDOW_H
+#define UI_MAINWINDOW_H
+
+#include <QtCore/QVariant>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QHeaderView>
+#include <QtGui/QListWidget>
+#include <QtGui/QMainWindow>
+#include <QtGui/QMenuBar>
+#include <QtGui/QPushButton>
+#include <QtGui/QStatusBar>
+#include <QtGui/QTabWidget>
+#include <QtGui/QToolBar>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class Ui_MainWindow
+{
+public:
+ QWidget *centralWidget;
+ QTabWidget *tabWidget;
+ QWidget *tabUnmount;
+ QListWidget *listWidget;
+ QPushButton *btnUnmount;
+ QPushButton *btnRefresh;
+ QWidget *tab_2;
+ QMenuBar *menuBar;
+ QToolBar *mainToolBar;
+ QStatusBar *statusBar;
+
+ void setupUi(QMainWindow *MainWindow)
+ {
+ if (MainWindow->objectName().isEmpty())
+ MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
+ MainWindow->resize(541, 355);
+ centralWidget = new QWidget(MainWindow);
+ centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
+ tabWidget = new QTabWidget(centralWidget);
+ tabWidget->setObjectName(QString::fromUtf8("tabWidget"));
+ tabWidget->setGeometry(QRect(0, 0, 511, 291));
+ tabUnmount = new QWidget();
+ tabUnmount->setObjectName(QString::fromUtf8("tabUnmount"));
+ listWidget = new QListWidget(tabUnmount);
+ listWidget->setObjectName(QString::fromUtf8("listWidget"));
+ listWidget->setGeometry(QRect(10, 10, 321, 221));
+ btnUnmount = new QPushButton(tabUnmount);
+ btnUnmount->setObjectName(QString::fromUtf8("btnUnmount"));
+ btnUnmount->setGeometry(QRect(350, 60, 141, 27));
+ btnRefresh = new QPushButton(tabUnmount);
+ btnRefresh->setObjectName(QString::fromUtf8("btnRefresh"));
+ btnRefresh->setGeometry(QRect(350, 10, 141, 27));
+ tabWidget->addTab(tabUnmount, QString());
+ tab_2 = new QWidget();
+ tab_2->setObjectName(QString::fromUtf8("tab_2"));
+ tabWidget->addTab(tab_2, QString());
+ MainWindow->setCentralWidget(centralWidget);
+ menuBar = new QMenuBar(MainWindow);
+ menuBar->setObjectName(QString::fromUtf8("menuBar"));
+ menuBar->setGeometry(QRect(0, 0, 541, 25));
+ MainWindow->setMenuBar(menuBar);
+ mainToolBar = new QToolBar(MainWindow);
+ mainToolBar->setObjectName(QString::fromUtf8("mainToolBar"));
+ MainWindow->addToolBar(Qt::TopToolBarArea, mainToolBar);
+ statusBar = new QStatusBar(MainWindow);
+ statusBar->setObjectName(QString::fromUtf8("statusBar"));
+ MainWindow->setStatusBar(statusBar);
+
+ retranslateUi(MainWindow);
+
+ tabWidget->setCurrentIndex(0);
+
+
+ QMetaObject::connectSlotsByName(MainWindow);
+ } // setupUi
+
+ void retranslateUi(QMainWindow *MainWindow)
+ {
+ MainWindow->setWindowTitle(QApplication::translate("MainWindow", "TC Utils", 0, QApplication::UnicodeUTF8));
+ btnUnmount->setText(QApplication::translate("MainWindow", "Unmount device", 0, QApplication::UnicodeUTF8));
+ btnRefresh->setText(QApplication::translate("MainWindow", "Get device list", 0, QApplication::UnicodeUTF8));
+ tabWidget->setTabText(tabWidget->indexOf(tabUnmount), QApplication::translate("MainWindow", "Tab 1", 0, QApplication::UnicodeUTF8));
+ tabWidget->setTabText(tabWidget->indexOf(tab_2), QApplication::translate("MainWindow", "Tab 2", 0, QApplication::UnicodeUTF8));
+ } // retranslateUi
+
+};
+
+namespace Ui {
+ class MainWindow: public Ui_MainWindow {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_MAINWINDOW_H
diff --git a/tcutils/utils.cpp b/tcutils/utils.cpp
new file mode 100644
index 00000000..1b8548c7
--- /dev/null
+++ b/tcutils/utils.cpp
@@ -0,0 +1,217 @@
+#include "utils.h"
+
+Utils::Utils()
+{
+}
+
+int Utils::getMountList(void *wtsChannel, QList<QListWidgetItem *> *itemList)
+{
+ QListWidgetItem *item;
+
+ STREAM s;
+ quint32 bytesToSend;
+ quint32 bytesWritten;
+ quint32 bytesRead;
+ quint32 cmdLen;
+ quint32 cmd;
+ int rv;
+ int i;
+ int nentries;
+ char buf[2048];
+
+ if (!wtsChannel)
+ return -1;
+
+ qstream_new(s, 1024 * 8);
+
+ /*
+ * command format:
+ * 4 bytes cmd_len length of this command
+ * 1 byte cmd TCU_CMD_GET_MOUNT_LIST
+ */
+
+ /* setup command */
+ qstream_wr_u32(&s, 1);
+ qstream_wr_u8(&s, TCU_CMD_GET_MOUNT_LIST);
+ bytesToSend = 5;
+
+ /* send command */
+ rv = WTSVirtualChannelWrite(wtsChannel, s.data, bytesToSend, &bytesWritten);
+ if (rv)
+ {
+ QMessageBox::information(NULL, "Get device list", "\nError sending "
+ "command to client");
+ return -1;
+ }
+
+ qstream_set_pos(&s, 0); /* reuse stream */
+
+ /* get response */
+
+ /*
+ * response format
+ * 4 bytes cmd_len length of this command
+ * 4 bytes cmd TCU_CMD_GET_MOUNT_LIST
+ * 1 byte nentries number of entries in this pkt
+ * n bytes entry_list nentries null terminated strings
+ */
+
+ rv = WTSVirtualChannelRead(wtsChannel, 1000 * 5, s.data, 1024 * 8, &bytesRead);
+ if (rv == 0 || bytesRead == 0)
+ goto error;
+
+ /* did we get the entire cmd? */
+ qstream_rd_u32(&s, cmdLen);
+ if (cmdLen != bytesRead - 4)
+ goto error;
+
+ /* did we get the right response? */
+ qstream_rd_u32(&s, cmd);
+ if (cmd != TCU_CMD_GET_MOUNT_LIST)
+ goto error;
+
+ qstream_rd_u8(&s, nentries);
+ if (nentries == 0)
+ goto done;
+
+ for (i = 0; i < nentries; i++)
+ {
+ strcpy(buf, s.pos);
+ qstream_inc_pos(&s, strlen(buf) + 1);
+ item = new QListWidgetItem;
+ item->setText(QString(buf));
+ itemList->append(item);
+ }
+
+done:
+ qstream_free(&s);
+ return 0;
+
+error:
+ qstream_free(&s);
+ return -1;
+}
+
+int Utils::unmountDevice(void *wtsChannel, QString device, QStatusBar *statusBar)
+{
+ STREAM s;
+ quint32 bytesRead;
+ quint32 cmdLen;
+ quint32 cmd;
+ quint32 bytesWritten;
+ int bytesToSend;
+ int rv;
+ int seconds = 0;
+ char status;
+ char* buf;
+
+ if (!wtsChannel)
+ return -1;
+
+ qstream_new(s, 1024);
+ buf = device.toAscii().data();
+
+ /*
+ * command format:
+ * 4 bytes cmd_len length of this command
+ * 4 bytes cmd TCU_CMD_UNMOUNT_DEVICE
+ * n bytes device null terminated device name
+ */
+
+ /* setup command */
+ bytesToSend = 4 + 4 + device.count() + 1;
+ qstream_wr_u32(&s, bytesToSend - 4);
+ qstream_wr_u32(&s, TCU_CMD_UNMOUNT_DEVICE);
+ strcpy(s.pos, buf);
+
+ /* send command */
+ rv = WTSVirtualChannelWrite(wtsChannel, s.data, bytesToSend, &bytesWritten);
+ if (rv)
+ {
+ QMessageBox::information(NULL, "Unmount device", "\nError sending "
+ "command to client");
+ return -1;
+ }
+
+ qstream_set_pos(&s, 0); /* reuse stream */
+
+ /* get response */
+
+ /*
+ * command format
+ * 4 bytes cmd_len number of bytes in this pkt
+ * 4 bytes cmd TCU_CMD_UNMOUNT_DEVICE
+ * 1 byte status operation status code
+ */
+
+ while (1)
+ {
+ rv = WTSVirtualChannelRead(wtsChannel, 1000 * 1, s.data, 1024, &bytesRead);
+ if (rv == 0)
+ goto error;
+
+ if (bytesRead)
+ break;
+
+ statusBar->showMessage("Waiting for client to unmount device: " +
+ QString::number(++seconds) + " seconds", 30000);
+ }
+
+ statusBar->showMessage("");
+
+ /* did we get the entire pkt? */
+ qstream_rd_u32(&s, cmdLen);
+ if (cmdLen != bytesRead - 4)
+ goto error;
+
+ /* did we get the right response? */
+ qstream_rd_u32(&s, cmd);
+ if (cmd != TCU_CMD_UNMOUNT_DEVICE)
+ goto error;
+
+ /* get status */
+ qstream_rd_u8(&s, status);
+ switch(status)
+ {
+ case UMOUNT_SUCCESS:
+ goto done;
+ break;
+
+ case UMOUNT_BUSY:
+ QMessageBox::information(NULL, "Unmount error", "\nCannot unmount device "
+ "because it is in use");
+ break;
+
+ case UMOUNT_NOT_MOUNTED:
+ QMessageBox::information(NULL, "Unmount error", "\nCannot unmount device "
+ "because it is not mounted");
+ break;
+
+ case UMOUNT_OP_NOT_PERMITTED:
+ QMessageBox::information(NULL, "Unmount error", "\nOperation not "
+ "permitted. The device may be in use");
+ break;
+
+ case UMOUNT_PERMISSION_DENIED:
+ QMessageBox::information(NULL, "Unmount error", "\nYou don't have "
+ "permission to unmount this device");
+ break;
+
+ case UMOUNT_UNKNOWN:
+ QMessageBox::information(NULL, "Unmount error", "Cannot unmount "
+ "device, an unknown error has occurred. The "
+ "drive may be in use or you do not have "
+ "permission to unmount it");
+ break;
+ }
+
+ goto error;
+
+done:
+ qstream_free(&s);
+ return 0;
+
+error:
+ qstream_free(&s);
+ return -1;
+}
diff --git a/tcutils/utils.h b/tcutils/utils.h
new file mode 100644
index 00000000..f0512dc0
--- /dev/null
+++ b/tcutils/utils.h
@@ -0,0 +1,150 @@
+#ifndef UTILS_H
+#define UTILS_H
+
+#include <QDebug>
+#include <QListWidgetItem>
+#include <QMessageBox>
+#include <QStatusBar>
+#include <xrdpapi.h>
+
+/*
+ * stream definition and macros to access them;
+ * all definitions default to little endian
+ */
+
+typedef struct stream
+{
+ char* data; /* holds stream data */
+ char* pos; /* current read/write position */
+ int size; /* number of bytes in data */
+} STREAM;
+
+#define qstream_new(_s, _size) \
+do \
+{ \
+ (_s).data = (char *) malloc(_size); \
+ (_s).pos = (_s).data; \
+ (_s).size = (_size); \
+} \
+while (0)
+
+#define qstream_new_zero(_s, _size) \
+do \
+{ \
+ (_s).data = (char *) calloc((_size), 1); \
+ (_s).pos = (_s).data; \
+ (_s).size = (_size); \
+} \
+while (0)
+
+#define qstream_free(_s) \
+do \
+{ \
+ if ((_s)->data) \
+ free((_s)->data); \
+} \
+while (0)
+
+#define qstream_set_pos(_s, _p) \
+do \
+{ \
+ (_s)->pos = (_s)->data + (_p); \
+} \
+while (0)
+
+#define qstream_inc_pos(_s, _v) \
+do \
+{ \
+ (_s)->pos += (_v); \
+} \
+while (0)
+
+#define qstream_rd_u8(_s, _v) \
+do \
+{ \
+ (_v) = *((unsigned char *) ((_s)->pos)); \
+ (_s)->pos++; \
+} \
+while (0)
+
+#define qstream_rd_u16(_s, _v) \
+do \
+{ \
+ (_v) = (unsigned short) \
+ ( \
+ (*((unsigned char *) ((_s)->pos + 0)) << 0) | \
+ (*((unsigned char *) ((_s)->pos + 1)) << 8) \
+ ); \
+ (_s)->pos += 2; \
+} while (0)
+
+#define qstream_rd_u32(_s, _v) \
+do \
+{ \
+ (_v) = (unsigned int) \
+ ( \
+ (*((unsigned char *) ((_s)->pos + 0)) << 0) | \
+ (*((unsigned char *) ((_s)->pos + 1)) << 8) | \
+ (*((unsigned char *) ((_s)->pos + 2)) << 16) | \
+ (*((unsigned char *) ((_s)->pos + 3)) << 24) \
+ ); \
+ (_s)->pos += 4; \
+} while (0)
+
+#define qstream_wr_u8(_s, _v) \
+do \
+{ \
+ *((_s)->pos) = (unsigned char) (_v); \
+ (_s)->pos++; \
+} while (0)
+
+#define qstream_wr_u16(_s, _v) \
+do \
+{ \
+ *((_s)->pos) = (unsigned char) ((_v) >> 0); \
+ (_s)->pos++; \
+ *((_s)->pos) = (unsigned char) ((_v) >> 8); \
+ (_s)->pos++; \
+} while (0)
+
+#define qstream_wr_u32(_s, _v) \
+do \
+{ \
+ *((_s)->pos) = (unsigned char) ((_v) >> 0); \
+ (_s)->pos++; \
+ *((_s)->pos) = (unsigned char) ((_v) >> 8); \
+ (_s)->pos++; \
+ *((_s)->pos) = (unsigned char) ((_v) >> 16); \
+ (_s)->pos++; \
+ *((_s)->pos) = (unsigned char) ((_v) >> 24); \
+ (_s)->pos++; \
+} while (0)
+
+/* list of commands we support; this list should match the one in */
+/* NeutrinoRDP channels/tcutils/tcutils_main.h */
+enum TCU_COMMANDS
+{
+ TCU_CMD_GET_MOUNT_LIST = 1,
+ TCU_CMD_UNMOUNT_DEVICE
+};
+
+/* umount error codes */
+enum TCU_UMOUNT_ERROR
+{
+ UMOUNT_SUCCESS = 0,
+ UMOUNT_BUSY,
+ UMOUNT_NOT_MOUNTED,
+ UMOUNT_OP_NOT_PERMITTED,
+ UMOUNT_PERMISSION_DENIED,
+ UMOUNT_UNKNOWN
+};
+
+class Utils
+{
+public:
+ Utils();
+ static int getMountList(void *wtsChannel, QList<QListWidgetItem *> *itemList);
+ static int unmountDevice(void *wtsChannel, QString device, QStatusBar *statusBar);
+};
+
+#endif // UTILS_H
diff --git a/tests/memtest/libmem.c b/tests/memtest/libmem.c
index 2fa0dea7..f05ea481 100644
--- a/tests/memtest/libmem.c
+++ b/tests/memtest/libmem.c
@@ -402,3 +402,13 @@ libmem_clear_flags(void* obj, int flags)
self->flags &= ~flags;
return 0;
}
+
+/*****************************************************************************/
+int
+libmem_get_alloced_bytes(void* obj)
+{
+ struct mem_info* self;
+
+ self = (struct mem_info*)obj;
+ return self->total_bytes;
+}
diff --git a/tests/memtest/libmem.h b/tests/memtest/libmem.h
index 4bc4b1ec..cd000443 100644
--- a/tests/memtest/libmem.h
+++ b/tests/memtest/libmem.h
@@ -14,5 +14,7 @@ int
libmem_set_flags(void* obj, int flags);
int
libmem_clear_flags(void* obj, int flags);
+int
+libmem_get_alloced_bytes(void* obj);
#endif
diff --git a/xorg/X11R7.6/cleanx.sh b/xorg/X11R7.6/cleanx.sh
new file mode 100755
index 00000000..7ec804e0
--- /dev/null
+++ b/xorg/X11R7.6/cleanx.sh
@@ -0,0 +1,102 @@
+#!/bin/sh
+#
+# all directories can be read only except
+# Read Write
+# share/X11/xkb/compiled/
+
+if test $# -lt 1
+then
+ echo ""
+ echo "usage: clean_build_dir.sh <installation dir>"
+ echo ""
+ exit 1
+fi
+
+BASEDIR=$1
+
+if ! test -d $BASEDIR
+then
+ echo "error directory $BASEDIR does not exist"
+ exit 1
+fi
+
+if ! test -w $BASEDIR
+then
+ echo "error directory $BASEDIR is not writable"
+ exit 1
+fi
+
+echo cleaning $BASEDIR
+
+if ! test -x $BASEDIR/bin/X11rdp
+then
+ echo "error $BASEDIR/bin/X11rdp does not exist"
+fi
+
+bin_check_file()
+{
+ if [ "$1" = "X11rdp" ]
+ then
+ return 0
+ fi
+ if [ "$1" = "xkbcomp" ]
+ then
+ return 0
+ fi
+ rm -f $1
+ return 0
+}
+
+HOLDPATH=$PWD
+cd $BASEDIR
+
+# remove unused directories
+rm -fr man/
+rm -fr include/
+rm -fr lib/python2.7/
+rm -fr lib/pkgconfig/
+rm -fr share/pkgconfig/
+rm -fr share/gtk-doc
+rm -fr share/doc
+rm -fr share/man
+rm -fr share/aclocal
+rm -fr share/intltool
+rm -fr share/util-macros
+
+# remove development files
+rm -f lib/*.a
+rm -f lib/*.la
+rm -f lib/xorg/modules/*.a
+rm -f lib/xorg/modules/*.la
+
+# remove symbols
+#strip lib/*.so
+#strip lib/xorg/modules/*.so
+
+# remove hardware specific files
+rm -f lib/dri/i915_dri.so
+rm -f lib/dri/i965_dri.so
+rm -f lib/dri/mach64_dri.so
+rm -f lib/dri/mga_dri.so
+rm -f lib/dri/r128_dri.so
+rm -f lib/dri/r200_dri.so
+rm -f lib/dri/r300_dri.so
+rm -f lib/dri/r600_dri.so
+rm -f lib/dri/radeon_dri.so
+rm -f lib/dri/savage_dri.so
+#strip lib/dri/swrast_dri.so
+rm -f lib/dri/tdfx_dri.so
+rm -f lib/dri/unichrome_dri.so
+
+# remove extra bin tools
+cd bin
+for i in *
+do
+ if ! test -d "$i"
+ then
+ bin_check_file $i
+ fi
+done
+cd ..
+
+cd $HOLDPATH
diff --git a/xorg/X11R7.6/rdp/Makefile b/xorg/X11R7.6/rdp/Makefile
index e40b7473..3b84c43c 100644
--- a/xorg/X11R7.6/rdp/Makefile
+++ b/xorg/X11R7.6/rdp/Makefile
@@ -13,7 +13,7 @@ rdpPolylines.o rdpPolySegment.o rdpFillSpans.o rdpSetSpans.o \
rdpCopyPlane.o rdpPolyPoint.o rdpPolyArc.o rdpFillPolygon.o \
rdpPolyFillArc.o rdpPolyText8.o rdpPolyText16.o \
rdpImageText8.o rdpImageText16.o rdpImageGlyphBlt.o rdpPolyGlyphBlt.o \
-rdpPushPixels.o rdpxv.o \
+rdpPushPixels.o rdpxv.o rdpglyph.o rdpComposite.o \
miinitext.o \
fbcmap_mi.o
@@ -43,7 +43,7 @@ LIBS = $(XSRCBASE)/dbe/.libs/libdbe.a \
LLIBS = -Wl,-rpath=$(LIBBASE) -lfreetype -lz -lm -lXfont -lXau \
-lXdmcp -lpixman-1 -lrt -ldl -lcrypto -lGL -lXdamage
-CFLAGS = -O2 -Wall -fno-strength-reduce \
+CFLAGS = -g -O2 -Wall -fno-strength-reduce \
-I../../include \
-I../../cfb \
-I../../mfb \
diff --git a/xorg/X11R7.6/rdp/rdp.h b/xorg/X11R7.6/rdp/rdp.h
index 6fd7c38a..32d05d6a 100644
--- a/xorg/X11R7.6/rdp/rdp.h
+++ b/xorg/X11R7.6/rdp/rdp.h
@@ -95,6 +95,23 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define PixelDPI 100
#define PixelToMM(_size) (((_size) * 254 + (PixelDPI) * 5) / ((PixelDPI) * 10))
+#define TAG_COMPOSITE 0
+#define TAG_COPYAREA 1
+#define TAG_POLYFILLRECT 2
+#define TAG_PUTIMAGE 3
+#define TAG_POLYRECTANGLE 4
+#define TAG_COPYPLANE 5
+#define TAG_POLYARC 6
+#define TAG_FILLPOLYGON 7
+#define TAG_POLYFILLARC 8
+#define TAG_IMAGETEXT8 9
+#define TAG_POLYTEXT8 10
+#define TAG_POLYTEXT16 11
+#define TAG_IMAGETEXT16 12
+#define TAG_IMAGEGLYPHBLT 13
+#define TAG_POLYGLYPHBLT 14
+#define TAG_PUSHPIXELS 15
+
struct image_data
{
int width;
@@ -103,6 +120,10 @@ struct image_data
int Bpp;
int lineBytes;
char* pixels;
+ char* shmem_pixels;
+ int shmem_id;
+ int shmem_offset;
+ int shmem_lineBytes;
};
/* Per-screen (framebuffer) structure. There is only one of these, since we
@@ -114,7 +135,9 @@ struct _rdpScreenInfoRec
int height;
int depth;
int bitsPerPixel;
- int sizeInBytes;
+ int sizeInBytes; /* size of current used frame buffer */
+ int sizeInBytesAlloc; /* size of current alloc frame buffer,
+ always >= sizeInBytes */
char* pfbMemory;
Pixel blackPixel;
Pixel whitePixel;
@@ -142,6 +165,8 @@ struct _rdpScreenInfoRec
CopyWindowProcPtr CopyWindow;
ClearToBackgroundProcPtr ClearToBackground;
ScreenWakeupHandlerProcPtr WakeupHandler;
+ CreatePictureProcPtr CreatePicture;
+ DestroyPictureProcPtr DestroyPicture;
CompositeProcPtr Composite;
GlyphsProcPtr Glyphs;
/* Backing store procedures */
@@ -198,6 +223,7 @@ typedef rdpWindowRec* rdpWindowPtr;
#define RDI_IMGLY 3 /* lossy */
#define RDI_LINE 4
#define RDI_SCRBLT 5
+#define RDI_TEXT 6
struct urdp_draw_item_fill
{
@@ -234,17 +260,25 @@ struct urdp_draw_item_scrblt
int cy;
};
+struct urdp_draw_item_text
+{
+ int opcode;
+ int fg_color;
+ struct rdp_text* rtext; /* in rdpglyph.h */
+};
+
union urdp_draw_item
{
struct urdp_draw_item_fill fill;
struct urdp_draw_item_img img;
struct urdp_draw_item_line line;
struct urdp_draw_item_scrblt scrblt;
+ struct urdp_draw_item_text text;
};
struct rdp_draw_item
{
- int type;
+ int type; /* RDI_FILL, RDI_IMGLL, ... */
int flags;
struct rdp_draw_item* prev;
struct rdp_draw_item* next;
@@ -252,6 +286,8 @@ struct rdp_draw_item
union urdp_draw_item u;
};
+#define XRDP_USE_COUNT_THRESHOLD 1
+
struct _rdpPixmapRec
{
int status;
@@ -259,6 +295,11 @@ struct _rdpPixmapRec
int con_number;
int is_dirty;
int is_scratch;
+ int is_alpha_dirty_not;
+ /* number of times used in a remote operation
+ if this gets above XRDP_USE_COUNT_THRESHOLD
+ then we force remote the pixmap */
+ int use_count;
int kind_width;
struct rdp_draw_item* draw_item_head;
struct rdp_draw_item* draw_item_tail;
@@ -325,6 +366,8 @@ void
hexdump(unsigned char *p, unsigned int len);
void
RegionAroundSegs(RegionPtr reg, xSegment* segs, int nseg);
+int
+get_crc(char* data, int data_bytes);
/* rdpdraw.c */
Bool
@@ -353,6 +396,9 @@ int
draw_item_add_srcblt_region(rdpPixmapRec* priv, RegionPtr reg,
int srcx, int srcy, int dstx, int dsty,
int cx, int cy);
+int
+draw_item_add_text_region(rdpPixmapRec* priv, RegionPtr reg, int color,
+ int opcode, struct rdp_text* rtext);
PixmapPtr
rdpCreatePixmap(ScreenPtr pScreen, int width, int height, int depth,
@@ -411,15 +457,19 @@ rdpDisplayCursor(ScreenPtr pScreen, CursorPtr pCursor);
void
rdpRecolorCursor(ScreenPtr pScreen, CursorPtr pCursor,
Bool displayed);
+
+/* rdpglyph.c */
+/* look in rdpglyph.h */
+
+/* rdpComposite.c */
+int
+rdpCreatePicture(PicturePtr pPicture);
+void
+rdpDestroyPicture(PicturePtr pPicture);
void
rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst,
INT16 yDst, CARD16 width, CARD16 height);
-void
-rdpGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc, INT16 ySrc, int nlists, GlyphListPtr lists,
- GlyphPtr* glyphs);
/* rdpinput.c */
int
@@ -461,6 +511,8 @@ int
rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv);
int
rdpup_remove_os_bitmap(int rdpindex);
+int
+rdpup_update_os_use(int rdpindex);
void
rdpup_get_screen_image_rect(struct image_data* id);
void
@@ -504,6 +556,8 @@ rdpup_set_cursor_ex(short x, short y, char *cur_data, char *cur_mask, int bpp);
int
rdpup_create_os_surface(int rdpindexd, int width, int height);
int
+rdpup_create_os_surface_bpp(int rdpindexd, int width, int height, int bpp);
+int
rdpup_switch_os_surface(int rdpindex);
int
rdpup_delete_os_surface(int rdpindex);
@@ -520,7 +574,29 @@ rdpup_delete_window(WindowPtr pWindow, rdpWindowRec* priv);
int
rdpup_check_dirty(PixmapPtr pDirtyPixmap, rdpPixmapRec* pDirtyPriv);
int
+rdpup_check_alpha_dirty(PixmapPtr pDirtyPixmap, rdpPixmapRec* pDirtyPriv);
+int
rdpup_check_dirty_screen(rdpPixmapRec* pDirtyPriv);
+int
+rdpup_add_char(int font, int charactor, short x, short y, int cx, int cy,
+ char* bmpdata, int bmpdata_bytes);
+int
+rdpup_add_char_alpha(int font, int charactor, short x, short y, int cx, int cy,
+ char* bmpdata, int bmpdata_bytes);
+int
+rdpup_draw_text(int font, int flags, int mixmode,
+ short clip_left, short clip_top,
+ short clip_right, short clip_bottom,
+ short box_left, short box_top,
+ short box_right, short box_bottom, short x, short y,
+ char* data, int data_bytes);
+int
+rdpup_composite(short srcidx, int srcformat, short srcwidth, CARD8 srcrepeat,
+ PictTransform* srctransform, CARD8 mskflags,
+ short mskidx, int mskformat, short mskwidth, CARD8 mskrepeat,
+ CARD8 op, short srcx, short srcy, short mskx, short msky,
+ short dstx, short dsty, short width, short height,
+ int dstformat);
void
rdpScheduleDeferredUpdate(void);
@@ -592,6 +668,13 @@ struct stream
#endif
/******************************************************************************/
+#define out_uint8(s, v) \
+{ \
+ *((s)->p) = (unsigned char)((v) >> 0); \
+ (s)->p++; \
+}
+
+/******************************************************************************/
#define init_stream(s, v) \
{ \
if ((v) > (s)->size) \
@@ -619,6 +702,13 @@ struct stream
}
/******************************************************************************/
+#define out_uint8s(s, n) do \
+{ \
+ memset((s)->p, 0, (n)); \
+ (s)->p += (n); \
+} while (0)
+
+/******************************************************************************/
#if defined(B_ENDIAN) || defined(NEED_ALIGN)
#define out_uint32_le(s, v) \
{ \
diff --git a/xorg/X11R7.6/rdp/rdpComposite.c b/xorg/X11R7.6/rdp/rdpComposite.c
new file mode 100644
index 00000000..f763783e
--- /dev/null
+++ b/xorg/X11R7.6/rdp/rdpComposite.c
@@ -0,0 +1,846 @@
+/*
+ Copyright 2012-2013 Jay Sorg
+
+ Permission to use, copy, modify, distribute, and sell this software and its
+ documentation for any purpose is hereby granted without fee, provided that
+ the above copyright notice appear in all copies and that both that
+ copyright notice and this permission notice appear in supporting
+ documentation.
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ */
+
+#include "rdp.h"
+#include "rdpdraw.h"
+
+#define LDEBUG 0
+
+#define LOG_LEVEL 1
+#define LLOG(_level, _args) \
+ do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0)
+#define LLOGLN(_level, _args) \
+ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0)
+
+extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */
+extern DevPrivateKeyRec g_rdpGCIndex; /* from rdpmain.c */
+extern DevPrivateKeyRec g_rdpWindowIndex; /* from rdpmain.c */
+extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */
+extern int g_Bpp; /* from rdpmain.c */
+extern ScreenPtr g_pScreen; /* from rdpmain.c */
+extern Bool g_wrapPixmap; /* from rdpmain.c */
+extern int g_can_do_pix_to_pix; /* from rdpmain.c */
+extern int g_do_dirty_os; /* in rdpmain.c */
+extern int g_do_dirty_ons; /* in rdpmain.c */
+extern rdpPixmapRec g_screenPriv; /* in rdpmain.c */
+extern int g_do_glyph_cache; /* in rdpmain.c */
+extern int g_doing_font; /* in rdpmain.c */
+extern int g_do_composite; /* in rdpmain.c */
+
+extern GCOps g_rdpGCOps; /* from rdpdraw.c */
+
+extern int g_con_number; /* in rdpup.c */
+
+extern int g_crc_seed; /* in rdpmisc.c */
+extern int g_crc_table[]; /* in rdpmisc.c */
+
+/******************************************************************************/
+int
+rdpCreatePicture(PicturePtr pPicture)
+{
+ PictureScreenPtr ps;
+ int rv;
+
+ LLOGLN(10, ("rdpCreatePicture:"));
+ ps = GetPictureScreen(g_pScreen);
+ ps->CreatePicture = g_rdpScreen.CreatePicture;
+ rv = ps->CreatePicture(pPicture);
+ ps->CreatePicture = rdpCreatePicture;
+ return rv;
+}
+
+/******************************************************************************/
+void
+rdpDestroyPicture(PicturePtr pPicture)
+{
+ PictureScreenPtr ps;
+
+ LLOGLN(10, ("rdpDestroyPicture:"));
+ ps = GetPictureScreen(g_pScreen);
+ ps->DestroyPicture = g_rdpScreen.DestroyPicture;
+ ps->DestroyPicture(pPicture);
+ ps->DestroyPicture = rdpDestroyPicture;
+}
+
+/******************************************************************************/
+static int
+print_format(PictFormatShort format)
+{
+ switch (format)
+ {
+ case PIXMAN_a2r10g10b10:
+ LLOGLN(0, (" PIXMAN_x2r10g10b10"));
+ break;
+ case PIXMAN_x2r10g10b10:
+ LLOGLN(0, (" PIXMAN_x2r10g10b10"));
+ break;
+ case PIXMAN_a2b10g10r10:
+ LLOGLN(0, (" PIXMAN_a2b10g10r10"));
+ break;
+ case PIXMAN_x2b10g10r10:
+ LLOGLN(0, (" PIXMAN_x2b10g10r10"));
+ break;
+
+ case PIXMAN_a8r8g8b8:
+ LLOGLN(0, (" PIXMAN_a8r8g8b8"));
+ break;
+ case PIXMAN_x8r8g8b8:
+ LLOGLN(0, (" PIXMAN_x8r8g8b8"));
+ break;
+ case PIXMAN_a8b8g8r8:
+ LLOGLN(0, (" PIXMAN_a8b8g8r8"));
+ break;
+ case PIXMAN_x8b8g8r8:
+ LLOGLN(0, (" PIXMAN_x8b8g8r8"));
+ break;
+ case PIXMAN_b8g8r8a8:
+ LLOGLN(0, (" PIXMAN_b8g8r8a8"));
+ break;
+ case PIXMAN_b8g8r8x8:
+ LLOGLN(0, (" PIXMAN_b8g8r8x8"));
+ break;
+
+ /* 24bpp formats */
+ case PIXMAN_r8g8b8:
+ LLOGLN(0, (" PIXMAN_r8g8b8"));
+ break;
+ case PIXMAN_b8g8r8:
+ LLOGLN(0, (" PIXMAN_b8g8r8"));
+ break;
+
+ /* 16bpp formats */
+ case PIXMAN_r5g6b5:
+ LLOGLN(0, (" PIXMAN_r5g6b5"));
+ break;
+ case PIXMAN_b5g6r5:
+ LLOGLN(0, (" PIXMAN_b5g6r5"));
+ break;
+
+ case PIXMAN_a1r5g5b5:
+ LLOGLN(0, (" PIXMAN_a1r5g5b5"));
+ break;
+ case PIXMAN_x1r5g5b5:
+ LLOGLN(0, (" PIXMAN_x1r5g5b5"));
+ break;
+ case PIXMAN_a1b5g5r5:
+ LLOGLN(0, (" PIXMAN_a1b5g5r5"));
+ break;
+ case PIXMAN_x1b5g5r5:
+ LLOGLN(0, (" PIXMAN_x1b5g5r5"));
+ break;
+ case PIXMAN_a4r4g4b4:
+ LLOGLN(0, (" PIXMAN_a4r4g4b4"));
+ break;
+ case PIXMAN_x4r4g4b4:
+ LLOGLN(0, (" PIXMAN_x4r4g4b4"));
+ break;
+ case PIXMAN_a4b4g4r4:
+ LLOGLN(0, (" PIXMAN_a4b4g4r4"));
+ break;
+ case PIXMAN_x4b4g4r4:
+ LLOGLN(0, (" PIXMAN_x4b4g4r4"));
+ break;
+
+ /* 8bpp formats */
+ case PIXMAN_a8:
+ LLOGLN(0, (" PIXMAN_a8"));
+ break;
+ case PIXMAN_r3g3b2:
+ LLOGLN(0, (" PIXMAN_r3g3b2"));
+ break;
+ case PIXMAN_b2g3r3:
+ LLOGLN(0, (" PIXMAN_b2g3r3"));
+ break;
+ case PIXMAN_a2r2g2b2:
+ LLOGLN(0, (" PIXMAN_a2r2g2b2"));
+ break;
+ case PIXMAN_a2b2g2r2:
+ LLOGLN(0, (" PIXMAN_a2b2g2r2"));
+ break;
+
+ case PIXMAN_c8:
+ LLOGLN(0, (" PIXMAN_c8"));
+ break;
+ case PIXMAN_g8:
+ LLOGLN(0, (" PIXMAN_g8"));
+ break;
+
+ case PIXMAN_x4a4:
+ LLOGLN(0, (" PIXMAN_x4a4"));
+ break;
+
+ /* 4bpp formats */
+ case PIXMAN_a4:
+ LLOGLN(0, (" PIXMAN_a4"));
+ break;
+ case PIXMAN_r1g2b1:
+ LLOGLN(0, (" PIXMAN_r1g2b1"));
+ break;
+ case PIXMAN_b1g2r1:
+ LLOGLN(0, (" PIXMAN_b1g2r1"));
+ break;
+ case PIXMAN_a1r1g1b1:
+ LLOGLN(0, (" PIXMAN_a1r1g1b1"));
+ break;
+ case PIXMAN_a1b1g1r1:
+ LLOGLN(0, (" PIXMAN_a1b1g1r1"));
+ break;
+
+ case PIXMAN_c4:
+ LLOGLN(0, (" PIXMAN_c4"));
+ break;
+ case PIXMAN_g4:
+ LLOGLN(0, (" PIXMAN_g4"));
+ break;
+
+ /* 1bpp formats */
+ case PIXMAN_a1:
+ LLOGLN(0, (" PIXMAN_a1"));
+ break;
+ case PIXMAN_g1:
+ LLOGLN(0, (" PIXMAN_g1"));
+ break;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+static int
+compsoite_print(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst,
+ INT16 yDst, CARD16 width, CARD16 height)
+{
+ PixmapPtr pSrcPixmap;
+ PixmapPtr pDstPixmap;
+ rdpPixmapRec* pSrcPriv;
+ rdpPixmapRec* pDstPriv;
+
+ LLOGLN(0, ("compsoite_print: op %d xSrc %d ySrc %d xDst %d yDst %d "
+ "width %d height %d",
+ op, xSrc, ySrc, xDst, yDst, width, height));
+
+ if (pSrc != 0)
+ {
+ LLOGLN(0, (" src depth %d width %d height %d repeat %d repeatType %d "
+ "dither %d filter %d alphaMap %p componentAlpha %d", pSrc->pDrawable->depth,
+ pSrc->pDrawable->width, pSrc->pDrawable->height,
+ pSrc->repeat, pSrc->repeatType, pSrc->dither, pSrc->filter,
+ pSrc->alphaMap, pSrc->componentAlpha));
+ LLOGLN(0, (" transform %p", pSrc->transform));
+ LLOGLN(0, (" detail format red %d red mask %d green %d green mask %d "
+ "blue %d blue mask %d",
+ pSrc->pFormat->direct.red, pSrc->pFormat->direct.redMask,
+ pSrc->pFormat->direct.green, pSrc->pFormat->direct.greenMask,
+ pSrc->pFormat->direct.blue, pSrc->pFormat->direct.blueMask));
+ print_format(pSrc->format);
+ if (pSrc->pDrawable->type == DRAWABLE_PIXMAP)
+ {
+ pSrcPixmap = (PixmapPtr)(pSrc->pDrawable);
+ pSrcPriv = GETPIXPRIV(pSrcPixmap);
+ LLOGLN(0, (" DRAWABLE_PIXMAP pSrcPriv %p status %d", pSrcPriv, pSrcPriv->status));
+ }
+ else if (pSrc->pDrawable->type == DRAWABLE_WINDOW)
+ {
+ LLOGLN(0, (" DRAWABLE_WINDOW"));
+ }
+ else
+ {
+ LLOGLN(0, (" OTHER"));
+ }
+ }
+ if (pMask != 0)
+ {
+ LLOGLN(0, (" msk depth %d width %d height %d repeat %d repeatType %d",
+ pMask->pDrawable->depth,
+ pMask->pDrawable->width,
+ pMask->pDrawable->height, pMask->repeat, pMask->repeatType));
+ print_format(pMask->format);
+ }
+ if (pDst != 0)
+ {
+ LLOGLN(0, (" dst depth %d width %d height %d repeat %d repeatType %d "
+ "dither %d filter %d alphaMap %p", pDst->pDrawable->depth,
+ pDst->pDrawable->width, pDst->pDrawable->height,
+ pDst->repeat, pDst->repeatType, pDst->dither, pDst->filter,
+ pDst->alphaMap));
+ LLOGLN(0, (" transform %p", pDst->transform));
+ print_format(pDst->format);
+ if (pDst->pDrawable->type == DRAWABLE_PIXMAP)
+ {
+ pDstPixmap = (PixmapPtr)(pDst->pDrawable);
+ pDstPriv = GETPIXPRIV(pDstPixmap);
+ LLOGLN(0, (" DRAWABLE_PIXMAP pDstPriv %p status %d", pDstPriv, pDstPriv->status));
+ }
+ else if (pDst->pDrawable->type == DRAWABLE_WINDOW)
+ {
+ LLOGLN(0, (" DRAWABLE_WINDOW"));
+ }
+ else
+ {
+ LLOGLN(0, (" OTHER"));
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************/
+static int
+src_alpha_needed(CARD8 op)
+{
+ int rv;
+
+ rv = 0;
+ switch (op)
+ {
+ case 3: /* Over */
+ case 6: /* InReverse */
+ case 8: /* OutReverse */
+ case 9: /* Atop */
+ case 10: /* AtopReverse */
+ case 11: /* Xor */
+ case 13: /* Saturate */
+ case 17: /* DisjointOver */
+ case 18: /* DisjointOverReverse */
+ case 19: /* DisjointIn */
+ case 20: /* DisjointInReverse */
+ case 21: /* DisjointOut */
+ case 22: /* DisjointOutReverse */
+ case 23: /* DisjointAtop */
+ case 24: /* DisjointAtopReverse */
+ case 25: /* DisjointXor */
+ case 29: /* ConjointOver */
+ case 30: /* ConjointOverReverse */
+ case 31: /* ConjointIn */
+ case 32: /* ConjointInReverse */
+ case 33: /* ConjointOut */
+ case 34: /* ConjointOutReverse */
+ case 35: /* ConjointAtop */
+ case 36: /* ConjointAtopReverse */
+ case 37: /* ConjointXor */
+ rv = 1;
+ break;
+ }
+ return rv;
+}
+
+/******************************************************************************/
+static int
+dst_alpha_needed(CARD8 op)
+{
+ int rv;
+
+ rv = 0;
+ switch (op)
+ {
+ case 4: /* OverReverse */
+ case 5: /* In */
+ case 7: /* Out */
+ case 9: /* Atop */
+ case 10: /* AtopReverse */
+ case 11: /* Xor */
+ case 13: /* Saturate */
+ case 17: /* DisjointOver */
+ case 18: /* DisjointOverReverse */
+ case 19: /* DisjointIn */
+ case 20: /* DisjointInReverse */
+ case 21: /* DisjointOut */
+ case 22: /* DisjointOutReverse */
+ case 23: /* DisjointAtop */
+ case 24: /* DisjointAtopReverse */
+ case 25: /* DisjointXor */
+ case 29: /* ConjointOver */
+ case 30: /* ConjointOverReverse */
+ case 31: /* ConjointIn */
+ case 32: /* ConjointInReverse */
+ case 33: /* ConjointOut */
+ case 34: /* ConjointOutReverse */
+ case 35: /* ConjointAtop */
+ case 36: /* ConjointAtopReverse */
+ case 37: /* ConjointXor */
+ rv = 1;
+ break;
+ }
+ return rv;
+}
+
+struct msk_info
+{
+ int flags;
+ int idx;
+ int format;
+ int width;
+ int repeat;
+};
+
+static char g_com_fail_strings[][128] =
+{
+ "OK",
+ "src not remotable",
+ "dst not remotable",
+ "msk not remotable"
+};
+
+/******************************************************************************/
+/* returns boolean */
+static int
+check_drawables(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst,
+ INT16 yDst, CARD16 width, CARD16 height, struct msk_info* msk)
+{
+ int rv;
+ int fail_reason;
+ PixmapPtr pSrcPixmap;
+ PixmapPtr pDstPixmap;
+ PixmapPtr pMskPixmap;
+ rdpPixmapRec* pSrcPriv;
+ rdpPixmapRec* pDstPriv;
+ rdpPixmapRec* pMskPriv;
+
+ fail_reason = 0;
+ pSrcPixmap = 0;
+ pDstPixmap = 0;
+ pMskPixmap = 0;
+ pSrcPriv = 0;
+ pDstPriv = 0;
+ pMskPriv = 0;
+ rv = 0;
+ if (pSrc != 0)
+ {
+ if (pSrc->pDrawable != 0)
+ {
+ if (pSrc->pDrawable->type == DRAWABLE_PIXMAP)
+ {
+ pSrcPixmap = (PixmapPtr)(pSrc->pDrawable);
+ pSrcPriv = GETPIXPRIV(pSrcPixmap);
+ if (xrdp_is_os(pSrcPixmap, pSrcPriv))
+ {
+ if (pDst != 0)
+ {
+ if (pDst->pDrawable != 0)
+ {
+ if (pDst->pDrawable->type == DRAWABLE_PIXMAP)
+ {
+ pDstPixmap = (PixmapPtr)(pDst->pDrawable);
+ pDstPriv = GETPIXPRIV(pDstPixmap);
+ if (xrdp_is_os(pDstPixmap, pDstPriv))
+ {
+ rv = 1;
+ }
+ else
+ {
+ fail_reason = 2;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ fail_reason = 1;
+ }
+ }
+ }
+ }
+ if (rv)
+ {
+ if (pMask != 0)
+ {
+#if 1
+ rv = 0;
+ if (pMask->pDrawable != 0)
+ {
+ if (pMask->pDrawable->type == DRAWABLE_PIXMAP)
+ {
+ pMskPixmap = (PixmapPtr)(pMask->pDrawable);
+ pMskPriv = GETPIXPRIV(pMskPixmap);
+ if (xrdp_is_os(pMskPixmap, pMskPriv))
+ {
+ rv = 1;
+ msk->flags = 1;
+ msk->idx = pMskPriv->rdpindex;
+ msk->format = pMask->format;
+ msk->width = pMask->pDrawable->width;
+ msk->repeat = pMask->repeatType;
+ }
+ else
+ {
+ fail_reason = 3;
+ }
+ }
+ }
+#endif
+ }
+ }
+ if (rv == 0)
+ {
+ LLOGLN(10, ("check_drawables: can not remote [%s]", g_com_fail_strings[fail_reason]));
+#if 0
+ compsoite_print(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
+ xDst, yDst, width, height);
+#endif
+ }
+ else
+ {
+ LLOGLN(10, ("check_drawables: can remote [%s]", g_com_fail_strings[fail_reason]));
+#if 0
+ compsoite_print(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
+ xDst, yDst, width, height);
+#endif
+ }
+ return rv;
+}
+
+/******************************************************************************/
+static int
+rdpRemoteComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst,
+ INT16 yDst, CARD16 width, CARD16 height)
+{
+ int ok_to_remote;
+ PixmapPtr pSrcPixmap;
+ PixmapPtr pMskPixmap;
+ PixmapPtr pDstPixmap;
+ rdpPixmapRec* pSrcPriv;
+ rdpPixmapRec* pMskPriv;
+ rdpPixmapRec* pDstPriv;
+ BoxRec box;
+ RegionRec reg1;
+ RegionRec reg2;
+ DrawablePtr p;
+ int j;
+ int num_clips;
+ struct msk_info msk;
+
+ LLOGLN(10, ("rdpRemoteComposite:"));
+
+ memset(&msk, 0, sizeof(msk));
+ ok_to_remote = check_drawables(op, pSrc, pMask, pDst, xSrc, ySrc,
+ xMask, yMask, xDst, yDst, width, height,
+ &msk);
+ if (!ok_to_remote)
+ {
+ return 1;
+ }
+
+ ValidatePicture(pSrc);
+ pSrcPixmap = (PixmapPtr)(pSrc->pDrawable);
+ pSrcPriv = GETPIXPRIV(pSrcPixmap);
+ rdpup_check_dirty(pSrcPixmap, pSrcPriv);
+ if (PIXMAN_FORMAT_A(pSrc->format) > 0)
+ {
+ if (src_alpha_needed(op))
+ {
+ rdpup_check_alpha_dirty(pSrcPixmap, pSrcPriv);
+ }
+ }
+
+ ValidatePicture(pDst);
+ pDstPixmap = (PixmapPtr)(pDst->pDrawable);
+ pDstPriv = GETPIXPRIV(pDstPixmap);
+ rdpup_check_dirty(pDstPixmap, pDstPriv);
+
+ if (PIXMAN_FORMAT_A(pDst->format) > 0)
+ {
+ if (dst_alpha_needed(op))
+ {
+ rdpup_check_alpha_dirty(pDstPixmap, pDstPriv);
+ }
+ }
+
+ if (pMask != 0)
+ {
+ ValidatePicture(pMask);
+ pMskPixmap = (PixmapPtr)(pMask->pDrawable);
+ pMskPriv = GETPIXPRIV(pMskPixmap);
+ rdpup_check_dirty(pMskPixmap, pMskPriv);
+ if (PIXMAN_FORMAT_A(msk.format) > 0)
+ {
+ rdpup_check_alpha_dirty(pMskPixmap, pMskPriv);
+ }
+ }
+
+ p = pDst->pDrawable;
+ rdpup_switch_os_surface(pDstPriv->rdpindex);
+ if (pDst->pCompositeClip != 0)
+ {
+ box.x1 = xDst;
+ box.y1 = yDst;
+ box.x2 = box.x1 + width;
+ box.y2 = box.y1 + height;
+ RegionInit(&reg1, &box, 0);
+ RegionInit(&reg2, NullBox, 0);
+ RegionCopy(&reg2, pDst->pCompositeClip);
+ RegionIntersect(&reg1, &reg1, &reg2);
+ RegionTranslate(&reg1, p->x, p->y);
+ num_clips = REGION_NUM_RECTS(&reg1);
+ if (num_clips > 0)
+ {
+ LLOGLN(10, ("num_clips %d", num_clips));
+ rdpup_begin_update();
+ for (j = num_clips - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&reg1)[j];
+ rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ LLOGLN(10, ("pSrc->format 0x%x 0x%x 0x%x %d %d %d %d %d %d %d %d",
+ pSrc->format, msk.format, pDst->format, xSrc, ySrc,
+ xMask, yMask, xDst, yDst, width, height));
+ rdpup_composite(pSrcPriv->rdpindex, pSrc->format,
+ pSrc->pDrawable->width, pSrc->repeatType,
+ pSrc->transform, msk.flags, msk.idx, msk.format,
+ msk.width, msk.repeat, op, xSrc, ySrc,
+ xMask, yMask, xDst, yDst, width, height, pDst->format);
+ }
+ rdpup_reset_clip();
+ rdpup_end_update();
+ }
+ RegionUninit(&reg1);
+ RegionUninit(&reg2);
+ }
+ else
+ {
+ rdpup_begin_update();
+ rdpup_composite(pSrcPriv->rdpindex, pSrc->format,
+ pSrc->pDrawable->width, pSrc->repeatType,
+ pSrc->transform, msk.flags, msk.idx, msk.format,
+ msk.width, msk.repeat, op, xSrc, ySrc,
+ xMask, yMask, xDst, yDst, width, height, pDst->format);
+ rdpup_end_update();
+ }
+ rdpup_switch_os_surface(-1);
+
+ return 0;
+}
+
+/******************************************************************************/
+static void
+rdpCompositeOrg(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst,
+ INT16 yDst, CARD16 width, CARD16 height)
+{
+ PictureScreenPtr ps;
+
+ ps = GetPictureScreen(g_pScreen);
+ ps->Composite = g_rdpScreen.Composite;
+ ps->Composite(op, pSrc, pMask, pDst, xSrc, ySrc,
+ xMask, yMask, xDst, yDst, width, height);
+ ps->Composite = rdpComposite;
+}
+
+/******************************************************************************/
+/* it looks like all the antialias draws go through here
+ op is one of the following
+ #define PictOpMinimum 0
+ #define PictOpClear 0
+ #define PictOpSrc 1
+ #define PictOpDst 2
+ #define PictOpOver 3
+ #define PictOpOverReverse 4
+ #define PictOpIn 5
+ #define PictOpInReverse 6
+ #define PictOpOut 7
+ #define PictOpOutReverse 8
+ #define PictOpAtop 9
+ #define PictOpAtopReverse 10
+ #define PictOpXor 11
+ #define PictOpAdd 12
+ #define PictOpSaturate 13
+ #define PictOpMaximum 13
+
+ see for porter duff
+ http://www.svgopen.org/2005/papers/abstractsvgopen/
+
+ */
+void
+rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst,
+ INT16 yDst, CARD16 width, CARD16 height)
+{
+ BoxRec box;
+ RegionRec reg1;
+ RegionRec reg2;
+ DrawablePtr p;
+ int dirty_type;
+ int j;
+ int num_clips;
+ int post_process;
+ int reset_surface;
+ int got_id;
+ WindowPtr pDstWnd;
+ PixmapPtr pDstPixmap;
+ rdpPixmapRec* pDstPriv;
+ rdpPixmapRec* pDirtyPriv;
+ struct image_data id;
+
+ LLOGLN(10, ("rdpComposite:"));
+
+ if (g_doing_font == 2)
+ {
+ rdpCompositeOrg(op, pSrc, pMask, pDst, xSrc, ySrc,
+ xMask, yMask, xDst, yDst, width, height);
+
+ return;
+ }
+
+#if 0
+ if (g_do_glyph_cache && g_do_alpha_glyphs)
+ {
+ if (pSrc->pDrawable->width == 1 &&
+ pSrc->pDrawable->height == 1)
+ {
+ if (pMask != 0)
+ {
+ /* TODO: here we can try to send it as a gylph */
+ }
+ }
+ }
+#endif
+
+ /* try to remote the composite call */
+ if (g_do_composite &&
+ rdpRemoteComposite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
+ xDst, yDst, width, height) == 0)
+ {
+ rdpCompositeOrg(op, pSrc, pMask, pDst, xSrc, ySrc,
+ xMask, yMask, xDst, yDst, width, height);
+ return;
+ }
+
+ rdpCompositeOrg(op, pSrc, pMask, pDst, xSrc, ySrc,
+ xMask, yMask, xDst, yDst, width, height);
+
+ LLOGLN(10, ("rdpComposite: op %d %p %p %p w %d h %d", op, pSrc, pMask, pDst, width, height));
+
+ p = pDst->pDrawable;
+
+ pDstPriv = 0;
+ dirty_type = 0;
+ pDirtyPriv = 0;
+ post_process = 0;
+ reset_surface = 0;
+ got_id = 0;
+ if (p->type == DRAWABLE_PIXMAP)
+ {
+ pDstPixmap = (PixmapPtr)p;
+ pDstPriv = GETPIXPRIV(pDstPixmap);
+ if (XRDP_IS_OS(pDstPriv))
+ {
+ post_process = 1;
+ if (g_do_dirty_os)
+ {
+ LLOGLN(10, ("rdpComposite: gettig dirty"));
+ pDstPriv->is_dirty = 1;
+ dirty_type = g_doing_font ? RDI_IMGLL : RDI_IMGLY;
+ pDirtyPriv = pDstPriv;
+ }
+ else
+ {
+ rdpup_switch_os_surface(pDstPriv->rdpindex);
+ reset_surface = 1;
+ rdpup_get_pixmap_image_rect(pDstPixmap, &id);
+ got_id = 1;
+ LLOGLN(10, ("rdpComposite: offscreen"));
+ }
+ }
+ }
+ else
+ {
+ if (p->type == DRAWABLE_WINDOW)
+ {
+ pDstWnd = (WindowPtr)p;
+ if (pDstWnd->viewable)
+ {
+ post_process = 1;
+ if (g_do_dirty_ons)
+ {
+ LLOGLN(10, ("rdpComposite: getting dirty"));
+ g_screenPriv.is_dirty = 1;
+ pDirtyPriv = &g_screenPriv;
+ dirty_type = g_doing_font ? RDI_IMGLL : RDI_IMGLY;
+ }
+ else
+ {
+ rdpup_get_screen_image_rect(&id);
+ got_id = 1;
+ }
+ }
+ }
+ }
+
+ if (!post_process)
+ {
+ return;
+ }
+
+ if (pDst->pCompositeClip != 0)
+ {
+ box.x1 = p->x + xDst;
+ box.y1 = p->y + yDst;
+ box.x2 = box.x1 + width;
+ box.y2 = box.y1 + height;
+ RegionInit(&reg1, &box, 0);
+ RegionInit(&reg2, NullBox, 0);
+ RegionCopy(&reg2, pDst->pCompositeClip);
+ RegionIntersect(&reg1, &reg1, &reg2);
+ if (dirty_type != 0)
+ {
+ draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_COMPOSITE);
+ }
+ else if (got_id)
+ {
+ num_clips = REGION_NUM_RECTS(&reg1);
+ if (num_clips > 0)
+ {
+ rdpup_begin_update();
+ for (j = num_clips - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&reg1)[j];
+ rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ rdpup_end_update();
+ }
+ }
+ RegionUninit(&reg1);
+ RegionUninit(&reg2);
+ }
+ else
+ {
+ box.x1 = p->x + xDst;
+ box.y1 = p->y + yDst;
+ box.x2 = box.x1 + width;
+ box.y2 = box.y1 + height;
+ if (dirty_type != 0)
+ {
+ RegionInit(&reg1, &box, 0);
+ draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_COMPOSITE);
+ RegionUninit(&reg1);
+ }
+ else if (got_id)
+ {
+ rdpup_begin_update();
+ rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ rdpup_end_update();
+ }
+ }
+ if (reset_surface)
+ {
+ rdpup_switch_os_surface(-1);
+ }
+}
diff --git a/xorg/X11R7.6/rdp/rdpCopyArea.c b/xorg/X11R7.6/rdp/rdpCopyArea.c
index a97aaf56..4718a89c 100644
--- a/xorg/X11R7.6/rdp/rdpCopyArea.c
+++ b/xorg/X11R7.6/rdp/rdpCopyArea.c
@@ -429,6 +429,8 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
pSrcPixmap = (PixmapPtr)pSrc;
pSrcPriv = GETPIXPRIV(pSrcPixmap);
+ LLOGLN(10, ("rdpCopyArea: 3 %d %d", pSrcPixmap->usage_hint, pSrcPriv->is_scratch));
+
if (xrdp_is_os(pSrcPixmap, pSrcPriv))
{
if (pDst->type == DRAWABLE_WINDOW)
@@ -468,10 +470,12 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
}
else
{
- LLOGLN(10, ("rdpCopyArea: 2"));
+ LLOGLN(10, ("rdpCopyArea: 2 %d %d", pSrcPixmap->usage_hint, pSrcPriv->is_scratch));
}
}
+ LLOGLN(10, ("rdpCopyArea: fallback"));
+
/* do original call */
rv = rdpCopyAreaOrg(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
@@ -492,10 +496,10 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
if (g_do_dirty_os)
{
- LLOGLN(10, ("rdpCopyArea: gettig dirty"));
+ LLOGLN(10, ("rdpCopyArea: getting dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
- dirty_type = RDI_IMGLL;
+ dirty_type = RDI_IMGLY;
}
else
{
@@ -522,10 +526,10 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
if (g_do_dirty_ons)
{
- LLOGLN(10, ("rdpCopyArea: gettig dirty"));
+ LLOGLN(10, ("rdpCopyArea: getting dirty"));
g_screenPriv.is_dirty = 1;
pDirtyPriv = &g_screenPriv;
- dirty_type = RDI_IMGLL;
+ dirty_type = RDI_IMGLY;
}
else
{
@@ -541,6 +545,8 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
return rv;
}
+ LLOGLN(10, ("rdpCopyArea: post_process"));
+
RegionInit(&clip_reg, NullBox, 0);
cd = rdp_get_clip(&clip_reg, pDst, pGC);
@@ -553,7 +559,7 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
box.x2 = box.x1 + w;
box.y2 = box.y1 + h;
RegionInit(&reg1, &box, 0);
- draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 1);
+ draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_COPYAREA);
RegionUninit(&reg1);
}
else if (got_id)
@@ -577,7 +583,7 @@ rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
box.y2 = box.y1 + h;
RegionInit(&box_reg, &box, 0);
RegionIntersect(&clip_reg, &clip_reg, &box_reg);
- draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type, 1);
+ draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type, TAG_COPYAREA);
RegionUninit(&box_reg);
}
else if (got_id)
diff --git a/xorg/X11R7.6/rdp/rdpCopyPlane.c b/xorg/X11R7.6/rdp/rdpCopyPlane.c
index aac03287..063766ee 100644
--- a/xorg/X11R7.6/rdp/rdpCopyPlane.c
+++ b/xorg/X11R7.6/rdp/rdpCopyPlane.c
@@ -111,7 +111,7 @@ rdpCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
if (g_do_dirty_os)
{
- LLOGLN(10, ("rdpCopyPlane: gettig dirty"));
+ LLOGLN(10, ("rdpCopyPlane: getting dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLL;
@@ -137,7 +137,7 @@ rdpCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
if (g_do_dirty_ons)
{
- LLOGLN(0, ("rdpCopyPlane: gettig dirty"));
+ LLOGLN(10, ("rdpCopyPlane: getting dirty"));
g_screenPriv.is_dirty = 1;
pDirtyPriv = &g_screenPriv;
dirty_type = RDI_IMGLL;
@@ -168,7 +168,7 @@ rdpCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
box.x2 = box.x1 + w;
box.y2 = box.y1 + h;
RegionInit(&reg1, &box, 0);
- draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 5);
+ draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_COPYPLANE);
RegionUninit(&reg1);
}
else if (got_id)
@@ -194,7 +194,7 @@ rdpCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
RegionInit(&reg2, NullBox, 0);
RegionCopy(&reg2, &clip_reg);
RegionIntersect(&reg1, &reg1, &reg2);
- draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 5);
+ draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_COPYPLANE);
RegionUninit(&reg1);
RegionUninit(&reg2);
}
diff --git a/xorg/X11R7.6/rdp/rdpFillPolygon.c b/xorg/X11R7.6/rdp/rdpFillPolygon.c
index 4c54f447..960f619e 100644
--- a/xorg/X11R7.6/rdp/rdpFillPolygon.c
+++ b/xorg/X11R7.6/rdp/rdpFillPolygon.c
@@ -150,7 +150,7 @@ rdpFillPolygon(DrawablePtr pDrawable, GCPtr pGC,
if (g_do_dirty_os)
{
- LLOGLN(10, ("rdpFillPolygon: gettig dirty"));
+ LLOGLN(10, ("rdpFillPolygon: getting dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLL;
@@ -176,7 +176,7 @@ rdpFillPolygon(DrawablePtr pDrawable, GCPtr pGC,
if (g_do_dirty_ons)
{
- LLOGLN(0, ("rdpFillPolygon: gettig dirty"));
+ LLOGLN(10, ("rdpFillPolygon: getting dirty"));
g_screenPriv.is_dirty = 1;
pDirtyPriv = &g_screenPriv;
dirty_type = RDI_IMGLL;
@@ -203,7 +203,7 @@ rdpFillPolygon(DrawablePtr pDrawable, GCPtr pGC,
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
- draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 7);
+ draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_FILLPOLYGON);
RegionUninit(&reg1);
}
else if (got_id)
@@ -223,7 +223,7 @@ rdpFillPolygon(DrawablePtr pDrawable, GCPtr pGC,
{
if (dirty_type != 0)
{
- draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type, 7);
+ draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type, TAG_FILLPOLYGON);
}
else if (got_id)
{
diff --git a/xorg/X11R7.6/rdp/rdpImageGlyphBlt.c b/xorg/X11R7.6/rdp/rdpImageGlyphBlt.c
index c5fcfaa7..d425a30b 100644
--- a/xorg/X11R7.6/rdp/rdpImageGlyphBlt.c
+++ b/xorg/X11R7.6/rdp/rdpImageGlyphBlt.c
@@ -108,7 +108,7 @@ rdpImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
if (g_do_dirty_os)
{
- LLOGLN(10, ("rdpImageGlyphBlt: gettig dirty"));
+ LLOGLN(10, ("rdpImageGlyphBlt: getting dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLL;
@@ -134,7 +134,7 @@ rdpImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
if (g_do_dirty_ons)
{
- LLOGLN(0, ("rdpImageGlyphBlt: gettig dirty"));
+ LLOGLN(10, ("rdpImageGlyphBlt: getting dirty"));
g_screenPriv.is_dirty = 1;
pDirtyPriv = &g_screenPriv;
dirty_type = RDI_IMGLL;
@@ -169,7 +169,7 @@ rdpImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
- draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 13);
+ draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_IMAGEGLYPHBLT);
RegionUninit(&reg1);
}
else if (got_id)
@@ -189,7 +189,7 @@ rdpImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
{
if (dirty_type != 0)
{
- draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type, 13);
+ draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type, TAG_IMAGEGLYPHBLT);
}
else if (got_id)
{
diff --git a/xorg/X11R7.6/rdp/rdpImageText16.c b/xorg/X11R7.6/rdp/rdpImageText16.c
index e6048095..604d85e3 100644
--- a/xorg/X11R7.6/rdp/rdpImageText16.c
+++ b/xorg/X11R7.6/rdp/rdpImageText16.c
@@ -106,7 +106,7 @@ rdpImageText16(DrawablePtr pDrawable, GCPtr pGC,
if (g_do_dirty_os)
{
- LLOGLN(10, ("rdpImageText16: gettig dirty"));
+ LLOGLN(10, ("rdpImageText16: getting dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLY;
@@ -132,7 +132,7 @@ rdpImageText16(DrawablePtr pDrawable, GCPtr pGC,
if (g_do_dirty_ons)
{
- LLOGLN(10, ("rdpImageText16: gettig dirty"));
+ LLOGLN(10, ("rdpImageText16: getting dirty"));
g_screenPriv.is_dirty = 1;
pDirtyPriv = &g_screenPriv;
dirty_type = RDI_IMGLL;
@@ -167,7 +167,7 @@ rdpImageText16(DrawablePtr pDrawable, GCPtr pGC,
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
- draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 12);
+ draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_IMAGETEXT16);
RegionUninit(&reg1);
}
else if (got_id)
@@ -187,7 +187,7 @@ rdpImageText16(DrawablePtr pDrawable, GCPtr pGC,
{
if (dirty_type != 0)
{
- draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type, 12);
+ draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type, TAG_IMAGETEXT16);
}
else if (got_id)
{
diff --git a/xorg/X11R7.6/rdp/rdpImageText8.c b/xorg/X11R7.6/rdp/rdpImageText8.c
index 641637e0..08dead18 100644
--- a/xorg/X11R7.6/rdp/rdpImageText8.c
+++ b/xorg/X11R7.6/rdp/rdpImageText8.c
@@ -106,7 +106,7 @@ rdpImageText8(DrawablePtr pDrawable, GCPtr pGC,
if (g_do_dirty_os)
{
- LLOGLN(10, ("rdpImageText8: gettig dirty"));
+ LLOGLN(10, ("rdpImageText8: getting dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLL;
@@ -132,7 +132,7 @@ rdpImageText8(DrawablePtr pDrawable, GCPtr pGC,
if (g_do_dirty_ons)
{
- LLOGLN(0, ("rdpImageText8: gettig dirty"));
+ LLOGLN(10, ("rdpImageText8: getting dirty"));
g_screenPriv.is_dirty = 1;
pDirtyPriv = &g_screenPriv;
dirty_type = RDI_IMGLL;
@@ -167,7 +167,7 @@ rdpImageText8(DrawablePtr pDrawable, GCPtr pGC,
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
- draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 9);
+ draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_IMAGETEXT8);
RegionUninit(&reg1);
}
else if (got_id)
@@ -187,7 +187,7 @@ rdpImageText8(DrawablePtr pDrawable, GCPtr pGC,
{
if (dirty_type != 0)
{
- draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type, 9);
+ draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type, TAG_IMAGETEXT8);
}
else if (got_id)
{
diff --git a/xorg/X11R7.6/rdp/rdpPolyArc.c b/xorg/X11R7.6/rdp/rdpPolyArc.c
index 6d6651f1..84a85587 100644
--- a/xorg/X11R7.6/rdp/rdpPolyArc.c
+++ b/xorg/X11R7.6/rdp/rdpPolyArc.c
@@ -125,7 +125,7 @@ rdpPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs)
if (g_do_dirty_os)
{
- LLOGLN(10, ("rdpPolyArc: gettig dirty"));
+ LLOGLN(10, ("rdpPolyArc: getting dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLL;
@@ -151,7 +151,7 @@ rdpPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs)
if (g_do_dirty_ons)
{
- LLOGLN(0, ("rdpPolyArc: gettig dirty"));
+ LLOGLN(10, ("rdpPolyArc: getting dirty"));
g_screenPriv.is_dirty = 1;
pDirtyPriv = &g_screenPriv;
dirty_type = RDI_IMGLL;
@@ -185,7 +185,7 @@ rdpPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs)
{
if (dirty_type != 0)
{
- draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type, 6);
+ draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type, TAG_POLYARC);
}
else if (got_id)
{
@@ -217,7 +217,7 @@ rdpPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs)
{
if (dirty_type != 0)
{
- draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type, 6);
+ draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type, TAG_POLYARC);
}
else if (got_id)
{
diff --git a/xorg/X11R7.6/rdp/rdpPolyFillArc.c b/xorg/X11R7.6/rdp/rdpPolyFillArc.c
index 6582f69e..e3822215 100644
--- a/xorg/X11R7.6/rdp/rdpPolyFillArc.c
+++ b/xorg/X11R7.6/rdp/rdpPolyFillArc.c
@@ -125,7 +125,7 @@ rdpPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs)
if (g_do_dirty_os)
{
- LLOGLN(10, ("rdpPolyFillArc: gettig dirty"));
+ LLOGLN(10, ("rdpPolyFillArc: getting dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLY;
@@ -151,7 +151,7 @@ rdpPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs)
if (g_do_dirty_ons)
{
- LLOGLN(0, ("rdpPolyFillArc: gettig dirty"));
+ LLOGLN(10, ("rdpPolyFillArc: getting dirty"));
g_screenPriv.is_dirty = 1;
pDirtyPriv = &g_screenPriv;
dirty_type = RDI_IMGLL;
@@ -185,7 +185,7 @@ rdpPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs)
{
if (dirty_type != 0)
{
- draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type, 8);
+ draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type, TAG_POLYFILLARC);
}
else if (got_id)
{
@@ -217,7 +217,7 @@ rdpPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs)
{
if (dirty_type != 0)
{
- draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type, 8);
+ draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type, TAG_POLYFILLARC);
}
else if (got_id)
{
diff --git a/xorg/X11R7.6/rdp/rdpPolyFillRect.c b/xorg/X11R7.6/rdp/rdpPolyFillRect.c
index e51fca4c..7db4be69 100644
--- a/xorg/X11R7.6/rdp/rdpPolyFillRect.c
+++ b/xorg/X11R7.6/rdp/rdpPolyFillRect.c
@@ -105,10 +105,11 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
if (g_do_dirty_ons)
{
- LLOGLN(10, ("rdpPolyFillRect: gettig dirty"));
+ LLOGLN(10, ("rdpPolyFillRect: getting dirty"));
g_screenPriv.is_dirty = 1;
pDirtyPriv = &g_screenPriv;
- dirty_type = RDI_IMGLL;
+ dirty_type = (FillTiled == pGC->fillStyle) ?
+ RDI_IMGLY : RDI_IMGLL;
}
else
{
@@ -122,10 +123,11 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
if (g_do_dirty_os)
{
- LLOGLN(10, ("rdpPolyFillRect: gettig dirty"));
+ LLOGLN(10, ("rdpPolyFillRect: getting dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
- dirty_type = RDI_FILL;
+ dirty_type = (FillTiled == pGC->fillStyle) ?
+ RDI_IMGLY : RDI_IMGLL;
}
else
{
@@ -148,10 +150,11 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
if (g_do_dirty_ons)
{
- LLOGLN(10, ("rdpPolyFillRect: gettig dirty"));
+ LLOGLN(10, ("rdpPolyFillRect: getting dirty"));
g_screenPriv.is_dirty = 1;
pDirtyPriv = &g_screenPriv;
- dirty_type = RDI_IMGLL;
+ dirty_type = (FillTiled == pGC->fillStyle) ?
+ RDI_IMGLY : RDI_IMGLL;
}
else
{
@@ -192,7 +195,8 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
}
else
{
- draw_item_add_img_region(pDirtyPriv, fill_reg, GXcopy, RDI_IMGLL, 2);
+ draw_item_add_img_region(pDirtyPriv, fill_reg, GXcopy,
+ dirty_type, TAG_POLYFILLRECT);
}
}
else if (got_id)
@@ -214,7 +218,8 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
for (j = REGION_NUM_RECTS(fill_reg) - 1; j >= 0; j--)
{
box = REGION_RECTS(fill_reg)[j];
- rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ rdpup_fill_rect(box.x1, box.y1,
+ box.x2 - box.x1, box.y2 - box.y1);
}
rdpup_set_opcode(GXcopy);
@@ -251,13 +256,15 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
pGC->alu == GXxor*/)) /* todo, why dosen't xor work? */
{
LLOGLN(10, ("rdpPolyFillRect: 3"));
- draw_item_add_fill_region(pDirtyPriv, &clip_reg, pGC->fgPixel,
+ draw_item_add_fill_region(pDirtyPriv, &clip_reg,
+ pGC->fgPixel,
pGC->alu);
}
else
{
LLOGLN(10, ("rdpPolyFillRect: 4"));
- draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, RDI_IMGLL, 2);
+ draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy,
+ dirty_type, TAG_POLYFILLRECT);
}
}
else if (got_id)
@@ -281,7 +288,8 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
for (j = num_clips - 1; j >= 0; j--)
{
box = REGION_RECTS(&clip_reg)[j];
- rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ rdpup_fill_rect(box.x1, box.y1,
+ box.x2 - box.x1, box.y2 - box.y1);
}
rdpup_set_opcode(GXcopy);
@@ -291,7 +299,8 @@ rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
for (j = num_clips - 1; j >= 0; j--)
{
box = REGION_RECTS(&clip_reg)[j];
- rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ rdpup_send_area(&id, box.x1, box.y1,
+ box.x2 - box.x1, box.y2 - box.y1);
}
}
diff --git a/xorg/X11R7.6/rdp/rdpPolyGlyphBlt.c b/xorg/X11R7.6/rdp/rdpPolyGlyphBlt.c
index 298b4b98..8ce1db08 100644
--- a/xorg/X11R7.6/rdp/rdpPolyGlyphBlt.c
+++ b/xorg/X11R7.6/rdp/rdpPolyGlyphBlt.c
@@ -108,7 +108,7 @@ rdpPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
if (g_do_dirty_os)
{
- LLOGLN(10, ("rdpPolyGlyphBlt: gettig dirty"));
+ LLOGLN(10, ("rdpPolyGlyphBlt: getting dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLY;
@@ -134,7 +134,7 @@ rdpPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
if (g_do_dirty_ons)
{
- LLOGLN(0, ("rdpPolyGlyphBlt: gettig dirty"));
+ LLOGLN(10, ("rdpPolyGlyphBlt: getting dirty"));
g_screenPriv.is_dirty = 1;
pDirtyPriv = &g_screenPriv;
dirty_type = RDI_IMGLL;
@@ -169,7 +169,7 @@ rdpPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
- draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 14);
+ draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_POLYGLYPHBLT);
RegionUninit(&reg1);
}
else if (got_id)
@@ -189,7 +189,7 @@ rdpPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
{
if (dirty_type != 0)
{
- draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type, 14);
+ draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type, TAG_POLYGLYPHBLT);
}
else if (got_id)
{
diff --git a/xorg/X11R7.6/rdp/rdpPolyPoint.c b/xorg/X11R7.6/rdp/rdpPolyPoint.c
index 28db831a..e2eadafd 100644
--- a/xorg/X11R7.6/rdp/rdpPolyPoint.c
+++ b/xorg/X11R7.6/rdp/rdpPolyPoint.c
@@ -156,7 +156,7 @@ rdpPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
if (g_do_dirty_os)
{
- LLOGLN(10, ("rdpPolyPoint: gettig dirty"));
+ LLOGLN(10, ("rdpPolyPoint: getting dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLL;
@@ -182,7 +182,7 @@ rdpPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
if (g_do_dirty_ons)
{
- LLOGLN(0, ("rdpPolyPoint: gettig dirty"));
+ LLOGLN(10, ("rdpPolyPoint: getting dirty"));
g_screenPriv.is_dirty = 1;
pDirtyPriv = &g_screenPriv;
dirty_type = RDI_IMGLL;
diff --git a/xorg/X11R7.6/rdp/rdpPolyRectangle.c b/xorg/X11R7.6/rdp/rdpPolyRectangle.c
index 85bef306..c1a5c971 100644
--- a/xorg/X11R7.6/rdp/rdpPolyRectangle.c
+++ b/xorg/X11R7.6/rdp/rdpPolyRectangle.c
@@ -118,7 +118,7 @@ rdpPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
if (g_do_dirty_os)
{
- LLOGLN(10, ("rdpPolyRectangle: gettig dirty"));
+ LLOGLN(10, ("rdpPolyRectangle: getting dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLL;
@@ -144,7 +144,7 @@ rdpPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
if (g_do_dirty_ons)
{
- LLOGLN(10, ("rdpPolyRectangle: gettig dirty"));
+ LLOGLN(10, ("rdpPolyRectangle: getting dirty"));
g_screenPriv.is_dirty = 1;
pDirtyPriv = &g_screenPriv;
dirty_type = RDI_IMGLL;
@@ -221,7 +221,7 @@ rdpPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
}
else
{
- draw_item_add_img_region(pDirtyPriv, fill_reg, GXcopy, dirty_type, 4);
+ draw_item_add_img_region(pDirtyPriv, fill_reg, GXcopy, dirty_type, TAG_POLYRECTANGLE);
}
RegionDestroy(fill_reg);
@@ -275,7 +275,7 @@ rdpPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
}
else
{
- draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type, 4);
+ draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type, TAG_POLYRECTANGLE);
}
}
else if (got_id)
diff --git a/xorg/X11R7.6/rdp/rdpPolySegment.c b/xorg/X11R7.6/rdp/rdpPolySegment.c
index 623ec748..f4bcfe31 100644
--- a/xorg/X11R7.6/rdp/rdpPolySegment.c
+++ b/xorg/X11R7.6/rdp/rdpPolySegment.c
@@ -115,7 +115,7 @@ rdpPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment *pSegs)
if (g_do_dirty_os)
{
- LLOGLN(10, ("rdpPolySegment: gettig dirty"));
+ LLOGLN(10, ("rdpPolySegment: getting dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLL;
@@ -141,7 +141,7 @@ rdpPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment *pSegs)
if (g_do_dirty_ons)
{
- LLOGLN(10, ("rdpPolySegment: gettig dirty"));
+ LLOGLN(10, ("rdpPolySegment: getting dirty"));
g_screenPriv.is_dirty = 1;
pDirtyPriv = &g_screenPriv;
dirty_type = RDI_IMGLL;
diff --git a/xorg/X11R7.6/rdp/rdpPolyText16.c b/xorg/X11R7.6/rdp/rdpPolyText16.c
index 9a253464..a28030f0 100644
--- a/xorg/X11R7.6/rdp/rdpPolyText16.c
+++ b/xorg/X11R7.6/rdp/rdpPolyText16.c
@@ -109,7 +109,7 @@ rdpPolyText16(DrawablePtr pDrawable, GCPtr pGC,
if (g_do_dirty_os)
{
- LLOGLN(10, ("rdpPolyText16: gettig dirty"));
+ LLOGLN(10, ("rdpPolyText16: getting dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLY;
@@ -135,7 +135,7 @@ rdpPolyText16(DrawablePtr pDrawable, GCPtr pGC,
if (g_do_dirty_ons)
{
- LLOGLN(0, ("rdpPolyText16: gettig dirty"));
+ LLOGLN(10, ("rdpPolyText16: getting dirty"));
g_screenPriv.is_dirty = 1;
pDirtyPriv = &g_screenPriv;
dirty_type = RDI_IMGLL;
@@ -170,7 +170,7 @@ rdpPolyText16(DrawablePtr pDrawable, GCPtr pGC,
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
- draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 11);
+ draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_POLYTEXT16);
RegionUninit(&reg1);
}
else if (got_id)
@@ -190,7 +190,7 @@ rdpPolyText16(DrawablePtr pDrawable, GCPtr pGC,
{
if (dirty_type != 0)
{
- draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type, 11);
+ draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type, TAG_POLYTEXT16);
}
else if (got_id)
{
diff --git a/xorg/X11R7.6/rdp/rdpPolyText8.c b/xorg/X11R7.6/rdp/rdpPolyText8.c
index 59f04d78..3157a538 100644
--- a/xorg/X11R7.6/rdp/rdpPolyText8.c
+++ b/xorg/X11R7.6/rdp/rdpPolyText8.c
@@ -109,7 +109,7 @@ rdpPolyText8(DrawablePtr pDrawable, GCPtr pGC,
if (g_do_dirty_os)
{
- LLOGLN(10, ("rdpPolyText8: gettig dirty"));
+ LLOGLN(10, ("rdpPolyText8: getting dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLY;
@@ -135,7 +135,7 @@ rdpPolyText8(DrawablePtr pDrawable, GCPtr pGC,
if (g_do_dirty_ons)
{
- LLOGLN(0, ("rdpPolyText8: gettig dirty"));
+ LLOGLN(10, ("rdpPolyText8: getting dirty"));
g_screenPriv.is_dirty = 1;
pDirtyPriv = &g_screenPriv;
dirty_type = RDI_IMGLL;
@@ -170,7 +170,7 @@ rdpPolyText8(DrawablePtr pDrawable, GCPtr pGC,
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
- draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 10);
+ draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_POLYTEXT8);
RegionUninit(&reg1);
}
else if (got_id)
@@ -190,7 +190,7 @@ rdpPolyText8(DrawablePtr pDrawable, GCPtr pGC,
{
if (dirty_type != 0)
{
- draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type, 10);
+ draw_item_add_img_region(pDirtyPriv, &reg, GXcopy, dirty_type, TAG_POLYTEXT8);
}
else if (got_id)
{
diff --git a/xorg/X11R7.6/rdp/rdpPolylines.c b/xorg/X11R7.6/rdp/rdpPolylines.c
index 759d1ff9..ba6381b8 100644
--- a/xorg/X11R7.6/rdp/rdpPolylines.c
+++ b/xorg/X11R7.6/rdp/rdpPolylines.c
@@ -166,7 +166,7 @@ rdpPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
if (g_do_dirty_os)
{
- LLOGLN(10, ("rdpPolylines: gettig dirty"));
+ LLOGLN(10, ("rdpPolylines: getting dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLL;
@@ -192,7 +192,7 @@ rdpPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
if (g_do_dirty_ons)
{
- LLOGLN(10, ("rdpPolylines: gettig dirty"));
+ LLOGLN(10, ("rdpPolylines: getting dirty"));
g_screenPriv.is_dirty = 1;
pDirtyPriv = &g_screenPriv;
dirty_type = RDI_IMGLL;
diff --git a/xorg/X11R7.6/rdp/rdpPushPixels.c b/xorg/X11R7.6/rdp/rdpPushPixels.c
index 6a353977..e7d330d1 100644
--- a/xorg/X11R7.6/rdp/rdpPushPixels.c
+++ b/xorg/X11R7.6/rdp/rdpPushPixels.c
@@ -102,7 +102,7 @@ rdpPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst,
if (g_do_dirty_os)
{
- LLOGLN(10, ("rdpPushPixels: gettig dirty"));
+ LLOGLN(10, ("rdpPushPixels: getting dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLY;
@@ -128,7 +128,7 @@ rdpPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst,
if (g_do_dirty_ons)
{
- LLOGLN(0, ("rdpPushPixels: gettig dirty"));
+ LLOGLN(10, ("rdpPushPixels: getting dirty"));
g_screenPriv.is_dirty = 1;
pDirtyPriv = &g_screenPriv;
dirty_type = RDI_IMGLL;
@@ -160,7 +160,7 @@ rdpPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst,
box.x2 = box.x1 + w;
box.y2 = box.y1 + h;
RegionInit(&reg1, &box, 0);
- draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 15);
+ draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_PUSHPIXELS);
RegionUninit(&reg1);
}
else if (got_id)
@@ -185,7 +185,7 @@ rdpPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst,
if (dirty_type != 0)
{
RegionInit(&reg1, &box, 0);
- draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type, 15);
+ draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type, TAG_PUSHPIXELS);
RegionUninit(&reg1);
}
else if (got_id)
diff --git a/xorg/X11R7.6/rdp/rdpPutImage.c b/xorg/X11R7.6/rdp/rdpPutImage.c
index 737e4b31..d244d895 100644
--- a/xorg/X11R7.6/rdp/rdpPutImage.c
+++ b/xorg/X11R7.6/rdp/rdpPutImage.c
@@ -106,7 +106,7 @@ rdpPutImage(DrawablePtr pDst, GCPtr pGC, int depth, int x, int y,
if (g_do_dirty_os)
{
- LLOGLN(10, ("rdpPutImage: gettig dirty"));
+ LLOGLN(10, ("rdpPutImage: getting dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLY;
@@ -132,10 +132,10 @@ rdpPutImage(DrawablePtr pDst, GCPtr pGC, int depth, int x, int y,
if (g_do_dirty_ons)
{
- LLOGLN(10, ("rdpPutImage: gettig dirty"));
+ LLOGLN(10, ("rdpPutImage: getting dirty"));
g_screenPriv.is_dirty = 1;
pDirtyPriv = &g_screenPriv;
- dirty_type = RDI_IMGLL;
+ dirty_type = RDI_IMGLY;
}
else
{
@@ -163,7 +163,7 @@ rdpPutImage(DrawablePtr pDst, GCPtr pGC, int depth, int x, int y,
box.x2 = box.x1 + w;
box.y2 = box.y1 + h;
RegionInit(&reg1, &box, 0);
- draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 3);
+ draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_PUTIMAGE);
RegionUninit(&reg1);
}
else if (got_id)
@@ -185,7 +185,7 @@ rdpPutImage(DrawablePtr pDst, GCPtr pGC, int depth, int x, int y,
RegionInit(&reg2, NullBox, 0);
RegionCopy(&reg2, &clip_reg);
RegionIntersect(&reg1, &reg1, &reg2);
- draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 3);
+ draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, TAG_PUTIMAGE);
RegionUninit(&reg1);
RegionUninit(&reg2);
}
diff --git a/xorg/X11R7.6/rdp/rdpSetSpans.c b/xorg/X11R7.6/rdp/rdpSetSpans.c
index 2b650e94..62dd8c5c 100644
--- a/xorg/X11R7.6/rdp/rdpSetSpans.c
+++ b/xorg/X11R7.6/rdp/rdpSetSpans.c
@@ -38,6 +38,8 @@ extern int g_Bpp; /* from rdpmain.c */
extern ScreenPtr g_pScreen; /* from rdpmain.c */
extern Bool g_wrapPixmap; /* from rdpmain.c */
extern int g_do_dirty_os; /* in rdpmain.c */
+extern int g_do_dirty_ons; /* in rdpmain.c */
+extern rdpPixmapRec g_screenPriv; /* in rdpmain.c */
extern GCOps g_rdpGCOps; /* from rdpdraw.c */
@@ -95,7 +97,7 @@ rdpSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
if (g_do_dirty_os)
{
- LLOGLN(10, ("rdpSetSpans: gettig dirty"));
+ LLOGLN(10, ("rdpSetSpans: getting dirty"));
pDstPriv->is_dirty = 1;
pDirtyPriv = pDstPriv;
dirty_type = RDI_IMGLY;
@@ -118,8 +120,18 @@ rdpSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
if (pDstWnd->viewable)
{
post_process = 1;
- rdpup_get_screen_image_rect(&id);
- got_id = 1;
+ if (g_do_dirty_ons)
+ {
+ LLOGLN(10, ("rdpSetSpans: getting dirty"));
+ g_screenPriv.is_dirty = 1;
+ pDirtyPriv = &g_screenPriv;
+ dirty_type = RDI_IMGLL;
+ }
+ else
+ {
+ rdpup_get_screen_image_rect(&id);
+ got_id = 1;
+ }
}
}
}
diff --git a/xorg/X11R7.6/rdp/rdpdraw.c b/xorg/X11R7.6/rdp/rdpdraw.c
index 4b900f4e..e276c0b7 100644
--- a/xorg/X11R7.6/rdp/rdpdraw.c
+++ b/xorg/X11R7.6/rdp/rdpdraw.c
@@ -45,6 +45,7 @@ Xserver drawing ops and funcs
#include "rdpImageGlyphBlt.h"
#include "rdpPolyGlyphBlt.h"
#include "rdpPushPixels.h"
+#include "rdpglyph.h"
#define LOG_LEVEL 1
#define LLOG(_level, _args) \
@@ -65,11 +66,10 @@ extern int g_do_dirty_os; /* in rdpmain.c */
extern int g_do_dirty_ons; /* in rdpmain.c */
extern rdpPixmapRec g_screenPriv; /* in rdpmain.c */
extern int g_con_number; /* in rdpmain.c */
+extern int g_do_glyph_cache; /* in rdpmain.c */
ColormapPtr g_rdpInstalledColormap;
-static int g_doing_font = 0;
-
GCFuncs g_rdpGCFuncs =
{
rdpValidateGC, rdpChangeGC, rdpCopyGC, rdpDestroyGC, rdpChangeClip,
@@ -407,6 +407,8 @@ rdpCloseScreen(int i, ScreenPtr pScreen)
int
draw_item_add(rdpPixmapRec *priv, struct rdp_draw_item *di)
{
+ priv->is_alpha_dirty_not = 0;
+
if (priv->draw_item_tail == 0)
{
priv->draw_item_tail = di;
@@ -458,6 +460,11 @@ draw_item_remove(rdpPixmapRec *priv, struct rdp_draw_item *di)
g_free(di->u.line.segs);
}
}
+
+ if (di->type == RDI_TEXT)
+ {
+ delete_rdp_text(di->u.text.rtext);
+ }
RegionDestroy(di->reg);
g_free(di);
@@ -483,13 +490,175 @@ draw_item_remove_all(rdpPixmapRec *priv)
/******************************************************************************/
int
+region_get_pixel_count(RegionPtr reg)
+{
+ int index;
+ int count;
+ int pixels;
+ int width;
+ int height;
+ BoxRec box;
+
+ pixels = 0;
+ count = REGION_NUM_RECTS(reg);
+ for (index = 0; index < count; index++)
+ {
+ box = REGION_RECTS(reg)[index];
+ width = box.x2 - box.x1;
+ height = box.y2 - box.y1;
+ pixels += width * height;
+ }
+ return pixels;
+}
+
+/******************************************************************************/
+/* returns boolean */
+int
+region_in_region(RegionPtr reg_small, int sreg_pcount, RegionPtr reg_big)
+{
+ int rv;
+ RegionRec reg;
+
+ rv = 0;
+ RegionInit(&reg, NullBox, 0);
+ RegionIntersect(&reg, reg_small, reg_big);
+ if (sreg_pcount == -1)
+ {
+ sreg_pcount = region_get_pixel_count(reg_small);
+ }
+ if (sreg_pcount == 0)
+ {
+ /* empty region not even in */
+ return 0;
+ }
+ if (region_get_pixel_count(&reg) == sreg_pcount)
+ {
+ rv = 1;
+ }
+ RegionUninit(&reg);
+ return rv;
+}
+
+/******************************************************************************/
+static int
+remove_empties(rdpPixmapRec* priv)
+{
+ struct rdp_draw_item* di;
+ struct rdp_draw_item* di_prev;
+ int rv;
+
+ rv = 0;
+ /* remove draw items with empty regions */
+ di = priv->draw_item_head;
+ di_prev = 0;
+ while (di != 0)
+ {
+ if (!RegionNotEmpty(di->reg))
+ {
+ LLOGLN(10, ("remove_empties: removing empty item type %d", di->type));
+ draw_item_remove(priv, di);
+ di = di_prev == 0 ? priv->draw_item_head : di_prev->next;
+ rv++;
+ }
+ else
+ {
+ di_prev = di;
+ di = di->next;
+ }
+ }
+ return rv;
+}
+
+/******************************************************************************/
+static int
+dump_draw_list(rdpPixmapRec* priv)
+{
+ struct rdp_draw_item* di;
+ int index;
+ int count;
+ BoxRec box;
+
+ LLOGLN(0, ("dump_draw_list:"));
+ di = priv->draw_item_head;
+ while (di != 0)
+ {
+ LLOGLN(0, (" type %d", di->type));
+ count = REGION_NUM_RECTS(di->reg);
+ if (count == 0)
+ {
+ LLOGLN(0, (" empty region"));
+ }
+ else
+ {
+ box = RegionExtents(di->reg)[0];
+ LLOGLN(0, (" region list follows extents x1 %d y1 %d x2 %d y2 %d",
+ box.x1, box.y1, box.x2, box.y2));
+ for (index = 0; index < count; index++)
+ {
+ box = REGION_RECTS(di->reg)[index];
+ LLOGLN(0, (" index %d x1 %d y1 %d x2 %d y2 %d",
+ index, box.x1, box.y1, box.x2, box.y2));
+ }
+ }
+ di = di->next;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/* returns boolean */
+static int
+region_interect_at_all(RegionPtr reg_small, RegionPtr reg_big)
+{
+ int rv;
+ RegionRec reg;
+
+ if (!RegionNotEmpty(reg_small))
+ {
+ return 0;
+ }
+ rv = 0;
+ RegionInit(&reg, NullBox, 0);
+ RegionIntersect(&reg, reg_big, reg_big);
+ if (RegionNotEmpty(&reg))
+ {
+ rv = 1;
+ }
+ RegionUninit(&reg);
+ return rv;
+}
+
+/******************************************************************************/
+int
draw_item_pack(PixmapPtr pix, rdpPixmapRec *priv)
{
struct rdp_draw_item *di;
struct rdp_draw_item *di_prev;
+ BoxRec box;
+ RegionRec treg;
#if 1
+ if (pix != 0)
+ {
+ box.x1 = 0;
+ box.x2 = pix->drawable.width;
+ box.y1 = 0;
+ box.y2 = pix->drawable.height;
+ RegionInit(&treg, &box, 0);
+ di = priv->draw_item_head;
+ di_prev = 0;
+ while (di != 0)
+ {
+ RegionIntersect(di->reg, di->reg, &treg);
+ di_prev = di;
+ di = di->next;
+ }
+ RegionUninit(&treg);
+ remove_empties(priv);
+ }
+#endif
+#if 1
/* look for repeating draw types */
if (priv->draw_item_head != 0)
{
@@ -500,6 +669,17 @@ draw_item_pack(PixmapPtr pix, rdpPixmapRec *priv)
while (di != 0)
{
+#if 0
+ if ((di_prev->type == RDI_IMGLL || di_prev->type == RDI_IMGLY) &&
+ (di->type == RDI_IMGLL || di->type == RDI_IMGLY))
+ {
+ LLOGLN(10, ("draw_item_pack: packing RDI_IMGLL and RDI_IMGLY"));
+ di_prev->type = RDI_IMGLY;
+ RegionUnion(di_prev->reg, di_prev->reg, di->reg);
+ draw_item_remove(priv, di);
+ di = di_prev->next;
+ }
+#else
if ((di_prev->type == RDI_IMGLL) && (di->type == RDI_IMGLL))
{
LLOGLN(10, ("draw_item_pack: packing RDI_IMGLL"));
@@ -507,6 +687,7 @@ draw_item_pack(PixmapPtr pix, rdpPixmapRec *priv)
draw_item_remove(priv, di);
di = di_prev->next;
}
+#endif
else if ((di_prev->type == RDI_IMGLY) && (di->type == RDI_IMGLY))
{
LLOGLN(10, ("draw_item_pack: packing RDI_IMGLY"));
@@ -522,10 +703,37 @@ draw_item_pack(PixmapPtr pix, rdpPixmapRec *priv)
}
}
}
-
+ remove_empties(priv);
#endif
+
#if 0
+ if (priv->draw_item_tail != 0)
+ {
+ if (priv->draw_item_tail->prev != 0)
+ {
+ di = priv->draw_item_tail;
+ while (di->prev != 0)
+ {
+ di_prev = di->prev;
+ while (di_prev != 0)
+ {
+ if ((di->type == RDI_TEXT) && (di_prev->type == RDI_IMGLY))
+ {
+ if (region_interect_at_all(di->reg, di_prev->reg))
+ {
+ di_prev->type = RDI_IMGLL;
+ }
+ }
+ di_prev = di_prev->prev;
+ }
+ di = di->prev;
+ }
+ }
+ }
+ remove_empties(priv);
+#endif
+#if 0
/* subtract regions */
if (priv->draw_item_tail != 0)
{
@@ -546,8 +754,11 @@ draw_item_pack(PixmapPtr pix, rdpPixmapRec *priv)
while (di_prev != 0)
{
- /* D = M - S */
- RegionSubtract(di_prev->reg, di_prev->reg, di->reg);
+ if (region_in_region(di_prev->reg, -1, di->reg))
+ {
+ /* empty region so this draw item will get removed below */
+ RegionEmpty(di_prev->reg);
+ }
di_prev = di_prev->prev;
}
}
@@ -556,30 +767,9 @@ draw_item_pack(PixmapPtr pix, rdpPixmapRec *priv)
}
}
}
-
+ remove_empties(priv);
#endif
-#if 1
- /* remove draw items with empty regions */
- di = priv->draw_item_head;
- di_prev = 0;
-
- while (di != 0)
- {
- if (!RegionNotEmpty(di->reg))
- {
- LLOGLN(10, ("draw_item_pack: removing empty item type %d", di->type));
- draw_item_remove(priv, di);
- di = di_prev == 0 ? priv->draw_item_head : di_prev->next;
- }
- else
- {
- di_prev = di;
- di = di->next;
- }
- }
-
-#endif
return 0;
}
@@ -693,6 +883,25 @@ draw_item_add_srcblt_region(rdpPixmapRec *priv, RegionPtr reg,
}
/******************************************************************************/
+int
+draw_item_add_text_region(rdpPixmapRec* priv, RegionPtr reg, int color,
+ int opcode, struct rdp_text* rtext)
+{
+ struct rdp_draw_item* di;
+
+ LLOGLN(10, ("draw_item_add_text_region:"));
+ di = (struct rdp_draw_item*)g_malloc(sizeof(struct rdp_draw_item), 1);
+ di->type = RDI_TEXT;
+ di->u.text.fg_color = color;
+ di->u.text.opcode = opcode;
+ di->u.text.rtext = rtext;
+ di->reg = RegionCreate(NullBox, 0);
+ RegionCopy(di->reg, reg);
+ draw_item_add(priv, di);
+ return 0;
+}
+
+/******************************************************************************/
PixmapPtr
rdpCreatePixmap(ScreenPtr pScreen, int width, int height, int depth,
unsigned usage_hint)
@@ -708,14 +917,14 @@ rdpCreatePixmap(ScreenPtr pScreen, int width, int height, int depth,
width, org_width, depth, g_rdpScreen.depth));
pScreen->CreatePixmap = g_rdpScreen.CreatePixmap;
rv = pScreen->CreatePixmap(pScreen, width, height, depth, usage_hint);
+ pScreen->CreatePixmap = rdpCreatePixmap;
priv = GETPIXPRIV(rv);
priv->rdpindex = -1;
- priv->con_number = g_con_number;
priv->kind_width = width;
pScreen->ModifyPixmapHeader(rv, org_width, 0, 0, 0, 0, 0);
- pScreen->CreatePixmap = rdpCreatePixmap;
- if (org_width == 0 && height == 0)
+ if ((org_width == 0) && (height == 0))
{
+ LLOGLN(10, ("rdpCreatePixmap: setting is_scratch"));
priv->is_scratch = 1;
}
return rv;
@@ -739,9 +948,11 @@ rdpDestroyPixmap(PixmapPtr pPixmap)
{
if (XRDP_IS_OS(priv))
{
- rdpup_remove_os_bitmap(priv->rdpindex);
- rdpup_delete_os_surface(priv->rdpindex);
- draw_item_remove_all(priv);
+ if (priv->rdpindex >= 0)
+ {
+ rdpup_remove_os_bitmap(priv->rdpindex);
+ rdpup_delete_os_surface(priv->rdpindex);
+ }
}
}
@@ -762,33 +973,41 @@ xrdp_is_os(PixmapPtr pix, rdpPixmapPtr priv)
int height;
struct image_data id;
- if (!XRDP_IS_OS(priv))
+ if (XRDP_IS_OS(priv))
+ {
+ /* update time stamp */
+ rdpup_update_os_use(priv->rdpindex);
+ }
+ else
{
width = pix->drawable.width;
height = pix->drawable.height;
if ((pix->usage_hint == 0) &&
(pix->drawable.depth >= g_rdpScreen.depth) &&
(width > 0) && (height > 0) && (priv->kind_width > 0) &&
- (priv->is_scratch == 0))
+ (priv->is_scratch == 0) && (priv->use_count >= 0))
{
- LLOGLN(10, ("%d %d", priv->kind_width, pix->drawable.width));
+ width = (width + 3) & ~3;
priv->rdpindex = rdpup_add_os_bitmap(pix, priv);
if (priv->rdpindex >= 0)
{
priv->status = 1;
- rdpup_create_os_surface(priv->rdpindex,
- priv->kind_width, height);
+ rdpup_create_os_surface(priv->rdpindex, width, height);
box.x1 = 0;
box.y1 = 0;
box.x2 = width;
box.y2 = height;
if (g_do_dirty_os)
{
+ LLOGLN(10, ("xrdp_is_os: priv->con_number %d g_con_number %d",
+ priv->con_number, g_con_number));
+ LLOGLN(10, ("xrdp_is_os: priv->use_count %d", priv->use_count));
if (priv->con_number != g_con_number)
{
+ LLOGLN(10, ("xrdp_is_os: queuing invalidating all"));
draw_item_remove_all(priv);
RegionInit(&reg1, &box, 0);
- draw_item_add_img_region(priv, &reg1, GXcopy, RDI_IMGLL, 16);
+ draw_item_add_img_region(priv, &reg1, GXcopy, RDI_IMGLY, 16);
RegionUninit(&reg1);
priv->is_dirty = 1;
priv->con_number = g_con_number;
@@ -804,11 +1023,18 @@ xrdp_is_os(PixmapPtr pix, rdpPixmapPtr priv)
rdpup_end_update();
rdpup_switch_os_surface(-1);
}
+ priv->use_count++;
return 1;
}
+ else
+ {
+ LLOGLN(10, ("xrdp_is_os: rdpup_add_os_bitmap failed"));
+ }
}
+ priv->use_count++;
return 0;
}
+ priv->use_count++;
return 1;
}
@@ -852,6 +1078,10 @@ rdpDestroyWindow(WindowPtr pWindow)
if (g_use_rail)
{
+#ifdef XRDP_WM_RDPUP
+ LLOGLN(10, (" rdpup_delete_window"));
+ rdpup_delete_window(pWindow, priv);
+#endif
}
return rv;
@@ -913,7 +1143,9 @@ rdpRealizeWindow(WindowPtr pWindow)
pWindow->drawable.x, pWindow->drawable.y,
pWindow->drawable.width, pWindow->drawable.height));
priv->status = 1;
+#ifdef XRDP_WM_RDPUP
rdpup_create_window(pWindow, priv);
+#endif
}
}
}
@@ -942,7 +1174,18 @@ rdpUnrealizeWindow(WindowPtr pWindow)
{
LLOGLN(10, ("rdpUnrealizeWindow:"));
priv->status = 0;
- rdpup_delete_window(pWindow, priv);
+ if (pWindow->overrideRedirect) {
+#ifdef XRDP_WM_RDPUP
+ /*
+ * Popups are unmapped by X server, so probably
+ * they will be mapped again. Thereby we should
+ * just hide those popups instead of destroying
+ * them.
+ */
+ LLOGLN(10, (" rdpup_show_window"));
+ rdpup_show_window(pWindow, priv, 0x0); /* 0x0 - do not show the window */
+#endif
+ }
}
}
@@ -1035,7 +1278,9 @@ rdpCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion)
BoxRec box2;
BoxPtr box3;
- LLOGLN(10, ("in rdpCopyWindow"));
+ LLOGLN(10, ("rdpCopyWindow:"));
+ LLOGLN(10, ("rdpCopyWindow: new x %d new y %d old x %d old y %d",
+ pWin->drawable.x, pWin->drawable.y, ptOldOrg.x, ptOldOrg.y));
RegionInit(&reg, NullBox, 0);
RegionCopy(&reg, pOldRegion);
RegionInit(&clip, NullBox, 0);
@@ -1047,18 +1292,28 @@ rdpCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion)
{
rdpup_check_dirty_screen(&g_screenPriv);
}
- rdpup_begin_update();
+
+ g_pScreen->CopyWindow = g_rdpScreen.CopyWindow;
+ g_pScreen->CopyWindow(pWin, ptOldOrg, pOldRegion);
+ g_pScreen->CopyWindow = rdpCopyWindow;
+
num_clip_rects = REGION_NUM_RECTS(&clip);
num_reg_rects = REGION_NUM_RECTS(&reg);
LLOGLN(10, ("rdpCopyWindow: num_clip_rects %d num_reg_rects %d",
num_clip_rects, num_reg_rects));
+ if ((num_clip_rects == 0) || (num_reg_rects == 0))
+ {
+ return;
+ }
+ rdpup_begin_update();
+
/* when there is a huge list of screen copies, just send as bitmap
firefox dragging test does this */
if ((num_clip_rects > 16) && (num_reg_rects > 16))
{
box3 = RegionExtents(&reg);
- rdpup_send_area(0, box3->x1, box3->y1,
+ rdpup_send_area(0, box3->x1 + dx, box3->y1 + dy,
box3->x2 - box3->x1,
box3->y2 - box3->y1);
}
@@ -1073,6 +1328,8 @@ rdpCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion)
for (j = 0; j < num_clip_rects; j++)
{
box1 = REGION_RECTS(&clip)[j];
+ LLOGLN(10, ("clip x %d y %d w %d h %d", box1.x1, box1.y1,
+ box1.x2 - box1.x1, box1.y2 - box1.y1));
rdpup_set_clip(box1.x1, box1.y1,
box1.x2 - box1.x1,
box1.y2 - box1.y1);
@@ -1080,6 +1337,8 @@ rdpCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion)
for (i = 0; i < num_reg_rects; i++)
{
box2 = REGION_RECTS(&reg)[i];
+ LLOGLN(10, ("reg x %d y %d w %d h %d", box2.x1, box2.y1,
+ box2.x2 - box2.x1, box2.y2 - box2.y1));
rdpup_screen_blt(box2.x1 + dx, box2.y1 + dy,
box2.x2 - box2.x1,
box2.y2 - box2.y1,
@@ -1092,6 +1351,8 @@ rdpCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion)
for (j = num_clip_rects - 1; j >= 0; j--)
{
box1 = REGION_RECTS(&clip)[j];
+ LLOGLN(10, ("clip x %d y %d w %d h %d", box1.x1, box1.y1,
+ box1.x2 - box1.x1, box1.y2 - box1.y1));
rdpup_set_clip(box1.x1, box1.y1,
box1.x2 - box1.x1,
box1.y2 - box1.y1);
@@ -1099,6 +1360,8 @@ rdpCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion)
for (i = num_reg_rects - 1; i >= 0; i--)
{
box2 = REGION_RECTS(&reg)[i];
+ LLOGLN(10, ("reg x %d y %d w %d h %d", box2.x1, box2.y1,
+ box2.x2 - box2.x1, box2.y2 - box2.y1));
rdpup_screen_blt(box2.x1 + dx, box2.y1 + dy,
box2.x2 - box2.x1,
box2.y2 - box2.y1,
@@ -1113,9 +1376,6 @@ rdpCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion)
RegionUninit(&reg);
RegionUninit(&clip);
- g_pScreen->CopyWindow = g_rdpScreen.CopyWindow;
- g_pScreen->CopyWindow(pWin, ptOldOrg, pOldRegion);
- g_pScreen->CopyWindow = rdpCopyWindow;
}
/******************************************************************************/
@@ -1153,7 +1413,7 @@ rdpClearToBackground(WindowPtr pWin, int x, int y, int w, int h,
if (g_do_dirty_ons)
{
- draw_item_add_img_region(&g_screenPriv, &reg, GXcopy, RDI_IMGLL, 16);
+ draw_item_add_img_region(&g_screenPriv, &reg, GXcopy, RDI_IMGLY, 16);
}
else
{
@@ -1191,7 +1451,7 @@ rdpRestoreAreas(WindowPtr pWin, RegionPtr prgnExposed)
if (g_do_dirty_ons)
{
- draw_item_add_img_region(&g_screenPriv, &reg, GXcopy, RDI_IMGLL, 16);
+ draw_item_add_img_region(&g_screenPriv, &reg, GXcopy, RDI_IMGLY, 16);
}
else
{
@@ -1274,196 +1534,3 @@ rdpSaveScreen(ScreenPtr pScreen, int on)
{
return 1;
}
-
-/******************************************************************************/
-/* it looks like all the antialias draws go through here */
-void
-rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
- INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst,
- INT16 yDst, CARD16 width, CARD16 height)
-{
- BoxRec box;
- PictureScreenPtr ps;
- RegionRec reg1;
- RegionRec reg2;
- DrawablePtr p;
- int dirty_type;
- int j;
- int num_clips;
- int post_process;
- int reset_surface;
- int got_id;
- WindowPtr pDstWnd;
- PixmapPtr pDstPixmap;
- rdpPixmapRec *pDstPriv;
- rdpPixmapRec *pDirtyPriv;
- struct image_data id;
-
- LLOGLN(10, ("rdpComposite:"));
- ps = GetPictureScreen(g_pScreen);
- ps->Composite = g_rdpScreen.Composite;
- ps->Composite(op, pSrc, pMask, pDst, xSrc, ySrc,
- xMask, yMask, xDst, yDst, width, height);
- ps->Composite = rdpComposite;
-
- p = pDst->pDrawable;
-
- dirty_type = 0;
- pDirtyPriv = 0;
- post_process = 0;
- reset_surface = 0;
- got_id = 0;
-
- if (p->type == DRAWABLE_PIXMAP)
- {
- pDstPixmap = (PixmapPtr)p;
- pDstPriv = GETPIXPRIV(pDstPixmap);
-
- if (xrdp_is_os(pDstPixmap, pDstPriv))
- {
- post_process = 1;
-
- if (g_do_dirty_os)
- {
- LLOGLN(10, ("rdpComposite: gettig dirty"));
- pDstPriv->is_dirty = 1;
- dirty_type = g_doing_font ? RDI_IMGLL : RDI_IMGLY;
- pDirtyPriv = pDstPriv;
-
- }
- else
- {
- rdpup_switch_os_surface(pDstPriv->rdpindex);
- reset_surface = 1;
- rdpup_get_pixmap_image_rect(pDstPixmap, &id);
- got_id = 1;
- LLOGLN(10, ("rdpComposite: offscreen"));
- }
- }
- }
- else
- {
- if (p->type == DRAWABLE_WINDOW)
- {
- pDstWnd = (WindowPtr)p;
-
- if (pDstWnd->viewable)
- {
- post_process = 1;
-
- if (g_do_dirty_ons)
- {
- LLOGLN(10, ("rdpComposite: gettig dirty"));
- g_screenPriv.is_dirty = 1;
- pDirtyPriv = &g_screenPriv;
- dirty_type = RDI_IMGLL;
- }
- else
- {
- rdpup_get_screen_image_rect(&id);
- got_id = 1;
- LLOGLN(10, ("rdpComposite: screen"));
- }
- }
- }
- }
-
- if (!post_process)
- {
- return;
- }
-
- if (pDst->pCompositeClip != 0)
- {
- box.x1 = p->x + xDst;
- box.y1 = p->y + yDst;
- box.x2 = box.x1 + width;
- box.y2 = box.y1 + height;
- RegionInit(&reg1, &box, 0);
- RegionInit(&reg2, NullBox, 0);
- RegionCopy(&reg2, pDst->pCompositeClip);
- RegionIntersect(&reg1, &reg1, &reg2);
-
- if (dirty_type != 0)
- {
- draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 0);
- }
- else if (got_id)
- {
- num_clips = REGION_NUM_RECTS(&reg1);
-
- if (num_clips > 0)
- {
- rdpup_begin_update();
-
- for (j = num_clips - 1; j >= 0; j--)
- {
- box = REGION_RECTS(&reg1)[j];
- rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
- }
-
- rdpup_end_update();
- }
- }
-
- RegionUninit(&reg1);
- RegionUninit(&reg2);
- }
- else
- {
- box.x1 = p->x + xDst;
- box.y1 = p->y + yDst;
- box.x2 = box.x1 + width;
- box.y2 = box.y1 + height;
-
- if (dirty_type != 0)
- {
- RegionInit(&reg1, &box, 0);
- draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 0);
- RegionUninit(&reg1);
- }
- else if (got_id)
- {
- rdpup_begin_update();
- rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
- rdpup_end_update();
- }
- }
-
- if (reset_surface)
- {
- rdpup_switch_os_surface(-1);
- }
-}
-
-/******************************************************************************/
-void
-rdpGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc, INT16 ySrc, int nlists, GlyphListPtr lists,
- GlyphPtr *glyphs)
-{
- PictureScreenPtr ps;
- int index;
-
- LLOGLN(10, ("rdpGlyphs:"));
- LLOGLN(10, ("rdpGlyphs: nlists %d len %d", nlists, lists->len));
- rdpup_set_hints(1, 1);
- g_doing_font = 1;
-
- for (index = 0; index < lists->len; index++)
- {
- LLOGLN(10, (" index %d size %d refcnt %d width %d height %d",
- index, (int)(glyphs[index]->size), (int)(glyphs[index]->refcnt),
- glyphs[index]->info.width, glyphs[index]->info.height));
- }
-
- ps = GetPictureScreen(g_pScreen);
- ps->Glyphs = g_rdpScreen.Glyphs;
- ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc,
- nlists, lists, glyphs);
- ps->Glyphs = rdpGlyphs;
- rdpup_set_hints(0, 1);
- g_doing_font = 0;
- LLOGLN(10, ("rdpGlyphs: out"));
-}
diff --git a/xorg/X11R7.6/rdp/rdpglyph.c b/xorg/X11R7.6/rdp/rdpglyph.c
new file mode 100644
index 00000000..cb895ae5
--- /dev/null
+++ b/xorg/X11R7.6/rdp/rdpglyph.c
@@ -0,0 +1,862 @@
+/*
+ Copyright 2012 Jay Sorg
+
+ Permission to use, copy, modify, distribute, and sell this software and its
+ documentation for any purpose is hereby granted without fee, provided that
+ the above copyright notice appear in all copies and that both that
+ copyright notice and this permission notice appear in supporting
+ documentation.
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ */
+
+/*
+ http://msdn.microsoft.com/en-us/library/cc241863(v=prot.20).aspx
+ 4.6.1 "d" Character
+ This topic has not yet been rated - Rate this topic
+ The following shows glyph image data (1 bpp format) for character
+ "d" extracted from a Cache Glyph (Revision 2) (section 2.2.2.2.1.2.6)
+ Secondary Drawing Order.
+
+ Glyph width = 5 pixels
+ Glyph height = 9 pixels
+ Glyph origin = (0, -9), marked with an "X" on the image grid
+ Bitmap = { 0x08, 0x08, 0x08, 0x78, 0x88, 0x88, 0x88, 0x88, 0x78 }
+
+ http://msdn.microsoft.com/en-us/library/cc241864(v=prot.20).aspx
+ 4.6.2 "p" Character
+ This topic has not yet been rated - Rate this topic
+ The following shows glyph image data (1 bpp format) for character
+ "p" extracted from a Cache Glyph (Revision 2) (section 2.2.2.2.1.2.6)
+ Secondary Drawing Order.
+
+ Glyph width = 5 pixels
+ Glyph height = 8 pixels
+ Glyph origin = (0, -6), marked with an "X" on the image grid
+ Bitmap = { 0xF0, 0x88, 0x88, 0x88, 0x88, 0xF0, 0x80, 0x80 }
+ */
+
+#include "rdp.h"
+#include "rdpdraw.h"
+#include "rdpglyph.h"
+
+extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */
+extern int g_do_dirty_os; /* in rdpmain.c */
+extern int g_do_alpha_glyphs; /* in rdpmain.c */
+extern int g_do_glyph_cache; /* in rdpmain.c */
+extern int g_doing_font; /* in rdpmain.c */
+extern ScreenPtr g_pScreen; /* in rdpmain.c */
+extern rdpScreenInfoRec g_rdpScreen; /* in rdpmain.c */
+
+
+#define LOG_LEVEL 1
+#define LLOG(_level, _args) \
+do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0)
+#define LLOGLN(_level, _args) \
+do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0)
+
+struct font_cache
+{
+ int offset;
+ int baseline;
+ int width;
+ int height;
+ int crc;
+ int stamp;
+};
+
+static struct font_cache g_font_cache[12][256];
+static int g_stamp = 0;
+
+/*****************************************************************************/
+static void
+set_mono_pixel(char* data, int x, int y, int width, int pixel)
+{
+ int start;
+ int shift;
+
+ width = (width + 7) / 8;
+ start = (y * width) + x / 8;
+ shift = x % 8;
+ if (pixel != 0)
+ {
+ data[start] = data[start] | (0x80 >> shift);
+ }
+ else
+ {
+ data[start] = data[start] & ~(0x80 >> shift);
+ }
+}
+
+/*****************************************************************************/
+static int
+lget_pixel(char* data, int x, int y, int depth, int stride_bytes)
+{
+ int start;
+ int shift;
+
+ if (depth == 1)
+ {
+ start = (y * stride_bytes) + x / 8;
+ shift = x % 8;
+ return (data[start] & (0x01 << shift)) ? 0xff : 0;
+ }
+ else if (depth == 8)
+ {
+ return data[y * stride_bytes + x];
+ }
+ return 0;
+}
+
+/******************************************************************************/
+static int
+glyph_get_data(ScreenPtr pScreen, GlyphPtr glyph, struct rdp_font_char* rfd)
+{
+ int i;
+ int j;
+ int src_xoff;
+ int src_yoff;
+ int src_stride_bytes;
+ int dst_stride_bytes;
+ int hh;
+ int ww;
+ int src_depth;
+ unsigned char pixel;
+ PicturePtr pPicture;
+ pixman_image_t *src;
+ uint32_t* pi32;
+ char* pi8;
+
+ pPicture = GlyphPicture(glyph)[pScreen->myNum];
+ if (pPicture == 0)
+ {
+ return 0;
+ }
+ src = image_from_pict(pPicture, FALSE, &src_xoff, &src_yoff);
+ if (src == 0)
+ {
+ return 0;
+ }
+
+ src_stride_bytes = pixman_image_get_stride(src);
+ if (g_do_alpha_glyphs)
+ {
+ dst_stride_bytes = (glyph->info.width + 3) & ~3;
+ rfd->bpp = 8;
+ }
+ else
+ {
+ dst_stride_bytes = (((glyph->info.width + 7) / 8) + 3) & ~3;
+ rfd->bpp = 1;
+ }
+ src_depth = pixman_image_get_depth(src);
+ ww = pixman_image_get_width(src);
+ hh = pixman_image_get_height(src);
+ if ((ww != glyph->info.width) || (hh != glyph->info.height) ||
+ ((src_depth != 1) && (src_depth != 8)))
+ {
+ LLOGLN(0, ("glyph_get_data: bad glyph"));
+ free_pixman_pict(pPicture, src);
+ return 0;
+ }
+ rfd->data_bytes = glyph->info.height * dst_stride_bytes;
+ rfd->data = (char*)g_malloc(rfd->data_bytes, 1);
+ rfd->offset = -glyph->info.x;
+ rfd->baseline = -glyph->info.y;
+ rfd->width = glyph->info.width;
+ rfd->height = glyph->info.height;
+ pi32 = pixman_image_get_data(src);
+ pi8 = (char*)pi32;
+ for (j = 0; j < rfd->height; j++)
+ {
+ for (i = 0; i < rfd->width; i++)
+ {
+ pixel = lget_pixel(pi8, i, j, src_depth, src_stride_bytes);
+ if (g_do_alpha_glyphs)
+ {
+ rfd->data[j * dst_stride_bytes + i] = pixel;
+ }
+ else
+ {
+ if (pixel > 0x7f)
+ {
+ set_mono_pixel(rfd->data, i, j, rfd->width, 1);
+ }
+ else
+ {
+ set_mono_pixel(rfd->data, i, j, rfd->width, 0);
+ }
+ }
+ }
+ }
+ free_pixman_pict(pPicture, src);
+ return 0;
+}
+
+/******************************************************************************/
+struct rdp_text*
+create_rdp_text(ScreenPtr pScreen, int nlists, GlyphListPtr lists,
+ GlyphPtr* glyphs)
+{
+ struct rdp_text* rv;
+ struct rdp_text* rtext;
+ struct rdp_text* last_rtext;
+ BoxRec box;
+ RegionRec reg1;
+ int n;
+ int lxoff;
+ int lyoff;
+ int count;
+ int lx;
+ int ly;
+ int font_index;
+ int max_height;
+ int min_height;
+ int force_new;
+ GlyphPtr glyph;
+ struct rdp_font_char* rfd;
+
+ LLOGLN(10, ("create_rdp_text: nlists %d", nlists));
+
+ max_height = 0;
+ min_height = 0x7fffffff;
+ lx = lists->xOff;
+ ly = lists->yOff;
+ lxoff = 0;
+ lyoff = 0;
+ force_new = 0;
+
+ rtext = (struct rdp_text*)g_malloc(sizeof(struct rdp_text), 1);
+ rtext->reg = RegionCreate(NullBox, 0);
+ rtext->flags = 3;
+ rtext->mixmode = 0;
+ rtext->x = lx;
+ rtext->y = ly;
+
+ rv = rtext;
+ last_rtext = rtext;
+
+ count = 0;
+ while (nlists--)
+ {
+ LLOGLN(10, ("lists->xOff %d lists->yOff %d", lists->xOff, lists->yOff));
+ if (count != 0)
+ {
+ lx += lists->xOff;
+ ly += lists->yOff;
+ force_new = 1;
+ }
+ count++;
+ n = lists->len;
+ lists++;
+ while (n--)
+ {
+ glyph = *glyphs++;
+ /* process glyph here */
+ if ((glyph->info.width > 0) && (glyph->info.height > 0))
+ {
+ if (force_new)
+ {
+ LLOGLN(10, ("create_rdp_text: too many chars"));
+ force_new = 0;
+ rtext = (struct rdp_text*)g_malloc(sizeof(struct rdp_text), 1);
+ rtext->reg = RegionCreate(NullBox, 0);
+ rtext->flags = 3;
+ rtext->mixmode = 0;
+ rtext->x = lx;
+ rtext->y = ly;
+ last_rtext->next = rtext;
+ last_rtext = rtext;
+ lxoff = 0;
+ lyoff = 0;
+ }
+ LLOGLN(10, ("x %d y %d width %d height %d xOff %d yOff %d "
+ "num_chars %d lxoff %d lyoff %d lx %d ly %d",
+ glyph->info.x, glyph->info.y,
+ glyph->info.width, glyph->info.height,
+ glyph->info.xOff, glyph->info.yOff, rtext->num_chars,
+ lxoff, lyoff, lx, ly));
+ rfd = (struct rdp_font_char*)g_malloc(sizeof(struct rdp_font_char), 1);
+ rtext->chars[rtext->num_chars] = rfd;
+ box.x1 = lx - glyph->info.x;
+ box.y1 = ly - glyph->info.y;
+ box.x2 = box.x1 + glyph->info.width;
+ box.y2 = box.y1 + glyph->info.height;
+ if (glyph->info.height > max_height)
+ {
+ max_height = glyph->info.height;
+ }
+ if (glyph->info.height < min_height)
+ {
+ min_height = glyph->info.height;
+ }
+ RegionInit(&reg1, &box, 0);
+ RegionUnion(rtext->reg, &reg1, rtext->reg);
+ RegionUninit(&reg1);
+
+ glyph_get_data(pScreen, glyph, rfd);
+
+ rfd->incby = lxoff;
+ lxoff = glyph->info.xOff;
+ lyoff = glyph->info.yOff;
+ rtext->num_chars++;
+ if (rtext->num_chars > 63)
+ {
+ force_new = 1;
+ }
+ }
+ else
+ {
+ lxoff += glyph->info.xOff;
+ lyoff += glyph->info.yOff;
+ }
+ lx += glyph->info.xOff;
+ ly += glyph->info.yOff;
+ }
+ }
+ if (max_height > 10)
+ {
+ font_index = 8;
+ }
+ else if (max_height < 7)
+ {
+ font_index = 6;
+ }
+ else
+ {
+ font_index = 7;
+ }
+ LLOGLN(10, ("create_rdp_text: min_height %d max_height %d font_index %d",
+ min_height, max_height, font_index));
+ rtext = rv;
+ while (rtext != 0)
+ {
+ rtext->font = font_index;
+ rtext = rtext->next;
+ }
+ return rv;
+}
+
+/******************************************************************************/
+int
+delete_rdp_text(struct rdp_text* rtext)
+{
+ int index;
+
+ if (rtext == 0)
+ {
+ return 0;
+ }
+ for (index = 0; index < rtext->num_chars; index++)
+ {
+ if (rtext->chars[index] != 0)
+ {
+ g_free(rtext->chars[index]->data);
+ g_free(rtext->chars[index]);
+ }
+ }
+ RegionDestroy(rtext->reg);
+ delete_rdp_text(rtext->next);
+ g_free(rtext);
+ return 0;
+}
+
+/******************************************************************************/
+static int
+get_color(PicturePtr pPicture)
+{
+ int src_xoff;
+ int src_yoff;
+ int rv;
+ uint32_t* pi32;
+ pixman_image_t *src;
+
+ src = image_from_pict(pPicture, FALSE, &src_xoff, &src_yoff);
+ if (src == 0)
+ {
+ return 0;
+ }
+ pi32 = pixman_image_get_data(src);
+ if (pi32 == 0)
+ {
+ return 0;
+ }
+ rv = *pi32;
+ LLOGLN(10, ("get_color: 0x%8.8x width %d height %d ", rv,
+ pixman_image_get_width(src),
+ pixman_image_get_height(src)));
+ free_pixman_pict(pPicture, src);
+ return rv;
+}
+
+/******************************************************************************/
+static int
+find_or_add_char(int font, struct rdp_font_char* rfd)
+{
+ int crc;
+ int index;
+ int char_index;
+ int oldest;
+
+ crc = get_crc(rfd->data, rfd->data_bytes);
+ LLOGLN(10, ("find_or_add_char: crc 0x%8.8x", crc));
+ char_index = 0;
+ oldest = 0x7fffffff;
+ for (index = 0; index < 250; index++)
+ {
+ if ((g_font_cache[font][index].crc == crc) &&
+ (g_font_cache[font][index].width == rfd->width) &&
+ (g_font_cache[font][index].height == rfd->height) &&
+ (g_font_cache[font][index].offset == rfd->offset) &&
+ (g_font_cache[font][index].baseline == rfd->baseline))
+ {
+ g_stamp++;
+ g_font_cache[font][index].stamp = g_stamp;
+ LLOGLN(10, ("find_or_add_char: found char at %d %d", font, index));
+ return index;
+ }
+ if (g_font_cache[font][index].stamp < oldest)
+ {
+ oldest = g_font_cache[font][index].stamp;
+ char_index = index;
+ }
+ }
+ g_stamp++;
+ g_font_cache[font][char_index].stamp = g_stamp;
+ g_font_cache[font][char_index].crc = crc;
+ g_font_cache[font][char_index].width = rfd->width;
+ g_font_cache[font][char_index].height = rfd->height;
+ g_font_cache[font][char_index].offset = rfd->offset;
+ g_font_cache[font][char_index].baseline = rfd->baseline;
+ LLOGLN(10, ("find_or_add_char: adding char at %d %d", font, char_index));
+ if (rfd->bpp == 8)
+ {
+ rdpup_add_char_alpha(font, char_index, rfd->offset, rfd->baseline,
+ rfd->width, rfd->height,
+ rfd->data, rfd->data_bytes);
+ }
+ else
+ {
+ rdpup_add_char(font, char_index, rfd->offset, rfd->baseline,
+ rfd->width, rfd->height,
+ rfd->data, rfd->data_bytes);
+ }
+ return char_index;
+}
+
+/******************************************************************************/
+int
+rdp_text_chars_to_data(struct rdp_text* rtext)
+{
+ int index;
+ int data_bytes;
+ int char_index;
+ struct rdp_font_char* rfd;
+
+ LLOGLN(10, ("rdp_text_chars_to_data: rtext->num_chars %d", rtext->num_chars));
+ data_bytes = 0;
+ for (index = 0; index < rtext->num_chars; index++)
+ {
+ rfd = rtext->chars[index];
+ if (rfd == 0)
+ {
+ LLOGLN(0, ("rdp_text_chars_to_data: error rfd is nil"));
+ continue;
+ }
+ char_index = find_or_add_char(rtext->font, rfd);
+ rtext->data[data_bytes] = char_index;
+ data_bytes++;
+ if (rfd->incby > 127)
+ {
+ rtext->data[data_bytes] = 0x80;
+ data_bytes++;
+ rtext->data[data_bytes] = (rfd->incby >> 0) & 0xff;
+ data_bytes++;
+ rtext->data[data_bytes] = (rfd->incby >> 8) & 0xff;
+ data_bytes++;
+ }
+ else
+ {
+ rtext->data[data_bytes] = rfd->incby;
+ data_bytes++;
+ }
+ }
+ rtext->data_bytes = data_bytes;
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ typedef struct _GlyphList {
+ INT16 xOff;
+ INT16 yOff;
+ CARD8 len;
+ PictFormatPtr format;
+ } GlyphListRec, *GlyphListPtr;
+ */
+/* see ghyphstr.h but the follow is not in there
+ typedef struct _XGlyphInfo {
+ unsigned short width;
+ unsigned short height;
+ short x;
+ short y;
+ short xOff;
+ short yOff;
+ } XGlyphInfo;
+ */
+static void
+rdpGlyphu(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int nlists, GlyphListPtr lists, GlyphPtr* glyphs,
+ BoxPtr extents)
+{
+ BoxRec box;
+ RegionRec reg1;
+ RegionRec reg2;
+ DrawablePtr p;
+ int dirty_type;
+ int j;
+ int num_clips;
+ int post_process;
+ int reset_surface;
+ int got_id;
+ int fg_color;
+ WindowPtr pDstWnd;
+ PixmapPtr pDstPixmap;
+ rdpPixmapRec* pDstPriv;
+ rdpPixmapRec* pDirtyPriv;
+ struct image_data id;
+ struct rdp_text* rtext;
+ struct rdp_text* trtext;
+
+ LLOGLN(10, ("rdpGlyphu: xSrc %d ySrc %d", xSrc, ySrc));
+
+ p = pDst->pDrawable;
+
+ dirty_type = 0;
+ pDirtyPriv = 0;
+ post_process = 0;
+ reset_surface = 0;
+ got_id = 0;
+ if (p->type == DRAWABLE_PIXMAP)
+ {
+ pDstPixmap = (PixmapPtr)p;
+ pDstPriv = GETPIXPRIV(pDstPixmap);
+ if (XRDP_IS_OS(pDstPriv))
+ {
+ rdpup_check_dirty(pDstPixmap, pDstPriv);
+ post_process = 1;
+ if (g_do_dirty_os)
+ {
+ LLOGLN(10, ("rdpGlyphu: gettig dirty"));
+ pDstPriv->is_dirty = 1;
+ dirty_type = RDI_IMGLL;
+ pDirtyPriv = pDstPriv;
+
+ }
+ else
+ {
+ rdpup_switch_os_surface(pDstPriv->rdpindex);
+ reset_surface = 1;
+ rdpup_get_pixmap_image_rect(pDstPixmap, &id);
+ got_id = 1;
+ LLOGLN(10, ("rdpGlyphu: offscreen"));
+ }
+ }
+ }
+ else
+ {
+ if (p->type == DRAWABLE_WINDOW)
+ {
+ pDstWnd = (WindowPtr)p;
+ if (pDstWnd->viewable)
+ {
+ post_process = 1;
+ rdpup_get_screen_image_rect(&id);
+ got_id = 1;
+ LLOGLN(10, ("rdpGlyphu: screen"));
+ }
+ }
+ }
+ if (!post_process)
+ {
+ return;
+ }
+
+ rtext = create_rdp_text(pDst->pDrawable->pScreen, nlists, lists, glyphs);
+ if (rtext == 0)
+ {
+ LLOGLN(0, ("rdpGlyphu: create_rdp_text failed"));
+ return;
+ }
+ fg_color = get_color(pSrc);
+
+ LLOGLN(10, ("rdpGlyphu: pDst->clientClipType %d pCompositeClip %p",
+ pDst->clientClipType, pDst->pCompositeClip));
+
+ if (pDst->pCompositeClip != 0)
+ {
+ box.x1 = p->x + extents->x1;
+ box.y1 = p->y + extents->y1;
+ box.x2 = p->x + extents->x2;
+ box.y2 = p->y + extents->y2;
+ RegionInit(&reg1, &box, 0);
+ RegionInit(&reg2, NullBox, 0);
+ RegionCopy(&reg2, pDst->pCompositeClip);
+ RegionIntersect(&reg1, &reg1, &reg2);
+ if (dirty_type != 0)
+ {
+ LLOGLN(10, ("1"));
+ draw_item_add_text_region(pDirtyPriv, &reg1, fg_color, GXcopy, rtext);
+ rtext = 0;
+ }
+ else if (got_id)
+ {
+ num_clips = REGION_NUM_RECTS(&reg1);
+ if (num_clips > 0)
+ {
+ LLOGLN(10, (" num_clips %d", num_clips));
+ rdpup_begin_update();
+ rdpup_set_fgcolor(fg_color);
+ trtext = rtext;
+ while (trtext != 0)
+ {
+ rdp_text_chars_to_data(trtext);
+ for (j = num_clips - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&reg1)[j];
+ LLOGLN(10, ("2"));
+ rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ LLOGLN(10, ("rdpGlyphu: rdpup_draw_text"));
+ box = RegionExtents(trtext->reg)[0];
+ rdpup_draw_text(trtext->font, trtext->flags, trtext->mixmode,
+ box.x1 + p->x, box.y1 + p->y,
+ box.x2 + p->x, box.y2 + p->y,
+ //box.x1 + p->x, box.y1 + p->y,
+ //box.x2 + p->x, box.y2 + p->y,
+ 0, 0, 0, 0,
+ trtext->x + p->x, trtext->y + p->y,
+ trtext->data, trtext->data_bytes);
+ }
+ trtext = trtext->next;
+ }
+ rdpup_reset_clip();
+ rdpup_end_update();
+ }
+ }
+ RegionUninit(&reg1);
+ RegionUninit(&reg2);
+ }
+ else
+ {
+ box.x1 = p->x + extents->x1;
+ box.y1 = p->y + extents->y1;
+ box.x2 = p->x + extents->x2;
+ box.y2 = p->y + extents->y2;
+ if (dirty_type != 0)
+ {
+ RegionInit(&reg1, &box, 0);
+ LLOGLN(10, ("3"));
+ draw_item_add_text_region(pDirtyPriv, &reg1, fg_color, GXcopy, rtext);
+ rtext = 0;
+ RegionUninit(&reg1);
+ }
+ else if (got_id)
+ {
+ rdpup_begin_update();
+ LLOGLN(10, ("4"));
+ rdpup_set_fgcolor(fg_color);
+ trtext = rtext;
+ while (trtext != 0)
+ {
+ LLOGLN(10, ("rdpGlyphu: rdpup_draw_text"));
+ rdp_text_chars_to_data(trtext);
+ box = RegionExtents(trtext->reg)[0];
+ rdpup_draw_text(trtext->font, trtext->flags, trtext->mixmode,
+ box.x1 + p->x, box.y1 + p->y,
+ box.x2 + p->x, box.y2 + p->y,
+ //box.x1 + p->x, box.y1 + p->y,
+ //box.x2 + p->x, box.y2 + p->y,
+ 0, 0, 0, 0,
+ trtext->x + p->x, trtext->y + p->y,
+ trtext->data, trtext->data_bytes);
+ trtext = trtext->next;
+ }
+ rdpup_end_update();
+ }
+ }
+ if (reset_surface)
+ {
+ rdpup_switch_os_surface(-1);
+ }
+ delete_rdp_text(rtext);
+}
+
+/******************************************************************************/
+static void
+GlyphExtents(int nlist, GlyphListPtr list, GlyphPtr* glyphs, BoxPtr extents)
+{
+ int x1;
+ int x2;
+ int y1;
+ int y2;
+ int n;
+ int x;
+ int y;
+ GlyphPtr glyph;
+
+ x = 0;
+ y = 0;
+ extents->x1 = MAXSHORT;
+ extents->x2 = MINSHORT;
+ extents->y1 = MAXSHORT;
+ extents->y2 = MINSHORT;
+ while (nlist--)
+ {
+ x += list->xOff;
+ y += list->yOff;
+ n = list->len;
+ list++;
+ while (n--)
+ {
+ glyph = *glyphs++;
+ x1 = x - glyph->info.x;
+ if (x1 < MINSHORT)
+ {
+ x1 = MINSHORT;
+ }
+ y1 = y - glyph->info.y;
+ if (y1 < MINSHORT)
+ {
+ y1 = MINSHORT;
+ }
+ x2 = x1 + glyph->info.width;
+ if (x2 > MAXSHORT)
+ {
+ x2 = MAXSHORT;
+ }
+ y2 = y1 + glyph->info.height;
+ if (y2 > MAXSHORT)
+ {
+ y2 = MAXSHORT;
+ }
+ if (x1 < extents->x1)
+ {
+ extents->x1 = x1;
+ }
+ if (x2 > extents->x2)
+ {
+ extents->x2 = x2;
+ }
+ if (y1 < extents->y1)
+ {
+ extents->y1 = y1;
+ }
+ if (y2 > extents->y2)
+ {
+ extents->y2 = y2;
+ }
+ x += glyph->info.xOff;
+ y += glyph->info.yOff;
+ }
+ }
+}
+
+/******************************************************************************/
+static void
+rdpGlypht(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int nlists, GlyphListPtr lists, GlyphPtr* glyphs)
+{
+ BoxRec extents;
+
+ GlyphExtents(nlists, lists, glyphs, &extents);
+ if ((extents.x2 <= extents.x1) || (extents.y2 <= extents.y1))
+ {
+ return;
+ }
+ rdpGlyphu(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlists, lists,
+ glyphs, &extents);
+}
+
+/******************************************************************************/
+/* make sure no glyph is too big */
+/* returns boolean */
+static int
+rdpGlyphCheck(int nlist, GlyphListPtr list, GlyphPtr* glyphs)
+{
+ int n;
+ GlyphPtr glyph;
+
+ while (nlist--)
+ {
+ n = list->len;
+ list++;
+ while (n--)
+ {
+ glyph = *glyphs++;
+ if ((glyph->info.width * glyph->info.height) > 8192)
+ {
+ LLOGLN(10, ("rdpGlyphCheck: too big"));
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+
+/******************************************************************************/
+void
+rdpGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc, INT16 ySrc, int nlists, GlyphListPtr lists,
+ GlyphPtr* glyphs)
+{
+ PictureScreenPtr ps;
+
+ LLOGLN(10, ("rdpGlyphs: op %d xSrc %d ySrc %d maskFormat %p",
+ op, xSrc, ySrc, maskFormat));
+
+ LLOGLN(10, ("rdpGlyphs: g_do_glyph_cache %d", g_do_glyph_cache));
+
+ if (g_do_glyph_cache && rdpGlyphCheck(nlists, lists, glyphs))
+ {
+ g_doing_font = 2;
+ rdpGlypht(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlists, lists, glyphs);
+ ps = GetPictureScreen(g_pScreen);
+ ps->Glyphs = g_rdpScreen.Glyphs;
+ ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc,
+ nlists, lists, glyphs);
+ ps->Glyphs = rdpGlyphs;
+ }
+ else
+ {
+ g_doing_font = 1;
+ rdpup_set_hints(1, 1);
+ ps = GetPictureScreen(g_pScreen);
+ ps->Glyphs = g_rdpScreen.Glyphs;
+ ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc,
+ nlists, lists, glyphs);
+ ps->Glyphs = rdpGlyphs;
+ rdpup_set_hints(0, 1);
+ }
+ g_doing_font = 0;
+ LLOGLN(10, ("rdpGlyphs: out"));
+}
+
+/******************************************************************************/
+int
+rdpGlyphInit(void)
+{
+ memset(&g_font_cache, 0, sizeof(g_font_cache));
+ return 0;
+}
diff --git a/xorg/X11R7.6/rdp/rdpglyph.h b/xorg/X11R7.6/rdp/rdpglyph.h
new file mode 100644
index 00000000..6907f9e7
--- /dev/null
+++ b/xorg/X11R7.6/rdp/rdpglyph.h
@@ -0,0 +1,64 @@
+/*
+Copyright 2012-2013 Jay Sorg
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+#ifndef __RDPGLYPH_H
+#define __RDPGLYPH_H
+
+struct rdp_font_char
+{
+ int offset; /* x */
+ int baseline; /* y */
+ int width; /* cx */
+ int height; /* cy */
+ int incby;
+ int bpp;
+ char* data;
+ int data_bytes;
+};
+
+struct rdp_text
+{
+ RegionPtr reg;
+ int font;
+ int x;
+ int y;
+ int flags;
+ int mixmode;
+ char data[256];
+ int data_bytes;
+ struct rdp_font_char* chars[256];
+ int num_chars;
+ struct rdp_text* next;
+};
+
+int
+delete_rdp_text(struct rdp_text* rtext);
+int
+rdp_text_chars_to_data(struct rdp_text* rtext);
+
+void
+rdpGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int nlists, GlyphListPtr lists, GlyphPtr* glyphs);
+int
+rdpGlyphInit(void);
+
+#endif
diff --git a/xorg/X11R7.6/rdp/rdpinput.c b/xorg/X11R7.6/rdp/rdpinput.c
index 39cd78dd..c8739ba0 100644
--- a/xorg/X11R7.6/rdp/rdpinput.c
+++ b/xorg/X11R7.6/rdp/rdpinput.c
@@ -44,6 +44,12 @@ keyboard and mouse stuff
#define DEBUG_OUT_INPUT(arg) ErrorF arg
#endif
+#define LOG_LEVEL 1
+#define LLOG(_level, _args) \
+ do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0)
+#define LLOGLN(_level, _args) \
+ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0)
+
extern ScreenPtr g_pScreen; /* in rdpmain.c */
extern DeviceIntPtr g_pointer; /* in rdpmain.c */
extern DeviceIntPtr g_keyboard; /* in rdpmain.c */
@@ -58,6 +64,13 @@ static int g_tab_down = 0;
/* this is toggled every time num lock key is released, not like the
above *_down vars */
static int g_scroll_lock_down = 0;
+static OsTimerPtr g_kbtimer = 0;
+
+static OsTimerPtr g_timer = 0;
+static int g_x = 0;
+static int g_y = 0;
+static int g_timer_schedualed = 0;
+static int g_delay_motion = 1; /* turn on or off */
#define MIN_KEY_CODE 8
#define MAX_KEY_CODE 255
@@ -315,10 +328,57 @@ rdpBell(int volume, DeviceIntPtr pDev, pointer ctrl, int cls)
}
/******************************************************************************/
+static CARD32
+rdpInDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg)
+{
+ //ErrorF("rdpInDeferredUpdateCallback:\n");
+
+ /* our keyboard device */
+ XkbSetRepeatKeys(g_keyboard, -1, AutoRepeatModeOff);
+ /* the main one for the server */
+ XkbSetRepeatKeys(inputInfo.keyboard, -1, AutoRepeatModeOff);
+
+ return 0;
+}
+
+/******************************************************************************/
void
rdpChangeKeyboardControl(DeviceIntPtr pDev, KeybdCtrl *ctrl)
{
+ XkbControlsPtr ctrls;
+
ErrorF("rdpChangeKeyboardControl:\n");
+ ctrls = 0;
+ if (pDev != 0)
+ {
+ if (pDev->key != 0)
+ {
+ if (pDev->key->xkbInfo != 0)
+ {
+ if (pDev->key->xkbInfo->desc != 0)
+ {
+ if (pDev->key->xkbInfo->desc->ctrls != 0)
+ {
+ ctrls = pDev->key->xkbInfo->desc->ctrls;
+ }
+ }
+ }
+ }
+ }
+ if (ctrls != 0)
+ {
+ if (ctrls->enabled_ctrls & XkbRepeatKeysMask)
+ {
+ //ErrorF("rdpChangeKeyboardControl: autoRepeat on\n");
+ /* schedual to turn off the autorepeat after 100 ms so any app
+ * polling it will be happy it's on */
+ g_kbtimer = TimerSet(g_kbtimer, 0, 100, rdpInDeferredUpdateCallback, 0);\
+ }
+ else
+ {
+ //ErrorF("rdpChangeKeyboardControl: autoRepeat off\n");
+ }
+ }
}
/******************************************************************************/
@@ -407,9 +467,9 @@ rdpMouseCtrl(DeviceIntPtr pDevice, PtrCtrl *pCtrl)
int
rdpMouseProc(DeviceIntPtr pDevice, int onoff)
{
- BYTE map[6];
+ BYTE map[8];
DevicePtr pDev;
- Atom btn_labels[6];
+ Atom btn_labels[8];
Atom axes_labels[2];
DEBUG_OUT_INPUT(("rdpMouseProc\n"));
@@ -425,17 +485,21 @@ rdpMouseProc(DeviceIntPtr pDevice, int onoff)
map[3] = 3;
map[4] = 4;
map[5] = 5;
+ map[6] = 6;
+ map[7] = 7;
btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
+ btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
+ btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
- InitPointerDeviceStruct(pDev, map, 5, btn_labels, rdpMouseCtrl,
+ InitPointerDeviceStruct(pDev, map, 7, btn_labels, rdpMouseCtrl,
GetMotionHistorySize(), 2, axes_labels);
break;
@@ -744,12 +808,13 @@ rdpEnqueueMotion(int x, int y)
EventListPtr rdp_events;
xEvent *pev;
+ LLOGLN(10, ("rdpEnqueueMotion: x %d y %d", x, y));
# if 0
if (x < 128)
{
rdpup_begin_update();
- rdpup_send_area(0, 0, 1024, 768);
+ rdpup_send_area(0, 0, 0, 1024, 768);
rdpup_end_update();
}
@@ -779,6 +844,7 @@ rdpEnqueueButton(int type, int buttons)
EventListPtr rdp_events;
xEvent *pev;
+ LLOGLN(10, ("rdpEnqueueButton:"));
i = GetEventList(&rdp_events);
n = GetPointerEvents(rdp_events, g_pointer, type, buttons, 0, 0, 0, 0);
@@ -809,35 +875,66 @@ rdpEnqueueKey(int type, int scancode)
}
/******************************************************************************/
+static CARD32
+rdpDeferredInputCallback(OsTimerPtr timer, CARD32 now, pointer arg)
+{
+ LLOGLN(10, ("rdpDeferredInputCallback:"));
+ g_timer_schedualed = 0;
+ rdpEnqueueMotion(g_x, g_y);
+ return 0;
+}
+
+/******************************************************************************/
void
PtrAddEvent(int buttonMask, int x, int y)
{
int i;
int type;
int buttons;
+ int send_now;
- rdpEnqueueMotion(x, y);
-
- for (i = 0; i < 5; i++)
+ LLOGLN(10, ("PtrAddEvent: x %d y %d", x, y));
+ send_now = (buttonMask ^ g_old_button_mask) || (g_delay_motion == 0);
+ LLOGLN(10, ("PtrAddEvent: send_now %d g_timer_schedualed %d",
+ send_now, g_timer_schedualed));
+ if (send_now)
{
- if ((buttonMask ^ g_old_button_mask) & (1 << i))
+ if (g_timer_schedualed)
{
- if (buttonMask & (1 << i))
- {
- type = ButtonPress;
- buttons = i + 1;
- rdpEnqueueButton(type, buttons);
- }
- else
+ g_timer_schedualed = 0;
+ TimerCancel(g_timer);
+ }
+ rdpEnqueueMotion(x, y);
+ for (i = 0; i < 5; i++)
+ {
+ if ((buttonMask ^ g_old_button_mask) & (1 << i))
{
- type = ButtonRelease;
- buttons = i + 1;
- rdpEnqueueButton(type, buttons);
+ if (buttonMask & (1 << i))
+ {
+ type = ButtonPress;
+ buttons = i + 1;
+ rdpEnqueueButton(type, buttons);
+ }
+ else
+ {
+ type = ButtonRelease;
+ buttons = i + 1;
+ rdpEnqueueButton(type, buttons);
+ }
}
}
+ g_old_button_mask = buttonMask;
+ }
+ else
+ {
+ g_x = x;
+ g_y = y;
+ if (!g_timer_schedualed)
+ {
+ g_timer_schedualed = 1;
+ g_timer = TimerSet(g_timer, 0, 60, rdpDeferredInputCallback, 0);
+ }
}
-
- g_old_button_mask = buttonMask;
}
/******************************************************************************/
@@ -916,9 +1013,13 @@ KbdAddEvent(int down, int param1, int param2, int param3, int param4)
if (x_scancode > 0)
{
+ /* left or right shift */
+ if ((rdp_scancode == 42) || (rdp_scancode == 54))
+ {
+ g_shift_down = down ? x_scancode : 0;
+ }
rdpEnqueueKey(type, x_scancode);
}
-
break;
case 56: /* left - right alt button */
@@ -932,6 +1033,7 @@ KbdAddEvent(int down, int param1, int param2, int param3, int param4)
x_scancode = 64; /* left alt button */
}
+ g_alt_down = down ? x_scancode : 0;
rdpEnqueueKey(type, x_scancode);
break;
@@ -1065,6 +1167,14 @@ KbdAddEvent(int down, int param1, int param2, int param3, int param4)
rdpEnqueueKey(type, 117);
break;
+ case 89: /* left meta */
+ rdpEnqueueKey(type, 156);
+ break;
+
+ case 90: /* right meta */
+ rdpEnqueueKey(type, 156);
+ break;
+
default:
x_scancode = rdp_scancode + MIN_KEY_CODE;
diff --git a/xorg/X11R7.6/rdp/rdpmain.c b/xorg/X11R7.6/rdp/rdpmain.c
index f1645cfe..1b924db7 100644
--- a/xorg/X11R7.6/rdp/rdpmain.c
+++ b/xorg/X11R7.6/rdp/rdpmain.c
@@ -24,6 +24,7 @@ Sets up the functions
#include "rdp.h"
#include "rdprandr.h"
+#include "rdpglyph.h"
#if 1
#define DEBUG_OUT(arg)
@@ -47,6 +48,9 @@ int g_can_do_pix_to_pix = 0;
int g_do_dirty_os = 1; /* delay remoting off screen bitmaps */
int g_do_dirty_ons = 1; /* delay remoting screen */
+int g_do_glyph_cache = 0; /* rdpup.c may set this */
+int g_do_alpha_glyphs = 1;
+int g_do_composite = 0; /* rdpup.c may set this */
Bool g_wrapWindow = 1;
Bool g_wrapPixmap = 1;
@@ -60,6 +64,7 @@ int g_use_rail = 0;
int g_con_number = 0; /* increments for each connection */
WindowPtr g_invalidate_window = 0;
+int g_doing_font = 0;
/* if true, use a unix domain socket instead of a tcp socket */
int g_use_uds = 0;
@@ -273,7 +278,8 @@ rdpScreenInit(int index, ScreenPtr pScreen, int argc, char **argv)
g_rdpScreen.sizeInBytes =
(g_rdpScreen.paddedWidthInBytes * g_rdpScreen.height);
ErrorF("buffer size %d\n", g_rdpScreen.sizeInBytes);
- g_rdpScreen.pfbMemory = (char *)g_malloc(2048 * 2048 * 4, 1);
+ g_rdpScreen.pfbMemory = (char *)g_malloc(g_rdpScreen.sizeInBytes, 1);
+ g_rdpScreen.sizeInBytesAlloc = g_rdpScreen.sizeInBytes;
}
if (g_rdpScreen.pfbMemory == 0)
@@ -397,6 +403,8 @@ rdpScreenInit(int index, ScreenPtr pScreen, int argc, char **argv)
if (ps)
{
+ g_rdpScreen.CreatePicture = ps->CreatePicture;
+ g_rdpScreen.DestroyPicture = ps->DestroyPicture;
g_rdpScreen.Composite = ps->Composite;
g_rdpScreen.Glyphs = ps->Glyphs;
@@ -410,6 +418,8 @@ rdpScreenInit(int index, ScreenPtr pScreen, int argc, char **argv)
if (ps)
{
+ ps->CreatePicture = rdpCreatePicture;
+ ps->DestroyPicture = rdpDestroyPicture;
ps->Composite = rdpComposite;
ps->Glyphs = rdpGlyphs;
}
@@ -529,6 +539,8 @@ rdpScreenInit(int index, ScreenPtr pScreen, int argc, char **argv)
}
+ rdpGlyphInit();
+
//rdpXvInit(pScreen);
ErrorF("rdpScreenInit: ret %d\n", ret);
diff --git a/xorg/X11R7.6/rdp/rdpmisc.c b/xorg/X11R7.6/rdp/rdpmisc.c
index dc54581a..eb5bedad 100644
--- a/xorg/X11R7.6/rdp/rdpmisc.c
+++ b/xorg/X11R7.6/rdp/rdpmisc.c
@@ -27,6 +27,59 @@ the rest
Bool noFontCacheExtension = 1;
+static int g_crc_seed = 0xffffffff;
+static int g_crc_table[256] =
+{
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+ 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+ 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+ 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+ 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+ 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+ 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+ 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+ 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+ 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+ 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+ 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+ 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+ 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+ 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+ 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+ 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+ 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+#define CRC_START(in_crc) (in_crc) = g_crc_seed
+#define CRC_PASS(in_pixel, in_crc) \
+ (in_crc) = g_crc_table[((in_crc) ^ (in_pixel)) & 0xff] ^ ((in_crc) >> 8)
+#define CRC_END(in_crc) (in_crc) = ((in_crc) ^ g_crc_seed)
+
/******************************************************************************/
/* print a time-stamped message to the log file (stderr). */
void
@@ -599,3 +652,19 @@ RegionAroundSegs(RegionPtr reg, xSegment *segs, int nseg)
index++;
}
}
+
+/******************************************************************************/
+int
+get_crc(char* data, int data_bytes)
+{
+ int crc;
+ int index;
+
+ CRC_START(crc);
+ for (index = 0; index < data_bytes; index++)
+ {
+ CRC_PASS(data[index], crc);
+ }
+ CRC_END(crc);
+ return crc;
+}
diff --git a/xorg/X11R7.6/rdp/rdprandr.c b/xorg/X11R7.6/rdp/rdprandr.c
index a767b1d8..8b3eb582 100644
--- a/xorg/X11R7.6/rdp/rdprandr.c
+++ b/xorg/X11R7.6/rdp/rdprandr.c
@@ -156,6 +156,13 @@ rdpRRScreenSetSize(ScreenPtr pScreen, CARD16 width, CARD16 height,
ErrorF(" resizing screenPixmap [%p] to %dx%d, currently at %dx%d\n",
(void *)screenPixmap, width, height,
screenPixmap->drawable.width, screenPixmap->drawable.height);
+ if (g_rdpScreen.sizeInBytes > g_rdpScreen.sizeInBytesAlloc)
+ {
+ g_free(g_rdpScreen.pfbMemory);
+ g_rdpScreen.pfbMemory = (char*)g_malloc(g_rdpScreen.sizeInBytes, 1);
+ g_rdpScreen.sizeInBytesAlloc = g_rdpScreen.sizeInBytes;
+ ErrorF("new buffer size %d\n", g_rdpScreen.sizeInBytes);
+ }
pScreen->ModifyPixmapHeader(screenPixmap, width, height,
g_rdpScreen.depth, g_rdpScreen.bitsPerPixel,
g_rdpScreen.paddedWidthInBytes,
diff --git a/xorg/X11R7.6/rdp/rdpup.c b/xorg/X11R7.6/rdp/rdpup.c
index 06c8bd73..52472121 100644
--- a/xorg/X11R7.6/rdp/rdpup.c
+++ b/xorg/X11R7.6/rdp/rdpup.c
@@ -21,6 +21,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "rdp.h"
#include "xrdp_rail.h"
+#include "rdpglyph.h"
+
+#include <signal.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/types.h>
#define LOG_LEVEL 1
#define LLOG(_level, _args) \
@@ -28,6 +34,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define LLOGLN(_level, _args) \
do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0)
+static int g_use_shmem = 1; /* turns on or off */
+static int g_shmemid = 0;
+static char *g_shmemptr = 0;
+static int g_shmem_lineBytes = 0;
+static RegionPtr g_shm_reg = 0;
+
+static int g_rect_id_ack = 0;
+static int g_rect_id = 0;
+
static int g_listen_sck = 0;
static int g_sck = 0;
static int g_sck_closed = 0;
@@ -53,8 +68,10 @@ extern ScreenPtr g_pScreen; /* from rdpmain.c */
extern int g_Bpp; /* from rdpmain.c */
extern int g_Bpp_mask; /* from rdpmain.c */
extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */
+extern int g_do_glyph_cache; /* from rdpmain.c */
extern int g_can_do_pix_to_pix; /* from rdpmain.c */
extern int g_use_rail; /* from rdpmain.c */
+extern int g_do_composite; /* from rdpmain.c */
/* true is to use unix domain socket */
extern int g_use_uds; /* in rdpmain.c */
@@ -71,9 +88,12 @@ struct rdpup_os_bitmap
int stamp;
};
+#define USE_MAX_OS_BYTES 1
+#define MAX_OS_BYTES (16 * 1024 * 1024)
static struct rdpup_os_bitmap *g_os_bitmaps = 0;
static int g_max_os_bitmaps = 0;
static int g_os_bitmap_stamp = 0;
+static int g_os_bitmap_alloc_size = 0;
static int g_pixmap_byte_total = 0;
static int g_pixmap_num_used = 0;
@@ -123,12 +143,70 @@ static int g_rdp_opcodes[16] =
0xff /* GXset 0xf 1 */
};
+static int g_do_kill_disconnected = 0; /* turn on or off */
+static OsTimerPtr g_dis_timer = 0;
+static int g_disconnect_scheduled = 0;
+static CARD32 g_disconnect_timeout_s = 60; /* 60 seconds */
+static CARD32 g_disconnect_time_ms = 0; /* time of disconnect in milliseconds */
+
+static int g_do_multimon = 0; /* multimon - turn on or off */
+
+/******************************************************************************/
+static CARD32
+rdpDeferredDisconnectCallback(OsTimerPtr timer, CARD32 now, pointer arg)
+{
+ CARD32 lnow_ms;
+
+ LLOGLN(10, ("rdpDeferredDisconnectCallback"));
+ if (g_connected)
+ {
+ /* this should not happen */
+ LLOGLN(0, ("rdpDeferredDisconnectCallback: connected"));
+ if (g_dis_timer != 0)
+ {
+ LLOGLN(0, ("rdpDeferredDisconnectCallback: canceling g_dis_timer"));
+ TimerCancel(g_dis_timer);
+ TimerFree(g_dis_timer);
+ g_dis_timer = 0;
+ }
+ g_disconnect_scheduled = 0;
+ return 0;
+ }
+ else
+ {
+ LLOGLN(10, ("rdpDeferredDisconnectCallback: not connected"));
+ }
+ lnow_ms = GetTimeInMillis();
+ if (lnow_ms - g_disconnect_time_ms > g_disconnect_timeout_s * 1000)
+ {
+ LLOGLN(0, ("rdpDeferredDisconnectCallback: exit X11rdp"));
+ kill(getpid(), SIGTERM);
+ return 0;
+ }
+ g_dis_timer = TimerSet(g_dis_timer, 0, 1000 * 10,
+ rdpDeferredDisconnectCallback, 0);
+ return 0;
+}
+
/*****************************************************************************/
static int
rdpup_disconnect(void)
{
int index;
+ LLOGLN(0, ("rdpup_disconnect:"));
+ if (g_do_kill_disconnected)
+ {
+ if (!g_disconnect_scheduled)
+ {
+ LLOGLN(0, ("rdpup_disconnect: starting g_dis_timer"));
+ g_dis_timer = TimerSet(g_dis_timer, 0, 1000 * 10,
+ rdpDeferredDisconnectCallback, 0);
+ g_disconnect_scheduled = 1;
+ }
+ g_disconnect_time_ms = GetTimeInMillis();
+ }
+
RemoveEnabledDevice(g_sck);
g_connected = 0;
g_tcp_close(g_sck);
@@ -151,15 +229,19 @@ rdpup_disconnect(void)
}
}
}
+ g_os_bitmap_alloc_size = 0;
g_max_os_bitmaps = 0;
g_free(g_os_bitmaps);
g_os_bitmaps = 0;
g_use_rail = 0;
+ g_do_glyph_cache = 0;
+ g_do_composite = 0;
return 0;
}
/*****************************************************************************/
+/* returns -1 on error */
int
rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv)
{
@@ -167,17 +249,32 @@ rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv)
int rv;
int oldest;
int oldest_index;
+ int this_bytes;
+ LLOGLN(10, ("rdpup_add_os_bitmap:"));
if (!g_connected)
{
+ LLOGLN(10, ("rdpup_add_os_bitmap: test error 1"));
return -1;
}
if (g_os_bitmaps == 0)
{
+ LLOGLN(10, ("rdpup_add_os_bitmap: test error 2"));
+ return -1;
+ }
+
+ this_bytes = pixmap->devKind * pixmap->drawable.height;
+ if (this_bytes > MAX_OS_BYTES)
+ {
+ LLOGLN(10, ("rdpup_add_os_bitmap: error, too big this_bytes %d "
+ "width %d height %d", this_bytes,
+ pixmap->drawable.height, pixmap->drawable.height));
return -1;
}
+ oldest = 0x7fffffff;
+ oldest_index = -1;
rv = -1;
index = 0;
@@ -194,42 +291,83 @@ rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv)
rv = index;
break;
}
-
+ else
+ {
+ if (g_os_bitmaps[index].stamp < oldest)
+ {
+ oldest = g_os_bitmaps[index].stamp;
+ oldest_index = index;
+ }
+ }
index++;
}
if (rv == -1)
{
+ if (oldest_index == -1)
+ {
+ LLOGLN(0, ("rdpup_add_os_bitmap: error"));
+ }
+ else
+ {
+ LLOGLN(10, ("rdpup_add_os_bitmap: too many pixmaps removing "
+ "oldest_index %d", oldest_index));
+ rdpup_remove_os_bitmap(oldest_index);
+ rdpup_delete_os_surface(oldest_index);
+ g_os_bitmaps[oldest_index].used = 1;
+ g_os_bitmaps[oldest_index].pixmap = pixmap;
+ g_os_bitmaps[oldest_index].priv = priv;
+ g_os_bitmaps[oldest_index].stamp = g_os_bitmap_stamp;
+ g_os_bitmap_stamp++;
+ g_pixmap_num_used++;
+ rv = oldest_index;
+ }
+ }
+
+ if (rv < 0)
+ {
+ LLOGLN(10, ("rdpup_add_os_bitmap: test error 3"));
+ return rv;
+ }
+
+ g_os_bitmap_alloc_size += this_bytes;
+ LLOGLN(10, ("rdpup_add_os_bitmap: this_bytes %d g_os_bitmap_alloc_size %d",
+ this_bytes, g_os_bitmap_alloc_size));
+#if USE_MAX_OS_BYTES
+ while (g_os_bitmap_alloc_size > MAX_OS_BYTES)
+ {
+ LLOGLN(10, ("rdpup_add_os_bitmap: must delete g_pixmap_num_used %d",
+ g_pixmap_num_used));
/* find oldest */
oldest = 0x7fffffff;
- oldest_index = 0;
+ oldest_index = -1;
index = 0;
-
while (index < g_max_os_bitmaps)
{
- if (g_os_bitmaps[index].stamp < oldest)
+ if (g_os_bitmaps[index].used && (g_os_bitmaps[index].stamp < oldest))
{
oldest = g_os_bitmaps[index].stamp;
oldest_index = index;
}
-
index++;
}
-
- LLOGLN(10, ("rdpup_add_os_bitmap: evicting old, oldest_index %d", oldest_index));
- /* evict old */
- g_os_bitmaps[oldest_index].priv->status = 0;
- g_os_bitmaps[oldest_index].priv->con_number = 0;
- /* set new */
- g_os_bitmaps[oldest_index].pixmap = pixmap;
- g_os_bitmaps[oldest_index].priv = priv;
- g_os_bitmaps[oldest_index].stamp = g_os_bitmap_stamp;
- g_os_bitmap_stamp++;
- rv = oldest_index;
+ if (oldest_index == -1)
+ {
+ LLOGLN(0, ("rdpup_add_os_bitmap: error 1"));
+ break;
+ }
+ if (oldest_index == rv)
+ {
+ LLOGLN(0, ("rdpup_add_os_bitmap: error 2"));
+ break;
+ }
+ rdpup_remove_os_bitmap(oldest_index);
+ rdpup_delete_os_surface(oldest_index);
}
-
+#endif
LLOGLN(10, ("rdpup_add_os_bitmap: new bitmap index %d", rv));
- LLOGLN(10, (" g_pixmap_num_used %d", g_pixmap_num_used));
+ LLOGLN(10, ("rdpup_add_os_bitmap: g_pixmap_num_used %d "
+ "g_os_bitmap_stamp 0x%8.8x", g_pixmap_num_used, g_os_bitmap_stamp));
return rv;
}
@@ -237,31 +375,84 @@ rdpup_add_os_bitmap(PixmapPtr pixmap, rdpPixmapPtr priv)
int
rdpup_remove_os_bitmap(int rdpindex)
{
+ PixmapPtr pixmap;
+ rdpPixmapPtr priv;
+ int this_bytes;
+
LLOGLN(10, ("rdpup_remove_os_bitmap: index %d stamp %d",
- rdpindex, g_os_bitmaps[rdpindex].stamp));
+ rdpindex, g_os_bitmaps[rdpindex].stamp));
if (g_os_bitmaps == 0)
{
+ LLOGLN(10, ("rdpup_remove_os_bitmap: test error 1"));
return 1;
}
if ((rdpindex < 0) && (rdpindex >= g_max_os_bitmaps))
{
+ LLOGLN(10, ("rdpup_remove_os_bitmap: test error 2"));
return 1;
}
if (g_os_bitmaps[rdpindex].used)
{
+ pixmap = g_os_bitmaps[rdpindex].pixmap;
+ priv = g_os_bitmaps[rdpindex].priv;
+ draw_item_remove_all(priv);
+ this_bytes = pixmap->devKind * pixmap->drawable.height;
+ g_os_bitmap_alloc_size -= this_bytes;
+ LLOGLN(10, ("rdpup_remove_os_bitmap: this_bytes %d "
+ "g_os_bitmap_alloc_size %d", this_bytes,
+ g_os_bitmap_alloc_size));
g_os_bitmaps[rdpindex].used = 0;
g_os_bitmaps[rdpindex].pixmap = 0;
g_os_bitmaps[rdpindex].priv = 0;
g_pixmap_num_used--;
+ priv->status = 0;
+ priv->con_number = 0;
+ priv->use_count = 0;
+ }
+ else
+ {
+ LLOGLN(0, ("rdpup_remove_os_bitmap: error"));
+ }
+
+ LLOGLN(10, ("rdpup_remove_os_bitmap: g_pixmap_num_used %d",
+ g_pixmap_num_used));
+ return 0;
+}
+
+/*****************************************************************************/
+int
+rdpup_update_os_use(int rdpindex)
+{
+ LLOGLN(10, ("rdpup_update_use: index %d stamp %d",
+ rdpindex, g_os_bitmaps[rdpindex].stamp));
+
+ if (g_os_bitmaps == 0)
+ {
+ return 1;
+ }
+
+ if ((rdpindex < 0) && (rdpindex >= g_max_os_bitmaps))
+ {
+ return 1;
+ }
+
+ if (g_os_bitmaps[rdpindex].used)
+ {
+ g_os_bitmaps[rdpindex].stamp = g_os_bitmap_stamp;
+ g_os_bitmap_stamp++;
+ }
+ else
+ {
+ LLOGLN(0, ("rdpup_update_use: error rdpindex %d", rdpindex));
}
- LLOGLN(10, (" g_pixmap_num_used %d", g_pixmap_num_used));
return 0;
}
+
/*****************************************************************************/
/* returns error */
static int
@@ -288,12 +479,14 @@ rdpup_send(char *data, int len)
}
else
{
+ LLOGLN(0, ("rdpup_send: g_tcp_send failed(returned -1)"));
rdpup_disconnect();
return 1;
}
}
else if (sent == 0)
{
+ LLOGLN(0, ("rdpup_send: g_tcp_send failed(returned zero)"));
rdpup_disconnect();
return 1;
}
@@ -344,6 +537,9 @@ rdpup_send_msg(struct stream *s)
static int
rdpup_send_pending(void)
{
+ int rv;
+
+ rv = 0;
if (g_connected && g_begin)
{
LLOGLN(10, ("end %d", g_count));
@@ -351,12 +547,16 @@ rdpup_send_pending(void)
out_uint16_le(g_out_s, 4);
g_count++;
s_mark_end(g_out_s);
- rdpup_send_msg(g_out_s);
+ if (rdpup_send_msg(g_out_s) != 0)
+ {
+ LLOGLN(0, ("rdpup_send_pending: rdpup_send_msg failed"));
+ rv = 1;
+ }
}
g_count = 0;
g_begin = 0;
- return 0;
+ return rv;
}
/******************************************************************************/
@@ -367,7 +567,14 @@ rdpDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg)
if (g_do_dirty_ons)
{
- rdpup_check_dirty_screen(&g_screenPriv);
+ if (g_rect_id == g_rect_id_ack)
+ {
+ rdpup_check_dirty_screen(&g_screenPriv);
+ }
+ else
+ {
+ LLOGLN(0, ("rdpDeferredUpdateCallback: skipping"));
+ }
}
else
{
@@ -413,12 +620,14 @@ rdpup_recv(char *data, int len)
}
else
{
+ LLOGLN(0, ("rdpup_recv: g_tcp_recv failed(returned -1)"));
rdpup_disconnect();
return 1;
}
}
else if (rcvd == 0)
{
+ LLOGLN(0, ("rdpup_recv: g_tcp_recv failed(returned 0)"));
rdpup_disconnect();
return 1;
}
@@ -466,6 +675,34 @@ rdpup_recv_msg(struct stream *s)
return rv;
}
+/*****************************************************************************/
+/* wait 'millis' milliseconds for the socket to be able to receive */
+/* returns boolean */
+static int
+sck_can_recv(int sck, int millis)
+{
+ fd_set rfds;
+ struct timeval time;
+ int rv;
+
+ time.tv_sec = millis / 1000;
+ time.tv_usec = (millis * 1000) % 1000000;
+ FD_ZERO(&rfds);
+
+ if (sck > 0)
+ {
+ FD_SET(((unsigned int)sck), &rfds);
+ rv = select(sck + 1, &rfds, 0, 0, &time);
+
+ if (rv > 0)
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
/******************************************************************************/
/*
this from miScreenInit
@@ -478,6 +715,7 @@ process_screen_size_msg(int width, int height, int bpp)
RRScreenSizePtr pSize;
int mmwidth;
int mmheight;
+ int bytes;
Bool ok;
LLOGLN(0, ("process_screen_size_msg: set width %d height %d bpp %d",
@@ -507,6 +745,28 @@ process_screen_size_msg(int width, int height, int bpp)
g_rdpScreen.rdp_Bpp_mask = 0xffffff;
}
+ if (g_use_shmem)
+ {
+ if (g_shmemptr != 0)
+ {
+ shmdt(g_shmemptr);
+ }
+ bytes = g_rdpScreen.rdp_width * g_rdpScreen.rdp_height *
+ g_rdpScreen.rdp_Bpp;
+ g_shmemid = shmget(IPC_PRIVATE, bytes, IPC_CREAT | 0777);
+ g_shmemptr = shmat(g_shmemid, 0, 0);
+ shmctl(g_shmemid, IPC_RMID, NULL);
+ LLOGLN(0, ("process_screen_size_msg: g_shmemid %d g_shmemptr %p",
+ g_shmemid, g_shmemptr));
+ g_shmem_lineBytes = g_rdpScreen.rdp_Bpp * g_rdpScreen.rdp_width;
+
+ if (g_shm_reg != 0)
+ {
+ RegionDestroy(g_shm_reg);
+ }
+ g_shm_reg = RegionCreate(NullBox, 0);
+ }
+
mmwidth = PixelToMM(width);
mmheight = PixelToMM(height);
@@ -631,6 +891,14 @@ rdpup_send_rail(void)
return 0;
}
+#define XR_BUTTON1 1
+#define XR_BUTTON2 2
+#define XR_BUTTON3 4
+#define XR_BUTTON4 8
+#define XR_BUTTON5 16
+#define XR_BUTTON6 32
+#define XR_BUTTON7 64
+
/******************************************************************************/
static int
rdpup_process_msg(struct stream *s)
@@ -643,6 +911,13 @@ rdpup_process_msg(struct stream *s)
int param4;
int bytes;
int i1;
+ int flags;
+ int x;
+ int y;
+ int cx;
+ int cy;
+ RegionRec reg;
+ BoxRec box;
in_uint16_le(s, msg_type);
@@ -672,44 +947,74 @@ rdpup_process_msg(struct stream *s)
g_cursor_y = l_bound_by(param2, 0, g_rdpScreen.height - 2);
PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
break;
- case 101:
- g_button_mask = g_button_mask & (~1);
+ case 101: /* left button up */
+ g_button_mask = g_button_mask & (~XR_BUTTON1);
+ PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
+ break;
+ case 102: /* left button down */
+ g_cursor_x = l_bound_by(param1, 0, g_rdpScreen.width - 2);
+ g_cursor_y = l_bound_by(param2, 0, g_rdpScreen.height - 2);
+ g_button_mask = g_button_mask | XR_BUTTON1;
+ PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
+ break;
+ case 103: /* right button up */
+ g_button_mask = g_button_mask & (~XR_BUTTON3);
PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
break;
- case 102:
- g_button_mask = g_button_mask | 1;
+ case 104: /* right button down */
+ g_cursor_x = l_bound_by(param1, 0, g_rdpScreen.width - 2);
+ g_cursor_y = l_bound_by(param2, 0, g_rdpScreen.height - 2);
+ g_button_mask = g_button_mask | XR_BUTTON3;
PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
break;
- case 103:
- g_button_mask = g_button_mask & (~4);
+ case 105: /* middle button down */
+ g_button_mask = g_button_mask & (~XR_BUTTON2);
PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
break;
- case 104:
- g_button_mask = g_button_mask | 4;
+ case 106: /* middle button up */
+ g_cursor_x = l_bound_by(param1, 0, g_rdpScreen.width - 2);
+ g_cursor_y = l_bound_by(param2, 0, g_rdpScreen.height - 2);
+ g_button_mask = g_button_mask | XR_BUTTON2;
PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
break;
- case 105:
- g_button_mask = g_button_mask & (~2);
+ case 107: /* button 4 up */
+ g_button_mask = g_button_mask & (~XR_BUTTON4);
PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
break;
- case 106:
- g_button_mask = g_button_mask | 2;
+ case 108: /* button 4 down */
+ g_cursor_x = l_bound_by(param1, 0, g_rdpScreen.width - 2);
+ g_cursor_y = l_bound_by(param2, 0, g_rdpScreen.height - 2);
+ g_button_mask = g_button_mask | XR_BUTTON4;
PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
break;
- case 107:
- g_button_mask = g_button_mask & (~8);
+ case 109: /* button 5 up */
+ g_button_mask = g_button_mask & (~XR_BUTTON5);
PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
break;
- case 108:
- g_button_mask = g_button_mask | 8;
+ case 110: /* button 5 down */
+ g_cursor_x = l_bound_by(param1, 0, g_rdpScreen.width - 2);
+ g_cursor_y = l_bound_by(param2, 0, g_rdpScreen.height - 2);
+ g_button_mask = g_button_mask | XR_BUTTON5;
+ PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
+ break;
+ case 111: /* button 6 up */
+ g_button_mask = g_button_mask & (~XR_BUTTON6);
PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
break;
- case 109:
- g_button_mask = g_button_mask & (~16);
+ case 112: /* button 6 down */
+ g_cursor_x = l_bound_by(param1, 0, g_rdpScreen.width - 2);
+ g_cursor_y = l_bound_by(param2, 0, g_rdpScreen.height - 2);
+ g_button_mask = g_button_mask | XR_BUTTON6;
PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
break;
- case 110:
- g_button_mask = g_button_mask | 16;
+ case 113: /* button 7 up */
+ g_button_mask = g_button_mask & (~XR_BUTTON7);
+ PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
+ break;
+ case 114: /* button 7 down */
+ g_cursor_x = l_bound_by(param1, 0, g_rdpScreen.width - 2);
+ g_cursor_y = l_bound_by(param2, 0, g_rdpScreen.height - 2);
+ g_button_mask = g_button_mask | XR_BUTTON7;
PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
break;
case 200:
@@ -760,8 +1065,28 @@ rdpup_process_msg(struct stream *s)
if (g_rdpScreen.client_info.rail_support_level > 0)
{
g_use_rail = 1;
+#ifdef XRDP_WM_RDPUP
rdpup_send_rail();
+#endif
+ }
+ if (g_rdpScreen.client_info.orders[0x1b]) /* 27 NEG_GLYPH_INDEX_INDEX */
+ {
+ LLOGLN(0, (" client supports glyph cache but server disabled"));
+ //g_do_glyph_cache = 1;
+ }
+ if (g_rdpScreen.client_info.order_flags_ex & 0x100)
+ {
+ g_do_composite = 1;
+ }
+ if (g_do_glyph_cache)
+ {
+ LLOGLN(0, (" using glyph cache"));
+ }
+ if (g_do_composite)
+ {
+ LLOGLN(0, (" using client composite"));
}
+ LLOGLN(10, ("order_flags_ex 0x%x", g_rdpScreen.client_info.order_flags_ex));
if (g_rdpScreen.client_info.offscreen_cache_entries == 2000)
{
LLOGLN(0, (" client can do offscreen to offscreen blits"));
@@ -780,7 +1105,43 @@ rdpup_process_msg(struct stream *s)
{
LLOGLN(0, (" client can not do new(color) cursor"));
}
+ if (g_rdpScreen.client_info.monitorCount > 0)
+ {
+ LLOGLN(0, (" client can do multimon"));
+ LLOGLN(0, (" client monitor data, monitorCount= %d", g_rdpScreen.client_info.monitorCount));
+ g_do_multimon = 1;
+ }
+ else
+ {
+ LLOGLN(0, (" client can not do multimon"));
+ g_do_multimon = 0;
+ }
}
+ else if (msg_type == 105)
+ {
+ LLOGLN(10, ("rdpup_process_msg: got msg 105"));
+ in_uint32_le(s, flags);
+ in_uint32_le(s, g_rect_id_ack);
+ in_uint32_le(s, x);
+ in_uint32_le(s, y);
+ in_uint32_le(s, cx);
+ in_uint32_le(s, cy);
+ LLOGLN(10, ("rdpup_process_msg: %d %d %d %d", x, y, cx ,cy));
+ LLOGLN(10, ("rdpup_process_msg: rect_id %d rect_id_ack %d", g_rect_id, g_rect_id_ack));
+
+ box.x1 = x;
+ box.y1 = y;
+ box.x2 = box.x1 + cx;
+ box.y2 = box.y1 + cy;
+
+ RegionInit(&reg, &box, 0);
+ LLOGLN(10, ("rdpup_process_msg: %d %d %d %d", box.x1, box.y1, box.x2, box.y2));
+ RegionSubtract(g_shm_reg, g_shm_reg, &reg);
+ RegionUninit(&reg);
+
+ }
+
+
else
{
rdpLog("unknown message type in rdpup_process_msg %d\n", msg_type);
@@ -799,6 +1160,10 @@ rdpup_get_screen_image_rect(struct image_data *id)
id->Bpp = g_rdpScreen.rdp_Bpp;
id->lineBytes = g_rdpScreen.paddedWidthInBytes;
id->pixels = g_rdpScreen.pfbMemory;
+ id->shmem_pixels = g_shmemptr;
+ id->shmem_id = g_shmemid;
+ id->shmem_offset = 0;
+ id->shmem_lineBytes = g_shmem_lineBytes;
}
/******************************************************************************/
@@ -811,6 +1176,10 @@ rdpup_get_pixmap_image_rect(PixmapPtr pPixmap, struct image_data *id)
id->Bpp = g_rdpScreen.rdp_Bpp;
id->lineBytes = pPixmap->devKind;
id->pixels = (char *)(pPixmap->devPrivate.ptr);
+ id->shmem_pixels = 0;
+ id->shmem_id = 0;
+ id->shmem_offset = 0;
+ id->shmem_lineBytes = 0;
}
/******************************************************************************/
@@ -818,6 +1187,7 @@ int
rdpup_init(void)
{
char text[256];
+ char *ptext;
int i;
if (!g_directory_exist("/tmp/.xrdp"))
@@ -902,6 +1272,39 @@ rdpup_init(void)
}
}
+ ptext = getenv("XRDP_SESMAN_MAX_IDLE_TIME");
+ if (ptext != 0)
+ {
+ }
+ ptext = getenv("XRDP_SESMAN_MAX_DISC_TIME");
+ if (ptext != 0)
+ {
+ i = atoi(ptext);
+ if (i > 0)
+ {
+ g_do_kill_disconnected = 1;
+ g_disconnect_timeout_s = atoi(ptext);
+ }
+ }
+ ptext = getenv("XRDP_SESMAN_KILL_DISCONNECTED");
+ if (ptext != 0)
+ {
+ i = atoi(ptext);
+ if (i != 0)
+ {
+ g_do_kill_disconnected = 1;
+ g_disconnect_timeout_s = 0;
+ }
+ }
+
+ if (g_do_kill_disconnected && (g_disconnect_timeout_s < 60))
+ {
+ g_disconnect_timeout_s = 60;
+ }
+
+ rdpLog("kill disconencted [%d] timeout [%d] sec\n", g_do_kill_disconnected,
+ g_disconnect_timeout_s);
+
return 1;
}
@@ -939,7 +1342,18 @@ rdpup_check(void)
g_sck_closed = 0;
g_begin = 0;
g_con_number++;
+ rdpGlyphInit();
AddEnabledDevice(g_sck);
+
+ if (g_dis_timer != 0)
+ {
+ LLOGLN(0, ("rdpup_check: canceling g_dis_timer"));
+ TimerCancel(g_dis_timer);
+ TimerFree(g_dis_timer);
+ g_dis_timer = 0;
+ }
+ g_disconnect_scheduled = 0;
+
}
}
@@ -1016,6 +1430,9 @@ rdpup_end_update(void)
int
rdpup_pre_check(int in_size)
{
+ int rv;
+
+ rv = 0;
if (!g_begin)
{
rdpup_begin_update();
@@ -1024,13 +1441,17 @@ rdpup_pre_check(int in_size)
if ((g_out_s->p - g_out_s->data) > (g_out_s->size - (in_size + 20)))
{
s_mark_end(g_out_s);
- rdpup_send_msg(g_out_s);
+ if (rdpup_send_msg(g_out_s) != 0)
+ {
+ LLOGLN(0, ("rdpup_pre_check: rdpup_send_msg failed"));
+ rv = 1;
+ }
g_count = 0;
init_stream(g_out_s, 0);
s_push_layer(g_out_s, iso_hdr, 8);
}
- return 0;
+ return rv;
}
/******************************************************************************/
@@ -1256,6 +1677,25 @@ convert_pixels(void *src, void *dst, int num_pixels)
/******************************************************************************/
int
+alpha_pixels(void* src, void* dst, int num_pixels)
+{
+ unsigned int* src32;
+ unsigned char* dst8;
+ int index;
+
+ src32 = (unsigned int*)src;
+ dst8 = (unsigned char*)dst;
+ for (index = 0; index < num_pixels; index++)
+ {
+ *dst8 = (*src32) >> 24;
+ dst8++;
+ src32++;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+int
rdpup_set_fgcolor(int fgcolor)
{
if (g_connected)
@@ -1427,6 +1867,26 @@ rdpup_create_os_surface(int rdpindex, int width, int height)
/******************************************************************************/
int
+rdpup_create_os_surface_bpp(int rdpindex, int width, int height, int bpp)
+{
+ LLOGLN(10, ("rdpup_create_os_surface_bpp:"));
+ if (g_connected)
+ {
+ LLOGLN(10, (" width %d height %d bpp %d", width, height, bpp));
+ rdpup_pre_check(13);
+ out_uint16_le(g_out_s, 31);
+ out_uint16_le(g_out_s, 13);
+ g_count++;
+ out_uint32_le(g_out_s, rdpindex);
+ out_uint16_le(g_out_s, width);
+ out_uint16_le(g_out_s, height);
+ out_uint8(g_out_s, bpp);
+ }
+ return 0;
+}
+
+/******************************************************************************/
+int
rdpup_switch_os_surface(int rdpindex)
{
LLOGLN(10, ("rdpup_switch_os_surface:"));
@@ -1559,11 +2019,13 @@ get_single_color(struct image_data *id, int x, int y, int w, int h)
}
/******************************************************************************/
-/* split the bitmap up into 64 x 64 pixel areas */
+/* split the bitmap up into 64 x 64 pixel areas
+ or send using shared memory */
void
rdpup_send_area(struct image_data *id, int x, int y, int w, int h)
{
char *s;
+ char *d;
int i;
int single_color;
int lx;
@@ -1571,7 +2033,10 @@ rdpup_send_area(struct image_data *id, int x, int y, int w, int h)
int lh;
int lw;
int size;
+ int safety;
struct image_data lid;
+ BoxRec box;
+ RegionRec reg;
LLOGLN(10, ("rdpup_send_area: id %p x %d y %d w %d h %d", id, x, y, w, h));
@@ -1628,9 +2093,76 @@ rdpup_send_area(struct image_data *id, int x, int y, int w, int h)
if (g_connected && g_begin)
{
LLOGLN(10, (" rdpup_send_area"));
- ly = y;
- while (ly < y + h)
+ if (id->shmem_pixels != 0)
+ {
+ LLOGLN(10, ("rdpup_send_area: using shmem"));
+ box.x1 = x;
+ box.y1 = y;
+ box.x2 = box.x1 + w;
+ box.y2 = box.y1 + h;
+ LLOGLN(10, ("rdpup_send_area: 1 x %d y %d w %d h %d", x, y, w, h));
+ safety = 0;
+ while (RegionContainsRect(g_shm_reg, &box))
+ {
+ /* instread of rdpup_end_update, call rdpup_send_pending */
+ rdpup_send_pending();
+ rdpup_begin_update();
+ safety++;
+ if (safety > 100)
+ {
+ LLOGLN(0, ("rdpup_send_area: shmem timeout"));
+ break;
+ }
+ if (sck_can_recv(g_sck, 100))
+ {
+ if (rdpup_recv_msg(g_in_s) == 0)
+ {
+ rdpup_process_msg(g_in_s);
+ }
+ }
+ }
+ s = id->pixels;
+ s += y * id->lineBytes;
+ s += x * g_Bpp;
+ d = id->shmem_pixels + id->shmem_offset;
+ d += y * id->shmem_lineBytes;
+ d += x * g_rdpScreen.rdp_Bpp;
+ ly = y;
+ while (ly < y + h)
+ {
+ convert_pixels(s, d, w);
+ s += id->lineBytes;
+ d += id->shmem_lineBytes;
+ ly += 1;
+ }
+ size = 36;
+ rdpup_pre_check(size);
+ out_uint16_le(g_out_s, 60);
+ out_uint16_le(g_out_s, size);
+ g_count++;
+ LLOGLN(10, ("rdpup_send_area: 2 x %d y %d w %d h %d", x, y, w, h));
+ out_uint16_le(g_out_s, x);
+ out_uint16_le(g_out_s, y);
+ out_uint16_le(g_out_s, w);
+ out_uint16_le(g_out_s, h);
+ out_uint32_le(g_out_s, 0);
+ g_rect_id++;
+ out_uint32_le(g_out_s, g_rect_id);
+ out_uint32_le(g_out_s, id->shmem_id);
+ out_uint32_le(g_out_s, id->shmem_offset);
+ out_uint16_le(g_out_s, id->width);
+ out_uint16_le(g_out_s, id->height);
+ out_uint16_le(g_out_s, x);
+ out_uint16_le(g_out_s, y);
+ RegionInit(&reg, &box, 0);
+ RegionUnion(g_shm_reg, g_shm_reg, &reg);
+ RegionUninit(&reg);
+ return;
+ }
+
+ ly = y;
+ while ((ly < y + h) && g_connected)
{
lx = x;
@@ -1682,6 +2214,103 @@ rdpup_send_area(struct image_data *id, int x, int y, int w, int h)
}
/******************************************************************************/
+/* split the bitmap up into 64 x 64 pixel areas */
+void
+rdpup_send_alpha_area(struct image_data* id, int x, int y, int w, int h)
+{
+ char* s;
+ int i;
+ int lx;
+ int ly;
+ int lh;
+ int lw;
+ int size;
+ struct image_data lid;
+
+ LLOGLN(10, ("rdpup_send_alpha_area: id %p x %d y %d w %d h %d",
+ id, x, y, w, h));
+ if (id == 0)
+ {
+ rdpup_get_screen_image_rect(&lid);
+ id = &lid;
+ }
+
+ if (x >= id->width)
+ {
+ return;
+ }
+ if (y >= id->height)
+ {
+ return;
+ }
+ if (x < 0)
+ {
+ w += x;
+ x = 0;
+ }
+ if (y < 0)
+ {
+ h += y;
+ y = 0;
+ }
+ if (w <= 0)
+ {
+ return;
+ }
+ if (h <= 0)
+ {
+ return;
+ }
+ if (x + w > id->width)
+ {
+ w = id->width - x;
+ }
+ if (y + h > id->height)
+ {
+ h = id->height - y;
+ }
+ LLOGLN(10, ("%d", w * h));
+ if (g_connected && g_begin)
+ {
+ LLOGLN(10, (" rdpup_send_area"));
+ ly = y;
+ while ((ly < y + h) && g_connected)
+ {
+ lx = x;
+ while ((lx < x + w) && g_connected)
+ {
+ lw = MIN(64, (x + w) - lx);
+ lh = MIN(64, (y + h) - ly);
+ size = lw * lh + 25;
+ rdpup_pre_check(size);
+ out_uint16_le(g_out_s, 32); /* server_paint_rect_bpp */
+ out_uint16_le(g_out_s, size);
+ g_count++;
+ out_uint16_le(g_out_s, lx);
+ out_uint16_le(g_out_s, ly);
+ out_uint16_le(g_out_s, lw);
+ out_uint16_le(g_out_s, lh);
+ out_uint32_le(g_out_s, lw * lh);
+ for (i = 0; i < lh; i++)
+ {
+ s = (id->pixels +
+ ((ly + i) * id->lineBytes) + (lx * g_Bpp));
+ alpha_pixels(s, g_out_s->p, lw);
+ g_out_s->p += lw;
+ }
+ out_uint16_le(g_out_s, lw);
+ out_uint16_le(g_out_s, lh);
+ out_uint16_le(g_out_s, 0);
+ out_uint16_le(g_out_s, 0);
+ out_uint8(g_out_s, 8);
+ lx += 64;
+ }
+ ly += 64;
+ }
+ }
+}
+
+/******************************************************************************/
void
rdpup_paint_rect_os(int x, int y, int cx, int cy,
int rdpindex, int srcx, int srcy)
@@ -1772,7 +2401,7 @@ rdpup_create_window(WindowPtr pWindow, rdpWindowRec *priv)
out_uint32_le(g_out_s, style); /* style */
out_uint32_le(g_out_s, ext_style); /* extended_style */
flags |= WINDOW_ORDER_FIELD_STYLE;
- out_uint32_le(g_out_s, 0); /* show_state */
+ out_uint32_le(g_out_s, 0x05); /* show_state */
flags |= WINDOW_ORDER_FIELD_SHOW;
out_uint16_le(g_out_s, title_bytes); /* title_info */
out_uint8a(g_out_s, title, title_bytes);
@@ -1843,6 +2472,27 @@ rdpup_delete_window(WindowPtr pWindow, rdpWindowRec *priv)
}
/******************************************************************************/
+void
+rdpup_show_window(WindowPtr pWindow, rdpWindowRec* priv, int showState)
+{
+ LLOGLN(10, ("rdpup_show_window: id 0x%8.8x state 0x%x", pWindow->drawable.id,
+ showState));
+ if (g_connected)
+ {
+ int flags = WINDOW_ORDER_TYPE_WINDOW;
+
+ rdpup_pre_check(16);
+ out_uint16_le(g_out_s, 27);
+ out_uint16_le(g_out_s, 16);
+ g_count++;
+ out_uint32_le(g_out_s, pWindow->drawable.id);
+ flags |= WINDOW_ORDER_FIELD_SHOW;
+ out_uint32_le(g_out_s, flags);
+ out_uint32_le(g_out_s, showState);
+ }
+}
+
+/******************************************************************************/
int
rdpup_check_dirty(PixmapPtr pDirtyPixmap, rdpPixmapRec *pDirtyPriv)
{
@@ -1854,6 +2504,8 @@ rdpup_check_dirty(PixmapPtr pDirtyPixmap, rdpPixmapRec *pDirtyPriv)
xSegment *seg;
struct image_data id;
struct rdp_draw_item *di;
+ struct rdp_text* rtext;
+ struct rdp_text* trtext;
if (pDirtyPriv == 0)
{
@@ -1865,10 +2517,6 @@ rdpup_check_dirty(PixmapPtr pDirtyPixmap, rdpPixmapRec *pDirtyPriv)
return 0;
}
- /* update use time / count */
- g_os_bitmaps[pDirtyPriv->rdpindex].stamp = g_os_bitmap_stamp;
- g_os_bitmap_stamp++;
-
LLOGLN(10, ("rdpup_check_dirty: got dirty"));
rdpup_switch_os_surface(pDirtyPriv->rdpindex);
rdpup_get_pixmap_image_rect(pDirtyPixmap, &id);
@@ -1960,6 +2608,37 @@ rdpup_check_dirty(PixmapPtr pDirtyPixmap, rdpPixmapRec *pDirtyPriv)
case RDI_SCRBLT:
LLOGLN(10, (" RDI_SCRBLT"));
break;
+ case RDI_TEXT:
+ LLOGLN(10, (" RDI_TEXT"));
+ num_clips = REGION_NUM_RECTS(di->reg);
+ if (num_clips > 0)
+ {
+ LLOGLN(10, (" num_clips %d", num_clips));
+ rdpup_set_fgcolor(di->u.text.fg_color);
+ rdpup_set_opcode(di->u.text.opcode);
+ rtext = di->u.text.rtext;
+ trtext = rtext;
+ while (trtext != 0)
+ {
+ rdp_text_chars_to_data(trtext);
+ for (clip_index = num_clips - 1; clip_index >= 0; clip_index--)
+ {
+ box = REGION_RECTS(di->reg)[clip_index];
+ rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ LLOGLN(10, (" %d %d %d %d", box.x1, box.y1, box.x2, box.y2));
+ box = RegionExtents(trtext->reg)[0];
+ rdpup_draw_text(trtext->font, trtext->flags, trtext->mixmode,
+ box.x1, box.y1, box.x2, box.y2,
+ //box.x1, box.y1, box.x2, box.y2,
+ 0, 0, 0, 0,
+ trtext->x, trtext->y, trtext->data, trtext->data_bytes);
+ }
+ trtext = trtext->next;
+ }
+ }
+ rdpup_reset_clip();
+ rdpup_set_opcode(GXcopy);
+ break;
}
di = di->next;
@@ -2030,8 +2709,8 @@ rdpup_check_dirty_screen(rdpPixmapRec *pDirtyPriv)
for (index = 0; index < count; index++)
{
box = REGION_RECTS(di->reg)[index];
- LLOGLN(10, (" RDI_IMGLL %d %d %d %d", box.x1, box.y1,
- box.x2, box.y2));
+ LLOGLN(10, (" RDI_IMGLL x %d y %d w %d h %d", box.x1, box.y1,
+ box.x2 - box.x1, box.y2 - box.y1));
rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1,
box.y2 - box.y1);
}
@@ -2095,3 +2774,171 @@ rdpup_check_dirty_screen(rdpPixmapRec *pDirtyPriv)
pDirtyPriv->is_dirty = 0;
return 0;
}
+
+/******************************************************************************/
+int
+rdpup_check_alpha_dirty(PixmapPtr pDirtyPixmap, rdpPixmapRec* pDirtyPriv)
+{
+ struct image_data id;
+
+ LLOGLN(10, ("rdpup_check_alpha_dirty: width %d height %d",
+ pDirtyPixmap->drawable.width, pDirtyPixmap->drawable.height));
+ if (pDirtyPriv == 0)
+ {
+ return 0;
+ }
+ LLOGLN(10, ("rdpup_check_alpha_dirty: is_alpha_dirty_not %d",
+ pDirtyPriv->is_alpha_dirty_not));
+ if (pDirtyPriv->is_alpha_dirty_not)
+ {
+ return 0;
+ }
+ pDirtyPriv->is_alpha_dirty_not = 1;
+ rdpup_switch_os_surface(pDirtyPriv->rdpindex);
+ rdpup_get_pixmap_image_rect(pDirtyPixmap, &id);
+ rdpup_begin_update();
+ rdpup_send_alpha_area(&id, 0, 0, pDirtyPixmap->drawable.width,
+ pDirtyPixmap->drawable.height);
+ rdpup_end_update();
+ rdpup_switch_os_surface(-1);
+ return 0;
+}
+
+/******************************************************************************/
+int
+rdpup_add_char(int font, int charactor, short x, short y, int cx, int cy,
+ char* bmpdata, int bmpdata_bytes)
+{
+ if (g_connected)
+ {
+ LLOGLN(10, (" rdpup_add_char"));
+ rdpup_pre_check(18 + bmpdata_bytes);
+ out_uint16_le(g_out_s, 28); /* add char */
+ out_uint16_le(g_out_s, 18 + bmpdata_bytes); /* size */
+ g_count++;
+ out_uint16_le(g_out_s, font);
+ out_uint16_le(g_out_s, charactor);
+ out_uint16_le(g_out_s, x);
+ out_uint16_le(g_out_s, y);
+ out_uint16_le(g_out_s, cx);
+ out_uint16_le(g_out_s, cy);
+ out_uint16_le(g_out_s, bmpdata_bytes);
+ out_uint8a(g_out_s, bmpdata, bmpdata_bytes);
+ }
+ return 0;
+}
+
+/******************************************************************************/
+int
+rdpup_add_char_alpha(int font, int charactor, short x, short y, int cx, int cy,
+ char* bmpdata, int bmpdata_bytes)
+{
+ if (g_connected)
+ {
+ LLOGLN(10, (" rdpup_add_char_alpha"));
+ rdpup_pre_check(18 + bmpdata_bytes);
+ out_uint16_le(g_out_s, 29); /* add char alpha */
+ out_uint16_le(g_out_s, 18 + bmpdata_bytes); /* size */
+ g_count++;
+ out_uint16_le(g_out_s, font);
+ out_uint16_le(g_out_s, charactor);
+ out_uint16_le(g_out_s, x);
+ out_uint16_le(g_out_s, y);
+ out_uint16_le(g_out_s, cx);
+ out_uint16_le(g_out_s, cy);
+ out_uint16_le(g_out_s, bmpdata_bytes);
+ out_uint8a(g_out_s, bmpdata, bmpdata_bytes);
+ }
+ return 0;
+}
+
+/******************************************************************************/
+int
+rdpup_draw_text(int font, int flags, int mixmode,
+ short clip_left, short clip_top,
+ short clip_right, short clip_bottom,
+ short box_left, short box_top,
+ short box_right, short box_bottom, short x, short y,
+ char* data, int data_bytes)
+{
+ if (g_connected)
+ {
+ LLOGLN(10, (" rdpup_draw_text"));
+ rdpup_pre_check(32 + data_bytes);
+ out_uint16_le(g_out_s, 30); /* draw text */
+ out_uint16_le(g_out_s, 32 + data_bytes); /* size */
+ g_count++;
+ out_uint16_le(g_out_s, font);
+ out_uint16_le(g_out_s, flags);
+ out_uint16_le(g_out_s, mixmode);
+ out_uint16_le(g_out_s, clip_left);
+ out_uint16_le(g_out_s, clip_top);
+ out_uint16_le(g_out_s, clip_right);
+ out_uint16_le(g_out_s, clip_bottom);
+ out_uint16_le(g_out_s, box_left);
+ out_uint16_le(g_out_s, box_top);
+ out_uint16_le(g_out_s, box_right);
+ out_uint16_le(g_out_s, box_bottom);
+ out_uint16_le(g_out_s, x);
+ out_uint16_le(g_out_s, y);
+ out_uint16_le(g_out_s, data_bytes);
+ out_uint8a(g_out_s, data, data_bytes);
+ }
+ return 0;
+}
+
+/******************************************************************************/
+int
+rdpup_composite(short srcidx, int srcformat, short srcwidth, CARD8 srcrepeat,
+ PictTransform* srctransform, CARD8 mskflags,
+ short mskidx, int mskformat, short mskwidth, CARD8 mskrepeat,
+ CARD8 op, short srcx, short srcy, short mskx, short msky,
+ short dstx, short dsty, short width, short height,
+ int dstformat)
+{
+ if (g_connected)
+ {
+ LLOGLN(10, (" rdpup_composite"));
+ rdpup_pre_check(84);
+ out_uint16_le(g_out_s, 33);
+ out_uint16_le(g_out_s, 84); /* size */
+ g_count++;
+ out_uint16_le(g_out_s, srcidx);
+ out_uint32_le(g_out_s, srcformat);
+ out_uint16_le(g_out_s, srcwidth);
+ out_uint8(g_out_s, srcrepeat);
+ if (srctransform == 0)
+ {
+ out_uint8s(g_out_s, 10 * 4);
+ }
+ else
+ {
+ out_uint32_le(g_out_s, 1);
+ out_uint32_le(g_out_s, srctransform->matrix[0][0]);
+ out_uint32_le(g_out_s, srctransform->matrix[0][1]);
+ out_uint32_le(g_out_s, srctransform->matrix[0][2]);
+ out_uint32_le(g_out_s, srctransform->matrix[1][0]);
+ out_uint32_le(g_out_s, srctransform->matrix[1][1]);
+ out_uint32_le(g_out_s, srctransform->matrix[1][2]);
+ out_uint32_le(g_out_s, srctransform->matrix[2][0]);
+ out_uint32_le(g_out_s, srctransform->matrix[2][1]);
+ out_uint32_le(g_out_s, srctransform->matrix[2][2]);
+ }
+ out_uint8(g_out_s, mskflags);
+ out_uint16_le(g_out_s, mskidx);
+ out_uint32_le(g_out_s, mskformat);
+ out_uint16_le(g_out_s, mskwidth);
+ out_uint8(g_out_s, mskrepeat);
+ out_uint8(g_out_s, op);
+ out_uint16_le(g_out_s, srcx);
+ out_uint16_le(g_out_s, srcy);
+ out_uint16_le(g_out_s, mskx);
+ out_uint16_le(g_out_s, msky);
+ out_uint16_le(g_out_s, dstx);
+ out_uint16_le(g_out_s, dsty);
+ out_uint16_le(g_out_s, width);
+ out_uint16_le(g_out_s, height);
+ out_uint32_le(g_out_s, dstformat);
+ }
+ return 0;
+}
diff --git a/xrdp/Makefile.am b/xrdp/Makefile.am
index ac3b7fe0..83d04a6c 100644
--- a/xrdp/Makefile.am
+++ b/xrdp/Makefile.am
@@ -1,11 +1,20 @@
EXTRA_DIST = xrdp.ini ad24b.bmp ad256.bmp xrdp24b.bmp xrdp256.bmp sans-10.fv1 cursor0.cur cursor1.cur xrdp.h xrdp_types.h
+EXTRA_INCLUDES =
+EXTRA_LIBS =
+EXTRA_FLAGS =
+
if XRDP_DEBUG
EXTRA_DEFINES = -DXRDP_DEBUG
else
EXTRA_DEFINES = -DXRDP_NODEBUG
endif
+if GOT_PREFIX
+EXTRA_INCLUDES += -I$(prefix)/include
+EXTRA_FLAGS += -L$(prefix)/lib -Wl,-rpath -Wl,$(prefix)/lib
+endif
+
AM_CFLAGS = \
-DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \
-DXRDP_SBIN_PATH=\"${sbindir}\" \
@@ -17,7 +26,8 @@ AM_CFLAGS = \
INCLUDES = \
-I$(top_builddir) \
-I$(top_srcdir)/common \
- -I$(top_srcdir)/libxrdp
+ -I$(top_srcdir)/libxrdp \
+ $(EXTRA_INCLUDES)
sbin_PROGRAMS = \
xrdp
@@ -41,6 +51,9 @@ xrdp_LDADD = \
$(top_builddir)/common/libcommon.la \
$(top_builddir)/libxrdp/libxrdp.la
+xrdp_LDFLAGS = \
+ $(EXTRA_FLAGS)
+
xrdpsysconfdir=$(sysconfdir)/xrdp
xrdpsysconf_DATA = \
diff --git a/xrdp/xrdp.c b/xrdp/xrdp.c
index 0c340e55..887ada68 100644
--- a/xrdp/xrdp.c
+++ b/xrdp/xrdp.c
@@ -138,7 +138,7 @@ xrdp_child_fork(void)
}
/*****************************************************************************/
-int APP_CC
+int DEFAULT_CC
g_is_term(void)
{
return g_is_wait_obj_set(g_term_event);
diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h
index 99d5743b..172d417a 100644
--- a/xrdp/xrdp.h
+++ b/xrdp/xrdp.h
@@ -27,8 +27,8 @@
#include "trans.h"
#include "list.h"
#include "libxrdpinc.h"
-#include "xrdp_types.h"
#include "xrdp_constants.h"
+#include "xrdp_types.h"
#include "defines.h"
#include "os_calls.h"
#include "ssl_calls.h"
@@ -41,7 +41,7 @@
long APP_CC
g_xrdp_sync(long (*sync_func)(long param1, long param2), long sync_param1,
long sync_param2);
-int APP_CC
+int DEFAULT_CC
g_is_term(void);
void APP_CC
g_set_term(int in_val);
@@ -283,6 +283,20 @@ xrdp_painter_copy(struct xrdp_painter* self,
int x, int y, int cx, int cy,
int srcx, int srcy);
int APP_CC
+xrdp_painter_composite(struct xrdp_painter* self,
+ struct xrdp_bitmap* src,
+ int srcformat,
+ int srcwidth,
+ int srcrepeat,
+ struct xrdp_bitmap* dst,
+ int* srctransform,
+ int mskflags,
+ struct xrdp_bitmap* msk,
+ int mskformat, int mskwidth, int mskrepeat, int op,
+ int srcx, int srcy, int mskx, int msky,
+ int dstx, int dsty, int width, int height,
+ int dstformat);
+int APP_CC
xrdp_painter_line(struct xrdp_painter* self,
struct xrdp_bitmap* bitmap,
int x1, int y1, int x2, int y2);
@@ -374,6 +388,16 @@ int DEFAULT_CC
server_paint_rect(struct xrdp_mod* mod, int x, int y, int cx, int cy,
char* data, int width, int height, int srcx, int srcy);
int DEFAULT_CC
+server_paint_rect_bpp(struct xrdp_mod* mod, int x, int y, int cx, int cy,
+ char* data, int width, int height, int srcx, int srcy,
+ int bpp);
+int DEFAULT_CC
+server_composite(struct xrdp_mod* mod, int srcidx, int srcformat, int srcwidth,
+ int srcrepeat, int* srctransform, int mskflags, int mskidx,
+ int mskformat, int mskwidth, int mskrepeat, int op,
+ int srcx, int srcy, int mskx, int msky,
+ int dstx, int dsty, int width, int height, int dstformat);
+int DEFAULT_CC
server_set_pointer(struct xrdp_mod* mod, int x, int y,
char* data, char* mask);
int DEFAULT_CC
@@ -434,6 +458,9 @@ int DEFAULT_CC
server_create_os_surface(struct xrdp_mod* mod, int id,
int width, int height);
int DEFAULT_CC
+server_create_os_surface_bpp(struct xrdp_mod* mod, int id,
+ int width, int height, int bpp);
+int DEFAULT_CC
server_switch_os_surface(struct xrdp_mod* mod, int id);
int DEFAULT_CC
server_delete_os_surface(struct xrdp_mod* mod, int id);
@@ -468,3 +495,7 @@ int DEFAULT_CC
server_monitored_desktop(struct xrdp_mod* mod,
struct rail_monitored_desktop_order* mdo,
int flags);
+int DEFAULT_CC
+server_add_char_alpha(struct xrdp_mod* mod, int font, int charactor,
+ int offset, int baseline,
+ int width, int height, char* data);
diff --git a/xrdp/xrdp.ini b/xrdp/xrdp.ini
index 9a484dbf..0e8d302b 100644
--- a/xrdp/xrdp.ini
+++ b/xrdp/xrdp.ini
@@ -13,6 +13,8 @@ tcp_nodelay=yes
# regulate if the listening socket use socket option keepalive
# if the network connection disappear without close messages the connection will be closed
tcp_keepalive=yes
+#tcp_send_buffer_bytes=32768
+#tcp_recv_buffer_bytes=32768
#black=000000
#grey=d6d3ce
#dark_grey=808080
@@ -32,6 +34,8 @@ tcp_keepalive=yes
# You can set the PAM error text in a gateway setup (MAX 256 chars)
#pamerrortxt=change your password according to policy at http://url
#new_cursors=no
+#nego_sec_layer=0
+allow_multimon=true
[Logging]
LogFile=xrdp.log
@@ -112,8 +116,8 @@ ip=ask
port=ask3389
[xrdp7]
-name=freerdp-any
-lib=libxrdpfreerdp1.so
+name=neutrinordp-any
+lib=libxrdpneutrinordp.so
ip=ask
port=ask3389
username=ask
diff --git a/xrdp/xrdp_bitmap.c b/xrdp/xrdp_bitmap.c
index 19620c40..b3faea41 100644
--- a/xrdp/xrdp_bitmap.c
+++ b/xrdp/xrdp_bitmap.c
@@ -821,6 +821,8 @@ xrdp_bitmap_copy_box_with_crc(struct xrdp_bitmap *self,
unsigned char *d8 = (unsigned char *)NULL;
unsigned short *s16 = (unsigned short *)NULL;
unsigned short *d16 = (unsigned short *)NULL;
+ unsigned int *s32;
+ unsigned int *d32;
if (self == 0)
{
@@ -864,16 +866,65 @@ xrdp_bitmap_copy_box_with_crc(struct xrdp_bitmap *self,
if (self->bpp == 24)
{
+ s32 = ((unsigned int *)(self->data)) + (self->width * y + x);
+ d32 = ((unsigned int *)(dest->data)) + (dest->width * desty + destx);
+ incs = self->width - cx;
+ incd = dest->width - cx;
+
for (i = 0; i < cy; i++)
{
- for (j = 0; j < cx; j++)
+ j = 0;
+ while (j < cx - 4)
{
- pixel = GETPIXEL32(self->data, j + x, i + y, self->width);
+ pixel = *s32;
CRC_PASS(pixel, crc);
CRC_PASS(pixel >> 8, crc);
CRC_PASS(pixel >> 16, crc);
- SETPIXEL32(dest->data, j + destx, i + desty, dest->width, pixel);
+ *d32 = pixel;
+ s32++;
+ d32++;
+
+ pixel = *s32;
+ CRC_PASS(pixel, crc);
+ CRC_PASS(pixel >> 8, crc);
+ CRC_PASS(pixel >> 16, crc);
+ *d32 = pixel;
+ s32++;
+ d32++;
+
+ pixel = *s32;
+ CRC_PASS(pixel, crc);
+ CRC_PASS(pixel >> 8, crc);
+ CRC_PASS(pixel >> 16, crc);
+ *d32 = pixel;
+ s32++;
+ d32++;
+
+ pixel = *s32;
+ CRC_PASS(pixel, crc);
+ CRC_PASS(pixel >> 8, crc);
+ CRC_PASS(pixel >> 16, crc);
+ *d32 = pixel;
+ s32++;
+ d32++;
+
+ j += 4;
}
+ while (j < cx)
+ {
+ pixel = *s32;
+ CRC_PASS(pixel, crc);
+ CRC_PASS(pixel >> 8, crc);
+ CRC_PASS(pixel >> 16, crc);
+ *d32 = pixel;
+ s32++;
+ d32++;
+
+ j += 1;
+ }
+
+ s32 += incs;
+ d32 += incd;
}
}
else if (self->bpp == 15 || self->bpp == 16)
diff --git a/xrdp/xrdp_cache.c b/xrdp/xrdp_cache.c
index cac7f114..c57fc2ad 100644
--- a/xrdp/xrdp_cache.c
+++ b/xrdp/xrdp_cache.c
@@ -21,6 +21,18 @@
#include "xrdp.h"
#include "log.h"
+#define LLOG_LEVEL 1
+#define LLOGLN(_level, _args) \
+ do \
+ { \
+ if (_level < LLOG_LEVEL) \
+ { \
+ g_write("xrdp:xrdp_cache [%10.10u]: ", g_time3()); \
+ g_writeln _args ; \
+ } \
+ } \
+ while (0)
+
/*****************************************************************************/
struct xrdp_cache *APP_CC
xrdp_cache_create(struct xrdp_wm *owner,
@@ -33,16 +45,28 @@ xrdp_cache_create(struct xrdp_wm *owner,
self->wm = owner;
self->session = session;
self->use_bitmap_comp = client_info->use_bitmap_comp;
- self->cache1_entries = client_info->cache1_entries;
+
+ self->cache1_entries = MIN(XRDP_MAX_BITMAP_CACHE_IDX,
+ client_info->cache1_entries);
+ self->cache1_entries = MAX(self->cache1_entries, 0);
self->cache1_size = client_info->cache1_size;
- self->cache2_entries = client_info->cache2_entries;
+
+ self->cache2_entries = MIN(XRDP_MAX_BITMAP_CACHE_IDX,
+ client_info->cache2_entries);
+ self->cache2_entries = MAX(self->cache2_entries, 0);
self->cache2_size = client_info->cache2_size;
- self->cache3_entries = client_info->cache3_entries;
+
+ self->cache3_entries = MIN(XRDP_MAX_BITMAP_CACHE_IDX,
+ client_info->cache3_entries);
+ self->cache3_entries = MAX(self->cache3_entries, 0);
self->cache3_size = client_info->cache3_size;
+
self->bitmap_cache_persist_enable = client_info->bitmap_cache_persist_enable;
self->bitmap_cache_version = client_info->bitmap_cache_version;
self->pointer_cache_entries = client_info->pointer_cache_entries;
self->xrdp_os_del_list = list_create();
+ LLOGLN(10, ("xrdp_cache_create: 0 %d 1 %d 2 %d",
+ self->cache1_entries, self->cache2_entries, self->cache3_entries));
return self;
}
@@ -59,9 +83,9 @@ xrdp_cache_delete(struct xrdp_cache *self)
}
/* free all the cached bitmaps */
- for (i = 0; i < 3; i++)
+ for (i = 0; i < XRDP_MAX_BITMAP_CACHE_ID; i++)
{
- for (j = 0; j < 2000; j++)
+ for (j = 0; j < XRDP_MAX_BITMAP_CACHE_IDX; j++)
{
xrdp_bitmap_delete(self->bitmap_items[i][j].bitmap);
}
@@ -98,9 +122,9 @@ xrdp_cache_reset(struct xrdp_cache *self,
int j;
/* free all the cached bitmaps */
- for (i = 0; i < 3; i++)
+ for (i = 0; i < XRDP_MAX_BITMAP_CACHE_ID; i++)
{
- for (j = 0; j < 2000; j++)
+ for (j = 0; j < XRDP_MAX_BITMAP_CACHE_IDX; j++)
{
xrdp_bitmap_delete(self->bitmap_items[i][j].bitmap);
}
@@ -136,6 +160,11 @@ xrdp_cache_reset(struct xrdp_cache *self,
return 0;
}
+#define COMPARE_WITH_CRC(_b1, _b2) \
+ ((_b1 != 0) && (_b2 != 0) && (_b1->crc == _b2->crc) && \
+ (_b1->bpp == _b2->bpp) && \
+ (_b1->width == _b2->width) && (_b1->height == _b2->height))
+
/*****************************************************************************/
/* returns cache id */
int APP_CC
@@ -170,14 +199,13 @@ xrdp_cache_add_bitmap(struct xrdp_cache *self, struct xrdp_bitmap *bitmap,
for (j = 0; j < self->cache1_entries; j++)
{
#ifdef USE_CRC
-
- if (xrdp_bitmap_compare_with_crc(self->bitmap_items[i][j].bitmap, bitmap))
+ if (COMPARE_WITH_CRC(self->bitmap_items[i][j].bitmap, bitmap))
#else
if (xrdp_bitmap_compare(self->bitmap_items[i][j].bitmap, bitmap))
#endif
{
self->bitmap_items[i][j].stamp = self->bitmap_stamp;
- DEBUG(("found bitmap at %d %d", i, j));
+ LLOGLN(10, ("found bitmap at %d %d", i, j));
xrdp_bitmap_delete(bitmap);
return MAKELONG(j, i);
}
@@ -190,14 +218,13 @@ xrdp_cache_add_bitmap(struct xrdp_cache *self, struct xrdp_bitmap *bitmap,
for (j = 0; j < self->cache2_entries; j++)
{
#ifdef USE_CRC
-
- if (xrdp_bitmap_compare_with_crc(self->bitmap_items[i][j].bitmap, bitmap))
+ if (COMPARE_WITH_CRC(self->bitmap_items[i][j].bitmap, bitmap))
#else
if (xrdp_bitmap_compare(self->bitmap_items[i][j].bitmap, bitmap))
#endif
{
self->bitmap_items[i][j].stamp = self->bitmap_stamp;
- DEBUG(("found bitmap at %d %d", i, j));
+ LLOGLN(10, ("found bitmap at %d %d", i, j));
xrdp_bitmap_delete(bitmap);
return MAKELONG(j, i);
}
@@ -210,14 +237,13 @@ xrdp_cache_add_bitmap(struct xrdp_cache *self, struct xrdp_bitmap *bitmap,
for (j = 0; j < self->cache3_entries; j++)
{
#ifdef USE_CRC
-
- if (xrdp_bitmap_compare_with_crc(self->bitmap_items[i][j].bitmap, bitmap))
+ if (COMPARE_WITH_CRC(self->bitmap_items[i][j].bitmap, bitmap))
#else
if (xrdp_bitmap_compare(self->bitmap_items[i][j].bitmap, bitmap))
#endif
{
self->bitmap_items[i][j].stamp = self->bitmap_stamp;
- DEBUG(("found bitmap at %d %d", i, j));
+ LLOGLN(10, ("found bitmap at %d %d", i, j));
xrdp_bitmap_delete(bitmap);
return MAKELONG(j, i);
}
@@ -225,7 +251,7 @@ xrdp_cache_add_bitmap(struct xrdp_cache *self, struct xrdp_bitmap *bitmap,
}
else
{
- log_message(LOG_LEVEL_ERROR,"error in xrdp_cache_add_bitmap, too big(%d)", bmp_size);
+ log_message(LOG_LEVEL_ERROR,"error in xrdp_cache_add_bitmap, too big(%d) bpp %d", bmp_size, bitmap->bpp);
}
/* look for oldest */
@@ -276,7 +302,8 @@ xrdp_cache_add_bitmap(struct xrdp_cache *self, struct xrdp_bitmap *bitmap,
}
}
- DEBUG(("adding bitmap at %d %d", cache_id, cache_idx));
+ LLOGLN(10, ("adding bitmap at %d %d ptr %p", cache_id, cache_idx,
+ self->bitmap_items[cache_id][cache_idx].bitmap));
/* set, send bitmap and return */
xrdp_bitmap_delete(self->bitmap_items[cache_id][cache_idx].bitmap);
self->bitmap_items[cache_id][cache_idx].bitmap = bitmap;
diff --git a/xrdp/xrdp_listen.c b/xrdp/xrdp_listen.c
index 965aa50d..5d7edf83 100644
--- a/xrdp/xrdp_listen.c
+++ b/xrdp/xrdp_listen.c
@@ -66,6 +66,10 @@ xrdp_listen_create(void)
{
log_message(LOG_LEVEL_ERROR,"xrdp_listen_create: trans_create failed");
}
+ else
+ {
+ self->listen_trans->is_term = g_is_term;
+ }
return self;
}
@@ -199,19 +203,31 @@ xrdp_listen_get_port_address(char *port, int port_bytes,
if (g_strcasecmp(val, "fork") == 0)
{
val = (char *)list_get_item(values, index);
- startup_param->fork = text2bool(val);
+ startup_param->fork = g_text2bool(val);
}
if (g_strcasecmp(val, "tcp_nodelay") == 0)
{
val = (char *)list_get_item(values, index);
- *tcp_nodelay = text2bool(val);
+ *tcp_nodelay = g_text2bool(val);
}
if (g_strcasecmp(val, "tcp_keepalive") == 0)
{
val = (char *)list_get_item(values, index);
- *tcp_keepalive = text2bool(val);
+ *tcp_keepalive = g_text2bool(val);
+ }
+
+ if (g_strcasecmp(val, "tcp_send_buffer_bytes") == 0)
+ {
+ val = (char *)list_get_item(values, index);
+ startup_param->send_buffer_bytes = g_atoi(val);
+ }
+
+ if (g_strcasecmp(val, "tcp_recv_buffer_bytes") == 0)
+ {
+ val = (char *)list_get_item(values, index);
+ startup_param->recv_buffer_bytes = g_atoi(val);
}
}
}
@@ -318,6 +334,7 @@ xrdp_listen_main_loop(struct xrdp_listen *self)
tbus done_obj;
int tcp_nodelay;
int tcp_keepalive;
+ int bytes;
self->status = 1;
@@ -352,6 +369,54 @@ xrdp_listen_main_loop(struct xrdp_listen *self)
}
}
+ if (self->startup_params->send_buffer_bytes > 0)
+ {
+ bytes = self->startup_params->send_buffer_bytes;
+ log_message(LOG_LEVEL_INFO, "setting send buffer to %d bytes",
+ bytes);
+ if (g_sck_set_send_buffer_bytes(self->listen_trans->sck,
+ bytes) != 0)
+ {
+ log_message(LOG_LEVEL_ERROR, "error setting send buffer");
+ }
+ else
+ {
+ if (g_sck_get_send_buffer_bytes(self->listen_trans->sck,
+ &bytes) != 0)
+ {
+ log_message(LOG_LEVEL_ERROR, "error getting send buffer");
+ }
+ else
+ {
+ log_message(LOG_LEVEL_INFO, "send buffer set to %d bytes", bytes);
+ }
+ }
+ }
+
+ if (self->startup_params->recv_buffer_bytes > 0)
+ {
+ bytes = self->startup_params->recv_buffer_bytes;
+ log_message(LOG_LEVEL_INFO, "setting recv buffer to %d bytes",
+ bytes);
+ if (g_sck_set_recv_buffer_bytes(self->listen_trans->sck,
+ bytes) != 0)
+ {
+ log_message(LOG_LEVEL_ERROR, "error setting recv buffer");
+ }
+ else
+ {
+ if (g_sck_get_recv_buffer_bytes(self->listen_trans->sck,
+ &bytes) != 0)
+ {
+ log_message(LOG_LEVEL_ERROR, "error getting recv buffer");
+ }
+ else
+ {
+ log_message(LOG_LEVEL_INFO, "recv buffer set to %d bytes", bytes);
+ }
+ }
+ }
+
self->listen_trans->trans_conn_in = xrdp_listen_conn_in;
self->listen_trans->callback_data = self;
term_obj = g_get_term_event(); /*Global termination event */
diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c
index 0a79810b..560ebedb 100644
--- a/xrdp/xrdp_mm.c
+++ b/xrdp/xrdp_mm.c
@@ -413,6 +413,10 @@ xrdp_mm_setup_mod1(struct xrdp_mm *self)
self->mod->server_notify_new_update = server_notify_new_update;
self->mod->server_notify_delete = server_notify_delete;
self->mod->server_monitored_desktop = server_monitored_desktop;
+ self->mod->server_add_char_alpha = server_add_char_alpha;
+ self->mod->server_create_os_surface_bpp = server_create_os_surface_bpp;
+ self->mod->server_paint_rect_bpp = server_paint_rect_bpp;
+ self->mod->server_composite = server_composite;
}
}
@@ -677,6 +681,265 @@ xrdp_mm_trans_process_channel_data(struct xrdp_mm *self, struct trans *trans)
/*****************************************************************************/
/* returns error
+ process rail create window order */
+static int APP_CC
+xrdp_mm_process_rail_create_window(struct xrdp_mm* self, struct stream* s)
+{
+ int flags;
+ int window_id;
+ int title_bytes;
+ int index;
+ int bytes;
+ int rv;
+ struct rail_window_state_order rwso;
+
+ g_memset(&rwso, 0, sizeof(rwso));
+ in_uint32_le(s, window_id);
+
+ g_writeln("xrdp_mm_process_rail_create_window: 0x%8.8x", window_id);
+
+ in_uint32_le(s, rwso.owner_window_id);
+ in_uint32_le(s, rwso.style);
+ in_uint32_le(s, rwso.extended_style);
+ in_uint32_le(s, rwso.show_state);
+ in_uint16_le(s, title_bytes);
+ if (title_bytes > 0)
+ {
+ rwso.title_info = g_malloc(title_bytes + 1, 0);
+ in_uint8a(s, rwso.title_info, title_bytes);
+ rwso.title_info[title_bytes] = 0;
+ }
+ in_uint32_le(s, rwso.client_offset_x);
+ in_uint32_le(s, rwso.client_offset_y);
+ in_uint32_le(s, rwso.client_area_width);
+ in_uint32_le(s, rwso.client_area_height);
+ in_uint32_le(s, rwso.rp_content);
+ in_uint32_le(s, rwso.root_parent_handle);
+ in_uint32_le(s, rwso.window_offset_x);
+ in_uint32_le(s, rwso.window_offset_y);
+ in_uint32_le(s, rwso.window_client_delta_x);
+ in_uint32_le(s, rwso.window_client_delta_y);
+ in_uint32_le(s, rwso.window_width);
+ in_uint32_le(s, rwso.window_height);
+ in_uint16_le(s, rwso.num_window_rects);
+ if (rwso.num_window_rects > 0)
+ {
+ bytes = sizeof(struct rail_window_rect) * rwso.num_window_rects;
+ rwso.window_rects = (struct rail_window_rect*)g_malloc(bytes, 0);
+ for (index = 0; index < rwso.num_window_rects; index++)
+ {
+ in_uint16_le(s, rwso.window_rects[index].left);
+ in_uint16_le(s, rwso.window_rects[index].top);
+ in_uint16_le(s, rwso.window_rects[index].right);
+ in_uint16_le(s, rwso.window_rects[index].bottom);
+ }
+ }
+ in_uint32_le(s, rwso.visible_offset_x);
+ in_uint32_le(s, rwso.visible_offset_y);
+ in_uint16_le(s, rwso.num_visibility_rects);
+ if (rwso.num_visibility_rects > 0)
+ {
+ bytes = sizeof(struct rail_window_rect) * rwso.num_visibility_rects;
+ rwso.visibility_rects = (struct rail_window_rect*)g_malloc(bytes, 0);
+ for (index = 0; index < rwso.num_visibility_rects; index++)
+ {
+ in_uint16_le(s, rwso.visibility_rects[index].left);
+ in_uint16_le(s, rwso.visibility_rects[index].top);
+ in_uint16_le(s, rwso.visibility_rects[index].right);
+ in_uint16_le(s, rwso.visibility_rects[index].bottom);
+ }
+ }
+ in_uint32_le(s, flags);
+ rv = libxrdp_orders_init(self->wm->session);
+ rv = libxrdp_window_new_update(self->wm->session, window_id, &rwso, flags);
+ rv = libxrdp_orders_send(self->wm->session);
+ g_free(rwso.title_info);
+ g_free(rwso.window_rects);
+ g_free(rwso.visibility_rects);
+ return rv;
+}
+
+/*****************************************************************************/
+/* returns error
+ process rail configure window order */
+static int APP_CC
+xrdp_mm_process_rail_configure_window(struct xrdp_mm* self, struct stream* s)
+{
+ int flags;
+ int window_id;
+ int index;
+ int bytes;
+ int rv;
+ struct rail_window_state_order rwso;
+
+ g_memset(&rwso, 0, sizeof(rwso));
+ in_uint32_le(s, window_id);
+
+ g_writeln("xrdp_mm_process_rail_configure_window: 0x%8.8x", window_id);
+
+ in_uint32_le(s, rwso.client_offset_x);
+ in_uint32_le(s, rwso.client_offset_y);
+ in_uint32_le(s, rwso.client_area_width);
+ in_uint32_le(s, rwso.client_area_height);
+ in_uint32_le(s, rwso.rp_content);
+ in_uint32_le(s, rwso.root_parent_handle);
+ in_uint32_le(s, rwso.window_offset_x);
+ in_uint32_le(s, rwso.window_offset_y);
+ in_uint32_le(s, rwso.window_client_delta_x);
+ in_uint32_le(s, rwso.window_client_delta_y);
+ in_uint32_le(s, rwso.window_width);
+ in_uint32_le(s, rwso.window_height);
+ in_uint16_le(s, rwso.num_window_rects);
+ if (rwso.num_window_rects > 0)
+ {
+ bytes = sizeof(struct rail_window_rect) * rwso.num_window_rects;
+ rwso.window_rects = (struct rail_window_rect*)g_malloc(bytes, 0);
+ for (index = 0; index < rwso.num_window_rects; index++)
+ {
+ in_uint16_le(s, rwso.window_rects[index].left);
+ in_uint16_le(s, rwso.window_rects[index].top);
+ in_uint16_le(s, rwso.window_rects[index].right);
+ in_uint16_le(s, rwso.window_rects[index].bottom);
+ }
+ }
+ in_uint32_le(s, rwso.visible_offset_x);
+ in_uint32_le(s, rwso.visible_offset_y);
+ in_uint16_le(s, rwso.num_visibility_rects);
+ if (rwso.num_visibility_rects > 0)
+ {
+ bytes = sizeof(struct rail_window_rect) * rwso.num_visibility_rects;
+ rwso.visibility_rects = (struct rail_window_rect*)g_malloc(bytes, 0);
+ for (index = 0; index < rwso.num_visibility_rects; index++)
+ {
+ in_uint16_le(s, rwso.visibility_rects[index].left);
+ in_uint16_le(s, rwso.visibility_rects[index].top);
+ in_uint16_le(s, rwso.visibility_rects[index].right);
+ in_uint16_le(s, rwso.visibility_rects[index].bottom);
+ }
+ }
+ in_uint32_le(s, flags);
+ rv = libxrdp_orders_init(self->wm->session);
+ rv = libxrdp_window_new_update(self->wm->session, window_id, &rwso, flags);
+ rv = libxrdp_orders_send(self->wm->session);
+ g_free(rwso.window_rects);
+ g_free(rwso.visibility_rects);
+ return rv;
+}
+
+/*****************************************************************************/
+/* returns error
+ process rail destroy window order */
+static int APP_CC
+xrdp_mm_process_rail_destroy_window(struct xrdp_mm* self, struct stream* s)
+{
+ int window_id;
+ int rv;
+
+ in_uint32_le(s, window_id);
+ g_writeln("xrdp_mm_process_rail_destroy_window 0x%8.8x", window_id);
+ rv = libxrdp_orders_init(self->wm->session);
+ rv = libxrdp_window_delete(self->wm->session, window_id);
+ rv = libxrdp_orders_send(self->wm->session);
+ return rv;
+}
+
+/*****************************************************************************/
+/* returns error
+ process rail update window (show state) order */
+static int APP_CC
+xrdp_mm_process_rail_show_window(struct xrdp_mm* self, struct stream* s)
+{
+ int window_id;
+ int rv;
+ int flags;
+ struct rail_window_state_order rwso;
+
+ g_memset(&rwso, 0, sizeof(rwso));
+ in_uint32_le(s, window_id);
+ in_uint32_le(s, flags);
+ in_uint32_le(s, rwso.show_state);
+ g_writeln("xrdp_mm_process_rail_show_window 0x%8.8x %x", window_id,
+ rwso.show_state);
+ rv = libxrdp_orders_init(self->wm->session);
+ rv = libxrdp_window_new_update(self->wm->session, window_id, &rwso, flags);
+ rv = libxrdp_orders_send(self->wm->session);
+ return rv;
+}
+
+/*****************************************************************************/
+/* returns error
+ process rail update window (title) order */
+static int APP_CC
+xrdp_mm_process_rail_update_window_text(struct xrdp_mm* self, struct stream* s)
+{
+ int size;
+ int flags;
+ int rv = 0;
+ int window_id;
+ struct rail_window_state_order rwso;
+
+ g_writeln("xrdp_mm_process_rail_update_window_text:");
+
+ in_uint32_le(s, window_id);
+ in_uint32_le(s, flags);
+ g_writeln(" update window title info: 0x%8.8x", window_id);
+
+ g_memset(&rwso, 0, sizeof(rwso));
+ in_uint32_le(s, size); /* title size */
+ rwso.title_info = g_malloc(size + 1, 0);
+ in_uint8a(s, rwso.title_info, size);
+ rwso.title_info[size] = 0;
+ g_writeln(" set window title %s size %d 0x%8.8x", rwso.title_info, size, flags);
+ rv = libxrdp_orders_init(self->wm->session);
+ rv = libxrdp_window_new_update(self->wm->session, window_id, &rwso, flags);
+ rv = libxrdp_orders_send(self->wm->session);
+ g_writeln(" set window title %s %d", rwso.title_info, rv);
+
+ g_free(rwso.title_info);
+
+ return rv;
+}
+
+/*****************************************************************************/
+/* returns error
+ process alternate secondary drawing orders for rail channel */
+static int APP_CC
+xrdp_mm_process_rail_drawing_orders(struct xrdp_mm* self, struct trans* trans)
+{
+ struct stream* s;
+ int order_type;
+ int rv = 0;
+
+ s = trans_get_in_s(trans);
+ if (s == 0)
+ {
+ return 1;
+ }
+ in_uint32_le(s, order_type);
+
+ switch(order_type)
+ {
+ case 2: /* create_window */
+ xrdp_mm_process_rail_create_window(self, s);
+ break;
+ case 4: /* destroy_window */
+ xrdp_mm_process_rail_destroy_window(self, s);
+ break;
+ case 6: /* show_window */
+ rv = xrdp_mm_process_rail_show_window(self, s);
+ break;
+ case 8: /* update title info */
+ rv = xrdp_mm_process_rail_update_window_text(self, s);
+ break;
+ default:
+ break;
+ }
+
+ return rv;
+}
+
+/*****************************************************************************/
+/* returns error
process a message for the channel handler */
static int APP_CC
xrdp_mm_chan_process_msg(struct xrdp_mm *self, struct trans *trans,
@@ -708,6 +971,9 @@ xrdp_mm_chan_process_msg(struct xrdp_mm *self, struct trans *trans,
case 8: /* channel data */
rv = xrdp_mm_trans_process_channel_data(self, trans);
break;
+ case 10: /* rail alternate secondary drawing orders */
+ rv = xrdp_mm_process_rail_drawing_orders(self, trans);
+ break;
default:
log_message(LOG_LEVEL_ERROR,"xrdp_mm_chan_process_msg: unknown id %d", id);
break;
@@ -793,15 +1059,17 @@ xrdp_mm_connect_chansrv(struct xrdp_mm *self, char *ip, char *port)
self->usechansrv = 1;
/* connect channel redir */
- if ((ip == 0) || (g_strcmp(ip, "127.0.0.1") == 0) || (ip[0] == 0))
+ if ((g_strcmp(ip, "127.0.0.1") == 0) || (ip[0] == 0))
{
/* unix socket */
self->chan_trans = trans_create(TRANS_MODE_UNIX, 8192, 8192);
+ self->chan_trans->is_term = g_is_term;
}
else
{
/* tcp */
self->chan_trans = trans_create(TRANS_MODE_TCP, 8192, 8192);
+ self->chan_trans->is_term = g_is_term;
}
self->chan_trans->trans_data_in = xrdp_mm_chan_data_in;
@@ -1486,6 +1754,7 @@ xrdp_mm_connect(struct xrdp_mm *self)
ok = 0;
trans_delete(self->sesman_trans);
self->sesman_trans = trans_create(TRANS_MODE_TCP, 8192, 8192);
+ self->sesman_trans->is_term = g_is_term;
xrdp_mm_get_sesman_port(port, sizeof(port));
g_snprintf(text, 255, "connecting to sesman ip %s port %s", ip, port);
xrdp_wm_log_msg(self->wm, text);
@@ -1796,6 +2065,79 @@ server_paint_rect(struct xrdp_mod *mod, int x, int y, int cx, int cy,
/*****************************************************************************/
int DEFAULT_CC
+server_paint_rect_bpp(struct xrdp_mod* mod, int x, int y, int cx, int cy,
+ char* data, int width, int height, int srcx, int srcy,
+ int bpp)
+{
+ struct xrdp_wm* wm;
+ struct xrdp_bitmap* b;
+ struct xrdp_painter* p;
+
+ p = (struct xrdp_painter*)(mod->painter);
+ if (p == 0)
+ {
+ return 0;
+ }
+ wm = (struct xrdp_wm*)(mod->wm);
+ b = xrdp_bitmap_create_with_data(width, height, bpp, data, wm);
+ xrdp_painter_copy(p, b, wm->target_surface, x, y, cx, cy, srcx, srcy);
+ xrdp_bitmap_delete(b);
+ return 0;
+}
+
+/*****************************************************************************/
+int DEFAULT_CC
+server_composite(struct xrdp_mod* mod, int srcidx, int srcformat,
+ int srcwidth, int srcrepeat, int* srctransform,
+ int mskflags, int mskidx, int mskformat, int mskwidth,
+ int mskrepeat, int op, int srcx, int srcy,
+ int mskx, int msky, int dstx, int dsty,
+ int width, int height, int dstformat)
+{
+ struct xrdp_wm* wm;
+ struct xrdp_bitmap* b;
+ struct xrdp_bitmap* msk;
+ struct xrdp_painter* p;
+ struct xrdp_os_bitmap_item* bi;
+
+ p = (struct xrdp_painter*)(mod->painter);
+ if (p == 0)
+ {
+ return 0;
+ }
+ wm = (struct xrdp_wm*)(mod->wm);
+ b = 0;
+ msk = 0;
+ bi = xrdp_cache_get_os_bitmap(wm->cache, srcidx);
+ if (bi != 0)
+ {
+ b = bi->bitmap;
+ }
+ if (mskflags & 1)
+ {
+ bi = xrdp_cache_get_os_bitmap(wm->cache, mskidx);
+ if (bi != 0)
+ {
+ msk = bi->bitmap;
+ }
+ }
+ if (b != 0)
+ {
+ xrdp_painter_composite(p, b, srcformat, srcwidth, srcrepeat,
+ wm->target_surface, srctransform,
+ mskflags, msk, mskformat, mskwidth, mskrepeat,
+ op, srcx, srcy, mskx, msky, dstx, dsty,
+ width, height, dstformat);
+ }
+ else
+ {
+ g_writeln("server_composite: error finding id %d or %d", srcidx, mskidx);
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+int DEFAULT_CC
server_set_pointer(struct xrdp_mod *mod, int x, int y,
char *data, char *mask)
{
@@ -2030,6 +2372,7 @@ server_add_char(struct xrdp_mod *mod, int font, int charactor,
fi.height = height;
fi.incby = 0;
fi.data = data;
+ fi.bpp = 1;
return libxrdp_orders_send_font(((struct xrdp_wm *)mod->wm)->session,
&fi, font, charactor);
}
@@ -2206,7 +2549,7 @@ is_channel_enabled(char *inName, struct list *names, struct list *values)
if ( index >= 0 )
{
val = (char *)list_get_item(values, index);
- reply = text2bool(val);
+ reply = g_text2bool(val);
if (reply == 0)
{
log_message(LOG_LEVEL_INFO,"This channel is disabled: %s", inName);
@@ -2410,6 +2753,29 @@ server_create_os_surface(struct xrdp_mod *mod, int rdpindex,
/*****************************************************************************/
int DEFAULT_CC
+server_create_os_surface_bpp(struct xrdp_mod* mod, int rdpindex,
+ int width, int height, int bpp)
+{
+ struct xrdp_wm* wm;
+ struct xrdp_bitmap* bitmap;
+ int error;
+
+ wm = (struct xrdp_wm*)(mod->wm);
+ bitmap = xrdp_bitmap_create(width, height, bpp,
+ WND_TYPE_OFFSCREEN, wm);
+ error = xrdp_cache_add_os_bitmap(wm->cache, bitmap, rdpindex);
+ if (error != 0)
+ {
+ g_writeln("server_create_os_surface_bpp: xrdp_cache_add_os_bitmap failed");
+ return 1;
+ }
+ bitmap->item_index = rdpindex;
+ bitmap->id = rdpindex;
+ return 0;
+}
+
+/*****************************************************************************/
+int DEFAULT_CC
server_switch_os_surface(struct xrdp_mod *mod, int rdpindex)
{
struct xrdp_wm *wm;
@@ -2436,7 +2802,7 @@ server_switch_os_surface(struct xrdp_mod *mod, int rdpindex)
bi = xrdp_cache_get_os_bitmap(wm->cache, rdpindex);
- if (bi != 0)
+ if ((bi != 0) && (bi->bitmap != 0))
{
//g_writeln("server_switch_os_surface: setting target_surface to rdpid %d", id);
wm->target_surface = bi->bitmap;
@@ -2627,3 +2993,23 @@ server_monitored_desktop(struct xrdp_mod *mod,
wm = (struct xrdp_wm *)(mod->wm);
return libxrdp_monitored_desktop(wm->session, mdo, flags);
}
+
+/*****************************************************************************/
+int DEFAULT_CC
+server_add_char_alpha(struct xrdp_mod* mod, int font, int charactor,
+ int offset, int baseline,
+ int width, int height, char* data)
+{
+ struct xrdp_font_char fi;
+
+ fi.offset = offset;
+ fi.baseline = baseline;
+ fi.width = width;
+ fi.height = height;
+ fi.incby = 0;
+ fi.data = data;
+ fi.bpp = 8;
+ return libxrdp_orders_send_font(((struct xrdp_wm*)mod->wm)->session,
+ &fi, font, charactor);
+}
+
diff --git a/xrdp/xrdp_painter.c b/xrdp/xrdp_painter.c
index 4457fee8..b9d1da16 100644
--- a/xrdp/xrdp_painter.c
+++ b/xrdp/xrdp_painter.c
@@ -849,7 +849,7 @@ xrdp_painter_copy(struct xrdp_painter *self,
{
w = MIN(64, ((srcx + cx) - i));
h = MIN(64, ((srcy + cy) - j));
- b = xrdp_bitmap_create(w, h, self->wm->screen->bpp, 0, self->wm);
+ b = xrdp_bitmap_create(w, h, src->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, self->wm->hints);
cache_id = HIWORD(bitmap_id);
@@ -889,6 +889,86 @@ xrdp_painter_copy(struct xrdp_painter *self,
/*****************************************************************************/
int APP_CC
+xrdp_painter_composite(struct xrdp_painter* self,
+ struct xrdp_bitmap* src,
+ int srcformat,
+ int srcwidth,
+ int srcrepeat,
+ struct xrdp_bitmap* dst,
+ int* srctransform,
+ int mskflags,
+ struct xrdp_bitmap* msk,
+ int mskformat, int mskwidth, int mskrepeat, int op,
+ int srcx, int srcy, int mskx, int msky,
+ int dstx, int dsty, int width, int height, int dstformat)
+{
+ struct xrdp_rect clip_rect;
+ struct xrdp_rect draw_rect;
+ struct xrdp_rect rect1;
+ struct xrdp_rect rect2;
+ struct xrdp_region* region;
+ int k;
+ int dx;
+ int dy;
+ int palette_id;
+ int cache_srcidx;
+ int cache_mskidx;
+
+ if (self == 0 || src == 0 || dst == 0)
+ {
+ return 0;
+ }
+
+ /* todo data */
+
+ if (dst->type == WND_TYPE_BITMAP)
+ {
+ return 0;
+ }
+
+ if (src->type == WND_TYPE_OFFSCREEN)
+ {
+ xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy);
+ region = xrdp_region_create(self->wm);
+ xrdp_region_add_rect(region, &clip_rect);
+ dstx += dx;
+ dsty += dy;
+
+ palette_id = 0;
+ cache_srcidx = src->item_index;
+ cache_mskidx = -1;
+ if (mskflags & 1)
+ {
+ if (msk != 0)
+ {
+ cache_mskidx = msk->item_index; // todo
+ }
+ }
+
+ k = 0;
+ while (xrdp_region_get_rect(region, k, &rect1) == 0)
+ {
+ if (rect_intersect(&rect1, &clip_rect, &rect2))
+ {
+ MAKERECT(rect1, dstx, dsty, width, height);
+ if (rect_intersect(&rect2, &rect1, &draw_rect))
+ {
+ libxrdp_orders_composite_blt(self->session, cache_srcidx, srcformat, srcwidth,
+ srcrepeat, srctransform, mskflags, cache_mskidx,
+ mskformat, mskwidth, mskrepeat, op, srcx, srcy,
+ mskx, msky, dstx, dsty, width, height, dstformat,
+ &draw_rect);
+ }
+ }
+ k++;
+ }
+ xrdp_region_delete(region);
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+int APP_CC
xrdp_painter_line(struct xrdp_painter *self,
struct xrdp_bitmap *dst,
int x1, int y1, int x2, int y2)
diff --git a/xrdp/xrdp_process.c b/xrdp/xrdp_process.c
index 228bf630..4c52eaac 100644
--- a/xrdp/xrdp_process.c
+++ b/xrdp/xrdp_process.c
@@ -203,6 +203,9 @@ xrdp_process_main_loop(struct xrdp_process *self)
else
{
g_writeln("xrdp_process_main_loop: libxrdp_process_incomming failed");
+ /* this will try to send a disconnect,
+ maybe should check that connection got far enough */
+ libxrdp_disconnect(self->session);
}
/* Run end in module */
xrdp_process_mod_end(self);
diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h
index e7bb7baf..3811b16b 100644
--- a/xrdp/xrdp_types.h
+++ b/xrdp/xrdp_types.h
@@ -22,6 +22,7 @@
#define LOG_WINDOW_CHAR_PER_LINE 60
#include "xrdp_rail.h"
+#include "xrdp_constants.h"
#define MAX_NR_CHANNELS 16
#define MAX_CHANNEL_NAME 16
@@ -51,8 +52,10 @@ struct xrdp_mod
int (*server_screen_blt)(struct xrdp_mod* v, int x, int y, int cx, int cy,
int srcx, int srcy);
int (*server_paint_rect)(struct xrdp_mod* v, int x, int y, int cx, int cy,
- char* data, int width, int height, int srcx, int srcy);
- int (*server_set_pointer)(struct xrdp_mod* v, int x, int y, char* data, char* mask);
+ char* data, int width, int height,
+ int srcx, int srcy);
+ int (*server_set_pointer)(struct xrdp_mod* v, int x, int y,
+ char* data, char* mask);
int (*server_palette)(struct xrdp_mod* v, int* palette);
int (*server_msg)(struct xrdp_mod* v, char* msg, int code);
int (*server_is_term)(struct xrdp_mod* v);
@@ -117,8 +120,23 @@ struct xrdp_mod
int flags);
int (*server_set_pointer_ex)(struct xrdp_mod* v, int x, int y, char* data,
char* mask, int bpp);
+ int (*server_add_char_alpha)(struct xrdp_mod* mod, int font, int charactor,
+ int offset, int baseline,
+ int width, int height, char* data);
- long server_dumby[100 - 38]; /* align, 100 minus the number of server
+ int (*server_create_os_surface_bpp)(struct xrdp_mod* v, int rdpindex,
+ int width, int height, int bpp);
+ int (*server_paint_rect_bpp)(struct xrdp_mod* v, int x, int y, int cx, int cy,
+ char* data, int width, int height,
+ int srcx, int srcy, int bpp);
+ int (*server_composite)(struct xrdp_mod* v, int srcidx, int srcformat,
+ int srcwidth, int srcrepeat, int* srctransform,
+ int mskflags, int mskidx, int mskformat,
+ int mskwidth, int mskrepeat, int op,
+ int srcx, int srcy, int mskx, int msky,
+ int dstx, int dsty, int width, int height,
+ int dstformat);
+ long server_dumby[100 - 42]; /* align, 100 minus the number of server
functions above */
/* common */
long handle; /* pointer to self as int */
@@ -185,6 +203,9 @@ struct xrdp_brush_item
char pattern[8];
};
+/* moved to xrdp_constants.h
+#define XRDP_BITMAP_CACHE_ENTRIES 2048 */
+
/* differnce caches */
struct xrdp_cache
{
@@ -195,7 +216,8 @@ struct xrdp_cache
struct xrdp_palette_item palette_items[6];
/* bitmap */
int bitmap_stamp;
- struct xrdp_bitmap_item bitmap_items[3][2000];
+ struct xrdp_bitmap_item bitmap_items[XRDP_MAX_BITMAP_CACHE_ID]
+ [XRDP_MAX_BITMAP_CACHE_IDX];
int use_bitmap_comp;
int cache1_entries;
int cache1_size;
@@ -467,4 +489,6 @@ struct xrdp_startup_params
int help;
int version;
int fork;
+ int send_buffer_bytes;
+ int recv_buffer_bytes;
};
diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c
index bfcc7548..bba25c34 100644
--- a/xrdp/xrdp_wm.c
+++ b/xrdp/xrdp_wm.c
@@ -401,7 +401,7 @@ xrdp_wm_load_static_colors_plus(struct xrdp_wm *self, char *autorun_name)
if (g_strcasecmp(val, "black") == 0)
{
val = (char *)list_get_item(values, index);
- self->black = HCOLOR(self->screen->bpp, xrdp_wm_htoi(val));
+ self->black = HCOLOR(self->screen->bpp,xrdp_wm_htoi(val));
}
else if (g_strcasecmp(val, "grey") == 0)
{
@@ -455,7 +455,7 @@ xrdp_wm_load_static_colors_plus(struct xrdp_wm *self, char *autorun_name)
else if (g_strcasecmp(val, "hidelogwindow") == 0)
{
val = (char *)list_get_item(values, index);
- self->hide_log_window = text2bool(val);
+ self->hide_log_window = g_text2bool(val);
}
else if (g_strcasecmp(val, "pamerrortxt") == 0)
{
@@ -1221,6 +1221,22 @@ xrdp_wm_mouse_click(struct xrdp_wm *self, int x, int y, int but, int down)
self->mm->mod->mod_event(self->mm->mod, WM_BUTTON5UP,
self->mouse_x, self->mouse_y, 0, 0);
}
+ if (but == 6 && down)
+ {
+ self->mm->mod->mod_event(self->mm->mod, WM_BUTTON6DOWN, x, y, 0, 0);
+ }
+ else if (but == 6 && !down)
+ {
+ self->mm->mod->mod_event(self->mm->mod, WM_BUTTON6UP, x, y, 0, 0);
+ }
+ if (but == 7 && down)
+ {
+ self->mm->mod->mod_event(self->mm->mod, WM_BUTTON7DOWN, x, y, 0, 0);
+ }
+ else if (but == 7 && !down)
+ {
+ self->mm->mod->mod_event(self->mm->mod, WM_BUTTON7UP, x, y, 0, 0);
+ }
}
}
}
@@ -1528,18 +1544,48 @@ xrdp_wm_process_input_mouse(struct xrdp_wm *self, int device_flags,
}
}
- if (device_flags == MOUSE_FLAG_BUTTON4 || /* 0x0280 */
- device_flags == 0x0278)
+ if (device_flags & 0x200) /* PTRFLAGS_WHEEL */
{
- xrdp_wm_mouse_click(self, 0, 0, 4, 0);
+ if (device_flags & 0x100) /* PTRFLAGS_WHEEL_NEGATIVE */
+ {
+ xrdp_wm_mouse_click(self, 0, 0, 5, 0);
+ }
+ else
+ {
+ xrdp_wm_mouse_click(self, 0, 0, 4, 0);
+ }
}
- if (device_flags == MOUSE_FLAG_BUTTON5 || /* 0x0380 */
- device_flags == 0x0388)
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+xrdp_wm_process_input_mousex(struct xrdp_wm* self, int device_flags,
+ int x, int y)
+{
+ if (device_flags & 0x8000) /* PTRXFLAGS_DOWN */
{
- xrdp_wm_mouse_click(self, 0, 0, 5, 0);
+ if (device_flags & 0x0001) /* PTRXFLAGS_BUTTON1 */
+ {
+ xrdp_wm_mouse_click(self, x, y, 6, 1);
+ }
+ else if (device_flags & 0x0002) /* PTRXFLAGS_BUTTON2 */
+ {
+ xrdp_wm_mouse_click(self, x, y, 7, 1);
+ }
+ }
+ else
+ {
+ if (device_flags & 0x0001) /* PTRXFLAGS_BUTTON1 */
+ {
+ xrdp_wm_mouse_click(self, x, y, 6, 0);
+ }
+ else if (device_flags & 0x0002) /* PTRXFLAGS_BUTTON2 */
+ {
+ xrdp_wm_mouse_click(self, x, y, 7, 0);
+ }
}
-
return 0;
}
@@ -1616,6 +1662,9 @@ callback(long id, int msg, long param1, long param2, long param3, long param4)
case 0x8001: /* RDP_INPUT_MOUSE */
rv = xrdp_wm_process_input_mouse(wm, param3, param1, param2);
break;
+ case 0x8002: /* RDP_INPUT_MOUSEX (INPUT_EVENT_MOUSEX) */
+ rv = xrdp_wm_process_input_mousex(wm, param3, param1, param2);
+ break;
case 0x4444: /* invalidate, this is not from RDP_DATA_PDU_INPUT */
/* like the rest, its from RDP_PDU_DATA with code 33 */
/* its the rdp client asking for a screen update */
diff --git a/xrdpvr/xrdpvr.c b/xrdpvr/xrdpvr.c
index 09a0a6b8..a6e7e894 100644
--- a/xrdpvr/xrdpvr.c
+++ b/xrdpvr/xrdpvr.c
@@ -28,6 +28,49 @@ PLAYER_STATE_INFO g_psi;
int g_video_index = -1;
int g_audio_index = -1;
+/*****************************************************************************/
+/* produce a hex dump */
+void hexdump(char *p, int len)
+{
+ unsigned char *line;
+ int i;
+ int thisline;
+ int offset;
+
+ line = (unsigned char *)p;
+ offset = 0;
+
+ while (offset < len)
+ {
+ printf("%04x ", offset);
+ thisline = len - offset;
+
+ if (thisline > 16)
+ {
+ thisline = 16;
+ }
+
+ for (i = 0; i < thisline; i++)
+ {
+ printf("%02x ", line[i]);
+ }
+
+ for (; i < 16; i++)
+ {
+ printf(" ");
+ }
+
+ for (i = 0; i < thisline; i++)
+ {
+ printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
+ }
+
+ printf("\n");
+ offset += thisline;
+ line += thisline;
+ }
+}
+
/**
* initialize the media player
*
@@ -45,12 +88,14 @@ xrdpvr_init_player(void *channel, int stream_id, char *filename)
return -1;
}
+#if 0
/* send metadata from media file to client */
if (xrdpvr_create_metadata_file(channel, filename))
{
printf("error sending metadata to client\n");
return -1;
}
+#endif
/* ask client to get video format from media file */
if (xrdpvr_set_video_format(channel, 101))
@@ -244,6 +289,9 @@ xrdpvr_play_media(void *channel, int stream_id, char *filename)
return -1;
}
+ g_psi.bsfc = av_bitstream_filter_init("h264_mp4toannexb");
+ printf("g_psi.bsfc %p\n", g_psi.bsfc);
+
return 0;
}
@@ -252,9 +300,13 @@ static int firstVideoPkt = 1;
int xrdpvr_get_frame(void **av_pkt_ret, int *is_video_frame, int *delay_in_us)
{
- AVPacket *av_pkt;
- double dts;
+ AVPacket *av_pkt;
+ double dts;
+ int error;
+ AVBitStreamFilterContext *bsfc;
+ AVPacket new_pkt;
+ //printf("xrdpvr_get_frame:\n");
/* alloc an AVPacket */
if ((av_pkt = (AVPacket *) malloc(sizeof(AVPacket))) == NULL)
return -1;
@@ -292,6 +344,34 @@ int xrdpvr_get_frame(void **av_pkt_ret, int *is_video_frame, int *delay_in_us)
}
else if (av_pkt->stream_index == g_video_index)
{
+
+ bsfc = g_psi.bsfc;
+ printf("hi %p\n", bsfc);
+ while (bsfc != 0)
+ {
+ new_pkt = *av_pkt;
+ error = av_bitstream_filter_filter(bsfc, g_psi.p_video_codec_ctx, 0,
+ &new_pkt.data, &new_pkt.size,
+ av_pkt->data, av_pkt->size,
+ av_pkt->flags & AV_PKT_FLAG_KEY);
+ //printf("new size %d\n", new_pkt.size);
+ //hexdump(new_pkt.data, 32);
+ //printf("old size %d\n", av_pkt->size);
+ //hexdump(av_pkt->data, 32);
+ if (error > 0)
+ {
+ av_free_packet(av_pkt);
+ new_pkt.destruct = av_destruct_packet;
+ }
+ else if (error < 0)
+ {
+ printf("bitstream filter error\n");
+ }
+ *av_pkt = new_pkt;
+ bsfc = bsfc->next;
+ }
+
+
dts = av_pkt->dts;
//printf("$$$ video raw_dts=%f raw_pts=%f\n", (double) av_pkt->dts, (double) av_pkt->dts);
@@ -344,9 +424,14 @@ int send_video_pkt(void *channel, int stream_id, void *pkt_p)
int xrdpvr_play_frame(void *channel, int stream_id, int *videoTimeout, int *audioTimeout)
{
- AVPacket av_pkt;
- double dts;
- int delay_in_us;
+ AVPacket av_pkt;
+ double dts;
+ int delay_in_us;
+ int error;
+ AVBitStreamFilterContext *bsfc;
+ AVPacket new_pkt;
+
+ printf("xrdpvr_play_frame:\n");
if (av_read_frame(g_psi.p_format_ctx, &av_pkt) < 0)
{
@@ -381,6 +466,29 @@ int xrdpvr_play_frame(void *channel, int stream_id, int *videoTimeout, int *audi
}
else if (av_pkt.stream_index == g_video_index)
{
+ bsfc = g_psi.bsfc;
+ printf("hi %p\n", bsfc);
+ while (bsfc != 0)
+ {
+ new_pkt= av_pkt;
+ error = av_bitstream_filter_filter(bsfc, g_psi.p_video_codec_ctx, 0,
+ &new_pkt.data, &new_pkt.size,
+ av_pkt.data, av_pkt.size,
+ av_pkt.flags & AV_PKT_FLAG_KEY);
+// av_pkt.flags & PKT_FLAG_KEY);
+ if (error > 0)
+ {
+ av_free_packet(&av_pkt);
+ new_pkt.destruct = av_destruct_packet;
+ }
+ else if (error < 0)
+ {
+ printf("bitstream filter error\n");
+ }
+ av_pkt = new_pkt;
+ bsfc = bsfc->next;
+ }
+
xrdpvr_send_video_data(channel, stream_id, av_pkt.size, av_pkt.data);
dts = av_pkt.dts;
diff --git a/xrdpvr/xrdpvr_internal.h b/xrdpvr/xrdpvr_internal.h
index ca01941c..17e2acfa 100644
--- a/xrdpvr/xrdpvr_internal.h
+++ b/xrdpvr/xrdpvr_internal.h
@@ -217,6 +217,8 @@ typedef struct _player_state_info
AVFrame *frame;
AVPacket avpkt;
+ AVBitStreamFilterContext *bsfc;
+
} PLAYER_STATE_INFO;
static int xrdpvr_write_to_client(void *channel, STREAM *s);
diff --git a/xup/xup.c b/xup/xup.c
index 5320a3c9..7ff5e5e8 100644
--- a/xup/xup.c
+++ b/xup/xup.c
@@ -19,6 +19,16 @@
*/
#include "xup.h"
+#include "log.h"
+
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#define LOG_LEVEL 1
+#define LLOG(_level, _args) \
+ do { if (_level < LOG_LEVEL) { g_write _args ; } } while (0)
+#define LLOGLN(_level, _args) \
+ do { if (_level < LOG_LEVEL) { g_writeln _args ; } } while (0)
/******************************************************************************/
/* returns error */
@@ -128,6 +138,33 @@ lib_mod_start(struct mod *mod, int w, int h, int bpp)
}
/******************************************************************************/
+static int APP_CC
+lib_mod_log_peer(struct mod *mod)
+{
+ int my_pid;
+ int pid;
+ int uid;
+ int gid;
+
+ my_pid = g_getpid();
+ if (g_sck_get_peer_cred(mod->sck, &pid, &uid, &gid) == 0)
+ {
+ log_message(LOG_LEVEL_INFO, "lib_mod_log_peer: xrdp_pid=%d connected "
+ "to X11rdp_pid=%d X11rdp_uid=%d X11rdp_gid=%d "
+ "client_ip=%s client_port=%s",
+ my_pid, pid, uid, gid,
+ mod->client_info.client_addr,
+ mod->client_info.client_port);
+ }
+ else
+ {
+ log_message(LOG_LEVEL_ERROR, "lib_mod_log_peer: g_sck_get_peer_cred "
+ "failed");
+ }
+ return 0;
+}
+
+/******************************************************************************/
/* return error */
int DEFAULT_CC
lib_mod_connect(struct mod *mod)
@@ -245,6 +282,14 @@ lib_mod_connect(struct mod *mod)
if (error == 0)
{
+ if (use_uds)
+ {
+ lib_mod_log_peer(mod);
+ }
+ }
+
+ if (error == 0)
+ {
/* send version message */
init_stream(s, 8192);
s_push_layer(s, iso_hdr, 4);
@@ -476,6 +521,25 @@ process_server_window_new_update(struct mod *mod, struct stream *s)
/******************************************************************************/
/* return error */
static int APP_CC
+process_server_window_show(struct mod* mod, struct stream* s)
+{
+ int window_id;
+ int rv;
+ int flags;
+ struct rail_window_state_order rwso;
+
+ g_memset(&rwso, 0, sizeof(rwso));
+ in_uint32_le(s, window_id);
+ in_uint32_le(s, flags);
+ in_uint32_le(s, rwso.show_state);
+ mod->server_window_new_update(mod, window_id, &rwso, flags);
+ rv = 0;
+ return rv;
+}
+
+/******************************************************************************/
+/* return error */
+static int APP_CC
process_server_window_delete(struct mod *mod, struct stream *s)
{
int window_id;
@@ -512,7 +576,35 @@ process_server_set_pointer_ex(struct mod *mod, struct stream *s)
/******************************************************************************/
/* return error */
-static int
+static int APP_CC
+send_paint_rect_ack(struct mod *mod, int flags, int x, int y, int cx, int cy,
+ int frame_id)
+{
+ int len;
+ struct stream *s;
+
+ make_stream(s);
+ init_stream(s, 8192);
+ s_push_layer(s, iso_hdr, 4);
+ out_uint16_le(s, 105);
+ out_uint32_le(s, flags);
+ out_uint32_le(s, frame_id);
+ out_uint32_le(s, x);
+ out_uint32_le(s, y);
+ out_uint32_le(s, cx);
+ out_uint32_le(s, cy);
+ s_mark_end(s);
+ len = (int)(s->end - s->data);
+ s_pop_layer(s, iso_hdr);
+ out_uint32_le(s, len);
+ lib_send(mod, s->data, len);
+ free_stream(s);
+ return 0;
+}
+
+/******************************************************************************/
+/* return error */
+static int APP_CC
lib_mod_process_orders(struct mod *mod, int type, struct stream *s)
{
int rv;
@@ -522,12 +614,17 @@ lib_mod_process_orders(struct mod *mod, int type, struct stream *s)
int cy;
int srcx;
int srcy;
+ int mskx;
+ int msky;
+ int dstx;
+ int dsty;
int len_bmpdata;
int style;
int x1;
int y1;
int x2;
int y2;
+ int bpp;
int rdpid;
int hints;
int mask;
@@ -536,6 +633,33 @@ lib_mod_process_orders(struct mod *mod, int type, struct stream *s)
int fgcolor;
int bgcolor;
int opcode;
+ int flags;
+ int shmem_id;
+ int shmem_offset;
+ int frame_id;
+ int charactor;
+ int font;
+ int mixmode;
+ int clip_left;
+ int clip_top;
+ int clip_right;
+ int clip_bottom;
+ int box_left;
+ int box_top;
+ int box_right;
+ int box_bottom;
+ int srcrepeat;
+ int srcidx;
+ int srcformat;
+ int srcwidth;
+ int mskflags;
+ int mskidx;
+ int mskformat;
+ int mskwidth;
+ int mskrepeat;
+ int dstformat;
+ int op;
+ int transform[10];
char *bmpdata;
char cur_data[32 * (32 * 3)];
char cur_mask[32 * (32 / 8)];
@@ -658,9 +782,143 @@ lib_mod_process_orders(struct mod *mod, int type, struct stream *s)
case 26: /* server_window_delete */
rv = process_server_window_delete(mod, s);
break;
+ case 27: /* server_window_new_update - show */
+ rv = process_server_window_show(mod, s);
+ break;
+ case 28: /* server_add_char */
+ in_uint16_le(s, font);
+ in_uint16_le(s, charactor);
+ in_sint16_le(s, x);
+ in_sint16_le(s, y);
+ in_uint16_le(s, cx);
+ in_uint16_le(s, cy);
+ in_uint16_le(s, len_bmpdata);
+ in_uint8p(s, bmpdata, len_bmpdata);
+ rv = mod->server_add_char(mod, font, charactor, x, y, cx, cy, bmpdata);
+ break;
+ case 29: /* server_add_char_alpha */
+ in_uint16_le(s, font);
+ in_uint16_le(s, charactor);
+ in_sint16_le(s, x);
+ in_sint16_le(s, y);
+ in_uint16_le(s, cx);
+ in_uint16_le(s, cy);
+ in_uint16_le(s, len_bmpdata);
+ in_uint8p(s, bmpdata, len_bmpdata);
+ rv = mod->server_add_char_alpha(mod, font, charactor, x, y, cx, cy, bmpdata);
+ break;
+ case 30: /* server_draw_text */
+ in_uint16_le(s, font);
+ in_uint16_le(s, flags);
+ in_uint16_le(s, mixmode);
+ in_sint16_le(s, clip_left);
+ in_sint16_le(s, clip_top);
+ in_sint16_le(s, clip_right);
+ in_sint16_le(s, clip_bottom);
+ in_sint16_le(s, box_left);
+ in_sint16_le(s, box_top);
+ in_sint16_le(s, box_right);
+ in_sint16_le(s, box_bottom);
+ in_sint16_le(s, x);
+ in_sint16_le(s, y);
+ in_uint16_le(s, len_bmpdata);
+ in_uint8p(s, bmpdata, len_bmpdata);
+ rv = mod->server_draw_text(mod, font, flags, mixmode, clip_left, clip_top,
+ clip_right, clip_bottom, box_left, box_top,
+ box_right, box_bottom, x, y, bmpdata, len_bmpdata);
+ break;
+ case 31: /* server_create_os_surface_bpp */
+ in_uint32_le(s, rdpid);
+ in_uint16_le(s, width);
+ in_uint16_le(s, height);
+ in_uint8(s, bpp);
+ rv = mod->server_create_os_surface_bpp(mod, rdpid, width, height, bpp);
+ break;
+ case 32: /* server_paint_rect_bpp */
+ in_sint16_le(s, x);
+ in_sint16_le(s, y);
+ in_uint16_le(s, cx);
+ in_uint16_le(s, cy);
+ in_uint32_le(s, len_bmpdata);
+ in_uint8p(s, bmpdata, len_bmpdata);
+ in_uint16_le(s, width);
+ in_uint16_le(s, height);
+ in_sint16_le(s, srcx);
+ in_sint16_le(s, srcy);
+ in_uint8(s, bpp);
+ rv = mod->server_paint_rect_bpp(mod, x, y, cx, cy,
+ bmpdata, width, height,
+ srcx, srcy, bpp);
+ break;
+ case 33:
+ in_uint16_le(s, srcidx);
+ in_uint32_le(s, srcformat);
+ in_uint16_le(s, srcwidth);
+ in_uint8(s, srcrepeat);
+ g_memcpy(transform, s->p, 40);
+ in_uint8s(s, 40);
+ in_uint8(s, mskflags);
+ in_uint16_le(s, mskidx);
+ in_uint32_le(s, mskformat);
+ in_uint16_le(s, mskwidth);
+ in_uint8(s, mskrepeat);
+ in_uint8(s, op);
+ in_sint16_le(s, srcx);
+ in_sint16_le(s, srcy);
+ in_sint16_le(s, mskx);
+ in_sint16_le(s, msky);
+ in_sint16_le(s, dstx);
+ in_sint16_le(s, dsty);
+ in_uint16_le(s, width);
+ in_uint16_le(s, height);
+ in_uint32_le(s, dstformat);
+ rv = mod->server_composite(mod, srcidx, srcformat, srcwidth, srcrepeat,
+ transform, mskflags, mskidx, mskformat,
+ mskwidth, mskrepeat, op, srcx, srcy, mskx, msky,
+ dstx, dsty, width, height, dstformat);
+ break;
case 51: /* server_set_pointer_ex */
rv = process_server_set_pointer_ex(mod, s);
break;
+ case 60: /* server_paint_rect_shmem */
+ in_sint16_le(s, x);
+ in_sint16_le(s, y);
+ in_uint16_le(s, cx);
+ in_uint16_le(s, cy);
+ in_uint32_le(s, flags);
+ in_uint32_le(s, frame_id);
+ in_uint32_le(s, shmem_id);
+ in_uint32_le(s, shmem_offset);
+ in_uint16_le(s, width);
+ in_uint16_le(s, height);
+ in_sint16_le(s, srcx);
+ in_sint16_le(s, srcy);
+ bmpdata = 0;
+ if (flags == 0) /* screen */
+ {
+ if (mod->screen_shmem_id == 0)
+ {
+ mod->screen_shmem_id = shmem_id;
+ mod->screen_shmem_pixels = shmat(mod->screen_shmem_id, 0, 0);
+ }
+ if (mod->screen_shmem_pixels != 0)
+ {
+ bmpdata = mod->screen_shmem_pixels + shmem_offset;
+ }
+ }
+ if (bmpdata != 0)
+ {
+ rv = mod->server_paint_rect(mod, x, y, cx, cy,
+ bmpdata, width, height,
+ srcx, srcy);
+ }
+ else
+ {
+ rv = 1;
+ }
+ send_paint_rect_ack(mod, flags, x, y, cx, cy, frame_id);
+ break;
+
default:
g_writeln("lib_mod_process_orders: unknown order type %d", type);
rv = 0;
diff --git a/xup/xup.h b/xup/xup.h
index a7956915..9ae4f920 100644
--- a/xup/xup.h
+++ b/xup/xup.h
@@ -53,7 +53,8 @@ struct mod
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);
+ 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);
@@ -119,8 +120,21 @@ struct mod
int flags);
int (*server_set_cursor_ex)(struct mod* v, int x, int y, char* data,
char* mask, int bpp);
+ int (*server_add_char_alpha)(struct mod* v, int font, int charactor,
+ int offset, int baseline,
+ int width, int height, char* data);
+ int (*server_create_os_surface_bpp)(struct mod* v, int rdpindex,
+ int width, int height, int bpp);
+ int (*server_paint_rect_bpp)(struct mod* v, int x, int y, int cx, int cy,
+ char* data, int width, int height,
+ int srcx, int srcy, int bpp);
+ int (*server_composite)(struct mod* v, int srcidx, int srcformat, int srcwidth,
+ int srcrepeat, int* srctransform, int mskflags, int mskidx,
+ int mskformat, int mskwidth, int mskrepeat, int op,
+ int srcx, int srcy, int mskx, int msky,
+ int dstx, int dsty, int width, int height, int dstformat);
- tbus server_dumby[100 - 38]; /* align, 100 minus the number of server
+ tbus server_dumby[100 - 42]; /* align, 100 minus the number of server
functions above */
/* common */
tbus handle; /* pointer to self as long */
@@ -139,4 +153,6 @@ struct mod
tbus sck_obj;
int shift_state;
struct xrdp_client_info client_info;
+ int screen_shmem_id;
+ char *screen_shmem_pixels;
};