859 else if (rContext->dwVersion == IFD_HVERSION_3_0) 860 { 861 /* The following binds version 3.0 of the IFD Handler specs */ 862 #define GET_ADDRESS_OPTIONALv3(s, code) / 863 { / 864 void *f1 = NULL; / 865 if (SCARD_S_SUCCESS != DYN_GetAddress(rContext->vHandle, &f1, "IFDH" #s)) / 866 { / 867 code / 868 } / 869 rContext->psFunctions.psFunctions_v3.pvf ## s = f1; / 870 } 871 872 #define GET_ADDRESSv3(s) / 873 GET_ADDRESS_OPTIONALv3(s, / 874 Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #s ); / 875 exit(1); ) |
862行,定义了一个宏,目的是加载动态库中的s函数,执行code代码,并初始化
reader上下文中的psFunctions.psFunctions_v3.pvf##s.
872行,定义了另一个宏,是上面一个宏的wrapper,仅仅具现化了code.
有了这两个helper宏,则对于v3版本的ifdhandler的动态库函数加载很是方便。
876 877 Log1(PCSC_LOG_INFO, "Loading IFD Handler 3.0"); 878 879 GET_ADDRESSv2(CreateChannel) 880 GET_ADDRESSv2(CloseChannel) 881 GET_ADDRESSv2(GetCapabilities) 882 GET_ADDRESSv2(SetCapabilities) 883 GET_ADDRESSv2(PowerICC) 884 GET_ADDRESSv2(TransmitToICC) 885 GET_ADDRESSv2(ICCPresence) 886 GET_ADDRESS_OPTIONALv2(SetProtocolParameters, ) 887 888 GET_ADDRESSv3(CreateChannelByName) 889 GET_ADDRESSv3(Control) 890 } |
876~890行,使用了上面的两个宏,进一步初始化了psFunctions.psFunctions_v3各字段。
必选的函数对应的各字段,
psFunctions.psFunctions_v3.pvfCreateChannel
psFunctions.psFunctions_v3.pvfCloseChannel
psFunctions.psFunctions_v3.pvfGetCapabilities
psFunctions.psFunctions_v3.pvfSetCapabilities
psFunctions.psFunctions_v3.pvfPowerICC
psFunctions.psFunctions_v3.pvfTransmitToICC
psFunctions.psFunctions_v3.pvfICCPresence
psFunctions.psFunctions_v3.pvfControl
psFunctions.psFunctions_v3.pvfCreateChannelByName
可选的函数对应的各字段,
psFunctions.psFunctions_v3.pvfSetProtocolParameters
好了,接下来是v4版本,有吗?现在还没有v4版本。
891 else 892 { 893 /* Who knows what could have happenned for it to get here. */ 894 Log1(PCSC_LOG_CRITICAL, "IFD Handler not 1.0/2.0 or 3.0"); 895 exit(1); 896 } 897 898 return SCARD_S_SUCCESS; 899 } |
891~899行,正如注释所说,因为前面已经进行了版本的判断,如果不是3个版本之一,
则直接退出。所以这里的else显的有些多余。
或许,也不算多余。可以表达现实。版本1,2,3代表权,钱,势。else进一步强调了,如果
没有拥有3者之一,那么命运将是坎坷的。被安排到最后一个else给人家垫背,最后还exit.
几千年的历史,基本都在重复这样的故事。
也请先行记住,有些高版本存在的函数,在低版本中并不存在。
好了。继续看IFDOpenIFD
定义在ifdwrapper.c
实现如下:
112 LONG IFDOpenIFD(PREADER_CONTEXT rContext) 113 { 114 RESPONSECODE rv = 0; 115 116 #ifndef PCSCLITE_STATIC_DRIVER 117 RESPONSECODE(*IO_create_channel) (DWORD) = NULL; 118 RESPONSECODE(*IFDH_create_channel) (DWORD, DWORD) = NULL; 119 RESPONSECODE(*IFDH_create_channel_by_name) (DWORD, LPSTR) = NULL; 120 121 if (rContext->dwVersion == IFD_HVERSION_1_0) 122 IO_create_channel = 123 rContext->psFunctions.psFunctions_v1.pvfCreateChannel; 124 else 125 if (rContext->dwVersion == IFD_HVERSION_2_0) 126 IFDH_create_channel = 127 rContext->psFunctions.psFunctions_v2.pvfCreateChannel; 128 else 129 { 130 IFDH_create_channel = 131 rContext->psFunctions.psFunctions_v3.pvfCreateChannel; 132 IFDH_create_channel_by_name = 133 rContext->psFunctions.psFunctions_v3.pvfCreateChannelByName; 134 } 135 #endif 136 137 /* LOCK THIS CODE REGION */ 138 (void)SYS_MutexLock(rContext->mMutex); 139 140 #ifndef PCSCLITE_STATIC_DRIVER 141 if (rContext->dwVersion == IFD_HVERSION_1_0) 142 { 143 rv = (*IO_create_channel) (rContext->dwPort); 144 } else if (rContext->dwVersion == IFD_HVERSION_2_0) 145 { 146 rv = (*IFDH_create_channel) (rContext->dwSlot, rContext->dwPort); 147 } else 148 { 149 /* use device name only if defined */ 150 if (rContext->lpcDevice[0] != '/0') 151 rv = (*IFDH_create_channel_by_name) (rContext->dwSlot, rContext->lpcDevice); 152 else 153 rv = (*IFDH_create_channel) (rContext->dwSlot, rContext->dwPort); 154 } 155 #else 156 if (rContext->dwVersion == IFD_HVERSION_1_0) 157 { 158 rv = IO_Create_Channel(rContext->dwPort); 159 } else if (rContext->dwVersion == IFD_HVERSION_2_0) 160 { 161 rv = IFDHCreateChannel(rContext->dwSlot, rContext->dwPort); 162 } else 163 { 164 /* Use device name only if defined */ 165 if (rContext->lpcDevice[0] != '/0') 166 rv = IFDHCreateChannelByName(rContext->dwSlot, rContext->lpcDevice); 167 else 168 rv = IFDHCreateChannel(rContext->dwSlot, rContext->dwPort); 169 } 170 #endif 171 172 /* END OF LOCKED REGION */ 173 (void)SYS_MutexUnLock(rContext->mMutex); 174 175 return rv; 176 } |
原来这个函数的目的是调用3个版本之一的create channel.
30 #undef PCSCLITE_STATIC_DRIVER |
所以说155~170没有真正编译。
117~119定义了函数指针。
120~135行,根据版本,正确初始化函数指针。
136~154行,调用函数指针所在的函数。
RFInitializeReader解说完成。
回到readerfatory.c
229 rv = RFInitializeReader(sReadersContexts[dwContext]); 230 if (rv != SCARD_S_SUCCESS) 231 { 232 /* Cannot connect to reader. Exit gracefully */ 233 Log2(PCSC_LOG_ERROR, "%s init failed.", lpcReader); 234 (void)RFRemoveReader(lpcReader, dwPort); 235 return rv; 236 } |
234行,RFRemoveReader.想想,它做什么,难道是从reader上下文数组中踢出不要的元素。
RFRemoveReader定义在readerfactory.c.少不了一个遍历。
实现如下:
402 LONG RFRemoveReader(LPSTR lpcReader, DWORD dwPort) 403 { 404 LONG rv; 405 PREADER_CONTEXT sContext; 406 407 if (lpcReader == 0) 408 return SCARD_E_INVALID_VALUE; 409 410 while (SCARD_S_SUCCESS == 411 RFReaderInfoNamePort(dwPort, lpcReader, &sContext)) 412 { 413 int i; 414 415 /* Try to destroy the thread */ 416 rv = EHDestroyEventHandler(sContext); 417 418 rv = RFUnInitializeReader(sContext); 419 if (rv != SCARD_S_SUCCESS) 420 return rv; 421 |
411行, RFReaderInfoNamePort根据dwPort和lpcReader从reader上下文数组中去寻找对应的元素。无论是否共用一个驱动,从RFAddReader前部,可以知道无法加入名字和端口都一样的reader.
RFReaderInfoNamePort定义在readerfactory.c
实现如下:
687 LONG RFReaderInfoNamePort(DWORD dwPort, LPSTR lpcReader, 688 PREADER_CONTEXT * sReader) 689 { 690 char lpcStripReader[MAX_READERNAME]; 691 int i; 692 693 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 694 { 695 if ((sReadersContexts[i])->vHandle != 0) 696 { 697 int tmplen; 698 699 strncpy(lpcStripReader, (sReadersContexts[i])->lpcReader, 700 sizeof(lpcStripReader)); 701 tmplen = strlen(lpcStripReader); 702 lpcStripReader[tmplen - 6] = 0; 703 704 if ((strcmp(lpcReader, lpcStripReader) == 0) && 705 (dwPort == (sReadersContexts[i])->dwPort)) 706 { 707 *sReader = sReadersContexts[i]; 708 return SCARD_S_SUCCESS; 709 } 710 } 711 } 712 |
693~712行,根据读卡器名字(不包括读卡器编号和槽号)和端口号,搜索读卡器上下文。
回到RFRemoveReader
的416行,
EHDestroyEventHandler定义在eventhandler.c