/* scardcontrol.c: sample code to use/test SCardControl() API Copyright (C) 2004 Ludovic Rousseau This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * $Id$ */ #include #include #include #include #include #include #include #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #define SCARD_CTL_CODE(code) (0x42000000 + (code)) #define IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE SCARD_CTL_CODE(1) #define IOCTL_SMARTCARD_VENDOR_VERIFY_PIN SCARD_CTL_CODE(2) #define IOCTL_SMARTCARD_VENDOR_MODIFY_PIN SCARD_CTL_CODE(3) #define IOCTL_SMARTCARD_VENDOR_TRANSFER_PIN SCARD_CTL_CODE(4) /* PCSC error message pretty print */ #define PCSC_ERROR_EXIT(rv, text) \ if (rv != SCARD_S_SUCCESS) \ { \ printf(text ": %s (0x%lX)\n", pcsc_stringify_error(rv), rv); \ goto end; \ } \ else \ printf(text ": OK\n\n"); #define PCSC_ERROR_CONT(rv, text) \ if (rv != SCARD_S_SUCCESS) \ printf(text ": %s (0x%lX)\n", pcsc_stringify_error(rv), rv); \ else \ printf(text ": OK\n\n"); int main(int argc, char *argv[]) { LONG rv; SCARDCONTEXT hContext; DWORD dwReaders; LPSTR mszReaders; char *ptr, **readers = NULL; int nbReaders; SCARDHANDLE hCard; DWORD dwActiveProtocol, dwReaderLen, dwState, dwProt, dwAtrLen; BYTE pbAtr[MAX_ATR_SIZE] = ""; BYTE pbReader[MAX_READERNAME] = ""; int reader_nb; int i, offset; unsigned char bSendBuffer[MAX_BUFFER_SIZE]; unsigned char bRecvBuffer[MAX_BUFFER_SIZE]; DWORD length; printf("SCardControl sample code\n"); printf("V 1.0 2004, Ludovic Rousseau \n"); rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); if (rv != SCARD_S_SUCCESS) { printf("SCardEstablishContext: Cannot Connect to Resource Manager %lX\n", rv); return 1; } /* Retrieve the available readers list */ rv = SCardListReaders(hContext, NULL, NULL, &dwReaders); if (rv != SCARD_S_SUCCESS) { printf("SCardListReader: %lX\n", rv); } mszReaders = malloc(sizeof(char)*dwReaders); if (mszReaders == NULL) { printf("malloc: not enough memory\n"); goto end; } rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders); if (rv != SCARD_S_SUCCESS) printf("SCardListReader: %lX\n", rv); /* Extract readers from the null separated string and get the total * number of readers */ nbReaders = 0; ptr = mszReaders; while (*ptr != '\0') { ptr += strlen(ptr)+1; nbReaders++; } if (nbReaders == 0) { printf("No reader found\n"); goto end; } /* allocate the readers table */ readers = calloc(nbReaders, sizeof(char *)); if (NULL == readers) { printf("Not enough memory for readers[]\n"); goto end; } /* fill the readers table */ nbReaders = 0; ptr = mszReaders; while (*ptr != '\0') { printf("%d: %s\n", nbReaders, ptr); readers[nbReaders] = ptr; ptr += strlen(ptr)+1; nbReaders++; } if (argc > 1) { reader_nb = atoi(argv[1]); if (reader_nb < 0 || reader_nb >= nbReaders) { printf("Wrong reader index: %d\n", reader_nb); goto end; } } else reader_nb = 0; /* connect to a card */ dwActiveProtocol = -1; rv = SCardConnect(hContext, readers[reader_nb], SCARD_SHARE_DIRECT, SCARD_PROTOCOL_ANY, &hCard, &dwActiveProtocol); printf(" Protocol: %ld\n", dwActiveProtocol); PCSC_ERROR_EXIT(rv, "SCardConnect") /* get firmware */ printf(" Get Firmware\n"); /* this is specific to Gemplus readers */ bSendBuffer[0] = 0x02; rv = SCardControl(hCard, IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE, bSendBuffer, 1, bRecvBuffer, sizeof(bRecvBuffer), &length); printf(" Firmware: "); for (i=0; i