你目前正处于脱机状态,正在等待 Internet 重新连接

在基于 Windows 7 的或基于 Windows Server 2008 R2 的计算机上的读卡器中插入智能卡时出现错误消息:"设备驱动程序未能成功安装"

重要说明:本文是由 Microsoft 机器翻译软件进行的翻译并可能由 Microsoft 社区通过社区翻译机构(CTF)技术进行后期编辑,或可能是由人工进行的翻译。Microsoft 同时向您提供机器翻译、人工翻译及社区后期编辑的文章,以便对我们知识库中的所有文章以多种语言提供访问。翻译的文章可能存在词汇、句法和/或语法方面的错误。Microsoft 对由于内容的误译或客户对内容的使用所导致的任何不准确、错误或损失不承担责任。

点击这里察看该文章的英文版: 976832
症状
当智能卡插入智能卡阅读器后时,Windows 尝试下载并安装智能卡 minidrivers 通过插服务卡。如果自定义的加密服务提供程序未在系统上安装智能卡的驱动程序在任一预配置位置,如 Windows 更新、 WSUS 或 intranet 路径不可用,在通知区域中将收到以下错误消息 ︰
未能成功安装设备驱动程序软件
有关详细信息,请单击此处。
此错误消息在几秒钟后就会消失。

另外,设备管理器中,在其他设备下的智能卡设备的"DNF"(没有找到驱动程序) 的状态。

这通常需要用户从智能卡颁发者若要解决此错误获得以下各项之一 ︰
  1. Windows logoed 智能卡微型驱动程序
  2. 智能卡自定义的加密服务提供程序 (CSP)。
  3. Windows 非 logoed 智能卡微型驱动程序
  4. 其他如 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 徽标计划受益于智能卡插 Device Stage 对于智能卡,如平台中引入了改进,等等。

有关智能卡用于 Windows 的微型驱动程序规范的详细信息,请访问下面的 Microsoft 网站 ︰ 有关如何开始使用获取智能卡 minidrivers 的徽标的过程的详细信息,请访问下面的 Windows 徽标计划 Web 站点 ︰

实现您的智能卡的空驱动程序

如果自定义软件这样的 PKCS #11 驱动程序、 ActiveX 控件或一些其他中间件是需要能够在 Windows 中,智能卡的使用和实施智能卡的微型驱动程序或自定义的 CSP 不是可行的办法,我们建议卡颁发者、 供应商或制造商应考虑提交空驱动程序与 Windows 更新。确保 NULL 驱动程序位于 Windows 更新的典型过程需要通过 Winqual 的成功未分类的设备提交。如果将来,没有可供这些卡的微型驱动程序,可以通过 Windows 徽标计划加入到 Windows Update 上载新的驱动程序。NULL 驱动程序之后可以由最终用户手动下载,也可通过使用可选更新可用。

下面是空的智能卡的驱动程序的一个示例模板。
;; Null Driver for Fabrikam Smartcard installation x86 and x64 package.;[Version]Signature="$Windows NT$"Class=SmartCardClassGuid={990A2BD7-E738-46c7-B26F-1CF8FB9F1391}Provider=%ProviderName%CatalogFile=delta.catDriverVer=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 ==================================[Strings]ProviderName ="Microsoft"CardDeviceName="Fabrikam Generic Smart card"
若要生成示例中的 DEVICE_ID 字符串引用的硬件设备 ID,请按照智能卡微型驱动程序的规范。若要执行此操作,请访问下面的 Microsoft 网站:

有关如何提交到 Microsoft NULL 驱动程序的详细信息,请与 Microsoft 客户支持服务联系。

禁用智能卡通过组策略的插被管理的计算机

此选项仅对管理员和所有必要的软件使用中企业正在使用智能卡安装通过使用软件管理工具 (如 SMS),管理计算机的企业部署建议。

