4

Windows >= XP で使用する PCSC リーダーへのハンドルとコンテキストのみを持っているwinscard場合、そのデバイス インスタンス ID を取得する方法や、SetupDi*API で使用して、そのリーダーに読み込まれているドライバーを特定する方法はありますか。

SCardGetReaderDeviceInstanceIdWindows 8 でしか利用できないため、残念ながら私には利用できません。

SetupDiプラン B として、スマート カード リーダー クラス GUID を使用して、すべてのスマート カード リーダーを列挙できます。しかし、API とAPIの間でリーダーを関連付けるためには、一意の属性が必要になります。たとえば、シリアル番号は良い候補のように思えますが、すべてのメーカーが使用しているわけではありません。SCard*SetupDi*

何か案は?

4

2 に答える 2

2

SCard を Setup と一致させる 1 つの方法は、ドライバーを開き、IOCTL_SMARTCARD_GET_ATTRIBUTE を使用して SCARD_ATTR_DEVICE_SYSTEM_NAME をクエリし、SCard API を介して一致させることです。

小さな問題が 1 つだけあります。スマートカード サービスは、共有せずにすべてのスマートカード ドライバーを開きます。デバイス ドライバを開く前に、まず Smartcard サービスを停止する必要があります。

もう 1 つの解決策は、SCardControl 関数を使用して、SCard API 内から IOCTL_xxx 呼び出しを介してドライバーを呼び出すことです。

ここでの問題は、今のところ Setup API の任意のプロパティと一致させるために使用できる IOCTL_xxx 呼び出しが見つからないことです。

サポートされている IOCTL_xxx 呼び出しをスキャンするためにブルート フォース ループを試みましたが、そうすると SCard API がクラッシュし、失敗したすべての IOCTL_xxx 呼び出しがイベント ビューアに報告されます。

- アップデート -

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 のいずれかからスマートカード デバイス名を生成するコードで、2 つのメソッド間の類似性を示しています。

//------------------------------------------------------------------------------
// 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;
}
于 2017-03-14T23:34:55.153 に答える