pcsc-lite  1.8.3
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 5962 2011-09-24 08:24:34Z 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 = (PCSCLITE_SVC_IDENTITY + SYS_RandomInt(1, 65535));
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 
239  if (rv != SCARD_S_SUCCESS)
240  {
241  Log2(PCSC_LOG_ERROR, "Reader %s Not Found", szReader);
242  return rv;
243  }
244 
245  /*
246  * Make sure the reader is working properly
247  */
248  rv = RFCheckReaderStatus(rContext);
249  if (rv != SCARD_S_SUCCESS)
250  return rv;
251 
252  /*******************************************
253  *
254  * This section checks for simple errors
255  *
256  *******************************************/
257 
258  /*
259  * Connect if not exclusive mode
260  */
262  {
263  Log1(PCSC_LOG_ERROR, "Error Reader Exclusive");
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");
291  return SCARD_E_NO_SMARTCARD;
292  }
293 
294  /* Power on (again) the card if needed */
295  (void)pthread_mutex_lock(&rContext->powerState_lock);
296  if (POWER_STATE_UNPOWERED == rContext->powerState)
297  {
298  DWORD dwAtrLen;
299 
300  dwAtrLen = sizeof(rContext->readerState->cardAtr);
301  rv = IFDPowerICC(rContext, IFD_POWER_UP,
302  rContext->readerState->cardAtr, &dwAtrLen);
303  rContext->readerState->cardAtrLength = dwAtrLen;
304 
305  if (rv == IFD_SUCCESS)
306  {
307  readerState = SCARD_PRESENT | SCARD_POWERED | SCARD_NEGOTIABLE;
308 
309  Log1(PCSC_LOG_DEBUG, "power up complete.");
310  LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
311  rContext->readerState->cardAtr,
312  rContext->readerState->cardAtrLength);
313  }
314  else
315  Log3(PCSC_LOG_ERROR, "Error powering up card: %ld 0x%04lX",
316  rv, rv);
317  }
318 
319  if (! (readerState & SCARD_POWERED))
320  {
321  Log1(PCSC_LOG_ERROR, "Card Not Powered");
322  (void)pthread_mutex_unlock(&rContext->powerState_lock);
323  return SCARD_W_UNPOWERED_CARD;
324  }
325 
326  /* the card is now in use */
327  rContext->powerState = POWER_STATE_INUSE;
328  Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_INUSE");
329  (void)pthread_mutex_unlock(&rContext->powerState_lock);
330  }
331 
332  /*******************************************
333  *
334  * This section tries to decode the ATR
335  * and set up which protocol to use
336  *
337  *******************************************/
338  if (dwPreferredProtocols & SCARD_PROTOCOL_RAW)
340  else
341  {
342  if (dwShareMode != SCARD_SHARE_DIRECT)
343  {
344  /* lock here instead in IFDSetPTS() to lock up to
345  * setting rContext->readerState->cardProtocol */
346  (void)pthread_mutex_lock(rContext->mMutex);
347 
348  /* the protocol is not yet set (no PPS yet) */
350  {
351  int availableProtocols, defaultProtocol;
352  int ret;
353 
354  ATRDecodeAtr(&availableProtocols, &defaultProtocol,
355  rContext->readerState->cardAtr,
356  rContext->readerState->cardAtrLength);
357 
358  /* If it is set to ANY let it do any of the protocols */
359  if (dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)
360  dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
361 
362  ret = PHSetProtocol(rContext, dwPreferredProtocols,
363  availableProtocols, defaultProtocol);
364 
365  /* keep cardProtocol = SCARD_PROTOCOL_UNDEFINED in case of error */
366  if (SET_PROTOCOL_PPS_FAILED == ret)
367  {
368  (void)pthread_mutex_unlock(rContext->mMutex);
370  }
371 
372  if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
373  {
374  (void)pthread_mutex_unlock(rContext->mMutex);
375  return SCARD_E_PROTO_MISMATCH;
376  }
377 
378  /* use negotiated protocol */
379  rContext->readerState->cardProtocol = ret;
380 
381  (void)pthread_mutex_unlock(rContext->mMutex);
382  }
383  else
384  {
385  (void)pthread_mutex_unlock(rContext->mMutex);
386 
387  if (! (dwPreferredProtocols & rContext->readerState->cardProtocol))
388  return SCARD_E_PROTO_MISMATCH;
389  }
390  }
391  }
392 
393  *pdwActiveProtocol = rContext->readerState->cardProtocol;
394 
395  if (dwShareMode != SCARD_SHARE_DIRECT)
396  {
397  switch (*pdwActiveProtocol)
398  {
399  case SCARD_PROTOCOL_T0:
400  case SCARD_PROTOCOL_T1:
401  Log2(PCSC_LOG_DEBUG, "Active Protocol: T=%d",
402  (*pdwActiveProtocol == SCARD_PROTOCOL_T0) ? 0 : 1);
403  break;
404 
405  case SCARD_PROTOCOL_RAW:
406  Log1(PCSC_LOG_DEBUG, "Active Protocol: RAW");
407  break;
408 
409  default:
410  Log2(PCSC_LOG_ERROR, "Active Protocol: unknown %ld",
411  *pdwActiveProtocol);
412  }
413  }
414  else
415  Log1(PCSC_LOG_DEBUG, "Direct access: no protocol selected");
416 
417  /*
418  * Prepare the SCARDHANDLE identity
419  */
420  *phCard = RFCreateReaderHandle(rContext);
421 
422  Log2(PCSC_LOG_DEBUG, "hCard Identity: %lx", *phCard);
423 
424  /*******************************************
425  *
426  * This section tries to set up the
427  * exclusivity modes. -1 is exclusive
428  *
429  *******************************************/
430 
431  if (dwShareMode == SCARD_SHARE_EXCLUSIVE)
432  {
433  if (rContext->contexts == PCSCLITE_SHARING_NO_CONTEXT)
434  {
436  (void)RFLockSharing(*phCard, rContext);
437  }
438  else
439  {
440  (void)RFDestroyReaderHandle(*phCard);
441  *phCard = 0;
443  }
444  }
445  else
446  {
447  /*
448  * Add a connection to the context stack
449  */
450  rContext->contexts += 1;
451  }
452 
453  /*
454  * Add this handle to the handle list
455  */
456  rv = RFAddReaderHandle(rContext, *phCard);
457 
458  if (rv != SCARD_S_SUCCESS)
459  {
460  /*
461  * Clean up - there is no more room
462  */
463  (void)RFDestroyReaderHandle(*phCard);
466  else
467  if (rContext->contexts > PCSCLITE_SHARING_NO_CONTEXT)
468  rContext->contexts -= 1;
469 
470  *phCard = 0;
471 
472  PROFILE_END
473 
474  return SCARD_F_INTERNAL_ERROR;
475  }
476 
477  /*
478  * Propagate new state to reader state
479  */
480  rContext->readerState->readerSharing = rContext->contexts;
481 
482  PROFILE_END
483 
484  return SCARD_S_SUCCESS;
485 }
486 
487 LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
488  DWORD dwPreferredProtocols, DWORD dwInitialization,
489  LPDWORD pdwActiveProtocol)
490 {
491  LONG rv;
492  READER_CONTEXT * rContext = NULL;
493 
494  Log1(PCSC_LOG_DEBUG, "Attempting reconnect to token.");
495 
496  if (hCard == 0)
497  return SCARD_E_INVALID_HANDLE;
498 
499  /*
500  * Handle the dwInitialization
501  */
502  if (dwInitialization != SCARD_LEAVE_CARD &&
503  dwInitialization != SCARD_RESET_CARD &&
504  dwInitialization != SCARD_UNPOWER_CARD)
505  return SCARD_E_INVALID_VALUE;
506 
507  if (dwShareMode != SCARD_SHARE_SHARED &&
508  dwShareMode != SCARD_SHARE_EXCLUSIVE &&
509  dwShareMode != SCARD_SHARE_DIRECT)
510  return SCARD_E_INVALID_VALUE;
511 
512  if ((dwShareMode != SCARD_SHARE_DIRECT) &&
513  !(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
514  !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
515  !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
516  !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
517  return SCARD_E_PROTO_MISMATCH;
518 
519  /* get rContext corresponding to hCard */
520  rv = RFReaderInfoById(hCard, &rContext);
521  if (rv != SCARD_S_SUCCESS)
522  return rv;
523 
524  /*
525  * Make sure the reader is working properly
526  */
527  rv = RFCheckReaderStatus(rContext);
528  if (rv != SCARD_S_SUCCESS)
529  return rv;
530 
531  rv = RFFindReaderHandle(hCard);
532  if (rv != SCARD_S_SUCCESS)
533  return rv;
534 
535  /*
536  * Make sure no one has a lock on this reader
537  */
538  rv = RFCheckSharing(hCard, rContext);
539  if (rv != SCARD_S_SUCCESS)
540  return rv;
541 
542  if (dwInitialization == SCARD_RESET_CARD ||
543  dwInitialization == SCARD_UNPOWER_CARD)
544  {
545  DWORD dwAtrLen;
546 
547  /*
548  * Notify the card has been reset
549  */
550  (void)RFSetReaderEventState(rContext, SCARD_RESET);
551 
552  /*
553  * Currently pcsc-lite keeps the card powered constantly
554  */
555  dwAtrLen = sizeof(rContext->readerState->cardAtr);
556  if (SCARD_RESET_CARD == dwInitialization)
557  rv = IFDPowerICC(rContext, IFD_RESET,
558  rContext->readerState->cardAtr, &dwAtrLen);
559  else
560  {
561  IFDPowerICC(rContext, IFD_POWER_DOWN, NULL, NULL);
562  rv = IFDPowerICC(rContext, IFD_POWER_UP,
563  rContext->readerState->cardAtr, &dwAtrLen);
564  }
565  rContext->readerState->cardAtrLength = dwAtrLen;
566 
567  /* the protocol is unset after a power on */
569 
570  /*
571  * Set up the status bit masks on readerState
572  */
573  if (rv == SCARD_S_SUCCESS)
574  {
575  rContext->readerState->cardAtrLength = dwAtrLen;
576  rContext->readerState->readerState =
578 
579  Log1(PCSC_LOG_DEBUG, "Reset complete.");
580  LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
581  rContext->readerState->cardAtr,
582  rContext->readerState->cardAtrLength);
583  }
584  else
585  {
586  rContext->readerState->cardAtrLength = 0;
587  Log1(PCSC_LOG_ERROR, "Error resetting card.");
588 
589  if (rv == SCARD_W_REMOVED_CARD)
590  {
591  rContext->readerState->readerState = SCARD_ABSENT;
592  return SCARD_E_NO_SMARTCARD;
593  }
594  else
595  {
596  rContext->readerState->readerState =
599  }
600  }
601  }
602  else
603  if (dwInitialization == SCARD_LEAVE_CARD)
604  {
605  uint32_t readerState = rContext->readerState->readerState;
606 
607  if (readerState & SCARD_ABSENT)
608  return SCARD_E_NO_SMARTCARD;
609 
610  if ((readerState & SCARD_PRESENT)
611  && (readerState & SCARD_SWALLOWED))
613  }
614 
615  /*******************************************
616  *
617  * This section tries to decode the ATR
618  * and set up which protocol to use
619  *
620  *******************************************/
621  if (dwPreferredProtocols & SCARD_PROTOCOL_RAW)
623  else
624  {
625  if (dwShareMode != SCARD_SHARE_DIRECT)
626  {
627  /* lock here instead in IFDSetPTS() to lock up to
628  * setting rContext->readerState->cardProtocol */
629  (void)pthread_mutex_lock(rContext->mMutex);
630 
631  /* the protocol is not yet set (no PPS yet) */
633  {
634  int availableProtocols, defaultProtocol;
635  int ret;
636 
637  ATRDecodeAtr(&availableProtocols, &defaultProtocol,
638  rContext->readerState->cardAtr,
639  rContext->readerState->cardAtrLength);
640 
641  /* If it is set to ANY let it do any of the protocols */
642  if (dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)
643  dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
644 
645  ret = PHSetProtocol(rContext, dwPreferredProtocols,
646  availableProtocols, defaultProtocol);
647 
648  /* keep cardProtocol = SCARD_PROTOCOL_UNDEFINED in case of error */
649  if (SET_PROTOCOL_PPS_FAILED == ret)
650  {
651  (void)pthread_mutex_unlock(rContext->mMutex);
653  }
654 
655  if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
656  {
657  (void)pthread_mutex_unlock(rContext->mMutex);
658  return SCARD_E_PROTO_MISMATCH;
659  }
660 
661  /* use negotiated protocol */
662  rContext->readerState->cardProtocol = ret;
663 
664  (void)pthread_mutex_unlock(rContext->mMutex);
665  }
666  else
667  {
668  (void)pthread_mutex_unlock(rContext->mMutex);
669 
670  if (! (dwPreferredProtocols & rContext->readerState->cardProtocol))
671  return SCARD_E_PROTO_MISMATCH;
672  }
673  }
674  }
675 
676  *pdwActiveProtocol = rContext->readerState->cardProtocol;
677 
678  if (dwShareMode != SCARD_SHARE_DIRECT)
679  {
680  switch (*pdwActiveProtocol)
681  {
682  case SCARD_PROTOCOL_T0:
683  case SCARD_PROTOCOL_T1:
684  Log2(PCSC_LOG_DEBUG, "Active Protocol: T=%d",
685  (*pdwActiveProtocol == SCARD_PROTOCOL_T0) ? 0 : 1);
686  break;
687 
688  case SCARD_PROTOCOL_RAW:
689  Log1(PCSC_LOG_DEBUG, "Active Protocol: RAW");
690  break;
691 
692  default:
693  Log2(PCSC_LOG_ERROR, "Active Protocol: unknown %ld",
694  *pdwActiveProtocol);
695  }
696  }
697  else
698  Log1(PCSC_LOG_DEBUG, "Direct access: no protocol selected");
699 
700  if (dwShareMode == SCARD_SHARE_EXCLUSIVE)
701  {
703  {
704  /*
705  * Do nothing - we are already exclusive
706  */
707  } else
708  {
709  if (rContext->contexts == PCSCLITE_SHARING_LAST_CONTEXT)
710  {
712  (void)RFLockSharing(hCard, rContext);
713  } else
714  {
716  }
717  }
718  } else if (dwShareMode == SCARD_SHARE_SHARED)
719  {
721  {
722  /*
723  * Do nothing - in sharing mode already
724  */
725  } else
726  {
727  /*
728  * We are in exclusive mode but want to share now
729  */
730  (void)RFUnlockSharing(hCard, rContext);
732  }
733  } else if (dwShareMode == SCARD_SHARE_DIRECT)
734  {
736  {
737  /*
738  * Do nothing - in sharing mode already
739  */
740  } else
741  {
742  /*
743  * We are in exclusive mode but want to share now
744  */
745  (void)RFUnlockSharing(hCard, rContext);
747  }
748  } else
749  return SCARD_E_INVALID_VALUE;
750 
751  /*
752  * Clear a previous event to the application
753  */
754  (void)RFClearReaderEventState(rContext, hCard);
755 
756  /*
757  * Propagate new state to reader state
758  */
759  rContext->readerState->readerSharing = rContext->contexts;
760 
761  return SCARD_S_SUCCESS;
762 }
763 
764 LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
765 {
766  LONG rv;
767  READER_CONTEXT * rContext = NULL;
768 
769  if (hCard == 0)
770  return SCARD_E_INVALID_HANDLE;
771 
772  /* get rContext corresponding to hCard */
773  rv = RFReaderInfoById(hCard, &rContext);
774  if (rv != SCARD_S_SUCCESS)
775  return rv;
776 
777  rv = RFFindReaderHandle(hCard);
778  if (rv != SCARD_S_SUCCESS)
779  return rv;
780 
781  if ((dwDisposition != SCARD_LEAVE_CARD)
782  && (dwDisposition != SCARD_UNPOWER_CARD)
783  && (dwDisposition != SCARD_RESET_CARD)
784  && (dwDisposition != SCARD_EJECT_CARD))
785  return SCARD_E_INVALID_VALUE;
786 
787  /*
788  * wait until a possible transaction is finished
789  */
790  if ((dwDisposition != SCARD_LEAVE_CARD) && (rContext->hLockId != 0)
791  && (rContext->hLockId != hCard))
792  {
793  Log1(PCSC_LOG_INFO, "Waiting for release of lock");
794  while (rContext->hLockId != 0)
796  Log1(PCSC_LOG_INFO, "Lock released");
797  }
798 
799  /*
800  * Try to unlock any blocks on this context
801  *
802  * This may fail with SCARD_E_SHARING_VIOLATION if a transaction is
803  * on going on another card context and dwDisposition == SCARD_LEAVE_CARD.
804  * We should not stop.
805  */
806  rv = RFUnlockAllSharing(hCard, rContext);
807  if (rv != SCARD_S_SUCCESS)
808  {
809  if (rv != SCARD_E_SHARING_VIOLATION)
810  {
811  return rv;
812  }
813  else
814  {
815  if (SCARD_LEAVE_CARD != dwDisposition)
816  return rv;
817  }
818  }
819 
820  Log2(PCSC_LOG_DEBUG, "Active Contexts: %d", rContext->contexts);
821  Log2(PCSC_LOG_DEBUG, "dwDisposition: %ld", dwDisposition);
822 
823  if (dwDisposition == SCARD_RESET_CARD ||
824  dwDisposition == SCARD_UNPOWER_CARD)
825  {
826  DWORD dwAtrLen;
827 
828  /*
829  * Notify the card has been reset
830  */
831  (void)RFSetReaderEventState(rContext, SCARD_RESET);
832 
833  /*
834  * Currently pcsc-lite keeps the card powered constantly
835  * unless DISABLE_AUTO_POWER_ON is defined
836  */
837  dwAtrLen = sizeof(rContext->readerState->cardAtr);
838  if (SCARD_RESET_CARD == dwDisposition)
839  rv = IFDPowerICC(rContext, IFD_RESET,
840  rContext->readerState->cardAtr, &dwAtrLen);
841  else
842  {
843  IFDPowerICC(rContext, IFD_POWER_DOWN, NULL, NULL);
844 
845 #ifdef DISABLE_AUTO_POWER_ON
846  rContext->powerState = POWER_STATE_UNPOWERED;
847  Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_UNPOWERED");
848 #else
849  rv = IFDPowerICC(rContext, IFD_POWER_UP,
850  rContext->readerState->cardAtr, &dwAtrLen);
851 #endif
852  }
853 
854  /* the protocol is unset after a power on */
856 
857 #ifdef DISABLE_AUTO_POWER_ON
858  if (SCARD_UNPOWER_CARD == dwDisposition)
859  {
860  rContext->readerState->cardAtrLength = 0;
861  if (rv == SCARD_S_SUCCESS)
863  else
864  {
865  Log3(PCSC_LOG_ERROR, "Error powering down card: %d 0x%04X",
866  rv, rv);
867  if (rv == SCARD_W_REMOVED_CARD)
868  rContext->readerState->readerState = SCARD_ABSENT;
869  else
870  rContext->readerState->readerState =
872  }
873  Log1(PCSC_LOG_INFO, "Skip card power on");
874  }
875  else
876 #endif
877  {
878  /*
879  * Set up the status bit masks on readerState
880  */
881  if (rv == SCARD_S_SUCCESS)
882  {
883  rContext->readerState->cardAtrLength = dwAtrLen;
884  rContext->readerState->readerState =
886 
887  Log1(PCSC_LOG_DEBUG, "Reset complete.");
888  LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
889  rContext->readerState->cardAtr,
890  rContext->readerState->cardAtrLength);
891  }
892  else
893  {
894  rContext->readerState->cardAtrLength = 0;
895  Log1(PCSC_LOG_ERROR, "Error resetting card.");
896 
897  if (rv == SCARD_W_REMOVED_CARD)
898  rContext->readerState->readerState = SCARD_ABSENT;
899  else
900  rContext->readerState->readerState =
902  }
903  }
904  }
905  else if (dwDisposition == SCARD_EJECT_CARD)
906  {
907  UCHAR controlBuffer[5];
908  UCHAR receiveBuffer[MAX_BUFFER_SIZE];
909  DWORD receiveLength;
910 
911  /*
912  * Set up the CTBCS command for Eject ICC
913  */
914  controlBuffer[0] = 0x20;
915  controlBuffer[1] = 0x15;
916  controlBuffer[2] = (rContext->slot & 0x0000FFFF) + 1;
917  controlBuffer[3] = 0x00;
918  controlBuffer[4] = 0x00;
919  receiveLength = 2;
920  rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
921  &receiveLength);
922 
923  if (rv == SCARD_S_SUCCESS)
924  {
925  if (receiveLength == 2 && receiveBuffer[0] == 0x90)
926  {
927  Log1(PCSC_LOG_DEBUG, "Card ejected successfully.");
928  /*
929  * Successful
930  */
931  }
932  else
933  Log1(PCSC_LOG_ERROR, "Error ejecting card.");
934  }
935  else
936  Log1(PCSC_LOG_ERROR, "Error ejecting card.");
937 
938  }
939  else if (dwDisposition == SCARD_LEAVE_CARD)
940  {
941  /*
942  * Do nothing
943  */
944  }
945 
946  /*
947  * Remove and destroy this handle
948  */
949  (void)RFRemoveReaderHandle(rContext, hCard);
950  (void)RFDestroyReaderHandle(hCard);
951 
952  /*
953  * For exclusive connection reset it to no connections
954  */
957  else
958  {
959  /*
960  * Remove a connection from the context stack
961  */
962  rContext->contexts -= 1;
963 
964  if (rContext->contexts < 0)
965  rContext->contexts = 0;
966  }
967 
968  if (PCSCLITE_SHARING_NO_CONTEXT == rContext->contexts)
969  {
970  RESPONSECODE (*fct)(DWORD) = NULL;
971  DWORD dwGetSize;
972 
973  (void)pthread_mutex_lock(&rContext->powerState_lock);
974  /* Switch to POWER_STATE_GRACE_PERIOD unless the card was not
975  * powered */
976  if (POWER_STATE_POWERED <= rContext->powerState)
977  {
978 #ifdef DISABLE_AUTO_POWER_ON
979  if (SCARD_RESET_CARD == dwDisposition)
980  {
982  Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_GRACE_PERIOD");
983  }
984 #else
986  Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_GRACE_PERIOD");
987 #endif
988  }
989 
990  (void)pthread_mutex_unlock(&rContext->powerState_lock);
991 
992  /* ask to stop the "polling" thread so it can be restarted using
993  * the correct timeout */
994  dwGetSize = sizeof(fct);
996  &dwGetSize, (PUCHAR)&fct);
997 
998  if ((IFD_SUCCESS == rv) && (dwGetSize == sizeof(fct)))
999  {
1000  Log1(PCSC_LOG_INFO, "Stoping polling thread");
1001  fct(rContext->slot);
1002  }
1003  }
1004 
1005  /*
1006  * Propagate new state to reader state
1007  */
1008  rContext->readerState->readerSharing = rContext->contexts;
1009 
1010  return SCARD_S_SUCCESS;
1011 }
1012 
1014 {
1015  LONG rv;
1016  READER_CONTEXT * rContext;
1017 
1018  if (hCard == 0)
1019  return SCARD_E_INVALID_HANDLE;
1020 
1021  /* get rContext corresponding to hCard */
1022  rv = RFReaderInfoById(hCard, &rContext);
1023  if (rv != SCARD_S_SUCCESS)
1024  return rv;
1025 
1026  /*
1027  * Make sure the reader is working properly
1028  */
1029  rv = RFCheckReaderStatus(rContext);
1030  if (rv != SCARD_S_SUCCESS)
1031  return rv;
1032 
1033  rv = RFFindReaderHandle(hCard);
1034  if (rv != SCARD_S_SUCCESS)
1035  return rv;
1036 
1037  /*
1038  * Make sure some event has not occurred
1039  */
1040  rv = RFCheckReaderEventState(rContext, hCard);
1041  if (rv != SCARD_S_SUCCESS)
1042  return rv;
1043 
1044  rv = RFLockSharing(hCard, rContext);
1045 
1046  /* if the transaction is not yet ready we sleep a bit so the client
1047  * do not retry immediately */
1048  if (SCARD_E_SHARING_VIOLATION == rv)
1050 
1051  Log2(PCSC_LOG_DEBUG, "Status: 0x%08lX", rv);
1052 
1053  return rv;
1054 }
1055 
1056 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
1057 {
1058  LONG rv;
1059  READER_CONTEXT * rContext = NULL;
1060 
1061  /*
1062  * Ignoring dwDisposition for now
1063  */
1064  if (hCard == 0)
1065  return SCARD_E_INVALID_HANDLE;
1066 
1067  if ((dwDisposition != SCARD_LEAVE_CARD)
1068  && (dwDisposition != SCARD_UNPOWER_CARD)
1069  && (dwDisposition != SCARD_RESET_CARD)
1070  && (dwDisposition != SCARD_EJECT_CARD))
1071  return SCARD_E_INVALID_VALUE;
1072 
1073  /* get rContext corresponding to hCard */
1074  rv = RFReaderInfoById(hCard, &rContext);
1075  if (rv != SCARD_S_SUCCESS)
1076  return rv;
1077 
1078  rv = RFFindReaderHandle(hCard);
1079  if (rv != SCARD_S_SUCCESS)
1080  return rv;
1081 
1082  /*
1083  * Make sure some event has not occurred
1084  */
1085  rv = RFCheckReaderEventState(rContext, hCard);
1086  if (rv != SCARD_S_SUCCESS)
1087  return rv;
1088 
1089  if (dwDisposition == SCARD_RESET_CARD ||
1090  dwDisposition == SCARD_UNPOWER_CARD)
1091  {
1092  DWORD dwAtrLen;
1093 
1094  /*
1095  * Currently pcsc-lite keeps the card always powered
1096  */
1097  dwAtrLen = sizeof(rContext->readerState->cardAtr);
1098  if (SCARD_RESET_CARD == dwDisposition)
1099  rv = IFDPowerICC(rContext, IFD_RESET,
1100  rContext->readerState->cardAtr, &dwAtrLen);
1101  else
1102  {
1103  IFDPowerICC(rContext, IFD_POWER_DOWN, NULL, NULL);
1104  rv = IFDPowerICC(rContext, IFD_POWER_UP,
1105  rContext->readerState->cardAtr, &dwAtrLen);
1106  }
1107 
1108  /* the protocol is unset after a power on */
1110 
1111  /*
1112  * Notify the card has been reset
1113  */
1114  (void)RFSetReaderEventState(rContext, SCARD_RESET);
1115 
1116  /*
1117  * Set up the status bit masks on readerState
1118  */
1119  if (rv == SCARD_S_SUCCESS)
1120  {
1121  rContext->readerState->cardAtrLength = dwAtrLen;
1122  rContext->readerState->readerState =
1124 
1125  Log1(PCSC_LOG_DEBUG, "Reset complete.");
1126  LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
1127  rContext->readerState->cardAtr,
1128  rContext->readerState->cardAtrLength);
1129  }
1130  else
1131  {
1132  rContext->readerState->cardAtrLength = 0;
1133  Log1(PCSC_LOG_ERROR, "Error resetting card.");
1134 
1135  if (rv == SCARD_W_REMOVED_CARD)
1136  rContext->readerState->readerState = SCARD_ABSENT;
1137  else
1138  rContext->readerState->readerState =
1140  }
1141  }
1142  else if (dwDisposition == SCARD_EJECT_CARD)
1143  {
1144  UCHAR controlBuffer[5];
1145  UCHAR receiveBuffer[MAX_BUFFER_SIZE];
1146  DWORD receiveLength;
1147 
1148  /*
1149  * Set up the CTBCS command for Eject ICC
1150  */
1151  controlBuffer[0] = 0x20;
1152  controlBuffer[1] = 0x15;
1153  controlBuffer[2] = (rContext->slot & 0x0000FFFF) + 1;
1154  controlBuffer[3] = 0x00;
1155  controlBuffer[4] = 0x00;
1156  receiveLength = 2;
1157  rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
1158  &receiveLength);
1159 
1160  if (rv == SCARD_S_SUCCESS)
1161  {
1162  if (receiveLength == 2 && receiveBuffer[0] == 0x90)
1163  {
1164  Log1(PCSC_LOG_DEBUG, "Card ejected successfully.");
1165  /*
1166  * Successful
1167  */
1168  }
1169  else
1170  Log1(PCSC_LOG_ERROR, "Error ejecting card.");
1171  }
1172  else
1173  Log1(PCSC_LOG_ERROR, "Error ejecting card.");
1174 
1175  }
1176  else if (dwDisposition == SCARD_LEAVE_CARD)
1177  {
1178  /*
1179  * Do nothing
1180  */
1181  }
1182 
1183  /*
1184  * Unlock any blocks on this context
1185  */
1186  (void)RFUnlockSharing(hCard, rContext);
1187 
1188  Log2(PCSC_LOG_DEBUG, "Status: 0x%08lX", rv);
1189 
1190  return rv;
1191 }
1192 
1193 LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderNames,
1194  LPDWORD pcchReaderLen, LPDWORD pdwState,
1195  LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1196 {
1197  LONG rv;
1198  READER_CONTEXT * rContext = NULL;
1199 
1200  /* These parameters are not used by the client
1201  * Client side code uses readerStates[] instead */
1202  (void)mszReaderNames;
1203  (void)pcchReaderLen;
1204  (void)pdwState;
1205  (void)pdwProtocol;
1206  (void)pbAtr;
1207  (void)pcbAtrLen;
1208 
1209  if (hCard == 0)
1210  return SCARD_E_INVALID_HANDLE;
1211 
1212  /* get rContext corresponding to hCard */
1213  rv = RFReaderInfoById(hCard, &rContext);
1214  if (rv != SCARD_S_SUCCESS)
1215  return rv;
1216 
1217  /*
1218  * Make sure no one has a lock on this reader
1219  */
1220  rv = RFCheckSharing(hCard, rContext);
1221  if (rv != SCARD_S_SUCCESS)
1222  return rv;
1223 
1224  if (rContext->readerState->cardAtrLength > MAX_ATR_SIZE)
1225  return SCARD_F_INTERNAL_ERROR;
1226 
1227  /*
1228  * This is a client side function however the server maintains the
1229  * list of events between applications so it must be passed through to
1230  * obtain this event if it has occurred
1231  */
1232 
1233  /*
1234  * Make sure some event has not occurred
1235  */
1236  rv = RFCheckReaderEventState(rContext, hCard);
1237  if (rv != SCARD_S_SUCCESS)
1238  return rv;
1239 
1240  /*
1241  * Make sure the reader is working properly
1242  */
1243  rv = RFCheckReaderStatus(rContext);
1244  if (rv != SCARD_S_SUCCESS)
1245  return rv;
1246 
1247  return rv;
1248 }
1249 
1250 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode,
1251  LPCVOID pbSendBuffer, DWORD cbSendLength,
1252  LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned)
1253 {
1254  LONG rv;
1255  READER_CONTEXT * rContext = NULL;
1256 
1257  /* 0 bytes returned by default */
1258  *lpBytesReturned = 0;
1259 
1260  if (0 == hCard)
1261  return SCARD_E_INVALID_HANDLE;
1262 
1263  /* get rContext corresponding to hCard */
1264  rv = RFReaderInfoById(hCard, &rContext);
1265  if (rv != SCARD_S_SUCCESS)
1266  return rv;
1267 
1268  /*
1269  * Make sure no one has a lock on this reader
1270  */
1271  rv = RFCheckSharing(hCard, rContext);
1272  if (rv != SCARD_S_SUCCESS)
1273  return rv;
1274 
1275  if (IFD_HVERSION_2_0 == rContext->version)
1276  if (NULL == pbSendBuffer || 0 == cbSendLength)
1278 
1279  /*
1280  * Make sure the reader is working properly
1281  */
1282  rv = RFCheckReaderStatus(rContext);
1283  if (rv != SCARD_S_SUCCESS)
1284  return rv;
1285 
1286  rv = RFFindReaderHandle(hCard);
1287  if (rv != SCARD_S_SUCCESS)
1288  return rv;
1289 
1290  if (IFD_HVERSION_2_0 == rContext->version)
1291  {
1292  /* we must wrap a API 3.0 client in an API 2.0 driver */
1293  *lpBytesReturned = cbRecvLength;
1294  return IFDControl_v2(rContext, (PUCHAR)pbSendBuffer,
1295  cbSendLength, pbRecvBuffer, lpBytesReturned);
1296  }
1297  else
1298  if (IFD_HVERSION_3_0 == rContext->version)
1299  return IFDControl(rContext, dwControlCode, pbSendBuffer,
1300  cbSendLength, pbRecvBuffer, cbRecvLength, lpBytesReturned);
1301  else
1303 }
1304 
1305 LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
1306  LPBYTE pbAttr, LPDWORD pcbAttrLen)
1307 {
1308  LONG rv;
1309  READER_CONTEXT * rContext = NULL;
1310 
1311  if (0 == hCard)
1312  return SCARD_E_INVALID_HANDLE;
1313 
1314  /* get rContext corresponding to hCard */
1315  rv = RFReaderInfoById(hCard, &rContext);
1316  if (rv != SCARD_S_SUCCESS)
1317  return rv;
1318 
1319  /*
1320  * Make sure no one has a lock on this reader
1321  */
1322  rv = RFCheckSharing(hCard, rContext);
1323  if (rv != SCARD_S_SUCCESS)
1324  return rv;
1325 
1326  /*
1327  * Make sure the reader is working properly
1328  */
1329  rv = RFCheckReaderStatus(rContext);
1330  if (rv != SCARD_S_SUCCESS)
1331  return rv;
1332 
1333  rv = RFFindReaderHandle(hCard);
1334  if (rv != SCARD_S_SUCCESS)
1335  return rv;
1336 
1337  /*
1338  * Make sure some event has not occurred
1339  */
1340  rv = RFCheckReaderEventState(rContext, hCard);
1341  if (rv != SCARD_S_SUCCESS)
1342  return rv;
1343 
1344  rv = IFDGetCapabilities(rContext, dwAttrId, pcbAttrLen, pbAttr);
1345  switch(rv)
1346  {
1347  case IFD_SUCCESS:
1348  rv = SCARD_S_SUCCESS;
1349  break;
1350  case IFD_ERROR_TAG:
1351  /* Special case SCARD_ATTR_DEVICE_FRIENDLY_NAME as it is better
1352  * implemented in pcscd (it knows the friendly name)
1353  */
1354  if (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME)
1355  {
1356  unsigned int len = strlen(rContext->readerState->readerName)+1;
1357 
1358  *pcbAttrLen = len;
1359  if (len > *pcbAttrLen)
1361  else
1362  {
1363  (void)strlcpy((char *)pbAttr,
1364  rContext->readerState->readerName, *pcbAttrLen);
1365  rv = SCARD_S_SUCCESS;
1366  }
1367 
1368  }
1369  else
1371  break;
1374  break;
1375  default:
1377  }
1378 
1379  return rv;
1380 }
1381 
1382 LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
1383  LPCBYTE pbAttr, DWORD cbAttrLen)
1384 {
1385  LONG rv;
1386  READER_CONTEXT * rContext = NULL;
1387 
1388  if (0 == hCard)
1389  return SCARD_E_INVALID_HANDLE;
1390 
1391  /* get rContext corresponding to hCard */
1392  rv = RFReaderInfoById(hCard, &rContext);
1393  if (rv != SCARD_S_SUCCESS)
1394  return rv;
1395 
1396  /*
1397  * Make sure no one has a lock on this reader
1398  */
1399  rv = RFCheckSharing(hCard, rContext);
1400  if (rv != SCARD_S_SUCCESS)
1401  return rv;
1402 
1403  /*
1404  * Make sure the reader is working properly
1405  */
1406  rv = RFCheckReaderStatus(rContext);
1407  if (rv != SCARD_S_SUCCESS)
1408  return rv;
1409 
1410  rv = RFFindReaderHandle(hCard);
1411  if (rv != SCARD_S_SUCCESS)
1412  return rv;
1413 
1414  /*
1415  * Make sure some event has not occurred
1416  */
1417  rv = RFCheckReaderEventState(rContext, hCard);
1418  if (rv != SCARD_S_SUCCESS)
1419  return rv;
1420 
1421  rv = IFDSetCapabilities(rContext, dwAttrId, cbAttrLen, (PUCHAR)pbAttr);
1422  if (rv == IFD_SUCCESS)
1423  return SCARD_S_SUCCESS;
1424  else
1425  if (rv == IFD_ERROR_TAG)
1427  else
1428  return SCARD_E_NOT_TRANSACTED;
1429 }
1430 
1431 LONG SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
1432  LPCBYTE pbSendBuffer, DWORD cbSendLength,
1433  SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer,
1434  LPDWORD pcbRecvLength)
1435 {
1436  LONG rv;
1437  READER_CONTEXT * rContext = NULL;
1438  SCARD_IO_HEADER sSendPci, sRecvPci;
1439  DWORD dwRxLength, tempRxLength;
1440 
1441  dwRxLength = *pcbRecvLength;
1442  *pcbRecvLength = 0;
1443 
1444  if (hCard == 0)
1445  return SCARD_E_INVALID_HANDLE;
1446 
1447  /*
1448  * Must at least have 2 status words even for SCardControl
1449  */
1450  if (dwRxLength < 2)
1452 
1453  /* get rContext corresponding to hCard */
1454  rv = RFReaderInfoById(hCard, &rContext);
1455  if (rv != SCARD_S_SUCCESS)
1456  return rv;
1457 
1458  /*
1459  * Make sure no one has a lock on this reader
1460  */
1461  rv = RFCheckSharing(hCard, rContext);
1462  if (rv != SCARD_S_SUCCESS)
1463  return rv;
1464 
1465  /*
1466  * Make sure the reader is working properly
1467  */
1468  rv = RFCheckReaderStatus(rContext);
1469  if (rv != SCARD_S_SUCCESS)
1470  return rv;
1471 
1472  rv = RFFindReaderHandle(hCard);
1473  if (rv != SCARD_S_SUCCESS)
1474  return rv;
1475 
1476  /*
1477  * Make sure some event has not occurred
1478  */
1479  rv = RFCheckReaderEventState(rContext, hCard);
1480  if (rv != SCARD_S_SUCCESS)
1481  return rv;
1482 
1483  /*
1484  * Check for some common errors
1485  */
1486  if (pioSendPci->dwProtocol != SCARD_PROTOCOL_RAW)
1487  {
1488  if (rContext->readerState->readerState & SCARD_ABSENT)
1489  {
1490  return SCARD_E_NO_SMARTCARD;
1491  }
1492  }
1493 
1494  if (pioSendPci->dwProtocol != SCARD_PROTOCOL_RAW)
1495  {
1496  if (pioSendPci->dwProtocol != SCARD_PROTOCOL_ANY_OLD)
1497  {
1498  if (pioSendPci->dwProtocol != rContext->readerState->cardProtocol)
1499  {
1500  return SCARD_E_PROTO_MISMATCH;
1501  }
1502  }
1503  }
1504 
1505  /*
1506  * Quick fix: PC/SC starts at 1 for bit masking but the IFD_Handler
1507  * just wants 0 or 1
1508  */
1509 
1510  sSendPci.Protocol = 0; /* protocol T=0 by default */
1511 
1512  if (pioSendPci->dwProtocol == SCARD_PROTOCOL_T1)
1513  {
1514  sSendPci.Protocol = 1;
1515  } else if (pioSendPci->dwProtocol == SCARD_PROTOCOL_RAW)
1516  {
1517  /*
1518  * This is temporary ......
1519  */
1520  sSendPci.Protocol = SCARD_PROTOCOL_RAW;
1521  } else if (pioSendPci->dwProtocol == SCARD_PROTOCOL_ANY_OLD)
1522  {
1523  /* Fix by Amira (Athena) */
1524  unsigned long i;
1525  unsigned long prot = rContext->readerState->cardProtocol;
1526 
1527  for (i = 0 ; prot != 1 ; i++)
1528  prot >>= 1;
1529 
1530  sSendPci.Protocol = i;
1531  }
1532 
1533  sSendPci.Length = pioSendPci->cbPciLength;
1534 
1535  sRecvPci.Protocol = pioRecvPci->dwProtocol;
1536  sRecvPci.Length = pioRecvPci->cbPciLength;
1537 
1538  /* the protocol number is decoded a few lines above */
1539  Log2(PCSC_LOG_DEBUG, "Send Protocol: T=%ld", sSendPci.Protocol);
1540 
1541  tempRxLength = dwRxLength;
1542 
1543  if ((pioSendPci->dwProtocol == SCARD_PROTOCOL_RAW)
1544  && (rContext->version == IFD_HVERSION_2_0))
1545  {
1546  rv = IFDControl_v2(rContext, (PUCHAR) pbSendBuffer, cbSendLength,
1547  pbRecvBuffer, &dwRxLength);
1548  } else
1549  {
1550  rv = IFDTransmit(rContext, sSendPci, (PUCHAR) pbSendBuffer,
1551  cbSendLength, pbRecvBuffer, &dwRxLength, &sRecvPci);
1552  }
1553 
1554  pioRecvPci->dwProtocol = sRecvPci.Protocol;
1555  pioRecvPci->cbPciLength = sRecvPci.Length;
1556 
1557  /*
1558  * Check for any errors that might have occurred
1559  */
1560 
1561  if (rv != SCARD_S_SUCCESS)
1562  {
1563  *pcbRecvLength = 0;
1564  Log2(PCSC_LOG_ERROR, "Card not transacted: 0x%08lX", rv);
1565  return rv;
1566  }
1567 
1568  /*
1569  * Available is less than received
1570  */
1571  if (tempRxLength < dwRxLength)
1572  {
1573  *pcbRecvLength = 0;
1575  }
1576 
1577  /*
1578  * Successful return
1579  */
1580  *pcbRecvLength = dwRxLength;
1581  return SCARD_S_SUCCESS;
1582 }
1583