Beispiel #1
0
void testGetATR_3(SCARDCONTEXT* phContext, WCHAR* readerName)
{
	DWORD retval;
	ULONG ulTimeout = INFINITE;
	ULONG ulReaderCount = 1;
	SCARD_READERSTATEW txreaderStates[1];

	memset(txreaderStates,0, sizeof(txreaderStates));
	txreaderStates[0].szReader = readerName;

	//get initial values
	retval = SCardGetStatusChange(*phContext, 0, txreaderStates ,ulReaderCount); 
	//wait for changes
	txreaderStates[0].dwCurrentState = txreaderStates[0].dwEventState;
	retval = SCardGetStatusChange(*phContext, ulTimeout, txreaderStates ,ulReaderCount); 

	printf ("trying to get the card's ATR by calling SCardGetStatusChange\n");
	printf ("returned: ATR length = %d retval: 0x%08x\n",txreaderStates[0].cbAtr, retval);
	printf ("ATR = ");
	for(int i = 0; i < txreaderStates[0].cbAtr ; i++)
	{
		printf(" 0x%02x",txreaderStates[0].rgbAtr[i]);
	}
	printf ("\n");

}
Beispiel #2
0
testA(int argc,char** argv ) {
	int i;
myprintf("=============================\n");
myprintf("Part A: Checking card monitor\n");
myprintf("=============================\n");
	(rgReaderStates[0])->dwCurrentState = SCARD_STATE_UNAWARE;
	 rv =SCardGetStatusChange( hContext, INFINITE, rgReaderStates[0], 1 ); 
	 if( (rgReaderStates[0])->dwEventState & SCARD_STATE_PRESENT ) {
		myprintf("<<  Please remove smart card \n");
		(rgReaderStates[0])->dwCurrentState = SCARD_STATE_PRESENT;
	 	rv =SCardGetStatusChange( hContext, INFINITE, rgReaderStates[0], 1 ); 
	 }
	printit("1.Please insert smart card");
		(rgReaderStates[0])->dwCurrentState = SCARD_STATE_EMPTY;
		rv =SCardGetStatusChange( hContext, INFINITE, rgReaderStates[0], 1 );
	 myprintf("Passed\n");
	 printit("2. IOCTL_SMARTCARD_IS_PRESENT");
	 myprintf("Passed\n");
	 printit("3. Please remove smart card ");
	 (rgReaderStates[0])->dwCurrentState = SCARD_STATE_PRESENT; 
     rv =SCardGetStatusChange( hContext, INFINITE, rgReaderStates[0], 1 );
     if( rv != SCARD_S_SUCCESS )
        return -1;
	 if( (rgReaderStates[0])->dwEventState & SCARD_STATE_EMPTY) myprintf("Passed\n");
	 else 
		myprintf("Failed \n");
	 printit("4. IOCTL_SMARTCARD_IS_ABSENT");
	 myprintf("Passed\n");
	 printit("5. Insert and remove a smart card repeatedly");
	(rgReaderStates[0])->dwCurrentState = SCARD_STATE_EMPTY;
	for(i=0;i<10;i++) {
	 	rv =SCardGetStatusChange( hContext, INFINITE, rgReaderStates[0], 1 ); 
		(rgReaderStates[0])->dwCurrentState = (rgReaderStates[0])->dwEventState;
	 }
	 myprintf("Passed \n");
	 if( more_details ) {
		 rv = SCardConnect(hContext, readerName,
            SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0| SCARD_PROTOCOL_T1,
            &hCard, &dwPref);
     	if ( rv != SCARD_S_SUCCESS ) {
     		SCardReleaseContext( hContext );
    		return 0;
 	 	}                         
		readerlen=100;
	 	rv = SCardStatus(hCard,readerName,&readerlen,&readerstate,&protocol,r,&atrlen);
	 	if( rv != SCARD_S_SUCCESS ) {
			return -1;
		 }
		 myprintf("ATR :");
		 for(i=0;i<atrlen;i++) {
			myprintf("%0x ",r[i]);
		 }
		 myprintf("\n");
		 myprintf("Powered up successfully \n");
	 }
	 return 0;
}
Beispiel #3
0
bool QPCSCReaderPrivate::updateState()
{
	if( !d->context )
		return false;
	LONG err = SCardGetStatusChange( d->context, 0, &state, 1 );
	return err == SCARD_S_SUCCESS;
}
Beispiel #4
0
LC_CLIENT_RESULT LC_Client_Start(LC_CLIENT *cl) {
  LONG rv;

  assert(cl);

#if 0
  /* check whether pnp pseudo reader is available */
  cl->readerStates[0].szReader = "\\\\?PnP?\\Notification";
  cl->readerStates[0].dwCurrentState = SCARD_STATE_UNAWARE;
  rv=SCardGetStatusChange(cl->scardContext, 0, cl->readerStates, 1);

  if (cl->readerStates[0].dwEventState && SCARD_STATE_UNKNOWN) {
    DBG_INFO(LC_LOGDOMAIN, "PnP not supported");
    cl->pnpAvailable=0;
  }
  else
    cl->pnpAvailable=1;
#endif

  rv=LC_Client_UpdateReaderStates(cl);
  if (rv<0) {
    DBG_INFO(LC_LOGDOMAIN, "here (%d)", (int) rv);
    return LC_Client_ResultGeneric;
  }
  cl->lastUsedReader=-1;

  return LC_Client_ResultOk;
}
Beispiel #5
0
/* -------------------------------------------------------------------------- */
LONG sc_init_u (sc_context *ctx, char *rdr) /* *rdr must be a full name */
{
  SCARD_READERSTATE rSt = {0};
  LONG rc=SCARD_S_SUCCESS;
  DWORD dw=SCARD_AUTOALLOCATE;

  rc=SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &ctx->hCtx);
  if (rc == SCARD_S_SUCCESS)
  {
    rSt.szReader = rdr;
    rSt.dwCurrentState = SCARD_STATE_UNAWARE;
    rc = SCardGetStatusChange(ctx->hCtx, 0, &rSt, 1);
    if ( (rSt.dwEventState & SCARD_STATE_EMPTY) > 0 ) rc = SC_BAD;
    else
    {
       ctx->rdr = NULL;
       ctx->rdrsz = SCARD_AUTOALLOCATE;
       ctx->CLA = 0;
       ctx->proto = SCARD_PCI_T0;
       ctx->rw = 0;
       rc = SCardConnect(ctx->hCtx, rdr, SCARD_SHARE_SHARED,
                         SCARD_MYPROTOSET, &ctx->hCard, &dw);
       if (rc == SCARD_S_SUCCESS)
       {
          SCardGetAttrib(ctx->hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME,
                         (LPBYTE)&ctx->rdr, &ctx->rdrsz);
          if (dw == SCARD_PROTOCOL_T1) ctx->proto = SCARD_PCI_T1;
          else if (dw == SCARD_PROTOCOL_RAW) ctx->proto = SCARD_PCI_RAW;
       }
    }
    if ( rc != SCARD_S_SUCCESS) SCardReleaseContext(ctx->hCtx);
  }

  return rc;
} /* sc_init */
//PCSCREADERDRIVERDLL_API unsigned short CCONV HD_ProbeCard(HANDLE ContextNo, HANDLE devNo, short ivPortNo, short ivCardSeat)	
//PCSCREADERDRIVERDLL_API unsigned short CCONV HD_ProbeCard(HANDLE ContextNo,  short ivPortNo, short ivCardSeat)	
PCSCREADERDRIVERDLL_API unsigned short CCONV HD_ProbeCard(HANDLE devNo,short	ivCardSeat)		
{
	SCARDCONTEXT		ContextNo=NULL;
	
	ret = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &ContextNo);
	if (ret != SCARD_S_SUCCESS) 
	{
//		GetErrorCode(ret);			
		return CER_PCSC_SCardEstablishContext ;
	}

	SCARD_READERSTATE udtReaderState[2];
	DWORD EventStatetpm;
	char Reader[300];

	strcpy(Reader,"Gemplus GemPC430 0\0");
	udtReaderState[0].szReader=Reader;
	//udtReaderState[0].dwCurrentState = SCARD_STATE_UNAVAILABLE;
	//udtReaderState[0].dwCurrentState = SCARD_STATE_PRESENT;
	udtReaderState[0].dwCurrentState = SCARD_STATE_UNAWARE;
