pcsc-lite 1.5.5

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 4333 2009-07-21 11:36:36Z rousseau $
00010  */
00011 
00021 #include "config.h"
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <sys/types.h>
00025 #include <fcntl.h>
00026 #include <unistd.h>
00027 #include <sys/un.h>
00028 #include <errno.h>
00029 #include <stddef.h>
00030 #include <sys/time.h>
00031 
00032 #include "misc.h"
00033 #include "pcscd.h"
00034 #include "winscard.h"
00035 #include "debug.h"
00036 #include "thread_generic.h"
00037 #include "strlcpycat.h"
00038 
00039 #include "readerfactory.h"
00040 #include "eventhandler.h"
00041 #include "sys_generic.h"
00042 #include "winscard_msg.h"
00043 #include "utils.h"
00044 
00046 #define SCARD_PROTOCOL_ANY_OLD  0x1000
00047 
00048 #ifndef TRUE
00049 #define TRUE 1
00050 #define FALSE 0
00051 #endif
00052 
00053 /* r = a - b */
00054 static long int time_sub(struct timeval *a, struct timeval *b)
00055 {
00056     struct timeval r;
00057     r.tv_sec = a -> tv_sec - b -> tv_sec;
00058     r.tv_usec = a -> tv_usec - b -> tv_usec;
00059     if (r.tv_usec < 0)
00060     {
00061         r.tv_sec--;
00062         r.tv_usec += 1000000;
00063     }
00064 
00065     return r.tv_sec * 1000000 + r.tv_usec;
00066 } /* time_sub */
00067 
00068 
00069 #undef DO_PROFILE
00070 #ifdef DO_PROFILE
00071 
00072 #define PROFILE_FILE "/tmp/pcsc_profile"
00073 #include <stdio.h>
00074 #include <sys/time.h>
00075 
00076 struct timeval profile_time_start;
00077 FILE *profile_fd;
00078 char profile_tty;
00079 char fct_name[100];
00080 
00081 #define PROFILE_START profile_start(__FUNCTION__);
00082 #define PROFILE_END(rv) profile_end(__FUNCTION__, rv);
00083 
00084 static void profile_start(const char *f)
00085 {
00086     static char initialized = FALSE;
00087 
00088     if (!initialized)
00089     {
00090         char filename[80];
00091 
00092         initialized = TRUE;
00093         sprintf(filename, "%s-%d", PROFILE_FILE, getuid());
00094         profile_fd = fopen(filename, "a+");
00095         if (NULL == profile_fd)
00096         {
00097             fprintf(stderr, "\33[01;31mCan't open %s: %s\33[0m\n",
00098                 PROFILE_FILE, strerror(errno));
00099             exit(-1);
00100         }
00101         fprintf(profile_fd, "\nStart a new profile\n");
00102 
00103         if (isatty(fileno(stderr)))
00104             profile_tty = TRUE;
00105         else
00106             profile_tty = FALSE;
00107     }
00108 
00109     /* PROFILE_END was not called before? */
00110     if (profile_tty && fct_name[0])
00111         printf("\33[01;34m WARNING: %s starts before %s finishes\33[0m\n",
00112             f, fct_name);
00113 
00114     strlcpy(fct_name, f, sizeof(fct_name));
00115 
00116     gettimeofday(&profile_time_start, NULL);
00117 } /* profile_start */
00118 
00119 static void profile_end(const char *f, LONG rv)
00120 {
00121     struct timeval profile_time_end;
00122     long d;
00123 
00124     gettimeofday(&profile_time_end, NULL);
00125     d = time_sub(&profile_time_end, &profile_time_start);
00126 
00127     if (profile_tty)
00128     {
00129         if (fct_name[0])
00130         {
00131             if (strncmp(fct_name, f, sizeof(fct_name)))
00132                 printf("\33[01;34m WARNING: %s ends before %s\33[0m\n",
00133                         f, fct_name);
00134         }
00135         else
00136             printf("\33[01;34m WARNING: %s ends but we lost its start\33[0m\n",
00137                 f);
00138 
00139         /* allow to detect missing PROFILE_END calls */
00140         fct_name[0] = '\0';
00141 
00142         if (rv != SCARD_S_SUCCESS)
00143             fprintf(stderr,
00144                 "\33[01;31mRESULT %s \33[35m%ld \33[34m0x%08lX %s\33[0m\n",
00145                 f, d, rv, pcsc_stringify_error(rv));
00146         else
00147             fprintf(stderr, "\33[01;31mRESULT %s \33[35m%ld\33[0m\n", f, d);
00148     }
00149     fprintf(profile_fd, "%s %ld\n", f, d);
00150     fflush(profile_fd);
00151 } /* profile_end */
00152 
00153 #else
00154 #define PROFILE_START
00155 #define PROFILE_END(rv)
00156 #endif
00157 
00162 struct _psChannelMap
00163 {
00164     SCARDHANDLE hCard;
00165     LPSTR readerName;
00166 };
00167 
00168 typedef struct _psChannelMap CHANNEL_MAP, *PCHANNEL_MAP;
00169 
00175 static struct _psContextMap
00176 {
00177     DWORD dwClientID;               
00178     SCARDCONTEXT hContext;          
00179     DWORD contextBlockStatus;
00180     PCSCLITE_MUTEX_T mMutex;        
00181     CHANNEL_MAP psChannelMap[PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS];
00182 } psContextMap[PCSCLITE_MAX_APPLICATION_CONTEXTS];
00183 
00187 static short isExecuted = 0;
00188 
00189 
00193 static time_t daemon_ctime = 0;
00194 static pid_t daemon_pid = 0;
00199 static pid_t client_pid = 0;
00200 
00206 static int mapAddr = 0;
00207 
00212 static PCSCLITE_MUTEX clientMutex = PTHREAD_MUTEX_INITIALIZER;
00213 
00220 static PREADER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS];
00221 
00222 PCSC_API SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_T0, 8 };    
00223 PCSC_API SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, 8 };    
00224 PCSC_API SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_RAW, 8 };  
00227 static LONG SCardAddContext(SCARDCONTEXT, DWORD);
00228 static LONG SCardGetContextIndice(SCARDCONTEXT);
00229 static LONG SCardGetContextIndiceTH(SCARDCONTEXT);
00230 static LONG SCardRemoveContext(SCARDCONTEXT);
00231 static LONG SCardCleanContext(LONG indice);
00232 
00233 static LONG SCardAddHandle(SCARDHANDLE, DWORD, LPCSTR);
00234 static LONG SCardGetIndicesFromHandle(SCARDHANDLE, /*@out@*/ PDWORD,
00235     /*@out@*/ PDWORD);
00236 static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE, /*@out@*/ PDWORD,
00237     /*@out@*/ PDWORD);
00238 static LONG SCardRemoveHandle(SCARDHANDLE);
00239 
00240 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
00241     LPBYTE pbAttr, LPDWORD pcbAttrLen);
00242 
00243 void DESTRUCTOR SCardUnload(void);
00244 
00245 /*
00246  * Thread safety functions
00247  */
00254 inline static LONG SCardLockThread(void)
00255 {
00256     return SYS_MutexLock(&clientMutex);
00257 }
00258 
00264 inline static LONG SCardUnlockThread(void)
00265 {
00266     return SYS_MutexUnLock(&clientMutex);
00267 }
00268 
00269 static LONG SCardEstablishContextTH(DWORD, LPCVOID, LPCVOID,
00270     /*@out@*/ LPSCARDCONTEXT);
00271 
00305 LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
00306     LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
00307 {
00308     LONG rv;
00309 
00310     PROFILE_START
00311 
00312     /* Check if the server is running */
00313     rv = SCardCheckDaemonAvailability();
00314     if (SCARD_E_INVALID_HANDLE == rv)
00315         /* we reconnected to a daemon or we got called from a forked child */
00316         rv = SCardCheckDaemonAvailability();
00317 
00318     if (rv != SCARD_S_SUCCESS)
00319         return rv;
00320 
00321     (void)SCardLockThread();
00322     rv = SCardEstablishContextTH(dwScope, pvReserved1,
00323         pvReserved2, phContext);
00324     (void)SCardUnlockThread();
00325 
00326     PROFILE_END(rv)
00327 
00328     return rv;
00329 }
00330 
00357 static LONG SCardEstablishContextTH(DWORD dwScope,
00358     /*@unused@*/ LPCVOID pvReserved1,
00359     /*@unused@*/ LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
00360 {
00361     LONG rv;
00362     int i;
00363     establish_struct scEstablishStruct;
00364     sharedSegmentMsg msgStruct;
00365     uint32_t dwClientID = 0;
00366 
00367     (void)pvReserved1;
00368     (void)pvReserved2;
00369     if (phContext == NULL)
00370         return SCARD_E_INVALID_PARAMETER;
00371     else
00372         *phContext = 0;
00373 
00374     /*
00375      * Do this only once:
00376      * - Initialize debug of need.
00377      * - Set up the memory mapped structures for reader states.
00378      * - Allocate each reader structure.
00379      * - Initialize context struct.
00380      */
00381     if (isExecuted == 0)
00382     {
00383         int pageSize;
00384 
00385         /*
00386          * Do any system initilization here
00387          */
00388         (void)SYS_Initialize();
00389 
00390         /*
00391          * Set up the memory mapped reader stats structures
00392          */
00393         mapAddr = SYS_OpenFile(PCSCLITE_PUBSHM_FILE, O_RDONLY, 0);
00394         if (mapAddr < 0)
00395         {
00396             Log3(PCSC_LOG_CRITICAL, "Cannot open public shared file %s: %s",
00397                 PCSCLITE_PUBSHM_FILE, strerror(errno));
00398             return SCARD_E_NO_SERVICE;
00399         }
00400 
00401         /* close on exec so that child processes do not inherits the file
00402          * descriptor. The child process will call SCardEstablishContext()
00403          * if needed. */
00404         (void)fcntl(mapAddr, F_SETFD, FD_CLOEXEC);
00405 
00406         pageSize = SYS_GetPageSize();
00407 
00408         /*
00409          * Allocate each reader structure in the memory map
00410          */
00411         for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00412         {
00413             readerStates[i] =
00414                 (PREADER_STATE)SYS_PublicMemoryMap(sizeof(READER_STATE),
00415                 mapAddr, (i * pageSize));
00416             if (readerStates[i] == NULL)
00417             {
00418                 Log2(PCSC_LOG_CRITICAL, "Cannot public memory map: %s",
00419                     strerror(errno));
00420                 (void)SYS_CloseFile(mapAddr);   /* Close the memory map file */
00421                 return SCARD_F_INTERNAL_ERROR;
00422             }
00423         }
00424 
00425         /*
00426          * Initializes the application contexts and all channels for each one
00427          */
00428         for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
00429         {
00430             int j;
00431 
00432             /*
00433              * Initially set the context struct to zero
00434              */
00435             psContextMap[i].dwClientID = 0;
00436             psContextMap[i].hContext = 0;
00437             psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;
00438             psContextMap[i].mMutex = NULL;
00439 
00440             for (j = 0; j < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; j++)
00441             {
00442                 /*
00443                  * Initially set the hcard structs to zero
00444                  */
00445                 psContextMap[i].psChannelMap[j].hCard = 0;
00446                 psContextMap[i].psChannelMap[j].readerName = NULL;
00447             }
00448         }
00449 
00450     }
00451 
00452     /*
00453      * Is there a free slot for this connection ?
00454      */
00455 
00456     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
00457     {
00458         if (psContextMap[i].dwClientID == 0)
00459             break;
00460     }
00461 
00462     if (i == PCSCLITE_MAX_APPLICATION_CONTEXTS)
00463     {
00464         return SCARD_E_NO_MEMORY;
00465     }
00466 
00467     /* Establishes a connection to the server */
00468     if (SHMClientSetupSession(&dwClientID) != 0)
00469     {
00470         (void)SYS_CloseFile(mapAddr);
00471         return SCARD_E_NO_SERVICE;
00472     }
00473 
00474     {   /* exchange client/server protocol versions */
00475         version_struct *veStr;
00476 
00477         memset(&msgStruct, 0, sizeof(msgStruct));
00478         msgStruct.mtype = CMD_VERSION;
00479         msgStruct.user_id = SYS_GetUID();
00480         msgStruct.group_id = SYS_GetGID();
00481         msgStruct.command = 0;
00482         msgStruct.date = time(NULL);
00483 
00484         veStr = &msgStruct.veStr;
00485         veStr->major = PROTOCOL_VERSION_MAJOR;
00486         veStr->minor = PROTOCOL_VERSION_MINOR;
00487 
00488         if (-1 == SHMMessageSend(&msgStruct, sizeof(msgStruct), dwClientID,
00489             PCSCLITE_MCLIENT_ATTEMPTS))
00490             return SCARD_E_NO_SERVICE;
00491 
00492         /*
00493          * Read a message from the server
00494          */
00495         if (-1 == SHMMessageReceive(&msgStruct, sizeof(msgStruct), dwClientID,
00496             PCSCLITE_CLIENT_ATTEMPTS))
00497         {
00498             Log1(PCSC_LOG_CRITICAL, "Your pcscd is too old and does not support CMD_VERSION");
00499             return SCARD_F_COMM_ERROR;
00500         }
00501 
00502         Log3(PCSC_LOG_INFO, "Server is protocol version %d:%d",
00503             veStr->major, veStr->minor);
00504 
00505         if (veStr->rv != SCARD_S_SUCCESS)
00506             return veStr->rv;
00507 
00508         isExecuted = 1;
00509     }
00510 
00511 again:
00512     /*
00513      * Try to establish an Application Context with the server
00514      */
00515     scEstablishStruct.dwScope = dwScope;
00516     scEstablishStruct.hContext = 0;
00517     scEstablishStruct.rv = SCARD_S_SUCCESS;
00518 
00519     rv = WrapSHMWrite(SCARD_ESTABLISH_CONTEXT, dwClientID,
00520         sizeof(scEstablishStruct), PCSCLITE_MCLIENT_ATTEMPTS,
00521         (void *) &scEstablishStruct);
00522 
00523     if (rv == -1)
00524         return SCARD_E_NO_SERVICE;
00525 
00526     /*
00527      * Read the response from the server
00528      */
00529     rv = SHMClientRead(&msgStruct, dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
00530 
00531     if (rv == -1)
00532         return SCARD_F_COMM_ERROR;
00533 
00534     memcpy(&scEstablishStruct, &msgStruct.data, sizeof(scEstablishStruct));
00535 
00536     if (scEstablishStruct.rv != SCARD_S_SUCCESS)
00537         return scEstablishStruct.rv;
00538 
00539     /* check we do not reuse an existing phContext */
00540     if (-1 != SCardGetContextIndiceTH(scEstablishStruct.hContext))
00541         /* we do not need to release the allocated context since
00542          * SCardReleaseContext() does nothing on the server side */
00543         goto again;
00544 
00545     *phContext = scEstablishStruct.hContext;
00546 
00547     /*
00548      * Allocate the new hContext - if allocator full return an error
00549      */
00550     rv = SCardAddContext(*phContext, dwClientID);
00551 
00552     return rv;
00553 }
00554 
00576 LONG SCardReleaseContext(SCARDCONTEXT hContext)
00577 {
00578     LONG rv;
00579     release_struct scReleaseStruct;
00580     sharedSegmentMsg msgStruct;
00581     LONG dwContextIndex;
00582 
00583     PROFILE_START
00584 
00585     /*
00586      * Make sure this context has been opened
00587      * and get dwContextIndex
00588      */
00589     dwContextIndex = SCardGetContextIndice(hContext);
00590     if (dwContextIndex == -1)
00591         return SCARD_E_INVALID_HANDLE;
00592 
00593     rv = SCardCheckDaemonAvailability();
00594     if (rv != SCARD_S_SUCCESS)
00595     {
00596         /*
00597          * Remove the local context from the stack
00598          */
00599         (void)SCardLockThread();
00600         (void)SCardRemoveContext(hContext);
00601         (void)SCardUnlockThread();
00602 
00603         return rv;
00604     }
00605 
00606     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
00607 
00608     /* check the context is still opened */
00609     dwContextIndex = SCardGetContextIndice(hContext);
00610     if (dwContextIndex == -1)
00611         /* the context is now invalid
00612          * -> another thread may have called SCardReleaseContext
00613          * -> so the mMutex has been unlocked */
00614         return SCARD_E_INVALID_HANDLE;
00615 
00616     scReleaseStruct.hContext = hContext;
00617     scReleaseStruct.rv = SCARD_S_SUCCESS;
00618 
00619     rv = WrapSHMWrite(SCARD_RELEASE_CONTEXT,
00620         psContextMap[dwContextIndex].dwClientID,
00621         sizeof(scReleaseStruct),
00622         PCSCLITE_MCLIENT_ATTEMPTS, (void *) &scReleaseStruct);
00623 
00624     if (rv == -1)
00625     {
00626         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00627         return SCARD_E_NO_SERVICE;
00628     }
00629 
00630     /*
00631      * Read a message from the server
00632      */
00633     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
00634         PCSCLITE_CLIENT_ATTEMPTS);
00635     memcpy(&scReleaseStruct, &msgStruct.data, sizeof(scReleaseStruct));
00636 
00637     if (rv == -1)
00638     {
00639         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00640         return SCARD_F_COMM_ERROR;
00641     }
00642 
00643     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00644 
00645     /*
00646      * Remove the local context from the stack
00647      */
00648     (void)SCardLockThread();
00649     (void)SCardRemoveContext(hContext);
00650     (void)SCardUnlockThread();
00651 
00652     PROFILE_END(scReleaseStruct.rv)
00653 
00654     return scReleaseStruct.rv;
00655 }
00656 
00672 LONG SCardSetTimeout(/*@unused@*/ SCARDCONTEXT hContext,
00673     /*@unused@*/ DWORD dwTimeout)
00674 {
00675     /*
00676      * Deprecated
00677      */
00678     (void)hContext;
00679     (void)dwTimeout;
00680     return SCARD_S_SUCCESS;
00681 }
00682 
00734 LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader,
00735     DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
00736     LPDWORD pdwActiveProtocol)
00737 {
00738     LONG rv;
00739     connect_struct scConnectStruct;
00740     sharedSegmentMsg msgStruct;
00741     LONG dwContextIndex;
00742 
00743     PROFILE_START
00744 
00745     /*
00746      * Check for NULL parameters
00747      */
00748     if (phCard == NULL || pdwActiveProtocol == NULL)
00749         return SCARD_E_INVALID_PARAMETER;
00750     else
00751         *phCard = 0;
00752 
00753     if (szReader == NULL)
00754         return SCARD_E_UNKNOWN_READER;
00755 
00756     /*
00757      * Check for uninitialized strings
00758      */
00759     if (strlen(szReader) > MAX_READERNAME)
00760         return SCARD_E_INVALID_VALUE;
00761 
00762     rv = SCardCheckDaemonAvailability();
00763     if (rv != SCARD_S_SUCCESS)
00764         return rv;
00765 
00766     /*
00767      * Make sure this context has been opened
00768      */
00769     dwContextIndex = SCardGetContextIndice(hContext);
00770     if (dwContextIndex == -1)
00771         return SCARD_E_INVALID_HANDLE;
00772 
00773     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
00774 
00775     /* check the context is still opened */
00776     dwContextIndex = SCardGetContextIndice(hContext);
00777     if (dwContextIndex == -1)
00778         /* the context is now invalid
00779          * -> another thread may have called SCardReleaseContext
00780          * -> so the mMutex has been unlocked */
00781         return SCARD_E_INVALID_HANDLE;
00782 
00783     strncpy(scConnectStruct.szReader, szReader, MAX_READERNAME);
00784 
00785     scConnectStruct.hContext = hContext;
00786     scConnectStruct.dwShareMode = dwShareMode;
00787     scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
00788     scConnectStruct.hCard = 0;
00789     scConnectStruct.dwActiveProtocol = 0;
00790     scConnectStruct.rv = SCARD_S_SUCCESS;
00791 
00792     rv = WrapSHMWrite(SCARD_CONNECT, psContextMap[dwContextIndex].dwClientID,
00793         sizeof(scConnectStruct),
00794         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scConnectStruct);
00795 
00796     if (rv == -1)
00797     {
00798         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00799         return SCARD_E_NO_SERVICE;
00800     }
00801 
00802     /*
00803      * Read a message from the server
00804      */
00805     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
00806         PCSCLITE_CLIENT_ATTEMPTS);
00807 
00808     memcpy(&scConnectStruct, &msgStruct.data, sizeof(scConnectStruct));
00809 
00810     if (rv == -1)
00811     {
00812         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00813         return SCARD_F_COMM_ERROR;
00814     }
00815 
00816     *phCard = scConnectStruct.hCard;
00817     *pdwActiveProtocol = scConnectStruct.dwActiveProtocol;
00818 
00819     if (scConnectStruct.rv == SCARD_S_SUCCESS)
00820     {
00821         /*
00822          * Keep track of the handle locally
00823          */
00824         rv = SCardAddHandle(*phCard, dwContextIndex, szReader);
00825         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00826 
00827         PROFILE_END(rv)
00828 
00829         return rv;
00830     }
00831 
00832     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00833 
00834     PROFILE_END(scConnectStruct.rv)
00835 
00836     return scConnectStruct.rv;
00837 }
00838 
00906 LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
00907     DWORD dwPreferredProtocols, DWORD dwInitialization,
00908     LPDWORD pdwActiveProtocol)
00909 {
00910     LONG rv;
00911     reconnect_struct scReconnectStruct;
00912     sharedSegmentMsg msgStruct;
00913     int i;
00914     DWORD dwContextIndex, dwChannelIndex;
00915 
00916     PROFILE_START
00917 
00918     if (pdwActiveProtocol == NULL)
00919         return SCARD_E_INVALID_PARAMETER;
00920 
00921     rv = SCardCheckDaemonAvailability();
00922     if (rv != SCARD_S_SUCCESS)
00923         return rv;
00924 
00925     /*
00926      * Make sure this handle has been opened
00927      */
00928     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
00929     if (rv == -1)
00930         return SCARD_E_INVALID_HANDLE;
00931 
00932     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
00933 
00934     /* check the handle is still valid */
00935     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
00936     if (rv == -1)
00937         /* the handle is now invalid
00938          * -> another thread may have called SCardReleaseContext
00939          * -> so the mMutex has been unlocked */
00940         return SCARD_E_INVALID_HANDLE;
00941 
00942     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00943     {
00944         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
00945 
00946         /* by default r == NULL */
00947         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
00948             break;
00949     }
00950 
00951     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
00952     {
00953         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00954         return SCARD_E_READER_UNAVAILABLE;
00955     }
00956 
00957     do
00958     {
00959         scReconnectStruct.hCard = hCard;
00960         scReconnectStruct.dwShareMode = dwShareMode;
00961         scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
00962         scReconnectStruct.dwInitialization = dwInitialization;
00963         scReconnectStruct.dwActiveProtocol = *pdwActiveProtocol;
00964         scReconnectStruct.rv = SCARD_S_SUCCESS;
00965 
00966         rv = WrapSHMWrite(SCARD_RECONNECT, psContextMap[dwContextIndex].dwClientID,
00967             sizeof(scReconnectStruct),
00968             PCSCLITE_CLIENT_ATTEMPTS, (void *) &scReconnectStruct);
00969 
00970         if (rv == -1)
00971         {
00972             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00973             return SCARD_E_NO_SERVICE;
00974         }
00975 
00976         /*
00977          * Read a message from the server
00978          */
00979         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
00980             PCSCLITE_CLIENT_ATTEMPTS);
00981 
00982         memcpy(&scReconnectStruct, &msgStruct.data, sizeof(scReconnectStruct));
00983 
00984         if (rv == -1)
00985         {
00986             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00987             return SCARD_F_COMM_ERROR;
00988         }
00989     } while (SCARD_E_SHARING_VIOLATION == scReconnectStruct.rv);
00990 
00991     *pdwActiveProtocol = scReconnectStruct.dwActiveProtocol;
00992 
00993     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00994 
00995     PROFILE_END(scReconnectStruct.rv)
00996 
00997     return scReconnectStruct.rv;
00998 }
00999 
01030 LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
01031 {
01032     LONG rv;
01033     disconnect_struct scDisconnectStruct;
01034     sharedSegmentMsg msgStruct;
01035     DWORD dwContextIndex, dwChannelIndex;
01036 
01037     PROFILE_START
01038 
01039     rv = SCardCheckDaemonAvailability();
01040     if (rv != SCARD_S_SUCCESS)
01041         return rv;
01042 
01043     /*
01044      * Make sure this handle has been opened
01045      */
01046     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01047     if (rv == -1)
01048         return SCARD_E_INVALID_HANDLE;
01049 
01050     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01051 
01052     /* check the handle is still valid */
01053     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01054     if (rv == -1)
01055         /* the handle is now invalid
01056          * -> another thread may have called SCardReleaseContext
01057          * -> so the mMutex has been unlocked */
01058         return SCARD_E_INVALID_HANDLE;
01059 
01060     scDisconnectStruct.hCard = hCard;
01061     scDisconnectStruct.dwDisposition = dwDisposition;
01062     scDisconnectStruct.rv = SCARD_S_SUCCESS;
01063 
01064     rv = WrapSHMWrite(SCARD_DISCONNECT, psContextMap[dwContextIndex].dwClientID,
01065         sizeof(scDisconnectStruct),
01066         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scDisconnectStruct);
01067 
01068     if (rv == -1)
01069     {
01070         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01071         return SCARD_E_NO_SERVICE;
01072     }
01073 
01074     /*
01075      * Read a message from the server
01076      */
01077     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01078         PCSCLITE_CLIENT_ATTEMPTS);
01079 
01080     memcpy(&scDisconnectStruct, &msgStruct.data,
01081         sizeof(scDisconnectStruct));
01082 
01083     if (rv == -1)
01084     {
01085         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01086         return SCARD_F_COMM_ERROR;
01087     }
01088 
01089     (void)SCardRemoveHandle(hCard);
01090 
01091     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01092 
01093     PROFILE_END(scDisconnectStruct.rv)
01094 
01095     return scDisconnectStruct.rv;
01096 }
01097 
01133 LONG SCardBeginTransaction(SCARDHANDLE hCard)
01134 {
01135 
01136     LONG rv;
01137     begin_struct scBeginStruct;
01138     int i;
01139     sharedSegmentMsg msgStruct;
01140     DWORD dwContextIndex, dwChannelIndex;
01141 
01142     PROFILE_START
01143 
01144     rv = SCardCheckDaemonAvailability();
01145     if (rv != SCARD_S_SUCCESS)
01146         return rv;
01147 
01148     /*
01149      * Make sure this handle has been opened
01150      */
01151     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01152     if (rv == -1)
01153         return SCARD_E_INVALID_HANDLE;
01154 
01155     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01156 
01157     /* check the handle is still valid */
01158     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01159     if (rv == -1)
01160         /* the handle is now invalid
01161          * -> another thread may have called SCardReleaseContext
01162          * -> so the mMutex has been unlocked */
01163         return SCARD_E_INVALID_HANDLE;
01164 
01165     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01166     {
01167         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01168 
01169         /* by default r == NULL */
01170         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01171             break;
01172     }
01173 
01174     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01175     {
01176         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01177         return SCARD_E_READER_UNAVAILABLE;
01178     }
01179 
01180     scBeginStruct.hCard = hCard;
01181     scBeginStruct.rv = SCARD_S_SUCCESS;
01182 
01183     /*
01184      * Query the server every so often until the sharing violation ends
01185      * and then hold the lock for yourself.
01186      */
01187 
01188     do
01189     {
01190         rv = WrapSHMWrite(SCARD_BEGIN_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
01191             sizeof(scBeginStruct),
01192             PCSCLITE_CLIENT_ATTEMPTS, (void *) &scBeginStruct);
01193 
01194         if (rv == -1)
01195         {
01196 
01197             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01198             return SCARD_E_NO_SERVICE;
01199         }
01200 
01201         /*
01202          * Read a message from the server
01203          */
01204         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01205             PCSCLITE_CLIENT_ATTEMPTS);
01206 
01207         memcpy(&scBeginStruct, &msgStruct.data, sizeof(scBeginStruct));
01208 
01209         if (rv == -1)
01210         {
01211 
01212             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01213             return SCARD_F_COMM_ERROR;
01214         }
01215 
01216     }
01217     while (scBeginStruct.rv == SCARD_E_SHARING_VIOLATION);
01218 
01219     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01220 
01221     PROFILE_END(scBeginStruct.rv);
01222 
01223     return scBeginStruct.rv;
01224 }
01225 
01266 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
01267 {
01268     LONG rv;
01269     end_struct scEndStruct;
01270     sharedSegmentMsg msgStruct;
01271     int randnum, i;
01272     DWORD dwContextIndex, dwChannelIndex;
01273 
01274     PROFILE_START
01275 
01276     /*
01277      * Zero out everything
01278      */
01279     randnum = 0;
01280 
01281     rv = SCardCheckDaemonAvailability();
01282     if (rv != SCARD_S_SUCCESS)
01283         return rv;
01284 
01285     /*
01286      * Make sure this handle has been opened
01287      */
01288     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01289     if (rv == -1)
01290         return SCARD_E_INVALID_HANDLE;
01291 
01292     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01293 
01294     /* check the handle is still valid */
01295     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01296     if (rv == -1)
01297         /* the handle is now invalid
01298          * -> another thread may have called SCardReleaseContext
01299          * -> so the mMutex has been unlocked */
01300         return SCARD_E_INVALID_HANDLE;
01301 
01302     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01303     {
01304         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01305 
01306         /* by default r == NULL */
01307         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01308             break;
01309     }
01310 
01311     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01312     {
01313         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01314         return SCARD_E_READER_UNAVAILABLE;
01315     }
01316 
01317     scEndStruct.hCard = hCard;
01318     scEndStruct.dwDisposition = dwDisposition;
01319     scEndStruct.rv = SCARD_S_SUCCESS;
01320 
01321     rv = WrapSHMWrite(SCARD_END_TRANSACTION,
01322         psContextMap[dwContextIndex].dwClientID,
01323         sizeof(scEndStruct),
01324         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scEndStruct);
01325 
01326     if (rv == -1)
01327     {
01328         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01329         return SCARD_E_NO_SERVICE;
01330     }
01331 
01332     /*
01333      * Read a message from the server
01334      */
01335     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01336         PCSCLITE_CLIENT_ATTEMPTS);
01337 
01338     memcpy(&scEndStruct, &msgStruct.data, sizeof(scEndStruct));
01339 
01340     if (rv == -1)
01341     {
01342         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01343         return SCARD_F_COMM_ERROR;
01344     }
01345 
01346     /*
01347      * This helps prevent starvation
01348      */
01349     randnum = SYS_RandomInt(1000, 10000);
01350     (void)SYS_USleep(randnum);
01351 
01352     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01353 
01354     PROFILE_END(scEndStruct.rv)
01355 
01356     return scEndStruct.rv;
01357 }
01358 
01365 LONG SCardCancelTransaction(SCARDHANDLE hCard)
01366 {
01367     LONG rv;
01368     cancel_struct scCancelStruct;
01369     sharedSegmentMsg msgStruct;
01370     int i;
01371     DWORD dwContextIndex, dwChannelIndex;
01372 
01373     PROFILE_START
01374 
01375     rv = SCardCheckDaemonAvailability();
01376     if (rv != SCARD_S_SUCCESS)
01377         return rv;
01378 
01379     /*
01380      * Make sure this handle has been opened
01381      */
01382     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01383     if (rv == -1)
01384         return SCARD_E_INVALID_HANDLE;
01385 
01386     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01387 
01388     /* check the handle is still valid */
01389     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01390     if (rv == -1)
01391         /* the handle is now invalid
01392          * -> another thread may have called SCardReleaseContext
01393          * -> so the mMutex has been unlocked */
01394         return SCARD_E_INVALID_HANDLE;
01395 
01396     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01397     {
01398         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01399 
01400         /* by default r == NULL */
01401         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01402             break;
01403     }
01404 
01405     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01406     {
01407         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01408         return SCARD_E_READER_UNAVAILABLE;
01409     }
01410 
01411     scCancelStruct.hCard = hCard;
01412 
01413     rv = WrapSHMWrite(SCARD_CANCEL_TRANSACTION,
01414         psContextMap[dwContextIndex].dwClientID,
01415         sizeof(scCancelStruct),
01416         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scCancelStruct);
01417 
01418     if (rv == -1)
01419     {
01420         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01421         return SCARD_E_NO_SERVICE;
01422     }
01423 
01424     /*
01425      * Read a message from the server
01426      */
01427     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01428         PCSCLITE_CLIENT_ATTEMPTS);
01429 
01430     memcpy(&scCancelStruct, &msgStruct.data, sizeof(scCancelStruct));
01431 
01432     if (rv == -1)
01433     {
01434         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01435         return SCARD_F_COMM_ERROR;
01436     }
01437 
01438     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01439 
01440     PROFILE_END(scCancelStruct.rv)
01441 
01442     return scCancelStruct.rv;
01443 }
01444 
01532 LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName,
01533     LPDWORD pcchReaderLen, LPDWORD pdwState,
01534     LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
01535 {
01536     DWORD dwReaderLen, dwAtrLen;
01537     LONG rv;
01538     int i;
01539     status_struct scStatusStruct;
01540     sharedSegmentMsg msgStruct;
01541     DWORD dwContextIndex, dwChannelIndex;
01542     char *r;
01543     char *bufReader = NULL;
01544     LPBYTE bufAtr = NULL;
01545     DWORD dummy;
01546 
01547     PROFILE_START
01548 
01549     /* default output values */
01550     if (pdwState)
01551         *pdwState = 0;
01552 
01553     if (pdwProtocol)
01554         *pdwProtocol = 0;
01555 
01556     /* Check for NULL parameters */ 
01557     if (pcchReaderLen == NULL)
01558         pcchReaderLen = &dummy;
01559     
01560     if (pcbAtrLen == NULL)
01561         pcbAtrLen = &dummy;
01562 
01563     /* length passed from caller */
01564     dwReaderLen = *pcchReaderLen;
01565     dwAtrLen = *pcbAtrLen;
01566 
01567     *pcchReaderLen = 0;
01568     *pcbAtrLen = 0;
01569 
01570     rv = SCardCheckDaemonAvailability();
01571     if (rv != SCARD_S_SUCCESS)
01572         return rv;
01573 
01574     /*
01575      * Make sure this handle has been opened
01576      */
01577     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01578     if (rv == -1)
01579         return SCARD_E_INVALID_HANDLE;
01580 
01581     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01582 
01583     /* check the handle is still valid */
01584     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01585     if (rv == -1)
01586         /* the handle is now invalid
01587          * -> another thread may have called SCardReleaseContext
01588          * -> so the mMutex has been unlocked */
01589         return SCARD_E_INVALID_HANDLE;
01590 
01591     r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01592     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01593     {
01594         /* by default r == NULL */
01595         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01596             break;
01597     }
01598 
01599     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01600     {
01601         rv = SCARD_E_READER_UNAVAILABLE;
01602         goto end;
01603     }
01604 
01605     /* initialise the structure */
01606     memset(&scStatusStruct, 0, sizeof(scStatusStruct));
01607     scStatusStruct.hCard = hCard;
01608 
01609     /* those sizes need to be initialised */
01610     scStatusStruct.pcchReaderLen = sizeof(scStatusStruct.mszReaderNames);
01611     scStatusStruct.pcbAtrLen = sizeof(scStatusStruct.pbAtr);
01612 
01613     rv = WrapSHMWrite(SCARD_STATUS, psContextMap[dwContextIndex].dwClientID,
01614         sizeof(scStatusStruct),
01615         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scStatusStruct);
01616 
01617     if (rv == -1)
01618     {
01619         rv = SCARD_E_NO_SERVICE;
01620         goto end;
01621     }
01622 
01623     /*
01624      * Read a message from the server
01625      */
01626     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01627         PCSCLITE_CLIENT_ATTEMPTS);
01628 
01629     memcpy(&scStatusStruct, &msgStruct.data, sizeof(scStatusStruct));
01630 
01631     if (rv == -1)
01632     {
01633         rv = SCARD_F_COMM_ERROR;
01634         goto end;
01635     }
01636 
01637     rv = scStatusStruct.rv;
01638     if (rv != SCARD_S_SUCCESS && rv != SCARD_E_INSUFFICIENT_BUFFER)
01639     {
01640         /*
01641          * An event must have occurred
01642          */
01643         goto end;
01644     }
01645 
01646     /*
01647      * Now continue with the client side SCardStatus
01648      */
01649 
01650     *pcchReaderLen = strlen(psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName) + 1;
01651     *pcbAtrLen = (readerStates[i])->cardAtrLength;
01652 
01653     if (pdwState)
01654         *pdwState = (readerStates[i])->readerState;
01655 
01656     if (pdwProtocol)
01657         *pdwProtocol = (readerStates[i])->cardProtocol;
01658 
01659     if (SCARD_AUTOALLOCATE == dwReaderLen)
01660     {
01661         dwReaderLen = *pcchReaderLen;
01662         bufReader = malloc(dwReaderLen);
01663         if (NULL == bufReader)
01664         {
01665             rv = SCARD_E_NO_MEMORY;
01666             goto end;
01667         }
01668         if (NULL == mszReaderName)
01669         {
01670             rv = SCARD_E_INVALID_PARAMETER;
01671             goto end;
01672         }
01673         *(char **)mszReaderName = bufReader;
01674     }
01675     else
01676         bufReader = mszReaderName;
01677 
01678     /* return SCARD_E_INSUFFICIENT_BUFFER only if buffer pointer is non NULL */
01679     if (bufReader)
01680     {
01681         if (*pcchReaderLen > dwReaderLen)
01682             rv = SCARD_E_INSUFFICIENT_BUFFER;
01683 
01684         strncpy(bufReader,
01685             psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName,
01686             dwReaderLen);
01687     }
01688 
01689     if (SCARD_AUTOALLOCATE == dwAtrLen)
01690     {
01691         dwAtrLen = *pcbAtrLen;
01692         bufAtr = malloc(dwAtrLen);
01693         if (NULL == bufAtr)
01694         {
01695             rv = SCARD_E_NO_MEMORY;
01696             goto end;
01697         }
01698         if (NULL == pbAtr)
01699         {
01700             rv = SCARD_E_INVALID_PARAMETER;
01701             goto end;
01702         }
01703         *(LPBYTE *)pbAtr = bufAtr;
01704     }
01705     else
01706         bufAtr = pbAtr;
01707 
01708     if (bufAtr)
01709     {
01710         if (*pcbAtrLen > dwAtrLen)
01711             rv = SCARD_E_INSUFFICIENT_BUFFER;
01712 
01713         memcpy(bufAtr, (readerStates[i])->cardAtr, min(*pcbAtrLen, dwAtrLen));
01714     }
01715 
01716 end:
01717     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01718 
01719     PROFILE_END(rv)
01720 
01721     return rv;
01722 }
01723 
01724 static long WaitForPcscdEvent(SCARDCONTEXT hContext, long dwTime)
01725 {
01726     char filename[FILENAME_MAX];
01727     char buf[1];
01728     int fd, r;
01729     struct timeval tv, *ptv = NULL;
01730     struct timeval before, after;
01731     fd_set read_fd;
01732 
01733     if (INFINITE != dwTime)
01734     {
01735         if (dwTime < 0)
01736             return 0;
01737         gettimeofday(&before, NULL);
01738         tv.tv_sec = dwTime/1000;
01739         tv.tv_usec = dwTime*1000 - tv.tv_sec*1000000;
01740         ptv = &tv;
01741     }
01742 
01743     (void)snprintf(filename, sizeof(filename), "%s/event.%d.%ld",
01744         PCSCLITE_EVENTS_DIR, SYS_GetPID(), hContext);
01745     r = mkfifo(filename, 0644);
01746     if (-1 == r)
01747     {
01748         Log2(PCSC_LOG_CRITICAL, "Can't create event fifo: %s", strerror(errno));
01749         goto exit;
01750     }
01751 
01752     fd = SYS_OpenFile(filename, O_RDONLY | O_NONBLOCK, 0);
01753 
01754     /* the file may have been removed between the mkfifo() and open() */
01755     if (-1 != fd)
01756     {
01757         FD_ZERO(&read_fd);
01758         FD_SET(fd, &read_fd);
01759         
01760         (void)select(fd+1, &read_fd, NULL, NULL, ptv);
01761 
01762         (void)SYS_ReadFile(fd, buf, 1);
01763         (void)SYS_CloseFile(fd);
01764     }
01765 
01766     (void)SYS_RemoveFile(filename);
01767 
01768     if (INFINITE != dwTime)
01769     {
01770         long int diff;
01771 
01772         gettimeofday(&after, NULL);
01773         diff = time_sub(&after, &before);
01774         dwTime -= diff/1000;
01775     }
01776 
01777 exit:
01778     return dwTime;
01779 }
01780 
01872 LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout,
01873     LPSCARD_READERSTATE_A rgReaderStates, DWORD cReaders)
01874 {
01875     PSCARD_READERSTATE_A currReader;
01876     PREADER_STATE rContext;
01877     long dwTime = dwTimeout;
01878     DWORD dwState;
01879     DWORD dwBreakFlag = 0;
01880     int j;
01881     LONG dwContextIndex;
01882     int currentReaderCount = 0;
01883     LONG rv = SCARD_S_SUCCESS;
01884 
01885     PROFILE_START
01886 
01887     if ((rgReaderStates == NULL && cReaders > 0)
01888         || (cReaders > PCSCLITE_MAX_READERS_CONTEXTS))
01889         return SCARD_E_INVALID_PARAMETER;
01890 
01891     /* Check the integrity of the reader states structures */
01892     for (j = 0; j < cReaders; j++)
01893     {
01894         if (rgReaderStates[j].szReader == NULL)
01895             return SCARD_E_INVALID_VALUE;
01896     }
01897 
01898     /* return if all readers are SCARD_STATE_IGNORE */
01899     if (cReaders > 0)
01900     {
01901         int nbNonIgnoredReaders = cReaders;
01902 
01903         for (j=0; j<cReaders; j++)
01904             if (rgReaderStates[j].dwCurrentState & SCARD_STATE_IGNORE)
01905                 nbNonIgnoredReaders--;
01906 
01907         if (0 == nbNonIgnoredReaders)
01908             return SCARD_S_SUCCESS;
01909     }
01910 
01911     rv = SCardCheckDaemonAvailability();
01912     if (rv != SCARD_S_SUCCESS)
01913         return rv;
01914 
01915     /*
01916      * Make sure this context has been opened
01917      */
01918     dwContextIndex = SCardGetContextIndice(hContext);
01919     if (dwContextIndex == -1)
01920         return SCARD_E_INVALID_HANDLE;
01921 
01922     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01923 
01924     /* check the context is still opened */
01925     dwContextIndex = SCardGetContextIndice(hContext);
01926     if (dwContextIndex == -1)
01927         /* the context is now invalid
01928          * -> another thread may have called SCardReleaseContext
01929          * -> so the mMutex has been unlocked */
01930         return SCARD_E_INVALID_HANDLE;
01931 
01932     /*
01933      * Application is waiting for a reader - return the first available
01934      * reader
01935      * This is DEPRECATED. Use the special reader name \\?PnP?\Notification
01936      * instead
01937      */
01938     if (cReaders == 0)
01939     {
01940         while (1)
01941         {
01942             int i;
01943 
01944             rv = SCardCheckDaemonAvailability();
01945             if (rv != SCARD_S_SUCCESS)
01946                 goto end;
01947 
01948             for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01949             {
01950                 if ((readerStates[i])->readerID != 0)
01951                 {
01952                     /* Reader was found */
01953                     rv = SCARD_S_SUCCESS;
01954                     goto end;
01955                 }
01956             }
01957 
01958             if (dwTimeout == 0)
01959             {
01960                 /* return immediately - no reader available */
01961                 rv = SCARD_E_READER_UNAVAILABLE;
01962                 goto end;
01963             }
01964 
01965             dwTime = WaitForPcscdEvent(hContext, dwTime);
01966             if (dwTimeout != INFINITE)
01967             {
01968                 if (dwTime <= 0)
01969                 {
01970                     rv = SCARD_E_TIMEOUT;
01971                     goto end;
01972                 }
01973             }
01974         }
01975     }
01976 
01977     /*
01978      * End of search for readers
01979      */
01980 
01981     /* Clear the event state for all readers */
01982     for (j = 0; j < cReaders; j++)
01983         rgReaderStates[j].dwEventState = 0;
01984 
01985     /* Now is where we start our event checking loop */
01986     Log1(PCSC_LOG_DEBUG, "Event Loop Start");
01987 
01988     psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_BLOCKING;
01989 
01990     /* Get the initial reader count on the system */
01991     for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
01992         if ((readerStates[j])->readerID != 0)
01993             currentReaderCount++;
01994 
01995     j = 0;
01996     do
01997     {
01998         rv = SCardCheckDaemonAvailability();
01999         if (rv != SCARD_S_SUCCESS)
02000         {
02001             if (psContextMap[dwContextIndex].mMutex)
02002                 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02003 
02004             PROFILE_END(rv)
02005 
02006             return rv;
02007         }
02008 
02009         currReader = &rgReaderStates[j];
02010 
02011         /* Ignore for IGNORED readers */
02012         if (!(currReader->dwCurrentState & SCARD_STATE_IGNORE))
02013         {
02014             LPSTR lpcReaderName;
02015             int i;
02016 
02017       /************ Looks for correct readernames *********************/
02018 
02019             lpcReaderName = (char *) currReader->szReader;
02020 
02021             for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02022             {
02023                 if (strcmp(lpcReaderName, (readerStates[i])->readerName) == 0)
02024                     break;
02025             }
02026 
02027             /* The requested reader name is not recognized */
02028             if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02029             {
02030                 /* PnP special reader? */
02031                 if (strcasecmp(lpcReaderName, "\\\\?PnP?\\Notification") == 0)
02032                 {
02033                     int k, newReaderCount = 0;
02034 
02035                     for (k=0; k < PCSCLITE_MAX_READERS_CONTEXTS; k++)
02036                         if ((readerStates[k])->readerID != 0)
02037                             newReaderCount++;
02038 
02039                     if (newReaderCount != currentReaderCount)
02040                     {
02041                         Log1(PCSC_LOG_INFO, "Reader list changed");
02042                         currentReaderCount = newReaderCount;
02043 
02044                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02045                         dwBreakFlag = 1;
02046                     }
02047                 }
02048                 else
02049                 {
02050                     currReader->dwEventState = SCARD_STATE_UNKNOWN | SCARD_STATE_UNAVAILABLE;
02051                     if (!(currReader->dwCurrentState & SCARD_STATE_UNKNOWN))
02052                     {
02053                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02054                         /*
02055                          * Spec says use SCARD_STATE_IGNORE but a removed USB
02056                          * reader with eventState fed into currentState will
02057                          * be ignored forever
02058                          */
02059                         dwBreakFlag = 1;
02060                     }
02061                 }
02062             }
02063             else
02064             {
02065                 /* The reader has come back after being away */
02066                 if (currReader->dwCurrentState & SCARD_STATE_UNKNOWN)
02067                 {
02068                     currReader->dwEventState |= SCARD_STATE_CHANGED;
02069                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
02070                     Log0(PCSC_LOG_DEBUG);
02071                     dwBreakFlag = 1;
02072                 }
02073 
02074     /*****************************************************************/
02075 
02076                 /* Set the reader status structure */
02077                 rContext = readerStates[i];
02078 
02079                 /* Now we check all the Reader States */
02080                 dwState = rContext->readerState;
02081 
02082                 /* only if current state has an non null event counter */
02083                 if (currReader->dwCurrentState & 0xFFFF0000)
02084                 {
02085                     int currentCounter, stateCounter;
02086 
02087                     stateCounter = (dwState >> 16) & 0xFFFF;
02088                     currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF;
02089 
02090                     /* has the event counter changed since the last call? */
02091                     if (stateCounter != currentCounter)
02092                     {
02093                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02094                         Log0(PCSC_LOG_DEBUG);
02095                         dwBreakFlag = 1;
02096                     }
02097 
02098                     /* add an event counter in the upper word of dwEventState */
02099                     currReader->dwEventState =
02100                         ((currReader->dwEventState & 0xffff )
02101                         | (stateCounter << 16));
02102                 }
02103 
02104     /*********** Check if the reader is in the correct state ********/
02105                 if (dwState & SCARD_UNKNOWN)
02106                 {
02107                     /* reader is in bad state */
02108                     currReader->dwEventState = SCARD_STATE_UNAVAILABLE;
02109                     if (!(currReader->dwCurrentState & SCARD_STATE_UNAVAILABLE))
02110                     {
02111                         /* App thinks reader is in good state and it is not */
02112                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02113                         Log0(PCSC_LOG_DEBUG);
02114                         dwBreakFlag = 1;
02115                     }
02116                 }
02117                 else
02118                 {
02119                     /* App thinks reader in bad state but it is not */
02120                     if (currReader-> dwCurrentState & SCARD_STATE_UNAVAILABLE)
02121                     {
02122                         currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
02123                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02124                         Log0(PCSC_LOG_DEBUG);
02125                         dwBreakFlag = 1;
02126                     }
02127                 }
02128 
02129     /********** Check for card presence in the reader **************/
02130 
02131                 if (dwState & SCARD_PRESENT)
02132                 {
02133                     /* card present but not yet powered up */
02134                     if (0 == rContext->cardAtrLength)
02135                         /* Allow the status thread to convey information */
02136                         (void)SYS_USleep(PCSCLITE_STATUS_POLL_RATE + 10);
02137 
02138                     currReader->cbAtr = rContext->cardAtrLength;
02139                     memcpy(currReader->rgbAtr, rContext->cardAtr,
02140                         currReader->cbAtr);
02141                 }
02142                 else
02143                     currReader->cbAtr = 0;
02144 
02145                 /* Card is now absent */
02146                 if (dwState & SCARD_ABSENT)
02147                 {
02148                     currReader->dwEventState |= SCARD_STATE_EMPTY;
02149                     currReader->dwEventState &= ~SCARD_STATE_PRESENT;
02150                     currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
02151                     currReader->dwEventState &= ~SCARD_STATE_IGNORE;
02152                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
02153                     currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
02154                     currReader->dwEventState &= ~SCARD_STATE_ATRMATCH;
02155                     currReader->dwEventState &= ~SCARD_STATE_MUTE;
02156                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
02157 
02158                     /* After present the rest are assumed */
02159                     if (currReader->dwCurrentState & SCARD_STATE_PRESENT)
02160                     {
02161                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02162                         Log0(PCSC_LOG_DEBUG);
02163                         dwBreakFlag = 1;
02164                     }
02165                 }
02166                 /* Card is now present */
02167                 else if (dwState & SCARD_PRESENT)
02168                 {
02169                     currReader->dwEventState |= SCARD_STATE_PRESENT;
02170                     currReader->dwEventState &= ~SCARD_STATE_EMPTY;
02171                     currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
02172                     currReader->dwEventState &= ~SCARD_STATE_IGNORE;
02173                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
02174                     currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
02175                     currReader->dwEventState &= ~SCARD_STATE_MUTE;
02176 
02177                     if (currReader->dwCurrentState & SCARD_STATE_EMPTY)
02178                     {
02179                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02180                         Log0(PCSC_LOG_DEBUG);
02181                         dwBreakFlag = 1;
02182                     }
02183 
02184                     if (dwState & SCARD_SWALLOWED)
02185                     {
02186                         currReader->dwEventState |= SCARD_STATE_MUTE;
02187                         if (!(currReader->dwCurrentState & SCARD_STATE_MUTE))
02188                         {
02189                             currReader->dwEventState |= SCARD_STATE_CHANGED;
02190                             Log0(PCSC_LOG_DEBUG);
02191                             dwBreakFlag = 1;
02192                         }
02193                     }
02194                     else
02195                     {
02196                         /* App thinks card is mute but it is not */
02197                         if (currReader->dwCurrentState & SCARD_STATE_MUTE)
02198                         {
02199                             currReader->dwEventState |= SCARD_STATE_CHANGED;
02200                             Log0(PCSC_LOG_DEBUG);
02201                             dwBreakFlag = 1;
02202                         }
02203                     }
02204                 }
02205 
02206                 /* Now figure out sharing modes */
02207                 if (rContext->readerSharing == -1)
02208                 {
02209                     currReader->dwEventState |= SCARD_STATE_EXCLUSIVE;
02210                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
02211                     if (currReader->dwCurrentState & SCARD_STATE_INUSE)
02212                     {
02213                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02214                         Log0(PCSC_LOG_DEBUG);
02215                         dwBreakFlag = 1;
02216                     }
02217                 }
02218                 else if (rContext->readerSharing >= 1)
02219                 {
02220                     /* A card must be inserted for it to be INUSE */
02221                     if (dwState & SCARD_PRESENT)
02222                     {
02223                         currReader->dwEventState |= SCARD_STATE_INUSE;
02224                         currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
02225                         if (currReader-> dwCurrentState & SCARD_STATE_EXCLUSIVE)
02226                         {
02227                             currReader->dwEventState |= SCARD_STATE_CHANGED;
02228                             Log0(PCSC_LOG_DEBUG);
02229                             dwBreakFlag = 1;
02230                         }
02231                     }
02232                 }
02233                 else if (rContext->readerSharing == 0)
02234                 {
02235                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
02236                     currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
02237 
02238                     if (currReader->dwCurrentState & SCARD_STATE_INUSE)
02239                     {
02240                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02241                         Log0(PCSC_LOG_DEBUG);
02242                         dwBreakFlag = 1;
02243                     }
02244                     else if (currReader-> dwCurrentState
02245                         & SCARD_STATE_EXCLUSIVE)
02246                     {
02247                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02248                         Log0(PCSC_LOG_DEBUG);
02249                         dwBreakFlag = 1;
02250                     }
02251                 }
02252 
02253                 if (currReader->dwCurrentState == SCARD_STATE_UNAWARE)
02254                 {
02255                     /*
02256                      * Break out of the while .. loop and return status
02257                      * once all the status's for all readers is met
02258                      */
02259                     currReader->dwEventState |= SCARD_STATE_CHANGED;
02260                     Log0(PCSC_LOG_DEBUG);
02261                     dwBreakFlag = 1;
02262                 }
02263             }   /* End of SCARD_STATE_UNKNOWN */
02264         }   /* End of SCARD_STATE_IGNORE */
02265 
02266         /* Counter and resetter */
02267         j++;
02268         if (j == cReaders)
02269         {
02270             /* go back to the first reader */
02271             j = 0;
02272 
02273             /* Declare all the break conditions */
02274 
02275             /* Break if UNAWARE is set and all readers have been checked */
02276             if (dwBreakFlag == 1)
02277                 break;
02278 
02279             if (BLOCK_STATUS_RESUME
02280                 == psContextMap[dwContextIndex].contextBlockStatus)
02281                 break;
02282 
02283             /* Only sleep once for each cycle of reader checks. */
02284             dwTime = WaitForPcscdEvent(hContext, dwTime);
02285 
02286             if (dwTimeout != INFINITE)
02287             {
02288                 /* If time is greater than timeout and all readers have been
02289                  * checked
02290                  */
02291                 if (dwTime <= 0)
02292                 {
02293                     rv = SCARD_E_TIMEOUT;
02294                     goto end;
02295                 }
02296             }
02297         }
02298     }
02299     while (1);
02300 
02301     if (psContextMap[dwContextIndex].contextBlockStatus == BLOCK_STATUS_RESUME)
02302         rv = SCARD_E_CANCELLED;
02303 
02304 end:
02305     Log1(PCSC_LOG_DEBUG, "Event Loop End");
02306 
02307     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02308 
02309     PROFILE_END(rv)
02310 
02311     return rv;
02312 }
02313 
02365 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
02366     DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
02367     LPDWORD lpBytesReturned)
02368 {
02369     LONG rv;
02370     control_struct scControlStruct;
02371     sharedSegmentMsg msgStruct;
02372     int i;
02373     DWORD dwContextIndex, dwChannelIndex;
02374 
02375     PROFILE_START
02376 
02377     /* 0 bytes received by default */
02378     if (NULL != lpBytesReturned)
02379         *lpBytesReturned = 0;
02380 
02381     rv = SCardCheckDaemonAvailability();
02382     if (rv != SCARD_S_SUCCESS)
02383         return rv;
02384 
02385     /*
02386      * Make sure this handle has been opened
02387      */
02388     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02389     if (rv == -1)
02390         return SCARD_E_INVALID_HANDLE;
02391 
02392     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02393 
02394     /* check the handle is still valid */
02395     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02396     if (rv == -1)
02397         /* the handle is now invalid
02398          * -> another thread may have called SCardReleaseContext
02399          * -> so the mMutex has been unlocked */
02400         return SCARD_E_INVALID_HANDLE;
02401 
02402     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02403     {
02404         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02405 
02406         /* by default r == NULL */
02407         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02408             break;
02409     }
02410 
02411     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02412     {
02413         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02414         return SCARD_E_READER_UNAVAILABLE;
02415     }
02416 
02417     if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
02418         || (cbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
02419     {
02420         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02421         return SCARD_E_INSUFFICIENT_BUFFER;
02422     }
02423 
02424     if ((cbSendLength > MAX_BUFFER_SIZE) || (cbRecvLength > MAX_BUFFER_SIZE))
02425     {
02426         /* extended control */
02427         unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED];
02428         control_struct_extended *scControlStructExtended = (control_struct_extended *)buffer;
02429         sharedSegmentMsg *pmsgStruct = (psharedSegmentMsg)buffer;
02430 
02431         scControlStructExtended->hCard = hCard;
02432         scControlStructExtended->dwControlCode = dwControlCode;
02433         scControlStructExtended->cbSendLength = cbSendLength;
02434         scControlStructExtended->cbRecvLength = cbRecvLength;
02435         scControlStructExtended->dwBytesReturned = 0;
02436         scControlStructExtended->rv = SCARD_S_SUCCESS;
02437         /* The size of data to send is the size of
02438          * struct control_struct_extended WITHOUT the data[] field
02439          * plus the effective data[] size
02440          */
02441         scControlStructExtended->size = sizeof(*scControlStructExtended)
02442             - (sizeof(control_struct_extended) - offsetof(control_struct_extended, data))
02443             + cbSendLength;
02444         memcpy(scControlStructExtended->data, pbSendBuffer, cbSendLength);
02445 
02446         rv = WrapSHMWrite(SCARD_CONTROL_EXTENDED,
02447             psContextMap[dwContextIndex].dwClientID,
02448             scControlStructExtended->size,
02449             PCSCLITE_CLIENT_ATTEMPTS, buffer);
02450 
02451         if (rv == -1)
02452         {
02453             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02454             return SCARD_E_NO_SERVICE;
02455         }
02456 
02457         /*
02458          * Read a message from the server
02459          */
02460         /* read the first block */
02461         rv = SHMMessageReceive(buffer, sizeof(sharedSegmentMsg),
02462             psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
02463         if (rv == -1)
02464         {
02465             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02466             return SCARD_F_COMM_ERROR;
02467         }
02468 
02469         /* we receive a sharedSegmentMsg and not a control_struct_extended */
02470         scControlStructExtended = (control_struct_extended *)&(pmsgStruct -> data);
02471 
02472         /* a second block is present */
02473         if (scControlStructExtended->size > PCSCLITE_MAX_MESSAGE_SIZE)
02474         {
02475             rv = SHMMessageReceive(buffer + sizeof(sharedSegmentMsg),
02476                 scControlStructExtended->size-PCSCLITE_MAX_MESSAGE_SIZE,
02477                 psContextMap[dwContextIndex].dwClientID,
02478                 PCSCLITE_CLIENT_ATTEMPTS);
02479             if (rv == -1)
02480             {
02481                 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02482                 return SCARD_F_COMM_ERROR;
02483             }
02484         }
02485 
02486         if (scControlStructExtended -> rv == SCARD_S_SUCCESS)
02487         {
02488             /*
02489              * Copy and zero it so any secret information is not leaked
02490              */
02491             memcpy(pbRecvBuffer, scControlStructExtended -> data,
02492                 scControlStructExtended -> dwBytesReturned);
02493             memset(scControlStructExtended -> data, 0x00,
02494                 scControlStructExtended -> dwBytesReturned);
02495         }
02496 
02497         if (NULL != lpBytesReturned)
02498             *lpBytesReturned = scControlStructExtended -> dwBytesReturned;
02499 
02500         rv = scControlStructExtended -> rv;
02501     }
02502     else
02503     {
02504         scControlStruct.hCard = hCard;
02505         scControlStruct.dwControlCode = dwControlCode;
02506         scControlStruct.cbSendLength = cbSendLength;
02507         scControlStruct.cbRecvLength = cbRecvLength;
02508         memcpy(scControlStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
02509 
02510         rv = WrapSHMWrite(SCARD_CONTROL,
02511             psContextMap[dwContextIndex].dwClientID,
02512             sizeof(scControlStruct), PCSCLITE_CLIENT_ATTEMPTS, &scControlStruct);
02513 
02514         if (rv == -1)
02515         {
02516             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02517             return SCARD_E_NO_SERVICE;
02518         }
02519 
02520         /*
02521          * Read a message from the server
02522          */
02523         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
02524             PCSCLITE_CLIENT_ATTEMPTS);
02525 
02526         if (rv == -1)
02527         {
02528             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02529             return SCARD_F_COMM_ERROR;
02530         }
02531 
02532         memcpy(&scControlStruct, &msgStruct.data, sizeof(scControlStruct));
02533 
02534         if (NULL != lpBytesReturned)
02535             *lpBytesReturned = scControlStruct.dwBytesReturned;
02536 
02537         if (scControlStruct.rv == SCARD_S_SUCCESS)
02538         {
02539             /*
02540              * Copy and zero it so any secret information is not leaked
02541              */
02542             memcpy(pbRecvBuffer, scControlStruct.pbRecvBuffer,
02543                 scControlStruct.cbRecvLength);
02544             memset(scControlStruct.pbRecvBuffer, 0x00,
02545                 sizeof(scControlStruct.pbRecvBuffer));
02546         }
02547 
02548         rv = scControlStruct.rv;
02549     }
02550 
02551     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02552 
02553     PROFILE_END(rv)
02554 
02555     return rv;
02556 }
02557 
02658 LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
02659     LPDWORD pcbAttrLen)
02660 {
02661     LONG ret;
02662     unsigned char *buf = NULL;
02663 
02664     PROFILE_START
02665 
02666     if (NULL == pcbAttrLen)
02667         return SCARD_E_INVALID_PARAMETER;
02668 
02669     if (SCARD_AUTOALLOCATE == *pcbAttrLen)
02670     {
02671         if (NULL == pbAttr)
02672             return SCARD_E_INVALID_PARAMETER;
02673 
02674         *pcbAttrLen = MAX_BUFFER_SIZE;
02675         buf = malloc(*pcbAttrLen);
02676         if (NULL == buf)
02677             return SCARD_E_NO_MEMORY;
02678 
02679         *(unsigned char **)pbAttr = buf;
02680     }
02681     else
02682     {
02683         buf = pbAttr;
02684 
02685         /* if only get the length */
02686         if (NULL == pbAttr)
02687             /* use a reasonable size */
02688             *pcbAttrLen = MAX_BUFFER_SIZE;
02689     }
02690 
02691     ret = SCardGetSetAttrib(hCard, SCARD_GET_ATTRIB, dwAttrId, buf,
02692         pcbAttrLen);
02693 
02694     PROFILE_END(ret)
02695 
02696     return ret;
02697 }
02698 
02732 LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
02733     DWORD cbAttrLen)
02734 {
02735     LONG ret;
02736 
02737     PROFILE_START
02738 
02739     if (NULL == pbAttr || 0 == cbAttrLen)
02740         return SCARD_E_INVALID_PARAMETER;
02741 
02742     ret = SCardGetSetAttrib(hCard, SCARD_SET_ATTRIB, dwAttrId, (LPBYTE)pbAttr,
02743         &cbAttrLen);
02744 
02745     PROFILE_END(ret)
02746 
02747     return ret;
02748 }
02749 
02750 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
02751     LPBYTE pbAttr, LPDWORD pcbAttrLen)
02752 {
02753     LONG rv;
02754     getset_struct scGetSetStruct;
02755     sharedSegmentMsg msgStruct;
02756     int i;
02757     DWORD dwContextIndex, dwChannelIndex;
02758 
02759     rv = SCardCheckDaemonAvailability();
02760     if (rv != SCARD_S_SUCCESS)
02761         return rv;
02762 
02763     /*
02764      * Make sure this handle has been opened
02765      */
02766     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02767     if (rv == -1)
02768         return SCARD_E_INVALID_HANDLE;
02769 
02770     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02771 
02772     /* check the handle is still valid */
02773     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02774     if (rv == -1)
02775         /* the handle is now invalid
02776          * -> another thread may have called SCardReleaseContext
02777          * -> so the mMutex has been unlocked */
02778         return SCARD_E_INVALID_HANDLE;
02779 
02780     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02781     {
02782         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02783 
02784         /* by default r == NULL */
02785         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02786             break;
02787     }
02788 
02789     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02790     {
02791         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02792         return SCARD_E_READER_UNAVAILABLE;
02793     }
02794 
02795     if (*pcbAttrLen > MAX_BUFFER_SIZE)
02796     {
02797         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02798         return SCARD_E_INSUFFICIENT_BUFFER;
02799     }
02800 
02801     scGetSetStruct.hCard = hCard;
02802     scGetSetStruct.dwAttrId = dwAttrId;
02803     scGetSetStruct.cbAttrLen = *pcbAttrLen;
02804     scGetSetStruct.rv = SCARD_E_NO_SERVICE;
02805     memset(scGetSetStruct.pbAttr, 0, sizeof(scGetSetStruct.pbAttr));
02806     if (SCARD_SET_ATTRIB == command)
02807         memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
02808 
02809     rv = WrapSHMWrite(command,
02810         psContextMap[dwContextIndex].dwClientID, sizeof(scGetSetStruct),
02811         PCSCLITE_CLIENT_ATTEMPTS, &scGetSetStruct);
02812 
02813     if (rv == -1)
02814     {
02815         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02816         return SCARD_E_NO_SERVICE;
02817     }
02818 
02819     /*
02820      * Read a message from the server
02821      */
02822     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
02823         PCSCLITE_CLIENT_ATTEMPTS);
02824 
02825     if (rv == -1)
02826     {
02827         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02828         return SCARD_F_COMM_ERROR;
02829     }
02830 
02831     memcpy(&scGetSetStruct, &msgStruct.data, sizeof(scGetSetStruct));
02832 
02833     if ((SCARD_S_SUCCESS == scGetSetStruct.rv) && (SCARD_GET_ATTRIB == command))
02834     {
02835         /*
02836          * Copy and zero it so any secret information is not leaked
02837          */
02838         if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
02839         {
02840             scGetSetStruct.cbAttrLen = *pcbAttrLen;
02841             scGetSetStruct.rv = SCARD_E_INSUFFICIENT_BUFFER;
02842         }
02843         else
02844             *pcbAttrLen = scGetSetStruct.cbAttrLen;
02845 
02846         if (pbAttr)
02847             memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
02848 
02849         memset(scGetSetStruct.pbAttr, 0x00, sizeof(scGetSetStruct.pbAttr));
02850     }
02851 
02852     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02853 
02854     return scGetSetStruct.rv;
02855 }
02856 
02915 LONG SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci,
02916     LPCBYTE pbSendBuffer, DWORD cbSendLength,
02917     LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer,
02918     LPDWORD pcbRecvLength)
02919 {
02920     LONG rv;
02921     int i;
02922     DWORD dwContextIndex, dwChannelIndex;
02923 
02924     PROFILE_START
02925 
02926     if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
02927             pcbRecvLength == NULL || pioSendPci == NULL)
02928         return SCARD_E_INVALID_PARAMETER;
02929 
02930     rv = SCardCheckDaemonAvailability();
02931     if (rv != SCARD_S_SUCCESS)
02932         return rv;
02933 
02934     /*
02935      * Make sure this handle has been opened
02936      */
02937     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02938     if (rv == -1)
02939     {
02940         *pcbRecvLength = 0;
02941         return SCARD_E_INVALID_HANDLE;
02942     }
02943 
02944     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02945 
02946     /* check the handle is still valid */
02947     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02948     if (rv == -1)
02949         /* the handle is now invalid
02950          * -> another thread may have called SCardReleaseContext
02951          * -> so the mMutex has been unlocked */
02952         return SCARD_E_INVALID_HANDLE;
02953 
02954     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02955     {
02956         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02957 
02958         /* by default r == NULL */
02959         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02960             break;
02961     }
02962 
02963     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02964     {
02965         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02966         return SCARD_E_READER_UNAVAILABLE;
02967     }
02968 
02969     if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
02970         || (*pcbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
02971     {
02972         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02973         return SCARD_E_INSUFFICIENT_BUFFER;
02974     }
02975 
02976     if ((cbSendLength > MAX_BUFFER_SIZE) || (*pcbRecvLength > MAX_BUFFER_SIZE))
02977     {
02978         /* extended APDU */
02979         unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED];
02980         transmit_struct_extended *scTransmitStructExtended = (transmit_struct_extended *)buffer;
02981         sharedSegmentMsg *pmsgStruct = (psharedSegmentMsg)buffer;
02982 
02983         scTransmitStructExtended->hCard = hCard;
02984         scTransmitStructExtended->cbSendLength = cbSendLength;
02985         scTransmitStructExtended->pcbRecvLength = *pcbRecvLength;
02986         /* The size of data to send is the size of
02987          * struct control_struct_extended WITHOUT the data[] field
02988          * plus the effective data[] size
02989          */
02990         scTransmitStructExtended->size = sizeof(*scTransmitStructExtended)
02991             - (sizeof(transmit_struct_extended) - offsetof(transmit_struct_extended, data))
02992             + cbSendLength;
02993         scTransmitStructExtended->ioSendPciProtocol = pioSendPci->dwProtocol;
02994         scTransmitStructExtended->ioSendPciLength = pioSendPci->cbPciLength;
02995         memcpy(scTransmitStructExtended->data, pbSendBuffer, cbSendLength);
02996         scTransmitStructExtended->rv = SCARD_S_SUCCESS;
02997 
02998         if (pioRecvPci)
02999         {
03000             scTransmitStructExtended->ioRecvPciProtocol = pioRecvPci->dwProtocol;
03001             scTransmitStructExtended->ioRecvPciLength = pioRecvPci->cbPciLength;
03002         }
03003         else
03004         {
03005             scTransmitStructExtended->ioRecvPciProtocol = SCARD_PROTOCOL_ANY;
03006             scTransmitStructExtended->ioRecvPciLength = sizeof(SCARD_IO_REQUEST);
03007         }
03008 
03009         rv = WrapSHMWrite(SCARD_TRANSMIT_EXTENDED,
03010             psContextMap[dwContextIndex].dwClientID,
03011             scTransmitStructExtended->size,
03012             PCSCLITE_CLIENT_ATTEMPTS, buffer);
03013 
03014         if (rv == -1)
03015         {
03016             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03017             return SCARD_E_NO_SERVICE;
03018         }
03019 
03020         /*
03021          * Read a message from the server
03022          */
03023         /* read the first block */
03024         rv = SHMMessageReceive(buffer, sizeof(sharedSegmentMsg), psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
03025         if (rv == -1)
03026         {
03027             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03028             return SCARD_F_COMM_ERROR;
03029         }
03030 
03031         /* we receive a sharedSegmentMsg and not a transmit_struct_extended */
03032         scTransmitStructExtended = (transmit_struct_extended *)&(pmsgStruct -> data);
03033 
03034         /* a second block is present */
03035         if (scTransmitStructExtended->size > PCSCLITE_MAX_MESSAGE_SIZE)
03036         {
03037             rv = SHMMessageReceive(buffer + sizeof(sharedSegmentMsg),
03038                 scTransmitStructExtended->size-PCSCLITE_MAX_MESSAGE_SIZE,
03039                 psContextMap[dwContextIndex].dwClientID,
03040                 PCSCLITE_CLIENT_ATTEMPTS);
03041             if (rv == -1)
03042             {
03043                 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03044                 return SCARD_F_COMM_ERROR;
03045             }
03046         }
03047 
03048         if (scTransmitStructExtended -> rv == SCARD_S_SUCCESS)
03049         {
03050             /*
03051              * Copy and zero it so any secret information is not leaked
03052              */
03053             memcpy(pbRecvBuffer, scTransmitStructExtended -> data,
03054                 scTransmitStructExtended -> pcbRecvLength);
03055             memset(scTransmitStructExtended -> data, 0x00,
03056                 scTransmitStructExtended -> pcbRecvLength);
03057 
03058             if (pioRecvPci)
03059             {
03060                 pioRecvPci->dwProtocol = scTransmitStructExtended->ioRecvPciProtocol;
03061                 pioRecvPci->cbPciLength = scTransmitStructExtended->ioRecvPciLength;
03062             }
03063         }
03064 
03065         *pcbRecvLength = scTransmitStructExtended -> pcbRecvLength;
03066         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03067 
03068         rv = scTransmitStructExtended -> rv;
03069     }
03070     else
03071     {
03072         /* short APDU */
03073         transmit_struct scTransmitStruct;
03074         sharedSegmentMsg msgStruct;
03075 
03076         scTransmitStruct.hCard = hCard;
03077         scTransmitStruct.cbSendLength = cbSendLength;
03078         scTransmitStruct.pcbRecvLength = *pcbRecvLength;
03079         scTransmitStruct.ioSendPciProtocol = pioSendPci->dwProtocol;
03080         scTransmitStruct.ioSendPciLength = pioSendPci->cbPciLength;
03081         memcpy(scTransmitStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
03082         memset(scTransmitStruct.pbSendBuffer+cbSendLength, 0, sizeof(scTransmitStruct.pbSendBuffer)-cbSendLength);
03083         memset(scTransmitStruct.pbRecvBuffer, 0, sizeof(scTransmitStruct.pbRecvBuffer));
03084         scTransmitStruct.rv = SCARD_S_SUCCESS;
03085 
03086         if (pioRecvPci)
03087         {
03088             scTransmitStruct.ioRecvPciProtocol = pioRecvPci->dwProtocol;
03089             scTransmitStruct.ioRecvPciLength = pioRecvPci->cbPciLength;
03090         }
03091         else
03092         {
03093             scTransmitStruct.ioRecvPciProtocol = SCARD_PROTOCOL_ANY;
03094             scTransmitStruct.ioRecvPciLength = sizeof(SCARD_IO_REQUEST);
03095         }
03096 
03097         rv = WrapSHMWrite(SCARD_TRANSMIT,
03098             psContextMap[dwContextIndex].dwClientID, sizeof(scTransmitStruct),
03099             PCSCLITE_CLIENT_ATTEMPTS, (void *) &scTransmitStruct);
03100 
03101         if (rv == -1)
03102         {
03103             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03104             return SCARD_E_NO_SERVICE;
03105         }
03106 
03107         /*
03108          * Read a message from the server
03109          */
03110         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
03111             PCSCLITE_CLIENT_ATTEMPTS);
03112 
03113         memcpy(&scTransmitStruct, &msgStruct.data, sizeof(scTransmitStruct));
03114 
03115         if (rv == -1)
03116         {
03117             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03118             return SCARD_F_COMM_ERROR;
03119         }
03120 
03121         /*
03122          * Zero it and free it so any secret information cannot be leaked
03123          */
03124         memset(scTransmitStruct.pbSendBuffer, 0x00, cbSendLength);
03125 
03126         if (scTransmitStruct.rv == SCARD_S_SUCCESS)
03127         {
03128             /*
03129              * Copy and zero it so any secret information is not leaked
03130              */
03131             memcpy(pbRecvBuffer, scTransmitStruct.pbRecvBuffer,
03132                 scTransmitStruct.pcbRecvLength);
03133             memset(scTransmitStruct.pbRecvBuffer, 0x00,
03134                 scTransmitStruct.pcbRecvLength);
03135 
03136             if (pioRecvPci)
03137             {
03138                 pioRecvPci->dwProtocol = scTransmitStruct.ioRecvPciProtocol;
03139                 pioRecvPci->cbPciLength = scTransmitStruct.ioRecvPciLength;
03140             }
03141         }
03142 
03143         *pcbRecvLength = scTransmitStruct.pcbRecvLength;
03144         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03145 
03146         rv = scTransmitStruct.rv;
03147     }
03148 
03149     PROFILE_END(rv)
03150 
03151     return rv;
03152 }
03153 
03202 LONG SCardListReaders(SCARDCONTEXT hContext, /*@unused@*/ LPCSTR mszGroups,
03203     LPSTR mszReaders, LPDWORD pcchReaders)
03204 {
03205     DWORD dwReadersLen;
03206     int i;
03207     LONG dwContextIndex;
03208     LONG rv = SCARD_S_SUCCESS;
03209     char *buf = NULL;
03210 
03211     (void)mszGroups;
03212     PROFILE_START
03213 
03214     /*
03215      * Check for NULL parameters
03216      */
03217     if (pcchReaders == NULL)
03218         return SCARD_E_INVALID_PARAMETER;
03219 
03220     rv = SCardCheckDaemonAvailability();
03221     if (rv != SCARD_S_SUCCESS)
03222         return rv;
03223 
03224     /*
03225      * Make sure this context has been opened
03226      */
03227     dwContextIndex = SCardGetContextIndice(hContext);
03228     if (dwContextIndex == -1)
03229         return SCARD_E_INVALID_HANDLE;
03230 
03231     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
03232 
03233     /* check the context is still opened */
03234     dwContextIndex = SCardGetContextIndice(hContext);
03235     if (dwContextIndex == -1)
03236         /* the context is now invalid
03237          * -> another thread may have called SCardReleaseContext
03238          * -> so the mMutex has been unlocked */
03239         return SCARD_E_INVALID_HANDLE;
03240 
03241     dwReadersLen = 0;
03242     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
03243         if ((readerStates[i])->readerID != 0)
03244             dwReadersLen += strlen((readerStates[i])->readerName) + 1;
03245 
03246     /* for the last NULL byte */
03247     dwReadersLen += 1;
03248 
03249     if (1 == dwReadersLen)
03250     {
03251         rv = SCARD_E_NO_READERS_AVAILABLE;
03252         goto end;
03253     }
03254 
03255     if (SCARD_AUTOALLOCATE == *pcchReaders)
03256     {
03257         buf = malloc(dwReadersLen);
03258         if (NULL == buf)
03259         {
03260             rv = SCARD_E_NO_MEMORY;
03261             goto end;
03262         }
03263         if (NULL == mszReaders)
03264         {
03265             rv = SCARD_E_INVALID_PARAMETER;
03266             goto end;
03267         }
03268         *(char **)mszReaders = buf;
03269     }
03270     else
03271     {
03272         buf = mszReaders;
03273 
03274         /* not enough place to store the reader names */
03275         if ((NULL != mszReaders) && (*pcchReaders < dwReadersLen))
03276         {
03277             rv = SCARD_E_INSUFFICIENT_BUFFER;
03278             goto end;
03279         }
03280     }
03281 
03282     if (mszReaders == NULL) /* text array not allocated */
03283         goto end;
03284 
03285     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
03286     {
03287         if ((readerStates[i])->readerID != 0)
03288         {
03289             /*
03290              * Build the multi-string
03291              */
03292             strcpy(buf, (readerStates[i])->readerName);
03293             buf += strlen((readerStates[i])->readerName)+1;
03294         }
03295     }
03296     *buf = '\0';    /* Add the last null */
03297 
03298 end:
03299     /* set the reader names length */
03300     *pcchReaders = dwReadersLen;
03301 
03302     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03303 
03304     PROFILE_END(rv)
03305 
03306     return rv;
03307 }
03308 
03321 LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
03322 {
03323     LONG rv = SCARD_S_SUCCESS;
03324     LONG dwContextIndex;
03325 
03326     PROFILE_START
03327 
03328     rv = SCardCheckDaemonAvailability();
03329     if (rv != SCARD_S_SUCCESS)
03330         return rv;
03331 
03332     /*
03333      * Make sure this context has been opened
03334      */
03335     dwContextIndex = SCardGetContextIndice(hContext);
03336     if (dwContextIndex == -1)
03337         return SCARD_E_INVALID_HANDLE;
03338 
03339     free((void *)pvMem);
03340 
03341     PROFILE_END(rv)
03342 
03343     return rv;
03344 }
03345 
03395 LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups,
03396     LPDWORD pcchGroups)
03397 {
03398     LONG rv = SCARD_S_SUCCESS;
03399     LONG dwContextIndex;
03400     char *buf = NULL;
03401 
03402     PROFILE_START
03403 
03404     /* Multi-string with two trailing \0 */
03405     const char ReaderGroup[] = "SCard$DefaultReaders\0";
03406     const int dwGroups = sizeof(ReaderGroup);
03407 
03408     rv = SCardCheckDaemonAvailability();
03409     if (rv != SCARD_S_SUCCESS)
03410         return rv;
03411 
03412     /*
03413      * Make sure this context has been opened
03414      */
03415     dwContextIndex = SCardGetContextIndice(hContext);
03416     if (dwContextIndex == -1)
03417         return SCARD_E_INVALID_HANDLE;
03418 
03419     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
03420 
03421     /* check the context is still opened */
03422     dwContextIndex = SCardGetContextIndice(hContext);
03423     if (dwContextIndex == -1)
03424         /* the context is now invalid
03425          * -> another thread may have called SCardReleaseContext
03426          * -> so the mMutex has been unlocked */
03427         return SCARD_E_INVALID_HANDLE;
03428 
03429     if (SCARD_AUTOALLOCATE == *pcchGroups)
03430     {
03431         buf = malloc(dwGroups);
03432         if (NULL == buf)
03433         {
03434             rv = SCARD_E_NO_MEMORY;
03435             goto end;
03436         }
03437         if (NULL == mszGroups)
03438         {
03439             rv = SCARD_E_INVALID_PARAMETER;
03440             goto end;
03441         }
03442         *(char **)mszGroups = buf;
03443     }
03444     else
03445     {
03446         buf = mszGroups;
03447 
03448         if ((NULL != mszGroups) && (*pcchGroups < dwGroups))
03449         {
03450             rv = SCARD_E_INSUFFICIENT_BUFFER;
03451             goto end;
03452         }
03453     }
03454 
03455     if (buf)
03456         memcpy(buf, ReaderGroup, dwGroups);
03457 
03458 end:
03459     *pcchGroups = dwGroups;
03460 
03461     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03462 
03463     PROFILE_END(rv)
03464 
03465     return rv;
03466 }
03467 
03495 LONG SCardCancel(SCARDCONTEXT hContext)
03496 {
03497     LONG dwContextIndex;
03498     LONG rv = SCARD_S_SUCCESS;
03499 
03500     PROFILE_START
03501 
03502     dwContextIndex = SCardGetContextIndice(hContext);
03503     if (dwContextIndex == -1)
03504         return SCARD_E_INVALID_HANDLE;
03505 
03506     /*
03507      * Set the block status for this Context so blocking calls will
03508      * complete
03509      */
03510     psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_RESUME;
03511 
03512     if (StatSynchronizeContext(hContext))
03513         rv = SCARD_F_INTERNAL_ERROR;
03514 
03515     PROFILE_END(rv)
03516 
03517     return rv;
03518 }
03519 
03543 LONG SCardIsValidContext(SCARDCONTEXT hContext)
03544 {
03545     LONG rv;
03546     LONG dwContextIndex;
03547 
03548     PROFILE_START
03549 
03550     rv = SCARD_S_SUCCESS;
03551 
03552     /* Check if the _same_ server is running */
03553     rv = SCardCheckDaemonAvailability();
03554     if (rv != SCARD_S_SUCCESS)
03555         return rv;
03556 
03557     /*
03558      * Make sure this context has been opened
03559      */
03560     dwContextIndex = SCardGetContextIndice(hContext);
03561     if (dwContextIndex == -1)
03562         rv = SCARD_E_INVALID_HANDLE;
03563 
03564     PROFILE_END(rv)
03565 
03566     return rv;
03567 }
03568 
03585 static LONG SCardAddContext(SCARDCONTEXT hContext, DWORD dwClientID)
03586 {
03587     int i;
03588 
03589     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03590     {
03591         if (psContextMap[i].hContext == 0)
03592         {
03593             psContextMap[i].hContext = hContext;
03594             psContextMap[i].dwClientID = dwClientID;
03595             psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;
03596             psContextMap[i].mMutex = malloc(sizeof(PCSCLITE_MUTEX));
03597             (void)SYS_MutexInit(psContextMap[i].mMutex);
03598             return SCARD_S_SUCCESS;
03599         }
03600     }
03601 
03602     return SCARD_E_NO_MEMORY;
03603 }
03604 
03617 static LONG SCardGetContextIndice(SCARDCONTEXT hContext)
03618 {
03619     LONG rv;
03620 
03621     (void)SCardLockThread();
03622     rv = SCardGetContextIndiceTH(hContext);
03623     (void)SCardUnlockThread();
03624 
03625     return rv;
03626 }
03627 
03640 static LONG SCardGetContextIndiceTH(SCARDCONTEXT hContext)
03641 {
03642     int i;
03643 
03644     /*
03645      * Find this context and return its spot in the array
03646      */
03647     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03648     {
03649         if ((hContext == psContextMap[i].hContext) && (hContext != 0))
03650             return i;
03651     }
03652 
03653     return -1;
03654 }
03655 
03665 static LONG SCardRemoveContext(SCARDCONTEXT hContext)
03666 {
03667     LONG  retIndice;
03668 
03669     retIndice = SCardGetContextIndiceTH(hContext);
03670 
03671     if (retIndice == -1)
03672         return SCARD_E_INVALID_HANDLE;
03673     else
03674         return SCardCleanContext(retIndice);
03675 }
03676 
03677 static LONG SCardCleanContext(LONG indice)
03678 {
03679     int i;
03680 
03681     psContextMap[indice].hContext = 0;
03682     (void)SHMClientCloseSession(psContextMap[indice].dwClientID);
03683     psContextMap[indice].dwClientID = 0;
03684     free(psContextMap[indice].mMutex);
03685     psContextMap[indice].mMutex = NULL;
03686     psContextMap[indice].contextBlockStatus = BLOCK_STATUS_RESUME;
03687 
03688     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03689     {
03690         /*
03691          * Reset the \c hCard structs to zero
03692          */
03693         psContextMap[indice].psChannelMap[i].hCard = 0;
03694         free(psContextMap[indice].psChannelMap[i].readerName);
03695         psContextMap[indice].psChannelMap[i].readerName = NULL;
03696     }
03697 
03698     return SCARD_S_SUCCESS;
03699 }
03700 
03701 /*
03702  * Functions for managing hCard values returned from SCardConnect.
03703  */
03704 
03705 static LONG SCardAddHandle(SCARDHANDLE hCard, DWORD dwContextIndex,
03706     LPCSTR readerName)
03707 {
03708     int i;
03709 
03710     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03711     {
03712         if (psContextMap[dwContextIndex].psChannelMap[i].hCard == 0)
03713         {
03714             psContextMap[dwContextIndex].psChannelMap[i].hCard = hCard;
03715             psContextMap[dwContextIndex].psChannelMap[i].readerName = strdup(readerName);
03716             return SCARD_S_SUCCESS;
03717         }
03718     }
03719 
03720     return SCARD_E_NO_MEMORY;
03721 }
03722 
03723 static LONG SCardRemoveHandle(SCARDHANDLE hCard)
03724 {
03725     DWORD dwContextIndice, dwChannelIndice;
03726     LONG rv;
03727 
03728     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndice, &dwChannelIndice);
03729     if (rv == -1)
03730         return SCARD_E_INVALID_HANDLE;
03731     else
03732     {
03733         psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].hCard = 0;
03734         free(psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName);
03735         psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName = NULL;
03736         return SCARD_S_SUCCESS;
03737     }
03738 }
03739 
03740 static LONG SCardGetIndicesFromHandle(SCARDHANDLE hCard,
03741     PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
03742 {
03743     LONG rv;
03744 
03745     if (0 == hCard)
03746         return -1;
03747 
03748     (void)SCardLockThread();
03749     rv = SCardGetIndicesFromHandleTH(hCard, pdwContextIndice, pdwChannelIndice);
03750     (void)SCardUnlockThread();
03751 
03752     return rv;
03753 }
03754 
03755 static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE hCard,
03756     PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
03757 {
03758     int i;
03759 
03760     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03761     {
03762         if (psContextMap[i].hContext != 0)
03763         {
03764             int j;
03765 
03766             for (j = 0; j < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; j++)
03767             {
03768                 if (psContextMap[i].psChannelMap[j].hCard == hCard)
03769                 {
03770                     *pdwContextIndice = i;
03771                     *pdwChannelIndice = j;
03772                     return SCARD_S_SUCCESS;
03773                 }
03774             }
03775 
03776         }
03777     }
03778 
03779     return -1;
03780 }
03781 
03790 LONG SCardCheckDaemonAvailability(void)
03791 {
03792     LONG rv;
03793     struct stat statBuffer;
03794     int need_restart = 0;
03795 
03796     rv = SYS_Stat(PCSCLITE_PUBSHM_FILE, &statBuffer);
03797 
03798     if (rv != 0)
03799     {
03800         Log2(PCSC_LOG_INFO, "PCSC Not Running: " PCSCLITE_PUBSHM_FILE ": %s",
03801             strerror(errno));
03802         return SCARD_E_NO_SERVICE;
03803     }
03804 
03805     /* when the _first_ reader is connected the ctime changes
03806      * I don't know why yet */
03807     if (daemon_ctime && statBuffer.st_ctime > daemon_ctime)
03808     {
03809         /* so we also check the daemon pid to be sure it is a new pcscd */
03810         if (GetDaemonPid() != daemon_pid)
03811         {
03812             Log1(PCSC_LOG_INFO, "PCSC restarted");
03813             need_restart = 1;
03814         }
03815     }
03816 
03817     /* after fork() need to restart */
03818     if (client_pid && client_pid != getpid())
03819     {
03820         Log1(PCSC_LOG_INFO, "Client forked");
03821         need_restart = 1;
03822     }
03823 
03824     if (need_restart)
03825     {
03826         int i;
03827 
03828         /* invalid all handles */
03829         (void)SCardLockThread();
03830 
03831         for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03832             if (psContextMap[i].hContext)
03833                 (void)SCardCleanContext(i);
03834 
03835         (void)SCardUnlockThread();
03836 
03837         /* reset pcscd status */
03838         daemon_ctime = 0;
03839         client_pid = 0;
03840 
03841         /* reset the lib */
03842         SCardUnload();
03843 
03844         return SCARD_E_INVALID_HANDLE;
03845     }
03846 
03847     daemon_ctime = statBuffer.st_ctime;
03848     daemon_pid = GetDaemonPid();
03849     client_pid = getpid();
03850 
03851     return SCARD_S_SUCCESS;
03852 }
03853 
03860 #ifdef __SUNPRO_C
03861 #pragma fini (SCardUnload)
03862 #endif
03863 
03864 void DESTRUCTOR SCardUnload(void)
03865 {
03866     int i;
03867 
03868     if (!isExecuted)
03869         return;
03870 
03871     /* unmap public shared file from memory */
03872     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03873     {
03874         if (readerStates[i] != NULL)
03875         {
03876             SYS_PublicMemoryUnmap(readerStates[i], sizeof(READER_STATE));
03877             readerStates[i] = NULL;
03878         }
03879     }
03880 
03881     (void)SYS_CloseFile(mapAddr);
03882     isExecuted = 0;
03883 }
03884