Mensaje de error al insertar una tarjeta inteligente en un lector en un equipo basado en Windows Server 2008 R2 o Windows 7: "software de controlador de dispositivo no se instaló correctamente"

Seleccione idioma Seleccione idioma
Id. de artículo: 976832 - Ver los productos a los que se aplica este artículo
Expandir todo | Contraer todo

En esta página

Síntomas

Cuando se inserta una tarjeta inteligente en un lector de tarjetas inteligentes, Windows intenta descargar e instalar los minidrivers de una tarjeta inteligente para la tarjeta a través de servicios de Plug and Play. Si el controlador de la tarjeta inteligente no está disponible en cualquiera de las ubicaciones configuradas previamente, tales como Windows Update, WSUS o rutas de acceso de la intranet, y un proveedor de servicios de cifrado personalizado no está ya instalado en el sistema, recibirá el siguiente mensaje de error en el área de notificación:
El software de controlador de dispositivo no se ha instalado correctamente
Haga clic aquí para obtener más información.
Este mensaje de error desaparece después de varios segundos.

Además, en el Administrador de dispositivos, bajo Otros dispositivos, el dispositivo de tarjeta inteligente tiene un estado de "DNF" (no se encontró el controlador).

Con frecuencia requiere que el usuario obtener uno de los siguientes elementos desde el emisor de tarjeta inteligente para resolver este error:
  1. Un minicontrolador y tarjetas inteligentes de Windows
  2. Un proveedor personalizado de servicios criptográficos (CSP) de la tarjeta inteligente.
  3. Un minicontrolador no y tarjetas inteligentes de Windows
  4. Otro software intermedio como un control ActiveX, PKCS #11 software u otro software personalizado.
Sin embargo, si el usuario no se proporciona con el único elemento 3 o 4 de esta lista, la tarjeta inteligente sigue funcionando en el sistema. Sin embargo, el usuario recibirá el mensaje de error que se menciona en esta sección cada vez inserten la tarjeta inteligente.

Este problema afecta a todas las versiones de Windows 7, Windows Server 2008 R2 y en versiones posteriores de ambos sistemas operativos.

Causa

Todas las tarjetas inteligentes requiere software adicional para funcionar en Windows, a menos que haya un controlador de bandeja de entrada que permite al usuario utilizar la tarjeta sin necesidad de instalar software adicional. El marco de la tarjeta inteligente de Windows se ha mejorado en Windows 7 para habilitar la descarga automática de tarjeta inteligente minidrivers desde Windows Update o desde otras ubicaciones similares como un servidor WSUS cuando se inserta la tarjeta inteligente en el lector. Todas las tarjetas inteligentes que aprobar con éxito los requisitos del logotipo, publicado por el programa de logotipo de Windows, se benefician de esta característica.

Sin embargo, si el software que se necesita para utilizar una tarjeta inteligente en Windows no es y es de un tipo que se diferencia de un minicontrolador, tales como un middleware de controlador de #11, un CSP personalizado, PKCS, o un control ActiveX, la opción de descarga automática se produce un error porque Microsoft certifica sólo una tarjeta inteligente minidrivers. Por lo tanto, si el usuario inserte una tarjeta para que un CSP personalizado no está registrado, el usuario recibe un mensaje de error que indica que el software de controlador para el dispositivo de tarjeta inteligente incluso aunque el usuario puede utilizar la tarjeta inteligente a través de software adicional que se ha instalado en el equipo del usuario de una instalación personalizada.

Solución

Aunque las tarjetas inteligentes seguirán funcionando a pesar de que el mensaje de error que ve el usuario, un emisor de tarjeta inteligente, proveedor o fabricante puede utilizar uno de los métodos siguientes para resolver este error.

Implementar un minicontrolador de tarjeta inteligente

Se recomienda que los emisores de tarjetas, proveedores y fabricantes implementan minidrivers de tarjeta inteligente y participan en el programa de logotipo de Windows para beneficiarse de las mejoras que se introducen en la plataforma tales como tarjetas inteligentes Plug and Play, Device Stage para tarjetas inteligentes, y así sucesivamente.

