diff options
178 files changed, 14128 insertions, 3286 deletions
diff --git a/common/arch.h b/common/arch.h index 6a29b0a9..b4eb4719 100644 --- a/common/arch.h +++ b/common/arch.h @@ -32,6 +32,12 @@ defined(__AIX__) || defined(__PPC__) || defined(__mips__) || \ defined(__ia64__) || defined(__ppc__) || defined(__arm__) #define NEED_ALIGN +#elif defined(__x86__) || defined(__x86_64__) || \ + defined(__AMD64__) || defined(_M_IX86) || \ + defined(__i386__) +#define NO_NEED_ALIGN +#else +#warning unknown arch #endif #endif @@ -62,6 +68,8 @@ #define EXPORT_CC #endif +#ifndef DEFINED_Ts +#define DEFINED_Ts typedef char ti8; typedef unsigned char tui8; typedef signed char tsi8; @@ -71,6 +79,7 @@ typedef signed short tsi16; typedef int ti32; typedef unsigned int tui32; typedef signed int tsi32; +typedef int tbool; #if defined(_WIN64) /* Microsoft's VC++ compiler uses the more backwards-compatible LLP64 model. Most other 64 bit compilers(Solaris, AIX, HP, Linux, Mac OS X) use @@ -94,5 +103,6 @@ typedef int tsock; typedef unsigned long long tui64; typedef signed long long tsi64; #endif +#endif /* DEFINED_Ts */ #endif diff --git a/common/os_calls.c b/common/os_calls.c index 2d5b4280..80b2d235 100644 --- a/common/os_calls.c +++ b/common/os_calls.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,11 @@ * put all the os / arch define in here you want */ +/* To test for Windows (64 bit or 32 bit) use _WIN32 and _WIN64 in addition + for 64 bit windows. _WIN32 is defined for both. + To test for Linux use __linux__. + To test for BSD use BSD */ + #if defined(HAVE_CONFIG_H) #include "config_ac.h" #endif @@ -42,6 +47,8 @@ #include <sys/types.h> #include <sys/wait.h> #include <sys/stat.h> +#include <sys/ipc.h> +#include <sys/shm.h> #include <dlfcn.h> #include <arpa/inet.h> #include <netdb.h> @@ -58,6 +65,13 @@ #include <stdio.h> #include <locale.h> +/* this is so we can use #ifdef BSD later */ +/* This is the recommended way of detecting BSD in the + FreeBSD Porter's Handbook. */ +#if (defined(__unix__) || defined(unix)) && !defined(USG) +#include <sys/param.h> +#endif + #include "os_calls.h" #include "arch.h" #include "log.h" @@ -594,10 +608,16 @@ g_tcp_local_socket(void) } /*****************************************************************************/ +/* returns error */ int APP_CC g_sck_get_peer_cred(int sck, int *pid, int *uid, int *gid) { +#if defined(SO_PEERCRED) +#if defined(_WIN32) int ucred_length; +#else + unsigned int ucred_length; +#endif struct myucred { pid_t pid; @@ -623,6 +643,9 @@ g_sck_get_peer_cred(int sck, int *pid, int *uid, int *gid) *gid = credentials.gid; } return 0; +#else + return 1; +#endif } /*****************************************************************************/ @@ -3118,3 +3141,35 @@ g_text2bool(const char *s) } return 0; } + +/*****************************************************************************/ +/* returns pointer or nil on error */ +void * APP_CC +g_shmat(int shmid) +{ +#if defined(_WIN32) + return 0; +#else + return shmat(shmid, 0, 0); +#endif +} + +/*****************************************************************************/ +/* returns -1 on error 0 on success */ +int APP_CC +g_shmdt(const void *shmaddr) +{ +#if defined(_WIN32) + return -1; +#else + return shmdt(shmaddr); +#endif +} + +/*****************************************************************************/ +/* returns -1 on error 0 on success */ +int APP_CC +g_gethostname(char *name, int len) +{ + return gethostname(name, len); +} diff --git a/common/os_calls.h b/common/os_calls.h index b6e1c91a..06ce8494 100644 --- a/common/os_calls.h +++ b/common/os_calls.h @@ -161,5 +161,8 @@ int APP_CC g_time1(void); int APP_CC g_time2(void); int APP_CC g_time3(void); int APP_CC g_text2bool(const char *s); +void * APP_CC g_shmat(int shmid); +int APP_CC g_shmdt(const void *shmaddr); +int APP_CC g_gethostname(char *name, int len); #endif diff --git a/common/ssl_calls.c b/common/ssl_calls.c index 4cb706f3..a187edc9 100644 --- a/common/ssl_calls.c +++ b/common/ssl_calls.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2012 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +24,7 @@ #include <openssl/rc4.h> #include <openssl/md5.h> #include <openssl/sha.h> +#include <openssl/hmac.h> #include <openssl/bn.h> #include <openssl/rsa.h> @@ -157,6 +158,151 @@ ssl_md5_complete(void *md5_info, char *data) MD5_Final((tui8 *)data, (MD5_CTX *)md5_info); } +/* FIPS stuff */ + +/*****************************************************************************/ +void *APP_CC +ssl_des3_encrypt_info_create(const char *key, const char* ivec) +{ + EVP_CIPHER_CTX *des3_ctx; + const tui8 *lkey; + const tui8 *livec; + + des3_ctx = (EVP_CIPHER_CTX *) g_malloc(sizeof(EVP_CIPHER_CTX), 1); + EVP_CIPHER_CTX_init(des3_ctx); + lkey = (const tui8 *) key; + livec = (const tui8 *) ivec; + EVP_EncryptInit_ex(des3_ctx, EVP_des_ede3_cbc(), NULL, lkey, livec); + EVP_CIPHER_CTX_set_padding(des3_ctx, 0); + return des3_ctx; +} + +/*****************************************************************************/ +void *APP_CC +ssl_des3_decrypt_info_create(const char *key, const char* ivec) +{ + EVP_CIPHER_CTX *des3_ctx; + const tui8 *lkey; + const tui8 *livec; + + des3_ctx = g_malloc(sizeof(EVP_CIPHER_CTX), 1); + EVP_CIPHER_CTX_init(des3_ctx); + lkey = (const tui8 *) key; + livec = (const tui8 *) ivec; + EVP_DecryptInit_ex(des3_ctx, EVP_des_ede3_cbc(), NULL, lkey, livec); + EVP_CIPHER_CTX_set_padding(des3_ctx, 0); + return des3_ctx; +} + +/*****************************************************************************/ +void APP_CC +ssl_des3_info_delete(void *des3) +{ + EVP_CIPHER_CTX *des3_ctx; + + des3_ctx = (EVP_CIPHER_CTX *) des3; + if (des3_ctx != 0) + { + EVP_CIPHER_CTX_cleanup(des3_ctx); + g_free(des3_ctx); + } +} + +/*****************************************************************************/ +int APP_CC +ssl_des3_encrypt(void *des3, int length, const char *in_data, char *out_data) +{ + EVP_CIPHER_CTX *des3_ctx; + int len; + const tui8 *lin_data; + tui8 *lout_data; + + des3_ctx = (EVP_CIPHER_CTX *) des3; + lin_data = (const tui8 *) in_data; + lout_data = (tui8 *) out_data; + len = 0; + EVP_EncryptUpdate(des3_ctx, lout_data, &len, lin_data, length); + return 0; +} + +/*****************************************************************************/ +int APP_CC +ssl_des3_decrypt(void *des3, int length, const char *in_data, char *out_data) +{ + EVP_CIPHER_CTX *des3_ctx; + int len; + const tui8 *lin_data; + tui8 *lout_data; + + des3_ctx = (EVP_CIPHER_CTX *) des3; + lin_data = (const tui8 *) in_data; + lout_data = (tui8 *) out_data; + len = 0; + EVP_DecryptUpdate(des3_ctx, lout_data, &len, lin_data, length); + return 0; +} + +/*****************************************************************************/ +void * APP_CC +ssl_hmac_info_create(void) +{ + HMAC_CTX *hmac_ctx; + + hmac_ctx = (HMAC_CTX *) g_malloc(sizeof(HMAC_CTX), 1); + HMAC_CTX_init(hmac_ctx); + return hmac_ctx; +} + +/*****************************************************************************/ +void APP_CC +ssl_hmac_info_delete(void *hmac) +{ + HMAC_CTX *hmac_ctx; + + hmac_ctx = (HMAC_CTX *) hmac; + if (hmac_ctx != 0) + { + HMAC_CTX_cleanup(hmac_ctx); + g_free(hmac_ctx); + } +} + +/*****************************************************************************/ +void APP_CC +ssl_hmac_sha1_init(void *hmac, const char *data, int len) +{ + HMAC_CTX *hmac_ctx; + + hmac_ctx = (HMAC_CTX *) hmac; + HMAC_Init_ex(hmac_ctx, data, len, EVP_sha1(), NULL); +} + +/*****************************************************************************/ +void APP_CC +ssl_hmac_transform(void *hmac, const char *data, int len) +{ + HMAC_CTX *hmac_ctx; + const tui8 *ldata; + + hmac_ctx = (HMAC_CTX *) hmac; + ldata = (const tui8*) data; + HMAC_Update(hmac_ctx, ldata, len); +} + +/*****************************************************************************/ +void APP_CC +ssl_hmac_complete(void *hmac, char *data, int len) +{ + HMAC_CTX *hmac_ctx; + tui8* ldata; + tui32 llen; + + hmac_ctx = (HMAC_CTX *) hmac; + ldata = (tui8 *) data; + llen = len; + HMAC_Final(hmac_ctx, ldata, &llen); +} + /*****************************************************************************/ static void APP_CC ssl_reverse_it(char *p, int len) diff --git a/common/ssl_calls.h b/common/ssl_calls.h index 3b59537a..40acfb5b 100644 --- a/common/ssl_calls.h +++ b/common/ssl_calls.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -53,6 +53,26 @@ void APP_CC ssl_md5_transform(void* md5_info, char* data, int len); void APP_CC ssl_md5_complete(void* md5_info, char* data); +void *APP_CC +ssl_des3_encrypt_info_create(const char *key, const char* ivec); +void *APP_CC +ssl_des3_decrypt_info_create(const char *key, const char* ivec); +void APP_CC +ssl_des3_info_delete(void *des3); +int APP_CC +ssl_des3_encrypt(void *des3, int length, const char *in_data, char *out_data); +int APP_CC +ssl_des3_decrypt(void *des3, int length, const char *in_data, char *out_data); +void * APP_CC +ssl_hmac_info_create(void); +void APP_CC +ssl_hmac_info_delete(void *hmac); +void APP_CC +ssl_hmac_sha1_init(void *hmac, const char *data, int len); +void APP_CC +ssl_hmac_transform(void *hmac, const char *data, int len); +void APP_CC +ssl_hmac_complete(void *hmac, char *data, int len); int APP_CC ssl_mod_exp(char* out, int out_len, char* in, int in_len, char* mod, int mod_len, char* exp, int exp_len); diff --git a/common/trans.c b/common/trans.c index bb349298..aced0667 100644 --- a/common/trans.c +++ b/common/trans.c @@ -282,7 +282,10 @@ trans_check_wait_objs(struct trans *self) if (self->trans_data_in != 0) { rv = self->trans_data_in(self); - init_stream(self->in_s, 0); + if (self->no_stream_init_on_data_in == 0) + { + init_stream(self->in_s, 0); + } } } } @@ -471,6 +474,15 @@ trans_write_copy(struct trans *self) } temp_s->next_packet = (char *) wait_s; } + + /* try to send */ + if (send_waiting(self, 0) != 0) + { + /* error */ + self->status = TRANS_STATUS_DOWN; + return 1; + } + return 0; } diff --git a/common/trans.h b/common/trans.h index 350f05cc..c2e5e0df 100644 --- a/common/trans.h +++ b/common/trans.h @@ -57,6 +57,8 @@ struct trans struct stream* wait_s; char addr[256]; char port[256]; + int no_stream_init_on_data_in; + int extra_flags; /* user defined */ }; struct trans* APP_CC @@ -66,6 +68,10 @@ trans_delete(struct trans* self); int APP_CC 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); +int APP_CC trans_check_wait_objs(struct trans* self); int APP_CC trans_force_read_s(struct trans* self, struct stream* in_s, int size); diff --git a/common/xrdp_client_info.h b/common/xrdp_client_info.h index acd145e6..50c9f143 100644 --- a/common/xrdp_client_info.h +++ b/common/xrdp_client_info.h @@ -110,6 +110,17 @@ struct xrdp_client_info int multimon; /* 0 = deny , 1 = allow */ int monitorCount; /* number of monitors detected (max = 16) */ struct monitor_info minfo[16]; /* client monitor data */ + + int keyboard_type; + int keyboard_subtype; + + int png_codec_id; + int png_prop_len; + char png_prop[64]; + int vendor_flags[4]; + int mcs_connection_type; + int mcs_early_capability_flags; + }; #endif diff --git a/configure.ac b/configure.ac index 6c0134e6..621ce4be 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.7.0], [xrdp-devel@lists.sourceforge.net]) +AC_INIT([xrdp], [0.9.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 @@ -43,14 +43,22 @@ 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]) AM_CONDITIONAL(XRDP_SIMPLESOUND, [test x$simplesound = xtrue]) + AC_ARG_ENABLE(fuse, AS_HELP_STRING([--enable-fuse], [Build fuse(clipboard file / drive redir) (default: no)]), [fuse=true], [fuse=false]) AM_CONDITIONAL(XRDP_FUSE, [test x$fuse = xtrue]) + +AC_ARG_ENABLE(loadpulsemodules, AS_HELP_STRING([--enable-loadpulsemodules], + [Build code to load pulse audio modules (default: no)]), + [loadpulsemodules=true], [loadpulsemodules=false]) +AM_CONDITIONAL(XRDP_LOAD_PULSE_MODULES, [test x$loadpulsemodules = xtrue]) + AC_ARG_ENABLE(xrdpvr, AS_HELP_STRING([--enable-xrdpvr], [Build xrdpvr module (default: no)]), [xrdpvr=true], [xrdpvr=false]) @@ -105,6 +113,13 @@ then [#define _FILE_OFFSET_BITS 64]) fi +# checking for libpulse +if ! test -z "$enable_loadpulsemodules" +then + AC_CHECK_HEADER([pulse/util.h], [], + [AC_MSG_ERROR([please install libpulse-dev or libpulse-devel])]) +fi + # checking for libpulse libpulse-simple if ! test -z "$enable_simplesound" then diff --git a/libxrdp/Makefile.am b/libxrdp/Makefile.am index 6564da36..e83fce10 100644 --- a/libxrdp/Makefile.am +++ b/libxrdp/Makefile.am @@ -55,8 +55,8 @@ libxrdp_la_SOURCES = \ xrdp_orders.c \ xrdp_rdp.c \ xrdp_sec.c \ - xrdp_tcp.c \ xrdp_bitmap_compress.c \ + xrdp_bitmap32_compress.c \ xrdp_jpeg_compress.c \ xrdp_orders_rail.c \ xrdp_mppc_enc.c diff --git a/libxrdp/libxrdp.c b/libxrdp/libxrdp.c index e72fa1d0..7ab1f914 100644 --- a/libxrdp/libxrdp.c +++ b/libxrdp/libxrdp.c @@ -32,8 +32,6 @@ libxrdp_init(tbus id, struct trans *trans) session->rdp = xrdp_rdp_create(session, trans); session->orders = xrdp_orders_create(session, (struct xrdp_rdp *)session->rdp); session->client_info = &(((struct xrdp_rdp *)session->rdp)->client_info); - make_stream(session->s); - init_stream(session->s, 8192 * 2); return session; } @@ -48,7 +46,6 @@ libxrdp_exit(struct xrdp_session *session) xrdp_orders_delete((struct xrdp_orders *)session->orders); xrdp_rdp_delete((struct xrdp_rdp *)session->rdp); - free_stream(session->s); g_free(session); return 0; } @@ -69,19 +66,38 @@ libxrdp_process_incomming(struct xrdp_session *session) /******************************************************************************/ int EXPORT_CC -libxrdp_process_data(struct xrdp_session *session) +libxrdp_process_data(struct xrdp_session *session, struct stream *s) { int cont; int rv; int code; int term; int dead_lock_counter; + struct xrdp_rdp *rdp; + struct stream *ls; + + if (session->in_process_data != 0) + { + g_writeln("libxrdp_process_data: error reentry"); + return 1; + } + session->in_process_data++; + + ls = 0; + if (s == 0) + { + make_stream(ls); + init_stream(ls, 8192 * 4); + s = ls; + } term = 0; cont = 1; rv = 0; dead_lock_counter = 0; + rdp = (struct xrdp_rdp *) (session->rdp); + while ((cont || !session->up_and_running) && !term) { if (session->is_term != 0) @@ -94,8 +110,7 @@ libxrdp_process_data(struct xrdp_session *session) code = 0; - if (xrdp_rdp_recv((struct xrdp_rdp *)(session->rdp), - session->s, &code) != 0) + if (xrdp_rdp_recv(rdp, s, &code) != 0) { rv = 1; break; @@ -106,20 +121,30 @@ libxrdp_process_data(struct xrdp_session *session) switch (code) { case -1: - xrdp_rdp_send_demand_active((struct xrdp_rdp *)session->rdp); + xrdp_rdp_send_demand_active(rdp); + + /* send Monitor Layout PDU for multimon */ + if (session->client_info->monitorCount > 0 && + session->client_info->multimon == 1) + { + DEBUG(("sending monitor layout pdu")); + if (xrdp_rdp_send_monitorlayout(rdp) != 0) + { + g_writeln("xrdp_rdp_send_monitorlayout: error"); + } + } + session->up_and_running = 0; break; case 0: dead_lock_counter++; break; case RDP_PDU_CONFIRM_ACTIVE: /* 3 */ - xrdp_rdp_process_confirm_active((struct xrdp_rdp *)session->rdp, - session->s); + xrdp_rdp_process_confirm_active(rdp, s); break; case RDP_PDU_DATA: /* 7 */ - if (xrdp_rdp_process_data((struct xrdp_rdp *)session->rdp, - session->s) != 0) + if (xrdp_rdp_process_data(rdp, s) != 0) { DEBUG(("libxrdp_process_data returned non zero")); cont = 0; @@ -138,17 +163,24 @@ libxrdp_process_data(struct xrdp_session *session) /*This situation can happen and this is a workaround*/ cont = 0; g_writeln("Serious programming error we were locked in a deadly loop") ; - g_writeln("remaining :%d", session->s->end - session->s->next_packet); - session->s->next_packet = 0; + g_writeln("remaining :%d", s->end - s->next_packet); + s->next_packet = 0; } if (cont) { - cont = (session->s->next_packet != 0) && - (session->s->next_packet < session->s->end); + cont = (s->next_packet != 0) && + (s->next_packet < s->end); } } + if (s == ls) + { + free_stream(s); + } + + session->in_process_data--; + return rv; } @@ -758,7 +790,7 @@ libxrdp_reset(struct xrdp_session *session, /* process till up and running */ session->up_and_running = 0; - if (libxrdp_process_data(session) != 0) + if (libxrdp_process_data(session, 0) != 0) { g_writeln("non handled error from libxrdp_process_data"); } diff --git a/libxrdp/libxrdp.h b/libxrdp/libxrdp.h index 5bf627b5..d9e5e6d1 100644 --- a/libxrdp/libxrdp.h +++ b/libxrdp/libxrdp.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,20 +37,13 @@ #include "file_loc.h" #include "xrdp_client_info.h" -/* tcp */ -struct xrdp_tcp -{ - struct trans* trans; - struct xrdp_iso* iso_layer; /* owner */ -}; - /* iso */ struct xrdp_iso { struct xrdp_mcs* mcs_layer; /* owner */ - struct xrdp_tcp* tcp_layer; int requestedProtocol; int selectedProtocol; + struct trans* trans; }; /* used in mcs */ @@ -73,6 +66,20 @@ struct xrdp_mcs struct list* channel_list; }; +/* Encryption Methods */ +#define CRYPT_METHOD_NONE 0x00000000 +#define CRYPT_METHOD_40BIT 0x00000001 +#define CRYPT_METHOD_128BIT 0x00000002 +#define CRYPT_METHOD_56BIT 0x00000008 +#define CRYPT_METHOD_FIPS 0x00000010 + +/* Encryption Levels */ +#define CRYPT_LEVEL_NONE 0x00000000 +#define CRYPT_LEVEL_LOW 0x00000001 +#define CRYPT_LEVEL_CLIENT_COMPATIBLE 0x00000002 +#define CRYPT_LEVEL_HIGH 0x00000003 +#define CRYPT_LEVEL_FIPS 0x00000004 + /* sec */ struct xrdp_sec { @@ -90,9 +97,9 @@ struct xrdp_sec char encrypt_key[16]; char decrypt_update_key[16]; char encrypt_update_key[16]; - int rc4_key_size; /* 1 = 40 bit, 2 = 128 bit */ + int crypt_method; int rc4_key_len; /* 8 = 40 bit, 16 = 128 bit */ - int crypt_level; /* 1, 2, 3 = low, meduim, high */ + int crypt_level; char sign_key[16]; void* decrypt_rc4_info; void* encrypt_rc4_info; @@ -102,6 +109,12 @@ struct xrdp_sec char pri_exp[64]; int channel_code; int multimon; + char fips_encrypt_key[24]; + char fips_decrypt_key[24]; + char fips_sign_key[20]; + void* encrypt_fips_info; + void* decrypt_fips_info; + void* sign_fips_info; }; /* channel */ @@ -221,7 +234,7 @@ struct xrdp_orders_state int com_blt_width; /* 2 */ int com_blt_height; /* 2 */ int com_blt_dstformat; /* 2 */ - + }; /* orders */ @@ -353,6 +366,8 @@ xrdp_rdp_incoming(struct xrdp_rdp* self); int APP_CC xrdp_rdp_send_demand_active(struct xrdp_rdp* self); int APP_CC +xrdp_rdp_send_monitorlayout(struct xrdp_rdp* self); +int APP_CC xrdp_rdp_process_confirm_active(struct xrdp_rdp* self, struct stream* s); int APP_CC xrdp_rdp_process_data(struct xrdp_rdp* self, struct stream* s); @@ -467,10 +482,33 @@ xrdp_bitmap_compress(char* in_data, int width, int height, int start_line, struct stream* temp_s, int e); int APP_CC +xrdp_bitmap32_compress(char* in_data, int width, int height, + struct stream* s, int bpp, int byte_limit, + int start_line, struct stream* temp_s, + int e); +int APP_CC xrdp_jpeg_compress(void *handle, char* in_data, int width, int height, struct stream* s, int bpp, int byte_limit, int start_line, struct stream* temp_s, int e, int quality); + +int APP_CC +xrdp_codec_jpeg_compress(void *handle, + int format, /* input data format */ + char *inp_data, /* input data */ + int width, /* width of inp_data */ + int height, /* height of inp_data */ + int stride, /* inp_data stride, in bytes*/ + int x, /* x loc in inp_data */ + int y, /* y loc in inp_data */ + int cx, /* width of area to compress */ + int cy, /* height of area to compress */ + int quality, /* higher numbers compress less */ + char *out_data, /* dest for jpg image */ + int *io_len /* length of out_data and on return */ + /* len of compressed data */ + ); + void *APP_CC xrdp_jpeg_init(void); int APP_CC diff --git a/libxrdp/libxrdpinc.h b/libxrdp/libxrdpinc.h index e5f52a05..d322eafa 100644 --- a/libxrdp/libxrdpinc.h +++ b/libxrdp/libxrdpinc.h @@ -70,8 +70,8 @@ struct xrdp_session void* orders; struct xrdp_client_info* client_info; int up_and_running; - struct stream* s; int (*is_term)(void); + int in_process_data; /* inc / dec libxrdp_process_data calls */ }; struct xrdp_session* DEFAULT_CC @@ -83,7 +83,7 @@ libxrdp_disconnect(struct xrdp_session* session); int DEFAULT_CC libxrdp_process_incomming(struct xrdp_session* session); int DEFAULT_CC -libxrdp_process_data(struct xrdp_session* session); +libxrdp_process_data(struct xrdp_session* session, struct stream *s); int DEFAULT_CC libxrdp_send_palette(struct xrdp_session* session, int* palette); int DEFAULT_CC diff --git a/libxrdp/xrdp_bitmap32_compress.c b/libxrdp/xrdp_bitmap32_compress.c new file mode 100644 index 00000000..b681d040 --- /dev/null +++ b/libxrdp/xrdp_bitmap32_compress.c @@ -0,0 +1,32 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2014 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * planar bitmap compressor + * 32 bpp compression + */ + +#include "libxrdp.h" + +/*****************************************************************************/ +int APP_CC +xrdp_bitmap32_compress(char *in_data, int width, int height, + struct stream *s, int bpp, int byte_limit, + int start_line, struct stream *temp_s, + int e) +{ + return 0; +} diff --git a/libxrdp/xrdp_bitmap_compress.c b/libxrdp/xrdp_bitmap_compress.c index 28a08e77..03c56f10 100644 --- a/libxrdp/xrdp_bitmap_compress.c +++ b/libxrdp/xrdp_bitmap_compress.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,13 +16,15 @@ * limitations under the License. * * bitmap compressor + * This is the original RDP bitmap compression algorithm. Pixel based. + * This does not do 32 bpp compression, nscodec, rfx, etc */ #include "libxrdp.h" /*****************************************************************************/ #define IN_PIXEL8(in_ptr, in_x, in_y, in_w, in_last_pixel, in_pixel); \ - { \ + do { \ if (in_ptr == 0) \ { \ in_pixel = 0; \ @@ -35,11 +37,11 @@ { \ in_pixel = in_last_pixel; \ } \ - } + } while (0) /*****************************************************************************/ #define IN_PIXEL16(in_ptr, in_x, in_y, in_w, in_last_pixel, in_pixel); \ - { \ + do { \ if (in_ptr == 0) \ { \ in_pixel = 0; \ @@ -52,11 +54,11 @@ { \ in_pixel = in_last_pixel; \ } \ - } + } while (0) /*****************************************************************************/ #define IN_PIXEL32(in_ptr, in_x, in_y, in_w, in_last_pixel, in_pixel); \ - { \ + do { \ if (in_ptr == 0) \ { \ in_pixel = 0; \ @@ -69,12 +71,12 @@ { \ in_pixel = in_last_pixel; \ } \ - } + } while (0) /*****************************************************************************/ /* color */ #define OUT_COLOR_COUNT1(in_count, in_s, in_data) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count < 32) \ @@ -98,12 +100,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* color */ #define OUT_COLOR_COUNT2(in_count, in_s, in_data) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count < 32) \ @@ -127,12 +129,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* color */ #define OUT_COLOR_COUNT3(in_count, in_s, in_data) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count < 32) \ @@ -162,12 +164,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* copy */ #define OUT_COPY_COUNT1(in_count, in_s, in_data) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count < 32) \ @@ -192,12 +194,12 @@ } \ in_count = 0; \ init_stream(in_data, 0); \ - } + } while (0) /*****************************************************************************/ /* copy */ #define OUT_COPY_COUNT2(in_count, in_s, in_data) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count < 32) \ @@ -225,12 +227,12 @@ } \ in_count = 0; \ init_stream(in_data, 0); \ - } + } while (0) /*****************************************************************************/ /* copy */ #define OUT_COPY_COUNT3(in_count, in_s, in_data) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count < 32) \ @@ -258,12 +260,12 @@ } \ in_count = 0; \ init_stream(in_data, 0); \ - } + } while (0) /*****************************************************************************/ /* bicolor */ #define OUT_BICOLOR_COUNT1(in_count, in_s, in_color1, in_color2) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count / 2 < 16) \ @@ -291,12 +293,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* bicolor */ #define OUT_BICOLOR_COUNT2(in_count, in_s, in_color1, in_color2) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count / 2 < 16) \ @@ -324,12 +326,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* bicolor */ #define OUT_BICOLOR_COUNT3(in_count, in_s, in_color1, in_color2) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count / 2 < 16) \ @@ -369,12 +371,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* fill */ #define OUT_FILL_COUNT1(in_count, in_s) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count < 32) \ @@ -394,12 +396,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* fill */ #define OUT_FILL_COUNT2(in_count, in_s) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count < 32) \ @@ -419,12 +421,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* fill */ #define OUT_FILL_COUNT3(in_count, in_s) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count < 32) \ @@ -444,12 +446,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* mix */ #define OUT_MIX_COUNT1(in_count, in_s) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count < 32) \ @@ -470,12 +472,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* mix */ #define OUT_MIX_COUNT2(in_count, in_s) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count < 32) \ @@ -496,12 +498,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* mix */ #define OUT_MIX_COUNT3(in_count, in_s) \ - { \ + do { \ if (in_count > 0) \ { \ if (in_count < 32) \ @@ -522,12 +524,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* fom */ #define OUT_FOM_COUNT1(in_count, in_s, in_mask, in_mask_len) \ - { \ + do { \ if (in_count > 0) \ { \ if ((in_count % 8) == 0 && in_count < 249) \ @@ -551,12 +553,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* fom */ #define OUT_FOM_COUNT2(in_count, in_s, in_mask, in_mask_len) \ - { \ + do { \ if (in_count > 0) \ { \ if ((in_count % 8) == 0 && in_count < 249) \ @@ -580,12 +582,12 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ /* fill or mix (fom) */ #define OUT_FOM_COUNT3(in_count, in_s, in_mask, in_mask_len) \ - { \ + do { \ if (in_count > 0) \ { \ if ((in_count % 8) == 0 && in_count < 249) \ @@ -609,7 +611,7 @@ } \ } \ in_count = 0; \ - } + } while (0) /*****************************************************************************/ #define TEST_FILL \ @@ -629,7 +631,7 @@ ) \ ) #define RESET_COUNTS \ - { \ + do { \ bicolor_count = 0; \ fill_count = 0; \ color_count = 0; \ @@ -637,7 +639,7 @@ fom_count = 0; \ fom_mask_len = 0; \ bicolor_spin = 0; \ - } + } while (0) /*****************************************************************************/ int APP_CC diff --git a/libxrdp/xrdp_iso.c b/libxrdp/xrdp_iso.c index 69c242d3..31c279b5 100644 --- a/libxrdp/xrdp_iso.c +++ b/libxrdp/xrdp_iso.c @@ -30,7 +30,7 @@ xrdp_iso_create(struct xrdp_mcs *owner, struct trans *trans) DEBUG((" in xrdp_iso_create")); self = (struct xrdp_iso *)g_malloc(sizeof(struct xrdp_iso), 1); self->mcs_layer = owner; - self->tcp_layer = xrdp_tcp_create(self, trans); + self->trans = trans; DEBUG((" out xrdp_iso_create")); return self; } @@ -44,7 +44,6 @@ xrdp_iso_delete(struct xrdp_iso *self) return; } - xrdp_tcp_delete(self->tcp_layer); g_free(self); } @@ -91,13 +90,21 @@ xrdp_iso_recv_msg(struct xrdp_iso *self, struct stream *s, int *code, int *len) { int ver; // TPKT Version int plen; // TPKT PacketLength + int do_read; *code = 0; // X.224 Packet Type *len = 0; // X.224 Length Indicator - if (xrdp_tcp_recv(self->tcp_layer, s, 4) != 0) + /* early in connection sequence, iso needs to do a force read */ + do_read = s != self->trans->in_s; + + if (do_read) { - return 1; + init_stream(s, 4); + if (trans_force_read_s(self->trans, s, 4) != 0) + { + return 1; + } } in_uint8(s, ver); @@ -115,9 +122,13 @@ xrdp_iso_recv_msg(struct xrdp_iso *self, struct stream *s, int *code, int *len) return 1; } - if (xrdp_tcp_recv(self->tcp_layer, s, plen - 4) != 0) + if (do_read) { - return 1; + init_stream(s, plen - 4); + if (trans_force_read_s(self->trans, s, plen - 4) != 0) + { + return 1; + } } if (!s_check_rem(s, 2)) @@ -147,6 +158,7 @@ xrdp_iso_recv_msg(struct xrdp_iso *self, struct stream *s, int *code, int *len) return 0; } + /*****************************************************************************/ /* returns error */ int APP_CC @@ -177,10 +189,7 @@ xrdp_iso_recv(struct xrdp_iso *self, struct stream *s) static int APP_CC xrdp_iso_send_rdpnegrsp(struct xrdp_iso *self, struct stream *s, int code) { - if (xrdp_tcp_init(self->tcp_layer, s) != 0) - { - return 1; - } + init_stream(s, 8192 * 4); /* 32 KB */ /* TPKT HEADER - 4 bytes */ out_uint8(s, 3); /* version */ @@ -217,7 +226,7 @@ xrdp_iso_send_rdpnegrsp(struct xrdp_iso *self, struct stream *s, int code) s_mark_end(s); - if (xrdp_tcp_send(self->tcp_layer, s) != 0) + if (trans_force_write_s(self->trans, s) != 0) { return 1; } @@ -228,10 +237,7 @@ xrdp_iso_send_rdpnegrsp(struct xrdp_iso *self, struct stream *s, int code) 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; - } + init_stream(s, 8192 * 4); /* 32 KB */ /* TPKT HEADER - 4 bytes */ out_uint8(s, 3); /* version */ @@ -250,7 +256,7 @@ xrdp_iso_send_rdpnegfailure(struct xrdp_iso *self, struct stream *s, int code, i out_uint32_le(s, failureCode); /* failure code */ s_mark_end(s); - if (xrdp_tcp_send(self->tcp_layer, s) != 0) + if (trans_force_write_s(self->trans, s) != 0) { return 1; } @@ -379,7 +385,7 @@ xrdp_iso_incoming(struct xrdp_iso *self) int APP_CC xrdp_iso_init(struct xrdp_iso *self, struct stream *s) { - xrdp_tcp_init(self->tcp_layer, s); + init_stream(s, 8192 * 4); /* 32 KB */ s_push_layer(s, iso_hdr, 7); return 0; } @@ -401,7 +407,7 @@ xrdp_iso_send(struct xrdp_iso *self, struct stream *s) out_uint8(s, ISO_PDU_DT); out_uint8(s, 0x80); - if (xrdp_tcp_send(self->tcp_layer, s) != 0) + if (trans_force_write_s(self->trans, s) != 0) { return 1; } diff --git a/libxrdp/xrdp_jpeg_compress.c b/libxrdp/xrdp_jpeg_compress.c index a41bd1cf..334cc2e3 100644 --- a/libxrdp/xrdp_jpeg_compress.c +++ b/libxrdp/xrdp_jpeg_compress.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -98,6 +98,67 @@ xrdp_jpeg_compress(void *handle, char *in_data, int width, int height, return height; } +/** + * Compress a rectangular area (aka inner rectangle) inside our + * frame buffer (inp_data) + *****************************************************************************/ + +int APP_CC +xrdp_codec_jpeg_compress(void *handle, + int format, /* input data format */ + char *inp_data, /* input data */ + int width, /* width of inp_data */ + int height, /* height of inp_data */ + int stride, /* inp_data stride, in bytes*/ + int x, /* x loc in inp_data */ + int y, /* y loc in inp_data */ + int cx, /* width of area to compress */ + int cy, /* height of area to compress */ + int quality, /* higher numbers compress less */ + char *out_data, /* dest for jpg image */ + int *io_len /* length of out_data and on return */ + /* len of compressed data */ + ) +{ + tjhandle tj_han; + int error; + int bpp; + char *src_ptr; + + /* + * note: for now we assume that format is always XBGR and ignore format + */ + + if (handle == 0) + { + g_writeln("xrdp_codec_jpeg_compress: handle is nil"); + return height; + } + + tj_han = (tjhandle) handle; + + /* get bytes per pixel */ + bpp = stride / width; + + /* start of inner rect in inp_data */ + src_ptr = inp_data + (y * stride + x * bpp); + + /* compress inner rect */ + error = tjCompress(tj_han, /* opaque handle */ + src_ptr, /* source buf */ + cx, /* width of area to compress */ + stride, /* pitch */ + cy, /* height of area to compress */ + TJPF_XBGR, /* pixel size */ + out_data, /* dest buf */ + io_len, /* inner_buf length & compressed_size */ + TJSAMP_420, /* jpeg sub sample */ + quality, /* jpeg quality */ + 0 /* flags */ + ); + return height; +} + /*****************************************************************************/ void *APP_CC xrdp_jpeg_init(void) diff --git a/libxrdp/xrdp_mcs.c b/libxrdp/xrdp_mcs.c index c145158c..9dcb5b51 100644 --- a/libxrdp/xrdp_mcs.c +++ b/libxrdp/xrdp_mcs.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -75,8 +75,8 @@ xrdp_mcs_delete(struct xrdp_mcs *self) } /*****************************************************************************/ -/* This function sends channel join confirm*/ -/* returns error = 1 ok = 0*/ +/* This function sends channel join confirm */ +/* returns error = 1 ok = 0 */ static int APP_CC xrdp_mcs_send_cjcf(struct xrdp_mcs *self, int userid, int chanid) { @@ -151,6 +151,12 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan) /* this is channels getting added from the client */ if (appid == MCS_CJRQ) { + if (s == self->iso_layer->trans->in_s) + { + /* this should not happen */ + g_writeln("xrdp_mcs_recv: error, MCS_CJRQ at wrong time"); + return 1; + } if (!s_check_rem(s, 4)) { return 1; @@ -165,13 +171,12 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan) { log_message(LOG_LEVEL_ERROR,"Non handled error from xrdp_mcs_send_cjcf") ; } - continue; } if (appid == MCS_SDRQ || appid == MCS_SDIN) { - break ; + break; } else { @@ -946,16 +951,17 @@ xrdp_mcs_send(struct xrdp_mcs *self, struct stream *s, int chan) * Internal help function to close the socket * @param self */ -void close_rdp_socket(struct xrdp_mcs *self) +void APP_CC +close_rdp_socket(struct xrdp_mcs *self) { - if(self->iso_layer->tcp_layer) + if (self->iso_layer != 0) { - if(self->iso_layer->tcp_layer->trans) + if (self->iso_layer->trans != 0) { - g_tcp_close(self->iso_layer->tcp_layer->trans->sck); - self->iso_layer->tcp_layer->trans->sck = 0 ; + g_tcp_close(self->iso_layer->trans->sck); + self->iso_layer->trans->sck = 0 ; g_writeln("xrdp_mcs_disconnect - socket closed"); - return ; + return; } } g_writeln("Failed to close socket"); diff --git a/libxrdp/xrdp_orders.c b/libxrdp/xrdp_orders.c index 0e2d90d2..317e1135 100644 --- a/libxrdp/xrdp_orders.c +++ b/libxrdp/xrdp_orders.c @@ -2570,8 +2570,16 @@ xrdp_orders_send_bitmap2(struct xrdp_orders *self, init_stream(temp_s, 16384); p = s->p; i = height; - lines_sending = xrdp_bitmap_compress(data, width, height, s, bpp, 16384, - i - 1, temp_s, e); + if (bpp > 24) + { + lines_sending = xrdp_bitmap32_compress(data, width, height, s, bpp, 16384, + i - 1, temp_s, e); + } + else + { + lines_sending = xrdp_bitmap_compress(data, width, height, s, bpp, 16384, + i - 1, temp_s, e); + } if (lines_sending != height) { diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index 9147287e..ec882f4e 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,41 +23,9 @@ #if defined(XRDP_NEUTRINORDP) #include <freerdp/codec/rfx.h> +#include <freerdp/constants.h> #endif -/* some compilers need unsigned char to avoid warnings */ -static tui8 g_unknown1[172] = -{ - 0xff, 0x02, 0xb6, 0x00, 0x28, 0x00, 0x00, 0x00, - 0x27, 0x00, 0x27, 0x00, 0x03, 0x00, 0x04, 0x00, - 0x00, 0x00, 0x26, 0x00, 0x01, 0x00, 0x1e, 0x00, - 0x02, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x1d, 0x00, - 0x04, 0x00, 0x27, 0x00, 0x05, 0x00, 0x0b, 0x00, - 0x06, 0x00, 0x28, 0x00, 0x08, 0x00, 0x21, 0x00, - 0x09, 0x00, 0x20, 0x00, 0x0a, 0x00, 0x22, 0x00, - 0x0b, 0x00, 0x25, 0x00, 0x0c, 0x00, 0x24, 0x00, - 0x0d, 0x00, 0x23, 0x00, 0x0e, 0x00, 0x19, 0x00, - 0x0f, 0x00, 0x16, 0x00, 0x10, 0x00, 0x15, 0x00, - 0x11, 0x00, 0x1c, 0x00, 0x12, 0x00, 0x1b, 0x00, - 0x13, 0x00, 0x1a, 0x00, 0x14, 0x00, 0x17, 0x00, - 0x15, 0x00, 0x18, 0x00, 0x16, 0x00, 0x0e, 0x00, - 0x18, 0x00, 0x0c, 0x00, 0x19, 0x00, 0x0d, 0x00, - 0x1a, 0x00, 0x12, 0x00, 0x1b, 0x00, 0x14, 0x00, - 0x1f, 0x00, 0x13, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x21, 0x00, 0x0a, 0x00, 0x22, 0x00, 0x06, 0x00, - 0x23, 0x00, 0x07, 0x00, 0x24, 0x00, 0x08, 0x00, - 0x25, 0x00, 0x09, 0x00, 0x26, 0x00, 0x04, 0x00, - 0x27, 0x00, 0x03, 0x00, 0x28, 0x00, 0x02, 0x00, - 0x29, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x05, 0x00, - 0x2b, 0x00, 0x2a, 0x00 -}; - -/* some compilers need unsigned char to avoid warnings */ -/* -static tui8 g_unknown2[8] = -{ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00 }; -*/ - /*****************************************************************************/ static int APP_CC xrdp_rdp_read_config(struct xrdp_client_info *client_info) @@ -112,6 +80,10 @@ xrdp_rdp_read_config(struct xrdp_client_info *client_info) { client_info->crypt_level = 3; } + else if (g_strcasecmp(value, "fips") == 0) + { + client_info->crypt_level = 4; + } else { log_message(LOG_LEVEL_ALWAYS,"Warning: Your configured crypt level is" @@ -226,8 +198,10 @@ xrdp_rdp_create(struct xrdp_session *session, struct trans *trans) /* read ini settings */ xrdp_rdp_read_config(&self->client_info); /* create sec layer */ - self->sec_layer = xrdp_sec_create(self, trans, self->client_info.crypt_level, - self->client_info.channel_code, self->client_info.multimon); + self->sec_layer = xrdp_sec_create(self, trans, + self->client_info.crypt_level, + self->client_info.channel_code, + self->client_info.multimon); /* default 8 bit v1 color bitmap cache entries and size */ self->client_info.cache1_entries = 600; self->client_info.cache1_size = 256; @@ -333,7 +307,10 @@ xrdp_rdp_recv(struct xrdp_rdp *self, struct stream *s, int *code) } else { - g_writeln("Wrong channel Id to be handled by xrdp_channel_process %d", chan); + if (chan != 1) + { + g_writeln("Wrong channel Id to be handled by xrdp_channel_process %d", chan); + } } s->next_packet = 0; @@ -515,69 +492,6 @@ xrdp_rdp_send_data_update_sync(struct xrdp_rdp *self) } /*****************************************************************************/ -static int APP_CC -xrdp_rdp_parse_client_mcs_data(struct xrdp_rdp *self) -{ - struct stream *p = (struct stream *)NULL; - int i = 0; - - p = &(self->sec_layer->client_mcs_data); - p->p = p->data; - if (!s_check_rem(p, 31 + 2 + 2 + 120 + 2)) - { - g_writeln("xrdp_rdp_parse_client_mcs_data: error"); - return 1; - } - in_uint8s(p, 31); - in_uint16_le(p, self->client_info.width); - in_uint16_le(p, self->client_info.height); - in_uint8s(p, 120); - self->client_info.bpp = 8; - in_uint16_le(p, i); - - switch (i) - { - case 0xca01: - if (!s_check_rem(p, 6 + 1)) - { - return 1; - } - in_uint8s(p, 6); - in_uint8(p, i); - - if (i > 8) - { - self->client_info.bpp = i; - } - - break; - case 0xca02: - self->client_info.bpp = 15; - break; - case 0xca03: - self->client_info.bpp = 16; - break; - case 0xca04: - self->client_info.bpp = 24; - break; - } - - if (self->client_info.max_bpp > 0) - { - if (self->client_info.bpp > self->client_info.max_bpp) - { - self->client_info.bpp = self->client_info.max_bpp; - } - } - - p->p = p->data; - DEBUG(("client width %d, client height %d bpp %d", - self->client_info.width, self->client_info.height, - self->client_info.bpp)); - return 0; -} - -/*****************************************************************************/ int APP_CC xrdp_rdp_incoming(struct xrdp_rdp *self) { @@ -587,19 +501,15 @@ xrdp_rdp_incoming(struct xrdp_rdp *self) { return 1; } - self->mcs_channel = self->sec_layer->mcs_layer->userid + MCS_USERCHANNEL_BASE; - xrdp_rdp_parse_client_mcs_data(self); DEBUG(("out xrdp_rdp_incoming mcs channel %d", self->mcs_channel)); - g_strncpy(self->client_info.client_addr, - self->sec_layer->mcs_layer->iso_layer->tcp_layer->trans->addr, + self->sec_layer->mcs_layer->iso_layer->trans->addr, sizeof(self->client_info.client_addr) - 1); g_strncpy(self->client_info.client_port, - self->sec_layer->mcs_layer->iso_layer->tcp_layer->trans->port, + self->sec_layer->mcs_layer->iso_layer->trans->port, sizeof(self->client_info.client_port) - 1); - return 0; } @@ -1572,7 +1482,7 @@ xrdp_rdp_process_screen_update(struct xrdp_rdp *self, struct stream *s) /*****************************************************************************/ static int APP_CC -xrdp_rdp_send_unknown1(struct xrdp_rdp *self) +xrdp_rdp_send_fontmap(struct xrdp_rdp *self) { struct stream *s; @@ -1585,7 +1495,11 @@ xrdp_rdp_send_unknown1(struct xrdp_rdp *self) return 1; } - out_uint8a(s, g_unknown1, 172); + out_uint16_le(s, 0); /* numberEntries */ + out_uint16_le(s, 0); /* totalNumEntries */ + out_uint16_le(s, 0x3); /* mapFlags (sequence flags) */ + out_uint16_le(s, 0x4); /* entrySize */ + s_mark_end(s); if (xrdp_rdp_send_data(self, s, 0x28) != 0) @@ -1597,7 +1511,45 @@ xrdp_rdp_send_unknown1(struct xrdp_rdp *self) free_stream(s); return 0; } +/*****************************************************************************/ +int APP_CC +xrdp_rdp_send_monitorlayout(struct xrdp_rdp *self) +{ + struct stream *s; + int i; + + make_stream(s); + init_stream(s, 8192); + + if (xrdp_rdp_init_data(self, s) != 0) + { + free_stream(s); + return 1; + } + + out_uint32_le(s, self->client_info.monitorCount); /* MonitorCount */ + /* TODO: validate for allowed monitors in terminal server (maybe by config?) */ + for (i = 0; i < self->client_info.monitorCount; i++) + { + out_uint32_le(s, self->client_info.minfo[i].left); + out_uint32_le(s, self->client_info.minfo[i].top); + out_uint32_le(s, self->client_info.minfo[i].right); + out_uint32_le(s, self->client_info.minfo[i].bottom); + out_uint32_le(s, self->client_info.minfo[i].is_primary); + } + + s_mark_end(s); + + if (xrdp_rdp_send_data(self, s, 0x37) != 0) + { + free_stream(s); + return 1; + } + + free_stream(s); + return 0; +} /*****************************************************************************/ static int APP_CC xrdp_rdp_process_data_font(struct xrdp_rdp *self, struct stream *s) @@ -1605,18 +1557,20 @@ xrdp_rdp_process_data_font(struct xrdp_rdp *self, struct stream *s) int seq; DEBUG(("in xrdp_rdp_process_data_font")); - in_uint8s(s, 2); /* num of fonts */ - in_uint8s(s, 2); /* unknown */ - in_uint16_le(s, seq); + in_uint8s(s, 2); /* NumberFonts: 0x0, SHOULD be set to 0 */ + in_uint8s(s, 2); /* TotalNumberFonts: 0x0, SHOULD be set to 0 */ + in_uint16_le(s, seq); /* ListFlags */ /* 419 client sends Seq 1, then 2 */ /* 2600 clients sends only Seq 3 */ if (seq == 2 || seq == 3) /* after second font message, we are up and */ { /* running */ - DEBUG(("sending unknown1")); - xrdp_rdp_send_unknown1(self); + DEBUG(("sending fontmap")); + xrdp_rdp_send_fontmap(self); + self->session->up_and_running = 1; + g_writeln("yeah, up_and_running"); DEBUG(("up_and_running set")); xrdp_rdp_send_data_update_sync(self); } diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index f52a080d..a4fe8c5a 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,12 @@ #include "libxrdp.h" #include "log.h" +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { g_write _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { g_writeln _args ; } } while (0) + /* some compilers need unsigned char to avoid warnings */ static tui8 g_pad_54[40] = { @@ -100,6 +106,83 @@ static tui8 g_lic3[20] = 0xf3, 0x99, 0x00, 0x00 }; +static const tui8 g_fips_reverse_table[256] = +{ + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff +}; + +static const tui8 g_fips_oddparity_table[256] = +{ + 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x07, 0x07, + 0x08, 0x08, 0x0b, 0x0b, 0x0d, 0x0d, 0x0e, 0x0e, + 0x10, 0x10, 0x13, 0x13, 0x15, 0x15, 0x16, 0x16, + 0x19, 0x19, 0x1a, 0x1a, 0x1c, 0x1c, 0x1f, 0x1f, + 0x20, 0x20, 0x23, 0x23, 0x25, 0x25, 0x26, 0x26, + 0x29, 0x29, 0x2a, 0x2a, 0x2c, 0x2c, 0x2f, 0x2f, + 0x31, 0x31, 0x32, 0x32, 0x34, 0x34, 0x37, 0x37, + 0x38, 0x38, 0x3b, 0x3b, 0x3d, 0x3d, 0x3e, 0x3e, + 0x40, 0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46, + 0x49, 0x49, 0x4a, 0x4a, 0x4c, 0x4c, 0x4f, 0x4f, + 0x51, 0x51, 0x52, 0x52, 0x54, 0x54, 0x57, 0x57, + 0x58, 0x58, 0x5b, 0x5b, 0x5d, 0x5d, 0x5e, 0x5e, + 0x61, 0x61, 0x62, 0x62, 0x64, 0x64, 0x67, 0x67, + 0x68, 0x68, 0x6b, 0x6b, 0x6d, 0x6d, 0x6e, 0x6e, + 0x70, 0x70, 0x73, 0x73, 0x75, 0x75, 0x76, 0x76, + 0x79, 0x79, 0x7a, 0x7a, 0x7c, 0x7c, 0x7f, 0x7f, + 0x80, 0x80, 0x83, 0x83, 0x85, 0x85, 0x86, 0x86, + 0x89, 0x89, 0x8a, 0x8a, 0x8c, 0x8c, 0x8f, 0x8f, + 0x91, 0x91, 0x92, 0x92, 0x94, 0x94, 0x97, 0x97, + 0x98, 0x98, 0x9b, 0x9b, 0x9d, 0x9d, 0x9e, 0x9e, + 0xa1, 0xa1, 0xa2, 0xa2, 0xa4, 0xa4, 0xa7, 0xa7, + 0xa8, 0xa8, 0xab, 0xab, 0xad, 0xad, 0xae, 0xae, + 0xb0, 0xb0, 0xb3, 0xb3, 0xb5, 0xb5, 0xb6, 0xb6, + 0xb9, 0xb9, 0xba, 0xba, 0xbc, 0xbc, 0xbf, 0xbf, + 0xc1, 0xc1, 0xc2, 0xc2, 0xc4, 0xc4, 0xc7, 0xc7, + 0xc8, 0xc8, 0xcb, 0xcb, 0xcd, 0xcd, 0xce, 0xce, + 0xd0, 0xd0, 0xd3, 0xd3, 0xd5, 0xd5, 0xd6, 0xd6, + 0xd9, 0xd9, 0xda, 0xda, 0xdc, 0xdc, 0xdf, 0xdf, + 0xe0, 0xe0, 0xe3, 0xe3, 0xe5, 0xe5, 0xe6, 0xe6, + 0xe9, 0xe9, 0xea, 0xea, 0xec, 0xec, 0xef, 0xef, + 0xf1, 0xf1, 0xf2, 0xf2, 0xf4, 0xf4, 0xf7, 0xf7, + 0xf8, 0xf8, 0xfb, 0xfb, 0xfd, 0xfd, 0xfe, 0xfe +}; + +static const tui8 g_fips_ivec[8] = +{ + 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF +}; + /*****************************************************************************/ static void APP_CC hex_str_to_bin(char *in, char *out, int out_len) @@ -145,22 +228,25 @@ xrdp_sec_create(struct xrdp_rdp *owner, struct trans *trans, int crypt_level, DEBUG((" in xrdp_sec_create")); self = (struct xrdp_sec *)g_malloc(sizeof(struct xrdp_sec), 1); self->rdp_layer = owner; - self->rc4_key_size = 1; /* 1 = 40 bit, 2 = 128 bit */ - self->crypt_level = 1; /* 1, 2, 3 = low, medium, high */ - + self->crypt_method = CRYPT_METHOD_NONE; + self->crypt_level = CRYPT_LEVEL_NONE; switch (crypt_level) { - case 1: - self->rc4_key_size = 1; - self->crypt_level = 1; + case 1: /* low */ + self->crypt_method = CRYPT_METHOD_40BIT; + self->crypt_level = CRYPT_LEVEL_LOW; + break; + case 2: /* medium */ + self->crypt_method = CRYPT_METHOD_40BIT; + self->crypt_level = CRYPT_LEVEL_CLIENT_COMPATIBLE; break; - case 2: - self->rc4_key_size = 1; - self->crypt_level = 2; + case 3: /* high */ + self->crypt_method = CRYPT_METHOD_128BIT; + self->crypt_level = CRYPT_LEVEL_HIGH; break; - case 3: - self->rc4_key_size = 2; - self->crypt_level = 3; + case 4: /* fips */ + self->crypt_method = CRYPT_METHOD_FIPS; + self->crypt_level = CRYPT_LEVEL_FIPS; break; default: g_writeln("Fatal : Illegal crypt_level"); @@ -204,6 +290,9 @@ xrdp_sec_delete(struct xrdp_sec *self) xrdp_mcs_delete(self->mcs_layer); ssl_rc4_info_delete(self->decrypt_rc4_info); /* TODO clear all data */ ssl_rc4_info_delete(self->encrypt_rc4_info); /* TODO clear all data */ + ssl_des3_info_delete(self->decrypt_fips_info); + ssl_des3_info_delete(self->encrypt_fips_info); + ssl_hmac_info_delete(self->sign_fips_info); g_free(self->client_mcs_data.data); g_free(self->server_mcs_data.data); /* Crypto information must always be cleared */ @@ -221,7 +310,11 @@ xrdp_sec_init(struct xrdp_sec *self, struct stream *s) return 1; } - if (self->crypt_level > 1) + if (self->crypt_level == CRYPT_LEVEL_FIPS) + { + s_push_layer(s, sec_hdr, 4 + 4 + 8); + } + else if (self->crypt_level > CRYPT_LEVEL_LOW) { s_push_layer(s, sec_hdr, 4 + 8); } @@ -283,8 +376,18 @@ xrdp_sec_update(char *key, char *update_key, int key_len) /*****************************************************************************/ static void APP_CC +xrdp_sec_fips_decrypt(struct xrdp_sec *self, char *data, int len) +{ + LLOGLN(10, ("xrdp_sec_fips_decrypt:")); + ssl_des3_decrypt(self->decrypt_fips_info, len, data, data); + self->decrypt_use_count++; +} + +/*****************************************************************************/ +static void APP_CC xrdp_sec_decrypt(struct xrdp_sec *self, char *data, int len) { + LLOGLN(10, ("xrdp_sec_decrypt:")); if (self->decrypt_use_count == 4096) { xrdp_sec_update(self->decrypt_key, self->decrypt_update_key, @@ -293,15 +396,24 @@ xrdp_sec_decrypt(struct xrdp_sec *self, char *data, int len) self->rc4_key_len); self->decrypt_use_count = 0; } - ssl_rc4_crypt(self->decrypt_rc4_info, data, len); self->decrypt_use_count++; } /*****************************************************************************/ static void APP_CC +xrdp_sec_fips_encrypt(struct xrdp_sec *self, char *data, int len) +{ + LLOGLN(10, ("xrdp_sec_fips_encrypt:")); + ssl_des3_encrypt(self->encrypt_fips_info, len, data, data); + self->encrypt_use_count++; +} + +/*****************************************************************************/ +static void APP_CC xrdp_sec_encrypt(struct xrdp_sec *self, char *data, int len) { + LLOGLN(10, ("xrdp_sec_encrypt:")); if (self->encrypt_use_count == 4096) { xrdp_sec_update(self->encrypt_key, self->encrypt_update_key, @@ -381,6 +493,8 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) { /* must be or error */ DEBUG(("xrdp_sec_process_logon_info: flags wrong, major error")); + LLOGLN(0, ("xrdp_sec_process_logon_info: flags wrong, likely decrypt " + "not working")); return 1; } @@ -429,6 +543,16 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) } in_uint16_le(s, len_user); + /* + * Microsoft's itap client running on Mac OS/Android + * always sends autologon credentials, even when user has not + * configured any + */ + if (len_user == 0) + { + self->rdp_layer->client_info.rdp_autologin = 0; + } + if (len_user > 511) { DEBUG(("ERROR [xrdp_sec_process_logon_info()]: len_user > 511")); @@ -557,8 +681,9 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) static int APP_CC xrdp_sec_send_lic_initial(struct xrdp_sec *self) { - struct stream *s = (struct stream *)NULL; + struct stream *s; + LLOGLN(10, ("xrdp_sec_send_lic_initial:")); make_stream(s); init_stream(s, 8192); @@ -697,12 +822,103 @@ xrdp_sec_hash_16(char *out, char *in, char *salt1, char *salt2) /*****************************************************************************/ static void APP_CC +fips_expand_key_bits(const char *in, char *out) +{ + tui8 buf[32]; + tui8 c; + int i; + int b; + int p; + int r; + + /* reverse every byte in the key */ + for (i = 0; i < 21; i++) + { + c = in[i]; + buf[i] = g_fips_reverse_table[c]; + } + /* insert a zero-bit after every 7th bit */ + for (i = 0, b = 0; i < 24; i++, b += 7) + { + p = b / 8; + r = b % 8; + if (r == 0) + { + out[i] = buf[p] & 0xfe; + } + else + { + /* c is accumulator */ + c = buf[p] << r; + c |= buf[p + 1] >> (8 - r); + out[i] = c & 0xfe; + } + } + /* reverse every byte */ + /* alter lsb so the byte has odd parity */ + for (i = 0; i < 24; i++) + { + c = out[i]; + c = g_fips_reverse_table[c]; + out[i] = g_fips_oddparity_table[c]; + } +} + +/****************************************************************************/ +static void APP_CC +xrdp_sec_fips_establish_keys(struct xrdp_sec *self) +{ + char server_encrypt_key[32]; + char server_decrypt_key[32]; + const char *fips_ivec; + void *sha1; + + LLOGLN(0, ("xrdp_sec_fips_establish_keys:")); + + sha1 = ssl_sha1_info_create(); + ssl_sha1_clear(sha1); + ssl_sha1_transform(sha1, self->client_random + 16, 16); + ssl_sha1_transform(sha1, self->server_random + 16, 16); + ssl_sha1_complete(sha1, server_decrypt_key); + + server_decrypt_key[20] = server_decrypt_key[0]; + fips_expand_key_bits(server_decrypt_key, self->fips_decrypt_key); + ssl_sha1_info_delete(sha1); + + sha1 = ssl_sha1_info_create(); + ssl_sha1_clear(sha1); + ssl_sha1_transform(sha1, self->client_random, 16); + ssl_sha1_transform(sha1, self->server_random, 16); + ssl_sha1_complete(sha1, server_encrypt_key); + server_encrypt_key[20] = server_encrypt_key[0]; + fips_expand_key_bits(server_encrypt_key, self->fips_encrypt_key); + ssl_sha1_info_delete(sha1); + + sha1 = ssl_sha1_info_create(); + ssl_sha1_clear(sha1); + ssl_sha1_transform(sha1, server_encrypt_key, 20); + ssl_sha1_transform(sha1, server_decrypt_key, 20); + ssl_sha1_complete(sha1, self->fips_sign_key); + ssl_sha1_info_delete(sha1); + + fips_ivec = (const char *) g_fips_ivec; + self->encrypt_fips_info = + ssl_des3_encrypt_info_create(self->fips_encrypt_key, fips_ivec); + self->decrypt_fips_info = + ssl_des3_decrypt_info_create(self->fips_decrypt_key, fips_ivec); + self->sign_fips_info = ssl_hmac_info_create(); +} + +/****************************************************************************/ +static void APP_CC xrdp_sec_establish_keys(struct xrdp_sec *self) { char session_key[48]; char temp_hash[48]; char input[48]; + LLOGLN(0, ("xrdp_sec_establish_keys:")); + g_memcpy(input, self->client_random, 24); g_memcpy(input + 24, self->server_random, 24); xrdp_sec_hash_48(temp_hash, input, self->client_random, @@ -715,7 +931,7 @@ xrdp_sec_establish_keys(struct xrdp_sec *self) xrdp_sec_hash_16(self->decrypt_key, session_key + 32, self->client_random, self->server_random); - if (self->rc4_key_size == 1) + if (self->crypt_method == CRYPT_METHOD_40BIT) { xrdp_sec_make_40bit(self->sign_key); xrdp_sec_make_40bit(self->encrypt_key); @@ -740,6 +956,8 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) { int flags; int len; + int ver; + int pad; DEBUG((" in xrdp_sec_recv")); @@ -758,12 +976,34 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) if (flags & SEC_ENCRYPT) /* 0x08 */ { - if (!s_check_rem(s, 8)) + if (self->crypt_level == CRYPT_LEVEL_FIPS) { - return 1; + if (!s_check_rem(s, 12)) + { + return 1; + } + in_uint16_le(s, len); + in_uint8(s, ver); + if ((len != 16) || (ver != 1)) + { + return 1; + } + in_uint8(s, pad); + LLOGLN(10, ("xrdp_sec_recv: len %d ver %d pad %d", len, ver, pad)); + in_uint8s(s, 8); /* signature(8) */ + LLOGLN(10, ("xrdp_sec_recv: data len %d", (int)(s->end - s->p))); + xrdp_sec_fips_decrypt(self, s->p, (int)(s->end - s->p)); + s->end -= pad; + } + else + { + if (!s_check_rem(s, 8)) + { + return 1; + } + in_uint8s(s, 8); /* signature(8) */ + xrdp_sec_decrypt(self, s->p, (int)(s->end - s->p)); } - in_uint8s(s, 8); /* signature */ - xrdp_sec_decrypt(self, s->p, (int)(s->end - s->p)); } if (flags & SEC_CLIENT_RANDOM) /* 0x01 */ @@ -776,7 +1016,14 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) in_uint8a(s, self->client_crypt_random, 64); xrdp_sec_rsa_op(self->client_random, self->client_crypt_random, self->pub_mod, self->pri_exp); - xrdp_sec_establish_keys(self); + if (self->crypt_level == CRYPT_LEVEL_FIPS) + { + xrdp_sec_fips_establish_keys(self); + } + else + { + xrdp_sec_establish_keys(self); + } *chan = 1; /* just set a non existing channel and exit */ DEBUG((" out xrdp_sec_recv")); return 0; @@ -843,6 +1090,23 @@ buf_out_uint32(char *buffer, int value) /*****************************************************************************/ /* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */ static void APP_CC +xrdp_sec_fips_sign(struct xrdp_sec *self, char *out, int out_len, + char *data, int data_len) +{ + char buf[20]; + char lenhdr[4]; + + buf_out_uint32(lenhdr, self->encrypt_use_count); + ssl_hmac_sha1_init(self->sign_fips_info, self->fips_sign_key, 20); + ssl_hmac_transform(self->sign_fips_info, data, data_len); + ssl_hmac_transform(self->sign_fips_info, lenhdr, 4); + ssl_hmac_complete(self->sign_fips_info, buf, 20); + g_memcpy(out, buf, out_len); +} + +/*****************************************************************************/ +/* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */ +static void APP_CC xrdp_sec_sign(struct xrdp_sec *self, char *out, int out_len, char *data, int data_len) { @@ -877,11 +1141,27 @@ int APP_CC xrdp_sec_send(struct xrdp_sec *self, struct stream *s, int chan) { int datalen; + int pad; + LLOGLN(10, ("xrdp_sec_send:")); DEBUG((" in xrdp_sec_send")); s_pop_layer(s, sec_hdr); - if (self->crypt_level > 1) + if (self->crypt_level == CRYPT_LEVEL_FIPS) + { + LLOGLN(10, ("xrdp_sec_send: fips")); + out_uint32_le(s, SEC_ENCRYPT); + datalen = (int)((s->end - s->p) - 12); + out_uint16_le(s, 16); /* crypto header size */ + out_uint8(s, 1); /* fips version */ + pad = (8 - (datalen % 8)) & 7; + g_memset(s->end, 0, pad); + s->end += pad; + out_uint8(s, pad); /* fips pad */ + xrdp_sec_fips_sign(self, s->p, 8, s->p + 8, datalen); + xrdp_sec_fips_encrypt(self, s->p + 8, datalen + pad); + } + else if (self->crypt_level > CRYPT_LEVEL_LOW) { out_uint32_le(s, SEC_ENCRYPT); datalen = (int)((s->end - s->p) - 8); @@ -903,6 +1183,235 @@ xrdp_sec_send(struct xrdp_sec *self, struct stream *s, int chan) } /*****************************************************************************/ +/* http://msdn.microsoft.com/en-us/library/cc240510.aspx + 2.2.1.3.2 Client Core Data (TS_UD_CS_CORE) */ +static int APP_CC +xrdp_sec_process_mcs_data_CS_CORE(struct xrdp_sec* self, struct stream* s) +{ + int colorDepth; + int postBeta2ColorDepth; + int highColorDepth; + int supportedColorDepths; + int earlyCapabilityFlags; + + in_uint8s(s, 4); /* version */ + in_uint16_le(s, self->rdp_layer->client_info.width); + in_uint16_le(s, self->rdp_layer->client_info.height); + in_uint16_le(s, colorDepth); + g_writeln("colorDepth 0x%4.4x (0xca00 4bpp 0xca01 8bpp)", colorDepth); + switch (colorDepth) + { + case 0xca00: /* RNS_UD_COLOR_4BPP */ + self->rdp_layer->client_info.bpp = 4; + break; + case 0xca01: /* RNS_UD_COLOR_8BPP */ + self->rdp_layer->client_info.bpp = 8; + break; + } + in_uint8s(s, 2); /* SASSequence */ + in_uint8s(s, 4); /* keyboardLayout */ + in_uint8s(s, 4); /* clientBuild */ + in_uint8s(s, 32); /* clientName */ + in_uint8s(s, 4); /* keyboardType */ + in_uint8s(s, 4); /* keyboardSubType */ + in_uint8s(s, 4); /* keyboardFunctionKey */ + in_uint8s(s, 64); /* imeFileName */ + in_uint16_le(s, postBeta2ColorDepth); + g_writeln("postBeta2ColorDepth 0x%4.4x (0xca00 4bpp 0xca01 8bpp " + "0xca02 15bpp 0xca03 16bpp 0xca04 24bpp)", postBeta2ColorDepth); + + switch (postBeta2ColorDepth) + { + case 0xca00: /* RNS_UD_COLOR_4BPP */ + self->rdp_layer->client_info.bpp = 4; + break; + case 0xca01: /* RNS_UD_COLOR_8BPP */ + self->rdp_layer->client_info.bpp = 8; + break; + case 0xca02: /* RNS_UD_COLOR_16BPP_555 */ + self->rdp_layer->client_info.bpp = 15; + break; + case 0xca03: /* RNS_UD_COLOR_16BPP_565 */ + self->rdp_layer->client_info.bpp = 16; + break; + case 0xca04: /* RNS_UD_COLOR_24BPP */ + self->rdp_layer->client_info.bpp = 24; + break; + } + if (!s_check_rem(s, 2)) + { + return 0; + } + in_uint8s(s, 2); /* clientProductId */ + + if (!s_check_rem(s, 4)) + { + return 0; + } + in_uint8s(s, 4); /* serialNumber */ + + if (!s_check_rem(s, 2)) + { + return 0; + } + in_uint16_le(s, highColorDepth); + g_writeln("highColorDepth 0x%4.4x (0x0004 4bpp 0x0008 8bpp 0x000f 15bpp " + "0x0010 16 bpp 0x0018 24bpp)", highColorDepth); + self->rdp_layer->client_info.bpp = highColorDepth; + + if (!s_check_rem(s, 2)) + { + return 0; + } + in_uint16_le(s, supportedColorDepths); + g_writeln("supportedColorDepths 0x%4.4x (0x0001 24bpp 0x0002 16bpp " + "0x0004 15bpp 0x0008 32bpp)", supportedColorDepths); + + if (!s_check_rem(s, 2)) + { + return 0; + } + in_uint16_le(s, earlyCapabilityFlags); + self->rdp_layer->client_info.mcs_early_capability_flags = earlyCapabilityFlags; + g_writeln("earlyCapabilityFlags 0x%4.4x (0x0002 want32)", + earlyCapabilityFlags); + if ((earlyCapabilityFlags & 0x0002) && (supportedColorDepths & 0x0008)) + { + self->rdp_layer->client_info.bpp = 32; + } + + if (!s_check_rem(s, 64)) + { + return 0; + } + in_uint8s(s, 64); /* clientDigProductId */ + + if (!s_check_rem(s, 1)) + { + return 0; + } + in_uint8(s, self->rdp_layer->client_info.mcs_connection_type); /* connectionType */ + g_writeln("got client client connection type 0x%8.8x", + self->rdp_layer->client_info.mcs_connection_type); + + if (!s_check_rem(s, 1)) + { + return 0; + } + in_uint8s(s, 1); /* pad1octet */ + + if (!s_check_rem(s, 4)) + { + return 0; + } + in_uint8s(s, 4); /* serverSelectedProtocol */ + + if (!s_check_rem(s, 4)) + { + return 0; + } + in_uint8s(s, 4); /* desktopPhysicalWidth */ + + if (!s_check_rem(s, 4)) + { + return 0; + } + in_uint8s(s, 4); /* desktopPhysicalHeight */ + + if (!s_check_rem(s, 2)) + { + return 0; + } + in_uint8s(s, 2); /* reserved */ + + return 0; +} + +/*****************************************************************************/ +static int APP_CC +xrdp_sec_process_mcs_data_CS_SECURITY(struct xrdp_sec *self, struct stream* s) +{ + int crypt_method; + int found; + + g_writeln("xrdp_sec_process_mcs_data_CS_SECURITY:"); + in_uint32_le(s, crypt_method); + if (crypt_method & CRYPT_METHOD_40BIT) + { + g_writeln(" client supports 40 bit encryption"); + } + if (crypt_method & CRYPT_METHOD_128BIT) + { + g_writeln(" client supports 128 bit encryption"); + } + if (crypt_method & CRYPT_METHOD_56BIT) + { + g_writeln(" client supports 56 bit encryption"); + } + if (crypt_method & CRYPT_METHOD_FIPS) + { + g_writeln(" client supports fips encryption"); + } + found = 0; + if ((found == 0) && + (self->crypt_method & CRYPT_METHOD_FIPS) && + (self->crypt_level == CRYPT_LEVEL_FIPS)) + { + if (crypt_method & CRYPT_METHOD_FIPS) + { + g_writeln(" client and server support fips, using fips"); + self->crypt_method = CRYPT_METHOD_FIPS; + self->crypt_level = CRYPT_LEVEL_FIPS; + found = 1; + } + } + if ((found == 0) && + (self->crypt_method & CRYPT_METHOD_128BIT) && + (self->crypt_level == CRYPT_LEVEL_HIGH)) + { + if (crypt_method & CRYPT_METHOD_128BIT) + { + g_writeln(" client and server support high crypt, using " + "high crypt"); + self->crypt_method = CRYPT_METHOD_128BIT; + self->crypt_level = CRYPT_LEVEL_HIGH; + found = 1; + } + } + if ((found == 0) && + (self->crypt_method & CRYPT_METHOD_40BIT) && + (self->crypt_level == CRYPT_LEVEL_CLIENT_COMPATIBLE)) + { + if (crypt_method & CRYPT_METHOD_40BIT) + { + g_writeln(" client and server support medium crypt, using " + "medium crypt"); + self->crypt_method = CRYPT_METHOD_40BIT; + self->crypt_level = CRYPT_LEVEL_CLIENT_COMPATIBLE; + found = 1; + } + } + if ((found == 0) && + (self->crypt_method & CRYPT_METHOD_40BIT) && + (self->crypt_level == CRYPT_LEVEL_LOW)) + { + if (crypt_method & CRYPT_METHOD_40BIT) + { + g_writeln(" client and server support low crypt, using " + "low crypt"); + self->crypt_method = CRYPT_METHOD_40BIT; + self->crypt_level = CRYPT_LEVEL_LOW; + found = 1; + } + } + if (found == 0) + { + g_writeln(" no security"); + } + return 0; +} + +/*****************************************************************************/ /* this adds the mcs channels in the list of channels to be used when creating the server mcs data */ static int APP_CC @@ -951,6 +1460,7 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s) return 0; } + /*****************************************************************************/ /* reads the client monitors data */ static int APP_CC @@ -1006,6 +1516,7 @@ xrdp_sec_process_mcs_data_monitors(struct xrdp_sec *self, struct stream *s) } return 0; } + /*****************************************************************************/ /* process client mcs data, we need some things in here to create the server mcs data */ @@ -1033,42 +1544,73 @@ xrdp_sec_process_mcs_data(struct xrdp_sec *self) in_uint16_le(s, tag); in_uint16_le(s, size); - if (size < 4 || !s_check_rem(s, size - 4)) + if ((size < 4) || (!s_check_rem(s, size - 4))) { - g_writeln("error in xrdp_sec_process_mcs_data tag %d size %d", - tag, size); + LLOGLN(0, ("error in xrdp_sec_process_mcs_data tag %d size %d", + tag, size)); break; } + LLOGLN(10, ("xrdp_sec_process_mcs_data: 0x%8.8x", tag)); switch (tag) { - case SEC_TAG_CLI_INFO: + case SEC_TAG_CLI_INFO: /* CS_CORE 0xC001 */ + if (xrdp_sec_process_mcs_data_CS_CORE(self, s) != 0) + { + return 1; + } break; - case SEC_TAG_CLI_CRYPT: + case SEC_TAG_CLI_CRYPT: /* CS_SECURITY 0xC002 */ + if (xrdp_sec_process_mcs_data_CS_SECURITY(self, s) != 0) + { + return 1; + } break; - case SEC_TAG_CLI_CHANNELS: + case SEC_TAG_CLI_CHANNELS: /* CS_NET 0xC003 */ if (xrdp_sec_process_mcs_data_channels(self, s) != 0) { return 1; } break; - case SEC_TAG_CLI_4: + case SEC_TAG_CLI_4: /* CS_CLUSTER 0xC004 */ break; - case SEC_TAG_CLI_MONITOR: + case SEC_TAG_CLI_MONITOR: /* CS_MONITOR 0xC005 */ if (xrdp_sec_process_mcs_data_monitors(self, s) != 0) { return 1; } break; + /* CS_MCS_MSGCHANNEL 0xC006 + CS_MONITOR_EX 0xC008 + CS_MULTITRANSPORT 0xC00A + SC_CORE 0x0C01 + SC_SECURITY 0x0C02 + SC_NET 0x0C03 + SC_MCS_MSGCHANNEL 0x0C04 + SC_MULTITRANSPORT 0x0C08 */ default: - g_writeln("error unknown xrdp_sec_process_mcs_data tag %d size %d", - tag, size); + LLOGLN(0, ("error unknown xrdp_sec_process_mcs_data " + "tag 0x%4.4x size %d", tag, size)); break; } s->p = hold_p + size; } + if (self->rdp_layer->client_info.max_bpp > 0) + { + if (self->rdp_layer->client_info.bpp > + self->rdp_layer->client_info.max_bpp) + { + LLOGLN(0, ("xrdp_rdp_parse_client_mcs_data: client asked " + "for %dbpp connection but configuration is limited " + "to %dbpp", self->rdp_layer->client_info.bpp, + self->rdp_layer->client_info.max_bpp)); + self->rdp_layer->client_info.bpp = + self->rdp_layer->client_info.max_bpp; + } + } + /* set p to beginning */ s->p = s->data; return 0; @@ -1152,9 +1694,8 @@ xrdp_sec_out_mcs_data(struct xrdp_sec *self) out_uint16_le(s, SEC_TAG_SRV_CRYPT); out_uint16_le(s, 0x00ec); /* len is 236 */ - out_uint32_le(s, self->rc4_key_size); /* key len 1 = 40 bit 2 = 128 bit */ - out_uint32_le(s, self->crypt_level); /* crypt level 1 = low 2 = medium */ - /* 3 = high */ + out_uint32_le(s, self->crypt_method); + out_uint32_le(s, self->crypt_level); out_uint32_le(s, 32); /* 32 bytes random len */ out_uint32_le(s, 0xb8); /* 184 bytes rsa info(certificate) len */ out_uint8a(s, self->server_random, 32); @@ -1232,6 +1773,15 @@ xrdp_sec_in_mcs_data(struct xrdp_sec *self) } in_uint8s(s, 39); in_uint32_le(s, client_info->keylayout); + /* get keyboard type / subtype */ + s->p = s->data; + if (!s_check_rem(s, 79 + 8)) + { + return 1; + } + in_uint8s(s, 79); + in_uint32_le(s, client_info->keyboard_type); + in_uint32_le(s, client_info->keyboard_subtype); s->p = s->data; return 0; } @@ -1247,8 +1797,8 @@ xrdp_sec_incoming(struct xrdp_sec *self) char *value = NULL; char key_file[256]; + LLOGLN(10, ("xrdp_sec_incoming:")); g_memset(key_file, 0, sizeof(char) * 256); - DEBUG((" in xrdp_sec_incoming")); g_random(self->server_random, 32); items = list_create(); @@ -1311,6 +1861,7 @@ xrdp_sec_incoming(struct xrdp_sec *self) { return 1; } + LLOGLN(10, ("xrdp_sec_incoming: out")); return 0; } diff --git a/libxrdp/xrdp_tcp.c b/libxrdp/xrdp_tcp.c deleted file mode 100644 index 473f3deb..00000000 --- a/libxrdp/xrdp_tcp.c +++ /dev/null @@ -1,89 +0,0 @@ -/** - * xrdp: A Remote Desktop Protocol server. - * - * Copyright (C) Jay Sorg 2004-2013 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * tcp layer - */ - -#include "libxrdp.h" - -/*****************************************************************************/ -struct xrdp_tcp *APP_CC -xrdp_tcp_create(struct xrdp_iso *owner, struct trans *trans) -{ - struct xrdp_tcp *self; - - DEBUG((" in xrdp_tcp_create")); - self = (struct xrdp_tcp *)g_malloc(sizeof(struct xrdp_tcp), 1); - self->iso_layer = owner; - self->trans = trans; - DEBUG((" out xrdp_tcp_create")); - return self; -} - -/*****************************************************************************/ -void APP_CC -xrdp_tcp_delete(struct xrdp_tcp *self) -{ - g_free(self); -} - -/*****************************************************************************/ -/* get out stream ready for data */ -/* returns error */ -int APP_CC -xrdp_tcp_init(struct xrdp_tcp *self, struct stream *s) -{ - init_stream(s, 8192); - return 0; -} - -/*****************************************************************************/ -/* returns error */ -int APP_CC -xrdp_tcp_recv(struct xrdp_tcp *self, struct stream *s, int len) -{ - DEBUG((" in xrdp_tcp_recv, gota get %d bytes", len)); - init_stream(s, len); - - if (trans_force_read_s(self->trans, s, len) != 0) - { - DEBUG((" error in trans_force_read_s")); - return 1; - } - - DEBUG((" out xrdp_tcp_recv")); - return 0; -} - -/*****************************************************************************/ -/* returns error */ -int APP_CC -xrdp_tcp_send(struct xrdp_tcp *self, struct stream *s) -{ - int len; - len = s->end - s->data; - DEBUG((" in xrdp_tcp_send, gota send %d bytes", len)); - - if (trans_force_write_s(self->trans, s) != 0) - { - DEBUG((" error in trans_force_write_s")); - return 1; - } - - DEBUG((" out xrdp_tcp_send, sent %d bytes ok", len)); - return 0; -} diff --git a/neutrinordp/xrdp-neutrinordp.c b/neutrinordp/xrdp-neutrinordp.c index f0424c26..3602e57c 100644 --- a/neutrinordp/xrdp-neutrinordp.c +++ b/neutrinordp/xrdp-neutrinordp.c @@ -17,17 +17,17 @@ * limitations under the License. */ -#include <freerdp/settings.h> -#include <X11/Xlib.h> #include "xrdp-neutrinordp.h" #include "xrdp-color.h" #include "xrdp_rail.h" #include "log.h" +#include <freerdp/settings.h> +#include <X11/Xlib.h> #ifdef XRDP_DEBUG #define LOG_LEVEL 99 #else -#define LOG_LEVEL 1 +#define LOG_LEVEL 10 #endif #define LLOG(_level, _args) \ @@ -1478,8 +1478,10 @@ lrail_WindowCreate(rdpContext *context, WINDOW_ORDER_INFO *orderInfo, int index; struct mod *mod; struct rail_window_state_order wso; + UNICONV* uniconv; LLOGLN(0, ("llrail_WindowCreate:")); + uniconv = freerdp_uniconv_new(); mod = ((struct mod_context *)context)->modi; memset(&wso, 0, sizeof(wso)); /* copy the window state order */ @@ -1490,7 +1492,8 @@ lrail_WindowCreate(rdpContext *context, WINDOW_ORDER_INFO *orderInfo, if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TITLE) { - freerdp_UnicodeToAsciiAlloc(window_state->titleInfo.string, &wso.title_info, window_state->titleInfo.length / 2); + wso.title_info = freerdp_uniconv_in(uniconv, + window_state->titleInfo.string, window_state->titleInfo.length); } LLOGLN(0, ("lrail_WindowCreate: %s", wso.title_info)); @@ -1616,29 +1619,31 @@ lrail_NotifyIconCreate(rdpContext *context, WINDOW_ORDER_INFO *orderInfo, { struct mod *mod; struct rail_notify_state_order rnso; + UNICONV* uniconv; LLOGLN(0, ("lrail_NotifyIconCreate:")); - + uniconv = freerdp_uniconv_new(); mod = ((struct mod_context *)context)->modi; memset(&rnso, 0, sizeof(rnso)); rnso.version = notify_icon_state->version; if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_TIP) - { - 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.tool_tip = freerdp_uniconv_in(uniconv, + notify_icon_state->toolTip.string, notify_icon_state->toolTip.length); + } + if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP) + { + rnso.infotip.timeout = notify_icon_state->infoTip.timeout; + rnso.infotip.flags = notify_icon_state->infoTip.flags; + rnso.infotip.text = freerdp_uniconv_in(uniconv, + notify_icon_state->infoTip.text.string, + notify_icon_state->infoTip.text.length); + rnso.infotip.title = freerdp_uniconv_in(uniconv, + notify_icon_state->infoTip.title.string, + notify_icon_state->infoTip.title.length); + } rnso.state = notify_icon_state->state; rnso.icon_cache_entry = notify_icon_state->icon.cacheEntry; @@ -1,5 +1,5 @@ -xrdp 0.7.0 +xrdp 0.9.0 Credits This project is very much dependent on FreeRDP(was rdesktop), the work of diff --git a/sesman/chansrv/Makefile.am b/sesman/chansrv/Makefile.am index 2d73f05c..9aa3ebe7 100644 --- a/sesman/chansrv/Makefile.am +++ b/sesman/chansrv/Makefile.am @@ -26,6 +26,11 @@ EXTRA_DEFINES += -DXRDP_FUSE EXTRA_LIBS += -lfuse endif +if XRDP_LOAD_PULSE_MODULES +EXTRA_DEFINES += -DXRDP_LOAD_PULSE_MODULES +EXTRA_LIBS += -lpulse +endif + AM_CFLAGS = \ -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \ -DXRDP_SBIN_PATH=\"${sbindir}\" \ diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index 01c6a43d..a89957ba 100644 --- a/sesman/chansrv/chansrv.c +++ b/sesman/chansrv/chansrv.c @@ -46,7 +46,6 @@ static int g_rdpsnd_index = -1; static int g_rdpdr_index = -1; static int g_rail_index = -1; static int g_drdynvc_index = -1; -static int g_sent = 0; /* if sent data to xrdp, waiting response */ /* state info for dynamic virtual channels */ static struct xrdp_api_data *g_dvc_channels[MAX_DVC_CHANNELS]; @@ -95,7 +94,7 @@ 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); @@ -297,7 +296,6 @@ send_data_from_chan_item(struct chan_item *chan_item) s_mark_end(s); 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_write_copy(g_con_trans); if (error != 0) @@ -363,10 +361,7 @@ send_channel_data(int chan_id, char *data, int size) if (g_chan_items[index].id == chan_id) { add_data_to_chan_item(g_chan_items + index, data, size); - if (g_sent == 0) - { - check_chan_items(); - } + check_chan_items(); return 0; } } @@ -380,10 +375,10 @@ 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 */ @@ -551,6 +546,7 @@ process_message_channel_setup(struct stream *s) g_rdpdr_index = g_num_chan_items; g_rdpdr_chan_id = ci->id; } + /* disabled for now */ else if (g_strcasecmp(ci->name, "rail") == 0) { g_rail_index = g_num_chan_items; @@ -579,8 +575,6 @@ process_message_channel_setup(struct stream *s) if (g_rdpsnd_index >= 0) { - /* gets reset to 1 by next send_data_from_chan_item */ - g_sent = 0; /* wait for response! */ sound_init(); } @@ -647,8 +641,9 @@ process_message_channel_data(struct stream *s) { rv = drdynvc_data_in(s, chan_id, chan_flags, length, total_length); } - else if (chan_id == ((struct xrdp_api_data *) - (g_api_con_trans->callback_data))->chan_id) + else if ((g_api_con_trans != 0) && + (chan_id == ((struct xrdp_api_data *) + (g_api_con_trans->callback_data))->chan_id)) { LOG(10, ("process_message_channel_data length %d total_length %d " "chan_flags 0x%8.8x", length, total_length, chan_flags)); @@ -664,7 +659,7 @@ process_message_channel_data(struct stream *s) if (chan_flags & 2) /* last */ { s_mark_end(ls); - trans_write_copy(g_api_con_trans); + rv = trans_force_write(g_api_con_trans); } } } @@ -678,7 +673,6 @@ static int APP_CC process_message_channel_data_response(struct stream *s) { LOG(10, ("process_message_channel_data_response:")); - g_sent = 0; check_chan_items(); return 0; } @@ -1213,25 +1207,23 @@ nil_signal_handler(int sig) void DEFAULT_CC child_signal_handler(int sig) { - int i1; + int pid; LOG(0, ("child_signal_handler:")); - do { - i1 = g_waitchild(); - - if (i1 == g_exec_pid) + pid = g_waitchild(); + LOG(0, ("child_signal_handler: child pid %d", pid)); + if ((pid == g_exec_pid) && (pid > 0)) { - LOG(0, ("child_signal_handler: found pid %d", i1)); + LOG(0, ("child_signal_handler: found pid %d", pid)); //shutdownx(); } - - LOG(10, (" %d", i1)); } - while (i1 >= 0); + while (pid >= 0); } +/*****************************************************************************/ void DEFAULT_CC segfault_signal_handler(int sig) { @@ -1378,7 +1370,7 @@ get_log_level(const char* level_str, unsigned int default_level) "LOG_LEVEL_DEBUG" }; unsigned int i; - + if (level_str == NULL || level_str[0] == 0) { return default_level; @@ -1448,7 +1440,7 @@ main(int argc, char **argv) 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"; diff --git a/sesman/chansrv/clipboard.c b/sesman/chansrv/clipboard.c index 25775f3b..6d52da85 100644 --- a/sesman/chansrv/clipboard.c +++ b/sesman/chansrv/clipboard.c @@ -363,7 +363,7 @@ clipboard_init(void) int ver_min; Status st; - log_debug("xrdp-chansrv: in clipboard_init"); + LOG(0, ("clipboard_init:")); if (g_clip_up) { @@ -507,7 +507,7 @@ clipboard_init(void) int APP_CC clipboard_deinit(void) { - log_debug("clipboard_deinit:"); + LOG(0, ("clipboard_deinit:")); if (g_wnd != 0) { XDestroyWindow(g_display, g_wnd); diff --git a/sesman/chansrv/drdynvc.c b/sesman/chansrv/drdynvc.c index eaad17cc..70b08d97 100644 --- a/sesman/chansrv/drdynvc.c +++ b/sesman/chansrv/drdynvc.c @@ -99,13 +99,15 @@ drdynvc_process_capability_response(struct stream *s, unsigned char cmd) /* read client's version */ in_uint16_le(s, cap_version); - if (cap_version != 2) + if ((cap_version != 2) && (cap_version != 3)) { - LOG(0, ("drdynvc_process_capability_response: incompatible DVC version %d detected", cap_version)); + LOG(0, ("drdynvc_process_capability_response: incompatible DVC " + "version %d detected", cap_version)); return -1; } - LOG(0, ("drdynvc_process_capability_response: DVC version 2 selected")); + LOG(0, ("drdynvc_process_capability_response: DVC version %d selected", + cap_version)); g_drdynvc_inited = 1; return 0; diff --git a/sesman/chansrv/fifo.c b/sesman/chansrv/fifo.c index 630df3cd..b212736a 100644 --- a/sesman/chansrv/fifo.c +++ b/sesman/chansrv/fifo.c @@ -24,6 +24,7 @@ #include "fifo.h" #include "mlog.h" +#include "os_calls.h" /** * Initialize a FIFO that grows as required @@ -50,7 +51,7 @@ fifo_init(FIFO* fp, int num_entries) fp->rd_ptr = 0; fp->wr_ptr = 0; - fp->user_data = (long *) g_malloc(sizeof(long) * num_entries); + fp->user_data = (long *) g_malloc(sizeof(long) * num_entries, 1); if (fp->user_data) { @@ -94,6 +95,7 @@ fifo_deinit(FIFO* fp) fp->rd_ptr = 0; fp->wr_ptr = 0; fp->entries = 0; + return 0; } /** @@ -148,7 +150,7 @@ fifo_insert(FIFO* fp, void* data) if (next_val == fp->rd_ptr) { /* FIFO is full, expand it by 10 entries */ - lp = (long *) g_malloc(sizeof(long) * (fp->entries + 10)); + lp = (long *) g_malloc(sizeof(long) * (fp->entries + 10), 1); if (!lp) { log_debug_low("FIFO full; cannot expand, no memory"); @@ -233,8 +235,6 @@ fifo_remove(FIFO* fp) void* fifo_peek(FIFO* fp) { - long data; - log_debug_high("entered\n"); if (!fp) diff --git a/sesman/chansrv/pcsc/dumps/scard-begin-tranaction.txt b/sesman/chansrv/pcsc/dumps/scard-begin-tranaction.txt new file mode 100644 index 00000000..fbd96824 --- /dev/null +++ b/sesman/chansrv/pcsc/dumps/scard-begin-tranaction.txt @@ -0,0 +1,12 @@ +TS_SCardBeginTransaction: +0000 03 00 00 93 02 f0 80 68 00 01 03 ed f0 80 84 08 .......h........ +0010 00 00 00 de 14 5c 5a 9e 86 37 2b 70 00 00 00 03 .....\Z..7+p.... +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 02 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 38 ...............8 +0040 00 00 00 bc 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 28 00 00 00 00 00 00 00 04 00 00 00 00 ...(............ +0070 00 02 00 04 00 00 00 04 00 02 00 00 00 00 00 04 ................ +0080 00 00 00 02 00 00 00 04 00 00 00 0a 00 00 00 00 ................ +0090 00 00 00 ... + diff --git a/sesman/chansrv/pcsc/dumps/scard-connect.txt b/sesman/chansrv/pcsc/dumps/scard-connect.txt new file mode 100644 index 00000000..8756cbfc --- /dev/null +++ b/sesman/chansrv/pcsc/dumps/scard-connect.txt @@ -0,0 +1,30 @@ +TS_SCardConnect: +0000 03 00 00 cb 02 f0 80 68 00 01 03 ed f0 80 bc 08 .......h........ +0010 00 00 00 7b 28 f8 7e 5c c8 16 e8 a8 00 00 00 03 ...{(.~\........ +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 01 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 70 ...............p +0040 00 00 00 b0 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 60 00 00 00 00 00 00 00 00 00 02 00 04 ...`............ +0070 00 00 00 04 00 02 00 02 00 00 00 03 00 00 00 19 ................ +0080 00 00 00 00 00 00 00 19 00 00 00 47 00 65 00 6d ...........G.e.m +0090 00 70 00 6c 00 75 00 73 00 20 00 47 00 65 00 6d .p.l.u.s. .G.e.m +00a0 00 50 00 43 00 20 00 54 00 77 00 69 00 6e 00 20 .P.C. .T.w.i.n. +00b0 00 30 00 30 00 20 00 30 00 30 00 00 00 00 00 04 .0.0. .0.0...... +00c0 00 00 00 01 00 00 00 00 00 00 00 ........... +TS_SCardConnect: +0000 03 00 00 cb 02 f0 80 68 00 01 03 ed f0 80 bc 08 .......h........ +0010 00 00 00 7b 28 f8 7e 5c c8 16 e8 a8 00 00 00 03 ...{(.~\........ +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 01 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 70 ...............p +0040 00 00 00 b0 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 60 00 00 00 00 00 00 00 00 00 02 00 04 ...`............ +0070 00 00 00 04 00 02 00 02 00 00 00 03 00 00 00 19 ................ +0080 00 00 00 00 00 00 00 19 00 00 00 47 00 65 00 6d ...........G.e.m +0090 00 70 00 6c 00 75 00 73 00 20 00 47 00 65 00 6d .p.l.u.s. .G.e.m +00a0 00 50 00 43 00 20 00 54 00 77 00 69 00 6e 00 20 .P.C. .T.w.i.n. +00b0 00 30 00 30 00 20 00 30 00 30 00 00 00 00 00 04 .0.0. .0.0...... +00c0 00 00 00 01 00 00 00 00 00 00 00 ........... + + diff --git a/sesman/chansrv/pcsc/dumps/scard-control.txt b/sesman/chansrv/pcsc/dumps/scard-control.txt new file mode 100644 index 00000000..515b1288 --- /dev/null +++ b/sesman/chansrv/pcsc/dumps/scard-control.txt @@ -0,0 +1,61 @@ +TS_SCardControl: +0000 03 00 00 a3 02 f0 80 68 00 01 03 ed f0 80 94 08 .......h........ +0010 00 00 00 05 18 7c 3e ca 9f 03 76 80 00 00 00 03 .....|>...v..... +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 00 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 48 ...............H +0040 00 00 00 d4 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 38 00 00 00 00 00 00 00 04 00 00 00 00 ...8............ +0070 00 02 00 04 00 00 00 04 00 02 00 20 35 31 00 00 ........... 51.. +0080 00 00 00 00 00 00 00 00 00 00 00 c8 00 00 00 04 ................ +0090 00 00 00 05 00 00 00 04 00 00 00 06 00 00 00 00 ................ +00a0 00 00 00 ... +TS_SCardControl: +0000 03 00 00 a3 02 f0 80 68 00 01 03 ed f0 80 94 08 .......h........ +0010 00 00 00 99 4c 06 de f1 41 78 64 80 00 00 00 03 ....L...Axd..... +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 01 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 48 ...............H +0040 00 00 00 d4 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 38 00 00 00 00 00 00 00 04 00 00 00 00 ...8............ +0070 00 02 00 04 00 00 00 04 00 02 00 20 35 31 00 00 ........... 51.. +0080 00 00 00 00 00 00 00 00 00 00 00 c8 00 00 00 04 ................ +0090 00 00 00 05 00 00 00 04 00 00 00 06 00 00 00 00 ................ +00a0 00 00 00 ... +TS_SCardControl: +0000 03 00 00 a3 02 f0 80 68 00 01 03 ed f0 80 94 08 .......h........ +0010 00 00 00 05 18 7c 3e ca 9f 03 76 80 00 00 00 03 .....|>...v..... +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 00 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 48 ...............H +0040 00 00 00 d4 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 38 00 00 00 00 00 00 00 04 00 00 00 00 ...8............ +0070 00 02 00 04 00 00 00 04 00 02 00 20 35 31 00 00 ........... 51.. +0080 00 00 00 00 00 00 00 00 00 00 00 c8 00 00 00 04 ................ +0090 00 00 00 05 00 00 00 04 00 00 00 06 00 00 00 00 ................ +00a0 00 00 00 ... +TS_SCardControl: +0000 03 00 00 a3 02 f0 80 68 00 01 03 ed f0 80 94 08 .......h........ +0010 00 00 00 99 4c 06 de f1 41 78 64 80 00 00 00 03 ....L...Axd..... +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 01 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 48 ...............H +0040 00 00 00 d4 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 38 00 00 00 00 00 00 00 04 00 00 00 00 ...8............ +0070 00 02 00 04 00 00 00 04 00 02 00 20 35 31 00 00 ........... 51.. +0080 00 00 00 00 00 00 00 00 00 00 00 c8 00 00 00 04 ................ +0090 00 00 00 05 00 00 00 04 00 00 00 06 00 00 00 00 ................ +00a0 00 00 00 ... +TS_SCardControl: +0000 03 00 00 a3 02 f0 80 68 00 01 03 ed f0 80 94 08 .......h........ +0010 00 00 00 87 62 bd 62 13 81 8a d6 80 00 00 00 03 ....b.b......... +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 01 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 48 ...............H +0040 00 00 00 d4 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 38 00 00 00 00 00 00 00 04 00 00 00 00 ...8............ +0070 00 02 00 04 00 00 00 04 00 02 00 20 35 31 00 00 ........... 51.. +0080 00 00 00 00 00 00 00 00 00 00 00 02 01 00 00 04 ................ +0090 00 00 00 07 00 00 00 04 00 00 00 0b 00 00 00 00 ................ +00a0 00 00 00 ... + diff --git a/sesman/chansrv/pcsc/dumps/scard-disconnect.txt b/sesman/chansrv/pcsc/dumps/scard-disconnect.txt new file mode 100644 index 00000000..4c52fc2c --- /dev/null +++ b/sesman/chansrv/pcsc/dumps/scard-disconnect.txt @@ -0,0 +1,24 @@ +TS_SCardDisconnect: +0000 03 00 00 93 02 f0 80 68 00 01 03 ed f0 80 84 08 .......h........ +0010 00 00 00 87 b4 3a 7f a4 2a 6d ad 70 00 00 00 03 .....:..*m.p.... +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 00 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 38 ...............8 +0040 00 00 00 b8 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 28 00 00 00 00 00 00 00 04 00 00 00 00 ...(............ +0070 00 02 00 04 00 00 00 04 00 02 00 00 00 00 00 04 ................ +0080 00 00 00 03 00 00 00 04 00 00 00 04 00 00 00 00 ................ +0090 00 00 00 ... +TS_SCardDisconnect: +0000 03 00 00 93 02 f0 80 68 00 01 03 ed f0 80 84 08 .......h........ +0010 00 00 00 72 7f fb 24 4e b1 36 c8 70 00 00 00 03 ...r..$N.6.p.... +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 01 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 38 ...............8 +0040 00 00 00 b8 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 28 00 00 00 00 00 00 00 04 00 00 00 00 ...(............ +0070 00 02 00 04 00 00 00 04 00 02 00 00 00 00 00 04 ................ +0080 00 00 00 04 00 00 00 04 00 00 00 05 00 00 00 00 ................ +0090 00 00 00 ... + + diff --git a/sesman/chansrv/pcsc/dumps/scard-end-tranaction.txt b/sesman/chansrv/pcsc/dumps/scard-end-tranaction.txt new file mode 100644 index 00000000..b33800ad --- /dev/null +++ b/sesman/chansrv/pcsc/dumps/scard-end-tranaction.txt @@ -0,0 +1,35 @@ +TS_SCardEndTransaction: +0000 03 00 00 93 02 f0 80 68 00 01 03 ed f0 80 84 08 .......h........ +0010 00 00 00 51 1c 06 7b 0a 94 e3 7f 70 00 00 00 03 ...Q..{....p.... +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 02 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 38 ...............8 +0040 00 00 00 c0 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 28 00 00 00 00 00 00 00 04 00 00 00 00 ...(............ +0070 00 02 00 04 00 00 00 04 00 02 00 00 00 00 00 04 ................ +0080 00 00 00 09 00 00 00 04 00 00 00 0a 00 00 00 00 ................ +0090 00 00 00 ... +TS_SCardEndTransaction: +0000 03 00 00 93 02 f0 80 68 00 01 03 ed f0 80 84 08 .......h........ +0010 00 00 00 51 1c 06 7b 0a 94 e3 7f 70 00 00 00 03 ...Q..{....p.... +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 02 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 38 ...............8 +0040 00 00 00 c0 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 28 00 00 00 00 00 00 00 04 00 00 00 00 ...(............ +0070 00 02 00 04 00 00 00 04 00 02 00 00 00 00 00 04 ................ +0080 00 00 00 09 00 00 00 04 00 00 00 0a 00 00 00 00 ................ +0090 00 00 00 ... +TS_SCardEndTransaction: +0000 03 00 00 93 02 f0 80 68 00 01 03 ed f0 80 84 08 .......h........ +0010 00 00 00 fe 1c ea fb 2e a3 58 a6 70 00 00 00 03 .........X.p.... +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 03 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 38 ...............8 +0040 00 00 00 c0 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 28 00 00 00 00 00 00 00 04 00 00 00 00 ...(............ +0070 00 02 00 04 00 00 00 04 00 02 00 00 00 00 00 04 ................ +0080 00 00 00 09 00 00 00 04 00 00 00 0a 00 00 00 00 ................ +0090 00 00 00 ... + + diff --git a/sesman/chansrv/pcsc/dumps/scard-establish-context.txt b/sesman/chansrv/pcsc/dumps/scard-establish-context.txt new file mode 100644 index 00000000..9e56614b --- /dev/null +++ b/sesman/chansrv/pcsc/dumps/scard-establish-context.txt @@ -0,0 +1,19 @@ +TS_SCardEstablishContext: +0000 03 00 00 72 02 f0 80 68 00 01 03 ed f0 64 08 00 ...r...h.....d.. +0010 00 00 a7 8d 52 74 fd 96 bc b4 50 00 00 00 03 00 ....Rt....P..... +0020 00 00 72 44 52 49 00 00 00 00 01 00 00 00 00 00 ..rDRI.......... +0030 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 18 00 ................ +0040 00 00 14 00 09 00 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc cc ................ +0060 cc cc 08 00 00 00 00 00 00 00 02 00 00 00 00 00 ................ +0070 00 00 .. +TS_SCardEstablishContext: +0000 03 00 00 72 02 f0 80 68 00 01 03 ed f0 64 08 00 ...r...h.....d.. +0010 00 00 51 f7 43 00 73 65 44 53 50 00 00 00 03 00 ..Q.C.seDSP..... +0020 00 00 72 44 52 49 00 00 00 00 01 00 00 00 00 00 ..rDRI.......... +0030 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 18 00 ................ +0040 00 00 14 00 09 00 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc cc ................ +0060 cc cc 08 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +0070 00 00 .. + diff --git a/sesman/chansrv/pcsc/dumps/scard-get-status-change.txt b/sesman/chansrv/pcsc/dumps/scard-get-status-change.txt new file mode 100644 index 00000000..fca216f8 --- /dev/null +++ b/sesman/chansrv/pcsc/dumps/scard-get-status-change.txt @@ -0,0 +1,25 @@ +TS_SCardGetStatusChange: +0000 03 00 01 6b 02 f0 80 68 00 01 03 ed f0 81 5c 08 ...k...h......\. +0010 00 00 00 bf 53 5b 23 43 71 9b 2b 48 01 00 00 03 ....S[#Cq.+H.... +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 00 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 10 ................ +0040 01 00 00 a4 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 00 01 00 00 00 00 00 00 04 00 00 00 00 ................ +0070 00 02 00 ff ff ff ff 02 00 00 00 04 00 02 00 04 ................ +0080 00 00 00 01 00 00 00 02 00 00 00 08 00 02 00 00 ................ +0090 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +00a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +00b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0c ................ +00c0 00 02 00 10 00 00 00 00 00 00 00 00 00 00 00 00 ................ +00d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +00e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +00f0 00 00 00 15 00 00 00 00 00 00 00 15 00 00 00 5c ...............\ +0100 00 5c 00 3f 00 50 00 6e 00 50 00 3f 00 5c 00 4e .\.?.P.n.P.?.\.N +0110 00 6f 00 74 00 69 00 66 00 69 00 63 00 61 00 74 .o.t.i.f.i.c.a.t +0120 00 69 00 6f 00 6e 00 00 00 00 00 19 00 00 00 00 .i.o.n.......... +0130 00 00 00 19 00 00 00 47 00 65 00 6d 00 70 00 6c .......G.e.m.p.l +0140 00 75 00 73 00 20 00 47 00 65 00 6d 00 50 00 43 .u.s. .G.e.m.P.C +0150 00 20 00 54 00 77 00 69 00 6e 00 20 00 30 00 30 . .T.w.i.n. .0.0 +0160 00 20 00 30 00 30 00 00 00 00 00 . .0.0..... + diff --git a/sesman/chansrv/pcsc/dumps/scard-list-readers.txt b/sesman/chansrv/pcsc/dumps/scard-list-readers.txt new file mode 100644 index 00000000..0f79fe43 --- /dev/null +++ b/sesman/chansrv/pcsc/dumps/scard-list-readers.txt @@ -0,0 +1,94 @@ +TS_SCardListReaders: +0000 03 00 00 b3 02 f0 80 68 00 01 03 ed f0 80 a4 08 .......h........ +0010 00 00 00 07 b5 7d d1 ba 7c 7e e9 90 00 00 00 03 .....}..|~...... +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 00 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 58 ...............X +0040 00 00 00 2c 00 09 00 00 00 00 00 00 00 00 00 00 ...,............ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 48 00 00 00 00 00 00 00 04 00 00 00 00 ...H............ +0070 00 02 00 24 00 00 00 04 00 02 00 00 00 00 00 ff ...$............ +0080 ff ff ff 04 00 00 00 01 00 00 00 24 00 00 00 53 ...........$...S +0090 00 43 00 61 00 72 00 64 00 24 00 41 00 6c 00 6c .C.a.r.d.$.A.l.l +00a0 00 52 00 65 00 61 00 64 00 65 00 72 00 73 00 00 .R.e.a.d.e.r.s.. +00b0 00 00 00 ... +TS_SCardListReaders: +0000 03 00 00 8a 02 f0 80 68 00 01 03 ed f0 7c 08 00 .......h.....|.. +0010 00 00 ae 89 33 c1 0d 6b e2 bb 68 00 00 00 03 00 ....3..k..h..... +0020 00 00 72 44 52 49 00 00 00 00 01 00 00 00 01 00 ..rDRI.......... +0030 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 30 00 ..............0. +0040 00 00 28 00 09 00 00 00 00 00 00 00 00 00 00 00 ..(............. +0050 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc cc ................ +0060 cc cc 20 00 00 00 00 00 00 00 04 00 00 00 00 00 .. ............. +0070 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 ................ +0080 00 00 04 00 00 00 02 00 00 00 .......... +TS_SCardListReaders: +0000 03 00 00 8a 02 f0 80 68 00 01 03 ed f0 7c 08 00 .......h.....|.. +0010 00 00 ef be 3f 08 43 ae 89 9b 68 00 00 00 03 00 ....?.C...h..... +0020 00 00 72 44 52 49 00 00 00 00 01 00 00 00 02 00 ..rDRI.......... +0030 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 30 00 ..............0. +0040 00 00 28 00 09 00 00 00 00 00 00 00 00 00 00 00 ..(............. +0050 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc cc ................ +0060 cc cc 20 00 00 00 00 00 00 00 04 00 00 00 00 00 .. ............. +0070 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 ................ +0080 00 00 04 00 00 00 02 00 00 00 .......... +TS_SCardListReaders: +0000 03 00 00 8a 02 f0 80 68 00 01 03 ed f0 7c 08 00 .......h.....|.. +0010 00 00 ae 89 33 c1 0d 6b e2 bb 68 00 00 00 03 00 ....3..k..h..... +0020 00 00 72 44 52 49 00 00 00 00 01 00 00 00 01 00 ..rDRI.......... +0030 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 30 00 ..............0. +0040 00 00 28 00 09 00 00 00 00 00 00 00 00 00 00 00 ..(............. +0050 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc cc ................ +0060 cc cc 20 00 00 00 00 00 00 00 04 00 00 00 00 00 .. ............. +0070 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 ................ +0080 00 00 04 00 00 00 02 00 00 00 .......... +TS_SCardListReaders: +0000 03 00 00 8a 02 f0 80 68 00 01 03 ed f0 7c 08 00 .......h.....|.. +0010 00 00 ae 89 33 c1 0d 6b e2 bb 68 00 00 00 03 00 ....3..k..h..... +0020 00 00 72 44 52 49 00 00 00 00 01 00 00 00 01 00 ..rDRI.......... +0030 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 30 00 ..............0. +0040 00 00 28 00 09 00 00 00 00 00 00 00 00 00 00 00 ..(............. +0050 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc cc ................ +0060 cc cc 20 00 00 00 00 00 00 00 04 00 00 00 00 00 .. ............. +0070 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 ................ +0080 00 00 04 00 00 00 02 00 00 00 .......... +TS_SCardListReaders: +0000 03 00 00 8a 02 f0 80 68 00 01 03 ed f0 7c 08 00 .......h.....|.. +0010 00 00 ae 89 33 c1 0d 6b e2 bb 68 00 00 00 03 00 ....3..k..h..... +0020 00 00 72 44 52 49 00 00 00 00 01 00 00 00 01 00 ..rDRI.......... +0030 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 30 00 ..............0. +0040 00 00 28 00 09 00 00 00 00 00 00 00 00 00 00 00 ..(............. +0050 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc cc ................ +0060 cc cc 20 00 00 00 00 00 00 00 04 00 00 00 00 00 .. ............. +0070 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 ................ +0080 00 00 04 00 00 00 02 00 00 00 .......... +TS_SCardListReaders: +0000 03 00 00 8a 02 f0 80 68 00 01 03 ed f0 7c 08 00 .......h.....|.. +0010 00 00 78 0a 67 31 92 fc d0 29 68 00 00 00 03 00 ..x.g1...)h..... +0020 00 00 72 44 52 49 00 00 00 00 01 00 00 00 03 00 ..rDRI.......... +0030 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 30 00 ..............0. +0040 00 00 28 00 09 00 00 00 00 00 00 00 00 00 00 00 ..(............. +0050 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc cc ................ +0060 cc cc 20 00 00 00 00 00 00 00 04 00 00 00 00 00 .. ............. +0070 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 ................ +0080 00 00 04 00 00 00 02 00 00 00 .......... +TS_SCardListReaders: +0000 03 00 00 8a 02 f0 80 68 00 01 03 ed f0 7c 08 00 .......h.....|.. +0010 00 00 ae 89 33 c1 0d 6b e2 bb 68 00 00 00 03 00 ....3..k..h..... +0020 00 00 72 44 52 49 00 00 00 00 01 00 00 00 01 00 ..rDRI.......... +0030 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 30 00 ..............0. +0040 00 00 28 00 09 00 00 00 00 00 00 00 00 00 00 00 ..(............. +0050 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc cc ................ +0060 cc cc 20 00 00 00 00 00 00 00 04 00 00 00 00 00 .. ............. +0070 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 ................ +0080 00 00 04 00 00 00 02 00 00 00 .......... +TS_SCardListReaders: +0000 03 00 00 8a 02 f0 80 68 00 01 03 ed f0 7c 08 00 .......h.....|.. +0010 00 00 ae 89 33 c1 0d 6b e2 bb 68 00 00 00 03 00 ....3..k..h..... +0020 00 00 72 44 52 49 00 00 00 00 01 00 00 00 01 00 ..rDRI.......... +0030 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 30 00 ..............0. +0040 00 00 28 00 09 00 00 00 00 00 00 00 00 00 00 00 ..(............. +0050 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc cc ................ +0060 cc cc 20 00 00 00 00 00 00 00 04 00 00 00 00 00 .. ............. +0070 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 ................ +0080 00 00 04 00 00 00 02 00 00 00 + diff --git a/sesman/chansrv/pcsc/dumps/scard-release-context.txt b/sesman/chansrv/pcsc/dumps/scard-release-context.txt new file mode 100644 index 00000000..7d4266b4 --- /dev/null +++ b/sesman/chansrv/pcsc/dumps/scard-release-context.txt @@ -0,0 +1,9 @@ +0000 03 00 00 7a 02 f0 80 68 00 01 03 ed f0 6c 08 00 ...z...h.....l.. +0010 00 00 c9 9d 01 9e ec 30 a3 4c 58 00 00 00 03 00 .......0.LX..... +0020 00 00 72 44 52 49 00 00 00 00 01 00 00 00 01 00 ..rDRI.......... +0030 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 20 00 .............. . +0040 00 00 18 00 09 00 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc cc ................ +0060 cc cc 10 00 00 00 00 00 00 00 04 00 00 00 00 00 ................ +0070 02 00 04 00 00 00 02 00 00 00 .......... + diff --git a/sesman/chansrv/pcsc/dumps/scard-status.txt b/sesman/chansrv/pcsc/dumps/scard-status.txt new file mode 100644 index 00000000..c4795ef8 --- /dev/null +++ b/sesman/chansrv/pcsc/dumps/scard-status.txt @@ -0,0 +1,122 @@ +TS_SCardStatus: +0000 03 00 00 9b 02 f0 80 68 00 01 03 ed f0 80 8c 08 .......h........ +0010 00 00 00 0e 8b f9 50 1f 35 28 35 78 00 00 00 03 ......P.5(5x.... +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 00 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 40 ...............@ +0040 00 00 00 cc 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 30 00 00 00 00 00 00 00 04 00 00 00 00 ...0............ +0070 00 02 00 04 00 00 00 04 00 02 00 00 00 00 00 ff ................ +0080 ff ff ff 20 00 00 00 04 00 00 00 05 00 00 00 04 ... ............ +0090 00 00 00 06 00 00 00 00 00 00 00 ........... +TS_SCardStatus: +0000 03 00 00 9b 02 f0 80 68 00 01 03 ed f0 80 8c 08 .......h........ +0010 00 00 00 0e 8b f9 50 1f 35 28 35 78 00 00 00 03 ......P.5(5x.... +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 00 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 40 ...............@ +0040 00 00 00 cc 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 30 00 00 00 00 00 00 00 04 00 00 00 00 ...0............ +0070 00 02 00 04 00 00 00 04 00 02 00 00 00 00 00 ff ................ +0080 ff ff ff 20 00 00 00 04 00 00 00 05 00 00 00 04 ... ............ +0090 00 00 00 06 00 00 00 00 00 00 00 ........... +TS_SCardStatus: +0000 03 00 00 9b 02 f0 80 68 00 01 03 ed f0 80 8c 08 .......h........ +0010 00 00 00 88 05 07 8b 2a 3c f5 16 78 00 00 00 03 .......*<..x.... +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 01 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 40 ...............@ +0040 00 00 00 cc 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 30 00 00 00 00 00 00 00 04 00 00 00 00 ...0............ +0070 00 02 00 04 00 00 00 04 00 02 00 00 00 00 00 ff ................ +0080 ff ff ff 20 00 00 00 04 00 00 00 05 00 00 00 04 ... ............ +0090 00 00 00 06 00 00 00 00 00 00 00 ........... +TS_SCardStatus: +0000 03 00 00 9b 02 f0 80 68 00 01 03 ed f0 80 8c 08 .......h........ +0010 00 00 00 3b cf 96 d8 27 3f cd 9f 78 00 00 00 03 ...;...'?..x.... +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 01 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 40 ...............@ +0040 00 00 00 c8 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 30 00 00 00 00 00 00 00 04 00 00 00 00 ...0............ +0070 00 02 00 04 00 00 00 04 00 02 00 01 00 00 00 00 ................ +0080 00 00 00 40 00 00 00 04 00 00 00 07 00 00 00 04 ...@............ +0090 00 00 00 09 00 00 00 00 00 00 00 ........... +TS_SCardStatus: +0000 03 00 00 9b 02 f0 80 68 00 01 03 ed f0 80 8c 08 .......h........ +0010 00 00 00 a3 8c 93 16 6c 49 59 23 78 00 00 00 03 .......lIY#x.... +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 02 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 40 ...............@ +0040 00 00 00 c8 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 30 00 00 00 00 00 00 00 04 00 00 00 00 ...0............ +0070 00 02 00 04 00 00 00 04 00 02 00 01 00 00 00 00 ................ +0080 00 00 00 40 00 00 00 04 00 00 00 07 00 00 00 04 ...@............ +0090 00 00 00 09 00 00 00 00 00 00 00 ........... +TS_SCardStatus: +0000 03 00 00 9b 02 f0 80 68 00 01 03 ed f0 80 8c 08 .......h........ +0010 00 00 00 6d d0 36 aa 65 50 4c 88 78 00 00 00 03 ...m.6.ePL.x.... +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 03 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 40 ...............@ +0040 00 00 00 c8 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 30 00 00 00 00 00 00 00 04 00 00 00 00 ...0............ +0070 00 02 00 04 00 00 00 04 00 02 00 01 00 00 00 00 ................ +0080 00 00 00 40 00 00 00 04 00 00 00 07 00 00 00 04 ...@............ +0090 00 00 00 09 00 00 00 00 00 00 00 ........... +TS_SCardStatus: +0000 03 00 00 9b 02 f0 80 68 00 01 03 ed f0 80 8c 08 .......h........ +0010 00 00 00 a3 8c 93 16 6c 49 59 23 78 00 00 00 03 .......lIY#x.... +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 02 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 40 ...............@ +0040 00 00 00 c8 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 30 00 00 00 00 00 00 00 04 00 00 00 00 ...0............ +0070 00 02 00 04 00 00 00 04 00 02 00 01 00 00 00 00 ................ +0080 00 00 00 40 00 00 00 04 00 00 00 07 00 00 00 04 ...@............ +0090 00 00 00 09 00 00 00 00 00 00 00 ........... +TS_SCardStatus: +0000 03 00 00 9b 02 f0 80 68 00 01 03 ed f0 80 8c 08 .......h........ +0010 00 00 00 6d d0 36 aa 65 50 4c 88 78 00 00 00 03 ...m.6.ePL.x.... +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 03 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 40 ...............@ +0040 00 00 00 c8 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 30 00 00 00 00 00 00 00 04 00 00 00 00 ...0............ +0070 00 02 00 04 00 00 00 04 00 02 00 01 00 00 00 00 ................ +0080 00 00 00 40 00 00 00 04 00 00 00 07 00 00 00 04 ...@............ +0090 00 00 00 09 00 00 00 00 00 00 00 ........... +TS_SCardStatus: +0000 03 00 00 9b 02 f0 80 68 00 01 03 ed f0 80 8c 08 .......h........ +0010 00 00 00 6d d0 36 aa 65 50 4c 88 78 00 00 00 03 ...m.6.ePL.x.... +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 03 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 40 ...............@ +0040 00 00 00 c8 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 30 00 00 00 00 00 00 00 04 00 00 00 00 ...0............ +0070 00 02 00 04 00 00 00 04 00 02 00 01 00 00 00 00 ................ +0080 00 00 00 40 00 00 00 04 00 00 00 07 00 00 00 04 ...@............ +0090 00 00 00 09 00 00 00 00 00 00 00 ........... +TS_SCardStatus: +0000 03 00 00 9b 02 f0 80 68 00 01 03 ed f0 80 8c 08 .......h........ +0010 00 00 00 a3 8c 93 16 6c 49 59 23 78 00 00 00 03 .......lIY#x.... +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 02 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 40 ...............@ +0040 00 00 00 c8 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 30 00 00 00 00 00 00 00 04 00 00 00 00 ...0............ +0070 00 02 00 04 00 00 00 04 00 02 00 01 00 00 00 00 ................ +0080 00 00 00 40 00 00 00 04 00 00 00 07 00 00 00 04 ...@............ +0090 00 00 00 09 00 00 00 00 00 00 00 ........... +TS_SCardStatus: +0000 03 00 00 9b 02 f0 80 68 00 01 03 ed f0 80 8c 08 .......h........ +0010 00 00 00 6d d0 36 aa 65 50 4c 88 78 00 00 00 03 ...m.6.ePL.x.... +0020 00 00 00 72 44 52 49 00 00 00 00 01 00 00 00 03 ...rDRI......... +0030 00 00 00 0e 00 00 00 00 00 00 00 00 08 00 00 40 ...............@ +0040 00 00 00 c8 00 09 00 00 00 00 00 00 00 00 00 00 ................ +0050 00 00 00 00 00 00 00 00 00 00 00 01 10 08 00 cc ................ +0060 cc cc cc 30 00 00 00 00 00 00 00 04 00 00 00 00 ...0............ +0070 00 02 00 04 00 00 00 04 00 02 00 01 00 00 00 00 ................ +0080 00 00 00 40 00 00 00 04 00 00 00 07 00 00 00 04 ...@............ +0090 00 00 00 09 00 00 00 00 00 00 00 ........... + diff --git a/sesman/chansrv/pcsc/dumps/scard-transmit.txt b/sesman/chansrv/pcsc/dumps/scard-transmit.txt new file mode 100644 index 00000000..a593dfc2 --- /dev/null +++ b/sesman/chansrv/pcsc/dumps/scard-transmit.txt @@ -0,0 +1,34 @@ +TS_SCardTransmit: +0000 01 10 08 00 cc cc cc cc 58 00 00 00 00 00 00 00 ........X....... +0010 04 00 00 00 00 00 02 00 04 00 00 00 04 00 02 00 ................ +0020 01 00 00 00 00 00 00 00 00 00 00 00 07 00 00 00 ................ +0030 08 00 02 00 0c 00 02 00 00 00 00 00 02 01 00 00 ................ +0040 04 00 00 00 05 00 00 00 04 00 00 00 0b 00 00 00 ................ +0050 07 00 00 00 00 a4 02 0c 02 ef 0f 00 01 00 00 00 ................ +0060 00 00 00 00 00 00 00 00 ........ +TS_SCardTransmit: +0000 01 10 08 00 cc cc cc cc 58 00 00 00 00 00 00 00 ........X....... +0010 04 00 00 00 00 00 02 00 04 00 00 00 04 00 02 00 ................ +0020 01 00 00 00 00 00 00 00 00 00 00 00 05 00 00 00 ................ +0030 08 00 02 00 0c 00 02 00 00 00 00 00 02 01 00 00 ................ +0040 04 00 00 00 05 00 00 00 04 00 00 00 0b 00 00 00 ................ +0050 05 00 00 00 00 b0 07 5b 10 00 00 00 01 00 00 00 .......[........ +0060 00 00 00 00 00 00 00 00 ........ +TS_SCardTransmit: +0000 01 10 08 00 cc cc cc cc 58 00 00 00 00 00 00 00 ........X....... +0010 04 00 00 00 00 00 02 00 04 00 00 00 04 00 02 00 ................ +0020 01 00 00 00 00 00 00 00 00 00 00 00 07 00 00 00 ................ +0030 08 00 02 00 0c 00 02 00 00 00 00 00 02 01 00 00 ................ +0040 04 00 00 00 05 00 00 00 04 00 00 00 0b 00 00 00 ................ +0050 07 00 00 00 00 a4 02 0c 02 ef 10 00 01 00 00 00 ................ +0060 00 00 00 00 00 00 00 00 ........ +TS_SCardTransmit: +0000 01 10 08 00 cc cc cc cc 58 00 00 00 00 00 00 00 ........X....... +0010 04 00 00 00 00 00 02 00 04 00 00 00 04 00 02 00 ................ +0020 01 00 00 00 00 00 00 00 00 00 00 00 05 00 00 00 ................ +0030 08 00 02 00 0c 00 02 00 00 00 00 00 02 01 00 00 ................ +0040 04 00 00 00 05 00 00 00 04 00 00 00 0b 00 00 00 ................ +0050 05 00 00 00 00 b0 07 04 10 00 00 00 01 00 00 00 ................ +0060 00 00 00 00 00 00 00 00 ........ + + diff --git a/sesman/chansrv/pcsc/wrapper/Makefile b/sesman/chansrv/pcsc/wrapper/Makefile new file mode 100755 index 00000000..181c6fbd --- /dev/null +++ b/sesman/chansrv/pcsc/wrapper/Makefile @@ -0,0 +1,14 @@ + +CC=bcc32.exe + +CFLAGS=-O2 + +OBJS=winscard.obj + +winscard.dll: $(OBJS) + $(CC) -ewinscard.dll -tWD $(OBJS) + +clean: + -del winscard.dll + -del *.obj + -del *.tds diff --git a/sesman/chansrv/pcsc/wrapper/winscard-func-names.txt b/sesman/chansrv/pcsc/wrapper/winscard-func-names.txt new file mode 100755 index 00000000..46c1cd17 --- /dev/null +++ b/sesman/chansrv/pcsc/wrapper/winscard-func-names.txt @@ -0,0 +1,78 @@ +ClassInstall32 +SCardAccessNewReaderEvent +SCardReleaseAllEvents +SCardReleaseNewReaderEvent +SCardAccessStartedEvent + +done SCardAddReaderToGroupA +done SCardAddReaderToGroupW +done SCardBeginTransaction +done SCardCancel +done SCardConnectA +done SCardConnectW +done SCardControl +done SCardDisconnect +done SCardEndTransaction +done SCardEstablishContext +done SCardForgetCardTypeA +done SCardForgetCardTypeW +done SCardForgetReaderA +done SCardForgetReaderGroupA +done SCardForgetReaderGroupW +done SCardForgetReaderW +done SCardFreeMemory +done SCardGetAttrib +done SCardGetCardTypeProviderNameA +done SCardGetCardTypeProviderNameW +done SCardGetProviderIdA +done SCardGetProviderIdW +done SCardGetStatusChangeA +done SCardGetStatusChangeW + +SCardGetTransmitCount + +done SCardIntroduceCardTypeA +done SCardIntroduceCardTypeW +done SCardIntroduceReaderA +done SCardIntroduceReaderGroupA +done SCardIntroduceReaderGroupW +done SCardIntroduceReaderW +done SCardIsValidContext +done SCardListCardsA +done SCardListCardsW +done SCardListInterfacesA +done SCardListInterfacesW +done SCardListReaderGroupsA +done SCardListReaderGroupsW +done SCardListReadersA +done SCardListReadersW +done SCardLocateCardsA + +SCardLocateCardsByATRA +SCardLocateCardsByATRW + +done SCardLocateCardsW + +SCardReadCacheA +SCardReadCacheW + +done SCardReconnect +done SCardReleaseContext + +SCardReleaseStartedEvent + +done SCardRemoveReaderFromGroupA +done SCardRemoveReaderFromGroupW +done SCardSetAttrib +done SCardSetCardTypeProviderNameA +done SCardSetCardTypeProviderNameW +done SCardState +done SCardStatusA +done SCardStatusW +done SCardTransmit + +SCardWriteCacheA +SCardWriteCacheW +g_rgSCardRawPci +g_rgSCardT0Pci +g_rgSCardT1Pci diff --git a/sesman/chansrv/pcsc/wrapper/winscard-funcs.h b/sesman/chansrv/pcsc/wrapper/winscard-funcs.h new file mode 100755 index 00000000..0a4198a3 --- /dev/null +++ b/sesman/chansrv/pcsc/wrapper/winscard-funcs.h @@ -0,0 +1,171 @@ + +#ifndef _WINSCARD_FUNCS_H +#define _WINSCARD_FUNCS_H + +typedef LONG WINAPI +(*tSCardEstablishContext)(DWORD dwScope, LPCVOID pvReserved1, + LPCVOID pvReserved2, LPSCARDCONTEXT phContext); +typedef LONG WINAPI +(*tSCardReleaseContext)(SCARDCONTEXT hContext); +typedef LONG WINAPI +(*tSCardIsValidContext)(SCARDCONTEXT hContext); +typedef LONG WINAPI +(*tSCardListReaderGroupsA)(SCARDCONTEXT hContext, LPSTR mszGroups, + LPDWORD pcchGroups); +typedef LONG WINAPI +(*tSCardListReaderGroupsW)(SCARDCONTEXT hContext, LPWSTR mszGroups, + LPDWORD pcchGroups); +typedef LONG WINAPI +(*tSCardListReadersA)(SCARDCONTEXT hContext, LPCSTR mszGroups, + LPSTR mszReaders, LPDWORD pcchReaders); +typedef LONG WINAPI +(*tSCardListReadersW)(SCARDCONTEXT hContext, LPCWSTR mszGroups, + LPWSTR mszReaders, LPDWORD pcchReaders); +typedef LONG WINAPI +(*tSCardListCardsA)(SCARDCONTEXT hContext, LPCBYTE pbAtr, + LPCGUID rgquidInterfaces, DWORD cguidInterfaceCount, + LPSTR mszCards, LPDWORD pcchCards); +typedef LONG WINAPI +(*tSCardListCardsW)(SCARDCONTEXT hContext, LPCBYTE pbAtr, + LPCGUID rgquidInterfaces, DWORD cguidInterfaceCount, + LPWSTR mszCards, LPDWORD pcchCards); +typedef LONG WINAPI +(*tSCardListInterfacesA)(SCARDCONTEXT hContext, LPCSTR szCard, + LPGUID pguidInterfaces, LPDWORD pcguidInterfaces); +typedef LONG WINAPI +(*tSCardListInterfacesW)(SCARDCONTEXT hContext, LPCWSTR szCard, + LPGUID pguidInterfaces, LPDWORD pcguidInterfaces); +typedef LONG WINAPI +(*tSCardGetProviderIdA)(SCARDCONTEXT hContext, LPCSTR szCard, + LPGUID pguidProviderId); +typedef LONG WINAPI +(*tSCardGetProviderIdW)(SCARDCONTEXT hContext, LPCWSTR szCard, + LPGUID pguidProviderId); +typedef LONG WINAPI +(*tSCardGetCardTypeProviderNameA)(SCARDCONTEXT hContext, LPCSTR szCardName, + DWORD dwProviderId, LPSTR szProvider, + LPDWORD pcchProvider); +typedef LONG WINAPI +(*tSCardGetCardTypeProviderNameW)(SCARDCONTEXT hContext, LPCWSTR szCardName, + DWORD dwProviderId, LPWSTR szProvider, + LPDWORD pcchProvider); +typedef LONG WINAPI +(*tSCardIntroduceReaderGroupA)(SCARDCONTEXT hContext, LPCSTR szGroupName); +typedef LONG WINAPI +(*tSCardIntroduceReaderGroupW)(SCARDCONTEXT hContext, LPCWSTR szGroupName); + +typedef LONG WINAPI +(*tSCardForgetReaderGroupA)(SCARDCONTEXT hContext, LPCSTR szGroupName); +typedef LONG WINAPI +(*tSCardForgetReaderGroupW)(SCARDCONTEXT hContext, LPCWSTR szGroupName); +typedef LONG WINAPI +(*tSCardIntroduceReaderA)(SCARDCONTEXT hContext, LPCSTR szReaderName, + LPCSTR szDeviceName); +typedef LONG WINAPI +(*tSCardIntroduceReaderW)(SCARDCONTEXT hContext, LPCWSTR szReaderName, + LPCWSTR szDeviceName); +typedef LONG WINAPI +(*tSCardForgetReaderA)(SCARDCONTEXT hContext, LPCSTR szReaderName); +typedef LONG WINAPI +(*tSCardForgetReaderW)(SCARDCONTEXT hContext, LPCWSTR szReaderName); + +typedef LONG WINAPI +(*tSCardAddReaderToGroupA)(SCARDCONTEXT hContext, LPCSTR szReaderName, + LPCSTR szGroupName); +typedef LONG WINAPI +(*tSCardAddReaderToGroupW)(SCARDCONTEXT hContext, LPCWSTR szReaderName, + LPCWSTR szGroupName); +typedef LONG WINAPI +(*tSCardRemoveReaderFromGroupA)(SCARDCONTEXT hContext, LPCSTR szReaderName, + LPCSTR szGroupName); +typedef LONG WINAPI +(*tSCardRemoveReaderFromGroupW)(SCARDCONTEXT hContext, LPCWSTR szReaderName, + LPCWSTR szGroupName); +typedef LONG WINAPI +(*tSCardIntroduceCardTypeA)(SCARDCONTEXT hContext, LPCSTR szCardName, + LPCGUID pguidPrimaryProvider, + LPCGUID rgguidInterfaces, + DWORD dwInterfaceCount, LPCBYTE pbAtr, + LPCBYTE pbAtrMask, DWORD cbAtrLen); +typedef LONG WINAPI +(*tSCardIntroduceCardTypeW)(SCARDCONTEXT hContext, LPCWSTR szCardName, + LPCGUID pguidPrimaryProvider, + LPCGUID rgguidInterfaces, + DWORD dwInterfaceCount, LPCBYTE pbAtr, + LPCBYTE pbAtrMask, DWORD cbAtrLen); +typedef LONG WINAPI +(*tSCardSetCardTypeProviderNameA)(SCARDCONTEXT hContext, LPCSTR szCardName, + DWORD dwProviderId, LPCSTR szProvider); +typedef LONG WINAPI +(*tSCardSetCardTypeProviderNameW)(SCARDCONTEXT hContext, LPCWSTR szCardName, + DWORD dwProviderId, LPCWSTR szProvider); +typedef LONG WINAPI +(*tSCardForgetCardTypeA)(SCARDCONTEXT hContext, LPCSTR szCardName); +typedef LONG WINAPI +(*tSCardForgetCardTypeW)(SCARDCONTEXT hContext, LPCWSTR szCardName); +typedef LONG WINAPI +(*tSCardFreeMemory)(SCARDCONTEXT hContext, LPCVOID pvMem); +typedef LONG WINAPI +(*tSCardLocateCardsA)(SCARDCONTEXT hContext, LPCSTR mszCards, + LPSCARD_READERSTATEA rgReaderStates, DWORD cReaders); +typedef LONG WINAPI +(*tSCardLocateCardsW)(SCARDCONTEXT hContext, LPCWSTR mszCards, + LPSCARD_READERSTATEW rgReaderStates, DWORD cReaders); +typedef LONG WINAPI +(*tSCardGetStatusChangeA)(SCARDCONTEXT hContext, DWORD dwTimeout, + LPSCARD_READERSTATEA rgReaderStates, + DWORD cReaders); +typedef LONG WINAPI +(*tSCardGetStatusChangeW)(SCARDCONTEXT hContext, DWORD dwTimeout, + LPSCARD_READERSTATEW rgReaderStates, + DWORD cReaders); +typedef LONG WINAPI +(*tSCardCancel)(SCARDCONTEXT hContext); +typedef LONG WINAPI +(*tSCardConnectA)(SCARDCONTEXT hContext, LPCSTR szReader, + DWORD dwShareMode, DWORD dwPreferredProtocols, + LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol); +typedef LONG WINAPI +(*tSCardConnectW)(SCARDCONTEXT hContext, LPCWSTR szReader, + DWORD dwShareMode, DWORD dwPreferredProtocols, + LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol); +typedef LONG WINAPI +(*tSCardReconnect)(SCARDHANDLE hCard, DWORD dwShareMode, + DWORD dwPreferredProtocols, DWORD dwInitialization, + LPDWORD pdwActiveProtocol); +typedef LONG WINAPI +(*tSCardDisconnect)(SCARDHANDLE hCard, DWORD dwDisposition); +typedef LONG WINAPI +(*tSCardBeginTransaction)(SCARDHANDLE hCard); +typedef LONG WINAPI +(*tSCardEndTransaction)(SCARDHANDLE hCard, DWORD dwDisposition); +typedef LONG WINAPI +(*tSCardCancelTransaction)(SCARDHANDLE hCard); +typedef LONG WINAPI +(*tSCardState)(SCARDHANDLE hCard, LPDWORD pdwState, LPDWORD pdwProtocol, + LPBYTE pbAtr, LPDWORD pcbAtrLen); +typedef LONG WINAPI +(*tSCardStatusA)(SCARDHANDLE hCard, LPSTR szReaderName, LPDWORD pcchReaderLen, + LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, + LPDWORD pcbAtrLen); +typedef LONG WINAPI +(*tSCardStatusW)(SCARDHANDLE hCard, LPWSTR szReaderName, LPDWORD pcchReaderLen, + LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, + LPDWORD pcbAtrLen); +typedef LONG WINAPI +(*tSCardTransmit)(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci, + LPCBYTE pbSendBuffer, DWORD cbSendLength, + LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer, + LPDWORD pcbRecvLength); +typedef LONG WINAPI +(*tSCardControl)(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID lpInBuffer, + DWORD nInBufferSize, LPVOID lpOutBuffer, + DWORD nOutBufferSize, LPDWORD lpBytesReturned); +typedef LONG WINAPI +(*tSCardGetAttrib)(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, + LPDWORD pcbAttrLen); +typedef LONG WINAPI +(*tSCardSetAttrib)(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, + DWORD cbAttrLen); + +#endif diff --git a/sesman/chansrv/pcsc/wrapper/winscard.c b/sesman/chansrv/pcsc/wrapper/winscard.c new file mode 100755 index 00000000..34157f7c --- /dev/null +++ b/sesman/chansrv/pcsc/wrapper/winscard.c @@ -0,0 +1,757 @@ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <windows.h> + +#include "winscard-funcs.h" + +#define LUNUSED(_param) (void) _param + +static tSCardEstablishContext aSCardEstablishContext; +static tSCardReleaseContext aSCardReleaseContext; +static tSCardIsValidContext aSCardIsValidContext; +static tSCardListReaderGroupsA aSCardListReaderGroupsA; +static tSCardListReaderGroupsW aSCardListReaderGroupsW; +static tSCardListReadersA aSCardListReadersA; +static tSCardListReadersW aSCardListReadersW; +static tSCardListCardsA aSCardListCardsA; +static tSCardListCardsW aSCardListCardsW; +static tSCardListInterfacesA aSCardListInterfacesA; +static tSCardListInterfacesW aSCardListInterfacesW; +static tSCardGetProviderIdA aSCardGetProviderIdA; +static tSCardGetProviderIdW aSCardGetProviderIdW; +static tSCardGetCardTypeProviderNameA aSCardGetCardTypeProviderNameA; +static tSCardGetCardTypeProviderNameW aSCardGetCardTypeProviderNameW; +static tSCardIntroduceReaderGroupA aSCardIntroduceReaderGroupA; +static tSCardIntroduceReaderGroupW aSCardIntroduceReaderGroupW; +static tSCardForgetReaderGroupA aSCardForgetReaderGroupA; +static tSCardForgetReaderGroupW aSCardForgetReaderGroupW; +static tSCardIntroduceReaderA aSCardIntroduceReaderA; +static tSCardIntroduceReaderW aSCardIntroduceReaderW; +static tSCardForgetReaderA aSCardForgetReaderA; +static tSCardForgetReaderW aSCardForgetReaderW; +static tSCardAddReaderToGroupA aSCardAddReaderToGroupA; +static tSCardAddReaderToGroupW aSCardAddReaderToGroupW; +static tSCardRemoveReaderFromGroupA aSCardRemoveReaderFromGroupA; +static tSCardRemoveReaderFromGroupW aSCardRemoveReaderFromGroupW; +static tSCardIntroduceCardTypeA aSCardIntroduceCardTypeA; +static tSCardIntroduceCardTypeW aSCardIntroduceCardTypeW; +static tSCardSetCardTypeProviderNameA aSCardSetCardTypeProviderNameA; +static tSCardSetCardTypeProviderNameW aSCardSetCardTypeProviderNameW; +static tSCardForgetCardTypeA aSCardForgetCardTypeA; +static tSCardForgetCardTypeW aSCardForgetCardTypeW; +static tSCardFreeMemory aSCardFreeMemory; +static tSCardLocateCardsA aSCardLocateCardsA; +static tSCardLocateCardsW aSCardLocateCardsW; +static tSCardGetStatusChangeA aSCardGetStatusChangeA; +static tSCardGetStatusChangeW aSCardGetStatusChangeW; +static tSCardCancel aSCardCancel; +static tSCardConnectA aSCardConnectA; +static tSCardConnectW aSCardConnectW; +static tSCardReconnect aSCardReconnect; +static tSCardDisconnect aSCardDisconnect; +static tSCardBeginTransaction aSCardBeginTransaction; +static tSCardEndTransaction aSCardEndTransaction; +static tSCardCancelTransaction aSCardCancelTransaction; +static tSCardState aSCardState; +static tSCardStatusA aSCardStatusA; +static tSCardStatusW aSCardStatusW; +static tSCardTransmit aSCardTransmit; +static tSCardControl aSCardControl; +static tSCardGetAttrib aSCardGetAttrib; +static tSCardSetAttrib aSCardSetAttrib; + +//__declspec(dllexport) const SCARD_IO_REQUEST g_rgSCardT0Pci = { 0 }; +//__declspec(dllexport) const SCARD_IO_REQUEST g_rgSCardT1Pci = { 0 }; +//__declspec(dllexport) const SCARD_IO_REQUEST g_rgSCardRawPci = { 0 }; + +static int g_true = 1; + +#define LLOGLN(_level, _args) do { if ((_level < 11) && g_true) { writeln _args ; } } while (0) + +/*****************************************************************************/ +static int +writeln(const char* format, ...) +{ + va_list ap; + char text[256]; + + va_start(ap, format); + vsnprintf(text, 255, format, ap); + va_end(ap); + OutputDebugString(text); + return 0; +} + +#define LLOAD(_func, _type, _name) \ +do { \ + _func = (_type) GetProcAddress(lib, _name); \ + if (_func == 0) \ + { \ + writeln("LLOAD error %s", _name); \ + } \ +} while (0) + +static int g_funcs_loaded = 0; + +/*****************************************************************************/ +static int __fastcall +load_funsc(void) +{ + HMODULE lib; + + if (g_funcs_loaded) + { + return 0; + } + g_funcs_loaded = 1; + lib = LoadLibrary("winscard-org.dll"); + LLOGLN(0, ("load_funsc: lib %p", lib)); + LLOAD(aSCardEstablishContext, tSCardEstablishContext, "SCardEstablishContext"); + LLOAD(aSCardReleaseContext, tSCardReleaseContext, "SCardReleaseContext"); + LLOAD(aSCardIsValidContext, tSCardIsValidContext, "SCardIsValidContext"); + LLOAD(aSCardListReaderGroupsA, tSCardListReaderGroupsA, "SCardListReaderGroupsA"); + LLOAD(aSCardListReaderGroupsW, tSCardListReaderGroupsW, "SCardListReaderGroupsW"); + LLOAD(aSCardListReadersA, tSCardListReadersA, "SCardListReadersA"); + LLOAD(aSCardListReadersW, tSCardListReadersW, "SCardListReadersW"); + LLOAD(aSCardListCardsA, tSCardListCardsA, "SCardListCardsA"); + LLOAD(aSCardListCardsW, tSCardListCardsW, "SCardListCardsW"); + LLOAD(aSCardListInterfacesA, tSCardListInterfacesA, "SCardListInterfacesA"); + LLOAD(aSCardListInterfacesW, tSCardListInterfacesW, "SCardListInterfacesW"); + LLOAD(aSCardGetProviderIdA, tSCardGetProviderIdA, "SCardGetProviderIdA"); + LLOAD(aSCardGetProviderIdW, tSCardGetProviderIdW, "SCardGetProviderIdW"); + LLOAD(aSCardGetCardTypeProviderNameA, tSCardGetCardTypeProviderNameA, "SCardGetCardTypeProviderNameA"); + LLOAD(aSCardGetCardTypeProviderNameW, tSCardGetCardTypeProviderNameW, "SCardGetCardTypeProviderNameW"); + LLOAD(aSCardIntroduceReaderGroupA, tSCardIntroduceReaderGroupA, "SCardIntroduceReaderGroupA"); + LLOAD(aSCardIntroduceReaderGroupW, tSCardIntroduceReaderGroupW, "SCardIntroduceReaderGroupW"); + LLOAD(aSCardForgetReaderGroupA, tSCardForgetReaderGroupA, "SCardForgetReaderGroupA"); + LLOAD(aSCardForgetReaderGroupW, tSCardForgetReaderGroupW, "SCardForgetReaderGroupW"); + LLOAD(aSCardIntroduceReaderA, tSCardIntroduceReaderA, "SCardIntroduceReaderA"); + LLOAD(aSCardIntroduceReaderW, tSCardIntroduceReaderW, "SCardIntroduceReaderW"); + LLOAD(aSCardForgetReaderA, tSCardForgetReaderA, "SCardForgetReaderA"); + LLOAD(aSCardForgetReaderW, tSCardForgetReaderW, "SCardForgetReaderW"); + LLOAD(aSCardAddReaderToGroupA, tSCardAddReaderToGroupA, "SCardAddReaderToGroupA"); + LLOAD(aSCardAddReaderToGroupW, tSCardAddReaderToGroupW, "SCardAddReaderToGroupW"); + LLOAD(aSCardRemoveReaderFromGroupA, tSCardRemoveReaderFromGroupA, "SCardRemoveReaderFromGroupA"); + LLOAD(aSCardRemoveReaderFromGroupW, tSCardRemoveReaderFromGroupW, "SCardRemoveReaderFromGroupW"); + LLOAD(aSCardIntroduceCardTypeA, tSCardIntroduceCardTypeA, "SCardIntroduceCardTypeA"); + LLOAD(aSCardIntroduceCardTypeW, tSCardIntroduceCardTypeW, "SCardIntroduceCardTypeW"); + LLOAD(aSCardSetCardTypeProviderNameA, tSCardSetCardTypeProviderNameA, "SCardSetCardTypeProviderNameA"); + LLOAD(aSCardSetCardTypeProviderNameW, tSCardSetCardTypeProviderNameW, "SCardSetCardTypeProviderNameW"); + LLOAD(aSCardForgetCardTypeA, tSCardForgetCardTypeA, "SCardForgetCardTypeA"); + LLOAD(aSCardForgetCardTypeW, tSCardForgetCardTypeW, "SCardForgetCardTypeW"); + LLOAD(aSCardFreeMemory, tSCardFreeMemory, "SCardFreeMemory"); + LLOAD(aSCardLocateCardsA, tSCardLocateCardsA, "SCardLocateCardsA"); + LLOAD(aSCardLocateCardsW, tSCardLocateCardsW, "SCardLocateCardsW"); + LLOAD(aSCardGetStatusChangeA, tSCardGetStatusChangeA, "SCardGetStatusChangeA"); + LLOAD(aSCardGetStatusChangeW, tSCardGetStatusChangeW, "SCardGetStatusChangeW"); + LLOAD(aSCardCancel, tSCardCancel, "SCardCancel"); + LLOAD(aSCardConnectA, tSCardConnectA, "SCardConnectA"); + LLOAD(aSCardConnectW, tSCardConnectW, "SCardConnectW"); + LLOAD(aSCardReconnect, tSCardReconnect, "SCardReconnect"); + LLOAD(aSCardDisconnect, tSCardDisconnect, "SCardDisconnect"); + LLOAD(aSCardBeginTransaction, tSCardBeginTransaction, "SCardBeginTransaction"); + LLOAD(aSCardEndTransaction, tSCardEndTransaction, "SCardEndTransaction"); + LLOAD(aSCardCancelTransaction, tSCardCancelTransaction, "SCardCancelTransaction"); + LLOAD(aSCardState, tSCardState, "SCardState"); + LLOAD(aSCardStatusA, tSCardStatusA, "SCardStatusA"); + LLOAD(aSCardStatusW, tSCardStatusW, "SCardStatusW"); + LLOAD(aSCardTransmit, tSCardTransmit, "SCardTransmit"); + LLOAD(aSCardControl, tSCardControl, "SCardControl"); + LLOAD(aSCardGetAttrib, tSCardGetAttrib, "SCardGetAttrib"); + LLOAD(aSCardSetAttrib, tSCardSetAttrib, "SCardSetAttrib"); + + return 0; +} + +/*****************************************************************************/ +BOOL WINAPI +DllEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + BOOL rv; + LUNUSED(hinstDLL); + LUNUSED(lpvReserved); + + LLOGLN(10, ("DllEntryPoint: hinstDLL %p fdwReason %d", hinstDLL, fdwReason)); + rv = FALSE; + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + LLOGLN(0, ("DllEntryPoint: DLL_PROCESS_ATTACH")); + load_funsc(); + rv = TRUE; + break; + case DLL_THREAD_ATTACH: + LLOGLN(10, ("DllEntryPoint: DLL_THREAD_ATTACH")); + rv = TRUE; + break; + case DLL_THREAD_DETACH: + LLOGLN(10, ("DllEntryPoint: DLL_THREAD_DETACH")); + rv = TRUE; + break; + case DLL_PROCESS_DETACH: + LLOGLN(0, ("DllEntryPoint: DLL_PROCESS_DETACH")); + rv = TRUE; + break; + default: + LLOGLN(0, ("DllEntryPoint: unknown fdwReason %d", fdwReason)); + break; + + } + return rv; +} + +/*****************************************************************************/ +LONG WINAPI +SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, + LPCVOID pvReserved2, LPSCARDCONTEXT phContext) +{ + LLOGLN(0, ("SCardEstablishContext:")); + return aSCardEstablishContext(dwScope, pvReserved1, pvReserved2, phContext); +} + +/*****************************************************************************/ +LONG WINAPI +SCardReleaseContext(SCARDCONTEXT hContext) +{ + LLOGLN(0, ("SCardReleaseContext:")); + return aSCardReleaseContext(hContext); +} + +/*****************************************************************************/ +LONG WINAPI +SCardIsValidContext(SCARDCONTEXT hContext) +{ + LLOGLN(0, ("SCardIsValidContext:")); + return aSCardIsValidContext(hContext); +} + +/*****************************************************************************/ +LONG WINAPI +SCardListReaderGroupsA(SCARDCONTEXT hContext, LPSTR mszGroups, + LPDWORD pcchGroups) +{ + LLOGLN(0, ("SCardListReaderGroupsA:")); + return aSCardListReaderGroupsA(hContext, mszGroups, pcchGroups); +} + +/*****************************************************************************/ +LONG WINAPI +SCardListReaderGroupsW(SCARDCONTEXT hContext, LPWSTR mszGroups, + LPDWORD pcchGroups) +{ + LLOGLN(0, ("SCardListReaderGroupsW:")); + return aSCardListReaderGroupsW(hContext, mszGroups, pcchGroups); +} + +/*****************************************************************************/ +LONG WINAPI +SCardListReadersA(SCARDCONTEXT hContext, LPCSTR mszGroups, + LPSTR mszReaders, LPDWORD pcchReaders) +{ + LLOGLN(0, ("SCardListReadersA:")); + return aSCardListReadersA(hContext, mszGroups, mszReaders, pcchReaders); +} + +/*****************************************************************************/ +LONG WINAPI +SCardListReadersW(SCARDCONTEXT hContext, LPCWSTR mszGroups, + LPWSTR mszReaders, LPDWORD pcchReaders) +{ + char text[256]; + LONG rv; + DWORD cchReaders; + + text[0] = 0; + if (mszGroups != 0) + { + wcstombs(text, mszGroups, 255); + } + cchReaders = *pcchReaders; + LLOGLN(0, ("SCardListReadersW: mszGroups [%s] cchReaders [%d]", text, *pcchReaders)); + rv = aSCardListReadersW(hContext, mszGroups, mszReaders, pcchReaders); + text[0] = 0; + if (cchReaders > 0) + { + wcstombs(text, mszReaders, 255); + } + LLOGLN(0, (" mszReaders [%s] cchReaders [%d]", text, *pcchReaders)); + return rv; +} + +/*****************************************************************************/ +LONG WINAPI +SCardListCardsA(SCARDCONTEXT hContext, LPCBYTE pbAtr, + LPCGUID rgquidInterfaces, DWORD cguidInterfaceCount, + LPSTR mszCards, LPDWORD pcchCards) +{ + LLOGLN(0, ("SCardListCardsA:")); + return aSCardListCardsA(hContext, pbAtr, rgquidInterfaces, + cguidInterfaceCount, mszCards, pcchCards); +} + +/*****************************************************************************/ +LONG WINAPI +SCardListCardsW(SCARDCONTEXT hContext, LPCBYTE pbAtr, + LPCGUID rgquidInterfaces, DWORD cguidInterfaceCount, + LPWSTR mszCards, LPDWORD pcchCards) +{ + LLOGLN(0, ("SCardListCardsW:")); + return aSCardListCardsW(hContext, pbAtr, rgquidInterfaces, + cguidInterfaceCount, mszCards, pcchCards); +} + +/*****************************************************************************/ +LONG WINAPI +SCardListInterfacesA(SCARDCONTEXT hContext, LPCSTR szCard, + LPGUID pguidInterfaces, LPDWORD pcguidInterfaces) +{ + LLOGLN(0, ("SCardListInterfacesA:")); + return aSCardListInterfacesA(hContext, szCard, pguidInterfaces, + pcguidInterfaces); +} + +/*****************************************************************************/ +LONG WINAPI +SCardListInterfacesW(SCARDCONTEXT hContext, LPCWSTR szCard, + LPGUID pguidInterfaces, LPDWORD pcguidInterfaces) +{ + LLOGLN(0, ("SCardListInterfacesW:")); + return aSCardListInterfacesW(hContext, szCard, pguidInterfaces, + pcguidInterfaces); +} + +/*****************************************************************************/ +LONG WINAPI +SCardGetProviderIdA(SCARDCONTEXT hContext, LPCSTR szCard, + LPGUID pguidProviderId) +{ + LLOGLN(0, ("SCardGetProviderIdA:")); + return aSCardGetProviderIdA(hContext, szCard, pguidProviderId); +} + +/****************************************************************************/ +LONG WINAPI +SCardGetProviderIdW(SCARDCONTEXT hContext, LPCWSTR szCard, + LPGUID pguidProviderId) +{ + LLOGLN(0, ("SCardGetProviderIdW:")); + return aSCardGetProviderIdW(hContext, szCard, pguidProviderId); +} + +/****************************************************************************/ +LONG WINAPI +SCardGetCardTypeProviderNameA(SCARDCONTEXT hContext, LPCSTR szCardName, + DWORD dwProviderId, LPSTR szProvider, + LPDWORD pcchProvider) +{ + LLOGLN(0, ("SCardGetCardTypeProviderNameA:")); + return aSCardGetCardTypeProviderNameA(hContext, szCardName, dwProviderId, + szProvider, pcchProvider); +} + +/*****************************************************************************/ +LONG WINAPI +SCardGetCardTypeProviderNameW(SCARDCONTEXT hContext, LPCWSTR szCardName, + DWORD dwProviderId, LPWSTR szProvider, + LPDWORD pcchProvider) +{ + LLOGLN(0, ("SCardGetCardTypeProviderNameW:")); + return aSCardGetCardTypeProviderNameW(hContext, szCardName, dwProviderId, + szProvider, pcchProvider); +} + +/*****************************************************************************/ +LONG WINAPI +SCardIntroduceReaderGroupA(SCARDCONTEXT hContext, LPCSTR szGroupName) +{ + LLOGLN(0, ("SCardIntroduceReaderGroupA:")); + return aSCardIntroduceReaderGroupA(hContext, szGroupName); +} + +/*****************************************************************************/ +LONG WINAPI +SCardIntroduceReaderGroupW(SCARDCONTEXT hContext, LPCWSTR szGroupName) +{ + LLOGLN(0, ("SCardIntroduceReaderGroupW:")); + return aSCardIntroduceReaderGroupW(hContext, szGroupName); +} + +/*****************************************************************************/ +LONG WINAPI +SCardForgetReaderGroupA(SCARDCONTEXT hContext, LPCSTR szGroupName) +{ + LLOGLN(0, ("SCardForgetReaderGroupA:")); + return aSCardForgetReaderGroupA(hContext, szGroupName); +} + +/*****************************************************************************/ +LONG WINAPI +SCardForgetReaderGroupW(SCARDCONTEXT hContext, LPCWSTR szGroupName) +{ + LLOGLN(0, ("SCardForgetReaderGroupW:")); + return aSCardForgetReaderGroupW(hContext, szGroupName); +} + +/*****************************************************************************/ +LONG WINAPI +SCardIntroduceReaderA(SCARDCONTEXT hContext, LPCSTR szReaderName, + LPCSTR szDeviceName) +{ + LLOGLN(0, ("SCardIntroduceReaderA:")); + return aSCardIntroduceReaderA(hContext, szReaderName, szDeviceName); +} + +/*****************************************************************************/ +LONG WINAPI +SCardIntroduceReaderW(SCARDCONTEXT hContext, LPCWSTR szReaderName, + LPCWSTR szDeviceName) +{ + LLOGLN(0, ("SCardIntroduceReaderW:")); + return aSCardIntroduceReaderW(hContext, szReaderName, szDeviceName); +} + +/*****************************************************************************/ +LONG WINAPI +SCardForgetReaderA(SCARDCONTEXT hContext, LPCSTR szReaderName) +{ + LLOGLN(0, ("SCardForgetReaderA:")); + return aSCardForgetReaderA(hContext, szReaderName); +} + +/*****************************************************************************/ +LONG WINAPI +SCardForgetReaderW(SCARDCONTEXT hContext, LPCWSTR szReaderName) +{ + LLOGLN(0, ("SCardForgetReaderW:")); + return aSCardForgetReaderW(hContext, szReaderName); +} + +/*****************************************************************************/ +LONG WINAPI +SCardAddReaderToGroupA(SCARDCONTEXT hContext, LPCSTR szReaderName, + LPCSTR szGroupName) +{ + LLOGLN(0, ("SCardAddReaderToGroupA:")); + return aSCardAddReaderToGroupA(hContext, szReaderName, szGroupName); +} + +/*****************************************************************************/ +LONG WINAPI +SCardAddReaderToGroupW(SCARDCONTEXT hContext, LPCWSTR szReaderName, + LPCWSTR szGroupName) +{ + LLOGLN(0, ("SCardAddReaderToGroupW:")); + return aSCardAddReaderToGroupW(hContext, szReaderName, szGroupName); +} + +/*****************************************************************************/ +LONG WINAPI +SCardRemoveReaderFromGroupA(SCARDCONTEXT hContext, LPCSTR szReaderName, + LPCSTR szGroupName) +{ + LLOGLN(0, ("SCardRemoveReaderFromGroupA:")); + return aSCardRemoveReaderFromGroupA(hContext, szReaderName, szGroupName); +} + +/*****************************************************************************/ +LONG WINAPI +SCardRemoveReaderFromGroupW(SCARDCONTEXT hContext, LPCWSTR szReaderName, + LPCWSTR szGroupName) +{ + LLOGLN(0, ("SCardRemoveReaderFromGroupW:")); + return aSCardRemoveReaderFromGroupW(hContext, szReaderName, szGroupName); +} + +/*****************************************************************************/ +LONG WINAPI +SCardIntroduceCardTypeA(SCARDCONTEXT hContext, LPCSTR szCardName, + LPCGUID pguidPrimaryProvider, + LPCGUID rgguidInterfaces, + DWORD dwInterfaceCount, LPCBYTE pbAtr, + LPCBYTE pbAtrMask, DWORD cbAtrLen) +{ + LLOGLN(0, ("SCardIntroduceCardTypeA:")); + return aSCardIntroduceCardTypeA(hContext, szCardName, pguidPrimaryProvider, + rgguidInterfaces, dwInterfaceCount, pbAtr, + pbAtrMask, cbAtrLen); +} + +/*****************************************************************************/ +LONG WINAPI +SCardIntroduceCardTypeW(SCARDCONTEXT hContext, LPCWSTR szCardName, + LPCGUID pguidPrimaryProvider, LPCGUID rgguidInterfaces, + DWORD dwInterfaceCount, LPCBYTE pbAtr, + LPCBYTE pbAtrMask, DWORD cbAtrLen) +{ + LLOGLN(0, ("SCardIntroduceCardTypeW:")); + return aSCardIntroduceCardTypeW(hContext, szCardName, pguidPrimaryProvider, + rgguidInterfaces, dwInterfaceCount, pbAtr, + pbAtrMask, cbAtrLen); +} + +/*****************************************************************************/ +LONG WINAPI +SCardSetCardTypeProviderNameA(SCARDCONTEXT hContext, LPCSTR szCardName, + DWORD dwProviderId, LPCSTR szProvider) +{ + LLOGLN(0, ("SCardSetCardTypeProviderNameA:")); + return aSCardSetCardTypeProviderNameA(hContext, szCardName, + dwProviderId, szProvider); +} + +/*****************************************************************************/ +LONG WINAPI +SCardSetCardTypeProviderNameW(SCARDCONTEXT hContext, LPCWSTR szCardName, + DWORD dwProviderId, LPCWSTR szProvider) +{ + LLOGLN(0, ("SCardSetCardTypeProviderNameW:")); + return aSCardSetCardTypeProviderNameW(hContext, szCardName, + dwProviderId, szProvider); +} + +/*****************************************************************************/ +LONG WINAPI +SCardForgetCardTypeA(SCARDCONTEXT hContext, LPCSTR szCardName) +{ + LLOGLN(0, ("SCardForgetCardTypeA:")); + return aSCardForgetCardTypeA(hContext, szCardName); +} + +/*****************************************************************************/ +LONG WINAPI +SCardForgetCardTypeW(SCARDCONTEXT hContext, LPCWSTR szCardName) +{ + LLOGLN(0, ("SCardForgetCardTypeW:")); + return aSCardForgetCardTypeW(hContext, szCardName); +} + +/*****************************************************************************/ +LONG WINAPI +SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem) +{ + LLOGLN(0, ("SCardFreeMemory:")); + return aSCardFreeMemory(hContext, pvMem); +} + +/*****************************************************************************/ +LONG WINAPI +SCardLocateCardsA(SCARDCONTEXT hContext, LPCSTR mszCards, + LPSCARD_READERSTATEA rgReaderStates, DWORD cReaders) +{ + LLOGLN(0, ("SCardLocateCardsA:")); + return aSCardLocateCardsA(hContext, mszCards, rgReaderStates, cReaders); +} + +/*****************************************************************************/ +LONG WINAPI +SCardLocateCardsW(SCARDCONTEXT hContext, LPCWSTR mszCards, + LPSCARD_READERSTATEW rgReaderStates, DWORD cReaders) +{ + LLOGLN(0, ("SCardLocateCardsW:")); + return aSCardLocateCardsW(hContext, mszCards, rgReaderStates, cReaders); +} + +/*****************************************************************************/ +LONG WINAPI +SCardGetStatusChangeA(SCARDCONTEXT hContext, DWORD dwTimeout, + LPSCARD_READERSTATEA rgReaderStates, + DWORD cReaders) +{ + LLOGLN(0, ("SCardGetStatusChangeA:")); + return aSCardGetStatusChangeA(hContext, dwTimeout, rgReaderStates, cReaders); +} + +/*****************************************************************************/ +LONG WINAPI +SCardGetStatusChangeW(SCARDCONTEXT hContext, DWORD dwTimeout, + LPSCARD_READERSTATEW rgReaderStates, + DWORD cReaders) +{ + LLOGLN(0, ("SCardGetStatusChangeW:")); + return aSCardGetStatusChangeW(hContext, dwTimeout, rgReaderStates, cReaders); +} + +/*****************************************************************************/ +LONG WINAPI +SCardCancel(SCARDCONTEXT hContext) +{ + LLOGLN(0, ("SCardCancel:")); + return aSCardCancel(hContext); +} + +/*****************************************************************************/ +LONG WINAPI +SCardConnectA(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, + DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, + LPDWORD pdwActiveProtocol) +{ + LLOGLN(0, ("SCardConnectA:")); + return aSCardConnectA(hContext, szReader, dwShareMode, + dwPreferredProtocols, phCard, + pdwActiveProtocol); +} + +/*****************************************************************************/ +LONG WINAPI +SCardConnectW(SCARDCONTEXT hContext, LPCWSTR szReader, DWORD dwShareMode, + DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, + LPDWORD pdwActiveProtocol) +{ + LLOGLN(0, ("SCardConnectW:")); + return aSCardConnectW(hContext, szReader, dwShareMode, + dwPreferredProtocols, phCard, + pdwActiveProtocol); +} + +/*****************************************************************************/ +LONG WINAPI +SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode, + DWORD dwPreferredProtocols, DWORD dwInitialization, + LPDWORD pdwActiveProtocol) +{ + LLOGLN(0, ("SCardReconnect:")); + return SCardReconnect(hCard, dwShareMode, dwPreferredProtocols, + dwInitialization, pdwActiveProtocol); +} + +/*****************************************************************************/ +LONG WINAPI +SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition) +{ + LLOGLN(0, ("SCardDisconnect:")); + return aSCardDisconnect(hCard, dwDisposition); +} + +/*****************************************************************************/ +LONG WINAPI +SCardBeginTransaction(SCARDHANDLE hCard) +{ + LLOGLN(0, ("SCardBeginTransaction:")); + return aSCardBeginTransaction(hCard); +} + +/*****************************************************************************/ +LONG WINAPI +SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition) +{ + LLOGLN(0, ("SCardEndTransaction:")); + return aSCardEndTransaction(hCard, dwDisposition); +} + +/*****************************************************************************/ +LONG WINAPI +SCardCancelTransaction(SCARDHANDLE hCard) +{ + LLOGLN(0, ("SCardCancelTransaction:")); + return aSCardCancelTransaction(hCard); +} + +/*****************************************************************************/ +LONG WINAPI +SCardState(SCARDHANDLE hCard, LPDWORD pdwState, LPDWORD pdwProtocol, + LPBYTE pbAtr, LPDWORD pcbAtrLen) +{ + LLOGLN(0, ("SCardState:")); + return aSCardState(hCard, pdwState, pdwProtocol, pbAtr, pcbAtrLen); +} + +/*****************************************************************************/ +LONG WINAPI +SCardStatusA(SCARDHANDLE hCard, LPSTR szReaderName, LPDWORD pcchReaderLen, + LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, + LPDWORD pcbAtrLen) +{ + LLOGLN(0, ("SCardStatusA:")); + return aSCardStatusA(hCard, szReaderName, pcchReaderLen, + pdwState, pdwProtocol, pbAtr, pcbAtrLen); +} + +/*****************************************************************************/ +LONG WINAPI +SCardStatusW(SCARDHANDLE hCard, LPWSTR szReaderName, LPDWORD pcchReaderLen, + LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, + LPDWORD pcbAtrLen) +{ + LONG rv; + + LLOGLN(0, ("SCardStatusW:")); + LLOGLN(0, (" cchReaderLen %d", *pcchReaderLen)); + LLOGLN(0, (" cbAtrLen %d", *pcbAtrLen)); + rv = aSCardStatusW(hCard, szReaderName, pcchReaderLen, + pdwState, pdwProtocol, pbAtr, pcbAtrLen); + LLOGLN(0, (" rv %d cchReaderLen %d", rv, *pcchReaderLen)); + return rv; +} + +/*****************************************************************************/ +LONG WINAPI +SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci, + LPCBYTE pbSendBuffer, DWORD cbSendLength, + LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer, + LPDWORD pcbRecvLength) +{ + LONG rv; + + LLOGLN(10, ("SCardTransmit:")); + LLOGLN(10, (" hCard %p", hCard)); + LLOGLN(10, (" cbSendLength %d", cbSendLength)); + LLOGLN(10, (" cbRecvLength %d", *pcbRecvLength)); + LLOGLN(10, (" pioSendPci->dwProtocol %d", pioSendPci->dwProtocol)); + LLOGLN(10, (" pioSendPci->cbPciLength %d", pioSendPci->cbPciLength)); + LLOGLN(10, (" pioRecvPci %p", pioRecvPci)); + if (pioRecvPci != NULL) + { + LLOGLN(10, (" pioRecvPci->dwProtocol %d", pioRecvPci->dwProtocol)); + LLOGLN(10, (" pioRecvPci->cbPciLength %d", pioRecvPci->cbPciLength)); + } + rv = aSCardTransmit(hCard, pioSendPci, pbSendBuffer, cbSendLength, + pioRecvPci, pbRecvBuffer, pcbRecvLength); + LLOGLN(10, (" rv %d cbRecvLength %d", rv, *pcbRecvLength)); + return rv; +} + +/*****************************************************************************/ +LONG WINAPI +SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID lpInBuffer, + DWORD nInBufferSize, LPVOID lpOutBuffer, + DWORD nOutBufferSize, LPDWORD lpBytesReturned) +{ + LONG rv; + char text[8148]; + + LLOGLN(10, ("SCardControl:")); + LLOGLN(10, (" hCard %p", hCard)); + LLOGLN(10, (" dwControlCode 0x%8.8x", dwControlCode)); + LLOGLN(10, (" lpInBuffer %p", lpInBuffer)); + LLOGLN(10, (" nInBufferSize %d", nInBufferSize)); + LLOGLN(10, (" lpOutBuffer %p", lpOutBuffer)); + LLOGLN(10, (" nOutBufferSize %d", nOutBufferSize)); + LLOGLN(10, (" lpBytesReturned %p", lpBytesReturned)); + rv = aSCardControl(hCard, dwControlCode, + lpInBuffer, nInBufferSize, + lpOutBuffer, nOutBufferSize, + lpBytesReturned); + LLOGLN(10, (" rv %d BytesReturned %d", rv, *lpBytesReturned)); + return rv; +} + +/*****************************************************************************/ +LONG WINAPI +SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, + LPDWORD pcbAttrLen) +{ + LLOGLN(0, ("SCardGetAttrib:")); + return aSCardGetAttrib(hCard, dwAttrId, pbAttr, pcbAttrLen); +} + +/*****************************************************************************/ +LONG WINAPI +SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, + DWORD cbAttrLen) +{ + LLOGLN(0, ("SCardSetAttrib:")); + return aSCardSetAttrib(hCard, dwAttrId, pbAttr, cbAttrLen); +} diff --git a/sesman/chansrv/pcsc/wrapper/winscard.def b/sesman/chansrv/pcsc/wrapper/winscard.def new file mode 100755 index 00000000..eb6d18df --- /dev/null +++ b/sesman/chansrv/pcsc/wrapper/winscard.def @@ -0,0 +1,53 @@ +EXPORTS +SCardEstablishContext +SCardReleaseContext +SCardIsValidContext +SCardListReaderGroupsA +SCardListReaderGroupsW +SCardListReadersA +SCardListReadersW +SCardListCardsA +SCardListCardsW +SCardListInterfacesA +SCardListInterfacesW +SCardGetProviderIdA +SCardGetProviderIdW +SCardGetCardTypeProviderNameA +SCardGetCardTypeProviderNameW +SCardIntroduceReaderGroupA +SCardIntroduceReaderGroupW +SCardForgetReaderGroupA +SCardForgetReaderGroupW +SCardIntroduceReaderA +SCardIntroduceReaderW +SCardForgetReaderA +SCardForgetReaderW +SCardAddReaderToGroupA +SCardAddReaderToGroupW +SCardRemoveReaderFromGroupA +SCardRemoveReaderFromGroupW +SCardIntroduceCardTypeA +SCardIntroduceCardTypeW +SCardSetCardTypeProviderNameA +SCardSetCardTypeProviderNameW +SCardForgetCardTypeA +SCardForgetCardTypeW +SCardFreeMemory +SCardLocateCardsA +SCardLocateCardsW +SCardGetStatusChangeA +SCardGetStatusChangeW +SCardCancel +SCardConnectA +SCardConnectW +SCardReconnect +SCardDisconnect +SCardBeginTransaction +SCardEndTransaction +SCardState +SCardStatusA +SCardStatusW +SCardTransmit +SCardControl +SCardGetAttrib +SCardSetAttrib diff --git a/sesman/chansrv/pcsc/xrdp_pcsc.c b/sesman/chansrv/pcsc/xrdp_pcsc.c index 502d3096..f4aaba14 100644 --- a/sesman/chansrv/pcsc/xrdp_pcsc.c +++ b/sesman/chansrv/pcsc/xrdp_pcsc.c @@ -52,9 +52,9 @@ typedef struct _SCARD_IO_REQUEST #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_rgSCardT0Pci = { 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 }; +PCSC_API SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_RAW, 8 }; #define LLOG_LEVEL 5 #define LLOGLN(_level, _args) \ @@ -243,16 +243,20 @@ send_message(int code, char *data, int bytes) { char header[8]; + pthread_mutex_lock(&g_mutex); SET_UINT32(header, 0, bytes); SET_UINT32(header, 4, code); if (send(g_sck, header, 8, 0) != 8) { + pthread_mutex_unlock(&g_mutex); return 1; } if (send(g_sck, data, bytes, 0) != bytes) { + pthread_mutex_unlock(&g_mutex); return 1; } + pthread_mutex_unlock(&g_mutex); return 0; } @@ -262,9 +266,72 @@ get_message(int *code, char *data, int *bytes) { char header[8]; int max_bytes; + int error; + int recv_rv; + int max; + int lcode; + struct timeval time; + fd_set rd_set; + + LLOGLN(10, ("get_message:")); + max = g_sck + 1; + while (1) + { + LLOGLN(10, ("get_message: loop")); + time.tv_sec = 1; + time.tv_usec = 0; + FD_ZERO(&rd_set); + FD_SET(((unsigned int)g_sck), &rd_set); + error = select(max, &rd_set, 0, 0, &time); + if (error == 1) + { + pthread_mutex_lock(&g_mutex); + time.tv_sec = 0; + time.tv_usec = 0; + FD_ZERO(&rd_set); + FD_SET(((unsigned int)g_sck), &rd_set); + error = select(max, &rd_set, 0, 0, &time); + if (error == 1) + { + /* just take a look at the next message */ + recv_rv = recv(g_sck, header, 8, MSG_PEEK); + if (recv_rv == 8) + { + lcode = GET_UINT32(header, 4); + if (lcode == *code) + { + /* still have mutex lock */ + break; + } + else + { + LLOGLN(10, ("get_message: lcode %d *code %d", + lcode, *code)); + } + } + else if (recv_rv == 0) + { + pthread_mutex_unlock(&g_mutex); + LLOGLN(0, ("get_message: recv_rv 0, disconnect")); + return 1; + } + else + { + LLOGLN(10, ("get_message: recv_rv %d", recv_rv)); + } + } + else + { + LLOGLN(10, ("get_message: select return %d", error)); + } + pthread_mutex_unlock(&g_mutex); + usleep(1000); + } + } if (recv(g_sck, header, 8, 0) != 8) { + pthread_mutex_unlock(&g_mutex); return 1; } max_bytes = *bytes; @@ -272,12 +339,15 @@ get_message(int *code, char *data, int *bytes) *code = GET_UINT32(header, 4); if (*bytes > max_bytes) { + pthread_mutex_unlock(&g_mutex); return 1; } if (recv(g_sck, data, *bytes, 0) != *bytes) { + pthread_mutex_unlock(&g_mutex); return 1; } + pthread_mutex_unlock(&g_mutex); return 0; } @@ -302,28 +372,24 @@ SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, 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; + code = SCARD_ESTABLISH_CONTEXT; 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)); @@ -346,28 +412,24 @@ SCardReleaseContext(SCARDCONTEXT hContext) 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; + code = SCARD_RELEASE_CONTEXT; 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; @@ -383,8 +445,6 @@ SCardIsValidContext(SCARDCONTEXT hContext) 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; } @@ -401,9 +461,9 @@ SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, int offset; LLOGLN(10, ("SCardConnect:")); - LLOGLN(10, ("SCardConnect: hContext %p szReader %s dwShareMode %d " + LLOGLN(10, ("SCardConnect: hContext 0x%8.8x szReader %s dwShareMode %d " "dwPreferredProtocols %d", - (void*)hContext, szReader, dwShareMode, dwPreferredProtocols)); + hContext, szReader, dwShareMode, dwPreferredProtocols)); if (g_sck == -1) { LLOGLN(0, ("SCardConnect: error, not connected")); @@ -425,31 +485,29 @@ SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD 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; + code = SCARD_CONNECT; 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)); + LLOGLN(10, ("SCardConnect: got status 0x%8.8x hCard 0x%8.8x " + "dwActiveProtocol %d", + status, *phCard, *pdwActiveProtocol)); return status; } @@ -465,8 +523,6 @@ SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode, 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; } @@ -479,35 +535,32 @@ SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition) int bytes; int status; - LLOGLN(10, ("SCardDisconnect:")); + LLOGLN(10, ("SCardDisconnect: hCard 0x%8.8x dwDisposition %d", + hCard, dwDisposition)); 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; + code = SCARD_DISCONNECT; 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; @@ -522,34 +575,35 @@ SCardBeginTransaction(SCARDHANDLE hCard) int bytes; int status; - LLOGLN(10, ("SCardBeginTransaction:")); + LLOGLN(10, ("SCardBeginTransaction: hCard 0x%8.8x", hCard)); + if (hCard == 0) + { + LLOGLN(0, ("SCardBeginTransaction: error, bad hCard")); + return SCARD_F_INTERNAL_ERROR; + } 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; + code = SCARD_BEGIN_TRANSACTION; 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; @@ -570,29 +624,25 @@ SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition) 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; + code = SCARD_END_TRANSACTION; 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; @@ -613,45 +663,50 @@ SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName, LPDWORD pcchReaderLen, int to_copy; LLOGLN(10, ("SCardStatus:")); + if (hCard == 0) + { + LLOGLN(0, ("SCardStatus: error, bad hCard")); + return SCARD_F_INTERNAL_ERROR; + } if (g_sck == -1) { LLOGLN(0, ("SCardStatus: error, not connected")); return SCARD_F_INTERNAL_ERROR; } + LLOGLN(10, (" hCard 0x%8.8x", hCard)); + LLOGLN(10, (" cchReaderLen %d", *pcchReaderLen)); + LLOGLN(10, (" cbAtrLen %d", *pcbAtrLen)); + 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; + code = SCARD_STATUS; 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)); + LLOGLN(10, ("SCardStatus: cchReaderLen in %d", *pcchReaderLen)); offset = 0; *pcchReaderLen = GET_UINT32(msg, offset); - LLOGLN(10, ("SCardStatus: cchReaderLen %d", *pcchReaderLen)); + LLOGLN(10, ("SCardStatus: cchReaderLen out %d", *pcchReaderLen)); offset += 4; if (cchReaderLen > 0) { @@ -663,7 +718,7 @@ SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName, LPDWORD pcchReaderLen, memcpy(mszReaderName, msg + offset, to_copy); mszReaderName[to_copy] = 0; } - LLOGLN(10, ("SCardStatus: mszReaderName %s", mszReaderName)); + LLOGLN(10, ("SCardStatus: mszReaderName out %s", mszReaderName)); offset += *pcchReaderLen; *pdwState = GET_UINT32(msg, offset); LLOGLN(10, ("SCardStatus: dwState %d", *pdwState)); @@ -689,12 +744,17 @@ SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, LPSCARD_READERSTATE rgReaderStates, DWORD cReaders) { char *msg; + const char *rname; int bytes; int code; int index; int offset; int str_len; int status; + int dwCurrentState; + int dwEventState; + int cbAtr; + char atr[36]; LLOGLN(10, ("SCardGetStatusChange:")); LLOGLN(10, (" dwTimeout %d cReaders %d", dwTimeout, cReaders)); @@ -710,64 +770,108 @@ SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, offset = 12; for (index = 0; index < cReaders; index++) { - str_len = strlen(rgReaderStates[index].szReader); + rgReaderStates[index].dwCurrentState &= ~2; + rgReaderStates[index].dwEventState &= ~2; + rname = rgReaderStates[index].szReader; + if (strcmp(rname, "\\\\?PnP?\\Notification") == 0) + { + LLOGLN(10, (" \\\\?PnP?\\Notification present")); + dwCurrentState = 0; + dwEventState = 0; + cbAtr = 0; + memset(atr, 0, 36); + } + else + { + dwCurrentState = rgReaderStates[index].dwCurrentState; + dwEventState = rgReaderStates[index].dwEventState; + cbAtr = rgReaderStates[index].cbAtr; + memset(atr, 0, 36); + memcpy(atr, rgReaderStates[index].rgbAtr, 33); + } + str_len = strlen(rname); str_len = LMIN(str_len, 99); memset(msg + offset, 0, 100); - memcpy(msg + offset, rgReaderStates[index].szReader, str_len); + memcpy(msg + offset, rname, str_len); + LLOGLN(10, (" in szReader %s", rname)); offset += 100; - LLOGLN(10, (" in dwCurrentState %d", rgReaderStates[index].dwCurrentState)); - SET_UINT32(msg, offset, rgReaderStates[index].dwCurrentState); + LLOGLN(10, (" in dwCurrentState 0x%8.8x", dwCurrentState)); + SET_UINT32(msg, offset, dwCurrentState); offset += 4; - LLOGLN(10, (" in dwEventState %d", rgReaderStates[index].dwEventState)); - SET_UINT32(msg, offset, rgReaderStates[index].dwEventState); + LLOGLN(10, (" in dwEventState 0x%8.8x", dwEventState)); + SET_UINT32(msg, offset, dwEventState); offset += 4; - LLOGLN(10, (" in cbAtr %d", rgReaderStates[index].cbAtr)); - SET_UINT32(msg, offset, rgReaderStates[index].cbAtr); + LLOGLN(10, (" in cbAtr %d", cbAtr)); + SET_UINT32(msg, offset, cbAtr); offset += 4; - memset(msg + offset, 0, 36); - memcpy(msg + offset, rgReaderStates[index].rgbAtr, 33); + memcpy(msg + offset, atr, 36); 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; + code = SCARD_GET_STATUS_CHANGE; 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; + rname = rgReaderStates[index].szReader; +#if 1 + if (strcmp(rname, "\\\\?PnP?\\Notification") == 0) + { + LLOGLN(10, (" out szReader %s", rgReaderStates[index].szReader)); + dwCurrentState = GET_UINT32(msg, offset); + rgReaderStates[index].dwCurrentState = dwCurrentState; + offset += 4; + LLOGLN(10, (" out dwCurrentState 0x%8.8x", dwCurrentState)); + // disable PnP for now + dwEventState = 4; // GET_UINT32(msg, offset); + rgReaderStates[index].dwEventState = dwEventState; + offset += 4; + LLOGLN(10, (" out dwEventState 0x%8.8x", dwEventState)); + cbAtr = GET_UINT32(msg, offset); + rgReaderStates[index].cbAtr = cbAtr; + offset += 4; + LLOGLN(10, (" out cbAtr %d", cbAtr)); + memcpy(rgReaderStates[index].rgbAtr, msg + offset, 33); + offset += 36; + } + else +#endif + { + LLOGLN(10, (" out szReader %s", rgReaderStates[index].szReader)); + dwCurrentState = GET_UINT32(msg, offset); + rgReaderStates[index].dwCurrentState = dwCurrentState; + offset += 4; + LLOGLN(10, (" out dwCurrentState 0x%8.8x", dwCurrentState)); + dwEventState = GET_UINT32(msg, offset); + rgReaderStates[index].dwEventState = dwEventState; + offset += 4; + LLOGLN(10, (" out dwEventState 0x%8.8x", dwEventState)); + cbAtr = GET_UINT32(msg, offset); + rgReaderStates[index].cbAtr = cbAtr; + offset += 4; + LLOGLN(10, (" out cbAtr %d", cbAtr)); + memcpy(rgReaderStates[index].rgbAtr, msg + offset, 33); + offset += 36; + } } status = GET_UINT32(msg, offset); offset += 4; @@ -793,9 +897,10 @@ SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, 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)); + LLOGLN(10, (" hCard 0x%8.8x", hCard)); + LLOGLN(10, (" dwControlCode 0x%8.8x", dwControlCode)); + LLOGLN(10, (" cbSendLength %d", cbSendLength)); + LLOGLN(10, (" cbRecvLength %d", cbRecvLength)); /* #define SCARD_CTL_CODE(code) (0x42000000 + (code)) control_code = (control_code & 0x3ffc) >> 2; @@ -805,7 +910,7 @@ SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, dwControlCode = dwControlCode - 0x42000000; dwControlCode = dwControlCode << 2; dwControlCode = dwControlCode | (49 << 16); - LLOGLN(10, ("SCardControl: dwControlCode 0x%8.8x", dwControlCode)); + LLOGLN(10, (" MS dwControlCode 0x%8.8x", dwControlCode)); msg = (char *) malloc(8192); offset = 0; @@ -819,32 +924,29 @@ SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, 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; + code = SCARD_CONTROL; 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); + LLOGLN(10, (" cbRecvLength %d", *lpBytesReturned)); offset += 4; memcpy(pbRecvBuffer, msg + offset, *lpBytesReturned); offset += *lpBytesReturned; @@ -866,6 +968,7 @@ SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, int offset; int status; int extra_len; + int got_recv_pci; LLOGLN(10, ("SCardTransmit:")); if (g_sck == -1) @@ -873,14 +976,16 @@ SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, LLOGLN(0, ("SCardTransmit: error, not connected")); return SCARD_F_INTERNAL_ERROR; } - LLOGLN(10, ("SCardTransmit: cbSendLength %d", cbSendLength)); - LLOGLN(10, ("SCardTransmit: pioRecvPci %p", pioRecvPci)); + LLOGLN(10, (" hCard 0x%8.8x", hCard)); + LLOGLN(10, (" cbSendLength %d", cbSendLength)); + LLOGLN(10, (" cbRecvLength %d", *pcbRecvLength)); + LLOGLN(10, (" pioSendPci->dwProtocol %d", (int)(pioSendPci->dwProtocol))); + LLOGLN(10, (" pioSendPci->cbPciLength %d", (int)(pioSendPci->cbPciLength))); + LLOGLN(10, (" pioRecvPci %p", pioRecvPci)); if (pioRecvPci != 0) { - LLOGLN(10, ("SCardTransmit: pioRecvPci->dwProtocol %d", - (int)pioRecvPci->dwProtocol)); - LLOGLN(10, ("SCardTransmit: pioRecvPci->cbPciLength %d", - (int)pioRecvPci->cbPciLength)); + LLOGLN(10, (" pioRecvPci->dwProtocol %d", (int)(pioRecvPci->dwProtocol))); + LLOGLN(10, (" pioRecvPci->cbPciLength %d", (int)(pioRecvPci->cbPciLength))); } msg = (char *) malloc(8192); offset = 0; @@ -899,8 +1004,10 @@ SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, offset += 4; memcpy(msg + offset, pbSendBuffer, cbSendLength); offset += cbSendLength; - if ((pioRecvPci == 0) || (pioRecvPci->cbPciLength < 8)) + // TODO figure out why recv pci does not work + if (1 || (pioRecvPci == 0) || (pioRecvPci->cbPciLength < 8)) { + got_recv_pci = 0; SET_UINT32(msg, offset, 0); /* dwProtocol */ offset += 4; SET_UINT32(msg, offset, 0); /* cbPciLength */ @@ -910,6 +1017,7 @@ SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, } else { + got_recv_pci = 1; SET_UINT32(msg, offset, pioRecvPci->dwProtocol); offset += 4; SET_UINT32(msg, offset, pioRecvPci->cbPciLength); @@ -922,32 +1030,28 @@ SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, } 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; + code = SCARD_TRANSMIT; 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) + if (got_recv_pci == 0) { offset += 8; extra_len = GET_UINT32(msg, offset); @@ -966,7 +1070,7 @@ SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, } *pcbRecvLength = GET_UINT32(msg, offset); offset += 4; - LLOGLN(10, ("SCardTransmit: cbRecvLength %d", *pcbRecvLength)); + LLOGLN(10, (" cbRecvLength %d", *pcbRecvLength)); memcpy(pbRecvBuffer, msg + offset, *pcbRecvLength); offset += *pcbRecvLength; status = GET_UINT32(msg, offset); @@ -985,8 +1089,6 @@ SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups, 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; } @@ -1004,41 +1106,58 @@ SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, int status; int offset; int index; + int bytes_groups; + int val; + int llen; char reader[100]; LLOGLN(10, ("SCardListReaders:")); + LLOGLN(10, ("SCardListReaders: mszGroups %s", mszGroups)); + LLOGLN(10, ("SCardListReaders: *pcchReaders %d", *pcchReaders)); 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) + offset = 0; + SET_UINT32(msg, offset, hContext); + offset += 4; + bytes_groups = 0; + if (mszGroups != 0) + { + bytes_groups = strlen(mszGroups); + } + SET_UINT32(msg, offset, bytes_groups); + offset += 4; + memcpy(msg + offset, mszGroups, bytes_groups); + offset += bytes_groups; + val = *pcchReaders; + SET_UINT32(msg, offset, val); + offset += 4; + if (send_message(SCARD_LIST_READERS, msg, offset) != 0) { LLOGLN(0, ("SCardListReaders: error, send_message")); free(msg); - pthread_mutex_unlock(&g_mutex); return SCARD_F_INTERNAL_ERROR; } bytes = 8192; + code = SCARD_LIST_READERS; 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; + llen = GET_UINT32(msg, offset); + offset += 4; num_readers = GET_UINT32(msg, offset); offset += 4; LLOGLN(10, ("SCardListReaders: mszReaders %p pcchReaders %p num_readers %d", @@ -1059,7 +1178,12 @@ SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, reader_names[reader_names_index] = 0; reader_names_index++; status = GET_UINT32(msg, offset); + LLOGLN(10, ("SCardListReaders: status 0x%8.8x", status)); offset += 4; + if (mszReaders == 0) + { + reader_names_index = llen / 2; + } if (pcchReaders != 0) { *pcchReaders = reader_names_index; @@ -1083,8 +1207,6 @@ SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem) 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; } @@ -1092,15 +1214,38 @@ SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem) PCSC_API LONG SCardCancel(SCARDCONTEXT hContext) { - LLOGLN(0, ("SCardCancel:")); + char msg[256]; + int code; + int bytes; + int status; + + LLOGLN(10, ("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; + SET_UINT32(msg, 0, hContext); + if (send_message(SCARD_CANCEL, msg, 4) != 0) + { + LLOGLN(0, ("SCardCancel: error, send_message")); + return SCARD_F_INTERNAL_ERROR; + } + bytes = 256; + code = SCARD_CANCEL; + if (get_message(&code, msg, &bytes) != 0) + { + LLOGLN(0, ("SCardCancel: error, get_message")); + return SCARD_F_INTERNAL_ERROR; + } + if ((code != SCARD_RELEASE_CONTEXT) || (bytes != 4)) + { + LLOGLN(0, ("SCardCancel: error, bad code")); + return SCARD_F_INTERNAL_ERROR; + } + status = GET_UINT32(msg, 0); + LLOGLN(10, ("SCardCancel: got status 0x%8.8x", status)); + return status; } /*****************************************************************************/ @@ -1114,8 +1259,6 @@ SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, 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; } @@ -1130,8 +1273,6 @@ SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, 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; } @@ -1139,7 +1280,7 @@ SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, PCSC_API char * pcsc_stringify_error(const long code) { - LLOGLN(10, ("pcsc_stringify_error: %d", (int)code)); + LLOGLN(10, ("pcsc_stringify_error: 0x%8.8x", (int)code)); switch (code) { case SCARD_S_SUCCESS: diff --git a/sesman/chansrv/pulse/Makefile b/sesman/chansrv/pulse/Makefile index 6efbfc16..da1a89a1 100644 --- a/sesman/chansrv/pulse/Makefile +++ b/sesman/chansrv/pulse/Makefile @@ -1,18 +1,17 @@ +# +# build xrdp pulseaudio modules +# +PULSE_DIR = /home/lk/pulseaudio-1.1 +CFLAGS = -Wall -O2 -I$(PULSE_DIR) -I$(PULSE_DIR)/src -DHAVE_CONFIG_H -fPIC -#PULSE_DIR=/home/jay/temp/pulseaudio-0.9.21 -#PULSE_DIR=/home/jay/pulseaudio-0.9.22 -#PULSE_DIR=/home/jay/pulseaudio-0.9.21 -PULSE_DIR=/home/jay/pulseaudio-2.0 +all: module-xrdp-sink.so module-xrdp-source.so -OBJS = module-xrdp-sink.o +module-xrdp-sink.so: module-xrdp-sink.o + $(CC) $(LDFLAGS) -shared -o module-xrdp-sink.so module-xrdp-sink.o -CFLAGS = -Wall -O2 -I$(PULSE_DIR) -I$(PULSE_DIR)/src -DHAVE_CONFIG_H -fPIC - -all: module-xrdp-sink.so - -module-xrdp-sink.so: $(OBJS) - $(CC) $(LDFLAGS) -shared -o module-xrdp-sink.so $(OBJS) +module-xrdp-source.so: module-xrdp-source.o + $(CC) $(LDFLAGS) -shared -o module-xrdp-source.so module-xrdp-source.o clean: - rm -f $(OBJS) module-xrdp-sink.so + rm -f module-xrdp-sink.o module-xrdp-sink.so module-xrdp-source.o module-xrdp-source.so diff --git a/sesman/chansrv/pulse/module-xrdp-sink.c b/sesman/chansrv/pulse/module-xrdp-sink.c index 3f09b727..d56a4883 100644 --- a/sesman/chansrv/pulse/module-xrdp-sink.c +++ b/sesman/chansrv/pulse/module-xrdp-sink.c @@ -72,10 +72,10 @@ PA_MODULE_USAGE( "channels=<number of channels> " "channel_map=<channel map>"); -#define DEFAULT_SINK_NAME "xrdp" +#define DEFAULT_SINK_NAME "xrdp-sink" #define BLOCK_USEC 30000 //#define BLOCK_USEC (PA_USEC_PER_SEC * 2) -#define CHANSRV_PORT_STR "/tmp/.xrdp/xrdp_chansrv_audio_socket_%d" +#define CHANSRV_PORT_STR "/tmp/.xrdp/xrdp_chansrv_audio_out_socket_%d" struct userdata { pa_core *core; diff --git a/sesman/chansrv/pulse/module-xrdp-source-symdef.h b/sesman/chansrv/pulse/module-xrdp-source-symdef.h new file mode 100644 index 00000000..e0467648 --- /dev/null +++ b/sesman/chansrv/pulse/module-xrdp-source-symdef.h @@ -0,0 +1,29 @@ +#ifndef foomodulenullsourcesymdeffoo +#define foomodulenullsourcesymdeffoo + +#include <pulsecore/core.h> +#include <pulsecore/module.h> +#include <pulsecore/macro.h> + +#define pa__init module_xrdp_source_LTX_pa__init +#define pa__done module_xrdp_source_LTX_pa__done +#define pa__get_author module_xrdp_source_LTX_pa__get_author +#define pa__get_description module_xrdp_source_LTX_pa__get_description +#define pa__get_usage module_xrdp_source_LTX_pa__get_usage +#define pa__get_version module_xrdp_source_LTX_pa__get_version +#define pa__get_deprecated module_xrdp_source_LTX_pa__get_deprecated +#define pa__load_once module_xrdp_source_LTX_pa__load_once +#define pa__get_n_used module_xrdp_source_LTX_pa__get_n_used + +int pa__init(pa_module*m); +void pa__done(pa_module*m); +int pa__get_n_used(pa_module*m); + +const char* pa__get_author(void); +const char* pa__get_description(void); +const char* pa__get_usage(void); +const char* pa__get_version(void); +const char* pa__get_deprecated(void); +pa_bool_t pa__load_once(void); + +#endif diff --git a/sesman/chansrv/pulse/module-xrdp-source.c b/sesman/chansrv/pulse/module-xrdp-source.c new file mode 100644 index 00000000..2d7ec4fa --- /dev/null +++ b/sesman/chansrv/pulse/module-xrdp-source.c @@ -0,0 +1,460 @@ +/*** + This file is part of PulseAudio. + + Copyright 2004-2008 Lennart Poettering + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include <sys/socket.h> +#include <sys/un.h> + +#include <pulse/rtclock.h> +#include <pulse/timeval.h> +#include <pulse/xmalloc.h> + +#include <pulsecore/core-util.h> +#include <pulsecore/log.h> +#include <pulsecore/macro.h> +#include <pulsecore/modargs.h> +#include <pulsecore/module.h> +#include <pulsecore/rtpoll.h> +#include <pulsecore/source.h> +#include <pulsecore/thread-mq.h> +#include <pulsecore/thread.h> + +#include "module-xrdp-source-symdef.h" + +PA_MODULE_AUTHOR("Laxmikant Rashinkar"); +PA_MODULE_DESCRIPTION("xrdp source"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); +PA_MODULE_USAGE( + "format=<sample format> " + "channels=<number of channels> " + "rate=<sample rate> " + "source_name=<name of source> " + "channel_map=<channel map> " + "description=<description for the source> " + "latency_time=<latency time in ms>"); + +#define DEFAULT_SOURCE_NAME "xrdp-source" +#define DEFAULT_LATENCY_TIME 10 +#define MAX_LATENCY_USEC (PA_USEC_PER_SEC * 2) +#define CHANSRV_PORT_STR "/tmp/.xrdp/xrdp_chansrv_audio_in_socket_%d" + +struct userdata { + pa_core *core; + pa_module *module; + pa_source *source; + + pa_thread *thread; + pa_thread_mq thread_mq; + pa_rtpoll *rtpoll; + + size_t block_size; + + pa_usec_t block_usec; + pa_usec_t timestamp; + pa_usec_t latency_time; + + /* xrdp stuff */ + int fd; /* UDS connection to xrdp chansrv */ + int display_num; /* X display number */ + int want_src_data; +}; + +static const char* const valid_modargs[] = { + "rate", + "format", + "channels", + "source_name", + "channel_map", + "description", + "latency_time", + NULL +}; + +static int get_display_num_from_display(char *display_text) ; + +static int source_process_msg(pa_msgobject *o, int code, void *data, + int64_t offset, pa_memchunk *chunk) { + + struct userdata *u = PA_SOURCE(o)->userdata; + + switch (code) { + case PA_SOURCE_MESSAGE_SET_STATE: + + if (PA_PTR_TO_UINT(data) == PA_SOURCE_RUNNING) + u->timestamp = pa_rtclock_now(); + + break; + + case PA_SOURCE_MESSAGE_GET_LATENCY: { + pa_usec_t now; + + now = pa_rtclock_now(); + *((pa_usec_t*) data) = u->timestamp > now ? u->timestamp - now : 0; + + return 0; + } + } + + return pa_source_process_msg(o, code, data, offset, chunk); +} + +static void source_update_requested_latency_cb(pa_source *s) { + struct userdata *u; + + pa_source_assert_ref(s); + u = s->userdata; + pa_assert(u); + + u->block_usec = pa_source_get_requested_latency_within_thread(s); +} + +static int data_get(struct userdata *u, pa_memchunk *chunk) { + + int fd; + int bytes; + struct sockaddr_un s; + char *data; + char buf[11]; + unsigned char ubuf[10]; + + if (u->fd == 0) { + /* connect to xrdp unix domain socket */ + fd = socket(PF_LOCAL, SOCK_STREAM, 0); + memset(&s, 0, sizeof(s)); + s.sun_family = AF_UNIX; + bytes = sizeof(s.sun_path) - 1; + snprintf(s.sun_path, bytes, CHANSRV_PORT_STR, u->display_num); + pa_log_debug("Trying to connect to %s", s.sun_path); + + if (connect(fd, (struct sockaddr *) &s, sizeof(struct sockaddr_un)) != 0) { + pa_log_debug("Connect failed"); + close(fd); + return -1; + } + + pa_log("Connected ok, fd=%d", fd); + pa_log_debug("###### connected to xrdp audio_in socket"); + u->fd = fd; + } + + data = (char *) pa_memblock_acquire(chunk->memblock); + + if (!u->want_src_data) { + char buf[12]; + + buf[0] = 0; + buf[1] = 0; + buf[2] = 0; + buf[3] = 0; + buf[4] = 11; + buf[5] = 0; + buf[6] = 0; + buf[7] = 0; + buf[8] = 1; + buf[9] = 0; + buf[10] = 0; + + send(u->fd, buf, 11, 0); + u->want_src_data = 1; + pa_log_debug("###### started recording"); + } + + /* ask for more data */ + buf[0] = 0; + buf[1] = 0; + buf[2] = 0; + buf[3] = 0; + buf[4] = 11; + buf[5] = 0; + buf[6] = 0; + buf[7] = 0; + buf[8] = 3; + buf[9] = (unsigned char) chunk->length; + buf[10] = (unsigned char) ((chunk->length >> 8) & 0xff); + + send(u->fd, buf, 11, 0); + + /* read length of data available */ + recv(u->fd, ubuf, 2, 0); + bytes = ((ubuf[1] << 8) & 0xff00) | (ubuf[0] & 0xff); + + if (bytes == 0) { + pa_memblock_release(chunk->memblock); + return 0; + } + + /* get data */ + bytes = recv(u->fd, data, bytes, 0); + + pa_memblock_release(chunk->memblock); + + return bytes; +} + +static void thread_func(void *userdata) { + struct userdata *u = userdata; + + pa_assert(u); + pa_thread_mq_install(&u->thread_mq); + u->timestamp = pa_rtclock_now(); + + for (;;) { + int ret; + + /* Generate some null data */ + if (u->source->thread_info.state == PA_SOURCE_RUNNING) { + pa_usec_t now; + pa_memchunk chunk; + + now = pa_rtclock_now(); + + if ((chunk.length = pa_usec_to_bytes(now - u->timestamp, &u->source->sample_spec)) > 0) { + chunk.memblock = pa_memblock_new(u->core->mempool, (size_t) -1); /* or chunk.length? */ + chunk.index = 0; + data_get(u, &chunk); + pa_source_post(u->source, &chunk); + pa_memblock_unref(chunk.memblock); + u->timestamp = now; + } + + pa_rtpoll_set_timer_absolute(u->rtpoll, u->timestamp + u->latency_time * PA_USEC_PER_MSEC); + } else { + if (u->want_src_data) + { + /* we dont want source data anymore */ + char buf[12]; + + buf[0] = 0; + buf[1] = 0; + buf[2] = 0; + buf[3] = 0; + buf[4] = 11; + buf[5] = 0; + buf[6] = 0; + buf[7] = 0; + buf[8] = 2; + buf[9] = 0; + buf[10] = 0; + + send(u->fd, buf, 11, 0); + u->want_src_data = 0; + pa_log_debug("###### stopped recording"); + } + pa_rtpoll_set_timer_disabled(u->rtpoll); + } + + /* Hmm, nothing to do. Let's sleep */ + if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) + goto fail; + + if (ret == 0) + goto finish; + } + +fail: + /* If this was no regular exit from the loop we have to continue + * processing messages until we received PA_MESSAGE_SHUTDOWN */ + pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL); + pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN); + +finish: + pa_log_debug("###### thread shutting down"); +} + +int pa__init(pa_module *m) { + struct userdata *u = NULL; + pa_sample_spec ss; + pa_channel_map map; + pa_modargs *ma = NULL; + pa_source_new_data data; + uint32_t latency_time = DEFAULT_LATENCY_TIME; + + pa_assert(m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log("Failed to parse module arguments."); + goto fail; + } + +#if 0 + ss = m->core->default_sample_spec; +#else + ss.format = PA_SAMPLE_S16LE; + ss.rate = 22050; + ss.channels = 2; +#endif + + map = m->core->default_channel_map; + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { + pa_log("Invalid sample format specification or channel map"); + goto fail; + } + + m->userdata = u = pa_xnew0(struct userdata, 1); + u->core = m->core; + u->module = m; + u->rtpoll = pa_rtpoll_new(); + pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll); + + pa_source_new_data_init(&data); + data.driver = __FILE__; + data.module = m; + pa_source_new_data_set_name(&data, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME)); + pa_source_new_data_set_sample_spec(&data, &ss); + pa_source_new_data_set_channel_map(&data, &map); + //pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, pa_modargs_get_value(ma, "description", "Null Input")); + pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, pa_modargs_get_value(ma, "description", "xrdp Input")); + pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, "abstract"); + + u->source = pa_source_new(m->core, &data, PA_SOURCE_LATENCY | PA_SOURCE_DYNAMIC_LATENCY); + pa_source_new_data_done(&data); + + if (!u->source) { + pa_log("Failed to create source object."); + goto fail; + } + + u->latency_time = DEFAULT_LATENCY_TIME; + if (pa_modargs_get_value_u32(ma, "latency_time", &latency_time) < 0) { + pa_log("Failed to parse latency_time value."); + goto fail; + } + u->latency_time = latency_time; + + u->source->parent.process_msg = source_process_msg; + u->source->update_requested_latency = source_update_requested_latency_cb; + u->source->userdata = u; + + pa_source_set_asyncmsgq(u->source, u->thread_mq.inq); + pa_source_set_rtpoll(u->source, u->rtpoll); + + pa_source_set_latency_range(u->source, 0, MAX_LATENCY_USEC); + u->block_usec = u->source->thread_info.max_latency; + + u->source->thread_info.max_rewind = + pa_usec_to_bytes(u->block_usec, &u->source->sample_spec); + + if (!(u->thread = pa_thread_new("null-source", thread_func, u))) { + pa_log("Failed to create thread."); + goto fail; + } + + pa_source_put(u->source); + + pa_modargs_free(ma); + + u->display_num = get_display_num_from_display(getenv("DISPLAY")); + + return 0; + +fail: + if (ma) + pa_modargs_free(ma); + + pa__done(m); + + return -1; +} + +void pa__done(pa_module*m) { + struct userdata *u; + + pa_assert(m); + + if (!(u = m->userdata)) + return; + + if (u->source) + pa_source_unlink(u->source); + + if (u->thread) { + pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL); + pa_thread_free(u->thread); + } + + pa_thread_mq_done(&u->thread_mq); + + if (u->source) + pa_source_unref(u->source); + + if (u->rtpoll) + pa_rtpoll_free(u->rtpoll); + + pa_xfree(u); +} + +static int get_display_num_from_display(char *display_text) { + int index; + int mode; + int host_index; + int disp_index; + int scre_index; + int display_num; + char host[256]; + char disp[256]; + char scre[256]; + + if (display_text == NULL) { + return 0; + } + 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; + display_num = atoi(disp); + return display_num; +} diff --git a/sesman/chansrv/pulse/pulse-notes.ubuntu.txt b/sesman/chansrv/pulse/pulse-notes.ubuntu.txt index cb6ec90f..18a3768f 100644 --- a/sesman/chansrv/pulse/pulse-notes.ubuntu.txt +++ b/sesman/chansrv/pulse/pulse-notes.ubuntu.txt @@ -1,34 +1,77 @@ -this is /etc/apt/sources.list -I added the deb-src line +-------------------------------------- + Building pulseaudio modules for xrdp +-------------------------------------- ----------------------- -deb http://packages.linuxmint.com/ maya main upstream import -deb http://archive.ubuntu.com/ubuntu/ precise main restricted universe multiverse -deb http://archive.ubuntu.com/ubuntu/ precise-updates main restricted universe multiverse -deb-src http://archive.ubuntu.com/ubuntu/ precise-updates main restricted universe multiverse -deb http://security.ubuntu.com/ubuntu/ precise-security main restricted universe multiverse -deb http://archive.canonical.com/ubuntu/ precise partner -deb http://packages.medibuntu.org/ precise free non-free +o append the following line to /etc/apt/sources.list -#deb http://archive.getdeb.net/ubuntu precise-getdeb apps -#deb http://archive.getdeb.net/ubuntu precise-getdeb games -deb http://drbl.sourceforge.net/drbl-core drbl stable ----------------------- + deb-src http://archive.ubuntu.com/ubuntu/ precise-updates main restricted universe multiverse -do all this in a new directory + this is what my /etc/apt/sources.list looks like -root -sudo apt-get install dpkg-dev + deb http://packages.linuxmint.com/ maya main upstream import + deb http://archive.ubuntu.com/ubuntu/ precise main restricted universe multiverse + deb http://archive.ubuntu.com/ubuntu/ precise-updates main restricted universe multiverse + deb http://security.ubuntu.com/ubuntu/ precise-security main restricted universe multiverse + deb http://archive.canonical.com/ubuntu/ precise partner + deb http://packages.medibuntu.org/ precise free non-free -non root -apt-get source pulseaudio + #deb http://archive.getdeb.net/ubuntu precise-getdeb apps + #deb http://archive.getdeb.net/ubuntu precise-getdeb games + deb http://drbl.sourceforge.net/drbl-core drbl stable + deb-src http://archive.ubuntu.com/ubuntu/ precise-updates main restricted universe multiverse -root -sudo apt-get build-dep pulseaudio + NOTE: If you get an error message that goes something like this: -cd pulseaudio-1.1 + E: You must put some 'source' URIs in your sources.list -non root -dpkg-buildpackage -rfakeroot -uc -b + try running the following command first: + apt-get source pulseaudio + +o run these commands in your home directory + + cd + sudo apt-get install dpkg-dev + apt-get source pulseaudio + sudo apt-get build-dep pulseaudio + + cd pulseaudio-1.1 + dpkg-buildpackage -rfakeroot -uc -b + +o edit Makefile and point PULSE_DIR to ~/pulseaudio<version> dir + +o run make; the outputs will be + module-xrdp-sink.so + module-xrdp-source.so + +o sudo cp module-xrdp-sink.so /usr/lib/pulse-<version>/modules + sudo cp module-xrdp-source.so /usr/lib/pulse-<version>/modules + note: on a 64bit machine use lib64 instead of lib + +o if you build xrdp with --enable-load_pulse_modules, then the above modules + will get loaded automatically when xrdp starts. However if --enable-load_pulse_modules + is not used, then you need to edit /etc/pulse/default.pa and insert the following + two lines into it: + + load-module module-xrdp-sink + load-module module-xrdp-source + +-------------------------------------- + To test sound/microphone redirection +-------------------------------------- + +o install gnome sound recorder or your favorite sound recorder + +o mplayer -ao pulse <audio file> + +o sudo apt-get install pavucontrol + +o in another window run pavucontrol and you should see xrdp-sink in use + +o to enable pulseaudio log + o edit /etc/pulse/daemon.conf and set + log-target = syslog + log-level = notice + o pulseaudio --kill + o log output will be in /var/log/syslog or /var/log/messages diff --git a/sesman/chansrv/rail.c b/sesman/chansrv/rail.c index fb1075c6..4bfeef7e 100644 --- a/sesman/chansrv/rail.c +++ b/sesman/chansrv/rail.c @@ -230,7 +230,7 @@ static struct rail_window_data* APP_CC rail_get_window_data_safe(Window window) { struct rail_window_data* rv; - + rv = rail_get_window_data(window); if (rv != 0) { @@ -331,19 +331,42 @@ rail_is_another_wm_running(void) int APP_CC rail_init(void) { + LOG(10, ("chansrv::rail_init:")); + xcommon_init(); + + return 0; +} + +/*****************************************************************************/ +int APP_CC +rail_deinit(void) +{ + if (g_rail_up) + { + list_delete(g_window_list); + g_window_list = 0; + /* no longer window manager */ + XSelectInput(g_display, g_root_window, 0); + g_rail_up = 0; + } + + return 0; +} + +int APP_CC +rail_startup() +{ int dummy; int ver_maj; int ver_min; Status st; - - LOG(10, ("chansrv::rail_init:")); - xcommon_init(); if (rail_is_another_wm_running()) { log_message(LOG_LEVEL_ERROR, "rail_init: another window manager " "is running"); } + list_delete(g_window_list); g_window_list = list_create(); rail_send_init(); @@ -372,21 +395,6 @@ rail_init(void) g_default_cursor = XCreateFontCursor(g_display, XC_left_ptr); XDefineCursor(g_display, g_root_window, g_default_cursor); } - return 0; -} - -/*****************************************************************************/ -int APP_CC -rail_deinit(void) -{ - if (g_rail_up) - { - list_delete(g_window_list); - g_window_list = 0; - /* no longer window manager */ - XSelectInput(g_display, g_root_window, 0); - g_rail_up = 0; - } return 0; } @@ -454,6 +462,8 @@ rail_process_exec(struct stream *s, int size) if (g_strlen(ExeOrFile) > 0) { + rail_startup(); + LOG(10, ("rail_process_exec: pre")); /* ask main thread to fork */ tc_mutex_lock(g_exec_mutex); @@ -481,13 +491,13 @@ rail_win_popdown(void) Window p; Window* children; XWindowAttributes window_attributes; - + /* * Check the tree of current existing X windows and dismiss * the managed rail popups by simulating a esc key, so * that the requested window can be closed properly. */ - + XQueryTree(g_display, g_root_window, &r, &p, &children, &nchild); for (i = nchild - 1; i >= 0; i--) { @@ -501,7 +511,7 @@ rail_win_popdown(void) rv = 1; } } - + XFree(children); return rv; } @@ -511,11 +521,11 @@ static int APP_CC rail_close_window(int window_id) { XEvent ce; - + LOG(0, ("chansrv::rail_close_window:")); - + rail_win_popdown(); - + g_memset(&ce, 0, sizeof(ce)); ce.xclient.type = ClientMessage; ce.xclient.message_type = g_wm_protocols_atom; @@ -562,13 +572,13 @@ rail_process_activate(struct stream *s, int size) window_id)); return 0; } - + g_focus_counter++; g_got_focus = enabled; LOG(10, (" window_id 0x%8.8x enabled %d", window_id, enabled)); XGetWindowAttributes(g_display, window_id, &window_attributes); - + if (enabled) { if (g_focus_win == window_id) @@ -619,7 +629,7 @@ rail_restore_windows(void) Window r; Window p; Window* children; - + XQueryTree(g_display, g_root_window, &r, &p, &children, &nchild); for (i = 0; i < nchild; i++) { @@ -671,7 +681,7 @@ rail_get_property(Display* display, Window target, Atom type, Atom property, int size; unsigned long nitems, bytes_left; char* prop_name; - + int ret = XGetWindowProperty(display, target, property, 0l, 1l, False, type, &atom_return, &size, @@ -683,7 +693,7 @@ rail_get_property(Display* display, Window target, Atom type, Atom property, XFree(prop_name); return 1; } - + if (bytes_left != 0) { XFree(*data); @@ -697,7 +707,7 @@ rail_get_property(Display* display, Window target, Atom type, Atom property, return 1; } } - + *count = nitems; return 0; } @@ -709,18 +719,18 @@ rail_win_get_state(Window win) unsigned long nitems = 0; int rv = -1; char* data = 0; - + rail_get_property(g_display, win, g_wm_state, g_wm_state, (unsigned char **)&data, &nitems); - + if (data || nitems > 0) { rv = *(unsigned long *)data; XFree(data); LOG(10, (" rail_win_get_state: %d", rv)); } - + return rv; } @@ -730,7 +740,7 @@ rail_win_set_state(Window win, unsigned long state) { int old_state; unsigned long data[2] = { state, None }; - + LOG(10, (" rail_win_set_state: %d", state)); /* check whether WM_STATE exists */ old_state = rail_win_get_state(win); @@ -756,7 +766,7 @@ rail_win_get_text(Window win, char **data) int ret = 0; int i = 0; unsigned long nitems = 0; - + ret = rail_get_property(g_display, win, g_utf8_string, g_net_wm_name, (unsigned char **)data, &nitems); if (ret != 0) @@ -764,7 +774,7 @@ rail_win_get_text(Window win, char **data) /* _NET_WM_NAME isn't set, use WM_NAME (XFetchName) instead */ XFetchName(g_display, win, data); } - + if (data) { char *ptr = *data; @@ -776,7 +786,7 @@ rail_win_get_text(Window win, char **data) } } } - + return i; } @@ -787,7 +797,7 @@ rail_minmax_window(int window_id, int max) LOG(10, ("chansrv::rail_minmax_window 0x%8.8x:", window_id)); if (max) { - + } else { XUnmapWindow(g_display, window_id); /* change window state to IconicState (3) */ @@ -804,7 +814,7 @@ static int APP_CC rail_restore_window(int window_id) { XWindowAttributes window_attributes; - + LOG(10, ("chansrv::rail_restore_window 0x%8.8x:", window_id)); XGetWindowAttributes(g_display, window_id, &window_attributes); if (window_attributes.map_state != IsViewable) @@ -815,7 +825,7 @@ rail_restore_window(int window_id) XRaiseWindow(g_display, window_id); LOG(10, ("chansrv::rail_process_activate: calling XSetInputFocus 0x%8.8x", window_id)); XSetInputFocus(g_display, window_id, RevertToParent, CurrentTime); - + return 0; } @@ -838,7 +848,7 @@ rail_process_system_command(struct stream *s, int size) window_id)); return 0; } - + switch (command) { case SC_SIZE: @@ -1196,7 +1206,7 @@ rail_win_send_text(Window win) int flags; int crc; struct rail_window_data* rwd; - + len = rail_win_get_text(win, &data); rwd = rail_get_window_data_safe(win); if (rwd != 0) @@ -1254,7 +1264,7 @@ static int APP_CC rail_destroy_window(Window window_id) { struct stream *s; - + LOG(10, ("chansrv::rail_destroy_window 0x%8.8x", window_id)); make_stream(s); init_stream(s, 1024); @@ -1348,7 +1358,7 @@ rail_create_window(Window window_id, Window owner_id) title_size = rail_win_get_text(window_id, &title_bytes); XGetTransientForHint(g_display, window_id, &transient_for); - + if (attributes.override_redirect) { style = RAIL_STYLE_TOOLTIP; @@ -1368,7 +1378,7 @@ rail_create_window(Window window_id, Window owner_id) make_stream(s); init_stream(s, 1024); - + out_uint32_le(s, 2); /* create_window */ out_uint32_le(s, window_id); /* window_id */ out_uint32_le(s, owner_id); /* owner_window_id */ @@ -1459,9 +1469,9 @@ rail_configure_request_window(XConfigureRequestEvent* config) int mask; int resized = 0; struct rail_window_data* rwd; - + struct stream* s; - + window_id = config->window; mask = config->value_mask; LOG(10, ("chansrv::rail_configure_request_window: mask %d", mask)); @@ -1580,13 +1590,13 @@ rail_configure_request_window(XConfigureRequestEvent* config) XFree(rwd); return 0; } - + LOG(10, ("chansrv::rail_configure_request_window: 0x%8.8x", window_id)); - - + + LOG(10, (" x %d y %d width %d height %d border_width %d", config->x, config->y, config->width, config->height, config->border_width)); - + index = list_index_of(g_window_list, window_id); if (index == -1) { @@ -1594,15 +1604,15 @@ rail_configure_request_window(XConfigureRequestEvent* config) LOG(0, ("chansrv::rail_configure_request_window: window not mapped")); return 0; } - + flags = WINDOW_ORDER_TYPE_WINDOW; - + make_stream(s); init_stream(s, 1024); - + out_uint32_le(s, 10); /* configure_window */ out_uint32_le(s, window_id); /* window_id */ - + out_uint32_le(s, 0); /* client_offset_x */ out_uint32_le(s, 0); /* client_offset_y */ flags |= WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET; @@ -1643,7 +1653,7 @@ rail_configure_request_window(XConfigureRequestEvent* config) } flags |= WINDOW_ORDER_FIELD_VISIBILITY; out_uint32_le(s, flags); /*flags*/ - + s_mark_end(s); send_rail_drawing_orders(s->data, (int)(s->end - s->data)); free_stream(s); @@ -1661,32 +1671,32 @@ rail_configure_window(XConfigureEvent *config) int flags; int index; int window_id; - + struct stream* s; - + window_id = config->window; - + LOG(10, ("chansrv::rail_configure_window 0x%8.8x", window_id)); - - + + LOG(10, (" x %d y %d width %d height %d border_width %d", config->x, config->y, config->width, config->height, config->border_width)); - + index = list_index_of(g_window_list, window_id); if (index == -1) { /* window isn't mapped yet */ return 0; } - + flags = WINDOW_ORDER_TYPE_WINDOW; - + make_stream(s); init_stream(s, 1024); - + out_uint32_le(s, 10); /* configure_window */ out_uint32_le(s, window_id); /* window_id */ - + out_uint32_le(s, 0); /* client_offset_x */ out_uint32_le(s, 0); /* client_offset_y */ flags |= WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET; @@ -1727,7 +1737,7 @@ rail_configure_window(XConfigureEvent *config) } flags |= WINDOW_ORDER_FIELD_VISIBILITY; out_uint32_le(s, flags); /*flags*/ - + s_mark_end(s); send_rail_drawing_orders(s->data, (int)(s->end - s->data)); free_stream(s); @@ -1772,7 +1782,7 @@ rail_xevent(void *xevent) LOG(10, (" got PropertyNotify window_id 0x%8.8x %s state new %d", lxevent->xproperty.window, prop_name, lxevent->xproperty.state == PropertyNewValue)); - + if (list_index_of(g_window_list, lxevent->xproperty.window) < 0) { break; @@ -1790,7 +1800,7 @@ rail_xevent(void *xevent) } XFree(prop_name); break; - + case ConfigureRequest: LOG(10, (" got ConfigureRequest window_id 0x%8.8x", lxevent->xconfigurerequest.window)); g_memset(&xwc, 0, sizeof(xwc)); @@ -1833,7 +1843,7 @@ rail_xevent(void *xevent) } rv = 0; break; - + case MapRequest: LOG(10, (" got MapRequest window 0x%8.8x", lxevent->xmaprequest.window)); XMapWindow(g_display, lxevent->xmaprequest.window); @@ -1916,7 +1926,7 @@ rail_xevent(void *xevent) case FocusOut: LOG(10, (" got FocusOut")); break; - + case ButtonPress: LOG(10, (" got ButtonPress")); break; @@ -1951,7 +1961,7 @@ rail_xevent(void *xevent) } rv = 0; break; - + default: if (g_xrr_event_base > 0) { diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index 29406d62..0d6d5405 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -2,6 +2,7 @@ * xrdp: A Remote Desktop Protocol server. * * Copyright (C) Laxmikant Rashinkar 2013 LK.Rashinkar@gmail.com + * Copyright (C) Jay Sorg 2013 jay.sorg@gmail.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,6 +29,7 @@ #include "irp.h" #include "devredir.h" #include "smartcard_pcsc.h" +#include "chansrv.h" /* * TODO @@ -58,9 +60,8 @@ #define LOG_INFO 1 #define LOG_DEBUG 2 -#ifndef LOG_LEVEL +#undef LOG_LEVEL #define LOG_LEVEL LOG_INFO -#endif #define log_error(_params...) \ do \ @@ -85,6 +86,7 @@ do \ do \ { \ if (LOG_DEBUG <= LOG_LEVEL) \ + if (2 <= 1) \ { \ g_write("[%10.10u]: SMART_CARD %s: %d : ", \ g_time3(), __func__, __LINE__); \ @@ -160,38 +162,58 @@ extern int g_rdpdr_chan_id; /* in chansrv.c */ 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, +static void APP_CC scard_send_EstablishContext(IRP *irp, int scope); +static void APP_CC scard_send_ReleaseContext(IRP *irp, + char *context, int context_bytes); +static void APP_CC scard_send_IsContextValid(IRP* irp, + char *context, int context_bytes); +static void APP_CC scard_send_ListReaders(IRP *irp, + char *context, int context_bytes, + char *groups, int cchReaders, + int wide); +static void APP_CC scard_send_GetStatusChange(IRP *irp, + char *context, int context_bytes, + 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, + READER_STATE *rsa); +static void APP_CC scard_send_Connect(IRP *irp, + char *context, int context_bytes, + int wide, + READER_STATE *rs); +static void APP_CC scard_send_Reconnect(IRP *irp, + char *context, int context_bytes, + char *card, int card_bytes, + READER_STATE *rs); +static void APP_CC scard_send_BeginTransaction(IRP *irp, + char *context, int context_bytes, + char *card, int card_bytes); +static void APP_CC scard_send_EndTransaction(IRP *irp, + char *context, int context_bytes, + char *card, int card_bytes, tui32 dwDisposition); -static void APP_CC scard_send_Status(IRP* irp, int wide, tui32 sc_handle, +static void APP_CC scard_send_Status(IRP *irp, int wide, + char *context, int context_bytes, + char *card, int card_bytes, 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, +static void APP_CC scard_send_Disconnect(IRP *irp, + char *context, int context_bytes, + char *card, int card_bytes, + int dwDisposition); +static int APP_CC scard_send_Transmit(IRP *irp, + char *context, int context_byte, + char *card, int card_bytes, 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, +static int APP_CC scard_send_Control(IRP* irp, char *context, int context_bytes, + char *card, int card_bytes, 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); +static int APP_CC scard_send_Cancel(IRP *irp, char *context, int context_bytes); +static int APP_CC scard_send_GetAttrib(IRP *irp, char *card, int card_bytes, + READER_STATE *rs); /****************************************************************************** ** local callbacks into this module ** @@ -278,7 +300,10 @@ scard_device_announce(tui32 device_id) log_debug("entered: device_id=%d", device_id); if (g_smartcards_inited) + { + log_error("already init"); return; + } g_memset(&smartcards, 0, sizeof(smartcards)); g_smartcards_inited = 1; @@ -315,7 +340,7 @@ scard_check_wait_objs(void) int APP_CC scard_init(void) { - log_debug("init"); + LOG(0, ("scard_init:")); return scard_pcsc_init(); } @@ -325,15 +350,18 @@ scard_init(void) int APP_CC scard_deinit(void) { - log_debug("deinit"); - return scard_pcsc_deinit(); + LOG(0, ("scard_deinit:")); + scard_pcsc_deinit(); + scard_release_resources(); + g_smartcards_inited = 0; + return 0; } /** * *****************************************************************************/ int APP_CC -scard_send_establish_context(struct trans *con, int scope) +scard_send_establish_context(void *user_data, int scope) { IRP *irp; @@ -348,7 +376,7 @@ scard_send_establish_context(struct trans *con, int scope) irp->CompletionId = g_completion_id++; irp->DeviceId = g_device_id; irp->callback = scard_handle_EstablishContext_Return; - irp->user_data = con; + irp->user_data = user_data; /* send IRP to client */ scard_send_EstablishContext(irp, scope); @@ -360,7 +388,8 @@ scard_send_establish_context(struct trans *con, int scope) * Release a previously established Smart Card context *****************************************************************************/ int APP_CC -scard_send_release_context(struct trans *con, tui32 context) +scard_send_release_context(void *user_data, + char *context, int context_bytes) { IRP *irp; @@ -375,10 +404,10 @@ scard_send_release_context(struct trans *con, tui32 context) irp->CompletionId = g_completion_id++; irp->DeviceId = g_device_id; irp->callback = scard_handle_ReleaseContext_Return; - irp->user_data = con; + irp->user_data = user_data; /* send IRP to client */ - scard_send_ReleaseContext(irp, context); + scard_send_ReleaseContext(irp, context, context_bytes); return 0; } @@ -387,7 +416,7 @@ scard_send_release_context(struct trans *con, tui32 context) * Checks if a previously established context is still valid *****************************************************************************/ int APP_CC -scard_send_is_valid_context(struct trans *con, tui32 context) +scard_send_is_valid_context(void *user_data, char *context, int context_bytes) { IRP *irp; @@ -402,10 +431,10 @@ scard_send_is_valid_context(struct trans *con, tui32 context) irp->CompletionId = g_completion_id++; irp->DeviceId = g_device_id; irp->callback = scard_handle_IsContextValid_Return; - irp->user_data = con; + irp->user_data = user_data; /* send IRP to client */ - scard_send_IsContextValid(irp, context); + scard_send_IsContextValid(irp, context, context_bytes); return 0; } @@ -414,7 +443,8 @@ scard_send_is_valid_context(struct trans *con, tui32 context) * *****************************************************************************/ int APP_CC -scard_send_list_readers(struct trans *con, tui32 context, int wide) +scard_send_list_readers(void *user_data, char *context, int context_bytes, + char *groups, int cchReaders, int wide) { IRP *irp; @@ -428,10 +458,11 @@ scard_send_list_readers(struct trans *con, tui32 context, int wide) irp->CompletionId = g_completion_id++; irp->DeviceId = g_device_id; irp->callback = scard_handle_ListReaders_Return; - irp->user_data = con; + irp->user_data = user_data; /* send IRP to client */ - scard_send_ListReaders(irp, context, wide); + scard_send_ListReaders(irp, context, context_bytes, groups, + cchReaders, wide); return 0; } @@ -446,8 +477,8 @@ scard_send_list_readers(struct trans *con, tui32 context, int wide) * @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, +scard_send_get_status_change(void *user_data, char *context, int context_bytes, + int wide, tui32 timeout, tui32 num_readers, READER_STATE* rsa) { IRP *irp; @@ -463,10 +494,11 @@ scard_send_get_status_change(struct trans *con, tui32 context, int wide, irp->CompletionId = g_completion_id++; irp->DeviceId = g_device_id; irp->callback = scard_handle_GetStatusChange_Return; - irp->user_data = con; + irp->user_data = user_data; /* send IRP to client */ - scard_send_GetStatusChange(irp, context, wide, timeout, num_readers, rsa); + scard_send_GetStatusChange(irp, context, context_bytes, wide, timeout, + num_readers, rsa); return 0; } @@ -478,8 +510,8 @@ scard_send_get_status_change(struct trans *con, tui32 context, int wide, * @param wide TRUE if unicode string *****************************************************************************/ int APP_CC -scard_send_connect(struct trans *con, tui32 context, int wide, - READER_STATE* rs) +scard_send_connect(void *user_data, char *context, int context_bytes, + int wide, READER_STATE* rs) { IRP *irp; @@ -494,10 +526,10 @@ scard_send_connect(struct trans *con, tui32 context, int wide, irp->CompletionId = g_completion_id++; irp->DeviceId = g_device_id; irp->callback = scard_handle_Connect_Return; - irp->user_data = con; + irp->user_data = user_data; /* send IRP to client */ - scard_send_Connect(irp, context, wide, rs); + scard_send_Connect(irp, context, context_bytes, wide, rs); return 0; } @@ -514,8 +546,8 @@ scard_send_connect(struct trans *con, tui32 context, int wide, * rs.init_type *****************************************************************************/ int APP_CC -scard_send_reconnect(struct trans *con, tui32 context, tui32 sc_handle, - READER_STATE* rs) +scard_send_reconnect(void *user_data, char *context, int context_bytes, + char *card, int card_bytes, READER_STATE* rs) { IRP *irp; @@ -530,10 +562,10 @@ scard_send_reconnect(struct trans *con, tui32 context, tui32 sc_handle, irp->CompletionId = g_completion_id++; irp->DeviceId = g_device_id; irp->callback = scard_handle_Reconnect_Return; - irp->user_data = con; + irp->user_data = user_data; /* send IRP to client */ - scard_send_Reconnect(irp, context, sc_handle, rs); + scard_send_Reconnect(irp, context, context_bytes, card, card_bytes, rs); return 0; } @@ -545,7 +577,8 @@ scard_send_reconnect(struct trans *con, tui32 context, tui32 sc_handle, * @param con connection to client *****************************************************************************/ int APP_CC -scard_send_begin_transaction(struct trans *con, tui32 sc_handle) +scard_send_begin_transaction(void *user_data, char *context, int context_bytes, + char *card, int card_bytes) { IRP *irp; @@ -560,10 +593,10 @@ scard_send_begin_transaction(struct trans *con, tui32 sc_handle) irp->CompletionId = g_completion_id++; irp->DeviceId = g_device_id; irp->callback = scard_handle_BeginTransaction_Return; - irp->user_data = con; + irp->user_data = user_data; /* send IRP to client */ - scard_send_BeginTransaction(irp, sc_handle); + scard_send_BeginTransaction(irp, context, context_bytes, card, card_bytes); return 0; } @@ -576,7 +609,8 @@ scard_send_begin_transaction(struct trans *con, tui32 sc_handle) * @param sc_handle handle to smartcard *****************************************************************************/ int APP_CC -scard_send_end_transaction(struct trans *con, tui32 sc_handle, +scard_send_end_transaction(void *user_data, char *context, int context_bytes, + char *card, int card_bytes, tui32 dwDisposition) { IRP *irp; @@ -592,10 +626,11 @@ scard_send_end_transaction(struct trans *con, tui32 sc_handle, irp->CompletionId = g_completion_id++; irp->DeviceId = g_device_id; irp->callback = scard_handle_EndTransaction_Return; - irp->user_data = con; + irp->user_data = user_data; /* send IRP to client */ - scard_send_EndTransaction(irp, sc_handle, dwDisposition); + scard_send_EndTransaction(irp, context, context_bytes, + card, card_bytes, dwDisposition); return 0; } @@ -607,7 +642,8 @@ scard_send_end_transaction(struct trans *con, tui32 sc_handle, * @param wide TRUE if unicode string *****************************************************************************/ int APP_CC -scard_send_status(struct trans *con, int wide, tui32 sc_handle, +scard_send_status(void *user_data, int wide, char *context, int context_bytes, + char *card, int card_bytes, int cchReaderLen, int cbAtrLen) { IRP *irp; @@ -623,10 +659,11 @@ scard_send_status(struct trans *con, int wide, tui32 sc_handle, irp->CompletionId = g_completion_id++; irp->DeviceId = g_device_id; irp->callback = scard_handle_Status_Return; - irp->user_data = con; + irp->user_data = user_data; /* send IRP to client */ - scard_send_Status(irp, wide, sc_handle, cchReaderLen, cbAtrLen); + scard_send_Status(irp, wide, context, context_bytes, card, card_bytes, + cchReaderLen, cbAtrLen); return 0; } @@ -638,8 +675,8 @@ scard_send_status(struct trans *con, int wide, tui32 sc_handle, * @param sc_handle handle to smartcard *****************************************************************************/ int APP_CC -scard_send_disconnect(struct trans *con, tui32 context, tui32 sc_handle, - int dwDisposition) +scard_send_disconnect(void *user_data, char *context, int context_bytes, + char *card, int card_bytes, int dwDisposition) { IRP *irp; @@ -654,10 +691,11 @@ scard_send_disconnect(struct trans *con, tui32 context, tui32 sc_handle, irp->CompletionId = g_completion_id++; irp->DeviceId = g_device_id; irp->callback = scard_handle_Disconnect_Return; - irp->user_data = con; + irp->user_data = user_data; /* send IRP to client */ - scard_send_Disconnect(irp, context, sc_handle, dwDisposition); + scard_send_Disconnect(irp, context, context_bytes, + card, card_bytes, dwDisposition); return 0; } @@ -667,7 +705,8 @@ scard_send_disconnect(struct trans *con, tui32 context, tui32 sc_handle, * associated with a valid context. *****************************************************************************/ int APP_CC -scard_send_transmit(struct trans *con, tui32 sc_handle, +scard_send_transmit(void *user_data, char *context, int context_bytes, + char *card, int card_bytes, char *send_data, int send_bytes, int recv_bytes, struct xrdp_scard_io_request *send_ior, struct xrdp_scard_io_request *recv_ior) @@ -685,11 +724,12 @@ scard_send_transmit(struct trans *con, tui32 sc_handle, irp->CompletionId = g_completion_id++; irp->DeviceId = g_device_id; irp->callback = scard_handle_Transmit_Return; - irp->user_data = con; + irp->user_data = user_data; /* send IRP to client */ - scard_send_Transmit(irp, sc_handle, send_data, send_bytes, recv_bytes, - send_ior, recv_ior); + scard_send_Transmit(irp, context, context_bytes, card, card_bytes, + send_data, send_bytes, + recv_bytes, send_ior, recv_ior); return 0; } @@ -698,7 +738,8 @@ scard_send_transmit(struct trans *con, tui32 sc_handle, * Communicate directly with the smart card reader *****************************************************************************/ int APP_CC -scard_send_control(struct trans *con, tui32 context, tui32 sc_handle, +scard_send_control(void *user_data, char* context, int context_bytes, + char *card, int card_bytes, char *send_data, int send_bytes, int recv_bytes, int control_code) { @@ -715,11 +756,13 @@ scard_send_control(struct trans *con, tui32 context, tui32 sc_handle, irp->CompletionId = g_completion_id++; irp->DeviceId = g_device_id; irp->callback = scard_handle_Control_Return; - irp->user_data = con; + irp->user_data = user_data; /* send IRP to client */ - scard_send_Control(irp, context, sc_handle, send_data, - send_bytes, recv_bytes, control_code); + scard_send_Control(irp, context, context_bytes, + card, card_bytes, + send_data, send_bytes, + recv_bytes, control_code); return 0; } @@ -728,7 +771,7 @@ scard_send_control(struct trans *con, tui32 context, tui32 sc_handle, * Cancel any outstanding calls *****************************************************************************/ int APP_CC -scard_send_cancel(struct trans *con, tui32 context) +scard_send_cancel(void *user_data, char *context, int context_bytes) { IRP *irp; @@ -743,10 +786,10 @@ scard_send_cancel(struct trans *con, tui32 context) irp->CompletionId = g_completion_id++; irp->DeviceId = g_device_id; irp->callback = scard_handle_Cancel_Return; - irp->user_data = con; + irp->user_data = user_data; /* send IRP to client */ - scard_send_Cancel(irp, context); + scard_send_Cancel(irp, context, context_bytes); return 0; } @@ -755,7 +798,8 @@ scard_send_cancel(struct trans *con, tui32 context) * Get reader attributes *****************************************************************************/ int APP_CC -scard_send_get_attrib(struct trans *con, tui32 sc_handle, READER_STATE* rs) +scard_send_get_attrib(void *user_data, char *card, int card_bytes, + READER_STATE* rs) { IRP *irp; @@ -770,10 +814,10 @@ scard_send_get_attrib(struct trans *con, tui32 sc_handle, READER_STATE* rs) irp->CompletionId = g_completion_id++; irp->DeviceId = g_device_id; irp->callback = scard_handle_GetAttrib_Return; - irp->user_data = con; + irp->user_data = user_data; /* send IRP to client */ - scard_send_GetAttrib(irp, sc_handle, rs); + scard_send_GetAttrib(irp, card, card_bytes, rs); return 0; } @@ -831,9 +875,9 @@ scard_make_new_ioctl(IRP *irp, tui32 ioctl) 0); xstream_wr_u32_le(s, 2048); /* OutputBufferLength */ - xstream_wr_u32_le(s, 0); /* InputBufferLength - insert later */ + s_push_layer(s, iso_hdr, 4); /* InputBufferLength - insert later */ xstream_wr_u32_le(s, ioctl); /* Ioctl Code */ - xstream_seek(s, 20); /* padding */ + out_uint8s(s, 20); /* padding */ /* [MS-RPCE] 2.2.6.1 */ xstream_wr_u32_le(s, 0x00081001); /* len 8, LE, v1 */ @@ -897,7 +941,6 @@ scard_get_free_slot(void) return -1; } -#if 0 /** * Release resources prior to shutting down *****************************************************************************/ @@ -915,7 +958,6 @@ scard_release_resources(void) } } } -#endif /** * @@ -932,32 +974,41 @@ scard_send_EstablishContext(IRP *irp, int scope) return; } - 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); + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ + out_uint32_le(s, 0x00000000); + out_uint32_le(s, scope); + out_uint32_le(s, 0x00000000); + + s_mark_end(s); + + s_pop_layer(s, mcs_hdr); + bytes = (int) (s->end - s->p); + bytes -= 8; + out_uint32_le(s, bytes); + + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + + free_stream(s); } /** * Release a previously established Smart Card context *****************************************************************************/ static void APP_CC -scard_send_ReleaseContext(IRP* irp, tui32 context) +scard_send_ReleaseContext(IRP *irp, char *context, int context_bytes) { /* see [MS-RDPESC] 3.1.4.2 */ - SMARTCARD* sc; - struct stream* s; + SMARTCARD *sc; + struct stream *s; int bytes; if ((sc = smartcards[irp->scard_index]) == NULL) @@ -967,49 +1018,48 @@ scard_send_ReleaseContext(IRP* irp, tui32 context) } if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_RELEASE_CONTEXT)) == NULL) + { + log_error("scard_make_new_ioctl failed"); 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 - */ + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ + out_uint32_le(s, 0x00000000); + out_uint32_le(s, context_bytes); + out_uint32_le(s, 0x00020000); + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); - xstream_wr_u32_le(s, 0); - xstream_seek(s, 12); + s_mark_end(s); - /* insert context */ - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, context); + s_pop_layer(s, mcs_hdr); + bytes = (int) (s->end - s->p); + bytes -= 8; + out_uint32_le(s, bytes); - /* get stream len */ - bytes = xstream_len(s); + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + + free_stream(s); } /** * Checks if a previously established context is still valid *****************************************************************************/ static void APP_CC -scard_send_IsContextValid(IRP* irp, tui32 context) +scard_send_IsContextValid(IRP *irp, char *context, int context_bytes) { /* see [MS-RDPESC] 3.1.4.3 */ - SMARTCARD* sc; - struct stream* s; + SMARTCARD *sc; + struct stream *s; int bytes; if ((sc = smartcards[irp->scard_index]) == NULL) @@ -1019,7 +1069,10 @@ scard_send_IsContextValid(IRP* irp, tui32 context) } if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_IS_VALID_CONTEXT)) == NULL) + { + log_error("scard_make_new_ioctl failed"); return; + } /* * command format @@ -1033,35 +1086,51 @@ scard_send_IsContextValid(IRP* irp, tui32 context) * u32 4 bytes context */ - xstream_wr_u32_le(s, 16); + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ /* insert context */ - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, context); + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); - /* get stream len */ - bytes = xstream_len(s); + s_mark_end(s); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + s_pop_layer(s, mcs_hdr); + bytes = (int) (s->end - s->p); + bytes -= 8; + out_uint32_le(s, bytes); + + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); + + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + + free_stream(s); } /** * *****************************************************************************/ static void APP_CC -scard_send_ListReaders(IRP *irp, tui32 context, int wide) +scard_send_ListReaders(IRP *irp, char *context, int context_bytes, + char *groups, int cchReaders, int wide) { /* see [MS-RDPESC] 2.2.2.4 */ SMARTCARD *sc; struct stream *s; int bytes; + int bytes_groups; + int val; + int index; + int num_chars; tui32 ioctl; + twchar w_groups[100]; + if ((sc = smartcards[irp->scard_index]) == NULL) { @@ -1073,70 +1142,85 @@ scard_send_ListReaders(IRP *irp, tui32 context, int wide) SCARD_IOCTL_LIST_READERS_A; if ((s = scard_make_new_ioctl(irp, ioctl)) == NULL) + { + log_error("scard_make_new_ioctl failed"); return; + } - xstream_wr_u32_le(s, 72); /* number of bytes to follow */ - xstream_seek(s, 28); /* freerdp does not use this */ + num_chars = 0; + bytes_groups = 0; + w_groups[0] = 0; + val = 0; + if (groups != 0) + { + if (groups[0] != 0) + { + num_chars = g_mbstowcs(w_groups, groups, 99); + bytes_groups = wide ? (num_chars + 2) * 2 : num_chars + 2; + val = 0x00020004; + } + } + + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ + out_uint32_le(s, 0x00000000); + out_uint32_le(s, context_bytes); + out_uint32_le(s, 0x00020000); + out_uint32_le(s, bytes_groups); + out_uint32_le(s, val); + out_uint32_le(s, 0x00000000); + out_uint32_le(s, cchReaders); /* insert context */ - 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); - xstream_wr_u16_le(s, 0x0043); - xstream_wr_u16_le(s, 0x0061); - xstream_wr_u16_le(s, 0x0072); - xstream_wr_u16_le(s, 0x0064); - xstream_wr_u16_le(s, 0x0024); - xstream_wr_u16_le(s, 0x0041); - xstream_wr_u16_le(s, 0x006c); - xstream_wr_u16_le(s, 0x006c); - xstream_wr_u16_le(s, 0x0052); - xstream_wr_u16_le(s, 0x0065); - xstream_wr_u16_le(s, 0x0061); - xstream_wr_u16_le(s, 0x0064); - xstream_wr_u16_le(s, 0x0065); - xstream_wr_u16_le(s, 0x0072); - xstream_wr_u16_le(s, 0x0073); - - xstream_wr_u32_le(s, 0x00); - - /* get stream len */ - bytes = xstream_len(s); - - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); + + if (bytes_groups > 0) + { + if (wide) + { + out_uint32_le(s, bytes_groups); + for (index = 0; index < num_chars; index++) + { + out_uint16_le(s, w_groups[index]); + } + out_uint16_le(s, 0); + out_uint16_le(s, 0); + } + else + { + out_uint32_le(s, bytes_groups); + for (index = 0; index < num_chars; index++) + { + out_uint8(s, w_groups[index]); + } + out_uint16_le(s, 0); + out_uint16_le(s, 0); + } + } + + s_mark_end(s); + + s_pop_layer(s, mcs_hdr); + bytes = (int) (s->end - s->p); + bytes -= 8; + out_uint32_le(s, bytes); + + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); + + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); - /* - scard_device_control: dumping 120 bytes of data - 0000 00 08 00 00 58 00 00 00 2c 00 09 00 00 00 00 00 ....X...,....... - 0010 00 00 00 00 00 00 00 00 00 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 04 00 00 00 00 00 02 00 24 00 00 00 04 00 02 00 ........$....... - 0040 00 00 00 00 ff ff ff ff 04 00 00 00 84 db 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=88 ioctl_code=0x9002c - */ +#if 0 + g_writeln("scard_send_ListReaders:"); + g_hexdump(s->data, bytes); +#endif - /* - 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 - */ + free_stream(s); } /*****************************************************************************/ @@ -1164,15 +1248,16 @@ align_s(struct stream *s, int bytes) * @param rsa array of READER_STATEs *****************************************************************************/ static void APP_CC -scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, tui32 timeout, +scard_send_GetStatusChange(IRP* irp, char *context, int context_bytes, + 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 */ - SMARTCARD* sc; - READER_STATE* rs; - struct stream* s; + SMARTCARD *sc; + READER_STATE *rs; + struct stream *s; tui32 ioctl; int bytes; int i; @@ -1190,28 +1275,35 @@ scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, tui32 timeout, SCARD_IOCTL_GET_STATUS_CHANGE_A; if ((s = scard_make_new_ioctl(irp, ioctl)) == NULL) + { + log_error("scard_make_new_ioctl failed"); return; + } + + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ + out_uint32_le(s, 0x00000000); + out_uint32_le(s, context_bytes); + out_uint32_le(s, 0x00020000); - 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 */ + out_uint32_le(s, timeout); + out_uint32_le(s, num_readers); + out_uint32_le(s, 0x00020004); /* ? */ /* insert context */ - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, context); + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); - xstream_wr_u32_le(s, 0); /* unused */ + out_uint32_le(s, num_readers); /* 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_uint32_le(s, 0x00020008); /* ? */ + out_uint32_le(s, rs->current_state); + out_uint32_le(s, rs->event_state); + out_uint32_le(s, rs->atr_len); + out_uint8p(s, rs->atr, 33); out_uint8s(s, 3); } @@ -1222,13 +1314,15 @@ scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, tui32 timeout, { 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); + out_uint32_le(s, num_chars + 2); + out_uint32_le(s, 0); + out_uint32_le(s, num_chars + 2); for (index = 0; index < num_chars; index++) { - xstream_wr_u16_le(s, w_reader_name[index]); + out_uint16_le(s, w_reader_name[index]); } + out_uint16_le(s, 0); + out_uint16_le(s, 0); align_s(s, 4); } } @@ -1239,26 +1333,42 @@ scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, tui32 timeout, { 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); + out_uint32_le(s, num_chars + 2); + out_uint32_le(s, 0); + out_uint32_le(s, num_chars + 2); for (index = 0; index < num_chars; index++) { - xstream_wr_u8(s, w_reader_name[index]); + out_uint8(s, w_reader_name[index]); } + out_uint8(s, 0); + out_uint8(s, 0); align_s(s, 4); } } - /* get stream len */ - bytes = xstream_len(s); + s_mark_end(s); + + s_pop_layer(s, mcs_hdr); + bytes = (int) (s->end - s->p); + bytes -= 8; + out_uint32_le(s, bytes); + + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + +#if 0 + g_writeln("scard_send_GetStatusChange:"); + g_hexdump(s->data, bytes); +#endif + + free_stream(s); } /** @@ -1269,7 +1379,8 @@ scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, tui32 timeout, * @param rs reader state *****************************************************************************/ static void APP_CC -scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs) +scard_send_Connect(IRP* irp, char *context, int context_bytes, + int wide, READER_STATE* rs) { /* see [MS-RDPESC] 2.2.2.13 for ASCII */ /* see [MS-RDPESC] 2.2.2.14 for Wide char */ @@ -1292,61 +1403,65 @@ scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs) SCARD_IOCTL_CONNECT_A; if ((s = scard_make_new_ioctl(irp, ioctl)) == NULL) + { + log_error("scard_make_new_ioctl failed"); return; + } - /* - * command format - * - * ...... - * 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 */ + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ + out_uint32_le(s, 0x00000000); + out_uint32_le(s, 0x00020000); + out_uint32_le(s, context_bytes); + out_uint32_le(s, 0x00020004); + out_uint32_le(s, rs->dwShareMode); + out_uint32_le(s, rs->dwPreferredProtocols); 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); + out_uint32_le(s, num_chars + 2); + out_uint32_le(s, 0x00000000); + out_uint32_le(s, num_chars + 2); if (wide) { for (index = 0; index < num_chars; index++) { - xstream_wr_u16_le(s, w_reader_name[index]); + out_uint16_le(s, w_reader_name[index]); } + out_uint16_le(s, 0); + out_uint16_le(s, 0); } else { for (index = 0; index < num_chars; index++) { - xstream_wr_u8(s, w_reader_name[index]); + out_uint8(s, w_reader_name[index]); } + out_uint8(s, 0); + out_uint8(s, 0); } align_s(s, 4); /* insert context */ - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, context); + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); + out_uint32_le(s, 0); + + s_mark_end(s); + + s_pop_layer(s, mcs_hdr); + bytes = (int) (s->end - s->p); + bytes -= 8; + out_uint32_le(s, bytes); - /* get stream len */ - bytes = xstream_len(s); + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + + free_stream(s); } /** @@ -1361,13 +1476,14 @@ scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs) * rs.init_type *****************************************************************************/ static void APP_CC -scard_send_Reconnect(IRP* irp, tui32 context, tui32 sc_handle, READER_STATE* rs) +scard_send_Reconnect(IRP *irp, char *context, int context_bytes, + char *card, int card_bytes, READER_STATE *rs) { /* see [MS-RDPESC] 2.2.2.15 */ /* see [MS-RDPESC] 3.1.4.36 */ - SMARTCARD* sc; - struct stream* s; + SMARTCARD *sc; + struct stream *s; int bytes; if ((sc = smartcards[irp->scard_index]) == NULL) @@ -1377,7 +1493,10 @@ scard_send_Reconnect(IRP* irp, tui32 context, tui32 sc_handle, READER_STATE* rs) } if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_RECONNECT)) == NULL) + { + log_error("scard_make_new_ioctl failed"); return; + } /* * command format @@ -1396,24 +1515,29 @@ scard_send_Reconnect(IRP* irp, tui32 context, tui32 sc_handle, READER_STATE* rs) * 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); + xstream_seek(s, 24); /* TODO */ + + out_uint32_le(s, rs->dwShareMode); + out_uint32_le(s, rs->dwPreferredProtocols); + out_uint32_le(s, rs->init_type); + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); + out_uint32_le(s, card_bytes); + out_uint8a(s, card, card_bytes); - /* get stream len */ - bytes = xstream_len(s); + s_mark_end(s); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); + + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + + free_stream(s); } /** @@ -1423,7 +1547,8 @@ scard_send_Reconnect(IRP* irp, tui32 context, tui32 sc_handle, READER_STATE* rs) * @param con connection to client *****************************************************************************/ static void APP_CC -scard_send_BeginTransaction(IRP *irp, tui32 sc_handle) +scard_send_BeginTransaction(IRP *irp, char *context, int context_bytes, + char *card, int card_bytes) { /* see [MS-RDPESC] 4.9 */ @@ -1438,35 +1563,47 @@ scard_send_BeginTransaction(IRP *irp, tui32 sc_handle) } if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_BEGIN_TRANSACTION)) == NULL) + { + log_error("scard_make_new_ioctl failed"); return; + } - /* - * 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 - */ + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ + out_uint32_le(s, 0x00000000); + out_uint32_le(s, context_bytes); + out_uint32_le(s, 0x00020000); + out_uint32_le(s, card_bytes); + out_uint32_le(s, 0x00020004); + out_uint32_le(s, 0x00000000); + + /* insert context */ + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); + + /* insert card */ + out_uint32_le(s, card_bytes); + out_uint8a(s, card, card_bytes); + + out_uint32_le(s, 0x00000000); - xstream_seek(s, 36); + s_mark_end(s); - /* insert handle */ - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, sc_handle); + s_pop_layer(s, mcs_hdr); + bytes = (int) (s->end - s->p); + bytes -= 8; + out_uint32_le(s, bytes); - /* get stream len */ - bytes = xstream_len(s); + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + + free_stream(s); } /** @@ -1477,7 +1614,9 @@ scard_send_BeginTransaction(IRP *irp, tui32 sc_handle) * @param sc_handle handle to smartcard *****************************************************************************/ static void APP_CC -scard_send_EndTransaction(IRP *irp, tui32 sc_handle, tui32 dwDisposition) +scard_send_EndTransaction(IRP *irp, char *context, int context_bytes, + char *card, int card_bytes, + tui32 dwDisposition) { /* see [MS-RDPESC] 3.1.4.32 */ @@ -1492,39 +1631,47 @@ scard_send_EndTransaction(IRP *irp, tui32 sc_handle, tui32 dwDisposition) } if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_END_TRANSACTION)) == NULL) + { + log_error("scard_make_new_ioctl failed"); 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 - */ + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ + out_uint32_le(s, 0x00000000); + out_uint32_le(s, context_bytes); + out_uint32_le(s, 0x00020000); + out_uint32_le(s, card_bytes); + out_uint32_le(s, 0x00020004); + out_uint32_le(s, dwDisposition); - xstream_seek(s, 24); - xstream_wr_u32_le(s, dwDisposition); - xstream_seek(s, 8); + /* insert context */ + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); - /* insert handle */ - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, sc_handle); + /* insert card */ + out_uint32_le(s, card_bytes); + out_uint8a(s, card, card_bytes); - /* get stream len */ - bytes = xstream_len(s); + out_uint32_le(s, 0); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + s_mark_end(s); + + s_pop_layer(s, mcs_hdr); + bytes = (int) (s->end - s->p); + bytes -= 8; + out_uint32_le(s, bytes); + + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); + + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + + free_stream(s); } /** @@ -1534,7 +1681,8 @@ scard_send_EndTransaction(IRP *irp, tui32 sc_handle, tui32 dwDisposition) * @param wide TRUE if unicode string *****************************************************************************/ static void APP_CC -scard_send_Status(IRP *irp, int wide, tui32 sc_handle, +scard_send_Status(IRP *irp, int wide, char *context, int context_bytes, + char *card, int card_bytes, int cchReaderLen, int cbAtrLen) { /* see [MS-RDPESC] 2.2.2.18 */ @@ -1556,43 +1704,62 @@ scard_send_Status(IRP *irp, int wide, tui32 sc_handle, log_error("scard_make_new_ioctl"); return; } +/* + 30 00 00 00 + 00 00 00 00 + 04 00 00 00 + 00 00 02 00 + 04 00 00 00 + 04 00 02 00 + 01 00 00 00 + 00 00 00 00 dwReaderLen + 40 00 00 00 dwAtrLen + 04 00 00 00 + 07 00 00 00 + 04 00 00 00 + 09 00 00 00 hCard + 00 00 00 00 +*/ + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ + out_uint32_le(s, 0x00000000); + out_uint32_le(s, context_bytes); + out_uint32_le(s, 0x00020000); + out_uint32_le(s, card_bytes); + out_uint32_le(s, 0x00020004); + out_uint32_le(s, 0x00000001); + out_uint32_le(s, cchReaderLen); /* readerLen, see [MS-RDPESC] 4.11 */ + out_uint32_le(s, cbAtrLen); /* atrLen, see [MS-RDPESC] 4.11 */ - /* - * 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 - */ + /* insert context */ + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); - 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 card */ + out_uint32_le(s, card_bytes); + out_uint8a(s, card, card_bytes); + + out_uint32_le(s, 0); + + s_mark_end(s); - /* insert sc_handle */ - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, sc_handle); + s_pop_layer(s, mcs_hdr); + bytes = (int) (s->end - s->p); + bytes -= 8; + out_uint32_le(s, bytes); - xstream_wr_u32_le(s, 0); + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); - /* get stream len */ - bytes = xstream_len(s); + bytes = (int) (s->end - s->data); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + //g_hexdump(s->data, bytes); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + + free_stream(s); } /** @@ -1602,13 +1769,13 @@ scard_send_Status(IRP *irp, int wide, tui32 sc_handle, * @param sc_handle handle to smartcard *****************************************************************************/ static void APP_CC -scard_send_Disconnect(IRP *irp, tui32 context, tui32 sc_handle, - int dwDisposition) +scard_send_Disconnect(IRP *irp, char *context, int context_bytes, + char *card, int card_bytes, int dwDisposition) { /* see [MS-RDPESC] 3.1.4.30 */ - SMARTCARD* sc; - struct stream* s; + SMARTCARD *sc; + struct stream *s; int bytes; if ((sc = smartcards[irp->scard_index]) == NULL) @@ -1618,43 +1785,47 @@ scard_send_Disconnect(IRP *irp, tui32 context, tui32 sc_handle, } if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_DISCONNECT)) == NULL) + { + log_error("scard_make_new_ioctl failed"); 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); + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ + out_uint32_le(s, 0x00000000); + out_uint32_le(s, context_bytes); + out_uint32_le(s, 0x00020000); + out_uint32_le(s, card_bytes); + out_uint32_le(s, 0x00020004); + out_uint32_le(s, dwDisposition); /* insert context */ - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, context); + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); + + /* insert card */ + out_uint32_le(s, card_bytes); + out_uint8a(s, card, card_bytes); + + out_uint32_le(s, 0x00000000); - /* insert handle */ - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, sc_handle); + s_mark_end(s); - /* get stream len */ - bytes = xstream_len(s); + s_pop_layer(s, mcs_hdr); + bytes = (int) (s->end - s->p); + bytes -= 8; + out_uint32_le(s, bytes); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); + + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + + free_stream(s); } /** @@ -1662,15 +1833,16 @@ scard_send_Disconnect(IRP *irp, tui32 context, tui32 sc_handle, * associated with a valid context. *****************************************************************************/ static int APP_CC -scard_send_Transmit(IRP* irp, tui32 sc_handle, char *send_data, +scard_send_Transmit(IRP *irp, char *context, int context_bytes, + char *card, int card_bytes, char *send_data, int send_bytes, int recv_bytes, struct xrdp_scard_io_request *send_ior, struct xrdp_scard_io_request *recv_ior) { /* see [MS-RDPESC] 2.2.2.19 */ - SMARTCARD* sc; - struct stream* s; + SMARTCARD *sc; + struct stream *s; int bytes; int val; @@ -1716,58 +1888,137 @@ scard_send_Transmit(IRP* irp, tui32 sc_handle, char *send_data, * 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); + //g_writeln("send_bytes %d", send_bytes); + //g_writeln("recv_bytes %d", recv_bytes); + +#if 0 + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ + out_uint32_be(s, 0x00000000); + out_uint32_be(s, 0x04000000); + out_uint32_be(s, 0x00000200); // map 0 + out_uint32_be(s, 0x04000000); + out_uint32_be(s, 0x04000200); // map 1 + out_uint32_be(s, 0x01000000); + out_uint32_be(s, 0x00000000); + out_uint32_be(s, 0x00000000); + + //out_uint32_be(s, 0x05000000); + out_uint32_le(s, send_bytes); + + out_uint32_be(s, 0x08000200); + out_uint32_be(s, 0x0c000200); + out_uint32_be(s, 0x00000000); + + //out_uint32_be(s, 0x02010000); + out_uint32_le(s, recv_bytes); + + out_uint32_be(s, 0x04000000); + out_uint32_be(s, 0x05000000); + out_uint32_be(s, 0x04000000); + out_uint32_be(s, 0x0b000000); + + //out_uint32_be(s, 0x05000000); + //out_uint32_be(s, 0x00b00704); + //out_uint32_be(s, 0x10000000); + out_uint32_le(s, send_bytes); + out_uint8p(s, send_data, send_bytes); + align_s(s, 4); + + out_uint32_be(s, 0x01000000); + out_uint32_be(s, 0x00000000); + out_uint32_be(s, 0x00000000); +#else + + //g_printf("send cbPciLength %d\n", send_ior->cbPciLength); + //g_printf("send extra_bytes %d\n", send_ior->extra_bytes); + //g_printf("recv cbPciLength %d\n", recv_ior->cbPciLength); + //g_printf("recv extra_bytes %d\n", recv_ior->extra_bytes); + + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ + out_uint32_le(s, 0x00000000); + + out_uint32_le(s, context_bytes); + out_uint32_le(s, 0x00020000); /* map0 */ + + out_uint32_le(s, card_bytes); + out_uint32_le(s, 0x00020004); /* map1 */ + + out_uint32_le(s, send_ior->dwProtocol); + out_uint32_le(s, send_ior->cbPciLength - 8); + 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); + out_uint32_le(s, val); /* map2 */ + + out_uint32_le(s, send_bytes); + + val = send_bytes > 0 ? 0x00020008 : 0; + out_uint32_le(s, val); /* map3 */ + + val = recv_ior->cbPciLength > 0 ? 0x0002000c : 0; + out_uint32_le(s, val); /* map 4 */ + + out_uint32_le(s, 0); // map5 + out_uint32_le(s, recv_bytes); + + /* map0 */ + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); + + /* map1 */ + out_uint32_le(s, card_bytes); + out_uint8a(s, card, card_bytes); if (send_ior->extra_bytes > 0) { - xstream_wr_u32_le(s, send_ior->extra_bytes); + out_uint32_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_uint32_le(s, send_bytes); out_uint8a(s, send_data, send_bytes); + align_s(s, 4); } if (recv_ior->cbPciLength > 0) { - xstream_wr_u32_le(s, recv_ior->dwProtocol); - xstream_wr_u32_le(s, recv_ior->cbPciLength); + /* map4 */ + out_uint32_le(s, recv_ior->dwProtocol); + out_uint32_le(s, recv_ior->cbPciLength - 8); val = recv_ior->extra_bytes > 0 ? 1 : 0; - xstream_wr_u32_le(s, val); + out_uint32_le(s, val); /* map6*/ if (val) { - xstream_wr_u32_le(s, recv_ior->extra_bytes); + out_uint32_le(s, recv_ior->extra_bytes); out_uint8a(s, recv_ior->extra_data, recv_ior->extra_bytes); } } +#endif + + s_mark_end(s); - /* get stream len */ - bytes = xstream_len(s); + s_pop_layer(s, mcs_hdr); + bytes = (int) (s->end - s->p); + bytes -= 8; + out_uint32_le(s, bytes); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); + + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + +#if 0 + g_writeln("scard_send_Transmit:"); + g_hexdump(s->data, bytes); +#endif + + free_stream(s); return 0; } @@ -1775,13 +2026,14 @@ scard_send_Transmit(IRP* irp, tui32 sc_handle, char *send_data, * Communicate directly with the smart card reader *****************************************************************************/ static int APP_CC -scard_send_Control(IRP* irp, tui32 context, tui32 sc_handle, char *send_data, +scard_send_Control(IRP *irp, char *context, int context_bytes, + char *card, int card_bytes, char *send_data, int send_bytes, int recv_bytes, int control_code) { /* see [MS-RDPESC] 2.2.2.19 */ - SMARTCARD* sc; - struct stream* s; + SMARTCARD *sc; + struct stream *s; int bytes; int val; @@ -1797,62 +2049,52 @@ scard_send_Control(IRP* irp, tui32 context, tui32 sc_handle, char *send_data, 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); - + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ + out_uint32_le(s, 0x00000000); + out_uint32_le(s, context_bytes); + out_uint32_le(s, 0x00020000); /* map0 */ + out_uint32_le(s, card_bytes); + out_uint32_le(s, 0x00020004); /* map1 */ + out_uint32_le(s, control_code); + out_uint32_le(s, send_bytes); + val = send_bytes > 0 ? 0x00020008 : 0; + out_uint32_le(s, val); /* map2 */ + out_uint32_le(s, 0x00000000); + out_uint32_le(s, recv_bytes); + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); + out_uint32_le(s, card_bytes); + out_uint8a(s, card, card_bytes); if (send_bytes > 0) { - xstream_wr_u32_le(s, send_bytes); + out_uint32_le(s, send_bytes); out_uint8a(s, send_data, send_bytes); } + else + { + out_uint32_le(s, 0x00000000); + } + + s_mark_end(s); - /* get stream len */ - bytes = xstream_len(s); + s_pop_layer(s, mcs_hdr); + bytes = (int) (s->end - s->p); + bytes -= 8; + out_uint32_le(s, bytes); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); + + bytes = (int) (s->end - s->data); + + //g_hexdump(s->data, bytes); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + + free_stream(s); return 0; } @@ -1860,12 +2102,12 @@ scard_send_Control(IRP* irp, tui32 context, tui32 sc_handle, char *send_data, * Cancel any outstanding calls *****************************************************************************/ static int APP_CC -scard_send_Cancel(IRP* irp, tui32 context) +scard_send_Cancel(IRP *irp, char *context, int context_bytes) { /* see [MS-RDPESC] 3.1.4.27 */ - SMARTCARD* sc; - struct stream* s; + SMARTCARD *sc; + struct stream *s; int bytes; if ((sc = smartcards[irp->scard_index]) == NULL) @@ -1880,31 +2122,31 @@ scard_send_Cancel(IRP* irp, tui32 context) 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 - */ + s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ + out_uint32_le(s, 0x00000000); + out_uint32_le(s, context_bytes); + out_uint32_le(s, 0x00020000); + out_uint32_le(s, context_bytes); + out_uint8a(s, context, context_bytes); + + s_mark_end(s); - xstream_seek(s, 16); - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, context); + s_pop_layer(s, mcs_hdr); + bytes = (int) (s->end - s->p); + bytes -= 8; + out_uint32_le(s, bytes); - /* get stream len */ - bytes = xstream_len(s); + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + + free_stream(s); return 0; } @@ -1912,12 +2154,12 @@ scard_send_Cancel(IRP* irp, tui32 context) * Get reader attributes *****************************************************************************/ static int APP_CC -scard_send_GetAttrib(IRP* irp, tui32 sc_handle, READER_STATE* rs) +scard_send_GetAttrib(IRP *irp, char *card, int card_bytes, READER_STATE *rs) { /* see [MS-RDPESC] 2.2.2.21 */ - SMARTCARD* sc; - struct stream* s; + SMARTCARD *sc; + struct stream *s; int bytes; if ((sc = smartcards[irp->scard_index]) == NULL) @@ -1948,23 +2190,27 @@ scard_send_GetAttrib(IRP* irp, tui32 sc_handle, READER_STATE* rs) * 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, 24); /* TODO */ + out_uint32_le(s, rs->dwAttribId); + out_uint32_le(s, 0); + out_uint32_le(s, rs->dwAttrLen); xstream_seek(s, 8); - xstream_wr_u32_le(s, 4); - xstream_wr_u32_le(s, sc_handle); + out_uint32_le(s, card_bytes); + out_uint8a(s, card, card_bytes); - /* get stream len */ - bytes = xstream_len(s); + s_mark_end(s); - /* InputBufferLength is number of bytes AFTER 20 byte padding */ - *(s->data + 28) = bytes - 56; + s_pop_layer(s, iso_hdr); + bytes = (int) (s->end - s->p); + bytes -= 28; + out_uint32_le(s, bytes); + + bytes = (int) (s->end - s->data); /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); - xstream_free(s); + + free_stream(s); return 0; } @@ -1983,7 +2229,6 @@ scard_handle_EstablishContext_Return(struct stream *s, IRP *irp, tui32 IoStatus) { tui32 len; - struct trans *con; log_debug("entered"); /* sanity check */ @@ -1992,16 +2237,9 @@ scard_handle_EstablishContext_Return(struct stream *s, IRP *irp, 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); + scard_function_establish_context_return(irp->user_data, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2015,7 +2253,6 @@ scard_handle_ReleaseContext_Return(struct stream *s, IRP *irp, tui32 IoStatus) { tui32 len; - struct trans *con; log_debug("entered"); /* sanity check */ @@ -2024,16 +2261,9 @@ scard_handle_ReleaseContext_Return(struct stream *s, IRP *irp, 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); + scard_function_release_context_return(irp->user_data, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2047,7 +2277,6 @@ APP_CC scard_handle_IsContextValid_Return(struct stream *s, IRP *irp, tui32 IoStatus) { tui32 len; - struct trans *con; log_debug("entered"); @@ -2058,17 +2287,9 @@ APP_CC scard_handle_IsContextValid_Return(struct stream *s, IRP *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); + scard_function_is_context_valid_return(irp->user_data, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2082,7 +2303,6 @@ scard_handle_ListReaders_Return(struct stream *s, IRP *irp, tui32 IoStatus) { tui32 len; - struct trans *con; log_debug("entered"); /* sanity check */ @@ -2091,16 +2311,9 @@ scard_handle_ListReaders_Return(struct stream *s, IRP *irp, 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); + scard_function_list_readers_return(irp->user_data, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2114,7 +2327,6 @@ scard_handle_GetStatusChange_Return(struct stream *s, IRP *irp, tui32 IoStatus) { tui32 len; - struct trans *con; log_debug("entered"); /* sanity check */ @@ -2123,16 +2335,9 @@ scard_handle_GetStatusChange_Return(struct stream *s, IRP *irp, 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); + scard_function_get_status_change_return(irp->user_data, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2146,7 +2351,6 @@ scard_handle_Connect_Return(struct stream *s, IRP *irp, tui32 IoStatus) { tui32 len; - struct trans *con; log_debug("entered"); @@ -2157,18 +2361,10 @@ scard_handle_Connect_Return(struct stream *s, IRP *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); + scard_function_connect_return(irp->user_data, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); @@ -2183,7 +2379,6 @@ scard_handle_Reconnect_Return(struct stream *s, IRP *irp, tui32 IoStatus) { tui32 len; - struct trans *con; log_debug("entered"); @@ -2194,17 +2389,9 @@ scard_handle_Reconnect_Return(struct stream *s, IRP *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); + scard_function_reconnect_return(irp->user_data, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2218,7 +2405,6 @@ scard_handle_BeginTransaction_Return(struct stream *s, IRP *irp, tui32 IoStatus) { tui32 len; - struct trans *con; log_debug("entered"); @@ -2229,17 +2415,9 @@ scard_handle_BeginTransaction_Return(struct stream *s, IRP *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); + scard_function_begin_transaction_return(irp->user_data, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2253,7 +2431,6 @@ scard_handle_EndTransaction_Return(struct stream *s, IRP *irp, tui32 IoStatus) { tui32 len; - struct trans *con; log_debug("entered"); @@ -2264,17 +2441,9 @@ scard_handle_EndTransaction_Return(struct stream *s, IRP *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); + scard_function_end_transaction_return(irp->user_data, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2288,7 +2457,6 @@ scard_handle_Status_Return(struct stream *s, IRP *irp, tui32 IoStatus) { tui32 len; - struct trans *con; log_debug("entered"); @@ -2299,17 +2467,9 @@ scard_handle_Status_Return(struct stream *s, IRP *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); + scard_function_status_return(irp->user_data, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2323,7 +2483,6 @@ scard_handle_Disconnect_Return(struct stream *s, IRP *irp, tui32 IoStatus) { tui32 len; - struct trans *con; log_debug("entered"); @@ -2334,17 +2493,9 @@ scard_handle_Disconnect_Return(struct stream *s, IRP *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); + scard_function_disconnect_return(irp->user_data, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2357,7 +2508,6 @@ scard_handle_Transmit_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus) { tui32 len; - struct trans *con; log_debug("entered"); @@ -2368,17 +2518,9 @@ scard_handle_Transmit_Return(struct stream *s, IRP *irp, tui32 DeviceId, 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); + scard_function_transmit_return(irp->user_data, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2391,7 +2533,6 @@ scard_handle_Control_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId,tui32 IoStatus) { tui32 len; - struct trans *con; log_debug("entered"); @@ -2402,17 +2543,9 @@ scard_handle_Control_Return(struct stream *s, IRP *irp, tui32 DeviceId, 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); + scard_function_control_return(irp->user_data, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2425,7 +2558,6 @@ scard_handle_Cancel_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus) { tui32 len; - struct trans *con; log_debug("entered"); @@ -2436,17 +2568,9 @@ scard_handle_Cancel_Return(struct stream *s, IRP *irp, tui32 DeviceId, 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); + scard_function_cancel_return(irp->user_data, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } @@ -2459,7 +2583,6 @@ scard_handle_GetAttrib_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus) { tui32 len; - struct trans *con; log_debug("entered"); @@ -2470,17 +2593,9 @@ scard_handle_GetAttrib_Return(struct stream *s, IRP *irp, tui32 DeviceId, 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); + scard_function_get_attrib_return(irp->user_data, s, len, IoStatus); devredir_irp_delete(irp); log_debug("leaving"); } diff --git a/sesman/chansrv/smartcard.h b/sesman/chansrv/smartcard.h index 88f4cdf6..3ea503a8 100644 --- a/sesman/chansrv/smartcard.h +++ b/sesman/chansrv/smartcard.h @@ -110,41 +110,62 @@ 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 APP_CC scard_send_establish_context(void *user_data, int scope); +int APP_CC scard_send_release_context(void *user_data, + char *context, int context_bytes); +int APP_CC scard_send_is_valid_context(void *user_data, + char *context, int context_bytes); +int APP_CC scard_send_list_readers(void *user_data, + char *context, int context_bytes, + char *groups, int cchReaders, int wide); + +int APP_CC scard_send_get_status_change(void *user_data, + char *context, int context_bytes, int wide, tui32 timeout, tui32 num_readers, READER_STATE* rsa); -int APP_CC scard_send_connect(struct trans *con, tui32 context, int wide, +int APP_CC scard_send_connect(void *user_data, + char *context, int context_bytes, int wide, READER_STATE* rs); -int APP_CC scard_send_reconnect(struct trans *con, tui32 context, - tui32 sc_handle, READER_STATE* rs); - -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, +int APP_CC scard_send_reconnect(void *user_data, + char *context, int context_bytes, + char *card, int card_bytes, + READER_STATE* rs); + +int APP_CC scard_send_begin_transaction(void *user_data, + char *context, int context_bytes, + char *card, int card_bytes); +int APP_CC scard_send_end_transaction(void *user_data, + char *context, int context_bytes, + char *card, int card_bytes, tui32 dwDisposition); -int APP_CC scard_send_status(struct trans *con, int wide, tui32 sc_handle, +int APP_CC scard_send_status(void *user_data, int wide, + char *context, int context_bytes, + char *card, int card_bytes, int cchReaderLen, int cbAtrLen); -int APP_CC scard_send_disconnect(struct trans *con, tui32 context, - tui32 sc_handle, int dwDisposition); - -int APP_CC scard_send_transmit(struct trans *con, tui32 sc_handle, +int APP_CC scard_send_disconnect(void *user_data, + char *context, int context_bytes, + char *card, int card_bytes, + int dwDisposition); + +int APP_CC scard_send_transmit(void *user_data, + char *context, int context_bytes, + char *card, int card_bytes, 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_send_control(struct trans *con, tui32 context, tui32 sc_handle, +int APP_CC scard_send_control(void *user_data, + char *context, int context_bytes, + char *card, int card_bytes, 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_cancel(void *user_data, + char *context, int context_bytes); -int APP_CC scard_send_get_attrib(struct trans *con, tui32 sc_handle, +int APP_CC scard_send_get_attrib(void *user_data, char *card, int card_bytes, READER_STATE* rs); /* diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index 29f60c8d..1d1618dc 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -35,6 +35,7 @@ #include "devredir.h" #include "trans.h" #include "chansrv.h" +#include "list.h" #if PCSC_STANDIN @@ -50,52 +51,340 @@ } \ while (0) -#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 */ - -/* TODO: put this in con */ -static int g_xrdp_pcsc_state = XRDP_PCSC_STATE_NONE; - extern int g_display_num; /* in chansrv.c */ +static int g_autoinc = 0; /* general purpose autoinc */ + +struct pcsc_card /* item for list of open cards in one context */ +{ + tui32 app_card; /* application card, always 4 bytes */ + int card_bytes; /* client card bytes */ + char card[16]; /* client card */ +}; + +struct pcsc_context +{ + tui32 app_context; /* application context, always 4 byte */ + int context_bytes; /* client context bytes */ + char context[16]; /* client context */ + struct list *cards; /* these need to be released on close */ +}; + /*****************************************************************************/ -struct pcsc_client +struct pcsc_uds_client { - struct trans *con; + int uds_client_id; /* unique id represents each app */ + struct trans *con; /* the connection to the app */ + struct list *contexts; /* list of struct pcsc_context */ + struct pcsc_context *connect_context; }; -#if 0 -static struct pcsc_client *g_head = 0; -static struct pcsc_client *g_tail = 0; -#endif +static struct list *g_uds_clients = 0; /* struct pcsc_uds_client */ static struct trans *g_lis = 0; -static struct trans *g_con = 0; /* todo, remove this */ static char g_pcsclite_ipc_dir[256] = ""; -static int g_pub_file_fd = 0; +static char g_pcsclite_ipc_file[256] = ""; + +/*****************************************************************************/ +/* got a new unix domain socket connection */ +static struct pcsc_uds_client * +create_uds_client(struct trans *con) +{ + struct pcsc_uds_client *uds_client; + + LLOGLN(10, ("create_uds_client:")); + if (con == 0) + { + return 0; + } + uds_client = g_malloc(sizeof(struct pcsc_uds_client), 1); + if (uds_client == 0) + { + return 0; + } + g_autoinc++; + uds_client->uds_client_id = g_autoinc; + uds_client->con = con; + con->callback_data = uds_client; + return uds_client; +} + +/*****************************************************************************/ +static struct pcsc_uds_client * +get_uds_client_by_id(int uds_client_id) +{ + struct pcsc_uds_client *uds_client; + int index; + + LLOGLN(10, ("get_uds_client_by_id:")); + if (uds_client_id == 0) + { + LLOGLN(10, ("get_uds_client_by_id: uds_client_id zero")); + return 0; + } + if (g_uds_clients == 0) + { + LLOGLN(10, ("get_uds_client_by_id: g_uds_clients is nil")); + return 0; + } + LLOGLN(10, (" count %d", g_uds_clients->count)); + for (index = 0; index < g_uds_clients->count; index++) + { + uds_client = (struct pcsc_uds_client *) + list_get_item(g_uds_clients, index); + if (uds_client->uds_client_id == uds_client_id) + { + return uds_client; + } + } + LLOGLN(10, ("get_uds_client_by_id: can't find uds_client_id %d", + uds_client_id)); + return 0; +} + +/*****************************************************************************/ +struct pcsc_context * +get_pcsc_context_by_app_context(struct pcsc_uds_client *uds_client, + int app_context) +{ + struct pcsc_context *rv; + int index; + + if (uds_client == 0) + { + return 0; + } + if (uds_client->contexts == 0) + { + return 0; + } + for (index = 0; index < uds_client->contexts->count; index++) + { + rv = (struct pcsc_context *) + list_get_item(uds_client->contexts, index); + if (rv->app_context == app_context) + { + return rv; + } + } + return 0; +} + +/*****************************************************************************/ +struct pcsc_card * +get_pcsc_card_by_app_card(struct pcsc_uds_client *uds_client, + int app_card, struct pcsc_context **acontext) +{ + struct pcsc_card *lcard; + struct pcsc_context *lcontext; + int index; + int index1; + + LLOGLN(10, ("get_pcsc_card_by_app_card:")); + LLOGLN(10, (" app_card %d", app_card)); + if (uds_client == 0) + { + LLOGLN(0, ("get_pcsc_card_by_app_card: error")); + return 0; + } + if (uds_client->contexts == 0) + { + LLOGLN(0, ("get_pcsc_card_by_app_card: error")); + return 0; + } + for (index = 0; index < uds_client->contexts->count; index++) + { + lcontext = (struct pcsc_context *) + list_get_item(uds_client->contexts, index); + if (lcontext != 0) + { + if (lcontext->cards != 0) + { + for (index1 = 0; index1 < lcontext->cards->count; index1++) + { + lcard = (struct pcsc_card *) + list_get_item(lcontext->cards, index1); + if (lcard != 0) + { + if (lcard->app_card == app_card) + { + if (acontext != 0) + { + *acontext = lcontext; + } + return lcard; + } + } + } + } + } + } + LLOGLN(0, ("get_pcsc_card_by_app_card: error")); + return 0; +} + +/*****************************************************************************/ +static int +free_uds_client(struct pcsc_uds_client *uds_client) +{ + int i; + int j; + struct pcsc_context *context; + struct pcsc_card *card; + + LLOGLN(10, ("free_uds_client:")); + if (uds_client == 0) + { + return 0; + } + if (uds_client->contexts != 0) + { + for (i = 0; i < uds_client->contexts->count; i++) + { + context = (struct pcsc_context *) + list_get_item(uds_client->contexts, i); + if (context != 0) + { + if (context->cards != 0) + { + for (j = 0; j < context->cards->count; j++) + { + card = (struct pcsc_card *) + list_get_item(context->cards, j); + if (card != 0) + { + /* TODO: send free card to client */ + g_free(card); + } + } + list_delete(context->cards); + } + LLOGLN(10, (" left over context 0x%8.8x", context->context)); + scard_send_cancel(0, context->context, context->context_bytes); + scard_send_release_context(0, context->context, + context->context_bytes); + g_free(context); + } + } + list_delete(uds_client->contexts); + } + trans_delete(uds_client->con); + g_free(uds_client); + return 0; +} + +/*****************************************************************************/ +static struct pcsc_context * +uds_client_add_context(struct pcsc_uds_client *uds_client, + char *context, int context_bytes) +{ + struct pcsc_context *pcscContext; + + LLOGLN(10, ("uds_client_add_context:")); + pcscContext = (struct pcsc_context *) + g_malloc(sizeof(struct pcsc_context), 1); + if (pcscContext == 0) + { + LLOGLN(0, ("uds_client_add_context: error")); + return 0; + } + g_autoinc++; + pcscContext->app_context = g_autoinc; + pcscContext->context_bytes = context_bytes; + g_memcpy(pcscContext->context, context, context_bytes); + if (uds_client->contexts == 0) + { + uds_client->contexts = list_create(); + if (uds_client->contexts == 0) + { + LLOGLN(0, ("uds_client_add_context: error")); + return 0; + } + } + list_add_item(uds_client->contexts, (tintptr) pcscContext); + return pcscContext; +} + +/*****************************************************************************/ +static int +uds_client_remove_context(struct pcsc_uds_client *uds_client, + struct pcsc_context *acontext) +{ + int index; + + if (uds_client->contexts == 0) + { + LLOGLN(0, ("uds_client_remove_context: error")); + return 1; + } + index = list_index_of(uds_client->contexts, (tintptr) acontext); + if (index < 0) + { + LLOGLN(0, ("uds_client_remove_context: error")); + return 1; + } + list_remove_item(uds_client->contexts, index); + g_free(acontext); // TODO free cards + return 0; +} + +/*****************************************************************************/ +static struct pcsc_card * +context_add_card(struct pcsc_uds_client *uds_client, + struct pcsc_context *acontext, + char *card, int card_bytes) +{ + struct pcsc_card *pcscCard; + + LLOGLN(10, ("context_add_card: card_bytes %d", card_bytes)); + pcscCard = (struct pcsc_card *) + g_malloc(sizeof(struct pcsc_card), 1); + if (pcscCard == 0) + { + LLOGLN(0, ("context_add_card: error")); + return 0; + } + g_autoinc++; + pcscCard->app_card = g_autoinc; + pcscCard->card_bytes = card_bytes; + g_memcpy(pcscCard->card, card, card_bytes); + if (acontext->cards == 0) + { + acontext->cards = list_create(); + if (acontext->cards == 0) + { + LLOGLN(0, ("context_add_card: error")); + return 0; + } + } + list_add_item(acontext->cards, (tintptr) pcscCard); + LLOGLN(10, (" new app_card %d", pcscCard->app_card)); + return pcscCard; +} /*****************************************************************************/ int APP_CC scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout) { - LLOGLN(10, ("scard_pcsc_get_wait_objs")); + struct pcsc_uds_client *uds_client; + int index; + + LLOGLN(10, ("scard_pcsc_get_wait_objs:")); if (g_lis != 0) { trans_get_wait_objs(g_lis, objs, count); } - if (g_con != 0) + if (g_uds_clients != 0) { - trans_get_wait_objs(g_con, objs, count); + for (index = 0; index < g_uds_clients->count; index++) + { + uds_client = (struct pcsc_uds_client *) + list_get_item(g_uds_clients, index); + if (uds_client != 0) + { + trans_get_wait_objs(uds_client->con, objs, count); + } + } } return 0; } @@ -104,14 +393,35 @@ scard_pcsc_get_wait_objs(tbus *objs, int *count, int *timeout) int APP_CC scard_pcsc_check_wait_objs(void) { - LLOGLN(10, ("scard_pcsc_check_wait_objs")); + struct pcsc_uds_client *uds_client; + int index; + + LLOGLN(10, ("scard_pcsc_check_wait_objs:")); if (g_lis != 0) { - trans_check_wait_objs(g_lis); + if (trans_check_wait_objs(g_lis) != 0) + { + LLOGLN(0, ("scard_pcsc_check_wait_objs: g_lis trans_check_wait_objs error")); + } } - if (g_con != 0) + if (g_uds_clients != 0) { - trans_check_wait_objs(g_con); + index = 0; + while (index < g_uds_clients->count) + { + uds_client = (struct pcsc_uds_client *) + list_get_item(g_uds_clients, index); + if (uds_client != 0) + { + if (trans_check_wait_objs(uds_client->con) != 0) + { + free_uds_client(uds_client); + list_remove_item(g_uds_clients, index); + continue; + } + } + index++; + } } return 0; } @@ -122,52 +432,71 @@ int APP_CC scard_process_establish_context(struct trans *con, struct stream *in_s) { int dwScope; + struct pcsc_uds_client *uds_client; + void *user_data; 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; + uds_client = (struct pcsc_uds_client *) (con->callback_data); in_uint32_le(in_s, dwScope); LLOGLN(10, ("scard_process_establish_context: dwScope 0x%8.8x", dwScope)); - scard_send_establish_context(con, dwScope); + user_data = (void *) (tintptr) (uds_client->uds_client_id); + scard_send_establish_context(user_data, dwScope); return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -scard_function_establish_context_return(struct trans *con, - struct stream *in_s, - int len) +scard_function_establish_context_return(void *user_data, + struct stream *in_s, + int len, int status) { int bytes; - tui32 context; - tui32 context_len; + int uds_client_id; + int context_bytes; + int app_context; + char context[16]; struct stream *out_s; + struct pcsc_uds_client *uds_client; + struct trans *con; + struct pcsc_context *lcontext; LLOGLN(10, ("scard_function_establish_context_return:")); - if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_EC) == 0) + LLOGLN(10, (" status 0x%8.8x", status)); + uds_client_id = (int) (tintptr) user_data; + uds_client = (struct pcsc_uds_client *) + get_uds_client_by_id(uds_client_id); + if (uds_client == 0) { - LLOGLN(0, ("scard_function_establish_context_return: opps")); + LLOGLN(0, ("scard_function_establish_context_return: " + "get_uds_client_by_id failed")); 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) + con = uds_client->con; + lcontext = 0; + app_context = 0; + g_memset(context, 0, 16); + if (status == 0) { - LLOGLN(0, ("scard_function_establish_context_return: opps")); - return 1; + in_uint8s(in_s, 28); + in_uint32_le(in_s, context_bytes); + if (context_bytes > 16) + { + LLOGLN(0, ("scard_function_establish_context_return: opps " + "context_bytes %d", context_bytes)); + g_hexdump(in_s->p, context_bytes); + return 1; + } + in_uint8a(in_s, context, context_bytes); + lcontext = uds_client_add_context(uds_client, context, context_bytes); + app_context = lcontext->app_context; + LLOGLN(10, ("scard_function_establish_context_return: " + "app_context %d", app_context)); } - 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 */ + out_uint32_le(out_s, app_context); + out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ s_mark_end(out_s); bytes = (int) (out_s->end - out_s->data); s_pop_layer(out_s, iso_hdr); @@ -182,40 +511,56 @@ int APP_CC scard_process_release_context(struct trans *con, struct stream *in_s) { int hContext; + struct pcsc_uds_client *uds_client; + struct pcsc_context *lcontext; + void *user_data; LLOGLN(10, ("scard_process_release_context:")); - if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_RC) + uds_client = (struct pcsc_uds_client *) (con->callback_data); + in_uint32_le(in_s, hContext); + LLOGLN(10, ("scard_process_release_context: hContext 0x%8.8x", hContext)); + user_data = (void *) (tintptr) (uds_client->uds_client_id); + lcontext = get_pcsc_context_by_app_context(uds_client, hContext); + if (lcontext == 0) { - LLOGLN(0, ("scard_process_establish_context: opps")); + LLOGLN(0, ("scard_process_release_context: " + "get_pcsc_context_by_app_context failed")); 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); + scard_send_release_context(user_data, lcontext->context, + lcontext->context_bytes); + uds_client_remove_context(uds_client, lcontext); return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -scard_function_release_context_return(struct trans *con, +scard_function_release_context_return(void *user_data, struct stream *in_s, - int len) + int len, int status) { int bytes; + int uds_client_id; struct stream *out_s; + struct pcsc_uds_client *uds_client; + struct trans *con; LLOGLN(10, ("scard_function_release_context_return:")); - if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_RC) == 0) + LLOGLN(10, (" status 0x%8.8x", status)); + uds_client_id = (int) (tintptr) user_data; + uds_client = (struct pcsc_uds_client *) + get_uds_client_by_id(uds_client_id); + if (uds_client == 0) { - LLOGLN(0, ("scard_function_release_context_return: opps")); + LLOGLN(0, ("scard_function_release_context_return: " + "get_uds_client_by_id failed")); return 1; } - g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_RC; + con = uds_client->con; 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 */ + out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ s_mark_end(out_s); bytes = (int) (out_s->end - out_s->data); s_pop_layer(out_s, iso_hdr); @@ -225,30 +570,55 @@ scard_function_release_context_return(struct trans *con, } /*****************************************************************************/ +struct pcsc_list_readers +{ + int uds_client_id; + int cchReaders; +}; + +/*****************************************************************************/ /* returns error */ int APP_CC scard_process_list_readers(struct trans *con, struct stream *in_s) { int hContext; + int bytes_groups; + int cchReaders; + char *groups; + struct pcsc_uds_client *uds_client; + struct pcsc_context *lcontext; + struct pcsc_list_readers *pcscListReaders; LLOGLN(10, ("scard_process_list_readers:")); - if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_LR) + uds_client = (struct pcsc_uds_client *) (con->callback_data); + in_uint32_le(in_s, hContext); + in_uint32_le(in_s, bytes_groups); + groups = (char *) g_malloc(bytes_groups + 1, 1); + in_uint8a(in_s, groups, bytes_groups); + in_uint32_le(in_s, cchReaders); + LLOGLN(10, ("scard_process_list_readers: hContext 0x%8.8x cchReaders %d", + hContext, cchReaders)); + lcontext = get_pcsc_context_by_app_context(uds_client, hContext); + if (lcontext == 0) { - LLOGLN(0, ("scard_process_list_readers: opps")); + LLOGLN(0, ("scard_process_list_readers: " + "get_pcsc_context_by_app_context failed")); 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); + pcscListReaders = g_malloc(sizeof(struct pcsc_list_readers), 1); + pcscListReaders->uds_client_id = uds_client->uds_client_id; + pcscListReaders->cchReaders = cchReaders; + scard_send_list_readers(pcscListReaders, lcontext->context, + lcontext->context_bytes, groups, cchReaders, 1); + g_free(groups); return 0; } /*****************************************************************************/ int APP_CC -scard_function_list_readers_return(struct trans *con, +scard_function_list_readers_return(void *user_data, struct stream *in_s, - int len) + int len, int status) { struct stream *out_s; int chr; @@ -256,68 +626,91 @@ scard_function_list_readers_return(struct trans *con, int rn_index; int index; int bytes; + int cchReaders; + int llen; + int uds_client_id; twchar reader_name[100]; char lreader_name[16][100]; + struct pcsc_uds_client *uds_client; + struct trans *con; + struct pcsc_list_readers *pcscListReaders; 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(10, (" status 0x%8.8x", status)); + pcscListReaders = (struct pcsc_list_readers *) user_data; + if (pcscListReaders == 0) { - LLOGLN(0, ("scard_function_list_readers_return: opps")); + LLOGLN(0, ("scard_function_list_readers_return: " + "pcscListReaders is nil")); return 1; } - g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_LR; - + uds_client_id = pcscListReaders->uds_client_id; + cchReaders = pcscListReaders->cchReaders; + g_free(pcscListReaders); + uds_client = (struct pcsc_uds_client *) + get_uds_client_by_id(uds_client_id); + if (uds_client == 0) + { + LLOGLN(0, ("scard_function_list_readers_return: " + "get_uds_client_by_id failed, could not find id %d", + uds_client_id)); + return 1; + } + con = uds_client->con; 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) + llen = 0; + if (status == 0) { - in_uint16_le(in_s, chr); - len -= 2; - if (chr == 0) + in_uint8s(in_s, 28); + in_uint32_le(in_s, len); + llen = len; + if (cchReaders > 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_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("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, llen); 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 */ + out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ s_mark_end(out_s); bytes = (int) (out_s->end - out_s->data); s_pop_layer(out_s, iso_hdr); @@ -333,15 +726,13 @@ scard_process_connect(struct trans *con, struct stream *in_s) { int hContext; READER_STATE rs; + struct pcsc_uds_client *uds_client; + void *user_data; + struct pcsc_context *lcontext; LLOGLN(10, ("scard_process_connect:")); - if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_C) - { - LLOGLN(0, ("scard_process_connect: opps")); - return 1; - } + uds_client = (struct pcsc_uds_client *) (con->callback_data); 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); @@ -349,38 +740,75 @@ scard_process_connect(struct trans *con, struct stream *in_s) 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); + user_data = (void *) (tintptr) (uds_client->uds_client_id); + lcontext = get_pcsc_context_by_app_context(uds_client, hContext); + if (lcontext == 0) + { + LLOGLN(0, ("scard_process_connect: " + "get_pcsc_context_by_app_context failed")); + return 1; + } + uds_client->connect_context = lcontext; + scard_send_connect(user_data, lcontext->context, lcontext->context_bytes, + 1, &rs); return 0; } /*****************************************************************************/ int APP_CC -scard_function_connect_return(struct trans *con, +scard_function_connect_return(void *user_data, struct stream *in_s, - int len) + int len, int status) { int dwActiveProtocol; int hCard; int bytes; + int uds_client_id; struct stream *out_s; - - //g_hexdump(in_s->p, len); - if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_C) == 0) + struct pcsc_uds_client *uds_client; + struct trans *con; + char *card; + int card_bytes; + struct pcsc_card *lcard; + + LLOGLN(10, ("scard_function_connect_return:")); + LLOGLN(10, (" status 0x%8.8x", status)); + uds_client_id = (int) (tintptr) user_data; + uds_client = (struct pcsc_uds_client *) + get_uds_client_by_id(uds_client_id); + if (uds_client == 0) { - LLOGLN(0, ("scard_function_connect_return: opps")); + LLOGLN(0, ("scard_function_connect_return: " + "get_uds_client_by_id failed")); 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)); + con = uds_client->con; + dwActiveProtocol = 0; + hCard = 0; + if (status == 0) + { + in_uint8s(in_s, 36); + in_uint32_le(in_s, dwActiveProtocol); + if (len > 40) + { + in_uint32_le(in_s, card_bytes); + in_uint8p(in_s, card, card_bytes); + lcard = context_add_card(uds_client, uds_client->connect_context, + card, card_bytes); + hCard = lcard->app_card; + LLOGLN(10, (" hCard %d dwActiveProtocol %d", hCard, + dwActiveProtocol)); + } + else + { + status = 0x8010000F; /* SCARD_E_PROTO_MISMATCH */ + } + } 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 */ + out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ s_mark_end(out_s); bytes = (int) (out_s->end - out_s->data); s_pop_layer(out_s, iso_hdr); @@ -394,53 +822,58 @@ scard_function_connect_return(struct trans *con, int APP_CC scard_process_disconnect(struct trans *con, struct stream *in_s) { - int hContext; int hCard; int dwDisposition; + struct pcsc_uds_client *uds_client; + void *user_data; + struct pcsc_context *lcontext; + struct pcsc_card *lcard; LLOGLN(10, ("scard_process_disconnect:")); - if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_D) + uds_client = (struct pcsc_uds_client *) (con->callback_data); + in_uint32_le(in_s, hCard); + in_uint32_le(in_s, dwDisposition); + user_data = (void *) (tintptr) (uds_client->uds_client_id); + lcard = get_pcsc_card_by_app_card(uds_client, hCard, &lcontext); + if ((lcontext == 0) || (lcard == 0)) { - LLOGLN(0, ("scard_process_disconnect: opps")); + LLOGLN(0, ("scard_process_disconnect: " + "get_pcsc_card_by_app_card failed")); 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); - + scard_send_disconnect(user_data, + lcontext->context, lcontext->context_bytes, + lcard->card, lcard->card_bytes, dwDisposition); return 0; } /*****************************************************************************/ int APP_CC -scard_function_disconnect_return(struct trans *con, +scard_function_disconnect_return(void *user_data, struct stream *in_s, - int len) + int len, int status) { - int dwActiveProtocol; - int hCard; int bytes; + int uds_client_id; struct stream *out_s; + struct pcsc_uds_client *uds_client; + struct trans *con; - //g_hexdump(in_s->p, len); - if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_D) == 0) + LLOGLN(10, ("scard_function_disconnect_return:")); + LLOGLN(10, (" status 0x%8.8x", status)); + uds_client_id = (int) (tintptr) user_data; + uds_client = (struct pcsc_uds_client *) + get_uds_client_by_id(uds_client_id); + if (uds_client == 0) { - LLOGLN(0, ("scard_function_connect_return: opps")); + LLOGLN(0, ("scard_function_disconnect_return: " + "get_uds_client_by_id failed")); 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)); + con = uds_client->con; 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 */ + out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ s_mark_end(out_s); bytes = (int) (out_s->end - out_s->data); s_pop_layer(out_s, iso_hdr); @@ -455,41 +888,57 @@ int APP_CC scard_process_begin_transaction(struct trans *con, struct stream *in_s) { int hCard; + struct pcsc_uds_client *uds_client; + void *user_data; + struct pcsc_card *lcard; + struct pcsc_context *lcontext; LLOGLN(10, ("scard_process_begin_transaction:")); - if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_BT) + uds_client = (struct pcsc_uds_client *) (con->callback_data); + in_uint32_le(in_s, hCard); + LLOGLN(10, ("scard_process_begin_transaction: hCard 0x%8.8x", hCard)); + user_data = (void *) (tintptr) (uds_client->uds_client_id); + lcard = get_pcsc_card_by_app_card(uds_client, hCard, &lcontext); + if ((lcard == 0) || (lcontext == 0)) { - LLOGLN(0, ("scard_process_begin_transaction: opps")); + LLOGLN(0, ("scard_process_begin_transaction: " + "get_pcsc_card_by_app_card failed")); 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); + scard_send_begin_transaction(user_data, + lcontext->context, lcontext->context_bytes, + lcard->card, lcard->card_bytes); return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -scard_function_begin_transaction_return(struct trans *con, +scard_function_begin_transaction_return(void *user_data, struct stream *in_s, - int len) + int len, int status) { struct stream *out_s; int bytes; + int uds_client_id; + struct pcsc_uds_client *uds_client; + struct trans *con; - //g_hexdump(in_s->p, len); - if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_BT) == 0) + LLOGLN(10, ("scard_function_begin_transaction_return:")); + LLOGLN(10, (" status 0x%8.8x", status)); + uds_client_id = (int) (tintptr) user_data; + uds_client = (struct pcsc_uds_client *) + get_uds_client_by_id(uds_client_id); + if (uds_client == 0) { - LLOGLN(0, ("scard_function_begin_transaction_return: opps")); + LLOGLN(0, ("scard_function_begin_transaction_return: " + "get_uds_client_by_id failed")); return 1; } - g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_BT; - + con = uds_client->con; 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 */ + out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ s_mark_end(out_s); bytes = (int) (out_s->end - out_s->data); s_pop_layer(out_s, iso_hdr); @@ -505,42 +954,60 @@ scard_process_end_transaction(struct trans *con, struct stream *in_s) { int hCard; int dwDisposition; + struct pcsc_uds_client *uds_client; + void *user_data; + struct pcsc_card *lcard; + struct pcsc_context *lcontext; 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; + uds_client = (struct pcsc_uds_client *) (con->callback_data); 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); + user_data = (void *) (tintptr) (uds_client->uds_client_id); + lcard = get_pcsc_card_by_app_card(uds_client, hCard, &lcontext); + if ((lcard == 0) || (lcontext == 0)) + { + LLOGLN(0, ("scard_process_end_transaction: " + "get_pcsc_card_by_app_card failed")); + return 1; + } + scard_send_end_transaction(user_data, + lcontext->context, lcontext->context_bytes, + lcard->card, lcard->card_bytes, + dwDisposition); return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -scard_function_end_transaction_return(struct trans *con, +scard_function_end_transaction_return(void *user_data, struct stream *in_s, - int len) + int len, int status) { struct stream *out_s; int bytes; + int uds_client_id; + struct pcsc_uds_client *uds_client; + struct trans *con; - //g_hexdump(in_s->p, len); - if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_ET) == 0) + LLOGLN(10, ("scard_function_end_transaction_return:")); + LLOGLN(10, (" status 0x%8.8x", status)); + uds_client_id = (int) (tintptr) user_data; + uds_client = (struct pcsc_uds_client *) + get_uds_client_by_id(uds_client_id); + if (uds_client == 0) { - LLOGLN(0, ("scard_function_end_transaction_return: opps")); + LLOGLN(0, ("scard_function_end_transaction_return: " + "get_uds_client_by_id failed")); return 1; } - g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_ET; + con = uds_client->con; 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 */ + out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ s_mark_end(out_s); bytes = (int) (out_s->end - out_s->data); s_pop_layer(out_s, iso_hdr); @@ -552,22 +1019,20 @@ scard_function_end_transaction_return(struct trans *con, /*****************************************************************************/ /* returns error */ int APP_CC -scard_function_cancel_return(struct trans *con, - struct stream *in_s, - int len) +scard_function_get_attrib_return(void *user_data, + struct stream *in_s, + int len, int status) { return 0; } /*****************************************************************************/ -/* returns error */ -int APP_CC -scard_function_get_attrib_return(struct trans *con, - struct stream *in_s, - int len) +struct pcsc_transmit { - return 0; -} + int uds_client_id; + struct xrdp_scard_io_request recv_ior; + int cbRecvLength; +}; /*****************************************************************************/ /* returns error */ @@ -580,14 +1045,13 @@ scard_process_transmit(struct trans *con, struct stream *in_s) char *send_data; struct xrdp_scard_io_request send_ior; struct xrdp_scard_io_request recv_ior; + struct pcsc_uds_client *uds_client; + struct pcsc_card *lcard; + struct pcsc_context *lcontext; + struct pcsc_transmit *pcscTransmit; 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; + uds_client = (struct pcsc_uds_client *) (con->callback_data); LLOGLN(10, ("scard_process_transmit:")); in_uint32_le(in_s, hCard); in_uint32_le(in_s, send_ior.dwProtocol); @@ -605,9 +1069,25 @@ scard_process_transmit(struct trans *con, struct stream *in_s) "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, + lcard = get_pcsc_card_by_app_card(uds_client, hCard, &lcontext); + if ((lcard == 0) || (lcontext == 0)) + { + LLOGLN(0, ("scard_process_transmit: " + "get_pcsc_card_by_app_card failed")); + return 1; + } + + pcscTransmit = (struct pcsc_transmit *) + g_malloc(sizeof(struct pcsc_transmit), 1); + pcscTransmit->uds_client_id = uds_client->uds_client_id; + pcscTransmit->recv_ior = recv_ior; + pcscTransmit->cbRecvLength = recv_bytes; + + scard_send_transmit(pcscTransmit, + lcontext->context, lcontext->context_bytes, + lcard->card, lcard->card_bytes, + send_data, send_bytes, recv_bytes, &send_ior, &recv_ior); return 0; } @@ -615,42 +1095,63 @@ scard_process_transmit(struct trans *con, struct stream *in_s) /*****************************************************************************/ /* returns error */ int APP_CC -scard_function_transmit_return(struct trans *con, +scard_function_transmit_return(void *user_data, struct stream *in_s, - int len) + int len, int status) { struct stream *out_s; int bytes; int val; int cbRecvLength; - struct xrdp_scard_io_request recv_ior; char *recvBuf; + struct xrdp_scard_io_request recv_ior; + struct pcsc_uds_client *uds_client; + struct trans *con; + struct pcsc_transmit *pcscTransmit; LLOGLN(10, ("scard_function_transmit_return:")); - //g_hexdump(in_s->p, len); - if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_TR) == 0) + LLOGLN(10, (" status 0x%8.8x", status)); + pcscTransmit = (struct pcsc_transmit *) user_data; + recv_ior = pcscTransmit->recv_ior; + uds_client = (struct pcsc_uds_client *) + get_uds_client_by_id(pcscTransmit->uds_client_id); + g_free(pcscTransmit); + + if (uds_client == 0) { - LLOGLN(0, ("scard_function_transmit_return: opps")); + LLOGLN(0, ("scard_function_transmit_return: " + "get_uds_client_by_id failed")); 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); + con = uds_client->con; cbRecvLength = 0; recvBuf = 0; - if (val != 0) + if (status == 0) { - in_uint32_le(in_s, cbRecvLength); - in_uint8p(in_s, recvBuf, cbRecvLength); + in_uint8s(in_s, 20); + in_uint32_le(in_s, val); + if (val != 0) + { + /* pioRecvPci */ + in_uint8s(in_s, 8); + in_uint32_le(in_s, recv_ior.dwProtocol); + in_uint32_le(in_s, recv_ior.cbPciLength); + recv_ior.cbPciLength += 8; + in_uint32_le(in_s, recv_ior.extra_bytes); + if (recv_ior.extra_bytes > 0) + { + in_uint8p(in_s, recv_ior.extra_data, recv_ior.extra_bytes); + } + } + + in_uint8s(in_s, 4); + in_uint32_le(in_s, val); + 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); @@ -661,7 +1162,7 @@ scard_function_transmit_return(struct trans *con, 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 */ + out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ s_mark_end(out_s); bytes = (int) (out_s->end - out_s->data); s_pop_layer(out_s, iso_hdr); @@ -675,20 +1176,18 @@ scard_function_transmit_return(struct trans *con, 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; + struct pcsc_uds_client *uds_client; + void *user_data; + struct pcsc_context *lcontext; + struct pcsc_card *lcard; 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; + uds_client = (struct pcsc_uds_client *) (con->callback_data); LLOGLN(10, ("scard_process_control:")); in_uint32_le(in_s, hCard); @@ -697,9 +1196,17 @@ scard_process_control(struct trans *con, struct stream *in_s) 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, + user_data = (void *) (tintptr) (uds_client->uds_client_id); + lcard = get_pcsc_card_by_app_card(uds_client, hCard, &lcontext); + if ((lcard == 0) || (lcontext == 0)) + { + LLOGLN(0, ("scard_process_control: " + "get_pcsc_card_by_app_card failed")); + return 1; + } + scard_send_control(user_data, lcontext->context, lcontext->context_bytes, + lcard->card, lcard->card_bytes, + send_data, send_bytes, recv_bytes, control_code); return 0; @@ -708,33 +1215,44 @@ scard_process_control(struct trans *con, struct stream *in_s) /*****************************************************************************/ /* returns error */ int APP_CC -scard_function_control_return(struct trans *con, +scard_function_control_return(void *user_data, struct stream *in_s, - int len) + int len, int status) { struct stream *out_s; int bytes; int cbRecvLength; char *recvBuf; + int uds_client_id; + struct pcsc_uds_client *uds_client; + struct trans *con; - //g_hexdump(in_s->p, len); - if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_CO) == 0) + LLOGLN(10, ("scard_function_control_return:")); + LLOGLN(10, (" status 0x%8.8x", status)); + uds_client_id = (int) (tintptr) user_data; + uds_client = (struct pcsc_uds_client *) + get_uds_client_by_id(uds_client_id); + if (uds_client == 0) { - LLOGLN(0, ("scard_function_control_return: opps")); + LLOGLN(0, ("scard_function_control_return: " + "get_uds_client_by_id failed")); 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); - + con = uds_client->con; + cbRecvLength = 0; + recvBuf = 0; + if (status == 0) + { + 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 */ + out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ s_mark_end(out_s); bytes = (int) (out_s->end - out_s->data); s_pop_layer(out_s, iso_hdr); @@ -744,6 +1262,13 @@ scard_function_control_return(struct trans *con, } /*****************************************************************************/ +struct pcsc_status +{ + int uds_client_id; + int cchReaderLen; +}; + +/*****************************************************************************/ /* returns error */ int APP_CC scard_process_status(struct trans *con, struct stream *in_s) @@ -751,20 +1276,34 @@ scard_process_status(struct trans *con, struct stream *in_s) int hCard; int cchReaderLen; int cbAtrLen; + struct pcsc_uds_client *uds_client; + struct pcsc_card *lcard; + struct pcsc_context *lcontext; + struct pcsc_status *pcscStatus; 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; + uds_client = (struct pcsc_uds_client *) (con->callback_data); in_uint32_le(in_s, hCard); in_uint32_le(in_s, cchReaderLen); in_uint32_le(in_s, cbAtrLen); + LLOGLN(10, ("scard_process_status: hCard 0x%8.8x cchReaderLen %d " + "cbAtrLen %d", hCard, cchReaderLen, cbAtrLen)); - scard_send_status(con, 1, hCard, cchReaderLen, cbAtrLen); + lcard = get_pcsc_card_by_app_card(uds_client, hCard, &lcontext); + if ((lcard == 0) || (lcontext == 0)) + { + LLOGLN(0, ("scard_process_status: " + "get_pcsc_card_by_app_card failed")); + return 1; + } + pcscStatus = (struct pcsc_status *) g_malloc(sizeof(struct pcsc_status), 1); + pcscStatus->uds_client_id = uds_client->uds_client_id; + pcscStatus->cchReaderLen = cchReaderLen; + scard_send_status(pcscStatus, 1, + lcontext->context, lcontext->context_bytes, + lcard->card, lcard->card_bytes, + cchReaderLen, cbAtrLen); return 0; } @@ -793,9 +1332,9 @@ static int g_ms2pc[] = { PC_SCARD_UNKNOWN, PC_SCARD_ABSENT, /*****************************************************************************/ /* returns error */ int APP_CC -scard_function_status_return(struct trans *con, +scard_function_status_return(void *user_data, struct stream *in_s, - int len) + int len, int status) { struct stream *out_s; int index; @@ -807,31 +1346,76 @@ scard_function_status_return(struct trans *con, char attr[32]; twchar reader_name[100]; char lreader_name[100]; + int uds_client_id; + struct pcsc_uds_client *uds_client; + struct trans *con; + struct pcsc_status *pcscStatus; - //g_hexdump(in_s->p, len); - if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_ST) == 0) + LLOGLN(10, ("scard_function_status_return:")); + LLOGLN(10, (" status 0x%8.8x", status)); + + pcscStatus = (struct pcsc_status *) user_data; + if (pcscStatus == 0) { - LLOGLN(0, ("scard_function_status_return: opps")); + LLOGLN(0, ("scard_function_status_return: pcscStatus is nil")); 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++) + + uds_client_id = pcscStatus->uds_client_id; + uds_client = (struct pcsc_uds_client *) + get_uds_client_by_id(uds_client_id); + if (uds_client == 0) + { + LLOGLN(0, ("scard_function_status_return: " + "get_uds_client_by_id failed")); + g_free(pcscStatus); + return 1; + } + g_free(pcscStatus); + con = uds_client->con; + dwReaderLen = 0; + dwState = 0; + dwProtocol = 0; + dwAtrLen = 0; + lreader_name[0] = 0; + if (status == 0) { - in_uint16_le(in_s, reader_name[index]); + 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); + if (dwReaderLen > 0) + { + in_uint32_le(in_s, dwReaderLen); + dwReaderLen /= 2; + } + else + { + dwReaderLen = 1; + } + if (dwReaderLen < 1) + { + LLOGLN(0, ("scard_function_status_return: dwReaderLen < 1")); + dwReaderLen = 1; + } + if (dwReaderLen > 99) + { + LLOGLN(0, ("scard_function_status_return: dwReaderLen too big " + "0x%8.8x", dwReaderLen)); + dwReaderLen = 99; + } + g_memset(reader_name, 0, sizeof(reader_name)); + g_memset(lreader_name, 0, sizeof(lreader_name)); + for (index = 0; index < dwReaderLen - 1; index++) + { + in_uint16_le(in_s, reader_name[index]); + } + g_wcstombs(lreader_name, reader_name, 99); } - 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)); @@ -844,7 +1428,7 @@ scard_function_status_return(struct trans *con, 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 */ + out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ s_mark_end(out_s); bytes = (int) (out_s->end - out_s->data); s_pop_layer(out_s, iso_hdr); @@ -863,13 +1447,12 @@ scard_process_get_status_change(struct trans *con, struct stream *in_s) int dwTimeout; int cReaders; READER_STATE *rsa; + struct pcsc_uds_client *uds_client; + void *user_data; + struct pcsc_context *lcontext; 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; - } + uds_client = (struct pcsc_uds_client *) (con->callback_data); in_uint32_le(in_s, hContext); in_uint32_le(in_s, dwTimeout); in_uint32_le(in_s, cReaders); @@ -900,10 +1483,17 @@ scard_process_get_status_change(struct trans *con, struct stream *in_s) 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); - + user_data = (void *) (tintptr) (uds_client->uds_client_id); + lcontext = get_pcsc_context_by_app_context(uds_client, hContext); + if (lcontext == 0) + { + LLOGLN(0, ("scard_process_get_status_change: " + "get_pcsc_context_by_app_context failed")); + return 1; + } + scard_send_get_status_change(user_data, + lcontext->context, lcontext->context_bytes, + 1, dwTimeout, cReaders, rsa); g_free(rsa); return 0; @@ -911,9 +1501,9 @@ scard_process_get_status_change(struct trans *con, struct stream *in_s) /*****************************************************************************/ int APP_CC -scard_function_get_status_change_return(struct trans *con, +scard_function_get_status_change_return(void *user_data, struct stream *in_s, - int len) + int len, int status) { int bytes; int index; @@ -923,59 +1513,138 @@ scard_function_get_status_change_return(struct trans *con, tui32 atr_len; /* number of bytes in atr[] */ tui8 atr[36]; struct stream *out_s; + int uds_client_id; + struct pcsc_uds_client *uds_client; + struct trans *con; 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(10, (" status 0x%8.8x", status)); + uds_client_id = (int) (tintptr) user_data; + uds_client = (struct pcsc_uds_client *) + get_uds_client_by_id(uds_client_id); + if (uds_client == 0) { - LLOGLN(0, ("scard_function_establish_context_return: opps")); + LLOGLN(0, ("scard_function_get_status_change_return: " + "get_uds_client_by_id failed")); 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) + con = uds_client->con; + + out_s = trans_get_out_s(con, 8192); + s_push_layer(out_s, iso_hdr, 8); + if (status != 0) + { + out_uint32_le(out_s, 0); /* cReaders */ + out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */ + } + else { - out_s = trans_get_out_s(con, 8192); - s_push_layer(out_s, iso_hdr, 8); + in_uint8s(in_s, 28); + in_uint32_le(in_s, cReaders); + LLOGLN(10, (" cReaders %d", cReaders)); out_uint32_le(out_s, cReaders); - for (index = 0; index < cReaders; index++) + if (cReaders > 0) { - 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); + 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); + out_uint32_le(out_s, status); /* 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); +} + +/*****************************************************************************/ +/* returns error */ +int APP_CC +scard_process_cancel(struct trans *con, struct stream *in_s) +{ + int hContext; + struct pcsc_uds_client *uds_client; + void *user_data; + struct pcsc_context *lcontext; + + LLOGLN(10, ("scard_process_cancel:")); + uds_client = (struct pcsc_uds_client *) (con->callback_data); + in_uint32_le(in_s, hContext); + LLOGLN(10, ("scard_process_cancel: hContext 0x%8.8x", hContext)); + user_data = (void *) (tintptr) (uds_client->uds_client_id); + lcontext = get_pcsc_context_by_app_context(uds_client, hContext); + if (lcontext == 0) + { + LLOGLN(0, ("scard_process_cancel: " + "get_pcsc_context_by_app_context failed")); + return 1; + } + scard_send_cancel(user_data, lcontext->context, lcontext->context_bytes); return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -scard_function_is_context_valid_return(struct trans *con, +scard_function_cancel_return(void *user_data, + struct stream *in_s, + int len, int status) +{ + int bytes; + int uds_client_id; + struct stream *out_s; + struct pcsc_uds_client *uds_client; + struct trans *con; + + LLOGLN(10, ("scard_function_cancel_return:")); + LLOGLN(10, (" status 0x%8.8x", status)); + uds_client_id = (int) (tintptr) user_data; + uds_client = (struct pcsc_uds_client *) + get_uds_client_by_id(uds_client_id); + if (uds_client == 0) + { + LLOGLN(0, ("scard_function_cancel_return: " + "get_uds_client_by_id failed")); + return 1; + } + con = uds_client->con; + out_s = trans_get_out_s(con, 8192); + s_push_layer(out_s, iso_hdr, 8); + out_uint32_le(out_s, status); /* 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, 0x0D); /* SCARD_CANCEL 0x0D */ + return trans_force_write(con); +} + +/*****************************************************************************/ +/* returns error */ +int APP_CC +scard_function_is_context_valid_return(void *user_data, struct stream *in_s, - int len) + int len, int status) { return 0; } /*****************************************************************************/ /* returns error */ -int APP_CC scard_function_reconnect_return(struct trans *con, +int APP_CC scard_function_reconnect_return(void *user_data, struct stream *in_s, - int len) + int len, int status) { return 0; } @@ -1050,7 +1719,8 @@ scard_process_msg(struct trans *con, struct stream *in_s, int command) break; case 0x0D: /* SCARD_CANCEL */ - LLOGLN(0, ("scard_process_msg: SCARD_CANCEL")); + LLOGLN(10, ("scard_process_msg: SCARD_CANCEL")); + rv = scard_process_cancel(con, in_s); break; case 0x0E: /* SCARD_CANCEL_TRANSACTION */ @@ -1088,10 +1758,6 @@ my_pcsc_trans_data_in(struct trans *trans) { return 0; } - if (trans != g_con) - { - return 1; - } s = trans_get_in_s(trans); in_uint32_le(s, size); in_uint32_le(s, command); @@ -1099,7 +1765,7 @@ my_pcsc_trans_data_in(struct trans *trans) error = trans_force_read(trans, size); if (error == 0) { - error = scard_process_msg(g_con, s, command); + error = scard_process_msg(trans, s, command); } return error; } @@ -1109,6 +1775,8 @@ my_pcsc_trans_data_in(struct trans *trans) int DEFAULT_CC my_pcsc_trans_conn_in(struct trans *trans, struct trans *new_trans) { + struct pcsc_uds_client *uds_client; + LLOGLN(10, ("my_pcsc_trans_conn_in:")); if (trans == 0) @@ -1126,9 +1794,20 @@ my_pcsc_trans_conn_in(struct trans *trans, struct trans *new_trans) return 1; } - g_con = new_trans; - g_con->trans_data_in = my_pcsc_trans_data_in; - g_con->header_size = 8; + uds_client = create_uds_client(new_trans); + if (uds_client == 0) + { + return 1; + } + uds_client->con->trans_data_in = my_pcsc_trans_data_in; + uds_client->con->header_size = 8; + + if (g_uds_clients == 0) + { + g_uds_clients = list_create(); + } + list_add_item(g_uds_clients, (tbus)uds_client); + return 0; } @@ -1136,7 +1815,6 @@ my_pcsc_trans_conn_in(struct trans *trans, struct trans *new_trans) int APP_CC scard_pcsc_init(void) { - char port[256]; char *home; int disp; int error; @@ -1145,31 +1823,35 @@ scard_pcsc_init(void) if (g_lis == 0) { g_lis = trans_create(2, 8192, 8192); - - //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_pcsclite_ipc_dir) != 0) + if (!g_remove_dir(g_pcsclite_ipc_dir)) { LLOGLN(0, ("scard_pcsc_init: g_remove_dir failed")); } } - if (!g_create_dir(g_pcsclite_ipc_dir)) + if (!g_directory_exist(g_pcsclite_ipc_dir)) { - LLOGLN(0, ("scard_pcsc_init: g_create_dir failed")); + if (!g_create_dir(g_pcsclite_ipc_dir)) + { + if (!g_directory_exist(g_pcsclite_ipc_dir)) + { + LLOGLN(0, ("scard_pcsc_init: g_create_dir failed")); + } + } } g_chmod_hex(g_pcsclite_ipc_dir, 0x1777); - g_snprintf(port, 255, "%s/pcscd.comm", g_pcsclite_ipc_dir); + g_snprintf(g_pcsclite_ipc_file, 255, "%s/pcscd.comm", g_pcsclite_ipc_dir); g_lis->trans_conn_in = my_pcsc_trans_conn_in; - error = trans_listen(g_lis, port); + error = trans_listen(g_lis, g_pcsclite_ipc_file); if (error != 0) { LLOGLN(0, ("scard_pcsc_init: trans_listen failed for port %s", - port)); + g_pcsclite_ipc_file)); return 1; } } @@ -1181,20 +1863,23 @@ int APP_CC scard_pcsc_deinit(void) { LLOGLN(0, ("scard_pcsc_deinit:")); + if (g_lis != 0) { trans_delete(g_lis); g_lis = 0; + } - g_file_close(g_pub_file_fd); - g_pub_file_fd = 0; - - if (g_remove_dir(g_pcsclite_ipc_dir) != 0) + if (g_pcsclite_ipc_dir[0] != 0) + { + g_file_delete(g_pcsclite_ipc_file); + if (!g_remove_dir(g_pcsclite_ipc_dir)) { LLOGLN(0, ("scard_pcsc_deinit: g_remove_dir failed")); } g_pcsclite_ipc_dir[0] = 0; } + return 0; } diff --git a/sesman/chansrv/smartcard_pcsc.h b/sesman/chansrv/smartcard_pcsc.h index bd5b9090..b7ca2183 100644 --- a/sesman/chansrv/smartcard_pcsc.h +++ b/sesman/chansrv/smartcard_pcsc.h @@ -28,62 +28,62 @@ 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, +int APP_CC scard_function_establish_context_return(void *user_data, struct stream *in_s, - int len); -int APP_CC scard_function_release_context_return(struct trans *con, + int len, int status); +int APP_CC scard_function_release_context_return(void *user_data, struct stream *in_s, - int len); -int APP_CC scard_function_list_readers_return(struct trans *con, + int len, int status); +int APP_CC scard_function_list_readers_return(void *user_data, struct stream *in_s, - int len); + int len, int status); -int APP_CC scard_function_transmit_return(struct trans *con, +int APP_CC scard_function_transmit_return(void *user_data, struct stream *in_s, - int len); + int len, int status); -int APP_CC scard_function_control_return(struct trans *con, +int APP_CC scard_function_control_return(void *user_data, struct stream *in_s, - int len); + int len, int status); -int APP_CC scard_function_get_status_change_return(struct trans *con, +int APP_CC scard_function_get_status_change_return(void *user_data, struct stream *in_s, - int len); + int len, int status); -int APP_CC scard_function_connect_return(struct trans *con, +int APP_CC scard_function_connect_return(void *user_data, struct stream *in_s, - int len); + int len, int status); -int APP_CC scard_function_status_return(struct trans *con, +int APP_CC scard_function_status_return(void *user_data, struct stream *in_s, - int len); + int len, int status); -int APP_CC scard_function_begin_transaction_return(struct trans *con, +int APP_CC scard_function_begin_transaction_return(void *user_data, struct stream *in_s, - int len); + int len, int status); -int APP_CC scard_function_end_transaction_return(struct trans *con, +int APP_CC scard_function_end_transaction_return(void *user_data, struct stream *in_s, - int len); + int len, int status); -int APP_CC scard_function_is_context_valid_return(struct trans *con, +int APP_CC scard_function_is_context_valid_return(void *user_data, struct stream *in_s, - int len); + int len, int status); -int APP_CC scard_function_reconnect_return(struct trans *con, +int APP_CC scard_function_reconnect_return(void *user_data, struct stream *in_s, - int len); + int len, int status); -int APP_CC scard_function_disconnect_return(struct trans *con, +int APP_CC scard_function_disconnect_return(void *user_data, struct stream *in_s, - int len); + int len, int status); -int APP_CC scard_function_cancel_return(struct trans *con, +int APP_CC scard_function_cancel_return(void *user_data, struct stream *in_s, - int len); + int len, int status); -int APP_CC scard_function_get_attrib_return(struct trans *con, +int APP_CC scard_function_get_attrib_return(void *user_data, struct stream *in_s, - int len); + int len, int status); #endif /* end #ifndef _SMARTCARD_PCSC_H */ diff --git a/sesman/chansrv/sound.c b/sesman/chansrv/sound.c index 2e85f1f2..eb299ecc 100644 --- a/sesman/chansrv/sound.c +++ b/sesman/chansrv/sound.c @@ -16,29 +16,53 @@ * limitations under the License. */ +#include <stdio.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/errno.h> +#include <signal.h> +#include <sys/un.h> + +#ifdef XRDP_LOAD_PULSE_MODULES +#include <pulse/util.h> +#endif + #include "sound.h" #include "thread_calls.h" #include "defines.h" +#include "fifo.h" extern int g_rdpsnd_chan_id; /* in chansrv.c */ extern int g_display_num; /* in chansrv.c */ -static struct trans *g_audio_l_trans = 0; /* listener */ -static struct trans *g_audio_c_trans = 0; /* connection */ -static int g_training_sent_time = 0; -static int g_cBlockNo = 0; +/* audio out: sound_server -> xrdp -> NeutrinoRDP */ +static struct trans *g_audio_l_trans_out = 0; /* listener */ +static struct trans *g_audio_c_trans_out = 0; /* connection */ + +/* audio in: sound_server <- xrdp <- NeutrinoRDP */ +static struct trans *g_audio_l_trans_in = 0; /* listener */ +static struct trans *g_audio_c_trans_in = 0; /* connection */ + +static int g_training_sent_time = 0; +static int g_cBlockNo = 0; +static int g_bytes_in_stream = 0; +static FIFO in_fifo; + +static struct stream *g_stream_inp = NULL; #define BBUF_SIZE (1024 * 8) char g_buffer[BBUF_SIZE]; int g_buf_index = 0; int g_sent_time[256]; +int g_sent_flag[256]; #if defined(XRDP_SIMPLESOUND) static void *DEFAULT_CC read_raw_audio_data(void *arg); #endif -#define CHANSRV_PORT_STR "/tmp/.xrdp/xrdp_chansrv_audio_socket_%d" +#define CHANSRV_PORT_OUT_STR "/tmp/.xrdp/xrdp_chansrv_audio_out_socket_%d" +#define CHANSRV_PORT_IN_STR "/tmp/.xrdp/xrdp_chansrv_audio_in_socket_%d" struct xr_wave_format_ex { @@ -52,8 +76,10 @@ struct xr_wave_format_ex char *data; }; -static char g_pmc_22050_data[] = { 0 }; -static struct xr_wave_format_ex g_pmc_22050 = +/* output formats */ + +static char g_pcm_22050_data[] = { 0 }; +static struct xr_wave_format_ex g_pcm_22050 = { 1, /* wFormatTag - WAVE_FORMAT_PCM */ 2, /* num of channels */ @@ -62,11 +88,11 @@ static struct xr_wave_format_ex g_pmc_22050 = 4, /* block align */ 16, /* bits per sample */ 0, /* data size */ - g_pmc_22050_data /* data */ + g_pcm_22050_data /* data */ }; -static char g_pmc_44100_data[] = { 0 }; -static struct xr_wave_format_ex g_pmc_44100 = +static char g_pcm_44100_data[] = { 0 }; +static struct xr_wave_format_ex g_pcm_44100 = { 1, /* wFormatTag - WAVE_FORMAT_PCM */ 2, /* num of channels */ @@ -75,24 +101,63 @@ static struct xr_wave_format_ex g_pmc_44100 = 4, /* block align */ 16, /* bits per sample */ 0, /* data size */ - g_pmc_44100_data /* data */ + g_pcm_44100_data /* data */ }; -#define NUM_BUILT_IN 2 -static struct xr_wave_format_ex *g_wave_formats[NUM_BUILT_IN] = +#define SND_NUM_OUTP_FORMATS 2 +static struct xr_wave_format_ex *g_wave_outp_formats[SND_NUM_OUTP_FORMATS] = { - &g_pmc_44100, - &g_pmc_22050 + &g_pcm_44100, + &g_pcm_22050 }; /* index into list from client */ static int g_current_client_format_index = 0; + /* index into list from server */ static int g_current_server_format_index = 0; +/* input formats */ + +static char g_pcm_inp_22050_data[] = { 0 }; +static struct xr_wave_format_ex g_pcm_inp_22050 = +{ + 1, /* wFormatTag - WAVE_FORMAT_PCM */ + 2, /* num of channels */ + 22050, /* samples per sec */ + 88200, /* avg bytes per sec */ + 4, /* block align */ + 16, /* bits per sample */ + 0, /* data size */ + g_pcm_inp_22050_data /* data */ +}; + +static char g_pcm_inp_44100_data[] = { 0 }; +static struct xr_wave_format_ex g_pcm_inp_44100 = +{ + 1, /* wFormatTag - WAVE_FORMAT_PCM */ + 2, /* num of channels */ + 44100, /* samples per sec */ + 176400, /* avg bytes per sec */ + 4, /* block align */ + 16, /* bits per sample */ + 0, /* data size */ + g_pcm_inp_44100_data /* data */ +}; + +#define SND_NUM_INP_FORMATS 2 +static struct xr_wave_format_ex *g_wave_inp_formats[SND_NUM_INP_FORMATS] = +{ + &g_pcm_inp_22050, + &g_pcm_inp_44100 +}; + +static int g_client_input_format_index = 0; +static int g_server_input_format_index = 0; + /*****************************************************************************/ static int APP_CC -sound_send_server_formats(void) +sound_send_server_output_formats(void) { struct stream *s; int bytes; @@ -103,15 +168,15 @@ sound_send_server_formats(void) init_stream(s, 8182); out_uint16_le(s, SNDC_FORMATS); size_ptr = s->p; - out_uint16_le(s, 0); /* size, set later */ - out_uint32_le(s, 0); /* dwFlags */ - out_uint32_le(s, 0); /* dwVolume */ - out_uint32_le(s, 0); /* dwPitch */ - out_uint16_le(s, 0); /* wDGramPort */ - out_uint16_le(s, NUM_BUILT_IN); /* wNumberOfFormats */ - out_uint8(s, g_cBlockNo); /* cLastBlockConfirmed */ - out_uint16_le(s, 2); /* wVersion */ - out_uint8(s, 0); /* bPad */ + out_uint16_le(s, 0); /* size, set later */ + out_uint32_le(s, 0); /* dwFlags */ + out_uint32_le(s, 0); /* dwVolume */ + out_uint32_le(s, 0); /* dwPitch */ + out_uint16_le(s, 0); /* wDGramPort */ + out_uint16_le(s, SND_NUM_OUTP_FORMATS); /* wNumberOfFormats */ + out_uint8(s, g_cBlockNo); /* cLastBlockConfirmed */ + out_uint16_le(s, 2); /* wVersion */ + out_uint8(s, 0); /* bPad */ /* sndFormats */ /* @@ -132,19 +197,19 @@ sound_send_server_formats(void) 00 00 */ - for (index = 0; index < NUM_BUILT_IN; index++) + for (index = 0; index < SND_NUM_OUTP_FORMATS; index++) { - out_uint16_le(s, g_wave_formats[index]->wFormatTag); - out_uint16_le(s, g_wave_formats[index]->nChannels); - out_uint32_le(s, g_wave_formats[index]->nSamplesPerSec); - out_uint32_le(s, g_wave_formats[index]->nAvgBytesPerSec); - out_uint16_le(s, g_wave_formats[index]->nBlockAlign); - out_uint16_le(s, g_wave_formats[index]->wBitsPerSample); - bytes = g_wave_formats[index]->cbSize; + out_uint16_le(s, g_wave_outp_formats[index]->wFormatTag); + out_uint16_le(s, g_wave_outp_formats[index]->nChannels); + out_uint32_le(s, g_wave_outp_formats[index]->nSamplesPerSec); + out_uint32_le(s, g_wave_outp_formats[index]->nAvgBytesPerSec); + out_uint16_le(s, g_wave_outp_formats[index]->nBlockAlign); + out_uint16_le(s, g_wave_outp_formats[index]->wBitsPerSample); + bytes = g_wave_outp_formats[index]->cbSize; out_uint16_le(s, bytes); if (bytes > 0) { - out_uint8p(s, g_wave_formats[index]->data, bytes); + out_uint8p(s, g_wave_outp_formats[index]->data, bytes); } } @@ -159,6 +224,7 @@ sound_send_server_formats(void) } /*****************************************************************************/ + static int sound_send_training(void) { @@ -189,26 +255,29 @@ sound_send_training(void) /*****************************************************************************/ static int APP_CC -sound_process_format(int aindex, int wFormatTag, int nChannels, - int nSamplesPerSec, int nAvgBytesPerSec, - int nBlockAlign, int wBitsPerSample, - int cbSize, char *data) -{ - LOG(0, ("sound_process_format:")); - LOG(0, (" wFormatTag %d", wFormatTag)); - LOG(0, (" nChannels %d", nChannels)); - LOG(0, (" nSamplesPerSec %d", nSamplesPerSec)); - LOG(0, (" nAvgBytesPerSec %d", nAvgBytesPerSec)); - LOG(0, (" nBlockAlign %d", nBlockAlign)); - LOG(0, (" wBitsPerSample %d", wBitsPerSample)); - LOG(0, (" cbSize %d", cbSize)); +sound_process_output_format(int aindex, int wFormatTag, int nChannels, + int nSamplesPerSec, int nAvgBytesPerSec, + int nBlockAlign, int wBitsPerSample, + int cbSize, char *data) +{ + LOG(1, ("sound_process_output_format:")); + LOG(1, (" wFormatTag %d", wFormatTag)); + LOG(1, (" nChannels %d", nChannels)); + LOG(1, (" nSamplesPerSec %d", nSamplesPerSec)); + LOG(1, (" nAvgBytesPerSec %d", nAvgBytesPerSec)); + LOG(1, (" nBlockAlign %d", nBlockAlign)); + LOG(1, (" wBitsPerSample %d", wBitsPerSample)); + LOG(1, (" cbSize %d", cbSize)); + g_hexdump(data, cbSize); - if (wFormatTag == g_pmc_44100.wFormatTag && - nChannels == g_pmc_44100.nChannels && - nSamplesPerSec == g_pmc_44100.nSamplesPerSec && - nAvgBytesPerSec == g_pmc_44100.nAvgBytesPerSec && - nBlockAlign == g_pmc_44100.nBlockAlign && - wBitsPerSample == g_pmc_44100.wBitsPerSample) + + /* select CD quality audio */ + if (wFormatTag == g_pcm_44100.wFormatTag && + nChannels == g_pcm_44100.nChannels && + nSamplesPerSec == g_pcm_44100.nSamplesPerSec && + nAvgBytesPerSec == g_pcm_44100.nAvgBytesPerSec && + nBlockAlign == g_pcm_44100.nBlockAlign && + wBitsPerSample == g_pcm_44100.wBitsPerSample) { g_current_client_format_index = aindex; g_current_server_format_index = 0; @@ -225,7 +294,7 @@ sound_process_format(int aindex, int wFormatTag, int nChannels, { g_current_client_format_index = aindex; g_current_server_format_index = lindex; - } + } } #endif return 0; @@ -239,7 +308,7 @@ sound_process_format(int aindex, int wFormatTag, int nChannels, */ static int APP_CC -sound_process_formats(struct stream *s, int size) +sound_process_output_formats(struct stream *s, int size) { int num_formats; int index; @@ -252,12 +321,8 @@ sound_process_formats(struct stream *s, int size) int cbSize; char *data; - LOG(0, ("sound_process_formats:")); - if (size < 16) - { return 1; - } in_uint8s(s, 14); in_uint16_le(s, num_formats); @@ -275,9 +340,9 @@ sound_process_formats(struct stream *s, int size) in_uint16_le(s, wBitsPerSample); in_uint16_le(s, cbSize); in_uint8p(s, data, cbSize); - sound_process_format(index, wFormatTag, nChannels, nSamplesPerSec, - nAvgBytesPerSec, nBlockAlign, wBitsPerSample, - cbSize, data); + sound_process_output_format(index, wFormatTag, nChannels, nSamplesPerSec, + nAvgBytesPerSec, nBlockAlign, wBitsPerSample, + cbSize, data); } sound_send_training(); } @@ -303,6 +368,16 @@ sound_send_wave_data_chunk(char *data, int data_bytes) return 0; } + if (g_sent_flag[(g_cBlockNo + 1) & 0xff] & 1) + { + LOG(10, ("sound_send_wave_data_chunk: no room")); + return 0; + } + else + { + LOG(10, ("sound_send_wave_data_chunk: got room")); + } + /* part one of 2 PDU wave info */ LOG(10, ("sound_send_wave_data_chunk: sending %d bytes", data_bytes)); @@ -318,6 +393,7 @@ sound_send_wave_data_chunk(char *data, int data_bytes) g_cBlockNo++; out_uint8(s, g_cBlockNo); g_sent_time[g_cBlockNo & 0xff] = time; + g_sent_flag[g_cBlockNo & 0xff] = 1; LOG(10, ("sound_send_wave_data_chunk: sending time %d, g_cBlockNo %d", time & 0xffff, g_cBlockNo & 0xff)); @@ -434,7 +510,8 @@ sound_process_wave_confirm(struct stream *s, int size) time = g_time2(); in_uint16_le(s, wTimeStamp); in_uint8(s, cConfirmedBlockNo); - time_diff = time - g_sent_time[cConfirmedBlockNo]; + time_diff = time - g_sent_time[cConfirmedBlockNo & 0xff]; + g_sent_flag[cConfirmedBlockNo & 0xff] &= ~1; LOG(10, ("sound_process_wave_confirm: wTimeStamp %d, " "cConfirmedBlockNo %d time diff %d", @@ -458,16 +535,18 @@ process_pcm_message(int id, int size, struct stream *s) sound_send_close(); break; default: - LOG(0, ("process_pcm_message: unknown id %d", id)); + LOG(10, ("process_pcm_message: unknown id %d", id)); break; } return 0; } /*****************************************************************************/ -/* data in from audio source, eg pulse, alsa */ + +/* data in from sound_server_sink */ + static int DEFAULT_CC -sound_trans_audio_data_in(struct trans *trans) +sound_sndsrvr_sink_data_in(struct trans *trans) { struct stream *s; int id; @@ -475,14 +554,10 @@ sound_trans_audio_data_in(struct trans *trans) int error; if (trans == 0) - { return 0; - } - if (trans != g_audio_c_trans) - { + if (trans != g_audio_c_trans_out) return 1; - } s = trans_get_in_s(trans); in_uint32_le(s, id); @@ -490,10 +565,11 @@ sound_trans_audio_data_in(struct trans *trans) if ((id & ~3) || (size > 128 * 1024 + 8) || (size < 8)) { - LOG(0, ("sound_trans_audio_data_in: bad message id %d size %d", id, size)); + LOG(0, ("sound_sndsrvr_sink_data_in: bad message id %d size %d", id, size)); return 1; } - LOG(10, ("sound_trans_audio_data_in: good message id %d size %d", id, size)); + + LOG(10, ("sound_sndsrvr_sink_data_in: good message id %d size %d", id, size)); error = trans_force_read(trans, size - 8); @@ -507,37 +583,62 @@ sound_trans_audio_data_in(struct trans *trans) } /*****************************************************************************/ -/* this is a connection in on the unix domain socket */ + +/* incoming connection on unix domain socket - sound_server_sink -> xrdp */ + static int DEFAULT_CC -sound_trans_audio_conn_in(struct trans *trans, struct trans *new_trans) +sound_sndsrvr_sink_conn_in(struct trans *trans, struct trans *new_trans) { - LOG(0, ("sound_trans_audio_conn_in:")); + LOG(0, ("sound_sndsrvr_sink_conn_in:")); if (trans == 0) - { return 1; - } - if (trans != g_audio_l_trans) - { + if (trans != g_audio_l_trans_out) return 1; - } - if (g_audio_c_trans != 0) /* if already set, error */ - { + if (g_audio_c_trans_out != 0) /* if already set, error */ return 1; - } if (new_trans == 0) - { return 1; - } - g_audio_c_trans = new_trans; - g_audio_c_trans->trans_data_in = sound_trans_audio_data_in; - g_audio_c_trans->header_size = 8; - trans_delete(g_audio_l_trans); - g_audio_l_trans = 0; + g_audio_c_trans_out = new_trans; + g_audio_c_trans_out->trans_data_in = sound_sndsrvr_sink_data_in; + g_audio_c_trans_out->header_size = 8; + trans_delete(g_audio_l_trans_out); + g_audio_l_trans_out = 0; + + return 0; +} + +/*****************************************************************************/ + +/* incoming connection on unix domain socket - sound_server_source -> xrdp */ + +static int DEFAULT_CC +sound_sndsrvr_source_conn_in(struct trans *trans, struct trans *new_trans) +{ + LOG(0, ("sound_sndsrvr_source_conn_in: client connected")); + + if (trans == 0) + return 1; + + if (trans != g_audio_l_trans_in) + return 1; + + if (g_audio_c_trans_in != 0) /* if already set, error */ + return 1; + + if (new_trans == 0) + return 1; + + g_audio_c_trans_in = new_trans; + g_audio_c_trans_in->trans_data_in = sound_sndsrvr_source_data_in; + g_audio_c_trans_in->header_size = 8; + trans_delete(g_audio_l_trans_in); + g_audio_l_trans_in = 0; + return 0; } @@ -546,21 +647,40 @@ int APP_CC sound_init(void) { char port[256]; - int error; LOG(0, ("sound_init:")); - sound_send_server_formats(); - 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); + g_memset(g_sent_flag, 0, sizeof(g_sent_flag)); - if (error != 0) - { +#ifdef XRDP_LOAD_PULSE_MODULES + if (load_pulse_modules()) + LOG(0, ("Audio and microphone redirection will not work!")); +#endif + + /* init sound output */ + sound_send_server_output_formats(); + + g_audio_l_trans_out = trans_create(TRANS_MODE_UNIX, 128 * 1024, 8192); + g_audio_l_trans_out->is_term = g_is_term; + g_snprintf(port, 255, CHANSRV_PORT_OUT_STR, g_display_num); + g_audio_l_trans_out->trans_conn_in = sound_sndsrvr_sink_conn_in; + + if (trans_listen(g_audio_l_trans_out, port) != 0) + LOG(0, ("sound_init: trans_listen failed")); + + /* init sound input */ + sound_send_server_input_formats(); + + g_audio_l_trans_in = trans_create(TRANS_MODE_UNIX, 128 * 1024, 8192); + g_audio_l_trans_in->is_term = g_is_term; + g_snprintf(port, 255, CHANSRV_PORT_IN_STR, g_display_num); + g_audio_l_trans_in->trans_conn_in = sound_sndsrvr_source_conn_in; + + if (trans_listen(g_audio_l_trans_in, port) != 0) LOG(0, ("sound_init: trans_listen failed")); - } + + /* save data from sound_server_source */ + fifo_init(&in_fifo, 100); #if defined(XRDP_SIMPLESOUND) @@ -576,23 +696,43 @@ sound_init(void) int APP_CC sound_deinit(void) { - if (g_audio_l_trans != 0) + if (g_audio_l_trans_out != 0) + { + trans_delete(g_audio_l_trans_out); + g_audio_l_trans_out = 0; + } + + if (g_audio_c_trans_out != 0) { - trans_delete(g_audio_l_trans); - g_audio_l_trans = 0; + trans_delete(g_audio_c_trans_out); + g_audio_c_trans_out = 0; } - if (g_audio_c_trans != 0) + if (g_audio_l_trans_in != 0) { - trans_delete(g_audio_c_trans); - g_audio_c_trans = 0; + trans_delete(g_audio_l_trans_in); + g_audio_l_trans_in = 0; } + if (g_audio_c_trans_in != 0) + { + trans_delete(g_audio_c_trans_in); + g_audio_c_trans_in = 0; + } + + fifo_deinit(&in_fifo); + +#ifdef XRDP_LOAD_PULSE_MODULES + system("pulseaudio --kill"); +#endif + return 0; } /*****************************************************************************/ + /* data in from client ( client -> xrdp -> chansrv ) */ + int APP_CC sound_data_in(struct stream *s, int chan_id, int chan_flags, int length, int total_length) @@ -615,11 +755,19 @@ sound_data_in(struct stream *s, int chan_id, int chan_flags, int length, break; case SNDC_FORMATS: - sound_process_formats(s, size); + sound_process_output_formats(s, size); + break; + + case SNDC_REC_NEGOTIATE: + sound_process_input_formats(s, size); + break; + + case SNDC_REC_DATA: + sound_process_input_data(s, size); break; default: - LOG(0, ("sound_data_in: unknown code %d size %d", code, size)); + LOG(10, ("sound_data_in: unknown code %d size %d", code, size)); break; } @@ -634,15 +782,27 @@ sound_get_wait_objs(tbus *objs, int *count, int *timeout) lcount = *count; - if (g_audio_l_trans != 0) + if (g_audio_l_trans_out != 0) { - objs[lcount] = g_audio_l_trans->sck; + objs[lcount] = g_audio_l_trans_out->sck; lcount++; } - if (g_audio_c_trans != 0) + if (g_audio_c_trans_out != 0) { - objs[lcount] = g_audio_c_trans->sck; + objs[lcount] = g_audio_c_trans_out->sck; + lcount++; + } + + if (g_audio_l_trans_in != 0) + { + objs[lcount] = g_audio_l_trans_in->sck; + lcount++; + } + + if (g_audio_c_trans_in != 0) + { + objs[lcount] = g_audio_c_trans_in->sck; lcount++; } @@ -654,19 +814,517 @@ sound_get_wait_objs(tbus *objs, int *count, int *timeout) int APP_CC sound_check_wait_objs(void) { - if (g_audio_l_trans != 0) + if (g_audio_l_trans_out != 0) + { + trans_check_wait_objs(g_audio_l_trans_out); + } + + if (g_audio_c_trans_out != 0) + { + trans_check_wait_objs(g_audio_c_trans_out); + } + + if (g_audio_l_trans_in != 0) { - trans_check_wait_objs(g_audio_l_trans); + trans_check_wait_objs(g_audio_l_trans_in); } - if (g_audio_c_trans != 0) + if (g_audio_c_trans_in != 0) { - trans_check_wait_objs(g_audio_c_trans); + trans_check_wait_objs(g_audio_c_trans_in); } return 0; } +/** + * Load xrdp pulseaudio sink and source modules + * + * @return 0 on success, -1 on failure + *****************************************************************************/ + +#ifdef XRDP_LOAD_PULSE_MODULES + +static int APP_CC +load_pulse_modules() +{ + struct sockaddr_un sa; + + pid_t pid; + char* cli; + int fd; + int i; + int rv; + char buf[1024]; + + /* is pulse audio daemon running? */ + if (pa_pid_file_check_running(&pid, "pulseaudio") < 0) + { + LOG(0, ("load_pulse_modules: No PulseAudio daemon running, " + "or not running as session daemon")); + } + + /* get name of unix domain socket used by pulseaudio for CLI */ + if ((cli = (char *) pa_runtime_path("cli")) == NULL) + { + LOG(0, ("load_pulse_modules: Error getting PulesAudio runtime path")); + return -1; + } + + /* open a socket */ + if ((fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) + { + pa_xfree(cli); + LOG(0, ("load_pulse_modules: Socket open error")); + return -1; + } + + /* set it up */ + memset(&sa, 0, sizeof(struct sockaddr_un)); + sa.sun_family = AF_UNIX; + pa_strlcpy(sa.sun_path, cli, sizeof(sa.sun_path)); + pa_xfree(cli); + + for (i = 0; i < 20; i++) + { + if (pa_pid_file_kill(SIGUSR2, NULL, "pulseaudio") < 0) + LOG(0, ("load_pulse_modules: Failed to kill PulseAudio daemon")); + + if ((rv = connect(fd, (struct sockaddr*) &sa, sizeof(sa))) < 0 && + (errno != ECONNREFUSED && errno != ENOENT)) + { + LOG(0, ("load_pulse_modules: connect() failed with error: %s", + strerror(errno))); + return -1; + } + + if (rv >= 0) + break; + + pa_msleep(300); + } + + if (i >= 20) + { + LOG(0, ("load_pulse_modules: Daemon not responding")); + return -1; + } + + LOG(0, ("load_pulse_modules: connected to pulseaudio daemon")); + + /* read back PulseAudio sign on message */ + memset(buf, 0, 1024); + recv(fd, buf, 1024, 0); + + /* send cmd to load source module */ + memset(buf, 0, 1024); + sprintf(buf, "load-module module-xrdp-source\n"); + send(fd, buf, strlen(buf), 0); + + /* read back response */ + memset(buf, 0, 1024); + recv(fd, buf, 1024, 0); + if (strcasestr(buf, "Module load failed") != 0) + { + LOG(0, ("load_pulse_modules: Error loading module-xrdp-source")); + } + else + { + LOG(0, ("load_pulse_modules: Loaded module-xrdp-source")); + + /* success, set it as the default source */ + memset(buf, 0, 1024); + sprintf(buf, "set-default-source xrdp-source\n"); + send(fd, buf, strlen(buf), 0); + + memset(buf, 0, 1024); + recv(fd, buf, 1024, 0); + + if (strcasestr(buf, "does not exist") != 0) + { + LOG(0, ("load_pulse_modules: Error setting default source")); + } + else + { + LOG(0, ("load_pulse_modules: set default source")); + } + } + + /* send cmd to load sink module */ + memset(buf, 0, 1024); + sprintf(buf, "load-module module-xrdp-sink\n"); + send(fd, buf, strlen(buf), 0); + + /* read back response */ + memset(buf, 0, 1024); + recv(fd, buf, 1024, 0); + if (strcasestr(buf, "Module load failed") != 0) + { + LOG(0, ("load_pulse_modules: Error loading module-xrdp-sink")); + } + else + { + LOG(0, ("load_pulse_modules: Loaded module-xrdp-sink")); + + /* success, set it as the default sink */ + memset(buf, 0, 1024); + sprintf(buf, "set-default-sink xrdp-sink\n"); + send(fd, buf, strlen(buf), 0); + + memset(buf, 0, 1024); + recv(fd, buf, 1024, 0); + + if (strcasestr(buf, "does not exist") != 0) + { + LOG(0, ("load_pulse_modules: Error setting default sink")); + } + else + { + LOG(0, ("load_pulse_modules: set default sink")); + } + } + + close(fd); + return 0; +} +#endif + +/****************************************************************************** + ** ** + ** Microphone releated code ** + ** ** + ******************************************************************************/ + +/** + * + *****************************************************************************/ + +static int APP_CC +sound_send_server_input_formats(void) +{ + struct stream* s; + int bytes; + int index; + char* size_ptr; + + make_stream(s); + init_stream(s, 8182); + out_uint16_le(s, SNDC_REC_NEGOTIATE); + size_ptr = s->p; + out_uint16_le(s, 0); /* size, set later */ + out_uint32_le(s, 0); /* unused */ + out_uint32_le(s, 0); /* unused */ + out_uint16_le(s, SND_NUM_INP_FORMATS); /* wNumberOfFormats */ + out_uint16_le(s, 2); /* wVersion */ + + /* + wFormatTag 2 byte offset 0 + nChannels 2 byte offset 2 + nSamplesPerSec 4 byte offset 4 + nAvgBytesPerSec 4 byte offset 8 + nBlockAlign 2 byte offset 12 + wBitsPerSample 2 byte offset 14 + cbSize 2 byte offset 16 + data variable offset 18 + */ + + for (index = 0; index < SND_NUM_INP_FORMATS; index++) + { + out_uint16_le(s, g_wave_inp_formats[index]->wFormatTag); + out_uint16_le(s, g_wave_inp_formats[index]->nChannels); + out_uint32_le(s, g_wave_inp_formats[index]->nSamplesPerSec); + out_uint32_le(s, g_wave_inp_formats[index]->nAvgBytesPerSec); + out_uint16_le(s, g_wave_inp_formats[index]->nBlockAlign); + out_uint16_le(s, g_wave_inp_formats[index]->wBitsPerSample); + bytes = g_wave_inp_formats[index]->cbSize; + out_uint16_le(s, bytes); + if (bytes > 0) + { + out_uint8p(s, g_wave_inp_formats[index]->data, bytes); + } + } + + s_mark_end(s); + bytes = (int)((s->end - s->data) - 4); + size_ptr[0] = bytes; + size_ptr[1] = bytes >> 8; + bytes = (int)(s->end - s->data); + send_channel_data(g_rdpsnd_chan_id, s->data, bytes); + free_stream(s); + return 0; +} + +/** + * + *****************************************************************************/ + +static int APP_CC +sound_process_input_format(int aindex, int wFormatTag, int nChannels, + int nSamplesPerSec, int nAvgBytesPerSec, + int nBlockAlign, int wBitsPerSample, + int cbSize, char *data) +{ + LOG(10, ("sound_process_input_format:")); + LOG(10, (" wFormatTag %d", wFormatTag)); + LOG(10, (" nChannels %d", nChannels)); + LOG(10, (" nSamplesPerSec %d", nSamplesPerSec)); + LOG(10, (" nAvgBytesPerSec %d", nAvgBytesPerSec)); + LOG(10, (" nBlockAlign %d", nBlockAlign)); + LOG(10, (" wBitsPerSample %d", wBitsPerSample)); + LOG(10, (" cbSize %d", cbSize)); + +#if 0 + /* select CD quality audio */ + if (wFormatTag == g_pcm_inp_44100.wFormatTag && + nChannels == g_pcm_inp_44100.nChannels && + nSamplesPerSec == g_pcm_inp_44100.nSamplesPerSec && + nAvgBytesPerSec == g_pcm_inp_44100.nAvgBytesPerSec && + nBlockAlign == g_pcm_inp_44100.nBlockAlign && + wBitsPerSample == g_pcm_inp_44100.wBitsPerSample) + { + g_client_input_format_index = aindex; + g_server_input_format_index = 0; + } +#else + /* select half of CD quality audio */ + if (wFormatTag == g_pcm_inp_22050.wFormatTag && + nChannels == g_pcm_inp_22050.nChannels && + nSamplesPerSec == g_pcm_inp_22050.nSamplesPerSec && + nAvgBytesPerSec == g_pcm_inp_22050.nAvgBytesPerSec && + nBlockAlign == g_pcm_inp_22050.nBlockAlign && + wBitsPerSample == g_pcm_inp_22050.wBitsPerSample) + { + g_client_input_format_index = aindex; + g_server_input_format_index = 0; + } +#endif + + return 0; +} + +/** + * + *****************************************************************************/ + +static int APP_CC +sound_process_input_formats(struct stream *s, int size) +{ + int num_formats; + int index; + int wFormatTag; + int nChannels; + int nSamplesPerSec; + int nAvgBytesPerSec; + int nBlockAlign; + int wBitsPerSample; + int cbSize; + char *data; + + LOG(10, ("sound_process_input_formats: size=%d", size)); + + in_uint8s(s, 8); /* skip 8 bytes */ + in_uint16_le(s, num_formats); + in_uint8s(s, 2); /* skip version */ + + if (num_formats > 0) + { + for (index = 0; index < num_formats; index++) + { + in_uint16_le(s, wFormatTag); + in_uint16_le(s, nChannels); + in_uint32_le(s, nSamplesPerSec); + in_uint32_le(s, nAvgBytesPerSec); + in_uint16_le(s, nBlockAlign); + in_uint16_le(s, wBitsPerSample); + in_uint16_le(s, cbSize); + in_uint8p(s, data, cbSize); + sound_process_input_format(index, wFormatTag, nChannels, nSamplesPerSec, + nAvgBytesPerSec, nBlockAlign, wBitsPerSample, + cbSize, data); + } + } + + return 0; +} + +/** + * + *****************************************************************************/ + +static int APP_CC +sound_input_start_recording() +{ + struct stream* s; + + /* if there is any data in FIFO, discard it */ + while ((s = (struct stream *) fifo_remove(&in_fifo)) != NULL) + xstream_free(s); + + xstream_new(s, 1024); + + /* + * command format + * + * 02 bytes command SNDC_REC_START + * 02 bytes length + * 02 bytes data format received earlier + */ + + out_uint16_le(s, SNDC_REC_START); + out_uint16_le(s, 2); + out_uint16_le(s, g_client_input_format_index); + + s_mark_end(s); + send_channel_data(g_rdpsnd_chan_id, s->data, 6); + xstream_free(s); + + return 0; +} + +/** + * + *****************************************************************************/ + +static int APP_CC +sound_input_stop_recording() +{ + struct stream* s; + + xstream_new(s, 1024); + + /* + * command format + * + * 02 bytes command SNDC_REC_STOP + * 02 bytes length (zero) + */ + + out_uint16_le(s, SNDC_REC_STOP); + out_uint16_le(s, 0); + + s_mark_end(s); + send_channel_data(g_rdpsnd_chan_id, s->data, 4); + xstream_free(s); + + return 0; +} + +/** + * Process data: xrdp <- client + *****************************************************************************/ + +static unsigned char data = 0; + +static int APP_CC +sound_process_input_data(struct stream *s, int bytes) +{ + struct stream *ls; + + xstream_new(ls, bytes); + memcpy(ls->data, s->p, bytes); + ls->p += bytes; + s_mark_end(ls); + + fifo_insert(&in_fifo, (void *) ls); + + return 0; +} + +/** + * Got a command from sound_server_source + *****************************************************************************/ + +static int DEFAULT_CC +sound_sndsrvr_source_data_in(struct trans *trans) +{ + struct stream *ts = NULL; + struct stream *s = NULL; + + tui16 bytes_req = 0; + int bytes_read = 0; + int cmd; + int i; + + if (trans == 0) + return 0; + + if (trans != g_audio_c_trans_in) + return 1; + + ts = trans_get_in_s(trans); + trans_force_read(trans, 3); + + ts->p = ts->data + 8; + in_uint8(ts, cmd); + in_uint16_le(ts, bytes_req); + + if (bytes_req != 0) + xstream_new(s, bytes_req + 2); + + if (cmd == PA_CMD_SEND_DATA) + { + /* set real len later */ + out_uint16_le(s, 0); + + while (bytes_read < bytes_req) + { + if (g_stream_inp == NULL) + g_stream_inp = (struct stream *) fifo_remove(&in_fifo); + + if (g_stream_inp == NULL) + { + /* no more data, send what we have */ + break; + } + else + { + if (g_bytes_in_stream == 0) + g_bytes_in_stream = g_stream_inp->size; + + i = bytes_req - bytes_read; + + if (i < g_bytes_in_stream) + { + xstream_copyin(s, &g_stream_inp->data[g_stream_inp->size - g_bytes_in_stream], i); + bytes_read += i; + g_bytes_in_stream -= i; + } + else + { + xstream_copyin(s, &g_stream_inp->data[g_stream_inp->size - g_bytes_in_stream], g_bytes_in_stream); + bytes_read += g_bytes_in_stream; + g_bytes_in_stream = 0; + xstream_free(g_stream_inp); + g_stream_inp = NULL; + } + } + } + + if (bytes_read) + { + s->data[0] = (char) (bytes_read & 0xff); + s->data[1] = (char) ((bytes_read >> 8) & 0xff); + } + + s_mark_end(s); + + trans_force_write_s(trans, s); + xstream_free(s); + } + else if (cmd == PA_CMD_START_REC) + { + sound_input_start_recording(); + } + else if (cmd == PA_CMD_STOP_REC) + { + sound_input_stop_recording(); + } + + return 0; +} + +/*****************************************************************************/ + #if defined(XRDP_SIMPLESOUND) #define AUDIO_BUF_SIZE 2048 diff --git a/sesman/chansrv/sound.h b/sesman/chansrv/sound.h index 0666ea00..c26d0913 100644 --- a/sesman/chansrv/sound.h +++ b/sesman/chansrv/sound.h @@ -43,16 +43,37 @@ #define SNDC_UDPWAVELAST 0x0B #define SNDC_QUALITYMODE 0x0C -int APP_CC -sound_init(void); -int APP_CC -sound_deinit(void); -int APP_CC -sound_get_wait_objs(tbus* objs, int* count, int* timeout); -int APP_CC -sound_check_wait_objs(void); -int APP_CC -sound_data_in(struct stream* s, int chan_id, int chan_flags, - int length, int total_length); +/* used for sound input (mic) */ +#define SNDC_REC_NEGOTIATE 39 +#define SNDC_REC_START 40 +#define SNDC_REC_STOP 41 +#define SNDC_REC_DATA 42 +#define SNDC_REC_SET_VOLUME 43 +/* commands recvd from pulseaudio source */ +#define PA_CMD_START_REC 1 +#define PA_CMD_STOP_REC 2 +#define PA_CMD_SEND_DATA 3 + +int APP_CC sound_init(void); +int APP_CC sound_deinit(void); +int APP_CC sound_get_wait_objs(tbus* objs, int* count, int* timeout); +int APP_CC sound_check_wait_objs(void); + +int APP_CC sound_data_in(struct stream* s, int chan_id, int chan_flags, + int length, int total_length); + +/* microphone related */ +static int APP_CC sound_send_server_input_formats(void); + +static int APP_CC sound_process_input_format(int aindex, int wFormatTag, + int nChannels, int nSamplesPerSec, int nAvgBytesPerSec, + int nBlockAlign, int wBitsPerSample, int cbSize, char *data); + +static int APP_CC sound_process_input_formats(struct stream *s, int size); +static int APP_CC sound_input_start_recording(); +static int APP_CC sound_input_stop_recording(); +static int APP_CC sound_process_input_data(struct stream *s, int bytes); +static int DEFAULT_CC sound_sndsrvr_source_data_in(struct trans *trans); +static int APP_CC load_pulse_modules(); #endif diff --git a/sesman/sesman.ini b/sesman/sesman.ini index 02fef5ba..5ee0b4cd 100644 --- a/sesman/sesman.ini +++ b/sesman/sesman.ini @@ -16,7 +16,7 @@ AlwaysGroupCheck = false [Sessions] X11DisplayOffset=10 -MaxSessions=10 +MaxSessions=50 # if 1, true, or yes, kill session after 60 seconds KillDisconnected=0 # if not zero, the seconds without mouse or keyboard input before disconnect diff --git a/sesman/session.c b/sesman/session.c index a5932736..32b2e6be 100644 --- a/sesman/session.c +++ b/sesman/session.c @@ -551,6 +551,7 @@ session_start_fork(int width, int height, int bpp, char *username, { g_waitpid(pampid); auth_stop_session(data); + g_deinit(); g_exit(0); } } diff --git a/tests/tcp_proxy/Makefile b/tests/tcp_proxy/Makefile index d19b4818..8f5821d3 100644 --- a/tests/tcp_proxy/Makefile +++ b/tests/tcp_proxy/Makefile @@ -1,6 +1,7 @@ -CFLAGS = -O2 -Wall -I../../common -LDFLAGS = -Wl -OBJS = main.o ../../common/os_calls.o + +CFLAGS = -O2 -Wall +LDFLAGS = +OBJS = main.o LIBS = -ldl all: tcp_proxy diff --git a/tests/tcp_proxy/main.c b/tests/tcp_proxy/main.c index 53458a57..2d283ed9 100644 --- a/tests/tcp_proxy/main.c +++ b/tests/tcp_proxy/main.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,20 @@ * limitations under the License. */ -#include <os_calls.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <unistd.h> +#include <fcntl.h> +#include <signal.h> +#include <errno.h> +#include <locale.h> +#include <netdb.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> int g_loc_io_count = 0; // bytes read from local port int g_rem_io_count = 0; // bytes read from remote port @@ -24,6 +37,394 @@ int g_rem_io_count = 0; // bytes read from remote port static int g_terminated = 0; static char g_buf[1024 * 32]; +#define DEFAULT_CC +#define APP_CC + +typedef unsigned short tui16; + +/*****************************************************************************/ +static void APP_CC +g_memset(void *ptr, int val, int size) +{ + memset(ptr, val, size); +} + +/*****************************************************************************/ +static void DEFAULT_CC +g_printf(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vfprintf(stdout, format, ap); + va_end(ap); +} + +/*****************************************************************************/ +static void DEFAULT_CC +g_writeln(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vfprintf(stdout, format, ap); + va_end(ap); + g_printf("\n"); +} + +/*****************************************************************************/ +static void APP_CC +g_hexdump(char *p, int len) +{ + unsigned char *line; + int i; + int thisline; + int offset; + + line = (unsigned char *)p; + offset = 0; + + while (offset < len) + { + g_printf("%04x ", offset); + thisline = len - offset; + + if (thisline > 16) + { + thisline = 16; + } + + for (i = 0; i < thisline; i++) + { + g_printf("%02x ", line[i]); + } + + for (; i < 16; i++) + { + g_printf(" "); + } + + for (i = 0; i < thisline; i++) + { + g_printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.'); + } + + g_writeln(""); + offset += thisline; + line += thisline; + } +} + +/*****************************************************************************/ +static int APP_CC +g_tcp_socket(void) +{ + int rv; + int option_value; + unsigned int option_len; + + rv = (int)socket(AF_INET, SOCK_STREAM, 0); + if (rv < 0) + { + return -1; + } + option_len = sizeof(option_value); + if (getsockopt(rv, SOL_SOCKET, SO_REUSEADDR, (char *)&option_value, + &option_len) == 0) + { + if (option_value == 0) + { + option_value = 1; + option_len = sizeof(option_value); + setsockopt(rv, SOL_SOCKET, SO_REUSEADDR, (char *)&option_value, + option_len); + } + } + + option_len = sizeof(option_value); + + if (getsockopt(rv, SOL_SOCKET, SO_SNDBUF, (char *)&option_value, + &option_len) == 0) + { + if (option_value < (1024 * 32)) + { + option_value = 1024 * 32; + option_len = sizeof(option_value); + setsockopt(rv, SOL_SOCKET, SO_SNDBUF, (char *)&option_value, + option_len); + } + } + + return rv; +} + +/*****************************************************************************/ +static int APP_CC +g_tcp_set_non_blocking(int sck) +{ + unsigned long i; + + i = fcntl(sck, F_GETFL); + i = i | O_NONBLOCK; + fcntl(sck, F_SETFL, i); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +g_tcp_bind(int sck, const char* port) +{ + struct sockaddr_in s; + + memset(&s, 0, sizeof(struct sockaddr_in)); + s.sin_family = AF_INET; + s.sin_port = htons((tui16)atoi(port)); + s.sin_addr.s_addr = INADDR_ANY; + return bind(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in)); +} + +/*****************************************************************************/ +static int APP_CC +g_tcp_listen(int sck) +{ + return listen(sck, 2); +} + +/*****************************************************************************/ +static int APP_CC +g_tcp_select(int sck1, int sck2) +{ + fd_set rfds; + struct timeval time; + int max = 0; + int rv = 0; + + g_memset(&rfds, 0, sizeof(fd_set)); + g_memset(&time, 0, sizeof(struct timeval)); + + time.tv_sec = 0; + time.tv_usec = 0; + FD_ZERO(&rfds); + + if (sck1 > 0) + { + FD_SET(((unsigned int)sck1), &rfds); + } + + if (sck2 > 0) + { + FD_SET(((unsigned int)sck2), &rfds); + } + + max = sck1; + + if (sck2 > max) + { + max = sck2; + } + + rv = select(max + 1, &rfds, 0, 0, &time); + + if (rv > 0) + { + rv = 0; + + if (FD_ISSET(((unsigned int)sck1), &rfds)) + { + rv = rv | 1; + } + + if (FD_ISSET(((unsigned int)sck2), &rfds)) + { + rv = rv | 2; + } + } + else + { + rv = 0; + } + + return rv; +} + +/*****************************************************************************/ +static int APP_CC +g_tcp_recv(int sck, void *ptr, int len, int flags) +{ + return recv(sck, ptr, len, flags); +} + +/*****************************************************************************/ +static void APP_CC +g_tcp_close(int sck) +{ + if (sck == 0) + { + return; + } + close(sck); +} + +/*****************************************************************************/ +static int APP_CC +g_tcp_send(int sck, const void *ptr, int len, int flags) +{ + return send(sck, ptr, len, flags); +} + +/*****************************************************************************/ +void APP_CC +g_sleep(int msecs) +{ + usleep(msecs * 1000); +} + +/*****************************************************************************/ +static int APP_CC +g_tcp_last_error_would_block(int sck) +{ + return (errno == EWOULDBLOCK) || (errno == EAGAIN) || (errno == EINPROGRESS); +} + +/*****************************************************************************/ +static int APP_CC +g_tcp_accept(int sck) +{ + int ret ; + struct sockaddr_in s; + unsigned int i; + + i = sizeof(struct sockaddr_in); + memset(&s, 0, i); + ret = accept(sck, (struct sockaddr *)&s, &i); + return ret ; +} + +/*****************************************************************************/ +static int APP_CC +g_tcp_connect(int sck, const char* address, const char* port) +{ + struct sockaddr_in s; + struct hostent* h; + + g_memset(&s, 0, sizeof(struct sockaddr_in)); + s.sin_family = AF_INET; + s.sin_port = htons((tui16)atoi(port)); + s.sin_addr.s_addr = inet_addr(address); + if (s.sin_addr.s_addr == INADDR_NONE) + { + h = gethostbyname(address); + if (h != 0) + { + if (h->h_name != 0) + { + if (h->h_addr_list != 0) + { + if ((*(h->h_addr_list)) != 0) + { + s.sin_addr.s_addr = *((int*)(*(h->h_addr_list))); + } + } + } + } + } + return connect(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in)); +} + +/*****************************************************************************/ +static int APP_CC +g_tcp_socket_ok(int sck) +{ + int opt; + unsigned int opt_len; + + opt_len = sizeof(opt); + + if (getsockopt(sck, SOL_SOCKET, SO_ERROR, (char *)(&opt), &opt_len) == 0) + { + if (opt == 0) + { + return 1; + } + } + + return 0; +} + +/*****************************************************************************/ +static void APP_CC +g_init(const char *app_name) +{ + setlocale(LC_CTYPE, ""); +} + +/*****************************************************************************/ +static void APP_CC +g_deinit(void) +{ +} + +/*****************************************************************************/ +static int APP_CC +g_tcp_can_send(int sck, int millis) +{ + fd_set wfds; + struct timeval time; + int rv; + + time.tv_sec = millis / 1000; + time.tv_usec = (millis * 1000) % 1000000; + FD_ZERO(&wfds); + + if (sck > 0) + { + FD_SET(((unsigned int)sck), &wfds); + rv = select(sck + 1, 0, &wfds, 0, &time); + + if (rv > 0) + { + return g_tcp_socket_ok(sck); + } + } + + return 0; +} + +/*****************************************************************************/ +static void APP_CC +g_signal_user_interrupt(void (*func)(int)) +{ + signal(SIGINT, func); +} + +/*****************************************************************************/ +static void APP_CC +g_signal_kill(void (*func)(int)) +{ + signal(SIGKILL, func); +} + +/*****************************************************************************/ +static void APP_CC +g_signal_terminate(void (*func)(int)) +{ + signal(SIGTERM, func); +} + +/*****************************************************************************/ +static void APP_CC +g_signal_usr1(void (*func)(int)) +{ + signal(SIGUSR1, func); +} + +/*****************************************************************************/ +static int APP_CC +g_strcasecmp(const char *c1, const char *c2) +{ + return strcasecmp(c1, c2); +} + /*****************************************************************************/ static int main_loop(char *local_port, char *remote_ip, char *remote_port, int hexdump) diff --git a/vrplayer/decoder.cpp b/vrplayer/decoder.cpp index b1741997..10e562e9 100644 --- a/vrplayer/decoder.cpp +++ b/vrplayer/decoder.cpp @@ -13,6 +13,7 @@ Decoder::Decoder(QObject *parent) : *****************************************************************************/ int Decoder::init(QString filename) { + printf("Decoder::init\n"); if (channel) return -1; diff --git a/vrplayer/decoderthread.cpp b/vrplayer/decoderthread.cpp index e31b1aa3..36ba4c85 100644 --- a/vrplayer/decoderthread.cpp +++ b/vrplayer/decoderthread.cpp @@ -1,3 +1,23 @@ + + +// not used + + + + + + + + + + + + + + + + + #include "decoderthread.h" /* @@ -178,7 +198,7 @@ void DecoderThread::videoTimerCallback() } pkt = videoQueue.dequeue(); - delayInMs = (int) ((float) pkt->delay_in_us / 1000.0); + delayInMs = (int) 10; // ((float) pkt->delay_in_us / 1000.0); send_video_pkt(channel, 101, pkt->av_pkt); delete pkt; updateSlider(); diff --git a/vrplayer/demuxmedia.cpp b/vrplayer/demuxmedia.cpp index c6893ceb..a8de41a1 100644 --- a/vrplayer/demuxmedia.cpp +++ b/vrplayer/demuxmedia.cpp @@ -3,26 +3,25 @@ #include "demuxmedia.h" -DemuxMedia::DemuxMedia(QObject *parent, QQueue<MediaPacket *> *audioQueue, - QQueue<MediaPacket *> *videoQueue, void *channel, int stream_id) : - QObject(parent) +DemuxMedia::DemuxMedia(QObject *parent, QQueue<MediaPacket *> *videoQueue, + void *channel, int stream_id) : QObject(parent) { - this->audioQueue = audioQueue; - this->videoQueue = videoQueue; this->channel = channel; this->stream_id = stream_id; - this->threadsStarted = false; this->vcrFlag = 0; + this->elapsedTime = 0; + this->la_seekPos = -1; + this->isStopped = 0; + this->pausedTime = 0; + this->videoQueue = videoQueue; - playAudio = new PlayAudio(NULL, audioQueue, &sendMutex, channel, 101); - playAudioThread = new QThread(this); - connect(playAudioThread, SIGNAL(started()), playAudio, SLOT(play())); - playAudio->moveToThread(playAudioThread); - - playVideo = new PlayVideo(NULL, videoQueue, &sendMutex, channel, 101); + playVideo = new PlayVideo(NULL, videoQueue, &sendMutex, channel, 101, 24); playVideoThread = new QThread(this); connect(playVideoThread, SIGNAL(started()), playVideo, SLOT(play())); playVideo->moveToThread(playVideoThread); + + playVideoThread->start(); + } void DemuxMedia::setVcrOp(int op) @@ -30,12 +29,18 @@ void DemuxMedia::setVcrOp(int op) vcrMutex.lock(); vcrFlag = op; vcrMutex.unlock(); + if (op == VCR_STOP) + { + clear(); + } +} - if (playVideo) - playVideo->setVcrOp(op); - - if (playAudio) - playAudio->setVcrOp(op); +int DemuxMedia::clear() +{ + sendMutex.lock(); + videoQueue->clear(); + sendMutex.unlock(); + return 0; } void DemuxMedia::startDemuxing() @@ -44,9 +49,6 @@ void DemuxMedia::startDemuxing() int is_video_frame; int rv; - if ((audioQueue == NULL) || (videoQueue == NULL)) - return; - while (1) { vcrMutex.lock(); @@ -55,18 +57,40 @@ void DemuxMedia::startDemuxing() case VCR_PLAY: vcrFlag = 0; vcrMutex.unlock(); + if (pausedTime) + { + elapsedTime = av_gettime() - pausedTime; + pausedTime = 0; + } + isStopped = false; continue; break; case VCR_PAUSE: vcrMutex.unlock(); + if (!pausedTime) + { + /* save amount of video played so far */ + pausedTime = av_gettime() - elapsedTime; + } usleep(1000 * 100); + isStopped = false; continue; break; case VCR_STOP: vcrMutex.unlock(); - usleep(1000 * 100); + + if (isStopped) + { + usleep(1000 * 100); + continue; + } + elapsedTime = 0; + pausedTime = 0; + la_seekPos = -1; + xrdpvr_seek_media(0, 0); + isStopped = true; continue; break; @@ -75,14 +99,6 @@ void DemuxMedia::startDemuxing() break; } - if ((audioQueue->count() >= 20) || (videoQueue->count() >= 20)) - { - if (!threadsStarted) - startAudioVideoThreads(); - - usleep(1000 * 20); - } - mediaPkt = new MediaPacket; rv = xrdpvr_get_frame(&mediaPkt->av_pkt, &is_video_frame, @@ -91,31 +107,61 @@ void DemuxMedia::startDemuxing() { /* looks like we reached end of file */ delete mediaPkt; - playVideo->onMediaRestarted(); usleep(1000 * 100); xrdpvr_seek_media(0, 0); + this->elapsedTime = 0; continue; } if (is_video_frame) + { + sendMutex.lock(); +#if 1 videoQueue->enqueue(mediaPkt); +#else + send_video_pkt(channel, stream_id, mediaPkt->av_pkt); + delete mediaPkt; +#endif + sendMutex.unlock(); + } else - audioQueue->enqueue(mediaPkt); + { + int frame; + sendMutex.lock(); + send_audio_pkt(channel, stream_id, mediaPkt->av_pkt); + sendMutex.unlock(); + xrdpvr_read_ack(channel, &frame); + delete mediaPkt; + } + + updateMediaPos(); + if (elapsedTime == 0) + { + elapsedTime = av_gettime(); + } + + /* time elapsed in 1/100th sec units since play started */ + emit onElapsedtime((av_gettime() - elapsedTime) / 10000); + } /* end while (1) */ } -PlayVideo * DemuxMedia::getPlayVideoInstance() +void DemuxMedia::onMediaSeek(int value) { - return this->playVideo; + posMutex.lock(); + la_seekPos = value; + posMutex.unlock(); } -void DemuxMedia::startAudioVideoThreads() +void DemuxMedia::updateMediaPos() { - if (threadsStarted) - return; - - playVideoThread->start(); - playAudioThread->start(); - threadsStarted = true; + posMutex.lock(); + if (la_seekPos >= 0) + { + xrdpvr_seek_media(la_seekPos, 0); + elapsedTime = av_gettime() - la_seekPos * 1000000; + la_seekPos = -1; + } + posMutex.unlock(); } diff --git a/vrplayer/demuxmedia.h b/vrplayer/demuxmedia.h index b83a8857..742ce525 100644 --- a/vrplayer/demuxmedia.h +++ b/vrplayer/demuxmedia.h @@ -37,33 +37,40 @@ class DemuxMedia : public QObject Q_OBJECT public: - explicit DemuxMedia(QObject *parent = 0, QQueue<MediaPacket *> *audioQueue = 0, - QQueue<MediaPacket *> *videoQueue = 0, void *channel = 0, int stream_id = 101); + explicit DemuxMedia(QObject *parent = 0, QQueue<MediaPacket *> *videoQueue = 0, + void *channel = 0, int stream_id = 101); void setVcrOp(int op); + int clear(); public slots: void startDemuxing(); - PlayVideo *getPlayVideoInstance(); + void onMediaSeek(int value); private: - QQueue<MediaPacket *> *audioQueue; + QMutex vcrMutex; + int vcrFlag; + void *channel; + int stream_id; + QMutex sendMutex; + QMutex posMutex; + int64_t elapsedTime; /* elapsed time in usecs since play started */ + int64_t pausedTime; /* time at which stream was paused */ + int64_t la_seekPos; /* locked access; must hold posMutex */ + bool isStopped; + QQueue<MediaPacket *> *videoQueue; - QMutex vcrMutex; - int vcrFlag; - void *channel; PlayVideo *playVideo; QThread *playVideoThread; - PlayAudio *playAudio; - QThread *playAudioThread; - int stream_id; - bool threadsStarted; - QMutex sendMutex; - void startAudioVideoThreads(); + void updateMediaPos(); signals: void onMediaRestarted(); + +signals: + void onElapsedtime(int val); /* in hundredth of a sec */ + }; #endif // DEMUXMEDIA_H diff --git a/vrplayer/dlgabout.ui b/vrplayer/dlgabout.ui index 8b2c38e5..7e40333f 100644 --- a/vrplayer/dlgabout.ui +++ b/vrplayer/dlgabout.ui @@ -23,7 +23,7 @@ </rect> </property> <property name="text"> - <string>VRPlayer v1.2</string> + <string>VRPlayer v1.6</string> </property> </widget> <widget class="QPushButton" name="okButton"> diff --git a/vrplayer/main.cpp b/vrplayer/main.cpp index d951345f..5e4821ab 100644 --- a/vrplayer/main.cpp +++ b/vrplayer/main.cpp @@ -1,11 +1,12 @@ + #include <QtGui/QApplication> #include "mainwindow.h" int main(int argc, char *argv[]) { + QApplication::setGraphicsSystem(QLatin1String("native")); QApplication a(argc, argv); MainWindow w; w.show(); - return a.exec(); } diff --git a/vrplayer/mainwindow.cpp b/vrplayer/mainwindow.cpp index 1782f710..e8884726 100644 --- a/vrplayer/mainwindow.cpp +++ b/vrplayer/mainwindow.cpp @@ -66,8 +66,8 @@ MainWindow::~MainWindow() { delete ui; - if (moveResizeTimer) - delete moveResizeTimer; + //if (moveResizeTimer) + // delete moveResizeTimer; } void MainWindow::closeEvent(QCloseEvent *event) @@ -86,56 +86,56 @@ void MainWindow::closeEvent(QCloseEvent *event) void MainWindow::resizeEvent(QResizeEvent *) { - if (vcrFlag != VCR_PLAY) + //if (vcrFlag != VCR_PLAY) { QRect rect; getVdoGeometry(&rect); interface->sendGeometry(rect); - return; + //return; } - interface->setVcrOp(VCR_PAUSE); - vcrFlag = VCR_PAUSE; - - if (!moveResizeTimer) - { - moveResizeTimer = new QTimer; - connect(moveResizeTimer, SIGNAL(timeout()), - this, SLOT(onMoveCompleted())); - } - lblVideo->setStyleSheet("QLabel { background-color : black; color : blue; }"); - moveResizeTimer->start(1000); + //interface->setVcrOp(VCR_PAUSE); + //vcrFlag = VCR_PAUSE; + + //if (!moveResizeTimer) + //{ + // moveResizeTimer = new QTimer; + // connect(moveResizeTimer, SIGNAL(timeout()), + // this, SLOT(onMoveCompleted())); + //} + //lblVideo->setStyleSheet("QLabel { background-color : black; color : blue; }"); + //moveResizeTimer->start(1000); } void MainWindow::moveEvent(QMoveEvent *) { - if (vcrFlag != VCR_PLAY) + //if (vcrFlag != VCR_PLAY) { QRect rect; getVdoGeometry(&rect); interface->sendGeometry(rect); - return; + //return; } - interface->setVcrOp(VCR_PAUSE); - vcrFlag = VCR_PAUSE; - - if (!moveResizeTimer) - { - moveResizeTimer = new QTimer; - connect(moveResizeTimer, SIGNAL(timeout()), - this, SLOT(onMoveCompleted())); - } - lblVideo->setStyleSheet("QLabel { background-color : black; color : blue; }"); - moveResizeTimer->start(1000); + //interface->setVcrOp(VCR_PAUSE); + //vcrFlag = VCR_PAUSE; + + //if (!moveResizeTimer) + //{ + // moveResizeTimer = new QTimer; + // connect(moveResizeTimer, SIGNAL(timeout()), + // this, SLOT(onMoveCompleted())); + //} + //lblVideo->setStyleSheet("QLabel { background-color : black; color : blue; }"); + //moveResizeTimer->start(1000); } void MainWindow::onVolSliderValueChanged(int value) { int volume; - + volume = (value * 0xffff) / 100; if (interface != 0) { @@ -153,8 +153,8 @@ void MainWindow::setupUI() lblVideo->setMinimumWidth(320); lblVideo->setMinimumHeight(200); QPalette palette = lblVideo->palette(); - palette.setColor(lblVideo->backgroundRole(), Qt::black); - palette.setColor(lblVideo->foregroundRole(), Qt::black); + palette.setColor(lblVideo->backgroundRole(), QColor(0x00, 0x00, 0x01, 0xff)); + palette.setColor(lblVideo->foregroundRole(), QColor(0x00, 0x00, 0x01, 0xff)); lblVideo->setAutoFillBackground(true); lblVideo->setPalette(palette); hboxLayoutTop = new QHBoxLayout; @@ -253,10 +253,17 @@ void MainWindow::openMediaFile() if (filename.length() == 0) { + /* no previous selection - open user's home folder TODO */ // TODO filename = QFileDialog::getOpenFileName(this, "Select Media File", "/"); + //filename = QFileDialog::getOpenFileName(this, "Select Media File", + // QDir::currentPath()); + filename = QFileDialog::getOpenFileName(this, "Select Media File", - QDir::currentPath()); + QDir::currentPath(), + "Media *.mov *.mp4 *.mkv (*.mov *.mp4 *.mkv)"); + + } else { @@ -288,11 +295,9 @@ void MainWindow::getVdoGeometry(QRect *rect) void MainWindow::clearDisplay() { - QPixmap pixmap(100,100); - pixmap.fill(QColor(0x00, 0x00, 0x00)); - QPainter painter(&pixmap); - painter.setBrush(QBrush(Qt::black)); - lblVideo->setPixmap(pixmap); + /* TODO: this needs to be set after video actually stops + * a few frames come after this */ + lblVideo->update(); } /******************************************************************************* @@ -302,13 +307,19 @@ void MainWindow::clearDisplay() void MainWindow::on_actionOpen_Media_File_triggered() { if (vcrFlag != 0) + { onBtnStopClicked(true); + } /* if media was specified on cmd line, use it just once */ if (gotMediaOnCmdline) + { gotMediaOnCmdline = false; + } else + { openMediaFile(); + } if (filename.length() == 0) { @@ -320,17 +331,27 @@ void MainWindow::on_actionOpen_Media_File_triggered() { remoteClientInited = false; interface->deInitRemoteClient(); - interface->initRemoteClient(); + if (interface->initRemoteClient() != 0) + { + QMessageBox::question(this, "vrplayer", "Unsupported codec", + QMessageBox::Ok); + return; + } } else { - interface->initRemoteClient(); + if (interface->initRemoteClient() != 0) + { + QMessageBox::question(this, "vrplayer", "Unsupported codec", + QMessageBox::Ok); + return; + } } - playVideo = interface->getPlayVideoInstance(); - if (playVideo) + demuxMedia = interface->getDemuxMediaInstance(); + if (demuxMedia) { - connect(playVideo, SIGNAL(onElapsedtime(int)), + connect(demuxMedia, SIGNAL(onElapsedtime(int)), this, SLOT(onElapsedTime(int))); } @@ -355,7 +376,7 @@ void MainWindow::onBtnPlayClicked(bool) { if (vcrFlag == 0) { - /* first time play button has been clicked */ + /* first time play button3 has been clicked */ on_actionOpen_Media_File_triggered(); btnPlay->setText("Pause"); vcrFlag = VCR_PLAY; @@ -385,8 +406,8 @@ void MainWindow::onBtnPlayClicked(bool) void MainWindow::onBtnRewindClicked(bool) { - if (playVideo) - playVideo->onMediaSeek(0); + //if (playVideo) + // playVideo->onMediaSeek(0); } void MainWindow::onBtnStopClicked(bool) @@ -400,7 +421,10 @@ void MainWindow::onBtnStopClicked(bool) lblCurrentPos->setText("00:00:00"); /* clear screen by filling it with black */ + usleep(500 * 1000); clearDisplay(); + + btnPlay->setChecked(false); } void MainWindow::onMediaDurationInSeconds(int duration) @@ -479,8 +503,10 @@ void MainWindow::onSliderValueChanged(int value) if (acceptSliderMove) { acceptSliderMove = false; - if (playVideo) - playVideo->onMediaSeek(value / 100); + if (demuxMedia != NULL) + { + demuxMedia->onMediaSeek(value / 100); + } } } @@ -503,6 +529,7 @@ void MainWindow::onSliderActionTriggered(int action) } } +// not called void MainWindow::onMoveCompleted() { QRect rect; @@ -512,7 +539,7 @@ void MainWindow::onMoveCompleted() interface->setVcrOp(VCR_PLAY); vcrFlag = VCR_PLAY; - moveResizeTimer->stop(); + //moveResizeTimer->stop(); } void MainWindow::on_actionAbout_triggered() diff --git a/vrplayer/mainwindow.h b/vrplayer/mainwindow.h index 4fef0d60..f0383098 100644 --- a/vrplayer/mainwindow.h +++ b/vrplayer/mainwindow.h @@ -111,7 +111,8 @@ private: /* private stuff */ OurInterface *interface; - PlayVideo *playVideo; + //PlayVideo *playVideo; + DemuxMedia *demuxMedia; QString filename; bool oneTimeInitSuccess; bool remoteClientInited; diff --git a/vrplayer/ourinterface.cpp b/vrplayer/ourinterface.cpp index cee66691..261ba04d 100644 --- a/vrplayer/ourinterface.cpp +++ b/vrplayer/ourinterface.cpp @@ -1,3 +1,4 @@ + #include "ourinterface.h" OurInterface::OurInterface(QObject *parent) : @@ -31,7 +32,8 @@ void OurInterface::oneTimeDeinit() closeVirtualChannel(); } -void OurInterface::initRemoteClient() +/* returns error */ +int OurInterface::initRemoteClient() { int64_t start_time; int64_t duration; @@ -39,18 +41,21 @@ void OurInterface::initRemoteClient() //elapsedTime = 0; if (sendMetadataFile()) - return; + return 1; if (sendVideoFormat()) - return; + return 1; if (sendAudioFormat()) - return; + return 1; if (sendGeometry(savedGeometry)) - return; + return 1; - xrdpvr_play_media(channel, 101, filename.toAscii().data()); + if (xrdpvr_play_media(channel, 101, filename.toAscii().data()) != 0) + { + return 1; + } xrdpvr_get_media_duration(&start_time, &duration); //qDebug() << "ourInterface:initRemoteClient: emit onMediaDurationInSecs: dur=" << duration; @@ -59,12 +64,13 @@ void OurInterface::initRemoteClient() /* LK_TODO this needs to be undone in deinitRemoteClient() */ if (!demuxMedia) { - demuxMedia = new DemuxMedia(NULL, &audioQueue, &videoQueue, channel, stream_id); + demuxMedia = new DemuxMedia(NULL, &videoQueue, channel, stream_id); demuxMediaThread = new QThread(this); connect(demuxMediaThread, SIGNAL(started()), demuxMedia, SLOT(startDemuxing())); demuxMedia->moveToThread(demuxMediaThread); - playVideo = demuxMedia->getPlayVideoInstance(); + //playVideo = demuxMedia->getPlayVideoInstance(); } + return 0; } void OurInterface::deInitRemoteClient() @@ -84,6 +90,7 @@ int OurInterface::openVirtualChannel() if (channel) return -1; + printf("OurInterface::openVirtualChannel:\n"); /* open a virtual channel and connect to remote client */ channel = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, "xrdpvr", 0); if (channel == NULL) @@ -116,37 +123,46 @@ int OurInterface::closeVirtualChannel() ******************************************************************************/ int OurInterface::sendMetadataFile() { + + if (xrdpvr_init_player(channel, 101, filename.toAscii().data())) + { + fprintf(stderr, "failed to initialize the player\n"); + return -1; + } +#if 0 if (xrdpvr_create_metadata_file(channel, filename.toAscii().data())) { emit on_ErrorMsg("I/O Error", "An error occurred while sending data to remote client"); return -1; } - +#endif return 0; } int OurInterface::sendVideoFormat() { +#if 0 if (xrdpvr_set_video_format(channel, stream_id)) { emit on_ErrorMsg("I/O Error", "Error sending video format to remote client"); return -1; } - +#endif return 0; } int OurInterface::sendAudioFormat() { +#if 0 if (xrdpvr_set_audio_format(channel, stream_id)) { emit on_ErrorMsg("I/O Error", "Error sending audio format to remote client"); return -1; } - +#endif return 0; } @@ -205,11 +221,17 @@ void OurInterface::playMedia() demuxMediaThread->start(); } -PlayVideo * OurInterface::getPlayVideoInstance() +//PlayVideo * OurInterface::getPlayVideoInstance() +//{ +// return this->playVideo; +//} + +DemuxMedia * OurInterface::getDemuxMediaInstance() { - return this->playVideo; + return this->demuxMedia; } + void OurInterface::setVcrOp(int op) { if (demuxMedia) diff --git a/vrplayer/ourinterface.h b/vrplayer/ourinterface.h index 86352001..be354025 100644 --- a/vrplayer/ourinterface.h +++ b/vrplayer/ourinterface.h @@ -31,16 +31,17 @@ class OurInterface : public QObject public: explicit OurInterface(QObject *parent = 0); - + /* public methods */ int oneTimeInit(); void oneTimeDeinit(); - void initRemoteClient(); + int initRemoteClient(); void deInitRemoteClient(); int sendGeometry(QRect rect); void setFilename(QString filename); void playMedia(); - PlayVideo *getPlayVideoInstance(); + //PlayVideo *getPlayVideoInstance(); + DemuxMedia *getDemuxMediaInstance(); void setVcrOp(int op); int setVolume(int volume); @@ -54,12 +55,12 @@ signals: private: /* private stuff */ - QQueue<MediaPacket *> audioQueue; + QQueue<MediaPacket *> videoQueue; DemuxMedia *demuxMedia; QThread *demuxMediaThread; - PlayVideo *playVideo; + //PlayVideo *playVideo; QString filename; void *channel; int stream_id; diff --git a/vrplayer/playaudio.cpp b/vrplayer/playaudio.cpp index fee98f9d..042b7e26 100644 --- a/vrplayer/playaudio.cpp +++ b/vrplayer/playaudio.cpp @@ -54,13 +54,15 @@ void PlayAudio::play() label1: + printf("audio\n"); if (audioQueue->isEmpty()) { qDebug() << "PlayAudio::play: GOT EMPTY"; - usleep(1000 * 100); + usleep(1000 * 10); continue; } + printf(""); pkt = audioQueue->dequeue(); sendMutex->lock(); send_audio_pkt(channel, stream_id, pkt->av_pkt); diff --git a/vrplayer/playvideo.cpp b/vrplayer/playvideo.cpp index 24ef492d..71fbcda9 100644 --- a/vrplayer/playvideo.cpp +++ b/vrplayer/playvideo.cpp @@ -1,5 +1,6 @@ #include <unistd.h> +#include <sys/time.h> #include "playvideo.h" #include <QDebug> @@ -8,179 +9,58 @@ PlayVideo::PlayVideo(QObject *parent, QQueue<MediaPacket *> *videoQueue, QMutex *sendMutex, void *channel, - int stream_id) : + int stream_id, int fps) : QObject(parent) { this->videoQueue = videoQueue; this->channel = channel; this->sendMutex = sendMutex; this->stream_id = stream_id; - elapsedTime = 0; - pausedTime = 0; - la_seekPos = -1; - vcrFlag = 0; - isStopped = false; + this->fps = fps; +} + +/** + ******************************************************************************/ +static int +get_mstime(void) +{ + struct timeval tp; + + gettimeofday(&tp, 0); + return (tp.tv_sec * 1000) + (tp.tv_usec / 1000); } void PlayVideo::play() { MediaPacket *pkt; - int usl; + int now_time; + int sleep_time; + int last_display_time; + last_display_time = 0; while (1) { - vcrMutex.lock(); - switch (vcrFlag) - { - case VCR_PLAY: - vcrFlag = 0; - vcrMutex.unlock(); - if (pausedTime) - { - elapsedTime = av_gettime() - pausedTime; - pausedTime = 0; - } - isStopped = false; - continue; - break; - - case VCR_PAUSE: - vcrMutex.unlock(); - if (!pausedTime) - { - /* save amount of video played so far */ - pausedTime = av_gettime() - elapsedTime; - } - usleep(1000 * 100); - isStopped = false; - continue; - break; - - case VCR_STOP: - vcrMutex.unlock(); - if (isStopped) - { - usleep(1000 * 100); - continue; - } - clearVideoQ(); - elapsedTime = 0; - pausedTime = 0; - la_seekPos = -1; - xrdpvr_seek_media(0, 0); - isStopped = true; - continue; - break; - - default: - vcrMutex.unlock(); - goto label1; - break; - } - -label1: - + sendMutex->lock(); if (videoQueue->isEmpty()) { + sendMutex->unlock(); + usleep(10 * 1000); continue; } pkt = videoQueue->dequeue(); - sendMutex->lock(); send_video_pkt(channel, stream_id, pkt->av_pkt); sendMutex->unlock(); - usl = pkt->delay_in_us; - if (usl < 0) + now_time = get_mstime(); + sleep_time = now_time - last_display_time; + if (sleep_time > (1000 / fps)) { - usl = 0; + sleep_time = (1000 / fps); } - if (usl > 100 * 1000) + if (sleep_time > 0) { - usl = 100 * 1000; + usleep(sleep_time * 1000); } - usleep(usl); - delete pkt; - updateMediaPos(); - if (elapsedTime == 0) - elapsedTime = av_gettime(); - - /* time elapsed in 1/100th sec units since play started */ - emit onElapsedtime((av_gettime() - elapsedTime) / 10000); - } -} - -void PlayVideo::onMediaRestarted() -{ - elapsedTime = av_gettime(); -} - -void PlayVideo::onMediaSeek(int value) -{ - posMutex.lock(); - la_seekPos = value; - posMutex.unlock(); -} - -void PlayVideo::updateMediaPos() -{ -#if 0 - if (elapsedTime == 0) - elapsedTime = av_gettime(); - - /* time elapsed in 1/100th sec units since play started */ - emit onElapsedtime((av_gettime() - elapsedTime) / 10000); -#endif - - posMutex.lock(); - if (la_seekPos >= 0) - { - //qDebug() << "seeking to" << la_seekPos; - xrdpvr_seek_media(la_seekPos, 0); - elapsedTime = av_gettime() - la_seekPos * 1000000; - la_seekPos = -1; - } - posMutex.unlock(); -} - -void PlayVideo::setVcrOp(int op) -{ - vcrMutex.lock(); - this->vcrFlag = op; - vcrMutex.unlock(); -} - -void PlayVideo::clearVideoQ() -{ - MediaPacket *pkt; - - while (!videoQueue->isEmpty()) - { - pkt = videoQueue->dequeue(); - av_free_packet((AVPacket *) pkt->av_pkt); + last_display_time = now_time; delete pkt; } } - -#if 0 -void DecoderThread::updateSlider() -{ - if (elapsedTime == 0) - elapsedTime = av_gettime(); - - /* time elapsed in 1/100th sec units since play started */ - emit onElapsedtime((av_gettime() - elapsedTime) / 10000); - - mutex.lock(); - if (la_seekPos >= 0) - { - //qDebug() << "seeking to" << la_seekPos; - //audioTimer->stop(); - //videoTimer->stop(); - xrdpvr_seek_media(la_seekPos, 0); - elapsedTime = av_gettime() - la_seekPos * 1000000; - //audioTimer->start(10); - //videoTimer->start(10); - la_seekPos = -1; - } - mutex.unlock(); -} -#endif diff --git a/vrplayer/playvideo.h b/vrplayer/playvideo.h index 2ae183b5..e2300f24 100644 --- a/vrplayer/playvideo.h +++ b/vrplayer/playvideo.h @@ -39,34 +39,36 @@ public: QQueue<MediaPacket *> *videoQueue = 0, QMutex *sendMutex = 0, void *channel = 0, - int stream_id = 101); + int stream_id = 101, + int fps = 24); - void onMediaSeek(int value); - void setVcrOp(int op); - void onMediaRestarted(); + //void onMediaSeek(int value); + //void setVcrOp(int op); + //void onMediaRestarted(); public slots: void play(); -signals: - void onElapsedtime(int val); /* in hundredth of a sec */ +//signals: +// void onElapsedtime(int val); /* in hundredth of a sec */ private: QQueue<MediaPacket *> *videoQueue; - int vcrFlag; - QMutex vcrMutex; +// int vcrFlag; +// QMutex vcrMutex; QMutex *sendMutex; - QMutex posMutex; - int64_t la_seekPos; /* locked access; must hold posMutex */ +// QMutex posMutex; +// int64_t la_seekPos; /* locked access; must hold posMutex */ void *channel; int stream_id; - int64_t elapsedTime; /* elapsed time in usecs since play started */ - int64_t pausedTime; /* time at which stream was paused */ - bool isStopped; + int fps; +// int64_t elapsedTime; /* elapsed time in usecs since play started */ +// int64_t pausedTime; /* time at which stream was paused */ +// bool isStopped; - void updateMediaPos(); - void clearVideoQ(); +// void updateMediaPos(); +// void clearVideoQ(); }; #endif // PLAYVIDEO_H diff --git a/xorg/X11R7.6/rdp/Makefile b/xorg/X11R7.6/rdp/Makefile index 3b84c43c..c18e01b6 100644 --- a/xorg/X11R7.6/rdp/Makefile +++ b/xorg/X11R7.6/rdp/Makefile @@ -14,6 +14,7 @@ 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 rdpglyph.o rdpComposite.o \ +rdpkeyboard.o rdpkeyboardevdev.o rdpkeyboardbase.o \ miinitext.o \ fbcmap_mi.o diff --git a/xorg/X11R7.6/rdp/rdp.h b/xorg/X11R7.6/rdp/rdp.h index 32d05d6a..7bc2eb6c 100644 --- a/xorg/X11R7.6/rdp/rdp.h +++ b/xorg/X11R7.6/rdp/rdp.h @@ -368,6 +368,8 @@ void RegionAroundSegs(RegionPtr reg, xSegment* segs, int nseg); int get_crc(char* data, int data_bytes); +int +get_mstime(void); /* rdpdraw.c */ Bool @@ -505,6 +507,8 @@ void KbdAddEvent(int down, int param1, int param2, int param3, int param4); void KbdSync(int param1); +int +rdpLoadLayout(int keylayout); /* rdpup.c */ int diff --git a/xorg/X11R7.6/rdp/rdpinput.c b/xorg/X11R7.6/rdp/rdpinput.c index c8739ba0..7fb20379 100644 --- a/xorg/X11R7.6/rdp/rdpinput.c +++ b/xorg/X11R7.6/rdp/rdpinput.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -32,17 +32,17 @@ keyboard and mouse stuff /* tab notes */ /* mstsc send tab up without a tab down to mark the mstsc has gained focus - this should have sure control alt and shift are all up + this should make sure control alt and shift are all up rdesktop does not do this */ /* this should be fixed in rdesktop */ #include "rdp.h" +#include <sys/types.h> +#include <sys/wait.h> -#if 1 -#define DEBUG_OUT_INPUT(arg) -#else -#define DEBUG_OUT_INPUT(arg) ErrorF arg -#endif +#include "rdpkeyboard.h" +#include "rdpkeyboardbase.h" +#include "rdpkeyboardevdev.h" #define LOG_LEVEL 1 #define LLOG(_level, _args) \ @@ -54,47 +54,21 @@ extern ScreenPtr g_pScreen; /* in rdpmain.c */ extern DeviceIntPtr g_pointer; /* in rdpmain.c */ extern DeviceIntPtr g_keyboard; /* in rdpmain.c */ extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ +extern int g_shift_down; /* in rdpmain.c */ +extern int g_alt_down; /* in rdpmain.c */ +extern int g_ctrl_down; /* in rdpmain.c */ static int g_old_button_mask = 0; -static int g_pause_spe = 0; -static int g_ctrl_down = 0; -static int g_alt_down = 0; -static int g_shift_down = 0; -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 -#define NO_OF_KEYS ((MAX_KEY_CODE - MIN_KEY_CODE) + 1) -#define GLYPHS_PER_KEY 2 -/* control */ -#define CONTROL_L_KEY_CODE 37 -#define CONTROL_R_KEY_CODE 109 -/* shift */ -#define SHIFT_L_KEY_CODE 50 -#define SHIFT_R_KEY_CODE 62 -/* win keys */ -#define SUPER_L_KEY_CODE 115 -#define SUPER_R_KEY_CODE 116 -/* alt */ -#define ALT_L_KEY_CODE 64 -#define ALT_R_KEY_CODE 113 -/* caps lock */ -#define CAPS_LOCK_KEY_CODE 66 -/* num lock */ -#define NUM_LOCK_KEY_CODE 77 - -#define N_PREDEFINED_KEYS \ - (sizeof(g_kbdMap) / (sizeof(KeySym) * GLYPHS_PER_KEY)) +static int g_use_evdev = 1; /* Copied from Xvnc/lib/font/util/utilbitmap.c */ static unsigned char g_reverse_byte[0x100] = @@ -133,205 +107,41 @@ static unsigned char g_reverse_byte[0x100] = 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff }; -static KeySym g_kbdMap[] = -{ - NoSymbol, NoSymbol, /* 8 */ - XK_Escape, NoSymbol, /* 9 */ - XK_1, XK_exclam, /* 10 */ - XK_2, XK_at, - XK_3, XK_numbersign, - XK_4, XK_dollar, - XK_5, XK_percent, - XK_6, XK_asciicircum, - XK_7, XK_ampersand, - XK_8, XK_asterisk, - XK_9, XK_parenleft, - XK_0, XK_parenright, - XK_minus, XK_underscore, /* 20 */ - XK_equal, XK_plus, - XK_BackSpace, NoSymbol, - XK_Tab, XK_ISO_Left_Tab, - XK_Q, NoSymbol, - XK_W, NoSymbol, - XK_E, NoSymbol, - XK_R, NoSymbol, - XK_T, NoSymbol, - XK_Y, NoSymbol, - XK_U, NoSymbol, /* 30 */ - XK_I, NoSymbol, - XK_O, NoSymbol, - XK_P, NoSymbol, - XK_bracketleft, XK_braceleft, - XK_bracketright, XK_braceright, - XK_Return, NoSymbol, - XK_Control_L, NoSymbol, - XK_A, NoSymbol, - XK_S, NoSymbol, - XK_D, NoSymbol, /* 40 */ - XK_F, NoSymbol, - XK_G, NoSymbol, - XK_H, NoSymbol, - XK_J, NoSymbol, - XK_K, NoSymbol, - XK_L, NoSymbol, - XK_semicolon, XK_colon, - XK_apostrophe, XK_quotedbl, - XK_grave, XK_asciitilde, - XK_Shift_L, NoSymbol, /* 50 */ - XK_backslash, XK_bar, - XK_Z, NoSymbol, - XK_X, NoSymbol, - XK_C, NoSymbol, - XK_V, NoSymbol, - XK_B, NoSymbol, - XK_N, NoSymbol, - XK_M, NoSymbol, - XK_comma, XK_less, - XK_period, XK_greater, /* 60 */ - XK_slash, XK_question, - XK_Shift_R, NoSymbol, - XK_KP_Multiply, NoSymbol, - XK_Alt_L, NoSymbol, - XK_space, NoSymbol, - XK_Caps_Lock, NoSymbol, - XK_F1, NoSymbol, - XK_F2, NoSymbol, - XK_F3, NoSymbol, - XK_F4, NoSymbol, /* 70 */ - XK_F5, NoSymbol, - XK_F6, NoSymbol, - XK_F7, NoSymbol, - XK_F8, NoSymbol, - XK_F9, NoSymbol, - XK_F10, NoSymbol, - XK_Num_Lock, NoSymbol, - XK_Scroll_Lock, NoSymbol, - XK_KP_Home, XK_KP_7, - XK_KP_Up, XK_KP_8, /* 80 */ - XK_KP_Prior, XK_KP_9, - XK_KP_Subtract, NoSymbol, - XK_KP_Left, XK_KP_4, - XK_KP_Begin, XK_KP_5, - XK_KP_Right, XK_KP_6, - XK_KP_Add, NoSymbol, - XK_KP_End, XK_KP_1, - XK_KP_Down, XK_KP_2, - XK_KP_Next, XK_KP_3, - XK_KP_Insert, XK_KP_0, /* 90 */ - XK_KP_Delete, XK_KP_Decimal, - NoSymbol, NoSymbol, - NoSymbol, NoSymbol, - NoSymbol, NoSymbol, - XK_F11, NoSymbol, - XK_F12, NoSymbol, - XK_Home, NoSymbol, - XK_Up, NoSymbol, - XK_Prior, NoSymbol, - XK_Left, NoSymbol, /* 100 */ - XK_Print, NoSymbol, - XK_Right, NoSymbol, - XK_End, NoSymbol, - XK_Down, NoSymbol, - XK_Next, NoSymbol, - XK_Insert, NoSymbol, - XK_Delete, NoSymbol, - XK_KP_Enter, NoSymbol, - XK_Control_R, NoSymbol, - XK_Pause, NoSymbol, /* 110 */ - XK_Print, NoSymbol, - XK_KP_Divide, NoSymbol, - XK_Alt_R, NoSymbol, - NoSymbol, NoSymbol, - XK_Super_L, NoSymbol, - XK_Super_R, NoSymbol, - XK_Menu, NoSymbol, - NoSymbol, NoSymbol, - NoSymbol, NoSymbol, - NoSymbol, NoSymbol, /* 120 */ - NoSymbol, NoSymbol -}; - #if 0 /******************************************************************************/ static void rdpSendBell(void) { - DEBUG_OUT_INPUT(("rdpSendBell\n")); + LLOGLN(10, ("rdpSendBell:")); } #endif /******************************************************************************/ void -KbdDeviceInit(DeviceIntPtr pDevice, KeySymsPtr pKeySyms, CARD8 *pModMap) -{ - int i; - - DEBUG_OUT_INPUT(("KbdDeviceInit\n")); - - for (i = 0; i < MAP_LENGTH; i++) - { - pModMap[i] = NoSymbol; - } - - pModMap[SHIFT_L_KEY_CODE] = ShiftMask; - pModMap[SHIFT_R_KEY_CODE] = ShiftMask; - pModMap[CAPS_LOCK_KEY_CODE] = LockMask; - pModMap[CONTROL_L_KEY_CODE] = ControlMask; - pModMap[CONTROL_R_KEY_CODE] = ControlMask; - pModMap[ALT_L_KEY_CODE] = Mod1Mask; - pModMap[ALT_R_KEY_CODE] = Mod1Mask; - pModMap[NUM_LOCK_KEY_CODE] = Mod2Mask; - pModMap[SUPER_L_KEY_CODE] = Mod4Mask; - pModMap[SUPER_R_KEY_CODE] = Mod4Mask; - pKeySyms->minKeyCode = MIN_KEY_CODE; - pKeySyms->maxKeyCode = MAX_KEY_CODE; - pKeySyms->mapWidth = GLYPHS_PER_KEY; - i = sizeof(KeySym) * MAP_LENGTH * GLYPHS_PER_KEY; - pKeySyms->map = (KeySym *)g_malloc(i, 1); - - if (pKeySyms->map == 0) - { - rdpLog("KbdDeviceInit g_malloc failed\n"); - exit(1); - } - - for (i = 0; i < MAP_LENGTH * GLYPHS_PER_KEY; i++) - { - pKeySyms->map[i] = NoSymbol; - } - - for (i = 0; i < N_PREDEFINED_KEYS * GLYPHS_PER_KEY; i++) - { - pKeySyms->map[i] = g_kbdMap[i]; - } -} - -/******************************************************************************/ -void KbdDeviceOn(void) { - DEBUG_OUT_INPUT(("KbdDeviceOn\n")); + LLOGLN(10, ("KbdDeviceOn:")); } /******************************************************************************/ void KbdDeviceOff(void) { - DEBUG_OUT_INPUT(("KbdDeviceOff\n")); + LLOGLN(10, ("KbdDeviceOff:")); } /******************************************************************************/ void rdpBell(int volume, DeviceIntPtr pDev, pointer ctrl, int cls) { - ErrorF("rdpBell:\n"); + LLOGLN(0, ("rdpBell:")); } /******************************************************************************/ static CARD32 rdpInDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg) { - //ErrorF("rdpInDeferredUpdateCallback:\n"); + LLOGLN(10, ("rdpInDeferredUpdateCallback:")); /* our keyboard device */ XkbSetRepeatKeys(g_keyboard, -1, AutoRepeatModeOff); @@ -347,7 +157,7 @@ rdpChangeKeyboardControl(DeviceIntPtr pDev, KeybdCtrl *ctrl) { XkbControlsPtr ctrls; - ErrorF("rdpChangeKeyboardControl:\n"); + LLOGLN(0, ("rdpChangeKeyboardControl:")); ctrls = 0; if (pDev != 0) { @@ -369,62 +179,253 @@ rdpChangeKeyboardControl(DeviceIntPtr pDev, KeybdCtrl *ctrl) { if (ctrls->enabled_ctrls & XkbRepeatKeysMask) { - //ErrorF("rdpChangeKeyboardControl: autoRepeat on\n"); + LLOGLN(10, ("rdpChangeKeyboardControl: autoRepeat on")); /* 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);\ + g_kbtimer = TimerSet(g_kbtimer, 0, 100, + rdpInDeferredUpdateCallback, 0); } else { - //ErrorF("rdpChangeKeyboardControl: autoRepeat off\n"); + LLOGLN(10, ("rdpChangeKeyboardControl: autoRepeat off")); + } + } +} + +/******************************************************************************/ +/* +0x00000401 Arabic (101) +0x00000402 Bulgarian +0x00000404 Chinese (Traditional) - US Keyboard +0x00000405 Czech +0x00000406 Danish +0x00000407 German +0x00000408 Greek +0x00000409 US +0x0000040A Spanish +0x0000040B Finnish +0x0000040C French +0x0000040D Hebrew +0x0000040E Hungarian +0x0000040F Icelandic +0x00000410 Italian +0x00000411 Japanese +0x00000412 Korean +0x00000413 Dutch +0x00000414 Norwegian +0x00000415 Polish (Programmers) +0x00000416 Portuguese (Brazilian ABNT) +0x00000418 Romanian +0x00000419 Russian +0x0000041A Croatian +0x0000041B Slovak +0x0000041C Albanian +0x0000041D Swedish +0x0000041E Thai Kedmanee +0x0000041F Turkish Q +0x00000420 Urdu +0x00000422 Ukrainian +0x00000423 Belarusian +0x00000424 Slovenian +0x00000425 Estonian +0x00000426 Latvian +0x00000427 Lithuanian IBM +0x00000429 Farsi +0x0000042A Vietnamese +0x0000042B Armenian Eastern +0x0000042C Azeri Latin +0x0000042F FYRO Macedonian +0x00000437 Georgian +0x00000438 Faeroese +0x00000439 Devanagari - INSCRIPT +0x0000043A Maltese 47-key +0x0000043B Norwegian with Sami +0x0000043F Kazakh +0x00000440 Kyrgyz Cyrillic +0x00000444 Tatar +0x00000445 Bengali +0x00000446 Punjabi +0x00000447 Gujarati +0x00000449 Tamil +0x0000044A Telugu +0x0000044B Kannada +0x0000044C Malayalam +0x0000044E Marathi +0x00000450 Mongolian Cyrillic +0x00000452 United Kingdom Extended +0x0000045A Syriac +0x00000461 Nepali +0x00000463 Pashto +0x00000465 Divehi Phonetic +0x0000046E Luxembourgish +0x00000481 Maori +0x00000804 Chinese (Simplified) - US Keyboard +0x00000807 Swiss German +0x00000809 United Kingdom +0x0000080A Latin American +0x0000080C Belgian French +0x00000813 Belgian (Period) +0x00000816 Portuguese +0x0000081A Serbian (Latin) +0x0000082C Azeri Cyrillic +0x0000083B Swedish with Sami +0x00000843 Uzbek Cyrillic +0x0000085D Inuktitut Latin +0x00000C0C Canadian French (legacy) +0x00000C1A Serbian (Cyrillic) +0x00001009 Canadian French +0x0000100C Swiss French +0x0000141A Bosnian +0x00001809 Irish +0x0000201A Bosnian Cyrillic +*/ + +/******************************************************************************/ +int +rdpLoadLayout(int keylayout) +{ + XkbRMLVOSet set; + XkbSrvInfoPtr xkbi; + XkbDescPtr xkb; + KeySymsPtr keySyms; + DeviceIntPtr pDev; + KeyCode first_key; + CARD8 num_keys; + + LLOGLN(0, ("rdpLoadLayout: keylayout 0x%8.8x display %s", + keylayout, display)); + memset(&set, 0, sizeof(set)); + if (g_use_evdev) + { + set.rules = "evdev"; + } + else + { + set.rules = "base"; + } + set.model = "pc104"; + set.layout = "us"; + switch (keylayout) + { + case 0x00000407: /* German */ + set.layout = "de"; + break; + case 0x00000409: /* US */ + set.layout = "us"; + break; + case 0x0000040C: /* French */ + set.layout = "fr"; + break; + case 0x00000410: /* Italian */ + set.layout = "it"; + break; + case 0x00000416: /* Portuguese (Brazilian ABNT) */ + set.model = "abnt2"; + set.layout = "br"; + break; + case 0x00000419: /* Russian */ + set.layout = "ru"; + break; + case 0x0000041D: /* Swedish */ + set.layout = "se"; + break; + case 0x00000816: /* Portuguese */ + set.layout = "pt"; + break; + default: + LLOGLN(0, ("rdpLoadLayout: unknown keylayout 0x%8.8x", keylayout)); + break; + } + set.variant = ""; + set.options = ""; + + /* free some stuff so we can call InitKeyboardDeviceStruct again */ + xkbi = g_keyboard->key->xkbInfo; + xkb = xkbi->desc; + XkbFreeKeyboard(xkb, 0, TRUE); + free(xkbi); + g_keyboard->key->xkbInfo = NULL; + free(g_keyboard->kbdfeed); + g_keyboard->kbdfeed = NULL; + free(g_keyboard->key); + g_keyboard->key = NULL; + + /* init keyboard and reload the map */ + if (!InitKeyboardDeviceStruct(g_keyboard, &set, rdpBell, + rdpChangeKeyboardControl)) + { + LLOGLN(0, ("rdpLoadLayout: InitKeyboardDeviceStruct failed")); + } + + /* notify the X11 clients eg. X_ChangeKeyboardMapping */ + keySyms = XkbGetCoreMap(g_keyboard); + first_key = keySyms->minKeyCode; + num_keys = (keySyms->maxKeyCode - keySyms->minKeyCode) + 1; + XkbApplyMappingChange(g_keyboard, keySyms, first_key, num_keys, + NULL, serverClient); + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) + { + XkbApplyMappingChange(pDev, keySyms, first_key, num_keys, + NULL, serverClient); } } + + return 0; } /******************************************************************************/ int rdpKeybdProc(DeviceIntPtr pDevice, int onoff) { - KeySymsRec keySyms; - CARD8 modMap[MAP_LENGTH]; DevicePtr pDev; XkbRMLVOSet set; + int ok; - DEBUG_OUT_INPUT(("rdpKeybdProc\n")); + LLOGLN(10, ("rdpKeybdProc:")); pDev = (DevicePtr)pDevice; switch (onoff) { case DEVICE_INIT: - KbdDeviceInit(pDevice, &keySyms, modMap); + LLOGLN(10, ("rdpKeybdProc: DEVICE_INIT")); memset(&set, 0, sizeof(set)); - set.rules = "base"; + if (g_use_evdev) + { + set.rules = "evdev"; + } + else + { + set.rules = "base"; + } set.model = "pc104"; set.layout = "us"; set.variant = ""; set.options = ""; - InitKeyboardDeviceStruct(pDevice, &set, rdpBell, - rdpChangeKeyboardControl); - //XkbDDXChangeControls(pDevice, 0, 0); + ok = InitKeyboardDeviceStruct(pDevice, &set, rdpBell, + rdpChangeKeyboardControl); + LLOGLN(10, ("rdpKeybdProc: InitKeyboardDeviceStruct %d", ok)); break; case DEVICE_ON: + LLOGLN(10, ("rdpKeybdProc: DEVICE_ON")); pDev->on = 1; KbdDeviceOn(); break; case DEVICE_OFF: + LLOGLN(10, ("rdpKeybdProc: DEVICE_OFF")); pDev->on = 0; KbdDeviceOff(); break; case DEVICE_CLOSE: - + LLOGLN(10, ("rdpKeybdProc: DEVICE_CLOSE")); if (pDev->on) { + pDev->on = 0; KbdDeviceOff(); } - break; } - return Success; } @@ -432,35 +433,35 @@ rdpKeybdProc(DeviceIntPtr pDevice, int onoff) void PtrDeviceControl(DeviceIntPtr dev, PtrCtrl *ctrl) { - DEBUG_OUT_INPUT(("PtrDeviceControl\n")); + LLOGLN(10, ("PtrDeviceControl:")); } /******************************************************************************/ void PtrDeviceInit(void) { - DEBUG_OUT_INPUT(("PtrDeviceInit\n")); + LLOGLN(10, ("PtrDeviceInit:")); } /******************************************************************************/ void PtrDeviceOn(DeviceIntPtr pDev) { - DEBUG_OUT_INPUT(("PtrDeviceOn\n")); + LLOGLN(10, ("PtrDeviceOn:")); } /******************************************************************************/ void PtrDeviceOff(void) { - DEBUG_OUT_INPUT(("PtrDeviceOff\n")); + LLOGLN(10, ("PtrDeviceOff:")); } /******************************************************************************/ static void rdpMouseCtrl(DeviceIntPtr pDevice, PtrCtrl *pCtrl) { - ErrorF("rdpMouseCtrl:\n"); + LLOGLN(0, ("rdpMouseCtrl:")); } /******************************************************************************/ @@ -472,7 +473,7 @@ rdpMouseProc(DeviceIntPtr pDevice, int onoff) Atom btn_labels[8]; Atom axes_labels[2]; - DEBUG_OUT_INPUT(("rdpMouseProc\n")); + LLOGLN(10, ("rdpMouseProc:")); pDev = (DevicePtr)pDevice; switch (onoff) @@ -528,7 +529,7 @@ rdpMouseProc(DeviceIntPtr pDevice, int onoff) Bool rdpCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y) { - DEBUG_OUT_INPUT(("rdpCursorOffScreen\n")); + LLOGLN(10, ("rdpCursorOffScreen:")); return 0; } @@ -536,14 +537,14 @@ rdpCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y) void rdpCrossScreen(ScreenPtr pScreen, Bool entering) { - DEBUG_OUT_INPUT(("rdpCrossScreen\n")); + LLOGLN(10, ("rdpCrossScreen:")); } /******************************************************************************/ void rdpPointerWarpCursor(DeviceIntPtr pDev, ScreenPtr pScr, int x, int y) { - ErrorF("rdpPointerWarpCursor:\n"); + LLOGLN(0, ("rdpPointerWarpCursor:")); miPointerWarpCursor(pDev, pScr, x, y); } @@ -551,21 +552,21 @@ rdpPointerWarpCursor(DeviceIntPtr pDev, ScreenPtr pScr, int x, int y) void rdpPointerEnqueueEvent(DeviceIntPtr pDev, InternalEvent *event) { - ErrorF("rdpPointerEnqueueEvent:\n"); + LLOGLN(0, ("rdpPointerEnqueueEvent:")); } /******************************************************************************/ void rdpPointerNewEventScreen(DeviceIntPtr pDev, ScreenPtr pScr, Bool fromDIX) { - ErrorF("rdpPointerNewEventScreen:\n"); + LLOGLN(0, ("rdpPointerNewEventScreen:")); } /******************************************************************************/ Bool rdpSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScr, CursorPtr pCurs) { - DEBUG_OUT_INPUT(("rdpSpriteRealizeCursor\n")); + LLOGLN(10, ("rdpSpriteRealizeCursor:")); return 1; } @@ -573,7 +574,7 @@ rdpSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScr, CursorPtr pCurs) Bool rdpSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScr, CursorPtr pCurs) { - DEBUG_OUT_INPUT(("hi rdpSpriteUnrealizeCursor\n")); + LLOGLN(10, ("rdpSpriteUnrealizeCursor:")); return 1; } @@ -780,14 +781,14 @@ rdpSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScr, CursorPtr pCurs, void rdpSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScr, int x, int y) { - DEBUG_OUT_INPUT(("hi rdpSpriteMoveCursor\n")); + LLOGLN(10, ("rdpSpriteMoveCursor:")); } /******************************************************************************/ Bool rdpSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScr) { - ErrorF("rdpSpriteDeviceCursorInitialize:\n"); + LLOGLN(0, ("rdpSpriteDeviceCursorInitialize:")); return 1; } @@ -795,7 +796,7 @@ rdpSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScr) void rdpSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScr) { - ErrorF("rdpSpriteDeviceCursorCleanup:\n"); + LLOGLN(0, ("rdpSpriteDeviceCursorCleanup:")); } /******************************************************************************/ @@ -856,25 +857,6 @@ rdpEnqueueButton(int type, int buttons) } /******************************************************************************/ -static void -rdpEnqueueKey(int type, int scancode) -{ - int i; - int n; - EventListPtr rdp_events; - xEvent *pev; - - i = GetEventList(&rdp_events); - n = GetKeyboardEvents(rdp_events, g_keyboard, type, scancode); - - for (i = 0; i < n; i++) - { - pev = (rdp_events + i)->event; - mieqEnqueue(g_keyboard, (InternalEvent *)pev); - } -} - -/******************************************************************************/ static CARD32 rdpDeferredInputCallback(OsTimerPtr timer, CARD32 now, pointer arg) { @@ -894,6 +876,10 @@ PtrAddEvent(int buttonMask, int x, int y) int send_now; LLOGLN(10, ("PtrAddEvent: x %d y %d", x, y)); + if (g_pointer == 0) + { + return; + } 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)); @@ -939,251 +925,15 @@ PtrAddEvent(int buttonMask, int x, int y) /******************************************************************************/ void -check_keysa(void) -{ - if (g_ctrl_down != 0) - { - rdpEnqueueKey(KeyRelease, g_ctrl_down); - g_ctrl_down = 0; - } - - if (g_alt_down != 0) - { - rdpEnqueueKey(KeyRelease, g_alt_down); - g_alt_down = 0; - } - - if (g_shift_down != 0) - { - rdpEnqueueKey(KeyRelease, g_shift_down); - g_shift_down = 0; - } -} - -/******************************************************************************/ -void -sendDownUpKeyEvent(int type, int x_scancode) +KbdAddEvent(int down, int param1, int param2, int param3, int param4) { - /* if type is keydown, send keyup + keydown */ - if (type == KeyPress) + if (g_use_evdev) { - rdpEnqueueKey(KeyRelease, x_scancode); - rdpEnqueueKey(KeyPress, x_scancode); + KbdAddEvent_evdev(down, param1, param2, param3, param4); } else { - rdpEnqueueKey(KeyRelease, x_scancode); - } -} - -/** - * @param down - true for KeyDown events, false otherwise - * @param param1 - ASCII code of pressed key - * @param param2 - - * @param param3 - scancode of pressed key - * @param param4 - - ******************************************************************************/ -void -KbdAddEvent(int down, int param1, int param2, int param3, int param4) -{ - int rdp_scancode; - int x_scancode; - int is_ext; - int is_spe; - int type; - -#if 0 - fprintf(stderr, "down=0x%x param1=0x%x param2=0x%x param3=0x%x " - "param4=0x%x\n", down, param1, param2, param3, param4); -#endif - - type = down ? KeyPress : KeyRelease; - rdp_scancode = param3; - is_ext = param4 & 256; /* 0x100 */ - is_spe = param4 & 512; /* 0x200 */ - x_scancode = 0; - - switch (rdp_scancode) - { - case 58: /* caps lock */ - case 42: /* left shift */ - case 54: /* right shift */ - case 70: /* scroll lock */ - x_scancode = rdp_scancode + MIN_KEY_CODE; - - if (x_scancode > 0) - { - /* 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 */ - - if (is_ext) - { - x_scancode = 113; /* right alt button */ - } - else - { - x_scancode = 64; /* left alt button */ - } - - g_alt_down = down ? x_scancode : 0; - rdpEnqueueKey(type, x_scancode); - break; - - case 15: /* tab */ - - if (!down && !g_tab_down) - { - check_keysa(); /* leave x_scancode 0 here, we don't want the tab key up */ - } - else - { - sendDownUpKeyEvent(type, 23); - } - - g_tab_down = down; - break; - - case 29: /* left or right ctrl */ - - /* this is to handle special case with pause key sending control first */ - if (is_spe) - { - if (down) - { - g_pause_spe = 1; - /* leave x_scancode 0 here, we don't want the control key down */ - } - } - else - { - x_scancode = is_ext ? 109 : 37; - g_ctrl_down = down ? x_scancode : 0; - rdpEnqueueKey(type, x_scancode); - } - - break; - - case 69: /* Pause or Num Lock */ - - if (g_pause_spe) - { - x_scancode = 110; - - if (!down) - { - g_pause_spe = 0; - } - } - else - { - x_scancode = g_ctrl_down ? 110 : 77; - } - - sendDownUpKeyEvent(type, x_scancode); - break; - - case 28: /* Enter or Return */ - x_scancode = is_ext ? 108 : 36; - sendDownUpKeyEvent(type, x_scancode); - break; - - case 53: /* / */ - x_scancode = is_ext ? 112 : 61; - sendDownUpKeyEvent(type, x_scancode); - break; - - case 55: /* * on KP or Print Screen */ - x_scancode = is_ext ? 111 : 63; - sendDownUpKeyEvent(type, x_scancode); - break; - - case 71: /* 7 or Home */ - x_scancode = is_ext ? 97 : 79; - sendDownUpKeyEvent(type, x_scancode); - break; - - case 72: /* 8 or Up */ - x_scancode = is_ext ? 98 : 80; - sendDownUpKeyEvent(type, x_scancode); - break; - - case 73: /* 9 or PgUp */ - x_scancode = is_ext ? 99 : 81; - sendDownUpKeyEvent(type, x_scancode); - break; - - case 75: /* 4 or Left */ - x_scancode = is_ext ? 100 : 83; - sendDownUpKeyEvent(type, x_scancode); - break; - - case 77: /* 6 or Right */ - x_scancode = is_ext ? 102 : 85; - sendDownUpKeyEvent(type, x_scancode); - break; - - case 79: /* 1 or End */ - x_scancode = is_ext ? 103 : 87; - sendDownUpKeyEvent(type, x_scancode); - break; - - case 80: /* 2 or Down */ - x_scancode = is_ext ? 104 : 88; - sendDownUpKeyEvent(type, x_scancode); - break; - - case 81: /* 3 or PgDn */ - x_scancode = is_ext ? 105 : 89; - sendDownUpKeyEvent(type, x_scancode); - break; - - case 82: /* 0 or Insert */ - x_scancode = is_ext ? 106 : 90; - sendDownUpKeyEvent(type, x_scancode); - break; - - case 83: /* . or Delete */ - x_scancode = is_ext ? 107 : 91; - sendDownUpKeyEvent(type, x_scancode); - break; - - case 91: /* left win key */ - rdpEnqueueKey(type, 115); - break; - - case 92: /* right win key */ - rdpEnqueueKey(type, 116); - break; - - case 93: /* menu key */ - 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; - - if (x_scancode > 0) - { - sendDownUpKeyEvent(type, x_scancode); - } - - break; + KbdAddEvent_base(down, param1, param2, param3, param4); } } @@ -1196,25 +946,29 @@ KbdSync(int param1) { int xkb_state; + if (g_keyboard == 0) + { + return; + } xkb_state = XkbStateFieldFromRec(&(g_keyboard->key->xkbInfo->state)); if ((!(xkb_state & 0x02)) != (!(param1 & 4))) /* caps lock */ { - ErrorF("KbdSync: toggling caps lock\n"); + LLOGLN(0, ("KbdSync: toggling caps lock")); KbdAddEvent(1, 58, 0, 58, 0); KbdAddEvent(0, 58, 49152, 58, 49152); } if ((!(xkb_state & 0x10)) != (!(param1 & 2))) /* num lock */ { - ErrorF("KbdSync: toggling num lock\n"); + LLOGLN(0, ("KbdSync: toggling num lock")); KbdAddEvent(1, 69, 0, 69, 0); KbdAddEvent(0, 69, 49152, 69, 49152); } if ((!(g_scroll_lock_down)) != (!(param1 & 1))) /* scroll lock */ { - ErrorF("KbdSync: toggling scroll lock\n"); + LLOGLN(0, ("KbdSync: toggling scroll lock")); KbdAddEvent(1, 70, 0, 70, 0); KbdAddEvent(0, 70, 49152, 70, 49152); } diff --git a/xorg/X11R7.6/rdp/rdpkeyboard.c b/xorg/X11R7.6/rdp/rdpkeyboard.c new file mode 100644 index 00000000..31fefe54 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpkeyboard.c @@ -0,0 +1,95 @@ +/* +Copyright 2005-2014 Jay Sorg + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +keyboard + +*/ + +#include "rdp.h" +#include "rdpkeyboard.h" +#include "rdpkeyboardevdev.h" + +#define LOG_LEVEL 1 +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +extern DeviceIntPtr g_keyboard; /* in rdpmain.c */ +extern int g_shift_down; /* in rdpmain.c */ +extern int g_alt_down; /* in rdpmain.c */ +extern int g_ctrl_down; /* in rdpmain.c */ +extern int g_pause_spe; /* in rdpmain.c */ +extern int g_tab_down; /* in rdpmain.c */ + +/******************************************************************************/ +void +rdpEnqueueKey(int type, int scancode) +{ + int i; + int n; + EventListPtr rdp_events; + xEvent *pev; + + i = GetEventList(&rdp_events); + n = GetKeyboardEvents(rdp_events, g_keyboard, type, scancode); + + for (i = 0; i < n; i++) + { + pev = (rdp_events + i)->event; + mieqEnqueue(g_keyboard, (InternalEvent *)pev); + } +} + +/******************************************************************************/ +void +check_keysa(void) +{ + if (g_ctrl_down != 0) + { + rdpEnqueueKey(KeyRelease, g_ctrl_down); + g_ctrl_down = 0; + } + + if (g_alt_down != 0) + { + rdpEnqueueKey(KeyRelease, g_alt_down); + g_alt_down = 0; + } + + if (g_shift_down != 0) + { + rdpEnqueueKey(KeyRelease, g_shift_down); + g_shift_down = 0; + } +} + +/******************************************************************************/ +void +sendDownUpKeyEvent(int type, int x_scancode) +{ + /* if type is keydown, send keyup + keydown */ + if (type == KeyPress) + { + rdpEnqueueKey(KeyRelease, x_scancode); + rdpEnqueueKey(KeyPress, x_scancode); + } + else + { + rdpEnqueueKey(KeyRelease, x_scancode); + } +} diff --git a/xorg/X11R7.6/rdp/rdpkeyboard.h b/xorg/X11R7.6/rdp/rdpkeyboard.h new file mode 100644 index 00000000..dc708501 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpkeyboard.h @@ -0,0 +1,68 @@ +/* +Copyright 2013-2014 Jay Sorg + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +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. + +keyboard map for base rules + +*/ + +#ifndef _RDPKEYBOARD_H +#define _RDPKEYBOARD_H + +#define MIN_KEY_CODE 8 +#define MAX_KEY_CODE 255 +#define NO_OF_KEYS ((MAX_KEY_CODE - MIN_KEY_CODE) + 1) +#define GLYPHS_PER_KEY 2 + +#define RDPSCAN_Tab 15 +#define RDPSCAN_Return 28 /* ext is used to know KP or not */ +#define RDPSCAN_Control 29 /* ext is used to know L or R */ +#define RDPSCAN_Shift_L 42 +#define RDPSCAN_Slash 53 +#define RDPSCAN_Shift_R 54 +#define RDPSCAN_KP_Multiply 55 +#define RDPSCAN_Alt 56 /* ext is used to know L or R */ +#define RDPSCAN_Caps_Lock 58 +#define RDPSCAN_Pause 69 +#define RDPSCAN_Scroll_Lock 70 +#define RDPSCAN_KP_7 71 /* KP7 or home */ +#define RDPSCAN_KP_8 72 /* KP8 or up */ +#define RDPSCAN_KP_9 73 /* KP9 or page up */ +#define RDPSCAN_KP_4 75 /* KP4 or left */ +#define RDPSCAN_KP_6 77 /* KP6 or right */ +#define RDPSCAN_KP_1 79 /* KP1 or home */ +#define RDPSCAN_KP_2 80 /* KP2 or up */ +#define RDPSCAN_KP_3 81 /* KP3 or page down */ +#define RDPSCAN_KP_0 82 /* KP0 or insert */ +#define RDPSCAN_KP_Decimal 83 /* KP. or delete */ +#define RDPSCAN_89 89 +#define RDPSCAN_90 90 +#define RDPSCAN_LWin 91 +#define RDPSCAN_RWin 92 +#define RDPSCAN_Menu 93 +#define RDPSCAN_115 115 +#define RDPSCAN_126 126 + +void +rdpEnqueueKey(int type, int scancode); +void +check_keysa(void); +void +sendDownUpKeyEvent(int type, int x_scancode); + +#endif diff --git a/xorg/X11R7.6/rdp/rdpkeyboardbase.c b/xorg/X11R7.6/rdp/rdpkeyboardbase.c new file mode 100644 index 00000000..4783f730 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpkeyboardbase.c @@ -0,0 +1,300 @@ +/* +Copyright 2005-2014 Jay Sorg + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +keyboard map for base rules + +*/ + +#include "rdp.h" +#include "rdpkeyboard.h" +#include "rdpkeyboardbase.h" + +extern DeviceIntPtr g_keyboard; /* in rdpmain.c */ +extern int g_shift_down; /* in rdpmain.c */ +extern int g_alt_down; /* in rdpmain.c */ +extern int g_ctrl_down; /* in rdpmain.c */ +extern int g_pause_spe; /* in rdpmain.c */ +extern int g_tab_down; /* in rdpmain.c */ + +#define LOG_LEVEL 1 +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +#define XSCAN_Tab 23 +#define XSCAN_Return 36 /* above right shift */ +#define XSCAN_Control_L 37 +#define XSCAN_Shift_L 50 +#define XSCAN_slash 61 +#define XSCAN_Shift_R 62 +#define XSCAN_KP_Multiply 63 +#define XSCAN_Alt_L 64 +#define XSCAN_Caps_Lock 66 /* caps lock */ +#define XSCAN_Num_Lock 77 /* num lock */ +#define XSCAN_KP_7 79 +#define XSCAN_KP_8 80 +#define XSCAN_KP_9 81 +#define XSCAN_KP_4 83 +#define XSCAN_KP_6 85 +#define XSCAN_KP_1 87 +#define XSCAN_KP_2 88 +#define XSCAN_KP_3 89 +#define XSCAN_KP_0 90 +#define XSCAN_KP_Decimal 91 +/* "/ ?" on br keybaord */ +#define XSCAN_97 97 /* ------------------------------? */ +#define XSCAN_Enter 108 /* 104 */ /* on keypad */ +#define XSCAN_Control_R 109 /* 105 */ +#define XSCAN_KP_Divide 112 /* 106 */ +#define XSCAN_Print 111 /* 107 */ +#define XSCAN_Alt_R 113 /* 108 */ +#define XSCAN_Home 97 /* 110 */ +#define XSCAN_Up 98 /* 111 */ +#define XSCAN_Prior 99 /* 112 */ +#define XSCAN_Left 100 /* 113 */ +#define XSCAN_Right 102 /* 114 */ +#define XSCAN_End 103 /* 115 */ +#define XSCAN_Down 104 /* 116 */ +#define XSCAN_Next 105 /* 117 */ +#define XSCAN_Insert 106 /* 118 */ +#define XSCAN_Delete 107 /* 119 */ +#define XSCAN_Pause 110 /* 127 */ +/* . on br keypad */ +#define XSCAN_129 129 /* ------------------------------? */ +#define XSCAN_LWin 115 /* 133 */ +#define XSCAN_RWin 116 /* 134 */ +#define XSCAN_Menu 117 /* 135 */ +#define XSCAN_LMeta 156 +#define XSCAN_RMeta 156 + +/******************************************************************************/ +void +KbdAddEvent_base(int down, int param1, int param2, int param3, int param4) +{ + int rdp_scancode; + int x_scancode; + int is_ext; + int is_spe; + int type; + + LLOGLN(10, ("KbdAddEvent_base: down=0x%x param1=0x%x param2=0x%x " + "param3=0x%x param4=0x%x", down, param1, param2, param3, param4)); + if (g_keyboard == 0) + { + return; + } + type = down ? KeyPress : KeyRelease; + rdp_scancode = param3; + is_ext = param4 & 256; /* 0x100 */ + is_spe = param4 & 512; /* 0x200 */ + x_scancode = 0; + + switch (rdp_scancode) + { + case RDPSCAN_Caps_Lock: /* caps lock */ + case RDPSCAN_Shift_L: /* left shift */ + case RDPSCAN_Shift_R: /* right shift */ + case RDPSCAN_Scroll_Lock: /* scroll lock */ + x_scancode = rdp_scancode + MIN_KEY_CODE; + + if (x_scancode > 0) + { + /* left or right shift */ + if ((rdp_scancode == RDPSCAN_Shift_L) || + (rdp_scancode == RDPSCAN_Shift_R)) + { + g_shift_down = down ? x_scancode : 0; + } + rdpEnqueueKey(type, x_scancode); + } + break; + + case RDPSCAN_Alt: /* left - right alt button */ + + if (is_ext) + { + x_scancode = XSCAN_Alt_R; /* right alt button */ + } + else + { + x_scancode = XSCAN_Alt_L; /* left alt button */ + } + + g_alt_down = down ? x_scancode : 0; + rdpEnqueueKey(type, x_scancode); + break; + + case RDPSCAN_Tab: /* tab */ + + if (!down && !g_tab_down) + { + check_keysa(); /* leave x_scancode 0 here, we don't want the tab key up */ + } + else + { + sendDownUpKeyEvent(type, XSCAN_Tab); + } + + g_tab_down = down; + break; + + case RDPSCAN_Control: /* left or right ctrl */ + + /* this is to handle special case with pause key sending control first */ + if (is_spe) + { + if (down) + { + g_pause_spe = 1; + /* leave x_scancode 0 here, we don't want the control key down */ + } + } + else + { + x_scancode = is_ext ? XSCAN_Control_R : XSCAN_Control_L; + g_ctrl_down = down ? x_scancode : 0; + rdpEnqueueKey(type, x_scancode); + } + + break; + + case RDPSCAN_Pause: /* Pause or Num Lock */ + + if (g_pause_spe) + { + x_scancode = XSCAN_Pause; + + if (!down) + { + g_pause_spe = 0; + } + } + else + { + x_scancode = g_ctrl_down ? XSCAN_Pause : XSCAN_Num_Lock; + } + + rdpEnqueueKey(type, x_scancode); + break; + + case RDPSCAN_Return: /* Enter or Return */ + x_scancode = is_ext ? XSCAN_Enter : XSCAN_Return; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_Slash: /* / */ + x_scancode = is_ext ? XSCAN_KP_Divide : XSCAN_slash; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_KP_Multiply: /* * on KP or Print Screen */ + x_scancode = is_ext ? XSCAN_Print : XSCAN_KP_Multiply; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_KP_7: /* 7 or Home */ + x_scancode = is_ext ? XSCAN_Home : XSCAN_KP_7; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_KP_8: /* 8 or Up */ + x_scancode = is_ext ? XSCAN_Up : XSCAN_KP_8; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_KP_9: /* 9 or PgUp */ + x_scancode = is_ext ? XSCAN_Prior : XSCAN_KP_9; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_KP_4: /* 4 or Left */ + x_scancode = is_ext ? XSCAN_Left : XSCAN_KP_4; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_KP_6: /* 6 or Right */ + x_scancode = is_ext ? XSCAN_Right : XSCAN_KP_6; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_KP_1: /* 1 or End */ + x_scancode = is_ext ? XSCAN_End : XSCAN_KP_1; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_KP_2: /* 2 or Down */ + x_scancode = is_ext ? XSCAN_Down : XSCAN_KP_2; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_KP_3: /* 3 or PgDn */ + x_scancode = is_ext ? XSCAN_Next : XSCAN_KP_3; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_KP_0: /* 0 or Insert */ + x_scancode = is_ext ? XSCAN_Insert : XSCAN_KP_0; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_KP_Decimal: /* . or Delete */ + x_scancode = is_ext ? XSCAN_Delete : XSCAN_KP_Decimal; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_LWin: /* left win key */ + rdpEnqueueKey(type, XSCAN_LWin); + break; + + case RDPSCAN_RWin: /* right win key */ + rdpEnqueueKey(type, XSCAN_RWin); + break; + + case RDPSCAN_Menu: /* menu key */ + rdpEnqueueKey(type, XSCAN_Menu); + break; + + case RDPSCAN_89: /* left meta */ + rdpEnqueueKey(type, XSCAN_LMeta); + break; + + case RDPSCAN_90: /* right meta */ + rdpEnqueueKey(type, XSCAN_RMeta); + break; + + case RDPSCAN_115: + rdpEnqueueKey(type, XSCAN_97); /* "/ ?" on br keybaord */ + break; + + case RDPSCAN_126: + rdpEnqueueKey(type, XSCAN_129); /* . on br keypad */ + break; + + default: + x_scancode = rdp_scancode + MIN_KEY_CODE; + + if (x_scancode > 0) + { + LLOGLN(10, ("KbdAddEvent_base: rdp_scancode %d x_scancode %d", + rdp_scancode, x_scancode)); + sendDownUpKeyEvent(type, x_scancode); + } + + break; + } +} diff --git a/xorg/X11R7.6/rdp/rdpkeyboardbase.h b/xorg/X11R7.6/rdp/rdpkeyboardbase.h new file mode 100644 index 00000000..6548b78e --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpkeyboardbase.h @@ -0,0 +1,30 @@ +/* +Copyright 2013-2014 Jay Sorg + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +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. + +keyboard map for base rules + +*/ + +#ifndef _RDPKEYBOARDBASE_H +#define _RDPKEYBOARDBASE_H + +void +KbdAddEvent_base(int down, int param1, int param2, int param3, int param4); + +#endif diff --git a/xorg/X11R7.6/rdp/rdpkeyboardevdev.c b/xorg/X11R7.6/rdp/rdpkeyboardevdev.c new file mode 100644 index 00000000..770a102f --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpkeyboardevdev.c @@ -0,0 +1,300 @@ +/* +Copyright 2005-2014 Jay Sorg + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +keyboard map for evdev rules + +*/ + +#include "rdp.h" +#include "rdpkeyboard.h" +#include "rdpkeyboardevdev.h" + +extern DeviceIntPtr g_keyboard; /* in rdpmain.c */ +extern int g_shift_down; /* in rdpmain.c */ +extern int g_alt_down; /* in rdpmain.c */ +extern int g_ctrl_down; /* in rdpmain.c */ +extern int g_pause_spe; /* in rdpmain.c */ +extern int g_tab_down; /* in rdpmain.c */ + +#define LOG_LEVEL 1 +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +#define XSCAN_Tab 23 +#define XSCAN_Return 36 /* above right shift */ +#define XSCAN_Control_L 37 +#define XSCAN_Shift_L 50 +#define XSCAN_slash 61 +#define XSCAN_Shift_R 62 +#define XSCAN_KP_Multiply 63 +#define XSCAN_Alt_L 64 +#define XSCAN_Caps_Lock 66 /* caps lock */ +#define XSCAN_Num_Lock 77 /* num lock */ +#define XSCAN_KP_7 79 +#define XSCAN_KP_8 80 +#define XSCAN_KP_9 81 +#define XSCAN_KP_4 83 +#define XSCAN_KP_6 85 +#define XSCAN_KP_1 87 +#define XSCAN_KP_2 88 +#define XSCAN_KP_3 89 +#define XSCAN_KP_0 90 +#define XSCAN_KP_Decimal 91 +/* "/ ?" on br keybaord */ +#define XSCAN_97 97 +#define XSCAN_Enter 104 /* on keypad */ +#define XSCAN_Control_R 105 +#define XSCAN_KP_Divide 106 +#define XSCAN_Print 107 +#define XSCAN_Alt_R 108 +#define XSCAN_Home 110 +#define XSCAN_Up 111 +#define XSCAN_Prior 112 +#define XSCAN_Left 113 +#define XSCAN_Right 114 +#define XSCAN_End 115 +#define XSCAN_Down 116 +#define XSCAN_Next 117 +#define XSCAN_Insert 118 +#define XSCAN_Delete 119 +#define XSCAN_Pause 127 +/* . on br keypad */ +#define XSCAN_129 129 +#define XSCAN_LWin 133 +#define XSCAN_RWin 134 +#define XSCAN_Menu 135 +#define XSCAN_LMeta 156 +#define XSCAN_RMeta 156 + +/******************************************************************************/ +void +KbdAddEvent_evdev(int down, int param1, int param2, int param3, int param4) +{ + int rdp_scancode; + int x_scancode; + int is_ext; + int is_spe; + int type; + + LLOGLN(10, ("KbdAddEvent_evdev: down=0x%x param1=0x%x param2=0x%x " + "param3=0x%x param4=0x%x", down, param1, param2, param3, param4)); + if (g_keyboard == 0) + { + return; + } + type = down ? KeyPress : KeyRelease; + rdp_scancode = param3; + is_ext = param4 & 256; /* 0x100 */ + is_spe = param4 & 512; /* 0x200 */ + x_scancode = 0; + + switch (rdp_scancode) + { + case RDPSCAN_Caps_Lock: /* caps lock */ + case RDPSCAN_Shift_L: /* left shift */ + case RDPSCAN_Shift_R: /* right shift */ + case RDPSCAN_Scroll_Lock: /* scroll lock */ + x_scancode = rdp_scancode + MIN_KEY_CODE; + + if (x_scancode > 0) + { + /* left or right shift */ + if ((rdp_scancode == RDPSCAN_Shift_L) || + (rdp_scancode == RDPSCAN_Shift_R)) + { + g_shift_down = down ? x_scancode : 0; + } + rdpEnqueueKey(type, x_scancode); + } + break; + + case RDPSCAN_Alt: /* left - right alt button */ + + if (is_ext) + { + x_scancode = XSCAN_Alt_R; /* right alt button */ + } + else + { + x_scancode = XSCAN_Alt_L; /* left alt button */ + } + + g_alt_down = down ? x_scancode : 0; + rdpEnqueueKey(type, x_scancode); + break; + + case RDPSCAN_Tab: /* tab */ + + if (!down && !g_tab_down) + { + check_keysa(); /* leave x_scancode 0 here, we don't want the tab key up */ + } + else + { + sendDownUpKeyEvent(type, XSCAN_Tab); + } + + g_tab_down = down; + break; + + case RDPSCAN_Control: /* left or right ctrl */ + + /* this is to handle special case with pause key sending control first */ + if (is_spe) + { + if (down) + { + g_pause_spe = 1; + /* leave x_scancode 0 here, we don't want the control key down */ + } + } + else + { + x_scancode = is_ext ? XSCAN_Control_R : XSCAN_Control_L; + g_ctrl_down = down ? x_scancode : 0; + rdpEnqueueKey(type, x_scancode); + } + + break; + + case RDPSCAN_Pause: /* Pause or Num Lock */ + + if (g_pause_spe) + { + x_scancode = XSCAN_Pause; + + if (!down) + { + g_pause_spe = 0; + } + } + else + { + x_scancode = g_ctrl_down ? XSCAN_Pause : XSCAN_Num_Lock; + } + + rdpEnqueueKey(type, x_scancode); + break; + + case RDPSCAN_Return: /* Enter or Return */ + x_scancode = is_ext ? XSCAN_Enter : XSCAN_Return; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_Slash: /* / */ + x_scancode = is_ext ? XSCAN_KP_Divide : XSCAN_slash; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_KP_Multiply: /* * on KP or Print Screen */ + x_scancode = is_ext ? XSCAN_Print : XSCAN_KP_Multiply; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_KP_7: /* 7 or Home */ + x_scancode = is_ext ? XSCAN_Home : XSCAN_KP_7; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_KP_8: /* 8 or Up */ + x_scancode = is_ext ? XSCAN_Up : XSCAN_KP_8; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_KP_9: /* 9 or PgUp */ + x_scancode = is_ext ? XSCAN_Prior : XSCAN_KP_9; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_KP_4: /* 4 or Left */ + x_scancode = is_ext ? XSCAN_Left : XSCAN_KP_4; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_KP_6: /* 6 or Right */ + x_scancode = is_ext ? XSCAN_Right : XSCAN_KP_6; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_KP_1: /* 1 or End */ + x_scancode = is_ext ? XSCAN_End : XSCAN_KP_1; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_KP_2: /* 2 or Down */ + x_scancode = is_ext ? XSCAN_Down : XSCAN_KP_2; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_KP_3: /* 3 or PgDn */ + x_scancode = is_ext ? XSCAN_Next : XSCAN_KP_3; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_KP_0: /* 0 or Insert */ + x_scancode = is_ext ? XSCAN_Insert : XSCAN_KP_0; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_KP_Decimal: /* . or Delete */ + x_scancode = is_ext ? XSCAN_Delete : XSCAN_KP_Decimal; + sendDownUpKeyEvent(type, x_scancode); + break; + + case RDPSCAN_LWin: /* left win key */ + rdpEnqueueKey(type, XSCAN_LWin); + break; + + case RDPSCAN_RWin: /* right win key */ + rdpEnqueueKey(type, XSCAN_RWin); + break; + + case RDPSCAN_Menu: /* menu key */ + rdpEnqueueKey(type, XSCAN_Menu); + break; + + case RDPSCAN_89: /* left meta */ + rdpEnqueueKey(type, XSCAN_LMeta); + break; + + case RDPSCAN_90: /* right meta */ + rdpEnqueueKey(type, XSCAN_RMeta); + break; + + case RDPSCAN_115: + rdpEnqueueKey(type, XSCAN_97); /* "/ ?" on br keybaord */ + break; + + case RDPSCAN_126: + rdpEnqueueKey(type, XSCAN_129); /* . on br keypad */ + break; + + default: + x_scancode = rdp_scancode + MIN_KEY_CODE; + + if (x_scancode > 0) + { + LLOGLN(10, ("KbdAddEvent_evdev: rdp_scancode %d x_scancode %d", + rdp_scancode, x_scancode)); + sendDownUpKeyEvent(type, x_scancode); + } + + break; + } +} diff --git a/xorg/X11R7.6/rdp/rdpkeyboardevdev.h b/xorg/X11R7.6/rdp/rdpkeyboardevdev.h new file mode 100644 index 00000000..8c673cbf --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpkeyboardevdev.h @@ -0,0 +1,30 @@ +/* +Copyright 2013-2014 Jay Sorg + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +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. + +keyboard map for base rules + +*/ + +#ifndef _RDPKEYBOARDEVDEV_H +#define _RDPKEYBOARDEVDEV_H + +void +KbdAddEvent_evdev(int down, int param1, int param2, int param3, int param4); + +#endif diff --git a/xorg/X11R7.6/rdp/rdpmain.c b/xorg/X11R7.6/rdp/rdpmain.c index 1b924db7..884b8a3a 100644 --- a/xorg/X11R7.6/rdp/rdpmain.c +++ b/xorg/X11R7.6/rdp/rdpmain.c @@ -32,6 +32,27 @@ Sets up the functions #define DEBUG_OUT(arg) ErrorF arg #endif +#ifndef XRDP_DISABLE_LINUX_ABSTRACT +#ifdef __linux__ +#define XRDP_DISABLE_LINUX_ABSTRACT 1 +#else +#define XRDP_DISABLE_LINUX_ABSTRACT 0 +#endif +#endif + +#if XRDP_DISABLE_LINUX_ABSTRACT +/* because including <X11/Xtrans/Xtransint.h> in problematic + * we dup a small struct + * we need to set flags to zero to turn off abstract sockets */ +struct _MyXtransport +{ + char *TransName; + int flags; +}; +/* in xtrans-1.2.6/Xtranssock.c */ +extern struct _MyXtransport _XSERVTransSocketLocalFuncs; +#endif + rdpScreenInfoRec g_rdpScreen; /* the one screen */ ScreenPtr g_pScreen = 0; @@ -71,6 +92,12 @@ int g_use_uds = 0; char g_uds_data[256] = ""; /* data */ char g_uds_cont[256] = ""; /* control */ +int g_shift_down = 0; +int g_alt_down = 0; +int g_ctrl_down = 0; +int g_pause_spe = 0; +int g_tab_down = 0; + /* set all these at once, use function set_bpp */ int g_bpp = 16; int g_Bpp = 2; @@ -228,6 +255,16 @@ rdpDestroyColormap(ColormapPtr pColormap) #endif /******************************************************************************/ +void +rdpSetUDSRights(void) +{ + char unixSocketName[128]; + + sprintf(unixSocketName, "/tmp/.X11-unix/X%s", display); + chmod(unixSocketName, 0700); +} + +/******************************************************************************/ /* returns boolean, true if everything is ok */ static Bool rdpScreenInit(int index, ScreenPtr pScreen, int argc, char **argv) @@ -540,8 +577,10 @@ rdpScreenInit(int index, ScreenPtr pScreen, int argc, char **argv) } rdpGlyphInit(); - + //rdpXvInit(pScreen); + + rdpSetUDSRights(); ErrorF("rdpScreenInit: ret %d\n", ret); @@ -614,6 +653,11 @@ ddxProcessArgument(int argc, char **argv, int i) void OsVendorInit(void) { +#if XRDP_DISABLE_LINUX_ABSTRACT + /* turn off the Linux abstract unix doamin sockets TRANS_ABSTRACT */ + /* TRANS_NOLISTEN = 1 << 3 */ + _XSERVTransSocketLocalFuncs.flags = 0; +#endif } /******************************************************************************/ diff --git a/xorg/X11R7.6/rdp/rdpmisc.c b/xorg/X11R7.6/rdp/rdpmisc.c index eb5bedad..1d57d1fa 100644 --- a/xorg/X11R7.6/rdp/rdpmisc.c +++ b/xorg/X11R7.6/rdp/rdpmisc.c @@ -668,3 +668,13 @@ get_crc(char* data, int data_bytes) CRC_END(crc); return crc; } + +/*****************************************************************************/ +int +get_mstime(void) +{ + struct timeval tp; + + gettimeofday(&tp, 0); + return (tp.tv_sec * 1000) + (tp.tv_usec / 1000); +} diff --git a/xorg/X11R7.6/rdp/rdprandr.c b/xorg/X11R7.6/rdp/rdprandr.c index 8b3eb582..d0ee6b1c 100644 --- a/xorg/X11R7.6/rdp/rdprandr.c +++ b/xorg/X11R7.6/rdp/rdprandr.c @@ -184,6 +184,7 @@ rdpRRScreenSetSize(ScreenPtr pScreen, CARD16 width, CARD16 height, pScreen->root->drawable.height = height; ResizeChildrenWinSize(pScreen->root, 0, 0, 0, 0); RRGetInfo(pScreen, 1); + RRScreenSizeNotify(pScreen); rdpInvalidateArea(g_pScreen, 0, 0, g_rdpScreen.width, g_rdpScreen.height); ErrorF(" screen resized to %dx%d\n", pScreen->width, pScreen->height); @@ -243,7 +244,7 @@ rdpRRModeDestroy(ScreenPtr pScreen, RRModePtr mode) /******************************************************************************/ Bool -rdpRROutputGetProperty(ScreenPtr pScreen, RROutputPtr output, Atom property) +rdpRROutputGetProperty(ScreenPtr pScreen, RROutputPtr output, Atom property) { ErrorF("rdpRROutputGetProperty:\n"); return TRUE; diff --git a/xorg/X11R7.6/rdp/rdpup.c b/xorg/X11R7.6/rdp/rdpup.c index 52472121..83525251 100644 --- a/xorg/X11R7.6/rdp/rdpup.c +++ b/xorg/X11R7.6/rdp/rdpup.c @@ -538,7 +538,7 @@ static int rdpup_send_pending(void) { int rv; - + rv = 0; if (g_connected && g_begin) { @@ -1116,6 +1116,9 @@ rdpup_process_msg(struct stream *s) LLOGLN(0, (" client can not do multimon")); g_do_multimon = 0; } + + rdpLoadLayout(g_rdpScreen.client_info.keylayout); + } else if (msg_type == 105) { @@ -1431,7 +1434,7 @@ int rdpup_pre_check(int in_size) { int rv; - + rv = 0; if (!g_begin) { @@ -2226,7 +2229,7 @@ rdpup_send_alpha_area(struct image_data* id, int x, int y, int w, int h) 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) @@ -2234,7 +2237,7 @@ rdpup_send_alpha_area(struct image_data* id, int x, int y, int w, int h) rdpup_get_screen_image_rect(&lid); id = &lid; } - + if (x >= id->width) { return; @@ -2480,7 +2483,7 @@ rdpup_show_window(WindowPtr pWindow, rdpWindowRec* priv, int 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); @@ -2780,7 +2783,7 @@ 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) diff --git a/xorg/server/module/Makefile b/xorg/server/module/Makefile index d30b2ba9..9003de4d 100644 --- a/xorg/server/module/Makefile +++ b/xorg/server/module/Makefile @@ -5,9 +5,11 @@ rdpPolyRectangle.o rdpPolyArc.o rdpFillPolygon.o rdpPolyFillRect.o \ rdpPolyFillArc.o rdpPolyText8.o rdpPolyText16.o rdpImageText8.o \ rdpImageText16.o rdpImageGlyphBlt.o rdpPolyGlyphBlt.o rdpPushPixels.o \ rdpCursor.o rdpMain.o rdpRandR.o rdpMisc.o rdpReg.o \ -rdpComposite.o rdpGlyphs.o rdpPixmap.o rdpInput.o rdpClientCon.o +rdpComposite.o rdpGlyphs.o rdpPixmap.o rdpInput.o rdpClientCon.o rdpCapture.o \ +rdpTrapezoids.o -CFLAGS = -g -O2 -Wall -fPIC -I/usr/include/xorg -I/usr/include/pixman-1 +CFLAGS = -g -O2 -Wall -fPIC -I/usr/include/xorg -I/usr/include/pixman-1 \ +-I../../../common LDFLAGS = diff --git a/xorg/server/module/rdp.h b/xorg/server/module/rdp.h index c3533e98..ba1bcfd0 100644 --- a/xorg/server/module/rdp.h +++ b/xorg/server/module/rdp.h @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -30,6 +30,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdpPri.h" +/* PIXMAN_a8r8g8b8 */ +#define XRDP_a8r8g8b8 \ +((32 << 24) | (2 << 16) | (8 << 12) | (8 << 8) | (8 << 4) | 8) + #define PixelDPI 100 #define PixelToMM(_size) (((_size) * 254 + (PixelDPI) * 5) / ((PixelDPI) * 10)) @@ -38,6 +42,44 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define RDPCLAMP(_val, _lo, _hi) \ (_val) < (_lo) ? (_lo) : (_val) > (_hi) ? (_hi) : (_val) +#define XRDP_CD_NODRAW 0 +#define XRDP_CD_NOCLIP 1 +#define XRDP_CD_CLIP 2 + +#if 0 +#define RegionCopy DONOTUSE +#define RegionTranslate DONOTUSE +#define RegionNotEmpty DONOTUSE +#define RegionIntersect DONOTUSE +#define RegionContainsRect DONOTUSE +#define RegionInit DONOTUSE +#define RegionUninit DONOTUSE +#define RegionFromRects DONOTUSE +#define RegionDestroy DONOTUSE +#define RegionCreate DONOTUSE +#define RegionUnion DONOTUSE +#define RegionSubtract DONOTUSE +#define RegionInverse DONOTUSE +#define RegionExtents DONOTUSE +#define RegionReset DONOTUSE +#define RegionBreak DONOTUSE +#define RegionUnionRect DONOTUSE +#endif + +struct image_data +{ + int width; + int height; + int bpp; + int Bpp; + int lineBytes; + char *pixels; + char *shmem_pixels; + int shmem_id; + int shmem_offset; + int shmem_lineBytes; +}; + /* defined in rdpClientCon.h */ typedef struct _rdpClientCon rdpClientCon; @@ -65,6 +107,56 @@ struct _rdpKeyboard }; typedef struct _rdpKeyboard rdpKeyboard; + +struct _rdpPixmapRec +{ + int status; + int rdpindex; + 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; +}; +typedef struct _rdpPixmapRec rdpPixmapRec; +typedef struct _rdpPixmapRec * rdpPixmapPtr; +#define GETPIXPRIV(_dev, _pPixmap) (rdpPixmapPtr) \ +rdpGetPixmapPrivate(&((_pPixmap)->devPrivates), (_dev)->privateKeyRecPixmap) + +struct _rdpCounts +{ + CARD32 rdpFillSpansCallCount; /* 1 */ + CARD32 rdpSetSpansCallCount; + CARD32 rdpPutImageCallCount; + CARD32 rdpCopyAreaCallCount; + CARD32 rdpCopyPlaneCallCount; + CARD32 rdpPolyPointCallCount; + CARD32 rdpPolylinesCallCount; + CARD32 rdpPolySegmentCallCount; + CARD32 rdpPolyRectangleCallCount; + CARD32 rdpPolyArcCallCount; /* 10 */ + CARD32 rdpFillPolygonCallCount; + CARD32 rdpPolyFillRectCallCount; + CARD32 rdpPolyFillArcCallCount; + CARD32 rdpPolyText8CallCount; + CARD32 rdpPolyText16CallCount; + CARD32 rdpImageText8CallCount; + CARD32 rdpImageText16CallCount; + CARD32 rdpImageGlyphBltCallCount; + CARD32 rdpPolyGlyphBltCallCount; + CARD32 rdpPushPixelsCallCount; /* 20 */ + CARD32 rdpCompositeCallCount; + CARD32 rdpCopyWindowCallCount; /* 22 */ + CARD32 rdpTrapezoidsCallCount; + CARD32 callCount[64 - 23]; +}; + /* move this to common header */ struct _rdpRec { @@ -75,6 +167,8 @@ struct _rdpRec int sizeInBytes; int num_modes; int bitsPerPixel; + int Bpp; + int Bpp_mask; char *pfbMemory; ScreenPtr pScreen; rdpDevPrivateKey privateKeyRecGC; @@ -88,6 +182,7 @@ struct _rdpRec CloseScreenProcPtr CloseScreen; CompositeProcPtr Composite; GlyphsProcPtr Glyphs; + TrapezoidsProcPtr Trapezoids; /* keyboard and mouse */ miPointerScreenFuncPtr pCursorFuncs; @@ -114,6 +209,25 @@ struct _rdpRec char uds_data[256]; rdpClientCon *clientConHead; rdpClientCon *clientConTail; + + rdpPixmapRec screenPriv; + int sendUpdateScheduled; /* boolean */ + OsTimerPtr sendUpdateTimer; + + int do_dirty_os; /* boolean */ + int do_dirty_ons; /* boolean */ + int disconnect_scheduled; /* boolean */ + int do_kill_disconnected; /* boolean */ + + OsTimerPtr disconnectTimer; + int disconnectScheduled; /* boolean */ + int disconnect_timeout_s; + int disconnect_time_ms; + + int conNumber; + + struct _rdpCounts counts; + }; typedef struct _rdpRec rdpRec; typedef struct _rdpRec * rdpPtr; @@ -127,11 +241,73 @@ struct _rdpGCRec typedef struct _rdpGCRec rdpGCRec; typedef struct _rdpGCRec * rdpGCPtr; -struct _rdpPixmapRec +#define RDI_FILL 1 +#define RDI_IMGLL 2 /* lossless */ +#define RDI_IMGLY 3 /* lossy */ +#define RDI_LINE 4 +#define RDI_SCRBLT 5 +#define RDI_TEXT 6 + +struct urdp_draw_item_fill { - int i1; + int opcode; + int fg_color; + int bg_color; + int pad0; +}; + +struct urdp_draw_item_img +{ + int opcode; + int pad0; +}; + +struct urdp_draw_item_line +{ + int opcode; + int fg_color; + int bg_color; + int width; + xSegment* segs; + int nseg; + int flags; +}; + +struct urdp_draw_item_scrblt +{ + int srcx; + int srcy; + int dstx; + int dsty; + int cx; + 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; /* RDI_FILL, RDI_IMGLL, ... */ + int flags; + struct rdp_draw_item* prev; + struct rdp_draw_item* next; + RegionPtr reg; + union urdp_draw_item u; }; -typedef struct _rdpPixmapRec rdpPixmapRec; -typedef struct _rdpPixmapRec * rdpPixmapPtr; +#define XRDP_USE_COUNT_THRESHOLD 1 #endif diff --git a/xorg/server/module/rdpCapture.c b/xorg/server/module/rdpCapture.c new file mode 100644 index 00000000..8819713a --- /dev/null +++ b/xorg/server/module/rdpCapture.c @@ -0,0 +1,154 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Laxmikant Rashinkar 2014 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Routines to copy regions from framebuffer to shared memory + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* this should be before all X11 .h files */ +#include <xorg-server.h> + +/* all driver need this */ +#include <xf86.h> +#include <xf86_OSproc.h> + +#include "rdp.h" +#include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" + +#define LOG_LEVEL 1 +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +/******************************************************************************/ +static Bool +rdpCapture0(RegionPtr in_reg, RegionPtr out_reg, + void *src, int src_width, int src_height, + int src_stride, int src_format, + void *dst, int dst_width, int dst_height, + int dst_stride, int dst_format, int max_rects) +{ + BoxPtr prects; + BoxRec rect; + RegionRec reg; + char *src_rect; + char *dst_rect; + int num_regions; + int bytespp; + int width; + int height; + int src_offset; + int dst_offset; + int bytes; + int i; + int j; + Bool rv; + + LLOGLN(10, ("rdpCapture0:")); + + rv = TRUE; + + rect.x1 = 0; + rect.y1 = 0; + rect.x2 = min(dst_width, src_width); + rect.y2 = min(dst_height, src_height); + rdpRegionInit(®, &rect, 0); + rdpRegionIntersect(®, in_reg, ®); + + num_regions = REGION_NUM_RECTS(®); + + if (num_regions > max_rects) + { + num_regions = 1; + prects = rdpRegionExtents(®); + rdpRegionUninit(out_reg); + rdpRegionInit(out_reg, prects, 0); + } + else + { + prects = REGION_RECTS(®); + rdpRegionCopy(out_reg, ®); + } + + if ((src_format == XRDP_a8r8g8b8) && (dst_format == XRDP_a8r8g8b8)) + { + bytespp = 4; + + for (i = 0; i < num_regions; i++) + { + /* get rect to copy */ + rect = prects[i]; + + /* get rect dimensions */ + width = rect.x2 - rect.x1; + height = rect.y2 - rect.y1; + + /* point to start of each rect in respective memory */ + src_offset = rect.y1 * src_stride + rect.x1 * bytespp; + dst_offset = rect.y1 * dst_stride + rect.x1 * bytespp; + src_rect = src + src_offset; + dst_rect = dst + dst_offset; + + /* bytes per line */ + bytes = width * bytespp; + + /* copy one line at a time */ + for (j = 0; j < height; j++) + { + memcpy(dst_rect, src_rect, bytes); + src_rect += src_stride; + dst_rect += dst_stride; + } + } + } + else + { + LLOGLN(0, ("rdpCapture0: unimp color conversion")); + } + rdpRegionUninit(®); + return rv; +} + +/** + * Copy an array of rectangles from one memory area to another + *****************************************************************************/ +Bool +rdpCapture(RegionPtr in_reg, RegionPtr out_reg, + void *src, int src_width, int src_height, + int src_stride, int src_format, + void *dst, int dst_width, int dst_height, + int dst_stride, int dst_format, int mode) +{ + LLOGLN(10, ("rdpCapture:")); + switch (mode) + { + case 0: + return rdpCapture0(in_reg, out_reg, + src, src_width, src_height, + src_stride, src_format, + dst, dst_width, dst_height, + dst_stride, dst_format, 15); + default: + LLOGLN(0, ("rdpCapture: unimp mode")); + break; + } + return TRUE; +} diff --git a/xorg/server/module/rdpCapture.h b/xorg/server/module/rdpCapture.h new file mode 100644 index 00000000..f92508c4 --- /dev/null +++ b/xorg/server/module/rdpCapture.h @@ -0,0 +1,27 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Laxmikant Rashinkar 2014 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Routines to copy regions from framebuffer to shared memory + */ + +Bool +rdpCapture(RegionPtr in_reg, RegionPtr out_reg, + void *src, int src_width, int src_height, + int src_stride, int src_format, + void *dst, int dst_width, int dst_height, + int dst_stride, int dst_format, + int mode); diff --git a/xorg/server/module/rdpClientCon.c b/xorg/server/module/rdpClientCon.c index 3edd1e0c..3c9cdad5 100644 --- a/xorg/server/module/rdpClientCon.c +++ b/xorg/server/module/rdpClientCon.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -24,6 +24,10 @@ Client connection to xrdp #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/shm.h> /* this should be before all X11 .h files */ #include <xorg-server.h> @@ -36,6 +40,9 @@ Client connection to xrdp #include "rdpDraw.h" #include "rdpClientCon.h" #include "rdpMisc.h" +#include "rdpInput.h" +#include "rdpReg.h" +#include "rdpCapture.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -43,41 +50,827 @@ Client connection to xrdp #define LTOUI32(_in) ((unsigned int)(_in)) +#define COLOR8(r, g, b) \ + ((((r) >> 5) << 0) | (((g) >> 5) << 3) | (((b) >> 6) << 6)) +#define COLOR15(r, g, b) \ + ((((r) >> 3) << 10) | (((g) >> 3) << 5) | (((b) >> 3) << 0)) +#define COLOR16(r, g, b) \ + ((((r) >> 3) << 11) | (((g) >> 2) << 5) | (((b) >> 3) << 0)) +#define COLOR24(r, g, b) \ + ((((r) >> 0) << 0) | (((g) >> 0) << 8) | (((b) >> 0) << 16)) +#define SPLITCOLOR32(r, g, b, c) \ + do { \ + r = ((c) >> 16) & 0xff; \ + g = ((c) >> 8) & 0xff; \ + b = (c) & 0xff; \ + } while (0) + +#define USE_MAX_OS_BYTES 1 +#define MAX_OS_BYTES (16 * 1024 * 1024) + +/* +0 GXclear, 0 +1 GXnor, DPon +2 GXandInverted, DPna +3 GXcopyInverted, Pn +4 GXandReverse, PDna +5 GXinvert, Dn +6 GXxor, DPx +7 GXnand, DPan +8 GXand, DPa +9 GXequiv, DPxn +a GXnoop, D +b GXorInverted, DPno +c GXcopy, P +d GXorReverse, PDno +e GXor, DPo +f GXset 1 +*/ + +static int g_rdp_opcodes[16] = +{ + 0x00, /* GXclear 0x0 0 */ + 0x88, /* GXand 0x1 src AND dst */ + 0x44, /* GXandReverse 0x2 src AND NOT dst */ + 0xcc, /* GXcopy 0x3 src */ + 0x22, /* GXandInverted 0x4 NOT src AND dst */ + 0xaa, /* GXnoop 0x5 dst */ + 0x66, /* GXxor 0x6 src XOR dst */ + 0xee, /* GXor 0x7 src OR dst */ + 0x11, /* GXnor 0x8 NOT src AND NOT dst */ + 0x99, /* GXequiv 0x9 NOT src XOR dst */ + 0x55, /* GXinvert 0xa NOT dst */ + 0xdd, /* GXorReverse 0xb src OR NOT dst */ + 0x33, /* GXcopyInverted 0xc NOT src */ + 0xbb, /* GXorInverted 0xd NOT src OR dst */ + 0x77, /* GXnand 0xe NOT src OR NOT dst */ + 0xff /* GXset 0xf 1 */ +}; + /******************************************************************************/ static int rdpClientConGotConnection(ScreenPtr pScreen, rdpPtr dev) { rdpClientCon *clientCon; + int new_sck; LLOGLN(0, ("rdpClientConGotConnection:")); clientCon = (rdpClientCon *) g_malloc(sizeof(rdpClientCon), 1); + clientCon->dev = dev; + dev->do_dirty_ons = 1; + make_stream(clientCon->in_s); init_stream(clientCon->in_s, 8192); make_stream(clientCon->out_s); init_stream(clientCon->out_s, 8192 * 4 + 100); + + new_sck = g_sck_accept(dev->listen_sck); + if (new_sck == -1) + { + LLOGLN(0, ("rdpClientConGotConnection: g_sck_accept failed")); + } + else + { + LLOGLN(0, ("rdpClientConGotConnection: g_sck_accept ok new_sck %d", + new_sck)); + clientCon->sck = new_sck; + g_sck_set_non_blocking(clientCon->sck); + g_sck_tcp_set_no_delay(clientCon->sck); /* only works if TCP */ + clientCon->connected = TRUE; + clientCon->sckClosed = FALSE; + clientCon->begin = FALSE; + dev->conNumber++; + clientCon->conNumber = dev->conNumber; + AddEnabledDevice(clientCon->sck); + } + if (dev->clientConTail == NULL) { + LLOGLN(0, ("rdpClientConGotConnection: adding only clientCon")); dev->clientConHead = clientCon; dev->clientConTail = clientCon; } else { + LLOGLN(0, ("rdpClientConGotConnection: adding clientCon")); dev->clientConTail->next = clientCon; dev->clientConTail = clientCon; } + + clientCon->dirtyRegion = rdpRegionCreate(NullBox, 0); + clientCon->shmRegion = rdpRegionCreate(NullBox, 0); + return 0; } /******************************************************************************/ +static CARD32 +rdpDeferredDisconnectCallback(OsTimerPtr timer, CARD32 now, pointer arg) +{ + CARD32 lnow_ms; + rdpPtr dev; + + dev = (rdpPtr) arg; + LLOGLN(10, ("rdpDeferredDisconnectCallback")); + if (dev->clientConHead != NULL) + { + /* this should not happen */ + LLOGLN(0, ("rdpDeferredDisconnectCallback: connected")); + if (dev->disconnectTimer != NULL) + { + LLOGLN(0, ("rdpDeferredDisconnectCallback: canceling g_dis_timer")); + TimerCancel(dev->disconnectTimer); + TimerFree(dev->disconnectTimer); + dev->disconnectTimer = NULL; + } + dev->disconnect_scheduled = FALSE; + return 0; + } + else + { + LLOGLN(10, ("rdpDeferredDisconnectCallback: not connected")); + } + lnow_ms = GetTimeInMillis(); + if (lnow_ms - dev->disconnect_time_ms > dev->disconnect_timeout_s * 1000) + { + LLOGLN(0, ("rdpDeferredDisconnectCallback: exit X11rdp")); + kill(getpid(), SIGTERM); + return 0; + } + dev->disconnectTimer = TimerSet(dev->disconnectTimer, 0, 1000 * 10, + rdpDeferredDisconnectCallback, dev); + return 0; +} + +/*****************************************************************************/ static int -rdpClientConGotData(ScreenPtr pScreen, rdpPtr dev, rdpClientCon *clientCon) +rdpClientConDisconnect(rdpPtr dev, rdpClientCon *clientCon) +{ + int index; + rdpClientCon *pcli; + rdpClientCon *plcli; + + LLOGLN(0, ("rdpClientConDisconnect:")); + if (dev->do_kill_disconnected) + { + if (dev->disconnect_scheduled == FALSE) + { + LLOGLN(0, ("rdpClientConDisconnect: starting g_dis_timer")); + dev->disconnectTimer = TimerSet(dev->disconnectTimer, 0, 1000 * 10, + rdpDeferredDisconnectCallback, dev); + dev->disconnect_scheduled = TRUE; + } + dev->disconnect_time_ms = GetTimeInMillis(); + } + + RemoveEnabledDevice(clientCon->sck); + g_sck_close(clientCon->sck); + if (clientCon->maxOsBitmaps > 0) + { + for (index = 0; index < clientCon->maxOsBitmaps; index++) + { + if (clientCon->osBitmaps[index].used) + { + if (clientCon->osBitmaps[index].priv != NULL) + { + clientCon->osBitmaps[index].priv->status = 0; + } + } + } + } + g_free(clientCon->osBitmaps); + + plcli = NULL; + pcli = dev->clientConHead; + while (pcli != NULL) + { + if (pcli == clientCon) + { + if (plcli == NULL) + { + /* removing first item */ + dev->clientConHead = pcli->next; + if (dev->clientConHead == NULL) + { + /* removed only */ + dev->clientConTail = NULL; + } + } + else + { + plcli->next = pcli->next; + if (pcli == dev->clientConTail) + { + /* removed last */ + dev->clientConTail = plcli; + } + } + LLOGLN(0, ("rdpClientConDisconnect: clientCon removed from " + "dev list")); + break; + } + plcli = pcli; + pcli = pcli->next; + } + rdpRegionDestroy(clientCon->dirtyRegion); + rdpRegionDestroy(clientCon->shmRegion); + g_free(clientCon); + return 0; +} + +/*****************************************************************************/ +/* returns error */ +static int +rdpClientConSend(rdpPtr dev, rdpClientCon *clientCon, char *data, int len) +{ + int sent; + + LLOGLN(10, ("rdpClientConSend - sending %d bytes", len)); + + if (clientCon->sckClosed) + { + return 1; + } + + while (len > 0) + { + sent = g_sck_send(clientCon->sck, data, len, 0); + + if (sent == -1) + { + if (g_sck_last_error_would_block(clientCon->sck)) + { + g_sleep(1); + } + else + { + LLOGLN(0, ("rdpClientConSend: g_tcp_send failed(returned -1)")); + rdpClientConDisconnect(dev, clientCon); + return 1; + } + } + else if (sent == 0) + { + LLOGLN(0, ("rdpClientConSend: g_tcp_send failed(returned zero)")); + rdpClientConDisconnect(dev, clientCon); + return 1; + } + else + { + data += sent; + len -= sent; + } + } + + return 0; +} + +/******************************************************************************/ +static int +rdpClientConSendMsg(rdpPtr dev, rdpClientCon *clientCon) +{ + int len; + int rv; + struct stream *s; + + rv = 1; + s = clientCon->out_s; + if (s != NULL) + { + len = (int) (s->end - s->data); + + if (len > s->size) + { + LLOGLN(0, ("rdpClientConSendMsg: overrun error len %d count %d", + len, clientCon->count)); + } + + s_pop_layer(s, iso_hdr); + out_uint16_le(s, 3); + out_uint16_le(s, clientCon->count); + out_uint32_le(s, len - 8); + rv = rdpClientConSend(dev, clientCon, s->data, len); + } + + if (rv != 0) + { + LLOGLN(0, ("rdpClientConSendMsg: error in rdpup_send_msg")); + } + + return rv; +} + +/******************************************************************************/ +static int +rdpClientConSendPending(rdpPtr dev, rdpClientCon *clientCon) +{ + int rv; + + rv = 0; + if (clientCon->connected && clientCon->begin) + { + out_uint16_le(clientCon->out_s, 2); /* XR_SERVER_END_UPDATE */ + out_uint16_le(clientCon->out_s, 4); /* size */ + clientCon->count++; + s_mark_end(clientCon->out_s); + if (rdpClientConSendMsg(dev, clientCon) != 0) + { + LLOGLN(0, ("rdpClientConSendPending: rdpClientConSendMsg failed")); + rv = 1; + } + } + clientCon->count = 0; + clientCon->begin = FALSE; + return rv; +} + +/******************************************************************************/ +/* returns error */ +static int +rdpClientConRecv(rdpPtr dev, rdpClientCon *clientCon, char *data, int len) +{ + int rcvd; + + if (clientCon->sckClosed) + { + return 1; + } + + while (len > 0) + { + rcvd = g_sck_recv(clientCon->sck, data, len, 0); + + if (rcvd == -1) + { + if (g_sck_last_error_would_block(clientCon->sck)) + { + g_sleep(1); + } + else + { + LLOGLN(0, ("rdpClientConRecv: g_sck_recv failed(returned -1)")); + rdpClientConDisconnect(dev, clientCon); + return 1; + } + } + else if (rcvd == 0) + { + LLOGLN(0, ("rdpClientConRecv: g_sck_recv failed(returned 0)")); + rdpClientConDisconnect(dev, clientCon); + return 1; + } + else + { + data += rcvd; + len -= rcvd; + } + } + + return 0; +} + +/******************************************************************************/ +static int +rdpClientConRecvMsg(rdpPtr dev, rdpClientCon *clientCon) +{ + int len; + int rv; + struct stream *s; + + rv = 1; + + s = clientCon->in_s; + if (s != 0) + { + init_stream(s, 4); + rv = rdpClientConRecv(dev, clientCon, s->data, 4); + + if (rv == 0) + { + s->end = s->data + 4; + in_uint32_le(s, len); + + if (len > 3) + { + init_stream(s, len); + rv = rdpClientConRecv(dev, clientCon, s->data, len - 4); + if (rv == 0) + { + s->end = s->data + len; + } + } + } + } + + if (rv != 0) + { + LLOGLN(0, ("rdpClientConRecvMsg: error")); + } + + return rv; +} + +/******************************************************************************/ +static int +rdpClientConSendCaps(rdpPtr dev, rdpClientCon *clientCon) +{ + struct stream *ls; + int len; + int rv; + int cap_count; + int cap_bytes; + + make_stream(ls); + init_stream(ls, 8192); + s_push_layer(ls, iso_hdr, 8); + + cap_count = 0; + cap_bytes = 0; + +#if 0 + out_uint16_le(ls, 0); + out_uint16_le(ls, 4); + cap_count++; + cap_bytes += 4; + + out_uint16_le(ls, 1); + out_uint16_le(ls, 4); + cap_count++; + cap_bytes += 4; +#endif + + s_mark_end(ls); + len = (int)(ls->end - ls->data); + s_pop_layer(ls, iso_hdr); + out_uint16_le(ls, 2); /* caps */ + out_uint16_le(ls, cap_count); /* num caps */ + out_uint32_le(ls, cap_bytes); /* caps len after header */ + + rv = rdpClientConSend(dev, clientCon, ls->data, len); + + if (rv != 0) + { + LLOGLN(0, ("rdpClientConSendCaps: rdpup_send failed")); + } + + free_stream(ls); + return rv; +} + +/******************************************************************************/ +static int +rdpClientConProcessMsgVersion(rdpPtr dev, rdpClientCon *clientCon, + int param1, int param2, int param3, int param4) +{ + LLOGLN(0, ("rdpClientConProcessMsgVersion: version %d %d %d %d", + param1, param2, param3, param4)); + + if ((param1 > 0) || (param2 > 0) || (param3 > 0) || (param4 > 0)) + { + rdpClientConSendCaps(dev, clientCon); + } + + return 0; +} + +/******************************************************************************/ +/* + this from miScreenInit + pScreen->mmWidth = (xsize * 254 + dpix * 5) / (dpix * 10); + pScreen->mmHeight = (ysize * 254 + dpiy * 5) / (dpiy * 10); +*/ +static int +rdpClientConProcessScreenSizeMsg(rdpPtr dev, rdpClientCon *clientCon, + int width, int height, int bpp) +{ + RRScreenSizePtr pSize; + int mmwidth; + int mmheight; + int bytes; + Bool ok; + + LLOGLN(0, ("rdpClientConProcessScreenSizeMsg: set width %d height %d bpp %d", + width, height, bpp)); + clientCon->rdp_width = width; + clientCon->rdp_height = height; + clientCon->rdp_bpp = bpp; + + if (bpp < 15) + { + clientCon->rdp_Bpp = 1; + clientCon->rdp_Bpp_mask = 0xff; + } + else if (bpp == 15) + { + clientCon->rdp_Bpp = 2; + clientCon->rdp_Bpp_mask = 0x7fff; + } + else if (bpp == 16) + { + clientCon->rdp_Bpp = 2; + clientCon->rdp_Bpp_mask = 0xffff; + } + else if (bpp > 16) + { + clientCon->rdp_Bpp = 4; + clientCon->rdp_Bpp_mask = 0xffffff; + } + + if (clientCon->shmemptr != 0) + { + shmdt(clientCon->shmemptr); + } + bytes = clientCon->rdp_width * clientCon->rdp_height * + clientCon->rdp_Bpp; + clientCon->shmemid = shmget(IPC_PRIVATE, bytes, IPC_CREAT | 0777); + clientCon->shmemptr = shmat(clientCon->shmemid, 0, 0); + shmctl(clientCon->shmemid, IPC_RMID, NULL); + LLOGLN(0, ("rdpClientConProcessScreenSizeMsg: shmemid %d shmemptr %p", + clientCon->shmemid, clientCon->shmemptr)); + clientCon->shmem_lineBytes = clientCon->rdp_Bpp * clientCon->rdp_width; + + if (clientCon->shmRegion != 0) + { + rdpRegionDestroy(clientCon->shmRegion); + } + clientCon->shmRegion = rdpRegionCreate(NullBox, 0); + + mmwidth = PixelToMM(width); + mmheight = PixelToMM(height); + + pSize = RRRegisterSize(dev->pScreen, width, height, mmwidth, mmheight); + RRSetCurrentConfig(dev->pScreen, RR_Rotate_0, 0, pSize); + + if ((dev->width != width) || (dev->height != height)) + { + ok = RRScreenSizeSet(dev->pScreen, width, height, mmwidth, mmheight); + LLOGLN(0, ("rdpClientConProcessScreenSizeMsg: RRScreenSizeSet ok=[%d]", ok)); + } + + return 0; +} + +/******************************************************************************/ +static int +rdpClientConProcessMsgClientInput(rdpPtr dev, rdpClientCon *clientCon) { - LLOGLN(0, ("rdpClientConGotData:")); + struct stream *s; + int msg; + int param1; + int param2; + int param3; + int param4; + int x; + int y; + int cx; + int cy; + + s = clientCon->in_s; + in_uint32_le(s, msg); + in_uint32_le(s, param1); + in_uint32_le(s, param2); + in_uint32_le(s, param3); + in_uint32_le(s, param4); + + LLOGLN(10, ("rdpClientConProcessMsgClientInput: msg %d param1 %d param2 %d " + "param3 %d param4 %d", msg, param1, param2, param3, param4)); + + if (msg < 100) + { + rdpInputKeyboardEvent(dev, msg, param1, param2, param3, param4); + } + else if (msg < 200) + { + rdpInputMouseEvent(dev, msg, param1, param2, param3, param4); + } + else if (msg == 200) /* invalidate */ + { + x = (param1 >> 16) & 0xffff; + y = param1 & 0xffff; + cx = (param2 >> 16) & 0xffff; + cy = param2 & 0xffff; + LLOGLN(0, ("rdpClientConProcessMsgClientInput: invalidate x %d y %d " + "cx %d cy %d", x, y, cx, cy)); + rdpClientConAddDirtyScreen(dev, clientCon, x, y, cx, cy); + } + else if (msg == 300) /* resize desktop */ + { + rdpClientConProcessScreenSizeMsg(dev, clientCon, param1, param2, param3); + } + else if (msg == 301) /* version */ + { + rdpClientConProcessMsgVersion(dev, clientCon, + param1, param2, param3, param4); + } + else + { + LLOGLN(0, ("rdpClientConProcessMsgClientInput: unknown msg %d", msg)); + } + return 0; } /******************************************************************************/ static int +rdpClientConProcessMsgClientInfo(rdpPtr dev, rdpClientCon *clientCon) +{ + struct stream *s; + int bytes; + int i1; + + LLOGLN(0, ("rdpClientConProcessMsgClientInfo:")); + s = clientCon->in_s; + in_uint32_le(s, bytes); + if (bytes > sizeof(clientCon->client_info)) + { + bytes = sizeof(clientCon->client_info); + } + memcpy(&(clientCon->client_info), s->p - 4, bytes); + clientCon->client_info.size = bytes; + + LLOGLN(0, (" got client info bytes %d", bytes)); + LLOGLN(0, (" jpeg support %d", clientCon->client_info.jpeg)); + i1 = clientCon->client_info.offscreen_support_level; + LLOGLN(0, (" offscreen support %d", i1)); + i1 = clientCon->client_info.offscreen_cache_size; + LLOGLN(0, (" offscreen size %d", i1)); + i1 = clientCon->client_info.offscreen_cache_entries; + LLOGLN(0, (" offscreen entries %d", i1)); + + if (clientCon->client_info.offscreen_support_level > 0) + { + if (clientCon->client_info.offscreen_cache_entries > 0) + { + clientCon->maxOsBitmaps = clientCon->client_info.offscreen_cache_entries; + g_free(clientCon->osBitmaps); + clientCon->osBitmaps = (struct rdpup_os_bitmap *) + g_malloc(sizeof(struct rdpup_os_bitmap) * clientCon->maxOsBitmaps, 1); + } + } + + if (clientCon->client_info.orders[0x1b]) /* 27 NEG_GLYPH_INDEX_INDEX */ + { + LLOGLN(0, (" client supports glyph cache but server disabled")); + //clientCon->doGlyphCache = 1; + } + if (clientCon->client_info.order_flags_ex & 0x100) + { + clientCon->doComposite = 1; + } + if (clientCon->doGlyphCache) + { + LLOGLN(0, (" using glyph cache")); + } + if (clientCon->doComposite) + { + LLOGLN(0, (" using client composite")); + } + LLOGLN(10, ("order_flags_ex 0x%x", clientCon->client_info.order_flags_ex)); + if (clientCon->client_info.offscreen_cache_entries == 2000) + { + LLOGLN(0, (" client can do offscreen to offscreen blits")); + clientCon->canDoPixToPix = 1; + } + else + { + LLOGLN(0, (" client can not do offscreen to offscreen blits")); + clientCon->canDoPixToPix = 0; + } + if (clientCon->client_info.pointer_flags & 1) + { + LLOGLN(0, (" client can do new(color) cursor")); + } + else + { + LLOGLN(0, (" client can not do new(color) cursor")); + } + if (clientCon->client_info.monitorCount > 0) + { + LLOGLN(0, (" client can do multimon")); + LLOGLN(0, (" client monitor data, monitorCount= %d", clientCon->client_info.monitorCount)); + clientCon->doMultimon = 1; + } + else + { + LLOGLN(0, (" client can not do multimon")); + clientCon->doMultimon = 0; + } + + //rdpLoadLayout(g_rdpScreen.client_info.keylayout); + + return 0; +} + +/******************************************************************************/ +static int +rdpClientConProcessMsgClientRegion(rdpPtr dev, rdpClientCon *clientCon) +{ + struct stream *s; + int flags; + int x; + int y; + int cx; + int cy; + RegionRec reg; + BoxRec box; + + LLOGLN(10, ("rdpClientConProcessMsgClientRegion:")); + s = clientCon->in_s; + + in_uint32_le(s, flags); + in_uint32_le(s, clientCon->rect_id_ack); + in_uint32_le(s, x); + in_uint32_le(s, y); + in_uint32_le(s, cx); + in_uint32_le(s, cy); + LLOGLN(10, ("rdpClientConProcessMsgClientRegion: %d %d %d %d flags 0x%8.8x", + x, y, cx, cy, flags)); + LLOGLN(10, ("rdpClientConProcessMsgClientRegion: rect_id %d rect_id_ack %d", + clientCon->rect_id, clientCon->rect_id_ack)); + + box.x1 = x; + box.y1 = y; + box.x2 = box.x1 + cx; + box.y2 = box.y1 + cy; + + rdpRegionInit(®, &box, 0); + LLOGLN(10, ("rdpClientConProcessMsgClientRegion: %d %d %d %d", + box.x1, box.y1, box.x2, box.y2)); + rdpRegionSubtract(clientCon->shmRegion, clientCon->shmRegion, ®); + rdpRegionUninit(®); + + return 0; +} + +/******************************************************************************/ +static int +rdpClientConProcessMsgClientRegionEx(rdpPtr dev, rdpClientCon *clientCon) +{ + struct stream *s; + int flags; + + LLOGLN(10, ("rdpClientConProcessMsgClientRegionEx:")); + s = clientCon->in_s; + + in_uint32_le(s, flags); + in_uint32_le(s, clientCon->rect_id_ack); + LLOGLN(10, ("rdpClientConProcessMsgClientRegionEx: flags 0x%8.8x", flags)); + LLOGLN(10, ("rdpClientConProcessMsgClientRegionEx: rect_id %d " + "rect_id_ack %d", clientCon->rect_id, clientCon->rect_id_ack)); + return 0; +} + +/******************************************************************************/ +static int +rdpClientConProcessMsg(rdpPtr dev, rdpClientCon *clientCon) +{ + int msg_type; + struct stream *s; + + LLOGLN(10, ("rdpClientConProcessMsg:")); + s = clientCon->in_s; + in_uint16_le(s, msg_type); + LLOGLN(10, ("rdpClientConProcessMsg: msg_type %d", msg_type)); + switch (msg_type) + { + case 103: /* client input */ + rdpClientConProcessMsgClientInput(dev, clientCon); + break; + case 104: /* client info */ + rdpClientConProcessMsgClientInfo(dev, clientCon); + break; + case 105: /* client region */ + rdpClientConProcessMsgClientRegion(dev, clientCon); + break; + case 106: /* client region ex */ + rdpClientConProcessMsgClientRegionEx(dev, clientCon); + break; + default: + break; + } + + return 0; +} + +/******************************************************************************/ +static int +rdpClientConGotData(ScreenPtr pScreen, rdpPtr dev, rdpClientCon *clientCon) +{ + int rv; + + LLOGLN(10, ("rdpClientConGotData:")); + + rv = rdpClientConRecvMsg(dev, clientCon); + if (rv == 0) + { + rv = rdpClientConProcessMsg(dev, clientCon); + } + + return rv; +} + +/******************************************************************************/ +static int rdpClientConGotControlConnection(ScreenPtr pScreen, rdpPtr dev, rdpClientCon *clientCon) { @@ -169,21 +962,36 @@ rdpClientConCheck(ScreenPtr pScreen) { if (FD_ISSET(LTOUI32(clientCon->sck), &rfds)) { - rdpClientConGotData(pScreen, dev, clientCon); + if (rdpClientConGotData(pScreen, dev, clientCon) != 0) + { + LLOGLN(0, ("rdpClientConCheck: rdpClientConGotData failed")); + clientCon = dev->clientConHead; + continue; + } } } if (clientCon->sckControlListener > 0) { if (FD_ISSET(LTOUI32(clientCon->sckControlListener), &rfds)) { - rdpClientConGotControlConnection(pScreen, dev, clientCon); + if (rdpClientConGotControlConnection(pScreen, dev, clientCon) != 0) + { + LLOGLN(0, ("rdpClientConCheck: rdpClientConGotControlConnection failed")); + clientCon = dev->clientConHead; + continue; + } } } if (clientCon->sckControl > 0) { if (FD_ISSET(LTOUI32(clientCon->sckControl), &rfds)) { - rdpClientConGotControlData(pScreen, dev, clientCon); + if (rdpClientConGotControlData(pScreen, dev, clientCon) != 0) + { + LLOGLN(0, ("rdpClientConCheck: rdpClientConGotControlData failed")); + clientCon = dev->clientConHead; + continue; + } } } clientCon = clientCon->next; @@ -219,13 +1027,13 @@ rdpClientConInit(rdpPtr dev) if (dev->listen_sck == 0) { unlink(dev->uds_data); - dev->listen_sck = g_tcp_local_socket_stream(); - if (g_tcp_local_bind(dev->listen_sck, dev->uds_data) != 0) + dev->listen_sck = g_sck_local_socket_stream(); + if (g_sck_local_bind(dev->listen_sck, dev->uds_data) != 0) { LLOGLN(0, ("rdpClientConInit: g_tcp_local_bind failed")); return 1; } - g_tcp_listen(dev->listen_sck); + g_sck_listen(dev->listen_sck); AddEnabledDevice(dev->listen_sck); } return 0; @@ -243,3 +1051,1159 @@ rdpClientConDeinit(rdpPtr dev) } return 0; } + +/******************************************************************************/ +int +rdpClientConBeginUpdate(rdpPtr dev, rdpClientCon *clientCon) +{ + LLOGLN(10, ("rdpClientConBeginUpdate:")); + + if (clientCon->connected) + { + if (clientCon->begin) + { + return 0; + } + init_stream(clientCon->out_s, 0); + s_push_layer(clientCon->out_s, iso_hdr, 8); + out_uint16_le(clientCon->out_s, 1); /* begin update */ + out_uint16_le(clientCon->out_s, 4); /* size */ + clientCon->begin = TRUE; + clientCon->count = 1; + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConEndUpdate(rdpPtr dev, rdpClientCon *clientCon) +{ + LLOGLN(10, ("rdpClientConEndUpdate")); + + if (clientCon->connected && clientCon->begin) + { + if (dev->do_dirty_ons) + { + /* in this mode, end update is only called in check dirty */ + rdpClientConSendPending(dev, clientCon); + } + else + { + rdpClientConScheduleDeferredUpdate(dev); + } + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConPreCheck(rdpPtr dev, rdpClientCon *clientCon, int in_size) +{ + int rv; + + rv = 0; + if (clientCon->begin == FALSE) + { + rdpClientConBeginUpdate(dev, clientCon); + } + + if ((clientCon->out_s->p - clientCon->out_s->data) > + (clientCon->out_s->size - (in_size + 20))) + { + s_mark_end(clientCon->out_s); + if (rdpClientConSendMsg(dev, clientCon) != 0) + { + LLOGLN(0, ("rdpClientConPreCheck: rdpup_send_msg failed")); + rv = 1; + } + clientCon->count = 0; + init_stream(clientCon->out_s, 0); + s_push_layer(clientCon->out_s, iso_hdr, 8); + } + + return rv; +} + +/******************************************************************************/ +int +rdpClientConFillRect(rdpPtr dev, rdpClientCon *clientCon, + short x, short y, int cx, int cy) +{ + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConFillRect:")); + rdpClientConPreCheck(dev, clientCon, 12); + out_uint16_le(clientCon->out_s, 3); /* fill rect */ + out_uint16_le(clientCon->out_s, 12); /* size */ + clientCon->count++; + out_uint16_le(clientCon->out_s, x); + out_uint16_le(clientCon->out_s, y); + out_uint16_le(clientCon->out_s, cx); + out_uint16_le(clientCon->out_s, cy); + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConScreenBlt(rdpPtr dev, rdpClientCon *clientCon, + short x, short y, int cx, int cy, short srcx, short srcy) +{ + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConScreenBlt: x %d y %d cx %d cy %d " + "srcx %d srcy %d", + x, y, cx, cy, srcx, srcy)); + rdpClientConPreCheck(dev, clientCon, 16); + out_uint16_le(clientCon->out_s, 4); /* screen blt */ + out_uint16_le(clientCon->out_s, 16); /* size */ + clientCon->count++; + out_uint16_le(clientCon->out_s, x); + out_uint16_le(clientCon->out_s, y); + out_uint16_le(clientCon->out_s, cx); + out_uint16_le(clientCon->out_s, cy); + out_uint16_le(clientCon->out_s, srcx); + out_uint16_le(clientCon->out_s, srcy); + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConSetClip(rdpPtr dev, rdpClientCon *clientCon, + short x, short y, int cx, int cy) +{ + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConSetClip:")); + rdpClientConPreCheck(dev, clientCon, 12); + out_uint16_le(clientCon->out_s, 10); /* set clip */ + out_uint16_le(clientCon->out_s, 12); /* size */ + clientCon->count++; + out_uint16_le(clientCon->out_s, x); + out_uint16_le(clientCon->out_s, y); + out_uint16_le(clientCon->out_s, cx); + out_uint16_le(clientCon->out_s, cy); + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConResetClip(rdpPtr dev, rdpClientCon *clientCon) +{ + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConResetClip:")); + rdpClientConPreCheck(dev, clientCon, 4); + out_uint16_le(clientCon->out_s, 11); /* reset clip */ + out_uint16_le(clientCon->out_s, 4); /* size */ + clientCon->count++; + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConConvertPixel(rdpPtr dev, rdpClientCon *clientCon, int in_pixel) +{ + int red; + int green; + int blue; + int rv; + + rv = 0; + + if (dev->depth == 24) + { + if (clientCon->rdp_bpp == 24) + { + rv = in_pixel; + SPLITCOLOR32(red, green, blue, rv); + rv = COLOR24(red, green, blue); + } + else if (clientCon->rdp_bpp == 16) + { + rv = in_pixel; + SPLITCOLOR32(red, green, blue, rv); + rv = COLOR16(red, green, blue); + } + else if (clientCon->rdp_bpp == 15) + { + rv = in_pixel; + SPLITCOLOR32(red, green, blue, rv); + rv = COLOR15(red, green, blue); + } + else if (clientCon->rdp_bpp == 8) + { + rv = in_pixel; + SPLITCOLOR32(red, green, blue, rv); + rv = COLOR8(red, green, blue); + } + } + else if (dev->depth == clientCon->rdp_bpp) + { + return in_pixel; + } + + return rv; +} + +/******************************************************************************/ +int +rdpClientConConvertPixels(rdpPtr dev, rdpClientCon *clientCon, + void *src, void *dst, int num_pixels) +{ + unsigned int pixel; + unsigned int red; + unsigned int green; + unsigned int blue; + unsigned int *src32; + unsigned int *dst32; + unsigned short *dst16; + unsigned char *dst8; + int index; + + if (dev->depth == clientCon->rdp_bpp) + { + memcpy(dst, src, num_pixels * dev->Bpp); + return 0; + } + + if (dev->depth == 24) + { + src32 = (unsigned int *)src; + + if (clientCon->rdp_bpp == 24) + { + dst32 = (unsigned int *)dst; + + for (index = 0; index < num_pixels; index++) + { + pixel = *src32; + *dst32 = pixel; + dst32++; + src32++; + } + } + else if (clientCon->rdp_bpp == 16) + { + dst16 = (unsigned short *)dst; + + for (index = 0; index < num_pixels; index++) + { + pixel = *src32; + SPLITCOLOR32(red, green, blue, pixel); + pixel = COLOR16(red, green, blue); + *dst16 = pixel; + dst16++; + src32++; + } + } + else if (clientCon->rdp_bpp == 15) + { + dst16 = (unsigned short *)dst; + + for (index = 0; index < num_pixels; index++) + { + pixel = *src32; + SPLITCOLOR32(red, green, blue, pixel); + pixel = COLOR15(red, green, blue); + *dst16 = pixel; + dst16++; + src32++; + } + } + else if (clientCon->rdp_bpp == 8) + { + dst8 = (unsigned char *)dst; + + for (index = 0; index < num_pixels; index++) + { + pixel = *src32; + SPLITCOLOR32(red, green, blue, pixel); + pixel = COLOR8(red, green, blue); + *dst8 = pixel; + dst8++; + src32++; + } + } + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConAlphaPixels(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 +rdpClientConSetFgcolor(rdpPtr dev, rdpClientCon *clientCon, int fgcolor) +{ + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConSetFgcolor:")); + rdpClientConPreCheck(dev, clientCon, 8); + out_uint16_le(clientCon->out_s, 12); /* set fgcolor */ + out_uint16_le(clientCon->out_s, 8); /* size */ + clientCon->count++; + fgcolor = fgcolor & dev->Bpp_mask; + fgcolor = rdpClientConConvertPixel(dev, clientCon, fgcolor) & + clientCon->rdp_Bpp_mask; + out_uint32_le(clientCon->out_s, fgcolor); + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConSetBgcolor(rdpPtr dev, rdpClientCon *clientCon, int bgcolor) +{ + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConSetBgcolor:")); + rdpClientConPreCheck(dev, clientCon, 8); + out_uint16_le(clientCon->out_s, 13); /* set bg color */ + out_uint16_le(clientCon->out_s, 8); /* size */ + clientCon->count++; + bgcolor = bgcolor & dev->Bpp_mask; + bgcolor = rdpClientConConvertPixel(dev, clientCon, bgcolor) & + clientCon->rdp_Bpp_mask; + out_uint32_le(clientCon->out_s, bgcolor); + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConSetOpcode(rdpPtr dev, rdpClientCon *clientCon, int opcode) +{ + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConSetOpcode:")); + rdpClientConPreCheck(dev, clientCon, 6); + out_uint16_le(clientCon->out_s, 14); /* set opcode */ + out_uint16_le(clientCon->out_s, 6); /* size */ + clientCon->count++; + out_uint16_le(clientCon->out_s, g_rdp_opcodes[opcode & 0xf]); + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConSetPen(rdpPtr dev, rdpClientCon *clientCon, int style, int width) +{ + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConSetPen:")); + rdpClientConPreCheck(dev, clientCon, 8); + out_uint16_le(clientCon->out_s, 17); /* set pen */ + out_uint16_le(clientCon->out_s, 8); /* size */ + clientCon->count++; + out_uint16_le(clientCon->out_s, style); + out_uint16_le(clientCon->out_s, width); + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConDrawLine(rdpPtr dev, rdpClientCon *clientCon, + short x1, short y1, short x2, short y2) +{ + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConDrawLine:")); + rdpClientConPreCheck(dev, clientCon, 12); + out_uint16_le(clientCon->out_s, 18); /* draw line */ + out_uint16_le(clientCon->out_s, 12); /* size */ + clientCon->count++; + out_uint16_le(clientCon->out_s, x1); + out_uint16_le(clientCon->out_s, y1); + out_uint16_le(clientCon->out_s, x2); + out_uint16_le(clientCon->out_s, y2); + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConSetCursor(rdpPtr dev, rdpClientCon *clientCon, + short x, short y, char *cur_data, char *cur_mask) +{ + int size; + + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConSetCursor:")); + size = 8 + 32 * (32 * 3) + 32 * (32 / 8); + rdpClientConPreCheck(dev, clientCon, size); + out_uint16_le(clientCon->out_s, 19); /* set cursor */ + out_uint16_le(clientCon->out_s, size); /* size */ + clientCon->count++; + x = RDPMAX(0, x); + x = RDPMIN(31, x); + y = RDPMAX(0, y); + y = RDPMIN(31, y); + out_uint16_le(clientCon->out_s, x); + out_uint16_le(clientCon->out_s, y); + out_uint8a(clientCon->out_s, cur_data, 32 * (32 * 3)); + out_uint8a(clientCon->out_s, cur_mask, 32 * (32 / 8)); + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConSetCursorEx(rdpPtr dev, rdpClientCon *clientCon, + short x, short y, char *cur_data, + char *cur_mask, int bpp) +{ + int size; + int Bpp; + + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConSetCursorEx:")); + Bpp = (bpp == 0) ? 3 : (bpp + 7) / 8; + size = 10 + 32 * (32 * Bpp) + 32 * (32 / 8); + rdpClientConPreCheck(dev, clientCon, size); + out_uint16_le(clientCon->out_s, 51); /* set cursor ex */ + out_uint16_le(clientCon->out_s, size); /* size */ + clientCon->count++; + x = RDPMAX(0, x); + x = RDPMIN(31, x); + y = RDPMAX(0, y); + y = RDPMIN(31, y); + out_uint16_le(clientCon->out_s, x); + out_uint16_le(clientCon->out_s, y); + out_uint16_le(clientCon->out_s, bpp); + out_uint8a(clientCon->out_s, cur_data, 32 * (32 * Bpp)); + out_uint8a(clientCon->out_s, cur_mask, 32 * (32 / 8)); + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConCreateOsSurface(rdpPtr dev, rdpClientCon *clientCon, + int rdpindex, int width, int height) +{ + LLOGLN(10, ("rdpClientConCreateOsSurface:")); + + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConCreateOsSurface: width %d height %d", width, height)); + rdpClientConPreCheck(dev, clientCon, 12); + out_uint16_le(clientCon->out_s, 20); + out_uint16_le(clientCon->out_s, 12); + clientCon->count++; + out_uint32_le(clientCon->out_s, rdpindex); + out_uint16_le(clientCon->out_s, width); + out_uint16_le(clientCon->out_s, height); + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConCreateOsSurfaceBpp(rdpPtr dev, rdpClientCon *clientCon, + int rdpindex, int width, int height, int bpp) +{ + LLOGLN(10, ("rdpClientConCreateOsSurfaceBpp:")); + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConCreateOsSurfaceBpp: width %d height %d " + "bpp %d", width, height, bpp)); + rdpClientConPreCheck(dev, clientCon, 13); + out_uint16_le(clientCon->out_s, 31); + out_uint16_le(clientCon->out_s, 13); + clientCon->count++; + out_uint32_le(clientCon->out_s, rdpindex); + out_uint16_le(clientCon->out_s, width); + out_uint16_le(clientCon->out_s, height); + out_uint8(clientCon->out_s, bpp); + } + return 0; +} + +/******************************************************************************/ +int +rdpClientConSwitchOsSurface(rdpPtr dev, rdpClientCon *clientCon, int rdpindex) +{ + LLOGLN(10, ("rdpClientConSwitchOsSurface:")); + + if (clientCon->connected) + { + if (clientCon->rdpIndex == rdpindex) + { + return 0; + } + + clientCon->rdpIndex = rdpindex; + LLOGLN(10, ("rdpClientConSwitchOsSurface: rdpindex %d", rdpindex)); + /* switch surface */ + rdpClientConPreCheck(dev, clientCon, 8); + out_uint16_le(clientCon->out_s, 21); + out_uint16_le(clientCon->out_s, 8); + out_uint32_le(clientCon->out_s, rdpindex); + clientCon->count++; + } + + return 0; +} + +/******************************************************************************/ +int +rdpClientConDeleteOsSurface(rdpPtr dev, rdpClientCon *clientCon, int rdpindex) +{ + LLOGLN(10, ("rdpClientConDeleteOsSurface: rdpindex %d", rdpindex)); + + if (clientCon->connected) + { + LLOGLN(10, ("rdpClientConDeleteOsSurface: rdpindex %d", rdpindex)); + rdpClientConPreCheck(dev, clientCon, 8); + out_uint16_le(clientCon->out_s, 22); + out_uint16_le(clientCon->out_s, 8); + clientCon->count++; + out_uint32_le(clientCon->out_s, rdpindex); + } + + return 0; +} + +/*****************************************************************************/ +/* returns -1 on error */ +int +rdpClientConAddOsBitmap(rdpPtr dev, rdpClientCon *clientCon, + PixmapPtr pixmap, rdpPixmapPtr priv) +{ + int index; + int rv; + int oldest; + int oldest_index; + int this_bytes; + + LLOGLN(10, ("rdpClientConAddOsBitmap:")); + if (clientCon->connected == FALSE) + { + LLOGLN(10, ("rdpClientConAddOsBitmap: test error 1")); + return -1; + } + + if (clientCon->osBitmaps == NULL) + { + LLOGLN(10, ("rdpClientConAddOsBitmap: test error 2")); + return -1; + } + + this_bytes = pixmap->devKind * pixmap->drawable.height; + if (this_bytes > MAX_OS_BYTES) + { + LLOGLN(10, ("rdpClientConAddOsBitmap: 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; + + while (index < clientCon->maxOsBitmaps) + { + if (clientCon->osBitmaps[index].used == FALSE) + { + clientCon->osBitmaps[index].used = TRUE; + clientCon->osBitmaps[index].pixmap = pixmap; + clientCon->osBitmaps[index].priv = priv; + clientCon->osBitmaps[index].stamp = clientCon->osBitmapStamp; + clientCon->osBitmapStamp++; + clientCon->osBitmapNumUsed++; + rv = index; + break; + } + else + { + if (clientCon->osBitmaps[index].stamp < oldest) + { + oldest = clientCon->osBitmaps[index].stamp; + oldest_index = index; + } + } + index++; + } + + if (rv == -1) + { + if (oldest_index == -1) + { + LLOGLN(0, ("rdpClientConAddOsBitmap: error")); + } + else + { + LLOGLN(10, ("rdpClientConAddOsBitmap: too many pixmaps removing " + "oldest_index %d", oldest_index)); + rdpClientConRemoveOsBitmap(dev, clientCon, oldest_index); + rdpClientConDeleteOsSurface(dev, clientCon, oldest_index); + clientCon->osBitmaps[oldest_index].used = TRUE; + clientCon->osBitmaps[oldest_index].pixmap = pixmap; + clientCon->osBitmaps[oldest_index].priv = priv; + clientCon->osBitmaps[oldest_index].stamp = clientCon->osBitmapStamp; + clientCon->osBitmapStamp++; + clientCon->osBitmapNumUsed++; + rv = oldest_index; + } + } + + if (rv < 0) + { + LLOGLN(10, ("rdpClientConAddOsBitmap: test error 3")); + return rv; + } + + clientCon->osBitmapAllocSize += this_bytes; + LLOGLN(10, ("rdpClientConAddOsBitmap: this_bytes %d " + "clientCon->osBitmapAllocSize %d", + this_bytes, clientCon->osBitmapAllocSize)); +#if USE_MAX_OS_BYTES + while (clientCon->osBitmapAllocSize > MAX_OS_BYTES) + { + LLOGLN(10, ("rdpClientConAddOsBitmap: must delete " + "clientCon->osBitmapNumUsed %d", + clientCon->osBitmapNumUsed)); + /* find oldest */ + oldest = 0x7fffffff; + oldest_index = -1; + index = 0; + while (index < clientCon->maxOsBitmaps) + { + if (clientCon->osBitmaps[index].used && + (clientCon->osBitmaps[index].stamp < oldest)) + { + oldest = clientCon->osBitmaps[index].stamp; + oldest_index = index; + } + index++; + } + if (oldest_index == -1) + { + LLOGLN(0, ("rdpClientConAddOsBitmap: error 1")); + break; + } + if (oldest_index == rv) + { + LLOGLN(0, ("rdpClientConAddOsBitmap: error 2")); + break; + } + rdpClientConRemoveOsBitmap(dev, clientCon, oldest_index); + rdpClientConDeleteOsSurface(dev, clientCon, oldest_index); + } +#endif + LLOGLN(10, ("rdpClientConAddOsBitmap: new bitmap index %d", rv)); + LLOGLN(10, ("rdpClientConAddOsBitmap: clientCon->osBitmapNumUsed %d " + "clientCon->osBitmapStamp 0x%8.8x", + clientCon->osBitmapNumUsed, clientCon->osBitmapStamp)); + return rv; +} + +/*****************************************************************************/ +int +rdpClientConRemoveOsBitmap(rdpPtr dev, rdpClientCon *clientCon, int rdpindex) +{ + PixmapPtr pixmap; + rdpPixmapPtr priv; + int this_bytes; + + if (clientCon->osBitmaps == NULL) + { + LLOGLN(10, ("rdpClientConRemoveOsBitmap: test error 1")); + return 1; + } + + LLOGLN(10, ("rdpClientConRemoveOsBitmap: index %d stamp %d", + rdpindex, clientCon->osBitmaps[rdpindex].stamp)); + + if ((rdpindex < 0) && (rdpindex >= clientCon->maxOsBitmaps)) + { + LLOGLN(10, ("rdpClientConRemoveOsBitmap: test error 2")); + return 1; + } + + if (clientCon->osBitmaps[rdpindex].used) + { + pixmap = clientCon->osBitmaps[rdpindex].pixmap; + priv = clientCon->osBitmaps[rdpindex].priv; + rdpDrawItemRemoveAll(dev, priv); + this_bytes = pixmap->devKind * pixmap->drawable.height; + clientCon->osBitmapAllocSize -= this_bytes; + LLOGLN(10, ("rdpClientConRemoveOsBitmap: this_bytes %d " + "clientCon->osBitmapAllocSize %d", this_bytes, + clientCon->osBitmapAllocSize)); + clientCon->osBitmaps[rdpindex].used = 0; + clientCon->osBitmaps[rdpindex].pixmap = 0; + clientCon->osBitmaps[rdpindex].priv = 0; + clientCon->osBitmapNumUsed--; + 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: clientCon->osBitmapNumUsed %d", + clientCon->osBitmapNumUsed)); + return 0; +} + +/*****************************************************************************/ +int +rdpClientConUpdateOsUse(rdpPtr dev, rdpClientCon *clientCon, int rdpindex) +{ + if (clientCon->osBitmaps == NULL) + { + return 1; + } + + LLOGLN(10, ("rdpClientConUpdateOsUse: index %d stamp %d", + rdpindex, clientCon->osBitmaps[rdpindex].stamp)); + + if ((rdpindex < 0) && (rdpindex >= clientCon->maxOsBitmaps)) + { + return 1; + } + + if (clientCon->osBitmaps[rdpindex].used) + { + clientCon->osBitmaps[rdpindex].stamp = clientCon->osBitmapStamp; + clientCon->osBitmapStamp++; + } + else + { + LLOGLN(0, ("rdpClientConUpdateOsUse: error rdpindex %d", rdpindex)); + } + + return 0; +} + +/******************************************************************************/ +static CARD32 +rdpClientConDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg) +{ + rdpPtr dev; + rdpClientCon *clientCon; + + LLOGLN(10, ("rdpClientConDeferredUpdateCallback")); + + dev = (rdpPtr) arg; + clientCon = dev->clientConHead; + while (clientCon != NULL) + { + if (dev->do_dirty_ons) + { + if (clientCon->rectId == clientCon->rectIdAck) + { + rdpClientConCheckDirtyScreen(dev, clientCon); + } + else + { + LLOGLN(0, ("rdpClientConDeferredUpdateCallback: skipping")); + } + } + else + { + rdpClientConSendPending(dev, clientCon); + } + clientCon = clientCon->next; + } + dev->sendUpdateScheduled = FALSE; + return 0; +} + +/******************************************************************************/ +void +rdpClientConScheduleDeferredUpdate(rdpPtr dev) +{ + if (dev->sendUpdateScheduled == FALSE) + { + dev->sendUpdateScheduled = TRUE; + dev->sendUpdateTimer = + TimerSet(dev->sendUpdateTimer, 0, 40, + rdpClientConDeferredUpdateCallback, dev); + } +} + +/******************************************************************************/ +int +rdpClientConCheckDirtyScreen(rdpPtr dev, rdpClientCon *clientCon) +{ + return 0; +} + +/******************************************************************************/ +static int +rdpClientConSendPaintRectShmEx(rdpPtr dev, rdpClientCon *clientCon, + struct image_data *id, + RegionPtr dirtyReg, RegionPtr copyReg) +{ + int index; + int size; + int num_rects_d; + int num_rects_c; + struct stream *s; + BoxRec box; + + rdpClientConBeginUpdate(dev, clientCon); + + num_rects_d = REGION_NUM_RECTS(dirtyReg); + num_rects_c = REGION_NUM_RECTS(copyReg); + size = 2 + 2 + 2 + num_rects_d * 8 + 2 + num_rects_c * 8; + size += 4 + 4 + 4 + 4 + 2 + 2; + rdpClientConPreCheck(dev, clientCon, size); + + s = clientCon->out_s; + out_uint16_le(s, 61); + out_uint16_le(s, size); + clientCon->count++; + + out_uint16_le(s, num_rects_d); + for (index = 0; index < num_rects_d; index++) + { + box = REGION_RECTS(dirtyReg)[index]; + out_uint16_le(s, box.x1); + out_uint16_le(s, box.y1); + out_uint16_le(s, box.x2 - box.x1); + out_uint16_le(s, box.y2 - box.y1); + } + + out_uint16_le(s, num_rects_c); + for (index = 0; index < num_rects_c; index++) + { + box = REGION_RECTS(copyReg)[index]; + out_uint16_le(s, box.x1); + out_uint16_le(s, box.y1); + out_uint16_le(s, box.x2 - box.x1); + out_uint16_le(s, box.y2 - box.y1); + } + + out_uint32_le(s, 0); + clientCon->rect_id++; + out_uint32_le(s, clientCon->rect_id); + out_uint32_le(s, id->shmem_id); + out_uint32_le(s, id->shmem_offset); + out_uint16_le(s, clientCon->rdp_width); + out_uint16_le(s, clientCon->rdp_height); + + rdpClientConEndUpdate(dev, clientCon); + + return 0; +} + +/******************************************************************************/ +static CARD32 +rdpDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg) +{ + rdpClientCon *clientCon; + RegionRec reg; + struct image_data id; + + LLOGLN(10, ("rdpDeferredUpdateCallback:")); + clientCon = (rdpClientCon *) arg; + + if (clientCon->rect_id != clientCon->rect_id_ack) + { + LLOGLN(0, ("rdpDeferredUpdateCallback: reschedual")); + clientCon->updateTimer = TimerSet(clientCon->updateTimer, 0, 40, + rdpDeferredUpdateCallback, clientCon); + return 0; + } + else + { + LLOGLN(10, ("rdpDeferredUpdateCallback: sending")); + } + rdpClientConGetScreenImageRect(clientCon->dev, clientCon, &id); + LLOGLN(10, ("rdpDeferredUpdateCallback: rdp_width %d rdp_height %d " + "rdp_Bpp %d screen width %d screen height %d", + clientCon->rdp_width, clientCon->rdp_height, clientCon->rdp_Bpp, + id.width, id.height)); + clientCon->updateSchedualed = FALSE; + rdpRegionInit(®, NullBox, 0); + rdpCapture(clientCon->dirtyRegion, ®, + id.pixels, id.width, id.height, + id.lineBytes, XRDP_a8r8g8b8, + id.shmem_pixels, clientCon->rdp_width, clientCon->rdp_height, + clientCon->rdp_width * clientCon->rdp_Bpp , XRDP_a8r8g8b8, 0); + rdpClientConSendPaintRectShmEx(clientCon->dev, clientCon, &id, + clientCon->dirtyRegion, ®); + rdpRegionDestroy(clientCon->dirtyRegion); + clientCon->dirtyRegion = rdpRegionCreate(NullBox, 0); + rdpRegionUninit(®); + return 0; +} + +/******************************************************************************/ +int +rdpClientConAddDirtyScreenReg(rdpPtr dev, rdpClientCon *clientCon, + RegionPtr reg) +{ + LLOGLN(10, ("rdpClientConAddDirtyScreenReg:")); + + rdpRegionUnion(clientCon->dirtyRegion, clientCon->dirtyRegion, reg); + if (clientCon->updateSchedualed == FALSE) + { + clientCon->updateTimer = TimerSet(clientCon->updateTimer, 0, 40, + rdpDeferredUpdateCallback, clientCon); + clientCon->updateSchedualed = TRUE; + } + return 0; +} + +/******************************************************************************/ +int +rdpClientConAddDirtyScreenBox(rdpPtr dev, rdpClientCon *clientCon, + BoxPtr box) +{ + RegionPtr reg; + + reg = rdpRegionCreate(box, 0); + rdpClientConAddDirtyScreenReg(dev, clientCon, reg); + rdpRegionDestroy(reg); + return 0; +} + +/******************************************************************************/ +int +rdpClientConAddDirtyScreen(rdpPtr dev, rdpClientCon *clientCon, + int x, int y, int cx, int cy) +{ + BoxRec box; + + box.x1 = x; + box.y1 = y; + box.x2 = box.x1 + cx; + box.y2 = box.y1 + cy; + rdpClientConAddDirtyScreenBox(dev, clientCon, &box); + return 0; +} + +/******************************************************************************/ +void +rdpClientConGetScreenImageRect(rdpPtr dev, rdpClientCon *clientCon, + struct image_data *id) +{ + id->width = dev->width; + id->height = dev->height; + id->bpp = clientCon->rdp_bpp; + id->Bpp = clientCon->rdp_Bpp; + id->lineBytes = dev->paddedWidthInBytes; + id->pixels = dev->pfbMemory; + id->shmem_pixels = clientCon->shmemptr; + id->shmem_id = clientCon->shmemid; + id->shmem_offset = 0; + id->shmem_lineBytes = clientCon->shmem_lineBytes; +} + +/******************************************************************************/ +void +rdpClientConGetPixmapImageRect(rdpPtr dev, rdpClientCon *clientCon, + PixmapPtr pPixmap, struct image_data *id) +{ + id->width = pPixmap->drawable.width; + id->height = pPixmap->drawable.height; + id->bpp = clientCon->rdp_bpp; + id->Bpp = clientCon->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; +} + +/******************************************************************************/ +void +rdpClientConSendArea(rdpPtr dev, rdpClientCon *clientCon, + struct image_data *id, int x, int y, int w, int h) +{ + struct image_data lid; + BoxRec box; + int ly; + int size; + char *src; + char *dst; + struct stream *s; + + LLOGLN(10, ("rdpClientConSendArea: id %p x %d y %d w %d h %d", id, x, y, w, h)); + + if (id == NULL) + { + rdpClientConGetScreenImageRect(dev, clientCon, &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; + } + + if (clientCon->connected && clientCon->begin) + { + if (id->shmem_pixels != 0) + { + LLOGLN(10, ("rdpClientConSendArea: using shmem")); + box.x1 = x; + box.y1 = y; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + src = id->pixels; + src += y * id->lineBytes; + src += x * dev->Bpp; + dst = id->shmem_pixels + id->shmem_offset; + dst += y * id->shmem_lineBytes; + dst += x * clientCon->rdp_Bpp; + ly = y; + while (ly < y + h) + { + rdpClientConConvertPixels(dev, clientCon, src, dst, w); + src += id->lineBytes; + dst += id->shmem_lineBytes; + ly += 1; + } + size = 36; + rdpClientConPreCheck(dev, clientCon, size); + s = clientCon->out_s; + out_uint16_le(s, 60); + out_uint16_le(s, size); + clientCon->count++; + LLOGLN(10, ("rdpClientConSendArea: 2 x %d y %d w %d h %d", x, y, w, h)); + out_uint16_le(s, x); + out_uint16_le(s, y); + out_uint16_le(s, w); + out_uint16_le(s, h); + out_uint32_le(s, 0); + clientCon->rect_id++; + out_uint32_le(s, clientCon->rect_id); + out_uint32_le(s, id->shmem_id); + out_uint32_le(s, id->shmem_offset); + out_uint16_le(s, id->width); + out_uint16_le(s, id->height); + out_uint16_le(s, x); + out_uint16_le(s, y); + rdpRegionUnionRect(clientCon->shmRegion, &box); + return; + } + } +} + +/******************************************************************************/ +int +rdpClientConAddAllReg(rdpPtr dev, RegionPtr reg, DrawablePtr pDrawable) +{ + rdpClientCon *clientCon; + Bool drw_is_vis; + + drw_is_vis = XRDP_DRAWABLE_IS_VISIBLE(dev, pDrawable); + if (!drw_is_vis) + { + return 0; + } + clientCon = dev->clientConHead; + while (clientCon != NULL) + { + rdpClientConAddDirtyScreenReg(dev, clientCon, reg); + clientCon = clientCon->next; + } + return 0; +} + +/******************************************************************************/ +int +rdpClientConAddAllBox(rdpPtr dev, BoxPtr box, DrawablePtr pDrawable) +{ + rdpClientCon *clientCon; + Bool drw_is_vis; + + drw_is_vis = XRDP_DRAWABLE_IS_VISIBLE(dev, pDrawable); + if (!drw_is_vis) + { + return 0; + } + clientCon = dev->clientConHead; + while (clientCon != NULL) + { + rdpClientConAddDirtyScreenBox(dev, clientCon, box); + clientCon = clientCon->next; + } + return 0; +} diff --git a/xorg/server/module/rdpClientCon.h b/xorg/server/module/rdpClientCon.h index 85a3925a..9cbe493a 100644 --- a/xorg/server/module/rdpClientCon.h +++ b/xorg/server/module/rdpClientCon.h @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -21,24 +21,141 @@ Client connection to xrdp */ +/* in xrdp/common */ +#include "xrdp_client_info.h" +#include "xrdp_constants.h" + #ifndef _RDPCLIENTCON_H #define _RDPCLIENTCON_H +/* used in rdpGlyphs.c */ +struct font_cache +{ + int offset; + int baseline; + int width; + int height; + int crc; + int stamp; +}; + +struct rdpup_os_bitmap +{ + int used; + PixmapPtr pixmap; + rdpPixmapPtr priv; + int stamp; +}; + +/* one of these for each client */ struct _rdpClientCon { + rdpPtr dev; + int sck; int sckControlListener; int sckControl; struct stream *out_s; struct stream *in_s; + + int rectIdAck; + int rectId; + int connected; /* boolean */ + int begin; /* boolean */ + int count; + int sckClosed; /* boolean */ + struct rdpup_os_bitmap *osBitmaps; + int maxOsBitmaps; + int osBitmapStamp; + int osBitmapAllocSize; + int osBitmapNumUsed; + int doComposite; + int doGlyphCache; + int canDoPixToPix; + int doMultimon; + + int rdp_bpp; /* client depth */ + int rdp_Bpp; + int rdp_Bpp_mask; + int rdp_width; + int rdp_height; + + int rdpIndex; /* current os target */ + + int conNumber; + + /* rdpGlyphs.c */ + struct font_cache font_cache[12][256]; + int font_stamp; + + RegionPtr dirtyRegion; + + struct xrdp_client_info client_info; + + char *shmemptr; + int shmemid; + int shmem_lineBytes; + RegionPtr shmRegion; + int rect_id; + int rect_id_ack; + + OsTimerPtr updateTimer; + int updateSchedualed; /* boolean */ + struct _rdpClientCon *next; }; int +rdpClientConBeginUpdate(rdpPtr dev, rdpClientCon *clientCon); +int +rdpClientConEndUpdate(rdpPtr dev, rdpClientCon *clientCon); +int +rdpClientConSetFgcolor(rdpPtr dev, rdpClientCon *clientCon, int fgcolor); +void +rdpClientConSendArea(rdpPtr dev, rdpClientCon *clientCon, + struct image_data *id, int x, int y, int w, int h); +int +rdpClientConFillRect(rdpPtr dev, rdpClientCon *clientCon, + short x, short y, int cx, int cy); +int rdpClientConCheck(ScreenPtr pScreen); int rdpClientConInit(rdpPtr dev); int rdpClientConDeinit(rdpPtr dev); +int +rdpClientConDeleteOsSurface(rdpPtr dev, rdpClientCon *clientCon, int rdpindex); + +int +rdpClientConRemoveOsBitmap(rdpPtr dev, rdpClientCon *clientCon, int rdpindex); + +void +rdpClientConScheduleDeferredUpdate(rdpPtr dev); +int +rdpClientConCheckDirtyScreen(rdpPtr dev, rdpClientCon *clientCon); +int +rdpClientConAddDirtyScreenReg(rdpPtr dev, rdpClientCon *clientCon, + RegionPtr reg); +int +rdpClientConAddDirtyScreenBox(rdpPtr dev, rdpClientCon *clientCon, + BoxPtr box); +int +rdpClientConAddDirtyScreen(rdpPtr dev, rdpClientCon *clientCon, + int x, int y, int cx, int cy); +void +rdpClientConGetScreenImageRect(rdpPtr dev, rdpClientCon *clientCon, + struct image_data *id); +int +rdpClientConAddAllReg(rdpPtr dev, RegionPtr reg, DrawablePtr pDrawable); +int +rdpClientConAddAllBox(rdpPtr dev, BoxPtr box, DrawablePtr pDrawable); +int +rdpClientConSetCursor(rdpPtr dev, rdpClientCon *clientCon, + short x, short y, char *cur_data, char *cur_mask); +int +rdpClientConSetCursorEx(rdpPtr dev, rdpClientCon *clientCon, + short x, short y, char *cur_data, + char *cur_mask, int bpp); + #endif diff --git a/xorg/server/module/rdpComposite.c b/xorg/server/module/rdpComposite.c index 8776335b..7535d6c3 100644 --- a/xorg/server/module/rdpComposite.c +++ b/xorg/server/module/rdpComposite.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -32,11 +32,14 @@ composite(alpha blending) calls #include <xf86.h> #include <xf86_OSproc.h> +#include "mipict.h" #include <picture.h> #include "rdp.h" -#include "rdpComposite.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" +#include "rdpComposite.h" /******************************************************************************/ #define LOG_LEVEL 1 @@ -65,11 +68,26 @@ rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, ScreenPtr pScreen; rdpPtr dev; PictureScreenPtr ps; + BoxRec box; + RegionRec reg; LLOGLN(10, ("rdpComposite:")); - pScreen = pSrc->pDrawable->pScreen; + pScreen = pDst->pDrawable->pScreen; dev = rdpGetDevFromScreen(pScreen); + dev->counts.rdpCompositeCallCount++; + box.x1 = xDst + pDst->pDrawable->x; + box.y1 = yDst + pDst->pDrawable->y; + box.x2 = box.x1 + width; + box.y2 = box.y1 + height; + rdpRegionInit(®, &box, 0); + if (pDst->pCompositeClip != NULL) + { + rdpRegionIntersect(®, pDst->pCompositeClip, ®); + } ps = GetPictureScreen(pScreen); + /* do original call */ rdpCompositeOrg(ps, dev, op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); + rdpClientConAddAllReg(dev, ®, pDst->pDrawable); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpComposite.h b/xorg/server/module/rdpComposite.h index 8924c1b4..017cb41d 100644 --- a/xorg/server/module/rdpComposite.h +++ b/xorg/server/module/rdpComposite.h @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpCopyArea.c b/xorg/server/module/rdpCopyArea.c index 91df1896..708891f6 100644 --- a/xorg/server/module/rdpCopyArea.c +++ b/xorg/server/module/rdpCopyArea.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -32,6 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -56,10 +58,35 @@ RegionPtr rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty) { + rdpPtr dev; RegionPtr rv; + RegionRec clip_reg; + RegionRec reg; + int cd; + BoxRec box; LLOGLN(10, ("rdpCopyArea:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpCopyAreaCallCount++; + box.x1 = dstx + pDst->x; + box.y1 = dsty + pDst->y; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + rdpRegionInit(®, &box, 0); + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDst, pGC); + LLOGLN(10, ("rdpCopyArea: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rv = rdpCopyAreaOrg(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDst); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); return rv; } diff --git a/xorg/server/module/rdpCopyPlane.c b/xorg/server/module/rdpCopyPlane.c index fb7c22b8..9ccf4c0a 100644 --- a/xorg/server/module/rdpCopyPlane.c +++ b/xorg/server/module/rdpCopyPlane.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -32,6 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -60,10 +62,35 @@ rdpCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, int dstx, int dsty, unsigned long bitPlane) { RegionPtr rv; + rdpPtr dev; + RegionRec clip_reg; + RegionRec reg; + int cd; + BoxRec box; LLOGLN(10, ("rdpCopyPlane:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpCopyPlaneCallCount++; + box.x1 = pDst->x + dstx; + box.y1 = pDst->y + dsty; + box.x2 = box.x1 + w; + box.y2 = box.x1 + h; + rdpRegionInit(®, &box, 0); + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDst, pGC); + LLOGLN(10, ("rdpCopyPlane: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rv = rdpCopyPlaneOrg(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, bitPlane); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDst); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); return rv; } diff --git a/xorg/server/module/rdpCopyPlane.h b/xorg/server/module/rdpCopyPlane.h index 85a79e76..6abd0293 100644 --- a/xorg/server/module/rdpCopyPlane.h +++ b/xorg/server/module/rdpCopyPlane.h @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpCursor.c b/xorg/server/module/rdpCursor.c index 1e5ad311..3859e8e7 100644 --- a/xorg/server/module/rdpCursor.c +++ b/xorg/server/module/rdpCursor.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -36,9 +36,50 @@ cursor #include <fb.h> #include <micmap.h> #include <mi.h> +#include <cursor.h> +#include <cursorstr.h> #include "rdp.h" #include "rdpMain.h" +#include "rdpDraw.h" +#include "rdpClientCon.h" + +/* Copied from Xvnc/lib/font/util/utilbitmap.c */ +static unsigned char g_reverse_byte[0x100] = +{ + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff +}; /******************************************************************************/ #define LOG_LEVEL 1 @@ -49,7 +90,7 @@ cursor Bool rdpSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScr, CursorPtr pCurs) { - LLOGLN(0, ("rdpSpriteRealizeCursor:")); + LLOGLN(10, ("rdpSpriteRealizeCursor:")); return TRUE; } @@ -57,30 +98,244 @@ rdpSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScr, CursorPtr pCurs) Bool rdpSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScr, CursorPtr pCurs) { - LLOGLN(0, ("rdpSpriteUnrealizeCursor:")); + LLOGLN(10, ("rdpSpriteUnrealizeCursor:")); return TRUE; } /******************************************************************************/ +static int +get_pixel_safe(char *data, int x, int y, int width, int height, int bpp) +{ + int start; + int shift; + int c; + unsigned int *src32; + + if (x < 0) + { + return 0; + } + + if (y < 0) + { + return 0; + } + + if (x >= width) + { + return 0; + } + + if (y >= height) + { + return 0; + } + + if (bpp == 1) + { + width = (width + 7) / 8; + start = (y * width) + x / 8; + shift = x % 8; + c = (unsigned char)(data[start]); +#if (X_BYTE_ORDER == X_LITTLE_ENDIAN) + return (g_reverse_byte[c] & (0x80 >> shift)) != 0; +#else + return (c & (0x80 >> shift)) != 0; +#endif + } + else if (bpp == 32) + { + src32 = (unsigned int*)data; + return src32[y * width + x]; + } + + return 0; +} + +/******************************************************************************/ +static void +set_pixel_safe(char *data, int x, int y, int width, int height, int bpp, + int pixel) +{ + int start; + int shift; + unsigned int *dst32; + + if (x < 0) + { + return; + } + + if (y < 0) + { + return; + } + + if (x >= width) + { + return; + } + + if (y >= height) + { + return; + } + + if (bpp == 1) + { + width = (width + 7) / 8; + start = (y * width) + x / 8; + shift = x % 8; + + if (pixel & 1) + { + data[start] = data[start] | (0x80 >> shift); + } + else + { + data[start] = data[start] & ~(0x80 >> shift); + } + } + else if (bpp == 24) + { + *(data + (3 * (y * width + x)) + 0) = pixel >> 0; + *(data + (3 * (y * width + x)) + 1) = pixel >> 8; + *(data + (3 * (y * width + x)) + 2) = pixel >> 16; + } + else if (bpp == 32) + { + dst32 = (unsigned int*)data; + dst32[y * width + x] = pixel; + } +} + +/******************************************************************************/ +void +rdpSpriteSetCursorCon(rdpClientCon *clientCon, + DeviceIntPtr pDev, ScreenPtr pScr, CursorPtr pCurs, + int x, int y) +{ + char cur_data[32 * (32 * 4)]; + char cur_mask[32 * (32 / 8)]; + char *mask; + char *data; + int i; + int j; + int w; + int h; + int p; + int xhot; + int yhot; + int paddedRowBytes; + int fgcolor; + int bgcolor; + int bpp; + + LLOGLN(10, ("rdpSpriteSetCursorCon:")); + + w = pCurs->bits->width; + h = pCurs->bits->height; + if ((pCurs->bits->argb != 0) && + (clientCon->client_info.pointer_flags & 1)) + { + bpp = 32; + paddedRowBytes = PixmapBytePad(w, 32); + xhot = pCurs->bits->xhot; + yhot = pCurs->bits->yhot; + data = (char *)(pCurs->bits->argb); + memset(cur_data, 0, sizeof(cur_data)); + memset(cur_mask, 0, sizeof(cur_mask)); + + for (j = 0; j < 32; j++) + { + for (i = 0; i < 32; i++) + { + p = get_pixel_safe(data, i, j, paddedRowBytes / 4, h, 32); + set_pixel_safe(cur_data, i, 31 - j, 32, 32, 32, p); + } + } + } + else + { + bpp = 0; + paddedRowBytes = PixmapBytePad(w, 1); + xhot = pCurs->bits->xhot; + yhot = pCurs->bits->yhot; + data = (char *)(pCurs->bits->source); + mask = (char *)(pCurs->bits->mask); + fgcolor = (((pCurs->foreRed >> 8) & 0xff) << 16) | + (((pCurs->foreGreen >> 8) & 0xff) << 8) | + ((pCurs->foreBlue >> 8) & 0xff); + bgcolor = (((pCurs->backRed >> 8) & 0xff) << 16) | + (((pCurs->backGreen >> 8) & 0xff) << 8) | + ((pCurs->backBlue >> 8) & 0xff); + memset(cur_data, 0, sizeof(cur_data)); + memset(cur_mask, 0, sizeof(cur_mask)); + + for (j = 0; j < 32; j++) + { + for (i = 0; i < 32; i++) + { + p = get_pixel_safe(mask, i, j, paddedRowBytes * 8, h, 1); + set_pixel_safe(cur_mask, i, 31 - j, 32, 32, 1, !p); + + if (p != 0) + { + p = get_pixel_safe(data, i, j, paddedRowBytes * 8, h, 1); + p = p ? fgcolor : bgcolor; + set_pixel_safe(cur_data, i, 31 - j, 32, 32, 24, p); + } + } + } + } + + rdpClientConBeginUpdate(clientCon->dev, clientCon); + rdpClientConSetCursorEx(clientCon->dev, clientCon, xhot, yhot, + cur_data, cur_mask, bpp); + rdpClientConEndUpdate(clientCon->dev, clientCon); + +} + +/******************************************************************************/ void rdpSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScr, CursorPtr pCurs, int x, int y) { - LLOGLN(0, ("rdpSpriteSetCursor:")); + rdpPtr dev; + rdpClientCon *clientCon; + + LLOGLN(10, ("rdpSpriteSetCursor:")); + if (pCurs == 0) + { + return; + } + + if (pCurs->bits == 0) + { + return; + } + + dev = rdpGetDevFromScreen(pScr); + clientCon = dev->clientConHead; + while (clientCon != NULL) + { + rdpSpriteSetCursorCon(clientCon, pDev, pScr, pCurs, x, y); + clientCon = clientCon->next; + } } /******************************************************************************/ void rdpSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScr, int x, int y) { - LLOGLN(0, ("rdpSpriteMoveCursor:")); + LLOGLN(10, ("rdpSpriteMoveCursor:")); } /******************************************************************************/ Bool rdpSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScr) { - LLOGLN(0, ("rdpSpriteDeviceCursorInitialize:")); + LLOGLN(10, ("rdpSpriteDeviceCursorInitialize:")); return TRUE; } @@ -88,6 +343,6 @@ rdpSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScr) void rdpSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScr) { - LLOGLN(0, ("rdpSpriteDeviceCursorCleanup:")); + LLOGLN(10, ("rdpSpriteDeviceCursorCleanup:")); xorgxrdpDownDown(pScr); } diff --git a/xorg/server/module/rdpCursor.h b/xorg/server/module/rdpCursor.h index b847d842..10a57d70 100644 --- a/xorg/server/module/rdpCursor.h +++ b/xorg/server/module/rdpCursor.h @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpDraw.c b/xorg/server/module/rdpDraw.c index 08fe4b85..b4e689af 100644 --- a/xorg/server/module/rdpDraw.c +++ b/xorg/server/module/rdpDraw.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -27,6 +27,7 @@ misc draw calls /* this should be before all X11 .h files */ #include <xorg-server.h> +#include <xorgVersion.h> /* all driver need this */ #include <xf86.h> @@ -36,28 +37,315 @@ misc draw calls #include <fb.h> #include <micmap.h> #include <mi.h> +#include <dixfontstr.h> #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpMisc.h" +#include "rdpGlyphs.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) +/******************************************************************************/ +/* return 0, draw nothing */ +/* return 1, draw with no clip */ +/* return 2, draw using clip */ +int +rdpDrawGetClip(rdpPtr dev, RegionPtr pRegion, DrawablePtr pDrawable, GCPtr pGC) +{ + WindowPtr pWindow; + RegionPtr temp; + BoxRec box; + int rv; + + rv = 0; + + if (pDrawable->type == DRAWABLE_PIXMAP) + { + switch (pGC->clientClipType) + { + case CT_NONE: + rv = 1; + break; + case CT_REGION: + rv = 2; + rdpRegionCopy(pRegion, pGC->clientClip); + break; + default: + LLOGLN(0, ("rdpDrawGetClip: unimp clip type %d", + pGC->clientClipType)); + break; + } + + if (rv == 2) /* check if the clip is the entire pixmap */ + { + box.x1 = 0; + box.y1 = 0; + box.x2 = pDrawable->width; + box.y2 = pDrawable->height; + + if (rdpRegionContainsRect(pRegion, &box) == rgnIN) + { + rv = 1; + } + } + } + else if (pDrawable->type == DRAWABLE_WINDOW) + { + pWindow = (WindowPtr)pDrawable; + + if (pWindow->viewable) + { + if (pGC->subWindowMode == IncludeInferiors) + { + temp = &pWindow->borderClip; + } + else + { + temp = &pWindow->clipList; + } + + if (rdpRegionNotEmpty(temp)) + { + switch (pGC->clientClipType) + { + case CT_NONE: + rv = 2; + rdpRegionCopy(pRegion, temp); + break; + case CT_REGION: + rv = 2; + rdpRegionCopy(pRegion, pGC->clientClip); + rdpRegionTranslate(pRegion, + pDrawable->x + pGC->clipOrg.x, + pDrawable->y + pGC->clipOrg.y); + rdpRegionIntersect(pRegion, pRegion, temp); + break; + default: + LLOGLN(0, ("rdpDrawGetClip: unimp clip type %d", + pGC->clientClipType)); + break; + } + + if (rv == 2) /* check if the clip is the entire screen */ + { + box.x1 = 0; + box.y1 = 0; + box.x2 = dev->width; + box.y2 = dev->height; + + if (rdpRegionContainsRect(pRegion, &box) == rgnIN) + { + rv = 1; + } + } + } + } + } + + return rv; +} + +/******************************************************************************/ +void +GetTextBoundingBox(DrawablePtr pDrawable, FontPtr font, int x, int y, + int n, BoxPtr pbox) +{ + int maxAscent; + int maxDescent; + int maxCharWidth; + + if (FONTASCENT(font) > FONTMAXBOUNDS(font, ascent)) + { + maxAscent = FONTASCENT(font); + } + else + { + maxAscent = FONTMAXBOUNDS(font, ascent); + } + + if (FONTDESCENT(font) > FONTMAXBOUNDS(font, descent)) + { + maxDescent = FONTDESCENT(font); + } + else + { + maxDescent = FONTMAXBOUNDS(font, descent); + } + + if (FONTMAXBOUNDS(font, rightSideBearing) > + FONTMAXBOUNDS(font, characterWidth)) + { + maxCharWidth = FONTMAXBOUNDS(font, rightSideBearing); + } + else + { + maxCharWidth = FONTMAXBOUNDS(font, characterWidth); + } + + pbox->x1 = pDrawable->x + x; + pbox->y1 = pDrawable->y + y - maxAscent; + pbox->x2 = pbox->x1 + maxCharWidth * n; + pbox->y2 = pbox->y1 + maxAscent + maxDescent; + + if (FONTMINBOUNDS(font, leftSideBearing) < 0) + { + pbox->x1 += FONTMINBOUNDS(font, leftSideBearing); + } +} + +/******************************************************************************/ +int +rdpDrawItemAdd(rdpPtr dev, rdpPixmapRec *priv, struct rdp_draw_item *di) +{ + priv->is_alpha_dirty_not = FALSE; + + if (priv->draw_item_tail == NULL) + { + priv->draw_item_tail = di; + priv->draw_item_head = di; + } + else + { + di->prev = priv->draw_item_tail; + priv->draw_item_tail->next = di; + priv->draw_item_tail = di; + } + + if (priv == &(dev->screenPriv)) + { + rdpClientConScheduleDeferredUpdate(dev); + } + + return 0; +} + +/******************************************************************************/ +int +rdpDrawItemRemove(rdpPtr dev, rdpPixmapRec *priv, struct rdp_draw_item *di) +{ + if (di->prev != NULL) + { + di->prev->next = di->next; + } + + if (di->next != NULL) + { + di->next->prev = di->prev; + } + + if (priv->draw_item_head == di) + { + priv->draw_item_head = di->next; + } + + if (priv->draw_item_tail == di) + { + priv->draw_item_tail = di->prev; + } + + if (di->type == RDI_LINE) + { + if (di->u.line.segs != NULL) + { + g_free(di->u.line.segs); + } + } + + if (di->type == RDI_TEXT) + { + rdpGlyphDeleteRdpText(di->u.text.rtext); + } + + rdpRegionDestroy(di->reg); + g_free(di); + return 0; +} + +/******************************************************************************/ +int +rdpDrawItemRemoveAll(rdpPtr dev, rdpPixmapRec *priv) +{ + struct rdp_draw_item *di; + + di = priv->draw_item_head; + + while (di != NULL) + { + rdpDrawItemRemove(dev, priv, di); + di = priv->draw_item_head; + } + + return 0; +} + /*****************************************************************************/ void rdpCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion) { ScreenPtr pScreen; rdpPtr dev; + RegionRec reg; + RegionRec clip; + int dx; + int dy; + int num_clip_rects; + int num_reg_rects; + BoxPtr box; + BoxRec box1; + LLOGLN(10, ("rdpCopyWindow:")); pScreen = pWin->drawable.pScreen; dev = rdpGetDevFromScreen(pScreen); + dev->counts.rdpCopyWindowCallCount++; + + rdpRegionInit(®, NullBox, 0); + rdpRegionCopy(®, pOldRegion); + rdpRegionInit(&clip, NullBox, 0); + rdpRegionCopy(&clip, &pWin->borderClip); + dx = pWin->drawable.x - ptOldOrg.x; + dy = pWin->drawable.y - ptOldOrg.y; + dev->pScreen->CopyWindow = dev->CopyWindow; dev->pScreen->CopyWindow(pWin, ptOldOrg, pOldRegion); dev->pScreen->CopyWindow = rdpCopyWindow; + + num_clip_rects = REGION_NUM_RECTS(&clip); + num_reg_rects = REGION_NUM_RECTS(®); + + if ((num_clip_rects == 0) || (num_reg_rects == 0)) + { + } + else + { + if ((num_clip_rects > 16) || (num_reg_rects > 16)) + { + LLOGLN(10, ("rdpCopyWindow: big list")); + box = rdpRegionExtents(®); + box1 = *box; + box1.x1 += dx; + box1.y1 += dy; + box1.x2 += dx; + box1.y2 += dy; + rdpClientConAddAllBox(dev, &box1, &(pWin->drawable)); + } + else + { + rdpRegionTranslate(®, dx, dy); + rdpRegionIntersect(®, ®, &clip); + rdpClientConAddAllReg(dev, ®, &(pWin->drawable)); + } + } + rdpRegionUninit(®); + rdpRegionUninit(&clip); } +#if XRDP_CLOSESCR == 1 /* before v1.13 */ + /*****************************************************************************/ Bool rdpCloseScreen(int index, ScreenPtr pScreen) @@ -73,11 +361,30 @@ rdpCloseScreen(int index, ScreenPtr pScreen) return rv; } +#else + +/*****************************************************************************/ +Bool +rdpCloseScreen(ScreenPtr pScreen) +{ + rdpPtr dev; + Bool rv; + + LLOGLN(0, ("rdpCloseScreen:")); + dev = rdpGetDevFromScreen(pScreen); + dev->pScreen->CloseScreen = dev->CloseScreen; + rv = dev->pScreen->CloseScreen(pScreen); + dev->pScreen->CloseScreen = rdpCloseScreen; + return rv; +} + +#endif + /******************************************************************************/ WindowPtr rdpGetRootWindowPtr(ScreenPtr pScreen) { -#if XORG_VERSION_CURRENT < (((1) * 10000000) + ((9) * 100000) + ((0) * 1000) + 0) +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 9, 0, 0, 0) return WindowTable[pScreen->myNum]; /* in globals.c */ #else return pScreen->root; diff --git a/xorg/server/module/rdpDraw.h b/xorg/server/module/rdpDraw.h index e2711768..af65b46c 100644 --- a/xorg/server/module/rdpDraw.h +++ b/xorg/server/module/rdpDraw.h @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -25,8 +25,23 @@ misc draw calls #define __RDPDRAW_H #include <xorg-server.h> +#include <xorgVersion.h> #include <xf86.h> +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 13, 0, 0, 0) +/* 1.1, 1.2, 1.3, 1.4 1.5, 1.6, 1.7, 1.8, 1.9, 1.10, 1.11, 1.12 */ +#define XRDP_CLOSESCR 1 +#else +/* 1.13 */ +#define XRDP_CLOSESCR 2 +#endif + +/* true if drawable is window or pixmap is screen */ +#define XRDP_DRAWABLE_IS_VISIBLE(_dev, _drw) \ +(((_drw)->type == DRAWABLE_WINDOW && ((WindowPtr)(_drw))->viewable) || \ + ((_drw)->type == DRAWABLE_PIXMAP && \ + ((PixmapPtr)(_drw))->devPrivate.ptr == (_dev)->pfbMemory)) + /******************************************************************************/ #define GC_OP_VARS rdpPtr dev; rdpGCPtr priv; GCFuncs *oldFuncs @@ -50,10 +65,26 @@ do { \ extern GCOps g_rdpGCOps; /* in rdpGC.c */ +int +rdpDrawGetClip(rdpPtr dev, RegionPtr pRegion, DrawablePtr pDrawable, GCPtr pGC); +void +GetTextBoundingBox(DrawablePtr pDrawable, FontPtr font, int x, int y, + int n, BoxPtr pbox); +int +rdpDrawItemAdd(rdpPtr dev, rdpPixmapRec *priv, struct rdp_draw_item *di); +int +rdpDrawItemRemove(rdpPtr dev, rdpPixmapRec *priv, struct rdp_draw_item *di); +int +rdpDrawItemRemoveAll(rdpPtr dev, rdpPixmapRec *priv); void rdpCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion); +#if XRDP_CLOSESCR == 1 Bool rdpCloseScreen(int index, ScreenPtr pScreen); +#else +Bool +rdpCloseScreen(ScreenPtr pScreen); +#endif WindowPtr rdpGetRootWindowPtr(ScreenPtr pScreen); rdpPtr diff --git a/xorg/server/module/rdpFillPolygon.c b/xorg/server/module/rdpFillPolygon.c index 7c5a51b8..34fe4096 100644 --- a/xorg/server/module/rdpFillPolygon.c +++ b/xorg/server/module/rdpFillPolygon.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -32,6 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -56,7 +58,60 @@ rdpFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape, int mode, int count, DDXPointPtr pPts) { + rdpPtr dev; + RegionRec clip_reg; + RegionRec reg; + int cd; + int maxx; + int maxy; + int minx; + int miny; + int index; + int x; + int y; + BoxRec box; + LLOGLN(10, ("rdpFillPolygon:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpFillPolygonCallCount++; + box.x1 = 0; + box.y1 = 0; + box.x2 = 0; + box.y2 = 0; + if (count > 0) + { + maxx = pPts[0].x; + maxy = pPts[0].y; + minx = maxx; + miny = maxy; + for (index = 1; index < count; index++) + { + x = pPts[index].x; + y = pPts[index].y; + maxx = RDPMAX(x, maxx); + minx = RDPMIN(x, minx); + maxy = RDPMAX(y, maxy); + miny = RDPMIN(y, miny); + } + box.x1 = pDrawable->x + minx; + box.y1 = pDrawable->y + miny; + box.x2 = pDrawable->x + maxx + 1; + box.y2 = pDrawable->y + maxy + 1; + } + rdpRegionInit(®, &box, 0); + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpFillPolygon: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rdpFillPolygonOrg(pDrawable, pGC, shape, mode, count, pPts); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpFillPolygon.h b/xorg/server/module/rdpFillPolygon.h index 89da9ae0..cdbfb13a 100644 --- a/xorg/server/module/rdpFillPolygon.h +++ b/xorg/server/module/rdpFillPolygon.h @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpFillSpans.c b/xorg/server/module/rdpFillSpans.c index db1929fc..8e98940a 100644 --- a/xorg/server/module/rdpFillSpans.c +++ b/xorg/server/module/rdpFillSpans.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpFillSpans.h b/xorg/server/module/rdpFillSpans.h index 7e014e6b..5c1db533 100644 --- a/xorg/server/module/rdpFillSpans.h +++ b/xorg/server/module/rdpFillSpans.h @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpGC.c b/xorg/server/module/rdpGC.c index 5f34c21c..f2668f3d 100644 --- a/xorg/server/module/rdpGC.c +++ b/xorg/server/module/rdpGC.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpGC.h b/xorg/server/module/rdpGC.h index 4ad129a2..fcdd201d 100644 --- a/xorg/server/module/rdpGC.h +++ b/xorg/server/module/rdpGC.h @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpGlyphs.c b/xorg/server/module/rdpGlyphs.c index fc2d347b..e6fcbb30 100644 --- a/xorg/server/module/rdpGlyphs.c +++ b/xorg/server/module/rdpGlyphs.c @@ -1,5 +1,5 @@ /* -Copyright 2012-2013 Jay Sorg +Copyright 2012-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -38,6 +38,8 @@ gylph(font) calls #include "rdp.h" #include "rdpGlyphs.h" #include "rdpDraw.h" +#include "rdpMisc.h" +#include "rdpReg.h" /******************************************************************************/ #define LOG_LEVEL 1 @@ -45,6 +47,30 @@ gylph(font) calls do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) /******************************************************************************/ +int +rdpGlyphDeleteRdpText(struct rdp_text *rtext) +{ + int index; + + if (rtext == NULL) + { + return 0; + } + for (index = 0; index < rtext->num_chars; index++) + { + if (rtext->chars[index] != NULL) + { + g_free(rtext->chars[index]->data); + g_free(rtext->chars[index]); + } + } + rdpRegionDestroy(rtext->reg); + rdpGlyphDeleteRdpText(rtext->next); + g_free(rtext); + return 0; +} + +/******************************************************************************/ static void rdpGlyphsOrg(PictureScreenPtr ps, rdpPtr dev, CARD8 op, PicturePtr pSrc, PicturePtr pDst, @@ -70,7 +96,7 @@ rdpGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictureScreenPtr ps; LLOGLN(10, ("rdpGlyphs:")); - pScreen = pSrc->pDrawable->pScreen; + pScreen = pDst->pDrawable->pScreen; dev = rdpGetDevFromScreen(pScreen); ps = GetPictureScreen(pScreen); rdpGlyphsOrg(ps, dev, op, pSrc, pDst, maskFormat, xSrc, ySrc, diff --git a/xorg/server/module/rdpGlyphs.h b/xorg/server/module/rdpGlyphs.h index d451d9f9..0128fe7c 100644 --- a/xorg/server/module/rdpGlyphs.h +++ b/xorg/server/module/rdpGlyphs.h @@ -1,5 +1,5 @@ /* -Copyright 2012-2013 Jay Sorg +Copyright 2012-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -24,6 +24,35 @@ gylph(font) calls #ifndef _RDPGLYPHS_H #define _RDPGLYPHS_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 +rdpGlyphDeleteRdpText(struct rdp_text* rtext); void rdpGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat, diff --git a/xorg/server/module/rdpImageGlyphBlt.c b/xorg/server/module/rdpImageGlyphBlt.c index f1f03203..74693fd9 100644 --- a/xorg/server/module/rdpImageGlyphBlt.c +++ b/xorg/server/module/rdpImageGlyphBlt.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -32,13 +32,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) /******************************************************************************/ -void +static void rdpImageGlyphBltOrg(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase) @@ -56,7 +58,30 @@ rdpImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase) { - LLOGLN(10, ("rdpImageGlyphBlt:")); + rdpPtr dev; + RegionRec clip_reg; + RegionRec reg; + int cd; + BoxRec box; + + LLOGLN(0, ("rdpImageGlyphBlt:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpImageGlyphBltCallCount++; + GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box); + rdpRegionInit(®, &box, 0); + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpImageGlyphBlt: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rdpImageGlyphBltOrg(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpImageGlyphBlt.h b/xorg/server/module/rdpImageGlyphBlt.h index c5483c7e..b71e5730 100644 --- a/xorg/server/module/rdpImageGlyphBlt.h +++ b/xorg/server/module/rdpImageGlyphBlt.h @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpImageText16.c b/xorg/server/module/rdpImageText16.c index cb421158..7ad8012b 100644 --- a/xorg/server/module/rdpImageText16.c +++ b/xorg/server/module/rdpImageText16.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -32,13 +32,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) /******************************************************************************/ -void +static void rdpImageText16Org(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, unsigned short *chars) { @@ -54,7 +56,30 @@ void rdpImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, unsigned short *chars) { + rdpPtr dev; + RegionRec clip_reg; + RegionRec reg; + int cd; + BoxRec box; + LLOGLN(10, ("rdpImageText16:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpImageText16CallCount++; + GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); + rdpRegionInit(®, &box, 0); + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpImageText16: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rdpImageText16Org(pDrawable, pGC, x, y, count, chars); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpImageText16.h b/xorg/server/module/rdpImageText16.h index 0ffb90f2..b7d0a861 100644 --- a/xorg/server/module/rdpImageText16.h +++ b/xorg/server/module/rdpImageText16.h @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpImageText8.c b/xorg/server/module/rdpImageText8.c index 4bb07fe4..abcfbff0 100644 --- a/xorg/server/module/rdpImageText8.c +++ b/xorg/server/module/rdpImageText8.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -32,13 +32,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) /******************************************************************************/ -void +static void rdpImageText8Org(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, char *chars) { @@ -54,8 +56,30 @@ void rdpImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, char *chars) { + rdpPtr dev; + RegionRec clip_reg; + RegionRec reg; + int cd; + BoxRec box; + LLOGLN(10, ("rdpImageText8:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpImageText8CallCount++; + GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); + rdpRegionInit(®, &box, 0); + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpImageText8: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rdpImageText8Org(pDrawable, pGC, x, y, count, chars); - return; + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpImageText8.h b/xorg/server/module/rdpImageText8.h index dc0c4ec5..cf7dd1bb 100644 --- a/xorg/server/module/rdpImageText8.h +++ b/xorg/server/module/rdpImageText8.h @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpInput.c b/xorg/server/module/rdpInput.c index a7bafd08..f19b2947 100644 --- a/xorg/server/module/rdpInput.c +++ b/xorg/server/module/rdpInput.c @@ -1,5 +1,5 @@ /* -Copyright 2013 Jay Sorg +Copyright 2013-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpInput.h b/xorg/server/module/rdpInput.h index 19315026..c0991ace 100644 --- a/xorg/server/module/rdpInput.h +++ b/xorg/server/module/rdpInput.h @@ -1,5 +1,5 @@ /* -Copyright 2013 Jay Sorg +Copyright 2013-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpMain.c b/xorg/server/module/rdpMain.c index f19b06cd..a8786ac2 100644 --- a/xorg/server/module/rdpMain.c +++ b/xorg/server/module/rdpMain.c @@ -1,5 +1,5 @@ /* -Copyright 2013 Jay Sorg +Copyright 2013-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpMain.h b/xorg/server/module/rdpMain.h index 0b9f7bb0..2d2cfbe1 100644 --- a/xorg/server/module/rdpMain.h +++ b/xorg/server/module/rdpMain.h @@ -1,5 +1,5 @@ /* -Copyright 2013 Jay Sorg +Copyright 2013-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpMisc.c b/xorg/server/module/rdpMisc.c index 34e71110..653342fe 100644 --- a/xorg/server/module/rdpMisc.c +++ b/xorg/server/module/rdpMisc.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -66,15 +66,43 @@ rdpBitsPerPixel(int depth) /* the g_ functions from os_calls.c */ /*****************************************************************************/ +/* wait 'millis' milliseconds for the socket to be able to receive */ +/* returns boolean */ +int +g_sck_can_recv(int sck, int millis) +{ + fd_set rfds; + struct timeval time; + int rv; + + time.tv_sec = millis / 1000; + time.tv_usec = (millis * 1000) % 1000000; + FD_ZERO(&rfds); + + if (sck > 0) + { + FD_SET(((unsigned int)sck), &rfds); + rv = select(sck + 1, &rfds, 0, 0, &time); + + if (rv > 0) + { + return 1; + } + } + + return 0; +} + +/*****************************************************************************/ int -g_tcp_recv(int sck, void *ptr, int len, int flags) +g_sck_recv(int sck, void *ptr, int len, int flags) { return recv(sck, ptr, len, flags); } /*****************************************************************************/ void -g_tcp_close(int sck) +g_sck_close(int sck) { if (sck == 0) { @@ -87,7 +115,7 @@ g_tcp_close(int sck) /*****************************************************************************/ int -g_tcp_last_error_would_block(int sck) +g_sck_last_error_would_block(int sck) { return (errno == EWOULDBLOCK) || (errno == EINPROGRESS); } @@ -101,7 +129,7 @@ g_sleep(int msecs) /*****************************************************************************/ int -g_tcp_send(int sck, void *ptr, int len, int flags) +g_sck_send(int sck, void *ptr, int len, int flags) { return send(sck, ptr, len, flags); } @@ -146,7 +174,7 @@ g_sprintf(char *dest, char *format, ...) /*****************************************************************************/ int -g_tcp_socket(void) +g_sck_tcp_socket(void) { int rv; int i; @@ -160,14 +188,14 @@ g_tcp_socket(void) /*****************************************************************************/ int -g_tcp_local_socket_dgram(void) +g_sck_local_socket_dgram(void) { return socket(AF_UNIX, SOCK_DGRAM, 0); } /*****************************************************************************/ int -g_tcp_local_socket_stream(void) +g_sck_local_socket_stream(void) { return socket(AF_UNIX, SOCK_STREAM, 0); } @@ -188,7 +216,7 @@ g_memset(void *d_ptr, const unsigned char chr, int size) /*****************************************************************************/ int -g_tcp_set_no_delay(int sck) +g_sck_tcp_set_no_delay(int sck) { int i; @@ -199,7 +227,7 @@ g_tcp_set_no_delay(int sck) /*****************************************************************************/ int -g_tcp_set_non_blocking(int sck) +g_sck_set_non_blocking(int sck) { unsigned long i; @@ -211,7 +239,7 @@ g_tcp_set_non_blocking(int sck) /*****************************************************************************/ int -g_tcp_accept(int sck) +g_sck_accept(int sck) { struct sockaddr_in s; unsigned int i; @@ -223,7 +251,7 @@ g_tcp_accept(int sck) /*****************************************************************************/ int -g_tcp_select(int sck1, int sck2, int sck3) +g_sck_select(int sck1, int sck2, int sck3) { fd_set rfds; struct timeval time; @@ -292,7 +320,7 @@ g_tcp_select(int sck1, int sck2, int sck3) /*****************************************************************************/ int -g_tcp_bind(int sck, char *port) +g_sck_tcp_bind(int sck, char *port) { struct sockaddr_in s; @@ -305,7 +333,7 @@ g_tcp_bind(int sck, char *port) /*****************************************************************************/ int -g_tcp_local_bind(int sck, char *port) +g_sck_local_bind(int sck, char *port) { struct sockaddr_un s; @@ -317,7 +345,7 @@ g_tcp_local_bind(int sck, char *port) /*****************************************************************************/ int -g_tcp_listen(int sck) +g_sck_listen(int sck) { return listen(sck, 2); } @@ -373,7 +401,7 @@ g_chmod_hex(const char *filename, int flags) /*****************************************************************************/ /* produce a hex dump */ void -g_hexdump(unsigned char *p, unsigned int len) +g_hexdump(void *p, long len) { unsigned char *line; int i; @@ -381,9 +409,9 @@ g_hexdump(unsigned char *p, unsigned int len) int offset; offset = 0; - line = p; + line = (unsigned char *) p; - while (offset < len) + while (offset < (int) len) { ErrorF("%04x ", offset); thisline = len - offset; diff --git a/xorg/server/module/rdpMisc.h b/xorg/server/module/rdpMisc.h index bed95891..58f6bd31 100644 --- a/xorg/server/module/rdpMisc.h +++ b/xorg/server/module/rdpMisc.h @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -29,15 +29,17 @@ the rest int rdpBitsPerPixel(int depth); int -g_tcp_recv(int sck, void *ptr, int len, int flags); +g_sck_can_recv(int sck, int millis); +int +g_sck_recv(int sck, void *ptr, int len, int flags); void -g_tcp_close(int sck); +g_sck_close(int sck); int -g_tcp_last_error_would_block(int sck); +g_sck_last_error_would_block(int sck); void g_sleep(int msecs); int -g_tcp_send(int sck, void *ptr, int len, int flags); +g_sck_send(int sck, void *ptr, int len, int flags); void * g_malloc(int size, int zero); void @@ -45,29 +47,29 @@ g_free(void *ptr); void g_sprintf(char *dest, char *format, ...); int -g_tcp_socket(void); +g_sck_tcp_socket(void); int -g_tcp_local_socket_dgram(void); +g_sck_local_socket_dgram(void); int -g_tcp_local_socket_stream(void); +g_sck_local_socket_stream(void); void g_memcpy(void *d_ptr, const void *s_ptr, int size); void g_memset(void *d_ptr, const unsigned char chr, int size); int -g_tcp_set_no_delay(int sck); +g_sck_tcp_set_no_delay(int sck); int -g_tcp_set_non_blocking(int sck); +g_sck_set_non_blocking(int sck); int -g_tcp_accept(int sck); +g_sck_accept(int sck); int -g_tcp_select(int sck1, int sck2, int sck3); +g_sck_select(int sck1, int sck2, int sck3); int -g_tcp_bind(int sck, char *port); +g_sck_tcp_bind(int sck, char *port); int -g_tcp_local_bind(int sck, char *port); +g_sck_local_bind(int sck, char *port); int -g_tcp_listen(int sck); +g_sck_listen(int sck); int g_create_dir(const char *dirname); int @@ -75,7 +77,7 @@ g_directory_exist(const char *dirname); int g_chmod_hex(const char *filename, int flags); void -g_hexdump(unsigned char *p, unsigned int len); +g_hexdump(void *p, long len); #if defined(X_BYTE_ORDER) # if X_BYTE_ORDER == X_LITTLE_ENDIAN @@ -87,7 +89,6 @@ g_hexdump(unsigned char *p, unsigned int len); # error Unknown endianness in rdp.h #endif /* check if we need to align data */ -/* check if we need to align data */ #if defined(__sparc__) || defined(__alpha__) || defined(__hppa__) || \ defined(__AIX__) || defined(__PPC__) || defined(__mips__) || \ defined(__ia64__) || defined(__ppc__) || defined(__arm__) @@ -97,157 +98,164 @@ g_hexdump(unsigned char *p, unsigned int len); /* parser state */ struct stream { - char* p; - char* end; - char* data; - int size; - /* offsets of various headers */ - char* iso_hdr; - char* mcs_hdr; - char* sec_hdr; - char* rdp_hdr; - char* channel_hdr; - char* next_packet; + char *p; + char *end; + char *data; + int size; + /* offsets of various headers */ + char *iso_hdr; + char *mcs_hdr; + char *sec_hdr; + char *rdp_hdr; + char *channel_hdr; + char *next_packet; }; /******************************************************************************/ #define s_push_layer(s, h, n) \ -{ \ - (s)->h = (s)->p; \ - (s)->p += (n); \ -} +do { \ + (s)->h = (s)->p; \ + (s)->p += (n); \ +} while (0) /******************************************************************************/ #define s_pop_layer(s, h) \ -{ \ - (s)->p = (s)->h; \ -} +do { \ + (s)->p = (s)->h; \ +} while (0) /******************************************************************************/ #if defined(B_ENDIAN) || defined(NEED_ALIGN) -#define out_uint16_le(s, v) \ -{ \ - *((s)->p) = (unsigned char)((v) >> 0); \ - (s)->p++; \ - *((s)->p) = (unsigned char)((v) >> 8); \ - (s)->p++; \ -} +#define out_uint16_le(s, v) \ +do { \ + *((s)->p) = (unsigned char)((v) >> 0); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 8); \ + (s)->p++; \ +} while (0) #else -#define out_uint16_le(s, v) \ -{ \ - *((unsigned short*)((s)->p)) = (unsigned short)(v); \ - (s)->p += 2; \ -} +#define out_uint16_le(s, v) \ +do { \ + *((unsigned short*)((s)->p)) = (unsigned short)(v); \ + (s)->p += 2; \ +} while (0) #endif /******************************************************************************/ -#define init_stream(s, v) \ -{ \ - if ((v) > (s)->size) \ - { \ - g_free((s)->data); \ - (s)->data = (char*)g_malloc((v), 0); \ - (s)->size = (v); \ - } \ - (s)->p = (s)->data; \ - (s)->end = (s)->data; \ - (s)->next_packet = 0; \ -} +#define init_stream(s, v) \ +do { \ + if ((v) > (s)->size) \ + { \ + g_free((s)->data); \ + (s)->data = (char*)g_malloc((v), 0); \ + (s)->size = (v); \ + } \ + (s)->p = (s)->data; \ + (s)->end = (s)->data; \ + (s)->next_packet = 0; \ +} while (0) + +/******************************************************************************/ +#define out_uint8p(s, v, n) \ +do { \ + g_memcpy((s)->p, (v), (n)); \ + (s)->p += (n); \ +} while (0) /******************************************************************************/ -#define out_uint8p(s, v, n) \ -{ \ - g_memcpy((s)->p, (v), (n)); \ - (s)->p += (n); \ -} +#define out_uint8a(s, v, n) \ +do { \ + out_uint8p((s), (v), (n)); \ +} while (0) /******************************************************************************/ -#define out_uint8a(s, v, n) \ -{ \ - out_uint8p((s), (v), (n)); \ -} +#define out_uint8(s, v) \ +do { \ + *((s)->p) = (unsigned char)((v) >> 0); \ + (s)->p++; \ +} while (0) /******************************************************************************/ #if defined(B_ENDIAN) || defined(NEED_ALIGN) -#define out_uint32_le(s, v) \ -{ \ - *((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++; \ -} +#define out_uint32_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++; \ +} while (0) #else -#define out_uint32_le(s, v) \ -{ \ - *((unsigned int*)((s)->p)) = (v); \ - (s)->p += 4; \ -} +#define out_uint32_le(s, v) \ +do { \ + *((unsigned int*)((s)->p)) = (v); \ + (s)->p += 4; \ +} while (0) #endif /******************************************************************************/ #if defined(B_ENDIAN) || defined(NEED_ALIGN) -#define in_uint32_le(s, v) \ -{ \ - (v) = (unsigned int) \ - ( \ - (*((unsigned char*)((s)->p + 0)) << 0) | \ - (*((unsigned char*)((s)->p + 1)) << 8) | \ - (*((unsigned char*)((s)->p + 2)) << 16) | \ - (*((unsigned char*)((s)->p + 3)) << 24) \ - ); \ - (s)->p += 4; \ -} +#define in_uint32_le(s, v) \ +do { \ + (v) = (unsigned int) \ + ( \ + (*((unsigned char*)((s)->p + 0)) << 0) | \ + (*((unsigned char*)((s)->p + 1)) << 8) | \ + (*((unsigned char*)((s)->p + 2)) << 16) | \ + (*((unsigned char*)((s)->p + 3)) << 24) \ + ); \ + (s)->p += 4; \ +} while (0) #else -#define in_uint32_le(s, v) \ -{ \ - (v) = *((unsigned int*)((s)->p)); \ - (s)->p += 4; \ -} +#define in_uint32_le(s, v) \ +do { \ + (v) = *((unsigned int*)((s)->p)); \ + (s)->p += 4; \ +} while (0) #endif /******************************************************************************/ #if defined(B_ENDIAN) || defined(NEED_ALIGN) -#define in_uint16_le(s, v) \ -{ \ - (v) = (unsigned short) \ - ( \ - (*((unsigned char*)((s)->p + 0)) << 0) | \ - (*((unsigned char*)((s)->p + 1)) << 8) \ - ); \ - (s)->p += 2; \ -} +#define in_uint16_le(s, v) \ +do { \ + (v) = (unsigned short) \ + ( \ + (*((unsigned char*)((s)->p + 0)) << 0) | \ + (*((unsigned char*)((s)->p + 1)) << 8) \ + ); \ + (s)->p += 2; \ +} while (0) #else -#define in_uint16_le(s, v) \ -{ \ - (v) = *((unsigned short*)((s)->p)); \ - (s)->p += 2; \ -} +#define in_uint16_le(s, v) \ +do { \ + (v) = *((unsigned short*)((s)->p)); \ + (s)->p += 2; \ +} while (0) #endif /******************************************************************************/ -#define s_mark_end(s) \ -{ \ - (s)->end = (s)->p; \ -} +#define s_mark_end(s) \ +do { \ + (s)->end = (s)->p; \ +} while (0) /******************************************************************************/ -#define make_stream(s) \ -{ \ - (s) = (struct stream*)g_malloc(sizeof(struct stream), 1); \ -} +#define make_stream(s) \ +do { \ + (s) = (struct stream*)g_malloc(sizeof(struct stream), 1); \ +} while (0) /******************************************************************************/ -#define free_stream(s) do \ -{ \ - if ((s) != 0) \ - { \ - g_free((s)->data); \ - } \ - g_free((s)); \ +#define free_stream(s) \ +do { \ + if ((s) != 0) \ + { \ + g_free((s)->data); \ + } \ + g_free((s)); \ } while (0) #endif diff --git a/xorg/server/module/rdpPixmap.c b/xorg/server/module/rdpPixmap.c index 08b76735..967438e0 100644 --- a/xorg/server/module/rdpPixmap.c +++ b/xorg/server/module/rdpPixmap.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -27,6 +27,7 @@ pixmap calls /* this should be before all X11 .h files */ #include <xorg-server.h> +#include <xorgVersion.h> /* all driver need this */ #include <xf86.h> @@ -34,12 +35,19 @@ pixmap calls #include "rdp.h" #include "rdpDraw.h" +#include "rdpPixmap.h" + +#ifndef XRDP_PIX +#warning XRDP_PIX not defined +#endif /******************************************************************************/ #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) +#if XRDP_PIX == 2 + /*****************************************************************************/ PixmapPtr rdpCreatePixmap(ScreenPtr pScreen, int width, int height, int depth, @@ -57,6 +65,26 @@ rdpCreatePixmap(ScreenPtr pScreen, int width, int height, int depth, return rv; } +#else + +/*****************************************************************************/ +PixmapPtr +rdpCreatePixmap(ScreenPtr pScreen, int width, int height, int depth) +{ + rdpPtr dev; + PixmapPtr rv; + + LLOGLN(10, ("rdpCreatePixmap: width %d height %d depth %d", + width, height, depth)); + dev = rdpGetDevFromScreen(pScreen); + pScreen->CreatePixmap = dev->CreatePixmap; + rv = pScreen->CreatePixmap(pScreen, width, height, depth); + pScreen->CreatePixmap = rdpCreatePixmap; + return rv; +} + +#endif + /******************************************************************************/ Bool rdpDestroyPixmap(PixmapPtr pPixmap) diff --git a/xorg/server/module/rdpPixmap.h b/xorg/server/module/rdpPixmap.h index 8456593f..7fce3186 100644 --- a/xorg/server/module/rdpPixmap.h +++ b/xorg/server/module/rdpPixmap.h @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -24,9 +24,25 @@ pixmap calls #ifndef __RDPPIXMAP_H #define __RDPPIXAMP_H +#include <xorg-server.h> +#include <xorgVersion.h> + +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 5, 0, 0, 0) +/* 1.1, 1.2, 1.3, 1.4 */ +#define XRDP_PIX 1 +#else +/* 1.5, 1.6, 1.7, 1.8, 1.9, 1.10, 1.11, 1.12 */ +#define XRDP_PIX 2 +#endif + +#if XRDP_PIX == 2 PixmapPtr rdpCreatePixmap(ScreenPtr pScreen, int width, int height, int depth, unsigned usage_hint); +#else +PixmapPtr +rdpCreatePixmap(ScreenPtr pScreen, int width, int height, int depth); +#endif Bool rdpDestroyPixmap(PixmapPtr pPixmap); Bool diff --git a/xorg/server/module/rdpPolyArc.c b/xorg/server/module/rdpPolyArc.c index e4282524..9a701dd8 100644 --- a/xorg/server/module/rdpPolyArc.c +++ b/xorg/server/module/rdpPolyArc.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -32,13 +32,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) /******************************************************************************/ -void +static void rdpPolyArcOrg(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs) { GC_OP_VARS; @@ -52,7 +54,49 @@ rdpPolyArcOrg(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs) void rdpPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs) { - LLOGLN(10, ("rdpPolyArc:")); + rdpPtr dev; + BoxRec box; + int index; + int cd; + int lw; + int extra; + RegionRec clip_reg; + RegionRec reg; + + LLOGLN(0, ("rdpPolyArc:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpPolyArcCallCount++; + rdpRegionInit(®, NullBox, 0); + if (narcs > 0) + { + lw = pGC->lineWidth; + if (lw == 0) + { + lw = 1; + } + extra = lw / 2; + for (index = 0; index < narcs; index++) + { + box.x1 = (parcs[index].x - extra) + pDrawable->x; + box.y1 = (parcs[index].y - extra) + pDrawable->y; + box.x2 = box.x1 + parcs[index].width + lw; + box.y2 = box.y1 + parcs[index].height + lw; + rdpRegionUnionRect(®, &box); + } + } + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpPolyArc: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rdpPolyArcOrg(pDrawable, pGC, narcs, parcs); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpPolyFillArc.c b/xorg/server/module/rdpPolyFillArc.c index 825dc20d..437929ae 100644 --- a/xorg/server/module/rdpPolyFillArc.c +++ b/xorg/server/module/rdpPolyFillArc.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -32,13 +32,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) /******************************************************************************/ -void +static void rdpPolyFillArcOrg(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs) { GC_OP_VARS; @@ -52,7 +54,49 @@ rdpPolyFillArcOrg(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs) void rdpPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs) { + rdpPtr dev; + BoxRec box; + int index; + int cd; + int lw; + int extra; + RegionRec clip_reg; + RegionRec reg; + LLOGLN(10, ("rdpPolyFillArc:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpPolyFillArcCallCount++; + rdpRegionInit(®, NullBox, 0); + if (narcs > 0) + { + lw = pGC->lineWidth; + if (lw == 0) + { + lw = 1; + } + extra = lw / 2; + for (index = 0; index < narcs; index++) + { + box.x1 = (parcs[index].x - extra) + pDrawable->x; + box.y1 = (parcs[index].y - extra) + pDrawable->y; + box.x2 = box.x1 + parcs[index].width + lw; + box.y2 = box.y1 + parcs[index].height + lw; + rdpRegionUnionRect(®, &box); + } + } + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpPolyFillArc: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rdpPolyFillArcOrg(pDrawable, pGC, narcs, parcs); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpPolyFillRect.c b/xorg/server/module/rdpPolyFillRect.c index 1de9cee1..f61202b2 100644 --- a/xorg/server/module/rdpPolyFillRect.c +++ b/xorg/server/module/rdpPolyFillRect.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -32,6 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -54,7 +56,30 @@ void rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, xRectangle *prectInit) { + rdpPtr dev; + RegionRec clip_reg; + RegionPtr reg; + int cd; + LLOGLN(10, ("rdpPolyFillRect:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpPolyFillRectCallCount++; + /* make a copy of rects */ + reg = rdpRegionFromRects(nrectFill, prectInit, CT_NONE); + rdpRegionTranslate(reg, pDrawable->x, pDrawable->y); + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpPolyFillRect: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(reg, &clip_reg, reg); + } /* do original call */ rdpPolyFillRectOrg(pDrawable, pGC, nrectFill, prectInit); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, reg, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionDestroy(reg); } diff --git a/xorg/server/module/rdpPolyGlyphBlt.c b/xorg/server/module/rdpPolyGlyphBlt.c index 2ba11996..e43e676b 100644 --- a/xorg/server/module/rdpPolyGlyphBlt.c +++ b/xorg/server/module/rdpPolyGlyphBlt.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -32,6 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -56,7 +58,30 @@ rdpPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase) { - LLOGLN(10, ("rdpPolyGlyphBlt:")); + rdpPtr dev; + RegionRec clip_reg; + RegionRec reg; + int cd; + BoxRec box; + + LLOGLN(0, ("rdpPolyGlyphBlt:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpPolyGlyphBltCallCount++; + GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box); + rdpRegionInit(®, &box, 0); + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpPolyGlyphBlt: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rdpPolyGlyphBltOrg(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpPolyGlyphBlt.h b/xorg/server/module/rdpPolyGlyphBlt.h index 9c6519d8..46ce1ac2 100644 --- a/xorg/server/module/rdpPolyGlyphBlt.h +++ b/xorg/server/module/rdpPolyGlyphBlt.h @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpPolyPoint.c b/xorg/server/module/rdpPolyPoint.c index 8379c1c6..5dfac5ef 100644 --- a/xorg/server/module/rdpPolyPoint.c +++ b/xorg/server/module/rdpPolyPoint.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -32,13 +32,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) /******************************************************************************/ -void +static void rdpPolyPointOrg(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr in_pts) { @@ -54,7 +56,38 @@ void rdpPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr in_pts) { + rdpPtr dev; + RegionRec clip_reg; + RegionRec reg; + int cd; + int index; + BoxRec box; + LLOGLN(10, ("rdpPolyPoint:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpPolyPointCallCount++; + rdpRegionInit(®, NullBox, 0); + for (index = 0; index < npt; index++) + { + box.x1 = in_pts[index].x + pDrawable->x; + box.y1 = in_pts[index].y + pDrawable->y; + box.x2 = box.x1 + 1; + box.y2 = box.y1 + 1; + rdpRegionUnionRect(®, &box); + } + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpPolyPoint: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rdpPolyPointOrg(pDrawable, pGC, mode, npt, in_pts); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpPolyPoint.h b/xorg/server/module/rdpPolyPoint.h index 87bf9459..06d1d428 100644 --- a/xorg/server/module/rdpPolyPoint.h +++ b/xorg/server/module/rdpPolyPoint.h @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpPolyRectangle.c b/xorg/server/module/rdpPolyRectangle.c index 90b23961..18311907 100644 --- a/xorg/server/module/rdpPolyRectangle.c +++ b/xorg/server/module/rdpPolyRectangle.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -32,6 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -50,12 +52,81 @@ rdpPolyRectangleOrg(DrawablePtr pDrawable, GCPtr pGC, int nrects, } /******************************************************************************/ -/* tested with pGC->lineWidth = 0, 1, 2, 4 and opcodes 3 and 6 */ void rdpPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects, xRectangle *rects) { + rdpPtr dev; + BoxRec box; + int index; + int up; + int down; + int lw; + int cd; + int x1; + int y1; + int x2; + int y2; + RegionRec clip_reg; + RegionRec reg; + LLOGLN(10, ("rdpPolyRectangle:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpPolyRectangleCallCount++; + rdpRegionInit(®, NullBox, 0); + lw = pGC->lineWidth; + if (lw < 1) + { + lw = 1; + } + up = lw / 2; + down = 1 + (lw - 1) / 2; + index = 0; + while (index < nrects) + { + x1 = rects[index].x + pDrawable->x; + y1 = rects[index].y + pDrawable->y; + x2 = x1 + rects[index].width; + y2 = y1 + rects[index].height; + /* top */ + box.x1 = x1 - up; + box.y1 = y1 - up; + box.x2 = x2 + down; + box.y2 = y1 + down; + rdpRegionUnionRect(®, &box); + /* left */ + box.x1 = x1 - up; + box.y1 = y1 - up; + box.x2 = x1 + down; + box.y2 = y2 + down; + rdpRegionUnionRect(®, &box); + /* right */ + box.x1 = x2 - up; + box.y1 = y1 - up; + box.x2 = x2 + down; + box.y2 = y2 + down; + rdpRegionUnionRect(®, &box); + /* bottom */ + box.x1 = x1 - up; + box.y1 = y2 - up; + box.x2 = x2 + down; + box.y2 = y2 + down; + rdpRegionUnionRect(®, &box); + index++; + } + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpPolyRectangle: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rdpPolyRectangleOrg(pDrawable, pGC, nrects, rects); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpPolySegment.c b/xorg/server/module/rdpPolySegment.c index 1ae62d27..98e4eb1f 100644 --- a/xorg/server/module/rdpPolySegment.c +++ b/xorg/server/module/rdpPolySegment.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -32,6 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -52,7 +54,46 @@ rdpPolySegmentOrg(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment *pSegs) void rdpPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment *pSegs) { + rdpPtr dev; + RegionRec clip_reg; + RegionRec reg; + int cd; + int index; + int x1; + int y1; + int x2; + int y2; + BoxRec box; + LLOGLN(10, ("rdpPolySegment:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpPolySegmentCallCount++; + rdpRegionInit(®, NullBox, 0); + for (index = 0; index < nseg; index++) + { + x1 = pSegs[index].x1 + pDrawable->x; + y1 = pSegs[index].y1 + pDrawable->y; + x2 = pSegs[index].x2 + pDrawable->x; + y2 = pSegs[index].y2 + pDrawable->y; + box.x1 = RDPMIN(x1, x2); + box.y1 = RDPMIN(y1, y2); + box.x2 = RDPMAX(x1, x2) + 1; + box.y2 = RDPMAX(y1, y2) + 1; + rdpRegionUnionRect(®, &box); + } + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpPolySegment: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rdpPolySegmentOrg(pDrawable, pGC, nseg, pSegs); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpPolySegment.h b/xorg/server/module/rdpPolySegment.h index 8c5f33ab..104fc37d 100644 --- a/xorg/server/module/rdpPolySegment.h +++ b/xorg/server/module/rdpPolySegment.h @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpPolyText16.c b/xorg/server/module/rdpPolyText16.c index 4a716e3f..90d68a8c 100644 --- a/xorg/server/module/rdpPolyText16.c +++ b/xorg/server/module/rdpPolyText16.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -32,13 +32,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) /******************************************************************************/ -int +static int rdpPolyText16Org(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, unsigned short *chars) { @@ -57,9 +59,31 @@ rdpPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, unsigned short *chars) { int rv; + rdpPtr dev; + RegionRec clip_reg; + RegionRec reg; + int cd; + BoxRec box; LLOGLN(10, ("rdpPolyText16:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpPolyText16CallCount++; + GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); + rdpRegionInit(®, &box, 0); + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpPolyText16: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rv = rdpPolyText16Org(pDrawable, pGC, x, y, count, chars); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); return rv; } diff --git a/xorg/server/module/rdpPolyText16.h b/xorg/server/module/rdpPolyText16.h index bcfa8379..9719a890 100644 --- a/xorg/server/module/rdpPolyText16.h +++ b/xorg/server/module/rdpPolyText16.h @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpPolyText8.c b/xorg/server/module/rdpPolyText8.c index e6671252..630bc04e 100644 --- a/xorg/server/module/rdpPolyText8.c +++ b/xorg/server/module/rdpPolyText8.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -32,13 +32,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) /******************************************************************************/ -int +static int rdpPolyText8Org(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, char *chars) { @@ -57,9 +59,31 @@ rdpPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, char *chars) { int rv; + rdpPtr dev; + RegionRec clip_reg; + RegionRec reg; + int cd; + BoxRec box; LLOGLN(10, ("rdpPolyText8:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpPolyText8CallCount++; + GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); + rdpRegionInit(®, &box, 0); + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpPolyText8: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rv = rdpPolyText8Org(pDrawable, pGC, x, y, count, chars); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); return rv; } diff --git a/xorg/server/module/rdpPolyText8.h b/xorg/server/module/rdpPolyText8.h index 95e80412..621251b9 100644 --- a/xorg/server/module/rdpPolyText8.h +++ b/xorg/server/module/rdpPolyText8.h @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpPolylines.c b/xorg/server/module/rdpPolylines.c index 7558407e..da979e9f 100644 --- a/xorg/server/module/rdpPolylines.c +++ b/xorg/server/module/rdpPolylines.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -32,6 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -54,7 +56,46 @@ void rdpPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr pptInit) { + rdpPtr dev; + RegionRec clip_reg; + RegionRec reg; + int cd; + int index; + int x1; + int y1; + int x2; + int y2; + BoxRec box; + LLOGLN(10, ("rdpPolylines:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpPolylinesCallCount++; + rdpRegionInit(®, NullBox, 0); + for (index = 1; index < npt; index++) + { + x1 = pptInit[index - 1].x + pDrawable->x; + y1 = pptInit[index - 1].y + pDrawable->y; + x2 = pptInit[index].x + pDrawable->x; + y2 = pptInit[index].y + pDrawable->y; + box.x1 = RDPMIN(x1, x2); + box.y1 = RDPMIN(y1, y2); + box.x2 = RDPMAX(x1, x2) + 1; + box.y2 = RDPMAX(y1, y2) + 1; + rdpRegionUnionRect(®, &box); + } + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDrawable, pGC); + LLOGLN(10, ("rdpPolylines: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rdpPolylinesOrg(pDrawable, pGC, mode, npt, pptInit); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDrawable); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpPolylines.h b/xorg/server/module/rdpPolylines.h index 2df3d388..56b66a77 100644 --- a/xorg/server/module/rdpPolylines.h +++ b/xorg/server/module/rdpPolylines.h @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpPri.c b/xorg/server/module/rdpPri.c index 43f3d883..3ceedc9c 100644 --- a/xorg/server/module/rdpPri.c +++ b/xorg/server/module/rdpPri.c @@ -1,5 +1,5 @@ /* -Copyright 2013 Jay Sorg +Copyright 2013-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -27,6 +27,7 @@ to deal with privates changing in xorg versions /* this should be before all X11 .h files */ #include <xorg-server.h> +#include <xorgVersion.h> /* all driver need this */ #include <xf86.h> @@ -40,10 +41,10 @@ to deal with privates changing in xorg versions #include "rdpPri.h" #include "rdpMisc.h" -#if XORG_VERSION_CURRENT < (((1) * 10000000) + ((5) * 100000) + ((0) * 1000) + 0) +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 5, 0, 0, 0) /* 1.1, 1.2, 1.3, 1.4 */ #define XRDP_PRI 1 -#elif XORG_VERSION_CURRENT < (((1) * 10000000) + ((9) * 100000) + ((0) * 1000) + 0) +#elif XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 9, 0, 0, 0) /* 1.5, 1.6, 1.7, 1.8 */ #define XRDP_PRI 2 #else diff --git a/xorg/server/module/rdpPri.h b/xorg/server/module/rdpPri.h index 625947a3..97e570f5 100644 --- a/xorg/server/module/rdpPri.h +++ b/xorg/server/module/rdpPri.h @@ -1,5 +1,5 @@ /* -Copyright 2013 Jay Sorg +Copyright 2013-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpPushPixels.c b/xorg/server/module/rdpPushPixels.c index bab4b03d..8ab046b8 100644 --- a/xorg/server/module/rdpPushPixels.c +++ b/xorg/server/module/rdpPushPixels.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -54,7 +54,7 @@ void rdpPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst, int w, int h, int x, int y) { - LLOGLN(10, ("rdpPushPixels:")); + LLOGLN(0, ("rdpPushPixels:")); /* do original call */ rdpPushPixelsOrg(pGC, pBitMap, pDst, w, h, x, y); } diff --git a/xorg/server/module/rdpPushPixels.h b/xorg/server/module/rdpPushPixels.h index 2e0cd1d1..a3e49482 100644 --- a/xorg/server/module/rdpPushPixels.h +++ b/xorg/server/module/rdpPushPixels.h @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpPutImage.c b/xorg/server/module/rdpPutImage.c index f7a33f7c..b7134479 100644 --- a/xorg/server/module/rdpPutImage.c +++ b/xorg/server/module/rdpPutImage.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -32,6 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdp.h" #include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -55,7 +57,33 @@ void rdpPutImage(DrawablePtr pDst, GCPtr pGC, int depth, int x, int y, int w, int h, int leftPad, int format, char *pBits) { + rdpPtr dev; + RegionRec clip_reg; + RegionRec reg; + int cd; + BoxRec box; + LLOGLN(10, ("rdpPutImage:")); + dev = rdpGetDevFromScreen(pGC->pScreen); + dev->counts.rdpPutImageCallCount++; + box.x1 = x + pDst->x; + box.y1 = y + pDst->y; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + rdpRegionInit(®, &box, 0); + rdpRegionInit(&clip_reg, NullBox, 0); + cd = rdpDrawGetClip(dev, &clip_reg, pDst, pGC); + LLOGLN(10, ("rdpPutImage: cd %d", cd)); + if (cd == XRDP_CD_CLIP) + { + rdpRegionIntersect(®, &clip_reg, ®); + } /* do original call */ rdpPutImageOrg(pDst, pGC, depth, x, y, w, h, leftPad, format, pBits); + if (cd != XRDP_CD_NODRAW) + { + rdpClientConAddAllReg(dev, ®, pDst); + } + rdpRegionUninit(&clip_reg); + rdpRegionUninit(®); } diff --git a/xorg/server/module/rdpPutImage.h b/xorg/server/module/rdpPutImage.h index 82e27872..f50a9528 100644 --- a/xorg/server/module/rdpPutImage.h +++ b/xorg/server/module/rdpPutImage.h @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpRandR.c b/xorg/server/module/rdpRandR.c index ad3808bd..37577645 100644 --- a/xorg/server/module/rdpRandR.c +++ b/xorg/server/module/rdpRandR.c @@ -1,5 +1,5 @@ /* -Copyright 2011-2013 Jay Sorg +Copyright 2011-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -27,6 +27,7 @@ RandR draw calls /* this should be before all X11 .h files */ #include <xorg-server.h> +#include <xorgVersion.h> /* all driver need this */ #include <xf86.h> @@ -141,8 +142,13 @@ rdpRRScreenSetSize(ScreenPtr pScreen, CARD16 width, CARD16 height, RRGetInfo(pScreen, 1); LLOGLN(0, (" screen resized to %dx%d", pScreen->width, pScreen->height)); RRScreenSizeNotify(pScreen); +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 13, 0, 0, 0) xf86EnableDisableFBAccess(pScreen->myNum, FALSE); xf86EnableDisableFBAccess(pScreen->myNum, TRUE); +#else + xf86EnableDisableFBAccess(xf86Screens[pScreen->myNum], FALSE); + xf86EnableDisableFBAccess(xf86Screens[pScreen->myNum], TRUE); +#endif return TRUE; } diff --git a/xorg/server/module/rdpRandR.h b/xorg/server/module/rdpRandR.h index 3aba7e1a..caadf336 100644 --- a/xorg/server/module/rdpRandR.h +++ b/xorg/server/module/rdpRandR.h @@ -1,5 +1,5 @@ /* -Copyright 2011-2013 Jay Sorg +Copyright 2011-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpReg.c b/xorg/server/module/rdpReg.c index e0cd4ea5..8ff7d79d 100644 --- a/xorg/server/module/rdpReg.c +++ b/xorg/server/module/rdpReg.c @@ -1,5 +1,5 @@ /* -Copyright 2013 Jay Sorg +Copyright 2013-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -27,6 +27,7 @@ to deal with regions changing in xorg versions /* this should be before all X11 .h files */ #include <xorg-server.h> +#include <xorgVersion.h> /* all driver need this */ #include <xf86.h> @@ -49,7 +50,7 @@ miRegionReset -> RegionReset miRegionBreak -> RegionBreak */ -#if XORG_VERSION_CURRENT < (((1) * 10000000) + ((9) * 100000) + ((0) * 1000) + 0) +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 9, 0, 0, 0) /* 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8 */ #define XRDP_REG 1 #else @@ -232,3 +233,33 @@ rdpRegionBreak(RegionPtr pReg) return RegionBreak(pReg); #endif } + +/*****************************************************************************/ +void +rdpRegionUnionRect(RegionPtr pReg, BoxPtr prect) +{ + RegionRec reg; + + rdpRegionInit(®, prect, 0); + rdpRegionUnion(pReg, pReg, ®); + rdpRegionUninit(®); +} + +/*****************************************************************************/ +int +rdpRegionPixelCount(RegionPtr pReg) +{ + int index; + int count; + int rv; + BoxRec box; + + rv = 0; + count = REGION_NUM_RECTS(pReg); + for (index = 0; index < count; index++) + { + box = REGION_RECTS(pReg)[index]; + rv += (box.x2 - box.x1) * (box.y2 - box.y1); + } + return rv; +} diff --git a/xorg/server/module/rdpReg.h b/xorg/server/module/rdpReg.h index b788cd69..a5cd73bf 100644 --- a/xorg/server/module/rdpReg.h +++ b/xorg/server/module/rdpReg.h @@ -1,5 +1,5 @@ /* -Copyright 2013 Jay Sorg +Copyright 2013-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -56,5 +56,9 @@ void rdpRegionReset(RegionPtr pReg, BoxPtr pBox); Bool rdpRegionBreak(RegionPtr pReg); +void +rdpRegionUnionRect(RegionPtr pReg, BoxPtr prect); +int +rdpRegionPixelCount(RegionPtr pReg); #endif diff --git a/xorg/server/module/rdpSetSpans.c b/xorg/server/module/rdpSetSpans.c index c2ea798e..e31ec6d4 100644 --- a/xorg/server/module/rdpSetSpans.c +++ b/xorg/server/module/rdpSetSpans.c @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpSetSpans.h b/xorg/server/module/rdpSetSpans.h index acaedd66..c6f73642 100644 --- a/xorg/server/module/rdpSetSpans.h +++ b/xorg/server/module/rdpSetSpans.h @@ -1,5 +1,5 @@ /* -Copyright 2005-2013 Jay Sorg +Copyright 2005-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that diff --git a/xorg/server/module/rdpTrapezoids.c b/xorg/server/module/rdpTrapezoids.c new file mode 100644 index 00000000..212780ce --- /dev/null +++ b/xorg/server/module/rdpTrapezoids.c @@ -0,0 +1,87 @@ +/* +Copyright 2014 Jay Sorg + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* this should be before all X11 .h files */ +#include <xorg-server.h> + +/* all driver need this */ +#include <xf86.h> +#include <xf86_OSproc.h> + +#include <mipict.h> +#include <picture.h> + +#include "rdp.h" +#include "rdpDraw.h" +#include "rdpClientCon.h" +#include "rdpReg.h" +#include "rdpTrapezoids.h" + +/******************************************************************************/ +#define LOG_LEVEL 1 +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +/******************************************************************************/ +static void +rdpTrapezoidsOrg(PictureScreenPtr ps, rdpPtr dev, + CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int ntrap, xTrapezoid *traps) +{ + ps->Trapezoids = dev->Trapezoids; + ps->Trapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps); + ps->Trapezoids = rdpTrapezoids; +} + +/******************************************************************************/ +void +rdpTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int ntrap, xTrapezoid *traps) +{ + ScreenPtr pScreen; + rdpPtr dev; + PictureScreenPtr ps; + BoxRec box; + RegionRec reg; + + LLOGLN(10, ("rdpTrapezoids:")); + pScreen = pDst->pDrawable->pScreen; + dev = rdpGetDevFromScreen(pScreen); + dev->counts.rdpTrapezoidsCallCount++; + miTrapezoidBounds(ntrap, traps, &box); + box.x1 += pDst->pDrawable->x; + box.y1 += pDst->pDrawable->y; + box.x2 += pDst->pDrawable->x; + box.y2 += pDst->pDrawable->y; + rdpRegionInit(®, &box, 0); + ps = GetPictureScreen(pScreen); + /* do original call */ + rdpTrapezoidsOrg(ps, dev, op, pSrc, pDst, maskFormat, xSrc, ySrc, + ntrap, traps); + rdpClientConAddAllReg(dev, ®, pDst->pDrawable); + rdpRegionUninit(®); +} diff --git a/xorg/server/module/rdpTrapezoids.h b/xorg/server/module/rdpTrapezoids.h new file mode 100644 index 00000000..77738dc4 --- /dev/null +++ b/xorg/server/module/rdpTrapezoids.h @@ -0,0 +1,30 @@ +/* +Copyright 2014 Jay Sorg + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + +#ifndef _RDPTRAPEZOIDS_H +#define _RDPTRAPEZOIDS_H + +void +rdpTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int ntrap, xTrapezoid *traps); + +#endif diff --git a/xorg/server/readme.txt b/xorg/server/readme.txt index dce66306..28bbc692 100644 --- a/xorg/server/readme.txt +++ b/xorg/server/readme.txt @@ -1,7 +1,16 @@ -Notes for building xrdpdev_drv.so and libxorgxrdp.so +------------------------------------------------------ + Notes for building xrdpdev_drv.so and libxorgxrdp.so +------------------------------------------------------ +Pre-requisites: + o sudo apt-get install xserver-xorg-dev +quick and easy way to build and run the driver + o cd xorg/server + o ./test-in-home.sh + + o see /etc/X11/xrdp/xorg.conf to see how things are configured to run it create /etc/X11/xrdp diff --git a/xorg/server/test-in-home.sh b/xorg/server/test-in-home.sh new file mode 100755 index 00000000..87c73a11 --- /dev/null +++ b/xorg/server/test-in-home.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +if [ -e /etc/X11/xrdp/xorg.conf ]; then + echo "/etc/X11/xrdp/xorg.conf ok" +else + echo "/etc/X11/xrdp/xorg.conf missing, run" + echo "sudo mkdir /etc/X11/xrdp" + echo "sudo cp xrdpdev/xorg.conf /etc/X11/xrdp/" + exit 1 +fi + +if [ -d $HOME/xorg-modules ]; then + echo "found directory ok" +else + echo "creating directory" + mkdir $HOME/xorg-modules + mkdir $HOME/xorg-modules/drivers + mkdir $HOME/xorg-modules/extensions + mkdir $HOME/xorg-modules/input + + cp /usr/lib/xorg/modules/libfb.so $HOME/xorg-modules/ + cp /usr/lib/xorg/modules/libint10.so $HOME/xorg-modules/ + cp /usr/lib/xorg/modules/libvbe.so $HOME/xorg-modules/ + + cp /usr/lib/xorg/modules/extensions/libdbe.so $HOME/xorg-modules/extensions/ + cp /usr/lib/xorg/modules/extensions/libdri.so $HOME/xorg-modules/extensions/ + cp /usr/lib/xorg/modules/extensions/libdri2.so $HOME/xorg-modules/extensions/ + cp /usr/lib/xorg/modules/extensions/libextmod.so $HOME/xorg-modules/extensions/ + cp /usr/lib/xorg/modules/extensions/libglx.so $HOME/xorg-modules/extensions/ + cp /usr/lib/xorg/modules/extensions/librecord.so $HOME/xorg-modules/extensions/ + +fi + +make +if test $? -ne 0 +then + echo "make failed" + exit 1 +fi +make xinstall +exec Xorg -modulepath $HOME/xorg-modules -config xrdp/xorg.conf -logfile /tmp/Xtmp.log -novtswitch -sharevts -noreset -ac vt7 :20 diff --git a/xorg/server/xrdpdev/Makefile b/xorg/server/xrdpdev/Makefile index 0219959e..bd17699f 100644 --- a/xorg/server/xrdpdev/Makefile +++ b/xorg/server/xrdpdev/Makefile @@ -1,7 +1,8 @@ OBJS = xrdpdev.o -CFLAGS = -g -O2 -Wall -fPIC -I/usr/include/xorg -I/usr/include/pixman-1 -I../module +CFLAGS = -g -O2 -Wall -fPIC -I/usr/include/xorg -I/usr/include/pixman-1 \ +-I../module -I../../../common LDFLAGS = diff --git a/xorg/server/xrdpdev/xrdpdev.c b/xorg/server/xrdpdev/xrdpdev.c index 2bc6732a..7e5959ba 100644 --- a/xorg/server/xrdpdev/xrdpdev.c +++ b/xorg/server/xrdpdev/xrdpdev.c @@ -1,5 +1,5 @@ /* -Copyright 2013 Jay Sorg +Copyright 2013-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -27,6 +27,7 @@ This is the main driver file /* this should be before all X11 .h files */ #include <xorg-server.h> +#include <xorgVersion.h> /* all driver need this */ #include <xf86.h> @@ -46,6 +47,7 @@ This is the main driver file #include "rdpRandR.h" #include "rdpMisc.h" #include "rdpComposite.h" +#include "rdpTrapezoids.h" #include "rdpGlyphs.h" #include "rdpPixmap.h" #include "rdpClientCon.h" @@ -409,7 +411,11 @@ rdpWakeupHandler1(pointer blockData, int result, pointer pReadmask) /*****************************************************************************/ static Bool +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 13, 0, 0, 0) rdpScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) +#else +rdpScreenInit(ScreenPtr pScreen, int argc, char **argv) +#endif { ScrnInfoPtr pScrn; rdpPtr dev; @@ -417,7 +423,7 @@ rdpScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) Bool vis_found; PictureScreenPtr ps; - pScrn = xf86Screens[scrnIndex]; + pScrn = xf86Screens[pScreen->myNum]; dev = XRDPPTR(pScrn); dev->pScreen = pScreen; @@ -530,6 +536,9 @@ rdpScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) /* glyphs */ dev->Glyphs = ps->Glyphs; ps->Glyphs = rdpGlyphs; + /* trapezoids */ + dev->Trapezoids = ps->Trapezoids; + ps->Trapezoids = rdpTrapezoids; } RegisterBlockAndWakeupHandlers(rdpBlockHandler1, rdpWakeupHandler1, pScreen); @@ -541,13 +550,21 @@ rdpScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) LLOGLN(0, ("rdpScreenInit: rdpClientConInit failed")); } + dev->Bpp_mask = 0x00FFFFFF; + dev->Bpp = 4; + dev->bitsPerPixel = 32; + LLOGLN(0, ("rdpScreenInit: out")); return TRUE; } /*****************************************************************************/ static Bool +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 13, 0, 0, 0) rdpSwitchMode(int a, DisplayModePtr b, int c) +#else +rdpSwitchMode(ScrnInfoPtr a, DisplayModePtr b) +#endif { LLOGLN(0, ("rdpSwitchMode:")); return TRUE; @@ -555,14 +572,22 @@ rdpSwitchMode(int a, DisplayModePtr b, int c) /*****************************************************************************/ static void +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 13, 0, 0, 0) rdpAdjustFrame(int a, int b, int c, int d) +#else +rdpAdjustFrame(ScrnInfoPtr a, int b, int c) +#endif { LLOGLN(10, ("rdpAdjustFrame:")); } /*****************************************************************************/ static Bool +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 13, 0, 0, 0) rdpEnterVT(int a, int b) +#else +rdpEnterVT(ScrnInfoPtr a) +#endif { LLOGLN(0, ("rdpEnterVT:")); return TRUE; @@ -570,14 +595,22 @@ rdpEnterVT(int a, int b) /*****************************************************************************/ static void +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 13, 0, 0, 0) rdpLeaveVT(int a, int b) +#else +rdpLeaveVT(ScrnInfoPtr a) +#endif { LLOGLN(0, ("rdpLeaveVT:")); } /*****************************************************************************/ static ModeStatus +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 13, 0, 0, 0) rdpValidMode(int a, DisplayModePtr b, Bool c, int d) +#else +rdpValidMode(ScrnInfoPtr a, DisplayModePtr b, Bool c, int d) +#endif { LLOGLN(0, ("rdpValidMode:")); return 0; diff --git a/xorg/server/xrdpkeyb/Makefile b/xorg/server/xrdpkeyb/Makefile index c8654851..8c81fcee 100644 --- a/xorg/server/xrdpkeyb/Makefile +++ b/xorg/server/xrdpkeyb/Makefile @@ -1,7 +1,8 @@ OBJS = rdpKeyboard.o -CFLAGS = -g -O2 -Wall -fPIC -I/usr/include/xorg -I/usr/include/pixman-1 -I../module +CFLAGS = -g -O2 -Wall -fPIC -I/usr/include/xorg -I/usr/include/pixman-1 \ +-I../module -I../../../common LDFLAGS = diff --git a/xorg/server/xrdpkeyb/rdpKeyboard.c b/xorg/server/xrdpkeyb/rdpKeyboard.c index 26ba73b4..a1e840b2 100644 --- a/xorg/server/xrdpkeyb/rdpKeyboard.c +++ b/xorg/server/xrdpkeyb/rdpKeyboard.c @@ -1,5 +1,5 @@ /* -Copyright 2013 Jay Sorg +Copyright 2013-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -492,7 +492,7 @@ rdpInputKeyboard(rdpPtr dev, int msg, long param1, long param2, rdpKeyboard *keyboard; keyboard = &(dev->keyboard); - LLOGLN(0, ("rdpInputKeyboard:")); + LLOGLN(10, ("rdpInputKeyboard:")); switch (msg) { case 15: /* key down */ diff --git a/xorg/server/xrdpmouse/Makefile b/xorg/server/xrdpmouse/Makefile index dfcabc88..905308ad 100644 --- a/xorg/server/xrdpmouse/Makefile +++ b/xorg/server/xrdpmouse/Makefile @@ -1,7 +1,8 @@ OBJS = rdpMouse.o -CFLAGS = -g -O2 -Wall -fPIC -I/usr/include/xorg -I/usr/include/pixman-1 -I../module +CFLAGS = -g -O2 -Wall -fPIC -I/usr/include/xorg -I/usr/include/pixman-1 \ +-I../module -I../../../common LDFLAGS = diff --git a/xorg/server/xrdpmouse/rdpMouse.c b/xorg/server/xrdpmouse/rdpMouse.c index 6215c408..2d8213cd 100644 --- a/xorg/server/xrdpmouse/rdpMouse.c +++ b/xorg/server/xrdpmouse/rdpMouse.c @@ -1,5 +1,5 @@ /* -Copyright 2013 Jay Sorg +Copyright 2013-2014 Jay Sorg Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -98,18 +98,16 @@ l_bound_by(int val, int low, int high) static void rdpEnqueueMotion(DeviceIntPtr device, int x, int y) { - int valuators[2]; - - valuators[0] = x; - valuators[1] = y; - xf86PostMotionEvent(device, TRUE, 0, 2, valuators); + LLOGLN(10, ("rdpEnqueueMotion:")); + xf86PostMotionEvent(device, TRUE, 0, 2, x, y); } /******************************************************************************/ static void rdpEnqueueButton(DeviceIntPtr device, int type, int buttons) { - xf86PostButtonEvent(device, FALSE, buttons, type, 0, 0); + LLOGLN(10, ("rdpEnqueueButton:")); + xf86PostButtonEvent(device, FALSE, buttons, type == ButtonPress, 0, 0); } /******************************************************************************/ @@ -122,6 +120,8 @@ PtrAddEvent(rdpPointer *pointer) rdpEnqueueMotion(pointer->device, pointer->cursor_x, pointer->cursor_y); + LLOGLN(10, ("PtrAddEvent: x %d y %d", pointer->cursor_x, pointer->cursor_y)); + for (i = 0; i < 5; i++) { if ((pointer->button_mask ^ pointer->old_button_mask) & (1 << i)) @@ -152,7 +152,8 @@ rdpInputMouse(rdpPtr dev, int msg, { rdpPointer *pointer; - LLOGLN(0, ("rdpInputMouse:")); + LLOGLN(10, ("rdpInputMouse: msg %d param1 %ld param2 %ld param3 %ld param4 %ld", + msg, param1, param2, param3, param4)); pointer = &(dev->pointer); switch (msg) { diff --git a/xrdp/Makefile.am b/xrdp/Makefile.am index 83d04a6c..71d84a33 100644 --- a/xrdp/Makefile.am +++ b/xrdp/Makefile.am @@ -1,4 +1,4 @@ -EXTRA_DIST = xrdp.ini ad24b.bmp ad256.bmp xrdp24b.bmp xrdp256.bmp sans-10.fv1 cursor0.cur cursor1.cur xrdp.h xrdp_types.h +EXTRA_DIST = xrdp.ini ad24b.bmp ad256.bmp xrdp24b.bmp xrdp256.bmp xrdp_logo.bmp sans-10.fv1 cursor0.cur cursor1.cur xrdp.h xrdp_types.h EXTRA_INCLUDES = EXTRA_LIBS = @@ -66,6 +66,7 @@ xrdppkgdata_DATA = \ ad256.bmp \ xrdp24b.bmp \ xrdp256.bmp \ + xrdp_logo.bmp \ sans-10.fv1 \ cursor0.cur \ cursor1.cur diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h index 172d417a..a778058f 100644 --- a/xrdp/xrdp.h +++ b/xrdp/xrdp.h @@ -108,6 +108,8 @@ xrdp_wm_send_bitmap(struct xrdp_wm* self, struct xrdp_bitmap* bitmap, int x, int y, int cx, int cy); int APP_CC xrdp_wm_set_pointer(struct xrdp_wm* self, int cache_idx); +unsigned int APP_CC +xrdp_wm_htoi (const char *ptr); int APP_CC xrdp_wm_set_focused(struct xrdp_wm* self, struct xrdp_bitmap* wnd); int APP_CC @@ -349,6 +351,8 @@ get_keymaps(int keylayout, struct xrdp_keymap* keymap); /* xrdp_login_wnd.c */ int APP_CC xrdp_login_wnd_create(struct xrdp_wm* self); +int APP_CC +load_xrdp_config(struct xrdp_config *config, int bpp); /* xrdp_bitmap_compress.c */ int APP_CC @@ -398,6 +402,10 @@ server_composite(struct xrdp_mod* mod, int srcidx, int srcformat, int srcwidth, int srcx, int srcy, int mskx, int msky, int dstx, int dsty, int width, int height, int dstformat); int DEFAULT_CC +server_paint_rects(struct xrdp_mod* mod, int num_drects, short *drects, + int num_crects, short *crects, + char *data, int width, int height, int flags); +int DEFAULT_CC server_set_pointer(struct xrdp_mod* mod, int x, int y, char* data, char* mask); int DEFAULT_CC diff --git a/xrdp/xrdp.ini b/xrdp/xrdp.ini index 0e8d302b..70c917e1 100644 --- a/xrdp/xrdp.ini +++ b/xrdp/xrdp.ini @@ -1,5 +1,8 @@ [globals] +# xrdp.ini file version number +ini_version=1 + bitmap_cache=yes bitmap_compression=yes port=3389 @@ -7,16 +10,25 @@ crypt_level=high allow_channels=true max_bpp=24 fork=yes + # regulate if the listening socket use socket option tcp_nodelay # no buffering will be performed in the TCP stack tcp_nodelay=yes + # regulate if the listening socket use socket option keepalive # if the network connection disappear without close messages the connection will be closed tcp_keepalive=yes + #tcp_send_buffer_bytes=32768 #tcp_recv_buffer_bytes=32768 + +# +# colors used by windows in RGB format +# + +blue=009cb5 +grey=dedede #black=000000 -#grey=d6d3ce #dark_grey=808080 #blue=08246b #dark_blue=08246b @@ -31,12 +43,55 @@ tcp_keepalive=yes # require_credentials=yes #bulk_compression=yes + # You can set the PAM error text in a gateway setup (MAX 256 chars) #pamerrortxt=change your password according to policy at http://url #new_cursors=no #nego_sec_layer=0 allow_multimon=true +# +# configure login screen +# + +# top level window background color in RGB format +ls_top_window_bg_color=009cb5 + +# width and height of login screen +ls_width=350 +ls_height=430 + +# login screen background color in RGB format +ls_bg_color=dedede + +# logo +ls_logo_filename= +ls_logo_x_pos=55 +ls_logo_y_pos=50 + +# for positioning labels such as username, password etc +ls_label_x_pos=30 +ls_label_width=60 + +# for positioning text and combo boxes next to above labels +ls_input_x_pos=110 +ls_input_width=210 + +# y pos for first label and combo box +ls_input_y_pos=220 + +# OK button +ls_btn_ok_x_pos=142 +ls_btn_ok_y_pos=370 +ls_btn_ok_width=85 +ls_btn_ok_height=30 + +# Cancel button +ls_btn_cancel_x_pos=237 +ls_btn_cancel_y_pos=370 +ls_btn_cancel_width=85 +ls_btn_cancel_height=30 + [Logging] LogFile=xrdp.log LogLevel=DEBUG @@ -122,6 +177,7 @@ ip=ask port=ask3389 username=ask password=ask + # You can override the common channel settings for each session type #channel.rdpdr=true #channel.rdpsnd=true diff --git a/xrdp/xrdp_bitmap.c b/xrdp/xrdp_bitmap.c index b3faea41..c3eef7a1 100644 --- a/xrdp/xrdp_bitmap.c +++ b/xrdp/xrdp_bitmap.c @@ -115,7 +115,7 @@ xrdp_bitmap_create(int width, int height, int bpp, self->child_list = list_create(); } - self->line_size = width *Bpp; + self->line_size = width * Bpp; if (self->type == WND_TYPE_COMBO) { diff --git a/xrdp/xrdp_login_wnd.c b/xrdp/xrdp_login_wnd.c index e7066798..2e53fca5 100644 --- a/xrdp/xrdp_login_wnd.c +++ b/xrdp/xrdp_login_wnd.c @@ -254,6 +254,9 @@ xrdp_wm_show_edits(struct xrdp_wm *self, struct xrdp_bitmap *combo) char *value; struct xrdp_mod_data *mod; struct xrdp_bitmap *b; + struct xrdp_cfg_globals *globals; + + globals = &self->xrdp_config->cfg_globals; username_set = 0; @@ -289,11 +292,13 @@ xrdp_wm_show_edits(struct xrdp_wm *self, struct xrdp_bitmap *combo) insert_index++; b->parent = self->login_window; b->owner = self->login_window; - b->left = self->login_window->width >= DEFAULT_WND_LOGIN_W ? 155 : 5; - b->top = DEFAULT_ELEMENT_TOP + DEFAULT_COMBO_H + 5 + (DEFAULT_EDIT_H + 5) * count; + b->left = globals->ls_label_x_pos; + + b->top = globals->ls_input_y_pos + DEFAULT_COMBO_H + 5 + (DEFAULT_EDIT_H + 5) * count; b->id = 100 + 2 * count; name = (char *)list_get_item(mod->names, index); set_string(&b->caption1, name); + /* edit */ b = xrdp_bitmap_create(DEFAULT_EDIT_W, DEFAULT_EDIT_H, self->screen->bpp, WND_TYPE_EDIT, self); @@ -302,8 +307,10 @@ xrdp_wm_show_edits(struct xrdp_wm *self, struct xrdp_bitmap *combo) insert_index++; b->parent = self->login_window; b->owner = self->login_window; - b->left = self->login_window->width >= DEFAULT_WND_LOGIN_W ? DEFAULT_WND_LOGIN_W - DEFAULT_EDIT_W - 30 : 70; - b->top = DEFAULT_ELEMENT_TOP + DEFAULT_COMBO_H + 5 + (DEFAULT_EDIT_H + 5) * count; + b->left = globals->ls_input_x_pos; + + b->top = globals->ls_input_y_pos + DEFAULT_COMBO_H + 5 + (DEFAULT_EDIT_H + 5) * count; + b->id = 100 + 2 * count + 1; b->pointer = 1; b->tab_stop = 1; @@ -506,15 +513,20 @@ xrdp_wm_login_fill_in_combo(struct xrdp_wm *self, struct xrdp_bitmap *b) int APP_CC xrdp_login_wnd_create(struct xrdp_wm *self) { - struct xrdp_bitmap *but; - struct xrdp_bitmap *combo; - char file_path[256]; + struct xrdp_bitmap *but; + struct xrdp_bitmap *combo; + struct xrdp_cfg_globals *globals; + + char buf[256]; + char buf1[256]; int log_width; int log_height; int regular; - log_width = DEFAULT_WND_LOGIN_W; - log_height = DEFAULT_WND_LOGIN_H; + globals = &self->xrdp_config->cfg_globals; + + log_width = globals->ls_width; + log_height = globals->ls_height; regular = 1; if (self->screen->width < log_width) @@ -537,115 +549,393 @@ xrdp_login_wnd_create(struct xrdp_wm *self) list_add_item(self->screen->child_list, (long)self->login_window); self->login_window->parent = self->screen; self->login_window->owner = self->screen; - self->login_window->bg_color = self->grey; + self->login_window->bg_color = globals->ls_bg_color; + self->login_window->left = self->screen->width / 2 - self->login_window->width / 2; + self->login_window->top = self->screen->height / 2 - self->login_window->height / 2; + self->login_window->notify = xrdp_wm_login_notify; - set_string(&self->login_window->caption1, "Login to xrdp"); + + g_gethostname(buf1, 256); + g_sprintf(buf, "Login to %s", buf1); + set_string(&self->login_window->caption1, buf); if (regular) { - /* image */ - but = xrdp_bitmap_create(4, 4, self->screen->bpp, WND_TYPE_IMAGE, self); + /* if logo image not specified, use default */ + if (globals->ls_logo_filename[0] == 0) + g_snprintf(globals->ls_logo_filename, 255, "%s/xrdp_logo.bmp", XRDP_SHARE_PATH); - if (self->screen->bpp > 8) - { - g_snprintf(file_path, 255, "%s/xrdp24b.bmp", XRDP_SHARE_PATH); - } - else - { - g_snprintf(file_path, 255, "%s/xrdp256.bmp", XRDP_SHARE_PATH); - } - - xrdp_bitmap_load(but, file_path, self->palette); - but->parent = self->screen; - but->owner = self->screen; - but->left = self->screen->width - but->width; - but->top = self->screen->height - but->height; - list_add_item(self->screen->child_list, (long)but); - - /* image */ + /* logo image */ but = xrdp_bitmap_create(4, 4, self->screen->bpp, WND_TYPE_IMAGE, self); - if (self->screen->bpp > 8) - { - g_snprintf(file_path, 255, "%s/ad24b.bmp", XRDP_SHARE_PATH); - } - else - { - g_snprintf(file_path, 255, "%s/ad256.bmp", XRDP_SHARE_PATH); - } + if (self->screen->bpp <= 8) + g_snprintf(globals->ls_logo_filename, 255, "%s/ad256.bmp", XRDP_SHARE_PATH); - xrdp_bitmap_load(but, file_path, self->palette); + xrdp_bitmap_load(but, globals->ls_logo_filename, self->palette); but->parent = self->login_window; but->owner = self->login_window; - but->left = 10; - but->top = 30; + but->left = globals->ls_logo_x_pos; + but->top = globals->ls_logo_y_pos; list_add_item(self->login_window->child_list, (long)but); } /* label */ - but = xrdp_bitmap_create(60, DEFAULT_EDIT_H, self->screen->bpp, WND_TYPE_LABEL, self); + but = xrdp_bitmap_create(globals->ls_label_width, DEFAULT_EDIT_H, self->screen->bpp, WND_TYPE_LABEL, self); list_add_item(self->login_window->child_list, (long)but); but->parent = self->login_window; but->owner = self->login_window; - but->left = regular ? 155 : 5; - but->top = DEFAULT_ELEMENT_TOP; - set_string(&but->caption1, "Module"); + but->left = globals->ls_label_x_pos; + but->top = globals->ls_input_y_pos; + set_string(&but->caption1, "Session"); /* combo */ - combo = xrdp_bitmap_create(DEFAULT_COMBO_W, DEFAULT_COMBO_H, self->screen->bpp, WND_TYPE_COMBO, self); + combo = xrdp_bitmap_create(globals->ls_input_width, DEFAULT_COMBO_H, + self->screen->bpp, WND_TYPE_COMBO, self); list_add_item(self->login_window->child_list, (long)combo); combo->parent = self->login_window; combo->owner = self->login_window; - combo->left = regular ? DEFAULT_WND_LOGIN_W - DEFAULT_COMBO_W - 30 : 70; - combo->top = DEFAULT_ELEMENT_TOP; + combo->left = globals->ls_input_x_pos; + combo->top = globals->ls_input_y_pos; combo->id = 6; combo->tab_stop = 1; xrdp_wm_login_fill_in_combo(self, combo); - /* button */ - but = xrdp_bitmap_create(DEFAULT_BUTTON_W, DEFAULT_BUTTON_H, self->screen->bpp, WND_TYPE_BUTTON, self); + /* OK button */ + but = xrdp_bitmap_create(globals->ls_btn_ok_width, globals->ls_btn_ok_height, + self->screen->bpp, WND_TYPE_BUTTON, self); list_add_item(self->login_window->child_list, (long)but); but->parent = self->login_window; but->owner = self->login_window; - but->left = regular ? DEFAULT_WND_LOGIN_W - ((DEFAULT_BUTTON_W + 10) * 3) - 10 : 30; - but->top = DEFAULT_WND_LOGIN_H - DEFAULT_BUTTON_H - 15; + but->left = globals->ls_btn_ok_x_pos; + but->top = globals->ls_btn_ok_y_pos; but->id = 3; set_string(&but->caption1, "OK"); but->tab_stop = 1; self->login_window->default_button = but; - /* button */ - but = xrdp_bitmap_create(DEFAULT_BUTTON_W, DEFAULT_BUTTON_H, self->screen->bpp, WND_TYPE_BUTTON, self); + /* Cancel button */ + but = xrdp_bitmap_create(globals->ls_btn_cancel_width, + globals->ls_btn_cancel_height, self->screen->bpp, + WND_TYPE_BUTTON, self); list_add_item(self->login_window->child_list, (long)but); but->parent = self->login_window; but->owner = self->login_window; - but->left = regular ? DEFAULT_WND_LOGIN_W - ((DEFAULT_BUTTON_W + 10) * 2) - 10 : ((log_width - 30) - DEFAULT_BUTTON_W); - but->top = DEFAULT_WND_LOGIN_H - DEFAULT_BUTTON_H - 15; + but->left = globals->ls_btn_cancel_x_pos; + but->top = globals->ls_btn_cancel_y_pos; but->id = 2; set_string(&but->caption1, "Cancel"); but->tab_stop = 1; self->login_window->esc_button = but; - if (regular) + /* labels and edits */ + xrdp_wm_show_edits(self, combo); + + return 0; +} + +/** + * Load configuration from xrdp.ini file + * + * @return 0 on success, -1 on failure + *****************************************************************************/ +int APP_CC +load_xrdp_config(struct xrdp_config *config, int bpp) +{ + struct xrdp_cfg_globals *globals; + + struct list *names; + struct list *values; + + char *n; + char *v; + char buf[256]; + int fd; + int i; + + if (!config) + return -1; + + globals = &config->cfg_globals; + + /* set default values incase we can't get them from xrdp.ini file */ + globals->ini_version = 1; + globals->ls_top_window_bg_color = HCOLOR(bpp, xrdp_wm_htoi("009cb5")); + globals->ls_bg_color = HCOLOR(bpp, xrdp_wm_htoi("dedede")); + globals->ls_width = 350; + globals->ls_height = 350; + globals->ls_bg_color = 0xdedede; + globals->ls_logo_x_pos = 63; + globals->ls_logo_y_pos = 50; + globals->ls_label_x_pos = 30; + globals->ls_label_width = 60; + globals->ls_input_x_pos = 110; + globals->ls_input_width = 210; + globals->ls_input_y_pos = 150; + globals->ls_btn_ok_x_pos = 150; + globals->ls_btn_ok_y_pos = 300; + globals->ls_btn_ok_width = 85; + globals->ls_btn_ok_height =30; + globals->ls_btn_cancel_x_pos = 245; + globals->ls_btn_cancel_y_pos = 300; + globals->ls_btn_cancel_width = 85; + globals->ls_btn_cancel_height = 30; + + /* open xrdp.ini file */ + g_snprintf(buf, 255, "%s/xrdp.ini", XRDP_CFG_PATH); + if ((fd = g_file_open(buf)) < 0) { - /* button */ - but = xrdp_bitmap_create(DEFAULT_BUTTON_W, DEFAULT_BUTTON_H, self->screen->bpp, WND_TYPE_BUTTON, self); - list_add_item(self->login_window->child_list, (long)but); - but->parent = self->login_window; - but->owner = self->login_window; - but->left = DEFAULT_WND_LOGIN_W - (DEFAULT_BUTTON_W + 10) - 10; - but->top = DEFAULT_WND_LOGIN_H - DEFAULT_BUTTON_H - 15; - but->id = 1; - set_string(&but->caption1, "Help"); - but->tab_stop = 1; + log_message(LOG_LEVEL_ERROR,"load_config: Could not read " + "xrdp.ini file %s", buf); + return -1; + } - /* labels and edits */ - xrdp_wm_show_edits(self, combo); + names = list_create(); + values = list_create(); + names->auto_free = 1; + values->auto_free = 1; + + if (file_read_section(fd, "globals", names, values) != 0) + { + list_delete(names); + list_delete(values); + g_file_close(fd); + log_message(LOG_LEVEL_ERROR,"load_config: Could not read globals " + "section from xrdp.ini file %s", buf); + return -1; + } + + for (i = 0; i < names->count; i++) + { + n = (char *) list_get_item(names, i); + v = (char *) list_get_item(values, i); + + /* + * parse globals section + */ + + if (g_strncmp(n, "ini_version", 64) == 0) + globals->ini_version = g_atoi(v); + + else if (g_strncmp(n, "bitmap_cache", 64) == 0) + globals->use_bitmap_cache = g_text2bool(v); + + else if (g_strncmp(n, "bitmap_compression", 64) == 0) + globals->use_bitmap_compression = g_text2bool(v); + + else if (g_strncmp(n, "port", 64) == 0) + globals->port = g_atoi(v); + + else if (g_strncmp(n, "crypt_level", 64) == 0) + { + if (g_strcmp(v, "low") == 0) + globals->crypt_level = 1; + else if (g_strcmp(v, "medium") == 0) + globals->crypt_level = 2; + else + globals->crypt_level = 3; + } + + else if (g_strncmp(n, "allow_channels", 64) == 0) + globals->allow_channels = g_text2bool(v); + + else if (g_strncmp(n, "max_bpp", 64) == 0) + globals->max_bpp = g_atoi(v); + + else if (g_strncmp(n, "fork", 64) == 0) + globals->fork = g_text2bool(v); + + else if (g_strncmp(n, "tcp_nodelay", 64) == 0) + globals->tcp_nodelay = g_text2bool(v); + + else if (g_strncmp(n, "tcp_keepalive", 64) == 0) + globals->tcp_keepalive = g_text2bool(v); + + else if (g_strncmp(n, "tcp_send_buffer_bytes", 64) == 0) + globals->tcp_send_buffer_bytes = g_atoi(v); + + else if (g_strncmp(n, "tcp_recv_buffer_bytes", 64) == 0) + globals->tcp_recv_buffer_bytes = g_atoi(v); + + /* colors */ + + else if (g_strncmp(n, "grey", 64) == 0) + globals->grey = xrdp_wm_htoi(v); + + else if (g_strncmp(n, "black", 64) == 0) + globals->black = xrdp_wm_htoi(v); + + else if (g_strncmp(n, "dark_grey", 64) == 0) + globals->dark_grey = xrdp_wm_htoi(v); + + else if (g_strncmp(n, "blue", 64) == 0) + globals->blue = xrdp_wm_htoi(v); + + else if (g_strncmp(n, "dark_blue", 64) == 0) + globals->dark_blue = xrdp_wm_htoi(v); + + else if (g_strncmp(n, "white", 64) == 0) + globals->white = xrdp_wm_htoi(v); + + else if (g_strncmp(n, "red", 64) == 0) + globals->red = xrdp_wm_htoi(v); + + else if (g_strncmp(n, "green", 64) == 0) + globals->green = xrdp_wm_htoi(v); + + else if (g_strncmp(n, "background", 64) == 0) + globals->background = xrdp_wm_htoi(v); + + /* misc stuff */ + + else if (g_strncmp(n, "autorun", 255) == 0) + g_strncpy(globals->autorun, v, 255); + + else if (g_strncmp(n, "hidelogwindow", 64) == 0) + globals->hidelogwindow = g_text2bool(v); + + else if (g_strncmp(n, "require_credentials", 64) == 0) + globals->require_credentials = g_text2bool(v); + + else if (g_strncmp(n, "bulk_compression", 64) == 0) + globals->bulk_compression = g_text2bool(v); + + else if (g_strncmp(n, "new_cursors", 64) == 0) + globals->new_cursors = g_text2bool(v); + + else if (g_strncmp(n, "nego_sec_layer", 64) == 0) + globals->nego_sec_layer = g_atoi(v); + + else if (g_strncmp(n, "allow_multimon", 64) == 0) + globals->allow_multimon = g_text2bool(v); + /* login screen values */ + else if (g_strncmp(n, "ls_top_window_bg_color", 64) == 0) + globals->ls_top_window_bg_color = HCOLOR(bpp, xrdp_wm_htoi(v)); + + else if (g_strncmp(n, "ls_width", 64) == 0) + globals->ls_width = g_atoi(v); + + else if (g_strncmp(n, "ls_height", 64) == 0) + globals->ls_height = g_atoi(v); + + else if (g_strncmp(n, "ls_bg_color", 64) == 0) + globals->ls_bg_color = HCOLOR(bpp, xrdp_wm_htoi(v)); + + else if (g_strncmp(n, "ls_logo_filename", 255) == 0) + { + g_strncpy(globals->ls_logo_filename, v, 255); + globals->ls_logo_filename[255] = 0; + } + + else if (g_strncmp(n, "ls_logo_x_pos", 64) == 0) + globals->ls_logo_x_pos = g_atoi(v); + + else if (g_strncmp(n, "ls_logo_y_pos", 64) == 0) + globals->ls_logo_y_pos = g_atoi(v); + + else if (g_strncmp(n, "ls_label_x_pos", 64) == 0) + globals->ls_label_x_pos = g_atoi(v); + + else if (g_strncmp(n, "ls_label_width", 64) == 0) + globals->ls_label_width = g_atoi(v); + + else if (g_strncmp(n, "ls_input_x_pos", 64) == 0) + globals->ls_input_x_pos = g_atoi(v); + + else if (g_strncmp(n, "ls_input_width", 64) == 0) + globals->ls_input_width = g_atoi(v); + + else if (g_strncmp(n, "ls_input_y_pos", 64) == 0) + globals->ls_input_y_pos = g_atoi(v); + + else if (g_strncmp(n, "ls_btn_ok_x_pos", 64) == 0) + globals->ls_btn_ok_x_pos = g_atoi(v); + + else if (g_strncmp(n, "ls_btn_ok_y_pos", 64) == 0) + globals->ls_btn_ok_y_pos = g_atoi(v); + + else if (g_strncmp(n, "ls_btn_ok_width", 64) == 0) + globals->ls_btn_ok_width = g_atoi(v); + + else if (g_strncmp(n, "ls_btn_ok_height", 64) == 0) + globals->ls_btn_ok_height = g_atoi(v); + + else if (g_strncmp(n, "ls_btn_cancel_x_pos", 64) == 0) + globals->ls_btn_cancel_x_pos = g_atoi(v); + + else if (g_strncmp(n, "ls_btn_cancel_y_pos", 64) == 0) + globals->ls_btn_cancel_y_pos = g_atoi(v); + + else if (g_strncmp(n, "ls_btn_cancel_width", 64) == 0) + globals->ls_btn_cancel_width = g_atoi(v); + + else if (g_strncmp(n, "ls_btn_cancel_height", 64) == 0) + globals->ls_btn_cancel_height = g_atoi(v); + } + +#if 0 + g_writeln("ini_version: %d", globals->ini_version); + g_writeln("use_bitmap_cache: %d", globals->use_bitmap_cache); + g_writeln("use_bitmap_compression: %d", globals->use_bitmap_compression); + g_writeln("port: %d", globals->port); + g_writeln("crypt_level: %d", globals->crypt_level); + g_writeln("allow_channels: %d", globals->allow_channels); + g_writeln("max_bpp: %d", globals->max_bpp); + g_writeln("fork: %d", globals->fork); + g_writeln("tcp_nodelay: %d", globals->tcp_nodelay); + g_writeln("tcp_keepalive: %d", globals->tcp_keepalive); + g_writeln("tcp_send_buffer_bytes: %d", globals->tcp_send_buffer_bytes); + g_writeln("tcp_recv_buffer_bytes: %d", globals->tcp_recv_buffer_bytes); + g_writeln("new_cursors: %d", globals->new_cursors); + g_writeln("allow_multimon: %d", globals->allow_multimon); + + g_writeln("grey: %d", globals->grey); + g_writeln("black: %d", globals->black); + g_writeln("dark_grey: %d", globals->dark_grey); + g_writeln("blue: %d", globals->blue); + g_writeln("dark_blue: %d", globals->dark_blue); + g_writeln("white: %d", globals->white); + g_writeln("red: %d", globals->red); + g_writeln("green: %d", globals->green); + g_writeln("background: %d", globals->background); + + g_writeln("autorun: %s", globals->autorun); + g_writeln("hidelogwindow: %d", globals->hidelogwindow); + g_writeln("require_credentials: %d", globals->require_credentials); + g_writeln("bulk_compression: %d", globals->bulk_compression); + g_writeln("new_cursors: %d", globals->new_cursors); + g_writeln("nego_sec_layer: %d", globals->nego_sec_layer); + g_writeln("allow_multimon: %d", globals->allow_multimon); + + g_writeln("ls_top_window_bg_color: %x", globals->ls_top_window_bg_color); + g_writeln("ls_width: %d", globals->ls_width); + g_writeln("ls_height: %d", globals->ls_height); + g_writeln("ls_bg_color: %x", globals->ls_bg_color); + g_writeln("ls_logo_filename: %s", globals->ls_logo_filename); + g_writeln("ls_logo_x_pos: %d", globals->ls_logo_x_pos); + g_writeln("ls_logo_y_pos: %d", globals->ls_logo_y_pos); + g_writeln("ls_label_x_pos: %d", globals->ls_label_x_pos); + g_writeln("ls_label_width: %d", globals->ls_label_width); + g_writeln("ls_input_x_pos: %d", globals->ls_input_x_pos); + g_writeln("ls_input_width: %d", globals->ls_input_width); + g_writeln("ls_input_y_pos: %d", globals->ls_input_y_pos); + g_writeln("ls_btn_ok_x_pos: %d", globals->ls_btn_ok_x_pos); + g_writeln("ls_btn_ok_y_pos: %d", globals->ls_btn_ok_y_pos); + g_writeln("ls_btn_ok_width: %d", globals->ls_btn_ok_width); + g_writeln("ls_btn_ok_height: %d", globals->ls_btn_ok_height); + g_writeln("ls_btn_cancel_x_pos: %d", globals->ls_btn_cancel_x_pos); + g_writeln("ls_btn_cancel_y_pos: %d", globals->ls_btn_cancel_y_pos); + g_writeln("ls_btn_cancel_width: %d", globals->ls_btn_cancel_width); + g_writeln("ls_btn_cancel_height: %d", globals->ls_btn_cancel_height); +#endif + + list_delete(names); + list_delete(values); + g_file_close(fd); return 0; } diff --git a/xrdp/xrdp_logo.bmp b/xrdp/xrdp_logo.bmp Binary files differnew file mode 100644 index 00000000..58ce50ff --- /dev/null +++ b/xrdp/xrdp_logo.bmp diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index 560ebedb..494d79d3 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -238,7 +238,7 @@ xrdp_mm_send_login(struct xrdp_mm *self) /*****************************************************************************/ /* returns error */ /* this goes through the login_names looking for one called 'aname' - then it copies the corisponding login_values item into 'dest' + then it copies the corresponding login_values item into 'dest' 'dest' must be at least 'dest_len' + 1 bytes in size */ static int APP_CC xrdp_mm_get_value(struct xrdp_mm *self, char *aname, char *dest, int dest_len) @@ -417,6 +417,7 @@ xrdp_mm_setup_mod1(struct xrdp_mm *self) self->mod->server_create_os_surface_bpp = server_create_os_surface_bpp; self->mod->server_paint_rect_bpp = server_paint_rect_bpp; self->mod->server_composite = server_composite; + self->mod->server_paint_rects = server_paint_rects; } } @@ -692,12 +693,12 @@ xrdp_mm_process_rail_create_window(struct xrdp_mm* self, struct stream* s) int bytes; int rv; struct rail_window_state_order rwso; - + g_memset(&rwso, 0, sizeof(rwso)); in_uint32_le(s, window_id); - + g_writeln("xrdp_mm_process_rail_create_window: 0x%8.8x", window_id); - + in_uint32_le(s, rwso.owner_window_id); in_uint32_le(s, rwso.style); in_uint32_le(s, rwso.extended_style); @@ -771,12 +772,12 @@ xrdp_mm_process_rail_configure_window(struct xrdp_mm* self, struct stream* s) int bytes; int rv; struct rail_window_state_order rwso; - + g_memset(&rwso, 0, sizeof(rwso)); in_uint32_le(s, window_id); - + g_writeln("xrdp_mm_process_rail_configure_window: 0x%8.8x", window_id); - + in_uint32_le(s, rwso.client_offset_x); in_uint32_le(s, rwso.client_offset_y); in_uint32_le(s, rwso.client_area_width); @@ -834,7 +835,7 @@ xrdp_mm_process_rail_destroy_window(struct xrdp_mm* self, struct stream* s) { int window_id; int rv; - + in_uint32_le(s, window_id); g_writeln("xrdp_mm_process_rail_destroy_window 0x%8.8x", window_id); rv = libxrdp_orders_init(self->wm->session); @@ -853,7 +854,7 @@ xrdp_mm_process_rail_show_window(struct xrdp_mm* self, struct stream* s) int rv; int flags; struct rail_window_state_order rwso; - + g_memset(&rwso, 0, sizeof(rwso)); in_uint32_le(s, window_id); in_uint32_le(s, flags); @@ -877,13 +878,13 @@ xrdp_mm_process_rail_update_window_text(struct xrdp_mm* self, struct stream* s) int rv = 0; int window_id; struct rail_window_state_order rwso; - + g_writeln("xrdp_mm_process_rail_update_window_text:"); - + in_uint32_le(s, window_id); in_uint32_le(s, flags); g_writeln(" update window title info: 0x%8.8x", window_id); - + g_memset(&rwso, 0, sizeof(rwso)); in_uint32_le(s, size); /* title size */ rwso.title_info = g_malloc(size + 1, 0); @@ -894,7 +895,7 @@ xrdp_mm_process_rail_update_window_text(struct xrdp_mm* self, struct stream* s) rv = libxrdp_window_new_update(self->wm->session, window_id, &rwso, flags); rv = libxrdp_orders_send(self->wm->session); g_writeln(" set window title %s %d", rwso.title_info, rv); - + g_free(rwso.title_info); return rv; @@ -909,14 +910,14 @@ xrdp_mm_process_rail_drawing_orders(struct xrdp_mm* self, struct trans* trans) struct stream* s; int order_type; int rv = 0; - + s = trans_get_in_s(trans); if (s == 0) { return 1; } in_uint32_le(s, order_type); - + switch(order_type) { case 2: /* create_window */ @@ -934,7 +935,7 @@ xrdp_mm_process_rail_drawing_orders(struct xrdp_mm* self, struct trans* trans) default: break; } - + return rv; } @@ -1511,7 +1512,7 @@ getPAMError(const int pamError, char *text, int text_bytes) case PAM_USER_UNKNOWN: return "User not known to the underlying authentication module"; case PAM_MAXTRIES: - return "Have exhasted maximum number of retries for service."; + return "Have exhausted maximum number of retries for service."; case PAM_NEW_AUTHTOK_REQD: return "Authentication token is no longer valid; new one required."; case PAM_ACCT_EXPIRED: @@ -2072,7 +2073,7 @@ server_paint_rect_bpp(struct xrdp_mod* mod, int x, int y, int cx, int cy, struct xrdp_wm* wm; struct xrdp_bitmap* b; struct xrdp_painter* p; - + p = (struct xrdp_painter*)(mod->painter); if (p == 0) { @@ -2099,7 +2100,7 @@ server_composite(struct xrdp_mod* mod, int srcidx, int srcformat, struct xrdp_bitmap* msk; struct xrdp_painter* p; struct xrdp_os_bitmap_item* bi; - + p = (struct xrdp_painter*)(mod->painter); if (p == 0) { @@ -2138,6 +2139,38 @@ server_composite(struct xrdp_mod* mod, int srcidx, int srcformat, /*****************************************************************************/ int DEFAULT_CC +server_paint_rects(struct xrdp_mod* mod, int num_drects, short *drects, + int num_crects, short *crects, + char *data, int width, int height, int flags) +{ + struct xrdp_wm* wm; + struct xrdp_painter* p; + struct xrdp_bitmap *b; + short *s; + int index; + + //g_writeln("server_paint_rects:"); + wm = (struct xrdp_wm*)(mod->wm); + p = (struct xrdp_painter*)(mod->painter); + if (p == 0) + { + return 0; + } + b = xrdp_bitmap_create_with_data(width, height, wm->screen->bpp, + data, wm); + s = crects; + for (index = 0; index < num_crects; index++) + { + xrdp_painter_copy(p, b, wm->target_surface, s[0], s[1], s[2], s[3], + s[0], s[1]); + s += 4; + } + xrdp_bitmap_delete(b); + return 0; +} + +/*****************************************************************************/ +int DEFAULT_CC server_set_pointer(struct xrdp_mod *mod, int x, int y, char *data, char *mask) { @@ -2493,7 +2526,7 @@ find_name_in_lists(char *inName, struct list *names) for (index = 0; index < names->count; index++) { name = (char *)list_get_item(names, index); - if ( (name != 0) && (g_strncmp(name, inName, MAX_CHANNEL_NAME) == 0) ) + if ( (name != 0) && (g_strncasecmp(name, inName, MAX_CHANNEL_NAME) == 0) ) { reply = index; break; /* stop loop - item found*/ @@ -2759,7 +2792,7 @@ server_create_os_surface_bpp(struct xrdp_mod* mod, int rdpindex, struct xrdp_wm* wm; struct xrdp_bitmap* bitmap; int error; - + wm = (struct xrdp_wm*)(mod->wm); bitmap = xrdp_bitmap_create(width, height, bpp, WND_TYPE_OFFSCREEN, wm); diff --git a/xrdp/xrdp_process.c b/xrdp/xrdp_process.c index 4c52eaac..78576f1f 100644 --- a/xrdp/xrdp_process.c +++ b/xrdp/xrdp_process.c @@ -61,7 +61,7 @@ xrdp_process_delete(struct xrdp_process *self) /*****************************************************************************/ static int APP_CC -xrdp_process_loop(struct xrdp_process *self) +xrdp_process_loop(struct xrdp_process *self, struct stream *s) { int rv; @@ -69,7 +69,7 @@ xrdp_process_loop(struct xrdp_process *self) if (self->session != 0) { - rv = libxrdp_process_data(self->session); + rv = libxrdp_process_data(self->session, s); } if ((self->wm == 0) && (self->session->up_and_running) && (rv == 0)) @@ -115,17 +115,116 @@ xrdp_process_mod_end(struct xrdp_process *self) } /*****************************************************************************/ +static int APP_CC +xrdp_process_get_pdu_bytes(const char *aheader) +{ + int rv; + const tui8 *header; + + rv = -1; + header = (const tui8 *) aheader; + if (header[0] == 0x03) + { + /* TPKT */ + rv = (header[2] << 8) | header[3]; + } + else if (header[0] == 0x30) + { + /* TSRequest (NLA) */ + if (header[1] & 0x80) + { + if ((header[1] & ~(0x80)) == 1) + { + rv = header[2]; + rv += 3; + } + else if ((header[1] & ~(0x80)) == 2) + { + rv = (header[2] << 8) | header[3]; + rv += 4; + } + else + { + g_writeln("xrdp_process_get_packet_bytes: error TSRequest!"); + return -1; + } + } + else + { + rv = header[1]; + rv += 2; + } + } + else + { + /* Fast-Path */ + if (header[1] & 0x80) + { + rv = ((header[1] & 0x7F) << 8) | header[2]; + } + else + { + rv = header[1]; + } + } + return rv; +} + +/*****************************************************************************/ static int DEFAULT_CC xrdp_process_data_in(struct trans *self) { struct xrdp_process *pro; + struct stream *s; + int len; DEBUG(("xrdp_process_data_in")); pro = (struct xrdp_process *)(self->callback_data); - if (xrdp_process_loop(pro) != 0) + s = pro->server_trans->in_s; + switch (pro->server_trans->extra_flags) { - return 1; + case 0: + /* early in connection sequence, we're in this mode */ + if (xrdp_process_loop(pro, 0) != 0) + { + g_writeln("xrdp_process_data_in: " + "xrdp_process_loop failed"); + return 1; + } + if (pro->session->up_and_running) + { + pro->server_trans->extra_flags = 1; + pro->server_trans->header_size = 4; + } + break; + + case 1: + /* we have enough now to get the PDU bytes */ + len = xrdp_process_get_pdu_bytes(s->p); + if (len == -1) + { + g_writeln("xrdp_process_data_in: " + "xrdp_process_get_packet_bytes failed"); + return 1; + } + pro->server_trans->header_size = len; + pro->server_trans->extra_flags = 2; + break; + + case 2: + /* the whole PDU is read in now process */ + s->p = s->data; + if (xrdp_process_loop(pro, s) != 0) + { + g_writeln("xrdp_process_data_in: " + "xrdp_process_loop failed"); + return 1; + } + init_stream(s, 0); + pro->server_trans->header_size = 4; + pro->server_trans->extra_flags = 1; + break; } return 0; @@ -145,8 +244,12 @@ xrdp_process_main_loop(struct xrdp_process *self) DEBUG(("xrdp_process_main_loop")); self->status = 1; + self->server_trans->extra_flags = 0; + self->server_trans->header_size = 0; + self->server_trans->no_stream_init_on_data_in = 1; self->server_trans->trans_data_in = xrdp_process_data_in; self->server_trans->callback_data = self; + init_stream(self->server_trans->in_s, 8192 * 4); self->session = libxrdp_init((tbus)self, self->server_trans); /* this callback function is in xrdp_wm.c */ self->session->callback = callback; diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h index 3811b16b..7d7eb72c 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -18,6 +18,9 @@ * types */ +#ifndef _XRDP_TYPES_H_ +#define _XRDP_TYPES_H_ + #define DEFAULT_STRING_LEN 255 #define LOG_WINDOW_CHAR_PER_LINE 60 @@ -136,7 +139,11 @@ struct xrdp_mod int srcx, int srcy, int mskx, int msky, int dstx, int dsty, int width, int height, int dstformat); - long server_dumby[100 - 42]; /* align, 100 minus the number of server + int (*server_paint_rects)(struct xrdp_mod* v, + int num_drects, short *drects, + int num_crects, short *crects, + char *data, int width, int height, int flags); + long server_dumby[100 - 43]; /* align, 100 minus the number of server functions above */ /* common */ long handle; /* pointer to self as int */ @@ -342,6 +349,9 @@ struct xrdp_wm int allowedchannels[MAX_NR_CHANNELS]; int allowedinitialized ; char pamerrortxt[256]; + + /* configuration derived from xrdp.ini */ + struct xrdp_config *xrdp_config; }; /* rdp process */ @@ -456,8 +466,8 @@ struct xrdp_bitmap #define DEFAULT_COMBO_H 21 #define DEFAULT_EDIT_W 210 #define DEFAULT_EDIT_H 21 -#define DEFAULT_WND_LOGIN_W 500 -#define DEFAULT_WND_LOGIN_H 250 +#define DEFAULT_WND_LOGIN_W 425 +#define DEFAULT_WND_LOGIN_H 475 #define DEFAULT_WND_HELP_W 340 #define DEFAULT_WND_HELP_H 300 #define DEFAULT_WND_LOG_W 400 @@ -492,3 +502,83 @@ struct xrdp_startup_params int send_buffer_bytes; int recv_buffer_bytes; }; + +/* + * For storing xrdp.ini configuration settings + */ + +struct xrdp_cfg_globals +{ + int ini_version; /* xrdp.ini file version number */ + int use_bitmap_cache; + int use_bitmap_compression; + int port; + int crypt_level; /* low=1, medium=2, high=3 */ + int allow_channels; + int max_bpp; + int fork; + int tcp_nodelay; + int tcp_keepalive; + int tcp_send_buffer_bytes; + int tcp_recv_buffer_bytes; + char autorun[256]; + int hidelogwindow; + int require_credentials; + int bulk_compression; + int new_cursors; + int nego_sec_layer; + int allow_multimon; + + /* colors */ + + int grey; + int black; + int dark_grey; + int blue; + int dark_blue; + int white; + int red; + int green; + int background; + + /* login screen */ + int ls_top_window_bg_color; /* top level window background color */ + int ls_width; /* window width */ + int ls_height; /* window height */ + int ls_bg_color; /* background color */ + char ls_logo_filename[256]; /* logo filename */ + int ls_logo_x_pos; /* logo x co-ordinate */ + int ls_logo_y_pos; /* logo y co-ordinate */ + int ls_label_x_pos; /* x pos of labels */ + int ls_label_width; /* width of labels */ + int ls_input_x_pos; /* x pos of text and combo boxes */ + int ls_input_width; /* width of input and combo boxes */ + int ls_input_y_pos; /* y pos for for first label and combo box */ + int ls_btn_ok_x_pos; /* x pos for OK button */ + int ls_btn_ok_y_pos; /* y pos for OK button */ + int ls_btn_ok_width; /* width of OK button */ + int ls_btn_ok_height; /* height of OK button */ + int ls_btn_cancel_x_pos; /* x pos for Cancel button */ + int ls_btn_cancel_y_pos; /* y pos for Cancel button */ + int ls_btn_cancel_width; /* width of Cancel button */ + int ls_btn_cancel_height; /* height of Cancel button */ +}; + +struct xrdp_cfg_logging +{ + +}; + +struct xrdp_cfg_channels +{ + +}; + +struct xrdp_config +{ + struct xrdp_cfg_globals cfg_globals; + struct xrdp_cfg_logging cfg_logging; + struct xrdp_cfg_channels cfg_channels; +}; + +#endif diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c index bba25c34..ffc6d3a2 100644 --- a/xrdp/xrdp_wm.c +++ b/xrdp/xrdp_wm.c @@ -58,6 +58,10 @@ xrdp_wm_create(struct xrdp_process *owner, xrdp_wm_set_login_mode(self, 0); self->target_surface = self->screen; self->current_surface_index = 0xffff; /* screen */ + + /* to store configuration from xrdp.ini */ + self->xrdp_config = g_malloc(sizeof(struct xrdp_config), 1); + return self; } @@ -79,6 +83,10 @@ xrdp_wm_delete(struct xrdp_wm *self) /* free default font */ xrdp_font_delete(self->default_font); g_delete_wait_obj(self->login_mode_event); + + if (self->xrdp_config) + g_free(self->xrdp_config); + /* free self */ g_free(self); } @@ -315,7 +323,8 @@ xrdp_wm_set_pointer(struct xrdp_wm *self, int cache_idx) /*****************************************************************************/ /* convert hex string to int */ -unsigned int xrdp_wm_htoi (const char *ptr) +unsigned int APP_CC +xrdp_wm_htoi (const char *ptr) { unsigned int value = 0; char ch = *ptr; @@ -535,12 +544,18 @@ xrdp_wm_init(struct xrdp_wm *self) char cfg_file[256]; char autorun_name[256]; + load_xrdp_config(self->xrdp_config, self->screen->bpp); + xrdp_wm_load_static_colors_plus(self, autorun_name); xrdp_wm_load_static_pointers(self); - self->screen->bg_color = self->background; + self->screen->bg_color = self->xrdp_config->cfg_globals.ls_top_window_bg_color; if (self->session->client_info->rdp_autologin || (autorun_name[0] != 0)) { + /* + * NOTE: this should eventually be accessed from self->xrdp_config + */ + g_snprintf(cfg_file, 255, "%s/xrdp.ini", XRDP_CFG_PATH); fd = g_file_open(cfg_file); /* xrdp.ini */ @@ -561,7 +576,7 @@ xrdp_wm_init(struct xrdp_wm *self) { if (autorun_name[0] == 0) { - /* if no doamin is passed, and no autorun in xrdp.ini, + /* if no domain is passed, and no autorun in xrdp.ini, use the first item in the xrdp.ini file thats not named 'globals' or 'Logging' or 'channels' */ @@ -1028,7 +1043,7 @@ xrdp_wm_mouse_move(struct xrdp_wm *self, int x, int y) b = xrdp_wm_at_pos(self->screen, x, y, 0); - if (b == 0) /* if b is null, the movment must be over the screen */ + if (b == 0) /* if b is null, the movement must be over the screen */ { if (self->screen->pointer != self->current_pointer) { @@ -1036,7 +1051,7 @@ xrdp_wm_mouse_move(struct xrdp_wm *self, int x, int y) self->current_pointer = self->screen->pointer; } - if (self->mm->mod != 0) /* if screen is mod controled */ + if (self->mm->mod != 0) /* if screen is mod controlled */ { if (self->mm->mod->mod_event != 0) { @@ -1175,7 +1190,7 @@ xrdp_wm_mouse_click(struct xrdp_wm *self, int x, int y, int but, int down) if (control == 0) { - if (self->mm->mod != 0) /* if screen is mod controled */ + if (self->mm->mod != 0) /* if screen is mod controlled */ { if (self->mm->mod->mod_event != 0) { @@ -1724,7 +1739,7 @@ xrdp_wm_login_mode_changed(struct xrdp_wm *self) } /*****************************************************************************/ -/* this is the log windows nofity function */ +/* this is the log windows notify function */ static int DEFAULT_CC xrdp_wm_log_wnd_notify(struct xrdp_bitmap *wnd, struct xrdp_bitmap *sender, diff --git a/xrdpvr/xrdpvr.c b/xrdpvr/xrdpvr.c index a6e7e894..6147a66e 100644 --- a/xrdpvr/xrdpvr.c +++ b/xrdpvr/xrdpvr.c @@ -2,6 +2,7 @@ * xrdp: A Remote Desktop Protocol server. * * Copyright (C) Laxmikant Rashinkar 2012-2013 LK.Rashinkar@gmail.com + * Copyright (C) Jay Sorg 2013 jay.sorg@gmail.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +31,8 @@ int g_audio_index = -1; /*****************************************************************************/ /* produce a hex dump */ -void hexdump(char *p, int len) +void +hexdump(char *p, int len) { unsigned char *line; int i; @@ -83,36 +85,13 @@ void hexdump(char *p, int len) int xrdpvr_init_player(void *channel, int stream_id, char *filename) { + printf("xrdpvr_init_player:\n"); if ((channel == NULL) || (stream_id <= 0) || (filename == NULL)) { 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)) - { - printf("xrdpvr_set_video_format() failed\n"); - return -1; - } - - /* TODO */ - sleep(3); - - /* ask client to get audio format from media file */ - if (xrdpvr_set_audio_format(channel, 101)) - { - printf("xrdpvr_set_audio_format() failed\n"); - return 1; - } + xrdpvr_send_init(channel); } /** @@ -195,7 +174,8 @@ xrdpvr_play_media(void *channel, int stream_id, char *filename) { int i; - printf("$$$$$$ xrdpvr_play_media: setting audioTimeout & videoTimeout to -1\n"); + printf("$$$$$$ xrdpvr_play_media: setting audioTimeout & " + "videoTimeout to -1\n"); g_psi.videoTimeout = -1; g_psi.audioTimeout = -1; @@ -218,28 +198,39 @@ xrdpvr_play_media(void *channel, int stream_id, char *filename) return -1; } -#if 0 +#if 1 /* print media info to standard out */ av_dump_format(g_psi.p_format_ctx, 0, filename, 0); #endif + printf("nb_streams %d\n", g_psi.p_format_ctx->nb_streams); + + g_audio_index = -1; + g_video_index = -1; + /* find first audio / video stream */ for (i = 0; i < g_psi.p_format_ctx->nb_streams; i++) { - if (g_psi.p_format_ctx->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO && - g_video_index < 0) + if (g_psi.p_format_ctx->streams[i]->codec->codec_type == + CODEC_TYPE_VIDEO && + g_psi.p_format_ctx->streams[i]->codec->codec_id == + CODEC_ID_H264 && + g_video_index < 0) { g_video_index = i; } - if (g_psi.p_format_ctx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO && - g_audio_index < 0) + if (g_psi.p_format_ctx->streams[i]->codec->codec_type == + CODEC_TYPE_AUDIO && + g_psi.p_format_ctx->streams[i]->codec->codec_id == + CODEC_ID_AAC && + g_audio_index < 0) { g_audio_index = i; } } - if ((g_audio_index < 0) && (g_video_index < 0)) + if ((g_audio_index < 0) || (g_video_index < 0)) { /* close file and return with error */ printf("ERROR: no audio/video stream found in %s\n", filename); @@ -256,7 +247,8 @@ xrdpvr_play_media(void *channel, int stream_id, char *filename) g_psi.p_video_codec_ctx = g_psi.p_format_ctx->streams[g_video_index]->codec; /* find decoder for audio stream */ - g_psi.p_audio_codec = avcodec_find_decoder(g_psi.p_audio_codec_ctx->codec_id); + g_psi.p_audio_codec = + avcodec_find_decoder(g_psi.p_audio_codec_ctx->codec_id); if (g_psi.p_audio_codec == NULL) { @@ -264,7 +256,8 @@ xrdpvr_play_media(void *channel, int stream_id, char *filename) } /* find decoder for video stream */ - g_psi.p_video_codec = avcodec_find_decoder(g_psi.p_video_codec_ctx->codec_id); + g_psi.p_video_codec = + avcodec_find_decoder(g_psi.p_video_codec_ctx->codec_id); if (g_psi.p_video_codec == NULL) { @@ -280,6 +273,14 @@ xrdpvr_play_media(void *channel, int stream_id, char *filename) return -1; } + printf("%d\n", g_psi.p_audio_codec_ctx->extradata_size); + hexdump(g_psi.p_audio_codec_ctx->extradata, + g_psi.p_audio_codec_ctx->extradata_size); + printf("%d %d %d %d\n", g_psi.p_audio_codec_ctx->sample_rate, + g_psi.p_audio_codec_ctx->bit_rate, + g_psi.p_audio_codec_ctx->channels, + g_psi.p_audio_codec_ctx->block_align); + /* open decoder for video stream */ //if (avcodec_open2(g_psi.p_video_codec_ctx, g_psi.p_video_codec, // NULL) < 0) @@ -292,13 +293,36 @@ xrdpvr_play_media(void *channel, int stream_id, char *filename) g_psi.bsfc = av_bitstream_filter_init("h264_mp4toannexb"); printf("g_psi.bsfc %p\n", g_psi.bsfc); + if (xrdpvr_set_video_format(channel, 101, 0, + g_psi.p_video_codec_ctx->width, + g_psi.p_video_codec_ctx->height)) + { + printf("xrdpvr_set_video_format() failed\n"); + return -1; + } + + printf("xrdpvr_play_media: calling xrdpvr_set_audio_format\n"); + if (xrdpvr_set_audio_format(channel, 101, 0, + g_psi.p_audio_codec_ctx->extradata, + g_psi.p_audio_codec_ctx->extradata_size, + g_psi.p_audio_codec_ctx->sample_rate, + g_psi.p_audio_codec_ctx->bit_rate, + g_psi.p_audio_codec_ctx->channels, + g_psi.p_audio_codec_ctx->block_align)) + { + printf("xrdpvr_set_audio_format() failed\n"); + return 1; + } + return 0; } static int firstAudioPkt = 1; static int firstVideoPkt = 1; -int xrdpvr_get_frame(void **av_pkt_ret, int *is_video_frame, int *delay_in_us) +/******************************************************************************/ +int +xrdpvr_get_frame(void **av_pkt_ret, int *is_video_frame, int *delay_in_us) { AVPacket *av_pkt; double dts; @@ -339,25 +363,19 @@ int xrdpvr_get_frame(void **av_pkt_ret, int *is_video_frame, int *delay_in_us) if (firstAudioPkt) { firstAudioPkt = 0; - //printf("##### first audio: dts=%f delay_in_ms=%d\n", dts, *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); + av_pkt->flags & PKT_FLAG_KEY); if (error > 0) { av_free_packet(av_pkt); @@ -371,32 +389,25 @@ int xrdpvr_get_frame(void **av_pkt_ret, int *is_video_frame, int *delay_in_us) bsfc = bsfc->next; } - dts = av_pkt->dts; - //printf("$$$ video raw_dts=%f raw_pts=%f\n", (double) av_pkt->dts, (double) av_pkt->dts); - dts *= av_q2d(g_psi.p_format_ctx->streams[g_video_index]->time_base); if (g_psi.videoTimeout < 0) { *delay_in_us = 1000 * 5; g_psi.videoTimeout = dts; - //printf("$$$ negative: videoTimeout=%f\n", g_psi.videoTimeout); } else { - //printf("$$$ positive: videoTimeout_b4 =%f\n", g_psi.videoTimeout); *delay_in_us = (int) ((dts - g_psi.videoTimeout) * 1000000); g_psi.videoTimeout = dts; - //printf("$$$ positive: videoTimeout_aft=%f\n", g_psi.videoTimeout); } *is_video_frame = 1; if (firstVideoPkt) { firstVideoPkt = 0; - //printf("$$$ first video: dts=%f delay_in_ms=%d\n", dts, *delay_in_us); } } @@ -404,7 +415,9 @@ int xrdpvr_get_frame(void **av_pkt_ret, int *is_video_frame, int *delay_in_us) return 0; } -int send_audio_pkt(void *channel, int stream_id, void *pkt_p) +/******************************************************************************/ +int +send_audio_pkt(void *channel, int stream_id, void *pkt_p) { AVPacket *av_pkt = (AVPacket *) pkt_p; @@ -413,7 +426,9 @@ int send_audio_pkt(void *channel, int stream_id, void *pkt_p) free(av_pkt); } -int send_video_pkt(void *channel, int stream_id, void *pkt_p) +/******************************************************************************/ +int +send_video_pkt(void *channel, int stream_id, void *pkt_p) { AVPacket *av_pkt = (AVPacket *) pkt_p; @@ -422,7 +437,10 @@ int send_video_pkt(void *channel, int stream_id, void *pkt_p) free(av_pkt); } -int xrdpvr_play_frame(void *channel, int stream_id, int *videoTimeout, int *audioTimeout) +/******************************************************************************/ +int +xrdpvr_play_frame(void *channel, int stream_id, int *videoTimeout, + int *audioTimeout) { AVPacket av_pkt; double dts; @@ -431,7 +449,7 @@ int xrdpvr_play_frame(void *channel, int stream_id, int *videoTimeout, int *audi AVBitStreamFilterContext *bsfc; AVPacket new_pkt; - printf("xrdpvr_play_frame:\n"); + //printf("xrdpvr_play_frame:\n"); if (av_read_frame(g_psi.p_format_ctx, &av_pkt) < 0) { @@ -460,22 +478,20 @@ int xrdpvr_play_frame(void *channel, int stream_id, int *videoTimeout, int *audi g_psi.audioTimeout = dts; } - //printf("audio delay: %d\n", delay_in_us); + printf("audio delay: %d\n", delay_in_us); usleep(delay_in_us); //usleep(1000 * 1); } 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); + av_pkt.flags & PKT_FLAG_KEY); if (error > 0) { av_free_packet(&av_pkt); @@ -494,8 +510,6 @@ int xrdpvr_play_frame(void *channel, int stream_id, int *videoTimeout, int *audi dts = av_pkt.dts; dts *= av_q2d(g_psi.p_format_ctx->streams[g_video_index]->time_base); - //printf("xrdpvr_play_frame:video: saved=%f dts=%f\n", g_psi.videoTimeout, dts); - *videoTimeout = (int) ((dts - g_psi.videoTimeout) * 1000000); *audioTimeout = -1; @@ -503,16 +517,14 @@ int xrdpvr_play_frame(void *channel, int stream_id, int *videoTimeout, int *audi { g_psi.videoTimeout = dts; delay_in_us = 1000 * 40; - //printf("xrdpvr_play_frame:video1: saved=%f dts=%f delay_in_us=%d\n", g_psi.videoTimeout, dts, delay_in_us); } else { delay_in_us = (int) ((dts - g_psi.videoTimeout) * 1000000); g_psi.videoTimeout = dts; - //printf("xrdpvr_play_frame:video2: saved=%f dts=%f delay_in_us=%d\n", g_psi.videoTimeout, dts, delay_in_us); } - //printf("video delay: %d\n", delay_in_us); + printf("video delay: %d\n", delay_in_us); usleep(delay_in_us); } @@ -520,6 +532,7 @@ int xrdpvr_play_frame(void *channel, int stream_id, int *videoTimeout, int *audi return 0; } +/******************************************************************************/ int xrdpvr_seek_media(int64_t pos, int backward) { @@ -535,10 +548,11 @@ xrdpvr_seek_media(int64_t pos, int backward) seek_target = av_rescale_q(pos * AV_TIME_BASE, AV_TIME_BASE_Q, - g_psi.p_format_ctx->streams[g_video_index]->time_base); + g_psi.p_format_ctx->streams[g_video_index]->time_base); - if(av_seek_frame(g_psi.p_format_ctx, g_video_index, seek_target, seek_flag) < 0) + if (av_seek_frame(g_psi.p_format_ctx, g_video_index, seek_target, + seek_flag) < 0) { printf("media seek error\n"); return -1; @@ -547,6 +561,7 @@ xrdpvr_seek_media(int64_t pos, int backward) return 0; } +/******************************************************************************/ void xrdpvr_get_media_duration(int64_t *start_time, int64_t *duration) { @@ -554,15 +569,17 @@ xrdpvr_get_media_duration(int64_t *start_time, int64_t *duration) *duration = g_psi.p_format_ctx->duration / AV_TIME_BASE; } +/******************************************************************************/ int -xrdpvr_set_geometry(void *channel, int stream_id, int xpos, int ypos, int width, int height) +xrdpvr_set_geometry(void *channel, int stream_id, int xpos, int ypos, + int width, int height) { STREAM *s; char *cptr; int rv; int len; -printf("xrdpvr_set_geometry: entered; x=%d y=%d\n", xpos, ypos); + printf("xrdpvr_set_geometry: entered; x=%d y=%d\n", xpos, ypos); stream_new(s, MAX_PDU_SIZE); @@ -596,18 +613,22 @@ printf("xrdpvr_set_geometry: entered; x=%d y=%d\n", xpos, ypos); * @return 0 on success, -1 on error *****************************************************************************/ int -xrdpvr_set_video_format(void *channel, uint32_t stream_id) +xrdpvr_set_video_format(void *channel, uint32_t stream_id, int format, + int width, int height) { STREAM *s; char *cptr; int rv; int len; + width = (width + 15) & ~15; stream_new(s, MAX_PDU_SIZE); - stream_ins_u32_le(s, 0); /* number of bytes to follow */ stream_ins_u32_le(s, CMD_SET_VIDEO_FORMAT); stream_ins_u32_le(s, stream_id); + stream_ins_u32_le(s, format); + stream_ins_u32_le(s, width); + stream_ins_u32_le(s, height); /* insert number of bytes in stream */ len = stream_length(s) - 4; @@ -631,7 +652,9 @@ xrdpvr_set_video_format(void *channel, uint32_t stream_id) * @return 0 on success, -1 on error *****************************************************************************/ int -xrdpvr_set_audio_format(void *channel, uint32_t stream_id) +xrdpvr_set_audio_format(void *channel, uint32_t stream_id, int format, + char *extradata, int extradata_size, int sample_rate, + int bit_rate, int channels, int block_align) { STREAM *s; char *cptr; @@ -640,9 +663,21 @@ xrdpvr_set_audio_format(void *channel, uint32_t stream_id) stream_new(s, MAX_PDU_SIZE); + printf("extradata_size %d sample_rate %d bit_rate %d channels %d " + "block_align %d\n", extradata_size, sample_rate, bit_rate, + channels, block_align); + stream_ins_u32_le(s, 0); /* number of bytes to follow */ stream_ins_u32_le(s, CMD_SET_AUDIO_FORMAT); stream_ins_u32_le(s, stream_id); + stream_ins_u32_le(s, format); + stream_ins_u32_le(s, extradata_size); + memcpy(s->p, extradata, extradata_size); + s->p += extradata_size; + stream_ins_u32_le(s, sample_rate); + stream_ins_u32_le(s, bit_rate); + stream_ins_u32_le(s, channels); + stream_ins_u32_le(s, block_align); /* insert number of bytes in stream */ len = stream_length(s) - 4; @@ -668,13 +703,15 @@ xrdpvr_set_audio_format(void *channel, uint32_t stream_id) * @return 0 on success, -1 on error *****************************************************************************/ int -xrdpvr_send_video_data(void *channel, uint32_t stream_id, uint32_t data_len, uint8_t *data) +xrdpvr_send_video_data(void *channel, uint32_t stream_id, + uint32_t data_len, uint8_t *data) { STREAM *s; char *cptr; int rv; int len; + //printf("xrdpvr_send_video_data:\n"); stream_new(s, MAX_PDU_SIZE + data_len); stream_ins_u32_le(s, 0); /* number of bytes to follow */ @@ -712,13 +749,15 @@ xrdpvr_send_video_data(void *channel, uint32_t stream_id, uint32_t data_len, uin * @return 0 on success, -1 on error *****************************************************************************/ int -xrdpvr_send_audio_data(void *channel, uint32_t stream_id, uint32_t data_len, uint8_t *data) +xrdpvr_send_audio_data(void *channel, uint32_t stream_id, uint32_t data_len, + uint8_t *data) { STREAM *s; char *cptr; int rv; int len; + //printf("xrdpvr_send_audio_data:\n"); stream_new(s, MAX_PDU_SIZE + data_len); stream_ins_u32_le(s, 0); /* number of bytes to follow */ @@ -737,6 +776,7 @@ xrdpvr_send_audio_data(void *channel, uint32_t stream_id, uint32_t data_len, uin /* write data to virtual channel */ rv = xrdpvr_write_to_client(channel, s); stream_free(s); + return rv; } @@ -816,6 +856,34 @@ xrdpvr_create_metadata_file(void *channel, char *filename) } /** + ******************************************************************************/ +static int +xrdpvr_read_from_client(void *channel, STREAM *s, int bytes, int timeout) +{ + unsigned int bytes_read; + int total_read; + int ok; + + //printf("xrdpvr_read_from_client:\n"); + total_read = 0; + while (total_read < bytes) + { + //printf("xrdpvr_read_from_client: loop\n"); + bytes_read = bytes - total_read; + ok = WTSVirtualChannelRead(channel, timeout, s->p, bytes_read, + &bytes_read); + //printf("xrdpvr_read_from_client: loop ok %d\n", ok); + if (ok) + { + //printf("xrdpvr_read_from_client: bytes_read %d\n", bytes_read); + total_read += bytes_read; + s->p += bytes_read; + } + } + return 0; +} + +/** * write data to a xrdpvr client * * @param channel opaque handle returned by WTSVirtualChannelOpenEx @@ -840,7 +908,8 @@ xrdpvr_write_to_client(void *channel, STREAM *s) while (1) { - rv = WTSVirtualChannelWrite(channel, &s->data[index], bytes_to_send, &bytes_written); + rv = WTSVirtualChannelWrite(channel, &s->data[index], bytes_to_send, + &bytes_written); if (rv < 0) { @@ -893,3 +962,43 @@ xrdpvr_set_volume(void *channel, int volume) stream_free(s); return rv; } + +int +xrdpvr_send_init(void *channel) +{ + STREAM *s; + char *cptr; + int rv; + int len; + + printf("xrdpvr_send_init:\n"); + stream_new(s, MAX_BUFSIZE); + + stream_ins_u32_le(s, 0); /* number of bytes to follow */ + stream_ins_u32_le(s, CMD_INIT_XRDPVR); + + /* insert number of bytes in stream */ + len = stream_length(s) - 4; + cptr = s->p; + s->p = s->data; + stream_ins_u32_le(s, len); + s->p = cptr; + + /* write data to virtual channel */ + rv = xrdpvr_write_to_client(channel, s); + stream_free(s); + return rv; +} + +int +xrdpvr_read_ack(void *channel, int *frame) +{ + STREAM *s; + + stream_new(s, MAX_PDU_SIZE); + xrdpvr_read_from_client(channel, s, 4, 1000); + s->p = s->data; + stream_ext_u32_le(s, *frame); + stream_free(s); + return 0; +} diff --git a/xrdpvr/xrdpvr.h b/xrdpvr/xrdpvr.h index 1324282c..d7f8ca92 100644 --- a/xrdpvr/xrdpvr.h +++ b/xrdpvr/xrdpvr.h @@ -2,6 +2,7 @@ * xrdp: A Remote Desktop Protocol server. * * Copyright (C) Laxmikant Rashinkar 2012-2013 LK.Rashinkar@gmail.com + * Copyright (C) Jay Sorg 2013 jay.sorg@gmail.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,19 +33,30 @@ extern "C" { int xrdpvr_init_player(void *channel, int stream_id, char *filename); int xrdpvr_deinit_player(void *channel, int stream_id); int xrdpvr_play_media(void *channel, int stream_id, char *filename); -int xrdpvr_set_geometry(void *channel, int stream_id, int xpos, int ypos, int width, int height); -int xrdpvr_set_video_format(void *channel, uint32_t stream_id); -int xrdpvr_set_audio_format(void *channel, uint32_t stream_id); -int xrdpvr_send_video_data(void *channel, uint32_t stream_id, uint32_t data_len, uint8_t *data); -int xrdpvr_send_audio_data(void *channel, uint32_t stream_id, uint32_t data_len, uint8_t *data); +int xrdpvr_set_geometry(void *channel, int stream_id, int xpos, int ypos, + int width, int height); +int xrdpvr_set_video_format(void *channel, uint32_t stream_id, int format, + int width, int height); +int xrdpvr_set_audio_format(void *channel, uint32_t stream_id, int format, + char *extradata, int extradata_size, + int sample_rate, int bit_rate, + int channels, int block_align); +int xrdpvr_send_video_data(void *channel, uint32_t stream_id, + uint32_t data_len, uint8_t *data); +int xrdpvr_send_audio_data(void *channel, uint32_t stream_id, + uint32_t data_len, uint8_t *data); int xrdpvr_create_metadata_file(void *channel, char *filename); -int xrdpvr_play_frame(void *channel, int stream_id, int *vdoTimeout, int *audioTimeout); +int xrdpvr_play_frame(void *channel, int stream_id, int *vdoTimeout, + int *audioTimeout); void xrdpvr_get_media_duration(int64_t *start_time, int64_t *duration); int xrdpvr_seek_media(int64_t pos, int backward); -int xrdpvr_get_frame(void **av_pkt_ret, int *is_video_frame, int *delay_in_us); +int xrdpvr_get_frame(void **av_pkt_ret, int *is_video_frame, + int *delay_in_us); int send_audio_pkt(void *channel, int stream_id, void *pkt_p); int send_video_pkt(void *channel, int stream_id, void *pkt_p); int xrdpvr_set_volume(void *channel, int volume); +int xrdpvr_send_init(void *channel); +int xrdpvr_read_ack(void *channel, int *frame); #ifdef __cplusplus } diff --git a/xrdpvr/xrdpvr_internal.h b/xrdpvr/xrdpvr_internal.h index 17e2acfa..90f87361 100644 --- a/xrdpvr/xrdpvr_internal.h +++ b/xrdpvr/xrdpvr_internal.h @@ -48,6 +48,7 @@ #ifdef DISTRO_UBUNTU1204 #define CODEC_TYPE_VIDEO AVMEDIA_TYPE_VIDEO #define CODEC_TYPE_AUDIO AVMEDIA_TYPE_AUDIO +#define PKT_FLAG_KEY AV_PKT_FLAG_KEY #endif #define MAX_BUFSIZE (1024 * 1024 * 8) @@ -62,6 +63,7 @@ #define CMD_DEINIT_XRDPVR 8 #define CMD_SET_GEOMETRY 9 #define CMD_SET_VOLUME 10 +#define CMD_INIT_XRDPVR 11 /* max number of bytes we can send in one pkt */ #define MAX_PDU_SIZE 1600 @@ -221,6 +223,7 @@ typedef struct _player_state_info } PLAYER_STATE_INFO; +static int xrdpvr_read_from_client(void *channel, STREAM *s, int bytes, int timeout); static int xrdpvr_write_to_client(void *channel, STREAM *s); #endif /* __XRDPVR_INTERNAL_H__ */ @@ -21,9 +21,6 @@ #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) @@ -226,7 +223,7 @@ lib_mod_connect(struct mod *mod) g_tcp_set_no_delay(mod->sck); } - mod->server_msg(mod, "connecting...", 0); + /* mod->server_msg(mod, "connecting...", 0); */ if (use_uds) { @@ -258,7 +255,7 @@ lib_mod_connect(struct mod *mod) } else { - mod->server_msg(mod, "connect error", 0); + /* mod->server_msg(mod, "connect error", 0); */ } } @@ -271,13 +268,13 @@ lib_mod_connect(struct mod *mod) mod->sck = 0; i++; - if (i >= 4) + if (i >= 60) { mod->server_msg(mod, "connection problem, giving up", 0); break; } - g_sleep(250); + g_sleep(500); } if (error == 0) @@ -438,6 +435,287 @@ lib_mod_event(struct mod *mod, int msg, tbus param1, tbus param2, /******************************************************************************/ /* return error */ static int APP_CC +process_server_fill_rect(struct mod *mod, struct stream *s) +{ + int rv; + int x; + int y; + int cx; + int cy; + + in_sint16_le(s, x); + in_sint16_le(s, y); + in_uint16_le(s, cx); + in_uint16_le(s, cy); + rv = mod->server_fill_rect(mod, x, y, cx, cy); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_screen_blt(struct mod *mod, struct stream *s) +{ + int rv; + int x; + int y; + int cx; + int cy; + int srcx; + int srcy; + + in_sint16_le(s, x); + in_sint16_le(s, y); + in_uint16_le(s, cx); + in_uint16_le(s, cy); + in_sint16_le(s, srcx); + in_sint16_le(s, srcy); + rv = mod->server_screen_blt(mod, x, y, cx, cy, srcx, srcy); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_paint_rect(struct mod *mod, struct stream *s) +{ + int rv; + int x; + int y; + int cx; + int cy; + int len_bmpdata; + char *bmpdata; + int width; + int height; + int srcx; + int srcy; + + in_sint16_le(s, x); + in_sint16_le(s, y); + in_uint16_le(s, cx); + in_uint16_le(s, cy); + in_uint32_le(s, len_bmpdata); + in_uint8p(s, bmpdata, len_bmpdata); + in_uint16_le(s, width); + in_uint16_le(s, height); + in_sint16_le(s, srcx); + in_sint16_le(s, srcy); + rv = mod->server_paint_rect(mod, x, y, cx, cy, + bmpdata, width, height, + srcx, srcy); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_set_clip(struct mod *mod, struct stream *s) +{ + int rv; + int x; + int y; + int cx; + int cy; + + in_sint16_le(s, x); + in_sint16_le(s, y); + in_uint16_le(s, cx); + in_uint16_le(s, cy); + rv = mod->server_set_clip(mod, x, y, cx, cy); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_reset_clip(struct mod *mod, struct stream *s) +{ + int rv; + + rv = mod->server_reset_clip(mod); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_set_fgcolor(struct mod *mod, struct stream *s) +{ + int rv; + int fgcolor; + + in_uint32_le(s, fgcolor); + rv = mod->server_set_fgcolor(mod, fgcolor); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_set_bgcolor(struct mod *mod, struct stream *s) +{ + int rv; + int bgcolor; + + in_uint32_le(s, bgcolor); + rv = mod->server_set_bgcolor(mod, bgcolor); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_set_opcode(struct mod *mod, struct stream *s) +{ + int rv; + int opcode; + + in_uint16_le(s, opcode); + rv = mod->server_set_opcode(mod, opcode); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_set_pen(struct mod *mod, struct stream *s) +{ + int rv; + int style; + int width; + + in_uint16_le(s, style); + in_uint16_le(s, width); + rv = mod->server_set_pen(mod, style, width); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_draw_line(struct mod *mod, struct stream *s) +{ + int rv; + int x1; + int y1; + int x2; + int y2; + + in_sint16_le(s, x1); + in_sint16_le(s, y1); + in_sint16_le(s, x2); + in_sint16_le(s, y2); + rv = mod->server_draw_line(mod, x1, y1, x2, y2); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_set_cursor(struct mod *mod, struct stream *s) +{ + int rv; + int x; + int y; + char cur_data[32 * (32 * 3)]; + char cur_mask[32 * (32 / 8)]; + + in_sint16_le(s, x); + in_sint16_le(s, y); + in_uint8a(s, cur_data, 32 * (32 * 3)); + in_uint8a(s, cur_mask, 32 * (32 / 8)); + rv = mod->server_set_cursor(mod, x, y, cur_data, cur_mask); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_create_os_surface(struct mod *mod, struct stream *s) +{ + int rv; + int rdpid; + int width; + int height; + + in_uint32_le(s, rdpid); + in_uint16_le(s, width); + in_uint16_le(s, height); + rv = mod->server_create_os_surface(mod, rdpid, width, height); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_switch_os_surface(struct mod *mod, struct stream *s) +{ + int rv; + int rdpid; + + in_uint32_le(s, rdpid); + rv = mod->server_switch_os_surface(mod, rdpid); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_delete_os_surface(struct mod *mod, struct stream *s) +{ + int rv; + int rdpid; + + in_uint32_le(s, rdpid); + rv = mod->server_delete_os_surface(mod, rdpid); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_paint_rect_os(struct mod *mod, struct stream *s) +{ + int rv; + int x; + int y; + int cx; + int cy; + int rdpid; + int srcx; + int srcy; + + in_sint16_le(s, x); + in_sint16_le(s, y); + in_uint16_le(s, cx); + in_uint16_le(s, cy); + in_uint32_le(s, rdpid); + in_sint16_le(s, srcx); + in_sint16_le(s, srcy); + rv = mod->server_paint_rect_os(mod, x, y, cx, cy, + rdpid, srcx, srcy); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_set_hints(struct mod *mod, struct stream *s) +{ + int rv; + int hints; + int mask; + + in_uint32_le(s, hints); + in_uint32_le(s, mask); + rv = mod->server_set_hints(mod, hints, mask); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC process_server_window_new_update(struct mod *mod, struct stream *s) { int flags; @@ -521,13 +799,27 @@ process_server_window_new_update(struct mod *mod, struct stream *s) /******************************************************************************/ /* return error */ static int APP_CC +process_server_window_delete(struct mod *mod, struct stream *s) +{ + int window_id; + int rv; + + in_uint32_le(s, window_id); + mod->server_window_delete(mod, window_id); + rv = 0; + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC 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); @@ -540,14 +832,209 @@ process_server_window_show(struct mod* mod, struct stream* s) /******************************************************************************/ /* return error */ static int APP_CC -process_server_window_delete(struct mod *mod, struct stream *s) +process_server_add_char(struct mod *mod, struct stream *s) { - int window_id; int rv; + int font; + int charactor; + int x; + int y; + int cx; + int cy; + int len_bmpdata; + char *bmpdata; - in_uint32_le(s, window_id); - mod->server_window_delete(mod, window_id); - rv = 0; + in_uint16_le(s, font); + in_uint16_le(s, charactor); + in_sint16_le(s, x); + in_sint16_le(s, y); + in_uint16_le(s, cx); + in_uint16_le(s, cy); + in_uint16_le(s, len_bmpdata); + in_uint8p(s, bmpdata, len_bmpdata); + rv = mod->server_add_char(mod, font, charactor, x, y, cx, cy, bmpdata); + return rv; +} + + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_add_char_alpha(struct mod *mod, struct stream *s) +{ + int rv; + int font; + int charactor; + int x; + int y; + int cx; + int cy; + int len_bmpdata; + char *bmpdata; + + in_uint16_le(s, font); + in_uint16_le(s, charactor); + in_sint16_le(s, x); + in_sint16_le(s, y); + in_uint16_le(s, cx); + in_uint16_le(s, cy); + in_uint16_le(s, len_bmpdata); + in_uint8p(s, bmpdata, len_bmpdata); + rv = mod->server_add_char_alpha(mod, font, charactor, x, y, cx, cy, + bmpdata); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_draw_text(struct mod *mod, struct stream *s) +{ + int rv; + int font; + int flags; + int mixmode; + int clip_left; + int clip_top; + int clip_right; + int clip_bottom; + int box_left; + int box_top; + int box_right; + int box_bottom; + int x; + int y; + int len_bmpdata; + char *bmpdata; + + in_uint16_le(s, font); + in_uint16_le(s, flags); + in_uint16_le(s, mixmode); + in_sint16_le(s, clip_left); + in_sint16_le(s, clip_top); + in_sint16_le(s, clip_right); + in_sint16_le(s, clip_bottom); + in_sint16_le(s, box_left); + in_sint16_le(s, box_top); + in_sint16_le(s, box_right); + in_sint16_le(s, box_bottom); + in_sint16_le(s, x); + in_sint16_le(s, y); + in_uint16_le(s, len_bmpdata); + in_uint8p(s, bmpdata, len_bmpdata); + rv = mod->server_draw_text(mod, font, flags, mixmode, clip_left, clip_top, + clip_right, clip_bottom, box_left, box_top, + box_right, box_bottom, x, y, bmpdata, len_bmpdata); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_create_os_surface_bpp(struct mod *mod, struct stream *s) +{ + int rv; + int rdpid; + int width; + int height; + int bpp; + + in_uint32_le(s, rdpid); + in_uint16_le(s, width); + in_uint16_le(s, height); + in_uint8(s, bpp); + rv = mod->server_create_os_surface_bpp(mod, rdpid, width, height, bpp); + return rv; +} + + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_paint_rect_bpp(struct mod *mod, struct stream *s) +{ + int rv; + int x; + int y; + int cx; + int cy; + int len_bmpdata; + char *bmpdata; + int width; + int height; + int srcx; + int srcy; + int bpp; + + in_sint16_le(s, x); + in_sint16_le(s, y); + in_uint16_le(s, cx); + in_uint16_le(s, cy); + in_uint32_le(s, len_bmpdata); + in_uint8p(s, bmpdata, len_bmpdata); + in_uint16_le(s, width); + in_uint16_le(s, height); + in_sint16_le(s, srcx); + in_sint16_le(s, srcy); + in_uint8(s, bpp); + rv = mod->server_paint_rect_bpp(mod, x, y, cx, cy, + bmpdata, width, height, + srcx, srcy, bpp); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_composite(struct mod *mod, struct stream *s) +{ + int rv; + int srcidx; + int srcformat; + int srcwidth; + int srcrepeat; + int transform[10]; + int mskflags; + int mskidx; + int mskformat; + int mskwidth; + int mskrepeat; + int op; + int srcx; + int srcy; + int mskx; + int msky; + int dstx; + int dsty; + int width; + int height; + int dstformat; + + in_uint16_le(s, srcidx); + in_uint32_le(s, srcformat); + in_uint16_le(s, srcwidth); + in_uint8(s, srcrepeat); + g_memcpy(transform, s->p, 40); + in_uint8s(s, 40); + in_uint8(s, mskflags); + in_uint16_le(s, mskidx); + in_uint32_le(s, mskformat); + in_uint16_le(s, mskwidth); + in_uint8(s, mskrepeat); + in_uint8(s, op); + in_sint16_le(s, srcx); + in_sint16_le(s, srcy); + in_sint16_le(s, mskx); + in_sint16_le(s, msky); + in_sint16_le(s, dstx); + in_sint16_le(s, dsty); + in_uint16_le(s, width); + in_uint16_le(s, height); + in_uint32_le(s, dstformat); + rv = mod->server_composite(mod, srcidx, srcformat, srcwidth, srcrepeat, + transform, mskflags, mskidx, mskformat, + mskwidth, mskrepeat, op, srcx, srcy, mskx, msky, + dstx, dsty, width, height, dstformat); return rv; } @@ -605,67 +1092,185 @@ send_paint_rect_ack(struct mod *mod, int flags, int x, int y, int cx, int cy, /******************************************************************************/ /* return error */ static int APP_CC -lib_mod_process_orders(struct mod *mod, int type, struct stream *s) +process_server_paint_rect_shmem(struct mod *mod, struct stream *s) { int rv; int x; int y; int cx; int cy; - int srcx; - int srcy; - int mskx; - int msky; - int dstx; - int dsty; - int len_bmpdata; - int style; - int x1; - int y1; - int x2; - int y2; - int bpp; - int rdpid; - int hints; - int mask; + int flags; + int frame_id; + int shmem_id; + int shmem_offset; int width; int height; - int fgcolor; - int bgcolor; - int opcode; + int srcx; + int srcy; + char *bmpdata; + + in_sint16_le(s, x); + in_sint16_le(s, y); + in_uint16_le(s, cx); + in_uint16_le(s, cy); + in_uint32_le(s, flags); + in_uint32_le(s, frame_id); + in_uint32_le(s, shmem_id); + in_uint32_le(s, shmem_offset); + in_uint16_le(s, width); + in_uint16_le(s, height); + in_sint16_le(s, srcx); + in_sint16_le(s, srcy); + bmpdata = 0; + if (flags == 0) /* screen */ + { + if (mod->screen_shmem_id == 0) + { + mod->screen_shmem_id = shmem_id; + mod->screen_shmem_pixels = g_shmat(mod->screen_shmem_id); + } + if (mod->screen_shmem_pixels != 0) + { + bmpdata = mod->screen_shmem_pixels + shmem_offset; + } + } + if (bmpdata != 0) + { + rv = mod->server_paint_rect(mod, x, y, cx, cy, + bmpdata, width, height, + srcx, srcy); + } + else + { + rv = 1; + } + send_paint_rect_ack(mod, flags, x, y, cx, cy, frame_id); + return rv; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +send_paint_rect_ex_ack(struct mod *mod, int flags, int frame_id) +{ + int len; + struct stream *s; + + make_stream(s); + init_stream(s, 8192); + s_push_layer(s, iso_hdr, 4); + out_uint16_le(s, 106); + out_uint32_le(s, flags); + out_uint32_le(s, frame_id); + s_mark_end(s); + len = (int)(s->end - s->data); + s_pop_layer(s, iso_hdr); + out_uint32_le(s, len); + lib_send(mod, s->data, len); + free_stream(s); + return 0; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +process_server_paint_rect_shmem_ex(struct mod *amod, struct stream *s) +{ + int num_drects; + int num_crects; int flags; + int frame_id; int shmem_id; int shmem_offset; - int frame_id; - int charactor; - int font; - int mixmode; - int clip_left; - int clip_top; - int clip_right; - int clip_bottom; - int box_left; - int box_top; - int box_right; - int box_bottom; - int srcrepeat; - int srcidx; - int srcformat; - int srcwidth; - int mskflags; - int mskidx; - int mskformat; - int mskwidth; - int mskrepeat; - int dstformat; - int op; - int transform[10]; + int width; + int height; + int x; + int y; + int cx; + int cy; + int index; + int rv; + tsi16 *ldrects; + tsi16 *ldrects1; + tsi16 *lcrects; + tsi16 *lcrects1; char *bmpdata; - char cur_data[32 * (32 * 3)]; - char cur_mask[32 * (32 / 8)]; - rv = 0; + /* dirty pixels */ + in_uint16_le(s, num_drects); + ldrects = (tsi16 *) g_malloc(2 * 4 * num_drects, 0); + ldrects1 = ldrects; + for (index = 0; index < num_drects; index++) + { + in_sint16_le(s, ldrects1[0]); + in_sint16_le(s, ldrects1[1]); + in_sint16_le(s, ldrects1[2]); + in_sint16_le(s, ldrects1[3]); + ldrects1 += 4; + } + + /* copied pixels */ + in_uint16_le(s, num_crects); + lcrects = (tsi16 *) g_malloc(2 * 4 * num_crects, 0); + lcrects1 = lcrects; + for (index = 0; index < num_crects; index++) + { + in_sint16_le(s, lcrects1[0]); + in_sint16_le(s, lcrects1[1]); + in_sint16_le(s, lcrects1[2]); + in_sint16_le(s, lcrects1[3]); + lcrects1 += 4; + } + + in_uint32_le(s, flags); + in_uint32_le(s, frame_id); + in_uint32_le(s, shmem_id); + in_uint32_le(s, shmem_offset); + + in_uint16_le(s, width); + in_uint16_le(s, height); + + bmpdata = 0; + if (flags == 0) /* screen */ + { + if (amod->screen_shmem_id == 0) + { + amod->screen_shmem_id = shmem_id; + amod->screen_shmem_pixels = g_shmat(amod->screen_shmem_id); + } + if (amod->screen_shmem_pixels != 0) + { + bmpdata = amod->screen_shmem_pixels + shmem_offset; + } + } + if (bmpdata != 0) + { + rv = amod->server_paint_rects(amod, num_drects, ldrects, + num_crects, lcrects, + bmpdata, width, height, 0); + } + else + { + rv = 1; + } + + send_paint_rect_ex_ack(amod, flags, frame_id); + + g_free(lcrects); + g_free(ldrects); + + return 0; +} + +/******************************************************************************/ +/* return error */ +static int APP_CC +lib_mod_process_orders(struct mod *mod, int type, struct stream *s) +{ + int rv; + + rv = 0; switch (type) { case 1: /* server_begin_update */ @@ -675,106 +1280,52 @@ lib_mod_process_orders(struct mod *mod, int type, struct stream *s) rv = mod->server_end_update(mod); break; case 3: /* server_fill_rect */ - in_sint16_le(s, x); - in_sint16_le(s, y); - in_uint16_le(s, cx); - in_uint16_le(s, cy); - rv = mod->server_fill_rect(mod, x, y, cx, cy); + rv = process_server_fill_rect(mod, s); break; case 4: /* server_screen_blt */ - in_sint16_le(s, x); - in_sint16_le(s, y); - in_uint16_le(s, cx); - in_uint16_le(s, cy); - in_sint16_le(s, srcx); - in_sint16_le(s, srcy); - rv = mod->server_screen_blt(mod, x, y, cx, cy, srcx, srcy); + rv = process_server_screen_blt(mod, s); break; case 5: /* server_paint_rect */ - in_sint16_le(s, x); - in_sint16_le(s, y); - in_uint16_le(s, cx); - in_uint16_le(s, cy); - in_uint32_le(s, len_bmpdata); - in_uint8p(s, bmpdata, len_bmpdata); - in_uint16_le(s, width); - in_uint16_le(s, height); - in_sint16_le(s, srcx); - in_sint16_le(s, srcy); - rv = mod->server_paint_rect(mod, x, y, cx, cy, - bmpdata, width, height, - srcx, srcy); + rv = process_server_paint_rect(mod, s); break; case 10: /* server_set_clip */ - in_sint16_le(s, x); - in_sint16_le(s, y); - in_uint16_le(s, cx); - in_uint16_le(s, cy); - rv = mod->server_set_clip(mod, x, y, cx, cy); + rv = process_server_set_clip(mod, s); break; case 11: /* server_reset_clip */ - rv = mod->server_reset_clip(mod); + rv = process_server_reset_clip(mod, s); break; case 12: /* server_set_fgcolor */ - in_uint32_le(s, fgcolor); - rv = mod->server_set_fgcolor(mod, fgcolor); + rv = process_server_set_fgcolor(mod, s); break; case 13: /* server_set_bgcolor */ - in_uint32_le(s, bgcolor); - rv = mod->server_set_bgcolor(mod, bgcolor); + rv = process_server_set_bgcolor(mod, s); break; - case 14: - in_uint16_le(s, opcode); - rv = mod->server_set_opcode(mod, opcode); + case 14: /* server_set_opcode */ + rv = process_server_set_opcode(mod, s); break; - case 17: - in_uint16_le(s, style); - in_uint16_le(s, width); - rv = mod->server_set_pen(mod, style, width); + case 17: /* server_set_pen */ + rv = process_server_set_pen(mod, s); break; - case 18: - in_sint16_le(s, x1); - in_sint16_le(s, y1); - in_sint16_le(s, x2); - in_sint16_le(s, y2); - rv = mod->server_draw_line(mod, x1, y1, x2, y2); + case 18: /* server_draw_line */ + rv = process_server_draw_line(mod, s); break; - case 19: - in_sint16_le(s, x); - in_sint16_le(s, y); - in_uint8a(s, cur_data, 32 * (32 * 3)); - in_uint8a(s, cur_mask, 32 * (32 / 8)); - rv = mod->server_set_cursor(mod, x, y, cur_data, cur_mask); + case 19: /* server_set_cursor */ + rv = process_server_set_cursor(mod, s); break; - case 20: - in_uint32_le(s, rdpid); - in_uint16_le(s, width); - in_uint16_le(s, height); - rv = mod->server_create_os_surface(mod, rdpid, width, height); + case 20: /* server_create_os_surface */ + rv = process_server_create_os_surface(mod, s); break; - case 21: - in_uint32_le(s, rdpid); - rv = mod->server_switch_os_surface(mod, rdpid); + case 21: /* server_switch_os_surface */ + rv = process_server_switch_os_surface(mod, s); break; - case 22: - in_uint32_le(s, rdpid); - rv = mod->server_delete_os_surface(mod, rdpid); + case 22: /* server_delete_os_surface */ + rv = process_server_delete_os_surface(mod, s); break; case 23: /* server_paint_rect_os */ - in_sint16_le(s, x); - in_sint16_le(s, y); - in_uint16_le(s, cx); - in_uint16_le(s, cy); - in_uint32_le(s, rdpid); - in_sint16_le(s, srcx); - in_sint16_le(s, srcy); - rv = mod->server_paint_rect_os(mod, x, y, cx, cy, - rdpid, srcx, srcy); + rv = process_server_paint_rect_os(mod, s); break; case 24: /* server_set_hints */ - in_uint32_le(s, hints); - in_uint32_le(s, mask); - rv = mod->server_set_hints(mod, hints, mask); + rv = process_server_set_hints(mod, s); break; case 25: /* server_window_new_update */ rv = process_server_window_new_update(mod, s); @@ -786,149 +1337,40 @@ lib_mod_process_orders(struct mod *mod, int type, struct stream *s) rv = process_server_window_show(mod, s); break; case 28: /* server_add_char */ - in_uint16_le(s, font); - in_uint16_le(s, charactor); - in_sint16_le(s, x); - in_sint16_le(s, y); - in_uint16_le(s, cx); - in_uint16_le(s, cy); - in_uint16_le(s, len_bmpdata); - in_uint8p(s, bmpdata, len_bmpdata); - rv = mod->server_add_char(mod, font, charactor, x, y, cx, cy, bmpdata); + rv = process_server_add_char(mod, s); break; case 29: /* server_add_char_alpha */ - in_uint16_le(s, font); - in_uint16_le(s, charactor); - in_sint16_le(s, x); - in_sint16_le(s, y); - in_uint16_le(s, cx); - in_uint16_le(s, cy); - in_uint16_le(s, len_bmpdata); - in_uint8p(s, bmpdata, len_bmpdata); - rv = mod->server_add_char_alpha(mod, font, charactor, x, y, cx, cy, bmpdata); + rv = process_server_add_char_alpha(mod, s); break; case 30: /* server_draw_text */ - in_uint16_le(s, font); - in_uint16_le(s, flags); - in_uint16_le(s, mixmode); - in_sint16_le(s, clip_left); - in_sint16_le(s, clip_top); - in_sint16_le(s, clip_right); - in_sint16_le(s, clip_bottom); - in_sint16_le(s, box_left); - in_sint16_le(s, box_top); - in_sint16_le(s, box_right); - in_sint16_le(s, box_bottom); - in_sint16_le(s, x); - in_sint16_le(s, y); - in_uint16_le(s, len_bmpdata); - in_uint8p(s, bmpdata, len_bmpdata); - rv = mod->server_draw_text(mod, font, flags, mixmode, clip_left, clip_top, - clip_right, clip_bottom, box_left, box_top, - box_right, box_bottom, x, y, bmpdata, len_bmpdata); + rv = process_server_draw_text(mod, s); break; case 31: /* server_create_os_surface_bpp */ - in_uint32_le(s, rdpid); - in_uint16_le(s, width); - in_uint16_le(s, height); - in_uint8(s, bpp); - rv = mod->server_create_os_surface_bpp(mod, rdpid, width, height, bpp); + rv = process_server_create_os_surface_bpp(mod, s); break; case 32: /* server_paint_rect_bpp */ - in_sint16_le(s, x); - in_sint16_le(s, y); - in_uint16_le(s, cx); - in_uint16_le(s, cy); - in_uint32_le(s, len_bmpdata); - in_uint8p(s, bmpdata, len_bmpdata); - in_uint16_le(s, width); - in_uint16_le(s, height); - in_sint16_le(s, srcx); - in_sint16_le(s, srcy); - in_uint8(s, bpp); - rv = mod->server_paint_rect_bpp(mod, x, y, cx, cy, - bmpdata, width, height, - srcx, srcy, bpp); + rv = process_server_paint_rect_bpp(mod, s); break; - case 33: - in_uint16_le(s, srcidx); - in_uint32_le(s, srcformat); - in_uint16_le(s, srcwidth); - in_uint8(s, srcrepeat); - g_memcpy(transform, s->p, 40); - in_uint8s(s, 40); - in_uint8(s, mskflags); - in_uint16_le(s, mskidx); - in_uint32_le(s, mskformat); - in_uint16_le(s, mskwidth); - in_uint8(s, mskrepeat); - in_uint8(s, op); - in_sint16_le(s, srcx); - in_sint16_le(s, srcy); - in_sint16_le(s, mskx); - in_sint16_le(s, msky); - in_sint16_le(s, dstx); - in_sint16_le(s, dsty); - in_uint16_le(s, width); - in_uint16_le(s, height); - in_uint32_le(s, dstformat); - rv = mod->server_composite(mod, srcidx, srcformat, srcwidth, srcrepeat, - transform, mskflags, mskidx, mskformat, - mskwidth, mskrepeat, op, srcx, srcy, mskx, msky, - dstx, dsty, width, height, dstformat); + case 33: /* server_composite */ + rv = process_server_composite(mod, s); break; case 51: /* server_set_pointer_ex */ rv = process_server_set_pointer_ex(mod, s); break; case 60: /* server_paint_rect_shmem */ - in_sint16_le(s, x); - in_sint16_le(s, y); - in_uint16_le(s, cx); - in_uint16_le(s, cy); - in_uint32_le(s, flags); - in_uint32_le(s, frame_id); - in_uint32_le(s, shmem_id); - in_uint32_le(s, shmem_offset); - in_uint16_le(s, width); - in_uint16_le(s, height); - in_sint16_le(s, srcx); - in_sint16_le(s, srcy); - bmpdata = 0; - if (flags == 0) /* screen */ - { - if (mod->screen_shmem_id == 0) - { - mod->screen_shmem_id = shmem_id; - mod->screen_shmem_pixels = shmat(mod->screen_shmem_id, 0, 0); - } - if (mod->screen_shmem_pixels != 0) - { - bmpdata = mod->screen_shmem_pixels + shmem_offset; - } - } - if (bmpdata != 0) - { - rv = mod->server_paint_rect(mod, x, y, cx, cy, - bmpdata, width, height, - srcx, srcy); - } - else - { - rv = 1; - } - send_paint_rect_ack(mod, flags, x, y, cx, cy, frame_id); + rv = process_server_paint_rect_shmem(mod, s); + break; + case 61: /* server_paint_rect_shmem_ex */ + rv = process_server_paint_rect_shmem_ex(mod, s); break; - default: g_writeln("lib_mod_process_orders: unknown order type %d", type); rv = 0; break; } - return rv; } - /******************************************************************************/ /* return error */ static int APP_CC @@ -1062,6 +1504,11 @@ lib_mod_signal(struct mod *mod) int DEFAULT_CC lib_mod_end(struct mod *mod) { + if (mod->screen_shmem_pixels != 0) + { + g_shmdt(mod->screen_shmem_pixels); + mod->screen_shmem_pixels = 0; + } return 0; } @@ -133,8 +133,12 @@ struct mod int mskformat, int mskwidth, int mskrepeat, int op, int srcx, int srcy, int mskx, int msky, int dstx, int dsty, int width, int height, int dstformat); + int (*server_paint_rects)(struct mod* v, + int num_drects, short *drects, + int num_crects, short *crects, + char *data, int width, int height, int flags); - tbus server_dumby[100 - 42]; /* align, 100 minus the number of server + tbus server_dumby[100 - 43]; /* align, 100 minus the number of server functions above */ /* common */ tbus handle; /* pointer to self as long */ |