Skip to content

Commit

Permalink
Fix Windows 10 SCARD_E_SERVICE_STOPPED from SCardListReaders()
Browse files Browse the repository at this point in the history
On Windows 10 the PC/SC manager is stopped when
the latest reader is unplugged.

#75
#27
#74
  • Loading branch information
ABautkin authored and LudovicRousseau committed Mar 25, 2019
1 parent a31fba3 commit bf906d3
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 2 deletions.
5 changes: 5 additions & 0 deletions smartcard/Exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""

Expand Down
18 changes: 17 additions & 1 deletion smartcard/pcsc/PCSCContext.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
10 changes: 9 additions & 1 deletion smartcard/pcsc/PCSCReader.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit bf906d3

Please sign in to comment.