如何找到一个PCSC阅读器的设备实例ID(How to find the device instan

2019-08-06 06:54发布

由于只有使用手柄和上下文的PCSC阅读器winscard在Windows> = XP,有没有办法让可以在使用其设备实例ID或其他东西SetupDi* API来找出是哪个驱动程序加载所述阅读器。

SCardGetReaderDeviceInstanceId是仅适用于Windows 8提供,所以很遗憾不适合我。

作为B计划,所有的智能卡读取器可以在列举SetupDi使用智能卡阅读器类GUID。 但我需要一个独特的属性能够与读者相关SCard* API和SetupDi* API。 例如,序列号听起来是个不错的人选,但不是所有的制造商都使用它。

有任何想法吗?

Answer 1:

与设置匹配SCARD一种方法是打开驱动程序,然后使用IOCTL_SMARTCARD_GET_ATTRIBUTE查询SCARD_ATTR_DEVICE_SYSTEM_NAME并通过SCARD API的一个匹配。

只有一个很小的问题。 智能卡服务打开所有的智能卡驱动程序,而共享。 首先,您需要能够打开设备驱动程序之前停止智能卡服务。

另一种解决方案是使用SCardControl函数调用驱动程序通过IOCTL_xxx从SCARD API中调用。

这里的问题是,直至目前为止我还没有找到一个IOCTL_xxx电话,我可以使用,以配合从安装程序API的任何财产。

这样做的时候,并报告所有的失败IOCTL_xxx调用事件查看器中我尝试了蛮力循环扫描支持IOCTL_xxx调用但SCARD API崩溃。

- 更新 -

该IOCTL支持以下标签:

SCARD_ATTR_VENDOR_NAME SCARD_ATTR_VENDOR_IFD_TYPE SCARD_ATTR_VENDOR_IFD_VERSION SCARD_ATTR_CHANNEL_ID SCARD_ATTR_PROTOCOL_TYPES SCARD_ATTR_DEFAULT_CLK SCARD_ATTR_MAX_CLK SCARD_ATTR_DEFAULT_DATA_RATE SCARD_ATTR_MAX_DATA_RATE SCARD_ATTR_MAX_IFSD SCARD_ATTR_POWER_MGMT_SUPPORT SCARD_ATTR_CHARACTERISTICS SCARD_ATTR_ICC_PRESENCE SCARD_ATTR_ICC_INTERFACE_STATUS SCARD_ATTR_DEVICE_UNIT

下面是产生从任一IOCTL智能卡设备名称的代码,并经由SCARD也证明两种方法之间的simularity

//------------------------------------------------------------------------------
// PROTOTYPES
//------------------------------------------------------------------------------

/* get the Smartcard DeviceName via IOCTL calls */
BOOL Smc_GetDeviceNameViaIOCTL(HANDLE,TCHAR*,UINT);

/* get the Smartcard DeviceName via SCARD calls */
BOOL Smc_GetDeviceNameViaSCARD(SCARDHANDLE,TCHAR*,UINT);





//------------------------------------------------------------------------------
// IMPLEMENTATIONS
//------------------------------------------------------------------------------




/************************************************/
/* get the Smartcard DeviceName via IOCTL calls */
/************************************************/

BOOL Smc_GetDeviceNameViaIOCTL(HANDLE in_hDev, TCHAR *out_Name, UINT in_MaxLen)
{
    /* locals */
    UINT  lv_Pos;
    DWORD lv_InBuf;
    DWORD lv_ValLen;
    DWORD lv_ChanID;
    CHAR  lv_OutBuf[256];
    BOOL  lv_Result;


  // reserve space for eos
  if (in_MaxLen-- <= 0)
    return FALSE;

  // init the position
  lv_Pos = 0;

  // set the tag
  lv_InBuf = SCARD_ATTR_VENDOR_NAME;

  // get the value
  lv_Result = DeviceIoControl(
    in_hDev, IOCTL_SMARTCARD_GET_ATTRIBUTE,
    &lv_InBuf, sizeof(DWORD), lv_OutBuf, 256, &lv_ValLen, 0);

  // fail?
  if (!lv_Result)
    return FALSE;

  // check the length, including space
  if (lv_Pos + lv_ValLen + 1 > in_MaxLen)
    return FALSE;

  // append to output
  AChar2TCharCL(lv_OutBuf, lv_ValLen, &out_Name[lv_Pos], in_MaxLen-lv_Pos);

  // update position
  lv_Pos += lv_ValLen;

  // append space
  out_Name[lv_Pos++] = ' ';

  // set the tag
  lv_InBuf = SCARD_ATTR_VENDOR_IFD_TYPE;

  // get the value
  lv_Result = DeviceIoControl(
    in_hDev, IOCTL_SMARTCARD_GET_ATTRIBUTE,
    &lv_InBuf, sizeof(DWORD), lv_OutBuf, 256, &lv_ValLen, 0);

  // fail?
  if (!lv_Result)
    return FALSE;

  // check the length, including space
  if (lv_Pos + lv_ValLen + 1 > in_MaxLen)
    return FALSE;

  // append to output
  AChar2TCharCL(lv_OutBuf, lv_ValLen, &out_Name[lv_Pos], in_MaxLen-lv_Pos);

  // update position
  lv_Pos += lv_ValLen;

  // append space
  out_Name[lv_Pos++] = ' ';

  // set the tag
  lv_InBuf = SCARD_ATTR_DEVICE_UNIT; 

  // get the value
  lv_Result = DeviceIoControl(
    in_hDev, IOCTL_SMARTCARD_GET_ATTRIBUTE,
    &lv_InBuf, sizeof(DWORD), &lv_ChanID, sizeof(DWORD), &lv_ValLen, 0);

  // fail?
  if (!lv_Result)
    return FALSE;

  // format as string
  FormatStringA(lv_OutBuf, 256, "%d", lv_ChanID);

  // check the length
  if (lv_Pos + strlenA(lv_OutBuf) > in_MaxLen)
    return FALSE;

  // append to output
  AChar2TCharC(lv_OutBuf, &out_Name[lv_Pos], in_MaxLen-lv_Pos);

  // done
  return TRUE;
}





/************************************************/
/* get the Smartcard DeviceName via SCARD calls */
/************************************************/

BOOL Smc_GetDeviceNameViaSCARD(SCARDHANDLE in_hCard, TCHAR *out_Name, UINT in_MaxLen)
{
    /* locals */
    UINT  lv_Pos;
    DWORD lv_InBuf;
    DWORD lv_ValLen;
    DWORD lv_ChanID;
    CHAR  lv_OutBuf[256];
    UINT  lv_hResult;


  // reserve space for eos
  if (in_MaxLen-- <= 0)
    return FALSE;

  // init the position
  lv_Pos = 0;

  // set the tag
  lv_InBuf  = SCARD_ATTR_VENDOR_NAME;
  lv_ValLen = 256;

  // get the value
  lv_hResult = lib_SCardGetAttrib(in_hCard, lv_InBuf, (BYTE*)lv_OutBuf, &lv_ValLen);

  // fail?
  if (FAILED(lv_hResult))
    return FALSE;

  // check the length, including space
  if (lv_Pos + lv_ValLen + 1 > in_MaxLen)
    return FALSE;

  // append to output
  AChar2TCharCL(lv_OutBuf, lv_ValLen, &out_Name[lv_Pos], in_MaxLen-lv_Pos);

  // update position
  lv_Pos += lv_ValLen;

  // append space
  out_Name[lv_Pos++] = ' ';

  // set the tag
  lv_InBuf  = SCARD_ATTR_VENDOR_IFD_TYPE;
  lv_ValLen = 256;

  // get the value
  lv_hResult = lib_SCardGetAttrib(in_hCard, lv_InBuf, (BYTE*)lv_OutBuf, &lv_ValLen);

  // fail?
  if (FAILED(lv_hResult))
    return FALSE;

  // check the length, including space
  if (lv_Pos + lv_ValLen + 1 > in_MaxLen)
    return FALSE;

  // append to output
  AChar2TCharCL(lv_OutBuf, lv_ValLen, &out_Name[lv_Pos], in_MaxLen-lv_Pos);

  // update position
  lv_Pos += lv_ValLen;

  // append space
  out_Name[lv_Pos++] = ' ';

  // set the tag
  lv_InBuf  = SCARD_ATTR_DEVICE_UNIT;
  lv_ValLen = sizeof(DWORD);

  // get the value
  lv_hResult = lib_SCardGetAttrib(in_hCard, lv_InBuf, (BYTE*)&lv_ChanID, &lv_ValLen);

  // fail?
  if (FAILED(lv_hResult))
    return FALSE;

  // format as string
  FormatStringA(lv_OutBuf, 256, "%d", lv_ChanID);

  // check the length
  if (lv_Pos + strlenA(lv_OutBuf) > in_MaxLen)
    return FALSE;

  // append to output
  AChar2TCharC(lv_OutBuf, &out_Name[lv_Pos], in_MaxLen-lv_Pos);

  // done
  return TRUE;
}


Answer 2:

从我的测试中,它的接缝SCARD服务顺序分配名称:
一个)SPDRP_FRIENDLYNAME如果存在的话
B)SPDRP_DEVICEDESC

这样一来,我可以给SCardListReaders()名称匹配与分辩设备/驱动器。

希望这可以帮助 ...



文章来源: How to find the device instance id of a PCSC reader