因为这将影响您的环境中的所有智能卡,此过程是强烈建议您不要在以下环境中 ︰
  • 面向最终用户,如网上银行的商业部署
  • 包含这两个环境插智能卡和使用组策略来禁用智能卡插的非即插智能卡
智能卡插可以完全禁用最终用户的计算机由组策略等机制的企业中。

如果您的部署使用只非即插智能卡解决方案,客户端计算机上的本地管理员可以禁用智能卡插。禁用智能卡插可以阻止智能卡的驱动程序,也称为智能卡 minidrivers,下载。它还可以防止智能卡插提示。

要禁用智能卡插在本地组策略,请执行以下步骤 ︰
  1. 单击开始键入 gpedit.msc搜索程序和文件中,然后按 enter 键。
  2. 在控制台树中在计算机配置下,单击管理模板
  3. 在详细信息窗格中,双击Windows 组件,然后双击智能卡
  4. 请用鼠标右键单击启用智能卡插服务,然后单击编辑
  5. 单击禁用,然后单击确定

更改的最终用户的系统和禁用智能卡插对特定卡

这是最推荐的选项。只有卡的旧卡并没有计划在将来实现智能卡 minidrivers,应使用此选项。此选项要求已经安装在系统的现有软件通知 Windows 没有即使在最终用户系统中存在任何此类 CSP 系统上安装一个自定义的 CSP。只要 Windows 确定自定义 CSP 已经安装在系统上,Windows 不会尝试下载并安装智能卡插到驱动程序。智能卡设备没有设备节点创建在设备管理器中可见。此选项导致到系统注册表的以下更改 ︰

子项 ︰
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\<Smart card name>
子项的注册表项 ︰
  • ATR = 十六进制的 dword 值 ︰ ATR 的智能卡,以逗号分隔。
  • ATRMask = 十六进制的 dword 值 ︰ 要应用到 ATR 字节无意义以遮盖 ATR 蒙板,以逗号分隔。
  • 加密提供程序 = 字符串值 ︰ 某些与智能卡相关的字符串。
例如 ︰
子项 ︰
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\Fabrikam ATM card
子项的注册表项 ︰
  • 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 提供程序"
对于 x64 位的系统,必须在以下注册表子项下进行相同更改 ︰
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards


我们建议,而不是直接更改系统注册表,您使用 WinSCard Api 引入到系统的这些更改。下面是示例代码示例检测到智能卡插入,然后通过创建将卡与非现有提供程序相关联的注册表项禁用智能卡插,为特定的卡。

