PCSC那事儿(二十一--SCardControl)

 

SCardControl

 

SCardControl 定义在 winscard_clnt.c

实现如下:

 

 

 

2365 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,

2366         DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,

2367         LPDWORD lpBytesReturned)

2368 {

2369         LONG rv;

2370         control_struct scControlStruct;

2371         sharedSegmentMsg msgStruct;

2372         int i;

2373         DWORD dwContextIndex, dwChannelIndex;

2374

2375         PROFILE_START

2376

2377         /* 0 bytes received by default */

2378         if (NULL != lpBytesReturned)

2379                 *lpBytesReturned = 0;

2380

 

 

 

2365~2380 行,要多说吗?

2381         rv = SCardCheckDaemonAvailability();

2382         if (rv != SCARD_S_SUCCESS)

2383                 return rv;

2384

2385         /*

2386          * Make sure this handle has been opened

2387          */

2388         rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);

2389         if (rv == -1)

2390                 return SCARD_E_INVALID_HANDLE;

2391

2392         (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);

2393

2394         /* check the handle is still valid */

2395         rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);

2396         if (rv == -1)

2397                 /* the handle is now invalid

2398                  * -> another thread may have called SCardReleaseContext

2399                   * -> so the mMutex has been unlocked */

2400                 return SCARD_E_INVALID_HANDLE;

2401

 

 

2381~2401 行,上面提过了。

问:有不少代码重复。

答案是,可以考虑 refator. 说说而已。

 

2402         for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)

2403         {

2404                  char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;

2405

2406                 /* by default r == NULL */

2407                 if (r && strcmp(r, (readerStates[i])->readerName) == 0)

2408                         break;

2409         }

2410

2411         if (i == PCSCLITE_MAX_READERS_CONTEXTS)

2412         {

2413                 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);

2414                 return SCARD_E_READER_UNAVAILABLE;

2415         }

2416

2417         if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)

2418                 || (cbRecvLength > MAX_BUFFER_SIZE_EXTENDED))

2419         {

2420                 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);

2421                 return SCARD_E_INSUFFICIENT_BUFFER;

2422         }

 

 

 

2402~2422 行, 豁然回首月明中,雕栏玉砌应犹在 ...”

看看这些在 SCardTransmit 都有。不用重复解说了。

 

2423

2424         if ((cbSendLength > MAX_BUFFER_SIZE) || (cbRecvLength > MAX_BUFFER_SIZE))

2425         {

2426                 /* extended control */

2427                 unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED];

2428                 control_struct_extended *scControlStructExtended = (control_struct_extended *)buffer;

 

2429                 sharedSegmentMsg *pmsgStruct = (psharedSegmentMsg)buffer;

2430

2431                  scControlStructExtended->hCard = hCard;

2432                 scControlStructExtended->dwControlCode = dwControlCode;

2433                 scControlStructExtended->cbSendLength = cbSendLength;

2434                 scControlStructExtended->cbRecvLength = cbRecvLength;

2435                 scControlStructExtended->dwBytesReturned = 0;

2436                 scControlStructExtended->rv = SCARD_S_SUCCESS;

2437                 /* The size of data to send is the size of

2438                  * struct control_struct_extended WITHOUT the data[] field

2439                  * plus the effective data[] size

2440                  */

2441                 scControlStructExtended->size = sizeof(*scControlStructExtended)

2442                         - (sizeof(control_struct_extended) - offsetof(control_struct_extended, data))

2443                         + cbSendLength;

2444                  memcpy(scControlStructExtended->data, pbSendBuffer, cbSendLength);

 

 

 

2423~2444 行,这个是?好像在哪里看过。对了还是在 SCardTransmit 收发长 APDU

的时候。

上面提到了

APDU 用到的那两种结构。发送采用 transmit_struct_extended

结构,接收采用 sharedSegmentMsg 结构, data 域内嵌 transmit_struct_extended 结构。

相比,短 APDU 也用到了两种结构。发送采用 transmit_struct 结构,接收采用 sharedSegmentMsg 结构, data 域内嵌 transmit_struct

 

