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

Generated on 16 Aug 2014 for pcsc-lite by  doxygen 1.6.1