chansrv: smartcard, more work on support for MSTSC

ulab-next
Jay Sorg 11 years ago
parent f265c14499
commit de9fa3d5fa

@ -1004,9 +1004,14 @@ SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders,
int status; int status;
int offset; int offset;
int index; int index;
int bytes_groups;
int val;
int llen;
char reader[100]; char reader[100];
LLOGLN(10, ("SCardListReaders:")); LLOGLN(10, ("SCardListReaders:"));
LLOGLN(10, ("SCardListReaders: mszGroups %s", mszGroups));
LLOGLN(10, ("SCardListReaders: *pcchReaders %d", *pcchReaders));
if (g_sck == -1) if (g_sck == -1)
{ {
LLOGLN(0, ("SCardListReaders: error, not connected")); LLOGLN(0, ("SCardListReaders: error, not connected"));
@ -1014,8 +1019,22 @@ SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders,
} }
msg = (char *) malloc(8192); msg = (char *) malloc(8192);
pthread_mutex_lock(&g_mutex); pthread_mutex_lock(&g_mutex);
SET_UINT32(msg, 0, hContext); offset = 0;
if (send_message(SCARD_LIST_READERS, msg, 4) != 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")); LLOGLN(0, ("SCardListReaders: error, send_message"));
free(msg); free(msg);
@ -1039,6 +1058,8 @@ SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders,
} }
pthread_mutex_unlock(&g_mutex); pthread_mutex_unlock(&g_mutex);
offset = 0; offset = 0;
llen = GET_UINT32(msg, offset);
offset += 4;
num_readers = GET_UINT32(msg, offset); num_readers = GET_UINT32(msg, offset);
offset += 4; offset += 4;
LLOGLN(10, ("SCardListReaders: mszReaders %p pcchReaders %p num_readers %d", LLOGLN(10, ("SCardListReaders: mszReaders %p pcchReaders %p num_readers %d",
@ -1060,6 +1081,10 @@ SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders,
reader_names_index++; reader_names_index++;
status = GET_UINT32(msg, offset); status = GET_UINT32(msg, offset);
offset += 4; offset += 4;
if (mszReaders == 0)
{
reader_names_index = llen;
}
if (pcchReaders != 0) if (pcchReaders != 0)
{ {
*pcchReaders = reader_names_index; *pcchReaders = reader_names_index;

@ -167,7 +167,9 @@ static void APP_CC scard_release_resources(void);
static void APP_CC scard_send_EstablishContext(IRP *irp, int scope); 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_ReleaseContext(IRP *irp, tui32 context);
static void APP_CC scard_send_IsContextValid(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_ListReaders(IRP *irp, tui32 context,
char *groups, int cchReaders,
int wide);
static void APP_CC scard_send_GetStatusChange(IRP *irp, tui32 context, int wide, static void APP_CC scard_send_GetStatusChange(IRP *irp, tui32 context, int wide,
tui32 timeout, tui32 num_readers, tui32 timeout, tui32 num_readers,
READER_STATE *rsa); READER_STATE *rsa);
@ -415,7 +417,8 @@ scard_send_is_valid_context(struct trans *con, tui32 context)
* *
*****************************************************************************/ *****************************************************************************/
int APP_CC int APP_CC
scard_send_list_readers(struct trans *con, tui32 context, int wide) scard_send_list_readers(struct trans *con, tui32 context, char *groups,
int cchReaders, int wide)
{ {
IRP *irp; IRP *irp;
@ -432,7 +435,7 @@ scard_send_list_readers(struct trans *con, tui32 context, int wide)
irp->user_data = con; irp->user_data = con;
/* send IRP to client */ /* send IRP to client */
scard_send_ListReaders(irp, context, wide); scard_send_ListReaders(irp, context, groups, cchReaders, wide);
return 0; return 0;
} }
@ -933,14 +936,18 @@ scard_send_EstablishContext(IRP *irp, int scope)
return; return;
} }
xstream_wr_u32_le(s, 0x08); /* len */ s_push_layer(s, mcs_hdr, 4); /* bytes, set later */
xstream_wr_u32_le(s, 0); /* unused */ out_uint32_le(s, 0x00000000);
xstream_wr_u32_le(s, scope); /* Ioctl specific data */ out_uint32_le(s, scope);
xstream_wr_u32_le(s, 0); /* don't know what this is, */ out_uint32_le(s, 0x00000000);
/* but Win7 is sending it */
s_mark_end(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); s_pop_layer(s, iso_hdr);
bytes = (int) (s->end - s->p); bytes = (int) (s->end - s->p);
bytes -= 28; bytes -= 28;
@ -951,7 +958,7 @@ scard_send_EstablishContext(IRP *irp, int scope)
/* send to client */ /* send to client */
send_channel_data(g_rdpdr_chan_id, s->data, bytes); send_channel_data(g_rdpdr_chan_id, s->data, bytes);
xstream_free(s); free_stream(s);
} }
/** /**
@ -978,28 +985,20 @@ scard_send_ReleaseContext(IRP *irp, tui32 context)
return; return;
} }
/* s_push_layer(s, mcs_hdr, 4); /* bytes, set later */
* command format out_uint32_le(s, 0x00000000);
* out_uint32_le(s, 0x00000004);
* ...... out_uint32_le(s, 0x00020000);
* 20 bytes padding out_uint32_le(s, 0x00000004);
* u32 4 bytes len 8, LE, v1 out_uint32_le(s, context);
* u32 4 bytes filler
* 4 bytes len - don't know what this is, zero for now
* 12 bytes unused
* u32 4 bytes context len
* 4 bytes context
*/
xstream_wr_u32_le(s, 0);
xstream_seek(s, 12);
/* insert context */
xstream_wr_u32_le(s, 4);
xstream_wr_u32_le(s, context);
s_mark_end(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); s_pop_layer(s, iso_hdr);
bytes = (int) (s->end - s->p); bytes = (int) (s->end - s->p);
bytes -= 28; bytes -= 28;
@ -1010,7 +1009,7 @@ scard_send_ReleaseContext(IRP *irp, tui32 context)
/* send to client */ /* send to client */
send_channel_data(g_rdpdr_chan_id, s->data, bytes); send_channel_data(g_rdpdr_chan_id, s->data, bytes);
xstream_free(s); free_stream(s);
} }
/** /**
@ -1067,21 +1066,28 @@ scard_send_IsContextValid(IRP *irp, tui32 context)
/* send to client */ /* send to client */
send_channel_data(g_rdpdr_chan_id, s->data, bytes); send_channel_data(g_rdpdr_chan_id, s->data, bytes);
xstream_free(s); free_stream(s);
} }
/** /**
* *
*****************************************************************************/ *****************************************************************************/
static void APP_CC static void APP_CC
scard_send_ListReaders(IRP *irp, tui32 context, int wide) scard_send_ListReaders(IRP *irp, tui32 context, char *groups,
int cchReaders, int wide)
{ {
/* see [MS-RDPESC] 2.2.2.4 */ /* see [MS-RDPESC] 2.2.2.4 */
SMARTCARD *sc; SMARTCARD *sc;
struct stream *s; struct stream *s;
int bytes; int bytes;
int bytes_groups;
int val;
int index;
int num_chars;
tui32 ioctl; tui32 ioctl;
twchar w_groups[100];
if ((sc = smartcards[irp->scard_index]) == NULL) if ((sc = smartcards[irp->scard_index]) == NULL)
{ {
@ -1098,42 +1104,64 @@ scard_send_ListReaders(IRP *irp, tui32 context, int wide)
return; return;
} }
xstream_wr_u32_le(s, 72); /* number of bytes to follow */ 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, 0x00000000);
out_uint32_le(s, 0x00000004); out_uint32_le(s, 0x00000004);
out_uint32_le(s, 0x00020000); out_uint32_le(s, 0x00020000);
out_uint32_le(s, 0x00000024); out_uint32_le(s, bytes_groups);
out_uint32_le(s, 0x00020004); out_uint32_le(s, val);
out_uint32_le(s, 0x00000000); out_uint32_le(s, 0x00000000);
out_uint32_le(s, 0xFFFFFFFF); out_uint32_le(s, cchReaders);
/* insert context */ /* insert context */
xstream_wr_u32_le(s, 4); out_uint32_le(s, 4);
xstream_wr_u32_le(s, context); out_uint32_le(s, context);
xstream_wr_u32_le(s, 36); /* length of mszGroups */ if (bytes_groups > 0)
xstream_wr_u16_le(s, 0x0053); {
xstream_wr_u16_le(s, 0x0043); if (wide)
xstream_wr_u16_le(s, 0x0061); {
xstream_wr_u16_le(s, 0x0072); out_uint32_le(s, bytes_groups);
xstream_wr_u16_le(s, 0x0064); for (index = 0; index < num_chars; index++)
xstream_wr_u16_le(s, 0x0024); {
xstream_wr_u16_le(s, 0x0041); out_uint16_le(s, w_groups[index]);
xstream_wr_u16_le(s, 0x006c); }
xstream_wr_u16_le(s, 0x006c); out_uint16_le(s, 0);
xstream_wr_u16_le(s, 0x0052); out_uint16_le(s, 0);
xstream_wr_u16_le(s, 0x0065); }
xstream_wr_u16_le(s, 0x0061); else
xstream_wr_u16_le(s, 0x0064); {
xstream_wr_u16_le(s, 0x0065); out_uint32_le(s, bytes_groups);
xstream_wr_u16_le(s, 0x0072); for (index = 0; index < num_chars; index++)
xstream_wr_u16_le(s, 0x0073); {
out_uint8(s, w_groups[index]);
xstream_wr_u32_le(s, 0x00); }
out_uint16_le(s, 0);
out_uint16_le(s, 0);
}
}
s_mark_end(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); s_pop_layer(s, iso_hdr);
bytes = (int) (s->end - s->p); bytes = (int) (s->end - s->p);
bytes -= 28; bytes -= 28;
@ -1149,33 +1177,7 @@ scard_send_ListReaders(IRP *irp, tui32 context, int wide)
g_hexdump(s->data, bytes); g_hexdump(s->data, bytes);
#endif #endif
xstream_free(s); free_stream(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
*/
/*
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
*/
} }
/*****************************************************************************/ /*****************************************************************************/
@ -1399,6 +1401,11 @@ scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs)
s_mark_end(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); s_pop_layer(s, iso_hdr);
bytes = (int) (s->end - s->p); bytes = (int) (s->end - s->p);
bytes -= 28; bytes -= 28;
@ -1409,7 +1416,7 @@ scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs)
/* send to client */ /* send to client */
send_channel_data(g_rdpdr_chan_id, s->data, bytes); send_channel_data(g_rdpdr_chan_id, s->data, bytes);
xstream_free(s); free_stream(s);
} }
/** /**
@ -1483,7 +1490,7 @@ scard_send_Reconnect(IRP *irp, tui32 context, tui32 sc_handle, READER_STATE *rs)
/* send to client */ /* send to client */
send_channel_data(g_rdpdr_chan_id, s->data, bytes); send_channel_data(g_rdpdr_chan_id, s->data, bytes);
xstream_free(s); free_stream(s);
} }
/** /**
@ -1545,7 +1552,7 @@ scard_send_BeginTransaction(IRP *irp, tui32 sc_handle)
/* send to client */ /* send to client */
send_channel_data(g_rdpdr_chan_id, s->data, bytes); send_channel_data(g_rdpdr_chan_id, s->data, bytes);
xstream_free(s); free_stream(s);
} }
/** /**
@ -1608,7 +1615,7 @@ scard_send_EndTransaction(IRP *irp, tui32 sc_handle, tui32 dwDisposition)
/* send to client */ /* send to client */
send_channel_data(g_rdpdr_chan_id, s->data, bytes); send_channel_data(g_rdpdr_chan_id, s->data, bytes);
xstream_free(s); free_stream(s);
} }
/** /**
@ -1689,7 +1696,7 @@ scard_send_Status(IRP *irp, int wide, tui32 sc_handle,
/* send to client */ /* send to client */
send_channel_data(g_rdpdr_chan_id, s->data, bytes); send_channel_data(g_rdpdr_chan_id, s->data, bytes);
xstream_free(s); free_stream(s);
} }
/** /**
@ -1755,7 +1762,7 @@ scard_send_Disconnect(IRP *irp, tui32 context, tui32 sc_handle,
/* send to client */ /* send to client */
send_channel_data(g_rdpdr_chan_id, s->data, bytes); send_channel_data(g_rdpdr_chan_id, s->data, bytes);
xstream_free(s); free_stream(s);
} }
/** /**
@ -1817,10 +1824,10 @@ scard_send_Transmit(IRP *irp, tui32 sc_handle, char *send_data,
* u32 4 bytes sc_handle * u32 4 bytes sc_handle
*/ */
g_writeln("send_bytes %d", send_bytes); //g_writeln("send_bytes %d", send_bytes);
g_writeln("recv_bytes %d", recv_bytes); //g_writeln("recv_bytes %d", recv_bytes);
#if 1 #if 0
s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ s_push_layer(s, mcs_hdr, 4); /* bytes, set later */
//out_uint32_be(s, 0x58000000); //out_uint32_be(s, 0x58000000);
out_uint32_be(s, 0x00000000); out_uint32_be(s, 0x00000000);
@ -1859,10 +1866,10 @@ scard_send_Transmit(IRP *irp, tui32 sc_handle, char *send_data,
out_uint32_be(s, 0x00000000); out_uint32_be(s, 0x00000000);
#else #else
g_printf("send cbPciLength %d\n", send_ior->cbPciLength); //g_printf("send cbPciLength %d\n", send_ior->cbPciLength);
g_printf("send extra_bytes %d\n", send_ior->extra_bytes); //g_printf("send extra_bytes %d\n", send_ior->extra_bytes);
g_printf("recv cbPciLength %d\n", recv_ior->cbPciLength); //g_printf("recv cbPciLength %d\n", recv_ior->cbPciLength);
g_printf("recv extra_bytes %d\n", recv_ior->extra_bytes); //g_printf("recv extra_bytes %d\n", recv_ior->extra_bytes);
s_push_layer(s, mcs_hdr, 4); /* bytes, set later */ s_push_layer(s, mcs_hdr, 4); /* bytes, set later */
out_uint32_le(s, 0x00000000); out_uint32_le(s, 0x00000000);
@ -1943,12 +1950,12 @@ scard_send_Transmit(IRP *irp, tui32 sc_handle, char *send_data,
/* send to client */ /* send to client */
send_channel_data(g_rdpdr_chan_id, s->data, bytes); send_channel_data(g_rdpdr_chan_id, s->data, bytes);
#if 1 #if 0
g_writeln("scard_send_Transmit:"); g_writeln("scard_send_Transmit:");
g_hexdump(s->data, bytes); g_hexdump(s->data, bytes);
#endif #endif
xstream_free(s); free_stream(s);
return 0; return 0;
} }
@ -2021,7 +2028,7 @@ scard_send_Control(IRP *irp, tui32 context, tui32 sc_handle, char *send_data,
/* send to client */ /* send to client */
send_channel_data(g_rdpdr_chan_id, s->data, bytes); send_channel_data(g_rdpdr_chan_id, s->data, bytes);
xstream_free(s); free_stream(s);
return 0; return 0;
} }
@ -2077,7 +2084,7 @@ scard_send_Cancel(IRP *irp, tui32 context)
/* send to client */ /* send to client */
send_channel_data(g_rdpdr_chan_id, s->data, bytes); send_channel_data(g_rdpdr_chan_id, s->data, bytes);
xstream_free(s); free_stream(s);
return 0; return 0;
} }
@ -2141,7 +2148,7 @@ scard_send_GetAttrib(IRP *irp, tui32 sc_handle, READER_STATE *rs)
/* send to client */ /* send to client */
send_channel_data(g_rdpdr_chan_id, s->data, bytes); send_channel_data(g_rdpdr_chan_id, s->data, bytes);
xstream_free(s); free_stream(s);
return 0; return 0;
} }

