`
java-mans
  • 浏览: 11387264 次
文章分类
社区版块
存档分类
最新评论

《ASCE1885的信息安全》のWindows下智能卡应用程序的开发(二)

 
阅读更多

1SCardListReaders函数用来获取系统中在指定读卡器组集合中的读卡器名字列表(去掉重复的)。调用者提供一读卡器组列表,函数返回这些指定组里面的读卡器名字列表;无法标识的组名将被忽略。

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;

}

2SCardGetStatusChange函数阻塞程序的运行直到指定的智能卡的可用性发生改变。调用者以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;失败时:智能卡错误码。

3SCardLocateCards函数在参数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;

}

4SCARD_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---读卡器中有一个不响应的智能卡

5SCardFreeMemory函数释放由资源管理器使用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");

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics