Important!

Blog moved to https://blog.apdu.fr/

I moved my blog from https://ludovicrousseau.blogspot.com/ to https://blog.apdu.fr/ . Why? I wanted to move away from Blogger (owne...

Sunday, December 26, 2021

Windows PC/SC and SCARD_E_SERVICE_STOPPED

It looks like Windows introduced a new behavior when the last smart card reader is disconnected. The PC/SC layer (WinSCard library) will return the error SCARD_E_SERVICE_STOPPED.

According to MSDN "Smart Card Return Values":

SCARD_E_SERVICE_STOPPED
0x8010001E
The smart card resource manager has shut down. 

 

Demonstration

The idea is to wait for a smart card reader if none is already present.

Then wait for the card reader to be disconnected.

Once disconnected SCardListReaders() will return SCARD_E_SERVICE_STOPPED (0x8010001E) instead of the expected SCARD_E_NO_READERS_AVAILABLE (0x8010002E).


Source code

#! /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)

hresult, readers = SCardListReaders(hcontext, [])
if not hresult in [SCARD_S_SUCCESS, SCARD_E_NO_READERS_AVAILABLE]:
    raise ListReadersException(hresult)
print('PC/SC Readers:', readers)

if not len(readers):
    print("Wait for the first reader")
    while not len(readers):
        hresult, readers = SCardListReaders(hcontext, [])
        if not hresult in [SCARD_S_SUCCESS, SCARD_E_NO_READERS_AVAILABLE]:
            raise ListReadersException(hresult)
        time.sleep(1)
    print('PC/SC Readers:', readers)

print("wait for the last reader removal")
while len(readers):
    hresult, readers = SCardListReaders(hcontext, [])
    if not hresult in [SCARD_S_SUCCESS, SCARD_E_NO_READERS_AVAILABLE]:
        raise ListReadersException(hresult)
    time.sleep(1)
print('PC/SC Readers:', readers)

hresult = SCardReleaseContext(hcontext)
if hresult != SCARD_S_SUCCESS:
    raise ReleaseContextException(hresult)

GNU/Linux result

rousseau@debian:~ $ ./SCardListReaders.py
PC/SC Readers: []
Wait for the first reader
PC/SC Readers: ['Alcor Micro AU9540 00 00']
wait for the last reader removal
PC/SC Readers: []

Windows result

(base) C:\Users\ludovic\Documents>python SCardListReaders.py
PC/SC Readers: []
Wait for the first reader
PC/SC Readers: ['Generic EMV Smartcard Reader 0']
wait for the last reader removal
Traceback (most recent call last):
  File "C:\Users\ludovic\Documents\SCardListReaders.py", line 29, in <module>
    raise ListReadersException(hresult)
smartcard.pcsc.PCSCExceptions.ListReadersException: Failed to list readers:
 Le gestionnaire de ressources des cartes ŕ puce s’est arręté. (0x8010001E)

Sorry for the error message in French. I don't know an equivalent of "LANG=C program" to have program run and use the default language (English).

You can also note the strange display of accented letters. Windows is not yet Unicode ready? :-)


Problems

The problem is that this new behavior broke code in PySCard, my PC/SC Python wrapper.

For example see

Yes, it is an old issue. I tried to fix it many times but the fixes has some other side effects and the problem is still present somewhere.

Windows is NOT my preferred platform (far from it) so fixing Windows issue is a P.I.T.A. for me. Help is really welcome here.

 

But Why?

What problem Microsoft is trying to solve with this behavior?

Why killing the resource manager and returning an error while there is still PC/SC clients connected to the resource manager?

If you have an idea of the answers please tell me.
If you know a way to change the behavior please tell me.

Use the pcsclite-muscle mailing list to discuss this issue.