PCSC那事儿(十六--SCardListReaders)

来源:互联网 发布:java 字符串搜索 编辑:程序博客网 时间:2024/05/29 02:54

 

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         }

 

 

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

提示插入读卡器,

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

别着急,慢慢说。