PCSC那事儿(十六--SCardListReaders)

 

SCardListReaders

SCardListReaders 做了什么?

定义在 winscard_clnt.c

实现如下:

3202 LONG SCardListReaders(SCARDCONTEXT hContext, /*@unused@*/ LPCSTR mszGroups,

3203         LPSTR mszReaders, LPDWORD pcchReaders)

3204 {

3205         DWORD dwReadersLen;

3206         int i;

3207          LONG dwContextIndex;

3208         LONG rv = SCARD_S_SUCCESS;

3209         char *buf = NULL;

3210

3211         (void)mszGroups;

3212         PROFILE_START

3213

3214         /*

3215          * Check for NULL parameters

3216          */

3217         if (pcchReaders == NULL)

3218                 return SCARD_E_INVALID_PARAMETER;

3219

3220         rv = SCardCheckDaemonAvailability();

3221         if (rv != SCARD_S_SUCCESS)

3222                 return rv;

3223

3224         /*

3225          * Make sure this context has been opened

3226          */

3227         dwContextIndex = SCardGetContextIndice(hContext);

3228         if (dwContextIndex == -1)

3229                 return SCARD_E_INVALID_HANDLE;

3230

3231         (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);

3232

 

3233         /* check the context is still opened */

3234         dwContextIndex = SCardGetContextIndice(hContext);

3235         if (dwContextIndex == -1)

3236                 /* the context is now invalid

3237                  * -> another thread may have called SCardReleaseContext

3238                  * -> so the mMutex has been unlocked */

3239                 return SCARD_E_INVALID_HANDLE;

3240

3241         dwReadersLen = 0;

3242         for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)

3243                 if ((readerStates[i])->readerID != 0)

3244                         dwReadersLen += strlen((readerStates[i])->readerName) + 1;

3245

3246         /* for the last NULL byte */

3247         dwReadersLen += 1;

3248

3249          if (1 == dwReadersLen)

3250         {

3251                 rv = SCARD_E_NO_READERS_AVAILABLE;

3252                 goto end;

3253         }

3254

3255         if (SCARD_AUTOALLOCATE == *pcchReaders)

3256         {

3257                 buf = malloc(dwReadersLen);

3258                 if (NULL == buf)

3259                 {

3260                         rv = SCARD_E_NO_MEMORY;

3261                         goto end;

3262                 }

3263                 if (NULL == mszReaders)

3264                 {

3265                         rv = SCARD_E_INVALID_PARAMETER;

3266                         goto end;

3267                 }

3268                 *(char **)mszReaders = buf;

3269         }

3270         else

3271         {

3272                 buf = mszReaders;

3273

3274                 /* not enough place to store the reader names */

3275                 if ((NULL != mszReaders) && (*pcchReaders < dwReadersLen))

3276                 {

 

3277                         rv = SCARD_E_INSUFFICIENT_BUFFER;

3278                          goto end;

3279                 }

3280         }

3281

3282         if (mszReaders == NULL) /* text array not allocated */

3283                 goto end;

3284

3285         for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)

3286         {

3287                 if ((readerStates[i])->readerID != 0)

3288                 {

3289                         /*

3290                          * Build the multi-string

3291                          */

3292                         strcpy(buf, (readerStates[i])->readerName);

3293                         buf += strlen((readerStates[i])->readerName)+1;

3294                 }

3295         }

3296         *buf = '/0';    /* Add the last null */

3297

3298 end:

3299         /* set the reader names length */

3300          *pcchReaders = dwReadersLen;

3301

3302         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);

3303

3304         PROFILE_END(rv)

3305

3306         return rv;

3307 }

 

 

上面又出现了

3227         dwContextIndex = SCardGetContextIndice(hContext);

3228         if (dwContextIndex == -1)

3229                 return SCARD_E_INVALID_HANDLE;

3230

3231         (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);

3232

3233          /* check the context is still opened */

3234         dwContextIndex = SCardGetContextIndice(hContext);

3235         if (dwContextIndex == -1)

3236                 /* the context is now invalid

3237                  * -> another thread may have called SCardReleaseContext

3238                  * -> so the mMutex has been unlocked */

3239                  return SCARD_E_INVALID_HANDLE ;

 

 

已经解释过了。以后这样的片段不再解释了。

3242         for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)

3243                 if ((readerStates[i])->readerID != 0)

3244                          dwReadersLen += strlen((readerStates[i])->readerName) + 1;

 

 

这里出现了 readerStates 这个在哪里初始化过?