对于 SCardControl ,采用一样的策略,但不同的结构体。

想到什么了?没法使用模板,这里采用了 c

 

APDU 用到了两种结构。发送采用 control_struct_extended

结构,接收采用 sharedSegmentMsg 结构, data 域内嵌 control_struct_extended 结构。

相比,短 APDU 也用到了两种结构。发送采用 control_struct 结构,接收采用 sharedSegmentMsg 结构, data 域内嵌 control_struct

 

 

control_struct 定义在 winscard_msg.h

  struct control_struct

        {

                int32_t hCard;

                uint32_t dwControlCode;

                uint8_t pbSendBuffer[MAX_BUFFER_SIZE];

 

                uint32_t cbSendLength;

                uint8_t pbRecvBuffer[MAX_BUFFER_SIZE];

                uint32_t cbRecvLength;

                 uint32_t dwBytesReturned;

                uint32_t rv;

        };

        typedef struct control_struct control_struct;

 

 

 

 

control_struct_extended 定义在 winscard_msg.h

  struct control_struct_extended

        {

                int32_t hCard;

                uint32_t dwControlCode;

                uint32_t cbSendLength;

                uint32_t cbRecvLength;

                uint32_t dwBytesReturned;

                 uint32_t rv;

                uint64_t size;

                uint8_t data[1];

        };

        typedef struct control_struct_extended control_struct_extended;

 

2445

2446                 rv = WrapSHMWrite(SCARD_CONTROL_EXTENDED,

2447                          psContextMap[dwContextIndex].dwClientID,

2448                         scControlStructExtended->size,

2449                         PCSCLITE_CLIENT_ATTEMPTS, buffer);

2450

2451                 if (rv == -1)

2452                 {

2453                          (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);

2454                         return SCARD_E_NO_SERVICE;

2455                 }

2456

2457                 /*

2458                  * Read a message from the server

2459                   */

2460                 /* read the first block */

2461                 rv = SHMMessageReceive(buffer, sizeof(sharedSegmentMsg),

 

2462                         psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);

2463                 if (rv == -1)

2464                 {

2465                         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);

2466                         return SCARD_F_COMM_ERROR;

2467                 }

2468

2469                 /* we receive a sharedSegmentMsg and not a control_struct_extended */

2470                 scControlStructExtended = (control_struct_extended *)&(pmsgStruct -> data);

2471

2472                 /* a second block is present */

2473                 if (scControlStructExtended->size > PCSCLITE_MAX_MESSAGE_SIZE)

2474                 {

2475                         rv = SHMMessageReceive(buffer + sizeof(sharedSegmentMsg),

2476                                 scControlStructExtended->size-PCSCLITE_MAX_MESSAGE_SIZE,

2477                                  psContextMap[dwContextIndex].dwClientID,

2478                                 PCSCLITE_CLIENT_ATTEMPTS);

2479                         if (rv == -1)

2480                         {

2481                                 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);

2482                                 return SCARD_F_COMM_ERROR;

2483                         }

2484                 }

2485

2486                 if (scControlStructExtended -> rv == SCARD_S_SUCCESS)

2487                 {

2488                         /*

2489                          * Copy and zero it so any secret information is not leaked

2490                          */

2491                         memcpy(pbRecvBuffer, scControlStructExtended -> data,

2492                                  scControlStructExtended -> dwBytesReturned);

2493                         memset(scControlStructExtended -> data, 0x00,

2494                                 scControlStructExtended -> dwBytesReturned);

2495                 }

2496

2497                  if (NULL != lpBytesReturned)

2498                         *lpBytesReturned = scControlStructExtended -> dwBytesReturned;

2499

2500                 rv = scControlStructExtended -> rv;

2501          }

 

 

 

2445~2501 行,长 APDU 处理完成。方法和 SCardTransmit 的长 APDU 一样。

仅仅是方法处理的数据结构不同。您会想到 模板 的好。

 

2502         else

