channels/smartcard: add improve completed IRP management
This commit is contained in:
parent
d53a9415ae
commit
67f691f90a
@ -35,6 +35,8 @@
|
|||||||
|
|
||||||
#include "smartcard_main.h"
|
#include "smartcard_main.h"
|
||||||
|
|
||||||
|
#define DEBUG_SMARTCARD_INIT 1
|
||||||
|
|
||||||
static BOOL g_SmartCardAsync = TRUE;
|
static BOOL g_SmartCardAsync = TRUE;
|
||||||
|
|
||||||
static void smartcard_free(DEVICE* device)
|
static void smartcard_free(DEVICE* device)
|
||||||
@ -51,6 +53,7 @@ static void smartcard_free(DEVICE* device)
|
|||||||
MessageQueue_Free(smartcard->IrpQueue);
|
MessageQueue_Free(smartcard->IrpQueue);
|
||||||
ListDictionary_Free(smartcard->rgSCardContextList);
|
ListDictionary_Free(smartcard->rgSCardContextList);
|
||||||
ListDictionary_Free(smartcard->rgOutstandingMessages);
|
ListDictionary_Free(smartcard->rgOutstandingMessages);
|
||||||
|
Queue_Free(smartcard->CompletedIrpQueue);
|
||||||
|
|
||||||
free(device);
|
free(device);
|
||||||
}
|
}
|
||||||
@ -62,6 +65,7 @@ static void smartcard_free(DEVICE* device)
|
|||||||
|
|
||||||
static void smartcard_init(DEVICE* device)
|
static void smartcard_init(DEVICE* device)
|
||||||
{
|
{
|
||||||
|
IRP* irp;
|
||||||
int index;
|
int index;
|
||||||
int keyCount;
|
int keyCount;
|
||||||
ULONG_PTR* pKeys;
|
ULONG_PTR* pKeys;
|
||||||
@ -76,6 +80,16 @@ static void smartcard_init(DEVICE* device)
|
|||||||
* be removed from rgSCardContextList.
|
* be removed from rgSCardContextList.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Step 1: Call SCardCancel on existing contexts, unblocking all outstanding IRPs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef DEBUG_SMARTCARD_INIT
|
||||||
|
printf("[1] rgSCardContextList: %d rgOutstandingMessages: %d\n",
|
||||||
|
ListDictionary_Count(smartcard->rgSCardContextList),
|
||||||
|
ListDictionary_Count(smartcard->rgOutstandingMessages));
|
||||||
|
#endif
|
||||||
|
|
||||||
if (ListDictionary_Count(smartcard->rgSCardContextList) > 0)
|
if (ListDictionary_Count(smartcard->rgSCardContextList) > 0)
|
||||||
{
|
{
|
||||||
pKeys = NULL;
|
pKeys = NULL;
|
||||||
@ -85,11 +99,73 @@ static void smartcard_init(DEVICE* device)
|
|||||||
{
|
{
|
||||||
hContext = (SCARDCONTEXT) ListDictionary_GetItemValue(smartcard->rgSCardContextList, (void*) pKeys[index]);
|
hContext = (SCARDCONTEXT) ListDictionary_GetItemValue(smartcard->rgSCardContextList, (void*) pKeys[index]);
|
||||||
|
|
||||||
|
if (SCardIsValidContext(hContext))
|
||||||
|
{
|
||||||
SCardCancel(hContext);
|
SCardCancel(hContext);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
free(pKeys);
|
free(pKeys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Step 2: Wait for all outstanding IRPs to complete.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef DEBUG_SMARTCARD_INIT
|
||||||
|
printf("[2] rgSCardContextList: %d rgOutstandingMessages: %d\n",
|
||||||
|
ListDictionary_Count(smartcard->rgSCardContextList),
|
||||||
|
ListDictionary_Count(smartcard->rgOutstandingMessages));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ListDictionary_Count(smartcard->rgOutstandingMessages) > 0)
|
||||||
|
{
|
||||||
|
pKeys = NULL;
|
||||||
|
keyCount = ListDictionary_GetKeys(smartcard->rgOutstandingMessages, &pKeys);
|
||||||
|
|
||||||
|
for (index = 0; index < keyCount; index++)
|
||||||
|
{
|
||||||
|
irp = (IRP*) ListDictionary_GetItemValue(smartcard->rgOutstandingMessages, (void*) pKeys[index]);
|
||||||
|
ListDictionary_Remove(smartcard->rgOutstandingMessages, (void*) pKeys[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(pKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Step 3: Call SCardReleaseContext on remaining contexts and remove them from rgSCardContextList.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef DEBUG_SMARTCARD_INIT
|
||||||
|
printf("[3] rgSCardContextList: %d rgOutstandingMessages: %d\n",
|
||||||
|
ListDictionary_Count(smartcard->rgSCardContextList),
|
||||||
|
ListDictionary_Count(smartcard->rgOutstandingMessages));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ListDictionary_Count(smartcard->rgSCardContextList) > 0)
|
||||||
|
{
|
||||||
|
pKeys = NULL;
|
||||||
|
keyCount = ListDictionary_GetKeys(smartcard->rgSCardContextList, &pKeys);
|
||||||
|
|
||||||
|
for (index = 0; index < keyCount; index++)
|
||||||
|
{
|
||||||
|
hContext = (SCARDCONTEXT) ListDictionary_GetItemValue(smartcard->rgSCardContextList, (void*) pKeys[index]);
|
||||||
|
ListDictionary_Remove(smartcard->rgSCardContextList, (void*) pKeys[index]);
|
||||||
|
|
||||||
|
if (SCardIsValidContext(hContext))
|
||||||
|
{
|
||||||
|
SCardReleaseContext(hContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(pKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_SMARTCARD_INIT
|
||||||
|
printf("[4] rgSCardContextList: %d rgOutstandingMessages: %d\n",
|
||||||
|
ListDictionary_Count(smartcard->rgSCardContextList),
|
||||||
|
ListDictionary_Count(smartcard->rgOutstandingMessages));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void smartcard_complete_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
void smartcard_complete_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
||||||
@ -110,6 +186,8 @@ void* smartcard_process_irp_worker_proc(IRP* irp)
|
|||||||
|
|
||||||
smartcard_irp_device_control(smartcard, irp);
|
smartcard_irp_device_control(smartcard, irp);
|
||||||
|
|
||||||
|
Queue_Enqueue(smartcard->CompletedIrpQueue, (void*) irp);
|
||||||
|
|
||||||
ExitThread(0);
|
ExitThread(0);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -162,6 +240,8 @@ void smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
|||||||
if (!asyncIrp)
|
if (!asyncIrp)
|
||||||
{
|
{
|
||||||
smartcard_irp_device_control(smartcard, irp);
|
smartcard_irp_device_control(smartcard, irp);
|
||||||
|
|
||||||
|
Queue_Enqueue(smartcard->CompletedIrpQueue, (void*) irp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -174,22 +254,32 @@ void smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
|||||||
{
|
{
|
||||||
fprintf(stderr, "Unexpected SmartCard IRP: MajorFunction 0x%08X MinorFunction: 0x%08X",
|
fprintf(stderr, "Unexpected SmartCard IRP: MajorFunction 0x%08X MinorFunction: 0x%08X",
|
||||||
irp->MajorFunction, irp->MinorFunction);
|
irp->MajorFunction, irp->MinorFunction);
|
||||||
|
|
||||||
irp->IoStatus = STATUS_NOT_SUPPORTED;
|
irp->IoStatus = STATUS_NOT_SUPPORTED;
|
||||||
smartcard_complete_irp(smartcard, irp);
|
|
||||||
|
Queue_Enqueue(smartcard->CompletedIrpQueue, (void*) irp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* smartcard_thread_func(void* arg)
|
static void* smartcard_thread_func(void* arg)
|
||||||
{
|
{
|
||||||
IRP* irp;
|
IRP* irp;
|
||||||
|
DWORD nCount;
|
||||||
|
DWORD status;
|
||||||
|
HANDLE hEvents[2];
|
||||||
wMessage message;
|
wMessage message;
|
||||||
SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) arg;
|
SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) arg;
|
||||||
|
|
||||||
|
nCount = 0;
|
||||||
|
hEvents[nCount++] = MessageQueue_Event(smartcard->IrpQueue);
|
||||||
|
hEvents[nCount++] = Queue_Event(smartcard->CompletedIrpQueue);
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (!MessageQueue_Wait(smartcard->IrpQueue))
|
status = WaitForMultipleObjects(nCount, hEvents, FALSE, INFINITE);
|
||||||
break;
|
|
||||||
|
|
||||||
|
if (WaitForSingleObject(MessageQueue_Event(smartcard->IrpQueue), 0) == WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
if (!MessageQueue_Peek(smartcard->IrpQueue, &message, TRUE))
|
if (!MessageQueue_Peek(smartcard->IrpQueue, &message, TRUE))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -199,8 +289,27 @@ static void* smartcard_thread_func(void* arg)
|
|||||||
irp = (IRP*) message.wParam;
|
irp = (IRP*) message.wParam;
|
||||||
|
|
||||||
if (irp)
|
if (irp)
|
||||||
|
{
|
||||||
smartcard_process_irp(smartcard, irp);
|
smartcard_process_irp(smartcard, irp);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WaitForSingleObject(Queue_Event(smartcard->CompletedIrpQueue), 0) == WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
irp = (IRP*) Queue_Dequeue(smartcard->CompletedIrpQueue);
|
||||||
|
|
||||||
|
if (irp)
|
||||||
|
{
|
||||||
|
if (irp->thread)
|
||||||
|
{
|
||||||
|
WaitForSingleObject(irp->thread, INFINITE);
|
||||||
|
CloseHandle(irp->thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
smartcard_complete_irp(smartcard, irp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ExitThread(0);
|
ExitThread(0);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -267,6 +376,7 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
|||||||
smartcard->IrpQueue = MessageQueue_New(NULL);
|
smartcard->IrpQueue = MessageQueue_New(NULL);
|
||||||
smartcard->rgSCardContextList = ListDictionary_New(TRUE);
|
smartcard->rgSCardContextList = ListDictionary_New(TRUE);
|
||||||
smartcard->rgOutstandingMessages = ListDictionary_New(TRUE);
|
smartcard->rgOutstandingMessages = ListDictionary_New(TRUE);
|
||||||
|
smartcard->CompletedIrpQueue = Queue_New(TRUE, -1, -1);
|
||||||
|
|
||||||
smartcard->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) smartcard_thread_func,
|
smartcard->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) smartcard_thread_func,
|
||||||
smartcard, CREATE_SUSPENDED, NULL);
|
smartcard, CREATE_SUSPENDED, NULL);
|
||||||
|
@ -92,6 +92,7 @@ struct _SMARTCARD_DEVICE
|
|||||||
|
|
||||||
HANDLE thread;
|
HANDLE thread;
|
||||||
wMessageQueue* IrpQueue;
|
wMessageQueue* IrpQueue;
|
||||||
|
wQueue* CompletedIrpQueue;
|
||||||
wListDictionary* rgSCardContextList;
|
wListDictionary* rgSCardContextList;
|
||||||
wListDictionary* rgOutstandingMessages;
|
wListDictionary* rgOutstandingMessages;
|
||||||
};
|
};
|
||||||
|
@ -1350,6 +1350,4 @@ void smartcard_irp_device_control(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
|||||||
Stream_Write_UINT32(irp->output, result); /* Result (4 bytes) */
|
Stream_Write_UINT32(irp->output, result); /* Result (4 bytes) */
|
||||||
|
|
||||||
Stream_SetPosition(irp->output, Stream_Length(irp->output));
|
Stream_SetPosition(irp->output, Stream_Length(irp->output));
|
||||||
|
|
||||||
smartcard_complete_irp(smartcard, irp);
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user