《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");

 

 

 

 

你可能感兴趣的:(windows)