智能卡通讯失败编程,执行SCardTransmit失败.该怎么解决

智能卡应用程序的开发_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
智能卡应用程序的开发
阅读已结束,下载文档到电脑
想免费下载更多文档?
定制HR最喜欢的简历
下载文档到电脑,方便使用
还剩3页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢博客访问: 92203
博文数量: 25
博客积分: 1522
博客等级: 上尉
技术积分: 220
注册时间:
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: C/C++
3.4 向智能卡发送指令
函数ScardTransmit()向智能卡发送指令,并接受返回的数据。
函数原型:LONG SCardTransmit(SCARDHANDLE hCard, LPCSCARD_I0_REQUEST pioSendPci,
LPCBYTE pbSendBuffer, DWORD cbSendLength, LPSCARD_IO_REQUEST pioRecvPci, LPBYTE
pbRecvBuffer, LPDWORD pcbRecvLength);
各个参数的含义:(1)hCard:输入类型;与智能卡连接的句柄。(2)pioSendPci:输入类型;指令的协议头结构的指针,由SCARD_IO_REQUEST结构定义。后面是使用的协议的协议控制信息。一般使用系统定义的结构,SCARD_PCI_T0(T=0协议)、
SCARD_PCI_T1(T=1协议)、SCARD_PCI_RAW(原始协议)。(3)pbSendBuffer:输入类型;要发送到智能卡的数据的指针。(4)cbSendLength:输入类型;pbSendBuffer的字节数目。(5)pioRecvPci:输入输出类型;指令协议头结构的指针,后面是使用的协议的协议控制信息,如果不返回协议控制信息,可以为NULL。(6)pbRecvBuffer:输入输出类型;从智能卡返回的数据的指针。(7)pcbRecvLength:输入输出类型;pbRecvBuffer的大小和实际大小。
对于T=0协议,收发缓冲的用法如下:
(a)向智能卡发送数据:要向智能卡发送n&0字节数据时,pbSendBuffer
前4字节分别为T=0的CLA、INS、P1、P2,第5字节是n,随后是n字节的数据;cbSendLength值为n+5(4字节头+1字节Lc+n字节数据)。PbRecvBuffer将接收SW1、SW2状态码;pcbRecvLength值在调用时至少为2,返回后为2。
BYTE&&&&&&& recvBuffer[260];
int&&&&&&&& sendSize, recvS
BTYE&&&&&&& sw1, sw2;
BYTE&&& select_mf[]={0xC0, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00};
sendSize=7;
recvSize=sizeof(recvBuffer);
lReturn = SCardTransmit(hCardHandle[0], SCARD_PCI_T0, select_mf, sendSize,
NULL, recvBuffer, &recvSize);
if ( lReturn != SCARD_S_SUCCESS )
printf("Failed SCardTransmit\n");
//返回的数据,recvSize=2
sw1=recvBuffer[recvSize-2];
sw2=recvBuffer[recvSize-1];
(b)从智能卡接收数据:为从智能卡接收n&0字节数据,pbSendBuffer
前4字节分别为T=0的CLA、INS、P1、P2,第5字节是n(即Le),如果从智能卡接收256字节,则第5字节为0;cbSendLength值为5(4字节头+1字节Le)。PbRecvBuffer将接收智能卡返回的n字节,随后是SW1、SW2状态码;pcbRecvLength的值在调用时至少为
n+2,返回后为n+2。
BYTE&&&&&&& get_challenge[]={0x00, 0x84, 0x00, 0x00, 0x08};
sendSize=5;
recvSize=sizeof(recvBuffer);
lReturn = SCardTransmit(hCardHandle[0], SCARD_PCI_T0, get_challenge,
sendSize, NULL, recvBuffer, &recvSize);
if ( lReturn != SCARD_S_SUCCESS )
printf("Failed SCardTransmit\n");
//返回的数据, recvSize=10
sw1=recvBuffer[recvSize-2];
sw2=recvBuffer[recvSize-1];
//data=recvBuffer[0]----recvBuffer[7]
(c)向智能卡发送没有数据交换的命令:应用程序既不向智能卡发送数据,也不从智能卡接收数据,pbSendBuffer
前4字节分别为T=0的CLA、INS、P1、P2,不发送P3;cbSendLength
值必须为4。PbRecvBuffer从智能卡接收SW1、SW2状态码;pcbRecvLength值在调用时至少为2,返回后为2。
BYTE&&& set_flag[]={0x80, 0xFE, 0x00, 0x00};
sendSize=4;
recvSize=sizeof(recvBuffer);
lReturn = SCardTransmit(hCardHandle[0], SCARD_PCI_T0, set_flag, sendSize,
NULL, recvBuffer, &recvSize);
if ( lReturn != SCARD_S_SUCCESS )
printf("Failed SCardTransmit\n");
//返回的数据,recvSize=2
sw1=recvBuffer[recvSize-2];
sw2=recvBuffer[recvSize-1];
(d)向智能卡发送具有双向数据交换的命令:T=0协议中,应用程序不能同时向智能卡发送数据,并从智能卡接收数据,即发送到智能卡的指令中,不能同时有Lc和Le。这只能分两步实现:向智能卡发送数据,接收智能卡返回的状态码,其中,SW2是智能卡将要返回的数据字节数目;从智能卡接收数据(指令为0x00、0xC0、0x00、0x00、Le)。
BYTE&&& get_response={0x00, 0xc0, 0x00, 0x00, 0x00};
BYTE&&& internal_auth[]={0x00, 0x88, 0x00, 0x00, 0x08, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07, 0x08};
sendSize=13;
recvSize=sizeof(recvBuffer);
lReturn = SCardTransmit(hCardHandle[0], SCARD_PCI_T0, internal_auth,
sendSize, NULL, recvBuffer, &recvSize);
if ( lReturn != SCARD_S_SUCCESS )
printf("Failed SCardTransmit\n");
//返回的数据,recvSize=2
sw1=recvBuffer[recvSize-2];
sw2=recvBuffer[recvSize-1];
&&& if ( sw1!=0x61 )
printf("Failed Command\n");
get_response[4]=sw2;
sendSize=5;
recvSize=sizeof(recvBuffer);
lReturn = SCardTransmit(hCardHandle[0], SCARD_PCI_T0, get_response,
sendSize, NULL, recvBuffer, &recvSize);
if ( lReturn != SCARD_S_SUCCESS )
printf("Failed SCardTransmit\n");
//返回的数据,recvSize=10
sw1=recvBuffer[recvSize-2];
sw2=recvBuffer[recvSize-1];
//data=recvBuffer[0]----recvBuffer[7]
3.5 断开与读卡器(智能卡)的连接
在与智能卡的数据交换完成后,可以使用函数ScardDisconnect()终止应用与智能卡之间的连接。
函数原型:LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition);
各个参数的含义:(1)hCard:输入类型;与智能卡连接的句柄。(2)dwDisposition:输入类型;断开连接时,对智能卡的操作,SCARD_LEAVE_CARD(不做任何操作)、SCARD_RESET_CARD(复位智能卡)、SCARD_UNPOWER_CARD(给智能卡掉电)、SCARD_EJECT_CARD(弹出智能卡)。
下面是断开与智能卡连接的代码:
lReturn = SCardDisconnect(hCardHandle[0], SCARD_LEAVE_CARD);
if ( lReturn != SCARD_S_SUCCESS )
printf("Failed SCardDisconnect\n");
3.6 释放资源管理上下文
&&& 在应用程序终止前时,应该调用函数ScardReleaseContext()释放资源管理器的上下文。
函数原型:LONG SCardReleaseContext(SCARDCONTEXT hContext);
各个参数含义:(1)hContext:输入类型;ScardEstablishContext()建立的资源管理器上下文的句柄,不能为NULL。
下面是释放资源管理上下文的代码:
lReturn = SCardReleaseContext(hSC);
if ( lReturn!=SCARD_S_SUCCESS )
printf("Failed SCardReleaseContext\n");
以上介绍的通过PC/SC来操作智能卡的流程,可以封装在一个类中。例如,我们可以设计一个类:
class CSmartReader
SCARDCONTEXT&&& hSC;
LONG&&&&&&&&&&& lR
char&&&&&&&&&&& mszReaders[1024];
LPTSTR&&&&&&&&& pReader, pReaderName[2];
DWORD&&&&&&&&&& dwL
int&&&&&&&&&&&& nReaders, nCurrentR
SCARDHANDLE&&&& hCardHandle[2];
DWORD&&&&&&&&&& dwAP;
&&& CSmartReader(); //建立上下文、取读卡器列表
&&& ~CSmartReader(); //释放上下文
&&& void SetCurrentReader(int currentReader);
&&& int GetReaders(); //获得读卡器数目
&&& int ConnectReader(); //与当前读卡器建立连接
&&& int DisConnectReader(); //与当前读卡器断开连接
&&& int SendCommand(BYTE command[], int commandLength, BYTE result[], int
*resultLength); //向读卡器发送命令,并接收返回的数据。返回值为sw
&&& 这样,我们就可以方便地使用PC/SC接口了。
作者:蒋遂平。
联系方式:、。
阅读(3872) | 评论(4) | 转发(0) |
相关热门文章
给主人留下些什么吧!~~
蒋老师您好,我有一个问题想请教您,我想知道如果智能卡的通讯协议使用的是T=1的话,那再使用ScardTransmit函数向智能卡发送指令,和接收数据的时候,和T=0协议下的有什么区别啊?
蒋老师您好,我有一个问题想请教您,我想知道如果智能卡的通讯协议使用的是T=1的话,那再使用ScardTransmit函数向智能卡发送指令,和接收数据的时候,和T=0协议下的有什么区别啊?
蒋老师您好,我有一个问题想请教您,我想知道如果智能卡的通讯协议使用的是T=1的话,那再使用ScardTransmit函数向智能卡发送指令,和接收数据的时候,和T=0协议下的有什么区别啊?
蒋老师您好,我有一个问题想请教您,我想知道如果智能卡的通讯协议使用的是T=1的话,那再使用ScardTransmit函数向智能卡发送指令,和接收数据的时候,和T=0协议下的有什么区别啊?
请登录后评论。您在基于 Windows 7 的或基于 Windows Server 2008 R2 的计算机上读取器中插入智能卡时出现错误消息:&设备驱动程序软件未能成功安装&
时间: 20:17:14
&&&& 阅读:1255
&&&& 评论:
&&&& 收藏:0
当智能卡插入智能卡阅读器后时,Windows 尝试下载并安装智能卡 minidrivers 通过插服务卡。如果自定义的加密服务提供程序未在系统上安装智能卡的驱动程序在任一预配置位置,如 Windows 更新、 WSUS 或 intranet 路径不可用,在通知区域中将收到以下错误消息:
未能成功安装设备驱动程序软件有关详细信息,请单击此处。
此错误消息在几秒钟后就会消失。另外,设备管理器中,在其他设备下的智能卡设备的"DNF"(没有找到驱动程序) 的状态。这通常需要用户从智能卡颁发者若要解决此错误获得以下各项之一:
Windows logoed 智能卡微型驱动程序
智能卡自定义的加密服务提供程序 (CSP)。
Windows 非 logoed 智能卡微型驱动程序
其他如 ActiveX 控件、 PKCS #11 软件或其他自定义软件的中间件。
但是,如果用户提供唯一 3 或 4,从该列表中的项,智能卡会继续在系统正常工作。但是,该用户将收到错误消息中提到这一节每次它们插入智能卡。此问题影响到所有版本的 Windows 7 中,Windows Server 2008 R2,和更高版本的这两个操作系统。
所有智能卡都需要附加软件才能在 Windows 中工作,除非有一个收件箱驱动程序,允许用户无需安装其他软件使用的卡。在 Windows 7 中以启用自动下载智能卡 minidrivers 从 Windows Update 或其他类似的位置,如一个 WSUS 服务器,智能卡插入到阅读器时,Windows 智能卡框架已经过改进。所有成功通过徽标要求,通过 Windows 徽标计划,发布的智能卡从该功能中受益。但是,如果在 Windows 中使用智能卡所需的软件不是 logoed 或者是微型驱动程序,例如 PKCS #11 驱动程序、 自定义的 CSP、 中间件或一个 ActiveX 控件,与不同类型的自动下载选项失败因为 Microsoft 认证只智能卡 minidrivers。因此,如果在用户插入的卡为其自定义 CSP 没有注册,用户会收到一条错误消息,指出尽管用户可以使用智能卡上通过自定义安装从用户的计算机已安装的其他软件是丢失的智能卡设备的驱动程序软件。
尽管智能卡继续忽略用户可以看到此错误消息的工作,智能卡颁发者、 供应商或制造商可以使用以下方法之一来纠正此错误。
我们建议卡颁发者、 供应商和制造商实施智能卡 minidrivers,并加入 Windows 徽标计划从中受益 (如智能卡插,智能卡设备贴图层平台中引入了改进,等等。有关智能卡用于 Windows 的微型驱动程序规范的详细信息,请访问下面的 Microsoft Web 站点:
有关如何开始使用获取您的智能卡 minidrivers 的徽标的过程的详细信息,请访问下面的 Windows 徽标计划 Web 站点:
如果自定义软件 (这些 PKCS #11 驱动程序、 ActiveX 控件或一些其他中间件是需要能够在 Windows 中,智能卡的使用和实施智能卡的微型驱动程序或自定义的 CSP 不是可行的办法,我们建议卡颁发者、 供应商或制造商应考虑提交空到 Windows 更新的驱动程序。确保空驱动程序在 Windows Update 上可用的典型过程需要通过 Winqual 的成功未分类的设备提交。如果将来,没有可供这些卡的微型驱动程序,可以通过 Windows 徽标计划加入到 Windows Update 上载新的驱动程序。空的驱动程序之后可以由最终用户手动下载,或可通过使用可选更新可用。
下面是空的智能卡的驱动程序的一个示例模板。
; Null Driver for Fabrikam Smartcard installation x86 and x64 package.
Signature="$Windows NT$"
Class=SmartCard
ClassGuid={990A2BD7-E738-46c7-B26F-1CF8FB9F1391}
Provider=%ProviderName%
CatalogFile=delta.cat
DriverVer=4/21/2006,1.0.0.0
[Manufacturer]
%ProviderName%=Minidriver,NTamd64,NTamd64.6.1,NTx86,NTx86.6.1
[Minidriver.NTamd64]
;This driver has no applicability on OS versions earlier than Windows 7
[Minidriver.NTx86]
;This driver has no applicability on OS versions earlier than Windows 7
[Minidriver.NTamd64.6.1]
%CardDeviceName%=Minidriver64_Install,&DEVICE_ID&
;%CardDeviceName%=Minidriver64_Install,&DEVICE_ID2&
;%CardDeviceName%=Minidriver64_Install,&DEVICE_ID3&
[Minidriver.NTx86.6.1]
%CardDeviceName%=Minidriver32_Install,&DEVICE_ID&
;%CardDeviceName%=Minidriver32_Install,&DEVICE_ID2&
;%CardDeviceName%=Minidriver32_Install,&DEVICE_ID3&
;Leave the following sections blank
[DefaultInstall]
[DefaultInstall.ntamd64]
[DefaultInstall.NTx86]
[DefaultInstall.ntamd64.6.1]
[DefaultInstall.NTx86.6.1]
[Minidriver64_Install.NT]
[Minidriver64_61_Install.NT]
[Minidriver32_Install.NT]
[Minidriver32_61_Install.NT]
[Minidriver64_61_Install.NT.Services]
AddService = ,2
[Minidriver32_61_Install.NT.Services]
AddService = ,2
; =================== Generic ==================================
ProviderName ="Microsoft"
CardDeviceName="Fabrikam Generic Smart card"
若要生成示例中的 DEVICE_ID 字符串引用的硬件设备 ID,请按照中微型驱动程序智能卡的技术指标的说明进行操作。若要执行此操作,请访问下面的 Microsoft 网站:
有关如何提交到 Microsoft 的空驱动程序的详细信息,请与 Microsoft 客户支持服务联系。
此选项仅对管理员和所有必要的软件以使用企业中正在使用智能卡使用安装的软件管理工具 (如 SMS),管理计算机的企业部署建议。因为这将影响您的环境中的所有智能卡,此过程是强烈建议您不要在以下环境中:
面向最终用户,如网上银行的商业部署
包含这两个环境插智能卡和使用组策略来禁用智能卡插的非即插智能卡
可以完全禁用智能卡插在最终用户的计算机由组策略等机制的企业。如果您的部署使用仅非即插智能卡解决方案,客户端计算机上的本地管理员可以禁用智能卡插。禁用智能卡插可以阻止智能卡的驱动程序,也称为智能卡 minidrivers,下载。它还可以防止智能卡插提示。要禁用智能卡插在本地组策略,请执行以下步骤:
单击开始,在搜索程序和文件框中,键入gpedit.msc&,然后按 enter 键。
在控制台树中在计算机配置下,单击管理模板。
在详细信息窗格中,双击Windows 组件,然后双击智能卡。
请用鼠标右键单击启用智能卡插服务,然后单击编辑。
单击被禁用,然后单击确定。
这是最推荐的选项。只有卡的旧卡并没有计划在将来实现智能卡 minidrivers,您应使用此选项。此选项要求在系统已安装的现有软件通知 Windows 没有自定义安装到系统上,即使在最终用户系统中存在任何此类 CSP CSP。只要 Windows 在确定存在一个自定义系统上已安装的 CSP,Windows 不会尝试下载并安装智能卡插到驱动程序。智能卡设备没有设备节点创建在设备管理器中可见。此选项导致对系统注册表的以下更改:子项:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\ & 智能卡名称 &
子项的注册表项:
ATR = 十六进制的 dword 值: ATR 的智能卡,以逗号分隔。
ATRMask = 十六进制的 dword 值: 要到 ATR 在无意义的字节以遮盖 ATR 应用蒙板,以逗号分隔。
加密提供程序 = 字符串值: 某些与智能卡相关的字符串。
例如:子项:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\Fabrikam ATM 卡
子项的注册表项:
ATR = 十六进制的 dword 值: 3b,dc,13 00、 40,3a,49、 54、 47,5f,4d,53、 43、 53、 50,5f,56、 32
ATRMask = 十六进制的 dword 值: ff、 ff、 ff、 ff、 ff、 ff、 ff、 ff、 ff、 ff、 ff、 ff、 ff、 ff、 ff、 ff、 ff、 ff
加密提供程序 = 字符串值:"Fabrikam ATM Dummy 提供程序"
对于 x 64 位系统,必须在以下注册表子项下进行相同更改:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards我们建议,而不是直接更改系统注册表,您使用 WinSCard Api 引入到系统的这些更改。下面是示例代码示例检测到智能卡插入,然后通过创建将卡与非现有提供程序相关联的注册表项来禁用智能卡插,为特定的卡。Microsoft 提供的编程示例仅用于说明,没有任何明示或暗示的担保。这包括但不限于适销性或特定用途适用性的暗示担保。本文假定您熟悉所演示的编程语言和用于创建和调试过程的工具。Microsoft 的支持工程师可以帮助解释某个特定过程的功能。但是,他们不会修改这些示例以提供额外的功能或构建过程以满足您的特定要求。
//==============================================================;
Disable Smart card Plug and Play for specific cards
This is an example of how to create a new
Smart Card Database entry when a smart card is inserted
into the computer.
This source code is only intended as a supplement to existing Microsoft
documentation.
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED. THIS INCLUDES BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
Copyright (C) Microsoft Corporation.
All Rights Reserved.
//==============================================================;
// This code must be compiled with UNICODE support to work correctly
#ifndef UNICODE
#define UNICODE
#include &windows.h&
#include &winscard.h&
#include &stdio.h&
#include &strsafe.h&
#include &rpc.h&
// Change this prefix to specify what the beginning of the
// introduced card name in the registry will be. This is
// be prepended to a GUID value.
#define CARD_NAME_PREFIX
L"MyCustomCard"
// This is the name that will be provided as the CSP for
// the card when introduced to the system. This is provided
// in order to disable Smart Card Plug and Play for this
#define CARD_CSP
L"$DisableSCPnP$"
// This special reader name is used to be notified when
// a reader is added to or removed from the system through
// SCardGetStatusChange.
#define PNP_READER_NAME
L"\\\\?PnP?\\Notification"
// Maximum ATR length plus alignment bytes. This value is
// used in the SCARD_READERSTATE structure
#define MAX_ATR_LEN
LONG GenerateCardName(
__deref_out LPWSTR
*ppwszCardName)
lReturn = NO_ERROR;
hr = S_OK;
cchFinalString = 0;
wszCardNamePrefix[] = CARD_NAME_PREFIX;
pwszFinalString = NULL;
uuidCardGuid = {0};
pwszCardGuid = NULL;
RPC_STATUS
rpcStatus = RPC_S_OK;
// Parameter check
if (NULL == ppwszCardName)
wprintf(L"Invalid parameter in GenerateCardName.\n");
return ERROR_INVALID_PARAMETER;
// Generate GUID
rpcStatus = UuidCreate(&uuidCardGuid);
if (RPC_S_OK != rpcStatus)
wprintf(L"Failed to create new GUID with error 0x%x.\n");
lReturn = (DWORD)rpcS
// Convert GUID to string
rpcStatus = UuidToString(&uuidCardGuid, &pwszCardGuid);
if (RPC_S_OK != rpcStatus)
wprintf(L"Failed to convert new GUID to string with error 0x%x.\n", rpcStatus);
lReturn = (DWORD)rpcS
// Allocate memory for final string
// Template is &prefix&-&guid&
cchFinalString = (DWORD)(wcslen(wszCardNamePrefix) + 1 + wcslen((LPWSTR)pwszCardGuid) + 1);
pwszFinalString = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, cchFinalString * sizeof(WCHAR));
if (NULL == pwszFinalString)
wprintf(L"Out of memory.\n");
lReturn = ERROR_OUTOFMEMORY;
// Create final string
hr = StringCchPrintf(
pwszFinalString,
cchFinalString,
wszCardNamePrefix,
pwszCardGuid);
if (FAILED(hr))
wprintf(L"Failed to create card name with error 0x%x.\n", hr);
lReturn = (DWORD)
// Set output params
*ppwszCardName = pwszFinalS
pwszFinalString = NULL;
if (NULL != pwszCardGuid)
RpcStringFree(&pwszCardGuid);
if (NULL != pwszFinalString)
HeapFree(GetProcessHeap(), 0, pwszFinalString);
LONG IntroduceCardATR(
__in SCARDCONTEXT
__in LPBYTE
__in DWORD
lReturn = NO_ERROR;
pwszCardName = NULL;
// Parameter checks
if (NULL == hSC || NULL == pbAtr || 0 == cbAtr)
wprintf(L"Invalid parameter in IntroduceCardATR.\n");
return ERROR_INVALID_PARAMETER;
// Generate a name for the card
lReturn = GenerateCardName(&pwszCardName);
if (NO_ERROR != lReturn)
wprintf(L"Failed to generate card name with error 0x%x.\n", lReturn);
// Introduce the card to the system
lReturn = SCardIntroduceCardType(
pwszCardName,
if (SCARD_S_SUCCESS != lReturn)
wprintf(L"Failed to introduce card ‘%s‘ to system with error 0x%x.\n", pwszCardName, lReturn);
// Set the provider name
lReturn = SCardSetCardTypeProviderName(
pwszCardName,
SCARD_PROVIDER_CSP,
CARD_CSP);
if (SCARD_S_SUCCESS != lReturn)
wprintf(L"Failed to set CSP for card ‘%s‘ with error 0x%x.\n", pwszCardName, lReturn);
wprintf(L"Card ‘%s‘ has been successfully introduced to the system and has had Plug and Play disabled.\n", pwszCardName);
if (NULL != pwszCardName)
HeapFree(GetProcessHeap(), 0, pwszCardName);
LONG ProcessCard(
__in SCARDCONTEXT
__in LPSCARD_READERSTATE
lReturn = NO_ERROR;
dwActiveProtocol = 0;
cbAtr = MAX_ATR_LEN;
dwIndex = 0;
cchCards = SCARD_AUTOALLOCATE;
pmszCards = NULL;
rgbAtr[MAX_ATR_LEN] = {0};
SCARDHANDLE hSCard = NULL;
// Parameter checks
if (NULL == hSC || NULL == pRdr)
wprintf(L"Invalid parameter in ProcessCard.\n");
return ERROR_INVALID_PARAMETER;
// Connect to the card in the provided reader in shared mode
lReturn = SCardConnect(
pRdr-&szReader,
SCARD_SHARE_SHARED,
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
&dwActiveProtocol);
if (SCARD_S_SUCCESS != lReturn)
wprintf(L"Failed to connect to card in reader ‘%s‘ with error 0x%x.\n", pRdr-&szReader, lReturn);
wprintf(L"Connected to card in reader ‘%s‘.\n", pRdr-&szReader);
* In this spot, put any necessary calls needed to identify that this
* is the type of card you are looking for. Usually this is done via
* SCardTransmit calls. For this example, we will grab the ATR of every
* inserted card.
// Obtain the ATR of the inserted card
lReturn = SCardGetAttrib(
SCARD_ATTR_ATR_STRING,
if (SCARD_S_SUCCESS != lReturn)
wprintf(L"Failed to obtain ATR of card in reader ‘%s‘ with error 0x%x.\n", pRdr-&szReader, lReturn);
// Output the ATR
wprintf(L"ATR of card in reader ‘%s‘:", pRdr-&szReader);
for (dwIndex = 0; dwIndex & cbA dwIndex++)
wprintf(L" %02x", rgbAtr[dwIndex]);
wprintf(L"\n");
// Determine if the ATR is already in the Smart Card Database
lReturn = SCardListCards(
(LPWSTR)&pmszCards,
&cchCards);
if (SCARD_S_SUCCESS != lReturn)
wprintf(L"Failed to determine if card in reader ‘%s‘ is currently recognized by the system with error 0x%x. Skipping.\n", pRdr-&szReader, lReturn);
else if (NULL == pmszCards || 0 == *pmszCards)
// Card not found. We need to add it.
wprintf(L"Card in reader ‘%s‘ is not currently recognized by the system. Adding ATR.\n", pRdr-&szReader);
lReturn = IntroduceCardATR(
// If an error occurs here, we will continue so we can try the next time
// the card is inserted as well as examine other readers.
wprintf(L"Card in reader ‘%s‘ is already known by the system. Not adding ATR.\n", pRdr-&szReader);
// Disconnect from the card. We do not need to reset it.
if (NULL != hSCard)
SCardDisconnect(hSCard, SCARD_LEAVE_CARD);
// Free resources
if (NULL != pmszCards)
SCardFreeMemory(hSC, pmszCards);
LONG MonitorReaders(
__in SCARDCONTEXT hSC)
pwszReaders = NULL;
pwszOldReaders = NULL;
pwszRdr = NULL;
dwRet = ERROR_SUCCESS;
cchReaders = SCARD_AUTOALLOCATE;
dwRdrCount = 0;
dwOldRdrCount = 0;
dwIndex = 0;
lReturn = NO_ERROR;
fDone = FALSE;
SCARD_READERSTATE
rgscState[MAXIMUM_SMARTCARD_READERS+1] = {0};
SCARD_READERSTATE
rgscOldState[MAXIMUM_SMARTCARD_READERS+1] = {0};
LPSCARD_READERSTATE pRdr = NULL;
// Parameter check
if (NULL == hSC)
wprintf(L"Invalid parameter in MonitorReaders.\n");
return ERROR_INVALID_PARAMETER;
// One of the entries for monitoring will be to detect new readers
// The first time through the loop will be to detect whether
// the system has any readers.
rgscState[0].szReader = PNP_READER_NAME;
rgscState[0].dwCurrentState = SCARD_STATE_UNAWARE;
dwRdrCount = 1;
while (!fDone)
while (!fDone)
// Wait for status changes to occur
wprintf(L"Monitoring for changes.\n");
lReturn = SCardGetStatusChange(
rgscState,
dwRdrCount);
switch (lReturn)
case SCARD_S_SUCCESS:
// Success
case SCARD_E_CANCELLED:
// Monitoring is being cancelled
wprintf(L"Monitoring cancelled. Exiting.\n");
fDone = TRUE;
// Error occurred
wprintf(L"Error 0x%x occurred while monitoring reader states.\n", lReturn);
fDone = TRUE;
if (!fDone)
// Examine the status change for each reader, skipping the PnP notification reader
for (dwIndex = 1; dwIndex & dwRdrC dwIndex++)
pRdr = &rgscState[dwIndex];
// Determine if a card is now present in the reader and
// it can be communicated with.
if ((pRdr-&dwCurrentState & SCARD_STATE_EMPTY ||
SCARD_STATE_UNAWARE == pRdr-&dwCurrentState) &&
pRdr-&dwEventState & SCARD_STATE_PRESENT &&
!(pRdr-&dwEventState & SCARD_STATE_MUTE))
// A card has been inserted and is available.
// Grab its ATR for addition to the database.
wprintf(L"A card has been inserted into reader ‘%s‘. Grabbing its ATR.\n", pRdr-&szReader);
lReturn = ProcessCard(hSC, pRdr);
// If an error occurs here, we will continue so we can try the next time
// the card is inserted as well as examine other readers.
// Save off the new state of the reader
pRdr-&dwCurrentState = pRdr-&dwEventS
// Now see if the number of readers in the system has changed.
// Save its new state as the current state for the next loop.
pRdr = &rgscState[0];
pRdr-&dwCurrentState = pRdr-&dwEventS
if (pRdr-&dwEventState & SCARD_STATE_CHANGED)
wprintf(L"Reader change detected.\n");
if (!fDone)
// Clean up previous loop
if (NULL != pwszOldReaders)
SCardFreeMemory(hSC, pwszOldReaders);
pwszOldReaders = NULL;
pwszReaders = NULL;
cchReaders = SCARD_AUTOALLOCATE;
// Save off PnP notification reader state and and list of readers previously found in the system
memcpy_s(&rgscOldState[0], sizeof(SCARD_READERSTATE), &rgscState[0], sizeof(SCARD_READERSTATE));
memset(rgscState, 0, sizeof(rgscState));
dwOldRdrCount = dwRdrC
pwszOldReaders = pwszR
// Obtain a list of all readers in the system
wprintf(L"Building reader list.\n");
lReturn = SCardListReaders(
(LPWSTR)&pwszReaders,
&cchReaders);
switch (lReturn)
case SCARD_S_SUCCESS:
// Success
case SCARD_E_NO_READERS_AVAILABLE:
// No readers in the system. This is OK.
lReturn = SCARD_S_SUCCESS;
// Error occurred
wprintf(L"Failed to obtain list of readers with error 0x%x.\n", lReturn);
fDone = TRUE;
// Build the reader list for monitoring - NULL indicates end-of-list
// First entry is the PnP Notification entry.
pRdr = rgscS
memcpy_s(&rgscState[0], sizeof(SCARD_READERSTATE), &rgscOldState[0], sizeof(SCARD_READERSTATE));
pwszRdr = pwszR
while ((NULL != pwszRdr) && (0 != *pwszRdr))
BOOL fFound = FALSE;
dwRdrCount++;
// Look for an existing reader state from a previous loop
for (dwIndex = 1; dwIndex & dwOldRdrC dwIndex++)
if ((lstrlen(pwszRdr) == lstrlen(rgscOldState[dwIndex].szReader)) &&
(0 == lstrcmpi(pwszRdr, rgscOldState[dwIndex].szReader)))
// Found a match. Copy it.
memcpy_s(pRdr, sizeof(SCARD_READERSTATE), &rgscOldState[dwIndex], sizeof(SCARD_READERSTATE));
fFound = TRUE;
if (!fFound)
// New reader
pRdr-&szReader = pwszR
pRdr-&dwCurrentState = SCARD_STATE_UNAWARE;
// Increment reader indices
pwszRdr += lstrlen(pwszRdr)+1;
// Clean up resources
if (NULL != pwszReaders)
SCardFreeMemory(hSC, pwszReaders);
if (NULL != pwszOldReaders)
SCardFreeMemory(hSC, pwszOldReaders);
LONG __cdecl main(
dwRet = ERROR_SUCCESS;
SCARDCONTEXT
hSC = NULL;
lReturn = NO_ERROR;
hStartedEvent = NULL;
// Get handle to event that will be signaled when the Smart Card Service is available
hStartedEvent = SCardAccessStartedEvent();
// Wait for the Smart Card Service to become available
dwRet = WaitForSingleObject(hStartedEvent, INFINITE);
if (WAIT_OBJECT_0 != dwRet)
wprintf(L"Wait for Smart Card Service failed with error 0x%x.\n", dwRet);
lReturn = dwR
// Establish a system-level context with the Smart Card Service
lReturn = SCardEstablishContext(
SCARD_SCOPE_SYSTEM,
if (SCARD_S_SUCCESS != lReturn)
wprintf(L"Failed to establish context with the Smart Card Service with error 0x%x.\n", lReturn);
// Begin monitoring the readers in the system
// This routine could be done in a separate thread so it can be cancelled via SCardCancel().
lReturn = MonitorReaders(hSC);
// Cleanup resources
if (NULL != hSC)
SCardReleaseContext(hSC);
if (NULL != hStartedEvent)
SCardReleaseStartedEvent();
wprintf(L"Done.\n");
&&国之画&&&& &&&&chrome插件
版权所有 京ICP备号-2
迷上了代码!

我要回帖

更多关于 python编程可执行文件 的文章

 

随机推荐