//	udtReaderState[0].dwEventState = SCARD_STATE_UNKNOWN |SCARD_STATE_CHANGED|SCARD_STATE_IGNORE;
//	udtReaderState[0].dwEventState = SCARD_STATE_PRESENT;
//	udtReaderState[0].dwEventState = SCARD_STATE_EMPTY;
	ret = SCardGetStatusChange(ContextNo, 0, udtReaderState, 1);
	if (ret != SCARD_S_SUCCESS)
	{
//		GetErrorCode(ret);
//		EventStatetpm = udtReaderState[0].dwEventState;
//		WriteLog("SCardGetStatusChange1", ivPortNo,EventStatetpm);
		SCardReleaseContext(ContextNo);
		ContextHandle = NULL;
		return CER_PCSC_SCardGetStatusChange;
	}
	EventStatetpm = udtReaderState[0].dwEventState;

	if ((EventStatetpm & 0x00000010)==0x00000010)	//0x00000010 -->SCARD_STATE_EMPTY
	{
//		GetErrorCode(ret);
		SCardReleaseContext(ContextNo);
		ContextHandle = NULL;
		return CER_NOCARD;
	}

	ret = SCardReleaseContext(ContextNo);
	if (ret != SCARD_S_SUCCESS)
	{
		GetErrorCode(ret);
		return CER_PCSC_SCardReleaseContext;
	}
	ContextNo = NULL;


	return EXCUTE_SUC;
}
Beispiel #7
0
long 
MySCardGetStatusChange(
	SCARDCONTEXT hContext,
    DWORD dwTimeout,
    LPSCARD_READERSTATE rgReaderStates,
    DWORD cReaders)
{
	long result;
	DWORD timecnt;
	DWORD timeslot;
	
	timecnt = 0;

#ifdef LINUX_OS
	fflush(stdout);
#endif

	if(dwTimeout > 100)
		timeslot = 100;
	else
		timeslot = 1;

	do
	{
		result = SCardGetStatusChange(hContext, dwTimeout, rgReaderStates, cReaders);

		if(result != SCARD_S_SUCCESS)
		{
			PRINTERR(("SCardGetStatusChange Fail : %08X\n", result));
			return result;
		}

		if(((rgReaderStates->dwCurrentState & SCARD_STATE_PRESENT) && !(rgReaderStates->dwEventState & SCARD_STATE_PRESENT)) ||
			(!(rgReaderStates->dwCurrentState & SCARD_STATE_PRESENT) && (rgReaderStates->dwEventState & SCARD_STATE_PRESENT)) )
		{
			break;
		}
		else
		{
			if(dwTimeout)
			{
				Sleep(timeslot);
				timecnt += timeslot;
			}
		}

	} while(timecnt < dwTimeout || dwTimeout == INFINITE);

	return result;
}
Beispiel #8
0
/* -------------------------------------------------------------------------- */
LONG sc_init (sc_context *ctx, char *rdr)
{
  SCARD_READERSTATE rSt = {0};
  LONG rc=SCARD_S_SUCCESS;
  LPTSTR c=NULL, cc=NULL;
  DWORD dw=SCARD_AUTOALLOCATE;

  rc=SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &ctx->hCtx);
  if (rc==SCARD_S_SUCCESS)
  {
     rc=SCardListReaders(ctx->hCtx, NULL, (LPTSTR) &c, &dw);
     if (rc==SCARD_S_SUCCESS)
     {
        cc=findfirststr(c, rdr);
        if (cc!=NULL)
        {
           rSt.szReader = cc;
           rSt.dwCurrentState = SCARD_STATE_UNAWARE;
           rc = SCardGetStatusChange(ctx->hCtx, 0, &rSt, 1);
           if ( (rSt.dwEventState & SCARD_STATE_EMPTY) > 0 ) rc = SC_BAD;
           else
           {
               ctx->rdr = NULL;
               ctx->rdrsz = SCARD_AUTOALLOCATE;
               ctx->CLA = 0;
               ctx->proto = SCARD_PCI_T0;
               ctx->rw = 0;
               rc=SCardConnect(ctx->hCtx, cc, SCARD_SHARE_SHARED,
                               SCARD_MYPROTOSET, &ctx->hCard, &dw);
               if (dw==SCARD_PROTOCOL_T1) ctx->proto=SCARD_PCI_T1;
               else if (dw==SCARD_PROTOCOL_RAW) ctx->proto=SCARD_PCI_RAW;
               if (rc==SCARD_S_SUCCESS)
                  SCardGetAttrib(ctx->hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME,
                             (LPBYTE)&ctx->rdr, &ctx->rdrsz);
           }
        } else rc=SC_BAD;
        SCardFreeMemory(ctx->hCtx, c);
     }
     if ( rc != SCARD_S_SUCCESS) SCardReleaseContext(ctx->hCtx);
  }

  return rc;
} /* sc_init */
Beispiel #9
0
void PCSC::WaitCard(){
	ReaderState.szReader = nameCardreader; // récupération du nom du lecteur
	ReaderState.dwCurrentState = SCARD_STATE_UNAWARE; 
	ReaderState.dwEventState = SCARD_STATE_UNAWARE;
	
	cout << "Carte en attente.." << endl;  
	
	do{
		//on recupere le Status du reader 
		*ReturnValue = SCardGetStatusChange(
							Context,
							30,
							&ReaderState,
							1);
	
	}while((ReaderState.dwEventState & SCARD_STATE_PRESENT) == 0); 
	// Tant que dwEventState & SCARD_STATE_PRESENT ne sont pas egale a 0 on continue la boucle
	
	cout << "Carte présente." <<endl ;  

	
}
Beispiel #10
0
DWORD WINAPI CReaderMonitor::ReaderMonitorProc(void* param)
{
	HRESULT hRes;
	LPTSTR mszNewReaderNames = NULL;

	while (!InterlockedCompareExchange(&g_fExit,0,0)) {

		if (g_hContext == 0) {
			// trying to establish context
			hRes = SCardEstablishContext(g_dwScope, NULL, NULL, &g_hContext);
			if (hRes != SCARD_S_SUCCESS) {
				Sleep(POLL_PERIOD);
				if(InterlockedCompareExchange(&g_fExit,1,1))
					break;
				g_hContext = 0;
			}
		}

		if (g_hContext) {

            if (SCARD_S_SUCCESS == SCardIsValidContext(g_hContext))
            {
			    // rescan reader list...
			    mszNewReaderNames = NULL;
			    DWORD cchReaderNames = 0;
			    do {
				    hRes = SCardListReaders(g_hContext, NULL, NULL, &cchReaderNames);
                if ((hRes == SCARD_S_SUCCESS) && cchReaderNames) {
					    mszNewReaderNames = new TCHAR[cchReaderNames];
					    hRes = SCardListReaders(g_hContext, NULL, mszNewReaderNames, &cchReaderNames);
					    if (hRes != SCARD_S_SUCCESS) {
						    delete[] mszNewReaderNames;
						    mszNewReaderNames = NULL;
					    }
				    }
			    }
			    while (hRes == SCARD_E_INSUFFICIENT_BUFFER);
            }
            else
                hRes = SCARD_E_NO_SERVICE;

			if(InterlockedCompareExchange(&g_fExit,1,1))
				break;

			// check reader listing status
			DWORD cNewReaderStates = 0;
			SCARD_READERSTATE *pNewReaderStates = NULL;
			switch (hRes) {
            case ERROR_INVALID_HANDLE:
			case SCARD_E_INVALID_HANDLE:
			case SCARD_E_NO_SERVICE:
			case SCARD_E_SERVICE_STOPPED:
				SCardReleaseContext(g_hContext);
				g_hContext = 0;
				hRes = SCARD_S_SUCCESS;
				break;
			case SCARD_E_NO_READERS_AVAILABLE:
				hRes = SCARD_S_SUCCESS;
				break;
			case SCARD_S_SUCCESS:
				for (LPCTSTR pReader = mszNewReaderNames; *pReader != 0; pReader += _tcslen(pReader) + 1)
					cNewReaderStates++;
				if (cNewReaderStates)
				{
					pNewReaderStates = new SCARD_READERSTATE[cNewReaderStates];
					memset(pNewReaderStates,0,cNewReaderStates* sizeof(SCARD_READERSTATE));
				}
			default:
				break;
			}

			if(InterlockedCompareExchange(&g_fExit,1,1))
				break;
			
			if (hRes == SCARD_S_SUCCESS) {
				// compare readers
				DWORD j;
				for (j = 0; j < g_cReaderStates; j++)
					g_pReaderStates[j].pvUserData = (LPVOID)1;
				LPCTSTR pReader = mszNewReaderNames;
				DWORD i = 0;
				if (pReader) {
					while (*pReader != 0) {
						pNewReaderStates[i].pvUserData = (LPVOID)1;
						pNewReaderStates[i].dwCurrentState = SCARD_STATE_UNAWARE;
						for (j = 0; j < g_cReaderStates; j++) {
							if (_tcscmp(pReader, g_pReaderStates[j].szReader) == 0) {
								g_pReaderStates[j].pvUserData = NULL;
								pNewReaderStates[i] = g_pReaderStates[j];
								break;
							}
						}

						pNewReaderStates[i].szReader = pReader;
						pReader += _tcslen(pReader) + 1;
						i++;
					}
				}

				// check removed readers
				for (j = 0; j < g_cReaderStates; j++) {
					if (g_pReaderStates[j].pvUserData != NULL) {
						NotifyReaderUnplug(g_pReaderStates[j].szReader);
						if(InterlockedCompareExchange(&g_fExit,1,1))
							goto end_label;
					}
				}

				// update current list
				if (g_pReaderStates)
					delete[] g_pReaderStates;
				if (g_mszReaderNames)
					delete[] g_mszReaderNames;
				g_mszReaderNames = mszNewReaderNames;
				g_pReaderStates = pNewReaderStates;
				g_cReaderStates = cNewReaderStates;
				mszNewReaderNames = NULL;
			}

			// check reader states
			if (g_cReaderStates == 0) {
                if (!g_bReadersListInitialized)
                {
                   SetEvent(g_readersCheckedEvent);
                   g_bReadersListInitialized = true;
                }
				Sleep(POLL_PERIOD);
				if(InterlockedCompareExchange(&g_fExit,1,1))
					break;
			}
			else {
				hRes = SCardGetStatusChange(g_hContext, POLL_PERIOD, g_pReaderStates, g_cReaderStates);
				if(InterlockedCompareExchange(&g_fExit,1,1))
					break;
				if (hRes == SCARD_S_SUCCESS) {
					// check changed readers...
					for (DWORD i = 0; i < g_cReaderStates && !InterlockedCompareExchange(&g_fExit,0,0); i++) {
						if (g_pReaderStates[i].pvUserData != NULL) {
							// new reader
							g_pReaderStates[i].pvUserData = NULL;
							g_pReaderStates[i].dwEventState &= ~SCARD_STATE_CHANGED;
                            g_pReaderStates[i].dwCurrentState = g_pReaderStates[i].dwEventState;
                            if ((g_pReaderStates[i].dwEventState & (SCARD_STATE_IGNORE | SCARD_STATE_MUTE)) == 0)
							    NotifyReaderPlug(g_pReaderStates[i]);
							if(InterlockedCompareExchange(&g_fExit,1,1))
								goto end_label;
							
						}
						else if (g_pReaderStates[i].dwEventState & SCARD_STATE_CHANGED) {
							// existing reader
							g_pReaderStates[i].dwEventState &= ~SCARD_STATE_CHANGED;
							if (    ((g_pReaderStates[i].dwEventState & (SCARD_STATE_IGNORE | SCARD_STATE_MUTE)) == 0)
                                &&  ((g_pReaderStates[i].dwCurrentState & SCARD_STATE_MUTE) == 0)
                                &&  (   ((g_pReaderStates[i].dwCurrentState & SCARD_STATE_PRESENT) && (!(g_pReaderStates[i].dwEventState & SCARD_STATE_PRESENT)))
                                      ||((!(g_pReaderStates[i].dwCurrentState & SCARD_STATE_PRESENT)) && (g_pReaderStates[i].dwEventState & SCARD_STATE_PRESENT))
                                    )
                               )
                            {
								NotifyReaderChange(g_pReaderStates[i]);
                            }
                            g_pReaderStates[i].dwCurrentState = g_pReaderStates[i].dwEventState & (~(SCARD_STATE_CHANGED | SCARD_STATE_IGNORE));
							if(InterlockedCompareExchange(&g_fExit,1,1))
								goto end_label; 
						}
					}
                }
                else if (hRes != SCARD_E_TIMEOUT)
                {
                    if(InterlockedCompareExchange(&g_fExit,1,1))
                        goto end_label; 

                    // something strange happened. Act as if all readers where disconnected
                    for (DWORD i = 0; i < g_cReaderStates; i++)
                    {
                        NotifyReaderUnplug(g_pReaderStates[i].szReader);
						if(InterlockedCompareExchange(&g_fExit,1,1))
							goto end_label;
                    }

				    if (g_pReaderStates)
					    delete[] g_pReaderStates;
				    if (g_mszReaderNames)
					    delete[] g_mszReaderNames;
				    g_mszReaderNames = NULL;
				    g_pReaderStates = NULL;
				    g_cReaderStates = 0;
				    SCardReleaseContext(g_hContext);
				    g_hContext = 0;
                }
                if (!g_bReadersListInitialized)
                {
                   SetEvent(g_readersCheckedEvent);
                   g_bReadersListInitialized = true;
                }				
			}
		}
	}
end_label:

	ResetGlobals();
	if(mszNewReaderNames)
		delete [] mszNewReaderNames;

	return 0;
}
int main(int argc, char **argv)
{
  SCARDCONTEXT      hContext;
  SCARD_READERSTATE rgscState[MAXIMUM_SMARTCARD_READERS];

  DWORD             dwReaders, dwReadersOld = 0;

  LPSTR  szReaders = NULL;
  DWORD  dwReadersSz;

  BOOL   first_run = TRUE;
  DWORD  i, j;
  LONG   rc;
  
  if ((argc >= 2) && (!strcmp(argv[1], "-m")))
    gbChangeMasterKey = TRUE;

  /*
   * Welcome message, check parameters
   * ---------------------------------
   */
  printf("SpringCard SDK for PC/SC (CSB6 family)\n");
  printf("\n");
  printf("NXP DESFIRE EV0 reference demo\n");
  printf("------------------------------\n");
  printf("www.springcard.com\n\n");
  printf("\n");
  printf("Press <Ctrl+C> to exit\n\n");

  /*
   * Get a handle to the PC/SC resource manager
   * ------------------------------------------
   */
  rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
  if(rc != SCARD_S_SUCCESS)
  {
    printf("SCardEstablishContext :%08lX\n",rc);
	  return EXIT_FAILURE;
  }

  /*
   * Infinite loop, we'll exit only when killed by Ctrl+C
   * ----------------------------------------------------
   */
  for (;;)
  {
    /*
     * Get the list of available readers
  	 */

    dwReadersSz = SCARD_AUTOALLOCATE;
	  rc = SCardListReaders(hContext,
                            NULL,                /* Any group */
                            (LPTSTR) &szReaders, /* Diabolic cast for buffer auto-allocation */
                            &dwReadersSz);       /* Beg for auto-allocation */
	  
	if (rc == SCARD_E_NO_READERS_AVAILABLE)
	{
	  /* No reader at all */
	  dwReaders = 0;
	} else if (rc != SCARD_S_SUCCESS)
	{
      printf("SCardListReaders error %08lX\n",rc);
	  break;
	} else
	{
	  /* Track events on found readers. */
	  LPTSTR pReader = szReaders;

	  for (dwReaders=0; dwReaders<MAXIMUM_SMARTCARD_READERS; dwReaders++)
	  {
        /* End of multi-string array */
		if (*pReader == '\0') break;

        /* Remember this reader's name */
		rgscState[dwReaders].szReader = pReader;

        /* Jump to next entry in multi-string array */
		pReader += strlen(pReader) + 1;
	  }
	}

	if (first_run)
    {
      /* Program startup, display the number of readers */
      if (dwReaders == 0)
      {
        printf("No PC/SC reader\n\n");
      } else
      {
        printf("%lu PC/SC reader%s found\n\n", dwReaders, dwReaders ? "s" : "");
      }
    }
      
	if (dwReadersOld != dwReaders)
	{
	  /* Reader added, or reader removed           */
      /* (re)set the initial state for all readers */
	  for (i=0; i<dwReaders; i++)
		rgscState[i].dwCurrentState = SCARD_STATE_UNAWARE;

      if (!first_run)
	  {
        int c;

	    /* Not the program startup, explain the event */
	    if (dwReadersOld > dwReaders)
		{
          c = (int) dwReadersOld-dwReaders;
		  printf("%d reader%s ha%s been removed from the system\n\n", c, (c==1)?" ":"s", (c==1)?"s":"ve");
		} else
		{
          c = (int) dwReaders-dwReadersOld;
		  printf("%d reader%s ha%s been added to the system\n\n", c, (c==1)?" ":"s", (c==1)?"s":"ve");
		}
	  }

      dwReadersOld = dwReaders;
	}

    if (dwReaders == 0)
    {
      /* We must wait here, because the SCardGetStatusChange doesn't wait  */
      /* at all in case there's no reader in the system. Silly, isn't it ? */
#ifdef WIN32
      Sleep(1000);
#endif
#ifdef __linux__
      sleep(1);
#endif
    }

	/*
     * Interesting part of the job : call SCardGetStatusChange to monitor all changes
     * taking place in the PC/SC reader(s)
     */
	
	rc = SCardGetStatusChange(hContext, INFINITE, rgscState, dwReaders);	
		
	if (rc != SCARD_S_SUCCESS)
    {
      printf("SCardGetStatusChange error %08lX\n",rc);
      break;
    }

	for (i=0; i<dwReaders; i++)
	{
	  BOOL just_inserted = FALSE;

      if (rgscState[i].dwEventState & SCARD_STATE_CHANGED)
	  {
        /* Something changed since last loop        */
        if ( (rgscState[i].dwEventState & SCARD_STATE_PRESENT)
         && !(rgscState[i].dwCurrentState & SCARD_STATE_PRESENT) )
          just_inserted = TRUE;

        /* Remember new current state for next loop */
        rgscState[i].dwCurrentState = rgscState[i].dwEventState;
	  } else
	  {
        /* Nothing new, don't display anything for this reader */
        /* (unless we're in the first run)                     */
        if (!first_run)
          continue;
	  }

      /*
       * Display current reader's state
       * ------------------------------
       */

	    /* Reader's name */
      printf("Reader %lu: %s\n", i, rgscState[i].szReader);

      /* Complete status */
      printf("\tCard state:\n");

      if (rgscState[i].dwEventState & SCARD_STATE_IGNORE)
        printf("\t\tIgnore this reader\n");

      if (rgscState[i].dwEventState & SCARD_STATE_UNKNOWN)
        printf("\t\tReader unknown\n");

      if (rgscState[i].dwEventState & SCARD_STATE_UNAVAILABLE)
        printf("\t\tStatus unavailable\n");

      if (rgscState[i].dwEventState & SCARD_STATE_EMPTY)
        printf("\t\tNo card in the reader\n");

      if (rgscState[i].dwEventState & SCARD_STATE_PRESENT)
        printf("\t\tCard present\n");

      if (rgscState[i].dwEventState & SCARD_STATE_ATRMATCH)
        printf("\t\tATR match\n");
  
      if (rgscState[i].dwEventState & SCARD_STATE_EXCLUSIVE)
        printf("\t\tReader reserved for exclusive use\n");

      if (rgscState[i].dwEventState & SCARD_STATE_INUSE)
        printf("\t\tReader/card in use\n");

      if (rgscState[i].dwEventState & SCARD_STATE_MUTE)
        printf("\t\tCard mute\n");

      if (just_inserted)
	  {
        /*
         * Display card's ATR
         * ------------------
         */

        if (rgscState[i].cbAtr)
		{
	      printf("\tCard ATR:");
		  for (j=0; j<rgscState[i].cbAtr; j++)
            printf(" %02X", rgscState[i].rgbAtr[j]);
          printf("\n");
		}

       /*
        * Do the Desfire library test on this card
        * ----------------------------------------
        */
        TestDesfire(hContext, rgscState[i].szReader);
	  }
	}

    /* Free the list of readers  */
    if (szReaders != NULL)
    {
      SCardFreeMemory(hContext, szReaders);
      szReaders = NULL;
    }
      
    /* Not the first run anymore */
		first_run = FALSE;
	}


  rc = SCardReleaseContext(hContext);

  /* Never go here (Ctrl+C kill us before !) */
  return EXIT_FAILURE;
}
/*
 * Class:     com_ibm_opencard_terminal_pcsc10_OCFPCSC1
 * Method:    SCardGetStatusChange
 * Signature: (II[Lcom/ibm/opencard/terminal/pcsc10/PcscReaderState;)V
 */
JNIEXPORT void JNICALL Java_com_ibm_opencard_terminal_pcsc10_OCFPCSC1_SCardGetStatusChange
(JNIEnv *env, jobject obj, jint context, jint timeout, jobjectArray jReaderState) {

    SCARD_READERSTATE   *readerState;
    int         numReaderState;
    int         ii;
    long        returnCode;
    jobject     objReaderState;
    jbyteArray  jATR;

    /* First access the PcscReaderState structure to initialize the return       */
    /* value. Allocate a reader state array for each java ReaderState structure. */

    numReaderState = env->GetArrayLength(jReaderState);
    if (numReaderState < 1) {
        throwPcscException(env, obj, "SCardGetStatusChange",
                           "size of ReaderState array must be greater than 0 elements", 0);
        return;
    }

    readerState = (SCARD_READERSTATE *)malloc(numReaderState * sizeof(SCARD_READERSTATE));
    if (readerState == NULL) {
        throwPcscException(env, obj, "SCardGetStatusChange", "error allocating memory for the readerState buffer", 0);
        return;
    }

    /* clear the allocated memory */
    memset(readerState, 0x00, numReaderState * sizeof(SCARD_READERSTATE));

    /* Now get each Java reader state structure and translate it into C++ */
    for (ii=0; ii<numReaderState; ii++) {
        objReaderState = env->GetObjectArrayElement(jReaderState, ii);
        if (env->ExceptionOccurred() != NULL) {
            free(readerState);
            throwPcscException(env, obj, "SCardGetStatusChange", "error getting elements from the readerState array", 0);
            return;
        }

        returnCode = getIntField(env, objReaderState, "CurrentState", (long *)&readerState[ii].dwCurrentState);
        if (returnCode) {
            free(readerState);
            throwPcscException(env, obj, "SCardGetStatusChange", "error getting CurrentState field from the readerState record", 0);
            return;
        }

        returnCode = getIntField(env, objReaderState, "EventState", (long*)&readerState[ii].dwEventState);
        if (returnCode) {
            free(readerState);
            throwPcscException(env, obj, "SCardGetStatusChange", "error getting EventState field from the readerState record", 0);
            return;
        }

        readerState[ii].szReader = (const char *)accessStringField(env, objReaderState, "Reader");
        if (readerState[ii].szReader == NULL) {
            free(readerState);
            throwPcscException(env, obj, "SCardGetStatusChange", "error getting Reader field from readerState record", 0);
            return;
        }

        int maxSize;
        returnCode = accessByteArray(env, objReaderState, "UserData", (unsigned char **)&readerState[ii].pvUserData, &maxSize);
        if (returnCode) {
            free(readerState);
            throwPcscException(env, obj, "SCardGetStatusChange", "error getting UserData field from readerState record", 0);
            return;
        }
    }

    /* set the response timeout to 1000ms */

    returnCode =  SCardGetStatusChange((SCARDCONTEXT)context, 1000, readerState, numReaderState);
    if (returnCode != SCARD_S_SUCCESS) {
        free(readerState);
        throwPcscException(env, obj, "SCardGetStatusChange", "error executing SCardGetStatusChange", returnCode);
        return;
    }

    readerState[0].dwCurrentState = readerState[0].dwEventState;

    /* write back the informations from the readerStatus to the java structures */
    for (ii=0; ii<numReaderState; ii++) {
        objReaderState = env->GetObjectArrayElement(jReaderState, ii);
        if (env->ExceptionOccurred() != NULL) {
            free(readerState);
            throwPcscException(env, obj, "SCardGetStatusChange", "error getting array elements", returnCode);
            return;
        }

        returnCode = setIntField(env, objReaderState, "EventState", readerState[ii].dwEventState);
        if (returnCode) {
            free(readerState);
            throwPcscException(env, obj, "SCardGetStatusChange", "error setting the EventState field", returnCode);
            return;
        }

        returnCode = releaseStringField(env, objReaderState, "Reader", (const char *)readerState[ii].szReader);
        if (returnCode) {
            free(readerState);
            throwPcscException(env, obj, "SCardGetStatusChange", "error setting the Reader field", returnCode);
            return;
        }

        returnCode = releaseByteArray(env, objReaderState, "UserData", (unsigned char *)readerState[ii].pvUserData);
        if (returnCode) {
            free(readerState);
            throwPcscException(env, obj, "SCardGetStatusChange", "error setting the UserData", returnCode);
            return;
        }

        // buffer for length of ATR
        jsize lenATR = (jsize)readerState[0].cbAtr;

        // check the length of the ATR in the PCSC ReaderState
        // if > 0 copy ATR to java ReaderState

        if (lenATR > 0) {

            // create new java bytearray with length of current ATR
            jATR = env->NewByteArray(lenATR);

            // copy PCSC ATR to jATR
            env->SetByteArrayRegion(jATR, 0, lenATR, (jbyte *)readerState[ii].rgbAtr);

            // find the ReaderState-Class
            jclass clsReaderState = env->GetObjectClass(objReaderState);

            // get the field ID from ATR-field
            jfieldID fldATR = env->GetFieldID(clsReaderState, "ATR", "[B");

            // set the ATR-field within the ReaderStateObject
            env->SetObjectField(objReaderState, fldATR, jATR);
        }
    }

    free(readerState);

    return;
}
Beispiel #13
0
/*
 *  This is the main work of the emulator, handling the thread that looks for
 *  changes in the readers and the cards.
 */
