SCardStatus returns SCARD_E_INSUFFICIENT_BUFFER
SCardStatus() does not correctly report the reader name length. The terminating NUL character of the reader name is not counted. So a second call toSCardStatus() using the size returned by the first SCardStatus() call will fail with 0x80100008 (that is SCARD_E_INSUFFICIENT_BUFFER).It is a really stupid bug and very easy to fix for Apple.
See also
"Problem with SCardStatus on MAC OS X 10.10 (Yosemite)" at https://smartcardservices.macosforge.org/trac/ticket/140.Apple bug report #19306215 "PC/SC SCardStatus returns SCARD_E_INSUFFICIENT_BUFFER". Closed by Apple, 9th January 2015, as a duplicated of #18890042.
Sample code
#include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef __APPLE__ #include <PCSC/winscard.h> #include <PCSC/wintypes.h> #else #include <winscard.h> #endif int main(int argc, const char * argv[]) { SCARDCONTEXT hContext; LPSTR mszReaders; DWORD err = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); if (err != SCARD_S_SUCCESS) { printf("ScardEstablishedContext: 0x%08x\n",err); return -1; } DWORD cchReaders = 0; err = SCardListReaders(hContext, "SCard$AllReaders", NULL, &cchReaders); if (err != 0) { printf("ScardListReaders: 0x%08x\n",err); return -1; } mszReaders = calloc(cchReaders, sizeof(char)); if (!mszReaders) { printf("calloc\n"); return -1; } err = SCardListReaders(hContext,"SCard$AllReaders", mszReaders, &cchReaders); if (err != SCARD_S_SUCCESS) { printf("ScardListReaders: 0x%08x\n",err); return -1; } printf("Reader: %s\n", mszReaders); SCARDHANDLE hCard; DWORD dwActiveProtocol; err = SCardConnect(hContext, mszReaders, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol); if (err != SCARD_S_SUCCESS) { printf("ScardConnect: 0x%08x\n",err); return -1; } /* 1st SCardStatus call to get the reader name length */ char name[100]; DWORD len; err = SCardStatus(hCard, NULL, &len, NULL, NULL, NULL, NULL); if (err != SCARD_S_SUCCESS) { printf("SCardStatus: 0x%08x\n",err); return -1; } printf("reader name length: %d\n", len); //len += 1; /* 2nd SCardStatus call to get the reader name value */ err = SCardStatus(hCard, name, &len, NULL, NULL, NULL, NULL); if (err != SCARD_S_SUCCESS) { printf("SCardStatus: 0x%08x\n",err); return -1; } printf("Reader name: %s (%ld)\n", name, strlen(name)); SCardDisconnect(hCard, SCARD_LEAVE_CARD); SCardReleaseContext(hContext); return 0; }
Result (on Yosemite)
$ CFLAGS="-framework PCSC" make main cc -framework PCSC main.c -o main
$ ./main Reader: Gemalto PC Twin Reader reader name length: 22 SCardStatus: 0x80100008
If I uncomment the line: len += 1; I get:
$ ./main Reader: Gemalto PC Twin Reader reader name length: 22 Reader name: Gemalto PC Twin Reader (22)
Note that the reader length returned by the first
SCardStatus() call is identical to the value returned by strlen(name). And strlen() does NOT includes the terminating NUL character.Expected result (on Debian)
$ CFLAGS=`pkg-config --cflags libpcsclite` LDFLAGS=`pkg-config --libs libpcsclite` make main cc -pthread -I/usr/include/PCSC -lpcsclite main.c -o main
$ ./main Reader: Gemalto PC Twin Reader 00 00 reader length: 29 Reader name: Gemalto PC Twin Reader 00 00 (28)
Note that the length returned by the first
SCardStatus() call is strlen(name) + 1.Known workaround
Add 1 to the reader length returned bySCardStatus().