Fehlermeldung beim Einlegen einer Smartcards in einen Reader auf einem Windows 7-basierte oder Windows Server 2008 R2-basierte Computer: "Geräte-Treibersoftware wurde nicht erfolgreich installiert."

SPRACHE AUSWÄHLEN SPRACHE AUSWÄHLEN
Artikel-ID: 976832 - Produkte anzeigen, auf die sich dieser Artikel bezieht
Alles erweitern | Alles schließen

Auf dieser Seite

Problembeschreibung

Wenn Sie eine Smartcard in einen Smartcard-Leser einlegen, versucht Windows herunterladen und installieren die Smartcard-Minidrivers für die Karte über Plug & Play-fähigen Diensten. Wenn der Treiber für die Smartcard nicht verfügbar, über eines der vorkonfigurierten Speicherorten, z. B. Windows Update, WSUS oder Intranet Pfade ist und ein benutzerdefinierten Crypto Service Provider noch nicht auf dem System installiert ist, wird sinngemäß folgende Fehlermeldung im Infobereich angezeigt:
Gerätetreibersoftware wurde nicht erfolgreich installiert.
Klicken Sie hier, um Details anzuzeigen.
Diese Fehlermeldung verschwindet nach einigen Sekunden.

Darüber hinaus im Geräte-Manager unter andere Geräte, besitzt das Smartcard-Gerät einen Status "DNF" (Treiber wurde nicht gefunden).

Dies erfordert häufig den Benutzer eines der folgenden Elemente aus dem Smartcard-Aussteller zur Behebung dieses Fehlers zu erhalten:
  1. Ein Windows-logoed Smartcard-Minitreiber
  2. Eine benutzerdefinierte Kryptografiedienstanbieter (CSP) für die Smartcard.
  3. Ein Windows-logoed Smartcard-Minitreiber
  4. Andere Middleware z. B. ein ActiveX-Steuerelement, PKCS # 11 Software oder andere benutzerdefinierte Software.
Jedoch, wenn der Benutzer mit nur der Eintrag 3 oder 4 aus dieser Liste bereitgestellt wird, weiterhin die Smartcard auf dem System arbeiten. Allerdings erhält der Benutzer die Fehlermeldung, die in diesem Abschnitt jedes Mal erwähnt wird, dass Sie die Smartcard einlegen.

Dieses Problem betrifft alle Versionen von Windows 7, Windows Server 2008 R2 und in späteren Versionen von beiden Betriebssystemen.

Ursache

Alle Smartcards erfordern zusätzlichen Software in Windows arbeiten, es sei denn, es eine Eingangstreiber, in dem den Benutzer die Karte verwenden gibt, ohne zusätzlichen Software installieren zu kann. Die Windows-Smartcard-Framework wurde in Windows 7 So aktivieren Sie das automatische Downloaden von Smartcard-Minidrivers von Windows Update oder von anderen ähnlichen Orten wie z. B. einen WSUS-Server, wenn die Smartcard in den Reader eingefügt wird verbessert. Alle Smartcards, die die Logoanforderungen erfolgreich zu, übergeben wie von der Windows-Logo-Programm veröffentlicht profitieren von dieser Funktion.

Jedoch, wenn die Software, die erforderlich sind, um eine Smartcard in Windows verwenden, nicht logoed ist oder einen Typ, der von einem Minitreiber, z. B. eine PKCS # 11-Treiber, eine benutzerdefinierte CSP, Middleware oder ein ActiveX-Steuerelement unterscheidet kann die Option automatischer Download, da Microsoft nur Smartcard Minidrivers zertifiziert. Wenn der Benutzer eine Karte eingefügt werden für die ein benutzerdefinierter CSP noch nicht registriert wurde, erhält der Benutzer daher eine Fehlermeldung, die besagt, dass die Treibersoftware für das Smart card-Gerät fehlt even though der Benutzer die Smart card durch zusätzliche Software verwenden kann, die auf dem Computer des Benutzers aus einer benutzerdefinierten Installation installiert wurde.

Lösung

Obwohl die Smartcards weiterhin, trotz der Fehlermeldung zu arbeiten, die der Benutzer sieht, können eine Smartcard Aussteller, Kreditor oder beim Hersteller eine der folgenden Methoden Sie um diesen Fehler zu beheben.

Implementieren Sie eine Smartcard-Minitreiber

Es wird empfohlen, Karte Aussteller, Kreditoren und Herstellern Smartcard Minidrivers implementieren und Teilnahme an der Windows-Logo-Programm, von den Verbesserungen zu profitieren, die in der Plattform, z. B. Smartcard Plug And Play-Gerät-Stufe für Smartcards, eingeführt wurden und so weiter.

Weitere Informationen zu Smartcard-Minitreiber Spezifikationen für Windows finden Sie auf folgender Website von Microsoft:
http://www.microsoft.com/whdc/device/input/smartcard/sc-minidriver.mspx
Weitere Informationen zum Einstieg in den Prozess zu erhalten, ein Logo für Ihr Smartcard-Minidrivers finden Sie auf den folgenden Windows Logo Program-Website:
http://www.microsoft.com/whdc/winlogo/default.mspx

