Search code examples
c++windows-7winscard

C++ source in Windows 7 SCardGetStatusChange returns code 6


I am implementing a PKCS#11 library which will communicate with card readers using winscard in windows and PCSC in MAC.

I am using the following sample code to get the card change status from readers. It works fine in MAC and returns 0x0122 for dwEventState. But in windows SCardGetStatusChange always returns 6 and dwEventState not changed.

Though SCardConnect successfully connect with the reader in windows and returns card handle.

Source

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef __APPLE__
#include <PCSC/winscard.h>
#include <PCSC/wintypes.h>
#else
#include <winscard.h>
#endif

int printResult (char *s, int rv){
    printf("%s %x \n", s, rv);
    return 0;
}

int main(void)
{
 LONG rv;

 SCARDCONTEXT hContext;
 LPTSTR mszReaders , pReader;
 SCARDHANDLE hCard;
 DWORD dwReaders, dwActiveProtocol;

 rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
 printResult("SCardEstablishContext", rv);

#ifdef SCARD_AUTOALLOCATE
 dwReaders = SCARD_AUTOALLOCATE;

 rv = SCardListReaders(hContext, NULL, (LPTSTR)&mszReaders, &dwReaders);
 printResult("SCardListReaders", rv);
#else
 rv = SCardListReaders(hContext, NULL, NULL, &dwReaders);
 printResult("SCardListReaders", rv)

 mszReaders = calloc(dwReaders, sizeof(char));
 rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders);
 printResult("SCardListReaders", rv)
#endif
 int count = 0;
switch( rv )
 {
     case SCARD_E_NO_READERS_AVAILABLE:
         printf("Reader is not in groups.\n");
         // Take appropriate action.
         // ...
         break;

     case SCARD_S_SUCCESS:
     {
         pReader = mszReaders;
         while ( 0 != *pReader )
         {
             ++count;
             printf("Reader: %s\n", pReader );
            rv = SCardConnect(hContext, pReader, SCARD_SHARE_SHARED,
              SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
            printResult("SCardConnect", rv);
            if (rv == SCARD_S_SUCCESS){
                SCARD_READERSTATE rgReaderStates;
                rgReaderStates.dwEventState = 0;
                rgReaderStates.dwCurrentState = SCARD_STATE_UNAWARE;
                rgReaderStates.szReader = pReader;
//              rgReaderStates.szReader = "OMNIKEY CardMan 3x21 0";

                rv = SCardGetStatusChange(hCard, 0, &rgReaderStates, 2);
                printf("CurrentState : 0x%08lX  Event State : 0x%08lX  RV=%ld\n", rgReaderStates.dwCurrentState, rgReaderStates.dwEventState, rv);
            }
             // Advance to the next value.
             pReader = pReader + strlen(pReader) + 1;
         }
          printf("Number of readers %d\n",count);
         // printf("reader name: %s\n", mszReaders[1]);
         // Free the memory.
         break;
     }
 default:
         printf("Failed SCardListReaders\n");
         // Take appropriate action.
         // ...
         break;
 }
 rv = SCardDisconnect(hCard, SCARD_LEAVE_CARD);
 printResult("SCardDisconnect", rv);

#ifdef SCARD_AUTOALLOCATE
 rv = SCardFreeMemory(hContext, mszReaders);
 printResult("SCardFreeMemory", rv);

#else
 free(mszReaders);
#endif

 rv = SCardReleaseContext(hContext);
 printResult("SCardReleaseContext", rv);

 return 0;
}

Output of the code is as follows

SCardEstablishContext 0
SCardListReaders 0
Reader: OMNIKEY CardMan 3x21 0
SCardConnect 0
CurrentState : 0x00000000  Event State : 0x00000000  RV=6
Reader: OMNIKEY CardMan 3x21 1
SCardConnect 0
CurrentState : 0x00000000  Event State : 0x00000000  RV=6
Number of readers 2
SCardDisconnect 0 
SCardFreeMemory 0 
SCardReleaseContext 0

Please help.


Solution

  • I have a mistake in my source

    rv = SCardGetStatusChange(hCard, 0, &rgReaderStates, 2);
    

    hCard should be replaced with hContext

    rv = SCardGetStatusChange(hContext, 0, &rgReaderStates, 2);
    

    Don't know why it provide accurate output on MAC