@ -113,7 +113,8 @@ int APP_CC scard_deinit(void);
int APP_CC scard_send_establish_context(struct trans *con, int scope); 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_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_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_list_readers(struct trans *con, tui32 context,
char *groups, int cchReaders, int wide);
int APP_CC scard_send_get_status_change(struct trans *con, tui32 context, int APP_CC scard_send_get_status_change(struct trans *con, tui32 context,
int wide, tui32 timeout, int wide, tui32 timeout,

@ -65,6 +65,7 @@
/* TODO: put this in con */ /* TODO: put this in con */
static int g_xrdp_pcsc_state = XRDP_PCSC_STATE_NONE; static int g_xrdp_pcsc_state = XRDP_PCSC_STATE_NONE;
static int g_xrdp_pcsc_extra1;
extern int g_display_num; /* in chansrv.c */ extern int g_display_num; /* in chansrv.c */
@ -238,6 +239,9 @@ int APP_CC
scard_process_list_readers(struct trans *con, struct stream *in_s) scard_process_list_readers(struct trans *con, struct stream *in_s)
{ {
int hContext; int hContext;
int bytes_groups;
int cchReaders;
char *groups;
LLOGLN(10, ("scard_process_list_readers:")); LLOGLN(10, ("scard_process_list_readers:"));
if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_LR) if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_LR)
@ -247,8 +251,15 @@ scard_process_list_readers(struct trans *con, struct stream *in_s)
} }
g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_LR; g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_LR;
in_uint32_le(in_s, hContext); in_uint32_le(in_s, hContext);
LLOGLN(10, ("scard_process_list_readers: dwScope 0x%8.8x", hContext)); in_uint32_le(in_s, bytes_groups);
scard_send_list_readers(con, hContext, 1); groups = (char *) g_malloc(bytes_groups + 1, 1);
in_uint8a(in_s, groups, bytes_groups);
in_uint32_le(in_s, cchReaders);
g_xrdp_pcsc_extra1 = g_xrdp_pcsc_extra1 = cchReaders;
LLOGLN(10, ("scard_process_list_readers: hContext 0x%8.8x cchReaders %d",
hContext, cchReaders));
scard_send_list_readers(con, hContext, groups, cchReaders, 1);
g_free(groups);
return 0; return 0;
} }
@ -264,6 +275,8 @@ scard_function_list_readers_return(struct trans *con,
int rn_index; int rn_index;
int index; int index;
int bytes; int bytes;
int cchReaders;
int llen;
twchar reader_name[100]; twchar reader_name[100];
char lreader_name[16][100]; char lreader_name[16][100];
@ -277,14 +290,20 @@ scard_function_list_readers_return(struct trans *con,
} }
g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_LR; g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_LR;
cchReaders = g_xrdp_pcsc_extra1;
g_memset(reader_name, 0, sizeof(reader_name)); g_memset(reader_name, 0, sizeof(reader_name));
g_memset(lreader_name, 0, sizeof(lreader_name)); g_memset(lreader_name, 0, sizeof(lreader_name));
rn_index = 0; rn_index = 0;
readers = 0; readers = 0;
llen = 0;
if (status == 0) if (status == 0)
{ {
in_uint8s(in_s, 28); in_uint8s(in_s, 28);
in_uint32_le(in_s, len); in_uint32_le(in_s, len);
llen = len;
if (cchReaders > 0)
{
while (len > 0) while (len > 0)
{ {
in_uint16_le(in_s, chr); in_uint16_le(in_s, chr);
@ -306,6 +325,7 @@ scard_function_list_readers_return(struct trans *con,
rn_index++; rn_index++;
} }
} }
}
if (rn_index > 0) if (rn_index > 0)
{ {
if (reader_name[0] != 0) if (reader_name[0] != 0)
@ -319,6 +339,7 @@ scard_function_list_readers_return(struct trans *con,
out_s = trans_get_out_s(con, 8192); out_s = trans_get_out_s(con, 8192);
s_push_layer(out_s, iso_hdr, 8); s_push_layer(out_s, iso_hdr, 8);
out_uint32_le(out_s, llen);
out_uint32_le(out_s, readers); out_uint32_le(out_s, readers);
for (index = 0; index < readers; index++) for (index = 0; index < readers; index++)
{ {

Loading…
Cancel
Save