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

Generated on Mon Aug 17 01:00:12 2009 for pcsc-lite by  doxygen 1.5.9