diff options
Diffstat (limited to 'sesman/chansrv/smartcard.c')
| -rw-r--r-- | sesman/chansrv/smartcard.c | 276 |
1 files changed, 195 insertions, 81 deletions
diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index 9d55807d..29406d62 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -59,7 +59,7 @@ #define LOG_DEBUG 2 #ifndef LOG_LEVEL -#define LOG_LEVEL LOG_DEBUG +#define LOG_LEVEL LOG_INFO #endif #define log_error(_params...) \ @@ -160,37 +160,36 @@ 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, 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); -static void APP_CC scard_send_Status(IRP* irp, int wide, tui32 sc_handle); - +static void APP_CC scard_send_EndTransaction(IRP* irp, tui32 sc_handle, + tui32 dwDisposition); +static void APP_CC scard_send_Status(IRP* irp, int wide, tui32 sc_handle, + int cchReaderLen, int cbAtrLen); static void APP_CC scard_send_Disconnect(IRP* irp, tui32 context, - tui32 sc_handle); - + tui32 sc_handle, int dwDisposition); static int APP_CC scard_send_Transmit(IRP* irp, tui32 sc_handle, - READER_STATE* rs); - + 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, - READER_STATE* rs); - + 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); @@ -577,7 +576,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(struct trans *con, tui32 sc_handle, + tui32 dwDisposition) { IRP *irp; @@ -595,7 +595,7 @@ scard_send_end_transaction(struct trans *con, tui32 sc_handle) irp->user_data = con; /* send IRP to client */ - scard_send_EndTransaction(irp, sc_handle); + scard_send_EndTransaction(irp, sc_handle, dwDisposition); return 0; } @@ -607,7 +607,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(struct trans *con, int wide, tui32 sc_handle, + int cchReaderLen, int cbAtrLen) { IRP *irp; @@ -625,7 +626,7 @@ scard_send_status(struct trans *con, int wide, tui32 sc_handle) irp->user_data = con; /* send IRP to client */ - scard_send_Status(irp, wide, sc_handle); + scard_send_Status(irp, wide, sc_handle, cchReaderLen, cbAtrLen); return 0; } @@ -637,7 +638,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) +scard_send_disconnect(struct trans *con, tui32 context, tui32 sc_handle, + int dwDisposition) { IRP *irp; @@ -655,7 +657,7 @@ scard_send_disconnect(struct trans *con, tui32 context, tui32 sc_handle) irp->user_data = con; /* send IRP to client */ - scard_send_Disconnect(irp, context, sc_handle); + scard_send_Disconnect(irp, context, sc_handle, dwDisposition); return 0; } @@ -665,7 +667,10 @@ 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, READER_STATE* rs) +scard_send_transmit(struct trans *con, tui32 sc_handle, + char *send_data, int send_bytes, int recv_bytes, + struct xrdp_scard_io_request *send_ior, + struct xrdp_scard_io_request *recv_ior) { IRP *irp; @@ -683,7 +688,8 @@ scard_send_transmit(struct trans *con, tui32 sc_handle, READER_STATE* rs) irp->user_data = con; /* send IRP to client */ - scard_send_Transmit(irp, sc_handle, rs); + scard_send_Transmit(irp, sc_handle, send_data, send_bytes, recv_bytes, + send_ior, recv_ior); return 0; } @@ -693,7 +699,8 @@ scard_send_transmit(struct trans *con, tui32 sc_handle, READER_STATE* rs) *****************************************************************************/ int APP_CC scard_send_control(struct trans *con, tui32 context, tui32 sc_handle, - READER_STATE* rs) + char *send_data, int send_bytes, + int recv_bytes, int control_code) { IRP *irp; @@ -711,7 +718,8 @@ scard_send_control(struct trans *con, tui32 context, tui32 sc_handle, irp->user_data = con; /* send IRP to client */ - scard_send_Control(irp, context, sc_handle, rs); + scard_send_Control(irp, context, sc_handle, send_data, + send_bytes, recv_bytes, control_code); return 0; } @@ -889,6 +897,7 @@ scard_get_free_slot(void) return -1; } +#if 0 /** * Release resources prior to shutting down *****************************************************************************/ @@ -906,6 +915,7 @@ scard_release_resources(void) } } } +#endif /** * @@ -1166,7 +1176,6 @@ scard_send_GetStatusChange(IRP* irp, tui32 context, int wide, tui32 timeout, tui32 ioctl; int bytes; int i; - int len; int num_chars; int index; twchar w_reader_name[100]; @@ -1269,7 +1278,6 @@ scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs) struct stream* s; tui32 ioctl; int bytes; - int len; int num_chars; int index; twchar w_reader_name[100]; @@ -1469,12 +1477,12 @@ 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) +scard_send_EndTransaction(IRP *irp, tui32 sc_handle, tui32 dwDisposition) { /* see [MS-RDPESC] 3.1.4.32 */ - SMARTCARD* sc; - struct stream* s; + SMARTCARD *sc; + struct stream *s; int bytes; if ((sc = smartcards[irp->scard_index]) == NULL) @@ -1501,7 +1509,7 @@ scard_send_EndTransaction(IRP *irp, tui32 sc_handle) */ xstream_seek(s, 24); - xstream_wr_u32_le(s, SCARD_LEAVE_CARD); + xstream_wr_u32_le(s, dwDisposition); xstream_seek(s, 8); /* insert handle */ @@ -1526,7 +1534,8 @@ scard_send_EndTransaction(IRP *irp, tui32 sc_handle) * @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, tui32 sc_handle, + int cchReaderLen, int cbAtrLen) { /* see [MS-RDPESC] 2.2.2.18 */ @@ -1541,11 +1550,12 @@ scard_send_Status(IRP *irp, int wide, tui32 sc_handle) return; } - ioctl = (wide) ? SCARD_IOCTL_CONNECT_W : - SCARD_IOCTL_CONNECT_A; - + ioctl = wide ? SCARD_IOCTL_STATUS_W : SCARD_IOCTL_STATUS_A; if ((s = scard_make_new_ioctl(irp, ioctl)) == NULL) + { + log_error("scard_make_new_ioctl"); return; + } /* * command format @@ -1564,8 +1574,8 @@ scard_send_Status(IRP *irp, int wide, tui32 sc_handle) */ xstream_seek(s, 28); - xstream_wr_u32_le(s, -1); /* readerLen, see [MS-RDPESC] 4.11 */ - xstream_wr_u32_le(s, 36); /* atrLen, see [MS-RDPESC] 4.11 */ + xstream_wr_u32_le(s, cchReaderLen); /* readerLen, see [MS-RDPESC] 4.11 */ + xstream_wr_u32_le(s, cbAtrLen); /* atrLen, see [MS-RDPESC] 4.11 */ xstream_seek(s, 8); /* insert sc_handle */ @@ -1592,7 +1602,8 @@ 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) +scard_send_Disconnect(IRP *irp, tui32 context, tui32 sc_handle, + int dwDisposition) { /* see [MS-RDPESC] 3.1.4.30 */ @@ -1625,7 +1636,7 @@ scard_send_Disconnect(IRP *irp, tui32 context, tui32 sc_handle) */ xstream_seek(s, 24); - xstream_wr_u32_le(s, SCARD_RESET_CARD); + xstream_wr_u32_le(s, dwDisposition); /* insert context */ xstream_wr_u32_le(s, 4); @@ -1651,22 +1662,35 @@ 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, READER_STATE* rs) +scard_send_Transmit(IRP* irp, tui32 sc_handle, char *send_data, + int send_bytes, int recv_bytes, + struct xrdp_scard_io_request *send_ior, + struct xrdp_scard_io_request *recv_ior) { /* see [MS-RDPESC] 2.2.2.19 */ SMARTCARD* sc; struct stream* s; int bytes; + int val; if ((sc = smartcards[irp->scard_index]) == NULL) { log_error("smartcards[%d] is NULL", irp->scard_index); - return; + return 1; } if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_TRANSMIT)) == NULL) - return; + { + log_error("scard_make_new_ioctl"); + return 1; + } + + log_debug("send_bytes %d recv_bytes %d send dwProtocol %d cbPciLength %d " + "extra_bytes %d recv dwProtocol %d cbPciLength %d", send_bytes, + recv_bytes, send_ior->dwProtocol, send_ior->cbPciLength, + send_ior->extra_bytes, recv_ior->dwProtocol, recv_ior->cbPciLength, + recv_ior->extra_bytes); /* * command format @@ -1693,21 +1717,48 @@ scard_send_Transmit(IRP* irp, tui32 sc_handle, READER_STATE* rs) */ xstream_seek(s, 12); - xstream_wr_u32_le(s, rs->map0); + xstream_wr_u32_le(s, 0); // map0 xstream_seek(s, 4); - xstream_wr_u32_le(s, rs->map1); - xstream_wr_u32_le(s, rs->dwProtocol); - xstream_wr_u32_le(s, rs->cbPciLength); - xstream_wr_u32_le(s, rs->map2); - xstream_wr_u32_le(s, rs->cbSendLength); - xstream_wr_u32_le(s, rs->map3); - xstream_wr_u32_le(s, rs->map4); - xstream_wr_u32_le(s, rs->map5); - xstream_wr_u32_le(s, rs->map6); - xstream_wr_u32_le(s, rs->cbRecvLength); + xstream_wr_u32_le(s, 0); // map1 + xstream_wr_u32_le(s, send_ior->dwProtocol); + xstream_wr_u32_le(s, send_ior->cbPciLength); + val = send_ior->extra_bytes > 0 ? 1 : 0; + xstream_wr_u32_le(s, val); // map2 + xstream_wr_u32_le(s, send_bytes); + val = send_bytes > 0 ? 1 : 0; + xstream_wr_u32_le(s, val); // map3 + val = recv_ior->cbPciLength > 0 ? 1 : 0; + xstream_wr_u32_le(s, val); // map 4 + xstream_wr_u32_le(s, 0); // map5 + xstream_wr_u32_le(s, recv_bytes); xstream_wr_u32_le(s, 4); xstream_wr_u32_le(s, sc_handle); + if (send_ior->extra_bytes > 0) + { + xstream_wr_u32_le(s, send_ior->extra_bytes); + out_uint8a(s, send_ior->extra_data, send_ior->extra_bytes); + } + + if (send_bytes > 0) + { + xstream_wr_u32_le(s, send_bytes); + out_uint8a(s, send_data, send_bytes); + } + + if (recv_ior->cbPciLength > 0) + { + xstream_wr_u32_le(s, recv_ior->dwProtocol); + xstream_wr_u32_le(s, recv_ior->cbPciLength); + val = recv_ior->extra_bytes > 0 ? 1 : 0; + xstream_wr_u32_le(s, val); + if (val) + { + xstream_wr_u32_le(s, recv_ior->extra_bytes); + out_uint8a(s, recv_ior->extra_data, recv_ior->extra_bytes); + } + } + /* get stream len */ bytes = xstream_len(s); @@ -1717,28 +1768,34 @@ scard_send_Transmit(IRP* irp, tui32 sc_handle, READER_STATE* rs) /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); xstream_free(s); + return 0; } /** * Communicate directly with the smart card reader *****************************************************************************/ static int APP_CC -scard_send_Control(IRP* irp, tui32 context, tui32 sc_handle, READER_STATE* rs) +scard_send_Control(IRP* irp, tui32 context, tui32 sc_handle, char *send_data, + int send_bytes, int recv_bytes, int control_code) { /* see [MS-RDPESC] 2.2.2.19 */ SMARTCARD* sc; struct stream* s; int bytes; + int val; if ((sc = smartcards[irp->scard_index]) == NULL) { log_error("smartcards[%d] is NULL", irp->scard_index); - return; + return 1; } if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_CONTROL)) == NULL) - return; + { + log_error("scard_make_new_ioctl"); + return 1; + } /* * command format @@ -1763,19 +1820,30 @@ scard_send_Control(IRP* irp, tui32 context, tui32 sc_handle, READER_STATE* rs) */ xstream_seek(s, 12); - xstream_wr_u32_le(s, rs->map0); - xstream_wr_u32_le(s, 0); - xstream_wr_u32_le(s, rs->map1); - xstream_wr_u32_le(s, rs->dwControlCode); - xstream_wr_u32_le(s, rs->cbRecvLength); - xstream_wr_u32_le(s, rs->map2); + 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, rs->cbOutBufferSize); + xstream_wr_u32_le(s, recv_bytes); xstream_wr_u32_le(s, 4); xstream_wr_u32_le(s, context); xstream_wr_u32_le(s, 4); xstream_wr_u32_le(s, sc_handle); + if (send_bytes > 0) + { + xstream_wr_u32_le(s, send_bytes); + out_uint8a(s, send_data, send_bytes); + } + /* get stream len */ bytes = xstream_len(s); @@ -1785,12 +1853,14 @@ scard_send_Control(IRP* irp, tui32 context, tui32 sc_handle, READER_STATE* rs) /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); xstream_free(s); + return 0; } /** * Cancel any outstanding calls *****************************************************************************/ -static int APP_CC scard_send_Cancel(IRP* irp, tui32 context) +static int APP_CC +scard_send_Cancel(IRP* irp, tui32 context) { /* see [MS-RDPESC] 3.1.4.27 */ @@ -1801,11 +1871,14 @@ static int APP_CC scard_send_Cancel(IRP* irp, tui32 context) if ((sc = smartcards[irp->scard_index]) == NULL) { log_error("smartcards[%d] is NULL", irp->scard_index); - return; + return 1; } if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_CANCEL)) == NULL) - return; + { + log_error("scard_make_new_ioctl"); + return 1; + } /* * command format @@ -1832,6 +1905,7 @@ static int APP_CC scard_send_Cancel(IRP* irp, tui32 context) /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); xstream_free(s); + return 0; } /** @@ -1849,11 +1923,14 @@ scard_send_GetAttrib(IRP* irp, tui32 sc_handle, READER_STATE* rs) if ((sc = smartcards[irp->scard_index]) == NULL) { log_error("smartcards[%d] is NULL", irp->scard_index); - return; + return 1; } if ((s = scard_make_new_ioctl(irp, SCARD_IOCTL_GETATTRIB)) == NULL) - return; + { + log_error("scard_make_new_ioctl"); + return 1; + } /* * command format @@ -1888,6 +1965,7 @@ scard_send_GetAttrib(IRP* irp, tui32 sc_handle, READER_STATE* rs) /* send to client */ send_channel_data(g_rdpdr_chan_id, s->data, bytes); xstream_free(s); + return 0; } /****************************************************************************** @@ -1960,11 +2038,16 @@ scard_handle_ReleaseContext_Return(struct stream *s, IRP *irp, log_debug("leaving"); } -static void APP_CC scard_handle_IsContextValid_Return(struct stream *s, IRP *irp, - tui32 DeviceId, tui32 CompletionId, - tui32 IoStatus) +/** + * + *****************************************************************************/ +static void +APP_CC scard_handle_IsContextValid_Return(struct stream *s, IRP *irp, + tui32 DeviceId, tui32 CompletionId, + tui32 IoStatus) { tui32 len; + struct trans *con; log_debug("entered"); @@ -1984,7 +2067,9 @@ static void APP_CC scard_handle_IsContextValid_Return(struct stream *s, IRP *irp /* get OutputBufferLen */ xstream_rd_u32_le(s, len); - + con = (struct trans *) (irp->user_data); + scard_function_is_context_valid_return(con, s, len); + devredir_irp_delete(irp); log_debug("leaving"); } @@ -2081,9 +2166,11 @@ scard_handle_Connect_Return(struct stream *s, IRP *irp, /* get OutputBufferLen */ xstream_rd_u32_le(s, len); + con = (struct trans *) (irp->user_data); scard_function_connect_return(con, s, len); devredir_irp_delete(irp); + log_debug("leaving"); } @@ -2096,6 +2183,7 @@ scard_handle_Reconnect_Return(struct stream *s, IRP *irp, tui32 IoStatus) { tui32 len; + struct trans *con; log_debug("entered"); @@ -2115,7 +2203,9 @@ scard_handle_Reconnect_Return(struct stream *s, IRP *irp, /* get OutputBufferLen */ xstream_rd_u32_le(s, len); - + con = (struct trans *) (irp->user_data); + scard_function_reconnect_return(con, s, len); + devredir_irp_delete(irp); log_debug("leaving"); } @@ -2128,6 +2218,7 @@ scard_handle_BeginTransaction_Return(struct stream *s, IRP *irp, tui32 IoStatus) { tui32 len; + struct trans *con; log_debug("entered"); @@ -2147,7 +2238,9 @@ scard_handle_BeginTransaction_Return(struct stream *s, IRP *irp, /* get OutputBufferLen */ xstream_rd_u32_le(s, len); - + con = (struct trans *) (irp->user_data); + scard_function_begin_transaction_return(con, s, len); + devredir_irp_delete(irp); log_debug("leaving"); } @@ -2160,6 +2253,7 @@ scard_handle_EndTransaction_Return(struct stream *s, IRP *irp, tui32 IoStatus) { tui32 len; + struct trans *con; log_debug("entered"); @@ -2179,7 +2273,9 @@ scard_handle_EndTransaction_Return(struct stream *s, IRP *irp, /* get OutputBufferLen */ xstream_rd_u32_le(s, len); - + con = (struct trans *) (irp->user_data); + scard_function_end_transaction_return(con, s, len); + devredir_irp_delete(irp); log_debug("leaving"); } @@ -2192,6 +2288,7 @@ scard_handle_Status_Return(struct stream *s, IRP *irp, tui32 IoStatus) { tui32 len; + struct trans *con; log_debug("entered"); @@ -2211,7 +2308,9 @@ scard_handle_Status_Return(struct stream *s, IRP *irp, /* get OutputBufferLen */ xstream_rd_u32_le(s, len); - + con = (struct trans *) (irp->user_data); + scard_function_status_return(con, s, len); + devredir_irp_delete(irp); log_debug("leaving"); } @@ -2224,6 +2323,7 @@ scard_handle_Disconnect_Return(struct stream *s, IRP *irp, tui32 IoStatus) { tui32 len; + struct trans *con; log_debug("entered"); @@ -2243,7 +2343,9 @@ scard_handle_Disconnect_Return(struct stream *s, IRP *irp, /* get OutputBufferLen */ xstream_rd_u32_le(s, len); - + con = (struct trans *) (irp->user_data); + scard_function_disconnect_return(con, s, len); + devredir_irp_delete(irp); log_debug("leaving"); } @@ -2255,6 +2357,7 @@ scard_handle_Transmit_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus) { tui32 len; + struct trans *con; log_debug("entered"); @@ -2274,7 +2377,9 @@ scard_handle_Transmit_Return(struct stream *s, IRP *irp, tui32 DeviceId, /* get OutputBufferLen */ xstream_rd_u32_le(s, len); - + con = (struct trans *) (irp->user_data); + scard_function_transmit_return(con, s, len); + devredir_irp_delete(irp); log_debug("leaving"); } @@ -2286,6 +2391,7 @@ scard_handle_Control_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId,tui32 IoStatus) { tui32 len; + struct trans *con; log_debug("entered"); @@ -2305,7 +2411,9 @@ scard_handle_Control_Return(struct stream *s, IRP *irp, tui32 DeviceId, /* get OutputBufferLen */ xstream_rd_u32_le(s, len); - + con = (struct trans *) (irp->user_data); + scard_function_control_return(con, s, len); + devredir_irp_delete(irp); log_debug("leaving"); } @@ -2317,6 +2425,7 @@ scard_handle_Cancel_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus) { tui32 len; + struct trans *con; log_debug("entered"); @@ -2336,7 +2445,9 @@ scard_handle_Cancel_Return(struct stream *s, IRP *irp, tui32 DeviceId, /* get OutputBufferLen */ xstream_rd_u32_le(s, len); - + con = (struct trans *) (irp->user_data); + scard_function_cancel_return(con, s, len); + devredir_irp_delete(irp); log_debug("leaving"); } @@ -2348,6 +2459,7 @@ scard_handle_GetAttrib_Return(struct stream *s, IRP *irp, tui32 DeviceId, tui32 CompletionId, tui32 IoStatus) { tui32 len; + struct trans *con; log_debug("entered"); @@ -2367,6 +2479,8 @@ scard_handle_GetAttrib_Return(struct stream *s, IRP *irp, tui32 DeviceId, /* get OutputBufferLen */ xstream_rd_u32_le(s, len); - + con = (struct trans *) (irp->user_data); + scard_function_get_attrib_return(con, s, len); + devredir_irp_delete(irp); log_debug("leaving"); } |