static void *
passthru_emul_event_thread(void *args)
{
    char *reader_list = NULL;
    int reader_list_len = 0;
    SCARD_READERSTATE_A *reader_states = NULL;
    int reader_count = 0;     /* number of active readers */
    int max_reader_count = 0; /* size of the reader_state array (including
                                 inactive readers) */
    LONG rv;
    int timeout=1000;
    int i;

    do {
        /* variables to hold on to our new values until we are ready to replace
         * our old values */
        char *new_reader_list = NULL;
        int new_reader_list_len = 0;
        int new_reader_count = 0;

        /* other temps */
        char * reader_entry;
        VReader *reader;

        /*
         * First check to see if the reader list has changed
         */
        rv = SCardListReaders(global_context, NULL, NULL, &new_reader_list_len);
        if (rv !=  SCARD_S_SUCCESS) {
           goto next;
        }
        /*
         * If the names have changed, we need to update our list and states.
         * This is where we detect reader insertions and removals.
         */
        if (new_reader_list_len != reader_list_len) {
            /* update the list */
            new_reader_list = (char *)malloc(new_reader_list_len);
            if (new_reader_list == NULL) {
                goto next;
            }
            rv = SCardListReaders(global_context, NULL, new_reader_list,
                                  &new_reader_list_len);
            if (rv !=  SCARD_S_SUCCESS) {
                free(new_reader_list);
                goto next;
            }
            /* clear out our event state */
            for (i=0; i < reader_count; i++) {
                    reader_states[i].dwEventState = 0;
            }
            /* count the readers and mark the ones that are still with us */
            for (reader_entry = new_reader_list; *reader_entry;
                 reader_entry += strlen(reader_entry)+1) {
                SCARD_READERSTATE_A *this_state;
                new_reader_count++;
                /* if the reader is still on the list, mark it present */
                this_state = passthru_get_reader_state(reader_states,
                                                       reader_count,
                                                       reader_entry);
                if (this_state) {
                    this_state->dwEventState = SCARD_STATE_PRESENT;
                }
            }
            /* eject any removed readers */
            for (i=0; i < reader_count; i++) {
                if (reader_states[i].dwEventState == SCARD_STATE_PRESENT) {
                    reader_states[i].dwEventState = 0;
                    continue;
                }
                reader = vreader_get_reader_by_name(reader_states[i].szReader);
                vreader_remove_reader(reader);
                vreader_free(reader);
                reader_states[i].szReader = NULL;
            }
            /* handle the shrinking list */
            if (new_reader_count < reader_count) {
                /* fold all the valid entries at the end of our reader_states
                 * array up into those locations vacated by ejected readers. */
                for (i=reader_count-1; i < (new_reader_count -1); i--) {
                        if (reader_states[i].szReader) {
                            SCARD_READERSTATE_A *blank_reader;
                            blank_reader =
                                passthru_get_blank_reader(reader_states,
                                                          new_reader_count);
                            assert(blank_reader);
                            *blank_reader = reader_states[i];
                            reader_states[i].szReader = NULL;
                        }
                 }
            }
            /* handle the growing list */
            if (new_reader_count >  max_reader_count) {
                SCARD_READERSTATE_A *new_reader_states;

                /* grow the list */
                new_reader_states =
                    (SCARD_READERSTATE_A *)realloc(reader_states,
                        sizeof(SCARD_READERSTATE_A)*new_reader_count);
                if (new_reader_states) {
                    /* successful, update our current state */
                    reader_states = new_reader_states;
                    max_reader_count = new_reader_count;
                } else {
                    new_reader_count = max_reader_count; /* couldn't get enough
                                                          * space to handle
                                                          * all the new readers
                                                          * */
                }
                /* mark our new entries as empty */
                for (i=reader_count; i > new_reader_count; i++) {
                    reader_states[i].szReader = NULL;
                }
            }
            /* now walk the reader list, updating the state */
            for (reader_entry = new_reader_list; *reader_entry;
                 reader_entry += strlen(reader_entry)+1) {
                SCARD_READERSTATE_A *this_state;
                this_state = passthru_get_reader_state(reader_states,
                                                       new_reader_count,
                                                       reader_entry);
                if (this_state) {
                    /* replace the old copy of the string with the new copy.
                     * This will allow us to free reader_list at the end */
                    reader_states->szReader = reader_entry;
                    continue;
                }
                /* this is a new reader, add it to the list */
                this_state =
                    passthru_get_blank_reader(reader_states, new_reader_count);
                if (!this_state) {
                    continue; /* this can happen of we couldn't get enough
                                 slots in the grow list */
                }
                this_state->szReader = reader_entry;
                this_state->dwCurrentState = SCARD_STATE_UNAWARE;
                reader = vreader_new(reader_entry, NULL, NULL);
                if (reader) {
                    vreader_add_reader(reader);
                }
                vreader_free(reader);
            }
            /* finally update our current variables */
            free(reader_list);
            reader_list = new_reader_list;
            reader_list_len = new_reader_list_len;
            reader_count = new_reader_count;
        }
next:
        rv = SCardGetStatusChange(global_context, timeout,
                                  reader_states, reader_count);
        if (rv == SCARD_E_TIMEOUT) {
            continue; /* check for new readers */
        }
        if (rv != SCARD_S_SUCCESS) {
            static int restarts = 0;
            VCardStatus status;

            /* try resetting the pcsc_lite subsystem */
            SCardReleaseContext(global_context);
            global_context = 0; /* should close it */
            printf("***** SCard failure %x\n", rv);
            restarts++;
            if (restarts >= 3) {
                printf("***** SCard failed %d times\n", restarts);
                return; /* exit thread */
            }
            status = passthru_pcsc_lite_init();
            assert(status == CARD_DONE);
            sleep(1);
            continue;
        }
        /* deal with card insertion/removal */
        for (i=0; i < reader_count ; i++) {
            if ((reader_states[i].dwEventState & SCARD_STATE_CHANGED) == 0) {
                continue;
            }
            reader_states[i].dwCurrentState = reader_states[i].dwEventState;
            reader = vreader_get_reader_by_name(reader_states[i].szReader);
            if (reader == NULL) {
                continue;
            }
            if (reader_states[i].dwEventState & SCARD_STATE_EMPTY) {
                if (vreader_card_is_present(reader) == VREADER_OK) {
                    vreader_insert_card(reader, NULL);
                }
            }
            if (reader_states[i].dwEventState & SCARD_STATE_PRESENT) {
                VCard *card;
                VCardStatus status = VCARD_FAIL;
                /* if there already was a card present, eject it before we
                 * insert the new one */
                if (vreader_card_is_present(reader) == VREADER_OK) {
                    vreader_insert_card(reader, NULL);
                }

                card = vcard_new(NULL, NULL);
                if (card != NULL) {
                    status = passthru_card_init(reader, card, "",
                                                NULL, NULL, NULL, 0);
                    passthru_card_set_atr(card, reader_states[i].rgbAtr,
                                  reader_states[i].cbAtr);
                    vcard_set_atr_func(card, passthru_card_get_atr);
                }
                if (status == VCARD_DONE) {
                    vreader_insert_card(reader, card);
                }
                vcard_free(card);
            }
            vreader_free(reader);
        }

     } while (1);
     return NULL;
}
BOOL MonitorReaders(SCARDCONTEXT hContext)
{
  DWORD  dwReaders, dwReadersOld = 0;
  SCARD_READERSTATE *rgscState;
	LPSTR  szReaders = NULL;
  DWORD  dwReadersSz; 
  DWORD  maxReaders;
	BOOL   bFirstRun = TRUE;
  DWORD  i, j;
	LONG   rc;

  /* Constant MAXIMUM_SMARTCARD_READERS is only 10 in Windows SDK */
  /* This is not enough for most of our tests. 64 sounds good...  */
  maxReaders = MAXIMUM_SMARTCARD_READERS;
  if (maxReaders<64) maxReaders = 64;

  rgscState = calloc(maxReaders, sizeof(SCARD_READERSTATE));
  if (rgscState == NULL)
  {
    printf("Out of memory\n");
    return FALSE;
  }

	for (;;)
	{
  	/* Get the list of available readers */
    dwReadersSz = SCARD_AUTOALLOCATE;
		rc = SCardListReaders(hContext,
                          NULL,                /* Any group */
                          (LPTSTR) &szReaders, /* Diabolic cast for buffer auto-allocation */
                          &dwReadersSz);       /* Beg for auto-allocation */
	  
		if (rc == SCARD_E_NO_READERS_AVAILABLE)
		{
		  /* No reader at all */
			dwReaders = 0;
		} else
    if (rc != SCARD_S_SUCCESS)
		{
      printf("SCardListReaders error 0x%08lX (%lu).\n", rc, rc);
			break;
		} else
		{
			/* Track events on found readers. */
			LPTSTR pReader = szReaders;

			for (dwReaders=0; dwReaders<maxReaders; dwReaders++)
			{
        /* End of multi-string array */
				if (*pReader == '\0')
					break;

        /* Remember this reader's name */
				rgscState[dwReaders].szReader = pReader;

        /* Jump to next entry in multi-string array */
				pReader += strlen(pReader) + 1;
			}
		}

		if (bFirstRun)
    {
      /* Program startup, display the number of readers */
      if (dwReaders == 0)
      {
        printf("No PC/SC reader\n\n");
      } else
      {
        printf("%ld PC/SC reader%s found\n\n", dwReaders, dwReaders ? "s" : "");
      }
    }
      
		if (dwReadersOld != dwReaders)
		{
			/* Reader added, or reader removed           */
      /* (re)set the initial state for all readers */
			for (i=0; i<dwReaders; i++)
				rgscState[i].dwCurrentState = SCARD_STATE_UNAWARE;

      if (!bFirstRun)
      {
        int c;

        /* Not the program startup, explain the event */
				if (dwReadersOld > dwReaders)
				{
          c = (int) dwReadersOld-dwReaders;
					printf("%d reader%s ha%s been removed from the system\n\n", c, (c==1)?" ":"s", (c==1)?"s":"ve");
				}
				else
				{
          c = (int) dwReaders-dwReadersOld;
					printf("%d reader%s ha%s been added to the system\n\n", c, (c==1)?" ":"s", (c==1)?"s":"ve");
				}
			}

      dwReadersOld = dwReaders;
		}

    if (dwReaders == 0)
    {
      /* We must wait here, because the SCardGetStatusChange doesn't wait  */
      /* at all in case there's no reader in the system. Silly, isn't it ? */
      Sleep(1000);
    }

		/*
     * Interesting part of the job : call SCardGetStatusChange to monitor all changes
     * taking place in the PC/SC reader(s)
     */
		rc = SCardGetStatusChange(hContext,
			                        INFINITE,
			                        rgscState,
			                        dwReaders);	
		
		if (rc != SCARD_S_SUCCESS)
    {
      printf("SCardGetStatusChange error 0x%08lX (%lu).\n", rc, rc);

      if (rc == SCARD_F_INTERNAL_ERROR)
      {
        /* Oups ? Restard from scratch after 2500ms */
        if (szReaders != NULL)
        {
          SCardFreeMemory(hContext, szReaders);
          szReaders = NULL;
        }
        Sleep(2500);
        continue;
      }
      break;
    }

		for (i=0; i<dwReaders; i++)
		{
      BOOL just_inserted = FALSE;

      if (rgscState[i].dwEventState & SCARD_STATE_CHANGED)
      {
        /* Something changed since last loop        */
        if ( (rgscState[i].dwEventState & SCARD_STATE_PRESENT)
         && !(rgscState[i].dwCurrentState & SCARD_STATE_PRESENT) )
          just_inserted = TRUE;

        /* Remember new current state for next loop */
        rgscState[i].dwCurrentState = rgscState[i].dwEventState;
      } else
      {
        /* Nothing new, don't display anything for this reader */
        /* (unless we're in the first run)                     */
        if (!bFirstRun)
          continue;
      }

			if (just_inserted)
			{
				printf("Card inserted in %s\n", rgscState[i].szReader);

				if (rgscState[i].dwEventState & SCARD_STATE_MUTE)
				{
					printf("\tCard is mute\n");
				} else
				{
					printf("\tATR: ");
					for (j=0; j<rgscState[i].cbAtr; j++)
						printf("%02X", rgscState[i].rgbAtr[j]);
					printf("\n");

					if (!ProcessCardAtr(hContext, rgscState[i].rgbAtr, rgscState[i].cbAtr))
            return FALSE;

					printf("\n");
				}
			}
		}

    /* Free the list of readers  */
    if (szReaders != NULL)
    {
      SCardFreeMemory(hContext, szReaders);
      szReaders = NULL;
    }
      
    /* Not the first run anymore */
		bFirstRun = FALSE;
	}


  /* Never go here (Ctrl+C kill us before !) */
  free(rgscState);
  return TRUE;
}
Beispiel #15
0
LC_CLIENT_RESULT LC_Client_GetNextCard(LC_CLIENT *cl, LC_CARD **pCard, int timeout) {
  LONG rv;
  int i;
  uint32_t progressId;
  time_t startt;
  uint64_t to;
  int distance;

  assert(cl);

  startt=time(0);
  if (timeout==GWEN_TIMEOUT_NONE ||
      timeout==GWEN_TIMEOUT_FOREVER)
    to=0;
  else
    to=timeout;

  progressId=GWEN_Gui_ProgressStart(GWEN_GUI_PROGRESS_DELAY |
				    GWEN_GUI_PROGRESS_ALLOW_EMBED |
				    GWEN_GUI_PROGRESS_SHOW_PROGRESS |
				    GWEN_GUI_PROGRESS_SHOW_ABORT,
				    I18N("Waiting for card to be inserted"),
				    NULL,
				    to,
				    0);

  distance=GWEN_GUI_CHECK_PERIOD;
  if (distance>timeout)
    distance=timeout;

  for (;;) {
    double d;
    int err;

    /* continue checking */
    for (i=cl->lastUsedReader+1; i<cl->readerCount; i++) {
      /* we have a change here */
      if (cl->readerStates[i].dwEventState & SCARD_STATE_CHANGED)
	cl->readerStates[i].dwCurrentState=cl->readerStates[i].dwEventState;
      else
        continue;

      DBG_DEBUG(LC_LOGDOMAIN, "Status changed on reader [%s] (%08x, %08x)",
		cl->readerStates[i].szReader,
		(unsigned int)(cl->readerStates[i].dwCurrentState),
		(unsigned int)(cl->readerStates[i].dwEventState));

      if (cl->pnpAvailable && i==cl->readerCount-1) {
	/* pnp pseudo reader: a reader has been added or removed */
	DBG_DEBUG(LC_LOGDOMAIN, "Pseudo reader, updating reader list (%08x, %08x)",
		  (unsigned int)(cl->readerStates[i].dwCurrentState),
		  (unsigned int)(cl->readerStates[i].dwEventState));
	LC_Client_UpdateReaderStates(cl);
	cl->lastUsedReader=-1;
	break;
      }
      else {
	if ((cl->readerStates[i].dwEventState & SCARD_STATE_PRESENT) &&
	    !(cl->readerStates[i].dwEventState & SCARD_STATE_EXCLUSIVE) &&
	    !(cl->readerStates[i].dwEventState & SCARD_STATE_INUSE)) {
	  LC_CLIENT_RESULT res;
	  LC_CARD *card=NULL;

	  /* card inserted and not used by another application */
	  DBG_DEBUG(LC_LOGDOMAIN, "Found usable card in reader [%s]", cl->readerStates[i].szReader);
	  res=LC_Client_ConnectCard(cl, cl->readerStates[i].szReader, &card);
	  if (res==LC_Client_ResultOk) {
	    /* card csuccessfully connected, return */
	    *pCard=card;
	    cl->lastUsedReader=i;
	    GWEN_Gui_ProgressEnd(progressId);
	    return LC_Client_ResultOk;
	  }
	  else {
	    DBG_ERROR(LC_LOGDOMAIN,
		      "Error connecting to card in reader [%s]",
		      cl->readerStates[i].szReader);
	  }
	}
	else {
	  DBG_INFO(LC_LOGDOMAIN, "Either no card in reader or card unavailable in reader [%s]",
		    cl->readerStates[i].szReader);
	}
      }
    }

    if (i>=cl->readerCount) {
      /* there was no relevant change in a reader, wait for status change */
      cl->lastUsedReader=-1;
      rv=SCardGetStatusChange(cl->scardContext, distance, cl->readerStates, cl->readerCount);
      if (rv==SCARD_E_TIMEOUT) {
	/* timeout, just repeat next loop */
	if (timeout==GWEN_TIMEOUT_NONE) {
	  GWEN_Gui_ProgressEnd(progressId);
	  return LC_Client_ResultWait;
	}
      }
      else if (rv!=SCARD_S_SUCCESS) {
	DBG_ERROR(LC_LOGDOMAIN, "SCardGetStatusChange: %d", (int) rv);
	GWEN_Gui_ProgressEnd(progressId);
        return LC_Client_ResultIoError;
      }
    }

    /* check timeout */
    d=difftime(time(0), startt);
    if (timeout!=GWEN_TIMEOUT_FOREVER) {
      if (timeout==GWEN_TIMEOUT_NONE ||
	  d>timeout) {
	DBG_INFO(GWEN_LOGDOMAIN,
		 "Timeout (%d) while waiting, giving up",
		 timeout);
	GWEN_Gui_ProgressEnd(progressId);
	return LC_Client_ResultWait;
      }
    }

    /* check for user abort */
    err=GWEN_Gui_ProgressAdvance(progressId, (uint64_t)(d*1000));
    if (err==GWEN_ERROR_USER_ABORTED) {
      DBG_ERROR(GWEN_LOGDOMAIN, "User aborted");
      GWEN_Gui_ProgressEnd(progressId);
      return LC_Client_ResultAborted;
    }
  }
}
Beispiel #16
0
bool silvia_pcsc_card_monitor::wait_for_card(silvia_pcsc_card** card)
{
	assert(card != NULL);
	
	// First, find which card readers are available
	LPTSTR readers;
	LPTSTR readers_orig;
	DWORD reader_len;
	
	LONG rv = SCardListReaders(pcsc_context, NULL, NULL, &reader_len);
	
	if ((rv != SCARD_S_SUCCESS) || (reader_len == 0))
	{
		return false;
	}
	
	readers_orig = readers = (LPTSTR) malloc(reader_len * sizeof(char));
	
	rv = SCardListReaders(pcsc_context, NULL, readers, &reader_len);
	
	if (rv != SCARD_S_SUCCESS)
	{
		free(readers_orig);
		
		return false;
	}
	
	// Add readers to availability structure
	std::vector<SCARD_READERSTATE> reader_states;
	
	while (reader_len > 1)
	{
		size_t len = strlen(readers);
		
		SCARD_READERSTATE reader_state;
		
		reader_state.szReader = readers;
		reader_state.pvUserData = NULL;
		reader_state.dwCurrentState = SCARD_STATE_UNAWARE;
		reader_state.dwEventState = SCARD_STATE_UNAWARE;
		reader_state.cbAtr = MAX_ATR_SIZE;
		
		reader_states.push_back(reader_state);
		
		reader_len -= len + 1;
		readers += len + 1;
	}
	
	rv = SCardGetStatusChange(pcsc_context, INFINITE, &reader_states[0], reader_states.size());
	
	if (rv != SCARD_S_SUCCESS)
	{
		free(readers_orig);
		
		return false;
	}
	
	while (true)
	{
		for (std::vector<SCARD_READERSTATE>::iterator i = reader_states.begin(); i != reader_states.end(); i++)
		{
			if (FLAG_SET(i->dwEventState, SCARD_STATE_PRESENT))
			{
				// Attempt to connect to this particular card
				DWORD active_protocol;
				SCARDHANDLE card_handle;
				
				rv = SCardConnect(pcsc_context, i->szReader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &card_handle, &active_protocol);
				
				if (rv == SCARD_S_SUCCESS)
				{
					*card = new silvia_pcsc_card(card_handle, active_protocol, i->szReader);
					
					free(readers_orig);
					
					return true;
				}
			}
			
			i->dwCurrentState = i->dwEventState;
		}
		
		rv = SCardGetStatusChange(pcsc_context, INFINITE, &reader_states[0], reader_states.size());
		
		if (rv != SCARD_S_SUCCESS)
		{
			break;
		}
	}
	
	free(readers_orig);
	
	return false;
}
Beispiel #17
0
int main(int argc, char *argv[])
{
	int current_reader;
	LONG rv;
	SCARDCONTEXT hContext;
	SCARD_READERSTATE *rgReaderStates_t = NULL;
	SCARD_READERSTATE rgReaderStates[1];
	DWORD dwReaders = 0, dwReadersOld;
	DWORD timeout;
	LPSTR mszReaders = NULL;
	char *ptr, **readers = NULL;
	int nbReaders, i;
	char atr[MAX_ATR_SIZE*3+1];	/* ATR in ASCII */
	char atr_command[sizeof(atr)+sizeof(ATR_PARSER)+2+1];
	int opt;
	int analyse_atr = TRUE;
	const char *blue = "";
	const char *red = "";
	const char *magenta = "";
	const char *color_end = "";
	int pnp = TRUE;

	printf("PC/SC device scanner\n");
	printf("V " VERSION " (c) 2001-2011, Ludovic Rousseau <*****@*****.**>\n");
	printf("Compiled with PC/SC lite version: " PCSCLITE_VERSION_NUMBER "\n");

	while ((opt = getopt(argc, argv, "Vhn")) != EOF)
	{
		switch (opt)
		{
			case 'n':
				analyse_atr = FALSE;
				break;

			case 'V':
				/* the version number is printed by default */
				return 1;
				break;

			case 'h':
				default:
				usage();
				return 1;
				break;
		}
	}

	if (argc - optind != 0)
	{
		usage();
		return 1;
	}

	/* check if terminal supports color */
	{
		const char *terms[] = { "linux", "xterm", "xterm-color", "Eterm", "rxvt", "rxvt-unicode" };
		char *term;

		term = getenv("TERM");
		if (term)
		{
			size_t j;

			/* for each known color terminal */
			for (j = 0; j < sizeof(terms) / sizeof(terms[0]); j++)
			{
				/* we found a supported term? */
				if (0 == strcmp(terms[j], term))
				{
					blue = "\33[34m";
					red = "\33[31m";
					magenta = "\33[35m";
					color_end = "\33[0m";
					break;
				}
			}
		}
	}

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

	rgReaderStates[0].szReader = "\\\\?PnP?\\Notification";
	rgReaderStates[0].dwCurrentState = SCARD_STATE_UNAWARE;

	rv = SCardGetStatusChange(hContext, 0, rgReaderStates, 1);
	if (rgReaderStates[0].dwEventState & SCARD_STATE_UNKNOWN)
	{
		timeout = TIMEOUT;
		printf("%sPlug'n play reader name not supported. Using polling every %ld ms.%s\n", magenta, timeout, color_end);
		pnp = FALSE;
	}
	else
	{
		timeout = INFINITE;
		printf("%sUsing reader plug'n play mechanism%s\n", magenta, color_end);
	}

get_readers:
	/* free memory possibly allocated in a previous loop */
	if (NULL != readers)
	{
		free(readers);
		readers = NULL;
	}

	if (NULL != rgReaderStates_t)
	{
		free(rgReaderStates_t);
		rgReaderStates_t = NULL;
	}

	/* Retrieve the available readers list.
	 *
	 * 1. Call with a null buffer to get the number of bytes to allocate
	 * 2. malloc the necessary storage
	 * 3. call with the real allocated buffer
	 */
	printf("%sScanning present readers...%s\n", red, color_end);
	rv = SCardListReaders(hContext, NULL, NULL, &dwReaders);
	if (rv != SCARD_E_NO_READERS_AVAILABLE)
		test_rv("SCardListReaders", rv, hContext);

	dwReadersOld = dwReaders;

	/* if non NULL we came back so free first */
	if (mszReaders)
	{
		free(mszReaders);
		mszReaders = NULL;
	}

	mszReaders = malloc(sizeof(char)*dwReaders);
	if (mszReaders == NULL)
	{
		printf("malloc: not enough memory\n");
		return 1;
	}

	*mszReaders = '\0';
	rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders);

	/* Extract readers from the null separated string and get the total
	 * number of readers */
	nbReaders = 0;
	ptr = mszReaders;
	while (*ptr != '\0')
	{
		ptr += strlen(ptr)+1;
		nbReaders++;
	}

	if (SCARD_E_NO_READERS_AVAILABLE == rv || 0 == nbReaders)
	{
		printf("%sWaiting for the first reader...%s", red, color_end);
		fflush(stdout);

		if (pnp)
		{
			rgReaderStates[0].szReader = "\\\\?PnP?\\Notification";
			rgReaderStates[0].dwCurrentState = SCARD_STATE_UNAWARE;

			rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1);
			test_rv("SCardGetStatusChange", rv, hContext);
		}
		else
		{
			rv = SCARD_S_SUCCESS;
			while ((SCARD_S_SUCCESS == rv) && (dwReaders == dwReadersOld))
			{
				rv = SCardListReaders(hContext, NULL, NULL, &dwReaders);
				if (SCARD_E_NO_READERS_AVAILABLE == rv)
					rv = SCARD_S_SUCCESS;
				sleep(1);
			}
		}
		printf("found one\n");
		goto get_readers;
	}
	else
		test_rv("SCardListReader", rv, hContext);

	/* allocate the readers table */
	readers = calloc(nbReaders+1, sizeof(char *));
	if (NULL == readers)
	{
		printf("Not enough memory for readers table\n");
		return -1;
	}

	/* fill the readers table */
	nbReaders = 0;
	ptr = mszReaders;
	while (*ptr != '\0')
	{
		printf("%s%d: %s%s\n", blue, nbReaders, ptr, color_end);
		readers[nbReaders] = ptr;
		ptr += strlen(ptr)+1;
		nbReaders++;
	}

	/* allocate the ReaderStates table */
	rgReaderStates_t = calloc(nbReaders+1, sizeof(* rgReaderStates_t));
	if (NULL == rgReaderStates_t)
	{
		printf("Not enough memory for readers states\n");
		return -1;
	}

	/* Set the initial states to something we do not know
	 * The loop below will include this state to the dwCurrentState
	 */
	for (i=0; i<nbReaders; i++)
	{
		rgReaderStates_t[i].szReader = readers[i];
		rgReaderStates_t[i].dwCurrentState = SCARD_STATE_UNAWARE;
		rgReaderStates_t[i].cbAtr = sizeof rgReaderStates_t[i].rgbAtr;
	}
	rgReaderStates_t[nbReaders].szReader = "\\\\?PnP?\\Notification";
	rgReaderStates_t[nbReaders].dwCurrentState = SCARD_STATE_UNAWARE;

	/* Wait endlessly for all events in the list of readers
	 * We only stop in case of an error
	 */
	if (pnp)
		nbReaders++;

	rv = SCardGetStatusChange(hContext, timeout, rgReaderStates_t, nbReaders);
	while ((rv == SCARD_S_SUCCESS) || (rv == SCARD_E_TIMEOUT))
	{
		time_t t;

		if (pnp)
		{
			if (rgReaderStates_t[nbReaders-1].dwEventState &
					SCARD_STATE_CHANGED)
				goto get_readers;
		}
		else
		{
			/* A new reader appeared? */
			if ((SCardListReaders(hContext, NULL, NULL, &dwReaders)
				== SCARD_S_SUCCESS) && (dwReaders != dwReadersOld))
				goto get_readers;
		}

		if (rv != SCARD_E_TIMEOUT)
		{
			/* Timestamp the event as we get notified */
			t = time(NULL);
			printf("\n%s", ctime(&t));
		}

		/* Now we have an event, check all the readers in the list to see what
		 * happened */
		for (current_reader=0; current_reader < nbReaders; current_reader++)
		{
			if (rgReaderStates_t[current_reader].dwEventState &
				SCARD_STATE_CHANGED)
			{
				/* If something has changed the new state is now the current
				 * state */
				rgReaderStates_t[current_reader].dwCurrentState =
					rgReaderStates_t[current_reader].dwEventState;
			}
			else
				/* If nothing changed then skip to the next reader */
				continue;

			/* From here we know that the state for the current reader has
			 * changed because we did not pass through the continue statement
			 * above.
			 */

			/* Specify the current reader's number and name */
			printf("Reader %d: %s%s%s\n", current_reader,
				magenta, rgReaderStates_t[current_reader].szReader,
				color_end);

			/* Dump the full current state */
			printf("  Card state: %s", red);

			if (rgReaderStates_t[current_reader].dwEventState &
				SCARD_STATE_IGNORE)
				printf("Ignore this reader, ");

			if (rgReaderStates_t[current_reader].dwEventState &
				SCARD_STATE_UNKNOWN)
			{
				printf("Reader unknown\n");
				goto get_readers;
			}

			if (rgReaderStates_t[current_reader].dwEventState &
				SCARD_STATE_UNAVAILABLE)
				printf("Status unavailable, ");

			if (rgReaderStates_t[current_reader].dwEventState &
				SCARD_STATE_EMPTY)
				printf("Card removed, ");

			if (rgReaderStates_t[current_reader].dwEventState &
				SCARD_STATE_PRESENT)
				printf("Card inserted, ");

			if (rgReaderStates_t[current_reader].dwEventState &
				SCARD_STATE_ATRMATCH)
				printf("ATR matches card, ");

			if (rgReaderStates_t[current_reader].dwEventState &
				SCARD_STATE_EXCLUSIVE)
				printf("Exclusive Mode, ");

			if (rgReaderStates_t[current_reader].dwEventState &
				SCARD_STATE_INUSE)
				printf("Shared Mode, ");

			if (rgReaderStates_t[current_reader].dwEventState &
				SCARD_STATE_MUTE)
				printf("Unresponsive card, ");

			printf("%s\n", color_end);

			/* force display */
			fflush(stdout);

			/* Also dump the ATR if available */
			if (rgReaderStates_t[current_reader].cbAtr > 0)
			{
				printf("  ATR: ");

				if (rgReaderStates_t[current_reader].cbAtr)
				{
					unsigned int j;

					for (j=0; j<rgReaderStates_t[current_reader].cbAtr; j++)
						sprintf(&atr[j*3], "%02X ",
							rgReaderStates_t[current_reader].rgbAtr[j]);

					atr[j*3-1] = '\0';
				}
				else
					atr[0] = '\0';

				printf("%s%s%s\n", magenta, atr, color_end);

				/* force display */
				fflush(stdout);

				if (analyse_atr)
				{
					printf("\n");

					sprintf(atr_command, ATR_PARSER " '%s'", atr);
					if (system(atr_command))
						perror(atr_command);
				}
			}
		} /* for */

		rv = SCardGetStatusChange(hContext, timeout, rgReaderStates_t,
			nbReaders);
	} /* while */

	/* If we get out the loop, GetStatusChange() was unsuccessful */
	test_rv("SCardGetStatusChange", rv, hContext);

	/* We try to leave things as clean as possible */
	rv = SCardReleaseContext(hContext);
	test_rv("SCardReleaseContext", rv, hContext);

	/* free memory possibly allocated */
	if (NULL != readers)
		free(readers);
	if (NULL != rgReaderStates_t)
		free(rgReaderStates_t);

	return 0;
} /* main */
Beispiel #18
0
/*
 * Return reader status change.
 */
