From 2aa248853a536606021e40338755f41c2425e4ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sat, 5 Apr 2014 17:15:17 -0400 Subject: [PATCH] channels/smartcard: cancel outstanding IRPs on re-initialization --- channels/rdpdr/client/irp.c | 1 + channels/rdpdr/client/rdpdr_main.c | 2 + channels/smartcard/client/smartcard_main.c | 39 +++++++++++-------- channels/smartcard/client/smartcard_main.h | 2 +- .../smartcard/client/smartcard_operations.c | 2 +- include/freerdp/channels/rdpdr.h | 1 + winpr/include/winpr/collections.h | 3 ++ .../utils/collections/ListDictionary.c | 18 +++++++++ 8 files changed, 49 insertions(+), 19 deletions(-) diff --git a/channels/rdpdr/client/irp.c b/channels/rdpdr/client/irp.c index 7e49a6c0f..d4e7678eb 100644 --- a/channels/rdpdr/client/irp.c +++ b/channels/rdpdr/client/irp.c @@ -90,6 +90,7 @@ 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; diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index eaeea1dde..fd027a6c6 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -696,6 +696,8 @@ static void rdpdr_process_init(rdpdrPlugin* rdpdr) IFCALL(device->Init, device); } + + free(pKeys); } static void rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s) diff --git a/channels/smartcard/client/smartcard_main.c b/channels/smartcard/client/smartcard_main.c index 415f31081..6c15cfe88 100644 --- a/channels/smartcard/client/smartcard_main.c +++ b/channels/smartcard/client/smartcard_main.c @@ -53,30 +53,32 @@ static void smartcard_free(DEVICE* device) /** * Initialization occurs when the protocol server sends a device announce message. - * At that time, dwDeviceId MUST receive the unique device ID announced. - * The OutstandingIrps list MUST be set to the empty list. + * At that time, we need to cancel all outstanding IRPs. */ static void smartcard_init(DEVICE* device) { + IRP* irp; + int index; + int keyCount; + ULONG_PTR* pKeys; SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) device; if (ListDictionary_Count(smartcard->OutstandingIrps) > 0) { - fprintf(stderr, "Warning: smartcard device initialized with outstanding IRPs\n"); + pKeys = NULL; + keyCount = ListDictionary_GetKeys(smartcard->OutstandingIrps, &pKeys); + + for (index = 0; index < keyCount; index++) + { + irp = (IRP*) ListDictionary_GetItemValue(smartcard->OutstandingIrps, (void*) pKeys[index]); + + if (irp) + irp->cancelled = TRUE; + } + + free(pKeys); } - - fprintf(stderr, "SmartCard Init\n"); -} - -IRP* smartcard_get_outstanding_irp_by_id(SMARTCARD_DEVICE* smartcard, UINT32 completionId) -{ - IRP* irp = NULL; - void* key = (void*) (size_t) completionId; - - irp = (IRP*) ListDictionary_GetItemValue(smartcard->OutstandingIrps, key); - - return irp; } void smartcard_complete_irp(SMARTCARD_DEVICE* smartcard, IRP* irp) @@ -86,7 +88,10 @@ void smartcard_complete_irp(SMARTCARD_DEVICE* smartcard, IRP* irp) key = (void*) (size_t) irp->CompletionId; ListDictionary_Remove(smartcard->OutstandingIrps, key); - irp->Complete(irp); + if (!irp->cancelled) + irp->Complete(irp); + else + irp->Discard(irp); } static void smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp) @@ -99,7 +104,7 @@ static void smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp) switch (irp->MajorFunction) { case IRP_MJ_DEVICE_CONTROL: - smartcard_device_control(smartcard, irp); + smartcard_irp_device_control(smartcard, irp); break; default: diff --git a/channels/smartcard/client/smartcard_main.h b/channels/smartcard/client/smartcard_main.h index dc7be8c2e..8ca1d102f 100644 --- a/channels/smartcard/client/smartcard_main.h +++ b/channels/smartcard/client/smartcard_main.h @@ -101,7 +101,7 @@ typedef struct _SMARTCARD_DEVICE SMARTCARD_DEVICE; void smartcard_complete_irp(SMARTCARD_DEVICE* smartcard, IRP* irp); -void smartcard_device_control(SMARTCARD_DEVICE* smartcard, IRP* irp); +void smartcard_irp_device_control(SMARTCARD_DEVICE* smartcard, IRP* irp); #include "smartcard_pack.h" diff --git a/channels/smartcard/client/smartcard_operations.c b/channels/smartcard/client/smartcard_operations.c index c2505570b..80a5172da 100644 --- a/channels/smartcard/client/smartcard_operations.c +++ b/channels/smartcard/client/smartcard_operations.c @@ -1871,7 +1871,7 @@ finish: return status; } -void smartcard_device_control(SMARTCARD_DEVICE* smartcard, IRP* irp) +void smartcard_irp_device_control(SMARTCARD_DEVICE* smartcard, IRP* irp) { UINT32 result; UINT32 status; diff --git a/include/freerdp/channels/rdpdr.h b/include/freerdp/channels/rdpdr.h index bef5a9e81..21547d01d 100644 --- a/include/freerdp/channels/rdpdr.h +++ b/include/freerdp/channels/rdpdr.h @@ -342,6 +342,7 @@ struct _IRP UINT32 IoStatus; wStream* output; + BOOL cancelled; pcIRPResponse Complete; pcIRPResponse Discard; }; diff --git a/winpr/include/winpr/collections.h b/winpr/include/winpr/collections.h index 86bd34a87..0a9e974fd 100644 --- a/winpr/include/winpr/collections.h +++ b/winpr/include/winpr/collections.h @@ -200,6 +200,9 @@ typedef struct _wListDictionary wListDictionary; WINPR_API int ListDictionary_Count(wListDictionary* listDictionary); +WINPR_API void ListDictionary_Lock(wListDictionary* listDictionary); +WINPR_API void ListDictionary_Unlock(wListDictionary* listDictionary); + WINPR_API void ListDictionary_Add(wListDictionary* listDictionary, void* key, void* value); WINPR_API void* ListDictionary_Remove(wListDictionary* listDictionary, void* key); WINPR_API void* ListDictionary_Remove_Head(wListDictionary* listDictionary); diff --git a/winpr/libwinpr/utils/collections/ListDictionary.c b/winpr/libwinpr/utils/collections/ListDictionary.c index 0d6b48145..3cd956958 100644 --- a/winpr/libwinpr/utils/collections/ListDictionary.c +++ b/winpr/libwinpr/utils/collections/ListDictionary.c @@ -92,6 +92,24 @@ BOOL ListDictionary_IsSynchronized(wListDictionary* listDictionary) return listDictionary->synchronized; } +/** + * Lock access to the ListDictionary + */ + +void ListDictionary_Lock(wListDictionary* listDictionary) +{ + EnterCriticalSection(&listDictionary->lock); +} + +/** + * Unlock access to the ListDictionary + */ + +void ListDictionary_Unlock(wListDictionary* listDictionary) +{ + LeaveCriticalSection(&listDictionary->lock); +} + /** * Methods */