Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1068515
  • 博文数量: 282
  • 博客积分: 10865
  • 博客等级: 上将
  • 技术积分: 2480
  • 用 户 组: 普通用户
  • 注册时间: 2006-05-12 12:35
文章存档

2017年(1)

2016年(3)

2015年(10)

2014年(12)

2013年(5)

2012年(10)

2011年(29)

2010年(3)

2008年(13)

2007年(92)

2006年(104)

我的朋友

分类: Windows平台

2015-08-24 23:41:48

转载:http://blog.csdn.net/yxstars/article/details/41522467

 PC/SC规范是一个基于WINDOWS平台的一个标准用户接口(API),提供了一个从个人电脑(Personal Computer)到智能卡(SmartCard)的整合环境,PC/SC规范建立在工业标准-ISO7816和EMV标准的基础上,但它对底层的设备接口和独立于设备的应用API接口(例如用来允许多个应用共享使用系统同一张智能卡的资源管理器)做了更详尽的补充。PC/SC体系由三个主要部件组成,分别规定的操作系统厂商、读写器(IFD)厂商、智能卡(ICC)厂商的职责。PC/SC的API函数由操作系统提供,在微软公司提供的MSDN有相关帮助(路径\\MSDN\Platform SDK\Security\Smart Card),函数声明在Winscard.h中。
   由于经常使用,所以我将PC/SC几个常用函数进行封装,方便调用。

1.载入头文件



  1. #include <WinSCard.h>  
  2. #pragma comment(lib,"WinSCard.lib")  
  3.   
  4. #define NUMBER_OF_READERS   4  
  5. #define INDEX_LENGTH        2  
  6. #define KEY_LENGTH          32  
  7. #define NAME_LENGTH         100  
  8. #define MAX_INPUT           1024  
  9. #define MAX_OUTPUT          4000  
  10. #define MAX_RESPONSE        2000  


2 建立资源管理器的上下文,并获得读卡器列表



  1. /************************************************************************/  
  2. /*  
  3.    与读卡器建立连接 
  4.    返回:连接失败0,否则返回读卡器列表数目 
  5. */  
  6. /************************************************************************/  
  7.   
  8. extern "C" __declspec(dllexportint CardReaderInit(  
  9.     char* messageBuffer,                   //_out_ 返回错误信息  
  10.     char(*ReaderName)[NAME_LENGTH],        //_out_ 返回读卡器列表信息  
  11.     SCARDCONTEXT* ContextHandle            //_out_ 返回读卡器句柄  
  12.     )  
  13. {  
  14.     // extra initialization   
  15.     //char  ReaderName[NUMBER_OF_READERS][NAME_LENGTH];  
  16.     memset(messageBuffer, 0, NAME_LENGTH);  
  17.     memset(ReaderName[0], 0, NAME_LENGTH);  
  18.     memset(ReaderName[1], 0, NAME_LENGTH);  
  19.     memset(ReaderName[2], 0, NAME_LENGTH);  
  20.     memset(ReaderName[3], 0, NAME_LENGTH);  
  21.   
  22.     PBYTE pOutBuffer = (PBYTE)malloc(MAX_OUTPUT);    
  23.     int OutBufferLine = 0;  
  24.   
  25.     PBYTE pResponseBuffer = (PBYTE)malloc(MAX_RESPONSE);  
  26.   
  27.     memset(pResponseBuffer, 0x00, MAX_RESPONSE);  
  28.   
  29.     //  
  30.     //  Open a context which communication to the Resource Manager  
  31.     //  
  32.     long ret = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, ContextHandle);  
  33.   
  34.     if (ret != SCARD_S_SUCCESS) {  
  35.         sprintf_s(messageBuffer, NAME_LENGTH, "Function SCardEstablishContext returned 0x%X error code.", ret);  
  36.         return false;  
  37.     }  
  38.   
  39.     int ReaderCount = 0;  
  40.     unsigned long ResponseLength = MAX_RESPONSE;  
  41.   
  42.     ret = SCardListReaders(*ContextHandle, 0, (char *)pResponseBuffer, &ResponseLength);  
  43.   
  44.     if (ret != SCARD_S_SUCCESS) {  
  45.         sprintf_s(messageBuffer, NAME_LENGTH, "Function SCardListReaders returned 0x%X error code.", ret);  
  46.         return false;  
  47.     }  
  48.     else {  
  49.         unsigned int        StringLen = 0;  
  50.         SCARDHANDLE CardHandle = NULL;  
  51.         while (ResponseLength > StringLen + 1) {  
  52.             strcpy(ReaderName[ReaderCount], (LPCTSTR)pResponseBuffer + StringLen);  
  53.             DWORD   ActiveProtocol = 0;  
  54.             ret = SCardConnect(*ContextHandle, ReaderName[ReaderCount], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &CardHandle, &ActiveProtocol);  
  55.             if (ret != SCARD_E_UNKNOWN_READER)  
  56.                 ReaderCount++;  
  57.             if (ret == SCARD_S_SUCCESS)  
  58.                 SCardDisconnect(CardHandle, SCARD_EJECT_CARD);  
  59.             StringLen += strlen((LPCTSTR)pResponseBuffer + StringLen + 1);  
  60.             StringLen += 2;  
  61.         }  
  62.     }  
  63.   
  64.     if (ReaderCount == 0) {  
  65.         sprintf_s(messageBuffer, NAME_LENGTH, "No driver is available for use with the resource manager!");  
  66.         return false;  
  67.     }  
  68.   
  69.     return ReaderCount;  
  70. }  




