Mensagem de erro quando você insere um cartão inteligente em uma leitora em um computador baseado em Windows 7 ou Windows Server 2008 R2: "software de driver de dispositivo não foi instalado com êxito"

Traduções deste artigo Traduções deste artigo
ID do artigo: 976832 - Exibir os produtos aos quais esse artigo se aplica.
Expandir tudo | Recolher tudo

Neste artigo

Sintomas

Quando você insere um cartão inteligente em uma leitora de cartão inteligente, o Windows tenta baixar e instalar o minidrivers de cartão inteligente para o cartão por meio de serviços de Plug and Play. Se o driver para o cartão inteligente não está disponível em nenhum dos locais pré-configurados, como Windows Update, WSUS ou caminhos de intranet e um provedor de serviços de criptografia personalizado já não está instalado no sistema, você recebe a seguinte mensagem de erro na área de notificação:
Software de driver de dispositivo não foi instalado com êxito
Clique aqui para obter detalhes.
Essa mensagem de erro desaparecerá após alguns segundos.

Além disso, no Gerenciador de dispositivos, em outros dispositivos, o dispositivo de cartão inteligente tem um status de "DNF" (Driver não encontrado).

Isso freqüentemente exige que o usuário obter um dos itens a seguir a partir do emissor do cartão inteligente para resolver esse erro:
  1. Um minidriver de logoed cartão inteligente do Windows
  2. Um provedor personalizado de serviços de criptografia (CSP) para o cartão inteligente.
  3. Minidriver de cartão não logoed um Windows
  4. Outro middleware como um controle ActiveX, PKCS n º 11 software ou outro software personalizado.
No entanto, se o usuário é fornecido com o único item 3 ou 4 nessa lista, o cartão inteligente continua a trabalhar com o sistema. No entanto, o usuário receberá a mensagem de erro que é mencionada nesta seção toda vez que inserem o cartão inteligente.

Esse problema afeta todas as versões do Windows 7, Windows Server 2008 R2 e em versões posteriores de ambos os sistemas operacionais.

Causa

Todos os cartões inteligentes requerem software adicional para funcionar no Windows, a menos que haja um driver de caixa de entrada que permite que o usuário use o cartão sem instalar software adicional. A estrutura de cartão inteligente do Windows foi aprimorada no Windows 7 para ativar o download automático de minidrivers de cartão inteligente do Windows Update ou de outros locais semelhantes, como um servidor WSUS quando o cartão inteligente está inserido no leitor. Todos os cartões inteligentes que passam com êxito os requisitos de logotipo, conforme publicado pelo programa de logotipo do Windows, se beneficiar deste recurso.

No entanto, se o software necessário para usar um cartão inteligente no Windows não é logoed ou é de um tipo diferente de um minidriver, como um driver PKCS n º 11, um CSP personalizado, middleware ou um controle ActiveX, o download automático opção falha porque o Microsoft certifica minidrivers de cartão inteligente somente. Portanto, se o usuário insere um cartão para o qual um CSP personalizado não estiver registrado, o usuário receberá uma mensagem de erro afirmando que o software de driver está ausente para o dispositivo de cartão inteligente, mesmo que o usuário pode usar o cartão inteligente por meio de software adicional foi instalado no computador do usuário de uma instalação personalizada.

Resolução

Embora os cartões inteligentes continue a funcionar apesar da mensagem de erro que o usuário vê, um emissor do cartão inteligente, o fornecedor ou o fabricante pode usar um dos seguintes métodos para resolver esse erro.

Implementar um minidriver de cartão inteligente

Recomendamos que os emissores de cartão, fornecedores e fabricantes implementam minidrivers de cartão inteligente e participarem do programa de logotipo do Windows para se beneficiar dos aprimoramentos que são introduzidos na plataforma, como cartões inteligentes Plug and Play, o Device Stage para cartões inteligentes, e assim por diante.

