Сообщение об ошибке при вставке смарт-карту в устройство чтения на компьютере под управлением Windows 7 или Windows Server 2008 R2: «драйвер устройства не был успешно установлен»

Переводы статьи Переводы статьи
Код статьи: 976832 - Vizualiza?i produsele pentru care se aplic? acest articol.
Развернуть все | Свернуть все

В этой статье

Проблема

При вставке смарт-карту в устройство чтения смарт-карт Windows пытается загрузить и установить minidrivers смарт-карты для карты через службы Plug and Play. Если на любом из предварительно настроенных мест, например из центра обновления Windows, WSUS или пути интрасети отсутствует драйвер для смарт-карт и пользовательских Криптопровайдер не установлен в системе, в области уведомлений появляется следующее сообщение об ошибке:
Драйвер устройства не был успешно установлен
Щелкните здесь для получения дополнительных сведений.
Это сообщение об ошибке исчезает через несколько секунд.

Кроме того в диспетчере устройств, в разделе другие устройства, устройства смарт-карт имеет статус "DNF" (драйвер не найден).

Часто требует от пользователя получить один из следующих элементов от поставщика смарт-карты для устранения этой ошибки:
  1. Минидрайвера logoed смарт-карт Windows
  2. Пользовательский поставщик криптографии (CSP) для смарт-карты.
  3. Минидрайвер Windows для смарт-карт без фирменной символики
  4. Другие промежуточного элемента управления ActiveX, PKCS #11 программное обеспечение или другое пользовательское программное обеспечение.
Тем не менее если пользователь входит в состав элемента только 3 или 4 из этого списка, смарт-карты продолжает работать в системе. Тем не менее пользователь получит сообщение об ошибке, описанное в этом разделе каждый раз что они вставить смарт-карту.

Эта проблема касается всех версий Windows 7, Windows Server 2008 R2 и в более поздних версиях обеих операционных систем.

Причина

Все смарт-карты требуется дополнительное программное обеспечение для работы в Windows, если драйверы, позволяющий пользователю использовать карту без установки дополнительного программного обеспечения. Платформу Windows смарт-карта была улучшена в Windows 7, чтобы включить автоматическую загрузку minidrivers смарт-карт из центра обновления Windows или из других подобных мест, таких как сервер WSUS, вставленный в устройство чтения смарт-карт. Все смарт-карты, которые успешно выполнить требования логотипа, опубликованной в программу размещения эмблемы Windows использовать преимущества этой функции.

Тем не менее если программное обеспечение, необходимое для использования смарт-карт в Windows не является logoed или типа, который отличается от минидрайвера, драйвер PKCS #11, пользовательские CSP, промежуточного слоя или элемент управления ActiveX, сбой параметр автоматического приема так как корпорация Майкрософт сертифицирует только minidrivers смарт-карты. Таким образом Если пользователь вставляет карту, для которого пользовательский CSP еще не зарегистрирован, пользователь получает сообщение об ошибке о том, что драйвер отсутствует для устройства смарт-карт, несмотря на то, что пользователь может использовать смарт-карты через дополнительного программного обеспечения, установленного на компьютере пользователя с пользовательской установки.

Решение

Хотя смарт-карт по-прежнему работать несмотря на сообщение об ошибке, пользователь видит, смарт-карт поставщик, поставщика или производителя можно использовать один из следующих методов для устранения этой ошибки.

Реализация минидрайвера смарт-карты

Рекомендуется реализовать смарт-карт minidrivers карточки поставщиков, поставщиков и производителей и принять участие в программе размещения эмблемы Windows для получения преимуществ усовершенствования, появившиеся в платформы, такие как смарт-карты Plug and Play Device Stage для смарт-карт и т. д.

Дополнительные сведения о спецификации минидрайвера смарт-карт для Windows посетите следующий веб-узел корпорации Майкрософт:
http://www.Microsoft.com/whdc/Device/Input/Smartcard/SC-minidriver.mspx
Дополнительные сведения о том, как начать процесс получения эмблемы для вашего minidrivers смарт-карты посетите Windows логотип программы веб-узла:
http://www.Microsoft.com/whdc/winlogo/Default.mspx

Реализовать ПУСТОГО драйвера для смарт-карты

Если пользовательское программное обеспечение драйвера PKCS #11, элемент управления ActiveX или других промежуточного слоя необходимо включить использование смарт-карт в Windows и реализации минидрайвера смарт-карты или пользовательские CSP не целесообразна, мы рекомендует карточки поставщиков, поставщиков или производителей передача NULL драйверов в центре обновления Windows. Типовой процесс, позволяющий удостовериться в том, что драйвер NULL доступен в центре обновления Windows требуется отправка успешно неопределенное устройство через Winqual. Если в будущем, отсутствует минидрайвера для этих карт, новый драйвер можно загрузить обновления Windows, участвуя в программе размещения эмблемы Windows. Драйверы NULL можно затем загрузить вручную пользователем или становятся доступными с помощью необязательных обновлений.

Ниже приведен пример шаблона для ПУСТОГО драйвера для смарт-карты.
;
; Null Driver for Fabrikam Smartcard installation x86 and x64 package.
;

[Version]
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 ==================================

[Strings]
ProviderName ="Microsoft"
CardDeviceName="Fabrikam Generic Smart card"
Чтобы создать код оборудования устройства, на которую ссылается строка DEVICE_ID в образце, следуйте инструкциям в спецификации для смарт-карт минидрайвера. Для этого посетите следующий веб-узел корпорации Майкрософт:
http://www.Microsoft.com/whdc/Device/Input/Smartcard/SC-minidriver.mspx


Подробные сведения об отправке ПУСТОГО драйвера в корпорацию Майкрософт обратитесь в службу технической поддержки Майкрософт.

