Mensagem de erro quando inserir um smart card num leitor num computador baseado no Windows 7 ou Windows Server 2008 R2: "o software de controlador de dispositivo instalado sem êxito"

Traduções de Artigos Traduções de Artigos
Artigo: 976832 - Ver produtos para os quais este artigo se aplica.
Expandir tudo | Reduzir tudo

Nesta página

Sintomas

Quando inserir um smart card no leitor de smart card, o Windows tenta transferir e instalar o minidrivers de um cartão Smart Card para a placa através dos serviços de Plug and Play. Se o controlador para o cartão Smart Card não está disponível em qualquer das localizações pré-configurados, tais como o Windows Update, WSUS ou caminhos de intranet, e um fornecedor de serviços de criptografia personalizado não estiver instalado no sistema, receberá a seguinte mensagem de erro na área de notificação:
Software de controlador de dispositivo não foi instalado com êxito
Clique aqui para obter detalhes.
Esta mensagem de erro desaparece após vários segundos.

Além disso, no Gestor de dispositivos, em Outros dispositivos, o dispositivo de cartão Smart Card tem um Estado de "DNF" (controlador não encontrado).

Isto requer frequentemente que o utilizador obter um dos seguintes itens do emissor do cartão Smart Card para resolver este erro:
  1. Um Minicontrolador logoed cartão Smart Card do Windows
  2. Um fornecedor personalizado de serviços criptográficos (CSP) do cartão Smart Card.
  3. Um Minicontrolador de smart card não logoed do Windows
  4. Outro middleware como um controlo ActiveX, o PKCS # #11 software, ou outro software personalizado.
No entanto, se o utilizador é fornecido com o único item 3 ou 4 desta lista, o cartão Smart Card continua a funcionar no sistema. No entanto, o utilizador receberá a mensagem de erro mencionada nesta secção sempre que se insira o smart card.

Este problema afecta todas as versões do Windows 7, Windows Server 2008 R2 e em versões posteriores de ambos os sistemas operativos.

Causa

Todos os cartões Smart Card requerem software adicional para funcionar no Windows, a menos que exista um controlador de local que permite ao utilizador utilizar a placa sem instalar software adicional. A estrutura de Smart Card do Windows foi melhorada no Windows 7 para activar a transferência automática de minidrivers de cartão Smart Card do Windows Update ou de outras localizações semelhantes, tal como um servidor WSUS quando é inserido o smart card no leitor. Todos os cartões Smart Card que passar com êxito os requisitos do logótipo, publicado pelo programa de logótipo Windows, beneficiar esta funcionalidade.

No entanto, se o software que é necessário utilizar um smart card no Windows não é logoed ou é de um tipo que difere uma Minicontrolador, tais como middleware do controlador de #11, um CSP personalizado, um PKCS #, ou um controlo ActiveX, a opção de transferência automática falha porque a Microsoft certifica apenas minidrivers de um cartão Smart Card. Por conseguinte, se o utilizador inserir um cartão para o qual um CSP personalizado não está já registado, o utilizador recebe uma mensagem de erro que indica que o software do controlador está em falta para o dispositivo de cartão Smart Card, mesmo que o utilizador pode utilizar o smart card através de software adicional que foi instalado no computador do utilizador de uma instalação personalizada.

Resolução

Apesar dos smart cards continuar a trabalhar não obstante a mensagem de erro que o utilizador vê, um emissor de smart card, o fornecedor ou o fabricante pode utilizar um dos seguintes métodos para resolver este erro.

Implementar Minicontrolador um cartão Smart Card

Recomendamos que os emitentes de cartão, fornecedores e os fabricantes de implementam minidrivers de cartão Smart Card e participam no programa de logótipo Windows para beneficiar dos melhoramentos que foram introduzidos na plataforma, tal como o cartão Smart Card Plug and Play, o Device Stage para cartões Smart Card, e assim sucessivamente.

Para mais informações sobre as especificações de Minicontrolador de cartão Smart Card para o Windows, visite o seguinte Web site da Microsoft:
http://www.microsoft.com/whdc/device/Input/smartcard/sc-minidriver.mspx
Para mais informações sobre como começar com o processo de obtenção de um logótipo para o minidrivers de cartão Smart Card, visite o seguinte site da Web de programa de logótipo do Windows:
http://www.microsoft.com/whdc/winlogo/default.mspx

Implementar um controlador NULL para o smart card

Se um PKCS essas #11 de software personalizado controlador, um controlo ActiveX ou alguns outro middleware é necessário para activar a utilização de smart card no Windows e a implementação de Minicontrolador um cartão Smart Card ou um CSP personalizado é não é uma opção viável, recomendamos que os emitentes de cartão, fornecedores ou fabricantes considerem submeter controladores nulo para o Windows Update. O processo normal para certificar-se de que um controlador NULL está disponível no Windows Update requer uma submissão de dispositivo não classificado com êxito através de Winqual. Se, no futuro, existe um Minicontrolador para estes cartões, o novo controlador possam ser enviado para actualização do Windows participando no programa de logótipo Windows. Os controladores de nulo, em seguida, podem ser transferidos manualmente, os utilizadores finais ou podem disponibilizados através da utilização de actualizações opcionais.

Segue-se um modelo de exemplo para um controlador NULL para um smart card.
;
; 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 o ID de dispositivo de hardware que é referenciado pela cadeia DEVICE_ID na amostra, siga as instruções na especificação do Minicontrolador de cartão Smart Card. Para tal, visite o seguinte Web site da Microsoft:
http://www.microsoft.com/whdc/device/Input/smartcard/sc-minidriver.mspx


Para obter informações detalhadas sobre como submeter um controlador NULL para a Microsoft, contacte o suporte técnico da Microsoft.

