summaryrefslogtreecommitdiffstats
path: root/sesman
diff options
context:
space:
mode:
Diffstat (limited to 'sesman')
-rw-r--r--sesman/chansrv/Makefile.am5
-rw-r--r--sesman/chansrv/chansrv.c44
-rw-r--r--sesman/chansrv/clipboard.c4
-rw-r--r--sesman/chansrv/drdynvc.c8
-rw-r--r--sesman/chansrv/fifo.c8
-rw-r--r--sesman/chansrv/pcsc/dumps/scard-begin-tranaction.txt12
-rw-r--r--sesman/chansrv/pcsc/dumps/scard-connect.txt30
-rw-r--r--sesman/chansrv/pcsc/dumps/scard-control.txt61
-rw-r--r--sesman/chansrv/pcsc/dumps/scard-disconnect.txt24
-rw-r--r--sesman/chansrv/pcsc/dumps/scard-end-tranaction.txt35
-rw-r--r--sesman/chansrv/pcsc/dumps/scard-establish-context.txt19
-rw-r--r--sesman/chansrv/pcsc/dumps/scard-get-status-change.txt25
-rw-r--r--sesman/chansrv/pcsc/dumps/scard-list-readers.txt94
-rw-r--r--sesman/chansrv/pcsc/dumps/scard-release-context.txt9
-rw-r--r--sesman/chansrv/pcsc/dumps/scard-status.txt122
-rw-r--r--sesman/chansrv/pcsc/dumps/scard-transmit.txt34
-rwxr-xr-xsesman/chansrv/pcsc/wrapper/Makefile14
-rwxr-xr-xsesman/chansrv/pcsc/wrapper/winscard-func-names.txt78
-rwxr-xr-xsesman/chansrv/pcsc/wrapper/winscard-funcs.h171
-rwxr-xr-xsesman/chansrv/pcsc/wrapper/winscard.c757
-rwxr-xr-xsesman/chansrv/pcsc/wrapper/winscard.def53
-rw-r--r--sesman/chansrv/pcsc/xrdp_pcsc.c377
-rw-r--r--sesman/chansrv/pulse/Makefile23
-rw-r--r--sesman/chansrv/pulse/module-xrdp-sink.c4
-rw-r--r--sesman/chansrv/pulse/module-xrdp-source-symdef.h29
-rw-r--r--sesman/chansrv/pulse/module-xrdp-source.c460
-rw-r--r--sesman/chansrv/pulse/pulse-notes.ubuntu.txt91
-rw-r--r--sesman/chansrv/rail.c156
-rw-r--r--sesman/chansrv/smartcard.c1373
-rw-r--r--sesman/chansrv/smartcard.h61
-rw-r--r--sesman/chansrv/smartcard_pcsc.c1353
-rw-r--r--sesman/chansrv/smartcard_pcsc.h60
-rw-r--r--sesman/chansrv/sound.c892
-rw-r--r--sesman/chansrv/sound.h43
-rw-r--r--sesman/sesman.ini2
-rw-r--r--sesman/session.c1
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);
}
}