分类: C/C++
2013-03-05 11:14:09
二、PC/SC API for Visual C++
1、#include
winscard.h是Visual C++编译时所需要的参数及基本资料结构,请记得连结时加入winscard.lib,这样才能完成您的程式,此两档在Visual C++ 的 include及library目录下可以找到,这种方式称为「隐式调用DLL」,程式好像与winscard.dll无关但实际上是透过DLL执行,. h档案内容大致如下:
#define SCARD_STATE_UNAWARE 0x00000000
#define SCARD_STATE_IGNORE 0x00000001
#define SCARD_STATE_CHANGED 0x00000002
#define SCARD_STATE_UNKNOWN 0x00000004
#define SCARD_STATE_UNAVAILABLE 0x00000008
WINSCARDDATA extern const SCARD_IO_REQUEST
g_rgSCardT0Pci,
g_rgSCardT1Pci,
g_rgSCardRawPci;
extern WINSCARDAPI LONG WINAPI
SCardEstablishContext(
IN DWORD dwScope,
IN LPCVOID pvReserved1,
IN LPCVOID pvReserved2,
OUT LPSCARDCONTEXT phContext);
其实 PC/SC 不一定要在Windows 系统执行,以下定义为Linux系统所使用之PC/SC,请比较一下差异在哪里。
typedef struct {
DWORD dwProtocol; /* SCARD_PROTOCOL_T0 or SCARD_PROTOCOL_T1 */
DWORD cbPciLength; /* Length of this structure - not used */
} SCARD_IO_REQUEST;
long SCardEstablishContext(unsigned long dwScope,const void *pvReserved1, const void *pvReserved2, long *phContext);
以下说明一些重要函式之功能,细节部分请参考,附件二、PC/SC API Reference Document。
2、ScardEstablishContext
SCardEstablishContext 直觉的解释就是建立PC/SC在作业系统下的资源,所有PC/SC应用程式开始时一定要呼叫此函式建立资源后才能开始运作,范例如下。
SCARDCONTEXT hContext;
LONG rv;
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
3、ScardListReaders
SCardListReaders 直觉的解释就是列出此台机器可用之Smartcard 读卡机,比较特别的是第一次呼叫时并不知道机器有几台可用之读卡机所以mszReaders先代入NULL,取得实际数量后再呼叫一次就可列出读卡机名称,此技巧运用在很多API 呼叫中,第一次看到觉得怪怪,仔细想想此种呼叫方式真聪明。
LPTSTR mszReaders;
DWORD dwReaders;
rv = SCardListReaders(hContext, NULL, NULL, &dwReaders);
mszReaders = (LPTSTR)malloc(sizeof(char)*dwReaders);
rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders);
4、ScardConnect
SCardConnect 直觉的解释就是建立Smartcard之连线,参数就是代入SCardListReaders 所列出之读卡机名称;当连线完成后Smartcard会被重置,传回ATR讯息。
SCARDHANDLE hCard;
DWORD dwActiveProtocol;
rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
5、ScardBeginTransaction
当读卡机以分享方式开启时,SCardBeginTransaction 就是宣告尔后将执行一连串的APDU指令以确保中间不被插断,当结束所有APDU指令后需呼叫ScardEndTransaction让其他连线继续运作;当读卡机以独占方式开启时,可以不必执行此函式,直接执行SCardTransmit即可。
rv = SCardBeginTransaction(hCard);
6、ScardTransmit
SCardTransmit是在呼叫SCardConnect函式后,传送APDU 指令到Smartcard的函式,可说是整个Smartcard程式设计的核心,在此特别说明下列程式。
DWORD dwSendLength, dwRecvLength;
SCARD_IO_REQUEST pioRecvPci;
/*必须使用BYTE传送及接收资料,如果您输入的指令是CHAR记得转换为BYTE ,很特别的是此函式呼叫时就已经定义好接收资料*/
BYTE pbRecvBuffer[10];
/*此行即为APDU Command,特别解释一下,这行指令是选取Master File。
Command CLA INS P1 P2 Lc Data Le
Select C0 A4 00 00 02 3F00
*/
BYTE pbSendBuffer[] = { 0xC0, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00 };
dwSendLength = sizeof(pbSendBuffer);
dwRecvLength = sizeof(pbRecvBuffer);
rv = SCardTransmit(hCard, SCARD_PCI_T0, pbSendBuffer, dwSendLength,
&pioRecvPci, pbRecvBuffer, &dwRecvLength);
7、SCardEndTransaction
SCardEndTransaction 是结束之前SCardBeginTransaction 之宣告;必须与SCardBeginTransaction配对使用。
rv = SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
8、ScardDisconnect
SCardDisconnect 是结束之前SCardConnect所建立的连线,呼叫此函式后就无法在传送APDU指令了。
rv = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
9、ScardReleaseContext
SCardReleaseContext 直觉的解释就是释放SCardEstablishContext 在作业系统下所建立的资源,所有PC/SC应用程式结束时一定要呼叫此函式归还资源。
rv = SCardReleaseContext(hContext);
10、其他PC/SC API
PC/SC API函式不只这些,某些应用场合可能会使用到,请参考附件二、PC/SC API Reference Document。