Okuyucuya akıllı kart taktığınızda hata iletisi: Cihaz sürücüsü yazılımı başarıyla yüklenmedi

Bu makalede, okuyucuya akıllı kart taktığınızda oluşan bir hataya çözüm sağlanır.

Şunlar için geçerlidir: Windows 7 Service Pack 1, Windows Server 2012 R2
Özgün KB numarası: 976832

Belirtiler

Akıllı kart okuyucuya akıllı kart taktığınızda Windows, Tak ve Kullan hizmetleri aracılığıyla kart için akıllı kart minidriver'larını indirmeye ve yüklemeye çalışır. Akıllı kartın sürücüsü Windows Update, WSUS veya intranet yolları gibi önceden yapılandırılmış konumların hiçbirinde kullanılamıyorsa ve sistemde özel bir Şifreleme hizmeti sağlayıcısı yüklü değilse, bildirim alanında aşağıdaki hata iletisini alırsınız:

Cihaz sürücüsü yazılımı başarıyla yüklenmedi

Ayrıntılar için buraya tıklayın.

Bu hata iletisi birkaç saniye sonra kaybolur.

Ek olarak, Aygıt Yöneticisi'da, Diğer cihazlar'ın altında Akıllı Kart cihazı DNF (Sürücü bulunamadı) durumuna sahiptir.

Bu genellikle kullanıcının bu hatayı çözmek için akıllı kart verenden aşağıdaki öğelerden birini almasını gerektirir:

  1. Windows tarafından kaydedilen akıllı kart minidriver.
  2. Akıllı kart için özel bir şifreleme hizmeti sağlayıcısı (CSP).
  3. Windows logolu olmayan akıllı kart minidriver.
  4. ActiveX denetimi, PKCS#11 yazılımı veya diğer özel yazılımlar gibi diğer ara yazılımlar.

Ancak, kullanıcıya bu listeden yalnızca 3. veya 4. öğe sağlanmışsa, akıllı kart sistemde çalışmaya devam eder. Ancak, kullanıcı akıllı kartı her taktığında bu bölümde belirtilen hata iletisini alır.

Bu sorun, Windows 7, Windows Server 2008 R2 ve her iki işletim sisteminin sonraki sürümlerindeki tüm sürümlerini etkiler.

Neden

Kullanıcının kartı ek yazılım yüklemeden kullanmasına izin veren bir gelen kutusu sürücüsü olmadığı sürece tüm akıllı kartların Windows'ta çalışması için ek yazılım gerekir. Windows Akıllı Kart Çerçevesi, akıllı kart okuyucuya takıldığında akıllı kart minidriver'larının Windows Update veya WSUS sunucusu gibi diğer benzer konumlardan otomatik olarak indirilmesini sağlamak için Windows 7'de geliştirilmiştir. Windows Logo Programı tarafından yayımlanan logo gereksinimlerini başarıyla geçen tüm akıllı kartlar bu özellikten yararlanmaktadır.

Ancak, Windows'ta akıllı kart kullanmak için gereken yazılım logolu değilse veya PKCS#11 sürücüsü, özel CSP, ara yazılım veya ActiveX denetimi gibi bir minidriver'dan farklı bir türdeyse, Microsoft yalnızca akıllı kart minidriver'larını sertifikalandırdığı için otomatik indirme seçeneği başarısız olur. Bu nedenle, kullanıcı özel bir CSP'nin kayıtlı olmadığı bir kart eklerse, kullanıcı özel yüklemeden kullanıcının bilgisayarına yüklenmiş ek yazılımlar aracılığıyla akıllı kartı kullanabilse bile, akıllı kart cihazı için sürücü yazılımının eksik olduğunu belirten bir hata iletisi alır.

Çözüm

Akıllı kartlar, kullanıcının gördüğü hata iletisine rağmen çalışmaya devam etse de, bir akıllı kart veren, satıcı veya üretici bu hatayı çözmek için aşağıdaki yöntemlerden birini kullanabilir.

