winscard.c

Go to the documentation of this file.
00001 /*
00002  * MUSCLE SmartCard Development ( http://www.linuxnet.com )
00003  *
00004  * Copyright (C) 1999-2004
00005  *  David Corcoran <corcoran@linuxnet.com>
00006  *  Ludovic Rousseau <ludovic.rousseau@free.fr>
00007  *
00008  * $Id: winscard.c 2613 2007-08-13 07:13:30Z rousseau $
00009  */
00010 
00081 #include "config.h"
00082 #include <stdlib.h>
00083 #include <sys/time.h>
00084 #include <string.h>
00085 
00086 #include "pcscd.h"
00087 #include "winscard.h"
00088 #include "ifdhandler.h"
00089 #include "debuglog.h"
00090 #include "readerfactory.h"
00091 #include "prothandler.h"
00092 #include "ifdwrapper.h"
00093 #include "atrhandler.h"
00094 #include "sys_generic.h"
00095 #include "eventhandler.h"
00096 
00097 #undef DO_PROFILE
00098 #ifdef DO_PROFILE
00099 
00100 #ifndef FALSE
00101 #define FALSE 0
00102 #define TRUE 1
00103 #endif
00104 
00105 #define PROFILE_FILE "/tmp/pcscd_profile"
00106 #include <stdio.h>
00107 #include <sys/time.h>
00108 #include <errno.h>
00109 #include <unistd.h>
00110 
00111 struct timeval profile_time_start;
00112 FILE *fd;
00113 char profile_tty;
00114 
00115 #define PROFILE_START profile_start(__FUNCTION__);
00116 #define PROFILE_END profile_end(__FUNCTION__, __LINE__);
00117 
00118 static void profile_start(const char *f)
00119 {
00120     static char initialized = FALSE;
00121 
00122     if (!initialized)
00123     {
00124         initialized = TRUE;
00125         fd = fopen(PROFILE_FILE, "a+");
00126         if (NULL == fd)
00127         {
00128             fprintf(stderr, "\33[01;31mCan't open %s: %s\33[0m\n",
00129                 PROFILE_FILE, strerror(errno));
00130             exit(-1);
00131         }
00132         fprintf(fd, "\nStart a new profile\n");
00133         fflush(fd);
00134 
00135         if (isatty(fileno(stderr)))
00136             profile_tty = TRUE;
00137         else
00138             profile_tty = FALSE;
00139     }
00140 
00141     gettimeofday(&profile_time_start, NULL);
00142 } /* profile_start */
00143 
00144 /* r = a - b */
00145 static long int time_sub(struct timeval *a, struct timeval *b)
00146 {
00147     struct timeval r;
00148     r.tv_sec = a -> tv_sec - b -> tv_sec;
00149     r.tv_usec = a -> tv_usec - b -> tv_usec;
00150     if (r.tv_usec < 0)
00151     {
00152         r.tv_sec--;
00153         r.tv_usec += 1000000;
00154     }
00155 
00156     return r.tv_sec * 1000000 + r.tv_usec;
00157 } /* time_sub */
00158 
00159 
00160 static void profile_end(const char *f, int line)
00161 {
00162     struct timeval profile_time_end;
00163     long d;
00164 
00165     gettimeofday(&profile_time_end, NULL);
00166     d = time_sub(&profile_time_end, &profile_time_start);
00167 
00168     if (profile_tty)
00169         fprintf(stderr, "\33[01;31mRESULT %s \33[35m%ld\33[0m (%d)\n", f, d,
00170             line);
00171     fprintf(fd, "%s %ld\n", f, d);
00172     fflush(fd);
00173 } /* profile_end */
00174 
00175 #else
00176 #define PROFILE_START
00177 #define PROFILE_END
00178 #endif
00179 
00181 #define SCARD_PROTOCOL_ANY_OLD   0x1000
00182 
00184 #define SCARD_LAST_CONTEXT       1
00185 
00186 #define SCARD_NO_CONTEXT         0
00187 
00188 #define SCARD_EXCLUSIVE_CONTEXT -1
00189 
00190 #define SCARD_NO_LOCK            0
00191 
00192 SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_T0, sizeof(SCARD_IO_REQUEST) };
00193 SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, sizeof(SCARD_IO_REQUEST) };
00194 SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_RAW, sizeof(SCARD_IO_REQUEST) };
00195 
00218 LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
00219     LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
00220 {
00221     /*
00222      * Check for NULL pointer
00223      */
00224     if (phContext == 0)
00225         return SCARD_E_INVALID_PARAMETER;
00226 
00227     if (dwScope != SCARD_SCOPE_USER && dwScope != SCARD_SCOPE_TERMINAL &&
00228         dwScope != SCARD_SCOPE_SYSTEM && dwScope != SCARD_SCOPE_GLOBAL)
00229     {
00230 
00231         *phContext = 0;
00232         return SCARD_E_INVALID_VALUE;
00233     }
00234 
00235     /*
00236      * Unique identifier for this server so that it can uniquely be
00237      * identified by clients and distinguished from others
00238      */
00239 
00240     *phContext = (PCSCLITE_SVC_IDENTITY + SYS_RandomInt(1, 65535));
00241 
00242     Log2(PCSC_LOG_DEBUG, "Establishing Context: %d", *phContext);
00243 
00244     return SCARD_S_SUCCESS;
00245 }
00246 
00247 LONG SCardReleaseContext(SCARDCONTEXT hContext)
00248 {
00249     /*
00250      * Nothing to do here RPC layer will handle this
00251      */
00252 
00253     Log2(PCSC_LOG_DEBUG, "Releasing Context: %d", hContext);
00254 
00255     return SCARD_S_SUCCESS;
00256 }
00257 
00258 LONG SCardSetTimeout(SCARDCONTEXT hContext, DWORD dwTimeout)
00259 {
00260     /*
00261      * This is only used at the client side of an RPC call but just in
00262      * case someone calls it here
00263      */
00264 
00265     return SCARD_E_UNSUPPORTED_FEATURE;
00266 }
00267 
00268 LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader,
00269     DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
00270     LPDWORD pdwActiveProtocol)
00271 {
00272     LONG rv;
00273     PREADER_CONTEXT rContext = NULL;
00274     DWORD dwStatus;
00275 
00276     PROFILE_START
00277 
00278     /*
00279      * Check for NULL parameters
00280      */
00281     if (szReader == NULL || phCard == NULL || pdwActiveProtocol == NULL)
00282         return SCARD_E_INVALID_PARAMETER;
00283     else
00284         *phCard = 0;
00285 
00286     if (!(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
00287             !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
00288             !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
00289             !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
00290         return SCARD_E_PROTO_MISMATCH;
00291 
00292     if (dwShareMode != SCARD_SHARE_EXCLUSIVE &&
00293             dwShareMode != SCARD_SHARE_SHARED &&
00294             dwShareMode != SCARD_SHARE_DIRECT)
00295         return SCARD_E_INVALID_VALUE;
00296 
00297     Log3(PCSC_LOG_DEBUG, "Attempting Connect to %s using protocol: %d",
00298         szReader, dwPreferredProtocols);
00299 
00300     rv = RFReaderInfo((LPSTR) szReader, &rContext);
00301 
00302     if (rv != SCARD_S_SUCCESS)
00303     {
00304         Log2(PCSC_LOG_ERROR, "Reader %s Not Found", szReader);
00305         return rv;
00306     }
00307 
00308     /*
00309      * Make sure the reader is working properly
00310      */
00311     rv = RFCheckReaderStatus(rContext);
00312     if (rv != SCARD_S_SUCCESS)
00313         return rv;
00314 
00315     /*******************************************
00316      *
00317      * This section checks for simple errors
00318      *
00319      *******************************************/
00320 
00321     /*
00322      * Connect if not exclusive mode
00323      */
00324     if (rContext->dwContexts == SCARD_EXCLUSIVE_CONTEXT)
00325     {
00326         Log1(PCSC_LOG_ERROR, "Error Reader Exclusive");
00327         return SCARD_E_SHARING_VIOLATION;
00328     }
00329 
00330     /*
00331      * wait until a possible transaction is finished
00332      */
00333     if (rContext->dwLockId != 0)
00334     {
00335         Log1(PCSC_LOG_INFO, "Waiting for release of lock");
00336         while (rContext->dwLockId != 0)
00337             SYS_USleep(PCSCLITE_LOCK_POLL_RATE);
00338         Log1(PCSC_LOG_INFO, "Lock released");
00339 
00340         /* Allow the status thread to convey information */
00341         SYS_USleep(PCSCLITE_STATUS_POLL_RATE + 10);
00342     }
00343 
00344     /* the reader has been removed while we were waiting */
00345     if (NULL == rContext->readerState)
00346         return SCARD_E_NO_SMARTCARD;
00347 
00348     /*******************************************
00349      *
00350      * This section tries to determine the
00351      * presence of a card or not
00352      *
00353      *******************************************/
00354     dwStatus = rContext->readerState->readerState;
00355 
00356     if (dwShareMode != SCARD_SHARE_DIRECT)
00357     {
00358         if (!(dwStatus & SCARD_PRESENT))
00359         {
00360             Log1(PCSC_LOG_ERROR, "Card Not Inserted");
00361             return SCARD_E_NO_SMARTCARD;
00362         }
00363 
00364         if (dwStatus & SCARD_SWALLOWED)
00365         {
00366             Log1(PCSC_LOG_ERROR, "Card Not Powered");
00367             return SCARD_W_UNPOWERED_CARD;
00368         }
00369     }
00370 
00371 
00372     /*******************************************
00373      *
00374      * This section tries to decode the ATR
00375      * and set up which protocol to use
00376      *
00377      *******************************************/
00378     if (dwPreferredProtocols & SCARD_PROTOCOL_RAW)
00379         rContext->readerState->cardProtocol = SCARD_PROTOCOL_RAW;
00380     else
00381     {
00382         if (dwShareMode != SCARD_SHARE_DIRECT)
00383         {
00384             /* the protocol is not yet set (no PPS yet) */
00385             if (SCARD_PROTOCOL_UNDEFINED == rContext->readerState->cardProtocol)
00386             {
00387                 UCHAR ucAvailable, ucDefault;
00388                 int ret;
00389 
00390                 ucDefault = PHGetDefaultProtocol(rContext->readerState->cardAtr,
00391                     rContext->readerState->cardAtrLength);
00392                 ucAvailable =
00393                     PHGetAvailableProtocols(rContext->readerState->cardAtr,
00394                             rContext->readerState->cardAtrLength);
00395 
00396                 /*
00397                  * If it is set to ANY let it do any of the protocols
00398                  */
00399                 if (dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)
00400                     dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
00401 
00402                 ret = PHSetProtocol(rContext, dwPreferredProtocols,
00403                     ucAvailable, ucDefault);
00404 
00405                 /* keep cardProtocol = SCARD_PROTOCOL_UNDEFINED in case of error  */
00406                 if (SET_PROTOCOL_PPS_FAILED == ret)
00407                     return SCARD_W_UNRESPONSIVE_CARD;
00408 
00409                 if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
00410                     return SCARD_E_PROTO_MISMATCH;
00411 
00412                 /* use negociated protocol */
00413                 rContext->readerState->cardProtocol = ret;
00414             }
00415             else
00416             {
00417                 if (! (dwPreferredProtocols & rContext->readerState->cardProtocol))
00418                     return SCARD_E_PROTO_MISMATCH;
00419             }
00420         }
00421     }
00422 
00423     *pdwActiveProtocol = rContext->readerState->cardProtocol;
00424 
00425     if (dwShareMode != SCARD_SHARE_DIRECT)
00426     {
00427         if ((*pdwActiveProtocol != SCARD_PROTOCOL_T0)
00428             && (*pdwActiveProtocol != SCARD_PROTOCOL_T1))
00429             Log2(PCSC_LOG_ERROR, "Active Protocol: unknown %d",
00430                 *pdwActiveProtocol);
00431         else
00432             Log2(PCSC_LOG_DEBUG, "Active Protocol: T=%d",
00433                 (*pdwActiveProtocol == SCARD_PROTOCOL_T0) ? 0 : 1);
00434     }
00435     else
00436         Log1(PCSC_LOG_DEBUG, "Direct access: no protocol selected");
00437 
00438     /*
00439      * Prepare the SCARDHANDLE identity
00440      */
00441     *phCard = RFCreateReaderHandle(rContext);
00442 
00443     Log2(PCSC_LOG_DEBUG, "hCard Identity: %x", *phCard);
00444 
00445     /*******************************************
00446      *
00447      * This section tries to set up the
00448      * exclusivity modes. -1 is exclusive
00449      *
00450      *******************************************/
00451 
00452     if (dwShareMode == SCARD_SHARE_EXCLUSIVE)
00453     {
00454         if (rContext->dwContexts == SCARD_NO_CONTEXT)
00455         {
00456             rContext->dwContexts = SCARD_EXCLUSIVE_CONTEXT;
00457             RFLockSharing(*phCard);
00458         }
00459         else
00460         {
00461             RFDestroyReaderHandle(*phCard);
00462             *phCard = 0;
00463             return SCARD_E_SHARING_VIOLATION;
00464         }
00465     }
00466     else
00467     {
00468         /*
00469          * Add a connection to the context stack
00470          */
00471         rContext->dwContexts += 1;
00472     }
00473 
00474     /*
00475      * Add this handle to the handle list
00476      */
00477     rv = RFAddReaderHandle(rContext, *phCard);
00478 
00479     if (rv != SCARD_S_SUCCESS)
00480     {
00481         /*
00482          * Clean up - there is no more room
00483          */
00484         RFDestroyReaderHandle(*phCard);
00485         if (rContext->dwContexts == SCARD_EXCLUSIVE_CONTEXT)
00486             rContext->dwContexts = SCARD_NO_CONTEXT;
00487         else
00488             if (rContext->dwContexts > SCARD_NO_CONTEXT)
00489                 rContext->dwContexts -= 1;
00490 
00491         *phCard = 0;
00492 
00493         PROFILE_END
00494 
00495         return SCARD_F_INTERNAL_ERROR;
00496     }
00497 
00498     /*
00499      * Allow the status thread to convey information
00500      */
00501     SYS_USleep(PCSCLITE_STATUS_POLL_RATE + 10);
00502 
00503     PROFILE_END
00504 
00505     return SCARD_S_SUCCESS;
00506 }
00507 
00508 LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
00509     DWORD dwPreferredProtocols, DWORD dwInitialization,
00510     LPDWORD pdwActiveProtocol)
00511 {
00512     LONG rv;
00513     PREADER_CONTEXT rContext = NULL;
00514     int do_sleep = 1;
00515 
00516     Log1(PCSC_LOG_DEBUG, "Attempting reconnect to token.");
00517 
00518     if (hCard == 0)
00519         return SCARD_E_INVALID_HANDLE;
00520 
00521     /*
00522      * Handle the dwInitialization
00523      */
00524     if (dwInitialization != SCARD_LEAVE_CARD &&
00525             dwInitialization != SCARD_RESET_CARD &&
00526             dwInitialization != SCARD_UNPOWER_CARD)
00527         return SCARD_E_INVALID_VALUE;
00528 
00529     if (dwShareMode != SCARD_SHARE_SHARED &&
00530             dwShareMode != SCARD_SHARE_EXCLUSIVE &&
00531             dwShareMode != SCARD_SHARE_DIRECT)
00532         return SCARD_E_INVALID_VALUE;
00533 
00534     if (!(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
00535             !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
00536             !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
00537             !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
00538         return SCARD_E_PROTO_MISMATCH;
00539 
00540     if (pdwActiveProtocol == NULL)
00541         return SCARD_E_INVALID_PARAMETER;
00542 
00543     rv = RFReaderInfoById(hCard, &rContext);
00544     if (rv != SCARD_S_SUCCESS)
00545         return rv;
00546 
00547     /*
00548      * Make sure the reader is working properly
00549      */
00550     rv = RFCheckReaderStatus(rContext);
00551     if (rv != SCARD_S_SUCCESS)
00552         return rv;
00553 
00554     rv = RFFindReaderHandle(hCard);
00555     if (rv != SCARD_S_SUCCESS)
00556         return rv;
00557 
00558     /*
00559      * Make sure no one has a lock on this reader
00560      */
00561     rv = RFCheckSharing(hCard);
00562     if (rv != SCARD_S_SUCCESS)
00563         return rv;
00564 
00565     /*
00566      * RFUnblockReader( rContext ); FIX - this doesn't work
00567      */
00568 
00569     if (dwInitialization == SCARD_RESET_CARD ||
00570         dwInitialization == SCARD_UNPOWER_CARD)
00571     {
00572         /*
00573          * Currently pcsc-lite keeps the card powered constantly
00574          */
00575         if (SCARD_RESET_CARD == dwInitialization)
00576             rv = IFDPowerICC(rContext, IFD_RESET,
00577                 rContext->readerState->cardAtr,
00578                 &rContext->readerState->cardAtrLength);
00579         else
00580         {
00581             rv = IFDPowerICC(rContext, IFD_POWER_DOWN,
00582                 rContext->readerState->cardAtr,
00583                 &rContext->readerState->cardAtrLength);
00584             rv = IFDPowerICC(rContext, IFD_POWER_UP,
00585                 rContext->readerState->cardAtr,
00586                 &rContext->readerState->cardAtrLength);
00587         }
00588 
00589         /* the protocol is unset after a power on */
00590         rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00591 
00592         /*
00593          * Notify the card has been reset
00594          * Not doing this could result in deadlock
00595          */
00596         rv = RFCheckReaderEventState(rContext, hCard);
00597         switch(rv)
00598         {
00599             /* avoid deadlock */
00600             case SCARD_W_RESET_CARD:
00601                 break;
00602 
00603             case SCARD_W_REMOVED_CARD:
00604                 Log1(PCSC_LOG_ERROR, "card removed");
00605                 return SCARD_W_REMOVED_CARD;
00606 
00607             /* invalid EventStatus */
00608             case SCARD_E_INVALID_VALUE:
00609                 Log1(PCSC_LOG_ERROR, "invalid EventStatus");
00610                 return SCARD_F_INTERNAL_ERROR;
00611 
00612             /* invalid hCard, but hCard was widely used some lines above :( */
00613             case SCARD_E_INVALID_HANDLE:
00614                 Log1(PCSC_LOG_ERROR, "invalid handle");
00615                 return SCARD_F_INTERNAL_ERROR;
00616 
00617             case SCARD_S_SUCCESS:
00618                 /*
00619                  * Notify the card has been reset
00620                  */
00621                 RFSetReaderEventState(rContext, SCARD_RESET);
00622 
00623                 /*
00624                  * Set up the status bit masks on dwStatus
00625                  */
00626                 if (rv == SCARD_S_SUCCESS)
00627                 {
00628                     rContext->readerState->readerState |= SCARD_PRESENT;
00629                     rContext->readerState->readerState &= ~SCARD_ABSENT;
00630                     rContext->readerState->readerState |= SCARD_POWERED;
00631                     rContext->readerState->readerState |= SCARD_NEGOTIABLE;
00632                     rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00633                     rContext->readerState->readerState &= ~SCARD_SWALLOWED;
00634                     rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00635                 }
00636                 else
00637                 {
00638                     rContext->readerState->readerState |= SCARD_PRESENT;
00639                     rContext->readerState->readerState &= ~SCARD_ABSENT;
00640                     rContext->readerState->readerState |= SCARD_SWALLOWED;
00641                     rContext->readerState->readerState &= ~SCARD_POWERED;
00642                     rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
00643                     rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00644                     rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00645                     rContext->readerState->cardAtrLength = 0;
00646                 }
00647 
00648                 if (rContext->readerState->cardAtrLength > 0)
00649                 {
00650                     Log1(PCSC_LOG_DEBUG, "Reset complete.");
00651                     LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
00652                         rContext->readerState->cardAtr,
00653                         rContext->readerState->cardAtrLength);
00654                 }
00655                 else
00656                 {
00657                     DWORD dwStatus, dwAtrLen;
00658                     UCHAR ucAtr[MAX_ATR_SIZE];
00659 
00660                     Log1(PCSC_LOG_ERROR, "Error resetting card.");
00661                     IFDStatusICC(rContext, &dwStatus, ucAtr, &dwAtrLen);
00662                     if (dwStatus & SCARD_PRESENT)
00663                         return SCARD_W_UNRESPONSIVE_CARD;
00664                     else
00665                         return SCARD_E_NO_SMARTCARD;
00666                 }
00667                 break;
00668 
00669             default:
00670                 Log2(PCSC_LOG_ERROR,
00671                     "invalid retcode from RFCheckReaderEventState (%X)", rv);
00672                 return SCARD_F_INTERNAL_ERROR;
00673                 break;
00674         }
00675 
00676         do_sleep = 1;
00677     }
00678     else
00679         if (dwInitialization == SCARD_LEAVE_CARD)
00680         {
00681             /*
00682              * Do nothing
00683              */
00684             do_sleep = 0;
00685         }
00686 
00687     /*******************************************
00688      *
00689      * This section tries to decode the ATR
00690      * and set up which protocol to use
00691      *
00692      *******************************************/
00693     if (dwPreferredProtocols & SCARD_PROTOCOL_RAW)
00694         rContext->readerState->cardProtocol = SCARD_PROTOCOL_RAW;
00695     else
00696     {
00697         if (dwShareMode != SCARD_SHARE_DIRECT)
00698         {
00699             /* the protocol is not yet set (no PPS yet) */
00700             if (SCARD_PROTOCOL_UNDEFINED == rContext->readerState->cardProtocol)
00701             {
00702                 UCHAR ucAvailable, ucDefault;
00703                 int ret;
00704 
00705                 ucDefault = PHGetDefaultProtocol(rContext->readerState->cardAtr,
00706                     rContext->readerState->cardAtrLength);
00707                 ucAvailable =
00708                     PHGetAvailableProtocols(rContext->readerState->cardAtr,
00709                             rContext->readerState->cardAtrLength);
00710 
00711                 /* If it is set to ANY let it do any of the protocols */
00712                 if (dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)
00713                     dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
00714 
00715                 ret = PHSetProtocol(rContext, dwPreferredProtocols,
00716                     ucAvailable, ucDefault);
00717 
00718                 /* keep cardProtocol = SCARD_PROTOCOL_UNDEFINED in case of error  */
00719                 if (SET_PROTOCOL_PPS_FAILED == ret)
00720                     return SCARD_W_UNRESPONSIVE_CARD;
00721 
00722                 if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
00723                     return SCARD_E_PROTO_MISMATCH;
00724 
00725                 /* use negociated protocol */
00726                 rContext->readerState->cardProtocol = ret;
00727             }
00728             else
00729             {
00730                 if (! (dwPreferredProtocols & rContext->readerState->cardProtocol))
00731                     return SCARD_E_PROTO_MISMATCH;
00732             }
00733         }
00734     }
00735 
00736     *pdwActiveProtocol = rContext->readerState->cardProtocol;
00737 
00738     if (dwShareMode == SCARD_SHARE_EXCLUSIVE)
00739     {
00740         if (rContext->dwContexts == SCARD_EXCLUSIVE_CONTEXT)
00741         {
00742             /*
00743              * Do nothing - we are already exclusive
00744              */
00745         } else
00746         {
00747             if (rContext->dwContexts == SCARD_LAST_CONTEXT)
00748             {
00749                 rContext->dwContexts = SCARD_EXCLUSIVE_CONTEXT;
00750                 RFLockSharing(hCard);
00751             } else
00752             {
00753                 return SCARD_E_SHARING_VIOLATION;
00754             }
00755         }
00756     } else if (dwShareMode == SCARD_SHARE_SHARED)
00757     {
00758         if (rContext->dwContexts != SCARD_EXCLUSIVE_CONTEXT)
00759         {
00760             /*
00761              * Do nothing - in sharing mode already
00762              */
00763         } else
00764         {
00765             /*
00766              * We are in exclusive mode but want to share now
00767              */
00768             RFUnlockSharing(hCard);
00769             rContext->dwContexts = SCARD_LAST_CONTEXT;
00770         }
00771     } else if (dwShareMode == SCARD_SHARE_DIRECT)
00772     {
00773         if (rContext->dwContexts != SCARD_EXCLUSIVE_CONTEXT)
00774         {
00775             /*
00776              * Do nothing - in sharing mode already
00777              */
00778         } else
00779         {
00780             /*
00781              * We are in exclusive mode but want to share now
00782              */
00783             RFUnlockSharing(hCard);
00784             rContext->dwContexts = SCARD_LAST_CONTEXT;
00785         }
00786     } else
00787         return SCARD_E_INVALID_VALUE;
00788 
00789     /*
00790      * Clear a previous event to the application
00791      */
00792     RFClearReaderEventState(rContext, hCard);
00793 
00794     /*
00795      * Allow the status thread to convey information
00796      */
00797     if (do_sleep)
00798         SYS_USleep(PCSCLITE_STATUS_POLL_RATE + 10);
00799 
00800     return SCARD_S_SUCCESS;
00801 }
00802 
00803 LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
00804 {
00805     LONG rv;
00806     PREADER_CONTEXT rContext = NULL;
00807 
00808     if (hCard == 0)
00809         return SCARD_E_INVALID_HANDLE;
00810 
00811     rv = RFReaderInfoById(hCard, &rContext);
00812     if (rv != SCARD_S_SUCCESS)
00813         return rv;
00814 
00815     rv = RFFindReaderHandle(hCard);
00816     if (rv != SCARD_S_SUCCESS)
00817         return rv;
00818 
00819     if ((dwDisposition != SCARD_LEAVE_CARD)
00820         && (dwDisposition != SCARD_UNPOWER_CARD)
00821         && (dwDisposition != SCARD_RESET_CARD)
00822         && (dwDisposition != SCARD_EJECT_CARD))
00823         return SCARD_E_INVALID_VALUE;
00824 
00825     /*
00826      * wait until a possible transaction is finished
00827      */
00828     if ((dwDisposition != SCARD_LEAVE_CARD) && (rContext->dwLockId != 0)
00829         && (rContext->dwLockId != hCard))
00830     {
00831         Log1(PCSC_LOG_INFO, "Waiting for release of lock");
00832         while (rContext->dwLockId != 0)
00833             SYS_USleep(PCSCLITE_LOCK_POLL_RATE);
00834         Log1(PCSC_LOG_INFO, "Lock released");
00835     }
00836 
00837     /* the reader has been removed while we were waiting */
00838     if (NULL == rContext->readerState)
00839         return SCARD_E_NO_SMARTCARD;
00840 
00841     /*
00842      * Unlock any blocks on this context
00843      */
00844     rv = RFUnlockSharing(hCard);
00845     if (rv != SCARD_S_SUCCESS)
00846         return rv;
00847 
00848     Log2(PCSC_LOG_DEBUG, "Active Contexts: %d", rContext->dwContexts);
00849 
00850     if (dwDisposition == SCARD_RESET_CARD ||
00851         dwDisposition == SCARD_UNPOWER_CARD)
00852     {
00853         /*
00854          * Currently pcsc-lite keeps the card powered constantly
00855          */
00856         if (SCARD_RESET_CARD == dwDisposition)
00857             rv = IFDPowerICC(rContext, IFD_RESET,
00858                 rContext->readerState->cardAtr,
00859                 &rContext->readerState->cardAtrLength);
00860         else
00861         {
00862             rv = IFDPowerICC(rContext, IFD_POWER_DOWN,
00863                 rContext->readerState->cardAtr,
00864                 &rContext->readerState->cardAtrLength);
00865             rv = IFDPowerICC(rContext, IFD_POWER_UP,
00866                 rContext->readerState->cardAtr,
00867                 &rContext->readerState->cardAtrLength);
00868         }
00869 
00870         /* the protocol is unset after a power on */
00871         rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00872 
00873         /*
00874          * Notify the card has been reset
00875          */
00876         RFSetReaderEventState(rContext, SCARD_RESET);
00877 
00878         /*
00879          * Set up the status bit masks on dwStatus
00880          */
00881         if (rv == SCARD_S_SUCCESS)
00882         {
00883             rContext->readerState->readerState |= SCARD_PRESENT;
00884             rContext->readerState->readerState &= ~SCARD_ABSENT;
00885             rContext->readerState->readerState |= SCARD_POWERED;
00886             rContext->readerState->readerState |= SCARD_NEGOTIABLE;
00887             rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00888             rContext->readerState->readerState &= ~SCARD_SWALLOWED;
00889             rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00890         }
00891         else
00892         {
00893             if (rContext->readerState->readerState & SCARD_ABSENT)
00894                 rContext->readerState->readerState &= ~SCARD_PRESENT;
00895             else
00896                 rContext->readerState->readerState |= SCARD_PRESENT;
00897             /* SCARD_ABSENT flag is already set */
00898             rContext->readerState->readerState |= SCARD_SWALLOWED;
00899             rContext->readerState->readerState &= ~SCARD_POWERED;
00900             rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
00901             rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00902             rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00903             rContext->readerState->cardAtrLength = 0;
00904         }
00905 
00906         if (rContext->readerState->cardAtrLength > 0)
00907             Log1(PCSC_LOG_DEBUG, "Reset complete.");
00908         else
00909             Log1(PCSC_LOG_ERROR, "Error resetting card.");
00910 
00911         /*
00912          * Allow the status thread to convey information
00913          */
00914         SYS_USleep(PCSCLITE_STATUS_POLL_RATE + 10);
00915     }
00916     else if (dwDisposition == SCARD_EJECT_CARD)
00917     {
00918         UCHAR controlBuffer[5];
00919         UCHAR receiveBuffer[MAX_BUFFER_SIZE];
00920         DWORD receiveLength;
00921 
00922         /*
00923          * Set up the CTBCS command for Eject ICC
00924          */
00925         controlBuffer[0] = 0x20;
00926         controlBuffer[1] = 0x15;
00927         controlBuffer[2] = (rContext->dwSlot & 0x0000FFFF) + 1;
00928         controlBuffer[3] = 0x00;
00929         controlBuffer[4] = 0x00;
00930         receiveLength = 2;
00931         rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
00932             &receiveLength);
00933 
00934         if (rv == SCARD_S_SUCCESS)
00935         {
00936             if (receiveLength == 2 && receiveBuffer[0] == 0x90)
00937             {
00938                 Log1(PCSC_LOG_DEBUG, "Card ejected successfully.");
00939                 /*
00940                  * Successful
00941                  */
00942             }
00943             else
00944                 Log1(PCSC_LOG_ERROR, "Error ejecting card.");
00945         }
00946         else
00947             Log1(PCSC_LOG_ERROR, "Error ejecting card.");
00948 
00949     }
00950     else if (dwDisposition == SCARD_LEAVE_CARD)
00951     {
00952         /*
00953          * Do nothing
00954          */
00955     }
00956 
00957     /*
00958      * Remove and destroy this handle
00959      */
00960     RFRemoveReaderHandle(rContext, hCard);
00961     RFDestroyReaderHandle(hCard);
00962 
00963     /*
00964      * For exclusive connection reset it to no connections
00965      */
00966     if (rContext->dwContexts == SCARD_EXCLUSIVE_CONTEXT)
00967     {
00968         rContext->dwContexts = SCARD_NO_CONTEXT;
00969         return SCARD_S_SUCCESS;
00970     }
00971 
00972     /*
00973      * Remove a connection from the context stack
00974      */
00975     rContext->dwContexts -= 1;
00976 
00977     if (rContext->dwContexts < 0)
00978         rContext->dwContexts = 0;
00979 
00980     return SCARD_S_SUCCESS;
00981 }
00982 
00983 LONG SCardBeginTransaction(SCARDHANDLE hCard)
00984 {
00985     LONG rv;
00986     PREADER_CONTEXT rContext;
00987 
00988     if (hCard == 0)
00989         return SCARD_E_INVALID_HANDLE;
00990 
00991     rv = RFReaderInfoById(hCard, &rContext);
00992 
00993     /*
00994      * Cannot find the hCard in this context
00995      */
00996     if (rv != SCARD_S_SUCCESS)
00997         return rv;
00998 
00999     /*
01000      * Make sure the reader is working properly
01001      */
01002     rv = RFCheckReaderStatus(rContext);
01003     if (rv != SCARD_S_SUCCESS)
01004         return rv;
01005 
01006     rv = RFFindReaderHandle(hCard);
01007     if (rv != SCARD_S_SUCCESS)
01008         return rv;
01009 
01010     /*
01011      * Make sure some event has not occurred
01012      */
01013     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01014         return rv;
01015 
01016     rv = RFLockSharing(hCard);
01017 
01018     /* if the transaction is not yet ready we sleep a bit so the client
01019      * do not retry immediately */
01020     if (SCARD_E_SHARING_VIOLATION == rv)
01021         SYS_USleep(PCSCLITE_LOCK_POLL_RATE);
01022 
01023     Log2(PCSC_LOG_DEBUG, "Status: 0x%08X", rv);
01024 
01025     return rv;
01026 }
01027 
01028 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
01029 {
01030     LONG rv;
01031     PREADER_CONTEXT rContext = NULL;
01032 
01033     /*
01034      * Ignoring dwDisposition for now
01035      */
01036     if (hCard == 0)
01037         return SCARD_E_INVALID_HANDLE;
01038 
01039     if ((dwDisposition != SCARD_LEAVE_CARD)
01040         && (dwDisposition != SCARD_UNPOWER_CARD)
01041         && (dwDisposition != SCARD_RESET_CARD)
01042         && (dwDisposition != SCARD_EJECT_CARD))
01043     return SCARD_E_INVALID_VALUE;
01044 
01045     rv = RFReaderInfoById(hCard, &rContext);
01046 
01047     /*
01048      * Cannot find the hCard in this context
01049      */
01050     if (rv != SCARD_S_SUCCESS)
01051         return rv;
01052 
01053     rv = RFFindReaderHandle(hCard);
01054     if (rv != SCARD_S_SUCCESS)
01055         return rv;
01056 
01057     /*
01058      * Make sure some event has not occurred
01059      */
01060     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01061         return rv;
01062 
01063     if (dwDisposition == SCARD_RESET_CARD ||
01064         dwDisposition == SCARD_UNPOWER_CARD)
01065     {
01066         /*
01067          * Currently pcsc-lite keeps the card always powered
01068          */
01069         if (SCARD_RESET_CARD == dwDisposition)
01070             rv = IFDPowerICC(rContext, IFD_RESET,
01071                 rContext->readerState->cardAtr,
01072                 &rContext->readerState->cardAtrLength);
01073         else
01074         {
01075             rv = IFDPowerICC(rContext, IFD_POWER_DOWN,
01076                 rContext->readerState->cardAtr,
01077                 &rContext->readerState->cardAtrLength);
01078             rv = IFDPowerICC(rContext, IFD_POWER_UP,
01079                 rContext->readerState->cardAtr,
01080                 &rContext->readerState->cardAtrLength);
01081         }
01082 
01083         /* the protocol is unset after a power on */
01084         rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
01085 
01086         /*
01087          * Notify the card has been reset
01088          */
01089         RFSetReaderEventState(rContext, SCARD_RESET);
01090 
01091         /*
01092          * Set up the status bit masks on dwStatus
01093          */
01094         if (rv == SCARD_S_SUCCESS)
01095         {
01096             rContext->readerState->readerState |= SCARD_PRESENT;
01097             rContext->readerState->readerState &= ~SCARD_ABSENT;
01098             rContext->readerState->readerState |= SCARD_POWERED;
01099             rContext->readerState->readerState |= SCARD_NEGOTIABLE;
01100             rContext->readerState->readerState &= ~SCARD_SPECIFIC;
01101             rContext->readerState->readerState &= ~SCARD_SWALLOWED;
01102             rContext->readerState->readerState &= ~SCARD_UNKNOWN;
01103         }
01104         else
01105         {
01106             if (rContext->readerState->readerState & SCARD_ABSENT)
01107                 rContext->readerState->readerState &= ~SCARD_PRESENT;
01108             else
01109                 rContext->readerState->readerState |= SCARD_PRESENT;
01110             /* SCARD_ABSENT flag is already set */
01111             rContext->readerState->readerState |= SCARD_SWALLOWED;
01112             rContext->readerState->readerState &= ~SCARD_POWERED;
01113             rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
01114             rContext->readerState->readerState &= ~SCARD_SPECIFIC;
01115             rContext->readerState->readerState &= ~SCARD_UNKNOWN;
01116             rContext->readerState->cardAtrLength = 0;
01117         }
01118 
01119         if (rContext->readerState->cardAtrLength > 0)
01120             Log1(PCSC_LOG_DEBUG, "Reset complete.");
01121         else
01122             Log1(PCSC_LOG_ERROR, "Error resetting card.");
01123 
01124     }
01125     else if (dwDisposition == SCARD_EJECT_CARD)
01126     {
01127         UCHAR controlBuffer[5];
01128         UCHAR receiveBuffer[MAX_BUFFER_SIZE];
01129         DWORD receiveLength;
01130 
01131         /*
01132          * Set up the CTBCS command for Eject ICC
01133          */
01134         controlBuffer[0] = 0x20;
01135         controlBuffer[1] = 0x15;
01136         controlBuffer[2] = (rContext->dwSlot & 0x0000FFFF) + 1;
01137         controlBuffer[3] = 0x00;
01138         controlBuffer[4] = 0x00;
01139         receiveLength = 2;
01140         rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
01141             &receiveLength);
01142 
01143         if (rv == SCARD_S_SUCCESS)
01144         {
01145             if (receiveLength == 2 && receiveBuffer[0] == 0x90)
01146             {
01147                 Log1(PCSC_LOG_DEBUG, "Card ejected successfully.");
01148                 /*
01149                  * Successful
01150                  */
01151             }
01152             else
01153                 Log1(PCSC_LOG_ERROR, "Error ejecting card.");
01154         }
01155         else
01156             Log1(PCSC_LOG_ERROR, "Error ejecting card.");
01157 
01158     }
01159     else if (dwDisposition == SCARD_LEAVE_CARD)
01160     {
01161         /*
01162          * Do nothing
01163          */
01164     }
01165 
01166     /*
01167      * Unlock any blocks on this context
01168      */
01169     RFUnlockSharing(hCard);
01170 
01171     Log2(PCSC_LOG_DEBUG, "Status: 0x%08X", rv);
01172 
01173     return rv;
01174 }
01175 
01176 LONG SCardCancelTransaction(SCARDHANDLE hCard)
01177 {
01178     LONG rv;
01179     PREADER_CONTEXT rContext = NULL;
01180 
01181     /*
01182      * Ignoring dwDisposition for now
01183      */
01184     if (hCard == 0)
01185         return SCARD_E_INVALID_HANDLE;
01186 
01187     rv = RFReaderInfoById(hCard, &rContext);
01188 
01189     /*
01190      * Cannot find the hCard in this context
01191      */
01192     if (rv != SCARD_S_SUCCESS)
01193         return rv;
01194 
01195     rv = RFFindReaderHandle(hCard);
01196     if (rv != SCARD_S_SUCCESS)
01197         return rv;
01198 
01199     /*
01200      * Make sure some event has not occurred
01201      */
01202     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01203         return rv;
01204 
01205     rv = RFUnlockSharing(hCard);
01206 
01207     Log2(PCSC_LOG_DEBUG, "Status: 0x%08X", rv);
01208 
01209     return rv;
01210 }
01211 
01212 LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderNames,
01213     LPDWORD pcchReaderLen, LPDWORD pdwState,
01214     LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
01215 {
01216     LONG rv;
01217     PREADER_CONTEXT rContext = NULL;
01218 
01219     if (hCard == 0)
01220         return SCARD_E_INVALID_HANDLE;
01221 
01222     rv = RFReaderInfoById(hCard, &rContext);
01223 
01224     /*
01225      * Cannot find the hCard in this context
01226      */
01227     if (rv != SCARD_S_SUCCESS)
01228         return rv;
01229 
01230     if (strlen(rContext->lpcReader) > MAX_BUFFER_SIZE
01231             || rContext->readerState->cardAtrLength > MAX_ATR_SIZE)
01232         return SCARD_F_INTERNAL_ERROR;
01233 
01234     /*
01235      * This is a client side function however the server maintains the
01236      * list of events between applications so it must be passed through to
01237      * obtain this event if it has occurred
01238      */
01239 
01240     /*
01241      * Make sure some event has not occurred
01242      */
01243     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01244         return rv;
01245 
01246     /*
01247      * Make sure the reader is working properly
01248      */
01249     rv = RFCheckReaderStatus(rContext);
01250     if (rv != SCARD_S_SUCCESS)
01251         return rv;
01252 
01253     if (mszReaderNames)
01254     {  /* want reader name */
01255         if (pcchReaderLen)
01256         { /* & present reader name length */
01257             if (*pcchReaderLen >= strlen(rContext->lpcReader))
01258             { /* & enough room */
01259                 *pcchReaderLen = strlen(rContext->lpcReader);
01260                 strncpy(mszReaderNames, rContext->lpcReader, MAX_READERNAME);
01261             }
01262             else
01263             {        /* may report only reader name len */
01264                 *pcchReaderLen = strlen(rContext->lpcReader);
01265                 rv = SCARD_E_INSUFFICIENT_BUFFER;
01266             }
01267         }
01268         else
01269         {            /* present buf & no buflen */
01270             return SCARD_E_INVALID_PARAMETER;
01271         }
01272     }
01273     else
01274     {
01275         if (pcchReaderLen)
01276         { /* want reader len only */
01277             *pcchReaderLen = strlen(rContext->lpcReader);
01278         }
01279         else
01280         {
01281         /* nothing todo */
01282         }
01283     }
01284 
01285     if (pdwState)
01286         *pdwState = rContext->readerState->readerState;
01287 
01288     if (pdwProtocol)
01289         *pdwProtocol = rContext->readerState->cardProtocol;
01290 
01291     if (pbAtr)
01292     {  /* want ATR */
01293         if (pcbAtrLen)
01294         { /* & present ATR length */
01295             if (*pcbAtrLen >= rContext->readerState->cardAtrLength)
01296             { /* & enough room */
01297                 *pcbAtrLen = rContext->readerState->cardAtrLength;
01298                 memcpy(pbAtr, rContext->readerState->cardAtr,
01299                     rContext->readerState->cardAtrLength);
01300             }
01301             else
01302             { /* may report only ATR len */
01303                 *pcbAtrLen = rContext->readerState->cardAtrLength;
01304                 rv = SCARD_E_INSUFFICIENT_BUFFER;
01305             }
01306         }
01307         else
01308         { /* present buf & no buflen */
01309             return SCARD_E_INVALID_PARAMETER;
01310         }
01311     }
01312     else
01313     {
01314         if (pcbAtrLen)
01315         { /* want ATR len only */
01316             *pcbAtrLen = rContext->readerState->cardAtrLength;
01317         }
01318         else
01319         {
01320             /* nothing todo */
01321         }
01322     }
01323 
01324     return rv;
01325 }
01326 
01327 LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout,
01328     LPSCARD_READERSTATE_A rgReaderStates, DWORD cReaders)
01329 {
01330     /*
01331      * Client side function
01332      */
01333     return SCARD_S_SUCCESS;
01334 }
01335 
01336 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode,
01337     LPCVOID pbSendBuffer, DWORD cbSendLength,
01338     LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned)
01339 {
01340     LONG rv;
01341     PREADER_CONTEXT rContext = NULL;
01342 
01343     /* 0 bytes returned by default */
01344     *lpBytesReturned = 0;
01345 
01346     if (0 == hCard)
01347         return SCARD_E_INVALID_HANDLE;
01348 
01349     /*
01350      * Make sure no one has a lock on this reader
01351      */
01352     if ((rv = RFCheckSharing(hCard)) != SCARD_S_SUCCESS)
01353         return rv;
01354 
01355     rv = RFReaderInfoById(hCard, &rContext);
01356     if (rv != SCARD_S_SUCCESS)
01357         return rv;
01358 
01359     if (IFD_HVERSION_2_0 == rContext->dwVersion)
01360         if (NULL == pbSendBuffer || 0 == cbSendLength)
01361             return SCARD_E_INVALID_PARAMETER;
01362 
01363     /*
01364      * Make sure the reader is working properly
01365      */
01366     rv = RFCheckReaderStatus(rContext);
01367     if (rv != SCARD_S_SUCCESS)
01368         return rv;
01369 
01370     rv = RFFindReaderHandle(hCard);
01371     if (rv != SCARD_S_SUCCESS)
01372         return rv;
01373 
01374     /*
01375      * Make sure some event has not occurred
01376      */
01377     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01378         return rv;
01379 
01380     if (IFD_HVERSION_2_0 == rContext->dwVersion)
01381     {
01382         /* we must wrap a API 3.0 client in an API 2.0 driver */
01383         *lpBytesReturned = cbRecvLength;
01384         return IFDControl_v2(rContext, (PUCHAR)pbSendBuffer,
01385             cbSendLength, pbRecvBuffer, lpBytesReturned);
01386     }
01387     else
01388         if (IFD_HVERSION_3_0 == rContext->dwVersion)
01389             return IFDControl(rContext, dwControlCode, pbSendBuffer,
01390                 cbSendLength, pbRecvBuffer, cbRecvLength, lpBytesReturned);
01391         else
01392             return SCARD_E_UNSUPPORTED_FEATURE;
01393 }
01394 
01395 LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
01396     LPBYTE pbAttr, LPDWORD pcbAttrLen)
01397 {
01398     LONG rv;
01399     PREADER_CONTEXT rContext = NULL;
01400 
01401     if (0 == hCard)
01402         return SCARD_E_INVALID_HANDLE;
01403 
01404     /*
01405      * Make sure no one has a lock on this reader
01406      */
01407     if ((rv = RFCheckSharing(hCard)) != SCARD_S_SUCCESS)
01408         return rv;
01409 
01410     rv = RFReaderInfoById(hCard, &rContext);
01411     if (rv != SCARD_S_SUCCESS)
01412         return rv;
01413 
01414     /*
01415      * Make sure the reader is working properly
01416      */
01417     rv = RFCheckReaderStatus(rContext);
01418     if (rv != SCARD_S_SUCCESS)
01419         return rv;
01420 
01421     rv = RFFindReaderHandle(hCard);
01422     if (rv != SCARD_S_SUCCESS)
01423         return rv;
01424 
01425     /*
01426      * Make sure some event has not occurred
01427      */
01428     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01429         return rv;
01430 
01431     rv = IFDGetCapabilities(rContext, dwAttrId, pcbAttrLen, pbAttr);
01432     if (rv == IFD_SUCCESS)
01433         return SCARD_S_SUCCESS;
01434     else
01435         if (rv == IFD_ERROR_TAG)
01436             return SCARD_E_UNSUPPORTED_FEATURE;
01437         else
01438             return SCARD_E_NOT_TRANSACTED;
01439 }
01440 
01441 LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
01442     LPCBYTE pbAttr, DWORD cbAttrLen)
01443 {
01444     LONG rv;
01445     PREADER_CONTEXT rContext = NULL;
01446 
01447     if (0 == hCard)
01448         return SCARD_E_INVALID_HANDLE;
01449 
01450     /*
01451      * Make sure no one has a lock on this reader
01452      */
01453     if ((rv = RFCheckSharing(hCard)) != SCARD_S_SUCCESS)
01454         return rv;
01455 
01456     rv = RFReaderInfoById(hCard, &rContext);
01457     if (rv != SCARD_S_SUCCESS)
01458         return rv;
01459 
01460     /*
01461      * Make sure the reader is working properly
01462      */
01463     rv = RFCheckReaderStatus(rContext);
01464     if (rv != SCARD_S_SUCCESS)
01465         return rv;
01466 
01467     rv = RFFindReaderHandle(hCard);
01468     if (rv != SCARD_S_SUCCESS)
01469         return rv;
01470 
01471     /*
01472      * Make sure some event has not occurred
01473      */
01474     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01475         return rv;
01476 
01477     rv = IFDSetCapabilities(rContext, dwAttrId, cbAttrLen, (PUCHAR)pbAttr);
01478     if (rv == IFD_SUCCESS)
01479         return SCARD_S_SUCCESS;
01480     else
01481         if (rv == IFD_ERROR_TAG)
01482             return SCARD_E_UNSUPPORTED_FEATURE;
01483         else
01484             return SCARD_E_NOT_TRANSACTED;
01485 }
01486 
01487 LONG SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci,
01488     LPCBYTE pbSendBuffer, DWORD cbSendLength,
01489     LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer,
01490     LPDWORD pcbRecvLength)
01491 {
01492     LONG rv;
01493     PREADER_CONTEXT rContext = NULL;
01494     SCARD_IO_HEADER sSendPci, sRecvPci;
01495     DWORD dwRxLength, tempRxLength;
01496 
01497     if (pcbRecvLength == 0)
01498         return SCARD_E_INVALID_PARAMETER;
01499 
01500     dwRxLength = *pcbRecvLength;
01501     *pcbRecvLength = 0;
01502 
01503     if (hCard == 0)
01504         return SCARD_E_INVALID_HANDLE;
01505 
01506     if (pbSendBuffer == NULL || pbRecvBuffer == NULL || pioSendPci == NULL)
01507         return SCARD_E_INVALID_PARAMETER;
01508 
01509     /*
01510      * Must at least send a 4 bytes APDU
01511      */
01512     if (cbSendLength < 4)
01513         return SCARD_E_INVALID_PARAMETER;
01514 
01515     /*
01516      * Must at least have 2 status words even for SCardControl
01517      */
01518     if (dwRxLength < 2)
01519         return SCARD_E_INSUFFICIENT_BUFFER;
01520 
01521     /*
01522      * Make sure no one has a lock on this reader
01523      */
01524     if ((rv = RFCheckSharing(hCard)) != SCARD_S_SUCCESS)
01525         return rv;
01526 
01527     rv = RFReaderInfoById(hCard, &rContext);
01528     if (rv != SCARD_S_SUCCESS)
01529         return rv;
01530 
01531     /*
01532      * Make sure the reader is working properly
01533      */
01534     rv = RFCheckReaderStatus(rContext);
01535     if (rv != SCARD_S_SUCCESS)
01536         return rv;
01537 
01538     rv = RFFindReaderHandle(hCard);
01539     if (rv != SCARD_S_SUCCESS)
01540         return rv;
01541 
01542     /*
01543      * Make sure some event has not occurred
01544      */
01545     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01546         return rv;
01547 
01548     /*
01549      * Check for some common errors
01550      */
01551     if (pioSendPci->dwProtocol != SCARD_PROTOCOL_RAW)
01552     {
01553         if (rContext->readerState->readerState & SCARD_ABSENT)
01554         {
01555             return SCARD_E_NO_SMARTCARD;
01556         }
01557     }
01558 
01559     if (pioSendPci->dwProtocol != SCARD_PROTOCOL_RAW)
01560     {
01561         if (pioSendPci->dwProtocol != SCARD_PROTOCOL_ANY_OLD)
01562         {
01563             if (pioSendPci->dwProtocol != rContext->readerState->cardProtocol)
01564             {
01565                 return SCARD_E_PROTO_MISMATCH;
01566             }
01567         }
01568     }
01569 
01570     /*
01571      * Quick fix: PC/SC starts at 1 for bit masking but the IFD_Handler
01572      * just wants 0 or 1
01573      */
01574 
01575     sSendPci.Protocol = 0; /* protocol T=0 by default */
01576 
01577     if (pioSendPci->dwProtocol == SCARD_PROTOCOL_T1)
01578     {
01579         sSendPci.Protocol = 1;
01580     } else if (pioSendPci->dwProtocol == SCARD_PROTOCOL_RAW)
01581     {
01582         /*
01583          * This is temporary ......
01584          */
01585         sSendPci.Protocol = SCARD_PROTOCOL_RAW;
01586     } else if (pioSendPci->dwProtocol == SCARD_PROTOCOL_ANY_OLD)
01587     {
01588       /* Fix by Amira (Athena) */
01589         unsigned long i;
01590         unsigned long prot = rContext->readerState->cardProtocol;
01591 
01592         for (i = 0 ; prot != 1 ; i++)
01593             prot >>= 1;
01594 
01595         sSendPci.Protocol = i;
01596     }
01597 
01598     sSendPci.Length = pioSendPci->cbPciLength;
01599 
01600     /* the protocol number is decoded a few lines above */
01601     Log2(PCSC_LOG_DEBUG, "Send Protocol: T=%d", sSendPci.Protocol);
01602 
01603     tempRxLength = dwRxLength;
01604 
01605     if (pioSendPci->dwProtocol == SCARD_PROTOCOL_RAW)
01606     {
01607         rv = IFDControl_v2(rContext, (PUCHAR) pbSendBuffer, cbSendLength,
01608             pbRecvBuffer, &dwRxLength);
01609     } else
01610     {
01611         rv = IFDTransmit(rContext, sSendPci, (PUCHAR) pbSendBuffer,
01612             cbSendLength, pbRecvBuffer, &dwRxLength, &sRecvPci);
01613     }
01614 
01615     if (pioRecvPci)
01616     {
01617         pioRecvPci->dwProtocol = sRecvPci.Protocol;
01618         pioRecvPci->cbPciLength = sRecvPci.Length;
01619     }
01620 
01621     /*
01622      * Check for any errors that might have occurred
01623      */
01624 
01625     if (rv != SCARD_S_SUCCESS)
01626     {
01627         *pcbRecvLength = 0;
01628         Log2(PCSC_LOG_ERROR, "Card not transacted: 0x%08lX", rv);
01629         return SCARD_E_NOT_TRANSACTED;
01630     }
01631 
01632     /*
01633      * Available is less than received
01634      */
01635     if (tempRxLength < dwRxLength)
01636     {
01637         *pcbRecvLength = 0;
01638         return SCARD_E_INSUFFICIENT_BUFFER;
01639     }
01640 
01641     /*
01642      * Successful return
01643      */
01644     *pcbRecvLength = dwRxLength;
01645     return SCARD_S_SUCCESS;
01646 }
01647 
01648 LONG SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups,
01649     LPSTR mszReaders, LPDWORD pcchReaders)
01650 {
01651     /*
01652      * Client side function
01653      */
01654     return SCARD_S_SUCCESS;
01655 }
01656 
01657 LONG SCardCancel(SCARDCONTEXT hContext)
01658 {
01659     /*
01660      * Client side function
01661      */
01662     return SCARD_S_SUCCESS;
01663 }
01664 

Generated on Wed Dec 21 12:23:40 2011 for pcsc-lite by  doxygen 1.4.7