SCardTransmit
245 行 SCardTransmit 定义在 winscard_clnt.c
实现如下:
2915 LONG SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci, 2916 LPCBYTE pbSendBuffer, DWORD cbSendLength, 2917 LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer,
2918 LPDWORD pcbRecvLength) 2919 { |
问:为什么从代码解说开始,每个函数 API 都不说明参数和用法?
答案是, 这些 API 都是符合 PCSC 规范的。第一章的各卷部分都对应做了说明了。所以不再重复。或者也可以看看源代码的这些函数实现的注释部分,这些参数都有注释说明。注释格式符合 Doxygen 要求。
如果这里重复说明,也就是重复昨天的故事,很罗曼蒂克。一可以增加篇幅,二可以增加工作量,三可以倍显所谓的耐心和专业精神。但此时此地,还是不要。
2920 LONG rv; 2921 int i; 2922 DWORD dwContextIndex, dwChannelIndex; 2923 2924 PROFILE_START 2925 2926 if (pbSendBuffer == NULL || pbRecvBuffer == NULL || 2927 pcbRecvLength == NULL || pioSendPci == NULL) 2928 return SCARD_E_INVALID_PARAMETER; 2929 |
2920~2929 常规检查。
问:上面提到了很多 API 了,实现的前部都有检查。能不能不检查?
答案是,在 c 的世界里,不检查意味着崩溃。意味着用彻夜的调试来消耗生命。不过
目前看,生命没有房价值钱,是吧?在 metaprogram 中可以实现这个想法。如果不接受
检查,那么赶快投入 metaprogram 的怀抱,把运行期的错误转移到编译期。
“ 把一个人的温暖转移到另一个人的胸膛 ” 。
2934 /* 2935 * Make sure this handle has been opened 2936 */ 2937 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex); 2938 if (rv == -1) 2939 { 2940 *pcbRecvLength = 0; 2941 return SCARD_E_INVALID_HANDLE; 2942 } 2943 2944 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 2945 2946 /* check the handle is still valid */
2947 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex); 2948 if (rv == -1) 2949 /* the handle is now invalid 2950 * -> another thread may have called SCardReleaseContext 2951 * -> so the mMutex has been unlocked */ 2952 return SCARD_E_INVALID_HANDLE; 2953 |
2934~2953 行,前面讲过了?似乎?是讲解过类似的片段,讲了 n 次。
但这个片段不太一样。
找出以前的片段对比对比。有对比才有发现,有攀比才有仇富,有发现才会警醒。
1872 LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, 1873 LPSCARD_READERSTATE_A rgReaderStates, DWORD cReaders) |
...
1918 dwContextIndex = SCardGetContextIndice(hContext); 1919 if (dwContextIndex == -1) 1920 return SCARD_E_INVALID_HANDLE; 1921 1922 (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 1923 1924 /* check the context is still opened */ 1925 dwContextIndex = SCardGetContextIndice(hContext); 1926 if (dwContextIndex == -1) 1927 /* the context is now invalid 1928 * -> another thread may have called SCardReleaseContext 1929 * -> so the mMutex has been unlocked */ 1930 return SCARD_E_INVALID_HANDLE; |
重要差别在
一个是
2937 rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex); |
另一个是
1925 dwContextIndex = SCardGetContextIndice(hContext); |
SCardGetContextIndice 上面讲解过了,从 APPLICATION 大佬的 psContextMap 数组
那里获得索引号。
SCardGetIndicesFromHandle 做什么呢?
3740 static LONG SCardGetIndicesFromHandle(SCARDHANDLE hCard, 3741 PDWORD pdwContextIndice, PDWORD pdwChannelIndice) 3742 { 3743 LONG rv; 3744 3745 if (0 == hCard) 3746 return -1; 3747 3748 (void)SCardLockThread(); 3749 rv = SCardGetIndicesFromHandleTH(hCard, pdwContextIndice, pdwChannelIndice); 3750 (void)SCardUnlockThread(); 3751 3752 return rv; 3753 } |
SCardGetIndicesFromHandle 把 SCardGetIndicesFromHandleTH 加锁并做 wrapper.
还是看看 SCardGetIndicesFromHandleTH.
3755 static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE hCard, 3756 PDWORD pdwContextIndice, PDWORD pdwChannelIndice) 3757 { 3758 int i; |