1)SCardListReaders函数用来获取系统中在指定读卡器组集合中的读卡器名字列表(去掉重复的)。调用者提供一读卡器组列表,函数返回这些指定组里面的读卡器名字列表;无法标识的组名将被忽略。
LONG WINAPI SCardListReaders(
__in SCARDCONTEXT hContext, //由SCardEstablishContext()建立的资源管理器上下文,
//不能为NULL
__in_opt LPCTSTR mszGroups, //读卡器组名,为NULL时表示列出系统中所有读卡器
__out LPTSTR mszReaders, //系统中指定读卡器组中的读卡器的名字,这是一个多重字符串
//各个名字之间用‘/0’分隔,最后一个名字后面是两个连续的‘/0’
//当该参数为NULL时,函数在pcchReaders中返回实际所需长度
__inout LPDWORD pcchReaders //mszReaders的有效字符长度,包括所有的‘/0’。当该参数指定
//为SCARD_AUTOALLOCATE时,mszReaders将被转为指向字节指针的
//指针,用于接收包含多重字符串的内存块地址,该内存块必须使用函数
//SCardFreeMemory来释放
);
返回值:成功时是SCARD_S_SUCCESS;当指定组中没有读卡器时,返回SCARD_E_NO_READERS_AVAILABLE;否则返回其他智能卡错误码。
下面是该函数的实例代码:
LPTSTR pmszReaders = NULL;
LPTSTR pReader;
LONG lReturn, lReturn2;
DWORD cch = SCARD_AUTOALLOCATE;
// Retrieve the list the readers.
// hSC was set by a previous call to SCardEstablishContext.
lReturn = SCardListReaders(hSC,
NULL,
(LPTSTR)&pmszReaders,
&cch );
switch( lReturn )
{
case SCARD_E_NO_READERS_AVAILABLE:
printf("Reader is not in groups./n");
// Take appropriate action.
// ...
break;
case SCARD_S_SUCCESS:
// Do something with the multi string of readers.
// Output the values.
// A double-null terminates the list of values.
pReader = pmszReaders;
while ( '/0' != *pReader )
{
// Display the value.
printf("Reader: %S/n", pReader );
// Advance to the next value.
pReader = pReader + wcslen((wchar_t *)pReader) + 1;
}
// Free the memory.
lReturn2 = SCardFreeMemory( hSC,
pmszReaders );
if ( SCARD_S_SUCCESS != lReturn2 )
printf("Failed SCardFreeMemory/n");
break;
default:
printf("Failed SCardListReaders/n");
// Take appropriate action.
// ...
break;
}
2)SCardGetStatusChange函数阻塞程序的运行直到指定的智能卡的可用性发生改变。调用者以SCARD_READERSTAT数组的形式提供需要监控的读卡器列表,以及最长等待的时间(ms)。
LONG WINAPI SCardGetStatusChange(
__in SCARDCONTEXT hContext, //由SCardEstablishContext()建立的资源管理器上下文
__in DWORD dwTimeout, //最长等待的毫秒数,0表示函数立即返回;INFINITE表示一直等待
__inout LPSCARD_READERSTATE rgReaderStates, //SCARD_READERSTATE结构数组,指定监控的
//读卡器,同时用于接收返回结果。为了接收新的智能卡到来的通知,需要将
//SCARD_READERSTATE结构中的szReader参数设为////?PnP?//Notification,其他成员
//设为0;注意:该结构数组中的每个结构的所有成员必须初始化为0后再根据需要设置
//其他值,否则,函数将在包含远程读卡器的情况下返回失败
__in DWORD cReaders //rgReaderStates结构中的元素个数
);
返回值:成功时:SCARD_S_SUCCESS;失败时:智能卡错误码。
3)SCardLocateCards函数在参数rgReaderStates中指定的读卡器列表中查找由参数mszCards指定的智能卡,并立即返回结果:
LONG WINAPI SCardLocateCards(
__in SCARDCONTEXT hContext, //由SCardEstablishContext()建立的资源管理器上下文
__in LPCTSTR mszCards, //包含要查找的智能卡的多重字符串
__inout LPSCARD_READERSTATE rgReaderStates, //SCARD_READERSTATE结构数组,作为输入参数
//时,指定在其中查找的读卡器列表;作为输出参数时,接收查找结果
__in DWORD cReaders //rgReaderStates结构中元素个数
);
返回值:成功时:SCARD_S_SUCCESS;失败时:智能卡错误码。
该函数和SCardGetStatusChange函数一起使用时特别有用,当调用SCardLocateCards函数找不到匹配的智能卡时,应用程序可以使用SCardGetStatusChange函数来等待智能卡可用性的改变。
实例代码如下:
// Copyright (c) Microsoft Corporation. All rights reserved.
#include <stdio.h>
#include <winscard.h>
#include <tchar.h>
#pragma comment(lib, "winscard.lib")
HRESULT __cdecl main()
{
HRESULT hr = S_OK;
LPTSTR szReaders, szRdr;
DWORD cchReaders = SCARD_AUTOALLOCATE;
DWORD dwI, dwRdrCount;
SCARD_READERSTATE rgscState[MAXIMUM_SMARTCARD_READERS];
TCHAR szCard[MAX_PATH];
SCARDCONTEXT hSC;
LONG lReturn;
// Establish the card to watch for.
// Multiple cards can be looked for, but
// this sample looks for only one card.
_tcscat_s ( szCard, MAX_PATH * sizeof(TCHAR), TEXT("GemSAFE"));
szCard[lstrlen(szCard) + 1] = 0; // Double trailing zero.
// Establish a context.
lReturn = SCardEstablishContext(SCARD_SCOPE_USER,
NULL,
NULL,
&hSC );
if ( SCARD_S_SUCCESS != lReturn )
{
printf("Failed SCardEstablishContext/n");
exit(1);
}
// Determine which readers are available.
lReturn = SCardListReaders(hSC,
NULL,
(LPTSTR)&szReaders,
&cchReaders );
if ( SCARD_S_SUCCESS != lReturn )
{
printf("Failed SCardListReaders/n");
exit(1);
}
// Place the readers into the state array.
szRdr = szReaders;
for ( dwI = 0; dwI < MAXIMUM_SMARTCARD_READERS; dwI++ )
{
if ( 0 == *szRdr )
break;
rgscState[dwI].szReader = szRdr;
rgscState[dwI].dwCurrentState = SCARD_STATE_UNAWARE;
szRdr += lstrlen(szRdr) + 1;
}
dwRdrCount = dwI;
// If any readers are available, proceed.
if ( 0 != dwRdrCount )
{
for (;;)
{
// Look for the card.
lReturn = SCardLocateCards(hSC,
szCard,
rgscState,
dwRdrCount );
if ( SCARD_S_SUCCESS != lReturn )
{
printf("Failed SCardLocateCards/n");
exit(1);
}
// Look through the array of readers.
for ( dwI=0; dwI < dwRdrCount; dwI++)
{
if ( 0 != ( SCARD_STATE_ATRMATCH &
rgscState[dwI].dwEventState))
{
_tprintf( TEXT("Card '%s' found in reader '%s'./n"),
szCard,
rgscState[dwI].szReader );
SCardFreeMemory( hSC,
szReaders );
return 0; // Context will be release automatically.
}
// Update the state.
rgscState[dwI].dwCurrentState = rgscState[dwI].dwEventState;
}
// Card not found yet; wait until there is a change.
lReturn = SCardGetStatusChange(hSC,
INFINITE, // infinite wait
rgscState,
dwRdrCount );
if ( SCARD_S_SUCCESS != lReturn )
{
printf("Failed SCardGetStatusChange/n");
exit(1);
}
} // for (;;)
}
else
printf("No readers available/n");
// Release the context.
lReturn = SCardReleaseContext(hSC);
if ( SCARD_S_SUCCESS != lReturn )
{
printf("Failed SCardReleaseContext/n");
exit(1);
}
SCardFreeMemory( hSC,
szReaders );
return hr;
}
4)SCARD_READERSTATE结构用于智能卡跟踪函数中,定义如下:
typedef struct {
LPCTSTR szReader; //要监控的读卡器名字的指针,将该参数设为////?PnP?//Notification,其他参数均
//设为0,可用于通知新的读卡器的到来
LPVOID pvUserData; //智能卡子系统不使用该参数,该参数被应用程序使用
DWORD dwCurrentState; //被应用程序感知的读卡器当前的状态
DWORD dwEventState; //被智能卡资源管理器感知的读卡器当前状态
DWORD cbAtr; //返回的ATR的字节个数
BYTE rgbAtr[36]; //插入的智能卡的ATR(包含额外对齐的字节)
} SCARD_READERSTATE, *PSCARD_READERSTATE, *LPSCARD_READERSTATE;
参数dwCurrentState取值组合如下:
SCARD_STATE_UNAWARE---应用程序对当前状态一无所知,但想知道;使用该参数,状态转移监视服
务将立即返回;
SCARD_STATE_IGNORE---应用程序对这个读卡器不感兴趣,在监控期间不考虑该读卡器,设置该参数将
忽略其他位掩码;
SCARD_STATE_UNAVAILABLE---应用程序希望该读卡器当前不可用,设置该参数将忽略其他后续位掩码
SCARD_STATE_EMPTY---应用程序希望读卡器中没有智能卡,设置该参数将忽略其他后续位掩码;
SCARD_STATE_PRESENT---应用程序希望读卡器中有一个智能卡;
SCARD_STATE_ATRMATCH---应用程序希望读卡器中有一个匹配目标智能卡的智能卡
SCARD_STATE_EXCLUSIVE---应用程序希望读卡器中的智能卡不被共享
SCARD_STATE_INUSE---应用程序希望读卡器中的智能卡正被一个或多个应用程序使用,但使用共享连接
SCARD_STATE_MUTE---应用程序希望读卡器中有一个不响应的智能卡
参数dwEventState取值组合如下:
SCARD_STATE_IGNORE---该读卡器应该被忽略;
SCARD_STATE_CHANGED---该位被设置时,应用程序假设读卡器发生了明显的状态改变;
SCARD_STATE_UNKNOWN---给定的读卡器名字不被资源管理器识别;
SCARD_STATE_UNAVAILABLE---读卡器的实际状态是不可用的;
SCARD_STATE_EMPTY---读卡器中没有智能卡;
SCARD_STATE_PRESENT---读卡器中有一个智能卡;
SCARD_STATE_ATRMATCH---读卡器中有一个匹配目标智能卡的智能卡;
SCARD_STATE_EXCLUSIVE---读卡器中的智能卡不被共享;
SCARD_STATE_INUSE---读卡器中的智能卡正被一个或多个应用程序使用,但使用共享连接
SCARD_STATE_MUTE---读卡器中有一个不响应的智能卡
5)SCardFreeMemory函数释放由资源管理器使用SCARD_AUTOALLOCATE分配的内存:
LONG WINAPI SCardFreeMemory(
__in SCARDCONTEXT hContext, //由SCardEstablishContext()返回的资源管理器上下文
__in LPCVOID pvMem //要释放的内存块
);
返回值:成功时:SCARD_S_SUCCESS;失败时:智能卡错误代码。
代码片段:
lReturn = SCardFreeMemory(hSC,
pmszReaders );
if ( SCARD_S_SUCCESS != lReturn )
printf("Failed SCardFreeMemory/n");