Отключить смарт-карты Plug and Play групповой политики для компьютеров

Этот параметр рекомендуется только на предприятиях, где компьютеры управляются администраторами и все, что установлено необходимое программное обеспечение для работы со смарт-картами, которые используются на предприятии с помощью программного средства управления, такие как SMS.

Так, как это повлияет на смарт-карты в среде данной процедуры настоятельно не рекомендуется в следующих условиях:
  • Коммерческие развертывания, предназначенные для конечных пользователей, такие как банковское обслуживание через Интернет
  • Среды, как Plug and Play, смарт-карты и смарт-карт не Plug and Play, использующих групповую политику для отключения Plug and Play для смарт-карт
Смарт-карта Plug and Play может быть полностью отключена на предприятиях, где компьютер конечного пользователя осуществляется механизмами, например групповой политикой.

Если в развертывании используются только решения смарт-карт не Plug and Play, смарт-карты Plug and Play можно отключить с помощью локального администратора на клиентском компьютере. Отключение устройства Plug and Play запрещает драйверов смарт-карт, также известный как minidrivers смарт-карты, загрузка. Она также предотвращает запросы Plug and Play для смарт-карт.

Чтобы отключить смарт-карты Plug and Play в локальной групповой политики, выполните следующие действия.
  1. Нажмите кнопку Пуск, тип gpedit.msc в поле Найти программы и файлы и нажмите клавишу ВВОД.
  2. В дереве консоли в разделе Конфигурация компьютеравыберите Административные шаблоны.
  3. В области сведений дважды щелкните Компоненты Windowsи смарт-карт.
  4. Щелкните правой кнопкой мыши Включить смарт-карты служба Plug and Playи нажмите кнопку Изменить.
  5. Нажмите кнопку Отключитьи нажмите кнопку ОК.

Изменение конечного пользователя системы и отключение смарт-карты Plug and Play для конкретных карт

Этот параметр рекомендуется использовать наименее используется. Этот параметр следует использовать только в том случае, если карты используемые устаревшие и не планируется в будущем реализовать minidrivers смарт-карты. Этот параметр требует, что существующее программное обеспечение, которое уже установлено в системе уведомить Windows имеется пользовательский CSP, установленных в системе, даже если такие CSP не существует на компьютере конечного пользователя. Как только Windows определяет пользовательские CSP, уже установленных в системе, Windows не пытается загрузить и установить драйвер устройства Plug and Play. Создается отсутствует узел устройства для устройства смарт-карт, который отображается в диспетчере устройств. Этот параметр приводит следующие изменения в системный реестр:

Подраздел:
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, округ Колумбия, 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 фиктивное поставщика»
Для x 64-разрядных систем идентичные изменения должны быть внесены в следующем подразделе:
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards


Корпорация Майкрософт рекомендует, вместо непосредственного изменения в системный реестр, использовать интерфейсы API WinSCard, чтобы внести эти изменения в систему. Ниже приведен пример кода примера, который обнаруживает вставки смарт-карты, а затем отключает смарт-карты Plug and Play для конкретной карточки путем создания записи в реестре, связывающую карточке поставщика не существует.

Корпорация Майкрософт предлагает примеры программного кода только для ознакомления, без гарантий, явных или подразумеваемых. Это включает, но не ограничивается, подразумеваемыми гарантиями товарной пригодности или пригодности для определенной цели. В данной статье предполагается, что вы знакомы с языком программирования предложенном и средствами, которые используются для создания и отладки. Сотрудники службы поддержки Майкрософт могут объяснить возможности конкретной процедуры. Тем не менее будут изменять примеры для реализации дополнительных возможностей или создания процедур для определенных требований.
//==============================================================;
//
//  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         36

LONG 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;
}

Ссылки

Дополнительные сведения об устранении неполадок Plug and Play для смарт-карт см. в следующей статье TechNet:
Смарт-карта Plug and Play, поиск и устранение неисправностей
http://TechNet.Microsoft.com/en-us/library/dd979536 (WS.10).aspx

Свойства

Код статьи: 976832 - Последний отзыв: 23 ноября 2013 г. - Revision: 5.0
Информация в данной статье относится к следующим продуктам.
  • Windows Server 2008 R2 Datacenter
  • Windows Server 2008 R2 Enterprise
  • Windows Server 2008 R2 Standard
  • Windows 7 Корпоративная
  • Windows 7 Домашняя базовая
  • Windows 7 Домашняя расширенная
  • Windows 7 Профессиональная
  • Windows 7 Начальная
  • Windows 7 Максимальная
Ключевые слова: 
kbsmartcard kbcodesnippet kbtshoot kbexpertiseinter kbsurveynew kbprb kbmt KB976832 KbMtru
Переведено с помощью машинного перевода
ВНИМАНИЕ! Данная статья переведена с использованием программного обеспечения Майкрософт для машинного перевода и, возможно, отредактирована посредством технологии Community Translation Framework (CTF). Корпорация Майкрософт предлагает вам статьи, обработанные средствами машинного перевода, отредактированные членами сообщества Майкрософт и переведенные профессиональными переводчиками, чтобы вы могли ознакомиться со всеми статьями нашей базы знаний на нескольких языках. Статьи, переведенные с использованием средств машинного перевода и отредактированные сообществом, могут содержать смысловое, синтаксические и (или) грамматические ошибки. Корпорация Майкрософт не несет ответственности за любые неточности, ошибки или ущерб, вызванные неправильным переводом контента или его использованием нашими клиентами. Подробнее об CTF можно узнать по адресу http://support.microsoft.com/gp/machine-translation-corrections/ru.
Эта статья на английском языке: 976832

Отправить отзыв

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com