Implementieren Sie eine NULL-Treiber für die Smartcard

Wenn benutzerdefinierte Software einen solchen PKCS # 11-Treiber, ein ActiveX-Steuerelement oder einige andere Middleware, erforderlich ist, um die Verwendung von Smartcards auf Windows aktivieren, und Implementieren einer Smartcard-Minitreiber oder einen benutzerdefinierten KRYPTOGRAFIEDIENSTANBIETER keine praktische Option ist, empfiehlt Microsoft, dass die Karte Aussteller, Lieferanten oder Herstellern Bedenken Senden von NULL-Treiber zu Windows Update. Der typische Vorgang für stellt sicher, dass ein NULL-Treiber auf Windows Update verfügbar ist, erfordert eine erfolgreiche nicht klassifiziertes Gerät Versendung über Winqual. Wenn in der Zukunft eine Minitreiber für diese Karten verfügbar ist, kann der neue Treiber zu Windows Update hochgeladen werden, in dem Windows-Logo-Programm teilnehmen. Die NULL-Treiber können dann manuell heruntergeladen werden durch die Endbenutzer oder können mithilfe von optionalen Updates zur Verfügung gestellt werden.

Der folgende Code ist ein Beispiel-Vorlage für einen NULL-Treiber für ein smart sein.
;
; 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 HARDWAREKENNUNG des Geräts zu generieren, die von der DEVICE_ID-Zeichenfolge in der Stichprobe verwiesen wird, folgen Sie den Anweisungen in den Smartcard-Minitreiber Spezifikation. Besuchen Sie hierzu die folgende Website von Microsoft:
http://www.microsoft.com/whdc/device/input/smartcard/sc-minidriver.mspx


Ausführliche Informationen dazu, wie einen NULL-Treiber an Microsoft übermitteln wenden Sie sich an Microsoft Product Support Services.

Deaktivieren von Smart Card Plug And Play über Gruppenrichtlinien auf den verwalteten Computern

Diese Option ist nur für Enterprise-Bereitstellungen empfohlen, auf dem Computer verwaltet werden von Administratoren und alle erforderliche Software mit den Smartcards arbeiten, die im Unternehmen verwendet werden mithilfe von Verwaltungstools Software wie SMS installiert ist.

Dieses Verfahren wird nicht in den folgenden Umgebungen empfohlen, da es die Smartcards in Ihrer Umgebung auswirken:
  • Kommerzielle Bereitstellungen, die Endbenutzer, wie z. B. Onlinebanking
  • Umgebungen, die beide enthalten Play Plug &, Smartcards und nicht Plug & Play-Smartcards, die mithilfe von Gruppenrichtlinien zum Deaktivieren von Plug & Play-fähigen für Smartcards
Smart Card Plug And Play kann in Unternehmen vollständig deaktiviert werden, auf dem Computer des Endbenutzers durch Mechanismen wie z. B. Gruppenrichtlinien verwaltet wird.

Wenn Ihre Bereitstellung nur nicht Plug & Play-Smartcard-Lösungen verwendet, kann von einem lokalen Administrator auf einem Clientcomputer Smart Card Plug And Play deaktiviert werden. Smart Card Plug And Play deaktivieren wird verhindert, dass Smartcard-Treiber, auch bekannt als Smartcard Minidrivers downloaden. Es verhindert außerdem Smart Card Plug And Play Eingabeaufforderungen.

Um die Smart Card Plug And Play in lokaler Gruppenrichtlinie zu deaktivieren, gehen Sie folgendermaßen vor:
  1. Klicken Sie auf Start, geben Sie gpedit.msc im Feld Suchen Programme und Dateien, und drücken Sie anschließend die [EINGABETASTE].
  2. Klicken Sie in der Konsolenstruktur unter Computerkonfiguration auf Administrative Vorlagen.
  3. Klicken Sie im Detailfenster doppelklicken Sie auf Windows-Komponenten, und doppelklicken Sie dann auf Smart Card.
  4. Klicken Sie mit der rechten Maustaste auf Smart Card Plug & Play-Dienst aktivieren, und klicken Sie dann auf Bearbeiten.
  5. Klicken Sie auf deaktiviert, und klicken Sie dann auf OK.

End-System des Benutzers ändern und Smart Card Plug And Play für bestimmte Karten deaktivieren

Dies ist die Option am wenigsten empfohlen. Sie sollten diese Option nur dann verwenden, wenn die Karten ältere Karten sind, und es gibt derzeit keine Pläne, Smartcard-Minidrivers in Zukunft zu implementieren. Diese Option erfordert, dass die vorhandene Software, die bereits auf dem System installiert ist benachrichtigt Windows, dass es eine benutzerdefinierte CSP auf dem System installiert werden, auch wenn keine solche CSP auf dem Endbenutzer-System vorhanden ist. Sobald Windows feststellt, dass eine benutzerdefinierte CSP auf dem System bereits installiert ist, versucht Windows nicht zum Downloaden und installieren Sie einen Treiber über Smart Card Plug And Play. Kein Geräteknoten für das Smartcard-Gerät wird erstellt, die im Geräte-Manager angezeigt wird. Diese Option ist das Ergebnis in die folgenden Änderungen in der Registrierung:

