winscard_scf.c

Go to the documentation of this file.
00001 /*
00002  * MUSCLE SmartCard Development ( http://www.linuxnet.com )
00003  *
00004  * Copyright (C) 2002
00005  *  David Corcoran <corcoran@linuxnet.com>
00006  *  Najam Siddiqui
00007  * Copyright (C) 2005
00008  *  Ludovic Rousseau <ludovic.rousseau@free.fr>
00009  *
00010  * $Id: winscard_scf.c 2151 2006-09-06 20:02:47Z rousseau $
00011  */
00012 
00018 #include "config.h"
00019 #include <stdlib.h>
00020 #include <string.h>
00021 #include <sys/types.h>
00022 #include <fcntl.h>
00023 #include <unistd.h>
00024 #include <sys/un.h>
00025 #include <smartcard/scf.h>
00026 #include <time.h>
00027 
00028 #include "pcsclite.h"
00029 #include "winscard.h"
00030 #include "debug.h"
00031 
00032 #include "thread_generic.h"
00033 
00034 #include "readerfactory.h"
00035 #include "eventhandler.h"
00036 #include "sys_generic.h"
00037 
00038 #define TRUE    1
00039 #define FALSE   0
00040 
00041 #undef PCSCLITE_MAX_READERS_CONTEXTS
00042 #define PCSCLITE_MAX_READERS_CONTEXTS   2
00043 
00044 /* Global session to manage Readers, Card events. */
00045 static SCF_Session_t g_hSession = NULL;
00046 
00047 /* Have to define this because they are defined in pcsclite.h as externs */
00048 SCARD_IO_REQUEST g_rgSCardT0Pci, g_rgSCardT1Pci, g_rgSCardRawPci;
00049 
00050 static struct _psTransmitMap
00051 {
00052     BYTE Buffer[266];
00053     int isResponseCached;
00054     LONG bufferLength;
00055 } psTransmitMap[PCSCLITE_MAX_APPLICATION_CONTEXTS];
00056 
00057 /* Channel Map to manage Card Connections. */
00058 static struct _psChannelMap
00059 {
00060     SCARDHANDLE PCSC_hCard;
00061     SCARDCONTEXT hContext;
00062     SCF_Session_t hSession;
00063     SCF_Terminal_t hTerminal;
00064     SCF_Card_t SCF_hCard;
00065     short haveLock;
00066     short isReset;
00067     int ReaderIndice;
00068 } psChannelMap[PCSCLITE_MAX_APPLICATION_CONTEXTS];
00069 
00070 /* Context Map to manage contexts and sessions. */
00071 static struct _psContextMap
00072 {
00073     SCARDCONTEXT hContext;
00074     SCF_Session_t hSession;
00075     DWORD contextBlockStatus;
00076 } psContextMap[PCSCLITE_MAX_APPLICATION_CONTEXTS];
00077 
00078 /* Reader Map to handle Status and GetStatusChange. */
00079 static struct _psReaderMap
00080 {
00081     SCF_Terminal_t hTerminal;
00082     LPSTR ReaderName;
00083     short SharedRefCount;
00084     DWORD dwCurrentState;
00085     BYTE bAtr[MAX_ATR_SIZE];
00086     DWORD dwAtrLength;
00087     SCF_ListenerHandle_t lHandle;
00088 } psReaderMap[PCSCLITE_MAX_READERS_CONTEXTS];
00089 
00090 static PCSCLITE_MUTEX clientMutex = PTHREAD_MUTEX_INITIALIZER;
00091 
00092 /*
00093  * Mutex for the Smardcard Event Handling, different from client Mutex
00094  * because event reporting from the ocfserver is done using a single thread,
00095  * so to get lock on the clientMutex may affect the performance of the ocf server.
00096  */
00097 static PCSCLITE_MUTEX EventMutex = PTHREAD_MUTEX_INITIALIZER;
00098 static PCSCLITE_MUTEX SCFInitMutex = PTHREAD_MUTEX_INITIALIZER;
00099 static pthread_cond_t EventCondition = PTHREAD_COND_INITIALIZER;
00100 static char PCSC_Initialized = 0;
00101 
00102 static LONG isOCFServerRunning(void);
00103 LONG SCardLockThread(void);
00104 LONG SCardUnlockThread(void);
00105 LONG SCardEventLock(void);
00106 LONG SCardEventUnlock(void);
00107 static LONG PCSC_SCF_Initialize(void);
00108 static void EventCallback(SCF_Event_t eventType, SCF_Terminal_t hTerm,
00109     void *cbdata);
00110 static LONG PCSC_SCF_getATR(SCF_Card_t hCard, LPBYTE pcbAtr,
00111     LPDWORD pcbAtrLen);
00112 
00113 static LONG ConvertStatus(SCF_Status_t status);
00114 static LONG SCardGetReaderIndice(LPCSTR ReaderName);
00115 static LONG getNewContext(SCARDCONTEXT * phContext);
00116 static LONG SCardAddContext(SCARDCONTEXT hContext, SCF_Session_t hSession);
00117 static SCF_Session_t getSessionForContext(SCARDCONTEXT hContext);
00118 static LONG SCardRemoveContext(SCARDCONTEXT hContext);
00119 static LONG SCardGetContextIndice(SCARDCONTEXT hContext);
00120 
00121 static LONG getNewHandle(SCARDCONTEXT hContext, LPCSTR szReader,
00122     SCARDHANDLE * phCard, DWORD);
00123 static LONG getCardForHandle(SCARDHANDLE PSCS_hCard, SCF_Card_t * SCF_hCard);
00124 static LONG SCardRemoveHandle(SCARDHANDLE hCard);
00125 static LONG SCardAddHandle(SCARDHANDLE PCSC_hCard, SCARDCONTEXT hContext,
00126     SCF_Session_t hSession, SCF_Terminal_t hTerminal,
00127     SCF_Card_t SCF_hCard, int, DWORD);
00128 static LONG SCardGetHandleIndice(SCARDHANDLE hCard);
00129 static LONG isActiveContextPresent(void);
00130 
00131 
00132 static LONG SCardEstablishContextTH(DWORD dwScope, LPCVOID pvReserved1,
00133     LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
00134 {
00135     LONG rv = 0;
00136 
00137     if (SCARD_S_SUCCESS != isOCFServerRunning())
00138         return SCARD_E_NO_SERVICE;
00139 
00140     rv = PCSC_SCF_Initialize();
00141 
00142     if (SCARD_S_SUCCESS != rv)
00143         return rv;
00144 
00145     if (NULL == phContext)
00146         return SCARD_E_INVALID_PARAMETER;
00147     else
00148         *phContext = 0;
00149 
00150     if (dwScope != SCARD_SCOPE_USER && dwScope != SCARD_SCOPE_TERMINAL &&
00151         dwScope != SCARD_SCOPE_SYSTEM && dwScope != SCARD_SCOPE_GLOBAL)
00152     {
00153         *phContext = 0;
00154         return SCARD_E_INVALID_VALUE;
00155     }
00156     rv = getNewContext(phContext);
00157     return rv;
00158 }
00159 
00160 LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
00161     LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
00162 {
00163     long rv;
00164 
00165     SCardLockThread();
00166     rv = SCardEstablishContextTH(dwScope, pvReserved1,
00167         pvReserved2, phContext);
00168     SCardUnlockThread();
00169 
00170     return rv;
00171 }
00172 
00173 static LONG SCardReleaseContextTH(SCARDCONTEXT hContext)
00174 {
00175     LONG rv;
00176     /* Zero out everything */
00177 
00178     if (SCARD_S_SUCCESS != isOCFServerRunning())
00179         return SCARD_E_NO_SERVICE;
00180 
00181     rv = 0;
00182 
00183     /* Remove the local context from the stack */
00184     rv = SCardRemoveContext(hContext);
00185 
00186     return rv;
00187 }
00188 
00189 LONG SCardReleaseContext(SCARDCONTEXT hContext)
00190 {
00191     long rv;
00192 
00193     SCardLockThread();
00194     rv = SCardReleaseContextTH(hContext);
00195     SCardUnlockThread();
00196 
00197     return rv;
00198 }
00199 
00200 
00201 static LONG SCardListReadersTH(SCARDCONTEXT hContext, LPCSTR mszGroups,
00202     LPSTR mszReaders, LPDWORD pcchReaders)
00203 {
00204     static int first_time = 1;
00205     int i = 0;
00206     static DWORD dwReadersLen = 0;
00207     LONG retIndice = 0;
00208     char *tempPtr;
00209 
00210     if (SCARD_S_SUCCESS != isOCFServerRunning())
00211         return SCARD_E_NO_SERVICE;
00212 
00213 /* Check for NULL parameters */
00214     if (pcchReaders == NULL)
00215     {
00216         return SCARD_E_INVALID_PARAMETER;
00217     }
00218     /*Check for Context validity */
00219     retIndice = SCardGetContextIndice(hContext);
00220     if (0 > retIndice)
00221         return SCARD_E_INVALID_HANDLE;
00222 
00223     /*Calculate the the buffer length reuired only once.
00224      */
00225     if (first_time)
00226     {
00227         for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00228         {
00229             if (NULL != psReaderMap[i].ReaderName)
00230                 dwReadersLen += strlen(psReaderMap[i].ReaderName) + 1;
00231         }
00232         dwReadersLen++;
00233         first_time = 0;
00234     }
00235     /*There are no readers available */
00236     if (1 >= dwReadersLen)
00237         return SCARD_E_READER_UNAVAILABLE;
00238 
00239     if (mszReaders == NULL)
00240     {
00241         *pcchReaders = dwReadersLen;
00242         return SCARD_S_SUCCESS;
00243     }
00244     else if (*pcchReaders == 0)
00245     {
00246         *pcchReaders = dwReadersLen;
00247         return SCARD_S_SUCCESS;
00248     }
00249     else if (*pcchReaders < dwReadersLen)
00250     {
00251         *pcchReaders = dwReadersLen;
00252         return SCARD_E_INSUFFICIENT_BUFFER;
00253     }
00254 
00255     tempPtr = mszReaders;
00256     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00257     {
00258         if (NULL != psReaderMap[i].ReaderName)
00259         {
00260             memcpy(tempPtr, psReaderMap[i].ReaderName,
00261                 strlen(psReaderMap[i].ReaderName) + 1);
00262             tempPtr += (strlen(psReaderMap[i].ReaderName) + 1);
00263         }
00264     }
00265     /*the extra NULL character as per the PCSC specs. */
00266     tempPtr[0] = '\0';
00267     *pcchReaders = dwReadersLen;
00268 
00269     return SCARD_S_SUCCESS;
00270 }
00271 
00272 
00273 LONG SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups,
00274     LPSTR mszReaders, LPDWORD pcchReaders)
00275 {
00276     long rv;
00277 
00278     SCardLockThread();
00279     rv = SCardListReadersTH(hContext, mszGroups, mszReaders, pcchReaders);
00280     SCardUnlockThread();
00281 
00282     return rv;
00283 }
00284 
00285 /* by najam */
00286 
00287 
00288 static LONG SCardConnectTH(SCARDCONTEXT hContext, LPCSTR szReader,
00289     DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
00290     LPDWORD pdwActiveProtocol)
00291 {
00292     LONG rv;
00293 
00294     if (SCARD_S_SUCCESS != isOCFServerRunning())
00295         return SCARD_E_NO_SERVICE;
00296 
00297     /* Zero out everything   */
00298     rv = 0;
00299 
00300     /* Check for NULL parameters */
00301     if (phCard == NULL || pdwActiveProtocol == NULL)
00302         return SCARD_E_INVALID_PARAMETER;
00303     else
00304         *phCard = 0;
00305 
00306     /* Make sure this context has been opened */
00307     if (SCardGetContextIndice(hContext) == -1)
00308         return SCARD_E_INVALID_HANDLE;
00309 
00310     if (szReader == NULL)
00311         return SCARD_E_UNKNOWN_READER;
00312 
00313     /* Check for uninitialized strings */
00314     if (strlen(szReader) > MAX_READERNAME)
00315         return SCARD_E_INVALID_VALUE;
00316 
00317     if (!(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
00318         !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
00319         !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
00320         !(dwPreferredProtocols & SCARD_PROTOCOL_ANY))
00321     {
00322         return SCARD_E_INVALID_VALUE;
00323     }
00324 
00325     if ((SCARD_SHARE_SHARED != dwShareMode) &&
00326         (SCARD_SHARE_EXCLUSIVE != dwShareMode) &&
00327         (SCARD_SHARE_DIRECT != dwShareMode))
00328     {
00329         return SCARD_E_INVALID_VALUE;
00330     }
00331     /* TODO Which Protocols have to be supported */
00332     /* Ignoring protocols for now */
00333     /* Make sure this handle has been opened */
00334 
00335     rv = getNewHandle(hContext, szReader, phCard, dwShareMode);
00336 
00337     if (SCARD_S_SUCCESS != rv)
00338         return rv;
00339 
00340     *pdwActiveProtocol = SCARD_PROTOCOL_T0;
00341     return SCARD_S_SUCCESS;
00342 }
00343 
00344 LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode,
00345     DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
00346     LPDWORD pdwActiveProtocol)
00347 {
00348     long rv;
00349 
00350     SCardLockThread();
00351     rv = SCardConnectTH(hContext, szReader, dwShareMode,
00352         dwPreferredProtocols, phCard, pdwActiveProtocol);
00353     SCardUnlockThread();
00354     return rv;
00355 }
00356 
00357 static LONG SCardDisconnectTH(SCARDHANDLE hCard, DWORD dwDisposition)
00358 {
00359     long rv;
00360     LONG retIndice = 0;
00361 
00362     SCF_Status_t status;
00363 
00364     /*check ocfserver availibility */
00365     if (SCARD_S_SUCCESS != isOCFServerRunning())
00366         return SCARD_E_NO_SERVICE;
00367 
00368     if (dwDisposition != SCARD_LEAVE_CARD &&
00369         dwDisposition != SCARD_RESET_CARD &&
00370         dwDisposition != SCARD_UNPOWER_CARD &&
00371         dwDisposition != SCARD_EJECT_CARD)
00372     {
00373         return SCARD_E_INVALID_VALUE;
00374     }
00375     /*CHECK HANDLE VALIDITY */
00376     retIndice = SCardGetHandleIndice(hCard);
00377     if ((retIndice == -1) || (NULL == psChannelMap[retIndice].SCF_hCard))
00378         return SCARD_E_INVALID_HANDLE;
00379 
00380     /* TODO Take Care of the Disposition...  */
00381     /* Resetting the card for SCARD_RESET_CARD |
00382        SCARD_UNPOWER_CARD | SCARD_EJECT_CARD */
00383     if (SCARD_LEAVE_CARD != dwDisposition)
00384     {
00385         /*must acquire the lock to reset card */
00386         status = SCF_Card_lock(psChannelMap[retIndice].SCF_hCard, 0);
00387         if ((SCF_STATUS_SUCCESS == status)
00388             || (SCF_STATUS_DOUBLELOCK == status))
00389         {
00390             status = SCF_Card_reset(psChannelMap[retIndice].SCF_hCard);
00391             SCF_Card_unlock(psChannelMap[retIndice].SCF_hCard);
00392             /*a usleep here will allow the RESET_EVENT to be reported and
00393                the Maps to be updated */
00394             SYS_USleep(10);
00395         }
00396     }
00397 
00398     rv = SCardRemoveHandle(hCard);
00399 
00400     return rv;
00401 }
00402 
00403 static LONG SCardReconnectTH(SCARDHANDLE hCard, DWORD dwShareMode,
00404     DWORD dwPreferredProtocols, DWORD dwInitialization,
00405     LPDWORD pdwActiveProtocol)
00406 {
00407     SCARDCONTEXT hContext;
00408     LPSTR ReaderName;
00409     SCARDHANDLE tempHandle;
00410     LONG rv;
00411 
00412     int retIndice = 0;
00413     if (SCARD_S_SUCCESS != isOCFServerRunning())
00414         return SCARD_E_NO_SERVICE;
00415     if (pdwActiveProtocol == NULL)
00416         return SCARD_E_INVALID_PARAMETER;
00417 
00418     if (dwInitialization != SCARD_LEAVE_CARD &&
00419         dwInitialization != SCARD_RESET_CARD &&
00420         dwInitialization != SCARD_UNPOWER_CARD &&
00421         dwInitialization != SCARD_EJECT_CARD)
00422     {
00423         return SCARD_E_INVALID_VALUE;
00424     }
00425 
00426     retIndice = SCardGetHandleIndice(hCard);
00427 
00428     if (-1 == retIndice)
00429         return SCARD_E_INVALID_HANDLE;
00430 
00431     hContext = psChannelMap[retIndice].hContext;
00432     ReaderName = psReaderMap[psChannelMap[retIndice].ReaderIndice].ReaderName;
00433 
00434     SCardDisconnectTH(hCard, dwInitialization);
00435 
00436     /* get a new handle */
00437     rv = SCardConnectTH(hContext, ReaderName, dwShareMode,
00438         dwPreferredProtocols, &tempHandle, pdwActiveProtocol);
00439     if (SCARD_S_SUCCESS != rv)
00440         return rv;
00441 
00442     retIndice = SCardGetHandleIndice(tempHandle);
00443     if (-1 == retIndice)
00444         return SCARD_E_NO_MEMORY;
00445 
00446     /*set PCSC hCard to old Handle */
00447     SCardEventLock();
00448     psChannelMap[retIndice].PCSC_hCard = hCard;
00449     SCardEventUnlock();
00450 
00451     return SCARD_S_SUCCESS;
00452 }
00453 
00454 LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
00455     DWORD dwPreferredProtocols, DWORD dwInitialization,
00456     LPDWORD pdwActiveProtocol)
00457 {
00458     long rv;
00459 
00460     SCardLockThread();
00461     rv = SCardReconnectTH(hCard, dwShareMode, dwPreferredProtocols,
00462         dwInitialization, pdwActiveProtocol);
00463     SCardUnlockThread();
00464     return rv;
00465 }
00466 
00467 LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
00468 {
00469     long rv;
00470 
00471     SCardLockThread();
00472     rv = SCardDisconnectTH(hCard, dwDisposition);
00473     SCardUnlockThread();
00474     return rv;
00475 }
00476 
00477 
00478 LONG SCardBeginTransaction(SCARDHANDLE hCard)
00479 {
00480     LONG rv;
00481 
00482     SCF_Card_t SCF_hCard;
00483     SCF_Status_t status;
00484     /* Zero out everything   */
00485     rv = 0;
00486 
00487     SCardLockThread();
00488     if (SCARD_S_SUCCESS != isOCFServerRunning())
00489     {
00490         SCardUnlockThread();
00491         return SCARD_E_NO_SERVICE;
00492     }
00493     rv = getCardForHandle(hCard, &SCF_hCard);
00494     if (SCARD_S_SUCCESS != rv)
00495     {
00496         SCardUnlockThread();
00497         return rv;
00498     }
00499     SCardUnlockThread();
00500 
00501     status = SCF_Card_lock(SCF_hCard, SCF_TIMEOUT_MAX);
00502 
00503     if (SCF_STATUS_DOUBLELOCK == status)
00504         return SCARD_S_SUCCESS;
00505 
00506     rv = ConvertStatus(status);
00507 
00508     return rv;
00509 }
00510 
00511 static LONG SCardEndTransactionTH(SCARDHANDLE hCard, DWORD dwDisposition)
00512 {
00513     LONG rv;
00514     LONG retIndice = 0;
00515     SCF_Card_t SCF_hCard;
00516     SCF_Status_t status;
00517 
00518     if (SCARD_S_SUCCESS != isOCFServerRunning())
00519         return SCARD_E_NO_SERVICE;
00520     /* Zero out everything   */
00521     rv = 0;
00522     if (dwDisposition != SCARD_LEAVE_CARD &&
00523         dwDisposition != SCARD_RESET_CARD &&
00524         dwDisposition != SCARD_UNPOWER_CARD &&
00525         dwDisposition != SCARD_EJECT_CARD)
00526     {
00527 
00528         return SCARD_E_INVALID_VALUE;
00529     }
00530     retIndice = SCardGetHandleIndice(hCard);
00531     if (retIndice == -1)
00532         return SCARD_E_INVALID_HANDLE;
00533 
00534     rv = getCardForHandle(hCard, &SCF_hCard);
00535     if (rv != SCARD_S_SUCCESS)
00536         return rv;
00537 
00538     /* TODO Take Care of the Disposition... */
00539     if (SCARD_LEAVE_CARD != dwDisposition)
00540     {
00541         status = SCF_Card_reset(psChannelMap[retIndice].SCF_hCard);
00542         if (SCF_STATUS_SUCCESS == status)
00543         {
00544             /* reset the isReset for this card */
00545             SYS_USleep(10);
00546             SCardEventLock();
00547             psChannelMap[retIndice].isReset = 0;
00548             SCardEventUnlock();
00549         }
00550     }
00551 
00552     status = SCF_Card_unlock(SCF_hCard);
00553 
00554     return ConvertStatus(status);
00555 }
00556 
00557 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
00558 {
00559     long rv;
00560 
00561     SCardLockThread();
00562     rv = SCardEndTransactionTH(hCard, dwDisposition);
00563     SCardUnlockThread();
00564     return rv;
00565 }
00566 
00567 static LONG SCardCancelTransactionTH(SCARDHANDLE hCard)
00568 {
00569     if (SCARD_S_SUCCESS != isOCFServerRunning())
00570         return SCARD_E_NO_SERVICE;
00571 
00572     /* TODO */
00573     return SCARD_S_SUCCESS;
00574 }
00575 
00576 LONG SCardCancelTransaction(SCARDHANDLE hCard)
00577 {
00578     long rv;
00579 
00580     SCardLockThread();
00581     rv = SCardCancelTransactionTH(hCard);
00582     SCardUnlockThread();
00583     return rv;
00584 }
00585 
00586 static LONG SCardStatusTH(SCARDHANDLE hCard, LPSTR mszReaderNames,
00587     LPDWORD pcchReaderLen, LPDWORD pdwState,
00588     LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
00589 {
00590     LONG retIndice, rv;
00591     int i;
00592     DWORD dwReaderLen;
00593     SCF_Card_t SCF_hCard;
00594 
00595     if (SCARD_S_SUCCESS != isOCFServerRunning())
00596         return SCARD_E_NO_SERVICE;
00597     /* Zero out everything   */
00598     retIndice = 0;
00599     dwReaderLen = 0;
00600     rv = 0;
00601     i = 0;
00602     /* Check for NULL parameters */
00603 
00604     if (pcchReaderLen == NULL || pdwState == NULL ||
00605         pdwProtocol == NULL || pcbAtrLen == NULL)
00606     {
00607         return SCARD_E_INVALID_PARAMETER;
00608     }
00609 
00610     retIndice = SCardGetHandleIndice(hCard);
00611 
00612     rv = getCardForHandle(hCard, &SCF_hCard);
00613     if (SCARD_S_SUCCESS != rv)
00614         return rv;
00615 
00616     dwReaderLen =
00617         strlen(psReaderMap[psChannelMap[retIndice].ReaderIndice].ReaderName);
00618 
00619     if (mszReaderNames == NULL)
00620     {
00621         *pcchReaderLen = dwReaderLen;
00622         *pcbAtrLen = 0;
00623         *pdwState = 0;
00624         *pdwProtocol = 0;
00625         return SCARD_S_SUCCESS;
00626     }
00627 
00628     if (*pcchReaderLen == 0)
00629     {
00630         *pcchReaderLen = dwReaderLen;
00631         *pcbAtrLen = 0;
00632         *pdwState = 0;
00633         *pdwProtocol = 0;
00634         return SCARD_S_SUCCESS;
00635     }
00636 
00637     if (*pcchReaderLen < dwReaderLen)
00638     {
00639         *pcchReaderLen = dwReaderLen;
00640         *pcbAtrLen = 0;
00641         *pdwState = 0;
00642         *pdwProtocol = 0;
00643         return SCARD_E_INSUFFICIENT_BUFFER;
00644     }
00645 
00646     *pcchReaderLen = dwReaderLen;
00647     strcpy(mszReaderNames,
00648         psReaderMap[psChannelMap[retIndice].ReaderIndice].ReaderName);
00649     *pdwProtocol = SCARD_PROTOCOL_T0;
00650 
00651     SCardEventLock();
00652     if (!(psReaderMap[psChannelMap[retIndice].ReaderIndice].
00653             dwCurrentState & SCARD_STATE_PRESENT))
00654     {
00655         *pdwState = SCARD_ABSENT;
00656         SCardEventUnlock();
00657         return SCARD_S_SUCCESS;
00658     }
00659 
00660     *pdwState = SCARD_NEGOTIABLE | SCARD_POWERED | SCARD_PRESENT;
00661     rv = PCSC_SCF_getATR(SCF_hCard, pbAtr, pcbAtrLen);
00662     if (SCARD_S_SUCCESS == rv)
00663     {
00664         /*referesh the Atr in the reader Map */
00665         psReaderMap[psChannelMap[retIndice].ReaderIndice].dwAtrLength =
00666             *pcbAtrLen;
00667         memcpy(psReaderMap[psChannelMap[retIndice].ReaderIndice].bAtr, pbAtr,
00668             *pcbAtrLen);
00669     }
00670 
00671     SCardEventUnlock();
00672     return SCARD_S_SUCCESS;
00673 }
00674 
00675 LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderNames,
00676     LPDWORD pcchReaderLen, LPDWORD pdwState,
00677     LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
00678 {
00679     long rv;
00680 
00681     SCardLockThread();
00682     rv = SCardStatusTH(hCard, mszReaderNames, pcchReaderLen, pdwState,
00683         pdwProtocol, pbAtr, pcbAtrLen);
00684     SCardUnlockThread();
00685     return rv;
00686 }
00687 
00688 LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout,
00689     LPSCARD_READERSTATE_A rgReaderStates, DWORD cReaders)
00690 {
00691 
00692     LONG rv, retIndice, readerIndice;
00693     PSCARD_READERSTATE_A currReader;
00694     PREADER_STATE rContext;
00695     LPSTR lpcReaderName;
00696     DWORD dwTime;
00697     DWORD dwState;
00698     DWORD dwBreakFlag;
00699     int i, j;
00700 
00701     if (SCARD_S_SUCCESS != isOCFServerRunning())
00702         return SCARD_E_NO_SERVICE;
00703 
00704     /* Zero out everything */
00705     rv = 0;
00706     rContext = 0;
00707     lpcReaderName = 0;
00708     dwTime = 0;
00709     j = 0;
00710     dwState = 0;
00711     i = 0;
00712     currReader = 0;
00713     retIndice = 0;
00714     readerIndice = 0;
00715     dwBreakFlag = 0;
00716 
00717     if (rgReaderStates == NULL && cReaders > 0)
00718         return SCARD_E_INVALID_PARAMETER;
00719 
00720     if (cReaders < 0)
00721         return SCARD_E_INVALID_VALUE;
00722 
00723     /* change by najam */
00724     SCardLockThread();
00725     retIndice = SCardGetContextIndice(hContext);
00726     /* change by najam */
00727     SCardUnlockThread();
00728     if (retIndice == -1)
00729         return SCARD_E_INVALID_HANDLE;
00730 
00731     /* Application is waiting for a reader -
00732        return the first available reader
00733      */
00734     if (cReaders == 0)
00735     {
00736         for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00737         {
00738             if (psReaderMap[i].ReaderName)
00739                 return SCARD_S_SUCCESS;
00740         }
00741         return SCARD_E_READER_UNAVAILABLE;
00742     }
00743     else if (cReaders > PCSCLITE_MAX_READERS_CONTEXTS)
00744     {
00745         return SCARD_E_INVALID_VALUE;
00746     }
00747     /* Check the integrity of the reader states structures */
00748     for (j = 0; j < cReaders; j++)
00749     {
00750         currReader = &rgReaderStates[j];
00751         if (currReader->szReader == NULL)
00752         {
00753             return SCARD_E_INVALID_VALUE;
00754         }
00755     }
00756     /* End of search for readers */
00757 
00758     /* Clear the event state for all readers */
00759     for (j = 0; j < cReaders; j++)
00760     {
00761         currReader = &rgReaderStates[j];
00762         currReader->dwEventState = 0;
00763     }
00764 
00765     /* Now is where we start our event checking loop */
00766 
00767     psContextMap[retIndice].contextBlockStatus = BLOCK_STATUS_BLOCKING;
00768     j = 0;
00769 
00770     do
00771     {
00772         SYS_USleep(10);
00773         if (SCARD_S_SUCCESS != isOCFServerRunning())
00774             return SCARD_E_NO_SERVICE;
00775 
00776         currReader = &rgReaderStates[j];
00777 
00778     /************ Look for IGNORED readers ****************************/
00779 
00780         if (currReader->dwCurrentState & SCARD_STATE_IGNORE)
00781         {
00782             currReader->dwEventState = SCARD_STATE_IGNORE;
00783         }
00784         else
00785         {
00786       /************ Looks for correct readernames *********************/
00787 
00788             lpcReaderName = (char *) currReader->szReader;
00789 
00790             readerIndice = SCardGetReaderIndice(lpcReaderName);
00791             /* The requested reader name is not recognized */
00792             if (0 > readerIndice)
00793             {
00794                 if (currReader->dwCurrentState & SCARD_STATE_UNKNOWN)
00795                 {
00796                     currReader->dwEventState = SCARD_STATE_UNKNOWN;
00797                 }
00798                 else
00799                 {
00800                     currReader->dwEventState =
00801                         SCARD_STATE_UNKNOWN | SCARD_STATE_CHANGED;
00802                     /* Spec says use SCARD_STATE_IGNORE but a removed USB reader
00803                        with eventState fed into currentState will be ignored forever */
00804                     dwBreakFlag = 1;
00805                 }
00806             }
00807             else
00808             {
00809                 /* The reader has come back after being away */
00810                 if (currReader->dwCurrentState & SCARD_STATE_UNKNOWN)
00811                 {
00812                     currReader->dwEventState |= SCARD_STATE_CHANGED;
00813                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
00814                     dwBreakFlag = 1;
00815                 }
00816 
00817     /*****************************************************************/
00818                 SCardEventLock();
00819                 /* Now we check all the Reader States */
00820                 dwState = psReaderMap[readerIndice].dwCurrentState;
00821 
00822     /*********** Check if the reader is in the correct state ********/
00823                 if (dwState & SCARD_STATE_UNKNOWN)
00824                 {
00825                     /* App thinks reader is in bad state and it is */
00826                     if (currReader->dwCurrentState & SCARD_STATE_UNAVAILABLE)
00827                     {
00828                         currReader->dwEventState = SCARD_STATE_UNAVAILABLE;
00829                     }
00830                     else
00831                     {
00832                         /* App thinks reader is in good state and it is not */
00833                         currReader->dwEventState = SCARD_STATE_CHANGED |
00834                             SCARD_STATE_UNAVAILABLE;
00835                         dwBreakFlag = 1;
00836                     }
00837                 }
00838                 else
00839                 {
00840                     /* App thinks reader in bad state but it is not */
00841                     if (currReader->dwCurrentState & SCARD_STATE_UNAVAILABLE)
00842                     {
00843                         currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
00844                         currReader->dwEventState |= SCARD_STATE_CHANGED;
00845                         dwBreakFlag = 1;
00846                     }
00847                 }
00848 
00849     /********** Check for card presence in the reader **************/
00850 
00851                 if (dwState & SCARD_STATE_PRESENT)
00852                 {
00853                     currReader->cbAtr = psReaderMap[readerIndice].dwAtrLength;
00854                     memcpy(currReader->rgbAtr, psReaderMap[readerIndice].bAtr,
00855                         currReader->cbAtr);
00856                 }
00857                 else
00858                 {
00859                     currReader->cbAtr = 0;
00860                 }
00861                 /* Card is now absent                   */
00862                 if (dwState & SCARD_STATE_EMPTY)
00863                 {
00864                     currReader->dwEventState |= SCARD_STATE_EMPTY;
00865                     currReader->dwEventState &= ~SCARD_STATE_PRESENT;
00866                     currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
00867                     currReader->dwEventState &= ~SCARD_STATE_IGNORE;
00868                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
00869                     currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
00870                     currReader->dwEventState &= ~SCARD_STATE_ATRMATCH;
00871                     currReader->dwEventState &= ~SCARD_STATE_MUTE;
00872                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
00873                     /* After present the rest are assumed */
00874                     if (currReader->dwCurrentState & SCARD_STATE_PRESENT ||
00875                         currReader->dwCurrentState & SCARD_STATE_ATRMATCH ||
00876                         currReader->dwCurrentState & SCARD_STATE_EXCLUSIVE ||
00877                         currReader->dwCurrentState & SCARD_STATE_INUSE)
00878                     {
00879                         currReader->dwEventState |= SCARD_STATE_CHANGED;
00880                         dwBreakFlag = 1;
00881                     }
00882                     /* Card is now present              */
00883                 }
00884                 else if (dwState & SCARD_STATE_PRESENT)
00885                 {
00886                     currReader->dwEventState |= SCARD_STATE_PRESENT;
00887                     currReader->dwEventState &= ~SCARD_STATE_EMPTY;
00888                     currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
00889                     currReader->dwEventState &= ~SCARD_STATE_IGNORE;
00890                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
00891                     currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
00892                     currReader->dwEventState &= ~SCARD_STATE_MUTE;
00893 
00894                     if (currReader->dwCurrentState & SCARD_STATE_EMPTY)
00895                     {
00896                         currReader->dwEventState |= SCARD_STATE_CHANGED;
00897                         dwBreakFlag = 1;
00898                     }
00899                     /* TODO */
00900                     if (0 && dwState & SCARD_SWALLOWED)
00901                     {
00902                         if (currReader->dwCurrentState & SCARD_STATE_MUTE)
00903                         {
00904                             currReader->dwEventState |= SCARD_STATE_MUTE;
00905                         }
00906                         else
00907                         {
00908                             currReader->dwEventState |= SCARD_STATE_MUTE;
00909                             if (currReader->dwCurrentState !=
00910                                 SCARD_STATE_UNAWARE)
00911                             {
00912                                 currReader->dwEventState |=
00913                                     SCARD_STATE_CHANGED;
00914                             }
00915                             dwBreakFlag = 1;
00916                         }
00917                     }
00918                     else
00919                     {
00920                         /* App thinks card is mute but it is not */
00921                         if (currReader->dwCurrentState & SCARD_STATE_MUTE)
00922                         {
00923                             currReader->dwEventState |= SCARD_STATE_CHANGED;
00924                             dwBreakFlag = 1;
00925                         }
00926                     }
00927                 }
00928 
00929                 if (-1 == psReaderMap[readerIndice].SharedRefCount)
00930                 {
00931                     currReader->dwEventState |= SCARD_STATE_EXCLUSIVE;
00932                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
00933                     if (!currReader->dwCurrentState & SCARD_STATE_EXCLUSIVE)
00934                     {
00935                         currReader->dwEventState |= SCARD_STATE_CHANGED;
00936                         dwBreakFlag = 1;
00937                     }
00938                 }
00939                 else if (psReaderMap[readerIndice].SharedRefCount >= 1)
00940                 {
00941                     /* A card must be inserted for it to be INUSE */
00942                     if (dwState & SCARD_STATE_PRESENT)
00943                     {
00944                         currReader->dwEventState |= SCARD_STATE_INUSE;
00945                         currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
00946                         if (!currReader->dwCurrentState & SCARD_STATE_INUSE)
00947                         {
00948                             currReader->dwEventState |= SCARD_STATE_CHANGED;
00949                             dwBreakFlag = 1;
00950                         }
00951                     }
00952                 }
00953                 SCardEventUnlock();
00954                 if (currReader->dwCurrentState == SCARD_STATE_UNAWARE)
00955                 {
00956                     /* Break out of the while .. loop and return status
00957                        once all the status's for all readers is met */
00958                     dwBreakFlag = 1;
00959                 }
00960                 SYS_USleep(PCSCLITE_STATUS_WAIT);
00961 
00962             }                   /* End of SCARD_STATE_UNKNOWN */
00963 
00964         }                       /* End of SCARD_STATE_IGNORE */
00965 
00966         /* Counter and resetter */
00967         j = j + 1;
00968         if (j == cReaders)
00969             j = 0;
00970 
00971         if (dwTimeout != INFINITE && dwTimeout != 0)
00972         {
00973             dwTime += PCSCLITE_STATUS_WAIT;
00974 
00975             /* If time is greater than timeout and all readers have been
00976                checked
00977              */
00978             if ((dwTime >= (dwTimeout * 1000)) && (j == 0))
00979             {
00980                 return SCARD_E_TIMEOUT;
00981             }
00982         }
00983 
00984         /* Declare all the break conditions */
00985         /* TODO think about this */
00986         if (psContextMap[retIndice].contextBlockStatus == BLOCK_STATUS_RESUME)
00987             break;
00988 
00989         /* Break if UNAWARE is set and all readers have been checked */
00990         if ((dwBreakFlag == 1) && (j == 0))
00991             break;
00992 
00993         /*
00994          * Solve the problem of never exiting the loop when a smartcard is
00995          * already inserted in the reader, thus blocking the application
00996          * (patch proposed by Serge Koganovitsch)
00997          */
00998         if ((dwTimeout == 0) && (j == 0))
00999             break;
01000 
01001     }
01002     while (1);                  /* end of do */
01003 
01004     if (psContextMap[retIndice].contextBlockStatus == BLOCK_STATUS_RESUME)
01005     {
01006         return SCARD_E_CANCELLED;
01007     }
01008 
01009     return SCARD_S_SUCCESS;
01010 }
01011 
01012 
01013 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
01014     DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
01015     LPDWORD lpBytesReturned)
01016 {
01017     /* TODO */
01018     return SCARD_S_SUCCESS;
01019 }
01020 
01021 static LONG SCardTransmitTH(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci,
01022     LPCBYTE pbSendBuffer, DWORD cbSendLength,
01023     LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)
01024 {
01025     BYTE Buffer[MAX_BUFFER_SIZE];
01026     LONG rv = 0;
01027     SCF_Card_t SCF_hCard;
01028     SCF_Status_t status;
01029     LONG retIndice;
01030     LONG localRecvLen = MAX_BUFFER_SIZE;
01031     if (SCARD_S_SUCCESS != isOCFServerRunning())
01032         return SCARD_E_NO_SERVICE;
01033     if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
01034         pcbRecvLength == NULL || pioSendPci == NULL)
01035     {
01036         return SCARD_E_INVALID_PARAMETER;
01037     }
01038 
01039     rv = getCardForHandle(hCard, &SCF_hCard);
01040     if (rv != SCARD_S_SUCCESS)
01041         return rv;
01042 
01043     if ((cbSendLength > MAX_BUFFER_SIZE) || (*pcbRecvLength < 2))
01044         return SCARD_E_INSUFFICIENT_BUFFER;
01045 
01046     /* TODO which protocols to support */
01047     /* if(pioSendPci && pioSendPci->dwProtocol) { */
01048     retIndice = SCardGetHandleIndice(hCard);
01049     if ((pbSendBuffer[1] == 0xC0) &&
01050         psTransmitMap[retIndice].isResponseCached)
01051     {
01052         if (*pcbRecvLength < psTransmitMap[retIndice].bufferLength)
01053         {
01054             *pcbRecvLength = psTransmitMap[retIndice].bufferLength;
01055             return SCARD_E_INSUFFICIENT_BUFFER;
01056         }
01057         *pcbRecvLength = psTransmitMap[retIndice].bufferLength;
01058         memcpy(pbRecvBuffer, psTransmitMap[retIndice].Buffer,
01059             psTransmitMap[retIndice].bufferLength);
01060         if (pioRecvPci && pioSendPci)
01061             pioRecvPci->dwProtocol = pioSendPci->dwProtocol;
01062         return SCARD_S_SUCCESS;
01063     }
01064     else
01065     {
01066         psTransmitMap[retIndice].isResponseCached = 0;
01067     }
01068 
01069     status = SCF_Card_exchangeAPDU(SCF_hCard,
01070         (const uint8_t *) pbSendBuffer, (size_t) cbSendLength,
01071         (uint8_t *) Buffer, (size_t *) & localRecvLen);
01072     if ((cbSendLength > 5) && (localRecvLen > 2))
01073     {
01074         if (SCF_STATUS_SUCCESS == status)
01075         {
01076             *pcbRecvLength = 2;
01077             pbRecvBuffer[0] = 0x61;
01078             pbRecvBuffer[1] = localRecvLen - 2;
01079             psTransmitMap[retIndice].isResponseCached = TRUE;
01080             psTransmitMap[retIndice].bufferLength = localRecvLen;
01081             memcpy(psTransmitMap[retIndice].Buffer, Buffer,
01082                 psTransmitMap[retIndice].bufferLength);
01083             if (pioRecvPci && pioSendPci)
01084                 pioRecvPci->dwProtocol = pioSendPci->dwProtocol;
01085             return SCARD_S_SUCCESS;
01086         }
01087     }
01088     else
01089     {
01090         if (SCF_STATUS_SUCCESS == status)
01091         {
01092             if (*pcbRecvLength < localRecvLen)
01093             {
01094                 *pcbRecvLength = localRecvLen;
01095                 return SCARD_E_INSUFFICIENT_BUFFER;
01096             }
01097             *pcbRecvLength = localRecvLen;
01098             memcpy(pbRecvBuffer, Buffer, *pcbRecvLength);
01099         }
01100     }
01101 
01102     /* TODO fill the received Pci ... */
01103     /* For now  just filling the send pci protocol. */
01104     if (pioRecvPci && pioSendPci)
01105         pioRecvPci->dwProtocol = pioSendPci->dwProtocol;
01106 
01107     rv = ConvertStatus(status);
01108     return rv;
01109 }
01110 
01111 LONG SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci,
01112     LPCBYTE pbSendBuffer, DWORD cbSendLength,
01113     LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)
01114 {
01115     long rv;
01116 
01117     SCardLockThread();
01118     rv = SCardTransmitTH(hCard, pioSendPci, pbSendBuffer, cbSendLength,
01119         pioRecvPci, pbRecvBuffer, pcbRecvLength);
01120     SCardUnlockThread();
01121 
01122     return rv;
01123 }
01124 
01125 
01126 static LONG SCardListReaderGroupsTH(SCARDCONTEXT hContext, LPSTR mszGroups,
01127     LPDWORD pcchGroups)
01128 {
01129     LONG rv = SCARD_S_SUCCESS;
01130     const char ReaderGroup[] = "SCard$DefaultReaders";
01131     const int dwGroups = strlen(ReaderGroup) + 2;
01132     if (SCARD_S_SUCCESS != isOCFServerRunning())
01133         return SCARD_E_NO_SERVICE;
01134     /* Make sure this context has been opened */
01135     if (SCardGetContextIndice(hContext) == -1)
01136     {
01137         return SCARD_E_INVALID_HANDLE;
01138     }
01139     if (mszGroups)
01140     {
01141 
01142         if (*pcchGroups < dwGroups)
01143             rv = SCARD_E_INSUFFICIENT_BUFFER;
01144         else
01145         {
01146             memset(mszGroups, 0, dwGroups);
01147             memcpy(mszGroups, ReaderGroup, strlen(ReaderGroup));
01148         }
01149     }
01150 
01151     *pcchGroups = dwGroups;
01152 
01153     return rv;
01154 }
01155 
01156 LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups,
01157     LPDWORD pcchGroups)
01158 {
01159     long rv;
01160 
01161     SCardLockThread();
01162     rv = SCardListReaderGroupsTH(hContext, mszGroups, pcchGroups);
01163     SCardUnlockThread();
01164 
01165     return rv;
01166 }
01167 
01168 static LONG SCardCancelTH(SCARDCONTEXT hContext)
01169 {
01170     LONG hContextIndice;
01171     if (SCARD_S_SUCCESS != isOCFServerRunning())
01172         return SCARD_E_NO_SERVICE;
01173 
01174     hContextIndice = SCardGetContextIndice(hContext);
01175 
01176     if (hContextIndice == -1)
01177         return SCARD_E_INVALID_HANDLE;
01178 
01179     /* Set the block status for this Context so blocking calls will complete */
01180     psContextMap[hContextIndice].contextBlockStatus = BLOCK_STATUS_RESUME;
01181 
01182     return SCARD_S_SUCCESS;
01183 }
01184 
01185 LONG SCardCancel(SCARDCONTEXT hContext)
01186 {
01187     long rv;
01188 
01189     SCardLockThread();
01190     rv = SCardCancelTH(hContext);
01191     SCardUnlockThread();
01192 
01193     return rv;
01194 }
01195 
01196 LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
01197     LPDWORD pcbAttrLen)
01198 {
01199     return SCARD_E_NOT_TRANSACTED;
01200 }
01201 
01202 LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
01203     DWORD cbAttrLen)
01204 {
01205     return SCARD_E_NOT_TRANSACTED;
01206 }
01207 
01208 static LONG SCardGetHandleIndice(SCARDHANDLE hCard)
01209 {
01210     int i = 0;
01211     static int LastIndex = 0;
01212 
01213     if (hCard == 0)
01214         return -1;
01215     if (psChannelMap[LastIndex].PCSC_hCard == hCard)
01216         return LastIndex;
01217 
01218     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
01219     {
01220         if (hCard == psChannelMap[i].PCSC_hCard)
01221             return i;
01222     }
01223 
01224     return -1;
01225 }
01226 static LONG SCardGetReaderIndice(LPCSTR ReaderName)
01227 {
01228     int i = 0;
01229 
01230     if (NULL == ReaderName)
01231         return -1;
01232 
01233     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01234     {
01235         if ((NULL != psReaderMap[i].ReaderName) &&
01236             (strncmp(psReaderMap[i].ReaderName, ReaderName,
01237                     strlen(psReaderMap[i].ReaderName)) == 0))
01238         {
01239             return i;
01240         }
01241     }
01242 
01243     return -1;
01244 }
01245 
01246 static LONG SCardAddHandle(SCARDHANDLE PCSC_hCard, SCARDCONTEXT hContext,
01247     SCF_Session_t hSession, SCF_Terminal_t hTerminal,
01248     SCF_Card_t SCF_hCard, int ReaderIndice, DWORD dwShareMode)
01249 {
01250     int i = 0;
01251 
01252     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
01253     {
01254         if (psChannelMap[i].PCSC_hCard == 0)
01255         {
01256             psChannelMap[i].PCSC_hCard = PCSC_hCard;
01257             psChannelMap[i].hContext = hContext;
01258             psChannelMap[i].hSession = hSession;
01259             psChannelMap[i].hTerminal = hTerminal;
01260             psChannelMap[i].SCF_hCard = SCF_hCard;
01261             psChannelMap[i].ReaderIndice = ReaderIndice;
01262             SCardEventLock();
01263             if (SCARD_SHARE_EXCLUSIVE == dwShareMode)
01264             {
01265                 psChannelMap[i].haveLock = TRUE;
01266                 psReaderMap[ReaderIndice].SharedRefCount = -1;
01267             }
01268             else
01269             {
01270                 psReaderMap[ReaderIndice].SharedRefCount++;
01271                 psReaderMap[ReaderIndice].dwCurrentState |= SCARD_STATE_INUSE;
01272             }
01273             PCSC_SCF_getATR(SCF_hCard, psReaderMap[ReaderIndice].bAtr,
01274                 &psReaderMap[ReaderIndice].dwAtrLength);
01275             SCardEventUnlock();
01276             return SCARD_S_SUCCESS;
01277         }
01278     }
01279     return SCARD_E_NO_MEMORY;
01280 }
01281 
01282 static LONG PCSC_SCF_getATR(SCF_Card_t hCard, LPBYTE pcbAtr,
01283     LPDWORD pcbAtrLen)
01284 {
01285     SCF_Status_t status;
01286 
01287     struct SCF_BinaryData_t *pAtr;
01288 
01289     status = SCF_Card_getInfo(hCard, "atr", &pAtr);
01290     if (SCF_STATUS_SUCCESS != status)
01291         return SCARD_F_COMM_ERROR;
01292 
01293     if ((NULL == pcbAtr) || (NULL == pcbAtrLen) ||
01294         (MAX_ATR_SIZE < pAtr->length))
01295     {
01296         if (NULL != pcbAtrLen)
01297             *pcbAtrLen = pAtr->length;
01298         SCF_Card_freeInfo(hCard, pAtr);
01299         return SCARD_E_INSUFFICIENT_BUFFER;
01300     }
01301 
01302     *pcbAtrLen = pAtr->length;
01303 
01304     memcpy(pcbAtr, pAtr->data, pAtr->length);
01305 
01306     SCF_Card_freeInfo(hCard, pAtr);
01307     return SCARD_S_SUCCESS;
01308 }
01309 
01310 static LONG SCardRemoveHandle(SCARDHANDLE hCard)
01311 {
01312     LONG retIndice = 0;
01313 
01314     retIndice = SCardGetHandleIndice(hCard);
01315 
01316     if (retIndice == -1)
01317     {
01318         return SCARD_E_INVALID_HANDLE;
01319     }
01320     SCardEventLock();
01321     SCF_Session_close(psChannelMap[retIndice].hSession);
01322     psChannelMap[retIndice].PCSC_hCard = 0;
01323     psChannelMap[retIndice].hContext = 0;
01324     psChannelMap[retIndice].hSession = NULL;
01325     psChannelMap[retIndice].hTerminal = NULL;
01326     psChannelMap[retIndice].SCF_hCard = NULL;
01327     psChannelMap[retIndice].isReset = 0;
01328     if (psChannelMap[retIndice].haveLock)
01329     {
01330         psChannelMap[retIndice].haveLock = FALSE;
01331         psReaderMap[psChannelMap[retIndice].ReaderIndice].SharedRefCount = 0;
01332     }
01333     else
01334     {
01335         psReaderMap[psChannelMap[retIndice].ReaderIndice].SharedRefCount--;
01336         if (0 >=
01337             psReaderMap[psChannelMap[retIndice].ReaderIndice].SharedRefCount)
01338         {
01339             psReaderMap[psChannelMap[retIndice].ReaderIndice].SharedRefCount =
01340                 0;
01341             psReaderMap[psChannelMap[retIndice].ReaderIndice].
01342                 dwCurrentState &=
01343                 (~(SCARD_STATE_EXCLUSIVE | SCARD_STATE_INUSE));
01344         }
01345     }
01346 
01347     psChannelMap[retIndice].ReaderIndice = 0;
01348     SCardEventUnlock();
01349     return SCARD_S_SUCCESS;
01350 }
01351 
01352 
01353 static LONG getCardForHandle(SCARDHANDLE PCSC_hCard, SCF_Card_t * SCF_hCard)
01354 {
01355     int retIndice = 0;
01356 
01357     retIndice = SCardGetHandleIndice(PCSC_hCard);
01358     if (0 > retIndice)
01359         return SCARD_E_INVALID_HANDLE;
01360 
01361     *SCF_hCard = psChannelMap[retIndice].SCF_hCard;
01362     if (NULL == *SCF_hCard)
01363         return SCARD_E_INVALID_HANDLE;
01364     SCardEventLock();
01365     if (psChannelMap[retIndice].isReset)
01366     {
01367         SCardEventUnlock();
01368         return SCARD_W_RESET_CARD;
01369     }
01370     SCardEventUnlock();
01371 
01372     return SCARD_S_SUCCESS;
01373 
01374 }
01375 
01376 static LONG getNewHandle(SCARDCONTEXT hContext, LPCSTR szReader,
01377     SCARDHANDLE * phCard, DWORD dwShareMode)
01378 {
01379     long rv = 0, ReaderIndice;
01380     SCF_Status_t status;
01381     SCF_Session_t hSession;
01382     SCF_Terminal_t hTerminal;
01383     SCF_Card_t SCF_hCard;
01384 
01385     ReaderIndice = SCardGetReaderIndice(szReader);
01386     if (-1 == ReaderIndice)
01387         return SCARD_E_UNKNOWN_READER;
01388 
01389     SCardEventLock();
01390     if ((psReaderMap[ReaderIndice].SharedRefCount == -1) ||
01391         ((SCARD_SHARE_EXCLUSIVE == dwShareMode) &&
01392             psReaderMap[ReaderIndice].SharedRefCount))
01393     {
01394         SCardEventUnlock();
01395         return SCARD_E_SHARING_VIOLATION;
01396     }
01397     SCardEventUnlock();
01398 
01399     status = SCF_Session_getSession(&hSession);
01400     if (SCF_STATUS_SUCCESS != status)
01401     {
01402         return ConvertStatus(status);
01403     }
01404     status = SCF_Session_getTerminal(hSession, szReader, &hTerminal);
01405     if (SCF_STATUS_SUCCESS != status)
01406     {
01407         SCF_Session_close(hSession);
01408         return ConvertStatus(status);
01409     }
01410     status = SCF_Terminal_getCard(hTerminal, &SCF_hCard);
01411     if (SCF_STATUS_SUCCESS != status)
01412     {
01413         SCF_Session_close(hSession);
01414         return ConvertStatus(status);
01415     }
01416 
01417     if (SCARD_SHARE_EXCLUSIVE == dwShareMode)
01418     {
01419         status = SCF_Card_lock(SCF_hCard, 0);
01420         if (status != SCF_STATUS_SUCCESS)
01421         {
01422             SCF_Session_close(hSession);
01423             return SCARD_E_SHARING_VIOLATION;
01424         }
01425     }
01426 
01427     while (1)
01428     {
01429         *phCard = (PCSCLITE_SVC_IDENTITY + SYS_RandomInt(1, 65535));
01430         if (SCardGetHandleIndice(*phCard) == -1)
01431             break;
01432     }
01433     rv = SCardAddHandle(*phCard, hContext, hSession,
01434         hTerminal, SCF_hCard, ReaderIndice, dwShareMode);
01435     if (SCARD_S_SUCCESS != rv)
01436     {
01437         SCF_Session_close(hSession);
01438         return rv;
01439     }
01440 
01441     return SCARD_S_SUCCESS;
01442 }
01443 
01444 
01445 
01446 /*
01447   Function Managing Terminals for Sessions
01448 */
01449 
01450 
01451 /*
01452   Functions for managing instances of SCardEstablishContext
01453   These functions keep track of Context handles and associate
01454   the blocking variable contextBlockStatus to an hContext
01455 */
01456 
01457 static LONG getNewContext(SCARDCONTEXT * phContext)
01458 {
01459     LONG rv;
01460     SCF_Session_t hSession = NULL;
01461     SCF_Status_t status;
01462 
01463     status = SCF_Session_getSession(&hSession);
01464     if (status != SCF_STATUS_SUCCESS)
01465         return SCARD_E_NO_SERVICE;
01466 
01467     while (1)
01468     {
01469         *phContext = (PCSCLITE_SVC_IDENTITY + SYS_RandomInt(1, 65535));
01470         if (-1 == SCardGetContextIndice(*phContext))
01471             break;
01472     }
01473 
01474     rv = SCardAddContext(*phContext, hSession);
01475     if (SCARD_S_SUCCESS != rv)
01476     {
01477         SCF_Session_close(hSession);
01478     }
01479 
01480     return rv;
01481 }
01482 
01483 static LONG SCardAddContext(SCARDCONTEXT hContext, SCF_Session_t hSession)
01484 {
01485     int i;
01486 
01487     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
01488     {
01489         if (psContextMap[i].hContext == 0)
01490         {
01491             psContextMap[i].hContext = hContext;
01492             psContextMap[i].hSession = hSession;
01493             psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;
01494             return SCARD_S_SUCCESS;
01495         }
01496     }
01497 
01498     return SCARD_E_NO_MEMORY;
01499 }
01500 
01501 static LONG SCardGetContextIndice(SCARDCONTEXT hContext)
01502 {
01503     int i;
01504 
01505     /* Find this context and return it's spot in the array */
01506     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
01507     {
01508         if ((hContext == psContextMap[i].hContext) && (hContext != 0))
01509         {
01510             return i;
01511         }
01512     }
01513 
01514     return -1;
01515 }
01516 
01517 static LONG SCardRemoveContext(SCARDCONTEXT hContext)
01518 {
01519     LONG retIndice;
01520     int i = 0;
01521     retIndice = 0;
01522 
01523     retIndice = SCardGetContextIndice(hContext);
01524 
01525     if (retIndice == -1)
01526     {
01527         return SCARD_E_INVALID_HANDLE;
01528     }
01529     else
01530     {
01531         /* Free all handles for this context. */
01532         for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
01533         {
01534             if (psChannelMap[i].hContext == hContext)
01535             {
01536                 SCardRemoveHandle(psChannelMap[i].PCSC_hCard);
01537             }
01538         }
01539         SCF_Session_close(psContextMap[retIndice].hSession);
01540         psContextMap[retIndice].hContext = 0;
01541         psContextMap[retIndice].hSession = NULL;
01542         psContextMap[retIndice].contextBlockStatus = BLOCK_STATUS_RESUME;
01543     }
01544 
01545     return SCARD_S_SUCCESS;
01546 }
01547 
01548 static SCF_Session_t getSessionForContext(SCARDCONTEXT hContext)
01549 {
01550     LONG retIndice;
01551     retIndice = 0;
01552 
01553     retIndice = SCardGetContextIndice(hContext);
01554 
01555     if (retIndice == -1)
01556         return NULL;
01557 
01558     return (psContextMap[retIndice].hSession);
01559 }
01560 
01561 
01562 /*  This function locks a mutex so another thread
01563     must wait to use this function
01564 */
01565 
01566 LONG SCardLockThread(void)
01567 {
01568     return SYS_MutexLock(&clientMutex);
01569 }
01570 
01571 LONG SCardEventLock(void)
01572 {
01573     return SYS_MutexLock(&EventMutex);
01574 }
01575 
01576 /*  This function unlocks a mutex so another thread
01577     may use the client library
01578 */
01579 
01580 LONG SCardUnlockThread(void)
01581 {
01582     return SYS_MutexUnLock(&clientMutex);
01583 }
01584 
01585 LONG SCardEventUnlock(void)
01586 {
01587     return SYS_MutexUnLock(&EventMutex);
01588 }
01589 
01590 static LONG isActiveContextPresent(void)
01591 {
01592     long fActiveContext = FALSE;
01593     int i;
01594 
01595     for (i=0; i<PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
01596     {
01597         if (psContextMap[i].hContext != 0)
01598         {
01599             fActiveContext = TRUE;
01600             break;
01601         }
01602     }
01603     return fActiveContext;
01604 }
01605 
01606 static void EventCallback(SCF_Event_t eventType, SCF_Terminal_t hTerm,
01607     void *cbdata)
01608 {
01609     static char bInitialized = 0;
01610     int i = 0;
01611     int ReaderIndice = 0;
01612     SCF_Card_t hCard;
01613 
01614     SCF_Status_t status;
01615 
01616 #if 0
01617     struct _psReaderMap *readerMap;
01618     readerMap = (struct _psReaderMap *) cbdata;
01619 #endif
01620 
01621     ReaderIndice = (int) cbdata;
01622     SCardEventLock();
01623     switch (eventType)
01624     {
01625     case SCF_EVENT_CARDINSERTED:
01626     case SCF_EVENT_CARDPRESENT:
01627 #if 0
01628         printf("card present dwState = %x\n",
01629             psReaderMap[ReaderIndice].dwCurrentState);
01630 #endif
01631         psReaderMap[ReaderIndice].dwCurrentState &=
01632             (~(SCARD_STATE_UNKNOWN | SCARD_STATE_UNAVAILABLE |
01633                 SCARD_STATE_EMPTY));
01634         psReaderMap[ReaderIndice].dwCurrentState |= SCARD_STATE_PRESENT;
01635 #if 0
01636         printf("card present post dwState = %x\n",
01637             psReaderMap[ReaderIndice].dwCurrentState);
01638 #endif
01639         /* TODO get the ATR... filled */
01640         status = SCF_Terminal_getCard(psReaderMap[ReaderIndice].hTerminal,
01641             &hCard);
01642         if (SCF_STATUS_SUCCESS == status)
01643         {
01644 #if 0
01645             printf("Setting ATR...\n");
01646 #endif
01647             PCSC_SCF_getATR(hCard, psReaderMap[ReaderIndice].bAtr,
01648                 &psReaderMap[ReaderIndice].dwAtrLength);
01649 #if 0
01650             printf("Atrlen = %d\n", psReaderMap[ReaderIndice].dwAtrLength);
01651 #endif
01652         }
01653         SCF_Card_close(hCard);
01654         break;
01655     case SCF_EVENT_CARDREMOVED:
01656     case SCF_EVENT_CARDABSENT:
01657 #if 0
01658         printf("card absent dwState = %x\n",
01659             psReaderMap[ReaderIndice].dwCurrentState);
01660 #endif
01661         psReaderMap[ReaderIndice].dwCurrentState &= (~(SCARD_STATE_PRESENT |
01662                 SCARD_STATE_EXCLUSIVE |
01663                 SCARD_STATE_INUSE |
01664                 SCARD_STATE_MUTE | SCARD_STATE_UNAVAILABLE));
01665         psReaderMap[ReaderIndice].dwCurrentState |= SCARD_STATE_EMPTY;
01666         psReaderMap[ReaderIndice].SharedRefCount = 0;
01667         psReaderMap[ReaderIndice].dwAtrLength = 0;
01668         for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
01669         {
01670             if ((0 != psChannelMap[i].PCSC_hCard) &&
01671                 (psChannelMap[i].ReaderIndice == ReaderIndice))
01672             {
01673                 psChannelMap[i].haveLock = FALSE;
01674             }
01675         }
01676 #if 0
01677         printf("card absent dwState = %x\n",
01678             psReaderMap[ReaderIndice].dwCurrentState);
01679 #endif
01680         break;
01681     case SCF_EVENT_TERMINALCLOSED:
01682         /* TODO .... */
01683         break;
01684     case SCF_EVENT_CARDRESET:
01685         for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
01686         {
01687             if ((0 != psChannelMap[i].PCSC_hCard) &&
01688                 (psChannelMap[i].ReaderIndice == ReaderIndice))
01689             {
01690                 psChannelMap[i].isReset = TRUE;
01691             }
01692         }
01693         break;
01694     default:
01695         break;
01696     }                           /* switch */
01697     /*
01698      * The OCF Server always calls the registered callback function
01699      * immediately after the callback function is registered,
01700      * but always with the state of SCF_EVENT_CARDABSENT even if
01701      * there is a card present in the reader, the OCF server then
01702      * calls the callback the second time with the correct state,
01703      * that is the reason for the check if (bInitialized == 2).
01704      * If there is no card present in the reader the PCSC_SCF_Initialize's
01705      * pthread_cond_timedwait times out after 2 secs.
01706      */
01707     if (bInitialized < 2)
01708     {
01709         bInitialized++;
01710         if (2 == bInitialized)
01711             pthread_cond_signal(&EventCondition);
01712     }
01713 
01714     SCardEventUnlock();
01715 }
01716 
01717 
01718 static LONG isOCFServerRunning(void)
01719 {
01720     static int isRunning = TRUE;
01721     SCF_Status_t status;
01722     SCF_Session_t hSession;
01723 
01724     if (FALSE == isRunning)
01725         return SCARD_E_NO_SERVICE;
01726 
01727     status = SCF_Session_getSession(&hSession);
01728     if (SCF_STATUS_SUCCESS != status)
01729     {
01730         isRunning = FALSE;
01731         return SCARD_E_NO_SERVICE;
01732     }
01733     SCF_Session_close(hSession);
01734 
01735     return SCARD_S_SUCCESS;
01736 }
01737 
01738 static LONG PCSC_SCF_Initialize(void)
01739 {
01740     SCF_Status_t status;
01741     char **tList = NULL;
01742     int i;
01743 
01744     if (PCSC_Initialized)
01745         return SCARD_S_SUCCESS;
01746     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
01747     {
01748         psContextMap[i].hContext = 0;
01749         psContextMap[i].hSession = 0;
01750         psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;
01751         psChannelMap[i].PCSC_hCard = 0;
01752         psChannelMap[i].SCF_hCard = 0;
01753         psChannelMap[i].hTerminal = 0;
01754         psChannelMap[i].hContext = 0;
01755         psChannelMap[i].hSession = 0;
01756         psChannelMap[i].haveLock = 0;
01757         psChannelMap[i].isReset = 0;
01758         psChannelMap[i].ReaderIndice = 0;
01759         psTransmitMap[i].isResponseCached = 0;
01760         psTransmitMap[i].bufferLength = 0;
01761     }
01762     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01763     {
01764         psReaderMap[i].ReaderName = NULL;
01765         psReaderMap[i].hTerminal = 0;
01766         psReaderMap[i].SharedRefCount = 0;
01767         psReaderMap[i].dwCurrentState |= SCARD_STATE_UNAVAILABLE;
01768         psReaderMap[i].dwAtrLength = 0;
01769         memset(psReaderMap[i].bAtr, 0, MAX_ATR_SIZE);
01770         psReaderMap[i].lHandle = NULL;
01771     }
01772 
01773     status = SCF_Session_getSession(&g_hSession);
01774     if (status != SCF_STATUS_SUCCESS)
01775         return SCARD_E_NO_SERVICE;
01776     status = SCF_Session_getInfo(g_hSession, "terminalnames", &tList);
01777     if (status != SCF_STATUS_SUCCESS)
01778         return SCARD_E_NO_SERVICE;
01779 
01780     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01781     {
01782         if (NULL == tList[i])
01783             break;
01784         psReaderMap[i].ReaderName = strdup(tList[i]);
01785         status =
01786             SCF_Session_getTerminal(g_hSession, psReaderMap[i].ReaderName,
01787             &psReaderMap[i].hTerminal);
01788         if (status != SCF_STATUS_SUCCESS)
01789             continue;
01790         status =
01791             SCF_Terminal_addEventListener(psReaderMap[i].hTerminal,
01792             SCF_EVENT_ALL, EventCallback, (void *) i,
01793             &psReaderMap[i].lHandle);
01794         if (status != SCF_STATUS_SUCCESS)
01795         {
01796             SCF_Terminal_close(psReaderMap[i].hTerminal);
01797             psReaderMap[i].hTerminal = NULL;
01798         }
01799     }
01800     SCF_Session_freeInfo(g_hSession, tList);
01801 
01802     SYS_MutexLock(&SCFInitMutex);
01803     /* wait for ocfserver to initialize... or 2 secs whichever is earlier */
01804     {
01805         struct timeval currTime;
01806         struct timespec absTime;
01807 
01808         gettimeofday(&currTime, NULL);
01809 
01810         /* Calculate absolute time to time out */
01811         absTime.tv_sec = currTime.tv_sec + 2;
01812         absTime.tv_nsec = currTime.tv_usec*1000;
01813 
01814         pthread_cond_timedwait(&EventCondition, &SCFInitMutex, &absTime);
01815     }
01816     SYS_MutexUnLock(&SCFInitMutex);
01817 
01818     PCSC_Initialized = 1;
01819     return SCARD_S_SUCCESS;
01820 }
01821 
01822 static LONG ConvertStatus(SCF_Status_t status)
01823 {
01824     switch (status)
01825     {
01826     case SCF_STATUS_COMMERROR:
01827         return SCARD_F_COMM_ERROR;
01828     case SCF_STATUS_FAILED:
01829         return SCARD_F_INTERNAL_ERROR;
01830     case SCF_STATUS_BADHANDLE:
01831         return SCARD_E_INVALID_HANDLE;
01832     case SCF_STATUS_UNKNOWNPROPERTY:
01833         return SCARD_F_UNKNOWN_ERROR;
01834     case SCF_STATUS_BADARGS:
01835         return SCARD_E_INVALID_VALUE;
01836     case SCF_STATUS_BADTERMINAL:
01837         return SCARD_E_READER_UNAVAILABLE;
01838     case SCF_STATUS_NOCARD:
01839         return SCARD_E_NO_SMARTCARD;
01840     case SCF_STATUS_CARDREMOVED:
01841         return SCARD_W_REMOVED_CARD;
01842     case SCF_STATUS_TIMEOUT:
01843         return SCARD_E_TIMEOUT;
01844 #if 0
01845     case SCF_STATUS_DOUBLELOCK:
01846         /* TODO */
01847         break;
01848 #endif
01849     case SCF_STATUS_CARDLOCKED:
01850         return SCARD_E_SHARING_VIOLATION;
01851     case SCF_STATUS_NOSPACE:
01852         return SCARD_E_NO_MEMORY;
01853     case SCF_STATUS_SUCCESS:
01854         return SCARD_S_SUCCESS;
01855     }
01856     return SCARD_F_UNKNOWN_ERROR;
01857 }
01858 
01859 /*
01860  * Note that this function is not used
01861  */
01862 LONG SCardCheckReaderAvailability(LPSTR readerName, LONG errorCode)
01863 {
01864 #if 0
01865     LONG retIndice;
01866     int i;
01867 
01868     retIndice = 0;
01869     i = 0;
01870     if (errorCode != SCARD_S_SUCCESS)
01871     {
01872         for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
01873         {
01874             if (strcmp(psChannelMap[i].readerName, readerName) == 0)
01875             {
01876                 return errorCode;
01877             }
01878         }
01879 
01880         return SCARD_E_READER_UNAVAILABLE;
01881 
01882     }
01883     else
01884     {
01885         return SCARD_S_SUCCESS;
01886     }
01887 #endif
01888     return 0;
01889 }
01890 
01891 /*
01892  * free resources allocated by the library
01893  * You _shall_ call this function if you use dlopen/dlclose to load/unload the
01894  * library. Otherwise you will exhaust the ressources available.
01895  */
01896 void SCardUnload(void)
01897 {
01898     int i=0;
01899 #if 0
01900     if (!isExecuted)
01901         return;
01902 
01903     SHMClientCloseSession();
01904     SYS_CloseFile(mapAddr);
01905     isExecuted = 0;
01906 #endif
01907 
01908     /*
01909      *  Cleanup only if PCSC has been initialized and there are no active
01910      *  context.  Checking for active context is critical when libpcsclite is
01911      *  linked with multiple modules. for eg. an application links with
01912      *  pcsclite and a PAM module also links with pcsclite, when the PAM is
01913      *  unloaded from memory and if it calls SCardUnload, pcsclite will
01914      *  un-initialize even though there are active references from the
01915      *  application. Now, why dont we add SCardUnload to the array of functions
01916      *  to be called on unload (-zfiniarray=SCUnload), well, that does not seem
01917      *  to solve the problem, SCardUnload is called when PAM is unloaded from
01918      *  memory having the same impact that PCSC is uninitialized enen though
01919      *  there are active references.
01920      */
01921     if((!PCSC_Initialized) || isActiveContextPresent())
01922         return;
01923 
01924     for(i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++)
01925         if (psReaderMap[i].hTerminal)
01926         {
01927             SCF_Terminal_removeEventListener(psReaderMap[i].hTerminal,
01928                 psReaderMap[i].lHandle);
01929 
01930             SCF_Terminal_close(psReaderMap[i].hTerminal);
01931 
01932             if (psReaderMap[i].ReaderName)
01933                 free(psReaderMap[i].ReaderName);
01934         }
01935 
01936     SCF_Session_close(g_hSession);
01937     PCSC_Initialized = 0;
01938 }
01939 
01940 /*
01941  * Note that this function is not used
01942  */
01943 LONG SCardCheckDaemonAvailability(void)
01944 {
01945     LONG rv = 1;                /* assume it exists */
01946 
01947     if (rv == 0)
01948         return SCARD_E_NO_SERVICE;
01949     else
01950         return SCARD_S_SUCCESS;
01951 }
01952 

Generated on Sat Jun 28 00:39:24 2008 for pcsc-lite by  doxygen 1.4.7