JNIEXPORT jint JNICALL GEN_FUNCNAME(Context_NativeGetStatusChange)
(JNIEnv *env, jobject _this, jint timeout, jobjectArray jrstates)
{
    SCARD_READERSTATE *crstates;
    SCARDCONTEXT ctx;
    jobject jrdrName;
    jobject jrstate;
    jboolean isCopy;
    jbyteArray jatr;
    DWORD rv;
    int crcnt;
    char *catr;
    int i;

    ctx = (SCARDCONTEXT) (*env)->GetLongField(env, _this, CtxField);

    if (jrstates == NULL) {
        rv = SCardGetStatusChange(ctx, INFINITE, NULL, 0);
        return rv;
    } else {
        crcnt = (*env)->GetArrayLength(env, jrstates);
        crstates = (SCARD_READERSTATE *)malloc(crcnt * sizeof(SCARD_READERSTATE));
        if (crstates == NULL) {
            pcscex_throw(env, "GetStatusChange(): invalid number of reader-states", 0);
            return SCARD_E_INVALID_PARAMETER;
        }

        for (i = 0; i < crcnt; i++) {
            jrstate = (*env)->GetObjectArrayElement(env, jrstates, i);
            if (jrstate == NULL) {
                free(crstates);
                npex_throw(env, "GetStatusChange(): invalid null entry in ReaderState array parameter");
                return SCARD_E_INVALID_PARAMETER;
            }

            crstates[i].dwCurrentState = (*env)->GetIntField(env, jrstate, CurrentStateField);
            crstates[i].dwEventState = (*env)->GetIntField(env, jrstate, EventStateField);

            jrdrName = (*env)->GetObjectField(env, jrstate, ReaderStateField);
            if (jrdrName == NULL) {
                free(crstates);
                npex_throw(env, "GetStatusChange(): invalid null reader name entry in one ReaderState parameter");
                return SCARD_E_INVALID_PARAMETER;
            }

            crstates[i].szReader = (*env)->GetStringUTFChars(env, jrdrName, &isCopy);

            // copy ATR and check its size.
            jatr = (jbyteArray) (*env)->GetObjectField(env, jrstate, AtrStateField);
            if (jatr != NULL) {
                catr = (*env)->GetByteArrayElements(env, jatr, &isCopy);
                crstates[i].cbAtr = (*env)->GetArrayLength(env, jatr);
                if (crstates[i].cbAtr < 0) {
                    free(crstates);
                    npex_throw(env, "GetStatusChange(): invalid zero-length ATR in ReaderState parameter");
                    return SCARD_E_INVALID_PARAMETER;
                }
                if (crstates[i].cbAtr > JPCSC_ATR_SIZE) {
                    free(crstates);
                    npex_throw(env, "GetStatusChange(): invalid ATR length in ReaderState parameter");
                    return SCARD_E_INVALID_PARAMETER;
                }
                memcpy(&crstates[i].rgbAtr[0], catr, crstates[i].cbAtr);
                (*env)->ReleaseByteArrayElements(env, jatr, catr, JNI_ABORT);
            } else {
                crstates[i].cbAtr = 0;
            }
        }

        rv = SCardGetStatusChange(ctx, timeout, &crstates[0], crcnt);
        if (rv != SCARD_S_SUCCESS) {
            free(crstates);
            return rv;
        }

        JPCSC_LOG(("NativeGetStatucChange(): readerstate returned ...\n"));
        pcsc_readerstatea_log(&crstates[0]);

        for (i = 0; i < crcnt; i++) {
            jrstate = (*env)->GetObjectArrayElement(env, jrstates, i);
            (*env)->SetIntField(env, jrstate, CurrentStateField, crstates[i].dwCurrentState);
            (*env)->SetIntField(env, jrstate, EventStateField, crstates[i].dwEventState);
            jrdrName = (*env)->GetObjectField(env, jrstate, ReaderStateField);
            (*env)->ReleaseStringUTFChars(env, jrdrName, crstates[i].szReader);

            jatr = (*env)->NewByteArray(env, crstates[i].cbAtr);
            (*env)->SetByteArrayRegion(env, jatr, 0, crstates[i].cbAtr, crstates[i].rgbAtr);
            (*env)->SetObjectField(env, jrstate, AtrStateField, jatr);
        }
        free(crstates);
        return rv;
    }
}
static uint32 handle_LocateCardsByATR(IRP* irp, tbool wide)
{
	LONG rv;
	int i, j, k;
	SCARDCONTEXT hContext;
	uint32 atrMaskCount = 0;
	uint32 readerCount = 0;
	SCARD_READERSTATE* cur = NULL;
	SCARD_READERSTATE* rsCur = NULL;
	SCARD_READERSTATE* readerStates = NULL;
	SERVER_SCARD_ATRMASK* curAtr = NULL;
	SERVER_SCARD_ATRMASK* pAtrMasks = NULL;

	stream_seek(irp->input, 0x2C);
	stream_read_uint32(irp->input, hContext);
	stream_read_uint32(irp->input, atrMaskCount);

	pAtrMasks = xmalloc(atrMaskCount * sizeof(SERVER_SCARD_ATRMASK));

	if (!pAtrMasks)
		return sc_output_return(irp, SCARD_E_NO_MEMORY);

	for (i = 0; i < atrMaskCount; i++)
	{
		stream_read_uint32(irp->input, pAtrMasks[i].cbAtr);
		stream_read(irp->input, pAtrMasks[i].rgbAtr, 36);
		stream_read(irp->input, pAtrMasks[i].rgbMask, 36);
	}

	stream_read_uint32(irp->input, readerCount);

	readerStates = xzalloc(readerCount * sizeof(SCARD_READERSTATE));

	if (!readerStates)
		return sc_output_return(irp, SCARD_E_NO_MEMORY);

	for (i = 0; i < readerCount; i++)
	{
		cur = &readerStates[i];

		stream_seek(irp->input, 4);

		/*
		 * TODO: on-wire is little endian; need to either
		 * convert to host endian or fix the headers to
		 * request the order we want
		 */
		stream_read_uint32(irp->input, cur->dwCurrentState);
		stream_read_uint32(irp->input, cur->dwEventState);
		stream_read_uint32(irp->input, cur->cbAtr);
		stream_read(irp->input, cur->rgbAtr, 32);

		stream_seek(irp->input, 4);

		/* reset high bytes? */
		cur->dwCurrentState &= 0x0000FFFF;
		cur->dwEventState &= 0x0000FFFF;
		cur->dwEventState = 0;
	}

	for (i = 0; i < readerCount; i++)
	{
		cur = &readerStates[i];
		uint32 dataLength;

		stream_seek(irp->input, 8);
		stream_read_uint32(irp->input, dataLength);
		sc_input_repos(irp, sc_input_string(irp, (char **) &cur->szReader, dataLength, wide));

		DEBUG_SCARD("   \"%s\"", cur->szReader ? cur->szReader : "NULL");
		DEBUG_SCARD("       user: 0x%08x, state: 0x%08x, event: 0x%08x",
				(unsigned) cur->pvUserData, (unsigned) cur->dwCurrentState,
				(unsigned) cur->dwEventState);

		if (strcmp(cur->szReader, "\\\\?PnP?\\Notification") == 0)
			cur->dwCurrentState |= SCARD_STATE_IGNORE;
	}

	rv = SCardGetStatusChange(hContext, 0x00000001, readerStates, readerCount);
	if (rv != SCARD_S_SUCCESS)
	{
		DEBUG_SCARD("Failure: %s (0x%08x)",
			pcsc_stringify_error(rv), (unsigned) rv);

		return sc_output_return(irp, rv);
	}

	DEBUG_SCARD("Success");
	for (i = 0, curAtr = pAtrMasks; i < atrMaskCount; i++, curAtr++)
	{
		for (j = 0, rsCur = readerStates; j < readerCount; j++, rsCur++)
		{
			tbool equal = 1;
			for (k = 0; k < cur->cbAtr; k++)
			{
				if ((curAtr->rgbAtr[k] & curAtr->rgbMask[k]) !=
				    (rsCur->rgbAtr[k] & curAtr->rgbMask[k]))
				{
					equal = 0;
					break;
				}
			}
			if (equal)
			{
				rsCur->dwEventState |= 0x00000040;	/* SCARD_STATE_ATRMATCH 0x00000040 */
			}
		}
	}

	stream_write_uint32(irp->output, readerCount);
	stream_write_uint32(irp->output, 0x00084dd8);
	stream_write_uint32(irp->output, readerCount);

	for (i = 0, rsCur = readerStates; i < readerCount; i++, rsCur++)
	{
		stream_write_uint32(irp->output, cur->dwCurrentState);
		stream_write_uint32(irp->output, cur->dwEventState);
		stream_write_uint32(irp->output, cur->cbAtr);
		stream_write(irp->output, cur->rgbAtr, 32);

		stream_write_zero(irp->output, 4);

		xfree((void*) cur->szReader);
	}

	sc_output_alignment(irp, 8);

	free(readerStates);

	return rv;
}
Beispiel #20
0
int main(/*@unused@*/ int argc, /*@unused@*/ char **argv)
{
	SCARDHANDLE hCard;
	SCARDCONTEXT hContext;
	SCARD_READERSTATE_A rgReaderStates[1];
	DWORD dwReaderLen, dwState, dwProt, dwAtrLen;
	DWORD dwPref, dwReaders = 0;
	char *pcReaders = NULL, *mszReaders;
#ifdef USE_AUTOALLOCATE
	unsigned char *pbAtr = NULL;
#else
	unsigned char pbAtr[MAX_ATR_SIZE];
#endif
	union {
		unsigned char as_char[100];
		DWORD as_DWORD;
		uint32_t as_uint32_t;
	} buf;
	DWORD dwBufLen;
	unsigned char *pbAttr = NULL;
	DWORD pcbAttrLen;
	char *mszGroups;
	DWORD dwGroups = 0;
	long rv;
	DWORD i;
	int p, iReader;
	int iList[16];
	SCARD_IO_REQUEST pioRecvPci;
	SCARD_IO_REQUEST pioSendPci;
	unsigned char bSendBuffer[MAX_BUFFER_SIZE];
	unsigned char bRecvBuffer[MAX_BUFFER_SIZE];
	DWORD send_length, length;

	(void)argc;
	(void)argv;

	printf("\nMUSCLE PC/SC Lite unitary test Program\n\n");

	printf(MAGENTA "THIS PROGRAM IS NOT DESIGNED AS A TESTING TOOL FOR END USERS!\n");
	printf("Do NOT use it unless you really know what you do.\n\n" NORMAL);

	printf("Testing SCardEstablishContext\t: ");
	rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
	test_rv(rv, hContext, PANIC);

	printf("Testing SCardIsValidContext\t: ");
	rv = SCardIsValidContext(hContext);
	test_rv(rv, hContext, PANIC);

	printf("Testing SCardIsValidContext\t: ");
	rv = SCardIsValidContext(hContext+1);
	test_rv(rv, hContext, DONT_PANIC);

	printf("Testing SCardListReaderGroups\t: ");
#ifdef USE_AUTOALLOCATE
	dwGroups = SCARD_AUTOALLOCATE;
	rv = SCardListReaderGroups(hContext, (LPSTR)&mszGroups, &dwGroups);
#else
	rv = SCardListReaderGroups(hContext, NULL, &dwGroups);
	test_rv(rv, hContext, PANIC);

	printf("Testing SCardListReaderGroups\t: ");
	mszGroups = calloc(dwGroups, sizeof(char));
	rv = SCardListReaderGroups(hContext, mszGroups, &dwGroups);
#endif
	test_rv(rv, hContext, PANIC);

	/*
	 * Have to understand the multi-string here
	 */
	p = 0;
	for (i = 0; i+1 < dwGroups; i++)
	{
		++p;
		printf(GREEN "Group %02d: %s\n" NORMAL, p, &mszGroups[i]);
		while (mszGroups[++i] != 0) ;
	}

#ifdef USE_AUTOALLOCATE
	printf("Testing SCardFreeMemory\t\t: ");
	rv = SCardFreeMemory(hContext, mszGroups);
	test_rv(rv, hContext, PANIC);
#else
	free(mszGroups);
#endif

wait_for_card_again:
	mszGroups = NULL;
	printf("Testing SCardListReaders\t: ");
	rv = SCardListReaders(hContext, mszGroups, NULL, &dwReaders);
	test_rv(rv, hContext, DONT_PANIC);
	if (SCARD_E_NO_READERS_AVAILABLE == rv)
	{
		printf("Testing SCardGetStatusChange \n");
		printf("Please insert a working reader\t: ");
		(void)fflush(stdout);
		rgReaderStates[0].szReader = "\\\\?PnP?\\Notification";
		rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY;

		rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1);
		test_rv(rv, hContext, PANIC);
	}

	printf("Testing SCardListReaders\t: ");
