Fehlermeldung beim Einfügen einer intelligenten Karte in einen Reader: Gerätetreibersoftware wurde nicht erfolgreich installiert

Dieser Artikel bietet eine Lösung für einen Fehler, der auftritt, wenn Sie eine intelligente Karte in einen Reader einfügen.

Gilt für: Windows 7 Service Pack 1, Windows Server 2012 R2
Ursprüngliche KB-Nummer: 976832

Symptome

Wenn Sie eine intelligente Karte in einen Smart Karte-Reader einfügen, versucht Windows, die Smart Karte Minidriver für die Karte über Plug & Play-Dienste herunterzuladen und zu installieren. Wenn der Treiber für die intelligente Karte an keinem der vorkonfigurierten Speicherorte wie z. B. Windows Update-, WSUS- oder Intranetpfade verfügbar ist und noch kein benutzerdefinierter Kryptografiedienstanbieter auf dem System installiert ist, erhalten Sie die folgende Fehlermeldung im Infobereich:

Gerätetreibersoftware wurde nicht erfolgreich installiert

Klicken Sie hier, um details zu erhalten.

Diese Fehlermeldung wird nach einigen Sekunden nicht mehr angezeigt.

Darüber hinaus verfügt das Smartcardgerät in Geräte-Manager unter Andere Geräte über eine status DNF (Treiber nicht gefunden).

Dies erfordert häufig, dass der Benutzer eines der folgenden Elemente vom Smart Karte Aussteller erhält, um diesen Fehler zu beheben:

  1. Ein von Windows protokollierter smarter Karte Minidriver.
  2. Ein benutzerdefinierter Kryptografiedienstanbieter (CSP) für die Smart Karte.
  3. Ein windows-nicht angemeldeter smarter Karte Minidriver.
  4. Andere Middleware wie ein ActiveX-Steuerelement, PKCS#11-Software oder andere benutzerdefinierte Software.

Wenn dem Benutzer jedoch nur Element 3 oder 4 aus dieser Liste zur Verfügung gestellt wird, funktioniert die intelligente Karte weiterhin auf dem System. Der Benutzer erhält die in diesem Abschnitt erwähnte Fehlermeldung jedoch jedes Mal, wenn er die intelligente Karte einfügt.

Dieses Problem betrifft alle Versionen von Windows 7, Windows Server 2008 R2 und in höheren Versionen beider Betriebssysteme.

Ursache

Alle Smartcards erfordern zusätzliche Software, um in Windows zu funktionieren, es sei denn, es gibt einen Posteingangstreiber, mit dem der Benutzer die Karte verwenden kann, ohne zusätzliche Software zu installieren. Das Windows SmartCard Framework wurde in Windows 7 verbessert, um das automatische Herunterladen von smarten Karte Minidrivern von Windows Update oder von anderen ähnlichen Orten wie einem WSUS-Server zu ermöglichen, wenn die intelligente Karte in den Reader eingefügt wird. Von diesem Feature profitieren alle Smartcards, die die Vom Windows-Logo-Programm veröffentlichten Logoanforderungen erfolgreich erfüllen.

Wenn die Software, die für die Verwendung eines intelligenten Karte in Windows erforderlich ist, jedoch nicht angemeldet ist oder von einem Typ ist, der sich von einem Minitreiber unterscheidet, z. B. ein PKCS#11-Treiber, ein benutzerdefinierter CSP, Middleware oder ein ActiveX-Steuerelement, schlägt die Option für den automatischen Download fehl, da Microsoft nur intelligente Karte Minidriver zertifiziert. Wenn der Benutzer daher eine Karte einfügt, für die noch kein benutzerdefinierter CSP registriert ist, erhält der Benutzer eine Fehlermeldung, die besagt, dass die Treibersoftware für das Smart Karte Gerät fehlt, obwohl der Benutzer die intelligente Karte über zusätzliche Software verwenden kann, die von einer benutzerdefinierten Installation auf dem Computer des Benutzers installiert wurde.

Lösung

Obwohl die Smartcards trotz der dem Benutzer angezeigten Fehlermeldung weiterhin funktionieren, kann ein intelligenter Karte Aussteller, Anbieter oder Hersteller eine der folgenden Methoden verwenden, um diesen Fehler zu beheben.