2503         {

2504                 scControlStruct.hCard = hCard;

2505                 scControlStruct.dwControlCode = dwControlCode;

2506                 scControlStruct.cbSendLength = cbSendLength;

2507                 scControlStruct.cbRecvLength = cbRecvLength;

2508                 memcpy(scControlStruct.pbSendBuffer, pbSendBuffer, cbSendLength);

2509

2510                 rv = WrapSHMWrite(SCARD_CONTROL,

2511                          psContextMap[dwContextIndex].dwClientID,

2512                         sizeof(scControlStruct), PCSCLITE_CLIENT_ATTEMPTS, &scControlStruct);

2513

2514                 if (rv == -1)

2515                 {

2516                         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);

2517                         return SCARD_E_NO_SERVICE;

2518                 }

2519

2520                 /*

2521                  * Read a message from the server

2522                  */

2523                  rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,

2524                         PCSCLITE_CLIENT_ATTEMPTS);

2525

2526                 if (rv == -1)

2527                 {

2528                         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);

2529                         return SCARD_F_COMM_ERROR;

2530                 }

2531

2532                 memcpy(&scControlStruct, &msgStruct.data, sizeof(scControlStruct));

2533

2534                 if (NULL != lpBytesReturned)

2535                         *lpBytesReturned = scControlStruct.dwBytesReturned;

2536

2537                 if (scControlStruct.rv == SCARD_S_SUCCESS)

 

2538                 {

2539                         /*

2540                          * Copy and zero it so any secret information is not leaked

2541                          */

2542                         memcpy(pbRecvBuffer, scControlStruct.pbRecvBuffer,

2543                                 scControlStruct.cbRecvLength);

2544                         memset(scControlStruct.pbRecvBuffer, 0x00,

2545                                 sizeof(scControlStruct.pbRecvBuffer));

2546                 }

2547

2548                 rv = scControlStruct.rv;

2549         }

2550

2551         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);

2552

2553         PROFILE_END(rv)

2554

2555         return rv;

2556 }

 

 

 

2502~2556 行,短 APDU 的处理。方法和 SCardTransmit 中短 APDU 的处理一样。

仅仅是方法处理的数据结构不同。

 

APDU 的处理还是比较有技巧的。通过一次发,两次收,就可以收到 PCSCLITE_MAX_MESSAGE_SIZE MAX_BUFFER_SIZE_EXTENDED 这么长的交互数据。

或许会想到,要这么麻烦,结构嵌套结构?可以第一次仅仅返回数据长度,第二次返回所有数据。前面提到了, testpcsc pcscd 之间采用 socket 通讯,虽然这里仅仅是一次发 ( 实际有可能是两次,详细见发送函数 WrapSHMWrite ) ,两次收,但对于底层来说,可能会被分解为多次的发,多次的收。如果第一次仅仅返回数据长度,这么小的信息量也要收一次,则发送效率比较低。所以第一次收的时候,除了返回数据长度,也返回了最大 PCSCLITE_MAX_MESSAGE_SIZE 长度的数据。

 

 

SCardControl 解说结束。

回头,回头。

 

回到 testpcsc.c

 

 

 

 

 

276         test_rv(rv, hContext, DONT_PANIC);

277

278         printf("Testing SCardGetAttrib/t/t: ");

279 #ifdef USE_AUTOALLOCATE

280         pcbAttrLen = SCARD_AUTOALLOCATE;

281         rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, (unsigned char *)&pbAttr,

282                 &pcbAttrLen);

283 #else

284         rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, NULL, &pcbAttrLen);

285         test_rv(rv, hContext, DONT_PANIC);

286         if (rv == SCARD_S_SUCCESS)

287         {

288                 printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld/n" NORMAL , pcbAttrLen);

289                 pbAttr = malloc(pcbAttrLen);

290         }

291

292         printf("Testing SCardGetAttrib/t/t: ");

293         rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, pbAttr, &pcbAttrLen);

294 #endif

 

 

 

 

 

281~282

  rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, (unsigned char *)&pbAttr,

  &pcbAttrLen);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值