diff options
Diffstat (limited to 'sesman')
36 files changed, 5126 insertions, 1406 deletions
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); } } |