Message d'erreur lorsque vous insérez une carte à puce dans un lecteur sur un ordinateur basé sur Windows Server 2008 R2 ou Windows 7: « logiciel de pilote de périphérique n'a pas été installée »

Traductions disponibles Traductions disponibles
Numéro d'article: 976832 - Voir les produits auxquels s'applique cet article
Agrandir tout | Réduire tout

Sommaire

Symptômes

Lorsque vous insérez une carte à puce dans un lecteur de carte à puce, Windows essaie de télécharger et installer le minidrivers de carte à puce pour la carte via les services Plug-and-Play. Si le pilote pour la carte à puce n'est pas disponible pour les emplacements préconfigurés, tels que Windows Update, WSUS ou chemins d'accès intranet, et un fournisseur de services de chiffrement personnalisé n'est pas déjà installé sur le système, le message d'erreur suivant s'affiche dans la zone de notification :
Logiciel de pilote de périphérique n'a pas été installé avec succès
Cliquez ici pour plus d'informations.
Ce message d'erreur disparaît après quelques secondes.

En outre, dans Gestionnaire de périphériques, sous Autres périphériques, le périphérique de carte à puce a le statut de « Fnd » (pilote introuvable).

Cela nécessite souvent l'utilisateur obtenir un des éléments suivants à partir de l'émetteur de carte à puce pour résoudre cette erreur :
  1. Un minipilote de carte à puce logoed Windows
  2. Un fournisseur personnalisé de services cryptographiques (CSP) pour la carte à puce.
  3. Un minipilote de carte à puce non logoed Windows
  4. Autre middleware tel qu'un contrôle ActiveX, PKCS # #11 logiciel ou autres logiciels personnalisés.
Toutefois, si l'utilisateur est fourni avec un seul élément 3 ou 4 à partir de cette liste, la carte à puce continue à fonctionner sur le système. Toutefois, l'utilisateur recevra le message d'erreur qui est mentionné dans cette section chaque fois qu'ils insèrent la carte à puce.

Ce problème affecte toutes les versions de Windows 7, Windows Server 2008 R2 et dans les versions ultérieures de ces deux systèmes d'exploitation.

Cause

Toutes les cartes à puce nécessitent des logiciels supplémentaires pour fonctionner dans Windows, sauf s'il existe un pilote fourni avec Windows qui permet à l'utilisateur d'utiliser la carte sans installer de logiciel supplémentaire. L'infrastructure de carte à puce Windows a été amélioré dans Windows 7 pour activer le téléchargement automatique de minidrivers de carte à puce à partir de Windows Update ou d'autres emplacements similaires tels qu'un serveur WSUS lorsque la carte à puce est insérée dans le lecteur. Toutes les cartes à puce qui passent avec succès les impératifs du logo, telles que publiées par le programme de Logo Windows, bénéficier de cette fonction.

Toutefois, si le logiciel est requis pour utiliser une carte à puce dans Windows n'est pas logoed ou a un type qui diffère d'un minipilote, tel qu'un pilote PKCS # #11, un fournisseur de services cryptographiques personnalisé, middleware ou un contrôle ActiveX, le téléchargement automatique option échoue parce que Microsoft ne certifie que les minidrivers de carte à puce. Par conséquent, si l'utilisateur insère une carte pour laquelle un fournisseur de services cryptographiques personnalisé n'est pas déjà inscrit, l'utilisateur reçoit un message d'erreur indiquant que le logiciel du pilote est manquant pour le périphérique de carte à puce même si l'utilisateur peut utiliser la carte à puce via un logiciel supplémentaire qui a été installé sur l'ordinateur de l'utilisateur à partir d'une installation personnalisée.

Résolution

Bien que les cartes à puce continuent de fonctionner malgré le message d'erreur que l'utilisateur voit, un émetteur de carte à puce, le fournisseur ou le fabricant peut utiliser une des méthodes suivantes pour résoudre cette erreur.

Implémenter un minipilote de carte à puce

Il est recommandé que les sociétés émettrices de cartes, les fournisseurs et les fabricants implémentent minidrivers de carte à puce et participent au programme Logo Windows pour tirer parti des améliorations qui ont été introduites dans la plate-forme, tels que cartes à puce Plug and Play, Device Stage de cartes à puce, et ainsi de suite.

Pour plus d'informations sur les spécifications de minipilote de carte à puce pour Windows, visitez le site Web de Microsoft à l'adresse suivante :
http://www.Microsoft.com/whdc/device/Input/SmartCard/SC-minidriver.mspx
Pour plus d'informations sur la mise en route avec le processus d'obtention d'un logo pour votre minidrivers de carte à puce, visitez le site Web Windows Logo Program suivant :
http://www.Microsoft.com/whdc/winlogo/default.mspx