Implementieren eines Smart Karte Minidrivers

Es wird empfohlen, dass Karte Aussteller, Anbieter und Hersteller intelligente Karte Minidriver implementieren und am Windows-Logo-Programm teilnehmen, um von den Verbesserungen zu profitieren, die auf der Plattform eingeführt wurden, z. B. Smartcard-Plug & Play, Device Stage für Smartcards usw.

Implementieren eines NULL-Treibers für Ihre intelligente Karte

Wenn benutzerdefinierte Software wie ein PKCS#11-Treiber, ein ActiveX-Steuerelement oder eine andere Middleware erforderlich ist, um die Verwendung intelligenter Karte unter Windows zu ermöglichen, und die Implementierung eines Smart Karte Minidrivers oder eines benutzerdefinierten CSP keine praktische Option ist, empfehlen wir, dass Karte Aussteller, Anbieter oder Hersteller erwägen, NULL-Treiber an Windows Update zu übermitteln. Der typische Prozess, um sicherzustellen, dass ein NULL-Treiber auf Windows Update erfordert eine erfolgreiche, nicht klassifizierte Geräteübermittlung über Winqual. Wenn in Zukunft ein Minitreiber für diese Karten verfügbar ist, kann der neue Treiber in Windows Update hochgeladen werden, indem sie am Windows-Logo-Programm teilnehmen. Die NULL-Treiber können dann manuell von den Endbenutzern heruntergeladen oder mithilfe optionaler Updates zur Verfügung gestellt werden.

Es folgt eine Beispielvorlage für einen NULL-Treiber für eine intelligente Karte.

;  
; 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"

Um die Hardwaregeräte-ID zu generieren, auf die in der DEVICE_ID Zeichenfolge im Beispiel verwiesen wird, befolgen Sie die Anweisungen in der Spezifikation des smarten Karte Minidrivers.

Ausführliche Informationen zum Übermitteln eines NULL-Treibers an Microsoft finden Sie unter Microsoft-Kundendienst.

Deaktivieren von Smartcard-Plug & Play bis Gruppenrichtlinie für verwaltete Computer

Diese Option wird nur für Unternehmensbereitstellungen empfohlen, bei denen die Computer von Administratoren verwaltet werden und die gesamte erforderliche Software zum Arbeiten mit den im Unternehmen verwendeten Smartcards mithilfe von Softwareverwaltungstools wie SMS installiert wird.

Von diesem Verfahren wird in den folgenden Umgebungen abgeraten, da es sich auf alle Smartcards in Ihrer Umgebung auswirkt:

  • Kommerzielle Bereitstellungen, die auf Endbenutzer ausgerichtet sind, z. B. Onlinebanking.
  • Umgebungen, die sowohl Plug & Play Smartcards als auch Nicht-Plug & Play-Smartcards enthalten, die Gruppenrichtlinie verwenden, um Plug & Play für Smartcards zu deaktivieren.

Smartcard-Plug & Play können in Unternehmen deaktiviert werden, in denen der Computer des Endbenutzers durch Mechanismen wie Gruppenrichtlinie verwaltet wird.

Wenn Ihre Bereitstellung nur nicht Plug & Play Smart Karte-Lösungen verwendet, können Smartcard-Plug & Play von einem lokalen Administrator auf einem Clientcomputer deaktiviert werden. Das Deaktivieren von Smartcard-Plug & Play verhindert, dass Smart Karte Treiber, die auch als Smart Karte Minidriver bezeichnet werden, heruntergeladen werden. Außerdem wird verhindert, dass Smartcard-Plug & Play Eingabeaufforderungen angezeigt werden.

Führen Sie die folgenden Schritte aus, um smartcard-Plug & Play in lokalen Gruppenrichtlinie zu deaktivieren:

  1. Klicken Sie auf Start, geben Sie gpedit.msc in das Feld Programme und Dateien suchen ein, und drücken Sie dann die EINGABETASTE.

  2. Klicken Sie in der Konsolenstruktur unter Computerkonfiguration auf Administrative Vorlagen.

  3. Doppelklicken Sie im Detailbereich auf Windows-Komponenten, und doppelklicken Sie dann auf Smartcard.

  4. Klicken Sie mit der rechten Maustaste auf Smartcard Plug & Play Dienst aktivieren, und klicken Sie dann auf Bearbeiten.

  5. Klicken Sie auf Deaktiviert und dann auf OK.

