channels/smartcard: add async irp processing

This commit is contained in:
Marc-André Moreau 2014-04-05 17:51:13 -04:00
parent 2aa248853a
commit 9de2a85f6a
5 changed files with 82 additions and 17 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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"

View File

@ -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;

View File

@ -342,9 +342,11 @@ struct _IRP
UINT32 IoStatus;
wStream* output;
BOOL cancelled;
pcIRPResponse Complete;
pcIRPResponse Discard;
HANDLE thread;
BOOL cancelled;
};
struct _DEVMAN