Para obtener más información acerca de las especificaciones del minicontrolador de tarjeta inteligente para Windows, visite el siguiente sitio Web de Microsoft:
http://www.Microsoft.com/whdc/Device/Input/smartcard/SC-minidriver.mspx
Para obtener más información acerca de cómo empezar a trabajar con el proceso de obtención de un logotipo para su minidrivers de tarjetas inteligentes, visite el siguiente sitio Web del programa de logotipo de Windows:
http://www.Microsoft.com/whdc/winlogo/default.mspx

Implementar un controlador NULL para la tarjeta inteligente

Si tal PKCS, #11 de software personalizado controlador, un control ActiveX o algún otro software intermedio es necesario para habilitar el uso de la tarjeta inteligente en Windows y la implementación de un minicontrolador de tarjeta inteligente o un CSP personalizado es no es una opción práctica, le recomendamos que los emisores de tarjetas, proveedores o fabricantes consideran enviar controladores NULL a Windows Update. El proceso típico para asegurarse de que un controlador NULL está disponible en Windows Update requiere una presentación de dispositivo sin clasificar correctamente a través de Winqual. Si en el futuro, hay un minicontrolador disponible para estas tarjetas, se puede cargar el nuevo controlador a Windows Update al participar en el programa de logotipo de Windows. Los controladores NULL, a continuación, se pueden descargar manualmente por los usuarios finales o se pueden realizar mediante el uso de las actualizaciones opcionales.

La siguiente es una plantilla de muestra para un controlador NULL para una tarjeta 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 generar el identificador de dispositivo de hardware al que hace referencia en el ejemplo de la cadena de DEVICE_ID, siga las instrucciones en la especificación del minicontrolador de tarjeta inteligente. Para ello, visite el siguiente sitio Web de Microsoft:
http://www.Microsoft.com/whdc/Device/Input/smartcard/SC-minidriver.mspx


Para obtener información detallada acerca de cómo enviar a un controlador NULL a Microsoft, póngase en contacto con los servicios de soporte técnico de Microsoft.

Deshabilitar la tarjeta inteligente Plug and Play a través de directiva de grupo para equipos gestionados

Esta opción se recomienda sólo para las implementaciones empresariales donde se administran los equipos por los administradores y todo está instalado el software necesario para trabajar con las tarjetas inteligentes que se utilizan en la empresa mediante el uso de herramientas de administración de software como SMS.

Este procedimiento no se recomienda en los siguientes entornos porque afectará a todas las tarjetas inteligentes en su entorno:
  • Implementaciones comerciales destinados a los usuarios finales, como la banca en línea
  • Plug and Play entornos que incluyan ambas tarjetas inteligentes y tarjetas inteligentes de Plug and Play que utilizar Directiva de grupo para deshabilitar Plug and Play para tarjetas inteligentes
Tarjetas inteligentes Plug and Play se puede deshabilitar completamente en las empresas donde se administra el equipo del usuario final mediante mecanismos como la directiva de grupo.

Si la implementación usa sólo las soluciones de tarjetas inteligentes Plug and Play, tarjetas inteligentes Plug and Play puede deshabilitarse por un administrador local en un equipo cliente. Deshabilitación de tarjetas inteligentes Plug and Play impide que los controladores de tarjetas inteligentes, también conocida como tarjeta inteligente minidrivers, descargar. También evita que los mensajes de tarjetas inteligentes Plug and Play.

Para deshabilitar la tarjeta inteligente Plug and Play en Directiva de grupo local, siga estos pasos:
  1. Haga clic en Inicio, tipo gpedit.msc en el Buscar programas y archivos cuadro y, a continuación, presione ENTRAR.
  2. En el árbol de consola Configuración del equipo, haga clic en Plantillas administrativas.
  3. En el panel de detalles, haga doble clic en Componentes de Windowsy, a continuación, haga doble clic en Tarjeta inteligente.
  4. Con el botón secundario Activar el servicio de tarjetas inteligentes Plug and Playy, a continuación, haga clic en Editar.
  5. Haga clic en Deshabilitadoy, a continuación, haga clic en ACEPTAR.

Cambiar el sistema del usuario final y deshabilitar la tarjeta inteligente Plug and Play para tarjetas específicas