Ändern des Systems des Endbenutzers und Deaktivieren von Smartcard-Plug & Play für bestimmte Karten

Dies ist die am wenigsten empfohlene Option. Sie sollten diese Option nur verwenden, wenn es sich bei den Karten um Legacykarten handelt und es keine Pläne gibt, smarte Karte Minidriver in Zukunft zu implementieren. Diese Option erfordert, dass die vorhandene Software, die bereits auf dem System installiert ist, Windows darüber informiert, dass ein benutzerdefinierter CSP auf dem System installiert ist, obwohl auf dem Endbenutzersystem kein solcher CSP vorhanden ist. Sobald Windows feststellt, dass bereits ein benutzerdefinierter CSP auf dem System installiert ist, versucht Windows nicht, einen Treiber über Smartcard-Plug & Play herunterzuladen und zu installieren. Es wird kein Geräteknoten für das Smart Karte-Gerät erstellt, der in Geräte-Manager sichtbar ist. Diese Option führt zu den folgenden Änderungen an der Systemregistrierung:

Unterschlüssel: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\<Smart card name>

Registrierungseinträge für Unterschlüssel:

  • ATR=Hexadezimales DWORD: Durch Kommas getrennte ATR des intelligenten Karte.

  • ATRMask= Hexadezimales DWORD: Durch Kommas getrennte Maske, die auf den ATR angewendet werden soll, um unwichtige Bytes in der ATR zu maskieren.

  • Crypto Provider=String value: Einige Zeichenfolgen, die für Ihre intelligente Karte relevant sind.

Zum Beispiel:

Unterschlüssel: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\Fabrikam ATM card

Registrierungseinträge für Unterschlüssel:

  • ATR=Hexadezimales DWORD: 3b,dc,13,00,40,3a,49,54,47,5f,4d,53,53,53,50,5f,56,32
  • ATRMask= Hexadezimales DWORD: ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff
  • Crypto Provider=String value: Fabrikam ATM Dummy Provider

Bei x64-Bit-Systemen müssen identische Änderungen unter dem folgenden Unterschlüssel vorgenommen werden: HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards

Anstatt die Systemregistrierung direkt zu ändern, sollten Sie winSCard-APIs verwenden, um diese Änderungen in das System einzuführen. Im Folgenden finden Sie ein Beispielcodebeispiel, das das Einfügen von smarten Karte erkennt und dann die Smartcard-Plug & Play für die jeweilige Karte deaktiviert, indem ein Registrierungseintrag erstellt wird, der die Karte einem nicht vorhandenen Anbieter zuordnet.

Die Verwendung der hier aufgeführten Informationen, Makro- oder Programmcodes geschieht auf Ihre eigene Verantwortung. Microsoft stellt Ihnen diese Informationen sowie Makro- und Programmlistings ohne Gewähr auf Richtigkeit, Vollständigkeit und/oder Funktionsfähigkeit sowie ohne Anspruch auf Support zur Verfügung. Die zur Verfügung gestellten Makro- und Programmierungsbeispiele sollen lediglich exemplarisch die Funktionsweise des Beispiels aufzeigen. Die Mitarbeiter der Microsoft Product Support Services erklären Ihnen gerne die Funktionsweise einer bestimmten Prozedur. Die Mitarbeiter werden diese Beispiele jedoch weder modifizieren, um zusätzliche Funktionalität zu schaffen, noch Prozeduren entwickeln, die auf Ihre spezifischen Bedürfnisse zugeschnitten sind.

//==============================================================;
//
// 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;
}

References

Weitere Informationen zur Behandlung von Problemen mit intelligentem Karte Plug & Play finden Sie im Leitfaden zur Problembehandlung für Smartcards.

Datensammlung

Wenn Sie Unterstützung vom Microsoft-Support benötigen, empfehlen wir Ihnen, die Informationen zu sammeln, indem Sie die Schritte unter Sammeln von Informationen mithilfe von TSS für Bereitstellungsprobleme ausführen.