#ifdef USE_AUTOALLOCATE
	dwReaders = SCARD_AUTOALLOCATE;
	rv = SCardListReaders(hContext, mszGroups, (LPSTR)&mszReaders, &dwReaders);
#else
	rv = SCardListReaders(hContext, mszGroups, NULL, &dwReaders);
	test_rv(rv, hContext, PANIC);

	printf("Testing SCardListReaders\t: ");
	mszReaders = calloc(dwReaders, sizeof(char));
	rv = SCardListReaders(hContext, mszGroups, mszReaders, &dwReaders);
#endif
	test_rv(rv, hContext, DONT_PANIC);

	/*
	 * Have to understand the multi-string here
	 */
	p = 0;
	for (i = 0; i+1 < dwReaders; i++)
	{
		++p;
		printf(GREEN "Reader %02d: %s\n" NORMAL, p, &mszReaders[i]);
		iList[p] = i;
		while (mszReaders[++i] != 0) ;
	}

	if (p > 1)
		do
		{
			char input[80];

			printf("Enter the reader number\t\t: ");
			(void)fgets(input, sizeof(input), stdin);
			(void)sscanf(input, "%d", &iReader);

			if (iReader > p || iReader <= 0)
				printf("Invalid Value - try again\n");
		}
		while (iReader > p || iReader <= 0);
	else
		iReader = 1;

	rgReaderStates[0].szReader = &mszReaders[iList[iReader]];
	rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY;

	printf("Waiting for card insertion\t: ");
	(void)fflush(stdout);
	rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1);
	test_rv(rv, hContext, PANIC);
	if (rgReaderStates[0].dwEventState & SCARD_STATE_UNKNOWN)
	{
		printf("\nA reader has been connected/disconnected\n");
		goto wait_for_card_again;
	}

	printf("Testing SCardConnect\t\t: ");
	rv = SCardConnect(hContext, &mszReaders[iList[iReader]],
		SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
		&hCard, &dwPref);
	test_rv(rv, hContext, PANIC);

	switch(dwPref)
	{
		case SCARD_PROTOCOL_T0:
			pioSendPci = *SCARD_PCI_T0;
			break;
		case SCARD_PROTOCOL_T1:
			pioSendPci = *SCARD_PCI_T1;
			break;
		case SCARD_PROTOCOL_RAW:
			pioSendPci = *SCARD_PCI_RAW;
			break;
		default:
			printf("Unknown protocol\n");
			return -1;
	}

	int bBreak = 0;

	while (1)
	{
		char inputCommand[1024];	
		char inputAPDU[1024];
		int inputAPDULen = sizeof(inputAPDU);
		printf("Enter APDU to send, (e.g. 00:A4:04:00:00)\n");
		printf("Command APDU: ");
		(void)fgets(inputCommand, sizeof(inputCommand), stdin);
		
		int stringlen = strlen(inputCommand);
		if( inputCommand[stringlen-1] == '\n' ) { inputCommand[stringlen-1] = 0; } //remove newline

		int bError = sc_hex_to_bin(inputCommand, inputAPDU, &inputAPDULen);
		//printf("debug - value bError: %i\n",bError);
		if (bError) { printf("Error parsing input\n\n"); continue; }

		send_length = inputAPDULen;
		if (inputAPDULen == 0) { break; }
		printf("debug inputAPDULen: %i\n",inputAPDULen); 
		memcpy(bSendBuffer, inputAPDU, send_length);
		length = sizeof(bRecvBuffer);

		printf("Testing SCardTransmit:\n "); printf("-> ");
		for (i=0; i<send_length; i++) { printf(" %02X", bSendBuffer[i]); }
		printf("\n");
		rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length,
			&pioRecvPci, bRecvBuffer, &length);
		test_rv(rv, hContext, PANIC);
		printf("<- " GREEN);
		for (i=0; i<length; i++)
			printf(" %02X", bRecvBuffer[i]);
		printf("\n" NORMAL);
	}

	testrun(&hCard, &hContext, &pioSendPci, 0);
	testrun(&hCard, &hContext, &pioSendPci, 1);
	testrun(&hCard, &hContext, &pioSendPci, 2);
	testrun(&hCard, &hContext, &pioSendPci, 3);

	printf("Testing SCardControl\t\t: ");
#ifdef PCSC_PRE_120
	{
		char buffer[1024] = "Foobar";
		DWORD cbRecvLength = sizeof(buffer);

		rv = SCardControl(hCard, buffer, 7, buffer, &cbRecvLength);
	}
#else
	{
		char buffer[1024] = { 0x02 };
		DWORD cbRecvLength = sizeof(buffer);

		rv = SCardControl(hCard, SCARD_CTL_CODE(1), buffer, 1, buffer,
			sizeof(buffer), &cbRecvLength);
		if (cbRecvLength && (SCARD_S_SUCCESS == rv))
		{
			for (i=0; i<cbRecvLength; i++)
				printf("%c", buffer[i]);
			printf(" ");
		}
	}
#endif
	test_rv(rv, hContext, DONT_PANIC);

	printf("Testing SCardGetAttrib\t\t: ");
#ifdef USE_AUTOALLOCATE
	pcbAttrLen = SCARD_AUTOALLOCATE;
	rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, (unsigned char *)&pbAttr,
		&pcbAttrLen);
#else
	rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, NULL, &pcbAttrLen);
	test_rv(rv, hContext, DONT_PANIC);
	if (rv == SCARD_S_SUCCESS)
	{
		printf("SCARD_ATTR_DEVICE_FRIENDLY_NAME length: " GREEN "%ld\n" NORMAL, pcbAttrLen);
		pbAttr = malloc(pcbAttrLen);
	}

	printf("Testing SCardGetAttrib\t\t: ");
	rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, pbAttr, &pcbAttrLen);
