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 4271 2009-06-23 08:12:05Z 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.phContext = 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.phContext))
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.phContext;
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 
00733 LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader,
00734     DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
00735     LPDWORD pdwActiveProtocol)
00736 {
00737     LONG rv;
00738     connect_struct scConnectStruct;
00739     sharedSegmentMsg msgStruct;
00740     LONG dwContextIndex;
00741 
00742     PROFILE_START
00743 
00744     /*
00745      * Check for NULL parameters
00746      */
00747     if (phCard == NULL || pdwActiveProtocol == NULL)
00748         return SCARD_E_INVALID_PARAMETER;
00749     else
00750         *phCard = 0;
00751 
00752     if (szReader == NULL)
00753         return SCARD_E_UNKNOWN_READER;
00754 
00755     /*
00756      * Check for uninitialized strings
00757      */
00758     if (strlen(szReader) > MAX_READERNAME)
00759         return SCARD_E_INVALID_VALUE;
00760 
00761     rv = SCardCheckDaemonAvailability();
00762     if (rv != SCARD_S_SUCCESS)
00763         return rv;
00764 
00765     /*
00766      * Make sure this context has been opened
00767      */
00768     dwContextIndex = SCardGetContextIndice(hContext);
00769     if (dwContextIndex == -1)
00770         return SCARD_E_INVALID_HANDLE;
00771 
00772     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
00773 
00774     /* check the context is still opened */
00775     dwContextIndex = SCardGetContextIndice(hContext);
00776     if (dwContextIndex == -1)
00777         /* the context is now invalid
00778          * -> another thread may have called SCardReleaseContext
00779          * -> so the mMutex has been unlocked */
00780         return SCARD_E_INVALID_HANDLE;
00781 
00782     strncpy(scConnectStruct.szReader, szReader, MAX_READERNAME);
00783 
00784     scConnectStruct.hContext = hContext;
00785     scConnectStruct.dwShareMode = dwShareMode;
00786     scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
00787     scConnectStruct.phCard = 0;
00788     scConnectStruct.pdwActiveProtocol = 0;
00789     scConnectStruct.rv = SCARD_S_SUCCESS;
00790 
00791     rv = WrapSHMWrite(SCARD_CONNECT, psContextMap[dwContextIndex].dwClientID,
00792         sizeof(scConnectStruct),
00793         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scConnectStruct);
00794 
00795     if (rv == -1)
00796     {
00797         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00798         return SCARD_E_NO_SERVICE;
00799     }
00800 
00801     /*
00802      * Read a message from the server
00803      */
00804     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
00805         PCSCLITE_CLIENT_ATTEMPTS);
00806 
00807     memcpy(&scConnectStruct, &msgStruct.data, sizeof(scConnectStruct));
00808 
00809     if (rv == -1)
00810     {
00811         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00812         return SCARD_F_COMM_ERROR;
00813     }
00814 
00815     *phCard = scConnectStruct.phCard;
00816     *pdwActiveProtocol = scConnectStruct.pdwActiveProtocol;
00817 
00818     if (scConnectStruct.rv == SCARD_S_SUCCESS)
00819     {
00820         /*
00821          * Keep track of the handle locally
00822          */
00823         rv = SCardAddHandle(*phCard, dwContextIndex, szReader);
00824         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00825 
00826         PROFILE_END(rv)
00827 
00828         return rv;
00829     }
00830 
00831     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00832 
00833     PROFILE_END(scConnectStruct.rv)
00834 
00835     return scConnectStruct.rv;
00836 }
00837 
00905 LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
00906     DWORD dwPreferredProtocols, DWORD dwInitialization,
00907     LPDWORD pdwActiveProtocol)
00908 {
00909     LONG rv;
00910     reconnect_struct scReconnectStruct;
00911     sharedSegmentMsg msgStruct;
00912     int i;
00913     DWORD dwContextIndex, dwChannelIndex;
00914 
00915     PROFILE_START
00916 
00917     if (pdwActiveProtocol == NULL)
00918         return SCARD_E_INVALID_PARAMETER;
00919 
00920     rv = SCardCheckDaemonAvailability();
00921     if (rv != SCARD_S_SUCCESS)
00922         return rv;
00923 
00924     /*
00925      * Make sure this handle has been opened
00926      */
00927     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
00928     if (rv == -1)
00929         return SCARD_E_INVALID_HANDLE;
00930 
00931     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
00932 
00933     /* check the handle is still valid */
00934     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
00935     if (rv == -1)
00936         /* the handle is now invalid
00937          * -> another thread may have called SCardReleaseContext
00938          * -> so the mMutex has been unlocked */
00939         return SCARD_E_INVALID_HANDLE;
00940 
00941     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00942     {
00943         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
00944 
00945         /* by default r == NULL */
00946         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
00947             break;
00948     }
00949 
00950     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
00951     {
00952         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00953         return SCARD_E_READER_UNAVAILABLE;
00954     }
00955 
00956     do
00957     {
00958         scReconnectStruct.hCard = hCard;
00959         scReconnectStruct.dwShareMode = dwShareMode;
00960         scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
00961         scReconnectStruct.dwInitialization = dwInitialization;
00962         scReconnectStruct.pdwActiveProtocol = *pdwActiveProtocol;
00963         scReconnectStruct.rv = SCARD_S_SUCCESS;
00964 
00965         rv = WrapSHMWrite(SCARD_RECONNECT, psContextMap[dwContextIndex].dwClientID,
00966             sizeof(scReconnectStruct),
00967             PCSCLITE_CLIENT_ATTEMPTS, (void *) &scReconnectStruct);
00968 
00969         if (rv == -1)
00970         {
00971             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00972             return SCARD_E_NO_SERVICE;
00973         }
00974 
00975         /*
00976          * Read a message from the server
00977          */
00978         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
00979             PCSCLITE_CLIENT_ATTEMPTS);
00980 
00981         memcpy(&scReconnectStruct, &msgStruct.data, sizeof(scReconnectStruct));
00982 
00983         if (rv == -1)
00984         {
00985             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00986             return SCARD_F_COMM_ERROR;
00987         }
00988     } while (SCARD_E_SHARING_VIOLATION == scReconnectStruct.rv);
00989 
00990     *pdwActiveProtocol = scReconnectStruct.pdwActiveProtocol;
00991 
00992     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00993 
00994     PROFILE_END(scReconnectStruct.rv)
00995 
00996     return scReconnectStruct.rv;
00997 }
00998 
01029 LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
01030 {
01031     LONG rv;
01032     disconnect_struct scDisconnectStruct;
01033     sharedSegmentMsg msgStruct;
01034     DWORD dwContextIndex, dwChannelIndex;
01035 
01036     PROFILE_START
01037 
01038     rv = SCardCheckDaemonAvailability();
01039     if (rv != SCARD_S_SUCCESS)
01040         return rv;
01041 
01042     /*
01043      * Make sure this handle has been opened
01044      */
01045     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01046     if (rv == -1)
01047         return SCARD_E_INVALID_HANDLE;
01048 
01049     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01050 
01051     /* check the handle is still valid */
01052     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01053     if (rv == -1)
01054         /* the handle is now invalid
01055          * -> another thread may have called SCardReleaseContext
01056          * -> so the mMutex has been unlocked */
01057         return SCARD_E_INVALID_HANDLE;
01058 
01059     scDisconnectStruct.hCard = hCard;
01060     scDisconnectStruct.dwDisposition = dwDisposition;
01061     scDisconnectStruct.rv = SCARD_S_SUCCESS;
01062 
01063     rv = WrapSHMWrite(SCARD_DISCONNECT, psContextMap[dwContextIndex].dwClientID,
01064         sizeof(scDisconnectStruct),
01065         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scDisconnectStruct);
01066 
01067     if (rv == -1)
01068     {
01069         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01070         return SCARD_E_NO_SERVICE;
01071     }
01072 
01073     /*
01074      * Read a message from the server
01075      */
01076     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01077         PCSCLITE_CLIENT_ATTEMPTS);
01078 
01079     memcpy(&scDisconnectStruct, &msgStruct.data,
01080         sizeof(scDisconnectStruct));
01081 
01082     if (rv == -1)
01083     {
01084         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01085         return SCARD_F_COMM_ERROR;
01086     }
01087 
01088     (void)SCardRemoveHandle(hCard);
01089 
01090     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01091 
01092     PROFILE_END(scDisconnectStruct.rv)
01093 
01094     return scDisconnectStruct.rv;
01095 }
01096 
01132 LONG SCardBeginTransaction(SCARDHANDLE hCard)
01133 {
01134 
01135     LONG rv;
01136     begin_struct scBeginStruct;
01137     int i;
01138     sharedSegmentMsg msgStruct;
01139     DWORD dwContextIndex, dwChannelIndex;
01140 
01141     PROFILE_START
01142 
01143     rv = SCardCheckDaemonAvailability();
01144     if (rv != SCARD_S_SUCCESS)
01145         return rv;
01146 
01147     /*
01148      * Make sure this handle has been opened
01149      */
01150     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01151     if (rv == -1)
01152         return SCARD_E_INVALID_HANDLE;
01153 
01154     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01155 
01156     /* check the handle is still valid */
01157     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01158     if (rv == -1)
01159         /* the handle is now invalid
01160          * -> another thread may have called SCardReleaseContext
01161          * -> so the mMutex has been unlocked */
01162         return SCARD_E_INVALID_HANDLE;
01163 
01164     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01165     {
01166         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01167 
01168         /* by default r == NULL */
01169         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01170             break;
01171     }
01172 
01173     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01174     {
01175         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01176         return SCARD_E_READER_UNAVAILABLE;
01177     }
01178 
01179     scBeginStruct.hCard = hCard;
01180     scBeginStruct.rv = SCARD_S_SUCCESS;
01181 
01182     /*
01183      * Query the server every so often until the sharing violation ends
01184      * and then hold the lock for yourself.
01185      */
01186 
01187     do
01188     {
01189         rv = WrapSHMWrite(SCARD_BEGIN_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
01190             sizeof(scBeginStruct),
01191             PCSCLITE_CLIENT_ATTEMPTS, (void *) &scBeginStruct);
01192 
01193         if (rv == -1)
01194         {
01195 
01196             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01197             return SCARD_E_NO_SERVICE;
01198         }
01199 
01200         /*
01201          * Read a message from the server
01202          */
01203         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01204             PCSCLITE_CLIENT_ATTEMPTS);
01205 
01206         memcpy(&scBeginStruct, &msgStruct.data, sizeof(scBeginStruct));
01207 
01208         if (rv == -1)
01209         {
01210 
01211             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01212             return SCARD_F_COMM_ERROR;
01213         }
01214 
01215     }
01216     while (scBeginStruct.rv == SCARD_E_SHARING_VIOLATION);
01217 
01218     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01219 
01220     PROFILE_END(scBeginStruct.rv);
01221 
01222     return scBeginStruct.rv;
01223 }
01224 
01265 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
01266 {
01267     LONG rv;
01268     end_struct scEndStruct;
01269     sharedSegmentMsg msgStruct;
01270     int randnum, i;
01271     DWORD dwContextIndex, dwChannelIndex;
01272 
01273     PROFILE_START
01274 
01275     /*
01276      * Zero out everything
01277      */
01278     randnum = 0;
01279 
01280     rv = SCardCheckDaemonAvailability();
01281     if (rv != SCARD_S_SUCCESS)
01282         return rv;
01283 
01284     /*
01285      * Make sure this handle has been opened
01286      */
01287     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01288     if (rv == -1)
01289         return SCARD_E_INVALID_HANDLE;
01290 
01291     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01292 
01293     /* check the handle is still valid */
01294     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01295     if (rv == -1)
01296         /* the handle is now invalid
01297          * -> another thread may have called SCardReleaseContext
01298          * -> so the mMutex has been unlocked */
01299         return SCARD_E_INVALID_HANDLE;
01300 
01301     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01302     {
01303         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01304 
01305         /* by default r == NULL */
01306         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01307             break;
01308     }
01309 
01310     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01311     {
01312         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01313         return SCARD_E_READER_UNAVAILABLE;
01314     }
01315 
01316     scEndStruct.hCard = hCard;
01317     scEndStruct.dwDisposition = dwDisposition;
01318     scEndStruct.rv = SCARD_S_SUCCESS;
01319 
01320     rv = WrapSHMWrite(SCARD_END_TRANSACTION,
01321         psContextMap[dwContextIndex].dwClientID,
01322         sizeof(scEndStruct),
01323         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scEndStruct);
01324 
01325     if (rv == -1)
01326     {
01327         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01328         return SCARD_E_NO_SERVICE;
01329     }
01330 
01331     /*
01332      * Read a message from the server
01333      */
01334     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01335         PCSCLITE_CLIENT_ATTEMPTS);
01336 
01337     memcpy(&scEndStruct, &msgStruct.data, sizeof(scEndStruct));
01338 
01339     if (rv == -1)
01340     {
01341         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01342         return SCARD_F_COMM_ERROR;
01343     }
01344 
01345     /*
01346      * This helps prevent starvation
01347      */
01348     randnum = SYS_RandomInt(1000, 10000);
01349     (void)SYS_USleep(randnum);
01350 
01351     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01352 
01353     PROFILE_END(scEndStruct.rv)
01354 
01355     return scEndStruct.rv;
01356 }
01357 
01364 LONG SCardCancelTransaction(SCARDHANDLE hCard)
01365 {
01366     LONG rv;
01367     cancel_struct scCancelStruct;
01368     sharedSegmentMsg msgStruct;
01369     int i;
01370     DWORD dwContextIndex, dwChannelIndex;
01371 
01372     PROFILE_START
01373 
01374     rv = SCardCheckDaemonAvailability();
01375     if (rv != SCARD_S_SUCCESS)
01376         return rv;
01377 
01378     /*
01379      * Make sure this handle has been opened
01380      */
01381     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01382     if (rv == -1)
01383         return SCARD_E_INVALID_HANDLE;
01384 
01385     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01386 
01387     /* check the handle is still valid */
01388     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01389     if (rv == -1)
01390         /* the handle is now invalid
01391          * -> another thread may have called SCardReleaseContext
01392          * -> so the mMutex has been unlocked */
01393         return SCARD_E_INVALID_HANDLE;
01394 
01395     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01396     {
01397         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01398 
01399         /* by default r == NULL */
01400         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01401             break;
01402     }
01403 
01404     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01405     {
01406         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01407         return SCARD_E_READER_UNAVAILABLE;
01408     }
01409 
01410     scCancelStruct.hCard = hCard;
01411 
01412     rv = WrapSHMWrite(SCARD_CANCEL_TRANSACTION,
01413         psContextMap[dwContextIndex].dwClientID,
01414         sizeof(scCancelStruct),
01415         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scCancelStruct);
01416 
01417     if (rv == -1)
01418     {
01419         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01420         return SCARD_E_NO_SERVICE;
01421     }
01422 
01423     /*
01424      * Read a message from the server
01425      */
01426     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01427         PCSCLITE_CLIENT_ATTEMPTS);
01428 
01429     memcpy(&scCancelStruct, &msgStruct.data, sizeof(scCancelStruct));
01430 
01431     if (rv == -1)
01432     {
01433         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01434         return SCARD_F_COMM_ERROR;
01435     }
01436 
01437     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01438 
01439     PROFILE_END(scCancelStruct.rv)
01440 
01441     return scCancelStruct.rv;
01442 }
01443 
01531 LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName,
01532     LPDWORD pcchReaderLen, LPDWORD pdwState,
01533     LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
01534 {
01535     DWORD dwReaderLen, dwAtrLen;
01536     LONG rv;
01537     int i;
01538     status_struct scStatusStruct;
01539     sharedSegmentMsg msgStruct;
01540     DWORD dwContextIndex, dwChannelIndex;
01541     char *r;
01542     char *bufReader = NULL;
01543     LPBYTE bufAtr = NULL;
01544     DWORD dummy;
01545 
01546     PROFILE_START
01547 
01548     /* default output values */
01549     if (pdwState)
01550         *pdwState = 0;
01551 
01552     if (pdwProtocol)
01553         *pdwProtocol = 0;
01554 
01555     /* Check for NULL parameters */ 
01556     if (pcchReaderLen == NULL)
01557         pcchReaderLen = &dummy;
01558     
01559     if (pcbAtrLen == NULL)
01560         pcbAtrLen = &dummy;
01561 
01562     /* length passed from caller */
01563     dwReaderLen = *pcchReaderLen;
01564     dwAtrLen = *pcbAtrLen;
01565 
01566     *pcchReaderLen = 0;
01567     *pcbAtrLen = 0;
01568 
01569     rv = SCardCheckDaemonAvailability();
01570     if (rv != SCARD_S_SUCCESS)
01571         return rv;
01572 
01573     /*
01574      * Make sure this handle has been opened
01575      */
01576     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01577     if (rv == -1)
01578         return SCARD_E_INVALID_HANDLE;
01579 
01580     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01581 
01582     /* check the handle is still valid */
01583     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01584     if (rv == -1)
01585         /* the handle is now invalid
01586          * -> another thread may have called SCardReleaseContext
01587          * -> so the mMutex has been unlocked */
01588         return SCARD_E_INVALID_HANDLE;
01589 
01590     r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01591     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01592     {
01593         /* by default r == NULL */
01594         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01595             break;
01596     }
01597 
01598     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01599     {
01600         rv = SCARD_E_READER_UNAVAILABLE;
01601         goto end;
01602     }
01603 
01604     /* initialise the structure */
01605     memset(&scStatusStruct, 0, sizeof(scStatusStruct));
01606     scStatusStruct.hCard = hCard;
01607 
01608     /* those sizes need to be initialised */
01609     scStatusStruct.pcchReaderLen = sizeof(scStatusStruct.mszReaderNames);
01610     scStatusStruct.pcbAtrLen = sizeof(scStatusStruct.pbAtr);
01611 
01612     rv = WrapSHMWrite(SCARD_STATUS, psContextMap[dwContextIndex].dwClientID,
01613         sizeof(scStatusStruct),
01614         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scStatusStruct);
01615 
01616     if (rv == -1)
01617     {
01618         rv = SCARD_E_NO_SERVICE;
01619         goto end;
01620     }
01621 
01622     /*
01623      * Read a message from the server
01624      */
01625     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01626         PCSCLITE_CLIENT_ATTEMPTS);
01627 
01628     memcpy(&scStatusStruct, &msgStruct.data, sizeof(scStatusStruct));
01629 
01630     if (rv == -1)
01631     {
01632         rv = SCARD_F_COMM_ERROR;
01633         goto end;
01634     }
01635 
01636     rv = scStatusStruct.rv;
01637     if (rv != SCARD_S_SUCCESS && rv != SCARD_E_INSUFFICIENT_BUFFER)
01638     {
01639         /*
01640          * An event must have occurred
01641          */
01642         goto end;
01643     }
01644 
01645     /*
01646      * Now continue with the client side SCardStatus
01647      */
01648 
01649     *pcchReaderLen = strlen(psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName) + 1;
01650     *pcbAtrLen = (readerStates[i])->cardAtrLength;
01651 
01652     if (pdwState)
01653         *pdwState = (readerStates[i])->readerState;
01654 
01655     if (pdwProtocol)
01656         *pdwProtocol = (readerStates[i])->cardProtocol;
01657 
01658     if (SCARD_AUTOALLOCATE == dwReaderLen)
01659     {
01660         dwReaderLen = *pcchReaderLen;
01661         bufReader = malloc(dwReaderLen);
01662         if (NULL == bufReader)
01663         {
01664             rv = SCARD_E_NO_MEMORY;
01665             goto end;
01666         }
01667         if (NULL == mszReaderName)
01668         {
01669             rv = SCARD_E_INVALID_PARAMETER;
01670             goto end;
01671         }
01672         *(char **)mszReaderName = bufReader;
01673     }
01674     else
01675         bufReader = mszReaderName;
01676 
01677     /* return SCARD_E_INSUFFICIENT_BUFFER only if buffer pointer is non NULL */
01678     if (bufReader)
01679     {
01680         if (*pcchReaderLen > dwReaderLen)
01681             rv = SCARD_E_INSUFFICIENT_BUFFER;
01682 
01683         strncpy(bufReader,
01684             psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName,
01685             dwReaderLen);
01686     }
01687 
01688     if (SCARD_AUTOALLOCATE == dwAtrLen)
01689     {
01690         dwAtrLen = *pcbAtrLen;
01691         bufAtr = malloc(dwAtrLen);
01692         if (NULL == bufAtr)
01693         {
01694             rv = SCARD_E_NO_MEMORY;
01695             goto end;
01696         }
01697         if (NULL == pbAtr)
01698         {
01699             rv = SCARD_E_INVALID_PARAMETER;
01700             goto end;
01701         }
01702         *(LPBYTE *)pbAtr = bufAtr;
01703     }
01704     else
01705         bufAtr = pbAtr;
01706 
01707     if (bufAtr)
01708     {
01709         if (*pcbAtrLen > dwAtrLen)
01710             rv = SCARD_E_INSUFFICIENT_BUFFER;
01711 
01712         memcpy(bufAtr, (readerStates[i])->cardAtr, min(*pcbAtrLen, dwAtrLen));
01713     }
01714 
01715 end:
01716     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01717 
01718     PROFILE_END(rv)
01719 
01720     return rv;
01721 }
01722 
01723 static long WaitForPcscdEvent(SCARDCONTEXT hContext, long dwTime)
01724 {
01725     char filename[FILENAME_MAX];
01726     char buf[1];
01727     int fd, r;
01728     struct timeval tv, *ptv = NULL;
01729     struct timeval before, after;
01730     fd_set read_fd;
01731 
01732     if (INFINITE != dwTime)
01733     {
01734         if (dwTime < 0)
01735             return 0;
01736         gettimeofday(&before, NULL);
01737         tv.tv_sec = dwTime/1000;
01738         tv.tv_usec = dwTime*1000 - tv.tv_sec*1000000;
01739         ptv = &tv;
01740     }
01741 
01742     (void)snprintf(filename, sizeof(filename), "%s/event.%d.%ld",
01743         PCSCLITE_EVENTS_DIR, SYS_GetPID(), hContext);
01744     r = mkfifo(filename, 0644);
01745     if (-1 == r)
01746     {
01747         Log2(PCSC_LOG_CRITICAL, "Can't create event fifo: %s", strerror(errno));
01748         goto exit;
01749     }
01750 
01751     fd = SYS_OpenFile(filename, O_RDONLY | O_NONBLOCK, 0);
01752 
01753     /* the file may have been removed between the mkfifo() and open() */
01754     if (-1 != fd)
01755     {
01756         FD_ZERO(&read_fd);
01757         FD_SET(fd, &read_fd);
01758         
01759         (void)select(fd+1, &read_fd, NULL, NULL, ptv);
01760 
01761         (void)SYS_ReadFile(fd, buf, 1);
01762         (void)SYS_CloseFile(fd);
01763     }
01764 
01765     (void)SYS_RemoveFile(filename);
01766 
01767     if (INFINITE != dwTime)
01768     {
01769         long int diff;
01770 
01771         gettimeofday(&after, NULL);
01772         diff = time_sub(&after, &before);
01773         dwTime -= diff/1000;
01774     }
01775 
01776 exit:
01777     return dwTime;
01778 }
01779 
01871 LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout,
01872     LPSCARD_READERSTATE_A rgReaderStates, DWORD cReaders)
01873 {
01874     PSCARD_READERSTATE_A currReader;
01875     PREADER_STATE rContext;
01876     long dwTime = dwTimeout;
01877     DWORD dwState;
01878     DWORD dwBreakFlag = 0;
01879     int j;
01880     LONG dwContextIndex;
01881     int currentReaderCount = 0;
01882     LONG rv = SCARD_S_SUCCESS;
01883 
01884     PROFILE_START
01885 
01886     if ((rgReaderStates == NULL && cReaders > 0)
01887         || (cReaders > PCSCLITE_MAX_READERS_CONTEXTS))
01888         return SCARD_E_INVALID_PARAMETER;
01889 
01890     /* Check the integrity of the reader states structures */
01891     for (j = 0; j < cReaders; j++)
01892     {
01893         if (rgReaderStates[j].szReader == NULL)
01894             return SCARD_E_INVALID_VALUE;
01895     }
01896 
01897     /* return if all readers are SCARD_STATE_IGNORE */
01898     if (cReaders > 0)
01899     {
01900         int nbNonIgnoredReaders = cReaders;
01901 
01902         for (j=0; j<cReaders; j++)
01903             if (rgReaderStates[j].dwCurrentState & SCARD_STATE_IGNORE)
01904                 nbNonIgnoredReaders--;
01905 
01906         if (0 == nbNonIgnoredReaders)
01907             return SCARD_S_SUCCESS;
01908     }
01909 
01910     rv = SCardCheckDaemonAvailability();
01911     if (rv != SCARD_S_SUCCESS)
01912         return rv;
01913 
01914     /*
01915      * Make sure this context has been opened
01916      */
01917     dwContextIndex = SCardGetContextIndice(hContext);
01918     if (dwContextIndex == -1)
01919         return SCARD_E_INVALID_HANDLE;
01920 
01921     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01922 
01923     /* check the context is still opened */
01924     dwContextIndex = SCardGetContextIndice(hContext);
01925     if (dwContextIndex == -1)
01926         /* the context is now invalid
01927          * -> another thread may have called SCardReleaseContext
01928          * -> so the mMutex has been unlocked */
01929         return SCARD_E_INVALID_HANDLE;
01930 
01931     /*
01932      * Application is waiting for a reader - return the first available
01933      * reader
01934      * This is DEPRECATED. Use the special reader name \\?PnP?\Notification
01935      * instead
01936      */
01937     if (cReaders == 0)
01938     {
01939         while (1)
01940         {
01941             int i;
01942 
01943             rv = SCardCheckDaemonAvailability();
01944             if (rv != SCARD_S_SUCCESS)
01945                 goto end;
01946 
01947             for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01948             {
01949                 if ((readerStates[i])->readerID != 0)
01950                 {
01951                     /* Reader was found */
01952                     rv = SCARD_S_SUCCESS;
01953                     goto end;
01954                 }
01955             }
01956 
01957             if (dwTimeout == 0)
01958             {
01959                 /* return immediately - no reader available */
01960                 rv = SCARD_E_READER_UNAVAILABLE;
01961                 goto end;
01962             }
01963 
01964             dwTime = WaitForPcscdEvent(hContext, dwTime);
01965             if (dwTimeout != INFINITE)
01966             {
01967                 if (dwTime <= 0)
01968                 {
01969                     rv = SCARD_E_TIMEOUT;
01970                     goto end;
01971                 }
01972             }
01973         }
01974     }
01975 
01976     /*
01977      * End of search for readers
01978      */
01979 
01980     /* Clear the event state for all readers */
01981     for (j = 0; j < cReaders; j++)
01982         rgReaderStates[j].dwEventState = 0;
01983 
01984     /* Now is where we start our event checking loop */
01985     Log1(PCSC_LOG_DEBUG, "Event Loop Start");
01986 
01987     psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_BLOCKING;
01988 
01989     /* Get the initial reader count on the system */
01990     for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
01991         if ((readerStates[j])->readerID != 0)
01992             currentReaderCount++;
01993 
01994     j = 0;
01995     do
01996     {
01997         rv = SCardCheckDaemonAvailability();
01998         if (rv != SCARD_S_SUCCESS)
01999         {
02000             if (psContextMap[dwContextIndex].mMutex)
02001                 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02002 
02003             PROFILE_END(rv)
02004 
02005             return rv;
02006         }
02007 
02008         currReader = &rgReaderStates[j];
02009 
02010         /* Ignore for IGNORED readers */
02011         if (!(currReader->dwCurrentState & SCARD_STATE_IGNORE))
02012         {
02013             LPSTR lpcReaderName;
02014             int i;
02015 
02016       /************ Looks for correct readernames *********************/
02017 
02018             lpcReaderName = (char *) currReader->szReader;
02019 
02020             for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02021             {
02022                 if (strcmp(lpcReaderName, (readerStates[i])->readerName) == 0)
02023                     break;
02024             }
02025 
02026             /* The requested reader name is not recognized */
02027             if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02028             {
02029                 /* PnP special reader? */
02030                 if (strcasecmp(lpcReaderName, "\\\\?PnP?\\Notification") == 0)
02031                 {
02032                     int k, newReaderCount = 0;
02033 
02034                     for (k=0; k < PCSCLITE_MAX_READERS_CONTEXTS; k++)
02035                         if ((readerStates[k])->readerID != 0)
02036                             newReaderCount++;
02037 
02038                     if (newReaderCount != currentReaderCount)
02039                     {
02040                         Log1(PCSC_LOG_INFO, "Reader list changed");
02041                         currentReaderCount = newReaderCount;
02042 
02043                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02044                         dwBreakFlag = 1;
02045                     }
02046                 }
02047                 else
02048                 {
02049                     currReader->dwEventState = SCARD_STATE_UNKNOWN | SCARD_STATE_UNAVAILABLE;
02050                     if (!(currReader->dwCurrentState & SCARD_STATE_UNKNOWN))
02051                     {
02052                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02053                         /*
02054                          * Spec says use SCARD_STATE_IGNORE but a removed USB
02055                          * reader with eventState fed into currentState will
02056                          * be ignored forever
02057                          */
02058                         dwBreakFlag = 1;
02059                     }
02060                 }
02061             }
02062             else
02063             {
02064                 /* The reader has come back after being away */
02065                 if (currReader->dwCurrentState & SCARD_STATE_UNKNOWN)
02066                 {
02067                     currReader->dwEventState |= SCARD_STATE_CHANGED;
02068                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
02069                     Log0(PCSC_LOG_DEBUG);
02070                     dwBreakFlag = 1;
02071                 }
02072 
02073     /*****************************************************************/
02074 
02075                 /* Set the reader status structure */
02076                 rContext = readerStates[i];
02077 
02078                 /* Now we check all the Reader States */
02079                 dwState = rContext->readerState;
02080 
02081                 /* only if current state has an non null event counter */
02082                 if (currReader->dwCurrentState & 0xFFFF0000)
02083                 {
02084                     int currentCounter, stateCounter;
02085 
02086                     stateCounter = (dwState >> 16) & 0xFFFF;
02087                     currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF;
02088 
02089                     /* has the event counter changed since the last call? */
02090                     if (stateCounter != currentCounter)
02091                     {
02092                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02093                         Log0(PCSC_LOG_DEBUG);
02094                         dwBreakFlag = 1;
02095                     }
02096 
02097                     /* add an event counter in the upper word of dwEventState */
02098                     currReader->dwEventState =
02099                         ((currReader->dwEventState & 0xffff )
02100                         | (stateCounter << 16));
02101                 }
02102 
02103     /*********** Check if the reader is in the correct state ********/
02104                 if (dwState & SCARD_UNKNOWN)
02105                 {
02106                     /* reader is in bad state */
02107                     currReader->dwEventState = SCARD_STATE_UNAVAILABLE;
02108                     if (!(currReader->dwCurrentState & SCARD_STATE_UNAVAILABLE))
02109                     {
02110                         /* App thinks reader is in good state and it is not */
02111                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02112                         Log0(PCSC_LOG_DEBUG);
02113                         dwBreakFlag = 1;
02114                     }
02115                 }
02116                 else
02117                 {
02118                     /* App thinks reader in bad state but it is not */
02119                     if (currReader-> dwCurrentState & SCARD_STATE_UNAVAILABLE)
02120                     {
02121                         currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
02122                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02123                         Log0(PCSC_LOG_DEBUG);
02124                         dwBreakFlag = 1;
02125                     }
02126                 }
02127 
02128     /********** Check for card presence in the reader **************/
02129 
02130                 if (dwState & SCARD_PRESENT)
02131                 {
02132                     /* card present but not yet powered up */
02133                     if (0 == rContext->cardAtrLength)
02134                         /* Allow the status thread to convey information */
02135                         (void)SYS_USleep(PCSCLITE_STATUS_POLL_RATE + 10);
02136 
02137                     currReader->cbAtr = rContext->cardAtrLength;
02138                     memcpy(currReader->rgbAtr, rContext->cardAtr,
02139                         currReader->cbAtr);
02140                 }
02141                 else
02142                     currReader->cbAtr = 0;
02143 
02144                 /* Card is now absent */
02145                 if (dwState & SCARD_ABSENT)
02146                 {
02147                     currReader->dwEventState |= SCARD_STATE_EMPTY;
02148                     currReader->dwEventState &= ~SCARD_STATE_PRESENT;
02149                     currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
02150                     currReader->dwEventState &= ~SCARD_STATE_IGNORE;
02151                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
02152                     currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
02153                     currReader->dwEventState &= ~SCARD_STATE_ATRMATCH;
02154                     currReader->dwEventState &= ~SCARD_STATE_MUTE;
02155                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
02156 
02157                     /* After present the rest are assumed */
02158                     if (currReader->dwCurrentState & SCARD_STATE_PRESENT)
02159                     {
02160                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02161                         Log0(PCSC_LOG_DEBUG);
02162                         dwBreakFlag = 1;
02163                     }
02164                 }
02165                 /* Card is now present */
02166                 else if (dwState & SCARD_PRESENT)
02167                 {
02168                     currReader->dwEventState |= SCARD_STATE_PRESENT;
02169                     currReader->dwEventState &= ~SCARD_STATE_EMPTY;
02170                     currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
02171                     currReader->dwEventState &= ~SCARD_STATE_IGNORE;
02172                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
02173                     currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
02174                     currReader->dwEventState &= ~SCARD_STATE_MUTE;
02175 
02176                     if (currReader->dwCurrentState & SCARD_STATE_EMPTY)
02177                     {
02178                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02179                         Log0(PCSC_LOG_DEBUG);
02180                         dwBreakFlag = 1;
02181                     }
02182 
02183                     if (dwState & SCARD_SWALLOWED)
02184                     {
02185                         currReader->dwEventState |= SCARD_STATE_MUTE;
02186                         if (!(currReader->dwCurrentState & SCARD_STATE_MUTE))
02187                         {
02188                             currReader->dwEventState |= SCARD_STATE_CHANGED;
02189                             Log0(PCSC_LOG_DEBUG);
02190                             dwBreakFlag = 1;
02191                         }
02192                     }
02193                     else
02194                     {
02195                         /* App thinks card is mute but it is not */
02196                         if (currReader->dwCurrentState & SCARD_STATE_MUTE)
02197                         {
02198                             currReader->dwEventState |= SCARD_STATE_CHANGED;
02199                             Log0(PCSC_LOG_DEBUG);
02200                             dwBreakFlag = 1;
02201                         }
02202                     }
02203                 }
02204 
02205                 /* Now figure out sharing modes */
02206                 if (rContext->readerSharing == -1)
02207                 {
02208                     currReader->dwEventState |= SCARD_STATE_EXCLUSIVE;
02209                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
02210                     if (currReader->dwCurrentState & SCARD_STATE_INUSE)
02211                     {
02212                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02213                         Log0(PCSC_LOG_DEBUG);
02214                         dwBreakFlag = 1;
02215                     }
02216                 }
02217                 else if (rContext->readerSharing >= 1)
02218                 {
02219                     /* A card must be inserted for it to be INUSE */
02220                     if (dwState & SCARD_PRESENT)
02221                     {
02222                         currReader->dwEventState |= SCARD_STATE_INUSE;
02223                         currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
02224                         if (currReader-> dwCurrentState & SCARD_STATE_EXCLUSIVE)
02225                         {
02226                             currReader->dwEventState |= SCARD_STATE_CHANGED;
02227                             Log0(PCSC_LOG_DEBUG);
02228                             dwBreakFlag = 1;
02229                         }
02230                     }
02231                 }
02232                 else if (rContext->readerSharing == 0)
02233                 {
02234                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
02235                     currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
02236 
02237                     if (currReader->dwCurrentState & SCARD_STATE_INUSE)
02238                     {
02239                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02240                         Log0(PCSC_LOG_DEBUG);
02241                         dwBreakFlag = 1;
02242                     }
02243                     else if (currReader-> dwCurrentState
02244                         & SCARD_STATE_EXCLUSIVE)
02245                     {
02246                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02247                         Log0(PCSC_LOG_DEBUG);
02248                         dwBreakFlag = 1;
02249                     }
02250                 }
02251 
02252                 if (currReader->dwCurrentState == SCARD_STATE_UNAWARE)
02253                 {
02254                     /*
02255                      * Break out of the while .. loop and return status
02256                      * once all the status's for all readers is met
02257                      */
02258                     currReader->dwEventState |= SCARD_STATE_CHANGED;
02259                     Log0(PCSC_LOG_DEBUG);
02260                     dwBreakFlag = 1;
02261                 }
02262             }   /* End of SCARD_STATE_UNKNOWN */
02263         }   /* End of SCARD_STATE_IGNORE */
02264 
02265         /* Counter and resetter */
02266         j++;
02267         if (j == cReaders)
02268         {
02269             /* go back to the first reader */
02270             j = 0;
02271 
02272             /* Declare all the break conditions */
02273 
02274             /* Break if UNAWARE is set and all readers have been checked */
02275             if (dwBreakFlag == 1)
02276                 break;
02277 
02278             if (BLOCK_STATUS_RESUME
02279                 == psContextMap[dwContextIndex].contextBlockStatus)
02280                 break;
02281 
02282             /* Only sleep once for each cycle of reader checks. */
02283             dwTime = WaitForPcscdEvent(hContext, dwTime);
02284 
02285             if (dwTimeout != INFINITE)
02286             {
02287                 /* If time is greater than timeout and all readers have been
02288                  * checked
02289                  */
02290                 if (dwTime <= 0)
02291                 {
02292                     rv = SCARD_E_TIMEOUT;
02293                     goto end;
02294                 }
02295             }
02296         }
02297     }
02298     while (1);
02299 
02300     if (psContextMap[dwContextIndex].contextBlockStatus == BLOCK_STATUS_RESUME)
02301         rv = SCARD_E_CANCELLED;
02302 
02303 end:
02304     Log1(PCSC_LOG_DEBUG, "Event Loop End");
02305 
02306     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02307 
02308     PROFILE_END(rv)
02309 
02310     return rv;
02311 }
02312 
02364 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
02365     DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
02366     LPDWORD lpBytesReturned)
02367 {
02368     LONG rv;
02369     control_struct scControlStruct;
02370     sharedSegmentMsg msgStruct;
02371     int i;
02372     DWORD dwContextIndex, dwChannelIndex;
02373 
02374     PROFILE_START
02375 
02376     /* 0 bytes received by default */
02377     if (NULL != lpBytesReturned)
02378         *lpBytesReturned = 0;
02379 
02380     rv = SCardCheckDaemonAvailability();
02381     if (rv != SCARD_S_SUCCESS)
02382         return rv;
02383 
02384     /*
02385      * Make sure this handle has been opened
02386      */
02387     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02388     if (rv == -1)
02389         return SCARD_E_INVALID_HANDLE;
02390 
02391     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02392 
02393     /* check the handle is still valid */
02394     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02395     if (rv == -1)
02396         /* the handle is now invalid
02397          * -> another thread may have called SCardReleaseContext
02398          * -> so the mMutex has been unlocked */
02399         return SCARD_E_INVALID_HANDLE;
02400 
02401     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02402     {
02403         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02404 
02405         /* by default r == NULL */
02406         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02407             break;
02408     }
02409 
02410     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02411     {
02412         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02413         return SCARD_E_READER_UNAVAILABLE;
02414     }
02415 
02416     if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
02417         || (cbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
02418     {
02419         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02420         return SCARD_E_INSUFFICIENT_BUFFER;
02421     }
02422 
02423     if ((cbSendLength > MAX_BUFFER_SIZE) || (cbRecvLength > MAX_BUFFER_SIZE))
02424     {
02425         /* extended control */
02426         unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED];
02427         control_struct_extended *scControlStructExtended = (control_struct_extended *)buffer;
02428         sharedSegmentMsg *pmsgStruct = (psharedSegmentMsg)buffer;
02429 
02430         scControlStructExtended->hCard = hCard;
02431         scControlStructExtended->dwControlCode = dwControlCode;
02432         scControlStructExtended->cbSendLength = cbSendLength;
02433         scControlStructExtended->cbRecvLength = cbRecvLength;
02434         scControlStructExtended->pdwBytesReturned = 0;
02435         scControlStructExtended->rv = SCARD_S_SUCCESS;
02436         /* The size of data to send is the size of
02437          * struct control_struct_extended WITHOUT the data[] field
02438          * plus the effective data[] size
02439          */
02440         scControlStructExtended->size = sizeof(*scControlStructExtended)
02441             - (sizeof(control_struct_extended) - offsetof(control_struct_extended, data))
02442             + cbSendLength;
02443         memcpy(scControlStructExtended->data, pbSendBuffer, cbSendLength);
02444 
02445         rv = WrapSHMWrite(SCARD_CONTROL_EXTENDED,
02446             psContextMap[dwContextIndex].dwClientID,
02447             scControlStructExtended->size,
02448             PCSCLITE_CLIENT_ATTEMPTS, buffer);
02449 
02450         if (rv == -1)
02451         {
02452             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02453             return SCARD_E_NO_SERVICE;
02454         }
02455 
02456         /*
02457          * Read a message from the server
02458          */
02459         /* read the first block */
02460         rv = SHMMessageReceive(buffer, sizeof(sharedSegmentMsg),
02461             psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
02462         if (rv == -1)
02463         {
02464             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02465             return SCARD_F_COMM_ERROR;
02466         }
02467 
02468         /* we receive a sharedSegmentMsg and not a control_struct_extended */
02469         scControlStructExtended = (control_struct_extended *)&(pmsgStruct -> data);
02470 
02471         /* a second block is present */
02472         if (scControlStructExtended->size > PCSCLITE_MAX_MESSAGE_SIZE)
02473         {
02474             rv = SHMMessageReceive(buffer + sizeof(sharedSegmentMsg),
02475                 scControlStructExtended->size-PCSCLITE_MAX_MESSAGE_SIZE,
02476                 psContextMap[dwContextIndex].dwClientID,
02477                 PCSCLITE_CLIENT_ATTEMPTS);
02478             if (rv == -1)
02479             {
02480                 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02481                 return SCARD_F_COMM_ERROR;
02482             }
02483         }
02484 
02485         if (scControlStructExtended -> rv == SCARD_S_SUCCESS)
02486         {
02487             /*
02488              * Copy and zero it so any secret information is not leaked
02489              */
02490             memcpy(pbRecvBuffer, scControlStructExtended -> data,
02491                 scControlStructExtended -> pdwBytesReturned);
02492             memset(scControlStructExtended -> data, 0x00,
02493                 scControlStructExtended -> pdwBytesReturned);
02494         }
02495 
02496         if (NULL != lpBytesReturned)
02497             *lpBytesReturned = scControlStructExtended -> pdwBytesReturned;
02498 
02499         rv = scControlStructExtended -> rv;
02500     }
02501     else
02502     {
02503         scControlStruct.hCard = hCard;
02504         scControlStruct.dwControlCode = dwControlCode;
02505         scControlStruct.cbSendLength = cbSendLength;
02506         scControlStruct.cbRecvLength = cbRecvLength;
02507         memcpy(scControlStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
02508 
02509         rv = WrapSHMWrite(SCARD_CONTROL,
02510             psContextMap[dwContextIndex].dwClientID,
02511             sizeof(scControlStruct), PCSCLITE_CLIENT_ATTEMPTS, &scControlStruct);
02512 
02513         if (rv == -1)
02514         {
02515             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02516             return SCARD_E_NO_SERVICE;
02517         }
02518 
02519         /*
02520          * Read a message from the server
02521          */
02522         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
02523             PCSCLITE_CLIENT_ATTEMPTS);
02524 
02525         if (rv == -1)
02526         {
02527             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02528             return SCARD_F_COMM_ERROR;
02529         }
02530 
02531         memcpy(&scControlStruct, &msgStruct.data, sizeof(scControlStruct));
02532 
02533         if (NULL != lpBytesReturned)
02534             *lpBytesReturned = scControlStruct.dwBytesReturned;
02535 
02536         if (scControlStruct.rv == SCARD_S_SUCCESS)
02537         {
02538             /*
02539              * Copy and zero it so any secret information is not leaked
02540              */
02541             memcpy(pbRecvBuffer, scControlStruct.pbRecvBuffer,
02542                 scControlStruct.cbRecvLength);
02543             memset(scControlStruct.pbRecvBuffer, 0x00,
02544                 sizeof(scControlStruct.pbRecvBuffer));
02545         }
02546 
02547         rv = scControlStruct.rv;
02548     }
02549 
02550     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02551 
02552     PROFILE_END(rv)
02553 
02554     return rv;
02555 }
02556 
02657 LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
02658     LPDWORD pcbAttrLen)
02659 {
02660     LONG ret;
02661     unsigned char *buf = NULL;
02662 
02663     PROFILE_START
02664 
02665     if (NULL == pcbAttrLen)
02666         return SCARD_E_INVALID_PARAMETER;
02667 
02668     if (SCARD_AUTOALLOCATE == *pcbAttrLen)
02669     {
02670         if (NULL == pbAttr)
02671             return SCARD_E_INVALID_PARAMETER;
02672 
02673         *pcbAttrLen = MAX_BUFFER_SIZE;
02674         buf = malloc(*pcbAttrLen);
02675         if (NULL == buf)
02676             return SCARD_E_NO_MEMORY;
02677 
02678         *(unsigned char **)pbAttr = buf;
02679     }
02680     else
02681     {
02682         buf = pbAttr;
02683 
02684         /* if only get the length */
02685         if (NULL == pbAttr)
02686             /* use a reasonable size */
02687             *pcbAttrLen = MAX_BUFFER_SIZE;
02688     }
02689 
02690     ret = SCardGetSetAttrib(hCard, SCARD_GET_ATTRIB, dwAttrId, buf,
02691         pcbAttrLen);
02692 
02693     PROFILE_END(ret)
02694 
02695     return ret;
02696 }
02697 
02731 LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
02732     DWORD cbAttrLen)
02733 {
02734     LONG ret;
02735 
02736     PROFILE_START
02737 
02738     if (NULL == pbAttr || 0 == cbAttrLen)
02739         return SCARD_E_INVALID_PARAMETER;
02740 
02741     ret = SCardGetSetAttrib(hCard, SCARD_SET_ATTRIB, dwAttrId, (LPBYTE)pbAttr,
02742         &cbAttrLen);
02743 
02744     PROFILE_END(ret)
02745 
02746     return ret;
02747 }
02748 
02749 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
02750     LPBYTE pbAttr, LPDWORD pcbAttrLen)
02751 {
02752     LONG rv;
02753     getset_struct scGetSetStruct;
02754     sharedSegmentMsg msgStruct;
02755     int i;
02756     DWORD dwContextIndex, dwChannelIndex;
02757 
02758     rv = SCardCheckDaemonAvailability();
02759     if (rv != SCARD_S_SUCCESS)
02760         return rv;
02761 
02762     /*
02763      * Make sure this handle has been opened
02764      */
02765     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02766     if (rv == -1)
02767         return SCARD_E_INVALID_HANDLE;
02768 
02769     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02770 
02771     /* check the handle is still valid */
02772     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02773     if (rv == -1)
02774         /* the handle is now invalid
02775          * -> another thread may have called SCardReleaseContext
02776          * -> so the mMutex has been unlocked */
02777         return SCARD_E_INVALID_HANDLE;
02778 
02779     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02780     {
02781         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02782 
02783         /* by default r == NULL */
02784         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02785             break;
02786     }
02787 
02788     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02789     {
02790         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02791         return SCARD_E_READER_UNAVAILABLE;
02792     }
02793 
02794     if (*pcbAttrLen > MAX_BUFFER_SIZE)
02795     {
02796         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02797         return SCARD_E_INSUFFICIENT_BUFFER;
02798     }
02799 
02800     scGetSetStruct.hCard = hCard;
02801     scGetSetStruct.dwAttrId = dwAttrId;
02802     scGetSetStruct.cbAttrLen = *pcbAttrLen;
02803     scGetSetStruct.rv = SCARD_E_NO_SERVICE;
02804     memset(scGetSetStruct.pbAttr, 0, sizeof(scGetSetStruct.pbAttr));
02805     if (SCARD_SET_ATTRIB == command)
02806         memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
02807 
02808     rv = WrapSHMWrite(command,
02809         psContextMap[dwContextIndex].dwClientID, sizeof(scGetSetStruct),
02810         PCSCLITE_CLIENT_ATTEMPTS, &scGetSetStruct);
02811 
02812     if (rv == -1)
02813     {
02814         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02815         return SCARD_E_NO_SERVICE;
02816     }
02817 
02818     /*
02819      * Read a message from the server
02820      */
02821     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
02822         PCSCLITE_CLIENT_ATTEMPTS);
02823 
02824     if (rv == -1)
02825     {
02826         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02827         return SCARD_F_COMM_ERROR;
02828     }
02829 
02830     memcpy(&scGetSetStruct, &msgStruct.data, sizeof(scGetSetStruct));
02831 
02832     if ((SCARD_S_SUCCESS == scGetSetStruct.rv) && (SCARD_GET_ATTRIB == command))
02833     {
02834         /*
02835          * Copy and zero it so any secret information is not leaked
02836          */
02837         if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
02838         {
02839             scGetSetStruct.cbAttrLen = *pcbAttrLen;
02840             scGetSetStruct.rv = SCARD_E_INSUFFICIENT_BUFFER;
02841         }
02842         else
02843             *pcbAttrLen = scGetSetStruct.cbAttrLen;
02844 
02845         if (pbAttr)
02846             memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
02847 
02848         memset(scGetSetStruct.pbAttr, 0x00, sizeof(scGetSetStruct.pbAttr));
02849     }
02850 
02851     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02852 
02853     return scGetSetStruct.rv;
02854 }
02855 
02914 LONG SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci,
02915     LPCBYTE pbSendBuffer, DWORD cbSendLength,
02916     LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer,
02917     LPDWORD pcbRecvLength)
02918 {
02919     LONG rv;
02920     int i;
02921     DWORD dwContextIndex, dwChannelIndex;
02922 
02923     PROFILE_START
02924 
02925     if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
02926             pcbRecvLength == NULL || pioSendPci == NULL)
02927         return SCARD_E_INVALID_PARAMETER;
02928 
02929     rv = SCardCheckDaemonAvailability();
02930     if (rv != SCARD_S_SUCCESS)
02931         return rv;
02932 
02933     /*
02934      * Make sure this handle has been opened
02935      */
02936     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02937     if (rv == -1)
02938     {
02939         *pcbRecvLength = 0;
02940         return SCARD_E_INVALID_HANDLE;
02941     }
02942 
02943     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02944 
02945     /* check the handle is still valid */
02946     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02947     if (rv == -1)
02948         /* the handle is now invalid
02949          * -> another thread may have called SCardReleaseContext
02950          * -> so the mMutex has been unlocked */
02951         return SCARD_E_INVALID_HANDLE;
02952 
02953     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02954     {
02955         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02956 
02957         /* by default r == NULL */
02958         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02959             break;
02960     }
02961 
02962     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02963     {
02964         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02965         return SCARD_E_READER_UNAVAILABLE;
02966     }
02967 
02968     if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
02969         || (*pcbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
02970     {
02971         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02972         return SCARD_E_INSUFFICIENT_BUFFER;
02973     }
02974 
02975     if ((cbSendLength > MAX_BUFFER_SIZE) || (*pcbRecvLength > MAX_BUFFER_SIZE))
02976     {
02977         /* extended APDU */
02978         unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED];
02979         transmit_struct_extended *scTransmitStructExtended = (transmit_struct_extended *)buffer;
02980         sharedSegmentMsg *pmsgStruct = (psharedSegmentMsg)buffer;
02981 
02982         scTransmitStructExtended->hCard = hCard;
02983         scTransmitStructExtended->cbSendLength = cbSendLength;
02984         scTransmitStructExtended->pcbRecvLength = *pcbRecvLength;
02985         /* The size of data to send is the size of
02986          * struct control_struct_extended WITHOUT the data[] field
02987          * plus the effective data[] size
02988          */
02989         scTransmitStructExtended->size = sizeof(*scTransmitStructExtended)
02990             - (sizeof(transmit_struct_extended) - offsetof(transmit_struct_extended, data))
02991             + cbSendLength;
02992         scTransmitStructExtended->pioSendPciProtocol = pioSendPci->dwProtocol;
02993         scTransmitStructExtended->pioSendPciLength = pioSendPci->cbPciLength;
02994         memcpy(scTransmitStructExtended->data, pbSendBuffer, cbSendLength);
02995         scTransmitStructExtended->rv = SCARD_S_SUCCESS;
02996 
02997         if (pioRecvPci)
02998         {
02999             scTransmitStructExtended->pioRecvPciProtocol = pioRecvPci->dwProtocol;
03000             scTransmitStructExtended->pioRecvPciLength = pioRecvPci->cbPciLength;
03001         }
03002         else
03003         {
03004             scTransmitStructExtended->pioRecvPciProtocol = SCARD_PROTOCOL_ANY;
03005             scTransmitStructExtended->pioRecvPciLength = sizeof(SCARD_IO_REQUEST);
03006         }
03007 
03008         rv = WrapSHMWrite(SCARD_TRANSMIT_EXTENDED,
03009             psContextMap[dwContextIndex].dwClientID,
03010             scTransmitStructExtended->size,
03011             PCSCLITE_CLIENT_ATTEMPTS, buffer);
03012 
03013         if (rv == -1)
03014         {
03015             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03016             return SCARD_E_NO_SERVICE;
03017         }
03018 
03019         /*
03020          * Read a message from the server
03021          */
03022         /* read the first block */
03023         rv = SHMMessageReceive(buffer, sizeof(sharedSegmentMsg), psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
03024         if (rv == -1)
03025         {
03026             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03027             return SCARD_F_COMM_ERROR;
03028         }
03029 
03030         /* we receive a sharedSegmentMsg and not a transmit_struct_extended */
03031         scTransmitStructExtended = (transmit_struct_extended *)&(pmsgStruct -> data);
03032 
03033         /* a second block is present */
03034         if (scTransmitStructExtended->size > PCSCLITE_MAX_MESSAGE_SIZE)
03035         {
03036             rv = SHMMessageReceive(buffer + sizeof(sharedSegmentMsg),
03037                 scTransmitStructExtended->size-PCSCLITE_MAX_MESSAGE_SIZE,
03038                 psContextMap[dwContextIndex].dwClientID,
03039                 PCSCLITE_CLIENT_ATTEMPTS);
03040             if (rv == -1)
03041             {
03042                 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03043                 return SCARD_F_COMM_ERROR;
03044             }
03045         }
03046 
03047         if (scTransmitStructExtended -> rv == SCARD_S_SUCCESS)
03048         {
03049             /*
03050              * Copy and zero it so any secret information is not leaked
03051              */
03052             memcpy(pbRecvBuffer, scTransmitStructExtended -> data,
03053                 scTransmitStructExtended -> pcbRecvLength);
03054             memset(scTransmitStructExtended -> data, 0x00,
03055                 scTransmitStructExtended -> pcbRecvLength);
03056 
03057             if (pioRecvPci)
03058             {
03059                 pioRecvPci->dwProtocol = scTransmitStructExtended->pioRecvPciProtocol;
03060                 pioRecvPci->cbPciLength = scTransmitStructExtended->pioRecvPciLength;
03061             }
03062         }
03063 
03064         *pcbRecvLength = scTransmitStructExtended -> pcbRecvLength;
03065         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03066 
03067         rv = scTransmitStructExtended -> rv;
03068     }
03069     else
03070     {
03071         /* short APDU */
03072         transmit_struct scTransmitStruct;
03073         sharedSegmentMsg msgStruct;
03074 
03075         scTransmitStruct.hCard = hCard;
03076         scTransmitStruct.cbSendLength = cbSendLength;
03077         scTransmitStruct.pcbRecvLength = *pcbRecvLength;
03078         scTransmitStruct.pioSendPciProtocol = pioSendPci->dwProtocol;
03079         scTransmitStruct.pioSendPciLength = pioSendPci->cbPciLength;
03080         memcpy(scTransmitStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
03081         memset(scTransmitStruct.pbSendBuffer+cbSendLength, 0, sizeof(scTransmitStruct.pbSendBuffer)-cbSendLength);
03082         memset(scTransmitStruct.pbRecvBuffer, 0, sizeof(scTransmitStruct.pbRecvBuffer));
03083         scTransmitStruct.rv = SCARD_S_SUCCESS;
03084 
03085         if (pioRecvPci)
03086         {
03087             scTransmitStruct.pioRecvPciProtocol = pioRecvPci->dwProtocol;
03088             scTransmitStruct.pioRecvPciLength = pioRecvPci->cbPciLength;
03089         }
03090         else
03091         {
03092             scTransmitStruct.pioRecvPciProtocol = SCARD_PROTOCOL_ANY;
03093             scTransmitStruct.pioRecvPciLength = sizeof(SCARD_IO_REQUEST);
03094         }
03095 
03096         rv = WrapSHMWrite(SCARD_TRANSMIT,
03097             psContextMap[dwContextIndex].dwClientID, sizeof(scTransmitStruct),
03098             PCSCLITE_CLIENT_ATTEMPTS, (void *) &scTransmitStruct);
03099 
03100         if (rv == -1)
03101         {
03102             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03103             return SCARD_E_NO_SERVICE;
03104         }
03105 
03106         /*
03107          * Read a message from the server
03108          */
03109         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
03110             PCSCLITE_CLIENT_ATTEMPTS);
03111 
03112         memcpy(&scTransmitStruct, &msgStruct.data, sizeof(scTransmitStruct));
03113 
03114         if (rv == -1)
03115         {
03116             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03117             return SCARD_F_COMM_ERROR;
03118         }
03119 
03120         /*
03121          * Zero it and free it so any secret information cannot be leaked
03122          */
03123         memset(scTransmitStruct.pbSendBuffer, 0x00, cbSendLength);
03124 
03125         if (scTransmitStruct.rv == SCARD_S_SUCCESS)
03126         {
03127             /*
03128              * Copy and zero it so any secret information is not leaked
03129              */
03130             memcpy(pbRecvBuffer, scTransmitStruct.pbRecvBuffer,
03131                 scTransmitStruct.pcbRecvLength);
03132             memset(scTransmitStruct.pbRecvBuffer, 0x00,
03133                 scTransmitStruct.pcbRecvLength);
03134 
03135             if (pioRecvPci)
03136             {
03137                 pioRecvPci->dwProtocol = scTransmitStruct.pioRecvPciProtocol;
03138                 pioRecvPci->cbPciLength = scTransmitStruct.pioRecvPciLength;
03139             }
03140         }
03141 
03142         *pcbRecvLength = scTransmitStruct.pcbRecvLength;
03143         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03144 
03145         rv = scTransmitStruct.rv;
03146     }
03147 
03148     PROFILE_END(rv)
03149 
03150     return rv;
03151 }
03152 
03201 LONG SCardListReaders(SCARDCONTEXT hContext, /*@unused@*/ LPCSTR mszGroups,
03202     LPSTR mszReaders, LPDWORD pcchReaders)
03203 {
03204     DWORD dwReadersLen;
03205     int i;
03206     LONG dwContextIndex;
03207     LONG rv = SCARD_S_SUCCESS;
03208     char *buf = NULL;
03209 
03210     (void)mszGroups;
03211     PROFILE_START
03212 
03213     /*
03214      * Check for NULL parameters
03215      */
03216     if (pcchReaders == NULL)
03217         return SCARD_E_INVALID_PARAMETER;
03218 
03219     rv = SCardCheckDaemonAvailability();
03220     if (rv != SCARD_S_SUCCESS)
03221         return rv;
03222 
03223     /*
03224      * Make sure this context has been opened
03225      */
03226     dwContextIndex = SCardGetContextIndice(hContext);
03227     if (dwContextIndex == -1)
03228         return SCARD_E_INVALID_HANDLE;
03229 
03230     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
03231 
03232     /* check the context is still opened */
03233     dwContextIndex = SCardGetContextIndice(hContext);
03234     if (dwContextIndex == -1)
03235         /* the context is now invalid
03236          * -> another thread may have called SCardReleaseContext
03237          * -> so the mMutex has been unlocked */
03238         return SCARD_E_INVALID_HANDLE;
03239 
03240     dwReadersLen = 0;
03241     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
03242         if ((readerStates[i])->readerID != 0)
03243             dwReadersLen += strlen((readerStates[i])->readerName) + 1;
03244 
03245     /* for the last NULL byte */
03246     dwReadersLen += 1;
03247 
03248     if (1 == dwReadersLen)
03249     {
03250         rv = SCARD_E_NO_READERS_AVAILABLE;
03251         goto end;
03252     }
03253 
03254     if (SCARD_AUTOALLOCATE == *pcchReaders)
03255     {
03256         buf = malloc(dwReadersLen);
03257         if (NULL == buf)
03258         {
03259             rv = SCARD_E_NO_MEMORY;
03260             goto end;
03261         }
03262         if (NULL == mszReaders)
03263         {
03264             rv = SCARD_E_INVALID_PARAMETER;
03265             goto end;
03266         }
03267         *(char **)mszReaders = buf;
03268     }
03269     else
03270     {
03271         buf = mszReaders;
03272 
03273         /* not enough place to store the reader names */
03274         if ((NULL != mszReaders) && (*pcchReaders < dwReadersLen))
03275         {
03276             rv = SCARD_E_INSUFFICIENT_BUFFER;
03277             goto end;
03278         }
03279     }
03280 
03281     if (mszReaders == NULL) /* text array not allocated */
03282         goto end;
03283 
03284     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
03285     {
03286         if ((readerStates[i])->readerID != 0)
03287         {
03288             /*
03289              * Build the multi-string
03290              */
03291             strcpy(buf, (readerStates[i])->readerName);
03292             buf += strlen((readerStates[i])->readerName)+1;
03293         }
03294     }
03295     *buf = '\0';    /* Add the last null */
03296 
03297 end:
03298     /* set the reader names length */
03299     *pcchReaders = dwReadersLen;
03300 
03301     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03302 
03303     PROFILE_END(rv)
03304 
03305     return rv;
03306 }
03307 
03320 LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
03321 {
03322     LONG rv = SCARD_S_SUCCESS;
03323     LONG dwContextIndex;
03324 
03325     PROFILE_START
03326 
03327     rv = SCardCheckDaemonAvailability();
03328     if (rv != SCARD_S_SUCCESS)
03329         return rv;
03330 
03331     /*
03332      * Make sure this context has been opened
03333      */
03334     dwContextIndex = SCardGetContextIndice(hContext);
03335     if (dwContextIndex == -1)
03336         return SCARD_E_INVALID_HANDLE;
03337 
03338     free((void *)pvMem);
03339 
03340     PROFILE_END(rv)
03341 
03342     return rv;
03343 }
03344 
03394 LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups,
03395     LPDWORD pcchGroups)
03396 {
03397     LONG rv = SCARD_S_SUCCESS;
03398     LONG dwContextIndex;
03399     char *buf = NULL;
03400 
03401     PROFILE_START
03402 
03403     /* Multi-string with two trailing \0 */
03404     const char ReaderGroup[] = "SCard$DefaultReaders\0";
03405     const int dwGroups = sizeof(ReaderGroup);
03406 
03407     rv = SCardCheckDaemonAvailability();
03408     if (rv != SCARD_S_SUCCESS)
03409         return rv;
03410 
03411     /*
03412      * Make sure this context has been opened
03413      */
03414     dwContextIndex = SCardGetContextIndice(hContext);
03415     if (dwContextIndex == -1)
03416         return SCARD_E_INVALID_HANDLE;
03417 
03418     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
03419 
03420     /* check the context is still opened */
03421     dwContextIndex = SCardGetContextIndice(hContext);
03422     if (dwContextIndex == -1)
03423         /* the context is now invalid
03424          * -> another thread may have called SCardReleaseContext
03425          * -> so the mMutex has been unlocked */
03426         return SCARD_E_INVALID_HANDLE;
03427 
03428     if (SCARD_AUTOALLOCATE == *pcchGroups)
03429     {
03430         buf = malloc(dwGroups);
03431         if (NULL == buf)
03432         {
03433             rv = SCARD_E_NO_MEMORY;
03434             goto end;
03435         }
03436         if (NULL == mszGroups)
03437         {
03438             rv = SCARD_E_INVALID_PARAMETER;
03439             goto end;
03440         }
03441         *(char **)mszGroups = buf;
03442     }
03443     else
03444     {
03445         buf = mszGroups;
03446 
03447         if ((NULL != mszGroups) && (*pcchGroups < dwGroups))
03448         {
03449             rv = SCARD_E_INSUFFICIENT_BUFFER;
03450             goto end;
03451         }
03452     }
03453 
03454     if (buf)
03455         memcpy(buf, ReaderGroup, dwGroups);
03456 
03457 end:
03458     *pcchGroups = dwGroups;
03459 
03460     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03461 
03462     PROFILE_END(rv)
03463 
03464     return rv;
03465 }
03466 
03494 LONG SCardCancel(SCARDCONTEXT hContext)
03495 {
03496     LONG dwContextIndex;
03497     LONG rv = SCARD_S_SUCCESS;
03498 
03499     PROFILE_START
03500 
03501     dwContextIndex = SCardGetContextIndice(hContext);
03502     if (dwContextIndex == -1)
03503         return SCARD_E_INVALID_HANDLE;
03504 
03505     /*
03506      * Set the block status for this Context so blocking calls will
03507      * complete
03508      */
03509     psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_RESUME;
03510 
03511     if (StatSynchronizeContext(hContext))
03512         rv = SCARD_F_INTERNAL_ERROR;
03513 
03514     PROFILE_END(rv)
03515 
03516     return rv;
03517 }
03518 
03542 LONG SCardIsValidContext(SCARDCONTEXT hContext)
03543 {
03544     LONG rv;
03545     LONG dwContextIndex;
03546 
03547     PROFILE_START
03548 
03549     rv = SCARD_S_SUCCESS;
03550 
03551     /* Check if the _same_ server is running */
03552     rv = SCardCheckDaemonAvailability();
03553     if (rv != SCARD_S_SUCCESS)
03554         return rv;
03555 
03556     /*
03557      * Make sure this context has been opened
03558      */
03559     dwContextIndex = SCardGetContextIndice(hContext);
03560     if (dwContextIndex == -1)
03561         rv = SCARD_E_INVALID_HANDLE;
03562 
03563     PROFILE_END(rv)
03564 
03565     return rv;
03566 }
03567 
03584 static LONG SCardAddContext(SCARDCONTEXT hContext, DWORD dwClientID)
03585 {
03586     int i;
03587 
03588     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03589     {
03590         if (psContextMap[i].hContext == 0)
03591         {
03592             psContextMap[i].hContext = hContext;
03593             psContextMap[i].dwClientID = dwClientID;
03594             psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;
03595             psContextMap[i].mMutex = malloc(sizeof(PCSCLITE_MUTEX));
03596             (void)SYS_MutexInit(psContextMap[i].mMutex);
03597             return SCARD_S_SUCCESS;
03598         }
03599     }
03600 
03601     return SCARD_E_NO_MEMORY;
03602 }
03603 
03616 static LONG SCardGetContextIndice(SCARDCONTEXT hContext)
03617 {
03618     LONG rv;
03619 
03620     (void)SCardLockThread();
03621     rv = SCardGetContextIndiceTH(hContext);
03622     (void)SCardUnlockThread();
03623 
03624     return rv;
03625 }
03626 
03639 static LONG SCardGetContextIndiceTH(SCARDCONTEXT hContext)
03640 {
03641     int i;
03642 
03643     /*
03644      * Find this context and return its spot in the array
03645      */
03646     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03647     {
03648         if ((hContext == psContextMap[i].hContext) && (hContext != 0))
03649             return i;
03650     }
03651 
03652     return -1;
03653 }
03654 
03664 static LONG SCardRemoveContext(SCARDCONTEXT hContext)
03665 {
03666     LONG  retIndice;
03667 
03668     retIndice = SCardGetContextIndiceTH(hContext);
03669 
03670     if (retIndice == -1)
03671         return SCARD_E_INVALID_HANDLE;
03672     else
03673         return SCardCleanContext(retIndice);
03674 }
03675 
03676 static LONG SCardCleanContext(LONG indice)
03677 {
03678     int i;
03679 
03680     psContextMap[indice].hContext = 0;
03681     (void)SHMClientCloseSession(psContextMap[indice].dwClientID);
03682     psContextMap[indice].dwClientID = 0;
03683     free(psContextMap[indice].mMutex);
03684     psContextMap[indice].mMutex = NULL;
03685     psContextMap[indice].contextBlockStatus = BLOCK_STATUS_RESUME;
03686 
03687     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03688     {
03689         /*
03690          * Reset the \c hCard structs to zero
03691          */
03692         psContextMap[indice].psChannelMap[i].hCard = 0;
03693         free(psContextMap[indice].psChannelMap[i].readerName);
03694         psContextMap[indice].psChannelMap[i].readerName = NULL;
03695     }
03696 
03697     return SCARD_S_SUCCESS;
03698 }
03699 
03700 /*
03701  * Functions for managing hCard values returned from SCardConnect.
03702  */
03703 
03704 static LONG SCardAddHandle(SCARDHANDLE hCard, DWORD dwContextIndex,
03705     LPCSTR readerName)
03706 {
03707     int i;
03708 
03709     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03710     {
03711         if (psContextMap[dwContextIndex].psChannelMap[i].hCard == 0)
03712         {
03713             psContextMap[dwContextIndex].psChannelMap[i].hCard = hCard;
03714             psContextMap[dwContextIndex].psChannelMap[i].readerName = strdup(readerName);
03715             return SCARD_S_SUCCESS;
03716         }
03717     }
03718 
03719     return SCARD_E_NO_MEMORY;
03720 }
03721 
03722 static LONG SCardRemoveHandle(SCARDHANDLE hCard)
03723 {
03724     DWORD dwContextIndice, dwChannelIndice;
03725     LONG rv;
03726 
03727     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndice, &dwChannelIndice);
03728     if (rv == -1)
03729         return SCARD_E_INVALID_HANDLE;
03730     else
03731     {
03732         psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].hCard = 0;
03733         free(psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName);
03734         psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName = NULL;
03735         return SCARD_S_SUCCESS;
03736     }
03737 }
03738 
03739 static LONG SCardGetIndicesFromHandle(SCARDHANDLE hCard,
03740     PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
03741 {
03742     LONG rv;
03743 
03744     if (0 == hCard)
03745         return -1;
03746 
03747     (void)SCardLockThread();
03748     rv = SCardGetIndicesFromHandleTH(hCard, pdwContextIndice, pdwChannelIndice);
03749     (void)SCardUnlockThread();
03750 
03751     return rv;
03752 }
03753 
03754 static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE hCard,
03755     PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
03756 {
03757     int i;
03758 
03759     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03760     {
03761         if (psContextMap[i].hContext != 0)
03762         {
03763             int j;
03764 
03765             for (j = 0; j < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; j++)
03766             {
03767                 if (psContextMap[i].psChannelMap[j].hCard == hCard)
03768                 {
03769                     *pdwContextIndice = i;
03770                     *pdwChannelIndice = j;
03771                     return SCARD_S_SUCCESS;
03772                 }
03773             }
03774 
03775         }
03776     }
03777 
03778     return -1;
03779 }
03780 
03789 LONG SCardCheckDaemonAvailability(void)
03790 {
03791     LONG rv;
03792     struct stat statBuffer;
03793     int need_restart = 0;
03794 
03795     rv = SYS_Stat(PCSCLITE_PUBSHM_FILE, &statBuffer);
03796 
03797     if (rv != 0)
03798     {
03799         Log2(PCSC_LOG_INFO, "PCSC Not Running: " PCSCLITE_PUBSHM_FILE ": %s",
03800             strerror(errno));
03801         return SCARD_E_NO_SERVICE;
03802     }
03803 
03804     /* when the _first_ reader is connected the ctime changes
03805      * I don't know why yet */
03806     if (daemon_ctime && statBuffer.st_ctime > daemon_ctime)
03807     {
03808         /* so we also check the daemon pid to be sure it is a new pcscd */
03809         if (GetDaemonPid() != daemon_pid)
03810         {
03811             Log1(PCSC_LOG_INFO, "PCSC restarted");
03812             need_restart = 1;
03813         }
03814     }
03815 
03816     /* after fork() need to restart */
03817     if (client_pid && client_pid != getpid())
03818     {
03819         Log1(PCSC_LOG_INFO, "Client forked");
03820         need_restart = 1;
03821     }
03822 
03823     if (need_restart)
03824     {
03825         int i;
03826 
03827         /* invalid all handles */
03828         (void)SCardLockThread();
03829 
03830         for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03831             if (psContextMap[i].hContext)
03832                 (void)SCardCleanContext(i);
03833 
03834         (void)SCardUnlockThread();
03835 
03836         /* reset pcscd status */
03837         daemon_ctime = 0;
03838         client_pid = 0;
03839 
03840         /* reset the lib */
03841         SCardUnload();
03842 
03843         return SCARD_E_INVALID_HANDLE;
03844     }
03845 
03846     daemon_ctime = statBuffer.st_ctime;
03847     daemon_pid = GetDaemonPid();
03848     client_pid = getpid();
03849 
03850     return SCARD_S_SUCCESS;
03851 }
03852 
03859 #ifdef __SUNPRO_C
03860 #pragma fini (SCardUnload)
03861 #endif
03862 
03863 void DESTRUCTOR SCardUnload(void)
03864 {
03865     int i;
03866 
03867     if (!isExecuted)
03868         return;
03869 
03870     /* unmap public shared file from memory */
03871     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03872     {
03873         if (readerStates[i] != NULL)
03874         {
03875             SYS_PublicMemoryUnmap(readerStates[i], sizeof(READER_STATE));
03876             readerStates[i] = NULL;
03877         }
03878     }
03879 
03880     (void)SYS_CloseFile(mapAddr);
03881     isExecuted = 0;
03882 }
03883 

Generated on Wed Jul 22 21:08:11 2009 for pcsc-lite by  doxygen 1.5.8