pcsc-lite  1.8.7
winscard.c
Go to the documentation of this file.
1 /*
2  * MUSCLE SmartCard Development ( http://www.linuxnet.com )
3  *
4  * Copyright (C) 1999-2004
5  * David Corcoran <corcoran@linuxnet.com>
6  * Copyright (C) 2002-2011
7  * Ludovic Rousseau <ludovic.rousseau@free.fr>
8  *
9  * $Id: winscard.c 6391 2012-07-26 18:44:54Z rousseau $
10  */
11 
82 #include "config.h"
83 #include <stdlib.h>
84 #include <sys/time.h>
85 #include <string.h>
86 #include <pthread.h>
87 
88 #include "pcscd.h"
89 #include "winscard.h"
90 #include "ifdhandler.h"
91 #include "debuglog.h"
92 #include "readerfactory.h"
93 #include "prothandler.h"
94 #include "ifdwrapper.h"
95 #include "atrhandler.h"
96 #include "sys_generic.h"
97 #include "eventhandler.h"
98 #include "utils.h"
99 #include "reader.h"
100 #include "strlcpycat.h"
101 
102 #undef DO_PROFILE
103 #ifdef DO_PROFILE
104 
105 #ifndef FALSE
106 #define FALSE 0
107 #define TRUE 1
108 #endif
109 
110 #define PROFILE_FILE "/tmp/pcscd_profile"
111 #include <stdio.h>
112 #include <sys/time.h>
113 #include <errno.h>
114 #include <unistd.h>
115 
116 struct timeval profile_time_start;
117 FILE *fd;
118 char profile_tty;
119 
120 #define PROFILE_START profile_start(__FUNCTION__);
121 #define PROFILE_END profile_end(__FUNCTION__, __LINE__);
122 
123 static void profile_start(const char *f)
124 {
125  static char initialized = FALSE;
126 
127  if (!initialized)
128  {
129  initialized = TRUE;
130  fd = fopen(PROFILE_FILE, "a+");
131  if (NULL == fd)
132  {
133  fprintf(stderr, "\33[01;31mCan't open %s: %s\33[0m\n",
134  PROFILE_FILE, strerror(errno));
135  exit(-1);
136  }
137  fprintf(fd, "\nStart a new profile\n");
138  fflush(fd);
139 
140  if (isatty(fileno(stderr)))
141  profile_tty = TRUE;
142  else
143  profile_tty = FALSE;
144  }
145 
146  gettimeofday(&profile_time_start, NULL);
147 } /* profile_start */
148 
149 
150 static void profile_end(const char *f, int line)
151 {
152  struct timeval profile_time_end;
153  long d;
154 
155  gettimeofday(&profile_time_end, NULL);
156  d = time_sub(&profile_time_end, &profile_time_start);
157 
158  if (profile_tty)
159  fprintf(stderr, "\33[01;31mRESULT %s \33[35m%ld\33[0m (%d)\n", f, d,
160  line);
161  fprintf(fd, "%s %ld\n", f, d);
162  fflush(fd);
163 } /* profile_end */
164 
165 #else
166 #define PROFILE_START
167 #define PROFILE_END
168 #endif
169 
171 #define SCARD_PROTOCOL_ANY_OLD 0x1000
172 
173 LONG SCardEstablishContext(DWORD dwScope, /*@unused@*/ LPCVOID pvReserved1,
174  /*@unused@*/ LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
175 {
176  (void)pvReserved1;
177  (void)pvReserved2;
178 
179  if (dwScope != SCARD_SCOPE_USER && dwScope != SCARD_SCOPE_TERMINAL &&
180  dwScope != SCARD_SCOPE_SYSTEM && dwScope != SCARD_SCOPE_GLOBAL)
181  {
182  *phContext = 0;
183  return SCARD_E_INVALID_VALUE;
184  }
185 
186  /*
187  * Unique identifier for this server so that it can uniquely be
188  * identified by clients and distinguished from others
189  */
190 
191  *phContext = SYS_RandomInt(0, -1);
192 
193  Log2(PCSC_LOG_DEBUG, "Establishing Context: 0x%lX", *phContext);
194 
195  return SCARD_S_SUCCESS;
196 }
197 
199 {
200  /*
201  * Nothing to do here RPC layer will handle this
202  */
203 
204  Log2(PCSC_LOG_DEBUG, "Releasing Context: 0x%lX", hContext);
205 
206  return SCARD_S_SUCCESS;
207 }
208 
209 LONG SCardConnect(/*@unused@*/ SCARDCONTEXT hContext, LPCSTR szReader,
210  DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
211  LPDWORD pdwActiveProtocol)
212 {
213  LONG rv;
214  READER_CONTEXT * rContext = NULL;
215  uint32_t readerState;
216 
217  (void)hContext;
218  PROFILE_START
219 
220  *phCard = 0;
221 
222  if ((dwShareMode != SCARD_SHARE_DIRECT) &&
223  !(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
224  !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
225  !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
226  !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
227  return SCARD_E_PROTO_MISMATCH;
228 
229  if (dwShareMode != SCARD_SHARE_EXCLUSIVE &&
230  dwShareMode != SCARD_SHARE_SHARED &&
231  dwShareMode != SCARD_SHARE_DIRECT)
232  return SCARD_E_INVALID_VALUE;
233 
234  Log3(PCSC_LOG_DEBUG, "Attempting Connect to %s using protocol: %ld",
235  szReader, dwPreferredProtocols);
236 
237  rv = RFReaderInfo((LPSTR) szReader, &rContext);
238  if (rv != SCARD_S_SUCCESS)
239  {
240  Log2(PCSC_LOG_ERROR, "Reader %s Not Found", szReader);
241  return rv;
242  }
243 
244  /*
245  * Make sure the reader is working properly
246  */
247  rv = RFCheckReaderStatus(rContext);
248  if (rv != SCARD_S_SUCCESS)
249  goto exit;
250 
251  /*******************************************
252  *
253  * This section checks for simple errors
254  *
255  *******************************************/
256 
257  /*
258  * Connect if not exclusive mode
259  */
261  {
262  Log1(PCSC_LOG_ERROR, "Error Reader Exclusive");
264  goto exit;
265  }
266 
267  /*
268  * wait until a possible transaction is finished
269  */
270  if (rContext->hLockId != 0)
271  {
272  Log1(PCSC_LOG_INFO, "Waiting for release of lock");
273  while (rContext->hLockId != 0)
275  Log1(PCSC_LOG_INFO, "Lock released");
276  }
277 
278  /*******************************************
279  *
280  * This section tries to determine the
281  * presence of a card or not
282  *
283  *******************************************/
284  readerState = rContext->readerState->readerState;
285 
286  if (dwShareMode != SCARD_SHARE_DIRECT)
287  {
288  if (!(readerState & SCARD_PRESENT))
289  {
290  Log1(PCSC_LOG_DEBUG, "Card Not Inserted");
292  goto exit;
293  }
294 
295  /* Power on (again) the card if needed */
296  (void)pthread_mutex_lock(&rContext->powerState_lock);
297  if (POWER_STATE_UNPOWERED == rContext->powerState)
298  {
299  DWORD dwAtrLen;
300 
301  dwAtrLen = sizeof(rContext->readerState->cardAtr);
302  rv = IFDPowerICC(rContext, IFD_POWER_UP,
303  rContext->readerState->cardAtr, &dwAtrLen);
304  rContext->readerState->cardAtrLength = dwAtrLen;
305 
306  if (rv == IFD_SUCCESS)
307  {
308  readerState = SCARD_PRESENT | SCARD_POWERED | SCARD_NEGOTIABLE;
309 
310  Log1(PCSC_LOG_DEBUG, "power up complete.");
311  LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
312  rContext->readerState->cardAtr,
313  rContext->readerState->cardAtrLength);
314  }
315  else
316  Log3(PCSC_LOG_ERROR, "Error powering up card: %ld 0x%04lX",
317  rv, rv);
318  }
319 
320  if (! (readerState & SCARD_POWERED))
321  {
322  Log1(PCSC_LOG_ERROR, "Card Not Powered");
323  (void)pthread_mutex_unlock(&rContext->powerState_lock);
325  goto exit;
326  }
327 
328  /* the card is now in use */
329  rContext->powerState = POWER_STATE_INUSE;
330  Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_INUSE");
331  (void)pthread_mutex_unlock(&rContext->powerState_lock);
332  }
333 
334  /*******************************************
335  *
336  * This section tries to decode the ATR
337  * and set up which protocol to use
338  *
339  *******************************************/
340  if (dwPreferredProtocols & SCARD_PROTOCOL_RAW)
342  else
343  {
344  if (dwShareMode != SCARD_SHARE_DIRECT)
345  {
346  /* lock here instead in IFDSetPTS() to lock up to
347  * setting rContext->readerState->cardProtocol */
348  (void)pthread_mutex_lock(rContext->mMutex);
349 
350  /* the protocol is not yet set (no PPS yet) */
352  {
353  int availableProtocols, defaultProtocol;
354  int ret;
355 
356  ATRDecodeAtr(&availableProtocols, &defaultProtocol,
357  rContext->readerState->cardAtr,
358  rContext->readerState->cardAtrLength);
359 
360  /* If it is set to ANY let it do any of the protocols */
361  if (dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)
362  dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
363 
364  ret = PHSetProtocol(rContext, dwPreferredProtocols,
365  availableProtocols, defaultProtocol);
366 
367  /* keep cardProtocol = SCARD_PROTOCOL_UNDEFINED in case of error */
368  if (SET_PROTOCOL_PPS_FAILED == ret)
369  {
370  (void)pthread_mutex_unlock(rContext->mMutex);
372  goto exit;
373  }
374 
375  if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
376  {
377  (void)pthread_mutex_unlock(rContext->mMutex);
379  goto exit;
380  }
381 
382  /* use negotiated protocol */
383  rContext->readerState->cardProtocol = ret;
384 
385  (void)pthread_mutex_unlock(rContext->mMutex);
386  }
387  else
388  {
389  (void)pthread_mutex_unlock(rContext->mMutex);
390 
391  if (! (dwPreferredProtocols & rContext->readerState->cardProtocol))
392  {
394  goto exit;
395  }
396  }
397  }
398  }
399 
400  *pdwActiveProtocol = rContext->readerState->cardProtocol;
401 
402  if (dwShareMode != SCARD_SHARE_DIRECT)
403  {
404  switch (*pdwActiveProtocol)
405  {
406  case SCARD_PROTOCOL_T0:
407  case SCARD_PROTOCOL_T1:
408  Log2(PCSC_LOG_DEBUG, "Active Protocol: T=%d",
409  (*pdwActiveProtocol == SCARD_PROTOCOL_T0) ? 0 : 1);
410  break;
411 
412  case SCARD_PROTOCOL_RAW:
413  Log1(PCSC_LOG_DEBUG, "Active Protocol: RAW");
414  break;
415 
416  default:
417  Log2(PCSC_LOG_ERROR, "Active Protocol: unknown %ld",
418  *pdwActiveProtocol);
419  }
420  }
421  else
422  Log1(PCSC_LOG_DEBUG, "Direct access: no protocol selected");
423 
424  /*
425  * Prepare the SCARDHANDLE identity
426  */
427  *phCard = RFCreateReaderHandle(rContext);
428 
429  Log2(PCSC_LOG_DEBUG, "hCard Identity: %lx", *phCard);
430 
431  /*******************************************
432  *
433  * This section tries to set up the
434  * exclusivity modes. -1 is exclusive
435  *
436  *******************************************/
437 
438  if (dwShareMode == SCARD_SHARE_EXCLUSIVE)
439  {
440  if (rContext->contexts == PCSCLITE_SHARING_NO_CONTEXT)
441  {
443  (void)RFLockSharing(*phCard, rContext);
444  }
445  else
446  {
447  (void)RFDestroyReaderHandle(*phCard);
448  *phCard = 0;
450  goto exit;
451  }
452  }
453  else
454  {
455  /*
456  * Add a connection to the context stack
457  */
458  rContext->contexts += 1;
459  }
460 
461  /*
462  * Add this handle to the handle list
463  */
464  rv = RFAddReaderHandle(rContext, *phCard);
465 
466  if (rv != SCARD_S_SUCCESS)
467  {
468  /*
469  * Clean up - there is no more room
470  */
471  (void)RFDestroyReaderHandle(*phCard);
474  else
475  if (rContext->contexts > PCSCLITE_SHARING_NO_CONTEXT)
476  rContext->contexts -= 1;
477 
478  *phCard = 0;
479 
481  goto exit;
482  }
483 
484  /*
485  * Propagate new state to reader state
486  */
487  rContext->readerState->readerSharing = rContext->contexts;
488 
489 exit:
490  UNREF_READER(rContext)
491 
492  PROFILE_END
493 
494  return rv;
495 }
496 
497 LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
498  DWORD dwPreferredProtocols, DWORD dwInitialization,
499  LPDWORD pdwActiveProtocol)
500 {
501  LONG rv;
502  READER_CONTEXT * rContext = NULL;
503 
504  Log1(PCSC_LOG_DEBUG, "Attempting reconnect to token.");
505 
506  if (hCard == 0)
507  return SCARD_E_INVALID_HANDLE;
508 
509  /*
510  * Handle the dwInitialization
511  */
512  if (dwInitialization != SCARD_LEAVE_CARD &&
513  dwInitialization != SCARD_RESET_CARD &&
514  dwInitialization != SCARD_UNPOWER_CARD)
515  return SCARD_E_INVALID_VALUE;
516 
517  if (dwShareMode != SCARD_SHARE_SHARED &&
518  dwShareMode != SCARD_SHARE_EXCLUSIVE &&
519  dwShareMode != SCARD_SHARE_DIRECT)
520  return SCARD_E_INVALID_VALUE;
521 
522  if ((dwShareMode != SCARD_SHARE_DIRECT) &&
523  !(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
524  !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
525  !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
526  !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
527  return SCARD_E_PROTO_MISMATCH;
528 
529  /* get rContext corresponding to hCard */
530  rv = RFReaderInfoById(hCard, &rContext);
531  if (rv != SCARD_S_SUCCESS)
532  return rv;
533 
534  /*
535  * Make sure the reader is working properly
536  */
537  rv = RFCheckReaderStatus(rContext);
538  if (rv != SCARD_S_SUCCESS)
539  goto exit;
540 
541  /*
542  * Make sure no one has a lock on this reader
543  */
544  rv = RFCheckSharing(hCard, rContext);
545  if (rv != SCARD_S_SUCCESS)
546  goto exit;
547 
548  if (dwInitialization == SCARD_RESET_CARD ||
549  dwInitialization == SCARD_UNPOWER_CARD)
550  {
551  DWORD dwAtrLen;
552 
553  /*
554  * Notify the card has been reset
555  */
556  (void)RFSetReaderEventState(rContext, SCARD_RESET);
557 
558  /*
559  * Currently pcsc-lite keeps the card powered constantly
560  */
561  dwAtrLen = sizeof(rContext->readerState->cardAtr);
562  if (SCARD_RESET_CARD == dwInitialization)
563  rv = IFDPowerICC(rContext, IFD_RESET,
564  rContext->readerState->cardAtr, &dwAtrLen);
565  else
566  {
567  IFDPowerICC(rContext, IFD_POWER_DOWN, NULL, NULL);
568  rv = IFDPowerICC(rContext, IFD_POWER_UP,
569  rContext->readerState->cardAtr, &dwAtrLen);
570  }
571  rContext->readerState->cardAtrLength = dwAtrLen;
572 
573  /* the protocol is unset after a power on */
575 
576  /*
577  * Set up the status bit masks on readerState
578  */
579  if (rv == SCARD_S_SUCCESS)
580  {
581  rContext->readerState->cardAtrLength = dwAtrLen;
582  rContext->readerState->readerState =
584 
585  Log1(PCSC_LOG_DEBUG, "Reset complete.");
586  LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
587  rContext->readerState->cardAtr,
588  rContext->readerState->cardAtrLength);
589  }
590  else
591  {
592  rContext->readerState->cardAtrLength = 0;
593  Log1(PCSC_LOG_ERROR, "Error resetting card.");
594 
595  if (rv == SCARD_W_REMOVED_CARD)
596  {
597  rContext->readerState->readerState = SCARD_ABSENT;
599  goto exit;
600  }
601  else
602  {
603  rContext->readerState->readerState =
606  goto exit;
607  }
608  }
609  }
610  else
611  if (dwInitialization == SCARD_LEAVE_CARD)
612  {
613  uint32_t readerState = rContext->readerState->readerState;
614 
615  if (readerState & SCARD_ABSENT)
616  {
618  goto exit;
619  }
620 
621  if ((readerState & SCARD_PRESENT)
622  && (readerState & SCARD_SWALLOWED))
623  {
625  goto exit;
626  }
627  }
628 
629  /*******************************************
630  *
631  * This section tries to decode the ATR
632  * and set up which protocol to use
633  *
634  *******************************************/
635  if (dwPreferredProtocols & SCARD_PROTOCOL_RAW)
637  else
638  {
639  if (dwShareMode != SCARD_SHARE_DIRECT)
640  {
641  /* lock here instead in IFDSetPTS() to lock up to
642  * setting rContext->readerState->cardProtocol */
643  (void)pthread_mutex_lock(rContext->mMutex);
644 
645  /* the protocol is not yet set (no PPS yet) */
647  {
648  int availableProtocols, defaultProtocol;
649  int ret;
650 
651  ATRDecodeAtr(&availableProtocols, &defaultProtocol,
652  rContext->readerState->cardAtr,
653  rContext->readerState->cardAtrLength);
654 
655  /* If it is set to ANY let it do any of the protocols */
656  if (dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)
657  dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
658 
659  ret = PHSetProtocol(rContext, dwPreferredProtocols,
660  availableProtocols, defaultProtocol);
661 
662  /* keep cardProtocol = SCARD_PROTOCOL_UNDEFINED in case of error */
663  if (SET_PROTOCOL_PPS_FAILED == ret)
664  {
665  (void)pthread_mutex_unlock(rContext->mMutex);
667  goto exit;
668  }
669 
670  if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
671  {
672  (void)pthread_mutex_unlock(rContext->mMutex);
674  goto exit;
675  }
676 
677  /* use negotiated protocol */
678  rContext->readerState->cardProtocol = ret;
679 
680  (void)pthread_mutex_unlock(rContext->mMutex);
681  }
682  else
683  {
684  (void)pthread_mutex_unlock(rContext->mMutex);
685 
686  if (! (dwPreferredProtocols & rContext->readerState->cardProtocol))
687  {
689  goto exit;
690  }
691  }
692  }
693  }
694 
695  *pdwActiveProtocol = rContext->readerState->cardProtocol;
696 
697  if (dwShareMode != SCARD_SHARE_DIRECT)
698  {
699  switch (*pdwActiveProtocol)
700  {
701  case SCARD_PROTOCOL_T0:
702  case SCARD_PROTOCOL_T1:
703  Log2(PCSC_LOG_DEBUG, "Active Protocol: T=%d",
704  (*pdwActiveProtocol == SCARD_PROTOCOL_T0) ? 0 : 1);
705  break;
706 
707  case SCARD_PROTOCOL_RAW:
708  Log1(PCSC_LOG_DEBUG, "Active Protocol: RAW");
709  break;
710 
711  default:
712  Log2(PCSC_LOG_ERROR, "Active Protocol: unknown %ld",
713  *pdwActiveProtocol);
714  }
715  }
716  else
717  Log1(PCSC_LOG_DEBUG, "Direct access: no protocol selected");
718 
719  if (dwShareMode == SCARD_SHARE_EXCLUSIVE)
720  {
722  {
723  /*
724  * Do nothing - we are already exclusive
725  */
726  }
727  else
728  {
729  if (rContext->contexts == PCSCLITE_SHARING_LAST_CONTEXT)
730  {
732  (void)RFLockSharing(hCard, rContext);
733  }
734  else
735  {
737  goto exit;
738  }
739  }
740  }
741  else if (dwShareMode == SCARD_SHARE_SHARED)
742  {
744  {
745  /*
746  * Do nothing - in sharing mode already
747  */
748  }
749  else
750  {
751  /*
752  * We are in exclusive mode but want to share now
753  */
754  (void)RFUnlockSharing(hCard, rContext);
756  }
757  }
758  else if (dwShareMode == SCARD_SHARE_DIRECT)
759  {
761  {
762  /*
763  * Do nothing - in sharing mode already
764  */
765  }
766  else
767  {
768  /*
769  * We are in exclusive mode but want to share now
770  */
771  (void)RFUnlockSharing(hCard, rContext);
773  }
774  }
775  else
776  {
778  goto exit;
779  }
780 
781  /*
782  * Clear a previous event to the application
783  */
784  (void)RFClearReaderEventState(rContext, hCard);
785 
786  /*
787  * Propagate new state to reader state
788  */
789  rContext->readerState->readerSharing = rContext->contexts;
790 
791  rv = SCARD_S_SUCCESS;
792 
793 exit:
794  UNREF_READER(rContext)
795 
796  return rv;
797 }
798 
799 LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
800 {
801  LONG rv;
802  READER_CONTEXT * rContext = NULL;
803 
804  if (hCard == 0)
805  return SCARD_E_INVALID_HANDLE;
806 
807  if ((dwDisposition != SCARD_LEAVE_CARD)
808  && (dwDisposition != SCARD_UNPOWER_CARD)
809  && (dwDisposition != SCARD_RESET_CARD)
810  && (dwDisposition != SCARD_EJECT_CARD))
811  return SCARD_E_INVALID_VALUE;
812 
813  /* get rContext corresponding to hCard */
814  rv = RFReaderInfoById(hCard, &rContext);
815  if (rv != SCARD_S_SUCCESS)
816  return rv;
817 
818  /*
819  * wait until a possible transaction is finished
820  */
821  if ((dwDisposition != SCARD_LEAVE_CARD) && (rContext->hLockId != 0)
822  && (rContext->hLockId != hCard))
823  {
824  Log1(PCSC_LOG_INFO, "Waiting for release of lock");
825  while (rContext->hLockId != 0)
827  Log1(PCSC_LOG_INFO, "Lock released");
828  }
829 
830  /*
831  * Try to unlock any blocks on this context
832  *
833  * This may fail with SCARD_E_SHARING_VIOLATION if a transaction is
834  * on going on another card context and dwDisposition == SCARD_LEAVE_CARD.
835  * We should not stop.
836  */
837  rv = RFUnlockAllSharing(hCard, rContext);
838  if (rv != SCARD_S_SUCCESS)
839  {
840  if (rv != SCARD_E_SHARING_VIOLATION)
841  {
842  goto exit;
843  }
844  else
845  {
846  if (SCARD_LEAVE_CARD != dwDisposition)
847  goto exit;
848  }
849  }
850 
851  Log2(PCSC_LOG_DEBUG, "Active Contexts: %d", rContext->contexts);
852  Log2(PCSC_LOG_DEBUG, "dwDisposition: %ld", dwDisposition);
853 
854  if (dwDisposition == SCARD_RESET_CARD ||
855  dwDisposition == SCARD_UNPOWER_CARD)
856  {
857  DWORD dwAtrLen;
858 
859  /*
860  * Notify the card has been reset
861  */
862  (void)RFSetReaderEventState(rContext, SCARD_RESET);
863 
864  /*
865  * Currently pcsc-lite keeps the card powered constantly
866  * unless DISABLE_AUTO_POWER_ON is defined
867  */
868  dwAtrLen = sizeof(rContext->readerState->cardAtr);
869  if (SCARD_RESET_CARD == dwDisposition)
870  rv = IFDPowerICC(rContext, IFD_RESET,
871  rContext->readerState->cardAtr, &dwAtrLen);
872  else
873  {
874  IFDPowerICC(rContext, IFD_POWER_DOWN, NULL, NULL);
875 
876 #ifdef DISABLE_AUTO_POWER_ON
877  rContext->powerState = POWER_STATE_UNPOWERED;
878  Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_UNPOWERED");
879 #else
880  rv = IFDPowerICC(rContext, IFD_POWER_UP,
881  rContext->readerState->cardAtr, &dwAtrLen);
882 #endif
883  }
884 
885  /* the protocol is unset after a power on */
887 
888 #ifdef DISABLE_AUTO_POWER_ON
889  if (SCARD_UNPOWER_CARD == dwDisposition)
890  {
891  rContext->readerState->cardAtrLength = 0;
892  if (rv == SCARD_S_SUCCESS)
894  else
895  {
896  Log3(PCSC_LOG_ERROR, "Error powering down card: %d 0x%04X",
897  rv, rv);
898  if (rv == SCARD_W_REMOVED_CARD)
899  rContext->readerState->readerState = SCARD_ABSENT;
900  else
901  rContext->readerState->readerState =
903  }
904  Log1(PCSC_LOG_INFO, "Skip card power on");
905  }
906  else
907 #endif
908  {
909  /*
910  * Set up the status bit masks on readerState
911  */
912  if (rv == SCARD_S_SUCCESS)
913  {
914  rContext->readerState->cardAtrLength = dwAtrLen;
915  rContext->readerState->readerState =
917 
918  Log1(PCSC_LOG_DEBUG, "Reset complete.");
919  LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
920  rContext->readerState->cardAtr,
921  rContext->readerState->cardAtrLength);
922  }
923  else
924  {
925  rContext->readerState->cardAtrLength = 0;
926  Log1(PCSC_LOG_ERROR, "Error resetting card.");
927 
928  if (rv == SCARD_W_REMOVED_CARD)
929  rContext->readerState->readerState = SCARD_ABSENT;
930  else
931  rContext->readerState->readerState =
933  }
934  }
935  }
936  else if (dwDisposition == SCARD_EJECT_CARD)
937  {
938  UCHAR controlBuffer[5];
939  UCHAR receiveBuffer[MAX_BUFFER_SIZE];
940  DWORD receiveLength;
941 
942  /*
943  * Set up the CTBCS command for Eject ICC
944  */
945  controlBuffer[0] = 0x20;
946  controlBuffer[1] = 0x15;
947  controlBuffer[2] = (rContext->slot & 0x0000FFFF) + 1;
948  controlBuffer[3] = 0x00;
949  controlBuffer[4] = 0x00;
950  receiveLength = 2;
951  rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
952  &receiveLength);
953 
954  if (rv == SCARD_S_SUCCESS)
955  {
956  if (receiveLength == 2 && receiveBuffer[0] == 0x90)
957  {
958  Log1(PCSC_LOG_DEBUG, "Card ejected successfully.");
959  /*
960  * Successful
961  */
962  }
963  else
964  Log1(PCSC_LOG_ERROR, "Error ejecting card.");
965  }
966  else
967  Log1(PCSC_LOG_ERROR, "Error ejecting card.");
968 
969  }
970  else if (dwDisposition == SCARD_LEAVE_CARD)
971  {
972  /*
973  * Do nothing
974  */
975  }
976 
977  /*
978  * Remove and destroy this handle
979  */
980  (void)RFRemoveReaderHandle(rContext, hCard);
981  (void)RFDestroyReaderHandle(hCard);
982 
983  /*
984  * For exclusive connection reset it to no connections
985  */
988  else
989  {
990  /*
991  * Remove a connection from the context stack
992  */
993  rContext->contexts -= 1;
994 
995  if (rContext->contexts < 0)
996  rContext->contexts = 0;
997  }
998 
999  if (PCSCLITE_SHARING_NO_CONTEXT == rContext->contexts)
1000  {
1001  RESPONSECODE (*fct)(DWORD) = NULL;
1002  DWORD dwGetSize;
1003 
1004  (void)pthread_mutex_lock(&rContext->powerState_lock);
1005  /* Switch to POWER_STATE_GRACE_PERIOD unless the card was not
1006  * powered */
1007  if (POWER_STATE_POWERED <= rContext->powerState)
1008  {
1009 #ifdef DISABLE_AUTO_POWER_ON
1010  if (SCARD_RESET_CARD == dwDisposition)
1011  {
1013  Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_GRACE_PERIOD");
1014  }
1015 #else
1017  Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_GRACE_PERIOD");
1018 #endif
1019  }
1020 
1021  (void)pthread_mutex_unlock(&rContext->powerState_lock);
1022 
1023  /* ask to stop the "polling" thread so it can be restarted using
1024  * the correct timeout */
1025  dwGetSize = sizeof(fct);
1027  &dwGetSize, (PUCHAR)&fct);
1028 
1029  if ((IFD_SUCCESS == rv) && (dwGetSize == sizeof(fct)))
1030  {
1031  Log1(PCSC_LOG_INFO, "Stopping polling thread");
1032  fct(rContext->slot);
1033  }
1034  }
1035 
1036  /*
1037  * Propagate new state to reader state
1038  */
1039  rContext->readerState->readerSharing = rContext->contexts;
1040 
1041  rv = SCARD_S_SUCCESS;
1042 
1043 exit:
1044  UNREF_READER(rContext)
1045 
1046  return rv;
1047 }
1048 
1050 {
1051  LONG rv;
1052  READER_CONTEXT * rContext;
1053 
1054  if (hCard == 0)
1055  return SCARD_E_INVALID_HANDLE;
1056 
1057  /* get rContext corresponding to hCard */
1058  rv = RFReaderInfoById(hCard, &rContext);
1059  if (rv != SCARD_S_SUCCESS)
1060  return rv;
1061 
1062  /*
1063  * Make sure the reader is working properly
1064  */
1065  rv = RFCheckReaderStatus(rContext);
1066  if (rv != SCARD_S_SUCCESS)
1067  goto exit;
1068 
1069  /*
1070  * Make sure some event has not occurred
1071  */
1072  rv = RFCheckReaderEventState(rContext, hCard);
1073  if (rv != SCARD_S_SUCCESS)
1074  goto exit;
1075 
1076  rv = RFLockSharing(hCard, rContext);
1077 
1078  /* if the transaction is not yet ready we sleep a bit so the client
1079  * do not retry immediately */
1080  if (SCARD_E_SHARING_VIOLATION == rv)
1082 
1083  Log2(PCSC_LOG_DEBUG, "Status: 0x%08lX", rv);
1084 
1085 exit:
1086  UNREF_READER(rContext)
1087 
1088  return rv;
1089 }
1090 
1091 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
1092 {
1093  LONG rv;
1094  READER_CONTEXT * rContext = NULL;
1095 
1096  /*
1097  * Ignoring dwDisposition for now
1098  */
1099  if (hCard == 0)
1100  return SCARD_E_INVALID_HANDLE;
1101 
1102  if ((dwDisposition != SCARD_LEAVE_CARD)
1103  && (dwDisposition != SCARD_UNPOWER_CARD)
1104  && (dwDisposition != SCARD_RESET_CARD)
1105  && (dwDisposition != SCARD_EJECT_CARD))
1106  return SCARD_E_INVALID_VALUE;
1107 
1108  /* get rContext corresponding to hCard */
1109  rv = RFReaderInfoById(hCard, &rContext);
1110  if (rv != SCARD_S_SUCCESS)
1111  return rv;
1112 
1113  /*
1114  * Make sure some event has not occurred
1115  */
1116  rv = RFCheckReaderEventState(rContext, hCard);
1117  if (rv != SCARD_S_SUCCESS)
1118  goto exit;
1119 
1120  if (dwDisposition == SCARD_RESET_CARD ||
1121  dwDisposition == SCARD_UNPOWER_CARD)
1122  {
1123  DWORD dwAtrLen;
1124 
1125  /*
1126  * Currently pcsc-lite keeps the card always powered
1127  */
1128  dwAtrLen = sizeof(rContext->readerState->cardAtr);
1129  if (SCARD_RESET_CARD == dwDisposition)
1130  rv = IFDPowerICC(rContext, IFD_RESET,
1131  rContext->readerState->cardAtr, &dwAtrLen);
1132  else
1133  {
1134  IFDPowerICC(rContext, IFD_POWER_DOWN, NULL, NULL);
1135  rv = IFDPowerICC(rContext, IFD_POWER_UP,
1136  rContext->readerState->cardAtr, &dwAtrLen);
1137  }
1138 
1139  /* the protocol is unset after a power on */
1141 
1142  /*
1143  * Notify the card has been reset
1144  */
1145  (void)RFSetReaderEventState(rContext, SCARD_RESET);
1146 
1147  /*
1148  * Set up the status bit masks on readerState
1149  */
1150  if (rv == SCARD_S_SUCCESS)
1151  {
1152  rContext->readerState->cardAtrLength = dwAtrLen;
1153  rContext->readerState->readerState =
1155 
1156  Log1(PCSC_LOG_DEBUG, "Reset complete.");
1157  LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
1158  rContext->readerState->cardAtr,
1159  rContext->readerState->cardAtrLength);
1160  }
1161  else
1162  {
1163  rContext->readerState->cardAtrLength = 0;
1164  Log1(PCSC_LOG_ERROR, "Error resetting card.");
1165 
1166  if (rv == SCARD_W_REMOVED_CARD)
1167  rContext->readerState->readerState = SCARD_ABSENT;
1168  else
1169  rContext->readerState->readerState =
1171  }
1172  }
1173  else if (dwDisposition == SCARD_EJECT_CARD)
1174  {
1175  UCHAR controlBuffer[5];
1176  UCHAR receiveBuffer[MAX_BUFFER_SIZE];
1177  DWORD receiveLength;
1178 
1179  /*
1180  * Set up the CTBCS command for Eject ICC
1181  */
1182  controlBuffer[0] = 0x20;
1183  controlBuffer[1] = 0x15;
1184  controlBuffer[2] = (rContext->slot & 0x0000FFFF) + 1;
1185  controlBuffer[3] = 0x00;
1186  controlBuffer[4] = 0x00;
1187  receiveLength = 2;
1188  rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
1189  &receiveLength);
1190 
1191  if (rv == SCARD_S_SUCCESS)
1192  {
1193  if (receiveLength == 2 && receiveBuffer[0] == 0x90)
1194  {
1195  Log1(PCSC_LOG_DEBUG, "Card ejected successfully.");
1196  /*
1197  * Successful
1198  */
1199  }
1200  else
1201  Log1(PCSC_LOG_ERROR, "Error ejecting card.");
1202  }
1203  else
1204  Log1(PCSC_LOG_ERROR, "Error ejecting card.");
1205 
1206  }
1207  else if (dwDisposition == SCARD_LEAVE_CARD)
1208  {
1209  /*
1210  * Do nothing
1211  */
1212  }
1213 
1214  /*
1215  * Unlock any blocks on this context
1216  */
1217  (void)RFUnlockSharing(hCard, rContext);
1218 
1219  Log2(PCSC_LOG_DEBUG, "Status: 0x%08lX", rv);
1220 
1221 exit:
1222  UNREF_READER(rContext)
1223 
1224  return rv;
1225 }
1226 
1227 LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderNames,
1228  LPDWORD pcchReaderLen, LPDWORD pdwState,
1229  LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1230 {
1231  LONG rv;
1232  READER_CONTEXT * rContext = NULL;
1233 
1234  /* These parameters are not used by the client
1235  * Client side code uses readerStates[] instead */
1236  (void)mszReaderNames;
1237  (void)pcchReaderLen;
1238  (void)pdwState;
1239  (void)pdwProtocol;
1240  (void)pbAtr;
1241  (void)pcbAtrLen;
1242 
1243  if (hCard == 0)
1244  return SCARD_E_INVALID_HANDLE;
1245 
1246  /* get rContext corresponding to hCard */
1247  rv = RFReaderInfoById(hCard, &rContext);
1248  if (rv != SCARD_S_SUCCESS)
1249  return rv;
1250 
1251  /*
1252  * Make sure no one has a lock on this reader
1253  */
1254  rv = RFCheckSharing(hCard, rContext);
1255  if (rv != SCARD_S_SUCCESS)
1256  goto exit;
1257 
1258  if (rContext->readerState->cardAtrLength > MAX_ATR_SIZE)
1259  {
1261  goto exit;
1262  }
1263 
1264  /*
1265  * This is a client side function however the server maintains the
1266  * list of events between applications so it must be passed through to
1267  * obtain this event if it has occurred
1268  */
1269 
1270  /*
1271  * Make sure some event has not occurred
1272  */
1273  rv = RFCheckReaderEventState(rContext, hCard);
1274  if (rv != SCARD_S_SUCCESS)
1275  goto exit;
1276 
1277  /*
1278  * Make sure the reader is working properly
1279  */
1280  rv = RFCheckReaderStatus(rContext);
1281  if (rv != SCARD_S_SUCCESS)
1282  goto exit;
1283 
1284 exit:
1285  UNREF_READER(rContext)
1286 
1287  return rv;
1288 }
1289 
1290 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode,
1291  LPCVOID pbSendBuffer, DWORD cbSendLength,
1292  LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned)
1293 {
1294  LONG rv;
1295  READER_CONTEXT * rContext = NULL;
1296 
1297  /* 0 bytes returned by default */
1298  *lpBytesReturned = 0;
1299 
1300  if (0 == hCard)
1301  return SCARD_E_INVALID_HANDLE;
1302 
1303  /* get rContext corresponding to hCard */
1304  rv = RFReaderInfoById(hCard, &rContext);
1305  if (rv != SCARD_S_SUCCESS)
1306  return rv;
1307 
1308  /*
1309  * Make sure no one has a lock on this reader
1310  */
1311  rv = RFCheckSharing(hCard, rContext);
1312  if (rv != SCARD_S_SUCCESS)
1313  goto exit;
1314 
1315  if (IFD_HVERSION_2_0 == rContext->version)
1316  if (NULL == pbSendBuffer || 0 == cbSendLength)
1317  {
1319  goto exit;
1320  }
1321 
1322  /*
1323  * Make sure the reader is working properly
1324  */
1325  rv = RFCheckReaderStatus(rContext);
1326  if (rv != SCARD_S_SUCCESS)
1327  goto exit;
1328 
1329  if (IFD_HVERSION_2_0 == rContext->version)
1330  {
1331  /* we must wrap a API 3.0 client in an API 2.0 driver */
1332  *lpBytesReturned = cbRecvLength;
1333  rv = IFDControl_v2(rContext, (PUCHAR)pbSendBuffer,
1334  cbSendLength, pbRecvBuffer, lpBytesReturned);
1335  }
1336  else
1337  if (IFD_HVERSION_3_0 == rContext->version)
1338  rv = IFDControl(rContext, dwControlCode, pbSendBuffer,
1339  cbSendLength, pbRecvBuffer, cbRecvLength, lpBytesReturned);
1340  else
1342 
1343 exit:
1344  UNREF_READER(rContext)
1345 
1346  return rv;
1347 }
1348 
1349 LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
1350  LPBYTE pbAttr, LPDWORD pcbAttrLen)
1351 {
1352  LONG rv;
1353  READER_CONTEXT * rContext = NULL;
1354 
1355  if (0 == hCard)
1356  return SCARD_E_INVALID_HANDLE;
1357 
1358  /* get rContext corresponding to hCard */
1359  rv = RFReaderInfoById(hCard, &rContext);
1360  if (rv != SCARD_S_SUCCESS)
1361  return rv;
1362 
1363  /*
1364  * Make sure no one has a lock on this reader
1365  */
1366  rv = RFCheckSharing(hCard, rContext);
1367  if (rv != SCARD_S_SUCCESS)
1368  goto exit;
1369 
1370  /*
1371  * Make sure the reader is working properly
1372  */
1373  rv = RFCheckReaderStatus(rContext);
1374  if (rv != SCARD_S_SUCCESS)
1375  goto exit;
1376 
1377  /*
1378  * Make sure some event has not occurred
1379  */
1380  rv = RFCheckReaderEventState(rContext, hCard);
1381  if (rv != SCARD_S_SUCCESS)
1382  goto exit;
1383 
1384  rv = IFDGetCapabilities(rContext, dwAttrId, pcbAttrLen, pbAttr);
1385  switch(rv)
1386  {
1387  case IFD_SUCCESS:
1388  rv = SCARD_S_SUCCESS;
1389  break;
1390  case IFD_ERROR_TAG:
1391  /* Special case SCARD_ATTR_DEVICE_FRIENDLY_NAME as it is better
1392  * implemented in pcscd (it knows the friendly name)
1393  */
1394  if (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME)
1395  {
1396  unsigned int len = strlen(rContext->readerState->readerName)+1;
1397 
1398  *pcbAttrLen = len;
1399  if (len > *pcbAttrLen)
1401  else
1402  {
1403  (void)strlcpy((char *)pbAttr,
1404  rContext->readerState->readerName, *pcbAttrLen);
1405  rv = SCARD_S_SUCCESS;
1406  }
1407 
1408  }
1409  else
1411  break;
1414  break;
1415  default:
1417  }
1418 
1419 exit:
1420  UNREF_READER(rContext)
1421 
1422  return rv;
1423 }
1424 
1425 LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
1426  LPCBYTE pbAttr, DWORD cbAttrLen)
1427 {
1428  LONG rv;
1429  READER_CONTEXT * rContext = NULL;
1430 
1431  if (0 == hCard)
1432  return SCARD_E_INVALID_HANDLE;
1433 
1434  /* get rContext corresponding to hCard */
1435  rv = RFReaderInfoById(hCard, &rContext);
1436  if (rv != SCARD_S_SUCCESS)
1437  return rv;
1438 
1439  /*
1440  * Make sure no one has a lock on this reader
1441  */
1442  rv = RFCheckSharing(hCard, rContext);
1443  if (rv != SCARD_S_SUCCESS)
1444  goto exit;
1445 
1446  /*
1447  * Make sure the reader is working properly
1448  */
1449  rv = RFCheckReaderStatus(rContext);
1450  if (rv != SCARD_S_SUCCESS)
1451  goto exit;
1452 
1453  /*
1454  * Make sure some event has not occurred
1455  */
1456  rv = RFCheckReaderEventState(rContext, hCard);
1457  if (rv != SCARD_S_SUCCESS)
1458  goto exit;
1459 
1460  rv = IFDSetCapabilities(rContext, dwAttrId, cbAttrLen, (PUCHAR)pbAttr);
1461  if (rv == IFD_SUCCESS)
1462  rv = SCARD_S_SUCCESS;
1463  else
1464  if (rv == IFD_ERROR_TAG)
1466  else
1468 
1469 exit:
1470  UNREF_READER(rContext)
1471 
1472  return rv;
1473 }
1474 
1475 LONG SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
1476  LPCBYTE pbSendBuffer, DWORD cbSendLength,
1477  SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer,
1478  LPDWORD pcbRecvLength)
1479 {
1480  LONG rv;
1481  READER_CONTEXT * rContext = NULL;
1482  SCARD_IO_HEADER sSendPci, sRecvPci;
1483  DWORD dwRxLength, tempRxLength;
1484 
1485  dwRxLength = *pcbRecvLength;
1486  *pcbRecvLength = 0;
1487 
1488  if (hCard == 0)
1489  return SCARD_E_INVALID_HANDLE;
1490 
1491  /*
1492  * Must at least have 2 status words even for SCardControl
1493  */
1494  if (dwRxLength < 2)
1496 
1497  /* get rContext corresponding to hCard */
1498  rv = RFReaderInfoById(hCard, &rContext);
1499  if (rv != SCARD_S_SUCCESS)
1500  return rv;
1501 
1502  /*
1503  * Make sure no one has a lock on this reader
1504  */
1505  rv = RFCheckSharing(hCard, rContext);
1506  if (rv != SCARD_S_SUCCESS)
1507  goto exit;
1508 
1509  /*
1510  * Make sure the reader is working properly
1511  */
1512  rv = RFCheckReaderStatus(rContext);
1513  if (rv != SCARD_S_SUCCESS)
1514  goto exit;
1515 
1516  /*
1517  * Make sure some event has not occurred
1518  */
1519  rv = RFCheckReaderEventState(rContext, hCard);
1520  if (rv != SCARD_S_SUCCESS)
1521  goto exit;
1522 
1523  /*
1524  * Check for some common errors
1525  */
1526  if (pioSendPci->dwProtocol != SCARD_PROTOCOL_RAW)
1527  {
1528  if (rContext->readerState->readerState & SCARD_ABSENT)
1529  {
1530  rv = SCARD_E_NO_SMARTCARD;
1531  goto exit;
1532  }
1533  }
1534 
1535  if (pioSendPci->dwProtocol != SCARD_PROTOCOL_RAW)
1536  {
1537  if (pioSendPci->dwProtocol != SCARD_PROTOCOL_ANY_OLD)
1538  {
1539  if (pioSendPci->dwProtocol != rContext->readerState->cardProtocol)
1540  {
1542  goto exit;
1543  }
1544  }
1545  }
1546 
1547  /*
1548  * Quick fix: PC/SC starts at 1 for bit masking but the IFD_Handler
1549  * just wants 0 or 1
1550  */
1551 
1552  sSendPci.Protocol = 0; /* protocol T=0 by default */
1553 
1554  if (pioSendPci->dwProtocol == SCARD_PROTOCOL_T1)
1555  {
1556  sSendPci.Protocol = 1;
1557  } else if (pioSendPci->dwProtocol == SCARD_PROTOCOL_RAW)
1558  {
1559  /*
1560  * This is temporary ......
1561  */
1562  sSendPci.Protocol = SCARD_PROTOCOL_RAW;
1563  } else if (pioSendPci->dwProtocol == SCARD_PROTOCOL_ANY_OLD)
1564  {
1565  /* Fix by Amira (Athena) */
1566  unsigned long i;
1567  unsigned long prot = rContext->readerState->cardProtocol;
1568 
1569  for (i = 0 ; prot != 1 ; i++)
1570  prot >>= 1;
1571 
1572  sSendPci.Protocol = i;
1573  }
1574 
1575  sSendPci.Length = pioSendPci->cbPciLength;
1576 
1577  sRecvPci.Protocol = pioRecvPci->dwProtocol;
1578  sRecvPci.Length = pioRecvPci->cbPciLength;
1579 
1580  /* the protocol number is decoded a few lines above */
1581  Log2(PCSC_LOG_DEBUG, "Send Protocol: T=%ld", sSendPci.Protocol);
1582 
1583  tempRxLength = dwRxLength;
1584 
1585  if ((pioSendPci->dwProtocol == SCARD_PROTOCOL_RAW)
1586  && (rContext->version == IFD_HVERSION_2_0))
1587  {
1588  rv = IFDControl_v2(rContext, (PUCHAR) pbSendBuffer, cbSendLength,
1589  pbRecvBuffer, &dwRxLength);
1590  } else
1591  {
1592  rv = IFDTransmit(rContext, sSendPci, (PUCHAR) pbSendBuffer,
1593  cbSendLength, pbRecvBuffer, &dwRxLength, &sRecvPci);
1594  }
1595 
1596  pioRecvPci->dwProtocol = sRecvPci.Protocol;
1597  pioRecvPci->cbPciLength = sRecvPci.Length;
1598 
1599  /*
1600  * Check for any errors that might have occurred
1601  */
1602 
1603  if (rv != SCARD_S_SUCCESS)
1604  {
1605  *pcbRecvLength = 0;
1606  Log2(PCSC_LOG_ERROR, "Card not transacted: 0x%08lX", rv);
1607  goto exit;
1608  }
1609 
1610  /*
1611  * Available is less than received
1612  */
1613  if (tempRxLength < dwRxLength)
1614  {
1615  *pcbRecvLength = 0;
1617  goto exit;
1618  }
1619 
1620  /*
1621  * Successful return
1622  */
1623  *pcbRecvLength = dwRxLength;
1624 
1625 exit:
1626  UNREF_READER(rContext)
1627 
1628  return rv;
1629 }
1630