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 ' 作为间隔,字符串的最后是两个 '/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 都是做些什么的?
别着急,慢慢说。