Microsoft 提供的编程示例仅用于说明,没有任何明示或暗示的担保。这包括但不限于适销性或特定用途适用性的暗示担保。本文假定您熟悉所演示的编程语言和用于创建和调试过程的工具。Microsoft 的支持工程师可以帮助解释某个特定过程的功能。但是,他们不会修改这些示例以提供额外的功能或构建过程以满足您的特定要求。
//==============================================================;////  Disable Smart card Plug and Play for specific cards////  Abstract://      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//  PURPOSE.////  Copyright (C) Microsoft Corporation.  All Rights Reserved.////==============================================================;// This code must be compiled with UNICODE support to work correctly#ifndef UNICODE#define UNICODE#endif#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// card.#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         36LONG GenerateCardName(    __deref_out LPWSTR  *ppwszCardName){    LONG        lReturn = NO_ERROR;    HRESULT     hr = S_OK;    DWORD       cchFinalString = 0;    WCHAR       wszCardNamePrefix[] = CARD_NAME_PREFIX;    LPWSTR      pwszFinalString = NULL;    UUID        uuidCardGuid = {0};    RPC_WSTR    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)rpcStatus;    }    else    {        // 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)rpcStatus;        }        else        {            // 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;            }            else            {                // Create final string                hr = StringCchPrintf(                            pwszFinalString,                            cchFinalString,                            L"%s-%s",                            wszCardNamePrefix,                            pwszCardGuid);                if (FAILED(hr))                {                    wprintf(L"Failed to create card name with error 0x%x.\n", hr);                    lReturn = (DWORD)hr;                }                else                {                    // Set output params                    *ppwszCardName = pwszFinalString;                    pwszFinalString = NULL;                }            }        }    }    if (NULL != pwszCardGuid)    {        RpcStringFree(&pwszCardGuid);    }    if (NULL != pwszFinalString)    {        HeapFree(GetProcessHeap(), 0, pwszFinalString);    }    return lReturn;}LONG IntroduceCardATR(    __in SCARDCONTEXT   hSC,    __in LPBYTE         pbAtr,    __in DWORD          cbAtr){    LONG    lReturn = NO_ERROR;    LPWSTR  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);    }    else    {        // Introduce the card to the system        lReturn = SCardIntroduceCardType(                                hSC,                                pwszCardName,                                NULL,                                NULL,                                0,                                pbAtr,                                NULL,                                cbAtr);        if (SCARD_S_SUCCESS != lReturn)        {            wprintf(L"Failed to introduce card '%s' to system with error 0x%x.\n", pwszCardName, lReturn);        }        else        {            // Set the provider name            lReturn = SCardSetCardTypeProviderName(                                        hSC,                                        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);            }            else            {                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);    }    return lReturn;}LONG ProcessCard(    __in SCARDCONTEXT           hSC,    __in LPSCARD_READERSTATE    pRdr){    LONG        lReturn = NO_ERROR;    DWORD       dwActiveProtocol = 0;    DWORD       cbAtr = MAX_ATR_LEN;    DWORD       dwIndex = 0;    DWORD       cchCards = SCARD_AUTOALLOCATE;    LPWSTR      pmszCards = NULL;    BYTE        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(                    hSC,                    pRdr->szReader,                    SCARD_SHARE_SHARED,                    SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,                    &hSCard,                    &dwActiveProtocol);    if (SCARD_S_SUCCESS != lReturn)    {        wprintf(L"Failed to connect to card in reader '%s' with error 0x%x.\n", pRdr->szReader, lReturn);    }    else    {        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(                            hSCard,                            SCARD_ATTR_ATR_STRING,                            rgbAtr,                            &cbAtr);        if (SCARD_S_SUCCESS != lReturn)        {            wprintf(L"Failed to obtain ATR of card in reader '%s' with error 0x%x.\n", pRdr->szReader, lReturn);        }        else        {            // Output the ATR            wprintf(L"ATR of card in reader '%s':", pRdr->szReader);            for (dwIndex = 0; dwIndex < cbAtr; dwIndex++)            {                wprintf(L" %02x", rgbAtr[dwIndex]);            }            wprintf(L"\n");            // Determine if the ATR is already in the Smart Card Database            lReturn = SCardListCards(                                hSC,                                rgbAtr,                                NULL,                                0,                                (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(                                    hSC,                                     rgbAtr,                                     cbAtr);                // 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.            }            else            {                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);    }    return lReturn;}LONG MonitorReaders(        __in SCARDCONTEXT hSC){    LPWSTR              pwszReaders = NULL;    LPWSTR              pwszOldReaders = NULL;    LPWSTR              pwszRdr = NULL;    DWORD               dwRet = ERROR_SUCCESS;    DWORD               cchReaders = SCARD_AUTOALLOCATE;    DWORD               dwRdrCount = 0;    DWORD               dwOldRdrCount = 0;    DWORD               dwIndex = 0;    LONG                lReturn = NO_ERROR;    BOOL                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(                                    hSC,                                    INFINITE,                                    rgscState,                                    dwRdrCount);            switch (lReturn)            {                case SCARD_S_SUCCESS:                    // Success                    break;                case SCARD_E_CANCELLED:                    // Monitoring is being cancelled                    wprintf(L"Monitoring cancelled. Exiting.\n");                    fDone = TRUE;                    break;                default:                    // Error occurred                    wprintf(L"Error 0x%x occurred while monitoring reader states.\n", lReturn);                    fDone = TRUE;                    break;            }            if (!fDone)            {                // Examine the status change for each reader, skipping the PnP notification reader                for (dwIndex = 1; dwIndex < dwRdrCount; 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->dwEventState;                }                // 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->dwEventState;                if (pRdr->dwEventState & SCARD_STATE_CHANGED)                {                    wprintf(L"Reader change detected.\n");                    break;                }            }           }        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 = dwRdrCount;            pwszOldReaders = pwszReaders;                        // Obtain a list of all readers in the system            wprintf(L"Building reader list.\n");            lReturn = SCardListReaders(                                hSC,                                NULL,                                (LPWSTR)&pwszReaders,                                &cchReaders);            switch (lReturn)            {                case SCARD_S_SUCCESS:                    // Success                    break;                case SCARD_E_NO_READERS_AVAILABLE:                    // No readers in the system. This is OK.                    lReturn = SCARD_S_SUCCESS;                    break;                default:                    // Error occurred                    wprintf(L"Failed to obtain list of readers with error 0x%x.\n", lReturn);                    fDone = TRUE;                    break;            }            // Build the reader list for monitoring - NULL indicates end-of-list            // First entry is the PnP Notification entry.            pRdr = rgscState;            memcpy_s(&rgscState[0], sizeof(SCARD_READERSTATE), &rgscOldState[0], sizeof(SCARD_READERSTATE));            pRdr++;            pwszRdr = pwszReaders;            while ((NULL != pwszRdr) && (0 != *pwszRdr))            {                BOOL fFound = FALSE;                dwRdrCount++;                // Look for an existing reader state from a previous loop                for (dwIndex = 1; dwIndex < dwOldRdrCount; 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;                        break;                    }                }                if (!fFound)                {                    // New reader                    pRdr->szReader = pwszRdr;                    pRdr->dwCurrentState = SCARD_STATE_UNAWARE;                }                // Increment reader indices                pRdr++;                pwszRdr += lstrlen(pwszRdr)+1;            }        }    }    // Clean up resources    if (NULL != pwszReaders)    {        SCardFreeMemory(hSC, pwszReaders);    }    if (NULL != pwszOldReaders)    {        SCardFreeMemory(hSC, pwszOldReaders);    }    return lReturn;}LONG __cdecl main(        VOID){    DWORD               dwRet = ERROR_SUCCESS;    SCARDCONTEXT        hSC = NULL;    LONG                lReturn = NO_ERROR;    HANDLE              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 = dwRet;    }    else    {        // Establish a system-level context with the Smart Card Service        lReturn = SCardEstablishContext(                                SCARD_SCOPE_SYSTEM,                                NULL,                                NULL,                                &hSC);        if (SCARD_S_SUCCESS != lReturn)        {            wprintf(L"Failed to establish context with the Smart Card Service with error 0x%x.\n", lReturn);        }        else        {            // 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");    return lReturn;}
参考
有关智能卡插问题进行故障排除的详细信息,请参阅下面的 TechNet 文章 ︰
即插即用 plugnplay win7 win2008R2 智能卡

属性

文章 ID:976832 - 上次审阅时间:06/12/2016 11:14:00 - 修订版本: 3.0

Windows Server 2008 R2 Datacenter, Windows Server 2008 R2 Enterprise, Windows Server 2008 R2 Standard, Windows 7 Enterprise, Windows 7 Home Basic, Windows 7 Home Premium, Windows 7 Professional, Windows 7 Starter, Windows 7 Ultimate

  • kbsmartcard kbcodesnippet kbtshoot kbexpertiseinter kbsurveynew kbprb kbmt KB976832 KbMtzh
反馈
ft.com/ms.js'><\/script>"); /html>