From 9de2a85f6a01ba9811b34c3ae3812fb51e8cf122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sat, 5 Apr 2014 17:51:13 -0400 Subject: [PATCH] channels/smartcard: add async irp processing --- channels/rdpdr/client/irp.c | 4 +- channels/smartcard/client/smartcard_main.c | 72 +++++++++++++++---- channels/smartcard/client/smartcard_main.h | 2 + .../smartcard/client/smartcard_operations.c | 17 +++++ include/freerdp/channels/rdpdr.h | 4 +- 5 files changed, 82 insertions(+), 17 deletions(-) diff --git a/channels/rdpdr/client/irp.c b/channels/rdpdr/client/irp.c index d4e7678eb..ff433159f 100644 --- a/channels/rdpdr/client/irp.c +++ b/channels/rdpdr/client/irp.c @@ -90,9 +90,11 @@ IRP* irp_new(DEVMAN* devman, wStream* s) Stream_Write_UINT32(irp->output, irp->CompletionId); /* CompletionId (4 bytes) */ Stream_Write_UINT32(irp->output, 0); /* IoStatus (4 bytes) */ - irp->cancelled = FALSE; irp->Complete = irp_complete; irp->Discard = irp_free; + irp->thread = NULL; + irp->cancelled = FALSE; + return irp; } diff --git a/channels/smartcard/client/smartcard_main.c b/channels/smartcard/client/smartcard_main.c index 6c15cfe88..f1f8bd4c4 100644 --- a/channels/smartcard/client/smartcard_main.c +++ b/channels/smartcard/client/smartcard_main.c @@ -34,6 +34,8 @@ #include "smartcard_main.h" +#define SMARTCARD_ASYNC_IRP 1 + static void smartcard_free(DEVICE* device) { SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) device; @@ -94,25 +96,16 @@ void smartcard_complete_irp(SMARTCARD_DEVICE* smartcard, IRP* irp) irp->Discard(irp); } -static void smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp) +void* smartcard_process_irp_worker_proc(IRP* irp) { - void* key; + SMARTCARD_DEVICE* smartcard; - key = (void*) (size_t) irp->CompletionId; - ListDictionary_Add(smartcard->OutstandingIrps, key, irp); + smartcard = (SMARTCARD_DEVICE*) irp->device; - switch (irp->MajorFunction) - { - case IRP_MJ_DEVICE_CONTROL: - smartcard_irp_device_control(smartcard, irp); - break; + smartcard_irp_device_control(smartcard, irp); - default: - fprintf(stderr, "MajorFunction 0x%X unexpected for smartcards.", irp->MajorFunction); - irp->IoStatus = STATUS_NOT_SUPPORTED; - smartcard_complete_irp(smartcard, irp); - break; - } + ExitThread(0); + return NULL; } /** @@ -120,6 +113,55 @@ static void smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp) * http://musclecard.996296.n3.nabble.com/Multiple-threads-and-SCardGetStatusChange-td4430.html */ +void smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp) +{ + void* key; + BOOL asyncIrp = FALSE; + UINT32 ioControlCode = 0; + + key = (void*) (size_t) irp->CompletionId; + ListDictionary_Add(smartcard->OutstandingIrps, key, irp); + + if (irp->MajorFunction == IRP_MJ_DEVICE_CONTROL) + { + smartcard_irp_device_control_peek_io_control_code(smartcard, irp, &ioControlCode); + +#ifdef SMARTCARD_ASYNC_IRP + if (!ioControlCode) + return; + + switch (ioControlCode) + { + case SCARD_IOCTL_TRANSMIT: + case SCARD_IOCTL_STATUSA: + case SCARD_IOCTL_STATUSW: + case SCARD_IOCTL_GETSTATUSCHANGEA: + case SCARD_IOCTL_GETSTATUSCHANGEW: + asyncIrp = TRUE; + break; + } +#endif + + if (!asyncIrp) + { + smartcard_irp_device_control(smartcard, irp); + } + else + { + irp->thread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE) smartcard_process_irp_worker_proc, + irp, 0, NULL); + } + } + else + { + fprintf(stderr, "Unexpected SmartCard IRP: MajorFunction 0x%08X MinorFunction: 0x%08X", + irp->MajorFunction, irp->MinorFunction); + irp->IoStatus = STATUS_NOT_SUPPORTED; + smartcard_complete_irp(smartcard, irp); + } +} + static void* smartcard_thread_func(void* arg) { IRP* irp; diff --git a/channels/smartcard/client/smartcard_main.h b/channels/smartcard/client/smartcard_main.h index 8ca1d102f..b401ea86e 100644 --- a/channels/smartcard/client/smartcard_main.h +++ b/channels/smartcard/client/smartcard_main.h @@ -100,8 +100,10 @@ struct _SMARTCARD_DEVICE typedef struct _SMARTCARD_DEVICE SMARTCARD_DEVICE; void smartcard_complete_irp(SMARTCARD_DEVICE* smartcard, IRP* irp); +void smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp); void smartcard_irp_device_control(SMARTCARD_DEVICE* smartcard, IRP* irp); +void smartcard_irp_device_control_peek_io_control_code(SMARTCARD_DEVICE* smartcard, IRP* irp, UINT32* ioControlCode); #include "smartcard_pack.h" diff --git a/channels/smartcard/client/smartcard_operations.c b/channels/smartcard/client/smartcard_operations.c index 80a5172da..09ae352aa 100644 --- a/channels/smartcard/client/smartcard_operations.c +++ b/channels/smartcard/client/smartcard_operations.c @@ -1871,6 +1871,23 @@ finish: return status; } +void smartcard_irp_device_control_peek_io_control_code(SMARTCARD_DEVICE* smartcard, IRP* irp, UINT32* ioControlCode) +{ + *ioControlCode = 0; + + if (Stream_GetRemainingLength(irp->input) < 32) + { + WLog_Print(smartcard->log, WLOG_WARN, "Device Control Request is too short: %d", + (int) Stream_GetRemainingLength(irp->input)); + return; + } + + Stream_Seek_UINT32(irp->input); /* OutputBufferLength (4 bytes) */ + Stream_Seek_UINT32(irp->input); /* InputBufferLength (4 bytes) */ + Stream_Read_UINT32(irp->input, *ioControlCode); /* IoControlCode (4 bytes) */ + Stream_Rewind(irp->input, (4 + 4 + 4)); +} + void smartcard_irp_device_control(SMARTCARD_DEVICE* smartcard, IRP* irp) { UINT32 result; diff --git a/include/freerdp/channels/rdpdr.h b/include/freerdp/channels/rdpdr.h index 21547d01d..a8e115e00 100644 --- a/include/freerdp/channels/rdpdr.h +++ b/include/freerdp/channels/rdpdr.h @@ -342,9 +342,11 @@ struct _IRP UINT32 IoStatus; wStream* output; - BOOL cancelled; pcIRPResponse Complete; pcIRPResponse Discard; + + HANDLE thread; + BOOL cancelled; }; struct _DEVMAN