SCardReleaseContext
看看 SCardReleaseContext 发生了什么。
576 LONG SCardReleaseContext(SCARDCONTEXT hContext) 577 { 578 LONG rv; 579 release_struct scReleaseStruct; 580 sharedSegmentMsg msgStruct; 581 LONG dwContextIndex; 582 583 PROFILE_START 584 585 /* 586 * Make sure this context has been opened 587 * and get dwContextIndex 588 */ 589 dwContextIndex = SCardGetContextIndice(hContext); 590 if (dwContextIndex == -1) 591 return SCARD_E_INVALID_HANDLE; 592 593 rv = SCardCheckDaemonAvailability();
594 if (rv != SCARD_S_SUCCESS) 595 { 596 /* 597 * Remove the local context from the stack 598 */ 599 (void)SCardLockThread(); 600 (void)SCardRemoveContext(hContext); 601 (void)SCardUnlockThread(); 602 603 return rv; 604 } 605 606 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 607 608 /* check the context is still opened */ 609 dwContextIndex = SCardGetContextIndice(hContext); 610 if (dwContextIndex == -1) 611 /* the context is now invalid 612 * -> another thread may have called SCardReleaseContext 613 * -> so the mMutex has been unlocked */ 614 return SCARD_E_INVALID_HANDLE; 615 616 scReleaseStruct.hContext = hContext; 617 scReleaseStruct.rv = SCARD_S_SUCCESS; 618 619 rv = WrapSHMWrite(SCARD_RELEASE_CONTEXT, 620 psContextMap[dwContextIndex].dwClientID, 621 sizeof(scReleaseStruct), 622 PCSCLITE_MCLIENT_ATTEMPTS, (void *) &scReleaseStruct); 623 624 if (rv == -1) 625 { 626 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 627 return SCARD_E_NO_SERVICE; 628 } 629 630 /* 631 * Read a message from the server 632 */ 633 rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, 634 PCSCLITE_CLIENT_ATTEMPTS); 635 memcpy(&scReleaseStruct, &msgStruct.data, sizeof(scReleaseStruct)); 636
637 if (rv == -1) 638 { 639 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 640 return SCARD_F_COMM_ERROR; 641 } 642 643 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 644 645 /* 646 * Remove the local context from the stack 647 */ 648 (void)SCardLockThread(); 649 (void)SCardRemoveContext(hContext); 650 (void)SCardUnlockThread(); 651 652 PROFILE_END(scReleaseStruct.rv) 653 654 return scReleaseStruct.rv; 655 } |
589~593 行,前面都提了 n 次。
599 (void)SCardLockThread(); 600 (void)SCardRemoveContext(hContext); 601 (void)SCardUnlockThread(); |
SCardRemoveContext
600 行,做了些什么, SCardRemoveContext
定义在 winscard_clnt.c 中
实现如下:
3665 static LONG SCardRemoveContext(SCARDCONTEXT hContext) 3666 { 3667 LONG retIndice; 3668 3669 retIndice = SCardGetContextIndiceTH(hContext); 3670 3671 if (retIndice == -1) 3672 return SCARD_E_INVALID_HANDLE; 3673 else 3674 return SCardCleanContext(retIndice); 3675 } |
SCardGetContextIndiceTH 做了些什么?
上面提过了。那么看 SCardCleanContext 了。
SCardCleanContext 定义在 winscard_clnt.c
实现如下:
3677 static LONG SCardCleanContext(LONG indice) 3678 { 3679 int i; 3680 3681 psContextMap[indice].hContext = 0; 3682 (void)SHMClientCloseSession(psContextMap[indice].dwClientID); 3683 psContextMap[indice].dwClientID = 0; 3684 free(psContextMap[indice].mMutex); 3685 psContextMap[indice].mMutex = NULL; 3686 psContextMap[indice].contextBlockStatus = BLOCK_STATUS_RESUME; 3687 3688 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++) 3689 { 3690 /* 3691 * Reset the /c hCard structs to zero 3692 */ 3693 psContextMap[indice].psChannelMap[i].hCard = 0; 3694 free(psContextMap[indice].psChannelMap[i].readerName); 3695 psContextMap[indice].psChannelMap[i].readerName = NULL; 3696 } 3697 3698 return SCARD_S_SUCCESS; 3699 } |
一层又一层, 所以说 SCardRemoveContext 实际是清除上下文数组和
这个函数的参数 hContext 相关的结构内容,上面说了, SCardEstablishContext
是注册,那么这个就是注销了。对于不再使用的上下文,被 SCardRemoveContext
剔除。没有利用价值就被剔除,有价值就被利用。很容易理解的。
关注下 psContextMap[indice].hContext = 0;
psContextMap[indice].dwClientID = 0;
曾经在 SCardEstablishContext 中获取的,都失去了。
刘德华唱到 “ 短短一生太多的变化 ... 终于失去她 ...”
醒醒,回到 606 行,能活到这行的,说明了 pcscd 还活着。
606~643 行, pcscd 还活着,当然 hContext 被剔除之前,就要告诉 pcscd ,让它收回原来分配来的对应的那份 hContext 上下文。很自然,不是吗?虽然这种做法,有些罗嗦。客户端和服务端在维护为了同一个目的的两个 stuff, 不是吗?
怎么通讯?
构造 release_struct ,然后通过前面提到的 WrapSHMWrite 发送这个数据包, SHMClientRead 接收响应包。
SCardReleaseContext 结束了。
回到 SCardListReaderGroups
3429 if (SCARD_AUTOALLOCATE == *pcchGroups) |
说明如果对应 *pcchGroups 的参数传入 SCARD_AUTOALLOCATE ,则要求在这个
函数内部给读卡器组列表分配内存。
接着只需要返回 "SCard$DefaultReaders/0" 就可以了。
3405 const char ReaderGroup[] = "SCard$DefaultReaders/0"; |
这个说明了, pcsc-lite 版本 (1.5.5) 仅仅支持默认组。
回头,回头,回到 testpcsc.c
109 #ifdef USE_AUTOALLOCATE 110 dwGroups = SCARD_AUTOALLOCATE; 111 rv = SCardListReaderGroups(hContext, (LPSTR)&mszGroups, &dwGroups); 112 #else 113 rv = SCardListReaderGroups(hContext, NULL, &dwGroups); 114 test_rv(rv, hContext, PANIC); 115 116 printf("Testing SCardListReaderGroups/t: "); 117 mszGroups = calloc(dwGroups, sizeof(char)); 118 rv = SCardListReaderGroups(hContext, mszGroups, &dwGroups); 119 # endif |
尝试了 SCardListReaderGroups 的两种调用方式,一种是 SCardListReaderGroups 内部自动分配内存,一种是 APPLICATION 自己分配内存。
133 #ifdef USE_AUTOALLOCATE 134 printf("Testing SCardFreeMemory/t/t: "); 135 rv = SCardFreeMemory(hContext, mszGroups); 136 test_rv(rv, hContext, PANIC); 137 #else 138 free(mszGroups); 139 #endif |
说明了,如果是 SCardListReaderGroups 分配了内存,那么你必须调用 SCardFreeMemory 来释放这些内存。如果是 APPLICATION 调用了内存,则需要 free.
看看这个做了些什么?