Mettre en ?uvre un pilote nul pour votre carte à puce

Si le logiciel personnalisé tel un pilote PKCS # #11, un contrôle ActiveX ou certains autre middleware est nécessaire pour activer l'utilisation de carte à puce sous Windows, et l'implémentation d'un minipilote de carte à puce ou un fournisseur de services cryptographiques personnalisé n'est pas une option pratique, nous recommandons de sociétés émettrices de cartes, des fournisseurs ou des fabricants mette soumettant des pilotes NULL à Windows Update. Le processus classique de s'assurer qu'un pilote nul est disponible sur Windows Update nécessite une soumission de périphérique non classifié réussies par le biais de Winqual. Si, à l'avenir, un minipilote est disponible pour ces cartes, le nouveau pilote peut être téléchargé vers Windows Update en participant au programme de Logo Windows. Les pilotes NULL peuvent ensuite être téléchargées manuellement par les utilisateurs finaux ou peuvent accessibles à l'aide de mises à jour facultatives.

Voici un exemple de modèle pour un pilote nul pour une carte à puce.
;
; 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"
Pour générer l'ID de périphérique matériel qui est référencé par la chaîne DEVICE_ID dans l'échantillon, suivez les instructions de spécification du minipilote de carte à puce. Pour ce faire, visitez le site Web de Microsoft à l'adresse suivante :
http://www.Microsoft.com/whdc/device/Input/SmartCard/SC-minidriver.mspx


Pour obtenir des informations détaillées sur la soumission d'un pilote nul pour Microsoft, veuillez contacter le service clientèle Microsoft.

Désactiver la carte à puce Plug and Play via la stratégie de groupe pour les ordinateurs gérés

Cette option est recommandée uniquement pour les déploiements d'entreprise où les ordinateurs sont gérés par les administrateurs et tous les logiciels nécessaires pour travailler avec les cartes à puce qui sont utilisés dans l'entreprise sont installé à l'aide des outils de gestion de logiciels tel que SMS.

Cette procédure est vivement déconseillée dans les environnements suivants, car cela affectera toutes les cartes à puce dans votre environnement :
  • Déploiements commerciales qui ciblent les utilisateurs finaux, tels que les opérations bancaires en ligne
  • Les environnements qui incluent les deux Plug and Play des cartes à puce et des cartes à puce non Plug-and-Play qui utilisent la stratégie de groupe pour désactiver le Plug-and-Play pour les cartes à puce
Carte à puce Plug-and-Play peut être complètement désactivé dans les entreprises où l'ordinateur de l'utilisateur final est gérée par des mécanismes tels que stratégie de groupe.

Si votre déploiement utilise uniquement les solutions de carte à puce de non-Plug-and-Play, carte à puce Plug-and-Play peut être désactivé par un administrateur local sur un ordinateur client. Désactivation de la carte à puce Plug-and-Play empêche le téléchargement des pilotes de carte à puce, également connu sous le nom minidrivers de carte à puce. Elle empêche également la carte à puce Plug-and-Play à l'écran.

Pour désactiver la carte à puce Plug and Play dans la stratégie de groupe local, procédez comme suit :
  1. Cliquez sur Démarrer, type gpedit.msc dans le Rechercher les programmes et fichiers zone et appuyez sur ENTRÉE.
  2. Dans l'arborescence de la console sous Configuration de l'ordinateur, cliquez sur Modèles d'administration.
  3. Dans le volet d'informations, double-cliquez sur Composants de Windows, puis double-cliquez sur Carte à puce.
  4. Avec le bouton droit Activer le service de carte à puce Plug-and-Play, puis cliquez sur Modifier.
  5. Cliquez sur Désactivé, puis cliquez sur OK.

Modifier le système de l'utilisateur final et de désactiver la carte à puce Plug and Play pour les cartes spécifiques

Il s'agit de l'option recommandée moindres. Vous devez utiliser cette option uniquement si les cartes sont hérités et il n'est pas prévu pour implémenter des minidrivers de carte à puce à l'avenir. Cette option nécessite que le logiciel existant qui est déjà installé sur le système de notification Windows qu'il y a un fournisseur de services cryptographiques personnalisé installé sur le système même si aucun CSP telle n'existe sur le système de l'utilisateur final. Dès que Windows détermine qu'il y a un fournisseur de services cryptographiques personnalisé déjà installé sur le système, Windows ne tente pas à télécharger et installer un pilote par le biais de carte à puce Plug-and-Play. Aucun n?ud de périphérique pour le périphérique de carte à puce n'est créé qui est visible dans le Gestionnaire de périphériques. Cette option entraîne les modifications suivantes au Registre système :