3 读卡器与智能卡连接


  1. /************************************************************************/  
  2. /* 
  3.     与卡片建立连接 
  4.     返回:连接失败0,否则返回1 
  5. */  
  6. /************************************************************************/  
  7. extern "C" __declspec(dllexportbool CardConnect(  
  8.     SCARDCONTEXT ContextHandle,           //_in_  传入读卡器句柄               
  9.     char(*ReaderName)[NAME_LENGTH],       //_in_  传入读卡器列表信息(二维数组)  
  10.     int actName,                          //_in_  传入选择的列表序号  
  11.     SCARDHANDLE *CardHandle,              //_out_ 返回卡片句柄  
  12.     long* ProtocolType,                   //_out_ 返回卡片协议  
  13.     char* messageBuffer                   //_out_ 返回错误信息  
  14.     )  
  15. {      // <span style="font-family: 'Courier New';font-size:14px;">ScardTransmit  </span><a target=_blank target="_blank" href="'Courier New';font-size:14px;"> style="margin:0px;padding:0px;border:none;background-color:inherit;">  
  16.     DWORD   ActiveProtocol = 0;  
  17.     *ProtocolType = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;  
  18.     long ret = SCardConnect(ContextHandle, ReaderName[actName], SCARD_SHARE_EXCLUSIVE, *ProtocolType, CardHandle, &ActiveProtocol);  
  19.   
  20.     memset(messageBuffer, 0x00, sizeof(messageBuffer) / sizeof(char));  
  21.     if (ret != SCARD_S_SUCCESS){  
  22.         GetErrorCode(ret, messageBuffer);  
  23.         return false;  
  24.     }  
  25.   
  26.     *ProtocolType = ActiveProtocol;  
  27.   
  28.     switch (*ProtocolType) {  
  29.     case SCARD_PROTOCOL_T0:  
  30.         sprintf_s(messageBuffer, NAME_LENGTH, "Function SCardConnect ok\nProtocoltype = T0");  
  31.         break;  
  32.     case SCARD_PROTOCOL_T1:  
  33.         sprintf_s(messageBuffer, NAME_LENGTH, "Function SCardConnect ok\nProtocoltype = T1");  
  34.         break;  
  35.     default:  
  36.         sprintf_s(messageBuffer, NAME_LENGTH, "Function SCardConnect ok\n%.8x", ActiveProtocol);  
  37.         break;  
  38.     }  
  39.   
  40.     return true;  
  41. }  


4 断开与读卡器的连接

  1. /************************************************************************/  
  2. /* 
  3.     与卡片断开连接 
  4.     返回:连接成功0.否则错误(v=vs.85).aspx 
  5. */  
  6. /************************************************************************/  
  7. extern "C" __declspec(dllexportlong CardDisconnect(  
  8.     SCARDHANDLE CardHandle               //_in_ 传入卡片句柄  
  9.     )  
  10. {  
  11.     return SCardDisconnect(CardHandle, SCARD_EJECT_CARD);  
  12. }  

5 释放资源管理上下文

  1. /************************************************************************/  
  2. /* 
  3.     与读卡器断开连接 
  4.     返回:连接成功0.否则错误(v=vs.85).aspx 
  5. */  
  6. /************************************************************************/  
  7. extern "C" __declspec(dllexportlong CardReaderDisconnect(  
  8.     SCARDCONTEXT ContextHandle           //_in_ 传入读卡器句柄  
  9.     )  
  10. {  
  11.     return SCardReleaseContext(ContextHandle);  
  12. }  

6 向智能卡发送指令

  1. int Transmit(byte* cmd,  
  2.     long ProtocolType,   
  3.     SCARDHANDLE CardHandle  
  4.     )  
  5. int Transmit(byte* cmd, long ProtocolType, SCARDHANDLE CardHandle)  
  6. {  
  7.     char    mhstr[MAX_INPUT];  
  8.     char    buf[MAX_INPUT / 2];  
  9.     PBYTE   pInBuffer;  
  10.     PBYTE   pResponseBuffer;  
  11.     memset(mhstr, 0, MAX_INPUT);  
  12.   
  13.     sprintf_s(mhstr, MAX_INPUT, "%s", cmd);  
  14.     int bufferLen = AToHex((char *)&mhstr, (BYTE *)&buf);  
  15.     if (!bufferLen)  {  
  16.         return false;  
  17.     }  
  18.   
  19.     SCARD_IO_REQUEST IO_Request;  
  20.     IO_Request.dwProtocol = ProtocolType;  
  21.     IO_Request.cbPciLength = (DWORDsizeof(SCARD_IO_REQUEST);  
  22.   
  23.     pInBuffer = (PBYTE)malloc(MAX_INPUT);  
  24.     memcpy(pInBuffer, buf, bufferLen);  
  25.     pResponseBuffer = (PBYTE)malloc(MAX_INPUT);  
  26.     memset(pResponseBuffer, 0x00, bufferLen);  
  27.   
  28.     unsigned long ResponseLength = MAX_RESPONSE;  
  29.       
  30.     long ret = SCardTransmit(CardHandle, &IO_Request, pInBuffer, bufferLen, 0, pResponseBuffer, &ResponseLength);  
  31.   
  32.     if (ret != SCARD_S_SUCCESS){  
  33.         GetErrorCode(ret, (char*)cmd);  
  34.         return false;  
  35.     }  
  36.   
  37.     DataX::AscToHex(pResponseBuffer, ResponseLength, cmd);  
  38.     cmd[ResponseLength * 2] = 0x00;  
  39.     return ResponseLength * 2;  
  40. }  


7 获取错误信息


  1. void GetErrorCode(long ret, char* messageBuffer)  
  2. {  
  3.     switch (ret) {  
  4.     case SCARD_E_CANCELLED:  
  5.         sprintf_s(messageBuffer, NAME_LENGTH, "The action was cancelled by an SCardCancel request.");  
  6.         break;  
  7.     case SCARD_E_CANT_DISPOSE:  
  8.         sprintf_s(messageBuffer, NAME_LENGTH, "The system could not dispose of the media in the requested manner.");  
  9.         break;  
  10.     case SCARD_E_CARD_UNSUPPORTED:  
  11.         sprintf_s(messageBuffer, NAME_LENGTH, "The smart card does not meet minimal requirements for support.");  
  12.         break;  
  13.     case SCARD_E_DUPLICATE_READER:  
  14.         sprintf_s(messageBuffer, NAME_LENGTH, "The reader driver didn't produce a unique reader name.");  
  15.         break;  
  16.     case SCARD_E_INSUFFICIENT_BUFFER:  
  17.         sprintf_s(messageBuffer, NAME_LENGTH, "The data buffer to receive returned data is too small for the returned data.");  
  18.         break;  
  19.     case SCARD_E_INVALID_ATR:  
  20.         sprintf_s(messageBuffer, NAME_LENGTH, "An ATR obtained from the registry is not a valid ATR string.");  
  21.         break;  
  22.     case SCARD_E_INVALID_HANDLE:  
  23.         sprintf_s(messageBuffer, NAME_LENGTH, "The supplied handle was invalid.");  
  24.         break;  
  25.     case SCARD_E_INVALID_PARAMETER:  
  26.         sprintf_s(messageBuffer, NAME_LENGTH, "One or more of the supplied parameters could not be properly interpreted.");  
  27.         break;  
  28.     case SCARD_E_INVALID_TARGET:  
  29.         sprintf_s(messageBuffer, NAME_LENGTH, "Registry startup information is missing or invalid.");  
  30.         break;  
  31.     case SCARD_E_INVALID_VALUE:  
  32.         sprintf_s(messageBuffer, NAME_LENGTH, "One or more of the supplied parameters?values could not be properly interpreted.");  
  33.         break;  
  34.     case SCARD_E_NOT_READY:  
  35.         sprintf_s(messageBuffer, NAME_LENGTH, "The reader or card is not ready to accept commands.");  
  36.         break;  
  37.     case SCARD_E_NOT_TRANSACTED:  
  38.         sprintf_s(messageBuffer, NAME_LENGTH, "An attempt was made to end a non-existent transaction.");  
  39.         break;  
  40.     case SCARD_E_NO_MEMORY:  
  41.         sprintf_s(messageBuffer, NAME_LENGTH, "Not enough memory available to complete this command.");  
  42.         break;  
  43.     case SCARD_E_NO_SERVICE:  
  44.         sprintf_s(messageBuffer, NAME_LENGTH, "The Smart card resource manager is not running.");  
  45.         break;  
  46.     case SCARD_E_NO_SMARTCARD:  
  47.         sprintf_s(messageBuffer, NAME_LENGTH, "The operation requires a smart card but no smart card is currently in the device.");  
  48.         break;  
  49.     case SCARD_E_PCI_TOO_SMALL:  
  50.         sprintf_s(messageBuffer, NAME_LENGTH, "The PCI Receive buffer was too small.");  
  51.         break;  
  52.     case SCARD_E_PROTO_MISMATCH:  
  53.         sprintf_s(messageBuffer, NAME_LENGTH, "The requested protocols are incompatible with the protocol currently in use with the card.");  
  54.         break;  
  55.     case SCARD_E_READER_UNAVAILABLE:  
  56.         sprintf_s(messageBuffer, NAME_LENGTH, "The specified reader is not currently available for use.");  
  57.         break;  
  58.     case SCARD_E_READER_UNSUPPORTED:  
  59.         sprintf_s(messageBuffer, NAME_LENGTH, "The reader driver does not meet minimal requirements for support.");  
  60.         break;  
  61.     case SCARD_E_SERVICE_STOPPED:  
  62.         sprintf_s(messageBuffer, NAME_LENGTH, "The Smart card resource manager has shut down.");  
  63.         break;  
  64.     case SCARD_E_SHARING_VIOLATION:  
  65.         sprintf_s(messageBuffer, NAME_LENGTH, "The card cannot be accessed because of other connections outstanding.");  
  66.         break;  
  67.     case SCARD_E_SYSTEM_CANCELLED:  
  68.         sprintf_s(messageBuffer, NAME_LENGTH, "The action was cancelled by the system presumably to log off or shut down.");  
  69.         break;  
  70.     case SCARD_E_TIMEOUT:  
  71.         sprintf_s(messageBuffer, NAME_LENGTH, "The user-specified timeout value has expired.");  
  72.         break;  
  73.     case SCARD_E_UNKNOWN_CARD:  
  74.         sprintf_s(messageBuffer, NAME_LENGTH, "The specified card name is not recognized.");  
  75.         break;  
  76.     case SCARD_E_UNKNOWN_READER:  
  77.         sprintf_s(messageBuffer, NAME_LENGTH, "The specified reader name is not recognized.");  
  78.         break;  
  79.     case SCARD_F_COMM_ERROR:  
  80.         sprintf_s(messageBuffer, NAME_LENGTH, "An internal communications error has been detected.");  
  81.         break;  
  82.     case SCARD_F_INTERNAL_ERROR:  
  83.         sprintf_s(messageBuffer, NAME_LENGTH, "An internal consistency check failed.");  
  84.         break;  
  85.     case SCARD_F_UNKNOWN_ERROR:  
  86.         sprintf_s(messageBuffer, NAME_LENGTH, "An internal error has been detected but the source is unknown.");  
  87.         break;  
  88.     case SCARD_F_WAITED_TOO_LONG:  
  89.         sprintf_s(messageBuffer, NAME_LENGTH, "An internal consistency timer has expired.");  
  90.         break;  
  91.     case SCARD_S_SUCCESS:  
  92.         sprintf_s(messageBuffer, NAME_LENGTH, "OK");  
  93.         break;  
  94.     case SCARD_W_REMOVED_CARD:  
  95.         sprintf_s(messageBuffer, NAME_LENGTH, "The card has been removed so that further communication is not possible.");  
  96.         break;  
  97.     case SCARD_W_RESET_CARD:  
  98.         sprintf_s(messageBuffer, NAME_LENGTH, "The card has been reset so any shared state information is invalid.");  
  99.         break;  
  100.     case SCARD_W_UNPOWERED_CARD:  
  101.         sprintf_s(messageBuffer, NAME_LENGTH, "Power has been removed from the card so that further communication is not possible.");  
  102.         break;  
  103.     case SCARD_W_UNRESPONSIVE_CARD:  
  104.         sprintf_s(messageBuffer, NAME_LENGTH, "The card is not responding to a reset.");  
  105.         break;  
  106.     case SCARD_W_UNSUPPORTED_CARD:  
  107.         sprintf_s(messageBuffer, NAME_LENGTH, "The reader cannot communicate with the card due to ATR configuration conflicts.");  
  108.         break;  
  109.     default:  
  110.         sprintf_s(messageBuffer, NAME_LENGTH, "Function returned unknown error code: #%ld", ret);  
  111.         break;  
  112.     }  
  113. }  


8 复位卡片


  1. bool CpuReset(SCARDHANDLE CardHandle, byte* atr)  
  2. {  
  3.     CHAR            szReader[200];  
  4.     DWORD           cch = 200;  
  5.     BYTE            bAttr[32];  
  6.     DWORD           cByte = 32;  
  7.     DWORD           dwState, dwProtocol;  
  8.     LONG            lReturn;  
  9.     string          AtrValue;  
  10.   
  11.     memset(bAttr, 0, 32);  
  12.     memset(szReader, 0, 200);  
  13.   
  14.     // Determine the status.  
  15.     // hCardHandle was set by an earlier call to SCardConnect.  
  16.     lReturn = SCardStatus(CardHandle,  
  17.         szReader,  
  18.         &cch,  
  19.         &dwState,  
  20.         &dwProtocol,  
  21.         (LPBYTE)&bAttr,  
  22.         &cByte);  
  23.   
  24.     if (SCARD_S_SUCCESS != lReturn)  
  25.         return FALSE;  
  26.       
  27.     DataX::AscToHex(bAttr, cByte, atr);  
  28.     return TRUE;  
  29. }  
阅读(1097) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~