#endif
	test_rv(rv, hContext, DONT_PANIC);
	if (rv == SCARD_S_SUCCESS)
		printf("SCARD_ATTR_DEVICE_FRIENDLY_NAME: " GREEN "%s\n" NORMAL, pbAttr);

#ifdef USE_AUTOALLOCATE
	printf("Testing SCardFreeMemory\t\t: ");
	rv = SCardFreeMemory(hContext, pbAttr);
	test_rv(rv, hContext, PANIC);
#else
	if (pbAttr)
		free(pbAttr);
#endif

	printf("Testing SCardGetAttrib\t\t: ");
#ifdef USE_AUTOALLOCATE
	pcbAttrLen = SCARD_AUTOALLOCATE;
	rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, (unsigned char *)&pbAttr,
		&pcbAttrLen);
#else
	rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, NULL, &pcbAttrLen);
	test_rv(rv, hContext, DONT_PANIC);
	if (rv == SCARD_S_SUCCESS)
	{
		printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld\n" NORMAL, pcbAttrLen);
		pbAttr = malloc(pcbAttrLen);
	}

	printf("Testing SCardGetAttrib\t\t: ");
	rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, pbAttr, &pcbAttrLen);
#endif
	test_rv(rv, hContext, DONT_PANIC);
	if (rv == SCARD_S_SUCCESS)
	{
		printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld\n" NORMAL, pcbAttrLen);
		printf("SCARD_ATTR_ATR_STRING: " GREEN);
		for (i = 0; i < pcbAttrLen; i++)
			printf("%02X ", pbAttr[i]);
		printf("\n" NORMAL);
	}

#ifdef USE_AUTOALLOCATE
	printf("Testing SCardFreeMemory\t\t: ");
	rv = SCardFreeMemory(hContext, pbAttr);
	test_rv(rv, hContext, PANIC);
#else
	if (pbAttr)
		free(pbAttr);
#endif

	printf("Testing SCardGetAttrib\t\t: ");
	dwBufLen = sizeof(buf);
	rv = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_IFD_VERSION, buf.as_char, &dwBufLen);
	test_rv(rv, hContext, DONT_PANIC);
	if (rv == SCARD_S_SUCCESS)
		printf("Vendor IFD version\t\t: " GREEN "0x%08lX\n" NORMAL,
			buf.as_DWORD);

	printf("Testing SCardGetAttrib\t\t: ");
	dwBufLen = sizeof(buf);
	rv = SCardGetAttrib(hCard, SCARD_ATTR_MAXINPUT, buf.as_char, &dwBufLen);
	test_rv(rv, hContext, DONT_PANIC);
	if (rv == SCARD_S_SUCCESS)
	{
		if (dwBufLen == sizeof(uint32_t))
			printf("Max message length\t\t: " GREEN "%d\n" NORMAL,
				buf.as_uint32_t);
		else
			printf(RED "Wrong size" NORMAL);
	}

	printf("Testing SCardGetAttrib\t\t: ");
	dwBufLen = sizeof(buf);
	rv = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_NAME, buf.as_char, &dwBufLen);
	test_rv(rv, hContext, DONT_PANIC);
	if (rv == SCARD_S_SUCCESS)
		printf("Vendor name\t\t\t: " GREEN "%s\n" NORMAL, buf.as_char);

	printf("Testing SCardSetAttrib\t\t: ");
	rv = SCardSetAttrib(hCard, SCARD_ATTR_ATR_STRING, (LPCBYTE)"", 1);
	test_rv(rv, hContext, DONT_PANIC);

	printf("Testing SCardStatus\t\t: ");

#ifdef USE_AUTOALLOCATE
	dwReaderLen = SCARD_AUTOALLOCATE;
	dwAtrLen = SCARD_AUTOALLOCATE;
	rv = SCardStatus(hCard, (LPSTR)&pcReaders, &dwReaderLen, &dwState, &dwProt,
		(LPBYTE)&pbAtr, &dwAtrLen);
#else
	dwReaderLen = 100;
	pcReaders   = malloc(sizeof(char) * 100);
	dwAtrLen    = MAX_ATR_SIZE;

	rv = SCardStatus(hCard, pcReaders, &dwReaderLen, &dwState, &dwProt,
		pbAtr, &dwAtrLen);
#endif
	test_rv(rv, hContext, PANIC);

	printf("Current Reader Name\t\t: " GREEN "%s\n" NORMAL, pcReaders);
	printf("Current Reader State\t\t: " GREEN "0x%.4lx\n" NORMAL, dwState);
	printf("Current Reader Protocol\t\t: T=" GREEN "%ld\n" NORMAL, dwProt - 1);
	printf("Current Reader ATR Size\t\t: " GREEN "%ld" NORMAL " bytes\n",
		dwAtrLen);
	printf("Current Reader ATR Value\t: " GREEN);

	for (i = 0; i < dwAtrLen; i++)
	{
		printf("%02X ", pbAtr[i]);
	}
	printf(NORMAL "\n");

#ifdef USE_AUTOALLOCATE
	printf("Testing SCardFreeMemory\t\t: ");
	rv = SCardFreeMemory(hContext, pcReaders);
	test_rv(rv, hContext, PANIC);
	printf("Testing SCardFreeMemory\t\t: ");
	rv = SCardFreeMemory(hContext, pbAtr);
	test_rv(rv, hContext, PANIC);
#else
	if (pcReaders)
		free(pcReaders);
#endif

	if (rv != SCARD_S_SUCCESS)
	{
		(void)SCardDisconnect(hCard, SCARD_RESET_CARD);
		(void)SCardReleaseContext(hContext);
	}

	printf("Press enter: ");
	(void)getchar();
	printf("Testing SCardReconnect\t\t: ");
	rv = SCardReconnect(hCard, SCARD_SHARE_SHARED,
		SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_UNPOWER_CARD, &dwPref);
	test_rv(rv, hContext, PANIC);

	printf("Testing SCardDisconnect\t\t: ");
	rv = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
	test_rv(rv, hContext, PANIC);

#ifdef USE_AUTOALLOCATE
	printf("Testing SCardFreeMemory\t\t: ");
	rv = SCardFreeMemory(hContext, mszReaders);
	test_rv(rv, hContext, PANIC);
#else
	free(mszReaders);