Ésta es la opción recomendada por lo menos. Debe utilizar esta opción sólo si las tarjetas son tarjetas heredadas y no hay planes para implementar minidrivers de tarjeta inteligente en el futuro. Esta opción requiere que el software existente que ya está instalado en el sistema de notificar a Windows que hay un CSP personalizado instalado en el sistema, incluso si no hay tal CSP existe en el sistema del usuario final. En cuanto Windows determina que existe un CSP personalizado ya instalado en el sistema, Windows no intenta descargar e instalar a un controlador a través de tarjetas inteligentes Plug and Play. No se crea ningún nodo de dispositivo para el dispositivo de tarjeta inteligente que está visible en el Administrador de dispositivos. Esta opción produce los siguientes cambios al registro del sistema:

Subclave:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\<Smart card name>
Las entradas del registro de la subclave:
  • ATR = DWORD Hexadecimal: ATR de la tarjeta inteligente separados por comas.
  • ATRMask = DWORD Hexadecimal: máscara para aplicar a la respuesta ATR para enmascarar las bytes insignificantes en la respuesta ATR delimitado por comas.
  • Proveedor de cifrado = valor de tipo String: alguna cadena correspondiente a la tarjeta inteligente.
Por ejemplo:
Subclave:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\Fabrikam ATM card
Las entradas del registro de la subclave:
  • ATR = DWORD Hexadecimal: 3b, dc, 13, 00, 40, 3a, 49, 54, 47, 5f, 4d, 53, 43, 53, 50, 5f, 56, 32
  • ATRMask = DWORD Hexadecimal: ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff
  • Proveedor de cifrado = valor de tipo String: "Proveedor de Fabrikam ATM maniquí"
Para los sistemas de 64 bits, deben realizarse cambios idénticos bajo la subclave siguiente:
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards


Se recomienda que, en lugar de cambiar directamente el registro del sistema, utilizar APIs WinSCard para introducir estos cambios en el sistema. Aquí es el ejemplo de código de ejemplo que detecta la inserción de tarjeta inteligente y, a continuación, deshabilita tarjetas inteligentes Plug and Play para la tarjeta en particular mediante la creación de una entrada del registro que asocia la tarjeta a un proveedor no existe.

Microsoft proporciona ejemplos de programación unicamente con fines ilustrativos, sin ninguna garantía tanto expresa como implícita. Esto incluye, pero no se limita a las garantías implícitas de comerciabilidad o idoneidad para un fin determinado. Este artículo se supone que está familiarizado con el lenguaje de programación que se muestra y con las herramientas que se utilizan para crear y depurar procedimientos. Ingenieros de soporte técnico de Microsoft pueden explicarle la funcionalidad de un determinado procedimiento. Sin embargo, no modificarán estos ejemplos para ofrecer mayor funcionalidad ni crearán procedimientos adaptados a sus requerimientos específicos.
//==============================================================;
//
//  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;
}

Referencias

Para obtener más información acerca de cómo solucionar problemas de tarjetas inteligentes Plug and Play, consulte el siguiente artículo de TechNet:
Guía de solución de problemas de tarjetas inteligentes Plug and Play
http://technet.Microsoft.com/en-us/library/dd979536 (WS.10) .aspx

Propiedades

Id. de artículo: 976832 - Última revisión: domingo, 21 de abril de 2013 - Versión: 4.0
La información de este artículo se refiere 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
Palabras clave: 
kbsmartcard kbcodesnippet kbtshoot kbexpertiseinter kbsurveynew kbprb kbmt KB976832 KbMtes
Traducción automática
IMPORTANTE: Este artículo ha sido traducido por un software de traducción automática de Microsoft (http://support.microsoft.com/gp/mtdetails) en lugar de un traductor humano. Microsoft le ofrece artículos traducidos por un traductor humano y artículos traducidos automáticamente para que tenga acceso en su propio idioma a todos los artículos de nuestra base de conocimientos (Knowledge Base). Sin embargo, los artículos traducidos automáticamente pueden contener errores en el vocabulario, la sintaxis o la gramática, como los que un extranjero podría cometer al hablar el idioma. Microsoft no se hace responsable de cualquier imprecisión, error o daño ocasionado por una mala traducción del contenido o como consecuencia de su utilización por nuestros clientes. Microsoft suele actualizar el software de traducción frecuentemente.
Haga clic aquí para ver el artículo original (en inglés): 976832

Enviar comentarios

 

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