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 hCard handle is now invalid
00932          * -> another thread may have called SCardReleaseContext
00933          *    so the mMutex has been unlocked (and is now invalid)
00934          * -> another thread may have called SCardDisconnect
00935          *    so the mMutex is STILL locked.
00936          *  since we don't know just unlock the mutext*/
00937         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00938         return SCARD_E_INVALID_HANDLE;
00939     }
00940 
00941     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00942     {
00943         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
00944 
00945         /* by default r == NULL */
00946         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
00947             break;
00948     }
00949 
00950     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
00951     {
00952         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00953         return SCARD_E_READER_UNAVAILABLE;
00954     }
00955 
00956     do
00957     {
00958         scReconnectStruct.hCard = hCard;
00959         scReconnectStruct.dwShareMode = dwShareMode;
00960         scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
00961         scReconnectStruct.dwInitialization = dwInitialization;
00962         scReconnectStruct.pdwActiveProtocol = *pdwActiveProtocol;
00963         scReconnectStruct.rv = SCARD_S_SUCCESS;
00964 
00965         rv = WrapSHMWrite(SCARD_RECONNECT, psContextMap[dwContextIndex].dwClientID,
00966             sizeof(scReconnectStruct),
00967             PCSCLITE_CLIENT_ATTEMPTS, (void *) &scReconnectStruct);
00968 
00969         if (rv == -1)
00970         {
00971             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00972             return SCARD_E_NO_SERVICE;
00973         }
00974 
00975         /*
00976          * Read a message from the server
00977          */
00978         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
00979             PCSCLITE_CLIENT_ATTEMPTS);
00980 
00981         memcpy(&scReconnectStruct, &msgStruct.data, sizeof(scReconnectStruct));
00982 
00983         if (rv == -1)
00984         {
00985             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00986             return SCARD_F_COMM_ERROR;
00987         }
00988     } while (SCARD_E_SHARING_VIOLATION == scReconnectStruct.rv);
00989 
00990     *pdwActiveProtocol = scReconnectStruct.pdwActiveProtocol;
00991 
00992     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00993 
00994     PROFILE_END(scReconnectStruct.rv)
00995 
00996     return scReconnectStruct.rv;
00997 }
00998 
01029 LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
01030 {
01031     LONG rv;
01032     disconnect_struct scDisconnectStruct;
01033     sharedSegmentMsg msgStruct;
01034     DWORD dwContextIndex, dwChannelIndex;
01035 
01036     PROFILE_START
01037 
01038     rv = SCardCheckDaemonAvailability();
01039     if (rv != SCARD_S_SUCCESS)
01040         return rv;
01041 
01042     /*
01043      * Make sure this handle has been opened
01044      */
01045     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01046     if (rv == -1)
01047         return SCARD_E_INVALID_HANDLE;
01048 
01049     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01050 
01051     /* check the handle is still valid */
01052     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01053     if (rv == -1) {
01054         /* the hCard handle is now invalid
01055          * -> another thread may have called SCardReleaseContext
01056          *    so the mMutex has been unlocked (and is now invalid)
01057          * -> another thread may have called SCardDisconnect
01058          *    so the mMutex is STILL locked.
01059          *  since we don't know just unlock the mutext*/
01060         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01061         return SCARD_E_INVALID_HANDLE;
01062     }
01063 
01064     scDisconnectStruct.hCard = hCard;
01065     scDisconnectStruct.dwDisposition = dwDisposition;
01066     scDisconnectStruct.rv = SCARD_S_SUCCESS;
01067 
01068     rv = WrapSHMWrite(SCARD_DISCONNECT, psContextMap[dwContextIndex].dwClientID,
01069         sizeof(scDisconnectStruct),
01070         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scDisconnectStruct);
01071 
01072     if (rv == -1)
01073     {
01074         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01075         return SCARD_E_NO_SERVICE;
01076     }
01077 
01078     /*
01079      * Read a message from the server
01080      */
01081     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01082         PCSCLITE_CLIENT_ATTEMPTS);
01083 
01084     memcpy(&scDisconnectStruct, &msgStruct.data,
01085         sizeof(scDisconnectStruct));
01086 
01087     if (rv == -1)
01088     {
01089         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01090         return SCARD_F_COMM_ERROR;
01091     }
01092 
01093     (void)SCardRemoveHandle(hCard);
01094 
01095     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01096 
01097     PROFILE_END(scDisconnectStruct.rv)
01098 
01099     return scDisconnectStruct.rv;
01100 }
01101 
01137 LONG SCardBeginTransaction(SCARDHANDLE hCard)
01138 {
01139 
01140     LONG rv;
01141     begin_struct scBeginStruct;
01142     int i;
01143     sharedSegmentMsg msgStruct;
01144     DWORD dwContextIndex, dwChannelIndex;
01145 
01146     PROFILE_START
01147 
01148     rv = SCardCheckDaemonAvailability();
01149     if (rv != SCARD_S_SUCCESS)
01150         return rv;
01151 
01152     /*
01153      * Make sure this handle has been opened
01154      */
01155     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01156     if (rv == -1)
01157         return SCARD_E_INVALID_HANDLE;
01158 
01159     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01160 
01161     /* check the handle is still valid */
01162     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01163     if (rv == -1) {
01164         /* the hCard handle is now invalid
01165          * -> another thread may have called SCardReleaseContext
01166          *    so the mMutex has been unlocked (and is now invalid)
01167          * -> another thread may have called SCardDisconnect
01168          *    so the mMutex is STILL locked.
01169          *  since we don't know just unlock the mutext*/
01170         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01171         return SCARD_E_INVALID_HANDLE;
01172     }
01173 
01174     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01175     {
01176         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01177 
01178         /* by default r == NULL */
01179         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01180             break;
01181     }
01182 
01183     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01184     {
01185         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01186         return SCARD_E_READER_UNAVAILABLE;
01187     }
01188 
01189     scBeginStruct.hCard = hCard;
01190     scBeginStruct.rv = SCARD_S_SUCCESS;
01191 
01192     /*
01193      * Query the server every so often until the sharing violation ends
01194      * and then hold the lock for yourself.
01195      */
01196 
01197     do
01198     {
01199         rv = WrapSHMWrite(SCARD_BEGIN_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
01200             sizeof(scBeginStruct),
01201             PCSCLITE_CLIENT_ATTEMPTS, (void *) &scBeginStruct);
01202 
01203         if (rv == -1)
01204         {
01205 
01206             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01207             return SCARD_E_NO_SERVICE;
01208         }
01209 
01210         /*
01211          * Read a message from the server
01212          */
01213         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01214             PCSCLITE_CLIENT_ATTEMPTS);
01215 
01216         memcpy(&scBeginStruct, &msgStruct.data, sizeof(scBeginStruct));
01217 
01218         if (rv == -1)
01219         {
01220 
01221             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01222             return SCARD_F_COMM_ERROR;
01223         }
01224 
01225     }
01226     while (scBeginStruct.rv == SCARD_E_SHARING_VIOLATION);
01227 
01228     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01229 
01230     PROFILE_END(scBeginStruct.rv);
01231 
01232     return scBeginStruct.rv;
01233 }
01234 
01275 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
01276 {
01277     LONG rv;
01278     end_struct scEndStruct;
01279     sharedSegmentMsg msgStruct;
01280     int randnum, i;
01281     DWORD dwContextIndex, dwChannelIndex;
01282 
01283     PROFILE_START
01284 
01285     /*
01286      * Zero out everything
01287      */
01288     randnum = 0;
01289 
01290     rv = SCardCheckDaemonAvailability();
01291     if (rv != SCARD_S_SUCCESS)
01292         return rv;
01293 
01294     /*
01295      * Make sure this handle has been opened
01296      */
01297     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01298     if (rv == -1)
01299         return SCARD_E_INVALID_HANDLE;
01300 
01301     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01302 
01303     /* check the handle is still valid */
01304     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01305     if (rv == -1) {
01306         /* the hCard handle is now invalid
01307          * -> another thread may have called SCardReleaseContext
01308          *    so the mMutex has been unlocked (and is now invalid)
01309          * -> another thread may have called SCardDisconnect
01310          *    so the mMutex is STILL locked.
01311          *  since we don't know just unlock the mutext*/
01312         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01313         return SCARD_E_INVALID_HANDLE;
01314     }
01315 
01316     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01317     {
01318         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01319 
01320         /* by default r == NULL */
01321         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01322             break;
01323     }
01324 
01325     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01326     {
01327         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01328         return SCARD_E_READER_UNAVAILABLE;
01329     }
01330 
01331     scEndStruct.hCard = hCard;
01332     scEndStruct.dwDisposition = dwDisposition;
01333     scEndStruct.rv = SCARD_S_SUCCESS;
01334 
01335     rv = WrapSHMWrite(SCARD_END_TRANSACTION,
01336         psContextMap[dwContextIndex].dwClientID,
01337         sizeof(scEndStruct),
01338         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scEndStruct);
01339 
01340     if (rv == -1)
01341     {
01342         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01343         return SCARD_E_NO_SERVICE;
01344     }
01345 
01346     /*
01347      * Read a message from the server
01348      */
01349     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01350         PCSCLITE_CLIENT_ATTEMPTS);
01351 
01352     memcpy(&scEndStruct, &msgStruct.data, sizeof(scEndStruct));
01353 
01354     if (rv == -1)
01355     {
01356         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01357         return SCARD_F_COMM_ERROR;
01358     }
01359 
01360     /*
01361      * This helps prevent starvation
01362      */
01363     randnum = SYS_RandomInt(1000, 10000);
01364     (void)SYS_USleep(randnum);
01365 
01366     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01367 
01368     PROFILE_END(scEndStruct.rv)
01369 
01370     return scEndStruct.rv;
01371 }
01372 
01379 LONG SCardCancelTransaction(SCARDHANDLE hCard)
01380 {
01381     LONG rv;
01382     cancel_struct scCancelStruct;
01383     sharedSegmentMsg msgStruct;
01384     int i;
01385     DWORD dwContextIndex, dwChannelIndex;
01386 
01387     PROFILE_START
01388 
01389     rv = SCardCheckDaemonAvailability();
01390     if (rv != SCARD_S_SUCCESS)
01391         return rv;
01392 
01393     /*
01394      * Make sure this handle has been opened
01395      */
01396     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01397     if (rv == -1)
01398         return SCARD_E_INVALID_HANDLE;
01399 
01400     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01401 
01402     /* check the handle is still valid */
01403     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01404     if (rv == -1) {
01405         /* the hCard handle is now invalid
01406          * -> another thread may have called SCardReleaseContext
01407          *    so the mMutex has been unlocked (and is now invalid)
01408          * -> another thread may have called SCardDisconnect
01409          *    so the mMutex is STILL locked.
01410          *  since we don't know just unlock the mutext*/
01411         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01412         return SCARD_E_INVALID_HANDLE;
01413     }
01414 
01415     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01416     {
01417         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01418 
01419         /* by default r == NULL */
01420         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01421             break;
01422     }
01423 
01424     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01425     {
01426         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01427         return SCARD_E_READER_UNAVAILABLE;
01428     }
01429 
01430     scCancelStruct.hCard = hCard;
01431 
01432     rv = WrapSHMWrite(SCARD_CANCEL_TRANSACTION,
01433         psContextMap[dwContextIndex].dwClientID,
01434         sizeof(scCancelStruct),
01435         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scCancelStruct);
01436 
01437     if (rv == -1)
01438     {
01439         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01440         return SCARD_E_NO_SERVICE;
01441     }
01442 
01443     /*
01444      * Read a message from the server
01445      */
01446     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01447         PCSCLITE_CLIENT_ATTEMPTS);
01448 
01449     memcpy(&scCancelStruct, &msgStruct.data, sizeof(scCancelStruct));
01450 
01451     if (rv == -1)
01452     {
01453         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01454         return SCARD_F_COMM_ERROR;
01455     }
01456 
01457     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01458 
01459     PROFILE_END(scCancelStruct.rv)
01460 
01461     return scCancelStruct.rv;
01462 }
01463 
01551 LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName,
01552     LPDWORD pcchReaderLen, LPDWORD pdwState,
01553     LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
01554 {
01555     DWORD dwReaderLen, dwAtrLen;
01556     LONG rv;
01557     int i;
01558     status_struct scStatusStruct;
01559     sharedSegmentMsg msgStruct;
01560     DWORD dwContextIndex, dwChannelIndex;
01561     char *r;
01562     char *bufReader = NULL;
01563     LPBYTE bufAtr = NULL;
01564     DWORD dummy;
01565 
01566     PROFILE_START
01567 
01568     /* default output values */
01569     if (pdwState)
01570         *pdwState = 0;
01571 
01572     if (pdwProtocol)
01573         *pdwProtocol = 0;
01574 
01575     /* Check for NULL parameters */ 
01576     if (pcchReaderLen == NULL)
01577         pcchReaderLen = &dummy;
01578     
01579     if (pcbAtrLen == NULL)
01580         pcbAtrLen = &dummy;
01581 
01582     /* length passed from caller */
01583     dwReaderLen = *pcchReaderLen;
01584     dwAtrLen = *pcbAtrLen;
01585 
01586     *pcchReaderLen = 0;
01587     *pcbAtrLen = 0;
01588 
01589     rv = SCardCheckDaemonAvailability();
01590     if (rv != SCARD_S_SUCCESS)
01591         return rv;
01592 
01593     /*
01594      * Make sure this handle has been opened
01595      */
01596     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01597     if (rv == -1)
01598         return SCARD_E_INVALID_HANDLE;
01599 
01600     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01601 
01602     /* check the handle is still valid */
01603     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01604     if (rv == -1) {
01605         /* the hCard handle is now invalid
01606          * -> another thread may have called SCardReleaseContext
01607          *    so the mMutex has been unlocked (and is now invalid)
01608          * -> another thread may have called SCardDisconnect
01609          *    so the mMutex is STILL locked.
01610          *  since we don't know just unlock the mutext*/
01611         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01612         return SCARD_E_INVALID_HANDLE;
01613     }
01614 
01615     r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01616     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01617     {
01618         /* by default r == NULL */
01619         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01620             break;
01621     }
01622 
01623     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01624     {
01625         rv = SCARD_E_READER_UNAVAILABLE;
01626         goto end;
01627     }
01628 
01629     /* initialise the structure */
01630     memset(&scStatusStruct, 0, sizeof(scStatusStruct));
01631     scStatusStruct.hCard = hCard;
01632 
01633     /* those sizes need to be initialised */
01634     scStatusStruct.pcchReaderLen = sizeof(scStatusStruct.mszReaderNames);
01635     scStatusStruct.pcbAtrLen = sizeof(scStatusStruct.pbAtr);
01636 
01637     rv = WrapSHMWrite(SCARD_STATUS, psContextMap[dwContextIndex].dwClientID,
01638         sizeof(scStatusStruct),
01639         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scStatusStruct);
01640 
01641     if (rv == -1)
01642     {
01643         rv = SCARD_E_NO_SERVICE;
01644         goto end;
01645     }
01646 
01647     /*
01648      * Read a message from the server
01649      */
01650     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01651         PCSCLITE_CLIENT_ATTEMPTS);
01652 
01653     memcpy(&scStatusStruct, &msgStruct.data, sizeof(scStatusStruct));
01654 
01655     if (rv == -1)
01656     {
01657         rv = SCARD_F_COMM_ERROR;
01658         goto end;
01659     }
01660 
01661     rv = scStatusStruct.rv;
01662     if (rv != SCARD_S_SUCCESS && rv != SCARD_E_INSUFFICIENT_BUFFER)
01663     {
01664         /*
01665          * An event must have occurred
01666          */
01667         goto end;
01668     }
01669 
01670     /*
01671      * Now continue with the client side SCardStatus
01672      */
01673 
01674     *pcchReaderLen = strlen(psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName) + 1;
01675     *pcbAtrLen = (readerStates[i])->cardAtrLength;
01676 
01677     if (pdwState)
01678         *pdwState = (readerStates[i])->readerState;
01679 
01680     if (pdwProtocol)
01681         *pdwProtocol = (readerStates[i])->cardProtocol;
01682 
01683     if (SCARD_AUTOALLOCATE == dwReaderLen)
01684     {
01685         dwReaderLen = *pcchReaderLen;
01686         bufReader = malloc(dwReaderLen);
01687         if (NULL == bufReader)
01688         {
01689             rv = SCARD_E_NO_MEMORY;
01690             goto end;
01691         }
01692         if (NULL == mszReaderName)
01693         {
01694             rv = SCARD_E_INVALID_PARAMETER;
01695             goto end;
01696         }
01697         *(char **)mszReaderName = bufReader;
01698     }
01699     else
01700         bufReader = mszReaderName;
01701 
01702     /* return SCARD_E_INSUFFICIENT_BUFFER only if buffer pointer is non NULL */
01703     if (bufReader)
01704     {
01705         if (*pcchReaderLen > dwReaderLen)
01706             rv = SCARD_E_INSUFFICIENT_BUFFER;
01707 
01708         strncpy(bufReader,
01709             psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName,
01710             dwReaderLen);
01711     }
01712 
01713     if (SCARD_AUTOALLOCATE == dwAtrLen)
01714     {
01715         dwAtrLen = *pcbAtrLen;
01716         bufAtr = malloc(dwAtrLen);
01717         if (NULL == bufAtr)
01718         {
01719             rv = SCARD_E_NO_MEMORY;
01720             goto end;
01721         }
01722         if (NULL == pbAtr)
01723         {
01724             rv = SCARD_E_INVALID_PARAMETER;
01725             goto end;
01726         }
01727         *(LPBYTE *)pbAtr = bufAtr;
01728     }
01729     else
01730         bufAtr = pbAtr;
01731 
01732     if (bufAtr)
01733     {
01734         if (*pcbAtrLen > dwAtrLen)
01735             rv = SCARD_E_INSUFFICIENT_BUFFER;
01736 
01737         memcpy(bufAtr, (readerStates[i])->cardAtr, min(*pcbAtrLen, dwAtrLen));
01738     }
01739 
01740 end:
01741     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01742 
01743     PROFILE_END(rv)
01744 
01745     return rv;
01746 }
01747 
01748 static long WaitForPcscdEvent(SCARDCONTEXT hContext, long dwTime)
01749 {
01750     char filename[FILENAME_MAX];
01751     char buf[1];
01752     int fd, r;
01753     struct timeval tv, *ptv = NULL;
01754     struct timeval before, after;
01755     fd_set read_fd;
01756 
01757     if (INFINITE != dwTime)
01758     {
01759         if (dwTime < 0)
01760             return 0;
01761         gettimeofday(&before, NULL);
01762         tv.tv_sec = dwTime/1000;
01763         tv.tv_usec = dwTime*1000 - tv.tv_sec*1000000;
01764         ptv = &tv;
01765     }
01766 
01767     (void)snprintf(filename, sizeof(filename), "%s/event.%d.%ld",
01768         PCSCLITE_EVENTS_DIR, SYS_GetPID(), hContext);
01769     r = mkfifo(filename, 0644);
01770     if ((-1 == r) && (errno != EEXIST))
01771     {
01772         Log2(PCSC_LOG_CRITICAL, "Can't create event fifo: %s", strerror(errno));
01773         goto exit;
01774     }
01775 
01776     fd = SYS_OpenFile(filename, O_RDONLY | O_NONBLOCK, 0);
01777 
01778     FD_ZERO(&read_fd);
01779     FD_SET(fd, &read_fd);
01780     
01781     (void)select(fd+1, &read_fd, NULL, NULL, ptv);
01782 
01783     (void)SYS_ReadFile(fd, buf, 1);
01784     (void)SYS_CloseFile(fd);
01785     (void)SYS_RemoveFile(filename);
01786 
01787     if (INFINITE != dwTime)
01788     {
01789         long int diff;
01790 
01791         gettimeofday(&after, NULL);
01792         diff = time_sub(&after, &before);
01793         dwTime -= diff/1000;
01794     }
01795 
01796 exit:
01797     return dwTime;
01798 }
01799 
01891 LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout,
01892     LPSCARD_READERSTATE_A rgReaderStates, DWORD cReaders)
01893 {
01894     PSCARD_READERSTATE_A currReader;
01895     PREADER_STATE rContext;
01896     long dwTime = dwTimeout;
01897     DWORD dwState;
01898     DWORD dwBreakFlag = 0;
01899     int j;
01900     LONG dwContextIndex;
01901     int currentReaderCount = 0;
01902     LONG rv = SCARD_S_SUCCESS;
01903 
01904     PROFILE_START
01905 
01906     if ((rgReaderStates == NULL && cReaders > 0)
01907         || (cReaders > PCSCLITE_MAX_READERS_CONTEXTS))
01908         return SCARD_E_INVALID_PARAMETER;
01909 
01910     /* Check the integrity of the reader states structures */
01911     for (j = 0; j < cReaders; j++)
01912     {
01913         if (rgReaderStates[j].szReader == NULL)
01914             return SCARD_E_INVALID_VALUE;
01915     }
01916 
01917     /* return if all readers are SCARD_STATE_IGNORE */
01918     if (cReaders > 0)
01919     {
01920         int nbNonIgnoredReaders = cReaders;
01921 
01922         for (j=0; j<cReaders; j++)
01923             if (rgReaderStates[j].dwCurrentState & SCARD_STATE_IGNORE)
01924                 nbNonIgnoredReaders--;
01925 
01926         if (0 == nbNonIgnoredReaders)
01927             return SCARD_S_SUCCESS;
01928     }
01929 
01930     rv = SCardCheckDaemonAvailability();
01931     if (rv != SCARD_S_SUCCESS)
01932         return rv;
01933 
01934     /*
01935      * Make sure this context has been opened
01936      */
01937     dwContextIndex = SCardGetContextIndice(hContext);
01938     if (dwContextIndex == -1)
01939         return SCARD_E_INVALID_HANDLE;
01940 
01941     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01942 
01943     /* check the context is still opened */
01944     dwContextIndex = SCardGetContextIndice(hContext);
01945     if (dwContextIndex == -1)
01946         /* the context is now invalid
01947          * -> another thread may have called SCardReleaseContext
01948          * -> so the mMutex has been unlocked */
01949         return SCARD_E_INVALID_HANDLE;
01950 
01951     /*
01952      * Application is waiting for a reader - return the first available
01953      * reader
01954      * This is DEPRECATED. Use the special reader name \\?PnP?\Notification
01955      * instead
01956      */
01957     if (cReaders == 0)
01958     {
01959         while (1)
01960         {
01961             int i;
01962 
01963             rv = SCardCheckDaemonAvailability();
01964             if (rv != SCARD_S_SUCCESS)
01965                 goto end;
01966 
01967             for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01968             {
01969                 if ((readerStates[i])->readerID != 0)
01970                 {
01971                     /* Reader was found */
01972                     rv = SCARD_S_SUCCESS;
01973                     goto end;
01974                 }
01975             }
01976 
01977             if (dwTimeout == 0)
01978             {
01979                 /* return immediately - no reader available */
01980                 rv = SCARD_E_READER_UNAVAILABLE;
01981                 goto end;
01982             }
01983 
01984             dwTime = WaitForPcscdEvent(hContext, dwTime);
01985             if (dwTimeout != INFINITE)
01986             {
01987                 if (dwTime <= 0)
01988                 {
01989                     rv = SCARD_E_TIMEOUT;
01990                     goto end;
01991                 }
01992             }
01993         }
01994     }
01995 
01996     /*
01997      * End of search for readers
01998      */
01999 
02000     /* Clear the event state for all readers */
02001     for (j = 0; j < cReaders; j++)
02002         rgReaderStates[j].dwEventState = 0;
02003 
02004     /* Now is where we start our event checking loop */
02005     Log1(PCSC_LOG_DEBUG, "Event Loop Start");
02006 
02007         if (psContextMap[dwContextIndex].contextBlockStatus == BLOCK_STATUS_CANCEL) {
02008         psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_RESUME;
02009         rv = SCARD_E_CANCELLED;
02010         goto end;
02011     }
02012 
02013     psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_BLOCKING;
02014 
02015     /* Get the initial reader count on the system */
02016     for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
02017         if ((readerStates[j])->readerID != 0)
02018             currentReaderCount++;
02019 
02020     j = 0;
02021     do
02022     {
02023         rv = SCardCheckDaemonAvailability();
02024         if (rv != SCARD_S_SUCCESS)
02025         {
02026             if (psContextMap[dwContextIndex].mMutex)
02027                 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02028 
02029             PROFILE_END(rv)
02030 
02031             return rv;
02032         }
02033 
02034         currReader = &rgReaderStates[j];
02035 
02036         /* Ignore for IGNORED readers */
02037         if (!(currReader->dwCurrentState & SCARD_STATE_IGNORE))
02038         {
02039             LPSTR lpcReaderName;
02040             int i;
02041 
02042       /************ Looks for correct readernames *********************/
02043 
02044             lpcReaderName = (char *) currReader->szReader;
02045 
02046             for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02047             {
02048                 if (strcmp(lpcReaderName, (readerStates[i])->readerName) == 0)
02049                     break;
02050             }
02051 
02052             /* The requested reader name is not recognized */
02053             if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02054             {
02055                 /* PnP special reader? */
02056                 if (strcasecmp(lpcReaderName, "\\\\?PnP?\\Notification") == 0)
02057                 {
02058                     int k, newReaderCount = 0;
02059 
02060                     for (k=0; k < PCSCLITE_MAX_READERS_CONTEXTS; k++)
02061                         if ((readerStates[k])->readerID != 0)
02062                             newReaderCount++;
02063 
02064                     if (newReaderCount != currentReaderCount)
02065                     {
02066                         Log1(PCSC_LOG_INFO, "Reader list changed");
02067                         currentReaderCount = newReaderCount;
02068 
02069                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02070                         dwBreakFlag = 1;
02071                     }
02072                 }
02073                 else
02074                 {
02075                     currReader->dwEventState = SCARD_STATE_UNKNOWN | SCARD_STATE_UNAVAILABLE;
02076                     if (!(currReader->dwCurrentState & SCARD_STATE_UNKNOWN))
02077                     {
02078                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02079                         /*
02080                          * Spec says use SCARD_STATE_IGNORE but a removed USB
02081                          * reader with eventState fed into currentState will
02082                          * be ignored forever
02083                          */
02084                         dwBreakFlag = 1;
02085                     }
02086                 }
02087             }
02088             else
02089             {
02090                 /* The reader has come back after being away */
02091                 if (currReader->dwCurrentState & SCARD_STATE_UNKNOWN)
02092                 {
02093                     currReader->dwEventState |= SCARD_STATE_CHANGED;
02094                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
02095                     dwBreakFlag = 1;
02096                 }
02097 
02098     /*****************************************************************/
02099 
02100                 /* Set the reader status structure */
02101                 rContext = readerStates[i];
02102 
02103                 /* Now we check all the Reader States */
02104                 dwState = rContext->readerState;
02105                 {
02106                     int currentCounter, stateCounter;
02107 
02108                     stateCounter = (dwState >> 16) & 0xFFFF;
02109                     currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF;
02110 
02111                     /* has the event counter changed since the last call? */
02112                     if (stateCounter != currentCounter)
02113                     {
02114                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02115                         dwBreakFlag = 1;
02116                     }
02117 
02118                     /* add an event counter in the upper word of dwEventState */
02119                     currReader->dwEventState =
02120                         ((currReader->dwEventState & 0xffff )
02121                         | (stateCounter << 16));
02122                 }
02123 
02124     /*********** Check if the reader is in the correct state ********/
02125                 if (dwState & SCARD_UNKNOWN)
02126                 {
02127                     /* reader is in bad state */
02128                     currReader->dwEventState = SCARD_STATE_UNAVAILABLE;
02129                     if (!(currReader->dwCurrentState & SCARD_STATE_UNAVAILABLE))
02130                     {
02131                         /* App thinks reader is in good state and it is not */
02132                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02133                         dwBreakFlag = 1;
02134                     }
02135                 }
02136                 else
02137                 {
02138                     /* App thinks reader in bad state but it is not */
02139                     if (currReader-> dwCurrentState & SCARD_STATE_UNAVAILABLE)
02140                     {
02141                         currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
02142                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02143                         dwBreakFlag = 1;
02144                     }
02145                 }
02146 
02147     /********** Check for card presence in the reader **************/
02148 
02149                 if (dwState & SCARD_PRESENT)
02150                 {
02151                     /* card present but not yet powered up */
02152                     if (0 == rContext->cardAtrLength)
02153                         /* Allow the status thread to convey information */
02154                         (void)SYS_USleep(PCSCLITE_STATUS_POLL_RATE + 10);
02155 
02156                     currReader->cbAtr = rContext->cardAtrLength;
02157                     memcpy(currReader->rgbAtr, rContext->cardAtr,
02158                         currReader->cbAtr);
02159                 }
02160                 else
02161                     currReader->cbAtr = 0;
02162 
02163                 /* Card is now absent */
02164                 if (dwState & SCARD_ABSENT)
02165                 {
02166                     currReader->dwEventState |= SCARD_STATE_EMPTY;
02167                     currReader->dwEventState &= ~SCARD_STATE_PRESENT;
02168                     currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
02169                     currReader->dwEventState &= ~SCARD_STATE_IGNORE;
02170                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
02171                     currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
02172                     currReader->dwEventState &= ~SCARD_STATE_ATRMATCH;
02173                     currReader->dwEventState &= ~SCARD_STATE_MUTE;
02174                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
02175 
02176                     /* After present the rest are assumed */
02177                     if (currReader->dwCurrentState & SCARD_STATE_PRESENT)
02178                     {
02179                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02180                         dwBreakFlag = 1;
02181                     }
02182                 }
02183                 /* Card is now present */
02184                 else if (dwState & SCARD_PRESENT)
02185                 {
02186                     currReader->dwEventState |= SCARD_STATE_PRESENT;
02187                     currReader->dwEventState &= ~SCARD_STATE_EMPTY;
02188                     currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
02189                     currReader->dwEventState &= ~SCARD_STATE_IGNORE;
02190                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
02191                     currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
02192                     currReader->dwEventState &= ~SCARD_STATE_MUTE;
02193 
02194                     if (currReader->dwCurrentState & SCARD_STATE_EMPTY)
02195                     {
02196                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02197                         dwBreakFlag = 1;
02198                     }
02199 
02200                     if (dwState & SCARD_SWALLOWED)
02201                     {
02202                         currReader->dwEventState |= SCARD_STATE_MUTE;
02203                         if (!(currReader->dwCurrentState & SCARD_STATE_MUTE))
02204                         {
02205                             currReader->dwEventState |= SCARD_STATE_CHANGED;
02206                             dwBreakFlag = 1;
02207                         }
02208                     }
02209                     else
02210                     {
02211                         /* App thinks card is mute but it is not */
02212                         if (currReader->dwCurrentState & SCARD_STATE_MUTE)
02213                         {
02214                             currReader->dwEventState |= SCARD_STATE_CHANGED;
02215                             dwBreakFlag = 1;
02216                         }
02217                     }
02218                 }
02219 
02220                 /* Now figure out sharing modes */
02221                 if (rContext->readerSharing == -1)
02222                 {
02223                     currReader->dwEventState |= SCARD_STATE_EXCLUSIVE;
02224                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
02225                     if (currReader->dwCurrentState & SCARD_STATE_INUSE)
02226                     {
02227                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02228                         dwBreakFlag = 1;
02229                     }
02230                 }
02231                 else if (rContext->readerSharing >= 1)
02232                 {
02233                     /* A card must be inserted for it to be INUSE */
02234                     if (dwState & SCARD_PRESENT)
02235                     {
02236                         currReader->dwEventState |= SCARD_STATE_INUSE;
02237                         currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
02238                         if (currReader-> dwCurrentState & SCARD_STATE_EXCLUSIVE)
02239                         {
02240                             currReader->dwEventState |= SCARD_STATE_CHANGED;
02241                             dwBreakFlag = 1;
02242                         }
02243                     }
02244                 }
02245                 else if (rContext->readerSharing == 0)
02246                 {
02247                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
02248                     currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
02249 
02250                     if (currReader->dwCurrentState & SCARD_STATE_INUSE)
02251                     {
02252                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02253                         dwBreakFlag = 1;
02254                     }
02255                     else if (currReader-> dwCurrentState
02256                         & SCARD_STATE_EXCLUSIVE)
02257                     {
02258                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02259                         dwBreakFlag = 1;
02260                     }
02261                 }
02262 
02263                 if (currReader->dwCurrentState == SCARD_STATE_UNAWARE)
02264                 {
02265                     /*
02266                      * Break out of the while .. loop and return status
02267                      * once all the status's for all readers is met
02268                      */
02269                     currReader->dwEventState |= SCARD_STATE_CHANGED;
02270                     dwBreakFlag = 1;
02271                 }
02272             }   /* End of SCARD_STATE_UNKNOWN */
02273         }   /* End of SCARD_STATE_IGNORE */
02274 
02275         /* Counter and resetter */
02276         j++;
02277         if (j == cReaders)
02278         {
02279             /* go back to the first reader */
02280             j = 0;
02281 
02282             /* Declare all the break conditions */
02283 
02284             /* Break if UNAWARE is set and all readers have been checked */
02285             if (dwBreakFlag == 1)
02286                 break;
02287 
02288             if (BLOCK_STATUS_BLOCKING
02289                 != psContextMap[dwContextIndex].contextBlockStatus)
02290                 break;
02291 
02292             /* Only sleep once for each cycle of reader checks. */
02293             dwTime = WaitForPcscdEvent(hContext, dwTime);
02294 
02295             if (dwTimeout != INFINITE)
02296             {
02297                 /* If time is greater than timeout and all readers have been
02298                  * checked
02299                  */
02300                 if (dwTime <= 0)
02301                 {
02302                     rv = SCARD_E_TIMEOUT;
02303                     goto end;
02304                 }
02305             }
02306         }
02307     }
02308     while (1);
02309 
02310     if (psContextMap[dwContextIndex].contextBlockStatus != BLOCK_STATUS_BLOCKING)
02311         rv = SCARD_E_CANCELLED;
02312 
02313     psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_RESUME;
02314 
02315 end:
02316     Log1(PCSC_LOG_DEBUG, "Event Loop End");
02317 
02318     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02319 
02320     PROFILE_END(rv)
02321 
02322     return rv;
02323 }
02324 
02376 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
02377     DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
02378     LPDWORD lpBytesReturned)
02379 {
02380     LONG rv;
02381     control_struct scControlStruct;
02382     sharedSegmentMsg msgStruct;
02383     int i;
02384     DWORD dwContextIndex, dwChannelIndex;
02385 
02386     PROFILE_START
02387 
02388     /* 0 bytes received by default */
02389     if (NULL != lpBytesReturned)
02390         *lpBytesReturned = 0;
02391 
02392     rv = SCardCheckDaemonAvailability();
02393     if (rv != SCARD_S_SUCCESS)
02394         return rv;
02395 
02396     /*
02397      * Make sure this handle has been opened
02398      */
02399     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02400     if (rv == -1)
02401         return SCARD_E_INVALID_HANDLE;
02402 
02403     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02404 
02405     /* check the handle is still valid */
02406     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02407     if (rv == -1) {
02408         /* the hCard handle is now invalid
02409          * -> another thread may have called SCardReleaseContext
02410          *    so the mMutex has been unlocked (and is now invalid)
02411          * -> another thread may have called SCardDisconnect
02412          *    so the mMutex is STILL locked.
02413          *  since we don't know just unlock the mutext*/
02414         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02415         return SCARD_E_INVALID_HANDLE;
02416     }
02417 
02418     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02419     {
02420         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02421 
02422         /* by default r == NULL */
02423         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02424             break;
02425     }
02426 
02427     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02428     {
02429         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02430         return SCARD_E_READER_UNAVAILABLE;
02431     }
02432 
02433     if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
02434         || (cbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
02435     {
02436         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02437         return SCARD_E_INSUFFICIENT_BUFFER;
02438     }
02439 
02440     if ((cbSendLength > MAX_BUFFER_SIZE) || (cbRecvLength > MAX_BUFFER_SIZE))
02441     {
02442         /* extended control */
02443         unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED];
02444         control_struct_extended *scControlStructExtended = (control_struct_extended *)buffer;
02445         sharedSegmentMsg *pmsgStruct = (psharedSegmentMsg)buffer;
02446 
02447         scControlStructExtended->hCard = hCard;
02448         scControlStructExtended->dwControlCode = dwControlCode;
02449         scControlStructExtended->cbSendLength = cbSendLength;
02450         scControlStructExtended->cbRecvLength = cbRecvLength;
02451         scControlStructExtended->pdwBytesReturned = 0;
02452         scControlStructExtended->rv = SCARD_S_SUCCESS;
02453         /* The size of data to send is the size of
02454          * struct control_struct_extended WITHOUT the data[] field
02455          * plus the effective data[] size
02456          */
02457         scControlStructExtended->size = sizeof(*scControlStructExtended)
02458             - (sizeof(control_struct_extended) - offsetof(control_struct_extended, data))
02459             + cbSendLength;
02460         memcpy(scControlStructExtended->data, pbSendBuffer, cbSendLength);
02461 
02462         rv = WrapSHMWrite(SCARD_CONTROL_EXTENDED,
02463             psContextMap[dwContextIndex].dwClientID,
02464             scControlStructExtended->size,
02465             PCSCLITE_CLIENT_ATTEMPTS, buffer);
02466 
02467         if (rv == -1)
02468         {
02469             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02470             return SCARD_E_NO_SERVICE;
02471         }
02472 
02473         /*
02474          * Read a message from the server
02475          */
02476         /* read the first block */
02477         rv = SHMMessageReceive(buffer, sizeof(sharedSegmentMsg),
02478             psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
02479         if (rv == -1)
02480         {
02481             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02482             return SCARD_F_COMM_ERROR;
02483         }
02484 
02485         /* we receive a sharedSegmentMsg and not a control_struct_extended */
02486         scControlStructExtended = (control_struct_extended *)&(pmsgStruct -> data);
02487 
02488         /* a second block is present */
02489         if (scControlStructExtended->size > PCSCLITE_MAX_MESSAGE_SIZE)
02490         {
02491             rv = SHMMessageReceive(buffer + sizeof(sharedSegmentMsg),
02492                 scControlStructExtended->size-PCSCLITE_MAX_MESSAGE_SIZE,
02493                 psContextMap[dwContextIndex].dwClientID,
02494                 PCSCLITE_CLIENT_ATTEMPTS);
02495             if (rv == -1)
02496             {
02497                 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02498                 return SCARD_F_COMM_ERROR;
02499             }
02500         }
02501 
02502         if (scControlStructExtended -> rv == SCARD_S_SUCCESS)
02503         {
02504             /*
02505              * Copy and zero it so any secret information is not leaked
02506              */
02507             memcpy(pbRecvBuffer, scControlStructExtended -> data,
02508                 scControlStructExtended -> pdwBytesReturned);
02509             memset(scControlStructExtended -> data, 0x00,
02510                 scControlStructExtended -> pdwBytesReturned);
02511         }
02512 
02513         if (NULL != lpBytesReturned)
02514             *lpBytesReturned = scControlStructExtended -> pdwBytesReturned;
02515 
02516         rv = scControlStructExtended -> rv;
02517     }
02518     else
02519     {
02520         scControlStruct.hCard = hCard;
02521         scControlStruct.dwControlCode = dwControlCode;
02522         scControlStruct.cbSendLength = cbSendLength;
02523         scControlStruct.cbRecvLength = cbRecvLength;
02524         memcpy(scControlStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
02525 
02526         rv = WrapSHMWrite(SCARD_CONTROL,
02527             psContextMap[dwContextIndex].dwClientID,
02528             sizeof(scControlStruct), PCSCLITE_CLIENT_ATTEMPTS, &scControlStruct);
02529 
02530         if (rv == -1)
02531         {
02532             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02533             return SCARD_E_NO_SERVICE;
02534         }
02535 
02536         /*
02537          * Read a message from the server
02538          */
02539         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
02540             PCSCLITE_CLIENT_ATTEMPTS);
02541 
02542         if (rv == -1)
02543         {
02544             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02545             return SCARD_F_COMM_ERROR;
02546         }
02547 
02548         memcpy(&scControlStruct, &msgStruct.data, sizeof(scControlStruct));
02549 
02550         if (NULL != lpBytesReturned)
02551             *lpBytesReturned = scControlStruct.dwBytesReturned;
02552 
02553         if (scControlStruct.rv == SCARD_S_SUCCESS)
02554         {
02555             /*
02556              * Copy and zero it so any secret information is not leaked
02557              */
02558             memcpy(pbRecvBuffer, scControlStruct.pbRecvBuffer,
02559                 scControlStruct.cbRecvLength);
02560             memset(scControlStruct.pbRecvBuffer, 0x00,
02561                 sizeof(scControlStruct.pbRecvBuffer));
02562         }
02563 
02564         rv = scControlStruct.rv;
02565     }
02566 
02567     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02568 
02569     PROFILE_END(rv)
02570 
02571     return rv;
02572 }
02573 
02673 LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
02674     LPDWORD pcbAttrLen)
02675 {
02676     LONG ret;
02677     unsigned char *buf = NULL;
02678 
02679     PROFILE_START
02680 
02681     if (NULL == pcbAttrLen)
02682         return SCARD_E_INVALID_PARAMETER;
02683 
02684     if (SCARD_AUTOALLOCATE == *pcbAttrLen)
02685     {
02686         if (NULL == pbAttr)
02687             return SCARD_E_INVALID_PARAMETER;
02688 
02689         *pcbAttrLen = MAX_BUFFER_SIZE;
02690         buf = malloc(*pcbAttrLen);
02691         if (NULL == buf)
02692             return SCARD_E_NO_MEMORY;
02693 
02694         *(unsigned char **)pbAttr = buf;
02695     }
02696     else
02697     {
02698         buf = pbAttr;
02699 
02700         /* if only get the length */
02701         if (NULL == pbAttr)
02702             /* use a reasonable size */
02703             *pcbAttrLen = MAX_BUFFER_SIZE;
02704     }
02705 
02706     ret = SCardGetSetAttrib(hCard, SCARD_GET_ATTRIB, dwAttrId, buf,
02707         pcbAttrLen);
02708 
02709     PROFILE_END(ret)
02710 
02711     return ret;
02712 }
02713 
02748 LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
02749     DWORD cbAttrLen)
02750 {
02751     LONG ret;
02752 
02753     PROFILE_START
02754 
02755     if (NULL == pbAttr || 0 == cbAttrLen)
02756         return SCARD_E_INVALID_PARAMETER;
02757 
02758     ret = SCardGetSetAttrib(hCard, SCARD_SET_ATTRIB, dwAttrId, (LPBYTE)pbAttr,
02759         &cbAttrLen);
02760 
02761     PROFILE_END(ret)
02762 
02763     return ret;
02764 }
02765 
02766 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
02767     LPBYTE pbAttr, LPDWORD pcbAttrLen)
02768 {
02769     LONG rv;
02770     getset_struct scGetSetStruct;
02771     sharedSegmentMsg msgStruct;
02772     int i;
02773     DWORD dwContextIndex, dwChannelIndex;
02774 
02775     rv = SCardCheckDaemonAvailability();
02776     if (rv != SCARD_S_SUCCESS)
02777         return rv;
02778 
02779     /*
02780      * Make sure this handle has been opened
02781      */
02782     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02783     if (rv == -1)
02784         return SCARD_E_INVALID_HANDLE;
02785 
02786     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02787 
02788     /* check the handle is still valid */
02789     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02790     if (rv == -1) {
02791         /* the hCard handle is now invalid
02792          * -> another thread may have called SCardReleaseContext
02793          *    so the mMutex has been unlocked (and is now invalid)
02794          * -> another thread may have called SCardDisconnect
02795          *    so the mMutex is STILL locked.
02796          *  since we don't know just unlock the mutext*/
02797         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02798         return SCARD_E_INVALID_HANDLE;
02799     }
02800 
02801     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02802     {
02803         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02804 
02805         /* by default r == NULL */
02806         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02807             break;
02808     }
02809 
02810     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02811     {
02812         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02813         return SCARD_E_READER_UNAVAILABLE;
02814     }
02815 
02816     if (*pcbAttrLen > MAX_BUFFER_SIZE)
02817     {
02818         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02819         return SCARD_E_INSUFFICIENT_BUFFER;
02820     }
02821 
02822     scGetSetStruct.hCard = hCard;
02823     scGetSetStruct.dwAttrId = dwAttrId;
02824     scGetSetStruct.cbAttrLen = *pcbAttrLen;
02825     scGetSetStruct.rv = SCARD_E_NO_SERVICE;
02826     memset(scGetSetStruct.pbAttr, 0, sizeof(scGetSetStruct.pbAttr));
02827     if (SCARD_SET_ATTRIB == command)
02828         memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
02829 
02830     rv = WrapSHMWrite(command,
02831         psContextMap[dwContextIndex].dwClientID, sizeof(scGetSetStruct),
02832         PCSCLITE_CLIENT_ATTEMPTS, &scGetSetStruct);
02833 
02834     if (rv == -1)
02835     {
02836         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02837         return SCARD_E_NO_SERVICE;
02838     }
02839 
02840     /*
02841      * Read a message from the server
02842      */
02843     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
02844         PCSCLITE_CLIENT_ATTEMPTS);
02845 
02846     if (rv == -1)
02847     {
02848         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02849         return SCARD_F_COMM_ERROR;
02850     }
02851 
02852     memcpy(&scGetSetStruct, &msgStruct.data, sizeof(scGetSetStruct));
02853 
02854     if ((SCARD_S_SUCCESS == scGetSetStruct.rv) && (SCARD_GET_ATTRIB == command))
02855     {
02856         /*
02857          * Copy and zero it so any secret information is not leaked
02858          */
02859         if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
02860         {
02861             scGetSetStruct.cbAttrLen = *pcbAttrLen;
02862             scGetSetStruct.rv = SCARD_E_INSUFFICIENT_BUFFER;
02863         }
02864         else
02865             *pcbAttrLen = scGetSetStruct.cbAttrLen;
02866 
02867         if (pbAttr)
02868             memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
02869 
02870         memset(scGetSetStruct.pbAttr, 0x00, sizeof(scGetSetStruct.pbAttr));
02871     }
02872 
02873     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02874 
02875     return scGetSetStruct.rv;
02876 }
02877 
02936 LONG SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci,
02937     LPCBYTE pbSendBuffer, DWORD cbSendLength,
02938     LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer,
02939     LPDWORD pcbRecvLength)
02940 {
02941     LONG rv;
02942     int i;
02943     DWORD dwContextIndex, dwChannelIndex;
02944 
02945     PROFILE_START
02946 
02947     if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
02948             pcbRecvLength == NULL || pioSendPci == NULL)
02949         return SCARD_E_INVALID_PARAMETER;
02950 
02951     rv = SCardCheckDaemonAvailability();
02952     if (rv != SCARD_S_SUCCESS)
02953         return rv;
02954 
02955     /*
02956      * Make sure this handle has been opened
02957      */
02958     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02959     if (rv == -1)
02960     {
02961         *pcbRecvLength = 0;
02962         return SCARD_E_INVALID_HANDLE;
02963     }
02964 
02965     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02966 
02967     /* check the handle is still valid */
02968     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02969     if (rv == -1) {
02970         /* the hCard handle is now invalid
02971          * -> another thread may have called SCardReleaseContext
02972          *    so the mMutex has been unlocked (and is now invalid)
02973          * -> another thread may have called SCardDisconnect
02974          *    so the mMutex is STILL locked.
02975          *  since we don't know just unlock the mutext*/
02976         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02977         return SCARD_E_INVALID_HANDLE;
02978     }
02979 
02980     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02981     {
02982         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02983 
02984         /* by default r == NULL */
02985         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02986             break;
02987     }
02988 
02989     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02990     {
02991         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02992         return SCARD_E_READER_UNAVAILABLE;
02993     }
02994 
02995     if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
02996         || (*pcbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
02997     {
02998         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02999         return SCARD_E_INSUFFICIENT_BUFFER;
03000     }
03001 
03002     if ((cbSendLength > MAX_BUFFER_SIZE) || (*pcbRecvLength > MAX_BUFFER_SIZE))
03003     {
03004         /* extended APDU */
03005         unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED];
03006         transmit_struct_extended *scTransmitStructExtended = (transmit_struct_extended *)buffer;
03007         sharedSegmentMsg *pmsgStruct = (psharedSegmentMsg)buffer;
03008 
03009         scTransmitStructExtended->hCard = hCard;
03010         scTransmitStructExtended->cbSendLength = cbSendLength;
03011         scTransmitStructExtended->pcbRecvLength = *pcbRecvLength;
03012         /* The size of data to send is the size of
03013          * struct control_struct_extended WITHOUT the data[] field
03014          * plus the effective data[] size
03015          */
03016         scTransmitStructExtended->size = sizeof(*scTransmitStructExtended)
03017             - (sizeof(transmit_struct_extended) - offsetof(transmit_struct_extended, data))
03018             + cbSendLength;
03019         scTransmitStructExtended->pioSendPciProtocol = pioSendPci->dwProtocol;
03020         scTransmitStructExtended->pioSendPciLength = pioSendPci->cbPciLength;
03021         memcpy(scTransmitStructExtended->data, pbSendBuffer, cbSendLength);
03022         scTransmitStructExtended->rv = SCARD_S_SUCCESS;
03023 
03024         if (pioRecvPci)
03025         {
03026             scTransmitStructExtended->pioRecvPciProtocol = pioRecvPci->dwProtocol;
03027             scTransmitStructExtended->pioRecvPciLength = pioRecvPci->cbPciLength;
03028         }
03029         else
03030         {
03031             scTransmitStructExtended->pioRecvPciProtocol = SCARD_PROTOCOL_ANY;
03032             scTransmitStructExtended->pioRecvPciLength = sizeof(SCARD_IO_REQUEST);
03033         }
03034 
03035         rv = WrapSHMWrite(SCARD_TRANSMIT_EXTENDED,
03036             psContextMap[dwContextIndex].dwClientID,
03037             scTransmitStructExtended->size,
03038             PCSCLITE_CLIENT_ATTEMPTS, buffer);
03039 
03040         if (rv == -1)
03041         {
03042             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03043             return SCARD_E_NO_SERVICE;
03044         }
03045 
03046         /*
03047          * Read a message from the server
03048          */
03049         /* read the first block */
03050         rv = SHMMessageReceive(buffer, sizeof(sharedSegmentMsg), psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
03051         if (rv == -1)
03052         {
03053             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03054             return SCARD_F_COMM_ERROR;
03055         }
03056 
03057         /* we receive a sharedSegmentMsg and not a transmit_struct_extended */
03058         scTransmitStructExtended = (transmit_struct_extended *)&(pmsgStruct -> data);
03059 
03060         /* a second block is present */
03061         if (scTransmitStructExtended->size > PCSCLITE_MAX_MESSAGE_SIZE)
03062         {
03063             rv = SHMMessageReceive(buffer + sizeof(sharedSegmentMsg),
03064                 scTransmitStructExtended->size-PCSCLITE_MAX_MESSAGE_SIZE,
03065                 psContextMap[dwContextIndex].dwClientID,
03066                 PCSCLITE_CLIENT_ATTEMPTS);
03067             if (rv == -1)
03068             {
03069                 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03070                 return SCARD_F_COMM_ERROR;
03071             }
03072         }
03073 
03074         if (scTransmitStructExtended -> rv == SCARD_S_SUCCESS)
03075         {
03076             /*
03077              * Copy and zero it so any secret information is not leaked
03078              */
03079             memcpy(pbRecvBuffer, scTransmitStructExtended -> data,
03080                 scTransmitStructExtended -> pcbRecvLength);
03081             memset(scTransmitStructExtended -> data, 0x00,
03082                 scTransmitStructExtended -> pcbRecvLength);
03083 
03084             if (pioRecvPci)
03085             {
03086                 pioRecvPci->dwProtocol = scTransmitStructExtended->pioRecvPciProtocol;
03087                 pioRecvPci->cbPciLength = scTransmitStructExtended->pioRecvPciLength;
03088             }
03089         }
03090 
03091         *pcbRecvLength = scTransmitStructExtended -> pcbRecvLength;
03092         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03093 
03094         rv = scTransmitStructExtended -> rv;
03095     }
03096     else
03097     {
03098         /* short APDU */
03099         transmit_struct scTransmitStruct;
03100         sharedSegmentMsg msgStruct;
03101 
03102         scTransmitStruct.hCard = hCard;
03103         scTransmitStruct.cbSendLength = cbSendLength;
03104         scTransmitStruct.pcbRecvLength = *pcbRecvLength;
03105         scTransmitStruct.pioSendPciProtocol = pioSendPci->dwProtocol;
03106         scTransmitStruct.pioSendPciLength = pioSendPci->cbPciLength;
03107         memcpy(scTransmitStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
03108         memset(scTransmitStruct.pbSendBuffer+cbSendLength, 0, sizeof(scTransmitStruct.pbSendBuffer)-cbSendLength);
03109         memset(scTransmitStruct.pbRecvBuffer, 0, sizeof(scTransmitStruct.pbRecvBuffer));
03110         scTransmitStruct.rv = SCARD_S_SUCCESS;
03111 
03112         if (pioRecvPci)
03113         {
03114             scTransmitStruct.pioRecvPciProtocol = pioRecvPci->dwProtocol;
03115             scTransmitStruct.pioRecvPciLength = pioRecvPci->cbPciLength;
03116         }
03117         else
03118         {
03119             scTransmitStruct.pioRecvPciProtocol = SCARD_PROTOCOL_ANY;
03120             scTransmitStruct.pioRecvPciLength = sizeof(SCARD_IO_REQUEST);
03121         }
03122 
03123         rv = WrapSHMWrite(SCARD_TRANSMIT,
03124             psContextMap[dwContextIndex].dwClientID, sizeof(scTransmitStruct),
03125             PCSCLITE_CLIENT_ATTEMPTS, (void *) &scTransmitStruct);
03126 
03127         if (rv == -1)
03128         {
03129             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03130             return SCARD_E_NO_SERVICE;
03131         }
03132 
03133         /*
03134          * Read a message from the server
03135          */
03136         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
03137             PCSCLITE_CLIENT_ATTEMPTS);
03138 
03139         memcpy(&scTransmitStruct, &msgStruct.data, sizeof(scTransmitStruct));
03140 
03141         if (rv == -1)
03142         {
03143             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03144             return SCARD_F_COMM_ERROR;
03145         }
03146 
03147         /*
03148          * Zero it and free it so any secret information cannot be leaked
03149          */
03150         memset(scTransmitStruct.pbSendBuffer, 0x00, cbSendLength);
03151 
03152         if (scTransmitStruct.rv == SCARD_S_SUCCESS)
03153         {
03154             /*
03155              * Copy and zero it so any secret information is not leaked
03156              */
03157             memcpy(pbRecvBuffer, scTransmitStruct.pbRecvBuffer,
03158                 scTransmitStruct.pcbRecvLength);
03159             memset(scTransmitStruct.pbRecvBuffer, 0x00,
03160                 scTransmitStruct.pcbRecvLength);
03161 
03162             if (pioRecvPci)
03163             {
03164                 pioRecvPci->dwProtocol = scTransmitStruct.pioRecvPciProtocol;
03165                 pioRecvPci->cbPciLength = scTransmitStruct.pioRecvPciLength;
03166             }
03167         }
03168 
03169         *pcbRecvLength = scTransmitStruct.pcbRecvLength;
03170         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03171 
03172         rv = scTransmitStruct.rv;
03173     }
03174 
03175     PROFILE_END(rv)
03176 
03177     return rv;
03178 }
03179 
03228 LONG SCardListReaders(SCARDCONTEXT hContext, /*@unused@*/ LPCSTR mszGroups,
03229     LPSTR mszReaders, LPDWORD pcchReaders)
03230 {
03231     DWORD dwReadersLen;
03232     int i;
03233     LONG dwContextIndex;
03234     LONG rv = SCARD_S_SUCCESS;
03235     char *buf = NULL;
03236 
03237     (void)mszGroups;
03238     PROFILE_START
03239 
03240     /*
03241      * Check for NULL parameters
03242      */
03243     if (pcchReaders == NULL)
03244         return SCARD_E_INVALID_PARAMETER;
03245 
03246     rv = SCardCheckDaemonAvailability();
03247     if (rv != SCARD_S_SUCCESS)
03248         return rv;
03249 
03250     /*
03251      * Make sure this context has been opened
03252      */
03253     dwContextIndex = SCardGetContextIndice(hContext);
03254     if (dwContextIndex == -1)
03255         return SCARD_E_INVALID_HANDLE;
03256 
03257     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
03258 
03259     /* check the context is still opened */
03260     dwContextIndex = SCardGetContextIndice(hContext);
03261     if (dwContextIndex == -1)
03262         /* the context is now invalid
03263          * -> another thread may have called SCardReleaseContext
03264          * -> so the mMutex has been unlocked */
03265         return SCARD_E_INVALID_HANDLE;
03266 
03267     dwReadersLen = 0;
03268     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
03269         if ((readerStates[i])->readerID != 0)
03270             dwReadersLen += strlen((readerStates[i])->readerName) + 1;
03271 
03272     /* for the last NULL byte */
03273     dwReadersLen += 1;
03274 
03275     if (1 == dwReadersLen)
03276     {
03277         rv = SCARD_E_NO_READERS_AVAILABLE;
03278         goto end;
03279     }
03280 
03281     if (SCARD_AUTOALLOCATE == *pcchReaders)
03282     {
03283         buf = malloc(dwReadersLen);
03284         if (NULL == buf)
03285         {
03286             rv = SCARD_E_NO_MEMORY;
03287             goto end;
03288         }
03289         if (NULL == mszReaders)
03290         {
03291             rv = SCARD_E_INVALID_PARAMETER;
03292             goto end;
03293         }
03294         *(char **)mszReaders = buf;
03295     }
03296     else
03297     {
03298         buf = mszReaders;
03299 
03300         /* not enough place to store the reader names */
03301         if ((NULL != mszReaders) && (*pcchReaders < dwReadersLen))
03302         {
03303             rv = SCARD_E_INSUFFICIENT_BUFFER;
03304             goto end;
03305         }
03306     }
03307 
03308     if (mszReaders == NULL) /* text array not allocated */
03309         goto end;
03310 
03311     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
03312     {
03313         if ((readerStates[i])->readerID != 0)
03314         {
03315             /*
03316              * Build the multi-string
03317              */
03318             strcpy(buf, (readerStates[i])->readerName);
03319             buf += strlen((readerStates[i])->readerName)+1;
03320         }
03321     }
03322     *buf = '\0';    /* Add the last null */
03323 
03324 end:
03325     /* set the reader names length */
03326     *pcchReaders = dwReadersLen;
03327 
03328     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03329 
03330     PROFILE_END(rv)
03331 
03332     return rv;
03333 }
03334 
03347 LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
03348 {
03349     LONG rv = SCARD_S_SUCCESS;
03350     LONG dwContextIndex;
03351 
03352     PROFILE_START
03353 
03354     rv = SCardCheckDaemonAvailability();
03355     if (rv != SCARD_S_SUCCESS)
03356         return rv;
03357 
03358     /*
03359      * Make sure this context has been opened
03360      */
03361     dwContextIndex = SCardGetContextIndice(hContext);
03362     if (dwContextIndex == -1)
03363         return SCARD_E_INVALID_HANDLE;
03364 
03365     free((void *)pvMem);
03366 
03367     PROFILE_END(rv)
03368 
03369     return rv;
03370 }
03371 
03421 LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups,
03422     LPDWORD pcchGroups)
03423 {
03424     LONG rv = SCARD_S_SUCCESS;
03425     LONG dwContextIndex;
03426     char *buf = NULL;
03427 
03428     PROFILE_START
03429 
03430     /* Multi-string with two trailing \0 */
03431     const char ReaderGroup[] = "SCard$DefaultReaders\0";
03432     const int dwGroups = sizeof(ReaderGroup);
03433 
03434     rv = SCardCheckDaemonAvailability();
03435     if (rv != SCARD_S_SUCCESS)
03436         return rv;
03437 
03438     /*
03439      * Make sure this context has been opened
03440      */
03441     dwContextIndex = SCardGetContextIndice(hContext);
03442     if (dwContextIndex == -1)
03443         return SCARD_E_INVALID_HANDLE;
03444 
03445     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
03446 
03447     /* check the context is still opened */
03448     dwContextIndex = SCardGetContextIndice(hContext);
03449     if (dwContextIndex == -1)
03450         /* the context is now invalid
03451          * -> another thread may have called SCardReleaseContext
03452          * -> so the mMutex has been unlocked */
03453         return SCARD_E_INVALID_HANDLE;
03454 
03455     if (SCARD_AUTOALLOCATE == *pcchGroups)
03456     {
03457         buf = malloc(dwGroups);
03458         if (NULL == buf)
03459         {
03460             rv = SCARD_E_NO_MEMORY;
03461             goto end;
03462         }
03463         if (NULL == mszGroups)
03464         {
03465             rv = SCARD_E_INVALID_PARAMETER;
03466             goto end;
03467         }
03468         *(char **)mszGroups = buf;
03469     }
03470     else
03471     {
03472         buf = mszGroups;
03473 
03474         if ((NULL != mszGroups) && (*pcchGroups < dwGroups))
03475         {
03476             rv = SCARD_E_INSUFFICIENT_BUFFER;
03477             goto end;
03478         }
03479     }
03480 
03481     if (buf)
03482         memcpy(buf, ReaderGroup, dwGroups);
03483 
03484 end:
03485     *pcchGroups = dwGroups;
03486 
03487     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03488 
03489     PROFILE_END(rv)
03490 
03491     return rv;
03492 }
03493 
03521 LONG SCardCancel(SCARDCONTEXT hContext)
03522 {
03523     LONG dwContextIndex;
03524     LONG rv = SCARD_S_SUCCESS;
03525 
03526     PROFILE_START
03527 
03528     dwContextIndex = SCardGetContextIndice(hContext);
03529     if (dwContextIndex == -1)
03530         return SCARD_E_INVALID_HANDLE;
03531 
03532     /*
03533      * Set the block status for this Context so blocking calls will
03534      * complete
03535      */
03536     psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_CANCEL;
03537 
03538     if (StatSynchronizeContext(hContext))
03539         rv = SCARD_F_INTERNAL_ERROR;
03540 
03541     PROFILE_END(rv)
03542 
03543     return rv;
03544 }
03545 
03569 LONG SCardIsValidContext(SCARDCONTEXT hContext)
03570 {
03571     LONG rv;
03572     LONG dwContextIndex;
03573 
03574     PROFILE_START
03575 
03576     rv = SCARD_S_SUCCESS;
03577 
03578     /* Check if the _same_ server is running */
03579     rv = SCardCheckDaemonAvailability();
03580     if (rv != SCARD_S_SUCCESS)
03581         return rv;
03582 
03583     /*
03584      * Make sure this context has been opened
03585      */
03586     dwContextIndex = SCardGetContextIndice(hContext);
03587     if (dwContextIndex == -1)
03588         rv = SCARD_E_INVALID_HANDLE;
03589 
03590     PROFILE_END(rv)
03591 
03592     return rv;
03593 }
03594 
03611 static LONG SCardAddContext(SCARDCONTEXT hContext, DWORD dwClientID)
03612 {
03613     int i;
03614 
03615     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03616     {
03617         if (psContextMap[i].hContext == 0)
03618         {
03619             psContextMap[i].hContext = hContext;
03620             psContextMap[i].dwClientID = dwClientID;
03621             psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;
03622             psContextMap[i].mMutex = malloc(sizeof(PCSCLITE_MUTEX));
03623             (void)SYS_MutexInit(psContextMap[i].mMutex);
03624             return SCARD_S_SUCCESS;
03625         }
03626     }
03627 
03628     return SCARD_E_NO_MEMORY;
03629 }
03630 
03643 static LONG SCardGetContextIndice(SCARDCONTEXT hContext)
03644 {
03645     LONG rv;
03646 
03647     (void)SCardLockThread();
03648     rv = SCardGetContextIndiceTH(hContext);
03649     (void)SCardUnlockThread();
03650 
03651     return rv;
03652 }
03653 
03666 static LONG SCardGetContextIndiceTH(SCARDCONTEXT hContext)
03667 {
03668     int i;
03669 
03670     /*
03671      * Find this context and return its spot in the array
03672      */
03673     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03674     {
03675         if ((hContext == psContextMap[i].hContext) && (hContext != 0))
03676             return i;
03677     }
03678 
03679     return -1;
03680 }
03681 
03691 static LONG SCardRemoveContext(SCARDCONTEXT hContext)
03692 {
03693     LONG  retIndice;
03694 
03695     retIndice = SCardGetContextIndiceTH(hContext);
03696 
03697     if (retIndice == -1)
03698         return SCARD_E_INVALID_HANDLE;
03699     else
03700         return SCardCleanContext(retIndice);
03701 }
03702 
03703 static LONG SCardCleanContext(LONG indice)
03704 {
03705     int i;
03706 
03707     psContextMap[indice].hContext = 0;
03708     (void)SHMClientCloseSession(psContextMap[indice].dwClientID);
03709     psContextMap[indice].dwClientID = 0;
03710     free(psContextMap[indice].mMutex);
03711     psContextMap[indice].mMutex = NULL;
03712     psContextMap[indice].contextBlockStatus = BLOCK_STATUS_RESUME;
03713 
03714     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03715     {
03716         /*
03717          * Reset the \c hCard structs to zero
03718          */
03719         psContextMap[indice].psChannelMap[i].hCard = 0;
03720         free(psContextMap[indice].psChannelMap[i].readerName);
03721         psContextMap[indice].psChannelMap[i].readerName = NULL;
03722     }
03723 
03724     return SCARD_S_SUCCESS;
03725 }
03726 
03727 /*
03728  * Functions for managing hCard values returned from SCardConnect.
03729  */
03730 
03731 static LONG SCardAddHandle(SCARDHANDLE hCard, DWORD dwContextIndex,
03732     LPCSTR readerName)
03733 {
03734     int i;
03735 
03736     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03737     {
03738         if (psContextMap[dwContextIndex].psChannelMap[i].hCard == 0)
03739         {
03740             psContextMap[dwContextIndex].psChannelMap[i].hCard = hCard;
03741             psContextMap[dwContextIndex].psChannelMap[i].readerName = strdup(readerName);
03742             return SCARD_S_SUCCESS;
03743         }
03744     }
03745 
03746     return SCARD_E_NO_MEMORY;
03747 }
03748 
03749 static LONG SCardRemoveHandle(SCARDHANDLE hCard)
03750 {
03751     DWORD dwContextIndice, dwChannelIndice;
03752     LONG rv;
03753 
03754     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndice, &dwChannelIndice);
03755     if (rv == -1)
03756         return SCARD_E_INVALID_HANDLE;
03757     else
03758     {
03759         psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].hCard = 0;
03760         free(psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName);
03761         psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName = NULL;
03762         return SCARD_S_SUCCESS;
03763     }
03764 }
03765 
03766 static LONG SCardGetIndicesFromHandle(SCARDHANDLE hCard,
03767     PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
03768 {
03769     LONG rv;
03770 
03771     if (0 == hCard)
03772         return -1;
03773 
03774     (void)SCardLockThread();
03775     rv = SCardGetIndicesFromHandleTH(hCard, pdwContextIndice, pdwChannelIndice);
03776     (void)SCardUnlockThread();
03777 
03778     return rv;
03779 }
03780 
03781 static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE hCard,
03782     PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
03783 {
03784     int i;
03785 
03786     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03787     {
03788         if (psContextMap[i].hContext != 0)
03789         {
03790             int j;
03791 
03792             for (j = 0; j < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; j++)
03793             {
03794                 if (psContextMap[i].psChannelMap[j].hCard == hCard)
03795                 {
03796                     *pdwContextIndice = i;
03797                     *pdwChannelIndice = j;
03798                     return SCARD_S_SUCCESS;
03799                 }
03800             }
03801 
03802         }
03803     }
03804 
03805     return -1;
03806 }
03807 
03816 LONG SCardCheckDaemonAvailability(void)
03817 {
03818     LONG rv;
03819     struct stat statBuffer;
03820     int need_restart = 0;
03821 
03822     rv = SYS_Stat(PCSCLITE_PUBSHM_FILE, &statBuffer);
03823 
03824     if (rv != 0)
03825     {
03826         Log2(PCSC_LOG_INFO, "PCSC Not Running: " PCSCLITE_PUBSHM_FILE ": %s",
03827             strerror(errno));
03828         return SCARD_E_NO_SERVICE;
03829     }
03830 
03831     /* when the _first_ reader is connected the ctime changes
03832      * I don't know why yet */
03833     if (daemon_ctime && statBuffer.st_ctime > daemon_ctime)
03834     {
03835         /* so we also check the daemon pid to be sure it is a new pcscd */
03836         if (GetDaemonPid() != daemon_pid)
03837         {
03838             Log1(PCSC_LOG_INFO, "PCSC restarted");
03839             need_restart = 1;
03840         }
03841     }
03842 
03843     /* after fork() need to restart */
03844     if (client_pid && client_pid != getpid())
03845     {
03846         Log1(PCSC_LOG_INFO, "Client forked");
03847         need_restart = 1;
03848     }
03849 
03850     if (need_restart)
03851     {
03852         int i;
03853 
03854         /* invalid all handles */
03855         (void)SCardLockThread();
03856 
03857         for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03858             if (psContextMap[i].hContext)
03859                 (void)SCardCleanContext(i);
03860 
03861         (void)SCardUnlockThread();
03862 
03863         /* reset pcscd status */
03864         daemon_ctime = 0;
03865         client_pid = 0;
03866 
03867         /* reset the lib */
03868         SCardUnload();
03869 
03870         return SCARD_E_INVALID_HANDLE;
03871     }
03872 
03873     daemon_ctime = statBuffer.st_ctime;
03874     daemon_pid = GetDaemonPid();
03875     client_pid = getpid();
03876 
03877     return SCARD_S_SUCCESS;
03878 }
03879 
03886 #ifdef __SUNPRO_C
03887 #pragma fini (SCardUnload)
03888 #endif
03889 
03890 void DESTRUCTOR SCardUnload(void)
03891 {
03892     int i;
03893 
03894     if (!isExecuted)
03895         return;
03896 
03897     /* unmap public shared file from memory */
03898     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03899     {
03900         if (readerStates[i] != NULL)
03901         {
03902             SYS_PublicMemoryUnmap(readerStates[i], sizeof(READER_STATE));
03903             readerStates[i] = NULL;
03904         }
03905     }
03906 
03907     (void)SYS_CloseFile(mapAddr);
03908     isExecuted = 0;
03909 }
03910 

Generated on 21 Mar 2017 for pcsc-lite by  doxygen 1.6.1