依然记得,在前面的 SCardEstablishContextTH

  411                 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)

  412                 {

  413                         readerStates[i] =

  414                                 (PREADER_STATE)SYS_PublicMemoryMap(sizeof(READER_STATE),

  415                                 mapAddr, (i * pageSize));

  416                         if (readerStates[i] == NULL)

  417                         {

  418                                 Log2(PCSC_LOG_CRITICAL, "Cannot public memory map: %s",

  419                                         strerror(errno));

  420                                 (void)SYS_CloseFile(mapAddr);   /* Close the memory map file */

  421                                 return SCARD_F_INTERNAL_ERROR;

  422                          }

  423                 }

 

 

I got it.

这里初始化过了。

通过共享内存,动态获得了系统中读卡器的状态。

看看 READER_STATE 的定义 , 再看一次

typedef struct pubReaderStatesList

        {

                int32_t readerID;

                char readerName[MAX_READERNAME];

                uint32_t readerState;

                int32_t readerSharing;

 

 

                UCHAR cardAtr[MAX_ATR_SIZE];

                uint32_t cardAtrLength;

                uint32_t cardProtocol;

        }

        READER_STATE, *PREADER_STATE;

 

 

这里有 readerName ,太好了。

这样的话, SCardListReaders 只要收集 READER_STATE 数组提供的 readerName ,就实现了获取读卡器列表。

3285~3294 行,从共享内存中获得了读卡器列表

3285         for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)

3286         {

3287                 if ((readerStates[i])->readerID != 0)

3288                 {

3289                         /*

3290                          * Build the multi-string

3291                          */

3292                         strcpy(buf, (readerStates[i])->readerName);

3293                         buf += strlen((readerStates[i])->readerName)+1;

3294                 }

3295         }

3296          *buf = '/0';    /* Add the last null */

 

 

 

特别又列了一次这个片段,是为了说明读卡器列表字符串的格式是:每个读卡器名字都是以 '/ ' 作为间隔,字符串的最后是两个 '/0' 。和读卡器组列表字符串的格式 ( 已经提过 ) 一样。

而且读卡器列表的内存分配方式也分为是 SCardListReaders 分配,还是 APPLICATION 自己分配两种。

 

回到 testpcsc.c 146

146         if (SCARD_E_NO_READERS_AVAILABLE == rv)

147         {

148                 printf("Testing SCardGetStatusChange /n");

149                 printf("Please insert a working reader/t: ");

150                 (void)fflush(stdout);

151                 rgReaderStates[0].szReader = "?PnP?//Notification";

152                 rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY;

153

154                 rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1);

155                 test_rv(rv, hContext, PANIC);

156          }

 

 

如果 144 SCardListReaders 没有找到任何读卡器,则 146 判断成立,

提示插入读卡器,

"?PnP?//Notification" 还有 SCardGetStatusChange 都是做些什么的?

别着急,慢慢说。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Windows PC/SC是一种用于智能卡通讯的API(应用程序编程接口)标准。PC/SCPC/SC Workgroup组织制定的,该组织是一个由智能卡产业的各个领域代表组成的国际标准化组织。PC/SC标准定义了在Windows系统上与智能卡通信的规范和流程。 在Windows PC/SC的工作流程中,有以下几个主要步骤: 1. 初始化:在使用PC/SC接口之前,需要通过调用SCardEstablishContext函数来初始化与PC/SC服务的通信。 2. 检测读卡器:通过调用SCardListReaders函数来检测系统上已连接的读卡器,并获得读卡器的列表。 3. 连接读卡器:通过调用SCardConnect函数并指定读卡器名称来连接一个读卡器。 4. 与卡片通信:一旦与读卡器建立了连接,就可以通过调用SCardTransmit函数来与智能卡进行通信,发送指令和接收相应数据。 5. 断开连接:在使用完智能卡后,需要通过调用SCardDisconnect函数来断开与卡片的连接。 6. 清理:最后,通过调用SCardReleaseContext函数来释放与PC/SC服务的通信。 通过这样的流程,应用程序可以与智能卡进行交互,实现对智能卡的读写、认证和应用管理等功能。 需要注意的是,Windows PC/SC还提供了更高级别的API,用于实现更复杂的智能卡功能,如PKI(公钥基础设施)认证、加密和数字签名等。同时,PC/SC也支持多种类型的智能卡,包括接触式和非接触式的智能卡,以及不同的通信协议,如ISO 7816等。 总之,Windows PC/SC提供了一个标准化的接口和工作流程,使得应用程序可以方便地与智能卡进行通信和交互,实现各种安全认证和应用管理的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值