Unterschlüssel:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\<Smart card name>
Teilschlüssel Registrierungseinträge:
  • ATR hexadezimal DWORD =: Komma als Trennzeichen ATR der Smartcard.
  • ATRMask = hexadezimal DWORD: Komma als Trennzeichen Maske, die die Maske, nichtsignifikante Bytes in den ATR ATR zuweisen.
  • Krypto-Anbieter = String-Wert: einige Zeichenfolge für die Smartcard relevant.
Beispiel:
Unterschlüssel:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\Fabrikam ATM card
Teilschlüssel Registrierungseinträge:
  • ATR hexadezimal DWORD =: 3 b, dc, 13, 00, 40, 3a, 49, 54, 47 5f, 4d, 53, 43, 53, 50, 5f, 56, 32
  • ATRMask = hexadezimal DWORD: ff ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff
  • Krypto-Anbieter = String-Wert: "Fabrikam ATM Dummy-Provider"
Für X 64-Bit-Systemen identische Änderungen müssen vorgenommen werden unter dem folgenden Teilschlüssel:
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards


Es wird empfohlen, dass statt die Registrierung direkt zu ändern, Sie WinSCard APIs, verwenden um diese Änderungen auf das System eingeführt. So sieht Beispiel Codebeispiel, in dem Einlegen der Smartcard erkennt und deaktiviert dann Smart Card Plug And Play für die bestimmten Karte durch Erstellen eines Registrierungseintrags, in dem die Karte einen nicht vorhandenen Anbieter zuordnet.

Microsoft bietet Programmierbeispiele, lediglich zur Veranschaulichung, ohne Gewährleistung, weder implizit noch explizit. Dies umfasst, ist jedoch nicht beschränkt auf konkludenten Garantien der Handelsüblichkeit oder Eignung für einen bestimmten Zweck. In diesem Artikel wird davon ausgegangen, dass Sie mit der Programmiersprache, die gezeigt wird, ist und mit den Tools, die zum Erstellen und Debuggen von Prozeduren verwendet werden, vertraut sind. Mitarbeiter der Microsoft Product Support Services können bei der Erläuterung der Funktionalität bestimmter Prozeduren helfen. Jedoch können Sie nicht ändern diese Beispiele in Bezug auf eine erweiterte Funktionalität oder Prozeduren entwickeln, die auf Ihre besonderen Bedürfnisse zugeschnitten.
//==============================================================;
//
//  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;
}

Informationsquellen

Weitere Informationen zur Behandlung von Problemen mit Plug & Play-fähigen Smartcard finden Sie unter den folgenden TechNet-Artikel:
Smart Card Plug And Play Troubleshooting Guide
http://technet.microsoft.com/en-us/library/dd979536(WS.10).aspx

Eigenschaften

Artikel-ID: 976832 - Geändert am: Freitag, 23. Oktober 2009 - Version: 2.0
Die Informationen in diesem Artikel beziehen sich auf:
  • 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
Keywords: 
kbmt kbsmartcard kbcodesnippet kbtshoot kbexpertiseinter kbsurveynew kbprb KB976832 KbMtde
Maschinell übersetzter Artikel
Wichtig: Dieser Artikel wurde maschinell und nicht von einem Menschen übersetzt. Die Microsoft Knowledge Base ist sehr umfangreich und ihre Inhalte werden ständig ergänzt beziehungsweise überarbeitet. Um Ihnen dennoch alle Inhalte auf Deutsch anbieten zu können, werden viele Artikel nicht von Menschen, sondern von Übersetzungsprogrammen übersetzt, die kontinuierlich optimiert werden. Doch noch sind maschinell übersetzte Texte in der Regel nicht perfekt, insbesondere hinsichtlich Grammatik und des Einsatzes von Fremdwörtern sowie Fachbegriffen. Microsoft übernimmt keine Gewähr für die sprachliche Qualität oder die technische Richtigkeit der Übersetzungen und ist nicht für Probleme haftbar, die direkt oder indirekt durch Übersetzungsfehler oder die Verwendung der übersetzten Inhalte durch Kunden entstehen könnten.
Den englischen Originalartikel können Sie über folgenden Link abrufen: 976832
Microsoft stellt Ihnen die in der Knowledge Base angebotenen Artikel und Informationen als Service-Leistung zur Verfügung. Microsoft übernimmt keinerlei Gewährleistung dafür, dass die angebotenen Artikel und Informationen auch in Ihrer Einsatzumgebung die erwünschten Ergebnisse erzielen. Die Entscheidung darüber, ob und in welcher Form Sie die angebotenen Artikel und Informationen nutzen, liegt daher allein bei Ihnen. Mit Ausnahme der gesetzlichen Haftung für Vorsatz ist jede Haftung von Microsoft im Zusammenhang mit Ihrer Nutzung dieser Artikel oder Informationen ausgeschlossen.

Ihr Feedback an uns

 

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