winscard_clnt.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  *  Damien Sauveron <damien.sauveron@labri.fr>
00007  *  Ludovic Rousseau <ludovic.rousseau@free.fr>
00008  *
00009  * $Id: winscard_clnt.c 2569 2007-06-19 19:10:19Z rousseau $
00010  */
00011 
00020 #include "config.h"
00021 #include <stdlib.h>
00022 #include <string.h>
00023 #include <sys/types.h>
00024 #include <fcntl.h>
00025 #include <unistd.h>
00026 #include <sys/un.h>
00027 #include <errno.h>
00028 #include <stddef.h>
00029 
00030 #include "misc.h"
00031 #include "pcscd.h"
00032 #include "winscard.h"
00033 #include "debug.h"
00034 #include "thread_generic.h"
00035 #include "strlcpycat.h"
00036 
00037 #include "readerfactory.h"
00038 #include "eventhandler.h"
00039 #include "sys_generic.h"
00040 #include "winscard_msg.h"
00041 #include "utils.h"
00042 
00044 #define SCARD_PROTOCOL_ANY_OLD  0x1000
00045 
00046 #ifndef TRUE
00047 #define TRUE 1
00048 #define FALSE 0
00049 #endif
00050 
00051 #undef DO_PROFILE
00052 #ifdef DO_PROFILE
00053 
00054 #define PROFILE_FILE "/tmp/pcsc_profile"
00055 #include <stdio.h>
00056 #include <sys/time.h>
00057 
00058 struct timeval profile_time_start;
00059 FILE *fd;
00060 char profile_tty;
00061 char fct_name[100];
00062 
00063 #define PROFILE_START profile_start(__FUNCTION__);
00064 #define PROFILE_END(rv) profile_end(__FUNCTION__, rv);
00065 
00066 static void profile_start(const char *f)
00067 {
00068     static char initialized = FALSE;
00069 
00070     if (!initialized)
00071     {
00072         char filename[80];
00073 
00074         initialized = TRUE;
00075         sprintf(filename, "%s-%d", PROFILE_FILE, getuid());
00076         fd = fopen(filename, "a+");
00077         if (NULL == fd)
00078         {
00079             fprintf(stderr, "\33[01;31mCan't open %s: %s\33[0m\n",
00080                 PROFILE_FILE, strerror(errno));
00081             exit(-1);
00082         }
00083         fprintf(fd, "\nStart a new profile\n");
00084 
00085         if (isatty(fileno(stderr)))
00086             profile_tty = TRUE;
00087         else
00088             profile_tty = FALSE;
00089     }
00090 
00091     /* PROFILE_END was not called before? */
00092     if (profile_tty && fct_name[0])
00093         printf("\33[01;34m WARNING: %s starts before %s finishes\33[0m\n",
00094             f, fct_name);
00095 
00096     strlcpy(fct_name, f, sizeof(fct_name));
00097 
00098     gettimeofday(&profile_time_start, NULL);
00099 } /* profile_start */
00100 
00101 /* r = a - b */
00102 static long int time_sub(struct timeval *a, struct timeval *b)
00103 {
00104     struct timeval r;
00105     r.tv_sec = a -> tv_sec - b -> tv_sec;
00106     r.tv_usec = a -> tv_usec - b -> tv_usec;
00107     if (r.tv_usec < 0)
00108     {
00109         r.tv_sec--;
00110         r.tv_usec += 1000000;
00111     }
00112 
00113     return r.tv_sec * 1000000 + r.tv_usec;
00114 } /* time_sub */
00115 
00116 
00117 static void profile_end(const char *f, LONG rv)
00118 {
00119     struct timeval profile_time_end;
00120     long d;
00121 
00122     gettimeofday(&profile_time_end, NULL);
00123     d = time_sub(&profile_time_end, &profile_time_start);
00124 
00125     if (profile_tty)
00126     {
00127         if (fct_name[0])
00128         {
00129             if (strncmp(fct_name, f, sizeof(fct_name)))
00130                 printf("\33[01;34m WARNING: %s ends before %s\33[0m\n",
00131                         f, fct_name);
00132         }
00133         else
00134             printf("\33[01;34m WARNING: %s ends but we lost its start\33[0m\n",
00135                 f);
00136 
00137         /* allow to detect missing PROFILE_END calls */
00138         fct_name[0] = '\0';
00139 
00140         if (rv != SCARD_S_SUCCESS)
00141             fprintf(stderr,
00142                 "\33[01;31mRESULT %s \33[35m%ld \33[34m0x%08lX %s\33[0m\n",
00143                 f, d, rv, pcsc_stringify_error(rv));
00144         else
00145             fprintf(stderr, "\33[01;31mRESULT %s \33[35m%ld\33[0m\n", f, d);
00146     }
00147     fprintf(fd, "%s %ld\n", f, d);
00148     fflush(fd);
00149 } /* profile_end */
00150 
00151 #else
00152 #define PROFILE_START
00153 #define PROFILE_END(rv)
00154 #endif
00155 
00160 struct _psChannelMap
00161 {
00162     SCARDHANDLE hCard;
00163     LPSTR readerName;
00164 };
00165 
00166 typedef struct _psChannelMap CHANNEL_MAP, *PCHANNEL_MAP;
00167 
00173 static struct _psContextMap
00174 {
00175     DWORD dwClientID;               
00176     SCARDCONTEXT hContext;          
00177     DWORD contextBlockStatus;
00178     PCSCLITE_MUTEX_T mMutex;        
00179     CHANNEL_MAP psChannelMap[PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS];
00180 } psContextMap[PCSCLITE_MAX_APPLICATION_CONTEXTS];
00181 
00185 static short isExecuted = 0;
00186 
00187 
00191 static time_t daemon_ctime = 0;
00192 static pid_t daemon_pid = 0;
00193 
00199 static int mapAddr = 0;
00200 
00205 static PCSCLITE_MUTEX clientMutex = PTHREAD_MUTEX_INITIALIZER;
00206 
00213 static PREADER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS];
00214 
00215 PCSC_API SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_T0, 8 };
00216 PCSC_API SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, 8 };
00217 PCSC_API SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_RAW, 8 };
00218 
00219 
00220 static LONG SCardAddContext(SCARDCONTEXT, DWORD);
00221 static LONG SCardGetContextIndice(SCARDCONTEXT);
00222 static LONG SCardGetContextIndiceTH(SCARDCONTEXT);
00223 static LONG SCardRemoveContext(SCARDCONTEXT);
00224 static LONG SCardCleanContext(LONG indice);
00225 
00226 static LONG SCardAddHandle(SCARDHANDLE, DWORD, LPCSTR);
00227 static LONG SCardGetIndicesFromHandle(SCARDHANDLE, PDWORD, PDWORD);
00228 static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE, PDWORD, PDWORD);
00229 static LONG SCardRemoveHandle(SCARDHANDLE);
00230 
00231 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
00232     LPBYTE pbAttr, LPDWORD pcbAttrLen);
00233 
00234 void DESTRUCTOR SCardUnload(void);
00235 
00236 /*
00237  * Thread safety functions
00238  */
00245 inline static LONG SCardLockThread(void)
00246 {
00247     return SYS_MutexLock(&clientMutex);
00248 }
00249 
00255 inline static LONG SCardUnlockThread(void)
00256 {
00257     return SYS_MutexUnLock(&clientMutex);
00258 }
00259 
00260 static LONG SCardEstablishContextTH(DWORD, LPCVOID, LPCVOID, LPSCARDCONTEXT);
00261 
00294 LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
00295     LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
00296 {
00297     LONG rv;
00298 
00299     PROFILE_START
00300 
00301     /* Check if the server is running */
00302     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
00303         return SCARD_E_NO_SERVICE;
00304 
00305     SCardLockThread();
00306     rv = SCardEstablishContextTH(dwScope, pvReserved1,
00307         pvReserved2, phContext);
00308     SCardUnlockThread();
00309 
00310     PROFILE_END(rv)
00311 
00312     return rv;
00313 }
00314 
00340 static LONG SCardEstablishContextTH(DWORD dwScope, LPCVOID pvReserved1,
00341     LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
00342 {
00343     LONG rv;
00344     int i;
00345     establish_struct scEstablishStruct;
00346     sharedSegmentMsg msgStruct;
00347     DWORD dwClientID = 0;
00348 
00349     if (phContext == NULL)
00350         return SCARD_E_INVALID_PARAMETER;
00351     else
00352         *phContext = 0;
00353 
00354     /*
00355      * Do this only once:
00356      * - Initialize debug of need.
00357      * - Set up the memory mapped structures for reader states.
00358      * - Allocate each reader structure.
00359      * - Initialize context struct.
00360      */
00361     if (isExecuted == 0)
00362     {
00363         int pageSize;
00364 
00365         /*
00366          * Do any system initilization here
00367          */
00368         SYS_Initialize();
00369 
00370         /*
00371          * Set up the memory mapped reader stats structures
00372          */
00373         mapAddr = SYS_OpenFile(PCSCLITE_PUBSHM_FILE, O_RDONLY, 0);
00374         if (mapAddr < 0)
00375         {
00376             Log2(PCSC_LOG_CRITICAL, "Cannot open public shared file: %s",
00377                 PCSCLITE_PUBSHM_FILE);
00378             return SCARD_E_NO_SERVICE;
00379         }
00380 
00381         /* close on exec so that child processes do not inherits the file
00382          * descriptor. The child process will call SCardEstablishContext()
00383          * if needed. */
00384         fcntl(mapAddr, F_SETFD, FD_CLOEXEC);
00385 
00386         pageSize = SYS_GetPageSize();
00387 
00388         /*
00389          * Allocate each reader structure in the memory map
00390          */
00391         for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00392         {
00393             readerStates[i] =
00394                 (PREADER_STATE)SYS_PublicMemoryMap(sizeof(READER_STATE),
00395                 mapAddr, (i * pageSize));
00396             if (readerStates[i] == NULL)
00397             {
00398                 Log1(PCSC_LOG_CRITICAL, "Cannot public memory map");
00399                 SYS_CloseFile(mapAddr); /* Close the memory map file */
00400                 return SCARD_F_INTERNAL_ERROR;
00401             }
00402         }
00403 
00404         /*
00405          * Initializes the application contexts and all channels for each one
00406          */
00407         for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
00408         {
00409             int j;
00410 
00411             /*
00412              * Initially set the context struct to zero
00413              */
00414             psContextMap[i].dwClientID = 0;
00415             psContextMap[i].hContext = 0;
00416             psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;
00417             psContextMap[i].mMutex = NULL;
00418 
00419             for (j = 0; j < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; j++)
00420             {
00421                 /*
00422                  * Initially set the hcard structs to zero
00423                  */
00424                 psContextMap[i].psChannelMap[j].hCard = 0;
00425                 psContextMap[i].psChannelMap[j].readerName = NULL;
00426             }
00427         }
00428 
00429     }
00430 
00431     /*
00432      * Is there a free slot for this connection ?
00433      */
00434 
00435     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
00436     {
00437         if (psContextMap[i].dwClientID == 0)
00438             break;
00439     }
00440 
00441     if (i == PCSCLITE_MAX_APPLICATION_CONTEXTS)
00442     {
00443         return SCARD_E_NO_MEMORY;
00444     }
00445 
00446     /* Establishes a connection to the server */
00447     if (SHMClientSetupSession(&dwClientID) != 0)
00448     {
00449         SYS_CloseFile(mapAddr);
00450         return SCARD_E_NO_SERVICE;
00451     }
00452 
00453     {   /* exchange client/server protocol versions */
00454         version_struct *veStr;
00455 
00456         memset(&msgStruct, 0, sizeof(msgStruct));
00457         msgStruct.mtype = CMD_VERSION;
00458         msgStruct.user_id = SYS_GetUID();
00459         msgStruct.group_id = SYS_GetGID();
00460         msgStruct.command = 0;
00461         msgStruct.date = time(NULL);
00462 
00463         veStr = (version_struct *) msgStruct.data;
00464         veStr->major = PROTOCOL_VERSION_MAJOR;
00465         veStr->minor = PROTOCOL_VERSION_MINOR;
00466 
00467         if (-1 == SHMMessageSend(&msgStruct, sizeof(msgStruct), dwClientID,
00468             PCSCLITE_MCLIENT_ATTEMPTS))
00469             return SCARD_E_NO_SERVICE;
00470 
00471         /*
00472          * Read a message from the server
00473          */
00474         if (-1 == SHMMessageReceive(&msgStruct, sizeof(msgStruct), dwClientID,
00475             PCSCLITE_CLIENT_ATTEMPTS))
00476         {
00477             Log1(PCSC_LOG_CRITICAL, "Your pcscd is too old and does not support CMD_VERSION");
00478             return SCARD_F_COMM_ERROR;
00479         }
00480 
00481         Log3(PCSC_LOG_INFO, "Server is protocol version %d:%d",
00482             veStr->major, veStr->minor);
00483 
00484         if (veStr->rv != SCARD_S_SUCCESS)
00485             return veStr->rv;
00486 
00487         isExecuted = 1;
00488     }
00489 
00490 
00491     if (dwScope != SCARD_SCOPE_USER && dwScope != SCARD_SCOPE_TERMINAL &&
00492         dwScope != SCARD_SCOPE_SYSTEM && dwScope != SCARD_SCOPE_GLOBAL)
00493     {
00494         return SCARD_E_INVALID_VALUE;
00495     }
00496 
00497     /*
00498      * Try to establish an Application Context with the server
00499      */
00500     scEstablishStruct.dwScope = dwScope;
00501     scEstablishStruct.phContext = 0;
00502     scEstablishStruct.rv = SCARD_S_SUCCESS;
00503 
00504     rv = WrapSHMWrite(SCARD_ESTABLISH_CONTEXT, dwClientID,
00505         sizeof(scEstablishStruct), PCSCLITE_MCLIENT_ATTEMPTS,
00506         (void *) &scEstablishStruct);
00507 
00508     if (rv == -1)
00509         return SCARD_E_NO_SERVICE;
00510 
00511     /*
00512      * Read the response from the server
00513      */
00514     rv = SHMClientRead(&msgStruct, dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
00515 
00516     if (rv == -1)
00517         return SCARD_F_COMM_ERROR;
00518 
00519     memcpy(&scEstablishStruct, &msgStruct.data, sizeof(scEstablishStruct));
00520 
00521     if (scEstablishStruct.rv != SCARD_S_SUCCESS)
00522         return scEstablishStruct.rv;
00523 
00524     *phContext = scEstablishStruct.phContext;
00525 
00526     /*
00527      * Allocate the new hContext - if allocator full return an error
00528      */
00529     rv = SCardAddContext(*phContext, dwClientID);
00530 
00531     return rv;
00532 }
00533 
00552 LONG SCardReleaseContext(SCARDCONTEXT hContext)
00553 {
00554     LONG rv;
00555     release_struct scReleaseStruct;
00556     sharedSegmentMsg msgStruct;
00557     LONG dwContextIndex;
00558 
00559     PROFILE_START
00560 
00561     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
00562         return SCARD_E_NO_SERVICE;
00563 
00564     /*
00565      * Make sure this context has been opened
00566      */
00567     dwContextIndex = SCardGetContextIndice(hContext);
00568     if (dwContextIndex == -1)
00569         return SCARD_E_INVALID_HANDLE;
00570 
00571     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
00572 
00573     scReleaseStruct.hContext = hContext;
00574     scReleaseStruct.rv = SCARD_S_SUCCESS;
00575 
00576     rv = WrapSHMWrite(SCARD_RELEASE_CONTEXT, psContextMap[dwContextIndex].dwClientID,
00577               sizeof(scReleaseStruct),
00578               PCSCLITE_MCLIENT_ATTEMPTS, (void *) &scReleaseStruct);
00579 
00580     if (rv == -1)
00581     {
00582         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00583         return SCARD_E_NO_SERVICE;
00584     }
00585 
00586     /*
00587      * Read a message from the server
00588      */
00589     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
00590     memcpy(&scReleaseStruct, &msgStruct.data, sizeof(scReleaseStruct));
00591 
00592     if (rv == -1)
00593     {
00594         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00595         return SCARD_F_COMM_ERROR;
00596     }
00597 
00598     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00599 
00600     /*
00601      * Remove the local context from the stack
00602      */
00603     SCardLockThread();
00604     SCardRemoveContext(hContext);
00605     SCardUnlockThread();
00606 
00607     PROFILE_END(scReleaseStruct.rv)
00608 
00609     return scReleaseStruct.rv;
00610 }
00611 
00624 LONG SCardSetTimeout(SCARDCONTEXT hContext, DWORD dwTimeout)
00625 {
00626     /*
00627      * Deprecated
00628      */
00629 
00630     return SCARD_S_SUCCESS;
00631 }
00632 
00683 LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader,
00684     DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
00685     LPDWORD pdwActiveProtocol)
00686 {
00687     LONG rv;
00688     connect_struct scConnectStruct;
00689     sharedSegmentMsg msgStruct;
00690     LONG dwContextIndex;
00691 
00692     PROFILE_START
00693 
00694     /*
00695      * Check for NULL parameters
00696      */
00697     if (phCard == NULL || pdwActiveProtocol == NULL)
00698         return SCARD_E_INVALID_PARAMETER;
00699     else
00700         *phCard = 0;
00701 
00702     if (szReader == NULL)
00703         return SCARD_E_UNKNOWN_READER;
00704 
00705     /*
00706      * Check for uninitialized strings
00707      */
00708     if (strlen(szReader) > MAX_READERNAME)
00709         return SCARD_E_INVALID_VALUE;
00710 
00711     if (!(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
00712         !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
00713         !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
00714         !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
00715     {
00716         return SCARD_E_INVALID_VALUE;
00717     }
00718 
00719     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
00720         return SCARD_E_NO_SERVICE;
00721 
00722     /*
00723      * Make sure this context has been opened
00724      */
00725     dwContextIndex = SCardGetContextIndice(hContext);
00726     if (dwContextIndex == -1)
00727         return SCARD_E_INVALID_HANDLE;
00728 
00729     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
00730 
00731     strncpy(scConnectStruct.szReader, szReader, MAX_READERNAME);
00732 
00733     scConnectStruct.hContext = hContext;
00734     scConnectStruct.dwShareMode = dwShareMode;
00735     scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
00736     scConnectStruct.phCard = 0;
00737     scConnectStruct.pdwActiveProtocol = 0;
00738     scConnectStruct.rv = SCARD_S_SUCCESS;
00739 
00740     rv = WrapSHMWrite(SCARD_CONNECT, psContextMap[dwContextIndex].dwClientID,
00741         sizeof(scConnectStruct),
00742         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scConnectStruct);
00743 
00744     if (rv == -1)
00745     {
00746         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00747         return SCARD_E_NO_SERVICE;
00748     }
00749 
00750     /*
00751      * Read a message from the server
00752      */
00753     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
00754 
00755     memcpy(&scConnectStruct, &msgStruct.data, sizeof(scConnectStruct));
00756 
00757     if (rv == -1)
00758     {
00759         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00760         return SCARD_F_COMM_ERROR;
00761     }
00762 
00763     *phCard = scConnectStruct.phCard;
00764     *pdwActiveProtocol = scConnectStruct.pdwActiveProtocol;
00765 
00766     if (scConnectStruct.rv == SCARD_S_SUCCESS)
00767     {
00768         /*
00769          * Keep track of the handle locally
00770          */
00771         rv = SCardAddHandle(*phCard, dwContextIndex, szReader);
00772         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00773 
00774         PROFILE_END(rv)
00775 
00776         return rv;
00777     }
00778 
00779     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00780 
00781     PROFILE_END(scConnectStruct.rv)
00782 
00783     return scConnectStruct.rv;
00784 }
00785 
00853 LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
00854     DWORD dwPreferredProtocols, DWORD dwInitialization,
00855     LPDWORD pdwActiveProtocol)
00856 {
00857     LONG rv;
00858     reconnect_struct scReconnectStruct;
00859     sharedSegmentMsg msgStruct;
00860     int i;
00861     DWORD dwContextIndex, dwChannelIndex;
00862 
00863     PROFILE_START
00864 
00865     if (dwInitialization != SCARD_LEAVE_CARD &&
00866         dwInitialization != SCARD_RESET_CARD &&
00867         dwInitialization != SCARD_UNPOWER_CARD &&
00868         dwInitialization != SCARD_EJECT_CARD)
00869     {
00870         return SCARD_E_INVALID_VALUE;
00871     }
00872 
00873     if (!(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
00874         !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
00875         !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
00876         !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
00877     {
00878         return SCARD_E_INVALID_VALUE;
00879     }
00880 
00881     if (pdwActiveProtocol == NULL)
00882         return SCARD_E_INVALID_PARAMETER;
00883 
00884     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
00885         return SCARD_E_NO_SERVICE;
00886 
00887     /*
00888      * Make sure this handle has been opened
00889      */
00890     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
00891 
00892     if (rv == -1)
00893         return SCARD_E_INVALID_HANDLE;
00894 
00895     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
00896 
00897 
00898     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00899     {
00900         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
00901 
00902         /* by default r == NULL */
00903         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
00904             break;
00905     }
00906 
00907     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
00908     {
00909         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00910         return SCARD_E_READER_UNAVAILABLE;
00911     }
00912 
00913     do
00914     {
00915         scReconnectStruct.hCard = hCard;
00916         scReconnectStruct.dwShareMode = dwShareMode;
00917         scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
00918         scReconnectStruct.dwInitialization = dwInitialization;
00919         scReconnectStruct.pdwActiveProtocol = *pdwActiveProtocol;
00920         scReconnectStruct.rv = SCARD_S_SUCCESS;
00921 
00922         rv = WrapSHMWrite(SCARD_RECONNECT, psContextMap[dwContextIndex].dwClientID,
00923             sizeof(scReconnectStruct),
00924             PCSCLITE_CLIENT_ATTEMPTS, (void *) &scReconnectStruct);
00925 
00926         if (rv == -1)
00927         {
00928             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00929             return SCARD_E_NO_SERVICE;
00930         }
00931 
00932         /*
00933          * Read a message from the server
00934          */
00935         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
00936 
00937         memcpy(&scReconnectStruct, &msgStruct.data, sizeof(scReconnectStruct));
00938 
00939         if (rv == -1)
00940         {
00941             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00942             return SCARD_F_COMM_ERROR;
00943         }
00944     } while (SCARD_E_SHARING_VIOLATION == scReconnectStruct.rv);
00945 
00946     *pdwActiveProtocol = scReconnectStruct.pdwActiveProtocol;
00947 
00948     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00949 
00950     PROFILE_END(scReconnectStruct.rv)
00951 
00952     return scReconnectStruct.rv;
00953 }
00954 
00985 LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
00986 {
00987     LONG rv;
00988     disconnect_struct scDisconnectStruct;
00989     sharedSegmentMsg msgStruct;
00990     DWORD dwContextIndex, dwChannelIndex;
00991 
00992     PROFILE_START
00993 
00994     if (dwDisposition != SCARD_LEAVE_CARD &&
00995         dwDisposition != SCARD_RESET_CARD &&
00996         dwDisposition != SCARD_UNPOWER_CARD &&
00997         dwDisposition != SCARD_EJECT_CARD)
00998     {
00999         return SCARD_E_INVALID_VALUE;
01000     }
01001 
01002     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01003         return SCARD_E_NO_SERVICE;
01004 
01005     /*
01006      * Make sure this handle has been opened
01007      */
01008     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01009 
01010     if (rv == -1)
01011         return SCARD_E_INVALID_HANDLE;
01012 
01013     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01014 
01015     scDisconnectStruct.hCard = hCard;
01016     scDisconnectStruct.dwDisposition = dwDisposition;
01017     scDisconnectStruct.rv = SCARD_S_SUCCESS;
01018 
01019     rv = WrapSHMWrite(SCARD_DISCONNECT, psContextMap[dwContextIndex].dwClientID,
01020         sizeof(scDisconnectStruct),
01021         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scDisconnectStruct);
01022 
01023     if (rv == -1)
01024     {
01025         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01026         return SCARD_E_NO_SERVICE;
01027     }
01028 
01029     /*
01030      * Read a message from the server
01031      */
01032     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
01033 
01034     memcpy(&scDisconnectStruct, &msgStruct.data,
01035         sizeof(scDisconnectStruct));
01036 
01037     if (rv == -1)
01038     {
01039         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01040         return SCARD_F_COMM_ERROR;
01041     }
01042 
01043     SCardRemoveHandle(hCard);
01044 
01045     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01046 
01047     PROFILE_END(scDisconnectStruct.rv)
01048 
01049     return scDisconnectStruct.rv;
01050 }
01051 
01084 LONG SCardBeginTransaction(SCARDHANDLE hCard)
01085 {
01086 
01087     LONG rv;
01088     begin_struct scBeginStruct;
01089     int i;
01090     sharedSegmentMsg msgStruct;
01091     DWORD dwContextIndex, dwChannelIndex;
01092 
01093     PROFILE_START
01094 
01095     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01096         return SCARD_E_NO_SERVICE;
01097 
01098     /*
01099      * Make sure this handle has been opened
01100      */
01101     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01102 
01103     if (rv == -1)
01104         return SCARD_E_INVALID_HANDLE;
01105 
01106     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01107 
01108     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01109     {
01110         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01111 
01112         /* by default r == NULL */
01113         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01114             break;
01115     }
01116 
01117     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01118     {
01119         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01120         return SCARD_E_READER_UNAVAILABLE;
01121     }
01122 
01123     scBeginStruct.hCard = hCard;
01124     scBeginStruct.rv = SCARD_S_SUCCESS;
01125 
01126     /*
01127      * Query the server every so often until the sharing violation ends
01128      * and then hold the lock for yourself.
01129      */
01130 
01131     do
01132     {
01133         rv = WrapSHMWrite(SCARD_BEGIN_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
01134             sizeof(scBeginStruct),
01135             PCSCLITE_CLIENT_ATTEMPTS, (void *) &scBeginStruct);
01136 
01137         if (rv == -1)
01138         {
01139 
01140             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01141             return SCARD_E_NO_SERVICE;
01142         }
01143 
01144         /*
01145          * Read a message from the server
01146          */
01147         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
01148 
01149 
01150         memcpy(&scBeginStruct, &msgStruct.data, sizeof(scBeginStruct));
01151 
01152         if (rv == -1)
01153         {
01154 
01155             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01156             return SCARD_F_COMM_ERROR;
01157         }
01158 
01159     }
01160     while (scBeginStruct.rv == SCARD_E_SHARING_VIOLATION);
01161 
01162     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01163 
01164     PROFILE_END(scBeginStruct.rv);
01165 
01166     return scBeginStruct.rv;
01167 }
01168 
01207 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
01208 {
01209     LONG rv;
01210     end_struct scEndStruct;
01211     sharedSegmentMsg msgStruct;
01212     int randnum, i;
01213     DWORD dwContextIndex, dwChannelIndex;
01214 
01215     PROFILE_START
01216 
01217     /*
01218      * Zero out everything
01219      */
01220     randnum = 0;
01221 
01222     if (dwDisposition != SCARD_LEAVE_CARD &&
01223         dwDisposition != SCARD_RESET_CARD &&
01224         dwDisposition != SCARD_UNPOWER_CARD &&
01225         dwDisposition != SCARD_EJECT_CARD)
01226     {
01227         return SCARD_E_INVALID_VALUE;
01228     }
01229 
01230     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01231         return SCARD_E_NO_SERVICE;
01232 
01233     /*
01234      * Make sure this handle has been opened
01235      */
01236     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01237 
01238     if (rv == -1)
01239         return SCARD_E_INVALID_HANDLE;
01240 
01241     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01242 
01243     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01244     {
01245         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01246 
01247         /* by default r == NULL */
01248         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01249             break;
01250     }
01251 
01252     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01253     {
01254         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01255         return SCARD_E_READER_UNAVAILABLE;
01256     }
01257 
01258     scEndStruct.hCard = hCard;
01259     scEndStruct.dwDisposition = dwDisposition;
01260     scEndStruct.rv = SCARD_S_SUCCESS;
01261 
01262     rv = WrapSHMWrite(SCARD_END_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
01263         sizeof(scEndStruct),
01264         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scEndStruct);
01265 
01266     if (rv == -1)
01267     {
01268         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01269         return SCARD_E_NO_SERVICE;
01270     }
01271 
01272     /*
01273      * Read a message from the server
01274      */
01275     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
01276 
01277     memcpy(&scEndStruct, &msgStruct.data, sizeof(scEndStruct));
01278 
01279     if (rv == -1)
01280     {
01281         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01282         return SCARD_F_COMM_ERROR;
01283     }
01284 
01285     /*
01286      * This helps prevent starvation
01287      */
01288     randnum = SYS_RandomInt(1000, 10000);
01289     SYS_USleep(randnum);
01290 
01291     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01292 
01293     PROFILE_END(scEndStruct.rv)
01294 
01295     return scEndStruct.rv;
01296 }
01297 
01303 LONG SCardCancelTransaction(SCARDHANDLE hCard)
01304 {
01305     LONG rv;
01306     cancel_struct scCancelStruct;
01307     sharedSegmentMsg msgStruct;
01308     int i;
01309     DWORD dwContextIndex, dwChannelIndex;
01310 
01311     PROFILE_START
01312 
01313     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01314         return SCARD_E_NO_SERVICE;
01315 
01316     /*
01317      * Make sure this handle has been opened
01318      */
01319     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01320 
01321     if (rv == -1)
01322         return SCARD_E_INVALID_HANDLE;
01323 
01324     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01325 
01326     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01327     {
01328         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01329 
01330         /* by default r == NULL */
01331         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01332             break;
01333     }
01334 
01335     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01336     {
01337         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01338         return SCARD_E_READER_UNAVAILABLE;
01339     }
01340 
01341     scCancelStruct.hCard = hCard;
01342 
01343     rv = WrapSHMWrite(SCARD_CANCEL_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
01344         sizeof(scCancelStruct),
01345         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scCancelStruct);
01346 
01347     if (rv == -1)
01348     {
01349         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01350         return SCARD_E_NO_SERVICE;
01351     }
01352 
01353     /*
01354      * Read a message from the server
01355      */
01356     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
01357 
01358     memcpy(&scCancelStruct, &msgStruct.data, sizeof(scCancelStruct));
01359 
01360     if (rv == -1)
01361     {
01362         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01363         return SCARD_F_COMM_ERROR;
01364     }
01365 
01366     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01367 
01368     PROFILE_END(scCancelStruct.rv)
01369 
01370     return scCancelStruct.rv;
01371 }
01372 
01430 LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderNames,
01431     LPDWORD pcchReaderLen, LPDWORD pdwState,
01432     LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
01433 {
01434     DWORD dwReaderLen, dwAtrLen;
01435     LONG rv;
01436     int i;
01437     status_struct scStatusStruct;
01438     sharedSegmentMsg msgStruct;
01439     DWORD dwContextIndex, dwChannelIndex;
01440     char *r;
01441 
01442     PROFILE_START
01443 
01444     /*
01445      * Check for NULL parameters
01446      */
01447 
01448     if (pcchReaderLen == NULL || pcbAtrLen == NULL)
01449         return SCARD_E_INVALID_PARAMETER;
01450 
01451     /* length passed from caller */
01452     dwReaderLen = *pcchReaderLen;
01453     dwAtrLen = *pcbAtrLen;
01454 
01455     /* default output values */
01456     if (pdwState)
01457         *pdwState = 0;
01458 
01459     if (pdwProtocol)
01460         *pdwProtocol = 0;
01461 
01462     *pcchReaderLen = 0;
01463     *pcbAtrLen = 0;
01464 
01465     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01466         return SCARD_E_NO_SERVICE;
01467 
01468     /*
01469      * Make sure this handle has been opened
01470      */
01471     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01472 
01473     if (rv == -1)
01474         return SCARD_E_INVALID_HANDLE;
01475 
01476     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01477 
01478     r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01479     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01480     {
01481         /* by default r == NULL */
01482         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01483             break;
01484     }
01485 
01486     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01487     {
01488         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01489         return SCARD_E_READER_UNAVAILABLE;
01490     }
01491 
01492     /* initialise the structure */
01493     memset(&scStatusStruct, 0, sizeof(scStatusStruct));
01494     scStatusStruct.hCard = hCard;
01495 
01496     /* those sizes need to be initialised */
01497     scStatusStruct.pcchReaderLen = sizeof(scStatusStruct.mszReaderNames);
01498     scStatusStruct.pcbAtrLen = sizeof(scStatusStruct.pbAtr);
01499 
01500     rv = WrapSHMWrite(SCARD_STATUS, psContextMap[dwContextIndex].dwClientID,
01501         sizeof(scStatusStruct),
01502         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scStatusStruct);
01503 
01504     if (rv == -1)
01505     {
01506         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01507         return SCARD_E_NO_SERVICE;
01508     }
01509 
01510     /*
01511      * Read a message from the server
01512      */
01513     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
01514 
01515     memcpy(&scStatusStruct, &msgStruct.data, sizeof(scStatusStruct));
01516 
01517     if (rv == -1)
01518     {
01519         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01520         return SCARD_F_COMM_ERROR;
01521     }
01522 
01523     rv = scStatusStruct.rv;
01524     if (rv != SCARD_S_SUCCESS && rv != SCARD_E_INSUFFICIENT_BUFFER)
01525     {
01526         /*
01527          * An event must have occurred
01528          */
01529         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01530         return rv;
01531     }
01532 
01533     /*
01534      * Now continue with the client side SCardStatus
01535      */
01536 
01537     *pcchReaderLen = strlen(psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName) + 1;
01538     *pcbAtrLen = (readerStates[i])->cardAtrLength;
01539 
01540     if (pdwState)
01541         *pdwState = (readerStates[i])->readerState;
01542 
01543     if (pdwProtocol)
01544         *pdwProtocol = (readerStates[i])->cardProtocol;
01545 
01546     /* return SCARD_E_INSUFFICIENT_BUFFER only if buffer pointer is non NULL */
01547     if (mszReaderNames)
01548     {
01549         if (*pcchReaderLen > dwReaderLen)
01550             rv = SCARD_E_INSUFFICIENT_BUFFER;
01551 
01552         strncpy(mszReaderNames,
01553             psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName,
01554             dwReaderLen);
01555     }
01556 
01557     if (pbAtr)
01558     {
01559         if (*pcbAtrLen > dwAtrLen)
01560             rv = SCARD_E_INSUFFICIENT_BUFFER;
01561 
01562         memcpy(pbAtr, (readerStates[i])->cardAtr,
01563             min(*pcbAtrLen, dwAtrLen));
01564     }
01565 
01566     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01567 
01568     PROFILE_END(rv)
01569 
01570     return rv;
01571 }
01572 
01658 LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout,
01659     LPSCARD_READERSTATE_A rgReaderStates, DWORD cReaders)
01660 {
01661     PSCARD_READERSTATE_A currReader;
01662     PREADER_STATE rContext;
01663     DWORD dwTime = 0;
01664     DWORD dwState;
01665     DWORD dwBreakFlag = 0;
01666     int j;
01667     LONG dwContextIndex;
01668     int currentReaderCount = 0;
01669 
01670     PROFILE_START
01671 
01672     if (rgReaderStates == NULL && cReaders > 0)
01673         return SCARD_E_INVALID_PARAMETER;
01674 
01675     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01676         return SCARD_E_NO_SERVICE;
01677 
01678     /*
01679      * Make sure this context has been opened
01680      */
01681 
01682     dwContextIndex = SCardGetContextIndice(hContext);
01683     if (dwContextIndex == -1)
01684         return SCARD_E_INVALID_HANDLE;
01685 
01686     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01687 
01688     /*
01689      * Application is waiting for a reader - return the first available
01690      * reader
01691      */
01692 
01693     if (cReaders == 0)
01694     {
01695         while (1)
01696         {
01697             int i;
01698 
01699             if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01700             {
01701                 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01702                 return SCARD_E_NO_SERVICE;
01703             }
01704 
01705             for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01706             {
01707                 if ((readerStates[i])->readerID != 0)
01708                 {
01709                     /*
01710                      * Reader was found
01711                      */
01712                     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01713 
01714                     PROFILE_END(SCARD_S_SUCCESS)
01715 
01716                     return SCARD_S_SUCCESS;
01717                 }
01718             }
01719 
01720             if (dwTimeout == 0)
01721             {
01722                 /*
01723                  * return immediately - no reader available
01724                  */
01725                 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01726                 return SCARD_E_READER_UNAVAILABLE;
01727             }
01728 
01729             SYS_USleep(PCSCLITE_STATUS_WAIT);
01730 
01731             if (dwTimeout != INFINITE)
01732             {
01733                 dwTime += PCSCLITE_STATUS_WAIT;
01734 
01735                 if (dwTime >= (dwTimeout * 1000))
01736                 {
01737                     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01738 
01739                     PROFILE_END(SCARD_E_TIMEOUT)
01740 
01741                     return SCARD_E_TIMEOUT;
01742                 }
01743             }
01744         }
01745     }
01746     else
01747         if (cReaders >= PCSCLITE_MAX_READERS_CONTEXTS)
01748         {
01749             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01750             return SCARD_E_INVALID_VALUE;
01751         }
01752 
01753     /*
01754      * Check the integrity of the reader states structures
01755      */
01756 
01757     for (j = 0; j < cReaders; j++)
01758     {
01759         currReader = &rgReaderStates[j];
01760 
01761         if (currReader->szReader == NULL)
01762         {
01763             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01764             return SCARD_E_INVALID_VALUE;
01765         }
01766     }
01767 
01768     /*
01769      * End of search for readers
01770      */
01771 
01772     /*
01773      * Clear the event state for all readers
01774      */
01775     for (j = 0; j < cReaders; j++)
01776     {
01777         currReader = &rgReaderStates[j];
01778         currReader->dwEventState = 0;
01779     }
01780 
01781     /*
01782      * Now is where we start our event checking loop
01783      */
01784 
01785     Log1(PCSC_LOG_DEBUG, "Event Loop Start");
01786 
01787     psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_BLOCKING;
01788 
01789     /* Get the initial reader count on the system */
01790     for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
01791         if ((readerStates[j])->readerID != 0)
01792             currentReaderCount++;
01793 
01794     j = 0;
01795 
01796     do
01797     {
01798         int newReaderCount = 0;
01799         char ReaderCountChanged = FALSE;
01800 
01801         if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01802         {
01803             if (psContextMap[dwContextIndex].mMutex)
01804                 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01805 
01806             PROFILE_END(SCARD_E_NO_SERVICE)
01807 
01808             return SCARD_E_NO_SERVICE;
01809         }
01810 
01811         if (j == 0)
01812         {
01813             int i;
01814 
01815             for (i=0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01816                 if ((readerStates[i])->readerID != 0)
01817                     newReaderCount++;
01818 
01819             if (newReaderCount != currentReaderCount)
01820             {
01821                 Log1(PCSC_LOG_INFO, "Reader list changed");
01822                 ReaderCountChanged = TRUE;
01823                 currentReaderCount = newReaderCount;
01824             }
01825         }
01826         currReader = &rgReaderStates[j];
01827 
01828     /************ Look for IGNORED readers ****************************/
01829 
01830         if (currReader->dwCurrentState & SCARD_STATE_IGNORE)
01831             currReader->dwEventState = SCARD_STATE_IGNORE;
01832         else
01833         {
01834             LPSTR lpcReaderName;
01835             int i;
01836 
01837       /************ Looks for correct readernames *********************/
01838 
01839             lpcReaderName = (char *) currReader->szReader;
01840 
01841             for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01842             {
01843                 if (strcmp(lpcReaderName, (readerStates[i])->readerName) == 0)
01844                     break;
01845             }
01846 
01847             /*
01848              * The requested reader name is not recognized
01849              */
01850             if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01851             {
01852                 if (currReader->dwCurrentState & SCARD_STATE_UNKNOWN)
01853                     currReader->dwEventState = SCARD_STATE_UNKNOWN;
01854                 else
01855                 {
01856                     currReader->dwEventState =
01857                         SCARD_STATE_UNKNOWN | SCARD_STATE_CHANGED;
01858                     /*
01859                      * Spec says use SCARD_STATE_IGNORE but a removed USB
01860                      * reader with eventState fed into currentState will
01861                      * be ignored forever
01862                      */
01863                     dwBreakFlag = 1;
01864                 }
01865             }
01866             else
01867             {
01868 
01869                 /*
01870                  * The reader has come back after being away
01871                  */
01872                 if (currReader->dwCurrentState & SCARD_STATE_UNKNOWN)
01873                 {
01874                     currReader->dwEventState |= SCARD_STATE_CHANGED;
01875                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
01876                     dwBreakFlag = 1;
01877                 }
01878 
01879     /*****************************************************************/
01880 
01881                 /*
01882                  * Set the reader status structure
01883                  */
01884                 rContext = readerStates[i];
01885 
01886                 /*
01887                  * Now we check all the Reader States
01888                  */
01889                 dwState = rContext->readerState;
01890                 {
01891                     int currentCounter, stateCounter;
01892 
01893                     stateCounter = (dwState >> 16) & 0xFFFF;
01894                     currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF;
01895 
01896                     /* has the event counter changed since the last call? */
01897                     if (stateCounter != currentCounter)
01898                         currReader->dwEventState |= SCARD_STATE_CHANGED;
01899 
01900                     /* add an event counter in the upper word of dwEventState */
01901                     currReader->dwEventState =
01902                         ((currReader->dwEventState & 0xffff )
01903                         | (stateCounter << 16));  
01904                 }
01905 
01906     /*********** Check if the reader is in the correct state ********/
01907                 if (dwState & SCARD_UNKNOWN)
01908                 {
01909                     /*
01910                      * App thinks reader is in bad state and it is
01911                      */
01912                     if (currReader-> dwCurrentState & SCARD_STATE_UNAVAILABLE)
01913                         currReader->dwEventState = SCARD_STATE_UNAVAILABLE;
01914                     else
01915                     {
01916                         /*
01917                          * App thinks reader is in good state and it is
01918                          * not
01919                          */
01920                         currReader->dwEventState = SCARD_STATE_CHANGED |
01921                             SCARD_STATE_UNAVAILABLE;
01922                         dwBreakFlag = 1;
01923                     }
01924                 }
01925                 else
01926                 {
01927                     /*
01928                      * App thinks reader in bad state but it is not
01929                      */
01930                     if (currReader-> dwCurrentState & SCARD_STATE_UNAVAILABLE)
01931                     {
01932                         currReader->dwEventState &=
01933                             ~SCARD_STATE_UNAVAILABLE;
01934                         currReader->dwEventState |= SCARD_STATE_CHANGED;
01935                         dwBreakFlag = 1;
01936                     }
01937                 }
01938 
01939     /********** Check for card presence in the reader **************/
01940 
01941                 if (dwState & SCARD_PRESENT)
01942                 {
01943                     /* card present but not yet powered up */
01944                     if (0 == rContext->cardAtrLength)
01945                         /* Allow the status thread to convey information */
01946                         SYS_USleep(PCSCLITE_STATUS_POLL_RATE + 10);
01947 
01948                     currReader->cbAtr = rContext->cardAtrLength;
01949                     memcpy(currReader->rgbAtr, rContext->cardAtr,
01950                         currReader->cbAtr);
01951                 }
01952                 else
01953                     currReader->cbAtr = 0;
01954 
01955                 /*
01956                  * Card is now absent
01957                  */
01958                 if (dwState & SCARD_ABSENT)
01959                 {
01960                     currReader->dwEventState |= SCARD_STATE_EMPTY;
01961                     currReader->dwEventState &= ~SCARD_STATE_PRESENT;
01962                     currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
01963                     currReader->dwEventState &= ~SCARD_STATE_IGNORE;
01964                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
01965                     currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
01966                     currReader->dwEventState &= ~SCARD_STATE_ATRMATCH;
01967                     currReader->dwEventState &= ~SCARD_STATE_MUTE;
01968                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
01969 
01970                     /*
01971                      * After present the rest are assumed
01972                      */
01973                     if (currReader->dwCurrentState & SCARD_STATE_PRESENT)
01974                     {
01975                         currReader->dwEventState |= SCARD_STATE_CHANGED;
01976                         dwBreakFlag = 1;
01977                     }
01978 
01979                     /*
01980                      * Card is now present
01981                      */
01982                 } else if (dwState & SCARD_PRESENT)
01983                 {
01984                     currReader->dwEventState |= SCARD_STATE_PRESENT;
01985                     currReader->dwEventState &= ~SCARD_STATE_EMPTY;
01986                     currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
01987                     currReader->dwEventState &= ~SCARD_STATE_IGNORE;
01988                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
01989                     currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
01990                     currReader->dwEventState &= ~SCARD_STATE_MUTE;
01991 
01992                     if (currReader->dwCurrentState & SCARD_STATE_EMPTY)
01993                     {
01994                         currReader->dwEventState |= SCARD_STATE_CHANGED;
01995                         dwBreakFlag = 1;
01996                     }
01997 
01998                     if (dwState & SCARD_SWALLOWED)
01999                     {
02000                         if (currReader->dwCurrentState & SCARD_STATE_MUTE)
02001                             currReader->dwEventState |= SCARD_STATE_MUTE;
02002                         else
02003                         {
02004                             currReader->dwEventState |= SCARD_STATE_MUTE;
02005                             if (currReader->dwCurrentState
02006                                 != SCARD_STATE_UNAWARE)
02007                                 currReader->dwEventState |= SCARD_STATE_CHANGED;
02008                             dwBreakFlag = 1;
02009                         }
02010                     }
02011                     else
02012                     {
02013                         /*
02014                          * App thinks card is mute but it is not
02015                          */
02016                         if (currReader->dwCurrentState & SCARD_STATE_MUTE)
02017                         {
02018                             currReader->dwEventState |=
02019                                 SCARD_STATE_CHANGED;
02020                             dwBreakFlag = 1;
02021                         }
02022                     }
02023                 }
02024 
02025                 /*
02026                  * Now figure out sharing modes
02027                  */
02028                 if (rContext->readerSharing == -1)
02029                 {
02030                     currReader->dwEventState |= SCARD_STATE_EXCLUSIVE;
02031                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
02032                     if (currReader->dwCurrentState & SCARD_STATE_INUSE)
02033                     {
02034                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02035                         dwBreakFlag = 1;
02036                     }
02037                 }
02038                 else if (rContext->readerSharing >= 1)
02039                 {
02040                     /*
02041                      * A card must be inserted for it to be INUSE
02042                      */
02043                     if (dwState & SCARD_PRESENT)
02044                     {
02045                         currReader->dwEventState |= SCARD_STATE_INUSE;
02046                         currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
02047                         if (currReader-> dwCurrentState & SCARD_STATE_EXCLUSIVE)
02048                         {
02049                             currReader->dwEventState |= SCARD_STATE_CHANGED;
02050                             dwBreakFlag = 1;
02051                         }
02052                     }
02053                 }
02054                 else if (rContext->readerSharing == 0)
02055                 {
02056                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
02057                     currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
02058 
02059                     if (currReader->dwCurrentState & SCARD_STATE_INUSE)
02060                     {
02061                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02062                         dwBreakFlag = 1;
02063                     }
02064                     else if (currReader-> dwCurrentState
02065                         & SCARD_STATE_EXCLUSIVE)
02066                     {
02067                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02068                         dwBreakFlag = 1;
02069                     }
02070                 }
02071 
02072                 if (currReader->dwCurrentState == SCARD_STATE_UNAWARE)
02073                 {
02074                     /*
02075                      * Break out of the while .. loop and return status
02076                      * once all the status's for all readers is met
02077                      */
02078                     currReader->dwEventState |= SCARD_STATE_CHANGED;
02079                     dwBreakFlag = 1;
02080                 }
02081 
02082             }   /* End of SCARD_STATE_UNKNOWN */
02083 
02084         }   /* End of SCARD_STATE_IGNORE */
02085 
02086         /*
02087          * Counter and resetter
02088          */
02089         j = j + 1;
02090         if (j == cReaders)
02091         {
02092             if (!dwBreakFlag)
02093             {
02094                 /* break if the reader count changed,
02095                  * so that the calling application can update
02096                  * the reader list
02097                  */
02098                 if (ReaderCountChanged)
02099                     break;
02100             }
02101             j = 0;
02102         }
02103 
02104         /*
02105          * Declare all the break conditions
02106          */
02107 
02108         if (psContextMap[dwContextIndex].contextBlockStatus
02109                 == BLOCK_STATUS_RESUME)
02110             break;
02111 
02112         /*
02113          * Break if UNAWARE is set and all readers have been checked
02114          */
02115         if ((dwBreakFlag == 1) && (j == 0))
02116             break;
02117 
02118         /*
02119          * Timeout has occurred and all readers checked
02120          */
02121         if ((dwTimeout == 0) && (j == 0))
02122             break;
02123 
02124         if (dwTimeout != INFINITE && dwTimeout != 0)
02125         {
02126             /*
02127              * If time is greater than timeout and all readers have been
02128              * checked
02129              */
02130             if ((dwTime >= (dwTimeout * 1000)) && (j == 0))
02131             {
02132                 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02133                 PROFILE_END(SCARD_E_TIMEOUT)
02134                 return SCARD_E_TIMEOUT;
02135             }
02136         }
02137 
02138         /*
02139          * Only sleep once for each cycle of reader checks.
02140          */
02141         if (j == 0)
02142         {
02143             SYS_USleep(PCSCLITE_STATUS_WAIT);
02144             dwTime += PCSCLITE_STATUS_WAIT;
02145         }
02146     }
02147     while (1);
02148 
02149     Log1(PCSC_LOG_DEBUG, "Event Loop End");
02150 
02151     if (psContextMap[dwContextIndex].contextBlockStatus ==
02152             BLOCK_STATUS_RESUME)
02153     {
02154         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02155         PROFILE_END(SCARD_E_CANCELLED)
02156         return SCARD_E_CANCELLED;
02157     }
02158 
02159     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02160 
02161     PROFILE_END(SCARD_S_SUCCESS)
02162 
02163     return SCARD_S_SUCCESS;
02164 }
02165 
02212 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
02213     DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
02214     LPDWORD lpBytesReturned)
02215 {
02216     LONG rv;
02217     control_struct scControlStruct;
02218     sharedSegmentMsg msgStruct;
02219     int i;
02220     DWORD dwContextIndex, dwChannelIndex;
02221 
02222     PROFILE_START
02223 
02224     /* 0 bytes received by default */
02225     if (NULL != lpBytesReturned)
02226         *lpBytesReturned = 0;
02227 
02228     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
02229         return SCARD_E_NO_SERVICE;
02230 
02231     /*
02232      * Make sure this handle has been opened
02233      */
02234     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02235 
02236     if (rv == -1)
02237         return SCARD_E_INVALID_HANDLE;
02238 
02239     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02240 
02241     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02242     {
02243         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02244 
02245         /* by default r == NULL */
02246         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02247             break;
02248     }
02249 
02250     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02251     {
02252         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02253         return SCARD_E_READER_UNAVAILABLE;
02254     }
02255 
02256     if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
02257         || (cbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
02258     {
02259         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02260         return SCARD_E_INSUFFICIENT_BUFFER;
02261     }
02262 
02263     if ((cbSendLength > MAX_BUFFER_SIZE) || (cbRecvLength > MAX_BUFFER_SIZE))
02264     {
02265         /* extended control */
02266         unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED];
02267         control_struct_extended *scControlStructExtended = (control_struct_extended *)buffer;
02268         sharedSegmentMsg *pmsgStruct = (psharedSegmentMsg)buffer;
02269 
02270         scControlStructExtended->hCard = hCard;
02271         scControlStructExtended->dwControlCode = dwControlCode;
02272         scControlStructExtended->cbSendLength = cbSendLength;
02273         scControlStructExtended->cbRecvLength = cbRecvLength;
02274         scControlStructExtended->pdwBytesReturned = 0;
02275         scControlStructExtended->rv = SCARD_S_SUCCESS;
02276         /* The size of data to send is the size of
02277          * struct control_struct_extended WITHOUT the data[] field
02278          * plus the effective data[] size
02279          */
02280         scControlStructExtended->size = sizeof(*scControlStructExtended)
02281             - (sizeof(control_struct_extended) - offsetof(control_struct_extended, data))
02282             + cbSendLength;
02283         memcpy(scControlStructExtended->data, pbSendBuffer, cbSendLength);
02284 
02285         rv = WrapSHMWrite(SCARD_CONTROL_EXTENDED,
02286             psContextMap[dwContextIndex].dwClientID,
02287             scControlStructExtended->size,
02288             PCSCLITE_CLIENT_ATTEMPTS, buffer);
02289 
02290         if (rv == -1)
02291         {
02292             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02293             return SCARD_E_NO_SERVICE;
02294         }
02295 
02296         /*
02297          * Read a message from the server
02298          */
02299         /* read the first block */
02300         rv = SHMMessageReceive(buffer, sizeof(sharedSegmentMsg), psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
02301         if (rv == -1)
02302         {
02303             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02304             return SCARD_F_COMM_ERROR;
02305         }
02306 
02307         /* we receive a sharedSegmentMsg and not a control_struct_extended */
02308         scControlStructExtended = (control_struct_extended *)&(pmsgStruct -> data);
02309 
02310         /* a second block is present */
02311         if (scControlStructExtended->size > PCSCLITE_MAX_MESSAGE_SIZE)
02312         {
02313             rv = SHMMessageReceive(buffer + sizeof(sharedSegmentMsg),
02314                 scControlStructExtended->size-PCSCLITE_MAX_MESSAGE_SIZE,
02315                 psContextMap[dwContextIndex].dwClientID,
02316                 PCSCLITE_CLIENT_ATTEMPTS);
02317             if (rv == -1)
02318             {
02319                 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02320                 return SCARD_F_COMM_ERROR;
02321             }
02322         }
02323 
02324         if (scControlStructExtended -> rv == SCARD_S_SUCCESS)
02325         {
02326             /*
02327              * Copy and zero it so any secret information is not leaked
02328              */
02329             memcpy(pbRecvBuffer, scControlStructExtended -> data,
02330                 scControlStructExtended -> pdwBytesReturned);
02331             memset(scControlStructExtended -> data, 0x00,
02332                 scControlStructExtended -> pdwBytesReturned);
02333         }
02334 
02335         if (NULL != lpBytesReturned)
02336             *lpBytesReturned = scControlStructExtended -> pdwBytesReturned;
02337 
02338         rv = scControlStructExtended -> rv;
02339     }
02340     else
02341     {
02342         scControlStruct.hCard = hCard;
02343         scControlStruct.dwControlCode = dwControlCode;
02344         scControlStruct.cbSendLength = cbSendLength;
02345         scControlStruct.cbRecvLength = cbRecvLength;
02346         memcpy(scControlStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
02347 
02348         rv = WrapSHMWrite(SCARD_CONTROL, psContextMap[dwContextIndex].dwClientID,
02349             sizeof(scControlStruct), PCSCLITE_CLIENT_ATTEMPTS, &scControlStruct);
02350 
02351         if (rv == -1)
02352         {
02353             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02354             return SCARD_E_NO_SERVICE;
02355         }
02356 
02357         /*
02358          * Read a message from the server
02359          */
02360         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
02361 
02362         if (rv == -1)
02363         {
02364             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02365             return SCARD_F_COMM_ERROR;
02366         }
02367 
02368         memcpy(&scControlStruct, &msgStruct.data, sizeof(scControlStruct));
02369 
02370         if (NULL != lpBytesReturned)
02371             *lpBytesReturned = scControlStruct.dwBytesReturned;
02372 
02373         if (scControlStruct.rv == SCARD_S_SUCCESS)
02374         {
02375             /*
02376              * Copy and zero it so any secret information is not leaked
02377              */
02378             memcpy(pbRecvBuffer, scControlStruct.pbRecvBuffer,
02379                 scControlStruct.cbRecvLength);
02380             memset(scControlStruct.pbRecvBuffer, 0x00,
02381                 sizeof(scControlStruct.pbRecvBuffer));
02382         }
02383 
02384         rv = scControlStruct.rv;
02385     }
02386 
02387     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02388 
02389     PROFILE_END(rv)
02390 
02391     return rv;
02392 }
02393 
02474 LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
02475     LPDWORD pcbAttrLen)
02476 {
02477     LONG ret;
02478 
02479     PROFILE_START
02480 
02481     if (NULL == pcbAttrLen)
02482         return SCARD_E_INVALID_PARAMETER;
02483 
02484     /* if only get the length */
02485     if (NULL == pbAttr)
02486         /* this variable may not be set by the caller. use a reasonable size */
02487         *pcbAttrLen = MAX_BUFFER_SIZE;
02488 
02489     ret = SCardGetSetAttrib(hCard, SCARD_GET_ATTRIB, dwAttrId, pbAttr,
02490         pcbAttrLen);
02491 
02492     PROFILE_END(ret)
02493 
02494     return ret;
02495 }
02496 
02527 LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
02528     DWORD cbAttrLen)
02529 {
02530     LONG ret;
02531 
02532     PROFILE_START
02533 
02534     if (NULL == pbAttr || 0 == cbAttrLen)
02535         return SCARD_E_INVALID_PARAMETER;
02536 
02537     ret = SCardGetSetAttrib(hCard, SCARD_SET_ATTRIB, dwAttrId, (LPBYTE)pbAttr,
02538         &cbAttrLen);
02539 
02540     PROFILE_END(ret)
02541 
02542     return ret;
02543 }
02544 
02545 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
02546     LPBYTE pbAttr, LPDWORD pcbAttrLen)
02547 {
02548     LONG rv;
02549     getset_struct scGetSetStruct;
02550     sharedSegmentMsg msgStruct;
02551     int i;
02552     DWORD dwContextIndex, dwChannelIndex;
02553 
02554     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
02555         return SCARD_E_NO_SERVICE;
02556 
02557     /*
02558      * Make sure this handle has been opened
02559      */
02560     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02561 
02562     if (rv == -1)
02563         return SCARD_E_INVALID_HANDLE;
02564 
02565     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02566 
02567     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02568     {
02569         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02570 
02571         /* by default r == NULL */
02572         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02573             break;
02574     }
02575 
02576     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02577     {
02578         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02579         return SCARD_E_READER_UNAVAILABLE;
02580     }
02581 
02582     if (*pcbAttrLen > MAX_BUFFER_SIZE)
02583     {
02584         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02585         return SCARD_E_INSUFFICIENT_BUFFER;
02586     }
02587 
02588     scGetSetStruct.hCard = hCard;
02589     scGetSetStruct.dwAttrId = dwAttrId;
02590     scGetSetStruct.cbAttrLen = *pcbAttrLen;
02591     scGetSetStruct.rv = SCARD_E_NO_SERVICE;
02592     memset(scGetSetStruct.pbAttr, 0, sizeof(scGetSetStruct.pbAttr));
02593     if (SCARD_SET_ATTRIB == command)
02594         memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
02595 
02596     rv = WrapSHMWrite(command,
02597         psContextMap[dwContextIndex].dwClientID, sizeof(scGetSetStruct),
02598         PCSCLITE_CLIENT_ATTEMPTS, &scGetSetStruct);
02599 
02600     if (rv == -1)
02601     {
02602         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02603         return SCARD_E_NO_SERVICE;
02604     }
02605 
02606     /*
02607      * Read a message from the server
02608      */
02609     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
02610 
02611     if (rv == -1)
02612     {
02613         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02614         return SCARD_F_COMM_ERROR;
02615     }
02616 
02617     memcpy(&scGetSetStruct, &msgStruct.data, sizeof(scGetSetStruct));
02618 
02619     if ((SCARD_S_SUCCESS == scGetSetStruct.rv) && (SCARD_GET_ATTRIB == command))
02620     {
02621         /*
02622          * Copy and zero it so any secret information is not leaked
02623          */
02624         if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
02625         {
02626             scGetSetStruct.cbAttrLen = *pcbAttrLen;
02627             scGetSetStruct.rv = SCARD_E_INSUFFICIENT_BUFFER;
02628         }
02629         else
02630             *pcbAttrLen = scGetSetStruct.cbAttrLen;
02631 
02632         if (pbAttr)
02633             memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
02634 
02635         memset(scGetSetStruct.pbAttr, 0x00, sizeof(scGetSetStruct.pbAttr));
02636     }
02637 
02638     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02639 
02640     return scGetSetStruct.rv;
02641 }
02642 
02696 LONG SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci,
02697     LPCBYTE pbSendBuffer, DWORD cbSendLength,
02698     LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer,
02699     LPDWORD pcbRecvLength)
02700 {
02701     LONG rv;
02702     int i;
02703     DWORD dwContextIndex, dwChannelIndex;
02704 
02705     PROFILE_START
02706 
02707     if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
02708             pcbRecvLength == NULL || pioSendPci == NULL)
02709         return SCARD_E_INVALID_PARAMETER;
02710 
02711     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
02712         return SCARD_E_NO_SERVICE;
02713 
02714     /*
02715      * Make sure this handle has been opened
02716      */
02717     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02718 
02719     if (rv == -1)
02720     {
02721         *pcbRecvLength = 0;
02722         return SCARD_E_INVALID_HANDLE;
02723     }
02724 
02725     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02726 
02727     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02728     {
02729         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02730 
02731         /* by default r == NULL */
02732         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02733             break;
02734     }
02735 
02736     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02737     {
02738         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02739         return SCARD_E_READER_UNAVAILABLE;
02740     }
02741 
02742     if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
02743         || (*pcbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
02744     {
02745         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02746         return SCARD_E_INSUFFICIENT_BUFFER;
02747     }
02748 
02749     if ((cbSendLength > MAX_BUFFER_SIZE) || (*pcbRecvLength > MAX_BUFFER_SIZE))
02750     {
02751         /* extended APDU */
02752         unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED];
02753         transmit_struct_extended *scTransmitStructExtended = (transmit_struct_extended *)buffer;
02754         sharedSegmentMsg *pmsgStruct = (psharedSegmentMsg)buffer;
02755 
02756         scTransmitStructExtended->hCard = hCard;
02757         scTransmitStructExtended->cbSendLength = cbSendLength;
02758         scTransmitStructExtended->pcbRecvLength = *pcbRecvLength;
02759         /* The size of data to send is the size of
02760          * struct control_struct_extended WITHOUT the data[] field
02761          * plus the effective data[] size
02762          */
02763         scTransmitStructExtended->size = sizeof(*scTransmitStructExtended)
02764             - (sizeof(transmit_struct_extended) - offsetof(transmit_struct_extended, data))
02765             + cbSendLength;
02766         memcpy(&scTransmitStructExtended->pioSendPci, pioSendPci,
02767             sizeof(SCARD_IO_REQUEST));
02768         memcpy(scTransmitStructExtended->data, pbSendBuffer, cbSendLength);
02769         scTransmitStructExtended->rv = SCARD_S_SUCCESS;
02770 
02771         if (pioRecvPci)
02772         {
02773             memcpy(&scTransmitStructExtended->pioRecvPci, pioRecvPci,
02774                 sizeof(SCARD_IO_REQUEST));
02775         }
02776         else
02777         {
02778             scTransmitStructExtended->pioRecvPci.dwProtocol = SCARD_PROTOCOL_ANY;
02779             scTransmitStructExtended->pioRecvPci.cbPciLength = sizeof(SCARD_IO_REQUEST);
02780         }
02781 
02782         rv = WrapSHMWrite(SCARD_TRANSMIT_EXTENDED,
02783             psContextMap[dwContextIndex].dwClientID,
02784             scTransmitStructExtended->size,
02785             PCSCLITE_CLIENT_ATTEMPTS, buffer);
02786 
02787         if (rv == -1)
02788         {
02789             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02790             return SCARD_E_NO_SERVICE;
02791         }
02792 
02793         /*
02794          * Read a message from the server
02795          */
02796         /* read the first block */
02797         rv = SHMMessageReceive(buffer, sizeof(sharedSegmentMsg), psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
02798         if (rv == -1)
02799         {
02800             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02801             return SCARD_F_COMM_ERROR;
02802         }
02803 
02804         /* we receive a sharedSegmentMsg and not a transmit_struct_extended */
02805         scTransmitStructExtended = (transmit_struct_extended *)&(pmsgStruct -> data);
02806 
02807         /* a second block is present */
02808         if (scTransmitStructExtended->size > PCSCLITE_MAX_MESSAGE_SIZE)
02809         {
02810             rv = SHMMessageReceive(buffer + sizeof(sharedSegmentMsg),
02811                 scTransmitStructExtended->size-PCSCLITE_MAX_MESSAGE_SIZE,
02812                 psContextMap[dwContextIndex].dwClientID,
02813                 PCSCLITE_CLIENT_ATTEMPTS);
02814             if (rv == -1)
02815             {
02816                 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02817                 return SCARD_F_COMM_ERROR;
02818             }
02819         }
02820 
02821         if (scTransmitStructExtended -> rv == SCARD_S_SUCCESS)
02822         {
02823             /*
02824              * Copy and zero it so any secret information is not leaked
02825              */
02826             memcpy(pbRecvBuffer, scTransmitStructExtended -> data,
02827                 scTransmitStructExtended -> pcbRecvLength);
02828             memset(scTransmitStructExtended -> data, 0x00,
02829                 scTransmitStructExtended -> pcbRecvLength);
02830 
02831             if (pioRecvPci)
02832                 memcpy(pioRecvPci, &scTransmitStructExtended -> pioRecvPci,
02833                     sizeof(SCARD_IO_REQUEST));
02834         }
02835 
02836         *pcbRecvLength = scTransmitStructExtended -> pcbRecvLength;
02837         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02838 
02839         rv = scTransmitStructExtended -> rv;
02840     }
02841     else
02842     {
02843         /* short APDU */
02844         transmit_struct scTransmitStruct;
02845         sharedSegmentMsg msgStruct;
02846 
02847         scTransmitStruct.hCard = hCard;
02848         scTransmitStruct.cbSendLength = cbSendLength;
02849         scTransmitStruct.pcbRecvLength = *pcbRecvLength;
02850         memcpy(&scTransmitStruct.pioSendPci, pioSendPci,
02851             sizeof(SCARD_IO_REQUEST));
02852         memcpy(scTransmitStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
02853         memset(scTransmitStruct.pbSendBuffer+cbSendLength, 0, sizeof(scTransmitStruct.pbSendBuffer)-cbSendLength);
02854         memset(scTransmitStruct.pbRecvBuffer, 0, sizeof(scTransmitStruct.pbRecvBuffer));
02855         scTransmitStruct.rv = SCARD_S_SUCCESS;
02856 
02857         scTransmitStruct.pioRecvPci.dwProtocol = SCARD_PROTOCOL_ANY;
02858         scTransmitStruct.pioRecvPci.cbPciLength = sizeof(scTransmitStruct.pioRecvPci);
02859 
02860         rv = WrapSHMWrite(SCARD_TRANSMIT,
02861             psContextMap[dwContextIndex].dwClientID, sizeof(scTransmitStruct),
02862             PCSCLITE_CLIENT_ATTEMPTS, (void *) &scTransmitStruct);
02863 
02864         if (rv == -1)
02865         {
02866             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02867             return SCARD_E_NO_SERVICE;
02868         }
02869 
02870         /*
02871          * Read a message from the server
02872          */
02873         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
02874 
02875         memcpy(&scTransmitStruct, &msgStruct.data, sizeof(scTransmitStruct));
02876 
02877         if (rv == -1)
02878         {
02879             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02880             return SCARD_F_COMM_ERROR;
02881         }
02882 
02883         /*
02884          * Zero it and free it so any secret information cannot be leaked
02885          */
02886         memset(scTransmitStruct.pbSendBuffer, 0x00, cbSendLength);
02887 
02888         if (scTransmitStruct.rv == SCARD_S_SUCCESS)
02889         {
02890             /*
02891              * Copy and zero it so any secret information is not leaked
02892              */
02893             memcpy(pbRecvBuffer, scTransmitStruct.pbRecvBuffer,
02894                 scTransmitStruct.pcbRecvLength);
02895             memset(scTransmitStruct.pbRecvBuffer, 0x00,
02896                 scTransmitStruct.pcbRecvLength);
02897 
02898             if (pioRecvPci)
02899                 memcpy(pioRecvPci, &scTransmitStruct.pioRecvPci,
02900                     sizeof(SCARD_IO_REQUEST));
02901         }
02902 
02903         *pcbRecvLength = scTransmitStruct.pcbRecvLength;
02904         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02905 
02906         rv = scTransmitStruct.rv;
02907     }
02908 
02909     PROFILE_END(rv)
02910 
02911     return rv;
02912 }
02913 
02943 LONG SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups,
02944     LPSTR mszReaders, LPDWORD pcchReaders)
02945 {
02946     DWORD dwReadersLen;
02947     int i, lastChrPtr;
02948     LONG dwContextIndex;
02949 
02950     PROFILE_START
02951 
02952     /*
02953      * Check for NULL parameters
02954      */
02955     if (pcchReaders == NULL)
02956         return SCARD_E_INVALID_PARAMETER;
02957 
02958     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
02959         return SCARD_E_NO_SERVICE;
02960 
02961     /*
02962      * Make sure this context has been opened
02963      */
02964     dwContextIndex = SCardGetContextIndice(hContext);
02965     if (dwContextIndex == -1)
02966         return SCARD_E_INVALID_HANDLE;
02967 
02968     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02969 
02970     dwReadersLen = 0;
02971     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02972         if ((readerStates[i])->readerID != 0)
02973             dwReadersLen += strlen((readerStates[i])->readerName) + 1;
02974 
02975     /* for the last NULL byte */
02976     dwReadersLen += 1;
02977 
02978     if ((mszReaders == NULL)    /* text array not allocated */
02979         || (*pcchReaders == 0)) /* size == 0 */
02980     {
02981         *pcchReaders = dwReadersLen;
02982         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02983         PROFILE_END(SCARD_S_SUCCESS)
02984         return SCARD_S_SUCCESS;
02985     }
02986 
02987     if (*pcchReaders < dwReadersLen)
02988     {
02989         *pcchReaders = dwReadersLen;
02990         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02991         PROFILE_END(SCARD_E_INSUFFICIENT_BUFFER)
02992         return SCARD_E_INSUFFICIENT_BUFFER;
02993     }
02994 
02995     lastChrPtr = 0;
02996     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02997     {
02998         if ((readerStates[i])->readerID != 0)
02999         {
03000             /*
03001              * Build the multi-string
03002              */
03003             strcpy(&mszReaders[lastChrPtr], (readerStates[i])->readerName);
03004             lastChrPtr += strlen((readerStates[i])->readerName)+1;
03005         }
03006     }
03007     mszReaders[lastChrPtr] = '\0';  /* Add the last null */
03008 
03009     *pcchReaders = dwReadersLen;
03010 
03011     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03012 
03013     PROFILE_END(SCARD_S_SUCCESS)
03014 
03015     return SCARD_S_SUCCESS;
03016 }
03017 
03049 LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups,
03050     LPDWORD pcchGroups)
03051 {
03052     LONG rv = SCARD_S_SUCCESS;
03053     LONG dwContextIndex;
03054 
03055     PROFILE_START
03056 
03057     const char ReaderGroup[] = "SCard$DefaultReaders";
03058     const int dwGroups = strlen(ReaderGroup) + 2;
03059 
03060     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
03061         return SCARD_E_NO_SERVICE;
03062 
03063     /*
03064      * Make sure this context has been opened
03065      */
03066     dwContextIndex = SCardGetContextIndice(hContext);
03067     if (dwContextIndex == -1)
03068         return SCARD_E_INVALID_HANDLE;
03069 
03070     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
03071 
03072     if (mszGroups)
03073     {
03074 
03075         if (*pcchGroups < dwGroups)
03076             rv = SCARD_E_INSUFFICIENT_BUFFER;
03077         else
03078         {
03079             memset(mszGroups, 0, dwGroups);
03080             memcpy(mszGroups, ReaderGroup, strlen(ReaderGroup));
03081         }
03082     }
03083 
03084     *pcchGroups = dwGroups;
03085 
03086     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03087 
03088     PROFILE_END(rv)
03089 
03090     return rv;
03091 }
03092 
03120 LONG SCardCancel(SCARDCONTEXT hContext)
03121 {
03122     LONG dwContextIndex;
03123 
03124     PROFILE_START
03125 
03126     dwContextIndex = SCardGetContextIndice(hContext);
03127 
03128     if (dwContextIndex == -1)
03129         return SCARD_E_INVALID_HANDLE;
03130 
03131     /*
03132      * Set the block status for this Context so blocking calls will
03133      * complete
03134      */
03135     psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_RESUME;
03136 
03137     PROFILE_END(SCARD_S_SUCCESS)
03138 
03139     return SCARD_S_SUCCESS;
03140 }
03141 
03165 LONG SCardIsValidContext(SCARDCONTEXT hContext)
03166 {
03167     LONG rv;
03168     LONG dwContextIndex;
03169 
03170     PROFILE_START
03171 
03172     rv = SCARD_S_SUCCESS;
03173 
03174     /* Check if the _same_ server is running */
03175     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
03176         return SCARD_E_INVALID_HANDLE;
03177 
03178     /*
03179      * Make sure this context has been opened
03180      */
03181     dwContextIndex = SCardGetContextIndice(hContext);
03182     if (dwContextIndex == -1)
03183         rv = SCARD_E_INVALID_HANDLE;
03184 
03185     PROFILE_END(rv)
03186 
03187     return rv;
03188 }
03189 
03206 static LONG SCardAddContext(SCARDCONTEXT hContext, DWORD dwClientID)
03207 {
03208     int i;
03209 
03210     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03211     {
03212         if (psContextMap[i].hContext == 0)
03213         {
03214             psContextMap[i].hContext = hContext;
03215             psContextMap[i].dwClientID = dwClientID;
03216             psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;
03217             psContextMap[i].mMutex = malloc(sizeof(PCSCLITE_MUTEX));
03218             SYS_MutexInit(psContextMap[i].mMutex);
03219             return SCARD_S_SUCCESS;
03220         }
03221     }
03222 
03223     return SCARD_E_NO_MEMORY;
03224 }
03225 
03238 static LONG SCardGetContextIndice(SCARDCONTEXT hContext)
03239 {
03240     LONG rv;
03241 
03242     SCardLockThread();
03243     rv = SCardGetContextIndiceTH(hContext);
03244     SCardUnlockThread();
03245 
03246     return rv;
03247 }
03248 
03261 static LONG SCardGetContextIndiceTH(SCARDCONTEXT hContext)
03262 {
03263     int i;
03264 
03265     /*
03266      * Find this context and return it's spot in the array
03267      */
03268     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03269     {
03270         if ((hContext == psContextMap[i].hContext) && (hContext != 0))
03271             return i;
03272     }
03273 
03274     return -1;
03275 }
03276 
03286 static LONG SCardRemoveContext(SCARDCONTEXT hContext)
03287 {
03288     LONG  retIndice;
03289 
03290     retIndice = SCardGetContextIndiceTH(hContext);
03291 
03292     if (retIndice == -1)
03293         return SCARD_E_INVALID_HANDLE;
03294     else
03295         return SCardCleanContext(retIndice);
03296 }
03297 
03298 static LONG SCardCleanContext(LONG indice)
03299 {
03300     int i;
03301 
03302     psContextMap[indice].hContext = 0;
03303     SHMClientCloseSession(psContextMap[indice].dwClientID);
03304     psContextMap[indice].dwClientID = 0;
03305     free(psContextMap[indice].mMutex);
03306     psContextMap[indice].mMutex = NULL;
03307     psContextMap[indice].contextBlockStatus = BLOCK_STATUS_RESUME;
03308 
03309     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03310     {
03311         /*
03312          * Reset the \c hCard structs to zero
03313          */
03314         psContextMap[indice].psChannelMap[i].hCard = 0;
03315         free(psContextMap[indice].psChannelMap[i].readerName);
03316         psContextMap[indice].psChannelMap[i].readerName = NULL;
03317     }
03318 
03319     return SCARD_S_SUCCESS;
03320 }
03321 
03322 /*
03323  * Functions for managing hCard values returned from SCardConnect.
03324  */
03325 
03326 static LONG SCardAddHandle(SCARDHANDLE hCard, DWORD dwContextIndex,
03327     LPCSTR readerName)
03328 {
03329     int i;
03330 
03331     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03332     {
03333         if (psContextMap[dwContextIndex].psChannelMap[i].hCard == 0)
03334         {
03335             psContextMap[dwContextIndex].psChannelMap[i].hCard = hCard;
03336             psContextMap[dwContextIndex].psChannelMap[i].readerName = strdup(readerName);
03337             return SCARD_S_SUCCESS;
03338         }
03339     }
03340 
03341     return SCARD_E_NO_MEMORY;
03342 }
03343 
03344 static LONG SCardRemoveHandle(SCARDHANDLE hCard)
03345 {
03346     DWORD dwContextIndice, dwChannelIndice;
03347     LONG rv;
03348 
03349     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndice, &dwChannelIndice);
03350 
03351     if (rv == -1)
03352         return SCARD_E_INVALID_HANDLE;
03353     else
03354     {
03355         psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].hCard = 0;
03356         free(psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName);
03357         psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName = NULL;
03358         return SCARD_S_SUCCESS;
03359     }
03360 }
03361 
03362 static LONG SCardGetIndicesFromHandle(SCARDHANDLE hCard, PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
03363 {
03364     LONG rv;
03365 
03366     if (0 == hCard)
03367         return -1;
03368 
03369     SCardLockThread();
03370     rv = SCardGetIndicesFromHandleTH(hCard, pdwContextIndice, pdwChannelIndice);
03371     SCardUnlockThread();
03372 
03373     return rv;
03374 }
03375 
03376 static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE hCard, PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
03377 {
03378     int i;
03379 
03380     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03381     {
03382         if (psContextMap[i].hContext != 0)
03383         {
03384             int j;
03385 
03386             for (j = 0; j < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; j++)
03387             {
03388                 if (psContextMap[i].psChannelMap[j].hCard == hCard)
03389                 {
03390                     *pdwContextIndice = i;
03391                     *pdwChannelIndice = j;
03392                     return SCARD_S_SUCCESS;
03393                 }
03394             }
03395 
03396         }
03397     }
03398 
03399     return -1;
03400 }
03401 
03409 LONG SCardCheckDaemonAvailability(void)
03410 {
03411     LONG rv;
03412     struct stat statBuffer;
03413 
03414     rv = SYS_Stat(PCSCLITE_PUBSHM_FILE, &statBuffer);
03415 
03416     if (rv != 0)
03417     {
03418         Log1(PCSC_LOG_INFO, "PCSC Not Running");
03419         return SCARD_E_NO_SERVICE;
03420     }
03421 
03422     if (daemon_ctime)
03423     {
03424         /* when the _first_ reader is connected the ctime changes
03425          * I don't know why yet */
03426         if (statBuffer.st_ctime > daemon_ctime)
03427         {
03428             pid_t new_pid;
03429 
03430             new_pid = GetDaemonPid();
03431 
03432             /* so we also check the daemon pid to be sure it is a new pcscd */
03433             if (new_pid != daemon_pid)
03434             {
03435                 int i;
03436 
03437                 Log1(PCSC_LOG_INFO, "PCSC restarted");
03438 
03439                 /* invalid all handles */
03440                 SCardLockThread();
03441 
03442                 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03443                     if (psContextMap[i].hContext)
03444                         SCardCleanContext(i);
03445 
03446                 SCardUnlockThread();
03447 
03448                 /* reset pcscd status */
03449                 daemon_ctime = 0;
03450 
03451                 /* reset the lib */
03452                 SCardUnload();
03453 
03454                 return SCARD_E_NO_SERVICE;
03455             }
03456 
03457             daemon_ctime = statBuffer.st_ctime;
03458         }
03459     }
03460     else
03461     {
03462         daemon_ctime = statBuffer.st_ctime;
03463         daemon_pid = GetDaemonPid();
03464     }
03465 
03466     return SCARD_S_SUCCESS;
03467 }
03468 
03474 #ifdef __SUNPRO_C
03475 #pragma fini (SCardUnload)
03476 #endif
03477 
03478 void DESTRUCTOR SCardUnload(void)
03479 {
03480     int i;
03481 
03482     if (!isExecuted)
03483         return;
03484 
03485     /* unmap public shared file from memory */
03486     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03487     {
03488         if (readerStates[i] != NULL)
03489         {
03490             SYS_PublicMemoryUnmap(readerStates[i], sizeof(READER_STATE));
03491             readerStates[i] = NULL;
03492         }
03493     }
03494 
03495     SYS_CloseFile(mapAddr);
03496     isExecuted = 0;
03497 }
03498 

Generated on Wed Oct 8 02:23:54 2008 for pcsc-lite by  doxygen 1.5.6