#endif

	printf("Testing SCardReleaseContext\t: ");
	rv = SCardReleaseContext(hContext);
	test_rv(rv, hContext, PANIC);

	printf("\n");
	printf("PC/SC Test Completed Successfully !\n");

	return 0;
}
Beispiel #21
0
void SCardReader::run()
{
    SCARDCONTEXT context;
    SCARDHANDLE cardHandle;
    DWORD activeProtocol;
    DWORD oldEventState;
    LONG erv;

    erv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &context);
    if (SCARD_S_SUCCESS == erv)
    {
        LONG crv;

        crv = SCardConnect(context, (LPCSTR) m_name, SCARD_SHARE_SHARED,
                          SCARD_PROTOCOL_T0, &cardHandle, &activeProtocol);
        do
        {
            if (SCARD_S_SUCCESS == crv)
            {
                SCARD_IO_REQUEST ioRecvPci;
                BYTE recvBuffer[32];
                BYTE sendBuffer[] = {0xFF, 0xCA, 0x00, 0x00, 0x00};
                DWORD recvLength = sizeof(recvBuffer);
                LONG trv;

                trv = SCardTransmit(cardHandle, SCARD_PCI_T0, sendBuffer, sizeof(sendBuffer),&ioRecvPci, recvBuffer, &recvLength);
                if (SCARD_S_SUCCESS == trv)
                {
                    if (recvLength == 6 && recvBuffer[4] == 0x90 && recvBuffer[5] == 0x00)
                        m_cardid = (int)recvBuffer[0] | (int)recvBuffer[1] << 8 | (int)recvBuffer[2] << 16 | (int)recvBuffer[3] << 24;

                    std::cout <<  m_cardid  <<  " card inserted." << std::endl;

                    if (m_mode == TallyMode) // m_mode(DriverMode)  初始化为DriverMode
                    {
                        //load authentication key
                        recvLength = sizeof(recvBuffer);
                        BYTE loadKey[] = {0xFF, 0x82, 0x00, 0x00, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
                        trv = SCardTransmit(cardHandle, SCARD_PCI_T0, loadKey, sizeof(loadKey), &ioRecvPci, recvBuffer, &recvLength);
                        if (SCARD_S_SUCCESS == trv && recvLength == 2 && recvBuffer[0] == 0x90 && recvBuffer[1] == 0x00)
                        {
                            //authentication key
                            recvLength = sizeof(recvBuffer);
                            BYTE authentication[] = {0xFF, 0x86, 0x00, 0x00, 0x05, 0x01, 0x00, 0x08, 0x60, 0x00};
                            trv = SCardTransmit(cardHandle, SCARD_PCI_T0, authentication, sizeof(authentication), &ioRecvPci, recvBuffer, &recvLength);
                            if (SCARD_S_SUCCESS == trv && recvLength == 2 && recvBuffer[0] == 0x90 && recvBuffer[1] == 0x00)
                            {
                                //read binary
                                recvLength = sizeof(recvBuffer);
                                BYTE read[] = {0xFF, 0xB0, 0x00, 0x08, 0x10};
                                trv = SCardTransmit(cardHandle, SCARD_PCI_T0, read, sizeof(read), &ioRecvPci, recvBuffer, &recvLength);
                                if (SCARD_S_SUCCESS == trv && recvLength == 18 && recvBuffer[16] == 0x90 && recvBuffer[17] == 0x00)
                                {
                                    QByteArray array((const char *)recvBuffer, 16);
                                    emit dataReady(QString::number(m_cardid), array);
                                }
                                else
                                    std::cerr << m_name << " : " << pcsc_stringify_error(trv) << std::endl;
                            }
                            else
                                std::cerr << m_name << " : " << pcsc_stringify_error(trv) << std::endl;
                        }
                        else
                            std::cerr << m_name << " : " << pcsc_stringify_error(trv) << std::endl;
                    }
                    else
                        emit inserted(QString::number(m_cardid));
                }
                else if (SCARD_E_NO_SMARTCARD == trv)
                    std::cerr << m_name << " : " << pcsc_stringify_error(trv) << std::endl;
                else
                {
                    std::cerr << m_name << " : " << pcsc_stringify_error(trv) << std::endl;
                    break;
                }

                (void) SCardDisconnect(cardHandle, SCARD_RESET_CARD);
            }

            if (SCARD_S_SUCCESS == crv || SCARD_E_NO_SMARTCARD == crv)
            {
                SCARD_READERSTATE readerStates;
                LONG grv;

                readerStates.szReader = m_name;
                readerStates.dwCurrentState = SCARD_STATE_UNAWARE;
                grv = SCardGetStatusChange(context, INFINITE, &readerStates, 1);
                oldEventState = readerStates.dwEventState;

                do
                {
                    if (SCARD_S_SUCCESS == grv)
                    {
                        if (readerStates.dwEventState != oldEventState)
                        {
                            //card inserted
                            if  ((SCARD_STATE_CHANGED & readerStates.dwEventState) && (SCARD_STATE_PRESENT & readerStates.dwEventState))
                                break;

                            //card removed
                            if ((SCARD_STATE_CHANGED & readerStates.dwEventState) && (SCARD_STATE_EMPTY & readerStates.dwEventState))
                            {
                                removed(QString::number(m_cardid));
                                std::cout << m_cardid <<  " card removed." << std::endl;
                            }
                        }
                        else
                            QThread::usleep(500);
                    }
                    else if (SCARD_E_TIMEOUT == grv)
                        QThread::sleep(1);
                    else
                        break;

                    oldEventState = readerStates.dwEventState;

                    readerStates.szReader = m_name;
                    readerStates.dwCurrentState = SCARD_STATE_UNAWARE;

                    grv = SCardGetStatusChange(context, INFINITE, &readerStates, 1);

                } while (true);

                //quit if fatal error occurs
                if (SCARD_S_SUCCESS != grv)
                    break;
            }
            else
            {
                std::cerr << m_name << " : " << pcsc_stringify_error(crv) << std::endl;
                break;
            }

            crv = SCardConnect(context, (LPCSTR) m_name, SCARD_SHARE_SHARED,
                              SCARD_PROTOCOL_T0, &cardHandle, &activeProtocol);

        } while(true);
    }
    else
        std::cerr << m_name << " : " << pcsc_stringify_error(erv) << std::endl;

    std::cout << m_name << " deamon thread has exit." << std::endl;
}
PCSC::PCSC( std::string& a_stInputReaderName, u2& a_u2PortNumber, std::string& a_stURI, u4& a_NameSpaceHivecode, u2& a_TypeHivecode, u4& a_Index ) {

    Log::begin( "PCSC::PCSC" );

    m_bDoTransact = true;

    std::string stIdentifiedReaderName = "";

    LPTSTR pReaderList = NULL;

    if( a_stInputReaderName.empty( ) ) {

        a_stInputReaderName = "selfdiscover";
    }

    m_hContextPCSC = 0;

    m_hCardPCSC = 0;

    LONG lReturn = SCardEstablishContext( 0, NULL, NULL, &m_hContextPCSC );

    if( SCARD_S_SUCCESS != lReturn )
    {
        std::string msg = "";
        Log::toString( msg, "SCardEstablishContext <%#02x>", lReturn );
        Log::error( "PCSC::PCSC", msg.c_str( ) );

        throw RemotingException((lpCharPtr)"PCSC: SCardEstablishContext error",lReturn);
    }

    // self-discovery mechanism
#ifdef WIN32
    if (_stricmp("selfdiscover", a_stInputReaderName.c_str()) == 0) {
#else
    if (strncasecmp("selfdiscover", a_stInputReaderName.c_str(),a_stInputReaderName.length()) == 0) {
#endif
        // In Windows SCARD_AUTOALLOCATE (-1) as a value of readerListChatLength
        // would signal the SCardListReaders to determine the size of reader string
        // This is not available in Linux so we call the SCardListReaders twice. First
        // to get the length and then the reader names.
#ifdef WIN32
        DWORD readerListCharLength = SCARD_AUTOALLOCATE;
        lReturn = SCardListReaders( m_hContextPCSC, NULL, (LPTSTR)&pReaderList, &readerListCharLength);

#else
        DWORD readerListCharLength = 0;

        lReturn = SCardListReaders(m_hContextPCSC,NULL,NULL,&readerListCharLength);
        if(lReturn != SCARD_S_SUCCESS)
            throw RemotingException((lpCharPtr)"PCSC: SCardListReaders error",lReturn);

        pReaderList = (lpCharPtr)malloc(sizeof(char)*readerListCharLength);
        lReturn = SCardListReaders(m_hContextPCSC, NULL,pReaderList, &readerListCharLength);
#endif


        if(lReturn != SCARD_S_SUCCESS) {

            std::string msg = "";
            Log::toString( msg, "SCardListReaders <%#02x>", lReturn );
            Log::error( "PCSC::PCSC", msg.c_str( ) );
            throw RemotingException((lpCharPtr)"PCSC: SCardListReaders error",lReturn);

        } else {

            u4 count = 0;
            u1 foundReader = FALSE;
            SCARDHANDLE finalCardHandle = 0;

            try {

                lpTCharPtr pReader = pReaderList;

                while ('\0' != *pReader ) {

                    size_t readerNameLen = strlen((const char*)pReader);
                    SCARD_READERSTATE readerStates[1];
                    readerStates[0].dwCurrentState = SCARD_STATE_UNAWARE;
                    readerStates[0].szReader = pReader;

                    if ( SCardGetStatusChange( m_hContextPCSC, 0, readerStates, 1) == SCARD_S_SUCCESS) {

                        if ((readerStates[0].dwEventState & SCARD_STATE_PRESENT) == SCARD_STATE_PRESENT) {

                            // we found a card in this reader
                            stIdentifiedReaderName = pReader;

                            DWORD activeProtocol;

                            lReturn = SCardConnect( m_hContextPCSC, (LPTSTR)stIdentifiedReaderName.c_str(), SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &m_hCardPCSC, &activeProtocol);

                            if (lReturn == SCARD_S_SUCCESS) {

                                // try to identify if we're dealing with a .NetCard
                                u1 answerData[258];
                                DWORD answerLen = 258;

                                Log::log( "PCSC::PCSC SCardTransmit..." );
                                lReturn = SCardTransmit( m_hCardPCSC, SCARD_PCI_T0, isNetCardAPDU, sizeof(isNetCardAPDU), NULL, (LPBYTE)answerData, &answerLen);
                                Log::log( "PCSC::PCSC - SCardTransmit <%#02x>", lReturn );

                                if (lReturn == SCARD_S_SUCCESS)
                                {
                                    u1 rethrowException = FALSE;
                                    try {
                                        if (answerData[answerLen - 2] == 0x61)
                                        {
                                            if (answerData[answerLen - 1] > 10)
                                            {
                                                u1Array invokeAPDU(0);
                                                invokeAPDU += (u1)0xD8;
                                                invokeAPDU += (u2)CARDMANAGER_SERVICE_PORT;
                                                invokeAPDU += (u1)0x6F;
                                                invokeAPDU += (u4)HIVECODE_NAMESPACE_SMARTCARD;
                                                invokeAPDU += (u2)HIVECODE_TYPE_SMARTCARD_CONTENTMANAGER;
                                                invokeAPDU += (u2)HIVECODE_METHOD_SMARTCARD_CONTENTMANAGER_GETASSOCIATEDPORT;
                                                std::string* cmServicem_stURI = new std::string(CARDMANAGER_SERVICE_NAME);
                                                invokeAPDU.Append(cmServicem_stURI);
                                                delete cmServicem_stURI;
                                                invokeAPDU += (u4)a_NameSpaceHivecode;
                                                invokeAPDU += (u2)a_TypeHivecode;
                                                invokeAPDU.Append(&a_stURI);

                                                // construct call
                                                if(invokeAPDU.GetLength() <= (s4)APDU_TO_CARD_MAX_SIZE) {
                                                    u1Array apdu(5);
                                                    apdu.GetBuffer()[0] = 0x80;
                                                    apdu.GetBuffer()[1] = 0xC2;
                                                    apdu.GetBuffer()[2] = 0x00;
                                                    apdu.GetBuffer()[3] = 0x00;
                                                    apdu.GetBuffer()[4] = (u1)invokeAPDU.GetLength();
                                                    apdu += invokeAPDU;

                                                    u1Array answer(0);

                                                    Log::log( "PCSC::PCSC - ExchangeData..." );
                                                    exchangeData(apdu, answer);
                                                    Log::log( "PCSC::PCSC - ExchangeData ok" );

                                                    Log::log( "PCSC::PCSC - CheckForException..." );
                                                    u4 protocolOffset = m_MarshallerUtil.CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT32);
                                                    Log::log( "PCSC::PCSC - CheckForException ok" );

                                                    u4 discoveredPortNumber = m_MarshallerUtil.ComReadU4At(answer, protocolOffset);
                                                    if ((a_u2PortNumber == 0) || (discoveredPortNumber == a_u2PortNumber))
                                                    {
                                                        a_u2PortNumber = (u2)discoveredPortNumber;

                                                        if (foundReader == TRUE)
                                                        {
                                                            if (a_Index == 0)
                                                            {
                                                                // this is the second reader/card/app that matches - we error at this point
                                                                rethrowException = TRUE;
                                                                std::string errorMessage( "At least 2 cards posses \"");
                                                                errorMessage += a_stURI.c_str( );
                                                                errorMessage += "\" service\r\nRemove conflicting cards from your system";
                                                                Log::error( "PCSC::PCSC", errorMessage.c_str( ) );

                                                                throw RemotingException(errorMessage);
                                                            }
                                                        }

                                                        foundReader = TRUE;
                                                        finalCardHandle = m_hCardPCSC;

                                                        // Advance to the next value.
                                                        count++;

                                                        if (count == a_Index)
                                                        {
                                                            // we enumerate one by one the valid readers - so stop here
                                                            break;
                                                        }

                                                        pReader = (lpTCharPtr)((lpTCharPtr)pReader + readerNameLen + 1);
                                                        continue;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    catch (...)
                                    {
                                        if (rethrowException == TRUE)
                                        {
                                            throw;
                                        }
                                        else
                                        {
                                            // swallow exception
                                        }
                                    }

                                    SCardDisconnect( m_hCardPCSC, SCARD_LEAVE_CARD);
                                    m_hCardPCSC = 0;
                                }
                                // this is not a .NetCard, or the service was not found - let's try another reader/card
                                else
                                {
                                    Log::error( "PCSC::PCSC", "SCardTransmit failed" );
                                }
                            }
                            else
                            {
                                Log::error( "PCSC::PCSC", "SCardConnect failed" );
                            }
                        }
                        else
                        {
                            Log::error( "PCSC::PCSC", "SCARD_STATE_PRESENT not present" );
                        }
                    }
                    else
                    {
                        Log::error( "PCSC::PCSC", "SCardGetStatusChange != SCARD_S_SUCCESS" );
                    }

                    // Advance to the next value.
                    pReader = (lpTCharPtr)((lpTCharPtr)pReader + readerNameLen + 1);
                }
            } catch (...) {

                stIdentifiedReaderName = "";

#ifdef WIN32
                /*lReturn = */SCardFreeMemory( m_hContextPCSC, pReaderList);
                /*if(lReturn != SCARD_S_SUCCESS) {
                throw RemotingException((lpCharPtr)"PCSC: SCardFreeMemory error",lReturn);
                }*/
#else
                if( pReaderList ) {

                    free(pReaderList);
                }
#endif
                throw;
            }

            // have we found anything ?
            if( !foundReader) {

                stIdentifiedReaderName = "";

#ifdef WIN32
                /*lReturn = */SCardFreeMemory( m_hContextPCSC, pReaderList);
                //if(lReturn != SCARD_S_SUCCESS) {
                //    throw RemotingException((lpCharPtr)"PCSC: SCardFreeMemory error",lReturn);
                //}
#else
                if(pReaderList ) {

                    free(pReaderList);
                }
#endif

                throw RemotingException((lpCharPtr)"Could not find any .NET smart card", SCARD_E_NO_SMARTCARD );
            }

            m_hCardPCSC = finalCardHandle;
        }

        m_stReaderName = stIdentifiedReaderName;

    } else {

        m_stReaderName = a_stInputReaderName;
    }

    Log::end( "PCSC::PCSC" );
}


/*
*/
void PCSC::exchangeData( u1Array &dataIn, u1Array &dataout ) {

    // check validity of handle
    if ( SCARD_S_SUCCESS != SCardIsValidContext( m_hContextPCSC ) ) {

        throw RemotingException( (lpCharPtr)"PCSC: Invalid handle", SCARD_E_INVALID_HANDLE );
    }

    try {

        if( m_bDoTransact ) { 

            beginTransaction( );
        }

        unsigned char ucRetry = 0;

        do {

            ucRetry++;

            unsigned char answerData[ 258 ];
            memset( answerData, 0, sizeof( answerData ) );

            DWORD answerLen = sizeof( answerData );

#ifdef __DEBUG_APDU__
            Log::logCK_UTF8CHAR_PTR( "PCSC::ExchangeData - Command", dataIn.GetBuffer( ), dataIn.GetLength( ) );
            Timer t;
            t.start( );
#endif

            LONG lReturn = SCardTransmit( m_hCardPCSC, SCARD_PCI_T0, dataIn.GetBuffer( ), dataIn.GetLength( ), NULL, (lpByte)answerData, &answerLen );

            if( SCARD_S_SUCCESS != lReturn ) {

                std::string msg = "";
                Log::toString( msg, "SCardTransmit <%#02x>", lReturn );
                Log::error( "PCSC::ExchangeData", msg.c_str( ) );
            }

            if( ( SCARD_W_REMOVED_CARD == lReturn ) || ( SCARD_W_RESET_CARD == lReturn ) ) {

                DWORD dwActiveProtocol = SCARD_PROTOCOL_T0;

                lReturn = SCardReconnect( m_hCardPCSC, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_LEAVE_CARD, &dwActiveProtocol );

                if( SCARD_S_SUCCESS != lReturn ) {

                    std::string msg = "";
                    Log::toString( msg, "SCardReconnect <%#02x>", lReturn );
                    Log::error( "PCSC::ExchangeData", msg.c_str( ) );

                    throw RemotingException( (lpCharPtr)"PCSC: SCardReconnect error", lReturn );
                }

                lReturn = SCardTransmit( m_hCardPCSC, SCARD_PCI_T0, dataIn.GetBuffer( ), dataIn.GetLength( ), NULL, (lpByte)answerData, &answerLen );

                if( SCARD_S_SUCCESS != lReturn ) {

                    Log::log( "PCSC::ExchangeData - SCardTransmit <%#02x>", lReturn );
                }

            } else if( SCARD_S_SUCCESS != lReturn ) {

                std::string s;
                Log::toString( s, "SCardTransmit failed <%#02x>", lReturn );
                Log::error( "PCSC::ExchangeData", s.c_str( ) );

                throw RemotingException( (lpCharPtr)"PCSC: SCardTransmit error", lReturn );
            }

            if (answerLen < 2) {

                Log::error( "PCSC::ExchangeData", "Incorrect length returned" );

                throw RemotingException((lpCharPtr)"PCSC: SCardTransmit error - Incorrect length returned",SCARD_F_COMM_ERROR);
            }

            if (answerLen > 2) {

                u1Array temp(answerLen - 2);

                temp.SetBuffer(answerData);

                dataout += temp;
            }

            u1 sw1 = answerData[answerLen - 2];

            u1 sw2 = answerData[answerLen - 1];

#ifdef __DEBUG_APDU__
            Log::log( "PCSC::ExchangeData - Status (1) <%02x%02x>", sw1, sw2 );
            Log::logCK_UTF8CHAR_PTR( "PCSC::ExchangeData - Response", answerData, answerLen );
            t.stop( "PCSC::ExchangeData - Response" );
#endif

            while( (sw1 == 0x61 ) || ( sw1 == 0x9F ) ) {

                memset( answerData, 0, sizeof( answerData ) );

                unsigned char GetResponse[ 5 ];

                memset( GetResponse, 0, sizeof( GetResponse ) );

                if (sw1 == 0x9F) {

                    GetResponse[0] = 0xA0;

                } else {

                    GetResponse[0] = 0x00;
                }

                GetResponse[1] = 0xC0;

                GetResponse[2] = 0x00;

                GetResponse[3] = 0x00;

                GetResponse[4] = sw2;

                answerLen = 258;

#ifdef __DEBUG_APDU__
                Log::logCK_UTF8CHAR_PTR( "PCSC::ExchangeData - Command", GetResponse, sizeof( GetResponse ) );
                t.start( );
#endif

                lReturn = SCardTransmit( m_hCardPCSC, SCARD_PCI_T0, (lpCByte)GetResponse, 5, NULL, (lpByte)answerData, &answerLen );

                if( ( SCARD_W_REMOVED_CARD == lReturn ) || ( SCARD_W_RESET_CARD == lReturn ) ) {

                    DWORD dwActiveProtocol = SCARD_PROTOCOL_T0;

                    lReturn = SCardReconnect( m_hCardPCSC, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_LEAVE_CARD, &dwActiveProtocol );

                    lReturn = SCardTransmit( m_hCardPCSC, SCARD_PCI_T0, (lpCByte)GetResponse, 5, NULL, (lpByte)answerData, &answerLen );

                } else if( SCARD_S_SUCCESS != lReturn ) {

                    std::string s;
                    Log::toString( s, "SCardTransmit failed <%02x>", lReturn );
                    Log::error( "PCSC::ExchangeData", s.c_str( ) );

                    throw RemotingException( (lpCharPtr)"PCSC: SCardTransmit error", lReturn );
                }

                if( answerLen < 2 ) {

                    Log::error( "PCSC::ExchangeData", "Incorrect length returned" );

                    throw RemotingException( (lpCharPtr)"PCSC: SCardTransmit error - Incorrect length returned", SCARD_F_COMM_ERROR );
                }

                if( answerLen > 2 ) {

                    u1Array temp( answerLen - 2 );

                    temp.SetBuffer( answerData );

                    dataout += temp;
                }

                sw1 = answerData[ answerLen - 2 ];

                sw2 = answerData[ answerLen - 1 ];

#ifdef __DEBUG_APDU__
                Log::log( "PCSC::ExchangeData - Status (2) <%02x%02x>", sw1, sw2 );
                Log::logCK_UTF8CHAR_PTR( "PCSC::ExchangeData - Response", answerData, answerLen );
                t.stop( "PCSC::ExchangeData - Response" );
#endif
            }

            // The response is not acceptable. We have to retry the data transmission
            if( ( 0x63 == sw1 ) || ( ( 0x69 == sw1 ) && ( 0x99 == sw2 ) ) ) {

                Log::log( "PCSC::ExchangeData - Invalid response. Retry" );

            } else {

                break;
            }

 /*               if( ( 0x90 == sw1 ) && ( 0x00 == sw2 ) ) {

                break;
            }*/

        } while ( 3 > ucRetry );

    } catch (...) {

        if( m_bDoTransact ) { 

            endTransaction( );
        }

        throw;
    }

    if( m_bDoTransact ) { 

        endTransaction( );
    }
}


/* Cleanup the context and card handle
*/
PCSC::~PCSC( ) {

    if( m_hCardPCSC ) {

        SCardDisconnect( m_hCardPCSC, SCARD_LEAVE_CARD );

        m_hCardPCSC = 0;
    }

    if( m_hContextPCSC ) {

        SCardReleaseContext( m_hContextPCSC );

        m_hContextPCSC = 0;
    }
}

MARSHALLER_NS_END
Beispiel #23
0
int main(/*@unused@*/ int argc, /*@unused@*/ char **argv)
{
	SCARDHANDLE hCard;
	SCARDCONTEXT hContext;
	SCARD_READERSTATE rgReaderStates[1];
	DWORD dwReaderLen, dwState, dwProt, dwAtrLen;
	DWORD dwPref, dwReaders = 0;
	char *pcReader = NULL, *mszReaders;
#ifdef USE_AUTOALLOCATE
	unsigned char *pbAtr = NULL;
#else
	unsigned char pbAtr[MAX_ATR_SIZE];
#endif
	union {
		unsigned char as_char[100];
		DWORD as_DWORD;
		uint32_t as_uint32_t;
	} buf;
	DWORD dwBufLen;
	unsigned char *pbAttr = NULL;
	DWORD pcbAttrLen;
	char *mszGroups;
	DWORD dwGroups = 0;
	long rv;
	DWORD i;
	int p, iReader;
	int iList[16] = {0};
	SCARD_IO_REQUEST ioRecvPci = *SCARD_PCI_T0;	/* use a default value */
	const SCARD_IO_REQUEST *pioSendPci;
	unsigned char bSendBuffer[MAX_BUFFER_SIZE];
	unsigned char bRecvBuffer[MAX_BUFFER_SIZE];
	DWORD send_length, length;

	(void)argc;
	(void)argv;

	printf("\nMUSCLE PC/SC Lite unitary test Program\n\n");

	printf(MAGENTA "THIS PROGRAM IS NOT DESIGNED AS A TESTING TOOL FOR END USERS!\n");
	printf("Do NOT use it unless you really know what you do.\n\n" NORMAL);

	printf("Testing SCardEstablishContext\t: ");
	rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
	test_rv(rv, hContext, PANIC);

	printf("Testing SCardIsValidContext\t: ");
	rv = SCardIsValidContext(hContext);
	test_rv(rv, hContext, PANIC);

	printf("Testing SCardIsValidContext\t: ");
	rv = SCardIsValidContext(hContext+1);
	test_rv(rv, hContext, DONT_PANIC);

	printf("Testing SCardListReaderGroups\t: ");
#ifdef USE_AUTOALLOCATE
	dwGroups = SCARD_AUTOALLOCATE;
	rv = SCardListReaderGroups(hContext, (LPSTR)&mszGroups, &dwGroups);
#else
	rv = SCardListReaderGroups(hContext, NULL, &dwGroups);
	test_rv(rv, hContext, PANIC);

	printf("Testing SCardListReaderGroups\t: ");
	mszGroups = calloc(dwGroups, sizeof(char));
	rv = SCardListReaderGroups(hContext, mszGroups, &dwGroups);
#endif
	test_rv(rv, hContext, PANIC);

	/*
	 * Have to understand the multi-string here
	 */
	p = 0;
	for (i = 0; i+1 < dwGroups; i++)
	{
		++p;
		printf(GREEN "Group %02d: %s\n" NORMAL, p, &mszGroups[i]);
		while (mszGroups[++i] != 0) ;
	}

#ifdef USE_AUTOALLOCATE
	printf("Testing SCardFreeMemory\t\t: ");
	rv = SCardFreeMemory(hContext, mszGroups);
	test_rv(rv, hContext, PANIC);
#else
	free(mszGroups);
#endif

wait_for_card_again:
	mszGroups = NULL;
	printf("Testing SCardListReaders\t: ");
	rv = SCardListReaders(hContext, mszGroups, NULL, &dwReaders);
	test_rv(rv, hContext, DONT_PANIC);
	if (SCARD_E_NO_READERS_AVAILABLE == rv)
	{
		printf("Testing SCardGetStatusChange \n");
		printf("Please insert a working reader\t: ");
		(void)fflush(stdout);
		rgReaderStates[0].szReader = "\\\\?PnP?\\Notification";
		rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY;

		rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1);
		test_rv(rv, hContext, PANIC);
	}

	printf("Testing SCardListReaders\t: ");
#ifdef USE_AUTOALLOCATE
	dwReaders = SCARD_AUTOALLOCATE;
	rv = SCardListReaders(hContext, mszGroups, (LPSTR)&mszReaders, &dwReaders);
#else
	rv = SCardListReaders(hContext, mszGroups, NULL, &dwReaders);
	test_rv(rv, hContext, PANIC);

	printf("Testing SCardListReaders\t: ");
	mszReaders = calloc(dwReaders, sizeof(char));
	rv = SCardListReaders(hContext, mszGroups, mszReaders, &dwReaders);
#endif
	test_rv(rv, hContext, DONT_PANIC);

	/*
	 * Have to understand the multi-string here
	 */
	p = 0;
	for (i = 0; i+1 < dwReaders; i++)
	{
		++p;
		printf(GREEN "Reader %02d: %s\n" NORMAL, p, &mszReaders[i]);
		iList[p] = i;
		while (mszReaders[++i] != 0) ;
	}

	if (p > 1)
		do
		{
			char input[80];
			char *r;

			printf("Enter the reader number\t\t: ");
			r = fgets(input, sizeof(input), stdin);
			if (NULL == r)
				iReader = -1;
			else
				iReader = atoi(input);

			if (iReader > p || iReader <= 0)
				printf("Invalid Value - try again\n");
		}
		while (iReader > p || iReader <= 0);
	else
		iReader = 1;

	rgReaderStates[0].szReader = &mszReaders[iList[iReader]];
	rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY;

	printf("Waiting for card insertion\t: ");
	(void)fflush(stdout);
	rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1);
	test_rv(rv, hContext, PANIC);
	if (rgReaderStates[0].dwEventState & SCARD_STATE_UNKNOWN)
	{
		printf("\nA reader has been connected/disconnected\n");
		goto wait_for_card_again;
	}

	printf("Testing SCardConnect\t\t: ");
	rv = SCardConnect(hContext, &mszReaders[iList[iReader]],
		SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
		&hCard, &dwPref);
	test_rv(rv, hContext, PANIC);

	switch(dwPref)
	{
		case SCARD_PROTOCOL_T0:
			pioSendPci = SCARD_PCI_T0;
			break;
		case SCARD_PROTOCOL_T1:
			pioSendPci = SCARD_PCI_T1;
			break;
		case SCARD_PROTOCOL_RAW:
			pioSendPci = SCARD_PCI_RAW;
			break;
		default:
			printf("Unknown protocol\n");
			return -1;
	}

	/* APDU select file */
	printf("Select file:");
	send_length = 7;
	memcpy(bSendBuffer, "\x00\xA4\x00\x00\x02\x3F\x00", send_length);
	for (i=0; i<send_length; i++)
		printf(" %02X", bSendBuffer[i]);
	printf("\n");
	length = sizeof(bRecvBuffer);

	printf("Testing SCardTransmit\t\t: ");
	rv = SCardTransmit(hCard, pioSendPci, bSendBuffer, send_length,
		&ioRecvPci, bRecvBuffer, &length);
	test_rv(rv, hContext, PANIC);
	printf(" card response:" GREEN);
	for (i=0; i<length; i++)
		printf(" %02X", bRecvBuffer[i]);
	printf("\n" NORMAL);

	printf("Testing SCardControl\t\t: ");
#ifdef PCSC_PRE_120
	{
		char buffer[1024] = "Foobar";
		DWORD cbRecvLength = sizeof(buffer);

		rv = SCardControl(hCard, buffer, 7, buffer, &cbRecvLength);
	}
#else
	{
		char buffer[1024] = { 0x02 };
		DWORD cbRecvLength = sizeof(buffer);

		rv = SCardControl(hCard, SCARD_CTL_CODE(1), buffer, 1, buffer,
			sizeof(buffer), &cbRecvLength);
		if (cbRecvLength && (SCARD_S_SUCCESS == rv))
		{
			for (i=0; i<cbRecvLength; i++)
				printf("%c", buffer[i]);
			printf(" ");
		}
	}
#endif
	test_rv(rv, hContext, DONT_PANIC);

	printf("Testing SCardGetAttrib\t\t: ");
#ifdef USE_AUTOALLOCATE
	pcbAttrLen = SCARD_AUTOALLOCATE;
	rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, (unsigned char *)&pbAttr,
		&pcbAttrLen);
#else
	rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, NULL, &pcbAttrLen);
	test_rv(rv, hContext, DONT_PANIC);
	if (rv == SCARD_S_SUCCESS)
	{
		printf("SCARD_ATTR_DEVICE_FRIENDLY_NAME length: " GREEN "%ld\n" NORMAL, pcbAttrLen);
		pbAttr = malloc(pcbAttrLen);
	}

	printf("Testing SCardGetAttrib\t\t: ");
	rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, pbAttr, &pcbAttrLen);
#endif
	test_rv(rv, hContext, DONT_PANIC);
	if (rv == SCARD_S_SUCCESS)
		printf("SCARD_ATTR_DEVICE_FRIENDLY_NAME: " GREEN "%s\n" NORMAL, pbAttr);

#ifdef USE_AUTOALLOCATE
	printf("Testing SCardFreeMemory\t\t: ");
	rv = SCardFreeMemory(hContext, pbAttr);
	test_rv(rv, hContext, PANIC);
#else
	if (pbAttr)
		free(pbAttr);
#endif

	printf("Testing SCardGetAttrib\t\t: ");
#ifdef USE_AUTOALLOCATE
	pcbAttrLen = SCARD_AUTOALLOCATE;
	rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, (unsigned char *)&pbAttr,
		&pcbAttrLen);