Para obter mais informações sobre especificações de minidriver de cartão inteligente do Windows, visite o seguinte site da Microsoft:
http://www.microsoft.com/whdc/device/Input/Smartcard/SC-minidriver.mspx
Para obter mais informações sobre como começar com o processo de obtenção de um logotipo para sua minidrivers de cartão inteligente, visite o seguinte site Windows Logo Program na Web:
http://www.microsoft.com/whdc/winlogo/default.mspx

Implementar um driver NULL para o cartão inteligente

Se software personalizado um driver PKCS n º 11, um controle ActiveX ou alguns outro middleware é necessário para ativar o uso de cartões inteligentes no Windows e implementar minidriver um cartão inteligente ou um CSP personalizado não é uma opção prática, recomendamos que os emissores de cartão, fornecedores ou fabricantes consideram enviar drivers nulo ao Windows Update. O processo típico de certificando-se de que um driver NULL está disponível no Windows Update requer o envio de um dispositivo não classificado com êxito por meio de Winqual. Se, no futuro, há um minidriver disponível para esses cartões, o novo driver pode ser carregado para o Windows Update participando do programa de logotipo do Windows. Os drivers NULL, em seguida, podem ser baixados manualmente, os usuários finais ou podem disponibilizados por meio de atualizações opcionais.

A seguir é uma amostra de modelo por um driver NULL para um cartão inteligente.
;
; 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"
Para gerar a identificação de dispositivo de hardware que é referenciada pela seqüência DEVICE_ID na amostra, siga as instruções na especificação do minidriver de cartão inteligente. Para fazer isso, visite o seguinte site da Microsoft:
http://www.microsoft.com/whdc/device/Input/Smartcard/SC-minidriver.mspx


Para obter informações detalhadas sobre como enviar um driver NULL para a Microsoft, entre em contato com o suporte técnico da Microsoft.

Desabilitar Smartcard Plug and Play através da diretiva de grupo para computadores gerenciados

Essa opção é recomendada somente para implantações empresariais onde os computadores são gerenciados por administradores e todo o software necessário para trabalhar com os cartões inteligentes que estão sendo usados na empresa é instalado usando as ferramentas de gerenciamento de software, como o SMS.

Esse procedimento é recomendável nos seguintes ambientes porque ela afetará todos os cartões inteligentes em seu ambiente:
  • Implantações comerciais que têm como alvo os usuários finais, como serviços bancários on-line
  • Ambientes que incluam ambos Plug and Play, cartões inteligentes e cartões inteligentes Plug and Play que usam a diretiva de grupo para desabilitar o Plug and Play para cartões inteligentes
Cartão inteligente Plug and Play pode ser completamente desabilitada em empresas onde o computador do usuário final é gerenciado por mecanismos como diretiva de grupo.

Se a implantação usar apenas soluções de cartão inteligente de Plug and Play, cartão inteligente Plug and Play pode ser desabilitado por um administrador local no computador cliente. Desativação de cartões inteligentes Plug and Play impede que drivers de cartão inteligente, também conhecido como minidrivers de cartão inteligente, fazendo o download. Ela também impede que avisos de Plug and Play de cartão inteligente.

Para desativar o cartão inteligente Plug and Play na diretiva de grupo local, execute estas etapas:
  1. Clique em Iniciar, tipo gpedit. msc Na caixa Pesquisar programas e arquivos e então pressione ENTER.
  2. Na árvore do console, em Configuração do computador, clique em Modelos administrativos.
  3. No painel de detalhes, clique duas vezes em Componentes do Windowse, em seguida, clique duas vezes em cartão inteligente.
  4. Clique com o botão Ativar serviço Plug and Play de cartão inteligentee, em seguida, clique em Editar.
  5. Clique em desativadoe, em seguida, clique em OK.

Alterar o sistema do usuário final e desabilitar Smartcard Plug and Play para placas específicas

