qt5 win7下调用 pcsc smartcard winscard库
简单的参考代码:(需要有智能卡读卡器设备)
https://download.csdn.net/download/wowocpp/14920759
win32: LIBS += -lWinSCard
xxx.pro文件
QT -= gui
CONFIG += c++11 console
CONFIG -= app_bundle
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
PCSC.cpp \
main.cpp
DEFINES += _UNICODE
win32: LIBS += -lWinSCard
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
HEADERS += \
PCSC.h
main.cpp
#include <QCoreApplication>
#include "winscard.h"
#include <conio.h>
#include <iostream>
#include "PCSC.h"
#include <QDebug>
int main(int argc, char *argv[])
{
// SCARDCONTEXT _context;
// LONG lRetValue = SCardEstablishContext(SCARD_SCOPE_USER, nullptr, nullptr, &_context);
// if ( SCARD_S_SUCCESS != lRetValue ){
// std::cout << "Failed SCardEstablishContext\n";
// }else{
// std::cout << "Success SCardEstablishContext\n";
// }
CPCSC smartCardReader ;
smartCardReader.ListCardReader();
printf("Hello World AAAA\n");
//std::cout << lRetValue;
std::cout <<"Hello" ;
std::cout <<SCARD_S_SUCCESS ;
_getch();
QCoreApplication a(argc, argv);
qDebug()<< QString::fromStdWString(smartCardReader.ppReadersName[2]);
smartCardReader.ConnectCard(smartCardReader.ppReadersName[2]);
#define HEX_BUF_LEN 100
BYTE HexDataBuf[HEX_BUF_LEN] = {0x00,0x84,0x00,0x00,0x04};
UINT i ;
int iHexBufCnt =5 ;
BYTE RecvData[HEX_BUF_LEN];
DWORD dwRecvDataLen =HEX_BUF_LEN;
BOOL bRet ;
bRet = smartCardReader.TransimitCard(HexDataBuf,iHexBufCnt,RecvData,&dwRecvDataLen);
if(bRet == TRUE){
printf("\nRecv Data :\n");
for(i=0;i < dwRecvDataLen;i++){
printf("%.2x\n",RecvData[i]);
}
}
return a.exec();
}
pcsc.cpp
#include <conio.h>
#include <iostream>
#include <string>
#include "PCSC.h"
#define log printf
#define log_t printf
//用到的接口包括
//1.和卡建立连接 OpenCard
//2.关闭和卡的连接 CloseCard
//3.查询当前的PCSC读卡器都有哪些
//4.选择一个读卡器进行连接
//5.APDU发送数据到卡,并且将卡返回的数据原路返回给上层buffer
//6.最后加上接口,读读卡器列表
//7.自己维护一个读卡器列表
//8.需要单独的建立环境的函数
CPCSC::CPCSC(void)
{
m_hContext = NULL;
m_hCard = NULL;
unReadersNum = 0 ;
bIsConnected = FALSE ;
}
CPCSC::~CPCSC(void)
{
DisConnectCard();
}
BOOL CPCSC::EstablishContext(void)
{
LONG res;
if(m_hContext != NULL){
return TRUE;
}
res = ::SCardEstablishContext(SCARD_SCOPE_USER,NULL,NULL,&m_hContext);
if(res != SCARD_S_SUCCESS){
m_hContext = NULL ;
return FALSE;
}
log("Establish Context Success %d\n",2);
return TRUE ;
}
BOOL CPCSC::ReleaseContext(void)
{
LONG ret ;
if(m_hContext != NULL){
ret = ::SCardReleaseContext(m_hContext);
if(SCARD_S_SUCCESS != ret){
return FALSE ;
}
}
return TRUE;
}
/*
将当前系统中的,所有的PCSC读卡器名称列出来
ppArrowReaders --- 二维数组
ArrowRow --- 二维数组的列
ArrowLine --- 二位数组的行
*/
BOOL CPCSC::ListCardReader(void)
{
LONG res ; // return value
LONG res2;
BOOL ret = TRUE ;
DWORD cch = SCARD_AUTOALLOCATE ;
LPTSTR pmszReaders = NULL ;
LPTSTR pReader = NULL;
UINT len = 0 ;
unReadersNum = 0 ;
EstablishContext();
res = SCardListReaders(m_hContext,
NULL,
(LPTSTR)&pmszReaders,
&cch);
switch(res){
case SCARD_E_NO_READERS_AVAILABLE:
//Reader is not in groups .
unReadersNum = 0 ;
ret = FALSE ;
break;
case SCARD_S_SUCCESS:
pReader = pmszReaders;
while( '\0' != *pReader){
printf("Reader: %S\n", pReader );
if(unReadersNum >= CARD_READERS_NUM){
unReadersNum = 0 ;
ret = FALSE ;
break ;
}
len = wcslen(pReader);
if(len >= CARD_READERS_NAME_LEN){
unReadersNum = 0 ;
ret = FALSE ;
break ;
}
wcscpy(ppReadersName[unReadersNum],pReader);
//wsprintf("pReader = %s\n",pmszReaders);
//std::cout << pReader ;
//wprintf("_tcslen(pReader = %d\n"),_tcslen(pReader));
unReadersNum++ ;
pReader = pReader + wcslen(pReader)+1 ;
}
res2 = SCardFreeMemory( m_hContext,
pmszReaders );
if ( SCARD_S_SUCCESS != res2 ){
ret = FALSE ;
unReadersNum = 0 ;
}
break ;
}
return ret;
}
/*
打开指定名称的读卡器
*/
BOOL CPCSC::ConnectCard(LPCTSTR lpReader)
{
LONG res ;
BOOL ret ;
if(bIsConnected == TRUE){
return TRUE;
}
ret = EstablishContext();
if(!ret){
return FALSE ;
}
printf("lpReader = %ws\n",lpReader);
res = SCardConnect(m_hContext,
lpReader,
SCARD_SHARE_EXCLUSIVE,
SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1,
&m_hCard,
&m_dwActiveProtocol
);
if(SCARD_S_SUCCESS != res){
m_hCard = NULL ;
DisConnectCard();
return FALSE ;
}
log("ScardConnect Success\n");
bIsConnected = TRUE ;
return TRUE;
}
void CPCSC::DisConnectCard(void)
{
if(m_hCard)
{
::SCardDisconnect(m_hCard,SCARD_EJECT_CARD);
m_hCard = 0;
}
if(m_hContext)
{
::SCardReleaseContext(m_hContext);
m_hContext = 0;
}
bIsConnected = FALSE ;
}
/*
Get Response:0x00,0xC0 ,0x00,0x00,0x0F
不是线程安全的
这个先不考虑
*/
BOOL CPCSC::TransimitCard(LPCBYTE pbSendBuffer,DWORD cbSendLength,LPBYTE pbRecvBuffer,LPDWORD pcbRecvLength)
{
LONG res ;
LPCSCARD_IO_REQUEST ioRequest ;
if(bIsConnected == FALSE){
return FALSE;
}
DWORD RecvLen = *pcbRecvLength ;
switch(m_dwActiveProtocol){
case SCARD_PROTOCOL_T0:
ioRequest = SCARD_PCI_T0;
break ;
case SCARD_PROTOCOL_T1:
ioRequest = SCARD_PCI_T1;
break ;
default :
ioRequest = SCARD_PCI_T0 ;
break ;
}
res = SCardTransmit(m_hCard,
ioRequest ,
pbSendBuffer,
cbSendLength,
NULL,
pbRecvBuffer,
pcbRecvLength
);
if(SCARD_S_SUCCESS != res){
return FALSE ;
}
BYTE SW1,SW2;
SW1 = pbRecvBuffer[*pcbRecvLength -2];
SW2 = pbRecvBuffer[*pcbRecvLength -1];
log("SW1=%.2x\n",SW1);
log("SW2=%.2x\n",SW2);
if(SW1 == 0x61){
BYTE ucSendBuf[5] = {0x00,0xC0,0x00,0x00};
ucSendBuf[4] = SW2;
/*SCardTransmit 会修改pcbRecvLength的值*/
*pcbRecvLength = RecvLen ;
res = SCardTransmit(m_hCard,
ioRequest ,
ucSendBuf,
5,
NULL,
pbRecvBuffer,
pcbRecvLength
);
if(res != SCARD_S_SUCCESS){
log("Fail\n");
return FALSE ;
}
log("success\n");
}
return TRUE ;
}
按下回车,或者是随便一个按键
(仅供参考)