#else
	rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, NULL, &pcbAttrLen);
	test_rv(rv, hContext, DONT_PANIC);
	if (rv == SCARD_S_SUCCESS)
	{
		printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld\n" NORMAL, pcbAttrLen);
		pbAttr = malloc(pcbAttrLen);
	}

	printf("Testing SCardGetAttrib\t\t: ");
	rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, pbAttr, &pcbAttrLen);
#endif
	test_rv(rv, hContext, DONT_PANIC);
	if (rv == SCARD_S_SUCCESS)
	{
		printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld\n" NORMAL, pcbAttrLen);
		printf("SCARD_ATTR_ATR_STRING: " GREEN);
		for (i = 0; i < pcbAttrLen; i++)
			printf("%02X ", pbAttr[i]);
		printf("\n" NORMAL);
	}

#ifdef USE_AUTOALLOCATE
	printf("Testing SCardFreeMemory\t\t: ");
	rv = SCardFreeMemory(hContext, pbAttr);
	test_rv(rv, hContext, PANIC);
#else
	if (pbAttr)
		free(pbAttr);
#endif

	printf("Testing SCardGetAttrib\t\t: ");
	dwBufLen = sizeof(buf);
	rv = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_IFD_VERSION, buf.as_char, &dwBufLen);
	test_rv(rv, hContext, DONT_PANIC);
	if (rv == SCARD_S_SUCCESS)
	{
		int valid = 1;	/* valid value by default */
		long value;
		printf("Vendor IFD version\t\t: ");
		if (dwBufLen == sizeof(DWORD))
			value = buf.as_DWORD;
		else
		{
			if (dwBufLen == sizeof(uint32_t))
				value = buf.as_uint32_t;
			else
			{
				printf(RED "Unsupported size\n" NORMAL);
				valid = 0;	/* invalid value */
			}
		}

		if (valid)
		{
			int M = (value & 0xFF000000) >> 24;		/* Major */
			int m = (value & 0x00FF0000) >> 16;		/* Minor */
			int b = (value & 0x0000FFFF);			/* build */
			printf(GREEN "%d.%d.%d\n" NORMAL, M, m, b);
		}
	}
static int pcsc_connect(cardreader_t *cr, unsigned prefered_protocol)
{
    DWORD attr_maxinput = 0;
    DWORD attr_maxinput_len = sizeof(unsigned int);
    SCARD_READERSTATE reader_state;
    pcsc_data_t* pcsc = cr->extra_data;
    int counter = 0;
    void *progress;

    memset(&reader_state,0,sizeof(reader_state));
    reader_state.szReader = cr->name+7;
    reader_state.dwCurrentState = SCARD_STATE_UNAWARE;
    pcsc->status = SCardGetStatusChange(pcsc->hcontext,INFINITE,&reader_state,1);

    if (pcsc->status != SCARD_S_SUCCESS)
    {
        log_printf(LOG_ERROR,"Failed to query reader status before connecting: %s (error 0x%08x).",
                pcsc_stringify_error(pcsc->status),
                pcsc->status );
        return 0;
    }

    progress = ui_inprogress_new("Connection","Waiting for the reader to connect to a card.");
    while ((reader_state.dwEventState & SCARD_STATE_PRESENT)==0)
    {
        reader_state.dwCurrentState = reader_state.dwEventState;
        if (((counter++)%30)==0)
        {
            log_printf(LOG_INFO,"Waiting for card to be present (current state: %s)...",
                    pcsc_stringify_state(reader_state.dwEventState));
        }

        if (!ui_inprogress_pulse(progress))
        {
            log_printf(LOG_ERROR,"Connection aborted by user");
            ui_inprogress_free(progress);
            pcsc->status = 0x6FFF;
            return 0;	    
        }

        pcsc->status = SCardGetStatusChange(pcsc->hcontext,100,&reader_state,1);
        if ((pcsc->status!=(LONG)SCARD_S_SUCCESS) && (pcsc->status!=(LONG)SCARD_E_TIMEOUT))
        {
            log_printf(LOG_ERROR,"Failed to query reader status change before connecting: %s (error 0x%08x/%08x).",
                    pcsc_stringify_error(pcsc->status),
                    pcsc->status,
                    SCARD_E_TIMEOUT );
            return 0;
        }
    }
    ui_inprogress_free(progress);

    log_printf(LOG_DEBUG,"Attempting to connect to '%s'",cr->name);
    pcsc->status = SCardConnect(pcsc->hcontext,
            cr->name+7,
            /* SCARD_SHARE_EXCLUSIVE, */
            SCARD_SHARE_SHARED,
            prefered_protocol,
            &(pcsc->hcard),
            &(cr->protocol));

    if (pcsc->status!=SCARD_S_SUCCESS)
    {
        log_printf(LOG_ERROR,"Connection failed: %s (error 0x%08x).",
                pcsc_stringify_error(pcsc->status),
                pcsc->status );
        return 0;
    }

    if (SCardGetAttrib(pcsc->hcard,SCARD_ATTR_MAXINPUT,(LPBYTE)&attr_maxinput,(LPDWORD)&attr_maxinput_len)==SCARD_S_SUCCESS)
        log_printf(LOG_INFO,"Reader maximum input length is %u bytes",attr_maxinput);
    else
        log_printf(LOG_DEBUG,"Could not determinate reader maximum input length");

    log_printf(LOG_INFO,"Connection successful, protocol is %s",pcsc_stringify_protocol(cr->protocol));
    cr->connected=1;

    return 1;
}
static uint32 handle_GetStatusChange(IRP* irp, tbool wide)
{
	LONG rv;
	SCARDCONTEXT hContext;
	DWORD dwTimeout = 0;
	DWORD readerCount = 0;
	SCARD_READERSTATE *readerStates, *cur;
	int i;

	stream_seek(irp->input, 0x18);
	stream_read_uint32(irp->input, dwTimeout);
	stream_read_uint32(irp->input, readerCount);

	stream_seek(irp->input, 8);

	stream_read_uint32(irp->input, hContext);

	stream_seek(irp->input, 4);

	DEBUG_SCARD("context: 0x%08x, timeout: 0x%08x, count: %d",
		     (unsigned) hContext, (unsigned) dwTimeout, (int) readerCount);
	if (readerCount > 0)
	{
		readerStates = xzalloc(readerCount * sizeof(SCARD_READERSTATE));
		if (!readerStates)
			return sc_output_return(irp, SCARD_E_NO_MEMORY);


		for (i = 0; i < readerCount; i++)
		{
			cur = &readerStates[i];

			stream_seek(irp->input, 4);

			/*
			 * TODO: on-wire is little endian; need to either
			 * convert to host endian or fix the headers to
			 * request the order we want
			 */
			stream_read_uint32(irp->input, cur->dwCurrentState);
			stream_read_uint32(irp->input, cur->dwEventState);
			stream_read_uint32(irp->input, cur->cbAtr);
			stream_read(irp->input, cur->rgbAtr, 32);

			stream_seek(irp->input, 4);

			/* reset high bytes? */
			cur->dwCurrentState &= 0x0000FFFF;
			cur->dwEventState &= 0x0000FFFF;
			cur->dwEventState = 0;
		}

		for (i = 0; i < readerCount; i++)
		{
			cur = &readerStates[i];
			uint32 dataLength;

			stream_seek(irp->input, 8);
			stream_read_uint32(irp->input, dataLength);
			sc_input_repos(irp, sc_input_string(irp, (char **) &cur->szReader, dataLength, wide));

			DEBUG_SCARD("   \"%s\"", cur->szReader ? cur->szReader : "NULL");
			DEBUG_SCARD("       user: 0x%08x, state: 0x%08x, event: 0x%08x",
				(unsigned) cur->pvUserData, (unsigned) cur->dwCurrentState,
				(unsigned) cur->dwEventState);

			if (strcmp(cur->szReader, "\\\\?PnP?\\Notification") == 0)
				cur->dwCurrentState |= SCARD_STATE_IGNORE;
		}
	}
	else
	{
		readerStates = NULL;
	}

	rv = SCardGetStatusChange(hContext, (DWORD) dwTimeout, readerStates, (DWORD) readerCount);

	if (rv != SCARD_S_SUCCESS)
		DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv);
	else
		DEBUG_SCARD("Success");

	stream_write_uint32(irp->output, readerCount);
	stream_write_uint32(irp->output, 0x00084dd8);
	stream_write_uint32(irp->output, readerCount);

	for (i = 0; i < readerCount; i++)
	{
		cur = &readerStates[i];

		DEBUG_SCARD("   \"%s\"", cur->szReader ? cur->szReader : "NULL");
		DEBUG_SCARD("       user: 0x%08x, state: 0x%08x, event: 0x%08x\n",
			(unsigned) cur->pvUserData, (unsigned) cur->dwCurrentState,
			(unsigned) cur->dwEventState);

		/* TODO: do byte conversions if necessary */
		stream_write_uint32(irp->output, cur->dwCurrentState);
		stream_write_uint32(irp->output, cur->dwEventState);
		stream_write_uint32(irp->output, cur->cbAtr);
		stream_write(irp->output, cur->rgbAtr, 32);

		stream_write_zero(irp->output, 4);

		xfree((void *)cur->szReader);
	}

	sc_output_alignment(irp, 8);

	xfree(readerStates);
	return rv;
}
Beispiel #26
0
void PCSCResourceManager::run()
{
    SCARDCONTEXT context;
    LONG rv;

    while (true)
    {
        rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &context);

        if (rv == SCARD_S_SUCCESS)
        {
            DWORD readerNum = SCARD_AUTOALLOCATE;
            LPSTR readerNames = NULL;

            do
            {
                rv = SCardListReaders(context, NULL, (LPSTR) &readerNames, &readerNum);

                if (rv == SCARD_S_SUCCESS)
                {
                    for (LPCSTR pch = readerNames; *pch != '\0'; pch += strlen(pch) + 1)
                    {
                        int i;
                        for (i = 0; i < m_availabeReaders.size(); i++)
                            if (0 == strcmp(m_availabeReaders[i]->name(), pch))
                                break;

                        if (i == m_availabeReaders.size())
                        {
                                SCardReader *reader = new SCardReader(pch);
                                m_availabeReaders.append(reader);
                                connect(reader, SIGNAL(unavailable(LPCSTR)), SLOT(clearUnavailabeReader(LPCSTR)));
                                reader->start();

                                emit readerPluged(reader);
                        }
                    }

                    (void) SCardFreeMemory(context, readerNames);
                }
                else
                    std::cout << pcsc_stringify_error(rv) << std::endl;

                if (rv == SCARD_S_SUCCESS || rv == SCARD_E_NO_READERS_AVAILABLE)
                {
                    SCARD_READERSTATE readerStates;

                    readerStates.szReader = "\\\\?PnP?\\Notification";
                    readerStates.dwCurrentState = SCARD_STATE_UNAWARE;

                    rv = SCardGetStatusChange(context, INFINITE, &readerStates, 1);

                    if (rv != SCARD_E_TIMEOUT || rv != SCARD_S_SUCCESS)
                    {
                        (void) SCardReleaseContext(context);
                        break;
                    }
                }
                else
                {
                    (void) SCardReleaseContext(context);
                    break;
                }
            } while (true);
        }
        else
        {
            std::cout << pcsc_stringify_error(rv) << std::endl;
            QThread::sleep(PCSC_ERROR_BREAK_TIME);
        }
    }
}