macOS HighSierra bug: SCardEndTransaction() returns SCARD_W_RESET_CARD instead of SCARD_W_REMOVED_CARD
This is part of the series: "macOS High Sierra and smart cards: known bugs"
SCardEndTransaction() returns different error codes than on GNU/Linux and Windows
SCardEndTransaction() on High Sierra returns error codes that are different than on GNU/Linux and Windows.SCardEndTransaction() returns SCARD_W_RESET_CARD after a card change
On High SierraSCardEndTransaction()
returns SCARD_W_RESET_CARD
if the card has been removed and inserted again in the reader.On GNU/Linux and Windows
SCardEndTransaction()
returns SCARD_W_REMOVED_CARD
instead.This behaviour can be very confusing for an application. The application has started a PC/SC transaction so it has an exclusive access to the card. No other application can reset the card during a transaction.
See also
Apple bug report #44672548 "PCSC SCardEndTransaction() returns SCARD_W_RESET_CARD instead of SCARD_W_REMOVED_CARD". Marked as duplicate of #23900844.This bug is very similar to previous bugs for other PC/SC functions:
-
SCardTransmit()
"macOS HighSierra bug: SCardTransmit() returns different error codes than on GNU/Linux and Windows" -
SCardBeginTransaction()
"OS X El Capitan bug: SCardBeginTransaction() returns different error codes than on GNU/Linux and Windows" -
SCardStatus()
"macOS HighSierra bug: SCardStatus() returns SCARD_W_RESET_CARD instead of SCARD_W_REMOVED_CARD"
Sample code
#include <stdio.h> #include <string.h> #include <unistd.h> #ifdef __APPLE__ #include <PCSC/winscard.h> #include <PCSC/wintypes.h> #else #include <winscard.h> #endif #define CHECK_RV(fct) if (SCARD_S_SUCCESS != rv) { printf(fct"() failed: %s (0x%08X)\n", pcsc_stringify_error(rv), rv); ret = 0; goto error; } else { printf(fct"(): OK\n"); } int main(void) { int ret = 1; SCARDCONTEXT hContext; SCARDHANDLE hCard; DWORD dwActiveProtocol; LONG rv; char mszReaders[1024]; DWORD dwReaders = sizeof(mszReaders); rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); CHECK_RV("SCardEstablishContext"); rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders); CHECK_RV("SCardListReaders"); rv = SCardConnect(hContext, mszReaders, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol); CHECK_RV("SCardConnect"); rv = SCardBeginTransaction(hCard); CHECK_RV("SCardBeginTransaction"); printf("Remove and insert the card. Then press Enter"); getchar(); rv = SCardEndTransaction(hCard, SCARD_LEAVE_CARD); CHECK_RV("SCardEndTransaction"); rv = SCardDisconnect(hCard, SCARD_UNPOWER_CARD); CHECK_RV("SCardDisconnect") rv = SCardReleaseContext(hContext); CHECK_RV("SCardReleaseContext") error: return ret; }
Result (on High Sierra)
$ ./main_Mac
SCardEstablishContext(): OK
SCardListReaders(): OK
SCardConnect(): OK
SCardBeginTransaction(): OK
Remove and insert the card. Then press Enter
SCardEndTransaction() failed: Card was reset. (0x80100068)
Expected result (on Debian)
$ ./main_Linux
SCardEstablishContext(): OK
SCardListReaders(): OK
SCardConnect(): OK
SCardBeginTransaction(): OK
Remove and insert the card. Then press Enter
SCardEndTransaction() failed: Card was removed. (0x80100069)