In a previous blog article " Windows PC/SC and SCARD_E_SERVICE_STOPPED " I presented a problem on Windows when the last reader is disconnected.
After a discussion on the pcsclite-muscle mailing list I got nice feedback.Thanks.
Diego de Felice gave a reference to a Microsoft documentation from 2016 "What's New in Smart Cards"
Smart Card Service start and stop behavior
Smart card reader detection logic has been added so that the Smart Card Service runs only when appropriate. On Windows Server 2012 and Windows 8, the Smart Card Service (scardsvr) automatically starts when the user connects a smart card reader and automatically stops when a user removes a smart card reader and no other smart card reader is connected to the computer. On startup, the Smart Card Service automatically starts if a reader was previously connected to the computer but a reader is not currently connected to the system. If no smart card readers are connected to the computer, the service will automatically shut down one minute after the last API call into the Smart Card Service. If a reader was never previously connected to the computer, the service will not start automatically.
So the (strange) behavior is documented by Microsoft.
Stephan Brunner then gave a solution: establish a new context.
Source code
I wanted to test the hack proposed by Stephan.
#! /usr/bin/env python3 from smartcard.scard import * from smartcard.pcsc.PCSCExceptions import * import time hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise EstablishContextException(hresult) i = 0 while True: hresult, readers = SCardListReaders(hcontext, []) exc = BaseSCardException(message="", hresult=hresult) print('(%d) %s:' % (i, str(exc)), readers) if not hresult in [SCARD_S_SUCCESS, SCARD_E_NO_READERS_AVAILABLE]: hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER) if hresult != SCARD_S_SUCCESS: raise EstablishContextException(hresult) time.sleep(1) i += 1
Output
(base) C:\Users\ludovic\Documents>python SCardListReaders.py (0) : Impossible de trouver un lecteur de carte ŕ puce. (0x8010002E): [] (1) : Impossible de trouver un lecteur de carte ŕ puce. (0x8010002E): [] (2) : Impossible de trouver un lecteur de carte ŕ puce. (0x8010002E): [] (3) : Impossible de trouver un lecteur de carte ŕ puce. (0x8010002E): [] (4) : L’opération a réussi. (0x00000000): ['Generic EMV Smartcard Reader 0'] (5) : L’opération a réussi. (0x00000000): ['Generic EMV Smartcard Reader 0'] (6) : L’opération a réussi. (0x00000000): ['Generic EMV Smartcard Reader 0'] (7) : L’opération a réussi. (0x00000000): ['Generic EMV Smartcard Reader 0'] (8) : L’opération a réussi. (0x00000000): ['Generic EMV Smartcard Reader 0'] (9) : Le gestionnaire de ressources des cartes ŕ puce s’est arręté. (0x8010001E): [] (10) : Impossible de trouver un lecteur de carte ŕ puce. (0x8010002E): [] (11) : Impossible de trouver un lecteur de carte ŕ puce. (0x8010002E): [] (12) : Impossible de trouver un lecteur de carte ŕ puce. (0x8010002E): [] (13) : L’opération a réussi. (0x00000000): ['Generic EMV Smartcard Reader 0'] (14) : L’opération a réussi. (0x00000000): ['Generic EMV Smartcard Reader 0'] (15) : L’opération a réussi. (0x00000000): ['Generic EMV Smartcard Reader 0'] (16) : L’opération a réussi. (0x00000000): ['Generic EMV Smartcard Reader 0'] (17) : Le gestionnaire de ressources des cartes ŕ puce s’est arręté. (0x8010001E): [] (18) : Impossible de trouver un lecteur de carte ŕ puce. (0x8010002E): [] (19) : Impossible de trouver un lecteur de carte ŕ puce. (0x8010002E): []
Description
Step 0, I start the script with no smart card reader connected. So
SCardListReaders()
returns the expected
0x8010002E
which is SCARD_E_NO_READERS_AVAILABLE
.
Step 4, Then I connect a smart card reader.
Step 9, Then I disconnect the smart card reader and
SCardListReaders()
returns the unexpected error
0x8010001E
i.e. SCARD_E_SERVICE_STOPPED
.
The program then calls SCardEstablishContext() again, with success, and continue.
Step 10, The next call to CardListReaders()
returns the expected
0x8010002E
. So I guess the PC/SC resource manager has been
re-started.
Step 13, Connecting a new smart card reader works fine and the reader is detected.
Step 17, I disconnect the reader and I get again the SCARD_E_SERVICE_STOPPED
error.
Without the hack
If the code does not establish a new context then
CardListReaders()
will return
SCARD_E_SERVICE_STOPPED
for ever. And if I connect a new reader
it is not detected.
I think this behavior explains the bug reported in CardRequest waitforcard ATR can't see reconnected readers on Windows (regression) #123.
Conclusion
Ignoring SCARD_E_SERVICE_STOPPED
, as I did in commit 5b43ef5, is not a correct solution. I have to work on a better solution (just for Windows).