Sous-clé :
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\<Smart card="" name=""></Smart>
Entrées de la sous-clé de Registre :
  • ATR = DWORD hexadécimale : séparés par des virgules ATR de la carte à puce.
  • ATRMask = DWORD hexadécimale : séparés par des virgules masque à appliquer à la RAR permet de masquer des octets non significatifs dans l'ATR.
  • Fournisseur de chiffrement = valeur de type String : certains chaîne pertinente pour votre carte à puce.
Par exemple :
Sous-clé :
Carte ATM HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\Fabrikam
Entrées de la sous-clé de Registre :
  • ATR = DWORD hexadécimale: 3 b, dc, 13, 00, 40, 3 a, 49, 54, 47, 5f, 4d, 53, 43, 53, 50, 5f, 56, 32
  • ATRMask = DWORD hexadécimale: ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff
  • Fournisseur de chiffrement = valeur de chaîne: « Fabrikam ATM factice Provider »
Pour les systèmes x 64 bits, les modifications identiques doivent être effectuées sous la sous-clé suivante :
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards


Nous recommandons que, au lieu de modifier directement le Registre système, vous utilisez WinSCard APIs d'introduire ces modifications au système. Voici un exemple de code qui détecte l'insertion de la carte à puce et puis désactive la carte à puce Plug and Play pour la carte particulière en créant une entrée de Registre qui associe la carte à un fournisseur non existant.

Microsoft fournit des exemples de programmation à titre d'illustration uniquement, sans garantie expresse ou implicite. Cela sous-entend, sans toutefois être exhaustif, un processus opérationnel pour des circonstances d'utilisation particulières. Cet article suppose que vous êtes familiarisé avec le langage de programmation présenté ainsi qu'avec les outils utilisés pour créer et déboguer les procédures. Ingénieurs du support technique Microsoft peuvent vous expliquer les fonctionnalités d'une procédure particulière. Toutefois, ils ne modifieront pas ces exemples pour fournir des fonctionnalités supplémentaires ou créer des procédures répondant à vos besoins spécifiques.
//==============================================================;
//
//  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;
}

Références

Pour plus d'informations sur la résolution des problèmes de Plug-and-Play de carte à puce, consultez l'article TechNet suivant :
Guide de dépannage de cartes à puce Plug and Play
http://technet.Microsoft.com/en-us/library/dd979536 (WS.10) .aspx

Propriétés

Numéro d'article: 976832 - Dernière mise à jour: lundi 3 décembre 2012 - Version: 4.0
Les informations contenues dans cet article s'appliquent au(x) produit(s) suivant(s):
  • Windows Server 2008 R2 Datacenter
  • Windows Server 2008 R2 Enterprise
  • Windows Server 2008 R2 Standard
  • Windows 7 Entreprise
  • Windows 7 Édition Familiale Basique
  • Windows 7 Édition Familiale Premium
  • Windows 7 Professionnel
  • Windows 7 Édition Starter
  • Windows 7 Édition Integrale
Mots-clés : 
kbsmartcard kbcodesnippet kbtshoot kbexpertiseinter kbsurveynew kbprb kbmt KB976832 KbMtfr
Traduction automatique
IMPORTANT : Cet article est issu du système de traduction automatique mis au point par Microsoft (http://support.microsoft.com/gp/mtdetails). Un certain nombre d?articles obtenus par traduction automatique sont en effet mis à votre disposition en complément des articles traduits en langue française par des traducteurs professionnels. Cela vous permet d?avoir accès, dans votre propre langue, à l?ensemble des articles de la base de connaissances rédigés originellement en langue anglaise. Les articles traduits automatiquement ne sont pas toujours parfaits et peuvent comporter des erreurs de vocabulaire, de syntaxe ou de grammaire (probablement semblables aux erreurs que ferait une personne étrangère s?exprimant dans votre langue !). Néanmoins, mis à part ces imperfections, ces articles devraient suffire à vous orienter et à vous aider à résoudre votre problème. Microsoft s?efforce aussi continuellement de faire évoluer son système de traduction automatique.
La version anglaise de cet article est la suivante: 976832
L'INFORMATION CONTENUE DANS CE DOCUMENT EST FOURNIE PAR MICROSOFT SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE. L'UTILISATEUR ASSUME LE RISQUE DE L'UTILISATION DU CONTENU DE CE DOCUMENT. CE DOCUMENT NE PEUT ETRE REVENDU OU CEDE EN ECHANGE D'UN QUELCONQUE PROFIT.

Envoyer des commentaires

 

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