fix channel/smartcard: async request handling
authorBernhard Miklautz <bernhard.miklautz@thincast.com>
Mon, 4 Dec 2017 14:22:07 +0000 (15:22 +0100)
committerBernhard Miklautz <bernhard.miklautz@thincast.com>
Wed, 13 Dec 2017 16:04:06 +0000 (17:04 +0100)
The smart card channel tried to mimic mstsc's behavior on if an IRP was
processed synchronously or asynchronously. As the channel uses one thread per
context it could happen, especially with PCSC, that the main
channel thread was blocked waiting for an smart card operation to
complete. To prevent that behavior only call known safe functions in the
main thread (like CreateContext) and call the rest asynchronously.

For example the channel would block if a ListReaders is invoked on
the same context where a GetStatusChange (infinite timeout)
was already pending. Only when a status change happened the channel
would continue.

Note: Due to the one context per thread design it's important that
cancel isn't queued an alway run synchronously. Otherwise a specific
context might lock.

channels/smartcard/client/smartcard_main.c

index 0945206..f21f0f2 100644 (file)
@@ -385,17 +385,17 @@ UINT smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
 
                asyncIrp = TRUE;
 
-               /**
-                * The following matches mstsc's behavior of processing
-                * only certain requests asynchronously while processing
-                * those expected to return fast synchronously.
-                */
-
                switch (operation->ioControlCode)
                {
                        case SCARD_IOCTL_ESTABLISHCONTEXT:
                        case SCARD_IOCTL_RELEASECONTEXT:
                        case SCARD_IOCTL_ISVALIDCONTEXT:
+                       case SCARD_IOCTL_CANCEL:
+                       case SCARD_IOCTL_ACCESSSTARTEDEVENT:
+                       case SCARD_IOCTL_RELEASESTARTEDEVENT:
+                               asyncIrp = FALSE;
+                               break;
+
                        case SCARD_IOCTL_LISTREADERGROUPSA:
                        case SCARD_IOCTL_LISTREADERGROUPSW:
                        case SCARD_IOCTL_LISTREADERSA:
@@ -416,21 +416,14 @@ UINT smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
                        case SCARD_IOCTL_LOCATECARDSW:
                        case SCARD_IOCTL_LOCATECARDSBYATRA:
                        case SCARD_IOCTL_LOCATECARDSBYATRW:
-                       case SCARD_IOCTL_CANCEL:
                        case SCARD_IOCTL_READCACHEA:
                        case SCARD_IOCTL_READCACHEW:
                        case SCARD_IOCTL_WRITECACHEA:
                        case SCARD_IOCTL_WRITECACHEW:
                        case SCARD_IOCTL_GETREADERICON:
                        case SCARD_IOCTL_GETDEVICETYPEID:
-                               asyncIrp = FALSE;
-                               break;
-
                        case SCARD_IOCTL_GETSTATUSCHANGEA:
                        case SCARD_IOCTL_GETSTATUSCHANGEW:
-                               asyncIrp = TRUE;
-                               break;
-
                        case SCARD_IOCTL_CONNECTA:
                        case SCARD_IOCTL_CONNECTW:
                        case SCARD_IOCTL_RECONNECT:
@@ -447,11 +440,6 @@ UINT smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
                        case SCARD_IOCTL_GETTRANSMITCOUNT:
                                asyncIrp = TRUE;
                                break;
-
-                       case SCARD_IOCTL_ACCESSSTARTEDEVENT:
-                       case SCARD_IOCTL_RELEASESTARTEDEVENT:
-                               asyncIrp = FALSE;
-                               break;
                }
 
                pContext = ListDictionary_GetItemValue(smartcard->rgSCardContextList,