Essa é a opção menos recomendado. Você deve usar essa opção somente se as placas são placas de legado e não há planos para implementar minidrivers de cartão inteligente no futuro. Esta opção requer que o software existente que já está instalado no sistema notificar o Windows que existe um CSP personalizado instalado no sistema, mesmo que tal CSP não existe no sistema do usuário final. Assim que o Windows determina que há um CSP personalizado já instalado no sistema, Windows não tente baixar e instalar um driver por meio de cartões inteligentes Plug and Play. Nenhum nó de dispositivo para o dispositivo de cartão inteligente é criado que está visível no Gerenciador de dispositivos. Essa opção resulta nas seguintes alterações no registro do sistema:

Subchave:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\<Smart card name>
Entradas da subchave do registro:
  • ATR = Hexadecimal DWORD: ATR do cartão inteligente delimitado por vírgulas.
  • ATRMask = Hexadecimal DWORD: máscara para aplicar a ATR para mascarar insignificante bytes na ATR delimitado por vírgulas.
  • Provedor de criptografia = valor de seqüência de caracteres: alguma cadeia de caracteres relevante para o cartão inteligente.
Por exemplo:
Subchave:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\Fabrikam ATM card
Entradas da subchave do registro:
  • ATR = Hexadecimal DWORD: 3b, dc, 13, 00, 40, 3a, 49, 54, 47, 5f, 4d, 53, 43, 53, 50, 5f, 56, 32
  • ATRMask = Hexadecimal DWORD: ff, ff, ff, ff, ff, ff, ff, ff, ff, TT, TT, TT, ff, ff, ff, ff, ff, ff
  • Provedor de criptografia = valor de seqüência: "Fabrikam ATM fictício Provider"
Para sistemas x64 bits, alterações idênticas devem ser feitas na seguinte subchave:
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards


É recomendável que, em vez de alterar diretamente o registro do sistema, você usar APIs de WinSCard apresentar essas alterações ao sistema. Aqui está o exemplo de código de exemplo que detecta a inserção do cartão inteligente e, em seguida, desativa o cartão inteligente Plug and Play para a placa específica, criando uma entrada do registro que associa o cartão com um provedor não existente.

A Microsoft fornece exemplos de programação apenas para ilustração, sem garantia expressa ou implícita. Isso inclui, mas não está limitado a, garantias implícitas de comercialização ou adequação um propósito específico. Este artigo pressupõe que você esteja familiarizado com a linguagem de programação que está sendo demonstrada e com as ferramentas usadas para criar e depurar procedimentos. Engenheiros de suporte da Microsoft podem ajudar a explicar a funcionalidade de um determinado procedimento. No entanto, eles não modificarão esses exemplos para fornecer funcionalidades adicionais ou construir procedimentos para atender às suas necessidades específicas.
//==============================================================;
//
//  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;
}

Referências

Para obter mais informações sobre como solucionar problemas do cartão inteligente Plug and Play, consulte o seguinte artigo do TechNet:
Guia de solução de problemas do cartão inteligente Plug and Play
http://technet.microsoft.com/en-us/library/dd979536 (WS

Propriedades

ID do artigo: 976832 - Última revisão: domingo, 9 de fevereiro de 2014 - Revisão: 4.0
A informação contida neste artigo aplica-se a:
  • 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
Palavras-chave: 
kbsmartcard kbcodesnippet kbtshoot kbexpertiseinter kbsurveynew kbprb kbmt KB976832 KbMtpt
Tradução automática
IMPORTANTE: Este artigo foi traduzido pelo software de tradução automática da Microsoft e eventualmente pode ter sido editado pela Microsoft Community através da tecnologia Community Translation Framework (CTF) ou por um tradutor profissional. A Microsoft oferece artigos traduzidos automaticamente por software, por tradutores profissionais e editados pela comunidade para que você tenha acesso a todos os artigos de nossa Base de Conhecimento em diversos idiomas. No entanto, um artigo traduzido pode conter erros de vocabulário, sintaxe e/ou gramática. A Microsoft não é responsável por qualquer inexatidão, erro ou dano causado por qualquer tradução imprecisa do conteúdo ou por seu uso pelos nossos clientes.
Clique aqui para ver a versão em Inglês deste artigo: 976832

Submeter comentários

 

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