Desactivar o cartão Smart Card Plug and Play através da política de grupo para computadores geridos

Esta opção é recomendada apenas para implementações empresariais onde os computadores são geridos por administradores e todo o software necessário para trabalhar com os cartões Smart Card que estão a ser utilizados na empresa é instalado utilizando ferramentas de gestão de software, como o SMS.

Este procedimento é aconselhável a sua utilização nos seguintes ambientes porque irá afectar todas as cartas de smart card no seu ambiente:
  • Implementações comerciais que se aplicam a utilizadores finais, por exemplo, operações bancárias online
  • Ambientes que incluem tanto os serviço Plug and Play smart cards e cartões Smart Card não Plug and Play que utilizam a política de grupo para desactivar o Plug and Play para cartões Smart Card
Cartão Smart Card Plug and Play pode ser completamente desactivado em empresas em que o computador do utilizador final é gerido pelo mecanismos tais como a política de grupo.

Se a implementação utiliza apenas as soluções de cartão de smart card não Plug and Play, o cartão Smart Card Plug and Play pode ser desactivado por um administrador local num computador cliente. A desactivação de cartão Smart Card Plug and Play impede que controladores de cartão Smart Card, também conhecido como minidrivers de cartão Smart Card, a transferir. Também impede que pedidos de informação do cartão Smart Card Plug and Play.

Para desactivar o cartão Smart Card Plug and Play na política de grupo local, siga estes passos:
  1. Clique em Iniciar, tipo gpedit. msc no Procurar programas e ficheiros caixa e, em seguida, prima ENTER.
  2. Na árvore da consola em Configuração do computador, clique em Modelos administrativos.
  3. No painel de detalhes, faça duplo clique em Componentes do Windowse, em seguida, faça duplo clique Cartão Smart Card.
  4. Com o botão direito Activar o serviço do cartão Smart Card Plug and Playe, em seguida, clique em Editar.
  5. Clique em Desactivadoe, em seguida, clique em OK.

Alterar o sistema do utilizador final e desactivar o cartão Smart Card Plug and Play para placas específicas

Esta é a opção recomendada de menos. Deverá utilizar esta opção apenas se as placas são placas legacy e não existem planos para implementar minidrivers de cartão Smart Card no futuro. Esta opção requer que o software existente que já está instalado no sistema notificar o Windows que não existe um CSP personalizado instalado no sistema, mesmo que esses CSP não existe no sistema do utilizador final. Logo que o Windows determinar que existe um CSP personalizado já instalado no sistema, o Windows não tente transferir e instalar um controlador através de cartão Smart Card Plug and Play. Nenhum nó do dispositivo para o dispositivo de cartão Smart Card é criada que é visível no Gestor de dispositivos. Esta opção resulta nas seguintes alterações ao registo do sistema:

Subchave:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\<Smart card name>
Entradas da subchave de registo:
  • ATR = Hexadecimal DWORD: ATR do smart card delimitado por vírgulas.
  • ATRMask = Hexadecimal DWORD: máscara para aplicar a ATR a máscara de saída de bytes insignificantes na ATR delimitado por vírgulas.
  • Fornecedor de criptografia = valor de cadeia: alguns cadeia relevante para o smart card.
Por exemplo:
Subchave:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\Fabrikam ATM card
Entradas da subchave de registo:
  • ATR = Hexadecimal DWORD: 3b, dc, 13, 00, 40, 3º a, 49, 54, 47, 5f, 4d, 53. o, 43. o, 53. o, 50, 5f, 56, 32
  • ATRMask = Hexadecimal DWORD: ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff
  • Fornecedor de criptografia = valor de cadeia: "Fabrikam ATM manequim Provider"
Para sistemas x64 bits, deverão ser efectuadas alterações idênticas na seguinte subchave:
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards


Recomenda-se que, em vez de alterar directamente o registo do sistema, utilize APIs de WinSCard para introduzir estas alterações no sistema. Eis um exemplo de código de exemplo que detecta a inserção de cartão Smart Card e, em seguida, desactiva o cartão Smart Card Plug and Play para o cartão específico através da criação de uma entrada de registo que associa o cartão um fornecedor não existente.

A Microsoft fornece exemplos de programação para ilustração apenas, sem garantia expressa ou implícita. Isto inclui, mas não está limitado a, garantias implícitas de comercialização ou adequação a um fim específico. Este artigo pressupõe que está familiarizado com a linguagem de programação que está a ser demonstrada e com as ferramentas que são utilizadas para criar e depurar procedimentos. Engenheiros de suporte da Microsoft podem ajudar a explicar a funcionalidade de um determinado procedimento. No entanto, não modificarão estes exemplos para proporcionarem funcionalidades adicionais nem criarão procedimentos adaptados às necessidades específicas do utilizador.
//==============================================================;
//
//  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 mais informações sobre como resolver problemas do cartão Smart Card Plug and Play, consulte o seguinte artigo da TechNet:
Guia de resolução de problemas do cartão Smart Card Plug and Play
aspx http://technet.microsoft.com/en-us/library/dd979536 (WS.10)

Propriedades

Artigo: 976832 - Última revisão: 2 de junho de 2013 - Revisão: 3.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 por um sistema de tradução automática (também designado por Machine translation ou MT), não tendo sido portanto revisto ou traduzido por humanos. A Microsoft tem artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais. O objectivo é simples: oferecer em Português a totalidade dos artigos existentes na base de dados do suporte. Sabemos no entanto que a tradução automática não é sempre perfeita. Esta pode conter erros de vocabulário, sintaxe ou gramática? erros semelhantes aos que um estrangeiro realiza ao falar em Português. A Microsoft não é responsável por incoerências, erros ou estragos realizados na sequência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza actualizações frequentes ao software de tradução automática (MT). Obrigado.
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