From bf906d3bc00bc929b05a3a10aabcf349138032d6 Mon Sep 17 00:00:00 2001 From: ABautkin Date: Thu, 21 Mar 2019 13:33:47 +0300 Subject: [PATCH] Fix Windows 10 SCARD_E_SERVICE_STOPPED from SCardListReaders() On Windows 10 the PC/SC manager is stopped when the latest reader is unplugged. https://github.com/LudovicRousseau/pyscard/pull/75 https://github.com/LudovicRousseau/pyscard/issues/27 https://github.com/LudovicRousseau/pyscard/issues/74 --- smartcard/Exceptions.py | 5 +++++ smartcard/pcsc/PCSCContext.py | 18 +++++++++++++++++- smartcard/pcsc/PCSCReader.py | 10 +++++++++- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/smartcard/Exceptions.py b/smartcard/Exceptions.py index 9eac5879..a426206f 100644 --- a/smartcard/Exceptions.py +++ b/smartcard/Exceptions.py @@ -70,6 +70,11 @@ class CardServiceException(SmartcardException): pass +class CardServiceStoppedException(SmartcardException): + """Raised when the CardService was stopped""" + pass + + class InvalidATRMaskLengthException(SmartcardException): """Raised when an ATR mask does not match an ATR length.""" diff --git a/smartcard/pcsc/PCSCContext.py b/smartcard/pcsc/PCSCContext.py index e5050d5b..badbf030 100644 --- a/smartcard/pcsc/PCSCContext.py +++ b/smartcard/pcsc/PCSCContext.py @@ -42,6 +42,9 @@ def __init__(self): def getContext(self): return self.hcontext + def releaseContext(self): + return SCardReleaseContext(self.hcontext) + # the singleton mutex = RLock() instance = None @@ -50,10 +53,23 @@ def __init__(self): PCSCContext.mutex.acquire() try: if not PCSCContext.instance: - PCSCContext.instance = PCSCContext.__PCSCContextSingleton() + self.renewContext() finally: PCSCContext.mutex.release() def __getattr__(self, name): if self.instance: return getattr(self.instance, name) + + def renewContext(): + PCSCContext.mutex.acquire() + try: + if PCSCContext.instance is not None: + PCSCContext.instance.releaseContext() + + PCSCContext.instance = PCSCContext.__PCSCContextSingleton() + finally: + PCSCContext.mutex.release() + + return PCSCContext.instance.getContext() + renewContext = staticmethod(renewContext) diff --git a/smartcard/pcsc/PCSCReader.py b/smartcard/pcsc/PCSCReader.py index e7f588d7..2121da01 100644 --- a/smartcard/pcsc/PCSCReader.py +++ b/smartcard/pcsc/PCSCReader.py @@ -45,6 +45,8 @@ def __PCSCreaders__(hcontext, groups=[]): if hresult != 0: if hresult == SCARD_E_NO_READERS_AVAILABLE: readers = [] + elif hresult == SCARD_E_SERVICE_STOPPED: + raise CardServiceStoppedException() else: raise ListReadersException(hresult) @@ -107,7 +109,13 @@ def readers(groups=[]): creaders = [] hcontext = PCSCContext().getContext() - for reader in __PCSCreaders__(hcontext, groups): + try: + pcsc_readers = __PCSCreaders__(hcontext, groups) + except CardServiceStoppedException: + hcontext = PCSCContext.renewContext() + pcsc_readers = __PCSCreaders__(hcontext, groups) + + for reader in pcsc_readers: creaders.append(PCSCReader.Factory.create(reader)) return creaders readers = staticmethod(readers)