转载: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.载入头文件
-
#include <WinSCard.h>
-
#pragma comment(lib,"WinSCard.lib")
-
-
#define NUMBER_OF_READERS 4
-
#define INDEX_LENGTH 2
-
#define KEY_LENGTH 32
-
#define NAME_LENGTH 100
-
#define MAX_INPUT 1024
-
#define MAX_OUTPUT 4000
-
#define MAX_RESPONSE 2000
2 建立资源管理器的上下文,并获得读卡器列表
-
-
-
-
-
-
-
-
extern "C" __declspec(dllexport) int CardReaderInit(
-
char* messageBuffer,
-
char(*ReaderName)[NAME_LENGTH],
-
SCARDCONTEXT* ContextHandle
-
)
-
{
-
-
-
memset(messageBuffer, 0, NAME_LENGTH);
-
memset(ReaderName[0], 0, NAME_LENGTH);
-
memset(ReaderName[1], 0, NAME_LENGTH);
-
memset(ReaderName[2], 0, NAME_LENGTH);
-
memset(ReaderName[3], 0, NAME_LENGTH);
-
-
PBYTE pOutBuffer = (PBYTE)malloc(MAX_OUTPUT);
-
int OutBufferLine = 0;
-
-
PBYTE pResponseBuffer = (PBYTE)malloc(MAX_RESPONSE);
-
-
memset(pResponseBuffer, 0x00, MAX_RESPONSE);
-
-
-
-
-
long ret = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, ContextHandle);
-
-
if (ret != SCARD_S_SUCCESS) {
-
sprintf_s(messageBuffer, NAME_LENGTH, "Function SCardEstablishContext returned 0x%X error code.", ret);
-
return false;
-
}
-
-
int ReaderCount = 0;
-
unsigned long ResponseLength = MAX_RESPONSE;
-
-
ret = SCardListReaders(*ContextHandle, 0, (char *)pResponseBuffer, &ResponseLength);
-
-
if (ret != SCARD_S_SUCCESS) {
-
sprintf_s(messageBuffer, NAME_LENGTH, "Function SCardListReaders returned 0x%X error code.", ret);
-
return false;
-
}
-
else {
-
unsigned int StringLen = 0;
-
SCARDHANDLE CardHandle = NULL;
-
while (ResponseLength > StringLen + 1) {
-
strcpy(ReaderName[ReaderCount], (LPCTSTR)pResponseBuffer + StringLen);
-
DWORD ActiveProtocol = 0;
-
ret = SCardConnect(*ContextHandle, ReaderName[ReaderCount], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &CardHandle, &ActiveProtocol);
-
if (ret != SCARD_E_UNKNOWN_READER)
-
ReaderCount++;
-
if (ret == SCARD_S_SUCCESS)
-
SCardDisconnect(CardHandle, SCARD_EJECT_CARD);
-
StringLen += strlen((LPCTSTR)pResponseBuffer + StringLen + 1);
-
StringLen += 2;
-
}
-
}
-
-
if (ReaderCount == 0) {
-
sprintf_s(messageBuffer, NAME_LENGTH, "No driver is available for use with the resource manager!");
-
return false;
-
}
-
-
return ReaderCount;
-
}
3 读卡器与智能卡连接
-
-
-
-
-
-
-
extern "C" __declspec(dllexport) bool CardConnect(
-
SCARDCONTEXT ContextHandle,
-
char(*ReaderName)[NAME_LENGTH],
-
int actName,
-
SCARDHANDLE *CardHandle,
-
long* ProtocolType,
-
char* messageBuffer
-
)
-
{
-
DWORD ActiveProtocol = 0;
-
*ProtocolType = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
-
long ret = SCardConnect(ContextHandle, ReaderName[actName], SCARD_SHARE_EXCLUSIVE, *ProtocolType, CardHandle, &ActiveProtocol);
-
-
memset(messageBuffer, 0x00, sizeof(messageBuffer) / sizeof(char));
-
if (ret != SCARD_S_SUCCESS){
-
GetErrorCode(ret, messageBuffer);
-
return false;
-
}
-
-
*ProtocolType = ActiveProtocol;
-
-
switch (*ProtocolType) {
-
case SCARD_PROTOCOL_T0:
-
sprintf_s(messageBuffer, NAME_LENGTH, "Function SCardConnect ok\nProtocoltype = T0");
-
break;
-
case SCARD_PROTOCOL_T1:
-
sprintf_s(messageBuffer, NAME_LENGTH, "Function SCardConnect ok\nProtocoltype = T1");
-
break;
-
default:
-
sprintf_s(messageBuffer, NAME_LENGTH, "Function SCardConnect ok\n%.8x", ActiveProtocol);
-
break;
-
}
-
-
return true;
-
}
4 断开与读卡器的连接
-
-
-
-
-
-
-
extern "C" __declspec(dllexport) long CardDisconnect(
-
SCARDHANDLE CardHandle
-
)
-
{
-
return SCardDisconnect(CardHandle, SCARD_EJECT_CARD);
-
}
5 释放资源管理上下文
-
-
-
-
-
-
-
extern "C" __declspec(dllexport) long CardReaderDisconnect(
-
SCARDCONTEXT ContextHandle
-
)
-
{
-
return SCardReleaseContext(ContextHandle);
-
}
6 向智能卡发送指令
-
int Transmit(byte* cmd,
-
long ProtocolType,
-
SCARDHANDLE CardHandle
-
)
-
int Transmit(byte* cmd, long ProtocolType, SCARDHANDLE CardHandle)
-
{
-
char mhstr[MAX_INPUT];
-
char buf[MAX_INPUT / 2];
-
PBYTE pInBuffer;
-
PBYTE pResponseBuffer;
-
memset(mhstr, 0, MAX_INPUT);
-
-
sprintf_s(mhstr, MAX_INPUT, "%s", cmd);
-
int bufferLen = AToHex((char *)&mhstr, (BYTE *)&buf);
-
if (!bufferLen) {
-
return false;
-
}
-
-
SCARD_IO_REQUEST IO_Request;
-
IO_Request.dwProtocol = ProtocolType;
-
IO_Request.cbPciLength = (DWORD) sizeof(SCARD_IO_REQUEST);
-
-
pInBuffer = (PBYTE)malloc(MAX_INPUT);
-
memcpy(pInBuffer, buf, bufferLen);
-
pResponseBuffer = (PBYTE)malloc(MAX_INPUT);
-
memset(pResponseBuffer, 0x00, bufferLen);
-
-
unsigned long ResponseLength = MAX_RESPONSE;
-
-
long ret = SCardTransmit(CardHandle, &IO_Request, pInBuffer, bufferLen, 0, pResponseBuffer, &ResponseLength);
-
-
if (ret != SCARD_S_SUCCESS){
-
GetErrorCode(ret, (char*)cmd);
-
return false;
-
}
-
-
DataX::AscToHex(pResponseBuffer, ResponseLength, cmd);
-
cmd[ResponseLength * 2] = 0x00;
-
return ResponseLength * 2;
-
}
7 获取错误信息
-
void GetErrorCode(long ret, char* messageBuffer)
-
{
-
switch (ret) {
-
case SCARD_E_CANCELLED:
-
sprintf_s(messageBuffer, NAME_LENGTH, "The action was cancelled by an SCardCancel request.");
-
break;
-
case SCARD_E_CANT_DISPOSE:
-
sprintf_s(messageBuffer, NAME_LENGTH, "The system could not dispose of the media in the requested manner.");
-
break;
-
case SCARD_E_CARD_UNSUPPORTED:
-
sprintf_s(messageBuffer, NAME_LENGTH, "The smart card does not meet minimal requirements for support.");
-
break;
-
case SCARD_E_DUPLICATE_READER:
-
sprintf_s(messageBuffer, NAME_LENGTH, "The reader driver didn't produce a unique reader name.");
-
break;
-
case SCARD_E_INSUFFICIENT_BUFFER:
-
sprintf_s(messageBuffer, NAME_LENGTH, "The data buffer to receive returned data is too small for the returned data.");
-
break;
-
case SCARD_E_INVALID_ATR:
-
sprintf_s(messageBuffer, NAME_LENGTH, "An ATR obtained from the registry is not a valid ATR string.");
-
break;
-
case SCARD_E_INVALID_HANDLE:
-
sprintf_s(messageBuffer, NAME_LENGTH, "The supplied handle was invalid.");
-
break;
-
case SCARD_E_INVALID_PARAMETER:
-
sprintf_s(messageBuffer, NAME_LENGTH, "One or more of the supplied parameters could not be properly interpreted.");
-
break;
-
case SCARD_E_INVALID_TARGET:
-
sprintf_s(messageBuffer, NAME_LENGTH, "Registry startup information is missing or invalid.");
-
break;
-
case SCARD_E_INVALID_VALUE:
-
sprintf_s(messageBuffer, NAME_LENGTH, "One or more of the supplied parameters?values could not be properly interpreted.");
-
break;
-
case SCARD_E_NOT_READY:
-
sprintf_s(messageBuffer, NAME_LENGTH, "The reader or card is not ready to accept commands.");
-
break;
-
case SCARD_E_NOT_TRANSACTED:
-
sprintf_s(messageBuffer, NAME_LENGTH, "An attempt was made to end a non-existent transaction.");
-
break;
-
case SCARD_E_NO_MEMORY:
-
sprintf_s(messageBuffer, NAME_LENGTH, "Not enough memory available to complete this command.");
-
break;
-
case SCARD_E_NO_SERVICE:
-
sprintf_s(messageBuffer, NAME_LENGTH, "The Smart card resource manager is not running.");
-
break;
-
case SCARD_E_NO_SMARTCARD:
-
sprintf_s(messageBuffer, NAME_LENGTH, "The operation requires a smart card but no smart card is currently in the device.");
-
break;
-
case SCARD_E_PCI_TOO_SMALL:
-
sprintf_s(messageBuffer, NAME_LENGTH, "The PCI Receive buffer was too small.");
-
break;
-
case SCARD_E_PROTO_MISMATCH:
-
sprintf_s(messageBuffer, NAME_LENGTH, "The requested protocols are incompatible with the protocol currently in use with the card.");
-
break;
-
case SCARD_E_READER_UNAVAILABLE:
-
sprintf_s(messageBuffer, NAME_LENGTH, "The specified reader is not currently available for use.");
-
break;
-
case SCARD_E_READER_UNSUPPORTED:
-
sprintf_s(messageBuffer, NAME_LENGTH, "The reader driver does not meet minimal requirements for support.");
-
break;
-
case SCARD_E_SERVICE_STOPPED:
-
sprintf_s(messageBuffer, NAME_LENGTH, "The Smart card resource manager has shut down.");
-
break;
-
case SCARD_E_SHARING_VIOLATION:
-
sprintf_s(messageBuffer, NAME_LENGTH, "The card cannot be accessed because of other connections outstanding.");
-
break;
-
case SCARD_E_SYSTEM_CANCELLED:
-
sprintf_s(messageBuffer, NAME_LENGTH, "The action was cancelled by the system presumably to log off or shut down.");
-
break;
-
case SCARD_E_TIMEOUT:
-
sprintf_s(messageBuffer, NAME_LENGTH, "The user-specified timeout value has expired.");
-
break;
-
case SCARD_E_UNKNOWN_CARD:
-
sprintf_s(messageBuffer, NAME_LENGTH, "The specified card name is not recognized.");
-
break;
-
case SCARD_E_UNKNOWN_READER:
-
sprintf_s(messageBuffer, NAME_LENGTH, "The specified reader name is not recognized.");
-
break;
-
case SCARD_F_COMM_ERROR:
-
sprintf_s(messageBuffer, NAME_LENGTH, "An internal communications error has been detected.");
-
break;
-
case SCARD_F_INTERNAL_ERROR:
-
sprintf_s(messageBuffer, NAME_LENGTH, "An internal consistency check failed.");
-
break;
-
case SCARD_F_UNKNOWN_ERROR:
-
sprintf_s(messageBuffer, NAME_LENGTH, "An internal error has been detected but the source is unknown.");
-
break;
-
case SCARD_F_WAITED_TOO_LONG:
-
sprintf_s(messageBuffer, NAME_LENGTH, "An internal consistency timer has expired.");
-
break;
-
case SCARD_S_SUCCESS:
-
sprintf_s(messageBuffer, NAME_LENGTH, "OK");
-
break;
-
case SCARD_W_REMOVED_CARD:
-
sprintf_s(messageBuffer, NAME_LENGTH, "The card has been removed so that further communication is not possible.");
-
break;
-
case SCARD_W_RESET_CARD:
-
sprintf_s(messageBuffer, NAME_LENGTH, "The card has been reset so any shared state information is invalid.");
-
break;
-
case SCARD_W_UNPOWERED_CARD:
-
sprintf_s(messageBuffer, NAME_LENGTH, "Power has been removed from the card so that further communication is not possible.");
-
break;
-
case SCARD_W_UNRESPONSIVE_CARD:
-
sprintf_s(messageBuffer, NAME_LENGTH, "The card is not responding to a reset.");
-
break;
-
case SCARD_W_UNSUPPORTED_CARD:
-
sprintf_s(messageBuffer, NAME_LENGTH, "The reader cannot communicate with the card due to ATR configuration conflicts.");
-
break;
-
default:
-
sprintf_s(messageBuffer, NAME_LENGTH, "Function returned unknown error code: #%ld", ret);
-
break;
-
}
-
}
8 复位卡片
-
bool CpuReset(SCARDHANDLE CardHandle, byte* atr)
-
{
-
CHAR szReader[200];
-
DWORD cch = 200;
-
BYTE bAttr[32];
-
DWORD cByte = 32;
-
DWORD dwState, dwProtocol;
-
LONG lReturn;
-
string AtrValue;
-
-
memset(bAttr, 0, 32);
-
memset(szReader, 0, 200);
-
-
-
-
lReturn = SCardStatus(CardHandle,
-
szReader,
-
&cch,
-
&dwState,
-
&dwProtocol,
-
(LPBYTE)&bAttr,
-
&cByte);
-
-
if (SCARD_S_SUCCESS != lReturn)
-
return FALSE;
-
-
DataX::AscToHex(bAttr, cByte, atr);
-
return TRUE;
-
}
-
阅读(1170) | 评论(0) | 转发(0) |