Akıllı kart minidriver uygulama

Akıllı Kart Tak ve Kullan, Akıllı Kartlar için Cihaz Aşaması gibi platformda sunulan iyileştirmelerden yararlanmak için kart verenlerin, satıcıların ve üreticilerin akıllı kart minidriver'ları uygulamasını ve Windows Logo Programı'na katılmasını öneririz.

Akıllı kartınız için NULL sürücü uygulama

Windows'da akıllı kart kullanımını etkinleştirmek için PKCS#11 sürücüsü, ActiveX denetimi veya başka bir ara yazılım gerekliyse ve akıllı kart minidriver veya özel CSP uygulamak pratik bir seçenek değilse, kart verenlerin, satıcıların veya üreticilerin Windows Update null sürücüler göndermeyi düşünmelerini öneririz. Windows Update'da NULL sürücünün kullanılabilir olduğundan emin olmak için kullanılabilecek tipik işlem, Winqual aracılığıyla başarılı bir sınıflandırılmamış cihaz gönderimi gerektirir. Gelecekte bu kartlar için kullanılabilir bir mini sürücü varsa, yeni sürücü Windows Logo Programı'na katılarak Windows Update yüklenebilir. Daha sonra NULL sürücüler son kullanıcılar tarafından el ile indirilebilir veya isteğe bağlı güncelleştirmeler kullanılarak kullanılabilir hale getirilebilir.

Aşağıda, akıllı kart için NULL sürücü için örnek bir şablon verilmiştir.

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

Örnekteki DEVICE_ID dizesi tarafından başvuruda bulunılan donanım cihazı kimliğini oluşturmak için akıllı kart minidriver belirtimindeki yönergeleri izleyin.

Microsoft'a NULL sürücü gönderme hakkında ayrıntılı bilgi için lütfen Microsoft Müşteri Destek Hizmetleri'ne başvurun.

Yönetilen bilgisayarlar için grup ilkesi aracılığıyla Akıllı Kart Tak ve Kullan devre dışı bırakma

Bu seçenek yalnızca bilgisayarların yöneticiler tarafından yönetildiği ve kuruluşta kullanılmakta olan akıllı kartlarla çalışmak için gerekli tüm yazılımların SMS gibi yazılım yönetim araçları kullanılarak yüklendiği kurumsal dağıtımlar için önerilir.

Ortamınızdaki tüm akıllı kartları etkileyeceğinden bu yordam aşağıdaki ortamlarda önerilmez:

  • Çevrimiçi bankacılık gibi son kullanıcıları hedefleyen ticari dağıtımlar.
  • Akıllı kartlar için Tak ve Kullan devre dışı bırakmak için grup ilkesi kullanan hem Tak ve Kullan akıllı kartları hem de Tak ve Kullan olmayan akıllı kartları içeren ortamlar.

Akıllı Kart Tak ve Kullan, son kullanıcının bilgisayarının grup ilkesi gibi mekanizmalarla yönetildiği kuruluşlarda devre dışı bırakılabilir.

Dağıtımınız yalnızca Tak ve Kullan olmayan akıllı kart çözümleri kullanıyorsa, Akıllı Kart Tak ve Kullan istemci bilgisayardaki yerel yönetici tarafından devre dışı bırakılabilir. Akıllı Kart Tak ve Kullan devre dışı bırakılması, akıllı kart mini sürücüleri olarak da bilinen akıllı kart sürücülerinin indirilmesini engeller. Ayrıca Akıllı Kart Tak ve Kullan istemlerini engeller.

Yerel grup ilkesi Akıllı Kart Tak ve Kullan devre dışı bırakmak için şu adımları izleyin:

  1. Başlat'a tıklayın, Program ve dosya ara kutusuna gpedit.msc yazın ve ENTER tuşuna basın.

  2. Bilgisayar Yapılandırması'nın altındaki konsol ağacında Yönetim Şablonları'na tıklayın.

  3. Ayrıntılar bölmesinde Windows Bileşenleri'ne çift tıklayın ve ardından Akıllı Kart'a çift tıklayın.

  4. Akıllı Kart Tak ve Kullan hizmetini aç'a sağ tıklayın ve ardından Düzenle'ye tıklayın.

  5. Devre Dışı'ya ve ardından Tamam'a tıklayın.

