#include "StdAfx.h"
#include "PCSC.h"
CPCSC::CPCSC()
{
m_hContext = 0;
m_hCard = 0;
}
CPCSC::~CPCSC()
{
DisConnectCard();
}
bool CPCSC::ConnectCard(char* sReader)
{
DisConnectCard();
LONG res;
//建立设备上下文
res = ::SCardEstablishContext(SCARD_SCOPE_USER,NULL,NULL,&m_hContext);
if(res != SCARD_S_SUCCESS)
{
m_hContext = 0;
return false;
}
LPTSTR pmszReaders = NULL;
LPTSTR pReader = NULL;
DWORD cch = SCARD_AUTOALLOCATE;
DWORD dwAP;
bool bConnected = false;
//遍历当前所有读卡器,并试图建立连接
res = ::SCardListReaders(m_hContext,sReader,(LPTSTR)&pmszReaders,&cch);
if(res == SCARD_S_SUCCESS)
{
pReader = pmszReaders;
while ( '\0' != *pReader )
{
//得到一个读卡器名字的串
res = ::SCardConnect(m_hContext,pReader,SCARD_SHARE_SHARED,SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1,&m_hCard,&dwAP);
if(SCARD_S_SUCCESS == res)
{
bConnected = true;
break;
}
else
{
pReader = pReader + strlen(pReader) + 1;
}
}
//释放名字串空间
::SCardFreeMemory(m_hContext,pmszReaders);
}
if(!bConnected)
{
//连接读卡器失败,释放设备上下文
::SCardReleaseContext(m_hContext);
m_hContext = 0;
m_hCard = 0;
}
return bConnected;
}
void CPCSC::DisConnectCard()
{
if(m_hCard)
{
::SCardDisconnect(m_hCard,SCARD_EJECT_CARD);
m_hCard = 0;
}
if(m_hContext)
{
::SCardReleaseContext(m_hContext);
m_hContext = 0;
}
}
bool CPCSC::SELECT(IN WORD wFileID, OUT BYTE& byResLen)
{
//组织Select命令的APDU指令
BYTE ucCmd[] = {0xa0,0xa4,0x00,0x00,0x02,HIBYTE(wFileID),LOBYTE(wFileID)};
BYTE ucRes[MAX_PATH];
DWORD dwlen = MAX_PATH;
//发送APDU指令
if(!RunAPDU(ucCmd,sizeof(ucCmd),ucRes,dwlen))
{
return false;
}
//校验返回值
//if the selected file is the MF or a DF: fileID,total memory space available,CHV status and other GSM specific data.
//if the selected file is the EF: fileID,file size,access condition,invalidated/not invalidated indicator,structure
//of EF and length of the records in case of linear fixed structure or cyclic structure.
//return value:
//90 00 normal ending
//91 xx normal ending, with extra information
//9f xx length xx of the response data
//9f 00 sim application toolkit is busy,command cant be executed at present
BYTE sw1 = ucRes[dwlen-2];
BYTE sw2 = ucRes[dwlen-1];
if(sw1 != 0x9f)
{
return false;
}
byResLen = sw2;
return true;
}
bool CPCSC::STATUS()
{
//组织Status命令的APDU指令
BYTE ucCmd[] = {0xa0,0xf2,0x00,0x00,0x00};
BYTE ucRes[MAX_PATH];
DWORD dwlen = MAX_PATH;
//发送APDU指令
if(!RunAPDU(ucCmd,sizeof(ucCmd),ucRes,dwlen))
{
return false;
}
//校验返回值
BYTE sw1 = ucRes[dwlen-2];
BYTE sw2 = ucRes[dwlen-1];
if(sw1 != 0x90)
{
return false;
}
return true;
}
bool CPCSC::READ_BINARY(OUT BYTE* ucFile, IN BYTE byLen, IN WORD wOffset)
{
//组织READ BINARY命令的APDU指令
BYTE ucCmd[] = {0xa0,0xb0,HIBYTE(wOffset),LOBYTE(wOffset),byLen};
BYTE ucRes[MAX_PATH];
DWORD dwlen = MAX_PATH;
//发送APDU指令
if(!RunAPDU(ucCmd,sizeof(ucCmd),ucRes,dwlen))
{
return false;
}
//校验返回值
BYTE sw1 = ucRes[dwlen-2];
BYTE sw2 = ucRes[dwlen-1];
if(sw1 != 0x90 || sw2 != 0x00)
{
return false;
}
//给结果赋值
memcpy(ucFile,ucRes,dwlen-2);
return true;
}
bool CPCSC::UPDATE_BINARY(IN BYTE* ucFile, IN BYTE byLen, IN WORD wOffset)
{
//组织UPDATE BINARY命令的APDU指令
BYTE ucCmd[MAX_PATH] = "";
ucCmd[0] = 0xa0;
ucCmd[1] = 0xd6;
ucCmd[2] = HIBYTE(wOffset);
ucCmd[3] = LOBYTE(wOffset);
ucCmd[4] = byLen;
memcpy(&ucCmd[5],ucFile,byLen);
BYTE ucRes[MAX_PATH];
DWORD dwlen = MAX_PATH;
//发送APDU指令
if(!RunAPDU(ucCmd,byLen+5,ucRes,dwlen))
{
return false;
}
//校验返回值
BYTE sw1 = ucRes[dwlen-2];
BYTE sw2 = ucRes[dwlen-1];
if(sw1 != 0x90 || sw2 != 0x00)
{
return false;
}
return true;
}
bool CPCSC::READ_RECORD(IN BYTE byRecNo, OUT BYTE* ucData, IN BYTE byRecLen)
{
//组织READ RECORD命令的APDU指令
BYTE ucCmd[] = {0xa0,0xb2,byRecNo+1,0x04,byRecLen};
BYTE ucRes[MAX_PATH];
DWORD dwlen = MAX_PATH;
//发送APDU指令
if(!RunAPDU(ucCmd,sizeof(ucCmd),ucRes,dwlen))
{
return false;
}
//校验返回值
BYTE sw1 = ucRes[dwlen-2];
BYTE sw2 = ucRes[dwlen-1];
if(sw1 != 0x90 || sw2 != 0x00)
{
return false;
}
//给结果赋值
memcpy(ucData,ucRes,dwlen-2);
return true;
}
bool CPCSC::UPDATE_RECORD(IN BYTE byRecNo,IN BYTE* ucData, IN BYTE byRecLen)
{
//组织UPDATE RECORD命令的APDU指令
BYTE ucCmd[MAX_PATH] = "";
ucCmd[0] = 0xa0;
ucCmd[1] = 0xdc;
ucCmd[2] = byRecNo+1;
ucCmd[3] = 0x04;
ucCmd[4] = byRecLen;
memcpy(&ucCmd[5],ucData,byRecLen);
BYTE ucRes[MAX_PATH];
DWORD dwlen = MAX_PATH;
//发送APDU指令
if(!RunAPDU(ucCmd,byRecLen+5,ucRes,dwlen))
{
return false;
}
//校验返回值
BYTE sw1 = ucRes[dwlen-2];
BYTE sw2 = ucRes[dwlen-1];
if(sw1 != 0x90 || sw2 != 0x00)
{
return false;
}
return true;
}
bool CPCSC::SEEK(IN BYTE* Patten, IN BYTE byPattenLen)
{
//组织SEEK命令的APDU指令
BYTE ucCmd[MAX_PATH] = "";
ucCmd[0] = 0xa0;
ucCmd[1] = 0xa2;
ucCmd[2] = 0x00;
ucCmd[3] = 0x00; //mode 1, from beging
ucCmd[4] = byPattenLen;
memcpy(&ucCmd[5],Patten,byPattenLen);
BYTE ucRes[MAX_PATH];
DWORD dwlen = MAX_PATH;
//发送APDU指令
if(!RunAPDU(ucCmd,byPattenLen+5,ucRes,dwlen))
{
return false;
}
//校验返回值
BYTE sw1 = ucRes[dwlen-2];
BYTE sw2 = ucRes[dwlen-1];
if(sw1 != 0x9f)
{
return false;
}
return true;
}
bool CPCSC::GET_RESPONSE(OUT BYTE* ucResp, IN BYTE byResLen)
{
//组织GET RESPONSE命令的APDU指令
BYTE ucCmd[] = {0xa0,0xc0,0x00,0x00,byResLen};
BYTE ucRes[MAX_PATH];
DWORD dwlen = MAX_PATH;
//发送APDU指令
if(!RunAPDU(ucCmd,sizeof(ucCmd),ucRes,dwlen))
{
return false;
}
//校验返回值
BYTE sw1 = ucRes[dwlen-2];
BYTE sw2 = ucRes[dwlen-1];
if(sw1 != 0x90 || sw2 != 0x00)
{
return false;
}
//给结果赋值
memcpy(ucResp,ucRes,dwlen-2);
return true;
}
bool CPCSC::VERIFY_CHV(IN BYTE byChvNo, IN CHAR* ucChv, IN BYTE byChvLen)
{
//组织VERIFY CHV命令的APDU指令
BYTE ucCmd[MAX_PATH] = "";
memset(ucCmd,0xff,MAX_PATH); //不足的串以0xff填充
ucCmd[0] = 0xa0;
ucCmd[1] = 0x20;
ucCmd[2] = 0x00;
ucCmd[3] = byChvNo;
ucCmd[4] = 0x08;
memcpy(&ucCmd[5],ucChv,byChvLen);
BYTE ucRes[MAX_PATH];
DWORD dwlen = MAX_PATH;
//发送APDU指令
if(!RunAPDU(ucCmd,13,ucRes,dwlen))
{
return false;
}
//校验返回值
BYTE sw1 = ucRes[dwlen-2];
BYTE sw2 = ucRes[dwlen-1];
if(sw1 != 0x90 || sw2 != 0x00)
{
return false;
}
return true;
}
bool CPCSC::UNBLOCK_CHV(IN BYTE byChvNo, IN BYTE* ucPuk, IN BYTE byPukLen, IN BYTE* ucChv, IN BYTE byChvLen)
{
//组织VERIFY CHV命令的APDU指令
BYTE ucCmd[MAX_PATH] = "";
memset(ucCmd,0xff,MAX_PATH); //不足的串以0xff填充
ucCmd[0] = 0xa0;
ucCmd[1] = 0x2c;
ucCmd[2] = 0x00;
ucCmd[3] = byChvNo;
ucCmd[4] = 0x10;
BYTE puk[8];
BYTE chv[8];
memset(puk,0xff,8);
memset(chv,0xff,8);
memcpy(puk,ucPuk,byPukLen);
memcpy(chv,ucChv,byChvLen);
memcpy(&ucCmd[5],puk,8);
memcpy(&ucCmd[13],chv,8);
BYTE ucRes[MAX_PATH];
DWORD dwlen = MAX_PATH;
if(!RunAPDU(ucCmd, 21, ucRes, dwlen))
{
return false;
}
//校验返回值
BYTE sw1 = ucRes[dwlen-2];
BYTE sw2 = ucRes[dwlen-1];
if(sw1 != 0x90 || sw2 != 0x00)
{
return false;
}
return true;
}
bool CPCSC::RunAPDU(IN unsigned char* ucCmd, IN DWORD nCmdLen, OUT unsigned char* ucRes, IN OUT DWORD& nResLen)
{
//判断读卡器是否连接
if(!m_hCard)
{
return false;
}
//发送数据请求
if(::SCardTransmit(m_hCard,SCARD_PCI_T0,ucCmd,nCmdLen,
- 1
- 2
前往页