#include #include #include #ifdef __APPLE__ #include #include #else #include #endif #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif #ifndef SCARD_CTL_CODE #define SCARD_CTL_CODE(code) (0x42000000 + (code)) #endif #define IOCTL_SMARTCARD_TOGGLE_CARD_STATE SCARD_CTL_CODE(2075) LONG GetReaderNames(SCARDCONTEXT hContext, LPSTR **pReaderNames, LPDWORD pNumReaders); void FreeReaderNames(LPSTR *readerNames, DWORD numReaders); /** * The main function. * @param[in] argc the argument count * @param[in] argv the array of arguments */ int main(int argc, char *argv[]) { LONG err = SCARD_S_SUCCESS; SCARDCONTEXT hContext; BOOL established = FALSE; LPSTR *readerNames = NULL; DWORD numReaders = 0; int readerIndex = -1; SCARDHANDLE hCard; DWORD activeProtocol = 0; int i = 0; // Establish the context. printf("Establishing the context...\n"); err = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &hContext); if (err != SCARD_S_SUCCESS) { printf("Error: SCardEstablishContext failed with error 0x%08X\n", err); goto cleanup; } established = TRUE; // Get reader names. printf("Getting reader names...\n"); err = GetReaderNames(hContext, &readerNames, &numReaders); if (err != SCARD_S_SUCCESS) { printf("Error: GetReaderNames failed with error 0x%08X\n", err); goto cleanup; } // Display reader names. for (i = 0; i < numReaders; i++) { printf("Reader %d: %s\n", i, readerNames[i]); } // Select reader. while ((readerIndex < 0) || (readerIndex >= numReaders)) { printf("Select reader: "); scanf("%d", &readerIndex); } // Connect to the reader. printf("Connecting to the reader (shared, T=0 or T=1)...\n"); err = SCardConnect(hContext, readerNames[readerIndex], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &activeProtocol); if (err != SCARD_S_SUCCESS) { printf("Error: SCardConnect failed with error 0x%08X\n", err); goto cleanup; } // Disconnect the reader. printf("Disconnecting the reader...\n"); err = SCardDisconnect(hCard, SCARD_LEAVE_CARD); if (err != SCARD_S_SUCCESS) { printf("Error: SCardConnect failed with error 0x%08X\n", err); goto cleanup; } // Connect to the reader. printf("Connecting to the reader (direct, raw)...\n"); err = SCardConnect(hContext, readerNames[readerIndex], SCARD_SHARE_DIRECT, SCARD_PROTOCOL_RAW, &hCard, &activeProtocol); if (err != SCARD_S_SUCCESS) { printf("Error: SCardConnect failed with error 0x%08X\n", err); goto cleanup; } // Disconnect the reader. printf("Disconnecting the reader...\n"); err = SCardDisconnect(hCard, SCARD_LEAVE_CARD); if (err != SCARD_S_SUCCESS) { printf("Error: SCardConnect failed with error 0x%08X\n", err); goto cleanup; } for (i = 0; i < 10; i++) { // Connect to the reader. printf("Connecting to the reader (shared, T=0 or T=1)...\n"); err = SCardConnect(hContext, readerNames[readerIndex], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &activeProtocol); if (err != SCARD_S_SUCCESS) { printf("Error: SCardConnect failed with error 0x%08X\n", err); } else { break; } } if (err != SCARD_S_SUCCESS) { goto cleanup; } // Disconnect the reader. printf("Disconnecting the reader...\n"); err = SCardDisconnect(hCard, SCARD_LEAVE_CARD); if (err != SCARD_S_SUCCESS) { printf("Error: SCardConnect failed with error 0x%08X\n", err); goto cleanup; } cleanup: // Free reader names. if (readerNames != NULL) { FreeReaderNames(readerNames, numReaders); readerNames = NULL; } if (established) { // Release the context. printf("Releasing the context...\n"); err = SCardReleaseContext(hContext); if (err != SCARD_S_SUCCESS) { printf("Error: SCardReleaseContext failed with error 0x%08X\n", err); } established = FALSE; } return 0; } /** * Gets reader names. * @param[in] hContext the context * @param[out] pReaderNames the pointer to the array of reader names * @param[out] pNumReaders the pointer to the number of readers * @return the error code */ LONG GetReaderNames(SCARDCONTEXT hContext, LPSTR **pReaderNames, LPDWORD pNumReaders) { LONG err = SCARD_S_SUCCESS; LPSTR buffer = NULL; DWORD bufferLength = 0; LPSTR pReader = NULL; DWORD numReaders = 0; // Get the buffer length. SCardListReaders(hContext, NULL, NULL, &bufferLength); // Allocate the buffer. buffer = malloc(bufferLength); if (buffer == NULL) { err = SCARD_E_NO_MEMORY; goto cleanup; } // List readers. err = SCardListReaders(hContext, NULL, buffer, &bufferLength); if (err != SCARD_S_SUCCESS) { goto cleanup; } // Count the number of readers. pReader = buffer; while (*pReader != '\0') { pReader = pReader + strlen(pReader) + 1; numReaders++; } // Allocate the array. if ((numReaders > 0) && (pReaderNames != NULL)) { int i = 0; *pReaderNames = (LPSTR *) calloc(numReaders, sizeof(LPSTR *)); if (*pReaderNames == NULL) { err = SCARD_E_NO_MEMORY; goto cleanup; } pReader = buffer; while (*pReader != '\0') { (*pReaderNames)[i] = malloc(strlen(pReader) + 1); if ((*pReaderNames)[i] == NULL) { err = SCARD_E_NO_MEMORY; goto cleanup; } strcpy((*pReaderNames)[i], pReader); i++; pReader = pReader + strlen(pReader) + 1; } } cleanup: if (err != SCARD_S_SUCCESS) { // Free reader names. if ((pReaderNames != NULL) && (*pReaderNames != NULL)) { FreeReaderNames(*pReaderNames, numReaders); *pReaderNames = NULL; } } // Free the buffer. if (buffer != NULL) { free(buffer); buffer = NULL; } // Return the number of readers. if (pNumReaders != NULL) { *pNumReaders = numReaders; } return err; } /** * Frees reader names. * @param[in] readerNames the array of reader names * @param[in] numReaders the number of readers */ void FreeReaderNames(LPSTR *readerNames, DWORD numReaders) { if (readerNames != NULL) { int i = 0; for (i = 0; i < numReaders; i++) { if (readerNames[i] != NULL) { free(readerNames[i]); readerNames[i] = NULL; } } free(readerNames); readerNames = NULL; } }