Son kullanıcının sistemini değiştirme ve belirli kartlar için Akıllı Kart Tak ve Kullan devre dışı bırakma

Bu, en az önerilen seçenektir. Bu seçeneği yalnızca kartlar eski kartlarsa ve gelecekte akıllı kart minidriver'ları uygulama planı yoksa kullanmalısınız. Bu seçenek, sistemde zaten yüklü olan mevcut yazılımın, son kullanıcı sisteminde böyle bir CSP olmasa bile sistemde yüklü özel bir CSP olduğunu Windows'a bildirmesini gerektirir. Windows sistemde zaten yüklü özel bir CSP olduğunu belirler belirlemez, Windows Akıllı Kart Tak ve Kullan aracılığıyla bir sürücüyü indirmeye ve yüklemeye çalışmaz. akıllı kart cihazı için Aygıt Yöneticisi görünür bir cihaz düğümü oluşturulmaz. Bu seçenek, sistem kayıt defterinde aşağıdaki değişikliklere neden olur:

Alt anahtar: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\<Smart card name>

Alt anahtar kayıt defteri girdileri:

  • ATR=Onaltılık DWORD: Akıllı kartın virgülle ayrılmış ATR'sini.

  • ATRMask= Onaltılık DWORD: ATR'deki önemsiz baytları maskelemesi için ATR'ye uygulanacak virgülle ayrılmış maske.

  • Crypto Provider=String değeri: Akıllı kartınızla ilgili bazı dizeler.

Örneğin:

Alt anahtar: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\Fabrikam ATM card

Alt anahtar kayıt defteri girdileri:

  • ATR=Onaltılık DWORD: 3b,dc,13,00,40,3a,49,54,47,5f,4d,53,43,53,50,5f,56,32
  • ATRMask= Onaltılık DWORD: ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff
  • Şifreleme Sağlayıcısı=Dize değeri: Fabrikam ATM Sahte Sağlayıcısı

x64 bit sistemler için aşağıdaki alt anahtar altında aynı değişiklikler yapılmalıdır: HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards

Bu değişiklikleri sisteme eklemek için sistem kayıt defterini doğrudan değiştirmek yerine WinSCard API'lerini kullanmanızı öneririz. Akıllı kart ekleme işlemini algılayan ve kartı var olmayan bir sağlayıcıyla ilişkilendiren bir kayıt defteri girişi oluşturarak belirli bir kart için Akıllı Kart Tak ve Kullan devre dışı bırakan örnek kod örneği aşağıda verilmiştir.

Microsoft, programlama örneklerini yalnızca gösterim amacıyla sağlar; örtülü veya açık garanti vermez. Buna zımni garantiler, satılabilirlik veya belirli bir amaca uygunluk da dahildir, ancak bunlarla sınırlı değildir. Bu makale, gösterilen programlama dilini ve yordamları oluşturmak ve hata ayıklamak amacıyla kullanılan araçları kullanmayı bildiğinizi varsayar. Microsoft destek mühendisleri belirli bir yordamın işlevselliğini açıklamaya yardımcı olabilir. Ancak gereksinimlerinizi karşılamaya yönelik olarak ek işlevsellik sağlamak veya yordamlar geliştirmek amacıyla bu örnekleri değiştirmeyeceklerdir.

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

Başvurular

Akıllı kart Tak ve Kullan sorunlarını giderme hakkında daha fazla bilgi için bkz. Akıllı Kart Sorun Giderme Kılavuzu.

Veri toplama

Microsoft destek ekibinden yardım almaya ihtiyacınız varsa Dağıtımla ilgili sorunlar için TSS kullanarak bilgi toplama bölümünde belirtilen adımları izleyerek bilgi toplamanızı öneririz.